diff options
Diffstat (limited to 'include/linux/gpio/driver.h')
| -rw-r--r-- | include/linux/gpio/driver.h | 178 | 
1 files changed, 144 insertions, 34 deletions
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 6a0e420915a3..f8245d67f070 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -20,9 +20,8 @@ struct module;  enum gpiod_flags;  enum gpio_lookup_flags; -#ifdef CONFIG_GPIOLIB +struct gpio_chip; -#ifdef CONFIG_GPIOLIB_IRQCHIP  /**   * struct gpio_irq_chip - GPIO interrupt controller   */ @@ -49,6 +48,84 @@ struct gpio_irq_chip {  	 */  	const struct irq_domain_ops *domain_ops; +#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY +	/** +	 * @fwnode: +	 * +	 * Firmware node corresponding to this gpiochip/irqchip, necessary +	 * for hierarchical irqdomain support. +	 */ +	struct fwnode_handle *fwnode; + +	/** +	 * @parent_domain: +	 * +	 * If non-NULL, will be set as the parent of this GPIO interrupt +	 * controller's IRQ domain to establish a hierarchical interrupt +	 * domain. The presence of this will activate the hierarchical +	 * interrupt support. +	 */ +	struct irq_domain *parent_domain; + +	/** +	 * @child_to_parent_hwirq: +	 * +	 * This callback translates a child hardware IRQ offset to a parent +	 * hardware IRQ offset on a hierarchical interrupt chip. The child +	 * hardware IRQs correspond to the GPIO index 0..ngpio-1 (see the +	 * ngpio field of struct gpio_chip) and the corresponding parent +	 * hardware IRQ and type (such as IRQ_TYPE_*) shall be returned by +	 * the driver. The driver can calculate this from an offset or using +	 * a lookup table or whatever method is best for this chip. Return +	 * 0 on successful translation in the driver. +	 * +	 * If some ranges of hardware IRQs do not have a corresponding parent +	 * HWIRQ, return -EINVAL, but also make sure to fill in @valid_mask and +	 * @need_valid_mask to make these GPIO lines unavailable for +	 * translation. +	 */ +	int (*child_to_parent_hwirq)(struct gpio_chip *chip, +				     unsigned int child_hwirq, +				     unsigned int child_type, +				     unsigned int *parent_hwirq, +				     unsigned int *parent_type); + +	/** +	 * @populate_parent_fwspec: +	 * +	 * This optional callback populates the &struct irq_fwspec for the +	 * parent's IRQ domain. If this is not specified, then +	 * &gpiochip_populate_parent_fwspec_twocell will be used. A four-cell +	 * variant named &gpiochip_populate_parent_fwspec_fourcell is also +	 * available. +	 */ +	void (*populate_parent_fwspec)(struct gpio_chip *chip, +				       struct irq_fwspec *fwspec, +				       unsigned int parent_hwirq, +				       unsigned int parent_type); + +	/** +	 * @child_offset_to_irq: +	 * +	 * This optional callback is used to translate the child's GPIO line +	 * offset on the GPIO chip to an IRQ number for the GPIO to_irq() +	 * callback. If this is not specified, then a default callback will be +	 * provided that returns the line offset. +	 */ +	unsigned int (*child_offset_to_irq)(struct gpio_chip *chip, +					    unsigned int pin); + +	/** +	 * @child_irq_domain_ops: +	 * +	 * The IRQ domain operations that will be used for this GPIO IRQ +	 * chip. If no operations are provided, then default callbacks will +	 * be populated to setup the IRQ hierarchy. Some drivers need to +	 * supply their own translate function. +	 */ +	struct irq_domain_ops child_irq_domain_ops; +#endif +  	/**  	 * @handler:  	 * @@ -125,11 +202,17 @@ struct gpio_irq_chip {  	bool threaded;  	/** -	 * @need_valid_mask: -	 * -	 * If set core allocates @valid_mask with all bits set to one. +	 * @init_valid_mask: optional routine to initialize @valid_mask, to be +	 * used if not all GPIO lines are valid interrupts. Sometimes some +	 * lines just cannot fire interrupts, and this routine, when defined, +	 * is passed a bitmap in "valid_mask" and it will have ngpios +	 * bits from 0..(ngpios-1) set to "1" as in valid. The callback can +	 * then directly set some bits to "0" if they cannot be used for +	 * interrupts.  	 */ -	bool need_valid_mask; +	void (*init_valid_mask)(struct gpio_chip *chip, +				unsigned long *valid_mask, +				unsigned int ngpios);  	/**  	 * @valid_mask: @@ -161,7 +244,6 @@ struct gpio_irq_chip {  	 */  	void		(*irq_disable)(struct irq_data *data);  }; -#endif /* CONFIG_GPIOLIB_IRQCHIP */  /**   * struct gpio_chip - abstract a GPIO controller @@ -282,7 +364,9 @@ struct gpio_chip {  	void			(*dbg_show)(struct seq_file *s,  						struct gpio_chip *chip); -	int			(*init_valid_mask)(struct gpio_chip *chip); +	int			(*init_valid_mask)(struct gpio_chip *chip, +						   unsigned long *valid_mask, +						   unsigned int ngpios);  	int			base;  	u16			ngpio; @@ -321,15 +405,6 @@ struct gpio_chip {  #endif /* CONFIG_GPIOLIB_IRQCHIP */  	/** -	 * @need_valid_mask: -	 * -	 * If set core allocates @valid_mask with all its values initialized -	 * with init_valid_mask() or set to one if init_valid_mask() is not -	 * defined -	 */ -	bool need_valid_mask; - -	/**  	 * @valid_mask:  	 *  	 * If not %NULL holds bitmask of GPIOs which are valid to be used @@ -421,9 +496,6 @@ extern int devm_gpiochip_add_data(struct device *dev, struct gpio_chip *chip,  extern struct gpio_chip *gpiochip_find(void *data,  			      int (*match)(struct gpio_chip *chip, void *data)); -/* lock/unlock as IRQ */ -int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset); -void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset);  bool gpiochip_line_is_irq(struct gpio_chip *chip, unsigned int offset);  int gpiochip_reqres_irq(struct gpio_chip *chip, unsigned int offset);  void gpiochip_relres_irq(struct gpio_chip *chip, unsigned int offset); @@ -441,15 +513,40 @@ bool gpiochip_line_is_valid(const struct gpio_chip *chip, unsigned int offset);  /* get driver data */  void *gpiochip_get_data(struct gpio_chip *chip); -struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc); -  struct bgpio_pdata {  	const char *label;  	int base;  	int ngpio;  }; -#if IS_ENABLED(CONFIG_GPIO_GENERIC) +#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY + +void gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip, +					     struct irq_fwspec *fwspec, +					     unsigned int parent_hwirq, +					     unsigned int parent_type); +void gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip, +					      struct irq_fwspec *fwspec, +					      unsigned int parent_hwirq, +					      unsigned int parent_type); + +#else + +static inline void gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip, +						    struct irq_fwspec *fwspec, +						    unsigned int parent_hwirq, +						    unsigned int parent_type) +{ +} + +static inline void gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip, +						     struct irq_fwspec *fwspec, +						     unsigned int parent_hwirq, +						     unsigned int parent_type) +{ +} + +#endif /* CONFIG_IRQ_DOMAIN_HIERARCHY */  int bgpio_init(struct gpio_chip *gc, struct device *dev,  	       unsigned long sz, void __iomem *dat, void __iomem *set, @@ -463,10 +560,6 @@ int bgpio_init(struct gpio_chip *gc, struct device *dev,  #define BGPIOF_READ_OUTPUT_REG_SET	BIT(4) /* reg_set stores output value */  #define BGPIOF_NO_OUTPUT		BIT(5) /* only input */ -#endif /* CONFIG_GPIO_GENERIC */ - -#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); @@ -555,15 +648,11 @@ static inline int gpiochip_irqchip_add_nested(struct gpio_chip *gpiochip,  }  #endif /* CONFIG_LOCKDEP */ -#endif /* CONFIG_GPIOLIB_IRQCHIP */ -  int gpiochip_generic_request(struct gpio_chip *chip, unsigned offset);  void gpiochip_generic_free(struct gpio_chip *chip, unsigned offset);  int gpiochip_generic_config(struct gpio_chip *chip, unsigned offset,  			    unsigned long config); -#ifdef CONFIG_PINCTRL -  /**   * struct gpio_pin_range - pin range controlled by a gpio chip   * @node: list for maintaining set of pin ranges, used internally @@ -576,6 +665,8 @@ struct gpio_pin_range {  	struct pinctrl_gpio_range range;  }; +#ifdef CONFIG_PINCTRL +  int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,  			   unsigned int gpio_offset, unsigned int pin_offset,  			   unsigned int npins); @@ -586,8 +677,6 @@ void gpiochip_remove_pin_ranges(struct gpio_chip *chip);  #else /* ! CONFIG_PINCTRL */ -struct pinctrl_dev; -  static inline int  gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,  		       unsigned int gpio_offset, unsigned int pin_offset, @@ -619,6 +708,15 @@ void gpiochip_free_own_desc(struct gpio_desc *desc);  void devprop_gpiochip_set_names(struct gpio_chip *chip,  				const struct fwnode_handle *fwnode); +#ifdef CONFIG_GPIOLIB + +/* lock/unlock as IRQ */ +int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset); +void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset); + + +struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc); +  #else /* CONFIG_GPIOLIB */  static inline struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc) @@ -628,6 +726,18 @@ static inline struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc)  	return ERR_PTR(-ENODEV);  } +static inline int gpiochip_lock_as_irq(struct gpio_chip *chip, +				       unsigned int offset) +{ +	WARN_ON(1); +	return -EINVAL; +} + +static inline void gpiochip_unlock_as_irq(struct gpio_chip *chip, +					  unsigned int offset) +{ +	WARN_ON(1); +}  #endif /* CONFIG_GPIOLIB */ -#endif +#endif /* __LINUX_GPIO_DRIVER_H */  |