diff options
Diffstat (limited to 'include/linux/gpio')
-rw-r--r-- | include/linux/gpio/consumer.h | 43 | ||||
-rw-r--r-- | include/linux/gpio/driver.h | 215 | ||||
-rw-r--r-- | include/linux/gpio/machine.h | 2 |
3 files changed, 226 insertions, 34 deletions
diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index c4a350d83578..6d236656aaef 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -100,10 +100,15 @@ int gpiod_direction_output_raw(struct gpio_desc *desc, int value); /* Value get/set from non-sleeping context */ int gpiod_get_value(const struct gpio_desc *desc); +int gpiod_get_array_value(unsigned int array_size, + struct gpio_desc **desc_array, int *value_array); 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); +int gpiod_get_raw_array_value(unsigned int array_size, + struct gpio_desc **desc_array, + int *value_array); 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, @@ -111,11 +116,17 @@ void gpiod_set_raw_array_value(unsigned int array_size, /* Value get/set from sleeping context */ int gpiod_get_value_cansleep(const struct gpio_desc *desc); +int gpiod_get_array_value_cansleep(unsigned int array_size, + struct gpio_desc **desc_array, + int *value_array); 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); +int gpiod_get_raw_array_value_cansleep(unsigned int array_size, + struct gpio_desc **desc_array, + int *value_array); 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, @@ -306,6 +317,14 @@ static inline int gpiod_get_value(const struct gpio_desc *desc) WARN_ON(1); return 0; } +static inline int gpiod_get_array_value(unsigned int array_size, + struct gpio_desc **desc_array, + int *value_array) +{ + /* GPIO can never have been requested */ + WARN_ON(1); + return 0; +} static inline void gpiod_set_value(struct gpio_desc *desc, int value) { /* GPIO can never have been requested */ @@ -324,6 +343,14 @@ static inline int gpiod_get_raw_value(const struct gpio_desc *desc) WARN_ON(1); return 0; } +static inline int gpiod_get_raw_array_value(unsigned int array_size, + struct gpio_desc **desc_array, + int *value_array) +{ + /* GPIO can never have been requested */ + WARN_ON(1); + return 0; +} static inline void gpiod_set_raw_value(struct gpio_desc *desc, int value) { /* GPIO can never have been requested */ @@ -343,6 +370,14 @@ static inline int gpiod_get_value_cansleep(const struct gpio_desc *desc) WARN_ON(1); return 0; } +static inline int gpiod_get_array_value_cansleep(unsigned int array_size, + struct gpio_desc **desc_array, + int *value_array) +{ + /* GPIO can never have been requested */ + WARN_ON(1); + return 0; +} static inline void gpiod_set_value_cansleep(struct gpio_desc *desc, int value) { /* GPIO can never have been requested */ @@ -361,6 +396,14 @@ static inline int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc) WARN_ON(1); return 0; } +static inline int gpiod_get_raw_array_value_cansleep(unsigned int array_size, + struct gpio_desc **desc_array, + int *value_array) +{ + /* GPIO can never have been requested */ + WARN_ON(1); + return 0; +} static inline void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value) { diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 424e5139ff10..55e672592fa9 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -20,6 +20,131 @@ struct module; #ifdef CONFIG_GPIOLIB +#ifdef CONFIG_GPIOLIB_IRQCHIP +/** + * struct gpio_irq_chip - GPIO interrupt controller + */ +struct gpio_irq_chip { + /** + * @chip: + * + * GPIO IRQ chip implementation, provided by GPIO driver. + */ + struct irq_chip *chip; + + /** + * @domain: + * + * Interrupt translation domain; responsible for mapping between GPIO + * hwirq number and Linux IRQ number. + */ + struct irq_domain *domain; + + /** + * @domain_ops: + * + * Table of interrupt domain operations for this IRQ chip. + */ + const struct irq_domain_ops *domain_ops; + + /** + * @handler: + * + * The IRQ handler to use (often a predefined IRQ core function) for + * GPIO IRQs, provided by GPIO driver. + */ + irq_flow_handler_t handler; + + /** + * @default_type: + * + * Default IRQ triggering type applied during GPIO driver + * initialization, provided by GPIO driver. + */ + unsigned int default_type; + + /** + * @lock_key: + * + * Per GPIO IRQ chip lockdep class. + */ + struct lock_class_key *lock_key; + + /** + * @parent_handler: + * + * The interrupt handler for the GPIO chip's parent interrupts, may be + * NULL if the parent interrupts are nested rather than cascaded. + */ + irq_flow_handler_t parent_handler; + + /** + * @parent_handler_data: + * + * Data associated, and passed to, the handler for the parent + * interrupt. + */ + void *parent_handler_data; + + /** + * @num_parents: + * + * The number of interrupt parents of a GPIO chip. + */ + unsigned int num_parents; + + /** + * @parents: + * + * A list of interrupt parents of a GPIO chip. This is owned by the + * driver, so the core will only reference this list, not modify it. + */ + unsigned int *parents; + + /** + * @map: + * + * A list of interrupt parents for each line of a GPIO chip. + */ + unsigned int *map; + + /** + * @threaded: + * + * True if set the interrupt handling uses nested threads. + */ + bool threaded; + + /** + * @need_valid_mask: + * + * If set core allocates @valid_mask with all bits set to one. + */ + bool need_valid_mask; + + /** + * @valid_mask: + * + * If not %NULL holds bitmask of GPIOs which are valid to be included + * in IRQ domain of the chip. + */ + unsigned long *valid_mask; + + /** + * @first: + * + * Required for static IRQ allocation. If set, irq_domain_add_simple() + * will allocate and map all IRQs during initialization. + */ + unsigned int first; +}; + +static inline struct gpio_irq_chip *to_gpio_irq_chip(struct irq_chip *chip) +{ + return container_of(chip, struct gpio_irq_chip, chip); +} +#endif + /** * struct gpio_chip - abstract a GPIO controller * @label: a functional name for the GPIO device, such as a part @@ -36,6 +161,8 @@ struct module; * @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", 0=low, 1=high, or negative error + * @get_multiple: reads values for multiple signals defined by "mask" and + * stores them in "bits", returns 0 on success or negative error * @set: assigns output value for signal "offset" * @set_multiple: assigns output values for multiple signals defined by "mask" * @set_config: optional hook for all kinds of settings. Uses the same @@ -66,9 +193,9 @@ struct module; * registers. * @read_reg: reader function for generic GPIO * @write_reg: writer function for generic GPIO - * @pin2mask: some generic GPIO controllers work with the big-endian bits - * notation, e.g. in a 8-bits register, GPIO7 is the least significant - * bit. This callback assigns the right bit mask. + * @be_bits: if the generic GPIO has big endian bit order (bit 31 is representing + * line 0, bit 30 is line 1 ... bit 0 is line 31) this is set to true by the + * generic GPIO core. It is for internal housekeeping only. * @reg_dat: data (in) register for generic GPIO * @reg_set: output set register (out=high) for generic GPIO * @reg_clr: output clear register (out=low) for generic GPIO @@ -81,23 +208,6 @@ struct module; * safely. * @bgpio_dir: shadowed direction register for generic GPIO to clear/set * direction safely. - * @irqchip: GPIO IRQ chip impl, provided by GPIO driver - * @irqdomain: Interrupt translation domain; responsible for mapping - * between GPIO hwirq number and linux irq number - * @irq_base: first linux IRQ number assigned to GPIO IRQ chip (deprecated) - * @irq_handler: the irq handler to use (often a predefined irq core function) - * for GPIO IRQs, provided by GPIO driver - * @irq_default_type: default IRQ triggering type applied during GPIO driver - * initialization, provided by GPIO driver - * @irq_chained_parent: GPIO IRQ chip parent/bank linux irq number, - * provided by GPIO driver for chained interrupt (not for nested - * interrupts). - * @irq_nested: True if set the interrupt handling is nested. - * @irq_need_valid_mask: If set core allocates @irq_valid_mask with all - * bits set to one - * @irq_valid_mask: If not %NULL holds bitmask of GPIOs which are valid to - * be included in IRQ domain of the chip - * @lock_key: per GPIO IRQ chip lockdep class * * A gpio_chip can help platforms abstract various sources of GPIOs so * they can all be accessed through a common programing interface. @@ -127,6 +237,9 @@ struct gpio_chip { unsigned offset, int value); int (*get)(struct gpio_chip *chip, unsigned offset); + int (*get_multiple)(struct gpio_chip *chip, + unsigned long *mask, + unsigned long *bits); void (*set)(struct gpio_chip *chip, unsigned offset, int value); void (*set_multiple)(struct gpio_chip *chip, @@ -148,7 +261,7 @@ struct gpio_chip { #if IS_ENABLED(CONFIG_GPIO_GENERIC) unsigned long (*read_reg)(void __iomem *reg); void (*write_reg)(void __iomem *reg, unsigned long data); - unsigned long (*pin2mask)(struct gpio_chip *gc, unsigned int pin); + bool be_bits; void __iomem *reg_dat; void __iomem *reg_set; void __iomem *reg_clr; @@ -164,16 +277,14 @@ struct gpio_chip { * 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; - unsigned int irq_chained_parent; - bool irq_nested; - bool irq_need_valid_mask; - unsigned long *irq_valid_mask; - struct lock_class_key *lock_key; + + /** + * @irq: + * + * Integrates interrupt chip functionality with the GPIO chip. Can be + * used to handle IRQs for most practical cases. + */ + struct gpio_irq_chip irq; #endif #if defined(CONFIG_OF_GPIO) @@ -211,7 +322,41 @@ extern const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset); /* add/remove chips */ -extern int gpiochip_add_data(struct gpio_chip *chip, void *data); +extern int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, + struct lock_class_key *lock_key); + +/** + * gpiochip_add_data() - register a gpio_chip + * @chip: the chip to register, with chip->base initialized + * @data: driver-private data associated with this chip + * + * Context: potentially before irqs will work + * + * When gpiochip_add_data() is called very early during boot, so that GPIOs + * can be freely used, the chip->parent device must be registered before + * the gpio framework's arch_initcall(). Otherwise sysfs initialization + * for GPIOs will fail rudely. + * + * gpiochip_add_data() must only be called after gpiolib initialization, + * ie after core_initcall(). + * + * If chip->base is negative, this requests dynamic assignment of + * a range of valid GPIOs. + * + * Returns: + * A negative errno if the chip can't be registered, such as because the + * chip->base is invalid or already associated with a different chip. + * Otherwise it returns zero as a success code. + */ +#ifdef CONFIG_LOCKDEP +#define gpiochip_add_data(chip, data) ({ \ + static struct lock_class_key key; \ + gpiochip_add_data_with_key(chip, data, &key); \ + }) +#else +#define gpiochip_add_data(chip, data) gpiochip_add_data_with_key(chip, data, NULL) +#endif + static inline int gpiochip_add(struct gpio_chip *chip) { return gpiochip_add_data(chip, NULL); @@ -265,6 +410,10 @@ int bgpio_init(struct gpio_chip *gc, struct device *dev, #ifdef CONFIG_GPIOLIB_IRQCHIP +int gpiochip_irq_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hwirq); +void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq); + void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip, struct irq_chip *irqchip, unsigned int parent_irq, @@ -279,7 +428,7 @@ int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip, unsigned int first_irq, irq_flow_handler_t handler, unsigned int type, - bool nested, + bool threaded, struct lock_class_key *lock_key); #ifdef CONFIG_LOCKDEP diff --git a/include/linux/gpio/machine.h b/include/linux/gpio/machine.h index b7225369e568..846be7c69a52 100644 --- a/include/linux/gpio/machine.h +++ b/include/linux/gpio/machine.h @@ -11,7 +11,7 @@ enum gpio_lookup_flags { GPIO_OPEN_DRAIN = (1 << 1), GPIO_OPEN_SOURCE = (1 << 2), GPIO_SLEEP_MAINTAIN_VALUE = (0 << 3), - GPIO_SLEEP_MAY_LOOSE_VALUE = (1 << 3), + GPIO_SLEEP_MAY_LOSE_VALUE = (1 << 3), }; /** |