xref: /linux/drivers/memory/ti-emif-sram-pm.S (revision cdd5b5a9761fd66d17586e4f4ba6588c70e640ea)
12aec85b2SThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */
28428e5adSDave Gerlach/*
38428e5adSDave Gerlach * Low level PM code for TI EMIF
48428e5adSDave Gerlach *
58428e5adSDave Gerlach * Copyright (C) 2016-2017 Texas Instruments Incorporated - http://www.ti.com/
68428e5adSDave Gerlach *	Dave Gerlach
78428e5adSDave Gerlach */
88428e5adSDave Gerlach
98428e5adSDave Gerlach#include <linux/linkage.h>
108428e5adSDave Gerlach#include <asm/assembler.h>
11*a9ff6961SLinus Walleij#include <asm/page.h>
128428e5adSDave Gerlach
138428e5adSDave Gerlach#include "emif.h"
14eef58fddSMasahiro Yamada#include "ti-emif-asm-offsets.h"
158428e5adSDave Gerlach
168428e5adSDave Gerlach#define EMIF_POWER_MGMT_WAIT_SELF_REFRESH_8192_CYCLES	0x00a0
178428e5adSDave Gerlach#define EMIF_POWER_MGMT_SR_TIMER_MASK			0x00f0
188428e5adSDave Gerlach#define EMIF_POWER_MGMT_SELF_REFRESH_MODE		0x0200
198428e5adSDave Gerlach#define EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK		0x0700
208428e5adSDave Gerlach
218428e5adSDave Gerlach#define EMIF_SDCFG_TYPE_DDR2				0x2 << SDRAM_TYPE_SHIFT
226c110561SDave Gerlach#define EMIF_SDCFG_TYPE_DDR3				0x3 << SDRAM_TYPE_SHIFT
238428e5adSDave Gerlach#define EMIF_STATUS_READY				0x4
248428e5adSDave Gerlach
258428e5adSDave Gerlach#define AM43XX_EMIF_PHY_CTRL_REG_COUNT                  0x120
268428e5adSDave Gerlach
278428e5adSDave Gerlach#define EMIF_AM437X_REGISTERS				0x1
288428e5adSDave Gerlach
298428e5adSDave Gerlach	.arm
308428e5adSDave Gerlach	.align 3
31a2faac39SNick Desaulniers	.arch armv7-a
328428e5adSDave Gerlach
338428e5adSDave GerlachENTRY(ti_emif_sram)
348428e5adSDave Gerlach
358428e5adSDave Gerlach/*
368428e5adSDave Gerlach * void ti_emif_save_context(void)
378428e5adSDave Gerlach *
388428e5adSDave Gerlach * Used during suspend to save the context of all required EMIF registers
398428e5adSDave Gerlach * to local memory if the EMIF is going to lose context during the sleep
408428e5adSDave Gerlach * transition. Operates on the VIRTUAL address of the EMIF.
418428e5adSDave Gerlach */
428428e5adSDave GerlachENTRY(ti_emif_save_context)
438428e5adSDave Gerlach	stmfd   sp!, {r4 - r11, lr}     @ save registers on stack
448428e5adSDave Gerlach
458428e5adSDave Gerlach	adr	r4, ti_emif_pm_sram_data
468428e5adSDave Gerlach	ldr	r0, [r4, #EMIF_PM_BASE_ADDR_VIRT_OFFSET]
478428e5adSDave Gerlach	ldr	r2, [r4, #EMIF_PM_REGS_VIRT_OFFSET]
488428e5adSDave Gerlach
498428e5adSDave Gerlach	/* Save EMIF configuration */
508428e5adSDave Gerlach	ldr	r1, [r0, #EMIF_SDRAM_CONFIG]
518428e5adSDave Gerlach	str	r1, [r2, #EMIF_SDCFG_VAL_OFFSET]
528428e5adSDave Gerlach
538428e5adSDave Gerlach	ldr	r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL]
548428e5adSDave Gerlach	str	r1, [r2, #EMIF_REF_CTRL_VAL_OFFSET]
558428e5adSDave Gerlach
568428e5adSDave Gerlach	ldr	r1, [r0, #EMIF_SDRAM_TIMING_1]
578428e5adSDave Gerlach	str     r1, [r2, #EMIF_TIMING1_VAL_OFFSET]
588428e5adSDave Gerlach
598428e5adSDave Gerlach	ldr	r1, [r0, #EMIF_SDRAM_TIMING_2]
608428e5adSDave Gerlach	str     r1, [r2, #EMIF_TIMING2_VAL_OFFSET]
618428e5adSDave Gerlach
628428e5adSDave Gerlach	ldr	r1, [r0, #EMIF_SDRAM_TIMING_3]
638428e5adSDave Gerlach	str     r1, [r2, #EMIF_TIMING3_VAL_OFFSET]
648428e5adSDave Gerlach
658428e5adSDave Gerlach	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
668428e5adSDave Gerlach	str     r1, [r2, #EMIF_PMCR_VAL_OFFSET]
678428e5adSDave Gerlach
688428e5adSDave Gerlach	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
698428e5adSDave Gerlach	str     r1, [r2, #EMIF_PMCR_SHDW_VAL_OFFSET]
708428e5adSDave Gerlach
718428e5adSDave Gerlach	ldr	r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG]
728428e5adSDave Gerlach	str     r1, [r2, #EMIF_ZQCFG_VAL_OFFSET]
738428e5adSDave Gerlach
748428e5adSDave Gerlach	ldr	r1, [r0, #EMIF_DDR_PHY_CTRL_1]
758428e5adSDave Gerlach	str     r1, [r2, #EMIF_DDR_PHY_CTLR_1_OFFSET]
768428e5adSDave Gerlach
778428e5adSDave Gerlach	ldr	r1, [r0, #EMIF_COS_CONFIG]
788428e5adSDave Gerlach	str     r1, [r2, #EMIF_COS_CONFIG_OFFSET]
798428e5adSDave Gerlach
808428e5adSDave Gerlach	ldr	r1, [r0, #EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING]
818428e5adSDave Gerlach	str     r1, [r2, #EMIF_PRIORITY_TO_COS_MAPPING_OFFSET]
828428e5adSDave Gerlach
838428e5adSDave Gerlach	ldr	r1, [r0, #EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING]
848428e5adSDave Gerlach	str     r1, [r2, #EMIF_CONNECT_ID_SERV_1_MAP_OFFSET]
858428e5adSDave Gerlach
868428e5adSDave Gerlach	ldr	r1, [r0, #EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING]
878428e5adSDave Gerlach	str     r1, [r2, #EMIF_CONNECT_ID_SERV_2_MAP_OFFSET]
888428e5adSDave Gerlach
898428e5adSDave Gerlach	ldr	r1, [r0, #EMIF_OCP_CONFIG]
908428e5adSDave Gerlach	str     r1, [r2, #EMIF_OCP_CONFIG_VAL_OFFSET]
918428e5adSDave Gerlach
928428e5adSDave Gerlach	ldr	r5, [r4, #EMIF_PM_CONFIG_OFFSET]
938428e5adSDave Gerlach	cmp	r5, #EMIF_SRAM_AM43_REG_LAYOUT
948428e5adSDave Gerlach	bne	emif_skip_save_extra_regs
958428e5adSDave Gerlach
968428e5adSDave Gerlach	ldr	r1, [r0, #EMIF_READ_WRITE_LEVELING_RAMP_CONTROL]
978428e5adSDave Gerlach	str     r1, [r2, #EMIF_RD_WR_LEVEL_RAMP_CTRL_OFFSET]
988428e5adSDave Gerlach
998428e5adSDave Gerlach	ldr	r1, [r0, #EMIF_READ_WRITE_EXECUTION_THRESHOLD]
1008428e5adSDave Gerlach	str     r1, [r2, #EMIF_RD_WR_EXEC_THRESH_OFFSET]
1018428e5adSDave Gerlach
1028428e5adSDave Gerlach	ldr	r1, [r0, #EMIF_LPDDR2_NVM_TIMING]
1038428e5adSDave Gerlach	str     r1, [r2, #EMIF_LPDDR2_NVM_TIM_OFFSET]
1048428e5adSDave Gerlach
1058428e5adSDave Gerlach	ldr	r1, [r0, #EMIF_LPDDR2_NVM_TIMING_SHDW]
1068428e5adSDave Gerlach	str     r1, [r2, #EMIF_LPDDR2_NVM_TIM_SHDW_OFFSET]
1078428e5adSDave Gerlach
1088428e5adSDave Gerlach	ldr	r1, [r0, #EMIF_DLL_CALIB_CTRL]
1098428e5adSDave Gerlach	str     r1, [r2, #EMIF_DLL_CALIB_CTRL_VAL_OFFSET]
1108428e5adSDave Gerlach
1118428e5adSDave Gerlach	ldr	r1, [r0, #EMIF_DLL_CALIB_CTRL_SHDW]
1128428e5adSDave Gerlach	str     r1, [r2, #EMIF_DLL_CALIB_CTRL_VAL_SHDW_OFFSET]
1138428e5adSDave Gerlach
1148428e5adSDave Gerlach	/* Loop and save entire block of emif phy regs */
1158428e5adSDave Gerlach	mov	r5, #0x0
1168428e5adSDave Gerlach	add	r4, r2, #EMIF_EXT_PHY_CTRL_VALS_OFFSET
1178428e5adSDave Gerlach	add	r3, r0, #EMIF_EXT_PHY_CTRL_1
1188428e5adSDave Gerlachddr_phy_ctrl_save:
1198428e5adSDave Gerlach	ldr	r1, [r3, r5]
1208428e5adSDave Gerlach	str	r1, [r4, r5]
1218428e5adSDave Gerlach	add	r5, r5, #0x4
1228428e5adSDave Gerlach	cmp	r5, #AM43XX_EMIF_PHY_CTRL_REG_COUNT
1238428e5adSDave Gerlach	bne	ddr_phy_ctrl_save
1248428e5adSDave Gerlach
1258428e5adSDave Gerlachemif_skip_save_extra_regs:
1268428e5adSDave Gerlach	ldmfd	sp!, {r4 - r11, pc}	@ restore regs and return
1278428e5adSDave GerlachENDPROC(ti_emif_save_context)
1288428e5adSDave Gerlach
1298428e5adSDave Gerlach/*
1308428e5adSDave Gerlach * void ti_emif_restore_context(void)
1318428e5adSDave Gerlach *
1328428e5adSDave Gerlach * Used during resume to restore the context of all required EMIF registers
1338428e5adSDave Gerlach * from local memory after the EMIF has lost context during a sleep transition.
1348428e5adSDave Gerlach * Operates on the PHYSICAL address of the EMIF.
1358428e5adSDave Gerlach */
1368428e5adSDave GerlachENTRY(ti_emif_restore_context)
1378428e5adSDave Gerlach	adr	r4, ti_emif_pm_sram_data
1388428e5adSDave Gerlach	ldr	r0, [r4, #EMIF_PM_BASE_ADDR_PHYS_OFFSET]
1398428e5adSDave Gerlach	ldr	r2, [r4, #EMIF_PM_REGS_PHYS_OFFSET]
1408428e5adSDave Gerlach
1418428e5adSDave Gerlach	/* Config EMIF Timings */
1428428e5adSDave Gerlach	ldr     r1, [r2, #EMIF_DDR_PHY_CTLR_1_OFFSET]
1438428e5adSDave Gerlach	str	r1, [r0, #EMIF_DDR_PHY_CTRL_1]
1448428e5adSDave Gerlach	str	r1, [r0, #EMIF_DDR_PHY_CTRL_1_SHDW]
1458428e5adSDave Gerlach
1468428e5adSDave Gerlach	ldr     r1, [r2, #EMIF_TIMING1_VAL_OFFSET]
1478428e5adSDave Gerlach	str	r1, [r0, #EMIF_SDRAM_TIMING_1]
1488428e5adSDave Gerlach	str	r1, [r0, #EMIF_SDRAM_TIMING_1_SHDW]
1498428e5adSDave Gerlach
1508428e5adSDave Gerlach	ldr     r1, [r2, #EMIF_TIMING2_VAL_OFFSET]
1518428e5adSDave Gerlach	str	r1, [r0, #EMIF_SDRAM_TIMING_2]
1528428e5adSDave Gerlach	str	r1, [r0, #EMIF_SDRAM_TIMING_2_SHDW]
1538428e5adSDave Gerlach
1548428e5adSDave Gerlach	ldr     r1, [r2, #EMIF_TIMING3_VAL_OFFSET]
1558428e5adSDave Gerlach	str	r1, [r0, #EMIF_SDRAM_TIMING_3]
1568428e5adSDave Gerlach	str	r1, [r0, #EMIF_SDRAM_TIMING_3_SHDW]
1578428e5adSDave Gerlach
1588428e5adSDave Gerlach	ldr     r1, [r2, #EMIF_REF_CTRL_VAL_OFFSET]
1598428e5adSDave Gerlach	str	r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL]
1608428e5adSDave Gerlach	str	r1, [r0, #EMIF_SDRAM_REFRESH_CTRL_SHDW]
1618428e5adSDave Gerlach
1628428e5adSDave Gerlach	ldr     r1, [r2, #EMIF_PMCR_VAL_OFFSET]
1638428e5adSDave Gerlach	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
1648428e5adSDave Gerlach
1658428e5adSDave Gerlach	ldr     r1, [r2, #EMIF_PMCR_SHDW_VAL_OFFSET]
1668428e5adSDave Gerlach	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
1678428e5adSDave Gerlach
1688428e5adSDave Gerlach	ldr     r1, [r2, #EMIF_COS_CONFIG_OFFSET]
1698428e5adSDave Gerlach	str	r1, [r0, #EMIF_COS_CONFIG]
1708428e5adSDave Gerlach
1718428e5adSDave Gerlach	ldr     r1, [r2, #EMIF_PRIORITY_TO_COS_MAPPING_OFFSET]
1728428e5adSDave Gerlach	str	r1, [r0, #EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING]
1738428e5adSDave Gerlach
1748428e5adSDave Gerlach	ldr	r1, [r2, #EMIF_CONNECT_ID_SERV_1_MAP_OFFSET]
1758428e5adSDave Gerlach	str	r1, [r0, #EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING]
1768428e5adSDave Gerlach
1778428e5adSDave Gerlach	ldr     r1, [r2, #EMIF_CONNECT_ID_SERV_2_MAP_OFFSET]
1788428e5adSDave Gerlach	str	r1, [r0, #EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING]
1798428e5adSDave Gerlach
1808428e5adSDave Gerlach	ldr     r1, [r2, #EMIF_OCP_CONFIG_VAL_OFFSET]
1818428e5adSDave Gerlach	str	r1, [r0, #EMIF_OCP_CONFIG]
1828428e5adSDave Gerlach
1838428e5adSDave Gerlach	ldr	r5, [r4, #EMIF_PM_CONFIG_OFFSET]
1848428e5adSDave Gerlach	cmp	r5, #EMIF_SRAM_AM43_REG_LAYOUT
1858428e5adSDave Gerlach	bne	emif_skip_restore_extra_regs
1868428e5adSDave Gerlach
1878428e5adSDave Gerlach	ldr     r1, [r2, #EMIF_RD_WR_LEVEL_RAMP_CTRL_OFFSET]
1888428e5adSDave Gerlach	str	r1, [r0, #EMIF_READ_WRITE_LEVELING_RAMP_CONTROL]
1898428e5adSDave Gerlach
1908428e5adSDave Gerlach	ldr     r1, [r2, #EMIF_RD_WR_EXEC_THRESH_OFFSET]
1918428e5adSDave Gerlach	str	r1, [r0, #EMIF_READ_WRITE_EXECUTION_THRESHOLD]
1928428e5adSDave Gerlach
1938428e5adSDave Gerlach	ldr     r1, [r2, #EMIF_LPDDR2_NVM_TIM_OFFSET]
1948428e5adSDave Gerlach	str	r1, [r0, #EMIF_LPDDR2_NVM_TIMING]
1958428e5adSDave Gerlach
1968428e5adSDave Gerlach	ldr     r1, [r2, #EMIF_LPDDR2_NVM_TIM_SHDW_OFFSET]
1978428e5adSDave Gerlach	str	r1, [r0, #EMIF_LPDDR2_NVM_TIMING_SHDW]
1988428e5adSDave Gerlach
1998428e5adSDave Gerlach	ldr     r1, [r2, #EMIF_DLL_CALIB_CTRL_VAL_OFFSET]
2008428e5adSDave Gerlach	str	r1, [r0, #EMIF_DLL_CALIB_CTRL]
2018428e5adSDave Gerlach
2028428e5adSDave Gerlach	ldr     r1, [r2, #EMIF_DLL_CALIB_CTRL_VAL_SHDW_OFFSET]
2038428e5adSDave Gerlach	str	r1, [r0, #EMIF_DLL_CALIB_CTRL_SHDW]
2048428e5adSDave Gerlach
2058428e5adSDave Gerlach	ldr     r1, [r2, #EMIF_ZQCFG_VAL_OFFSET]
2068428e5adSDave Gerlach	str	r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG]
2078428e5adSDave Gerlach
2088428e5adSDave Gerlach	/* Loop and restore entire block of emif phy regs */
2098428e5adSDave Gerlach	mov	r5, #0x0
2108428e5adSDave Gerlach	/* Load ti_emif_regs_amx3 + EMIF_EXT_PHY_CTRL_VALS_OFFSET for address
2118428e5adSDave Gerlach	 * to phy register save space
2128428e5adSDave Gerlach	 */
2138428e5adSDave Gerlach	add	r3, r2, #EMIF_EXT_PHY_CTRL_VALS_OFFSET
2148428e5adSDave Gerlach	add	r4, r0, #EMIF_EXT_PHY_CTRL_1
2158428e5adSDave Gerlachddr_phy_ctrl_restore:
2168428e5adSDave Gerlach	ldr	r1, [r3, r5]
2178428e5adSDave Gerlach	str	r1, [r4, r5]
2188428e5adSDave Gerlach	add	r5, r5, #0x4
2198428e5adSDave Gerlach	cmp	r5, #AM43XX_EMIF_PHY_CTRL_REG_COUNT
2208428e5adSDave Gerlach	bne	ddr_phy_ctrl_restore
2218428e5adSDave Gerlach
2228428e5adSDave Gerlachemif_skip_restore_extra_regs:
2238428e5adSDave Gerlach	/*
2248428e5adSDave Gerlach	 * Output impedence calib needed only for DDR3
2258428e5adSDave Gerlach	 * but since the initial state of this will be
2268428e5adSDave Gerlach	 * disabled for DDR2 no harm in restoring the
2278428e5adSDave Gerlach	 * old configuration
2288428e5adSDave Gerlach	 */
2298428e5adSDave Gerlach	ldr     r1, [r2, #EMIF_ZQCFG_VAL_OFFSET]
2308428e5adSDave Gerlach	str	r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG]
2318428e5adSDave Gerlach
2328428e5adSDave Gerlach	/* Write to sdcfg last for DDR2 only */
2338428e5adSDave Gerlach	ldr	r1, [r2, #EMIF_SDCFG_VAL_OFFSET]
2348428e5adSDave Gerlach	and	r2, r1, #SDRAM_TYPE_MASK
2358428e5adSDave Gerlach	cmp	r2, #EMIF_SDCFG_TYPE_DDR2
2368428e5adSDave Gerlach	streq	r1, [r0, #EMIF_SDRAM_CONFIG]
2378428e5adSDave Gerlach
2388428e5adSDave Gerlach	mov	pc, lr
2398428e5adSDave GerlachENDPROC(ti_emif_restore_context)
2408428e5adSDave Gerlach
2418428e5adSDave Gerlach/*
2426c110561SDave Gerlach * void ti_emif_run_hw_leveling(void)
2436c110561SDave Gerlach *
2446c110561SDave Gerlach * Used during resume to run hardware leveling again and restore the
2456c110561SDave Gerlach * configuration of the EMIF PHY, only for DDR3.
2466c110561SDave Gerlach */
2476c110561SDave GerlachENTRY(ti_emif_run_hw_leveling)
2486c110561SDave Gerlach	adr	r4, ti_emif_pm_sram_data
2496c110561SDave Gerlach	ldr	r0, [r4, #EMIF_PM_BASE_ADDR_PHYS_OFFSET]
2506c110561SDave Gerlach
2516c110561SDave Gerlach	ldr	r3, [r0, #EMIF_READ_WRITE_LEVELING_CONTROL]
2526c110561SDave Gerlach	orr	r3, r3, #RDWRLVLFULL_START
2536c110561SDave Gerlach	ldr	r2, [r0, #EMIF_SDRAM_CONFIG]
2546c110561SDave Gerlach	and	r2, r2, #SDRAM_TYPE_MASK
2556c110561SDave Gerlach	cmp	r2, #EMIF_SDCFG_TYPE_DDR3
2566c110561SDave Gerlach	bne	skip_hwlvl
2576c110561SDave Gerlach
2586c110561SDave Gerlach	str	r3, [r0, #EMIF_READ_WRITE_LEVELING_CONTROL]
2596c110561SDave Gerlach
2606c110561SDave Gerlach	/*
2616c110561SDave Gerlach	 * If EMIF registers are touched during initial stage of HW
2626c110561SDave Gerlach	 * leveling sequence there will be an L3 NOC timeout error issued
2636c110561SDave Gerlach	 * as the EMIF will not respond, which is not fatal, but it is
2646c110561SDave Gerlach	 * avoidable. This small wait loop is enough time for this condition
2656c110561SDave Gerlach	 * to clear, even at worst case of CPU running at max speed of 1Ghz.
2666c110561SDave Gerlach	 */
2676c110561SDave Gerlach	mov	r2, #0x2000
2686c110561SDave Gerlach1:
2696c110561SDave Gerlach	subs	r2, r2, #0x1
2706c110561SDave Gerlach	bne	1b
2716c110561SDave Gerlach
2726c110561SDave Gerlach	/* Bit clears when operation is complete */
2736c110561SDave Gerlach2:	ldr     r1, [r0, #EMIF_READ_WRITE_LEVELING_CONTROL]
2746c110561SDave Gerlach	tst     r1, #RDWRLVLFULL_START
2756c110561SDave Gerlach	bne     2b
2766c110561SDave Gerlach
2776c110561SDave Gerlachskip_hwlvl:
2786c110561SDave Gerlach	mov	pc, lr
2796c110561SDave GerlachENDPROC(ti_emif_run_hw_leveling)
2806c110561SDave Gerlach
2816c110561SDave Gerlach/*
2828428e5adSDave Gerlach * void ti_emif_enter_sr(void)
2838428e5adSDave Gerlach *
2848428e5adSDave Gerlach * Programs the EMIF to tell the SDRAM to enter into self-refresh
2858428e5adSDave Gerlach * mode during a sleep transition. Operates on the VIRTUAL address
2868428e5adSDave Gerlach * of the EMIF.
2878428e5adSDave Gerlach */
2888428e5adSDave GerlachENTRY(ti_emif_enter_sr)
2898428e5adSDave Gerlach	stmfd   sp!, {r4 - r11, lr}     @ save registers on stack
2908428e5adSDave Gerlach
2918428e5adSDave Gerlach	adr	r4, ti_emif_pm_sram_data
2928428e5adSDave Gerlach	ldr	r0, [r4, #EMIF_PM_BASE_ADDR_VIRT_OFFSET]
2938428e5adSDave Gerlach	ldr	r2, [r4, #EMIF_PM_REGS_VIRT_OFFSET]
2948428e5adSDave Gerlach
2958428e5adSDave Gerlach	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
2968428e5adSDave Gerlach	bic	r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK
2978428e5adSDave Gerlach	orr	r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE
2988428e5adSDave Gerlach	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
2998428e5adSDave Gerlach
3008428e5adSDave Gerlach	ldmfd	sp!, {r4 - r11, pc}	@ restore regs and return
3018428e5adSDave GerlachENDPROC(ti_emif_enter_sr)
3028428e5adSDave Gerlach
3038428e5adSDave Gerlach/*
3048428e5adSDave Gerlach * void ti_emif_exit_sr(void)
3058428e5adSDave Gerlach *
3068428e5adSDave Gerlach * Programs the EMIF to tell the SDRAM to exit self-refresh mode
3078428e5adSDave Gerlach * after a sleep transition. Operates on the PHYSICAL address of
3088428e5adSDave Gerlach * the EMIF.
3098428e5adSDave Gerlach */
3108428e5adSDave GerlachENTRY(ti_emif_exit_sr)
3118428e5adSDave Gerlach	adr	r4, ti_emif_pm_sram_data
3128428e5adSDave Gerlach	ldr	r0, [r4, #EMIF_PM_BASE_ADDR_PHYS_OFFSET]
3138428e5adSDave Gerlach	ldr	r2, [r4, #EMIF_PM_REGS_PHYS_OFFSET]
3148428e5adSDave Gerlach
3158428e5adSDave Gerlach	/*
3168428e5adSDave Gerlach	 * Toggle EMIF to exit refresh mode:
3178428e5adSDave Gerlach	 * if EMIF lost context, PWR_MGT_CTRL is currently 0, writing disable
3188428e5adSDave Gerlach	 *   (0x0), wont do diddly squat! so do a toggle from SR(0x2) to disable
3198428e5adSDave Gerlach	 *   (0x0) here.
3208428e5adSDave Gerlach	 * *If* EMIF did not lose context, nothing broken as we write the same
3218428e5adSDave Gerlach	 *   value(0x2) to reg before we write a disable (0x0).
3228428e5adSDave Gerlach	 */
3238428e5adSDave Gerlach	ldr	r1, [r2, #EMIF_PMCR_VAL_OFFSET]
3248428e5adSDave Gerlach	bic	r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK
3258428e5adSDave Gerlach	orr	r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE
3268428e5adSDave Gerlach	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
3278428e5adSDave Gerlach	bic	r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK
3288428e5adSDave Gerlach	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
3298428e5adSDave Gerlach
3308428e5adSDave Gerlach        /* Wait for EMIF to become ready */
3318428e5adSDave Gerlach1:	ldr     r1, [r0, #EMIF_STATUS]
3328428e5adSDave Gerlach	tst     r1, #EMIF_STATUS_READY
3338428e5adSDave Gerlach	beq     1b
3348428e5adSDave Gerlach
3358428e5adSDave Gerlach	mov	pc, lr
3368428e5adSDave GerlachENDPROC(ti_emif_exit_sr)
3378428e5adSDave Gerlach
3388428e5adSDave Gerlach/*
3398428e5adSDave Gerlach * void ti_emif_abort_sr(void)
3408428e5adSDave Gerlach *
3418428e5adSDave Gerlach * Disables self-refresh after a failed transition to a low-power
3428428e5adSDave Gerlach * state so the kernel can jump back to DDR and follow abort path.
3438428e5adSDave Gerlach * Operates on the VIRTUAL address of the EMIF.
3448428e5adSDave Gerlach */
3458428e5adSDave GerlachENTRY(ti_emif_abort_sr)
3468428e5adSDave Gerlach	stmfd   sp!, {r4 - r11, lr}     @ save registers on stack
3478428e5adSDave Gerlach
3488428e5adSDave Gerlach	adr	r4, ti_emif_pm_sram_data
3498428e5adSDave Gerlach	ldr	r0, [r4, #EMIF_PM_BASE_ADDR_VIRT_OFFSET]
3508428e5adSDave Gerlach	ldr	r2, [r4, #EMIF_PM_REGS_VIRT_OFFSET]
3518428e5adSDave Gerlach
3528428e5adSDave Gerlach	ldr	r1, [r2, #EMIF_PMCR_VAL_OFFSET]
3538428e5adSDave Gerlach	bic	r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK
3548428e5adSDave Gerlach	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
3558428e5adSDave Gerlach
3568428e5adSDave Gerlach	/* Wait for EMIF to become ready */
3578428e5adSDave Gerlach1:	ldr     r1, [r0, #EMIF_STATUS]
3588428e5adSDave Gerlach	tst     r1, #EMIF_STATUS_READY
3598428e5adSDave Gerlach	beq     1b
3608428e5adSDave Gerlach
3618428e5adSDave Gerlach	ldmfd	sp!, {r4 - r11, pc}	@ restore regs and return
3628428e5adSDave GerlachENDPROC(ti_emif_abort_sr)
3638428e5adSDave Gerlach
3648428e5adSDave Gerlach	.align 3
3658428e5adSDave GerlachENTRY(ti_emif_pm_sram_data)
3668428e5adSDave Gerlach	.space EMIF_PM_DATA_SIZE
3678428e5adSDave GerlachENTRY(ti_emif_sram_sz)
3688428e5adSDave Gerlach        .word   . - ti_emif_save_context
369