1 /* 2 * pm.c - Common OMAP2+ power management-related code 3 * 4 * Copyright (C) 2010 Texas Instruments, Inc. 5 * Copyright (C) 2010 Nokia Corporation 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 */ 11 12 #include <linux/kernel.h> 13 #include <linux/init.h> 14 #include <linux/io.h> 15 #include <linux/err.h> 16 #include <linux/opp.h> 17 #include <linux/export.h> 18 #include <linux/suspend.h> 19 20 #include <asm/system_misc.h> 21 22 #include <plat/omap-pm.h> 23 #include <plat/omap_device.h> 24 #include "common.h" 25 26 #include "prcm-common.h" 27 #include "voltage.h" 28 #include "powerdomain.h" 29 #include "clockdomain.h" 30 #include "pm.h" 31 #include "twl-common.h" 32 33 static struct omap_device_pm_latency *pm_lats; 34 35 /* 36 * omap_pm_suspend: points to a function that does the SoC-specific 37 * suspend work 38 */ 39 int (*omap_pm_suspend)(void); 40 41 static int __init _init_omap_device(char *name) 42 { 43 struct omap_hwmod *oh; 44 struct platform_device *pdev; 45 46 oh = omap_hwmod_lookup(name); 47 if (WARN(!oh, "%s: could not find omap_hwmod for %s\n", 48 __func__, name)) 49 return -ENODEV; 50 51 pdev = omap_device_build(oh->name, 0, oh, NULL, 0, pm_lats, 0, false); 52 if (WARN(IS_ERR(pdev), "%s: could not build omap_device for %s\n", 53 __func__, name)) 54 return -ENODEV; 55 56 return 0; 57 } 58 59 /* 60 * Build omap_devices for processors and bus. 61 */ 62 static void __init omap2_init_processor_devices(void) 63 { 64 _init_omap_device("mpu"); 65 if (omap3_has_iva()) 66 _init_omap_device("iva"); 67 68 if (cpu_is_omap44xx()) { 69 _init_omap_device("l3_main_1"); 70 _init_omap_device("dsp"); 71 _init_omap_device("iva"); 72 } else { 73 _init_omap_device("l3_main"); 74 } 75 } 76 77 /* Types of sleep_switch used in omap_set_pwrdm_state */ 78 #define FORCEWAKEUP_SWITCH 0 79 #define LOWPOWERSTATE_SWITCH 1 80 81 int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused) 82 { 83 if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO) 84 clkdm_allow_idle(clkdm); 85 else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP && 86 atomic_read(&clkdm->usecount) == 0) 87 clkdm_sleep(clkdm); 88 return 0; 89 } 90 91 /* 92 * This sets pwrdm state (other than mpu & core. Currently only ON & 93 * RET are supported. 94 */ 95 int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst) 96 { 97 u8 curr_pwrst, next_pwrst; 98 int sleep_switch = -1, ret = 0, hwsup = 0; 99 100 if (!pwrdm || IS_ERR(pwrdm)) 101 return -EINVAL; 102 103 while (!(pwrdm->pwrsts & (1 << pwrst))) { 104 if (pwrst == PWRDM_POWER_OFF) 105 return ret; 106 pwrst--; 107 } 108 109 next_pwrst = pwrdm_read_next_pwrst(pwrdm); 110 if (next_pwrst == pwrst) 111 return ret; 112 113 curr_pwrst = pwrdm_read_pwrst(pwrdm); 114 if (curr_pwrst < PWRDM_POWER_ON) { 115 if ((curr_pwrst > pwrst) && 116 (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) { 117 sleep_switch = LOWPOWERSTATE_SWITCH; 118 } else { 119 hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]); 120 clkdm_wakeup(pwrdm->pwrdm_clkdms[0]); 121 sleep_switch = FORCEWAKEUP_SWITCH; 122 } 123 } 124 125 ret = pwrdm_set_next_pwrst(pwrdm, pwrst); 126 if (ret) 127 pr_err("%s: unable to set power state of powerdomain: %s\n", 128 __func__, pwrdm->name); 129 130 switch (sleep_switch) { 131 case FORCEWAKEUP_SWITCH: 132 if (hwsup) 133 clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]); 134 else 135 clkdm_sleep(pwrdm->pwrdm_clkdms[0]); 136 break; 137 case LOWPOWERSTATE_SWITCH: 138 pwrdm_set_lowpwrstchange(pwrdm); 139 pwrdm_wait_transition(pwrdm); 140 pwrdm_state_switch(pwrdm); 141 break; 142 } 143 144 return ret; 145 } 146 147 148 149 /* 150 * This API is to be called during init to set the various voltage 151 * domains to the voltage as per the opp table. Typically we boot up 152 * at the nominal voltage. So this function finds out the rate of 153 * the clock associated with the voltage domain, finds out the correct 154 * opp entry and sets the voltage domain to the voltage specified 155 * in the opp entry 156 */ 157 static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name, 158 const char *oh_name) 159 { 160 struct voltagedomain *voltdm; 161 struct clk *clk; 162 struct opp *opp; 163 unsigned long freq, bootup_volt; 164 struct device *dev; 165 166 if (!vdd_name || !clk_name || !oh_name) { 167 pr_err("%s: invalid parameters\n", __func__); 168 goto exit; 169 } 170 171 dev = omap_device_get_by_hwmod_name(oh_name); 172 if (IS_ERR(dev)) { 173 pr_err("%s: Unable to get dev pointer for hwmod %s\n", 174 __func__, oh_name); 175 goto exit; 176 } 177 178 voltdm = voltdm_lookup(vdd_name); 179 if (IS_ERR(voltdm)) { 180 pr_err("%s: unable to get vdd pointer for vdd_%s\n", 181 __func__, vdd_name); 182 goto exit; 183 } 184 185 clk = clk_get(NULL, clk_name); 186 if (IS_ERR(clk)) { 187 pr_err("%s: unable to get clk %s\n", __func__, clk_name); 188 goto exit; 189 } 190 191 freq = clk->rate; 192 clk_put(clk); 193 194 rcu_read_lock(); 195 opp = opp_find_freq_ceil(dev, &freq); 196 if (IS_ERR(opp)) { 197 rcu_read_unlock(); 198 pr_err("%s: unable to find boot up OPP for vdd_%s\n", 199 __func__, vdd_name); 200 goto exit; 201 } 202 203 bootup_volt = opp_get_voltage(opp); 204 rcu_read_unlock(); 205 if (!bootup_volt) { 206 pr_err("%s: unable to find voltage corresponding " 207 "to the bootup OPP for vdd_%s\n", __func__, vdd_name); 208 goto exit; 209 } 210 211 voltdm_scale(voltdm, bootup_volt); 212 return 0; 213 214 exit: 215 pr_err("%s: unable to set vdd_%s\n", __func__, vdd_name); 216 return -EINVAL; 217 } 218 219 #ifdef CONFIG_SUSPEND 220 static int omap_pm_enter(suspend_state_t suspend_state) 221 { 222 int ret = 0; 223 224 if (!omap_pm_suspend) 225 return -ENOENT; /* XXX doublecheck */ 226 227 switch (suspend_state) { 228 case PM_SUSPEND_STANDBY: 229 case PM_SUSPEND_MEM: 230 ret = omap_pm_suspend(); 231 break; 232 default: 233 ret = -EINVAL; 234 } 235 236 return ret; 237 } 238 239 static int omap_pm_begin(suspend_state_t state) 240 { 241 disable_hlt(); 242 if (cpu_is_omap34xx()) 243 omap_prcm_irq_prepare(); 244 return 0; 245 } 246 247 static void omap_pm_end(void) 248 { 249 enable_hlt(); 250 return; 251 } 252 253 static void omap_pm_finish(void) 254 { 255 if (cpu_is_omap34xx()) 256 omap_prcm_irq_complete(); 257 } 258 259 static const struct platform_suspend_ops omap_pm_ops = { 260 .begin = omap_pm_begin, 261 .end = omap_pm_end, 262 .enter = omap_pm_enter, 263 .finish = omap_pm_finish, 264 .valid = suspend_valid_only_mem, 265 }; 266 267 #endif /* CONFIG_SUSPEND */ 268 269 static void __init omap3_init_voltages(void) 270 { 271 if (!cpu_is_omap34xx()) 272 return; 273 274 omap2_set_init_voltage("mpu_iva", "dpll1_ck", "mpu"); 275 omap2_set_init_voltage("core", "l3_ick", "l3_main"); 276 } 277 278 static void __init omap4_init_voltages(void) 279 { 280 if (!cpu_is_omap44xx()) 281 return; 282 283 omap2_set_init_voltage("mpu", "dpll_mpu_ck", "mpu"); 284 omap2_set_init_voltage("core", "l3_div_ck", "l3_main_1"); 285 omap2_set_init_voltage("iva", "dpll_iva_m5x2_ck", "iva"); 286 } 287 288 static int __init omap2_common_pm_init(void) 289 { 290 if (!of_have_populated_dt()) 291 omap2_init_processor_devices(); 292 omap_pm_if_init(); 293 294 return 0; 295 } 296 postcore_initcall(omap2_common_pm_init); 297 298 int __init omap2_common_pm_late_init(void) 299 { 300 /* 301 * In the case of DT, the PMIC and SR initialization will be done using 302 * a completely different mechanism. 303 * Disable this part if a DT blob is available. 304 */ 305 if (of_have_populated_dt()) 306 return 0; 307 308 /* Init the voltage layer */ 309 omap_pmic_late_init(); 310 omap_voltage_late_init(); 311 312 /* Initialize the voltages */ 313 omap3_init_voltages(); 314 omap4_init_voltages(); 315 316 /* Smartreflex device init */ 317 omap_devinit_smartreflex(); 318 319 #ifdef CONFIG_SUSPEND 320 suspend_set_ops(&omap_pm_ops); 321 #endif 322 323 return 0; 324 } 325