linux/arch/arm/mach-omap2/sram34xx.S

186 lines
5.1 KiB
ArmAsm
Raw Normal View History

/*
* linux/arch/arm/mach-omap3/sram.S
*
* Omap3 specific functions that need to be run in internal SRAM
*
* (C) Copyright 2007
* Texas Instruments Inc.
* Rajendra Nayak <rnayak@ti.com>
*
* (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
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
#include <mach/hardware.h>
#include <mach/io.h>
#include "sdrc.h"
#include "cm.h"
.text
/*
* Change frequency of core dpll
* r0 = sdrc_rfr_ctrl r1 = sdrc_actim_ctrla r2 = sdrc_actim_ctrlb r3 = M2
* r4 = Unlock SDRC DLL? (1 = yes, 0 = no) -- only unlock DLL for
* SDRC rates < 83MHz
* r5 = number of MPU cycles to wait for SDRC to stabilize after
* reprogramming the SDRC when switching to a slower MPU speed
* r6 = SDRC_MR_0 register value
*
*/
ENTRY(omap3_sram_configure_core_dpll)
stmfd sp!, {r1-r12, lr} @ store regs to stack
ldr r4, [sp, #52] @ pull extra args off the stack
ldr r5, [sp, #56] @ load extra args from the stack
ldr r6, [sp, #60] @ load extra args from the stack
OMAP3 SRAM: add ARM barriers to omap3_sram_configure_core_dpll Add more barriers in the SRAM CORE DPLL M2 divider change code. - Add a DSB SY after the function's entry point to flush all cached and buffered writes and wait for the interconnect to claim that they have completed[1]. The idea here is to force all delayed write traffic going to the SDRAM to at least post to the L3 interconnect before continuing. If these writes are allowed to occur after the SDRC is idled, the writes will not be acknowledged and the ARM will stall. Note that in this case, it does not matter if the writes actually complete to the SDRAM - it is only necessary for the writes to leave the ARM itself. If the writes are posted by the interconnect when the SDRC goes into idle, the writes will be delayed until the SDRC returns from idle[2]. If the SDRC is in the middle of a write when it is requested to enter idle, the SDRC will not acknowledge the idle request until the writes complete to the SDRAM.[3] The old-style DMB in sdram_in_selfrefresh is now superfluous, so, remove it. - Add an ISB before the function's exit point to prevent the ARM from speculatively executing into SDRAM before the SDRAM is enabled[4]. ... 1. ARMv7 ARM (DDI 0406A) A3-47, A3-48. 2. Private communication with Richard Woodruff <r-woodruff2@ti.com>. 3. Private communication with Richard Woodruff <r-woodruff2@ti.com>. 4. ARMv7 ARM (DDI 0406A) A3-48. Signed-off-by: Paul Walmsley <paul@pwsan.com> Cc: Richard Woodruff <r-woodruff2@ti.com>
2009-05-13 07:27:09 +08:00
dsb @ flush buffered writes to interconnect
cmp r3, #0x2
blne configure_sdrc
cmp r4, #0x1
bleq unlock_dll
blne lock_dll
bl sdram_in_selfrefresh @ put the SDRAM in self refresh
bl configure_core_dpll
bl enable_sdrc
cmp r4, #0x1
bleq wait_dll_unlock
blne wait_dll_lock
cmp r3, #0x1
beq return_to_sdram
bl configure_sdrc
mov r12, r5 @ if slowing, wait for SDRC to stabilize
bl wait_clk_stable
return_to_sdram:
OMAP3 SRAM: add ARM barriers to omap3_sram_configure_core_dpll Add more barriers in the SRAM CORE DPLL M2 divider change code. - Add a DSB SY after the function's entry point to flush all cached and buffered writes and wait for the interconnect to claim that they have completed[1]. The idea here is to force all delayed write traffic going to the SDRAM to at least post to the L3 interconnect before continuing. If these writes are allowed to occur after the SDRC is idled, the writes will not be acknowledged and the ARM will stall. Note that in this case, it does not matter if the writes actually complete to the SDRAM - it is only necessary for the writes to leave the ARM itself. If the writes are posted by the interconnect when the SDRC goes into idle, the writes will be delayed until the SDRC returns from idle[2]. If the SDRC is in the middle of a write when it is requested to enter idle, the SDRC will not acknowledge the idle request until the writes complete to the SDRAM.[3] The old-style DMB in sdram_in_selfrefresh is now superfluous, so, remove it. - Add an ISB before the function's exit point to prevent the ARM from speculatively executing into SDRAM before the SDRAM is enabled[4]. ... 1. ARMv7 ARM (DDI 0406A) A3-47, A3-48. 2. Private communication with Richard Woodruff <r-woodruff2@ti.com>. 3. Private communication with Richard Woodruff <r-woodruff2@ti.com>. 4. ARMv7 ARM (DDI 0406A) A3-48. Signed-off-by: Paul Walmsley <paul@pwsan.com> Cc: Richard Woodruff <r-woodruff2@ti.com>
2009-05-13 07:27:09 +08:00
isb @ prevent speculative exec past here
mov r0, #0 @ return value
ldmfd sp!, {r1-r12, pc} @ restore regs and return
unlock_dll:
ldr r11, omap3_sdrc_dlla_ctrl
ldr r12, [r11]
orr r12, r12, #0x4
str r12, [r11] @ (no OCP barrier needed)
bx lr
lock_dll:
ldr r11, omap3_sdrc_dlla_ctrl
ldr r12, [r11]
bic r12, r12, #0x4
str r12, [r11] @ (no OCP barrier needed)
bx lr
sdram_in_selfrefresh:
ldr r11, omap3_sdrc_power @ read the SDRC_POWER register
ldr r12, [r11] @ read the contents of SDRC_POWER
mov r9, r12 @ keep a copy of SDRC_POWER bits
orr r12, r12, #0x40 @ enable self refresh on idle req
bic r12, r12, #0x4 @ clear PWDENA
str r12, [r11] @ write back to SDRC_POWER register
ldr r12, [r11] @ posted-write barrier for SDRC
ldr r11, omap3_cm_iclken1_core @ read the CM_ICLKEN1_CORE reg
ldr r12, [r11]
bic r12, r12, #0x2 @ disable iclk bit for SDRC
str r12, [r11]
wait_sdrc_idle:
ldr r11, omap3_cm_idlest1_core
ldr r12, [r11]
and r12, r12, #0x2 @ check for SDRC idle
cmp r12, #2
bne wait_sdrc_idle
bx lr
configure_core_dpll:
ldr r11, omap3_cm_clksel1_pll
ldr r12, [r11]
ldr r10, core_m2_mask_val @ modify m2 for core dpll
and r12, r12, r10
orr r12, r12, r3, lsl #0x1B @ r3 contains the M2 val
str r12, [r11]
ldr r12, [r11] @ posted-write barrier for CM
bx lr
wait_clk_stable:
subs r12, r12, #1
bne wait_clk_stable
bx lr
enable_sdrc:
ldr r11, omap3_cm_iclken1_core
ldr r12, [r11]
orr r12, r12, #0x2 @ enable iclk bit for SDRC
str r12, [r11]
wait_sdrc_idle1:
ldr r11, omap3_cm_idlest1_core
ldr r12, [r11]
and r12, r12, #0x2
cmp r12, #0
bne wait_sdrc_idle1
restore_sdrc_power_val:
ldr r11, omap3_sdrc_power
str r9, [r11] @ restore SDRC_POWER, no barrier needed
bx lr
wait_dll_lock:
ldr r11, omap3_sdrc_dlla_status
ldr r12, [r11]
and r12, r12, #0x4
cmp r12, #0x4
bne wait_dll_lock
bx lr
wait_dll_unlock:
ldr r11, omap3_sdrc_dlla_status
ldr r12, [r11]
and r12, r12, #0x4
cmp r12, #0x0
bne wait_dll_unlock
bx lr
configure_sdrc:
ldr r11, omap3_sdrc_rfr_ctrl
str r0, [r11]
ldr r11, omap3_sdrc_actim_ctrla
str r1, [r11]
ldr r11, omap3_sdrc_actim_ctrlb
str r2, [r11]
ldr r11, omap3_sdrc_mr_0
str r6, [r11]
ldr r6, [r11] @ posted-write barrier for SDRC
bx lr
omap3_sdrc_power:
.word OMAP34XX_SDRC_REGADDR(SDRC_POWER)
omap3_cm_clksel1_pll:
.word OMAP34XX_CM_REGADDR(PLL_MOD, CM_CLKSEL1)
omap3_cm_idlest1_core:
.word OMAP34XX_CM_REGADDR(CORE_MOD, CM_IDLEST)
omap3_cm_iclken1_core:
.word OMAP34XX_CM_REGADDR(CORE_MOD, CM_ICLKEN1)
omap3_sdrc_rfr_ctrl:
.word OMAP34XX_SDRC_REGADDR(SDRC_RFR_CTRL_0)
omap3_sdrc_actim_ctrla:
.word OMAP34XX_SDRC_REGADDR(SDRC_ACTIM_CTRL_A_0)
omap3_sdrc_actim_ctrlb:
.word OMAP34XX_SDRC_REGADDR(SDRC_ACTIM_CTRL_B_0)
omap3_sdrc_mr_0:
.word OMAP34XX_SDRC_REGADDR(SDRC_MR_0)
omap3_sdrc_dlla_status:
.word OMAP34XX_SDRC_REGADDR(SDRC_DLLA_STATUS)
omap3_sdrc_dlla_ctrl:
.word OMAP34XX_SDRC_REGADDR(SDRC_DLLA_CTRL)
core_m2_mask_val:
.word 0x07FFFFFF
ENTRY(omap3_sram_configure_core_dpll_sz)
.word . - omap3_sram_configure_core_dpll