使用TP的IRQ脚做手势唤醒。双击屏幕后,从log看cpu已经被唤醒了,但很快又睡下去,通过log分析,发现没有进入中断处理函数。这里使用的电平中断。以前已分析过电平/边沿唤醒cpu流程https://blog.youkuaiyun.com/mike8825/article/details/98473014,打印发现handle_level_irq只跑了一遍,第二次的handle_level_irq没有过来导致无法进入中断函数。一开始怀疑是低电平的持续时间不够,导致没有第二次中断过来。修改TP的固件,让TP的IRQ拉低到500ms,也是一样的情况,也用示波器确认信号确实拉低了500ms。跟cpu厂商那边沟通,说该cpu支持边沿唤醒,也支持电平唤醒,建议用边沿唤醒测试。修过代码后,边沿唤醒的确有效,但电平唤醒为什么不会进入中断。fae加了一些打印信息,也发现什么异常。
查看cpu手册,gpio支持dbc和level模式,再看下gpio代码,只有dbc模式才会设置电平模式,所以设置电平中断没有成功,导致还是边沿的电平触发方式,所以中断只会过来一次,第二次中断没有过来,导致没有进入中断模式,也就是平台代码的BUG。
static int sprd_gpio_plus_irq_set_type(struct irq_data *data,unsigned int flow_type)
{
case IRQ_TYPE_LEVEL_LOW:
mode = sprd_gpio_plus_read(chip, channel, REG_INT_CRL,
BIT_INT_MODE, INT_MODE_WIDTH);
dbnc = sprd_gpio_plus_read(chip, channel, REG_INT_CRL,
BIT_DBC_CYCLE, DBC_CYCLE_WIDTH);
if ((mode == GPIO_INT_DBC_MODE) && (dbnc == 0)) {
sprd_gpio_plus_write(chip, channel, REG_INT_CRL,
BIT_INT_MODE, INT_MODE_WIDTH, GPIO_INT_LEVEL_MODE);
}
sprd_gpio_plus_write(chip, channel, REG_INT_CRL,
BIT_INT_LEVEL, 1, 0);
irq_set_handler_locked(data, handle_level_irq);
break;
}