Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 /*
0003  * linux/arch/arm/mach-omap2/sram243x.S
0004  *
0005  * Omap2 specific functions that need to be run in internal SRAM
0006  *
0007  * (C) Copyright 2004
0008  * Texas Instruments, <www.ti.com>
0009  * Richard Woodruff <r-woodruff2@ti.com>
0010  *
0011  * Richard Woodruff notes that any changes to this code must be carefully
0012  * audited and tested to ensure that they don't cause a TLB miss while
0013  * the SDRAM is inaccessible.  Such a situation will crash the system
0014  * since it will cause the ARM MMU to attempt to walk the page tables.
0015  * These crashes may be intermittent.
0016  */
0017 #include <linux/linkage.h>
0018 
0019 #include <asm/assembler.h>
0020 
0021 #include "soc.h"
0022 #include "iomap.h"
0023 #include "prm2xxx.h"
0024 #include "cm2xxx.h"
0025 #include "sdrc.h"
0026 
0027     .text
0028 
0029     .align  3
0030 ENTRY(omap243x_sram_ddr_init)
0031     stmfd   sp!, {r0 - r12, lr} @ save registers on stack
0032 
0033     mov r12, r2         @ capture CS1 vs CS0
0034     mov r8, r3          @ capture force parameter
0035 
0036     /* frequency shift down */
0037     ldr r2, omap243x_sdi_cm_clksel2_pll @ get address of dpllout reg
0038     mov r3, #0x1        @ value for 1x operation
0039     str r3, [r2]        @ go to L1-freq operation
0040 
0041     /* voltage shift down */
0042     mov r9, #0x1            @ set up for L1 voltage call
0043     bl voltage_shift        @ go drop voltage
0044 
0045     /* dll lock mode */
0046     ldr r11, omap243x_sdi_sdrc_dlla_ctrl    @ addr of dlla ctrl
0047     ldr r10, [r11]      @ get current val
0048     cmp r12, #0x1       @ cs1 base (2422 es2.05/1)
0049     addeq   r11, r11, #0x8      @ if cs1 base, move to DLLB
0050     mvn r9, #0x4        @ mask to get clear bit2
0051     and r10, r10, r9        @ clear bit2 for lock mode.
0052     orr r10, r10, #0x8      @ make sure DLL on (es2 bit pos)
0053     orr r10, r10, #0x2      @ 90 degree phase for all below 133MHz
0054     str r10, [r11]      @ commit to DLLA_CTRL
0055     bl  i_dll_wait      @ wait for dll to lock
0056 
0057     /* get dll value */
0058     add r11, r11, #0x4      @ get addr of status reg
0059     ldr r10, [r11]      @ get locked value
0060 
0061     /* voltage shift up */
0062     mov r9, #0x0            @ shift back to L0-voltage
0063     bl voltage_shift        @ go raise voltage
0064 
0065     /* frequency shift up */
0066     mov r3, #0x2        @ value for 2x operation
0067     str r3, [r2]        @ go to L0-freq operation
0068 
0069     /* reset entry mode for dllctrl */
0070     sub r11, r11, #0x4      @ move from status to ctrl
0071     cmp r12, #0x1       @ normalize if cs1 based
0072     subeq   r11, r11, #0x8      @ possibly back to DLLA
0073     cmp r8, #0x1        @ if forced unlock exit
0074     orreq   r1, r1, #0x4        @ make sure exit with unlocked value
0075     str r1, [r11]       @ restore DLLA_CTRL high value
0076     add r11, r11, #0x8      @ move to DLLB_CTRL addr
0077     str r1, [r11]       @ set value DLLB_CTRL
0078     bl  i_dll_wait      @ wait for possible lock
0079 
0080     /* set up for return, DDR should be good */
0081     str r10, [r0]           @ write dll_status and return counter
0082     ldmfd   sp!, {r0 - r12, pc} @ restore regs and return
0083 
0084     /* ensure the DLL has relocked */
0085 i_dll_wait:
0086     mov r4, #0x800      @ delay DLL relock, min 0x400 L3 clocks
0087 i_dll_delay:
0088     subs    r4, r4, #0x1
0089     bne i_dll_delay
0090     ret lr
0091 
0092     /*
0093      * shift up or down voltage, use R9 as input to tell level.
0094      * wait for it to finish, use 32k sync counter, 1tick=31uS.
0095      */
0096 voltage_shift:
0097     ldr r4, omap243x_sdi_prcm_voltctrl  @ get addr of volt ctrl.
0098     ldr r5, [r4]        @ get value.
0099     ldr r6, prcm_mask_val   @ get value of mask
0100     and r5, r5, r6      @ apply mask to clear bits
0101     orr r5, r5, r9      @ bulld value for L0/L1-volt operation.
0102     str r5, [r4]        @ set up for change.
0103     mov r3, #0x4000     @ get val for force
0104     orr r5, r5, r3      @ build value for force
0105     str r5, [r4]        @ Force transition to L1
0106 
0107     ldr r3, omap243x_sdi_timer_32ksynct_cr  @ get addr of counter
0108     ldr r5, [r3]        @ get value
0109     add r5, r5, #0x3        @ give it at most 93uS
0110 volt_delay:
0111     ldr r7, [r3]        @ get timer value
0112     cmp r5, r7          @ time up?
0113     bhi volt_delay      @ not yet->branch
0114     ret lr          @ back to caller.
0115 
0116 omap243x_sdi_cm_clksel2_pll:
0117     .word OMAP2430_CM_REGADDR(PLL_MOD, CM_CLKSEL2)
0118 omap243x_sdi_sdrc_dlla_ctrl:
0119     .word OMAP243X_SDRC_REGADDR(SDRC_DLLA_CTRL)
0120 omap243x_sdi_prcm_voltctrl:
0121     .word OMAP2430_PRCM_VOLTCTRL
0122 prcm_mask_val:
0123     .word 0xFFFF3FFC
0124 omap243x_sdi_timer_32ksynct_cr:
0125     .word OMAP2_L4_IO_ADDRESS(OMAP2430_32KSYNCT_BASE + 0x010)
0126 ENTRY(omap243x_sram_ddr_init_sz)
0127     .word   . - omap243x_sram_ddr_init
0128 
0129 /*
0130  * Reprograms memory timings.
0131  * r0 = [PRCM_FULL | PRCM_HALF] r1 = SDRC_DLLA_CTRL value r2 = [DDR | SDR]
0132  * PRCM_FULL = 2, PRCM_HALF = 1, DDR = 1, SDR = 0
0133  */
0134     .align  3
0135 ENTRY(omap243x_sram_reprogram_sdrc)
0136     stmfd   sp!, {r0 - r10, lr} @ save registers on stack
0137     mov r3, #0x0        @ clear for mrc call
0138     mcr p15, 0, r3, c7, c10, 4  @ memory barrier, finish ARM SDR/DDR
0139     nop
0140     nop
0141     ldr r6, omap243x_srs_sdrc_rfr_ctrl  @ get addr of refresh reg
0142     ldr r5, [r6]        @ get value
0143     mov r5, r5, lsr #8      @ isolate rfr field and drop burst
0144 
0145     cmp r0, #0x1        @ going to half speed?
0146     movne   r9, #0x0        @ if up set flag up for pre up, hi volt
0147 
0148     blne    voltage_shift_c     @ adjust voltage
0149 
0150     cmp r0, #0x1        @ going to half speed (post branch link)
0151     moveq   r5, r5, lsr #1      @ divide by 2 if to half
0152     movne   r5, r5, lsl #1      @ mult by 2 if to full
0153     mov r5, r5, lsl #8      @ put rfr field back into place
0154     add r5, r5, #0x1        @ turn on burst of 1
0155     ldr r4, omap243x_srs_cm_clksel2_pll @ get address of out reg
0156     ldr r3, [r4]        @ get curr value
0157     orr r3, r3, #0x3
0158     bic r3, r3, #0x3        @ clear lower bits
0159     orr r3, r3, r0      @ new state value
0160     str r3, [r4]        @ set new state (pll/x, x=1 or 2)
0161     nop
0162     nop
0163 
0164     moveq   r9, #0x1        @ if speed down, post down, drop volt
0165     bleq    voltage_shift_c
0166 
0167     mcr p15, 0, r3, c7, c10, 4  @ memory barrier
0168     str r5, [r6]        @ set new RFR_1 value
0169     add r6, r6, #0x30       @ get RFR_2 addr
0170     str r5, [r6]        @ set RFR_2
0171     nop
0172     cmp r2, #0x1        @ (SDR or DDR) do we need to adjust DLL
0173     bne freq_out        @ leave if SDR, no DLL function
0174 
0175     /* With DDR, we need to take care of the DLL for the frequency change */
0176     ldr r2, omap243x_srs_sdrc_dlla_ctrl @ addr of dlla ctrl
0177     str r1, [r2]        @ write out new SDRC_DLLA_CTRL
0178     add r2, r2, #0x8        @ addr to SDRC_DLLB_CTRL
0179     str r1, [r2]        @ commit to SDRC_DLLB_CTRL
0180     mov r1, #0x2000     @ wait DLL relock, min 0x400 L3 clocks
0181 dll_wait:
0182     subs    r1, r1, #0x1
0183     bne dll_wait
0184 freq_out:
0185     ldmfd   sp!, {r0 - r10, pc} @ restore regs and return
0186 
0187     /*
0188      * shift up or down voltage, use R9 as input to tell level.
0189      *  wait for it to finish, use 32k sync counter, 1tick=31uS.
0190      */
0191 voltage_shift_c:
0192     ldr r10, omap243x_srs_prcm_voltctrl @ get addr of volt ctrl
0193     ldr r8, [r10]       @ get value
0194     ldr r7, ddr_prcm_mask_val   @ get value of mask
0195     and r8, r8, r7      @ apply mask to clear bits
0196     orr r8, r8, r9      @ bulld value for L0/L1-volt operation.
0197     str r8, [r10]       @ set up for change.
0198     mov r7, #0x4000     @ get val for force
0199     orr r8, r8, r7      @ build value for force
0200     str r8, [r10]       @ Force transition to L1
0201 
0202     ldr r10, omap243x_srs_timer_32ksynct    @ get addr of counter
0203     ldr r8, [r10]       @ get value
0204     add r8, r8, #0x2        @ give it at most 62uS (min 31+)
0205 volt_delay_c:
0206     ldr r7, [r10]       @ get timer value
0207     cmp r8, r7          @ time up?
0208     bhi volt_delay_c        @ not yet->branch
0209     ret lr          @ back to caller
0210 
0211 omap243x_srs_cm_clksel2_pll:
0212     .word OMAP2430_CM_REGADDR(PLL_MOD, CM_CLKSEL2)
0213 omap243x_srs_sdrc_dlla_ctrl:
0214     .word OMAP243X_SDRC_REGADDR(SDRC_DLLA_CTRL)
0215 omap243x_srs_sdrc_rfr_ctrl:
0216     .word OMAP243X_SDRC_REGADDR(SDRC_RFR_CTRL_0)
0217 omap243x_srs_prcm_voltctrl:
0218     .word OMAP2430_PRCM_VOLTCTRL
0219 ddr_prcm_mask_val:
0220     .word 0xFFFF3FFC
0221 omap243x_srs_timer_32ksynct:
0222     .word OMAP2_L4_IO_ADDRESS(OMAP2430_32KSYNCT_BASE + 0x010)
0223 
0224 ENTRY(omap243x_sram_reprogram_sdrc_sz)
0225     .word   . - omap243x_sram_reprogram_sdrc
0226 
0227 /*
0228  * Set dividers and pll. Also recalculate DLL value for DDR and unlock mode.
0229  */
0230     .align  3
0231 ENTRY(omap243x_sram_set_prcm)
0232     stmfd   sp!, {r0-r12, lr}   @ regs to stack
0233     adr r4, pbegin      @ addr of preload start
0234     adr r8, pend        @ addr of preload end
0235     mcrr    p15, 1, r8, r4, c12 @ preload into icache
0236 pbegin:
0237     /* move into fast relock bypass */
0238     ldr r8, omap243x_ssp_pll_ctl    @ get addr
0239     ldr r5, [r8]        @ get val
0240     mvn r6, #0x3        @ clear mask
0241     and r5, r5, r6      @ clear field
0242     orr r7, r5, #0x2        @ fast relock val
0243     str r7, [r8]        @ go to fast relock
0244     ldr r4, omap243x_ssp_pll_stat   @ addr of stat
0245 block:
0246     /* wait for bypass */
0247     ldr r8, [r4]        @ stat value
0248     and r8, r8, #0x3        @ mask for stat
0249     cmp r8, #0x1        @ there yet
0250     bne block           @ loop if not
0251 
0252     /* set new dpll dividers _after_ in bypass */
0253     ldr r4, omap243x_ssp_pll_div    @ get addr
0254     str r0, [r4]        @ set dpll ctrl val
0255 
0256     ldr r4, omap243x_ssp_set_config @ get addr
0257     mov r8, #1          @ valid cfg msk
0258     str r8, [r4]        @ make dividers take
0259 
0260     mov r4, #100        @ dead spin a bit
0261 wait_a_bit:
0262     subs    r4, r4, #1      @ dec loop
0263     bne wait_a_bit      @ delay done?
0264 
0265     /* check if staying in bypass */
0266     cmp r2, #0x1        @ stay in bypass?
0267     beq pend            @ jump over dpll relock
0268 
0269     /* relock DPLL with new vals */
0270     ldr r5, omap243x_ssp_pll_stat   @ get addr
0271     ldr r4, omap243x_ssp_pll_ctl    @ get addr
0272     orr r8, r7, #0x3        @ val for lock dpll
0273     str r8, [r4]        @ set val
0274     mov r0, #1000       @ dead spin a bit
0275 wait_more:
0276     subs    r0, r0, #1      @ dec loop
0277     bne wait_more       @ delay done?
0278 wait_lock:
0279     ldr r8, [r5]        @ get lock val
0280     and r8, r8, #3      @ isolate field
0281     cmp r8, #2          @ locked?
0282     bne wait_lock       @ wait if not
0283 pend:
0284     /* update memory timings & briefly lock dll */
0285     ldr r4, omap243x_ssp_sdrc_rfr   @ get addr
0286     str r1, [r4]        @ update refresh timing
0287     ldr r11, omap243x_ssp_dlla_ctrl @ get addr of DLLA ctrl
0288     ldr r10, [r11]      @ get current val
0289     mvn r9, #0x4        @ mask to get clear bit2
0290     and r10, r10, r9        @ clear bit2 for lock mode
0291     orr r10, r10, #0x8      @ make sure DLL on (es2 bit pos)
0292     str r10, [r11]      @ commit to DLLA_CTRL
0293     add r11, r11, #0x8      @ move to dllb
0294     str r10, [r11]      @ hit DLLB also
0295 
0296     mov r4, #0x800      @ relock time (min 0x400 L3 clocks)
0297 wait_dll_lock:
0298     subs    r4, r4, #0x1
0299     bne wait_dll_lock
0300     nop
0301     ldmfd   sp!, {r0-r12, pc}   @ restore regs and return
0302 
0303 omap243x_ssp_set_config:
0304     .word OMAP2430_PRCM_CLKCFG_CTRL
0305 omap243x_ssp_pll_ctl:
0306     .word OMAP2430_CM_REGADDR(PLL_MOD, CM_CLKEN)
0307 omap243x_ssp_pll_stat:
0308     .word OMAP2430_CM_REGADDR(PLL_MOD, CM_IDLEST)
0309 omap243x_ssp_pll_div:
0310     .word OMAP2430_CM_REGADDR(PLL_MOD, CM_CLKSEL1)
0311 omap243x_ssp_sdrc_rfr:
0312     .word OMAP243X_SDRC_REGADDR(SDRC_RFR_CTRL_0)
0313 omap243x_ssp_dlla_ctrl:
0314     .word OMAP243X_SDRC_REGADDR(SDRC_DLLA_CTRL)
0315 
0316 ENTRY(omap243x_sram_set_prcm_sz)
0317     .word   . - omap243x_sram_set_prcm