• pinctrl


    1. pinctrl简介

            pinctrl子系统管理的Pin可以用作iic,也可以用作gpio;但是gpio子系统管理的pin只能用作输出或输入等功能(用作gpio的pin也是通过pinctrl子系统来管理的)。

    2. pinctrl使用方法

            1、其他驱动(除了IOMUX驱动本身或者说是pinctrl子系统本身外)通过pinctrl子系统提供的接口改变设备状态的接口如下,通常都是如下三个步骤:

    1. 1>pinctrl=devm_pinctrl_get(struct device)
    2. 2>pinctrl_state=pinctrl_lookup_state(pinctrl,state)
    3. 3>pinctrl_select_state(pinctrl,pinctrl_state)

            2、pinctrl子系统会调用类似1中的三个步骤初始化IOMUX节点下的字节点,所以有想要使能的PIN脚但是又不属于其它设备节点的pin脚可以都添加在IOMUX节点的子节点中;其他驱动的设备在平台总线被绑定之后会调用1中的三个步骤对设备相关的pin脚做初始化。

            3、pinctrl子系统提供的三个接口只能使能在设备节点中通过pinctrl-%d的形式明确标识的fsl,pins属性对应的pin脚。所以设备树文件的关键点还是在于设备节点是否使用pinctrl-%d的方式引用pin_grp,只需确保被外设引用的pin_grp是对的即可。

    3. pinctrl注册流程

            pinctrl子系统会将SOC可配置的引脚及其对应的功能全部注册到内核,驱动中通过pinctrl-pinctrl-%d的形式明确标识需要使用的引脚和功能,通过pinctrl_get()从内核获取引脚的使用权。注册全部引脚的代码流程如下:

     1>drivers/pinctrl/pinctrl-imx6dl.c

    1. static const struct pinctrl_pin_desc imx6dl_pinctrl_pads[] = {
    2. IMX_PINCTRL_PIN(MX6DL_PAD_RESERVE0),
    3. ······省去214
    4. IMX_PINCTRL_PIN(MX6DL_PAD_SD4_DAT7),
    5. }; #IMX6DL这款SOC可配置的引脚共214
    6. static struct imx_pinctrl_soc_info imx6dl_pinctrl_info = {
    7. .pins = imx6dl_pinctrl_pads,
    8. .npins = ARRAY_SIZE(imx6dl_pinctrl_pads), #注意
    9. };
    10. static int imx6dl_pinctrl_probe(struct platform_device *pdev)
    11. {
    12. return imx_pinctrl_probe(pdev, &imx6dl_pinctrl_info);
    13. }

    2>drivers/pinctrl/pinctrl-imx.c

    1. int imx_pinctrl_probe(struct platform_device *pdev,
    2. struct imx_pinctrl_soc_info *info)
    3. {
    4. imx_pinctrl_desc.pins = info->pins;
    5. imx_pinctrl_desc.npins = info->npins; #注意
    6. #解析设备树中关于Pin的配置信息,并将其放到链表中管理起来
    7. imx_pinctrl_probe_dt(pdev, info);
    8. #向内核注册SOC的所有可配置引脚
    9. pinctrl_register(&imx_pinctrl_desc, &pdev->dev, ipctl);
    10. }

    3>drivers/pinctrl/core.c

    1. struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
    2. struct device *dev, void *driver_data)
    3. {
    4. pinctrl_register_pins(pctldev, pctldesc->pins, pctldesc->npins);
    5. }
    6. static int pinctrl_register_pins(struct pinctrl_dev *pctldev,
    7. struct pinctrl_pin_desc const *pins,unsigned num_descs)
    8. {
    9. /*遍历传入的所有Pin的数据结构,一个个处理,pinctrl drvier会传入所有的pin管脚及对应的名称*/
    10. for (i = 0; i < num_descs; i++)
    11. ret = pinctrl_register_one_pin(pctldev,pins[i].number, pins[i].name);
    12. }

  • 相关阅读:
    【C++】多态 ⑥ ( 函数重定义涉及的问题 - 子类覆盖父类函数名 )
    好心情精神心理科医生:抗抑郁药物是否成瘾?
    【大数据折腾不息系列】(三) MySQL安装
    mysql 运行参数优化
    Android 混淆使用及其字典混淆(Proguard)
    SpringBoot启动流程源码分析
    Codeforces Round 895 div3 | JorbanS
    一次不完整的渗透
    AI加速(五)| 一个例子看懂流水——从指令到算法
    springMVC 面试题
  • 原文地址:https://blog.csdn.net/qq_41076734/article/details/124711546