转载韦工的处理办法

今天跟同事看一个TP驱动,上电后日志都正常,但是触摸没反应,然后开始排查。

上电后可以正常读到芯片的chip ID,那说明I2C是通讯正常的,也可以说明触摸芯片的供电也是正常的。

基于这个,我搬来示波器,测量中断引脚的信号,发现两个现象

 

1、从休眠到唤醒状态后,中断脚有波形,而且波形上看不出异常。

2、中断处理函数没有跑进去

 

—— 触摸屏的dts文件编写如下

 文件:arch/arm/boot/dts/inxxx.dts
 cap_touch@14 {
  compatible = "mediatek,cap_touch";
  reg = <0x14>;
  interrupt-parent = <&pio>;
  interrupts = <100 IRQ_TYPE_EDGE_FALLING>;
  int-gpio = <&pio 100 0>;
  rst-gpio = <&pio 101 0>;
 };

compatible 是和驱动里面的name 匹配上的。

reg 是I2C芯片的 地址。

interrupt-parent 对应的是平台的中断控制器,里面应用的 pio对应的是mt8167.dtsi文件里面的中断控制器dts描述

interrupts 的第一个参数对应的是中断号,第二个参数对应的是中断的触发方式。

int-gpio 里面引用的 pio 也是用到了 pio里面的gpio口控制器,第二个参数对应的是gpio 编号,第三个对应的是gpio口的电平。

rst-gpio 和上面同理。

看内核文档对gpiodts的描述

 文件:Documentation/devicetree/binding/pinctrl/pinctrl-mt65xx.txt
 Eg: <&pio 6 0>
 <[phandle of the gpio controller node]
 [line number within the gpio controller]
 [flags]>
 Values for gpio specifier:
 - Line number: is a value between 0 to 202.
 - Flags:  bit field of flags, as defined in <dt-bindings/gpio/gpio.h>. Only the following flags are supported: 0 - GPIO_ACTIVE_HIGH 1 - GPIO_ACTIVE_LOW

看看&pio这个里面都是一些什么东西

pio: pinctrl@10005000 {
   compatible = "mediatek,mt8167-pinctrl";
   reg = <0 0x1000b000 0 0x1000>;
   mediatek,pctl-regmap = <&syscfg_pctl_a>;
   pins-are-numbered;
   gpio-controller;
   #gpio-cells = <2>;
   interrupt-controller;
   #interrupt-cells = <2>;
   interrupts = <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>;
};

—— 看看注册上的中断的编号

xxxx:/ # cat proc/interrupts
           CPU0
 18:      19578       GIC  27 Edge      arch_timer
 20:          0  MT_SYSIRQ 132 Level     mtk_timer
 21:         12  MT_SYSIRQ  84 Level     mtk-uart
 30:          0  MT_SYSIRQ 128 Level     SPM
 31:          0  MT_SYSIRQ 129 Level     SPM
 32:          0  MT_SYSIRQ 130 Level     SPM
 33:          0  MT_SYSIRQ 131 Level     SPM
 34:          0  MT_SYSIRQ 221 Edge      ATF_irq
 39:          0  MT_SYSIRQ 194 Level     BTCVSD_ISR_Handle
 40:          0  MT_SYSIRQ 198 Edge      mtk-wdt
 42:          0  MT_SYSIRQ 204 Level     mt-pmic-pwrap
 43:          0  MT_SYSIRQ 149 Edge      mtk-kpd
 45:          0  MT_SYSIRQ 121 Level     10203000.m4u
 46:          0  MT_SYSIRQ 218 Level     CIRQ
 47:          0  MT_SYSIRQ 114 Level     TEE IRQ
 49:       2942  MT_SYSIRQ 125 Level     mtk_cmdq
 50:          0  MT_SYSIRQ 126 Level     TEE IRQ
 53:          0  MT_SYSIRQ  76 Level     mt-pwm
 54:         30  MT_SYSIRQ  80 Level     i2c-mt65xx
 55:         16  MT_SYSIRQ  81 Level     i2c-mt65xx
 56:         64  MT_SYSIRQ  82 Level     i2c-mt65xx
 57:          0  MT_SYSIRQ  77 Level     mt8167-thermal
 58:         16  MT_SYSIRQ  83 Level     ptp
 62:      20967  MT_SYSIRQ  72 Level     musb-hdrc
 63:          0  MT_SYSIRQ 120 Level     Afe_ISR_Handle
 64:       2950  MT_SYSIRQ 185 Level     pvrsrvkm
 65:     113181  MT_SYSIRQ  78 Level     11120000.mmc
 67:          0  MT_SYSIRQ 210 Level     musbfsh-hdrc.0
 74:        347  MT_SYSIRQ 160 Level     DISPSYS
 75:      12980  MT_SYSIRQ 162 Level     DISPSYS
 76:          0  MT_SYSIRQ 163 Level     DISPSYS
 80:          0  MT_SYSIRQ 167 Level     DISPSYS
 83:          0  MT_SYSIRQ 171 Level     DISPSYS
 85:       1466  MT_SYSIRQ 153 Level     DISPSYS
 88:          0  MT_SYSIRQ 180 Level     ISP
123:          0  mtk-eint  28 Level     mt6397-pmic
136:          0  mtk-eint  41 Level     USB_IDDIG
195:          6  mtk-eint 100 Edge      mtk-tpd
264:          0  mt6397-irq   6 Edge      mt6397-thr_l
265:          0  mt6397-irq   7 Edge      mt6397-thr_h
266:          0  mt6397-irq   5 Edge      mtk-pmic-keys
267:          0  mt6397-irq  17 Edge      mtk-pmic-keys
268:          0  mt6397-irq  18 Edge      mtk-pmic-keys
269:          0  mt6397-irq  19 Edge      mtk-pmic-keys
270:          0  mt6397-irq  20 Edge      mt6397-rtc
IPI0:          0  CPU wakeup interrupts
IPI1:          0  Timer broadcast interrupts
IPI2:      31856  Rescheduling interrupts
IPI3:         35  Function call interrupts
IPI4:        121  Single function call interrupts
IPI5:          0  CPU stop interrupts
IPI6:          0  IRQ work interrupts
IPI7:          0  completion interrupts
Err:          0

#看看驱动文件如何驾驭这些dts配置

先使用函数获取dts里面的内容

  tpd_rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpio", 0);
  tpd_int_gpio = of_get_named_gpio(dev->of_node, "int-gpio", 0);

然后就是申请

static int gtp_get_gpio_res(void)
{
#if defined(CONFIG_OF) && !defined(CONFIG_GTP_USE_PINCTRL)
 int ret;
 /* configure the gpio pins */
 ret = gpio_request_one(tpd_rst_gpio, GPIOF_OUT_INIT_LOW,
     "touchp_reset");
 if (ret < 0) {
  GTP_ERROR("Unable to request gpio reset_pin\n");
  return -1;
 }
 ret = gpio_request_one(tpd_int_gpio, GPIOF_IN,
     "tpd_int");
 if (ret < 0) {
  GTP_ERROR("Unable to request gpio int_pin\n");
  gpio_free(tpd_rst_gpio);
  return -1;
 }
#endif
 return 0;
}

然后去看中断注册函数的时候,会有点奇怪

static int tpd_irq_registration(void)
{
 struct device_node *node = NULL;
 unsigned long irqf_val = 0;
 int ret = 0;

// node = of_find_compatible_node(NULL, NULL, "mediatek,cap_touch");//0704
 node = of_find_matching_node(NULL, touch_of_match);

 if (node) {
//  touch_irq = gpio_to_irq(tpd_int_gpio);
  touch_irq = irq_of_parse_and_map(node, 0);
  GTP_ERROR("###### touch_irq = %d\n",(int)touch_irq);
  irqf_val = !int_type ? IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
   
  irq_enabled = true; //
  ret = request_irq(touch_irq, (irq_handler_t) tpd_interrupt_handler,
    irqf_val, TPD_DEVICE, NULL); //jason test here
  GTP_ERROR("###### ret = %d\n",(int)ret);
  if (ret < 0)
   GTP_ERROR("tpd request_irq IRQ LINE NOT AVAILABLE!.");
}

// touch_irq = gpio_to_irq(tpd_int_gpio); 这行代码被注释掉了,也就是不用 gpio_to_irq来使用中断了。

目前的驱动使用了 irq_of_parse_and_map 函数来解析dts内容给驱动使用。

使用 irq_of_parse_and_map 的原因还是为了让驱动工程师少干活,dts 已经把中断的信息给描述清楚了,包括上面说的 interrupts 和 interrupt-parent 属性,这个函数会解析这两个属性,并实现对应的映射关系。

—— 看看内核代码对这个函数的解释

/**
 * irq_of_parse_and_map - Parse and map an interrupt into linux virq space
 * @dev: Device node of the device whose interrupt is to be mapped
 * @index: Index of the interrupt to map
 *
 * This function is a wrapper that chains of_irq_parse_one() and
 * irq_create_of_mapping() to make things easier to callers
 */
unsigned int irq_of_parse_and_map(struct device_node *dev, int index)
{
 struct of_phandle_args oirq;

 if (of_irq_parse_one(dev, index, &oirq))
  return 0;

 return irq_create_of_mapping(&oirq);
}
EXPORT_SYMBOL_GPL(irq_of_parse_and_map);

上面的英文的意思是,这个函数是解析并映射中断到 linux virq 空间,dev对应的就是device指针,index 就是需要映射的中断的索引。

该函数是 of_irq_parse_one() 和 irq_create_of_mapping() 的封装,封装的作用是为了码农写代码更容易一些。

我们再看看

touch_irq = irq_of_parse_and_map(node, 0);

后边的这个 0表示的是偏移索引,如果我们在dts里面这样写的话,就可以使用索引来选择我们的配置

interrupts = <0 0 4>, <0 1 4>;

我们在 proc/interrupts下看到的编号「195」就是这里出来的

195:         69          0          0          0  mtk-eint 100 Edge      mtk-tpd

#所以为什么中断函数没有进去?

检查了一轮发现是因为dts描述里面的 interrupts 属性没有写对,interrupts 的第一个参数需要和gpio口编号对应起来,但是我们沿用上个项目的代码,应该修改了这个gpio口,我们软件没有及时修改过来。

 

当然了,知道问题后就很快解决了。

 

触摸后可以看到触摸屏可以正常报点是一件非常开心的事情。

 

#驱动获取dts中断的方式

这部分韦东山老师总结的非常好的,我建议大家看看这篇文章

 

在Linux驱动中获取dts描述的中断


 

针对不同的设备,获取的方式不同,比较常见的是在dts里面把中断描述成一个gpio口,然后在驱动中先获取gpio口,然后再转换成中断。

 

#总结

这部分属于炒旧饭,触摸屏驱动是比较常见的外设,调试的难度也不是很大,正常的调试顺序是

 

— 先搞定供电
— 再搞定I2C、I2C一般需要上拉,还有I2C的速率,I2C的电平。

— 再看看地址,我们Linux 里面一般是 7bit 地址,需要注意,地址也会跟硬件设计相关。

— 上面都正常了,就可以去排查中断的问题了,有的GPIO可能默认没有中断,也需要软件配置。

— 然后就观察软件是否能进入中断处理函数,有的驱动是支持轮询的,但是代码位置都差不多。

 

这样都正常后就可以开机测试触摸是否正常了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值