• pinctrl子系统 - 源码解析(五)


    一,pincontroller (pinctrl server)构造

    1,pin controller driver与 device match并执行probe
    1. diwali_pinctrl_init
    2. platform_driver_register(&diwali_pinctrl_driver); //根据match table找到device
    3. diwali_pinctrl_probe
    4. pinctrl_data = of_device_get_match_data(&pdev->dev);//获取msm_pinctrl_soc_data
    5. msm_pinctrl_probe(pdev, pinctrl_data);//传递soc data
    2,probe流程
    1. int msm_pinctrl_probe(struct platform_device *pdev,
    2. const struct msm_pinctrl_soc_data *soc_data)
    3. {
    4. // 1)分配一个msm_pinctrl结构并初始化
    5. msm_pinctrl_data = pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
    6. if (!pctrl)
    7. return -ENOMEM;
    8. pctrl->dev = &pdev->dev;
    9. pctrl->soc = soc_data;
    10. pctrl->chip = msm_gpio_template;
    11. pctrl->intr_target_use_scm = of_device_is_compatible(
    12. pctrl->dev->of_node,
    13. "qcom,ipq8064-pinctrl");
    14. // 2)从pin controller device dts节点中获取设备的物理地址
    15. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    16. if (!res)
    17. return -ENOENT;
    18. //将设备的物理地址转换为虚拟地址,使用该地址读写该pin controller device
    19. pctrl->regs[0] = devm_ioremap_resource(&pdev->dev, res);
    20. if (IS_ERR(pctrl->regs[0]))
    21. return PTR_ERR(pctrl->regs[0]);
    22. pctrl->phys_base[0] = res->start;
    23. //3)从pin controller device dts节点中获取irq number
    24. pctrl->irq = platform_get_irq(pdev, 0);
    25. if (pctrl->irq < 0)
    26. return pctrl->irq;
    27. //4) 构造一个pinctrl_desc
    28. pctrl->desc.owner = THIS_MODULE;
    29. //引脚枚举与命名
    30. pctrl->desc.pctlops = &msm_pinctrl_ops;
    31. //引脚复用
    32. pctrl->desc.pmxops = &msm_pinmux_ops;
    33. //引脚配置
    34. pctrl->desc.confops = &msm_pinconf_ops;
    35. pctrl->desc.name = dev_name(&pdev->dev);
    36. //soc data提供
    37. pctrl->desc.pins = pctrl->soc->pins;
    38. pctrl->desc.npins = pctrl->soc->npins;
    39. pctrl->desc.num_custom_params = ARRAY_SIZE(msm_gpio_bindings);
    40. pctrl->desc.custom_params = msm_gpio_bindings;
    41. //根据pinctrl_desc信息构造一个pinctrl_dev
    42. pctrl->pctrl = devm_pinctrl_register(&pdev->dev, &pctrl->desc, pctrl);
    43. if (IS_ERR(pctrl->pctrl)) {
    44. dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
    45. return PTR_ERR(pctrl->pctrl);
    46. }
    47. //5)
    48. ret = msm_gpio_init(pctrl);
    49. if (ret)
    50. return ret;
    51. platform_set_drvdata(pdev, pctrl);
    52. }

    pin controller描述符中包括了三类操作函数:pctlops是一些全局的控制函数,pmxops是复用引脚相关的操作函数,confops操作函数是用来配置引脚的特性(例如:pull-up/down)。这些callback函数都是和具体的底层pin controller的操作相关,qcom平台pinctrl controller low level driver实现的API如下,每一个的实现请查看kernel开源代码pinctrl-msm.c:

    1)struct pinctrl_ops

    1. static const struct pinctrl_ops msm_pinctrl_ops = {
    2. .get_groups_count = msm_get_groups_count,
    3. .get_group_name = msm_get_group_name,
    4. .get_group_pins = msm_get_group_pins,
    5. .dt_node_to_map = pinconf_generic_dt_node_to_map_group,
    6. .dt_free_map = pinctrl_utils_free_map,
    7. };

    2)struct pinmux_ops

    1. static const struct pinmux_ops msm_pinmux_ops = {
    2. .request = msm_pinmux_request,
    3. .get_functions_count = msm_get_functions_count,
    4. .get_function_name = msm_get_function_name,
    5. .get_function_groups = msm_get_function_groups,
    6. .gpio_request_enable = msm_pinmux_request_gpio,
    7. .set_mux = msm_pinmux_set_mux,
    8. };

    3)struct pinconf_ops

    1. static const struct pinconf_ops msm_pinconf_ops = {
    2. .is_generic = true,
    3. .pin_config_group_get = msm_config_group_get,
    4. .pin_config_group_set = msm_config_group_set,
    5. };
    3,devm_pinctrl_register()流程
    1. pctrl->pctrl = devm_pinctrl_register(&pdev->dev, &pctrl->desc, pctrl);
    2. pctldev = pinctrl_register(pctldesc, dev, driver_data);
    3. pinctrl_init_controller(pctldesc, dev, driver_data);
    4. //给pinctrl_dev分配内存
    5. pctldev = kzalloc(sizeof(*pctldev), GFP_KERNEL);
    6. // driver_data是msm_pinctrl
    7. pctldev->driver_data = driver_data;
    8. //check core ops for sanity
    9. pinctrl_check_ops(pctldev);
    10. //If we're implementing pinmuxing, check the ops for sanity
    11. pinmux_check_ops(pctldev);
    12. //If we're implementing pinconfig, check the ops for sanity
    13. pinconf_check_ops(pctldev);
    14. pinctrl_register_pins(pctldev, pctldesc->pins, pctldesc->npins);
    15. pinctrl_enable(pctldev);
    16. //将pinctrl_dev加入pinctrldev_list链表
    17. list_add_tail(&pctldev->node, &pinctrldev_list);
    18. //在每一个pin controller device的目录中生成pinctrl调试节点,eg:/sys/kernel/debug/pinctrl/f000000.pinctrl
    19. pinctrl_init_device_debugfs(pctldev);
    20. debugfs_create_file("pins", S_IFREG | S_IRUGO, device_root, pctldev, &pinctrl_pins_fops);
    21. debugfs_create_file("pingroups", S_IFREG | S_IRUGO, device_root, pctldev, &pinctrl_groups_fops);
    22. debugfs_create_file("gpio-ranges", S_IFREG | S_IRUGO, device_root, pctldev, &pinctrl_gpioranges_fops);

    二,client端使用pinctrl的过程

    1,dev_pin_info

    设备节点要么被转换为platform_device,或者其他结构体(比如i2c_client),但是里面都会有一个device结构体,每个device结构体里都有一个dev_pin_info结构体,用来保存设备的pinctrl信息。

    platform_device匹配driver会执行probe探测函数,执行到驱动中真正的probe函数之前,会进行pinctrl的处理,处理函数为pinctrl_bind_pins。

    1. really_probe()
    2. pinctrl_bind_pins(dev);
    3. devm_pinctrl_get(dev);
    4. pinctrl_get(dev);
    5. create_pinctrl(dev, NULL);
    6. //把dts中该设备的pinctrl配置解析到pinctrl map中
    7. pinctrl_dt_to_map(p, pctldev);
    8. dt_to_map_one_config(p, pctldev, statename, np_config);
    9. ops->dt_node_to_map(pctldev, np_config, &map, &num_maps);
    10. .dt_node_to_map = pinconf_generic_dt_node_to_map_group,
    11. pinconf_generic_dt_node_to_map
    12. //pinctrl map mux
    13. pinctrl_utils_add_map_mux
    14. //pinctrl map configs
    15. pinctrl_utils_add_map_configs
    16. //把pinctrl map 转为pinctrl setting
    17. add_setting(p, pctldev, map);
    18. pinmux_map_to_setting(map, setting);
    19. pinconf_map_to_setting(map, setting);
    20. list_add_tail(&setting->node, &state->settings);
    21. //该设备的pinctrl state holder挂到pinctrl_list链表
    22. list_add_tail(&p->node, &pinctrl_list);
    23. //解析标准的pinctrl state,PINCTRL_STATE_DEFAULT/PINCTRL_STATE_INIT/PINCTRL_STATE_SLEEP/PINCTRL_STATE_IDLE
    24. dev->pins->default_state = pinctrl_lookup_state(dev->pins->p, PINCTRL_STATE_DEFAULT);
    25. dev->pins->init_state = pinctrl_lookup_state(dev->pins->p, PINCTRL_STATE_INIT);
    26. pinctrl_select_state(dev->pins->p, dev->pins->default_state);
    27. dev->pins->sleep_state = pinctrl_lookup_state(dev->pins->p, PINCTRL_STATE_SLEEP);
    28. dev->pins->idle_state = pinctrl_lookup_state(dev->pins->p, PINCTRL_STATE_IDLE);
    29. //执行device或者driver的probe函数
    30. dev->bus->probe(dev);
    31. drv->probe(dev);
    2,pinctrl debugfs
    2.1 一个pin controller device --- f000000.pinctrl
    1. ls -l /sys/kernel/debug/pinctrl/f000000.pinctrl
    2. -r--r--r-- 1 root root 0 1970-01-01 00:00 gpio-ranges
    3. -r--r--r-- 1 root root 0 1970-01-01 00:00 pinconf-groups
    4. -r--r--r-- 1 root root 0 1970-01-01 00:00 pinconf-pins
    5. -r--r--r-- 1 root root 0 1970-01-01 00:00 pingroups
    6. -r--r--r-- 1 root root 0 1970-01-01 00:00 pinmux-functions
    7. -r--r--r-- 1 root root 0 1970-01-01 00:00 pinmux-pins
    8. -r--r--r-- 1 root root 0 1970-01-01 00:00 pins

    系统中注册的所有的pinctrl controller,打印接口:

    1. static int pinctrl_devices_show(struct seq_file *s, void *what)
    2. {
    3. struct pinctrl_dev *pctldev;
    4. seq_puts(s, "name [pinmux] [pinconf]\n");
    5. mutex_lock(&pinctrldev_list_mutex);
    6. list_for_each_entry(pctldev, &pinctrldev_list, node) {
    7. seq_printf(s, "%s ", pctldev->desc->name);
    8. if (pctldev->desc->pmxops)
    9. seq_puts(s, "yes ");
    10. else
    11. seq_puts(s, "no ");
    12. if (pctldev->desc->confops)
    13. seq_puts(s, "yes");
    14. else
    15. seq_puts(s, "no");
    16. seq_puts(s, "\n");
    17. }
    18. mutex_unlock(&pinctrldev_list_mutex);
    19. return 0;
    20. }
    21. DEFINE_SHOW_ATTRIBUTE(pinctrl_devices);

    cat /sys/kernel/debug/pinctrl/pinctrl-devices:

    1. name [pinmux] [pinconf]
    2. f000000.pinctrl yes yes
    3. c42d000.qcom,spmi:qcom,pmk8350@0:pinctrl@b000 yes yes
    4. c42d000.qcom,spmi:qcom,pm8350c@2:pinctrl@8800 yes yes
    5. c42d000.qcom,spmi:qcom,pm7325@1:pinctrl@8800 yes yes
    6. c42d000.qcom,spmi:qcom,pm8350b@3:pinctrl@8800 yes yes
    7. soc:spf_core_platform:lpi_pinctrl@3440000 yes yes
    2.2 pinctrl maps信息打印接口
    1. static int pinctrl_maps_show(struct seq_file *s, void *what)
    2. {
    3. struct pinctrl_maps *maps_node;
    4. int i;
    5. const struct pinctrl_map *map;
    6. seq_puts(s, "Pinctrl maps:\n");
    7. mutex_lock(&pinctrl_maps_mutex);
    8. for_each_maps(maps_node, i, map) {
    9. seq_printf(s, "device %s\nstate %s\ntype %s (%d)\n",
    10. map->dev_name, map->name, map_type(map->type),
    11. map->type);
    12. if (map->type != PIN_MAP_TYPE_DUMMY_STATE)
    13. seq_printf(s, "controlling device %s\n",
    14. map->ctrl_dev_name);
    15. switch (map->type) {
    16. case PIN_MAP_TYPE_MUX_GROUP:
    17. pinmux_show_map(s, map);
    18. break;
    19. case PIN_MAP_TYPE_CONFIGS_PIN:
    20. case PIN_MAP_TYPE_CONFIGS_GROUP:
    21. pinconf_show_map(s, map);
    22. break;
    23. default:
    24. break;
    25. }
    26. seq_putc(s, '\n');
    27. }
    28. mutex_unlock(&pinctrl_maps_mutex);
    29. return 0;
    30. }
    31. DEFINE_SHOW_ATTRIBUTE(pinctrl_maps);

    pinctrl client 节点举例:

    1. //一个device的pinctrl state配置
    2. xxx@xx {
    3. pinctrl-names = "pmx_ts_active", "pmx_ts_suspend", "pmx_ts_release";
    4. pinctrl-0 = <&ts_active>;
    5. pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
    6. pinctrl-2 = <&ts_release>;
    7. };

    pinctrl server 端的配置见上一篇文章,解析后的pinctrl maps信息:

    cat /sys/kernel/debug/pinctrl/pinctrl-maps

    1. device spi1.0
    2. state pmx_ts_active
    3. type MUX_GROUP (2)
    4. controlling device f000000.pinctrl
    5. group gpio129
    6. function gpio
    7. device spi1.0
    8. state pmx_ts_active
    9. type MUX_GROUP (2)
    10. controlling device f000000.pinctrl
    11. group gpio51
    12. function gpio
    13. device spi1.0
    14. state pmx_ts_active
    15. type CONFIGS_GROUP (4)
    16. controlling device f000000.pinctrl
    17. group gpio129
    18. config 00000105
    19. config 00000809
    20. device spi1.0
    21. state pmx_ts_active
    22. type CONFIGS_GROUP (4)
    23. controlling device f000000.pinctrl
    24. group gpio51
    25. config 00000105
    26. config 00000809
    27. device spi1.0
    28. state pmx_ts_suspend
    29. type MUX_GROUP (2)
    30. controlling device f000000.pinctrl
    31. group gpio51
    32. function gpio
    33. device spi1.0
    34. state pmx_ts_suspend
    35. type CONFIGS_GROUP (4)
    36. controlling device f000000.pinctrl
    37. group gpio51
    38. config 00000103
    39. config 00000209
    40. device spi1.0
    41. state pmx_ts_suspend
    42. type MUX_GROUP (2)
    43. controlling device f000000.pinctrl
    44. group gpio129
    45. function gpio
    46. device spi1.0
    47. state pmx_ts_suspend
    48. type CONFIGS_GROUP (4)
    49. controlling device f000000.pinctrl
    50. group gpio129
    51. config 00000103
    52. config 00000209
    53. device spi1.0
    54. state pmx_ts_release
    55. type MUX_GROUP (2)
    56. controlling device f000000.pinctrl
    57. group gpio129
    58. function gpio
    59. device spi1.0
    60. state pmx_ts_release
    61. type MUX_GROUP (2)
    62. controlling device f000000.pinctrl
    63. group gpio51
    64. function gpio
    65. device spi1.0
    66. state pmx_ts_release
    67. type CONFIGS_GROUP (4)
    68. controlling device f000000.pinctrl
    69. group gpio129
    70. config 00000001
    71. config 00000209
    72. device spi1.0
    73. state pmx_ts_release
    74. type CONFIGS_GROUP (4)
    75. controlling device f000000.pinctrl
    76. group gpio51
    77. config 00000001
    78. config 00000209
    2.3 pinctrl setting信息打印接口
    1. static int pinctrl_show(struct seq_file *s, void *what)
    2. {
    3. struct pinctrl *p;
    4. struct pinctrl_state *state;
    5. struct pinctrl_setting *setting;
    6. seq_puts(s, "Requested pin control handlers their pinmux maps:\n");
    7. mutex_lock(&pinctrl_list_mutex);
    8. list_for_each_entry(p, &pinctrl_list, node) {
    9. seq_printf(s, "device: %s current state: %s\n",
    10. dev_name(p->dev),
    11. p->state ? p->state->name : "none");
    12. list_for_each_entry(state, &p->states, node) {
    13. seq_printf(s, " state: %s\n", state->name);
    14. list_for_each_entry(setting, &state->settings, node) {
    15. struct pinctrl_dev *pctldev = setting->pctldev;
    16. seq_printf(s, " type: %s controller %s ",
    17. map_type(setting->type),
    18. pinctrl_dev_get_name(pctldev));
    19. switch (setting->type) {
    20. case PIN_MAP_TYPE_MUX_GROUP:
    21. pinmux_show_setting(s, setting);
    22. break;
    23. case PIN_MAP_TYPE_CONFIGS_PIN:
    24. case PIN_MAP_TYPE_CONFIGS_GROUP:
    25. pinconf_show_setting(s, setting);
    26. break;
    27. default:
    28. break;
    29. }
    30. }
    31. }
    32. }
    33. mutex_unlock(&pinctrl_list_mutex);
    34. return 0;
    35. }
    36. DEFINE_SHOW_ATTRIBUTE(pinctrl);

    上一节pinctrl maps转成的pinctrl settings信息打印:

    cat /sys/kernel/debug/pinctrl/pinctrl-handles

    1. device: spi1.0 current state: pmx_ts_active
    2. state: pmx_ts_active
    3. type: MUX_GROUP controller f000000.pinctrl group: gpio129 (129) function: gpio (0)
    4. type: MUX_GROUP controller f000000.pinctrl group: gpio51 (51) function: gpio (0)
    5. type: CONFIGS_GROUP controller f000000.pinctrl group gpio129 (129)config 00000105
    6. config 00000809
    7. type: CONFIGS_GROUP controller f000000.pinctrl group gpio51 (51)config 00000105
    8. config 00000809
    9. state: pmx_ts_suspend
    10. type: MUX_GROUP controller f000000.pinctrl group: gpio51 (51) function: gpio (0)
    11. type: CONFIGS_GROUP controller f000000.pinctrl group gpio51 (51)config 00000103
    12. config 00000209
    13. type: MUX_GROUP controller f000000.pinctrl group: gpio129 (129) function: gpio (0)
    14. type: CONFIGS_GROUP controller f000000.pinctrl group gpio129 (129)config 00000103
    15. config 00000209
    16. state: pmx_ts_release
    17. type: MUX_GROUP controller f000000.pinctrl group: gpio129 (129) function: gpio (0)
    18. type: MUX_GROUP controller f000000.pinctrl group: gpio51 (51) function: gpio (0)
    19. type: CONFIGS_GROUP controller f000000.pinctrl group gpio129 (129)config 00000001
    20. config 00000209
    21. type: CONFIGS_GROUP controller f000000.pinctrl group gpio51 (51)config 00000001
    22. config 00000209
    3,设备树节点转换为pinctrl_map

    pinctrl_dt_to_map:

    1. int pinctrl_dt_to_map(struct pinctrl *p, struct pinctrl_dev *pctldev)
    2. {
    3. struct device_node *np = p->dev->of_node;
    4. int state, ret;
    5. char *propname;
    6. struct property *prop;
    7. const char *statename;
    8. const __be32 *list;
    9. int size, config;
    10. phandle phandle;
    11. struct device_node *np_config;
    12. /* CONFIG_OF enabled, p->dev not instantiated from DT */
    13. if (!np) {
    14. if (of_have_populated_dt())
    15. dev_dbg(p->dev,
    16. "no of_node; not parsing pinctrl DT\n");
    17. return 0;
    18. }
    19. /* We may store pointers to property names within the node */
    20. of_node_get(np);
    21. /* For each defined state ID */
    22. //遍历所有的state ID
    23. for (state = 0; ; state++) {
    24. /* Retrieve the pinctrl-* property */
    25. propname = kasprintf(GFP_KERNEL, "pinctrl-%d", state);
    26. if (!propname)
    27. return -ENOMEM;
    28. prop = of_find_property(np, propname, &size);
    29. kfree(propname);
    30. if (!prop) {
    31. if (state == 0) {
    32. of_node_put(np);
    33. return -ENODEV;
    34. }
    35. break;
    36. }
    37. list = prop->value;
    38. //一个state对应的config的数量
    39. size /= sizeof(*list);
    40. /* Determine whether pinctrl-names property names the state */
    41. //从pinctrl-names中获取statename
    42. ret = of_property_read_string_index(np, "pinctrl-names",
    43. state, &statename);
    44. /*
    45. * If not, statename is just the integer state ID. But rather
    46. * than dynamically allocate it and have to free it later,
    47. * just point part way into the property name for the string.
    48. */
    49. if (ret < 0)
    50. statename = prop->name + strlen("pinctrl-");
    51. /* For every referenced pin configuration node in it */
    52. //遍历每一个state下面的每一个config
    53. for (config = 0; config < size; config++) {
    54. phandle = be32_to_cpup(list++);
    55. /* Look up the pin configuration node */
    56. np_config = of_find_node_by_phandle(phandle);
    57. if (!np_config) {
    58. dev_err(p->dev,
    59. "prop %s index %i invalid phandle\n",
    60. prop->name, config);
    61. ret = -EINVAL;
    62. goto err;
    63. }
    64. /* Parse the node */
    65. //对于一个config节点的解析函数
    66. ret = dt_to_map_one_config(p, pctldev, statename,
    67. np_config);
    68. of_node_put(np_config);
    69. if (ret < 0)
    70. goto err;
    71. }
    72. /* No entries in DT? Generate a dummy state table entry */
    73. if (!size) {
    74. ret = dt_remember_dummy_state(p, statename);
    75. if (ret < 0)
    76. goto err;
    77. }
    78. }
    79. return 0;
    80. err:
    81. pinctrl_dt_free_maps(p);
    82. return ret;
    83. }

    dt_to_map_one_config:

    1. static int dt_to_map_one_config(struct pinctrl *p,
    2. struct pinctrl_dev *hog_pctldev,
    3. const char *statename,
    4. struct device_node *np_config)
    5. {
    6. struct pinctrl_dev *pctldev = NULL;
    7. struct device_node *np_pctldev;
    8. const struct pinctrl_ops *ops;
    9. int ret;
    10. struct pinctrl_map *map;
    11. unsigned num_maps;
    12. bool allow_default = false;
    13. /* Find the pin controller containing np_config */
    14. np_pctldev = of_node_get(np_config);
    15. for (;;) {
    16. //找到pctldev
    17. pctldev = get_pinctrl_dev_from_of_node(np_pctldev);
    18. }
    19. of_node_put(np_pctldev);
    20. /*
    21. * Call pinctrl driver to parse device tree node, and
    22. * generate mapping table entries
    23. */
    24. ops = pctldev->desc->pctlops;
    25. if (!ops->dt_node_to_map) {
    26. dev_err(p->dev, "pctldev %s doesn't support DT\n",
    27. dev_name(pctldev->dev));
    28. return -ENODEV;
    29. }
    30. //调用pinctrl driver中实现的dt_node_to_map
    31. ret = ops->dt_node_to_map(pctldev, np_config, &map, &num_maps);
    32. /* Stash the mapping table chunk away for later use */
    33. //保存解析出来的pinctrl maps
    34. return dt_remember_or_free_map(p, statename, pctldev, map, num_maps);
    35. }

    保存解析出来的pinctrl maps,pinctrldt_remember_or_free_map:

    1. dt_remember_or_free_map
    2. list_add_tail(&dt_map->node, &p->dt_maps);
    3. pinctrl_register_mappings(map, num_maps);
    4. list_add_tail(&maps_node->node, &pinctrl_maps);
    4,pinctrl map to pinctrl setting流程
    1. mutex_lock(&pinctrl_maps_mutex);
    2. /* Iterate over the pin control maps to locate the right ones */
    3. //取出pinctrl_maps链表中的每一个node,遍历每一个node中的&_maps_node_->maps[_i_] (指向struct pinctrl_map的map指针)
    4. for_each_maps(maps_node, i, map) {
    5. /* Map must be for this device */
    6. if (strcmp(map->dev_name, devname))
    7. continue;
    8. /*
    9. * If pctldev is not null, we are claiming hog for it,
    10. * that means, setting that is served by pctldev by itself.
    11. *
    12. * Thus we must skip map that is for this device but is served
    13. * by other device.
    14. */
    15. if (pctldev &&
    16. strcmp(dev_name(pctldev->dev), map->ctrl_dev_name))
    17. continue;
    18. //一个map转为一个setting
    19. ret = add_setting(p, pctldev, map);
    20. /*
    21. * At this point the adding of a setting may:
    22. *
    23. * - Defer, if the pinctrl device is not yet available
    24. * - Fail, if the pinctrl device is not yet available,
    25. * AND the setting is a hog. We cannot defer that, since
    26. * the hog will kick in immediately after the device
    27. * is registered.
    28. *
    29. * If the error returned was not -EPROBE_DEFER then we
    30. * accumulate the errors to see if we end up with
    31. * an -EPROBE_DEFER later, as that is the worst case.
    32. */
    33. if (ret == -EPROBE_DEFER) {
    34. pinctrl_free(p, false);
    35. mutex_unlock(&pinctrl_maps_mutex);
    36. return ERR_PTR(ret);
    37. }
    38. }
    39. mutex_unlock(&pinctrl_maps_mutex);

    add_setting:

    1. static int add_setting(struct pinctrl *p, struct pinctrl_dev *pctldev,
    2. const struct pinctrl_map *map)
    3. {
    4. struct pinctrl_state *state;
    5. struct pinctrl_setting *setting;
    6. int ret;
    7. //首先在struct pinctrl结构体中查找该state是否存在,list_for_each_entry(state, &p->states, node)
    8. state = find_state(p, map->name);
    9. if (!state)
    10. //如果state不存在就新建一个state,list_add_tail(&state->node, &p->states);
    11. state = create_state(p, map->name);
    12. if (IS_ERR(state))
    13. return PTR_ERR(state);
    14. if (map->type == PIN_MAP_TYPE_DUMMY_STATE)
    15. return 0;
    16. //给struct pinctrl_setting分配内存空间
    17. setting = kzalloc(sizeof(*setting), GFP_KERNEL);
    18. if (!setting)
    19. return -ENOMEM;
    20. //初始化setting结构体
    21. setting->type = map->type;
    22. if (pctldev)
    23. setting->pctldev = pctldev;
    24. else
    25. setting->pctldev =
    26. get_pinctrl_dev_from_devname(map->ctrl_dev_name);
    27. if (!setting->pctldev) {
    28. kfree(setting);
    29. /* Do not defer probing of hogs (circular loop) */
    30. if (!strcmp(map->ctrl_dev_name, map->dev_name))
    31. return -ENODEV;
    32. /*
    33. * OK let us guess that the driver is not there yet, and
    34. * let's defer obtaining this pinctrl handle to later...
    35. */
    36. dev_info(p->dev, "unknown pinctrl device %s in map entry, deferring probe",
    37. map->ctrl_dev_name);
    38. return -EPROBE_DEFER;
    39. }
    40. setting->dev_name = map->dev_name;
    41. switch (map->type) {
    42. case PIN_MAP_TYPE_MUX_GROUP:
    43. //pinmux map to setting
    44. ret = pinmux_map_to_setting(map, setting);
    45. break;
    46. case PIN_MAP_TYPE_CONFIGS_PIN:
    47. case PIN_MAP_TYPE_CONFIGS_GROUP:
    48. //pin configure map to setting
    49. ret = pinconf_map_to_setting(map, setting);
    50. break;
    51. default:
    52. ret = -EINVAL;
    53. break;
    54. }
    55. if (ret < 0) {
    56. kfree(setting);
    57. return ret;
    58. }
    59. //将转化后的setting挂到state->settings链表
    60. list_add_tail(&setting->node, &state->settings);
    61. return 0;
    62. }

    pinmux_map_to_setting:

    1. int pinmux_map_to_setting(const struct pinctrl_map *map,
    2. struct pinctrl_setting *setting)
    3. {
    4. struct pinctrl_dev *pctldev = setting->pctldev;
    5. const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
    6. char const * const *groups;
    7. unsigned num_groups;
    8. int ret;
    9. ret = pinmux_func_name_to_selector(pctldev, map->data.mux.function);
    10. setting->data.mux.func = ret;
    11. ret = pmxops->get_function_groups(pctldev, setting->data.mux.func,
    12. &groups, &num_groups);
    13. if (ret < 0) {
    14. dev_err(pctldev->dev, "can't query groups for function %s\n",
    15. map->data.mux.function);
    16. return ret;
    17. }
    18. ret = pinctrl_get_group_selector(pctldev, group);
    19. if (ret < 0) {
    20. dev_err(pctldev->dev, "invalid group %s in map table\n",
    21. map->data.mux.group);
    22. return ret;
    23. }
    24. setting->data.mux.group = ret;
    25. return 0;
    26. }

    map 到 setting的转化只是将字符串转为整型数表示的形式。

    5,client节点如何使用设置管脚
    1. really_probe
    2. pinctrl_bind_pins
    3. /* 寻找state */
    4. pinctrl_lookup_state
    5. /* 选择state */
    6. pinctrl_select_state
    7. pinctrl_commit_state
    8. /* 遍历settings链表 */
    9. list_for_each_entry(setting, &state->settings, node) {
    10. switch (setting->type) {
    11. case PIN_MAP_TYPE_MUX_GROUP:
    12. /* 设置复用 */
    13. pinmux_enable_setting(setting);
    14. ops->set_mux(...);
    15. case PIN_MAP_TYPE_CONFIGS_PIN:
    16. case PIN_MAP_TYPE_CONFIGS_GROUP:
    17. /* 设置配置 */
    18. pinconf_apply_setting(setting);
    19. ops->pin_config_group_set(...);
    20. }

    参考链接:

    pinctrl 子系统介绍_pinctrl子系统_kenny_wju的博客-CSDN博客

    Linux内核中的GPIO系统之(3):pin controller driver代码分析

  • 相关阅读:
    2419. 按位与最大的最长子数组
    DXF笔记:根据法向量,求出位置矩阵或坐标系
    回放及资料下载|2022 智能云边开源峰会
    PAT(Advanced Level) Practice(with python)——1066 Root of AVL Tree
    CF1668A Direction Change
    软考高级系统架构设计师系列之:深入理解设计模式
    音视频开发是不是C++开发中最难的细分方向?
    java8函数式编程,常用高阶函数处理
    @Autowired和@Resource注解的区别和联系
    E. Wish I Knew How to Sort codeforces1754E
  • 原文地址:https://blog.csdn.net/u011456016/article/details/133852597