Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1611488 > unrolled thread
| Started by | Dave Gerlach <d-gerlach@ti.com> |
|---|---|
| First post | 2017-03-29 04:00 +0200 |
| Last post | 2017-03-29 21:00 +0200 |
| Articles | 8 — 2 participants |
Back to article view | Back to linux.kernel
[PATCH 0/8] ARM: OMAP2+: AM33XX/AM43XX: Add suspend-resume support Dave Gerlach <d-gerlach@ti.com> - 2017-03-29 04:00 +0200
[PATCH 5/8] ARM: OMAP2+: Introduce low-level suspend code for AM43XX Dave Gerlach <d-gerlach@ti.com> - 2017-03-29 04:10 +0200
[PATCH 4/8] ARM: OMAP2+: Introduce low-level suspend code for AM33XX Dave Gerlach <d-gerlach@ti.com> - 2017-03-29 04:10 +0200
[PATCH 6/8] ARM: OMAP2+: pm33xx-core: Add platform code needed for PM Dave Gerlach <d-gerlach@ti.com> - 2017-03-29 04:10 +0200
Re: [PATCH 6/8] ARM: OMAP2+: pm33xx-core: Add platform code needed for PM Tony Lindgren <tony@atomide.com> - 2017-04-04 18:20 +0200
[PATCH 1/8] ARM: OMAP: Wakeupgen: Add context save/restore for AM43XX Dave Gerlach <d-gerlach@ti.com> - 2017-03-29 04:10 +0200
Re: [PATCH 0/8] ARM: OMAP2+: AM33XX/AM43XX: Add suspend-resume support Tony Lindgren <tony@atomide.com> - 2017-03-29 19:20 +0200
Re: [PATCH 0/8] ARM: OMAP2+: AM33XX/AM43XX: Add suspend-resume support Dave Gerlach <d-gerlach@ti.com> - 2017-03-29 21:00 +0200
| From | Dave Gerlach <d-gerlach@ti.com> |
|---|---|
| Date | 2017-03-29 04:00 +0200 |
| Subject | [PATCH 0/8] ARM: OMAP2+: AM33XX/AM43XX: Add suspend-resume support |
| Message-ID | <tqb3X-8bm-3@gated-at.bofh.it> |
Hi, This series contains the remaining code to enable suspend to mem and standby on am335x and am437x platforms. It depends on the ti-emif-sram series sent here [1]. This code also depends on firmware for the wkup_m3 that is available here [2] that can either be placed in /lib/firmware or built in to the kernel. Patch 1,2,3 are straightforward support changes to enable PM. Patches 4 and 5 add the required low-level PM suspend code that is relocated to SRAM for each platform. Patch 6 and patch 7 serve as the split between code that can live in drivers and code that must remain under mach-omap2. The idea here was to maintain the minimal amount of ARM and OMAP specific code inside mach-omap2 while providing ops that can be called into from a module that lives in drivers and contains the bulk of the PM code. Patch 6 also contains additions to the ARM asm-offsets file to allow us to automatically generate C struct member offsets and sizes to be used by the assembly code introduced earlier, more info can be seen in the changelog. Patch 7 introduces the pm33xx driver which makes use of the wkup_m3_ipc and ti-emif-sram drivers to enable PM on the system. Because pm33xx depends on modules it must be able to defer probe so patch 8 creates a dummy pm33xx platform device to cause pm33xx to probe initially but also defer if needed. As with the ti-emif-sram driver, which also contains relocatable SRAM code, we can only get read-only exectuable memory regions from the mmio-sram driver so we also provide a second region to the driver that is read/write to be used for data during execution. This is the reason two sram regions are mapped and so many offsets must be provided to the code section. For testing the drivers required are: CONFIG_MAILBOX CONFIG_OMAP2PLUS_MBOX CONFIG_WKUP_M3_RPROC CONFIG_SOC_TI CONFIG_WKUP_M3_IPC CONFIG_TI_EMIF_SRAM CONFIG_AMX3_PM There is still a device tree patch series to follow that will completely enable PM but I will wait to send that until this series and the emif series have been reviewed, until then all patches have been pushed here for use [3]. Regards, Dave [1] http://www.spinics.net/lists/linux-omap/msg136345.html [2] https://git.ti.com/processor-firmware/ti-amx3-cm3-pm-firmware/blobs/7eb9c0856a9e8b3b42bf64f761da135852b8eea7/bin/am335x-pm-firmware.elf [3] https://github.com/dgerlach/linux-pm/tree/upstream/v4.11/amx3-suspend-dev Dave Gerlach (8): ARM: OMAP: Wakeupgen: Add context save/restore for AM43XX ARM: OMAP2+: timer: Add suspend-resume callbacks for clkevent device ARM: OMAP2+: pm: Remove __init from omap_pm_clkdms_setup ARM: OMAP2+: Introduce low-level suspend code for AM33XX ARM: OMAP2+: Introduce low-level suspend code for AM43XX ARM: OMAP2+: pm33xx-core: Add platform code needed for PM soc: ti: Add pm33xx driver for basic suspend support ARM: OMAP2+: Create dummy platform_device for pm33xx arch/arm/kernel/asm-offsets.c | 2 + arch/arm/mach-omap2/Kconfig | 1 + arch/arm/mach-omap2/Makefile | 4 + arch/arm/mach-omap2/common.h | 7 + arch/arm/mach-omap2/io.c | 2 + arch/arm/mach-omap2/omap-wakeupgen.c | 68 +++++- arch/arm/mach-omap2/pm.c | 2 +- arch/arm/mach-omap2/pm.h | 5 + arch/arm/mach-omap2/pm33xx-core.c | 193 +++++++++++++++++ arch/arm/mach-omap2/sleep33xx.S | 219 +++++++++++++++++++ arch/arm/mach-omap2/sleep43xx.S | 403 +++++++++++++++++++++++++++++++++++ arch/arm/mach-omap2/timer.c | 28 +++ drivers/soc/ti/Kconfig | 9 + drivers/soc/ti/Makefile | 1 + drivers/soc/ti/pm33xx.c | 337 +++++++++++++++++++++++++++++ include/linux/platform_data/pm33xx.h | 69 ++++++ 16 files changed, 1343 insertions(+), 7 deletions(-) create mode 100644 arch/arm/mach-omap2/pm33xx-core.c create mode 100644 arch/arm/mach-omap2/sleep33xx.S create mode 100644 arch/arm/mach-omap2/sleep43xx.S create mode 100644 drivers/soc/ti/pm33xx.c create mode 100644 include/linux/platform_data/pm33xx.h -- 2.11.0
[toc] | [next] | [standalone]
| From | Dave Gerlach <d-gerlach@ti.com> |
|---|---|
| Date | 2017-03-29 04:10 +0200 |
| Subject | [PATCH 5/8] ARM: OMAP2+: Introduce low-level suspend code for AM43XX |
| Message-ID | <tqbdD-8tJ-1@gated-at.bofh.it> |
| In reply to | #1611488 |
Although similar to AM33XX, introduce a new low-level asm file for
suspend containing new context save and restore paths for EMIF and l2
cache disabling and enabling.
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
---
arch/arm/mach-omap2/sleep43xx.S | 403 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 403 insertions(+)
create mode 100644 arch/arm/mach-omap2/sleep43xx.S
diff --git a/arch/arm/mach-omap2/sleep43xx.S b/arch/arm/mach-omap2/sleep43xx.S
new file mode 100644
index 000000000000..6012f83cb7f4
--- /dev/null
+++ b/arch/arm/mach-omap2/sleep43xx.S
@@ -0,0 +1,403 @@
+/*
+ * Low level suspend code for AM43XX SoCs
+ *
+ * Copyright (C) 2013-2017 Texas Instruments Incorporated - http://www.ti.com/
+ * Dave Gerlach, Vaibhav Bedia
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/linkage.h>
+#include <linux/ti-emif-sram.h>
+
+#include <asm/asm-offsets.h>
+#include <asm/assembler.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/memory.h>
+
+#include "cm33xx.h"
+#include "common.h"
+#include "iomap.h"
+#include "omap-secure.h"
+#include "omap44xx.h"
+#include "prm33xx.h"
+#include "prcm43xx.h"
+
+#define AM33XX_CM_CLKCTRL_MODULEMODE_DISABLE 0x0003
+#define AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE 0x0002
+
+#define AM43XX_EMIF_POWEROFF_ENABLE 0x1
+#define AM43XX_EMIF_POWEROFF_DISABLE 0x0
+
+#define AM43XX_CM_CLKSTCTRL_CLKTRCTRL_SW_SLEEP 0x1
+#define AM43XX_CM_CLKSTCTRL_CLKTRCTRL_HW_AUTO 0x3
+
+#define AM43XX_CM_BASE 0x44DF0000
+
+#define AM43XX_CM_REGADDR(inst, reg) \
+ AM33XX_L4_WK_IO_ADDRESS(AM43XX_CM_BASE + (inst) + (reg))
+
+#define AM43XX_CM_MPU_CLKSTCTRL AM43XX_CM_REGADDR(AM43XX_CM_MPU_INST, \
+ AM43XX_CM_MPU_MPU_CDOFFS)
+#define AM43XX_CM_MPU_MPU_CLKCTRL AM43XX_CM_REGADDR(AM43XX_CM_MPU_INST, \
+ AM43XX_CM_MPU_MPU_CLKCTRL_OFFSET)
+#define AM43XX_CM_PER_EMIF_CLKCTRL AM43XX_CM_REGADDR(AM43XX_CM_PER_INST, \
+ AM43XX_CM_PER_EMIF_CLKCTRL_OFFSET)
+#define AM43XX_PRM_EMIF_CTRL_OFFSET 0x0030
+
+ .align 3
+
+ENTRY(am43xx_do_wfi)
+ stmfd sp!, {r4 - r11, lr} @ save registers on stack
+
+ /* Retrieve l2 cache virt address BEFORE we shut off EMIF */
+ ldr r1, get_l2cache_base
+ blx r1
+ mov r8, r0
+
+ /*
+ * Flush all data from the L1 and L2 data cache before disabling
+ * SCTLR.C bit.
+ */
+ ldr r1, kernel_flush
+ blx r1
+
+ /*
+ * Clear the SCTLR.C bit to prevent further data cache
+ * allocation. Clearing SCTLR.C would make all the data accesses
+ * strongly ordered and would not hit the cache.
+ */
+ mrc p15, 0, r0, c1, c0, 0
+ bic r0, r0, #(1 << 2) @ Disable the C bit
+ mcr p15, 0, r0, c1, c0, 0
+ isb
+ dsb
+
+ /*
+ * Invalidate L1 and L2 data cache.
+ */
+ ldr r1, kernel_flush
+ blx r1
+
+ /*
+ * The kernel doesn't interwork: v7_flush_dcache_all in particluar will
+ * always return in Thumb state when CONFIG_THUMB2_KERNEL is enabled.
+ * This sequence switches back to ARM. Note that .align may insert a
+ * nop: bx pc needs to be word-aligned in order to work.
+ */
+ THUMB( .thumb )
+ THUMB( .align )
+ THUMB( bx pc )
+ THUMB( nop )
+ .arm
+
+#ifdef CONFIG_CACHE_L2X0
+ /*
+ * Clean and invalidate the L2 cache.
+ */
+#ifdef CONFIG_PL310_ERRATA_727915
+ mov r0, #0x03
+ mov r12, #OMAP4_MON_L2X0_DBG_CTRL_INDEX
+ dsb
+ smc #0
+ dsb
+#endif
+ mov r0, r8
+ adr r4, am43xx_pm_ro_sram_data
+ ldr r3, [r4, #AMX3_PM_RO_SRAM_DATA_VIRT_OFFSET]
+
+ mov r2, r0
+ ldr r0, [r2, #L2X0_AUX_CTRL]
+ str r0, [r3, #AMX3_PM_L2_AUX_CTRL_VAL_OFFSET]
+ ldr r0, [r2, #L310_PREFETCH_CTRL]
+ str r0, [r3, #AMX3_PM_L2_PREFETCH_CTRL_VAL_OFFSET]
+
+ ldr r0, l2_val
+ str r0, [r2, #L2X0_CLEAN_INV_WAY]
+wait:
+ ldr r0, [r2, #L2X0_CLEAN_INV_WAY]
+ ldr r1, l2_val
+ ands r0, r0, r1
+ bne wait
+#ifdef CONFIG_PL310_ERRATA_727915
+ mov r0, #0x00
+ mov r12, #OMAP4_MON_L2X0_DBG_CTRL_INDEX
+ dsb
+ smc #0
+ dsb
+#endif
+l2x_sync:
+ mov r0, r8
+ mov r2, r0
+ mov r0, #0x0
+ str r0, [r2, #L2X0_CACHE_SYNC]
+sync:
+ ldr r0, [r2, #L2X0_CACHE_SYNC]
+ ands r0, r0, #0x1
+ bne sync
+#endif
+
+ adr r9, am43xx_emif_sram_table
+
+ ldr r3, [r9, #EMIF_PM_SAVE_CONTEXT_OFFSET]
+ blx r3
+
+ ldr r3, [r9, #EMIF_PM_ENTER_SR_OFFSET]
+ blx r3
+
+ /* Disable EMIF */
+ ldr r1, am43xx_virt_emif_clkctrl
+ ldr r2, [r1]
+ bic r2, r2, #AM33XX_CM_CLKCTRL_MODULEMODE_DISABLE
+ str r2, [r1]
+
+wait_emif_disable:
+ ldr r2, [r1]
+ ldr r3, module_disabled_val
+ cmp r2, r3
+ bne wait_emif_disable
+
+ /*
+ * For the MPU WFI to be registered as an interrupt
+ * to WKUP_M3, MPU_CLKCTRL.MODULEMODE needs to be set
+ * to DISABLED
+ */
+ ldr r1, am43xx_virt_mpu_clkctrl
+ ldr r2, [r1]
+ bic r2, r2, #AM33XX_CM_CLKCTRL_MODULEMODE_DISABLE
+ str r2, [r1]
+
+ /*
+ * Put MPU CLKDM to SW_SLEEP
+ */
+ ldr r1, am43xx_virt_mpu_clkstctrl
+ mov r2, #AM43XX_CM_CLKSTCTRL_CLKTRCTRL_SW_SLEEP
+ str r2, [r1]
+
+ /*
+ * Execute a barrier instruction to ensure that all cache,
+ * TLB and branch predictor maintenance operations issued
+ * have completed.
+ */
+ dsb
+ dmb
+
+ /*
+ * Execute a WFI instruction and wait until the
+ * STANDBYWFI output is asserted to indicate that the
+ * CPU is in idle and low power state. CPU can specualatively
+ * prefetch the instructions so add NOPs after WFI. Sixteen
+ * NOPs as per Cortex-A9 pipeline.
+ */
+ wfi
+
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ /* We come here in case of an abort due to a late interrupt */
+ ldr r1, am43xx_virt_mpu_clkstctrl
+ mov r2, #AM43XX_CM_CLKSTCTRL_CLKTRCTRL_HW_AUTO
+ str r2, [r1]
+
+ /* Set MPU_CLKCTRL.MODULEMODE back to ENABLE */
+ ldr r1, am43xx_virt_mpu_clkctrl
+ mov r2, #AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE
+ str r2, [r1]
+
+ /* Re-enable EMIF */
+ ldr r1, am43xx_virt_emif_clkctrl
+ mov r2, #AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE
+ str r2, [r1]
+wait_emif_enable:
+ ldr r3, [r1]
+ cmp r2, r3
+ bne wait_emif_enable
+
+ /*
+ * Set SCTLR.C bit to allow data cache allocation
+ */
+ mrc p15, 0, r0, c1, c0, 0
+ orr r0, r0, #(1 << 2) @ Enable the C bit
+ mcr p15, 0, r0, c1, c0, 0
+ isb
+
+ ldr r1, [r9, #EMIF_PM_ABORT_SR_OFFSET]
+ blx r1
+
+ /* Let the suspend code know about the abort */
+ mov r0, #1
+ ldmfd sp!, {r4 - r11, pc} @ restore regs and return
+ENDPROC(am43xx_do_wfi)
+
+ .align
+ENTRY(am43xx_resume_offset)
+ .word . - am43xx_do_wfi
+
+ENTRY(am43xx_resume_from_deep_sleep)
+ /* Set MPU CLKSTCTRL to HW AUTO so that CPUidle works properly */
+ ldr r1, am43xx_virt_mpu_clkstctrl
+ mov r2, #AM43XX_CM_CLKSTCTRL_CLKTRCTRL_HW_AUTO
+ str r2, [r1]
+
+ /* For AM43xx, use EMIF power down until context is restored */
+ ldr r2, am43xx_phys_emif_poweroff
+ mov r1, #AM43XX_EMIF_POWEROFF_ENABLE
+ str r1, [r2, #0x0]
+
+ /* Re-enable EMIF */
+ ldr r1, am43xx_phys_emif_clkctrl
+ mov r2, #AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE
+ str r2, [r1]
+wait_emif_enable1:
+ ldr r3, [r1]
+ cmp r2, r3
+ bne wait_emif_enable1
+
+ adr r9, am43xx_emif_sram_table
+
+ ldr r1, [r9, #EMIF_PM_RESTORE_CONTEXT_OFFSET]
+ blx r1
+
+ ldr r1, [r9, #EMIF_PM_EXIT_SR_OFFSET]
+ blx r1
+
+ ldr r2, am43xx_phys_emif_poweroff
+ mov r1, #AM43XX_EMIF_POWEROFF_DISABLE
+ str r1, [r2, #0x0]
+
+#ifdef CONFIG_CACHE_L2X0
+ ldr r2, l2_cache_base
+ ldr r0, [r2, #L2X0_CTRL]
+ and r0, #0x0f
+ cmp r0, #1
+ beq skip_l2en @ Skip if already enabled
+
+ adr r4, am43xx_pm_ro_sram_data
+ ldr r3, [r4, #AMX3_PM_RO_SRAM_DATA_PHYS_OFFSET]
+ ldr r0, [r3, #AMX3_PM_L2_PREFETCH_CTRL_VAL_OFFSET]
+
+ ldr r12, l2_smc1
+ dsb
+ smc #0
+ dsb
+set_aux_ctrl:
+ ldr r0, [r3, #AMX3_PM_L2_AUX_CTRL_VAL_OFFSET]
+ ldr r12, l2_smc2
+ dsb
+ smc #0
+ dsb
+
+ /* L2 invalidate on resume */
+ ldr r0, l2_val
+ ldr r2, l2_cache_base
+ str r0, [r2, #L2X0_INV_WAY]
+wait2:
+ ldr r0, [r2, #L2X0_INV_WAY]
+ ldr r1, l2_val
+ ands r0, r0, r1
+ bne wait2
+#ifdef CONFIG_PL310_ERRATA_727915
+ mov r0, #0x00
+ mov r12, #OMAP4_MON_L2X0_DBG_CTRL_INDEX
+ dsb
+ smc #0
+ dsb
+#endif
+l2x_sync2:
+ ldr r2, l2_cache_base
+ mov r0, #0x0
+ str r0, [r2, #L2X0_CACHE_SYNC]
+sync2:
+ ldr r0, [r2, #L2X0_CACHE_SYNC]
+ ands r0, r0, #0x1
+ bne sync2
+
+ mov r0, #0x1
+ ldr r12, l2_smc3
+ dsb
+ smc #0
+ dsb
+#endif
+skip_l2en:
+ /* We are back. Branch to the common CPU resume routine */
+ mov r0, #0
+ ldr pc, resume_addr
+ENDPROC(am43xx_resume_from_deep_sleep)
+
+/*
+ * Local variables
+ */
+ .align
+resume_addr:
+ .word cpu_resume - PAGE_OFFSET + 0x80000000
+get_l2cache_base:
+ .word omap4_get_l2cache_base
+kernel_flush:
+ .word v7_flush_dcache_all
+ddr_start:
+ .word PAGE_OFFSET
+
+am43xx_phys_emif_poweroff:
+ .word (AM43XX_CM_BASE + AM43XX_PRM_DEVICE_INST + \
+ AM43XX_PRM_EMIF_CTRL_OFFSET)
+am43xx_virt_mpu_clkstctrl:
+ .word (AM43XX_CM_MPU_CLKSTCTRL)
+am43xx_virt_mpu_clkctrl:
+ .word (AM43XX_CM_MPU_MPU_CLKCTRL)
+am43xx_virt_emif_clkctrl:
+ .word (AM43XX_CM_PER_EMIF_CLKCTRL)
+am43xx_phys_emif_clkctrl:
+ .word (AM43XX_CM_BASE + AM43XX_CM_PER_INST + \
+ AM43XX_CM_PER_EMIF_CLKCTRL_OFFSET)
+module_disabled_val:
+ .word 0x30000
+
+/* L2 cache related defines for AM437x */
+l2_cache_base:
+ .word OMAP44XX_L2CACHE_BASE
+l2_smc1:
+ .word OMAP4_MON_L2X0_PREFETCH_INDEX
+l2_smc2:
+ .word OMAP4_MON_L2X0_AUXCTRL_INDEX
+l2_smc3:
+ .word OMAP4_MON_L2X0_CTRL_INDEX
+l2_val:
+ .word 0xffff
+
+/* DDR related defines */
+ENTRY(am43xx_emif_sram_table)
+ .space EMIF_PM_FUNCTIONS_SIZE
+
+ENTRY(am43xx_pm_sram)
+.word am43xx_do_wfi
+.word am43xx_do_wfi_sz
+.word am43xx_resume_offset
+.word am43xx_emif_sram_table
+.word am43xx_pm_ro_sram_data
+
+ENTRY(am43xx_pm_ro_sram_data)
+ .space AMX3_PM_RO_SRAM_DATA_SIZE
+
+ENTRY(am43xx_do_wfi_sz)
+ .word . - am43xx_do_wfi
--
2.11.0
[toc] | [prev] | [next] | [standalone]
| From | Dave Gerlach <d-gerlach@ti.com> |
|---|---|
| Date | 2017-03-29 04:10 +0200 |
| Subject | [PATCH 4/8] ARM: OMAP2+: Introduce low-level suspend code for AM33XX |
| Message-ID | <tqbdE-8tJ-13@gated-at.bofh.it> |
| In reply to | #1611488 |
In preparation for suspend-resume support for AM33XX, add
the assembly file with the code which is copied to internal
memory (OCMC RAM) during bootup and runs from there.
As part of the low power entry (DeepSleep0 mode in AM33XX TRM),
the code running from OCMC RAM does the following
1. Calls routine to store the EMIF configuration
2. Calls routine to place external memory in self-refresh
3. Disables EMIF clock
4. Executes WFI after writing to MPU_CLKCTRL register.
If no interrupts have come, WFI execution on MPU gets registered
as an interrupt with the WKUP-M3. WKUP-M3 takes care of disabling
some clocks which MPU should not (L3, L4, OCMC RAM etc) and takes
care of clockdomain and powerdomain transitions as part of the
DeepSleep0 mode entry.
In case a late interrupt comes in, WFI ends up as a NOP and MPU
continues execution from internal memory. The 'abort path' code
undoes whatever was done as part of the low power entry and indicates
a suspend failure by passing a non-zero value to the cpu_resume routine.
The 'resume path' code is similar to the 'abort path' with the key
difference of MMU being enabled in the 'abort path' but being
disabled in the 'resume path' due to MPU getting powered off.
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
---
arch/arm/mach-omap2/sleep33xx.S | 219 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 219 insertions(+)
create mode 100644 arch/arm/mach-omap2/sleep33xx.S
diff --git a/arch/arm/mach-omap2/sleep33xx.S b/arch/arm/mach-omap2/sleep33xx.S
new file mode 100644
index 000000000000..8353d94d248a
--- /dev/null
+++ b/arch/arm/mach-omap2/sleep33xx.S
@@ -0,0 +1,219 @@
+/*
+ * Low level suspend code for AM33XX SoCs
+ *
+ * Copyright (C) 2012-2017 Texas Instruments Incorporated - http://www.ti.com/
+ * Dave Gerlach, Vaibhav Bedia
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/linkage.h>
+#include <linux/ti-emif-sram.h>
+#include <asm/asm-offsets.h>
+#include <asm/assembler.h>
+#include <asm/memory.h>
+
+#include "iomap.h"
+#include "cm33xx.h"
+
+#define AM33XX_CM_CLKCTRL_MODULEMODE_DISABLE 0x0003
+#define AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE 0x0002
+
+ .align 3
+
+ENTRY(am33xx_do_wfi)
+ stmfd sp!, {r4 - r11, lr} @ save registers on stack
+
+ /*
+ * Flush all data from the L1 and L2 data cache before disabling
+ * SCTLR.C bit.
+ */
+ ldr r1, kernel_flush
+ blx r1
+
+ /*
+ * Clear the SCTLR.C bit to prevent further data cache
+ * allocation. Clearing SCTLR.C would make all the data accesses
+ * strongly ordered and would not hit the cache.
+ */
+ mrc p15, 0, r0, c1, c0, 0
+ bic r0, r0, #(1 << 2) @ Disable the C bit
+ mcr p15, 0, r0, c1, c0, 0
+ isb
+
+ /*
+ * Invalidate L1 and L2 data cache.
+ */
+ ldr r1, kernel_flush
+ blx r1
+
+ adr r9, am33xx_emif_sram_table
+
+ ldr r3, [r9, #EMIF_PM_SAVE_CONTEXT_OFFSET]
+ blx r3
+
+ ldr r3, [r9, #EMIF_PM_ENTER_SR_OFFSET]
+ blx r3
+
+ /* Disable EMIF */
+ ldr r1, virt_emif_clkctrl
+ ldr r2, [r1]
+ bic r2, r2, #AM33XX_CM_CLKCTRL_MODULEMODE_DISABLE
+ str r2, [r1]
+
+ ldr r1, virt_emif_clkctrl
+wait_emif_disable:
+ ldr r2, [r1]
+ ldr r3, module_disabled_val
+ cmp r2, r3
+ bne wait_emif_disable
+
+ /*
+ * For the MPU WFI to be registered as an interrupt
+ * to WKUP_M3, MPU_CLKCTRL.MODULEMODE needs to be set
+ * to DISABLED
+ */
+ ldr r1, virt_mpu_clkctrl
+ ldr r2, [r1]
+ bic r2, r2, #AM33XX_CM_CLKCTRL_MODULEMODE_DISABLE
+ str r2, [r1]
+
+ /*
+ * Execute an ISB instruction to ensure that all of the
+ * CP15 register changes have been committed.
+ */
+ isb
+
+ /*
+ * Execute a barrier instruction to ensure that all cache,
+ * TLB and branch predictor maintenance operations issued
+ * have completed.
+ */
+ dsb
+ dmb
+
+ /*
+ * Execute a WFI instruction and wait until the
+ * STANDBYWFI output is asserted to indicate that the
+ * CPU is in idle and low power state. CPU can specualatively
+ * prefetch the instructions so add NOPs after WFI. Thirteen
+ * NOPs as per Cortex-A8 pipeline.
+ */
+ wfi
+
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ /* We come here in case of an abort due to a late interrupt */
+
+ /* Set MPU_CLKCTRL.MODULEMODE back to ENABLE */
+ ldr r1, virt_mpu_clkctrl
+ mov r2, #AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE
+ str r2, [r1]
+
+ /* Re-enable EMIF */
+ ldr r1, virt_emif_clkctrl
+ mov r2, #AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE
+ str r2, [r1]
+wait_emif_enable:
+ ldr r3, [r1]
+ cmp r2, r3
+ bne wait_emif_enable
+
+
+ ldr r1, [r9, #EMIF_PM_ABORT_SR_OFFSET]
+ blx r1
+
+ /*
+ * Set SCTLR.C bit to allow data cache allocation
+ */
+ mrc p15, 0, r0, c1, c0, 0
+ orr r0, r0, #(1 << 2) @ Enable the C bit
+ mcr p15, 0, r0, c1, c0, 0
+ isb
+
+ /* Let the suspend code know about the abort */
+ mov r0, #1
+ ldmfd sp!, {r4 - r11, pc} @ restore regs and return
+ENDPROC(am33xx_do_wfi)
+
+ .align
+ENTRY(am33xx_resume_offset)
+ .word . - am33xx_do_wfi
+
+ENTRY(am33xx_resume_from_deep_sleep)
+ /* Re-enable EMIF */
+ ldr r0, phys_emif_clkctrl
+ mov r1, #AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE
+ str r1, [r0]
+wait_emif_enable1:
+ ldr r2, [r0]
+ cmp r1, r2
+ bne wait_emif_enable1
+
+ adr r9, am33xx_emif_sram_table
+
+ ldr r1, [r9, #EMIF_PM_RESTORE_CONTEXT_OFFSET]
+ blx r1
+
+ ldr r1, [r9, #EMIF_PM_EXIT_SR_OFFSET]
+ blx r1
+
+resume_to_ddr:
+ /* We are back. Branch to the common CPU resume routine */
+ mov r0, #0
+ ldr pc, resume_addr
+ENDPROC(am33xx_resume_from_deep_sleep)
+
+/*
+ * Local variables
+ */
+ .align
+resume_addr:
+ .word cpu_resume - PAGE_OFFSET + 0x80000000
+kernel_flush:
+ .word v7_flush_dcache_all
+virt_mpu_clkctrl:
+ .word AM33XX_CM_MPU_MPU_CLKCTRL
+virt_emif_clkctrl:
+ .word AM33XX_CM_PER_EMIF_CLKCTRL
+phys_emif_clkctrl:
+ .word (AM33XX_CM_BASE + AM33XX_CM_PER_MOD + \
+ AM33XX_CM_PER_EMIF_CLKCTRL_OFFSET)
+module_disabled_val:
+ .word 0x30000
+
+/* DDR related defines */
+am33xx_emif_sram_table:
+ .space EMIF_PM_FUNCTIONS_SIZE
+
+ENTRY(am33xx_pm_sram)
+.word am33xx_do_wfi
+.word am33xx_do_wfi_sz
+.word am33xx_resume_offset
+.word am33xx_emif_sram_table
+.word am33xx_pm_ro_sram_data
+
+ENTRY(am33xx_pm_ro_sram_data)
+ .space AMX3_PM_RO_SRAM_DATA_SIZE
+
+ENTRY(am33xx_do_wfi_sz)
+ .word . - am33xx_do_wfi
--
2.11.0
[toc] | [prev] | [next] | [standalone]
| From | Dave Gerlach <d-gerlach@ti.com> |
|---|---|
| Date | 2017-03-29 04:10 +0200 |
| Subject | [PATCH 6/8] ARM: OMAP2+: pm33xx-core: Add platform code needed for PM |
| Message-ID | <tqbdE-8tJ-21@gated-at.bofh.it> |
| In reply to | #1611488 |
Most of the PM code needed for am335x and am437x can be moved into a
module under drivers but some core code must remain in mach-omap2 at the
moment. This includes some internal clockdomain APIs and low-level ARM
APIs which are also not exported for use by modules.
Implement a few functions that handle these low-level platform
operations can be passed to the pm33xx module through the use of
platform data.
In addition to this, to be able to share data structures between C and
the sleep33xx and sleep43xx assembly code, we can automatically generate
all of the C struct member offsets and sizes as macros by making use of
the ARM asm-offsets file. In the same header that we define our data
structures in we also define all the macros in an inline function and by
adding a call to this in the asm_offsets file all macros are properly
generated and available to the assembly code without cluttering up the
asm-offsets file.
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
---
arch/arm/kernel/asm-offsets.c | 2 +
arch/arm/mach-omap2/Kconfig | 1 +
arch/arm/mach-omap2/Makefile | 4 +
arch/arm/mach-omap2/pm.h | 5 +
arch/arm/mach-omap2/pm33xx-core.c | 181 +++++++++++++++++++++++++++++++++++
include/linux/platform_data/pm33xx.h | 69 +++++++++++++
6 files changed, 262 insertions(+)
create mode 100644 arch/arm/mach-omap2/pm33xx-core.c
create mode 100644 include/linux/platform_data/pm33xx.h
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index d728b5660e36..62253e7bfac4 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -28,6 +28,7 @@
#include <asm/vdso_datapage.h>
#include <asm/hardware/cache-l2x0.h>
#include <linux/kbuild.h>
+#include <linux/platform_data/pm33xx.h>
#include <linux/ti-emif-sram.h>
/*
@@ -187,6 +188,7 @@ int main(void)
#if defined(CONFIG_SOC_AM33XX) || defined(CONFIG_SOC_AM43XX)
BLANK();
ti_emif_offsets();
+ amx3_pm_asm_offsets();
#endif
return 0;
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 0465338183c7..940173fa0992 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -72,6 +72,7 @@ config SOC_AM43XX
select ARM_ERRATA_754322
select ARM_ERRATA_775420
select OMAP_INTERCONNECT
+ select ARM_CPU_SUSPEND if PM
config SOC_DRA7XX
bool "TI DRA7XX"
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index c89757abb0ae..8475ae3f9ff1 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -88,6 +88,8 @@ omap-4-5-pm-common += pm44xx.o
obj-$(CONFIG_ARCH_OMAP4) += $(omap-4-5-pm-common)
obj-$(CONFIG_SOC_OMAP5) += $(omap-4-5-pm-common)
obj-$(CONFIG_SOC_DRA7XX) += $(omap-4-5-pm-common)
+obj-$(CONFIG_SOC_AM33XX) += pm33xx-core.o sleep33xx.o
+obj-$(CONFIG_SOC_AM43XX) += pm33xx-core.o sleep43xx.o
obj-$(CONFIG_PM_DEBUG) += pm-debug.o
obj-$(CONFIG_POWER_AVS_OMAP) += sr_device.o
@@ -95,6 +97,8 @@ obj-$(CONFIG_POWER_AVS_OMAP_CLASS3) += smartreflex-class3.o
AFLAGS_sleep24xx.o :=-Wa,-march=armv6
AFLAGS_sleep34xx.o :=-Wa,-march=armv7-a$(plus_sec)
+AFLAGS_sleep33xx.o :=-Wa,-march=armv7-a$(plus_sec)
+AFLAGS_sleep43xx.o :=-Wa,-march=armv7-a$(plus_sec)
endif
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index b668719b9b25..2f9649b89053 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -81,6 +81,11 @@ extern unsigned int omap3_do_wfi_sz;
/* ... and its pointer from SRAM after copy */
extern void (*omap3_do_wfi_sram)(void);
+struct am33xx_pm_platform_data *am33xx_pm_get_pdata(void);
+
+extern struct am33xx_pm_sram_addr am33xx_pm_sram;
+extern struct am33xx_pm_sram_addr am43xx_pm_sram;
+
/* save_secure_ram_context function pointer and size, for copy to SRAM */
extern int save_secure_ram_context(u32 *addr);
extern unsigned int save_secure_ram_context_sz;
diff --git a/arch/arm/mach-omap2/pm33xx-core.c b/arch/arm/mach-omap2/pm33xx-core.c
new file mode 100644
index 000000000000..c84ffc4de2e9
--- /dev/null
+++ b/arch/arm/mach-omap2/pm33xx-core.c
@@ -0,0 +1,181 @@
+/*
+ * AM33XX Arch Power Management Routines
+ *
+ * Copyright (C) 2016-2017 Texas Instruments Incorporated - http://www.ti.com/
+ * Dave Gerlach
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <asm/smp_scu.h>
+#include <asm/suspend.h>
+#include <linux/platform_data/pm33xx.h>
+
+#include "cm33xx.h"
+#include "common.h"
+#include "control.h"
+#include "clockdomain.h"
+#include "iomap.h"
+#include "omap_hwmod.h"
+#include "pm.h"
+#include "powerdomain.h"
+#include "prm33xx.h"
+#include "soc.h"
+#include "sram.h"
+
+static struct powerdomain *cefuse_pwrdm, *gfx_pwrdm, *per_pwrdm, *mpu_pwrdm;
+static struct clockdomain *gfx_l4ls_clkdm;
+static void __iomem *scu_base;
+
+static int __init am43xx_map_scu(void)
+{
+ scu_base = ioremap(scu_a9_get_base(), SZ_256);
+
+ if (!scu_base)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static int amx3_common_init(void)
+{
+ gfx_pwrdm = pwrdm_lookup("gfx_pwrdm");
+ per_pwrdm = pwrdm_lookup("per_pwrdm");
+ mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
+
+ if ((!gfx_pwrdm) || (!per_pwrdm) || (!mpu_pwrdm))
+ return -ENODEV;
+
+ (void)clkdm_for_each(omap_pm_clkdms_setup, NULL);
+
+ /* CEFUSE domain can be turned off post bootup */
+ cefuse_pwrdm = pwrdm_lookup("cefuse_pwrdm");
+ if (cefuse_pwrdm)
+ omap_set_pwrdm_state(cefuse_pwrdm, PWRDM_POWER_OFF);
+ else
+ pr_err("PM: Failed to get cefuse_pwrdm\n");
+
+ return 0;
+}
+
+static int am33xx_suspend_init(void)
+{
+ int ret;
+
+ gfx_l4ls_clkdm = clkdm_lookup("gfx_l4ls_gfx_clkdm");
+
+ if (!gfx_l4ls_clkdm) {
+ pr_err("PM: Cannot lookup gfx_l4ls_clkdm clockdomains\n");
+ return -ENODEV;
+ }
+
+ ret = amx3_common_init();
+
+ return ret;
+}
+
+static int am43xx_suspend_init(void)
+{
+ int ret = 0;
+
+ ret = am43xx_map_scu();
+ if (ret) {
+ pr_err("PM: Could not ioremap SCU\n");
+ return ret;
+ }
+
+ ret = amx3_common_init();
+
+ return ret;
+}
+
+static void amx3_pre_suspend_common(void)
+{
+ omap_set_pwrdm_state(gfx_pwrdm, PWRDM_POWER_OFF);
+}
+
+static void amx3_post_suspend_common(void)
+{
+ int status;
+ /*
+ * Because gfx_pwrdm is the only one under MPU control,
+ * comment on transition status
+ */
+ status = pwrdm_read_pwrst(gfx_pwrdm);
+ if (status != PWRDM_POWER_OFF)
+ pr_err("PM: GFX domain did not transition: %x\n", status);
+}
+
+static int am33xx_suspend(unsigned int state, int (*fn)(unsigned long))
+{
+ int ret = 0;
+
+ amx3_pre_suspend_common();
+ ret = cpu_suspend(0, fn);
+ amx3_post_suspend_common();
+
+ /*
+ * BUG: GFX_L4LS clock domain needs to be woken up to
+ * ensure thet L4LS clock domain does not get stuck in
+ * transition. If that happens L3 module does not get
+ * disabled, thereby leading to PER power domain
+ * transition failing
+ */
+
+ clkdm_wakeup(gfx_l4ls_clkdm);
+ clkdm_sleep(gfx_l4ls_clkdm);
+
+ return ret;
+}
+
+static int am43xx_suspend(unsigned int state, int (*fn)(unsigned long))
+{
+ int ret = 0;
+
+ amx3_pre_suspend_common();
+ scu_power_mode(scu_base, SCU_PM_POWEROFF);
+ ret = cpu_suspend(0, fn);
+ scu_power_mode(scu_base, SCU_PM_NORMAL);
+ amx3_post_suspend_common();
+
+ return ret;
+}
+
+static struct am33xx_pm_sram_addr *amx3_get_sram_addrs(void)
+{
+ if (soc_is_am33xx())
+ return &am33xx_pm_sram;
+ else if (soc_is_am437x())
+ return &am43xx_pm_sram;
+ else
+ return NULL;
+}
+
+static struct am33xx_pm_platform_data am33xx_ops = {
+ .init = am33xx_suspend_init,
+ .soc_suspend = am33xx_suspend,
+ .get_sram_addrs = amx3_get_sram_addrs,
+};
+
+static struct am33xx_pm_platform_data am43xx_ops = {
+ .init = am43xx_suspend_init,
+ .soc_suspend = am43xx_suspend,
+ .get_sram_addrs = amx3_get_sram_addrs,
+};
+
+struct am33xx_pm_platform_data *am33xx_pm_get_pdata(void)
+{
+ if (soc_is_am33xx())
+ return &am33xx_ops;
+ else if (soc_is_am437x())
+ return &am43xx_ops;
+ else
+ return NULL;
+}
diff --git a/include/linux/platform_data/pm33xx.h b/include/linux/platform_data/pm33xx.h
new file mode 100644
index 000000000000..c191ab681093
--- /dev/null
+++ b/include/linux/platform_data/pm33xx.h
@@ -0,0 +1,69 @@
+/*
+ * TI pm33xx platform data
+ *
+ * Copyright (C) 2016-2017 Texas Instruments, Inc.
+ * Dave Gerlach <d-gerlach@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _LINUX_PLATFORM_DATA_PM33XX_H
+#define _LINUX_PLATFORM_DATA_PM33XX_H
+
+#include <linux/kbuild.h>
+
+#ifndef __ASSEMBLER__
+struct am33xx_pm_sram_addr {
+ void (*do_wfi)(void);
+ unsigned long *do_wfi_sz;
+ unsigned long *resume_offset;
+ unsigned long *emif_sram_table;
+ unsigned long *ro_sram_data;
+};
+
+struct am33xx_pm_platform_data {
+ int (*init)(void);
+ int (*soc_suspend)(unsigned int state, int (*fn)(unsigned long));
+ struct am33xx_pm_sram_addr *(*get_sram_addrs)(void);
+};
+
+struct am33xx_pm_sram_data {
+ u32 wfi_flags;
+ u32 l2_aux_ctrl_val;
+ u32 l2_prefetch_ctrl_val;
+};
+
+struct am33xx_pm_ro_sram_data {
+ u32 amx3_pm_sram_data_virt;
+ u32 amx3_pm_sram_data_phys;
+};
+
+extern inline void amx3_pm_asm_offsets(void)
+{
+ DEFINE(AMX3_PM_WFI_FLAGS_OFFSET,
+ offsetof(struct am33xx_pm_sram_data, wfi_flags));
+ DEFINE(AMX3_PM_L2_AUX_CTRL_VAL_OFFSET,
+ offsetof(struct am33xx_pm_sram_data, l2_aux_ctrl_val));
+ DEFINE(AMX3_PM_L2_PREFETCH_CTRL_VAL_OFFSET,
+ offsetof(struct am33xx_pm_sram_data, l2_prefetch_ctrl_val));
+ DEFINE(AMX3_PM_SRAM_DATA_SIZE, sizeof(struct am33xx_pm_sram_data));
+
+ BLANK();
+
+ DEFINE(AMX3_PM_RO_SRAM_DATA_VIRT_OFFSET,
+ offsetof(struct am33xx_pm_ro_sram_data, amx3_pm_sram_data_virt));
+ DEFINE(AMX3_PM_RO_SRAM_DATA_PHYS_OFFSET,
+ offsetof(struct am33xx_pm_ro_sram_data, amx3_pm_sram_data_phys));
+ DEFINE(AMX3_PM_RO_SRAM_DATA_SIZE,
+ sizeof(struct am33xx_pm_ro_sram_data));
+}
+
+#endif /* __ASSEMBLER__ */
+#endif /* _LINUX_PLATFORM_DATA_PM33XX_H */
--
2.11.0
[toc] | [prev] | [next] | [standalone]
| From | Tony Lindgren <tony@atomide.com> |
|---|---|
| Date | 2017-04-04 18:20 +0200 |
| Subject | Re: [PATCH 6/8] ARM: OMAP2+: pm33xx-core: Add platform code needed for PM |
| Message-ID | <tszlv-7cC-7@gated-at.bofh.it> |
| In reply to | #1611503 |
Russell, * Dave Gerlach <d-gerlach@ti.com> [170328 19:01]: > Most of the PM code needed for am335x and am437x can be moved into a > module under drivers but some core code must remain in mach-omap2 at the > moment. This includes some internal clockdomain APIs and low-level ARM > APIs which are also not exported for use by modules. > > Implement a few functions that handle these low-level platform > operations can be passed to the pm33xx module through the use of > platform data. > > In addition to this, to be able to share data structures between C and > the sleep33xx and sleep43xx assembly code, we can automatically generate > all of the C struct member offsets and sizes as macros by making use of > the ARM asm-offsets file. In the same header that we define our data > structures in we also define all the macros in an inline function and by > adding a call to this in the asm_offsets file all macros are properly > generated and available to the assembly code without cluttering up the > asm-offsets file. > > Signed-off-by: Dave Gerlach <d-gerlach@ti.com> > --- > arch/arm/kernel/asm-offsets.c | 2 + > arch/arm/mach-omap2/Kconfig | 1 + > arch/arm/mach-omap2/Makefile | 4 + > arch/arm/mach-omap2/pm.h | 5 + > arch/arm/mach-omap2/pm33xx-core.c | 181 +++++++++++++++++++++++++++++++++++ > include/linux/platform_data/pm33xx.h | 69 +++++++++++++ > 6 files changed, 262 insertions(+) > create mode 100644 arch/arm/mach-omap2/pm33xx-core.c > create mode 100644 include/linux/platform_data/pm33xx.h > > diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c > index d728b5660e36..62253e7bfac4 100644 > --- a/arch/arm/kernel/asm-offsets.c > +++ b/arch/arm/kernel/asm-offsets.c > @@ -28,6 +28,7 @@ > #include <asm/vdso_datapage.h> > #include <asm/hardware/cache-l2x0.h> > #include <linux/kbuild.h> > +#include <linux/platform_data/pm33xx.h> > #include <linux/ti-emif-sram.h> > > /* > @@ -187,6 +188,7 @@ int main(void) > #if defined(CONFIG_SOC_AM33XX) || defined(CONFIG_SOC_AM43XX) > BLANK(); > ti_emif_offsets(); > + amx3_pm_asm_offsets(); > #endif > > return 0; Here too can you please check this is OK with you. Regards, Tony
[toc] | [prev] | [next] | [standalone]
| From | Dave Gerlach <d-gerlach@ti.com> |
|---|---|
| Date | 2017-03-29 04:10 +0200 |
| Subject | [PATCH 1/8] ARM: OMAP: Wakeupgen: Add context save/restore for AM43XX |
| Message-ID | <tqbdE-8tJ-27@gated-at.bofh.it> |
| In reply to | #1611488 |
AM43XX has the same wakeupgen IP as OMAP4/5. The only
notable difference is the presence of 7 register banks
and lack of SAR area which has been used in OMAP4/5 for
saving and restoring the context around low power states.
In case of AM43XX the context is saved and restored by
the kernel. Introduce wakeupgen_ops so that context save
and restore can be set on a per-SoC basis during init.
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
---
arch/arm/mach-omap2/omap-wakeupgen.c | 68 ++++++++++++++++++++++++++++++++----
1 file changed, 62 insertions(+), 6 deletions(-)
diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c
index 369f95a703ac..33ed5d53fa45 100644
--- a/arch/arm/mach-omap2/omap-wakeupgen.c
+++ b/arch/arm/mach-omap2/omap-wakeupgen.c
@@ -58,6 +58,17 @@ static unsigned int irq_banks = DEFAULT_NR_REG_BANKS;
static unsigned int max_irqs = DEFAULT_IRQS;
static unsigned int omap_secure_apis;
+#ifdef CONFIG_CPU_PM
+static unsigned int wakeupgen_context[MAX_NR_REG_BANKS];
+#endif
+
+struct omap_wakeupgen_ops {
+ void (*save_context)(void);
+ void (*restore_context)(void);
+};
+
+static struct omap_wakeupgen_ops *wakeupgen_ops;
+
/*
* Static helper functions.
*/
@@ -264,6 +275,16 @@ static inline void omap5_irq_save_context(void)
}
+static inline void am43xx_irq_save_context(void)
+{
+ u32 i;
+
+ for (i = 0; i < irq_banks; i++) {
+ wakeupgen_context[i] = wakeupgen_readl(i, 0);
+ wakeupgen_writel(0, i, CPU0_ID);
+ }
+}
+
/*
* Save WakeupGen interrupt context in SAR BANK3. Restore is done by
* ROM code. WakeupGen IP is integrated along with GIC to manage the
@@ -280,11 +301,8 @@ static void irq_save_context(void)
if (!sar_base)
sar_base = omap4_get_sar_ram_base();
-
- if (soc_is_omap54xx())
- omap5_irq_save_context();
- else
- omap4_irq_save_context();
+ if (wakeupgen_ops && wakeupgen_ops->save_context)
+ wakeupgen_ops->save_context();
}
/*
@@ -306,6 +324,20 @@ static void irq_sar_clear(void)
writel_relaxed(val, sar_base + offset);
}
+static void am43xx_irq_restore_context(void)
+{
+ u32 i;
+
+ for (i = 0; i < irq_banks; i++)
+ wakeupgen_writel(wakeupgen_context[i], i, CPU0_ID);
+}
+
+static void irq_restore_context(void)
+{
+ if (wakeupgen_ops && wakeupgen_ops->restore_context)
+ wakeupgen_ops->restore_context();
+}
+
/*
* Save GIC and Wakeupgen interrupt context using secure API
* for HS/EMU devices.
@@ -319,6 +351,26 @@ static void irq_save_secure_context(void)
if (ret != API_HAL_RET_VALUE_OK)
pr_err("GIC and Wakeupgen context save failed\n");
}
+
+/* Define ops for context save and restore for each SoC */
+static struct omap_wakeupgen_ops omap4_wakeupgen_ops = {
+ .save_context = omap4_irq_save_context,
+ .restore_context = irq_sar_clear,
+};
+
+static struct omap_wakeupgen_ops omap5_wakeupgen_ops = {
+ .save_context = omap5_irq_save_context,
+ .restore_context = irq_sar_clear,
+};
+
+static struct omap_wakeupgen_ops am43xx_wakeupgen_ops = {
+ .save_context = am43xx_irq_save_context,
+ .restore_context = am43xx_irq_restore_context,
+};
+#else
+static struct omap_wakeupgen_ops omap4_wakeupgen_ops = {};
+static struct omap_wakeupgen_ops omap5_wakeupgen_ops = {};
+static struct omap_wakeupgen_ops am43xx_wakeupgen_ops = {};
#endif
#ifdef CONFIG_HOTPLUG_CPU
@@ -359,7 +411,7 @@ static int irq_notifier(struct notifier_block *self, unsigned long cmd, void *v)
break;
case CPU_CLUSTER_PM_EXIT:
if (omap_type() == OMAP2_DEVICE_TYPE_GP)
- irq_sar_clear();
+ irq_restore_context();
break;
}
return NOTIFY_OK;
@@ -494,9 +546,13 @@ static int __init wakeupgen_init(struct device_node *node,
irq_banks = OMAP4_NR_BANKS;
max_irqs = OMAP4_NR_IRQS;
omap_secure_apis = 1;
+ wakeupgen_ops = &omap4_wakeupgen_ops;
+ } else if (soc_is_omap54xx()) {
+ wakeupgen_ops = &omap5_wakeupgen_ops;
} else if (soc_is_am43xx()) {
irq_banks = AM43XX_NR_REG_BANKS;
max_irqs = AM43XX_IRQS;
+ wakeupgen_ops = &am43xx_wakeupgen_ops;
}
domain = irq_domain_add_hierarchy(parent_domain, 0, max_irqs,
--
2.11.0
[toc] | [prev] | [next] | [standalone]
| From | Tony Lindgren <tony@atomide.com> |
|---|---|
| Date | 2017-03-29 19:20 +0200 |
| Subject | Re: [PATCH 0/8] ARM: OMAP2+: AM33XX/AM43XX: Add suspend-resume support |
| Message-ID | <tqpqi-1xr-3@gated-at.bofh.it> |
| In reply to | #1611488 |
* Dave Gerlach <d-gerlach@ti.com> [170328 19:00]: > Hi, > This series contains the remaining code to enable suspend to mem and standby on > am335x and am437x platforms. It depends on the ti-emif-sram series sent here [1]. Looks good to me in general. To remove the dependency, can some of this be merged separately without breaking things before [1]? Maybe by disabling some of the PM states until [1] is in place? Regards, Tony
[toc] | [prev] | [next] | [standalone]
| From | Dave Gerlach <d-gerlach@ti.com> |
|---|---|
| Date | 2017-03-29 21:00 +0200 |
| Subject | Re: [PATCH 0/8] ARM: OMAP2+: AM33XX/AM43XX: Add suspend-resume support |
| Message-ID | <tqqZ4-2xD-17@gated-at.bofh.it> |
| In reply to | #1612163 |
Hi Tony, On 03/29/2017 12:13 PM, Tony Lindgren wrote: > * Dave Gerlach <d-gerlach@ti.com> [170328 19:00]: >> Hi, >> This series contains the remaining code to enable suspend to mem and standby on >> am335x and am437x platforms. It depends on the ti-emif-sram series sent here [1]. > > Looks good to me in general. To remove the dependency, can some > of this be merged separately without breaking things before [1]? > Maybe by disabling some of the PM states until [1] is in place? Thanks for the feedback. Actually, patch 7 is the only patch with a dependency to [1]. The rest of the patches just add platform PM support needed for suspend but won't do much of anything until patch 7 actually enables the suspend states, so there is no reason why patches 1-6 and patch 8 can't be merged now. Regards, Dave > > Regards, > > Tony >
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web