1/* 2 * Low level PM code for TI EMIF 3 * 4 * Copyright (C) 2016-2017 Texas Instruments Incorporated - http://www.ti.com/ 5 * Dave Gerlach 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License as 9 * published by the Free Software Foundation version 2. 10 * 11 * This program is distributed "as is" WITHOUT ANY WARRANTY of any 12 * kind, whether express or implied; without even the implied warranty 13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 */ 16 17#include <generated/ti-emif-asm-offsets.h> 18#include <linux/linkage.h> 19#include <asm/assembler.h> 20#include <asm/memory.h> 21 22#include "emif.h" 23 24#define EMIF_POWER_MGMT_WAIT_SELF_REFRESH_8192_CYCLES 0x00a0 25#define EMIF_POWER_MGMT_SR_TIMER_MASK 0x00f0 26#define EMIF_POWER_MGMT_SELF_REFRESH_MODE 0x0200 27#define EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK 0x0700 28 29#define EMIF_SDCFG_TYPE_DDR2 0x2 << SDRAM_TYPE_SHIFT 30#define EMIF_STATUS_READY 0x4 31 32#define AM43XX_EMIF_PHY_CTRL_REG_COUNT 0x120 33 34#define EMIF_AM437X_REGISTERS 0x1 35 36 .arm 37 .align 3 38 39ENTRY(ti_emif_sram) 40 41/* 42 * void ti_emif_save_context(void) 43 * 44 * Used during suspend to save the context of all required EMIF registers 45 * to local memory if the EMIF is going to lose context during the sleep 46 * transition. Operates on the VIRTUAL address of the EMIF. 47 */ 48ENTRY(ti_emif_save_context) 49 stmfd sp!, {r4 - r11, lr} @ save registers on stack 50 51 adr r4, ti_emif_pm_sram_data 52 ldr r0, [r4, #EMIF_PM_BASE_ADDR_VIRT_OFFSET] 53 ldr r2, [r4, #EMIF_PM_REGS_VIRT_OFFSET] 54 55 /* Save EMIF configuration */ 56 ldr r1, [r0, #EMIF_SDRAM_CONFIG] 57 str r1, [r2, #EMIF_SDCFG_VAL_OFFSET] 58 59 ldr r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL] 60 str r1, [r2, #EMIF_REF_CTRL_VAL_OFFSET] 61 62 ldr r1, [r0, #EMIF_SDRAM_TIMING_1] 63 str r1, [r2, #EMIF_TIMING1_VAL_OFFSET] 64 65 ldr r1, [r0, #EMIF_SDRAM_TIMING_2] 66 str r1, [r2, #EMIF_TIMING2_VAL_OFFSET] 67 68 ldr r1, [r0, #EMIF_SDRAM_TIMING_3] 69 str r1, [r2, #EMIF_TIMING3_VAL_OFFSET] 70 71 ldr r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL] 72 str r1, [r2, #EMIF_PMCR_VAL_OFFSET] 73 74 ldr r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW] 75 str r1, [r2, #EMIF_PMCR_SHDW_VAL_OFFSET] 76 77 ldr r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG] 78 str r1, [r2, #EMIF_ZQCFG_VAL_OFFSET] 79 80 ldr r1, [r0, #EMIF_DDR_PHY_CTRL_1] 81 str r1, [r2, #EMIF_DDR_PHY_CTLR_1_OFFSET] 82 83 ldr r1, [r0, #EMIF_COS_CONFIG] 84 str r1, [r2, #EMIF_COS_CONFIG_OFFSET] 85 86 ldr r1, [r0, #EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING] 87 str r1, [r2, #EMIF_PRIORITY_TO_COS_MAPPING_OFFSET] 88 89 ldr r1, [r0, #EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING] 90 str r1, [r2, #EMIF_CONNECT_ID_SERV_1_MAP_OFFSET] 91 92 ldr r1, [r0, #EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING] 93 str r1, [r2, #EMIF_CONNECT_ID_SERV_2_MAP_OFFSET] 94 95 ldr r1, [r0, #EMIF_OCP_CONFIG] 96 str r1, [r2, #EMIF_OCP_CONFIG_VAL_OFFSET] 97 98 ldr r5, [r4, #EMIF_PM_CONFIG_OFFSET] 99 cmp r5, #EMIF_SRAM_AM43_REG_LAYOUT 100 bne emif_skip_save_extra_regs 101 102 ldr r1, [r0, #EMIF_READ_WRITE_LEVELING_RAMP_CONTROL] 103 str r1, [r2, #EMIF_RD_WR_LEVEL_RAMP_CTRL_OFFSET] 104 105 ldr r1, [r0, #EMIF_READ_WRITE_EXECUTION_THRESHOLD] 106 str r1, [r2, #EMIF_RD_WR_EXEC_THRESH_OFFSET] 107 108 ldr r1, [r0, #EMIF_LPDDR2_NVM_TIMING] 109 str r1, [r2, #EMIF_LPDDR2_NVM_TIM_OFFSET] 110 111 ldr r1, [r0, #EMIF_LPDDR2_NVM_TIMING_SHDW] 112 str r1, [r2, #EMIF_LPDDR2_NVM_TIM_SHDW_OFFSET] 113 114 ldr r1, [r0, #EMIF_DLL_CALIB_CTRL] 115 str r1, [r2, #EMIF_DLL_CALIB_CTRL_VAL_OFFSET] 116 117 ldr r1, [r0, #EMIF_DLL_CALIB_CTRL_SHDW] 118 str r1, [r2, #EMIF_DLL_CALIB_CTRL_VAL_SHDW_OFFSET] 119 120 /* Loop and save entire block of emif phy regs */ 121 mov r5, #0x0 122 add r4, r2, #EMIF_EXT_PHY_CTRL_VALS_OFFSET 123 add r3, r0, #EMIF_EXT_PHY_CTRL_1 124ddr_phy_ctrl_save: 125 ldr r1, [r3, r5] 126 str r1, [r4, r5] 127 add r5, r5, #0x4 128 cmp r5, #AM43XX_EMIF_PHY_CTRL_REG_COUNT 129 bne ddr_phy_ctrl_save 130 131emif_skip_save_extra_regs: 132 ldmfd sp!, {r4 - r11, pc} @ restore regs and return 133ENDPROC(ti_emif_save_context) 134 135/* 136 * void ti_emif_restore_context(void) 137 * 138 * Used during resume to restore the context of all required EMIF registers 139 * from local memory after the EMIF has lost context during a sleep transition. 140 * Operates on the PHYSICAL address of the EMIF. 141 */ 142ENTRY(ti_emif_restore_context) 143 adr r4, ti_emif_pm_sram_data 144 ldr r0, [r4, #EMIF_PM_BASE_ADDR_PHYS_OFFSET] 145 ldr r2, [r4, #EMIF_PM_REGS_PHYS_OFFSET] 146 147 /* Config EMIF Timings */ 148 ldr r1, [r2, #EMIF_DDR_PHY_CTLR_1_OFFSET] 149 str r1, [r0, #EMIF_DDR_PHY_CTRL_1] 150 str r1, [r0, #EMIF_DDR_PHY_CTRL_1_SHDW] 151 152 ldr r1, [r2, #EMIF_TIMING1_VAL_OFFSET] 153 str r1, [r0, #EMIF_SDRAM_TIMING_1] 154 str r1, [r0, #EMIF_SDRAM_TIMING_1_SHDW] 155 156 ldr r1, [r2, #EMIF_TIMING2_VAL_OFFSET] 157 str r1, [r0, #EMIF_SDRAM_TIMING_2] 158 str r1, [r0, #EMIF_SDRAM_TIMING_2_SHDW] 159 160 ldr r1, [r2, #EMIF_TIMING3_VAL_OFFSET] 161 str r1, [r0, #EMIF_SDRAM_TIMING_3] 162 str r1, [r0, #EMIF_SDRAM_TIMING_3_SHDW] 163 164 ldr r1, [r2, #EMIF_REF_CTRL_VAL_OFFSET] 165 str r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL] 166 str r1, [r0, #EMIF_SDRAM_REFRESH_CTRL_SHDW] 167 168 ldr r1, [r2, #EMIF_PMCR_VAL_OFFSET] 169 str r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL] 170 171 ldr r1, [r2, #EMIF_PMCR_SHDW_VAL_OFFSET] 172 str r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW] 173 174 ldr r1, [r2, #EMIF_COS_CONFIG_OFFSET] 175 str r1, [r0, #EMIF_COS_CONFIG] 176 177 ldr r1, [r2, #EMIF_PRIORITY_TO_COS_MAPPING_OFFSET] 178 str r1, [r0, #EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING] 179 180 ldr r1, [r2, #EMIF_CONNECT_ID_SERV_1_MAP_OFFSET] 181 str r1, [r0, #EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING] 182 183 ldr r1, [r2, #EMIF_CONNECT_ID_SERV_2_MAP_OFFSET] 184 str r1, [r0, #EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING] 185 186 ldr r1, [r2, #EMIF_OCP_CONFIG_VAL_OFFSET] 187 str r1, [r0, #EMIF_OCP_CONFIG] 188 189 ldr r5, [r4, #EMIF_PM_CONFIG_OFFSET] 190 cmp r5, #EMIF_SRAM_AM43_REG_LAYOUT 191 bne emif_skip_restore_extra_regs 192 193 ldr r1, [r2, #EMIF_RD_WR_LEVEL_RAMP_CTRL_OFFSET] 194 str r1, [r0, #EMIF_READ_WRITE_LEVELING_RAMP_CONTROL] 195 196 ldr r1, [r2, #EMIF_RD_WR_EXEC_THRESH_OFFSET] 197 str r1, [r0, #EMIF_READ_WRITE_EXECUTION_THRESHOLD] 198 199 ldr r1, [r2, #EMIF_LPDDR2_NVM_TIM_OFFSET] 200 str r1, [r0, #EMIF_LPDDR2_NVM_TIMING] 201 202 ldr r1, [r2, #EMIF_LPDDR2_NVM_TIM_SHDW_OFFSET] 203 str r1, [r0, #EMIF_LPDDR2_NVM_TIMING_SHDW] 204 205 ldr r1, [r2, #EMIF_DLL_CALIB_CTRL_VAL_OFFSET] 206 str r1, [r0, #EMIF_DLL_CALIB_CTRL] 207 208 ldr r1, [r2, #EMIF_DLL_CALIB_CTRL_VAL_SHDW_OFFSET] 209 str r1, [r0, #EMIF_DLL_CALIB_CTRL_SHDW] 210 211 ldr r1, [r2, #EMIF_ZQCFG_VAL_OFFSET] 212 str r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG] 213 214 /* Loop and restore entire block of emif phy regs */ 215 mov r5, #0x0 216 /* Load ti_emif_regs_amx3 + EMIF_EXT_PHY_CTRL_VALS_OFFSET for address 217 * to phy register save space 218 */ 219 add r3, r2, #EMIF_EXT_PHY_CTRL_VALS_OFFSET 220 add r4, r0, #EMIF_EXT_PHY_CTRL_1 221ddr_phy_ctrl_restore: 222 ldr r1, [r3, r5] 223 str r1, [r4, r5] 224 add r5, r5, #0x4 225 cmp r5, #AM43XX_EMIF_PHY_CTRL_REG_COUNT 226 bne ddr_phy_ctrl_restore 227 228emif_skip_restore_extra_regs: 229 /* 230 * Output impedence calib needed only for DDR3 231 * but since the initial state of this will be 232 * disabled for DDR2 no harm in restoring the 233 * old configuration 234 */ 235 ldr r1, [r2, #EMIF_ZQCFG_VAL_OFFSET] 236 str r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG] 237 238 /* Write to sdcfg last for DDR2 only */ 239 ldr r1, [r2, #EMIF_SDCFG_VAL_OFFSET] 240 and r2, r1, #SDRAM_TYPE_MASK 241 cmp r2, #EMIF_SDCFG_TYPE_DDR2 242 streq r1, [r0, #EMIF_SDRAM_CONFIG] 243 244 mov pc, lr 245ENDPROC(ti_emif_restore_context) 246 247/* 248 * void ti_emif_enter_sr(void) 249 * 250 * Programs the EMIF to tell the SDRAM to enter into self-refresh 251 * mode during a sleep transition. Operates on the VIRTUAL address 252 * of the EMIF. 253 */ 254ENTRY(ti_emif_enter_sr) 255 stmfd sp!, {r4 - r11, lr} @ save registers on stack 256 257 adr r4, ti_emif_pm_sram_data 258 ldr r0, [r4, #EMIF_PM_BASE_ADDR_VIRT_OFFSET] 259 ldr r2, [r4, #EMIF_PM_REGS_VIRT_OFFSET] 260 261 ldr r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL] 262 bic r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK 263 orr r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE 264 str r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL] 265 266 ldmfd sp!, {r4 - r11, pc} @ restore regs and return 267ENDPROC(ti_emif_enter_sr) 268 269/* 270 * void ti_emif_exit_sr(void) 271 * 272 * Programs the EMIF to tell the SDRAM to exit self-refresh mode 273 * after a sleep transition. Operates on the PHYSICAL address of 274 * the EMIF. 275 */ 276ENTRY(ti_emif_exit_sr) 277 adr r4, ti_emif_pm_sram_data 278 ldr r0, [r4, #EMIF_PM_BASE_ADDR_PHYS_OFFSET] 279 ldr r2, [r4, #EMIF_PM_REGS_PHYS_OFFSET] 280 281 /* 282 * Toggle EMIF to exit refresh mode: 283 * if EMIF lost context, PWR_MGT_CTRL is currently 0, writing disable 284 * (0x0), wont do diddly squat! so do a toggle from SR(0x2) to disable 285 * (0x0) here. 286 * *If* EMIF did not lose context, nothing broken as we write the same 287 * value(0x2) to reg before we write a disable (0x0). 288 */ 289 ldr r1, [r2, #EMIF_PMCR_VAL_OFFSET] 290 bic r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK 291 orr r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE 292 str r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL] 293 bic r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK 294 str r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL] 295 296 /* Wait for EMIF to become ready */ 2971: ldr r1, [r0, #EMIF_STATUS] 298 tst r1, #EMIF_STATUS_READY 299 beq 1b 300 301 mov pc, lr 302ENDPROC(ti_emif_exit_sr) 303 304/* 305 * void ti_emif_abort_sr(void) 306 * 307 * Disables self-refresh after a failed transition to a low-power 308 * state so the kernel can jump back to DDR and follow abort path. 309 * Operates on the VIRTUAL address of the EMIF. 310 */ 311ENTRY(ti_emif_abort_sr) 312 stmfd sp!, {r4 - r11, lr} @ save registers on stack 313 314 adr r4, ti_emif_pm_sram_data 315 ldr r0, [r4, #EMIF_PM_BASE_ADDR_VIRT_OFFSET] 316 ldr r2, [r4, #EMIF_PM_REGS_VIRT_OFFSET] 317 318 ldr r1, [r2, #EMIF_PMCR_VAL_OFFSET] 319 bic r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK 320 str r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL] 321 322 /* Wait for EMIF to become ready */ 3231: ldr r1, [r0, #EMIF_STATUS] 324 tst r1, #EMIF_STATUS_READY 325 beq 1b 326 327 ldmfd sp!, {r4 - r11, pc} @ restore regs and return 328ENDPROC(ti_emif_abort_sr) 329 330 .align 3 331ENTRY(ti_emif_pm_sram_data) 332 .space EMIF_PM_DATA_SIZE 333ENTRY(ti_emif_sram_sz) 334 .word . - ti_emif_save_context 335