aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/of
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/of')
-rw-r--r--drivers/of/address.c10
-rw-r--r--drivers/of/base.c60
-rw-r--r--drivers/of/irq.c164
-rw-r--r--drivers/of/of_pci_irq.c40
-rw-r--r--drivers/of/selftest.c161
5 files changed, 324 insertions, 111 deletions
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 556a7fb6ead3..4b9317bdb81c 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -489,7 +489,7 @@ static u64 __of_translate_address(struct device_node *dev,
489 int na, ns, pna, pns; 489 int na, ns, pna, pns;
490 u64 result = OF_BAD_ADDR; 490 u64 result = OF_BAD_ADDR;
491 491
492 pr_debug("OF: ** translation for device %s **\n", dev->full_name); 492 pr_debug("OF: ** translation for device %s **\n", of_node_full_name(dev));
493 493
494 /* Increase refcount at current level */ 494 /* Increase refcount at current level */
495 of_node_get(dev); 495 of_node_get(dev);
@@ -504,13 +504,13 @@ static u64 __of_translate_address(struct device_node *dev,
504 bus->count_cells(dev, &na, &ns); 504 bus->count_cells(dev, &na, &ns);
505 if (!OF_CHECK_COUNTS(na, ns)) { 505 if (!OF_CHECK_COUNTS(na, ns)) {
506 printk(KERN_ERR "prom_parse: Bad cell count for %s\n", 506 printk(KERN_ERR "prom_parse: Bad cell count for %s\n",
507 dev->full_name); 507 of_node_full_name(dev));
508 goto bail; 508 goto bail;
509 } 509 }
510 memcpy(addr, in_addr, na * 4); 510 memcpy(addr, in_addr, na * 4);
511 511
512 pr_debug("OF: bus is %s (na=%d, ns=%d) on %s\n", 512 pr_debug("OF: bus is %s (na=%d, ns=%d) on %s\n",
513 bus->name, na, ns, parent->full_name); 513 bus->name, na, ns, of_node_full_name(parent));
514 of_dump_addr("OF: translating address:", addr, na); 514 of_dump_addr("OF: translating address:", addr, na);
515 515
516 /* Translate */ 516 /* Translate */
@@ -532,12 +532,12 @@ static u64 __of_translate_address(struct device_node *dev,
532 pbus->count_cells(dev, &pna, &pns); 532 pbus->count_cells(dev, &pna, &pns);
533 if (!OF_CHECK_COUNTS(pna, pns)) { 533 if (!OF_CHECK_COUNTS(pna, pns)) {
534 printk(KERN_ERR "prom_parse: Bad cell count for %s\n", 534 printk(KERN_ERR "prom_parse: Bad cell count for %s\n",
535 dev->full_name); 535 of_node_full_name(dev));
536 break; 536 break;
537 } 537 }
538 538
539 pr_debug("OF: parent bus is %s (na=%d, ns=%d) on %s\n", 539 pr_debug("OF: parent bus is %s (na=%d, ns=%d) on %s\n",
540 pbus->name, pna, pns, parent->full_name); 540 pbus->name, pna, pns, of_node_full_name(parent));
541 541
542 /* Apply bus translation */ 542 /* Apply bus translation */
543 if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop)) 543 if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop))
diff --git a/drivers/of/base.c b/drivers/of/base.c
index ced4c06d79b3..f2431091f4c1 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -272,9 +272,9 @@ static bool __of_find_n_match_cpu_property(struct device_node *cpun,
272 272
273 ac = of_n_addr_cells(cpun); 273 ac = of_n_addr_cells(cpun);
274 cell = of_get_property(cpun, prop_name, &prop_len); 274 cell = of_get_property(cpun, prop_name, &prop_len);
275 if (!cell) 275 if (!cell || !ac)
276 return false; 276 return false;
277 prop_len /= sizeof(*cell); 277 prop_len /= sizeof(*cell) * ac;
278 for (tid = 0; tid < prop_len; tid++) { 278 for (tid = 0; tid < prop_len; tid++) {
279 hwid = of_read_number(cell, ac); 279 hwid = of_read_number(cell, ac);
280 if (arch_match_cpu_phys_id(cpu, hwid)) { 280 if (arch_match_cpu_phys_id(cpu, hwid)) {
@@ -287,6 +287,31 @@ static bool __of_find_n_match_cpu_property(struct device_node *cpun,
287 return false; 287 return false;
288} 288}
289 289
290/*
291 * arch_find_n_match_cpu_physical_id - See if the given device node is
292 * for the cpu corresponding to logical cpu 'cpu'. Return true if so,
293 * else false. If 'thread' is non-NULL, the local thread number within the
294 * core is returned in it.
295 */
296bool __weak arch_find_n_match_cpu_physical_id(struct device_node *cpun,
297 int cpu, unsigned int *thread)
298{
299 /* Check for non-standard "ibm,ppc-interrupt-server#s" property
300 * for thread ids on PowerPC. If it doesn't exist fallback to
301 * standard "reg" property.
302 */
303 if (IS_ENABLED(CONFIG_PPC) &&
304 __of_find_n_match_cpu_property(cpun,
305 "ibm,ppc-interrupt-server#s",
306 cpu, thread))
307 return true;
308
309 if (__of_find_n_match_cpu_property(cpun, "reg", cpu, thread))
310 return true;
311
312 return false;
313}
314
290/** 315/**
291 * of_get_cpu_node - Get device node associated with the given logical CPU 316 * of_get_cpu_node - Get device node associated with the given logical CPU
292 * 317 *
@@ -307,26 +332,10 @@ static bool __of_find_n_match_cpu_property(struct device_node *cpun,
307 */ 332 */
308struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) 333struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
309{ 334{
310 struct device_node *cpun, *cpus; 335 struct device_node *cpun;
311 336
312 cpus = of_find_node_by_path("/cpus"); 337 for_each_node_by_type(cpun, "cpu") {
313 if (!cpus) { 338 if (arch_find_n_match_cpu_physical_id(cpun, cpu, thread))
314 pr_warn("Missing cpus node, bailing out\n");
315 return NULL;
316 }
317
318 for_each_child_of_node(cpus, cpun) {
319 if (of_node_cmp(cpun->type, "cpu"))
320 continue;
321 /* Check for non-standard "ibm,ppc-interrupt-server#s" property
322 * for thread ids on PowerPC. If it doesn't exist fallback to
323 * standard "reg" property.
324 */
325 if (IS_ENABLED(CONFIG_PPC) &&
326 __of_find_n_match_cpu_property(cpun,
327 "ibm,ppc-interrupt-server#s", cpu, thread))
328 return cpun;
329 if (__of_find_n_match_cpu_property(cpun, "reg", cpu, thread))
330 return cpun; 339 return cpun;
331 } 340 }
332 return NULL; 341 return NULL;
@@ -1183,6 +1192,15 @@ int of_property_count_strings(struct device_node *np, const char *propname)
1183} 1192}
1184EXPORT_SYMBOL_GPL(of_property_count_strings); 1193EXPORT_SYMBOL_GPL(of_property_count_strings);
1185 1194
1195void of_print_phandle_args(const char *msg, const struct of_phandle_args *args)
1196{
1197 int i;
1198 printk("%s %s", msg, of_node_full_name(args->np));
1199 for (i = 0; i < args->args_count; i++)
1200 printk(i ? ",%08x" : ":%08x", args->args[i]);
1201 printk("\n");
1202}
1203
1186static int __of_parse_phandle_with_args(const struct device_node *np, 1204static int __of_parse_phandle_with_args(const struct device_node *np,
1187 const char *list_name, 1205 const char *list_name,
1188 const char *cells_name, 1206 const char *cells_name,
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 1752988d6aa8..d385bb824772 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -31,18 +31,17 @@
31 * @dev: Device node of the device whose interrupt is to be mapped 31 * @dev: Device node of the device whose interrupt is to be mapped
32 * @index: Index of the interrupt to map 32 * @index: Index of the interrupt to map
33 * 33 *
34 * This function is a wrapper that chains of_irq_map_one() and 34 * This function is a wrapper that chains of_irq_parse_one() and
35 * irq_create_of_mapping() to make things easier to callers 35 * irq_create_of_mapping() to make things easier to callers
36 */ 36 */
37unsigned int irq_of_parse_and_map(struct device_node *dev, int index) 37unsigned int irq_of_parse_and_map(struct device_node *dev, int index)
38{ 38{
39 struct of_irq oirq; 39 struct of_phandle_args oirq;
40 40
41 if (of_irq_map_one(dev, index, &oirq)) 41 if (of_irq_parse_one(dev, index, &oirq))
42 return 0; 42 return 0;
43 43
44 return irq_create_of_mapping(oirq.controller, oirq.specifier, 44 return irq_create_of_mapping(&oirq);
45 oirq.size);
46} 45}
47EXPORT_SYMBOL_GPL(irq_of_parse_and_map); 46EXPORT_SYMBOL_GPL(irq_of_parse_and_map);
48 47
@@ -79,33 +78,34 @@ struct device_node *of_irq_find_parent(struct device_node *child)
79} 78}
80 79
81/** 80/**
82 * of_irq_map_raw - Low level interrupt tree parsing 81 * of_irq_parse_raw - Low level interrupt tree parsing
83 * @parent: the device interrupt parent 82 * @parent: the device interrupt parent
84 * @intspec: interrupt specifier ("interrupts" property of the device) 83 * @addr: address specifier (start of "reg" property of the device) in be32 format
85 * @ointsize: size of the passed in interrupt specifier 84 * @out_irq: structure of_irq updated by this function
86 * @addr: address specifier (start of "reg" property of the device)
87 * @out_irq: structure of_irq filled by this function
88 * 85 *
89 * Returns 0 on success and a negative number on error 86 * Returns 0 on success and a negative number on error
90 * 87 *
91 * This function is a low-level interrupt tree walking function. It 88 * This function is a low-level interrupt tree walking function. It
92 * can be used to do a partial walk with synthetized reg and interrupts 89 * can be used to do a partial walk with synthetized reg and interrupts
93 * properties, for example when resolving PCI interrupts when no device 90 * properties, for example when resolving PCI interrupts when no device
94 * node exist for the parent. 91 * node exist for the parent. It takes an interrupt specifier structure as
92 * input, walks the tree looking for any interrupt-map properties, translates
93 * the specifier for each map, and then returns the translated map.
95 */ 94 */
96int of_irq_map_raw(struct device_node *parent, const __be32 *intspec, 95int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
97 u32 ointsize, const __be32 *addr, struct of_irq *out_irq)
98{ 96{
99 struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL; 97 struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL;
100 const __be32 *tmp, *imap, *imask; 98 __be32 initial_match_array[MAX_PHANDLE_ARGS];
99 const __be32 *match_array = initial_match_array;
100 const __be32 *tmp, *imap, *imask, dummy_imask[] = { [0 ... MAX_PHANDLE_ARGS] = ~0 };
101 u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0; 101 u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0;
102 int imaplen, match, i; 102 int imaplen, match, i;
103 103
104 pr_debug("of_irq_map_raw: par=%s,intspec=[0x%08x 0x%08x...],ointsize=%d\n", 104#ifdef DEBUG
105 parent->full_name, be32_to_cpup(intspec), 105 of_print_phandle_args("of_irq_parse_raw: ", out_irq);
106 be32_to_cpup(intspec + 1), ointsize); 106#endif
107 107
108 ipar = of_node_get(parent); 108 ipar = of_node_get(out_irq->np);
109 109
110 /* First get the #interrupt-cells property of the current cursor 110 /* First get the #interrupt-cells property of the current cursor
111 * that tells us how to interpret the passed-in intspec. If there 111 * that tells us how to interpret the passed-in intspec. If there
@@ -126,9 +126,9 @@ int of_irq_map_raw(struct device_node *parent, const __be32 *intspec,
126 goto fail; 126 goto fail;
127 } 127 }
128 128
129 pr_debug("of_irq_map_raw: ipar=%s, size=%d\n", ipar->full_name, intsize); 129 pr_debug("of_irq_parse_raw: ipar=%s, size=%d\n", of_node_full_name(ipar), intsize);
130 130
131 if (ointsize != intsize) 131 if (out_irq->args_count != intsize)
132 return -EINVAL; 132 return -EINVAL;
133 133
134 /* Look for this #address-cells. We have to implement the old linux 134 /* Look for this #address-cells. We have to implement the old linux
@@ -147,6 +147,16 @@ int of_irq_map_raw(struct device_node *parent, const __be32 *intspec,
147 147
148 pr_debug(" -> addrsize=%d\n", addrsize); 148 pr_debug(" -> addrsize=%d\n", addrsize);
149 149
150 /* Range check so that the temporary buffer doesn't overflow */
151 if (WARN_ON(addrsize + intsize > MAX_PHANDLE_ARGS))
152 goto fail;
153
154 /* Precalculate the match array - this simplifies match loop */
155 for (i = 0; i < addrsize; i++)
156 initial_match_array[i] = addr ? addr[i] : 0;
157 for (i = 0; i < intsize; i++)
158 initial_match_array[addrsize + i] = cpu_to_be32(out_irq->args[i]);
159
150 /* Now start the actual "proper" walk of the interrupt tree */ 160 /* Now start the actual "proper" walk of the interrupt tree */
151 while (ipar != NULL) { 161 while (ipar != NULL) {
152 /* Now check if cursor is an interrupt-controller and if it is 162 /* Now check if cursor is an interrupt-controller and if it is
@@ -155,15 +165,19 @@ int of_irq_map_raw(struct device_node *parent, const __be32 *intspec,
155 if (of_get_property(ipar, "interrupt-controller", NULL) != 165 if (of_get_property(ipar, "interrupt-controller", NULL) !=
156 NULL) { 166 NULL) {
157 pr_debug(" -> got it !\n"); 167 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); 168 of_node_put(old);
164 return 0; 169 return 0;
165 } 170 }
166 171
172 /*
173 * interrupt-map parsing does not work without a reg
174 * property when #address-cells != 0
175 */
176 if (addrsize && !addr) {
177 pr_debug(" -> no reg passed in when needed !\n");
178 goto fail;
179 }
180
167 /* Now look for an interrupt-map */ 181 /* Now look for an interrupt-map */
168 imap = of_get_property(ipar, "interrupt-map", &imaplen); 182 imap = of_get_property(ipar, "interrupt-map", &imaplen);
169 /* No interrupt map, check for an interrupt parent */ 183 /* No interrupt map, check for an interrupt parent */
@@ -176,34 +190,16 @@ int of_irq_map_raw(struct device_node *parent, const __be32 *intspec,
176 190
177 /* Look for a mask */ 191 /* Look for a mask */
178 imask = of_get_property(ipar, "interrupt-map-mask", NULL); 192 imask = of_get_property(ipar, "interrupt-map-mask", NULL);
179 193 if (!imask)
180 /* If we were passed no "reg" property and we attempt to parse 194 imask = dummy_imask;
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 195
189 /* Parse interrupt-map */ 196 /* Parse interrupt-map */
190 match = 0; 197 match = 0;
191 while (imaplen > (addrsize + intsize + 1) && !match) { 198 while (imaplen > (addrsize + intsize + 1) && !match) {
192 /* Compare specifiers */ 199 /* Compare specifiers */
193 match = 1; 200 match = 1;
194 for (i = 0; i < addrsize && match; ++i) { 201 for (i = 0; i < (addrsize + intsize); i++, imaplen--)
195 __be32 mask = imask ? imask[i] 202 match = !((match_array[i] ^ *imap++) & 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 203
208 pr_debug(" -> match=%d (imaplen=%d)\n", match, imaplen); 204 pr_debug(" -> match=%d (imaplen=%d)\n", match, imaplen);
209 205
@@ -237,6 +233,8 @@ int of_irq_map_raw(struct device_node *parent, const __be32 *intspec,
237 newintsize, newaddrsize); 233 newintsize, newaddrsize);
238 234
239 /* Check for malformed properties */ 235 /* Check for malformed properties */
236 if (WARN_ON(newaddrsize + newintsize > MAX_PHANDLE_ARGS))
237 goto fail;
240 if (imaplen < (newaddrsize + newintsize)) 238 if (imaplen < (newaddrsize + newintsize))
241 goto fail; 239 goto fail;
242 240
@@ -248,12 +246,18 @@ int of_irq_map_raw(struct device_node *parent, const __be32 *intspec,
248 if (!match) 246 if (!match)
249 goto fail; 247 goto fail;
250 248
251 of_node_put(old); 249 /*
252 old = of_node_get(newpar); 250 * Successfully parsed an interrrupt-map translation; copy new
251 * interrupt specifier into the out_irq structure
252 */
253 of_node_put(out_irq->np);
254 out_irq->np = of_node_get(newpar);
255
256 match_array = imap - newaddrsize - newintsize;
257 for (i = 0; i < newintsize; i++)
258 out_irq->args[i] = be32_to_cpup(imap - newintsize + i);
259 out_irq->args_count = intsize = newintsize;
253 addrsize = newaddrsize; 260 addrsize = newaddrsize;
254 intsize = newintsize;
255 intspec = imap - intsize;
256 addr = intspec - addrsize;
257 261
258 skiplevel: 262 skiplevel:
259 /* Iterate again with new parent */ 263 /* Iterate again with new parent */
@@ -264,46 +268,53 @@ int of_irq_map_raw(struct device_node *parent, const __be32 *intspec,
264 } 268 }
265 fail: 269 fail:
266 of_node_put(ipar); 270 of_node_put(ipar);
267 of_node_put(old); 271 of_node_put(out_irq->np);
268 of_node_put(newpar); 272 of_node_put(newpar);
269 273
270 return -EINVAL; 274 return -EINVAL;
271} 275}
272EXPORT_SYMBOL_GPL(of_irq_map_raw); 276EXPORT_SYMBOL_GPL(of_irq_parse_raw);
273 277
274/** 278/**
275 * of_irq_map_one - Resolve an interrupt for a device 279 * of_irq_parse_one - Resolve an interrupt for a device
276 * @device: the device whose interrupt is to be resolved 280 * @device: the device whose interrupt is to be resolved
277 * @index: index of the interrupt to resolve 281 * @index: index of the interrupt to resolve
278 * @out_irq: structure of_irq filled by this function 282 * @out_irq: structure of_irq filled by this function
279 * 283 *
280 * This function resolves an interrupt, walking the tree, for a given 284 * This function resolves an interrupt for a node by walking the interrupt tree,
281 * device-tree node. It's the high level pendant to of_irq_map_raw(). 285 * finding which interrupt controller node it is attached to, and returning the
286 * interrupt specifier that can be used to retrieve a Linux IRQ number.
282 */ 287 */
283int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq) 288int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_args *out_irq)
284{ 289{
285 struct device_node *p; 290 struct device_node *p;
286 const __be32 *intspec, *tmp, *addr; 291 const __be32 *intspec, *tmp, *addr;
287 u32 intsize, intlen; 292 u32 intsize, intlen;
288 int res = -EINVAL; 293 int i, res = -EINVAL;
289 294
290 pr_debug("of_irq_map_one: dev=%s, index=%d\n", device->full_name, index); 295 pr_debug("of_irq_parse_one: dev=%s, index=%d\n", of_node_full_name(device), index);
291 296
292 /* OldWorld mac stuff is "special", handle out of line */ 297 /* OldWorld mac stuff is "special", handle out of line */
293 if (of_irq_workarounds & OF_IMAP_OLDWORLD_MAC) 298 if (of_irq_workarounds & OF_IMAP_OLDWORLD_MAC)
294 return of_irq_map_oldworld(device, index, out_irq); 299 return of_irq_parse_oldworld(device, index, out_irq);
300
301 /* Get the reg property (if any) */
302 addr = of_get_property(device, "reg", NULL);
295 303
296 /* Get the interrupts property */ 304 /* Get the interrupts property */
297 intspec = of_get_property(device, "interrupts", &intlen); 305 intspec = of_get_property(device, "interrupts", &intlen);
298 if (intspec == NULL) 306 if (intspec == NULL) {
299 return -EINVAL; 307 /* Try the new-style interrupts-extended */
308 res = of_parse_phandle_with_args(device, "interrupts-extended",
309 "#interrupt-cells", index, out_irq);
310 if (res)
311 return -EINVAL;
312 return of_irq_parse_raw(addr, out_irq);
313 }
300 intlen /= sizeof(*intspec); 314 intlen /= sizeof(*intspec);
301 315
302 pr_debug(" intspec=%d intlen=%d\n", be32_to_cpup(intspec), intlen); 316 pr_debug(" intspec=%d intlen=%d\n", be32_to_cpup(intspec), intlen);
303 317
304 /* Get the reg property (if any) */
305 addr = of_get_property(device, "reg", NULL);
306
307 /* Look for the interrupt parent. */ 318 /* Look for the interrupt parent. */
308 p = of_irq_find_parent(device); 319 p = of_irq_find_parent(device);
309 if (p == NULL) 320 if (p == NULL)
@@ -321,14 +332,20 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq
321 if ((index + 1) * intsize > intlen) 332 if ((index + 1) * intsize > intlen)
322 goto out; 333 goto out;
323 334
324 /* Get new specifier and map it */ 335 /* Copy intspec into irq structure */
325 res = of_irq_map_raw(p, intspec + index * intsize, intsize, 336 intspec += index * intsize;
326 addr, out_irq); 337 out_irq->np = p;
338 out_irq->args_count = intsize;
339 for (i = 0; i < intsize; i++)
340 out_irq->args[i] = be32_to_cpup(intspec++);
341
342 /* Check if there are any interrupt-map translations to process */
343 res = of_irq_parse_raw(addr, out_irq);
327 out: 344 out:
328 of_node_put(p); 345 of_node_put(p);
329 return res; 346 return res;
330} 347}
331EXPORT_SYMBOL_GPL(of_irq_map_one); 348EXPORT_SYMBOL_GPL(of_irq_parse_one);
332 349
333/** 350/**
334 * of_irq_to_resource - Decode a node's IRQ and return it as a resource 351 * of_irq_to_resource - Decode a node's IRQ and return it as a resource
@@ -354,8 +371,8 @@ int of_irq_to_resource(struct device_node *dev, int index, struct resource *r)
354 &name); 371 &name);
355 372
356 r->start = r->end = irq; 373 r->start = r->end = irq;
357 r->flags = IORESOURCE_IRQ; 374 r->flags = IORESOURCE_IRQ | irqd_get_trigger_type(irq_get_irq_data(irq));
358 r->name = name ? name : dev->full_name; 375 r->name = name ? name : of_node_full_name(dev);
359 } 376 }
360 377
361 return irq; 378 return irq;
@@ -368,9 +385,10 @@ EXPORT_SYMBOL_GPL(of_irq_to_resource);
368 */ 385 */
369int of_irq_count(struct device_node *dev) 386int of_irq_count(struct device_node *dev)
370{ 387{
388 struct of_phandle_args irq;
371 int nr = 0; 389 int nr = 0;
372 390
373 while (of_irq_to_resource(dev, nr, NULL)) 391 while (of_irq_parse_one(dev, nr, &irq) == 0)
374 nr++; 392 nr++;
375 393
376 return nr; 394 return nr;
diff --git a/drivers/of/of_pci_irq.c b/drivers/of/of_pci_irq.c
index d86076431af6..8736bc7676c5 100644
--- a/drivers/of/of_pci_irq.c
+++ b/drivers/of/of_pci_irq.c
@@ -4,7 +4,7 @@
4#include <linux/export.h> 4#include <linux/export.h>
5 5
6/** 6/**
7 * of_irq_map_pci - Resolve the interrupt for a PCI device 7 * of_irq_parse_pci - Resolve the interrupt for a PCI device
8 * @pdev: the device whose interrupt is to be resolved 8 * @pdev: the device whose interrupt is to be resolved
9 * @out_irq: structure of_irq filled by this function 9 * @out_irq: structure of_irq filled by this function
10 * 10 *
@@ -14,7 +14,7 @@
14 * PCI tree until an device-node is found, at which point it will finish 14 * PCI tree until an device-node is found, at which point it will finish
15 * resolving using the OF tree walking. 15 * resolving using the OF tree walking.
16 */ 16 */
17int of_irq_map_pci(const struct pci_dev *pdev, struct of_irq *out_irq) 17int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq)
18{ 18{
19 struct device_node *dn, *ppnode; 19 struct device_node *dn, *ppnode;
20 struct pci_dev *ppdev; 20 struct pci_dev *ppdev;
@@ -29,7 +29,7 @@ int of_irq_map_pci(const struct pci_dev *pdev, struct of_irq *out_irq)
29 */ 29 */
30 dn = pci_device_to_OF_node(pdev); 30 dn = pci_device_to_OF_node(pdev);
31 if (dn) { 31 if (dn) {
32 rc = of_irq_map_one(dn, 0, out_irq); 32 rc = of_irq_parse_one(dn, 0, out_irq);
33 if (!rc) 33 if (!rc)
34 return rc; 34 return rc;
35 } 35 }
@@ -84,9 +84,37 @@ int of_irq_map_pci(const struct pci_dev *pdev, struct of_irq *out_irq)
84 pdev = ppdev; 84 pdev = ppdev;
85 } 85 }
86 86
87 out_irq->np = ppnode;
88 out_irq->args_count = 1;
89 out_irq->args[0] = lspec;
87 lspec_be = cpu_to_be32(lspec); 90 lspec_be = cpu_to_be32(lspec);
88 laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8)); 91 laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8));
89 laddr[1] = laddr[2] = cpu_to_be32(0); 92 laddr[1] = laddr[2] = cpu_to_be32(0);
90 return of_irq_map_raw(ppnode, &lspec_be, 1, laddr, out_irq); 93 return of_irq_parse_raw(laddr, out_irq);
91} 94}
92EXPORT_SYMBOL_GPL(of_irq_map_pci); 95EXPORT_SYMBOL_GPL(of_irq_parse_pci);
96
97/**
98 * of_irq_parse_and_map_pci() - Decode a PCI irq from the device tree and map to a virq
99 * @dev: The pci device needing an irq
100 * @slot: PCI slot number; passed when used as map_irq callback. Unused
101 * @pin: PCI irq pin number; passed when used as map_irq callback. Unused
102 *
103 * @slot and @pin are unused, but included in the function so that this
104 * function can be used directly as the map_irq callback to pci_fixup_irqs().
105 */
106int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin)
107{
108 struct of_phandle_args oirq;
109 int ret;
110
111 ret = of_irq_parse_pci(dev, &oirq);
112 if (ret) {
113 dev_err(&dev->dev, "of_irq_parse_pci() failed with rc=%d\n", ret);
114 return 0; /* Proper return code 0 == NO_IRQ */
115 }
116
117 return irq_create_of_mapping(&oirq);
118}
119EXPORT_SYMBOL_GPL(of_irq_parse_and_map_pci);
120
diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c
index 0eb5c38b4e07..e21012bde639 100644
--- a/drivers/of/selftest.c
+++ b/drivers/of/selftest.c
@@ -9,18 +9,24 @@
9#include <linux/errno.h> 9#include <linux/errno.h>
10#include <linux/module.h> 10#include <linux/module.h>
11#include <linux/of.h> 11#include <linux/of.h>
12#include <linux/of_irq.h>
12#include <linux/list.h> 13#include <linux/list.h>
13#include <linux/mutex.h> 14#include <linux/mutex.h>
14#include <linux/slab.h> 15#include <linux/slab.h>
15#include <linux/device.h> 16#include <linux/device.h>
16 17
17static bool selftest_passed = true; 18static struct selftest_results {
19 int passed;
20 int failed;
21} selftest_results;
22
18#define selftest(result, fmt, ...) { \ 23#define selftest(result, fmt, ...) { \
19 if (!(result)) { \ 24 if (!(result)) { \
20 pr_err("FAIL %s:%i " fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ 25 selftest_results.failed++; \
21 selftest_passed = false; \ 26 pr_err("FAIL %s():%i " fmt, __func__, __LINE__, ##__VA_ARGS__); \
22 } else { \ 27 } else { \
23 pr_info("pass %s:%i\n", __FILE__, __LINE__); \ 28 selftest_results.passed++; \
29 pr_debug("pass %s():%i\n", __func__, __LINE__); \
24 } \ 30 } \
25} 31}
26 32
@@ -131,7 +137,6 @@ static void __init of_selftest_property_match_string(void)
131 struct device_node *np; 137 struct device_node *np;
132 int rc; 138 int rc;
133 139
134 pr_info("start\n");
135 np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a"); 140 np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a");
136 if (!np) { 141 if (!np) {
137 pr_err("No testcase data in device tree\n"); 142 pr_err("No testcase data in device tree\n");
@@ -154,6 +159,147 @@ static void __init of_selftest_property_match_string(void)
154 selftest(rc == -EILSEQ, "unterminated string; rc=%i", rc); 159 selftest(rc == -EILSEQ, "unterminated string; rc=%i", rc);
155} 160}
156 161
162static void __init of_selftest_parse_interrupts(void)
163{
164 struct device_node *np;
165 struct of_phandle_args args;
166 int i, rc;
167
168 np = of_find_node_by_path("/testcase-data/interrupts/interrupts0");
169 if (!np) {
170 pr_err("missing testcase data\n");
171 return;
172 }
173
174 for (i = 0; i < 4; i++) {
175 bool passed = true;
176 args.args_count = 0;
177 rc = of_irq_parse_one(np, i, &args);
178
179 passed &= !rc;
180 passed &= (args.args_count == 1);
181 passed &= (args.args[0] == (i + 1));
182
183 selftest(passed, "index %i - data error on node %s rc=%i\n",
184 i, args.np->full_name, rc);
185 }
186 of_node_put(np);
187
188 np = of_find_node_by_path("/testcase-data/interrupts/interrupts1");
189 if (!np) {
190 pr_err("missing testcase data\n");
191 return;
192 }
193
194 for (i = 0; i < 4; i++) {
195 bool passed = true;
196 args.args_count = 0;
197 rc = of_irq_parse_one(np, i, &args);
198
199 /* Test the values from tests-phandle.dtsi */
200 switch (i) {
201 case 0:
202 passed &= !rc;
203 passed &= (args.args_count == 1);
204 passed &= (args.args[0] == 9);
205 break;
206 case 1:
207 passed &= !rc;
208 passed &= (args.args_count == 3);
209 passed &= (args.args[0] == 10);
210 passed &= (args.args[1] == 11);
211 passed &= (args.args[2] == 12);
212 break;
213 case 2:
214 passed &= !rc;
215 passed &= (args.args_count == 2);
216 passed &= (args.args[0] == 13);
217 passed &= (args.args[1] == 14);
218 break;
219 case 3:
220 passed &= !rc;
221 passed &= (args.args_count == 2);
222 passed &= (args.args[0] == 15);
223 passed &= (args.args[1] == 16);
224 break;
225 default:
226 passed = false;
227 }
228 selftest(passed, "index %i - data error on node %s rc=%i\n",
229 i, args.np->full_name, rc);
230 }
231 of_node_put(np);
232}
233
234static void __init of_selftest_parse_interrupts_extended(void)
235{
236 struct device_node *np;
237 struct of_phandle_args args;
238 int i, rc;
239
240 np = of_find_node_by_path("/testcase-data/interrupts/interrupts-extended0");
241 if (!np) {
242 pr_err("missing testcase data\n");
243 return;
244 }
245
246 for (i = 0; i < 7; i++) {
247 bool passed = true;
248 rc = of_irq_parse_one(np, i, &args);
249
250 /* Test the values from tests-phandle.dtsi */
251 switch (i) {
252 case 0:
253 passed &= !rc;
254 passed &= (args.args_count == 1);
255 passed &= (args.args[0] == 1);
256 break;
257 case 1:
258 passed &= !rc;
259 passed &= (args.args_count == 3);
260 passed &= (args.args[0] == 2);
261 passed &= (args.args[1] == 3);
262 passed &= (args.args[2] == 4);
263 break;
264 case 2:
265 passed &= !rc;
266 passed &= (args.args_count == 2);
267 passed &= (args.args[0] == 5);
268 passed &= (args.args[1] == 6);
269 break;
270 case 3:
271 passed &= !rc;
272 passed &= (args.args_count == 1);
273 passed &= (args.args[0] == 9);
274 break;
275 case 4:
276 passed &= !rc;
277 passed &= (args.args_count == 3);
278 passed &= (args.args[0] == 10);
279 passed &= (args.args[1] == 11);
280 passed &= (args.args[2] == 12);
281 break;
282 case 5:
283 passed &= !rc;
284 passed &= (args.args_count == 2);
285 passed &= (args.args[0] == 13);
286 passed &= (args.args[1] == 14);
287 break;
288 case 6:
289 passed &= !rc;
290 passed &= (args.args_count == 1);
291 passed &= (args.args[0] == 15);
292 break;
293 default:
294 passed = false;
295 }
296
297 selftest(passed, "index %i - data error on node %s rc=%i\n",
298 i, args.np->full_name, rc);
299 }
300 of_node_put(np);
301}
302
157static int __init of_selftest(void) 303static int __init of_selftest(void)
158{ 304{
159 struct device_node *np; 305 struct device_node *np;
@@ -168,7 +314,10 @@ static int __init of_selftest(void)
168 pr_info("start of selftest - you will see error messages\n"); 314 pr_info("start of selftest - you will see error messages\n");
169 of_selftest_parse_phandle_with_args(); 315 of_selftest_parse_phandle_with_args();
170 of_selftest_property_match_string(); 316 of_selftest_property_match_string();
171 pr_info("end of selftest - %s\n", selftest_passed ? "PASS" : "FAIL"); 317 of_selftest_parse_interrupts();
318 of_selftest_parse_interrupts_extended();
319 pr_info("end of selftest - %i passed, %i failed\n",
320 selftest_results.passed, selftest_results.failed);
172 return 0; 321 return 0;
173} 322}
174late_initcall(of_selftest); 323late_initcall(of_selftest);