aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/powermac/smp.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2005-12-13 21:10:10 -0500
committerPaul Mackerras <paulus@samba.org>2006-01-08 23:03:17 -0500
commit1beb6a7d6cbed3ac03500ce9b5b9bb632c512039 (patch)
tree727aa76da5a82fca449dadf3cebbadc414ad6555 /arch/powerpc/platforms/powermac/smp.c
parentcd0c7f06803be06a5cf4564aa5a900f4b6aea603 (diff)
[PATCH] powerpc: Experimental support for new G5 Macs (#2)
This adds some very basic support for the new machines, including the Quad G5 (tested), and other new dual core based machines and iMac G5 iSight (untested). This is still experimental ! There is no thermal control yet, there is no proper handing of MSIs, etc.. but it boots, I have all 4 cores up on my machine. Compared to the previous version of this patch, this one adds DART IOMMU support for the U4 chipset and thus should work fine on setups with more than 2Gb of RAM. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/platforms/powermac/smp.c')
-rw-r--r--arch/powerpc/platforms/powermac/smp.c319
1 files changed, 168 insertions, 151 deletions
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index 862f1e985c19..df01bb8feb16 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -361,7 +361,6 @@ static void __init psurge_dual_sync_tb(int cpu_nr)
361 set_dec(tb_ticks_per_jiffy); 361 set_dec(tb_ticks_per_jiffy);
362 /* XXX fixme */ 362 /* XXX fixme */
363 set_tb(0, 0); 363 set_tb(0, 0);
364 last_jiffy_stamp(cpu_nr) = 0;
365 364
366 if (cpu_nr > 0) { 365 if (cpu_nr > 0) {
367 mb(); 366 mb();
@@ -429,15 +428,62 @@ struct smp_ops_t psurge_smp_ops = {
429}; 428};
430#endif /* CONFIG_PPC32 - actually powersurge support */ 429#endif /* CONFIG_PPC32 - actually powersurge support */
431 430
431/*
432 * Core 99 and later support
433 */
434
435static void (*pmac_tb_freeze)(int freeze);
436static unsigned long timebase;
437static int tb_req;
438
439static void smp_core99_give_timebase(void)
440{
441 unsigned long flags;
442
443 local_irq_save(flags);
444
445 while(!tb_req)
446 barrier();
447 tb_req = 0;
448 (*pmac_tb_freeze)(1);
449 mb();
450 timebase = get_tb();
451 mb();
452 while (timebase)
453 barrier();
454 mb();
455 (*pmac_tb_freeze)(0);
456 mb();
457
458 local_irq_restore(flags);
459}
460
461
462static void __devinit smp_core99_take_timebase(void)
463{
464 unsigned long flags;
465
466 local_irq_save(flags);
467
468 tb_req = 1;
469 mb();
470 while (!timebase)
471 barrier();
472 mb();
473 set_tb(timebase >> 32, timebase & 0xffffffff);
474 timebase = 0;
475 mb();
476 set_dec(tb_ticks_per_jiffy/2);
477
478 local_irq_restore(flags);
479}
480
432#ifdef CONFIG_PPC64 481#ifdef CONFIG_PPC64
433/* 482/*
434 * G5s enable/disable the timebase via an i2c-connected clock chip. 483 * G5s enable/disable the timebase via an i2c-connected clock chip.
435 */ 484 */
436static struct device_node *pmac_tb_clock_chip_host; 485static struct device_node *pmac_tb_clock_chip_host;
437static u8 pmac_tb_pulsar_addr; 486static u8 pmac_tb_pulsar_addr;
438static void (*pmac_tb_freeze)(int freeze);
439static DEFINE_SPINLOCK(timebase_lock);
440static unsigned long timebase;
441 487
442static void smp_core99_cypress_tb_freeze(int freeze) 488static void smp_core99_cypress_tb_freeze(int freeze)
443{ 489{
@@ -447,7 +493,8 @@ static void smp_core99_cypress_tb_freeze(int freeze)
447 /* Strangely, the device-tree says address is 0xd2, but darwin 493 /* Strangely, the device-tree says address is 0xd2, but darwin
448 * accesses 0xd0 ... 494 * accesses 0xd0 ...
449 */ 495 */
450 pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_combined); 496 pmac_low_i2c_setmode(pmac_tb_clock_chip_host,
497 pmac_low_i2c_mode_combined);
451 rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host, 498 rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
452 0xd0 | pmac_low_i2c_read, 499 0xd0 | pmac_low_i2c_read,
453 0x81, &data, 1); 500 0x81, &data, 1);
@@ -475,7 +522,8 @@ static void smp_core99_pulsar_tb_freeze(int freeze)
475 u8 data; 522 u8 data;
476 int rc; 523 int rc;
477 524
478 pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_combined); 525 pmac_low_i2c_setmode(pmac_tb_clock_chip_host,
526 pmac_low_i2c_mode_combined);
479 rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host, 527 rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
480 pmac_tb_pulsar_addr | pmac_low_i2c_read, 528 pmac_tb_pulsar_addr | pmac_low_i2c_read,
481 0x2e, &data, 1); 529 0x2e, &data, 1);
@@ -496,54 +544,14 @@ static void smp_core99_pulsar_tb_freeze(int freeze)
496 } 544 }
497} 545}
498 546
499 547static void __init smp_core99_setup_i2c_hwsync(int ncpus)
500static void smp_core99_give_timebase(void)
501{
502 /* Open i2c bus for synchronous access */
503 if (pmac_low_i2c_open(pmac_tb_clock_chip_host, 0))
504 panic("Can't open i2c for TB sync !\n");
505
506 spin_lock(&timebase_lock);
507 (*pmac_tb_freeze)(1);
508 mb();
509 timebase = get_tb();
510 spin_unlock(&timebase_lock);
511
512 while (timebase)
513 barrier();
514
515 spin_lock(&timebase_lock);
516 (*pmac_tb_freeze)(0);
517 spin_unlock(&timebase_lock);
518
519 /* Close i2c bus */
520 pmac_low_i2c_close(pmac_tb_clock_chip_host);
521}
522
523
524static void __devinit smp_core99_take_timebase(void)
525{
526 while (!timebase)
527 barrier();
528 spin_lock(&timebase_lock);
529 set_tb(timebase >> 32, timebase & 0xffffffff);
530 timebase = 0;
531 spin_unlock(&timebase_lock);
532}
533
534static void __init smp_core99_setup(int ncpus)
535{ 548{
536 struct device_node *cc = NULL; 549 struct device_node *cc = NULL;
537 struct device_node *p; 550 struct device_node *p;
551 const char *name = NULL;
538 u32 *reg; 552 u32 *reg;
539 int ok; 553 int ok;
540 554
541 /* HW sync only on these platforms */
542 if (!machine_is_compatible("PowerMac7,2") &&
543 !machine_is_compatible("PowerMac7,3") &&
544 !machine_is_compatible("RackMac3,1"))
545 return;
546
547 /* Look for the clock chip */ 555 /* Look for the clock chip */
548 while ((cc = of_find_node_by_name(cc, "i2c-hwclock")) != NULL) { 556 while ((cc = of_find_node_by_name(cc, "i2c-hwclock")) != NULL) {
549 p = of_get_parent(cc); 557 p = of_get_parent(cc);
@@ -561,114 +569,64 @@ static void __init smp_core99_setup(int ncpus)
561 if (device_is_compatible(cc, "pulsar-legacy-slewing")) { 569 if (device_is_compatible(cc, "pulsar-legacy-slewing")) {
562 pmac_tb_freeze = smp_core99_pulsar_tb_freeze; 570 pmac_tb_freeze = smp_core99_pulsar_tb_freeze;
563 pmac_tb_pulsar_addr = 0xd2; 571 pmac_tb_pulsar_addr = 0xd2;
564 printk(KERN_INFO "Timebase clock is Pulsar chip\n"); 572 name = "Pulsar";
565 } else if (device_is_compatible(cc, "cy28508")) { 573 } else if (device_is_compatible(cc, "cy28508")) {
566 pmac_tb_freeze = smp_core99_cypress_tb_freeze; 574 pmac_tb_freeze = smp_core99_cypress_tb_freeze;
567 printk(KERN_INFO "Timebase clock is Cypress chip\n"); 575 name = "Cypress";
568 } 576 }
569 break; 577 break;
570 case 0xd4: 578 case 0xd4:
571 pmac_tb_freeze = smp_core99_pulsar_tb_freeze; 579 pmac_tb_freeze = smp_core99_pulsar_tb_freeze;
572 pmac_tb_pulsar_addr = 0xd4; 580 pmac_tb_pulsar_addr = 0xd4;
573 printk(KERN_INFO "Timebase clock is Pulsar chip\n"); 581 name = "Pulsar";
574 break; 582 break;
575 } 583 }
576 if (pmac_tb_freeze != NULL) { 584 if (pmac_tb_freeze != NULL)
577 pmac_tb_clock_chip_host = of_get_parent(cc);
578 of_node_put(cc);
579 break; 585 break;
580 }
581 } 586 }
582 if (pmac_tb_freeze == NULL) { 587 if (pmac_tb_freeze != NULL) {
583 smp_ops->give_timebase = smp_generic_give_timebase; 588 struct device_node *p = of_get_parent(cc);
584 smp_ops->take_timebase = smp_generic_take_timebase; 589 of_node_put(cc);
590 while(p && strcmp(p->type, "i2c")) {
591 cc = of_get_parent(p);
592 of_node_put(p);
593 p = cc;
594 }
595 if (p == NULL)
596 goto no_i2c_sync;
597 /* Open i2c bus for synchronous access */
598 if (pmac_low_i2c_open(p, 0)) {
599 printk(KERN_ERR "Failed top open i2c bus %s for clock"
600 " sync, fallback to software sync !\n",
601 p->full_name);
602 of_node_put(p);
603 goto no_i2c_sync;
604 }
605 pmac_tb_clock_chip_host = p;
606 printk(KERN_INFO "Processor timebase sync using %s i2c clock\n",
607 name);
608 return;
585 } 609 }
610 no_i2c_sync:
611 pmac_tb_freeze = NULL;
586} 612}
587 613
588/* nothing to do here, caches are already set up by service processor */ 614#endif /* CONFIG_PPC64 */
589static inline void __devinit core99_init_caches(int cpu)
590{
591}
592 615
593#else /* CONFIG_PPC64 */
594 616
595/* 617/*
596 * SMP G4 powermacs use a GPIO to enable/disable the timebase. 618 * SMP G4 and newer G5 use a GPIO to enable/disable the timebase.
597 */ 619 */
598 620
599static unsigned int core99_tb_gpio; /* Timebase freeze GPIO */ 621static unsigned int core99_tb_gpio; /* Timebase freeze GPIO */
600 622
601static unsigned int pri_tb_hi, pri_tb_lo; 623static void smp_core99_gpio_tb_freeze(int freeze)
602static unsigned int pri_tb_stamp;
603
604/* not __init, called in sleep/wakeup code */
605void smp_core99_give_timebase(void)
606{ 624{
607 unsigned long flags; 625 if (freeze)
608 unsigned int t; 626 pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 4);
609 627 else
610 /* wait for the secondary to be in take_timebase */ 628 pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 0);
611 for (t = 100000; t > 0 && !sec_tb_reset; --t)
612 udelay(10);
613 if (!sec_tb_reset) {
614 printk(KERN_WARNING "Timeout waiting sync on second CPU\n");
615 return;
616 }
617
618 /* freeze the timebase and read it */
619 /* disable interrupts so the timebase is disabled for the
620 shortest possible time */
621 local_irq_save(flags);
622 pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 4);
623 pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0); 629 pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0);
624 mb();
625 pri_tb_hi = get_tbu();
626 pri_tb_lo = get_tbl();
627 pri_tb_stamp = last_jiffy_stamp(smp_processor_id());
628 mb();
629
630 /* tell the secondary we're ready */
631 sec_tb_reset = 2;
632 mb();
633
634 /* wait for the secondary to have taken it */
635 /* note: can't use udelay here, since it needs the timebase running */
636 for (t = 10000000; t > 0 && sec_tb_reset; --t)
637 barrier();
638 if (sec_tb_reset)
639 /* XXX BUG_ON here? */
640 printk(KERN_WARNING "Timeout waiting sync(2) on second CPU\n");
641
642 /* Now, restart the timebase by leaving the GPIO to an open collector */
643 pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 0);
644 pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0);
645 local_irq_restore(flags);
646}
647
648/* not __init, called in sleep/wakeup code */
649void smp_core99_take_timebase(void)
650{
651 unsigned long flags;
652
653 /* tell the primary we're here */
654 sec_tb_reset = 1;
655 mb();
656
657 /* wait for the primary to set pri_tb_hi/lo */
658 while (sec_tb_reset < 2)
659 mb();
660
661 /* set our stuff the same as the primary */
662 local_irq_save(flags);
663 set_dec(1);
664 set_tb(pri_tb_hi, pri_tb_lo);
665 last_jiffy_stamp(smp_processor_id()) = pri_tb_stamp;
666 mb();
667
668 /* tell the primary we're done */
669 sec_tb_reset = 0;
670 mb();
671 local_irq_restore(flags);
672} 630}
673 631
674/* L2 and L3 cache settings to pass from CPU0 to CPU1 on G4 cpus */ 632/* L2 and L3 cache settings to pass from CPU0 to CPU1 on G4 cpus */
@@ -677,6 +635,7 @@ volatile static long int core99_l3_cache;
677 635
678static void __devinit core99_init_caches(int cpu) 636static void __devinit core99_init_caches(int cpu)
679{ 637{
638#ifndef CONFIG_PPC64
680 if (!cpu_has_feature(CPU_FTR_L2CR)) 639 if (!cpu_has_feature(CPU_FTR_L2CR))
681 return; 640 return;
682 641
@@ -702,30 +661,80 @@ static void __devinit core99_init_caches(int cpu)
702 _set_L3CR(core99_l3_cache); 661 _set_L3CR(core99_l3_cache);
703 printk("CPU%d: L3CR set to %lx\n", cpu, core99_l3_cache); 662 printk("CPU%d: L3CR set to %lx\n", cpu, core99_l3_cache);
704 } 663 }
664#endif /* !CONFIG_PPC64 */
705} 665}
706 666
707static void __init smp_core99_setup(int ncpus) 667static void __init smp_core99_setup(int ncpus)
708{ 668{
709 struct device_node *cpu; 669#ifdef CONFIG_PPC64
710 u32 *tbprop = NULL;
711 int i;
712 670
713 core99_tb_gpio = KL_GPIO_TB_ENABLE; /* default value */ 671 /* i2c based HW sync on some G5s */
714 cpu = of_find_node_by_type(NULL, "cpu"); 672 if (machine_is_compatible("PowerMac7,2") ||
715 if (cpu != NULL) { 673 machine_is_compatible("PowerMac7,3") ||
716 tbprop = (u32 *)get_property(cpu, "timebase-enable", NULL); 674 machine_is_compatible("RackMac3,1"))
717 if (tbprop) 675 smp_core99_setup_i2c_hwsync(ncpus);
718 core99_tb_gpio = *tbprop; 676
719 of_node_put(cpu); 677 /* GPIO based HW sync on recent G5s */
678 if (pmac_tb_freeze == NULL) {
679 struct device_node *np =
680 of_find_node_by_name(NULL, "timebase-enable");
681 u32 *reg = (u32 *)get_property(np, "reg", NULL);
682
683 if (np && reg && !strcmp(np->type, "gpio")) {
684 core99_tb_gpio = *reg;
685 if (core99_tb_gpio < 0x50)
686 core99_tb_gpio += 0x50;
687 pmac_tb_freeze = smp_core99_gpio_tb_freeze;
688 printk(KERN_INFO "Processor timebase sync using"
689 " GPIO 0x%02x\n", core99_tb_gpio);
690 }
720 } 691 }
721 692
722 /* XXX should get this from reg properties */ 693#else /* CONFIG_PPC64 */
723 for (i = 1; i < ncpus; ++i) 694
724 smp_hw_index[i] = i; 695 /* GPIO based HW sync on ppc32 Core99 */
725 powersave_nap = 0; 696 if (pmac_tb_freeze == NULL && !machine_is_compatible("MacRISC4")) {
726} 697 struct device_node *cpu;
698 u32 *tbprop = NULL;
699
700 core99_tb_gpio = KL_GPIO_TB_ENABLE; /* default value */
701 cpu = of_find_node_by_type(NULL, "cpu");
702 if (cpu != NULL) {
703 tbprop = (u32 *)get_property(cpu, "timebase-enable",
704 NULL);
705 if (tbprop)
706 core99_tb_gpio = *tbprop;
707 of_node_put(cpu);
708 }
709 pmac_tb_freeze = smp_core99_gpio_tb_freeze;
710 printk(KERN_INFO "Processor timebase sync using"
711 " GPIO 0x%02x\n", core99_tb_gpio);
712 }
713
714#endif /* CONFIG_PPC64 */
715
716 /* No timebase sync, fallback to software */
717 if (pmac_tb_freeze == NULL) {
718 smp_ops->give_timebase = smp_generic_give_timebase;
719 smp_ops->take_timebase = smp_generic_take_timebase;
720 printk(KERN_INFO "Processor timebase sync using software\n");
721 }
722
723#ifndef CONFIG_PPC64
724 {
725 int i;
726
727 /* XXX should get this from reg properties */
728 for (i = 1; i < ncpus; ++i)
729 smp_hw_index[i] = i;
730 }
727#endif 731#endif
728 732
733 /* 32 bits SMP can't NAP */
734 if (!machine_is_compatible("MacRISC4"))
735 powersave_nap = 0;
736}
737
729static int __init smp_core99_probe(void) 738static int __init smp_core99_probe(void)
730{ 739{
731 struct device_node *cpus; 740 struct device_node *cpus;
@@ -803,17 +812,25 @@ static void __devinit smp_core99_setup_cpu(int cpu_nr)
803 mpic_setup_this_cpu(); 812 mpic_setup_this_cpu();
804 813
805 if (cpu_nr == 0) { 814 if (cpu_nr == 0) {
806#ifdef CONFIG_POWER4 815#ifdef CONFIG_PPC64
807 extern void g5_phy_disable_cpu1(void); 816 extern void g5_phy_disable_cpu1(void);
808 817
818 /* Close i2c bus if it was used for tb sync */
819 if (pmac_tb_clock_chip_host) {
820 pmac_low_i2c_close(pmac_tb_clock_chip_host);
821 pmac_tb_clock_chip_host = NULL;
822 }
823
809 /* If we didn't start the second CPU, we must take 824 /* If we didn't start the second CPU, we must take
810 * it off the bus 825 * it off the bus
811 */ 826 */
812 if (machine_is_compatible("MacRISC4") && 827 if (machine_is_compatible("MacRISC4") &&
813 num_online_cpus() < 2) 828 num_online_cpus() < 2)
814 g5_phy_disable_cpu1(); 829 g5_phy_disable_cpu1();
815#endif /* CONFIG_POWER4 */ 830#endif /* CONFIG_PPC64 */
816 if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349); 831
832 if (ppc_md.progress)
833 ppc_md.progress("core99_setup_cpu 0 done", 0x349);
817 } 834 }
818} 835}
819 836