OMAP2+: voltage: split out voltage processor (VP) code into new layer
authorKevin Hilman <khilman@ti.com>
Mon, 21 Mar 2011 21:29:13 +0000 (14:29 -0700)
committerKevin Hilman <khilman@ti.com>
Thu, 15 Sep 2011 18:39:11 +0000 (11:39 -0700)
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
arch/arm/mach-omap2/voltage.c
arch/arm/mach-omap2/voltage.h
arch/arm/mach-omap2/vp.c [new file with mode: 0644]
arch/arm/mach-omap2/vp.h

index 59db6d9ba244652f9b618a54e785b76d1a01f08d..824718969e31b683d672e0e2bee3b59ade4edaf3 100644 (file)
@@ -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) \
index e1a22a3d2f035df413b3f84457cf11f275afe60d..9b9f01973d122251157f6b3f6898d2cc391a0b44 100644 (file)
@@ -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;
@@ -438,129 +219,6 @@ unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm)
        return vdd->curr_volt;
 }
 
-/**
- * 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.
@@ -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);
                }
        }
 
index 488576497c883d4f2bb275410c72e811482f2aae..ea6bb98c63f8428012f02dcbba90c716aed1232a 100644 (file)
@@ -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 (file)
index 0000000..f3503de
--- /dev/null
@@ -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);
+}
index 5406b08463b626b98ab733fe7b730597a4f1e8f0..025cf164da71ee016f74233e8a20aff95068ce16 100644 (file)
@@ -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