1 /* SPDX-License-Identifier: GPL-2.0 */
2 #include <linux/linkage.h>
5 #include <asm/ppc_asm.h>
6 #include <asm/processor.h>
10 #define SDRAM_CTRL 0x104
11 #define SC_MODE_EN (1<<31)
12 #define SC_CKE (1<<30)
13 #define SC_REF_EN (1<<28)
14 #define SC_SOFT_PRE (1<<1)
16 #define GPIOW_GPIOE 0xc00
17 #define GPIOW_DDR 0xc08
18 #define GPIOW_DVO 0xc0c
21 #define CDM_SDRAM (1<<3)
24 /* helpers... beware: r10 and r4 are overwritten */
25 #define SAVE_SPRN(reg, addr) \
26 mfspr r10, SPRN_##reg; \
27 stw r10, ((addr)*4)(r4);
29 #define LOAD_SPRN(reg, addr) \
30 lwz r10, ((addr)*4)(r4); \
31 mtspr SPRN_##reg, r10; \
41 /* ---------------------------------------------------------------------- */
42 /* low-power mode with help of M68HLC908QT1 */
44 .globl lite5200_low_power
47 mr r7, r3 /* save SRAM va */
48 mr r8, r4 /* save MBAR va */
50 /* setup wakeup address for u-boot at physical location 0x0 */
51 lis r3, CONFIG_KERNEL_START@h
52 lis r4, lite5200_wakeup@h
53 ori r4, r4, lite5200_wakeup@l
59 * save stuff BDI overwrites
60 * 0xf0 (0xe0->0x100 gets overwritten when BDI connected;
61 * even when CONFIG_BDI_SWITCH is disabled and MMU XLAT commented; heisenbug?))
62 * WARNING: self-refresh doesn't seem to work when BDI2000 is connected,
63 * possibly because BDI sets SDRAM registers before wakeup code does
66 ori r4, r4, registers@l
70 /* save registers to r4 [destroys r10] */
74 /* flush caches [destroys r3, r4] */
78 /* copy code to sram */
80 li r3, (sram_code_end - sram_code)/4
83 ori r3, r3, sram_code@l
91 /* get tb_ticks_per_usec */
92 lis r3, tb_ticks_per_usec@h
93 lwz r11, tb_ticks_per_usec@l(r3)
95 /* disable I and D caches */
97 ori r3, r3, HID0_ICE | HID0_DCE
98 xori r3, r3, HID0_ICE | HID0_DCE
111 lwz r4, SDRAM_CTRL(r8)
113 /* send NOP (precharge) */
114 oris r4, r4, SC_MODE_EN@h /* mode_en */
115 stw r4, SDRAM_CTRL(r8)
118 ori r4, r4, SC_SOFT_PRE /* soft_pre */
119 stw r4, SDRAM_CTRL(r8)
121 xori r4, r4, SC_SOFT_PRE
123 xoris r4, r4, SC_MODE_EN@h /* !mode_en */
124 stw r4, SDRAM_CTRL(r8)
127 /* delay (for NOP to finish) */
132 * mode_en must not be set when enabling self-refresh
133 * send AR with CKE low (self-refresh)
135 oris r4, r4, (SC_REF_EN | SC_CKE)@h
136 xoris r4, r4, (SC_CKE)@h /* ref_en !cke */
137 stw r4, SDRAM_CTRL(r8)
140 /* delay (after !CKE there should be two cycles) */
146 ori r4, r4, CDM_SDRAM
147 xori r4, r4, CDM_SDRAM
156 /* turn off with QT chip */
158 stb r4, GPIOW_GPIOE(r8) /* enable gpio_wkup1 */
161 stb r4, GPIOW_DVO(r8) /* "output" high */
163 stb r4, GPIOW_DDR(r8) /* output */
165 stb r4, GPIOW_DVO(r8) /* output high */
174 stb r4, GPIOW_DVO(r8) /* output low */
177 /* wait until we're offline */
182 /* local udelay in sram is needed */
183 SYM_FUNC_START_LOCAL(udelay)
184 /* r11 - tb_ticks_per_usec, r12 - usecs, overwrites r13 */
187 add r12, r13, r12 /* end */
189 mftb r13 /* current */
199 /* uboot jumps here on resume */
205 LOAD_SPRN(HID1, 0x19)
206 /* FIXME: Should this use HID2_G2_LE? */
207 LOAD_SPRN(HID2_750FX, 0x1a)
210 /* address translation is tricky (see turn_on_mmu) */
212 ori r10, r10, MSR_DR | MSR_IR
217 ori r10, r10, mmu_on@l
222 /* kernel offset (r4 is still set from restore_registers) */
223 addis r4, r4, CONFIG_KERNEL_START@h
227 lwz r10, (4*0x1b)(r4)
231 /* invalidate caches */
233 ori r5, r10, HID0_ICFI | HID0_DCI
234 mtspr SPRN_HID0, r5 /* invalidate caches */
240 lwz r10, (4*0x18)(r4)
241 mtspr SPRN_HID0, r10 /* restore (enable caches, DPM) */
242 /* ^ this has to be after address translation set in MSR */
247 /* restore 0xf0 (BDI2000) */
248 lis r3, CONFIG_KERNEL_START@h
249 lwz r10, (0x1d*4)(r4)
256 _ASM_NOKPROBE_SYMBOL(lite5200_wakeup)
259 /* ---------------------------------------------------------------------- */
260 /* boring code: helpers */
263 #define SAVE_BAT(n, addr) \
264 SAVE_SPRN(DBAT##n##L, addr); \
265 SAVE_SPRN(DBAT##n##U, addr+1); \
266 SAVE_SPRN(IBAT##n##L, addr+2); \
267 SAVE_SPRN(IBAT##n##U, addr+3);
269 #define SAVE_SR(n, addr) \
271 stw r10, ((addr)*4)(r4);
273 #define SAVE_4SR(n, addr) \
275 SAVE_SR(n+1, addr+1); \
276 SAVE_SR(n+2, addr+2); \
277 SAVE_SR(n+3, addr+3);
279 SYM_FUNC_START_LOCAL(save_regs)
283 stmw r11, 0xc(r4) /* 0xc -> 0x5f, (0x18*4-1) */
285 SAVE_SPRN(HID0, 0x18)
286 SAVE_SPRN(HID1, 0x19)
287 /* FIXME: Should this use HID2_G2_LE? */
288 SAVE_SPRN(HID2_750FX, 0x1a)
290 stw r10, (4*0x1b)(r4)
291 /*SAVE_SPRN(LR, 0x1c) have to save it before the call */
292 /* 0x1d reserved by 0xf0 */
294 SAVE_SPRN(SDR1, 0x1f)
311 SAVE_SPRN(SPRG0, 0x50)
312 SAVE_SPRN(SPRG1, 0x51)
313 SAVE_SPRN(SPRG2, 0x52)
314 SAVE_SPRN(SPRG3, 0x53)
315 SAVE_SPRN(SPRG4, 0x54)
316 SAVE_SPRN(SPRG5, 0x55)
317 SAVE_SPRN(SPRG6, 0x56)
318 SAVE_SPRN(SPRG7, 0x57)
320 SAVE_SPRN(IABR, 0x58)
321 SAVE_SPRN(DABR, 0x59)
322 SAVE_SPRN(TBRL, 0x5a)
323 SAVE_SPRN(TBRU, 0x5b)
326 SYM_FUNC_END(save_regs)
329 /* restore registers */
330 #define LOAD_BAT(n, addr) \
331 LOAD_SPRN(DBAT##n##L, addr); \
332 LOAD_SPRN(DBAT##n##U, addr+1); \
333 LOAD_SPRN(IBAT##n##L, addr+2); \
334 LOAD_SPRN(IBAT##n##U, addr+3);
336 #define LOAD_SR(n, addr) \
337 lwz r10, ((addr)*4)(r4); \
340 #define LOAD_4SR(n, addr) \
342 LOAD_SR(n+1, addr+1); \
343 LOAD_SR(n+2, addr+2); \
344 LOAD_SR(n+3, addr+3);
346 SYM_FUNC_START_LOCAL(restore_regs)
348 ori r4, r4, registers@l
350 /* MMU is not up yet */
351 subis r4, r4, CONFIG_KERNEL_START@h
359 * these are a bit tricky
366 * 0x1d - reserved by 0xf0 (BDI2000)
368 LOAD_SPRN(RPA, 0x1e);
369 LOAD_SPRN(SDR1, 0x1f);
371 /* restore MMU regs */
387 LOAD_SPRN(SPRG0, 0x50);
388 LOAD_SPRN(SPRG1, 0x51);
389 LOAD_SPRN(SPRG2, 0x52);
390 LOAD_SPRN(SPRG3, 0x53);
391 LOAD_SPRN(SPRG4, 0x54);
392 LOAD_SPRN(SPRG5, 0x55);
393 LOAD_SPRN(SPRG6, 0x56);
394 LOAD_SPRN(SPRG7, 0x57);
396 LOAD_SPRN(IABR, 0x58);
397 LOAD_SPRN(DABR, 0x59);
398 LOAD_SPRN(TBWL, 0x5a); /* these two have separate R/W regs */
399 LOAD_SPRN(TBWU, 0x5b);
402 _ASM_NOKPROBE_SYMBOL(restore_regs)
403 SYM_FUNC_END(restore_regs)
407 /* cache flushing code. copied from arch/ppc/boot/util.S */
408 #define NUM_CACHE_LINES (128*8)
412 * Do this by just reading lots of stuff into the cache.
414 SYM_FUNC_START_LOCAL(flush_data_cache)
415 lis r3,CONFIG_KERNEL_START@h
416 ori r3,r3,CONFIG_KERNEL_START@l
417 li r4,NUM_CACHE_LINES
421 addi r3,r3,L1_CACHE_BYTES /* Next line, please */
424 SYM_FUNC_END(flush_data_cache)