summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/tegra_cl_dvfs.c
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2013-10-11 23:32:04 -0700
committerYu-Huan Hsu <yhsu@nvidia.com>2013-10-14 12:54:10 -0700
commite955cf9a83a31fb603be3f92d7a30e3e97d2e1e4 (patch)
tree5105eafa777175f59a43b91c9d585bf043ca6d18 /arch/arm/mach-tegra/tegra_cl_dvfs.c
parentdf96d264eec6338b2e08d05465d1c6d08d3eb658 (diff)
ARM: tegra: dvfs: Explicitly enumerate CL-DVFS PWM buses
Defined explicit enumeration for supported Cl-DVFS PWM configurations: - 1-wire bus with external buffer between CL-DVFS data output and PMIC input - 1-wire bus with direct connection from CL-DVFS data output and PMIC input - 2-wire bus with direct connection from CL-DVFS data/clock outputs and PMIC inputs Re-factored PWM control code to use this explicit definitions instead of inferring bus configuration from gpio and/or pingroup specification in platform data. Populate bus enumerations entries in platform data on platforms that use Cl-DVFS PWM interface (ardbeg and loki Tegra12 platforms). Bug 1349163 Change-Id: I1af3a7c2ee189f891b7639d4cbed9f057355b9cf Signed-off-by: Alex Frid <afrid@nvidia.com> Reviewed-on: http://git-master/r/298708 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/tegra_cl_dvfs.c')
-rw-r--r--arch/arm/mach-tegra/tegra_cl_dvfs.c62
1 files changed, 45 insertions, 17 deletions
diff --git a/arch/arm/mach-tegra/tegra_cl_dvfs.c b/arch/arm/mach-tegra/tegra_cl_dvfs.c
index b30e951e96ff..aa47a3905b4b 100644
--- a/arch/arm/mach-tegra/tegra_cl_dvfs.c
+++ b/arch/arm/mach-tegra/tegra_cl_dvfs.c
@@ -323,15 +323,16 @@ static int output_enable(struct tegra_cl_dvfs *cld)
if (is_i2c(cld)) {
val |= CL_DVFS_OUTPUT_CFG_I2C_ENABLE;
} else {
- int pg, gpio = cld->p_data->u.pmu_pwm.out_gpio;
- if (gpio) {
- int v = cld->p_data->u.pmu_pwm.out_enable_high ? 1 : 0;
+ struct tegra_cl_dvfs_platform_data *d = cld->p_data;
+ if (d->u.pmu_pwm.pwm_bus == TEGRA_CL_DVFS_PWM_1WIRE_BUFFER) {
+ int gpio = d->u.pmu_pwm.out_gpio;
+ int v = d->u.pmu_pwm.out_enable_high ? 1 : 0;
__gpio_set_value(gpio, v);
return 0;
}
- pg = cld->p_data->u.pmu_pwm.pwm_pingroup;
- if (pg) {
+ if (d->u.pmu_pwm.pwm_bus == TEGRA_CL_DVFS_PWM_1WIRE_DIRECT) {
+ int pg = d->u.pmu_pwm.pwm_pingroup;
tegra_pinmux_set_tristate(pg, TEGRA_TRI_NORMAL);
return 0;
}
@@ -347,16 +348,17 @@ static int output_enable(struct tegra_cl_dvfs *cld)
static int output_disable_pwm(struct tegra_cl_dvfs *cld)
{
u32 val;
+ struct tegra_cl_dvfs_platform_data *d = cld->p_data;
- int pg, gpio = cld->p_data->u.pmu_pwm.out_gpio;
- if (gpio) {
- int v = cld->p_data->u.pmu_pwm.out_enable_high ? 0 : 1;
+ if (d->u.pmu_pwm.pwm_bus == TEGRA_CL_DVFS_PWM_1WIRE_BUFFER) {
+ int gpio = d->u.pmu_pwm.out_gpio;
+ int v = d->u.pmu_pwm.out_enable_high ? 0 : 1;
__gpio_set_value(gpio, v);
return 0;
}
- pg = cld->p_data->u.pmu_pwm.pwm_pingroup;
- if (pg) {
+ if (d->u.pmu_pwm.pwm_bus == TEGRA_CL_DVFS_PWM_1WIRE_DIRECT) {
+ int pg = d->u.pmu_pwm.pwm_pingroup;
tegra_pinmux_set_tristate(pg, TEGRA_TRI_TRISTATE);
return 0;
}
@@ -1080,6 +1082,8 @@ static void cl_dvfs_init_pwm_if(struct tegra_cl_dvfs *cld)
u32 val, div;
struct tegra_cl_dvfs_platform_data *p_data = cld->p_data;
bool delta_mode = p_data->u.pmu_pwm.delta_mode;
+ int pg = p_data->u.pmu_pwm.pwm_pingroup;
+ int pcg = p_data->u.pmu_pwm.pwm_clk_pingroup;
div = GET_DIV(cld->ref_rate, p_data->u.pmu_pwm.pwm_rate, 1);
@@ -1090,13 +1094,31 @@ static void cl_dvfs_init_pwm_if(struct tegra_cl_dvfs *cld)
/*
* Different ways to enable/disable PWM depending on board design:
- * a) Use native CL-DVFS output configuration PWM_ENABLE control
- * b) Use gpio control of external buffer (out_gpio is populated)
- * c) Use tristate PWM pingroup control (pwm_pingroup is populated)
+ * a) Use native CL-DVFS output PWM_ENABLE control (2WIRE bus)
+ * b) Use gpio control of external buffer (1WIRE bus with buffer)
+ * c) Use tristate PWM pingroup control (1WIRE bus with direct connect)
* in cases (b) and (c) keep CL-DVFS native control always enabled
*/
- if (p_data->u.pmu_pwm.out_gpio || p_data->u.pmu_pwm.pwm_pingroup)
+
+ switch (p_data->u.pmu_pwm.pwm_bus) {
+ case TEGRA_CL_DVFS_PWM_1WIRE_BUFFER:
+ tegra_pinmux_set_tristate(pg, TEGRA_TRI_NORMAL);
val |= CL_DVFS_OUTPUT_CFG_PWM_ENABLE;
+ break;
+
+ case TEGRA_CL_DVFS_PWM_1WIRE_DIRECT:
+ tegra_pinmux_set_tristate(pg, TEGRA_TRI_TRISTATE);
+ val |= CL_DVFS_OUTPUT_CFG_PWM_ENABLE;
+ break;
+
+ case TEGRA_CL_DVFS_PWM_2WIRE:
+ tegra_pinmux_set_tristate(pg, TEGRA_TRI_NORMAL);
+ tegra_pinmux_set_tristate(pcg, TEGRA_TRI_NORMAL);
+ break;
+
+ default:
+ BUG();
+ }
cl_dvfs_writel(cld, val, CL_DVFS_OUTPUT_CFG);
cl_dvfs_wmb(cld);
@@ -1274,7 +1296,7 @@ static void cl_dvfs_disable_clocks(struct tegra_cl_dvfs *cld)
static int cl_dvfs_init(struct tegra_cl_dvfs *cld)
{
- int ret;
+ int ret, gpio, flags;
/* Enable output inerface clock */
if (cld->p_data->pmu_if == TEGRA_CL_DVFS_PMU_I2C) {
@@ -1286,8 +1308,14 @@ static int cl_dvfs_init(struct tegra_cl_dvfs *cld)
}
cld->i2c_rate = clk_get_rate(cld->i2c_clk);
} else if (cld->p_data->pmu_if == TEGRA_CL_DVFS_PMU_PWM) {
- int gpio = cld->p_data->u.pmu_pwm.out_gpio;
- int flags = cld->p_data->u.pmu_pwm.out_enable_high ?
+ if (cld->p_data->u.pmu_pwm.pwm_bus >
+ TEGRA_CL_DVFS_PWM_1WIRE_DIRECT) {
+ /* FIXME: PWM 2-wire support */
+ pr_err("%s: not supported PWM 2-wire bus\n", __func__);
+ return -ENOSYS;
+ }
+ gpio = cld->p_data->u.pmu_pwm.out_gpio;
+ flags = cld->p_data->u.pmu_pwm.out_enable_high ?
GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH;
if (gpio && gpio_request_one(gpio, flags, "cl_dvfs_pwm")) {
pr_err("%s: Failed to request pwm gpio %d\n",