Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 367 lines (311 sloc) 10.854 kb
4bc042b initial public release v1.50
Patrick Titiano authored
1 /*
2 *
3 * @Component OMAPCONF
4 * @Filename voltdm54xx.c
5 * @Description OMAP5 Voltage Domain Definitions & APIs
6 * @Author Patrick Titiano (p-titiano@ti.com)
7 * @Date 2011
8 * @Copyright Texas Instruments Incorporated
9 *
10 *
11 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
12 *
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 *
18 * Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 *
21 * Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the
24 * distribution.
25 *
26 * Neither the name of Texas Instruments Incorporated nor the names of
27 * its contributors may be used to endorse or promote products derived
28 * from this software without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
33 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
34 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
36 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
40 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 *
42 */
43
44
45 #include <voltdm54xx.h>
46 #include <dpll54xx.h>
47 #include <cpuinfo.h>
48 #include <prm54xx-defs.h>
49 #include <sr54xx.h>
50 #include <pwrdm.h>
51 #include <clock54xx.h>
52 #include <module54xx.h>
53 #include <autoadjust_table.h>
54 #include <reg.h>
55 #include <pmic.h>
56
57
58 /* #define VOLTDM54XX_DEBUG */
59 #ifdef VOLTDM54XX_DEBUG
60 #define dprintf(format, ...) printf(format, ## __VA_ARGS__)
61 #else
62 #define dprintf(format, ...)
63 #endif
64
65
66 static const char
67 voltdm54xx_names_table[VDD54XX_ID_MAX][VOLTDM_MAX_NAME_LENGTH] = {
68 "VDD_WKUP",
69 "VDD_MPU",
70 "VDD_MM",
71 "VDD_CORE"};
72
73
74 static const char
75 opp54xx_names_table[OPP54XX_ID_MAX + 1][OPP_MAX_NAME_LENGTH] = {
76 "DPLL_CASC",
77 "LOW",
78 "NOM",
79 "HIGH",
80 "SPEEDBIN",
81 "UNKNOWN"};
82
83
84 /* ------------------------------------------------------------------------*//**
85 * @FUNCTION voltdm54xx_name_get
86 * @BRIEF return voltage domain name
87 * @RETURNS voltage domain name on success
88 * NULL in case of error
89 * @param[in] id: valid voltage domain ID
90 * @DESCRIPTION return voltage domain name
91 *//*------------------------------------------------------------------------ */
92 const char *voltdm54xx_name_get(voltdm54xx_id id)
93 {
94 CHECK_ARG_LESS_THAN(id, VDD54XX_ID_MAX, NULL);
95
96 return voltdm54xx_names_table[id];
97 }
98
99
100 /* ------------------------------------------------------------------------*//**
101 * @FUNCTION opp54xx_s2id
102 * @BRIEF convert string to valid OPP ID
103 * @RETURNS OPP54XX_DPLL_CASC if s == "dpll_casc"
104 * OPP54XX_LOW if s == "low"
105 * OPP54XX_NOM if s == "nom"
106 * OPP54XX_HIGH if s == "high"
107 * OPP54XX_SB if s == "speedbin"
108 * OPP54XX_ID_MAX otherwise
109 * @param[in,out] s: string
110 * @DESCRIPTION convert string to valid OPP ID
111 *//*------------------------------------------------------------------------ */
112 opp54xx_id opp54xx_s2id(char *s)
113 {
114 CHECK_NULL_ARG(s, OPP54XX_ID_MAX);
115
116 if (strcmp(s, "dpll_casc") == 0)
117 return OPP54XX_DPLL_CASC;
118 else if (strcmp(s, "low") == 0)
119 return OPP54XX_LOW;
120 else if (strcmp(s, "nom") == 0)
121 return OPP54XX_NOM;
122 else if (strcmp(s, "high") == 0)
123 return OPP54XX_HIGH;
124 else if (strcmp(s, "speedbin") == 0)
125 return OPP54XX_SB;
126 else
127 return OPP54XX_ID_MAX;
128 }
129
130
131 /* ------------------------------------------------------------------------*//**
132 * @FUNCTION opp54xx_name_get
133 * @BRIEF return OPP name
134 * @RETURNS OPP name on success
135 * NULL in case of error
136 * @param[in] id: valid OPP ID
137 * @DESCRIPTION return OPP name
138 *//*------------------------------------------------------------------------ */
139 const char *opp54xx_name_get(opp54xx_id id)
140 {
141 CHECK_ARG_LESS_THAN(id, OPP54XX_ID_MAX + 1, NULL);
142
143 return opp54xx_names_table[id];
144 }
145
146
147 /* ------------------------------------------------------------------------*//**
148 * @FUNCTION voltdm54xx_opp_get
149 * @BRIEF find the current voltage domain OPP
150 * @RETURNS valid OPP ID in case of success
151 * OPP54XX_ID_MAX in case of error
152 * @param[in] id: voltage domain ID
153 * @DESCRIPTION find the current voltage domain OPP
154 *//*------------------------------------------------------------------------ */
155 opp54xx_id voltdm54xx_opp_get(voltdm54xx_id id)
156 {
157 opp54xx_id opp_id;
158 mod54xx_id module_id;
159 dpll54xx_id dpll_id;
160 dpll_status status;
161 double rate = 0.0, rate_por = 0.0;
162
163 CHECK_CPU(54xx, OPP54XX_ID_MAX);
164 CHECK_ARG_LESS_THAN(id, VDD54XX_ID_MAX, OPP54XX_ID_MAX);
165
166 /*
167 * Determine current OPPs by getting MPU / IVA / L3 / SARRAM rate
168 * and comparing it to POR rate.
169 */
170 switch (id) {
171 case VDD54XX_WKUP:
172 module_id = OMAP5_L4WKUP_INTERCONNECT;
173 dpll_id = DPLL54XX_CORE;
174 break;
175
176 case VDD54XX_MPU:
177 module_id = OMAP5_MPU;
178 dpll_id = DPLL54XX_MPU;
179 break;
180
181 case VDD54XX_MM:
182 module_id = OMAP5_IVA;
183 dpll_id = DPLL54XX_IVA;
184 break;
185
186 case VDD54XX_CORE:
187 module_id = OMAP5_L3_MAIN1_INTERCONNECT;
188 dpll_id = DPLL54XX_CORE;
189 break;
190
191 default:
192 return OPP54XX_ID_MAX;
193 }
194
195 /* if the DPLL clocking the selected module is stopped,
196 * reported speed will be 0 and OPP cannot be detected.
197 * Hence, if DPLL is stopped, ignore DPLL status to get
198 * the speed when the DPLL is running.
199 */
200 status = dpll54xx_status_get(dpll_id);
201 if (status == DPLL_STATUS_STOPPED)
202 rate = mod54xx_clk_rate_get(module_id, 1);
203 else
204 rate = mod54xx_clk_rate_get(module_id, 0);
205
206 dprintf("%s(%s): %s rate is %lfMHz\n", __func__,
207 voltdm54xx_name_get(id),
208 clk54xx_name_get(mod54xx_clk_get(module_id)), rate);
209
210 for (opp_id = OPP54XX_DPLL_CASC; opp_id < OPP54XX_ID_MAX; opp_id++) {
211 rate_por = mod54xx_por_clk_rate_get(module_id, opp_id);
212 dprintf("%s(%s): %s POR rate for %s is %lf\n",
213 __func__, voltdm54xx_name_get(id),
214 mod54xx_name_get(module_id),
215 opp54xx_name_get(opp_id), rate_por);
216 if ((int) rate == (int) rate_por) {
217 dprintf("%s(%s): OPP found: %s\n",
218 __func__, voltdm54xx_name_get(id),
219 opp54xx_name_get(opp_id));
220 return opp_id;
221 }
222 }
223
224 dprintf("%s(%s): OPP not found!\n", __func__, voltdm54xx_name_get(id));
225
226 return OPP54XX_ID_MAX;
227 }
228
229
230 /* ------------------------------------------------------------------------*//**
231 * @FUNCTION vr54xx_vsel2uv
232 * @BRIEF for a given rail, convert SMPS vsel command into voltage
233 * in microvolts.
234 * @RETURNS voltage in microvolts corresponding to SMPS vsel command
235 * @param[in] id: valid voltage rail
236 * @param[in] vsel: SMPS vsel command
237 * @DESCRIPTION for a given rail, convert SMPS vsel command into voltage
238 * in microvolts.
239 *//*------------------------------------------------------------------------ */
240 unsigned long vr54xx_vsel2uv(voltdm54xx_id id, unsigned char vsel)
241 {
242 unsigned long uv = 0;
243
244 CHECK_ARG_LESS_THAN(id, VDD54XX_ID_MAX, 0);
245
246 dprintf("%s(%s, 0x%X) = %luuV\n", __func__,
247 voltdm54xx_name_get(id), vsel, uv);
248 /* FIXME */
249 /* just to remove "unused parameter" warnings ... */
250 vsel = vsel;
251
252 return uv;
253 }
254
255
256 /* ------------------------------------------------------------------------*//**
257 * @FUNCTION vr54xx_vsel2volt
258 * @BRIEF for a given rail, convert SMPS vsel command into voltage
259 * (in VOLTS).
260 * @RETURNS voltage in VOLTS corresponding to SMPS vsel command
261 * @param[in] id: voltage rail
262 * @param[in] vsel: SMPS vsel command
263 * @DESCRIPTION for a given rail, convert SMPS vsel command into voltage
264 * (in VOLTS).
265 *//*------------------------------------------------------------------------ */
266 double vr54xx_vsel2volt(voltdm54xx_id id, unsigned char vsel)
267 {
268 double volt;
269
270 CHECK_ARG_LESS_THAN(id, VDD54XX_ID_MAX, 0);
271
272 volt = (double) vr54xx_vsel2uv(id, vsel);
273 volt /= (double) 1000000.0;
274
275 dprintf("%s(%s, 0x%X) = %lfV\n", __func__,
276 voltdm54xx_name_get(id), vsel, volt);
277
278 return volt;
279 }
280
281
282 /* ------------------------------------------------------------------------*//**
283 * @FUNCTION voltdm54xx_voltage_get
284 * @BRIEF find the current supply voltage of a domain
285 * @RETURNS supply voltage in case of success (>= 0.0)
286 * OMAPCONF_ERR_ARG
287 * OMAPCONF_ERR_CPU
288 * OMAPCONF_ERR_REG_ACCESS
289 * OMAPCONF_ERR_NOT_AVAILABLE
290 * @param[in] id: valid voltage domain ID
291 * @DESCRIPTION find the current supply voltage of a domain,
292 * taking care of the voltage domain state
293 * (ON/ON_LP/RET/OFF)
294 * NB: use PRCM VP VOLTAGE register to retrieve ON voltage.
295 * Hence SR/VP/VC have to be at least initialized
296 * (SR could be disabled)
297 *//*------------------------------------------------------------------------ */
298 double voltdm54xx_voltage_get(voltdm54xx_id id)
299 {
300 double volt;
301
302 CHECK_CPU(54xx, (double) OMAPCONF_ERR_CPU);
303 CHECK_ARG_LESS_THAN(id, VDD54XX_ID_MAX, (double) OMAPCONF_ERR_ARG);
304
305 /* Retrieve domain state */
306 switch (id) {
307 case VDD54XX_WKUP:
308 return (double) OMAPCONF_ERR_NOT_AVAILABLE;
309
310 case VDD54XX_MPU:
311 volt = smps_voltage_get(PMIC_SMPS_MPU);
312 break;
313 case VDD54XX_MM:
314 volt = smps_voltage_get(PMIC_SMPS_MM);
315 break;
316 case VDD54XX_CORE:
317 volt = smps_voltage_get(PMIC_SMPS_CORE);
318 break;
319
320 default:
321 return (double) OMAPCONF_ERR_ARG;
322 }
323
324 dprintf("%s(%s): volt=%lfV\n", __func__, voltdm54xx_name_get(id), volt);
325
326 return volt;
327 }
328
329
330 /* ------------------------------------------------------------------------*//**
331 * @FUNCTION voltdm54xx_voltage_set
332 * @BRIEF set voltage of given voltage domain
333 * @RETURNS 0 in case of success
334 * OMAPCONF_ERR_CPU
335 * OMAPCONF_ERR_ARG
336 * OMAPCONF_ERR_NOT_AVAILABLE
337 * OMAPCONF_ERR_REG_ACCESS
338 * OMAPCONF_ERR_INTERNAL
339 * @param[in] id: valid voltage domain ID
340 * @DESCRIPTION set voltage of given voltage domain
341 *//*------------------------------------------------------------------------ */
342 int voltdm54xx_voltage_set(voltdm54xx_id id, unsigned long uv)
343 {
344
345 CHECK_CPU(54xx, (double) OMAPCONF_ERR_CPU);
346 CHECK_ARG_LESS_THAN(id, VDD54XX_ID_MAX, (double) OMAPCONF_ERR_ARG);
347
348 /* Retrieve domain state */
349 switch (id) {
350 case VDD54XX_WKUP:
351 return OMAPCONF_ERR_NOT_AVAILABLE;
352
353 case VDD54XX_MPU:
354 return smps_voltage_set(PMIC_SMPS_MPU, uv);
355 break;
356 case VDD54XX_MM:
357 return smps_voltage_set(PMIC_SMPS_MM, uv);
358 break;
359 case VDD54XX_CORE:
360 return smps_voltage_set(PMIC_SMPS_CORE, uv);
361 break;
362
363 default:
364 return OMAPCONF_ERR_ARG;
365 }
366 }
Something went wrong with that request. Please try again.