#include <linux/clk.h>
#include <linux/io.h>
#include <linux/irq.h>
+#include <linux/time.h>
#include <asm/mach/time.h>
#include <asm/mach/irq.h>
#include <asm/mach-types.h>
-#include <asm/arch/irqs.h>
-#include <asm/arch/clock.h>
-#include <asm/arch/sram.h>
-#include <asm/arch/control.h>
-#include <asm/arch/gpio.h>
-#include <asm/arch/pm.h>
-#include <asm/arch/mux.h>
-#include <asm/arch/dma.h>
-#include <asm/arch/board.h>
+#include <mach/irqs.h>
+#include <mach/clock.h>
+#include <mach/sram.h>
+#include <mach/control.h>
+#include <mach/gpio.h>
+#include <mach/pm.h>
+#include <mach/mux.h>
+#include <mach/dma.h>
+#include <mach/board.h>
#include "prm.h"
#include "prm-regbits-24xx.h"
#include "sdrc.h"
#include "pm.h"
-#include <asm/arch/powerdomain.h>
-#include <asm/arch/clockdomain.h>
+#include <mach/powerdomain.h>
+#include <mach/clockdomain.h>
static void (*omap2_sram_idle)(void);
-static void (*omap2_sram_suspend)(void __iomem *dllctrl);
+static void (*omap2_sram_suspend)(u32 dllctrl, void __iomem *sdrc_dlla_ctrl,
+ void __iomem *sdrc_power);
static void (*saved_idle)(void);
static struct powerdomain *mpu_pwrdm;
f1 = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
f2 = cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);
- serial_console_fclk_mask(&f1, &f2);
+
+ /* Ignore UART clocks. These are handled by UART core (serial.c) */
+ f1 &= ~(OMAP24XX_EN_UART1 | OMAP24XX_EN_UART2);
+ f2 &= ~OMAP24XX_EN_UART3;
+
if (f1 | f2)
return 1;
return 0;
static void omap2_enter_full_retention(void)
{
- u32 l, sleep_time = 0;
+ u32 l;
+ struct timespec ts_preidle, ts_postidle, ts_idle;
/* There is 1 reference hold for all children of the oscillator
* clock, the following will remove it. If no one else uses the
if (omap2_pm_debug) {
omap2_pm_dump(0, 0, 0);
- sleep_time = omap2_read_32k_sync_counter();
+ getnstimeofday(&ts_preidle);
}
/* One last check for pending IRQs to avoid extra latency due
if (omap_irq_pending())
goto no_sleep;
- serial_console_sleep(1);
+ omap_uart_prepare_idle(0);
+ omap_uart_prepare_idle(1);
+ omap_uart_prepare_idle(2);
+
/* Jump to SRAM suspend code */
- omap2_sram_suspend(OMAP_SDRC_REGADDR(SDRC_DLLA_CTRL));
+ omap2_sram_suspend(sdrc_read_reg(SDRC_DLLA_CTRL),
+ OMAP_SDRC_REGADDR(SDRC_DLLA_CTRL),
+ OMAP_SDRC_REGADDR(SDRC_POWER));
no_sleep:
- serial_console_sleep(0);
+ omap_uart_resume_idle(2);
+ omap_uart_resume_idle(1);
+ omap_uart_resume_idle(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);
+ getnstimeofday(&ts_postidle);
+ ts_idle = timespec_sub(ts_postidle, ts_preidle);
+ tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
+ omap2_pm_dump(0, 1, tmp);
}
omap2_gpio_resume_after_retention();
prm_clear_mod_reg_bits(0x4 | 0x1, WKUP_MOD, PM_WKST);
/* MPU domain wake events */
- l = __raw_readl(OMAP24XX_PRCM_IRQSTATUS_MPU);
+ l = prm_read_mod_reg(OCP_MOD, OMAP2_PRM_IRQSTATUS_MPU_OFFSET);
if (l & 0x01)
- __raw_writel(0x01, OMAP24XX_PRCM_IRQSTATUS_MPU);
+ prm_write_mod_reg(0x01, OCP_MOD,
+ OMAP2_PRM_IRQSTATUS_MPU_OFFSET);
if (l & 0x20)
- __raw_writel(0x20, OMAP24XX_PRCM_IRQSTATUS_MPU);
+ prm_write_mod_reg(0x20, OCP_MOD,
+ OMAP2_PRM_IRQSTATUS_MPU_OFFSET);
/* Mask future PRCM-to-MPU interrupts */
- __raw_writel(0x0, OMAP24XX_PRCM_IRQSTATUS_MPU);
+ prm_write_mod_reg(0x0, OCP_MOD, OMAP2_PRM_IRQSTATUS_MPU_OFFSET);
}
static int omap2_i2c_active(void)
static void omap2_enter_mpu_retention(void)
{
- u32 sleep_time = 0;
int only_idle = 0;
+ struct timespec ts_preidle, ts_postidle, ts_idle;
/* Putting MPU into the WFI state while a transfer is active
* seems to cause the I2C block to timeout. Why? Good question. */
if (omap2_pm_debug) {
omap2_pm_dump(only_idle ? 2 : 1, 0, 0);
- sleep_time = omap2_read_32k_sync_counter();
+ getnstimeofday(&ts_preidle);
}
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);
+ getnstimeofday(&ts_postidle);
+ ts_idle = timespec_sub(ts_postidle, ts_preidle);
+ tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
+ omap2_pm_dump(only_idle ? 2 : 1, 1, tmp);
}
}
return 0;
if (atomic_read(&sleep_block) > 0)
return 0;
- if (clk_get_usecount(osc_ck) > 1)
+ if (osc_ck->usecount > 1)
return 0;
if (omap_dma_running())
return 0;
mir1 = omap_readl(0x480fe0a4);
omap_writel(1 << 5, 0x480fe0ac);
+ omap_uart_prepare_suspend();
omap2_enter_full_retention();
omap_writel(mir1, 0x480fe0a4);
struct powerdomain *pwrdm;
/* Enable autoidle */
- __raw_writel(OMAP24XX_AUTOIDLE, OMAP24XX_PRCM_SYSCONFIG);
+ prm_write_mod_reg(OMAP24XX_AUTOIDLE, OCP_MOD,
+ OMAP24XX_PRM_SYSCONFIG_OFFSET);
/* Set all domain wakeup dependencies */
prm_write_mod_reg(OMAP_EN_WKUP_MASK, MPU_MOD, PM_WKDEP);
/* REVISIT: Configure number of 32 kHz clock cycles for sys_clk
* stabilisation */
- __raw_writel(15 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_PRCM_CLKSSETUP);
+ prm_write_mod_reg(15 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD,
+ OMAP24XX_PRCM_CLKSSETUP_OFFSET);
/* Configure automatic voltage transition */
- __raw_writel(2 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_PRCM_VOLTSETUP);
+ prm_write_mod_reg(2 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD,
+ OMAP24XX_PRCM_VOLTSETUP_OFFSET);
prm_write_mod_reg(OMAP24XX_AUTO_EXTVOLT |
(0x1 << OMAP24XX_SETOFF_LEVEL_SHIFT) |
OMAP24XX_MEMRETCTRL |
u32 l;
printk(KERN_INFO "Power Management for OMAP2 initializing\n");
- l = __raw_readl(OMAP24XX_PRCM_REVISION);
+ l = prm_read_mod_reg(OCP_MOD, OMAP24XX_PRM_REVISION_OFFSET);
printk(KERN_INFO "PRCM revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
/* Look up important powerdomains, clockdomains */
prcm_setup_regs();
- pm_init_serial_console();
-
/* Hack to prevent MPU retention when STI console is enabled. */
{
const struct omap_sti_console_config *sti;
* These routines need to be in SRAM as that's the only
* memory the MPU can see when it wakes up.
*/
- if (cpu_is_omap242x()) {
- omap2_sram_idle = omap_sram_push(omap242x_idle_loop_suspend,
- omap242x_idle_loop_suspend_sz);
-
- omap2_sram_suspend = omap_sram_push(omap242x_cpu_suspend,
- omap242x_cpu_suspend_sz);
- } else {
- omap2_sram_idle = omap_sram_push(omap243x_idle_loop_suspend,
- omap243x_idle_loop_suspend_sz);
+ if (cpu_is_omap24xx()) {
+ omap2_sram_idle = omap_sram_push(omap24xx_idle_loop_suspend,
+ omap24xx_idle_loop_suspend_sz);
- omap2_sram_suspend = omap_sram_push(omap243x_cpu_suspend,
- omap243x_cpu_suspend_sz);
+ omap2_sram_suspend = omap_sram_push(omap24xx_cpu_suspend,
+ omap24xx_cpu_suspend_sz);
}
suspend_set_ops(&omap_pm_ops);