247 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			247 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| /*
 | |
|  * arch/sh/kernel/cpu/sh4a/sleep-sh_mobile.S
 | |
|  *
 | |
|  * Sleep mode and Standby modes support for SuperH Mobile
 | |
|  *
 | |
|  *  Copyright (C) 2009 Magnus Damm
 | |
|  *
 | |
|  * This file is subject to the terms and conditions of the GNU General Public
 | |
|  * License.  See the file "COPYING" in the main directory of this archive
 | |
|  * for more details.
 | |
|  */
 | |
| 
 | |
| #include <linux/sys.h>
 | |
| #include <linux/errno.h>
 | |
| #include <linux/linkage.h>
 | |
| #include <asm/asm-offsets.h>
 | |
| #include <asm/suspend.h>
 | |
| 
 | |
| /*
 | |
|  * Kernel mode register usage, see entry.S:
 | |
|  *	k0	scratch
 | |
|  *	k1	scratch
 | |
|  *	k4	scratch
 | |
|  */
 | |
| #define k0	r0
 | |
| #define k1	r1
 | |
| #define k4	r4
 | |
| 
 | |
| /* manage self-refresh and enter standby mode.
 | |
|  * this code will be copied to on-chip memory and executed from there.
 | |
|  */
 | |
| 
 | |
| 	.balign 	4096,0,4096
 | |
| ENTRY(sh_mobile_standby)
 | |
| 
 | |
| 	/* save original vbr */
 | |
| 	stc	vbr, r1
 | |
| 	mova	saved_vbr, r0
 | |
| 	mov.l	r1, @r0
 | |
| 
 | |
| 	/* point vbr to our on-chip memory page */
 | |
| 	ldc	r5, vbr
 | |
| 
 | |
| 	/* save return address */
 | |
| 	mova	saved_spc, r0
 | |
| 	sts	pr, r5
 | |
| 	mov.l	r5, @r0
 | |
| 
 | |
| 	/* save sr */
 | |
| 	mova	saved_sr, r0
 | |
| 	stc	sr, r5
 | |
| 	mov.l	r5, @r0
 | |
| 
 | |
| 	/* save mode flags */
 | |
| 	mova	saved_mode, r0
 | |
| 	mov.l	r4, @r0
 | |
| 
 | |
| 	/* put mode flags in r0 */
 | |
| 	mov	r4, r0
 | |
| 
 | |
| 	tst	#SUSP_SH_SF, r0
 | |
| 	bt	skip_set_sf
 | |
| #ifdef CONFIG_CPU_SUBTYPE_SH7724
 | |
| 	/* DBSC: put memory in self-refresh mode */
 | |
| 	mov.l	dben_reg, r4
 | |
| 	mov.l	dben_data0, r1
 | |
| 	mov.l	r1, @r4
 | |
| 
 | |
| 	mov.l	dbrfpdn0_reg, r4
 | |
| 	mov.l	dbrfpdn0_data0, r1
 | |
| 	mov.l	r1, @r4
 | |
| 
 | |
| 	mov.l	dbcmdcnt_reg, r4
 | |
| 	mov.l	dbcmdcnt_data0, r1
 | |
| 	mov.l	r1, @r4
 | |
| 
 | |
| 	mov.l	dbcmdcnt_reg, r4
 | |
| 	mov.l	dbcmdcnt_data1, r1
 | |
| 	mov.l	r1, @r4
 | |
| 
 | |
| 	mov.l	dbrfpdn0_reg, r4
 | |
| 	mov.l	dbrfpdn0_data1, r1
 | |
| 	mov.l	r1, @r4
 | |
| #else
 | |
| 	/* SBSC: disable power down and put in self-refresh mode */
 | |
| 	mov.l	1f, r4
 | |
| 	mov.l	2f, r1
 | |
| 	mov.l	@r4, r2
 | |
| 	or	r1, r2
 | |
| 	mov.l   3f, r3
 | |
| 	and	r3, r2
 | |
| 	mov.l	r2, @r4
 | |
| #endif
 | |
| 
 | |
| skip_set_sf:
 | |
| 	tst	#SUSP_SH_STANDBY, r0
 | |
| 	bt	test_rstandby
 | |
| 
 | |
| 	/* set mode to "software standby mode" */
 | |
| 	bra	do_sleep
 | |
| 	 mov	#0x80, r1
 | |
| 
 | |
| test_rstandby:
 | |
| 	tst	#SUSP_SH_RSTANDBY, r0
 | |
| 	bt	test_ustandby
 | |
| 
 | |
| 	/* set mode to "r-standby mode" */
 | |
| 	bra	do_sleep
 | |
| 	 mov	#0x20, r1
 | |
| 
 | |
| test_ustandby:
 | |
| 	tst	#SUSP_SH_USTANDBY, r0
 | |
| 	bt	force_sleep
 | |
| 
 | |
| 	/* set mode to "u-standby mode" */
 | |
| 	bra	do_sleep
 | |
| 	 mov	#0x10, r1
 | |
| 
 | |
| force_sleep:
 | |
| 
 | |
| 	/* set mode to "sleep mode" */
 | |
| 	mov	#0x00, r1
 | |
| 
 | |
| do_sleep:
 | |
| 	/* setup and enter selected standby mode */
 | |
| 	mov.l	5f, r4
 | |
| 	mov.l	r1, @r4
 | |
| again:
 | |
| 	sleep
 | |
| 	bra	again
 | |
| 	 nop
 | |
| 
 | |
| restore_jump_vbr:
 | |
| 	/* setup spc with return address to c code */
 | |
| 	mov.l	saved_spc, k0
 | |
| 	ldc	k0, spc
 | |
| 
 | |
| 	/* restore vbr */
 | |
| 	mov.l	saved_vbr, k0
 | |
| 	ldc	k0, vbr
 | |
| 
 | |
| 	/* setup ssr with saved sr */
 | |
| 	mov.l	saved_sr, k0
 | |
| 	ldc	k0, ssr
 | |
| 
 | |
| 	/* get mode flags */
 | |
| 	mov.l	saved_mode, k0
 | |
| 
 | |
| done_sleep:
 | |
| 	/* reset standby mode to sleep mode */
 | |
| 	mov.l	5f, k4
 | |
| 	mov	#0x00, k1
 | |
| 	mov.l	k1, @k4
 | |
| 
 | |
| 	tst	#SUSP_SH_SF, k0
 | |
| 	bt	skip_restore_sf
 | |
| 
 | |
| #ifdef CONFIG_CPU_SUBTYPE_SH7724
 | |
| 	/* DBSC: put memory in auto-refresh mode */
 | |
| 	mov.l	dbrfpdn0_reg, k4
 | |
| 	mov.l	dbrfpdn0_data0, k1
 | |
| 	mov.l	k1, @k4
 | |
| 
 | |
| 	nop /* sleep 140 ns */
 | |
| 	nop
 | |
| 	nop
 | |
| 	nop
 | |
| 
 | |
| 	mov.l	dbcmdcnt_reg, k4
 | |
| 	mov.l	dbcmdcnt_data0, k1
 | |
| 	mov.l	k1, @k4
 | |
| 
 | |
| 	mov.l	dbcmdcnt_reg, k4
 | |
| 	mov.l	dbcmdcnt_data1, k1
 | |
| 	mov.l	k1, @k4
 | |
| 
 | |
| 	mov.l	dben_reg, k4
 | |
| 	mov.l	dben_data1, k1
 | |
| 	mov.l	k1, @k4
 | |
| 
 | |
| 	mov.l	dbrfpdn0_reg, k4
 | |
| 	mov.l	dbrfpdn0_data2, k1
 | |
| 	mov.l	k1, @k4
 | |
| #else
 | |
| 	/* SBSC: set auto-refresh mode */
 | |
| 	mov.l	1f, k4
 | |
| 	mov.l	@k4, k0
 | |
| 	mov.l   4f, k1
 | |
| 	and	k1, k0
 | |
| 	mov.l	k0, @k4
 | |
| 	mov.l	6f, k4
 | |
| 	mov.l	8f, k0
 | |
| 	mov.l	@k4, k1
 | |
| 	mov	#-1, k4
 | |
| 	add	k4, k1
 | |
| 	or	k1, k0
 | |
| 	mov.l	7f, k1
 | |
| 	mov.l	k0, @k1
 | |
| #endif
 | |
| skip_restore_sf:
 | |
| 	/* jump to vbr vector */
 | |
| 	mov.l	saved_vbr, k0
 | |
| 	mov.l	offset_vbr, k4
 | |
| 	add	k4, k0
 | |
| 	jmp	@k0
 | |
| 	 nop
 | |
| 
 | |
| 	.balign 4
 | |
| saved_mode:	.long	0
 | |
| saved_spc:	.long	0
 | |
| saved_sr:	.long	0
 | |
| saved_vbr:	.long	0
 | |
| offset_vbr:	.long	0x600
 | |
| #ifdef CONFIG_CPU_SUBTYPE_SH7724
 | |
| dben_reg:	.long	0xfd000010 /* DBEN */
 | |
| dben_data0:	.long	0
 | |
| dben_data1:	.long	1
 | |
| dbrfpdn0_reg:	.long	0xfd000040 /* DBRFPDN0 */
 | |
| dbrfpdn0_data0:	.long	0
 | |
| dbrfpdn0_data1:	.long	1
 | |
| dbrfpdn0_data2:	.long	0x00010000
 | |
| dbcmdcnt_reg:	.long	0xfd000014 /* DBCMDCNT */
 | |
| dbcmdcnt_data0:	.long	2
 | |
| dbcmdcnt_data1:	.long	4
 | |
| #else
 | |
| 1:	.long	0xfe400008 /* SDCR0 */
 | |
| 2:	.long	0x00000400
 | |
| 3:	.long	0xffff7fff
 | |
| 4:	.long	0xfffffbff
 | |
| #endif
 | |
| 5:	.long	0xa4150020 /* STBCR */
 | |
| 6:	.long   0xfe40001c /* RTCOR */
 | |
| 7:	.long   0xfe400018 /* RTCNT */
 | |
| 8:	.long   0xa55a0000
 | |
| 
 | |
| 
 | |
| /* interrupt vector @ 0x600 */
 | |
| 	.balign 	0x400,0,0x400
 | |
| 	.long	0xdeadbeef
 | |
| 	.balign 	0x200,0,0x200
 | |
| 	bra	restore_jump_vbr
 | |
| 	 nop
 | |
| sh_mobile_standby_end:
 | |
| 
 | |
| ENTRY(sh_mobile_standby_size)
 | |
| 	.long sh_mobile_standby_end - sh_mobile_standby
 |