patch-2.3.99-pre9 linux/arch/mips/kernel/setup.c

Next file: linux/arch/mips/kernel/signal.c
Previous file: linux/arch/mips/kernel/scall_o32.S
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/setup.c linux/arch/mips/kernel/setup.c
@@ -1,4 +1,4 @@
-/* $Id: setup.c,v 1.22 2000/01/27 01:05:23 ralf Exp $
+/* $Id: setup.c,v 1.28 2000/03/13 22:21:44 harald Exp $
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
@@ -39,6 +39,7 @@
 #include <asm/io.h>
 #include <asm/stackframe.h>
 #include <asm/system.h>
+#include <asm/cpu.h>
 #ifdef CONFIG_SGI_IP22
 #include <asm/sgialib.h>
 #endif
@@ -46,11 +47,13 @@
 struct mips_cpuinfo boot_cpu_data = { NULL, NULL, 0 };
 
 /*
- * Not all of the MIPS CPUs have the "wait" instruction available.  This
- * is set to true if it is available.  The wait instruction stops the
- * pipeline and reduces the power consumption of the CPU very much.
+ * Not all of the MIPS CPUs have the "wait" instruction available. Moreover,
+ * the implementation of the "wait" feature differs between CPU families. This
+ * points to the function that implements CPU specific wait. 
+ * The wait instruction stops the pipeline and reduces the power consumption of
+ * the CPU very much.
  */
-char wait_available;
+void (*cpu_wait)(void) = NULL;
 
 /*
  * Do we have a cyclecounter available?
@@ -119,6 +122,125 @@
  */
 unsigned long isa_slot_offset;
 
+extern void sgi_sysinit(void);
+extern void SetUpBootInfo(void);
+extern void loadmmu(void);
+extern asmlinkage void start_kernel(void);
+extern int prom_init(int, char **, char **, int *);
+
+/*
+ * Probe whether cpu has config register by trying to play with
+ * alternate cache bit and see whether it matters.
+ * It's used by cpu_probe to distinguish between R3000A and R3081.
+ */
+static inline int cpu_has_confreg(void)
+{
+#ifdef CONFIG_CPU_R3000
+	extern unsigned long r3k_cache_size(unsigned long);
+	unsigned long size1, size2; 
+	unsigned long cfg = read_32bit_cp0_register(CP0_CONF);
+
+	size1 = r3k_cache_size(ST0_DE);
+	write_32bit_cp0_register(CP0_CONF, cfg^CONF_AC);
+	size2 = r3k_cache_size(ST0_DE);
+	write_32bit_cp0_register(CP0_CONF, cfg);
+	return size1 != size2;
+#else
+	return 0;
+#endif
+}
+
+static inline void cpu_probe(void)
+{
+	unsigned int prid = read_32bit_cp0_register(CP0_PRID);
+	switch(prid & 0xff00) {
+	case PRID_IMP_R2000:
+		mips_cputype = CPU_R2000;
+		break;
+	case PRID_IMP_R3000:
+		if((prid & 0xff) == PRID_REV_R3000A)
+			if(cpu_has_confreg())
+				mips_cputype = CPU_R3081E;
+			else
+				mips_cputype = CPU_R3000A;
+		else
+			 mips_cputype = CPU_R3000;
+		break;
+	case PRID_IMP_R4000:
+		if((prid & 0xff) == PRID_REV_R4400)
+			mips_cputype = CPU_R4400SC;
+		else
+			mips_cputype = CPU_R4000SC;
+		break;
+	case PRID_IMP_R4600:
+		mips_cputype = CPU_R4600;
+		break;
+	case PRID_IMP_R4650:
+		mips_cputype = CPU_R4650;
+		break;
+	case PRID_IMP_R4700:
+		mips_cputype = CPU_R4700;
+		break;
+	case PRID_IMP_R5000:
+		mips_cputype = CPU_R5000;
+		break;
+	case PRID_IMP_NEVADA:
+		mips_cputype = CPU_NEVADA;
+		break;
+	case PRID_IMP_R6000:
+		mips_cputype = CPU_R6000;
+		break;
+	case PRID_IMP_R6000A:
+		mips_cputype = CPU_R6000A;
+		break;
+	case PRID_IMP_R8000:
+		mips_cputype = CPU_R8000;
+		break;
+	case PRID_IMP_R10000:
+		mips_cputype = CPU_R10000;
+		break;
+	default:
+		mips_cputype = CPU_UNKNOWN;
+	}
+}
+
+asmlinkage void __init init_arch(int argc, char **argv, char **envp, int *prom_vec)
+{
+	unsigned int s;
+
+	/* Determine which MIPS variant we are running on. */
+	cpu_probe();
+
+	prom_init(argc, argv, envp, prom_vec);
+
+#ifdef CONFIG_SGI_IP22
+	sgi_sysinit();
+#endif
+#ifdef CONFIG_COBALT_MICRO_SERVER
+	SetUpBootInfo();
+#endif
+
+	/*
+	 * Determine the mmu/cache attached to this machine,
+	 * then flush the tlb and caches.  On the r4xx0
+	 * variants this also sets CP0_WIRED to zero.
+	 */
+	loadmmu();
+
+	/* Disable coprocessors */
+	s = read_32bit_cp0_register(CP0_STATUS);
+	s &= ~(ST0_CU1|ST0_CU2|ST0_CU3|ST0_KX|ST0_SX);
+	s |= ST0_CU0;
+	write_32bit_cp0_register(CP0_STATUS, s);
+
+	/*
+	 * Main should never return here, but
+	 * just in case, we know what happens.
+	 */
+	for(;;)
+		start_kernel();
+}
+
 static void __init default_irq_setup(void)
 {
 	panic("Unknown machtype in init_IRQ");
@@ -156,7 +278,7 @@
 	switch(mips_machgroup)
 	{
 #ifdef CONFIG_BAGET_MIPS
-	case MACH_GROUP_UNKNOWN: 
+	case MACH_GROUP_BAGET: 
 		baget_setup();
 		break;
 #endif
@@ -220,4 +342,19 @@
 			*memory_start_p = initrd_end;
 	}
 #endif
+
+	paging_init();
+}
+
+void r3081_wait(void) 
+{
+	unsigned long cfg = read_32bit_cp0_register(CP0_CONF);
+	write_32bit_cp0_register(CP0_CONF, cfg|CONF_HALT);
+}
+
+void r4k_wait(void)
+{
+	__asm__(".set\tmips3\n\t"
+		"wait\n\t"
+		".set\tmips0");
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)