- diwali_pinctrl_init
- platform_driver_register(&diwali_pinctrl_driver); //根据match table找到device
- diwali_pinctrl_probe
- pinctrl_data = of_device_get_match_data(&pdev->dev);//获取msm_pinctrl_soc_data
- msm_pinctrl_probe(pdev, pinctrl_data);//传递soc data
- int msm_pinctrl_probe(struct platform_device *pdev,
- const struct msm_pinctrl_soc_data *soc_data)
- {
- // 1)分配一个msm_pinctrl结构并初始化
- msm_pinctrl_data = pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
- if (!pctrl)
- return -ENOMEM;
-
- pctrl->dev = &pdev->dev;
- pctrl->soc = soc_data;
- pctrl->chip = msm_gpio_template;
- pctrl->intr_target_use_scm = of_device_is_compatible(
- pctrl->dev->of_node,
- "qcom,ipq8064-pinctrl");
-
- // 2)从pin controller device dts节点中获取设备的物理地址
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENOENT;
- //将设备的物理地址转换为虚拟地址,使用该地址读写该pin controller device
- pctrl->regs[0] = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(pctrl->regs[0]))
- return PTR_ERR(pctrl->regs[0]);
-
- pctrl->phys_base[0] = res->start;
-
- //3)从pin controller device dts节点中获取irq number
- pctrl->irq = platform_get_irq(pdev, 0);
- if (pctrl->irq < 0)
- return pctrl->irq;
-
- //4) 构造一个pinctrl_desc
- pctrl->desc.owner = THIS_MODULE;
- //引脚枚举与命名
- pctrl->desc.pctlops = &msm_pinctrl_ops;
- //引脚复用
- pctrl->desc.pmxops = &msm_pinmux_ops;
- //引脚配置
- pctrl->desc.confops = &msm_pinconf_ops;
- pctrl->desc.name = dev_name(&pdev->dev);
- //soc data提供
- pctrl->desc.pins = pctrl->soc->pins;
- pctrl->desc.npins = pctrl->soc->npins;
- pctrl->desc.num_custom_params = ARRAY_SIZE(msm_gpio_bindings);
- pctrl->desc.custom_params = msm_gpio_bindings;
-
- //根据pinctrl_desc信息构造一个pinctrl_dev
- pctrl->pctrl = devm_pinctrl_register(&pdev->dev, &pctrl->desc, pctrl);
- if (IS_ERR(pctrl->pctrl)) {
- dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
- return PTR_ERR(pctrl->pctrl);
- }
-
- //5)
- ret = msm_gpio_init(pctrl);
- if (ret)
- return ret;
-
- platform_set_drvdata(pdev, pctrl);
- }
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
- static const struct pinctrl_ops msm_pinctrl_ops = {
- .get_groups_count = msm_get_groups_count,
- .get_group_name = msm_get_group_name,
- .get_group_pins = msm_get_group_pins,
- .dt_node_to_map = pinconf_generic_dt_node_to_map_group,
- .dt_free_map = pinctrl_utils_free_map,
- };
2)struct pinmux_ops
- static const struct pinmux_ops msm_pinmux_ops = {
- .request = msm_pinmux_request,
- .get_functions_count = msm_get_functions_count,
- .get_function_name = msm_get_function_name,
- .get_function_groups = msm_get_function_groups,
- .gpio_request_enable = msm_pinmux_request_gpio,
- .set_mux = msm_pinmux_set_mux,
- };
3)struct pinconf_ops
- static const struct pinconf_ops msm_pinconf_ops = {
- .is_generic = true,
- .pin_config_group_get = msm_config_group_get,
- .pin_config_group_set = msm_config_group_set,
- };
- pctrl->pctrl = devm_pinctrl_register(&pdev->dev, &pctrl->desc, pctrl);
- pctldev = pinctrl_register(pctldesc, dev, driver_data);
- pinctrl_init_controller(pctldesc, dev, driver_data);
- //给pinctrl_dev分配内存
- pctldev = kzalloc(sizeof(*pctldev), GFP_KERNEL);
- // driver_data是msm_pinctrl
- pctldev->driver_data = driver_data;
- //check core ops for sanity
- pinctrl_check_ops(pctldev);
- //If we're implementing pinmuxing, check the ops for sanity
- pinmux_check_ops(pctldev);
- //If we're implementing pinconfig, check the ops for sanity
- pinconf_check_ops(pctldev);
- pinctrl_register_pins(pctldev, pctldesc->pins, pctldesc->npins);
- pinctrl_enable(pctldev);
- //将pinctrl_dev加入pinctrldev_list链表
- list_add_tail(&pctldev->node, &pinctrldev_list);
- //在每一个pin controller device的目录中生成pinctrl调试节点,eg:/sys/kernel/debug/pinctrl/f000000.pinctrl
- pinctrl_init_device_debugfs(pctldev);
- debugfs_create_file("pins", S_IFREG | S_IRUGO, device_root, pctldev, &pinctrl_pins_fops);
- debugfs_create_file("pingroups", S_IFREG | S_IRUGO, device_root, pctldev, &pinctrl_groups_fops);
- debugfs_create_file("gpio-ranges", S_IFREG | S_IRUGO, device_root, pctldev, &pinctrl_gpioranges_fops);
设备节点要么被转换为platform_device,或者其他结构体(比如i2c_client),但是里面都会有一个device结构体,每个device结构体里都有一个dev_pin_info结构体,用来保存设备的pinctrl信息。
platform_device匹配driver会执行probe探测函数,执行到驱动中真正的probe函数之前,会进行pinctrl的处理,处理函数为pinctrl_bind_pins。
- really_probe()
- pinctrl_bind_pins(dev);
- devm_pinctrl_get(dev);
- pinctrl_get(dev);
- create_pinctrl(dev, NULL);
- //把dts中该设备的pinctrl配置解析到pinctrl map中
- pinctrl_dt_to_map(p, pctldev);
- dt_to_map_one_config(p, pctldev, statename, np_config);
- ops->dt_node_to_map(pctldev, np_config, &map, &num_maps);
- .dt_node_to_map = pinconf_generic_dt_node_to_map_group,
- pinconf_generic_dt_node_to_map
- //pinctrl map mux
- pinctrl_utils_add_map_mux
- //pinctrl map configs
- pinctrl_utils_add_map_configs
-
- //把pinctrl map 转为pinctrl setting
- add_setting(p, pctldev, map);
- pinmux_map_to_setting(map, setting);
- pinconf_map_to_setting(map, setting);
- list_add_tail(&setting->node, &state->settings);
-
- //该设备的pinctrl state holder挂到pinctrl_list链表
- list_add_tail(&p->node, &pinctrl_list);
-
- //解析标准的pinctrl state,PINCTRL_STATE_DEFAULT/PINCTRL_STATE_INIT/PINCTRL_STATE_SLEEP/PINCTRL_STATE_IDLE
- dev->pins->default_state = pinctrl_lookup_state(dev->pins->p, PINCTRL_STATE_DEFAULT);
- dev->pins->init_state = pinctrl_lookup_state(dev->pins->p, PINCTRL_STATE_INIT);
- pinctrl_select_state(dev->pins->p, dev->pins->default_state);
-
- dev->pins->sleep_state = pinctrl_lookup_state(dev->pins->p, PINCTRL_STATE_SLEEP);
- dev->pins->idle_state = pinctrl_lookup_state(dev->pins->p, PINCTRL_STATE_IDLE);
-
- //执行device或者driver的probe函数
- dev->bus->probe(dev);
- drv->probe(dev);
- ls -l /sys/kernel/debug/pinctrl/f000000.pinctrl
- -r--r--r-- 1 root root 0 1970-01-01 00:00 gpio-ranges
- -r--r--r-- 1 root root 0 1970-01-01 00:00 pinconf-groups
- -r--r--r-- 1 root root 0 1970-01-01 00:00 pinconf-pins
- -r--r--r-- 1 root root 0 1970-01-01 00:00 pingroups
- -r--r--r-- 1 root root 0 1970-01-01 00:00 pinmux-functions
- -r--r--r-- 1 root root 0 1970-01-01 00:00 pinmux-pins
- -r--r--r-- 1 root root 0 1970-01-01 00:00 pins
系统中注册的所有的pinctrl controller,打印接口:
- static int pinctrl_devices_show(struct seq_file *s, void *what)
- {
- struct pinctrl_dev *pctldev;
-
- seq_puts(s, "name [pinmux] [pinconf]\n");
-
- mutex_lock(&pinctrldev_list_mutex);
-
- list_for_each_entry(pctldev, &pinctrldev_list, node) {
- seq_printf(s, "%s ", pctldev->desc->name);
- if (pctldev->desc->pmxops)
- seq_puts(s, "yes ");
- else
- seq_puts(s, "no ");
- if (pctldev->desc->confops)
- seq_puts(s, "yes");
- else
- seq_puts(s, "no");
- seq_puts(s, "\n");
- }
-
- mutex_unlock(&pinctrldev_list_mutex);
-
- return 0;
- }
- DEFINE_SHOW_ATTRIBUTE(pinctrl_devices);
cat /sys/kernel/debug/pinctrl/pinctrl-devices:
- name [pinmux] [pinconf]
- f000000.pinctrl yes yes
- c42d000.qcom,spmi:qcom,pmk8350@0:pinctrl@b000 yes yes
- c42d000.qcom,spmi:qcom,pm8350c@2:pinctrl@8800 yes yes
- c42d000.qcom,spmi:qcom,pm7325@1:pinctrl@8800 yes yes
- c42d000.qcom,spmi:qcom,pm8350b@3:pinctrl@8800 yes yes
- soc:spf_core_platform:lpi_pinctrl@3440000 yes yes
- static int pinctrl_maps_show(struct seq_file *s, void *what)
- {
- struct pinctrl_maps *maps_node;
- int i;
- const struct pinctrl_map *map;
-
- seq_puts(s, "Pinctrl maps:\n");
-
- mutex_lock(&pinctrl_maps_mutex);
- for_each_maps(maps_node, i, map) {
- seq_printf(s, "device %s\nstate %s\ntype %s (%d)\n",
- map->dev_name, map->name, map_type(map->type),
- map->type);
-
- if (map->type != PIN_MAP_TYPE_DUMMY_STATE)
- seq_printf(s, "controlling device %s\n",
- map->ctrl_dev_name);
-
- switch (map->type) {
- case PIN_MAP_TYPE_MUX_GROUP:
- pinmux_show_map(s, map);
- break;
- case PIN_MAP_TYPE_CONFIGS_PIN:
- case PIN_MAP_TYPE_CONFIGS_GROUP:
- pinconf_show_map(s, map);
- break;
- default:
- break;
- }
-
- seq_putc(s, '\n');
- }
- mutex_unlock(&pinctrl_maps_mutex);
-
- return 0;
- }
- DEFINE_SHOW_ATTRIBUTE(pinctrl_maps);
pinctrl client 节点举例:
- //一个device的pinctrl state配置
- xxx@xx {
- pinctrl-names = "pmx_ts_active", "pmx_ts_suspend", "pmx_ts_release";
- pinctrl-0 = <&ts_active>;
- pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
- pinctrl-2 = <&ts_release>;
- };
pinctrl server 端的配置见上一篇文章,解析后的pinctrl maps信息:
cat /sys/kernel/debug/pinctrl/pinctrl-maps
- device spi1.0
- state pmx_ts_active
- type MUX_GROUP (2)
- controlling device f000000.pinctrl
- group gpio129
- function gpio
- device spi1.0
- state pmx_ts_active
- type MUX_GROUP (2)
- controlling device f000000.pinctrl
- group gpio51
- function gpio
- device spi1.0
- state pmx_ts_active
- type CONFIGS_GROUP (4)
- controlling device f000000.pinctrl
- group gpio129
- config 00000105
- config 00000809
- device spi1.0
- state pmx_ts_active
- type CONFIGS_GROUP (4)
- controlling device f000000.pinctrl
- group gpio51
- config 00000105
- config 00000809
- device spi1.0
- state pmx_ts_suspend
- type MUX_GROUP (2)
- controlling device f000000.pinctrl
- group gpio51
- function gpio
- device spi1.0
- state pmx_ts_suspend
- type CONFIGS_GROUP (4)
- controlling device f000000.pinctrl
- group gpio51
- config 00000103
- config 00000209
- device spi1.0
- state pmx_ts_suspend
- type MUX_GROUP (2)
- controlling device f000000.pinctrl
- group gpio129
- function gpio
- device spi1.0
- state pmx_ts_suspend
- type CONFIGS_GROUP (4)
- controlling device f000000.pinctrl
- group gpio129
- config 00000103
- config 00000209
- device spi1.0
- state pmx_ts_release
- type MUX_GROUP (2)
- controlling device f000000.pinctrl
- group gpio129
- function gpio
- device spi1.0
- state pmx_ts_release
- type MUX_GROUP (2)
- controlling device f000000.pinctrl
- group gpio51
- function gpio
- device spi1.0
- state pmx_ts_release
- type CONFIGS_GROUP (4)
- controlling device f000000.pinctrl
- group gpio129
- config 00000001
- config 00000209
- device spi1.0
- state pmx_ts_release
- type CONFIGS_GROUP (4)
- controlling device f000000.pinctrl
- group gpio51
- config 00000001
- config 00000209
- static int pinctrl_show(struct seq_file *s, void *what)
- {
- struct pinctrl *p;
- struct pinctrl_state *state;
- struct pinctrl_setting *setting;
-
- seq_puts(s, "Requested pin control handlers their pinmux maps:\n");
-
- mutex_lock(&pinctrl_list_mutex);
-
- list_for_each_entry(p, &pinctrl_list, node) {
- seq_printf(s, "device: %s current state: %s\n",
- dev_name(p->dev),
- p->state ? p->state->name : "none");
-
- list_for_each_entry(state, &p->states, node) {
- seq_printf(s, " state: %s\n", state->name);
-
- list_for_each_entry(setting, &state->settings, node) {
- struct pinctrl_dev *pctldev = setting->pctldev;
-
- seq_printf(s, " type: %s controller %s ",
- map_type(setting->type),
- pinctrl_dev_get_name(pctldev));
-
- switch (setting->type) {
- case PIN_MAP_TYPE_MUX_GROUP:
- pinmux_show_setting(s, setting);
- break;
- case PIN_MAP_TYPE_CONFIGS_PIN:
- case PIN_MAP_TYPE_CONFIGS_GROUP:
- pinconf_show_setting(s, setting);
- break;
- default:
- break;
- }
- }
- }
- }
-
- mutex_unlock(&pinctrl_list_mutex);
-
- return 0;
- }
- DEFINE_SHOW_ATTRIBUTE(pinctrl);
上一节pinctrl maps转成的pinctrl settings信息打印:
cat /sys/kernel/debug/pinctrl/pinctrl-handles
- device: spi1.0 current state: pmx_ts_active
-
- state: pmx_ts_active
- type: MUX_GROUP controller f000000.pinctrl group: gpio129 (129) function: gpio (0)
- type: MUX_GROUP controller f000000.pinctrl group: gpio51 (51) function: gpio (0)
- type: CONFIGS_GROUP controller f000000.pinctrl group gpio129 (129)config 00000105
- config 00000809
- type: CONFIGS_GROUP controller f000000.pinctrl group gpio51 (51)config 00000105
- config 00000809
- state: pmx_ts_suspend
- type: MUX_GROUP controller f000000.pinctrl group: gpio51 (51) function: gpio (0)
- type: CONFIGS_GROUP controller f000000.pinctrl group gpio51 (51)config 00000103
- config 00000209
- type: MUX_GROUP controller f000000.pinctrl group: gpio129 (129) function: gpio (0)
- type: CONFIGS_GROUP controller f000000.pinctrl group gpio129 (129)config 00000103
- config 00000209
- state: pmx_ts_release
- type: MUX_GROUP controller f000000.pinctrl group: gpio129 (129) function: gpio (0)
- type: MUX_GROUP controller f000000.pinctrl group: gpio51 (51) function: gpio (0)
- type: CONFIGS_GROUP controller f000000.pinctrl group gpio129 (129)config 00000001
- config 00000209
- type: CONFIGS_GROUP controller f000000.pinctrl group gpio51 (51)config 00000001
- config 00000209
pinctrl_dt_to_map:
- int pinctrl_dt_to_map(struct pinctrl *p, struct pinctrl_dev *pctldev)
- {
- struct device_node *np = p->dev->of_node;
- int state, ret;
- char *propname;
- struct property *prop;
- const char *statename;
- const __be32 *list;
- int size, config;
- phandle phandle;
- struct device_node *np_config;
-
- /* CONFIG_OF enabled, p->dev not instantiated from DT */
- if (!np) {
- if (of_have_populated_dt())
- dev_dbg(p->dev,
- "no of_node; not parsing pinctrl DT\n");
- return 0;
- }
-
- /* We may store pointers to property names within the node */
- of_node_get(np);
-
- /* For each defined state ID */
- //遍历所有的state ID
- for (state = 0; ; state++) {
- /* Retrieve the pinctrl-* property */
- propname = kasprintf(GFP_KERNEL, "pinctrl-%d", state);
- if (!propname)
- return -ENOMEM;
- prop = of_find_property(np, propname, &size);
- kfree(propname);
- if (!prop) {
- if (state == 0) {
- of_node_put(np);
- return -ENODEV;
- }
- break;
- }
- list = prop->value;
- //一个state对应的config的数量
- size /= sizeof(*list);
-
- /* Determine whether pinctrl-names property names the state */
- //从pinctrl-names中获取statename
- ret = of_property_read_string_index(np, "pinctrl-names",
- state, &statename);
- /*
- * If not, statename is just the integer state ID. But rather
- * than dynamically allocate it and have to free it later,
- * just point part way into the property name for the string.
- */
- if (ret < 0)
- statename = prop->name + strlen("pinctrl-");
-
- /* For every referenced pin configuration node in it */
- //遍历每一个state下面的每一个config
- for (config = 0; config < size; config++) {
- phandle = be32_to_cpup(list++);
-
- /* Look up the pin configuration node */
- np_config = of_find_node_by_phandle(phandle);
- if (!np_config) {
- dev_err(p->dev,
- "prop %s index %i invalid phandle\n",
- prop->name, config);
- ret = -EINVAL;
- goto err;
- }
-
- /* Parse the node */
- //对于一个config节点的解析函数
- ret = dt_to_map_one_config(p, pctldev, statename,
- np_config);
- of_node_put(np_config);
- if (ret < 0)
- goto err;
- }
-
- /* No entries in DT? Generate a dummy state table entry */
- if (!size) {
- ret = dt_remember_dummy_state(p, statename);
- if (ret < 0)
- goto err;
- }
- }
-
- return 0;
-
- err:
- pinctrl_dt_free_maps(p);
- return ret;
- }
dt_to_map_one_config:
- static int dt_to_map_one_config(struct pinctrl *p,
- struct pinctrl_dev *hog_pctldev,
- const char *statename,
- struct device_node *np_config)
- {
- struct pinctrl_dev *pctldev = NULL;
- struct device_node *np_pctldev;
- const struct pinctrl_ops *ops;
- int ret;
- struct pinctrl_map *map;
- unsigned num_maps;
- bool allow_default = false;
-
- /* Find the pin controller containing np_config */
- np_pctldev = of_node_get(np_config);
- for (;;) {
- //找到pctldev
- pctldev = get_pinctrl_dev_from_of_node(np_pctldev);
- }
- of_node_put(np_pctldev);
-
- /*
- * Call pinctrl driver to parse device tree node, and
- * generate mapping table entries
- */
- ops = pctldev->desc->pctlops;
- if (!ops->dt_node_to_map) {
- dev_err(p->dev, "pctldev %s doesn't support DT\n",
- dev_name(pctldev->dev));
- return -ENODEV;
- }
-
- //调用pinctrl driver中实现的dt_node_to_map
- ret = ops->dt_node_to_map(pctldev, np_config, &map, &num_maps);
-
- /* Stash the mapping table chunk away for later use */
- //保存解析出来的pinctrl maps
- return dt_remember_or_free_map(p, statename, pctldev, map, num_maps);
- }
保存解析出来的pinctrl maps,pinctrldt_remember_or_free_map:
- dt_remember_or_free_map
- list_add_tail(&dt_map->node, &p->dt_maps);
- pinctrl_register_mappings(map, num_maps);
- list_add_tail(&maps_node->node, &pinctrl_maps);
- mutex_lock(&pinctrl_maps_mutex);
- /* Iterate over the pin control maps to locate the right ones */
- //取出pinctrl_maps链表中的每一个node,遍历每一个node中的&_maps_node_->maps[_i_] (指向struct pinctrl_map的map指针)
- for_each_maps(maps_node, i, map) {
- /* Map must be for this device */
- if (strcmp(map->dev_name, devname))
- continue;
- /*
- * If pctldev is not null, we are claiming hog for it,
- * that means, setting that is served by pctldev by itself.
- *
- * Thus we must skip map that is for this device but is served
- * by other device.
- */
- if (pctldev &&
- strcmp(dev_name(pctldev->dev), map->ctrl_dev_name))
- continue;
-
- //一个map转为一个setting
- ret = add_setting(p, pctldev, map);
- /*
- * At this point the adding of a setting may:
- *
- * - Defer, if the pinctrl device is not yet available
- * - Fail, if the pinctrl device is not yet available,
- * AND the setting is a hog. We cannot defer that, since
- * the hog will kick in immediately after the device
- * is registered.
- *
- * If the error returned was not -EPROBE_DEFER then we
- * accumulate the errors to see if we end up with
- * an -EPROBE_DEFER later, as that is the worst case.
- */
- if (ret == -EPROBE_DEFER) {
- pinctrl_free(p, false);
- mutex_unlock(&pinctrl_maps_mutex);
- return ERR_PTR(ret);
- }
- }
- mutex_unlock(&pinctrl_maps_mutex);
add_setting:
- static int add_setting(struct pinctrl *p, struct pinctrl_dev *pctldev,
- const struct pinctrl_map *map)
- {
- struct pinctrl_state *state;
- struct pinctrl_setting *setting;
- int ret;
-
- //首先在struct pinctrl结构体中查找该state是否存在,list_for_each_entry(state, &p->states, node)
- state = find_state(p, map->name);
- if (!state)
- //如果state不存在就新建一个state,list_add_tail(&state->node, &p->states);
- state = create_state(p, map->name);
- if (IS_ERR(state))
- return PTR_ERR(state);
-
- if (map->type == PIN_MAP_TYPE_DUMMY_STATE)
- return 0;
-
- //给struct pinctrl_setting分配内存空间
- setting = kzalloc(sizeof(*setting), GFP_KERNEL);
- if (!setting)
- return -ENOMEM;
-
- //初始化setting结构体
- setting->type = map->type;
-
- if (pctldev)
- setting->pctldev = pctldev;
- else
- setting->pctldev =
- get_pinctrl_dev_from_devname(map->ctrl_dev_name);
- if (!setting->pctldev) {
- kfree(setting);
- /* Do not defer probing of hogs (circular loop) */
- if (!strcmp(map->ctrl_dev_name, map->dev_name))
- return -ENODEV;
- /*
- * OK let us guess that the driver is not there yet, and
- * let's defer obtaining this pinctrl handle to later...
- */
- dev_info(p->dev, "unknown pinctrl device %s in map entry, deferring probe",
- map->ctrl_dev_name);
- return -EPROBE_DEFER;
- }
-
- setting->dev_name = map->dev_name;
-
- switch (map->type) {
- case PIN_MAP_TYPE_MUX_GROUP:
- //pinmux map to setting
- ret = pinmux_map_to_setting(map, setting);
- break;
- case PIN_MAP_TYPE_CONFIGS_PIN:
- case PIN_MAP_TYPE_CONFIGS_GROUP:
- //pin configure map to setting
- ret = pinconf_map_to_setting(map, setting);
- break;
- default:
- ret = -EINVAL;
- break;
- }
- if (ret < 0) {
- kfree(setting);
- return ret;
- }
-
- //将转化后的setting挂到state->settings链表
- list_add_tail(&setting->node, &state->settings);
-
- return 0;
- }
pinmux_map_to_setting:
- int pinmux_map_to_setting(const struct pinctrl_map *map,
- struct pinctrl_setting *setting)
- {
- struct pinctrl_dev *pctldev = setting->pctldev;
- const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
- char const * const *groups;
- unsigned num_groups;
- int ret;
-
- ret = pinmux_func_name_to_selector(pctldev, map->data.mux.function);
- setting->data.mux.func = ret;
-
-
- ret = pmxops->get_function_groups(pctldev, setting->data.mux.func,
- &groups, &num_groups);
- if (ret < 0) {
- dev_err(pctldev->dev, "can't query groups for function %s\n",
- map->data.mux.function);
- return ret;
- }
-
- ret = pinctrl_get_group_selector(pctldev, group);
- if (ret < 0) {
- dev_err(pctldev->dev, "invalid group %s in map table\n",
- map->data.mux.group);
- return ret;
- }
- setting->data.mux.group = ret;
-
- return 0;
- }
map 到 setting的转化只是将字符串转为整型数表示的形式。
- really_probe
- pinctrl_bind_pins
- /* 寻找state */
- pinctrl_lookup_state
- /* 选择state */
- pinctrl_select_state
- pinctrl_commit_state
- /* 遍历settings链表 */
- list_for_each_entry(setting, &state->settings, node) {
- switch (setting->type) {
- case PIN_MAP_TYPE_MUX_GROUP:
- /* 设置复用 */
- pinmux_enable_setting(setting);
- ops->set_mux(...);
- case PIN_MAP_TYPE_CONFIGS_PIN:
- case PIN_MAP_TYPE_CONFIGS_GROUP:
- /* 设置配置 */
- pinconf_apply_setting(setting);
- ops->pin_config_group_set(...);
- }
参考链接: