]> Pileus Git - ~andy/linux/blob - arch/arm/mach-omap2/vp.c
OMAP3+: VP: remove omap_vp_runtime_data
[~andy/linux] / 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 << __ffs(vp->common->vpconfig_initvoltage_mask);
38         voltdm->write(vpconfig, vp->vpconfig);
39
40         /* Trigger initVDD value copy to voltage processor */
41         voltdm->write((vpconfig | vp->common->vpconfig_initvdd),
42                        vp->vpconfig);
43
44         /* Clear initVDD copy trigger bit */
45         voltdm->write(vpconfig, vp->vpconfig);
46 }
47
48 /* Generic voltage init functions */
49 void __init omap_vp_init(struct voltagedomain *voltdm)
50 {
51         struct omap_vp_instance *vp = voltdm->vp;
52         u32 val, sys_clk_rate, timeout, waittime;
53         u32 vddmin, vddmax, vstepmin, vstepmax;
54
55         if (!voltdm->read || !voltdm->write) {
56                 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
57                         __func__, voltdm->name);
58                 return;
59         }
60
61         vp->enabled = false;
62
63         /* Divide to avoid overflow */
64         sys_clk_rate = voltdm->sys_clk.rate / 1000;
65
66         timeout = (sys_clk_rate * voltdm->pmic->vp_timeout_us) / 1000;
67         vddmin = voltdm->pmic->vp_vddmin;
68         vddmax = voltdm->pmic->vp_vddmax;
69
70         waittime = ((voltdm->pmic->step_size / voltdm->pmic->slew_rate) *
71                     sys_clk_rate) / 1000;
72         vstepmin = voltdm->pmic->vp_vstepmin;
73         vstepmax = voltdm->pmic->vp_vstepmax;
74
75         /*
76          * VP_CONFIG: error gain is not set here, it will be updated
77          * on each scale, based on OPP.
78          */
79         val = (voltdm->pmic->vp_erroroffset <<
80                __ffs(voltdm->vp->common->vpconfig_erroroffset_mask)) |
81                 vp->common->vpconfig_timeouten;
82         voltdm->write(val, vp->vpconfig);
83
84         /* VSTEPMIN */
85         val = (waittime << vp->common->vstepmin_smpswaittimemin_shift) |
86                 (vstepmin <<  vp->common->vstepmin_stepmin_shift);
87         voltdm->write(val, vp->vstepmin);
88
89         /* VSTEPMAX */
90         val = (vstepmax << vp->common->vstepmax_stepmax_shift) |
91                 (waittime << vp->common->vstepmax_smpswaittimemax_shift);
92         voltdm->write(val, vp->vstepmax);
93
94         /* VLIMITTO */
95         val = (vddmax << vp->common->vlimitto_vddmax_shift) |
96                 (vddmin << vp->common->vlimitto_vddmin_shift) |
97                 (timeout <<  vp->common->vlimitto_timeout_shift);
98         voltdm->write(val, vp->vlimitto);
99 }
100
101 int omap_vp_update_errorgain(struct voltagedomain *voltdm,
102                              unsigned long target_volt)
103 {
104         struct omap_volt_data *volt_data;
105
106         /* Get volt_data corresponding to target_volt */
107         volt_data = omap_voltage_get_voltdata(voltdm, target_volt);
108         if (IS_ERR(volt_data))
109                 return -EINVAL;
110
111         /* Setting vp errorgain based on the voltage */
112         voltdm->rmw(voltdm->vp->common->vpconfig_errorgain_mask,
113                     volt_data->vp_errgain <<
114                     __ffs(voltdm->vp->common->vpconfig_errorgain_mask),
115                     voltdm->vp->vpconfig);
116
117         return 0;
118 }
119
120 /* VP force update method of voltage scaling */
121 int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
122                               unsigned long target_volt)
123 {
124         struct omap_vp_instance *vp = voltdm->vp;
125         u32 vpconfig;
126         u8 target_vsel, current_vsel;
127         int ret, timeout = 0;
128
129         ret = omap_vc_pre_scale(voltdm, target_volt, &target_vsel, &current_vsel);
130         if (ret)
131                 return ret;
132
133         /*
134          * Clear all pending TransactionDone interrupt/status. Typical latency
135          * is <3us
136          */
137         while (timeout++ < VP_TRANXDONE_TIMEOUT) {
138                 vp->common->ops->clear_txdone(vp->id);
139                 if (!vp->common->ops->check_txdone(vp->id))
140                         break;
141                 udelay(1);
142         }
143         if (timeout >= VP_TRANXDONE_TIMEOUT) {
144                 pr_warning("%s: vdd_%s TRANXDONE timeout exceeded."
145                         "Voltage change aborted", __func__, voltdm->name);
146                 return -ETIMEDOUT;
147         }
148
149         /* Configure for VP-Force Update */
150         vpconfig = voltdm->read(vp->vpconfig);
151         vpconfig &= ~(vp->common->vpconfig_initvdd |
152                         vp->common->vpconfig_forceupdate |
153                         vp->common->vpconfig_initvoltage_mask);
154         vpconfig |= ((target_vsel <<
155                       __ffs(vp->common->vpconfig_initvoltage_mask)));
156         voltdm->write(vpconfig, vp->vpconfig);
157
158         /* Trigger initVDD value copy to voltage processor */
159         vpconfig |= vp->common->vpconfig_initvdd;
160         voltdm->write(vpconfig, vp->vpconfig);
161
162         /* Force update of voltage */
163         vpconfig |= vp->common->vpconfig_forceupdate;
164         voltdm->write(vpconfig, vp->vpconfig);
165
166         /*
167          * Wait for TransactionDone. Typical latency is <200us.
168          * Depends on SMPSWAITTIMEMIN/MAX and voltage change
169          */
170         timeout = 0;
171         omap_test_timeout(vp->common->ops->check_txdone(vp->id),
172                           VP_TRANXDONE_TIMEOUT, timeout);
173         if (timeout >= VP_TRANXDONE_TIMEOUT)
174                 pr_err("%s: vdd_%s TRANXDONE timeout exceeded."
175                         "TRANXDONE never got set after the voltage update\n",
176                         __func__, voltdm->name);
177
178         omap_vc_post_scale(voltdm, target_volt, target_vsel, current_vsel);
179
180         /*
181          * Disable TransactionDone interrupt , clear all status, clear
182          * control registers
183          */
184         timeout = 0;
185         while (timeout++ < VP_TRANXDONE_TIMEOUT) {
186                 vp->common->ops->clear_txdone(vp->id);
187                 if (!vp->common->ops->check_txdone(vp->id))
188                         break;
189                 udelay(1);
190         }
191
192         if (timeout >= VP_TRANXDONE_TIMEOUT)
193                 pr_warning("%s: vdd_%s TRANXDONE timeout exceeded while trying"
194                         "to clear the TRANXDONE status\n",
195                         __func__, voltdm->name);
196
197         vpconfig = voltdm->read(vp->vpconfig);
198         /* Clear initVDD copy trigger bit */
199         vpconfig &= ~vp->common->vpconfig_initvdd;
200         voltdm->write(vpconfig, vp->vpconfig);
201         /* Clear force bit */
202         vpconfig &= ~vp->common->vpconfig_forceupdate;
203         voltdm->write(vpconfig, vp->vpconfig);
204
205         return 0;
206 }
207
208 /**
209  * omap_vp_get_curr_volt() - API to get the current vp voltage.
210  * @voltdm:     pointer to the VDD.
211  *
212  * This API returns the current voltage for the specified voltage processor
213  */
214 unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm)
215 {
216         struct omap_vp_instance *vp = voltdm->vp;
217         u8 curr_vsel;
218
219         if (!voltdm || IS_ERR(voltdm)) {
220                 pr_warning("%s: VDD specified does not exist!\n", __func__);
221                 return 0;
222         }
223
224         if (!voltdm->read) {
225                 pr_err("%s: No read API for reading vdd_%s regs\n",
226                         __func__, voltdm->name);
227                 return 0;
228         }
229
230         curr_vsel = voltdm->read(vp->voltage);
231
232         if (!voltdm->pmic || !voltdm->pmic->vsel_to_uv) {
233                 pr_warning("%s: PMIC function to convert vsel to voltage"
234                         "in uV not registerd\n", __func__);
235                 return 0;
236         }
237
238         return voltdm->pmic->vsel_to_uv(curr_vsel);
239 }
240
241 /**
242  * omap_vp_enable() - API to enable a particular VP
243  * @voltdm:     pointer to the VDD whose VP is to be enabled.
244  *
245  * This API enables a particular voltage processor. Needed by the smartreflex
246  * class drivers.
247  */
248 void omap_vp_enable(struct voltagedomain *voltdm)
249 {
250         struct omap_vp_instance *vp;
251         u32 vpconfig;
252
253         if (!voltdm || IS_ERR(voltdm)) {
254                 pr_warning("%s: VDD specified does not exist!\n", __func__);
255                 return;
256         }
257
258         vp = voltdm->vp;
259         if (!voltdm->read || !voltdm->write) {
260                 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
261                         __func__, voltdm->name);
262                 return;
263         }
264
265         /* If VP is already enabled, do nothing. Return */
266         if (vp->enabled)
267                 return;
268
269         vp_latch_vsel(voltdm);
270
271         /* Enable VP */
272         vpconfig = voltdm->read(vp->vpconfig);
273         vpconfig |= vp->common->vpconfig_vpenable;
274         voltdm->write(vpconfig, vp->vpconfig);
275         vp->enabled = true;
276 }
277
278 /**
279  * omap_vp_disable() - API to disable a particular VP
280  * @voltdm:     pointer to the VDD whose VP is to be disabled.
281  *
282  * This API disables a particular voltage processor. Needed by the smartreflex
283  * class drivers.
284  */
285 void omap_vp_disable(struct voltagedomain *voltdm)
286 {
287         struct omap_vp_instance *vp;
288         u32 vpconfig;
289         int timeout;
290
291         if (!voltdm || IS_ERR(voltdm)) {
292                 pr_warning("%s: VDD specified does not exist!\n", __func__);
293                 return;
294         }
295
296         vp = voltdm->vp;
297         if (!voltdm->read || !voltdm->write) {
298                 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
299                         __func__, voltdm->name);
300                 return;
301         }
302
303         /* If VP is already disabled, do nothing. Return */
304         if (!vp->enabled) {
305                 pr_warning("%s: Trying to disable VP for vdd_%s when"
306                         "it is already disabled\n", __func__, voltdm->name);
307                 return;
308         }
309
310         /* Disable VP */
311         vpconfig = voltdm->read(vp->vpconfig);
312         vpconfig &= ~vp->common->vpconfig_vpenable;
313         voltdm->write(vpconfig, vp->vpconfig);
314
315         /*
316          * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us
317          */
318         omap_test_timeout((voltdm->read(vp->vstatus)),
319                           VP_IDLE_TIMEOUT, timeout);
320
321         if (timeout >= VP_IDLE_TIMEOUT)
322                 pr_warning("%s: vdd_%s idle timedout\n",
323                         __func__, voltdm->name);
324
325         vp->enabled = false;
326
327         return;
328 }