Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 | /* * linux/arch/arm/mach-omap2/sram243x.S * * Omap2 specific functions that need to be run in internal SRAM * * (C) Copyright 2004 * Texas Instruments, <www.ti.com> * Richard Woodruff <r-woodruff2@ti.com> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * * Richard Woodruff notes that any changes to this code must be carefully * audited and tested to ensure that they don't cause a TLB miss while * the SDRAM is inaccessible. Such a situation will crash the system * since it will cause the ARM MMU to attempt to walk the page tables. * These crashes may be intermittent. */ #include <linux/linkage.h> #include <asm/assembler.h> #include <mach/hardware.h> #include "iomap.h" #include "prm2xxx_3xxx.h" #include "cm2xxx_3xxx.h" #include "sdrc.h" .text .align 3 ENTRY(omap243x_sram_ddr_init) stmfd sp!, {r0 - r12, lr} @ save registers on stack mov r12, r2 @ capture CS1 vs CS0 mov r8, r3 @ capture force parameter /* frequency shift down */ ldr r2, omap243x_sdi_cm_clksel2_pll @ get address of dpllout reg mov r3, #0x1 @ value for 1x operation str r3, [r2] @ go to L1-freq operation /* voltage shift down */ mov r9, #0x1 @ set up for L1 voltage call bl voltage_shift @ go drop voltage /* dll lock mode */ ldr r11, omap243x_sdi_sdrc_dlla_ctrl @ addr of dlla ctrl ldr r10, [r11] @ get current val cmp r12, #0x1 @ cs1 base (2422 es2.05/1) addeq r11, r11, #0x8 @ if cs1 base, move to DLLB mvn r9, #0x4 @ mask to get clear bit2 and r10, r10, r9 @ clear bit2 for lock mode. orr r10, r10, #0x8 @ make sure DLL on (es2 bit pos) orr r10, r10, #0x2 @ 90 degree phase for all below 133Mhz str r10, [r11] @ commit to DLLA_CTRL bl i_dll_wait @ wait for dll to lock /* get dll value */ add r11, r11, #0x4 @ get addr of status reg ldr r10, [r11] @ get locked value /* voltage shift up */ mov r9, #0x0 @ shift back to L0-voltage bl voltage_shift @ go raise voltage /* frequency shift up */ mov r3, #0x2 @ value for 2x operation str r3, [r2] @ go to L0-freq operation /* reset entry mode for dllctrl */ sub r11, r11, #0x4 @ move from status to ctrl cmp r12, #0x1 @ normalize if cs1 based subeq r11, r11, #0x8 @ possibly back to DLLA cmp r8, #0x1 @ if forced unlock exit orreq r1, r1, #0x4 @ make sure exit with unlocked value str r1, [r11] @ restore DLLA_CTRL high value add r11, r11, #0x8 @ move to DLLB_CTRL addr str r1, [r11] @ set value DLLB_CTRL bl i_dll_wait @ wait for possible lock /* set up for return, DDR should be good */ str r10, [r0] @ write dll_status and return counter ldmfd sp!, {r0 - r12, pc} @ restore regs and return /* ensure the DLL has relocked */ i_dll_wait: mov r4, #0x800 @ delay DLL relock, min 0x400 L3 clocks i_dll_delay: subs r4, r4, #0x1 bne i_dll_delay mov pc, lr /* * shift up or down voltage, use R9 as input to tell level. * wait for it to finish, use 32k sync counter, 1tick=31uS. */ voltage_shift: ldr r4, omap243x_sdi_prcm_voltctrl @ get addr of volt ctrl. ldr r5, [r4] @ get value. ldr r6, prcm_mask_val @ get value of mask and r5, r5, r6 @ apply mask to clear bits orr r5, r5, r9 @ bulld value for L0/L1-volt operation. str r5, [r4] @ set up for change. mov r3, #0x4000 @ get val for force orr r5, r5, r3 @ build value for force str r5, [r4] @ Force transition to L1 ldr r3, omap243x_sdi_timer_32ksynct_cr @ get addr of counter ldr r5, [r3] @ get value add r5, r5, #0x3 @ give it at most 93uS volt_delay: ldr r7, [r3] @ get timer value cmp r5, r7 @ time up? bhi volt_delay @ not yet->branch mov pc, lr @ back to caller. omap243x_sdi_cm_clksel2_pll: .word OMAP2430_CM_REGADDR(PLL_MOD, CM_CLKSEL2) omap243x_sdi_sdrc_dlla_ctrl: .word OMAP243X_SDRC_REGADDR(SDRC_DLLA_CTRL) omap243x_sdi_prcm_voltctrl: .word OMAP2430_PRCM_VOLTCTRL prcm_mask_val: .word 0xFFFF3FFC omap243x_sdi_timer_32ksynct_cr: .word OMAP2_L4_IO_ADDRESS(OMAP2430_32KSYNCT_BASE + 0x010) ENTRY(omap243x_sram_ddr_init_sz) .word . - omap243x_sram_ddr_init /* * Reprograms memory timings. * r0 = [PRCM_FULL | PRCM_HALF] r1 = SDRC_DLLA_CTRL value r2 = [DDR | SDR] * PRCM_FULL = 2, PRCM_HALF = 1, DDR = 1, SDR = 0 */ .align 3 ENTRY(omap243x_sram_reprogram_sdrc) stmfd sp!, {r0 - r10, lr} @ save registers on stack mov r3, #0x0 @ clear for mrc call mcr p15, 0, r3, c7, c10, 4 @ memory barrier, finish ARM SDR/DDR nop nop ldr r6, omap243x_srs_sdrc_rfr_ctrl @ get addr of refresh reg ldr r5, [r6] @ get value mov r5, r5, lsr #8 @ isolate rfr field and drop burst cmp r0, #0x1 @ going to half speed? movne r9, #0x0 @ if up set flag up for pre up, hi volt blne voltage_shift_c @ adjust voltage cmp r0, #0x1 @ going to half speed (post branch link) moveq r5, r5, lsr #1 @ divide by 2 if to half movne r5, r5, lsl #1 @ mult by 2 if to full mov r5, r5, lsl #8 @ put rfr field back into place add r5, r5, #0x1 @ turn on burst of 1 ldr r4, omap243x_srs_cm_clksel2_pll @ get address of out reg ldr r3, [r4] @ get curr value orr r3, r3, #0x3 bic r3, r3, #0x3 @ clear lower bits orr r3, r3, r0 @ new state value str r3, [r4] @ set new state (pll/x, x=1 or 2) nop nop moveq r9, #0x1 @ if speed down, post down, drop volt bleq voltage_shift_c mcr p15, 0, r3, c7, c10, 4 @ memory barrier str r5, [r6] @ set new RFR_1 value add r6, r6, #0x30 @ get RFR_2 addr str r5, [r6] @ set RFR_2 nop cmp r2, #0x1 @ (SDR or DDR) do we need to adjust DLL bne freq_out @ leave if SDR, no DLL function /* With DDR, we need to take care of the DLL for the frequency change */ ldr r2, omap243x_srs_sdrc_dlla_ctrl @ addr of dlla ctrl str r1, [r2] @ write out new SDRC_DLLA_CTRL add r2, r2, #0x8 @ addr to SDRC_DLLB_CTRL str r1, [r2] @ commit to SDRC_DLLB_CTRL mov r1, #0x2000 @ wait DLL relock, min 0x400 L3 clocks dll_wait: subs r1, r1, #0x1 bne dll_wait freq_out: ldmfd sp!, {r0 - r10, pc} @ restore regs and return /* * shift up or down voltage, use R9 as input to tell level. * wait for it to finish, use 32k sync counter, 1tick=31uS. */ voltage_shift_c: ldr r10, omap243x_srs_prcm_voltctrl @ get addr of volt ctrl ldr r8, [r10] @ get value ldr r7, ddr_prcm_mask_val @ get value of mask and r8, r8, r7 @ apply mask to clear bits orr r8, r8, r9 @ bulld value for L0/L1-volt operation. str r8, [r10] @ set up for change. mov r7, #0x4000 @ get val for force orr r8, r8, r7 @ build value for force str r8, [r10] @ Force transition to L1 ldr r10, omap243x_srs_timer_32ksynct @ get addr of counter ldr r8, [r10] @ get value add r8, r8, #0x2 @ give it at most 62uS (min 31+) volt_delay_c: ldr r7, [r10] @ get timer value cmp r8, r7 @ time up? bhi volt_delay_c @ not yet->branch mov pc, lr @ back to caller omap243x_srs_cm_clksel2_pll: .word OMAP2430_CM_REGADDR(PLL_MOD, CM_CLKSEL2) omap243x_srs_sdrc_dlla_ctrl: .word OMAP243X_SDRC_REGADDR(SDRC_DLLA_CTRL) omap243x_srs_sdrc_rfr_ctrl: .word OMAP243X_SDRC_REGADDR(SDRC_RFR_CTRL_0) omap243x_srs_prcm_voltctrl: .word OMAP2430_PRCM_VOLTCTRL ddr_prcm_mask_val: .word 0xFFFF3FFC omap243x_srs_timer_32ksynct: .word OMAP2_L4_IO_ADDRESS(OMAP2430_32KSYNCT_BASE + 0x010) ENTRY(omap243x_sram_reprogram_sdrc_sz) .word . - omap243x_sram_reprogram_sdrc /* * Set dividers and pll. Also recalculate DLL value for DDR and unlock mode. */ .align 3 ENTRY(omap243x_sram_set_prcm) stmfd sp!, {r0-r12, lr} @ regs to stack adr r4, pbegin @ addr of preload start adr r8, pend @ addr of preload end mcrr p15, 1, r8, r4, c12 @ preload into icache pbegin: /* move into fast relock bypass */ ldr r8, omap243x_ssp_pll_ctl @ get addr ldr r5, [r8] @ get val mvn r6, #0x3 @ clear mask and r5, r5, r6 @ clear field orr r7, r5, #0x2 @ fast relock val str r7, [r8] @ go to fast relock ldr r4, omap243x_ssp_pll_stat @ addr of stat block: /* wait for bypass */ ldr r8, [r4] @ stat value and r8, r8, #0x3 @ mask for stat cmp r8, #0x1 @ there yet bne block @ loop if not /* set new dpll dividers _after_ in bypass */ ldr r4, omap243x_ssp_pll_div @ get addr str r0, [r4] @ set dpll ctrl val ldr r4, omap243x_ssp_set_config @ get addr mov r8, #1 @ valid cfg msk str r8, [r4] @ make dividers take mov r4, #100 @ dead spin a bit wait_a_bit: subs r4, r4, #1 @ dec loop bne wait_a_bit @ delay done? /* check if staying in bypass */ cmp r2, #0x1 @ stay in bypass? beq pend @ jump over dpll relock /* relock DPLL with new vals */ ldr r5, omap243x_ssp_pll_stat @ get addr ldr r4, omap243x_ssp_pll_ctl @ get addr orr r8, r7, #0x3 @ val for lock dpll str r8, [r4] @ set val mov r0, #1000 @ dead spin a bit wait_more: subs r0, r0, #1 @ dec loop bne wait_more @ delay done? wait_lock: ldr r8, [r5] @ get lock val and r8, r8, #3 @ isolate field cmp r8, #2 @ locked? bne wait_lock @ wait if not pend: /* update memory timings & briefly lock dll */ ldr r4, omap243x_ssp_sdrc_rfr @ get addr str r1, [r4] @ update refresh timing ldr r11, omap243x_ssp_dlla_ctrl @ get addr of DLLA ctrl ldr r10, [r11] @ get current val mvn r9, #0x4 @ mask to get clear bit2 and r10, r10, r9 @ clear bit2 for lock mode orr r10, r10, #0x8 @ make sure DLL on (es2 bit pos) str r10, [r11] @ commit to DLLA_CTRL add r11, r11, #0x8 @ move to dllb str r10, [r11] @ hit DLLB also mov r4, #0x800 @ relock time (min 0x400 L3 clocks) wait_dll_lock: subs r4, r4, #0x1 bne wait_dll_lock nop ldmfd sp!, {r0-r12, pc} @ restore regs and return omap243x_ssp_set_config: .word OMAP2430_PRCM_CLKCFG_CTRL omap243x_ssp_pll_ctl: .word OMAP2430_CM_REGADDR(PLL_MOD, CM_CLKEN) omap243x_ssp_pll_stat: .word OMAP2430_CM_REGADDR(PLL_MOD, CM_IDLEST) omap243x_ssp_pll_div: .word OMAP2430_CM_REGADDR(PLL_MOD, CM_CLKSEL1) omap243x_ssp_sdrc_rfr: .word OMAP243X_SDRC_REGADDR(SDRC_RFR_CTRL_0) omap243x_ssp_dlla_ctrl: .word OMAP243X_SDRC_REGADDR(SDRC_DLLA_CTRL) ENTRY(omap243x_sram_set_prcm_sz) .word . - omap243x_sram_set_prcm |