Linux 內核層和 用戶層 配置 GPIO 引腳

  Linux BSP 開發的基礎就是和GPIO打交道, 下面總結下這幾天對某家開發板的GPIO控制的知識。node

  公司的開發板用的是 DTB  模式 ,首先,進入 dts,dtsi文件查看關於GPIO 的模塊。linux

soc {
                .
                .
                .
        gpio0: gpio@****addr {
            compatible = "**********";
            reg = <0 0x****addr 0 0x50>;
            interrupts = <SPI 4 IRQ_TYPE_LEVEL_HIGH>;
            #gpio-cells = <2>;
            gpio-controller;
            gpio-ranges = <&pfc 0 0 16>;
            #interrupt-cells = <2>;
            interrupt-controller;
            clocks = <&cpg CPG_MOD 912>;
            power-domains = <*****>;
        };
               .
               .
               .

};

  能夠看到 GPIO 節點 掛在 SOC node 下 ,手上這塊開發板 把GPIO分紅了8個 bank  :  gpio0 - gpio7ios

    reg =<0 地址 0 長度> bash

         #gpio-cells  =<2> 表示 要用2個cell描述一個 GPIO引腳 dom

    如 I2C中定義 :  pwd-gpios  = <&gpio6 7 GPIO_ACTIVE_HIGH>;this

    表示 bank 6 的gpio  用 2個cell 描述  :7,GPIO_ACTIVE_HIGH (7表示bank 6 下的第七個引腳通常是 GP 6_07表示  ;GPIO_ACTIVE_HIGH則爲高電平有效)     spa

    gpio-controller;  interrupt-controller; 表示 bank 0 下的引腳 既能夠做爲中斷引腳 ,也能夠做爲 通用的GPIO引腳 code

         gpio-ranges = <&pfc 0 0 16>;  表示 bank 0下有16個 GPIO引腳 orm

 

   GPIO 使用 pinctrl 方式來驅動 ,pin control subsystem 會 :對象

    1. 枚舉全部可用的pin 腳   ,因而每一個引腳就有的惟一的 ID (num) ,這個ID 很關鍵,對於之後的操做。

    

enum {
    PINMUX_RESERVED = 0,

    PINMUX_DATA_BEGIN,
    GP_ALL(DATA), /* add GP_0_1_DATA  ,GP_0_1_DATA..... */
    PINMUX_DATA_END,

#define F_(x, y)

.....
}

    2.管理 這些Pin腳的, 因爲pin 能夠複用 好比 SPI 和GPIO 複用一個pin腳 如:  GP2_08 / MISO,因而引伸出 pin group 和 pin functon 兩個概念:

    i2c2_pins: i2c2 {
        groups = "i2c2_a";
        function = "i2c2";
    };

    在dts 中如上所示 ,其中 i2c2_a 在 pinctl 源碼中 以下所示,i2c的兩根引腳使用 GP5_0 ,GP5_4. 

static const unsigned int i2c2_a_pins[] = {
    /* SDA, SCL */
    GP_PIN(5, 0),GP_PIN(5, 4),
};

    function 以下 : 

struct sh_pfc_function {
    const char *name;
    const char * const *groups;
    unsigned int nr_groups;
};
#define SH_PFC_FUNCTION(n = i2c2)                \
    {                        \
        .name = #n,                \
        .groups = n##_groups,            \
        .nr_groups = ARRAY_SIZE(n##_groups),    \
    }

好了 ,基本概念就先寫這麼多  。

 

內核層配置 GPIO 

在 寫內核驅動的時候 若是但願配置某個GPIO引腳 , 能夠在dts中 添加:  pwd-gpios  = <&gpio0 7 GPIO_ACTIVE_HIGH>;

 在 driver 代碼中 ,  須要包含 #include <linux/gpio.h>使用 : 

    gpio_id = of_get_named_gpio(your_driver->dev->of_node,"pwd-gpios", 0);

獲取 GP0_07的 ID號 ,而後申請 一個GPIO 操做對象。

    if (gpio_is_valid(gpio_id))  //判斷一個IO是否合法

      devm_gpio_request_one(&platform_device->dev, gpio_id,GPIOF_OUT_INIT_LOW, name);

設置GPIO的方向,若是是輸出同時設置電平:
    /* set as input or output, returning 0 or negative errno */
    int gpio_direction_input(unsigned gpio);
    int gpio_direction_output(unsigned gpio, int value);

獲取輸入引腳的電平:
    /* GPIO INPUT: return zero or nonzero */
    int gpio_get_value(unsigned gpio);

設置輸出: 
    void gpio_set_value(unsigned gpio, int value);

釋放申請的GPIO對象 

        void gpio_free(unsigned gpio);

將GPIO映射爲IRQ中斷:
    /* map GPIO numbers to IRQ numbers */
    int gpio_to_irq(unsigned gpio);

    /* map IRQ numbers to GPIO numbers (avoid using this) */
    int irq_to_gpio(unsigned irq);

 設置GPIO IRQ中斷類型:

    set_irq_type(gpio_to_irq( gpio), IRQ_TYPE_EDGE_FALLING);

用戶層配置 GPIO 

須要確認  內核  menuconfig  中 Device Drivers -》  GPIO Support  設 y .

在 /sys/class/gpio  目錄下以下所示 : 

root@salvator-x:/sys/class/gpio# ls
export         gpiochip361  gpiochip419  gpiochip453  gpiochip496
gpiochip357  gpiochip393  gpiochip437  gpiochip468  unexport

gpiochip 後面的數字 是每一個bank 的基地址  也就是  GP0 對應 gpiochip468

那麼  GP0_07 的 ID 就是  468 + 7 ;(可能不一樣的內核版本,或者 開發板不同 )經過 :

root@salvator-x:/sys/class/gpio# echo 475 > export

會對應生成 gpio475 目錄 

root@salvator-x:/sys/class/gpio/gpio475# ls
active_low  device  direction  edge  power  subsystem  uevent  value

經過 

root@salvator-x:/sys/class/gpio/gpio475# echo 1 >value 
root@salvator-x:/sys/class/gpio/gpio475# echo 0 >value
root@salvator-x:/sys/class/gpio/gpio475# echo "in" > direction 
root@salvator-x:/sys/class/gpio/gpio475# echo "out" > direction 

來控制輸出輸入  ,電平高低 。 

 

最後,關於 Pinctrl 的內容還有太多要寫,就先寫到這把。。。。。

來不及寫 參考文檔了,具體是 結合 wowotech 和 公司的設備,要下班了。。。

 ADD :..........................................................................

獲取GPIO不一樣組 基地址的 bash 命令 :

for i in gpiochip* ; do echo `cat $i/label`: `cat $i/base` ; done

相關文章
相關標籤/搜索