Subject: WFI idle for ARM926EJ-S/ARM1026EJ-S
To: None <port-arm@netbsd.org>
From: Todd Allan <todd_allan@picovex.com>
List: port-arm
Date: 08/07/2006 15:02:20
This is a multi-part message in MIME format.
--------------050406090507030404070901
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

The attached patch adds a powersave idle for ARM926EJS/ARM1026EJS, 
comprised of a Wait For Interrupt operation as described in the ARM ARM: 
write SBZ data to CP15 coprocessor register 7, CRm=c0, opcode2=0.

This should work on some other ARM processors as well, and the patch 
implements it in a generic cpufunc, but some ARM implementations, 
notably including XScale, do this differently.  The patch has only been 
tested on a 926EJ-S; it enables WFI on the 926EJ-S and on the 10EJ-S, 
the TRM for which indicates that it implements this operation.  This 
patch applies on top of a patch from Scott Allan previously sent 
07/31/2006 in thread "Patch to add support for ARM9E".

Any suggestions appreciated, thanks.


--------------050406090507030404070901
Content-Type: text/x-patch;
 name="armv5_wfi_idle.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="armv5_wfi_idle.patch"

Index: netbsd_quilt/src/sys/arch/arm/arm/cpufunc.c
===================================================================
--- netbsd_quilt.orig/src/sys/arch/arm/arm/cpufunc.c
+++ netbsd_quilt/src/sys/arch/arm/arm/cpufunc.c
@@ -501,7 +501,7 @@ struct cpu_functions armv5_ec_cpufuncs =
 	cpufunc_nullop,			/* flush_brnchtgt_C	*/
 	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
 
-	(void *)cpufunc_nullop,		/* sleep		*/
+	cpufunc_sleep,			/* sleep		*/
 
 	/* Soft functions */
 
@@ -1108,6 +1108,10 @@ set_cpufuncs()
 		cpu_reset_needs_v4_MMU_disable = 1;	/* V4 or higher */
 		get_cachetype_cp15();
 		pmap_pte_init_generic();
+
+		/* Use powersave on this CPU. */
+		cpu_do_powersave = 1;
+
 		return 0;
 	}
 #endif /* CPU_ARM9E || CPU_ARM10 */
Index: netbsd_quilt/src/sys/arch/arm/arm/cpufunc_asm.S
===================================================================
--- netbsd_quilt.orig/src/sys/arch/arm/arm/cpufunc_asm.S
+++ netbsd_quilt/src/sys/arch/arm/arm/cpufunc_asm.S
@@ -148,3 +148,12 @@ ENTRY(get_pc_str_offset)
 	ldr	r0, [sp]
 	sub	r0, r0, r1
 	ldmdb	fp, {fp, sp, pc}
+
+/*
+ * WFI low-power idle per ARM ARM.
+ */
+
+ENTRY(cpufunc_sleep)
+	mov	r0, #0x0
+	mcr p15, 0, r0, c7, c0, 4
+	mov	pc, lr
Index: netbsd_quilt/src/sys/arch/arm/include/cpufunc.h
===================================================================
--- netbsd_quilt.orig/src/sys/arch/arm/include/cpufunc.h
+++ netbsd_quilt/src/sys/arch/arm/include/cpufunc.h
@@ -209,6 +209,7 @@ u_int	cpufunc_control		__P((u_int, u_int
 void	cpufunc_domains		__P((u_int));
 u_int	cpufunc_faultstatus	__P((void));
 u_int	cpufunc_faultaddress	__P((void));
+void	cpufunc_sleep		__P((int));
 
 #ifdef CPU_ARM3
 u_int	arm3_control		__P((u_int, u_int));

--------------050406090507030404070901--