【Linux 驱动】IMX6ULL gpio驱动
1. 概述
如果
pinctrl
子系统将一个 PIN 复用为 GPIO 的话,那么接下来要用到 gpio 子系统了。gpio 子系统顾名思义,就是用于初始化 GPIO 并且提供相应的 API 函数,比如设置 GPIO为输入输出,设置读取 GPIO 的值等。gpio 子系统的主要目的就是方便驱动开发者使用 gpio,驱动开发者在设备树中添加 gpio 相关信息,然后就可以在驱动程序中使用 gpio 子系统提供的 API函数来操作 GPIO,Linux 内核向驱动开发者屏蔽掉了 GPIO 的设置过程,极大的方便了驱动开发者使用 GPIO
Linux的GPIO子系统驱动框架由三个主要部分组成:① GPIO控制器驱动程序、②gpio lib驱动程序 ③GPIO字符设备驱动程序:
2. gpio 子系统相关结构体
2.1 struct gpio_chip
/*** struct gpio_chip - abstract a GPIO controller* @label: for diagnostics* @dev: optional device providing the GPIOs* @owner: helps prevent removal of modules exporting active GPIOs* @list: links gpio_chips together for traversal* @request: optional hook for chip-specific activation, such as* enabling module power and clock; may sleep* @free: optional hook for chip-specific deactivation, such as* disabling module power and clock; may sleep* @get_direction: returns direction for signal "offset", 0=out, 1=in,* (same as GPIOF_DIR_XXX), or negative error* @direction_input: configures signal "offset" as input, or returns error* @direction_output: configures signal "offset" as output, or returns error* @get: returns value for signal "offset"; for output signals this* returns either the value actually sensed, or zero* @set: assigns output value for signal "offset"* @set_multiple: assigns output values for multiple signals defined by "mask"* @set_debounce: optional hook for setting debounce time for specified gpio in* interrupt triggered gpio chips* @to_irq: optional hook supporting non-static gpio_to_irq() mappings;* implementation may not sleep* @dbg_show: optional routine to show contents in debugfs; default code* will be used when this is omitted, but custom code can show extra* state (such as pullup/pulldown configuration).* @base: identifies the first GPIO number handled by this chip; or, if* negative during registration, requests dynamic ID allocation.* @ngpio: the number of GPIOs handled by this controller; the last GPIO* handled is (base + ngpio - 1).* @desc: array of ngpio descriptors. Private.* @names: if set, must be an array of strings to use as alternative* names for the GPIOs in this chip. Any entry in the array* may be NULL if there is no alias for the GPIO, however the* array must be @ngpio entries long. A name can include a single printk* format specifier for an unsigned int. It is substituted by the actual* number of the gpio.* @can_sleep: flag must be set iff get()/set() methods sleep, as they* must while accessing GPIO expander chips over I2C or SPI. This* implies that if the chip supports IRQs, these IRQs need to be threaded* as the chip access may sleep when e.g. reading out the IRQ status* registers.* @exported: flags if the gpiochip is exported for use from sysfs. Private.* @irq_not_threaded: flag must be set if @can_sleep is set but the* IRQs don't need to be threaded** A gpio_chip can help platforms abstract various sources of GPIOs so* they can all be accessed through a common programing interface.* Example sources would be SOC controllers, FPGAs, multifunction* chips, dedicated GPIO expanders, and so on.** Each chip controls a number of signals, identified in method calls* by "offset" values in the range 0..(@ngpio - 1). When those signals* are referenced through calls like gpio_get_value(gpio), the offset* is calculated by subtracting @base from the gpio number.*/
struct gpio_chip {const char *label;struct device *dev;struct module *owner;struct list_head list;//请求一个 GPIO引脚int (*request)(struct gpio_chip *chip,unsigned offset);//释放一个GPIO引脚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);//输出模式,并且set gpio valint (*direction_output)(struct gpio_chip *chip,unsigned offset, int value);//读取 GPIO 引脚的值int (*get)(struct gpio_chip *chip,unsigned offset);//设置gpio 引脚值void (*set)(struct gpio_chip *chip,unsigned offset, int value);//设置多个gpio 引脚值void (*set_multiple)(struct gpio_chip *chip,unsigned long *mask,unsigned long *bits);//设置 GPIO 引脚的去抖动时间int (*set_debounce)(struct gpio_chip *chip,unsigned offset,unsigned debounce);int (*to_irq)(struct gpio_chip *chip,unsigned offset);void (*dbg_show)(struct seq_file *s,struct gpio_chip *chip);int base; //chip的基地址u16 ngpio; //GPIO 引脚数量struct gpio_desc *desc; //gpio描述结构体数组,里面保存了此控制器可以控制的引脚描述const char *const *names;bool can_sleep;bool irq_not_threaded;bool exported;#ifdef CONFIG_GPIOLIB_IRQCHIP/** With CONFIG_GPIOLIB_IRQCHIP we get an irqchip inside the gpiolib* to handle IRQs for most practical cases.*/struct irq_chip *irqchip;struct irq_domain *irqdomain;unsigned int irq_base;irq_flow_handler_t irq_handler;unsigned int irq_default_type;
#endif#if defined(CONFIG_OF_GPIO)/** If CONFIG_OF is enabled, then all GPIO controllers described in the* device tree automatically may have an OF translation*/struct device_node *of_node;int of_gpio_n_cells;int (*of_xlate)(struct gpio_chip *gc,const struct of_phandle_args *gpiospec, u32 *flags);
#endif
#ifdef CONFIG_PINCTRL/** If CONFIG_PINCTRL is enabled, then gpio controllers can optionally* describe the actual pin range which they serve in an SoC. This* information would be used by pinctrl subsystem to configure* corresponding pins for gpio usage.*/struct list_head pin_ranges;
#endif
};
2.2 struct gpio_desc
struct gpio_desc {struct gpio_chip *chip; //属于哪个gpio_chipunsigned long flags;
/* flag symbols are bit numbers */
#define FLAG_REQUESTED 0
#define FLAG_IS_OUT 1
#define FLAG_EXPORT 2 /* protected by sysfs_lock */
#define FLAG_SYSFS 3 /* exported via /sys/class/gpio/control */
#define FLAG_TRIG_FALL 4 /* trigger on falling edge */
#define FLAG_TRIG_RISE 5 /* trigger on rising edge */
#define FLAG_ACTIVE_LOW 6 /* value has active low */
#define FLAG_OPEN_DRAIN 7 /* Gpio is open drain type */
#define FLAG_OPEN_SOURCE 8 /* Gpio is open source type */
#define FLAG_USED_AS_IRQ 9 /* GPIO is connected to an IRQ */
#define FLAG_SYSFS_DIR 10 /* show sysfs direction attribute */
#define FLAG_IS_HOGGED 11 /* GPIO is hogged */#define ID_SHIFT 16 /* add new flags before this one */#define GPIO_FLAGS_MASK ((1 << ID_SHIFT) - 1)
#define GPIO_TRIGGER_MASK (BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE))const char *label;
};
3. IMX6ULL gpio-controller构造过程
4. gpiochip_add