With this patch OMAP34xx enters and resumes from off-mode successfully
with suspend and dynamic idle. CPU idle is broken with this patch and should
be fixed separately.

Signed-off-by: Tero Kristo <[EMAIL PROTECTED]>
---
 arch/arm/mach-omap2/cpuidle34xx.c  |   15 ++---
 arch/arm/mach-omap2/cpuidle34xx.h  |    2 +
 arch/arm/mach-omap2/pm34xx.c       |  110 +++++++++++++++++++-----------------
 arch/arm/mach-omap2/serial.c       |   97 +++++++++++++++++--------------
 arch/arm/plat-omap/dma.c           |   26 +++++++++
 include/asm-arm/arch-omap/common.h |    8 ++-
 6 files changed, 150 insertions(+), 108 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c 
b/arch/arm/mach-omap2/cpuidle34xx.c
index 53fd376..1b960ea 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -39,8 +39,6 @@
 #include "pm.h"
 #include "clock34xx.h"
 
-#ifdef CONFIG_CPU_IDLE
-
 struct omap3_processor_cx omap3_power_states[OMAP3_MAX_STATES];
 struct omap3_processor_cx current_cx_state;
 static int padconf_saved;
@@ -404,10 +402,8 @@ void omap3_save_core_ctx(void)
        omap_save_gpmc_ctx();
        /* Save the system control module context, padconf already save above*/
        omap_save_control_ctx();
-       omap_save_uart_ctx(0);
-       omap_serial_enable_clocks(0, 0);
-       omap_save_uart_ctx(1);
-       omap_serial_enable_clocks(0, 1);
+
+       omap_dma_global_context_save();
 }
 
 void omap3_restore_core_ctx(void)
@@ -418,13 +414,12 @@ void omap3_restore_core_ctx(void)
        omap_restore_gpmc_ctx();
        /* Restore the interrupt controller context */
        omap_restore_intc_ctx();
-       omap_serial_enable_clocks(1, 0);
-       omap_restore_uart_ctx(0);
-       omap_serial_enable_clocks(1, 1);
-       omap_restore_uart_ctx(1);
        padconf_saved = 0;
+
+       omap_dma_global_context_restore();
 }
 
+#ifdef CONFIG_CPU_IDLE
 /* omap3_enter_idle - Programs OMAP3 to enter the specified state.
  * returns the total time during which the system was idle.
  */
diff --git a/arch/arm/mach-omap2/cpuidle34xx.h 
b/arch/arm/mach-omap2/cpuidle34xx.h
index bcdf978..0b3396d 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.h
+++ b/arch/arm/mach-omap2/cpuidle34xx.h
@@ -64,6 +64,8 @@ extern void omap3_restore_per_ctx();
 extern void omap_save_uart_ctx(int);
 extern void omap_restore_uart_ctx(int);
 extern void omap3_restore_sram_ctx();
+void omap_dma_global_context_restore(void);
+void omap_dma_global_context_save(void);
 extern int omap3_can_sleep();
 
 struct omap3_processor_cx {
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index dc7bb90..ff9890a 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -60,7 +60,17 @@ u32 restore_pointer_address;
 
 static LIST_HEAD(pwrst_list);
 
-void (*_omap_sram_idle)(u32 *addr, int save_state, int disable_clocks);
+void omap3_save_per_ctx(void);
+void omap3_restore_per_ctx(void);
+void omap3_restore_sram_ctx(void);
+void omap3_save_core_ctx(void);
+void omap3_restore_core_ctx(void);
+void omap3_save_prcm_ctx(void);
+void omap3_restore_prcm_ctx(void);
+void omap_dma_global_context_restore(void);
+void omap_dma_global_context_save(void);
+
+void (*_omap_sram_idle)(u32 *addr, int save_state);
 
 static void (*saved_idle)(void);
 
@@ -245,10 +255,43 @@ void omap_sram_idle(void)
                return;
        }
 
-       _omap_sram_idle(context_mem, save_state, clocks_off_while_idle);
-       /* Restore table entry modified during MMU restoration */
+       omap3_save_core_ctx();
+       omap3_save_prcm_ctx();
+
+       omap3_save_per_ctx();
+       omap2_gpio_prepare_for_retention();
+
+       /* XXX This is for gpio fclk hack. Will be removed as gpio driver
+        * handles fcks correctly */
+       per_gpio_clk_disable();
+
+       omap_save_uart_ctx();
+       omap_serial_enable_clocks(0);
+
+       *(scratchpad_restore_addr) = restore_pointer_address;
+
+       _omap_sram_idle(context_mem, save_state);
+
+       *(scratchpad_restore_addr) = 0x0;
+
        if (pwrdm_read_prev_pwrst(mpu_pwrdm) == 0x0)
                restore_table_entry();
+
+       omap3_restore_prcm_ctx();
+       omap3_restore_sram_ctx();
+       omap3_restore_core_ctx();
+
+       omap_serial_enable_clocks(1); /* Causes crash with CORE off */
+
+       omap_restore_uart_ctx();
+
+       /* XXX This is for gpio fclk hack. Will be removed as gpio driver
+        * handles fcks correctly */
+
+       per_gpio_clk_enable();
+       omap3_restore_per_ctx();
+
+       omap2_gpio_resume_after_retention();
 }
 
 static int omap3_fclks_active(void)
@@ -357,29 +400,8 @@ static void omap3_pm_idle(void)
        if (omap_irq_pending())
                goto out;
 
-       omap2_gpio_prepare_for_retention();
-
-       if (clocks_off_while_idle) {
-               omap_serial_enable_clocks(0, 0);
-               omap_serial_enable_clocks(0, 1);
-               omap_serial_enable_clocks(0, 2);
-               /* XXX This is for gpio fclk hack. Will be removed as
-                * gpio driver * handles fcks correctly */
-               per_gpio_clk_disable();
-       }
-
        omap_sram_idle();
 
-       if (clocks_off_while_idle) {
-               omap_serial_enable_clocks(1, 0);
-               omap_serial_enable_clocks(1, 1);
-               omap_serial_enable_clocks(1, 2);
-               /* XXX This is for gpio fclk hack. Will be removed as
-                * gpio driver * handles fcks correctly */
-               per_gpio_clk_enable();
-       }
-
-       omap2_gpio_resume_after_retention();
 out:
        local_fiq_enable();
        local_irq_enable();
@@ -412,29 +434,14 @@ static int omap3_pm_suspend(void)
                        goto restore;
        }
 
-       omap2_gpio_prepare_for_retention();
-
-       if (clocks_off_while_idle) {
-               omap_serial_enable_clocks(0, 0);
-               omap_serial_enable_clocks(0, 1);
-               omap_serial_enable_clocks(0, 2);
-               /* XXX This is for gpio fclk hack. Will be removed as
-                * gpio driver * handles fcks correctly */
-               per_gpio_clk_disable();
-       }
+       local_irq_disable();
+       local_fiq_disable();
 
        omap_sram_idle();
 
-       if (clocks_off_while_idle) {
-               omap_serial_enable_clocks(1, 0);
-               omap_serial_enable_clocks(1, 1);
-               omap_serial_enable_clocks(1, 2);
-               /* XXX This is for gpio fclk hack. Will be removed as
-                * gpio driver * handles fcks correctly */
-               per_gpio_clk_enable();
-       }
+       local_fiq_enable();
+       local_irq_enable();
 
-       omap2_gpio_resume_after_retention();
 restore:
        /* Restore next_pwrsts */
        list_for_each_entry(pwrst, &pwrst_list, node) {
@@ -657,10 +664,9 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm)
        if (!pwrst)
                return -ENOMEM;
        pwrst->pwrdm = pwrdm;
-       if (!strcmp(pwrst->pwrdm->name, "core_pwrdm"))
-               pwrst->next_state = PWRDM_POWER_RET;
-       else
-               pwrst->next_state = PWRDM_POWER_OFF;
+
+       pwrst->next_state = PWRDM_POWER_OFF;
+
        list_add(&pwrst->node, &pwrst_list);
 
        if (pwrdm_has_hdwr_sar(pwrdm))
@@ -678,6 +684,7 @@ void omap_push_sram_idle()
 int __init omap3_pm_init(void)
 {
        struct power_state *pwrst;
+       struct powerdomain *neon_pwrdm;
        char clk_name[11];
        int ret, i;
 
@@ -687,7 +694,6 @@ int __init omap3_pm_init(void)
         * supervised mode for powerdomains */
        prcm_setup_regs();
        save_scratchpad_contents();
-
        ret = request_irq(INT_34XX_PRCM_MPU_IRQ,
                          (irq_handler_t)prcm_interrupt_handler,
                          IRQF_DISABLED, "prcm", NULL);
@@ -704,8 +710,10 @@ int __init omap3_pm_init(void)
        }
 
        mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
-       if (mpu_pwrdm == NULL) {
-               printk(KERN_ERR "Failed to get mpu_pwrdm\n");
+       neon_pwrdm = pwrdm_lookup("neon_pwrdm");
+
+       if (mpu_pwrdm == NULL || neon_pwrdm == NULL) {
+               printk(KERN_ERR "Failed to get mpu_pwrdm or neon_pwrdm\n");
                goto err2;
        }
 
@@ -723,6 +731,7 @@ int __init omap3_pm_init(void)
                gpio_fcks[i-1] = clk_get(NULL, clk_name);
        }
 
+       pwrdm_add_wkdep(neon_pwrdm, mpu_pwrdm);
 err1:
        return ret;
 err2:
@@ -851,4 +860,3 @@ void save_scratchpad_contents(void)
        *(scratchpad_address++) = 0x0;
        *(scratchpad_address++) = (u32) sdram_context_address;
 }
-
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 9a9ea10..c222e77 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -157,15 +157,18 @@ static void omap_serial_kick(void)
                NSEC_PER_SEC);
 }
 
-void omap_serial_enable_clocks(int enable, int unum)
+void omap_serial_enable_clocks(int enable)
 {
-       if (uart_ick[unum] && uart_fck[unum]) {
-               if (enable) {
-                       clk_enable(uart_ick[unum]);
-                       clk_enable(uart_fck[unum]);
-               } else {
-                       clk_disable(uart_ick[unum]);
-                       clk_disable(uart_fck[unum]);
+       int i;
+       for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {
+               if (uart_ick[i] && uart_fck[i]) {
+                       if (enable) {
+                               clk_enable(uart_ick[i]);
+                               clk_enable(uart_fck[i]);
+                       } else {
+                               clk_disable(uart_ick[i]);
+                               clk_disable(uart_fck[i]);
+                       }
                }
        }
 }
@@ -300,55 +303,61 @@ void __init omap_serial_init(void)
        omap_serial_kick();
 }
 
-void omap_save_uart_ctx(int unum)
+void omap_save_uart_ctx(void)
 {
+       int i;
        u16 lcr = 0;
 
-       struct plat_serial8250_port *p = serial_platform_data + unum;
+       for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {
+               struct plat_serial8250_port *p = serial_platform_data + i;
 
-       if (uart_ick[unum] == NULL)
-               return;
+               if (!uart_ick[i])
+                       continue;
 
-       lcr = serial_read_reg(p, UART_LCR);
-       serial_write_reg(p, UART_LCR, 0xBF);
-       uart_ctx[unum].dll = serial_read_reg(p, UART_DLL);
-       uart_ctx[unum].dlh = serial_read_reg(p, UART_DLM);
-       serial_write_reg(p, UART_LCR, lcr);
-       uart_ctx[unum].ier = serial_read_reg(p, UART_IER);
-       uart_ctx[unum].sysc = serial_read_reg(p, UART_OMAP_SYSC);
-       uart_ctx[unum].scr = serial_read_reg(p, UART_OMAP_SCR);
-       uart_ctx[unum].wer = serial_read_reg(p, UART_OMAP_WER);
+               lcr = serial_read_reg(p, UART_LCR);
+               serial_write_reg(p, UART_LCR, 0xBF);
+               uart_ctx[i].dll = serial_read_reg(p, UART_DLL);
+               uart_ctx[i].dlh = serial_read_reg(p, UART_DLM);
+               serial_write_reg(p, UART_LCR, lcr);
+               uart_ctx[i].ier = serial_read_reg(p, UART_IER);
+               uart_ctx[i].sysc = serial_read_reg(p, UART_OMAP_SYSC);
+               uart_ctx[i].scr = serial_read_reg(p, UART_OMAP_SCR);
+               uart_ctx[i].wer = serial_read_reg(p, UART_OMAP_WER);
+       }
 }
 EXPORT_SYMBOL(omap_save_uart_ctx);
 
-void omap_restore_uart_ctx(int unum)
+void omap_restore_uart_ctx(void)
 {
+       int i;
        u16 efr = 0;
 
-       struct plat_serial8250_port *p = serial_platform_data + unum;
+       for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {
+               struct plat_serial8250_port *p = serial_platform_data + i;
 
-       if (uart_ick[unum] == NULL)
-               return;
+               if (!uart_ick[i])
+                       continue;
 
-       serial_write_reg(p, UART_OMAP_MDR1, 0x7);
-       serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
-       efr = serial_read_reg(p, UART_EFR);
-       serial_write_reg(p, UART_EFR, UART_EFR_ECB);
-       serial_write_reg(p, UART_LCR, 0x0); /* Operational mode */
-       serial_write_reg(p, UART_IER, 0x0);
-       serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
-       serial_write_reg(p, UART_DLL, uart_ctx[unum].dll);
-       serial_write_reg(p, UART_DLM, uart_ctx[unum].dlh);
-       serial_write_reg(p, UART_LCR, 0x0); /* Operational mode */
-       serial_write_reg(p, UART_IER, uart_ctx[unum].ier);
-       serial_write_reg(p, UART_FCR, 0xA1);
-       serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
-       serial_write_reg(p, UART_EFR, efr);
-       serial_write_reg(p, UART_LCR, UART_LCR_WLEN8);
-       serial_write_reg(p, UART_OMAP_SCR, uart_ctx[unum].scr);
-       serial_write_reg(p, UART_OMAP_WER, uart_ctx[unum].wer);
-       serial_write_reg(p, UART_OMAP_SYSC, uart_ctx[unum].sysc);
-       serial_write_reg(p, UART_OMAP_MDR1, 0x00); /* UART 16x mode */
+               serial_write_reg(p, UART_OMAP_MDR1, 0x7);
+               serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
+               efr = serial_read_reg(p, UART_EFR);
+               serial_write_reg(p, UART_EFR, UART_EFR_ECB);
+               serial_write_reg(p, UART_LCR, 0x0); /* Operational mode */
+               serial_write_reg(p, UART_IER, 0x0);
+               serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
+               serial_write_reg(p, UART_DLL, uart_ctx[i].dll);
+               serial_write_reg(p, UART_DLM, uart_ctx[i].dlh);
+               serial_write_reg(p, UART_LCR, 0x0); /* Operational mode */
+               serial_write_reg(p, UART_IER, uart_ctx[i].ier);
+               serial_write_reg(p, UART_FCR, 0xA1);
+               serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
+               serial_write_reg(p, UART_EFR, efr);
+               serial_write_reg(p, UART_LCR, UART_LCR_WLEN8);
+               serial_write_reg(p, UART_OMAP_SCR, uart_ctx[i].scr);
+               serial_write_reg(p, UART_OMAP_WER, uart_ctx[i].wer);
+               serial_write_reg(p, UART_OMAP_SYSC, uart_ctx[i].sysc);
+               serial_write_reg(p, UART_OMAP_MDR1, 0x00); /* UART 16x mode */
+       }
 }
 EXPORT_SYMBOL(omap_restore_uart_ctx);
 
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index fac8e99..a0da9b6 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -51,6 +51,12 @@ enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED };
 
 static int enable_1510_mode;
 
+static struct omap_dma_global_context_registers {
+       u32 dma_irqenable_l0;
+       u32 dma_ocp_sysconfig;
+       u32 dma_gcr;
+} omap_dma_global_context;
+
 struct omap_dma_lch {
        int next_lch;
        int dev_id;
@@ -2290,6 +2296,26 @@ void omap_stop_lcd_dma(void)
 }
 EXPORT_SYMBOL(omap_stop_lcd_dma);
 
+void omap_dma_global_context_save(void)
+{
+       omap_dma_global_context.dma_irqenable_l0 =
+                       dma_read(IRQENABLE_L0);
+       omap_dma_global_context.dma_ocp_sysconfig =
+                       dma_read(OCP_SYSCONFIG);
+       omap_dma_global_context.dma_gcr = dma_read(GCR);
+}
+EXPORT_SYMBOL(omap_dma_global_context_save);
+
+void omap_dma_global_context_restore(void)
+{
+       dma_write(omap_dma_global_context.dma_gcr, GCR);
+       dma_write(omap_dma_global_context.dma_ocp_sysconfig,
+                       OCP_SYSCONFIG);
+       dma_write(omap_dma_global_context.dma_irqenable_l0,
+                       IRQENABLE_L0);
+}
+EXPORT_SYMBOL(omap_dma_global_context_restore);
+
 
/*----------------------------------------------------------------------------*/
 
 static int __init omap_init_dma(void)
diff --git a/include/asm-arm/arch-omap/common.h 
b/include/asm-arm/arch-omap/common.h
index 0f8d3a8..c8b6a83 100644
--- a/include/asm-arm/arch-omap/common.h
+++ b/include/asm-arm/arch-omap/common.h
@@ -34,12 +34,14 @@ struct sys_timer;
 extern void omap_map_common_io(void);
 extern struct sys_timer omap_timer;
 extern void omap_serial_init(void);
-extern void omap_serial_enable_clocks(int enable, int unum);
+extern void omap_serial_enable_clocks(int enable);
 extern int omap_serial_can_sleep(void);
-extern void omap_gpio_save(void);
-extern void omap_gpio_restore(void);
 extern void omap_serial_fclk_mask(u32 *f1, u32 *f2);
 void omap_serial_check_wakeup(void);
+extern void omap_save_uart_ctx(void);
+extern void omap_restore_uart_ctx(void);
+extern void omap_gpio_save(void);
+extern void omap_gpio_restore(void);
 #ifdef CONFIG_I2C_OMAP
 extern int omap_register_i2c_bus(int bus_id, u32 clkrate,
                                 struct i2c_board_info const *info,
-- 
1.5.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to