2 * OMAP3/4 LDO users core
4 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
5 * Mike Turquette <mturquette@ti.com>
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>
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
) ?
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
,
48 if (_is_abb_enabled(voltdm
, abb
) == available
)
51 voltdm
->rmw(abb
->setup_bits
->enable_mask
,
52 (available
) ? abb
->setup_bits
->enable_mask
: 0,
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
)
70 while (timeout
++ < abb
->tranx_timeout
) {
71 ret
= abb
->ops
->check_txdone(abb
->prm_irq_id
);
78 if (timeout
>= abb
->tranx_timeout
) {
79 pr_warning("%s:%s: ABB TRANXDONE waittimeout(timeout=%d)\n",
80 __func__
, voltdm
->name
, timeout
);
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
)
99 /* clear interrupt status */
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
);
111 if (timeout
>= abb
->tranx_timeout
) {
112 pr_warning("%s:%s: ABB TRANXDONE timeout(timeout=%d)\n",
113 __func__
, voltdm
->name
, timeout
);
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
;
129 ret
= _abb_clear_tranx(voltdm
, abb
);
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
),
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
);
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
162 static int _abb_scale(struct voltagedomain
*voltdm
,
163 struct omap_volt_data
*target_vdata
, bool is_prescale
)
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
);
176 if (IS_ERR_OR_NULL(abb
)) {
177 WARN(1, "%s:%s: no abb structure!\n", __func__
, voltdm
->name
);
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
)
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
);
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
))
208 if (!is_prescale
&& (target_abb
< curr_abb
))
211 /* Time to set ABB now */
212 ret
= _abb_set_abb(voltdm
, target_abb
);
214 abb
->__cur_abb_type
= target_abb
;
215 pr_debug("%s: %s: scaled - t_abb=%d!\n", __func__
,
216 voltdm
->name
, target_abb
);
218 pr_warning("%s: %s: failed scale: t_abb=%d (%d)!\n", __func__
,
219 voltdm
->name
, target_abb
, ret
);
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
);
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
)
266 struct omap_ldo_abb_instance
*abb
;
268 if (IS_ERR_OR_NULL(voltdm
)) {
269 pr_err("%s: No voltdm?\n", __func__
);
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
);
279 if (IS_ERR_OR_NULL(abb
))
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
);
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
),
315 /* Allow Forward Body-Bias */
316 voltdm
->rmw(abb
->setup_bits
->active_fbb_mask
,
317 abb
->setup_bits
->active_fbb_mask
, abb
->setup_reg
);
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
);