18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#include <asm/reg.h>
38c2ecf20Sopenharmony_ci#include <asm/ppc_asm.h>
48c2ecf20Sopenharmony_ci#include <asm/processor.h>
58c2ecf20Sopenharmony_ci#include <asm/cache.h>
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#define SDRAM_CTRL	0x104
98c2ecf20Sopenharmony_ci#define SC_MODE_EN	(1<<31)
108c2ecf20Sopenharmony_ci#define SC_CKE		(1<<30)
118c2ecf20Sopenharmony_ci#define SC_REF_EN	(1<<28)
128c2ecf20Sopenharmony_ci#define SC_SOFT_PRE	(1<<1)
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#define GPIOW_GPIOE	0xc00
158c2ecf20Sopenharmony_ci#define GPIOW_DDR	0xc08
168c2ecf20Sopenharmony_ci#define GPIOW_DVO	0xc0c
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#define CDM_CE		0x214
198c2ecf20Sopenharmony_ci#define CDM_SDRAM	(1<<3)
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci/* helpers... beware: r10 and r4 are overwritten */
238c2ecf20Sopenharmony_ci#define SAVE_SPRN(reg, addr)		\
248c2ecf20Sopenharmony_ci	mfspr	r10, SPRN_##reg;	\
258c2ecf20Sopenharmony_ci	stw	r10, ((addr)*4)(r4);
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci#define LOAD_SPRN(reg, addr)		\
288c2ecf20Sopenharmony_ci	lwz	r10, ((addr)*4)(r4);	\
298c2ecf20Sopenharmony_ci	mtspr	SPRN_##reg, r10;	\
308c2ecf20Sopenharmony_ci	sync;				\
318c2ecf20Sopenharmony_ci	isync;
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci	.data
358c2ecf20Sopenharmony_ciregisters:
368c2ecf20Sopenharmony_ci	.space 0x5c*4
378c2ecf20Sopenharmony_ci	.text
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci/* ---------------------------------------------------------------------- */
408c2ecf20Sopenharmony_ci/* low-power mode with help of M68HLC908QT1 */
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	.globl lite5200_low_power
438c2ecf20Sopenharmony_cilite5200_low_power:
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	mr	r7, r3	/* save SRAM va */
468c2ecf20Sopenharmony_ci	mr	r8, r4	/* save MBAR va */
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	/* setup wakeup address for u-boot at physical location 0x0 */
498c2ecf20Sopenharmony_ci	lis	r3, CONFIG_KERNEL_START@h
508c2ecf20Sopenharmony_ci	lis	r4, lite5200_wakeup@h
518c2ecf20Sopenharmony_ci	ori	r4, r4, lite5200_wakeup@l
528c2ecf20Sopenharmony_ci	sub	r4, r4, r3
538c2ecf20Sopenharmony_ci	stw	r4, 0(r3)
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	/*
578c2ecf20Sopenharmony_ci	 * save stuff BDI overwrites
588c2ecf20Sopenharmony_ci	 * 0xf0 (0xe0->0x100 gets overwritten when BDI connected;
598c2ecf20Sopenharmony_ci	 *   even when CONFIG_BDI_SWITCH is disabled and MMU XLAT commented; heisenbug?))
608c2ecf20Sopenharmony_ci	 * WARNING: self-refresh doesn't seem to work when BDI2000 is connected,
618c2ecf20Sopenharmony_ci	 *   possibly because BDI sets SDRAM registers before wakeup code does
628c2ecf20Sopenharmony_ci	 */
638c2ecf20Sopenharmony_ci	lis	r4, registers@h
648c2ecf20Sopenharmony_ci	ori	r4, r4, registers@l
658c2ecf20Sopenharmony_ci	lwz	r10, 0xf0(r3)
668c2ecf20Sopenharmony_ci	stw	r10, (0x1d*4)(r4)
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci	/* save registers to r4 [destroys r10] */
698c2ecf20Sopenharmony_ci	SAVE_SPRN(LR, 0x1c)
708c2ecf20Sopenharmony_ci	bl	save_regs
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	/* flush caches [destroys r3, r4] */
738c2ecf20Sopenharmony_ci	bl	flush_data_cache
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	/* copy code to sram */
778c2ecf20Sopenharmony_ci	mr	r4, r7
788c2ecf20Sopenharmony_ci	li	r3, (sram_code_end - sram_code)/4
798c2ecf20Sopenharmony_ci	mtctr	r3
808c2ecf20Sopenharmony_ci	lis	r3, sram_code@h
818c2ecf20Sopenharmony_ci	ori	r3, r3, sram_code@l
828c2ecf20Sopenharmony_ci1:
838c2ecf20Sopenharmony_ci	lwz	r5, 0(r3)
848c2ecf20Sopenharmony_ci	stw	r5, 0(r4)
858c2ecf20Sopenharmony_ci	addi	r3, r3, 4
868c2ecf20Sopenharmony_ci	addi	r4, r4, 4
878c2ecf20Sopenharmony_ci	bdnz	1b
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	/* get tb_ticks_per_usec */
908c2ecf20Sopenharmony_ci	lis	r3, tb_ticks_per_usec@h
918c2ecf20Sopenharmony_ci	lwz	r11, tb_ticks_per_usec@l(r3)
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	/* disable I and D caches */
948c2ecf20Sopenharmony_ci	mfspr	r3, SPRN_HID0
958c2ecf20Sopenharmony_ci	ori	r3, r3, HID0_ICE | HID0_DCE
968c2ecf20Sopenharmony_ci	xori	r3, r3, HID0_ICE | HID0_DCE
978c2ecf20Sopenharmony_ci	sync; isync;
988c2ecf20Sopenharmony_ci	mtspr	SPRN_HID0, r3
998c2ecf20Sopenharmony_ci	sync; isync;
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	/* jump to sram */
1028c2ecf20Sopenharmony_ci	mtlr	r7
1038c2ecf20Sopenharmony_ci	blrl
1048c2ecf20Sopenharmony_ci	/* doesn't return */
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_cisram_code:
1088c2ecf20Sopenharmony_ci	/* self refresh */
1098c2ecf20Sopenharmony_ci	lwz	r4, SDRAM_CTRL(r8)
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	/* send NOP (precharge) */
1128c2ecf20Sopenharmony_ci	oris	r4, r4, SC_MODE_EN@h	/* mode_en */
1138c2ecf20Sopenharmony_ci	stw	r4, SDRAM_CTRL(r8)
1148c2ecf20Sopenharmony_ci	sync
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	ori	r4, r4, SC_SOFT_PRE	/* soft_pre */
1178c2ecf20Sopenharmony_ci	stw	r4, SDRAM_CTRL(r8)
1188c2ecf20Sopenharmony_ci	sync
1198c2ecf20Sopenharmony_ci	xori	r4, r4, SC_SOFT_PRE
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	xoris	r4, r4, SC_MODE_EN@h	/* !mode_en */
1228c2ecf20Sopenharmony_ci	stw	r4, SDRAM_CTRL(r8)
1238c2ecf20Sopenharmony_ci	sync
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	/* delay (for NOP to finish) */
1268c2ecf20Sopenharmony_ci	li	r12, 1
1278c2ecf20Sopenharmony_ci	bl	udelay
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci	/*
1308c2ecf20Sopenharmony_ci	 * mode_en must not be set when enabling self-refresh
1318c2ecf20Sopenharmony_ci	 * send AR with CKE low (self-refresh)
1328c2ecf20Sopenharmony_ci	 */
1338c2ecf20Sopenharmony_ci	oris	r4, r4, (SC_REF_EN | SC_CKE)@h
1348c2ecf20Sopenharmony_ci	xoris	r4, r4, (SC_CKE)@h	/* ref_en !cke */
1358c2ecf20Sopenharmony_ci	stw	r4, SDRAM_CTRL(r8)
1368c2ecf20Sopenharmony_ci	sync
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci	/* delay (after !CKE there should be two cycles) */
1398c2ecf20Sopenharmony_ci	li	r12, 1
1408c2ecf20Sopenharmony_ci	bl	udelay
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	/* disable clock */
1438c2ecf20Sopenharmony_ci	lwz	r4, CDM_CE(r8)
1448c2ecf20Sopenharmony_ci	ori	r4, r4, CDM_SDRAM
1458c2ecf20Sopenharmony_ci	xori	r4, r4, CDM_SDRAM
1468c2ecf20Sopenharmony_ci	stw	r4, CDM_CE(r8)
1478c2ecf20Sopenharmony_ci	sync
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	/* delay a bit */
1508c2ecf20Sopenharmony_ci	li	r12, 1
1518c2ecf20Sopenharmony_ci	bl	udelay
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	/* turn off with QT chip */
1558c2ecf20Sopenharmony_ci	li	r4, 0x02
1568c2ecf20Sopenharmony_ci	stb	r4, GPIOW_GPIOE(r8)	/* enable gpio_wkup1 */
1578c2ecf20Sopenharmony_ci	sync
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci	stb	r4, GPIOW_DVO(r8)	/* "output" high */
1608c2ecf20Sopenharmony_ci	sync
1618c2ecf20Sopenharmony_ci	stb	r4, GPIOW_DDR(r8)	/* output */
1628c2ecf20Sopenharmony_ci	sync
1638c2ecf20Sopenharmony_ci	stb	r4, GPIOW_DVO(r8)	/* output high */
1648c2ecf20Sopenharmony_ci	sync
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci	/* 10uS delay */
1678c2ecf20Sopenharmony_ci	li	r12, 10
1688c2ecf20Sopenharmony_ci	bl	udelay
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci	/* turn off */
1718c2ecf20Sopenharmony_ci	li	r4, 0
1728c2ecf20Sopenharmony_ci	stb	r4, GPIOW_DVO(r8)	/* output low */
1738c2ecf20Sopenharmony_ci	sync
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci	/* wait until we're offline */
1768c2ecf20Sopenharmony_ci  1:
1778c2ecf20Sopenharmony_ci	b	1b
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	/* local udelay in sram is needed */
1818c2ecf20Sopenharmony_ci  udelay: /* r11 - tb_ticks_per_usec, r12 - usecs, overwrites r13 */
1828c2ecf20Sopenharmony_ci	mullw	r12, r12, r11
1838c2ecf20Sopenharmony_ci	mftb	r13	/* start */
1848c2ecf20Sopenharmony_ci	add	r12, r13, r12 /* end */
1858c2ecf20Sopenharmony_ci    1:
1868c2ecf20Sopenharmony_ci	mftb	r13	/* current */
1878c2ecf20Sopenharmony_ci	cmp	cr0, r13, r12
1888c2ecf20Sopenharmony_ci	blt	1b
1898c2ecf20Sopenharmony_ci	blr
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_cisram_code_end:
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci/* uboot jumps here on resume */
1968c2ecf20Sopenharmony_cilite5200_wakeup:
1978c2ecf20Sopenharmony_ci	bl	restore_regs
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci	/* HIDs, MSR */
2018c2ecf20Sopenharmony_ci	LOAD_SPRN(HID1, 0x19)
2028c2ecf20Sopenharmony_ci	LOAD_SPRN(HID2, 0x1a)
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci	/* address translation is tricky (see turn_on_mmu) */
2068c2ecf20Sopenharmony_ci	mfmsr	r10
2078c2ecf20Sopenharmony_ci	ori	r10, r10, MSR_DR | MSR_IR
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	mtspr	SPRN_SRR1, r10
2118c2ecf20Sopenharmony_ci	lis	r10, mmu_on@h
2128c2ecf20Sopenharmony_ci	ori	r10, r10, mmu_on@l
2138c2ecf20Sopenharmony_ci	mtspr	SPRN_SRR0, r10
2148c2ecf20Sopenharmony_ci	sync
2158c2ecf20Sopenharmony_ci	rfi
2168c2ecf20Sopenharmony_cimmu_on:
2178c2ecf20Sopenharmony_ci	/* kernel offset (r4 is still set from restore_registers) */
2188c2ecf20Sopenharmony_ci	addis	r4, r4, CONFIG_KERNEL_START@h
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci	/* restore MSR */
2228c2ecf20Sopenharmony_ci	lwz	r10, (4*0x1b)(r4)
2238c2ecf20Sopenharmony_ci	mtmsr	r10
2248c2ecf20Sopenharmony_ci	sync; isync;
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	/* invalidate caches */
2278c2ecf20Sopenharmony_ci	mfspr	r10, SPRN_HID0
2288c2ecf20Sopenharmony_ci	ori	r5, r10, HID0_ICFI | HID0_DCI
2298c2ecf20Sopenharmony_ci	mtspr	SPRN_HID0, r5	/* invalidate caches */
2308c2ecf20Sopenharmony_ci	sync; isync;
2318c2ecf20Sopenharmony_ci	mtspr	SPRN_HID0, r10
2328c2ecf20Sopenharmony_ci	sync; isync;
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	/* enable caches */
2358c2ecf20Sopenharmony_ci	lwz	r10, (4*0x18)(r4)
2368c2ecf20Sopenharmony_ci	mtspr	SPRN_HID0, r10	/* restore (enable caches, DPM) */
2378c2ecf20Sopenharmony_ci	/* ^ this has to be after address translation set in MSR */
2388c2ecf20Sopenharmony_ci	sync
2398c2ecf20Sopenharmony_ci	isync
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	/* restore 0xf0 (BDI2000) */
2438c2ecf20Sopenharmony_ci	lis	r3, CONFIG_KERNEL_START@h
2448c2ecf20Sopenharmony_ci	lwz	r10, (0x1d*4)(r4)
2458c2ecf20Sopenharmony_ci	stw	r10, 0xf0(r3)
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	LOAD_SPRN(LR, 0x1c)
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	blr
2518c2ecf20Sopenharmony_ci_ASM_NOKPROBE_SYMBOL(lite5200_wakeup)
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci/* ---------------------------------------------------------------------- */
2558c2ecf20Sopenharmony_ci/* boring code: helpers */
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci/* save registers */
2588c2ecf20Sopenharmony_ci#define SAVE_BAT(n, addr)		\
2598c2ecf20Sopenharmony_ci	SAVE_SPRN(DBAT##n##L, addr);	\
2608c2ecf20Sopenharmony_ci	SAVE_SPRN(DBAT##n##U, addr+1);	\
2618c2ecf20Sopenharmony_ci	SAVE_SPRN(IBAT##n##L, addr+2);	\
2628c2ecf20Sopenharmony_ci	SAVE_SPRN(IBAT##n##U, addr+3);
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci#define SAVE_SR(n, addr)		\
2658c2ecf20Sopenharmony_ci	mfsr	r10, n;			\
2668c2ecf20Sopenharmony_ci	stw	r10, ((addr)*4)(r4);
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci#define SAVE_4SR(n, addr)	\
2698c2ecf20Sopenharmony_ci	SAVE_SR(n, addr);	\
2708c2ecf20Sopenharmony_ci	SAVE_SR(n+1, addr+1);	\
2718c2ecf20Sopenharmony_ci	SAVE_SR(n+2, addr+2);	\
2728c2ecf20Sopenharmony_ci	SAVE_SR(n+3, addr+3);
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_cisave_regs:
2758c2ecf20Sopenharmony_ci	stw	r0, 0(r4)
2768c2ecf20Sopenharmony_ci	stw	r1, 0x4(r4)
2778c2ecf20Sopenharmony_ci	stw	r2, 0x8(r4)
2788c2ecf20Sopenharmony_ci	stmw	r11, 0xc(r4) /* 0xc -> 0x5f, (0x18*4-1) */
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci	SAVE_SPRN(HID0, 0x18)
2818c2ecf20Sopenharmony_ci	SAVE_SPRN(HID1, 0x19)
2828c2ecf20Sopenharmony_ci	SAVE_SPRN(HID2, 0x1a)
2838c2ecf20Sopenharmony_ci	mfmsr	r10
2848c2ecf20Sopenharmony_ci	stw	r10, (4*0x1b)(r4)
2858c2ecf20Sopenharmony_ci	/*SAVE_SPRN(LR, 0x1c) have to save it before the call */
2868c2ecf20Sopenharmony_ci	/* 0x1d reserved by 0xf0 */
2878c2ecf20Sopenharmony_ci	SAVE_SPRN(RPA,   0x1e)
2888c2ecf20Sopenharmony_ci	SAVE_SPRN(SDR1,  0x1f)
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci	/* save MMU regs */
2918c2ecf20Sopenharmony_ci	SAVE_BAT(0, 0x20)
2928c2ecf20Sopenharmony_ci	SAVE_BAT(1, 0x24)
2938c2ecf20Sopenharmony_ci	SAVE_BAT(2, 0x28)
2948c2ecf20Sopenharmony_ci	SAVE_BAT(3, 0x2c)
2958c2ecf20Sopenharmony_ci	SAVE_BAT(4, 0x30)
2968c2ecf20Sopenharmony_ci	SAVE_BAT(5, 0x34)
2978c2ecf20Sopenharmony_ci	SAVE_BAT(6, 0x38)
2988c2ecf20Sopenharmony_ci	SAVE_BAT(7, 0x3c)
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci	SAVE_4SR(0, 0x40)
3018c2ecf20Sopenharmony_ci	SAVE_4SR(4, 0x44)
3028c2ecf20Sopenharmony_ci	SAVE_4SR(8, 0x48)
3038c2ecf20Sopenharmony_ci	SAVE_4SR(12, 0x4c)
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	SAVE_SPRN(SPRG0, 0x50)
3068c2ecf20Sopenharmony_ci	SAVE_SPRN(SPRG1, 0x51)
3078c2ecf20Sopenharmony_ci	SAVE_SPRN(SPRG2, 0x52)
3088c2ecf20Sopenharmony_ci	SAVE_SPRN(SPRG3, 0x53)
3098c2ecf20Sopenharmony_ci	SAVE_SPRN(SPRG4, 0x54)
3108c2ecf20Sopenharmony_ci	SAVE_SPRN(SPRG5, 0x55)
3118c2ecf20Sopenharmony_ci	SAVE_SPRN(SPRG6, 0x56)
3128c2ecf20Sopenharmony_ci	SAVE_SPRN(SPRG7, 0x57)
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci	SAVE_SPRN(IABR,  0x58)
3158c2ecf20Sopenharmony_ci	SAVE_SPRN(DABR,  0x59)
3168c2ecf20Sopenharmony_ci	SAVE_SPRN(TBRL,  0x5a)
3178c2ecf20Sopenharmony_ci	SAVE_SPRN(TBRU,  0x5b)
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci	blr
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci/* restore registers */
3238c2ecf20Sopenharmony_ci#define LOAD_BAT(n, addr)		\
3248c2ecf20Sopenharmony_ci	LOAD_SPRN(DBAT##n##L, addr);	\
3258c2ecf20Sopenharmony_ci	LOAD_SPRN(DBAT##n##U, addr+1);	\
3268c2ecf20Sopenharmony_ci	LOAD_SPRN(IBAT##n##L, addr+2);	\
3278c2ecf20Sopenharmony_ci	LOAD_SPRN(IBAT##n##U, addr+3);
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci#define LOAD_SR(n, addr)		\
3308c2ecf20Sopenharmony_ci	lwz	r10, ((addr)*4)(r4);	\
3318c2ecf20Sopenharmony_ci	mtsr	n, r10;
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci#define LOAD_4SR(n, addr)	\
3348c2ecf20Sopenharmony_ci	LOAD_SR(n, addr);	\
3358c2ecf20Sopenharmony_ci	LOAD_SR(n+1, addr+1);	\
3368c2ecf20Sopenharmony_ci	LOAD_SR(n+2, addr+2);	\
3378c2ecf20Sopenharmony_ci	LOAD_SR(n+3, addr+3);
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_cirestore_regs:
3408c2ecf20Sopenharmony_ci	lis	r4, registers@h
3418c2ecf20Sopenharmony_ci	ori	r4, r4, registers@l
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci	/* MMU is not up yet */
3448c2ecf20Sopenharmony_ci	subis	r4, r4, CONFIG_KERNEL_START@h
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci	lwz	r0, 0(r4)
3478c2ecf20Sopenharmony_ci	lwz	r1, 0x4(r4)
3488c2ecf20Sopenharmony_ci	lwz	r2, 0x8(r4)
3498c2ecf20Sopenharmony_ci	lmw	r11, 0xc(r4)
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	/*
3528c2ecf20Sopenharmony_ci	 * these are a bit tricky
3538c2ecf20Sopenharmony_ci	 *
3548c2ecf20Sopenharmony_ci	 * 0x18 - HID0
3558c2ecf20Sopenharmony_ci	 * 0x19 - HID1
3568c2ecf20Sopenharmony_ci	 * 0x1a - HID2
3578c2ecf20Sopenharmony_ci	 * 0x1b - MSR
3588c2ecf20Sopenharmony_ci	 * 0x1c - LR
3598c2ecf20Sopenharmony_ci	 * 0x1d - reserved by 0xf0 (BDI2000)
3608c2ecf20Sopenharmony_ci	 */
3618c2ecf20Sopenharmony_ci	LOAD_SPRN(RPA,   0x1e);
3628c2ecf20Sopenharmony_ci	LOAD_SPRN(SDR1,  0x1f);
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	/* restore MMU regs */
3658c2ecf20Sopenharmony_ci	LOAD_BAT(0, 0x20)
3668c2ecf20Sopenharmony_ci	LOAD_BAT(1, 0x24)
3678c2ecf20Sopenharmony_ci	LOAD_BAT(2, 0x28)
3688c2ecf20Sopenharmony_ci	LOAD_BAT(3, 0x2c)
3698c2ecf20Sopenharmony_ci	LOAD_BAT(4, 0x30)
3708c2ecf20Sopenharmony_ci	LOAD_BAT(5, 0x34)
3718c2ecf20Sopenharmony_ci	LOAD_BAT(6, 0x38)
3728c2ecf20Sopenharmony_ci	LOAD_BAT(7, 0x3c)
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci	LOAD_4SR(0, 0x40)
3758c2ecf20Sopenharmony_ci	LOAD_4SR(4, 0x44)
3768c2ecf20Sopenharmony_ci	LOAD_4SR(8, 0x48)
3778c2ecf20Sopenharmony_ci	LOAD_4SR(12, 0x4c)
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci	/* rest of regs */
3808c2ecf20Sopenharmony_ci	LOAD_SPRN(SPRG0, 0x50);
3818c2ecf20Sopenharmony_ci	LOAD_SPRN(SPRG1, 0x51);
3828c2ecf20Sopenharmony_ci	LOAD_SPRN(SPRG2, 0x52);
3838c2ecf20Sopenharmony_ci	LOAD_SPRN(SPRG3, 0x53);
3848c2ecf20Sopenharmony_ci	LOAD_SPRN(SPRG4, 0x54);
3858c2ecf20Sopenharmony_ci	LOAD_SPRN(SPRG5, 0x55);
3868c2ecf20Sopenharmony_ci	LOAD_SPRN(SPRG6, 0x56);
3878c2ecf20Sopenharmony_ci	LOAD_SPRN(SPRG7, 0x57);
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci	LOAD_SPRN(IABR,  0x58);
3908c2ecf20Sopenharmony_ci	LOAD_SPRN(DABR,  0x59);
3918c2ecf20Sopenharmony_ci	LOAD_SPRN(TBWL,  0x5a);	/* these two have separate R/W regs */
3928c2ecf20Sopenharmony_ci	LOAD_SPRN(TBWU,  0x5b);
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci	blr
3958c2ecf20Sopenharmony_ci_ASM_NOKPROBE_SYMBOL(restore_regs)
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci/* cache flushing code. copied from arch/ppc/boot/util.S */
4008c2ecf20Sopenharmony_ci#define NUM_CACHE_LINES (128*8)
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci/*
4038c2ecf20Sopenharmony_ci * Flush data cache
4048c2ecf20Sopenharmony_ci * Do this by just reading lots of stuff into the cache.
4058c2ecf20Sopenharmony_ci */
4068c2ecf20Sopenharmony_ciflush_data_cache:
4078c2ecf20Sopenharmony_ci	lis	r3,CONFIG_KERNEL_START@h
4088c2ecf20Sopenharmony_ci	ori	r3,r3,CONFIG_KERNEL_START@l
4098c2ecf20Sopenharmony_ci	li	r4,NUM_CACHE_LINES
4108c2ecf20Sopenharmony_ci	mtctr	r4
4118c2ecf20Sopenharmony_ci1:
4128c2ecf20Sopenharmony_ci	lwz	r4,0(r3)
4138c2ecf20Sopenharmony_ci	addi	r3,r3,L1_CACHE_BYTES	/* Next line, please */
4148c2ecf20Sopenharmony_ci	bdnz	1b
4158c2ecf20Sopenharmony_ci	blr
416