[Linux Driver] - Use pinctrl subsystem to realize dynamic switching of pin functions

One, dts settings

&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>;
        };
    };
    ...
};

note:

The corresponding pin configuration of “default” is pinctrl-0;

The corresponding pin configuration of "gpio_state" is pinctrl-1;

Generally, it is enough to have two pin states, one is the pin state in the active state, and the other is the pin state in the dormant state.

Two, drive

The device is configured, let's look at the driver.

2.1. Main pinctrl function (core.c (drivers/pinctrl))

1. Get a pinctrl handle, the parameter is dev is the device structure that contains the pin, that is, the device of the device xxx

struct pinctrl *devm_pinctrl_get(struct device *dev);

2. Get the pin corresponding to pin_state, pin state

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

3. Set the pin to a certain state

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

2.2, specific code

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

    ... ... 
}

Guess you like

Origin blog.csdn.net/u014674293/article/details/114230461