c9a315f9d3d8e99a130ce3fe74670d92fa3c9d77
[pandora-kernel.git] / arch / arm / mach-omap2 / vp.c
1 #include <linux/kernel.h>
2 #include <linux/init.h>
3
4 #include <plat/common.h>
5
6 #include "voltage.h"
7 #include "vp.h"
8 #include "prm-regbits-34xx.h"
9 #include "prm-regbits-44xx.h"
10 #include "prm44xx.h"
11
12 static void vp_latch_vsel(struct voltagedomain *voltdm)
13 {
14         struct omap_vp_instance *vp = voltdm->vp;
15         u32 vpconfig;
16         unsigned long uvdc;
17         char vsel;
18
19         uvdc = omap_voltage_get_nom_volt(voltdm);
20         if (!uvdc) {
21                 pr_warning("%s: unable to find current voltage for vdd_%s\n",
22                         __func__, voltdm->name);
23                 return;
24         }
25
26         if (!voltdm->pmic || !voltdm->pmic->uv_to_vsel) {
27                 pr_warning("%s: PMIC function to convert voltage in uV to"
28                         " vsel not registered\n", __func__);
29                 return;
30         }
31
32         vsel = voltdm->pmic->uv_to_vsel(uvdc);
33
34         vpconfig = voltdm->read(vp->vpconfig);
35         vpconfig &= ~(vp->common->vpconfig_initvoltage_mask |
36                         vp->common->vpconfig_initvdd);
37         vpconfig |= vsel << vp->common->vpconfig_initvoltage_shift;
38
39         voltdm->write(vpconfig, vp->vpconfig);
40
41         /* Trigger initVDD value copy to voltage processor */
42         voltdm->write((vpconfig | vp->common->vpconfig_initvdd),
43                        vp->vpconfig);
44
45         /* Clear initVDD copy trigger bit */
46         voltdm->write(vpconfig, vp->vpconfig);
47 }
48
49 /* Generic voltage init functions */
50 void __init omap_vp_init(struct voltagedomain *voltdm)
51 {
52         struct omap_vp_instance *vp = voltdm->vp;
53         struct omap_vdd_info *vdd = voltdm->vdd;
54         u32 vp_val;
55
56         if (!voltdm->read || !voltdm->write) {
57                 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
58                         __func__, voltdm->name);
59                 return;
60         }
61
62         vp_val = vdd->vp_rt_data.vpconfig_erroroffset |
63                 (vdd->vp_rt_data.vpconfig_errorgain <<
64                 vp->common->vpconfig_errorgain_shift) |
65                 vp->common->vpconfig_timeouten;
66         voltdm->write(vp_val, vp->vpconfig);
67
68         vp_val = ((vdd->vp_rt_data.vstepmin_smpswaittimemin <<
69                 vp->common->vstepmin_smpswaittimemin_shift) |
70                 (vdd->vp_rt_data.vstepmin_stepmin <<
71                 vp->common->vstepmin_stepmin_shift));
72         voltdm->write(vp_val, vp->vstepmin);
73
74         vp_val = ((vdd->vp_rt_data.vstepmax_smpswaittimemax <<
75                 vp->common->vstepmax_smpswaittimemax_shift) |
76                 (vdd->vp_rt_data.vstepmax_stepmax <<
77                 vp->common->vstepmax_stepmax_shift));
78         voltdm->write(vp_val, vp->vstepmax);
79
80         vp_val = ((vdd->vp_rt_data.vlimitto_vddmax <<
81                 vp->common->vlimitto_vddmax_shift) |
82                 (vdd->vp_rt_data.vlimitto_vddmin <<
83                 vp->common->vlimitto_vddmin_shift) |
84                 (vdd->vp_rt_data.vlimitto_timeout <<
85                 vp->common->vlimitto_timeout_shift));
86         voltdm->write(vp_val, vp->vlimitto);
87 }
88
89 /* VP force update method of voltage scaling */
90 int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
91                               unsigned long target_volt)
92 {
93         struct omap_vp_instance *vp = voltdm->vp;
94         u32 vpconfig;
95         u8 target_vsel, current_vsel;
96         int ret, timeout = 0;
97
98         ret = omap_vc_pre_scale(voltdm, target_volt, &target_vsel, &current_vsel);
99         if (ret)
100                 return ret;
101
102         /*
103          * Clear all pending TransactionDone interrupt/status. Typical latency
104          * is <3us
105          */
106         while (timeout++ < VP_TRANXDONE_TIMEOUT) {
107                 vp->common->ops->clear_txdone(vp->id);
108                 if (!vp->common->ops->check_txdone(vp->id))
109                         break;
110                 udelay(1);
111         }
112         if (timeout >= VP_TRANXDONE_TIMEOUT) {
113                 pr_warning("%s: vdd_%s TRANXDONE timeout exceeded."
114                         "Voltage change aborted", __func__, voltdm->name);
115                 return -ETIMEDOUT;
116         }
117
118         /* Configure for VP-Force Update */
119         vpconfig = voltdm->read(vp->vpconfig);
120         vpconfig &= ~(vp->common->vpconfig_initvdd |
121                         vp->common->vpconfig_forceupdate |
122                         vp->common->vpconfig_initvoltage_mask);
123         vpconfig |= ((target_vsel <<
124                         vp->common->vpconfig_initvoltage_shift));
125         voltdm->write(vpconfig, vp->vpconfig);
126
127         /* Trigger initVDD value copy to voltage processor */
128         vpconfig |= vp->common->vpconfig_initvdd;
129         voltdm->write(vpconfig, vp->vpconfig);
130
131         /* Force update of voltage */
132         vpconfig |= vp->common->vpconfig_forceupdate;
133         voltdm->write(vpconfig, vp->vpconfig);
134
135         /*
136          * Wait for TransactionDone. Typical latency is <200us.
137          * Depends on SMPSWAITTIMEMIN/MAX and voltage change
138          */
139         timeout = 0;
140         omap_test_timeout(vp->common->ops->check_txdone(vp->id),
141                           VP_TRANXDONE_TIMEOUT, timeout);
142         if (timeout >= VP_TRANXDONE_TIMEOUT)
143                 pr_err("%s: vdd_%s TRANXDONE timeout exceeded."
144                         "TRANXDONE never got set after the voltage update\n",
145                         __func__, voltdm->name);
146
147         omap_vc_post_scale(voltdm, target_volt, target_vsel, current_vsel);
148
149         /*
150          * Disable TransactionDone interrupt , clear all status, clear
151          * control registers
152          */
153         timeout = 0;
154         while (timeout++ < VP_TRANXDONE_TIMEOUT) {
155                 vp->common->ops->clear_txdone(vp->id);
156                 if (!vp->common->ops->check_txdone(vp->id))
157                         break;
158                 udelay(1);
159         }
160
161         if (timeout >= VP_TRANXDONE_TIMEOUT)
162                 pr_warning("%s: vdd_%s TRANXDONE timeout exceeded while trying"
163                         "to clear the TRANXDONE status\n",
164                         __func__, voltdm->name);
165
166         vpconfig = voltdm->read(vp->vpconfig);
167         /* Clear initVDD copy trigger bit */
168         vpconfig &= ~vp->common->vpconfig_initvdd;
169         voltdm->write(vpconfig, vp->vpconfig);
170         /* Clear force bit */
171         vpconfig &= ~vp->common->vpconfig_forceupdate;
172         voltdm->write(vpconfig, vp->vpconfig);
173
174         return 0;
175 }
176
177 /**
178  * omap_vp_get_curr_volt() - API to get the current vp voltage.
179  * @voltdm:     pointer to the VDD.
180  *
181  * This API returns the current voltage for the specified voltage processor
182  */
183 unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm)
184 {
185         struct omap_vp_instance *vp = voltdm->vp;
186         u8 curr_vsel;
187
188         if (!voltdm || IS_ERR(voltdm)) {
189                 pr_warning("%s: VDD specified does not exist!\n", __func__);
190                 return 0;
191         }
192
193         if (!voltdm->read) {
194                 pr_err("%s: No read API for reading vdd_%s regs\n",
195                         __func__, voltdm->name);
196                 return 0;
197         }
198
199         curr_vsel = voltdm->read(vp->voltage);
200
201         if (!voltdm->pmic || !voltdm->pmic->vsel_to_uv) {
202                 pr_warning("%s: PMIC function to convert vsel to voltage"
203                         "in uV not registerd\n", __func__);
204                 return 0;
205         }
206
207         return voltdm->pmic->vsel_to_uv(curr_vsel);
208 }
209
210 /**
211  * omap_vp_enable() - API to enable a particular VP
212  * @voltdm:     pointer to the VDD whose VP is to be enabled.
213  *
214  * This API enables a particular voltage processor. Needed by the smartreflex
215  * class drivers.
216  */
217 void omap_vp_enable(struct voltagedomain *voltdm)
218 {
219         struct omap_vp_instance *vp;
220         u32 vpconfig;
221
222         if (!voltdm || IS_ERR(voltdm)) {
223                 pr_warning("%s: VDD specified does not exist!\n", __func__);
224                 return;
225         }
226
227         vp = voltdm->vp;
228         if (!voltdm->read || !voltdm->write) {
229                 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
230                         __func__, voltdm->name);
231                 return;
232         }
233
234         /* If VP is already enabled, do nothing. Return */
235         if (vp->enabled)
236                 return;
237
238         vp_latch_vsel(voltdm);
239
240         /* Enable VP */
241         vpconfig = voltdm->read(vp->vpconfig);
242         vpconfig |= vp->common->vpconfig_vpenable;
243         voltdm->write(vpconfig, vp->vpconfig);
244         vp->enabled = true;
245 }
246
247 /**
248  * omap_vp_disable() - API to disable a particular VP
249  * @voltdm:     pointer to the VDD whose VP is to be disabled.
250  *
251  * This API disables a particular voltage processor. Needed by the smartreflex
252  * class drivers.
253  */
254 void omap_vp_disable(struct voltagedomain *voltdm)
255 {
256         struct omap_vp_instance *vp;
257         u32 vpconfig;
258         int timeout;
259
260         if (!voltdm || IS_ERR(voltdm)) {
261                 pr_warning("%s: VDD specified does not exist!\n", __func__);
262                 return;
263         }
264
265         vp = voltdm->vp;
266         if (!voltdm->read || !voltdm->write) {
267                 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
268                         __func__, voltdm->name);
269                 return;
270         }
271
272         /* If VP is already disabled, do nothing. Return */
273         if (!vp->enabled) {
274                 pr_warning("%s: Trying to disable VP for vdd_%s when"
275                         "it is already disabled\n", __func__, voltdm->name);
276                 return;
277         }
278
279         /* Disable VP */
280         vpconfig = voltdm->read(vp->vpconfig);
281         vpconfig &= ~vp->common->vpconfig_vpenable;
282         voltdm->write(vpconfig, vp->vpconfig);
283
284         /*
285          * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us
286          */
287         omap_test_timeout((voltdm->read(vp->vstatus)),
288                           VP_IDLE_TIMEOUT, timeout);
289
290         if (timeout >= VP_IDLE_TIMEOUT)
291                 pr_warning("%s: vdd_%s idle timedout\n",
292                         __func__, voltdm->name);
293
294         vp->enabled = false;
295
296         return;
297 }