ARM: OMAP4: core retention support
Subsystems (7)
v7 cover ARM: OMAP4: core retention support
Hi,
Changes compared to previous version:
- ported on top of 3.5-rc7
- patch 3: added a few modules here not having context_offs
- patch 8: NEW:
* ROM code on EMU / HS devices seem to wipe the contents of L4PER_PWRSTCTRL register, thus this patch adds an errata + save and restore for this register, this was noticed while testing cpu_idle on EMU device
- patch 9: NEW:
* sl2if hwmod is still blocking core retention on omap4, this patch comments it out similarly to aess / usb_host_fs
- patch 10: NEW:
* adds support for lostcontext_mask, this is needed by l4_abe / aess hwmods as they will share context register, but use different bits within it
- patch 11: NEW:
* adds the hwmod data for sharing context register for l4_abe / aess
- patch 12: NEW:
* context lost counter logic update for modules that don't have context register
Some of the NEW patches (10..12) are result of comments received on l-o list, and can be merged with other patches in the set if they are seen acceptable. Core retention works without these patches fine, but they address some corner cases.
Tested with omap4460 GP panda + omap4430 EMU blaze, with both suspend + cpu_idle. cpu_idle + uart autosuspend seems to have an issue with omap4 currently that it loses some of the characters at the end of a print, should be fixed on uart driver level. Made a quick hack myself for this by modifying the serial_omap_tx_empty() to not use pm_runtime_put but pm_runtime_put_autosuspend at end, but this might not be the right way to fix this.
Working test tree available also:git://gitorious.org/~kristo/omap-pm/omap-pm-work.git
branch: mainline-3.5-rc7-omap4-ret-v7
Branch contains also func pwrst code from Jean + io_chain set + one timekeeping patch from mainline tip to make suspend work properly.
-Tero
PATCH v7 1/12 ARM: OMAP4: PM: add errata support
Added similar PM errata flag support as omap3 has. This should be used in similar manner, set the flags during init time, and check the flag values during runtime.
--- arch/arm/mach-omap2/pm.h | 7 +++++++ arch/arm/mach-omap2/pm44xx.c | 1 + 2 files changed, 8 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/pm.h +7 -0
@@ -88,6 +88,13 @@ extern void enable_omap3630_toggle_l2_on_restore(void);static inline void enable_omap3630_toggle_l2_on_restore (void ) { }#endif /* defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) */ +#if defined(CONFIG_ARCH_OMAP4 ) +extern u16 pm44xx_errata; +#define IS_PM44XX_ERRATUM (id) (pm44xx_errata & (id)) +#else +#define IS_PM44XX_ERRATUM (id) 0 +#endif +#ifdef CONFIG_OMAP_SMARTREFLEX extern int omap_devinit_smartreflex (void );extern void omap_enable_smartreflex_on_init (void );
arch/arm/mach-omap2/pm44xx.c +1 -0
@@ -33,6 +33,7 @@ struct power_state { };static LIST_HEAD (pwrst_list); +u16 pm44xx_errata;#ifdef CONFIG_SUSPEND static int omap4_pm_suspend (void )
Signature · 1 line
1.7.4.1
PATCH v7 2/12 ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX GIC control register change.
In reply to Tero KristoFrom: Santosh Shilimkar <[email protected]>
On OMAP4+ devices, GIC register context is lost when MPUSS hits the OSWR(Open Switch Retention). On the CPU wakeup path, ROM code gets executed and one of the steps in it is to restore the saved context of the GIC. The ROM Code GIC distributor restoration is split in two parts: CPU specific register done by each CPU and common register done by only one CPU.
Below is the abstract flow.
...............................................................
- MPUSS in OSWR state.
- CPU0 wakes up on the event(interrupt) and start executing ROM code.
[..]
- CPU0 executes "GIC Restoration:"
[...]
- CPU0 swicthes to non-secure mode and jumps to OS resume code.
[...]
- CPU0 is online in OS
- CPU0 enables the GIC distributor. GICD.Enable Non-secure = 1
- CPU0 wakes up CPU1 with clock-domain force wakeup method.
- CPU0 continues it's execution.
[..]
- CPU1 wakes up and start executing ROM code.
[..]
- CPU1 executes "GIC Restoration:"
[..]
- CPU1 swicthes to non-secure mode and jumps to OS resume code.
[...]
- CPU1 is online in OS and start executing.
[...] -
GIC Restoration: /* Common routine for HS and GP devices */ {
if (GICD != 1) { /* This will be true in OSWR state */
if (GIC_SAR_BACKUP_STATE == SAVED)
- CPU restores GIC distributor
else
- reconfigure GIC distributor to boot values.
GICD.Enable secure = 1
}
if (GIC_SAR_BACKUP_STATE == SAVED)
- CPU restore its GIC CPU interface registers if saved.
else
- reconfigure its GIC CPU interface registers to boot values.
}
...............................................................
So as mentioned in the flow, GICD != 1 condition decides how the GIC registers are handled in ROM code wakeup path from OSWR. As evident from the flow, ROM code relies on the entire GICD register value and not specific register bits.
The assumption was valid till CortexA9 r1pX version since there was only one banked bit to control secure and non-secure GICD. Secure view which ROM code sees:
bit 0 == Enable Non-secure
Non-secure view which HLOS sees:
bit 0 == Enable secureBut GICD register has changed between CortexA9 r1pX and r2pX. On r2pX GICD register is composed of 2 bits.
Secure view which ROM code sees:
bit 1 == Enable Non-secure
bit 0 == Enable secure
Non-secure view which HLOS sees:
bit 0 == Enable Non-secureHence on OMAP4460(r2pX) devices, if you go through the above flow again during CPU1 wakeup, GICD == 3 and hence ROM code fails to understand the real wakeup power state and reconfigures GIC distributor to boot values. This is nasty since you loose the entire interrupt controller context in a live system.
The ROM code fix done on next OMAP4 device (OMAP4470 - r2px) is to check "GICD.Enable secure != 1" for GIC restoration in OSWR wakeup path.
Since ROM code can't be fixed on OMAP4460 devices, a work around needs to be implemented. As evident from the flow, as long as CPU1 sees GICD == 1 in it's wakeup path from OSWR, the issue won't happen. Below is the flow with the work-around.
...............................................................
- MPUSS in OSWR state.
- CPU0 wakes up on the event(interrupt) and start executing ROM code.
[..]
- CPU0 executes "GIC Restoration:"
[..]
- CPU0 swicthes to non-secure mode and jumps to OS resume code.
[..]
- CPU0 is online in OS.
- CPU0 does GICD.Enable Non-secure = 0
- CPU0 wakes up CPU1 with clock domain force wakeup method.
- CPU0 waits for GICD.Enable Non-secure = 1
- CPU0 coninues it's execution.
[..]
- CPU1 wakes up and start executing ROM code.
[..]
- CPU1 executes "GIC Restoration:"
[..]
- CPU1 swicthes to non-secure mode and jumps to OS resume code.
[..]
- CPU1 is online in OS
- CPU1 does GICD.Enable Non-secure = 1
- CPU1 start executing
[...]
...............................................................
With this procedure, the GIC configuration done between the CPU0 wakeup and CPU1 wakeup will not be lost but during this short windows, the CPU0 will not receive interrupts.
The BUG is applicable to only OMAP4460(r2pX) devices. OMAP4470 (also r2pX) is not affected by this bug because ROM code has been fixed.
--- arch/arm/mach-omap2/common.h | 2 + arch/arm/mach-omap2/omap-headsmp.S | 38 +++++++++++++++++++++++++++++ arch/arm/mach-omap2/omap-mpuss-lowpower.c | 9 ++++++- arch/arm/mach-omap2/omap-smp.c | 28 ++++++++++++++++++++- arch/arm/mach-omap2/omap4-common.c | 8 +++++- arch/arm/mach-omap2/pm.h | 2 + 6 files changed, 84 insertions(+), 3 deletions(-)
arch/arm/mach-omap2/common.h +2 -0
@@ -246,6 +246,7 @@ static inline void __iomem *omap4_get_scu_base(void)#endif extern void __init gic_init_irq (void ); +extern void gic_dist_disable (void );extern void omap_smc1 (u32 fn,u32 arg);extern void __iomem *omap4_get_sar_ram_base (void );extern void omap_do_wfi (void );
@@ -253,6 +254,7 @@ extern void omap_do_wfi(void);#ifdef CONFIG_SMP /* Needed for secondary core boot */ extern void omap_secondary_startup (void ); +extern void omap_secondary_startup_4460 (void );extern u32 omap_modify_auxcoreboot0 (u32 set_mask,u32 clear_mask);extern void omap_auxcoreboot_addr (u32 cpu_addr);extern u32 omap_read_auxcoreboot0 (void );
arch/arm/mach-omap2/omap-headsmp.S +38 -0
@@ -18,6 +18,8 @@ #include <linux/linkage.h> #include <linux/init.h> +#include <plat/omap44xx.h> + __CPUINIT /* * OMAP4 specific entry point for secondary CPU to jump from ROM
@@ -43,3 +45,39 @@ hold: ldr r12,=0x103 b secondary_startup ENDPROC(omap_secondary_startup) +ENTRY(omap_secondary_startup_4460) +hold_2: ldr r12,=0x103 + dsb + smc #0 @ read from AuxCoreBoot0 + mov r0, r0, lsr #9 + mrc p15, 0, r4, c0, c0, 5 + and r4, r4, #0x0f + cmp r0, r4 + bne hold_2 + + /* + * GIC distributor control register has changed between + * CortexA9 r1pX and r2pX. The Control Register secure + * banked version is now composed of 2 bits: + * bit 0 == Secure Enable + * bit 1 == Non-Secure Enable + * The Non-Secure banked register has not changed + * Because the ROM Code is based on the r1pX GIC, the CPU1 + * GIC restoration will cause a problem to CPU0 Non-Secure SW. + * The workaround must be: + * 1) Before doing the CPU1 wakeup, CPU0 must disable + * the GIC distributor + * 2) CPU1 must re-enable the GIC distributor on + * it's wakeup path. + */ + ldr r1, =OMAP44XX_GIC_DIST_BASE + ldr r0, [r1] + orr r0, #1 + str r0, [r1] + + /* + * we've been released from the wait loop,secondary_stack + * should now contain the SVC stack for this core + */ + b secondary_startup +ENDPROC(omap_secondary_startup_4460)
arch/arm/mach-omap2/omap-mpuss-lowpower.c +8 -1
@@ -68,6 +68,7 @@ struct omap4_cpu_pm_info {void __iomem *scu_sar_addr;void __iomem *wkup_sar_addr;void __iomem *l2x0_sar_addr; +void (*secondary_startup)(void ); }; static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info);
@@ -301,6 +302,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)int __cpuinit omap4_hotplug_cpu (unsigned int cpu,unsigned int power_state) {unsigned int cpu_state =0 ; +struct omap4_cpu_pm_info *pm_info = &per_cpu (omap4_pm_info, cpu);if (omap_rev () ==OMAP4430_REV_ES1_0 )return -ENXIO ;
@@ -310,7 +312,7 @@ int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)clear_cpu_prev_pwrst (cpu);set_cpu_next_pwrst (cpu, power_state); -set_cpu_wakeup_addr (cpu,virt_to_phys (omap_secondary_startup)); +set_cpu_wakeup_addr (cpu,virt_to_phys (pm_info->secondary_startup));scu_pwrst_prepare (cpu, power_state);/*
@@ -361,6 +363,11 @@ int __init omap4_mpuss_init(void) 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 = omap_secondary_startup_4460; +else + pm_info->secondary_startup = omap_secondary_startup; + pm_info->pwrdm =pwrdm_lookup ("cpu1_pwrdm" );if (!pm_info->pwrdm) {pr_err ("Lookup failed for CPU1 pwrdm\n" );
arch/arm/mach-omap2/omap-smp.c +27 -1
@@ -30,6 +30,7 @@#include "iomap.h" #include "common.h" #include "clockdomain.h" +#include "pm.h" /* SCU base address */ static void __iomem *scu_base;
@@ -104,6 +105,24 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)* 4.3.4.2 Power States of CPU0 and CPU1 */ if (booted) { +/* +* GIC distributor control register has changed between +* CortexA9 r1pX and r2pX. The Control Register secure +* banked version is now composed of 2 bits: +* bit 0 == Secure Enable +* bit 1 == Non-Secure Enable +* The Non-Secure banked register has not changed +* Because the ROM Code is based on the r1pX GIC, the CPU1 +* GIC restoration will cause a problem to CPU0 Non-Secure SW. +* The workaround must be: +* 1) Before doing the CPU1 wakeup, CPU0 must disable +* the GIC distributor +* 2) CPU1 must re-enable the GIC distributor on +* it's wakeup path. +*/ +if (IS_PM44XX_ERRATUM (PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD )) +gic_dist_disable (); +clkdm_wakeup (cpu1_clkdm);clkdm_allow_idle (cpu1_clkdm); }else {
@@ -124,13 +143,20 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)static void __init wakeup_secondary (void ) { +void *startup_addr = omap_secondary_startup; +/* * Write the address of secondary startup routine into the * AuxCoreBoot1 where ROM code will jump and start executing * on secondary core once out of WFE * A barrier is added to ensure that write buffer is drained */ -omap_auxcoreboot_addr (virt_to_phys (omap_secondary_startup)); +if (cpu_is_omap446x ()) { + startup_addr = omap_secondary_startup_4460; + pm44xx_errata |=PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD ; + } + +omap_auxcoreboot_addr (virt_to_phys (startup_addr));smp_wmb ();/*
arch/arm/mach-omap2/omap4-common.c +7 -1
@@ -40,6 +40,7 @@ static void __iomem *l2cache_base;#endif static void __iomem *sar_ram_base; +static void __iomem *gic_dist_base_addr;#ifdef CONFIG_OMAP4_ERRATA_I688 /* Used to implement memory barrier on DRAM path */
@@ -94,7 +95,6 @@ void __init omap_barriers_init(void)void __init gic_init_irq (void ) {void __iomem *omap_irq_base; -void __iomem *gic_dist_base_addr;/* Static mapping, never released */ gic_dist_base_addr =ioremap (OMAP44XX_GIC_DIST_BASE ,SZ_4K );
@@ -109,6 +109,12 @@ void __init gic_init_irq(void)gic_init (0 ,29 , gic_dist_base_addr, omap_irq_base); } +void gic_dist_disable (void ) +{ +if (gic_dist_base_addr) +__raw_writel (0x0 , gic_dist_base_addr +GIC_DIST_CTRL ); +} +#ifdef CONFIG_CACHE_L2X0 void __iomem *omap4_get_l2cache_base (void )
arch/arm/mach-omap2/pm.h +2 -0
@@ -88,6 +88,8 @@ extern void enable_omap3630_toggle_l2_on_restore(void);static inline void enable_omap3630_toggle_l2_on_restore (void ) { }#endif /* defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) */ +#define PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD (1 << 0) +#if defined(CONFIG_ARCH_OMAP4 )extern u16 pm44xx_errata;#define IS_PM44XX_ERRATUM (id) (pm44xx_errata & (id))
Signature · 1 line
1.7.4.1
PATCH v7 3/12 ARM: OMAP4: hwmod: flag hwmods/modules not supporting module level context status
In reply to Tero KristoOn OMAP4 most modules/hwmods support module level context status. On OMAP3 and earlier, we relied on the power domain level context status. Identify all modules that don't support 'context_offs' by marking the offset as USHRT_MAX. Rest have a valid 'context_offs' populated in .prcm structure already.
--- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 46 ++++++++++++++++++++++++++++ 1 files changed, 46 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/omap_hwmod_44xx_data.c +46 -0
@@ -204,6 +204,7 @@ static struct omap_hwmod omap44xx_l4_abe_hwmod = { .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM1_ABE_L4ABE_CLKCTRL_OFFSET, + .context_offs = USHRT_MAX, }, }, };
@@ -260,6 +261,11 @@ static struct omap_hwmod omap44xx_mpu_private_hwmod = { .name = "mpu_private", .class = &omap44xx_mpu_bus_hwmod_class, .clkdm_name = "mpuss_clkdm", + .prcm = { + .omap4 = { + .context_offs = USHRT_MAX, + }, + }, };/*
@@ -448,6 +454,11 @@ static struct omap_hwmod omap44xx_ctrl_module_core_hwmod = { .class = &omap44xx_ctrl_module_hwmod_class, .clkdm_name = "l4_cfg_clkdm", .mpu_irqs = omap44xx_ctrl_module_core_irqs, + .prcm = { + .omap4 = { + .context_offs = USHRT_MAX, + }, + }, };/* ctrl_module_pad_core */
@@ -455,6 +466,11 @@ static struct omap_hwmod omap44xx_ctrl_module_pad_core_hwmod = { .name = "ctrl_module_pad_core", .class = &omap44xx_ctrl_module_hwmod_class, .clkdm_name = "l4_cfg_clkdm", + .prcm = { + .omap4 = { + .context_offs = USHRT_MAX, + }, + }, };/* ctrl_module_wkup */
@@ -462,6 +478,11 @@ static struct omap_hwmod omap44xx_ctrl_module_wkup_hwmod = { .name = "ctrl_module_wkup", .class = &omap44xx_ctrl_module_hwmod_class, .clkdm_name = "l4_wkup_clkdm", + .prcm = { + .omap4 = { + .context_offs = USHRT_MAX, + }, + }, };/* ctrl_module_pad_wkup */
@@ -469,6 +490,11 @@ static struct omap_hwmod omap44xx_ctrl_module_pad_wkup_hwmod = { .name = "ctrl_module_pad_wkup", .class = &omap44xx_ctrl_module_hwmod_class, .clkdm_name = "l4_wkup_clkdm", + .prcm = { + .omap4 = { + .context_offs = USHRT_MAX, + }, + }, };/*
@@ -2538,6 +2564,11 @@ static struct omap_hwmod omap44xx_prcm_mpu_hwmod = { .name = "prcm_mpu", .class = &omap44xx_prcm_hwmod_class, .clkdm_name = "l4_wkup_clkdm", + .prcm = { + .omap4 = { + .context_offs = USHRT_MAX, + }, + }, };/* cm_core_aon */
@@ -2545,6 +2576,11 @@ static struct omap_hwmod omap44xx_cm_core_aon_hwmod = { .name = "cm_core_aon", .class = &omap44xx_prcm_hwmod_class, .clkdm_name = "cm_clkdm", + .prcm = { + .omap4 = { + .context_offs = USHRT_MAX, + }, + }, };/* cm_core */
@@ -2552,6 +2588,11 @@ static struct omap_hwmod omap44xx_cm_core_hwmod = { .name = "cm_core", .class = &omap44xx_prcm_hwmod_class, .clkdm_name = "cm_clkdm", + .prcm = { + .omap4 = { + .context_offs = USHRT_MAX, + }, + }, };/* prm */
@@ -2588,6 +2629,11 @@ static struct omap_hwmod omap44xx_scrm_hwmod = { .name = "scrm", .class = &omap44xx_scrm_hwmod_class, .clkdm_name = "l4_wkup_clkdm", + .prcm = { + .omap4 = { + .context_offs = USHRT_MAX, + }, + }, };/*
Signature · 1 line
1.7.4.1
Paul Walmsley
maintainerPATCH v7 3/12 ARM: OMAP4: hwmod: flag hwmods/modules not supporting module level context status
Hi Tero,
Quoted 7 lines · Tero Kristo
On OMAP4 most modules/hwmods support module level context status. On OMAP3 and earlier, we relied on the power domain level context status. Identify all modules that don't support '
context_offs' by marking the offset asUSHRT_MAX. Rest have a valid 'context_offs' populated in .prcm structure already.Signed-off-by Tero Kristo <[email protected]>
This one was changed here to use a separate flag rather than adding a magic value to the context_offs field -- mostly because I've been burnt by missing tests for those kinds of magic values in the past. It should be possible to roll the .modulemode field into this .flags field in a future patch to eliminate any kernel object size changes.
The modified patch is below, queued for 3.7.
- Paul
From: Tero Kristo <[email protected]>
Date: Wed, 12 Sep 2012 11:53:54 -0600
Subject: [PATCH] ARM: OMAP4: hwmod: flag hwmods/modules not supporting module
level context status
On OMAP4 most modules/hwmods support module level context status. On OMAP3 and earlier, we relied on the power domain level context status. Identify all modules that don't support 'context_offs' by adding a flag bit, HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT. Rest have a valid 'context_offs' populated in .prcm structure already.
[paul at pwsan.com: add flag bit rather than overloading .context_offs;
update changelog message]
--- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 46 ++++++++++++++++++++++++++ arch/arm/plat-omap/include/plat/omap_hwmod.h | 12 ++++++- 2 files changed, 57 insertions(+), 1 deletion(-)
arch/arm/mach-omap2/omap_hwmod_44xx_data.c +46 -0
@@ -203,6 +203,7 @@ static struct omap_hwmod omap44xx_l4_abe_hwmod = { .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM1_ABE_L4ABE_CLKCTRL_OFFSET, + .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT, }, }, };
@@ -259,6 +260,11 @@ static struct omap_hwmod omap44xx_mpu_private_hwmod = { .name = "mpu_private", .class = &omap44xx_mpu_bus_hwmod_class, .clkdm_name = "mpuss_clkdm", + .prcm = { + .omap4 = { + .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT, + }, + }, };/*
@@ -447,6 +453,11 @@ static struct omap_hwmod omap44xx_ctrl_module_core_hwmod = { .class = &omap44xx_ctrl_module_hwmod_class, .clkdm_name = "l4_cfg_clkdm", .mpu_irqs = omap44xx_ctrl_module_core_irqs, + .prcm = { + .omap4 = { + .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT, + }, + }, };/* ctrl_module_pad_core */
@@ -454,6 +465,11 @@ static struct omap_hwmod omap44xx_ctrl_module_pad_core_hwmod = { .name = "ctrl_module_pad_core", .class = &omap44xx_ctrl_module_hwmod_class, .clkdm_name = "l4_cfg_clkdm", + .prcm = { + .omap4 = { + .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT, + }, + }, };/* ctrl_module_wkup */
@@ -461,6 +477,11 @@ static struct omap_hwmod omap44xx_ctrl_module_wkup_hwmod = { .name = "ctrl_module_wkup", .class = &omap44xx_ctrl_module_hwmod_class, .clkdm_name = "l4_wkup_clkdm", + .prcm = { + .omap4 = { + .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT, + }, + }, };/* ctrl_module_pad_wkup */
@@ -468,6 +489,11 @@ static struct omap_hwmod omap44xx_ctrl_module_pad_wkup_hwmod = { .name = "ctrl_module_pad_wkup", .class = &omap44xx_ctrl_module_hwmod_class, .clkdm_name = "l4_wkup_clkdm", + .prcm = { + .omap4 = { + .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT, + }, + }, };/*
@@ -2537,18 +2563,33 @@ static struct omap_hwmod omap44xx_prcm_mpu_hwmod = { .name = "prcm_mpu", .class = &omap44xx_prcm_hwmod_class, .clkdm_name = "l4_wkup_clkdm", + .prcm = { + .omap4 = { + .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT, + }, + }, };/* cm_core_aon */ static struct omap_hwmod omap44xx_cm_core_aon_hwmod = { .name ="cm_core_aon" , .class = &omap44xx_prcm_hwmod_class, + .prcm = { + .omap4 = { + .flags =HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT , + }, + }, };/* cm_core */ static struct omap_hwmod omap44xx_cm_core_hwmod = { .name ="cm_core" , .class = &omap44xx_prcm_hwmod_class, + .prcm = { + .omap4 = { + .flags =HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT , + }, + }, };/* prm */
@@ -2584,6 +2625,11 @@ static struct omap_hwmod omap44xx_scrm_hwmod = { .name = "scrm", .class = &omap44xx_scrm_hwmod_class, .clkdm_name = "l4_wkup_clkdm", + .prcm = { + .omap4 = { + .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT, + }, + }, };/*
arch/arm/plat-omap/include/plat/omap_hwmod.h +11 -1
@@ -2,7 +2,7 @@* omap_hwmod macros, structures * * Copyright (C) 2009-2011 Nokia Corporation -* Copyright (C) 2011 Texas Instruments, Inc. +* Copyright (C) 2012 Texas Instruments, Inc. * Paul Walmsley * * Created in collaboration with (alphabetical order): Beno?t Cousson,
@@ -384,6 +384,14 @@ struct omap_hwmod_omap2_prcm {u8 idlest_stdby_bit; }; +/* +* Possible values for struct omap_hwmod_omap4_prcm.flags +* +* HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT: Some IP blocks don't have a PRCM +* module-level context loss register associated with them; this +* flag bit should be set in those cases +*/ +#define HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT (1 << 0)/** * struct omap_hwmod_omap4_prcm - OMAP4-specific PRCM data
@@ -391,6 +399,7 @@ struct omap_hwmod_omap2_prcm {* @rstctrl_reg: address of the XXX_RSTCTRL register located in the PRM * @rstst_reg: (AM33XX only) address of the XXX_RSTST register in the PRM * @submodule_wkdep_bit: bit shift of the WKDEP range +* @flags: PRCM register capabilities for this IP block */ struct omap_hwmod_omap4_prcm {u16 clkctrl_offs;
@@ -399,6 +408,7 @@ struct omap_hwmod_omap4_prcm {u16 context_offs;u8 submodule_wkdep_bit;u8 modulemode; +u8 flags; };
Signature · 1 line
1.7.10.4
PATCH v7 4/12 ARM: OMAP: hwmod: Add support for per hwmod/module context lost count
In reply to Tero KristoFrom: Rajendra Nayak <[email protected]>
OMAP4 has module specific context lost registers which makes it now possible to have module level context loss count, instead of relying on the powerdomain level context count.
Add 2 private hwmod api's to update/clear the hwmod/module specific context lost counters/register.
Update the module specific context_lost_counter and clear the hardware bits just after enabling the module.
omap_hwmod_get_context_loss_count() now returns the hwmod context loss count them on platforms where they exist (OMAP4), else fall back on the pwrdm level counters for older platforms.
[paul at pwsan.com: added function kerneldoc, fixed structure kerneldoc,
rearranged structure to avoid memory waste, marked fns as OMAP4-specific, prevent fn entry on non-OMAP4 chips, reduced indentation, merged update and clear, merged patches]
[t-kristo at ti.com: added support for arch specific hwmod ops, and changed
the no context offset indicator to USHRT_MAX]
--- arch/arm/mach-omap2/omap_hwmod.c | 71 ++++++++++++++++++++++++-- arch/arm/plat-omap/include/plat/omap_hwmod.h | 8 ++- 2 files changed, 73 insertions(+), 6 deletions(-)
arch/arm/mach-omap2/omap_hwmod.c +67 -4
@@ -170,6 +170,13 @@/* omap_hwmod_list contains all registered struct omap_hwmods */ static LIST_HEAD (omap_hwmod_list); +struct hwmod_ops { +void (*hwmod_update_context_lost)(struct omap_hwmod *oh); +int (*hwmod_get_context_lost)(struct omap_hwmod *oh); +}; + +static struct hwmod_ops *arch_hwmod; +/* mpu_oh: used to add/remove MPU initiator from sleepdep list */ static struct omap_hwmod *mpu_oh;
@@ -1784,6 +1791,52 @@ static void _reconfigure_io_chain(void) }/** +* _omap4_update_context_lost - increment hwmod context loss counter if +* hwmod context was lost, and clear hardware context loss reg +* @oh: hwmod to check for context loss +* +* If the PRCM indicates that the hwmod @oh lost context, increment +* our in-memory context loss counter, and clear the RM_*_CONTEXT +* bits. No return value. +*/ +static void _omap4_update_context_lost (struct omap_hwmod *oh) +{ +u32 r; + +if (oh->prcm.omap4.context_offs ==USHRT_MAX ) +return ; + + r =omap4_prminst_read_inst_reg (oh->clkdm->pwrdm.ptr->prcm_partition, + oh->clkdm->pwrdm.ptr->prcm_offs, + oh->prcm.omap4.context_offs); + +if (!r) +return ; + + oh->prcm.omap4.context_lost_counter++; + +omap4_prminst_write_inst_reg (r, oh->clkdm->pwrdm.ptr->prcm_partition, + oh->clkdm->pwrdm.ptr->prcm_offs, + oh->prcm.omap4.context_offs); +} + +/** +* _omap4_get_context_lost - get context loss counter for a hwmod +* @oh: hwmod to get context loss counter for +* +* Returns the in-memory context loss counter for a hwmod. +*/ +static int _omap4_get_context_lost (struct omap_hwmod *oh) +{ +return oh->prcm.omap4.context_lost_counter; +} + +static struct hwmod_ops omap4_hwmod_ops = { + .hwmod_update_context_lost = _omap4_update_context_lost, + .hwmod_get_context_lost = _omap4_get_context_lost, +}; + +/** * _enable - enable an omap_hwmod * @oh: struct omap_hwmod * *
@@ -1864,6 +1917,9 @@ static int _enable(struct omap_hwmod *oh)_enable_clocks (oh);_enable_module (oh); +if (arch_hwmod && arch_hwmod->hwmod_update_context_lost) + arch_hwmod->hwmod_update_context_lost (oh); + r =_wait_target_ready (oh);if (!r) {/*
@@ -2700,6 +2756,9 @@ int __init omap_hwmod_setup_one(const char *oh_name)*/ static int __init omap_hwmod_setup_all (void ) { +if (cpu_is_omap44xx ()) + arch_hwmod = &omap4_hwmod_ops; +_ensure_mpu_hwmod_is_setup (NULL );omap_hwmod_for_each (_init,NULL );
@@ -3353,17 +3412,21 @@ ohsps_unlock:* omap_hwmod_get_context_loss_count - get lost context count * @oh: struct omap_hwmod * * -* Query the powerdomain of of @oh to get the context loss -* count for this device. +* Returns the context loss count of associated @oh +* upon success, or zero if no context loss data is available. * -* Returns the context loss count of the powerdomain assocated with @oh -* upon success, or zero if no powerdomain exists for @oh. +* On OMAP4, this queries the per-hwmod context loss register, +* assuming one exists. If not, or on OMAP2/3, this queries the +* enclosing powerdomain context loss count. */ int omap_hwmod_get_context_loss_count (struct omap_hwmod *oh) {struct powerdomain *pwrdm;int ret =0 ; +if (arch_hwmod && arch_hwmod->hwmod_get_context_lost) +return arch_hwmod->hwmod_get_context_lost (oh); + pwrdm =omap_hwmod_get_pwrdm (oh);if (pwrdm) ret =pwrdm_get_context_loss_count (pwrdm);
arch/arm/plat-omap/include/plat/omap_hwmod.h +6 -2
@@ -372,9 +372,12 @@ struct omap_hwmod_omap2_prcm {/** * struct omap_hwmod_omap4_prcm - OMAP4-specific PRCM data -* @clkctrl_reg: PRCM address of the clock control register -* @rstctrl_reg: address of the XXX_RSTCTRL register located in the PRM +* @clkctrl_offs: offset of the PRCM clock control register +* @rstctrl_offs: offset of the XXX_RSTCTRL register located in the PRM +* @context_offs: offset of the RM_*_CONTEXT register * @submodule_wkdep_bit: bit shift of the WKDEP range +* @modulemode: allowable modulemodes +* @context_lost_counter: Count of module level context lost */ struct omap_hwmod_omap4_prcm {u16 clkctrl_offs;
@@ -382,6 +385,7 @@ struct omap_hwmod_omap4_prcm {u16 context_offs;u8 submodule_wkdep_bit;u8 modulemode; +unsigned context_lost_counter; };
Signature · 1 line
1.7.4.1
Paul Walmsley
maintainerPATCH v7 4/12 ARM: OMAP: hwmod: Add support for per hwmod/module context lost count
Quoted 17 lines · Tero Kristo
From: Rajendra Nayak <[email protected]>
OMAP4 has module specific context lost registers which makes it now possible to have module level context loss count, instead of relying on the powerdomain level context count.
Add 2 private hwmod api's to update/clear the hwmod/module specific context lost counters/register.
Update the module specific
context_lost_counterand clear the hardware bits just after enabling the module.
omap_hwmod_get_context_loss_count()now returns the hwmod context loss count them on platforms where they exist (OMAP4), else fall back on the pwrdm level counters for older platforms.Signed-off-by Rajendra Nayak <[email protected]>
Quoted 8 lines
[paul at pwsan.com: added function kerneldoc, fixed structure kerneldoc,
rearranged structure to avoid memory waste, marked fns as OMAP4-specific, prevent fn entry on non-OMAP4 chips, reduced indentation, merged update and clear, merged patches]Signed-off-by Paul Walmsley <[email protected]>[t-kristo at ti.com: added support for arch specific hwmod ops, and changed
the no context offset indicator toUSHRT_MAX]Signed-off-by Tero Kristo <[email protected]>
This one has been modified to align with the changes on patch 3, and queued for 3.7.
- Paul
From: Rajendra Nayak <[email protected]>
Date: Wed, 12 Sep 2012 11:55:55 -0600
Subject: [PATCH] ARM: OMAP: hwmod: Add support for per hwmod/module context
lost count
OMAP4 has module specific context lost registers which makes it now possible to have module level context loss count, instead of relying on the powerdomain level context count.
Add 2 private hwmod api's to update/clear the hwmod/module specific context lost counters/register.
Update the module specific context_lost_counter and clear the hardware bits just after enabling the module.
omap_hwmod_get_context_loss_count() now returns the hwmod context loss count them on platforms where they exist (OMAP4), else fall back on the pwrdm level counters for older platforms.
[paul at pwsan.com: added function kerneldoc, fixed structure kerneldoc,
rearranged structure to avoid memory waste, marked fns as OMAP4-specific, prevent fn entry on non-OMAP4 chips, reduced indentation, merged update and clear, merged patches]
[t-kristo at ti.com: added support for arch specific hwmod ops, and changed
the no context offset indicator to USHRT_MAX]
--- arch/arm/mach-omap2/omap_hwmod.c | 71 ++++++++++++++++++++++++-- arch/arm/plat-omap/include/plat/omap_hwmod.h | 11 ++-- 2 files changed, 74 insertions(+), 8 deletions(-)
arch/arm/mach-omap2/omap_hwmod.c +67 -4
@@ -195,6 +195,13 @@ static struct omap_hwmod_soc_ops soc_ops;/* omap_hwmod_list contains all registered struct omap_hwmods */ static LIST_HEAD (omap_hwmod_list); +struct hwmod_ops { +void (*hwmod_update_context_lost)(struct omap_hwmod *oh); +int (*hwmod_get_context_lost)(struct omap_hwmod *oh); +}; + +static struct hwmod_ops *arch_hwmod; +/* mpu_oh: used to add/remove MPU initiator from sleepdep list */ static struct omap_hwmod *mpu_oh;
@@ -1789,6 +1796,52 @@ static void _reconfigure_io_chain(void) }/** +* _omap4_update_context_lost - increment hwmod context loss counter if +* hwmod context was lost, and clear hardware context loss reg +* @oh: hwmod to check for context loss +* +* If the PRCM indicates that the hwmod @oh lost context, increment +* our in-memory context loss counter, and clear the RM_*_CONTEXT +* bits. No return value. +*/ +static void _omap4_update_context_lost (struct omap_hwmod *oh) +{ +u32 r; + +if (oh->prcm.omap4.flags &HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT ) +return ; + + r =omap4_prminst_read_inst_reg (oh->clkdm->pwrdm.ptr->prcm_partition, + oh->clkdm->pwrdm.ptr->prcm_offs, + oh->prcm.omap4.context_offs); + +if (!r) +return ; + + oh->prcm.omap4.context_lost_counter++; + +omap4_prminst_write_inst_reg (r, oh->clkdm->pwrdm.ptr->prcm_partition, + oh->clkdm->pwrdm.ptr->prcm_offs, + oh->prcm.omap4.context_offs); +} + +/** +* _omap4_get_context_lost - get context loss counter for a hwmod +* @oh: hwmod to get context loss counter for +* +* Returns the in-memory context loss counter for a hwmod. +*/ +static int _omap4_get_context_lost (struct omap_hwmod *oh) +{ +return oh->prcm.omap4.context_lost_counter; +} + +static struct hwmod_ops omap4_hwmod_ops = { + .hwmod_update_context_lost = _omap4_update_context_lost, + .hwmod_get_context_lost = _omap4_get_context_lost, +}; + +/** * _enable - enable an omap_hwmod * @oh: struct omap_hwmod * *
@@ -1870,6 +1923,9 @@ static int _enable(struct omap_hwmod *oh)if (soc_ops.enable_module) soc_ops.enable_module (oh); +if (arch_hwmod && arch_hwmod->hwmod_update_context_lost) + arch_hwmod->hwmod_update_context_lost (oh); + r = (soc_ops.wait_target_ready) ? soc_ops.wait_target_ready (oh) : -EINVAL ;if (!r) {
@@ -2903,6 +2959,9 @@ int __init omap_hwmod_setup_one(const char *oh_name)*/ static int __init omap_hwmod_setup_all (void ) { +if (cpu_is_omap44xx ()) + arch_hwmod = &omap4_hwmod_ops; +_ensure_mpu_hwmod_is_setup (NULL );omap_hwmod_for_each (_init,NULL );
@@ -3557,17 +3616,21 @@ ohsps_unlock:* omap_hwmod_get_context_loss_count - get lost context count * @oh: struct omap_hwmod * * -* Query the powerdomain of of @oh to get the context loss -* count for this device. +* Returns the context loss count of associated @oh +* upon success, or zero if no context loss data is available. * -* Returns the context loss count of the powerdomain assocated with @oh -* upon success, or zero if no powerdomain exists for @oh. +* On OMAP4, this queries the per-hwmod context loss register, +* assuming one exists. If not, or on OMAP2/3, this queries the +* enclosing powerdomain context loss count. */ int omap_hwmod_get_context_loss_count (struct omap_hwmod *oh) {struct powerdomain *pwrdm;int ret =0 ; +if (arch_hwmod && arch_hwmod->hwmod_get_context_lost) +return arch_hwmod->hwmod_get_context_lost (oh); + pwrdm =omap_hwmod_get_pwrdm (oh);if (pwrdm) ret =pwrdm_get_context_loss_count (pwrdm);
arch/arm/plat-omap/include/plat/omap_hwmod.h +7 -4
@@ -2,7 +2,7 @@* omap_hwmod macros, structures * * Copyright (C) 2009-2011 Nokia Corporation -* Copyright (C) 2012 Texas Instruments, Inc. +* Copyright (C) 2011-2012 Texas Instruments, Inc. * Paul Walmsley * * Created in collaboration with (alphabetical order): Beno?t Cousson,
@@ -392,14 +392,16 @@ struct omap_hwmod_omap2_prcm {* flag bit should be set in those cases */ #define HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT (1 << 0) -/** * struct omap_hwmod_omap4_prcm - OMAP4-specific PRCM data -* @clkctrl_reg: PRCM address of the clock control register -* @rstctrl_reg: address of the XXX_RSTCTRL register located in the PRM +* @clkctrl_offs: offset of the PRCM clock control register +* @rstctrl_offs: offset of the XXX_RSTCTRL register located in the PRM +* @context_offs: offset of the RM_*_CONTEXT register * @rstst_reg: (AM33XX only) address of the XXX_RSTST register in the PRM * @submodule_wkdep_bit: bit shift of the WKDEP range * @flags: PRCM register capabilities for this IP block +* @modulemode: allowable modulemodes +* @context_lost_counter: Count of module level context lost */ struct omap_hwmod_omap4_prcm {u16 clkctrl_offs;
@@ -409,6 +411,7 @@ struct omap_hwmod_omap4_prcm {u8 submodule_wkdep_bit;u8 modulemode;u8 flags; +unsigned context_lost_counter; };
Signature · 1 line
1.7.10.4
Paul Walmsley
maintainerPATCH v7 4/12 ARM: OMAP: hwmod: Add support for per hwmod/module context lost count
Hi
Well, anyway. This patch had some other issues that were found upon a closer inspection:
- it adds a new 'hwmod_ops' set of function pointers rather than using the existing 'soc_ops' mechanism
- it returns an unsigned int as a signed integer -- not sure why static analysis didn't catch this one :-(
Here's the updated patch.
- Paul
From: Rajendra Nayak <[email protected]>
Date: Wed, 12 Sep 2012 11:55:55 -0600
Subject: [PATCH] ARM: OMAP: hwmod: Add support for per hwmod/module context
lost count
OMAP4 has module specific context lost registers which makes it now possible to have module level context loss count, instead of relying on the powerdomain level context count.
Add 2 private hwmod api's to update/clear the hwmod/module specific context lost counters/register.
Update the module specific context_lost_counter and clear the hardware bits just after enabling the module.
omap_hwmod_get_context_loss_count() now returns the hwmod context loss count them on platforms where they exist (OMAP4), else fall back on the pwrdm level counters for older platforms.
[paul at pwsan.com: added function kerneldoc, fixed structure kerneldoc,
rearranged structure to avoid memory waste, marked fns as OMAP4-specific, prevent fn entry on non-OMAP4 chips, reduced indentation, merged update and clear, merged patches]
[t-kristo at ti.com: added support for arch specific hwmod ops, and changed
the no context offset indicator to USHRT_MAX]
[paul at pwsan.com: use NO_CONTEXT_LOSS_BIT flag rather than USHRT_MAX;
convert unsigned context lost counter to int to match the return type; get rid of hwmod_ops in favor of the existing soc_ops mechanism]
--- arch/arm/mach-omap2/omap_hwmod.c | 60 ++++++++++++++++++++++++-- arch/arm/plat-omap/include/plat/omap_hwmod.h | 11 +++-- 2 files changed, 63 insertions(+), 8 deletions(-)
arch/arm/mach-omap2/omap_hwmod.c +56 -4
@@ -187,6 +187,8 @@ struct omap_hwmod_soc_ops {int (*is_hardreset_asserted)(struct omap_hwmod *oh,struct omap_hwmod_rst_info *ohri);int (*init_clkdm)(struct omap_hwmod *oh); +void (*update_context_lost)(struct omap_hwmod *oh); +int (*get_context_lost)(struct omap_hwmod *oh); };/* soc_ops: adapts the omap_hwmod code to the currently-booted SoC */
@@ -1789,6 +1791,47 @@ static void _reconfigure_io_chain(void) }/** +* _omap4_update_context_lost - increment hwmod context loss counter if +* hwmod context was lost, and clear hardware context loss reg +* @oh: hwmod to check for context loss +* +* If the PRCM indicates that the hwmod @oh lost context, increment +* our in-memory context loss counter, and clear the RM_*_CONTEXT +* bits. No return value. +*/ +static void _omap4_update_context_lost (struct omap_hwmod *oh) +{ +u32 r; + +if (oh->prcm.omap4.flags &HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT ) +return ; + + r =omap4_prminst_read_inst_reg (oh->clkdm->pwrdm.ptr->prcm_partition, + oh->clkdm->pwrdm.ptr->prcm_offs, + oh->prcm.omap4.context_offs); + +if (!r) +return ; + + oh->prcm.omap4.context_lost_counter++; + +omap4_prminst_write_inst_reg (r, oh->clkdm->pwrdm.ptr->prcm_partition, + oh->clkdm->pwrdm.ptr->prcm_offs, + oh->prcm.omap4.context_offs); +} + +/** +* _omap4_get_context_lost - get context loss counter for a hwmod +* @oh: hwmod to get context loss counter for +* +* Returns the in-memory context loss counter for a hwmod. +*/ +static int _omap4_get_context_lost (struct omap_hwmod *oh) +{ +return oh->prcm.omap4.context_lost_counter; +} + +/** * _enable - enable an omap_hwmod * @oh: struct omap_hwmod * *
@@ -1870,6 +1913,9 @@ static int _enable(struct omap_hwmod *oh)if (soc_ops.enable_module) soc_ops.enable_module (oh); +if (soc_ops.update_context_lost) + soc_ops.update_context_lost (oh); + r = (soc_ops.wait_target_ready) ? soc_ops.wait_target_ready (oh) : -EINVAL ;if (!r) {
@@ -3557,17 +3603,21 @@ ohsps_unlock:* omap_hwmod_get_context_loss_count - get lost context count * @oh: struct omap_hwmod * * -* Query the powerdomain of of @oh to get the context loss -* count for this device. +* Returns the context loss count of associated @oh +* upon success, or zero if no context loss data is available. * -* Returns the context loss count of the powerdomain assocated with @oh -* upon success, or zero if no powerdomain exists for @oh. +* On OMAP4, this queries the per-hwmod context loss register, +* assuming one exists. If not, or on OMAP2/3, this queries the +* enclosing powerdomain context loss count. */ int omap_hwmod_get_context_loss_count (struct omap_hwmod *oh) {struct powerdomain *pwrdm;int ret =0 ; +if (soc_ops.get_context_lost) +return soc_ops.get_context_lost (oh); + pwrdm =omap_hwmod_get_pwrdm (oh);if (pwrdm) ret =pwrdm_get_context_loss_count (pwrdm);
@@ -3677,6 +3727,8 @@ void __init omap_hwmod_init(void) soc_ops.deassert_hardreset = _omap4_deassert_hardreset; soc_ops.is_hardreset_asserted = _omap4_is_hardreset_asserted; soc_ops.init_clkdm = _init_clkdm; + soc_ops.update_context_lost = _omap4_update_context_lost; + soc_ops.get_context_lost = _omap4_get_context_lost; }else {WARN (1 ,"omap_hwmod: unknown SoC type\n" ); }
arch/arm/plat-omap/include/plat/omap_hwmod.h +7 -4
@@ -2,7 +2,7 @@* omap_hwmod macros, structures * * Copyright (C) 2009-2011 Nokia Corporation -* Copyright (C) 2012 Texas Instruments, Inc. +* Copyright (C) 2011-2012 Texas Instruments, Inc. * Paul Walmsley * * Created in collaboration with (alphabetical order): Beno?t Cousson,
@@ -392,14 +392,16 @@ struct omap_hwmod_omap2_prcm {* flag bit should be set in those cases */ #define HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT (1 << 0) -/** * struct omap_hwmod_omap4_prcm - OMAP4-specific PRCM data -* @clkctrl_reg: PRCM address of the clock control register -* @rstctrl_reg: address of the XXX_RSTCTRL register located in the PRM +* @clkctrl_offs: offset of the PRCM clock control register +* @rstctrl_offs: offset of the XXX_RSTCTRL register located in the PRM +* @context_offs: offset of the RM_*_CONTEXT register * @rstst_reg: (AM33XX only) address of the XXX_RSTST register in the PRM * @submodule_wkdep_bit: bit shift of the WKDEP range * @flags: PRCM register capabilities for this IP block +* @modulemode: allowable modulemodes +* @context_lost_counter: Count of module level context lost */ struct omap_hwmod_omap4_prcm {u16 clkctrl_offs;
@@ -409,6 +411,7 @@ struct omap_hwmod_omap4_prcm {u8 submodule_wkdep_bit;u8 modulemode;u8 flags; +int context_lost_counter; };
Signature · 1 line
1.7.10.4
Paul Walmsley
maintainerPATCH v7 4/12 ARM: OMAP: hwmod: Add support for per hwmod/module context lost count
In reply to Paul WalmsleyHi
Quoted 8 lines · Paul Walmsley
Quoted 6 lines · Tero Kristo
From: Rajendra Nayak <[email protected]>
OMAP4 has module specific context lost registers which makes it now possible to have module level context loss count, instead of relying on the powerdomain level context count.
Quoted 5 lines
Quoted 2 lines
Add 2 private hwmod api's to update/clear the hwmod/module specific context lost counters/register.
This one has been modified to align with the changes on patch 3, and queued for 3.7.
Am sorry to say that I had to drop the code changes from this patch, due to the OMAP serial bugs addressed by these two patches:
http://comments.gmane.org/gmane.linux.ports.arm.omap/84729 http://www.spinics.net/lists/arm-kernel/msg196034.html
Without those two patches, OMAP4430ES2 Panda crashes after Tero's patches are applied, with the same symptom as with the N800 crash. Applying those two patches fixes the problem.
It would be good if you guys could ask Greg to pick up the first patch ASAP so we can queue the second one during the early 3.7-rc time frame.
- Paul
PATCH v7 5/12 ARM: OMAP4: pwrdm: add support for reading prev logic and mem states
In reply to Tero KristoOn OMAP4, there is no support to read previous logic state or previous memory state achieved when a power domain transitions to RET. Instead there are module level context registers.
In order to support the powerdomain level logic/mem_off_counters on OMAP4, instead use the previous power state achieved (RET) and the *programmed* logic/mem RET state to derive if a powerdomain lost logic or did not.
If the powerdomain is programmed to enter RET state and lose logic in RET state, knowing that the powerdomain entered RET is good enough to derive that the logic was lost as well, in such cases.
--- arch/arm/mach-omap2/powerdomain44xx.c | 59 +++++++++++++++++++++++++++++++++ 1 files changed, 59 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/powerdomain44xx.c +59 -0
@@ -151,6 +151,34 @@ static int omap4_pwrdm_read_logic_retst(struct powerdomain *pwrdm)return v; } +/** +* omap4_pwrdm_read_prev_logic_pwrst - read the previous logic powerstate +* @pwrdm: struct powerdomain * to read the state for +* +* Reads the previous logic powerstate for a powerdomain. This function +* must determine the previous logic powerstate by first checking the +* previous powerstate for the domain. If that was OFF, then logic has +* been lost. If previous state was RETENTION, the function reads the +* setting for the next retention logic state to see the actual value. +* In every other case, the logic is retained. Returns either +* PWRDM_LOGIC_MEM_PWRST_OFF or PWRDM_LOGIC_MEM_PWRST_RET depending +* whether the logic was retained or not. +*/ +static int omap4_pwrdm_read_prev_logic_pwrst (struct powerdomain *pwrdm) +{ +int state; + + state =omap4_pwrdm_read_prev_pwrst (pwrdm); + +if (state ==PWRDM_POWER_OFF ) +return PWRDM_LOGIC_MEM_PWRST_OFF ; + +if (state !=PWRDM_POWER_RET ) +return PWRDM_LOGIC_MEM_PWRST_RET ; + +return omap4_pwrdm_read_logic_retst (pwrdm); +} +static int omap4_pwrdm_read_mem_pwrst (struct powerdomain *pwrdm,u8 bank) {u32 m, v;
@@ -179,6 +207,35 @@ static int omap4_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)return v; } +/** +* omap4_pwrdm_read_prev_mem_pwrst - reads the previous memory powerstate +* @pwrdm: struct powerdomain * to read mem powerstate for +* @bank: memory bank index +* +* Reads the previous memory powerstate for a powerdomain. This function +* must determine the previous memory powerstate by first checking the +* previous powerstate for the domain. If that was OFF, then logic has +* been lost. If previous state was RETENTION, the function reads the +* setting for the next memory retention state to see the actual value. +* In every other case, the logic is retained. Returns either +* PWRDM_LOGIC_MEM_PWRST_OFF or PWRDM_LOGIC_MEM_PWRST_RET depending +* whether logic was retained or not. +*/ +static int omap4_pwrdm_read_prev_mem_pwrst (struct powerdomain *pwrdm,u8 bank) +{ +int state; + + state =omap4_pwrdm_read_prev_pwrst (pwrdm); + +if (state ==PWRDM_POWER_OFF ) +return PWRDM_LOGIC_MEM_PWRST_OFF ; + +if (state !=PWRDM_POWER_RET ) +return PWRDM_LOGIC_MEM_PWRST_RET ; + +return omap4_pwrdm_read_mem_retst (pwrdm, bank); +} +static int omap4_pwrdm_wait_transition (struct powerdomain *pwrdm) {u32 c =0 ;
@@ -220,9 +277,11 @@ struct pwrdm_ops omap4_pwrdm_operations = { .pwrdm_clear_all_prev_pwrst = omap4_pwrdm_clear_all_prev_pwrst, .pwrdm_set_logic_retst = omap4_pwrdm_set_logic_retst, .pwrdm_read_logic_pwrst = omap4_pwrdm_read_logic_pwrst, + .pwrdm_read_prev_logic_pwrst = omap4_pwrdm_read_prev_logic_pwrst, .pwrdm_read_logic_retst = omap4_pwrdm_read_logic_retst, .pwrdm_read_mem_pwrst = omap4_pwrdm_read_mem_pwrst, .pwrdm_read_mem_retst = omap4_pwrdm_read_mem_retst, + .pwrdm_read_prev_mem_pwrst = omap4_pwrdm_read_prev_mem_pwrst, .pwrdm_set_mem_onst = omap4_pwrdm_set_mem_onst, .pwrdm_set_mem_retst = omap4_pwrdm_set_mem_retst, .pwrdm_wait_transition = omap4_pwrdm_wait_transition,
Signature · 1 line
1.7.4.1
Paul Walmsley
maintainerPATCH v7 5/12 ARM: OMAP4: pwrdm: add support for reading prev logic and mem states
Quoted 9 lines · Tero Kristo
On OMAP4, there is no support to read previous logic state or previous memory state achieved when a power domain transitions to RET. Instead there are module level context registers.
In order to support the powerdomain level logic/mem_off_counters on OMAP4, instead use the previous power state achieved (RET) and the *programmed* logic/mem RET state to derive if a powerdomain lost logic or did not.
Quoted 5 lines
If the powerdomain is programmed to enter RET state and lose logic in RET state, knowing that the powerdomain entered RET is good enough to derive that the logic was lost as well, in such cases.
Signed-off-by Tero Kristo <[email protected]>
This one was modified to remove this patch's dependency on the functional powerstate series and queued for 3.7. The modified patch follows.
- Paul
From: Tero Kristo <[email protected]>
Date: Thu, 19 Jul 2012 16:26:25 +0300
Subject: [PATCH] ARM: OMAP4: powerdomain: add support for reading prev logic
and mem states
On OMAP4, there is no support to read previous logic state or previous memory state achieved when a power domain transitions to RET. Instead there are module level context registers.
In order to support the powerdomain level logic/mem_off_counters on OMAP4, instead use the previous power state achieved (RET) and the *programmed* logic/mem RET state to derive if a powerdomain lost logic or did not.
If the powerdomain is programmed to enter RET state and lose logic in RET state, knowing that the powerdomain entered RET is good enough to derive that the logic was lost as well, in such cases.
[paul at pwsan.com: removed dependency on functional power state series for now;
bumped copyright date]
--- arch/arm/mach-omap2/powerdomain44xx.c | 61 ++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-)
arch/arm/mach-omap2/powerdomain44xx.c +60 -1
@@ -1,7 +1,7 @@/* * OMAP4 powerdomain control * -* Copyright (C) 2009-2010 Texas Instruments, Inc. +* Copyright (C) 2009-2010, 2012 Texas Instruments, Inc. * Copyright (C) 2007-2009 Nokia Corporation * * Derived from mach-omap2/powerdomain.c written by Paul Walmsley
@@ -151,6 +151,34 @@ static int omap4_pwrdm_read_logic_retst(struct powerdomain *pwrdm)return v; } +/** +* omap4_pwrdm_read_prev_logic_pwrst - read the previous logic powerstate +* @pwrdm: struct powerdomain * to read the state for +* +* Reads the previous logic powerstate for a powerdomain. This +* function must determine the previous logic powerstate by first +* checking the previous powerstate for the domain. If that was OFF, +* then logic has been lost. If previous state was RETENTION, the +* function reads the setting for the next retention logic state to +* see the actual value. In every other case, the logic is +* retained. Returns either PWRDM_POWER_OFF or PWRDM_POWER_RET +* depending whether the logic was retained or not. +*/ +static int omap4_pwrdm_read_prev_logic_pwrst (struct powerdomain *pwrdm) +{ +int state; + + state =omap4_pwrdm_read_prev_pwrst (pwrdm); + +if (state ==PWRDM_POWER_OFF ) +return PWRDM_POWER_OFF ; + +if (state !=PWRDM_POWER_RET ) +return PWRDM_POWER_RET ; + +return omap4_pwrdm_read_logic_retst (pwrdm); +} +static int omap4_pwrdm_read_mem_pwrst (struct powerdomain *pwrdm,u8 bank) {u32 m, v;
@@ -179,6 +207,35 @@ static int omap4_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)return v; } +/** +* omap4_pwrdm_read_prev_mem_pwrst - reads the previous memory powerstate +* @pwrdm: struct powerdomain * to read mem powerstate for +* @bank: memory bank index +* +* Reads the previous memory powerstate for a powerdomain. This +* function must determine the previous memory powerstate by first +* checking the previous powerstate for the domain. If that was OFF, +* then logic has been lost. If previous state was RETENTION, the +* function reads the setting for the next memory retention state to +* see the actual value. In every other case, the logic is +* retained. Returns either PWRDM_POWER_OFF or PWRDM_POWER_RET +* depending whether logic was retained or not. +*/ +static int omap4_pwrdm_read_prev_mem_pwrst (struct powerdomain *pwrdm,u8 bank) +{ +int state; + + state =omap4_pwrdm_read_prev_pwrst (pwrdm); + +if (state ==PWRDM_POWER_OFF ) +return PWRDM_POWER_OFF ; + +if (state !=PWRDM_POWER_RET ) +return PWRDM_POWER_RET ; + +return omap4_pwrdm_read_mem_retst (pwrdm, bank); +} +static int omap4_pwrdm_wait_transition (struct powerdomain *pwrdm) {u32 c =0 ;
@@ -217,9 +274,11 @@ struct pwrdm_ops omap4_pwrdm_operations = { .pwrdm_clear_all_prev_pwrst = omap4_pwrdm_clear_all_prev_pwrst, .pwrdm_set_logic_retst = omap4_pwrdm_set_logic_retst, .pwrdm_read_logic_pwrst = omap4_pwrdm_read_logic_pwrst, + .pwrdm_read_prev_logic_pwrst = omap4_pwrdm_read_prev_logic_pwrst, .pwrdm_read_logic_retst = omap4_pwrdm_read_logic_retst, .pwrdm_read_mem_pwrst = omap4_pwrdm_read_mem_pwrst, .pwrdm_read_mem_retst = omap4_pwrdm_read_mem_retst, + .pwrdm_read_prev_mem_pwrst = omap4_pwrdm_read_prev_mem_pwrst, .pwrdm_set_mem_onst = omap4_pwrdm_set_mem_onst, .pwrdm_set_mem_retst = omap4_pwrdm_set_mem_retst, .pwrdm_wait_transition = omap4_pwrdm_wait_transition,
Signature · 1 line
1.7.10.4
PATCH v7 6/12 ARM: OMAP4: suspend: Program all domains to retention
In reply to Tero KristoFrom: Rajendra Nayak <[email protected]>
Remove the FIXME's in the suspend sequence since we now intend to support system level RET support.
[Jean Pihet <[email protected]>: ported on top of the functional power states]
--- arch/arm/mach-omap2/pm44xx.c | 10 +++------- 1 files changed, 3 insertions(+), 7 deletions(-)
arch/arm/mach-omap2/pm44xx.c +3 -7
@@ -97,19 +97,15 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)if (!strncmp (pwrdm->name,"cpu" ,3 ))return 0 ; -/* -* FIXME: Remove this check when core retention is supported -* Only MPUSS power domain is added in the list. -*/ -if (strcmp (pwrdm->name,"mpu_pwrdm" )) -return 0 ; pwrst =kmalloc (sizeof (struct power_state ),GFP_ATOMIC );if (!pwrst)return -ENOMEM ; pwrst->pwrdm = pwrdm; - pwrst->next_state =PWRDM_FUNC_PWRST_CSWR ; + pwrst->next_state =pwrdm_get_achievable_func_pwrst ( + pwrdm, +PWRDM_FUNC_PWRST_CSWR );list_add (&pwrst->node, &pwrst_list);return omap_set_pwrdm_state (pwrst->pwrdm, pwrst->next_state);
Signature · 1 line
1.7.4.1
PATCH v7 6/12 ARM: OMAP4: suspend: Program all domains to retention
Hello.
Quoted 9 lines · Tero Kristo
From: Rajendra Nayak <[email protected]>
Remove the FIXME's in the suspend sequence since we now intend to support system level RET support.
Signed-off-by Rajendra Nayak <[email protected]>Signed-off-by Tero Kristo <[email protected]>[Jean Pihet <[email protected]>: ported on top of the functional power states]
Shouldn't Jean also have signed off?
Quoted 1 line
Reviewed-by Santosh Shilimkar <[email protected]>
WBR, Sergei
PATCH v7 6/12 ARM: OMAP4: suspend: Program all domains to retention
Hi!
Quoted 9 lines · Sergei Shtylyov
Hello.
Quoted 4 lines · Tero Kristo
From: Rajendra Nayak <[email protected]>
Remove the FIXME's in the suspend sequence since we now intend to support system level RET support.
Quoted 6 lines
Quoted 4 lines
Signed-off-by Rajendra Nayak <[email protected]>Signed-off-by Tero Kristo <[email protected]>[Jean Pihet <[email protected]>: ported on top of the functional power states]
Shouldn't Jean also have signed off?
Sure! I am OK with this change, feel free to add:
Regards,
Jean
Quoted 8 lines
Quoted 2 lines
Reviewed-by Santosh Shilimkar <[email protected]>WBR, Sergei
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH v7 6/12 ARM: OMAP4: suspend: Program all domains to retention
In reply to Tero KristoQuoted 10 lines · Tero Kristo
From: Rajendra Nayak <[email protected]>
Remove the FIXME's in the suspend sequence since we now intend to support system level RET support.
Signed-off-by Rajendra Nayak <[email protected]>Signed-off-by Tero Kristo <[email protected]>[Jean Pihet <[email protected]>: ported on top of the functional power states]
Reviewed-by Santosh Shilimkar <[email protected]>
Paul, go ahead and queue this one with the others.
Kevin
PATCH v7 7/12 ARM: OMAP4: PM: put all domains to OSWR during suspend
In reply to Tero Kristo--- arch/arm/mach-omap2/pm44xx.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
arch/arm/mach-omap2/pm44xx.c +1 -1
@@ -105,7 +105,7 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused) pwrst->pwrdm = pwrdm; pwrst->next_state =pwrdm_get_achievable_func_pwrst ( pwrdm, -PWRDM_FUNC_PWRST_CSWR ); +PWRDM_FUNC_PWRST_OSWR );list_add (&pwrst->node, &pwrst_list);return omap_set_pwrdm_state (pwrst->pwrdm, pwrst->next_state);
Signature · 1 line
1.7.4.1
Paul Walmsley
maintainerPATCH v7 7/12 ARM: OMAP4: PM: put all domains to OSWR during suspend
Quoted 1 line · Tero Kristo
Signed-off-by Tero Kristo <[email protected]>
This one needs at least some short description for the changelog. Maybe just a brief explanation that OSWR saves more energy that CSWR, but has higher resume latency, and since resume from system suspend is considered to be a high-latency operation, OSWR is appropriate here.
- Paul
PATCH v7 7/12 ARM: OMAP4: PM: put all domains to OSWR during suspend
Quoted 8 lines · Paul Walmsley
Quoted 1 line · Tero Kristo
Signed-off-by Tero Kristo <[email protected]>This one needs at least some short description for the changelog. Maybe just a brief explanation that OSWR saves more energy that CSWR, but has higher resume latency, and since resume from system suspend is considered to be a high-latency operation, OSWR is appropriate here.
Yea, I can add one. How about this:
Subject: [PATCHv7 07/12] ARM: OMAP4: PM: put all domains to OSWR during suspend
Currently OMAP4 suspend puts all power domains to CSWR. OSWR is a deeper state that saves more power, but has higher latencies also. As suspend is considered a high-latency operation, OSWR is appropriate here.
---
I'll update this to next rev if one is requested.
(Kind of hoping this set would be reaching maturity already.)
-Tero
Paul Walmsley
maintainerPATCH v7 7/12 ARM: OMAP4: PM: put all domains to OSWR during suspend
Hi
Quoted 11 lines · Tero Kristo
Subject: [PATCHv7 07/12] ARM: OMAP4: PM: put all domains to OSWR during suspend
Currently OMAP4 suspend puts all power domains to CSWR. OSWR is a deeper state that saves more power, but has higher latencies also. As suspend is considered a high-latency operation, OSWR is appropriate here.
Signed-off-by Tero Kristo <[email protected]>---
I'll update this to next rev if one is requested.
No need, I'll add it in the local copy here.
Quoted 1 line
(Kind of hoping this set would be reaching maturity already.)
It kind of looks to me like there are two or three separate sets within the series. My feeling is that Kevin should take the first two, then I should take the rest other than 6 and 7. Then once those are queued, we can pull in 6 and 7. Does that make sense to you?
- Paul
PATCH v7 7/12 ARM: OMAP4: PM: put all domains to OSWR during suspend
Quoted 11 lines · Paul Walmsley
Hi
Quoted 7 lines · Tero Kristo
Subject: [PATCHv7 07/12] ARM: OMAP4: PM: put all domains to OSWR during suspend
Currently OMAP4 suspend puts all power domains to CSWR. OSWR is a deeper state that saves more power, but has higher latencies also. As suspend is considered a high-latency operation, OSWR is appropriate here.
Quoted 6 lines
Quoted 4 lines
Signed-off-by Tero Kristo <[email protected]>---
I'll update this to next rev if one is requested.
No need, I'll add it in the local copy here.
Thanks, thats what I thought. :)
Quoted 7 lines
Quoted 2 lines
(Kind of hoping this set would be reaching maturity already.)
It kind of looks to me like there are two or three separate sets within the series. My feeling is that Kevin should take the first two, then I should take the rest other than 6 and 7. Then once those are queued, we can pull in 6 and 7. Does that make sense to you?
Yea, that looks good to me. Patches up from 6+ should only be pulled once the pre-reqs for this set are in also (io-chain + Jean's func pwrst stuff.) I haven't actually tried these patches without the pre-reqs lately, but I think they should be fine.
-Tero
PATCH v7 7/12 ARM: OMAP4: PM: put all domains to OSWR during suspend
In reply to Paul WalmsleyPaul Walmsley <[email protected]> writes:
[...]
Quoted 6 lines
It kind of looks to me like there are two or three separate sets within the series. My feeling is that Kevin should take the first two, then I should take the rest other than 6 and 7. Then once those are queued, we can pull in 6 and 7. Does that make sense to you?
Looks like 1, 2 & 7 are needed for OSWR, and the rest can go now via Paul.
Tero, can create a new OSWR series including 1, 2 & 7? Can you also refresh it against Jean's latest functional power state series (v6)?
Thanks,
Kevin
PATCH v7 7/12 ARM: OMAP4: PM: put all domains to OSWR during suspend
Quoted 11 lines · Kevin Hilman
Paul Walmsley <[email protected]> writes:
[...]
Quoted 6 lines
It kind of looks to me like there are two or three separate sets within the series. My feeling is that Kevin should take the first two, then I should take the rest other than 6 and 7. Then once those are queued, we can pull in 6 and 7. Does that make sense to you?
Quoted 5 lines
Looks like 1, 2 & 7 are needed for OSWR, and the rest can go now via Paul.
Tero, can create a new OSWR series including 1, 2 & 7? Can you also refresh it against Jean's latest functional power state series (v6)?
Yes, I already have these patches locally available. I'll just refresh them against Paul's minor tweaks on rest of the patches and re-post.
-Tero
PATCH v7 8/12 ARM: OMAP4430: PM: Work-around for ROM code BUG of PER pwrst ctrl
In reply to Tero KristoOn OMAP4430 HS / EMU chips, ROM code appears to re-configure L4PER domain next powerstate during wakeup from OSWR / OFF, programming it to ON. This will prevent successive entries to cpuidle retention / off, until kernel decices to change the L4PER target state, which can be delayed for a very long time as kernel is lazy programming the target state.
This patch fixes the issue within the low power OSWR / OFF mode code, so that this register is saved / restored across MPU OSWR / OFF state.
This problem seems to only occur with OMAP4430 HS/EMU, it does not impact OMAP4460+ or GP devices.
--- arch/arm/mach-omap2/omap-mpuss-lowpower.c | 39 ++++++++++++++++++++++++++++- arch/arm/mach-omap2/pm.h | 1 + arch/arm/mach-omap2/pm44xx.c | 10 +++++++ 3 files changed, 49 insertions(+), 1 deletions(-)
arch/arm/mach-omap2/omap-mpuss-lowpower.c +38 -1
@@ -52,6 +52,7 @@#include <plat/omap44xx.h> +#include "iomap.h" #include "common.h" #include "omap4-sar-layout.h" #include "pm.h"
@@ -97,6 +98,15 @@ static inline void set_cpu_next_pwrst(unsigned int cpu_id,omap_set_pwrdm_state (pm_info->pwrdm, power_state); } +struct reg_tuple { +void __iomem *addr; +u32 val; +}; + +static struct reg_tuple l4per_reg[] = { + {.addr =OMAP4430_PM_L4PER_PWRSTCTRL }, +}; +/* * Read CPU's previous power state */
@@ -215,6 +225,28 @@ static void save_l2x0_context(void) {}#endif +static inline void save_l4per_regs (void ) +{ +int i; + +if (!IS_PM44XX_ERRATUM (PM_OMAP4_ROM_L4PER_ERRATUM_PWSTCT )) +return ; + +for (i =0 ; i <ARRAY_SIZE (l4per_reg); i++) + l4per_reg[i].val =__raw_readl (l4per_reg[i].addr); +} + +static inline void restore_l4per_regs (void ) +{ +int i; + +if (!IS_PM44XX_ERRATUM (PM_OMAP4_ROM_L4PER_ERRATUM_PWSTCT )) +return ; + +for (i =0 ; i <ARRAY_SIZE (l4per_reg); i++) +__raw_writel (l4per_reg[i].val, l4per_reg[i].addr); +} +/** * omap4_enter_lowpower: OMAP4 MPUSS Low Power Entry Function * The purpose of this function is to manage low power programming
@@ -265,8 +297,10 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)* In MPUSS OSWR or device OFF, interrupt controller context is lost. */ mpuss_clear_prev_logic_pwrst (); -if (pwrdm_read_next_func_pwrst (mpuss_pd) ==PWRDM_FUNC_PWRST_OSWR ) +if (pwrdm_read_next_func_pwrst (mpuss_pd) ==PWRDM_FUNC_PWRST_OSWR ) { +save_l4per_regs (); save_state =2 ; + }cpu_clear_prev_logic_pwrst (cpu);set_cpu_next_pwrst (cpu, power_state);
@@ -289,6 +323,9 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) wakeup_cpu =smp_processor_id ();set_cpu_next_pwrst (wakeup_cpu,PWRDM_FUNC_PWRST_ON ); +if (omap4_mpuss_read_prev_context_state ()) +restore_l4per_regs (); +pwrdm_post_transition ();return 0 ;
arch/arm/mach-omap2/pm.h +1 -0
@@ -89,6 +89,7 @@ static inline void enable_omap3630_toggle_l2_on_restore(void) { }#endif /* defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) */ #define PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD (1 << 0) +#define PM_OMAP4_ROM_L4PER_ERRATUM_PWSTCT (1 << 1)#if defined(CONFIG_ARCH_OMAP4 )extern u16 pm44xx_errata;
arch/arm/mach-omap2/pm44xx.c +10 -0
@@ -194,6 +194,16 @@ int __init omap4_pm_init(void) (void )clkdm_for_each (omap_pm_clkdms_setup,NULL ); +/* +* ROM core appears to modify the L4PER powerstate control register +* during wakeup from OSWR / OFF, which will prevent further low +* power state transitions until the register is re-programmed. +* Thus, we must save / restore the register during idle. This +* seems to happen only on omap4430, on HS / EMU chips only. +*/ +if (cpu_is_omap443x () &&omap_type () !=OMAP2_DEVICE_TYPE_GP ) + pm44xx_errata |=PM_OMAP4_ROM_L4PER_ERRATUM_PWSTCT ; +#ifdef CONFIG_SUSPEND omap_pm_suspend = omap4_pm_suspend;#endif
Signature · 1 line
1.7.4.1
Paul Walmsley
maintainerPATCH v7 8/12 ARM: OMAP4430: PM: Work-around for ROM code BUG of PER pwrst ctrl
Hi
Quoted 23 lines · Tero Kristo
On OMAP4430 HS / EMU chips, ROM code appears to re-configure L4PER domain next powerstate during wakeup from OSWR / OFF, programming it to ON. This will prevent successive entries to cpuidle retention / off, until kernel decices to change the L4PER target state, which can be delayed for a very long time as kernel is lazy programming the target state.
This patch fixes the issue within the low power OSWR / OFF mode code, so that this register is saved / restored across MPU OSWR / OFF state.
This problem seems to only occur with OMAP4430 HS/EMU, it does not impact OMAP4460+ or GP devices.
Signed-off-by Tero Kristo <[email protected]>--- arch/arm/mach-omap2/omap-mpuss-lowpower.c | 39 ++++++++++++++++++++++++++++- arch/arm/mach-omap2/pm.h | 1 + arch/arm/mach-omap2/pm44xx.c | 10 +++++++ 3 files changed, 49 insertions(+), 1 deletions(-)arch/arm/mach-omap2/omap-mpuss-lowpower.c +0
-0
...
arch/arm/mach-omap2/omap-mpuss-lowpower.c static void save_l2x0_context(void) · line 236
Quoted 13 lines
arch/arm/mach-omap2/omap-mpuss-lowpower.c +9
-0@@ -215,6 +225,28 @@ static void save_l2x0_context(void) {}#endif +static inline void save_l4per_regs (void ) +{ +int i; + +if (!IS_PM44XX_ERRATUM (PM_OMAP4_ROM_L4PER_ERRATUM_PWSTCT )) +return ; + +for (i =0 ; i <ARRAY_SIZE (l4per_reg); i++) + l4per_reg[i].val =__raw_readl (l4per_reg[i].addr);
This is accessing the system PRM registers directly. We're trying to remove these raw register accesses from non-PRM code because a PRM driver is in the works. Please move this to prm44xx.c or prminst44xx.c and implement a higher-level interface that omap-mpuss-lowpower.c can call.
- Paul
PATCH v7 8/12 ARM: OMAP4430: PM: Work-around for ROM code BUG of PER pwrst ctrl
Quoted 34 lines · Paul Walmsley
Hi
Quoted 23 lines · Tero Kristo
On OMAP4430 HS / EMU chips, ROM code appears to re-configure L4PER domain next powerstate during wakeup from OSWR / OFF, programming it to ON. This will prevent successive entries to cpuidle retention / off, until kernel decices to change the L4PER target state, which can be delayed for a very long time as kernel is lazy programming the target state.
This patch fixes the issue within the low power OSWR / OFF mode code, so that this register is saved / restored across MPU OSWR / OFF state.
This problem seems to only occur with OMAP4430 HS/EMU, it does not impact OMAP4460+ or GP devices.
Signed-off-by Tero Kristo <[email protected]>--- arch/arm/mach-omap2/omap-mpuss-lowpower.c | 39 ++++++++++++++++++++++++++++- arch/arm/mach-omap2/pm.h | 1 + arch/arm/mach-omap2/pm44xx.c | 10 +++++++ 3 files changed, 49 insertions(+), 1 deletions(-)arch/arm/mach-omap2/omap-mpuss-lowpower.c +0
-0...
Quoted 4 lines
arch/arm/mach-omap2/omap-mpuss-lowpower.c +0
-0@@ -215,6 +225,28 @@ static void save_l2x0_context(void) {}#endif
Quoted 14 lines
arch/arm/mach-omap2/omap-mpuss-lowpower.c static void save_l2x0_context(void) · line 236
Quoted 9 lines
arch/arm/mach-omap2/omap-mpuss-lowpower.c +9
-0+static inline void save_l4per_regs (void ) +{ +int i; + +if (!IS_PM44XX_ERRATUM (PM_OMAP4_ROM_L4PER_ERRATUM_PWSTCT )) +return ; + +for (i =0 ; i <ARRAY_SIZE (l4per_reg); i++) + l4per_reg[i].val =__raw_readl (l4per_reg[i].addr);This is accessing the system PRM registers directly. We're trying to remove these raw register accesses from non-PRM code because a PRM driver is in the works. Please move this to
prm44xx.corprminst44xx.cand implement a higher-level interface thatomap-mpuss-lowpower.ccan call.
Ok, will figure out something for next rev.
-Tero
PATCH v7 8/12 ARM: OMAP4430: PM: Work-around for ROM code BUG of PER pwrst ctrl
In reply to Paul WalmsleyQuoted 34 lines · Paul Walmsley
Hi
Quoted 23 lines · Tero Kristo
On OMAP4430 HS / EMU chips, ROM code appears to re-configure L4PER domain next powerstate during wakeup from OSWR / OFF, programming it to ON. This will prevent successive entries to cpuidle retention / off, until kernel decices to change the L4PER target state, which can be delayed for a very long time as kernel is lazy programming the target state.
This patch fixes the issue within the low power OSWR / OFF mode code, so that this register is saved / restored across MPU OSWR / OFF state.
This problem seems to only occur with OMAP4430 HS/EMU, it does not impact OMAP4460+ or GP devices.
Signed-off-by Tero Kristo <[email protected]>--- arch/arm/mach-omap2/omap-mpuss-lowpower.c | 39 ++++++++++++++++++++++++++++- arch/arm/mach-omap2/pm.h | 1 + arch/arm/mach-omap2/pm44xx.c | 10 +++++++ 3 files changed, 49 insertions(+), 1 deletions(-)arch/arm/mach-omap2/omap-mpuss-lowpower.c +0
-0...
Quoted 4 lines
arch/arm/mach-omap2/omap-mpuss-lowpower.c +0
-0@@ -215,6 +225,28 @@ static void save_l2x0_context(void) {}#endif
Quoted 14 lines
arch/arm/mach-omap2/omap-mpuss-lowpower.c static void save_l2x0_context(void) · line 236
Quoted 9 lines
arch/arm/mach-omap2/omap-mpuss-lowpower.c +9
-0+static inline void save_l4per_regs (void ) +{ +int i; + +if (!IS_PM44XX_ERRATUM (PM_OMAP4_ROM_L4PER_ERRATUM_PWSTCT )) +return ; + +for (i =0 ; i <ARRAY_SIZE (l4per_reg); i++) + l4per_reg[i].val =__raw_readl (l4per_reg[i].addr);This is accessing the system PRM registers directly. We're trying to remove these raw register accesses from non-PRM code because a PRM driver is in the works. Please move this to
prm44xx.corprminst44xx.cand implement a higher-level interface thatomap-mpuss-lowpower.ccan call.
It looks like this can be dropped out for now completely, I guess I had a broken PPA on my board which was causing this problem.
-Tero
PATCH v7 9/12 ARM: OMAP4: hwmod data: temporarily comment out data for the sl2if IP block
In reply to Tero KristoThe OMAP4 sl2if IP block requires some special programming for it to enter idle. Without this programming, they will prevent the rest of the chip from entering full chip idle.
This patch comments out the IP block data.
Later, once the appropriate support is available, this patch can be reverted.
--- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-)
arch/arm/mach-omap2/omap_hwmod_44xx_data.c +6 -6
@@ -4266,7 +4266,7 @@ static struct omap_hwmod_ocp_if omap44xx_dsp__iva = { };/* dsp -> sl2if */ -static struct omap_hwmod_ocp_if omap44xx_dsp__sl2if = { +static struct omap_hwmod_ocp_if __maybe_unused omap44xx_dsp__sl2if = { .master = &omap44xx_dsp_hwmod, .slave = &omap44xx_sl2if_hwmod, .clk ="dpll_iva_m5x2_ck" ,
@@ -4884,7 +4884,7 @@ static struct omap_hwmod_ocp_if omap44xx_l3_main_2__iss = { };/* iva -> sl2if */ -static struct omap_hwmod_ocp_if omap44xx_iva__sl2if = { +static struct omap_hwmod_ocp_if __maybe_unused omap44xx_iva__sl2if = { .master = &omap44xx_iva_hwmod, .slave = &omap44xx_sl2if_hwmod, .clk ="dpll_iva_m5x2_ck" ,
@@ -5418,7 +5418,7 @@ static struct omap_hwmod_ocp_if omap44xx_l4_wkup__scrm = { };/* l3_main_2 -> sl2if */ -static struct omap_hwmod_ocp_if omap44xx_l3_main_2__sl2if = { +static struct omap_hwmod_ocp_if __maybe_unused omap44xx_l3_main_2__sl2if = { .master = &omap44xx_l3_main_2_hwmod, .slave = &omap44xx_sl2if_hwmod, .clk ="l3_div_ck" ,
@@ -6088,7 +6088,7 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = { &omap44xx_l4_abe__dmic, &omap44xx_l4_abe__dmic_dma, &omap44xx_dsp__iva, - &omap44xx_dsp__sl2if, +/* &omap44xx_dsp__sl2if, */ &omap44xx_l4_cfg__dsp, &omap44xx_l3_main_2__dss, &omap44xx_l4_per__dss,
@@ -6124,7 +6124,7 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = { &omap44xx_l4_per__i2c4, &omap44xx_l3_main_2__ipu, &omap44xx_l3_main_2__iss, - &omap44xx_iva__sl2if, +/* &omap44xx_iva__sl2if, */ &omap44xx_l3_main_2__iva, &omap44xx_l4_wkup__kbd, &omap44xx_l4_cfg__mailbox,
@@ -6155,7 +6155,7 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = { &omap44xx_l4_cfg__cm_core, &omap44xx_l4_wkup__prm, &omap44xx_l4_wkup__scrm, - &omap44xx_l3_main_2__sl2if, +/* &omap44xx_l3_main_2__sl2if, */ &omap44xx_l4_abe__slimbus1, &omap44xx_l4_abe__slimbus1_dma, &omap44xx_l4_per__slimbus2,
Signature · 1 line
1.7.4.1
Paul Walmsley
maintainerPATCH v7 9/12 ARM: OMAP4: hwmod data: temporarily comment out data for the sl2if IP block
Hi Tero
Quoted 4 lines · Tero Kristo
The OMAP4 sl2if IP block requires some special programming for it to enter idle. Without this programming, they will prevent the rest of the chip from entering full chip idle.
Quoted 8 lines
This patch comments out the IP block data.
Later, once the appropriate support is available, this patch can be reverted.
Cc Paul Walmsley <[email protected]>Cc Beno?t Cousson <[email protected]>Signed-off-by Tero Kristo <[email protected]>
Originally I was hoping that we could apply a real fix for this one. But looking at the proposed alternative in the old SL2IF E-mail threads, I'm still not convinced by what's proposed there. So we'd better take this one for the time being.
Queued for 3.6-rc.
- Paul
PATCH v7 10/12 ARM: OMAP4: HWMOD: add support for lostcontext_mask
In reply to Tero KristoCurrently hwmod only provides the offset for the context lose register, and if we attempt to share the same register between two or more hwmods, the resulting context loss counts get wrong. Thus, we need a way to specify which bits are used for the context loss information for each. This is accomplished by adding a new field to the omap4 prcm struct, 'lostcontext_mask', which specifies a bit-mask to use for filtering the register. Only the specified bits are read and cleared by the context lose counter update code. If a hwmod doesn't specify 'lostcontext_mask' (default behavior), the whole contents of the context register are used without any filtering.
--- arch/arm/mach-omap2/omap_hwmod.c | 8 ++++++++ arch/arm/plat-omap/include/plat/omap_hwmod.h | 6 ++++++ 2 files changed, 14 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/omap_hwmod.c +8 -0
@@ -1810,11 +1810,19 @@ static void _omap4_update_context_lost(struct omap_hwmod *oh) oh->clkdm->pwrdm.ptr->prcm_offs, oh->prcm.omap4.context_offs); +/* +* If lostcontext_mask is defined, only check these bits for +* losing context. Otherwise check whole register. +*/ +if (oh->prcm.omap4.lostcontext_mask) + r &= oh->prcm.omap4.lostcontext_mask; +if (!r)return ; oh->prcm.omap4.context_lost_counter++; +/* Clear selected bits */ omap4_prminst_write_inst_reg (r, oh->clkdm->pwrdm.ptr->prcm_partition, oh->clkdm->pwrdm.ptr->prcm_offs, oh->prcm.omap4.context_offs);
arch/arm/plat-omap/include/plat/omap_hwmod.h +6 -0
@@ -375,14 +375,20 @@ struct omap_hwmod_omap2_prcm {* @clkctrl_offs: offset of the PRCM clock control register * @rstctrl_offs: offset of the XXX_RSTCTRL register located in the PRM * @context_offs: offset of the RM_*_CONTEXT register +* @lostcontext_mask: bitmask for selecting bits from RM_*_CONTEXT register * @submodule_wkdep_bit: bit shift of the WKDEP range * @modulemode: allowable modulemodes * @context_lost_counter: Count of module level context lost +* +* If @lostcontext_mask is not defined, context loss check code uses +* whole register without masking. @lostcontext_mask should only be defined +* in cases where @context_offs register is shared by two or more hwmods. */ struct omap_hwmod_omap4_prcm {u16 clkctrl_offs;u16 rstctrl_offs;u16 context_offs; +u32 lostcontext_mask;u8 submodule_wkdep_bit;u8 modulemode;unsigned context_lost_counter;
Signature · 1 line
1.7.4.1
Paul Walmsley
maintainerPATCH v7 10/12 ARM: OMAP4: HWMOD: add support for lostcontext_mask
Quoted 11 lines · Tero Kristo
Currently hwmod only provides the offset for the context lose register, and if we attempt to share the same register between two or more hwmods, the resulting context loss counts get wrong. Thus, we need a way to specify which bits are used for the context loss information for each. This is accomplished by adding a new field to the omap4 prcm struct, '
lostcontext_mask', which specifies a bit-mask to use for filtering the register. Only the specified bits are read and cleared by the context lose counter update code. If a hwmod doesn't specify 'lostcontext_mask' (default behavior), the whole contents of the context register are used without any filtering.
Quoted 1 line
Signed-off-by Tero Kristo <[email protected]>
Thanks, queued for 3.7.
- Paul
PATCH v7 11/12 ARM: OMAP4: hwmod_data: add context lose information for l4_abe hwmod
In reply to Tero Kristo'l4_abe' hwmod uses the LOSTMEM_AESSMEM bit of RM_ABE_AESS_CONTEXT register, as l4_abe doesn't have its own dedicated register for this purpose. This register is shared with 'aess' hwmod, thus both hwmods must also specify which bits of the register are used for them.
--- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
arch/arm/mach-omap2/omap_hwmod_44xx_data.c +3 -1
@@ -204,7 +204,8 @@ static struct omap_hwmod omap44xx_l4_abe_hwmod = { .prcm = { .omap4 = { .clkctrl_offs = OMAP4_CM1_ABE_L4ABE_CLKCTRL_OFFSET, - .context_offs = USHRT_MAX, + .context_offs = OMAP4_RM_ABE_AESS_CONTEXT_OFFSET, + .lostcontext_mask = OMAP4430_LOSTMEM_AESSMEM_MASK, }, }, };
@@ -350,6 +351,7 @@ static struct omap_hwmod omap44xx_aess_hwmod = { .omap4 = { .clkctrl_offs = OMAP4_CM1_ABE_AESS_CLKCTRL_OFFSET, .context_offs = OMAP4_RM_ABE_AESS_CONTEXT_OFFSET, + .lostcontext_mask = OMAP4430_LOSTCONTEXT_DFF_MASK, .modulemode = MODULEMODE_SWCTRL, }, },
Signature · 1 line
1.7.4.1
PATCH v7 12/12 ARM: OMAP4: hwmod: update context lost counter logic for hwmods without context reg
In reply to Tero KristoWith this patch, the hwmods that don't have context register, will now increment their context lost counter always unless they belong to an always on powerdomain which never loses context. The always on pwrdm type is checked by looking at the the powerdomain registered for the hwmod, and seeing if it only has ON within its valid powerstates.
--- arch/arm/mach-omap2/omap_hwmod.c | 21 ++++++++++++++++++++- 1 files changed, 20 insertions(+), 1 deletions(-)
arch/arm/mach-omap2/omap_hwmod.c +20 -1
@@ -1802,9 +1802,28 @@ static void _reconfigure_io_chain(void)static void _omap4_update_context_lost (struct omap_hwmod *oh) {u32 r; +struct powerdomain *pwrdm; + +/* Special handling if we have not defined context register */ +if (oh->prcm.omap4.context_offs ==USHRT_MAX ) { +/* Get powerdomain pointer for this hwmod */ +if (oh->clkdm) + pwrdm = oh->clkdm->pwrdm.ptr; +else + pwrdm =NULL ; -if (oh->prcm.omap4.context_offs ==USHRT_MAX ) +/* +* If our powerdomain is of 'always on' type (i.e. +* available powerstates == PWRSTS_ON), don't increment +* context lost and return +*/ +if (pwrdm && pwrdm->pwrsts ==PWRSTS_ON ) +return ; + +/* Otherwise, increase context lost counter and return */ + oh->prcm.omap4.context_lost_counter++;return ; + } r = omap4_prminst_read_inst_reg(oh->clkdm->pwrdm.ptr->prcm_partition, oh->clkdm->pwrdm.ptr->prcm_offs,
Signature · 1 line
1.7.4.1