]> Pileus Git - ~andy/linux/blob - arch/arm/mach-omap2/vp.c
OMAP3+: VP: remove unused omap_vp_get_curr_volt()
[~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         if (!voltdm->vp)
107                 return -EINVAL;
108
109         /* Get volt_data corresponding to target_volt */
110         volt_data = omap_voltage_get_voltdata(voltdm, target_volt);
111         if (IS_ERR(volt_data))
112                 return -EINVAL;
113
114         /* Setting vp errorgain based on the voltage */
115         voltdm->rmw(voltdm->vp->common->vpconfig_errorgain_mask,
116                     volt_data->vp_errgain <<
117                     __ffs(voltdm->vp->common->vpconfig_errorgain_mask),
118                     voltdm->vp->vpconfig);
119
120         return 0;
121 }
122
123 /* VP force update method of voltage scaling */
124 int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
125                               unsigned long target_volt)
126 {
127         struct omap_vp_instance *vp = voltdm->vp;
128         u32 vpconfig;
129         u8 target_vsel, current_vsel;
130         int ret, timeout = 0;
131
132         ret = omap_vc_pre_scale(voltdm, target_volt, &target_vsel, &current_vsel);
133         if (ret)
134                 return ret;
135
136         /*
137          * Clear all pending TransactionDone interrupt/status. Typical latency
138          * is <3us
139          */
140         while (timeout++ < VP_TRANXDONE_TIMEOUT) {
141                 vp->common->ops->clear_txdone(vp->id);
142                 if (!vp->common->ops->check_txdone(vp->id))
143                         break;
144                 udelay(1);
145         }
146         if (timeout >= VP_TRANXDONE_TIMEOUT) {
147                 pr_warning("%s: vdd_%s TRANXDONE timeout exceeded."
148                         "Voltage change aborted", __func__, voltdm->name);
149                 return -ETIMEDOUT;
150         }
151
152         /* Configure for VP-Force Update */
153         vpconfig = voltdm->read(vp->vpconfig);
154         vpconfig &= ~(vp->common->vpconfig_initvdd |
155                         vp->common->vpconfig_forceupdate |
156                         vp->common->vpconfig_initvoltage_mask);
157         vpconfig |= ((target_vsel <<
158                       __ffs(vp->common->vpconfig_initvoltage_mask)));
159         voltdm->write(vpconfig, vp->vpconfig);
160
161         /* Trigger initVDD value copy to voltage processor */
162         vpconfig |= vp->common->vpconfig_initvdd;
163         voltdm->write(vpconfig, vp->vpconfig);
164
165         /* Force update of voltage */
166         vpconfig |= vp->common->vpconfig_forceupdate;
167         voltdm->write(vpconfig, vp->vpconfig);
168
169         /*
170          * Wait for TransactionDone. Typical latency is <200us.
171          * Depends on SMPSWAITTIMEMIN/MAX and voltage change
172          */
173         timeout = 0;
174         omap_test_timeout(vp->common->ops->check_txdone(vp->id),
175                           VP_TRANXDONE_TIMEOUT, timeout);
176         if (timeout >= VP_TRANXDONE_TIMEOUT)
177                 pr_err("%s: vdd_%s TRANXDONE timeout exceeded."
178                         "TRANXDONE never got set after the voltage update\n",
179                         __func__, voltdm->name);
180
181         omap_vc_post_scale(voltdm, target_volt, target_vsel, current_vsel);
182
183         /*
184          * Disable TransactionDone interrupt , clear all status, clear
185          * control registers
186          */
187         timeout = 0;
188         while (timeout++ < VP_TRANXDONE_TIMEOUT) {
189                 vp->common->ops->clear_txdone(vp->id);
190                 if (!vp->common->ops->check_txdone(vp->id))
191                         break;
192                 udelay(1);
193         }
194
195         if (timeout >= VP_TRANXDONE_TIMEOUT)
196                 pr_warning("%s: vdd_%s TRANXDONE timeout exceeded while trying"
197                         "to clear the TRANXDONE status\n",
198                         __func__, voltdm->name);
199
200         vpconfig = voltdm->read(vp->vpconfig);
201         /* Clear initVDD copy trigger bit */
202         vpconfig &= ~vp->common->vpconfig_initvdd;
203         voltdm->write(vpconfig, vp->vpconfig);
204         /* Clear force bit */
205         vpconfig &= ~vp->common->vpconfig_forceupdate;
206         voltdm->write(vpconfig, vp->vpconfig);
207
208         return 0;
209 }
210
211 /**
212  * omap_vp_enable() - API to enable a particular VP
213  * @voltdm:     pointer to the VDD whose VP is to be enabled.
214  *
215  * This API enables a particular voltage processor. Needed by the smartreflex
216  * class drivers.
217  */
218 void omap_vp_enable(struct voltagedomain *voltdm)
219 {
220         struct omap_vp_instance *vp;
221         u32 vpconfig;
222
223         if (!voltdm || IS_ERR(voltdm)) {
224                 pr_warning("%s: VDD specified does not exist!\n", __func__);
225                 return;
226         }
227
228         vp = voltdm->vp;
229         if (!voltdm->read || !voltdm->write) {
230                 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
231                         __func__, voltdm->name);
232                 return;
233         }
234
235         /* If VP is already enabled, do nothing. Return */
236         if (vp->enabled)
237                 return;
238
239         vp_latch_vsel(voltdm);
240
241         /* Enable VP */
242         vpconfig = voltdm->read(vp->vpconfig);
243         vpconfig |= vp->common->vpconfig_vpenable;
244         voltdm->write(vpconfig, vp->vpconfig);
245         vp->enabled = true;
246 }
247
248 /**
249  * omap_vp_disable() - API to disable a particular VP
250  * @voltdm:     pointer to the VDD whose VP is to be disabled.
251  *
252  * This API disables a particular voltage processor. Needed by the smartreflex
253  * class drivers.
254  */
255 void omap_vp_disable(struct voltagedomain *voltdm)
256 {
257         struct omap_vp_instance *vp;
258         u32 vpconfig;
259         int timeout;
260
261         if (!voltdm || IS_ERR(voltdm)) {
262                 pr_warning("%s: VDD specified does not exist!\n", __func__);
263                 return;
264         }
265
266         vp = voltdm->vp;
267         if (!voltdm->read || !voltdm->write) {
268                 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
269                         __func__, voltdm->name);
270                 return;
271         }
272
273         /* If VP is already disabled, do nothing. Return */
274         if (!vp->enabled) {
275                 pr_warning("%s: Trying to disable VP for vdd_%s when"
276                         "it is already disabled\n", __func__, voltdm->name);
277                 return;
278         }
279
280         /* Disable VP */
281         vpconfig = voltdm->read(vp->vpconfig);
282         vpconfig &= ~vp->common->vpconfig_vpenable;
283         voltdm->write(vpconfig, vp->vpconfig);
284
285         /*
286          * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us
287          */
288         omap_test_timeout((voltdm->read(vp->vstatus)),
289                           VP_IDLE_TIMEOUT, timeout);
290
291         if (timeout >= VP_IDLE_TIMEOUT)
292                 pr_warning("%s: vdd_%s idle timedout\n",
293                         __func__, voltdm->name);
294
295         vp->enabled = false;
296
297         return;
298 }