diff options
author | Rob Herring <rob.herring@calxeda.com> | 2013-11-07 11:34:46 -0500 |
---|---|---|
committer | Rob Herring <rob.herring@calxeda.com> | 2013-11-07 11:34:46 -0500 |
commit | b5480950c6cbb7b07ab1c1a5af0dc661a1cb6f24 (patch) | |
tree | b5fcb00387a838beb2bcf2f8ed2fd3d6d460c8ae /drivers/of | |
parent | e363bbac316ffb5daaf45d855f82680148cafe20 (diff) | |
parent | 355e62f5ad12b005c862838156262eb2df2f8dff (diff) |
Merge remote-tracking branch 'grant/devicetree/next' into for-next
Diffstat (limited to 'drivers/of')
-rw-r--r-- | drivers/of/address.c | 10 | ||||
-rw-r--r-- | drivers/of/base.c | 60 | ||||
-rw-r--r-- | drivers/of/irq.c | 164 | ||||
-rw-r--r-- | drivers/of/of_pci_irq.c | 40 | ||||
-rw-r--r-- | drivers/of/selftest.c | 161 |
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 | */ | ||
296 | bool __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 | */ |
308 | struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) | 333 | struct 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 | } |
1184 | EXPORT_SYMBOL_GPL(of_property_count_strings); | 1193 | EXPORT_SYMBOL_GPL(of_property_count_strings); |
1185 | 1194 | ||
1195 | void 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 | |||
1186 | static int __of_parse_phandle_with_args(const struct device_node *np, | 1204 | static 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 | */ |
37 | unsigned int irq_of_parse_and_map(struct device_node *dev, int index) | 37 | unsigned 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 | } |
47 | EXPORT_SYMBOL_GPL(irq_of_parse_and_map); | 46 | EXPORT_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 | */ |
96 | int of_irq_map_raw(struct device_node *parent, const __be32 *intspec, | 95 | int 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 | } |
272 | EXPORT_SYMBOL_GPL(of_irq_map_raw); | 276 | EXPORT_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 | */ |
283 | int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq) | 288 | int 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 | } |
331 | EXPORT_SYMBOL_GPL(of_irq_map_one); | 348 | EXPORT_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 | */ |
369 | int of_irq_count(struct device_node *dev) | 386 | int 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 | */ |
17 | int of_irq_map_pci(const struct pci_dev *pdev, struct of_irq *out_irq) | 17 | int 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 | } |
92 | EXPORT_SYMBOL_GPL(of_irq_map_pci); | 95 | EXPORT_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 | */ | ||
106 | int 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 | } | ||
119 | EXPORT_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 | ||
17 | static bool selftest_passed = true; | 18 | static 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 | ||
162 | static 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 | |||
234 | static 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 | |||
157 | static int __init of_selftest(void) | 303 | static 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 | } |
174 | late_initcall(of_selftest); | 323 | late_initcall(of_selftest); |