gpio子系统和pinctrl子系统(中)

pinctrl子系统核心实现分析

pinctrl子系统的内容在drivers/pinctrl文件夹下,主要文件有(建议先看看pinctrl内核文档Documentation/pinctrl.txt):
core.c
devicetree.c
pinconf.c
pinmux.c
pinctrl-xxx.c

core.c为pinctrl的核心代码,实现了pinctrl框架,pinmux.c和pinconf.c基于core实现了对pinmux和pinconf的支持,pinctrl-xxx.c为厂商相关的pinctrl实现(又是苦逼的bsp工程师_),当然有些厂商还未采用pinctrl机制,因此就没有对应的实现。最后说一句,pinctrl的实现不许用我们在驱动里调用任何它提供的api,所有的pinctrl动作都是在通用内核代码里完成了,对于驱动工程师是透明的。驱动工程师只需要通过设备树文件就能掌控整个系统的pin管理了,后面分析的过程会证实这一点。

pinctrl在代码层级只与bsp工程师有关,他们需要调用pinctrl api pinctrl_register注册。先引用一张网上截图:

pinctrl子系统框架


对于驱动工程师,只需要通过设备树文件就可以起到配置整个系统pin的目的。有几个概念先理一下,功能和组,功能就是指uart、i2c、spi等这些,组是pin的集合,我们都知道现在的soc的pin中,经常会遇到一个功能可以由不同的pin集合(即组)配置,当然同一时间只能选一个pin集合,因此,当我们要用某个功能的时候,需要告诉它func以及哪一组。下面开始分析pinctrl_register


   
   
  1. struct pinctrl_dev * pinctrl_register( struct pinctrl_desc *pctldesc,
  2. struct device *dev, void *driver_data)
  3. {
  4. struct pinctrl_dev *pctldev;
  5. int ret;
  6. if (!pctldesc)
  7. return NULL;
  8. if (!pctldesc->name)
  9. return NULL;
  10. //一般只有pinctrl chip driver需要调用pinctrl_register,pctldev就是软件上pinctrl的抽象
  11. pctldev = kzalloc( sizeof(*pctldev), GFP_KERNEL);
  12. if (pctldev == NULL) {
  13. dev_err(dev, "failed to alloc struct pinctrl_dev\n");
  14. return NULL;
  15. }
  16. /* Initialize pin control device struct */
  17. //初始化一些成员,后面会遇到它们的
  18. pctldev->owner = pctldesc->owner;
  19. pctldev->desc = pctldesc;
  20. pctldev->driver_data = driver_data;
  21. //pin_desc_tree用于存放所有的pin信息,由后面即将分析的pinctrl_register_pins来填充
  22. //所有pin信息来源于输入参数pctldesc,也就是说每个pinctrl chip driver的实现者需要告诉pinctrl
  23. //子系统该pinctrl chip所有的pin信息
  24. INIT_RADIX_TREE(&pctldev->pin_desc_tree, GFP_KERNEL);
  25. //这个由gpio子系统填充信息,还记得of_gpiochip_add_pin_range吧^_^最后总结的时候再结合gpio子系统一起看看这部分
  26. INIT_LIST_HEAD(&pctldev->gpio_ranges);
  27. pctldev->dev = dev;
  28. mutex_init(&pctldev->mutex);
  29. /* check core ops for sanity */
  30. //pinctrl_ops是pinctrl chip driver必须要实现的一组回调集合,后面在用到它里面的api时再详细讲解
  31. if ( pinctrl_check_ops(pctldev)) {
  32. dev_err(dev, "pinctrl ops lacks necessary functions\n");
  33. goto out_err;
  34. }
  35. /* If we're implementing pinmuxing, check the ops for sanity */
  36. //如果提供了pinmux ops,检查下是否合法
  37. if (pctldesc->pmxops) {
  38. if ( pinmux_check_ops(pctldev))
  39. goto out_err;
  40. }
  41. /* If we're implementing pinconfig, check the ops for sanity */
  42. //如果提供了pinconf ops,检查下是否合法
  43. if (pctldesc->confops) {
  44. if ( pinconf_check_ops(pctldev))
  45. goto out_err;
  46. }
  47. /* Register all the pins */
  48. dev_dbg(dev, "try to register %d pins ...\n", pctldesc->npins);
  49. //第一个核心操作,后面详细分析    ---------> 1
  50. ret = pinctrl_register_pins(pctldev, pctldesc->pins, pctldesc->npins);
  51. if (ret) {
  52. dev_err(dev, "error during pin registration\n");
  53. pinctrl_free_pindescs(pctldev, pctldesc->pins,
  54. pctldesc->npins);
  55. goto out_err;
  56. }
  57. mutex_lock(&pinctrldev_list_mutex);
  58. //将pctldev加入到全局链表
  59. list_add_tail(&pctldev->node, &pinctrldev_list);
  60. mutex_unlock(&pinctrldev_list_mutex);
  61. //这是第二个核心操作,往往pinctrl设备本身也需要做一些配置,这个函数就是用于处理这个功能---------> 2
  62. pctldev->p = pinctrl_get(pctldev->dev);
  63. if (! IS_ERR(pctldev->p)) {
  64. //如果pinctrl设备提供了default状态,设置为default状态
  65. pctldev->hog_default =
  66. pinctrl_lookup_state(pctldev->p, PINCTRL_STATE_DEFAULT);
  67. if ( IS_ERR(pctldev->hog_default)) {
  68. dev_dbg(dev, "failed to lookup the default state\n");
  69. } else {
  70. //设置为default状态
  71. if ( pinctrl_select_state(pctldev->p,
  72. pctldev->hog_default))
  73. dev_err(dev,
  74. "failed to select default state\n");
  75. }
  76. //如果pinctrl设备提供了sleep状态,获取它,以后再用
  77. pctldev->hog_sleep =
  78. pinctrl_lookup_state(pctldev->p,
  79. PINCTRL_STATE_SLEEP);
  80. if ( IS_ERR(pctldev->hog_sleep))
  81. dev_dbg(dev, "failed to lookup the sleep state\n");
  82. }
  83. //和调试相关,先忽略吧
  84. pinctrl_init_device_debugfs(pctldev);
  85. return pctldev;
  86. out_err:
  87. mutex_destroy(&pctldev->mutex);
  88. kfree(pctldev);
  89. return NULL;
  90. }

总结一下,pinctrl_register主要做了以下工作:

  1. 分配pctldev数据结构,并添加到全局链表pinctrldev_list
  2. 填充pctldev,根据pctldesc里的pin信息注册所有的pin信息到pctldev里的pin_desc_tree管理起来,
  3. 如果该pinctrl对应的设备树里有描述它自己的pin配置信息,那么解析它,并设置为default状态。这一部分是任何一个用到pinctrl设备都会进行的动作(解析、设置状态)
  4. 初始化调试相关的东西

下面先看看pinctrl_register_pins的过程:


   
   
  1. static int pinctrl_register_pins(struct pinctrl_dev *pctldev,
  2. struct pinctrl_pin_desc const *pins,
  3. unsigned num_descs)
  4. {
  5. unsigned i;
  6. int ret = 0;
  7. for (i = 0; i < num_descs; i++) {
  8. //遍历传入的所有pin的数据结构,一个个处理它们
  9. //pinctrl driver会传入所有的pin管脚及对应的名称
  10. ret = pinctrl_register_one_pin(pctldev,
  11. pins[i].number, pins[i].name);
  12. if (ret)
  13. return ret;
  14. }
  15. return 0;
  16. }
  17. static int pinctrl_register_one_pin(struct pinctrl_dev *pctldev,
  18. unsigned number, const char *name)
  19. {
  20. struct pin_desc *pindesc;
  21. //查看是否已经存在了
  22. pindesc = pin_desc_get(pctldev, number);
  23. if (pindesc != NULL) {
  24. pr_err( "pin %d already registered on %s\n", number,
  25. pctldev->desc->name);
  26. return -EINVAL;
  27. }
  28. //分配一个pinctrl子系统用于管理pin的数据结构
  29. pindesc = kzalloc( sizeof(*pindesc), GFP_KERNEL);
  30. if (pindesc == NULL) {
  31. dev_err(pctldev->dev, "failed to alloc struct pin_desc\n");
  32. return -ENOMEM;
  33. }
  34. /* Set owner */
  35. //指定该pin的拥有者
  36. pindesc->pctldev = pctldev;
  37. /* Copy basic pin info */
  38. if (name) {
  39. //如果指定了名字,那么好吧,就用你了
  40. pindesc->name = name;
  41. } else {
  42. //如果没有指定名字,用默认的格式组合一个
  43. pindesc->name = kasprintf(GFP_KERNEL, "PIN%u", number);
  44. if (pindesc->name == NULL) {
  45. kfree(pindesc);
  46. return -ENOMEM;
  47. }
  48. pindesc->dynamic_name = true;
  49. }
  50. //将该pin添加到pctldev里管理起来
  51. radix_tree_insert(&pctldev->pin_desc_tree, number, pindesc);
  52. pr_debug( "registered pin %d (%s) on %s\n",
  53. number, pindesc->name, pctldev->desc->name);
  54. return 0;
  55. }

下面开始分析第二个核心部分pinctrl_get,注意,这部分是任何一个用到pinctrl设备都会进行的动作(解析、设置状态),所以还必须弄清楚它,它主要的作用就是通过解析该设备的pinctrl信息生成一个pinctrl数据结构,用于管理该设备的pin信息,如有哪些状态、每个状态有哪些设置(设置包括pinmux和pinconf两种,有些设备只用需要pinmux,有些需要pinmux和pinconf)


   
   
  1. struct pinctrl * pinctrl_get( struct device *dev)
  2. {
  3. struct pinctrl *p;
  4. if ( WARN_ON(!dev))
  5. return ERR_PTR(-EINVAL);
  6. /*
  7. * See if somebody else (such as the device core) has already
  8. * obtained a handle to the pinctrl for this device. In that case,
  9. * return another pointer to it.
  10. */
  11. //如果已经有其他模块get了,那么pinctrl肯定已经创建好了,直接返回吧
  12. p = find_pinctrl(dev);
  13. if (p != NULL) {
  14. dev_dbg(dev, "obtain a copy of previously claimed pinctrl\n");
  15. kref_get(&p->users);
  16. return p;
  17. }
  18. //否则,创建一个pinctrl用于管理该设备本身的pin信息
  19. return create_pinctrl(dev);
  20. }

继续看解析的过程,通过看懂这部分,我们应该就很清楚设备树里需要怎么配置,怎么对整个系统的pin配置起作用的


   
   
  1. static struct pinctrl * create_pinctrl( struct device *dev)
  2. {
  3. struct pinctrl *p;
  4. const char *devname;
  5. struct pinctrl_maps *maps_node;
  6. int i;
  7. struct pinctrl_map const *map;
  8. int ret;
  9. /*
  10. * create the state cookie holder struct pinctrl for each
  11. * mapping, this is what consumers will get when requesting
  12. * a pin control handle with pinctrl_get()
  13. */
  14. p = kzalloc( sizeof(*p), GFP_KERNEL);
  15. if (p == NULL) {
  16. dev_err(dev, "failed to alloc struct pinctrl\n");
  17. return ERR_PTR(-ENOMEM);
  18. }
  19. p->dev = dev;
  20. //每个需要管理的设备都会有对应的pinctrl,每个设备也会有多个状态,如default、sleep等等(内核
  21. //默认定义了一些,自己也可以随意定义),每个状态又有可能有多种设置。这个需要自己慢慢理解^_^
  22. //这里的states成员就是用于存放所有的状态的
  23. INIT_LIST_HEAD(&p->states);
  24. //这里的dt_maps就是用于存放所有的设置的
  25. INIT_LIST_HEAD(&p->dt_maps);
  26. //又是一个复杂的函数,后面分析,它主要用于解析设备树里的信息,生成该设备对应的maps(设置)
  27. ret = pinctrl_dt_to_map(p);
  28. if (ret < 0) {
  29. kfree(p);
  30. return ERR_PTR(ret);
  31. }
  32. devname = dev_name(dev);
  33. mutex_lock(&pinctrl_maps_mutex);
  34. /* Iterate over the pin control maps to locate the right ones */
  35. //遍历所有的的设置,这里遍历的是全局的maps链表,因为它要用到
  36. //pinctrl_map结构,而p->dt_maps里的不是该类型
  37. for_each_maps(maps_node, i, map) {
  38. /* Map must be for this device */
  39. //检查是否属于俺的设置
  40. if ( strcmp(map->dev_name, devname))
  41. continue;
  42. //将该设置加入到pinctrl中,也许有人会奇怪,前面的dt_maps不是已经包含了该设备的所有设置了么,
  43. //其实这里会对每个设置做进一步处理,然后放入到p中,后面分析
  44. ret = add_setting(p, map);
  45. /*
  46. * At this point the adding of a setting may:
  47. *
  48. * - Defer, if the pinctrl device is not yet available
  49. * - Fail, if the pinctrl device is not yet available,
  50. * AND the setting is a hog. We cannot defer that, since
  51. * the hog will kick in immediately after the device
  52. * is registered.
  53. *
  54. * If the error returned was not -EPROBE_DEFER then we
  55. * accumulate the errors to see if we end up with
  56. * an -EPROBE_DEFER later, as that is the worst case.
  57. */
  58. if (ret == -EPROBE_DEFER) {
  59. pinctrl_free(p, false);
  60. mutex_unlock(&pinctrl_maps_mutex);
  61. return ERR_PTR(ret);
  62. }
  63. }
  64. mutex_unlock(&pinctrl_maps_mutex);
  65. if (ret < 0) {
  66. /* If some other error than deferral occured, return here */
  67. pinctrl_free(p, false);
  68. return ERR_PTR(ret);
  69. }
  70. kref_init(&p->users);
  71. /* Add the pinctrl handle to the global list */
  72. mutex_lock(&pinctrl_list_mutex);
  73. //将每个设备用于控制pin的结构也放到一个全局链表中
  74. list_add_tail(&p->node, &pinctrl_list);
  75. mutex_unlock(&pinctrl_list_mutex);
  76. return p;
  77. }

先总结下create_pinctrl

  1. 创建一个pinctrl,将它加入到全局的pinctrl链表
  2. 解析该设备的说有设备树信息,将解析的状态挂到states里,解析的设置挂到dt_maps(当然,设置同时也挂到全局的maps里去了)

实在不想贴代码了,不过不贴又不好解释清楚_ 继续上pinctrl_dt_to_map吧,它就是实现了上面总结的第二点:


   
   
  1. int pinctrl_dt_to_map(struct pinctrl *p)
  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. for (state = 0; ; state++) {
  23. /* Retrieve the pinctrl-* property */
  24. //pinctrl子系统规定了几个属性,如pinctrl-n,用于指定一个状态对应的设置,从0开始
  25. propname = kasprintf(GFP_KERNEL, "pinctrl-%d", state);
  26. //查找pinctrl-n属性
  27. prop = of_find_property(np, propname, &size);
  28. kfree(propname);
  29. if (!prop)
  30. break;
  31. //value对应的就是该状态对应的设置(可能有多个),后面会处理它
  32. list = prop->value;
  33. size /= sizeof(*list);
  34. /* Determine whether pinctrl-names property names the state */
  35. //读pinctrl-names属性,也属于pinctrl子系统规定的属性,用于指定每个状态的名字,一一对应的
  36. ret = of_property_read_string_index(np, "pinctrl-names",
  37. state, &statename);
  38. /*
  39. * If not, statename is just the integer state ID. But rather
  40. * than dynamically allocate it and have to free it later,
  41. * just point part way into the property name for the string.
  42. */
  43. if (ret < 0) {
  44. /* strlen("pinctrl-") == 8 */
  45. //如果美誉pinctrl-names属性,那么状态名就是index
  46. statename = prop->name + 8;
  47. }
  48. /* For every referenced pin configuration node in it */
  49. //一个一个处理设置
  50. for (config = 0; config < size; config++) {
  51. //第一个成员规定为配置节点(属于pinctrl的子节点)的引用,因此通过它可以找到该配置节点
  52. phandle = be32_to_cpup(list++);
  53. /* Look up the pin configuration node */
  54. np_config = of_find_node_by_phandle(phandle);
  55. if (!np_config) {
  56. dev_err(p->dev,
  57. "prop %s index %i invalid phandle\n",
  58. prop->name, config);
  59. ret = -EINVAL;
  60. goto err;
  61. }
  62. /* Parse the node */
  63. //找到对应的配置节点了,那么就解析那个配置节点到该设备的这个状态的这个设置中吧,后面继续贴 哎
  64. ret = dt_to_map_one_config(p, statename, np_config);
  65. of_node_put(np_config);
  66. if (ret < 0)
  67. goto err;
  68. }
  69. /* No entries in DT? Generate a dummy state table entry */
  70. if (!size) {
  71. ret = dt_remember_dummy_state(p, statename);
  72. if (ret < 0)
  73. goto err;
  74. }
  75. }
  76. return 0;
  77. err:
  78. pinctrl_dt_free_maps(p);
  79. return ret;
  80. }

继续看dt_to_map_one_config


   
   
  1. static int dt_to_map_one_config(struct pinctrl *p, const char *statename,
  2. struct device_node *np_config)
  3. {
  4. struct device_node *np_pctldev;
  5. struct pinctrl_dev *pctldev;
  6. const struct pinctrl_ops *ops;
  7. int ret;
  8. struct pinctrl_map *map;
  9. unsigned num_maps;
  10. /* Find the pin controller containing np_config */
  11. np_pctldev = of_node_get(np_config);
  12. for (;;) {
  13. //找该节点的父节点,就是pinctrl设备啦,我们得通过它获取pctldev,毕竟只有它才有啊
  14. np_pctldev = of_get_next_parent(np_pctldev);
  15. if (!np_pctldev || of_node_is_root(np_pctldev)) {
  16. dev_info(p->dev, "could not find pctldev for node %s, deferring probe\n",
  17. np_config->full_name);
  18. of_node_put(np_pctldev);
  19. /* OK let's just assume this will appear later then */
  20. return -EPROBE_DEFER;
  21. }
  22. pctldev = get_pinctrl_dev_from_of_node(np_pctldev);
  23. if (pctldev) //拿到就跳出
  24. break;
  25. /* Do not defer probing of hogs (circular loop) */
  26. if (np_pctldev == p->dev->of_node) {
  27. of_node_put(np_pctldev);
  28. return -ENODEV;
  29. }
  30. }
  31. of_node_put(np_pctldev);
  32. /*
  33. * Call pinctrl driver to parse device tree node, and
  34. * generate mapping table entries
  35. */
  36. ops = pctldev->desc->pctlops;
  37. //这里就用到了pinctrl_register注册时pctlops里的dt_node_to_map回调函数了
  38. if (!ops->dt_node_to_map) {
  39. dev_err(p->dev, "pctldev %s doesn't support DT\n",
  40. dev_name(pctldev->dev));
  41. return -ENODEV;
  42. }
  43. //调用它,靠它来解析出这个配置节点,毕竟格式只有对应的pinctrl driver最清楚
  44. ret = ops-> dt_node_to_map(pctldev, np_config, &map, &num_maps);
  45. if (ret < 0)
  46. return ret;
  47. /* Stash the mapping table chunk away for later use */
  48. //将解析出来的设置添加到pctldev的dt_maps中,也会加到全局的maps中啦,这里就不再深入分析了,自己都觉得太啰嗦了
  49. return dt_remember_or_free_map(p, statename, pctldev, map, num_maps);
  50. }

继续看add_setting:


   
   
  1. static int add_setting(struct pinctrl *p, struct pinctrl_map const *map)
  2. {
  3. struct pinctrl_state *state;
  4. struct pinctrl_setting *setting;
  5. int ret;
  6. //前面只是解析出了所有的设置,这里就将所有的设置按状态归类起来,如果状态还没创建,就创建一个
  7. state = find_state(p, map->name);
  8. if (!state)
  9. state = create_state(p, map->name);
  10. if ( IS_ERR(state))
  11. return PTR_ERR(state);
  12. if (map->type == PIN_MAP_TYPE_DUMMY_STATE)
  13. return 0;
  14. //分配一个设置数据结构
  15. setting = kzalloc( sizeof(*setting), GFP_KERNEL);
  16. if (setting == NULL) {
  17. dev_err(p->dev,
  18. "failed to alloc struct pinctrl_setting\n");
  19. return -ENOMEM;
  20. }
  21. //设置的类型
  22. setting->type = map->type;
  23. //设置所属的pctldev
  24. setting->pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name);
  25. if (setting->pctldev == NULL) {
  26. kfree(setting);
  27. /* Do not defer probing of hogs (circular loop) */
  28. if (! strcmp(map->ctrl_dev_name, map->dev_name))
  29. return -ENODEV;
  30. /*
  31. * OK let us guess that the driver is not there yet, and
  32. * let's defer obtaining this pinctrl handle to later...
  33. */
  34. dev_info(p->dev, "unknown pinctrl device %s in map entry, deferring probe",
  35. map->ctrl_dev_name);
  36. return -EPROBE_DEFER;
  37. }
  38. //设置名字
  39. setting->dev_name = map->dev_name;
  40. switch (map->type) { //根据设置的类型处理设置,因为设置可以表示mux功能,也可以表示conf功能
  41. case PIN_MAP_TYPE_MUX_GROUP: //如果是mux功能的设置,调用mux模块处理
  42. ret = pinmux_map_to_setting(map, setting);
  43. break;
  44. case PIN_MAP_TYPE_CONFIGS_PIN:
  45. case PIN_MAP_TYPE_CONFIGS_GROUP: //如果是mux功能的设置,调用conf模块处理
  46. ret = pinconf_map_to_setting(map, setting);
  47. break;
  48. default:
  49. ret = -EINVAL;
  50. break;
  51. }
  52. if (ret < 0) {
  53. kfree(setting);
  54. return ret;
  55. }
  56. //将设置放入状态链表归类
  57. list_add_tail(&setting->node, &state->settings);
  58. return 0;
  59. }

下面分别分析pinmux_map_to_settingpinconf_map_to_setting,先pinmux_map_to_setting,它是和pinmux相关,对应pinmux.c文件,里面也会用到pinmux_ops


   
   
  1. int pinmux_map_to_setting(struct pinctrl_map const *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. const char *group;
  10. int i;
  11. //如果在register的时候没有指定pinmux_ops,那么该函数什么都不做,出错返回
  12. if (!pmxops) {
  13. dev_err(pctldev->dev, "does not support mux function\n");
  14. return -EINVAL;
  15. }
  16. //现在就是pinmux_ops作用的时候啦!里面会以从0开始的索引不停的调用
  17. //pinmux_ops里的get_function_name来获取对应的名字,然后和前面解析设备树过程解析出来的名字做匹配
  18. //直到找到或到末尾,返回该索引。这个索引与功能之间的关系由pinctrl bsp实现者负责
  19. ret = pinmux_func_name_to_selector(pctldev, map->data.mux.function);
  20. if (ret < 0) {
  21. dev_err(pctldev->dev, "invalid function %s in map table\n",
  22. map->data.mux.function);
  23. return ret;
  24. }
  25. //保存该索引
  26. setting->data.mux.func = ret;
  27. //调用pmxops的get_function_groups获取该索引对应的组(可能存在多个,前面已经说过,一个功能可以由多个组实现,同一时间只能选一个组)
  28. ret = pmxops-> get_function_groups(pctldev, setting->data.mux.func,
  29. &groups, &num_groups);
  30. if (ret < 0) {
  31. dev_err(pctldev->dev, "can't query groups for function %s\n",
  32. map->data.mux.function);
  33. return ret;
  34. }
  35. if (!num_groups) {
  36. dev_err(pctldev->dev,
  37. "function %s can't be selected on any group\n",
  38. map->data.mux.function);
  39. return -EINVAL;
  40. }
  41. //如果设备树里有直接指定组,那么就会以指定的组为默认选择
  42. if (map->data.mux.group) {
  43. bool found = false;
  44. group = map->data.mux.group;
  45. //当然,也还是要校验下,组是否有效
  46. for (i = 0; i < num_groups; i++) {
  47. if (! strcmp(group, groups[i])) {
  48. found = true;
  49. break;
  50. }
  51. }
  52. if (!found) {
  53. dev_err(pctldev->dev,
  54. "invalid group \"%s\" for function \"%s\"\n",
  55. group, map->data.mux.function);
  56. return -EINVAL;
  57. }
  58. } else {
  59. //如果没有指定,那么就用第一个组咯
  60. group = groups[ 0];
  61. }
  62. //根据选定的组,获取该组的信息,返回的是该组对应的索引,这里会调用pmxops的get_group_name,操作
  63. //过程和前面的pinmux_func_name_to_selector类似
  64. ret = pinctrl_get_group_selector(pctldev, group);
  65. if (ret < 0) {
  66. dev_err(pctldev->dev, "invalid group %s in map table\n",
  67. map->data.mux.group);
  68. return ret;
  69. }
  70. //保存该组索引
  71. setting->data.mux.group = ret;
  72. return 0;
  73. }

继续pinconf_map_to_setting吧,它是和pinconf相关,对应pinconf.c文件,但里面还没用pinconf_ops,后面才会用到:


   
   
  1. int pinconf_map_to_setting(struct pinctrl_map const *map,
  2. struct pinctrl_setting *setting)
  3. {
  4. struct pinctrl_dev *pctldev = setting->pctldev;
  5. int pin;
  6. switch (setting->type) { //该设置到底是什么类型,是pinctrl driver回调dt_node_to_map里解析的
  7. //配置有两种类型,一种是一个pin一个pin的配置,一种是将一些pin的配置组合为一个组,指定某个组就会采用那个组里的所有的pin的配置
  8. case PIN_MAP_TYPE_CONFIGS_PIN:
  9. //根据设备树里指定的pin名字获取它对应的pin号
  10. pin = pin_get_from_name(pctldev,
  11. map->data.configs.group_or_pin);
  12. if (pin < 0) {
  13. dev_err(pctldev->dev, "could not map pin config for \"%s\"",
  14. map->data.configs.group_or_pin);
  15. return pin;
  16. }
  17. //将该设置对应的pin号保存起来
  18. setting->data.configs.group_or_pin = pin;
  19. break;
  20. case PIN_MAP_TYPE_CONFIGS_GROUP:
  21. //根据设备树指定的pin组获取它对应的group号
  22. pin = pinctrl_get_group_selector(pctldev,
  23. map->data.configs.group_or_pin);
  24. if (pin < 0) {
  25. dev_err(pctldev->dev, "could not map group config for \"%s\"",
  26. map->data.configs.group_or_pin);
  27. return pin;
  28. }
  29. //将该设置对应的group号保存起来
  30. setting->data.configs.group_or_pin = pin;
  31. break;
  32. default:
  33. return -EINVAL;
  34. }
  35. //保存所有其他用于配置的信息
  36. setting->data.configs.num_configs = map->data.configs.num_configs;
  37. setting->data.configs.configs = map->data.configs.configs;
  38. return 0;
  39. }

现在都仅仅是分析了pinmux_map_to_settingpinconf_map_to_setting,具体它们的作用我们在后面才能看的出来,所以继续分析吧!到这里pinctrl_get分析完了,执行完pinctrl_get,就意味着该设备的所有和pin相关的设备树信息已经解析完成,并生成了用于管理、配置的数据结构,为以后的其他api提供了支持。其他驱动一般不会直接调用pinctrl_get,而是调用它的变体devm_pinctrl_get或者pinctrl_get_select来初始化设备。devm_pinctrl_get就不用说了啦,pinctrl_get_select类似与pinctrl_register调用pinctrl_get及它后的那段代码的结合,不仅调用了pinctrl_get,还根据输入参数让设备处于指定的状态。通过pinctrl_select_state来让设备处于指定的状态,下面开始分析它,通过分析它,应该就清楚了前面各种填充的作用啦!


   
   
  1. int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)
  2. {
  3. struct pinctrl_setting *setting, *setting2;
  4. struct pinctrl_state *old_state = p->state;
  5. int ret;
  6. //如果当前就是该状态,直接返回成功
  7. if (p->state == state)
  8. return 0;
  9. //如果之前有设置过状态,那需要做一些额外处理
  10. if (p->state) {
  11. /*
  12. * The set of groups with a mux configuration in the old state
  13. * may not be identical to the set of groups with a mux setting
  14. * in the new state. While this might be unusual, it's entirely
  15. * possible for the "user"-supplied mapping table to be written
  16. * that way. For each group that was configured in the old state
  17. * but not in the new state, this code puts that group into a
  18. * safe/disabled state.
  19. */
  20. list_for_each_entry(setting, &p->state->settings, node) {
  21. bool found = false;
  22. if (setting->type != PIN_MAP_TYPE_MUX_GROUP)
  23. continue;
  24. list_for_each_entry(setting2, &state->settings, node) {
  25. if (setting2->type != PIN_MAP_TYPE_MUX_GROUP)
  26. continue;
  27. if (setting2->data.mux.group ==
  28. setting->data.mux.group) {
  29. found = true;
  30. break;
  31. }
  32. }
  33. if (!found)
  34. pinmux_disable_setting(setting);
  35. }
  36. }
  37. p->state = NULL;
  38. /* Apply all the settings for the new state */
  39. //
  40. list_for_each_entry(setting, &state->settings, node) {
  41. //遍历该设备的该状态下的所有设置,一个个设置上去
  42. switch (setting->type) {
  43. case PIN_MAP_TYPE_MUX_GROUP: //如果该设置是mux设置,那么调用pinmux_enable_setting,这里面
  44. //就用到了前面填充的信息
  45. ret = pinmux_enable_setting(setting);
  46. break;
  47. case PIN_MAP_TYPE_CONFIGS_PIN:
  48. case PIN_MAP_TYPE_CONFIGS_GROUP: //如果该设置是conf设置,那么调用pinconf_apply_setting,
  49. //这里面就用到了前面填充的信息
  50. ret = pinconf_apply_setting(setting);
  51. break;
  52. default:
  53. ret = -EINVAL;
  54. break;
  55. }
  56. if (ret < 0) {
  57. goto unapply_new_state;
  58. }
  59. }
  60. p->state = state;
  61. return 0;
  62. unapply_new_state:
  63. dev_err(p->dev, "Error applying setting, reverse things back\n");
  64. list_for_each_entry(setting2, &state->settings, node) {
  65. if (&setting2->node == &setting->node)
  66. break;
  67. /*
  68. * All we can do here is pinmux_disable_setting.
  69. * That means that some pins are muxed differently now
  70. * than they were before applying the setting (We can't
  71. * "unmux a pin"!), but it's not a big deal since the pins
  72. * are free to be muxed by another apply_setting.
  73. */
  74. if (setting2->type == PIN_MAP_TYPE_MUX_GROUP)
  75. pinmux_disable_setting(setting2);
  76. }
  77. /* There's no infinite recursive loop here because p->state is NULL */
  78. if (old_state)
  79. pinctrl_select_state(p, old_state);
  80. return ret;
  81. }

pinmux_enable_setting当然处于pinmux.c中,根据前面填充的setting->data.mux.group获取该组的pin信息,然后以pin号为参数循环回调ops->request,最后回调ops->enable。

pinconf_apply_setting当然处于pinconf.c中,根据前面填充的group_or_pinconfigsnum_configs以及type分别回调pin_config_setpin_config_group_set

最后补充下,本文描述的都是基于设备树方式的pinctrl处理,其实也可以通过pinctrl_register_mappings调用静态添加所有的设置,只是不常用该方式而已。

未完,待续!
2015年7月

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值