~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm/mach-omap2/sleep43xx.S

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* SPDX-License-Identifier: GPL-2.0 */
  2 /*
  3  * Low level suspend code for AM43XX SoCs
  4  *
  5  * Copyright (C) 2013-2018 Texas Instruments Incorporated - https://www.ti.com/
  6  *      Dave Gerlach, Vaibhav Bedia
  7  */
  8 
  9 #include <linux/linkage.h>
 10 #include <linux/ti-emif-sram.h>
 11 #include <linux/platform_data/pm33xx.h>
 12 #include <asm/assembler.h>
 13 #include <asm/hardware/cache-l2x0.h>
 14 #include <asm/page.h>
 15 
 16 #include "cm33xx.h"
 17 #include "common.h"
 18 #include "iomap.h"
 19 #include "omap-secure.h"
 20 #include "omap44xx.h"
 21 #include "pm-asm-offsets.h"
 22 #include "prm33xx.h"
 23 #include "prcm43xx.h"
 24 
 25 /* replicated define because linux/bitops.h cannot be included in assembly */
 26 #define BIT(nr)                 (1 << (nr))
 27 
 28 #define AM33XX_CM_CLKCTRL_MODULESTATE_DISABLED          0x00030000
 29 #define AM33XX_CM_CLKCTRL_MODULEMODE_DISABLE            0x0003
 30 #define AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE             0x0002
 31 
 32 #define AM43XX_EMIF_POWEROFF_ENABLE                     0x1
 33 #define AM43XX_EMIF_POWEROFF_DISABLE                    0x0
 34 
 35 #define AM43XX_CM_CLKSTCTRL_CLKTRCTRL_SW_SLEEP          0x1
 36 #define AM43XX_CM_CLKSTCTRL_CLKTRCTRL_HW_AUTO           0x3
 37 
 38 #define AM43XX_CM_BASE                                  0x44DF0000
 39 
 40 #define AM43XX_CM_REGADDR(inst, reg)                           \
 41        AM33XX_L4_WK_IO_ADDRESS(AM43XX_CM_BASE + (inst) + (reg))
 42 
 43 #define AM43XX_CM_MPU_CLKSTCTRL AM43XX_CM_REGADDR(AM43XX_CM_MPU_INST, \
 44                                         AM43XX_CM_MPU_MPU_CDOFFS)
 45 #define AM43XX_CM_MPU_MPU_CLKCTRL AM43XX_CM_REGADDR(AM43XX_CM_MPU_INST, \
 46                                         AM43XX_CM_MPU_MPU_CLKCTRL_OFFSET)
 47 #define AM43XX_CM_PER_EMIF_CLKCTRL  AM43XX_CM_REGADDR(AM43XX_CM_PER_INST, \
 48                                         AM43XX_CM_PER_EMIF_CLKCTRL_OFFSET)
 49 #define AM43XX_PRM_EMIF_CTRL_OFFSET                     0x0030
 50 
 51 #define RTC_SECONDS_REG                                 0x0
 52 #define RTC_PMIC_REG                                    0x98
 53 #define RTC_PMIC_POWER_EN                               BIT(16)
 54 #define RTC_PMIC_EXT_WAKEUP_STS                         BIT(12)
 55 #define RTC_PMIC_EXT_WAKEUP_POL                         BIT(4)
 56 #define RTC_PMIC_EXT_WAKEUP_EN                          BIT(0)
 57 
 58         .arm
 59         .arch armv7-a
 60         .arch_extension sec
 61         .align 3
 62 
 63 ENTRY(am43xx_do_wfi)
 64         stmfd   sp!, {r4 - r11, lr}     @ save registers on stack
 65 
 66         /* Save wfi_flags arg to data space */
 67         mov     r4, r0
 68         adr     r3, am43xx_pm_ro_sram_data
 69         ldr     r2, [r3, #AMX3_PM_RO_SRAM_DATA_VIRT_OFFSET]
 70         str     r4, [r2, #AMX3_PM_WFI_FLAGS_OFFSET]
 71 
 72 #ifdef CONFIG_CACHE_L2X0
 73         /* Retrieve l2 cache virt address BEFORE we shut off EMIF */
 74         ldr     r1, get_l2cache_base
 75         blx     r1
 76         mov     r8, r0
 77 #endif
 78 
 79         /* Only flush cache is we know we are losing MPU context */
 80         tst     r4, #WFI_FLAG_FLUSH_CACHE
 81         beq     cache_skip_flush
 82 
 83         /*
 84          * Flush all data from the L1 and L2 data cache before disabling
 85          * SCTLR.C bit.
 86          */
 87         ldr     r1, kernel_flush
 88         blx     r1
 89 
 90         /*
 91          * Clear the SCTLR.C bit to prevent further data cache
 92          * allocation. Clearing SCTLR.C would make all the data accesses
 93          * strongly ordered and would not hit the cache.
 94          */
 95         mrc     p15, 0, r0, c1, c0, 0
 96         bic     r0, r0, #(1 << 2)       @ Disable the C bit
 97         mcr     p15, 0, r0, c1, c0, 0
 98         isb
 99         dsb
100 
101         /*
102          * Invalidate L1 and L2 data cache.
103          */
104         ldr     r1, kernel_flush
105         blx     r1
106 
107 #ifdef CONFIG_CACHE_L2X0
108         /*
109          * Clean and invalidate the L2 cache.
110          */
111 #ifdef CONFIG_PL310_ERRATA_727915
112         mov     r0, #0x03
113         mov     r12, #OMAP4_MON_L2X0_DBG_CTRL_INDEX
114         dsb
115         smc     #0
116         dsb
117 #endif
118         mov     r0, r8
119         adr     r4, am43xx_pm_ro_sram_data
120         ldr     r3, [r4, #AMX3_PM_RO_SRAM_DATA_VIRT_OFFSET]
121 
122         mov     r2, r0
123         ldr     r0, [r2, #L2X0_AUX_CTRL]
124         str     r0, [r3, #AMX3_PM_L2_AUX_CTRL_VAL_OFFSET]
125         ldr     r0, [r2, #L310_PREFETCH_CTRL]
126         str     r0, [r3, #AMX3_PM_L2_PREFETCH_CTRL_VAL_OFFSET]
127 
128         ldr     r0, l2_val
129         str     r0, [r2, #L2X0_CLEAN_INV_WAY]
130 wait:
131         ldr     r0, [r2, #L2X0_CLEAN_INV_WAY]
132         ldr     r1, l2_val
133         ands    r0, r0, r1
134         bne     wait
135 #ifdef CONFIG_PL310_ERRATA_727915
136         mov     r0, #0x00
137         mov     r12, #OMAP4_MON_L2X0_DBG_CTRL_INDEX
138         dsb
139         smc     #0
140         dsb
141 #endif
142 l2x_sync:
143         mov     r0, r8
144         mov     r2, r0
145         mov     r0, #0x0
146         str     r0, [r2, #L2X0_CACHE_SYNC]
147 sync:
148         ldr     r0, [r2, #L2X0_CACHE_SYNC]
149         ands    r0, r0, #0x1
150         bne     sync
151 #endif
152 
153         /* Restore wfi_flags */
154         adr     r3, am43xx_pm_ro_sram_data
155         ldr     r2, [r3, #AMX3_PM_RO_SRAM_DATA_VIRT_OFFSET]
156         ldr     r4, [r2, #AMX3_PM_WFI_FLAGS_OFFSET]
157 
158 cache_skip_flush:
159         /*
160          * If we are trying to enter RTC+DDR mode we must perform
161          * a read from the rtc address space to ensure translation
162          * presence in the TLB to avoid page table walk after DDR
163          * is unavailable.
164          */
165         tst     r4, #WFI_FLAG_RTC_ONLY
166         beq     skip_rtc_va_refresh
167 
168         adr     r3, am43xx_pm_ro_sram_data
169         ldr     r1, [r3, #AMX3_PM_RTC_BASE_VIRT_OFFSET]
170         ldr     r0, [r1]
171 
172 skip_rtc_va_refresh:
173         /* Check if we want self refresh */
174         tst     r4, #WFI_FLAG_SELF_REFRESH
175         beq     emif_skip_enter_sr
176 
177         adr     r9, am43xx_emif_sram_table
178 
179         ldr     r3, [r9, #EMIF_PM_ENTER_SR_OFFSET]
180         blx     r3
181 
182 emif_skip_enter_sr:
183         /* Only necessary if PER is losing context */
184         tst     r4, #WFI_FLAG_SAVE_EMIF
185         beq     emif_skip_save
186 
187         ldr     r3, [r9, #EMIF_PM_SAVE_CONTEXT_OFFSET]
188         blx     r3
189 
190 emif_skip_save:
191         /* Only can disable EMIF if we have entered self refresh */
192         tst     r4, #WFI_FLAG_SELF_REFRESH
193         beq     emif_skip_disable
194 
195         /* Disable EMIF */
196         ldr     r1, am43xx_virt_emif_clkctrl
197         ldr     r2, [r1]
198         bic     r2, r2, #AM33XX_CM_CLKCTRL_MODULEMODE_DISABLE
199         str     r2, [r1]
200 
201 wait_emif_disable:
202         ldr     r2, [r1]
203         mov     r3, #AM33XX_CM_CLKCTRL_MODULESTATE_DISABLED
204         cmp     r2, r3
205         bne     wait_emif_disable
206 
207 emif_skip_disable:
208         tst     r4, #WFI_FLAG_RTC_ONLY
209         beq     skip_rtc_only
210 
211         adr     r3, am43xx_pm_ro_sram_data
212         ldr     r1, [r3, #AMX3_PM_RTC_BASE_VIRT_OFFSET]
213 
214         ldr     r0, [r1, #RTC_PMIC_REG]
215         orr     r0, r0, #RTC_PMIC_POWER_EN
216         orr     r0, r0, #RTC_PMIC_EXT_WAKEUP_STS
217         orr     r0, r0, #RTC_PMIC_EXT_WAKEUP_EN
218         orr     r0, r0, #RTC_PMIC_EXT_WAKEUP_POL
219         str     r0, [r1, #RTC_PMIC_REG]
220         ldr     r0, [r1, #RTC_PMIC_REG]
221         /* Wait for 2 seconds to lose power */
222         mov     r3, #2
223         ldr     r2, [r1, #RTC_SECONDS_REG]
224 rtc_loop:
225         ldr     r0, [r1, #RTC_SECONDS_REG]
226         cmp     r0, r2
227         beq     rtc_loop
228         mov     r2, r0
229         subs    r3, r3, #1
230         bne     rtc_loop
231 
232         b       re_enable_emif
233 
234 skip_rtc_only:
235 
236         tst     r4, #WFI_FLAG_WAKE_M3
237         beq     wkup_m3_skip
238 
239         /*
240          * For the MPU WFI to be registered as an interrupt
241          * to WKUP_M3, MPU_CLKCTRL.MODULEMODE needs to be set
242          * to DISABLED
243          */
244         ldr     r1, am43xx_virt_mpu_clkctrl
245         ldr     r2, [r1]
246         bic     r2, r2, #AM33XX_CM_CLKCTRL_MODULEMODE_DISABLE
247         str     r2, [r1]
248 
249         /*
250          * Put MPU CLKDM to SW_SLEEP
251          */
252         ldr     r1, am43xx_virt_mpu_clkstctrl
253         mov     r2, #AM43XX_CM_CLKSTCTRL_CLKTRCTRL_SW_SLEEP
254         str     r2, [r1]
255 
256 wkup_m3_skip:
257         /*
258          * Execute a barrier instruction to ensure that all cache,
259          * TLB and branch predictor maintenance operations issued
260          * have completed.
261          */
262         dsb
263         dmb
264 
265         /*
266          * Execute a WFI instruction and wait until the
267          * STANDBYWFI output is asserted to indicate that the
268          * CPU is in idle and low power state. CPU can specualatively
269          * prefetch the instructions so add NOPs after WFI. Sixteen
270          * NOPs as per Cortex-A9 pipeline.
271          */
272         wfi
273 
274         nop
275         nop
276         nop
277         nop
278         nop
279         nop
280         nop
281         nop
282         nop
283         nop
284         nop
285         nop
286         nop
287         nop
288         nop
289         nop
290 
291         /* We come here in case of an abort due to a late interrupt */
292         ldr     r1, am43xx_virt_mpu_clkstctrl
293         mov     r2, #AM43XX_CM_CLKSTCTRL_CLKTRCTRL_HW_AUTO
294         str     r2, [r1]
295 
296         /* Set MPU_CLKCTRL.MODULEMODE back to ENABLE */
297         ldr     r1, am43xx_virt_mpu_clkctrl
298         mov     r2, #AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE
299         str     r2, [r1]
300 
301 re_enable_emif:
302         /* Re-enable EMIF */
303         ldr     r1, am43xx_virt_emif_clkctrl
304         mov     r2, #AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE
305         str     r2, [r1]
306 wait_emif_enable:
307         ldr     r3, [r1]
308         cmp     r2, r3
309         bne     wait_emif_enable
310 
311         tst     r4, #WFI_FLAG_FLUSH_CACHE
312         beq     cache_skip_restore
313 
314         /*
315          * Set SCTLR.C bit to allow data cache allocation
316          */
317         mrc     p15, 0, r0, c1, c0, 0
318         orr     r0, r0, #(1 << 2)       @ Enable the C bit
319         mcr     p15, 0, r0, c1, c0, 0
320         isb
321 
322 cache_skip_restore:
323         /* Only necessary if PER is losing context */
324         tst     r4, #WFI_FLAG_SELF_REFRESH
325         beq     emif_skip_exit_sr_abt
326 
327         adr     r9, am43xx_emif_sram_table
328         ldr     r1, [r9, #EMIF_PM_ABORT_SR_OFFSET]
329         blx     r1
330 
331 emif_skip_exit_sr_abt:
332         /* Let the suspend code know about the abort */
333         mov     r0, #1
334         ldmfd   sp!, {r4 - r11, pc}     @ restore regs and return
335 ENDPROC(am43xx_do_wfi)
336 
337         .align
338 ENTRY(am43xx_resume_offset)
339         .word . - am43xx_do_wfi
340 
341 ENTRY(am43xx_resume_from_deep_sleep)
342         /* Set MPU CLKSTCTRL to HW AUTO so that CPUidle works properly */
343         ldr     r1, am43xx_virt_mpu_clkstctrl
344         mov     r2, #AM43XX_CM_CLKSTCTRL_CLKTRCTRL_HW_AUTO
345         str     r2, [r1]
346 
347         /* For AM43xx, use EMIF power down until context is restored */
348         ldr     r2, am43xx_phys_emif_poweroff
349         mov     r1, #AM43XX_EMIF_POWEROFF_ENABLE
350         str     r1, [r2, #0x0]
351 
352         /* Re-enable EMIF */
353         ldr     r1, am43xx_phys_emif_clkctrl
354         mov     r2, #AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE
355         str     r2, [r1]
356 wait_emif_enable1:
357         ldr     r3, [r1]
358         cmp     r2, r3
359         bne     wait_emif_enable1
360 
361         adr     r9, am43xx_emif_sram_table
362 
363         ldr     r1, [r9, #EMIF_PM_RESTORE_CONTEXT_OFFSET]
364         blx     r1
365 
366         ldr     r1, [r9, #EMIF_PM_EXIT_SR_OFFSET]
367         blx     r1
368 
369         ldr     r2, am43xx_phys_emif_poweroff
370         mov     r1, #AM43XX_EMIF_POWEROFF_DISABLE
371         str     r1, [r2, #0x0]
372 
373         ldr     r1, [r9, #EMIF_PM_RUN_HW_LEVELING]
374         blx     r1
375 
376 #ifdef CONFIG_CACHE_L2X0
377         ldr     r2, l2_cache_base
378         ldr     r0, [r2, #L2X0_CTRL]
379         and     r0, #0x0f
380         cmp     r0, #1
381         beq     skip_l2en                       @ Skip if already enabled
382 
383         adr     r4, am43xx_pm_ro_sram_data
384         ldr     r3, [r4, #AMX3_PM_RO_SRAM_DATA_PHYS_OFFSET]
385         ldr     r0, [r3, #AMX3_PM_L2_PREFETCH_CTRL_VAL_OFFSET]
386 
387         ldr     r12, l2_smc1
388         dsb
389         smc     #0
390         dsb
391 set_aux_ctrl:
392         ldr     r0, [r3, #AMX3_PM_L2_AUX_CTRL_VAL_OFFSET]
393         ldr     r12, l2_smc2
394         dsb
395         smc     #0
396         dsb
397 
398         /* L2 invalidate on resume */
399         ldr     r0, l2_val
400         ldr     r2, l2_cache_base
401         str     r0, [r2, #L2X0_INV_WAY]
402 wait2:
403         ldr     r0, [r2, #L2X0_INV_WAY]
404         ldr     r1, l2_val
405         ands    r0, r0, r1
406         bne     wait2
407 #ifdef CONFIG_PL310_ERRATA_727915
408         mov     r0, #0x00
409         mov     r12, #OMAP4_MON_L2X0_DBG_CTRL_INDEX
410         dsb
411         smc     #0
412         dsb
413 #endif
414 l2x_sync2:
415         ldr     r2, l2_cache_base
416         mov     r0, #0x0
417         str     r0, [r2, #L2X0_CACHE_SYNC]
418 sync2:
419         ldr     r0, [r2, #L2X0_CACHE_SYNC]
420         ands    r0, r0, #0x1
421         bne     sync2
422 
423         mov     r0, #0x1
424         ldr     r12, l2_smc3
425         dsb
426         smc     #0
427         dsb
428 #endif
429 skip_l2en:
430         /* We are back. Branch to the common CPU resume routine */
431         mov     r0, #0
432         ldr     pc, resume_addr
433 ENDPROC(am43xx_resume_from_deep_sleep)
434 
435 /*
436  * Local variables
437  */
438         .align
439 kernel_flush:
440         .word   v7_flush_dcache_all
441 ddr_start:
442         .word   PAGE_OFFSET
443 
444 am43xx_phys_emif_poweroff:
445         .word   (AM43XX_CM_BASE + AM43XX_PRM_DEVICE_INST + \
446                  AM43XX_PRM_EMIF_CTRL_OFFSET)
447 am43xx_virt_mpu_clkstctrl:
448         .word   (AM43XX_CM_MPU_CLKSTCTRL)
449 am43xx_virt_mpu_clkctrl:
450         .word   (AM43XX_CM_MPU_MPU_CLKCTRL)
451 am43xx_virt_emif_clkctrl:
452         .word   (AM43XX_CM_PER_EMIF_CLKCTRL)
453 am43xx_phys_emif_clkctrl:
454         .word   (AM43XX_CM_BASE + AM43XX_CM_PER_INST + \
455                  AM43XX_CM_PER_EMIF_CLKCTRL_OFFSET)
456 
457 #ifdef CONFIG_CACHE_L2X0
458 /* L2 cache related defines for AM437x */
459 get_l2cache_base:
460         .word   omap4_get_l2cache_base
461 l2_cache_base:
462         .word   OMAP44XX_L2CACHE_BASE
463 l2_smc1:
464         .word   OMAP4_MON_L2X0_PREFETCH_INDEX
465 l2_smc2:
466         .word   OMAP4_MON_L2X0_AUXCTRL_INDEX
467 l2_smc3:
468         .word   OMAP4_MON_L2X0_CTRL_INDEX
469 l2_val:
470         .word   0xffff
471 #endif
472 
473 .align 3
474 /* DDR related defines */
475 ENTRY(am43xx_emif_sram_table)
476         .space EMIF_PM_FUNCTIONS_SIZE
477 
478 ENTRY(am43xx_pm_sram)
479         .word am43xx_do_wfi
480         .word am43xx_do_wfi_sz
481         .word am43xx_resume_offset
482         .word am43xx_emif_sram_table
483         .word am43xx_pm_ro_sram_data
484 
485 resume_addr:
486         .word   cpu_resume - PAGE_OFFSET + 0x80000000
487 .align 3
488 
489 ENTRY(am43xx_pm_ro_sram_data)
490         .space AMX3_PM_RO_SRAM_DATA_SIZE
491 
492 ENTRY(am43xx_do_wfi_sz)
493         .word   . - am43xx_do_wfi

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php