diff options
Diffstat (limited to 'arch/sparc64/kernel/ebus.c')
-rw-r--r-- | arch/sparc64/kernel/ebus.c | 197 |
1 files changed, 94 insertions, 103 deletions
diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index c69504aa638f..98e0a8cbeecd 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc64/kernel/ebus.c | |||
@@ -269,10 +269,6 @@ EXPORT_SYMBOL(ebus_dma_enable); | |||
269 | 269 | ||
270 | struct linux_ebus *ebus_chain = NULL; | 270 | struct linux_ebus *ebus_chain = NULL; |
271 | 271 | ||
272 | #ifdef CONFIG_SUN_AUXIO | ||
273 | extern void auxio_probe(void); | ||
274 | #endif | ||
275 | |||
276 | static inline void *ebus_alloc(size_t size) | 272 | static inline void *ebus_alloc(size_t size) |
277 | { | 273 | { |
278 | void *mem; | 274 | void *mem; |
@@ -283,77 +279,55 @@ static inline void *ebus_alloc(size_t size) | |||
283 | return mem; | 279 | return mem; |
284 | } | 280 | } |
285 | 281 | ||
286 | static void __init ebus_ranges_init(struct linux_ebus *ebus) | ||
287 | { | ||
288 | int success; | ||
289 | |||
290 | ebus->num_ebus_ranges = 0; | ||
291 | success = prom_getproperty(ebus->prom_node, "ranges", | ||
292 | (char *)ebus->ebus_ranges, | ||
293 | sizeof(ebus->ebus_ranges)); | ||
294 | if (success != -1) | ||
295 | ebus->num_ebus_ranges = (success/sizeof(struct linux_prom_ebus_ranges)); | ||
296 | } | ||
297 | |||
298 | static void __init ebus_intmap_init(struct linux_ebus *ebus) | ||
299 | { | ||
300 | int success; | ||
301 | |||
302 | ebus->num_ebus_intmap = 0; | ||
303 | success = prom_getproperty(ebus->prom_node, "interrupt-map", | ||
304 | (char *)ebus->ebus_intmap, | ||
305 | sizeof(ebus->ebus_intmap)); | ||
306 | if (success == -1) | ||
307 | return; | ||
308 | |||
309 | ebus->num_ebus_intmap = (success/sizeof(struct linux_prom_ebus_intmap)); | ||
310 | |||
311 | success = prom_getproperty(ebus->prom_node, "interrupt-map-mask", | ||
312 | (char *)&ebus->ebus_intmask, | ||
313 | sizeof(ebus->ebus_intmask)); | ||
314 | if (success == -1) { | ||
315 | prom_printf("%s: can't get interrupt-map-mask\n", __FUNCTION__); | ||
316 | prom_halt(); | ||
317 | } | ||
318 | } | ||
319 | |||
320 | int __init ebus_intmap_match(struct linux_ebus *ebus, | 282 | int __init ebus_intmap_match(struct linux_ebus *ebus, |
321 | struct linux_prom_registers *reg, | 283 | struct linux_prom_registers *reg, |
322 | int *interrupt) | 284 | int *interrupt) |
323 | { | 285 | { |
286 | struct linux_prom_ebus_intmap *imap; | ||
287 | struct linux_prom_ebus_intmask *imask; | ||
324 | unsigned int hi, lo, irq; | 288 | unsigned int hi, lo, irq; |
325 | int i; | 289 | int i, len, n_imap; |
290 | |||
291 | imap = of_get_property(ebus->prom_node, "interrupt-map", &len); | ||
292 | if (!imap) | ||
293 | return 0; | ||
294 | n_imap = len / sizeof(imap[0]); | ||
326 | 295 | ||
327 | if (!ebus->num_ebus_intmap) | 296 | imask = of_get_property(ebus->prom_node, "interrupt-map-mask", NULL); |
297 | if (!imask) | ||
328 | return 0; | 298 | return 0; |
329 | 299 | ||
330 | hi = reg->which_io & ebus->ebus_intmask.phys_hi; | 300 | hi = reg->which_io & imask->phys_hi; |
331 | lo = reg->phys_addr & ebus->ebus_intmask.phys_lo; | 301 | lo = reg->phys_addr & imask->phys_lo; |
332 | irq = *interrupt & ebus->ebus_intmask.interrupt; | 302 | irq = *interrupt & imask->interrupt; |
333 | for (i = 0; i < ebus->num_ebus_intmap; i++) { | 303 | for (i = 0; i < n_imap; i++) { |
334 | if ((ebus->ebus_intmap[i].phys_hi == hi) && | 304 | if ((imap[i].phys_hi == hi) && |
335 | (ebus->ebus_intmap[i].phys_lo == lo) && | 305 | (imap[i].phys_lo == lo) && |
336 | (ebus->ebus_intmap[i].interrupt == irq)) { | 306 | (imap[i].interrupt == irq)) { |
337 | *interrupt = ebus->ebus_intmap[i].cinterrupt; | 307 | *interrupt = imap[i].cinterrupt; |
338 | return 0; | 308 | return 0; |
339 | } | 309 | } |
340 | } | 310 | } |
341 | return -1; | 311 | return -1; |
342 | } | 312 | } |
343 | 313 | ||
344 | void __init fill_ebus_child(int node, struct linux_prom_registers *preg, | 314 | void __init fill_ebus_child(struct device_node *dp, |
345 | struct linux_ebus_child *dev, int non_standard_regs) | 315 | struct linux_prom_registers *preg, |
316 | struct linux_ebus_child *dev, | ||
317 | int non_standard_regs) | ||
346 | { | 318 | { |
347 | int regs[PROMREG_MAX]; | 319 | int *regs; |
348 | int irqs[PROMREG_MAX]; | 320 | int *irqs; |
349 | int i, len; | 321 | int i, len; |
350 | 322 | ||
351 | dev->prom_node = node; | 323 | dev->prom_node = dp; |
352 | prom_getstring(node, "name", dev->prom_name, sizeof(dev->prom_name)); | 324 | printk(" (%s)", dp->name); |
353 | printk(" (%s)", dev->prom_name); | ||
354 | 325 | ||
355 | len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs)); | 326 | regs = of_get_property(dp, "reg", &len); |
356 | dev->num_addrs = len / sizeof(regs[0]); | 327 | if (!regs) |
328 | dev->num_addrs = 0; | ||
329 | else | ||
330 | dev->num_addrs = len / sizeof(regs[0]); | ||
357 | 331 | ||
358 | if (non_standard_regs) { | 332 | if (non_standard_regs) { |
359 | /* This is to handle reg properties which are not | 333 | /* This is to handle reg properties which are not |
@@ -370,21 +344,21 @@ void __init fill_ebus_child(int node, struct linux_prom_registers *preg, | |||
370 | int rnum = regs[i]; | 344 | int rnum = regs[i]; |
371 | if (rnum >= dev->parent->num_addrs) { | 345 | if (rnum >= dev->parent->num_addrs) { |
372 | prom_printf("UGH: property for %s was %d, need < %d\n", | 346 | prom_printf("UGH: property for %s was %d, need < %d\n", |
373 | dev->prom_name, len, dev->parent->num_addrs); | 347 | dp->name, len, dev->parent->num_addrs); |
374 | panic(__FUNCTION__); | 348 | prom_halt(); |
375 | } | 349 | } |
376 | dev->resource[i].start = dev->parent->resource[i].start; | 350 | dev->resource[i].start = dev->parent->resource[i].start; |
377 | dev->resource[i].end = dev->parent->resource[i].end; | 351 | dev->resource[i].end = dev->parent->resource[i].end; |
378 | dev->resource[i].flags = IORESOURCE_MEM; | 352 | dev->resource[i].flags = IORESOURCE_MEM; |
379 | dev->resource[i].name = dev->prom_name; | 353 | dev->resource[i].name = dp->name; |
380 | } | 354 | } |
381 | } | 355 | } |
382 | 356 | ||
383 | for (i = 0; i < PROMINTR_MAX; i++) | 357 | for (i = 0; i < PROMINTR_MAX; i++) |
384 | dev->irqs[i] = PCI_IRQ_NONE; | 358 | dev->irqs[i] = PCI_IRQ_NONE; |
385 | 359 | ||
386 | len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs)); | 360 | irqs = of_get_property(dp, "interrupts", &len); |
387 | if ((len == -1) || (len == 0)) { | 361 | if (!irqs) { |
388 | dev->num_irqs = 0; | 362 | dev->num_irqs = 0; |
389 | /* | 363 | /* |
390 | * Oh, well, some PROMs don't export interrupts | 364 | * Oh, well, some PROMs don't export interrupts |
@@ -392,8 +366,8 @@ void __init fill_ebus_child(int node, struct linux_prom_registers *preg, | |||
392 | * | 366 | * |
393 | * Be smart about PS/2 keyboard and mouse. | 367 | * Be smart about PS/2 keyboard and mouse. |
394 | */ | 368 | */ |
395 | if (!strcmp(dev->parent->prom_name, "8042")) { | 369 | if (!strcmp(dev->parent->prom_node->name, "8042")) { |
396 | if (!strcmp(dev->prom_name, "kb_ps2")) { | 370 | if (!strcmp(dev->prom_node->name, "kb_ps2")) { |
397 | dev->num_irqs = 1; | 371 | dev->num_irqs = 1; |
398 | dev->irqs[0] = dev->parent->irqs[0]; | 372 | dev->irqs[0] = dev->parent->irqs[0]; |
399 | } else { | 373 | } else { |
@@ -423,32 +397,32 @@ void __init fill_ebus_child(int node, struct linux_prom_registers *preg, | |||
423 | 397 | ||
424 | static int __init child_regs_nonstandard(struct linux_ebus_device *dev) | 398 | static int __init child_regs_nonstandard(struct linux_ebus_device *dev) |
425 | { | 399 | { |
426 | if (!strcmp(dev->prom_name, "i2c") || | 400 | if (!strcmp(dev->prom_node->name, "i2c") || |
427 | !strcmp(dev->prom_name, "SUNW,lombus")) | 401 | !strcmp(dev->prom_node->name, "SUNW,lombus")) |
428 | return 1; | 402 | return 1; |
429 | return 0; | 403 | return 0; |
430 | } | 404 | } |
431 | 405 | ||
432 | void __init fill_ebus_device(int node, struct linux_ebus_device *dev) | 406 | void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *dev) |
433 | { | 407 | { |
434 | struct linux_prom_registers regs[PROMREG_MAX]; | 408 | struct linux_prom_registers *regs; |
435 | struct linux_ebus_child *child; | 409 | struct linux_ebus_child *child; |
436 | int irqs[PROMINTR_MAX]; | 410 | int *irqs; |
437 | int i, n, len; | 411 | int i, n, len; |
438 | 412 | ||
439 | dev->prom_node = node; | 413 | dev->prom_node = dp; |
440 | prom_getstring(node, "name", dev->prom_name, sizeof(dev->prom_name)); | 414 | |
441 | printk(" [%s", dev->prom_name); | 415 | printk(" [%s", dp->name); |
442 | 416 | ||
443 | len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs)); | 417 | regs = of_get_property(dp, "reg", &len); |
444 | if (len == -1) { | 418 | if (!regs) { |
445 | dev->num_addrs = 0; | 419 | dev->num_addrs = 0; |
446 | goto probe_interrupts; | 420 | goto probe_interrupts; |
447 | } | 421 | } |
448 | 422 | ||
449 | if (len % sizeof(struct linux_prom_registers)) { | 423 | if (len % sizeof(struct linux_prom_registers)) { |
450 | prom_printf("UGH: proplen for %s was %d, need multiple of %d\n", | 424 | prom_printf("UGH: proplen for %s was %d, need multiple of %d\n", |
451 | dev->prom_name, len, | 425 | dev->prom_node->name, len, |
452 | (int)sizeof(struct linux_prom_registers)); | 426 | (int)sizeof(struct linux_prom_registers)); |
453 | prom_halt(); | 427 | prom_halt(); |
454 | } | 428 | } |
@@ -466,7 +440,7 @@ void __init fill_ebus_device(int node, struct linux_ebus_device *dev) | |||
466 | dev->resource[i].end = | 440 | dev->resource[i].end = |
467 | (dev->resource[i].start + (unsigned long)regs[i].reg_size - 1UL); | 441 | (dev->resource[i].start + (unsigned long)regs[i].reg_size - 1UL); |
468 | dev->resource[i].flags = IORESOURCE_MEM; | 442 | dev->resource[i].flags = IORESOURCE_MEM; |
469 | dev->resource[i].name = dev->prom_name; | 443 | dev->resource[i].name = dev->prom_node->name; |
470 | request_resource(&dev->bus->self->resource[n], | 444 | request_resource(&dev->bus->self->resource[n], |
471 | &dev->resource[i]); | 445 | &dev->resource[i]); |
472 | } | 446 | } |
@@ -475,8 +449,8 @@ probe_interrupts: | |||
475 | for (i = 0; i < PROMINTR_MAX; i++) | 449 | for (i = 0; i < PROMINTR_MAX; i++) |
476 | dev->irqs[i] = PCI_IRQ_NONE; | 450 | dev->irqs[i] = PCI_IRQ_NONE; |
477 | 451 | ||
478 | len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs)); | 452 | irqs = of_get_property(dp, "interrupts", &len); |
479 | if ((len == -1) || (len == 0)) { | 453 | if (!irqs) { |
480 | dev->num_irqs = 0; | 454 | dev->num_irqs = 0; |
481 | } else { | 455 | } else { |
482 | dev->num_irqs = len / sizeof(irqs[0]); | 456 | dev->num_irqs = len / sizeof(irqs[0]); |
@@ -497,7 +471,18 @@ probe_interrupts: | |||
497 | } | 471 | } |
498 | } | 472 | } |
499 | 473 | ||
500 | if ((node = prom_getchild(node))) { | 474 | dev->ofdev.node = dp; |
475 | dev->ofdev.dev.parent = &dev->bus->ofdev.dev; | ||
476 | dev->ofdev.dev.bus = &ebus_bus_type; | ||
477 | strcpy(dev->ofdev.dev.bus_id, dp->path_component_name); | ||
478 | |||
479 | /* Register with core */ | ||
480 | if (of_device_register(&dev->ofdev) != 0) | ||
481 | printk(KERN_DEBUG "ebus: device registration error for %s!\n", | ||
482 | dev->ofdev.dev.bus_id); | ||
483 | |||
484 | dp = dp->child; | ||
485 | if (dp) { | ||
501 | printk(" ->"); | 486 | printk(" ->"); |
502 | dev->children = ebus_alloc(sizeof(struct linux_ebus_child)); | 487 | dev->children = ebus_alloc(sizeof(struct linux_ebus_child)); |
503 | 488 | ||
@@ -505,18 +490,18 @@ probe_interrupts: | |||
505 | child->next = NULL; | 490 | child->next = NULL; |
506 | child->parent = dev; | 491 | child->parent = dev; |
507 | child->bus = dev->bus; | 492 | child->bus = dev->bus; |
508 | fill_ebus_child(node, ®s[0], | 493 | fill_ebus_child(dp, regs, child, |
509 | child, child_regs_nonstandard(dev)); | 494 | child_regs_nonstandard(dev)); |
510 | 495 | ||
511 | while ((node = prom_getsibling(node)) != 0) { | 496 | while ((dp = dp->sibling) != NULL) { |
512 | child->next = ebus_alloc(sizeof(struct linux_ebus_child)); | 497 | child->next = ebus_alloc(sizeof(struct linux_ebus_child)); |
513 | 498 | ||
514 | child = child->next; | 499 | child = child->next; |
515 | child->next = NULL; | 500 | child->next = NULL; |
516 | child->parent = dev; | 501 | child->parent = dev; |
517 | child->bus = dev->bus; | 502 | child->bus = dev->bus; |
518 | fill_ebus_child(node, ®s[0], | 503 | fill_ebus_child(dp, regs, child, |
519 | child, child_regs_nonstandard(dev)); | 504 | child_regs_nonstandard(dev)); |
520 | } | 505 | } |
521 | } | 506 | } |
522 | printk("]"); | 507 | printk("]"); |
@@ -543,7 +528,8 @@ void __init ebus_init(void) | |||
543 | struct linux_ebus *ebus; | 528 | struct linux_ebus *ebus; |
544 | struct pci_dev *pdev; | 529 | struct pci_dev *pdev; |
545 | struct pcidev_cookie *cookie; | 530 | struct pcidev_cookie *cookie; |
546 | int nd, ebusnd, is_rio; | 531 | struct device_node *dp; |
532 | int is_rio; | ||
547 | int num_ebus = 0; | 533 | int num_ebus = 0; |
548 | 534 | ||
549 | pdev = find_next_ebus(NULL, &is_rio); | 535 | pdev = find_next_ebus(NULL, &is_rio); |
@@ -553,20 +539,22 @@ void __init ebus_init(void) | |||
553 | } | 539 | } |
554 | 540 | ||
555 | cookie = pdev->sysdata; | 541 | cookie = pdev->sysdata; |
556 | ebusnd = cookie->prom_node; | 542 | dp = cookie->prom_node; |
557 | 543 | ||
558 | ebus_chain = ebus = ebus_alloc(sizeof(struct linux_ebus)); | 544 | ebus_chain = ebus = ebus_alloc(sizeof(struct linux_ebus)); |
559 | ebus->next = NULL; | 545 | ebus->next = NULL; |
560 | ebus->is_rio = is_rio; | 546 | ebus->is_rio = is_rio; |
561 | 547 | ||
562 | while (ebusnd) { | 548 | while (dp) { |
549 | struct device_node *child; | ||
550 | |||
563 | /* SUNW,pci-qfe uses four empty ebuses on it. | 551 | /* SUNW,pci-qfe uses four empty ebuses on it. |
564 | I think we should not consider them here, | 552 | I think we should not consider them here, |
565 | as they have half of the properties this | 553 | as they have half of the properties this |
566 | code expects and once we do PCI hot-plug, | 554 | code expects and once we do PCI hot-plug, |
567 | we'd have to tweak with the ebus_chain | 555 | we'd have to tweak with the ebus_chain |
568 | in the runtime after initialization. -jj */ | 556 | in the runtime after initialization. -jj */ |
569 | if (!prom_getchild (ebusnd)) { | 557 | if (!dp->child) { |
570 | pdev = find_next_ebus(pdev, &is_rio); | 558 | pdev = find_next_ebus(pdev, &is_rio); |
571 | if (!pdev) { | 559 | if (!pdev) { |
572 | if (ebus == ebus_chain) { | 560 | if (ebus == ebus_chain) { |
@@ -578,22 +566,29 @@ void __init ebus_init(void) | |||
578 | } | 566 | } |
579 | ebus->is_rio = is_rio; | 567 | ebus->is_rio = is_rio; |
580 | cookie = pdev->sysdata; | 568 | cookie = pdev->sysdata; |
581 | ebusnd = cookie->prom_node; | 569 | dp = cookie->prom_node; |
582 | continue; | 570 | continue; |
583 | } | 571 | } |
584 | printk("ebus%d:", num_ebus); | 572 | printk("ebus%d:", num_ebus); |
585 | 573 | ||
586 | prom_getstring(ebusnd, "name", ebus->prom_name, sizeof(ebus->prom_name)); | ||
587 | ebus->index = num_ebus; | 574 | ebus->index = num_ebus; |
588 | ebus->prom_node = ebusnd; | 575 | ebus->prom_node = dp; |
589 | ebus->self = pdev; | 576 | ebus->self = pdev; |
590 | ebus->parent = pbm = cookie->pbm; | 577 | ebus->parent = pbm = cookie->pbm; |
591 | 578 | ||
592 | ebus_ranges_init(ebus); | 579 | ebus->ofdev.node = dp; |
593 | ebus_intmap_init(ebus); | 580 | ebus->ofdev.dev.parent = &pdev->dev; |
581 | ebus->ofdev.dev.bus = &ebus_bus_type; | ||
582 | strcpy(ebus->ofdev.dev.bus_id, dp->path_component_name); | ||
594 | 583 | ||
595 | nd = prom_getchild(ebusnd); | 584 | /* Register with core */ |
596 | if (!nd) | 585 | if (of_device_register(&ebus->ofdev) != 0) |
586 | printk(KERN_DEBUG "ebus: device registration error for %s!\n", | ||
587 | ebus->ofdev.dev.bus_id); | ||
588 | |||
589 | |||
590 | child = dp->child; | ||
591 | if (!child) | ||
597 | goto next_ebus; | 592 | goto next_ebus; |
598 | 593 | ||
599 | ebus->devices = ebus_alloc(sizeof(struct linux_ebus_device)); | 594 | ebus->devices = ebus_alloc(sizeof(struct linux_ebus_device)); |
@@ -602,16 +597,16 @@ void __init ebus_init(void) | |||
602 | dev->next = NULL; | 597 | dev->next = NULL; |
603 | dev->children = NULL; | 598 | dev->children = NULL; |
604 | dev->bus = ebus; | 599 | dev->bus = ebus; |
605 | fill_ebus_device(nd, dev); | 600 | fill_ebus_device(child, dev); |
606 | 601 | ||
607 | while ((nd = prom_getsibling(nd)) != 0) { | 602 | while ((child = child->sibling) != NULL) { |
608 | dev->next = ebus_alloc(sizeof(struct linux_ebus_device)); | 603 | dev->next = ebus_alloc(sizeof(struct linux_ebus_device)); |
609 | 604 | ||
610 | dev = dev->next; | 605 | dev = dev->next; |
611 | dev->next = NULL; | 606 | dev->next = NULL; |
612 | dev->children = NULL; | 607 | dev->children = NULL; |
613 | dev->bus = ebus; | 608 | dev->bus = ebus; |
614 | fill_ebus_device(nd, dev); | 609 | fill_ebus_device(child, dev); |
615 | } | 610 | } |
616 | 611 | ||
617 | next_ebus: | 612 | next_ebus: |
@@ -622,7 +617,7 @@ void __init ebus_init(void) | |||
622 | break; | 617 | break; |
623 | 618 | ||
624 | cookie = pdev->sysdata; | 619 | cookie = pdev->sysdata; |
625 | ebusnd = cookie->prom_node; | 620 | dp = cookie->prom_node; |
626 | 621 | ||
627 | ebus->next = ebus_alloc(sizeof(struct linux_ebus)); | 622 | ebus->next = ebus_alloc(sizeof(struct linux_ebus)); |
628 | ebus = ebus->next; | 623 | ebus = ebus->next; |
@@ -631,8 +626,4 @@ void __init ebus_init(void) | |||
631 | ++num_ebus; | 626 | ++num_ebus; |
632 | } | 627 | } |
633 | pci_dev_put(pdev); /* XXX for the case, when ebusnd is 0, is it OK? */ | 628 | pci_dev_put(pdev); /* XXX for the case, when ebusnd is 0, is it OK? */ |
634 | |||
635 | #ifdef CONFIG_SUN_AUXIO | ||
636 | auxio_probe(); | ||
637 | #endif | ||
638 | } | 629 | } |