xref: /openbmc/linux/drivers/of/irq.c (revision 4800cd83)
1  /*
2   *  Derived from arch/i386/kernel/irq.c
3   *    Copyright (C) 1992 Linus Torvalds
4   *  Adapted from arch/i386 by Gary Thomas
5   *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
6   *  Updated and modified by Cort Dougan <cort@fsmlabs.com>
7   *    Copyright (C) 1996-2001 Cort Dougan
8   *  Adapted for Power Macintosh by Paul Mackerras
9   *    Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
10   *
11   * This program is free software; you can redistribute it and/or
12   * modify it under the terms of the GNU General Public License
13   * as published by the Free Software Foundation; either version
14   * 2 of the License, or (at your option) any later version.
15   *
16   * This file contains the code used to make IRQ descriptions in the
17   * device tree to actual irq numbers on an interrupt controller
18   * driver.
19   */
20  
21  #include <linux/errno.h>
22  #include <linux/module.h>
23  #include <linux/of.h>
24  #include <linux/of_irq.h>
25  #include <linux/string.h>
26  
27  /* For archs that don't support NO_IRQ (such as x86), provide a dummy value */
28  #ifndef NO_IRQ
29  #define NO_IRQ 0
30  #endif
31  
32  /**
33   * irq_of_parse_and_map - Parse and map an interrupt into linux virq space
34   * @device: Device node of the device whose interrupt is to be mapped
35   * @index: Index of the interrupt to map
36   *
37   * This function is a wrapper that chains of_irq_map_one() and
38   * irq_create_of_mapping() to make things easier to callers
39   */
40  unsigned int irq_of_parse_and_map(struct device_node *dev, int index)
41  {
42  	struct of_irq oirq;
43  
44  	if (of_irq_map_one(dev, index, &oirq))
45  		return NO_IRQ;
46  
47  	return irq_create_of_mapping(oirq.controller, oirq.specifier,
48  				     oirq.size);
49  }
50  EXPORT_SYMBOL_GPL(irq_of_parse_and_map);
51  
52  /**
53   * of_irq_find_parent - Given a device node, find its interrupt parent node
54   * @child: pointer to device node
55   *
56   * Returns a pointer to the interrupt parent node, or NULL if the interrupt
57   * parent could not be determined.
58   */
59  static struct device_node *of_irq_find_parent(struct device_node *child)
60  {
61  	struct device_node *p;
62  	const __be32 *parp;
63  
64  	if (!of_node_get(child))
65  		return NULL;
66  
67  	do {
68  		parp = of_get_property(child, "interrupt-parent", NULL);
69  		if (parp == NULL)
70  			p = of_get_parent(child);
71  		else {
72  			if (of_irq_workarounds & OF_IMAP_NO_PHANDLE)
73  				p = of_node_get(of_irq_dflt_pic);
74  			else
75  				p = of_find_node_by_phandle(be32_to_cpup(parp));
76  		}
77  		of_node_put(child);
78  		child = p;
79  	} while (p && of_get_property(p, "#interrupt-cells", NULL) == NULL);
80  
81  	return p;
82  }
83  
84  /**
85   * of_irq_map_raw - Low level interrupt tree parsing
86   * @parent:	the device interrupt parent
87   * @intspec:	interrupt specifier ("interrupts" property of the device)
88   * @ointsize:   size of the passed in interrupt specifier
89   * @addr:	address specifier (start of "reg" property of the device)
90   * @out_irq:	structure of_irq filled by this function
91   *
92   * Returns 0 on success and a negative number on error
93   *
94   * This function is a low-level interrupt tree walking function. It
95   * can be used to do a partial walk with synthetized reg and interrupts
96   * properties, for example when resolving PCI interrupts when no device
97   * node exist for the parent.
98   */
99  int of_irq_map_raw(struct device_node *parent, const __be32 *intspec,
100  		   u32 ointsize, const __be32 *addr, struct of_irq *out_irq)
101  {
102  	struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL;
103  	const __be32 *tmp, *imap, *imask;
104  	u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0;
105  	int imaplen, match, i;
106  
107  	pr_debug("of_irq_map_raw: par=%s,intspec=[0x%08x 0x%08x...],ointsize=%d\n",
108  		 parent->full_name, be32_to_cpup(intspec),
109  		 be32_to_cpup(intspec + 1), ointsize);
110  
111  	ipar = of_node_get(parent);
112  
113  	/* First get the #interrupt-cells property of the current cursor
114  	 * that tells us how to interpret the passed-in intspec. If there
115  	 * is none, we are nice and just walk up the tree
116  	 */
117  	do {
118  		tmp = of_get_property(ipar, "#interrupt-cells", NULL);
119  		if (tmp != NULL) {
120  			intsize = be32_to_cpu(*tmp);
121  			break;
122  		}
123  		tnode = ipar;
124  		ipar = of_irq_find_parent(ipar);
125  		of_node_put(tnode);
126  	} while (ipar);
127  	if (ipar == NULL) {
128  		pr_debug(" -> no parent found !\n");
129  		goto fail;
130  	}
131  
132  	pr_debug("of_irq_map_raw: ipar=%s, size=%d\n", ipar->full_name, intsize);
133  
134  	if (ointsize != intsize)
135  		return -EINVAL;
136  
137  	/* Look for this #address-cells. We have to implement the old linux
138  	 * trick of looking for the parent here as some device-trees rely on it
139  	 */
140  	old = of_node_get(ipar);
141  	do {
142  		tmp = of_get_property(old, "#address-cells", NULL);
143  		tnode = of_get_parent(old);
144  		of_node_put(old);
145  		old = tnode;
146  	} while (old && tmp == NULL);
147  	of_node_put(old);
148  	old = NULL;
149  	addrsize = (tmp == NULL) ? 2 : be32_to_cpu(*tmp);
150  
151  	pr_debug(" -> addrsize=%d\n", addrsize);
152  
153  	/* Now start the actual "proper" walk of the interrupt tree */
154  	while (ipar != NULL) {
155  		/* Now check if cursor is an interrupt-controller and if it is
156  		 * then we are done
157  		 */
158  		if (of_get_property(ipar, "interrupt-controller", NULL) !=
159  				NULL) {
160  			pr_debug(" -> got it !\n");
161  			for (i = 0; i < intsize; i++)
162  				out_irq->specifier[i] =
163  						of_read_number(intspec +i, 1);
164  			out_irq->size = intsize;
165  			out_irq->controller = ipar;
166  			of_node_put(old);
167  			return 0;
168  		}
169  
170  		/* Now look for an interrupt-map */
171  		imap = of_get_property(ipar, "interrupt-map", &imaplen);
172  		/* No interrupt map, check for an interrupt parent */
173  		if (imap == NULL) {
174  			pr_debug(" -> no map, getting parent\n");
175  			newpar = of_irq_find_parent(ipar);
176  			goto skiplevel;
177  		}
178  		imaplen /= sizeof(u32);
179  
180  		/* Look for a mask */
181  		imask = of_get_property(ipar, "interrupt-map-mask", NULL);
182  
183  		/* If we were passed no "reg" property and we attempt to parse
184  		 * an interrupt-map, then #address-cells must be 0.
185  		 * Fail if it's not.
186  		 */
187  		if (addr == NULL && addrsize != 0) {
188  			pr_debug(" -> no reg passed in when needed !\n");
189  			goto fail;
190  		}
191  
192  		/* Parse interrupt-map */
193  		match = 0;
194  		while (imaplen > (addrsize + intsize + 1) && !match) {
195  			/* Compare specifiers */
196  			match = 1;
197  			for (i = 0; i < addrsize && match; ++i) {
198  				u32 mask = imask ? imask[i] : 0xffffffffu;
199  				match = ((addr[i] ^ imap[i]) & mask) == 0;
200  			}
201  			for (; i < (addrsize + intsize) && match; ++i) {
202  				u32 mask = imask ? imask[i] : 0xffffffffu;
203  				match =
204  				   ((intspec[i-addrsize] ^ imap[i]) & mask) == 0;
205  			}
206  			imap += addrsize + intsize;
207  			imaplen -= addrsize + intsize;
208  
209  			pr_debug(" -> match=%d (imaplen=%d)\n", match, imaplen);
210  
211  			/* Get the interrupt parent */
212  			if (of_irq_workarounds & OF_IMAP_NO_PHANDLE)
213  				newpar = of_node_get(of_irq_dflt_pic);
214  			else
215  				newpar = of_find_node_by_phandle(be32_to_cpup(imap));
216  			imap++;
217  			--imaplen;
218  
219  			/* Check if not found */
220  			if (newpar == NULL) {
221  				pr_debug(" -> imap parent not found !\n");
222  				goto fail;
223  			}
224  
225  			/* Get #interrupt-cells and #address-cells of new
226  			 * parent
227  			 */
228  			tmp = of_get_property(newpar, "#interrupt-cells", NULL);
229  			if (tmp == NULL) {
230  				pr_debug(" -> parent lacks #interrupt-cells!\n");
231  				goto fail;
232  			}
233  			newintsize = be32_to_cpu(*tmp);
234  			tmp = of_get_property(newpar, "#address-cells", NULL);
235  			newaddrsize = (tmp == NULL) ? 0 : be32_to_cpu(*tmp);
236  
237  			pr_debug(" -> newintsize=%d, newaddrsize=%d\n",
238  			    newintsize, newaddrsize);
239  
240  			/* Check for malformed properties */
241  			if (imaplen < (newaddrsize + newintsize))
242  				goto fail;
243  
244  			imap += newaddrsize + newintsize;
245  			imaplen -= newaddrsize + newintsize;
246  
247  			pr_debug(" -> imaplen=%d\n", imaplen);
248  		}
249  		if (!match)
250  			goto fail;
251  
252  		of_node_put(old);
253  		old = of_node_get(newpar);
254  		addrsize = newaddrsize;
255  		intsize = newintsize;
256  		intspec = imap - intsize;
257  		addr = intspec - addrsize;
258  
259  	skiplevel:
260  		/* Iterate again with new parent */
261  		pr_debug(" -> new parent: %s\n", newpar ? newpar->full_name : "<>");
262  		of_node_put(ipar);
263  		ipar = newpar;
264  		newpar = NULL;
265  	}
266   fail:
267  	of_node_put(ipar);
268  	of_node_put(old);
269  	of_node_put(newpar);
270  
271  	return -EINVAL;
272  }
273  EXPORT_SYMBOL_GPL(of_irq_map_raw);
274  
275  /**
276   * of_irq_map_one - Resolve an interrupt for a device
277   * @device: the device whose interrupt is to be resolved
278   * @index: index of the interrupt to resolve
279   * @out_irq: structure of_irq filled by this function
280   *
281   * This function resolves an interrupt, walking the tree, for a given
282   * device-tree node. It's the high level pendant to of_irq_map_raw().
283   */
284  int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq)
285  {
286  	struct device_node *p;
287  	const __be32 *intspec, *tmp, *addr;
288  	u32 intsize, intlen;
289  	int res = -EINVAL;
290  
291  	pr_debug("of_irq_map_one: dev=%s, index=%d\n", device->full_name, index);
292  
293  	/* OldWorld mac stuff is "special", handle out of line */
294  	if (of_irq_workarounds & OF_IMAP_OLDWORLD_MAC)
295  		return of_irq_map_oldworld(device, index, out_irq);
296  
297  	/* Get the interrupts property */
298  	intspec = of_get_property(device, "interrupts", &intlen);
299  	if (intspec == NULL)
300  		return -EINVAL;
301  	intlen /= sizeof(*intspec);
302  
303  	pr_debug(" intspec=%d intlen=%d\n", be32_to_cpup(intspec), intlen);
304  
305  	/* Get the reg property (if any) */
306  	addr = of_get_property(device, "reg", NULL);
307  
308  	/* Look for the interrupt parent. */
309  	p = of_irq_find_parent(device);
310  	if (p == NULL)
311  		return -EINVAL;
312  
313  	/* Get size of interrupt specifier */
314  	tmp = of_get_property(p, "#interrupt-cells", NULL);
315  	if (tmp == NULL)
316  		goto out;
317  	intsize = be32_to_cpu(*tmp);
318  
319  	pr_debug(" intsize=%d intlen=%d\n", intsize, intlen);
320  
321  	/* Check index */
322  	if ((index + 1) * intsize > intlen)
323  		goto out;
324  
325  	/* Get new specifier and map it */
326  	res = of_irq_map_raw(p, intspec + index * intsize, intsize,
327  			     addr, out_irq);
328   out:
329  	of_node_put(p);
330  	return res;
331  }
332  EXPORT_SYMBOL_GPL(of_irq_map_one);
333  
334  /**
335   * of_irq_to_resource - Decode a node's IRQ and return it as a resource
336   * @dev: pointer to device tree node
337   * @index: zero-based index of the irq
338   * @r: pointer to resource structure to return result into.
339   */
340  int of_irq_to_resource(struct device_node *dev, int index, struct resource *r)
341  {
342  	int irq = irq_of_parse_and_map(dev, index);
343  
344  	/* Only dereference the resource if both the
345  	 * resource and the irq are valid. */
346  	if (r && irq != NO_IRQ) {
347  		r->start = r->end = irq;
348  		r->flags = IORESOURCE_IRQ;
349  		r->name = dev->full_name;
350  	}
351  
352  	return irq;
353  }
354  EXPORT_SYMBOL_GPL(of_irq_to_resource);
355  
356  /**
357   * of_irq_count - Count the number of IRQs a node uses
358   * @dev: pointer to device tree node
359   */
360  int of_irq_count(struct device_node *dev)
361  {
362  	int nr = 0;
363  
364  	while (of_irq_to_resource(dev, nr, NULL) != NO_IRQ)
365  		nr++;
366  
367  	return nr;
368  }
369  
370  /**
371   * of_irq_to_resource_table - Fill in resource table with node's IRQ info
372   * @dev: pointer to device tree node
373   * @res: array of resources to fill in
374   * @nr_irqs: the number of IRQs (and upper bound for num of @res elements)
375   *
376   * Returns the size of the filled in table (up to @nr_irqs).
377   */
378  int of_irq_to_resource_table(struct device_node *dev, struct resource *res,
379  		int nr_irqs)
380  {
381  	int i;
382  
383  	for (i = 0; i < nr_irqs; i++, res++)
384  		if (of_irq_to_resource(dev, i, res) == NO_IRQ)
385  			break;
386  
387  	return i;
388  }
389