aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/powermac/smp.c
diff options
context:
space:
mode:
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