aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-07-13 02:19:31 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-07-13 04:50:15 -0400
commita83f982313bc60dd3d87e50f8c88d6a169e8a5a0 (patch)
treeccbf0bd78ad540d870c295712fd60e49f9206d8a
parent9bbd952e7f965757b5c913b6f98ad37a191137bd (diff)
[SPARC]: Fix OF register translations under sub-PCI busses.
There is an implicit assumption in the code that ranges will translate to something that can fit in 2 32-bit cells, or a 64-bit value. For certain kinds of things below PCI this isn't necessarily true. Here is what the relevant OF device hierarchy looks like for one of the serial controllers on an Ultra5: Node 0xf005f1e0 ranges: 00000000.00000000.00000000.000001fe.01000000.00000000.01000000 01000000.00000000.00000000.000001fe.02000000.00000000.01000000 02000000.00000000.00000000.000001ff.00000000.00000001.00000000 03000000.00000000.00000000.000001ff.00000000.00000001.00000000 device_type: 'pci' model: 'SUNW,sabre' Node 0xf005f9d4 device_type: 'pci' model: 'SUNW,simba' Node 0xf0060d24 ranges: 00000010.00000000 82010810.00000000.f0000000 01000000 00000014.00000000 82010814.00000000.f1000000 00800000 name: 'ebus' Node 0xf0062dac reg: 00000014.003083f8.00000008 --> 0x1ff.f13083f8 device_type: 'serial' name: 'su' So the correct translation here is: 1) Match "su" register to second ranges entry of 'ebus', which translates into a PCI triplet "82010814.00000000.f1000000" of size 00800000, which gives us "82010814.00000000.f13083f8". 2) Pass-through "SUNW,simba" since it lacks ranges property 3) Match "82010814.00000000.f13083f8" to third ranges property of PCI controller node 'SUNW,sabre', and we arrive at the final physical MMIO address of "0x1fff13083f8". Due to the 2-cell assumption, we couldn't translate to a PCI 3-cell value, and we couldn't perform a pass-thru on it either. It was easiest to just stop splitting the ranges application operation between two methods, ->map and ->translate, and just let ->map do all the work. That way it would work purely on 32-bit cell arrays instead of having to "return" some value like a u64. It's still not %100 correct because the out-of-range check is still done using the 64 least significant bits of the range and address. But it does work for all the cases I've thrown at it so far. Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--arch/sparc/kernel/of_device.c167
-rw-r--r--arch/sparc64/kernel/of_device.c308
2 files changed, 271 insertions, 204 deletions
diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c
index bbd3203b86af..5a2faad5d043 100644
--- a/arch/sparc/kernel/of_device.c
+++ b/arch/sparc/kernel/of_device.c
@@ -183,7 +183,7 @@ struct bus_type of_bus_type = {
183}; 183};
184EXPORT_SYMBOL(of_bus_type); 184EXPORT_SYMBOL(of_bus_type);
185 185
186static inline u64 of_read_addr(u32 *cell, int size) 186static inline u64 of_read_addr(const u32 *cell, int size)
187{ 187{
188 u64 r = 0; 188 u64 r = 0;
189 while (size--) 189 while (size--)
@@ -209,8 +209,8 @@ struct of_bus {
209 int (*match)(struct device_node *parent); 209 int (*match)(struct device_node *parent);
210 void (*count_cells)(struct device_node *child, 210 void (*count_cells)(struct device_node *child,
211 int *addrc, int *sizec); 211 int *addrc, int *sizec);
212 u64 (*map)(u32 *addr, u32 *range, int na, int ns, int pna); 212 int (*map)(u32 *addr, const u32 *range,
213 int (*translate)(u32 *addr, u64 offset, int na); 213 int na, int ns, int pna);
214 unsigned int (*get_flags)(u32 *addr); 214 unsigned int (*get_flags)(u32 *addr);
215}; 215};
216 216
@@ -224,27 +224,49 @@ static void of_bus_default_count_cells(struct device_node *dev,
224 get_cells(dev, addrc, sizec); 224 get_cells(dev, addrc, sizec);
225} 225}
226 226
227static u64 of_bus_default_map(u32 *addr, u32 *range, int na, int ns, int pna) 227/* Make sure the least significant 64-bits are in-range. Even
228 * for 3 or 4 cell values it is a good enough approximation.
229 */
230static int of_out_of_range(const u32 *addr, const u32 *base,
231 const u32 *size, int na, int ns)
228{ 232{
229 u64 cp, s, da; 233 u64 a = of_read_addr(addr, na);
234 u64 b = of_read_addr(base, na);
235
236 if (a < b)
237 return 1;
230 238
231 cp = of_read_addr(range, na); 239 b += of_read_addr(size, ns);
232 s = of_read_addr(range + na + pna, ns); 240 if (a >= b)
233 da = of_read_addr(addr, na); 241 return 1;
234 242
235 if (da < cp || da >= (cp + s)) 243 return 0;
236 return OF_BAD_ADDR;
237 return da - cp;
238} 244}
239 245
240static int of_bus_default_translate(u32 *addr, u64 offset, int na) 246static int of_bus_default_map(u32 *addr, const u32 *range,
247 int na, int ns, int pna)
241{ 248{
242 u64 a = of_read_addr(addr, na); 249 u32 result[OF_MAX_ADDR_CELLS];
243 memset(addr, 0, na * 4); 250 int i;
244 a += offset; 251
245 if (na > 1) 252 if (ns > 2) {
246 addr[na - 2] = a >> 32; 253 printk("of_device: Cannot handle size cells (%d) > 2.", ns);
247 addr[na - 1] = a & 0xffffffffu; 254 return -EINVAL;
255 }
256
257 if (of_out_of_range(addr, range, range + na + pna, na, ns))
258 return -EINVAL;
259
260 /* Start with the parent range base. */
261 memcpy(result, range + na, pna * 4);
262
263 /* Add in the child address offset. */
264 for (i = 0; i < na; i++)
265 result[pna - 1 - i] +=
266 (addr[na - 1 - i] -
267 range[na - 1 - i]);
268
269 memcpy(addr, result, pna * 4);
248 270
249 return 0; 271 return 0;
250} 272}
@@ -254,14 +276,26 @@ static unsigned int of_bus_default_get_flags(u32 *addr)
254 return IORESOURCE_MEM; 276 return IORESOURCE_MEM;
255} 277}
256 278
257
258/* 279/*
259 * PCI bus specific translator 280 * PCI bus specific translator
260 */ 281 */
261 282
262static int of_bus_pci_match(struct device_node *np) 283static int of_bus_pci_match(struct device_node *np)
263{ 284{
264 return !strcmp(np->type, "pci") || !strcmp(np->type, "pciex"); 285 if (!strcmp(np->type, "pci") || !strcmp(np->type, "pciex")) {
286 /* Do not do PCI specific frobbing if the
287 * PCI bridge lacks a ranges property. We
288 * want to pass it through up to the next
289 * parent as-is, not with the PCI translate
290 * method which chops off the top address cell.
291 */
292 if (!of_find_property(np, "ranges", NULL))
293 return 0;
294
295 return 1;
296 }
297
298 return 0;
265} 299}
266 300
267static void of_bus_pci_count_cells(struct device_node *np, 301static void of_bus_pci_count_cells(struct device_node *np,
@@ -273,27 +307,32 @@ static void of_bus_pci_count_cells(struct device_node *np,
273 *sizec = 2; 307 *sizec = 2;
274} 308}
275 309
276static u64 of_bus_pci_map(u32 *addr, u32 *range, int na, int ns, int pna) 310static int of_bus_pci_map(u32 *addr, const u32 *range,
311 int na, int ns, int pna)
277{ 312{
278 u64 cp, s, da; 313 u32 result[OF_MAX_ADDR_CELLS];
314 int i;
279 315
280 /* Check address type match */ 316 /* Check address type match */
281 if ((addr[0] ^ range[0]) & 0x03000000) 317 if ((addr[0] ^ range[0]) & 0x03000000)
282 return OF_BAD_ADDR; 318 return -EINVAL;
283 319
284 /* Read address values, skipping high cell */ 320 if (of_out_of_range(addr + 1, range + 1, range + na + pna,
285 cp = of_read_addr(range + 1, na - 1); 321 na - 1, ns))
286 s = of_read_addr(range + na + pna, ns); 322 return -EINVAL;
287 da = of_read_addr(addr + 1, na - 1);
288 323
289 if (da < cp || da >= (cp + s)) 324 /* Start with the parent range base. */
290 return OF_BAD_ADDR; 325 memcpy(result, range + na, pna * 4);
291 return da - cp;
292}
293 326
294static int of_bus_pci_translate(u32 *addr, u64 offset, int na) 327 /* Add in the child address offset, skipping high cell. */
295{ 328 for (i = 0; i < na - 1; i++)
296 return of_bus_default_translate(addr + 1, offset, na - 1); 329 result[pna - 1 - i] +=
330 (addr[na - 1 - i] -
331 range[na - 1 - i]);
332
333 memcpy(addr, result, pna * 4);
334
335 return 0;
297} 336}
298 337
299static unsigned int of_bus_pci_get_flags(u32 *addr) 338static unsigned int of_bus_pci_get_flags(u32 *addr)
@@ -332,16 +371,11 @@ static void of_bus_sbus_count_cells(struct device_node *child,
332 *sizec = 1; 371 *sizec = 1;
333} 372}
334 373
335static u64 of_bus_sbus_map(u32 *addr, u32 *range, int na, int ns, int pna) 374static int of_bus_sbus_map(u32 *addr, const u32 *range, int na, int ns, int pna)
336{ 375{
337 return of_bus_default_map(addr, range, na, ns, pna); 376 return of_bus_default_map(addr, range, na, ns, pna);
338} 377}
339 378
340static int of_bus_sbus_translate(u32 *addr, u64 offset, int na)
341{
342 return of_bus_default_translate(addr, offset, na);
343}
344
345static unsigned int of_bus_sbus_get_flags(u32 *addr) 379static unsigned int of_bus_sbus_get_flags(u32 *addr)
346{ 380{
347 return IORESOURCE_MEM; 381 return IORESOURCE_MEM;
@@ -360,7 +394,6 @@ static struct of_bus of_busses[] = {
360 .match = of_bus_pci_match, 394 .match = of_bus_pci_match,
361 .count_cells = of_bus_pci_count_cells, 395 .count_cells = of_bus_pci_count_cells,
362 .map = of_bus_pci_map, 396 .map = of_bus_pci_map,
363 .translate = of_bus_pci_translate,
364 .get_flags = of_bus_pci_get_flags, 397 .get_flags = of_bus_pci_get_flags,
365 }, 398 },
366 /* SBUS */ 399 /* SBUS */
@@ -370,7 +403,6 @@ static struct of_bus of_busses[] = {
370 .match = of_bus_sbus_match, 403 .match = of_bus_sbus_match,
371 .count_cells = of_bus_sbus_count_cells, 404 .count_cells = of_bus_sbus_count_cells,
372 .map = of_bus_sbus_map, 405 .map = of_bus_sbus_map,
373 .translate = of_bus_sbus_translate,
374 .get_flags = of_bus_sbus_get_flags, 406 .get_flags = of_bus_sbus_get_flags,
375 }, 407 },
376 /* Default */ 408 /* Default */
@@ -380,7 +412,6 @@ static struct of_bus of_busses[] = {
380 .match = NULL, 412 .match = NULL,
381 .count_cells = of_bus_default_count_cells, 413 .count_cells = of_bus_default_count_cells,
382 .map = of_bus_default_map, 414 .map = of_bus_default_map,
383 .translate = of_bus_default_translate,
384 .get_flags = of_bus_default_get_flags, 415 .get_flags = of_bus_default_get_flags,
385 }, 416 },
386}; 417};
@@ -405,33 +436,34 @@ static int __init build_one_resource(struct device_node *parent,
405 u32 *ranges; 436 u32 *ranges;
406 unsigned int rlen; 437 unsigned int rlen;
407 int rone; 438 int rone;
408 u64 offset = OF_BAD_ADDR;
409 439
410 ranges = of_get_property(parent, "ranges", &rlen); 440 ranges = of_get_property(parent, "ranges", &rlen);
411 if (ranges == NULL || rlen == 0) { 441 if (ranges == NULL || rlen == 0) {
412 offset = of_read_addr(addr, na); 442 u32 result[OF_MAX_ADDR_CELLS];
413 memset(addr, 0, pna * 4); 443 int i;
414 goto finish; 444
445 memset(result, 0, pna * 4);
446 for (i = 0; i < na; i++)
447 result[pna - 1 - i] =
448 addr[na - 1 - i];
449
450 memcpy(addr, result, pna * 4);
451 return 0;
415 } 452 }
416 453
417 /* Now walk through the ranges */ 454 /* Now walk through the ranges */
418 rlen /= 4; 455 rlen /= 4;
419 rone = na + pna + ns; 456 rone = na + pna + ns;
420 for (; rlen >= rone; rlen -= rone, ranges += rone) { 457 for (; rlen >= rone; rlen -= rone, ranges += rone) {
421 offset = bus->map(addr, ranges, na, ns, pna); 458 if (!bus->map(addr, ranges, na, ns, pna))
422 if (offset != OF_BAD_ADDR) 459 return 0;
423 break;
424 } 460 }
425 if (offset == OF_BAD_ADDR)
426 return 1;
427
428 memcpy(addr, ranges + na, 4 * pna);
429 461
430finish: 462 return 1;
431 /* Translate it into parent bus space */
432 return pbus->translate(addr, offset, pna);
433} 463}
434 464
465static int of_resource_verbose;
466
435static void __init build_device_resources(struct of_device *op, 467static void __init build_device_resources(struct of_device *op,
436 struct device *parent) 468 struct device *parent)
437{ 469{
@@ -497,7 +529,8 @@ static void __init build_device_resources(struct of_device *op,
497 pbus = of_match_bus(pp); 529 pbus = of_match_bus(pp);
498 pbus->count_cells(dp, &pna, &pns); 530 pbus->count_cells(dp, &pna, &pns);
499 531
500 if (build_one_resource(dp, bus, pbus, addr, dna, dns, pna)) 532 if (build_one_resource(dp, bus, pbus, addr,
533 dna, dns, pna))
501 break; 534 break;
502 535
503 dna = pna; 536 dna = pna;
@@ -507,6 +540,12 @@ static void __init build_device_resources(struct of_device *op,
507 540
508 build_res: 541 build_res:
509 memset(r, 0, sizeof(*r)); 542 memset(r, 0, sizeof(*r));
543
544 if (of_resource_verbose)
545 printk("%s reg[%d] -> %llx\n",
546 op->node->full_name, index,
547 result);
548
510 if (result != OF_BAD_ADDR) { 549 if (result != OF_BAD_ADDR) {
511 r->start = result & 0xffffffff; 550 r->start = result & 0xffffffff;
512 r->end = result + size - 1; 551 r->end = result + size - 1;
@@ -643,6 +682,18 @@ static int __init of_bus_driver_init(void)
643 682
644postcore_initcall(of_bus_driver_init); 683postcore_initcall(of_bus_driver_init);
645 684
685static int __init of_debug(char *str)
686{
687 int val = 0;
688
689 get_option(&str, &val);
690 if (val & 1)
691 of_resource_verbose = 1;
692 return 1;
693}
694
695__setup("of_debug=", of_debug);
696
646int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus) 697int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus)
647{ 698{
648 /* initialize common driver fields */ 699 /* initialize common driver fields */
diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c
index 8e177a0abc1c..7064cee290ae 100644
--- a/arch/sparc64/kernel/of_device.c
+++ b/arch/sparc64/kernel/of_device.c
@@ -210,7 +210,7 @@ struct bus_type of_bus_type = {
210}; 210};
211EXPORT_SYMBOL(of_bus_type); 211EXPORT_SYMBOL(of_bus_type);
212 212
213static inline u64 of_read_addr(u32 *cell, int size) 213static inline u64 of_read_addr(const u32 *cell, int size)
214{ 214{
215 u64 r = 0; 215 u64 r = 0;
216 while (size--) 216 while (size--)
@@ -236,8 +236,8 @@ struct of_bus {
236 int (*match)(struct device_node *parent); 236 int (*match)(struct device_node *parent);
237 void (*count_cells)(struct device_node *child, 237 void (*count_cells)(struct device_node *child,
238 int *addrc, int *sizec); 238 int *addrc, int *sizec);
239 u64 (*map)(u32 *addr, u32 *range, int na, int ns, int pna); 239 int (*map)(u32 *addr, const u32 *range,
240 int (*translate)(u32 *addr, u64 offset, int na); 240 int na, int ns, int pna);
241 unsigned int (*get_flags)(u32 *addr); 241 unsigned int (*get_flags)(u32 *addr);
242}; 242};
243 243
@@ -251,27 +251,49 @@ static void of_bus_default_count_cells(struct device_node *dev,
251 get_cells(dev, addrc, sizec); 251 get_cells(dev, addrc, sizec);
252} 252}
253 253
254static u64 of_bus_default_map(u32 *addr, u32 *range, int na, int ns, int pna) 254/* Make sure the least significant 64-bits are in-range. Even
255 * for 3 or 4 cell values it is a good enough approximation.
256 */
257static int of_out_of_range(const u32 *addr, const u32 *base,
258 const u32 *size, int na, int ns)
255{ 259{
256 u64 cp, s, da; 260 u64 a = of_read_addr(addr, na);
261 u64 b = of_read_addr(base, na);
257 262
258 cp = of_read_addr(range, na); 263 if (a < b)
259 s = of_read_addr(range + na + pna, ns); 264 return 1;
260 da = of_read_addr(addr, na);
261 265
262 if (da < cp || da >= (cp + s)) 266 b += of_read_addr(size, ns);
263 return OF_BAD_ADDR; 267 if (a >= b)
264 return da - cp; 268 return 1;
269
270 return 0;
265} 271}
266 272
267static int of_bus_default_translate(u32 *addr, u64 offset, int na) 273static int of_bus_default_map(u32 *addr, const u32 *range,
274 int na, int ns, int pna)
268{ 275{
269 u64 a = of_read_addr(addr, na); 276 u32 result[OF_MAX_ADDR_CELLS];
270 memset(addr, 0, na * 4); 277 int i;
271 a += offset; 278
272 if (na > 1) 279 if (ns > 2) {
273 addr[na - 2] = a >> 32; 280 printk("of_device: Cannot handle size cells (%d) > 2.", ns);
274 addr[na - 1] = a & 0xffffffffu; 281 return -EINVAL;
282 }
283
284 if (of_out_of_range(addr, range, range + na + pna, na, ns))
285 return -EINVAL;
286
287 /* Start with the parent range base. */
288 memcpy(result, range + na, pna * 4);
289
290 /* Add in the child address offset. */
291 for (i = 0; i < na; i++)
292 result[pna - 1 - i] +=
293 (addr[na - 1 - i] -
294 range[na - 1 - i]);
295
296 memcpy(addr, result, pna * 4);
275 297
276 return 0; 298 return 0;
277} 299}
@@ -287,7 +309,20 @@ static unsigned int of_bus_default_get_flags(u32 *addr)
287 309
288static int of_bus_pci_match(struct device_node *np) 310static int of_bus_pci_match(struct device_node *np)
289{ 311{
290 return !strcmp(np->type, "pci") || !strcmp(np->type, "pciex"); 312 if (!strcmp(np->type, "pci") || !strcmp(np->type, "pciex")) {
313 /* Do not do PCI specific frobbing if the
314 * PCI bridge lacks a ranges property. We
315 * want to pass it through up to the next
316 * parent as-is, not with the PCI translate
317 * method which chops off the top address cell.
318 */
319 if (!of_find_property(np, "ranges", NULL))
320 return 0;
321
322 return 1;
323 }
324
325 return 0;
291} 326}
292 327
293static void of_bus_pci_count_cells(struct device_node *np, 328static void of_bus_pci_count_cells(struct device_node *np,
@@ -299,27 +334,32 @@ static void of_bus_pci_count_cells(struct device_node *np,
299 *sizec = 2; 334 *sizec = 2;
300} 335}
301 336
302static u64 of_bus_pci_map(u32 *addr, u32 *range, int na, int ns, int pna) 337static int of_bus_pci_map(u32 *addr, const u32 *range,
338 int na, int ns, int pna)
303{ 339{
304 u64 cp, s, da; 340 u32 result[OF_MAX_ADDR_CELLS];
341 int i;
305 342
306 /* Check address type match */ 343 /* Check address type match */
307 if ((addr[0] ^ range[0]) & 0x03000000) 344 if ((addr[0] ^ range[0]) & 0x03000000)
308 return OF_BAD_ADDR; 345 return -EINVAL;
309 346
310 /* Read address values, skipping high cell */ 347 if (of_out_of_range(addr + 1, range + 1, range + na + pna,
311 cp = of_read_addr(range + 1, na - 1); 348 na - 1, ns))
312 s = of_read_addr(range + na + pna, ns); 349 return -EINVAL;
313 da = of_read_addr(addr + 1, na - 1);
314 350
315 if (da < cp || da >= (cp + s)) 351 /* Start with the parent range base. */
316 return OF_BAD_ADDR; 352 memcpy(result, range + na, pna * 4);
317 return da - cp;
318}
319 353
320static int of_bus_pci_translate(u32 *addr, u64 offset, int na) 354 /* Add in the child address offset, skipping high cell. */
321{ 355 for (i = 0; i < na - 1; i++)
322 return of_bus_default_translate(addr + 1, offset, na - 1); 356 result[pna - 1 - i] +=
357 (addr[na - 1 - i] -
358 range[na - 1 - i]);
359
360 memcpy(addr, result, pna * 4);
361
362 return 0;
323} 363}
324 364
325static unsigned int of_bus_pci_get_flags(u32 *addr) 365static unsigned int of_bus_pci_get_flags(u32 *addr)
@@ -340,59 +380,6 @@ static unsigned int of_bus_pci_get_flags(u32 *addr)
340} 380}
341 381
342/* 382/*
343 * ISA bus specific translator
344 */
345
346static int of_bus_isa_match(struct device_node *np)
347{
348 return !strcmp(np->name, "isa");
349}
350
351static void of_bus_isa_count_cells(struct device_node *child,
352 int *addrc, int *sizec)
353{
354 if (addrc)
355 *addrc = 2;
356 if (sizec)
357 *sizec = 1;
358}
359
360static u64 of_bus_isa_map(u32 *addr, u32 *range, int na, int ns, int pna)
361{
362 u64 cp, s, da;
363
364 /* Check address type match */
365 if ((addr[0] ^ range[0]) & 0x00000001)
366 return OF_BAD_ADDR;
367
368 /* Read address values, skipping high cell */
369 cp = of_read_addr(range + 1, na - 1);
370 s = of_read_addr(range + na + pna, ns);
371 da = of_read_addr(addr + 1, na - 1);
372
373 if (da < cp || da >= (cp + s))
374 return OF_BAD_ADDR;
375 return da - cp;
376}
377
378static int of_bus_isa_translate(u32 *addr, u64 offset, int na)
379{
380 return of_bus_default_translate(addr + 1, offset, na - 1);
381}
382
383static unsigned int of_bus_isa_get_flags(u32 *addr)
384{
385 unsigned int flags = 0;
386 u32 w = addr[0];
387
388 if (w & 1)
389 flags |= IORESOURCE_IO;
390 else
391 flags |= IORESOURCE_MEM;
392 return flags;
393}
394
395/*
396 * SBUS bus specific translator 383 * SBUS bus specific translator
397 */ 384 */
398 385
@@ -411,16 +398,11 @@ static void of_bus_sbus_count_cells(struct device_node *child,
411 *sizec = 1; 398 *sizec = 1;
412} 399}
413 400
414static u64 of_bus_sbus_map(u32 *addr, u32 *range, int na, int ns, int pna) 401static int of_bus_sbus_map(u32 *addr, const u32 *range, int na, int ns, int pna)
415{ 402{
416 return of_bus_default_map(addr, range, na, ns, pna); 403 return of_bus_default_map(addr, range, na, ns, pna);
417} 404}
418 405
419static int of_bus_sbus_translate(u32 *addr, u64 offset, int na)
420{
421 return of_bus_default_translate(addr, offset, na);
422}
423
424static unsigned int of_bus_sbus_get_flags(u32 *addr) 406static unsigned int of_bus_sbus_get_flags(u32 *addr)
425{ 407{
426 return IORESOURCE_MEM; 408 return IORESOURCE_MEM;
@@ -439,19 +421,8 @@ static struct of_bus of_busses[] = {
439 .match = of_bus_pci_match, 421 .match = of_bus_pci_match,
440 .count_cells = of_bus_pci_count_cells, 422 .count_cells = of_bus_pci_count_cells,
441 .map = of_bus_pci_map, 423 .map = of_bus_pci_map,
442 .translate = of_bus_pci_translate,
443 .get_flags = of_bus_pci_get_flags, 424 .get_flags = of_bus_pci_get_flags,
444 }, 425 },
445 /* ISA */
446 {
447 .name = "isa",
448 .addr_prop_name = "reg",
449 .match = of_bus_isa_match,
450 .count_cells = of_bus_isa_count_cells,
451 .map = of_bus_isa_map,
452 .translate = of_bus_isa_translate,
453 .get_flags = of_bus_isa_get_flags,
454 },
455 /* SBUS */ 426 /* SBUS */
456 { 427 {
457 .name = "sbus", 428 .name = "sbus",
@@ -459,7 +430,6 @@ static struct of_bus of_busses[] = {
459 .match = of_bus_sbus_match, 430 .match = of_bus_sbus_match,
460 .count_cells = of_bus_sbus_count_cells, 431 .count_cells = of_bus_sbus_count_cells,
461 .map = of_bus_sbus_map, 432 .map = of_bus_sbus_map,
462 .translate = of_bus_sbus_translate,
463 .get_flags = of_bus_sbus_get_flags, 433 .get_flags = of_bus_sbus_get_flags,
464 }, 434 },
465 /* Default */ 435 /* Default */
@@ -469,7 +439,6 @@ static struct of_bus of_busses[] = {
469 .match = NULL, 439 .match = NULL,
470 .count_cells = of_bus_default_count_cells, 440 .count_cells = of_bus_default_count_cells,
471 .map = of_bus_default_map, 441 .map = of_bus_default_map,
472 .translate = of_bus_default_translate,
473 .get_flags = of_bus_default_get_flags, 442 .get_flags = of_bus_default_get_flags,
474 }, 443 },
475}; 444};
@@ -494,33 +463,62 @@ static int __init build_one_resource(struct device_node *parent,
494 u32 *ranges; 463 u32 *ranges;
495 unsigned int rlen; 464 unsigned int rlen;
496 int rone; 465 int rone;
497 u64 offset = OF_BAD_ADDR;
498 466
499 ranges = of_get_property(parent, "ranges", &rlen); 467 ranges = of_get_property(parent, "ranges", &rlen);
500 if (ranges == NULL || rlen == 0) { 468 if (ranges == NULL || rlen == 0) {
501 offset = of_read_addr(addr, na); 469 u32 result[OF_MAX_ADDR_CELLS];
502 memset(addr, 0, pna * 4); 470 int i;
503 goto finish; 471
472 memset(result, 0, pna * 4);
473 for (i = 0; i < na; i++)
474 result[pna - 1 - i] =
475 addr[na - 1 - i];
476
477 memcpy(addr, result, pna * 4);
478 return 0;
504 } 479 }
505 480
506 /* Now walk through the ranges */ 481 /* Now walk through the ranges */
507 rlen /= 4; 482 rlen /= 4;
508 rone = na + pna + ns; 483 rone = na + pna + ns;
509 for (; rlen >= rone; rlen -= rone, ranges += rone) { 484 for (; rlen >= rone; rlen -= rone, ranges += rone) {
510 offset = bus->map(addr, ranges, na, ns, pna); 485 if (!bus->map(addr, ranges, na, ns, pna))
511 if (offset != OF_BAD_ADDR) 486 return 0;
512 break;
513 } 487 }
514 if (offset == OF_BAD_ADDR) 488
489 return 1;
490}
491
492static int __init use_1to1_mapping(struct device_node *pp)
493{
494 char *model;
495
496 /* If this is on the PMU bus, don't try to translate it even
497 * if a ranges property exists.
498 */
499 if (!strcmp(pp->name, "pmu"))
515 return 1; 500 return 1;
516 501
517 memcpy(addr, ranges + na, 4 * pna); 502 /* If we have a ranges property in the parent, use it. */
503 if (of_find_property(pp, "ranges", NULL) != NULL)
504 return 0;
518 505
519finish: 506 /* If the parent is the dma node of an ISA bus, pass
520 /* Translate it into parent bus space */ 507 * the translation up to the root.
521 return pbus->translate(addr, offset, pna); 508 */
509 if (!strcmp(pp->name, "dma"))
510 return 0;
511
512 /* Similarly for Simba PCI bridges. */
513 model = of_get_property(pp, "model", NULL);
514 if (model && !strcmp(model, "SUNW,simba"))
515 return 0;
516
517 return 1;
522} 518}
523 519
520static int of_resource_verbose;
521
524static void __init build_device_resources(struct of_device *op, 522static void __init build_device_resources(struct of_device *op,
525 struct device *parent) 523 struct device *parent)
526{ 524{
@@ -564,15 +562,7 @@ static void __init build_device_resources(struct of_device *op,
564 562
565 memcpy(addr, reg, na * 4); 563 memcpy(addr, reg, na * 4);
566 564
567 /* If the immediate parent has no ranges property to apply, 565 if (use_1to1_mapping(pp)) {
568 * just use a 1<->1 mapping. Unless it is the 'dma' child
569 * of an isa bus, which must be passed up towards the root.
570 *
571 * Also, don't try to translate PMU bus device registers.
572 */
573 if ((of_find_property(pp, "ranges", NULL) == NULL &&
574 strcmp(pp->name, "dma") != 0) ||
575 !strcmp(pp->name, "pmu")) {
576 result = of_read_addr(addr, na); 566 result = of_read_addr(addr, na);
577 goto build_res; 567 goto build_res;
578 } 568 }
@@ -591,7 +581,8 @@ static void __init build_device_resources(struct of_device *op,
591 pbus = of_match_bus(pp); 581 pbus = of_match_bus(pp);
592 pbus->count_cells(dp, &pna, &pns); 582 pbus->count_cells(dp, &pna, &pns);
593 583
594 if (build_one_resource(dp, bus, pbus, addr, dna, dns, pna)) 584 if (build_one_resource(dp, bus, pbus, addr,
585 dna, dns, pna))
595 break; 586 break;
596 587
597 dna = pna; 588 dna = pna;
@@ -601,6 +592,12 @@ static void __init build_device_resources(struct of_device *op,
601 592
602 build_res: 593 build_res:
603 memset(r, 0, sizeof(*r)); 594 memset(r, 0, sizeof(*r));
595
596 if (of_resource_verbose)
597 printk("%s reg[%d] -> %lx\n",
598 op->node->full_name, index,
599 result);
600
604 if (result != OF_BAD_ADDR) { 601 if (result != OF_BAD_ADDR) {
605 if (tlb_type == hypervisor) 602 if (tlb_type == hypervisor)
606 result &= 0x0fffffffffffffffUL; 603 result &= 0x0fffffffffffffffUL;
@@ -684,6 +681,8 @@ static unsigned int __init pci_irq_swizzle(struct device_node *dp,
684 return ret; 681 return ret;
685} 682}
686 683
684static int of_irq_verbose;
685
687static unsigned int __init build_one_device_irq(struct of_device *op, 686static unsigned int __init build_one_device_irq(struct of_device *op,
688 struct device *parent, 687 struct device *parent,
689 unsigned int irq) 688 unsigned int irq)
@@ -698,10 +697,11 @@ static unsigned int __init build_one_device_irq(struct of_device *op,
698 if (dp->irq_trans) { 697 if (dp->irq_trans) {
699 irq = dp->irq_trans->irq_build(dp, irq, 698 irq = dp->irq_trans->irq_build(dp, irq,
700 dp->irq_trans->data); 699 dp->irq_trans->data);
701#if 1 700
702 printk("%s: direct translate %x --> %x\n", 701 if (of_irq_verbose)
703 dp->full_name, orig_irq, irq); 702 printk("%s: direct translate %x --> %x\n",
704#endif 703 dp->full_name, orig_irq, irq);
704
705 return irq; 705 return irq;
706 } 706 }
707 707
@@ -728,12 +728,13 @@ static unsigned int __init build_one_device_irq(struct of_device *op,
728 iret = apply_interrupt_map(dp, pp, 728 iret = apply_interrupt_map(dp, pp,
729 imap, imlen, imsk, 729 imap, imlen, imsk,
730 &irq); 730 &irq);
731#if 1 731
732 printk("%s: Apply [%s:%x] imap --> [%s:%x]\n", 732 if (of_irq_verbose)
733 op->node->full_name, 733 printk("%s: Apply [%s:%x] imap --> [%s:%x]\n",
734 pp->full_name, this_orig_irq, 734 op->node->full_name,
735 (iret ? iret->full_name : "NULL"), irq); 735 pp->full_name, this_orig_irq,
736#endif 736 (iret ? iret->full_name : "NULL"), irq);
737
737 if (!iret) 738 if (!iret)
738 break; 739 break;
739 740
@@ -747,11 +748,13 @@ static unsigned int __init build_one_device_irq(struct of_device *op,
747 unsigned int this_orig_irq = irq; 748 unsigned int this_orig_irq = irq;
748 749
749 irq = pci_irq_swizzle(dp, pp, irq); 750 irq = pci_irq_swizzle(dp, pp, irq);
750#if 1 751 if (of_irq_verbose)
751 printk("%s: PCI swizzle [%s] %x --> %x\n", 752 printk("%s: PCI swizzle [%s] "
752 op->node->full_name, 753 "%x --> %x\n",
753 pp->full_name, this_orig_irq, irq); 754 op->node->full_name,
754#endif 755 pp->full_name, this_orig_irq,
756 irq);
757
755 } 758 }
756 759
757 if (pp->irq_trans) { 760 if (pp->irq_trans) {
@@ -767,10 +770,9 @@ static unsigned int __init build_one_device_irq(struct of_device *op,
767 770
768 irq = ip->irq_trans->irq_build(op->node, irq, 771 irq = ip->irq_trans->irq_build(op->node, irq,
769 ip->irq_trans->data); 772 ip->irq_trans->data);
770#if 1 773 if (of_irq_verbose)
771 printk("%s: Apply IRQ trans [%s] %x --> %x\n", 774 printk("%s: Apply IRQ trans [%s] %x --> %x\n",
772 op->node->full_name, ip->full_name, orig_irq, irq); 775 op->node->full_name, ip->full_name, orig_irq, irq);
773#endif
774 776
775 return irq; 777 return irq;
776} 778}
@@ -870,6 +872,20 @@ static int __init of_bus_driver_init(void)
870 872
871postcore_initcall(of_bus_driver_init); 873postcore_initcall(of_bus_driver_init);
872 874
875static int __init of_debug(char *str)
876{
877 int val = 0;
878
879 get_option(&str, &val);
880 if (val & 1)
881 of_resource_verbose = 1;
882 if (val & 2)
883 of_irq_verbose = 1;
884 return 1;
885}
886
887__setup("of_debug=", of_debug);
888
873int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus) 889int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus)
874{ 890{
875 /* initialize common driver fields */ 891 /* initialize common driver fields */