aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc')
-rw-r--r--arch/ppc/platforms/pmac_smp.c78
1 files changed, 54 insertions, 24 deletions
diff --git a/arch/ppc/platforms/pmac_smp.c b/arch/ppc/platforms/pmac_smp.c
index 2b88745576a0..731841f9a5b8 100644
--- a/arch/ppc/platforms/pmac_smp.c
+++ b/arch/ppc/platforms/pmac_smp.c
@@ -116,6 +116,8 @@ static unsigned int core99_tb_gpio;
116 116
117/* Sync flag for HW tb sync */ 117/* Sync flag for HW tb sync */
118static volatile int sec_tb_reset = 0; 118static volatile int sec_tb_reset = 0;
119static unsigned int pri_tb_hi, pri_tb_lo;
120static unsigned int pri_tb_stamp;
119 121
120static void __init core99_init_caches(int cpu) 122static void __init core99_init_caches(int cpu)
121{ 123{
@@ -453,7 +455,7 @@ static int __init smp_core99_probe(void)
453#endif 455#endif
454 struct device_node *cpus, *firstcpu; 456 struct device_node *cpus, *firstcpu;
455 int i, ncpus = 0, boot_cpu = -1; 457 int i, ncpus = 0, boot_cpu = -1;
456 u32 *tbprop; 458 u32 *tbprop = NULL;
457 459
458 if (ppc_md.progress) ppc_md.progress("smp_core99_probe", 0x345); 460 if (ppc_md.progress) ppc_md.progress("smp_core99_probe", 0x345);
459 cpus = firstcpu = find_type_devices("cpu"); 461 cpus = firstcpu = find_type_devices("cpu");
@@ -576,46 +578,74 @@ static void __init smp_core99_setup_cpu(int cpu_nr)
576 } 578 }
577} 579}
578 580
579void __init smp_core99_take_timebase(void) 581/* not __init, called in sleep/wakeup code */
582void smp_core99_take_timebase(void)
580{ 583{
581 /* Secondary processor "takes" the timebase by freezing 584 unsigned long flags;
582 * it, resetting its local TB and telling CPU 0 to go on 585
583 */ 586 /* tell the primary we're here */
584 pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 4); 587 sec_tb_reset = 1;
585 pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0);
586 mb(); 588 mb();
587 589
588 set_dec(tb_ticks_per_jiffy); 590 /* wait for the primary to set pri_tb_hi/lo */
589 set_tb(0, 0); 591 while (sec_tb_reset < 2)
590 last_jiffy_stamp(smp_processor_id()) = 0; 592 mb();
591 593
594 /* set our stuff the same as the primary */
595 local_irq_save(flags);
596 set_dec(1);
597 set_tb(pri_tb_hi, pri_tb_lo);
598 last_jiffy_stamp(smp_processor_id()) = pri_tb_stamp;
599 mb();
600
601 /* tell the primary we're done */
602 sec_tb_reset = 0;
592 mb(); 603 mb();
593 sec_tb_reset = 1; 604 local_irq_restore(flags);
594} 605}
595 606
596void __init smp_core99_give_timebase(void) 607/* not __init, called in sleep/wakeup code */
608void smp_core99_give_timebase(void)
597{ 609{
610 unsigned long flags;
598 unsigned int t; 611 unsigned int t;
599 612
600 /* Primary processor waits for secondary to have frozen 613 /* wait for the secondary to be in take_timebase */
601 * the timebase, resets local TB, and kick timebase again 614 for (t = 100000; t > 0 && !sec_tb_reset; --t)
602 */ 615 udelay(10);
603 /* wait for the secondary to have reset its TB before proceeding */ 616 if (!sec_tb_reset) {
604 for (t = 1000; t > 0 && !sec_tb_reset; --t)
605 udelay(1000);
606 if (t == 0)
607 printk(KERN_WARNING "Timeout waiting sync on second CPU\n"); 617 printk(KERN_WARNING "Timeout waiting sync on second CPU\n");
618 return;
619 }
608 620
609 set_dec(tb_ticks_per_jiffy); 621 /* freeze the timebase and read it */
610 set_tb(0, 0); 622 /* disable interrupts so the timebase is disabled for the
611 last_jiffy_stamp(smp_processor_id()) = 0; 623 shortest possible time */
624 local_irq_save(flags);
625 pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 4);
626 pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0);
627 mb();
628 pri_tb_hi = get_tbu();
629 pri_tb_lo = get_tbl();
630 pri_tb_stamp = last_jiffy_stamp(smp_processor_id());
612 mb(); 631 mb();
613 632
633 /* tell the secondary we're ready */
634 sec_tb_reset = 2;
635 mb();
636
637 /* wait for the secondary to have taken it */
638 for (t = 100000; t > 0 && sec_tb_reset; --t)
639 udelay(10);
640 if (sec_tb_reset)
641 printk(KERN_WARNING "Timeout waiting sync(2) on second CPU\n");
642 else
643 smp_tb_synchronized = 1;
644
614 /* Now, restart the timebase by leaving the GPIO to an open collector */ 645 /* Now, restart the timebase by leaving the GPIO to an open collector */
615 pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 0); 646 pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 0);
616 pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0); 647 pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0);
617 648 local_irq_restore(flags);
618 smp_tb_synchronized = 1;
619} 649}
620 650
621 651