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