24 #include <linux/kernel.h>
25 #include <linux/sched.h>
32 #include <linux/errno.h>
35 #include <linux/compiler.h>
37 #include <asm/ptrace.h>
42 #include <asm/pgtable.h>
43 #include <asm/sections.h>
47 #include <asm/machdep.h>
51 #include <asm/cacheflush.h>
61 #define DBG(fmt...) udbg_printf(fmt)
69 static void (*pmac_tb_freeze)(
int freeze);
73 #ifdef CONFIG_PPC_PMAC32_PSURGE
80 #define HAMMERHEAD_BASE 0xf8000000
81 #define HHEAD_CONFIG 0x90
82 #define HHEAD_SEC_INTR 0xc0
86 #define PSURGE_PRI_INTR 0xf3019000
90 #define PSURGE_START 0xf2800000
93 #define PSURGE_QUAD_REG_ADDR 0xf8800000
95 #define PSURGE_QUAD_IRQ_SET 0
96 #define PSURGE_QUAD_IRQ_CLR 1
97 #define PSURGE_QUAD_IRQ_PRIMARY 2
98 #define PSURGE_QUAD_CKSTOP_CTL 3
99 #define PSURGE_QUAD_PRIMARY_ARB 4
100 #define PSURGE_QUAD_BOARD_ID 6
101 #define PSURGE_QUAD_WHICH_CPU 7
102 #define PSURGE_QUAD_CKSTOP_RDBK 8
103 #define PSURGE_QUAD_RESET_CTL 11
105 #define PSURGE_QUAD_OUT(r, v) (out_8(quad_base + ((r) << 4) + 4, (v)))
106 #define PSURGE_QUAD_IN(r) (in_8(quad_base + ((r) << 4) + 4) & 0x0f)
107 #define PSURGE_QUAD_BIS(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) | (v)))
108 #define PSURGE_QUAD_BIC(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) & ~(v)))
114 static volatile u8 __iomem *psurge_sec_intr;
118 #define PSURGE_NONE -1
119 #define PSURGE_DUAL 0
120 #define PSURGE_QUAD_OKEE 1
121 #define PSURGE_QUAD_COTTON 2
122 #define PSURGE_QUAD_ICEGRASS 3
125 static int psurge_type = PSURGE_NONE;
134 static inline void psurge_set_ipi(
int cpu)
136 if (psurge_type == PSURGE_NONE)
140 else if (psurge_type == PSURGE_DUAL)
141 out_8(psurge_sec_intr, 0);
143 PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_SET, 1 << cpu);
146 static inline void psurge_clr_ipi(
int cpu)
149 switch(psurge_type) {
151 out_8(psurge_sec_intr, ~0);
155 PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, 1 << cpu);
174 static void smp_psurge_cause_ipi(
int cpu,
unsigned long data)
179 static int psurge_host_map(
struct irq_domain *
h,
unsigned int virq,
188 .
map = psurge_host_map,
191 static int psurge_secondary_ipi_init(
void)
200 if (psurge_secondary_virq)
201 rc =
request_irq(psurge_secondary_virq, psurge_ipi_intr,
205 pr_err(
"Failed to setup secondary cpu IPI\n");
215 static int __init psurge_quad_probe(
void)
220 type = PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID);
222 || type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID))
228 for (i = 0; i < 100; i++) {
230 bogus[(0+
i)%8] = 0x00000000;
231 bogus[(1+
i)%8] = 0x55555555;
232 bogus[(2+
i)%8] = 0xFFFFFFFF;
233 bogus[(3+
i)%8] = 0xAAAAAAAA;
234 bogus[(4+
i)%8] = 0x33333333;
235 bogus[(5+
i)%8] = 0xCCCCCCCC;
236 bogus[(6+
i)%8] = 0xCCCCCCCC;
237 bogus[(7+
i)%8] = 0x33333333;
239 asm volatile(
"dcbf 0,%0" : :
"r" (
bogus) :
"memory");
241 if (type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID))
247 static void __init psurge_quad_init(
void)
251 if (
ppc_md.progress)
ppc_md.progress(
"psurge_quad_init", 0x351);
252 procbits = ~PSURGE_QUAD_IN(PSURGE_QUAD_WHICH_CPU);
253 if (psurge_type == PSURGE_QUAD_ICEGRASS)
254 PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits);
256 PSURGE_QUAD_BIC(PSURGE_QUAD_CKSTOP_CTL, procbits);
258 out_8(psurge_sec_intr, ~0);
259 PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, procbits);
260 PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits);
261 if (psurge_type != PSURGE_QUAD_ICEGRASS)
262 PSURGE_QUAD_BIS(PSURGE_QUAD_CKSTOP_CTL, procbits);
263 PSURGE_QUAD_BIC(PSURGE_QUAD_PRIMARY_ARB, procbits);
265 PSURGE_QUAD_BIC(PSURGE_QUAD_RESET_CTL, procbits);
267 PSURGE_QUAD_BIS(PSURGE_QUAD_PRIMARY_ARB, procbits);
271 static int __init smp_psurge_probe(
void)
295 hhead_base =
ioremap(HAMMERHEAD_BASE, 0x800);
296 quad_base =
ioremap(PSURGE_QUAD_REG_ADDR, 1024);
297 psurge_sec_intr = hhead_base + HHEAD_SEC_INTR;
299 psurge_type = psurge_quad_probe();
300 if (psurge_type != PSURGE_DUAL) {
309 if ((
in_8(hhead_base + HHEAD_CONFIG) & 0x02) == 0) {
312 psurge_type = PSURGE_NONE;
318 if (psurge_secondary_ipi_init())
321 psurge_start =
ioremap(PSURGE_START, 4);
322 psurge_pri_intr =
ioremap(PSURGE_PRI_INTR, 4);
331 for (i = 1; i <
ncpus ; ++
i)
334 if (
ppc_md.progress)
ppc_md.progress(
"smp_psurge_probe - done", 0x352);
339 static int __init smp_psurge_kick_cpu(
int nr)
353 asm volatile(
"dcbf 0,%0" : :
"r" (a) :
"memory");
354 asm volatile(
"sync");
356 if (
ppc_md.progress)
ppc_md.progress(
"smp_psurge_kick_cpu", 0x353);
369 for (i = 0; i < 2000; ++
i)
370 asm volatile(
"nop" : : :
"memory");
378 for (i = 0; i < 100000 && !cpu_callin_map[
nr]; ++
i) {
379 for (j = 1; j < 10000; j++)
380 asm volatile(
"nop" : : :
"memory");
381 asm volatile(
"sync" : : :
"memory");
383 if (!cpu_callin_map[nr])
387 if (psurge_type == PSURGE_DUAL) {
400 if (psurge_type == PSURGE_DUAL)
403 if (
ppc_md.progress)
ppc_md.progress(
"smp_psurge_kick_cpu - done", 0x354);
408 static struct irqaction psurge_irqaction = {
411 .name =
"primary IPI",
414 static void __init smp_psurge_setup_cpu(
int cpu_nr)
416 if (cpu_nr != 0 || !psurge_start)
426 void __init smp_psurge_take_timebase(
void)
428 if (psurge_type != PSURGE_DUAL)
436 set_tb(timebase >> 32, timebase & 0xffffffff);
442 void __init smp_psurge_give_timebase(
void)
448 struct smp_ops_t psurge_smp_ops = {
449 .message_pass =
NULL,
450 .cause_ipi = smp_psurge_cause_ipi,
451 .probe = smp_psurge_probe,
452 .kick_cpu = smp_psurge_kick_cpu,
453 .setup_cpu = smp_psurge_setup_cpu,
454 .give_timebase = smp_psurge_give_timebase,
455 .take_timebase = smp_psurge_take_timebase,
464 static void smp_core99_give_timebase(
void)
473 (*pmac_tb_freeze)(1);
480 (*pmac_tb_freeze)(0);
487 static void __devinit smp_core99_take_timebase(
void)
498 set_tb(timebase >> 32, timebase & 0xffffffff);
510 static u8 pmac_tb_pulsar_addr;
512 static void smp_core99_cypress_tb_freeze(
int freeze)
521 pmac_i2c_mode_combined);
523 0xd0 | pmac_i2c_read,
528 data = (data & 0xf3) | (freeze ? 0x00 : 0x0c);
532 0xd0 | pmac_i2c_write,
537 printk(
"Cypress Timebase %s rc: %d\n",
538 freeze ?
"freeze" :
"unfreeze", rc);
539 panic(
"Timebase freeze failed !\n");
544 static void smp_core99_pulsar_tb_freeze(
int freeze)
550 pmac_i2c_mode_combined);
552 pmac_tb_pulsar_addr | pmac_i2c_read,
557 data = (data & 0x88) | (freeze ? 0x11 : 0x22);
561 pmac_tb_pulsar_addr | pmac_i2c_write,
566 freeze ?
"freeze" :
"unfreeze", rc);
567 panic(
"Timebase freeze failed !\n");
571 static void __init smp_core99_setup_i2c_hwsync(
int ncpus)
588 if (pmac_tb_clock_chip_host ==
NULL)
596 pmac_tb_freeze = smp_core99_pulsar_tb_freeze;
597 pmac_tb_pulsar_addr = 0xd2;
600 pmac_tb_freeze = smp_core99_cypress_tb_freeze;
605 pmac_tb_freeze = smp_core99_pulsar_tb_freeze;
606 pmac_tb_pulsar_addr = 0xd4;
610 if (pmac_tb_freeze !=
NULL)
613 if (pmac_tb_freeze !=
NULL) {
617 " sync, fallback to software sync !\n");
625 pmac_tb_freeze =
NULL;
626 pmac_tb_clock_chip_host =
NULL;
635 static void smp_core99_pfunc_tb_freeze(
int freeze)
643 args.u[0].v = !freeze;
654 static unsigned int core99_tb_gpio;
656 static void smp_core99_gpio_tb_freeze(
int freeze)
659 pmac_call_feature(PMAC_FTR_WRITE_GPIO,
NULL, core99_tb_gpio, 4);
661 pmac_call_feature(PMAC_FTR_WRITE_GPIO,
NULL, core99_tb_gpio, 0);
662 pmac_call_feature(PMAC_FTR_READ_GPIO,
NULL, core99_tb_gpio, 0);
669 volatile static long int core99_l2_cache;
670 volatile static long int core99_l3_cache;
672 static void __devinit core99_init_caches(
int cpu)
679 core99_l2_cache = _get_L2CR();
680 printk(
"CPU0: L2CR is %lx\n", core99_l2_cache);
682 printk(
"CPU%d: L2CR was %lx\n", cpu, _get_L2CR());
684 _set_L2CR(core99_l2_cache);
685 printk(
"CPU%d: L2CR set to %lx\n", cpu, core99_l2_cache);
692 core99_l3_cache = _get_L3CR();
693 printk(
"CPU0: L3CR is %lx\n", core99_l3_cache);
695 printk(
"CPU%d: L3CR was %lx\n", cpu, _get_L3CR());
697 _set_L3CR(core99_l3_cache);
698 printk(
"CPU%d: L3CR set to %lx\n", cpu, core99_l3_cache);
703 static void __init smp_core99_setup(
int ncpus)
711 smp_core99_setup_i2c_hwsync(ncpus);
714 if (pmac_tb_freeze ==
NULL) {
719 pmac_tb_freeze = smp_core99_pfunc_tb_freeze;
721 " platform function\n");
732 core99_tb_gpio = KL_GPIO_TB_ENABLE;
737 core99_tb_gpio = *tbprop;
740 pmac_tb_freeze = smp_core99_gpio_tb_freeze;
742 " GPIO 0x%02x\n", core99_tb_gpio);
748 if (pmac_tb_freeze ==
NULL) {
759 for (i = 1; i <
ncpus; ++
i)
760 set_hard_smp_processor_id(i, i);
769 static int __init smp_core99_probe(
void)
774 if (
ppc_md.progress)
ppc_md.progress(
"smp_core99_probe", 0x345);
793 smp_core99_setup(ncpus);
799 core99_init_caches(0);
804 static int __devinit smp_core99_kick_cpu(
int nr)
806 unsigned int save_vector;
810 if (nr < 0 || nr > 3)
814 ppc_md.progress(
"smp_core99_kick_cpu", 0x346);
828 pmac_call_feature(PMAC_FTR_RESET_CPU,
NULL, nr, 0);
838 *vector = save_vector;
842 if (
ppc_md.progress)
ppc_md.progress(
"smp_core99_kick_cpu done", 0x347);
847 static void __devinit smp_core99_setup_cpu(
int cpu_nr)
851 core99_init_caches(cpu_nr);
858 #ifdef CONFIG_HOTPLUG_CPU
860 unsigned long action,
void *hcpu)
868 if (pmac_tb_clock_chip_host) {
871 pr_err(
"Failed to open i2c bus for time sync\n");
872 return notifier_from_errno(rc);
879 if (pmac_tb_clock_chip_host)
889 .notifier_call = smp_core99_cpu_notify,
893 static void __init smp_core99_bringup_done(
void)
895 extern void g5_phy_disable_cpu1(
void);
898 if (pmac_tb_clock_chip_host)
907 g5_phy_disable_cpu1();
909 #ifdef CONFIG_HOTPLUG_CPU
910 register_cpu_notifier(&smp_core99_cpu_nb);
914 ppc_md.progress(
"smp_core99_bringup_done", 0x349);
918 #ifdef CONFIG_HOTPLUG_CPU
920 static int smp_core99_cpu_disable(
void)
922 int rc = generic_cpu_disable();
933 static void pmac_cpu_die(
void)
940 generic_set_cpu_dead(cpu);
948 static void pmac_cpu_die(
void)
962 generic_set_cpu_dead(cpu);
988 .message_pass = smp_mpic_message_pass,
989 .probe = smp_core99_probe,
991 .bringup_done = smp_core99_bringup_done,
993 .kick_cpu = smp_core99_kick_cpu,
994 .setup_cpu = smp_core99_setup_cpu,
995 .give_timebase = smp_core99_give_timebase,
996 .take_timebase = smp_core99_take_timebase,
997 #if defined(CONFIG_HOTPLUG_CPU)
998 .cpu_disable = smp_core99_cpu_disable,
999 .cpu_die = generic_cpu_die,
1017 #ifdef CONFIG_PPC_PMAC32_PSURGE
1026 for (cpu = 1; cpu < 4 && cpu <
NR_CPUS; ++
cpu)
1032 #ifdef CONFIG_HOTPLUG_CPU
1033 ppc_md.cpu_die = pmac_cpu_die;