修改kernel-3.18\drivers\misc\mediatek\mach\mt6797\amt6797_evb_m\dct\dct\codegen.dws目录下的DWS文件,在对应的I2C_CHANNEL上添加GOODIX的设备,并设定I2C的地址,如下代码段1中所示:
代码段1
kernel-3.18\drivers\misc\mediatek\mach\mt6797\amt6797_evb_m\dct\dct\codegen.dws
0x5D
该DWS文件,在内核编译后会在\out\arch\arm64\boot\dts目录下生一个cust.dtsi文件,在该文件中会出现刚在DWS文件中添加的设备,此文件对应的设备下仅包含有设备的: compatible, reg, status等信息,而GPIO、IRQ、PINCTRL等信息都不在该cust.dtsi文件中,如下代码段2中所示。
代码段2
\out\arch\arm64\boot\dts
&i2c4 {
#address-cells = <1>;
#size-cells = <0>;
clock-frequency = <400000>;
mediatek,use-open-drain;
cap_touch@5d {
compatible = "mediatek,cap_touch";
reg = <0x5d>;
status = "okay";
};
fts_touch@70 {
compatible = "mediatek,fts_touch";
reg = <0x70>;
status = "okay";
};
};
这里的“compatible”就是用于与驱动中的MODULE_INIT相匹配的ID,两者一致了驱动的probe函数才能正常运行起来。比如这个例子中的“cap_touch”,驱动中设置相应的compatible也为“cap_touch”即可保证probe函数能起来。
Linux内核在启动的过程中会加载设备树文件,并最终生成相应的i2c_client对象,设备树中的相关资源信息都会被内核保存到“i2c_client->dev.of_node”中,驱动中使用该“of_node”通过of_get_named_gpio等方法即可获取到dts中的信息。比如下面的代码段3,我们在驱动中调用of_get_named_gpio(node,"goodix,reset-gpio", 0),该方法即可为我们返回DTS中与"goodix,reset-gpio"相对应的信息,非常简便。
我们刚才也说过了i2c_client->dev.of_node中的信息是内核从DTS中抽取并存放到该对象中的,内核中不止一个i2c_client,DTS中也不止一个设备的信息,内核是怎样将它们进行对应的呢?在DTS中,每个设备都会有一个设备名,在该设备下我们可以设置compatible, addr以及GPIO、IRQ等资源,内核最终在生成i2c_client时会将这些资源存放在of_node中。但MTK有些特殊,它将设备的compatible, addr设备和GPIO、IRQ等资源的设置分散在了不同的文件中。因此,如代码段3中所示,开头的“&touch”,代表的就是对设备名为“touch”的设备的资源信息补充。
在目前MTK开发板的内核中,对于设备“cap_touch”仅仅只设置了其compatible, addr,而且还是从DWS中生成过来的,其它的,GPIO、IRQ等资源都没有声明,而是将这些资源全都放了在kernel-3.18/arch/arm64/boot/dts/amt6797_evb_m.dts文件中的设备名为“touch”的设备下。那么肯定的,驱动是无法从i2c_client->dev.of_node获取资源信息的,因为我们在DTS中根本就没有为“cap_touch”声明任何资源。
那在驱动中如何去获取资源信息呢?在MTK平台上,使用
of_node = of_find_node_by_name(NULL,"goodix,touch");
将of_node指向了设备“touch”,有了of_node,后面即可一样地通过of_get_named_gpio等函数去获取资源了。
这是MTK平台比较坑的几点:
1、 从DWS去生成设备,而不是直接在DTS中修改/添加设备;
2、 设备树中设备compatible,addr的声明与GPIO、IRQ等资源的声明分散在不同的文件中;
3、 MTK平台上的驱动中对of_node进行了重新的定位,将其将向了”touch”设备;
其实完全可以将MTK平台做的与高通平台一样的,不修改DWS,而是直接去修改DTC,并且将设备相关的信息放在一起而不要再分散开来,最后,不要在驱动中去修改of_node的指向,而是将对应设备的资源信息都放在对应的设备下。
设备的GPIO、IRQ、PINCTRL等信息是写在以下文件中:
kernel-3.18/arch/arm64/boot/dts/amt6797_evb_m.dts
具体代码如下所示:
代码段3
kernel-3.18/arch/arm64/boot/dts/amt6797_evb_m.dts
&touch {
tpd-resolution = <1080 1920>;
use-tpd-button = <1>;
tpd-key-num = <3>;
tpd-key-local= <139 172 158 0>;
tpd-key-dim-local = <90 883 100 40 230 883 100 40 370 883100 40 0 0 0 0>;
tpd-max-touch-num = <5>;
tpd-filter-enable = <1>;
tpd-filter-pixel-density = <192>;
tpd-filter-custom-prameters = <0 0 0 0 0 0 0 0 0 0 00>;
tpd-filter-custom-speed = <0 0 0>;
pinctrl-names = "default","state_eint_as_int", "state_eint_output0", "state_eint_output1",
"state_rst_output0","state_rst_output1";
pinctrl-0 = <&ctp_pins_default>;
pinctrl-1 = <&ctp_pins_eint_as_int>;
pinctrl-2 = <&ctp_pins_eint_output0>;
pinctrl-3 = <&ctp_pins_eint_output1>;
pinctrl-4 = <&ctp_pins_rst_output0>;
pinctrl-5 = <&ctp_pins_rst_output1>;
status = "okay";
goodix,touch {
goodix,reset-gpio = <&pio 256 0>;
goodix,irq-gpio = <&pio 86 0>;
goodix,irq-flags = <2>; /* 1:trigger rising,2:trigger falling;*/
goodix,power-on-delay-us = <10000>; /* 10ms*/
goodix,power-off-delay-us = <10000>; /* 10ms*/
goodix,panel-max-id = <10>;
goodix,panel-max-x = <1080>;
goodix,panel-max-y = <1920>;
goodix,panel-max-w = <1000>;
goodix,panel-max-p = <1000>;
//goodix,swap-axis;
goodix,panel-key-map = <172 158>;/*KEY_HOMEPAGE, KEY_BACK*/
sensor0 {
/*goodix,panel-max-x = <401>;
goodix,panel-max-y = <401>;
goodix,panel-max-w = <401>;
goodix,panel-max-p = <254>;*/
};
};
观察以上代码可知,这些设备信息是对“touch”对象的扩充,而不是“cap_touch”
需要注意的是:无论是直接修改DSW文件,还是修改dts文件,compatible都应该是在i2cXX里面,XX对应是触控设备挂在哪个I2C下面,比如前面例子中的I2C4.
另外,在dts文件中添加的中断、GPIO、pinctrl等信息可以不放在i2cXX下面,驱动调用内核函数通过相应的名字都可以找到对应的信息,但为了统一最好也放在i2cXX下面。
Compatible可以在DWS文件中修改,然后由内核编译时生成;也可以直接在dts中相应的i2cXX中修改,都是一样的。目前所知的,如果DWS和dts都有compatible,那么应该是以后加载的为准,也即dts为准,具体是不是这样,还需要进一步的验证。