0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/linkage.h>
0010 #include <linux/ti-emif-sram.h>
0011 #include <linux/platform_data/pm33xx.h>
0012 #include <asm/assembler.h>
0013 #include <asm/hardware/cache-l2x0.h>
0014 #include <asm/memory.h>
0015
0016 #include "cm33xx.h"
0017 #include "common.h"
0018 #include "iomap.h"
0019 #include "omap-secure.h"
0020 #include "omap44xx.h"
0021 #include "pm-asm-offsets.h"
0022 #include "prm33xx.h"
0023 #include "prcm43xx.h"
0024
0025
0026 #define BIT(nr) (1 << (nr))
0027
0028 #define AM33XX_CM_CLKCTRL_MODULESTATE_DISABLED 0x00030000
0029 #define AM33XX_CM_CLKCTRL_MODULEMODE_DISABLE 0x0003
0030 #define AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE 0x0002
0031
0032 #define AM43XX_EMIF_POWEROFF_ENABLE 0x1
0033 #define AM43XX_EMIF_POWEROFF_DISABLE 0x0
0034
0035 #define AM43XX_CM_CLKSTCTRL_CLKTRCTRL_SW_SLEEP 0x1
0036 #define AM43XX_CM_CLKSTCTRL_CLKTRCTRL_HW_AUTO 0x3
0037
0038 #define AM43XX_CM_BASE 0x44DF0000
0039
0040 #define AM43XX_CM_REGADDR(inst, reg) \
0041 AM33XX_L4_WK_IO_ADDRESS(AM43XX_CM_BASE + (inst) + (reg))
0042
0043 #define AM43XX_CM_MPU_CLKSTCTRL AM43XX_CM_REGADDR(AM43XX_CM_MPU_INST, \
0044 AM43XX_CM_MPU_MPU_CDOFFS)
0045 #define AM43XX_CM_MPU_MPU_CLKCTRL AM43XX_CM_REGADDR(AM43XX_CM_MPU_INST, \
0046 AM43XX_CM_MPU_MPU_CLKCTRL_OFFSET)
0047 #define AM43XX_CM_PER_EMIF_CLKCTRL AM43XX_CM_REGADDR(AM43XX_CM_PER_INST, \
0048 AM43XX_CM_PER_EMIF_CLKCTRL_OFFSET)
0049 #define AM43XX_PRM_EMIF_CTRL_OFFSET 0x0030
0050
0051 #define RTC_SECONDS_REG 0x0
0052 #define RTC_PMIC_REG 0x98
0053 #define RTC_PMIC_POWER_EN BIT(16)
0054 #define RTC_PMIC_EXT_WAKEUP_STS BIT(12)
0055 #define RTC_PMIC_EXT_WAKEUP_POL BIT(4)
0056 #define RTC_PMIC_EXT_WAKEUP_EN BIT(0)
0057
0058 .arm
0059 .arch armv7-a
0060 .arch_extension sec
0061 .align 3
0062
0063 ENTRY(am43xx_do_wfi)
0064 stmfd sp!, {r4 - r11, lr} @ save registers on stack
0065
0066
0067 mov r4, r0
0068 adr r3, am43xx_pm_ro_sram_data
0069 ldr r2, [r3, #AMX3_PM_RO_SRAM_DATA_VIRT_OFFSET]
0070 str r4, [r2, #AMX3_PM_WFI_FLAGS_OFFSET]
0071
0072 #ifdef CONFIG_CACHE_L2X0
0073
0074 ldr r1, get_l2cache_base
0075 blx r1
0076 mov r8, r0
0077 #endif
0078
0079
0080 tst r4, #WFI_FLAG_FLUSH_CACHE
0081 beq cache_skip_flush
0082
0083
0084
0085
0086
0087 ldr r1, kernel_flush
0088 blx r1
0089
0090
0091
0092
0093
0094
0095 mrc p15, 0, r0, c1, c0, 0
0096 bic r0, r0, #(1 << 2) @ Disable the C bit
0097 mcr p15, 0, r0, c1, c0, 0
0098 isb
0099 dsb
0100
0101
0102
0103
0104 ldr r1, kernel_flush
0105 blx r1
0106
0107 #ifdef CONFIG_CACHE_L2X0
0108
0109
0110
0111 #ifdef CONFIG_PL310_ERRATA_727915
0112 mov r0, #0x03
0113 mov r12, #OMAP4_MON_L2X0_DBG_CTRL_INDEX
0114 dsb
0115 smc #0
0116 dsb
0117 #endif
0118 mov r0, r8
0119 adr r4, am43xx_pm_ro_sram_data
0120 ldr r3, [r4, #AMX3_PM_RO_SRAM_DATA_VIRT_OFFSET]
0121
0122 mov r2, r0
0123 ldr r0, [r2, #L2X0_AUX_CTRL]
0124 str r0, [r3, #AMX3_PM_L2_AUX_CTRL_VAL_OFFSET]
0125 ldr r0, [r2, #L310_PREFETCH_CTRL]
0126 str r0, [r3, #AMX3_PM_L2_PREFETCH_CTRL_VAL_OFFSET]
0127
0128 ldr r0, l2_val
0129 str r0, [r2, #L2X0_CLEAN_INV_WAY]
0130 wait:
0131 ldr r0, [r2, #L2X0_CLEAN_INV_WAY]
0132 ldr r1, l2_val
0133 ands r0, r0, r1
0134 bne wait
0135 #ifdef CONFIG_PL310_ERRATA_727915
0136 mov r0, #0x00
0137 mov r12, #OMAP4_MON_L2X0_DBG_CTRL_INDEX
0138 dsb
0139 smc #0
0140 dsb
0141 #endif
0142 l2x_sync:
0143 mov r0, r8
0144 mov r2, r0
0145 mov r0, #0x0
0146 str r0, [r2, #L2X0_CACHE_SYNC]
0147 sync:
0148 ldr r0, [r2, #L2X0_CACHE_SYNC]
0149 ands r0, r0, #0x1
0150 bne sync
0151 #endif
0152
0153
0154 adr r3, am43xx_pm_ro_sram_data
0155 ldr r2, [r3, #AMX3_PM_RO_SRAM_DATA_VIRT_OFFSET]
0156 ldr r4, [r2, #AMX3_PM_WFI_FLAGS_OFFSET]
0157
0158 cache_skip_flush:
0159
0160
0161
0162
0163
0164
0165 tst r4, #WFI_FLAG_RTC_ONLY
0166 beq skip_rtc_va_refresh
0167
0168 adr r3, am43xx_pm_ro_sram_data
0169 ldr r1, [r3, #AMX3_PM_RTC_BASE_VIRT_OFFSET]
0170 ldr r0, [r1]
0171
0172 skip_rtc_va_refresh:
0173
0174 tst r4, #WFI_FLAG_SELF_REFRESH
0175 beq emif_skip_enter_sr
0176
0177 adr r9, am43xx_emif_sram_table
0178
0179 ldr r3, [r9, #EMIF_PM_ENTER_SR_OFFSET]
0180 blx r3
0181
0182 emif_skip_enter_sr:
0183
0184 tst r4, #WFI_FLAG_SAVE_EMIF
0185 beq emif_skip_save
0186
0187 ldr r3, [r9, #EMIF_PM_SAVE_CONTEXT_OFFSET]
0188 blx r3
0189
0190 emif_skip_save:
0191
0192 tst r4, #WFI_FLAG_SELF_REFRESH
0193 beq emif_skip_disable
0194
0195
0196 ldr r1, am43xx_virt_emif_clkctrl
0197 ldr r2, [r1]
0198 bic r2, r2, #AM33XX_CM_CLKCTRL_MODULEMODE_DISABLE
0199 str r2, [r1]
0200
0201 wait_emif_disable:
0202 ldr r2, [r1]
0203 mov r3, #AM33XX_CM_CLKCTRL_MODULESTATE_DISABLED
0204 cmp r2, r3
0205 bne wait_emif_disable
0206
0207 emif_skip_disable:
0208 tst r4, #WFI_FLAG_RTC_ONLY
0209 beq skip_rtc_only
0210
0211 adr r3, am43xx_pm_ro_sram_data
0212 ldr r1, [r3, #AMX3_PM_RTC_BASE_VIRT_OFFSET]
0213
0214 ldr r0, [r1, #RTC_PMIC_REG]
0215 orr r0, r0, #RTC_PMIC_POWER_EN
0216 orr r0, r0, #RTC_PMIC_EXT_WAKEUP_STS
0217 orr r0, r0, #RTC_PMIC_EXT_WAKEUP_EN
0218 orr r0, r0, #RTC_PMIC_EXT_WAKEUP_POL
0219 str r0, [r1, #RTC_PMIC_REG]
0220 ldr r0, [r1, #RTC_PMIC_REG]
0221
0222 mov r3, #2
0223 ldr r2, [r1, #RTC_SECONDS_REG]
0224 rtc_loop:
0225 ldr r0, [r1, #RTC_SECONDS_REG]
0226 cmp r0, r2
0227 beq rtc_loop
0228 mov r2, r0
0229 subs r3, r3, #1
0230 bne rtc_loop
0231
0232 b re_enable_emif
0233
0234 skip_rtc_only:
0235
0236 tst r4, #WFI_FLAG_WAKE_M3
0237 beq wkup_m3_skip
0238
0239
0240
0241
0242
0243
0244 ldr r1, am43xx_virt_mpu_clkctrl
0245 ldr r2, [r1]
0246 bic r2, r2, #AM33XX_CM_CLKCTRL_MODULEMODE_DISABLE
0247 str r2, [r1]
0248
0249
0250
0251
0252 ldr r1, am43xx_virt_mpu_clkstctrl
0253 mov r2, #AM43XX_CM_CLKSTCTRL_CLKTRCTRL_SW_SLEEP
0254 str r2, [r1]
0255
0256 wkup_m3_skip:
0257
0258
0259
0260
0261
0262 dsb
0263 dmb
0264
0265
0266
0267
0268
0269
0270
0271
0272 wfi
0273
0274 nop
0275 nop
0276 nop
0277 nop
0278 nop
0279 nop
0280 nop
0281 nop
0282 nop
0283 nop
0284 nop
0285 nop
0286 nop
0287 nop
0288 nop
0289 nop
0290
0291
0292 ldr r1, am43xx_virt_mpu_clkstctrl
0293 mov r2, #AM43XX_CM_CLKSTCTRL_CLKTRCTRL_HW_AUTO
0294 str r2, [r1]
0295
0296
0297 ldr r1, am43xx_virt_mpu_clkctrl
0298 mov r2, #AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE
0299 str r2, [r1]
0300
0301 re_enable_emif:
0302
0303 ldr r1, am43xx_virt_emif_clkctrl
0304 mov r2, #AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE
0305 str r2, [r1]
0306 wait_emif_enable:
0307 ldr r3, [r1]
0308 cmp r2, r3
0309 bne wait_emif_enable
0310
0311 tst r4, #WFI_FLAG_FLUSH_CACHE
0312 beq cache_skip_restore
0313
0314
0315
0316
0317 mrc p15, 0, r0, c1, c0, 0
0318 orr r0, r0, #(1 << 2) @ Enable the C bit
0319 mcr p15, 0, r0, c1, c0, 0
0320 isb
0321
0322 cache_skip_restore:
0323
0324 tst r4, #WFI_FLAG_SELF_REFRESH
0325 beq emif_skip_exit_sr_abt
0326
0327 adr r9, am43xx_emif_sram_table
0328 ldr r1, [r9, #EMIF_PM_ABORT_SR_OFFSET]
0329 blx r1
0330
0331 emif_skip_exit_sr_abt:
0332
0333 mov r0, #1
0334 ldmfd sp!, {r4 - r11, pc} @ restore regs and return
0335 ENDPROC(am43xx_do_wfi)
0336
0337 .align
0338 ENTRY(am43xx_resume_offset)
0339 .word . - am43xx_do_wfi
0340
0341 ENTRY(am43xx_resume_from_deep_sleep)
0342
0343 ldr r1, am43xx_virt_mpu_clkstctrl
0344 mov r2, #AM43XX_CM_CLKSTCTRL_CLKTRCTRL_HW_AUTO
0345 str r2, [r1]
0346
0347
0348 ldr r2, am43xx_phys_emif_poweroff
0349 mov r1, #AM43XX_EMIF_POWEROFF_ENABLE
0350 str r1, [r2, #0x0]
0351
0352
0353 ldr r1, am43xx_phys_emif_clkctrl
0354 mov r2, #AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE
0355 str r2, [r1]
0356 wait_emif_enable1:
0357 ldr r3, [r1]
0358 cmp r2, r3
0359 bne wait_emif_enable1
0360
0361 adr r9, am43xx_emif_sram_table
0362
0363 ldr r1, [r9, #EMIF_PM_RESTORE_CONTEXT_OFFSET]
0364 blx r1
0365
0366 ldr r1, [r9, #EMIF_PM_EXIT_SR_OFFSET]
0367 blx r1
0368
0369 ldr r2, am43xx_phys_emif_poweroff
0370 mov r1, #AM43XX_EMIF_POWEROFF_DISABLE
0371 str r1, [r2, #0x0]
0372
0373 ldr r1, [r9, #EMIF_PM_RUN_HW_LEVELING]
0374 blx r1
0375
0376 #ifdef CONFIG_CACHE_L2X0
0377 ldr r2, l2_cache_base
0378 ldr r0, [r2, #L2X0_CTRL]
0379 and r0, #0x0f
0380 cmp r0, #1
0381 beq skip_l2en @ Skip if already enabled
0382
0383 adr r4, am43xx_pm_ro_sram_data
0384 ldr r3, [r4, #AMX3_PM_RO_SRAM_DATA_PHYS_OFFSET]
0385 ldr r0, [r3, #AMX3_PM_L2_PREFETCH_CTRL_VAL_OFFSET]
0386
0387 ldr r12, l2_smc1
0388 dsb
0389 smc #0
0390 dsb
0391 set_aux_ctrl:
0392 ldr r0, [r3, #AMX3_PM_L2_AUX_CTRL_VAL_OFFSET]
0393 ldr r12, l2_smc2
0394 dsb
0395 smc #0
0396 dsb
0397
0398
0399 ldr r0, l2_val
0400 ldr r2, l2_cache_base
0401 str r0, [r2, #L2X0_INV_WAY]
0402 wait2:
0403 ldr r0, [r2, #L2X0_INV_WAY]
0404 ldr r1, l2_val
0405 ands r0, r0, r1
0406 bne wait2
0407 #ifdef CONFIG_PL310_ERRATA_727915
0408 mov r0, #0x00
0409 mov r12, #OMAP4_MON_L2X0_DBG_CTRL_INDEX
0410 dsb
0411 smc #0
0412 dsb
0413 #endif
0414 l2x_sync2:
0415 ldr r2, l2_cache_base
0416 mov r0, #0x0
0417 str r0, [r2, #L2X0_CACHE_SYNC]
0418 sync2:
0419 ldr r0, [r2, #L2X0_CACHE_SYNC]
0420 ands r0, r0, #0x1
0421 bne sync2
0422
0423 mov r0, #0x1
0424 ldr r12, l2_smc3
0425 dsb
0426 smc #0
0427 dsb
0428 #endif
0429 skip_l2en:
0430
0431 mov r0, #0
0432 ldr pc, resume_addr
0433 ENDPROC(am43xx_resume_from_deep_sleep)
0434
0435
0436
0437
0438 .align
0439 kernel_flush:
0440 .word v7_flush_dcache_all
0441 ddr_start:
0442 .word PAGE_OFFSET
0443
0444 am43xx_phys_emif_poweroff:
0445 .word (AM43XX_CM_BASE + AM43XX_PRM_DEVICE_INST + \
0446 AM43XX_PRM_EMIF_CTRL_OFFSET)
0447 am43xx_virt_mpu_clkstctrl:
0448 .word (AM43XX_CM_MPU_CLKSTCTRL)
0449 am43xx_virt_mpu_clkctrl:
0450 .word (AM43XX_CM_MPU_MPU_CLKCTRL)
0451 am43xx_virt_emif_clkctrl:
0452 .word (AM43XX_CM_PER_EMIF_CLKCTRL)
0453 am43xx_phys_emif_clkctrl:
0454 .word (AM43XX_CM_BASE + AM43XX_CM_PER_INST + \
0455 AM43XX_CM_PER_EMIF_CLKCTRL_OFFSET)
0456
0457 #ifdef CONFIG_CACHE_L2X0
0458
0459 get_l2cache_base:
0460 .word omap4_get_l2cache_base
0461 l2_cache_base:
0462 .word OMAP44XX_L2CACHE_BASE
0463 l2_smc1:
0464 .word OMAP4_MON_L2X0_PREFETCH_INDEX
0465 l2_smc2:
0466 .word OMAP4_MON_L2X0_AUXCTRL_INDEX
0467 l2_smc3:
0468 .word OMAP4_MON_L2X0_CTRL_INDEX
0469 l2_val:
0470 .word 0xffff
0471 #endif
0472
0473 .align 3
0474
0475 ENTRY(am43xx_emif_sram_table)
0476 .space EMIF_PM_FUNCTIONS_SIZE
0477
0478 ENTRY(am43xx_pm_sram)
0479 .word am43xx_do_wfi
0480 .word am43xx_do_wfi_sz
0481 .word am43xx_resume_offset
0482 .word am43xx_emif_sram_table
0483 .word am43xx_pm_ro_sram_data
0484
0485 resume_addr:
0486 .word cpu_resume - PAGE_OFFSET + 0x80000000
0487 .align 3
0488
0489 ENTRY(am43xx_pm_ro_sram_data)
0490 .space AMX3_PM_RO_SRAM_DATA_SIZE
0491
0492 ENTRY(am43xx_do_wfi_sz)
0493 .word . - am43xx_do_wfi