aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/pm.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/pm.c')
-rw-r--r--arch/arm/mach-omap2/pm.c102
1 files changed, 102 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 9b1db592759f..d5a102c71989 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -13,13 +13,16 @@
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/io.h> 14#include <linux/io.h>
15#include <linux/err.h> 15#include <linux/err.h>
16#include <linux/opp.h>
16 17
17#include <plat/omap-pm.h> 18#include <plat/omap-pm.h>
18#include <plat/omap_device.h> 19#include <plat/omap_device.h>
19#include <plat/common.h> 20#include <plat/common.h>
21#include <plat/voltage.h>
20 22
21#include "powerdomain.h" 23#include "powerdomain.h"
22#include "clockdomain.h" 24#include "clockdomain.h"
25#include "pm.h"
23 26
24static struct omap_device_pm_latency *pm_lats; 27static struct omap_device_pm_latency *pm_lats;
25 28
@@ -154,6 +157,86 @@ err:
154 return ret; 157 return ret;
155} 158}
156 159
160/*
161 * This API is to be called during init to put the various voltage
162 * domains to the voltage as per the opp table. Typically we boot up
163 * at the nominal voltage. So this function finds out the rate of
164 * the clock associated with the voltage domain, finds out the correct
165 * opp entry and puts the voltage domain to the voltage specifies
166 * in the opp entry
167 */
168static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name,
169 struct device *dev)
170{
171 struct voltagedomain *voltdm;
172 struct clk *clk;
173 struct opp *opp;
174 unsigned long freq, bootup_volt;
175
176 if (!vdd_name || !clk_name || !dev) {
177 printk(KERN_ERR "%s: Invalid parameters!\n", __func__);
178 goto exit;
179 }
180
181 voltdm = omap_voltage_domain_lookup(vdd_name);
182 if (IS_ERR(voltdm)) {
183 printk(KERN_ERR "%s: Unable to get vdd pointer for vdd_%s\n",
184 __func__, vdd_name);
185 goto exit;
186 }
187
188 clk = clk_get(NULL, clk_name);
189 if (IS_ERR(clk)) {
190 printk(KERN_ERR "%s: unable to get clk %s\n",
191 __func__, clk_name);
192 goto exit;
193 }
194
195 freq = clk->rate;
196 clk_put(clk);
197
198 opp = opp_find_freq_ceil(dev, &freq);
199 if (IS_ERR(opp)) {
200 printk(KERN_ERR "%s: unable to find boot up OPP for vdd_%s\n",
201 __func__, vdd_name);
202 goto exit;
203 }
204
205 bootup_volt = opp_get_voltage(opp);
206 if (!bootup_volt) {
207 printk(KERN_ERR "%s: unable to find voltage corresponding"
208 "to the bootup OPP for vdd_%s\n", __func__, vdd_name);
209 goto exit;
210 }
211
212 omap_voltage_scale_vdd(voltdm, bootup_volt);
213 return 0;
214
215exit:
216 printk(KERN_ERR "%s: Unable to put vdd_%s to its init voltage\n\n",
217 __func__, vdd_name);
218 return -EINVAL;
219}
220
221static void __init omap3_init_voltages(void)
222{
223 if (!cpu_is_omap34xx())
224 return;
225
226 omap2_set_init_voltage("mpu", "dpll1_ck", mpu_dev);
227 omap2_set_init_voltage("core", "l3_ick", l3_dev);
228}
229
230static void __init omap4_init_voltages(void)
231{
232 if (!cpu_is_omap44xx())
233 return;
234
235 omap2_set_init_voltage("mpu", "dpll_mpu_ck", mpu_dev);
236 omap2_set_init_voltage("core", "l3_div_ck", l3_dev);
237 omap2_set_init_voltage("iva", "dpll_iva_m5x2_ck", iva_dev);
238}
239
157static int __init omap2_common_pm_init(void) 240static int __init omap2_common_pm_init(void)
158{ 241{
159 omap2_init_processor_devices(); 242 omap2_init_processor_devices();
@@ -163,3 +246,22 @@ static int __init omap2_common_pm_init(void)
163} 246}
164postcore_initcall(omap2_common_pm_init); 247postcore_initcall(omap2_common_pm_init);
165 248
249static int __init omap2_common_pm_late_init(void)
250{
251 /* Init the OMAP TWL parameters */
252 omap3_twl_init();
253 omap4_twl_init();
254
255 /* Init the voltage layer */
256 omap_voltage_late_init();
257
258 /* Initialize the voltages */
259 omap3_init_voltages();
260 omap4_init_voltages();
261
262 /* Smartreflex device init */
263 omap_devinit_smartreflex();
264
265 return 0;
266}
267late_initcall(omap2_common_pm_late_init);