* [PATCH 00/17] omap4: pm: suspend, hotplug and cpuilde support
@ 2011-02-19 10:42 Santosh Shilimkar
2011-02-19 10:42 ` [PATCH 01/17] omap4: pm: Add omap WakeupGen module support Santosh Shilimkar
` (17 more replies)
0 siblings, 18 replies; 55+ messages in thread
From: Santosh Shilimkar @ 2011-02-19 10:42 UTC (permalink / raw)
To: linux-arm-kernel
This series adds OMAP4 suspend and cpuidle support till MPU subsystem
(MPUSS) off-mode. The suspend on SMP machines uses cpu-hotplug
infrastructure to take down the non-boot CPUs. We put secondary
CPU(CPU1 in OMAP4) to OFF state via cpu-hotplug.
In cpuidle too, low power states are attempted only when the
CPU1 is put to OFF state via cpu-hotplug because of hardware
constraints.
Timer wakeup from suspend, debug pm counters and enable_off_mode
provisions are supported as well.
Special thanks to Kevin Hilman <khilman@ti.com> for doing detail
off-the list reviews.
The patches are generated against mainline 2.6.38-rc5 and tested with
OMAP4430 SDP and OMAP4 PANDA board. Any OMAP4 board with ES2.X silicon,
below features should work with this series. On ES1.0, these PM
features are not supported.
1. CPU hotplug (CPU is put into off-mode)
2. Suspend (Both CPUs put to off-mode and MPUSS to OFF/RET)
3. CPUILDE with below C-states.
C1 - CPU0 ON + CPU1 ON/OFF + MPU ON + CORE ON
C2 - CPU0 ON + CPU1 OFF + MPU ON + CORE ON
C3 - CPU0 OFF + CPU1 OFF + MPU CSWR + CORE ON
C4 - CPU0 OFF + CPU1 OFF + MPU OFF + CORE ON
In OMAP4 mpuss consist of dual Cortex-A9 with per-cpu local timers
GIC(Generic Interrupt Controller), SCU(Snoop Control Unit) and PL310
L2 cache controller and CPU0/CPU1 LPRM modules.
CPU0, CPU1 and MPUSS have there own power domain and hence multiple
low power state combinations are possible. The CPU10 and CPU1
Close switch Retention(CSWR) isn't supported by hardware.
Based on various studies, measurements, hardware constraints
and recommendations from hardware team, only below low power
modes are supported on OMAP4.
----------------------------------------
CPU0 CPU1 MPUSS
----------------------------------------
ON ON ON
OFF OFF CSWR
OFF OFF OSWR
OFF OFF OFF
-----------------------------------------
Note: CPU0 is the master core and it is the last CPU to go down
and first to wake-up when MPUSS low power states are attempted
OSWR(Open Switch Retention) is not added as part of this series
because it needs some power domain level support which isn't ready
yet.
http://www.mail-archive.com/linux-omap at vger.kernel.org/msg38667.html
Powerdomain INACTIVE support is also dropped because of its
inconsistency between OMAP4 and OMAP3.
More information on this thread -
http://www.spinics.net/lists/linux-omap/msg45370.html
This series has a dependency on few patches from below series which
are posted earlier.
- Clock domain split series [1] (Already in Paul's queue)
- Few power domain patches from [2] (Already in Paul's queue)
- GIC and SCU patches from [3]
- Local Timer patches from [4]
The cpu-hotplug and suspend works with omap2plus_defconfig. Not to damage
your file system with current omap2plus_defconfig, disable ARCH_OMAP2 so
that V6 and V7 support is not built together with SMP.
To tryout cpuidle, CONFIG_CPU_IDLE needs to be enabled in the build.
CPU-HOTPLUG commands :
offline : $echo 0 > /sys/devices/system/cpu/cpu1/online
online : $echo 1 > /sys/devices/system/cpu/cpu1/online
Suspend :$echo mem > /sys/power/state
cpuilde : To trigger cpuidle deeper C-states on OMAP4, CPU1 needs
to be offlied
$echo 0 > /sys/devices/system/cpu/cpu1/online
To see PM debug counters,
$mount -t debugfs debugfs /proc/sys/debug/
$cat /proc/sys/debug/pm_debug/count
off-mode debugfs control:
enable: $echo 1 > /proc/sys/debug/pm_debug/enable_off_mode
disable: $echo 0 > /proc/sys/debug/pm_debug/enable_off_mode
For testing, I have put together all these patches and dependencies
on below git branch.
git://dev.omapzoom.org/pub/scm/santosh/kernel-omap4-base.git omap4_pm_fornext
Rajendra Nayak (1):
omap4: cpuidle: Basic CPUidle support
Santosh Shilimkar (16):
omap4: pm: Add omap WakeupGen module support
omap4: pm: Add SAR RAM support
omap4: Export scu base address
omap4: pm: Add CPUx OFF mode support
omap4: pm: Initialise all the clockdomains to supported states
omap4: pm: Program CPU1 to hit OFF when off-lined
omap4: pm: CPU1 wakeup workaround form Low power modes
omap4: pm: Add GIC save/restore support
omap4: pm: Add WakeupGen save/restore support
omap4: pm: Add L2 cache lowpower support
omap4: suspend: Add MPUSS RET and OFF support
omap4: pm-debug: Add wakeup timer and debug counters
omap4: cpuidle: Add MPUSS RET OFF states
omap4: cpuidle: Switch to gptimer from twd in deeper C-states.
omap4: cpuidle: Allow debugfs control through enable_off_mode
omap4: Remove un-used do_wfi() macro.
arch/arm/mach-omap2/Makefile | 8 +-
arch/arm/mach-omap2/cpuidle44xx.c | 365 +++++++++++++++++
arch/arm/mach-omap2/include/mach/omap-wakeupgen.h | 41 ++
arch/arm/mach-omap2/include/mach/omap4-common.h | 56 +++-
arch/arm/mach-omap2/omap-hotplug.c | 31 ++-
arch/arm/mach-omap2/omap-smp.c | 29 ++-
arch/arm/mach-omap2/omap-wakeupgen.c | 287 +++++++++++++
arch/arm/mach-omap2/omap4-common.c | 28 ++-
arch/arm/mach-omap2/omap4-mpuss-lowpower.c | 442 +++++++++++++++++++++
arch/arm/mach-omap2/omap4-sar-layout.h | 71 ++++
arch/arm/mach-omap2/pm-debug.c | 8 +-
arch/arm/mach-omap2/pm.h | 3 +
arch/arm/mach-omap2/pm44xx.c | 125 ++++++-
arch/arm/mach-omap2/sleep44xx.S | 398 +++++++++++++++++++
arch/arm/plat-omap/include/plat/omap44xx.h | 1 +
15 files changed, 1870 insertions(+), 23 deletions(-)
create mode 100644 arch/arm/mach-omap2/cpuidle44xx.c
create mode 100644 arch/arm/mach-omap2/include/mach/omap-wakeupgen.h
create mode 100644 arch/arm/mach-omap2/omap-wakeupgen.c
create mode 100644 arch/arm/mach-omap2/omap4-mpuss-lowpower.c
create mode 100644 arch/arm/mach-omap2/omap4-sar-layout.h
create mode 100644 arch/arm/mach-omap2/sleep44xx.S
Regrads,
Santosh
[1] http://www.spinics.net/lists/linux-omap/msg44153.html
[2] http://www.mail-archive.com/linux-omap at vger.kernel.org/msg43257.html
[3] http://www.mail-archive.com/linux-omap at vger.kernel.org/msg42939.html
[4] http://www.spinics.net/lists/linux-omap/msg45710.html
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 01/17] omap4: pm: Add omap WakeupGen module support
2011-02-19 10:42 [PATCH 00/17] omap4: pm: suspend, hotplug and cpuilde support Santosh Shilimkar
@ 2011-02-19 10:42 ` Santosh Shilimkar
2011-03-02 21:47 ` Kevin Hilman
2011-02-19 10:42 ` [PATCH 02/17] omap4: pm: Add SAR RAM support Santosh Shilimkar
` (16 subsequent siblings)
17 siblings, 1 reply; 55+ messages in thread
From: Santosh Shilimkar @ 2011-02-19 10:42 UTC (permalink / raw)
To: linux-arm-kernel
This patch adds OMAP WakeupGen support. The WakeupGen unit is responsible
for generating wakeup event from the incoming interrupts and enable bits.
The WakeupGen is implemented in MPU Always-On power domain. During normal
operation, WakeupGen delivers external interrupts directly to the GIC.
When the CPUx asserts StandbyWFI, indicating it wants to enter lowpower
state, the Standby Controller checks with the WakeupGen unit using the
idlereq/idleack handshake to make sure there is no incoming interrupts.
The GIC and WakeupGen needs to be kept in synchronisation for proper
interrupt functioning.
Hence this patch hooks up the omap WakeupGen mask/unmask along with GIC using
architecture specific hooks.
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
---
arch/arm/mach-omap2/Makefile | 3 +-
arch/arm/mach-omap2/include/mach/omap-wakeupgen.h | 40 ++++
arch/arm/mach-omap2/omap-wakeupgen.c | 213 +++++++++++++++++++++
arch/arm/mach-omap2/omap4-common.c | 3 +
4 files changed, 258 insertions(+), 1 deletions(-)
create mode 100644 arch/arm/mach-omap2/include/mach/omap-wakeupgen.h
create mode 100644 arch/arm/mach-omap2/omap-wakeupgen.c
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 72f2891..54ff219 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -24,7 +24,8 @@ obj-$(CONFIG_TWL4030_CORE) += omap_twl.o
obj-$(CONFIG_SMP) += omap-smp.o omap-headsmp.o
obj-$(CONFIG_LOCAL_TIMERS) += timer-mpu.o
obj-$(CONFIG_HOTPLUG_CPU) += omap-hotplug.o
-obj-$(CONFIG_ARCH_OMAP4) += omap44xx-smc.o omap4-common.o
+obj-$(CONFIG_ARCH_OMAP4) += omap44xx-smc.o omap4-common.o \
+ omap-wakeupgen.o
plus_sec := $(call as-instr,.arch_extension sec,+sec)
AFLAGS_omap-headsmp.o :=-Wa,-march=armv7-a$(plus_sec)
diff --git a/arch/arm/mach-omap2/include/mach/omap-wakeupgen.h b/arch/arm/mach-omap2/include/mach/omap-wakeupgen.h
new file mode 100644
index 0000000..f10d106
--- /dev/null
+++ b/arch/arm/mach-omap2/include/mach/omap-wakeupgen.h
@@ -0,0 +1,40 @@
+/*
+ * OMAP WakeupGen header file
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Written by Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef OMAP_ARCH_WAKEUPGEN_H
+#define OMAP_ARCH_WAKEUPGEN_H
+
+#define OMAP_WKG_CONTROL_0 0x00
+#define OMAP_WKG_ENB_A_0 0x10
+#define OMAP_WKG_ENB_B_0 0x14
+#define OMAP_WKG_ENB_C_0 0x18
+#define OMAP_WKG_ENB_D_0 0x1c
+#define OMAP_WKG_ENB_SECURE_A_0 0x20
+#define OMAP_WKG_ENB_SECURE_B_0 0x24
+#define OMAP_WKG_ENB_SECURE_C_0 0x28
+#define OMAP_WKG_ENB_SECURE_D_0 0x2c
+#define OMAP_WKG_ENB_A_1 0x410
+#define OMAP_WKG_ENB_B_1 0x414
+#define OMAP_WKG_ENB_C_1 0x418
+#define OMAP_WKG_ENB_D_1 0x41c
+#define OMAP_WKG_ENB_SECURE_A_1 0x420
+#define OMAP_WKG_ENB_SECURE_B_1 0x424
+#define OMAP_WKG_ENB_SECURE_C_1 0x428
+#define OMAP_WKG_ENB_SECURE_D_1 0x42c
+#define OMAP_AUX_CORE_BOOT_0 0x800
+#define OMAP_AUX_CORE_BOOT_1 0x804
+#define OMAP_PTMSYNCREQ_MASK 0xc00
+#define OMAP_PTMSYNCREQ_EN 0xc04
+#define OMAP_TIMESTAMPCYCLELO 0xc08
+#define OMAP_TIMESTAMPCYCLEHI 0xc0c
+
+extern int __init omap_wakeupgen_init(void);
+extern void omap_wakeupgen_irqmask_all(unsigned int cpu, unsigned int set);
+#endif
diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c
new file mode 100644
index 0000000..e26a0ed
--- /dev/null
+++ b/arch/arm/mach-omap2/omap-wakeupgen.c
@@ -0,0 +1,213 @@
+/*
+ * OMAP WakeupGen Source file
+ *
+ * The WakeupGen unit is responsible for generating wakeup event from the
+ * incoming interrupts and enable bits. The WakeupGen is implemented in MPU
+ * always-On power domain. The WakeupGen consists of two sub-units, one for
+ * each CPU and manages only SPI interrupts. Hardware requirements is that
+ * the GIC and WakeupGen should be kept in sync for proper operation.
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Written by Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware/gic.h>
+
+#include <mach/omap-wakeupgen.h>
+
+#define NR_BANKS 4
+#define MAX_IRQS 128
+#define WKG_MASK_ALL 0x00000000
+#define WKG_UNMASK_ALL 0xffffffff
+#define CPU_ENA_OFFSET 0x400
+#define CPU0_ID 0x0
+#define CPU1_ID 0x1
+
+/* WakeupGen Base addres */
+static void __iomem *wakeupgen_base;
+static DEFINE_PER_CPU(u32 [NR_BANKS], irqmasks);
+static DEFINE_SPINLOCK(wakeupgen_lock);
+
+/*
+ * Static helper functions
+ */
+
+static inline u32 cpu_readl(u8 idx, u32 cpu)
+{
+ return __raw_readl(wakeupgen_base + OMAP_WKG_ENB_A_0 +
+ (cpu * CPU_ENA_OFFSET) + (idx * 4));
+}
+
+static inline void cpu_writel(u32 val, u8 idx, u32 cpu)
+{
+ __raw_writel(val, wakeupgen_base + OMAP_WKG_ENB_A_0 +
+ (cpu * CPU_ENA_OFFSET) + (idx * 4));
+}
+
+static void _wakeupgen_set_all(unsigned int cpu, unsigned int reg)
+{
+ u8 i;
+
+ for (i = 0; i < NR_BANKS; i++)
+ cpu_writel(reg, i, cpu);
+}
+
+static void _wakeupgen_set(unsigned int irq, unsigned int set)
+{
+ unsigned int val, spi_irq;
+ unsigned int cpu = smp_processor_id();
+ u8 i;
+
+ /*
+ * PPIs and SGIs are not supported
+ */
+ if (irq < OMAP44XX_IRQ_GIC_START)
+ return;
+
+ /*
+ * Subtract the GIC offset
+ */
+ spi_irq = irq - OMAP44XX_IRQ_GIC_START;
+ if (spi_irq > MAX_IRQS) {
+ pr_err("omap wakeupGen: Invalid IRQ%d\n", irq);
+ return ;
+ }
+
+ /*
+ * Each wakeup gen register controls 32
+ * interrupts. i.e 1 bit per SPI IRQ
+ */
+ i = spi_irq >> 5;
+ spi_irq %= 32;
+
+ val = cpu_readl(i, cpu);
+ if (set)
+ val |= BIT(spi_irq);
+ else
+ val &= ~BIT(spi_irq);
+ cpu_writel(val, i, cpu);
+}
+
+static void _wakeupgen_save_masks(unsigned int cpu)
+{
+ u8 i;
+
+ for (i = 0; i < NR_BANKS; i++)
+ per_cpu(irqmasks, cpu)[i] = cpu_readl(i, cpu);
+}
+
+static void _wakeupgen_restore_masks(unsigned int cpu)
+{
+ u8 i;
+
+ for (i = 0; i < NR_BANKS; i++)
+ cpu_writel(per_cpu(irqmasks, cpu)[i], i, cpu);
+}
+
+/*
+ * Architecture specific Mask extensiom
+ */
+static void wakeupgen_mask(struct irq_data *d)
+{
+ spin_lock(&wakeupgen_lock);
+ _wakeupgen_set(d->irq, 0);
+ spin_unlock(&wakeupgen_lock);
+}
+
+/*
+ * Architecture specific Unmask extensiom
+ */
+static void wakeupgen_unmask(struct irq_data *d)
+{
+
+ spin_lock(&wakeupgen_lock);
+ _wakeupgen_set(d->irq, 1);
+ spin_unlock(&wakeupgen_lock);
+}
+
+#ifdef CONFIG_PM
+/*
+ * Architecture specific set_wake extension
+ */
+static int wakeupgen_set_wake(struct irq_data *d, unsigned int on)
+{
+ spin_lock(&wakeupgen_lock);
+ _wakeupgen_set(d->irq, on);
+ spin_unlock(&wakeupgen_lock);
+
+ return 0;
+}
+
+#else
+#define wakeupgen_set_wake NULL
+#endif
+
+/**
+ * omap_wakeupgen_irqmask_all() - Mask or unmask interrupts
+ * @cpu - CPU ID
+ * @set - The IRQ register mask.
+ * 0 = Mask all interrupts on the 'cpu'
+ * 1 = Unmask all interrupts on the 'cpu'
+ *
+ * Ensure that the initial mask is maintained. This is faster than
+ * iterating through GIC rgeisters to arrive at the correct masks
+ */
+void omap_wakeupgen_irqmask_all(unsigned int cpu, unsigned int set)
+{
+ if (omap_rev() == OMAP4430_REV_ES1_0)
+ return;
+
+ spin_lock(&wakeupgen_lock);
+ if (set) {
+ _wakeupgen_save_masks(cpu);
+ _wakeupgen_set_all(cpu, WKG_MASK_ALL);
+ } else {
+ _wakeupgen_set_all(cpu, WKG_UNMASK_ALL);
+ _wakeupgen_restore_masks(cpu);
+ }
+ spin_unlock(&wakeupgen_lock);
+}
+
+/*
+ * Initialse the wakeupgen module
+ */
+int __init omap_wakeupgen_init(void)
+{
+ u8 i;
+
+ /* Not supported on on OMAP4 ES1.0 silicon */
+ if (omap_rev() == OMAP4430_REV_ES1_0) {
+ WARN(1, "WakeupGen: Not supported on OMAP4430 ES1.0\n");
+ return -EPERM;
+ }
+
+ /* Static mapping, never released */
+ wakeupgen_base = ioremap(OMAP44XX_WKUPGEN_BASE, SZ_4K);
+ BUG_ON(!wakeupgen_base);
+
+ /* Clear all IRQ bitmasks at wakeupGen level */
+ for (i = 0; i < NR_BANKS; i++) {
+ cpu_writel(0, i, CPU0_ID);
+ cpu_writel(0, i, CPU1_ID);
+ }
+
+ /*
+ * Override gic architecture specific fucntioms to add
+ * OMAP WakeupGen interrupt controller along with GIC
+ */
+ gic_arch_extn.irq_mask = wakeupgen_mask;
+ gic_arch_extn.irq_unmask = wakeupgen_unmask;
+ gic_arch_extn.irq_set_wake = wakeupgen_set_wake;
+
+ return 0;
+}
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
index 1926864..559d227 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -21,6 +21,7 @@
#include <mach/hardware.h>
#include <mach/omap4-common.h>
+#include <mach/omap-wakeupgen.h>
#ifdef CONFIG_CACHE_L2X0
void __iomem *l2cache_base;
@@ -41,6 +42,8 @@ void __init gic_init_irq(void)
gic_cpu_base = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_512);
BUG_ON(!gic_cpu_base);
+ omap_wakeupgen_init();
+
gic_init(0, 29, gic_dist_base_addr, gic_cpu_base);
}
--
1.6.0.4
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 02/17] omap4: pm: Add SAR RAM support
2011-02-19 10:42 [PATCH 00/17] omap4: pm: suspend, hotplug and cpuilde support Santosh Shilimkar
2011-02-19 10:42 ` [PATCH 01/17] omap4: pm: Add omap WakeupGen module support Santosh Shilimkar
@ 2011-02-19 10:42 ` Santosh Shilimkar
2011-03-02 21:56 ` Kevin Hilman
2011-02-19 10:42 ` [PATCH 03/17] omap4: Export scu base address Santosh Shilimkar
` (15 subsequent siblings)
17 siblings, 1 reply; 55+ messages in thread
From: Santosh Shilimkar @ 2011-02-19 10:42 UTC (permalink / raw)
To: linux-arm-kernel
This patch adds SAR RAM support on OMAP4430. SAR RAM used to save
and restore the HW context in low power modes.
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
---
arch/arm/mach-omap2/omap4-common.c | 25 ++++++++++++++++++++++++-
arch/arm/mach-omap2/omap4-sar-layout.h | 24 ++++++++++++++++++++++++
arch/arm/plat-omap/include/plat/omap44xx.h | 1 +
3 files changed, 49 insertions(+), 1 deletions(-)
create mode 100644 arch/arm/mach-omap2/omap4-sar-layout.h
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
index 559d227..48484a5 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -23,12 +23,14 @@
#include <mach/omap4-common.h>
#include <mach/omap-wakeupgen.h>
+#include "omap4-sar-layout.h"
+
#ifdef CONFIG_CACHE_L2X0
void __iomem *l2cache_base;
#endif
void __iomem *gic_dist_base_addr;
-
+void __iomem *sar_ram_base;
void __init gic_init_irq(void)
{
@@ -107,3 +109,24 @@ static int __init omap_l2_cache_init(void)
}
early_initcall(omap_l2_cache_init);
#endif
+
+/*
+ * SAR RAM used to save and restore the HW
+ * context in low power modes
+ */
+static int __init omap4_sar_ram_init(void)
+{
+ /*
+ * To avoid code running on other OMAPs in
+ * multi-omap builds
+ */
+ if (!cpu_is_omap44xx())
+ return -ENODEV;
+
+ /* Static mapping, never released */
+ sar_ram_base = ioremap(OMAP44XX_SAR_RAM_BASE, SZ_8K);
+ BUG_ON(!sar_ram_base);
+
+ return 0;
+}
+early_initcall(omap4_sar_ram_init);
diff --git a/arch/arm/mach-omap2/omap4-sar-layout.h b/arch/arm/mach-omap2/omap4-sar-layout.h
new file mode 100644
index 0000000..bb66816
--- /dev/null
+++ b/arch/arm/mach-omap2/omap4-sar-layout.h
@@ -0,0 +1,24 @@
+/*
+ * omap4-sar-layout.h: OMAP4 SAR RAM layout header file
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef OMAP_ARCH_OMAP4_SAR_LAYOUT_H
+#define OMAP_ARCH_OMAP4_SAR_LAYOUT_H
+
+/*
+ * SAR BANK offsets from base address OMAP44XX_SAR_RAM_BASE
+ */
+#define SAR_BANK1_OFFSET 0x0000
+#define SAR_BANK2_OFFSET 0x1000
+#define SAR_BANK3_OFFSET 0x2000
+#define SAR_BANK4_OFFSET 0x3000
+
+extern void __iomem *sar_ram_base;
+
+#endif
diff --git a/arch/arm/plat-omap/include/plat/omap44xx.h b/arch/arm/plat-omap/include/plat/omap44xx.h
index ea2b8a6..c0d478e 100644
--- a/arch/arm/plat-omap/include/plat/omap44xx.h
+++ b/arch/arm/plat-omap/include/plat/omap44xx.h
@@ -45,6 +45,7 @@
#define OMAP44XX_WKUPGEN_BASE 0x48281000
#define OMAP44XX_MCPDM_BASE 0x40132000
#define OMAP44XX_MCPDM_L3_BASE 0x49032000
+#define OMAP44XX_SAR_RAM_BASE 0x4a326000
#define OMAP44XX_MAILBOX_BASE (L4_44XX_BASE + 0xF4000)
#define OMAP44XX_HSUSB_OTG_BASE (L4_44XX_BASE + 0xAB000)
--
1.6.0.4
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 03/17] omap4: Export scu base address
2011-02-19 10:42 [PATCH 00/17] omap4: pm: suspend, hotplug and cpuilde support Santosh Shilimkar
2011-02-19 10:42 ` [PATCH 01/17] omap4: pm: Add omap WakeupGen module support Santosh Shilimkar
2011-02-19 10:42 ` [PATCH 02/17] omap4: pm: Add SAR RAM support Santosh Shilimkar
@ 2011-02-19 10:42 ` Santosh Shilimkar
2011-03-02 21:58 ` Kevin Hilman
2011-02-19 10:42 ` [PATCH 04/17] omap4: pm: Add CPUx OFF mode support Santosh Shilimkar
` (14 subsequent siblings)
17 siblings, 1 reply; 55+ messages in thread
From: Santosh Shilimkar @ 2011-02-19 10:42 UTC (permalink / raw)
To: linux-arm-kernel
The scu base address needs to be accessed in cpu hotplug
for power management. Hence export the same
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
---
arch/arm/mach-omap2/include/mach/omap4-common.h | 4 ++++
arch/arm/mach-omap2/omap-smp.c | 2 +-
2 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-omap2/include/mach/omap4-common.h b/arch/arm/mach-omap2/include/mach/omap4-common.h
index 5b0270b..0e5edd8 100644
--- a/arch/arm/mach-omap2/include/mach/omap4-common.h
+++ b/arch/arm/mach-omap2/include/mach/omap4-common.h
@@ -26,6 +26,10 @@ extern void __iomem *l2cache_base;
extern void __iomem *gic_dist_base_addr;
+#ifdef CONFIG_SMP
+extern void __iomem *scu_base;
+#endif
+
extern void __init gic_init_irq(void);
extern void omap_smc1(u32 fn, u32 arg);
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
index b66cfe8..b105a29 100644
--- a/arch/arm/mach-omap2/omap-smp.c
+++ b/arch/arm/mach-omap2/omap-smp.c
@@ -26,7 +26,7 @@
#include <mach/omap4-common.h>
/* SCU base address */
-static void __iomem *scu_base;
+void __iomem *scu_base;
static DEFINE_SPINLOCK(boot_lock);
--
1.6.0.4
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 04/17] omap4: pm: Add CPUx OFF mode support
2011-02-19 10:42 [PATCH 00/17] omap4: pm: suspend, hotplug and cpuilde support Santosh Shilimkar
` (2 preceding siblings ...)
2011-02-19 10:42 ` [PATCH 03/17] omap4: Export scu base address Santosh Shilimkar
@ 2011-02-19 10:42 ` Santosh Shilimkar
2011-03-02 22:12 ` Kevin Hilman
2011-02-19 10:42 ` [PATCH 05/17] omap4: pm: Initialise all the clockdomains to supported states Santosh Shilimkar
` (13 subsequent siblings)
17 siblings, 1 reply; 55+ messages in thread
From: Santosh Shilimkar @ 2011-02-19 10:42 UTC (permalink / raw)
To: linux-arm-kernel
This patch adds the CPU0 and CPU1 off mode support. CPUX close switch
retention (CSWR) is not supported by hardware design.
The CPUx OFF mode isn't supported on OMAP4430 ES1.0
CPUx sleep code is common for hotplug, suspend and cpuilde.
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
---
arch/arm/mach-omap2/Makefile | 4 +-
arch/arm/mach-omap2/include/mach/omap4-common.h | 46 +++
arch/arm/mach-omap2/omap4-mpuss-lowpower.c | 241 ++++++++++++++++
arch/arm/mach-omap2/omap4-sar-layout.h | 14 +
arch/arm/mach-omap2/pm44xx.c | 6 +
arch/arm/mach-omap2/sleep44xx.S | 334 +++++++++++++++++++++++
6 files changed, 644 insertions(+), 1 deletions(-)
create mode 100644 arch/arm/mach-omap2/omap4-mpuss-lowpower.c
create mode 100644 arch/arm/mach-omap2/sleep44xx.S
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 54ff219..5d94f7e 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -63,13 +63,15 @@ obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o
obj-$(CONFIG_ARCH_OMAP2) += sleep24xx.o pm_bus.o voltage.o
obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o voltage.o \
cpuidle34xx.o pm_bus.o
-obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o voltage.o pm_bus.o
+obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o voltage.o pm_bus.o \
+ omap4-mpuss-lowpower.o sleep44xx.o
obj-$(CONFIG_PM_DEBUG) += pm-debug.o
obj-$(CONFIG_OMAP_SMARTREFLEX) += sr_device.o smartreflex.o
obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3) += smartreflex-class3.o
AFLAGS_sleep24xx.o :=-Wa,-march=armv6
AFLAGS_sleep34xx.o :=-Wa,-march=armv7-a
+AFLAGS_sleep44xx.o :=-Wa,-march=armv7-a
ifeq ($(CONFIG_PM_VERBOSE),y)
CFLAGS_pm_bus.o += -DDEBUG
diff --git a/arch/arm/mach-omap2/include/mach/omap4-common.h b/arch/arm/mach-omap2/include/mach/omap4-common.h
index 0e5edd8..74c9aa7 100644
--- a/arch/arm/mach-omap2/include/mach/omap4-common.h
+++ b/arch/arm/mach-omap2/include/mach/omap4-common.h
@@ -13,6 +13,9 @@
#ifndef OMAP_ARCH_OMAP4_COMMON_H
#define OMAP_ARCH_OMAP4_COMMON_H
+#include <asm/proc-fns.h>
+
+#ifndef __ASSEMBLER__
/*
* wfi used in low power code. Directly opcode is used instead
* of instruction to avoid mulit-omap build break
@@ -33,4 +36,47 @@ extern void __iomem *scu_base;
extern void __init gic_init_irq(void);
extern void omap_smc1(u32 fn, u32 arg);
+/*
+ * Read MPIDR: Multiprocessor affinity register
+ */
+static inline unsigned int hard_smp_processor_id(void)
+{
+ unsigned int cpunum;
+
+ asm volatile (
+ "mrc p15, 0, %0, c0, c0, 5\n"
+ : "=r" (cpunum));
+ return cpunum &= 0x0F;
+}
+
+#if defined(CONFIG_SMP) && defined(CONFIG_PM)
+extern int omap4_mpuss_init(void);
+extern int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state);
+extern void omap4_cpu_suspend(unsigned int cpu, unsigned int save_state);
+extern void omap4_cpu_resume(void);
+
+#else
+
+static inline int omap4_enter_lowpower(unsigned int cpu,
+ unsigned int power_state)
+{
+ cpu_do_idle();
+ return 0;
+}
+
+static inline int omap4_mpuss_init(void)
+{
+ return 0;
+}
+
+static inline void omap4_cpu_suspend(unsigned int cpu, unsigned int save_state)
+{
+}
+
+static inline void omap4_cpu_resume(void)
+{
+}
+
#endif
+#endif /* __ASSEMBLER__ */
+#endif /* OMAP_ARCH_OMAP4_COMMON_H */
diff --git a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
new file mode 100644
index 0000000..c0f358d
--- /dev/null
+++ b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
@@ -0,0 +1,241 @@
+/*
+ * OMAP4 MPUSS low power code
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Written by Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * OMAP4430 MPUSS mainly consists of dual Cortex-A9 with per-CPU
+ * Local timer and Watchdog, GIC, SCU, PL310 L2 cache controller,
+ * CPU0 and CPU1 LPRM modules.
+ * CPU0, CPU1 and MPUSS each have there own power domain and
+ * hence multiple low power combinations of MPUSS are possible.
+ *
+ * The CPU0 and CPU1 can't support Closed switch Retention (CSWR)
+ * because the mode is not supported by hw constraints of dormant
+ * mode. While waking up from the dormant mode, a reset signal
+ * to the Cortex-A9 processor must be asserted by the external
+ * power controller.
+ *
+ * With architectural inputs and hardware recommendations, only
+ * below modes are supported from power gain vs latency point of view.
+ *
+ * CPU0 CPU1 MPUSS
+ * ----------------------------------------------
+ * ON ON ON
+ * ON(Inactive) OFF ON(Inactive)
+ * OFF OFF CSWR
+ * OFF OFF OSWR (*TBD)
+ * OFF OFF OFF* (*TBD)
+ * ----------------------------------------------
+ *
+ * Note: CPU0 is the master core and it is the last CPU to go down
+ * and first to wake-up when MPUSS low power states are excercised
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/linkage.h>
+#include <linux/smp.h>
+
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <asm/smp_scu.h>
+#include <asm/system.h>
+
+#include <plat/omap44xx.h>
+#include <mach/omap4-common.h>
+
+#include "omap4-sar-layout.h"
+#include "pm.h"
+#include "powerdomain.h"
+
+#ifdef CONFIG_SMP
+
+#define CPU0_ID 0x0
+#define CPU1_ID 0x1
+
+struct omap4_cpu_pm_info {
+ struct powerdomain *pwrdm;
+ void __iomem *scu_sar_addr;
+};
+
+static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info);
+
+/*
+ * Set the CPUx powerdomain's previous power state
+ */
+static inline void set_cpu_next_pwrst(unsigned int cpu_id,
+ unsigned int power_state)
+{
+ struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);
+
+ pwrdm_set_next_pwrst(pm_info->pwrdm, power_state);
+}
+
+/*
+ * Read CPU's previous power state
+ */
+static inline unsigned int read_cpu_prev_pwrst(unsigned int cpu_id)
+{
+ struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);
+
+ return pwrdm_read_prev_pwrst(pm_info->pwrdm);
+}
+
+/*
+ * Clear the CPUx powerdomain's previous power state
+ */
+static inline void clear_cpu_prev_pwrst(unsigned int cpu_id)
+{
+ struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);
+
+ pwrdm_clear_all_prev_pwrst(pm_info->pwrdm);
+}
+
+/*
+ * Store the SCU power status value to scratchpad memory
+ */
+static void scu_pwrst_prepare(unsigned int cpu_id, unsigned int cpu_state)
+{
+ struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);
+ u32 scu_pwr_st;
+
+ switch (cpu_state) {
+ case PWRDM_POWER_RET:
+ scu_pwr_st = SCU_PM_DORMANT;
+ break;
+ case PWRDM_POWER_OFF:
+ scu_pwr_st = SCU_PM_POWEROFF;
+ break;
+ case PWRDM_POWER_ON:
+ case PWRDM_POWER_INACTIVE:
+ default:
+ scu_pwr_st = SCU_PM_NORMAL;
+ break;
+ }
+
+ __raw_writel(scu_pwr_st, pm_info->scu_sar_addr);
+}
+
+/*
+ * OMAP4 MPUSS Low Power Entry Function
+ *
+ * The purpose of this function is to manage low power programming
+ * of OMAP4 MPUSS subsystem
+ * Paramenters:
+ * cpu : CPU ID
+ * power_state: Targetted Low power state.
+ */
+int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
+{
+ unsigned int save_state = 0;
+ unsigned int wakeup_cpu = hard_smp_processor_id();
+
+ if ((cpu > NR_CPUS) || (omap_rev() == OMAP4430_REV_ES1_0))
+ goto ret;
+
+ switch (power_state) {
+ case PWRDM_POWER_ON:
+ case PWRDM_POWER_INACTIVE:
+ save_state = 0;
+ break;
+ case PWRDM_POWER_OFF:
+ save_state = 1;
+ break;
+ case PWRDM_POWER_RET:
+ default:
+ /*
+ * CPUx CSWR is invalid hardware state. Also CPUx OSWR
+ * doesn't make much scense, since logic is lost and $L1
+ * needs to be cleaned because of coherency. This makes
+ * CPUx OSWR equivalent to CPUX OFF and hence not supported
+ */
+ goto ret;
+ }
+
+ clear_cpu_prev_pwrst(cpu);
+ set_cpu_next_pwrst(cpu, power_state);
+ scu_pwrst_prepare(cpu, power_state);
+
+ /*
+ * Call low level function with targeted CPU id
+ * and its low power state.
+ */
+ omap4_cpu_suspend(cpu, save_state);
+
+ /*
+ * Restore the CPUx power state to ON otherwise CPUx
+ * power domain can transitions to programmed low power
+ * state while doing WFI outside the low powe code. On
+ * secure devices, CPUx does WFI which can result in
+ * domain transition
+ */
+ wakeup_cpu = hard_smp_processor_id();
+ set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON);
+
+ret:
+ return 0;
+}
+
+/*
+ * Initialise OMAP4 MPUSS
+ */
+int __init omap4_mpuss_init(void)
+{
+ struct omap4_cpu_pm_info *pm_info;
+
+ if (omap_rev() == OMAP4430_REV_ES1_0) {
+ WARN(1, "Power Management not supported on OMAP4430 ES1.0\n");
+ return -EPERM;
+ }
+
+ /* Initilaise per CPU PM information */
+ pm_info = &per_cpu(omap4_pm_info, CPU0_ID);
+ pm_info->scu_sar_addr = sar_ram_base + SCU_OFFSET0;
+ pm_info->pwrdm = pwrdm_lookup("cpu0_pwrdm");
+ if (!pm_info->pwrdm) {
+ pr_err("Lookup failed for CPU0 pwrdm\n");
+ return -ENODEV;
+ }
+
+ /* Clear CPU previous power domain state */
+ pwrdm_clear_all_prev_pwrst(pm_info->pwrdm);
+
+ /* Initialise CPU0 power domain state to ON */
+ pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON);
+
+ pm_info = &per_cpu(omap4_pm_info, CPU1_ID);
+ pm_info->scu_sar_addr = sar_ram_base + SCU_OFFSET1;
+ pm_info->pwrdm = pwrdm_lookup("cpu1_pwrdm");
+ if (!pm_info->pwrdm) {
+ pr_err("Lookup failed for CPU1 pwrdm\n");
+ return -ENODEV;
+ }
+
+ /* Clear CPU previous power domain state */
+ pwrdm_clear_all_prev_pwrst(pm_info->pwrdm);
+
+ /* Initialise CPU1 power domain state to ON */
+ pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON);
+
+ /*
+ * Program the wakeup routine address for the CPU0 and CPU1
+ * used for OFF or DORMANT wakeup. Wakeup routine address
+ * is fixed so programit in init itself.
+ */
+ __raw_writel(virt_to_phys(omap4_cpu_resume),
+ sar_ram_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET);
+ __raw_writel(virt_to_phys(omap4_cpu_resume),
+ sar_ram_base + CPU0_WAKEUP_NS_PA_ADDR_OFFSET);
+
+ return 0;
+}
+
+#endif
+
diff --git a/arch/arm/mach-omap2/omap4-sar-layout.h b/arch/arm/mach-omap2/omap4-sar-layout.h
index bb66816..c4251db 100644
--- a/arch/arm/mach-omap2/omap4-sar-layout.h
+++ b/arch/arm/mach-omap2/omap4-sar-layout.h
@@ -19,6 +19,20 @@
#define SAR_BANK3_OFFSET 0x2000
#define SAR_BANK4_OFFSET 0x3000
+/* Scratch pad memory offsets from SAR_BANK1 */
+#define CPU0_SAVE_OFFSET 0xb00
+#define CPU1_SAVE_OFFSET 0xc00
+#define MMU_OFFSET 0xd00
+#define SCU_OFFSET0 0xd20
+#define SCU_OFFSET1 0xd24
+
+/* CPUx Wakeup Non-Secure Physical Address offsets in SAR_BANK3 */
+#define CPU0_WAKEUP_NS_PA_ADDR_OFFSET 0xa04
+#define CPU1_WAKEUP_NS_PA_ADDR_OFFSET 0xa08
+
+#ifndef __ASSEMBLER__
+
extern void __iomem *sar_ram_base;
#endif
+#endif
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index 8431d41..b142673 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -115,6 +115,12 @@ static int __init omap4_pm_init(void)
/* Enable autoidle for all clks which support it*/
omap_clk_enable_autoidle();
+
+ ret = omap4_mpuss_init();
+ if (ret) {
+ pr_err("Failed to initialise OMAP4 MPUSS\n");
+ goto err2;
+ }
#endif
#ifdef CONFIG_SUSPEND
diff --git a/arch/arm/mach-omap2/sleep44xx.S b/arch/arm/mach-omap2/sleep44xx.S
new file mode 100644
index 0000000..bb42a7a
--- /dev/null
+++ b/arch/arm/mach-omap2/sleep44xx.S
@@ -0,0 +1,334 @@
+/*
+ * OMAP44xx CPU low power powerdown and powerup code.
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Written by Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * This program is free software,you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/linkage.h>
+#include <asm/system.h>
+#include <asm/smp_scu.h>
+#include <asm/memory.h>
+
+#include <plat/omap44xx.h>
+#include <mach/omap4-common.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#include "omap4-sar-layout.h"
+
+#ifdef CONFIG_SMP
+
+/* Masks used for MMU manipulation */
+#define TTRBIT_MASK 0xffffc000
+#define TABLE_INDEX_MASK 0xfff00000
+#define TABLE_ENTRY 0x00000c02
+#define CACHE_DISABLE_MASK 0xffffe7fb
+
+/*
+ * =============================
+ * == CPU suspend entry point ==
+ * =============================
+ *
+ * void omap4_cpu_suspend(unsigned int cpu, unsigned int save_state)
+ *
+ * This function code saves the CPU context and performs the CPU
+ * power down sequence. Calling WFI effectively changes the CPU
+ * power domains states to the desired target power state.
+ *
+ * @cpu : contains cpu id (r0)
+ * @save_state : contains context save state (r1)
+ * 0 - No context lost
+ * 1 - CPUx L1 and logic lost: MPUSS CSWR
+ * 2 - CPUx L1 and logic lost + GIC lost: MPUSS OSWR
+ * 3 - CPUx L1 and logic lost + GIC + L2 lost: MPUSS OFF
+ * @return: This function never returns for CPU OFF and DORMANT power states.
+ * It retunrs to the caller for CPU INACTIVE and ON power states or in case
+ * CPU failed to transition to targeted OFF/DORMANT state.
+ */
+
+ENTRY(omap4_cpu_suspend)
+ stmfd sp!, {r0-r12, lr} @ Save registers on stack
+ cmp r1, #0x0
+ beq do_WFI @ Nothing to save, jump to WFI
+ ldr r8, =sar_ram_base
+ ldr r8, [r8]
+ ands r0, r0, #0x0f
+ orreq r8, r8, #CPU0_SAVE_OFFSET
+ orrne r8, r8, #CPU1_SAVE_OFFSET
+
+ /*
+ * Save only needed CPU CP15 registers. VFP, breakpoint,
+ * performance monitor registers are not saved. Generic
+ * code suppose to take care of those.
+ */
+ mov r4, sp @ Store sp
+ mrs r5, spsr @ Store spsr
+ mov r6, lr @ Store lr
+ stmia r8!, {r4-r6}
+
+ /* c1 and c2 registers */
+ mrc p15, 0, r4, c1, c0, 2 @ CPACR
+ mrc p15, 0, r5, c2, c0, 0 @ TTBR0
+ mrc p15, 0, r6, c2, c0, 1 @ TTBR1
+ mrc p15, 0, r7, c2, c0, 2 @ TTBCR
+ stmia r8!, {r4-r7}
+
+ /* c3 and c10 registers */
+ mrc p15, 0, r4, c3, c0, 0 @ DACR
+ mrc p15, 0, r5, c10, c2, 0 @ PRRR
+ mrc p15, 0, r6, c10, c2, 1 @ NMRR
+ stmia r8!,{r4-r6}
+
+ /* c13 registers */
+ mrc p15, 0, r4, c13, c0, 1 @ Context ID
+ mrc p15, 0, r5, c13, c0, 2 @ User r/w thread ID
+ mrc p15, 0, r6, c13, c0, 3 @ User ro thread ID
+ mrc p15, 0, r7, c13, c0, 4 @ Privilege only thread ID
+ stmia r8!, {r4-r7}
+
+ /* c12 and CPSR registers */
+ mrc p15, 0, r4, c12, c0, 0 @ Secure or NS VBAR
+ mrs r5, cpsr @ Store CPSR
+ stmia r8!, {r4,r5}
+
+ /* c1 control register */
+ mrc p15, 0, r4, c1, c0, 0 @ Save control register
+ stmia r8!, {r4}
+
+ /* Clear the SCTLR C bit to prevent further data cache allocation */
+ mrc p15, 0, r0, c1, c0, 0
+ bic r0, r0, #(1 << 2) @ Disable the C bit
+ mcr p15, 0, r0, c1, c0, 0
+ isb
+
+ /*
+ * Clean and invalidate all data from the L1 data cache.
+ * The L2 duplicate snoop tag RAM for this CPU is now
+ * empty. This prevents any new data cache snoops or data
+ * cache maintenance operations from other CPUs in the cluster
+ * being issued to this CPU.
+ */
+ bl v7_flush_dcache_all
+
+ /*
+ * Switch the CPU from Symmetric Multiprocessing (SMP) mode
+ * to AsymmetricMultiprocessing (AMP) mode by programming
+ * the SCU power status to DORMANT or OFF mode.
+ * This enables the CPU to be taken out of coherency by
+ * preventing the CPU from receiving cache, TLB, or BTB
+ * maintenance operations broadcast by other CPUs in the cluster.
+ */
+ ldr r8, =sar_ram_base
+ ldr r8, [r8]
+ mrc p15, 0, r0, c0, c0, 5 @ Read MPIDR
+ ands r0, r0, #0x0f
+ ldreq r1, [r8, #SCU_OFFSET0]
+ ldrne r1, [r8, #SCU_OFFSET1]
+ ldr r0, =scu_base
+ ldr r0, [r0]
+ bl scu_power_mode
+
+do_WFI:
+ /*
+ * Execute an ISB instruction to ensure that all of the
+ * CP15 register changes have been committed.
+ */
+ isb
+
+ /*
+ * Execute a barrier instruction to ensure that all cache,
+ * TLB and branch predictor maintenance operations issued
+ * by any CPU in the cluster have completed.
+ */
+ dsb
+ dmb
+
+ /*
+ * Execute a WFI instruction and wait until the
+ * STANDBYWFI output is asserted to indicate that the
+ * CPU is in idle and low power state.
+ */
+ wfi @ Wait For Interrupt
+
+ /*
+ * CPU is here when it failed to enter OFF/DORMANT or
+ * no low power state was attempted.
+ */
+ mrc p15, 0, r0, c1, c0, 0
+ tst r0, #(1 << 2) @ Check C bit enabled?
+ orreq r0, r0, #(1 << 2) @ Enable the C bit
+ mcreq p15, 0, r0, c1, c0, 0
+ isb
+
+ /*
+ * Ensure the CPU power state is set to NORMAL in
+ * SCU power state so that CPU is back in coherency.
+ * In non-coherent mode CPU can lock-up and lead to
+ * system deadlock.
+ */
+ ldr r0, =scu_base
+ ldr r0, [r0]
+ mov r1, #SCU_PM_NORMAL
+ bl scu_power_mode
+ isb
+ dsb
+
+ ldmfd sp!, {r0-r12, pc} @ Restore regs and return
+ENDPROC(omap4_cpu_suspend)
+
+/*
+ * ============================
+ * == CPU resume entry point ==
+ * ============================
+ *
+ * void omap4_cpu_resume(void)
+ *
+ * ROM code jumps to this function while waking up from CPU
+ * OFF or DORMANT state. Physical address of the function is
+ * stored in the SAR RAM while entering to OFF or DORMANT mode.
+ */
+
+ENTRY(omap4_cpu_resume)
+ /*
+ * Check the wakeup cpuid and use appropriate
+ * SAR BANK location for context restore.
+ */
+ ldr r3, =OMAP44XX_SAR_RAM_BASE
+ mov r1, #0
+ mcr p15, 0, r1, c7, c5, 0 @ Invalidate L1 I
+ mrc p15, 0, r0, c0, c0, 5 @ MPIDR
+ ands r0, r0, #0x0f
+ orreq r3, r3, #CPU0_SAVE_OFFSET
+ orrne r3, r3, #CPU1_SAVE_OFFSET
+
+ /* Restore cp15 registers */
+ ldmia r3!, {r4-r6}
+ mov sp, r4 @ Restore sp
+ msr spsr_cxsf, r5 @ Restore spsr
+ mov lr, r6 @ Restore lr
+
+ /* c1 and c2 registers */
+ ldmia r3!, {r4-r7}
+ mcr p15, 0, r4, c1, c0, 2 @ CPACR
+ mcr p15, 0, r5, c2, c0, 0 @ TTBR0
+ mcr p15, 0, r6, c2, c0, 1 @ TTBR1
+ mcr p15, 0, r7, c2, c0, 2 @ TTBCR
+
+ /* c3 and c10 registers */
+ ldmia r3!,{r4-r6}
+ mcr p15, 0, r4, c3, c0, 0 @ DACR
+ mcr p15, 0, r5, c10, c2, 0 @ PRRR
+ mcr p15, 0, r6, c10, c2, 1 @ NMRR
+
+ /* c13 registers */
+ ldmia r3!,{r4-r7}
+ mcr p15, 0, r4, c13, c0, 1 @ Context ID
+ mcr p15, 0, r5, c13, c0, 2 @ User r/w thread ID
+ mcr p15, 0, r6, c13, c0, 3 @ User ro thread ID
+ mcr p15, 0, r7, c13, c0, 4 @ Privilege only thread ID
+
+ /* c12 and CPSR registers */
+ ldmia r3!,{r4,r5}
+ mrc p15, 0, r4, c12, c0, 0 @ Secure or NS VBAR
+ msr cpsr, r5 @ store cpsr
+
+ /*
+ * Enabling MMU here. Page entry needs to be altered
+ * to create temporary 1:1 map and then resore the entry
+ * ones MMU is enabled
+ */
+ mrc p15, 0, r7, c2, c0, 2 @ Read TTBRControl
+ and r7, #0x7 @ Extract N (0:2) to decide
+ cmp r7, #0x0 @ TTBR0/TTBR1
+ beq use_ttbr0
+ttbr_error:
+ b ttbr_error @ Only N = 0 supported
+use_ttbr0:
+ mrc p15, 0, r2, c2, c0, 0 @ Read TTBR0
+ ldr r5, =TTRBIT_MASK
+ and r2, r5
+ mov r4, pc
+ ldr r5, =TABLE_INDEX_MASK
+ and r4, r5 @ r4 = 31 to 20 bits of pc
+ ldr r1, =TABLE_ENTRY
+ add r1, r1, r4 @ r1 has value of table entry
+ lsr r4, #18 @ Address of table entry
+ add r2, r4 @ r2 - location to be modified
+
+ /* Ensure the modified entry makes it to main memory */
+#ifdef CONFIG_CACHE_L2X0
+ ldr r5, =OMAP44XX_L2CACHE_BASE
+ str r2, [r5, #L2X0_CLEAN_INV_LINE_PA]
+wait_l2:
+ ldr r0, [r5, #L2X0_CLEAN_INV_LINE_PA]
+ ands r0, #1
+ bne wait_l2
+#endif
+
+ /* Storing previous entry of location being modified */
+ ldr r5, =OMAP44XX_SAR_RAM_BASE
+ ldr r4, [r2]
+ str r4, [r5, #MMU_OFFSET] @ Modify the table entry
+ str r1, [r2]
+
+ /*
+ * Storing address of entry being modified
+ * It will be restored after enabling MMU
+ */
+ ldr r5, =OMAP44XX_SAR_RAM_BASE
+ orr r5, r5, #MMU_OFFSET
+ str r2, [r5, #0x04]
+ mov r0, #0
+ mcr p15, 0, r0, c7, c5, 4 @ Flush prefetch buffer
+ mcr p15, 0, r0, c7, c5, 6 @ Invalidate BTB
+ mcr p15, 0, r0, c8, c5, 0 @ Invalidate ITLB
+ mcr p15, 0, r0, c8, c6, 0 @ Invalidate DTLB
+
+ /*
+ * Restore control register but don't enable Data caches here.
+ * Caches will be enabled after restoring MMU table entry.
+ */
+ ldmia r3!, {r4}
+ str r4, [r5, #0x08] @ Store previous value of CR
+ ldr r2, =CACHE_DISABLE_MASK
+ and r4, r2
+ mcr p15, 0, r4, c1, c0, 0
+ isb
+ dsb
+ ldr r0, =mmu_on_label
+ bx r0
+mmu_on_label:
+ /* Set up the per-CPU stacks */
+ bl cpu_init
+
+ /*
+ * Restore the MMU table entry that was modified for
+ * enabling MMU.
+ */
+ ldr r8, =sar_ram_base
+ ldr r8, [r8]
+ orr r8, r8, #MMU_OFFSET @ Get address of entry that..
+ ldr r2, [r8, #0x04] @ was modified
+ ldr r3, =local_va2pa_offet
+ add r2, r2, r3
+ ldr r0, [r8] @ Get the previous value..
+ str r0, [r2] @ which needs to be restored
+ mov r0, #0
+ mcr p15, 0, r0, c7, c1, 6 @ flush TLB and issue barriers
+ dsb
+ isb
+ ldr r0, [r8, #0x08] @ Restore the Control register
+ mcr p15, 0, r0, c1, c0, 0 @ with caches enabled.
+ isb
+
+ ldmfd sp!, {r0-r12, pc} @ restore regs and return
+
+ .equ local_va2pa_offet, (PHYS_OFFSET + PAGE_OFFSET)
+
+ENDPROC(omap4_cpu_resume)
+
+#endif
--
1.6.0.4
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 05/17] omap4: pm: Initialise all the clockdomains to supported states
2011-02-19 10:42 [PATCH 00/17] omap4: pm: suspend, hotplug and cpuilde support Santosh Shilimkar
` (3 preceding siblings ...)
2011-02-19 10:42 ` [PATCH 04/17] omap4: pm: Add CPUx OFF mode support Santosh Shilimkar
@ 2011-02-19 10:42 ` Santosh Shilimkar
2011-03-02 22:17 ` Kevin Hilman
2011-02-19 10:42 ` [PATCH 06/17] omap4: pm: Program CPU1 to hit OFF when off-lined Santosh Shilimkar
` (12 subsequent siblings)
17 siblings, 1 reply; 55+ messages in thread
From: Santosh Shilimkar @ 2011-02-19 10:42 UTC (permalink / raw)
To: linux-arm-kernel
Initialise hardware supervised mode for all clockdomains if it's
supported. Initiate sleep transition for other clockdomains,
if they are not being used.
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
---
arch/arm/mach-omap2/pm44xx.c | 22 +++++++++++++++++++++-
1 files changed, 21 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index b142673..9a9dc41 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -17,9 +17,11 @@
#include <linux/slab.h>
#include <plat/clock.h>
-#include "powerdomain.h"
#include <mach/omap4-common.h>
+#include "powerdomain.h"
+#include "clockdomain.h"
+
struct power_state {
struct powerdomain *pwrdm;
u32 next_state;
@@ -74,6 +76,22 @@ static const struct platform_suspend_ops omap_pm_ops = {
};
#endif /* CONFIG_SUSPEND */
+/*
+ * Enable hardwarew supervised mode for all clockdomains if it's
+ * supported. Initiate sleep transition for other clockdomains, if
+ * they are not used
+ */
+static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
+{
+ if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
+ clkdm_allow_idle(clkdm);
+ else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&
+ atomic_read(&clkdm->usecount) == 0)
+ clkdm_sleep(clkdm);
+ return 0;
+}
+
+
static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
{
struct power_state *pwrst;
@@ -116,6 +134,8 @@ static int __init omap4_pm_init(void)
/* Enable autoidle for all clks which support it*/
omap_clk_enable_autoidle();
+ (void) clkdm_for_each(clkdms_setup, NULL);
+
ret = omap4_mpuss_init();
if (ret) {
pr_err("Failed to initialise OMAP4 MPUSS\n");
--
1.6.0.4
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 06/17] omap4: pm: Program CPU1 to hit OFF when off-lined
2011-02-19 10:42 [PATCH 00/17] omap4: pm: suspend, hotplug and cpuilde support Santosh Shilimkar
` (4 preceding siblings ...)
2011-02-19 10:42 ` [PATCH 05/17] omap4: pm: Initialise all the clockdomains to supported states Santosh Shilimkar
@ 2011-02-19 10:42 ` Santosh Shilimkar
2011-02-19 10:42 ` [PATCH 07/17] omap4: pm: CPU1 wakeup workaround form Low power modes Santosh Shilimkar
` (11 subsequent siblings)
17 siblings, 0 replies; 55+ messages in thread
From: Santosh Shilimkar @ 2011-02-19 10:42 UTC (permalink / raw)
To: linux-arm-kernel
Program non-boot CPUs to hit lowest supported power state
when it is off-lined using cpu hotplug framework.
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
---
arch/arm/mach-omap2/omap-hotplug.c | 18 +++++++++++++-----
1 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/arch/arm/mach-omap2/omap-hotplug.c b/arch/arm/mach-omap2/omap-hotplug.c
index 4976b93..9f8f097 100644
--- a/arch/arm/mach-omap2/omap-hotplug.c
+++ b/arch/arm/mach-omap2/omap-hotplug.c
@@ -20,6 +20,9 @@
#include <asm/cacheflush.h>
#include <mach/omap4-common.h>
+#include <mach/omap-wakeupgen.h>
+
+#include "powerdomain.h"
int platform_cpu_kill(unsigned int cpu)
{
@@ -32,6 +35,8 @@ int platform_cpu_kill(unsigned int cpu)
*/
void platform_cpu_die(unsigned int cpu)
{
+ unsigned int this_cpu;
+
flush_cache_all();
dsb();
@@ -39,18 +44,21 @@ void platform_cpu_die(unsigned int cpu)
* we're ready for shutdown now, so do it
*/
if (omap_modify_auxcoreboot0(0x0, 0x200) != 0x0)
- printk(KERN_CRIT "Secure clear status failed\n");
+ pr_err("Secure clear status failed\n");
for (;;) {
/*
- * Execute WFI
+ * Enter into low power state
+ * clear all interrupt wakeup sources
*/
- do_wfi();
-
- if (omap_read_auxcoreboot0() == cpu) {
+ omap_wakeupgen_irqmask_all(cpu, 1);
+ omap4_enter_lowpower(cpu, PWRDM_POWER_OFF);
+ this_cpu = hard_smp_processor_id();
+ if (omap_read_auxcoreboot0() == this_cpu) {
/*
* OK, proper wakeup, we're done
*/
+ omap_wakeupgen_irqmask_all(this_cpu, 0);
break;
}
pr_debug("CPU%u: spurious wakeup call\n", cpu);
--
1.6.0.4
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 07/17] omap4: pm: CPU1 wakeup workaround form Low power modes
2011-02-19 10:42 [PATCH 00/17] omap4: pm: suspend, hotplug and cpuilde support Santosh Shilimkar
` (5 preceding siblings ...)
2011-02-19 10:42 ` [PATCH 06/17] omap4: pm: Program CPU1 to hit OFF when off-lined Santosh Shilimkar
@ 2011-02-19 10:42 ` Santosh Shilimkar
2011-03-02 22:23 ` Kevin Hilman
2011-03-02 23:44 ` Kevin Hilman
2011-02-19 10:42 ` [PATCH 08/17] omap4: pm: Add GIC save/restore support Santosh Shilimkar
` (10 subsequent siblings)
17 siblings, 2 replies; 55+ messages in thread
From: Santosh Shilimkar @ 2011-02-19 10:42 UTC (permalink / raw)
To: linux-arm-kernel
The SGI(Software Generated Interrupts) are not wakeup capable from
low power states. This is known limitation on OMAP4 and needs to be
worked around by using software forced clockdomain wake-up. CPU0 forces
the CPU1 clockdomain to software force wakeup. After the wakeup, CPU1
restores its clockdomain hardware supervised mode.
More details can be found in OMAP4430 TRM - Version J
Section :
4.3.4.2 Power States of CPU0 and CPU1
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
---
arch/arm/mach-omap2/omap-hotplug.c | 9 +++++++++
arch/arm/mach-omap2/omap-smp.c | 27 ++++++++++++++++++++++++++-
2 files changed, 35 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-omap2/omap-hotplug.c b/arch/arm/mach-omap2/omap-hotplug.c
index 9f8f097..cf4ab15 100644
--- a/arch/arm/mach-omap2/omap-hotplug.c
+++ b/arch/arm/mach-omap2/omap-hotplug.c
@@ -23,6 +23,7 @@
#include <mach/omap-wakeupgen.h>
#include "powerdomain.h"
+#include "clockdomain.h"
int platform_cpu_kill(unsigned int cpu)
{
@@ -36,6 +37,11 @@ int platform_cpu_kill(unsigned int cpu)
void platform_cpu_die(unsigned int cpu)
{
unsigned int this_cpu;
+ static struct clockdomain *cpu1_clkdm;
+
+ /* To avoid cpu1 clockdomain lookup every time */
+ if (!cpu1_clkdm)
+ cpu1_clkdm = clkdm_lookup("mpu1_clkdm");
flush_cache_all();
dsb();
@@ -59,6 +65,9 @@ void platform_cpu_die(unsigned int cpu)
* OK, proper wakeup, we're done
*/
omap_wakeupgen_irqmask_all(this_cpu, 0);
+
+ /* Restore clockdomain to hardware supervised */
+ clkdm_allow_idle(cpu1_clkdm);
break;
}
pr_debug("CPU%u: spurious wakeup call\n", cpu);
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
index b105a29..31c9b79 100644
--- a/arch/arm/mach-omap2/omap-smp.c
+++ b/arch/arm/mach-omap2/omap-smp.c
@@ -25,6 +25,8 @@
#include <mach/hardware.h>
#include <mach/omap4-common.h>
+#include "clockdomain.h"
+
/* SCU base address */
void __iomem *scu_base;
@@ -48,6 +50,8 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
{
+ static struct clockdomain *cpu1_clkdm;
+ static bool booted;
/*
* Set synchronisation state between this boot processor
* and the secondary one
@@ -63,7 +67,28 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
omap_modify_auxcoreboot0(0x200, 0xfffffdff);
flush_cache_all();
smp_wmb();
- smp_cross_call(cpumask_of(cpu), 1);
+
+ /* To avoid cpu1 clockdomain lookup every time */
+ if (!cpu1_clkdm)
+ cpu1_clkdm = clkdm_lookup("mpu1_clkdm");
+
+ /*
+ * The SGI(Software Generated Interrupts) are not wakeup capable
+ * from low power states. This is known limitation on OMAP4 and
+ * needs to be worked around by using software forced clockdomain
+ * wake-up. To wakeup CPU1, CPU0 forces the CPU1 clockdomain to
+ * software force wakeup. After the wakeup, CPU1 restores its
+ * clockdomain hardware supervised mode.
+ * More details can be found in OMAP4430 TRM - Version J
+ * Section :
+ * 4.3.4.2 Power States of CPU0 and CPU1
+ */
+ if (booted) {
+ clkdm_wakeup(cpu1_clkdm);
+ } else {
+ dsb_sev();
+ booted = true;
+ }
/*
* Now the secondary core is starting up let it run its
--
1.6.0.4
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 08/17] omap4: pm: Add GIC save/restore support
2011-02-19 10:42 [PATCH 00/17] omap4: pm: suspend, hotplug and cpuilde support Santosh Shilimkar
` (6 preceding siblings ...)
2011-02-19 10:42 ` [PATCH 07/17] omap4: pm: CPU1 wakeup workaround form Low power modes Santosh Shilimkar
@ 2011-02-19 10:42 ` Santosh Shilimkar
2011-03-02 22:29 ` Kevin Hilman
2011-02-19 10:42 ` [PATCH 09/17] omap4: pm: Add WakeupGen " Santosh Shilimkar
` (9 subsequent siblings)
17 siblings, 1 reply; 55+ messages in thread
From: Santosh Shilimkar @ 2011-02-19 10:42 UTC (permalink / raw)
To: linux-arm-kernel
On OMAP4 when attempting MPU off-mode or OSWR, the GIC context is
lost. This patch adds GIC context save and restore support.
The context save is done by software and restore is done by
ROM code from predefined SAR locations where the context suppose
to be saved. Refer to ROM code specs for the GIC layout details.
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
---
arch/arm/mach-omap2/omap-hotplug.c | 4 +
arch/arm/mach-omap2/omap4-mpuss-lowpower.c | 176 +++++++++++++++++++++++++++-
arch/arm/mach-omap2/omap4-sar-layout.h | 20 +++
3 files changed, 199 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-omap2/omap-hotplug.c b/arch/arm/mach-omap2/omap-hotplug.c
index cf4ab15..deab389 100644
--- a/arch/arm/mach-omap2/omap-hotplug.c
+++ b/arch/arm/mach-omap2/omap-hotplug.c
@@ -19,6 +19,8 @@
#include <linux/smp.h>
#include <asm/cacheflush.h>
+#include <asm/hardware/gic.h>
+
#include <mach/omap4-common.h>
#include <mach/omap-wakeupgen.h>
@@ -58,6 +60,7 @@ void platform_cpu_die(unsigned int cpu)
* clear all interrupt wakeup sources
*/
omap_wakeupgen_irqmask_all(cpu, 1);
+ gic_secondary_set(0, true);
omap4_enter_lowpower(cpu, PWRDM_POWER_OFF);
this_cpu = hard_smp_processor_id();
if (omap_read_auxcoreboot0() == this_cpu) {
@@ -65,6 +68,7 @@ void platform_cpu_die(unsigned int cpu)
* OK, proper wakeup, we're done
*/
omap_wakeupgen_irqmask_all(this_cpu, 0);
+ gic_secondary_set(0, false);
/* Restore clockdomain to hardware supervised */
clkdm_allow_idle(cpu1_clkdm);
diff --git a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
index c0f358d..4140251 100644
--- a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
+++ b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
@@ -47,6 +47,8 @@
#include <asm/tlbflush.h>
#include <asm/smp_scu.h>
#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/hardware/gic.h>
#include <plat/omap44xx.h>
#include <mach/omap4-common.h>
@@ -59,6 +61,19 @@
#define CPU0_ID 0x0
#define CPU1_ID 0x1
+#define GIC_MASK_ALL 0x0
+#define GIC_ISR_NON_SECURE 0xffffffff
+#define SPI_ENABLE_SET_OFFSET 0x04
+#define PPI_PRI_OFFSET 0x1c
+#define SPI_PRI_OFFSET 0x20
+#define SPI_TARGET_OFFSET 0x20
+#define SPI_CONFIG_OFFSET 0x20
+
+/* GIC save SAR bank base */
+static struct powerdomain *mpuss_pd;
+
+/* Variables to store maximum spi(Shared Peripheral Interrupts) registers. */
+static u32 max_spi_irq, max_spi_reg;
struct omap4_cpu_pm_info {
struct powerdomain *pwrdm;
@@ -67,6 +82,17 @@ struct omap4_cpu_pm_info {
static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info);
+/* Helper functions */
+static inline void sar_writel(u32 val, u32 offset, u8 idx)
+{
+ __raw_writel(val, sar_ram_base + offset + 4 * idx);
+}
+
+static inline u32 gic_readl(u32 offset, u8 idx)
+{
+ return __raw_readl(gic_dist_base_addr + offset + 4 * idx);
+}
+
/*
* Set the CPUx powerdomain's previous power state
*/
@@ -124,6 +150,85 @@ static void scu_pwrst_prepare(unsigned int cpu_id, unsigned int cpu_state)
}
/*
+ * Save GIC context in SAR RAM. Restore is done by ROM code
+ * GIC is lost only when MPU hits OSWR or OFF. It consists
+ * of a distributor and a per-CPU interface module. The GIC
+ * save restore is optimised to save only necessary registers.
+ */
+static void gic_save_context(void)
+{
+ u8 i;
+ u32 val;
+
+ /*
+ * Interrupt Clear Enable registers are inverse of set enable
+ * and hence not needed to be saved. ROM code programs it
+ * based on Set Enable register values.
+ */
+
+ /* Save CPU 0 Interrupt Set Enable register */
+ val = gic_readl(GIC_DIST_ENABLE_SET, 0);
+ sar_writel(val, ICDISER_CPU0_OFFSET, 0);
+
+ /* Disable interrupts on CPU1 */
+ sar_writel(GIC_MASK_ALL, ICDISER_CPU1_OFFSET, 0);
+
+ /* Save all SPI Set Enable register */
+ for (i = 0; i < max_spi_reg; i++) {
+ val = gic_readl(GIC_DIST_ENABLE_SET + SPI_ENABLE_SET_OFFSET, i);
+ sar_writel(val, ICDISER_SPI_OFFSET, i);
+ }
+
+ /*
+ * Interrupt Priority Registers
+ * Secure sw accesses, last 5 bits of the 8 bits (bit[7:3] are used)
+ * Non-Secure sw accesses, last 4 bits (i.e. bits[7:4] are used)
+ * But the Secure Bits[7:3] are shifted by 1 in Non-Secure access.
+ * Secure (bits[7:3] << 1)== Non Secure bits[7:4]
+ * Hence right shift the value by 1 while saving the priority
+ */
+
+ /* Save SGI priority registers (Software Generated Interrupt) */
+ for (i = 0; i < 4; i++) {
+ val = gic_readl(GIC_DIST_PRI, i);
+
+ /* Save the priority bits of the Interrupts */
+ sar_writel(val >> 0x1, ICDIPR_SFI_CPU0_OFFSET, i);
+
+ /* Disable the interrupts on CPU1 */
+ sar_writel(GIC_MASK_ALL, ICDIPR_SFI_CPU1_OFFSET, i);
+ }
+
+ /* Save PPI priority registers (Private Peripheral Intterupts) */
+ val = gic_readl(GIC_DIST_PRI + PPI_PRI_OFFSET, 0);
+ sar_writel(val >> 0x1, ICDIPR_PPI_CPU0_OFFSET, 0);
+ sar_writel(GIC_MASK_ALL, ICDIPR_PPI_CPU1_OFFSET, 0);
+
+ /* SPI priority registers - 4 interrupts/register */
+ for (i = 0; i < (max_spi_irq / 4); i++) {
+ val = gic_readl((GIC_DIST_PRI + SPI_PRI_OFFSET), i);
+ sar_writel(val >> 0x1, ICDIPR_SPI_OFFSET, i);
+ }
+
+ /* SPI Interrupt Target registers - 4 interrupts/register */
+ for (i = 0; i < (max_spi_irq / 4); i++) {
+ val = gic_readl((GIC_DIST_TARGET + SPI_TARGET_OFFSET), i);
+ sar_writel(val, ICDIPTR_SPI_OFFSET, i);
+ }
+
+ /* SPI Interrupt Congigeration eegisters- 16 interrupts/register */
+ for (i = 0; i < (max_spi_irq / 16); i++) {
+ val = gic_readl((GIC_DIST_CONFIG + SPI_CONFIG_OFFSET), i);
+ sar_writel(val, ICDICFR_OFFSET, i);
+ }
+
+ /* Set the Backup Bit Mask status for GIC */
+ val = __raw_readl(sar_ram_base + SAR_BACKUP_STATUS_OFFSET);
+ val |= (SAR_BACKUP_STATUS_GIC_CPU0 | SAR_BACKUP_STATUS_GIC_CPU1);
+ __raw_writel(val, sar_ram_base + SAR_BACKUP_STATUS_OFFSET);
+}
+
+/*
* OMAP4 MPUSS Low Power Entry Function
*
* The purpose of this function is to manage low power programming
@@ -131,11 +236,25 @@ static void scu_pwrst_prepare(unsigned int cpu_id, unsigned int cpu_state)
* Paramenters:
* cpu : CPU ID
* power_state: Targetted Low power state.
+ *
+ * MPUSS Low power states
+ * The basic rule is that the MPUSS power domain must be@the higher or
+ * equal power state (state that consume more power) than the higher of the
+ * two CPUs. For example, it is illegal for system power to be OFF, while
+ * the power of one or both of the CPU is DORMANT. When an illegal state is
+ * entered, then the hardware behavior is unpredictable.
+ *
+ * MPUSS state for the context save
+ * save_state =
+ * 0 - Nothing lost and no need to save: MPUSS INACTIVE
+ * 1 - CPUx L1 and logic lost: MPUSS CSWR
+ * 2 - CPUx L1 and logic lost + GIC lost: MPUSS OSWR
+ * 3 - CPUx L1 and logic lost + GIC + L2 lost: MPUSS OFF
*/
int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
{
unsigned int save_state = 0;
- unsigned int wakeup_cpu = hard_smp_processor_id();
+ unsigned int wakeup_cpu;
if ((cpu > NR_CPUS) || (omap_rev() == OMAP4430_REV_ES1_0))
goto ret;
@@ -159,6 +278,23 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
goto ret;
}
+ /*
+ * MPUSS book keeping should be executed by master
+ * CPU only which is also the last CPU to go down.
+ */
+ if (cpu)
+ goto cpu_prepare;
+
+ /*
+ * Check MPUSS next state and save GIC if needed
+ * GIC lost during MPU OFF and OSWR
+ */
+ if (pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_OFF) {
+ gic_save_context();
+ save_state = 3;
+ }
+
+cpu_prepare:
clear_cpu_prev_pwrst(cpu);
set_cpu_next_pwrst(cpu, power_state);
scu_pwrst_prepare(cpu, power_state);
@@ -179,6 +315,19 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
wakeup_cpu = hard_smp_processor_id();
set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON);
+ /* If !master cpu return to hotplug-path */
+ if (wakeup_cpu)
+ goto ret;
+
+ /* Check MPUSS previous power state and enable GIC if needed */
+ if (pwrdm_read_prev_pwrst(mpuss_pd) == PWRDM_POWER_OFF) {
+ /* Clear SAR BACKUP status */
+ __raw_writel(0x0, sar_ram_base + SAR_BACKUP_STATUS_OFFSET);
+ /* Enable GIC distributor and inteface on CPU0*/
+ gic_secondary_set(CPU0_ID, 1);
+ gic_dist_set(CPU0_ID, 1);
+ }
+
ret:
return 0;
}
@@ -189,6 +338,7 @@ ret:
int __init omap4_mpuss_init(void)
{
struct omap4_cpu_pm_info *pm_info;
+ u8 i;
if (omap_rev() == OMAP4430_REV_ES1_0) {
WARN(1, "Power Management not supported on OMAP4430 ES1.0\n");
@@ -234,6 +384,30 @@ int __init omap4_mpuss_init(void)
__raw_writel(virt_to_phys(omap4_cpu_resume),
sar_ram_base + CPU0_WAKEUP_NS_PA_ADDR_OFFSET);
+ mpuss_pd = pwrdm_lookup("mpu_pwrdm");
+ if (!mpuss_pd) {
+ pr_err("Failed to get lookup for MPUSS pwrdm\n");
+ return -ENODEV;
+ }
+
+ /*
+ * Find out how many interrupts are supported.
+ * OMAP4 supports max of 128 SPIs where as GIC can support
+ * up to 1020 interrupt sources.
+ */
+ max_spi_reg = __raw_readl(gic_dist_base_addr + GIC_DIST_CTR) & 0x1f;
+ max_spi_irq = max_spi_reg * 32;
+
+ /*
+ * Mark the PPI and SPI interrupts as non-secure.
+ * program the SAR locations for interrupt security registers to
+ * reflect the same.
+ */
+ sar_writel(GIC_ISR_NON_SECURE, ICDISR_CPU0_OFFSET, 0);
+ sar_writel(GIC_ISR_NON_SECURE, ICDISR_CPU1_OFFSET, 0);
+ for (i = 0; i < max_spi_reg; i++)
+ sar_writel(GIC_ISR_NON_SECURE, ICDISR_SPI_OFFSET, i);
+
return 0;
}
diff --git a/arch/arm/mach-omap2/omap4-sar-layout.h b/arch/arm/mach-omap2/omap4-sar-layout.h
index c4251db..0a19f49 100644
--- a/arch/arm/mach-omap2/omap4-sar-layout.h
+++ b/arch/arm/mach-omap2/omap4-sar-layout.h
@@ -30,6 +30,26 @@
#define CPU0_WAKEUP_NS_PA_ADDR_OFFSET 0xa04
#define CPU1_WAKEUP_NS_PA_ADDR_OFFSET 0xa08
+ /* GIC save restore offset from SAR_BANK3 */
+#define SAR_BACKUP_STATUS_OFFSET (SAR_BANK3_OFFSET + 0x500)
+#define SAR_SECURE_RAM_SIZE_OFFSET (SAR_BANK3_OFFSET + 0x504)
+#define SAR_SECRAM_SAVED_AT_OFFSET (SAR_BANK3_OFFSET + 0x508)
+#define ICDISR_CPU0_OFFSET (SAR_BANK3_OFFSET + 0x50c)
+#define ICDISR_CPU1_OFFSET (SAR_BANK3_OFFSET + 0x510)
+#define ICDISR_SPI_OFFSET (SAR_BANK3_OFFSET + 0x514)
+#define ICDISER_CPU0_OFFSET (SAR_BANK3_OFFSET + 0x524)
+#define ICDISER_CPU1_OFFSET (SAR_BANK3_OFFSET + 0x528)
+#define ICDISER_SPI_OFFSET (SAR_BANK3_OFFSET + 0x52c)
+#define ICDIPR_SFI_CPU0_OFFSET (SAR_BANK3_OFFSET + 0x53c)
+#define ICDIPR_PPI_CPU0_OFFSET (SAR_BANK3_OFFSET + 0x54c)
+#define ICDIPR_SFI_CPU1_OFFSET (SAR_BANK3_OFFSET + 0x550)
+#define ICDIPR_PPI_CPU1_OFFSET (SAR_BANK3_OFFSET + 0x560)
+#define ICDIPR_SPI_OFFSET (SAR_BANK3_OFFSET + 0x564)
+#define ICDIPTR_SPI_OFFSET (SAR_BANK3_OFFSET + 0x5e4)
+#define ICDICFR_OFFSET (SAR_BANK3_OFFSET + 0x664)
+#define SAR_BACKUP_STATUS_GIC_CPU0 0x1
+#define SAR_BACKUP_STATUS_GIC_CPU1 0x2
+
#ifndef __ASSEMBLER__
extern void __iomem *sar_ram_base;
--
1.6.0.4
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 09/17] omap4: pm: Add WakeupGen save/restore support
2011-02-19 10:42 [PATCH 00/17] omap4: pm: suspend, hotplug and cpuilde support Santosh Shilimkar
` (7 preceding siblings ...)
2011-02-19 10:42 ` [PATCH 08/17] omap4: pm: Add GIC save/restore support Santosh Shilimkar
@ 2011-02-19 10:42 ` Santosh Shilimkar
2011-03-02 22:34 ` Kevin Hilman
2011-02-19 10:42 ` [PATCH 10/17] omap4: pm: Add L2 cache lowpower support Santosh Shilimkar
` (8 subsequent siblings)
17 siblings, 1 reply; 55+ messages in thread
From: Santosh Shilimkar @ 2011-02-19 10:42 UTC (permalink / raw)
To: linux-arm-kernel
WakeupGen is lost only when device hits off-mode. Though the register
context is retained in MPUSS OFF/OSWR state, hardware recommondation is
to save/restore WakeupGen along with GIC to have consistent interrupt
state at both the blocks. The ROM code restore mechinism also does
restore of wakeupgen on mpu OFF/OSWR
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
---
arch/arm/mach-omap2/include/mach/omap-wakeupgen.h | 1 +
arch/arm/mach-omap2/omap-wakeupgen.c | 74 +++++++++++++++++++++
arch/arm/mach-omap2/omap4-mpuss-lowpower.c | 2 +
arch/arm/mach-omap2/omap4-sar-layout.h | 11 +++
4 files changed, 88 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/include/mach/omap-wakeupgen.h b/arch/arm/mach-omap2/include/mach/omap-wakeupgen.h
index f10d106..66f31c3 100644
--- a/arch/arm/mach-omap2/include/mach/omap-wakeupgen.h
+++ b/arch/arm/mach-omap2/include/mach/omap-wakeupgen.h
@@ -37,4 +37,5 @@
extern int __init omap_wakeupgen_init(void);
extern void omap_wakeupgen_irqmask_all(unsigned int cpu, unsigned int set);
+extern void omap_wakeupgen_save(void);
#endif
diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c
index e26a0ed..0f0a5ed 100644
--- a/arch/arm/mach-omap2/omap-wakeupgen.c
+++ b/arch/arm/mach-omap2/omap-wakeupgen.c
@@ -24,6 +24,9 @@
#include <asm/hardware/gic.h>
#include <mach/omap-wakeupgen.h>
+#include <mach/omap4-common.h>
+
+#include "omap4-sar-layout.h"
#define NR_BANKS 4
#define MAX_IRQS 128
@@ -54,6 +57,11 @@ static inline void cpu_writel(u32 val, u8 idx, u32 cpu)
(cpu * CPU_ENA_OFFSET) + (idx * 4));
}
+static inline void sar_writel(u32 val, u32 offset, u8 idx)
+{
+ __raw_writel(val, sar_ram_base + offset + (idx * 4));
+}
+
static void _wakeupgen_set_all(unsigned int cpu, unsigned int reg)
{
u8 i;
@@ -211,3 +219,69 @@ int __init omap_wakeupgen_init(void)
return 0;
}
+
+/**
+ * omap_wakeupgen_save() - WakeupGen context save function
+ *
+ * Save WakewupGen context in SAR BANK3. Restore is done by ROM code.
+ * WakeupGen is lost only when DEVICE hits OFF. Though the register
+ * context is retained in MPU OFF/OSWR state, hw recommondation is to
+ * save/restore WakeupGen along with GIC to have consistent interrupt
+ * state at both the blocks.
+ *
+ * During normal operation, WakeupGen delivers external interrupts
+ * directly to the GIC. When the CPU asserts StandbyWFI, indicating
+ * it wants to enter lowpower state, the Standby Controller checks
+ * with the WakeupGen unit using the idlereq/idleack handshake to make
+ * sure there is no incoming interrupts.
+ */
+
+void omap_wakeupgen_save(void)
+{
+ u8 i;
+ u32 val;
+
+ if (omap_rev() == OMAP4430_REV_ES1_0)
+ return;
+
+ for (i = 0; i < NR_BANKS; i++) {
+ /* Save the CPUx interrupt mask for IRQ 0 to 127 */
+ val = cpu_readl(i, 0);
+ sar_writel(val, WAKEUPGENENB_OFFSET_CPU0, i);
+ val = cpu_readl(i, 1);
+ sar_writel(val, WAKEUPGENENB_OFFSET_CPU1, i);
+
+ /*
+ * Disable the secure interrupts for CPUx. The restore
+ * code blindly restores secure and non-secure interrupt
+ * masks from SAR RAM. Secure interrupts are not suppose
+ * to be enabled from HLOS. So overwrite the SAR location
+ * so that the secure interrupt remains disabled.
+ */
+ sar_writel(0x0, WAKEUPGENENB_SECURE_OFFSET_CPU0, i);
+ sar_writel(0x0, WAKEUPGENENB_SECURE_OFFSET_CPU1, i);
+ }
+
+ /* Save AuxBoot* registers */
+ val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
+ __raw_writel(val, sar_ram_base + AUXCOREBOOT0_OFFSET);
+ val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
+ __raw_writel(val, sar_ram_base + AUXCOREBOOT1_OFFSET);
+
+ /* Save SyncReq generation logic */
+ val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
+ __raw_writel(val, sar_ram_base + AUXCOREBOOT0_OFFSET);
+ val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
+ __raw_writel(val, sar_ram_base + AUXCOREBOOT1_OFFSET);
+
+ /* Save SyncReq generation logic */
+ val = __raw_readl(wakeupgen_base + OMAP_PTMSYNCREQ_MASK);
+ __raw_writel(val, sar_ram_base + PTMSYNCREQ_MASK_OFFSET);
+ val = __raw_readl(wakeupgen_base + OMAP_PTMSYNCREQ_EN);
+ __raw_writel(val, sar_ram_base + PTMSYNCREQ_EN_OFFSET);
+
+ /* Set the Backup Bit Mask status */
+ val = __raw_readl(sar_ram_base + SAR_BACKUP_STATUS_OFFSET);
+ val |= SAR_BACKUP_STATUS_WAKEUPGEN;
+ __raw_writel(val, sar_ram_base + SAR_BACKUP_STATUS_OFFSET);
+}
diff --git a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
index 4140251..a30f19b 100644
--- a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
+++ b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
@@ -52,6 +52,7 @@
#include <plat/omap44xx.h>
#include <mach/omap4-common.h>
+#include <mach/omap-wakeupgen.h>
#include "omap4-sar-layout.h"
#include "pm.h"
@@ -290,6 +291,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
* GIC lost during MPU OFF and OSWR
*/
if (pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_OFF) {
+ omap_wakeupgen_save();
gic_save_context();
save_state = 3;
}
diff --git a/arch/arm/mach-omap2/omap4-sar-layout.h b/arch/arm/mach-omap2/omap4-sar-layout.h
index 0a19f49..5a815c4 100644
--- a/arch/arm/mach-omap2/omap4-sar-layout.h
+++ b/arch/arm/mach-omap2/omap4-sar-layout.h
@@ -52,6 +52,17 @@
#ifndef __ASSEMBLER__
+/* WakeUpGen save restore offset from OMAP44XX_SAR_RAM_BASE */
+#define WAKEUPGENENB_OFFSET_CPU0 (SAR_BANK3_OFFSET + 0x684)
+#define WAKEUPGENENB_SECURE_OFFSET_CPU0 (SAR_BANK3_OFFSET + 0x694)
+#define WAKEUPGENENB_OFFSET_CPU1 (SAR_BANK3_OFFSET + 0x6a4)
+#define WAKEUPGENENB_SECURE_OFFSET_CPU1 (SAR_BANK3_OFFSET + 0x6b4)
+#define AUXCOREBOOT0_OFFSET (SAR_BANK3_OFFSET + 0x6c4)
+#define AUXCOREBOOT1_OFFSET (SAR_BANK3_OFFSET + 0x6c8)
+#define PTMSYNCREQ_MASK_OFFSET (SAR_BANK3_OFFSET + 0x6cc)
+#define PTMSYNCREQ_EN_OFFSET (SAR_BANK3_OFFSET + 0x6d0)
+#define SAR_BACKUP_STATUS_WAKEUPGEN 0x10
+
extern void __iomem *sar_ram_base;
#endif
--
1.6.0.4
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 10/17] omap4: pm: Add L2 cache lowpower support
2011-02-19 10:42 [PATCH 00/17] omap4: pm: suspend, hotplug and cpuilde support Santosh Shilimkar
` (8 preceding siblings ...)
2011-02-19 10:42 ` [PATCH 09/17] omap4: pm: Add WakeupGen " Santosh Shilimkar
@ 2011-02-19 10:42 ` Santosh Shilimkar
2011-03-02 22:36 ` Kevin Hilman
2011-02-19 10:42 ` [PATCH 11/17] omap4: suspend: Add MPUSS RET and OFF support Santosh Shilimkar
` (7 subsequent siblings)
17 siblings, 1 reply; 55+ messages in thread
From: Santosh Shilimkar @ 2011-02-19 10:42 UTC (permalink / raw)
To: linux-arm-kernel
When MPUSS hits off-mode e, L2 cache is lost. This patch adds L2X0
necessary maintenance operations and context restoration in the
low power code.
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
---
arch/arm/mach-omap2/omap4-mpuss-lowpower.c | 11 +++++
arch/arm/mach-omap2/omap4-sar-layout.h | 2 +
arch/arm/mach-omap2/sleep44xx.S | 64 ++++++++++++++++++++++++++++
3 files changed, 77 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
index a30f19b..bff768f 100644
--- a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
+++ b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
@@ -49,6 +49,7 @@
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/hardware/gic.h>
+#include <asm/hardware/cache-l2x0.h>
#include <plat/omap44xx.h>
#include <mach/omap4-common.h>
@@ -341,6 +342,7 @@ int __init omap4_mpuss_init(void)
{
struct omap4_cpu_pm_info *pm_info;
u8 i;
+ u32 val;
if (omap_rev() == OMAP4430_REV_ES1_0) {
WARN(1, "Power Management not supported on OMAP4430 ES1.0\n");
@@ -410,6 +412,15 @@ int __init omap4_mpuss_init(void)
for (i = 0; i < max_spi_reg; i++)
sar_writel(GIC_ISR_NON_SECURE, ICDISR_SPI_OFFSET, i);
+#ifdef CONFIG_CACHE_L2X0
+ /*
+ * Save the L2X0 AUXCTRL value to SAR memory. Its used to
+ * in every restore patch MPUSS OFF path.
+ */
+ val = __raw_readl(l2cache_base + L2X0_AUX_CTRL);
+ __raw_writel(val, sar_ram_base + L2X0_AUXCTRL_OFFSET);
+#endif
+
return 0;
}
diff --git a/arch/arm/mach-omap2/omap4-sar-layout.h b/arch/arm/mach-omap2/omap4-sar-layout.h
index 5a815c4..eb2d53b 100644
--- a/arch/arm/mach-omap2/omap4-sar-layout.h
+++ b/arch/arm/mach-omap2/omap4-sar-layout.h
@@ -25,6 +25,8 @@
#define MMU_OFFSET 0xd00
#define SCU_OFFSET0 0xd20
#define SCU_OFFSET1 0xd24
+#define L2X0_OFFSET 0xd28
+#define L2X0_AUXCTRL_OFFSET 0xd2c
/* CPUx Wakeup Non-Secure Physical Address offsets in SAR_BANK3 */
#define CPU0_WAKEUP_NS_PA_ADDR_OFFSET 0xa04
diff --git a/arch/arm/mach-omap2/sleep44xx.S b/arch/arm/mach-omap2/sleep44xx.S
index bb42a7a..e683f78 100644
--- a/arch/arm/mach-omap2/sleep44xx.S
+++ b/arch/arm/mach-omap2/sleep44xx.S
@@ -13,6 +13,7 @@
#include <asm/system.h>
#include <asm/smp_scu.h>
#include <asm/memory.h>
+#include <asm/hardware/cache-l2x0.h>
#include <plat/omap44xx.h>
#include <mach/omap4-common.h>
@@ -56,6 +57,7 @@ ENTRY(omap4_cpu_suspend)
beq do_WFI @ Nothing to save, jump to WFI
ldr r8, =sar_ram_base
ldr r8, [r8]
+ str r1, [r8, #L2X0_OFFSET] @ Store save state
ands r0, r0, #0x0f
orreq r8, r8, #CPU0_SAVE_OFFSET
orrne r8, r8, #CPU1_SAVE_OFFSET
@@ -131,6 +133,42 @@ ENTRY(omap4_cpu_suspend)
ldr r0, =scu_base
ldr r0, [r0]
bl scu_power_mode
+ isb
+ dsb
+
+#ifdef CONFIG_CACHE_L2X0
+ /*
+ * Clean and invalidate the L2 cache.
+ * Common cache-l2x0.c functions can't be used here since it
+ * uses spinlocks. We are out of coherency here with data cache
+ * disabled. The spinlock implementation uses exclusive load/store
+ * instruction which can fail without data cache being enabled.
+ * OMAP4 hardware doesn't support exclusive monitor which can
+ * overcome exclusive access issue. Because of this, CPU can
+ * lead to deadlock.
+ */
+l2x_clean_inv:
+ ldr r8, =sar_ram_base
+ ldr r8, [r8]
+ ldr r0, [r8, #L2X0_OFFSET]
+ cmp r0, #3
+ bne do_WFI
+ ldr r2, =l2cache_base
+ ldr r2, [r2]
+ mov r0, #0xff
+ str r0, [r2, #L2X0_CLEAN_WAY]
+wait:
+ ldr r0, [r2, #L2X0_CLEAN_WAY]
+ ands r0, r0, #0xff
+ bne wait
+l2x_sync:
+ mov r0, #0x0
+ str r0, [r2, #L2X0_CACHE_SYNC]
+sync:
+ ldr r0, [r2, #L2X0_CACHE_SYNC]
+ ands r0, r0, #0x1
+ bne sync
+#endif
do_WFI:
/*
@@ -193,6 +231,32 @@ ENDPROC(omap4_cpu_suspend)
*/
ENTRY(omap4_cpu_resume)
+#ifdef CONFIG_CACHE_L2X0
+ /*
+ * Restore the L2 AUXCTRL and enable the L2 cache.
+ * 0x109 = Program the L2X0 AUXCTRL
+ * 0x102 = Enable the L2 using L2X0 CTRL
+ * register r0 contains value to be programmed.
+ * L2 cache is already invalidate by ROM code as part
+ * of MPUSS OFF wakeup path.
+ */
+ ldr r2, =OMAP44XX_L2CACHE_BASE
+ ldr r0, [r2, #L2X0_CTRL]
+ and r0, #0x0f
+ cmp r0, #1
+ beq skip_l2en @ Skip if already enabled
+ ldr r3, =OMAP44XX_SAR_RAM_BASE
+ ldr r0, [r3, #L2X0_AUXCTRL_OFFSET]
+ ldr r12, =0x109 @ Setup L2 AUXCTRL value
+ dsb
+ smc #0
+ mov r0, #0x1
+ ldr r12, =0x102 @ Enable L2 Cache controller
+ dsb
+ smc #0
+skip_l2en:
+#endif
+
/*
* Check the wakeup cpuid and use appropriate
* SAR BANK location for context restore.
--
1.6.0.4
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 11/17] omap4: suspend: Add MPUSS RET and OFF support
2011-02-19 10:42 [PATCH 00/17] omap4: pm: suspend, hotplug and cpuilde support Santosh Shilimkar
` (9 preceding siblings ...)
2011-02-19 10:42 ` [PATCH 10/17] omap4: pm: Add L2 cache lowpower support Santosh Shilimkar
@ 2011-02-19 10:42 ` Santosh Shilimkar
2011-03-02 22:45 ` Kevin Hilman
2011-02-19 10:42 ` [PATCH 12/17] omap4: pm-debug: Add wakeup timer and debug counters Santosh Shilimkar
` (6 subsequent siblings)
17 siblings, 1 reply; 55+ messages in thread
From: Santosh Shilimkar @ 2011-02-19 10:42 UTC (permalink / raw)
To: linux-arm-kernel
This patch adds MPUSS(MPU Sub System) RET and OFF mode support
to suspend path. For both MPUSS RET and OFF support, CPUs are
programmed to OFF state.
Only MPUSS RET and OFF supported at this point of time. CORE RET
will be added subsequently.
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
---
arch/arm/mach-omap2/omap4-mpuss-lowpower.c | 8 ++-
arch/arm/mach-omap2/pm-debug.c | 2 +
arch/arm/mach-omap2/pm.h | 1 +
arch/arm/mach-omap2/pm44xx.c | 88 ++++++++++++++++++++++++++--
4 files changed, 93 insertions(+), 6 deletions(-)
diff --git a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
index bff768f..ab2e101 100644
--- a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
+++ b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
@@ -25,7 +25,7 @@
* ON(Inactive) OFF ON(Inactive)
* OFF OFF CSWR
* OFF OFF OSWR (*TBD)
- * OFF OFF OFF* (*TBD)
+ * OFF OFF OFF
* ----------------------------------------------
*
* Note: CPU0 is the master core and it is the last CPU to go down
@@ -291,6 +291,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
* Check MPUSS next state and save GIC if needed
* GIC lost during MPU OFF and OSWR
*/
+ pwrdm_clear_all_prev_pwrst(mpuss_pd);
if (pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_OFF) {
omap_wakeupgen_save();
gic_save_context();
@@ -357,6 +358,8 @@ int __init omap4_mpuss_init(void)
pr_err("Lookup failed for CPU0 pwrdm\n");
return -ENODEV;
}
+ /* Clear CPU previous power domain state */
+ pwrdm_clear_all_prev_pwrst(pm_info->pwrdm);
/* Clear CPU previous power domain state */
pwrdm_clear_all_prev_pwrst(pm_info->pwrdm);
@@ -394,6 +397,9 @@ int __init omap4_mpuss_init(void)
return -ENODEV;
}
+ /* Clear CPU previous power domain state */
+ pwrdm_clear_all_prev_pwrst(mpuss_pd);
+
/*
* Find out how many interrupts are supported.
* OMAP4 supports max of 128 SPIs where as GIC can support
diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index 125f565..9b46b3e 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -588,6 +588,8 @@ static int option_set(void *data, u64 val)
omap_pm_disable_off_mode();
if (cpu_is_omap34xx())
omap3_pm_off_mode_enable(val);
+ else if (cpu_is_omap44xx())
+ omap4_pm_off_mode_enable(val);
}
return 0;
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 1c1b0ab..f557407 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -17,6 +17,7 @@
extern void *omap3_secure_ram_storage;
extern void omap3_pm_off_mode_enable(int);
+extern void omap4_pm_off_mode_enable(int);
extern void omap_sram_idle(void);
extern int omap3_can_sleep(void);
extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index 9a9dc41..f527e33 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -1,8 +1,9 @@
/*
* OMAP4 Power Management Routines
*
- * Copyright (C) 2010 Texas Instruments, Inc.
+ * Copyright (C) 2010-2011 Texas Instruments, Inc.
* Rajendra Nayak <rnayak@ti.com>
+ * Santosh Shilimkar <santosh.shilimkar@ti.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -21,6 +22,7 @@
#include "powerdomain.h"
#include "clockdomain.h"
+#include "pm.h"
struct power_state {
struct powerdomain *pwrdm;
@@ -36,7 +38,50 @@ static LIST_HEAD(pwrst_list);
#ifdef CONFIG_SUSPEND
static int omap4_pm_suspend(void)
{
- do_wfi();
+ struct power_state *pwrst;
+ int state, ret = 0;
+ u32 cpu_id = smp_processor_id();
+
+ /* Save current powerdomain state */
+ list_for_each_entry(pwrst, &pwrst_list, node) {
+ pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm);
+ }
+
+ /* Set targeted power domain states by suspend */
+ list_for_each_entry(pwrst, &pwrst_list, node) {
+ /* FIXME: Remove this check when CORE retention is supported */
+ if (!strcmp(pwrst->pwrdm->name, "mpu_pwrdm"))
+ omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
+ }
+
+ /*
+ * For MPUSS to hit power domain retention(CSWR or OSWR),
+ * CPU0 and CPU1 power domain needs to be in OFF or DORMANT
+ * state. For MPUSS to reach off-mode. CPU0 and CPU1 power domain
+ * should be in off state.
+ * Only master CPU followes suspend path. All other CPUs follow
+ * cpu-hotplug path in system wide suspend. On OMAP4, CPU power
+ * domain CSWR is not supported by hardware.
+ * More details can be found in OMAP4430 TRM section 4.3.4.2.
+ */
+ omap4_enter_lowpower(cpu_id, PWRDM_POWER_OFF);
+
+ /* Restore next powerdomain state */
+ list_for_each_entry(pwrst, &pwrst_list, node) {
+ state = pwrdm_read_prev_pwrst(pwrst->pwrdm);
+ if (state > pwrst->next_state) {
+ pr_info("Powerdomain (%s) didn't enter "
+ "target state %d\n",
+ pwrst->pwrdm->name, pwrst->next_state);
+ ret = -1;
+ }
+ omap_set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state);
+ }
+ if (ret)
+ pr_err("Could not enter target state in pm_suspend\n");
+ else
+ pr_err("Successfully put all powerdomains to target state\n");
+
return 0;
}
@@ -91,7 +136,6 @@ static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
return 0;
}
-
static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
{
struct power_state *pwrst;
@@ -99,14 +143,48 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
if (!pwrdm->pwrsts)
return 0;
+ /*
+ * Skip CPU0 and CPU1 power domains. CPU1 is programmed
+ * through hotplug path and CPU0 explicitly programmed
+ * further down in the code path
+ */
+ if ((!strcmp(pwrdm->name, "cpu0_pwrdm")) ||
+ (!strcmp(pwrdm->name, "cpu1_pwrdm")))
+ return 0;
+
pwrst = kmalloc(sizeof(struct power_state), GFP_ATOMIC);
if (!pwrst)
return -ENOMEM;
pwrst->pwrdm = pwrdm;
- pwrst->next_state = PWRDM_POWER_ON;
+
+ /* FIXME: Remove this check when core retention is supported */
+ if (!strcmp(pwrst->pwrdm->name, "mpu_pwrdm"))
+ pwrst->next_state = PWRDM_POWER_RET;
+ else
+ pwrst->next_state = PWRDM_POWER_ON;
+
list_add(&pwrst->node, &pwrst_list);
- return pwrdm_set_next_pwrst(pwrst->pwrdm, pwrst->next_state);
+ return omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
+}
+
+void omap4_pm_off_mode_enable(int enable)
+{
+ struct power_state *pwrst;
+ u32 state;
+
+ if (enable)
+ state = PWRDM_POWER_OFF;
+ else
+ state = PWRDM_POWER_RET;
+
+ list_for_each_entry(pwrst, &pwrst_list, node) {
+ /* FIXME: Remove this check when core retention is supported */
+ if (!strcmp(pwrst->pwrdm->name, "mpu_pwrdm")) {
+ pwrst->next_state = state;
+ omap_set_pwrdm_state(pwrst->pwrdm, state);
+ }
+ }
}
/**
--
1.6.0.4
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 12/17] omap4: pm-debug: Add wakeup timer and debug counters
2011-02-19 10:42 [PATCH 00/17] omap4: pm: suspend, hotplug and cpuilde support Santosh Shilimkar
` (10 preceding siblings ...)
2011-02-19 10:42 ` [PATCH 11/17] omap4: suspend: Add MPUSS RET and OFF support Santosh Shilimkar
@ 2011-02-19 10:42 ` Santosh Shilimkar
2011-03-02 22:51 ` Kevin Hilman
2011-02-19 10:42 ` [PATCH 13/17] omap4: cpuidle: Basic CPUidle support Santosh Shilimkar
` (5 subsequent siblings)
17 siblings, 1 reply; 55+ messages in thread
From: Santosh Shilimkar @ 2011-02-19 10:42 UTC (permalink / raw)
To: linux-arm-kernel
This patch adds configurable wakeup timer support in suspend. Also
for statistics pm counter support is added.
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
---
arch/arm/mach-omap2/omap4-mpuss-lowpower.c | 8 ++++++++
arch/arm/mach-omap2/pm-debug.c | 6 ++++--
arch/arm/mach-omap2/pm44xx.c | 5 +++++
3 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
index ab2e101..5e0141e 100644
--- a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
+++ b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
@@ -287,6 +287,10 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
if (cpu)
goto cpu_prepare;
+#ifdef CONFIG_PM_DEBUG
+ pwrdm_pre_transition();
+#endif
+
/*
* Check MPUSS next state and save GIC if needed
* GIC lost during MPU OFF and OSWR
@@ -332,6 +336,10 @@ cpu_prepare:
gic_dist_set(CPU0_ID, 1);
}
+#ifdef CONFIG_PM_DEBUG
+ pwrdm_post_transition();
+#endif
+
ret:
return 0;
}
diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index 9b46b3e..7d6dd5b 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -606,9 +606,11 @@ static int __init pm_dbg_init(void)
if (pm_dbg_init_done)
return 0;
- if (cpu_is_omap34xx())
+ if (cpu_is_omap34xx()) {
pm_dbg_reg_modules = omap3_pm_reg_modules;
- else {
+ } else if (cpu_is_omap44xx()) {
+ /* Allow pm_dbg_init on OMAP4. */
+ } else {
printk(KERN_ERR "%s: only OMAP3 supported\n", __func__);
return -ENODEV;
}
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index f527e33..8e57b42 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -42,6 +42,11 @@ static int omap4_pm_suspend(void)
int state, ret = 0;
u32 cpu_id = smp_processor_id();
+ /* Wakeup timer from suspend */
+ if (wakeup_timer_seconds || wakeup_timer_milliseconds)
+ omap2_pm_wakeup_on_timer(wakeup_timer_seconds,
+ wakeup_timer_milliseconds);
+
/* Save current powerdomain state */
list_for_each_entry(pwrst, &pwrst_list, node) {
pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm);
--
1.6.0.4
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 13/17] omap4: cpuidle: Basic CPUidle support
2011-02-19 10:42 [PATCH 00/17] omap4: pm: suspend, hotplug and cpuilde support Santosh Shilimkar
` (11 preceding siblings ...)
2011-02-19 10:42 ` [PATCH 12/17] omap4: pm-debug: Add wakeup timer and debug counters Santosh Shilimkar
@ 2011-02-19 10:42 ` Santosh Shilimkar
2011-03-02 22:55 ` Kevin Hilman
2011-02-19 10:42 ` [PATCH 14/17] omap4: cpuidle: Add MPUSS RET OFF states Santosh Shilimkar
` (4 subsequent siblings)
17 siblings, 1 reply; 55+ messages in thread
From: Santosh Shilimkar @ 2011-02-19 10:42 UTC (permalink / raw)
To: linux-arm-kernel
From: Rajendra Nayak <rnayak@ti.com>
The patch adds a basic CPUidle driver for OMAP4. Just
one C state is registered for both CPU cores which
does a wfi.
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
---
arch/arm/mach-omap2/Makefile | 3 +-
arch/arm/mach-omap2/cpuidle44xx.c | 165 +++++++++++++++++++++++++++++++++++++
arch/arm/mach-omap2/pm.h | 1 +
arch/arm/mach-omap2/pm44xx.c | 2 +
4 files changed, 170 insertions(+), 1 deletions(-)
create mode 100644 arch/arm/mach-omap2/cpuidle44xx.c
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 5d94f7e..2b4fe44 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -64,7 +64,8 @@ obj-$(CONFIG_ARCH_OMAP2) += sleep24xx.o pm_bus.o voltage.o
obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o voltage.o \
cpuidle34xx.o pm_bus.o
obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o voltage.o pm_bus.o \
- omap4-mpuss-lowpower.o sleep44xx.o
+ omap4-mpuss-lowpower.o sleep44xx.o \
+ cpuidle44xx.o
obj-$(CONFIG_PM_DEBUG) += pm-debug.o
obj-$(CONFIG_OMAP_SMARTREFLEX) += sr_device.o smartreflex.o
obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3) += smartreflex-class3.o
diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c
new file mode 100644
index 0000000..6c3c69d
--- /dev/null
+++ b/arch/arm/mach-omap2/cpuidle44xx.c
@@ -0,0 +1,165 @@
+/*
+ * OMAP4 CPU IDLE Routines
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/sched.h>
+#include <linux/cpuidle.h>
+
+#include <asm/proc-fns.h>
+
+#include <mach/omap4-common.h>
+
+#include "pm.h"
+
+#ifdef CONFIG_CPU_IDLE
+
+#define OMAP4_MAX_STATES 1
+/* C1 - CPUx wfi + MPU inactive + CORE inactive */
+#define OMAP4_STATE_C1 0
+
+struct omap4_processor_cx {
+ u8 valid;
+ u8 type;
+ u32 sleep_latency;
+ u32 wakeup_latency;
+ u32 cpu0_state;
+ u32 cpu1_state;
+ u32 mpu_state;
+ u32 core_state;
+ u32 threshold;
+ u32 flags;
+};
+
+struct omap4_processor_cx omap4_power_states[OMAP4_MAX_STATES];
+struct omap4_processor_cx current_cx_state;
+
+static struct cpuidle_params cpuidle_params_table[] = {
+ /* C1 */
+ {1, 2, 2, 5},
+};
+
+/**
+ * omap4_enter_idle - Programs OMAP4 to enter the specified state
+ * @dev: cpuidle device
+ * @state: The target state to be programmed
+ *
+ * Called from the CPUidle framework to program the device to the
+ * specified low power state selected by the governor.
+ * Returns the amount of time spent in the low power state.
+ */
+static int omap4_enter_idle(struct cpuidle_device *dev,
+ struct cpuidle_state *state)
+{
+ struct timespec ts_preidle, ts_postidle, ts_idle;
+
+ /* Used to keep track of the total time in idle */
+ getnstimeofday(&ts_preidle);
+
+ local_irq_disable();
+ local_fiq_disable();
+
+ cpu_do_idle();
+
+ getnstimeofday(&ts_postidle);
+ ts_idle = timespec_sub(ts_postidle, ts_preidle);
+
+ local_irq_enable();
+ local_fiq_enable();
+
+ return ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * USEC_PER_SEC;
+}
+
+DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev);
+
+/**
+ * omap4_init_power_states - Initialises the OMAP4 specific C states.
+ *
+ * Below is the desciption of each C state.
+ * C1 : CPUx wfi + MPU inative + Core inactive
+ */
+void omap_init_power_states(void)
+{
+ /* C1 . CPUx wfi + MPU inactive + Core inactive */
+ omap4_power_states[OMAP4_STATE_C1].valid =
+ cpuidle_params_table[OMAP4_STATE_C1].valid;
+ omap4_power_states[OMAP4_STATE_C1].type = OMAP4_STATE_C1;
+ omap4_power_states[OMAP4_STATE_C1].sleep_latency =
+ cpuidle_params_table[OMAP4_STATE_C1].sleep_latency;
+ omap4_power_states[OMAP4_STATE_C1].wakeup_latency =
+ cpuidle_params_table[OMAP4_STATE_C1].wake_latency;
+ omap4_power_states[OMAP4_STATE_C1].threshold =
+ cpuidle_params_table[OMAP4_STATE_C1].threshold;
+ omap4_power_states[OMAP4_STATE_C1].mpu_state = PWRDM_POWER_ON;
+ omap4_power_states[OMAP4_STATE_C1].core_state = PWRDM_POWER_ON;
+ omap4_power_states[OMAP4_STATE_C1].flags = CPUIDLE_FLAG_TIME_VALID;
+
+}
+
+struct cpuidle_driver omap4_idle_driver = {
+ .name = "omap4_idle",
+ .owner = THIS_MODULE,
+};
+
+/**
+ * omap4_idle_init - Init routine for OMAP4 idle
+ *
+ * Registers the OMAP4 specific cpuidle driver with the cpuidle
+ * framework with the valid set of states.
+ */
+int __init omap4_idle_init(void)
+{
+ int cpu_id, i, count = 0;
+ struct omap4_processor_cx *cx;
+ struct cpuidle_state *state;
+ struct cpuidle_device *dev;
+
+ omap_init_power_states();
+ cpuidle_register_driver(&omap4_idle_driver);
+
+ for_each_cpu(cpu_id, cpu_online_mask) {
+ pr_err("CPUidle for CPU%d registered\n", cpu_id);
+ dev = &per_cpu(omap4_idle_dev, cpu_id);
+ dev->cpu = cpu_id;
+ count = 0;
+ for (i = OMAP4_STATE_C1; i < OMAP4_MAX_STATES; i++) {
+ cx = &omap4_power_states[i];
+ state = &dev->states[count];
+
+ if (!cx->valid)
+ continue;
+ cpuidle_set_statedata(state, cx);
+ state->exit_latency = cx->sleep_latency +
+ cx->wakeup_latency;
+ state->target_residency = cx->threshold;
+ state->flags = cx->flags;
+ state->enter = omap4_enter_idle;
+ sprintf(state->name, "C%d", count+1);
+ count++;
+ }
+
+ if (!count)
+ return -EINVAL;
+ dev->state_count = count;
+
+ if (cpuidle_register_device(dev)) {
+ pr_err("%s: CPUidle register device failed\n",
+ __func__);
+ return -EIO;
+ }
+ }
+
+ return 0;
+}
+#else
+int __init omap4_idle_init(void)
+{
+ return 0;
+}
+#endif /* CONFIG_CPU_IDLE */
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index f557407..ce848b0 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -22,6 +22,7 @@ extern void omap_sram_idle(void);
extern int omap3_can_sleep(void);
extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
extern int omap3_idle_init(void);
+extern int omap4_idle_init(void);
#if defined(CONFIG_PM_OPP)
extern int omap3_opp_init(void);
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index 8e57b42..628242d 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -230,6 +230,8 @@ static int __init omap4_pm_init(void)
suspend_set_ops(&omap_pm_ops);
#endif /* CONFIG_SUSPEND */
+ omap4_idle_init();
+
err2:
return ret;
}
--
1.6.0.4
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 14/17] omap4: cpuidle: Add MPUSS RET OFF states
2011-02-19 10:42 [PATCH 00/17] omap4: pm: suspend, hotplug and cpuilde support Santosh Shilimkar
` (12 preceding siblings ...)
2011-02-19 10:42 ` [PATCH 13/17] omap4: cpuidle: Basic CPUidle support Santosh Shilimkar
@ 2011-02-19 10:42 ` Santosh Shilimkar
2011-02-21 10:19 ` Jean Pihet
2011-03-02 23:32 ` Kevin Hilman
2011-02-19 10:42 ` [PATCH 15/17] omap4: cpuidle: Switch to gptimer from twd in deeper C-states Santosh Shilimkar
` (3 subsequent siblings)
17 siblings, 2 replies; 55+ messages in thread
From: Santosh Shilimkar @ 2011-02-19 10:42 UTC (permalink / raw)
To: linux-arm-kernel
This patch adds MPUSS low power states in cpuidle.
C1 - CPU0 ON + CPU1 ON/OFF + MPU ON + CORE ON
C2 - CPU0 ON + CPU1 OFF + MPU ON + CORE ON
C3 - CPU0 OFF + CPU1 OFF + MPU CSWR + CORE ON
C4 - CPU0 OFF + CPU1 OFF + MPU OFF + CORE ON
MPU OSWR isn't supported yet. To support OSWR, power domain context
registers needs to be managed which are not supported yet. A patch
to address this was submitted but it's not ready for merge yet because
it was not addressing all OMAP4 power domain context registers.
More info on this issue:
http://www.mail-archive.com/linux-omap at vger.kernel.org/msg38667.html
OMAP4 powerdomain INACTIVE support is also dropped because of inconsistency
of it with OMAP3. More information on this thread.
http://www.spinics.net/lists/linux-omap/msg45370.html
CORE low power states and associated latencies will be updated as part
along with chip retention support.
On OMAP4 because of hardware constraints, no low power states are
targeted when both CPUs are online and in SMP mode. The low power
states are attempted only when secondary CPU gets offline to OFF
through hotplug infrastructure.
Thanks to Nicole Chalhoub <n-chalhoub@ti.com> for doing exhaustive
C-state latency profiling.
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
---
arch/arm/mach-omap2/cpuidle44xx.c | 190 ++++++++++++++++++++++++++++++++++---
1 files changed, 176 insertions(+), 14 deletions(-)
diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c
index 6c3c69d..aa1584e 100644
--- a/arch/arm/mach-omap2/cpuidle44xx.c
+++ b/arch/arm/mach-omap2/cpuidle44xx.c
@@ -3,6 +3,7 @@
*
* Copyright (C) 2011 Texas Instruments, Inc.
* Rajendra Nayak <rnayak@ti.com>
+ * Santosh Shilimkar <santosh.shilimkar@ti.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -17,12 +18,21 @@
#include <mach/omap4-common.h>
#include "pm.h"
+#include "prm.h"
#ifdef CONFIG_CPU_IDLE
-#define OMAP4_MAX_STATES 1
-/* C1 - CPUx wfi + MPU inactive + CORE inactive */
+#define CPUIDLE_FLAG_CHECK_BM 0x10000 /* use omap4_enter_idle_bm() */
+#define OMAP4_MAX_STATES 4
+
+/* C1 - CPU0 ON + CPU1 ON/OFF + MPU ON + CORE ON */
#define OMAP4_STATE_C1 0
+/* C2 - CPU0 ON + CPU1 OFF + MPU ON + CORE ON */
+#define OMAP4_STATE_C2 1
+/* C3 - CPU0 OFF + CPU1 OFF + MPU CSWR + CORE ON */
+#define OMAP4_STATE_C3 2
+/* C4 - CPU0 OFF + CPU1 OFF + MPU OFF + CORE ON */
+#define OMAP4_STATE_C4 3
struct omap4_processor_cx {
u8 valid;
@@ -32,19 +42,44 @@ struct omap4_processor_cx {
u32 cpu0_state;
u32 cpu1_state;
u32 mpu_state;
+ u32 mpu_logic_state;
u32 core_state;
+ u32 core_logic_state;
u32 threshold;
u32 flags;
+ const char *desc;
};
-struct omap4_processor_cx omap4_power_states[OMAP4_MAX_STATES];
-struct omap4_processor_cx current_cx_state;
+static struct omap4_processor_cx omap4_power_states[OMAP4_MAX_STATES];
+static struct powerdomain *mpu_pd, *cpu1_pd, *core_pd;
+/*
+ * FIXME: Full latenecy numbers needs to be updated as part of
+ * cpuidle CORE retention support.
+ * Currently only MPUSS latency numbers are added based on
+ * measurements done internally. The numbers for MPUSS are
+ * not board dependent and hence set directly here instead of
+ * passing it from board files.
+ */
static struct cpuidle_params cpuidle_params_table[] = {
- /* C1 */
- {1, 2, 2, 5},
+ /* C1 - CPU0 WFI + CPU1 ON/OFF + MPU ON + CORE ON */
+ {1, 2, 2, 5},
+ /* C2 - CPU0 ON + CPU1 OFF + MPU ON + CORE ON */
+ {1, 140, 160, 300},
+ /* C3 - CPU0 OFF + CPU1 OFF + MPU CSWR + CORE ON */
+ {1, 200, 300, 700},
+ /* C4 - CPU0 OFF + CPU1 OFF + MPU OFF + CORE ON */
+ {1, 1400, 600, 5000},
};
+DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev);
+
+static int omap4_idle_bm_check(void)
+{
+ /* FIXME: Populate this with CORE retention support */
+ return 0;
+}
+
/**
* omap4_enter_idle - Programs OMAP4 to enter the specified state
* @dev: cpuidle device
@@ -57,7 +92,9 @@ static struct cpuidle_params cpuidle_params_table[] = {
static int omap4_enter_idle(struct cpuidle_device *dev,
struct cpuidle_state *state)
{
+ struct omap4_processor_cx *cx = cpuidle_get_statedata(state);
struct timespec ts_preidle, ts_postidle, ts_idle;
+ u32 cpu1_state;
/* Used to keep track of the total time in idle */
getnstimeofday(&ts_preidle);
@@ -65,28 +102,74 @@ static int omap4_enter_idle(struct cpuidle_device *dev,
local_irq_disable();
local_fiq_disable();
- cpu_do_idle();
+ /*
+ * Special hardware/software considerations:
+ * 1. Do only WFI for secondary CPU(non-boot - CPU1).
+ * Secondary cores are taken down only via hotplug path.
+ * 2. Do only a WFI as long as in SMP mode.
+ * 3. Continue to do only WFI till CPU1 hits OFF state.
+ * This is necessary to honour hardware recommondation
+ * of triggeing all the possible low power modes once CPU1 is
+ * out of coherency and in OFF mode.
+ * Update dev->last_state so that governor stats reflects right
+ * data.
+ */
+ cpu1_state = pwrdm_read_pwrst(cpu1_pd);
+ if ((dev->cpu) || (num_online_cpus() > 1) ||
+ (cpu1_state != PWRDM_POWER_OFF)) {
+ dev->last_state = dev->safe_state;
+ cpu_do_idle();
+ goto return_sleep_time;
+ }
+ pwrdm_set_logic_retst(mpu_pd, cx->mpu_logic_state);
+ omap_set_pwrdm_state(mpu_pd, cx->mpu_state);
+ pwrdm_set_logic_retst(core_pd, cx->core_logic_state);
+ omap_set_pwrdm_state(core_pd, cx->core_state);
+
+ omap4_enter_lowpower(dev->cpu, cx->cpu0_state);
+
+return_sleep_time:
getnstimeofday(&ts_postidle);
ts_idle = timespec_sub(ts_postidle, ts_preidle);
local_irq_enable();
local_fiq_enable();
+
return ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * USEC_PER_SEC;
}
-DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev);
+/**
+ * omap4_enter_idle_bm - Checks for any bus activity
+ * @dev: cpuidle device
+ * @state: The target state to be programmed
+ *
+ * Used for C states with CPUIDLE_FLAG_CHECK_BM flag set. This
+ * function checks for any pending activity and then programs the
+ * device to the specified or a safer state.
+ */
+static int omap4_enter_idle_bm(struct cpuidle_device *dev,
+ struct cpuidle_state *state)
+{
+ if ((state->flags & CPUIDLE_FLAG_CHECK_BM) && omap4_idle_bm_check()) {
+ BUG_ON(!dev->safe_state);
+ state = dev->safe_state;
+ }
+
+ dev->last_state = state;
+ return omap4_enter_idle(dev, state);
+}
/**
* omap4_init_power_states - Initialises the OMAP4 specific C states.
*
- * Below is the desciption of each C state.
- * C1 : CPUx wfi + MPU inative + Core inactive
*/
-void omap_init_power_states(void)
+void omap4_init_power_states(void)
{
- /* C1 . CPUx wfi + MPU inactive + Core inactive */
+ /*
+ * C1 - CPU0 WFI + CPU1 OFF + MPU ON + CORE ON
+ */
omap4_power_states[OMAP4_STATE_C1].valid =
cpuidle_params_table[OMAP4_STATE_C1].valid;
omap4_power_states[OMAP4_STATE_C1].type = OMAP4_STATE_C1;
@@ -96,9 +179,80 @@ void omap_init_power_states(void)
cpuidle_params_table[OMAP4_STATE_C1].wake_latency;
omap4_power_states[OMAP4_STATE_C1].threshold =
cpuidle_params_table[OMAP4_STATE_C1].threshold;
+ omap4_power_states[OMAP4_STATE_C1].cpu0_state = PWRDM_POWER_ON;
+ omap4_power_states[OMAP4_STATE_C1].cpu1_state = PWRDM_POWER_OFF;
omap4_power_states[OMAP4_STATE_C1].mpu_state = PWRDM_POWER_ON;
+ omap4_power_states[OMAP4_STATE_C1].mpu_logic_state = PWRDM_POWER_RET;
omap4_power_states[OMAP4_STATE_C1].core_state = PWRDM_POWER_ON;
+ omap4_power_states[OMAP4_STATE_C1].core_logic_state = PWRDM_POWER_RET;
omap4_power_states[OMAP4_STATE_C1].flags = CPUIDLE_FLAG_TIME_VALID;
+ omap4_power_states[OMAP4_STATE_C1].desc = "MPU ON + CORE ON";
+
+ /*
+ * C2 - CPU0 ON + CPU1 OFF + MPU ON + CORE ON
+ */
+ omap4_power_states[OMAP4_STATE_C2].valid =
+ cpuidle_params_table[OMAP4_STATE_C2].valid;
+ omap4_power_states[OMAP4_STATE_C2].type = OMAP4_STATE_C2;
+ omap4_power_states[OMAP4_STATE_C2].sleep_latency =
+ cpuidle_params_table[OMAP4_STATE_C2].sleep_latency;
+ omap4_power_states[OMAP4_STATE_C2].wakeup_latency =
+ cpuidle_params_table[OMAP4_STATE_C2].wake_latency;
+ omap4_power_states[OMAP4_STATE_C2].threshold =
+ cpuidle_params_table[OMAP4_STATE_C2].threshold;
+ omap4_power_states[OMAP4_STATE_C2].cpu0_state = PWRDM_POWER_ON;
+ omap4_power_states[OMAP4_STATE_C2].cpu1_state = PWRDM_POWER_OFF;
+ omap4_power_states[OMAP4_STATE_C2].mpu_state = PWRDM_POWER_ON;
+ omap4_power_states[OMAP4_STATE_C2].mpu_logic_state = PWRDM_POWER_RET;
+ omap4_power_states[OMAP4_STATE_C2].core_state = PWRDM_POWER_ON;
+ omap4_power_states[OMAP4_STATE_C2].core_logic_state = PWRDM_POWER_RET;
+ omap4_power_states[OMAP4_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID |
+ CPUIDLE_FLAG_CHECK_BM;
+ omap4_power_states[OMAP4_STATE_C2].desc = "MPU ON + CORE ON";
+
+ /*
+ * C3 - CPU0 OFF + CPU1 OFF + MPU CSWR + CORE ON
+ */
+ omap4_power_states[OMAP4_STATE_C3].valid =
+ cpuidle_params_table[OMAP4_STATE_C3].valid;
+ omap4_power_states[OMAP4_STATE_C3].type = OMAP4_STATE_C3;
+ omap4_power_states[OMAP4_STATE_C3].sleep_latency =
+ cpuidle_params_table[OMAP4_STATE_C3].sleep_latency;
+ omap4_power_states[OMAP4_STATE_C3].wakeup_latency =
+ cpuidle_params_table[OMAP4_STATE_C3].wake_latency;
+ omap4_power_states[OMAP4_STATE_C3].threshold =
+ cpuidle_params_table[OMAP4_STATE_C3].threshold;
+ omap4_power_states[OMAP4_STATE_C3].cpu0_state = PWRDM_POWER_OFF;
+ omap4_power_states[OMAP4_STATE_C3].cpu1_state = PWRDM_POWER_OFF;
+ omap4_power_states[OMAP4_STATE_C3].mpu_state = PWRDM_POWER_RET;
+ omap4_power_states[OMAP4_STATE_C3].mpu_logic_state = PWRDM_POWER_RET;
+ omap4_power_states[OMAP4_STATE_C3].core_state = PWRDM_POWER_ON;
+ omap4_power_states[OMAP4_STATE_C3].core_logic_state = PWRDM_POWER_RET;
+ omap4_power_states[OMAP4_STATE_C3].flags = CPUIDLE_FLAG_TIME_VALID |
+ CPUIDLE_FLAG_CHECK_BM;
+ omap4_power_states[OMAP4_STATE_C3].desc = "MPU CSWR + CORE ON";
+
+ /*
+ * C4 - CPU0 OFF + CPU1 OFF + MPU OFF + CORE ON
+ */
+ omap4_power_states[OMAP4_STATE_C4].valid =
+ cpuidle_params_table[OMAP4_STATE_C4].valid;
+ omap4_power_states[OMAP4_STATE_C4].type = OMAP4_STATE_C4;
+ omap4_power_states[OMAP4_STATE_C4].sleep_latency =
+ cpuidle_params_table[OMAP4_STATE_C4].sleep_latency;
+ omap4_power_states[OMAP4_STATE_C4].wakeup_latency =
+ cpuidle_params_table[OMAP4_STATE_C4].wake_latency;
+ omap4_power_states[OMAP4_STATE_C4].threshold =
+ cpuidle_params_table[OMAP4_STATE_C4].threshold;
+ omap4_power_states[OMAP4_STATE_C4].cpu0_state = PWRDM_POWER_OFF;
+ omap4_power_states[OMAP4_STATE_C4].cpu1_state = PWRDM_POWER_OFF;
+ omap4_power_states[OMAP4_STATE_C4].mpu_state = PWRDM_POWER_OFF;
+ omap4_power_states[OMAP4_STATE_C4].mpu_logic_state = PWRDM_POWER_OFF;
+ omap4_power_states[OMAP4_STATE_C4].core_state = PWRDM_POWER_ON;
+ omap4_power_states[OMAP4_STATE_C4].core_logic_state = PWRDM_POWER_RET;
+ omap4_power_states[OMAP4_STATE_C4].flags = CPUIDLE_FLAG_TIME_VALID |
+ CPUIDLE_FLAG_CHECK_BM;
+ omap4_power_states[OMAP4_STATE_C4].desc = "MPU OFF + CORE ON";
}
@@ -120,7 +274,11 @@ int __init omap4_idle_init(void)
struct cpuidle_state *state;
struct cpuidle_device *dev;
- omap_init_power_states();
+ mpu_pd = pwrdm_lookup("mpu_pwrdm");
+ cpu1_pd = pwrdm_lookup("cpu1_pwrdm");
+ core_pd = pwrdm_lookup("core_pwrdm");
+
+ omap4_init_power_states();
cpuidle_register_driver(&omap4_idle_driver);
for_each_cpu(cpu_id, cpu_online_mask) {
@@ -139,8 +297,12 @@ int __init omap4_idle_init(void)
cx->wakeup_latency;
state->target_residency = cx->threshold;
state->flags = cx->flags;
- state->enter = omap4_enter_idle;
+ if (cx->type == OMAP4_STATE_C1)
+ dev->safe_state = state;
+ state->enter = (state->flags & CPUIDLE_FLAG_CHECK_BM) ?
+ omap4_enter_idle_bm : omap4_enter_idle;
sprintf(state->name, "C%d", count+1);
+ strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN);
count++;
}
--
1.6.0.4
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 15/17] omap4: cpuidle: Switch to gptimer from twd in deeper C-states.
2011-02-19 10:42 [PATCH 00/17] omap4: pm: suspend, hotplug and cpuilde support Santosh Shilimkar
` (13 preceding siblings ...)
2011-02-19 10:42 ` [PATCH 14/17] omap4: cpuidle: Add MPUSS RET OFF states Santosh Shilimkar
@ 2011-02-19 10:42 ` Santosh Shilimkar
2011-02-19 10:42 ` [PATCH 16/17] omap4: cpuidle: Allow debugfs control through enable_off_mode Santosh Shilimkar
` (2 subsequent siblings)
17 siblings, 0 replies; 55+ messages in thread
From: Santosh Shilimkar @ 2011-02-19 10:42 UTC (permalink / raw)
To: linux-arm-kernel
CPU local timer(TWD) stops when the CPU is transitioning into
deeper C-States. Since these timers are not wakeup capable, we
need the wakeup capable global timer to program the wakeup time
depending on the next timer expiry.
It can be handled by registering a global wakeup capable timer along
with local timers marked with (mis)feature flag CLOCK_EVT_FEAT_C3STOP.
Then notify the clock events layer from idle code using
CLOCK_EVT_NOTIFY_BROADCAST_ENTER/EXIT).
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
---
arch/arm/mach-omap2/cpuidle44xx.c | 8 ++++++++
1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c
index aa1584e..e887eb5 100644
--- a/arch/arm/mach-omap2/cpuidle44xx.c
+++ b/arch/arm/mach-omap2/cpuidle44xx.c
@@ -12,6 +12,7 @@
#include <linux/sched.h>
#include <linux/cpuidle.h>
+#include <linux/clockchips.h>
#include <asm/proc-fns.h>
@@ -95,6 +96,7 @@ static int omap4_enter_idle(struct cpuidle_device *dev,
struct omap4_processor_cx *cx = cpuidle_get_statedata(state);
struct timespec ts_preidle, ts_postidle, ts_idle;
u32 cpu1_state;
+ int cpu_id = smp_processor_id();
/* Used to keep track of the total time in idle */
getnstimeofday(&ts_preidle);
@@ -127,8 +129,14 @@ static int omap4_enter_idle(struct cpuidle_device *dev,
pwrdm_set_logic_retst(core_pd, cx->core_logic_state);
omap_set_pwrdm_state(core_pd, cx->core_state);
+ if (cx->type > OMAP4_STATE_C1)
+ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu_id);
+
omap4_enter_lowpower(dev->cpu, cx->cpu0_state);
+ if (cx->type > OMAP4_STATE_C1)
+ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu_id);
+
return_sleep_time:
getnstimeofday(&ts_postidle);
ts_idle = timespec_sub(ts_postidle, ts_preidle);
--
1.6.0.4
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 16/17] omap4: cpuidle: Allow debugfs control through enable_off_mode
2011-02-19 10:42 [PATCH 00/17] omap4: pm: suspend, hotplug and cpuilde support Santosh Shilimkar
` (14 preceding siblings ...)
2011-02-19 10:42 ` [PATCH 15/17] omap4: cpuidle: Switch to gptimer from twd in deeper C-states Santosh Shilimkar
@ 2011-02-19 10:42 ` Santosh Shilimkar
2011-03-02 23:43 ` Kevin Hilman
2011-02-19 10:42 ` [PATCH 17/17] omap4: Remove un-used do_wfi() macro Santosh Shilimkar
2011-03-02 23:46 ` [PATCH 00/17] omap4: pm: suspend, hotplug and cpuilde support Kevin Hilman
17 siblings, 1 reply; 55+ messages in thread
From: Santosh Shilimkar @ 2011-02-19 10:42 UTC (permalink / raw)
To: linux-arm-kernel
Only MPU OFF and RET is controllable. CORE state is blocked
at ON state till the CORE RET support is added.
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
---
arch/arm/mach-omap2/cpuidle44xx.c | 30 ++++++++++++++++++++++++++++++
arch/arm/mach-omap2/pm.h | 1 +
arch/arm/mach-omap2/pm44xx.c | 4 ++++
3 files changed, 35 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c
index e887eb5..4207862 100644
--- a/arch/arm/mach-omap2/cpuidle44xx.c
+++ b/arch/arm/mach-omap2/cpuidle44xx.c
@@ -170,6 +170,31 @@ static int omap4_enter_idle_bm(struct cpuidle_device *dev,
}
/**
+ * omap4_cpuidle_update_states() - Update the cpuidle states
+ * @mpu_deepest_state: Enable states upto and including this for mpu domain
+ * @core_deepest_state: Enable states upto and including this for core domain
+ *
+ * This goes through the list of states available and enables and disables the
+ * validity of C states based on deepest state that can be achieved for the
+ * variable domain
+ */
+void omap4_cpuidle_update_states(u32 mpu_deepest_state, u32 core_deepest_state)
+{
+ int i;
+
+ for (i = OMAP4_STATE_C1; i < OMAP4_MAX_STATES; i++) {
+ struct omap4_processor_cx *cx = &omap4_power_states[i];
+
+ if ((cx->mpu_state >= mpu_deepest_state) &&
+ (cx->core_state >= core_deepest_state)) {
+ cx->valid = 1;
+ } else {
+ cx->valid = 0;
+ }
+ }
+}
+
+/**
* omap4_init_power_states - Initialises the OMAP4 specific C states.
*
*/
@@ -325,6 +350,11 @@ int __init omap4_idle_init(void)
}
}
+ if (enable_off_mode)
+ omap4_cpuidle_update_states(PWRDM_POWER_OFF, PWRDM_POWER_OFF);
+ else
+ omap4_cpuidle_update_states(PWRDM_POWER_RET, PWRDM_POWER_RET);
+
return 0;
}
#else
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index ce848b0..4df89d1 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -77,6 +77,7 @@ extern u32 sleep_while_idle;
#if defined(CONFIG_CPU_IDLE)
extern void omap3_cpuidle_update_states(u32, u32);
+extern void omap4_cpuidle_update_states(u32, u32);
#endif
#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index 628242d..6244ab2 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -183,6 +183,10 @@ void omap4_pm_off_mode_enable(int enable)
else
state = PWRDM_POWER_RET;
+#ifdef CONFIG_CPU_IDLE
+ omap4_cpuidle_update_states(state, PWRDM_POWER_ON);
+#endif
+
list_for_each_entry(pwrst, &pwrst_list, node) {
/* FIXME: Remove this check when core retention is supported */
if (!strcmp(pwrst->pwrdm->name, "mpu_pwrdm")) {
--
1.6.0.4
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 17/17] omap4: Remove un-used do_wfi() macro.
2011-02-19 10:42 [PATCH 00/17] omap4: pm: suspend, hotplug and cpuilde support Santosh Shilimkar
` (15 preceding siblings ...)
2011-02-19 10:42 ` [PATCH 16/17] omap4: cpuidle: Allow debugfs control through enable_off_mode Santosh Shilimkar
@ 2011-02-19 10:42 ` Santosh Shilimkar
2011-03-02 23:46 ` [PATCH 00/17] omap4: pm: suspend, hotplug and cpuilde support Kevin Hilman
17 siblings, 0 replies; 55+ messages in thread
From: Santosh Shilimkar @ 2011-02-19 10:42 UTC (permalink / raw)
To: linux-arm-kernel
With OMAP4 suspend, idle and hotplug series, we no longer need
do_wfi() macro.
Remove the same.
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
---
arch/arm/mach-omap2/include/mach/omap4-common.h | 6 ------
1 files changed, 0 insertions(+), 6 deletions(-)
diff --git a/arch/arm/mach-omap2/include/mach/omap4-common.h b/arch/arm/mach-omap2/include/mach/omap4-common.h
index 74c9aa7..ca20333 100644
--- a/arch/arm/mach-omap2/include/mach/omap4-common.h
+++ b/arch/arm/mach-omap2/include/mach/omap4-common.h
@@ -16,12 +16,6 @@
#include <asm/proc-fns.h>
#ifndef __ASSEMBLER__
-/*
- * wfi used in low power code. Directly opcode is used instead
- * of instruction to avoid mulit-omap build break
- */
-#define do_wfi() \
- __asm__ __volatile__ (".word 0xe320f003" : : : "memory")
#ifdef CONFIG_CACHE_L2X0
extern void __iomem *l2cache_base;
--
1.6.0.4
^ permalink raw reply related [flat|nested] 55+ messages in thread
* [PATCH 14/17] omap4: cpuidle: Add MPUSS RET OFF states
2011-02-19 10:42 ` [PATCH 14/17] omap4: cpuidle: Add MPUSS RET OFF states Santosh Shilimkar
@ 2011-02-21 10:19 ` Jean Pihet
2011-02-21 10:26 ` Santosh Shilimkar
2011-03-02 23:32 ` Kevin Hilman
1 sibling, 1 reply; 55+ messages in thread
From: Jean Pihet @ 2011-02-21 10:19 UTC (permalink / raw)
To: linux-arm-kernel
Hi Santosh,
I have a few comments and questions inlined.
On Sat, Feb 19, 2011 at 11:42 AM, Santosh Shilimkar
<santosh.shilimkar@ti.com> wrote:
> This patch adds MPUSS low power states in cpuidle.
>
> ? ? ? ?C1 - CPU0 ON + CPU1 ON/OFF + MPU ON + CORE ON
> ? ? ? ?C2 - CPU0 ON + CPU1 OFF + MPU ON + CORE ON
> ? ? ? ?C3 - CPU0 OFF + CPU1 OFF + MPU CSWR + CORE ON
> ? ? ? ?C4 - CPU0 OFF + CPU1 OFF + MPU OFF + CORE ON
>
> MPU OSWR isn't supported yet. To support OSWR, power domain context
> registers needs to be managed which are not supported yet. A patch
> to address this was submitted but it's not ready for merge yet because
> it was not addressing all OMAP4 power domain context registers.
> More info on this issue:
> ? ? ? ?http://www.mail-archive.com/linux-omap at vger.kernel.org/msg38667.html
>
> OMAP4 powerdomain INACTIVE support is also dropped because of inconsistency
> of it with OMAP3. More information ?on this thread.
> ? ? ? ?http://www.spinics.net/lists/linux-omap/msg45370.html
>
> CORE low power states and associated latencies will be updated as part
> along with chip retention support.
>
> On OMAP4 because of hardware constraints, no low power states are
> targeted when both CPUs are online and in SMP mode. The low power
> states are attempted only when secondary CPU gets offline to OFF
> through hotplug infrastructure.
>
> Thanks to Nicole Chalhoub <n-chalhoub@ti.com> for doing exhaustive
> C-state latency profiling.
>
> Signed-off-by: Rajendra Nayak <rnayak@ti.com>
> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Reviewed-by: Kevin Hilman <khilman@ti.com>
> ---
> ?arch/arm/mach-omap2/cpuidle44xx.c | ?190 ++++++++++++++++++++++++++++++++++---
> ?1 files changed, 176 insertions(+), 14 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c
> index 6c3c69d..aa1584e 100644
> --- a/arch/arm/mach-omap2/cpuidle44xx.c
> +++ b/arch/arm/mach-omap2/cpuidle44xx.c
> @@ -3,6 +3,7 @@
> ?*
> ?* Copyright (C) 2011 Texas Instruments, Inc.
> ?* Rajendra Nayak <rnayak@ti.com>
> + * Santosh Shilimkar <santosh.shilimkar@ti.com>
> ?*
> ?* This program is free software; you can redistribute it and/or modify
> ?* it under the terms of the GNU General Public License version 2 as
> @@ -17,12 +18,21 @@
> ?#include <mach/omap4-common.h>
>
> ?#include "pm.h"
> +#include "prm.h"
>
> ?#ifdef CONFIG_CPU_IDLE
>
> -#define OMAP4_MAX_STATES ? ? ? 1
> -/* C1 - CPUx wfi + MPU inactive + CORE inactive */
> +#define CPUIDLE_FLAG_CHECK_BM ?0x10000 /* use omap4_enter_idle_bm() */
> +#define OMAP4_MAX_STATES ? ? ? 4
> +
> +/* C1 - CPU0 ON + CPU1 ON/OFF + MPU ON + CORE ON */
> ?#define OMAP4_STATE_C1 ? ? ? ? 0
> +/* C2 - CPU0 ON + CPU1 OFF + MPU ON + CORE ON */
> +#define OMAP4_STATE_C2 ? ? ? ? 1
> +/* C3 - CPU0 OFF + CPU1 OFF + MPU CSWR + CORE ON */
> +#define OMAP4_STATE_C3 ? ? ? ? 2
> +/* C4 - CPU0 OFF + CPU1 OFF + MPU OFF + CORE ON */
> +#define OMAP4_STATE_C4 ? ? ? ? 3
>
> ?struct omap4_processor_cx {
> ? ? ? ?u8 valid;
> @@ -32,19 +42,44 @@ struct omap4_processor_cx {
> ? ? ? ?u32 cpu0_state;
> ? ? ? ?u32 cpu1_state;
> ? ? ? ?u32 mpu_state;
> + ? ? ? u32 mpu_logic_state;
> ? ? ? ?u32 core_state;
> + ? ? ? u32 core_logic_state;
> ? ? ? ?u32 threshold;
> ? ? ? ?u32 flags;
> + ? ? ? const char *desc;
> ?};
>
> -struct omap4_processor_cx omap4_power_states[OMAP4_MAX_STATES];
> -struct omap4_processor_cx current_cx_state;
> +static struct omap4_processor_cx omap4_power_states[OMAP4_MAX_STATES];
> +static struct powerdomain *mpu_pd, *cpu1_pd, *core_pd;
>
> +/*
> + * FIXME: Full latenecy numbers needs to be updated as part of
Typo: 'latency'
> + * cpuidle CORE retention support.
> + * Currently only MPUSS latency numbers are added based on
> + * measurements done internally. The numbers for MPUSS are
> + * not board dependent and hence set directly here instead of
> + * passing it from board files.
> + */
> ?static struct cpuidle_params cpuidle_params_table[] = {
> - ? ? ? /* C1 */
> - ? ? ? {1, 2, 2, 5},
> + ? ? ? /* C1 - CPU0 WFI + CPU1 ON/OFF + MPU ON ? + CORE ON */
> + ? ? ? {1, ? ? 2, ? ? ?2, ? ? ?5},
> + ? ? ? /* C2 - CPU0 ON + CPU1 OFF + MPU ON ?+ CORE ON */
> + ? ? ? {1, ? ? 140, ? ?160, ? ?300},
> + ? ? ? /* C3 - CPU0 OFF + CPU1 OFF + MPU CSWR + CORE ON */
> + ? ? ? {1, ? ? 200, ? ?300, ? ?700},
> + ? ? ? /* C4 - CPU0 OFF + CPU1 OFF + MPU OFF + CORE ON */
> + ? ? ? {1, ? ? 1400, ? 600, ? ?5000},
> ?};
>
> +DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev);
> +
> +static int omap4_idle_bm_check(void)
> +{
> + ? ? ? /* FIXME: Populate this with CORE retention support */
> + ? ? ? return 0;
> +}
> +
> ?/**
> ?* omap4_enter_idle - Programs OMAP4 to enter the specified state
> ?* @dev: cpuidle device
> @@ -57,7 +92,9 @@ static struct cpuidle_params cpuidle_params_table[] = {
> ?static int omap4_enter_idle(struct cpuidle_device *dev,
> ? ? ? ? ? ? ? ? ? ? ? ?struct cpuidle_state *state)
> ?{
> + ? ? ? struct omap4_processor_cx *cx = cpuidle_get_statedata(state);
> ? ? ? ?struct timespec ts_preidle, ts_postidle, ts_idle;
> + ? ? ? u32 cpu1_state;
>
> ? ? ? ?/* Used to keep track of the total time in idle */
> ? ? ? ?getnstimeofday(&ts_preidle);
> @@ -65,28 +102,74 @@ static int omap4_enter_idle(struct cpuidle_device *dev,
> ? ? ? ?local_irq_disable();
> ? ? ? ?local_fiq_disable();
>
> - ? ? ? cpu_do_idle();
I think the piece of code below is rather difficult to read and
understand. Based on the patch description and the comment here below
I do not see the relation with the code.
" On OMAP4 because of hardware constraints, no low power states are
targeted when both CPUs are online and in SMP mode. The low power
states are attempted only when secondary CPU gets offline to OFF
through hotplug infrastructure. "
The test below does not seem to match this comment.
> + ? ? ? /*
> + ? ? ? ?* Special hardware/software considerations:
> + ? ? ? ?* 1. Do only WFI for secondary CPU(non-boot - CPU1).
> + ? ? ? ?* ? ?Secondary cores are taken down only via hotplug path.
The comment looks contradictory. Which one is taken OFF using this
code, which one from hotplug?
Does this correspond to the condition '(dev->cpu)' in the test below?
> + ? ? ? ?* 2. Do only a WFI as long as in SMP mode.
Does this correspond to the condition '(num_online_cpus() > 1)' in the
test below? If so it this one triggering the low power mode for cpu0?
> + ? ? ? ?* 3. Continue to do only WFI till CPU1 hits OFF state.
> + ? ? ? ?* ? ?This is necessary to honour hardware recommondation
> + ? ? ? ?* ? ?of triggeing all the possible low power modes once CPU1 is
> + ? ? ? ?* ? ?out of coherency and in OFF mode.
Does this correspond to the condition '(cpu1_state !=
PWRDM_POWER_OFF)' in the test below?
> + ? ? ? ?* Update dev->last_state so that governor stats reflects right
> + ? ? ? ?* data.
> + ? ? ? ?*/
> + ? ? ? cpu1_state = pwrdm_read_pwrst(cpu1_pd);
> + ? ? ? if ((dev->cpu) || (num_online_cpus() > 1) ||
> + ? ? ? ? ? ? ? ? ? ? ? (cpu1_state != PWRDM_POWER_OFF)) {
Are '||' correct here?
Sorry if the code behaves correctly, the remarks are about readability
especially in the comments.
Regards,
Jean
> + ? ? ? ? ? ? ? dev->last_state = dev->safe_state;
> + ? ? ? ? ? ? ? cpu_do_idle();
> + ? ? ? ? ? ? ? goto return_sleep_time;
> + ? ? ? }
>
> + ? ? ? pwrdm_set_logic_retst(mpu_pd, cx->mpu_logic_state);
> + ? ? ? omap_set_pwrdm_state(mpu_pd, cx->mpu_state);
> + ? ? ? pwrdm_set_logic_retst(core_pd, cx->core_logic_state);
> + ? ? ? omap_set_pwrdm_state(core_pd, cx->core_state);
> +
> + ? ? ? omap4_enter_lowpower(dev->cpu, cx->cpu0_state);
> +
> +return_sleep_time:
> ? ? ? ?getnstimeofday(&ts_postidle);
> ? ? ? ?ts_idle = timespec_sub(ts_postidle, ts_preidle);
>
> ? ? ? ?local_irq_enable();
> ? ? ? ?local_fiq_enable();
>
> +
> ? ? ? ?return ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * USEC_PER_SEC;
> ?}
>
> -DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev);
> +/**
> + * omap4_enter_idle_bm - Checks for any bus activity
> + * @dev: cpuidle device
> + * @state: The target state to be programmed
> + *
> + * Used for C states with CPUIDLE_FLAG_CHECK_BM flag set. This
> + * function checks for any pending activity and then programs the
> + * device to the specified or a safer state.
> + */
> +static int omap4_enter_idle_bm(struct cpuidle_device *dev,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct cpuidle_state *state)
> +{
> + ? ? ? if ((state->flags & CPUIDLE_FLAG_CHECK_BM) && omap4_idle_bm_check()) {
> + ? ? ? ? ? ? ? BUG_ON(!dev->safe_state);
> + ? ? ? ? ? ? ? state = dev->safe_state;
> + ? ? ? }
> +
> + ? ? ? dev->last_state = state;
> + ? ? ? return omap4_enter_idle(dev, state);
> +}
>
> ?/**
> ?* omap4_init_power_states - Initialises the OMAP4 specific C states.
> ?*
> - * Below is the desciption of each C state.
> - * C1 : CPUx wfi + MPU inative + Core inactive
> ?*/
> -void omap_init_power_states(void)
> +void omap4_init_power_states(void)
> ?{
> - ? ? ? /* C1 . CPUx wfi + MPU inactive + Core inactive */
> + ? ? ? /*
> + ? ? ? ?* C1 - CPU0 WFI + CPU1 OFF + MPU ON + CORE ON
> + ? ? ? ?*/
> ? ? ? ?omap4_power_states[OMAP4_STATE_C1].valid =
> ? ? ? ? ? ? ? ? ? ? ? ?cpuidle_params_table[OMAP4_STATE_C1].valid;
> ? ? ? ?omap4_power_states[OMAP4_STATE_C1].type = OMAP4_STATE_C1;
> @@ -96,9 +179,80 @@ void omap_init_power_states(void)
> ? ? ? ? ? ? ? ? ? ? ? ?cpuidle_params_table[OMAP4_STATE_C1].wake_latency;
> ? ? ? ?omap4_power_states[OMAP4_STATE_C1].threshold =
> ? ? ? ? ? ? ? ? ? ? ? ?cpuidle_params_table[OMAP4_STATE_C1].threshold;
> + ? ? ? omap4_power_states[OMAP4_STATE_C1].cpu0_state = PWRDM_POWER_ON;
> + ? ? ? omap4_power_states[OMAP4_STATE_C1].cpu1_state = PWRDM_POWER_OFF;
> ? ? ? ?omap4_power_states[OMAP4_STATE_C1].mpu_state = PWRDM_POWER_ON;
> + ? ? ? omap4_power_states[OMAP4_STATE_C1].mpu_logic_state = PWRDM_POWER_RET;
> ? ? ? ?omap4_power_states[OMAP4_STATE_C1].core_state = PWRDM_POWER_ON;
> + ? ? ? omap4_power_states[OMAP4_STATE_C1].core_logic_state = PWRDM_POWER_RET;
> ? ? ? ?omap4_power_states[OMAP4_STATE_C1].flags = CPUIDLE_FLAG_TIME_VALID;
> + ? ? ? omap4_power_states[OMAP4_STATE_C1].desc = "MPU ON + CORE ON";
> +
> + ? ? ? /*
> + ? ? ? ?* C2 - CPU0 ON + CPU1 OFF + MPU ON + CORE ON
> + ? ? ? ?*/
> + ? ? ? omap4_power_states[OMAP4_STATE_C2].valid =
> + ? ? ? ? ? ? ? ? ? ? ? cpuidle_params_table[OMAP4_STATE_C2].valid;
> + ? ? ? omap4_power_states[OMAP4_STATE_C2].type = OMAP4_STATE_C2;
> + ? ? ? omap4_power_states[OMAP4_STATE_C2].sleep_latency =
> + ? ? ? ? ? ? ? ? ? ? ? cpuidle_params_table[OMAP4_STATE_C2].sleep_latency;
> + ? ? ? omap4_power_states[OMAP4_STATE_C2].wakeup_latency =
> + ? ? ? ? ? ? ? ? ? ? ? cpuidle_params_table[OMAP4_STATE_C2].wake_latency;
> + ? ? ? omap4_power_states[OMAP4_STATE_C2].threshold =
> + ? ? ? ? ? ? ? ? ? ? ? cpuidle_params_table[OMAP4_STATE_C2].threshold;
> + ? ? ? omap4_power_states[OMAP4_STATE_C2].cpu0_state = PWRDM_POWER_ON;
> + ? ? ? omap4_power_states[OMAP4_STATE_C2].cpu1_state = PWRDM_POWER_OFF;
> + ? ? ? omap4_power_states[OMAP4_STATE_C2].mpu_state = PWRDM_POWER_ON;
> + ? ? ? omap4_power_states[OMAP4_STATE_C2].mpu_logic_state = PWRDM_POWER_RET;
> + ? ? ? omap4_power_states[OMAP4_STATE_C2].core_state = PWRDM_POWER_ON;
> + ? ? ? omap4_power_states[OMAP4_STATE_C2].core_logic_state = PWRDM_POWER_RET;
> + ? ? ? omap4_power_states[OMAP4_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID |
> + ? ? ? ? ? ? ? CPUIDLE_FLAG_CHECK_BM;
> + ? ? ? omap4_power_states[OMAP4_STATE_C2].desc = "MPU ON + CORE ON";
> +
> + ? ? ? /*
> + ? ? ? ?* C3 - CPU0 OFF + CPU1 OFF + MPU CSWR + CORE ON
> + ? ? ? ?*/
> + ? ? ? omap4_power_states[OMAP4_STATE_C3].valid =
> + ? ? ? ? ? ? ? ? ? ? ? cpuidle_params_table[OMAP4_STATE_C3].valid;
> + ? ? ? omap4_power_states[OMAP4_STATE_C3].type = OMAP4_STATE_C3;
> + ? ? ? omap4_power_states[OMAP4_STATE_C3].sleep_latency =
> + ? ? ? ? ? ? ? ? ? ? ? cpuidle_params_table[OMAP4_STATE_C3].sleep_latency;
> + ? ? ? omap4_power_states[OMAP4_STATE_C3].wakeup_latency =
> + ? ? ? ? ? ? ? ? ? ? ? cpuidle_params_table[OMAP4_STATE_C3].wake_latency;
> + ? ? ? omap4_power_states[OMAP4_STATE_C3].threshold =
> + ? ? ? ? ? ? ? ? ? ? ? cpuidle_params_table[OMAP4_STATE_C3].threshold;
> + ? ? ? omap4_power_states[OMAP4_STATE_C3].cpu0_state = PWRDM_POWER_OFF;
> + ? ? ? omap4_power_states[OMAP4_STATE_C3].cpu1_state = PWRDM_POWER_OFF;
> + ? ? ? omap4_power_states[OMAP4_STATE_C3].mpu_state = PWRDM_POWER_RET;
> + ? ? ? omap4_power_states[OMAP4_STATE_C3].mpu_logic_state = PWRDM_POWER_RET;
> + ? ? ? omap4_power_states[OMAP4_STATE_C3].core_state = PWRDM_POWER_ON;
> + ? ? ? omap4_power_states[OMAP4_STATE_C3].core_logic_state = PWRDM_POWER_RET;
> + ? ? ? omap4_power_states[OMAP4_STATE_C3].flags = CPUIDLE_FLAG_TIME_VALID |
> + ? ? ? ? ? ? ? CPUIDLE_FLAG_CHECK_BM;
> + ? ? ? omap4_power_states[OMAP4_STATE_C3].desc = "MPU CSWR + CORE ON";
> +
> + ? ? ? /*
> + ? ? ? ?* C4 - CPU0 OFF + CPU1 OFF + MPU OFF + CORE ON
> + ? ? ? ?*/
> + ? ? ? omap4_power_states[OMAP4_STATE_C4].valid =
> + ? ? ? ? ? ? ? ? ? ? ? cpuidle_params_table[OMAP4_STATE_C4].valid;
> + ? ? ? omap4_power_states[OMAP4_STATE_C4].type = OMAP4_STATE_C4;
> + ? ? ? omap4_power_states[OMAP4_STATE_C4].sleep_latency =
> + ? ? ? ? ? ? ? ? ? ? ? cpuidle_params_table[OMAP4_STATE_C4].sleep_latency;
> + ? ? ? omap4_power_states[OMAP4_STATE_C4].wakeup_latency =
> + ? ? ? ? ? ? ? ? ? ? ? cpuidle_params_table[OMAP4_STATE_C4].wake_latency;
> + ? ? ? omap4_power_states[OMAP4_STATE_C4].threshold =
> + ? ? ? ? ? ? ? ? ? ? ? cpuidle_params_table[OMAP4_STATE_C4].threshold;
> + ? ? ? omap4_power_states[OMAP4_STATE_C4].cpu0_state = PWRDM_POWER_OFF;
> + ? ? ? omap4_power_states[OMAP4_STATE_C4].cpu1_state = PWRDM_POWER_OFF;
> + ? ? ? omap4_power_states[OMAP4_STATE_C4].mpu_state = PWRDM_POWER_OFF;
> + ? ? ? omap4_power_states[OMAP4_STATE_C4].mpu_logic_state = PWRDM_POWER_OFF;
> + ? ? ? omap4_power_states[OMAP4_STATE_C4].core_state = PWRDM_POWER_ON;
> + ? ? ? omap4_power_states[OMAP4_STATE_C4].core_logic_state = PWRDM_POWER_RET;
> + ? ? ? omap4_power_states[OMAP4_STATE_C4].flags = CPUIDLE_FLAG_TIME_VALID |
> + ? ? ? ? ? ? ? CPUIDLE_FLAG_CHECK_BM;
> + ? ? ? omap4_power_states[OMAP4_STATE_C4].desc = "MPU OFF + CORE ON";
>
> ?}
>
> @@ -120,7 +274,11 @@ int __init omap4_idle_init(void)
> ? ? ? ?struct cpuidle_state *state;
> ? ? ? ?struct cpuidle_device *dev;
>
> - ? ? ? omap_init_power_states();
> + ? ? ? mpu_pd = pwrdm_lookup("mpu_pwrdm");
> + ? ? ? cpu1_pd = pwrdm_lookup("cpu1_pwrdm");
> + ? ? ? core_pd = pwrdm_lookup("core_pwrdm");
> +
> + ? ? ? omap4_init_power_states();
> ? ? ? ?cpuidle_register_driver(&omap4_idle_driver);
>
> ? ? ? ?for_each_cpu(cpu_id, cpu_online_mask) {
> @@ -139,8 +297,12 @@ int __init omap4_idle_init(void)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?cx->wakeup_latency;
> ? ? ? ? ? ? ? ? ? ? ? ?state->target_residency = cx->threshold;
> ? ? ? ? ? ? ? ? ? ? ? ?state->flags = cx->flags;
> - ? ? ? ? ? ? ? ? ? ? ? state->enter = omap4_enter_idle;
> + ? ? ? ? ? ? ? ? ? ? ? if (cx->type == OMAP4_STATE_C1)
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? dev->safe_state = state;
> + ? ? ? ? ? ? ? ? ? ? ? state->enter = (state->flags & CPUIDLE_FLAG_CHECK_BM) ?
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? omap4_enter_idle_bm : omap4_enter_idle;
> ? ? ? ? ? ? ? ? ? ? ? ?sprintf(state->name, "C%d", count+1);
> + ? ? ? ? ? ? ? ? ? ? ? strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN);
> ? ? ? ? ? ? ? ? ? ? ? ?count++;
> ? ? ? ? ? ? ? ?}
>
> --
> 1.6.0.4
>
> --
> 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
>
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 14/17] omap4: cpuidle: Add MPUSS RET OFF states
2011-02-21 10:19 ` Jean Pihet
@ 2011-02-21 10:26 ` Santosh Shilimkar
2011-02-21 14:01 ` Santosh Shilimkar
0 siblings, 1 reply; 55+ messages in thread
From: Santosh Shilimkar @ 2011-02-21 10:26 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Jean Pihet [mailto:jean.pihet at newoldbits.com]
> Sent: Monday, February 21, 2011 3:49 PM
> To: Santosh Shilimkar
> Cc: linux-omap at vger.kernel.org; khilman at ti.com; linux-arm-
> kernel at lists.infradead.org; Rajendra Nayak
> Subject: Re: [PATCH 14/17] omap4: cpuidle: Add MPUSS RET OFF states
>
> Hi Santosh,
>
[...]
>
> > + * cpuidle CORE retention support.
> > + * Currently only MPUSS latency numbers are added based on
> > + * measurements done internally. The numbers for MPUSS are
> > + * not board dependent and hence set directly here instead of
> > + * passing it from board files.
> > + */
> > ?static struct cpuidle_params cpuidle_params_table[] = {
> > - ? ? ? /* C1 */
> > - ? ? ? {1, 2, 2, 5},
> > + ? ? ? /* C1 - CPU0 WFI + CPU1 ON/OFF + MPU ON ? + CORE ON */
> > + ? ? ? {1, ? ? 2, ? ? ?2, ? ? ?5},
> > + ? ? ? /* C2 - CPU0 ON + CPU1 OFF + MPU ON ?+ CORE ON */
> > + ? ? ? {1, ? ? 140, ? ?160, ? ?300},
> > + ? ? ? /* C3 - CPU0 OFF + CPU1 OFF + MPU CSWR + CORE ON */
> > + ? ? ? {1, ? ? 200, ? ?300, ? ?700},
> > + ? ? ? /* C4 - CPU0 OFF + CPU1 OFF + MPU OFF + CORE ON */
> > + ? ? ? {1, ? ? 1400, ? 600, ? ?5000},
> > ?};
> >
> > +DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev);
> > +
> > +static int omap4_idle_bm_check(void)
> > +{
> > + ? ? ? /* FIXME: Populate this with CORE retention support */
> > + ? ? ? return 0;
> > +}
> > +
> > ?/**
> > ?* omap4_enter_idle - Programs OMAP4 to enter the specified state
> > ?* @dev: cpuidle device
> > @@ -57,7 +92,9 @@ static struct cpuidle_params
> cpuidle_params_table[] = {
> > ?static int omap4_enter_idle(struct cpuidle_device *dev,
> > ? ? ? ? ? ? ? ? ? ? ? ?struct cpuidle_state *state)
> > ?{
> > + ? ? ? struct omap4_processor_cx *cx =
> cpuidle_get_statedata(state);
> > ? ? ? ?struct timespec ts_preidle, ts_postidle, ts_idle;
> > + ? ? ? u32 cpu1_state;
> >
> > ? ? ? ?/* Used to keep track of the total time in idle */
> > ? ? ? ?getnstimeofday(&ts_preidle);
> > @@ -65,28 +102,74 @@ static int omap4_enter_idle(struct
> cpuidle_device *dev,
> > ? ? ? ?local_irq_disable();
> > ? ? ? ?local_fiq_disable();
> >
> > - ? ? ? cpu_do_idle();
>
> I think the piece of code below is rather difficult to read and
> understand. Based on the patch description and the comment here
> below
> I do not see the relation with the code.
>
There is relation. The comments are as per the conditions. And
The hardware constraint is back-ground behind the conditions.
> " On OMAP4 because of hardware constraints, no low power states are
> targeted when both CPUs are online and in SMP mode. The low power
> states are attempted only when secondary CPU gets offline to OFF
> through hotplug infrastructure. "
> The test below does not seem to match this comment.
>
> > + ? ? ? /*
> > + ? ? ? ?* Special hardware/software considerations:
> > + ? ? ? ?* 1. Do only WFI for secondary CPU(non-boot - CPU1).
> > + ? ? ? ?* ? ?Secondary cores are taken down only via hotplug
> path.
> The comment looks contradictory. Which one is taken OFF using this
> code, which one from hotplug?
> Does this correspond to the condition '(dev->cpu)' in the test
> below?
Yes.
>
> > + ? ? ? ?* 2. Do only a WFI as long as in SMP mode.
> Does this correspond to the condition '(num_online_cpus() > 1)' in
> the
> test below? If so it this one triggering the low power mode for
> cpu0?
yes
>
> > + ? ? ? ?* 3. Continue to do only WFI till CPU1 hits OFF state.
> > + ? ? ? ?* ? ?This is necessary to honour hardware recommondation
> > + ? ? ? ?* ? ?of triggeing all the possible low power modes once
> CPU1 is
> > + ? ? ? ?* ? ?out of coherency and in OFF mode.
> Does this correspond to the condition '(cpu1_state !=
> PWRDM_POWER_OFF)' in the test below?
>
Yes
> > + ? ? ? ?* Update dev->last_state so that governor stats reflects
> right
> > + ? ? ? ?* data.
> > + ? ? ? ?*/
> > + ? ? ? cpu1_state = pwrdm_read_pwrst(cpu1_pd);
> > + ? ? ? if ((dev->cpu) || (num_online_cpus() > 1) ||
> > + ? ? ? ? ? ? ? ? ? ? ? (cpu1_state != PWRDM_POWER_OFF)) {
> Are '||' correct here?
Yes.
> Sorry if the code behaves correctly, the remarks are about
> readability especially in the comments.
>
You got all three correct. Instead of having three If's doing
same thing I have merged them and added comments above.
And you got all of them correctly.
Regards,
Santosh
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 14/17] omap4: cpuidle: Add MPUSS RET OFF states
2011-02-21 10:26 ` Santosh Shilimkar
@ 2011-02-21 14:01 ` Santosh Shilimkar
0 siblings, 0 replies; 55+ messages in thread
From: Santosh Shilimkar @ 2011-02-21 14:01 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Santosh Shilimkar [mailto:santosh.shilimkar at ti.com]
> Sent: Monday, February 21, 2011 3:57 PM
> To: Jean Pihet
> Cc: linux-omap at vger.kernel.org; Kevin Hilman; linux-arm-
> kernel at lists.infradead.org; Rajendra Nayak
> Subject: RE: [PATCH 14/17] omap4: cpuidle: Add MPUSS RET OFF states
>
[...]
> > I think the piece of code below is rather difficult to read and
> > understand. Based on the patch description and the comment here
> > below
> > I do not see the relation with the code.
> >
> There is relation. The comments are as per the conditions. And
> The hardware constraint is back-ground behind the conditions.
>
> > " On OMAP4 because of hardware constraints, no low power states
> are
> > targeted when both CPUs are online and in SMP mode. The low power
> > states are attempted only when secondary CPU gets offline to OFF
> > through hotplug infrastructure. "
> > The test below does not seem to match this comment.
> >
> > > + ? ? ? /*
> > > + ? ? ? ?* Special hardware/software considerations:
> > > + ? ? ? ?* 1. Do only WFI for secondary CPU(non-boot - CPU1).
> > > + ? ? ? ?* ? ?Secondary cores are taken down only via hotplug
> > path.
> > The comment looks contradictory. Which one is taken OFF using this
> > code, which one from hotplug?
> > Does this correspond to the condition '(dev->cpu)' in the test
> > below?
>
> Yes.
> >
> > > + ? ? ? ?* 2. Do only a WFI as long as in SMP mode.
> > Does this correspond to the condition '(num_online_cpus() > 1)' in
> > the
> > test below? If so it this one triggering the low power mode for
> > cpu0?
> yes
> >
> > > + ? ? ? ?* 3. Continue to do only WFI till CPU1 hits OFF state.
> > > + ? ? ? ?* ? ?This is necessary to honour hardware
> recommondation
> > > + ? ? ? ?* ? ?of triggeing all the possible low power modes once
> > CPU1 is
> > > + ? ? ? ?* ? ?out of coherency and in OFF mode.
> > Does this correspond to the condition '(cpu1_state !=
> > PWRDM_POWER_OFF)' in the test below?
> >
> Yes
>
> > > + ? ? ? ?* Update dev->last_state so that governor stats
> reflects
> > right
> > > + ? ? ? ?* data.
> > > + ? ? ? ?*/
> > > + ? ? ? cpu1_state = pwrdm_read_pwrst(cpu1_pd);
> > > + ? ? ? if ((dev->cpu) || (num_online_cpus() > 1) ||
> > > + ? ? ? ? ? ? ? ? ? ? ? (cpu1_state != PWRDM_POWER_OFF)) {
> > Are '||' correct here?
> Yes.
>
> > Sorry if the code behaves correctly, the remarks are about
> > readability especially in the comments.
> >
> You got all three correct. Instead of having three If's doing
> same thing I have merged them and added comments above.
>
> And you got all of them correctly.
>
Will add the code conditions in comments as well so that
it becomes mere readable.
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 01/17] omap4: pm: Add omap WakeupGen module support
2011-02-19 10:42 ` [PATCH 01/17] omap4: pm: Add omap WakeupGen module support Santosh Shilimkar
@ 2011-03-02 21:47 ` Kevin Hilman
2011-03-03 16:04 ` Santosh Shilimkar
0 siblings, 1 reply; 55+ messages in thread
From: Kevin Hilman @ 2011-03-02 21:47 UTC (permalink / raw)
To: linux-arm-kernel
Hi Santosh,
Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
> This patch adds OMAP WakeupGen support. The WakeupGen unit is responsible
> for generating wakeup event from the incoming interrupts and enable bits.
> The WakeupGen is implemented in MPU Always-On power domain. During normal
> operation, WakeupGen delivers external interrupts directly to the GIC.
> When the CPUx asserts StandbyWFI, indicating it wants to enter lowpower
> state, the Standby Controller checks with the WakeupGen unit using the
> idlereq/idleack handshake to make sure there is no incoming interrupts.
> The GIC and WakeupGen needs to be kept in synchronisation for proper
> interrupt functioning.
>
> Hence this patch hooks up the omap WakeupGen mask/unmask along with GIC using
> architecture specific hooks.
>
> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Reviewed-by: Kevin Hilman <khilman@ti.com>
A few comments below...
> ---
> arch/arm/mach-omap2/Makefile | 3 +-
> arch/arm/mach-omap2/include/mach/omap-wakeupgen.h | 40 ++++
> arch/arm/mach-omap2/omap-wakeupgen.c | 213 +++++++++++++++++++++
> arch/arm/mach-omap2/omap4-common.c | 3 +
> 4 files changed, 258 insertions(+), 1 deletions(-)
> create mode 100644 arch/arm/mach-omap2/include/mach/omap-wakeupgen.h
> create mode 100644 arch/arm/mach-omap2/omap-wakeupgen.c
>
> diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
> index 72f2891..54ff219 100644
> --- a/arch/arm/mach-omap2/Makefile
> +++ b/arch/arm/mach-omap2/Makefile
> @@ -24,7 +24,8 @@ obj-$(CONFIG_TWL4030_CORE) += omap_twl.o
> obj-$(CONFIG_SMP) += omap-smp.o omap-headsmp.o
> obj-$(CONFIG_LOCAL_TIMERS) += timer-mpu.o
> obj-$(CONFIG_HOTPLUG_CPU) += omap-hotplug.o
> -obj-$(CONFIG_ARCH_OMAP4) += omap44xx-smc.o omap4-common.o
> +obj-$(CONFIG_ARCH_OMAP4) += omap44xx-smc.o omap4-common.o \
> + omap-wakeupgen.o
>
> plus_sec := $(call as-instr,.arch_extension sec,+sec)
> AFLAGS_omap-headsmp.o :=-Wa,-march=armv7-a$(plus_sec)
> diff --git a/arch/arm/mach-omap2/include/mach/omap-wakeupgen.h b/arch/arm/mach-omap2/include/mach/omap-wakeupgen.h
> new file mode 100644
> index 0000000..f10d106
> --- /dev/null
> +++ b/arch/arm/mach-omap2/include/mach/omap-wakeupgen.h
> @@ -0,0 +1,40 @@
> +/*
> + * OMAP WakeupGen header file
> + *
> + * Copyright (C) 2011 Texas Instruments, Inc.
> + * Written by Santosh Shilimkar <santosh.shilimkar@ti.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +#ifndef OMAP_ARCH_WAKEUPGEN_H
> +#define OMAP_ARCH_WAKEUPGEN_H
> +
> +#define OMAP_WKG_CONTROL_0 0x00
> +#define OMAP_WKG_ENB_A_0 0x10
> +#define OMAP_WKG_ENB_B_0 0x14
> +#define OMAP_WKG_ENB_C_0 0x18
> +#define OMAP_WKG_ENB_D_0 0x1c
> +#define OMAP_WKG_ENB_SECURE_A_0 0x20
> +#define OMAP_WKG_ENB_SECURE_B_0 0x24
> +#define OMAP_WKG_ENB_SECURE_C_0 0x28
> +#define OMAP_WKG_ENB_SECURE_D_0 0x2c
> +#define OMAP_WKG_ENB_A_1 0x410
> +#define OMAP_WKG_ENB_B_1 0x414
> +#define OMAP_WKG_ENB_C_1 0x418
> +#define OMAP_WKG_ENB_D_1 0x41c
> +#define OMAP_WKG_ENB_SECURE_A_1 0x420
> +#define OMAP_WKG_ENB_SECURE_B_1 0x424
> +#define OMAP_WKG_ENB_SECURE_C_1 0x428
> +#define OMAP_WKG_ENB_SECURE_D_1 0x42c
> +#define OMAP_AUX_CORE_BOOT_0 0x800
> +#define OMAP_AUX_CORE_BOOT_1 0x804
> +#define OMAP_PTMSYNCREQ_MASK 0xc00
> +#define OMAP_PTMSYNCREQ_EN 0xc04
> +#define OMAP_TIMESTAMPCYCLELO 0xc08
> +#define OMAP_TIMESTAMPCYCLEHI 0xc0c
> +
> +extern int __init omap_wakeupgen_init(void);
> +extern void omap_wakeupgen_irqmask_all(unsigned int cpu, unsigned int set);
> +#endif
> diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c
> new file mode 100644
> index 0000000..e26a0ed
> --- /dev/null
> +++ b/arch/arm/mach-omap2/omap-wakeupgen.c
> @@ -0,0 +1,213 @@
> +/*
> + * OMAP WakeupGen Source file
> + *
> + * The WakeupGen unit is responsible for generating wakeup event from the
> + * incoming interrupts and enable bits. The WakeupGen is implemented in MPU
> + * always-On power domain. The WakeupGen consists of two sub-units, one for
> + * each CPU and manages only SPI interrupts. Hardware requirements is that
> + * the GIC and WakeupGen should be kept in sync for proper operation.
> + *
> + * Copyright (C) 2011 Texas Instruments, Inc.
> + * Written by Santosh Shilimkar <santosh.shilimkar@ti.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/irq.h>
> +#include <linux/platform_device.h>
> +
> +#include <asm/hardware/gic.h>
> +
> +#include <mach/omap-wakeupgen.h>
> +
> +#define NR_BANKS 4
> +#define MAX_IRQS 128
> +#define WKG_MASK_ALL 0x00000000
> +#define WKG_UNMASK_ALL 0xffffffff
> +#define CPU_ENA_OFFSET 0x400
> +#define CPU0_ID 0x0
> +#define CPU1_ID 0x1
> +
> +/* WakeupGen Base addres */
> +static void __iomem *wakeupgen_base;
> +static DEFINE_PER_CPU(u32 [NR_BANKS], irqmasks);
> +static DEFINE_SPINLOCK(wakeupgen_lock);
> +
> +/*
> + * Static helper functions
> + */
> +
> +static inline u32 cpu_readl(u8 idx, u32 cpu)
Minor nit: the cpu_ prefix is too generic, how about wakeupgen_ or wugen_?
> +{
> + return __raw_readl(wakeupgen_base + OMAP_WKG_ENB_A_0 +
> + (cpu * CPU_ENA_OFFSET) + (idx * 4));
> +}
> +
> +static inline void cpu_writel(u32 val, u8 idx, u32 cpu)
> +{
> + __raw_writel(val, wakeupgen_base + OMAP_WKG_ENB_A_0 +
> + (cpu * CPU_ENA_OFFSET) + (idx * 4));
> +}
> +
> +static void _wakeupgen_set_all(unsigned int cpu, unsigned int reg)
> +{
> + u8 i;
> +
> + for (i = 0; i < NR_BANKS; i++)
> + cpu_writel(reg, i, cpu);
> +}
> +
> +static void _wakeupgen_set(unsigned int irq, unsigned int set)
I (still) don't like a single "set" function, especially when it takes a
"set" argument.
Make separate set and clear functions, with the common stuff in a helper
function like _wakeupgen_get_irq() or something.
> +{
> + unsigned int val, spi_irq;
> + unsigned int cpu = smp_processor_id();
> + u8 i;
> +
> + /*
> + * PPIs and SGIs are not supported
> + */
> + if (irq < OMAP44XX_IRQ_GIC_START)
> + return;
> +
> + /*
> + * Subtract the GIC offset
> + */
> + spi_irq = irq - OMAP44XX_IRQ_GIC_START;
> + if (spi_irq > MAX_IRQS) {
> + pr_err("omap wakeupGen: Invalid IRQ%d\n", irq);
> + return ;
> + }
> +
> + /*
> + * Each wakeup gen register controls 32
> + * interrupts. i.e 1 bit per SPI IRQ
> + */
> + i = spi_irq >> 5;
> + spi_irq %= 32;
> +
> + val = cpu_readl(i, cpu);
> + if (set)
> + val |= BIT(spi_irq);
> + else
> + val &= ~BIT(spi_irq);
> + cpu_writel(val, i, cpu);
> +}
> +
> +static void _wakeupgen_save_masks(unsigned int cpu)
> +{
> + u8 i;
> +
> + for (i = 0; i < NR_BANKS; i++)
> + per_cpu(irqmasks, cpu)[i] = cpu_readl(i, cpu);
> +}
> +
> +static void _wakeupgen_restore_masks(unsigned int cpu)
> +{
> + u8 i;
> +
> + for (i = 0; i < NR_BANKS; i++)
> + cpu_writel(per_cpu(irqmasks, cpu)[i], i, cpu);
> +}
> +
> +/*
> + * Architecture specific Mask extensiom
> + */
> +static void wakeupgen_mask(struct irq_data *d)
> +{
> + spin_lock(&wakeupgen_lock);
> + _wakeupgen_set(d->irq, 0);
> + spin_unlock(&wakeupgen_lock);
> +}
> +
> +/*
> + * Architecture specific Unmask extensiom
> + */
> +static void wakeupgen_unmask(struct irq_data *d)
> +{
> +
> + spin_lock(&wakeupgen_lock);
> + _wakeupgen_set(d->irq, 1);
> + spin_unlock(&wakeupgen_lock);
> +}
> +
> +#ifdef CONFIG_PM
I think this should be CONFIG_SUSPEND
> +/*
> + * Architecture specific set_wake extension
> + */
> +static int wakeupgen_set_wake(struct irq_data *d, unsigned int on)
> +{
> + spin_lock(&wakeupgen_lock);
> + _wakeupgen_set(d->irq, on);
> + spin_unlock(&wakeupgen_lock);
> +
> + return 0;
> +}
> +
> +#else
> +#define wakeupgen_set_wake NULL
> +#endif
> +
> +/**
> + * omap_wakeupgen_irqmask_all() - Mask or unmask interrupts
> + * @cpu - CPU ID
> + * @set - The IRQ register mask.
> + * 0 = Mask all interrupts on the 'cpu'
> + * 1 = Unmask all interrupts on the 'cpu'
> + *
> + * Ensure that the initial mask is maintained. This is faster than
> + * iterating through GIC rgeisters to arrive at the correct masks
> + */
> +void omap_wakeupgen_irqmask_all(unsigned int cpu, unsigned int set)
> +{
> + if (omap_rev() == OMAP4430_REV_ES1_0)
> + return;
> +
> + spin_lock(&wakeupgen_lock);
> + if (set) {
> + _wakeupgen_save_masks(cpu);
> + _wakeupgen_set_all(cpu, WKG_MASK_ALL);
> + } else {
> + _wakeupgen_set_all(cpu, WKG_UNMASK_ALL);
> + _wakeupgen_restore_masks(cpu);
> + }
> + spin_unlock(&wakeupgen_lock);
> +}
> +
> +/*
> + * Initialse the wakeupgen module
> + */
> +int __init omap_wakeupgen_init(void)
> +{
> + u8 i;
> +
> + /* Not supported on on OMAP4 ES1.0 silicon */
> + if (omap_rev() == OMAP4430_REV_ES1_0) {
> + WARN(1, "WakeupGen: Not supported on OMAP4430 ES1.0\n");
> + return -EPERM;
> + }
> +
> + /* Static mapping, never released */
> + wakeupgen_base = ioremap(OMAP44XX_WKUPGEN_BASE, SZ_4K);
> + BUG_ON(!wakeupgen_base);
A WARN_ON() with a graceful exit is more appropriate here:
from asm-generic/bug.h:
/*
* Don't use BUG() or BUG_ON() unless there's really no way out; one
* example might be detecting data structure corruption in the middle
* of an operation that can't be backed out of. If the (sub)system
* can somehow continue operating, perhaps with reduced functionality,
* it's probably not BUG-worthy.
*
* If you're tempted to BUG(), think again: is completely giving up
* really the *only* solution? There are usually better options, where
* users don't need to reboot ASAP and can mostly shut down cleanly.
*/
> + /* Clear all IRQ bitmasks at wakeupGen level */
> + for (i = 0; i < NR_BANKS; i++) {
> + cpu_writel(0, i, CPU0_ID);
> + cpu_writel(0, i, CPU1_ID);
> + }
> +
> + /*
> + * Override gic architecture specific fucntioms to add
> + * OMAP WakeupGen interrupt controller along with GIC
> + */
> + gic_arch_extn.irq_mask = wakeupgen_mask;
> + gic_arch_extn.irq_unmask = wakeupgen_unmask;
> + gic_arch_extn.irq_set_wake = wakeupgen_set_wake;
> +
> + return 0;
> +}
> diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
> index 1926864..559d227 100644
> --- a/arch/arm/mach-omap2/omap4-common.c
> +++ b/arch/arm/mach-omap2/omap4-common.c
> @@ -21,6 +21,7 @@
>
> #include <mach/hardware.h>
> #include <mach/omap4-common.h>
> +#include <mach/omap-wakeupgen.h>
>
> #ifdef CONFIG_CACHE_L2X0
> void __iomem *l2cache_base;
> @@ -41,6 +42,8 @@ void __init gic_init_irq(void)
> gic_cpu_base = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_512);
> BUG_ON(!gic_cpu_base);
>
> + omap_wakeupgen_init();
> +
> gic_init(0, 29, gic_dist_base_addr, gic_cpu_base);
> }
Kevin
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 02/17] omap4: pm: Add SAR RAM support
2011-02-19 10:42 ` [PATCH 02/17] omap4: pm: Add SAR RAM support Santosh Shilimkar
@ 2011-03-02 21:56 ` Kevin Hilman
2011-03-03 16:08 ` Santosh Shilimkar
0 siblings, 1 reply; 55+ messages in thread
From: Kevin Hilman @ 2011-03-02 21:56 UTC (permalink / raw)
To: linux-arm-kernel
Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
> This patch adds SAR RAM support on OMAP4430. SAR RAM used to save
> and restore the HW context in low power modes.
>
> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Reviewed-by: Kevin Hilman <khilman@ti.com>
> ---
> arch/arm/mach-omap2/omap4-common.c | 25 ++++++++++++++++++++++++-
> arch/arm/mach-omap2/omap4-sar-layout.h | 24 ++++++++++++++++++++++++
> arch/arm/plat-omap/include/plat/omap44xx.h | 1 +
> 3 files changed, 49 insertions(+), 1 deletions(-)
> create mode 100644 arch/arm/mach-omap2/omap4-sar-layout.h
>
> diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
> index 559d227..48484a5 100644
> --- a/arch/arm/mach-omap2/omap4-common.c
> +++ b/arch/arm/mach-omap2/omap4-common.c
> @@ -23,12 +23,14 @@
> #include <mach/omap4-common.h>
> #include <mach/omap-wakeupgen.h>
>
> +#include "omap4-sar-layout.h"
> +
> #ifdef CONFIG_CACHE_L2X0
> void __iomem *l2cache_base;
> #endif
>
> void __iomem *gic_dist_base_addr;
> -
> +void __iomem *sar_ram_base;
>
> void __init gic_init_irq(void)
> {
> @@ -107,3 +109,24 @@ static int __init omap_l2_cache_init(void)
> }
> early_initcall(omap_l2_cache_init);
> #endif
> +
> +/*
> + * SAR RAM used to save and restore the HW
> + * context in low power modes
> + */
> +static int __init omap4_sar_ram_init(void)
> +{
> + /*
> + * To avoid code running on other OMAPs in
> + * multi-omap builds
> + */
> + if (!cpu_is_omap44xx())
> + return -ENODEV;
> +
> + /* Static mapping, never released */
> + sar_ram_base = ioremap(OMAP44XX_SAR_RAM_BASE, SZ_8K);
> + BUG_ON(!sar_ram_base);
Again, a BUG is not approprate here.
Instead, other code needs to properly handle when sar_ram_base == NULL
> + return 0;
> +}
> +early_initcall(omap4_sar_ram_init);
> diff --git a/arch/arm/mach-omap2/omap4-sar-layout.h b/arch/arm/mach-omap2/omap4-sar-layout.h
> new file mode 100644
> index 0000000..bb66816
> --- /dev/null
> +++ b/arch/arm/mach-omap2/omap4-sar-layout.h
> @@ -0,0 +1,24 @@
> +/*
> + * omap4-sar-layout.h: OMAP4 SAR RAM layout header file
> + *
> + * Copyright (C) 2011 Texas Instruments, Inc.
> + * Santosh Shilimkar <santosh.shilimkar@ti.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +#ifndef OMAP_ARCH_OMAP4_SAR_LAYOUT_H
> +#define OMAP_ARCH_OMAP4_SAR_LAYOUT_H
> +
> +/*
> + * SAR BANK offsets from base address OMAP44XX_SAR_RAM_BASE
> + */
> +#define SAR_BANK1_OFFSET 0x0000
> +#define SAR_BANK2_OFFSET 0x1000
> +#define SAR_BANK3_OFFSET 0x2000
> +#define SAR_BANK4_OFFSET 0x3000
> +
> +extern void __iomem *sar_ram_base;
This patch creates this as global, but has no global users.
Also, personally, I don't like these 'base address as global pointer'
that are appearing throughout the OMAP4 code. This one is continuing
the pattern of some others (gic_dist_base_addr, gic_cpu_base) etc., but
I'm not crazy about them. BTW, the gic* ones also suffer from the BUG
problem and do not properly handle error conditions.
It would be much cleaner to keep this base address static (and local)
and just create some sar_read/write helpers that can be used from other
code.
Hmm, I see the assembly code uses this base address to. For that, a
helper function to get the base address could be created.
Kevin
> +#endif
> diff --git a/arch/arm/plat-omap/include/plat/omap44xx.h b/arch/arm/plat-omap/include/plat/omap44xx.h
> index ea2b8a6..c0d478e 100644
> --- a/arch/arm/plat-omap/include/plat/omap44xx.h
> +++ b/arch/arm/plat-omap/include/plat/omap44xx.h
> @@ -45,6 +45,7 @@
> #define OMAP44XX_WKUPGEN_BASE 0x48281000
> #define OMAP44XX_MCPDM_BASE 0x40132000
> #define OMAP44XX_MCPDM_L3_BASE 0x49032000
> +#define OMAP44XX_SAR_RAM_BASE 0x4a326000
>
> #define OMAP44XX_MAILBOX_BASE (L4_44XX_BASE + 0xF4000)
> #define OMAP44XX_HSUSB_OTG_BASE (L4_44XX_BASE + 0xAB000)
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 03/17] omap4: Export scu base address
2011-02-19 10:42 ` [PATCH 03/17] omap4: Export scu base address Santosh Shilimkar
@ 2011-03-02 21:58 ` Kevin Hilman
2011-03-03 16:09 ` Santosh Shilimkar
0 siblings, 1 reply; 55+ messages in thread
From: Kevin Hilman @ 2011-03-02 21:58 UTC (permalink / raw)
To: linux-arm-kernel
Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
> The scu base address needs to be accessed in cpu hotplug
> for power management. Hence export the same
As with previous patch, rather than export the base address itself, it
should export a helper function to get the base address
Kevin
> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Reviewed-by: Kevin Hilman <khilman@ti.com>
> ---
> arch/arm/mach-omap2/include/mach/omap4-common.h | 4 ++++
> arch/arm/mach-omap2/omap-smp.c | 2 +-
> 2 files changed, 5 insertions(+), 1 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/include/mach/omap4-common.h b/arch/arm/mach-omap2/include/mach/omap4-common.h
> index 5b0270b..0e5edd8 100644
> --- a/arch/arm/mach-omap2/include/mach/omap4-common.h
> +++ b/arch/arm/mach-omap2/include/mach/omap4-common.h
> @@ -26,6 +26,10 @@ extern void __iomem *l2cache_base;
>
> extern void __iomem *gic_dist_base_addr;
>
> +#ifdef CONFIG_SMP
> +extern void __iomem *scu_base;
> +#endif
> +
> extern void __init gic_init_irq(void);
> extern void omap_smc1(u32 fn, u32 arg);
>
> diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
> index b66cfe8..b105a29 100644
> --- a/arch/arm/mach-omap2/omap-smp.c
> +++ b/arch/arm/mach-omap2/omap-smp.c
> @@ -26,7 +26,7 @@
> #include <mach/omap4-common.h>
>
> /* SCU base address */
> -static void __iomem *scu_base;
> +void __iomem *scu_base;
>
> static DEFINE_SPINLOCK(boot_lock);
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 04/17] omap4: pm: Add CPUx OFF mode support
2011-02-19 10:42 ` [PATCH 04/17] omap4: pm: Add CPUx OFF mode support Santosh Shilimkar
@ 2011-03-02 22:12 ` Kevin Hilman
2011-03-03 16:14 ` Santosh Shilimkar
0 siblings, 1 reply; 55+ messages in thread
From: Kevin Hilman @ 2011-03-02 22:12 UTC (permalink / raw)
To: linux-arm-kernel
Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
> This patch adds the CPU0 and CPU1 off mode support. CPUX close switch
s/CPUX/CPUx/
> retention (CSWR) is not supported by hardware design.
>
> The CPUx OFF mode isn't supported on OMAP4430 ES1.0
>
> CPUx sleep code is common for hotplug, suspend and cpuilde.
s/cpuilde/CPUidle/
> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Reviewed-by: Kevin Hilman <khilman@ti.com>
> ---
> arch/arm/mach-omap2/Makefile | 4 +-
> arch/arm/mach-omap2/include/mach/omap4-common.h | 46 +++
> arch/arm/mach-omap2/omap4-mpuss-lowpower.c | 241 ++++++++++++++++
> arch/arm/mach-omap2/omap4-sar-layout.h | 14 +
> arch/arm/mach-omap2/pm44xx.c | 6 +
> arch/arm/mach-omap2/sleep44xx.S | 334 +++++++++++++++++++++++
> 6 files changed, 644 insertions(+), 1 deletions(-)
> create mode 100644 arch/arm/mach-omap2/omap4-mpuss-lowpower.c
> create mode 100644 arch/arm/mach-omap2/sleep44xx.S
>
> diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
> index 54ff219..5d94f7e 100644
> --- a/arch/arm/mach-omap2/Makefile
> +++ b/arch/arm/mach-omap2/Makefile
> @@ -63,13 +63,15 @@ obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o
> obj-$(CONFIG_ARCH_OMAP2) += sleep24xx.o pm_bus.o voltage.o
> obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o voltage.o \
> cpuidle34xx.o pm_bus.o
> -obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o voltage.o pm_bus.o
> +obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o voltage.o pm_bus.o \
> + omap4-mpuss-lowpower.o sleep44xx.o
> obj-$(CONFIG_PM_DEBUG) += pm-debug.o
> obj-$(CONFIG_OMAP_SMARTREFLEX) += sr_device.o smartreflex.o
> obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3) += smartreflex-class3.o
>
> AFLAGS_sleep24xx.o :=-Wa,-march=armv6
> AFLAGS_sleep34xx.o :=-Wa,-march=armv7-a
> +AFLAGS_sleep44xx.o :=-Wa,-march=armv7-a
>
> ifeq ($(CONFIG_PM_VERBOSE),y)
> CFLAGS_pm_bus.o += -DDEBUG
> diff --git a/arch/arm/mach-omap2/include/mach/omap4-common.h b/arch/arm/mach-omap2/include/mach/omap4-common.h
> index 0e5edd8..74c9aa7 100644
> --- a/arch/arm/mach-omap2/include/mach/omap4-common.h
> +++ b/arch/arm/mach-omap2/include/mach/omap4-common.h
> @@ -13,6 +13,9 @@
> #ifndef OMAP_ARCH_OMAP4_COMMON_H
> #define OMAP_ARCH_OMAP4_COMMON_H
>
> +#include <asm/proc-fns.h>
> +
> +#ifndef __ASSEMBLER__
> /*
> * wfi used in low power code. Directly opcode is used instead
> * of instruction to avoid mulit-omap build break
> @@ -33,4 +36,47 @@ extern void __iomem *scu_base;
> extern void __init gic_init_irq(void);
> extern void omap_smc1(u32 fn, u32 arg);
>
> +/*
> + * Read MPIDR: Multiprocessor affinity register
> + */
> +static inline unsigned int hard_smp_processor_id(void)
> +{
> + unsigned int cpunum;
> +
> + asm volatile (
> + "mrc p15, 0, %0, c0, c0, 5\n"
> + : "=r" (cpunum));
> + return cpunum &= 0x0F;
minor: lower-case hex numbers are preferred
> +}
> +
> +#if defined(CONFIG_SMP) && defined(CONFIG_PM)
s/CONFIG_PM/CONFIG_SUSPEND/
> +extern int omap4_mpuss_init(void);
> +extern int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state);
> +extern void omap4_cpu_suspend(unsigned int cpu, unsigned int save_state);
> +extern void omap4_cpu_resume(void);
> +
> +#else
> +
> +static inline int omap4_enter_lowpower(unsigned int cpu,
> + unsigned int power_state)
> +{
> + cpu_do_idle();
> + return 0;
> +}
> +
> +static inline int omap4_mpuss_init(void)
> +{
> + return 0;
> +}
> +
> +static inline void omap4_cpu_suspend(unsigned int cpu, unsigned int save_state)
> +{
> +}
> +
> +static inline void omap4_cpu_resume(void)
> +{
> +}
> +
> #endif
> +#endif /* __ASSEMBLER__ */
> +#endif /* OMAP_ARCH_OMAP4_COMMON_H */
> diff --git a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
> new file mode 100644
> index 0000000..c0f358d
> --- /dev/null
> +++ b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
> @@ -0,0 +1,241 @@
> +/*
> + * OMAP4 MPUSS low power code
> + *
> + * Copyright (C) 2011 Texas Instruments, Inc.
> + * Written by Santosh Shilimkar <santosh.shilimkar@ti.com>
> + *
> + * OMAP4430 MPUSS mainly consists of dual Cortex-A9 with per-CPU
> + * Local timer and Watchdog, GIC, SCU, PL310 L2 cache controller,
> + * CPU0 and CPU1 LPRM modules.
> + * CPU0, CPU1 and MPUSS each have there own power domain and
> + * hence multiple low power combinations of MPUSS are possible.
> + *
> + * The CPU0 and CPU1 can't support Closed switch Retention (CSWR)
> + * because the mode is not supported by hw constraints of dormant
> + * mode. While waking up from the dormant mode, a reset signal
> + * to the Cortex-A9 processor must be asserted by the external
> + * power controller.
> + *
> + * With architectural inputs and hardware recommendations, only
> + * below modes are supported from power gain vs latency point of view.
> + *
> + * CPU0 CPU1 MPUSS
> + * ----------------------------------------------
> + * ON ON ON
> + * ON(Inactive) OFF ON(Inactive)
> + * OFF OFF CSWR
> + * OFF OFF OSWR (*TBD)
> + * OFF OFF OFF* (*TBD)
> + * ----------------------------------------------
> + *
> + * Note: CPU0 is the master core and it is the last CPU to go down
> + * and first to wake-up when MPUSS low power states are excercised
> + *
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/io.h>
> +#include <linux/errno.h>
> +#include <linux/linkage.h>
> +#include <linux/smp.h>
> +
> +#include <asm/cacheflush.h>
> +#include <asm/tlbflush.h>
> +#include <asm/smp_scu.h>
> +#include <asm/system.h>
> +
> +#include <plat/omap44xx.h>
> +#include <mach/omap4-common.h>
> +
> +#include "omap4-sar-layout.h"
> +#include "pm.h"
> +#include "powerdomain.h"
> +
> +#ifdef CONFIG_SMP
> +
> +#define CPU0_ID 0x0
> +#define CPU1_ID 0x1
These are also defined in the wakeupgen module, and are not really
needed. As these are only ever used in per_cpu() context, just using
the number directly is fine with me.
> +struct omap4_cpu_pm_info {
> + struct powerdomain *pwrdm;
> + void __iomem *scu_sar_addr;
> +};
> +
> +static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info);
> +
> +/*
> + * Set the CPUx powerdomain's previous power state
> + */
> +static inline void set_cpu_next_pwrst(unsigned int cpu_id,
> + unsigned int power_state)
> +{
> + struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);
> +
> + pwrdm_set_next_pwrst(pm_info->pwrdm, power_state);
> +}
> +
> +/*
> + * Read CPU's previous power state
> + */
> +static inline unsigned int read_cpu_prev_pwrst(unsigned int cpu_id)
> +{
> + struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);
> +
> + return pwrdm_read_prev_pwrst(pm_info->pwrdm);
> +}
> +
> +/*
> + * Clear the CPUx powerdomain's previous power state
> + */
> +static inline void clear_cpu_prev_pwrst(unsigned int cpu_id)
> +{
> + struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);
> +
> + pwrdm_clear_all_prev_pwrst(pm_info->pwrdm);
> +}
> +
> +/*
> + * Store the SCU power status value to scratchpad memory
> + */
> +static void scu_pwrst_prepare(unsigned int cpu_id, unsigned int cpu_state)
> +{
> + struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);
> + u32 scu_pwr_st;
> +
> + switch (cpu_state) {
> + case PWRDM_POWER_RET:
> + scu_pwr_st = SCU_PM_DORMANT;
> + break;
> + case PWRDM_POWER_OFF:
> + scu_pwr_st = SCU_PM_POWEROFF;
> + break;
> + case PWRDM_POWER_ON:
> + case PWRDM_POWER_INACTIVE:
> + default:
> + scu_pwr_st = SCU_PM_NORMAL;
> + break;
> + }
> +
> + __raw_writel(scu_pwr_st, pm_info->scu_sar_addr);
> +}
> +
> +/*
> + * OMAP4 MPUSS Low Power Entry Function
> + *
> + * The purpose of this function is to manage low power programming
> + * of OMAP4 MPUSS subsystem
> + * Paramenters:
> + * cpu : CPU ID
> + * power_state: Targetted Low power state.
> + */
> +int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
> +{
> + unsigned int save_state = 0;
> + unsigned int wakeup_cpu = hard_smp_processor_id();
> +
> + if ((cpu > NR_CPUS) || (omap_rev() == OMAP4430_REV_ES1_0))
> + goto ret;
> +
> + switch (power_state) {
> + case PWRDM_POWER_ON:
> + case PWRDM_POWER_INACTIVE:
> + save_state = 0;
> + break;
> + case PWRDM_POWER_OFF:
> + save_state = 1;
> + break;
> + case PWRDM_POWER_RET:
> + default:
> + /*
> + * CPUx CSWR is invalid hardware state. Also CPUx OSWR
> + * doesn't make much scense, since logic is lost and $L1
> + * needs to be cleaned because of coherency. This makes
> + * CPUx OSWR equivalent to CPUX OFF and hence not supported
> + */
a WARN() of some sort here would probably be useful to detect incorrect
programming of power state.
> + goto ret;
> + }
> +
> + clear_cpu_prev_pwrst(cpu);
> + set_cpu_next_pwrst(cpu, power_state);
> + scu_pwrst_prepare(cpu, power_state);
> +
> + /*
> + * Call low level function with targeted CPU id
> + * and its low power state.
> + */
> + omap4_cpu_suspend(cpu, save_state);
> +
> + /*
> + * Restore the CPUx power state to ON otherwise CPUx
> + * power domain can transitions to programmed low power
> + * state while doing WFI outside the low powe code. On
> + * secure devices, CPUx does WFI which can result in
> + * domain transition
> + */
> + wakeup_cpu = hard_smp_processor_id();
> + set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON);
> +
> +ret:
> + return 0;
> +}
> +
> +/*
> + * Initialise OMAP4 MPUSS
> + */
> +int __init omap4_mpuss_init(void)
> +{
> + struct omap4_cpu_pm_info *pm_info;
> +
> + if (omap_rev() == OMAP4430_REV_ES1_0) {
> + WARN(1, "Power Management not supported on OMAP4430 ES1.0\n");
> + return -EPERM;
-ENODEV is probably more appropriate here
> + }
> +
> + /* Initilaise per CPU PM information */
> + pm_info = &per_cpu(omap4_pm_info, CPU0_ID);
> + pm_info->scu_sar_addr = sar_ram_base + SCU_OFFSET0;
> + pm_info->pwrdm = pwrdm_lookup("cpu0_pwrdm");
> + if (!pm_info->pwrdm) {
> + pr_err("Lookup failed for CPU0 pwrdm\n");
> + return -ENODEV;
> + }
> +
> + /* Clear CPU previous power domain state */
> + pwrdm_clear_all_prev_pwrst(pm_info->pwrdm);
> +
> + /* Initialise CPU0 power domain state to ON */
> + pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON);
> +
> + pm_info = &per_cpu(omap4_pm_info, CPU1_ID);
> + pm_info->scu_sar_addr = sar_ram_base + SCU_OFFSET1;
> + pm_info->pwrdm = pwrdm_lookup("cpu1_pwrdm");
> + if (!pm_info->pwrdm) {
> + pr_err("Lookup failed for CPU1 pwrdm\n");
> + return -ENODEV;
> + }
> +
> + /* Clear CPU previous power domain state */
> + pwrdm_clear_all_prev_pwrst(pm_info->pwrdm);
> +
> + /* Initialise CPU1 power domain state to ON */
> + pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON);
> +
> + /*
> + * Program the wakeup routine address for the CPU0 and CPU1
> + * used for OFF or DORMANT wakeup. Wakeup routine address
> + * is fixed so programit in init itself.
> + */
> + __raw_writel(virt_to_phys(omap4_cpu_resume),
> + sar_ram_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET);
> + __raw_writel(virt_to_phys(omap4_cpu_resume),
> + sar_ram_base + CPU0_WAKEUP_NS_PA_ADDR_OFFSET);
> +
> + return 0;
> +}
> +
> +#endif
> +
> diff --git a/arch/arm/mach-omap2/omap4-sar-layout.h b/arch/arm/mach-omap2/omap4-sar-layout.h
> index bb66816..c4251db 100644
> --- a/arch/arm/mach-omap2/omap4-sar-layout.h
> +++ b/arch/arm/mach-omap2/omap4-sar-layout.h
> @@ -19,6 +19,20 @@
> #define SAR_BANK3_OFFSET 0x2000
> #define SAR_BANK4_OFFSET 0x3000
>
> +/* Scratch pad memory offsets from SAR_BANK1 */
> +#define CPU0_SAVE_OFFSET 0xb00
> +#define CPU1_SAVE_OFFSET 0xc00
> +#define MMU_OFFSET 0xd00
> +#define SCU_OFFSET0 0xd20
> +#define SCU_OFFSET1 0xd24
> +
> +/* CPUx Wakeup Non-Secure Physical Address offsets in SAR_BANK3 */
> +#define CPU0_WAKEUP_NS_PA_ADDR_OFFSET 0xa04
> +#define CPU1_WAKEUP_NS_PA_ADDR_OFFSET 0xa08
> +
> +#ifndef __ASSEMBLER__
> +
> extern void __iomem *sar_ram_base;
>
> #endif
> +#endif
> diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
> index 8431d41..b142673 100644
> --- a/arch/arm/mach-omap2/pm44xx.c
> +++ b/arch/arm/mach-omap2/pm44xx.c
> @@ -115,6 +115,12 @@ static int __init omap4_pm_init(void)
>
> /* Enable autoidle for all clks which support it*/
> omap_clk_enable_autoidle();
> +
> + ret = omap4_mpuss_init();
> + if (ret) {
> + pr_err("Failed to initialise OMAP4 MPUSS\n");
> + goto err2;
> + }
> #endif
>
> #ifdef CONFIG_SUSPEND
> diff --git a/arch/arm/mach-omap2/sleep44xx.S b/arch/arm/mach-omap2/sleep44xx.S
> new file mode 100644
> index 0000000..bb42a7a
> --- /dev/null
> +++ b/arch/arm/mach-omap2/sleep44xx.S
> @@ -0,0 +1,334 @@
> +/*
> + * OMAP44xx CPU low power powerdown and powerup code.
> + *
> + * Copyright (C) 2011 Texas Instruments, Inc.
> + * Written by Santosh Shilimkar <santosh.shilimkar@ti.com>
> + *
> + * This program is free software,you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/linkage.h>
> +#include <asm/system.h>
> +#include <asm/smp_scu.h>
> +#include <asm/memory.h>
> +
> +#include <plat/omap44xx.h>
> +#include <mach/omap4-common.h>
> +#include <asm/hardware/cache-l2x0.h>
> +
> +#include "omap4-sar-layout.h"
> +
> +#ifdef CONFIG_SMP
> +
> +/* Masks used for MMU manipulation */
> +#define TTRBIT_MASK 0xffffc000
> +#define TABLE_INDEX_MASK 0xfff00000
> +#define TABLE_ENTRY 0x00000c02
> +#define CACHE_DISABLE_MASK 0xffffe7fb
> +
> +/*
> + * =============================
> + * == CPU suspend entry point ==
> + * =============================
> + *
> + * void omap4_cpu_suspend(unsigned int cpu, unsigned int save_state)
> + *
> + * This function code saves the CPU context and performs the CPU
> + * power down sequence. Calling WFI effectively changes the CPU
> + * power domains states to the desired target power state.
> + *
> + * @cpu : contains cpu id (r0)
> + * @save_state : contains context save state (r1)
> + * 0 - No context lost
> + * 1 - CPUx L1 and logic lost: MPUSS CSWR
> + * 2 - CPUx L1 and logic lost + GIC lost: MPUSS OSWR
> + * 3 - CPUx L1 and logic lost + GIC + L2 lost: MPUSS OFF
> + * @return: This function never returns for CPU OFF and DORMANT power states.
> + * It retunrs to the caller for CPU INACTIVE and ON power states or in case
typo: returns
> + * CPU failed to transition to targeted OFF/DORMANT state.
to avoid confusion, what happens for OFF/dormant should probably be
summarized too.
I didn't do a detailed review of the below assembly since you're much
more knowlegable there than me.
However, will the assembly code here work in Thumb-2 mode? Dave Martin
has been working on that for OMAP3, but we should make sure the OMAP4
stuff is Thumb-2 ready out of the box.
[...]
Kevin
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 05/17] omap4: pm: Initialise all the clockdomains to supported states
2011-02-19 10:42 ` [PATCH 05/17] omap4: pm: Initialise all the clockdomains to supported states Santosh Shilimkar
@ 2011-03-02 22:17 ` Kevin Hilman
2011-03-03 16:14 ` Santosh Shilimkar
0 siblings, 1 reply; 55+ messages in thread
From: Kevin Hilman @ 2011-03-02 22:17 UTC (permalink / raw)
To: linux-arm-kernel
Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
> Initialise hardware supervised mode for all clockdomains if it's
> supported. Initiate sleep transition for other clockdomains,
> if they are not being used.
>
> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Signed-off-by: Rajendra Nayak <rnayak@ti.com>
> Reviewed-by: Kevin Hilman <khilman@ti.com>
> ---
> arch/arm/mach-omap2/pm44xx.c | 22 +++++++++++++++++++++-
> 1 files changed, 21 insertions(+), 1 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
> index b142673..9a9dc41 100644
> --- a/arch/arm/mach-omap2/pm44xx.c
> +++ b/arch/arm/mach-omap2/pm44xx.c
> @@ -17,9 +17,11 @@
> #include <linux/slab.h>
> #include <plat/clock.h>
>
> -#include "powerdomain.h"
> #include <mach/omap4-common.h>
>
> +#include "powerdomain.h"
> +#include "clockdomain.h"
> +
> struct power_state {
> struct powerdomain *pwrdm;
> u32 next_state;
> @@ -74,6 +76,22 @@ static const struct platform_suspend_ops omap_pm_ops = {
> };
> #endif /* CONFIG_SUSPEND */
>
> +/*
> + * Enable hardwarew supervised mode for all clockdomains if it's
typo: hardware
> + * supported. Initiate sleep transition for other clockdomains, if
> + * they are not used
> + */
> +static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
> +{
> + if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
> + clkdm_allow_idle(clkdm);
> + else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&
> + atomic_read(&clkdm->usecount) == 0)
> + clkdm_sleep(clkdm);
> + return 0;
> +}
> +
> +
> static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
> {
> struct power_state *pwrst;
> @@ -116,6 +134,8 @@ static int __init omap4_pm_init(void)
> /* Enable autoidle for all clks which support it*/
> omap_clk_enable_autoidle();
>
> + (void) clkdm_for_each(clkdms_setup, NULL);
> +
> ret = omap4_mpuss_init();
> if (ret) {
> pr_err("Failed to initialise OMAP4 MPUSS\n");
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 07/17] omap4: pm: CPU1 wakeup workaround form Low power modes
2011-02-19 10:42 ` [PATCH 07/17] omap4: pm: CPU1 wakeup workaround form Low power modes Santosh Shilimkar
@ 2011-03-02 22:23 ` Kevin Hilman
2011-03-03 16:15 ` Santosh Shilimkar
2011-03-02 23:44 ` Kevin Hilman
1 sibling, 1 reply; 55+ messages in thread
From: Kevin Hilman @ 2011-03-02 22:23 UTC (permalink / raw)
To: linux-arm-kernel
Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
> The SGI(Software Generated Interrupts) are not wakeup capable from
> low power states. This is known limitation on OMAP4 and needs to be
> worked around by using software forced clockdomain wake-up. CPU0 forces
> the CPU1 clockdomain to software force wakeup. After the wakeup, CPU1
> restores its clockdomain hardware supervised mode.
>
> More details can be found in OMAP4430 TRM - Version J
> Section :
> 4.3.4.2 Power States of CPU0 and CPU1
>
> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Reviewed-by: Kevin Hilman <khilman@ti.com>
> ---
> arch/arm/mach-omap2/omap-hotplug.c | 9 +++++++++
> arch/arm/mach-omap2/omap-smp.c | 27 ++++++++++++++++++++++++++-
> 2 files changed, 35 insertions(+), 1 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/omap-hotplug.c b/arch/arm/mach-omap2/omap-hotplug.c
> index 9f8f097..cf4ab15 100644
> --- a/arch/arm/mach-omap2/omap-hotplug.c
> +++ b/arch/arm/mach-omap2/omap-hotplug.c
> @@ -23,6 +23,7 @@
> #include <mach/omap-wakeupgen.h>
>
> #include "powerdomain.h"
> +#include "clockdomain.h"
>
> int platform_cpu_kill(unsigned int cpu)
> {
> @@ -36,6 +37,11 @@ int platform_cpu_kill(unsigned int cpu)
> void platform_cpu_die(unsigned int cpu)
> {
> unsigned int this_cpu;
> + static struct clockdomain *cpu1_clkdm;
> +
> + /* To avoid cpu1 clockdomain lookup every time */
minor: comment doesn't really match code and could just be removed
> + if (!cpu1_clkdm)
> + cpu1_clkdm = clkdm_lookup("mpu1_clkdm");
>
> flush_cache_all();
> dsb();
> @@ -59,6 +65,9 @@ void platform_cpu_die(unsigned int cpu)
> * OK, proper wakeup, we're done
> */
> omap_wakeupgen_irqmask_all(this_cpu, 0);
> +
> + /* Restore clockdomain to hardware supervised */
> + clkdm_allow_idle(cpu1_clkdm);
> break;
> }
> pr_debug("CPU%u: spurious wakeup call\n", cpu);
> diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
> index b105a29..31c9b79 100644
> --- a/arch/arm/mach-omap2/omap-smp.c
> +++ b/arch/arm/mach-omap2/omap-smp.c
> @@ -25,6 +25,8 @@
> #include <mach/hardware.h>
> #include <mach/omap4-common.h>
>
> +#include "clockdomain.h"
> +
> /* SCU base address */
> void __iomem *scu_base;
>
> @@ -48,6 +50,8 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
>
> int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
> {
> + static struct clockdomain *cpu1_clkdm;
> + static bool booted;
> /*
> * Set synchronisation state between this boot processor
> * and the secondary one
> @@ -63,7 +67,28 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
> omap_modify_auxcoreboot0(0x200, 0xfffffdff);
> flush_cache_all();
> smp_wmb();
> - smp_cross_call(cpumask_of(cpu), 1);
> +
> + /* To avoid cpu1 clockdomain lookup every time */
ditto
> + if (!cpu1_clkdm)
> + cpu1_clkdm = clkdm_lookup("mpu1_clkdm");
> +
> + /*
> + * The SGI(Software Generated Interrupts) are not wakeup capable
> + * from low power states. This is known limitation on OMAP4 and
> + * needs to be worked around by using software forced clockdomain
> + * wake-up. To wakeup CPU1, CPU0 forces the CPU1 clockdomain to
> + * software force wakeup. After the wakeup, CPU1 restores its
> + * clockdomain hardware supervised mode.
> + * More details can be found in OMAP4430 TRM - Version J
> + * Section :
> + * 4.3.4.2 Power States of CPU0 and CPU1
> + */
> + if (booted) {
> + clkdm_wakeup(cpu1_clkdm);
> + } else {
> + dsb_sev();
> + booted = true;
> + }
>
> /*
> * Now the secondary core is starting up let it run its
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 08/17] omap4: pm: Add GIC save/restore support
2011-02-19 10:42 ` [PATCH 08/17] omap4: pm: Add GIC save/restore support Santosh Shilimkar
@ 2011-03-02 22:29 ` Kevin Hilman
2011-03-03 16:29 ` Santosh Shilimkar
2011-03-04 8:39 ` Santosh Shilimkar
0 siblings, 2 replies; 55+ messages in thread
From: Kevin Hilman @ 2011-03-02 22:29 UTC (permalink / raw)
To: linux-arm-kernel
Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
> On OMAP4 when attempting MPU off-mode or OSWR, the GIC context is
> lost. This patch adds GIC context save and restore support.
>
> The context save is done by software and restore is done by
> ROM code from predefined SAR locations where the context suppose
s/suppose/supposed/
> to be saved. Refer to ROM code specs for the GIC layout details.
Does this doc have a name? I've never seen such a thing and would
really like to.
> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Reviewed-by: Kevin Hilman <khilman@ti.com>
> ---
> arch/arm/mach-omap2/omap-hotplug.c | 4 +
> arch/arm/mach-omap2/omap4-mpuss-lowpower.c | 176 +++++++++++++++++++++++++++-
> arch/arm/mach-omap2/omap4-sar-layout.h | 20 +++
> 3 files changed, 199 insertions(+), 1 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/omap-hotplug.c b/arch/arm/mach-omap2/omap-hotplug.c
> index cf4ab15..deab389 100644
> --- a/arch/arm/mach-omap2/omap-hotplug.c
> +++ b/arch/arm/mach-omap2/omap-hotplug.c
> @@ -19,6 +19,8 @@
> #include <linux/smp.h>
>
> #include <asm/cacheflush.h>
> +#include <asm/hardware/gic.h>
> +
> #include <mach/omap4-common.h>
> #include <mach/omap-wakeupgen.h>
>
> @@ -58,6 +60,7 @@ void platform_cpu_die(unsigned int cpu)
> * clear all interrupt wakeup sources
> */
> omap_wakeupgen_irqmask_all(cpu, 1);
> + gic_secondary_set(0, true);
> omap4_enter_lowpower(cpu, PWRDM_POWER_OFF);
> this_cpu = hard_smp_processor_id();
> if (omap_read_auxcoreboot0() == this_cpu) {
> @@ -65,6 +68,7 @@ void platform_cpu_die(unsigned int cpu)
> * OK, proper wakeup, we're done
> */
> omap_wakeupgen_irqmask_all(this_cpu, 0);
> + gic_secondary_set(0, false);
>
> /* Restore clockdomain to hardware supervised */
> clkdm_allow_idle(cpu1_clkdm);
> diff --git a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
> index c0f358d..4140251 100644
> --- a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
> +++ b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
> @@ -47,6 +47,8 @@
> #include <asm/tlbflush.h>
> #include <asm/smp_scu.h>
> #include <asm/system.h>
> +#include <asm/irq.h>
> +#include <asm/hardware/gic.h>
>
> #include <plat/omap44xx.h>
> #include <mach/omap4-common.h>
> @@ -59,6 +61,19 @@
>
> #define CPU0_ID 0x0
> #define CPU1_ID 0x1
> +#define GIC_MASK_ALL 0x0
> +#define GIC_ISR_NON_SECURE 0xffffffff
> +#define SPI_ENABLE_SET_OFFSET 0x04
> +#define PPI_PRI_OFFSET 0x1c
> +#define SPI_PRI_OFFSET 0x20
> +#define SPI_TARGET_OFFSET 0x20
> +#define SPI_CONFIG_OFFSET 0x20
> +
> +/* GIC save SAR bank base */
> +static struct powerdomain *mpuss_pd;
> +
> +/* Variables to store maximum spi(Shared Peripheral Interrupts) registers. */
> +static u32 max_spi_irq, max_spi_reg;
>
> struct omap4_cpu_pm_info {
> struct powerdomain *pwrdm;
> @@ -67,6 +82,17 @@ struct omap4_cpu_pm_info {
>
> static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info);
>
> +/* Helper functions */
> +static inline void sar_writel(u32 val, u32 offset, u8 idx)
> +{
> + __raw_writel(val, sar_ram_base + offset + 4 * idx);
> +}
aha, this is what I was thinking of in the earlier SAR patch.
Something like this should be part of the SAR code, not here.
> +static inline u32 gic_readl(u32 offset, u8 idx)
> +{
> + return __raw_readl(gic_dist_base_addr + offset + 4 * idx);
> +}
Similarily, it would be nice tos see this as part of GIC code so
this code doesn't have to access a global base address pointer.
> /*
> * Set the CPUx powerdomain's previous power state
> */
> @@ -124,6 +150,85 @@ static void scu_pwrst_prepare(unsigned int cpu_id, unsigned int cpu_state)
> }
>
> /*
> + * Save GIC context in SAR RAM. Restore is done by ROM code
> + * GIC is lost only when MPU hits OSWR or OFF. It consists
> + * of a distributor and a per-CPU interface module. The GIC
> + * save restore is optimised to save only necessary registers.
> + */
> +static void gic_save_context(void)
> +{
> + u8 i;
> + u32 val;
> +
> + /*
> + * Interrupt Clear Enable registers are inverse of set enable
> + * and hence not needed to be saved. ROM code programs it
> + * based on Set Enable register values.
> + */
> +
> + /* Save CPU 0 Interrupt Set Enable register */
> + val = gic_readl(GIC_DIST_ENABLE_SET, 0);
> + sar_writel(val, ICDISER_CPU0_OFFSET, 0);
> +
> + /* Disable interrupts on CPU1 */
> + sar_writel(GIC_MASK_ALL, ICDISER_CPU1_OFFSET, 0);
> +
> + /* Save all SPI Set Enable register */
> + for (i = 0; i < max_spi_reg; i++) {
> + val = gic_readl(GIC_DIST_ENABLE_SET + SPI_ENABLE_SET_OFFSET, i);
> + sar_writel(val, ICDISER_SPI_OFFSET, i);
> + }
> +
> + /*
> + * Interrupt Priority Registers
> + * Secure sw accesses, last 5 bits of the 8 bits (bit[7:3] are used)
> + * Non-Secure sw accesses, last 4 bits (i.e. bits[7:4] are used)
> + * But the Secure Bits[7:3] are shifted by 1 in Non-Secure access.
> + * Secure (bits[7:3] << 1)== Non Secure bits[7:4]
> + * Hence right shift the value by 1 while saving the priority
> + */
> +
> + /* Save SGI priority registers (Software Generated Interrupt) */
> + for (i = 0; i < 4; i++) {
> + val = gic_readl(GIC_DIST_PRI, i);
> +
> + /* Save the priority bits of the Interrupts */
> + sar_writel(val >> 0x1, ICDIPR_SFI_CPU0_OFFSET, i);
> +
> + /* Disable the interrupts on CPU1 */
> + sar_writel(GIC_MASK_ALL, ICDIPR_SFI_CPU1_OFFSET, i);
> + }
> +
> + /* Save PPI priority registers (Private Peripheral Intterupts) */
> + val = gic_readl(GIC_DIST_PRI + PPI_PRI_OFFSET, 0);
> + sar_writel(val >> 0x1, ICDIPR_PPI_CPU0_OFFSET, 0);
> + sar_writel(GIC_MASK_ALL, ICDIPR_PPI_CPU1_OFFSET, 0);
> +
> + /* SPI priority registers - 4 interrupts/register */
> + for (i = 0; i < (max_spi_irq / 4); i++) {
> + val = gic_readl((GIC_DIST_PRI + SPI_PRI_OFFSET), i);
> + sar_writel(val >> 0x1, ICDIPR_SPI_OFFSET, i);
> + }
> +
> + /* SPI Interrupt Target registers - 4 interrupts/register */
> + for (i = 0; i < (max_spi_irq / 4); i++) {
> + val = gic_readl((GIC_DIST_TARGET + SPI_TARGET_OFFSET), i);
> + sar_writel(val, ICDIPTR_SPI_OFFSET, i);
> + }
> +
> + /* SPI Interrupt Congigeration eegisters- 16 interrupts/register */
> + for (i = 0; i < (max_spi_irq / 16); i++) {
> + val = gic_readl((GIC_DIST_CONFIG + SPI_CONFIG_OFFSET), i);
> + sar_writel(val, ICDICFR_OFFSET, i);
> + }
> +
> + /* Set the Backup Bit Mask status for GIC */
> + val = __raw_readl(sar_ram_base + SAR_BACKUP_STATUS_OFFSET);
> + val |= (SAR_BACKUP_STATUS_GIC_CPU0 | SAR_BACKUP_STATUS_GIC_CPU1);
> + __raw_writel(val, sar_ram_base + SAR_BACKUP_STATUS_OFFSET);
> +}
> +
> +/*
> * OMAP4 MPUSS Low Power Entry Function
> *
> * The purpose of this function is to manage low power programming
> @@ -131,11 +236,25 @@ static void scu_pwrst_prepare(unsigned int cpu_id, unsigned int cpu_state)
> * Paramenters:
> * cpu : CPU ID
> * power_state: Targetted Low power state.
> + *
> + * MPUSS Low power states
> + * The basic rule is that the MPUSS power domain must be at the higher or
> + * equal power state (state that consume more power) than the higher of the
> + * two CPUs. For example, it is illegal for system power to be OFF, while
> + * the power of one or both of the CPU is DORMANT. When an illegal state is
> + * entered, then the hardware behavior is unpredictable.
> + *
> + * MPUSS state for the context save
> + * save_state =
> + * 0 - Nothing lost and no need to save: MPUSS INACTIVE
> + * 1 - CPUx L1 and logic lost: MPUSS CSWR
> + * 2 - CPUx L1 and logic lost + GIC lost: MPUSS OSWR
> + * 3 - CPUx L1 and logic lost + GIC + L2 lost: MPUSS OFF
> */
> int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
> {
> unsigned int save_state = 0;
> - unsigned int wakeup_cpu = hard_smp_processor_id();
> + unsigned int wakeup_cpu;
>
> if ((cpu > NR_CPUS) || (omap_rev() == OMAP4430_REV_ES1_0))
> goto ret;
> @@ -159,6 +278,23 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
> goto ret;
> }
>
> + /*
> + * MPUSS book keeping should be executed by master
> + * CPU only which is also the last CPU to go down.
> + */
> + if (cpu)
> + goto cpu_prepare;
> +
> + /*
> + * Check MPUSS next state and save GIC if needed
> + * GIC lost during MPU OFF and OSWR
> + */
> + if (pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_OFF) {
> + gic_save_context();
> + save_state = 3;
> + }
> +
> +cpu_prepare:
> clear_cpu_prev_pwrst(cpu);
> set_cpu_next_pwrst(cpu, power_state);
> scu_pwrst_prepare(cpu, power_state);
> @@ -179,6 +315,19 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
> wakeup_cpu = hard_smp_processor_id();
> set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON);
>
> + /* If !master cpu return to hotplug-path */
> + if (wakeup_cpu)
> + goto ret;
> +
> + /* Check MPUSS previous power state and enable GIC if needed */
> + if (pwrdm_read_prev_pwrst(mpuss_pd) == PWRDM_POWER_OFF) {
> + /* Clear SAR BACKUP status */
> + __raw_writel(0x0, sar_ram_base + SAR_BACKUP_STATUS_OFFSET);
> + /* Enable GIC distributor and inteface on CPU0*/
> + gic_secondary_set(CPU0_ID, 1);
> + gic_dist_set(CPU0_ID, 1);
> + }
> +
> ret:
> return 0;
> }
> @@ -189,6 +338,7 @@ ret:
> int __init omap4_mpuss_init(void)
> {
> struct omap4_cpu_pm_info *pm_info;
> + u8 i;
>
> if (omap_rev() == OMAP4430_REV_ES1_0) {
> WARN(1, "Power Management not supported on OMAP4430 ES1.0\n");
> @@ -234,6 +384,30 @@ int __init omap4_mpuss_init(void)
> __raw_writel(virt_to_phys(omap4_cpu_resume),
> sar_ram_base + CPU0_WAKEUP_NS_PA_ADDR_OFFSET);
>
> + mpuss_pd = pwrdm_lookup("mpu_pwrdm");
> + if (!mpuss_pd) {
> + pr_err("Failed to get lookup for MPUSS pwrdm\n");
> + return -ENODEV;
> + }
> +
> + /*
> + * Find out how many interrupts are supported.
> + * OMAP4 supports max of 128 SPIs where as GIC can support
> + * up to 1020 interrupt sources.
> + */
> + max_spi_reg = __raw_readl(gic_dist_base_addr + GIC_DIST_CTR) & 0x1f;
> + max_spi_irq = max_spi_reg * 32;
Based on the spec, this should also be max'd at 1020 so you never write
the reserved values after 1020.
Kevin
> + /*
> + * Mark the PPI and SPI interrupts as non-secure.
> + * program the SAR locations for interrupt security registers to
> + * reflect the same.
> + */
> + sar_writel(GIC_ISR_NON_SECURE, ICDISR_CPU0_OFFSET, 0);
> + sar_writel(GIC_ISR_NON_SECURE, ICDISR_CPU1_OFFSET, 0);
> + for (i = 0; i < max_spi_reg; i++)
> + sar_writel(GIC_ISR_NON_SECURE, ICDISR_SPI_OFFSET, i);
> +
> return 0;
> }
>
> diff --git a/arch/arm/mach-omap2/omap4-sar-layout.h b/arch/arm/mach-omap2/omap4-sar-layout.h
> index c4251db..0a19f49 100644
> --- a/arch/arm/mach-omap2/omap4-sar-layout.h
> +++ b/arch/arm/mach-omap2/omap4-sar-layout.h
> @@ -30,6 +30,26 @@
> #define CPU0_WAKEUP_NS_PA_ADDR_OFFSET 0xa04
> #define CPU1_WAKEUP_NS_PA_ADDR_OFFSET 0xa08
>
> + /* GIC save restore offset from SAR_BANK3 */
> +#define SAR_BACKUP_STATUS_OFFSET (SAR_BANK3_OFFSET + 0x500)
> +#define SAR_SECURE_RAM_SIZE_OFFSET (SAR_BANK3_OFFSET + 0x504)
> +#define SAR_SECRAM_SAVED_AT_OFFSET (SAR_BANK3_OFFSET + 0x508)
> +#define ICDISR_CPU0_OFFSET (SAR_BANK3_OFFSET + 0x50c)
> +#define ICDISR_CPU1_OFFSET (SAR_BANK3_OFFSET + 0x510)
> +#define ICDISR_SPI_OFFSET (SAR_BANK3_OFFSET + 0x514)
> +#define ICDISER_CPU0_OFFSET (SAR_BANK3_OFFSET + 0x524)
> +#define ICDISER_CPU1_OFFSET (SAR_BANK3_OFFSET + 0x528)
> +#define ICDISER_SPI_OFFSET (SAR_BANK3_OFFSET + 0x52c)
> +#define ICDIPR_SFI_CPU0_OFFSET (SAR_BANK3_OFFSET + 0x53c)
> +#define ICDIPR_PPI_CPU0_OFFSET (SAR_BANK3_OFFSET + 0x54c)
> +#define ICDIPR_SFI_CPU1_OFFSET (SAR_BANK3_OFFSET + 0x550)
> +#define ICDIPR_PPI_CPU1_OFFSET (SAR_BANK3_OFFSET + 0x560)
> +#define ICDIPR_SPI_OFFSET (SAR_BANK3_OFFSET + 0x564)
> +#define ICDIPTR_SPI_OFFSET (SAR_BANK3_OFFSET + 0x5e4)
> +#define ICDICFR_OFFSET (SAR_BANK3_OFFSET + 0x664)
> +#define SAR_BACKUP_STATUS_GIC_CPU0 0x1
> +#define SAR_BACKUP_STATUS_GIC_CPU1 0x2
> +
> #ifndef __ASSEMBLER__
>
> extern void __iomem *sar_ram_base;
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 09/17] omap4: pm: Add WakeupGen save/restore support
2011-02-19 10:42 ` [PATCH 09/17] omap4: pm: Add WakeupGen " Santosh Shilimkar
@ 2011-03-02 22:34 ` Kevin Hilman
0 siblings, 0 replies; 55+ messages in thread
From: Kevin Hilman @ 2011-03-02 22:34 UTC (permalink / raw)
To: linux-arm-kernel
Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
> WakeupGen is lost only when device hits off-mode. Though the register
> context is retained in MPUSS OFF/OSWR state, hardware recommondation is
> to save/restore WakeupGen along with GIC to have consistent interrupt
> state at both the blocks. The ROM code restore mechinism also does
> restore of wakeupgen on mpu OFF/OSWR
Changelog needs some clarification...
The way I read the above is that "save is not needed, but we do it
anyways for consistency"
It's not terribly clear (to me) how "consistent state" would be lost
if this does not happen.
IOW, describing a potential inconsistent state would be helpful for the
changelog (and code.)
> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Reviewed-by: Kevin Hilman <khilman@ti.com>
> ---
> arch/arm/mach-omap2/include/mach/omap-wakeupgen.h | 1 +
> arch/arm/mach-omap2/omap-wakeupgen.c | 74 +++++++++++++++++++++
> arch/arm/mach-omap2/omap4-mpuss-lowpower.c | 2 +
> arch/arm/mach-omap2/omap4-sar-layout.h | 11 +++
> 4 files changed, 88 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/include/mach/omap-wakeupgen.h b/arch/arm/mach-omap2/include/mach/omap-wakeupgen.h
> index f10d106..66f31c3 100644
> --- a/arch/arm/mach-omap2/include/mach/omap-wakeupgen.h
> +++ b/arch/arm/mach-omap2/include/mach/omap-wakeupgen.h
> @@ -37,4 +37,5 @@
>
> extern int __init omap_wakeupgen_init(void);
> extern void omap_wakeupgen_irqmask_all(unsigned int cpu, unsigned int set);
> +extern void omap_wakeupgen_save(void);
> #endif
> diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c
> index e26a0ed..0f0a5ed 100644
> --- a/arch/arm/mach-omap2/omap-wakeupgen.c
> +++ b/arch/arm/mach-omap2/omap-wakeupgen.c
> @@ -24,6 +24,9 @@
> #include <asm/hardware/gic.h>
>
> #include <mach/omap-wakeupgen.h>
> +#include <mach/omap4-common.h>
> +
> +#include "omap4-sar-layout.h"
>
> #define NR_BANKS 4
> #define MAX_IRQS 128
> @@ -54,6 +57,11 @@ static inline void cpu_writel(u32 val, u8 idx, u32 cpu)
> (cpu * CPU_ENA_OFFSET) + (idx * 4));
> }
>
> +static inline void sar_writel(u32 val, u32 offset, u8 idx)
> +{
> + __raw_writel(val, sar_ram_base + offset + (idx * 4));
> +}
> +
aha, another function that belongs in the SAR code.
[...]
Kevin
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 10/17] omap4: pm: Add L2 cache lowpower support
2011-02-19 10:42 ` [PATCH 10/17] omap4: pm: Add L2 cache lowpower support Santosh Shilimkar
@ 2011-03-02 22:36 ` Kevin Hilman
2011-03-03 16:30 ` Santosh Shilimkar
0 siblings, 1 reply; 55+ messages in thread
From: Kevin Hilman @ 2011-03-02 22:36 UTC (permalink / raw)
To: linux-arm-kernel
Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
> When MPUSS hits off-mode e, L2 cache is lost. This patch adds L2X0
> necessary maintenance operations and context restoration in the
> low power code.
>
> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Reviewed-by: Kevin Hilman <khilman@ti.com>
> ---
> arch/arm/mach-omap2/omap4-mpuss-lowpower.c | 11 +++++
> arch/arm/mach-omap2/omap4-sar-layout.h | 2 +
> arch/arm/mach-omap2/sleep44xx.S | 64 ++++++++++++++++++++++++++++
> 3 files changed, 77 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
> index a30f19b..bff768f 100644
> --- a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
> +++ b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
> @@ -49,6 +49,7 @@
> #include <asm/system.h>
> #include <asm/irq.h>
> #include <asm/hardware/gic.h>
> +#include <asm/hardware/cache-l2x0.h>
>
> #include <plat/omap44xx.h>
> #include <mach/omap4-common.h>
> @@ -341,6 +342,7 @@ int __init omap4_mpuss_init(void)
> {
> struct omap4_cpu_pm_info *pm_info;
> u8 i;
> + u32 val;
This will cause an 'unused variable' compiler warning when
!CONFIG_CACHE_L2X0
[...]
Kevin
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 11/17] omap4: suspend: Add MPUSS RET and OFF support
2011-02-19 10:42 ` [PATCH 11/17] omap4: suspend: Add MPUSS RET and OFF support Santosh Shilimkar
@ 2011-03-02 22:45 ` Kevin Hilman
2011-03-03 16:31 ` Santosh Shilimkar
0 siblings, 1 reply; 55+ messages in thread
From: Kevin Hilman @ 2011-03-02 22:45 UTC (permalink / raw)
To: linux-arm-kernel
Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
> This patch adds MPUSS(MPU Sub System) RET and OFF mode support
> to suspend path. For both MPUSS RET and OFF support, CPUs are
> programmed to OFF state.
>
> Only MPUSS RET and OFF supported at this point of time. CORE RET
> will be added subsequently.
>
> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Reviewed-by: Kevin Hilman <khilman@ti.com>
> ---
> arch/arm/mach-omap2/omap4-mpuss-lowpower.c | 8 ++-
> arch/arm/mach-omap2/pm-debug.c | 2 +
> arch/arm/mach-omap2/pm.h | 1 +
> arch/arm/mach-omap2/pm44xx.c | 88 ++++++++++++++++++++++++++--
> 4 files changed, 93 insertions(+), 6 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
> index bff768f..ab2e101 100644
> --- a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
> +++ b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
> @@ -25,7 +25,7 @@
> * ON(Inactive) OFF ON(Inactive)
> * OFF OFF CSWR
> * OFF OFF OSWR (*TBD)
> - * OFF OFF OFF* (*TBD)
> + * OFF OFF OFF
> * ----------------------------------------------
> *
> * Note: CPU0 is the master core and it is the last CPU to go down
> @@ -291,6 +291,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
> * Check MPUSS next state and save GIC if needed
> * GIC lost during MPU OFF and OSWR
> */
> + pwrdm_clear_all_prev_pwrst(mpuss_pd);
> if (pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_OFF) {
> omap_wakeupgen_save();
> gic_save_context();
> @@ -357,6 +358,8 @@ int __init omap4_mpuss_init(void)
> pr_err("Lookup failed for CPU0 pwrdm\n");
> return -ENODEV;
> }
> + /* Clear CPU previous power domain state */
> + pwrdm_clear_all_prev_pwrst(pm_info->pwrdm);
? duplicate of lines immediately following.
> /* Clear CPU previous power domain state */
> pwrdm_clear_all_prev_pwrst(pm_info->pwrdm);
> @@ -394,6 +397,9 @@ int __init omap4_mpuss_init(void)
> return -ENODEV;
> }
>
> + /* Clear CPU previous power domain state */
> + pwrdm_clear_all_prev_pwrst(mpuss_pd);
> +
> /*
> * Find out how many interrupts are supported.
> * OMAP4 supports max of 128 SPIs where as GIC can support
> diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
> index 125f565..9b46b3e 100644
> --- a/arch/arm/mach-omap2/pm-debug.c
> +++ b/arch/arm/mach-omap2/pm-debug.c
> @@ -588,6 +588,8 @@ static int option_set(void *data, u64 val)
> omap_pm_disable_off_mode();
> if (cpu_is_omap34xx())
> omap3_pm_off_mode_enable(val);
> + else if (cpu_is_omap44xx())
> + omap4_pm_off_mode_enable(val);
> }
>
> return 0;
> diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
> index 1c1b0ab..f557407 100644
> --- a/arch/arm/mach-omap2/pm.h
> +++ b/arch/arm/mach-omap2/pm.h
> @@ -17,6 +17,7 @@
>
> extern void *omap3_secure_ram_storage;
> extern void omap3_pm_off_mode_enable(int);
> +extern void omap4_pm_off_mode_enable(int);
> extern void omap_sram_idle(void);
> extern int omap3_can_sleep(void);
> extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
> diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
> index 9a9dc41..f527e33 100644
> --- a/arch/arm/mach-omap2/pm44xx.c
> +++ b/arch/arm/mach-omap2/pm44xx.c
> @@ -1,8 +1,9 @@
> /*
> * OMAP4 Power Management Routines
> *
> - * Copyright (C) 2010 Texas Instruments, Inc.
> + * Copyright (C) 2010-2011 Texas Instruments, Inc.
> * Rajendra Nayak <rnayak@ti.com>
> + * Santosh Shilimkar <santosh.shilimkar@ti.com>
> *
> * This program is free software; you can redistribute it and/or modify
> * it under the terms of the GNU General Public License version 2 as
> @@ -21,6 +22,7 @@
>
> #include "powerdomain.h"
> #include "clockdomain.h"
> +#include "pm.h"
>
> struct power_state {
> struct powerdomain *pwrdm;
> @@ -36,7 +38,50 @@ static LIST_HEAD(pwrst_list);
> #ifdef CONFIG_SUSPEND
> static int omap4_pm_suspend(void)
> {
> - do_wfi();
> + struct power_state *pwrst;
> + int state, ret = 0;
> + u32 cpu_id = smp_processor_id();
> +
> + /* Save current powerdomain state */
> + list_for_each_entry(pwrst, &pwrst_list, node) {
> + pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm);
> + }
> +
> + /* Set targeted power domain states by suspend */
> + list_for_each_entry(pwrst, &pwrst_list, node) {
> + /* FIXME: Remove this check when CORE retention is supported */
> + if (!strcmp(pwrst->pwrdm->name, "mpu_pwrdm"))
> + omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
> + }
pwrst_list is the list of powerdomains to that will be changed during
suspend.
Rather than doing this string match for every suspend, just do the check
once during init and only add powerdomains that can transition to the
list.
> + /*
> + * For MPUSS to hit power domain retention(CSWR or OSWR),
> + * CPU0 and CPU1 power domain needs to be in OFF or DORMANT
> + * state. For MPUSS to reach off-mode. CPU0 and CPU1 power domain
> + * should be in off state.
> + * Only master CPU followes suspend path. All other CPUs follow
> + * cpu-hotplug path in system wide suspend. On OMAP4, CPU power
> + * domain CSWR is not supported by hardware.
> + * More details can be found in OMAP4430 TRM section 4.3.4.2.
> + */
> + omap4_enter_lowpower(cpu_id, PWRDM_POWER_OFF);
> +
> + /* Restore next powerdomain state */
> + list_for_each_entry(pwrst, &pwrst_list, node) {
> + state = pwrdm_read_prev_pwrst(pwrst->pwrdm);
> + if (state > pwrst->next_state) {
> + pr_info("Powerdomain (%s) didn't enter "
> + "target state %d\n",
> + pwrst->pwrdm->name, pwrst->next_state);
> + ret = -1;
> + }
> + omap_set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state);
> + }
> + if (ret)
> + pr_err("Could not enter target state in pm_suspend\n");
> + else
> + pr_err("Successfully put all powerdomains to target state\n");
> +
> return 0;
> }
>
> @@ -91,7 +136,6 @@ static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
> return 0;
> }
>
> -
stray whitespace change
> static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
> {
> struct power_state *pwrst;
> @@ -99,14 +143,48 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
> if (!pwrdm->pwrsts)
> return 0;
>
> + /*
> + * Skip CPU0 and CPU1 power domains. CPU1 is programmed
> + * through hotplug path and CPU0 explicitly programmed
> + * further down in the code path
> + */
> + if ((!strcmp(pwrdm->name, "cpu0_pwrdm")) ||
> + (!strcmp(pwrdm->name, "cpu1_pwrdm")))
> + return 0;
> +
> pwrst = kmalloc(sizeof(struct power_state), GFP_ATOMIC);
> if (!pwrst)
> return -ENOMEM;
> pwrst->pwrdm = pwrdm;
> - pwrst->next_state = PWRDM_POWER_ON;
> +
> + /* FIXME: Remove this check when core retention is supported */
> + if (!strcmp(pwrst->pwrdm->name, "mpu_pwrdm"))
> + pwrst->next_state = PWRDM_POWER_RET;
> + else
> + pwrst->next_state = PWRDM_POWER_ON;
> +
> list_add(&pwrst->node, &pwrst_list);
>
> - return pwrdm_set_next_pwrst(pwrst->pwrdm, pwrst->next_state);
> + return omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
> +}
> +
> +void omap4_pm_off_mode_enable(int enable)
> +{
> + struct power_state *pwrst;
> + u32 state;
> +
> + if (enable)
> + state = PWRDM_POWER_OFF;
> + else
> + state = PWRDM_POWER_RET;
> +
> + list_for_each_entry(pwrst, &pwrst_list, node) {
> + /* FIXME: Remove this check when core retention is supported */
> + if (!strcmp(pwrst->pwrdm->name, "mpu_pwrdm")) {
same string-match comment as above
> + pwrst->next_state = state;
> + omap_set_pwrdm_state(pwrst->pwrdm, state);
> + }
> + }
> }
>
> /**
Kevin
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 12/17] omap4: pm-debug: Add wakeup timer and debug counters
2011-02-19 10:42 ` [PATCH 12/17] omap4: pm-debug: Add wakeup timer and debug counters Santosh Shilimkar
@ 2011-03-02 22:51 ` Kevin Hilman
2011-03-03 16:34 ` Santosh Shilimkar
0 siblings, 1 reply; 55+ messages in thread
From: Kevin Hilman @ 2011-03-02 22:51 UTC (permalink / raw)
To: linux-arm-kernel
Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
> This patch adds configurable wakeup timer support in suspend. Also
> for statistics pm counter support is added.
>
> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Reviewed-by: Kevin Hilman <khilman@ti.com>
> ---
> arch/arm/mach-omap2/omap4-mpuss-lowpower.c | 8 ++++++++
> arch/arm/mach-omap2/pm-debug.c | 6 ++++--
> arch/arm/mach-omap2/pm44xx.c | 5 +++++
> 3 files changed, 17 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
> index ab2e101..5e0141e 100644
> --- a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
> +++ b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
> @@ -287,6 +287,10 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
> if (cpu)
> goto cpu_prepare;
>
> +#ifdef CONFIG_PM_DEBUG
> + pwrdm_pre_transition();
> +#endif
Why the #ifdef?
> /*
> * Check MPUSS next state and save GIC if needed
> * GIC lost during MPU OFF and OSWR
> @@ -332,6 +336,10 @@ cpu_prepare:
> gic_dist_set(CPU0_ID, 1);
> }
>
> +#ifdef CONFIG_PM_DEBUG
> + pwrdm_post_transition();
> +#endif
> +
> ret:
> return 0;
> }
> diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
> index 9b46b3e..7d6dd5b 100644
> --- a/arch/arm/mach-omap2/pm-debug.c
> +++ b/arch/arm/mach-omap2/pm-debug.c
> @@ -606,9 +606,11 @@ static int __init pm_dbg_init(void)
> if (pm_dbg_init_done)
> return 0;
>
> - if (cpu_is_omap34xx())
> + if (cpu_is_omap34xx()) {
> pm_dbg_reg_modules = omap3_pm_reg_modules;
> - else {
> + } else if (cpu_is_omap44xx()) {
> + /* Allow pm_dbg_init on OMAP4. */
Doing this will cause crashes if the 'registers/*' debugfs file is
accessed.
Since there are no 'reg_modules' created, you should also prevent the
creation of the 'registers' debugfs entries.
Kevin
> + } else {
> printk(KERN_ERR "%s: only OMAP3 supported\n", __func__);
> return -ENODEV;
> }
> diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
> index f527e33..8e57b42 100644
> --- a/arch/arm/mach-omap2/pm44xx.c
> +++ b/arch/arm/mach-omap2/pm44xx.c
> @@ -42,6 +42,11 @@ static int omap4_pm_suspend(void)
> int state, ret = 0;
> u32 cpu_id = smp_processor_id();
>
> + /* Wakeup timer from suspend */
> + if (wakeup_timer_seconds || wakeup_timer_milliseconds)
> + omap2_pm_wakeup_on_timer(wakeup_timer_seconds,
> + wakeup_timer_milliseconds);
> +
> /* Save current powerdomain state */
> list_for_each_entry(pwrst, &pwrst_list, node) {
> pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm);
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 13/17] omap4: cpuidle: Basic CPUidle support
2011-02-19 10:42 ` [PATCH 13/17] omap4: cpuidle: Basic CPUidle support Santosh Shilimkar
@ 2011-03-02 22:55 ` Kevin Hilman
0 siblings, 0 replies; 55+ messages in thread
From: Kevin Hilman @ 2011-03-02 22:55 UTC (permalink / raw)
To: linux-arm-kernel
Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
> From: Rajendra Nayak <rnayak@ti.com>
>
> The patch adds a basic CPUidle driver for OMAP4. Just
> one C state is registered for both CPU cores which
> does a wfi.
s/wfi/WFI/
> Signed-off-by: Rajendra Nayak <rnayak@ti.com>
> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Reviewed-by: Kevin Hilman <khilman@ti.com>
Mostly minor nits below...
> ---
> arch/arm/mach-omap2/Makefile | 3 +-
> arch/arm/mach-omap2/cpuidle44xx.c | 165 +++++++++++++++++++++++++++++++++++++
> arch/arm/mach-omap2/pm.h | 1 +
> arch/arm/mach-omap2/pm44xx.c | 2 +
> 4 files changed, 170 insertions(+), 1 deletions(-)
> create mode 100644 arch/arm/mach-omap2/cpuidle44xx.c
>
> diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
> index 5d94f7e..2b4fe44 100644
> --- a/arch/arm/mach-omap2/Makefile
> +++ b/arch/arm/mach-omap2/Makefile
> @@ -64,7 +64,8 @@ obj-$(CONFIG_ARCH_OMAP2) += sleep24xx.o pm_bus.o voltage.o
> obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o voltage.o \
> cpuidle34xx.o pm_bus.o
> obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o voltage.o pm_bus.o \
> - omap4-mpuss-lowpower.o sleep44xx.o
> + omap4-mpuss-lowpower.o sleep44xx.o \
> + cpuidle44xx.o
> obj-$(CONFIG_PM_DEBUG) += pm-debug.o
> obj-$(CONFIG_OMAP_SMARTREFLEX) += sr_device.o smartreflex.o
> obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3) += smartreflex-class3.o
> diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c
> new file mode 100644
> index 0000000..6c3c69d
> --- /dev/null
> +++ b/arch/arm/mach-omap2/cpuidle44xx.c
> @@ -0,0 +1,165 @@
> +/*
> + * OMAP4 CPU IDLE Routines
s/IDLE/idle/
> + *
> + * Copyright (C) 2011 Texas Instruments, Inc.
> + * Rajendra Nayak <rnayak@ti.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/sched.h>
> +#include <linux/cpuidle.h>
> +
> +#include <asm/proc-fns.h>
> +
> +#include <mach/omap4-common.h>
> +
> +#include "pm.h"
> +
> +#ifdef CONFIG_CPU_IDLE
> +
> +#define OMAP4_MAX_STATES 1
> +/* C1 - CPUx wfi + MPU inactive + CORE inactive */
s/wfi/WFI/
> +#define OMAP4_STATE_C1 0
> +
> +struct omap4_processor_cx {
> + u8 valid;
> + u8 type;
> + u32 sleep_latency;
> + u32 wakeup_latency;
> + u32 cpu0_state;
> + u32 cpu1_state;
> + u32 mpu_state;
> + u32 core_state;
> + u32 threshold;
> + u32 flags;
> +};
> +
> +struct omap4_processor_cx omap4_power_states[OMAP4_MAX_STATES];
> +struct omap4_processor_cx current_cx_state;
> +
> +static struct cpuidle_params cpuidle_params_table[] = {
> + /* C1 */
> + {1, 2, 2, 5},
> +};
> +
> +/**
> + * omap4_enter_idle - Programs OMAP4 to enter the specified state
> + * @dev: cpuidle device
> + * @state: The target state to be programmed
> + *
> + * Called from the CPUidle framework to program the device to the
> + * specified low power state selected by the governor.
> + * Returns the amount of time spent in the low power state.
> + */
> +static int omap4_enter_idle(struct cpuidle_device *dev,
> + struct cpuidle_state *state)
> +{
> + struct timespec ts_preidle, ts_postidle, ts_idle;
> +
> + /* Used to keep track of the total time in idle */
> + getnstimeofday(&ts_preidle);
> +
> + local_irq_disable();
> + local_fiq_disable();
> +
> + cpu_do_idle();
> +
> + getnstimeofday(&ts_postidle);
> + ts_idle = timespec_sub(ts_postidle, ts_preidle);
> +
> + local_irq_enable();
> + local_fiq_enable();
> +
> + return ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * USEC_PER_SEC;
> +}
> +
> +DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev);
> +
> +/**
> + * omap4_init_power_states - Initialises the OMAP4 specific C states.
> + *
> + * Below is the desciption of each C state.
> + * C1 : CPUx wfi + MPU inative + Core inactive
> + */
> +void omap_init_power_states(void)
> +{
> + /* C1 . CPUx wfi + MPU inactive + Core inactive */
> + omap4_power_states[OMAP4_STATE_C1].valid =
> + cpuidle_params_table[OMAP4_STATE_C1].valid;
> + omap4_power_states[OMAP4_STATE_C1].type = OMAP4_STATE_C1;
> + omap4_power_states[OMAP4_STATE_C1].sleep_latency =
> + cpuidle_params_table[OMAP4_STATE_C1].sleep_latency;
> + omap4_power_states[OMAP4_STATE_C1].wakeup_latency =
> + cpuidle_params_table[OMAP4_STATE_C1].wake_latency;
> + omap4_power_states[OMAP4_STATE_C1].threshold =
> + cpuidle_params_table[OMAP4_STATE_C1].threshold;
> + omap4_power_states[OMAP4_STATE_C1].mpu_state = PWRDM_POWER_ON;
> + omap4_power_states[OMAP4_STATE_C1].core_state = PWRDM_POWER_ON;
> + omap4_power_states[OMAP4_STATE_C1].flags = CPUIDLE_FLAG_TIME_VALID;
> +
> +}
> +
> +struct cpuidle_driver omap4_idle_driver = {
> + .name = "omap4_idle",
> + .owner = THIS_MODULE,
> +};
> +
> +/**
> + * omap4_idle_init - Init routine for OMAP4 idle
> + *
> + * Registers the OMAP4 specific cpuidle driver with the cpuidle
> + * framework with the valid set of states.
> + */
> +int __init omap4_idle_init(void)
> +{
> + int cpu_id, i, count = 0;
> + struct omap4_processor_cx *cx;
> + struct cpuidle_state *state;
> + struct cpuidle_device *dev;
> +
> + omap_init_power_states();
> + cpuidle_register_driver(&omap4_idle_driver);
> +
> + for_each_cpu(cpu_id, cpu_online_mask) {
> + pr_err("CPUidle for CPU%d registered\n", cpu_id);
stray debug print?
> + dev = &per_cpu(omap4_idle_dev, cpu_id);
> + dev->cpu = cpu_id;
> + count = 0;
> + for (i = OMAP4_STATE_C1; i < OMAP4_MAX_STATES; i++) {
> + cx = &omap4_power_states[i];
> + state = &dev->states[count];
> +
> + if (!cx->valid)
> + continue;
> + cpuidle_set_statedata(state, cx);
> + state->exit_latency = cx->sleep_latency +
> + cx->wakeup_latency;
> + state->target_residency = cx->threshold;
> + state->flags = cx->flags;
> + state->enter = omap4_enter_idle;
> + sprintf(state->name, "C%d", count+1);
> + count++;
> + }
> +
> + if (!count)
> + return -EINVAL;
> + dev->state_count = count;
> +
> + if (cpuidle_register_device(dev)) {
> + pr_err("%s: CPUidle register device failed\n",
> + __func__);
> + return -EIO;
> + }
> + }
> +
> + return 0;
> +}
> +#else
> +int __init omap4_idle_init(void)
> +{
> + return 0;
> +}
> +#endif /* CONFIG_CPU_IDLE */
> diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
> index f557407..ce848b0 100644
> --- a/arch/arm/mach-omap2/pm.h
> +++ b/arch/arm/mach-omap2/pm.h
> @@ -22,6 +22,7 @@ extern void omap_sram_idle(void);
> extern int omap3_can_sleep(void);
> extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
> extern int omap3_idle_init(void);
> +extern int omap4_idle_init(void);
>
> #if defined(CONFIG_PM_OPP)
> extern int omap3_opp_init(void);
> diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
> index 8e57b42..628242d 100644
> --- a/arch/arm/mach-omap2/pm44xx.c
> +++ b/arch/arm/mach-omap2/pm44xx.c
> @@ -230,6 +230,8 @@ static int __init omap4_pm_init(void)
> suspend_set_ops(&omap_pm_ops);
> #endif /* CONFIG_SUSPEND */
>
> + omap4_idle_init();
> +
> err2:
> return ret;
> }
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 14/17] omap4: cpuidle: Add MPUSS RET OFF states
2011-02-19 10:42 ` [PATCH 14/17] omap4: cpuidle: Add MPUSS RET OFF states Santosh Shilimkar
2011-02-21 10:19 ` Jean Pihet
@ 2011-03-02 23:32 ` Kevin Hilman
1 sibling, 0 replies; 55+ messages in thread
From: Kevin Hilman @ 2011-03-02 23:32 UTC (permalink / raw)
To: linux-arm-kernel
Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
> This patch adds MPUSS low power states in cpuidle.
>
> C1 - CPU0 ON + CPU1 ON/OFF + MPU ON + CORE ON
> C2 - CPU0 ON + CPU1 OFF + MPU ON + CORE ON
> C3 - CPU0 OFF + CPU1 OFF + MPU CSWR + CORE ON
> C4 - CPU0 OFF + CPU1 OFF + MPU OFF + CORE ON
>
> MPU OSWR isn't supported yet. To support OSWR, power domain context
> registers needs to be managed which are not supported yet. A patch
> to address this was submitted but it's not ready for merge yet because
> it was not addressing all OMAP4 power domain context registers.
> More info on this issue:
> http://www.mail-archive.com/linux-omap at vger.kernel.org/msg38667.html
>
> OMAP4 powerdomain INACTIVE support is also dropped because of inconsistency
> of it with OMAP3. More information on this thread.
> http://www.spinics.net/lists/linux-omap/msg45370.html
>
> CORE low power states and associated latencies will be updated as part
> along with chip retention support.
>
> On OMAP4 because of hardware constraints, no low power states are
> targeted when both CPUs are online and in SMP mode. The low power
> states are attempted only when secondary CPU gets offline to OFF
> through hotplug infrastructure.
>
> Thanks to Nicole Chalhoub <n-chalhoub@ti.com> for doing exhaustive
> C-state latency profiling.
>
> Signed-off-by: Rajendra Nayak <rnayak@ti.com>
> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Reviewed-by: Kevin Hilman <khilman@ti.com>
> ---
> arch/arm/mach-omap2/cpuidle44xx.c | 190 ++++++++++++++++++++++++++++++++++---
> 1 files changed, 176 insertions(+), 14 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c
> index 6c3c69d..aa1584e 100644
> --- a/arch/arm/mach-omap2/cpuidle44xx.c
> +++ b/arch/arm/mach-omap2/cpuidle44xx.c
> @@ -3,6 +3,7 @@
> *
> * Copyright (C) 2011 Texas Instruments, Inc.
> * Rajendra Nayak <rnayak@ti.com>
> + * Santosh Shilimkar <santosh.shilimkar@ti.com>
> *
> * This program is free software; you can redistribute it and/or modify
> * it under the terms of the GNU General Public License version 2 as
> @@ -17,12 +18,21 @@
> #include <mach/omap4-common.h>
>
> #include "pm.h"
> +#include "prm.h"
>
> #ifdef CONFIG_CPU_IDLE
>
> -#define OMAP4_MAX_STATES 1
> -/* C1 - CPUx wfi + MPU inactive + CORE inactive */
> +#define CPUIDLE_FLAG_CHECK_BM 0x10000 /* use omap4_enter_idle_bm() */
> +#define OMAP4_MAX_STATES 4
> +
> +/* C1 - CPU0 ON + CPU1 ON/OFF + MPU ON + CORE ON */
> #define OMAP4_STATE_C1 0
> +/* C2 - CPU0 ON + CPU1 OFF + MPU ON + CORE ON */
> +#define OMAP4_STATE_C2 1
> +/* C3 - CPU0 OFF + CPU1 OFF + MPU CSWR + CORE ON */
> +#define OMAP4_STATE_C3 2
> +/* C4 - CPU0 OFF + CPU1 OFF + MPU OFF + CORE ON */
> +#define OMAP4_STATE_C4 3
>
> struct omap4_processor_cx {
> u8 valid;
> @@ -32,19 +42,44 @@ struct omap4_processor_cx {
> u32 cpu0_state;
> u32 cpu1_state;
> u32 mpu_state;
> + u32 mpu_logic_state;
> u32 core_state;
> + u32 core_logic_state;
> u32 threshold;
> u32 flags;
> + const char *desc;
> };
>
> -struct omap4_processor_cx omap4_power_states[OMAP4_MAX_STATES];
> -struct omap4_processor_cx current_cx_state;
> +static struct omap4_processor_cx omap4_power_states[OMAP4_MAX_STATES];
> +static struct powerdomain *mpu_pd, *cpu1_pd, *core_pd;
>
> +/*
> + * FIXME: Full latenecy numbers needs to be updated as part of
> + * cpuidle CORE retention support.
> + * Currently only MPUSS latency numbers are added based on
> + * measurements done internally. The numbers for MPUSS are
> + * not board dependent and hence set directly here instead of
> + * passing it from board files.
> + */
> static struct cpuidle_params cpuidle_params_table[] = {
> - /* C1 */
> - {1, 2, 2, 5},
> + /* C1 - CPU0 WFI + CPU1 ON/OFF + MPU ON + CORE ON */
Above comments say 'CPU0 ON' intead of WFI. Make this consistent.
Also, according to the code, CPU1 is always programmed to OFF.
That being the case, what's the difference between C1 and C2?
> + {1, 2, 2, 5},
> + /* C2 - CPU0 ON + CPU1 OFF + MPU ON + CORE ON */
> + {1, 140, 160, 300},
> + /* C3 - CPU0 OFF + CPU1 OFF + MPU CSWR + CORE ON */
> + {1, 200, 300, 700},
> + /* C4 - CPU0 OFF + CPU1 OFF + MPU OFF + CORE ON */
> + {1, 1400, 600, 5000},
> };
>
> +DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev);
> +
> +static int omap4_idle_bm_check(void)
The 'bm' terminology here is from legacy x86-based CPUidle code (for
bus-master.) Let's just call this 'activity' check.
> +{
> + /* FIXME: Populate this with CORE retention support */
> + return 0;
> +}
How about just leaving this function out altogether until it's needed.
Also leave out the #define CPUIDLE_FLAG_CHECK_BM for now.
I think we may be able to do OMAP4 a little smarter than we've done
OMAP3 using the ->prepare hook of struct cpuidle_device, and get rid of
this 'bm' check. More on that below...
> /**
> * omap4_enter_idle - Programs OMAP4 to enter the specified state
> * @dev: cpuidle device
> @@ -57,7 +92,9 @@ static struct cpuidle_params cpuidle_params_table[] = {
> static int omap4_enter_idle(struct cpuidle_device *dev,
> struct cpuidle_state *state)
> {
> + struct omap4_processor_cx *cx = cpuidle_get_statedata(state);
> struct timespec ts_preidle, ts_postidle, ts_idle;
> + u32 cpu1_state;
>
> /* Used to keep track of the total time in idle */
> getnstimeofday(&ts_preidle);
> @@ -65,28 +102,74 @@ static int omap4_enter_idle(struct cpuidle_device *dev,
> local_irq_disable();
> local_fiq_disable();
>
> - cpu_do_idle();
> + /*
> + * Special hardware/software considerations:
> + * 1. Do only WFI for secondary CPU(non-boot - CPU1).
> + * Secondary cores are taken down only via hotplug path.
Then why even create a 'struct cpuidle_device' for the non-boot CPUs?
If you only create a cpuidle_device for the boot CPU, the non-boot CPUs
will just use the default pm_idle which should be WFI only, right?
> + * 2. Do only a WFI as long as in SMP mode.
> + * 3. Continue to do only WFI till CPU1 hits OFF state.
> + * This is necessary to honour hardware recommondation
> + * of triggeing all the possible low power modes once CPU1 is
> + * out of coherency and in OFF mode.
> + * Update dev->last_state so that governor stats reflects right
> + * data.
> + */
> + cpu1_state = pwrdm_read_pwrst(cpu1_pd);
> + if ((dev->cpu) || (num_online_cpus() > 1) ||
> + (cpu1_state != PWRDM_POWER_OFF)) {
> + dev->last_state = dev->safe_state;
We currently have 2 existing ways of doing some pre-transition
checking.
1) through the ->prepare hook of 'struct cpuidle_device'
2) through the existing 'bm_check' mechanism
Here you're adding yet another one, and I don't really like it.
Also, The 'safe state' is C1, but you're not doing the same thing as a
"normal" C1.
What's wrong with just updating 'cx' and falling through so you actually
do the same thing as the C-state you're reporting.
That being said, I think it might be better to use the ->prepare hook
for this. Here's what I propose.
By default, all C-states except C1 have the CPUIDLE_FLAG_IGNORE flag set
(meaning they will be ignored by the governor.) Only on CPU1 hot-unplug
is the ignore flag removed from the other states, and conversly when
CPU1 is hot-plugged, the ignore flag is added back.
Doing this shifts the burden up to the governor and will prevent all of
this logic from happening for every idle transition.
> + cpu_do_idle();
> + goto return_sleep_time;
> + }
>
> + pwrdm_set_logic_retst(mpu_pd, cx->mpu_logic_state);
> + omap_set_pwrdm_state(mpu_pd, cx->mpu_state);
> + pwrdm_set_logic_retst(core_pd, cx->core_logic_state);
> + omap_set_pwrdm_state(core_pd, cx->core_state);
> +
> + omap4_enter_lowpower(dev->cpu, cx->cpu0_state);
> +
> +return_sleep_time:
> getnstimeofday(&ts_postidle);
> ts_idle = timespec_sub(ts_postidle, ts_preidle);
>
> local_irq_enable();
> local_fiq_enable();
>
> +
> return ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * USEC_PER_SEC;
> }
[...]
Kevin
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 16/17] omap4: cpuidle: Allow debugfs control through enable_off_mode
2011-02-19 10:42 ` [PATCH 16/17] omap4: cpuidle: Allow debugfs control through enable_off_mode Santosh Shilimkar
@ 2011-03-02 23:43 ` Kevin Hilman
0 siblings, 0 replies; 55+ messages in thread
From: Kevin Hilman @ 2011-03-02 23:43 UTC (permalink / raw)
To: linux-arm-kernel
Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
> Only MPU OFF and RET is controllable. CORE state is blocked
> at ON state till the CORE RET support is added.
-ECONFUSED
None of the C-states currently have CORE != ON:
./cpuidle44xx.c:219: omap4_power_states[OMAP4_STATE_C1].core_state = PWRDM_POWER_ON;
./cpuidle44xx.c:240: omap4_power_states[OMAP4_STATE_C2].core_state = PWRDM_POWER_ON;
./cpuidle44xx.c:262: omap4_power_states[OMAP4_STATE_C3].core_state = PWRDM_POWER_ON;
./cpuidle44xx.c:284: omap4_power_states[OMAP4_STATE_C4].core_state = PWRDM_POWER_ON;
> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Reviewed-by: Kevin Hilman <khilman@ti.com>
> ---
> arch/arm/mach-omap2/cpuidle44xx.c | 30 ++++++++++++++++++++++++++++++
> arch/arm/mach-omap2/pm.h | 1 +
> arch/arm/mach-omap2/pm44xx.c | 4 ++++
> 3 files changed, 35 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c
> index e887eb5..4207862 100644
> --- a/arch/arm/mach-omap2/cpuidle44xx.c
> +++ b/arch/arm/mach-omap2/cpuidle44xx.c
> @@ -170,6 +170,31 @@ static int omap4_enter_idle_bm(struct cpuidle_device *dev,
> }
>
> /**
> + * omap4_cpuidle_update_states() - Update the cpuidle states
> + * @mpu_deepest_state: Enable states upto and including this for mpu domain
> + * @core_deepest_state: Enable states upto and including this for core domain
> + *
> + * This goes through the list of states available and enables and disables the
> + * validity of C states based on deepest state that can be achieved for the
> + * variable domain
> + */
> +void omap4_cpuidle_update_states(u32 mpu_deepest_state, u32 core_deepest_state)
> +{
> + int i;
> +
> + for (i = OMAP4_STATE_C1; i < OMAP4_MAX_STATES; i++) {
> + struct omap4_processor_cx *cx = &omap4_power_states[i];
> +
> + if ((cx->mpu_state >= mpu_deepest_state) &&
> + (cx->core_state >= core_deepest_state)) {
> + cx->valid = 1;
> + } else {
> + cx->valid = 0;
> + }
> + }
> +}
Also, as mentioned in a previous patch, for OMAP4 I'd like to move away
from this approach to updating the states and rather use the ->prepare
hook along with the ignore flag.
> +/**
> * omap4_init_power_states - Initialises the OMAP4 specific C states.
> *
> */
> @@ -325,6 +350,11 @@ int __init omap4_idle_init(void)
> }
> }
>
> + if (enable_off_mode)
> + omap4_cpuidle_update_states(PWRDM_POWER_OFF, PWRDM_POWER_OFF);
> + else
> + omap4_cpuidle_update_states(PWRDM_POWER_RET, PWRDM_POWER_RET);
> +
> return 0;
> }
> #else
> diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
> index ce848b0..4df89d1 100644
> --- a/arch/arm/mach-omap2/pm.h
> +++ b/arch/arm/mach-omap2/pm.h
> @@ -77,6 +77,7 @@ extern u32 sleep_while_idle;
>
> #if defined(CONFIG_CPU_IDLE)
> extern void omap3_cpuidle_update_states(u32, u32);
> +extern void omap4_cpuidle_update_states(u32, u32);
> #endif
>
> #if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
> diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
> index 628242d..6244ab2 100644
> --- a/arch/arm/mach-omap2/pm44xx.c
> +++ b/arch/arm/mach-omap2/pm44xx.c
> @@ -183,6 +183,10 @@ void omap4_pm_off_mode_enable(int enable)
> else
> state = PWRDM_POWER_RET;
>
> +#ifdef CONFIG_CPU_IDLE
> + omap4_cpuidle_update_states(state, PWRDM_POWER_ON);
> +#endif
> +
> list_for_each_entry(pwrst, &pwrst_list, node) {
> /* FIXME: Remove this check when core retention is supported */
> if (!strcmp(pwrst->pwrdm->name, "mpu_pwrdm")) {
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 07/17] omap4: pm: CPU1 wakeup workaround form Low power modes
2011-02-19 10:42 ` [PATCH 07/17] omap4: pm: CPU1 wakeup workaround form Low power modes Santosh Shilimkar
2011-03-02 22:23 ` Kevin Hilman
@ 2011-03-02 23:44 ` Kevin Hilman
1 sibling, 0 replies; 55+ messages in thread
From: Kevin Hilman @ 2011-03-02 23:44 UTC (permalink / raw)
To: linux-arm-kernel
Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
> The SGI(Software Generated Interrupts) are not wakeup capable from
> low power states. This is known limitation on OMAP4 and needs to be
> worked around by using software forced clockdomain wake-up. CPU0 forces
> the CPU1 clockdomain to software force wakeup. After the wakeup, CPU1
> restores its clockdomain hardware supervised mode.
>
> More details can be found in OMAP4430 TRM - Version J
> Section :
> 4.3.4.2 Power States of CPU0 and CPU1
>
> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Reviewed-by: Kevin Hilman <khilman@ti.com>
One other thing...
in subject: s/form/from/
Kevin
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 00/17] omap4: pm: suspend, hotplug and cpuilde support
2011-02-19 10:42 [PATCH 00/17] omap4: pm: suspend, hotplug and cpuilde support Santosh Shilimkar
` (16 preceding siblings ...)
2011-02-19 10:42 ` [PATCH 17/17] omap4: Remove un-used do_wfi() macro Santosh Shilimkar
@ 2011-03-02 23:46 ` Kevin Hilman
2011-03-03 7:20 ` Santosh Shilimkar
2011-03-04 17:20 ` Santosh Shilimkar
17 siblings, 2 replies; 55+ messages in thread
From: Kevin Hilman @ 2011-03-02 23:46 UTC (permalink / raw)
To: linux-arm-kernel
Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
> This series adds OMAP4 suspend and cpuidle support till MPU subsystem
> (MPUSS) off-mode. The suspend on SMP machines uses cpu-hotplug
> infrastructure to take down the non-boot CPUs. We put secondary
> CPU(CPU1 in OMAP4) to OFF state via cpu-hotplug.
> In cpuidle too, low power states are attempted only when the
> CPU1 is put to OFF state via cpu-hotplug because of hardware
> constraints.
Minor nit on patch subjects: both OMAP and PM are acronyms, please
capitalize.
Also, can you rebase this on Paul's integration-2.6.39 branch? There
are several things in this series that conflict with changes there.
Thanks,
Kevin
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 00/17] omap4: pm: suspend, hotplug and cpuilde support
2011-03-02 23:46 ` [PATCH 00/17] omap4: pm: suspend, hotplug and cpuilde support Kevin Hilman
@ 2011-03-03 7:20 ` Santosh Shilimkar
2011-03-04 17:20 ` Santosh Shilimkar
1 sibling, 0 replies; 55+ messages in thread
From: Santosh Shilimkar @ 2011-03-03 7:20 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Kevin Hilman [mailto:khilman at ti.com]
> Sent: Thursday, March 03, 2011 5:16 AM
> To: Santosh Shilimkar
> Cc: linux-omap at vger.kernel.org; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH 00/17] omap4: pm: suspend, hotplug and cpuilde
> support
>
> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
>
> > This series adds OMAP4 suspend and cpuidle support till MPU
> subsystem
> > (MPUSS) off-mode. The suspend on SMP machines uses cpu-hotplug
> > infrastructure to take down the non-boot CPUs. We put secondary
> > CPU(CPU1 in OMAP4) to OFF state via cpu-hotplug.
> > In cpuidle too, low power states are attempted only when the
> > CPU1 is put to OFF state via cpu-hotplug because of hardware
> > constraints.
>
> Minor nit on patch subjects: both OMAP and PM are acronyms, please
> capitalize.
>
Will Fix that.
> Also, can you rebase this on Paul's integration-2.6.39 branch?
> There
> are several things in this series that conflict with changes there.
>
I did that already and found issues around static dependencies.
Rajendra and myself are sorting those out.
Will address the comments on this series and post v2.
Regards,
Santosh
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 01/17] omap4: pm: Add omap WakeupGen module support
2011-03-02 21:47 ` Kevin Hilman
@ 2011-03-03 16:04 ` Santosh Shilimkar
0 siblings, 0 replies; 55+ messages in thread
From: Santosh Shilimkar @ 2011-03-03 16:04 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Kevin Hilman [mailto:khilman at ti.com]
> Sent: Thursday, March 03, 2011 3:17 AM
> To: Santosh Shilimkar
> Cc: linux-omap at vger.kernel.org; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH 01/17] omap4: pm: Add omap WakeupGen module
> support
>
[...]
> > +
> > +static inline u32 cpu_readl(u8 idx, u32 cpu)
>
> Minor nit: the cpu_ prefix is too generic, how about wakeupgen_ or
> wugen_?
>
Done. I used wakeupgen_ prefeix.
[...]
> > +static void _wakeupgen_set_all(unsigned int cpu, unsigned int
> reg)
> > +{
> > + u8 i;
> > +
> > + for (i = 0; i < NR_BANKS; i++)
> > + cpu_writel(reg, i, cpu);
> > +}
> > +
> > +static void _wakeupgen_set(unsigned int irq, unsigned int set)
>
> I (still) don't like a single "set" function, especially when it
> takes a
> "set" argument.
>
> Make separate set and clear functions, with the common stuff in a
> helper function like _wakeupgen_get_irq() or something.
>
Done.
[...]
> > +
> > +#ifdef CONFIG_PM
>
> I think this should be CONFIG_SUSPEND
I don't see any body using "CONFIG_SUSPEND".
set_wake() seems to be under CONFIG_PM, so I
am retaining as it is.
>
> > +/*
> > + * Architecture specific set_wake extension
> > + */
> > +static int wakeupgen_set_wake(struct irq_data *d, unsigned int
> on)
> > + /* Static mapping, never released */
> > + wakeupgen_base = ioremap(OMAP44XX_WKUPGEN_BASE, SZ_4K);
> > + BUG_ON(!wakeupgen_base);
>
> A WARN_ON() with a graceful exit is more appropriate here:
>
Done.
Regards
Santosh
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 02/17] omap4: pm: Add SAR RAM support
2011-03-02 21:56 ` Kevin Hilman
@ 2011-03-03 16:08 ` Santosh Shilimkar
0 siblings, 0 replies; 55+ messages in thread
From: Santosh Shilimkar @ 2011-03-03 16:08 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Kevin Hilman [mailto:khilman at ti.com]
> Sent: Thursday, March 03, 2011 3:27 AM
> To: Santosh Shilimkar
> Cc: linux-omap at vger.kernel.org; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH 02/17] omap4: pm: Add SAR RAM support
>
[..]
> > +
> > + /* Static mapping, never released */
> > + sar_ram_base = ioremap(OMAP44XX_SAR_RAM_BASE, SZ_8K);
> > + BUG_ON(!sar_ram_base);
>
> Again, a BUG is not approprate here.
>
> Instead, other code needs to properly handle when sar_ram_base ==
> NULL
>
Fixed.
> > + return 0;
> > +}
> > +early_initcall(omap4_sar_ram_init);
> > diff --git a/arch/arm/mach-omap2/omap4-sar-layout.h
> b/arch/arm/mach-omap2/omap4-sar-layout.h
> > new file mode 100644
> > index 0000000..bb66816
> > --- /dev/null
> > +++ b/arch/arm/mach-omap2/omap4-sar-layout.h
> > @@ -0,0 +1,24 @@
[....]
> > +
> > +extern void __iomem *sar_ram_base;
>
> This patch creates this as global, but has no global users.
>
> Also, personally, I don't like these 'base address as global
> pointer'
> that are appearing throughout the OMAP4 code. This one is
> continuing
> the pattern of some others (gic_dist_base_addr, gic_cpu_base) etc.,
> but
> I'm not crazy about them. BTW, the gic* ones also suffer from the
> BUG
> problem and do not properly handle error conditions.
>
> It would be much cleaner to keep this base address static (and
> local)
> and just create some sar_read/write helpers that can be used from
> other code.
>
I have fixed all of these in one patch and added helper functions
to get the address. Also removed BUG_ON() from gic_*() functions
as well.
> Hmm, I see the assembly code uses this base address to. For that, a
> helper function to get the base address could be created.
>
Regards,
Santosh
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 03/17] omap4: Export scu base address
2011-03-02 21:58 ` Kevin Hilman
@ 2011-03-03 16:09 ` Santosh Shilimkar
0 siblings, 0 replies; 55+ messages in thread
From: Santosh Shilimkar @ 2011-03-03 16:09 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Kevin Hilman [mailto:khilman at ti.com]
> Sent: Thursday, March 03, 2011 3:29 AM
> To: Santosh Shilimkar
> Cc: linux-omap at vger.kernel.org; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH 03/17] omap4: Export scu base address
>
> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
>
> > The scu base address needs to be accessed in cpu hotplug
> > for power management. Hence export the same
>
> As with previous patch, rather than export the base address itself,
> it should export a helper function to get the base address
>
I dropped this patch in favor of the exported helpers to
get base address.
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 04/17] omap4: pm: Add CPUx OFF mode support
2011-03-02 22:12 ` Kevin Hilman
@ 2011-03-03 16:14 ` Santosh Shilimkar
0 siblings, 0 replies; 55+ messages in thread
From: Santosh Shilimkar @ 2011-03-03 16:14 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Kevin Hilman [mailto:khilman at ti.com]
> Sent: Thursday, March 03, 2011 3:43 AM
> To: Santosh Shilimkar
> Cc: linux-omap at vger.kernel.org; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH 04/17] omap4: pm: Add CPUx OFF mode support
>
> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
>
> > This patch adds the CPU0 and CPU1 off mode support. CPUX close
> switch
>
> s/CPUX/CPUx/
>
> > retention (CSWR) is not supported by hardware design.
> >
> > The CPUx OFF mode isn't supported on OMAP4430 ES1.0
> >
> > CPUx sleep code is common for hotplug, suspend and cpuilde.
>
> s/cpuilde/CPUidle/
>
> > Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> > Reviewed-by: Kevin Hilman <khilman@ti.com>
>
> > ---
Fixed all the comments on this patch.
[....]
> > +++ b/arch/arm/mach-omap2/sleep44xx.S
[....]
>
> I didn't do a detailed review of the below assembly since you're
> much more knowlegable there than me.
>
> However, will the assembly code here work in Thumb-2 mode? Dave
> Martin
> has been working on that for OMAP3, but we should make sure the
> OMAP4 stuff is Thumb-2 ready out of the box.
>
The code as such builds for THUMB2 as I tried last time. At least
I have tried not to break it for THUMB2 anywhere.
Regards,
Santosh
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 05/17] omap4: pm: Initialise all the clockdomains to supported states
2011-03-02 22:17 ` Kevin Hilman
@ 2011-03-03 16:14 ` Santosh Shilimkar
0 siblings, 0 replies; 55+ messages in thread
From: Santosh Shilimkar @ 2011-03-03 16:14 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Kevin Hilman [mailto:khilman at ti.com]
> Sent: Thursday, March 03, 2011 3:48 AM
> To: Santosh Shilimkar
> Cc: linux-omap at vger.kernel.org; linux-arm-
> kernel at lists.infradead.org; Rajendra Nayak
> Subject: Re: [PATCH 05/17] omap4: pm: Initialise all the
> clockdomains to supported states
>
> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
>
> > Initialise hardware supervised mode for all clockdomains if it's
> > supported. Initiate sleep transition for other clockdomains,
> > if they are not being used.
> >
> > Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> > Signed-off-by: Rajendra Nayak <rnayak@ti.com>
> > Reviewed-by: Kevin Hilman <khilman@ti.com>
> > ---
> > arch/arm/mach-omap2/pm44xx.c | 22 +++++++++++++++++++++-
> > 1 files changed, 21 insertions(+), 1 deletions(-)
> >
> > diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-
> omap2/pm44xx.c
> > index b142673..9a9dc41 100644
> > --- a/arch/arm/mach-omap2/pm44xx.c
> > +++ b/arch/arm/mach-omap2/pm44xx.c
> > @@ -17,9 +17,11 @@
> > #include <linux/slab.h>
> > #include <plat/clock.h>
> >
> > -#include "powerdomain.h"
> > #include <mach/omap4-common.h>
> >
> > +#include "powerdomain.h"
> > +#include "clockdomain.h"
> > +
> > struct power_state {
> > struct powerdomain *pwrdm;
> > u32 next_state;
> > @@ -74,6 +76,22 @@ static const struct platform_suspend_ops
> omap_pm_ops = {
> > };
> > #endif /* CONFIG_SUSPEND */
> >
> > +/*
> > + * Enable hardwarew supervised mode for all clockdomains if it's
>
> typo: hardware
>
Fixed
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 07/17] omap4: pm: CPU1 wakeup workaround form Low power modes
2011-03-02 22:23 ` Kevin Hilman
@ 2011-03-03 16:15 ` Santosh Shilimkar
0 siblings, 0 replies; 55+ messages in thread
From: Santosh Shilimkar @ 2011-03-03 16:15 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Kevin Hilman [mailto:khilman at ti.com]
> Sent: Thursday, March 03, 2011 3:54 AM
> To: Santosh Shilimkar
> Cc: linux-omap at vger.kernel.org; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH 07/17] omap4: pm: CPU1 wakeup workaround form
> Low power modes
>
> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
>
> > The SGI(Software Generated Interrupts) are not wakeup capable from
> > low power states. This is known limitation on OMAP4 and needs to
> be
> > worked around by using software forced clockdomain wake-up. CPU0
> forces
> > the CPU1 clockdomain to software force wakeup. After the wakeup,
> CPU1
> > restores its clockdomain hardware supervised mode.
> >
> > More details can be found in OMAP4430 TRM - Version J
> > Section :
> > 4.3.4.2 Power States of CPU0 and CPU1
> >
> > Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> > Reviewed-by: Kevin Hilman <khilman@ti.com>
> > ---
> > arch/arm/mach-omap2/omap-hotplug.c | 9 +++++++++
> > arch/arm/mach-omap2/omap-smp.c | 27
> ++++++++++++++++++++++++++-
> > 2 files changed, 35 insertions(+), 1 deletions(-)
> >
> > diff --git a/arch/arm/mach-omap2/omap-hotplug.c b/arch/arm/mach-
> omap2/omap-hotplug.c
> > index 9f8f097..cf4ab15 100644
> > --- a/arch/arm/mach-omap2/omap-hotplug.c
> > +++ b/arch/arm/mach-omap2/omap-hotplug.c
> > @@ -23,6 +23,7 @@
> > #include <mach/omap-wakeupgen.h>
> >
> > #include "powerdomain.h"
> > +#include "clockdomain.h"
> >
> > int platform_cpu_kill(unsigned int cpu)
> > {
> > @@ -36,6 +37,11 @@ int platform_cpu_kill(unsigned int cpu)
> > void platform_cpu_die(unsigned int cpu)
> > {
> > unsigned int this_cpu;
> > + static struct clockdomain *cpu1_clkdm;
> > +
> > + /* To avoid cpu1 clockdomain lookup every time */
>
> minor: comment doesn't really match code and could just be removed
>
Fixed
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 08/17] omap4: pm: Add GIC save/restore support
2011-03-02 22:29 ` Kevin Hilman
@ 2011-03-03 16:29 ` Santosh Shilimkar
2011-03-03 17:03 ` Kevin Hilman
2011-03-04 8:39 ` Santosh Shilimkar
1 sibling, 1 reply; 55+ messages in thread
From: Santosh Shilimkar @ 2011-03-03 16:29 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Kevin Hilman [mailto:khilman at ti.com]
> Sent: Thursday, March 03, 2011 4:00 AM
> To: Santosh Shilimkar
> Cc: linux-omap at vger.kernel.org; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH 08/17] omap4: pm: Add GIC save/restore support
[...]
> > @@ -67,6 +82,17 @@ struct omap4_cpu_pm_info {
> >
> > static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info);
> >
> > +/* Helper functions */
> > +static inline void sar_writel(u32 val, u32 offset, u8 idx)
> > +{
> > + __raw_writel(val, sar_ram_base + offset + 4 * idx);
> > +}
>
> aha, this is what I was thinking of in the earlier SAR patch.
>
> Something like this should be part of the SAR code, not here.
>
If you remember during the internal review, this helpers
are added to improve the readability and they are inline
functions. Same is the case with wakeupgen save code.
If you move this code to SAR file and GIC helper
to gic file, the save routine will become highly
un-optimal.
In General Save is like below.
Read_Harfware_register()
Write_it_sar_location()
This happens for every GIC and wakeupgen
registers and hence moving this across files
and calling them from there is going add un-necessary
stack overhead.
I already got rid-off the global address pointers. I will
get those now using omap4_get_*_base() and store it for
local use in the file.
> > +static inline u32 gic_readl(u32 offset, u8 idx)
> > +{
> > + return __raw_readl(gic_dist_base_addr + offset + 4 * idx);
> > +}
>
> Similarily, it would be nice tos see this as part of GIC code so
> this code doesn't have to access a global base address pointer.
>
Same comment applies here too.
Regards
Santosh
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 10/17] omap4: pm: Add L2 cache lowpower support
2011-03-02 22:36 ` Kevin Hilman
@ 2011-03-03 16:30 ` Santosh Shilimkar
0 siblings, 0 replies; 55+ messages in thread
From: Santosh Shilimkar @ 2011-03-03 16:30 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Kevin Hilman [mailto:khilman at ti.com]
> Sent: Thursday, March 03, 2011 4:06 AM
> To: Santosh Shilimkar
> Cc: linux-omap at vger.kernel.org; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH 10/17] omap4: pm: Add L2 cache lowpower support
>
> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
>
> > When MPUSS hits off-mode e, L2 cache is lost. This patch adds L2X0
> > necessary maintenance operations and context restoration in the
> > low power code.
> >
> > Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> > Reviewed-by: Kevin Hilman <khilman@ti.com>
> > ---
> > arch/arm/mach-omap2/omap4-mpuss-lowpower.c | 11 +++++
> > arch/arm/mach-omap2/omap4-sar-layout.h | 2 +
> > arch/arm/mach-omap2/sleep44xx.S | 64
> ++++++++++++++++++++++++++++
> > 3 files changed, 77 insertions(+), 0 deletions(-)
> >
> > diff --git a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
> b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
> > index a30f19b..bff768f 100644
> > --- a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
> > +++ b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
> > @@ -49,6 +49,7 @@
> > #include <asm/system.h>
> > #include <asm/irq.h>
> > #include <asm/hardware/gic.h>
> > +#include <asm/hardware/cache-l2x0.h>
> >
> > #include <plat/omap44xx.h>
> > #include <mach/omap4-common.h>
> > @@ -341,6 +342,7 @@ int __init omap4_mpuss_init(void)
> > {
> > struct omap4_cpu_pm_info *pm_info;
> > u8 i;
> > + u32 val;
>
> This will cause an 'unused variable' compiler warning when
> !CONFIG_CACHE_L2X0
>
Good catch. Fixed
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 11/17] omap4: suspend: Add MPUSS RET and OFF support
2011-03-02 22:45 ` Kevin Hilman
@ 2011-03-03 16:31 ` Santosh Shilimkar
0 siblings, 0 replies; 55+ messages in thread
From: Santosh Shilimkar @ 2011-03-03 16:31 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Kevin Hilman [mailto:khilman at ti.com]
> Sent: Thursday, March 03, 2011 4:16 AM
> To: Santosh Shilimkar
> Cc: linux-omap at vger.kernel.org; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH 11/17] omap4: suspend: Add MPUSS RET and OFF
> support
>
> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
>
[...]
> > +
> > + /* Set targeted power domain states by suspend */
> > + list_for_each_entry(pwrst, &pwrst_list, node) {
> > + /* FIXME: Remove this check when CORE retention is
> supported */
> > + if (!strcmp(pwrst->pwrdm->name, "mpu_pwrdm"))
> > + omap_set_pwrdm_state(pwrst->pwrdm, pwrst-
> >next_state);
> > + }
>
> pwrst_list is the list of powerdomains to that will be changed
> during suspend.
>
> Rather than doing this string match for every suspend, just do the
> check once during init and only add powerdomains that can
> transition to the list.
>
Will fix this accordingly then.
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 12/17] omap4: pm-debug: Add wakeup timer and debug counters
2011-03-02 22:51 ` Kevin Hilman
@ 2011-03-03 16:34 ` Santosh Shilimkar
2011-03-03 17:05 ` Kevin Hilman
0 siblings, 1 reply; 55+ messages in thread
From: Santosh Shilimkar @ 2011-03-03 16:34 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Kevin Hilman [mailto:khilman at ti.com]
> Sent: Thursday, March 03, 2011 4:21 AM
> To: Santosh Shilimkar
> Cc: linux-omap at vger.kernel.org; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH 12/17] omap4: pm-debug: Add wakeup timer and
> debug counters
>
> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
>
> > This patch adds configurable wakeup timer support in suspend. Also
> > for statistics pm counter support is added.
> >
> > Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> > Reviewed-by: Kevin Hilman <khilman@ti.com>
> > ---
> > arch/arm/mach-omap2/omap4-mpuss-lowpower.c | 8 ++++++++
> > arch/arm/mach-omap2/pm-debug.c | 6 ++++--
> > arch/arm/mach-omap2/pm44xx.c | 5 +++++
> > 3 files changed, 17 insertions(+), 2 deletions(-)
> >
> > diff --git a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
> b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
> > index ab2e101..5e0141e 100644
> > --- a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
> > +++ b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
> > @@ -287,6 +287,10 @@ int omap4_enter_lowpower(unsigned int cpu,
> unsigned int power_state)
> > if (cpu)
> > goto cpu_prepare;
> >
> > +#ifdef CONFIG_PM_DEBUG
> > + pwrdm_pre_transition();
> > +#endif
>
> Why the #ifdef?
>
Because these stats updates are quite expensive
in low power code and for the production kernel
you don't need this extra penalty.
> > /*
> > * Check MPUSS next state and save GIC if needed
> > * GIC lost during MPU OFF and OSWR
> > @@ -332,6 +336,10 @@ cpu_prepare:
> > gic_dist_set(CPU0_ID, 1);
> > }
> >
> > +#ifdef CONFIG_PM_DEBUG
> > + pwrdm_post_transition();
> > +#endif
> > +
> > ret:
> > return 0;
> > }
> > diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-
> omap2/pm-debug.c
> > index 9b46b3e..7d6dd5b 100644
> > --- a/arch/arm/mach-omap2/pm-debug.c
> > +++ b/arch/arm/mach-omap2/pm-debug.c
> > @@ -606,9 +606,11 @@ static int __init pm_dbg_init(void)
> > if (pm_dbg_init_done)
> > return 0;
> >
> > - if (cpu_is_omap34xx())
> > + if (cpu_is_omap34xx()) {
> > pm_dbg_reg_modules = omap3_pm_reg_modules;
> > - else {
> > + } else if (cpu_is_omap44xx()) {
> > + /* Allow pm_dbg_init on OMAP4. */
>
> Doing this will cause crashes if the 'registers/*' debugfs file is
> accessed.
>
> Since there are no 'reg_modules' created, you should also prevent
> the creation of the 'registers' debugfs entries.
>
Will do
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 08/17] omap4: pm: Add GIC save/restore support
2011-03-03 16:29 ` Santosh Shilimkar
@ 2011-03-03 17:03 ` Kevin Hilman
0 siblings, 0 replies; 55+ messages in thread
From: Kevin Hilman @ 2011-03-03 17:03 UTC (permalink / raw)
To: linux-arm-kernel
Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
>> -----Original Message-----
>> From: Kevin Hilman [mailto:khilman at ti.com]
>> Sent: Thursday, March 03, 2011 4:00 AM
>> To: Santosh Shilimkar
>> Cc: linux-omap at vger.kernel.org; linux-arm-kernel at lists.infradead.org
>> Subject: Re: [PATCH 08/17] omap4: pm: Add GIC save/restore support
> [...]
>
>> > @@ -67,6 +82,17 @@ struct omap4_cpu_pm_info {
>> >
>> > static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info);
>> >
>> > +/* Helper functions */
>> > +static inline void sar_writel(u32 val, u32 offset, u8 idx)
>> > +{
>> > + __raw_writel(val, sar_ram_base + offset + 4 * idx);
>> > +}
>>
>> aha, this is what I was thinking of in the earlier SAR patch.
>>
>> Something like this should be part of the SAR code, not here.
>>
> If you remember during the internal review, this helpers
> are added to improve the readability and they are inline
> functions. Same is the case with wakeupgen save code.
>
> If you move this code to SAR file and GIC helper
> to gic file, the save routine will become highly
> un-optimal.
>
> In General Save is like below.
> Read_Harfware_register()
> Write_it_sar_location()
>
> This happens for every GIC and wakeupgen
> registers and hence moving this across files
> and calling them from there is going add un-necessary
> stack overhead.
>
> I already got rid-off the global address pointers. I will
> get those now using omap4_get_*_base() and store it for
> local use in the file.
OK, that should be fine.
Thanks,
Kevin
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 12/17] omap4: pm-debug: Add wakeup timer and debug counters
2011-03-03 16:34 ` Santosh Shilimkar
@ 2011-03-03 17:05 ` Kevin Hilman
2011-03-04 6:26 ` Santosh Shilimkar
0 siblings, 1 reply; 55+ messages in thread
From: Kevin Hilman @ 2011-03-03 17:05 UTC (permalink / raw)
To: linux-arm-kernel
Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
>> -----Original Message-----
>> From: Kevin Hilman [mailto:khilman at ti.com]
>> Sent: Thursday, March 03, 2011 4:21 AM
>> To: Santosh Shilimkar
>> Cc: linux-omap at vger.kernel.org; linux-arm-kernel at lists.infradead.org
>> Subject: Re: [PATCH 12/17] omap4: pm-debug: Add wakeup timer and
>> debug counters
>>
>> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
>>
>> > This patch adds configurable wakeup timer support in suspend. Also
>> > for statistics pm counter support is added.
>> >
>> > Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
>> > Reviewed-by: Kevin Hilman <khilman@ti.com>
>> > ---
>> > arch/arm/mach-omap2/omap4-mpuss-lowpower.c | 8 ++++++++
>> > arch/arm/mach-omap2/pm-debug.c | 6 ++++--
>> > arch/arm/mach-omap2/pm44xx.c | 5 +++++
>> > 3 files changed, 17 insertions(+), 2 deletions(-)
>> >
>> > diff --git a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
>> b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
>> > index ab2e101..5e0141e 100644
>> > --- a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
>> > +++ b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
>> > @@ -287,6 +287,10 @@ int omap4_enter_lowpower(unsigned int cpu,
>> unsigned int power_state)
>> > if (cpu)
>> > goto cpu_prepare;
>> >
>> > +#ifdef CONFIG_PM_DEBUG
>> > + pwrdm_pre_transition();
>> > +#endif
>>
>> Why the #ifdef?
>>
> Because these stats updates are quite expensive
> in low power code and for the production kernel
> you don't need this extra penalty.
OK, then please fix this in the powerdomain code (or header.)
c.f. "#ifdefs are ugly" section of Documentation/SubmittingPatches
Kevin
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 12/17] omap4: pm-debug: Add wakeup timer and debug counters
2011-03-03 17:05 ` Kevin Hilman
@ 2011-03-04 6:26 ` Santosh Shilimkar
0 siblings, 0 replies; 55+ messages in thread
From: Santosh Shilimkar @ 2011-03-04 6:26 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Kevin Hilman [mailto:khilman at ti.com]
> Sent: Thursday, March 03, 2011 10:36 PM
> To: Santosh Shilimkar
> Cc: linux-omap at vger.kernel.org; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH 12/17] omap4: pm-debug: Add wakeup timer and
> debug counters
>
> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
>
> >> -----Original Message-----
> >> From: Kevin Hilman [mailto:khilman at ti.com]
> >> Sent: Thursday, March 03, 2011 4:21 AM
> >> To: Santosh Shilimkar
> >> Cc: linux-omap at vger.kernel.org; linux-arm-
> kernel at lists.infradead.org
> >> Subject: Re: [PATCH 12/17] omap4: pm-debug: Add wakeup timer and
> >> debug counters
> >>
> >> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
> >>
> >> > This patch adds configurable wakeup timer support in suspend.
> Also
> >> > for statistics pm counter support is added.
> >> >
> >> > Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> >> > Reviewed-by: Kevin Hilman <khilman@ti.com>
> >> > ---
> >> > arch/arm/mach-omap2/omap4-mpuss-lowpower.c | 8 ++++++++
> >> > arch/arm/mach-omap2/pm-debug.c | 6 ++++--
> >> > arch/arm/mach-omap2/pm44xx.c | 5 +++++
> >> > 3 files changed, 17 insertions(+), 2 deletions(-)
> >> >
> >> > diff --git a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
> >> b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
> >> > index ab2e101..5e0141e 100644
> >> > --- a/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
> >> > +++ b/arch/arm/mach-omap2/omap4-mpuss-lowpower.c
> >> > @@ -287,6 +287,10 @@ int omap4_enter_lowpower(unsigned int cpu,
> >> unsigned int power_state)
> >> > if (cpu)
> >> > goto cpu_prepare;
> >> >
> >> > +#ifdef CONFIG_PM_DEBUG
> >> > + pwrdm_pre_transition();
> >> > +#endif
> >>
> >> Why the #ifdef?
> >>
> > Because these stats updates are quite expensive
> > in low power code and for the production kernel
> > you don't need this extra penalty.
>
> OK, then please fix this in the powerdomain code (or header.)
>
The trace framework also plan to use it so putting power
domain APIs under PM_DEBUG won't be good idea. So I will drop
the #ifdef from this code then
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 08/17] omap4: pm: Add GIC save/restore support
2011-03-02 22:29 ` Kevin Hilman
2011-03-03 16:29 ` Santosh Shilimkar
@ 2011-03-04 8:39 ` Santosh Shilimkar
2011-03-04 16:11 ` Kevin Hilman
1 sibling, 1 reply; 55+ messages in thread
From: Santosh Shilimkar @ 2011-03-04 8:39 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Kevin Hilman [mailto:khilman at ti.com]
> Sent: Thursday, March 03, 2011 4:00 AM
> To: Santosh Shilimkar
> Cc: linux-omap at vger.kernel.org; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH 08/17] omap4: pm: Add GIC save/restore support
>
> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
>
[...]
> > + /*
> > + * Find out how many interrupts are supported.
> > + * OMAP4 supports max of 128 SPIs where as GIC can support
> > + * up to 1020 interrupt sources.
> > + */
> > + max_spi_reg = __raw_readl(gic_dist_base_addr + GIC_DIST_CTR) &
> 0x1f;
> > + max_spi_irq = max_spi_reg * 32;
>
> Based on the spec, this should also be max'd at 1020 so you never
> write the reserved values after 1020.
>
That's correct as per generic GIC specs. On OMAP4, the maximum IRQs
already fused in "DIST_CTR" bit-fields and fixed. Hence we don't
need that additional comparison.
Regards
Santosh
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 08/17] omap4: pm: Add GIC save/restore support
2011-03-04 8:39 ` Santosh Shilimkar
@ 2011-03-04 16:11 ` Kevin Hilman
2011-03-04 16:14 ` Santosh Shilimkar
0 siblings, 1 reply; 55+ messages in thread
From: Kevin Hilman @ 2011-03-04 16:11 UTC (permalink / raw)
To: linux-arm-kernel
Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
>> -----Original Message-----
>> From: Kevin Hilman [mailto:khilman at ti.com]
>> Sent: Thursday, March 03, 2011 4:00 AM
>> To: Santosh Shilimkar
>> Cc: linux-omap at vger.kernel.org; linux-arm-kernel at lists.infradead.org
>> Subject: Re: [PATCH 08/17] omap4: pm: Add GIC save/restore support
>>
>> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
>>
>
> [...]
>
>> > + /*
>> > + * Find out how many interrupts are supported.
>> > + * OMAP4 supports max of 128 SPIs where as GIC can support
>> > + * up to 1020 interrupt sources.
>> > + */
>> > + max_spi_reg = __raw_readl(gic_dist_base_addr + GIC_DIST_CTR) &
>> 0x1f;
>> > + max_spi_irq = max_spi_reg * 32;
>>
>> Based on the spec, this should also be max'd at 1020 so you never
>> write the reserved values after 1020.
>>
>
> That's correct as per generic GIC specs. On OMAP4, the maximum IRQs
> already fused in "DIST_CTR" bit-fields and fixed. Hence we don't
> need that additional comparison.
>
OK, clarifiying this in the comment above would avoid confusion for
anyone looking at this code in combination with the spec.
Thanks,
Kevin
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 08/17] omap4: pm: Add GIC save/restore support
2011-03-04 16:11 ` Kevin Hilman
@ 2011-03-04 16:14 ` Santosh Shilimkar
0 siblings, 0 replies; 55+ messages in thread
From: Santosh Shilimkar @ 2011-03-04 16:14 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Kevin Hilman [mailto:khilman at ti.com]
> Sent: Friday, March 04, 2011 9:42 PM
> To: Santosh Shilimkar
> Cc: linux-omap at vger.kernel.org; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH 08/17] omap4: pm: Add GIC save/restore support
>
> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
>
> >> -----Original Message-----
> >> From: Kevin Hilman [mailto:khilman at ti.com]
> >> Sent: Thursday, March 03, 2011 4:00 AM
> >> To: Santosh Shilimkar
> >> Cc: linux-omap at vger.kernel.org; linux-arm-
> kernel at lists.infradead.org
> >> Subject: Re: [PATCH 08/17] omap4: pm: Add GIC save/restore
> support
> >>
> >> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
> >>
> >
> > [...]
> >
> >> > + /*
> >> > + * Find out how many interrupts are supported.
> >> > + * OMAP4 supports max of 128 SPIs where as GIC can
> support
> >> > + * up to 1020 interrupt sources.
> >> > + */
> >> > + max_spi_reg = __raw_readl(gic_dist_base_addr +
> GIC_DIST_CTR) &
> >> 0x1f;
> >> > + max_spi_irq = max_spi_reg * 32;
> >>
> >> Based on the spec, this should also be max'd at 1020 so you never
> >> write the reserved values after 1020.
> >>
> >
> > That's correct as per generic GIC specs. On OMAP4, the maximum
> IRQs
> > already fused in "DIST_CTR" bit-fields and fixed. Hence we don't
> > need that additional comparison.
> >
>
> OK, clarifiying this in the comment above would avoid confusion for
> anyone looking at this code in combination with the spec.
>
Ok. Will update it
^ permalink raw reply [flat|nested] 55+ messages in thread
* [PATCH 00/17] omap4: pm: suspend, hotplug and cpuilde support
2011-03-02 23:46 ` [PATCH 00/17] omap4: pm: suspend, hotplug and cpuilde support Kevin Hilman
2011-03-03 7:20 ` Santosh Shilimkar
@ 2011-03-04 17:20 ` Santosh Shilimkar
1 sibling, 0 replies; 55+ messages in thread
From: Santosh Shilimkar @ 2011-03-04 17:20 UTC (permalink / raw)
To: linux-arm-kernel
> -----Original Message-----
> From: Kevin Hilman [mailto:khilman at ti.com]
> Sent: Thursday, March 03, 2011 5:16 AM
> To: Santosh Shilimkar
> Cc: linux-omap at vger.kernel.org; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH 00/17] omap4: pm: suspend, hotplug and cpuilde
> support
>
> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
>
> > This series adds OMAP4 suspend and cpuidle support till MPU
> subsystem
> > (MPUSS) off-mode. The suspend on SMP machines uses cpu-hotplug
> > infrastructure to take down the non-boot CPUs. We put secondary
> > CPU(CPU1 in OMAP4) to OFF state via cpu-hotplug.
> > In cpuidle too, low power states are attempted only when the
> > CPU1 is put to OFF state via cpu-hotplug because of hardware
> > constraints.
>
> Minor nit on patch subjects: both OMAP and PM are acronyms, please
> capitalize.
>
> Also, can you rebase this on Paul's integration-2.6.39 branch?
> There
> are several things in this series that conflict with changes there.
>
Rebased branch against your pm-core.
git://dev.omapzoom.org/pub/scm/santosh/kernel-omap4-base.git
omap4_pm_for-next
Regards,
Santosh
^ permalink raw reply [flat|nested] 55+ messages in thread
end of thread, other threads:[~2011-03-04 17:20 UTC | newest]
Thread overview: 55+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-02-19 10:42 [PATCH 00/17] omap4: pm: suspend, hotplug and cpuilde support Santosh Shilimkar
2011-02-19 10:42 ` [PATCH 01/17] omap4: pm: Add omap WakeupGen module support Santosh Shilimkar
2011-03-02 21:47 ` Kevin Hilman
2011-03-03 16:04 ` Santosh Shilimkar
2011-02-19 10:42 ` [PATCH 02/17] omap4: pm: Add SAR RAM support Santosh Shilimkar
2011-03-02 21:56 ` Kevin Hilman
2011-03-03 16:08 ` Santosh Shilimkar
2011-02-19 10:42 ` [PATCH 03/17] omap4: Export scu base address Santosh Shilimkar
2011-03-02 21:58 ` Kevin Hilman
2011-03-03 16:09 ` Santosh Shilimkar
2011-02-19 10:42 ` [PATCH 04/17] omap4: pm: Add CPUx OFF mode support Santosh Shilimkar
2011-03-02 22:12 ` Kevin Hilman
2011-03-03 16:14 ` Santosh Shilimkar
2011-02-19 10:42 ` [PATCH 05/17] omap4: pm: Initialise all the clockdomains to supported states Santosh Shilimkar
2011-03-02 22:17 ` Kevin Hilman
2011-03-03 16:14 ` Santosh Shilimkar
2011-02-19 10:42 ` [PATCH 06/17] omap4: pm: Program CPU1 to hit OFF when off-lined Santosh Shilimkar
2011-02-19 10:42 ` [PATCH 07/17] omap4: pm: CPU1 wakeup workaround form Low power modes Santosh Shilimkar
2011-03-02 22:23 ` Kevin Hilman
2011-03-03 16:15 ` Santosh Shilimkar
2011-03-02 23:44 ` Kevin Hilman
2011-02-19 10:42 ` [PATCH 08/17] omap4: pm: Add GIC save/restore support Santosh Shilimkar
2011-03-02 22:29 ` Kevin Hilman
2011-03-03 16:29 ` Santosh Shilimkar
2011-03-03 17:03 ` Kevin Hilman
2011-03-04 8:39 ` Santosh Shilimkar
2011-03-04 16:11 ` Kevin Hilman
2011-03-04 16:14 ` Santosh Shilimkar
2011-02-19 10:42 ` [PATCH 09/17] omap4: pm: Add WakeupGen " Santosh Shilimkar
2011-03-02 22:34 ` Kevin Hilman
2011-02-19 10:42 ` [PATCH 10/17] omap4: pm: Add L2 cache lowpower support Santosh Shilimkar
2011-03-02 22:36 ` Kevin Hilman
2011-03-03 16:30 ` Santosh Shilimkar
2011-02-19 10:42 ` [PATCH 11/17] omap4: suspend: Add MPUSS RET and OFF support Santosh Shilimkar
2011-03-02 22:45 ` Kevin Hilman
2011-03-03 16:31 ` Santosh Shilimkar
2011-02-19 10:42 ` [PATCH 12/17] omap4: pm-debug: Add wakeup timer and debug counters Santosh Shilimkar
2011-03-02 22:51 ` Kevin Hilman
2011-03-03 16:34 ` Santosh Shilimkar
2011-03-03 17:05 ` Kevin Hilman
2011-03-04 6:26 ` Santosh Shilimkar
2011-02-19 10:42 ` [PATCH 13/17] omap4: cpuidle: Basic CPUidle support Santosh Shilimkar
2011-03-02 22:55 ` Kevin Hilman
2011-02-19 10:42 ` [PATCH 14/17] omap4: cpuidle: Add MPUSS RET OFF states Santosh Shilimkar
2011-02-21 10:19 ` Jean Pihet
2011-02-21 10:26 ` Santosh Shilimkar
2011-02-21 14:01 ` Santosh Shilimkar
2011-03-02 23:32 ` Kevin Hilman
2011-02-19 10:42 ` [PATCH 15/17] omap4: cpuidle: Switch to gptimer from twd in deeper C-states Santosh Shilimkar
2011-02-19 10:42 ` [PATCH 16/17] omap4: cpuidle: Allow debugfs control through enable_off_mode Santosh Shilimkar
2011-03-02 23:43 ` Kevin Hilman
2011-02-19 10:42 ` [PATCH 17/17] omap4: Remove un-used do_wfi() macro Santosh Shilimkar
2011-03-02 23:46 ` [PATCH 00/17] omap4: pm: suspend, hotplug and cpuilde support Kevin Hilman
2011-03-03 7:20 ` Santosh Shilimkar
2011-03-04 17:20 ` Santosh Shilimkar
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).