From: Kevin Hilman <khilman@ti.com>
To: linux-omap@vger.kernel.org
Cc: Paul Walmsely <paul@pwsan.com>, Benoit Cousson <b-cousson@ti.com>
Subject: [PATCH/RFC 16/19] OMAP2+: voltage: split out voltage processor (VP) code into new layer
Date: Wed, 23 Mar 2011 17:00:30 -0700 [thread overview]
Message-ID: <1300924833-26745-17-git-send-email-khilman@ti.com> (raw)
In-Reply-To: <1300924833-26745-1-git-send-email-khilman@ti.com>
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 a0d8f61..bb82611 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 a7dd088..985d55a 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, ¤t_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_voltage;
@@ -805,8 +463,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);
}
if (voltdm->vc)
diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h
index 68a9439..c5d3087 100644
--- a/arch/arm/mach-omap2/voltage.h
+++ b/arch/arm/mach-omap2/voltage.h
@@ -159,9 +159,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, ¤t_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.4
next prev parent reply other threads:[~2011-03-24 0:00 UTC|newest]
Thread overview: 50+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-03-24 0:00 [PATCH/RFC 00/19] OMAP: voltage layer cleanup and restructure Kevin Hilman
2011-03-24 0:00 ` [PATCH/RFC 01/19] OMAP2+: hwmod: remove unused voltagedomain pointer Kevin Hilman
2011-03-25 8:58 ` Jean Pihet
2011-03-25 14:24 ` Kevin Hilman
2011-03-24 0:00 ` [PATCH/RFC 02/19] OMAP2+: voltage: move PRCM mod offets into VC/VP structures Kevin Hilman
2011-03-24 0:00 ` [PATCH/RFC 03/19] OMAP2+: voltage: move prm_irqst_reg from VP into voltage domain Kevin Hilman
2011-03-24 0:00 ` [PATCH/RFC 04/19] OMAP2+: voltage: start towards a new voltagedomain layer Kevin Hilman
2011-03-25 8:59 ` Jean Pihet
2011-03-25 15:48 ` Kevin Hilman
2011-03-25 16:41 ` Jean Pihet
2011-03-24 0:00 ` [PATCH/RFC 05/19] OMAP3: voltage: rename "mpu" voltagedomain to "mpu_iva" Kevin Hilman
2011-03-24 0:00 ` [PATCH/RFC 06/19] OMAP3: voltagedomain data: add wakeup domain Kevin Hilman
2011-03-25 9:00 ` Jean Pihet
2011-03-24 0:00 ` [PATCH/RFC 07/19] OMAP3: voltage: add scalable flag to voltagedomain Kevin Hilman
2011-03-24 5:23 ` Vishwanath Sripathy
2011-03-24 14:12 ` Kevin Hilman
2011-03-24 14:54 ` Cousson, Benoit
2011-03-24 17:31 ` Vishwanath Sripathy
2011-03-24 0:00 ` [PATCH/RFC 08/19] OMAP2+: powerdomain: add voltagedomain to struct powerdomain Kevin Hilman
2011-03-25 9:05 ` Jean Pihet
2011-03-25 15:49 ` Kevin Hilman
2011-03-24 0:00 ` [PATCH/RFC 09/19] OMAP2: add voltage domains and connect to powerdomains Kevin Hilman
2011-03-24 0:00 ` [PATCH/RFC 10/19] OMAP3: powerdomain data: add voltage domains Kevin Hilman
2011-03-25 9:09 ` Jean Pihet
2011-03-25 15:51 ` Kevin Hilman
2011-03-25 16:43 ` Jean Pihet
2011-03-24 0:00 ` [PATCH/RFC 11/19] OMAP4: " Kevin Hilman
2011-03-24 0:00 ` [PATCH/RFC 12/19] OMAP2+: powerdomain: add voltage domain lookup during register Kevin Hilman
2011-03-25 9:18 ` Jean Pihet
2011-03-25 15:52 ` Kevin Hilman
2011-03-24 0:00 ` [PATCH/RFC 13/19] OMAP2+: voltage: keep track of powerdomains in each voltagedomain Kevin Hilman
2011-03-25 9:22 ` Jean Pihet
2011-03-25 15:56 ` Kevin Hilman
2011-03-25 16:52 ` Jean Pihet
2011-03-24 0:00 ` [PATCH/RFC 14/19] OMAP2+: voltage: split voltage controller (VC) code into dedicated layer Kevin Hilman
2011-03-25 9:26 ` Jean Pihet
2011-03-24 0:00 ` [PATCH/RFC 15/19] OMAP2+: voltage: move VC into struct voltagedomain, misc. renames Kevin Hilman
2011-03-24 0:00 ` Kevin Hilman [this message]
2011-03-24 0:00 ` [PATCH/RFC 17/19] OMAP2+: voltage: VC: begin spliting out SoC specifics; start with i2c slave addr Kevin Hilman
2011-03-24 0:00 ` [PATCH/RFC 18/19] OMAP2+: VC: support PMICs with separate voltage and command registers Kevin Hilman
2011-03-24 0:00 ` [PATCH/RFC 19/19] OMAP2+: VC: add SoC-specific op for PMIC register addresses Kevin Hilman
2011-03-25 0:02 ` [PATCH/RFC 00/19] OMAP: voltage layer cleanup and restructure Kevin Hilman
2011-03-25 0:09 ` [PATCH] OMAP2+: VC: begin spliting out SoC specifics; start with i2c slave addr Kevin Hilman
2011-03-25 0:09 ` [PATCH] OMAP2+: VC: add SoC-specific op for PMIC register addresses Kevin Hilman
2011-03-25 9:31 ` Vishwanath Sripathy
2011-03-25 14:22 ` Kevin Hilman
2011-03-25 14:37 ` [PATCH/RFC 00/19] OMAP: voltage layer cleanup and restructure Cousson, Benoit
2011-03-25 23:02 ` Paul Walmsley
2011-03-26 0:20 ` Kevin Hilman
2011-03-25 8:58 ` Jean Pihet
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1300924833-26745-17-git-send-email-khilman@ti.com \
--to=khilman@ti.com \
--cc=b-cousson@ti.com \
--cc=linux-omap@vger.kernel.org \
--cc=paul@pwsan.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).