msm: footswitch-8x60: Update 8064 footswitch_enable() sequence for GFX3D

Update 8064's GFX3D enable sequence per hardware designer recommendations
to improve system stability when responding to the inrush current event.

Differences from the standard footswitch_enable() sequence include:
 - Decreasing the reset_rate from 27MHz to 1.8MHz, and increasing
   reset_delay_us from 1us to 10us to compensate for the slower clock.
 - Enable clocks for reset propagation only after the core has been
   powered on.
 - Forcefully limit the AFAB and EBI1 clocks to a low value (decided
   by the RPM) by means of a write to the RPM_CTL RPM resource.
 - Removal of the reset toggle after powering on the core, which (while
   harmless) is not applicable to 8064.

Change-Id: I943842b56ff96b2e6077a419566d91ac184a6fda
Signed-off-by: Matt Wagantall <mattw@codeaurora.org>
This commit is contained in:
Matt Wagantall
2013-04-01 16:18:37 -07:00
committed by Iliyan Malchev
parent 667dd0a4f3
commit 38116f735b
4 changed files with 131 additions and 6 deletions

View File

@@ -5443,9 +5443,9 @@ static struct clk_lookup msm_clocks_8064[] = {
CLK_LOOKUP("npl_clk", npl_tv_clk.c, ""), CLK_LOOKUP("npl_clk", npl_tv_clk.c, ""),
CLK_LOOKUP("core_clk", gfx3d_clk.c, "kgsl-3d0.0"), CLK_LOOKUP("core_clk", gfx3d_clk.c, "kgsl-3d0.0"),
CLK_LOOKUP("core_clk", gfx3d_clk.c, "footswitch-8x60.2"), CLK_LOOKUP("core_clk", gfx3d_clk.c, "footswitch-8x60.11"),
CLK_LOOKUP("bus_clk", CLK_LOOKUP("bus_clk",
gfx3d_axi_clk.c, "footswitch-8x60.2"), gfx3d_axi_clk.c, "footswitch-8x60.11"),
CLK_LOOKUP("iface_clk", vcap_p_clk.c, ""), CLK_LOOKUP("iface_clk", vcap_p_clk.c, ""),
CLK_LOOKUP("iface_clk", vcap_p_clk.c, "msm_vcap.0"), CLK_LOOKUP("iface_clk", vcap_p_clk.c, "msm_vcap.0"),
CLK_LOOKUP("iface_clk", vcap_p_clk.c, "footswitch-8x60.10"), CLK_LOOKUP("iface_clk", vcap_p_clk.c, "footswitch-8x60.10"),
@@ -5499,7 +5499,7 @@ static struct clk_lookup msm_clocks_8064[] = {
CLK_LOOKUP("master_iface_clk", dsi2_m_p_clk.c, "mipi_dsi.2"), CLK_LOOKUP("master_iface_clk", dsi2_m_p_clk.c, "mipi_dsi.2"),
CLK_LOOKUP("slave_iface_clk", dsi2_s_p_clk.c, "mipi_dsi.2"), CLK_LOOKUP("slave_iface_clk", dsi2_s_p_clk.c, "mipi_dsi.2"),
CLK_LOOKUP("iface_clk", gfx3d_p_clk.c, "kgsl-3d0.0"), CLK_LOOKUP("iface_clk", gfx3d_p_clk.c, "kgsl-3d0.0"),
CLK_LOOKUP("iface_clk", gfx3d_p_clk.c, "footswitch-8x60.2"), CLK_LOOKUP("iface_clk", gfx3d_p_clk.c, "footswitch-8x60.11"),
CLK_LOOKUP("master_iface_clk", hdmi_m_p_clk.c, "hdmi_msm.1"), CLK_LOOKUP("master_iface_clk", hdmi_m_p_clk.c, "hdmi_msm.1"),
CLK_LOOKUP("slave_iface_clk", hdmi_s_p_clk.c, "hdmi_msm.1"), CLK_LOOKUP("slave_iface_clk", hdmi_s_p_clk.c, "hdmi_msm.1"),
CLK_LOOKUP("iface_clk", ijpeg_p_clk.c, "msm_gemini.0"), CLK_LOOKUP("iface_clk", ijpeg_p_clk.c, "msm_gemini.0"),

View File

@@ -1965,11 +1965,12 @@ struct platform_device msm_gss = {
static struct fs_driver_data gfx3d_fs_data = { static struct fs_driver_data gfx3d_fs_data = {
.clks = (struct fs_clk_data[]){ .clks = (struct fs_clk_data[]){
{ .name = "core_clk", .reset_rate = 27000000 }, { .name = "core_clk", .reset_rate = 1800000 },
{ .name = "iface_clk" }, { .name = "iface_clk" },
{ .name = "bus_clk" }, { .name = "bus_clk" },
{ 0 } { 0 }
}, },
.reset_delay_us = 10,
.bus_port0 = MSM_BUS_MASTER_GRAPHICS_3D, .bus_port0 = MSM_BUS_MASTER_GRAPHICS_3D,
.bus_port1 = MSM_BUS_MASTER_GRAPHICS_3D_PORT1, .bus_port1 = MSM_BUS_MASTER_GRAPHICS_3D_PORT1,
}; };
@@ -2058,7 +2059,7 @@ struct platform_device *apq8064_footswitch[] __initdata = {
FS_8X60(FS_IJPEG, "vdd", "msm_gemini.0", &ijpeg_fs_data), FS_8X60(FS_IJPEG, "vdd", "msm_gemini.0", &ijpeg_fs_data),
FS_8X60(FS_VFE, "vdd", "msm_vfe32.0", &vfe_fs_data), FS_8X60(FS_VFE, "vdd", "msm_vfe32.0", &vfe_fs_data),
FS_8X60(FS_VPE, "vdd", "msm_vpe.0", &vpe_fs_data), FS_8X60(FS_VPE, "vdd", "msm_vpe.0", &vpe_fs_data),
FS_8X60(FS_GFX3D, "vdd", "kgsl-3d0.0", &gfx3d_fs_data), FS_8X60(FS_GFX3D_8064, "vdd", "kgsl-3d0.0", &gfx3d_fs_data),
FS_8X60(FS_VED, "vdd", "msm_vidc.0", &ved_fs_data), FS_8X60(FS_VED, "vdd", "msm_vidc.0", &ved_fs_data),
FS_8X60(FS_VCAP, "vdd", "msm_vcap.0", &vcap_fs_data), FS_8X60(FS_VCAP, "vdd", "msm_vcap.0", &vcap_fs_data),
}; };

View File

@@ -25,7 +25,10 @@
#include <mach/msm_bus.h> #include <mach/msm_bus.h>
#include <mach/scm-io.h> #include <mach/scm-io.h>
#include <mach/clk.h> #include <mach/clk.h>
#include <mach/rpm.h>
#include "footswitch.h" #include "footswitch.h"
#include "rpm_resources.h"
#ifdef CONFIG_MSM_SECURE_IO #ifdef CONFIG_MSM_SECURE_IO
#undef readl_relaxed #undef readl_relaxed
@@ -449,6 +452,118 @@ err:
return rc; return rc;
} }
static void force_bus_clocks(bool enforce)
{
static struct msm_rpm_iv_pair iv;
int ret;
if (enforce) {
iv.id = MSM_RPM_STATUS_ID_RPM_CTL;
ret = msm_rpm_get_status(&iv, 1);
if (ret)
pr_err("Failed to read RPM_CTL resource status\n");
iv.id = MSM_RPM_ID_RPM_CTL;
iv.value |= BIT(6);
} else {
iv.value &= ~BIT(6);
}
ret = msm_rpmrs_set(MSM_RPM_CTX_SET_0, &iv, 1);
if (ret)
pr_err("Force bus clocks request=%d failed\n", enforce);
}
static int gfx3d_8064_footswitch_enable(struct regulator_dev *rdev)
{
struct footswitch *fs = rdev_get_drvdata(rdev);
struct fs_clk_data *clock;
uint32_t regval, rc = 0;
mutex_lock(&claim_lock);
fs->is_claimed = true;
mutex_unlock(&claim_lock);
/* Return early if already enabled. */
regval = readl_relaxed(fs->gfs_ctl_reg);
if ((regval & (ENABLE_BIT | CLAMP_BIT)) == ENABLE_BIT)
return 0;
/* Un-halt all bus ports in the power domain. */
if (fs->bus_port0) {
rc = msm_bus_axi_portunhalt(fs->bus_port0);
if (rc) {
pr_err("%s port 0 unhalt failed.\n", fs->desc.name);
goto err;
}
}
if (fs->bus_port1) {
rc = msm_bus_axi_portunhalt(fs->bus_port1);
if (rc) {
pr_err("%s port 1 unhalt failed.\n", fs->desc.name);
goto err_port2_halt;
}
}
/* Apply AFAB/EBI clock limits. */
force_bus_clocks(true);
/* Enable the power rail at the footswitch. */
regval |= ENABLE_BIT;
writel_relaxed(regval, fs->gfs_ctl_reg);
/* Wait for the rail to fully charge. */
mb();
udelay(1);
/* Make sure required clocks are on at the correct rates. */
rc = setup_clocks(fs);
if (rc)
goto err_setup_clocks;
/*
* (Re-)Assert resets for all clocks in the clock domain, since
* footswitch_enable() is first called before footswitch_disable()
* and resets should be asserted before power is restored.
*/
for (clock = fs->clk_data; clock->clk; clock++)
; /* Do nothing */
for (clock--; clock >= fs->clk_data; clock--)
clk_reset(clock->clk, CLK_RESET_ASSERT);
/* Wait for synchronous resets to propagate. */
udelay(fs->reset_delay_us);
/* Un-clamp the I/O ports. */
regval &= ~CLAMP_BIT;
writel_relaxed(regval, fs->gfs_ctl_reg);
/* Deassert resets for all clocks in the power domain. */
for (clock = fs->clk_data; clock->clk; clock++)
clk_reset(clock->clk, CLK_RESET_DEASSERT);
/* Prevent core memory from collapsing when its clock is gated. */
clk_set_flags(fs->core_clk, CLKFLAG_RETAIN);
/* Return clocks to their state before this function. */
restore_clocks(fs);
/* Remove AFAB/EBI clock limits after any transients have settled. */
udelay(30);
force_bus_clocks(false);
fs->is_enabled = true;
return 0;
err_setup_clocks:
regval &= ~ENABLE_BIT;
writel_relaxed(regval, fs->gfs_ctl_reg);
force_bus_clocks(false);
err_port2_halt:
msm_bus_axi_porthalt(fs->bus_port0);
err:
return rc;
}
static struct regulator_ops standard_fs_ops = { static struct regulator_ops standard_fs_ops = {
.is_enabled = footswitch_is_enabled, .is_enabled = footswitch_is_enabled,
.enable = footswitch_enable, .enable = footswitch_enable,
@@ -461,6 +576,12 @@ static struct regulator_ops gfx2d_fs_ops = {
.disable = gfx2d_footswitch_disable, .disable = gfx2d_footswitch_disable,
}; };
static struct regulator_ops gfx3d_8064_fs_ops = {
.is_enabled = footswitch_is_enabled,
.enable = gfx3d_8064_footswitch_enable,
.disable = footswitch_disable,
};
#define FOOTSWITCH(_id, _name, _ops, _gfs_ctl_reg) \ #define FOOTSWITCH(_id, _name, _ops, _gfs_ctl_reg) \
[(_id)] = { \ [(_id)] = { \
.desc = { \ .desc = { \
@@ -475,6 +596,8 @@ static struct regulator_ops gfx2d_fs_ops = {
static struct footswitch footswitches[] = { static struct footswitch footswitches[] = {
FOOTSWITCH(FS_GFX2D0, "fs_gfx2d0", &gfx2d_fs_ops, GFX2D0_GFS_CTL_REG), FOOTSWITCH(FS_GFX2D0, "fs_gfx2d0", &gfx2d_fs_ops, GFX2D0_GFS_CTL_REG),
FOOTSWITCH(FS_GFX2D1, "fs_gfx2d1", &gfx2d_fs_ops, GFX2D1_GFS_CTL_REG), FOOTSWITCH(FS_GFX2D1, "fs_gfx2d1", &gfx2d_fs_ops, GFX2D1_GFS_CTL_REG),
FOOTSWITCH(FS_GFX3D_8064, "fs_gfx3d", &gfx3d_8064_fs_ops,
GFX3D_GFS_CTL_REG),
FOOTSWITCH(FS_GFX3D, "fs_gfx3d", &standard_fs_ops, GFX3D_GFS_CTL_REG), FOOTSWITCH(FS_GFX3D, "fs_gfx3d", &standard_fs_ops, GFX3D_GFS_CTL_REG),
FOOTSWITCH(FS_IJPEG, "fs_ijpeg", &standard_fs_ops, GEMINI_GFS_CTL_REG), FOOTSWITCH(FS_IJPEG, "fs_ijpeg", &standard_fs_ops, GEMINI_GFS_CTL_REG),
FOOTSWITCH(FS_MDP, "fs_mdp", &standard_fs_ops, MDP_GFS_CTL_REG), FOOTSWITCH(FS_MDP, "fs_mdp", &standard_fs_ops, MDP_GFS_CTL_REG),

View File

@@ -28,7 +28,8 @@
#define FS_VFE 8 #define FS_VFE 8
#define FS_VPE 9 #define FS_VPE 9
#define FS_VCAP 10 #define FS_VCAP 10
#define MAX_FS 11 #define FS_GFX3D_8064 11
#define MAX_FS 12
struct fs_clk_data { struct fs_clk_data {
const char *name; const char *name;