From a89726d3b4cb81b033e34cc55974a33dab3279da Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Wed, 6 Feb 2013 19:39:07 +0530 Subject: ARM: OMAP5 / DRA7: PM: Update CPU context register offset On OMAP5, RM_CPUi_CPUi_CONTEXT offset has changed. Update the code so that same code works for OMAP4+ devices. DRA7 and OMAP5 have the same context offset as well. Signed-off-by: Santosh Shilimkar [rnayak@ti.com: for DRA7] Signed-off-by: Rajendra Nayak [nm@ti.com: rebase, split/merge etc..] Signed-off-by: Nishanth Menon Reviewed-by: Kevin Hilman Tested-by: Kevin Hilman --- arch/arm/mach-omap2/omap-mpuss-lowpower.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'arch/arm/mach-omap2/omap-mpuss-lowpower.c') diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c index 4001325f90fb..63a1dd708d80 100644 --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c @@ -56,6 +56,7 @@ #include "omap4-sar-layout.h" #include "pm.h" #include "prcm_mpu44xx.h" +#include "prcm_mpu54xx.h" #include "prminst44xx.h" #include "prcm44xx.h" #include "prm44xx.h" @@ -89,6 +90,7 @@ struct cpu_pm_ops { static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info); static struct powerdomain *mpuss_pd; static void __iomem *sar_base; +static u32 cpu_context_offset; static int default_finish_suspend(unsigned long cpu_state) { @@ -161,14 +163,14 @@ static inline void cpu_clear_prev_logic_pwrst(unsigned int cpu_id) if (cpu_id) { reg = omap4_prcm_mpu_read_inst_reg(OMAP4430_PRCM_MPU_CPU1_INST, - OMAP4_RM_CPU1_CPU1_CONTEXT_OFFSET); + cpu_context_offset); omap4_prcm_mpu_write_inst_reg(reg, OMAP4430_PRCM_MPU_CPU1_INST, - OMAP4_RM_CPU1_CPU1_CONTEXT_OFFSET); + cpu_context_offset); } else { reg = omap4_prcm_mpu_read_inst_reg(OMAP4430_PRCM_MPU_CPU0_INST, - OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET); + cpu_context_offset); omap4_prcm_mpu_write_inst_reg(reg, OMAP4430_PRCM_MPU_CPU0_INST, - OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET); + cpu_context_offset); } } @@ -392,6 +394,9 @@ int __init omap4_mpuss_init(void) omap_pm_ops.finish_suspend = omap4_finish_suspend; omap_pm_ops.resume = omap4_cpu_resume; omap_pm_ops.scu_prepare = scu_pwrst_prepare; + cpu_context_offset = OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET; + } else if (soc_is_omap54xx() || soc_is_dra7xx()) { + cpu_context_offset = OMAP54XX_RM_CPU0_CPU0_CONTEXT_OFFSET; } return 0; -- cgit v1.2.3 From 6d846c46683a4a8a54fbd30b0ff1434a7d898026 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Thu, 12 Apr 2012 17:01:52 +0530 Subject: ARM: OMAP5 / DRA7: PM: Enable Mercury retention mode on CPUx powerdomains In addition to the standard power-management technique, the OMAP5 / DRA7 MPU subsystem also employs an SR3-APG (mercury) power management technology to reduce leakage. It allows for full logic and memories retention on MPU_C0 and MPU_C1 and is controlled by the PRCM_MPU. Only "Fast-mode" is supported on the OMAP5 and DRA7 family of processors. Signed-off-by: Santosh Shilimkar [nm@ti.com: minor consolidation] Signed-off-by: Nishanth Menon Reviewed-by: Kevin Hilman Tested-by: Kevin Hilman --- arch/arm/mach-omap2/omap-mpuss-lowpower.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'arch/arm/mach-omap2/omap-mpuss-lowpower.c') diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c index 63a1dd708d80..fad6e8c7e69e 100644 --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c @@ -320,6 +320,21 @@ int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state) } +/* + * Enable Mercury Fast HG retention mode by default. + */ +static void enable_mercury_retention_mode(void) +{ + u32 reg; + + reg = omap4_prcm_mpu_read_inst_reg(OMAP54XX_PRCM_MPU_DEVICE_INST, + OMAP54XX_PRCM_MPU_PRM_PSCON_COUNT_OFFSET); + /* Enable HG_EN, HG_RAMPUP = fast mode */ + reg |= BIT(24) | BIT(25); + omap4_prcm_mpu_write_inst_reg(reg, OMAP54XX_PRCM_MPU_DEVICE_INST, + OMAP54XX_PRCM_MPU_PRM_PSCON_COUNT_OFFSET); +} + /* * Initialise OMAP4 MPUSS */ @@ -397,6 +412,7 @@ int __init omap4_mpuss_init(void) cpu_context_offset = OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET; } else if (soc_is_omap54xx() || soc_is_dra7xx()) { cpu_context_offset = OMAP54XX_RM_CPU0_CPU0_CONTEXT_OFFSET; + enable_mercury_retention_mode(); } return 0; -- cgit v1.2.3 From 325f29da0d21900a78a91724acd6640e59f3e13c Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 3 May 2013 15:34:40 +0530 Subject: ARM: OMAP5 / DRA7: PM: Avoid all SAR saves Get rid of all assumptions about always having a sar base on *all* OMAP4+ platforms. We dont need one on DRA7 and it is not necessary at this point for OMAP5 either. Signed-off-by: Rajendra Nayak [nm@ti.com: Split and optimize] Signed-off-by: Nishanth Menon Reviewed-by: Kevin Hilman Tested-by: Kevin Hilman --- arch/arm/mach-omap2/omap-mpuss-lowpower.c | 55 +++++++++++++++++++------------ 1 file changed, 34 insertions(+), 21 deletions(-) (limited to 'arch/arm/mach-omap2/omap-mpuss-lowpower.c') diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c index fad6e8c7e69e..53d8de5764e8 100644 --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c @@ -118,7 +118,8 @@ static inline void set_cpu_wakeup_addr(unsigned int cpu_id, u32 addr) { struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id); - writel_relaxed(addr, pm_info->wkup_sar_addr); + if (pm_info->wkup_sar_addr) + writel_relaxed(addr, pm_info->wkup_sar_addr); } /* @@ -143,7 +144,8 @@ static void scu_pwrst_prepare(unsigned int cpu_id, unsigned int cpu_state) break; } - writel_relaxed(scu_pwr_st, pm_info->scu_sar_addr); + if (pm_info->scu_sar_addr) + writel_relaxed(scu_pwr_st, pm_info->scu_sar_addr); } /* Helper functions for MPUSS OSWR */ @@ -181,7 +183,8 @@ static void l2x0_pwrst_prepare(unsigned int cpu_id, unsigned int save_state) { struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id); - writel_relaxed(save_state, pm_info->l2x0_sar_addr); + if (pm_info->l2x0_sar_addr) + writel_relaxed(save_state, pm_info->l2x0_sar_addr); } /* @@ -191,10 +194,14 @@ static void l2x0_pwrst_prepare(unsigned int cpu_id, unsigned int save_state) #ifdef CONFIG_CACHE_L2X0 static void __init save_l2x0_context(void) { - writel_relaxed(l2x0_saved_regs.aux_ctrl, - sar_base + L2X0_AUXCTRL_OFFSET); - writel_relaxed(l2x0_saved_regs.prefetch_ctrl, - sar_base + L2X0_PREFETCH_CTRL_OFFSET); + void __iomem *l2x0_base = omap4_get_l2cache_base(); + + if (l2x0_base && sar_base) { + writel_relaxed(l2x0_saved_regs.aux_ctrl, + sar_base + L2X0_AUXCTRL_OFFSET); + writel_relaxed(l2x0_saved_regs.prefetch_ctrl, + sar_base + L2X0_PREFETCH_CTRL_OFFSET); + } } #else static void __init save_l2x0_context(void) @@ -347,13 +354,17 @@ int __init omap4_mpuss_init(void) return -ENODEV; } - sar_base = omap4_get_sar_ram_base(); + if (cpu_is_omap44xx()) + sar_base = omap4_get_sar_ram_base(); /* Initilaise per CPU PM information */ pm_info = &per_cpu(omap4_pm_info, 0x0); - pm_info->scu_sar_addr = sar_base + SCU_OFFSET0; - pm_info->wkup_sar_addr = sar_base + CPU0_WAKEUP_NS_PA_ADDR_OFFSET; - pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET0; + if (sar_base) { + pm_info->scu_sar_addr = sar_base + SCU_OFFSET0; + pm_info->wkup_sar_addr = sar_base + + CPU0_WAKEUP_NS_PA_ADDR_OFFSET; + pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET0; + } pm_info->pwrdm = pwrdm_lookup("cpu0_pwrdm"); if (!pm_info->pwrdm) { pr_err("Lookup failed for CPU0 pwrdm\n"); @@ -368,9 +379,12 @@ int __init omap4_mpuss_init(void) pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON); pm_info = &per_cpu(omap4_pm_info, 0x1); - pm_info->scu_sar_addr = sar_base + SCU_OFFSET1; - pm_info->wkup_sar_addr = sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET; - pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1; + if (sar_base) { + pm_info->scu_sar_addr = sar_base + SCU_OFFSET1; + pm_info->wkup_sar_addr = sar_base + + CPU1_WAKEUP_NS_PA_ADDR_OFFSET; + pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1; + } if (cpu_is_omap446x()) pm_info->secondary_startup = omap4460_secondary_startup; else @@ -397,13 +411,12 @@ int __init omap4_mpuss_init(void) pwrdm_clear_all_prev_pwrst(mpuss_pd); mpuss_clear_prev_logic_pwrst(); - /* Save device type on scratchpad for low level code to use */ - if (omap_type() != OMAP2_DEVICE_TYPE_GP) - writel_relaxed(1, sar_base + OMAP_TYPE_OFFSET); - else - writel_relaxed(0, sar_base + OMAP_TYPE_OFFSET); - - save_l2x0_context(); + if (sar_base) { + /* Save device type on scratchpad for low level code to use */ + writel_relaxed((omap_type() != OMAP2_DEVICE_TYPE_GP) ? 1 : 0, + sar_base + OMAP_TYPE_OFFSET); + save_l2x0_context(); + } if (cpu_is_omap44xx()) { omap_pm_ops.finish_suspend = omap4_finish_suspend; -- cgit v1.2.3 From e97c4eb342055b24da886b56377dc0093e835b4a Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Fri, 6 Jun 2014 17:30:43 -0500 Subject: ARM: OMAP5 / DRA7: PM: Provide a dummy startup function for CPU hotplug Dont assume that all OMAP4+ code will be able to use OMAP4 hotplug logic. On OMAP5, DRA7, we do not need this in place yet, also, currently the CPU startup pointer is located in omap4_cpu_pm_info instead of cpu_pm_ops. So, isolate the function to hotplug_restart pointer in cpu_pm_ops where it should have belonged, initalize them as per valid startup pointers for OMAP4430/60 as in current logic, however provide dummy_cpu_resume to be the startup location as well. Signed-off-by: Santosh Shilimkar [nm@ti.com: split this out of original code and isolate it] Signed-off-by: Nishanth Menon Reviewed-by: Kevin Hilman Tested-by: Kevin Hilman --- arch/arm/mach-omap2/omap-mpuss-lowpower.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'arch/arm/mach-omap2/omap-mpuss-lowpower.c') diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c index 53d8de5764e8..207fce2d6932 100644 --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c @@ -69,7 +69,6 @@ struct omap4_cpu_pm_info { void __iomem *scu_sar_addr; void __iomem *wkup_sar_addr; void __iomem *l2x0_sar_addr; - void (*secondary_startup)(void); }; /** @@ -77,6 +76,7 @@ struct omap4_cpu_pm_info { * @finish_suspend: CPU suspend finisher function pointer * @resume: CPU resume function pointer * @scu_prepare: CPU Snoop Control program function pointer + * @hotplug_restart: CPU restart function pointer * * Structure holds functions pointer for CPU low power operations like * suspend, resume and scu programming. @@ -85,6 +85,7 @@ struct cpu_pm_ops { int (*finish_suspend)(unsigned long cpu_state); void (*resume)(void); void (*scu_prepare)(unsigned int cpu_id, unsigned int cpu_state); + void (*hotplug_restart)(void); }; static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info); @@ -108,6 +109,7 @@ struct cpu_pm_ops omap_pm_ops = { .finish_suspend = default_finish_suspend, .resume = dummy_cpu_resume, .scu_prepare = dummy_scu_prepare, + .hotplug_restart = dummy_cpu_resume, }; /* @@ -312,7 +314,7 @@ int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state) pwrdm_clear_all_prev_pwrst(pm_info->pwrdm); pwrdm_set_next_pwrst(pm_info->pwrdm, power_state); - set_cpu_wakeup_addr(cpu, virt_to_phys(pm_info->secondary_startup)); + set_cpu_wakeup_addr(cpu, virt_to_phys(omap_pm_ops.hotplug_restart)); omap_pm_ops.scu_prepare(cpu, power_state); /* @@ -385,10 +387,6 @@ int __init omap4_mpuss_init(void) CPU1_WAKEUP_NS_PA_ADDR_OFFSET; pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1; } - if (cpu_is_omap446x()) - pm_info->secondary_startup = omap4460_secondary_startup; - else - pm_info->secondary_startup = omap4_secondary_startup; pm_info->pwrdm = pwrdm_lookup("cpu1_pwrdm"); if (!pm_info->pwrdm) { @@ -422,12 +420,16 @@ int __init omap4_mpuss_init(void) omap_pm_ops.finish_suspend = omap4_finish_suspend; omap_pm_ops.resume = omap4_cpu_resume; omap_pm_ops.scu_prepare = scu_pwrst_prepare; + omap_pm_ops.hotplug_restart = omap4_secondary_startup; cpu_context_offset = OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET; } else if (soc_is_omap54xx() || soc_is_dra7xx()) { cpu_context_offset = OMAP54XX_RM_CPU0_CPU0_CONTEXT_OFFSET; enable_mercury_retention_mode(); } + if (cpu_is_omap446x()) + omap_pm_ops.hotplug_restart = omap4460_secondary_startup; + return 0; } -- cgit v1.2.3 From 6099dd37c66931085557363b4716483f97cf92a0 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Mon, 27 May 2013 15:46:44 +0530 Subject: ARM: OMAP5 / DRA7: Enable CPU RET on suspend On OMAP5 / DRA7, prevent a CPU powerdomain OFF and resulting MPU OSWR and instead attempt a CPU RET and side effect, MPU RET in suspend. NOTE: the hardware was originally designed to be capable of achieving deep power states such as OFF and OSWR, however due to various issues and risks, deepest valid state was determined to be CSWR - hence we use the errata framework to handle this case. Signed-off-by: Rajendra Nayak [nm@ti.com: updates] Signed-off-by: Nishanth Menon Reviewed-by: Kevin Hilman Tested-by: Kevin Hilman --- arch/arm/mach-omap2/omap-mpuss-lowpower.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch/arm/mach-omap2/omap-mpuss-lowpower.c') diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c index 207fce2d6932..297352f214df 100644 --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c @@ -242,6 +242,10 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) save_state = 1; break; case PWRDM_POWER_RET: + if (IS_PM44XX_ERRATUM(PM_OMAP4_CPU_OSWR_DISABLE)) { + save_state = 0; + break; + } default: /* * CPUx CSWR is invalid hardware state. Also CPUx OSWR -- cgit v1.2.3