1*4882a593Smuzhiyun/* 2*4882a593Smuzhiyun * SA11x0 Assembler Sleep/WakeUp Management Routines 3*4882a593Smuzhiyun * 4*4882a593Smuzhiyun * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com> 5*4882a593Smuzhiyun * 6*4882a593Smuzhiyun * This program is free software; you can redistribute it and/or 7*4882a593Smuzhiyun * modify it under the terms of the GNU General Public License. 8*4882a593Smuzhiyun * 9*4882a593Smuzhiyun * History: 10*4882a593Smuzhiyun * 11*4882a593Smuzhiyun * 2001-02-06: Cliff Brake Initial code 12*4882a593Smuzhiyun * 13*4882a593Smuzhiyun * 2001-08-29: Nicolas Pitre Simplified. 14*4882a593Smuzhiyun * 15*4882a593Smuzhiyun * 2002-05-27: Nicolas Pitre Revisited, more cleanup and simplification. 16*4882a593Smuzhiyun * Storage is on the stack now. 17*4882a593Smuzhiyun */ 18*4882a593Smuzhiyun 19*4882a593Smuzhiyun#include <linux/linkage.h> 20*4882a593Smuzhiyun#include <asm/assembler.h> 21*4882a593Smuzhiyun#include <mach/hardware.h> 22*4882a593Smuzhiyun 23*4882a593Smuzhiyun .text 24*4882a593Smuzhiyun/* 25*4882a593Smuzhiyun * sa1100_finish_suspend() 26*4882a593Smuzhiyun * 27*4882a593Smuzhiyun * Causes sa11x0 to enter sleep state 28*4882a593Smuzhiyun * 29*4882a593Smuzhiyun * Must be aligned to a cacheline. 30*4882a593Smuzhiyun */ 31*4882a593Smuzhiyun .balign 32 32*4882a593SmuzhiyunENTRY(sa1100_finish_suspend) 33*4882a593Smuzhiyun @ disable clock switching 34*4882a593Smuzhiyun mcr p15, 0, r1, c15, c2, 2 35*4882a593Smuzhiyun 36*4882a593Smuzhiyun ldr r6, =MDREFR 37*4882a593Smuzhiyun ldr r4, [r6] 38*4882a593Smuzhiyun orr r4, r4, #MDREFR_K1DB2 39*4882a593Smuzhiyun ldr r5, =PPCR 40*4882a593Smuzhiyun 41*4882a593Smuzhiyun @ Pre-load __loop_udelay into the I-cache 42*4882a593Smuzhiyun mov r0, #1 43*4882a593Smuzhiyun bl __loop_udelay 44*4882a593Smuzhiyun mov r0, r0 45*4882a593Smuzhiyun 46*4882a593Smuzhiyun @ The following must all exist in a single cache line to 47*4882a593Smuzhiyun @ avoid accessing memory until this sequence is complete, 48*4882a593Smuzhiyun @ otherwise we occasionally hang. 49*4882a593Smuzhiyun 50*4882a593Smuzhiyun @ Adjust memory timing before lowering CPU clock 51*4882a593Smuzhiyun str r4, [r6] 52*4882a593Smuzhiyun 53*4882a593Smuzhiyun @ delay 90us and set CPU PLL to lowest speed 54*4882a593Smuzhiyun @ fixes resume problem on high speed SA1110 55*4882a593Smuzhiyun mov r0, #90 56*4882a593Smuzhiyun bl __loop_udelay 57*4882a593Smuzhiyun mov r1, #0 58*4882a593Smuzhiyun str r1, [r5] 59*4882a593Smuzhiyun mov r0, #90 60*4882a593Smuzhiyun bl __loop_udelay 61*4882a593Smuzhiyun 62*4882a593Smuzhiyun /* 63*4882a593Smuzhiyun * SA1110 SDRAM controller workaround. register values: 64*4882a593Smuzhiyun * 65*4882a593Smuzhiyun * r0 = &MSC0 66*4882a593Smuzhiyun * r1 = &MSC1 67*4882a593Smuzhiyun * r2 = &MSC2 68*4882a593Smuzhiyun * r3 = MSC0 value 69*4882a593Smuzhiyun * r4 = MSC1 value 70*4882a593Smuzhiyun * r5 = MSC2 value 71*4882a593Smuzhiyun * r6 = &MDREFR 72*4882a593Smuzhiyun * r7 = first MDREFR value 73*4882a593Smuzhiyun * r8 = second MDREFR value 74*4882a593Smuzhiyun * r9 = &MDCNFG 75*4882a593Smuzhiyun * r10 = MDCNFG value 76*4882a593Smuzhiyun * r11 = third MDREFR value 77*4882a593Smuzhiyun * r12 = &PMCR 78*4882a593Smuzhiyun * r13 = PMCR value (1) 79*4882a593Smuzhiyun */ 80*4882a593Smuzhiyun 81*4882a593Smuzhiyun ldr r0, =MSC0 82*4882a593Smuzhiyun ldr r1, =MSC1 83*4882a593Smuzhiyun ldr r2, =MSC2 84*4882a593Smuzhiyun 85*4882a593Smuzhiyun ldr r3, [r0] 86*4882a593Smuzhiyun bic r3, r3, #FMsk(MSC_RT) 87*4882a593Smuzhiyun bic r3, r3, #FMsk(MSC_RT)<<16 88*4882a593Smuzhiyun 89*4882a593Smuzhiyun ldr r4, [r1] 90*4882a593Smuzhiyun bic r4, r4, #FMsk(MSC_RT) 91*4882a593Smuzhiyun bic r4, r4, #FMsk(MSC_RT)<<16 92*4882a593Smuzhiyun 93*4882a593Smuzhiyun ldr r5, [r2] 94*4882a593Smuzhiyun bic r5, r5, #FMsk(MSC_RT) 95*4882a593Smuzhiyun bic r5, r5, #FMsk(MSC_RT)<<16 96*4882a593Smuzhiyun 97*4882a593Smuzhiyun ldr r7, [r6] 98*4882a593Smuzhiyun bic r7, r7, #0x0000FF00 99*4882a593Smuzhiyun bic r7, r7, #0x000000F0 100*4882a593Smuzhiyun orr r8, r7, #MDREFR_SLFRSH 101*4882a593Smuzhiyun 102*4882a593Smuzhiyun ldr r9, =MDCNFG 103*4882a593Smuzhiyun ldr r10, [r9] 104*4882a593Smuzhiyun bic r10, r10, #(MDCNFG_DE0+MDCNFG_DE1) 105*4882a593Smuzhiyun bic r10, r10, #(MDCNFG_DE2+MDCNFG_DE3) 106*4882a593Smuzhiyun 107*4882a593Smuzhiyun bic r11, r8, #MDREFR_SLFRSH 108*4882a593Smuzhiyun bic r11, r11, #MDREFR_E1PIN 109*4882a593Smuzhiyun 110*4882a593Smuzhiyun ldr r12, =PMCR 111*4882a593Smuzhiyun 112*4882a593Smuzhiyun mov r13, #PMCR_SF 113*4882a593Smuzhiyun 114*4882a593Smuzhiyun b sa1110_sdram_controller_fix 115*4882a593Smuzhiyun 116*4882a593Smuzhiyun .align 5 117*4882a593Smuzhiyunsa1110_sdram_controller_fix: 118*4882a593Smuzhiyun 119*4882a593Smuzhiyun @ Step 1 clear RT field of all MSCx registers 120*4882a593Smuzhiyun str r3, [r0] 121*4882a593Smuzhiyun str r4, [r1] 122*4882a593Smuzhiyun str r5, [r2] 123*4882a593Smuzhiyun 124*4882a593Smuzhiyun @ Step 2 clear DRI field in MDREFR 125*4882a593Smuzhiyun str r7, [r6] 126*4882a593Smuzhiyun 127*4882a593Smuzhiyun @ Step 3 set SLFRSH bit in MDREFR 128*4882a593Smuzhiyun str r8, [r6] 129*4882a593Smuzhiyun 130*4882a593Smuzhiyun @ Step 4 clear DE bis in MDCNFG 131*4882a593Smuzhiyun str r10, [r9] 132*4882a593Smuzhiyun 133*4882a593Smuzhiyun @ Step 5 clear DRAM refresh control register 134*4882a593Smuzhiyun str r11, [r6] 135*4882a593Smuzhiyun 136*4882a593Smuzhiyun @ Wow, now the hardware suspend request pins can be used, that makes them functional for 137*4882a593Smuzhiyun @ about 7 ns out of the entire time that the CPU is running! 138*4882a593Smuzhiyun 139*4882a593Smuzhiyun @ Step 6 set force sleep bit in PMCR 140*4882a593Smuzhiyun 141*4882a593Smuzhiyun str r13, [r12] 142*4882a593Smuzhiyun 143*4882a593Smuzhiyun20: b 20b @ loop waiting for sleep 144