Subject: Re: Supported ARM7 CPUs
To: Chris Gilbert , Ben Harris <bjh21@netbsd.org>
From: John Fremlin <vii@users.sourceforge.net>
List: port-arm32
Date: 06/02/2001 23:59:37
--=-=-=

Chris Gilbert <chris@paradox.demon.co.uk> writes:

[...]

> > > It's because ARM7TDMI is a very different core from ARM7.  They
> > > have different register assignments in CP15 for one thing.  To
> > > support ARM7TDMI, you'll need to add another batch of cpufunc
> > > routines.
> >
> > OK I've written them (from the 710 T docs). I do hope that the
> > abort fixups are no different, because I am disinclined to try to
> > audit those ;-)
> >
> > Is anybody willing to check over and or commit the code? I don't want
> > to keep it in my private tree.
> 
> If you send the patches to the list everyone can take a look and
> someone (possibly me :)) will commit them.

Here is the patch, about as ready as it's going to be for a while,
because I'll need some userspace before the data abort fixups get
tested. I'm sending it out now to avoid it getting stuck in my tree
(and possibly never to be seen again if I lose interest in the psionw
port).

Included:

        Add support for ARM 7TDMI CPU

        Fix some panic strings with \n at the end (which Ben should
        probably get rid of when fixing the disassem stuff)


Pending changes to sys/arch/arm:

        Inline asm versions of cpufunc.h funcs, which will make the
        hpcarm crews's lives easier - currently they inline the stuff
        by hand actually in the middle of C code :-(

        Pmap panic string fixes.



--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment;
  filename=netbsd-20010602-arm-7tdmi.patch

Index: arm/cpufunc.c
===================================================================
RCS file: /pub/NetBSD-CVS/syssrc/sys/arch/arm/arm/cpufunc.c,v
retrieving revision 1.3
diff -u -r1.3 cpufunc.c
--- cpufunc.c	2001/05/13 14:41:56	1.3
+++ cpufunc.c	2001/06/02 22:44:15
@@ -1,6 +1,7 @@
 /*	$NetBSD: cpufunc.c,v 1.3 2001/05/13 14:41:56 bjh21 Exp $	*/
 
 /*
+ * arm7tdmi support code Copyright (c) 2001 John Fremlin
  * arm8 support code Copyright (c) 1997 ARM Limited
  * arm8 support code Copyright (c) 1997 Causality Limited
  * Copyright (c) 1997 Mark Brinicombe.
@@ -195,6 +196,76 @@
 };
 #endif	/* CPU_ARM7 */
 
+#ifdef CPU_ARM7TDMI
+struct cpu_functions arm7tdmi_cpufuncs = {
+	/* CPU functions */
+	
+	cpufunc_id,			/* id			 */
+
+	/* MMU functions */
+
+	cpufunc_control,		/* control		*/
+	cpufunc_domains,		/* domain		*/
+	arm7tdmi_setttb,			/* setttb		*/
+	cpufunc_faultstatus,		/* faultstatus		*/
+	cpufunc_faultaddress,		/* faultaddress		*/
+
+	/* TLB functions */
+
+	arm7tdmi_tlb_flushID,		/* tlb_flushID		*/
+	arm7tdmi_tlb_flushID_SE,		/* tlb_flushID_SE	*/
+	arm7tdmi_tlb_flushID,		/* tlb_flushI		*/
+	arm7tdmi_tlb_flushID_SE,		/* tlb_flushI_SE	*/
+	arm7tdmi_tlb_flushID,		/* tlb_flushD		*/
+	arm7tdmi_tlb_flushID_SE,		/* tlb_flushD_SE	*/
+
+	/* Cache functions */
+
+	arm7tdmi_cache_flushID,		/* cache_flushID	*/
+	(void *)arm7tdmi_cache_flushID,	/* cache_flushID_SE	*/
+	arm7tdmi_cache_flushID,		/* cache_flushI		*/
+	(void *)arm7tdmi_cache_flushID,	/* cache_flushI_SE	*/
+	arm7tdmi_cache_flushID,		/* cache_flushD		*/
+	(void *)arm7tdmi_cache_flushID,	/* cache_flushD_SE	*/
+
+	cpufunc_nullop,			/* cache_cleanID	s*/
+	(void *)cpufunc_nullop,		/* cache_cleanID_E	s*/
+	cpufunc_nullop,			/* cache_cleanD		s*/
+	(void *)cpufunc_nullop,		/* cache_cleanD_E	*/
+
+	arm7tdmi_cache_flushID,		/* cache_purgeID	s*/
+	(void *)arm7tdmi_cache_flushID,	/* cache_purgeID_E	s*/
+	arm7tdmi_cache_flushID,		/* cache_purgeD		s*/
+	(void *)arm7tdmi_cache_flushID,	/* cache_purgeD_E	s*/
+
+	/* Other functions */
+
+	cpufunc_nullop,			/* flush_prefetchbuf	*/
+	cpufunc_nullop,			/* drain_writebuf	*/
+	cpufunc_nullop,			/* flush_brnchtgt_C	*/
+	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
+
+	(void *)cpufunc_nullop,		/* sleep		*/
+
+	/* Soft functions */
+
+	cpufunc_nullop,			/* cache_syncI		*/
+	(void *)cpufunc_nullop,		/* cache_cleanID_rng	*/
+	(void *)cpufunc_nullop,		/* cache_cleanD_rng	*/
+	(void *)arm7tdmi_cache_flushID,	/* cache_purgeID_rng	*/
+	(void *)arm7tdmi_cache_flushID,	/* cache_purgeD_rng	*/
+	(void *)cpufunc_nullop,		/* cache_syncI_rng	*/
+
+	arm7_dataabt_fixup,		/* dataabt_fixup	*/
+	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
+
+	arm7tdmi_context_switch,		/* context_switch	*/
+
+	arm7tdmi_setup			/* cpu setup		*/
+
+};
+#endif	/* CPU_ARM7TDMI */
+
 #ifdef CPU_ARM8
 struct cpu_functions arm8_cpufuncs = {
 	/* CPU functions */
@@ -370,6 +441,15 @@
 		return 0;
 	}
 #endif	/* CPU_ARM7 */
+#ifdef CPU_ARM7TDMI
+	if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD &&
+	    CPU_ID_IS7(cputype) &&
+	    (cputype & CPU_ID_7ARCH_MASK) == CPU_ID_7ARCH_V4T) {
+		cpufuncs = arm7tdmi_cpufuncs;
+		cpu_reset_needs_v4_MMU_disable = 0;
+		return 0;
+	}
+#endif	
 #ifdef CPU_ARM8
 	if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD &&
 	    (cputype & 0x0000f000) == 0x00008000) {
@@ -425,7 +505,7 @@
 #endif
 #endif
 
-#ifdef CPU_ARM6
+#if defined(CPU_ARM6)
 /*
  * ARM6 data abort fixup
  *
@@ -507,11 +587,11 @@
 		base = (fault_instruction >> 16) & 0x0f;
 		if (base == 13 && (frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) {
 			disassemble(fault_pc);
-			panic("Abort handler cannot fix this :-(\n");
+			panic("Abort handler cannot fix this :-(");
 		}
 		if (base == 15) {
 			disassemble(fault_pc);
-			panic("Abort handler cannot fix this :-(\n");
+			panic("Abort handler cannot fix this :-(");
 		}
 #ifdef DEBUG_FAULT_CORRECTION
 		if (pmap_debug_level >=0)
@@ -533,7 +613,7 @@
 			offset = fault_instruction & 0x0f;
 			if (offset == base) {
 				disassemble(fault_pc);
-				panic("Abort handler cannot fix this :-(\n");
+				panic("Abort handler cannot fix this :-(");
 			}
                 
 /* Register offset - hard we have to cope with shifts ! */
@@ -544,12 +624,12 @@
 			else {
 				if ((fault_instruction & (1 << 7)) != 0) {
 					disassemble(fault_pc);
-					panic("Abort handler cannot fix this :-(\n");
+					panic("Abort handler cannot fix this :-(");
 				}
 				shift = ((fault_instruction >> 8) & 0xf);
 				if (base == shift) {
 					disassemble(fault_pc);
-					panic("Abort handler cannot fix this :-(\n");
+					panic("Abort handler cannot fix this :-(");
 				}
 #ifdef DEBUG_FAULT_CORRECTION
 				if (pmap_debug_level >=0)
@@ -575,7 +655,7 @@
 				break;
 			case 3 : /* Rotate right */
 				disassemble(fault_pc);
-				panic("Abort handler cannot fix this :-(\n");
+				panic("Abort handler cannot fix this :-(");
 				break;
 			}
 
@@ -617,7 +697,7 @@
 			base = (fault_instruction >> 16) & 0x0f;
 			if (base == 15) {
 				disassemble(fault_pc);
-				panic("Abort handler cannot fix this :-(\n");
+				panic("Abort handler cannot fix this :-(");
 			}
 			/* Count registers transferred */
 			count = 0;
@@ -663,11 +743,11 @@
 			base = (fault_instruction >> 16) & 0x0f;
 			if (base == 13 && (frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) {
 				disassemble(fault_pc);
-				panic("Abort handler cannot fix this :-(\n");
+				panic("Abort handler cannot fix this :-(");
 			}
 			if (base == 15) {
 				disassemble(fault_pc);
-				panic("Abort handler cannot fix this :-(\n");
+				panic("Abort handler cannot fix this :-(");
 			}
 
 			offset = (fault_instruction & 0xff) << 2;
@@ -718,7 +798,7 @@
 }
 #endif	/* CPU_ARM6 */
 
-#ifdef CPU_ARM7
+#if defined(CPU_ARM7) || defined(CPU_ARM7TDMI)
 /*
  * ARM7 data abort fixup
  *
@@ -794,11 +874,11 @@
 		base = (fault_instruction >> 16) & 0x0f;
 		if (base == 13 && (frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) {
 			disassemble(fault_pc);
-			panic("Abort handler cannot fix this :-(\n");
+			panic("Abort handler cannot fix this :-(");
 		}
 		if (base == 15) {
 			disassemble(fault_pc);
-			panic("Abort handler cannot fix this :-(\n");
+			panic("Abort handler cannot fix this :-(");
 		}
 #ifdef DEBUG_FAULT_CORRECTION
 		if (pmap_debug_level >=0)
@@ -820,7 +900,7 @@
 			offset = fault_instruction & 0x0f;
 			if (offset == base) {
 				disassemble(fault_pc);
-				panic("Abort handler cannot fix this :-(\n");
+				panic("Abort handler cannot fix this :-(");
 			}
                 
 /* Register offset - hard we have to cope with shifts ! */
@@ -831,12 +911,12 @@
 			else {
 				if ((fault_instruction & (1 << 7)) != 0) {
 					disassemble(fault_pc);
-					panic("Abort handler cannot fix this :-(\n");
+					panic("Abort handler cannot fix this :-(");
 				}
 				shift = ((fault_instruction >> 8) & 0xf);
 				if (base == shift) {
 					disassemble(fault_pc);
-					panic("Abort handler cannot fix this :-(\n");
+					panic("Abort handler cannot fix this :-(");
 				}
 #ifdef DEBUG_FAULT_CORRECTION
 				if (pmap_debug_level >=0)
@@ -862,7 +942,7 @@
 				break;
 			case 3 : /* Rotate right */
 				disassemble(fault_pc);
-				panic("Abort handler cannot fix this :-(\n");
+				panic("Abort handler cannot fix this :-(");
 				break;
 			}
 
@@ -903,7 +983,7 @@
 			base = (fault_instruction >> 16) & 0x0f;
 			if (base == 15) {
 				disassemble(fault_pc);
-				panic("Abort handler cannot fix this :-(\n");
+				panic("Abort handler cannot fix this :-(");
 			}
 			/* Count registers transferred */
 			count = 0;
@@ -949,11 +1029,11 @@
 			base = (fault_instruction >> 16) & 0x0f;
 			if (base == 13 && (frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) {
 				disassemble(fault_pc);
-				panic("Abort handler cannot fix this :-(\n");
+				panic("Abort handler cannot fix this :-(");
 			}
 			if (base == 15) {
 				disassemble(fault_pc);
-				panic("Abort handler cannot fix this :-(\n");
+				panic("Abort handler cannot fix this :-(");
 			}
 
 			offset = (fault_instruction & 0xff) << 2;
@@ -1002,14 +1082,14 @@
 
 	return(ABORT_FIXUP_OK);
 }
-#endif	/* CPU_ARM7 */
+#endif	/* CPU_ARM7 || CPU_ARM7TDMI */
 
 /*
  * CPU Setup code
  */
 
-#if defined(CPU_ARM6) || defined(CPU_ARM7) || defined(CPU_ARM8) || \
- 	defined(CPU_SA110)
+#if defined(CPU_ARM6) || defined(CPU_ARM7) || defined(CPU_ARM7TDMI) \
+	|| defined(CPU_ARM8) || defined(CPU_SA110)
 int cpuctrl;
 
 #define IGN	0
@@ -1050,9 +1130,10 @@
 	}
 	return(cpuctrl);
 }
-#endif
+#endif /* CPU_ARM6 || CPU_ARM7 || CPU_ARM7TDMI || CPU_ARM8 || CPU_SA110 */
 
-#if defined (CPU_ARM6) || defined(CPU_ARM7) || defined(CPU_ARM8)
+#if defined (CPU_ARM6) || defined(CPU_ARM7) || defined(CPU_ARM7TDMI) \
+	|| defined(CPU_ARM8)
 struct cpu_option arm678_options[] = {
 #ifdef COMPAT_12
 	{ "nocache",		IGN, BIC, CPU_CONTROL_IDC_ENABLE },
@@ -1065,7 +1146,7 @@
 	{ NULL,			IGN, IGN, 0 }
 };
 
-#endif	/* CPU_ARM6 || CPU_ARM7 || CPU_ARM8 */
+#endif	/* CPU_ARM6 || CPU_ARM7 || CPU_ARM7TDMI || CPU_ARM8 */
 
 #ifdef CPU_ARM6
 struct cpu_option arm6_options[] = {
@@ -1146,6 +1227,38 @@
 	cpu_control(0xffffffff, cpuctrl);
 }
 #endif	/* CPU_ARM7 */
+
+#ifdef CPU_ARM7TDMI
+struct cpu_option arm7tdmi_options[] = {
+	{ "arm7.cache",		BIC, OR,  CPU_CONTROL_IDC_ENABLE },
+	{ "arm7.nocache",	OR,  BIC, CPU_CONTROL_IDC_ENABLE },
+	{ "arm7.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
+	{ "arm7.nowritebuf",	OR,  BIC, CPU_CONTROL_WBUF_ENABLE },
+#ifdef COMPAT_12
+	{ "fpaclk2",		BIC, OR,  CPU_CONTROL_CPCLK },
+#endif	/* COMPAT_12 */
+	{ "arm700.fpaclk",	BIC, OR,  CPU_CONTROL_CPCLK },
+	{ NULL,			IGN, IGN, 0 }
+};
+
+void
+arm7tdmi_setup(args)
+	char *args;
+{
+	cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
+		 | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
+		 | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE;
+
+	cpuctrl = parse_cpu_options(args, arm678_options, cpuctrl);
+	cpuctrl = parse_cpu_options(args, arm7tdmi_options, cpuctrl);
+
+	/* Clear out the cache */
+	cpu_cache_purgeID();
+
+	/* Set the control register */    
+	cpu_control(0xffffffff, cpuctrl);
+}
+#endif	/* CPU_ARM7TDMI */
 
 #ifdef CPU_ARM8
 struct cpu_option arm8_options[] = {
Index: arm/cpufunc_asm.S
===================================================================
RCS file: /pub/NetBSD-CVS/syssrc/sys/arch/arm/arm/cpufunc_asm.S,v
retrieving revision 1.1
diff -u -r1.1 cpufunc_asm.S
--- cpufunc_asm.S	2001/05/06 18:01:44	1.1
+++ cpufunc_asm.S	2001/06/02 22:44:21
@@ -1,6 +1,7 @@
 /*	$NetBSD: cpufunc_asm.S,v 1.1 2001/05/06 18:01:44 bjh21 Exp $	*/
 
 /*
+ * arm7tdmi support code Copyright (c) 2001 John Fremlin
  * arm8 support code Copyright (c) 1997 ARM Limited
  * arm8 support code Copyright (c) 1997 Causality Limited
  * Copyright (c) 1997,1998 Mark Brinicombe.
@@ -173,6 +174,25 @@
 	mov	pc, lr
 #endif	/* CPU_ARM6 || CPU_ARM7 */
 
+#ifdef CPU_ARM7TDMI
+	
+ENTRY(arm7tdmi_setttb)
+	mov	r1,r0 /* store the ttb in a safe place */
+	mov	r2,lr /* ditto with lr */
+	
+	bl	_C_LABEL(arm7tdmi_cache_flushID)
+	
+	/* Write the TTB */
+	mcr	p15, 0, r1, c2, c0, 0
+
+	/* If we have updated the TTB we must flush the TLB */
+	bl	_C_LABEL(arm7tdmi_tlb_flushID)
+	/* For good measure we will flush the IDC as well */
+	bl	_C_LABEL(arm7tdmi_cache_flushID)
+
+	mov	pc, r2
+#endif	/* CPU_7TDMI */
+	
 #ifdef CPU_ARM8
 ENTRY(arm8_setttb)
 	/* We need to clean and flush the cache as it uses virtual
@@ -261,6 +281,16 @@
 	mov	pc, lr
 #endif	/* CPU_ARM6 || CPU_ARM7 */
 
+#ifdef CPU_ARM7TDMI
+ENTRY(arm7tdmi_tlb_flushID)
+	mov	r0,#0
+	mcr	p15, 0, r0, c8, c7, 0
+	mov	pc,lr
+	
+ENTRY(arm7tdmi_tlb_flushID_SE)
+	mcr	p15, 0, r0, c8, c7, 1
+	mov	pc,lr		
+#endif	
 #ifdef CPU_ARM8
 ENTRY(arm8_tlb_flushID)
 	mcr	15, 0, r0, c8, c7, 0		/* flush I+D tlb */
@@ -304,6 +334,18 @@
 	mov	pc, lr
 #endif	/* CPU_ARM6 || CPU_ARM7 */
 
+#ifdef CPU_ARM7TDMI
+ENTRY(arm7tdmi_cache_flushID)
+	mov	r0, #0
+	
+	mcr	p15, 0, r0, c7, c7, 0
+	/* Make sure that the pipeline is emptied */
+	mov	r0, r0
+	mov	r0, r0
+
+	mov	pc,lr
+#endif	
+	
 #ifdef CPU_ARM8
 ENTRY(arm8_cache_flushID)
 	mcr	15, 0, r0, c7, c7, 0		/* flush I+D cache */
@@ -756,6 +798,10 @@
 	mov     pc, lr
 #endif
 
+#ifdef CPU_ARM7TDMI
+ENTRY(arm7tdmi_context_switch)
+	b arm7tdmi_setttb
+#endif	
 #ifdef CPU_ARM8
 ENTRY(arm8_context_switch)
 	/* Switch the memory to the new process */
Index: arm32/cpu.c
===================================================================
RCS file: /pub/NetBSD-CVS/syssrc/sys/arch/arm/arm32/cpu.c,v
retrieving revision 1.2
diff -u -r1.2 cpu.c
--- cpu.c	2001/05/13 13:53:08	1.2
+++ cpu.c	2001/06/02 22:44:25
@@ -294,7 +294,7 @@
 	{ "ARM3",	"CPU_ARM3" },	/* CPU_CLASS_ARM3 */
 	{ "ARM6",	"CPU_ARM6" },	/* CPU_CLASS_ARM6 */
 	{ "ARM7",	"CPU_ARM7" },	/* CPU_CLASS_ARM7 */
-	{ "ARM7TDMI",	NULL },		/* CPU_CLASS_ARM7TDMI */
+	{ "ARM7TDMI",	"CPU_ARM7TDMI" },/* CPU_CLASS_ARM7TDMI */
 	{ "ARM8",	"CPU_ARM8" },	/* CPU_CLASS_ARM8 */
 	{ "ARM9TDMI",	NULL },		/* CPU_CLASS_ARM9TDMI */
 	{ "ARM9E-S",	NULL },		/* CPU_CLASS_ARM9ES */
@@ -340,6 +340,7 @@
 	switch (cpu->cpu_class) {
 	case CPU_CLASS_ARM6:
 	case CPU_CLASS_ARM7:
+	case CPU_CLASS_ARM7TDMI:
 	case CPU_CLASS_ARM8:
 		if ((cpu->cpu_ctrl & CPU_CONTROL_IDC_ENABLE) == 0)
 			strcat(cpu->cpu_model, " IDC disabled");
@@ -390,6 +391,9 @@
 #ifdef CPU_ARM7
 	case CPU_CLASS_ARM7:
 #endif
+#ifdef CPU_ARM7TDMI
+	case CPU_CLASS_ARM7TDMI:
+#endif		
 #ifdef CPU_ARM8
 	case CPU_CLASS_ARM8:
 #endif
Index: include/cpufunc.h
===================================================================
RCS file: /pub/NetBSD-CVS/syssrc/sys/arch/arm/include/cpufunc.h,v
retrieving revision 1.2
diff -u -r1.2 cpufunc.h
--- cpufunc.h	2001/03/06 22:29:13	1.2
+++ cpufunc.h	2001/06/02 22:44:50
@@ -202,6 +202,16 @@
 void	arm7_setup		__P((char *string));
 #endif	/* CPU_ARM7 */
 
+#ifdef CPU_ARM7TDMI
+int	arm7_dataabt_fixup	__P((void *arg));
+void	arm7tdmi_setup		__P((char *string));
+void	arm7tdmi_setttb		__P((u_int ttb));
+void	arm7tdmi_tlb_flushID	__P((void));
+void	arm7tdmi_tlb_flushID_SE	__P((u_int va));
+void	arm7tdmi_cache_flushID	__P((void));
+void	arm7tdmi_context_switch	__P((void));
+#endif /* CPU_ARM7TDMI */
+
 #ifdef CPU_ARM8
 void	arm8_setttb		__P((u_int ttb));
 void	arm8_tlb_flushID	__P((void));

--=-=-=


-- 

	http://ape.n3.net

--=-=-=--