Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
irq.c
Go to the documentation of this file.
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 ([email protected])
6  * Updated and modified by Cort Dougan <[email protected]>
7  * Copyright (C) 1996-2001 Cort Dougan
8  * Adapted for Power Macintosh by Paul Mackerras
9  * Copyright (C) 1996 Paul Mackerras ([email protected])
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/list.h>
23 #include <linux/module.h>
24 #include <linux/of.h>
25 #include <linux/of_irq.h>
26 #include <linux/string.h>
27 #include <linux/slab.h>
28 
37 unsigned int irq_of_parse_and_map(struct device_node *dev, int index)
38 {
39  struct of_irq oirq;
40 
41  if (of_irq_map_one(dev, index, &oirq))
42  return 0;
43 
44  return irq_create_of_mapping(oirq.controller, oirq.specifier,
45  oirq.size);
46 }
48 
57 {
58  struct device_node *p;
59  const __be32 *parp;
60 
61  if (!of_node_get(child))
62  return NULL;
63 
64  do {
65  parp = of_get_property(child, "interrupt-parent", NULL);
66  if (parp == NULL)
67  p = of_get_parent(child);
68  else {
69  if (of_irq_workarounds & OF_IMAP_NO_PHANDLE)
70  p = of_node_get(of_irq_dflt_pic);
71  else
73  }
74  of_node_put(child);
75  child = p;
76  } while (p && of_get_property(p, "#interrupt-cells", NULL) == NULL);
77 
78  return p;
79 }
80 
96 int of_irq_map_raw(struct device_node *parent, const __be32 *intspec,
97  u32 ointsize, const __be32 *addr, struct of_irq *out_irq)
98 {
99  struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL;
100  const __be32 *tmp, *imap, *imask;
101  u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0;
102  int imaplen, match, i;
103 
104  pr_debug("of_irq_map_raw: par=%s,intspec=[0x%08x 0x%08x...],ointsize=%d\n",
105  parent->full_name, be32_to_cpup(intspec),
106  be32_to_cpup(intspec + 1), ointsize);
107 
108  ipar = of_node_get(parent);
109 
110  /* First get the #interrupt-cells property of the current cursor
111  * that tells us how to interpret the passed-in intspec. If there
112  * is none, we are nice and just walk up the tree
113  */
114  do {
115  tmp = of_get_property(ipar, "#interrupt-cells", NULL);
116  if (tmp != NULL) {
117  intsize = be32_to_cpu(*tmp);
118  break;
119  }
120  tnode = ipar;
121  ipar = of_irq_find_parent(ipar);
122  of_node_put(tnode);
123  } while (ipar);
124  if (ipar == NULL) {
125  pr_debug(" -> no parent found !\n");
126  goto fail;
127  }
128 
129  pr_debug("of_irq_map_raw: ipar=%s, size=%d\n", ipar->full_name, intsize);
130 
131  if (ointsize != intsize)
132  return -EINVAL;
133 
134  /* Look for this #address-cells. We have to implement the old linux
135  * trick of looking for the parent here as some device-trees rely on it
136  */
137  old = of_node_get(ipar);
138  do {
139  tmp = of_get_property(old, "#address-cells", NULL);
140  tnode = of_get_parent(old);
141  of_node_put(old);
142  old = tnode;
143  } while (old && tmp == NULL);
144  of_node_put(old);
145  old = NULL;
146  addrsize = (tmp == NULL) ? 2 : be32_to_cpu(*tmp);
147 
148  pr_debug(" -> addrsize=%d\n", addrsize);
149 
150  /* Now start the actual "proper" walk of the interrupt tree */
151  while (ipar != NULL) {
152  /* Now check if cursor is an interrupt-controller and if it is
153  * then we are done
154  */
155  if (of_get_property(ipar, "interrupt-controller", NULL) !=
156  NULL) {
157  pr_debug(" -> got it !\n");
158  for (i = 0; i < intsize; i++)
159  out_irq->specifier[i] =
160  of_read_number(intspec +i, 1);
161  out_irq->size = intsize;
162  out_irq->controller = ipar;
163  of_node_put(old);
164  return 0;
165  }
166 
167  /* Now look for an interrupt-map */
168  imap = of_get_property(ipar, "interrupt-map", &imaplen);
169  /* No interrupt map, check for an interrupt parent */
170  if (imap == NULL) {
171  pr_debug(" -> no map, getting parent\n");
172  newpar = of_irq_find_parent(ipar);
173  goto skiplevel;
174  }
175  imaplen /= sizeof(u32);
176 
177  /* Look for a mask */
178  imask = of_get_property(ipar, "interrupt-map-mask", NULL);
179 
180  /* If we were passed no "reg" property and we attempt to parse
181  * an interrupt-map, then #address-cells must be 0.
182  * Fail if it's not.
183  */
184  if (addr == NULL && addrsize != 0) {
185  pr_debug(" -> no reg passed in when needed !\n");
186  goto fail;
187  }
188 
189  /* Parse interrupt-map */
190  match = 0;
191  while (imaplen > (addrsize + intsize + 1) && !match) {
192  /* Compare specifiers */
193  match = 1;
194  for (i = 0; i < addrsize && match; ++i) {
195  __be32 mask = imask ? imask[i]
196  : cpu_to_be32(0xffffffffu);
197  match = ((addr[i] ^ imap[i]) & mask) == 0;
198  }
199  for (; i < (addrsize + intsize) && match; ++i) {
200  __be32 mask = imask ? imask[i]
201  : cpu_to_be32(0xffffffffu);
202  match =
203  ((intspec[i-addrsize] ^ imap[i]) & mask) == 0;
204  }
205  imap += addrsize + intsize;
206  imaplen -= addrsize + intsize;
207 
208  pr_debug(" -> match=%d (imaplen=%d)\n", match, imaplen);
209 
210  /* Get the interrupt parent */
211  if (of_irq_workarounds & OF_IMAP_NO_PHANDLE)
212  newpar = of_node_get(of_irq_dflt_pic);
213  else
214  newpar = of_find_node_by_phandle(be32_to_cpup(imap));
215  imap++;
216  --imaplen;
217 
218  /* Check if not found */
219  if (newpar == NULL) {
220  pr_debug(" -> imap parent not found !\n");
221  goto fail;
222  }
223 
224  /* Get #interrupt-cells and #address-cells of new
225  * parent
226  */
227  tmp = of_get_property(newpar, "#interrupt-cells", NULL);
228  if (tmp == NULL) {
229  pr_debug(" -> parent lacks #interrupt-cells!\n");
230  goto fail;
231  }
232  newintsize = be32_to_cpu(*tmp);
233  tmp = of_get_property(newpar, "#address-cells", NULL);
234  newaddrsize = (tmp == NULL) ? 0 : be32_to_cpu(*tmp);
235 
236  pr_debug(" -> newintsize=%d, newaddrsize=%d\n",
237  newintsize, newaddrsize);
238 
239  /* Check for malformed properties */
240  if (imaplen < (newaddrsize + newintsize))
241  goto fail;
242 
243  imap += newaddrsize + newintsize;
244  imaplen -= newaddrsize + newintsize;
245 
246  pr_debug(" -> imaplen=%d\n", imaplen);
247  }
248  if (!match)
249  goto fail;
250 
251  of_node_put(old);
252  old = of_node_get(newpar);
253  addrsize = newaddrsize;
254  intsize = newintsize;
255  intspec = imap - intsize;
256  addr = intspec - addrsize;
257 
258  skiplevel:
259  /* Iterate again with new parent */
260  pr_debug(" -> new parent: %s\n", of_node_full_name(newpar));
261  of_node_put(ipar);
262  ipar = newpar;
263  newpar = NULL;
264  }
265  fail:
266  of_node_put(ipar);
267  of_node_put(old);
268  of_node_put(newpar);
269 
270  return -EINVAL;
271 }
273 
283 int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq)
284 {
285  struct device_node *p;
286  const __be32 *intspec, *tmp, *addr;
287  u32 intsize, intlen;
288  int res = -EINVAL;
289 
290  pr_debug("of_irq_map_one: dev=%s, index=%d\n", device->full_name, index);
291 
292  /* OldWorld mac stuff is "special", handle out of line */
293  if (of_irq_workarounds & OF_IMAP_OLDWORLD_MAC)
294  return of_irq_map_oldworld(device, index, out_irq);
295 
296  /* Get the interrupts property */
297  intspec = of_get_property(device, "interrupts", &intlen);
298  if (intspec == NULL)
299  return -EINVAL;
300  intlen /= sizeof(*intspec);
301 
302  pr_debug(" intspec=%d intlen=%d\n", be32_to_cpup(intspec), intlen);
303 
304  /* Get the reg property (if any) */
305  addr = of_get_property(device, "reg", NULL);
306 
307  /* Look for the interrupt parent. */
308  p = of_irq_find_parent(device);
309  if (p == NULL)
310  return -EINVAL;
311 
312  /* Get size of interrupt specifier */
313  tmp = of_get_property(p, "#interrupt-cells", NULL);
314  if (tmp == NULL)
315  goto out;
316  intsize = be32_to_cpu(*tmp);
317 
318  pr_debug(" intsize=%d intlen=%d\n", intsize, intlen);
319 
320  /* Check index */
321  if ((index + 1) * intsize > intlen)
322  goto out;
323 
324  /* Get new specifier and map it */
325  res = of_irq_map_raw(p, intspec + index * intsize, intsize,
326  addr, out_irq);
327  out:
328  of_node_put(p);
329  return res;
330 }
332 
339 int of_irq_to_resource(struct device_node *dev, int index, struct resource *r)
340 {
341  int irq = irq_of_parse_and_map(dev, index);
342 
343  /* Only dereference the resource if both the
344  * resource and the irq are valid. */
345  if (r && irq) {
346  const char *name = NULL;
347 
348  /*
349  * Get optional "interrupts-names" property to add a name
350  * to the resource.
351  */
352  of_property_read_string_index(dev, "interrupt-names", index,
353  &name);
354 
355  r->start = r->end = irq;
356  r->flags = IORESOURCE_IRQ;
357  r->name = name ? name : dev->full_name;
358  }
359 
360  return irq;
361 }
363 
369 {
370  int nr = 0;
371 
372  while (of_irq_to_resource(dev, nr, NULL))
373  nr++;
374 
375  return nr;
376 }
377 
387  int nr_irqs)
388 {
389  int i;
390 
391  for (i = 0; i < nr_irqs; i++, res++)
392  if (!of_irq_to_resource(dev, i, res))
393  break;
394 
395  return i;
396 }
398 
399 struct intc_desc {
400  struct list_head list;
401  struct device_node *dev;
403 };
404 
412 void __init of_irq_init(const struct of_device_id *matches)
413 {
414  struct device_node *np, *parent = NULL;
415  struct intc_desc *desc, *temp_desc;
416  struct list_head intc_desc_list, intc_parent_list;
417 
418  INIT_LIST_HEAD(&intc_desc_list);
419  INIT_LIST_HEAD(&intc_parent_list);
420 
421  for_each_matching_node(np, matches) {
422  if (!of_find_property(np, "interrupt-controller", NULL))
423  continue;
424  /*
425  * Here, we allocate and populate an intc_desc with the node
426  * pointer, interrupt-parent device_node etc.
427  */
428  desc = kzalloc(sizeof(*desc), GFP_KERNEL);
429  if (WARN_ON(!desc))
430  goto err;
431 
432  desc->dev = np;
434  if (desc->interrupt_parent == np)
435  desc->interrupt_parent = NULL;
436  list_add_tail(&desc->list, &intc_desc_list);
437  }
438 
439  /*
440  * The root irq controller is the one without an interrupt-parent.
441  * That one goes first, followed by the controllers that reference it,
442  * followed by the ones that reference the 2nd level controllers, etc.
443  */
444  while (!list_empty(&intc_desc_list)) {
445  /*
446  * Process all controllers with the current 'parent'.
447  * First pass will be looking for NULL as the parent.
448  * The assumption is that NULL parent means a root controller.
449  */
450  list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {
451  const struct of_device_id *match;
452  int ret;
453  of_irq_init_cb_t irq_init_cb;
454 
455  if (desc->interrupt_parent != parent)
456  continue;
457 
458  list_del(&desc->list);
459  match = of_match_node(matches, desc->dev);
460  if (WARN(!match->data,
461  "of_irq_init: no init function for %s\n",
462  match->compatible)) {
463  kfree(desc);
464  continue;
465  }
466 
467  pr_debug("of_irq_init: init %s @ %p, parent %p\n",
468  match->compatible,
469  desc->dev, desc->interrupt_parent);
470  irq_init_cb = (of_irq_init_cb_t)match->data;
471  ret = irq_init_cb(desc->dev, desc->interrupt_parent);
472  if (ret) {
473  kfree(desc);
474  continue;
475  }
476 
477  /*
478  * This one is now set up; add it to the parent list so
479  * its children can get processed in a subsequent pass.
480  */
481  list_add_tail(&desc->list, &intc_parent_list);
482  }
483 
484  /* Get the next pending parent that might have children */
485  desc = list_first_entry(&intc_parent_list, typeof(*desc), list);
486  if (list_empty(&intc_parent_list) || !desc) {
487  pr_err("of_irq_init: children remain, but no parents\n");
488  break;
489  }
490  list_del(&desc->list);
491  parent = desc->dev;
492  kfree(desc);
493  }
494 
495  list_for_each_entry_safe(desc, temp_desc, &intc_parent_list, list) {
496  list_del(&desc->list);
497  kfree(desc);
498  }
499 err:
500  list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {
501  list_del(&desc->list);
502  kfree(desc);
503  }
504 }