[PATCH] Au1xxx Sleeping functions for 2.6

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello,

here a patch against Linuxmips-2.6.15 to fix the sleeping functions
for CPUs au1xxx.

Currently the sleep mode works but a lot of internal peripherals'
drivers miss the power management functions so is possibile that the
kernel hangs at wake up if some internal peripherals other than the
first serial line is enabled (expecially for the ethernet)!

However I'm working for a full support of sleep mode and I hope to be
able to send a patch to fix this in the near future...

Ciao,

Rodolfo

-- 

GNU/Linux Solutions                  e-mail:    giometti@xxxxxxxxxxxx
Linux Device Driver                             giometti@xxxxxxxxx
Embedded Systems                     		giometti@xxxxxxxx
UNIX programming                     phone:     +39 349 2432127
--- /home/develop/embedded/mips/linux/linux-mips.git/arch/mips/au1000/common/sleeper.S	2006-03-31 16:57:26.000000000 +0200
+++ arch/mips/au1000/common/sleeper.S	2006-03-31 16:26:35.000000000 +0200
@@ -9,22 +9,54 @@
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
  */
+#include <linux/config.h>
 #include <asm/asm.h>
 #include <asm/mipsregs.h>
 #include <asm/addrspace.h>
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
+#include <asm/mach-au1x00/au1000.h>
+
+/*
+ * Note: This file is *not* conditional on CONFIG_PM since Alchemy sleep 
+ * need not be tied to any particular power management scheme.
+ */
+
+	.extern __flush_cache_all
 
 	.text
-	.set	macro
-	.set	noat
 	.align	5
 
-/* Save all of the processor general registers and go to sleep.
- * A wakeup condition will get us back here to restore the registers.
+/*
+ * Save the processor general registers and go to sleep. A wakeup
+ * condition will get us back here to restore the registers.
  */
-LEAF(save_and_sleep)
 
+/* still need to fix alignment issues here */
+save_and_sleep_frmsz = 48
+NESTED(save_and_sleep, save_and_sleep_frmsz, ra)
+	.set noreorder
+	.set nomacro
+	.set noat
+	subu sp, save_and_sleep_frmsz
+	sw ra, save_and_sleep_frmsz-4(sp)
+	sw s0, save_and_sleep_frmsz-8(sp)
+	sw s1, save_and_sleep_frmsz-12(sp)
+	sw s2, save_and_sleep_frmsz-16(sp)
+	sw s3, save_and_sleep_frmsz-20(sp)
+	sw s4, save_and_sleep_frmsz-24(sp)
+	sw s5, save_and_sleep_frmsz-28(sp)
+	sw s6, save_and_sleep_frmsz-32(sp)
+	sw s7, save_and_sleep_frmsz-36(sp)
+	sw s8, save_and_sleep_frmsz-40(sp)
+	sw gp, save_and_sleep_frmsz-44(sp)
+
+	/* We only need to save the registers that the calling function 
+	 * hasn't saved for us.  0 is always zero.  8 - 15, 24 and 25 are 
+	 * temporaries and can be used without saving. 26 and 27 are reserved 
+	 * for interrupt/trap handling and expected to change.  29 is the 
+	 * stack pointer which is handled as a special case here.
+	 */
 	subu	sp, PT_SIZE
 	sw	$1, PT_R1(sp)
 	sw	$2, PT_R2(sp)
@@ -33,14 +65,6 @@
 	sw	$5, PT_R5(sp)
 	sw	$6, PT_R6(sp)
 	sw	$7, PT_R7(sp)
-	sw	$8, PT_R8(sp)
-	sw	$9, PT_R9(sp)
-	sw	$10, PT_R10(sp)
-	sw	$11, PT_R11(sp)
-	sw	$12, PT_R12(sp)
-	sw	$13, PT_R13(sp)
-	sw	$14, PT_R14(sp)
-	sw	$15, PT_R15(sp)
 	sw	$16, PT_R16(sp)
 	sw	$17, PT_R17(sp)
 	sw	$18, PT_R18(sp)
@@ -49,32 +73,54 @@
 	sw	$21, PT_R21(sp)
 	sw	$22, PT_R22(sp)
 	sw	$23, PT_R23(sp)
-	sw	$24, PT_R24(sp)
-	sw	$25, PT_R25(sp)
-	sw	$26, PT_R26(sp)
-	sw	$27, PT_R27(sp)
 	sw	$28, PT_R28(sp)
-	sw	$29, PT_R29(sp)
 	sw	$30, PT_R30(sp)
 	sw	$31, PT_R31(sp)
+#define PT_C0STATUS PT_LO
+#define PT_CONTEXT PT_HI
+#define PT_PAGEMASK PT_EPC
+#define PT_CONFIG PT_BVADDR
 	mfc0	k0, CP0_STATUS
-	sw	k0, 0x20(sp)
+	sw	k0, PT_C0STATUS(sp) // 0x20
 	mfc0	k0, CP0_CONTEXT
-	sw	k0, 0x1c(sp)
+	sw	k0, PT_CONTEXT(sp) // 0x1c
 	mfc0	k0, CP0_PAGEMASK
-	sw	k0, 0x18(sp)
+	sw	k0, PT_PAGEMASK(sp) // 0x18
 	mfc0	k0, CP0_CONFIG
-	sw	k0, 0x14(sp)
+	sw	k0, PT_CONFIG(sp) // 0x14
+
+#if 0
+        /* Infinite loop to allow JTAG attach before sleep mode (debug only)
+         */
+2:      li      t1, 0
+        beq     t1, zero, 2b
+        nop
+#endif
+
+	.set macro
+	.set at
+
+	li	t0, SYS_SLPPWR
+	sw	zero, 0(t0)	/* Get the processor ready to sleep */
+	sync
 
 	/* Now set up the scratch registers so the boot rom will
 	 * return to this point upon wakeup.
+	 * sys_scratch0 : SP
+	 * sys_scratch1 : RA
 	 */
-	la	k0, 1f
-	lui	k1, 0xb190
-	ori	k1, 0x18
-	sw	sp, 0(k1)
-	ori 	k1, 0x1c
-	sw	k0, 0(k1)
+	li	t0, SYS_SCRATCH0
+	li	t1, SYS_SCRATCH1
+	sw	sp, 0(t0)
+	la	k0, resume_from_sleep
+	sw	k0, 0(t1)
+
+/* Flush DCACHE to make sure context is in memory
+*/
+	la 	t1, __flush_cache_all   /* _flush_cache_all is a function ptr */
+	lw 	t0,0(t1)
+	jal	t0
+	nop
 
 /* Put SDRAM into self refresh.  Preload instructions into cache,
  * issue a precharge, then auto refresh, then sleep commands to it.
@@ -87,30 +133,74 @@
  	cache	0x14, 96(t0)
 	.set	mips0
 
+	/* Put SDRAM to sleep */
 sdsleep:
-	lui 	k0, 0xb400
-	sw	zero, 0x001c(k0)	/* Precharge */
-	sw	zero, 0x0020(k0)	/* Auto refresh */
-	sw	zero, 0x0030(k0)	/* SDRAM sleep */
+	li 	a0, MEM_PHYS_ADDR
+	or 	a0, a0, 0xA0000000
+#if defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1100) || defined(CONFIG_SOC_AU1500)
+	lw 	k0, MEM_SDMODE0(a0)
+	sw	zero, MEM_SDPRECMD(a0) 	/* Precharge */
+	sw	zero, MEM_SDAUTOREF(a0)	/* Auto Refresh */
+	sw	zero, MEM_SDSLEEP(a0)  	/* Sleep */
 	sync
-
-	lui 	k1, 0xb190
-	sw	zero, 0x0078(k1)	/* get ready  to sleep */
+#endif
+#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
+	sw	zero, MEM_SDPRECMD(a0) 	/* Precharge */
+	sw 	zero, MEM_SDSREF(a0)
+	
+	#lw 	t0, MEM_SDSTAT(a0)
+	#and	t0, t0, 0x01000000
+	li 	t0, 0x01000000
+refresh_not_set:
+	lw 	t1, MEM_SDSTAT(a0)
+	and	t2, t1, t0
+	beq	zero, t2, refresh_not_set
+	nop
+
+	li	t0, ~0x30000000
+	lw 	t1, MEM_SDCONFIGA(a0)
+	and	t1, t0, t1
+	sw 	t1, MEM_SDCONFIGA(a0)
 	sync
-	sw	zero, 0x007c(k1)	/* Put processor to sleep */
+#endif
+
+	li	t0, SYS_SLEEP
+	sw	zero, 0(t0)	/* Put processor to sleep */
 	sync
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
 
 	/* This is where we return upon wakeup.
 	 * Reload all of the registers and return.
 	 */
-1:	nop
-	lw	k0, 0x20(sp)
+resume_from_sleep:
+	nop
+	.set nomacro
+	.set noat
+
+#if 0
+        /* Infinite loop to allow JTAG attach before sleep mode (debug only)
+         */
+2:      li      t1, 0
+        beq     t1, zero, 2b
+        nop
+#endif
+
+	/* Restore CPU registers
+	 */
+	lw	k0, PT_C0STATUS(sp) // 0x20
 	mtc0	k0, CP0_STATUS
-	lw	k0, 0x1c(sp)
+	lw	k0, PT_CONTEXT(sp) // 0x1c
 	mtc0	k0, CP0_CONTEXT
-	lw	k0, 0x18(sp)
+	lw	k0, PT_PAGEMASK(sp) // 0x18
 	mtc0	k0, CP0_PAGEMASK
-	lw	k0, 0x14(sp)
+	lw	k0, PT_CONFIG(sp) // 0x14
 	mtc0	k0, CP0_CONFIG
 	lw	$1, PT_R1(sp)
 	lw	$2, PT_R2(sp)
@@ -119,14 +209,6 @@
 	lw	$5, PT_R5(sp)
 	lw	$6, PT_R6(sp)
 	lw	$7, PT_R7(sp)
-	lw	$8, PT_R8(sp)
-	lw	$9, PT_R9(sp)
-	lw	$10, PT_R10(sp)
-	lw	$11, PT_R11(sp)
-	lw	$12, PT_R12(sp)
-	lw	$13, PT_R13(sp)
-	lw	$14, PT_R14(sp)
-	lw	$15, PT_R15(sp)
 	lw	$16, PT_R16(sp)
 	lw	$17, PT_R17(sp)
 	lw	$18, PT_R18(sp)
@@ -135,15 +217,37 @@
 	lw	$21, PT_R21(sp)
 	lw	$22, PT_R22(sp)
 	lw	$23, PT_R23(sp)
-	lw	$24, PT_R24(sp)
-	lw	$25, PT_R25(sp)
-	lw	$26, PT_R26(sp)
-	lw	$27, PT_R27(sp)
 	lw	$28, PT_R28(sp)
-	lw	$29, PT_R29(sp)
 	lw	$30, PT_R30(sp)
 	lw	$31, PT_R31(sp)
+
+	.set macro
+	.set at
+
+	/* Clear the wake source, but save it as the return value of the
+           function */
+	li	t0, SYS_WAKESRC
+	lw	v0, 0(t0)
+	sw	v0, PT_R2(sp)
+	sw	zero, 0(t0)
+
 	addiu	sp, PT_SIZE
 
+	lw gp, save_and_sleep_frmsz-44(sp)
+	lw s8, save_and_sleep_frmsz-40(sp)
+	lw s7, save_and_sleep_frmsz-36(sp)
+	lw s6, save_and_sleep_frmsz-32(sp)
+	lw s5, save_and_sleep_frmsz-28(sp)
+	lw s4, save_and_sleep_frmsz-24(sp)
+	lw s3, save_and_sleep_frmsz-20(sp)
+	lw s2, save_and_sleep_frmsz-16(sp)
+	lw s1, save_and_sleep_frmsz-12(sp)
+	lw s0, save_and_sleep_frmsz-8(sp)
+	lw ra, save_and_sleep_frmsz-4(sp)
+
+	addu sp, save_and_sleep_frmsz
 	jr	ra
+	nop
+	.set reorder
 END(save_and_sleep)
+

[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux