2 * pm.c - Common OMAP2+ power management-related code
4 * Copyright (C) 2010 Texas Instruments, Inc.
5 * Copyright (C) 2010 Nokia Corporation
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.
12 #include <linux/kernel.h>
13 #include <linux/init.h>
15 #include <linux/err.h>
16 #include <linux/opp.h>
17 #include <linux/export.h>
18 #include <linux/suspend.h>
20 #include <asm/system_misc.h>
22 #include <plat/omap-pm.h>
23 #include <plat/omap_device.h>
26 #include "prcm-common.h"
28 #include "powerdomain.h"
29 #include "clockdomain.h"
31 #include "twl-common.h"
33 static struct omap_device_pm_latency *pm_lats;
36 * omap_pm_suspend: points to a function that does the SoC-specific
39 int (*omap_pm_suspend)(void);
41 static int __init _init_omap_device(char *name)
43 struct omap_hwmod *oh;
44 struct platform_device *pdev;
46 oh = omap_hwmod_lookup(name);
47 if (WARN(!oh, "%s: could not find omap_hwmod for %s\n",
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",
60 * Build omap_devices for processors and bus.
62 static void __init omap2_init_processor_devices(void)
64 _init_omap_device("mpu");
66 _init_omap_device("iva");
68 if (cpu_is_omap44xx()) {
69 _init_omap_device("l3_main_1");
70 _init_omap_device("dsp");
71 _init_omap_device("iva");
73 _init_omap_device("l3_main");
77 /* Types of sleep_switch used in omap_set_pwrdm_state */
78 #define FORCEWAKEUP_SWITCH 0
79 #define LOWPOWERSTATE_SWITCH 1
81 int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
83 if ((clkdm->flags & CLKDM_CAN_ENABLE_AUTO) &&
84 !(clkdm->flags & CLKDM_MISSING_IDLE_REPORTING))
85 clkdm_allow_idle(clkdm);
86 else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&
87 atomic_read(&clkdm->usecount) == 0)
93 * This sets pwrdm state (other than mpu & core. Currently only ON &
96 int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst)
98 u8 curr_pwrst, next_pwrst;
99 int sleep_switch = -1, ret = 0, hwsup = 0;
101 if (!pwrdm || IS_ERR(pwrdm))
104 while (!(pwrdm->pwrsts & (1 << pwrst))) {
105 if (pwrst == PWRDM_POWER_OFF)
110 next_pwrst = pwrdm_read_next_pwrst(pwrdm);
111 if (next_pwrst == pwrst)
114 curr_pwrst = pwrdm_read_pwrst(pwrdm);
115 if (curr_pwrst < PWRDM_POWER_ON) {
116 if ((curr_pwrst > pwrst) &&
117 (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
118 sleep_switch = LOWPOWERSTATE_SWITCH;
120 hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
121 clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
122 sleep_switch = FORCEWAKEUP_SWITCH;
126 ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
128 pr_err("%s: unable to set power state of powerdomain: %s\n",
129 __func__, pwrdm->name);
131 switch (sleep_switch) {
132 case FORCEWAKEUP_SWITCH:
134 clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
136 clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
138 case LOWPOWERSTATE_SWITCH:
139 pwrdm_set_lowpwrstchange(pwrdm);
140 pwrdm_wait_transition(pwrdm);
141 pwrdm_state_switch(pwrdm);
151 * This API is to be called during init to set the various voltage
152 * domains to the voltage as per the opp table. Typically we boot up
153 * at the nominal voltage. So this function finds out the rate of
154 * the clock associated with the voltage domain, finds out the correct
155 * opp entry and sets the voltage domain to the voltage specified
158 static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name,
161 struct voltagedomain *voltdm;
164 unsigned long freq, bootup_volt;
167 if (!vdd_name || !clk_name || !oh_name) {
168 pr_err("%s: invalid parameters\n", __func__);
172 dev = omap_device_get_by_hwmod_name(oh_name);
174 pr_err("%s: Unable to get dev pointer for hwmod %s\n",
179 voltdm = voltdm_lookup(vdd_name);
180 if (IS_ERR(voltdm)) {
181 pr_err("%s: unable to get vdd pointer for vdd_%s\n",
186 clk = clk_get(NULL, clk_name);
188 pr_err("%s: unable to get clk %s\n", __func__, clk_name);
192 freq = clk_get_rate(clk);
196 opp = opp_find_freq_ceil(dev, &freq);
199 pr_err("%s: unable to find boot up OPP for vdd_%s\n",
204 bootup_volt = opp_get_voltage(opp);
207 pr_err("%s: unable to find voltage corresponding to the bootup OPP for vdd_%s\n",
212 voltdm_scale(voltdm, bootup_volt);
216 pr_err("%s: unable to set vdd_%s\n", __func__, vdd_name);
220 #ifdef CONFIG_SUSPEND
221 static int omap_pm_enter(suspend_state_t suspend_state)
225 if (!omap_pm_suspend)
226 return -ENOENT; /* XXX doublecheck */
228 switch (suspend_state) {
229 case PM_SUSPEND_STANDBY:
231 ret = omap_pm_suspend();
240 static int omap_pm_begin(suspend_state_t state)
243 if (cpu_is_omap34xx())
244 omap_prcm_irq_prepare();
248 static void omap_pm_end(void)
254 static void omap_pm_finish(void)
256 if (cpu_is_omap34xx())
257 omap_prcm_irq_complete();
260 static const struct platform_suspend_ops omap_pm_ops = {
261 .begin = omap_pm_begin,
263 .enter = omap_pm_enter,
264 .finish = omap_pm_finish,
265 .valid = suspend_valid_only_mem,
268 #endif /* CONFIG_SUSPEND */
270 static void __init omap3_init_voltages(void)
272 if (!cpu_is_omap34xx())
275 omap2_set_init_voltage("mpu_iva", "dpll1_ck", "mpu");
276 omap2_set_init_voltage("core", "l3_ick", "l3_main");
279 static void __init omap4_init_voltages(void)
281 if (!cpu_is_omap44xx())
284 omap2_set_init_voltage("mpu", "dpll_mpu_ck", "mpu");
285 omap2_set_init_voltage("core", "l3_div_ck", "l3_main_1");
286 omap2_set_init_voltage("iva", "dpll_iva_m5x2_ck", "iva");
289 static int __init omap2_common_pm_init(void)
291 if (!of_have_populated_dt())
292 omap2_init_processor_devices();
297 postcore_initcall(omap2_common_pm_init);
299 int __init omap2_common_pm_late_init(void)
302 * In the case of DT, the PMIC and SR initialization will be done using
303 * a completely different mechanism.
304 * Disable this part if a DT blob is available.
306 if (of_have_populated_dt())
309 /* Init the voltage layer */
310 omap_pmic_late_init();
311 omap_voltage_late_init();
313 /* Initialize the voltages */
314 omap3_init_voltages();
315 omap4_init_voltages();
317 /* Smartreflex device init */
318 omap_devinit_smartreflex();
320 #ifdef CONFIG_SUSPEND
321 suspend_set_ops(&omap_pm_ops);