aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorManuel Lauss <mano@roarinelk.homelinux.net>2008-12-21 03:26:25 -0500
committerRalf Baechle <ralf@linux-mips.org>2009-01-11 04:57:27 -0500
commit564365b0fc3395ed55501ef25705664888cebdbc (patch)
treeed2228df7ea13585f014937b4fc0a6cd7138a674 /arch
parent2699cdfb765c3b7d77d28ea3bc7d84e486697177 (diff)
MIPS: Alchemy: Fix up PM code on Au1550/Au1200
Au1550/Au1200 have a different memory controller which requires additi- onal code to properly put memory to sleep (code taken from AMD/RMI's Linux-2.6.11 source package). Also fix up the remaining pm-related paths to compile on Au1200/Au1550 platforms. Signed-off-by: Manuel Lauss <mano@roarinelk.homelinux.net> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/alchemy/common/power.c266
-rw-r--r--arch/mips/alchemy/common/reset.c2
-rw-r--r--arch/mips/alchemy/common/sleeper.S118
-rw-r--r--arch/mips/include/asm/mach-au1x00/au1000.h6
4 files changed, 225 insertions, 167 deletions
diff --git a/arch/mips/alchemy/common/power.c b/arch/mips/alchemy/common/power.c
index 997dd56bcc5e..f08312b10d04 100644
--- a/arch/mips/alchemy/common/power.c
+++ b/arch/mips/alchemy/common/power.c
@@ -35,7 +35,6 @@
35#include <linux/jiffies.h> 35#include <linux/jiffies.h>
36 36
37#include <asm/uaccess.h> 37#include <asm/uaccess.h>
38#include <asm/cacheflush.h>
39#include <asm/mach-au1x00/au1000.h> 38#include <asm/mach-au1x00/au1000.h>
40 39
41#ifdef CONFIG_PM 40#ifdef CONFIG_PM
@@ -47,8 +46,6 @@
47#define DPRINTK(fmt, args...) 46#define DPRINTK(fmt, args...)
48#endif 47#endif
49 48
50static void au1000_calibrate_delay(void);
51
52extern unsigned long save_local_and_disable(int controller); 49extern unsigned long save_local_and_disable(int controller);
53extern void restore_local_and_enable(int controller, unsigned long mask); 50extern void restore_local_and_enable(int controller, unsigned long mask);
54 51
@@ -64,17 +61,15 @@ static DEFINE_SPINLOCK(pm_lock);
64 * We only have to save/restore registers that aren't otherwise 61 * We only have to save/restore registers that aren't otherwise
65 * done as part of a driver pm_* function. 62 * done as part of a driver pm_* function.
66 */ 63 */
67static unsigned int sleep_aux_pll_cntrl; 64static unsigned int sleep_uart0_inten;
68static unsigned int sleep_cpu_pll_cntrl; 65static unsigned int sleep_uart0_fifoctl;
69static unsigned int sleep_pin_function; 66static unsigned int sleep_uart0_linectl;
70static unsigned int sleep_uart0_inten; 67static unsigned int sleep_uart0_clkdiv;
71static unsigned int sleep_uart0_fifoctl; 68static unsigned int sleep_uart0_enable;
72static unsigned int sleep_uart0_linectl; 69static unsigned int sleep_usb[2];
73static unsigned int sleep_uart0_clkdiv; 70static unsigned int sleep_sys_clocks[5];
74static unsigned int sleep_uart0_enable; 71static unsigned int sleep_sys_pinfunc;
75static unsigned int sleep_usbhost_enable; 72static unsigned int sleep_static_memctlr[4][3];
76static unsigned int sleep_usbdev_enable;
77static unsigned int sleep_static_memctlr[4][3];
78 73
79/* 74/*
80 * Define this to cause the value you write to /proc/sys/pm/sleep to 75 * Define this to cause the value you write to /proc/sys/pm/sleep to
@@ -108,31 +103,45 @@ static void save_core_regs(void)
108 sleep_uart0_linectl = au_readl(UART0_ADDR + UART_LCR); 103 sleep_uart0_linectl = au_readl(UART0_ADDR + UART_LCR);
109 sleep_uart0_clkdiv = au_readl(UART0_ADDR + UART_CLK); 104 sleep_uart0_clkdiv = au_readl(UART0_ADDR + UART_CLK);
110 sleep_uart0_enable = au_readl(UART0_ADDR + UART_MOD_CNTRL); 105 sleep_uart0_enable = au_readl(UART0_ADDR + UART_MOD_CNTRL);
106 au_sync();
111 107
108#ifndef CONFIG_SOC_AU1200
112 /* Shutdown USB host/device. */ 109 /* Shutdown USB host/device. */
113 sleep_usbhost_enable = au_readl(USB_HOST_CONFIG); 110 sleep_usb[0] = au_readl(USB_HOST_CONFIG);
114 111
115 /* There appears to be some undocumented reset register.... */ 112 /* There appears to be some undocumented reset register.... */
116 au_writel(0, 0xb0100004); au_sync(); 113 au_writel(0, 0xb0100004);
117 au_writel(0, USB_HOST_CONFIG); au_sync(); 114 au_sync();
115 au_writel(0, USB_HOST_CONFIG);
116 au_sync();
117
118 sleep_usb[1] = au_readl(USBD_ENABLE);
119 au_writel(0, USBD_ENABLE);
120 au_sync();
121
122#else /* AU1200 */
118 123
119 sleep_usbdev_enable = au_readl(USBD_ENABLE); 124 /* enable access to OTG mmio so we can save OTG CAP/MUX.
120 au_writel(0, USBD_ENABLE); au_sync(); 125 * FIXME: write an OTG driver and move this stuff there!
126 */
127 au_writel(au_readl(USB_MSR_BASE + 4) | (1 << 6), USB_MSR_BASE + 4);
128 au_sync();
129 sleep_usb[0] = au_readl(0xb4020020); /* OTG_CAP */
130 sleep_usb[1] = au_readl(0xb4020024); /* OTG_MUX */
131#endif
121 132
122 /* Save interrupt controller state. */ 133 /* Save interrupt controller state. */
123 save_au1xxx_intctl(); 134 save_au1xxx_intctl();
124 135
125 /* Clocks and PLLs. */ 136 /* Clocks and PLLs. */
126 sleep_aux_pll_cntrl = au_readl(SYS_AUXPLL); 137 sleep_sys_clocks[0] = au_readl(SYS_FREQCTRL0);
138 sleep_sys_clocks[1] = au_readl(SYS_FREQCTRL1);
139 sleep_sys_clocks[2] = au_readl(SYS_CLKSRC);
140 sleep_sys_clocks[3] = au_readl(SYS_CPUPLL);
141 sleep_sys_clocks[4] = au_readl(SYS_AUXPLL);
127 142
128 /* 143 /* pin mux config */
129 * We don't really need to do this one, but unless we 144 sleep_sys_pinfunc = au_readl(SYS_PINFUNC);
130 * write it again it won't have a valid value if we
131 * happen to read it.
132 */
133 sleep_cpu_pll_cntrl = au_readl(SYS_CPUPLL);
134
135 sleep_pin_function = au_readl(SYS_PINFUNC);
136 145
137 /* Save the static memory controller configuration. */ 146 /* Save the static memory controller configuration. */
138 sleep_static_memctlr[0][0] = au_readl(MEM_STCFG0); 147 sleep_static_memctlr[0][0] = au_readl(MEM_STCFG0);
@@ -151,12 +160,37 @@ static void save_core_regs(void)
151 160
152static void restore_core_regs(void) 161static void restore_core_regs(void)
153{ 162{
154 extern void restore_au1xxx_intctl(void); 163 /* restore clock configuration. Writing CPUPLL last will
155 extern void wakeup_counter0_adjust(void); 164 * stall a bit and stabilize other clocks (unless this is
165 * one of those Au1000 with a write-only PLL, where we dont
166 * have a valid value)
167 */
168 au_writel(sleep_sys_clocks[0], SYS_FREQCTRL0);
169 au_writel(sleep_sys_clocks[1], SYS_FREQCTRL1);
170 au_writel(sleep_sys_clocks[2], SYS_CLKSRC);
171 au_writel(sleep_sys_clocks[4], SYS_AUXPLL);
172 if (!au1xxx_cpu_has_pll_wo())
173 au_writel(sleep_sys_clocks[3], SYS_CPUPLL);
174 au_sync();
175
176 au_writel(sleep_sys_pinfunc, SYS_PINFUNC);
177 au_sync();
178
179#ifndef CONFIG_SOC_AU1200
180 au_writel(sleep_usb[0], USB_HOST_CONFIG);
181 au_writel(sleep_usb[1], USBD_ENABLE);
182 au_sync();
183#else
184 /* enable accces to OTG memory */
185 au_writel(au_readl(USB_MSR_BASE + 4) | (1 << 6), USB_MSR_BASE + 4);
186 au_sync();
156 187
157 au_writel(sleep_aux_pll_cntrl, SYS_AUXPLL); au_sync(); 188 /* restore OTG caps and port mux. */
158 au_writel(sleep_cpu_pll_cntrl, SYS_CPUPLL); au_sync(); 189 au_writel(sleep_usb[0], 0xb4020020 + 0); /* OTG_CAP */
159 au_writel(sleep_pin_function, SYS_PINFUNC); au_sync(); 190 au_sync();
191 au_writel(sleep_usb[1], 0xb4020020 + 4); /* OTG_MUX */
192 au_sync();
193#endif
160 194
161 /* Restore the static memory controller configuration. */ 195 /* Restore the static memory controller configuration. */
162 au_writel(sleep_static_memctlr[0][0], MEM_STCFG0); 196 au_writel(sleep_static_memctlr[0][0], MEM_STCFG0);
@@ -196,16 +230,45 @@ void wakeup_from_suspend(void)
196 suspend_mode = 0; 230 suspend_mode = 0;
197} 231}
198 232
199int au_sleep(void) 233void au_sleep(void)
234{
235 save_core_regs();
236 au1xxx_save_and_sleep();
237 restore_core_regs();
238}
239
240static int pm_do_sleep(ctl_table *ctl, int write, struct file *file,
241 void __user *buffer, size_t *len, loff_t *ppos)
200{ 242{
201 unsigned long wakeup, flags; 243 unsigned long wakeup, flags;
202 extern void save_and_sleep(void); 244 int ret;
245#ifdef SLEEP_TEST_TIMEOUT
246#define TMPBUFLEN2 16
247 char buf[TMPBUFLEN2], *p;
248#endif
203 249
204 spin_lock_irqsave(&pm_lock, flags); 250 spin_lock_irqsave(&pm_lock, flags);
205 251
206 save_core_regs(); 252 if (!write) {
253 *len = 0;
254 ret = 0;
255 goto out_unlock;
256 };
207 257
208 flush_cache_all(); 258#ifdef SLEEP_TEST_TIMEOUT
259 if (*len > TMPBUFLEN2 - 1) {
260 ret = -EFAULT;
261 goto out_unlock;
262 }
263 if (copy_from_user(buf, buffer, *len)) {
264 return -EFAULT;
265 goto out_unlock;
266 }
267 buf[*len] = 0;
268 p = buf;
269 sleep_ticks = simple_strtoul(p, &p, 0);
270 wakeup_counter0_set(sleep_ticks);
271#endif
209 272
210 /** 273 /**
211 ** The code below is all system dependent and we should probably 274 ** The code below is all system dependent and we should probably
@@ -223,9 +286,6 @@ int au_sleep(void)
223 wakeup |= 1 << 6; /* turn on GPIO 6 wakeup */ 286 wakeup |= 1 << 6; /* turn on GPIO 6 wakeup */
224#else 287#else
225 /* For testing, allow match20 to wake us up. */ 288 /* For testing, allow match20 to wake us up. */
226#ifdef SLEEP_TEST_TIMEOUT
227 wakeup_counter0_set(sleep_ticks);
228#endif
229 wakeup = 1 << 8; /* turn on match20 wakeup */ 289 wakeup = 1 << 8; /* turn on match20 wakeup */
230 wakeup = 0; 290 wakeup = 0;
231#endif 291#endif
@@ -234,41 +294,62 @@ int au_sleep(void)
234 au_writel(wakeup, SYS_WAKEMSK); 294 au_writel(wakeup, SYS_WAKEMSK);
235 au_sync(); 295 au_sync();
236 296
237 save_and_sleep(); 297 au_sleep();
298 ret = 0;
238 299
239 /* 300out_unlock:
240 * After a wakeup, the cpu vectors back to 0x1fc00000, so
241 * it's up to the boot code to get us back here.
242 */
243 restore_core_regs();
244 spin_unlock_irqrestore(&pm_lock, flags); 301 spin_unlock_irqrestore(&pm_lock, flags);
245 return 0; 302 return ret;
246} 303}
247 304
248static int pm_do_sleep(ctl_table *ctl, int write, struct file *file, 305#if !defined(CONFIG_SOC_AU1200) && !defined(CONFIG_SOC_AU1550)
249 void __user *buffer, size_t *len, loff_t *ppos) 306
307/*
308 * This is right out of init/main.c
309 */
310
311/*
312 * This is the number of bits of precision for the loops_per_jiffy.
313 * Each bit takes on average 1.5/HZ seconds. This (like the original)
314 * is a little better than 1%.
315 */
316#define LPS_PREC 8
317
318static void au1000_calibrate_delay(void)
250{ 319{
251#ifdef SLEEP_TEST_TIMEOUT 320 unsigned long ticks, loopbit;
252#define TMPBUFLEN2 16 321 int lps_precision = LPS_PREC;
253 char buf[TMPBUFLEN2], *p;
254#endif
255 322
256 if (!write) 323 loops_per_jiffy = 1 << 12;
257 *len = 0;
258 else {
259#ifdef SLEEP_TEST_TIMEOUT
260 if (*len > TMPBUFLEN2 - 1)
261 return -EFAULT;
262 if (copy_from_user(buf, buffer, *len))
263 return -EFAULT;
264 buf[*len] = 0;
265 p = buf;
266 sleep_ticks = simple_strtoul(p, &p, 0);
267#endif
268 324
269 au_sleep(); 325 while (loops_per_jiffy <<= 1) {
326 /* Wait for "start of" clock tick */
327 ticks = jiffies;
328 while (ticks == jiffies)
329 /* nothing */ ;
330 /* Go ... */
331 ticks = jiffies;
332 __delay(loops_per_jiffy);
333 ticks = jiffies - ticks;
334 if (ticks)
335 break;
336 }
337
338 /*
339 * Do a binary approximation to get loops_per_jiffy set to be equal
340 * one clock (up to lps_precision bits)
341 */
342 loops_per_jiffy >>= 1;
343 loopbit = loops_per_jiffy;
344 while (lps_precision-- && (loopbit >>= 1)) {
345 loops_per_jiffy |= loopbit;
346 ticks = jiffies;
347 while (ticks == jiffies);
348 ticks = jiffies;
349 __delay(loops_per_jiffy);
350 if (jiffies != ticks) /* longer than 1 tick */
351 loops_per_jiffy &= ~loopbit;
270 } 352 }
271 return 0;
272} 353}
273 354
274static int pm_do_freq(ctl_table *ctl, int write, struct file *file, 355static int pm_do_freq(ctl_table *ctl, int write, struct file *file,
@@ -377,7 +458,7 @@ static int pm_do_freq(ctl_table *ctl, int write, struct file *file,
377 458
378 return retval; 459 return retval;
379} 460}
380 461#endif
381 462
382static struct ctl_table pm_table[] = { 463static struct ctl_table pm_table[] = {
383 { 464 {
@@ -388,6 +469,7 @@ static struct ctl_table pm_table[] = {
388 .mode = 0600, 469 .mode = 0600,
389 .proc_handler = &pm_do_sleep 470 .proc_handler = &pm_do_sleep
390 }, 471 },
472#if !defined(CONFIG_SOC_AU1200) && !defined(CONFIG_SOC_AU1550)
391 { 473 {
392 .ctl_name = CTL_UNNUMBERED, 474 .ctl_name = CTL_UNNUMBERED,
393 .procname = "freq", 475 .procname = "freq",
@@ -396,6 +478,7 @@ static struct ctl_table pm_table[] = {
396 .mode = 0600, 478 .mode = 0600,
397 .proc_handler = &pm_do_freq 479 .proc_handler = &pm_do_freq
398 }, 480 },
481#endif
399 {} 482 {}
400}; 483};
401 484
@@ -429,51 +512,4 @@ static int __init pm_init(void)
429 512
430__initcall(pm_init); 513__initcall(pm_init);
431 514
432/*
433 * This is right out of init/main.c
434 */
435
436/*
437 * This is the number of bits of precision for the loops_per_jiffy.
438 * Each bit takes on average 1.5/HZ seconds. This (like the original)
439 * is a little better than 1%.
440 */
441#define LPS_PREC 8
442
443static void au1000_calibrate_delay(void)
444{
445 unsigned long ticks, loopbit;
446 int lps_precision = LPS_PREC;
447
448 loops_per_jiffy = 1 << 12;
449
450 while (loops_per_jiffy <<= 1) {
451 /* Wait for "start of" clock tick */
452 ticks = jiffies;
453 while (ticks == jiffies)
454 /* nothing */ ;
455 /* Go ... */
456 ticks = jiffies;
457 __delay(loops_per_jiffy);
458 ticks = jiffies - ticks;
459 if (ticks)
460 break;
461 }
462
463 /*
464 * Do a binary approximation to get loops_per_jiffy set to be equal
465 * one clock (up to lps_precision bits)
466 */
467 loops_per_jiffy >>= 1;
468 loopbit = loops_per_jiffy;
469 while (lps_precision-- && (loopbit >>= 1)) {
470 loops_per_jiffy |= loopbit;
471 ticks = jiffies;
472 while (ticks == jiffies);
473 ticks = jiffies;
474 __delay(loops_per_jiffy);
475 if (jiffies != ticks) /* longer than 1 tick */
476 loops_per_jiffy &= ~loopbit;
477 }
478}
479#endif /* CONFIG_PM */ 515#endif /* CONFIG_PM */
diff --git a/arch/mips/alchemy/common/reset.c b/arch/mips/alchemy/common/reset.c
index d555429c8d6f..0191c936cb5e 100644
--- a/arch/mips/alchemy/common/reset.c
+++ b/arch/mips/alchemy/common/reset.c
@@ -31,8 +31,6 @@
31 31
32#include <asm/mach-au1x00/au1000.h> 32#include <asm/mach-au1x00/au1000.h>
33 33
34extern int au_sleep(void);
35
36void au1000_restart(char *command) 34void au1000_restart(char *command)
37{ 35{
38 /* Set all integrated peripherals to disabled states */ 36 /* Set all integrated peripherals to disabled states */
diff --git a/arch/mips/alchemy/common/sleeper.S b/arch/mips/alchemy/common/sleeper.S
index 3006e270c8bc..4f4b16741d12 100644
--- a/arch/mips/alchemy/common/sleeper.S
+++ b/arch/mips/alchemy/common/sleeper.S
@@ -15,16 +15,17 @@
15#include <asm/regdef.h> 15#include <asm/regdef.h>
16#include <asm/stackframe.h> 16#include <asm/stackframe.h>
17 17
18 .extern __flush_cache_all
19
18 .text 20 .text
19 .set macro 21 .set noreorder
20 .set noat 22 .set noat
21 .align 5 23 .align 5
22 24
23/* Save all of the processor general registers and go to sleep. 25/* Save all of the processor general registers and go to sleep.
24 * A wakeup condition will get us back here to restore the registers. 26 * A wakeup condition will get us back here to restore the registers.
25 */ 27 */
26LEAF(save_and_sleep) 28LEAF(au1xxx_save_and_sleep)
27
28 subu sp, PT_SIZE 29 subu sp, PT_SIZE
29 sw $1, PT_R1(sp) 30 sw $1, PT_R1(sp)
30 sw $2, PT_R2(sp) 31 sw $2, PT_R2(sp)
@@ -33,14 +34,6 @@ LEAF(save_and_sleep)
33 sw $5, PT_R5(sp) 34 sw $5, PT_R5(sp)
34 sw $6, PT_R6(sp) 35 sw $6, PT_R6(sp)
35 sw $7, PT_R7(sp) 36 sw $7, PT_R7(sp)
36 sw $8, PT_R8(sp)
37 sw $9, PT_R9(sp)
38 sw $10, PT_R10(sp)
39 sw $11, PT_R11(sp)
40 sw $12, PT_R12(sp)
41 sw $13, PT_R13(sp)
42 sw $14, PT_R14(sp)
43 sw $15, PT_R15(sp)
44 sw $16, PT_R16(sp) 37 sw $16, PT_R16(sp)
45 sw $17, PT_R17(sp) 38 sw $17, PT_R17(sp)
46 sw $18, PT_R18(sp) 39 sw $18, PT_R18(sp)
@@ -49,12 +42,9 @@ LEAF(save_and_sleep)
49 sw $21, PT_R21(sp) 42 sw $21, PT_R21(sp)
50 sw $22, PT_R22(sp) 43 sw $22, PT_R22(sp)
51 sw $23, PT_R23(sp) 44 sw $23, PT_R23(sp)
52 sw $24, PT_R24(sp)
53 sw $25, PT_R25(sp)
54 sw $26, PT_R26(sp) 45 sw $26, PT_R26(sp)
55 sw $27, PT_R27(sp) 46 sw $27, PT_R27(sp)
56 sw $28, PT_R28(sp) 47 sw $28, PT_R28(sp)
57 sw $29, PT_R29(sp)
58 sw $30, PT_R30(sp) 48 sw $30, PT_R30(sp)
59 sw $31, PT_R31(sp) 49 sw $31, PT_R31(sp)
60 mfc0 k0, CP0_STATUS 50 mfc0 k0, CP0_STATUS
@@ -66,20 +56,26 @@ LEAF(save_and_sleep)
66 mfc0 k0, CP0_CONFIG 56 mfc0 k0, CP0_CONFIG
67 sw k0, 0x14(sp) 57 sw k0, 0x14(sp)
68 58
59 /* flush caches to make sure context is in memory */
60 la t1, __flush_cache_all
61 lw t0, 0(t1)
62 jalr t0
63 nop
64
69 /* Now set up the scratch registers so the boot rom will 65 /* Now set up the scratch registers so the boot rom will
70 * return to this point upon wakeup. 66 * return to this point upon wakeup.
67 * sys_scratch0 : SP
68 * sys_scratch1 : RA
71 */ 69 */
72 la k0, 1f 70 lui t3, 0xb190 /* sys_xxx */
73 lui k1, 0xb190 71 sw sp, 0x0018(t3)
74 ori k1, 0x18 72 la k0, 3f /* resume path */
75 sw sp, 0(k1) 73 sw k0, 0x001c(t3)
76 ori k1, 0x1c
77 sw k0, 0(k1)
78 74
79/* Put SDRAM into self refresh. Preload instructions into cache, 75 /* Put SDRAM into self refresh: Preload instructions into cache,
80 * issue a precharge, then auto refresh, then sleep commands to it. 76 * issue a precharge, auto/self refresh, then sleep commands to it.
81 */ 77 */
82 la t0, sdsleep 78 la t0, 1f
83 .set mips3 79 .set mips3
84 cache 0x14, 0(t0) 80 cache 0x14, 0(t0)
85 cache 0x14, 32(t0) 81 cache 0x14, 32(t0)
@@ -87,24 +83,57 @@ LEAF(save_and_sleep)
87 cache 0x14, 96(t0) 83 cache 0x14, 96(t0)
88 .set mips0 84 .set mips0
89 85
90sdsleep: 861: lui a0, 0xb400 /* mem_xxx */
91 lui k0, 0xb400 87#if defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1100) || \
92 sw zero, 0x001c(k0) /* Precharge */ 88 defined(CONFIG_SOC_AU1500)
93 sw zero, 0x0020(k0) /* Auto refresh */ 89 sw zero, 0x001c(a0) /* Precharge */
94 sw zero, 0x0030(k0) /* SDRAM sleep */ 90 sync
91 sw zero, 0x0020(a0) /* Auto Refresh */
92 sync
93 sw zero, 0x0030(a0) /* Sleep */
94 sync
95#endif
96
97#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
98 sw zero, 0x08c0(a0) /* Precharge */
95 sync 99 sync
100 sw zero, 0x08d0(a0) /* Self Refresh */
101 sync
102
103 /* wait for sdram to enter self-refresh mode */
104 lui t0, 0x0100
1052: lw t1, 0x0850(a0) /* mem_sdstat */
106 and t2, t1, t0
107 beq t2, zero, 2b
108 nop
96 109
97 lui k1, 0xb190 110 /* disable SDRAM clocks */
98 sw zero, 0x0078(k1) /* get ready to sleep */ 111 lui t0, 0xcfff
112 ori t0, t0, 0xffff
113 lw t1, 0x0840(a0) /* mem_sdconfiga */
114 and t1, t0, t1 /* clear CE[1:0] */
115 sw t1, 0x0840(a0) /* mem_sdconfiga */
99 sync 116 sync
100 sw zero, 0x007c(k1) /* Put processor to sleep */ 117#endif
118
119 /* put power supply and processor to sleep */
120 sw zero, 0x0078(t3) /* sys_slppwr */
121 sync
122 sw zero, 0x007c(t3) /* sys_sleep */
101 sync 123 sync
124 nop
125 nop
126 nop
127 nop
128 nop
129 nop
130 nop
131 nop
102 132
103 /* This is where we return upon wakeup. 133 /* This is where we return upon wakeup.
104 * Reload all of the registers and return. 134 * Reload all of the registers and return.
105 */ 135 */
1061: nop 1363: lw k0, 0x20(sp)
107 lw k0, 0x20(sp)
108 mtc0 k0, CP0_STATUS 137 mtc0 k0, CP0_STATUS
109 lw k0, 0x1c(sp) 138 lw k0, 0x1c(sp)
110 mtc0 k0, CP0_CONTEXT 139 mtc0 k0, CP0_CONTEXT
@@ -113,10 +142,11 @@ sdsleep:
113 lw k0, 0x14(sp) 142 lw k0, 0x14(sp)
114 mtc0 k0, CP0_CONFIG 143 mtc0 k0, CP0_CONFIG
115 144
116 /* We need to catch the ealry Alchemy SOCs with 145 /* We need to catch the early Alchemy SOCs with
117 * the write-only Config[OD] bit and set it back to one... 146 * the write-only Config[OD] bit and set it back to one...
118 */ 147 */
119 jal au1x00_fixup_config_od 148 jal au1x00_fixup_config_od
149 nop
120 lw $1, PT_R1(sp) 150 lw $1, PT_R1(sp)
121 lw $2, PT_R2(sp) 151 lw $2, PT_R2(sp)
122 lw $3, PT_R3(sp) 152 lw $3, PT_R3(sp)
@@ -124,14 +154,6 @@ sdsleep:
124 lw $5, PT_R5(sp) 154 lw $5, PT_R5(sp)
125 lw $6, PT_R6(sp) 155 lw $6, PT_R6(sp)
126 lw $7, PT_R7(sp) 156 lw $7, PT_R7(sp)
127 lw $8, PT_R8(sp)
128 lw $9, PT_R9(sp)
129 lw $10, PT_R10(sp)
130 lw $11, PT_R11(sp)
131 lw $12, PT_R12(sp)
132 lw $13, PT_R13(sp)
133 lw $14, PT_R14(sp)
134 lw $15, PT_R15(sp)
135 lw $16, PT_R16(sp) 157 lw $16, PT_R16(sp)
136 lw $17, PT_R17(sp) 158 lw $17, PT_R17(sp)
137 lw $18, PT_R18(sp) 159 lw $18, PT_R18(sp)
@@ -140,15 +162,11 @@ sdsleep:
140 lw $21, PT_R21(sp) 162 lw $21, PT_R21(sp)
141 lw $22, PT_R22(sp) 163 lw $22, PT_R22(sp)
142 lw $23, PT_R23(sp) 164 lw $23, PT_R23(sp)
143 lw $24, PT_R24(sp)
144 lw $25, PT_R25(sp)
145 lw $26, PT_R26(sp) 165 lw $26, PT_R26(sp)
146 lw $27, PT_R27(sp) 166 lw $27, PT_R27(sp)
147 lw $28, PT_R28(sp) 167 lw $28, PT_R28(sp)
148 lw $29, PT_R29(sp)
149 lw $30, PT_R30(sp) 168 lw $30, PT_R30(sp)
150 lw $31, PT_R31(sp) 169 lw $31, PT_R31(sp)
151 addiu sp, PT_SIZE
152
153 jr ra 170 jr ra
154END(save_and_sleep) 171 addiu sp, PT_SIZE
172END(au1xxx_save_and_sleep)
diff --git a/arch/mips/include/asm/mach-au1x00/au1000.h b/arch/mips/include/asm/mach-au1x00/au1000.h
index 2b88c2982cb0..515373c6d4a1 100644
--- a/arch/mips/include/asm/mach-au1x00/au1000.h
+++ b/arch/mips/include/asm/mach-au1x00/au1000.h
@@ -137,6 +137,12 @@ extern void set_au1x00_uart_baud_base(unsigned long new_baud_base);
137extern unsigned long get_au1x00_uart_baud_base(void); 137extern unsigned long get_au1x00_uart_baud_base(void);
138extern unsigned long au1xxx_calc_clock(void); 138extern unsigned long au1xxx_calc_clock(void);
139 139
140/* PM: arch/mips/alchemy/common/sleeper.S, power.c, irq.c */
141void au1xxx_save_and_sleep(void);
142void au_sleep(void);
143void save_au1xxx_intctl(void);
144void restore_au1xxx_intctl(void);
145
140/* 146/*
141 * Every board describes its IRQ mapping with this table. 147 * Every board describes its IRQ mapping with this table.
142 */ 148 */