基于Linux 3.10.49内核的pinctrl流程分析

Linux kernel 3.10.49+
 pinctrl驱动的platform注册就不说了,
无非就是platform_driver_register这个入口,
最后匹配到合适的设备后调用struct platform_driver 的probe函数.

这里说说, pinctl io复用关系(pinmux)的是怎么通过device tree source(dts)设置的.
1. 首先,当然是看pinctrl驱动的probe函数(这相当于驱动初始化的入口):
    drivers/pinctrl/pinctrl-xxxxxx.c : xxxxxx_pinctrl_probe(...)
    xxxxxx_pinctrl_probe(...) --> pinctrl_register(...)

2. drivers/pinctrl/core.c : pinctrl_register(...)
    pinctrl_register(...) --> pinctrl_get(...)

3. drivers/pinctrl/core.c : pinctrl_get(...)
    pinctrl_get(...) --> create_pinctrl(...)

4. drivers/pinctrl/core.c : create_pinctrl(...)
    create_pinctrl(...) --> pinctrl_dt_to_map(...)

5. drivers/pinctrl/devicetree.c : pinctrl_dt_to_map(...)
    pinctrl_dt_to_map(...) --> dt_to_map_one_config(...)

6. drivers/pinctrl/devicetree.c : dt_to_map_one_config(...)
    dt_to_map_one_config(...) --> ops->dt_node_to_map(...) // 回调函数. 第7~10步是进入到回调后的一系列初始化.

7. ops->dt_node_to_map 就是 drivers/pinctrl/pinctrl-xxxxxx.c 中 struct pinctrl_ops 的 dt_node_to_map成员函数指针,
    也就是struct pinctrl_ops xxxxxx_pinctrl_ops->dt_node_to_map  = xxxxxx_pinctrl_dt_node_to_map;

8.  drivers/pinctrl/pinctrl-xxxxxx.c : xxxxxx_pinctrl_dt_node_to_map(...)
    xxxxxx_pinctrl_dt_node_to_map(...) --> 轮询调用 xxxxxx_pinctrl_dt_subnode_to_map(...)
    轮询的内容: struct device_node *np 其中一个就是 dts文件里pinmuxing node设备, 而pinmuxing node设备有7个子node(看例子):
    如: arm926u, i2c0, i2c1等.
        state_default: pinmuxing {
            arm926u {
                    xxx,function = "arm926u";
                    xxx,group = "arm926u";
            };
            i2c0 {
                    xxx,function = "i2c";
                    xxx,group = "i2c0_pos_0";
            };
            i2c1 {
                    xxx,function = "i2c";
                    xxx,group = "i2c1";
            };
            i2c2 {
                    xxx,function = "i2c";
                    xxx,group = "i2c2";
            };
            uart0 {
                    xxx,function = "uart";
                    xxx,group = "uart0_pos_0";
            };
            uart1 {
                    xxx,function = "uart";
                    xxx,group = "uart1_pos_0";
            };
            wdt {
                    xxx,function = "wdt";
                    xxx,group = "wdt";
            };
        };

9. drivers/pinctrl/pinctrl-xxxxxx.c : xxxxxx_pinctrl_dt_subnode_to_map(...)
    在这里有:
    ret = of_property_read_string(np, "xxx,function", &function);  // 哈哈, 解析dts node设备属性
    ret = of_property_read_string(np, "xxx,group", &group);
    reserve_map(...) // allocate map内存
    最后调用 add_map_mux(...);

10. drivers/pinctrl/pinctrl-xxxxxx.c : add_map_mux(...)
    (*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP;  //特别注意这个type, 后续用到
    (*map)[*num_maps].data.mux.group = group;        // group只是个字符串, 如:i2c0_pos_0
    (*map)[*num_maps].data.mux.function = function;  // function只是个字符串, 如:i2c
    (*num_maps)++;

11. 回调ops->dt_node_to_map完成, 回到第6步继续运行.
    drivers/pinctrl/devicetree.c : 运行dt_remember_or_free_map(...);

12. drivers/pinctrl/devicetree.c : dt_remember_or_free_map(...)
    dt_remember_or_free_map(...) --> pinctrl_register_map(...)

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/7ba6319fb11879e189706f1d0eff5d9e.html