From: Lesly A M <leslyam@ti.com>
To: linux-omap@vger.kernel.org
Cc: Lesly A M <leslyam@ti.com>, Nishanth Menon <nm@ti.com>,
David Derrick <dderrick@ti.com>,
Samuel Ortiz <sameo@linux.intel.com>
Subject: [PATCH v9 6/9] MFD: TWL4030: workaround changes for TWL4030 Erratum 27
Date: Thu, 14 Apr 2011 17:57:54 +0530 [thread overview]
Message-ID: <1302784077-16697-7-git-send-email-leslyam@ti.com> (raw)
In-Reply-To: <1302784077-16697-1-git-send-email-leslyam@ti.com>
Workaround for TWL5030 Silicon Errata 27 & 28:
27 - VDD1, VDD2, may have glitches when their output value is updated.
28 - VDD1 and / or VDD2 DCDC clock may stop working when internal clock
is switched from internal to external.
Erratum 27:
If the DCDC regulators is running on their internal oscillator,
negative glitches may occur on VDD1, VDD2 output when voltage is changed.
The OMAP device may reboot if the VDD1 or VDD2 go below the
core minimum operating voltage.
WORKAROUND
Set up the TWL5030 DC-DC power supplies to use the HFCLKIN instead of
the internal oscillator.
Erratum 28:
VDD1/VDD2 clock system may hang during switching the clock source from
internal oscillator to external. VDD1/VDD2 output voltages may collapse
if clock stops.
WORKAROUND
If HFCLK is disabled in OFFMODE, modify the sleep/wakeup sequence and
setuptimes to make sure the switching will happen only when HFCLKIN is stable.
Also use the TWL5030 watchdog to safeguard the first switching from
internal oscillator to HFCLKIN during the TWL5030 init.
IMPACT
power sequence is changed.
sleep/wakeup time values will be changed.
The workaround changes are called from twl4030_power_init(), since we have to
make some i2c_read calls to check the TWL4030 version & the i2c will not be
initialized in the early stage.
This workaround is required for TWL5030 Silicon version less than ES1.2
The power script & setup time changes are recommended by TI HW team.
http://omapedia.org/wiki/TWL4030_power_scripts
Changes taken from TWL4030 Erratum 27 workaround patch by Nishanth Menon.
Signed-off-by: Lesly A M <leslyam@ti.com>
Cc: Nishanth Menon <nm@ti.com>
Cc: David Derrick <dderrick@ti.com>
Cc: Samuel Ortiz <sameo@linux.intel.com>
---
arch/arm/mach-omap2/twl4030-script.c | 150 ++++++++++++++++++++++++++++++++++
drivers/mfd/twl4030-power.c | 78 ++++++++++++++++++
include/linux/i2c/twl.h | 1 +
3 files changed, 229 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/twl4030-script.c b/arch/arm/mach-omap2/twl4030-script.c
index aa5afbd..97cdaa3 100644
--- a/arch/arm/mach-omap2/twl4030-script.c
+++ b/arch/arm/mach-omap2/twl4030-script.c
@@ -324,8 +324,158 @@ static struct twl4030_resconfig twl4030_rconfig[] = {
{ 0, 0},
};
+/*
+ * Sleep and active sequences with changes for TWL5030 Erratum 27 workaround
+ *
+ * Sysoff (using sys_off signal):
+ * When SYS_CLKREQ goes low during retention no resources will be affected
+ * since no resources are assigned to P3 only.
+ *
+ * Since all resources are assigned to P1 and P3 then all resources
+ * will be affected on the falling edge of P3 (SYS_CLKREQ).
+ * When OMAP lower the SYS_CLKREQ signal PMIC will execute the
+ * A2S sequence in which HFCLKOUT is dissabled first and
+ * after 488.32 usec(PRM_VOLTOFFSET) resources assigned to P1 and P3
+ * and of TYPE2=1 are put to sleep
+ * (VDD1, VDD2, VPLL1, REGEN, NRESPWRON & SYSEN).
+ * Again after a 61.04 usec resources assigned to P1 and P3
+ * and of TYPE2=2 are put to sleep
+ * (VINTANA1, VINTANA2, VINTDIG, VIO & CLKEN).
+ *
+ * On wakeup event OMAP goes active and pulls the SYS_CLKREQ high,
+ * and will execute the S2A sequence which is same for P1_P2 & P3.
+ * This will turn on all resources of TYPE2=2 to go to the active state.
+ * Three dummy broadcast messages are added to get a delay of ~10 ms
+ * before enabling the HFCLKOUT resource. And after a 30.52 usec
+ * all resources of TYPE2=1 are put to the active state.
+ *
+ * This 10ms delay can be reduced if the oscillator is having less
+ * stabilization time. A should be taken care if it needs more time
+ * for stabilization.
+ *
+ */
+
+/**
+ * DOC: Sleep to Active sequence for P1/P2/P3
+ *
+ * The wakeup sequence is adjusted to do the VDD1/VDD2 voltage ramp-up
+ * only after HFCLKIN is stabilized and the HFCLKOUT is enabled.
+ */
+static struct twl4030_ins wakeup_seq_erratum27[] __initdata = {
+ /*
+ * Broadcast message to put res(TYPE2 = 2) to active.
+ * Wait for ~10 mS (ramp-up time for OSC on the board)
+ * after HFCLKIN is enabled
+ */
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2,
+ RES_STATE_ACTIVE), 55},
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2,
+ RES_STATE_ACTIVE), 55},
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2,
+ RES_STATE_ACTIVE), 54},
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2,
+ RES_STATE_ACTIVE), 1},
+ /* Singular message to enable HCLKOUT after HFCLKIN is stabilized */
+ {MSG_SINGULAR(DEV_GRP_NULL, RES_HFCLKOUT, RES_STATE_ACTIVE), 1},
+ /*
+ * Broadcast message to put res(TYPE2 = 1) to active.
+ * VDD1/VDD2 ramp-up after HFCLKIN is stable and HFCLKOUT is enabled.
+ */
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1,
+ RES_STATE_ACTIVE), 2},
+};
+
+static struct twl4030_script wakeup_script_erratum27 __initdata = {
+ .script = wakeup_seq_erratum27,
+ .size = ARRAY_SIZE(wakeup_seq_erratum27),
+ .flags = TWL4030_WAKEUP12_SCRIPT | TWL4030_WAKEUP3_SCRIPT,
+};
+
+/**
+ * DOC: Active to Sleep sequence for P1/P2/P3
+ *
+ * The sleep sequence is adjusted to do the switching of VDD1/VDD2/VIO OSC from
+ * HFCLKIN to internal oscillator when the HFCLKIN is stable.
+ */
+static struct twl4030_ins __initdata sleep_on_seq_erratum27[] = {
+ /*
+ * Singular message to disable HCLKOUT.
+ * Wait for ~488.32 uS to do the switching of VDD1/VDD2/VIO OSC from
+ * HFCLKIN to internal oscillator before disabling HFCLKIN.
+ */
+ {MSG_SINGULAR(DEV_GRP_NULL, RES_HFCLKOUT, RES_STATE_SLEEP), 20},
+ /* Broadcast message to put res(TYPE2 = 1) to sleep */
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1,
+ RES_STATE_SLEEP), 2},
+ /* Broadcast message to put res(TYPE2 = 2) to sleep, disable HFCLKIN */
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2,
+ RES_STATE_SLEEP), 2},
+};
+
+static struct twl4030_script sleep_on_script_erratum27 __initdata = {
+ .script = sleep_on_seq_erratum27,
+ .size = ARRAY_SIZE(sleep_on_seq_erratum27),
+ .flags = TWL4030_SLEEP_SCRIPT,
+};
+
+/* TWL4030 script for sleep, wakeup & warm_reset */
+static struct twl4030_script *twl4030_scripts_erratum27[] __initdata = {
+ &sleep_on_script_erratum27,
+ &wakeup_script_erratum27,
+ &wrst_script,
+};
+
+/**
+ * DOC: TWL4030 resource configuration
+ *
+ * VDD1/VDD2/VPLL are assigned to P1 and P3, to have better control
+ * during OFFMODE. HFCLKOUT is assigned to P1 and P3 (*p2) to turn off
+ * only during OFFMODE.
+ * (*P2 is included if the platform uses it for modem/some other processor)
+ */
+static struct twl4030_resconfig twl4030_rconfig_erratum27[] = {
+ { .resource = RES_VPLL1, .devgroup = DEV_GRP_P1 | DEV_GRP_P3,
+ .type = 3, .type2 = 1, .remap_sleep = RES_STATE_OFF },
+ { .resource = RES_VINTANA1, .devgroup = DEV_GRP_ALL, .type = 1,
+ .type2 = 2, .remap_sleep = RES_STATE_SLEEP },
+ { .resource = RES_VINTANA2, .devgroup = DEV_GRP_ALL, .type = 0,
+ .type2 = 2, .remap_sleep = RES_STATE_SLEEP },
+ { .resource = RES_VINTDIG, .devgroup = DEV_GRP_ALL, .type = 1,
+ .type2 = 2, .remap_sleep = RES_STATE_SLEEP },
+ { .resource = RES_VIO, .devgroup = DEV_GRP_ALL, .type = 2,
+ .type2 = 2, .remap_sleep = RES_STATE_SLEEP },
+ { .resource = RES_VDD1, .devgroup = DEV_GRP_P1 | DEV_GRP_P3,
+ .type = 4, .type2 = 1, .remap_sleep = RES_STATE_OFF },
+ { .resource = RES_VDD2, .devgroup = DEV_GRP_P1 | DEV_GRP_P3,
+ .type = 3, .type2 = 1, .remap_sleep = RES_STATE_OFF },
+ { .resource = RES_REGEN, .devgroup = DEV_GRP_ALL, .type = 2,
+ .type2 = 1, .remap_sleep = RES_STATE_SLEEP },
+ { .resource = RES_NRES_PWRON, .devgroup = DEV_GRP_ALL, .type = 0,
+ .type2 = 1, .remap_sleep = RES_STATE_SLEEP },
+ { .resource = RES_CLKEN, .devgroup = DEV_GRP_ALL, .type = 3,
+ .type2 = 2, .remap_sleep = RES_STATE_SLEEP },
+ { .resource = RES_SYSEN, .devgroup = DEV_GRP_ALL, .type = 6,
+ .type2 = 1, .remap_sleep = RES_STATE_SLEEP },
+ { .resource = RES_HFCLKOUT, .devgroup = DEV_GRP_P1 | DEV_GRP_P3,
+ .type = 0, .type2 = 1, .remap_sleep = RES_STATE_SLEEP },
+ { 0, 0},
+};
+
+/**
+ * twl5030_script_erratum27() - API to modify TWL4030 script
+ *
+ * Updating the TWL4030 script & resource configuration
+ */
+static void __init twl5030_script_erratum27(void)
+{
+ twl4030_generic_script.scripts = twl4030_scripts_erratum27;
+ twl4030_generic_script.num = ARRAY_SIZE(twl4030_scripts_erratum27);
+ twl4030_generic_script.resource_config = twl4030_rconfig_erratum27;
+}
+
struct twl4030_power_data twl4030_generic_script __initdata = {
.scripts = twl4030_scripts,
.num = ARRAY_SIZE(twl4030_scripts),
.resource_config = twl4030_rconfig,
+ .twl5030_erratum27wa_script = twl5030_script_erratum27,
};
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
index 8162e43..8d1db78 100644
--- a/drivers/mfd/twl4030-power.c
+++ b/drivers/mfd/twl4030-power.c
@@ -63,6 +63,14 @@ static u8 twl4030_start_script_address = 0x2b;
#define R_MEMORY_ADDRESS PHY_TO_OFF_PM_MASTER(0x59)
#define R_MEMORY_DATA PHY_TO_OFF_PM_MASTER(0x5a)
+#define R_VDD1_OSC 0x5C
+#define R_VDD2_OSC 0x6A
+#define R_VIO_OSC 0x52
+#define EXT_FS_CLK_EN BIT(6)
+
+#define R_WDT_CFG 0x03
+#define WDT_WRK_TIMEOUT 0x03
+
/* resource configuration registers
<RESOURCE>_DEV_GRP at address 'n+0'
<RESOURCE>_TYPE at address 'n+1'
@@ -511,6 +519,67 @@ int twl4030_remove_script(u8 flags)
return err;
}
+/**
+ * twl_dcdc_use_hfclk - API to use HFCLK for TWL DCDCs
+ *
+ * TWL DCDCs switching to HFCLK instead of using internal RC oscillator.
+ */
+static int __init twl_dcdc_use_hfclk(void)
+{
+ u8 val;
+ u8 smps_osc_reg[] = {R_VDD1_OSC, R_VDD2_OSC, R_VIO_OSC};
+ int i;
+ int err;
+
+ for (i = 0; i < sizeof(smps_osc_reg); i++) {
+ err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &val,
+ smps_osc_reg[i]);
+ val |= EXT_FS_CLK_EN;
+ err |= twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, val,
+ smps_osc_reg[i]);
+ }
+ return err;
+}
+
+/**
+ * twl_erratum27_workaround - Workaround for TWL5030 Silicon Erratum 27
+ * 27 - VDD1, VDD2, may have glitches when their output value is updated.
+ * 28 - VDD1 and / or VDD2 DCDC clock may stop working when internal clock is
+ * switched from internal to external.
+ *
+ * Workaround requires the TWL DCDCs to use HFCLK instead of
+ * internal oscillator. Also enable TWL watchdog before switching the osc
+ * to recover if the VDD1/VDD2 stop working.
+ */
+static void __init twl_erratum27_workaround(void)
+{
+ u8 wdt_counter_val = 0;
+ int err;
+
+ /* Setup the twl wdt to take care of borderline failure case */
+ err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &wdt_counter_val,
+ R_WDT_CFG);
+ err |= twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, WDT_WRK_TIMEOUT,
+ R_WDT_CFG);
+
+ /* TWL DCDC switching to HFCLK */
+ err |= twl_dcdc_use_hfclk();
+
+ /* restore the original value */
+ err |= twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, wdt_counter_val,
+ R_WDT_CFG);
+ if (err)
+ pr_warning("TWL4030: workaround setup failed!\n");
+}
+
+static bool is_twl5030_erratum27wa_required(void)
+{
+ if (twl_get_type() == TWL_SIL_5030)
+ return (twl_get_version() < TWL5030_REV_1_2);
+
+ return 0;
+}
+
void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
{
int err = 0;
@@ -530,6 +599,15 @@ void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
if (err)
goto unlock;
+ /* Applying TWL5030 Erratum 27 WA based on Si revision &
+ * flag updated from board file*/
+ if (is_twl5030_erratum27wa_required()) {
+ pr_info("TWL5030: Enabling workaround for Si Erratum 27\n");
+ twl_erratum27_workaround();
+ if (twl4030_scripts->twl5030_erratum27wa_script)
+ twl4030_scripts->twl5030_erratum27wa_script();
+ }
+
for (i = 0; i < twl4030_scripts->num; i++) {
err = load_twl4030_script(twl4030_scripts->scripts[i], address);
if (err)
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
index e1ff2c4..a37077e 100644
--- a/include/linux/i2c/twl.h
+++ b/include/linux/i2c/twl.h
@@ -672,6 +672,7 @@ struct twl4030_power_data {
struct twl4030_script **scripts;
unsigned num;
struct twl4030_resconfig *resource_config;
+ void (*twl5030_erratum27wa_script)(void);
#define TWL4030_RESCONFIG_UNDEF ((u8)-1)
};
--
1.7.1
next prev parent reply other threads:[~2011-04-14 12:27 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-04-14 12:27 [PATCH v9 0/9] OMAP3: PM: TWL4030 power scripts and workaround for TWL erratum 27 Lesly A M
2011-04-14 12:27 ` [PATCH v9 1/9] OMAP3: PM: Fix for the TWL4030 sleep/wakeup sequence Lesly A M
2011-04-26 9:54 ` Samuel Ortiz
2011-04-14 12:27 ` [PATCH v9 2/9] OMAP3: PM: Correct the warning print during script loading Lesly A M
2011-04-26 9:57 ` Samuel Ortiz
2011-04-14 12:27 ` [PATCH v9 3/9] OMAP3: PM: Modifying the macro name Main_Ref to all caps Lesly A M
2011-04-26 10:07 ` Samuel Ortiz
2011-04-14 12:27 ` [PATCH v9 4/9] OMAP3: PM: TWL4030 power scripts for OMAP3 boards Lesly A M
2011-04-18 12:32 ` Tony Lindgren
2011-04-18 12:55 ` Manuel, Lesly Arackal
2011-04-18 12:58 ` Tony Lindgren
2011-04-27 12:59 ` Manuel, Lesly Arackal
2011-04-27 13:05 ` Tony Lindgren
2011-04-14 12:27 ` [PATCH v9 5/9] OMAP3: PM: TWL5030 version checking Lesly A M
2011-04-26 10:12 ` Samuel Ortiz
2011-04-14 12:27 ` Lesly A M [this message]
2011-04-26 10:13 ` [PATCH v9 6/9] MFD: TWL4030: workaround changes for TWL4030 Erratum 27 Samuel Ortiz
2011-04-27 14:24 ` Manuel, Lesly Arackal
2011-04-14 12:27 ` [PATCH v9 7/9] OMAP3430: Updating the board file to use TWL4030 scripts Lesly A M
2011-04-14 12:27 ` [PATCH v9 8/9] OMAP3630: " Lesly A M
2011-04-14 12:27 ` [PATCH v9 9/9] OMAP3: PM: TWL4030 optimizing resource configuration Lesly A M
2011-05-03 13:21 ` [PATCH v9 0/9] OMAP3: PM: TWL4030 power scripts and workaround for TWL erratum 27 Jean Pihet
2011-05-04 14:28 ` Manuel, Lesly Arackal
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=1302784077-16697-7-git-send-email-leslyam@ti.com \
--to=leslyam@ti.com \
--cc=dderrick@ti.com \
--cc=linux-omap@vger.kernel.org \
--cc=nm@ti.com \
--cc=sameo@linux.intel.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).