xref: /openbmc/linux/kernel/irq/devres.c (revision 2d65c42b)
152a65ff5SThomas Gleixner // SPDX-License-Identifier: GPL-2.0
25ea81769SAl Viro #include <linux/module.h>
35ea81769SAl Viro #include <linux/interrupt.h>
40af3678fSAl Viro #include <linux/device.h>
51aeb272cSRobert P. J. Day #include <linux/gfp.h>
62b5e7730SBartosz Golaszewski #include <linux/irq.h>
75ea81769SAl Viro 
81c3e3630SBartosz Golaszewski #include "internals.h"
91c3e3630SBartosz Golaszewski 
105ea81769SAl Viro /*
115ea81769SAl Viro  * Device resource management aware IRQ request/free implementation.
125ea81769SAl Viro  */
135ea81769SAl Viro struct irq_devres {
145ea81769SAl Viro 	unsigned int irq;
155ea81769SAl Viro 	void *dev_id;
165ea81769SAl Viro };
175ea81769SAl Viro 
devm_irq_release(struct device * dev,void * res)185ea81769SAl Viro static void devm_irq_release(struct device *dev, void *res)
195ea81769SAl Viro {
205ea81769SAl Viro 	struct irq_devres *this = res;
215ea81769SAl Viro 
225ea81769SAl Viro 	free_irq(this->irq, this->dev_id);
235ea81769SAl Viro }
245ea81769SAl Viro 
devm_irq_match(struct device * dev,void * res,void * data)255ea81769SAl Viro static int devm_irq_match(struct device *dev, void *res, void *data)
265ea81769SAl Viro {
275ea81769SAl Viro 	struct irq_devres *this = res, *match = data;
285ea81769SAl Viro 
295ea81769SAl Viro 	return this->irq == match->irq && this->dev_id == match->dev_id;
305ea81769SAl Viro }
315ea81769SAl Viro 
325ea81769SAl Viro /**
33935bd5b9SArjan van de Ven  *	devm_request_threaded_irq - allocate an interrupt line for a managed device
345ea81769SAl Viro  *	@dev: device to request interrupt for
355ea81769SAl Viro  *	@irq: Interrupt line to allocate
365ea81769SAl Viro  *	@handler: Function to be called when the IRQ occurs
37935bd5b9SArjan van de Ven  *	@thread_fn: function to be called in a threaded interrupt context. NULL
38935bd5b9SArjan van de Ven  *		    for devices which handle everything in @handler
395ea81769SAl Viro  *	@irqflags: Interrupt type flags
40899b5fbfSHeiner Kallweit  *	@devname: An ascii name for the claiming device, dev_name(dev) if NULL
415ea81769SAl Viro  *	@dev_id: A cookie passed back to the handler function
425ea81769SAl Viro  *
435ea81769SAl Viro  *	Except for the extra @dev argument, this function takes the
445ea81769SAl Viro  *	same arguments and performs the same function as
45307b28b9SEmilio López  *	request_threaded_irq().  IRQs requested with this function will be
465ea81769SAl Viro  *	automatically freed on driver detach.
475ea81769SAl Viro  *
485ea81769SAl Viro  *	If an IRQ allocated with this function needs to be freed
495c42dc70SJean Delvare  *	separately, devm_free_irq() must be used.
505ea81769SAl Viro  */
devm_request_threaded_irq(struct device * dev,unsigned int irq,irq_handler_t handler,irq_handler_t thread_fn,unsigned long irqflags,const char * devname,void * dev_id)51935bd5b9SArjan van de Ven int devm_request_threaded_irq(struct device *dev, unsigned int irq,
52935bd5b9SArjan van de Ven 			      irq_handler_t handler, irq_handler_t thread_fn,
53935bd5b9SArjan van de Ven 			      unsigned long irqflags, const char *devname,
54935bd5b9SArjan van de Ven 			      void *dev_id)
555ea81769SAl Viro {
565ea81769SAl Viro 	struct irq_devres *dr;
575ea81769SAl Viro 	int rc;
585ea81769SAl Viro 
595ea81769SAl Viro 	dr = devres_alloc(devm_irq_release, sizeof(struct irq_devres),
605ea81769SAl Viro 			  GFP_KERNEL);
615ea81769SAl Viro 	if (!dr)
625ea81769SAl Viro 		return -ENOMEM;
635ea81769SAl Viro 
64899b5fbfSHeiner Kallweit 	if (!devname)
65899b5fbfSHeiner Kallweit 		devname = dev_name(dev);
66899b5fbfSHeiner Kallweit 
67935bd5b9SArjan van de Ven 	rc = request_threaded_irq(irq, handler, thread_fn, irqflags, devname,
68935bd5b9SArjan van de Ven 				  dev_id);
695ea81769SAl Viro 	if (rc) {
707f30e49eSTejun Heo 		devres_free(dr);
715ea81769SAl Viro 		return rc;
725ea81769SAl Viro 	}
735ea81769SAl Viro 
745ea81769SAl Viro 	dr->irq = irq;
755ea81769SAl Viro 	dr->dev_id = dev_id;
765ea81769SAl Viro 	devres_add(dev, dr);
775ea81769SAl Viro 
785ea81769SAl Viro 	return 0;
795ea81769SAl Viro }
80935bd5b9SArjan van de Ven EXPORT_SYMBOL(devm_request_threaded_irq);
815ea81769SAl Viro 
825ea81769SAl Viro /**
830668d306SStephen Boyd  *	devm_request_any_context_irq - allocate an interrupt line for a managed device
840668d306SStephen Boyd  *	@dev: device to request interrupt for
850668d306SStephen Boyd  *	@irq: Interrupt line to allocate
860668d306SStephen Boyd  *	@handler: Function to be called when the IRQ occurs
870668d306SStephen Boyd  *	@irqflags: Interrupt type flags
88899b5fbfSHeiner Kallweit  *	@devname: An ascii name for the claiming device, dev_name(dev) if NULL
890668d306SStephen Boyd  *	@dev_id: A cookie passed back to the handler function
900668d306SStephen Boyd  *
910668d306SStephen Boyd  *	Except for the extra @dev argument, this function takes the
920668d306SStephen Boyd  *	same arguments and performs the same function as
930668d306SStephen Boyd  *	request_any_context_irq().  IRQs requested with this function will be
940668d306SStephen Boyd  *	automatically freed on driver detach.
950668d306SStephen Boyd  *
960668d306SStephen Boyd  *	If an IRQ allocated with this function needs to be freed
970668d306SStephen Boyd  *	separately, devm_free_irq() must be used.
980668d306SStephen Boyd  */
devm_request_any_context_irq(struct device * dev,unsigned int irq,irq_handler_t handler,unsigned long irqflags,const char * devname,void * dev_id)990668d306SStephen Boyd int devm_request_any_context_irq(struct device *dev, unsigned int irq,
1000668d306SStephen Boyd 			      irq_handler_t handler, unsigned long irqflags,
1010668d306SStephen Boyd 			      const char *devname, void *dev_id)
1020668d306SStephen Boyd {
1030668d306SStephen Boyd 	struct irq_devres *dr;
1040668d306SStephen Boyd 	int rc;
1050668d306SStephen Boyd 
1060668d306SStephen Boyd 	dr = devres_alloc(devm_irq_release, sizeof(struct irq_devres),
1070668d306SStephen Boyd 			  GFP_KERNEL);
1080668d306SStephen Boyd 	if (!dr)
1090668d306SStephen Boyd 		return -ENOMEM;
1100668d306SStephen Boyd 
111899b5fbfSHeiner Kallweit 	if (!devname)
112899b5fbfSHeiner Kallweit 		devname = dev_name(dev);
113899b5fbfSHeiner Kallweit 
1140668d306SStephen Boyd 	rc = request_any_context_irq(irq, handler, irqflags, devname, dev_id);
11563781394SAxel Lin 	if (rc < 0) {
1160668d306SStephen Boyd 		devres_free(dr);
1170668d306SStephen Boyd 		return rc;
1180668d306SStephen Boyd 	}
1190668d306SStephen Boyd 
1200668d306SStephen Boyd 	dr->irq = irq;
1210668d306SStephen Boyd 	dr->dev_id = dev_id;
1220668d306SStephen Boyd 	devres_add(dev, dr);
1230668d306SStephen Boyd 
12463781394SAxel Lin 	return rc;
1250668d306SStephen Boyd }
1260668d306SStephen Boyd EXPORT_SYMBOL(devm_request_any_context_irq);
1270668d306SStephen Boyd 
1280668d306SStephen Boyd /**
1295ea81769SAl Viro  *	devm_free_irq - free an interrupt
1305ea81769SAl Viro  *	@dev: device to free interrupt for
1315ea81769SAl Viro  *	@irq: Interrupt line to free
1325ea81769SAl Viro  *	@dev_id: Device identity to free
1335ea81769SAl Viro  *
1345ea81769SAl Viro  *	Except for the extra @dev argument, this function takes the
1355ea81769SAl Viro  *	same arguments and performs the same function as free_irq().
1365ea81769SAl Viro  *	This function instead of free_irq() should be used to manually
1379ce8e498SBaruch Siach  *	free IRQs allocated with devm_request_irq().
1385ea81769SAl Viro  */
devm_free_irq(struct device * dev,unsigned int irq,void * dev_id)1395ea81769SAl Viro void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id)
1405ea81769SAl Viro {
1415ea81769SAl Viro 	struct irq_devres match_data = { irq, dev_id };
1425ea81769SAl Viro 
1435ea81769SAl Viro 	WARN_ON(devres_destroy(dev, devm_irq_release, devm_irq_match,
1445ea81769SAl Viro 			       &match_data));
145ae891a1bSMaxin B John 	free_irq(irq, dev_id);
1465ea81769SAl Viro }
1475ea81769SAl Viro EXPORT_SYMBOL(devm_free_irq);
1482b5e7730SBartosz Golaszewski 
1492b5e7730SBartosz Golaszewski struct irq_desc_devres {
1502b5e7730SBartosz Golaszewski 	unsigned int from;
1512b5e7730SBartosz Golaszewski 	unsigned int cnt;
1522b5e7730SBartosz Golaszewski };
1532b5e7730SBartosz Golaszewski 
devm_irq_desc_release(struct device * dev,void * res)1542b5e7730SBartosz Golaszewski static void devm_irq_desc_release(struct device *dev, void *res)
1552b5e7730SBartosz Golaszewski {
1562b5e7730SBartosz Golaszewski 	struct irq_desc_devres *this = res;
1572b5e7730SBartosz Golaszewski 
1582b5e7730SBartosz Golaszewski 	irq_free_descs(this->from, this->cnt);
1592b5e7730SBartosz Golaszewski }
1602b5e7730SBartosz Golaszewski 
1612b5e7730SBartosz Golaszewski /**
1622b5e7730SBartosz Golaszewski  * __devm_irq_alloc_descs - Allocate and initialize a range of irq descriptors
1632b5e7730SBartosz Golaszewski  *			    for a managed device
1642b5e7730SBartosz Golaszewski  * @dev:	Device to allocate the descriptors for
1652b5e7730SBartosz Golaszewski  * @irq:	Allocate for specific irq number if irq >= 0
1662b5e7730SBartosz Golaszewski  * @from:	Start the search from this irq number
1672b5e7730SBartosz Golaszewski  * @cnt:	Number of consecutive irqs to allocate
1682b5e7730SBartosz Golaszewski  * @node:	Preferred node on which the irq descriptor should be allocated
1692b5e7730SBartosz Golaszewski  * @owner:	Owning module (can be NULL)
170bec04037SDou Liyang  * @affinity:	Optional pointer to an irq_affinity_desc array of size @cnt
1712b5e7730SBartosz Golaszewski  *		which hints where the irq descriptors should be allocated
1722b5e7730SBartosz Golaszewski  *		and which default affinities to use
1732b5e7730SBartosz Golaszewski  *
1742b5e7730SBartosz Golaszewski  * Returns the first irq number or error code.
1752b5e7730SBartosz Golaszewski  *
1762b5e7730SBartosz Golaszewski  * Note: Use the provided wrappers (devm_irq_alloc_desc*) for simplicity.
1772b5e7730SBartosz Golaszewski  */
__devm_irq_alloc_descs(struct device * dev,int irq,unsigned int from,unsigned int cnt,int node,struct module * owner,const struct irq_affinity_desc * affinity)1782b5e7730SBartosz Golaszewski int __devm_irq_alloc_descs(struct device *dev, int irq, unsigned int from,
1792b5e7730SBartosz Golaszewski 			   unsigned int cnt, int node, struct module *owner,
180bec04037SDou Liyang 			   const struct irq_affinity_desc *affinity)
1812b5e7730SBartosz Golaszewski {
1822b5e7730SBartosz Golaszewski 	struct irq_desc_devres *dr;
1832b5e7730SBartosz Golaszewski 	int base;
1842b5e7730SBartosz Golaszewski 
1852b5e7730SBartosz Golaszewski 	dr = devres_alloc(devm_irq_desc_release, sizeof(*dr), GFP_KERNEL);
1862b5e7730SBartosz Golaszewski 	if (!dr)
1872b5e7730SBartosz Golaszewski 		return -ENOMEM;
1882b5e7730SBartosz Golaszewski 
1892b5e7730SBartosz Golaszewski 	base = __irq_alloc_descs(irq, from, cnt, node, owner, affinity);
1902b5e7730SBartosz Golaszewski 	if (base < 0) {
1912b5e7730SBartosz Golaszewski 		devres_free(dr);
1922b5e7730SBartosz Golaszewski 		return base;
1932b5e7730SBartosz Golaszewski 	}
1942b5e7730SBartosz Golaszewski 
1952b5e7730SBartosz Golaszewski 	dr->from = base;
1962b5e7730SBartosz Golaszewski 	dr->cnt = cnt;
1972b5e7730SBartosz Golaszewski 	devres_add(dev, dr);
1982b5e7730SBartosz Golaszewski 
1992b5e7730SBartosz Golaszewski 	return base;
2002b5e7730SBartosz Golaszewski }
2012b5e7730SBartosz Golaszewski EXPORT_SYMBOL_GPL(__devm_irq_alloc_descs);
2021c3e3630SBartosz Golaszewski 
2031c3e3630SBartosz Golaszewski #ifdef CONFIG_GENERIC_IRQ_CHIP
2041c3e3630SBartosz Golaszewski /**
2051c3e3630SBartosz Golaszewski  * devm_irq_alloc_generic_chip - Allocate and initialize a generic chip
2061c3e3630SBartosz Golaszewski  *                               for a managed device
2071c3e3630SBartosz Golaszewski  * @dev:	Device to allocate the generic chip for
2081c3e3630SBartosz Golaszewski  * @name:	Name of the irq chip
2091c3e3630SBartosz Golaszewski  * @num_ct:	Number of irq_chip_type instances associated with this
2101c3e3630SBartosz Golaszewski  * @irq_base:	Interrupt base nr for this chip
2111c3e3630SBartosz Golaszewski  * @reg_base:	Register base address (virtual)
2121c3e3630SBartosz Golaszewski  * @handler:	Default flow handler associated with this chip
2131c3e3630SBartosz Golaszewski  *
2141c3e3630SBartosz Golaszewski  * Returns an initialized irq_chip_generic structure. The chip defaults
2151c3e3630SBartosz Golaszewski  * to the primary (index 0) irq_chip_type and @handler
2161c3e3630SBartosz Golaszewski  */
2171c3e3630SBartosz Golaszewski struct irq_chip_generic *
devm_irq_alloc_generic_chip(struct device * dev,const char * name,int num_ct,unsigned int irq_base,void __iomem * reg_base,irq_flow_handler_t handler)2181c3e3630SBartosz Golaszewski devm_irq_alloc_generic_chip(struct device *dev, const char *name, int num_ct,
2191c3e3630SBartosz Golaszewski 			    unsigned int irq_base, void __iomem *reg_base,
2201c3e3630SBartosz Golaszewski 			    irq_flow_handler_t handler)
2211c3e3630SBartosz Golaszewski {
2221c3e3630SBartosz Golaszewski 	struct irq_chip_generic *gc;
2231c3e3630SBartosz Golaszewski 
2242d65c42bSGustavo A. R. Silva 	gc = devm_kzalloc(dev, struct_size(gc, chip_types, num_ct), GFP_KERNEL);
2251c3e3630SBartosz Golaszewski 	if (gc)
2261c3e3630SBartosz Golaszewski 		irq_init_generic_chip(gc, name, num_ct,
2271c3e3630SBartosz Golaszewski 				      irq_base, reg_base, handler);
2281c3e3630SBartosz Golaszewski 
2291c3e3630SBartosz Golaszewski 	return gc;
2301c3e3630SBartosz Golaszewski }
2311c3e3630SBartosz Golaszewski EXPORT_SYMBOL_GPL(devm_irq_alloc_generic_chip);
23230fd8fc5SBartosz Golaszewski 
23330fd8fc5SBartosz Golaszewski struct irq_generic_chip_devres {
23430fd8fc5SBartosz Golaszewski 	struct irq_chip_generic *gc;
23530fd8fc5SBartosz Golaszewski 	u32 msk;
23630fd8fc5SBartosz Golaszewski 	unsigned int clr;
23730fd8fc5SBartosz Golaszewski 	unsigned int set;
23830fd8fc5SBartosz Golaszewski };
23930fd8fc5SBartosz Golaszewski 
devm_irq_remove_generic_chip(struct device * dev,void * res)24030fd8fc5SBartosz Golaszewski static void devm_irq_remove_generic_chip(struct device *dev, void *res)
24130fd8fc5SBartosz Golaszewski {
24230fd8fc5SBartosz Golaszewski 	struct irq_generic_chip_devres *this = res;
24330fd8fc5SBartosz Golaszewski 
24430fd8fc5SBartosz Golaszewski 	irq_remove_generic_chip(this->gc, this->msk, this->clr, this->set);
24530fd8fc5SBartosz Golaszewski }
24630fd8fc5SBartosz Golaszewski 
24730fd8fc5SBartosz Golaszewski /**
24830fd8fc5SBartosz Golaszewski  * devm_irq_setup_generic_chip - Setup a range of interrupts with a generic
24930fd8fc5SBartosz Golaszewski  *                               chip for a managed device
25030fd8fc5SBartosz Golaszewski  *
25130fd8fc5SBartosz Golaszewski  * @dev:	Device to setup the generic chip for
25230fd8fc5SBartosz Golaszewski  * @gc:		Generic irq chip holding all data
25330fd8fc5SBartosz Golaszewski  * @msk:	Bitmask holding the irqs to initialize relative to gc->irq_base
25430fd8fc5SBartosz Golaszewski  * @flags:	Flags for initialization
25530fd8fc5SBartosz Golaszewski  * @clr:	IRQ_* bits to clear
25630fd8fc5SBartosz Golaszewski  * @set:	IRQ_* bits to set
25730fd8fc5SBartosz Golaszewski  *
25830fd8fc5SBartosz Golaszewski  * Set up max. 32 interrupts starting from gc->irq_base. Note, this
25930fd8fc5SBartosz Golaszewski  * initializes all interrupts to the primary irq_chip_type and its
26030fd8fc5SBartosz Golaszewski  * associated handler.
26130fd8fc5SBartosz Golaszewski  */
devm_irq_setup_generic_chip(struct device * dev,struct irq_chip_generic * gc,u32 msk,enum irq_gc_flags flags,unsigned int clr,unsigned int set)26230fd8fc5SBartosz Golaszewski int devm_irq_setup_generic_chip(struct device *dev, struct irq_chip_generic *gc,
26330fd8fc5SBartosz Golaszewski 				u32 msk, enum irq_gc_flags flags,
26430fd8fc5SBartosz Golaszewski 				unsigned int clr, unsigned int set)
26530fd8fc5SBartosz Golaszewski {
26630fd8fc5SBartosz Golaszewski 	struct irq_generic_chip_devres *dr;
26730fd8fc5SBartosz Golaszewski 
26830fd8fc5SBartosz Golaszewski 	dr = devres_alloc(devm_irq_remove_generic_chip,
26930fd8fc5SBartosz Golaszewski 			  sizeof(*dr), GFP_KERNEL);
27030fd8fc5SBartosz Golaszewski 	if (!dr)
27130fd8fc5SBartosz Golaszewski 		return -ENOMEM;
27230fd8fc5SBartosz Golaszewski 
27330fd8fc5SBartosz Golaszewski 	irq_setup_generic_chip(gc, msk, flags, clr, set);
27430fd8fc5SBartosz Golaszewski 
27530fd8fc5SBartosz Golaszewski 	dr->gc = gc;
27630fd8fc5SBartosz Golaszewski 	dr->msk = msk;
27730fd8fc5SBartosz Golaszewski 	dr->clr = clr;
27830fd8fc5SBartosz Golaszewski 	dr->set = set;
27930fd8fc5SBartosz Golaszewski 	devres_add(dev, dr);
28030fd8fc5SBartosz Golaszewski 
28130fd8fc5SBartosz Golaszewski 	return 0;
28230fd8fc5SBartosz Golaszewski }
28330fd8fc5SBartosz Golaszewski EXPORT_SYMBOL_GPL(devm_irq_setup_generic_chip);
2841c3e3630SBartosz Golaszewski #endif /* CONFIG_GENERIC_IRQ_CHIP */
285