patch-2.4.21 linux-2.4.21/arch/ppc/platforms/pmac_smp.c
Next file: linux-2.4.21/arch/ppc/platforms/pmac_time.c
Previous file: linux-2.4.21/arch/ppc/platforms/pmac_sleep.S
Back to the patch index
Back to the overall index
- Lines: 255
- Date:
2003-06-13 07:51:31.000000000 -0700
- Orig file:
linux-2.4.20/arch/ppc/platforms/pmac_smp.c
- Orig date:
2002-11-28 15:53:11.000000000 -0800
diff -urN linux-2.4.20/arch/ppc/platforms/pmac_smp.c linux-2.4.21/arch/ppc/platforms/pmac_smp.c
@@ -1,11 +1,14 @@
/*
- * BK Id: %F% %I% %G% %U% %#%
- */
-/*
* SMP support for power macintosh.
*
* We support both the old "powersurge" SMP architecture
* and the current Core99 (G4 PowerMac) machines.
+ *
+ * Note that we don't support the very first rev. of
+ * Apple/DayStar 2 CPUs board, the one with the funky
+ * watchdog. Hopefully, none of these should be there except
+ * maybe internally to Apple. I should probably still add some
+ * code to detect this card though and disable SMP. --BenH.
*
* Support Macintosh G4 SMP by Troy Benjegerdes (hozer@drgw.net)
* and Ben Herrenschmidt <benh@kernel.crashing.org>.
@@ -96,15 +99,16 @@
static volatile u8 *psurge_sec_intr;
static volatile u32 *psurge_start;
-/* what sort of powersurge board we have */
-static int psurge_type;
-
/* values for psurge_type */
+#define PSURGE_NONE -1
#define PSURGE_DUAL 0
#define PSURGE_QUAD_OKEE 1
#define PSURGE_QUAD_COTTON 2
#define PSURGE_QUAD_ICEGRASS 3
+/* what sort of powersurge board we have */
+static int psurge_type = PSURGE_NONE;
+
volatile static long int core99_l2_cache;
volatile static long int core99_l3_cache;
@@ -140,113 +144,13 @@
}
}
-/* Some CPU registers have to be saved from the first CPU and
- * applied to others. Note that we override what is setup by
- * the cputable intentionally.
- */
-
-#define reg_hid0 0
-#define reg_hid1 1
-#define reg_msscr0 2
-#define reg_msssr0 3
-#define reg_ictrl 4
-#define reg_ldstcr 5
-#define reg_ldstdb 6
-#define reg_count 7
-
-#define stringify __stringify
-
-static unsigned long cpu_regs[reg_count];
-
-static void __pmac
-cpu_setup_grab(void)
-{
- unsigned int pvers = mfspr(SPRN_PVR)>>16;
-
- /* Read cache setting of CPU 0 */
- core99_init_caches();
-
- /* 7400/7410/7450 */
- if (pvers == 0x8000 || pvers == 0x000c || pvers == 0x800c) {
- cpu_regs[reg_hid0] = mfspr(SPRN_HID0);
- cpu_regs[reg_msscr0] = mfspr(SPRN_MSSCR0);
- cpu_regs[reg_msssr0] = mfspr(SPRN_MSSSR0);
- }
- /* 7450 only */
- if (pvers == 0x8000) {
- cpu_regs[reg_hid1] = mfspr(SPRN_HID1);
- cpu_regs[reg_ictrl] = mfspr(SPRN_ICTRL);
- cpu_regs[reg_ldstcr] = mfspr(SPRN_LDSTCR);
- cpu_regs[reg_ldstdb] = mfspr(SPRN_LDSTDB);
- }
- flush_dcache_range((unsigned long)cpu_regs, (unsigned long)&cpu_regs[reg_count]);
-}
-
-static void __pmac
-cpu_setup_apply(int cpu_nr)
-{
- unsigned int pvers = mfspr(SPRN_PVR)>>16;
-
- /* Apply cache setting from CPU 0 */
- core99_init_caches();
-
- /* 7400/7410/7450 */
- if (pvers == 0x8000 || pvers == 0x000c || pvers == 0x800c) {
- unsigned long tmp;
- __asm__ __volatile__ (
- "lwz %0,4*"stringify(reg_hid0)"(%1)\n"
- "sync\n"
- "mtspr "stringify(SPRN_HID0)", %0\n"
- "isync;sync\n"
- "lwz %0, 4*"stringify(reg_msscr0)"(%1)\n"
- "sync\n"
- "mtspr "stringify(SPRN_MSSCR0)", %0\n"
- "isync;sync\n"
-// "lwz %0, "stringify(reg_msssr0)"(%1)\n"
-// "sync\n"
-// "mtspr "stringify(SPRN_MSSSR0)", %0\n"
-// "isync;sync\n"
- : "=&r" (tmp) : "r" (cpu_regs));
- }
- /* 7410 only */
- if (pvers == 0x800c) {
- unsigned long tmp;
- __asm__ __volatile__ (
- "li %0, 0\n"
- "sync\n"
- "mtspr "stringify(SPRN_L2CR2)", %0\n"
- "isync;sync\n"
- : "=&r" (tmp));
- }
- /* 7450 only */
- if (pvers == 0x8000) {
- unsigned long tmp;
- __asm__ __volatile__ (
- "lwz %0, 4*"stringify(reg_hid1)"(%1)\n"
- "sync\n"
- "mtspr "stringify(SPRN_HID1)", %0\n"
- "isync;sync\n"
- "lwz %0, 4*"stringify(reg_ictrl)"(%1)\n"
- "sync\n"
- "mtspr "stringify(SPRN_ICTRL)", %0\n"
- "isync;sync\n"
- "lwz %0, 4*"stringify(reg_ldstcr)"(%1)\n"
- "sync\n"
- "mtspr "stringify(SPRN_LDSTCR)", %0\n"
- "isync;sync\n"
- "lwz %0, 4*"stringify(reg_ldstdb)"(%1)\n"
- "sync\n"
- "mtspr "stringify(SPRN_LDSTDB)", %0\n"
- "isync;sync\n"
- : "=&r" (tmp) : "r" (cpu_regs));
- }
-}
-
/*
* Set and clear IPIs for powersurge.
*/
static inline void psurge_set_ipi(int cpu)
{
+ if (psurge_type == PSURGE_NONE)
+ return;
if (cpu == 0)
in_be32(psurge_pri_intr);
else if (psurge_type == PSURGE_DUAL)
@@ -258,10 +162,14 @@
static inline void psurge_clr_ipi(int cpu)
{
if (cpu > 0) {
- if (psurge_type == PSURGE_DUAL)
+ switch(psurge_type) {
+ case PSURGE_DUAL:
out_8(psurge_sec_intr, ~0);
- else
+ case PSURGE_NONE:
+ break;
+ default:
PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, 1 << cpu);
+ }
}
}
@@ -413,6 +321,7 @@
if ((in_8(hhead_base + HHEAD_CONFIG) & 0x02) == 0) {
/* not a dual-cpu card */
iounmap((void *) hhead_base);
+ psurge_type = PSURGE_NONE;
return 1;
}
ncpus = 2;
@@ -499,15 +408,19 @@
{
if (cpu_nr == 0) {
+ /* If we failed to start the second CPU, we should still
+ * send it an IPI to start the timebase & DEC or we might
+ * have them stuck.
+ */
if (smp_num_cpus < 2)
- return;
+ goto sync_tb;
/* reset the entry point so if we get another intr we won't
* try to startup again */
out_be32(psurge_start, 0x100);
- if (request_irq(30, psurge_primary_intr, 0, "primary IPI", 0))
+ if (request_irq(30, psurge_primary_intr, SA_INTERRUPT, "primary IPI", 0))
printk(KERN_ERR "Couldn't get primary IPI interrupt");
}
-
+sync_tb:
if (psurge_type == PSURGE_DUAL)
psurge_dual_sync_tb(cpu_nr);
}
@@ -529,8 +442,11 @@
openpic_request_IPIs();
for (i = 1; i < ncpus; ++i)
smp_hw_index[i] = i;
+#ifdef CONFIG_6xx /* XXX */
powersave_nap = 0;
- cpu_setup_grab();
+#endif
+ /* Read cache setting of CPU 0 */
+ core99_init_caches();
}
return ncpus;
@@ -594,9 +510,12 @@
static void __init
smp_core99_setup_cpu(int cpu_nr)
{
- /* Setup some registers */
+
+ /* Setup some critical registers
+ * and apply cache setting from CPU 0
+ */
if (cpu_nr != 0)
- cpu_setup_apply(cpu_nr);
+ core99_init_caches();
/* Setup openpic */
do_openpic_setup_cpu();
@@ -608,16 +527,16 @@
/* PowerSurge-style Macs */
struct smp_ops_t psurge_smp_ops __pmacdata = {
- smp_psurge_message_pass,
- smp_psurge_probe,
- smp_psurge_kick_cpu,
- smp_psurge_setup_cpu,
+ .message_pass = smp_psurge_message_pass,
+ .probe = smp_psurge_probe,
+ .kick_cpu = smp_psurge_kick_cpu,
+ .setup_cpu = smp_psurge_setup_cpu,
};
/* Core99 Macs (dual G4s) */
struct smp_ops_t core99_smp_ops __pmacdata = {
- smp_openpic_message_pass,
- smp_core99_probe,
- smp_core99_kick_cpu,
- smp_core99_setup_cpu,
+ .message_pass = smp_openpic_message_pass,
+ .probe = smp_core99_probe,
+ .kick_cpu = smp_core99_kick_cpu,
+ .setup_cpu = smp_core99_setup_cpu,
};
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)