1 1.1 ober /* $OpenBSD: pxa2x0_apm_asm.S,v 1.4 2007/11/02 05:18:25 miod Exp $ */ 2 1.1 ober 3 1.1 ober /* 4 1.1 ober * Copyright (c) 2005 Uwe Stuehler <uwe (at) openbsd.org> 5 1.1 ober * 6 1.1 ober * Permission to use, copy, modify, and distribute this software for any 7 1.1 ober * purpose with or without fee is hereby granted, provided that the above 8 1.1 ober * copyright notice and this permission notice appear in all copies. 9 1.1 ober * 10 1.1 ober * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 1.1 ober * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 1.1 ober * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 1.1 ober * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 1.1 ober * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 1.1 ober * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 1.1 ober * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 1.1 ober */ 18 1.1 ober 19 1.3 matt #include <arm/asm.h> 20 1.3 matt #include <arm/locore.h> 21 1.1 ober 22 1.1 ober #include <arch/arm/xscale/pxa2x0reg.h> 23 1.1 ober #include <arch/arm/sa11x0/sa11x0_reg.h> 24 1.1 ober 25 1.1 ober /* XXX replace with values defined elsewhere. */ 26 1.1 ober #define DCACHE_CACHELINECOUNT 1024 27 1.1 ober #define CACHELINESIZE 32 28 1.1 ober #define DCACHE_SIZE (CACHELINESIZE * DCACHE_CACHELINECOUNT) 29 1.1 ober 30 1.1 ober /* cp14 register 6 */ 31 1.1 ober #define CLKCFG_T (1<<0) /* turbo */ 32 1.1 ober #define CLKCFG_F (1<<1) /* frequency change */ 33 1.1 ober #define CLKCFG_HT (1<<2) /* half-turbo */ 34 1.1 ober #define CLKCFG_B (1<<3) /* fast-bus */ 35 1.1 ober 36 1.1 ober /* cp14 register 7 */ 37 1.1 ober #define PWRMODE_NORMAL (0<<0) 38 1.1 ober #define PWRMODE_IDLE (1<<0) 39 1.1 ober #define PWRMODE_STANDBY (2<<0) 40 1.1 ober #define PWRMODE_SLEEP (3<<0) 41 1.1 ober #define PWRMODE_DEEP_SLEEP (7<<0) 42 1.1 ober 43 1.1 ober /* XXX */ 44 1.1 ober #define MDREFR_C3000 (MDREFR_K0DB2|MDREFR_E1PIN|MDREFR_K1RUN|\ 45 1.1 ober MDREFR_K1DB2|MDREFR_K2DB2|MDREFR_APD) 46 1.1 ober #define MDREFR_DRI_91MHZ (0x13<<0) 47 1.1 ober #define MDREFR_HIGH (MDREFR_C3000 | 0x030) 48 1.1 ober #define MDREFR_LOW (MDREFR_C3000 | 0x00b) 49 1.1 ober #define MDREFR_SPEED_91 (MDREFR_C3000 | MDREFR_DRI_91MHZ) 50 1.1 ober #define MDREFR_SPEED_LOW (MDREFR_C3000 | 0x017) 51 1.1 ober #define MSC0_HIGH \ 52 1.1 ober ( 7 << MSC_RRR_SHIFT << 16) | \ 53 1.1 ober (15 << MSC_RDN_SHIFT << 16) | \ 54 1.1 ober (15 << MSC_RDF_SHIFT << 16) | \ 55 1.1 ober (MSC_RT_NONBURST << 16) | \ 56 1.1 ober ( 2 << MSC_RRR_SHIFT) | \ 57 1.1 ober (13 << MSC_RDN_SHIFT) | \ 58 1.1 ober (13 << MSC_RDF_SHIFT) | \ 59 1.1 ober MSC_RBW /* PXA271 */ | \ 60 1.1 ober MSC_RT_NONBURST 61 1.1 ober #define MSC1_HIGH \ 62 1.1 ober ( 7 << MSC_RRR_SHIFT << 16) | \ 63 1.1 ober (15 << MSC_RDN_SHIFT << 16) | \ 64 1.1 ober (15 << MSC_RDF_SHIFT << 16) | \ 65 1.1 ober (MSC_RT_VLIO << 16) | \ 66 1.1 ober ( 3 << MSC_RRR_SHIFT) | \ 67 1.1 ober ( 4 << MSC_RDN_SHIFT) | \ 68 1.1 ober (13 << MSC_RDF_SHIFT) | \ 69 1.1 ober MSC_RT_VLIO 70 1.1 ober #define MSC2_HIGH \ 71 1.1 ober ( 7 << MSC_RRR_SHIFT << 16) | \ 72 1.1 ober (15 << MSC_RDN_SHIFT << 16) | \ 73 1.1 ober (15 << MSC_RDF_SHIFT << 16) | \ 74 1.1 ober (MSC_RT_NONBURST << 16) | \ 75 1.1 ober ( 3 << MSC_RRR_SHIFT) | \ 76 1.1 ober ( 4 << MSC_RDN_SHIFT) | \ 77 1.1 ober (13 << MSC_RDF_SHIFT) | \ 78 1.1 ober MSC_RT_VLIO 79 1.1 ober #define MSC0_LOW \ 80 1.1 ober ( 7 << MSC_RRR_SHIFT << 16) | \ 81 1.1 ober (15 << MSC_RDN_SHIFT << 16) | \ 82 1.1 ober (15 << MSC_RDF_SHIFT << 16) | \ 83 1.1 ober (MSC_RT_NONBURST << 16) | \ 84 1.1 ober ( 1 << MSC_RRR_SHIFT) | \ 85 1.1 ober ( 8 << MSC_RDN_SHIFT) | \ 86 1.1 ober ( 8 << MSC_RDF_SHIFT) | \ 87 1.1 ober MSC_RBW /* PXA271 */ | \ 88 1.1 ober MSC_RT_NONBURST 89 1.1 ober #define MSC1_LOW \ 90 1.1 ober ( 7 << MSC_RRR_SHIFT << 16) | \ 91 1.1 ober (15 << MSC_RDN_SHIFT << 16) | \ 92 1.1 ober (15 << MSC_RDF_SHIFT << 16) | \ 93 1.1 ober (MSC_RT_VLIO << 16) | \ 94 1.1 ober ( 1 << MSC_RRR_SHIFT) | \ 95 1.1 ober ( 2 << MSC_RDN_SHIFT) | \ 96 1.1 ober ( 6 << MSC_RDF_SHIFT) | \ 97 1.1 ober MSC_RT_VLIO 98 1.1 ober #define MSC2_LOW \ 99 1.1 ober ( 7 << MSC_RRR_SHIFT << 16) | \ 100 1.1 ober (15 << MSC_RDN_SHIFT << 16) | \ 101 1.1 ober (15 << MSC_RDF_SHIFT << 16) | \ 102 1.1 ober (MSC_RT_NONBURST << 16) | \ 103 1.1 ober ( 1 << MSC_RRR_SHIFT) | \ 104 1.1 ober ( 2 << MSC_RDN_SHIFT) | \ 105 1.1 ober ( 6 << MSC_RDF_SHIFT) | \ 106 1.1 ober MSC_RT_VLIO 107 1.1 ober 108 1.1 ober .text 109 1.1 ober .global _C_LABEL(vector_page) 110 1.1 ober .global _C_LABEL(xscale_cache_clean_addr) 111 1.1 ober .global _C_LABEL(pxa2x0_clkman_ioh) 112 1.1 ober .global _C_LABEL(pxa2x0_memctl_ioh) 113 1.1 ober 114 1.1 ober .Lvector_page: 115 1.1 ober .word _C_LABEL(vector_page) 116 1.1 ober .Lxscale_cache_clean_addr: 117 1.1 ober .word _C_LABEL(xscale_cache_clean_addr) 118 1.1 ober 119 1.1 ober .Lgpioiohp: .word _C_LABEL(pxa2x0_gpio_ioh) 120 1.1 ober .Lclkmaniohp: .word _C_LABEL(pxa2x0_clkman_ioh) 121 1.1 ober .Lmemctliohp: .word _C_LABEL(pxa2x0_memctl_ioh) 122 1.1 ober 123 1.1 ober .Lsleepdata: .word sleepdata 124 1.1 ober .Lsleepdata_phys: .word sleepdata - 0xc0200000 + 0xa0200000 /* XXX */ 125 1.1 ober .Lsleepdata_svc: .word sleepdata_svc 126 1.1 ober 127 1.1 ober .Lcccr_high: .word CCCR_A | CCCR_TURBO_X2 | CCCR_RUN_X16 128 1.1 ober .Lmdrefr_high: .word MDREFR_HIGH 129 1.1 ober .Lmsc0_high: .word MSC0_HIGH 130 1.1 ober .Lmsc1_high: .word MSC1_HIGH 131 1.1 ober .Lmsc2_high: .word MSC2_HIGH 132 1.1 ober .Lmdrefr_low: .word MDREFR_LOW 133 1.1 ober .Lmsc0_low: .word MSC0_LOW 134 1.1 ober .Lmsc1_low: .word MSC1_LOW 135 1.1 ober .Lmsc2_low: .word MSC2_LOW 136 1.1 ober 137 1.1 ober /* 138 1.1 ober * void pxa2x0_cpu_suspend(void) 139 1.1 ober * 140 1.1 ober * Enter sleep mode without automatic voltage change. The core must 141 1.1 ober * be in low power mode, and interrupts disabled. 142 1.1 ober */ 143 1.1 ober ENTRY(pxa2x0_cpu_suspend) 144 1.1 ober stmdb sp!, {r0-r12, lr} 145 1.1 ober 146 1.1 ober ldr r3, .Lsleepdata /* Point to the data area. */ 147 1.1 ober ldr r2, =pxa2x0_cpu_resume_virt 148 1.1 ober str r2, [r3], #4 149 1.1 ober 150 1.1 ober mrc p15, 0, r2, c1, c0, 0 /* Load MMU control register. */ 151 1.1 ober mov r0, #0xff000000 152 1.1 ober orr r0, r0, #0x00ff0000 153 1.1 ober bic r2, r2, r0 /* Clear undefined bits. */ 154 1.1 ober str r2, [r3], #4 /* Save MMU control register. */ 155 1.1 ober 156 1.1 ober mrc p15, 0, r2, c2, c0, 0 /* Load TTB address. */ 157 1.1 ober mov r0, #0x00003f00 158 1.1 ober orr r0, r0, #0x000000ff 159 1.1 ober bic r2, r2, r0 /* Clear undefined bits. */ 160 1.1 ober str r2, [r3], #4 /* Save TTB address. */ 161 1.1 ober 162 1.1 ober mrc p15, 0, r2, c3, c0, 0 /* Load domain access control. */ 163 1.1 ober str r2, [r3], #4 /* Save domain access control. */ 164 1.1 ober 165 1.1 ober mrs r2, spsr /* Load SVC saved CPSR. */ 166 1.1 ober str r2, [r3], #4 /* Save SVC saved CPSR. */ 167 1.1 ober str sp, [r3], #4 /* Save SVC stack pointer. */ 168 1.1 ober 169 1.1 ober mov r1, #(PSR_FIQ32_MODE | I32_bit | F32_bit) 170 1.1 ober msr cpsr, r1 /* Enter FIQ mode. */ 171 1.1 ober mrs r2, spsr /* Load FIQ mode saved CPSR. */ 172 1.1 ober stmia r3!, {r2, r8-r12, sp, lr} /* Save FIQ mode registers. */ 173 1.1 ober 174 1.1 ober mov r1, #(PSR_IRQ32_MODE | I32_bit | F32_bit) 175 1.1 ober msr cpsr, r1 /* Enter IRQ mode. */ 176 1.1 ober mrs r0, spsr /* Load IRQ mode saved CPSR. */ 177 1.1 ober stmia r3!, {r0, sp, lr} /* Save IRQ mode registers. */ 178 1.1 ober 179 1.1 ober mov r1, #(PSR_ABT32_MODE | I32_bit | F32_bit) 180 1.1 ober msr cpsr, r1 /* Enter ABT mode. */ 181 1.1 ober mrs r0, spsr /* Load ABT mode saved CPSR. */ 182 1.1 ober stmia r3!, {r0, sp, lr} /* Save ABT mode registers. */ 183 1.1 ober 184 1.1 ober mov r1, #(PSR_UND32_MODE | I32_bit | F32_bit) 185 1.1 ober msr cpsr, r1 /* Enter UND mode. */ 186 1.1 ober mrs r0, spsr /* Load UND mode saved CPSR. */ 187 1.1 ober stmia r3!, {r0, sp, lr} /* Save UND mode registers. */ 188 1.1 ober 189 1.1 ober mov r1, #(PSR_SYS32_MODE | I32_bit | F32_bit) 190 1.1 ober msr cpsr, r1 /* Enter SYS mode. */ 191 1.1 ober stmia r3!, {sp, lr} /* Save SYS mode registers. */ 192 1.1 ober 193 1.1 ober mov r1, #(PSR_SVC32_MODE | I32_bit | F32_bit) 194 1.1 ober msr cpsr, r1 /* Return to SVC mode. */ 195 1.1 ober 196 1.1 ober /* At this point all critical registers have been saved. */ 197 1.1 ober 198 1.1 ober mov r0, #0 199 1.1 ober mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ 200 1.1 ober 201 1.1 ober mov r1, #DCACHE_CACHELINECOUNT 202 1.1 ober ldr r2, .Lxscale_cache_clean_addr 203 1.1 ober ldr r0, [r2] 204 1.1 ober /* 205 1.1 ober * For an explanation of the following two instructions, refer 206 1.1 ober * to the ``BUG ALERT'' section of the XSCALE_CACHE_CLEAN_PROLOGUE 207 1.1 ober * macro in arch/arm/arm/cpufunc_asm_xscale.S. 208 1.1 ober */ 209 1.1 ober eor r0, r0, #(DCACHE_SIZE) 210 1.1 ober str r0, [r2] 211 1.1 ober 212 1.1 ober cache_flush_loop: 213 1.1 ober mrs r2, cpsr 214 1.1 ober orr r2, r2, #(I32_bit|F32_bit) 215 1.1 ober msr cpsr_c, r2 /* disable IRQ/FIQ */ 216 1.1 ober 217 1.1 ober mcr p15, 0, r0, c7, c2, 5 /* allocate cache line */ 218 1.1 ober mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */ 219 1.1 ober 220 1.1 ober mrs r2, cpsr 221 1.1 ober and r2, r2, #~(I32_bit|F32_bit) 222 1.1 ober msr cpsr_c, r2 /* enable IRQ/FIQ */ 223 1.1 ober 224 1.1 ober add r0, r0, #CACHELINESIZE 225 1.1 ober subs r1, r1, #1 226 1.1 ober bne cache_flush_loop 227 1.1 ober 228 1.1 ober mov r0, #0 229 1.1 ober mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ 230 1.1 ober 231 1.1 ober b 1f 232 1.1 ober 1: 233 1.1 ober nop 234 1.1 ober nop 235 1.1 ober nop 236 1.1 ober nop 237 1.1 ober nop 238 1.1 ober nop 239 1.1 ober nop 240 1.1 ober nop 241 1.1 ober nop 242 1.1 ober nop 243 1.1 ober nop 244 1.1 ober 245 1.1 ober /* Prepare to enter sleep mode. */ 246 1.1 ober mov r1, #PWRMODE_SLEEP 247 1.1 ober 248 1.1 ober /* Prepare to put SDRAM into self-refresh mode. */ 249 1.1 ober ldr r4, .Lmemctliohp 250 1.1 ober ldr r4, [r4] 251 1.1 ober add r4, r4, #MEMCTL_MDREFR 252 1.1 ober ldr r5, [r4] 253 1.1 ober orr r5, r5, #MDREFR_SLFRSH 254 1.1 ober 255 1.1 ober /* XXX prepare pointer to physical address 0, but for whom? */ 256 1.1 ober ldr r2, .Lvector_page 257 1.1 ober 258 1.1 ober /* 259 1.1 ober * Execute the rest of this routine from cache. The needed values 260 1.1 ober * are now in registers. 261 1.1 ober */ 262 1.1 ober b 1f 263 1.1 ober /* XXX tell as(1) to dump the literal pool here, but why? */ 264 1.1 ober .ltorg 265 1.1 ober .align 5 266 1.1 ober 1: 267 1.1 ober 268 1.1 ober /* Put SDRAM into self-refresh mode manually. */ 269 1.1 ober str r5, [r4] 270 1.1 ober nop 271 1.1 ober 272 1.1 ober /* 273 1.1 ober * Enter sleep mode. Exit from sleep mode returns the processor 274 1.1 ober * to normal run mode. Execution resumes at the physical address 275 1.1 ober * stored in the PSPR after the required boot sequence (a short 276 1.1 ober * excursion into the ROM boot loader). 277 1.1 ober */ 278 1.1 ober mcr p14, 0, r1, c7, c0, 0 279 1.1 ober 280 1.1 ober /* Just in case that wake-up does not resume at */ 281 1.1 ober nop 282 1.1 ober nop 283 1.1 ober nop 284 1.1 ober 1: 285 1.1 ober b 1b 286 1.1 ober 287 1.1 ober /* 288 1.1 ober * void pxa2x0_cpu_resume(void) 289 1.1 ober */ 290 1.1 ober .align 5 291 1.1 ober ENTRY(pxa2x0_cpu_resume) 292 1.1 ober /* XXX C3000-specific */ 293 1.1 ober ldr r0, .Lmdrefr_addr_phys 294 1.1 ober b 1f 295 1.1 ober .align 5 296 1.1 ober 1: 297 1.1 ober ldr r2, [r0] 298 1.1 ober bic r2, r2, #MDREFR_DRI & 0x000000ff 299 1.1 ober bic r2, r2, #MDREFR_DRI & 0x0000ff00 300 1.1 ober orr r2, r2, #MDREFR_DRI_91MHZ 301 1.1 ober str r2, [r0] 302 1.1 ober b 1f 303 1.1 ober .align 5 304 1.1 ober 1: 305 1.1 ober ldr r0, .Lsleepdata_phys /* Point to PA of saved data. */ 306 1.1 ober 307 1.1 ober ldmia r0!, {r7-r10} 308 1.1 ober mcr p15, 0, r10, c3, c0, 0 /* Restore domain access control. */ 309 1.1 ober mcr p15, 0, r9, c2, c0, 0 /* Restore TTB address. */ 310 1.1 ober mcr p15, 0, r0, c8, c7, 0 /* Flush I+D TLBs. */ 311 1.1 ober mcr p15, 0, r0, c7, c7, 0 /* Flush I+D BTB. */ 312 1.1 ober mcr p15, 0, r8, c1, c0, 0 /* Restore MMU control. */ 313 1.1 ober mov pc, r7 /* Jump to virtual address. */ 314 1.1 ober nop 315 1.1 ober nop 316 1.1 ober nop 317 1.1 ober nop 318 1.1 ober nop 319 1.1 ober nop 320 1.1 ober nop 321 1.1 ober nop 322 1.1 ober 323 1.1 ober pxa2x0_cpu_resume_virt: 324 1.1 ober ldr r2, .Lsleepdata_svc /* Load VA of saved registers. */ 325 1.1 ober 326 1.1 ober /* Restore SVC mode SPSR and stack pointer. */ 327 1.1 ober ldr r0, [r2], #4 328 1.1 ober msr spsr, r0 329 1.1 ober ldr sp, [r2], #4 330 1.1 ober 331 1.1 ober /* Restore FIQ mode registers. */ 332 1.1 ober mov r1, #(PSR_FIQ32_MODE | I32_bit | F32_bit) 333 1.1 ober msr cpsr, r1 334 1.1 ober ldr r0, [r2], #4 335 1.1 ober msr spsr, r0 336 1.1 ober ldr r8, [r2], #4 337 1.1 ober ldr r9, [r2], #4 338 1.1 ober ldr r10, [r2], #4 339 1.1 ober ldr r11, [r2], #4 340 1.1 ober ldr r12, [r2], #4 341 1.1 ober ldr sp, [r2], #4 342 1.1 ober ldr lr, [r2], #4 343 1.1 ober 344 1.1 ober /* Restore IRQ mode registers. */ 345 1.1 ober mov r1, #(PSR_IRQ32_MODE | I32_bit | F32_bit) 346 1.1 ober msr cpsr, r1 347 1.1 ober ldr r0, [r2], #4 348 1.1 ober msr spsr, r0 349 1.1 ober ldr sp, [r2], #4 350 1.1 ober ldr lr, [r2], #4 351 1.1 ober 352 1.1 ober /* Restore ABT mode registers. */ 353 1.1 ober mov r1, #(PSR_ABT32_MODE | I32_bit | F32_bit) 354 1.1 ober msr cpsr, r1 355 1.1 ober ldr r0, [r2], #4 356 1.1 ober msr spsr, r0 357 1.1 ober ldr sp, [r2], #4 358 1.1 ober ldr lr, [r2], #4 359 1.1 ober 360 1.1 ober /* Restore UND mode registers. */ 361 1.1 ober mov r1, #(PSR_UND32_MODE | I32_bit | F32_bit) 362 1.1 ober msr cpsr, r1 363 1.1 ober ldr r0, [r2], #4 364 1.1 ober msr spsr, r0 365 1.1 ober ldr sp, [r2], #4 366 1.1 ober ldr lr, [r2], #4 367 1.1 ober 368 1.1 ober /* Restore SYS mode registers. */ 369 1.1 ober mov r1, #(PSR_SYS32_MODE | I32_bit | F32_bit) 370 1.1 ober msr cpsr, r1 371 1.1 ober ldr sp, [r2], #4 372 1.1 ober ldr lr, [r2], #4 373 1.1 ober 374 1.1 ober /* Return to SVC mode. */ 375 1.1 ober mov r1, #(PSR_SVC32_MODE | I32_bit | F32_bit) 376 1.1 ober msr cpsr, r1 377 1.1 ober 378 1.1 ober ldmia sp!, {r0-r12, pc} 379 1.1 ober 380 1.1 ober .Lmdrefr_addr_phys: 381 1.1 ober .word PXA2X0_MEMCTL_BASE + MEMCTL_MDREFR 382 1.1 ober 383 1.1 ober .data 384 1.1 ober 385 1.1 ober /* 386 1.1 ober * Saved processor state 387 1.1 ober */ 388 1.1 ober .align 5 389 1.1 ober sleepdata: 390 1.1 ober .word 0 /* =pxa2x0_cpu_resume_virt */ 391 1.1 ober .word 0 /* MMU control */ 392 1.1 ober .word 0 /* MMU TTB address */ 393 1.1 ober .word 0 /* MMU domain access control */ 394 1.1 ober sleepdata_svc: 395 1.1 ober .word 0 /* SVC mode saved CPSR */ 396 1.1 ober .word 0 /* SVC mode stack pointer */ 397 1.1 ober .word 0 /* FIQ mode saved CPSR */ 398 1.1 ober .word 0 /* FIQ mode r8 */ 399 1.1 ober .word 0 /* FIQ mode r9 */ 400 1.1 ober .word 0 /* FIQ mode r10 */ 401 1.1 ober .word 0 /* FIQ mode r11 */ 402 1.1 ober .word 0 /* FIQ mode r12 */ 403 1.1 ober .word 0 /* FIQ mode stack pointer */ 404 1.1 ober .word 0 /* FIQ mode link register */ 405 1.1 ober .word 0 /* IRQ mode saved CPSR */ 406 1.1 ober .word 0 /* IRQ mode stack pointer */ 407 1.1 ober .word 0 /* IRQ mode link register */ 408 1.1 ober .word 0 /* ABT mode saved CPSR */ 409 1.1 ober .word 0 /* ABT mode stack pointer */ 410 1.1 ober .word 0 /* ABT mode link register */ 411 1.1 ober .word 0 /* UND mode saved CPSR */ 412 1.1 ober .word 0 /* UND mode stack pointer */ 413 1.1 ober .word 0 /* UND mode link register */ 414 1.1 ober .word 0 /* SYS mode stack pointer */ 415 1.1 ober .word 0 /* SYS mode link register */ 416 1.1 ober 417 1.1 ober .text 418 1.1 ober 419 1.1 ober /* 420 1.1 ober * void pxa27x_run_mode(void) 421 1.1 ober * 422 1.1 ober * Disable half-turbo and turbo mode, but keep fast-bus mode. 423 1.1 ober * Memory and LCD clock is not changed, so no reconfiguration is 424 1.1 ober * necessary. 425 1.1 ober */ 426 1.1 ober ENTRY(pxa27x_run_mode) 427 1.1 ober stmdb sp!, {r0} 428 1.1 ober mrc p14, 0, r0, c6, c0, 0 429 1.1 ober and r0, r0, #~(CLKCFG_HT | CLKCFG_F| CLKCFG_T) 430 1.1 ober mcr p14, 0, r0, c6, c0, 0 431 1.1 ober ldmia sp!, {r0} 432 1.1 ober mov pc, lr 433 1.1 ober 434 1.1 ober /* 435 1.2 skrll * void pxa27x_fastbus_run_mode(int enable, uint32_t mdrefr) 436 1.1 ober * 437 1.1 ober * Enter normal run mode with fast-bus mode enabled or disabled. 438 1.1 ober * The new value of MDREFR is programmed before or after CLKCFG, 439 1.1 ober * as appropriate. 440 1.1 ober */ 441 1.1 ober .align 5 442 1.1 ober ENTRY(pxa27x_fastbus_run_mode) 443 1.1 ober stmdb sp!, {r0-r2, lr} 444 1.1 ober ldr r2, .Lmemctliohp 445 1.1 ober ldr r2, [r2] 446 1.1 ober cmp r0, #0 447 1.1 ober beq disable_fastbus 448 1.1 ober b enable_fastbus 449 1.1 ober .align 5 450 1.1 ober enable_fastbus: 451 1.1 ober /* Enter normal run mode with fast-bus mode enabled. */ 452 1.1 ober mov r0, #CLKCFG_B 453 1.1 ober mcr p14, 0, r0, c6, c0, 0 454 1.1 ober /* Set the new SDRAM refresh rate. */ 455 1.1 ober str r1, [r2, #MEMCTL_MDREFR] 456 1.1 ober ldr r0, [r2, #MEMCTL_MDREFR] 457 1.1 ober mov r0, r0 458 1.1 ober ldmia sp!, {r0-r2, pc} 459 1.1 ober .align 5 460 1.1 ober disable_fastbus: 461 1.1 ober /* Set the new SDRAM refresh rate. */ 462 1.1 ober str r1, [r2, #MEMCTL_MDREFR] 463 1.1 ober ldr r0, [r2, #MEMCTL_MDREFR] 464 1.1 ober mov r0, r0 465 1.1 ober /* Enter normal run mode with fast-bus mode disabled. */ 466 1.1 ober mov r0, #0x0 467 1.1 ober mcr p14, 0, r0, c6, c0, 0 468 1.1 ober ldmia sp!, {r0-r2, pc} 469 1.1 ober 470 1.1 ober /* Keep these offsets in sync with struct memcfg. */ 471 1.1 ober #define memcfg_mdrefr_high 0x00 472 1.1 ober #define memcfg_mdrefr_low 0x04 473 1.1 ober #define memcfg_mdrefr_low2 0x08 /* unused */ 474 1.1 ober #define memcfg_msc_high 0x0c 475 1.1 ober #define memcfg_msc_low 0x18 476 1.1 ober #define memcfg_mdrefr_91 0x24 477 1.1 ober 478 1.1 ober /* 479 1.1 ober * void pxa27x_frequency_change(int cccr, int clkcfg, 480 1.1 ober * struct pxa2x0_memcfg *memcfg) 481 1.1 ober * 482 1.1 ober * Change the core PLL frequency and SDRAM refresh rate, ensuring the 483 1.1 ober * proper sequence of operations. If the CCCR_A bit is clear and L 484 1.1 ober * is not equal to 7 the result is undefined. 485 1.1 ober */ 486 1.1 ober .align 5 487 1.1 ober ENTRY(pxa27x_frequency_change) 488 1.1 ober stmdb sp!, {r0-r5, lr} 489 1.1 ober 490 1.1 ober /* Always write to CCCR before a frequency change. */ 491 1.1 ober ldr r3, .Lclkmaniohp 492 1.1 ober ldr r3, [r3] 493 1.1 ober str r0, [r3, #CLKMAN_CCCR] 494 1.1 ober 495 1.1 ober /* Load the needed values into registers to avoid SDRAM access. */ 496 1.1 ober and r3, r0, #CCCR_L_MASK 497 1.1 ober ldr r0, .Lmemctliohp 498 1.1 ober ldr r0, [r0] 499 1.1 ober cmp r3, #CCCR_RUN_X7 /* L=7 is 91MHz mode */ 500 1.1 ober beq frequency_change_91 501 1.1 ober and r3, r1, #CLKCFG_B 502 1.1 ober cmp r3, #CLKCFG_B 503 1.1 ober bne frequency_change_208 504 1.1 ober /* FALLTHROUGH */ 505 1.1 ober frequency_change_high: 506 1.1 ober ldr r3, [r2, #memcfg_mdrefr_low] 507 1.1 ober ldr r4, [r2, #memcfg_mdrefr_high] 508 1.1 ober add r2, r2, #memcfg_msc_high 509 1.1 ober bl frequency_change_on_cache /* XXX why BL? */ 510 1.1 ober frequency_change_208: 511 1.1 ober ldr r3, [r2, #memcfg_mdrefr_low] 512 1.1 ober ldr r4, [r2, #memcfg_mdrefr_low] 513 1.1 ober add r2, r2, #memcfg_msc_high 514 1.1 ober bl frequency_change_on_cache 515 1.1 ober frequency_change_91: 516 1.1 ober ldr r3, [r2, #memcfg_mdrefr_low] 517 1.1 ober ldr r4, [r2, #memcfg_mdrefr_91] 518 1.1 ober add r2, r2, #memcfg_msc_low 519 1.1 ober bl frequency_change_on_cache 520 1.1 ober 521 1.1 ober /* Align execution to a cache line. */ 522 1.1 ober .align 5 523 1.1 ober frequency_change_on_cache: 524 1.1 ober /* Change to a low SDRAM refresh rate. Wait until the store to 525 1.1 ober * MDREFR is complete, following section 2.4 I/O Ordering and 526 1.1 ober * 6.5.1.4 of the PXA27x Developer's Manual. */ 527 1.1 ober str r3, [r0, #MEMCTL_MDREFR] 528 1.1 ober ldr r5, [r0, #MEMCTL_MDREFR] 529 1.1 ober mov r5, r5 530 1.1 ober /* Program new CLKCFG value, starting a core PLL frequency change 531 1.1 ober * if CLKCFG_F is set. */ 532 1.1 ober mcr p14, 0, r1, c6, c0, 0 533 1.1 ober /* Change SDRAM clock frequency to 104MHz, and ensure that the 534 1.1 ober * store to MDREFR is complete before the next SDRAM access. */ 535 1.1 ober str r4, [r0, #MEMCTL_MDREFR] 536 1.1 ober ldr r5, [r0, #MEMCTL_MDREFR] 537 1.1 ober mov r5, r5 538 1.1 ober /* Configure synchronous, static, and VLIO interfaces. */ 539 1.1 ober ldr r1, [r2], #4 540 1.1 ober str r1, [r0, #MEMCTL_MSC0] 541 1.1 ober ldr r1, [r2], #4 542 1.1 ober str r1, [r0, #MEMCTL_MSC1] 543 1.1 ober ldr r1, [r2] 544 1.1 ober str r1, [r0, #MEMCTL_MSC2] 545 1.1 ober ldmia sp!, {r0-r5, pc} 546 1.1 ober 547 1.1 ober /* 548 1.1 ober * void pxa27x_cpu_speed_91(void) 549 1.1 ober * 550 1.1 ober * Switch core run frequency to 91 MHz. 551 1.1 ober */ 552 1.1 ober .align 5 553 1.1 ober ENTRY(pxa27x_cpu_speed_91) 554 1.1 ober stmdb sp!, {r0-r3, lr} 555 1.1 ober 556 1.1 ober ldr r0, .Lclkmaniohp 557 1.1 ober ldr r0, [r0] 558 1.1 ober ldr r1, .Lcccr_91 559 1.1 ober str r1, [r0, #CLKMAN_CCCR] 560 1.1 ober 561 1.1 ober ldr r0, .Lmemctliohp 562 1.1 ober ldr r0, [r0] 563 1.1 ober ldr r2, .Lmdrefr_91 564 1.1 ober ldr r3, .Lmdrefr_low 565 1.1 ober 566 1.1 ober bl 1f 567 1.1 ober .align 5 568 1.1 ober 1: 569 1.1 ober str r3, [r0, #MEMCTL_MDREFR] 570 1.1 ober ldr r3, [r0, #MEMCTL_MDREFR] 571 1.1 ober 572 1.1 ober mov r1, #CLKCFG_F 573 1.1 ober mcr p14, 0, r1, c6, c0, 0 574 1.1 ober str r2, [r0, #MEMCTL_MDREFR] 575 1.1 ober ldr r2, [r0, #MEMCTL_MDREFR] 576 1.1 ober 577 1.1 ober ldr r1, .Lmsc0_low 578 1.1 ober str r1, [r0, #MEMCTL_MSC0] 579 1.1 ober ldr r1, .Lmsc1_low 580 1.1 ober str r1, [r0, #MEMCTL_MSC1] 581 1.1 ober ldr r1, .Lmsc2_low 582 1.1 ober str r1, [r0, #MEMCTL_MSC2] 583 1.1 ober 584 1.1 ober ldmia sp!, {r0-r3, pc} 585 1.1 ober 586 1.1 ober .Lcccr_91: .word CCCR_TURBO_X1 | CCCR_RUN_X7 587 1.1 ober .Lmdrefr_91: .word MDREFR_SPEED_91 588