linux设备树里的gpio应用

linux设备树里的gpio应用

本文转自http://blog.csdn.net/jklinux/article/details/78581120?locationnum=3&fps=1

参考内核源码里的Documentation/devicetree/bindings/gpio/gpio.txt
在设备树里的节点设备需要使用到gpio口,则需要在一个或多个节点属性里提供gpio口的信息.


关于gpio口信息的节点属性命名方式是: name-gpios , 其中name用于指此gpio口在设备里的具体用途.
如用于复位的io口,则属性可以命名为: reset-gpios

出于兼容旧版本设备树的原因,属性名里也可以不写name而直接使用gpios作为属性名.这种方式内核以后不再允许使用.

关于gpio口的节点属性名还可以命名: name-gpio, 但这种方式内核也不会再使用.


关于gpio口的属性值.
一个属性值可以写单个的gpio口信息, 也可以写多个的gpio口信息

单个gpio口信息的属性值: <&gpio控制器节点名 具体gpio口的标识符>
一个具有多个gpio口信息的属性值: <&gpio控制器节点名 具体gpio口的标识符>,<&gpio控制器节点名 具体gpio口的标识符> …;
具体gpio口的标识符是由多个数字组成, 数字的个数由所用的gpio控制器节点里的#gpio-cells属性值指定.
如:

sunxi-h3-h5.dtsi里关于gpio控制器的节点信息:
        pio: pinctrl@01c20800 {  /*也可以通过此基地址在芯片手册里确认具体是哪个控制器 */
        ...
            gpio-controller;  /* 标明此节点是gpio控制器 */
            #gpio-cells = <3>; /* 标明每个gpio口的标识符由3个数字来识别(第0个数字表示gpio的组, 第1个数字表示组内的gpio口序号, 第3个数字表示gpio口的有效状态) */
                   /* 有些方案只用两个数字 */
                ...

    };



----------


gpio口的有效状态在内核头文件include/dt-bindings/gpio/gpio.h里定义:
/* Bit 0 express polarity */
#define GPIO_ACTIVE_HIGH 0
#define GPIO_ACTIVE_LOW 1

/* Bit 1 express single-endedness */
#define GPIO_PUSH_PULL 0
#define GPIO_SINGLE_ENDED 2


#define GPIO_OPEN_DRAIN (GPIO_SINGLE_ENDED | GPIO_ACTIVE_LOW)
#define GPIO_OPEN_SOURCE (GPIO_SINGLE_ENDED | GPIO_ACTIVE_HIGH) 



----------



则表示一个PA17口上接的led灯时,则可以如下指定:
    myleds {
        compatible = "myleds";

        led0 {
        label = "led0";
        led0-gpios = <&pio 0  17  GPIO_ACTIVE_HIGH>
            /* 0表示PA组的io口, 因h5里第0组的io口就是以PA开始命名的 */
        };  

    };

   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
如设备使用多个gpio口,也可以写在一个属性值里.
    myleds {
        ...

        leds-gpios = <&pio 0  18  GPIO_ACTIVE_HIGH>, <&pio 0  19  GPIO_ACTIVE_HIGH>;
        ...
    };

   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8


在以前没用设备树的内核里使用u32类型的一个数值表示一个gpio口, 具体的数值由芯片厂商负责定义好.
调用gpio口时只需使用如下的函数即可:

#include <linux/gpio.h>

int gpio_direction_input(unsigned gpio);
int gpio_direction_output(unsigned gpio, int value);
int gpio_get_value(unsigned gpio);
void gpio_set_value(unsigned gpio, int value);
int gpio_to_irq(unsigned gpio);
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7


使用设备树的内核里使用struct gpio_desc类型的一个对象表示设备树节点属性里的一个gpio口, 对象里的成员值由芯片厂商的驱动代码负责初始化,我们只需使用函数gpiod_get()获取即可.
可使用struct gpio_descs类型的一个对象装载struct gpio_desc多个对象(gpiod_get_array()函数获取).

#include <linux/gpio/consumer.h>

struct gpio_descs {
    unsigned int ndescs;
    struct gpio_desc *desc[];
};


在获取一个或多个在设备树设备节点属性里的gpio口时,可以指定获取的gpio口是作输入/输出.
#define GPIOD_FLAGS_BIT_DIR_SET     BIT(0)
#define GPIOD_FLAGS_BIT_DIR_OUT     BIT(1)
#define GPIOD_FLAGS_BIT_DIR_VAL     BIT(2)

enum gpiod_flags {
    GPIOD_ASIS  = 0,
    GPIOD_IN    = GPIOD_FLAGS_BIT_DIR_SET, //作输入
    GPIOD_OUT_LOW   = GPIOD_FLAGS_BIT_DIR_SET | GPIOD_FLAGS_BIT_DIR_OUT, //作输出且输出低电平
    GPIOD_OUT_HIGH  = GPIOD_FLAGS_BIT_DIR_SET | GPIOD_FLAGS_BIT_DIR_OUT |
              GPIOD_FLAGS_BIT_DIR_VAL, //作输出且输出高电平
};

int gpiod_count(struct device *dev, const char *con_id); //获取设备节点里的gpio口个数


//以下函数用于获取设备节点(不是它的子节点)属性值里gpio口的信息 
//参数con_id用于指定自定义的属性名的前缀,如属性名"leds-gpios", 则con_id应为"leds"
//flags用于指定获取gpio口信息时指定gpio是作输入或输出高低电平

struct gpio_desc *__must_check gpiod_get(struct device *dev,
                     const char *con_id,
                     enum gpiod_flags flags);
struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
                           const char *con_id,
                           unsigned int idx,
                           enum gpiod_flags flags);
struct gpio_desc *__must_check gpiod_get_optional(struct device *dev,
                          const char *con_id,
                          enum gpiod_flags flags);
struct gpio_desc *__must_check gpiod_get_index_optional(struct device *dev,
                            const char *con_id,
                            unsigned int index,
                            enum gpiod_flags flags);
struct gpio_descs *__must_check gpiod_get_array(struct device *dev,
                        const char *con_id,
                        enum gpiod_flags flags);
struct gpio_descs *__must_check gpiod_get_array_optional(struct device *dev,
                            const char *con_id,
                            enum gpiod_flags flags);

struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
                          const char *con_id,
                          enum gpiod_flags flags);
struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
                            const char *con_id,
                            unsigned int idx,
                            enum gpiod_flags flags);
struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev,
                               const char *con_id,
                               enum gpiod_flags flags);
struct gpio_desc *__must_check
devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
                  unsigned int index, enum gpiod_flags flags);
struct gpio_descs *__must_check devm_gpiod_get_array(struct device *dev,
                             const char *con_id,
                             enum gpiod_flags flags);
struct gpio_descs *__must_check
devm_gpiod_get_array_optional(struct device *dev, const char *con_id,
                  enum gpiod_flags flags);

//下面4个*_put函数用于回收设备节点属性里关于gpio口的信息.
//**注意只有释放gpio_desc资源后才可重新获取**
void devm_gpiod_put(struct device *dev, struct gpio_desc *desc);
void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs);
void gpiod_put(struct gpio_desc *desc); 
void gpiod_put_array(struct gpio_descs *descs);

//函数以devm开头的是有标明相应的资源是属于哪个struct device对象的功能.


////////////////////////////////////////////////////////////
//获取到gpio口的struct gpio_desc对象地址后,就可以通过下面函数操作gpio口

int gpiod_get_direction(struct gpio_desc *desc); //判断gpio是作输入或输出
int gpiod_direction_input(struct gpio_desc *desc); //gpio口作输入
int gpiod_direction_output(struct gpio_desc *desc, int value); //作输出, value用于指定输出的电平, 1表示输出有效电平,0表示输出失效电平。与在设备节点里设置GPIO_ACTIVIE_HIGHT/LOW有关
int gpiod_direction_output_raw(struct gpio_desc *desc, int value); //作输出, value用于直接指定是输出高低电平, 1表示高电平, 0表示低平, 带raw的函数是不会管ACTIVIE_LOW/ACTIVIE_HIGH的状态的


int gpiod_get_value(const struct gpio_desc *desc);
void gpiod_set_value(struct gpio_desc *desc, int value);
void gpiod_set_array_value(unsigned int array_size,
               struct gpio_desc **desc_array, int *value_array);
int gpiod_get_raw_value(const struct gpio_desc *desc);
void gpiod_set_raw_value(struct gpio_desc *desc, int value);
void gpiod_set_raw_array_value(unsigned int array_size,
                   struct gpio_desc **desc_array,
                   int *value_array);


int gpiod_get_value_cansleep(const struct gpio_desc *desc);
void gpiod_set_value_cansleep(struct gpio_desc *desc, int value);
void gpiod_set_array_value_cansleep(unsigned int array_size,
                    struct gpio_desc **desc_array,
                    int *value_array);
int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc);
void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value);
void gpiod_set_raw_array_value_cansleep(unsigned int array_size,
                    struct gpio_desc **desc_array,
                    int *value_array);

///////////////////////////////////////////////////
int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce); //设置过滤抖动电平信号

int gpiod_is_active_low(const struct gpio_desc *desc);
int gpiod_cansleep(const struct gpio_desc *desc);

int gpiod_to_irq(const struct gpio_desc *desc); //根据gpio_desc信息找到gpio口对应的中断号

struct gpio_desc *gpio_to_desc(unsigned gpio); //根据u32的gpio号找到gpio口对应的gpio_desc对象地址
int desc_to_gpio(const struct gpio_desc *desc); //根据gpio口的gpio_desc对象找到对象的u32的gpio号.


////////////////////////////////////////////////////
//获取设备节点里子节点关于gpio的属性值函数:

struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
                     const char *propname, int index,
                     enum gpiod_flags dflags,
                     const char *label);
struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev,
                        const char *con_id, int index,
                        struct fwnode_handle *child,
                        enum gpiod_flags flags,
                        const char *label);
static inline
struct gpio_desc *devm_fwnode_get_gpiod_from_child(struct device *dev,
                           const char *con_id,
                           struct fwnode_handle *child,
                           enum gpiod_flags flags,
                           const char *label);


   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
                                            <link rel="stylesheet" href="http://csdnimg.cn/release/phoenix/production/markdown_views-0bc64ada25.css">
                                </div>
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值