• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/kernel.h>
3 #include <linux/init.h>
4 
5 #include "common.h"
6 
7 #include "voltage.h"
8 #include "vp.h"
9 #include "prm-regbits-34xx.h"
10 #include "prm-regbits-44xx.h"
11 #include "prm44xx.h"
12 
_vp_set_init_voltage(struct voltagedomain * voltdm,u32 volt)13 static u32 _vp_set_init_voltage(struct voltagedomain *voltdm, u32 volt)
14 {
15 	struct omap_vp_instance *vp = voltdm->vp;
16 	u32 vpconfig;
17 	char vsel;
18 
19 	vsel = voltdm->pmic->uv_to_vsel(volt);
20 
21 	vpconfig = voltdm->read(vp->vpconfig);
22 	vpconfig &= ~(vp->common->vpconfig_initvoltage_mask |
23 		      vp->common->vpconfig_forceupdate |
24 		      vp->common->vpconfig_initvdd);
25 	vpconfig |= vsel << __ffs(vp->common->vpconfig_initvoltage_mask);
26 	voltdm->write(vpconfig, vp->vpconfig);
27 
28 	/* Trigger initVDD value copy to voltage processor */
29 	voltdm->write((vpconfig | vp->common->vpconfig_initvdd),
30 		       vp->vpconfig);
31 
32 	/* Clear initVDD copy trigger bit */
33 	voltdm->write(vpconfig, vp->vpconfig);
34 
35 	return vpconfig;
36 }
37 
38 /* Generic voltage init functions */
omap_vp_init(struct voltagedomain * voltdm)39 void __init omap_vp_init(struct voltagedomain *voltdm)
40 {
41 	struct omap_vp_instance *vp = voltdm->vp;
42 	u32 val, sys_clk_rate, timeout, waittime;
43 	u32 vddmin, vddmax, vstepmin, vstepmax;
44 
45 	if (!voltdm->pmic || !voltdm->pmic->uv_to_vsel) {
46 		pr_err("%s: No PMIC info for vdd_%s\n", __func__, voltdm->name);
47 		return;
48 	}
49 
50 	if (!voltdm->read || !voltdm->write) {
51 		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
52 			__func__, voltdm->name);
53 		return;
54 	}
55 
56 	vp->enabled = false;
57 
58 	/* Divide to avoid overflow */
59 	sys_clk_rate = voltdm->sys_clk.rate / 1000;
60 
61 	timeout = (sys_clk_rate * voltdm->pmic->vp_timeout_us) / 1000;
62 	vddmin = max(voltdm->vp_param->vddmin, voltdm->pmic->vddmin);
63 	vddmax = min(voltdm->vp_param->vddmax, voltdm->pmic->vddmax);
64 	vddmin = voltdm->pmic->uv_to_vsel(vddmin);
65 	vddmax = voltdm->pmic->uv_to_vsel(vddmax);
66 
67 	waittime = DIV_ROUND_UP(voltdm->pmic->step_size * sys_clk_rate,
68 				1000 * voltdm->pmic->slew_rate);
69 	vstepmin = voltdm->pmic->vp_vstepmin;
70 	vstepmax = voltdm->pmic->vp_vstepmax;
71 
72 	/*
73 	 * VP_CONFIG: error gain is not set here, it will be updated
74 	 * on each scale, based on OPP.
75 	 */
76 	val = (voltdm->pmic->vp_erroroffset <<
77 	       __ffs(voltdm->vp->common->vpconfig_erroroffset_mask)) |
78 		vp->common->vpconfig_timeouten;
79 	voltdm->write(val, vp->vpconfig);
80 
81 	/* VSTEPMIN */
82 	val = (waittime << vp->common->vstepmin_smpswaittimemin_shift) |
83 		(vstepmin <<  vp->common->vstepmin_stepmin_shift);
84 	voltdm->write(val, vp->vstepmin);
85 
86 	/* VSTEPMAX */
87 	val = (vstepmax << vp->common->vstepmax_stepmax_shift) |
88 		(waittime << vp->common->vstepmax_smpswaittimemax_shift);
89 	voltdm->write(val, vp->vstepmax);
90 
91 	/* VLIMITTO */
92 	val = (vddmax << vp->common->vlimitto_vddmax_shift) |
93 		(vddmin << vp->common->vlimitto_vddmin_shift) |
94 		(timeout <<  vp->common->vlimitto_timeout_shift);
95 	voltdm->write(val, vp->vlimitto);
96 }
97 
omap_vp_update_errorgain(struct voltagedomain * voltdm,unsigned long target_volt)98 int omap_vp_update_errorgain(struct voltagedomain *voltdm,
99 			     unsigned long target_volt)
100 {
101 	struct omap_volt_data *volt_data;
102 
103 	if (!voltdm->vp)
104 		return -EINVAL;
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 */
omap_vp_forceupdate_scale(struct voltagedomain * voltdm,unsigned long target_volt)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_warn("%s: vdd_%s TRANXDONE timeout exceeded. Voltage change aborted\n",
145 			__func__, voltdm->name);
146 		return -ETIMEDOUT;
147 	}
148 
149 	vpconfig = _vp_set_init_voltage(voltdm, target_volt);
150 
151 	/* Force update of voltage */
152 	voltdm->write(vpconfig | vp->common->vpconfig_forceupdate,
153 		      voltdm->vp->vpconfig);
154 
155 	/*
156 	 * Wait for TransactionDone. Typical latency is <200us.
157 	 * Depends on SMPSWAITTIMEMIN/MAX and voltage change
158 	 */
159 	timeout = 0;
160 	omap_test_timeout(vp->common->ops->check_txdone(vp->id),
161 			  VP_TRANXDONE_TIMEOUT, timeout);
162 	if (timeout >= VP_TRANXDONE_TIMEOUT)
163 		pr_err("%s: vdd_%s TRANXDONE timeout exceeded. TRANXDONE never got set after the voltage update\n",
164 		       __func__, voltdm->name);
165 
166 	omap_vc_post_scale(voltdm, target_volt, target_vsel, current_vsel);
167 
168 	/*
169 	 * Disable TransactionDone interrupt , clear all status, clear
170 	 * control registers
171 	 */
172 	timeout = 0;
173 	while (timeout++ < VP_TRANXDONE_TIMEOUT) {
174 		vp->common->ops->clear_txdone(vp->id);
175 		if (!vp->common->ops->check_txdone(vp->id))
176 			break;
177 		udelay(1);
178 	}
179 
180 	if (timeout >= VP_TRANXDONE_TIMEOUT)
181 		pr_warn("%s: vdd_%s TRANXDONE timeout exceeded while trying to clear the TRANXDONE status\n",
182 			__func__, voltdm->name);
183 
184 	/* Clear force bit */
185 	voltdm->write(vpconfig, vp->vpconfig);
186 
187 	return 0;
188 }
189 
190 /**
191  * omap_vp_enable() - API to enable a particular VP
192  * @voltdm:	pointer to the VDD whose VP is to be enabled.
193  *
194  * This API enables a particular voltage processor. Needed by the smartreflex
195  * class drivers.
196  */
omap_vp_enable(struct voltagedomain * voltdm)197 void omap_vp_enable(struct voltagedomain *voltdm)
198 {
199 	struct omap_vp_instance *vp;
200 	u32 vpconfig, volt;
201 
202 	if (!voltdm || IS_ERR(voltdm)) {
203 		pr_warn("%s: VDD specified does not exist!\n", __func__);
204 		return;
205 	}
206 
207 	vp = voltdm->vp;
208 	if (!voltdm->read || !voltdm->write) {
209 		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
210 			__func__, voltdm->name);
211 		return;
212 	}
213 
214 	/* If VP is already enabled, do nothing. Return */
215 	if (vp->enabled)
216 		return;
217 
218 	volt = voltdm_get_voltage(voltdm);
219 	if (!volt) {
220 		pr_warn("%s: unable to find current voltage for %s\n",
221 			__func__, voltdm->name);
222 		return;
223 	}
224 
225 	vpconfig = _vp_set_init_voltage(voltdm, volt);
226 
227 	/* Enable VP */
228 	vpconfig |= vp->common->vpconfig_vpenable;
229 	voltdm->write(vpconfig, vp->vpconfig);
230 
231 	vp->enabled = true;
232 }
233 
234 /**
235  * omap_vp_disable() - API to disable a particular VP
236  * @voltdm:	pointer to the VDD whose VP is to be disabled.
237  *
238  * This API disables a particular voltage processor. Needed by the smartreflex
239  * class drivers.
240  */
omap_vp_disable(struct voltagedomain * voltdm)241 void omap_vp_disable(struct voltagedomain *voltdm)
242 {
243 	struct omap_vp_instance *vp;
244 	u32 vpconfig;
245 	int timeout;
246 
247 	if (!voltdm || IS_ERR(voltdm)) {
248 		pr_warn("%s: VDD specified does not exist!\n", __func__);
249 		return;
250 	}
251 
252 	vp = voltdm->vp;
253 	if (!voltdm->read || !voltdm->write) {
254 		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
255 			__func__, voltdm->name);
256 		return;
257 	}
258 
259 	/* If VP is already disabled, do nothing. Return */
260 	if (!vp->enabled) {
261 		pr_warn("%s: Trying to disable VP for vdd_%s when it is already disabled\n",
262 			__func__, voltdm->name);
263 		return;
264 	}
265 
266 	/* Disable VP */
267 	vpconfig = voltdm->read(vp->vpconfig);
268 	vpconfig &= ~vp->common->vpconfig_vpenable;
269 	voltdm->write(vpconfig, vp->vpconfig);
270 
271 	/*
272 	 * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us
273 	 */
274 	omap_test_timeout((voltdm->read(vp->vstatus)),
275 			  VP_IDLE_TIMEOUT, timeout);
276 
277 	if (timeout >= VP_IDLE_TIMEOUT)
278 		pr_warn("%s: vdd_%s idle timedout\n", __func__, voltdm->name);
279 
280 	vp->enabled = false;
281 
282 	return;
283 }
284