Subject: Re: WFI idle for ARM926EJ-S/ARM1026EJ-S
To: Todd Allan <todd_allan@picovex.com>
From: Jason Thorpe <thorpej@shagadelic.org>
List: port-arm
Date: 08/08/2006 09:43:55
On Aug 7, 2006, at 3:02 PM, Todd Allan wrote:
> 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.
Note, this should be controllable by sysctl -- a couple of years ago,
I discovered that using the powersave mode on Xscale, anyway, led to a
huge performance drop in a server appliance application.
It should probably default to "powersave enabled", and let
applications that need the extra performance tune for that.
>
> 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.
>
> 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));
-- thorpej