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