Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*
0003  * Low level suspend code for AM43XX SoCs
0004  *
0005  * Copyright (C) 2013-2018 Texas Instruments Incorporated - https://www.ti.com/
0006  *  Dave Gerlach, Vaibhav Bedia
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 /* replicated define because linux/bitops.h cannot be included in assembly */
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     /* Save wfi_flags arg to data space */
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     /* Retrieve l2 cache virt address BEFORE we shut off EMIF */
0074     ldr r1, get_l2cache_base
0075     blx r1
0076     mov r8, r0
0077 #endif
0078 
0079     /* Only flush cache is we know we are losing MPU context */
0080     tst r4, #WFI_FLAG_FLUSH_CACHE
0081     beq cache_skip_flush
0082 
0083     /*
0084      * Flush all data from the L1 and L2 data cache before disabling
0085      * SCTLR.C bit.
0086      */
0087     ldr r1, kernel_flush
0088     blx r1
0089 
0090     /*
0091      * Clear the SCTLR.C bit to prevent further data cache
0092      * allocation. Clearing SCTLR.C would make all the data accesses
0093      * strongly ordered and would not hit the cache.
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      * Invalidate L1 and L2 data cache.
0103      */
0104     ldr r1, kernel_flush
0105     blx r1
0106 
0107 #ifdef CONFIG_CACHE_L2X0
0108     /*
0109      * Clean and invalidate the L2 cache.
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     /* Restore wfi_flags */
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      * If we are trying to enter RTC+DDR mode we must perform
0161      * a read from the rtc address space to ensure translation
0162      * presence in the TLB to avoid page table walk after DDR
0163      * is unavailable.
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     /* Check if we want self refresh */
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     /* Only necessary if PER is losing context */
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     /* Only can disable EMIF if we have entered self refresh */
0192     tst r4, #WFI_FLAG_SELF_REFRESH
0193     beq emif_skip_disable
0194 
0195     /* Disable EMIF */
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     /* Wait for 2 seconds to lose power */
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      * For the MPU WFI to be registered as an interrupt
0241      * to WKUP_M3, MPU_CLKCTRL.MODULEMODE needs to be set
0242      * to DISABLED
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      * Put MPU CLKDM to SW_SLEEP
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      * Execute a barrier instruction to ensure that all cache,
0259      * TLB and branch predictor maintenance operations issued
0260      * have completed.
0261      */
0262     dsb
0263     dmb
0264 
0265     /*
0266      * Execute a WFI instruction and wait until the
0267      * STANDBYWFI output is asserted to indicate that the
0268      * CPU is in idle and low power state. CPU can specualatively
0269      * prefetch the instructions so add NOPs after WFI. Sixteen
0270      * NOPs as per Cortex-A9 pipeline.
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     /* We come here in case of an abort due to a late interrupt */
0292     ldr r1, am43xx_virt_mpu_clkstctrl
0293     mov r2, #AM43XX_CM_CLKSTCTRL_CLKTRCTRL_HW_AUTO
0294     str r2, [r1]
0295 
0296     /* Set MPU_CLKCTRL.MODULEMODE back to ENABLE */
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     /* Re-enable EMIF */
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      * Set SCTLR.C bit to allow data cache allocation
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     /* Only necessary if PER is losing context */
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     /* Let the suspend code know about the abort */
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     /* Set MPU CLKSTCTRL to HW AUTO so that CPUidle works properly */
0343     ldr r1, am43xx_virt_mpu_clkstctrl
0344     mov r2, #AM43XX_CM_CLKSTCTRL_CLKTRCTRL_HW_AUTO
0345     str r2, [r1]
0346 
0347     /* For AM43xx, use EMIF power down until context is restored */
0348     ldr r2, am43xx_phys_emif_poweroff
0349     mov r1, #AM43XX_EMIF_POWEROFF_ENABLE
0350     str r1, [r2, #0x0]
0351 
0352     /* Re-enable EMIF */
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     /* L2 invalidate on resume */
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     /* We are back. Branch to the common CPU resume routine */
0431     mov r0, #0
0432     ldr pc, resume_addr
0433 ENDPROC(am43xx_resume_from_deep_sleep)
0434 
0435 /*
0436  * Local variables
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 /* L2 cache related defines for AM437x */
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 /* DDR related defines */
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