diff options
author | Alex Frid <afrid@nvidia.com> | 2013-10-11 23:32:04 -0700 |
---|---|---|
committer | Yu-Huan Hsu <yhsu@nvidia.com> | 2013-10-14 12:54:10 -0700 |
commit | e955cf9a83a31fb603be3f92d7a30e3e97d2e1e4 (patch) | |
tree | 5105eafa777175f59a43b91c9d585bf043ca6d18 /arch/arm/mach-tegra/tegra_cl_dvfs.c | |
parent | df96d264eec6338b2e08d05465d1c6d08d3eb658 (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.c | 62 |
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", |