pinctrl子系统

  • 1. Pinctrl引入
    • 1.1 Pinctrl作用
    • 1.2 Pinctrl重要概念
  • 2. Pinctrl子系统主要数据结构
    • 2.1 设备树
      • 2.1.1 理想模型
      • 2.1.2 实际例子
    • 2.2 pincontroller的数据结构
      • 2.2.1 pinctrl_desc和pinctrl_dev
        • 1. 结构体引入
        • 2. 作用1:描述、获取、解析引脚
        • 3. 作用2:引脚复用
        • 4. 作用3:引脚配置
        • 5. 使用pinctrl_desc注册得到pinctrl_dev
    • 2.3 client的数据结构
      • 2.3.1 device结构体
      • 2.3.2 dev_pin_info、pinctrl、pinctrl_map和pinctrl_setting
  • 3. Pincontroller构造过程情景分析
    • 3.1 设备树节点
    • 3.2 驱动代码执行流程
    • 3.3 作用1:描述、获取、解析引脚
      • 3.3.1 单个引脚
      • 3.3.2 某组引脚
      • 3.3.3 设备树节点解析 - 节点转换为pinctrl-map
    • 3.4 作用2:引脚复用、配置
      • 3.4.1 引脚复用
      • 3.4.2 引脚配置
  • 4. client端使用pinctrl过程的情景分析
    • 4.1 设备树节点
    • 4.2 client节点如何使用pinctrl
      • 4.2.1 client节点如何构造pinctrl
        • 1. 设备树节点转换为pinctrl_map
        • 2. pinctrl_map转换为pinctrl_setting
      • 4.2.2 client节点如何使用设置管脚
        • 1. 复用设置
        • 2. 配置设置
  • 5. 海思平台上编写Pinctrl驱动程序
    • 5.1 设备树
    • 5.2 驱动代码
      • 5.2.1 pincontroller端
      • 5.2.2 client device端
    • 5.3 使用debugfs调试

转载自:

Pinctrl子系统

1. Pinctrl引入

参考资料:

  • Linux 5.x内核文档

    • Documentation\devicetree\bindings\pinctrl\pinctrl-bindings.txt
  • Linux 4.x内核文档
    • Documentation\pinctrl.txt
    • Documentation\devicetree\bindings\pinctrl\pinctrl-bindings.txt

1.1 Pinctrl作用

无论是哪种芯片,都有类似下图的结构:

想要pinA、B用于GPIO,需要设置IOMUX让它们连接到GPIO模块;要想让pinA、B用于I2C,需要设置IOMUX让它们连接到I2C模块,这里GPIO、I2C应该是并列的关系,它们能够使用之前,需要设置复用关系IOMUX,有时还要配置引脚,比如上拉、下拉、开漏等等。现在芯片一般动辄几百个引脚,在使用到GPIO、I2C等功能时,若一个引脚一个引脚去找对应的寄存器进行配置非常浪费时间和精力,所以内核引入了Pinctrl子系统,把引脚的复用和配置抽象出来,只需要芯片厂商把自家芯片的支持进去,就可以很方便的配置引脚。

Pinctrl:Pin Controller,顾名思义,就是用来控制引脚的:

  • 引脚枚举与命名(Enumerating and naming)
  • 引脚复用(Multiplexing):比如用作GPIO、I2C或其他功能
  • 引脚配置(Configuration):比如上拉、下拉、开漏、驱动强度等

1.2 Pinctrl重要概念

从设备树开始学习Pinctrl会比较容易。参考内核Documentation\devicetree\bindings\pinctrl\pinctrl-bindings.txt,Pinctrl子系统涉及2个对象:Pin controller devices、Pinctrl client devices

  • Pin controller devices:提供服务,可以用它来复用引脚、配置引脚,是一个软件上的概念。
    注意:Pin controller和GPIO Controller不同,前者控制的引脚可用于GPIO功能、I2C功能;后者只是把引脚配置为输入、输出等简单的功能。两者的关系是先用Pin controller把引脚配置为GPIO,再用GPIO Controler把引脚配置为输入或输出。
  • Pinctrl client devices:使用服务,Pinctrl系统的客户,即使用Pinctrl系统的设备。声明自己要使用哪些引脚的哪些功能,怎么配置它们。

在设备树中,上述两个对象被定义成两个节点,如下图所示。左边是Pin controller节点,右边是client device节点:

a. Pin state:对于一个client device来说,比如他是一个UART设备,它有多个“状态”:default、sleep等,那对应的引脚也有这些状态。比如默认状态下,UART设备是工作的,那么所用的引脚就要复用为UART功能。在休眠状态下,为了省电,可以把这些引脚复用为GPIO功能,或者直接把它们配置输出高电平。上图中,pinctrl-names属性里定义了2种状态:default、sleep。
第0种状态用到的引脚在pinctrl-0中定义,它是state_0_node_a,位于Pincontroller节点中。 第1种状态用到的引脚在pinctrl-1中定义,它是state_1_node_a,位于pincontroller节点中。
当这个设备处于default状态时,pinctrl子系统会自动根据上述信息把所用引脚复用为uart0功能。
当这个设备处于sleep状态时,pinctrl子系统会自动根据上述信息把所用引脚配置为高电平。
b. groups、function和pins:一个设备会用到一个或多个引脚pin,这些引脚就可以归为一组group,复用为某个功能function;当然:一个设备可以用到多组引脚,比如A1、A2两组引脚,A1组复用为F1功能,A2组复用为F2功能。

c. pin multiplexing node和pin configuration node:在上图Pin controller节点中,有子节点或孙节点,它们是给client device使用的。
可以用来描述复用信息:哪组(group)引脚复用为哪个功能(function);
可以用来描述配置信息:哪组(group)引脚配置为哪个设置功能(setting),比如上拉、下拉等。
注意:Pin controller节点的格式,没有统一的标准!!!!每家芯片都不一样,甚至上面的group、function关键字也不一定有,但是概念是有的。而client device节点的格式是统一的。


这是由于怎么去解析Pincontroller节点下的子节点完全是有芯片厂商决定,内核Pinctrl驱动框架只定义了解析节点的接口而已,而Client端是由内核代码统一管理的。

2. Pinctrl子系统主要数据结构

参考资料

  • pincontroller数据结构

    • drivers\pinctrl\core.h
    • include\linux\pinctrl\pinctrl.h
    • include\linux\pinctrl\pinmux.h
    • include\linux\pinctrl\pinconf.h
  • client数据结构
    • drivers\pinctrl\core.h
    • include\linux\pinctrl\devinfo.h
    • include\linux\device.h
    • include\linux\pinctrl\machine.h

2.1 设备树

2.1.1 理想模型

2.1.2 实际例子

  • IMX6ULL

  • fy00

2.2 pincontroller的数据结构

记住pinctrl的三大作用,有助于理解所涉及的数据结构:

  • 引脚枚举与命名(Enumerating and naming)
  • 引脚复用(Multiplexing):比如用作GPIO、I2C或其他功能
  • 引脚配置(Configuration):比如上拉、下来、open drain、驱动强度等

2.2.1 pinctrl_desc和pinctrl_dev

1. 结构体引入

Pincontroller虽然是一个软件P的概念,但是它背后是有硬件支持的,所以可以使用一个结构体来表示它:pinctrl_dev

怎么构造出pinctrl_dev?我们只需要描述它:提供一个pinctrl_desc,然后调用pinctrl_register就可以:

struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,struct device *dev, void *driver_data);

怎么使用pinctrl_desc、pinctrl_dev来描述一个pin controller?这两个结构体定义如下

pinctrl_desc示例如下:

  • pinctrl_pin_desc:描述引脚
  • pinctrl_ops:引脚控制操作,用来获取某组引脚,解析设备树节点创建映射
  • pinmux_ops:复用操作
  • pinconf_ops:配置操作

2. 作用1:描述、获取、解析引脚

使用结构体pinctrl_pin_desc来描述一个引脚,一个pin controller有多个引脚:

/*** struct pinctrl_pin_desc - boards/machines provide information on their*/
struct pinctrl_pin_desc {unsigned number;     //引脚序号const char *name;    //引脚名void *drv_data;
};

使用pinctrl_ops来操作引脚,主要功能如下:

/*** struct pinctrl_ops - global pin control operations, to be implemented by* pin controller drivers.*/
struct pinctrl_ops {//获取组数int (*get_groups_count) ();//获取组名const char *(*get_group_name) ();//获取某组的引脚int (*get_group_pins) ();//用以debugfs提供每个引脚的信息void (*pin_dbg_show) ();//解析设备树节点,转换成pinctrl_map,重点int (*dt_node_to_map) ();//释放mapvoid (*dt_free_map) ();
};
  • 来取出某组的引脚:get_groups_count、get_group_pins
  • 处理设备树中pin controller中的某个节点创建映射:dt_node_to_map,把device_node转换为一系列的pinctrl_map

3. 作用2:引脚复用

/*** struct pinmux_ops - pinmux operations, to be implemented by pin controller* drivers that support pinmuxing*/
struct pinmux_ops {int (*request) ();int (*free) ();//获取func数量int (*get_functions_count) ();//获取func名const char *(*get_function_name) ();//获取func下的组int (*get_function_groups) ();//设置复用int (*set_mux) ();int (*gpio_request_enable) ();void (*gpio_disable_free) ();int (*gpio_set_direction) ();bool strict;
};

4. 作用3:引脚配置

struct pinconf_ops {
#ifdef CONFIG_GENERIC_PINCONFbool is_generic;
#endif//获取单个引脚配置int (*pin_config_get) ();//配置单个引脚int (*pin_config_set) ();//获取某组引脚配置int (*pin_config_group_get) ();//配置某组引脚int (*pin_config_group_set) ();//用以debugfs修改pin配置信息int (*pin_config_dbg_parse_modify) ();//用以debugfs提供pin配置信息void (*pin_config_dbg_show) ();//用以debugfs提供group配置信息void (*pin_config_group_dbg_show) ();//用以debugfs解析并显示pin的配置void (*pin_config_config_dbg_show) (s);
};

5. 使用pinctrl_desc注册得到pinctrl_dev

调用devm_pinctrl_register或pinctrl_register,就可以根据pinctrl_desc构造出pinctrl_dev,并且把pinctrl_dev放入链表:

devm_pinctrl_registerpinctrl_registerstruct pinctrl_dev *pctldev;pctldev = kzalloc(sizeof(*pctldev), GFP_KERNEL);pctldev->owner = pctldesc->owner;pctldev->desc = pctldesc;pctldev->driver_data = driver_data;/* check core ops for sanity 校验关键函数是否被定义*/ret = pinctrl_check_ops(pctldev);/* If we're implementing pinmuxing, check the ops for sanity */ret = pinmux_check_ops(pctldev);/* If we're implementing pinconfig, check the ops for sanity */ret = pinconf_check_ops(pctldev);/* Register all the pins 注册所有的引脚*/ret = pinctrl_register_pins(pctldev, pctldesc->pins, pctldesc->npins);/* 加入链表 */list_add_tail(&pctldev->node, &pinctrldev_list);

2.3 client的数据结构

在设备树中,使用pinctrl时格式如下:

/* For a client device requiring named states */
device {pinctrl-names = "active", "idle";pinctrl-0 = <&state_0_node_a>;pinctrl-1 = <&state_1_node_a &state_1_node_b>;
};

2.3.1 device结构体

设备节点要么被转换为platform_device,或者其他结构体(比如i2c_client),但是里面都会有一个device结构体:

2.3.2 dev_pin_info、pinctrl、pinctrl_map和pinctrl_setting

每个device结构体里都有一个dev_pin_info结构体,用来保存设备的pinctrl信息

假设芯片上有多个pin controller,那么这个设备使用哪个pin controller ?
这需要通过设备树来确定:

  • 分析设备树,找到pin controller
  • 对于每个状态,比如default、init,去分析pin controller中的设备树节点
    • 使用pin controller的pinctrl_ops.dt_node_to_map来处理设备树的pinctrl节点信息,例如pinctrl-0 = <&state_0_node_a>,state_0_node_a节点被解析为一系列的pinctrl_map
    • 这些pinctrl_map放在pinctrl.dt_maps链表中
    • 每个pinctrl_map都被转换为pinctrl_setting,放在对应的pinctrl_state.settings链表中
  • 选择状态时,遍历settings链表,执行pin controller复用或配置函数

3. Pincontroller构造过程情景分析

参考资料

  • drivers\pinctrl\molchip\pinctrl-mcfy00.c
  • drivers\pinctrl\molchip\pinctrl-mc-common.c
  • drivers\pinctrl\core.c
  • drivers\base\dd.c
  • drivers\base\pinctrl.c
  • drivers\pinctrl\devicetree.c
  • drivers\pinctrl\pinmux.c
  • drivers\pinctrl\pinconf.c

3.1 设备树节点

3.2 驱动代码执行流程

调用过程:
drivers\pinctrl\molchip\pinctrl-mcfy00.c
drivers\pinctrl\molchip\pinctrl-mc-common.c

mcfy00_pinctrl_probemc_pctrl_initpctl->pctl_desc.name = dev_name(&pdev->dev);pctl->pctl_desc.owner = THIS_MODULE;pctl->pctl_desc.pins = pins;pctl->pctl_desc.npins = pctl->devdata->npins;pctl->pctl_desc.confops = &mc_pconf_ops;pctl->pctl_desc.pctlops = &mc_pctrl_ops;pctl->pctl_desc.pmxops = &mc_pmx_ops;pctl->dev = &pdev->dev;pctl->pctl_dev = devm_pinctrl_register(&pdev->dev, &pctl->pctl_desc,pctl);

3.3 作用1:描述、获取、解析引脚

3.3.1 单个引脚

//debugfs查看pin信息:cat /sys/kernel/debug/pinctrl/28200000.pinctrl/pins
pctl->pctl_desc.pins = pins;
pctl->pctl_desc.npins = pctl->devdata->npins;

3.3.2 某组引脚

//开发板查看 cat /sys/kernel/debug/pinctrl/28200000.pinctrl/pingroups
//FY001是把一个管脚当做一个组处理,见mc_pctrl_build_state
pctl->pctl_desc.pctlops = &mc_pctrl_ops;static const struct pinctrl_ops mc_pctrl_ops = {.dt_node_to_map        = mc_pctrl_dt_node_to_map,.dt_free_map     = pinctrl_utils_free_map,.get_groups_count = mc_pctrl_get_groups_count,.get_group_name        = mc_pctrl_get_group_name,.get_group_pins      = mc_pctrl_get_group_pins,
};

3.3.3 设备树节点解析 - 节点转换为pinctrl-map

详见第4节

static int mc_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,struct device_node *np_config,struct pinctrl_map **map, unsigned *num_maps)

3.4 作用2:引脚复用、配置

详见第4节

3.4.1 引脚复用

static const struct pinmux_ops mc_pmx_ops = {.get_functions_count   = mc_pmx_get_funcs_cnt,.get_function_name  = mc_pmx_get_func_name,.get_function_groups    = mc_pmx_get_func_groups,.set_mux      = mc_pmx_set_mux,
};

3.4.2 引脚配置

//FY00无引脚配置
static const struct pinconf_ops mc_pconf_ops = {.pin_config_group_get  = mc_pconf_group_get,.pin_config_group_set = mc_pconf_group_set,
};

4. client端使用pinctrl过程的情景分析

4.1 设备树节点

4.2 client节点如何使用pinctrl

设备节点要么被转换为platform_device,或者其他结构体(比如i2c_client),但是里面都会有一个device结构体,每个device结构体里都有一个dev_pin_info结构体,用来保存设备的pinctrl信息。
platform_device匹配driver会执行probe探测函数,执行到驱动中真正的probe函数之前,会进行pinctrl的处理,处理函数为pinctrl_bind_pins,调用过程如下

platform_device_registerplatform_device_adddevice_addbus_probe_device;device_initial_probe__device_attachbus_for_each_drv(dev->bus, NULL, &data, __device_attach_driver); // 对于plarform_bus_type下的每一个driver, 调用__device_attach_driver__device_attach_driverdriver_match_device(drv, dev);drv->bus->match(dev, drv)// 调用platform_bus_type.matchdriver_probe_devicereally_probe/* If using pinctrl, bind pins now before probing */pinctrl_bind_pinsdrv->probe //执行driver中的probe函数

pinctrl_bind_pins做了什么?

  • 构造pinctrl

    • 通过pinctrl_ops.dt_node_to_map将设备树节点转换成一系列pinctrl_map
    • pinctrl_map转换成pinctrl_setting,放入settings链表,记录在pinctrl_state中
  • 选择state,遍历settings链表,进行pinctrl的mux和config

4.2.1 client节点如何构造pinctrl


设备引用pin controller中的某个节点时,这个节点会被转换为一些列的pinctrl_map:

  • 转换为多少个pinctrl_map,完全由具体的驱动决定
  • 每个pinctrl_map,又被转换为一个pinctrl_setting
  • 举例,设备节点里有:pinctrl-0 = <&state_0_node_a> pinctrl-0 = <&state_0_node_a &state_0_node_b>
    • pinctrl-0对应一个状态,会得到一个pinctrl_state
    • state_0_node_a节点被解析为一系列的pinctrl_map
    • 这一系列的pinctrl_map被转换为一系列的pinctrl_setting
    • 这些pinctrl_setting被放入pinctrl_state的settings链表

函数调用过程

really_probepinctrl_bind_pins/* 分配dev_pin_info结构体 */devm_kzalloc(dev, sizeof(*(dev->pins)), GFP_KERNEL);/* 获取pinctrl */devm_pinctrl_get(dev);pinctrl_get/* 构建pinctrl */create_pinctrl(dev);/* 分配pinctrl */p = kzalloc(sizeof(*p), GFP_KERNEL);/* 设备树节点转换为pinctrl_map */pinctrl_dt_to_map(p);/* 每个pinctrl_map,又被转换为一个pinctrl_setting,添加到setting链表 */for_each_maps(maps_node, i, map) {ret = add_setting(p, map);}

1. 设备树节点转换为pinctrl_map

这些设备树节点信息会被转换为一些列的pinctrl_map,以fy00的uart2_pins节点举例

函数调用过程

pinctrl_dt_to_map(p);for (state = 0; ; state++) {propname = kasprintf(GFP_KERNEL, "pinctrl-%d", state);/* 取出pinctrl-%d节点属性 */prop = of_find_property(np, propname, &size);list = prop->value;size /= sizeof(*list);/* 对pinctrl-%d中的每一个phandle进行pinctrl_map转换 *//* 例如pinctrl-0 = <&state_0_node_a &state_0_node_b>有两个phandle */for (config = 0; config < size; config++) {/* 根据phandle找到对应节点 */np_config = of_find_node_by_phandle(phandle);/* Parse the node */dt_to_map_one_config(p, statename, np_config);/* 调用Pincontroller中dt_node_to_map函数,构造pinctrl_map */ops->dt_node_to_map()/* 将pinctrl_map添加到maps链表 */dt_remember_or_free_mappinctrl_register_maplist_add_tail}}/* fy00的dt_node_to_map函数 */
mc_pctrl_dt_node_to_map()/* 取出每一个子节点 */for_each_child_of_node(np_config, np) {mc_pctrl_dt_subnode_to_map/* 获取设备树pinmux属性 */pins = of_find_property(node, "pinmux", NULL);num_pins = pins->length / sizeof(u32);for (i = 0; i < num_pins; i++) {of_property_read_u32_index(node, "pinmux",i, &pinfunc); /* 解析设备树,将pinmux属性中每一个成员记录在pin和func中 */pin = MC_GET_PIN_NO(pinfunc);func = MC_GET_PIN_FUNC(pinfunc);/* 设置复用的pinctrl_map */mc_pctrl_dt_node_to_map_func();(*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP;(*map)[*num_maps].data.mux.group = grp->name;(*map)[*num_maps].data.mux.function = mc_gpio_functions[fnum];(*num_maps)++;if (has_config) {/* 设置配置pinctrl_map,fy00没有配置pinctrl_map */pinctrl_utils_add_map_configs(*map)[*num_maps].type = type;(*map)[*num_maps].data.configs.group_or_pin = group;(*map)[*num_maps].data.configs.configs = dup_configs;(*map)[*num_maps].data.configs.num_configs = num_configs;(*num_maps)++;}}}

2. pinctrl_map转换为pinctrl_setting

函数调用过程

for_each_maps() {add_setting();find_state();if (!state)/* 第一次添加state到states链表 */create_state(p, map->name);list_add_tail(&state->node, &p->states);/* 将map的name和tpye赋值给setting */setting->type = map->type;setting->dev_name = map->dev_name;switch (map->type) {/* MUX类型 */case PIN_MAP_TYPE_MUX_GROUP:pinmux_map_to_setting(map, setting);/* 将pinctrl_map中的function字符串转换为序号,赋值给setting*/pinmux_func_name_to_selector(pctldev, map->data.mux.function);setting->data.mux.func = ret;/* 将pinctrl_map中的group字符串转换为序号,赋值给setting */ret = pinctrl_get_group_selector(pctldev, group);setting->data.mux.group = ret;/* CONFIGS类型 */case PIN_MAP_TYPE_CONFIGS_PIN:case PIN_MAP_TYPE_CONFIGS_GROUP:pinconf_map_to_setting(map, setting);/* 从pinctrl_map取出pin或group赋值给setting */setting->data.configs.group_or_pin = pin;/* 将pinctrl_map的configs赋值给setting */setting->data.configs.num_configs = map->data.configs.num_configs;setting->data.configs.configs = map->data.configs.configs;}/* 添加到settings链表 */list_add_tail(&setting->node, &state->settings);
}

4.2.2 client节点如何使用设置管脚

涉及pinctrl子系统的其他2个作用:引脚复用、引脚配置
切换state情景分析

really_probepinctrl_bind_pins/* 寻找state */pinctrl_lookup_state/* 选择state */pinctrl_select_statepinctrl_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(...);}

1. 复用设置

与具体芯片有关,以fy00为例

mc_pmx_set_mux()pinctrl_params_data.mc_pmx_set_mode();//寄存器操作fy00_pmx_set_mode

2. 配置设置

与具体芯片有关,fy00无配置函数,实际也是通过dt_node_to_map拿到设备树中的配置数据,在pin_config_group_set完成寄存器操作。

5. 海思平台上编写Pinctrl驱动程序

5.1 设备树

对于hisi_i2c这个设备,将AT26、AN26两个引脚复用成i2c功能,对应寄存器配置成0x1403

5.2 驱动代码

5.2.1 pincontroller端

/* pin属性 */
static const struct pinctrl_pin_desc pins[] = {{0, "AT26", &AT26_REG},{1, "AN26", &AN26_REG},{2, "AN28", &AN28_REG},{3, "AR27", &AR27_REG},{4, "AP27", &AP27_REG},
};struct hisi_functions_desc {const char *func_name;const char **groups;int num_groups;
};static const char *i2c0_grps[] = {"AT26", "AN26"};
static const char *gpio_grps[] = {"AT26", "AN26", "AN28", "AR27", "AP27"};
static const char *spi0_grps[] = {"AT26", "AN26", "AN28", "AR27", "AP27"};/* func和group属性,本驱动中pin即group */
static struct hisi_functions_desc g_funcs_des[] = {{"gpio", gpio_grps, 5},{"i2c",  i2c0_grps, 2},{"spi", spi0_grps, 5},
};

5.2.2 client device端

5.3 使用debugfs调试

加载驱动insmod

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

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

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

cd soc\:amba\:hisi_pincontroller/
cat pinconf-groups

cat pingroups

cat pinmux-pins

cat pinconf-pins

cat pinmux-functions

cat pins

pinctrl 子系统介绍相关推荐

  1. Linux设备模型、平台设备驱动、设备树(device tree)、GPIO子系统以及pinctrl子系统介绍

    文章目录 一.Linux设备模型介绍 (1)设备驱动模型总体介绍 (2)设备驱动模型文件表现 (3)设备驱动模型工作原理 [1]总线 [2]设备 [3]驱动 [4]注册流程 二.平台设备驱动介绍 (1 ...

  2. linux查询引脚功能复用,Linux:使用pinctrl子系统动态切换复用pin脚的功能

    Linux:使用pinctrl子系统动态切换复用pin脚的功能 Linux:使用pinctrl子系统动态切换复用pin脚的功能 Linux:使用pinctrl子系统动态切换复用pin脚的功能 一.许多 ...

  3. Linux 学习笔记:pinctrl 子系统

    一.概述 在使用 pinctrl 和 gpio 子系统之前,开发gpio驱动,需要在驱动代码中直接操作所涉及的 GPIO 寄存器(配置IO 复用,配置IO口为输出方,设置IO输出高低电平),驱动开发方 ...

  4. Linux pinctrl子系统分析之三 数据结构分析

    在上一章我们通过数据结构间的关联,说明了pinctrl子系统的软件框架.本章我们主要介绍每一个数据结构的定义,从而加深对pinctrl子系统相关的数据结构理解.本章我们依然从soc pin描述.boa ...

  5. 韦东山 IMX6ULL和正点原子_GPIO和Pinctrl子系统的使用在100ASK_IMX6ULL上机实验

    来源:百问网 作者:韦东山 本文字数:924,阅读时长:3分钟 阅读本节前先阅读: Pinctrl子系统重要概念 GPIO子系统重要概念 基于GPIO子系统的LED驱动程序 1.1 确定引脚并生成设备 ...

  6. linux pinctl 分析,Linux驱动架构之pinctrl子系统分析(一)

    1.前言 在嵌入式系统中,许多SoC的内部都包含了pin控制器,通过芯片内部的pin控制器,我们可以配置一个或者一组引脚的状态和功能特性,Linux内核为了统一各SoC厂商的引脚管理,提供了pinct ...

  7. 32驱动_轻松掌握pinctrl子系统驱动开发——一个虚拟pinctrl dev驱动开发

    这周主要对pinctrl子系统进行分析,该分析的基本上已经分析完成,唯一没有细说的估计就是gpio与pinctrl之间的关联了.本章即是pinctrl子系统分析的最后一章,本章我们主要实现一个虚拟的p ...

  8. pinctrl子系统初始化RGB灯

    文章目录 系列文章目录 前言 正文 引入 iomuxc节点:pinctrl子系统初窥 iomuxc节点 节点引脚配置方式 节点配置信息记录 pinctrl子系统实验:RGB灯引脚初始化 platfor ...

  9. PINCTRL子系统

    转载地址:http://www.360doc.com/content/14/0914/22/426085_409500256.shtml PINCTRL子系统用于处理: - 枚举和命名控制引脚 - 复 ...

最新文章

  1. Python零散知识点记录
  2. csu 1985: 驱R符
  3. ue4 开发动作游戏_【图片】第三人称动作游戏开发日志【虚幻4吧】_百度贴吧
  4. C++基本序列式容器 vector (一)
  5. 代码优化 5 大原则,第一条就是别优化了!!!
  6. 《SAS编程与数据挖掘商业案例》学习笔记之十四
  7. EF框架中,在实体中手动更新字段,数据库数据未同步到程序中应该怎么解决呢?
  8. 创建组_在Allegro软件中的Groups组创建之后怎么进行打散呢?
  9. 如何用 IDEA 提升十倍开发效率?
  10. 基于JAVA+SpringMVC+MYSQL的苗木销售系统
  11. c++ ado操作mysql_利用ADO在C++下操作access数据库
  12. ArrayListd的长度问题
  13. ubuntu20 scrt 连接ssh报错的解决方法
  14. foobar2000 v1.2
  15. _initialize() 区别 __construct()
  16. 上海数据交易中心交易系统开放
  17. python二项分布产生随机数_python随机生成 - osc_c10h48oh的个人空间 - OSCHINA - 中文开源技术交流社区...
  18. 微信开放平台(公众号第三方平台) -- 全网发布
  19. Zerotier 搭建moon
  20. 烟雨白银坨_SAP刘梦_新浪博客

热门文章

  1. PDF在线编辑器的实现
  2. 潜心一技、做到极致!——Elastic认证工程师之路
  3. 人工智能既预测世界杯冠军,还帮你“讨债”?
  4. Charles的基本使用方法
  5. 风向值与风向描述定义
  6. 刚刚:魅族PANDAER妙磁背甲让iPhone 13满血,《原神》稳定60帧
  7. 记录和“异地恋女友”的第一次相见
  8. Javascript深入浅出之闭包
  9. openwrt查看linux内核,OpenWrt教程-如何升级linux内核版本
  10. 《信息物理融合系统(CPS)设计、建模与仿真——基于 Ptolemy II 平台》——第3章 数据流 3.1同步数据流...