From 0d45741059eb1c21dd4c1f34083d1ecaed7fca96 Mon Sep 17 00:00:00 2001
From: Kevin Hilman <khilman@ti.com>
Date: Mon, 21 Mar 2011 14:29:13 -0700
Subject: [PATCH 112/149] OMAP2+: voltage: split out voltage processor (VP) code into new layer

This patch is primarily a move of VP specific code from voltage.c into
its own code in vp.c and adds prototypes to vp.h

No functional changes, except debugfs...

VP debugfs moved to 'vp' subdir of <debugfs>/voltage/ and 'vp_'
prefixes removed from all debugfs filenames.

Signed-off-by: Kevin Hilman <khilman@ti.com>
---
 arch/arm/mach-omap2/Makefile  |    2 +-
 arch/arm/mach-omap2/voltage.c |  348 +-------------------------------------
 arch/arm/mach-omap2/voltage.h |    3 -
 arch/arm/mach-omap2/vp.c      |  374 +++++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/vp.h      |    9 +
 5 files changed, 387 insertions(+), 349 deletions(-)
 create mode 100644 arch/arm/mach-omap2/vp.c

diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index ecbf361..8e79ca5 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -90,7 +90,7 @@ obj-$(CONFIG_ARCH_OMAP4)		+= prcm.o cm2xxx_3xxx.o cminst44xx.o \
 
 # OMAP voltage domains
 ifeq ($(CONFIG_PM),y)
-voltagedomain-common			:= voltage.o vc.o
+voltagedomain-common			:= voltage.o vc.o vp.o
 obj-$(CONFIG_ARCH_OMAP2)		+= $(voltagedomain-common) \
 					   voltagedomains2xxx_data.o
 obj-$(CONFIG_ARCH_OMAP3)		+= $(voltagedomain-common) \
diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
index e1a22a3..9b9f019 100644
--- a/arch/arm/mach-omap2/voltage.c
+++ b/arch/arm/mach-omap2/voltage.c
@@ -46,10 +46,6 @@ static LIST_HEAD(voltdm_list);
 #define VOLTAGE_DIR_SIZE	16
 static struct dentry *voltage_dir;
 
-/* Init function pointers */
-static int vp_forceupdate_scale_voltage(struct voltagedomain *voltdm,
-					unsigned long target_volt);
-
 static u32 omap3_voltage_read_reg(u16 mod, u8 offset)
 {
 	return omap2_prm_read_mod_reg(mod, offset);
@@ -105,7 +101,7 @@ static int __init _config_common_vdd_data(struct voltagedomain *voltdm)
 	sys_clk_speed /= 1000;
 
 	/* Generic voltage parameters */
-	vdd->volt_scale = vp_forceupdate_scale_voltage;
+	vdd->volt_scale = omap_vp_forceupdate_scale;
 	vdd->vp_enabled = false;
 
 	vdd->vp_rt_data.vpconfig_erroroffset =
@@ -127,30 +123,6 @@ static int __init _config_common_vdd_data(struct voltagedomain *voltdm)
 	return 0;
 }
 
-/* Voltage debugfs support */
-static int vp_volt_debug_get(void *data, u64 *val)
-{
-	struct voltagedomain *voltdm = (struct voltagedomain *)data;
-	struct omap_vdd_info *vdd = voltdm->vdd;
-	u8 vsel;
-
-	if (!vdd) {
-		pr_warning("Wrong paramater passed\n");
-		return -EINVAL;
-	}
-
-	vsel = vdd->read_reg(vdd->vp_data->vp_common->prm_mod, vdd->vp_data->voltage);
-
-	if (!vdd->pmic_info->vsel_to_uv) {
-		pr_warning("PMIC function to convert vsel to voltage"
-			"in uV not registerd\n");
-		return -EINVAL;
-	}
-
-	*val = vdd->pmic_info->vsel_to_uv(vsel);
-	return 0;
-}
-
 static int nom_volt_debug_get(void *data, u64 *val)
 {
 	struct voltagedomain *voltdm = (struct voltagedomain *)data;
@@ -165,85 +137,8 @@ static int nom_volt_debug_get(void *data, u64 *val)
 	return 0;
 }
 
-DEFINE_SIMPLE_ATTRIBUTE(vp_volt_debug_fops, vp_volt_debug_get, NULL, "%llu\n");
 DEFINE_SIMPLE_ATTRIBUTE(nom_volt_debug_fops, nom_volt_debug_get, NULL,
 								"%llu\n");
-static void vp_latch_vsel(struct voltagedomain *voltdm)
-{
-	u32 vpconfig;
-	unsigned long uvdc;
-	char vsel;
-	struct omap_vdd_info *vdd = voltdm->vdd;
-
-	uvdc = omap_voltage_get_nom_volt(voltdm);
-	if (!uvdc) {
-		pr_warning("%s: unable to find current voltage for vdd_%s\n",
-			__func__, voltdm->name);
-		return;
-	}
-
-	if (!vdd->pmic_info || !vdd->pmic_info->uv_to_vsel) {
-		pr_warning("%s: PMIC function to convert voltage in uV to"
-			" vsel not registered\n", __func__);
-		return;
-	}
-
-	vsel = vdd->pmic_info->uv_to_vsel(uvdc);
-
-	vpconfig = vdd->read_reg(vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
-	vpconfig &= ~(vdd->vp_data->vp_common->vpconfig_initvoltage_mask |
-			vdd->vp_data->vp_common->vpconfig_initvdd);
-	vpconfig |= vsel << vdd->vp_data->vp_common->vpconfig_initvoltage_shift;
-
-	vdd->write_reg(vpconfig, vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
-
-	/* Trigger initVDD value copy to voltage processor */
-	vdd->write_reg((vpconfig | vdd->vp_data->vp_common->vpconfig_initvdd),
-		       vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
-
-	/* Clear initVDD copy trigger bit */
-	vdd->write_reg(vpconfig, vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
-}
-
-/* Generic voltage init functions */
-static void __init vp_init(struct voltagedomain *voltdm)
-{
-	struct omap_vdd_info *vdd = voltdm->vdd;
-	u32 vp_val;
-
-	if (!vdd->read_reg || !vdd->write_reg) {
-		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
-			__func__, voltdm->name);
-		return;
-	}
-
-	vp_val = vdd->vp_rt_data.vpconfig_erroroffset |
-		(vdd->vp_rt_data.vpconfig_errorgain <<
-		vdd->vp_data->vp_common->vpconfig_errorgain_shift) |
-		vdd->vp_data->vp_common->vpconfig_timeouten;
-	vdd->write_reg(vp_val, vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
-
-	vp_val = ((vdd->vp_rt_data.vstepmin_smpswaittimemin <<
-		vdd->vp_data->vp_common->vstepmin_smpswaittimemin_shift) |
-		(vdd->vp_rt_data.vstepmin_stepmin <<
-		vdd->vp_data->vp_common->vstepmin_stepmin_shift));
-	vdd->write_reg(vp_val, vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vstepmin);
-
-	vp_val = ((vdd->vp_rt_data.vstepmax_smpswaittimemax <<
-		vdd->vp_data->vp_common->vstepmax_smpswaittimemax_shift) |
-		(vdd->vp_rt_data.vstepmax_stepmax <<
-		vdd->vp_data->vp_common->vstepmax_stepmax_shift));
-	vdd->write_reg(vp_val, vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vstepmax);
-
-	vp_val = ((vdd->vp_rt_data.vlimitto_vddmax <<
-		vdd->vp_data->vp_common->vlimitto_vddmax_shift) |
-		(vdd->vp_rt_data.vlimitto_vddmin <<
-		vdd->vp_data->vp_common->vlimitto_vddmin_shift) |
-		(vdd->vp_rt_data.vlimitto_timeout <<
-		vdd->vp_data->vp_common->vlimitto_timeout_shift));
-	vdd->write_reg(vp_val, vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vlimitto);
-}
-
 static void __init vdd_debugfs_init(struct voltagedomain *voltdm)
 {
 	char *name;
@@ -268,125 +163,11 @@ static void __init vdd_debugfs_init(struct voltagedomain *voltdm)
 		return;
 	}
 
-	(void) debugfs_create_x16("vp_errorgain", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_rt_data.vpconfig_errorgain));
-	(void) debugfs_create_x16("vp_smpswaittimemin", S_IRUGO,
-				vdd->debug_dir,
-				&(vdd->vp_rt_data.vstepmin_smpswaittimemin));
-	(void) debugfs_create_x8("vp_stepmin", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_rt_data.vstepmin_stepmin));
-	(void) debugfs_create_x16("vp_smpswaittimemax", S_IRUGO,
-				vdd->debug_dir,
-				&(vdd->vp_rt_data.vstepmax_smpswaittimemax));
-	(void) debugfs_create_x8("vp_stepmax", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_rt_data.vstepmax_stepmax));
-	(void) debugfs_create_x8("vp_vddmax", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_rt_data.vlimitto_vddmax));
-	(void) debugfs_create_x8("vp_vddmin", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_rt_data.vlimitto_vddmin));
-	(void) debugfs_create_x16("vp_timeout", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_rt_data.vlimitto_timeout));
-	(void) debugfs_create_file("curr_vp_volt", S_IRUGO, vdd->debug_dir,
-				(void *) voltdm, &vp_volt_debug_fops);
 	(void) debugfs_create_file("curr_nominal_volt", S_IRUGO,
 				vdd->debug_dir, (void *) voltdm,
 				&nom_volt_debug_fops);
 }
 
-/* VP force update method of voltage scaling */
-static int vp_forceupdate_scale_voltage(struct voltagedomain *voltdm,
-		unsigned long target_volt)
-{
-	struct omap_vdd_info *vdd = voltdm->vdd;
-	u32 vpconfig;
-	u8 target_vsel, current_vsel;
-	int ret, timeout = 0;
-
-	ret = omap_vc_pre_scale(voltdm, target_volt, &target_vsel, &current_vsel);
-	if (ret)
-		return ret;
-
-	/*
-	 * Clear all pending TransactionDone interrupt/status. Typical latency
-	 * is <3us
-	 */
-	while (timeout++ < VP_TRANXDONE_TIMEOUT) {
-		vdd->write_reg(vdd->vp_data->prm_irqst_data->tranxdone_status,
-			       vdd->prm_irqst_mod, vdd->prm_irqst_reg);
-		if (!(vdd->read_reg(vdd->prm_irqst_mod, vdd->prm_irqst_reg) &
-		      vdd->vp_data->prm_irqst_data->tranxdone_status))
-			break;
-		udelay(1);
-	}
-	if (timeout >= VP_TRANXDONE_TIMEOUT) {
-		pr_warning("%s: vdd_%s TRANXDONE timeout exceeded."
-			"Voltage change aborted", __func__, voltdm->name);
-		return -ETIMEDOUT;
-	}
-
-	/* Configure for VP-Force Update */
-	vpconfig = vdd->read_reg(vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
-	vpconfig &= ~(vdd->vp_data->vp_common->vpconfig_initvdd |
-			vdd->vp_data->vp_common->vpconfig_forceupdate |
-			vdd->vp_data->vp_common->vpconfig_initvoltage_mask);
-	vpconfig |= ((target_vsel <<
-			vdd->vp_data->vp_common->vpconfig_initvoltage_shift));
-	vdd->write_reg(vpconfig, vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
-
-	/* Trigger initVDD value copy to voltage processor */
-	vpconfig |= vdd->vp_data->vp_common->vpconfig_initvdd;
-	vdd->write_reg(vpconfig, vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
-
-	/* Force update of voltage */
-	vpconfig |= vdd->vp_data->vp_common->vpconfig_forceupdate;
-	vdd->write_reg(vpconfig, vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
-
-	/*
-	 * Wait for TransactionDone. Typical latency is <200us.
-	 * Depends on SMPSWAITTIMEMIN/MAX and voltage change
-	 */
-	timeout = 0;
-	omap_test_timeout((vdd->read_reg(vdd->prm_irqst_mod,
-					 vdd->prm_irqst_reg) &
-			   vdd->vp_data->prm_irqst_data->tranxdone_status),
-			  VP_TRANXDONE_TIMEOUT, timeout);
-	if (timeout >= VP_TRANXDONE_TIMEOUT)
-		pr_err("%s: vdd_%s TRANXDONE timeout exceeded."
-			"TRANXDONE never got set after the voltage update\n",
-			__func__, voltdm->name);
-
-	omap_vc_post_scale(voltdm, target_volt, target_vsel, current_vsel);
-
-	/*
-	 * Disable TransactionDone interrupt , clear all status, clear
-	 * control registers
-	 */
-	timeout = 0;
-	while (timeout++ < VP_TRANXDONE_TIMEOUT) {
-		vdd->write_reg(vdd->vp_data->prm_irqst_data->tranxdone_status,
-			       vdd->prm_irqst_mod, vdd->prm_irqst_reg);
-		if (!(vdd->read_reg(vdd->prm_irqst_mod, vdd->prm_irqst_reg) &
-		      vdd->vp_data->prm_irqst_data->tranxdone_status))
-			break;
-		udelay(1);
-	}
-
-	if (timeout >= VP_TRANXDONE_TIMEOUT)
-		pr_warning("%s: vdd_%s TRANXDONE timeout exceeded while trying"
-			"to clear the TRANXDONE status\n",
-			__func__, voltdm->name);
-
-	vpconfig = vdd->read_reg(vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
-	/* Clear initVDD copy trigger bit */
-	vpconfig &= ~vdd->vp_data->vp_common->vpconfig_initvdd;
-	vdd->write_reg(vpconfig, vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
-	/* Clear force bit */
-	vpconfig &= ~vdd->vp_data->vp_common->vpconfig_forceupdate;
-	vdd->write_reg(vpconfig, vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
-
-	return 0;
-}
-
 static int __init omap_vdd_data_configure(struct voltagedomain *voltdm)
 {
 	struct omap_vdd_info *vdd = voltdm->vdd;
@@ -439,129 +220,6 @@ unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm)
 }
 
 /**
- * omap_vp_get_curr_volt() - API to get the current vp voltage.
- * @voltdm:	pointer to the VDD.
- *
- * This API returns the current voltage for the specified voltage processor
- */
-unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm)
-{
-	struct omap_vdd_info *vdd;
-	u8 curr_vsel;
-
-	if (!voltdm || IS_ERR(voltdm)) {
-		pr_warning("%s: VDD specified does not exist!\n", __func__);
-		return 0;
-	}
-
-	vdd = voltdm->vdd;
-	if (!vdd->read_reg) {
-		pr_err("%s: No read API for reading vdd_%s regs\n",
-			__func__, voltdm->name);
-		return 0;
-	}
-
-	curr_vsel = vdd->read_reg(vdd->vp_data->vp_common->prm_mod, vdd->vp_data->voltage);
-
-	if (!vdd->pmic_info || !vdd->pmic_info->vsel_to_uv) {
-		pr_warning("%s: PMIC function to convert vsel to voltage"
-			"in uV not registerd\n", __func__);
-		return 0;
-	}
-
-	return vdd->pmic_info->vsel_to_uv(curr_vsel);
-}
-
-/**
- * omap_vp_enable() - API to enable a particular VP
- * @voltdm:	pointer to the VDD whose VP is to be enabled.
- *
- * This API enables a particular voltage processor. Needed by the smartreflex
- * class drivers.
- */
-void omap_vp_enable(struct voltagedomain *voltdm)
-{
-	struct omap_vdd_info *vdd;
-	u32 vpconfig;
-
-	if (!voltdm || IS_ERR(voltdm)) {
-		pr_warning("%s: VDD specified does not exist!\n", __func__);
-		return;
-	}
-
-	vdd = voltdm->vdd;
-	if (!vdd->read_reg || !vdd->write_reg) {
-		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
-			__func__, voltdm->name);
-		return;
-	}
-
-	/* If VP is already enabled, do nothing. Return */
-	if (vdd->vp_enabled)
-		return;
-
-	vp_latch_vsel(voltdm);
-
-	/* Enable VP */
-	vpconfig = vdd->read_reg(vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
-	vpconfig |= vdd->vp_data->vp_common->vpconfig_vpenable;
-	vdd->write_reg(vpconfig, vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
-	vdd->vp_enabled = true;
-}
-
-/**
- * omap_vp_disable() - API to disable a particular VP
- * @voltdm:	pointer to the VDD whose VP is to be disabled.
- *
- * This API disables a particular voltage processor. Needed by the smartreflex
- * class drivers.
- */
-void omap_vp_disable(struct voltagedomain *voltdm)
-{
-	struct omap_vdd_info *vdd;
-	u32 vpconfig;
-	int timeout;
-
-	if (!voltdm || IS_ERR(voltdm)) {
-		pr_warning("%s: VDD specified does not exist!\n", __func__);
-		return;
-	}
-
-	vdd = voltdm->vdd;
-	if (!vdd->read_reg || !vdd->write_reg) {
-		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
-			__func__, voltdm->name);
-		return;
-	}
-
-	/* If VP is already disabled, do nothing. Return */
-	if (!vdd->vp_enabled) {
-		pr_warning("%s: Trying to disable VP for vdd_%s when"
-			"it is already disabled\n", __func__, voltdm->name);
-		return;
-	}
-
-	/* Disable VP */
-	vpconfig = vdd->read_reg(vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
-	vpconfig &= ~vdd->vp_data->vp_common->vpconfig_vpenable;
-	vdd->write_reg(vpconfig, vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vpconfig);
-
-	/*
-	 * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us
-	 */
-	omap_test_timeout((vdd->read_reg(vdd->vp_data->vp_common->prm_mod, vdd->vp_data->vstatus)),
-				VP_IDLE_TIMEOUT, timeout);
-
-	if (timeout >= VP_IDLE_TIMEOUT)
-		pr_warning("%s: vdd_%s idle timedout\n",
-			__func__, voltdm->name);
-
-	vdd->vp_enabled = false;
-
-	return;
-}
-
-/**
  * omap_voltage_scale_vdd() - API to scale voltage of a particular
  *				voltage domain.
  * @voltdm:	pointer to the VDD which is to be scaled.
@@ -766,7 +424,7 @@ void omap_change_voltscale_method(struct voltagedomain *voltdm,
 
 	switch (voltscale_method) {
 	case VOLTSCALE_VPFORCEUPDATE:
-		vdd->volt_scale = vp_forceupdate_scale_voltage;
+		vdd->volt_scale = omap_vp_forceupdate_scale;
 		return;
 	case VOLTSCALE_VCBYPASS:
 		vdd->volt_scale = omap_vc_bypass_scale;
@@ -810,8 +468,8 @@ int __init omap_voltage_late_init(void)
 		if (voltdm->vdd) {
 			if (omap_vdd_data_configure(voltdm))
 				continue;
-			vp_init(voltdm);
 			vdd_debugfs_init(voltdm);
+			omap_vp_init(voltdm);
 		}
 	}
 
diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h
index b06e03f..83fa239 100644
--- a/arch/arm/mach-omap2/voltage.h
+++ b/arch/arm/mach-omap2/voltage.h
@@ -152,9 +152,6 @@ struct omap_vdd_info {
 		unsigned long target_volt);
 };
 
-unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm);
-void omap_vp_enable(struct voltagedomain *voltdm);
-void omap_vp_disable(struct voltagedomain *voltdm);
 int omap_voltage_scale_vdd(struct voltagedomain *voltdm,
 		unsigned long target_volt);
 void omap_voltage_reset(struct voltagedomain *voltdm);
diff --git a/arch/arm/mach-omap2/vp.c b/arch/arm/mach-omap2/vp.c
new file mode 100644
index 0000000..f3503de
--- /dev/null
+++ b/arch/arm/mach-omap2/vp.c
@@ -0,0 +1,374 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/debugfs.h>
+
+#include <plat/common.h>
+
+#include "voltage.h"
+#include "vp.h"
+#include "prm-regbits-34xx.h"
+#include "prm-regbits-44xx.h"
+#include "prm44xx.h"
+
+static void __init vp_debugfs_init(struct voltagedomain *voltdm);
+
+static void vp_latch_vsel(struct voltagedomain *voltdm)
+{
+	struct omap_vp_instance_data *vp = voltdm->vdd->vp_data;
+	u32 vpconfig;
+	unsigned long uvdc;
+	char vsel;
+	struct omap_vdd_info *vdd = voltdm->vdd;
+
+	uvdc = omap_voltage_get_nom_volt(voltdm);
+	if (!uvdc) {
+		pr_warning("%s: unable to find current voltage for vdd_%s\n",
+			__func__, voltdm->name);
+		return;
+	}
+
+	if (!vdd->pmic_info || !vdd->pmic_info->uv_to_vsel) {
+		pr_warning("%s: PMIC function to convert voltage in uV to"
+			" vsel not registered\n", __func__);
+		return;
+	}
+
+	vsel = vdd->pmic_info->uv_to_vsel(uvdc);
+
+	vpconfig = vdd->read_reg(vp->vp_common->prm_mod, vp->vpconfig);
+	vpconfig &= ~(vp->vp_common->vpconfig_initvoltage_mask |
+			vp->vp_common->vpconfig_initvdd);
+	vpconfig |= vsel << vp->vp_common->vpconfig_initvoltage_shift;
+
+	vdd->write_reg(vpconfig, vp->vp_common->prm_mod, vp->vpconfig);
+
+	/* Trigger initVDD value copy to voltage processor */
+	vdd->write_reg((vpconfig | vp->vp_common->vpconfig_initvdd),
+		       vp->vp_common->prm_mod, vp->vpconfig);
+
+	/* Clear initVDD copy trigger bit */
+	vdd->write_reg(vpconfig, vp->vp_common->prm_mod, vp->vpconfig);
+}
+
+/* Generic voltage init functions */
+void __init omap_vp_init(struct voltagedomain *voltdm)
+{
+	struct omap_vp_instance_data *vp = voltdm->vdd->vp_data;
+	struct omap_vdd_info *vdd = voltdm->vdd;
+	u32 vp_val;
+
+	if (!vdd->read_reg || !vdd->write_reg) {
+		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
+			__func__, voltdm->name);
+		return;
+	}
+
+	vp_val = vdd->vp_rt_data.vpconfig_erroroffset |
+		(vdd->vp_rt_data.vpconfig_errorgain <<
+		vp->vp_common->vpconfig_errorgain_shift) |
+		vp->vp_common->vpconfig_timeouten;
+	vdd->write_reg(vp_val, vp->vp_common->prm_mod, vp->vpconfig);
+
+	vp_val = ((vdd->vp_rt_data.vstepmin_smpswaittimemin <<
+		vp->vp_common->vstepmin_smpswaittimemin_shift) |
+		(vdd->vp_rt_data.vstepmin_stepmin <<
+		vp->vp_common->vstepmin_stepmin_shift));
+	vdd->write_reg(vp_val, vp->vp_common->prm_mod, vp->vstepmin);
+
+	vp_val = ((vdd->vp_rt_data.vstepmax_smpswaittimemax <<
+		vp->vp_common->vstepmax_smpswaittimemax_shift) |
+		(vdd->vp_rt_data.vstepmax_stepmax <<
+		vp->vp_common->vstepmax_stepmax_shift));
+	vdd->write_reg(vp_val, vp->vp_common->prm_mod, vp->vstepmax);
+
+	vp_val = ((vdd->vp_rt_data.vlimitto_vddmax <<
+		vp->vp_common->vlimitto_vddmax_shift) |
+		(vdd->vp_rt_data.vlimitto_vddmin <<
+		vp->vp_common->vlimitto_vddmin_shift) |
+		(vdd->vp_rt_data.vlimitto_timeout <<
+		vp->vp_common->vlimitto_timeout_shift));
+	vdd->write_reg(vp_val, vp->vp_common->prm_mod, vp->vlimitto);
+
+	vp_debugfs_init(voltdm);
+}
+
+/* VP force update method of voltage scaling */
+int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
+			      unsigned long target_volt)
+{
+	struct omap_vp_instance_data *vp = voltdm->vdd->vp_data;
+	struct omap_vdd_info *vdd = voltdm->vdd;
+	u32 vpconfig;
+	u8 target_vsel, current_vsel;
+	int ret, timeout = 0;
+
+	ret = omap_vc_pre_scale(voltdm, target_volt, &target_vsel, &current_vsel);
+	if (ret)
+		return ret;
+
+	/*
+	 * Clear all pending TransactionDone interrupt/status. Typical latency
+	 * is <3us
+	 */
+	while (timeout++ < VP_TRANXDONE_TIMEOUT) {
+		vdd->write_reg(vp->prm_irqst_data->tranxdone_status,
+			       vdd->prm_irqst_mod, vdd->prm_irqst_reg);
+		if (!(vdd->read_reg(vdd->prm_irqst_mod, vdd->prm_irqst_reg) &
+		      vp->prm_irqst_data->tranxdone_status))
+			break;
+		udelay(1);
+	}
+	if (timeout >= VP_TRANXDONE_TIMEOUT) {
+		pr_warning("%s: vdd_%s TRANXDONE timeout exceeded."
+			"Voltage change aborted", __func__, voltdm->name);
+		return -ETIMEDOUT;
+	}
+
+	/* Configure for VP-Force Update */
+	vpconfig = vdd->read_reg(vp->vp_common->prm_mod, vp->vpconfig);
+	vpconfig &= ~(vp->vp_common->vpconfig_initvdd |
+			vp->vp_common->vpconfig_forceupdate |
+			vp->vp_common->vpconfig_initvoltage_mask);
+	vpconfig |= ((target_vsel <<
+			vp->vp_common->vpconfig_initvoltage_shift));
+	vdd->write_reg(vpconfig, vp->vp_common->prm_mod, vp->vpconfig);
+
+	/* Trigger initVDD value copy to voltage processor */
+	vpconfig |= vp->vp_common->vpconfig_initvdd;
+	vdd->write_reg(vpconfig, vp->vp_common->prm_mod, vp->vpconfig);
+
+	/* Force update of voltage */
+	vpconfig |= vp->vp_common->vpconfig_forceupdate;
+	vdd->write_reg(vpconfig, vp->vp_common->prm_mod, vp->vpconfig);
+
+	/*
+	 * Wait for TransactionDone. Typical latency is <200us.
+	 * Depends on SMPSWAITTIMEMIN/MAX and voltage change
+	 */
+	timeout = 0;
+	omap_test_timeout((vdd->read_reg(vdd->prm_irqst_mod,
+					 vdd->prm_irqst_reg) &
+			   vp->prm_irqst_data->tranxdone_status),
+			  VP_TRANXDONE_TIMEOUT, timeout);
+	if (timeout >= VP_TRANXDONE_TIMEOUT)
+		pr_err("%s: vdd_%s TRANXDONE timeout exceeded."
+			"TRANXDONE never got set after the voltage update\n",
+			__func__, voltdm->name);
+
+	omap_vc_post_scale(voltdm, target_volt, target_vsel, current_vsel);
+
+	/*
+	 * Disable TransactionDone interrupt , clear all status, clear
+	 * control registers
+	 */
+	timeout = 0;
+	while (timeout++ < VP_TRANXDONE_TIMEOUT) {
+		vdd->write_reg(vp->prm_irqst_data->tranxdone_status,
+			       vdd->prm_irqst_mod, vdd->prm_irqst_reg);
+		if (!(vdd->read_reg(vdd->prm_irqst_mod, vdd->prm_irqst_reg) &
+		      vp->prm_irqst_data->tranxdone_status))
+			break;
+		udelay(1);
+	}
+
+	if (timeout >= VP_TRANXDONE_TIMEOUT)
+		pr_warning("%s: vdd_%s TRANXDONE timeout exceeded while trying"
+			"to clear the TRANXDONE status\n",
+			__func__, voltdm->name);
+
+	vpconfig = vdd->read_reg(vp->vp_common->prm_mod, vp->vpconfig);
+	/* Clear initVDD copy trigger bit */
+	vpconfig &= ~vp->vp_common->vpconfig_initvdd;
+	vdd->write_reg(vpconfig, vp->vp_common->prm_mod, vp->vpconfig);
+	/* Clear force bit */
+	vpconfig &= ~vp->vp_common->vpconfig_forceupdate;
+	vdd->write_reg(vpconfig, vp->vp_common->prm_mod, vp->vpconfig);
+
+	return 0;
+}
+
+/**
+ * omap_vp_get_curr_volt() - API to get the current vp voltage.
+ * @voltdm:	pointer to the VDD.
+ *
+ * This API returns the current voltage for the specified voltage processor
+ */
+unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm)
+{
+	struct omap_vp_instance_data *vp = voltdm->vdd->vp_data;
+	struct omap_vdd_info *vdd;
+	u8 curr_vsel;
+
+	if (!voltdm || IS_ERR(voltdm)) {
+		pr_warning("%s: VDD specified does not exist!\n", __func__);
+		return 0;
+	}
+
+	vdd = voltdm->vdd;
+	if (!vdd->read_reg) {
+		pr_err("%s: No read API for reading vdd_%s regs\n",
+			__func__, voltdm->name);
+		return 0;
+	}
+
+	curr_vsel = vdd->read_reg(vp->vp_common->prm_mod, vp->voltage);
+
+	if (!vdd->pmic_info || !vdd->pmic_info->vsel_to_uv) {
+		pr_warning("%s: PMIC function to convert vsel to voltage"
+			"in uV not registerd\n", __func__);
+		return 0;
+	}
+
+	return vdd->pmic_info->vsel_to_uv(curr_vsel);
+}
+
+/**
+ * omap_vp_enable() - API to enable a particular VP
+ * @voltdm:	pointer to the VDD whose VP is to be enabled.
+ *
+ * This API enables a particular voltage processor. Needed by the smartreflex
+ * class drivers.
+ */
+void omap_vp_enable(struct voltagedomain *voltdm)
+{
+	struct omap_vp_instance_data *vp;
+	struct omap_vdd_info *vdd;
+	u32 vpconfig;
+
+	if (!voltdm || IS_ERR(voltdm)) {
+		pr_warning("%s: VDD specified does not exist!\n", __func__);
+		return;
+	}
+
+	vdd = voltdm->vdd;
+	vp = voltdm->vdd->vp_data;
+	if (!vdd->read_reg || !vdd->write_reg) {
+		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
+			__func__, voltdm->name);
+		return;
+	}
+
+	/* If VP is already enabled, do nothing. Return */
+	if (vdd->vp_enabled)
+		return;
+
+	vp_latch_vsel(voltdm);
+
+	/* Enable VP */
+	vpconfig = vdd->read_reg(vp->vp_common->prm_mod, vp->vpconfig);
+	vpconfig |= vp->vp_common->vpconfig_vpenable;
+	vdd->write_reg(vpconfig, vp->vp_common->prm_mod, vp->vpconfig);
+	vdd->vp_enabled = true;
+}
+
+/**
+ * omap_vp_disable() - API to disable a particular VP
+ * @voltdm:	pointer to the VDD whose VP is to be disabled.
+ *
+ * This API disables a particular voltage processor. Needed by the smartreflex
+ * class drivers.
+ */
+void omap_vp_disable(struct voltagedomain *voltdm)
+{
+	struct omap_vp_instance_data *vp;
+	struct omap_vdd_info *vdd;
+	u32 vpconfig;
+	int timeout;
+
+	if (!voltdm || IS_ERR(voltdm)) {
+		pr_warning("%s: VDD specified does not exist!\n", __func__);
+		return;
+	}
+
+	vdd = voltdm->vdd;
+	vp = voltdm->vdd->vp_data;
+	if (!vdd->read_reg || !vdd->write_reg) {
+		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
+			__func__, voltdm->name);
+		return;
+	}
+
+	/* If VP is already disabled, do nothing. Return */
+	if (!vdd->vp_enabled) {
+		pr_warning("%s: Trying to disable VP for vdd_%s when"
+			"it is already disabled\n", __func__, voltdm->name);
+		return;
+	}
+
+	/* Disable VP */
+	vpconfig = vdd->read_reg(vp->vp_common->prm_mod, vp->vpconfig);
+	vpconfig &= ~vp->vp_common->vpconfig_vpenable;
+	vdd->write_reg(vpconfig, vp->vp_common->prm_mod, vp->vpconfig);
+
+	/*
+	 * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us
+	 */
+	omap_test_timeout((vdd->read_reg(vp->vp_common->prm_mod, vp->vstatus)),
+				VP_IDLE_TIMEOUT, timeout);
+
+	if (timeout >= VP_IDLE_TIMEOUT)
+		pr_warning("%s: vdd_%s idle timedout\n",
+			__func__, voltdm->name);
+
+	vdd->vp_enabled = false;
+
+	return;
+}
+
+/* Voltage debugfs support */
+static int vp_volt_debug_get(void *data, u64 *val)
+{
+	struct voltagedomain *voltdm = (struct voltagedomain *)data;
+	struct omap_vp_instance_data *vp = voltdm->vdd->vp_data;
+	struct omap_vdd_info *vdd = voltdm->vdd;
+	u8 vsel;
+
+	if (!vdd) {
+		pr_warning("Wrong paramater passed\n");
+		return -EINVAL;
+	}
+
+	vsel = vdd->read_reg(vp->vp_common->prm_mod, vp->voltage);
+
+	if (!vdd->pmic_info->vsel_to_uv) {
+		pr_warning("PMIC function to convert vsel to voltage"
+			"in uV not registerd\n");
+		return -EINVAL;
+	}
+
+	*val = vdd->pmic_info->vsel_to_uv(vsel);
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(vp_volt_debug_fops, vp_volt_debug_get, NULL, "%llu\n");
+
+static void __init vp_debugfs_init(struct voltagedomain *voltdm)
+{
+	struct omap_vdd_info *vdd = voltdm->vdd;
+	struct dentry *debug_dir;
+
+	debug_dir = debugfs_create_dir("vp", vdd->debug_dir);
+	if (IS_ERR(debug_dir))
+		pr_err("%s: Unable to create VP debugfs dir dir\n", __func__);
+
+	(void) debugfs_create_x16("errorgain", S_IRUGO, debug_dir,
+				&(vdd->vp_rt_data.vpconfig_errorgain));
+	(void) debugfs_create_x16("smpswaittimemin", S_IRUGO,
+				debug_dir,
+				&(vdd->vp_rt_data.vstepmin_smpswaittimemin));
+	(void) debugfs_create_x8("stepmin", S_IRUGO, debug_dir,
+				&(vdd->vp_rt_data.vstepmin_stepmin));
+	(void) debugfs_create_x16("smpswaittimemax", S_IRUGO,
+				debug_dir,
+				&(vdd->vp_rt_data.vstepmax_smpswaittimemax));
+	(void) debugfs_create_x8("stepmax", S_IRUGO, debug_dir,
+				&(vdd->vp_rt_data.vstepmax_stepmax));
+	(void) debugfs_create_x8("vddmax", S_IRUGO, debug_dir,
+				&(vdd->vp_rt_data.vlimitto_vddmax));
+	(void) debugfs_create_x8("vddmin", S_IRUGO, debug_dir,
+				&(vdd->vp_rt_data.vlimitto_vddmin));
+	(void) debugfs_create_x16("timeout", S_IRUGO, debug_dir,
+				&(vdd->vp_rt_data.vlimitto_timeout));
+	(void) debugfs_create_file("curr_volt", S_IRUGO, debug_dir,
+				(void *) voltdm, &vp_volt_debug_fops);
+}
diff --git a/arch/arm/mach-omap2/vp.h b/arch/arm/mach-omap2/vp.h
index 5406b08..025cf16 100644
--- a/arch/arm/mach-omap2/vp.h
+++ b/arch/arm/mach-omap2/vp.h
@@ -19,6 +19,8 @@
 
 #include <linux/kernel.h>
 
+struct voltagedomain;
+
 /* XXX document */
 #define VP_IDLE_TIMEOUT		200
 #define VP_TRANXDONE_TIMEOUT	300
@@ -139,4 +141,11 @@ extern struct omap_vp_instance_data omap4_vp_mpu_data;
 extern struct omap_vp_instance_data omap4_vp_iva_data;
 extern struct omap_vp_instance_data omap4_vp_core_data;
 
+void omap_vp_init(struct voltagedomain *voltdm);
+void omap_vp_enable(struct voltagedomain *voltdm);
+void omap_vp_disable(struct voltagedomain *voltdm);
+unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm);
+int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
+			      unsigned long target_volt);
+
 #endif
-- 
1.7.2.5

