Skip to contentSkip to conversation

Merge in N800 PM code

PATCH In review Tony Lindgren 2 participants 6 messages Jan 19, 2007 – Jan 26, 2007

Subsystems (4)
lore
Share & tools
lore

Tony Lindgren

author maintainer
#0 lore raw

PATCH 1/1 Merge in N800 PM code

Hi all,

I'm planning to merge in the Nokia N800 PM code for omap2 available at
[1] and [2].

N800 patch gets rid of pm-domain.c and moves those functions to pm.c. It also adds handy debugging via serial console by keeping the serial clock on for few seconds after serial interrupts before allowing deeper sleep states.

Can somebody please test if it boots/works on H4? I don't currently have access to H4. Also it would be nice to get it patched to provide basic PM for 2430.

Once we have this merged in, we can start figuring out the interfaces needed for dynamic power management etc.

Regards,

Tony

[1] http://repository.maemo.org/pool/maemo3.0/free/source/kernel-source-rx-34_2.6.18.orig.tar.gz
[2] http://repository.maemo.org/pool/maemo3.0/free/source/kernel-source-rx-34_2.6.18-osso29.diff.gz

Merge Nokia N800 PM code from:

http://repository.maemo.org/pool/maemo3.0/free/source/kernel-source-rx-34_2.6.18.orig.tar.gz
http://repository.maemo.org/pool/maemo3.0/free/source/kernel-source-rx-34_2.6.18-osso29.diff.gz

N800 code moves PM related register access to pm.c from pm-domain.c to pm.c and adds PM debugging support via serial console.

arch/arm/mach-omap2/Makefile +1 -1
@@ -9,7 +9,7 @@
 obj-$(CONFIG_OMAP_MPU_TIMER)		+= timer-gp.o
 
 # Power Management
-obj-$(CONFIG_PM) += pm.o pm-domain.o sleep.o
+obj-$(CONFIG_PM) += pm.o sleep.o
 
 # DSP
 obj-$(CONFIG_OMAP_DSP)	+= mailbox_mach.o
arch/arm/mach-omap2/pm.c +9 -0
@@ -6,6 +6,16 @@
  * Copyright (C) 2006 Nokia Corporation
  * Tony Lindgren <[email protected]>
  *
+ * Fixed suspend-resume/dynamic-idle to get OMAP to retention
+ * Amit Kucheria <[email protected]>
+ * Igor Stoppa <[email protected]>
+ *
+ * Fixed MPU sleep to get ARM idle
+ * Igor Stoppa <[email protected]>
+ *
+ * Fixed MPU sleep some more
+ * Juha Yrjola
 + *
  * Copyright (C) 2005 Texas Instruments, Inc.
  * Richard Woodruff <[email protected]>

*
@@ -24,6 +34,7 @@
#include <linux/sysfs.h>
#include <linux/module.h>
#include <linux/delay.h>
+#include <linux/clk.h>

#include <asm/io.h>
#include <asm/irq.h>
@@ -36,27 +47,612 @@
#include <asm/arch/clock.h>
#include <asm/arch/sram.h>
#include <asm/arch/pm.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/dma.h>
+#include <asm/arch/board.h>
+
+#define PRCM_BASE 0x48008000
+#define PRCM_REVISION 0x000
+#define PRCM_SYSCONFIG 0x010
+#define PRCM_IRQSTATUS_MPU 0x018
+#define PRCM_IRQENABLE_MPU 0x01c
+#define PRCM_VOLTCTRL 0x050
+#define AUTO_EXTVOLT (1 << 15)
+#define FORCE_EXTVOLT (1 << 14)
+#define SETOFF_LEVEL(x) (((x) & 0x3) << 12)
+#define MEMRETCTRL (1 << 8)
+#define SETRET_LEVEL(x) (((x) & 0x3) << 6)
+#define VOLT_LEVEL(x) (((x) & 0x3) << 0)
+#define PRCM_CLKSRC_CTRL 0x060
+#define PRCM_CLKOUT_CTRL 0x070
+#define PRCM_CLKEMUL_CTRL 0x078
+#define PRCM_CLKCFG_CTRL 0x080
+#define PRCM_VOLTSETUP 0x090
+#define PRCM_CLKSSETUP 0x094
+
+
+#define CM_CLKSEL_MPU 0x140
+#define CM_CLKSTCTRL_MPU 0x148
+#define AUTOSTAT_MPU (1 << 0)
+#define PM_WKDEP_MPU 0x1c8
+#define EN_WKUP (1 << 4)
+#define EN_GFX (1 << 3)
+#define EN_DSP (1 << 2)
+#define EN_MPU (1 << 1)
+#define EN_CORE (1 << 0)
+#define PM_PWSTCTRL_MPU 0x1e0
+#define PM_PWSTST_MPU 0x1e4
+
+
+#define CM_FCLKEN1_CORE 0x200
+#define CM_FCLKEN2_CORE 0x204
+#define CM_ICLKEN1_CORE 0x210
+#define CM_ICLKEN2_CORE 0x214
+#define CM_ICLKEN4_CORE 0x21c
+#define CM_IDLEST1_CORE 0x220
+#define CM_IDLEST2_CORE 0x224
+#define CM_AUTOIDLE1_CORE 0x230
+#define CM_AUTOIDLE2_CORE 0x234
+#define CM_AUTOIDLE3_CORE 0x238
+#define CM_AUTOIDLE4_CORE 0x23c
+#define CM_CLKSEL1_CORE 0x240
+#define CM_CLKSEL2_CORE 0x244
+#define CM_CLKSTCTRL_CORE 0x248
+#define AUTOSTAT_DSS (1 << 2)
+#define AUTOSTAT_L4 (1 << 1)
+#define AUTOSTAT_L3 (1 << 0)
+#define PM_WKEN1_CORE 0x2a0
+#define PM_WKEN2_CORE 0x2a4
+#define PM_WKST1_CORE 0x2b0
+#define PM_WKST2_CORE 0x2b4
+#define PM_WKDEP_CORE 0x2c8
+#define PM_PWSTCTRL_CORE 0x2e0
+#define PM_PWSTST_CORE 0x2e4
+
+
+#define CM_CLKSTCTRL_GFX 0x348
+#define AUTOSTAT_GFX (1 << 0)
+#define PM_WKDEP_GFX 0x3c8
+#define PM_PWSTCTRL_GFX 0x3e0
+
+
+#define CM_FCLKEN_WKUP 0x400
+#define CM_ICLKEN_WKUP 0x410
+#define CM_AUTOIDLE_WKUP 0x430
+#define PM_WKEN_WKUP 0x4a0
+#define EN_GPIOS (1 << 2)
+#define EN_GPT1 (1 << 0)
+#define PM_WKST_WKUP 0x4b0
+
+
+#define CM_CLKEN_PLL 0x500
+#define CM_IDLEST_CKGEN 0x520
+#define CM_AUTOIDLE_PLL 0x530
+#define CM_CLKSEL1_PLL 0x540
+#define CM_CLKSEL2_PLL 0x544
+
+
+#define CM_FCLKEN_DSP 0x800
+#define CM_ICLKEN_DSP 0x810
+#define CM_IDLEST_DSP 0x820
+#define CM_AUTOIDLE_DSP 0x830
+#define CM_CLKSEL_DSP 0x840
+#define CM_CLKSTCTRL_DSP 0x848
+#define AUTOSTAT_IVA (1 << 8)
+#define AUTOSTAT_DSP (1 << 0)
+#define RM_RSTCTRL_DSP 0x850
+#define RM_RSTST_DSP 0x858
+#define PM_WKDEP_DSP 0x8c8
+#define PM_PWSTCTRL_DSP 0x8e0
+#define PM_PWSTST_DSP 0x8e4

-#include "prcm-regs.h"
-
-static struct clk *vclk;
static void (*omap2_sram_idle)(void);
-static void (*omap2_sram_suspend)(int dllctrl, int cpu_rev); +static void (*omap2_sram_suspend)(int dllctrl);
static void (*saved_idle)(void);

-extern void __init pmdomain_init(void);
-extern void pmdomain_set_autoidle(void);
+static u32 prcm_base = IO_ADDRESS(PRCM_BASE);
+
+static inline void prcm_write_reg(int idx, u32 val)
+{
+ __raw_writel(val, prcm_base + idx);
+}
+
+static inline u32 prcm_read_reg(int idx)
+{
+ return __raw_readl(prcm_base + idx);
+}
+
+static u32 omap2_read_32k_sync_counter(void)
+{
+ return omap_readl(0x48004010);
+}
+
+#ifdef CONFIG_PM_DEBUG
+int omap2_pm_debug = 0;
+
+static int serial_console_clock_disabled;
+static int serial_console_uart;
+static unsigned int serial_console_next_disable;
+
+static struct clk *console_iclk, *console_fclk;
+
+static void serial_console_kick(void)
+{
+ serial_console_next_disable = omap2_read_32k_sync_counter();
+ /* Keep the clocks on for 4 secs */
+ serial_console_next_disable += 4 * 32768;
+}
+
+static void serial_wait_tx(void)
+{
+ static const unsigned long uart_bases[3] = {
+ 0x4806a000, 0x4806c000, 0x4806e000
+ };
+ unsigned long lsr_reg;
+ int looped = 0;
+
+ /* Wait for TX FIFO and THR to get empty */
+ lsr_reg = IO_ADDRESS(uart_bases[serial_console_uart - 1] + (5 << 2));
+ while ((__raw_readb(lsr_reg) & 0x60) != 0x60)
+ looped = 1;
+ if (looped)
+ serial_console_kick();
+}
+
+static void serial_console_fclk_mask(u32 *f1, u32 *f2)
+{
+ switch (serial_console_uart) {
+ case 1:
+ *f1 &= ~(1 << 21);
+ break;
+ case 2:
+ *f1 &= ~(1 << 22);
+ break;
+ case 3:
+ *f2 &= ~(1 << 2);
+ break;
+ }
+}
+
+static void serial_console_sleep(int enable)
+{
+ if (console_iclk == NULL || console_fclk == NULL)
+ return;
+
+ if (enable) {
+ BUG_ON(serial_console_clock_disabled);
+ if (clk_get_usecount(console_fclk) == 0)
+ return;
+ if ((int) serial_console_next_disable - (int) omap2_read_32k_sync_counter() >= 0)
+ return;
+ serial_wait_tx();
+ clk_disable(console_iclk);
+ clk_disable(console_fclk);
+ serial_console_clock_disabled = 1;
+ } else {
+ int serial_wakeup = 0;
+ u32 l;
+
+ switch (serial_console_uart) {
+ case 1:
+ l = prcm_read_reg(PM_WKST1_CORE);
+ if (l & (1 << 21))
+ serial_wakeup = 1;
+ break;
+ case 2:
+ l = prcm_read_reg(PM_WKST1_CORE);
+ if (l & (1 << 22))
+ serial_wakeup = 1;
+ break;
+ case 3:
+ l = prcm_read_reg(PM_WKST2_CORE);
+ if (l & (1 << 2))
+ serial_wakeup = 1;
+ break;
+ }
+ if (serial_wakeup)
+ serial_console_kick();
+ if (!serial_console_clock_disabled)
+ return;
+ clk_enable(console_iclk);
+ clk_enable(console_fclk);
+ serial_console_clock_disabled = 0;
+ }
+}
+
+static void pm_init_serial_console(void)
+{
+ const struct omap_serial_console_config *conf;
+ char name[16];
+ u32 l;
+
+ conf = omap_get_config(OMAP_TAG_SERIAL_CONSOLE,
+ struct omap_serial_console_config);
+ if (conf == NULL)
+ return;
+ if (conf->console_uart > 3 || conf->console_uart < 1)
+ return;
+ serial_console_uart = conf->console_uart;
+ sprintf(name, "uart%d_fck", conf->console_uart);
+ console_fclk = clk_get(NULL, name);
+ if (IS_ERR(console_fclk))
+ console_fclk = NULL;
+ name[6] = 'i';
+ console_iclk = clk_get(NULL, name);
+ if (IS_ERR(console_fclk))
+ console_iclk = NULL;
+ if (console_fclk == NULL || console_iclk == NULL) {
+ serial_console_uart = 0;
+ return;
+ }
+ switch (serial_console_uart) {
+ case 1:
+ l = prcm_read_reg(PM_WKEN1_CORE);
+ l |= 1 << 21;
+ prcm_write_reg(PM_WKEN1_CORE, l);
+ break;
+ case 2:
+ l = prcm_read_reg(PM_WKEN1_CORE);
+ l |= 1 << 22;
+ prcm_write_reg(PM_WKEN1_CORE, l);
+ break;
+ case 3:
+ l = prcm_read_reg(PM_WKEN2_CORE);
+ l |= 1 << 2;
+ prcm_write_reg(PM_WKEN2_CORE, l);
+ break;
+ }
+}
+
+#define DUMP_REG(reg) \
+ regs[reg_count].name = #reg; \
+ regs[reg_count++].val = prcm_read_reg(reg)
+#define DUMP_INTC_REG(reg, off) \
+ regs[reg_count].name = #reg; \
+ regs[reg_count++].val = __raw_readl(IO_ADDRESS(0x480fe000 + (off)))
+
+static void omap2_pm_dump(int mode, int resume, unsigned int us)
+{
+ struct reg {
+ const char *name;
+ u32 val;
+ } regs[32];
+ int reg_count = 0, i;
+ const char *s1 = NULL, *s2 = NULL;
+
+ if (!resume) {
+#if 0
+ /* MPU */
+ DUMP_REG(PRCM_IRQENABLE_MPU);
+ DUMP_REG(CM_CLKSTCTRL_MPU);
+ DUMP_REG(PM_PWSTCTRL_MPU);
+ DUMP_REG(PM_PWSTST_MPU);
+ DUMP_REG(PM_WKDEP_MPU);
+#endif
+#if 0
+ /* INTC */
+ DUMP_INTC_REG(INTC_MIR0, 0x0084);
+ DUMP_INTC_REG(INTC_MIR1, 0x00a4);
+ DUMP_INTC_REG(INTC_MIR2, 0x00c4);
+#endif
+#if 0
+ DUMP_REG(CM_FCLKEN1_CORE);
+ DUMP_REG(CM_FCLKEN2_CORE);
+ DUMP_REG(CM_FCLKEN_WKUP);
+ DUMP_REG(CM_ICLKEN1_CORE);
+ DUMP_REG(CM_ICLKEN2_CORE);
+ DUMP_REG(CM_ICLKEN_WKUP);
+ DUMP_REG(CM_CLKEN_PLL);
+ DUMP_REG(PRCM_CLKEMUL_CTRL);
+ DUMP_REG(CM_AUTOIDLE_PLL);
+ DUMP_REG(PM_PWSTST_CORE);
+ DUMP_REG(PRCM_CLKSRC_CTRL);
+#endif
+#if 0
+ /* DSP */
+ DUMP_REG(CM_FCLKEN_DSP);
+ DUMP_REG(CM_ICLKEN_DSP);
+ DUMP_REG(CM_IDLEST_DSP);
+ DUMP_REG(CM_AUTOIDLE_DSP);
+ DUMP_REG(CM_CLKSEL_DSP);
+ DUMP_REG(CM_CLKSTCTRL_DSP);
+ DUMP_REG(RM_RSTCTRL_DSP);
+ DUMP_REG(RM_RSTST_DSP);
+ DUMP_REG(PM_PWSTCTRL_DSP);
+ DUMP_REG(PM_PWSTST_DSP);
+#endif
+ } else {
+ DUMP_REG(PM_WKST1_CORE);
+ DUMP_REG(PM_WKST2_CORE);
+ DUMP_REG(PM_WKST_WKUP);
+ DUMP_REG(PRCM_IRQSTATUS_MPU);
+#if 1
+ DUMP_INTC_REG(INTC_PENDING_IRQ0, 0x0098);
+ DUMP_INTC_REG(INTC_PENDING_IRQ1, 0x00b8);
+ DUMP_INTC_REG(INTC_PENDING_IRQ2, 0x00d8);
+#endif
+ }
+
+ switch (mode) {
+ case 0:
+ s1 = "full";
+ s2 = "retention";
+ break;
+ case 1:
+ s1 = "MPU";
+ s2 = "retention";
+ break;
+ case 2:
+ s1 = "MPU";
+ s2 = "idle";
+ break;
+ }
+
+ if (!resume)
+ printk("--- Going to %s %s (next timer after %u ms)\n", s1, s2,
+ jiffies_to_msecs(next_timer_interrupt() - jiffies));
+ else
+ printk("--- Woke up (slept for %u.%03u ms)\n", us / 1000, us % 1000);
+ for (i = 0; i < reg_count; i++)
+ printk("%-20s: 0x%08x\n", regs[i].name, regs[i].val);
+}
+
+#else
+static inline void serial_console_sleep(int enable) {}
+static inline void pm_init_serial_console(void) {}
+static inline void omap2_pm_dump(int mode, int resume, unsigned int us) {} +static inline void serial_console_fclk_mask(u32 *f1, u32 *f2) {}
+
+#define omap2_pm_debug 0
+
+#endif
+
+static unsigned short enable_dyn_sleep = 0; /* disabled till drivers are fixed */ +
+static ssize_t omap_pm_sleep_while_idle_show(struct subsystem * subsys, char *buf) +{
+ return sprintf(buf, "%hu\n", enable_dyn_sleep);
+}
+
+static ssize_t omap_pm_sleep_while_idle_store(struct subsystem * subsys,
+ const char * buf,
+ size_t n)
+{
+ unsigned short value;
+ if (sscanf(buf, "%hu", &value) != 1 ||
+ (value != 0 && value != 1)) {
+ printk(KERN_ERR "idle_sleep_store: Invalid value\n");
+ return -EINVAL;
+ }
+ enable_dyn_sleep = value;
+ return n;
+}
+
+static struct subsys_attribute sleep_while_idle_attr = {
+ .attr = {
+ .name = __stringify(sleep_while_idle),
+ .mode = 0644,
+ },
+ .show = omap_pm_sleep_while_idle_show,
+ .store = omap_pm_sleep_while_idle_store,
+};
+
+extern struct subsystem power_subsys;
+
+static struct clk *osc_ck, *emul_ck;
+
+#define CONTROL_DEVCONF __REG32(0x48000274)
+#define SDRC_DLLA_CTRL __REG32(0x68009060)
+
+static int omap2_fclks_active(void)
+{
+ u32 f1, f2;

-static unsigned int omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_SIZE];
+ f1 = prcm_read_reg(CM_FCLKEN1_CORE);
+ f2 = prcm_read_reg(CM_FCLKEN2_CORE);
+ serial_console_fclk_mask(&f1, &f2);
+ if (f1 | f2)
+ return 1;
+ return 0;
+}

-void omap2_pm_idle(void)
+static int omap2_irq_pending(void)
+{
+ u32 pending_reg = IO_ADDRESS(0x480fe098);
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (__raw_readl(pending_reg))
+ return 1;
+ pending_reg += 0x20;
+ }
+ return 0;
+}
+
+static atomic_t sleep_block = ATOMIC_INIT(0); +
+void omap2_block_sleep(void)
+{
+ atomic_inc(&sleep_block);
+}
+
+void omap2_allow_sleep(void)
+{
+ int i;
+
+ i = atomic_dec_return(&sleep_block);
+ BUG_ON(i < 0);
+}
+
+extern void omap2_gpio_prepare_for_retention(void); +extern void omap2_gpio_resume_after_retention(void); +
+static void omap2_enter_full_retention(void) +{
+ u32 sleep_time = 0;
+
+ /* There is 1 reference hold for all children of the oscillator
+ * clock, the following will remove it. If no one else uses the
+ * oscillator itself it will be disabled if/when we enter retention
+ * mode.
+ */
+ clk_disable(osc_ck);
+
+ /* Clear old wake-up events */
+ prcm_write_reg(PM_WKST1_CORE, 0xffffffff);
+ prcm_write_reg(PM_WKST2_CORE, 0xffffffff);
+ prcm_write_reg(PM_WKST_WKUP, 0xffffffff);
+
+ /* Try to enter retention */
+ prcm_write_reg(PM_PWSTCTRL_MPU, (0x01 << 0) | (1 << 2));
+
+ /* Workaround to kill USB */
+ CONTROL_DEVCONF |= 0x00008000;
+
+ omap2_gpio_prepare_for_retention();
+
+ if (omap2_pm_debug) {
+ omap2_pm_dump(0, 0, 0);
+ sleep_time = omap2_read_32k_sync_counter();
+ }
+
+ /* One last check for pending IRQs to avoid extra latency due
+ * to sleeping unnecessarily. */
+ if (omap2_irq_pending())
+ goto no_sleep;
+
+ serial_console_sleep(1);
+ /* Jump to SRAM suspend code */
+ omap2_sram_suspend(SDRC_DLLA_CTRL);
+no_sleep:
+ serial_console_sleep(0);
+
+ if (omap2_pm_debug) {
+ unsigned long long tmp;
+ u32 resume_time;
+
+ resume_time = omap2_read_32k_sync_counter();
+ tmp = resume_time - sleep_time;
+ tmp *= 1000000;
+ omap2_pm_dump(0, 1, tmp / 32768);
+ }
+ omap2_gpio_resume_after_retention();
+
+ clk_enable(osc_ck);
+
+}
+
+static int omap2_i2c_active(void)
+{
+ u32 l;
+
+ l = prcm_read_reg(CM_FCLKEN1_CORE);
+ return l & ((1 << 19) | (1 << 20));
+}
+
+static int sti_console_enabled;
+
+static int omap2_allow_mpu_retention(void) +{
+ u32 l;
+
+ if (atomic_read(&sleep_block))
+ return 0;
+
+ /* Check for UART2, UART1, McSPI2, McSPI1 and DSS1. */
+ l = prcm_read_reg(CM_FCLKEN1_CORE);
+ if (l & 0x04660001)
+ return 0;
+ /* Check for UART3. */
+ l = prcm_read_reg(CM_FCLKEN2_CORE);
+ if (l & (1 << 2))
+ return 0;
+ if (sti_console_enabled)
+ return 0;
+
+ /* FIXME: Enable soon */
+ return 0;
+}
+
+static void omap2_enter_mpu_retention(void) +{
+ u32 sleep_time = 0;
+ int only_idle = 0;
+
+ /* Putting MPU into the WFI state while a transfer is active
+ * seems to cause the I2C block to timeout. Why? Good question. */
+ if (omap2_i2c_active())
+ return;
+
+ /* The peripherals seem not to be able to wake up the MPU when
+ * it is in retention mode. */
+ if (omap2_allow_mpu_retention()) {
+ prcm_write_reg(PM_WKST1_CORE, 0xffffffff);
+ prcm_write_reg(PM_WKST2_CORE, 0xffffffff);
+ prcm_write_reg(PM_WKST_WKUP, 0xffffffff);
+
+ /* Try to enter MPU retention */
+ prcm_write_reg(PM_PWSTCTRL_MPU, (0x01 << 0) | (1 << 2));
+ } else {
+ /* Block MPU retention */
+ prcm_write_reg(PM_PWSTCTRL_MPU, 1 << 2);
+ only_idle = 1;
+ }
+
+ if (omap2_pm_debug) {
+ omap2_pm_dump(only_idle ? 2 : 1, 0, 0);
+ sleep_time = omap2_read_32k_sync_counter();
+ }
+
+ omap2_sram_idle();
+
+ if (omap2_pm_debug) {
+ unsigned long long tmp;
+ u32 resume_time;
+
+ resume_time = omap2_read_32k_sync_counter();
+ tmp = resume_time - sleep_time;
+ tmp *= 1000000;
+ omap2_pm_dump(only_idle ? 2 : 1, 1, tmp / 32768);
+ }
+}
+
+static int omap2_can_sleep(void)
+{
+ if (!enable_dyn_sleep)
+ return 0;
+ if (omap2_fclks_active())
+ return 0;
+ if (atomic_read(&sleep_block) > 0)
+ return 0;
+ if (clk_get_usecount(osc_ck) > 1)
+ return 0;
+ if (omap_dma_running())
+ return 0;
+
+ return 1;
+}
+
+static void omap2_pm_idle(void)
{
local_irq_disable(); local_fiq_disable();
- if (need_resched()) {
- local_fiq_enable();
- local_irq_enable();
- return;
+
+ if (!omap2_can_sleep()) {
+ /* timer_dyn_reprogram() takes about 100-200 us to complete.
+ * In some contexts (e.g. when waiting for a GPMC-SDRAM DMA
+ * transfer to complete), the increased latency is too much.
+ *
+ * omap2_block_sleep() and omap2_allow_sleep() can be used
+ * to indicate this.
+ */
+ if (atomic_read(&sleep_block) == 0) {
+ timer_dyn_reprogram();
+ if (omap2_irq_pending())
+ goto out;
+ }
+ omap2_enter_mpu_retention();
+ goto out;
}

/*
@@ -66,7 +662,12 @@
*/
timer_dyn_reprogram();

- omap2_sram_idle();
+ if (omap2_irq_pending())
+ goto out;
+
+ omap2_enter_full_retention();
+
+out:
local_fiq_enable();
local_irq_enable();
}
@@ -79,15 +680,12 @@
saved_idle = pm_idle;
pm_idle = NULL;

- switch (state)
- {
+ switch (state) {
case PM_SUSPEND_STANDBY:
case PM_SUSPEND_MEM:
break;
-
case PM_SUSPEND_DISK:
return -ENOTSUPP;
-
default:
return -EINVAL;
}
@@ -95,250 +693,21 @@
return error;
}

-#define INT0_WAKE_MASK (OMAP_IRQ_BIT(INT_24XX_GPIO_BANK1) | \
- OMAP_IRQ_BIT(INT_24XX_GPIO_BANK2) | \
- OMAP_IRQ_BIT(INT_24XX_GPIO_BANK3))
-
-#define INT1_WAKE_MASK (OMAP_IRQ_BIT(INT_24XX_GPIO_BANK4))
-
-#define INT2_WAKE_MASK (OMAP_IRQ_BIT(INT_24XX_UART1_IRQ) | \
- OMAP_IRQ_BIT(INT_24XX_UART2_IRQ) | \
- OMAP_IRQ_BIT(INT_24XX_UART3_IRQ))
-
-#define preg(reg) printk("%s\t(0x%p):\t0x%08x\n", #reg, &reg, reg);
-
-static void omap2_pm_debug(char * desc)
-{
- printk("%s:\n", desc);
-
- preg(CM_CLKSTCTRL_MPU);
- preg(CM_CLKSTCTRL_CORE);
- preg(CM_CLKSTCTRL_GFX);
- preg(CM_CLKSTCTRL_DSP);
- preg(CM_CLKSTCTRL_MDM);
-
- preg(PM_PWSTCTRL_MPU);
- preg(PM_PWSTCTRL_CORE);
- preg(PM_PWSTCTRL_GFX);
- preg(PM_PWSTCTRL_DSP);
- preg(PM_PWSTCTRL_MDM);
-
- preg(PM_PWSTST_MPU);
- preg(PM_PWSTST_CORE);
- preg(PM_PWSTST_GFX);
- preg(PM_PWSTST_DSP);
- preg(PM_PWSTST_MDM);
-
- preg(CM_AUTOIDLE1_CORE);
- preg(CM_AUTOIDLE2_CORE);
- preg(CM_AUTOIDLE3_CORE);
- preg(CM_AUTOIDLE4_CORE);
- preg(CM_AUTOIDLE_WKUP);
- preg(CM_AUTOIDLE_PLL);
- preg(CM_AUTOIDLE_DSP);
- preg(CM_AUTOIDLE_MDM);
-
- preg(CM_ICLKEN1_CORE);
- preg(CM_ICLKEN2_CORE);
- preg(CM_ICLKEN3_CORE);
- preg(CM_ICLKEN4_CORE);
- preg(CM_ICLKEN_GFX);
- preg(CM_ICLKEN_WKUP);
- preg(CM_ICLKEN_DSP);
- preg(CM_ICLKEN_MDM);
-
- preg(CM_IDLEST1_CORE);
- preg(CM_IDLEST2_CORE);
- preg(CM_IDLEST3_CORE);
- preg(CM_IDLEST4_CORE);
- preg(CM_IDLEST_GFX);
- preg(CM_IDLEST_WKUP);
- preg(CM_IDLEST_CKGEN);
- preg(CM_IDLEST_DSP);
- preg(CM_IDLEST_MDM);
-
- preg(RM_RSTST_MPU);
- preg(RM_RSTST_GFX);
- preg(RM_RSTST_WKUP);
- preg(RM_RSTST_DSP);
- preg(RM_RSTST_MDM);
-
- preg(PM_WKDEP_MPU);
- preg(PM_WKDEP_CORE);
- preg(PM_WKDEP_GFX);
- preg(PM_WKDEP_DSP);
- preg(PM_WKDEP_MDM);
-
- preg(CM_FCLKEN_WKUP);
- preg(CM_ICLKEN_WKUP);
- preg(CM_IDLEST_WKUP);
- preg(CM_AUTOIDLE_WKUP);
- preg(CM_CLKSEL_WKUP);
-
- preg(PM_WKEN_WKUP);
- preg(PM_WKST_WKUP);
-}
-
-static inline void omap2_pm_save_registers(void) -{
- /* Save interrupt registers */
- OMAP24XX_SAVE(INTC_MIR0);
- OMAP24XX_SAVE(INTC_MIR1);
- OMAP24XX_SAVE(INTC_MIR2);
-
- /* Save power control registers */
- OMAP24XX_SAVE(CM_CLKSTCTRL_MPU);
- OMAP24XX_SAVE(CM_CLKSTCTRL_CORE);
- OMAP24XX_SAVE(CM_CLKSTCTRL_GFX);
- OMAP24XX_SAVE(CM_CLKSTCTRL_DSP);
- OMAP24XX_SAVE(CM_CLKSTCTRL_MDM);
-
- /* Save power state registers */
- OMAP24XX_SAVE(PM_PWSTCTRL_MPU);
- OMAP24XX_SAVE(PM_PWSTCTRL_CORE);
- OMAP24XX_SAVE(PM_PWSTCTRL_GFX);
- OMAP24XX_SAVE(PM_PWSTCTRL_DSP);
- OMAP24XX_SAVE(PM_PWSTCTRL_MDM);
-
- /* Save autoidle registers */
- OMAP24XX_SAVE(CM_AUTOIDLE1_CORE);
- OMAP24XX_SAVE(CM_AUTOIDLE2_CORE);
- OMAP24XX_SAVE(CM_AUTOIDLE3_CORE);
- OMAP24XX_SAVE(CM_AUTOIDLE4_CORE);
- OMAP24XX_SAVE(CM_AUTOIDLE_WKUP);
- OMAP24XX_SAVE(CM_AUTOIDLE_PLL);
- OMAP24XX_SAVE(CM_AUTOIDLE_DSP);
- OMAP24XX_SAVE(CM_AUTOIDLE_MDM);
-
- /* Save idle state registers */
- OMAP24XX_SAVE(CM_IDLEST1_CORE);
- OMAP24XX_SAVE(CM_IDLEST2_CORE);
- OMAP24XX_SAVE(CM_IDLEST3_CORE);
- OMAP24XX_SAVE(CM_IDLEST4_CORE);
- OMAP24XX_SAVE(CM_IDLEST_GFX);
- OMAP24XX_SAVE(CM_IDLEST_WKUP);
- OMAP24XX_SAVE(CM_IDLEST_CKGEN);
- OMAP24XX_SAVE(CM_IDLEST_DSP);
- OMAP24XX_SAVE(CM_IDLEST_MDM);
-
- /* Save clock registers */
- OMAP24XX_SAVE(CM_FCLKEN1_CORE);
- OMAP24XX_SAVE(CM_FCLKEN2_CORE);
- OMAP24XX_SAVE(CM_ICLKEN1_CORE);
- OMAP24XX_SAVE(CM_ICLKEN2_CORE);
- OMAP24XX_SAVE(CM_ICLKEN3_CORE);
- OMAP24XX_SAVE(CM_ICLKEN4_CORE);
-}
-
-static inline void omap2_pm_restore_registers(void) -{
- /* Restore clock state registers */
- OMAP24XX_RESTORE(CM_CLKSTCTRL_MPU);
- OMAP24XX_RESTORE(CM_CLKSTCTRL_CORE);
- OMAP24XX_RESTORE(CM_CLKSTCTRL_GFX);
- OMAP24XX_RESTORE(CM_CLKSTCTRL_DSP);
- OMAP24XX_RESTORE(CM_CLKSTCTRL_MDM);
-
- /* Restore power state registers */
- OMAP24XX_RESTORE(PM_PWSTCTRL_MPU);
- OMAP24XX_RESTORE(PM_PWSTCTRL_CORE);
- OMAP24XX_RESTORE(PM_PWSTCTRL_GFX);
- OMAP24XX_RESTORE(PM_PWSTCTRL_DSP);
- OMAP24XX_RESTORE(PM_PWSTCTRL_MDM);
-
- /* Restore idle state registers */
- OMAP24XX_RESTORE(CM_IDLEST1_CORE);
- OMAP24XX_RESTORE(CM_IDLEST2_CORE);
- OMAP24XX_RESTORE(CM_IDLEST3_CORE);
- OMAP24XX_RESTORE(CM_IDLEST4_CORE);
- OMAP24XX_RESTORE(CM_IDLEST_GFX);
- OMAP24XX_RESTORE(CM_IDLEST_WKUP);
- OMAP24XX_RESTORE(CM_IDLEST_CKGEN);
- OMAP24XX_RESTORE(CM_IDLEST_DSP);
- OMAP24XX_RESTORE(CM_IDLEST_MDM);
-
- /* Restore autoidle registers */
- OMAP24XX_RESTORE(CM_AUTOIDLE1_CORE);
- OMAP24XX_RESTORE(CM_AUTOIDLE2_CORE);
- OMAP24XX_RESTORE(CM_AUTOIDLE3_CORE);
- OMAP24XX_RESTORE(CM_AUTOIDLE4_CORE);
- OMAP24XX_RESTORE(CM_AUTOIDLE_WKUP);
- OMAP24XX_RESTORE(CM_AUTOIDLE_PLL);
- OMAP24XX_RESTORE(CM_AUTOIDLE_DSP);
- OMAP24XX_RESTORE(CM_AUTOIDLE_MDM);
-
- /* Restore clock registers */
- OMAP24XX_RESTORE(CM_FCLKEN1_CORE);
- OMAP24XX_RESTORE(CM_FCLKEN2_CORE);
- OMAP24XX_RESTORE(CM_ICLKEN1_CORE);
- OMAP24XX_RESTORE(CM_ICLKEN2_CORE);
- OMAP24XX_RESTORE(CM_ICLKEN3_CORE);
- OMAP24XX_RESTORE(CM_ICLKEN4_CORE);
-
- /* REVISIT: Clear interrupts here */
-
- /* Restore interrupt registers */
- OMAP24XX_RESTORE(INTC_MIR0);
- OMAP24XX_RESTORE(INTC_MIR1);
- OMAP24XX_RESTORE(INTC_MIR2);
-}
-
static int omap2_pm_suspend(void)
{
- int processor_type = 0;
+ u32 wken_wkup, mir1;

- /* REVISIT: 0x21 or 0x26? */
- if (cpu_is_omap2420())
- processor_type = 0x21;
+ wken_wkup = prcm_read_reg(PM_WKEN_WKUP);
+ prcm_write_reg(PM_WKEN_WKUP, wken_wkup & ~EN_GPT1);

- if (!processor_type)
- return -ENOTSUPP;
+ /* Mask GPT1 */
+ mir1 = omap_readl(0x480fe0a4);
+ omap_writel(1 << 5, 0x480fe0ac);

- local_irq_disable();
- local_fiq_disable();
-
- omap2_pm_save_registers();
-
- /* Disable interrupts except for the wake events */
- INTC_MIR_SET0 = 0xffffffff & ~INT0_WAKE_MASK;
- INTC_MIR_SET1 = 0xffffffff & ~INT1_WAKE_MASK;
- INTC_MIR_SET2 = 0xffffffff & ~INT2_WAKE_MASK;
-
- pmdomain_set_autoidle();
-
- /* Clear old wake-up events */
- PM_WKST1_CORE = 0;
- PM_WKST2_CORE = 0;
- PM_WKST_WKUP = 0;
+ omap2_enter_full_retention();

- /* Enable wake-up events */
- PM_WKEN1_CORE = (1 << 22) | (1 << 21); /* UART1 & 2 */
- PM_WKEN2_CORE = (1 << 2); /* UART3 */
- PM_WKEN_WKUP = (1 << 2) | (1 << 0); /* GPIO & GPT1 */
-
- /* Disable clocks except for CM_ICLKEN2_CORE. It gets disabled
- * in the SRAM suspend code */
- CM_FCLKEN1_CORE = 0;
- CM_FCLKEN2_CORE = 0;
- CM_ICLKEN1_CORE = 0;
- CM_ICLKEN3_CORE = 0;
- CM_ICLKEN4_CORE = 0;
-
- omap2_pm_debug("Status before suspend");
-
- /* Must wait for serial buffers to clear */
- mdelay(200);
-
- /* Jump to SRAM suspend code
- * REVISIT: When is this SDRC_DLLB_CTRL?
- */
- omap2_sram_suspend(SDRC_DLLA_CTRL, processor_type);
-
- /* Back from sleep */
- omap2_pm_restore_registers();
-
- local_fiq_enable();
- local_irq_enable();
+ omap_writel(mir1, 0x480fe0a4);
+ prcm_write_reg(PM_WKEN_WKUP, wken_wkup);

return 0;
}
@@ -347,8 +716,7 @@
{
int ret = 0;

- switch (state)
- {
+ switch (state) {
case PM_SUSPEND_STANDBY:
case PM_SUSPEND_MEM:
ret = omap2_pm_suspend();
@@ -376,16 +744,100 @@
.finish = omap2_pm_finish,
};

+static void __init prcm_setup_regs(void)
+{
+ u32 l;
+
+ /* Enable autoidle */
+ prcm_write_reg(PRCM_SYSCONFIG, 1 << 0);
+
+ /* Set all domain wakeup dependencies */
+ prcm_write_reg(PM_WKDEP_MPU, EN_WKUP);
+ prcm_write_reg(PM_WKDEP_DSP, 0);
+ prcm_write_reg(PM_WKDEP_GFX, 0);
+
+ l = prcm_read_reg(PM_PWSTCTRL_CORE);
+ /* Enable retention for all memory blocks */
+ l |= (1 << 3) | (1 << 4) | (1 << 5);
+ /* Set power state to RETENTION */
+ l &= ~0x03;
+ l |= 0x01 << 0;
+ prcm_write_reg(PM_PWSTCTRL_CORE, l);
+
+ prcm_write_reg(PM_PWSTCTRL_MPU, (0x01 << 0) | (1 << 2));
+
+ /* Power down DSP and GFX */
+ prcm_write_reg(PM_PWSTCTRL_DSP, (1 << 18) | 0x03);
+ prcm_write_reg(PM_PWSTCTRL_GFX, (1 << 18) | 0x03);
+
+ /* Enable clock auto control for all domains */
+ prcm_write_reg(CM_CLKSTCTRL_MPU, AUTOSTAT_MPU);
+ prcm_write_reg(CM_CLKSTCTRL_CORE, AUTOSTAT_DSS | AUTOSTAT_L4 | AUTOSTAT_L3);
+ prcm_write_reg(CM_CLKSTCTRL_GFX, AUTOSTAT_GFX);
+ prcm_write_reg(CM_CLKSTCTRL_DSP, AUTOSTAT_IVA | AUTOSTAT_DSP);
+
+ /* Enable clock autoidle for all domains */
+ prcm_write_reg(CM_AUTOIDLE1_CORE, 0xfffffff9);
+ prcm_write_reg(CM_AUTOIDLE2_CORE, 0x07);
+ prcm_write_reg(CM_AUTOIDLE3_CORE, 0x07);
+ prcm_write_reg(CM_AUTOIDLE4_CORE, 0x1f);
+
+ prcm_write_reg(CM_AUTOIDLE_DSP, 0x02);
+
+ /* Put DPLL and both APLLs into autoidle mode */
+ prcm_write_reg(CM_AUTOIDLE_PLL, (0x03 << 0) | (0x03 << 2) | (0x03 << 6));
+
+ prcm_write_reg(CM_AUTOIDLE_WKUP, 0x3f);
+
+ /* REVISIT: Configure number of 32 kHz clock cycles for sys_clk
+ * stabilisation */
+ prcm_write_reg(PRCM_CLKSSETUP, 15);
+
+ /* Configure automatic voltage transition */
+ prcm_write_reg(PRCM_VOLTSETUP, 2);
+ l = AUTO_EXTVOLT | SETOFF_LEVEL(1) | MEMRETCTRL | \
+ SETRET_LEVEL(1) | VOLT_LEVEL(0);
+ prcm_write_reg(PRCM_VOLTCTRL, l);
+
+ /* Enable wake-up events */
+ prcm_write_reg(PM_WKEN_WKUP, EN_GPIOS | EN_GPT1);
+}
+
int __init omap2_pm_init(void)
{
- printk("Power Management for TI OMAP.\n");
+ u32 l;
+
+ printk(KERN_INFO "Power Management for OMAP2 initializing\n");
+ l = prcm_read_reg(PRCM_REVISION);
+ printk(KERN_INFO "PRCM revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
+
+ osc_ck = clk_get(NULL, "osc_ck");
+ if (IS_ERR(osc_ck)) {
+ printk(KERN_ERR "could not get osc_ck\n");
+ return -ENODEV;
+ }

- vclk = clk_get(NULL, "virt_prcm_set");
- if (IS_ERR(vclk)) {
- printk(KERN_ERR "Could not get PM vclk\n");
+ emul_ck = clk_get(NULL, "emul_ck");
+ if (IS_ERR(emul_ck)) {
+ printk(KERN_ERR "could not get emul_ck\n");
+ clk_put(osc_ck);
return -ENODEV;
}

+ prcm_setup_regs();
+
+ pm_init_serial_console();
+
+ /* Hack to prevent MPU retention when STI console is enabled. */
+ {
+ const struct omap_sti_console_config *sti;
+
+ sti = omap_get_config(OMAP_TAG_STI_CONSOLE,
+ struct omap_sti_console_config);
+ if (sti != NULL && sti->enable)
+ sti_console_enabled = 1;
+ }
+
/*
* We copy the assembler sleep/wakeup routines to SRAM.
* These routines need to be in SRAM as that's the only
@@ -393,16 +845,15 @@
*/
omap2_sram_idle = omap_sram_push(omap24xx_idle_loop_suspend,
omap24xx_idle_loop_suspend_sz);
-
omap2_sram_suspend = omap_sram_push(omap24xx_cpu_suspend,
omap24xx_cpu_suspend_sz);

pm_set_ops(&omap_pm_ops);
pm_idle = omap2_pm_idle;

- pmdomain_init();
+ subsys_create_file(&power_subsys, &sleep_while_idle_attr);

return 0;
}

-__initcall(omap2_pm_init);
+late_initcall(omap2_pm_init);

arch/arm/mach-omap2/sleep.S +5 -18
@@ -5,6 +5,10 @@
  * Texas Instruments, <www.ti.com>
  * Richard Woodruff <[email protected]>
  *
+ * (C) Copyright 2006 Nokia Corporation
+ * Fixed idle loop sleep
+ * Igor Stoppa <[email protected]>
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of
@@ -26,14 +30,6 @@
 #include <asm/arch/io.h>
 #include <asm/arch/pm.h>
 
-#define A_32KSYNC_CR_V		IO_ADDRESS(OMAP_TIMER32K_BASE+0x10)
-#define A_PRCM_VOLTCTRL_V	IO_ADDRESS(OMAP24XX_PRCM_BASE+0x50)
-#define A_PRCM_CLKCFG_CTRL_V	IO_ADDRESS(OMAP24XX_PRCM_BASE+0x80)
-#define A_CM_CLKEN_PLL_V	IO_ADDRESS(OMAP24XX_PRCM_BASE+0x500)
-#define A_CM_IDLEST_CKGEN_V	IO_ADDRESS(OMAP24XX_PRCM_BASE+0x520)
-#define A_CM_CLKSEL1_PLL_V	IO_ADDRESS(OMAP24XX_PRCM_BASE+0x540)
-#define A_CM_CLKSEL2_PLL_V	IO_ADDRESS(OMAP24XX_PRCM_BASE+0x544)
-
 #define A_SDRC_DLLA_CTRL_V	IO_ADDRESS(OMAP24XX_SDRC_BASE+0x60)
 #define	A_SDRC_POWER_V		IO_ADDRESS(OMAP24XX_SDRC_BASE+0x70)
 #define A_SDRC_RFR_CTRL_V	IO_ADDRESS(OMAP24XX_SDRC_BASE+0xA4)
@@ -53,7 +49,7 @@
  */
 ENTRY(omap24xx_idle_loop_suspend)
 	stmfd	sp!, {r0, lr}		@ save registers on stack
-	mov	r0, #0			@ clear for mcr setup
+	mov	r0, #0x0		@ clear for mrc call
 	mcr	p15, 0, r0, c7, c0, 4	@ wait for interrupt
 	ldmfd	sp!, {r0, pc}		@ restore regs and return
 
@@ -67,9 +63,6 @@
  *
  * Input:
  * R0 :	DLL ctrl value pre-Sleep
- * R1 : Processor+Revision
- *	2420: 0x21 = 242xES1, 0x26 = 242xES2.2
- *	2430: 0x31 = 2430ES1, 0x32 = 2430ES2
  *
  * The if the DPLL is going to AutoIdle. It seems like the DPLL may be back on
  * when we get called, but the DLL probably isn't.  We will wait a bit more in
@@ -129,14 +122,8 @@
 	.word A_SDRC_POWER_V
 A_SDRC0:
 	.word A_SDRC0_V
-A_CM_CLKSEL2_PLL_S:
-	.word A_CM_CLKSEL2_PLL_V
-A_CM_CLKEN_PLL:
-	.word A_CM_CLKEN_PLL_V
 A_SDRC_DLLA_CTRL_S:
 	.word A_SDRC_DLLA_CTRL_V
-A_SDRC_MANUAL_S:
-	.word A_SDRC_MANUAL_V
 
 ENTRY(omap24xx_cpu_suspend_sz)
 	.word	. - omap24xx_cpu_suspend
include/asm-arm/arch-omap/pm.h +3 -63

87 lines not on this page · raw message

arch/arm/mach-omap2/pm-domain.c deleted +0 -299

299 lines not on this page · raw message

#1 lore raw
Quoted 1 line

[1]

http://repository.maemo.org/pool/maemo3.0/free/source/kernel-source-

Quoted 2 lines

rx-34_2.6.18.orig.tar.gz
[2]

http://repository.maemo.org/pool/maemo3.0/free/source/kernel-source-

Quoted 1 line

rx-34_2.6.18-osso29.diff.gz

Are these images available somewhere with a bit better connection? A week and some ago when I tried to download I didn't get any connection. After that I was traveling for a bit. Now that I'm trying again it is not progressing either.

Regards,
Richard W.

author maintainer
#2 lore raw
Quoted 11 lines · Woodruff, Richard
Quoted 1 line

[1]

http://repository.maemo.org/pool/maemo3.0/free/source/kernel-source-

Quoted 2 lines

rx-34_2.6.18.orig.tar.gz
[2]

http://repository.maemo.org/pool/maemo3.0/free/source/kernel-source-

Quoted 1 line

rx-34_2.6.18-osso29.diff.gz

Are these images available somewhere with a bit better connection? A week and some ago when I tried to download I didn't get any connection. After that I was traveling for a bit. Now that I'm trying again it is not progressing either.

Hmm, seems to download fine over my DSL line at around 160K/s, maybe it's some issue with TI proxy?

Tony

#3 lore raw
Quoted 1 line
Quoted 1 line

Are these images available somewhere with a bit better connection?

A

Quoted 1 line
Quoted 1 line

week and some ago when I tried to download I didn't get any

connection.

Quoted 1 line
Quoted 1 line

After that I was traveling for a bit. Now that I'm trying again it

is

Quoted 4 lines
Quoted 1 line

not progressing either.

Hmm, seems to download fine over my DSL line at around 160K/s, maybe it's some issue with TI proxy?

Perhaps... A couple different people around here grabbed them and have offered so I'll use that.

Thanks,
Richard W.

author maintainer
#4 lore raw
Quoted 5 lines · Woodruff, Richard
Quoted 1 line
Quoted 1 line

Are these images available somewhere with a bit better connection?

A

Quoted 1 line
Quoted 1 line

week and some ago when I tried to download I didn't get any

connection.

Quoted 1 line
Quoted 1 line

After that I was traveling for a bit. Now that I'm trying again it

Quoted 8 lines

is

Quoted 4 lines
Quoted 1 line

not progressing either.

Hmm, seems to download fine over my DSL line at around 160K/s, maybe it's some issue with TI proxy?

Perhaps... A couple different people around here grabbed them and have offered so I'll use that.

I've pushed the N800 PM code.

Tony

author maintainer
#5 lore raw
In reply to Tony Lindgren
Quoted 17 lines · Tony Lindgren

Hi all,

I'm planning to merge in the Nokia N800 PM code for omap2 available at
[1] and [2].

N800 patch gets rid of pm-domain.c and moves those functions to pm.c. It also adds handy debugging via serial console by keeping the serial clock on for few seconds after serial interrupts before allowing deeper sleep states.

Can somebody please test if it boots/works on H4? I don't currently have access to H4. Also it would be nice to get it patched to provide basic PM for 2430.

Once we have this merged in, we can start figuring out the interfaces needed for dynamic power management etc.

Quoted 6 lines

Regards,

Tony

[1] http://repository.maemo.org/pool/maemo3.0/free/source/kernel-source-rx-34_2.6.18.orig.tar.gz
[2] http://repository.maemo.org/pool/maemo3.0/free/source/kernel-source-rx-34_2.6.18-osso29.diff.gz

Oops, turns out the patch ad an extra space in it and does not apply. Here's a fixed version.

Tony

Merge Nokia N800 PM code from:

http://repository.maemo.org/pool/maemo3.0/free/source/kernel-source-rx-34_2.6.18.orig.tar.gz
http://repository.maemo.org/pool/maemo3.0/free/source/kernel-source-rx-34_2.6.18-osso29.diff.gz

N800 code moves PM related register access to pm.c from pm-domain.c to pm.c and adds PM debugging support via serial console.

arch/arm/mach-omap2/Makefile +1 -1
@@ -9,7 +9,7 @@
 obj-$(CONFIG_OMAP_MPU_TIMER)		+= timer-gp.o
 
 # Power Management
-obj-$(CONFIG_PM) += pm.o pm-domain.o sleep.o
+obj-$(CONFIG_PM) += pm.o sleep.o
 
 # DSP
 obj-$(CONFIG_OMAP_DSP)	+= mailbox_mach.o
arch/arm/mach-omap2/pm.c +715 -264

1,066 lines not on this page · raw message

arch/arm/mach-omap2/sleep.S +5 -18
@@ -5,6 +5,10 @@
  * Texas Instruments, <www.ti.com>
  * Richard Woodruff <[email protected]>
  *
+ * (C) Copyright 2006 Nokia Corporation
+ * Fixed idle loop sleep
+ * Igor Stoppa <[email protected]>
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of
@@ -26,14 +30,6 @@
 #include <asm/arch/io.h>
 #include <asm/arch/pm.h>
 
-#define A_32KSYNC_CR_V		IO_ADDRESS(OMAP_TIMER32K_BASE+0x10)
-#define A_PRCM_VOLTCTRL_V	IO_ADDRESS(OMAP24XX_PRCM_BASE+0x50)
-#define A_PRCM_CLKCFG_CTRL_V	IO_ADDRESS(OMAP24XX_PRCM_BASE+0x80)
-#define A_CM_CLKEN_PLL_V	IO_ADDRESS(OMAP24XX_PRCM_BASE+0x500)
-#define A_CM_IDLEST_CKGEN_V	IO_ADDRESS(OMAP24XX_PRCM_BASE+0x520)
-#define A_CM_CLKSEL1_PLL_V	IO_ADDRESS(OMAP24XX_PRCM_BASE+0x540)
-#define A_CM_CLKSEL2_PLL_V	IO_ADDRESS(OMAP24XX_PRCM_BASE+0x544)
-
 #define A_SDRC_DLLA_CTRL_V	IO_ADDRESS(OMAP24XX_SDRC_BASE+0x60)
 #define	A_SDRC_POWER_V		IO_ADDRESS(OMAP24XX_SDRC_BASE+0x70)
 #define A_SDRC_RFR_CTRL_V	IO_ADDRESS(OMAP24XX_SDRC_BASE+0xA4)
@@ -53,7 +49,7 @@
  */
 ENTRY(omap24xx_idle_loop_suspend)
 	stmfd	sp!, {r0, lr}		@ save registers on stack
-	mov	r0, #0			@ clear for mcr setup
+	mov	r0, #0x0		@ clear for mrc call
 	mcr	p15, 0, r0, c7, c0, 4	@ wait for interrupt
 	ldmfd	sp!, {r0, pc}		@ restore regs and return
 
@@ -67,9 +63,6 @@
  *
  * Input:
  * R0 :	DLL ctrl value pre-Sleep
- * R1 : Processor+Revision
- *	2420: 0x21 = 242xES1, 0x26 = 242xES2.2
- *	2430: 0x31 = 2430ES1, 0x32 = 2430ES2
  *
  * The if the DPLL is going to AutoIdle. It seems like the DPLL may be back on
  * when we get called, but the DLL probably isn't.  We will wait a bit more in
@@ -129,14 +122,8 @@
 	.word A_SDRC_POWER_V
 A_SDRC0:
 	.word A_SDRC0_V
-A_CM_CLKSEL2_PLL_S:
-	.word A_CM_CLKSEL2_PLL_V
-A_CM_CLKEN_PLL:
-	.word A_CM_CLKEN_PLL_V
 A_SDRC_DLLA_CTRL_S:
 	.word A_SDRC_DLLA_CTRL_V
-A_SDRC_MANUAL_S:
-	.word A_SDRC_MANUAL_V
 
 ENTRY(omap24xx_cpu_suspend_sz)
 	.word	. - omap24xx_cpu_suspend
include/asm-arm/arch-omap/pm.h +3 -63

87 lines not on this page · raw message

arch/arm/mach-omap2/pm-domain.c deleted +0 -299

299 lines not on this page · raw message