OMAP2+: powerdomain: add voltage domain lookup during register
[deliverable/linux.git] / arch / arm / mach-omap2 / voltage.c
CommitLineData
2f34ce81
TG
1/*
2 * OMAP3/OMAP4 Voltage Management Routines
3 *
4 * Author: Thara Gopinath <thara@ti.com>
5 *
6 * Copyright (C) 2007 Texas Instruments, Inc.
7 * Rajendra Nayak <rnayak@ti.com>
8 * Lesly A M <x0080970@ti.com>
9 *
c0718df4 10 * Copyright (C) 2008, 2011 Nokia Corporation
2f34ce81 11 * Kalle Jokiniemi
c0718df4 12 * Paul Walmsley
2f34ce81
TG
13 *
14 * Copyright (C) 2010 Texas Instruments, Inc.
15 * Thara Gopinath <thara@ti.com>
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License version 2 as
19 * published by the Free Software Foundation.
20 */
21
22#include <linux/delay.h>
23#include <linux/io.h>
24#include <linux/clk.h>
25#include <linux/err.h>
26#include <linux/debugfs.h>
27#include <linux/slab.h>
28
29#include <plat/common.h>
2f34ce81
TG
30
31#include "prm-regbits-34xx.h"
bd38107b
TG
32#include "prm-regbits-44xx.h"
33#include "prm44xx.h"
34#include "prcm44xx.h"
35#include "prminst44xx.h"
2f34ce81
TG
36#include "control.h"
37
e1d6f472
PW
38#include "voltage.h"
39
c0718df4
PW
40#include "vc.h"
41#include "vp.h"
42
81a60482 43static LIST_HEAD(voltdm_list);
2f34ce81 44
81a60482 45#define VOLTAGE_DIR_SIZE 16
2f34ce81
TG
46static struct dentry *voltage_dir;
47
48/* Init function pointers */
81a60482 49static int vp_forceupdate_scale_voltage(struct voltagedomain *voltdm,
c0718df4 50 unsigned long target_volt);
2f34ce81
TG
51
52static u32 omap3_voltage_read_reg(u16 mod, u8 offset)
53{
54 return omap2_prm_read_mod_reg(mod, offset);
55}
56
57static void omap3_voltage_write_reg(u32 val, u16 mod, u8 offset)
58{
59 omap2_prm_write_mod_reg(val, mod, offset);
60}
61
bd38107b
TG
62static u32 omap4_voltage_read_reg(u16 mod, u8 offset)
63{
64 return omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
65 mod, offset);
66}
67
68static void omap4_voltage_write_reg(u32 val, u16 mod, u8 offset)
69{
70 omap4_prminst_write_inst_reg(val, OMAP4430_PRM_PARTITION, mod, offset);
71}
72
81a60482 73static int __init _config_common_vdd_data(struct voltagedomain *voltdm)
c0718df4
PW
74{
75 char *sys_ck_name;
76 struct clk *sys_ck;
77 u32 sys_clk_speed, timeout_val, waittime;
81a60482 78 struct omap_vdd_info *vdd = voltdm->vdd;
c0718df4
PW
79
80 /*
81 * XXX Clockfw should handle this, or this should be in a
82 * struct record
83 */
84 if (cpu_is_omap24xx() || cpu_is_omap34xx())
85 sys_ck_name = "sys_ck";
86 else if (cpu_is_omap44xx())
87 sys_ck_name = "sys_clkin_ck";
88 else
89 return -EINVAL;
90
91 /*
92 * Sys clk rate is require to calculate vp timeout value and
93 * smpswaittimemin and smpswaittimemax.
94 */
95 sys_ck = clk_get(NULL, sys_ck_name);
96 if (IS_ERR(sys_ck)) {
97 pr_warning("%s: Could not get the sys clk to calculate"
81a60482 98 "various vdd_%s params\n", __func__, voltdm->name);
c0718df4
PW
99 return -EINVAL;
100 }
101 sys_clk_speed = clk_get_rate(sys_ck);
102 clk_put(sys_ck);
103 /* Divide to avoid overflow */
104 sys_clk_speed /= 1000;
105
106 /* Generic voltage parameters */
c0718df4
PW
107 vdd->volt_scale = vp_forceupdate_scale_voltage;
108 vdd->vp_enabled = false;
109
110 vdd->vp_rt_data.vpconfig_erroroffset =
111 (vdd->pmic_info->vp_erroroffset <<
112 vdd->vp_data->vp_common->vpconfig_erroroffset_shift);
113
114 timeout_val = (sys_clk_speed * vdd->pmic_info->vp_timeout_us) / 1000;
115 vdd->vp_rt_data.vlimitto_timeout = timeout_val;
116 vdd->vp_rt_data.vlimitto_vddmin = vdd->pmic_info->vp_vddmin;
117 vdd->vp_rt_data.vlimitto_vddmax = vdd->pmic_info->vp_vddmax;
118
119 waittime = ((vdd->pmic_info->step_size / vdd->pmic_info->slew_rate) *
120 sys_clk_speed) / 1000;
121 vdd->vp_rt_data.vstepmin_smpswaittimemin = waittime;
122 vdd->vp_rt_data.vstepmax_smpswaittimemax = waittime;
123 vdd->vp_rt_data.vstepmin_stepmin = vdd->pmic_info->vp_vstepmin;
124 vdd->vp_rt_data.vstepmax_stepmax = vdd->pmic_info->vp_vstepmax;
125
126 return 0;
127}
128
077fceca
TG
129/* Voltage debugfs support */
130static int vp_volt_debug_get(void *data, u64 *val)
131{
81a60482
KH
132 struct voltagedomain *voltdm = (struct voltagedomain *)data;
133 struct omap_vdd_info *vdd = voltdm->vdd;
077fceca
TG
134 u8 vsel;
135
136 if (!vdd) {
137 pr_warning("Wrong paramater passed\n");
138 return -EINVAL;
139 }
140
a7460daf 141 vsel = vdd->read_reg(vdd->vp_data->vp_common->prm_mod, vdd->vp_data->voltage);
077fceca
TG
142
143 if (!vdd->pmic_info->vsel_to_uv) {
144 pr_warning("PMIC function to convert vsel to voltage"
145 "in uV not registerd\n");
146 return -EINVAL;
147 }
148
149 *val = vdd->pmic_info->vsel_to_uv(vsel);
150 return 0;
151}
152
153static int nom_volt_debug_get(void *data, u64 *val)
154{
81a60482 155 struct voltagedomain *voltdm = (struct voltagedomain *)data;
077fceca 156
81a60482 157 if (!voltdm) {
077fceca
TG
158 pr_warning("Wrong paramater passed\n");
159 return -EINVAL;
160 }
161
81a60482 162 *val = omap_voltage_get_nom_volt(voltdm);
077fceca
TG
163
164 return 0;
165}
166
167DEFINE_SIMPLE_ATTRIBUTE(vp_volt_debug_fops, vp_volt_debug_get, NULL, "%llu\n");
168DEFINE_SIMPLE_ATTRIBUTE(nom_volt_debug_fops, nom_volt_debug_get, NULL,
169 "%llu\n");
81a60482 170static void vp_latch_vsel(struct voltagedomain *voltdm)
2f34ce81
TG
171{
172 u32 vpconfig;
2f34ce81
TG
173 unsigned long uvdc;
174 char vsel;
81a60482 175 struct omap_vdd_info *vdd = voltdm->vdd;
2f34ce81 176
81a60482 177 uvdc = omap_voltage_get_nom_volt(voltdm);
2f34ce81
TG
178 if (!uvdc) {
179 pr_warning("%s: unable to find current voltage for vdd_%s\n",
81a60482 180 __func__, voltdm->name);
2f34ce81
TG
181 return;
182 }
183
184 if (!vdd->pmic_info || !vdd->pmic_info->uv_to_vsel) {
185 pr_warning("%s: PMIC function to convert voltage in uV to"
186 " vsel not registered\n", __func__);
187 return;
188 }
189
2f34ce81
TG
190 vsel = vdd->pmic_info->uv_to_vsel(uvdc);
191
a7460daf 192 vpconfig = vdd->read_reg(vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
c0718df4
PW
193 vpconfig &= ~(vdd->vp_data->vp_common->vpconfig_initvoltage_mask |
194 vdd->vp_data->vp_common->vpconfig_initvdd);
195 vpconfig |= vsel << vdd->vp_data->vp_common->vpconfig_initvoltage_shift;
2f34ce81 196
a7460daf 197 vdd->write_reg(vpconfig, vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
2f34ce81
TG
198
199 /* Trigger initVDD value copy to voltage processor */
c0718df4 200 vdd->write_reg((vpconfig | vdd->vp_data->vp_common->vpconfig_initvdd),
a7460daf 201 vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
2f34ce81
TG
202
203 /* Clear initVDD copy trigger bit */
a7460daf 204 vdd->write_reg(vpconfig, vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
2f34ce81
TG
205}
206
207/* Generic voltage init functions */
81a60482 208static void __init vp_init(struct voltagedomain *voltdm)
2f34ce81 209{
81a60482 210 struct omap_vdd_info *vdd = voltdm->vdd;
2f34ce81 211 u32 vp_val;
2f34ce81
TG
212
213 if (!vdd->read_reg || !vdd->write_reg) {
214 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
81a60482 215 __func__, voltdm->name);
2f34ce81
TG
216 return;
217 }
218
c0718df4
PW
219 vp_val = vdd->vp_rt_data.vpconfig_erroroffset |
220 (vdd->vp_rt_data.vpconfig_errorgain <<
221 vdd->vp_data->vp_common->vpconfig_errorgain_shift) |
222 vdd->vp_data->vp_common->vpconfig_timeouten;
a7460daf 223 vdd->write_reg(vp_val, vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
c0718df4
PW
224
225 vp_val = ((vdd->vp_rt_data.vstepmin_smpswaittimemin <<
226 vdd->vp_data->vp_common->vstepmin_smpswaittimemin_shift) |
227 (vdd->vp_rt_data.vstepmin_stepmin <<
228 vdd->vp_data->vp_common->vstepmin_stepmin_shift));
a7460daf 229 vdd->write_reg(vp_val, vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vstepmin);
c0718df4
PW
230
231 vp_val = ((vdd->vp_rt_data.vstepmax_smpswaittimemax <<
232 vdd->vp_data->vp_common->vstepmax_smpswaittimemax_shift) |
233 (vdd->vp_rt_data.vstepmax_stepmax <<
234 vdd->vp_data->vp_common->vstepmax_stepmax_shift));
a7460daf 235 vdd->write_reg(vp_val, vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vstepmax);
c0718df4
PW
236
237 vp_val = ((vdd->vp_rt_data.vlimitto_vddmax <<
238 vdd->vp_data->vp_common->vlimitto_vddmax_shift) |
239 (vdd->vp_rt_data.vlimitto_vddmin <<
240 vdd->vp_data->vp_common->vlimitto_vddmin_shift) |
241 (vdd->vp_rt_data.vlimitto_timeout <<
242 vdd->vp_data->vp_common->vlimitto_timeout_shift));
a7460daf 243 vdd->write_reg(vp_val, vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vlimitto);
2f34ce81
TG
244}
245
81a60482 246static void __init vdd_debugfs_init(struct voltagedomain *voltdm)
2f34ce81
TG
247{
248 char *name;
81a60482 249 struct omap_vdd_info *vdd = voltdm->vdd;
2f34ce81
TG
250
251 name = kzalloc(VOLTAGE_DIR_SIZE, GFP_KERNEL);
252 if (!name) {
253 pr_warning("%s: Unable to allocate memory for debugfs"
254 " directory name for vdd_%s",
81a60482 255 __func__, voltdm->name);
2f34ce81
TG
256 return;
257 }
258 strcpy(name, "vdd_");
81a60482 259 strcat(name, voltdm->name);
2f34ce81
TG
260
261 vdd->debug_dir = debugfs_create_dir(name, voltage_dir);
62270119 262 kfree(name);
2f34ce81
TG
263 if (IS_ERR(vdd->debug_dir)) {
264 pr_warning("%s: Unable to create debugfs directory for"
81a60482 265 " vdd_%s\n", __func__, voltdm->name);
2f34ce81 266 vdd->debug_dir = NULL;
077fceca 267 return;
2f34ce81 268 }
077fceca
TG
269
270 (void) debugfs_create_x16("vp_errorgain", S_IRUGO, vdd->debug_dir,
c0718df4 271 &(vdd->vp_rt_data.vpconfig_errorgain));
077fceca
TG
272 (void) debugfs_create_x16("vp_smpswaittimemin", S_IRUGO,
273 vdd->debug_dir,
c0718df4 274 &(vdd->vp_rt_data.vstepmin_smpswaittimemin));
077fceca 275 (void) debugfs_create_x8("vp_stepmin", S_IRUGO, vdd->debug_dir,
c0718df4 276 &(vdd->vp_rt_data.vstepmin_stepmin));
077fceca
TG
277 (void) debugfs_create_x16("vp_smpswaittimemax", S_IRUGO,
278 vdd->debug_dir,
c0718df4 279 &(vdd->vp_rt_data.vstepmax_smpswaittimemax));
077fceca 280 (void) debugfs_create_x8("vp_stepmax", S_IRUGO, vdd->debug_dir,
c0718df4 281 &(vdd->vp_rt_data.vstepmax_stepmax));
077fceca 282 (void) debugfs_create_x8("vp_vddmax", S_IRUGO, vdd->debug_dir,
c0718df4 283 &(vdd->vp_rt_data.vlimitto_vddmax));
077fceca 284 (void) debugfs_create_x8("vp_vddmin", S_IRUGO, vdd->debug_dir,
c0718df4 285 &(vdd->vp_rt_data.vlimitto_vddmin));
077fceca 286 (void) debugfs_create_x16("vp_timeout", S_IRUGO, vdd->debug_dir,
c0718df4 287 &(vdd->vp_rt_data.vlimitto_timeout));
077fceca 288 (void) debugfs_create_file("curr_vp_volt", S_IRUGO, vdd->debug_dir,
81a60482 289 (void *) voltdm, &vp_volt_debug_fops);
077fceca 290 (void) debugfs_create_file("curr_nominal_volt", S_IRUGO,
81a60482 291 vdd->debug_dir, (void *) voltdm,
077fceca 292 &nom_volt_debug_fops);
2f34ce81
TG
293}
294
295/* Voltage scale and accessory APIs */
81a60482 296static int _pre_volt_scale(struct voltagedomain *voltdm,
2f34ce81
TG
297 unsigned long target_volt, u8 *target_vsel, u8 *current_vsel)
298{
81a60482 299 struct omap_vdd_info *vdd = voltdm->vdd;
2f34ce81 300 struct omap_volt_data *volt_data;
c0718df4
PW
301 const struct omap_vc_common_data *vc_common;
302 const struct omap_vp_common_data *vp_common;
2f34ce81 303 u32 vc_cmdval, vp_errgain_val;
c0718df4
PW
304
305 vc_common = vdd->vc_data->vc_common;
306 vp_common = vdd->vp_data->vp_common;
2f34ce81
TG
307
308 /* Check if suffiecient pmic info is available for this vdd */
309 if (!vdd->pmic_info) {
310 pr_err("%s: Insufficient pmic info to scale the vdd_%s\n",
81a60482 311 __func__, voltdm->name);
2f34ce81
TG
312 return -EINVAL;
313 }
314
315 if (!vdd->pmic_info->uv_to_vsel) {
316 pr_err("%s: PMIC function to convert voltage in uV to"
317 "vsel not registered. Hence unable to scale voltage"
81a60482 318 "for vdd_%s\n", __func__, voltdm->name);
2f34ce81
TG
319 return -ENODATA;
320 }
321
322 if (!vdd->read_reg || !vdd->write_reg) {
323 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
81a60482 324 __func__, voltdm->name);
2f34ce81
TG
325 return -EINVAL;
326 }
327
2f34ce81 328 /* Get volt_data corresponding to target_volt */
81a60482 329 volt_data = omap_voltage_get_voltdata(voltdm, target_volt);
2f34ce81
TG
330 if (IS_ERR(volt_data))
331 volt_data = NULL;
332
333 *target_vsel = vdd->pmic_info->uv_to_vsel(target_volt);
a7460daf 334 *current_vsel = vdd->read_reg(vdd->vp_data->vp_common->prm_mod, vdd->vp_data->voltage);
2f34ce81
TG
335
336 /* Setting the ON voltage to the new target voltage */
a7460daf 337 vc_cmdval = vdd->read_reg(vdd->vc_data->vc_common->prm_mod, vdd->vc_data->cmdval_reg);
c0718df4
PW
338 vc_cmdval &= ~vc_common->cmd_on_mask;
339 vc_cmdval |= (*target_vsel << vc_common->cmd_on_shift);
a7460daf 340 vdd->write_reg(vc_cmdval, vdd->vc_data->vc_common->prm_mod, vdd->vc_data->cmdval_reg);
2f34ce81
TG
341
342 /* Setting vp errorgain based on the voltage */
343 if (volt_data) {
a7460daf 344 vp_errgain_val = vdd->read_reg(vdd->vp_data->vp_common->prm_mod,
c0718df4
PW
345 vdd->vp_data->vpconfig);
346 vdd->vp_rt_data.vpconfig_errorgain = volt_data->vp_errgain;
347 vp_errgain_val &= ~vp_common->vpconfig_errorgain_mask;
348 vp_errgain_val |= vdd->vp_rt_data.vpconfig_errorgain <<
349 vp_common->vpconfig_errorgain_shift;
a7460daf 350 vdd->write_reg(vp_errgain_val, vdd->vp_data->vp_common->prm_mod,
c0718df4 351 vdd->vp_data->vpconfig);
2f34ce81
TG
352 }
353
354 return 0;
355}
356
81a60482 357static void _post_volt_scale(struct voltagedomain *voltdm,
2f34ce81
TG
358 unsigned long target_volt, u8 target_vsel, u8 current_vsel)
359{
81a60482 360 struct omap_vdd_info *vdd = voltdm->vdd;
2f34ce81
TG
361 u32 smps_steps = 0, smps_delay = 0;
362
363 smps_steps = abs(target_vsel - current_vsel);
364 /* SMPS slew rate / step size. 2us added as buffer. */
365 smps_delay = ((smps_steps * vdd->pmic_info->step_size) /
366 vdd->pmic_info->slew_rate) + 2;
367 udelay(smps_delay);
368
369 vdd->curr_volt = target_volt;
370}
371
372/* vc_bypass_scale_voltage - VC bypass method of voltage scaling */
81a60482 373static int vc_bypass_scale_voltage(struct voltagedomain *voltdm,
2f34ce81
TG
374 unsigned long target_volt)
375{
81a60482 376 struct omap_vdd_info *vdd = voltdm->vdd;
2f34ce81
TG
377 u32 loop_cnt = 0, retries_cnt = 0;
378 u32 vc_valid, vc_bypass_val_reg, vc_bypass_value;
2f34ce81
TG
379 u8 target_vsel, current_vsel;
380 int ret;
381
81a60482 382 ret = _pre_volt_scale(voltdm, target_volt, &target_vsel, &current_vsel);
2f34ce81
TG
383 if (ret)
384 return ret;
385
c0718df4
PW
386 vc_valid = vdd->vc_data->vc_common->valid;
387 vc_bypass_val_reg = vdd->vc_data->vc_common->bypass_val_reg;
388 vc_bypass_value = (target_vsel << vdd->vc_data->vc_common->data_shift) |
2f34ce81 389 (vdd->pmic_info->pmic_reg <<
c0718df4 390 vdd->vc_data->vc_common->regaddr_shift) |
2f34ce81 391 (vdd->pmic_info->i2c_slave_addr <<
c0718df4 392 vdd->vc_data->vc_common->slaveaddr_shift);
2f34ce81 393
a7460daf
KH
394 vdd->write_reg(vc_bypass_value, vdd->vc_data->vc_common->prm_mod, vc_bypass_val_reg);
395 vdd->write_reg(vc_bypass_value | vc_valid, vdd->vc_data->vc_common->prm_mod,
c0718df4 396 vc_bypass_val_reg);
2f34ce81 397
a7460daf 398 vc_bypass_value = vdd->read_reg(vdd->vc_data->vc_common->prm_mod, vc_bypass_val_reg);
2f34ce81
TG
399 /*
400 * Loop till the bypass command is acknowledged from the SMPS.
401 * NOTE: This is legacy code. The loop count and retry count needs
402 * to be revisited.
403 */
404 while (!(vc_bypass_value & vc_valid)) {
405 loop_cnt++;
406
407 if (retries_cnt > 10) {
408 pr_warning("%s: Retry count exceeded\n", __func__);
409 return -ETIMEDOUT;
410 }
411
412 if (loop_cnt > 50) {
413 retries_cnt++;
414 loop_cnt = 0;
415 udelay(10);
416 }
a7460daf 417 vc_bypass_value = vdd->read_reg(vdd->vc_data->vc_common->prm_mod,
c0718df4 418 vc_bypass_val_reg);
2f34ce81
TG
419 }
420
81a60482 421 _post_volt_scale(voltdm, target_volt, target_vsel, current_vsel);
2f34ce81
TG
422 return 0;
423}
424
425/* VP force update method of voltage scaling */
81a60482 426static int vp_forceupdate_scale_voltage(struct voltagedomain *voltdm,
2f34ce81
TG
427 unsigned long target_volt)
428{
81a60482 429 struct omap_vdd_info *vdd = voltdm->vdd;
2f34ce81 430 u32 vpconfig;
c39263c3 431 u8 target_vsel, current_vsel;
2f34ce81
TG
432 int ret, timeout = 0;
433
81a60482 434 ret = _pre_volt_scale(voltdm, target_volt, &target_vsel, &current_vsel);
2f34ce81
TG
435 if (ret)
436 return ret;
437
2f34ce81
TG
438 /*
439 * Clear all pending TransactionDone interrupt/status. Typical latency
440 * is <3us
441 */
442 while (timeout++ < VP_TRANXDONE_TIMEOUT) {
c0718df4 443 vdd->write_reg(vdd->vp_data->prm_irqst_data->tranxdone_status,
c39263c3
KH
444 vdd->prm_irqst_mod, vdd->prm_irqst_reg);
445 if (!(vdd->read_reg(vdd->prm_irqst_mod, vdd->prm_irqst_reg) &
c0718df4
PW
446 vdd->vp_data->prm_irqst_data->tranxdone_status))
447 break;
2f34ce81
TG
448 udelay(1);
449 }
450 if (timeout >= VP_TRANXDONE_TIMEOUT) {
451 pr_warning("%s: vdd_%s TRANXDONE timeout exceeded."
81a60482 452 "Voltage change aborted", __func__, voltdm->name);
2f34ce81
TG
453 return -ETIMEDOUT;
454 }
455
456 /* Configure for VP-Force Update */
a7460daf 457 vpconfig = vdd->read_reg(vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
c0718df4
PW
458 vpconfig &= ~(vdd->vp_data->vp_common->vpconfig_initvdd |
459 vdd->vp_data->vp_common->vpconfig_forceupdate |
460 vdd->vp_data->vp_common->vpconfig_initvoltage_mask);
2f34ce81 461 vpconfig |= ((target_vsel <<
c0718df4 462 vdd->vp_data->vp_common->vpconfig_initvoltage_shift));
a7460daf 463 vdd->write_reg(vpconfig, vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
2f34ce81
TG
464
465 /* Trigger initVDD value copy to voltage processor */
c0718df4 466 vpconfig |= vdd->vp_data->vp_common->vpconfig_initvdd;
a7460daf 467 vdd->write_reg(vpconfig, vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
2f34ce81
TG
468
469 /* Force update of voltage */
c0718df4 470 vpconfig |= vdd->vp_data->vp_common->vpconfig_forceupdate;
a7460daf 471 vdd->write_reg(vpconfig, vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
2f34ce81
TG
472
473 /*
474 * Wait for TransactionDone. Typical latency is <200us.
475 * Depends on SMPSWAITTIMEMIN/MAX and voltage change
476 */
477 timeout = 0;
c39263c3
KH
478 omap_test_timeout((vdd->read_reg(vdd->prm_irqst_mod,
479 vdd->prm_irqst_reg) &
c0718df4
PW
480 vdd->vp_data->prm_irqst_data->tranxdone_status),
481 VP_TRANXDONE_TIMEOUT, timeout);
2f34ce81
TG
482 if (timeout >= VP_TRANXDONE_TIMEOUT)
483 pr_err("%s: vdd_%s TRANXDONE timeout exceeded."
484 "TRANXDONE never got set after the voltage update\n",
81a60482 485 __func__, voltdm->name);
2f34ce81 486
81a60482 487 _post_volt_scale(voltdm, target_volt, target_vsel, current_vsel);
2f34ce81
TG
488
489 /*
490 * Disable TransactionDone interrupt , clear all status, clear
491 * control registers
492 */
493 timeout = 0;
494 while (timeout++ < VP_TRANXDONE_TIMEOUT) {
c0718df4 495 vdd->write_reg(vdd->vp_data->prm_irqst_data->tranxdone_status,
c39263c3
KH
496 vdd->prm_irqst_mod, vdd->prm_irqst_reg);
497 if (!(vdd->read_reg(vdd->prm_irqst_mod, vdd->prm_irqst_reg) &
c0718df4
PW
498 vdd->vp_data->prm_irqst_data->tranxdone_status))
499 break;
2f34ce81
TG
500 udelay(1);
501 }
502
503 if (timeout >= VP_TRANXDONE_TIMEOUT)
504 pr_warning("%s: vdd_%s TRANXDONE timeout exceeded while trying"
505 "to clear the TRANXDONE status\n",
81a60482 506 __func__, voltdm->name);
2f34ce81 507
a7460daf 508 vpconfig = vdd->read_reg(vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
2f34ce81 509 /* Clear initVDD copy trigger bit */
c0718df4 510 vpconfig &= ~vdd->vp_data->vp_common->vpconfig_initvdd;
a7460daf 511 vdd->write_reg(vpconfig, vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
2f34ce81 512 /* Clear force bit */
c0718df4 513 vpconfig &= ~vdd->vp_data->vp_common->vpconfig_forceupdate;
a7460daf 514 vdd->write_reg(vpconfig, vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
2f34ce81
TG
515
516 return 0;
517}
518
81a60482 519static void __init omap3_vfsm_init(struct voltagedomain *voltdm)
c0718df4 520{
81a60482
KH
521 struct omap_vdd_info *vdd = voltdm->vdd;
522
c0718df4
PW
523 /*
524 * Voltage Manager FSM parameters init
525 * XXX This data should be passed in from the board file
526 */
a7460daf
KH
527 vdd->write_reg(OMAP3_CLKSETUP, vdd->vc_data->vc_common->prm_mod, OMAP3_PRM_CLKSETUP_OFFSET);
528 vdd->write_reg(OMAP3_VOLTOFFSET, vdd->vc_data->vc_common->prm_mod,
c0718df4 529 OMAP3_PRM_VOLTOFFSET_OFFSET);
a7460daf 530 vdd->write_reg(OMAP3_VOLTSETUP2, vdd->vc_data->vc_common->prm_mod,
c0718df4
PW
531 OMAP3_PRM_VOLTSETUP2_OFFSET);
532}
2f34ce81 533
81a60482 534static void __init omap3_vc_init(struct voltagedomain *voltdm)
2f34ce81 535{
81a60482 536 struct omap_vdd_info *vdd = voltdm->vdd;
2f34ce81 537 static bool is_initialized;
c0718df4
PW
538 u8 on_vsel, onlp_vsel, ret_vsel, off_vsel;
539 u32 vc_val;
2f34ce81 540
c0718df4 541 if (is_initialized)
2f34ce81 542 return;
2f34ce81
TG
543
544 /* Set up the on, inactive, retention and off voltage */
545 on_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->on_volt);
546 onlp_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->onlp_volt);
547 ret_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->ret_volt);
548 off_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->off_volt);
c0718df4
PW
549 vc_val = ((on_vsel << vdd->vc_data->vc_common->cmd_on_shift) |
550 (onlp_vsel << vdd->vc_data->vc_common->cmd_onlp_shift) |
551 (ret_vsel << vdd->vc_data->vc_common->cmd_ret_shift) |
552 (off_vsel << vdd->vc_data->vc_common->cmd_off_shift));
a7460daf 553 vdd->write_reg(vc_val, vdd->vc_data->vc_common->prm_mod, vdd->vc_data->cmdval_reg);
2f34ce81 554
c0718df4
PW
555 /*
556 * Generic VC parameters init
557 * XXX This data should be abstracted out
558 */
a7460daf 559 vdd->write_reg(OMAP3430_CMD1_MASK | OMAP3430_RAV1_MASK, vdd->vc_data->vc_common->prm_mod,
2f34ce81 560 OMAP3_PRM_VC_CH_CONF_OFFSET);
a7460daf 561 vdd->write_reg(OMAP3430_MCODE_SHIFT | OMAP3430_HSEN_MASK, vdd->vc_data->vc_common->prm_mod,
2f34ce81 562 OMAP3_PRM_VC_I2C_CFG_OFFSET);
c0718df4 563
81a60482 564 omap3_vfsm_init(voltdm);
c0718df4 565
2f34ce81
TG
566 is_initialized = true;
567}
568
c0718df4
PW
569
570/* OMAP4 specific voltage init functions */
81a60482 571static void __init omap4_vc_init(struct voltagedomain *voltdm)
2f34ce81 572{
81a60482 573 struct omap_vdd_info *vdd = voltdm->vdd;
c0718df4
PW
574 static bool is_initialized;
575 u32 vc_val;
2f34ce81 576
c0718df4
PW
577 if (is_initialized)
578 return;
2f34ce81 579
c0718df4 580 /* TODO: Configure setup times and CMD_VAL values*/
2f34ce81
TG
581
582 /*
c0718df4
PW
583 * Generic VC parameters init
584 * XXX This data should be abstracted out
2f34ce81 585 */
c0718df4
PW
586 vc_val = (OMAP4430_RAV_VDD_MPU_L_MASK | OMAP4430_CMD_VDD_MPU_L_MASK |
587 OMAP4430_RAV_VDD_IVA_L_MASK | OMAP4430_CMD_VDD_IVA_L_MASK |
588 OMAP4430_RAV_VDD_CORE_L_MASK | OMAP4430_CMD_VDD_CORE_L_MASK);
a7460daf 589 vdd->write_reg(vc_val, vdd->vc_data->vc_common->prm_mod, OMAP4_PRM_VC_CFG_CHANNEL_OFFSET);
2f34ce81 590
c0718df4
PW
591 /* XXX These are magic numbers and do not belong! */
592 vc_val = (0x60 << OMAP4430_SCLL_SHIFT | 0x26 << OMAP4430_SCLH_SHIFT);
a7460daf 593 vdd->write_reg(vc_val, vdd->vc_data->vc_common->prm_mod, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET);
2f34ce81 594
c0718df4 595 is_initialized = true;
2f34ce81
TG
596}
597
81a60482 598static void __init omap_vc_init(struct voltagedomain *voltdm)
bd38107b 599{
81a60482 600 struct omap_vdd_info *vdd = voltdm->vdd;
bd38107b 601 u32 vc_val;
bd38107b
TG
602
603 if (!vdd->pmic_info || !vdd->pmic_info->uv_to_vsel) {
604 pr_err("%s: PMIC info requried to configure vc for"
605 "vdd_%s not populated.Hence cannot initialize vc\n",
81a60482 606 __func__, voltdm->name);
bd38107b
TG
607 return;
608 }
609
610 if (!vdd->read_reg || !vdd->write_reg) {
611 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
81a60482 612 __func__, voltdm->name);
bd38107b
TG
613 return;
614 }
615
bd38107b 616 /* Set up the SMPS_SA(i2c slave address in VC */
a7460daf 617 vc_val = vdd->read_reg(vdd->vc_data->vc_common->prm_mod,
c0718df4
PW
618 vdd->vc_data->vc_common->smps_sa_reg);
619 vc_val &= ~vdd->vc_data->smps_sa_mask;
620 vc_val |= vdd->pmic_info->i2c_slave_addr << vdd->vc_data->smps_sa_shift;
a7460daf 621 vdd->write_reg(vc_val, vdd->vc_data->vc_common->prm_mod,
c0718df4 622 vdd->vc_data->vc_common->smps_sa_reg);
bd38107b
TG
623
624 /* Setup the VOLRA(pmic reg addr) in VC */
a7460daf 625 vc_val = vdd->read_reg(vdd->vc_data->vc_common->prm_mod,
c0718df4
PW
626 vdd->vc_data->vc_common->smps_volra_reg);
627 vc_val &= ~vdd->vc_data->smps_volra_mask;
628 vc_val |= vdd->pmic_info->pmic_reg << vdd->vc_data->smps_volra_shift;
a7460daf 629 vdd->write_reg(vc_val, vdd->vc_data->vc_common->prm_mod,
c0718df4
PW
630 vdd->vc_data->vc_common->smps_volra_reg);
631
632 /* Configure the setup times */
a7460daf 633 vc_val = vdd->read_reg(vdd->vc_data->vc_common->prm_mod, vdd->vfsm->voltsetup_reg);
c0718df4
PW
634 vc_val &= ~vdd->vfsm->voltsetup_mask;
635 vc_val |= vdd->pmic_info->volt_setup_time <<
636 vdd->vfsm->voltsetup_shift;
a7460daf 637 vdd->write_reg(vc_val, vdd->vc_data->vc_common->prm_mod, vdd->vfsm->voltsetup_reg);
bd38107b 638
c0718df4 639 if (cpu_is_omap34xx())
81a60482 640 omap3_vc_init(voltdm);
c0718df4 641 else if (cpu_is_omap44xx())
81a60482 642 omap4_vc_init(voltdm);
bd38107b
TG
643}
644
81a60482 645static int __init omap_vdd_data_configure(struct voltagedomain *voltdm)
bd38107b 646{
81a60482 647 struct omap_vdd_info *vdd = voltdm->vdd;
c0718df4 648 int ret = -EINVAL;
bd38107b
TG
649
650 if (!vdd->pmic_info) {
651 pr_err("%s: PMIC info requried to configure vdd_%s not"
652 "populated.Hence cannot initialize vdd_%s\n",
81a60482 653 __func__, voltdm->name, voltdm->name);
c0718df4 654 goto ovdc_out;
bd38107b
TG
655 }
656
81a60482 657 if (IS_ERR_VALUE(_config_common_vdd_data(voltdm)))
c0718df4 658 goto ovdc_out;
bd38107b 659
c0718df4
PW
660 if (cpu_is_omap34xx()) {
661 vdd->read_reg = omap3_voltage_read_reg;
662 vdd->write_reg = omap3_voltage_write_reg;
663 ret = 0;
664 } else if (cpu_is_omap44xx()) {
665 vdd->read_reg = omap4_voltage_read_reg;
666 vdd->write_reg = omap4_voltage_write_reg;
667 ret = 0;
bd38107b 668 }
bd38107b 669
c0718df4
PW
670ovdc_out:
671 return ret;
bd38107b
TG
672}
673
2f34ce81
TG
674/* Public functions */
675/**
676 * omap_voltage_get_nom_volt() - Gets the current non-auto-compensated voltage
677 * @voltdm: pointer to the VDD for which current voltage info is needed
678 *
679 * API to get the current non-auto-compensated voltage for a VDD.
680 * Returns 0 in case of error else returns the current voltage for the VDD.
681 */
682unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm)
683{
684 struct omap_vdd_info *vdd;
685
686 if (!voltdm || IS_ERR(voltdm)) {
687 pr_warning("%s: VDD specified does not exist!\n", __func__);
688 return 0;
689 }
690
81a60482 691 vdd = voltdm->vdd;
2f34ce81
TG
692
693 return vdd->curr_volt;
694}
695
696/**
697 * omap_vp_get_curr_volt() - API to get the current vp voltage.
698 * @voltdm: pointer to the VDD.
699 *
700 * This API returns the current voltage for the specified voltage processor
701 */
702unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm)
703{
704 struct omap_vdd_info *vdd;
705 u8 curr_vsel;
706
707 if (!voltdm || IS_ERR(voltdm)) {
708 pr_warning("%s: VDD specified does not exist!\n", __func__);
709 return 0;
710 }
711
81a60482 712 vdd = voltdm->vdd;
2f34ce81
TG
713 if (!vdd->read_reg) {
714 pr_err("%s: No read API for reading vdd_%s regs\n",
715 __func__, voltdm->name);
716 return 0;
717 }
718
a7460daf 719 curr_vsel = vdd->read_reg(vdd->vp_data->vp_common->prm_mod, vdd->vp_data->voltage);
2f34ce81
TG
720
721 if (!vdd->pmic_info || !vdd->pmic_info->vsel_to_uv) {
722 pr_warning("%s: PMIC function to convert vsel to voltage"
723 "in uV not registerd\n", __func__);
724 return 0;
725 }
726
727 return vdd->pmic_info->vsel_to_uv(curr_vsel);
728}
729
730/**
731 * omap_vp_enable() - API to enable a particular VP
732 * @voltdm: pointer to the VDD whose VP is to be enabled.
733 *
734 * This API enables a particular voltage processor. Needed by the smartreflex
735 * class drivers.
736 */
737void omap_vp_enable(struct voltagedomain *voltdm)
738{
739 struct omap_vdd_info *vdd;
740 u32 vpconfig;
2f34ce81
TG
741
742 if (!voltdm || IS_ERR(voltdm)) {
743 pr_warning("%s: VDD specified does not exist!\n", __func__);
744 return;
745 }
746
81a60482 747 vdd = voltdm->vdd;
2f34ce81
TG
748 if (!vdd->read_reg || !vdd->write_reg) {
749 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
750 __func__, voltdm->name);
751 return;
752 }
753
2f34ce81
TG
754 /* If VP is already enabled, do nothing. Return */
755 if (vdd->vp_enabled)
756 return;
757
81a60482 758 vp_latch_vsel(voltdm);
2f34ce81
TG
759
760 /* Enable VP */
a7460daf 761 vpconfig = vdd->read_reg(vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
c0718df4 762 vpconfig |= vdd->vp_data->vp_common->vpconfig_vpenable;
a7460daf 763 vdd->write_reg(vpconfig, vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
2f34ce81
TG
764 vdd->vp_enabled = true;
765}
766
767/**
768 * omap_vp_disable() - API to disable a particular VP
769 * @voltdm: pointer to the VDD whose VP is to be disabled.
770 *
771 * This API disables a particular voltage processor. Needed by the smartreflex
772 * class drivers.
773 */
774void omap_vp_disable(struct voltagedomain *voltdm)
775{
776 struct omap_vdd_info *vdd;
777 u32 vpconfig;
2f34ce81
TG
778 int timeout;
779
780 if (!voltdm || IS_ERR(voltdm)) {
781 pr_warning("%s: VDD specified does not exist!\n", __func__);
782 return;
783 }
784
81a60482 785 vdd = voltdm->vdd;
2f34ce81
TG
786 if (!vdd->read_reg || !vdd->write_reg) {
787 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
788 __func__, voltdm->name);
789 return;
790 }
791
2f34ce81
TG
792 /* If VP is already disabled, do nothing. Return */
793 if (!vdd->vp_enabled) {
794 pr_warning("%s: Trying to disable VP for vdd_%s when"
795 "it is already disabled\n", __func__, voltdm->name);
796 return;
797 }
798
799 /* Disable VP */
a7460daf 800 vpconfig = vdd->read_reg(vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
c0718df4 801 vpconfig &= ~vdd->vp_data->vp_common->vpconfig_vpenable;
a7460daf 802 vdd->write_reg(vpconfig, vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
2f34ce81
TG
803
804 /*
805 * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us
806 */
a7460daf 807 omap_test_timeout((vdd->read_reg(vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vstatus)),
2f34ce81
TG
808 VP_IDLE_TIMEOUT, timeout);
809
810 if (timeout >= VP_IDLE_TIMEOUT)
811 pr_warning("%s: vdd_%s idle timedout\n",
812 __func__, voltdm->name);
813
814 vdd->vp_enabled = false;
815
816 return;
817}
818
819/**
820 * omap_voltage_scale_vdd() - API to scale voltage of a particular
821 * voltage domain.
822 * @voltdm: pointer to the VDD which is to be scaled.
823 * @target_volt: The target voltage of the voltage domain
824 *
825 * This API should be called by the kernel to do the voltage scaling
826 * for a particular voltage domain during dvfs or any other situation.
827 */
828int omap_voltage_scale_vdd(struct voltagedomain *voltdm,
829 unsigned long target_volt)
830{
831 struct omap_vdd_info *vdd;
832
833 if (!voltdm || IS_ERR(voltdm)) {
834 pr_warning("%s: VDD specified does not exist!\n", __func__);
835 return -EINVAL;
836 }
837
81a60482 838 vdd = voltdm->vdd;
2f34ce81
TG
839
840 if (!vdd->volt_scale) {
841 pr_err("%s: No voltage scale API registered for vdd_%s\n",
842 __func__, voltdm->name);
843 return -ENODATA;
844 }
845
81a60482 846 return vdd->volt_scale(voltdm, target_volt);
2f34ce81
TG
847}
848
849/**
850 * omap_voltage_reset() - Resets the voltage of a particular voltage domain
851 * to that of the current OPP.
852 * @voltdm: pointer to the VDD whose voltage is to be reset.
853 *
854 * This API finds out the correct voltage the voltage domain is supposed
25985edc 855 * to be at and resets the voltage to that level. Should be used especially
2f34ce81
TG
856 * while disabling any voltage compensation modules.
857 */
858void omap_voltage_reset(struct voltagedomain *voltdm)
859{
860 unsigned long target_uvdc;
861
862 if (!voltdm || IS_ERR(voltdm)) {
863 pr_warning("%s: VDD specified does not exist!\n", __func__);
864 return;
865 }
866
867 target_uvdc = omap_voltage_get_nom_volt(voltdm);
868 if (!target_uvdc) {
869 pr_err("%s: unable to find current voltage for vdd_%s\n",
870 __func__, voltdm->name);
871 return;
872 }
873
874 omap_voltage_scale_vdd(voltdm, target_uvdc);
875}
876
877/**
878 * omap_voltage_get_volttable() - API to get the voltage table associated with a
879 * particular voltage domain.
880 * @voltdm: pointer to the VDD for which the voltage table is required
881 * @volt_data: the voltage table for the particular vdd which is to be
882 * populated by this API
883 *
884 * This API populates the voltage table associated with a VDD into the
885 * passed parameter pointer. Returns the count of distinct voltages
886 * supported by this vdd.
887 *
888 */
889void omap_voltage_get_volttable(struct voltagedomain *voltdm,
890 struct omap_volt_data **volt_data)
891{
892 struct omap_vdd_info *vdd;
893
894 if (!voltdm || IS_ERR(voltdm)) {
895 pr_warning("%s: VDD specified does not exist!\n", __func__);
896 return;
897 }
898
81a60482 899 vdd = voltdm->vdd;
2f34ce81
TG
900
901 *volt_data = vdd->volt_data;
902}
903
904/**
905 * omap_voltage_get_voltdata() - API to get the voltage table entry for a
906 * particular voltage
907 * @voltdm: pointer to the VDD whose voltage table has to be searched
908 * @volt: the voltage to be searched in the voltage table
909 *
910 * This API searches through the voltage table for the required voltage
911 * domain and tries to find a matching entry for the passed voltage volt.
912 * If a matching entry is found volt_data is populated with that entry.
913 * This API searches only through the non-compensated voltages int the
914 * voltage table.
915 * Returns pointer to the voltage table entry corresponding to volt on
25985edc 916 * success. Returns -ENODATA if no voltage table exisits for the passed voltage
2f34ce81
TG
917 * domain or if there is no matching entry.
918 */
919struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
920 unsigned long volt)
921{
922 struct omap_vdd_info *vdd;
923 int i;
924
925 if (!voltdm || IS_ERR(voltdm)) {
926 pr_warning("%s: VDD specified does not exist!\n", __func__);
927 return ERR_PTR(-EINVAL);
928 }
929
81a60482 930 vdd = voltdm->vdd;
2f34ce81
TG
931
932 if (!vdd->volt_data) {
933 pr_warning("%s: voltage table does not exist for vdd_%s\n",
934 __func__, voltdm->name);
935 return ERR_PTR(-ENODATA);
936 }
937
938 for (i = 0; vdd->volt_data[i].volt_nominal != 0; i++) {
939 if (vdd->volt_data[i].volt_nominal == volt)
940 return &vdd->volt_data[i];
941 }
942
943 pr_notice("%s: Unable to match the current voltage with the voltage"
944 "table for vdd_%s\n", __func__, voltdm->name);
945
946 return ERR_PTR(-ENODATA);
947}
948
949/**
950 * omap_voltage_register_pmic() - API to register PMIC specific data
951 * @voltdm: pointer to the VDD for which the PMIC specific data is
952 * to be registered
953 * @pmic_info: the structure containing pmic info
954 *
955 * This API is to be called by the SOC/PMIC file to specify the
956 * pmic specific info as present in omap_volt_pmic_info structure.
957 */
958int omap_voltage_register_pmic(struct voltagedomain *voltdm,
959 struct omap_volt_pmic_info *pmic_info)
960{
961 struct omap_vdd_info *vdd;
962
963 if (!voltdm || IS_ERR(voltdm)) {
964 pr_warning("%s: VDD specified does not exist!\n", __func__);
965 return -EINVAL;
966 }
967
81a60482 968 vdd = voltdm->vdd;
2f34ce81
TG
969
970 vdd->pmic_info = pmic_info;
971
972 return 0;
973}
974
975/**
976 * omap_voltage_get_dbgdir() - API to get pointer to the debugfs directory
977 * corresponding to a voltage domain.
978 *
979 * @voltdm: pointer to the VDD whose debug directory is required.
980 *
981 * This API returns pointer to the debugfs directory corresponding
982 * to the voltage domain. Should be used by drivers requiring to
983 * add any debug entry for a particular voltage domain. Returns NULL
984 * in case of error.
985 */
986struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm)
987{
988 struct omap_vdd_info *vdd;
989
990 if (!voltdm || IS_ERR(voltdm)) {
991 pr_warning("%s: VDD specified does not exist!\n", __func__);
992 return NULL;
993 }
994
81a60482 995 vdd = voltdm->vdd;
2f34ce81
TG
996
997 return vdd->debug_dir;
998}
999
1000/**
1001 * omap_change_voltscale_method() - API to change the voltage scaling method.
1002 * @voltdm: pointer to the VDD whose voltage scaling method
1003 * has to be changed.
1004 * @voltscale_method: the method to be used for voltage scaling.
1005 *
1006 * This API can be used by the board files to change the method of voltage
1007 * scaling between vpforceupdate and vcbypass. The parameter values are
1008 * defined in voltage.h
1009 */
1010void omap_change_voltscale_method(struct voltagedomain *voltdm,
1011 int voltscale_method)
1012{
1013 struct omap_vdd_info *vdd;
1014
1015 if (!voltdm || IS_ERR(voltdm)) {
1016 pr_warning("%s: VDD specified does not exist!\n", __func__);
1017 return;
1018 }
1019
81a60482 1020 vdd = voltdm->vdd;
2f34ce81
TG
1021
1022 switch (voltscale_method) {
1023 case VOLTSCALE_VPFORCEUPDATE:
1024 vdd->volt_scale = vp_forceupdate_scale_voltage;
1025 return;
1026 case VOLTSCALE_VCBYPASS:
1027 vdd->volt_scale = vc_bypass_scale_voltage;
1028 return;
1029 default:
1030 pr_warning("%s: Trying to change the method of voltage scaling"
1031 "to an unsupported one!\n", __func__);
1032 }
1033}
1034
2f34ce81
TG
1035/**
1036 * omap_voltage_late_init() - Init the various voltage parameters
1037 *
1038 * This API is to be called in the later stages of the
1039 * system boot to init the voltage controller and
1040 * voltage processors.
1041 */
1042int __init omap_voltage_late_init(void)
1043{
81a60482 1044 struct voltagedomain *voltdm;
2f34ce81 1045
81a60482 1046 if (list_empty(&voltdm_list)) {
2f34ce81
TG
1047 pr_err("%s: Voltage driver support not added\n",
1048 __func__);
1049 return -EINVAL;
1050 }
1051
1052 voltage_dir = debugfs_create_dir("voltage", NULL);
1053 if (IS_ERR(voltage_dir))
1054 pr_err("%s: Unable to create voltage debugfs main dir\n",
1055 __func__);
81a60482 1056 list_for_each_entry(voltdm, &voltdm_list, node) {
37efca7e
KH
1057 if (!voltdm->scalable)
1058 continue;
1059
81a60482
KH
1060 if (voltdm->vdd) {
1061 if (omap_vdd_data_configure(voltdm))
1062 continue;
1063 omap_vc_init(voltdm);
1064 vp_init(voltdm);
1065 vdd_debugfs_init(voltdm);
1066 }
2f34ce81
TG
1067 }
1068
1069 return 0;
1070}
1071
81a60482 1072static struct voltagedomain *_voltdm_lookup(const char *name)
2f34ce81 1073{
81a60482
KH
1074 struct voltagedomain *voltdm, *temp_voltdm;
1075
1076 voltdm = NULL;
1077
1078 list_for_each_entry(temp_voltdm, &voltdm_list, node) {
1079 if (!strcmp(name, temp_voltdm->name)) {
1080 voltdm = temp_voltdm;
1081 break;
1082 }
1083 }
1084
1085 return voltdm;
1086}
1087
1088static int _voltdm_register(struct voltagedomain *voltdm)
1089{
1090 if (!voltdm || !voltdm->name)
1091 return -EINVAL;
1092
1093 list_add(&voltdm->node, &voltdm_list);
1094
1095 pr_debug("voltagedomain: registered %s\n", voltdm->name);
1096
2f34ce81
TG
1097 return 0;
1098}
81a60482
KH
1099
1100/**
1101 * voltdm_lookup - look up a voltagedomain by name, return a pointer
1102 * @name: name of voltagedomain
1103 *
1104 * Find a registered voltagedomain by its name @name. Returns a pointer
1105 * to the struct voltagedomain if found, or NULL otherwise.
1106 */
1107struct voltagedomain *voltdm_lookup(const char *name)
1108{
1109 struct voltagedomain *voltdm ;
1110
1111 if (!name)
1112 return NULL;
1113
1114 voltdm = _voltdm_lookup(name);
1115
1116 return voltdm;
1117}
1118
1119/**
1120 * voltdm_init - set up the voltagedomain layer
1121 * @voltdm_list: array of struct voltagedomain pointers to register
1122 *
1123 * Loop through the array of voltagedomains @voltdm_list, registering all
1124 * that are available on the current CPU. If voltdm_list is supplied
1125 * and not null, all of the referenced voltagedomains will be
1126 * registered. No return value.
1127 */
1128void voltdm_init(struct voltagedomain **voltdms)
1129{
1130 struct voltagedomain **v;
1131
1132 if (voltdms) {
1133 for (v = voltdms; *v; v++)
1134 _voltdm_register(*v);
1135 }
1136}
This page took 0.177129 seconds and 5 git commands to generate.