15ea81769SAl Viro #include <linux/module.h> 25ea81769SAl Viro #include <linux/interrupt.h> 30af3678fSAl Viro #include <linux/device.h> 41aeb272cSRobert P. J. Day #include <linux/gfp.h> 52b5e7730SBartosz Golaszewski #include <linux/irq.h> 65ea81769SAl Viro 71c3e3630SBartosz Golaszewski #include "internals.h" 81c3e3630SBartosz Golaszewski 95ea81769SAl Viro /* 105ea81769SAl Viro * Device resource management aware IRQ request/free implementation. 115ea81769SAl Viro */ 125ea81769SAl Viro struct irq_devres { 135ea81769SAl Viro unsigned int irq; 145ea81769SAl Viro void *dev_id; 155ea81769SAl Viro }; 165ea81769SAl Viro 175ea81769SAl Viro static void devm_irq_release(struct device *dev, void *res) 185ea81769SAl Viro { 195ea81769SAl Viro struct irq_devres *this = res; 205ea81769SAl Viro 215ea81769SAl Viro free_irq(this->irq, this->dev_id); 225ea81769SAl Viro } 235ea81769SAl Viro 245ea81769SAl Viro static int devm_irq_match(struct device *dev, void *res, void *data) 255ea81769SAl Viro { 265ea81769SAl Viro struct irq_devres *this = res, *match = data; 275ea81769SAl Viro 285ea81769SAl Viro return this->irq == match->irq && this->dev_id == match->dev_id; 295ea81769SAl Viro } 305ea81769SAl Viro 315ea81769SAl Viro /** 32935bd5b9SArjan van de Ven * devm_request_threaded_irq - allocate an interrupt line for a managed device 335ea81769SAl Viro * @dev: device to request interrupt for 345ea81769SAl Viro * @irq: Interrupt line to allocate 355ea81769SAl Viro * @handler: Function to be called when the IRQ occurs 36935bd5b9SArjan van de Ven * @thread_fn: function to be called in a threaded interrupt context. NULL 37935bd5b9SArjan van de Ven * for devices which handle everything in @handler 385ea81769SAl Viro * @irqflags: Interrupt type flags 39899b5fbfSHeiner Kallweit * @devname: An ascii name for the claiming device, dev_name(dev) if NULL 405ea81769SAl Viro * @dev_id: A cookie passed back to the handler function 415ea81769SAl Viro * 425ea81769SAl Viro * Except for the extra @dev argument, this function takes the 435ea81769SAl Viro * same arguments and performs the same function as 44307b28b9SEmilio López * request_threaded_irq(). IRQs requested with this function will be 455ea81769SAl Viro * automatically freed on driver detach. 465ea81769SAl Viro * 475ea81769SAl Viro * If an IRQ allocated with this function needs to be freed 485c42dc70SJean Delvare * separately, devm_free_irq() must be used. 495ea81769SAl Viro */ 50935bd5b9SArjan van de Ven int devm_request_threaded_irq(struct device *dev, unsigned int irq, 51935bd5b9SArjan van de Ven irq_handler_t handler, irq_handler_t thread_fn, 52935bd5b9SArjan van de Ven unsigned long irqflags, const char *devname, 53935bd5b9SArjan van de Ven void *dev_id) 545ea81769SAl Viro { 555ea81769SAl Viro struct irq_devres *dr; 565ea81769SAl Viro int rc; 575ea81769SAl Viro 585ea81769SAl Viro dr = devres_alloc(devm_irq_release, sizeof(struct irq_devres), 595ea81769SAl Viro GFP_KERNEL); 605ea81769SAl Viro if (!dr) 615ea81769SAl Viro return -ENOMEM; 625ea81769SAl Viro 63899b5fbfSHeiner Kallweit if (!devname) 64899b5fbfSHeiner Kallweit devname = dev_name(dev); 65899b5fbfSHeiner Kallweit 66935bd5b9SArjan van de Ven rc = request_threaded_irq(irq, handler, thread_fn, irqflags, devname, 67935bd5b9SArjan van de Ven dev_id); 685ea81769SAl Viro if (rc) { 697f30e49eSTejun Heo devres_free(dr); 705ea81769SAl Viro return rc; 715ea81769SAl Viro } 725ea81769SAl Viro 735ea81769SAl Viro dr->irq = irq; 745ea81769SAl Viro dr->dev_id = dev_id; 755ea81769SAl Viro devres_add(dev, dr); 765ea81769SAl Viro 775ea81769SAl Viro return 0; 785ea81769SAl Viro } 79935bd5b9SArjan van de Ven EXPORT_SYMBOL(devm_request_threaded_irq); 805ea81769SAl Viro 815ea81769SAl Viro /** 820668d306SStephen Boyd * devm_request_any_context_irq - allocate an interrupt line for a managed device 830668d306SStephen Boyd * @dev: device to request interrupt for 840668d306SStephen Boyd * @irq: Interrupt line to allocate 850668d306SStephen Boyd * @handler: Function to be called when the IRQ occurs 860668d306SStephen Boyd * @thread_fn: function to be called in a threaded interrupt context. NULL 870668d306SStephen Boyd * for devices which handle everything in @handler 880668d306SStephen Boyd * @irqflags: Interrupt type flags 89899b5fbfSHeiner Kallweit * @devname: An ascii name for the claiming device, dev_name(dev) if NULL 900668d306SStephen Boyd * @dev_id: A cookie passed back to the handler function 910668d306SStephen Boyd * 920668d306SStephen Boyd * Except for the extra @dev argument, this function takes the 930668d306SStephen Boyd * same arguments and performs the same function as 940668d306SStephen Boyd * request_any_context_irq(). IRQs requested with this function will be 950668d306SStephen Boyd * automatically freed on driver detach. 960668d306SStephen Boyd * 970668d306SStephen Boyd * If an IRQ allocated with this function needs to be freed 980668d306SStephen Boyd * separately, devm_free_irq() must be used. 990668d306SStephen Boyd */ 1000668d306SStephen Boyd int devm_request_any_context_irq(struct device *dev, unsigned int irq, 1010668d306SStephen Boyd irq_handler_t handler, unsigned long irqflags, 1020668d306SStephen Boyd const char *devname, void *dev_id) 1030668d306SStephen Boyd { 1040668d306SStephen Boyd struct irq_devres *dr; 1050668d306SStephen Boyd int rc; 1060668d306SStephen Boyd 1070668d306SStephen Boyd dr = devres_alloc(devm_irq_release, sizeof(struct irq_devres), 1080668d306SStephen Boyd GFP_KERNEL); 1090668d306SStephen Boyd if (!dr) 1100668d306SStephen Boyd return -ENOMEM; 1110668d306SStephen Boyd 112899b5fbfSHeiner Kallweit if (!devname) 113899b5fbfSHeiner Kallweit devname = dev_name(dev); 114899b5fbfSHeiner Kallweit 1150668d306SStephen Boyd rc = request_any_context_irq(irq, handler, irqflags, devname, dev_id); 11663781394SAxel Lin if (rc < 0) { 1170668d306SStephen Boyd devres_free(dr); 1180668d306SStephen Boyd return rc; 1190668d306SStephen Boyd } 1200668d306SStephen Boyd 1210668d306SStephen Boyd dr->irq = irq; 1220668d306SStephen Boyd dr->dev_id = dev_id; 1230668d306SStephen Boyd devres_add(dev, dr); 1240668d306SStephen Boyd 12563781394SAxel Lin return rc; 1260668d306SStephen Boyd } 1270668d306SStephen Boyd EXPORT_SYMBOL(devm_request_any_context_irq); 1280668d306SStephen Boyd 1290668d306SStephen Boyd /** 1305ea81769SAl Viro * devm_free_irq - free an interrupt 1315ea81769SAl Viro * @dev: device to free interrupt for 1325ea81769SAl Viro * @irq: Interrupt line to free 1335ea81769SAl Viro * @dev_id: Device identity to free 1345ea81769SAl Viro * 1355ea81769SAl Viro * Except for the extra @dev argument, this function takes the 1365ea81769SAl Viro * same arguments and performs the same function as free_irq(). 1375ea81769SAl Viro * This function instead of free_irq() should be used to manually 1389ce8e498SBaruch Siach * free IRQs allocated with devm_request_irq(). 1395ea81769SAl Viro */ 1405ea81769SAl Viro void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id) 1415ea81769SAl Viro { 1425ea81769SAl Viro struct irq_devres match_data = { irq, dev_id }; 1435ea81769SAl Viro 1445ea81769SAl Viro WARN_ON(devres_destroy(dev, devm_irq_release, devm_irq_match, 1455ea81769SAl Viro &match_data)); 146ae891a1bSMaxin B John free_irq(irq, dev_id); 1475ea81769SAl Viro } 1485ea81769SAl Viro EXPORT_SYMBOL(devm_free_irq); 1492b5e7730SBartosz Golaszewski 1502b5e7730SBartosz Golaszewski struct irq_desc_devres { 1512b5e7730SBartosz Golaszewski unsigned int from; 1522b5e7730SBartosz Golaszewski unsigned int cnt; 1532b5e7730SBartosz Golaszewski }; 1542b5e7730SBartosz Golaszewski 1552b5e7730SBartosz Golaszewski static void devm_irq_desc_release(struct device *dev, void *res) 1562b5e7730SBartosz Golaszewski { 1572b5e7730SBartosz Golaszewski struct irq_desc_devres *this = res; 1582b5e7730SBartosz Golaszewski 1592b5e7730SBartosz Golaszewski irq_free_descs(this->from, this->cnt); 1602b5e7730SBartosz Golaszewski } 1612b5e7730SBartosz Golaszewski 1622b5e7730SBartosz Golaszewski /** 1632b5e7730SBartosz Golaszewski * __devm_irq_alloc_descs - Allocate and initialize a range of irq descriptors 1642b5e7730SBartosz Golaszewski * for a managed device 1652b5e7730SBartosz Golaszewski * @dev: Device to allocate the descriptors for 1662b5e7730SBartosz Golaszewski * @irq: Allocate for specific irq number if irq >= 0 1672b5e7730SBartosz Golaszewski * @from: Start the search from this irq number 1682b5e7730SBartosz Golaszewski * @cnt: Number of consecutive irqs to allocate 1692b5e7730SBartosz Golaszewski * @node: Preferred node on which the irq descriptor should be allocated 1702b5e7730SBartosz Golaszewski * @owner: Owning module (can be NULL) 1712b5e7730SBartosz Golaszewski * @affinity: Optional pointer to an affinity mask array of size @cnt 1722b5e7730SBartosz Golaszewski * which hints where the irq descriptors should be allocated 1732b5e7730SBartosz Golaszewski * and which default affinities to use 1742b5e7730SBartosz Golaszewski * 1752b5e7730SBartosz Golaszewski * Returns the first irq number or error code. 1762b5e7730SBartosz Golaszewski * 1772b5e7730SBartosz Golaszewski * Note: Use the provided wrappers (devm_irq_alloc_desc*) for simplicity. 1782b5e7730SBartosz Golaszewski */ 1792b5e7730SBartosz Golaszewski int __devm_irq_alloc_descs(struct device *dev, int irq, unsigned int from, 1802b5e7730SBartosz Golaszewski unsigned int cnt, int node, struct module *owner, 1812b5e7730SBartosz Golaszewski const struct cpumask *affinity) 1822b5e7730SBartosz Golaszewski { 1832b5e7730SBartosz Golaszewski struct irq_desc_devres *dr; 1842b5e7730SBartosz Golaszewski int base; 1852b5e7730SBartosz Golaszewski 1862b5e7730SBartosz Golaszewski dr = devres_alloc(devm_irq_desc_release, sizeof(*dr), GFP_KERNEL); 1872b5e7730SBartosz Golaszewski if (!dr) 1882b5e7730SBartosz Golaszewski return -ENOMEM; 1892b5e7730SBartosz Golaszewski 1902b5e7730SBartosz Golaszewski base = __irq_alloc_descs(irq, from, cnt, node, owner, affinity); 1912b5e7730SBartosz Golaszewski if (base < 0) { 1922b5e7730SBartosz Golaszewski devres_free(dr); 1932b5e7730SBartosz Golaszewski return base; 1942b5e7730SBartosz Golaszewski } 1952b5e7730SBartosz Golaszewski 1962b5e7730SBartosz Golaszewski dr->from = base; 1972b5e7730SBartosz Golaszewski dr->cnt = cnt; 1982b5e7730SBartosz Golaszewski devres_add(dev, dr); 1992b5e7730SBartosz Golaszewski 2002b5e7730SBartosz Golaszewski return base; 2012b5e7730SBartosz Golaszewski } 2022b5e7730SBartosz Golaszewski EXPORT_SYMBOL_GPL(__devm_irq_alloc_descs); 2031c3e3630SBartosz Golaszewski 2041c3e3630SBartosz Golaszewski #ifdef CONFIG_GENERIC_IRQ_CHIP 2051c3e3630SBartosz Golaszewski /** 2061c3e3630SBartosz Golaszewski * devm_irq_alloc_generic_chip - Allocate and initialize a generic chip 2071c3e3630SBartosz Golaszewski * for a managed device 2081c3e3630SBartosz Golaszewski * @dev: Device to allocate the generic chip for 2091c3e3630SBartosz Golaszewski * @name: Name of the irq chip 2101c3e3630SBartosz Golaszewski * @num_ct: Number of irq_chip_type instances associated with this 2111c3e3630SBartosz Golaszewski * @irq_base: Interrupt base nr for this chip 2121c3e3630SBartosz Golaszewski * @reg_base: Register base address (virtual) 2131c3e3630SBartosz Golaszewski * @handler: Default flow handler associated with this chip 2141c3e3630SBartosz Golaszewski * 2151c3e3630SBartosz Golaszewski * Returns an initialized irq_chip_generic structure. The chip defaults 2161c3e3630SBartosz Golaszewski * to the primary (index 0) irq_chip_type and @handler 2171c3e3630SBartosz Golaszewski */ 2181c3e3630SBartosz Golaszewski struct irq_chip_generic * 2191c3e3630SBartosz Golaszewski devm_irq_alloc_generic_chip(struct device *dev, const char *name, int num_ct, 2201c3e3630SBartosz Golaszewski unsigned int irq_base, void __iomem *reg_base, 2211c3e3630SBartosz Golaszewski irq_flow_handler_t handler) 2221c3e3630SBartosz Golaszewski { 2231c3e3630SBartosz Golaszewski struct irq_chip_generic *gc; 2241c3e3630SBartosz Golaszewski unsigned long sz = sizeof(*gc) + num_ct * sizeof(struct irq_chip_type); 2251c3e3630SBartosz Golaszewski 2261c3e3630SBartosz Golaszewski gc = devm_kzalloc(dev, sz, GFP_KERNEL); 2271c3e3630SBartosz Golaszewski if (gc) 2281c3e3630SBartosz Golaszewski irq_init_generic_chip(gc, name, num_ct, 2291c3e3630SBartosz Golaszewski irq_base, reg_base, handler); 2301c3e3630SBartosz Golaszewski 2311c3e3630SBartosz Golaszewski return gc; 2321c3e3630SBartosz Golaszewski } 2331c3e3630SBartosz Golaszewski EXPORT_SYMBOL_GPL(devm_irq_alloc_generic_chip); 2341c3e3630SBartosz Golaszewski #endif /* CONFIG_GENERIC_IRQ_CHIP */ 235