diff options
author | Teo Hall <teo.hall@freescale.com> | 2015-10-30 10:09:36 -0500 |
---|---|---|
committer | Teo Hall <teo.hall@freescale.com> | 2015-11-03 10:35:19 -0600 |
commit | 011ed0ab784eb566b68ebacea57ae3a6857b48ff (patch) | |
tree | 48901abf862e75647f43acfaa2016eab3bc01010 | |
parent | 2a69a6e413c4aa5c7662f971e535d559d6013f7c (diff) | |
download | freescale-011ed0ab784eb566b68ebacea57ae3a6857b48ff.tar.gz |
MLK-11262-5: ARM: imx: add M4 rekick after DSM
Save M4 tcm in ddr. Copy memory after exit from DSM.
Also hold M4 in reset when entering DSM.
Signed-off-by: Teo Hall <teo.hall@freescale.com>
-rw-r--r-- | arch/arm/mach-imx/pm-imx7.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/arch/arm/mach-imx/pm-imx7.c b/arch/arm/mach-imx/pm-imx7.c index 0117dce0caf..59cbc51baa3 100644 --- a/arch/arm/mach-imx/pm-imx7.c +++ b/arch/arm/mach-imx/pm-imx7.c @@ -9,6 +9,7 @@ * http://www.gnu.org/copyleft/gpl.html */ +#include <linux/busfreq-imx.h> #include <linux/delay.h> #include <linux/init.h> #include <linux/io.h> @@ -111,6 +112,11 @@ #define GPIO_IMR 0x14 #define GPIO_EDGE 0x1c +#define M4RCR 0x0C +#define M4_SP_OFF 0x00 +#define M4_PC_OFF 0x04 +#define M4_RCR_HALT 0xAB +#define M4_RCR_GO 0xAA extern unsigned long iram_tlb_base_addr; extern unsigned long iram_tlb_phys_addr; @@ -119,6 +125,11 @@ static void __iomem *ocram_base; static unsigned int ocram_size; static unsigned int *lpm_ocram_saved_in_ddr; static void __iomem *lpm_ocram_base; + +static unsigned int *lpm_m4tcm_saved_in_ddr; +static void __iomem *lpm_m4tcm_base; +static void __iomem *m4_bootrom_base; + static unsigned int lpm_ocram_size; static void __iomem *ccm_base; static void __iomem *lpsr_base; @@ -684,6 +695,10 @@ static int imx7_pm_enter(suspend_state_t state) imx_anatop_pre_suspend(); imx_gpcv2_pre_suspend(true); if (imx_gpcv2_is_mf_mix_off()) { + /* stop m4 if mix will also be shutdown */ + if (imx_src_is_m4_enabled() && imx_mu_is_m4_in_stop()) + writel(M4_RCR_HALT, + pm_info->src_base.vbase + M4RCR); imx7_console_save(console_saved_reg); memcpy(ocram_saved_in_ddr, ocram_base, ocram_size); if (lpsr_enabled) { @@ -717,6 +732,24 @@ static int imx7_pm_enter(suspend_state_t state) imx7_pm_is_resume_from_lpsr()) { memcpy(ocram_base, ocram_saved_in_ddr, ocram_size); imx7_console_restore(console_saved_reg); + if (imx_src_is_m4_enabled() && imx_mu_is_m4_in_stop()) { + /* restore M4 image */ + memcpy(lpm_m4tcm_base, + lpm_m4tcm_saved_in_ddr, SZ_32K); + /* set sp from word in the image */ + writel(*(lpm_m4tcm_saved_in_ddr), + m4_bootrom_base + M4_SP_OFF); + /* set PC from next word */ + writel(*(lpm_m4tcm_saved_in_ddr+1), + m4_bootrom_base + M4_PC_OFF); + /* kick m4 to enable */ + writel(M4_RCR_GO, + pm_info->src_base.vbase + M4RCR); + /* offset high bus count for m4 image */ + request_bus_freq(BUS_FREQ_HIGH); + /* gpc wakeup */ + imx_mu_lpm_ready(true); + } } /* clear LPSR resume address */ imx7_pm_set_lpsr_resume_addr(0); @@ -988,7 +1021,27 @@ void __init imx7d_pm_init(void) { struct device_node *np; struct resource res; + if (imx_src_is_m4_enabled()) { + /* map the 32K of M4 TCM */ + np = of_find_node_by_path( + "/tcml@007f8000"); + if (np) + lpm_m4tcm_base = of_iomap(np, 0); + WARN_ON(!lpm_m4tcm_base); + /* map the m4 bootrom from dtb */ + np = of_find_node_by_path( + "/soc/sram@00180000"); + if (np) + m4_bootrom_base = of_iomap(np, 0); + WARN_ON(!m4_bootrom_base); + + lpm_m4tcm_saved_in_ddr = kzalloc(SZ_32K, GFP_KERNEL); + WARN_ON(!lpm_m4tcm_saved_in_ddr); + + /* save M4 Image to DDR */ + memcpy(lpm_m4tcm_saved_in_ddr, lpm_m4tcm_base, SZ_32K); + } np = of_find_compatible_node(NULL, NULL, "fsl,lpm-sram"); if (of_get_property(np, "fsl,enable-lpsr", NULL)) lpsr_enabled = true; |