^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/gfp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "internals.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Device resource management aware IRQ request/free implementation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) struct irq_devres {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) unsigned int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) void *dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) static void devm_irq_release(struct device *dev, void *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) struct irq_devres *this = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) free_irq(this->irq, this->dev_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static int devm_irq_match(struct device *dev, void *res, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct irq_devres *this = res, *match = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) return this->irq == match->irq && this->dev_id == match->dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * devm_request_threaded_irq - allocate an interrupt line for a managed device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * @dev: device to request interrupt for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * @irq: Interrupt line to allocate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * @handler: Function to be called when the IRQ occurs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * @thread_fn: function to be called in a threaded interrupt context. NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * for devices which handle everything in @handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * @irqflags: Interrupt type flags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * @devname: An ascii name for the claiming device, dev_name(dev) if NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * @dev_id: A cookie passed back to the handler function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * Except for the extra @dev argument, this function takes the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * same arguments and performs the same function as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * request_threaded_irq(). IRQs requested with this function will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * automatically freed on driver detach.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * If an IRQ allocated with this function needs to be freed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * separately, devm_free_irq() must be used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) int devm_request_threaded_irq(struct device *dev, unsigned int irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) irq_handler_t handler, irq_handler_t thread_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) unsigned long irqflags, const char *devname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct irq_devres *dr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) dr = devres_alloc(devm_irq_release, sizeof(struct irq_devres),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (!dr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) if (!devname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) devname = dev_name(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) rc = request_threaded_irq(irq, handler, thread_fn, irqflags, devname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) dev_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) devres_free(dr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) dr->irq = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) dr->dev_id = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) devres_add(dev, dr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) EXPORT_SYMBOL(devm_request_threaded_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * devm_request_any_context_irq - allocate an interrupt line for a managed device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * @dev: device to request interrupt for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * @irq: Interrupt line to allocate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * @handler: Function to be called when the IRQ occurs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * @irqflags: Interrupt type flags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * @devname: An ascii name for the claiming device, dev_name(dev) if NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * @dev_id: A cookie passed back to the handler function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * Except for the extra @dev argument, this function takes the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * same arguments and performs the same function as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * request_any_context_irq(). IRQs requested with this function will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * automatically freed on driver detach.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * If an IRQ allocated with this function needs to be freed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * separately, devm_free_irq() must be used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) int devm_request_any_context_irq(struct device *dev, unsigned int irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) irq_handler_t handler, unsigned long irqflags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) const char *devname, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct irq_devres *dr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) dr = devres_alloc(devm_irq_release, sizeof(struct irq_devres),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (!dr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (!devname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) devname = dev_name(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) rc = request_any_context_irq(irq, handler, irqflags, devname, dev_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) devres_free(dr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) dr->irq = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) dr->dev_id = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) devres_add(dev, dr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) EXPORT_SYMBOL(devm_request_any_context_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * devm_free_irq - free an interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * @dev: device to free interrupt for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * @irq: Interrupt line to free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * @dev_id: Device identity to free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * Except for the extra @dev argument, this function takes the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * same arguments and performs the same function as free_irq().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * This function instead of free_irq() should be used to manually
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * free IRQs allocated with devm_request_irq().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct irq_devres match_data = { irq, dev_id };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) WARN_ON(devres_destroy(dev, devm_irq_release, devm_irq_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) &match_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) free_irq(irq, dev_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) EXPORT_SYMBOL(devm_free_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) struct irq_desc_devres {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) unsigned int from;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) unsigned int cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static void devm_irq_desc_release(struct device *dev, void *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct irq_desc_devres *this = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) irq_free_descs(this->from, this->cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * __devm_irq_alloc_descs - Allocate and initialize a range of irq descriptors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * for a managed device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * @dev: Device to allocate the descriptors for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * @irq: Allocate for specific irq number if irq >= 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * @from: Start the search from this irq number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * @cnt: Number of consecutive irqs to allocate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * @node: Preferred node on which the irq descriptor should be allocated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * @owner: Owning module (can be NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * @affinity: Optional pointer to an irq_affinity_desc array of size @cnt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * which hints where the irq descriptors should be allocated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * and which default affinities to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * Returns the first irq number or error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * Note: Use the provided wrappers (devm_irq_alloc_desc*) for simplicity.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) int __devm_irq_alloc_descs(struct device *dev, int irq, unsigned int from,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) unsigned int cnt, int node, struct module *owner,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) const struct irq_affinity_desc *affinity)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) struct irq_desc_devres *dr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) int base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) dr = devres_alloc(devm_irq_desc_release, sizeof(*dr), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (!dr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) base = __irq_alloc_descs(irq, from, cnt, node, owner, affinity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (base < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) devres_free(dr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) dr->from = base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) dr->cnt = cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) devres_add(dev, dr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) EXPORT_SYMBOL_GPL(__devm_irq_alloc_descs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) #ifdef CONFIG_GENERIC_IRQ_CHIP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * devm_irq_alloc_generic_chip - Allocate and initialize a generic chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * for a managed device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * @dev: Device to allocate the generic chip for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * @name: Name of the irq chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * @num_ct: Number of irq_chip_type instances associated with this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * @irq_base: Interrupt base nr for this chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * @reg_base: Register base address (virtual)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * @handler: Default flow handler associated with this chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * Returns an initialized irq_chip_generic structure. The chip defaults
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) * to the primary (index 0) irq_chip_type and @handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) struct irq_chip_generic *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) devm_irq_alloc_generic_chip(struct device *dev, const char *name, int num_ct,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) unsigned int irq_base, void __iomem *reg_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) irq_flow_handler_t handler)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct irq_chip_generic *gc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) gc = devm_kzalloc(dev, struct_size(gc, chip_types, num_ct), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (gc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) irq_init_generic_chip(gc, name, num_ct,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) irq_base, reg_base, handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return gc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) EXPORT_SYMBOL_GPL(devm_irq_alloc_generic_chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) struct irq_generic_chip_devres {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) struct irq_chip_generic *gc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) u32 msk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) unsigned int clr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) unsigned int set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static void devm_irq_remove_generic_chip(struct device *dev, void *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) struct irq_generic_chip_devres *this = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) irq_remove_generic_chip(this->gc, this->msk, this->clr, this->set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * devm_irq_setup_generic_chip - Setup a range of interrupts with a generic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) * chip for a managed device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * @dev: Device to setup the generic chip for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * @gc: Generic irq chip holding all data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * @msk: Bitmask holding the irqs to initialize relative to gc->irq_base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) * @flags: Flags for initialization
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * @clr: IRQ_* bits to clear
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * @set: IRQ_* bits to set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * Set up max. 32 interrupts starting from gc->irq_base. Note, this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) * initializes all interrupts to the primary irq_chip_type and its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) * associated handler.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) int devm_irq_setup_generic_chip(struct device *dev, struct irq_chip_generic *gc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) u32 msk, enum irq_gc_flags flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) unsigned int clr, unsigned int set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) struct irq_generic_chip_devres *dr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) dr = devres_alloc(devm_irq_remove_generic_chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) sizeof(*dr), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (!dr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) irq_setup_generic_chip(gc, msk, flags, clr, set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) dr->gc = gc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) dr->msk = msk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) dr->clr = clr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) dr->set = set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) devres_add(dev, dr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) EXPORT_SYMBOL_GPL(devm_irq_setup_generic_chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) #endif /* CONFIG_GENERIC_IRQ_CHIP */