ARM: cpu topology: Add debugfs interface for cpu_power
[cmplus.git] / arch / arm / mach-omap2 / ldo.c
blob13ee2a3f8d0a326df38ae9bce6c95e24e22bbfff
1 /*
2 * OMAP3/4 LDO users core
4 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
5 * Mike Turquette <mturquette@ti.com>
6 * Nishanth Menon
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
13 #include <linux/kernel.h>
14 #include <linux/delay.h>
15 #include <linux/init.h>
17 #include <plat/cpu.h>
18 #include "voltage.h"
19 #include "ldo.h"
21 /**
22 * _is_abb_enabled() - check if abb is enabled
23 * @voltdm: voltage domain to check for
24 * @abb: abb instance pointer
26 * Returns true if enabled, else returns false
28 static inline bool _is_abb_enabled(struct voltagedomain *voltdm,
29 struct omap_ldo_abb_instance *abb)
31 return (voltdm->read(abb->setup_reg) & abb->setup_bits->enable_mask) ?
32 true : false;
35 /**
36 * _abb_set_availability() - sets the availability of the ABB LDO
37 * @voltdm: voltage domain for which we would like to set
38 * @abb: abb instance pointer
39 * @available: should I enable/disable the LDO?
41 * Depending on the request, it enables/disables the LDO if it was not
42 * in that state already.
44 static inline void _abb_set_availability(struct voltagedomain *voltdm,
45 struct omap_ldo_abb_instance *abb,
46 bool available)
48 if (_is_abb_enabled(voltdm, abb) == available)
49 return;
51 voltdm->rmw(abb->setup_bits->enable_mask,
52 (available) ? abb->setup_bits->enable_mask : 0,
53 abb->setup_reg);
56 /**
57 * _abb_wait_tranx() - wait for abb tranxdone event
58 * @voltdm: voltage domain we are operating on
59 * @abb: pointer to the abb instance
61 * Returns -ETIMEDOUT if the event is not set on time.
63 static int _abb_wait_tranx(struct voltagedomain *voltdm,
64 struct omap_ldo_abb_instance *abb)
66 int timeout;
67 int ret;
69 timeout = 0;
70 while (timeout++ < abb->tranx_timeout) {
71 ret = abb->ops->check_txdone(abb->prm_irq_id);
72 if (ret)
73 break;
75 udelay(1);
78 if (timeout >= abb->tranx_timeout) {
79 pr_warning("%s:%s: ABB TRANXDONE waittimeout(timeout=%d)\n",
80 __func__, voltdm->name, timeout);
81 return -ETIMEDOUT;
83 return 0;
86 /**
87 * _abb_clear_tranx() - clear abb tranxdone event
88 * @voltdm: voltage domain we are operating on
89 * @abb: pointer to the abb instance
91 * Returns -ETIMEDOUT if the event is not cleared on time.
93 static int _abb_clear_tranx(struct voltagedomain *voltdm,
94 struct omap_ldo_abb_instance *abb)
96 int timeout;
97 int ret;
99 /* clear interrupt status */
100 timeout = 0;
101 while (timeout++ < abb->tranx_timeout) {
102 abb->ops->clear_txdone(abb->prm_irq_id);
104 ret = abb->ops->check_txdone(abb->prm_irq_id);
105 if (!ret)
106 break;
108 udelay(1);
111 if (timeout >= abb->tranx_timeout) {
112 pr_warning("%s:%s: ABB TRANXDONE timeout(timeout=%d)\n",
113 __func__, voltdm->name, timeout);
114 return -ETIMEDOUT;
116 return 0;
120 * _abb_set_abb() - helper to actually set ABB (NOMINAL/FAST)
121 * @voltdm: voltage domain we are operating on
122 * @abb_type: ABB type we want to set
124 static int _abb_set_abb(struct voltagedomain *voltdm, int abb_type)
126 struct omap_ldo_abb_instance *abb = voltdm->abb;
127 int ret;
129 ret = _abb_clear_tranx(voltdm, abb);
130 if (ret)
131 return ret;
133 /* program next state of ABB ldo */
134 voltdm->rmw(abb->ctrl_bits->opp_sel_mask,
135 abb_type << __ffs(abb->ctrl_bits->opp_sel_mask),
136 abb->ctrl_reg);
138 /* initiate ABB ldo change */
139 voltdm->rmw(abb->ctrl_bits->opp_change_mask,
140 abb->ctrl_bits->opp_change_mask, abb->ctrl_reg);
142 /* Wait for conversion completion */
143 ret = _abb_wait_tranx(voltdm, abb);
144 WARN_ONCE(ret, "%s: voltdm %s ABB TRANXDONE was not set on time:%d\n",
145 __func__, voltdm->name, ret);
146 /* clear interrupt status */
147 ret |= _abb_clear_tranx(voltdm, abb);
149 return ret;
153 * _abb_scale() - wrapper which does the necessary things for pre and post scale
154 * @voltdm: voltage domain to operate on
155 * @target_volt: voltage we are going to
156 * @is_prescale: are we doing a prescale operation?
158 * NOTE: We expect caller ensures that a specific voltdm is modified
159 * sequentially. All locking is expected to be implemented by users
160 * of LDO functions
162 static int _abb_scale(struct voltagedomain *voltdm,
163 struct omap_volt_data *target_vdata, bool is_prescale)
165 int ret = 0;
166 int curr_abb, target_abb;
167 struct omap_ldo_abb_instance *abb;
169 if (IS_ERR_OR_NULL(target_vdata)) {
170 pr_err("%s:%s: Invalid volt data tv=%p!\n", __func__,
171 voltdm->name, target_vdata);
172 return -EINVAL;
175 abb = voltdm->abb;
176 if (IS_ERR_OR_NULL(abb)) {
177 WARN(1, "%s:%s: no abb structure!\n", __func__, voltdm->name);
178 return -EINVAL;
181 curr_abb = abb->__cur_abb_type;
182 target_abb = target_vdata->abb_type;
184 pr_debug("%s: %s: Enter: t_v=%ld scale=%d c_abb=%d t_abb=%d ret=%d\n",
185 __func__, voltdm->name, omap_get_nominal_voltage(target_vdata),
186 is_prescale, curr_abb, target_abb, ret);
188 /* If we were'nt booting and there is no change, we get out */
189 if (target_abb == curr_abb && voltdm->curr_volt)
190 goto out;
192 /* Do we have an invalid ABB entry? scream for a fix! */
193 if (curr_abb == OMAP_ABB_NONE || target_abb == OMAP_ABB_NONE) {
194 WARN(1, "%s:%s: INVALID abb entries? curr=%d target=%d\n",
195 __func__, voltdm->name, curr_abb, target_abb);
196 return -EINVAL;
200 * We set up ABB as follows:
201 * if we are scaling *to* a voltage which needs ABB, do it in post
202 * if we are scaling *from* a voltage which needs ABB, do it in pre
203 * So, if the conditions are in reverse, we just return happy
205 if (is_prescale && (target_abb > curr_abb))
206 goto out;
208 if (!is_prescale && (target_abb < curr_abb))
209 goto out;
211 /* Time to set ABB now */
212 ret = _abb_set_abb(voltdm, target_abb);
213 if (!ret) {
214 abb->__cur_abb_type = target_abb;
215 pr_debug("%s: %s: scaled - t_abb=%d!\n", __func__,
216 voltdm->name, target_abb);
217 } else {
218 pr_warning("%s: %s: failed scale: t_abb=%d (%d)!\n", __func__,
219 voltdm->name, target_abb, ret);
222 out:
223 pr_debug("%s: %s:Exit: t_v=%ld scale=%d c_abb=%d t_abb=%d ret=%d\n",
224 __func__, voltdm->name, omap_get_nominal_voltage(target_vdata),
225 is_prescale, curr_abb, target_abb, ret);
226 return ret;
231 * omap_ldo_abb_pre_scale() - Enable required ABB strategy before voltage scale
232 * @voltdm: voltage domain to operate on
233 * @target_volt: target voltage data we moved to.
235 int omap_ldo_abb_pre_scale(struct voltagedomain *voltdm,
236 struct omap_volt_data *target_vdata)
238 return _abb_scale(voltdm, target_vdata, true);
242 * omap_ldo_abb_pre_scale() - Enable required ABB strategy after voltage scale
243 * @voltdm: voltage domain operated on
244 * @target_volt: target voltage we are going to
246 int omap_ldo_abb_post_scale(struct voltagedomain *voltdm,
247 struct omap_volt_data *target_vdata)
249 return _abb_scale(voltdm, target_vdata, false);
253 * omap_ldo_abb_init() - initialize the ABB LDO for associated for this domain
254 * @voltdm: voltdm for which we need to initialize the ABB LDO
256 * Programs up the the configurations that dont change in the domain
258 * Return 0 if all goes fine, else returns appropriate error value
260 void __init omap_ldo_abb_init(struct voltagedomain *voltdm)
262 u32 sys_clk_rate;
263 u32 cycle_rate;
264 u32 settling_time;
265 u32 wait_count_val;
266 struct omap_ldo_abb_instance *abb;
268 if (IS_ERR_OR_NULL(voltdm)) {
269 pr_err("%s: No voltdm?\n", __func__);
270 return;
272 if (!voltdm->read || !voltdm->write || !voltdm->rmw) {
273 pr_err("%s: No read/write/rmw API for accessing vdd_%s regs\n",
274 __func__, voltdm->name);
275 return;
278 abb = voltdm->abb;
279 if (IS_ERR_OR_NULL(abb))
280 return;
281 if (IS_ERR_OR_NULL(abb->ctrl_bits) || IS_ERR_OR_NULL(abb->setup_bits)) {
282 pr_err("%s: Corrupted ABB configuration on vdd_%s regs\n",
283 __func__, voltdm->name);
284 return;
288 * SR2_WTCNT_VALUE must be programmed with the expected settling time
289 * for ABB ldo transition. This value depends on the cycle rate for
290 * the ABB IP (varies per OMAP family), and the system clock frequency
291 * (varies per board). The formula is:
293 * SR2_WTCNT_VALUE = SettlingTime / (CycleRate / SystemClkRate))
294 * where SettlingTime is in micro-seconds and SystemClkRate is in MHz.
296 * To avoid dividing by zero multiply both CycleRate and SettlingTime
297 * by 10 such that the final result is the one we want.
300 /* Convert SYS_CLK rate to MHz & prevent divide by zero */
301 sys_clk_rate = DIV_ROUND_CLOSEST(voltdm->sys_clk.rate, 1000000);
302 cycle_rate = abb->cycle_rate * 10;
303 settling_time = abb->settling_time * 10;
305 /* Calculate cycle rate */
306 cycle_rate = DIV_ROUND_CLOSEST(cycle_rate, sys_clk_rate);
308 /* Calulate SR2_WTCNT_VALUE */
309 wait_count_val = DIV_ROUND_CLOSEST(settling_time, cycle_rate);
311 voltdm->rmw(abb->setup_bits->wait_count_mask,
312 wait_count_val << __ffs(abb->setup_bits->wait_count_mask),
313 abb->setup_reg);
315 /* Allow Forward Body-Bias */
316 voltdm->rmw(abb->setup_bits->active_fbb_mask,
317 abb->setup_bits->active_fbb_mask, abb->setup_reg);
319 /* Enable ABB */
320 _abb_set_availability(voltdm, abb, true);
323 * Beware of the bootloader!
324 * Initialize current abb type based on what we read off the reg.
325 * we cant trust the initial state based off boot voltage's volt_data
326 * even. Not all bootloaders are nice :(
328 abb->__cur_abb_type = (voltdm->read(abb->ctrl_reg) &
329 abb->ctrl_bits->opp_sel_mask) >>
330 __ffs(abb->ctrl_bits->opp_sel_mask);
332 return;