GPIO子系统
GPIO相应的API使用GPIO步骤include header#include <linux/gpio.h>check valid (optional)每一个chip上的gpio数量是有限制的(而且gpio号码一定>=0),为了防止指定的gpio号码是错的,可以先使用gpio_is_valid来检查。int gpio_is_valid(int number);//return t
GPIO相关的内核参考文档为Documentation/gpio.txt
GPIO相应的API
标准GPIO API
这些API的头文件定义于include/linux/gpio.h中,实际位于include/asm-generic/gpio.h中
bool gpio_is_valid(int number);
int gpio_request(unsigned gpio, const char *label);
void gpio_free(unsigned gpio);
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_export(unsigned gpio, bool direction_may_change);
void gpio_unexport(unsigned gpio);
int __gpio_cansleep(unsigned gpio);
int gpio_get_value_cansleep(unsigned gpio);
void gpio_set_value_cansleep(unsigned gpio, int value);
int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);
int gpio_request_array(const struct gpio *array, size_t num);
void gpio_free_array(const struct gpio *array, size_t num);
中断部分的API
中断函数的原型实现在kernel/irq目录下
int __gpio_to_irq(unsigned gpio);
int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev);
void free_irq(unsigned int irq, void *dev_id);
int irq_set_irq_type(unsigned int irq, unsigned int type);
void enable_irq(unsigned int irq);
void disable_irq(unsigned int irq);
int __disable_irq_nosync(unsigned int irq);
使用GPIO步骤
- include header
#include <linux/gpio.h>
- check valid (optional)
每一个chip上的gpio数量是有限制的(而且gpio号码一定>=0),为了防止指定的gpio号码是错的,可以先使用gpio_is_valid来检查。
int gpio_is_valid(int number);//return true if valid.
request gpio (optional, but recommended)
gpio_request可以检查gpio number是否超出范围或小于0及指定的gpio是否正在使用,因为有时候别的地方也控制着同一个gpio可能会发生预期外的结果。/** * return -EINVAL if GPIO is not valid(same as gpio_is_valid) * return -EBUSY if GPIO is already used * return 0 if GPIO is fine to use * 因此我們只要檢查回傳質是否>=0就可以判斷是否可用。 * 第一個參數是填入GPIO的號碼、第二個參數是想要對這個GPIO的命名。 * $ cat /sys/kernel/debug/gpio就可以看到 */ int gpio_request(unsigned gpio, const char *label);
configure 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);
access gpio
/* GPIO INPUT: return zero or nonzero */ int gpio_get_value(unsigned gpio); /* GPIO OUTPUT */ void gpio_set_value(unsigned gpio, int value);
free gpio
当使用完GPIO之后利用gpio_free来释放GPIO
int gpio_free(unsigned gpio);
GPIO源码架构分析
gpio相应的API其实调用的是注册的struct gpio_chip中的一些方法,来看下struct gpio_chip这个结构体,
struct gpio_chip {
const char *label;
struct device *dev;
struct module *owner;
struct list_head list;
int (*request)(struct gpio_chip *chip, unsigned offset);
void (*free)(struct gpio_chip *chip, unsigned offset);
int (*get_direction)(struct gpio_chip *chip, unsigned offset);
int (*direction_input)(struct gpio_chip *chip, unsigned offset);
int (*get)(struct gpio_chip *chip, unsigned offset);
int (*direction_output)(struct gpio_chip *chip, unsigned offset, int value);
int (*set_debounce)(struct gpio_chip *chip, unsigned offset, unsigned debounce);
void (*set)(struct gpio_chip *chip, unsigned offset, int value);
int (*to_irq)(struct gpio_chip *chip, unsigned offset);
void (*dbg_show)(struct seq_file *s, struct gpio_chip *chip);
int base;
u16 ngpio;
struct gpio_desc *desc;
const char *const *names;
unsigned can_sleep:1;
unsigned exported:1;
所以要使用gpio相应的API,必须事先注册一个struct gpio_chip结构体,并实现其中的方法,如下是一个例子,
static struct gpio_chip template_chip = {
.label = "wm8994",
.owner = THIS_MODULE,
.request = wm8994_gpio_request,
.direction_input = wm8994_gpio_direction_in,
.get = wm8994_gpio_get,
.direction_output = wm8994_gpio_direction_out,
.set = wm8994_gpio_set,
.to_irq = wm8994_gpio_to_irq,
.dbg_show = wm8994_gpio_dbg_show,
.can_sleep = 1,
};
另外需要说明一点是在struct gpio_chip结构体的这些函数中,既可以直接去操作gpio相应的寄存器,也可以通过i2c等接口去操作gpio,也可以调用pinctrl中提供的一些操作gpio的方法,总之,这个结构体的这些函数必须实现能够操作gpio。
更多推荐
所有评论(0)