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 19 #include <plat/omap-pm.h> 20 #include <plat/omap_device.h> 21 #include "common.h" 22 23 #include "voltage.h" 24 #include "powerdomain.h" 25 #include "clockdomain.h" 26 #include "pm.h" 27 #include "twl-common.h" 28 29 static struct omap_device_pm_latency *pm_lats; 30 31 static int _init_omap_device(char *name) 32 { 33 struct omap_hwmod *oh; 34 struct platform_device *pdev; 35 36 oh = omap_hwmod_lookup(name); 37 if (WARN(!oh, "%s: could not find omap_hwmod for %s\n", 38 __func__, name)) 39 return -ENODEV; 40 41 pdev = omap_device_build(oh->name, 0, oh, NULL, 0, pm_lats, 0, false); 42 if (WARN(IS_ERR(pdev), "%s: could not build omap_device for %s\n", 43 __func__, name)) 44 return -ENODEV; 45 46 return 0; 47 } 48 49 /* 50 * Build omap_devices for processors and bus. 51 */ 52 static void omap2_init_processor_devices(void) 53 { 54 _init_omap_device("mpu"); 55 if (omap3_has_iva()) 56 _init_omap_device("iva"); 57 58 if (cpu_is_omap44xx()) { 59 _init_omap_device("l3_main_1"); 60 _init_omap_device("dsp"); 61 _init_omap_device("iva"); 62 } else { 63 _init_omap_device("l3_main"); 64 } 65 } 66 67 /* Types of sleep_switch used in omap_set_pwrdm_state */ 68 #define FORCEWAKEUP_SWITCH 0 69 #define LOWPOWERSTATE_SWITCH 1 70 71 /* 72 * This sets pwrdm state (other than mpu & core. Currently only ON & 73 * RET are supported. 74 */ 75 int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state) 76 { 77 u32 cur_state; 78 int sleep_switch = -1; 79 int ret = 0; 80 int hwsup = 0; 81 82 if (pwrdm == NULL || IS_ERR(pwrdm)) 83 return -EINVAL; 84 85 while (!(pwrdm->pwrsts & (1 << state))) { 86 if (state == PWRDM_POWER_OFF) 87 return ret; 88 state--; 89 } 90 91 cur_state = pwrdm_read_next_pwrst(pwrdm); 92 if (cur_state == state) 93 return ret; 94 95 if (pwrdm_read_pwrst(pwrdm) < PWRDM_POWER_ON) { 96 if ((pwrdm_read_pwrst(pwrdm) > state) && 97 (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) { 98 sleep_switch = LOWPOWERSTATE_SWITCH; 99 } else { 100 hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]); 101 clkdm_wakeup(pwrdm->pwrdm_clkdms[0]); 102 sleep_switch = FORCEWAKEUP_SWITCH; 103 } 104 } 105 106 ret = pwrdm_set_next_pwrst(pwrdm, state); 107 if (ret) { 108 pr_err("%s: unable to set state of powerdomain: %s\n", 109 __func__, pwrdm->name); 110 goto err; 111 } 112 113 switch (sleep_switch) { 114 case FORCEWAKEUP_SWITCH: 115 if (hwsup) 116 clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]); 117 else 118 clkdm_sleep(pwrdm->pwrdm_clkdms[0]); 119 break; 120 case LOWPOWERSTATE_SWITCH: 121 pwrdm_set_lowpwrstchange(pwrdm); 122 break; 123 default: 124 return ret; 125 } 126 127 pwrdm_state_switch(pwrdm); 128 err: 129 return ret; 130 } 131 132 /* 133 * This API is to be called during init to set the various voltage 134 * domains to the voltage as per the opp table. Typically we boot up 135 * at the nominal voltage. So this function finds out the rate of 136 * the clock associated with the voltage domain, finds out the correct 137 * opp entry and sets the voltage domain to the voltage specified 138 * in the opp entry 139 */ 140 static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name, 141 const char *oh_name) 142 { 143 struct voltagedomain *voltdm; 144 struct clk *clk; 145 struct opp *opp; 146 unsigned long freq, bootup_volt; 147 struct device *dev; 148 149 if (!vdd_name || !clk_name || !oh_name) { 150 pr_err("%s: invalid parameters\n", __func__); 151 goto exit; 152 } 153 154 dev = omap_device_get_by_hwmod_name(oh_name); 155 if (IS_ERR(dev)) { 156 pr_err("%s: Unable to get dev pointer for hwmod %s\n", 157 __func__, oh_name); 158 goto exit; 159 } 160 161 voltdm = voltdm_lookup(vdd_name); 162 if (IS_ERR(voltdm)) { 163 pr_err("%s: unable to get vdd pointer for vdd_%s\n", 164 __func__, vdd_name); 165 goto exit; 166 } 167 168 clk = clk_get(NULL, clk_name); 169 if (IS_ERR(clk)) { 170 pr_err("%s: unable to get clk %s\n", __func__, clk_name); 171 goto exit; 172 } 173 174 freq = clk->rate; 175 clk_put(clk); 176 177 opp = opp_find_freq_ceil(dev, &freq); 178 if (IS_ERR(opp)) { 179 pr_err("%s: unable to find boot up OPP for vdd_%s\n", 180 __func__, vdd_name); 181 goto exit; 182 } 183 184 bootup_volt = opp_get_voltage(opp); 185 if (!bootup_volt) { 186 pr_err("%s: unable to find voltage corresponding " 187 "to the bootup OPP for vdd_%s\n", __func__, vdd_name); 188 goto exit; 189 } 190 191 voltdm_scale(voltdm, bootup_volt); 192 return 0; 193 194 exit: 195 pr_err("%s: unable to set vdd_%s\n", __func__, vdd_name); 196 return -EINVAL; 197 } 198 199 static void __init omap3_init_voltages(void) 200 { 201 if (!cpu_is_omap34xx()) 202 return; 203 204 omap2_set_init_voltage("mpu_iva", "dpll1_ck", "mpu"); 205 omap2_set_init_voltage("core", "l3_ick", "l3_main"); 206 } 207 208 static void __init omap4_init_voltages(void) 209 { 210 if (!cpu_is_omap44xx()) 211 return; 212 213 omap2_set_init_voltage("mpu", "dpll_mpu_ck", "mpu"); 214 omap2_set_init_voltage("core", "l3_div_ck", "l3_main_1"); 215 omap2_set_init_voltage("iva", "dpll_iva_m5x2_ck", "iva"); 216 } 217 218 static int __init omap2_common_pm_init(void) 219 { 220 if (!of_have_populated_dt()) 221 omap2_init_processor_devices(); 222 omap_pm_if_init(); 223 224 return 0; 225 } 226 postcore_initcall(omap2_common_pm_init); 227 228 static int __init omap2_common_pm_late_init(void) 229 { 230 /* Init the voltage layer */ 231 omap_pmic_late_init(); 232 omap_voltage_late_init(); 233 234 /* Initialize the voltages */ 235 omap3_init_voltages(); 236 omap4_init_voltages(); 237 238 /* Smartreflex device init */ 239 omap_devinit_smartreflex(); 240 241 return 0; 242 } 243 late_initcall(omap2_common_pm_late_init); 244