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(...)