diff options
Diffstat (limited to 'arch/arm/mach-omap2/pm.c')
-rw-r--r-- | arch/arm/mach-omap2/pm.c | 102 |
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 | ||
24 | static struct omap_device_pm_latency *pm_lats; | 27 | static 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 | */ | ||
168 | static 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 | |||
215 | exit: | ||
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 | |||
221 | static 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 | |||
230 | static 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 | |||
157 | static int __init omap2_common_pm_init(void) | 240 | static 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 | } |
164 | postcore_initcall(omap2_common_pm_init); | 247 | postcore_initcall(omap2_common_pm_init); |
165 | 248 | ||
249 | static 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 | } | ||
267 | late_initcall(omap2_common_pm_late_init); | ||