xref: /openbmc/linux/arch/arm/mach-omap2/sleep33xx.S (revision 8a94cd7e)
18a94cd7eSDave Gerlach/* SPDX-License-Identifier: GPL-2.0 */
28a94cd7eSDave Gerlach/*
38a94cd7eSDave Gerlach * Low level suspend code for AM33XX SoCs
48a94cd7eSDave Gerlach *
58a94cd7eSDave Gerlach * Copyright (C) 2012-2018 Texas Instruments Incorporated - http://www.ti.com/
68a94cd7eSDave Gerlach *	Dave Gerlach, Vaibhav Bedia
78a94cd7eSDave Gerlach */
88a94cd7eSDave Gerlach
98a94cd7eSDave Gerlach#include <linux/linkage.h>
108a94cd7eSDave Gerlach#include <linux/ti-emif-sram.h>
118a94cd7eSDave Gerlach#include <asm/assembler.h>
128a94cd7eSDave Gerlach#include <asm/memory.h>
138a94cd7eSDave Gerlach
148a94cd7eSDave Gerlach#include "iomap.h"
158a94cd7eSDave Gerlach#include "cm33xx.h"
168a94cd7eSDave Gerlach
178a94cd7eSDave Gerlach#define AM33XX_CM_CLKCTRL_MODULESTATE_DISABLED			0x00030000
188a94cd7eSDave Gerlach#define AM33XX_CM_CLKCTRL_MODULEMODE_DISABLE			0x0003
198a94cd7eSDave Gerlach#define AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE			0x0002
208a94cd7eSDave Gerlach
218a94cd7eSDave Gerlach	.arm
228a94cd7eSDave Gerlach	.align 3
238a94cd7eSDave Gerlach
248a94cd7eSDave GerlachENTRY(am33xx_do_wfi)
258a94cd7eSDave Gerlach	stmfd	sp!, {r4 - r11, lr}	@ save registers on stack
268a94cd7eSDave Gerlach
278a94cd7eSDave Gerlach	/*
288a94cd7eSDave Gerlach	 * Flush all data from the L1 and L2 data cache before disabling
298a94cd7eSDave Gerlach	 * SCTLR.C bit.
308a94cd7eSDave Gerlach	 */
318a94cd7eSDave Gerlach	ldr	r1, kernel_flush
328a94cd7eSDave Gerlach	blx	r1
338a94cd7eSDave Gerlach
348a94cd7eSDave Gerlach	/*
358a94cd7eSDave Gerlach	 * Clear the SCTLR.C bit to prevent further data cache
368a94cd7eSDave Gerlach	 * allocation. Clearing SCTLR.C would make all the data accesses
378a94cd7eSDave Gerlach	 * strongly ordered and would not hit the cache.
388a94cd7eSDave Gerlach	 */
398a94cd7eSDave Gerlach	mrc	p15, 0, r0, c1, c0, 0
408a94cd7eSDave Gerlach	bic	r0, r0, #(1 << 2)	@ Disable the C bit
418a94cd7eSDave Gerlach	mcr	p15, 0, r0, c1, c0, 0
428a94cd7eSDave Gerlach	isb
438a94cd7eSDave Gerlach
448a94cd7eSDave Gerlach	/*
458a94cd7eSDave Gerlach	 * Invalidate L1 and L2 data cache.
468a94cd7eSDave Gerlach	 */
478a94cd7eSDave Gerlach	ldr	r1, kernel_flush
488a94cd7eSDave Gerlach	blx	r1
498a94cd7eSDave Gerlach
508a94cd7eSDave Gerlach	adr	r9, am33xx_emif_sram_table
518a94cd7eSDave Gerlach
528a94cd7eSDave Gerlach	ldr	r3, [r9, #EMIF_PM_ENTER_SR_OFFSET]
538a94cd7eSDave Gerlach	blx	r3
548a94cd7eSDave Gerlach
558a94cd7eSDave Gerlach	ldr	r3, [r9, #EMIF_PM_SAVE_CONTEXT_OFFSET]
568a94cd7eSDave Gerlach	blx	r3
578a94cd7eSDave Gerlach
588a94cd7eSDave Gerlach	/* Disable EMIF */
598a94cd7eSDave Gerlach	ldr     r1, virt_emif_clkctrl
608a94cd7eSDave Gerlach	ldr     r2, [r1]
618a94cd7eSDave Gerlach	bic     r2, r2, #AM33XX_CM_CLKCTRL_MODULEMODE_DISABLE
628a94cd7eSDave Gerlach	str     r2, [r1]
638a94cd7eSDave Gerlach
648a94cd7eSDave Gerlach	ldr	r1, virt_emif_clkctrl
658a94cd7eSDave Gerlachwait_emif_disable:
668a94cd7eSDave Gerlach	ldr	r2, [r1]
678a94cd7eSDave Gerlach	mov	r3, #AM33XX_CM_CLKCTRL_MODULESTATE_DISABLED
688a94cd7eSDave Gerlach	cmp	r2, r3
698a94cd7eSDave Gerlach	bne	wait_emif_disable
708a94cd7eSDave Gerlach
718a94cd7eSDave Gerlach	/*
728a94cd7eSDave Gerlach	 * For the MPU WFI to be registered as an interrupt
738a94cd7eSDave Gerlach	 * to WKUP_M3, MPU_CLKCTRL.MODULEMODE needs to be set
748a94cd7eSDave Gerlach	 * to DISABLED
758a94cd7eSDave Gerlach	 */
768a94cd7eSDave Gerlach	ldr	r1, virt_mpu_clkctrl
778a94cd7eSDave Gerlach	ldr	r2, [r1]
788a94cd7eSDave Gerlach	bic	r2, r2, #AM33XX_CM_CLKCTRL_MODULEMODE_DISABLE
798a94cd7eSDave Gerlach	str	r2, [r1]
808a94cd7eSDave Gerlach
818a94cd7eSDave Gerlach	/*
828a94cd7eSDave Gerlach	 * Execute an ISB instruction to ensure that all of the
838a94cd7eSDave Gerlach	 * CP15 register changes have been committed.
848a94cd7eSDave Gerlach	 */
858a94cd7eSDave Gerlach	isb
868a94cd7eSDave Gerlach
878a94cd7eSDave Gerlach	/*
888a94cd7eSDave Gerlach	 * Execute a barrier instruction to ensure that all cache,
898a94cd7eSDave Gerlach	 * TLB and branch predictor maintenance operations issued
908a94cd7eSDave Gerlach	 * have completed.
918a94cd7eSDave Gerlach	 */
928a94cd7eSDave Gerlach	dsb
938a94cd7eSDave Gerlach	dmb
948a94cd7eSDave Gerlach
958a94cd7eSDave Gerlach	/*
968a94cd7eSDave Gerlach	 * Execute a WFI instruction and wait until the
978a94cd7eSDave Gerlach	 * STANDBYWFI output is asserted to indicate that the
988a94cd7eSDave Gerlach	 * CPU is in idle and low power state. CPU can specualatively
998a94cd7eSDave Gerlach	 * prefetch the instructions so add NOPs after WFI. Thirteen
1008a94cd7eSDave Gerlach	 * NOPs as per Cortex-A8 pipeline.
1018a94cd7eSDave Gerlach	 */
1028a94cd7eSDave Gerlach	wfi
1038a94cd7eSDave Gerlach
1048a94cd7eSDave Gerlach	nop
1058a94cd7eSDave Gerlach	nop
1068a94cd7eSDave Gerlach	nop
1078a94cd7eSDave Gerlach	nop
1088a94cd7eSDave Gerlach	nop
1098a94cd7eSDave Gerlach	nop
1108a94cd7eSDave Gerlach	nop
1118a94cd7eSDave Gerlach	nop
1128a94cd7eSDave Gerlach	nop
1138a94cd7eSDave Gerlach	nop
1148a94cd7eSDave Gerlach	nop
1158a94cd7eSDave Gerlach	nop
1168a94cd7eSDave Gerlach	nop
1178a94cd7eSDave Gerlach
1188a94cd7eSDave Gerlach	/* We come here in case of an abort due to a late interrupt */
1198a94cd7eSDave Gerlach
1208a94cd7eSDave Gerlach	/* Set MPU_CLKCTRL.MODULEMODE back to ENABLE */
1218a94cd7eSDave Gerlach	ldr	r1, virt_mpu_clkctrl
1228a94cd7eSDave Gerlach	mov	r2, #AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE
1238a94cd7eSDave Gerlach	str	r2, [r1]
1248a94cd7eSDave Gerlach
1258a94cd7eSDave Gerlach	/* Re-enable EMIF */
1268a94cd7eSDave Gerlach	ldr	r1, virt_emif_clkctrl
1278a94cd7eSDave Gerlach	mov	r2, #AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE
1288a94cd7eSDave Gerlach	str	r2, [r1]
1298a94cd7eSDave Gerlachwait_emif_enable:
1308a94cd7eSDave Gerlach	ldr	r3, [r1]
1318a94cd7eSDave Gerlach	cmp	r2, r3
1328a94cd7eSDave Gerlach	bne	wait_emif_enable
1338a94cd7eSDave Gerlach
1348a94cd7eSDave Gerlach
1358a94cd7eSDave Gerlach	ldr	r1, [r9, #EMIF_PM_ABORT_SR_OFFSET]
1368a94cd7eSDave Gerlach	blx	r1
1378a94cd7eSDave Gerlach
1388a94cd7eSDave Gerlach	/*
1398a94cd7eSDave Gerlach	 * Set SCTLR.C bit to allow data cache allocation
1408a94cd7eSDave Gerlach	 */
1418a94cd7eSDave Gerlach	mrc	p15, 0, r0, c1, c0, 0
1428a94cd7eSDave Gerlach	orr	r0, r0, #(1 << 2)	@ Enable the C bit
1438a94cd7eSDave Gerlach	mcr	p15, 0, r0, c1, c0, 0
1448a94cd7eSDave Gerlach	isb
1458a94cd7eSDave Gerlach
1468a94cd7eSDave Gerlach	/* Let the suspend code know about the abort */
1478a94cd7eSDave Gerlach	mov	r0, #1
1488a94cd7eSDave Gerlach	ldmfd	sp!, {r4 - r11, pc}	@ restore regs and return
1498a94cd7eSDave GerlachENDPROC(am33xx_do_wfi)
1508a94cd7eSDave Gerlach
1518a94cd7eSDave Gerlach	.align
1528a94cd7eSDave GerlachENTRY(am33xx_resume_offset)
1538a94cd7eSDave Gerlach	.word . - am33xx_do_wfi
1548a94cd7eSDave Gerlach
1558a94cd7eSDave GerlachENTRY(am33xx_resume_from_deep_sleep)
1568a94cd7eSDave Gerlach	/* Re-enable EMIF */
1578a94cd7eSDave Gerlach	ldr	r0, phys_emif_clkctrl
1588a94cd7eSDave Gerlach	mov	r1, #AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE
1598a94cd7eSDave Gerlach	str	r1, [r0]
1608a94cd7eSDave Gerlachwait_emif_enable1:
1618a94cd7eSDave Gerlach	ldr	r2, [r0]
1628a94cd7eSDave Gerlach	cmp	r1, r2
1638a94cd7eSDave Gerlach	bne	wait_emif_enable1
1648a94cd7eSDave Gerlach
1658a94cd7eSDave Gerlach	adr	r9, am33xx_emif_sram_table
1668a94cd7eSDave Gerlach
1678a94cd7eSDave Gerlach	ldr	r1, [r9, #EMIF_PM_RESTORE_CONTEXT_OFFSET]
1688a94cd7eSDave Gerlach	blx	r1
1698a94cd7eSDave Gerlach
1708a94cd7eSDave Gerlach	ldr	r1, [r9, #EMIF_PM_EXIT_SR_OFFSET]
1718a94cd7eSDave Gerlach	blx	r1
1728a94cd7eSDave Gerlach
1738a94cd7eSDave Gerlachresume_to_ddr:
1748a94cd7eSDave Gerlach	/* We are back. Branch to the common CPU resume routine */
1758a94cd7eSDave Gerlach	mov	r0, #0
1768a94cd7eSDave Gerlach	ldr	pc, resume_addr
1778a94cd7eSDave GerlachENDPROC(am33xx_resume_from_deep_sleep)
1788a94cd7eSDave Gerlach
1798a94cd7eSDave Gerlach/*
1808a94cd7eSDave Gerlach * Local variables
1818a94cd7eSDave Gerlach */
1828a94cd7eSDave Gerlach	.align
1838a94cd7eSDave Gerlachresume_addr:
1848a94cd7eSDave Gerlach	.word	cpu_resume - PAGE_OFFSET + 0x80000000
1858a94cd7eSDave Gerlachkernel_flush:
1868a94cd7eSDave Gerlach	.word   v7_flush_dcache_all
1878a94cd7eSDave Gerlachvirt_mpu_clkctrl:
1888a94cd7eSDave Gerlach	.word	AM33XX_CM_MPU_MPU_CLKCTRL
1898a94cd7eSDave Gerlachvirt_emif_clkctrl:
1908a94cd7eSDave Gerlach	.word	AM33XX_CM_PER_EMIF_CLKCTRL
1918a94cd7eSDave Gerlachphys_emif_clkctrl:
1928a94cd7eSDave Gerlach	.word	(AM33XX_CM_BASE + AM33XX_CM_PER_MOD + \
1938a94cd7eSDave Gerlach		AM33XX_CM_PER_EMIF_CLKCTRL_OFFSET)
1948a94cd7eSDave Gerlach
1958a94cd7eSDave Gerlach.align 3
1968a94cd7eSDave Gerlach/* DDR related defines */
1978a94cd7eSDave Gerlacham33xx_emif_sram_table:
1988a94cd7eSDave Gerlach	.space EMIF_PM_FUNCTIONS_SIZE
1998a94cd7eSDave Gerlach
2008a94cd7eSDave GerlachENTRY(am33xx_pm_sram)
2018a94cd7eSDave Gerlach	.word am33xx_do_wfi
2028a94cd7eSDave Gerlach	.word am33xx_do_wfi_sz
2038a94cd7eSDave Gerlach	.word am33xx_resume_offset
2048a94cd7eSDave Gerlach	.word am33xx_emif_sram_table
2058a94cd7eSDave Gerlach	.word am33xx_pm_ro_sram_data
2068a94cd7eSDave Gerlach
2078a94cd7eSDave Gerlach.align 3
2088a94cd7eSDave GerlachENTRY(am33xx_pm_ro_sram_data)
2098a94cd7eSDave Gerlach	.space AMX3_PM_RO_SRAM_DATA_SIZE
2108a94cd7eSDave Gerlach
2118a94cd7eSDave GerlachENTRY(am33xx_do_wfi_sz)
2128a94cd7eSDave Gerlach	.word	. - am33xx_do_wfi
213