[Linux 驱动] -- 使用 pinctrl 子系统实现引脚功能动态切换

一、dts 设置

&uart6 {
    pinctrl-names = "default","gpio_state";
    pinctrl-1 = <&uart6_gpio>;
    gpio_tx = <&gpio3 RK_PC4 GPIO_ACTIVE_HIGH>;
    gpio_rx = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>;
    status = "okay";
};

&pinctrl {
    ...
    uart6-gpio {
        uart6_gpio: uart6-gpio {
            rockchip,pins = <3 RK_PC5 0 &pcfg_pull_down>,
                            <3 RK_PC4 0 &pcfg_pull_down>;
        };
    };
    ...
};

注意:

“default” 对应的引脚配置为 pinctrl-0;

“gpio_state” 对应的引脚配置为 pinctrl-1;

一般引脚的状态为两个就可以了,一个为活跃状态的引脚状态,一个室休眠状态的引脚状态。

二、驱动

设备配置好了,我们来看驱动程序。

2.1、主要 pinctrl 函数(core.c (drivers/pinctrl))

1、获取一个 pinctrl 句柄,参数是 dev 是包含这个 pin 的 device 结构体 即 xxx 这个设备的 device

struct pinctrl *devm_pinctrl_get(struct device *dev);

2、获取这个 pin 对应 pin_state,引脚状态

struct pinctrl_state *pinctrl_lookup_state(struct pinctrl *p, const char *name);

3、设置引脚为某个 state

int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state);

2.2、具体代码

#include <linux/gpio.h>
#include <linux/of_gpio.h>

static struct pinctrl *pinctrl;
static struct pinctrl_state *gpio_state_idle;
static struct pinctrl_state *gpio_state_default;

static int dw8250_suspend(struct device *dev)
{
    ... ...
    
    struct pinctrl_state *set_state;
    pinctrl = devm_pinctrl_get(dev);
    if(IS_ERR_OR_NULL(pinctrl)){
        printk("[KERNAL]: %s()-%d: Pinctrl not defined \r\n", __func__, __LINE__);
    }
    else {
        printk("[KERNAL]: %s()-%d: Using pinctrl\r\n", __func__, __LINE__);
        set_state = pinctrl_lookup_state(pinctrl, "gpio_state");
        if(IS_ERR_OR_NULL(set_state)) {
            printk("[KERNAL]: %s-%d: pinctrl lookup failed for idle state \r\n", __func__, __LINE__);
        }
        else {
            printk("[KERNAL]: %s-%d: pinctrl state idle \r\n", __func__, __LINE__);
            gpio_state_idle = set_state;
            pinctrl_select_state(pinctrl, gpio_state_idle);
        }
    }

    ... ... 
}
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
pinctrl 子系统Linux 内核中的一个子系统,用于管理和控制 SoC(System-on-a-Chip)上的。在编写 pinctrl 子系统驱动时,需要完成以下几个步骤: 1. 定义 pinctrl 子系统设备树节点 在设备树中定义 pinctrl 子系统节点,包括组、功能等信息。这些信息将在驱动程序中使用。 2. 注册 pinctrl 子系统驱动程序中调用 pinctrl_register() 函数注册 pinctrl 子系统。此时,内核会根据设备树节点中的信息创建 pinctrl 子系统的实例,并将其加入到内核中的全局列表中。 3. 实现 pinctrl 子系统驱动程序 实现 pinctrl 子系统驱动程序,包括 pinmux 和 pinconf 两个部分。 pinmux 部分负责选择组中的某个,并将其配置为特定的模式(如输入、输出等)。 pinconf 部分负责配置的其他属性,如电气特性、驱动能力等。 4. 注册 pinctrl 子系统驱动程序 在驱动程序中调用 pinctrl_register_mappings() 函数注册 pinctrl 子系统驱动程序。这将使驱动程序与 pinctrl 子系统建立连接,并允许驱动程序向子系统发送命令。 5. 使用 pinctrl 子系统驱动程序中使用 pinctrl 子系统,包括选择组和,配置的模式和属性等。这些操作通过调用 pinctrl_select_state() 和 pinctrl_set_state() 等函数完成。 以上是编写 pinctrl 子系统驱动程序的基本步骤。需要注意的是,具体实现可能会因为硬件平台和需求的不同而有所不同。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值