// SPDX-License-Identifier: GPL-2.0 // // regmap based irq_chip // // Copyright 2011 Wolfson Microelectronics plc // // Author: Mark Brown <[email protected]> #include <linux/device.h> #include <linux/export.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/irqdomain.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> #include <linux/slab.h> #include "internal.h" struct regmap_irq_chip_data { … }; static inline const struct regmap_irq *irq_to_regmap_irq(struct regmap_irq_chip_data *data, int irq) { … } static bool regmap_irq_can_bulk_read_status(struct regmap_irq_chip_data *data) { … } static void regmap_irq_lock(struct irq_data *data) { … } static void regmap_irq_sync_unlock(struct irq_data *data) { … } static void regmap_irq_enable(struct irq_data *data) { … } static void regmap_irq_disable(struct irq_data *data) { … } static int regmap_irq_set_type(struct irq_data *data, unsigned int type) { … } static int regmap_irq_set_wake(struct irq_data *data, unsigned int on) { … } static const struct irq_chip regmap_irq_chip = …; static inline int read_sub_irq_data(struct regmap_irq_chip_data *data, unsigned int b) { … } static irqreturn_t regmap_irq_thread(int irq, void *d) { … } static int regmap_irq_map(struct irq_domain *h, unsigned int virq, irq_hw_number_t hw) { … } static const struct irq_domain_ops regmap_domain_ops = …; /** * regmap_irq_get_irq_reg_linear() - Linear IRQ register mapping callback. * @data: Data for the &struct regmap_irq_chip * @base: Base register * @index: Register index * * Returns the register address corresponding to the given @base and @index * by the formula ``base + index * regmap_stride * irq_reg_stride``. */ unsigned int regmap_irq_get_irq_reg_linear(struct regmap_irq_chip_data *data, unsigned int base, int index) { … } EXPORT_SYMBOL_GPL(…); /** * regmap_irq_set_type_config_simple() - Simple IRQ type configuration callback. * @buf: Buffer containing configuration register values, this is a 2D array of * `num_config_bases` rows, each of `num_config_regs` elements. * @type: The requested IRQ type. * @irq_data: The IRQ being configured. * @idx: Index of the irq's config registers within each array `buf[i]` * @irq_drv_data: Driver specific IRQ data * * This is a &struct regmap_irq_chip->set_type_config callback suitable for * chips with one config register. Register values are updated according to * the &struct regmap_irq_type data associated with an IRQ. */ int regmap_irq_set_type_config_simple(unsigned int **buf, unsigned int type, const struct regmap_irq *irq_data, int idx, void *irq_drv_data) { … } EXPORT_SYMBOL_GPL(…); /** * regmap_add_irq_chip_fwnode() - Use standard regmap IRQ controller handling * * @fwnode: The firmware node where the IRQ domain should be added to. * @map: The regmap for the device. * @irq: The IRQ the device uses to signal interrupts. * @irq_flags: The IRQF_ flags to use for the primary interrupt. * @irq_base: Allocate at specific IRQ number if irq_base > 0. * @chip: Configuration for the interrupt controller. * @data: Runtime data structure for the controller, allocated on success. * * Returns 0 on success or an errno on failure. * * In order for this to be efficient the chip really should use a * register cache. The chip driver is responsible for restoring the * register values used by the IRQ controller over suspend and resume. */ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode, struct regmap *map, int irq, int irq_flags, int irq_base, const struct regmap_irq_chip *chip, struct regmap_irq_chip_data **data) { … } EXPORT_SYMBOL_GPL(…); /** * regmap_add_irq_chip() - Use standard regmap IRQ controller handling * * @map: The regmap for the device. * @irq: The IRQ the device uses to signal interrupts. * @irq_flags: The IRQF_ flags to use for the primary interrupt. * @irq_base: Allocate at specific IRQ number if irq_base > 0. * @chip: Configuration for the interrupt controller. * @data: Runtime data structure for the controller, allocated on success. * * Returns 0 on success or an errno on failure. * * This is the same as regmap_add_irq_chip_fwnode, except that the firmware * node of the regmap is used. */ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, int irq_base, const struct regmap_irq_chip *chip, struct regmap_irq_chip_data **data) { … } EXPORT_SYMBOL_GPL(…); /** * regmap_del_irq_chip() - Stop interrupt handling for a regmap IRQ chip * * @irq: Primary IRQ for the device * @d: ®map_irq_chip_data allocated by regmap_add_irq_chip() * * This function also disposes of all mapped IRQs on the chip. */ void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *d) { … } EXPORT_SYMBOL_GPL(…); static void devm_regmap_irq_chip_release(struct device *dev, void *res) { … } static int devm_regmap_irq_chip_match(struct device *dev, void *res, void *data) { … } /** * devm_regmap_add_irq_chip_fwnode() - Resource managed regmap_add_irq_chip_fwnode() * * @dev: The device pointer on which irq_chip belongs to. * @fwnode: The firmware node where the IRQ domain should be added to. * @map: The regmap for the device. * @irq: The IRQ the device uses to signal interrupts * @irq_flags: The IRQF_ flags to use for the primary interrupt. * @irq_base: Allocate at specific IRQ number if irq_base > 0. * @chip: Configuration for the interrupt controller. * @data: Runtime data structure for the controller, allocated on success * * Returns 0 on success or an errno on failure. * * The ®map_irq_chip_data will be automatically released when the device is * unbound. */ int devm_regmap_add_irq_chip_fwnode(struct device *dev, struct fwnode_handle *fwnode, struct regmap *map, int irq, int irq_flags, int irq_base, const struct regmap_irq_chip *chip, struct regmap_irq_chip_data **data) { … } EXPORT_SYMBOL_GPL(…); /** * devm_regmap_add_irq_chip() - Resource managed regmap_add_irq_chip() * * @dev: The device pointer on which irq_chip belongs to. * @map: The regmap for the device. * @irq: The IRQ the device uses to signal interrupts * @irq_flags: The IRQF_ flags to use for the primary interrupt. * @irq_base: Allocate at specific IRQ number if irq_base > 0. * @chip: Configuration for the interrupt controller. * @data: Runtime data structure for the controller, allocated on success * * Returns 0 on success or an errno on failure. * * The ®map_irq_chip_data will be automatically released when the device is * unbound. */ int devm_regmap_add_irq_chip(struct device *dev, struct regmap *map, int irq, int irq_flags, int irq_base, const struct regmap_irq_chip *chip, struct regmap_irq_chip_data **data) { … } EXPORT_SYMBOL_GPL(…); /** * devm_regmap_del_irq_chip() - Resource managed regmap_del_irq_chip() * * @dev: Device for which the resource was allocated. * @irq: Primary IRQ for the device. * @data: ®map_irq_chip_data allocated by regmap_add_irq_chip(). * * A resource managed version of regmap_del_irq_chip(). */ void devm_regmap_del_irq_chip(struct device *dev, int irq, struct regmap_irq_chip_data *data) { … } EXPORT_SYMBOL_GPL(…); /** * regmap_irq_chip_get_base() - Retrieve interrupt base for a regmap IRQ chip * * @data: regmap irq controller to operate on. * * Useful for drivers to request their own IRQs. */ int regmap_irq_chip_get_base(struct regmap_irq_chip_data *data) { … } EXPORT_SYMBOL_GPL(…); /** * regmap_irq_get_virq() - Map an interrupt on a chip to a virtual IRQ * * @data: regmap irq controller to operate on. * @irq: index of the interrupt requested in the chip IRQs. * * Useful for drivers to request their own IRQs. */ int regmap_irq_get_virq(struct regmap_irq_chip_data *data, int irq) { … } EXPORT_SYMBOL_GPL(…); /** * regmap_irq_get_domain() - Retrieve the irq_domain for the chip * * @data: regmap_irq controller to operate on. * * Useful for drivers to request their own IRQs and for integration * with subsystems. For ease of integration NULL is accepted as a * domain, allowing devices to just call this even if no domain is * allocated. */ struct irq_domain *regmap_irq_get_domain(struct regmap_irq_chip_data *data) { … } EXPORT_SYMBOL_GPL(…);