1/* 2 * OMAP2 Power Management Routines 3 * 4 * Copyright (C) 2005 Texas Instruments, Inc. 5 * Copyright (C) 2006-2008 Nokia Corporation 6 * 7 * Written by: 8 * Richard Woodruff <r-woodruff2@ti.com> 9 * Tony Lindgren 10 * Juha Yrjola 11 * Amit Kucheria <amit.kucheria@nokia.com> 12 * Igor Stoppa <igor.stoppa@nokia.com> 13 * 14 * Based on pm.c for omap1 15 * 16 * This program is free software; you can redistribute it and/or modify 17 * it under the terms of the GNU General Public License version 2 as 18 * published by the Free Software Foundation. 19 */ 20 21#include <linux/suspend.h> 22#include <linux/sched.h> 23#include <linux/proc_fs.h> 24#include <linux/interrupt.h> 25#include <linux/sysfs.h> 26#include <linux/module.h> 27#include <linux/delay.h> 28#include <linux/clk-provider.h> 29#include <linux/irq.h> 30#include <linux/time.h> 31#include <linux/gpio.h> 32#include <linux/platform_data/gpio-omap.h> 33 34#include <asm/fncpy.h> 35 36#include <asm/mach/time.h> 37#include <asm/mach/irq.h> 38#include <asm/mach-types.h> 39#include <asm/system_misc.h> 40 41#include <linux/omap-dma.h> 42 43#include "soc.h" 44#include "common.h" 45#include "clock.h" 46#include "prm2xxx.h" 47#include "prm-regbits-24xx.h" 48#include "cm2xxx.h" 49#include "cm-regbits-24xx.h" 50#include "sdrc.h" 51#include "sram.h" 52#include "pm.h" 53#include "control.h" 54#include "powerdomain.h" 55#include "clockdomain.h" 56 57static void (*omap2_sram_suspend)(u32 dllctrl, void __iomem *sdrc_dlla_ctrl, 58 void __iomem *sdrc_power); 59 60static struct powerdomain *mpu_pwrdm, *core_pwrdm; 61static struct clockdomain *dsp_clkdm, *mpu_clkdm, *wkup_clkdm, *gfx_clkdm; 62 63static struct clk *osc_ck, *emul_ck; 64 65static int omap2_enter_full_retention(void) 66{ 67 u32 l; 68 69 /* There is 1 reference hold for all children of the oscillator 70 * clock, the following will remove it. If no one else uses the 71 * oscillator itself it will be disabled if/when we enter retention 72 * mode. 73 */ 74 clk_disable(osc_ck); 75 76 /* Clear old wake-up events */ 77 /* REVISIT: These write to reserved bits? */ 78 omap_prm_clear_mod_irqs(CORE_MOD, PM_WKST1, ~0); 79 omap_prm_clear_mod_irqs(CORE_MOD, OMAP24XX_PM_WKST2, ~0); 80 omap_prm_clear_mod_irqs(WKUP_MOD, PM_WKST, ~0); 81 82 pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_RET); 83 pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET); 84 85 /* Workaround to kill USB */ 86 l = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0) | OMAP24XX_USBSTANDBYCTRL; 87 omap_ctrl_writel(l, OMAP2_CONTROL_DEVCONF0); 88 89 omap2_gpio_prepare_for_idle(0); 90 91 /* One last check for pending IRQs to avoid extra latency due 92 * to sleeping unnecessarily. */ 93 if (omap_irq_pending()) 94 goto no_sleep; 95 96 /* Jump to SRAM suspend code */ 97 omap2_sram_suspend(sdrc_read_reg(SDRC_DLLA_CTRL), 98 OMAP_SDRC_REGADDR(SDRC_DLLA_CTRL), 99 OMAP_SDRC_REGADDR(SDRC_POWER)); 100 101no_sleep: 102 omap2_gpio_resume_after_idle(); 103 104 clk_enable(osc_ck); 105 106 /* clear CORE wake-up events */ 107 omap_prm_clear_mod_irqs(CORE_MOD, PM_WKST1, ~0); 108 omap_prm_clear_mod_irqs(CORE_MOD, OMAP24XX_PM_WKST2, ~0); 109 110 /* wakeup domain events - bit 1: GPT1, bit5 GPIO */ 111 omap_prm_clear_mod_irqs(WKUP_MOD, PM_WKST, 0x4 | 0x1); 112 113 /* MPU domain wake events */ 114 omap_prm_clear_mod_irqs(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET, 0x1); 115 116 omap_prm_clear_mod_irqs(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET, 0x20); 117 118 pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON); 119 pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_ON); 120 121 return 0; 122} 123 124static int sti_console_enabled; 125 126static int omap2_allow_mpu_retention(void) 127{ 128 if (!omap2xxx_cm_mpu_retention_allowed()) 129 return 0; 130 if (sti_console_enabled) 131 return 0; 132 133 return 1; 134} 135 136static void omap2_enter_mpu_retention(void) 137{ 138 const int zero = 0; 139 140 /* The peripherals seem not to be able to wake up the MPU when 141 * it is in retention mode. */ 142 if (omap2_allow_mpu_retention()) { 143 /* REVISIT: These write to reserved bits? */ 144 omap_prm_clear_mod_irqs(CORE_MOD, PM_WKST1, ~0); 145 omap_prm_clear_mod_irqs(CORE_MOD, OMAP24XX_PM_WKST2, ~0); 146 omap_prm_clear_mod_irqs(WKUP_MOD, PM_WKST, ~0); 147 148 /* Try to enter MPU retention */ 149 pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET); 150 151 } else { 152 /* Block MPU retention */ 153 pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON); 154 } 155 156 /* WFI */ 157 asm("mcr p15, 0, %0, c7, c0, 4" : : "r" (zero) : "memory", "cc"); 158 159 pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON); 160} 161 162static int omap2_can_sleep(void) 163{ 164 if (omap2xxx_cm_fclks_active()) 165 return 0; 166 if (__clk_is_enabled(osc_ck)) 167 return 0; 168 if (omap_dma_running()) 169 return 0; 170 171 return 1; 172} 173 174static void omap2_pm_idle(void) 175{ 176 if (!omap2_can_sleep()) { 177 if (omap_irq_pending()) 178 return; 179 omap2_enter_mpu_retention(); 180 return; 181 } 182 183 if (omap_irq_pending()) 184 return; 185 186 omap2_enter_full_retention(); 187} 188 189static void __init prcm_setup_regs(void) 190{ 191 int i, num_mem_banks; 192 struct powerdomain *pwrdm; 193 194 /* 195 * Enable autoidle 196 * XXX This should be handled by hwmod code or PRCM init code 197 */ 198 omap2_prm_write_mod_reg(OMAP24XX_AUTOIDLE_MASK, OCP_MOD, 199 OMAP2_PRCM_SYSCONFIG_OFFSET); 200 201 /* 202 * Set CORE powerdomain memory banks to retain their contents 203 * during RETENTION 204 */ 205 num_mem_banks = pwrdm_get_mem_bank_count(core_pwrdm); 206 for (i = 0; i < num_mem_banks; i++) 207 pwrdm_set_mem_retst(core_pwrdm, i, PWRDM_POWER_RET); 208 209 pwrdm_set_logic_retst(core_pwrdm, PWRDM_POWER_RET); 210 211 pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET); 212 213 /* Force-power down DSP, GFX powerdomains */ 214 215 pwrdm = clkdm_get_pwrdm(dsp_clkdm); 216 pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF); 217 218 pwrdm = clkdm_get_pwrdm(gfx_clkdm); 219 pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF); 220 221 /* Enable hardware-supervised idle for all clkdms */ 222 clkdm_for_each(omap_pm_clkdms_setup, NULL); 223 clkdm_add_wkdep(mpu_clkdm, wkup_clkdm); 224 225 omap_common_suspend_init(omap2_enter_full_retention); 226 227 /* REVISIT: Configure number of 32 kHz clock cycles for sys_clk 228 * stabilisation */ 229 omap2_prm_write_mod_reg(15 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD, 230 OMAP2_PRCM_CLKSSETUP_OFFSET); 231 232 /* Configure automatic voltage transition */ 233 omap2_prm_write_mod_reg(2 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD, 234 OMAP2_PRCM_VOLTSETUP_OFFSET); 235 omap2_prm_write_mod_reg(OMAP24XX_AUTO_EXTVOLT_MASK | 236 (0x1 << OMAP24XX_SETOFF_LEVEL_SHIFT) | 237 OMAP24XX_MEMRETCTRL_MASK | 238 (0x1 << OMAP24XX_SETRET_LEVEL_SHIFT) | 239 (0x0 << OMAP24XX_VOLT_LEVEL_SHIFT), 240 OMAP24XX_GR_MOD, OMAP2_PRCM_VOLTCTRL_OFFSET); 241 242 /* Enable wake-up events */ 243 omap2_prm_write_mod_reg(OMAP24XX_EN_GPIOS_MASK | OMAP24XX_EN_GPT1_MASK, 244 WKUP_MOD, PM_WKEN); 245 246 /* Enable SYS_CLKEN control when all domains idle */ 247 omap2_prm_set_mod_reg_bits(OMAP_AUTOEXTCLKMODE_MASK, OMAP24XX_GR_MOD, 248 OMAP2_PRCM_CLKSRC_CTRL_OFFSET); 249} 250 251int __init omap2_pm_init(void) 252{ 253 u32 l; 254 255 printk(KERN_INFO "Power Management for OMAP2 initializing\n"); 256 l = omap2_prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_REVISION_OFFSET); 257 printk(KERN_INFO "PRCM revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f); 258 259 /* Look up important powerdomains */ 260 261 mpu_pwrdm = pwrdm_lookup("mpu_pwrdm"); 262 if (!mpu_pwrdm) 263 pr_err("PM: mpu_pwrdm not found\n"); 264 265 core_pwrdm = pwrdm_lookup("core_pwrdm"); 266 if (!core_pwrdm) 267 pr_err("PM: core_pwrdm not found\n"); 268 269 /* Look up important clockdomains */ 270 271 mpu_clkdm = clkdm_lookup("mpu_clkdm"); 272 if (!mpu_clkdm) 273 pr_err("PM: mpu_clkdm not found\n"); 274 275 wkup_clkdm = clkdm_lookup("wkup_clkdm"); 276 if (!wkup_clkdm) 277 pr_err("PM: wkup_clkdm not found\n"); 278 279 dsp_clkdm = clkdm_lookup("dsp_clkdm"); 280 if (!dsp_clkdm) 281 pr_err("PM: dsp_clkdm not found\n"); 282 283 gfx_clkdm = clkdm_lookup("gfx_clkdm"); 284 if (!gfx_clkdm) 285 pr_err("PM: gfx_clkdm not found\n"); 286 287 288 osc_ck = clk_get(NULL, "osc_ck"); 289 if (IS_ERR(osc_ck)) { 290 printk(KERN_ERR "could not get osc_ck\n"); 291 return -ENODEV; 292 } 293 294 if (cpu_is_omap242x()) { 295 emul_ck = clk_get(NULL, "emul_ck"); 296 if (IS_ERR(emul_ck)) { 297 printk(KERN_ERR "could not get emul_ck\n"); 298 clk_put(osc_ck); 299 return -ENODEV; 300 } 301 } 302 303 prcm_setup_regs(); 304 305 /* 306 * We copy the assembler sleep/wakeup routines to SRAM. 307 * These routines need to be in SRAM as that's the only 308 * memory the MPU can see when it wakes up after the entire 309 * chip enters idle. 310 */ 311 omap2_sram_suspend = omap_sram_push(omap24xx_cpu_suspend, 312 omap24xx_cpu_suspend_sz); 313 314 arm_pm_idle = omap2_pm_idle; 315 316 return 0; 317} 318