⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lite5200_sleep.s

📁 linux内核源码
💻 S
字号:
#include <asm/reg.h>#include <asm/ppc_asm.h>#include <asm/processor.h>#include <asm/cache.h>#define SDRAM_CTRL	0x104#define SC_MODE_EN	(1<<31)#define SC_CKE		(1<<30)#define SC_REF_EN	(1<<28)#define SC_SOFT_PRE	(1<<1)#define GPIOW_GPIOE	0xc00#define GPIOW_DDR	0xc08#define GPIOW_DVO	0xc0c#define CDM_CE		0x214#define CDM_SDRAM	(1<<3)/* helpers... beware: r10 and r4 are overwritten */#define SAVE_SPRN(reg, addr)		\	mfspr	r10, SPRN_##reg;	\	stw	r10, ((addr)*4)(r4);#define LOAD_SPRN(reg, addr)		\	lwz	r10, ((addr)*4)(r4);	\	mtspr	SPRN_##reg, r10;	\	sync;				\	isync;	.dataregisters:	.space 0x5c*4	.text/* ---------------------------------------------------------------------- *//* low-power mode with help of M68HLC908QT1 */	.globl lite5200_low_powerlite5200_low_power:	mr	r7, r3	/* save SRAM va */	mr	r8, r4	/* save MBAR va */	/* setup wakeup address for u-boot at physical location 0x0 */	lis	r3, CONFIG_KERNEL_START@h	lis	r4, lite5200_wakeup@h	ori	r4, r4, lite5200_wakeup@l	sub	r4, r4, r3	stw	r4, 0(r3)	/*	 * save stuff BDI overwrites	 * 0xf0 (0xe0->0x100 gets overwritten when BDI connected;	 *   even when CONFIG_BDI* is disabled and MMU XLAT commented; heisenbug?))	 * WARNING: self-refresh doesn't seem to work when BDI2000 is connected,	 *   possibly because BDI sets SDRAM registers before wakeup code does	 */	lis	r4, registers@h	ori	r4, r4, registers@l	lwz	r10, 0xf0(r3)	stw	r10, (0x1d*4)(r4)	/* save registers to r4 [destroys r10] */	SAVE_SPRN(LR, 0x1c)	bl	save_regs	/* flush caches [destroys r3, r4] */	bl	flush_data_cache	/* copy code to sram */	mr	r4, r7	li	r3, (sram_code_end - sram_code)/4	mtctr	r3	lis	r3, sram_code@h	ori	r3, r3, sram_code@l1:	lwz	r5, 0(r3)	stw	r5, 0(r4)	addi	r3, r3, 4	addi	r4, r4, 4	bdnz	1b	/* get tb_ticks_per_usec */	lis	r3, tb_ticks_per_usec@h	lwz	r11, tb_ticks_per_usec@l(r3)	/* disable I and D caches */	mfspr	r3, SPRN_HID0	ori	r3, r3, HID0_ICE | HID0_DCE	xori	r3, r3, HID0_ICE | HID0_DCE	sync; isync;	mtspr	SPRN_HID0, r3	sync; isync;	/* jump to sram */	mtlr	r7	blrl	/* doesn't return */sram_code:	/* self refresh */	lwz	r4, SDRAM_CTRL(r8)	/* send NOP (precharge) */	oris	r4, r4, SC_MODE_EN@h	/* mode_en */	stw	r4, SDRAM_CTRL(r8)	sync	ori	r4, r4, SC_SOFT_PRE	/* soft_pre */	stw	r4, SDRAM_CTRL(r8)	sync	xori	r4, r4, SC_SOFT_PRE	xoris	r4, r4, SC_MODE_EN@h	/* !mode_en */	stw	r4, SDRAM_CTRL(r8)	sync	/* delay (for NOP to finish) */	li	r12, 1	bl	udelay	/*	 * mode_en must not be set when enabling self-refresh	 * send AR with CKE low (self-refresh)	 */	oris	r4, r4, (SC_REF_EN | SC_CKE)@h	xoris	r4, r4, (SC_CKE)@h	/* ref_en !cke */	stw	r4, SDRAM_CTRL(r8)	sync	/* delay (after !CKE there should be two cycles) */	li	r12, 1	bl	udelay	/* disable clock */	lwz	r4, CDM_CE(r8)	ori	r4, r4, CDM_SDRAM	xori	r4, r4, CDM_SDRAM	stw	r4, CDM_CE(r8)	sync	/* delay a bit */	li	r12, 1	bl	udelay	/* turn off with QT chip */	li	r4, 0x02	stb	r4, GPIOW_GPIOE(r8)	/* enable gpio_wkup1 */	sync	stb	r4, GPIOW_DVO(r8)	/* "output" high */	sync	stb	r4, GPIOW_DDR(r8)	/* output */	sync	stb	r4, GPIOW_DVO(r8)	/* output high */	sync	/* 10uS delay */	li	r12, 10	bl	udelay	/* turn off */	li	r4, 0	stb	r4, GPIOW_DVO(r8)	/* output low */	sync	/* wait until we're offline */  1:	b	1b	/* local udelay in sram is needed */  udelay: /* r11 - tb_ticks_per_usec, r12 - usecs, overwrites r13 */	mullw	r12, r12, r11	mftb	r13	/* start */	addi	r12, r13, r12 /* end */    1:	mftb	r13	/* current */	cmp	cr0, r13, r12	blt	1b	blrsram_code_end:/* uboot jumps here on resume */lite5200_wakeup:	bl	restore_regs	/* HIDs, MSR */	LOAD_SPRN(HID1, 0x19)	LOAD_SPRN(HID2, 0x1a)	/* address translation is tricky (see turn_on_mmu) */	mfmsr	r10	ori	r10, r10, MSR_DR | MSR_IR	mtspr	SPRN_SRR1, r10	lis	r10, mmu_on@h	ori	r10, r10, mmu_on@l	mtspr	SPRN_SRR0, r10	sync	rfimmu_on:	/* kernel offset (r4 is still set from restore_registers) */	addis	r4, r4, CONFIG_KERNEL_START@h	/* restore MSR */	lwz	r10, (4*0x1b)(r4)	mtmsr	r10	sync; isync;	/* invalidate caches */	mfspr	r10, SPRN_HID0	ori	r5, r10, HID0_ICFI | HID0_DCI	mtspr	SPRN_HID0, r5	/* invalidate caches */	sync; isync;	mtspr	SPRN_HID0, r10	sync; isync;	/* enable caches */	lwz	r10, (4*0x18)(r4)	mtspr	SPRN_HID0, r10	/* restore (enable caches, DPM) */	/* ^ this has to be after address translation set in MSR */	sync	isync	/* restore 0xf0 (BDI2000) */	lis	r3, CONFIG_KERNEL_START@h	lwz	r10, (0x1d*4)(r4)	stw	r10, 0xf0(r3)	LOAD_SPRN(LR, 0x1c)	blr/* ---------------------------------------------------------------------- *//* boring code: helpers *//* save registers */#define SAVE_BAT(n, addr)		\	SAVE_SPRN(DBAT##n##L, addr);	\	SAVE_SPRN(DBAT##n##U, addr+1);	\	SAVE_SPRN(IBAT##n##L, addr+2);	\	SAVE_SPRN(IBAT##n##U, addr+3);#define SAVE_SR(n, addr)		\	mfsr	r10, n;			\	stw	r10, ((addr)*4)(r4);#define SAVE_4SR(n, addr)	\	SAVE_SR(n, addr);	\	SAVE_SR(n+1, addr+1);	\	SAVE_SR(n+2, addr+2);	\	SAVE_SR(n+3, addr+3);save_regs:	stw	r0, 0(r4)	stw	r1, 0x4(r4)	stw	r2, 0x8(r4)	stmw	r11, 0xc(r4) /* 0xc -> 0x5f, (0x18*4-1) */	SAVE_SPRN(HID0, 0x18)	SAVE_SPRN(HID1, 0x19)	SAVE_SPRN(HID2, 0x1a)	mfmsr	r10	stw	r10, (4*0x1b)(r4)	/*SAVE_SPRN(LR, 0x1c) have to save it before the call */	/* 0x1d reserved by 0xf0 */	SAVE_SPRN(RPA,   0x1e)	SAVE_SPRN(SDR1,  0x1f)	/* save MMU regs */	SAVE_BAT(0, 0x20)	SAVE_BAT(1, 0x24)	SAVE_BAT(2, 0x28)	SAVE_BAT(3, 0x2c)	SAVE_BAT(4, 0x30)	SAVE_BAT(5, 0x34)	SAVE_BAT(6, 0x38)	SAVE_BAT(7, 0x3c)	SAVE_4SR(0, 0x40)	SAVE_4SR(4, 0x44)	SAVE_4SR(8, 0x48)	SAVE_4SR(12, 0x4c)	SAVE_SPRN(SPRG0, 0x50)	SAVE_SPRN(SPRG1, 0x51)	SAVE_SPRN(SPRG2, 0x52)	SAVE_SPRN(SPRG3, 0x53)	SAVE_SPRN(SPRG4, 0x54)	SAVE_SPRN(SPRG5, 0x55)	SAVE_SPRN(SPRG6, 0x56)	SAVE_SPRN(SPRG7, 0x57)	SAVE_SPRN(IABR,  0x58)	SAVE_SPRN(DABR,  0x59)	SAVE_SPRN(TBRL,  0x5a)	SAVE_SPRN(TBRU,  0x5b)	blr/* restore registers */#define LOAD_BAT(n, addr)		\	LOAD_SPRN(DBAT##n##L, addr);	\	LOAD_SPRN(DBAT##n##U, addr+1);	\	LOAD_SPRN(IBAT##n##L, addr+2);	\	LOAD_SPRN(IBAT##n##U, addr+3);#define LOAD_SR(n, addr)		\	lwz	r10, ((addr)*4)(r4);	\	mtsr	n, r10;#define LOAD_4SR(n, addr)	\	LOAD_SR(n, addr);	\	LOAD_SR(n+1, addr+1);	\	LOAD_SR(n+2, addr+2);	\	LOAD_SR(n+3, addr+3);restore_regs:	lis	r4, registers@h	ori	r4, r4, registers@l	/* MMU is not up yet */	subis	r4, r4, CONFIG_KERNEL_START@h	lwz	r0, 0(r4)	lwz	r1, 0x4(r4)	lwz	r2, 0x8(r4)	lmw	r11, 0xc(r4)	/*	 * these are a bit tricky	 *	 * 0x18 - HID0	 * 0x19 - HID1	 * 0x1a - HID2	 * 0x1b - MSR	 * 0x1c - LR	 * 0x1d - reserved by 0xf0 (BDI2000)	 */	LOAD_SPRN(RPA,   0x1e);	LOAD_SPRN(SDR1,  0x1f);	/* restore MMU regs */	LOAD_BAT(0, 0x20)	LOAD_BAT(1, 0x24)	LOAD_BAT(2, 0x28)	LOAD_BAT(3, 0x2c)	LOAD_BAT(4, 0x30)	LOAD_BAT(5, 0x34)	LOAD_BAT(6, 0x38)	LOAD_BAT(7, 0x3c)	LOAD_4SR(0, 0x40)	LOAD_4SR(4, 0x44)	LOAD_4SR(8, 0x48)	LOAD_4SR(12, 0x4c)	/* rest of regs */	LOAD_SPRN(SPRG0, 0x50);	LOAD_SPRN(SPRG1, 0x51);	LOAD_SPRN(SPRG2, 0x52);	LOAD_SPRN(SPRG3, 0x53);	LOAD_SPRN(SPRG4, 0x54);	LOAD_SPRN(SPRG5, 0x55);	LOAD_SPRN(SPRG6, 0x56);	LOAD_SPRN(SPRG7, 0x57);	LOAD_SPRN(IABR,  0x58);	LOAD_SPRN(DABR,  0x59);	LOAD_SPRN(TBWL,  0x5a);	/* these two have separate R/W regs */	LOAD_SPRN(TBWU,  0x5b);	blr/* cache flushing code. copied from arch/ppc/boot/util.S */#define NUM_CACHE_LINES (128*8)/* * Flush data cache * Do this by just reading lots of stuff into the cache. */flush_data_cache:	lis	r3,CONFIG_KERNEL_START@h	ori	r3,r3,CONFIG_KERNEL_START@l	li	r4,NUM_CACHE_LINES	mtctr	r41:	lwz	r4,0(r3)	addi	r3,r3,L1_CACHE_BYTES	/* Next line, please */	bdnz	1b	blr

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -