gpio pinctrl

1.pinctrl驅動

SoC內部都包含pin控制器,通過控制pin的寄存器,我們可以配置一個或者一組引腳的功能和特性
linux系統下采用pinctrl子系統管理所有的IO管腳

# ls out/target/product/msm8998/obj/kernel/msm-4.4/drivers/pinctrl/qcom/ -l
總用量 1668
-rw-r--r-- 1 root root 821920  6月  8 13:37 built-in.o
-rw-r--r-- 1 root root    136  6月  8 15:33 modules.builtin
-rw-r--r-- 1 root root      0  6月  8 15:35 modules.order
-rw-r--r-- 1 root root 254448  6月  8 13:37 pinctrl-msm8998.o
-rw-r--r-- 1 root root 206232 11月 10  2017 pinctrl-msm.o
-rw-r--r-- 1 root root 233064 11月 10  2017 pinctrl-sdm660.o
-rw-r--r-- 1 root root 155960 11月 10  2017 pinctrl-wcd.o

驅動位置kernel/msm-4.4/drivers/pinctrl/qcom/pinctrl-msm8998.c

platform_driver_register(&msm8998_pinctrl_driver);
static const struct of_device_id msm8998_pinctrl_of_match[] = {
    { .compatible = "qcom,msm8998-pinctrl", },
    { },
}

static const struct msm_pinctrl_soc_data msm8998_pinctrl = {
    .pins = msm8998_pins,//管腳描述,包括管腳編號和管腳字符串描述
    .npins = ARRAY_SIZE(msm8998_pins),//管腳的總個數
    .functions = msm8998_functions,//數組描述所有的SOC所支持的mux functions
    .nfunctions = ARRAY_SIZE(msm8998_functions),
    .groups = msm8998_groups,//描述引腳SOC支持的所有引腳組的陣列
    .ngroups = ARRAY_SIZE(msm8998_groups),
    .ngpios = 153,//可以導出的gpio的數量
};

dts

compatible = "qcom,msm8998-pinctrl";
kernel/msm-4.4/arch/arm/boot/dts/qcom/msm8998-pinctrl.dtsi:
//msm_uart功能
uart_console_active: uart_console_active {
            mux {
                pins = "gpio4", "gpio5";
                function = "blsp_uart8_a";//串口功能
            };

            config {
                pins = "gpio4", "gpio5";
                drive-strength = <2>;
                bias-disable;
            };
        };

led_disable: led_disable {
            mux {
                pins = "gpio21";
                function = "gpio";//gpio功能
            };

            config {
                pins = "gpio21";
                drive_strength = <2>;
                output-low;
                bias-disable;
            };
        };

2. gpiolib驅動

在drivers/gpio下實現了通用的基於gpiolib的GPIO驅動,
其中定義了一個通用的用於描述底層GPIO控制器的gpio_chip結構體,
並要求具體的SoC實現gpio_chip結構體的成員函數,
最後透過gpiochip_add()註冊gpio_chip
kernel/msm-4.4/drivers/gpio/gpiolib.c
在用戶空間/sys/class/gpio目錄下看到

msm8998:/sys/class/gpio # ls
export       gpiochip346 gpiochip506 gpiochip666 gpiochip826 gpiochip986 
gpiochip0    gpiochip378 gpiochip538 gpiochip698 gpiochip858 unexport    
gpiochip1018 gpiochip410 gpiochip570 gpiochip730 gpiochip890 
gpiochip1019 gpiochip442 gpiochip602 gpiochip762 gpiochip922 
gpiochip341  gpiochip474 gpiochip634 gpiochip794 gpiochip954 

操作gpio以gpio21爲例
msm8998:/sys/class/gpio # echo 21 > export
msm8998:/sys/class/gpio # cd gpio21/
echo in/out > direction    //設置gpio輸入或輸出
msm8998:/sys/class/gpio/gpio21 # echo out > direction
msm8998:/sys/class/gpio/gpio21 # echo '1' > value //設置gpio的電平
操作完成後
msm8998:/sys/class/gpio # echo 21 > unexport

主要操作direction和value這兩個文件
direction 用來配置輸入(in)還是輸出(out)
value 如果這個GPIO配置成了輸入,那麼通過cat value可以查看當前這個GPIO是什麼電位
如果配置成了輸出,那麼可以通過echo 1/0 > value給這個GPIO口指定輸出電平

3.在內核中配置gpio

1)單個gpio的配置

kernel/msm-4.4/arch/arm/boot/dts/qcom/msm8998-qrd-skuk-hdk.dtsi

st,reset-gpio = <&tlmm 89 0x00>;

驅動代碼的獲取
int rest_gpio = of_get_named_gpio_flags(np,”st, reset-gpio”, 0, NULL); 
       gpio_request(rest_gpio, "gpio_name");        
       gpio_direction_output(rest_gpio, 1);           
       gpio_set_value(rest_gpio, 0);                   
       gpio_free(rest_gpio);                           

關於TLMM
MSM Socs擁有pinmux controller作爲Top-LEVEL Mode Multiplexer(TLMM)
TLMM支持複用和配置不同類型的pins


2)用pinctrl配置設備樹,一次配置多個gpio
在驅動裏邊常常碰到驅動相關的一個或者幾個gpio,在 
醒來或者睡眠的時候需要設置成不同的類型,例如醒來的時候是i2c端口,但睡眠的時候可能要 
設置成GPIO並把輸出設置成0等。
參考:kernel/msm-4.4/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
kernel/msm-4.4/arch/arm/boot/dts/qcom/msm8998-qrd-skuk-hdk.dtsi
    pinctrl-0 = <&ts_active>; //引用ts_active
    pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;//引用ts_int_suspend ts-reset_suspend
在kernel/msm-4.4/arch/arm/boot/dts/qcom/msm8998-pinctrl.dtsi中
ts_mux {
            ts_active: ts_active {
                mux {
                    pins = "gpio89", "gpio125";
                    function = "gpio";
                };

                config {
                    pins = "gpio89", "gpio125";
                    drive-strength = <16>;
                    bias-pull-up;//上拉
                };
            };

            ts_reset_suspend: ts_reset_suspend {
                mux {
                    pins = "gpio89";
                    function = "gpio";
                };

                config {
                    pins = "gpio89";
                    drive-strength = <2>;
                    bias-pull-down;//下拉
                };
            };

            ts_int_suspend: ts_int_suspend {
                mux {
                    pins = "gpio125";
                    function = "gpio";
                };

                config {
                    pins = "gpio125";
                    drive-strength = <2>;
                    bias-disable;
                };
            };
        };
};

內核驅動代碼
kernel/msm-4.4/drivers/input/touchscreen/st/fts.c
kernel/msm-4.4/drivers/input/touchscreen/ft5x06_ts.c

ft5x06_data->ts_pinctrl = devm_pinctrl_get(&(ft5x06_data->client->dev));//獲取device對應節點下的pinctrl

ft5x06_data->pinctrl_state_active
        = pinctrl_lookup_state(ft5x06_data->ts_pinctrl,PINCTRL_STATE_ACTIVE);//通過pinctrl名獲取pinctrl對應狀態

ft5x06_data->pinctrl_state_release
        = pinctrl_lookup_state(ft5x06_data->ts_pinctrl,PINCTRL_STATE_RELEASE);

pinctrl_select_state(data->ts_pinctrl,data->pinctrl_state_release);////設置pinctrl的狀態爲pinctrl_state_release

devm_pinctrl_put(ft5x06_data->ts_pinctrl);//釋放資源
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章