Linux Audio

Check our new training course

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