[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);
        }
    }

    ... ... 
}

猜你喜欢

转载自blog.csdn.net/u014674293/article/details/114230461
今日推荐