summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2010-06-09 19:33:57 -0700
committerGary King <gking@nvidia.com>2010-07-02 07:15:44 -0700
commita3562cf11c826bc29e3f76ec6c31fa8376e88524 (patch)
treed4753cbb2c33bfd9feed26ec2dd3e05102956404
parent3835a7b2eb6d95033c84c03d97c83958c491df59 (diff)
[ARM/tegra] ODM: Resequenced USB_AVDD power control.
Attached USB_AVDD rail to PMU power enable input on entry to LP0, so that it is guaranteed to be turned On in h/w before bootrom code starts. Restored default USB_AVDD control configuration on LP0 exit, and keep it enabled until USB driver takes over. Since the USB_AVDD re-configuration must happen after USB driver suspend during LP0 entry, and before USB driver resume during LP0 exit, moved RM PMU-related operations from pm notifier callbacks to platform .prepare method (called after all drivers are suspended, but before irqs are disabled), and its .finish counterpart. Bug 702919 Bug 691042 Change-Id: I98d48ae15e960f41dd441fe3c38337ac04649a5e Reviewed-on: http://git-master.nvidia.com/r/2365 Tested-by: Aleksandr Frid <afrid@nvidia.com> Reviewed-by: Gary King <gking@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/nvrm_user.c5
-rw-r--r--arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b.c33
-rw-r--r--arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_supply_info_table.h3
-rw-r--r--arch/arm/mach-tegra/suspend.c24
4 files changed, 60 insertions, 5 deletions
diff --git a/arch/arm/mach-tegra/nvrm_user.c b/arch/arm/mach-tegra/nvrm_user.c
index 4125769b1e59..f5ab25bd5d3d 100644
--- a/arch/arm/mach-tegra/nvrm_user.c
+++ b/arch/arm/mach-tegra/nvrm_user.c
@@ -545,8 +545,6 @@ static void notify_daemon(const char* notice)
int tegra_pm_notifier(struct notifier_block *nb,
unsigned long event, void *nouse)
{
- NvOdmSocPowerState state =
- NvOdmQueryLowestSocPowerState()->LowestPowerState;
printk(KERN_INFO "%s: start processing event=%lx\n", __func__, event);
// Notify the event to nvrm_daemon.
@@ -556,11 +554,8 @@ int tegra_pm_notifier(struct notifier_block *nb,
notify_daemon(STRING_PM_DISPLAY_OFF);
#endif
notify_daemon(STRING_PM_SUSPEND_PREPARE);
- NvRmPrivDfsSuspend(state);
- NvRmPrivPmuLPxStateConfig(s_hRmGlobal, state, NV_TRUE);
break;
case PM_POST_SUSPEND:
- NvRmPrivPmuLPxStateConfig(s_hRmGlobal, state, NV_FALSE);
notify_daemon(STRING_PM_POST_SUSPEND);
#ifndef CONFIG_HAS_EARLYSUSPEND
notify_daemon(STRING_PM_DISPLAY_ON);
diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b.c
index fdd3b3eeffa1..d7f38d091b29 100644
--- a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b.c
+++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b.c
@@ -75,6 +75,12 @@ Max8907bPrivData *hMax8907bPmu;
// sequencer 2 because of the bug in the silicon.
#define MAX8907B_II2RR_PWREN_WAR (0x12)
+// Power up AVDD_USB on exit from deep sleep mode together with core rail,
+// before boot code starts, and keep it On during resume until USB driver
+// takes over
+#define WAR_AVDD_USB_EARLY_PWR_UP 1
+#define WAR_AVDD_USB_RESUME_KEEP_ON 1
+
/**
* The FAN5355 is used to scale the voltage of an external
* DC/DC voltage rail (for PCIE). However, voltage scaling is
@@ -1269,6 +1275,8 @@ Max8907bPwrEnAttach(
Max8907bPmuSupply Supply,
NvBool Attach)
{
+ static NvU8 s_ResumeSeqSelLdo4 = MAX8907B_SEQSEL_DEFAULT_LDO4;
+
NvU8 CtlAddr, CtlData, CntAddr, CntData, SeqSel;
switch (Supply)
@@ -1290,12 +1298,25 @@ Max8907bPwrEnAttach(
if (!Max8907bI2cWrite8(hDevice, CntAddr, CntData))
return NV_FALSE;
+#if WAR_AVDD_USB_EARLY_PWR_UP
+ // Attach USB rail to sequencer 2 as well, when core is attached
+ // (= entry to LP0), and dettach it respectively.
+ if (!Max8907bPwrEnAttach(hDevice, Max8907bPmuSupply_LDO4, Attach))
+ return NV_FALSE;
+#endif
CntData = Attach ? MAX8907B_SEQCNT_PWREN_LX_V2 :
MAX8907B_SEQCNT_DEFAULT_LX_V2;
SeqSel = Attach ? MAX8907B_SEQSEL_PWREN_LXX :
MAX8907B_SEQSEL_DEFAULT_LX_V2;
break;
+ case Max8907bPmuSupply_LDO4: // USB
+ CntData = Attach ? MAX8907B_SEQCNT_PWREN_LD04 :
+ MAX8907B_SEQCNT_DEFAULT_LDO4;
+ SeqSel = Attach ? MAX8907B_SEQSEL_PWREN_LXX :
+ s_ResumeSeqSelLdo4;
+ break;
+
default:
NV_ASSERT(!"This supply must not be attached to PWREN");
return NV_FALSE;
@@ -1306,6 +1327,18 @@ Max8907bPwrEnAttach(
// Read control refgister, and select target sequencer
if (!Max8907bI2cRead8(hDevice, CtlAddr, &CtlData))
return NV_FALSE;
+
+ if (Supply == Max8907bPmuSupply_LDO4)
+ {
+ NvU8 seq = (CtlData >> MAX8907B_CTL_SEQ_SHIFT) & MAX8907B_CTL_SEQ_MASK;
+ NvOdmOsPrintf("[NVODM PMU] AVDD_USB switching sequencer from %d to %d,"
+ " (control was = 0x%x)\n", seq, SeqSel, CtlData);
+#if !WAR_AVDD_USB_RESUME_KEEP_ON
+ if (Attach)
+ s_ResumeSeqSelLdo4 = seq; // save to restore on LP0 resume
+#endif
+ }
+
CtlData &= (~(MAX8907B_CTL_SEQ_MASK << MAX8907B_CTL_SEQ_SHIFT ));
CtlData |= ((SeqSel & MAX8907B_CTL_SEQ_MASK) << MAX8907B_CTL_SEQ_SHIFT );
diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_supply_info_table.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_supply_info_table.h
index 77cf70bc32b5..9ab16636f7b9 100644
--- a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_supply_info_table.h
+++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_supply_info_table.h
@@ -79,6 +79,7 @@ extern "C"
// Defines default sequencer selection
#define MAX8907B_SEQSEL_DEFAULT_LX_V1 0 /* SEQ1 (SYSEN) */
#define MAX8907B_SEQSEL_DEFAULT_LX_V2 0 /* SEQ1 (SYSEN) */
+#define MAX8907B_SEQSEL_DEFAULT_LDO4 0 /* SEQ1 (SYSEN) */
// Defines common for all supplies PWREN sequencer selection
#define MAX8907B_SEQSEL_PWREN_LXX 1 /* SEQ2 (PWREN) */
@@ -89,6 +90,7 @@ extern "C"
// Defines sequencer count default values
#define MAX8907B_SEQCNT_DEFAULT_LX_V1 0x1C
#define MAX8907B_SEQCNT_DEFAULT_LX_V2 0x1C
+#define MAX8907B_SEQCNT_DEFAULT_LDO4 0x72
// Defines sequencer count PWREN control values (these settings applied
// togeteher, when both CPU/V1 and CORE/V2 rails are attached to PWREN;
@@ -97,6 +99,7 @@ extern "C"
// B[3:0] - power down delay in 20us taps
#define MAX8907B_SEQCNT_PWREN_LX_V1 0xC0 /* 240us up delay */
#define MAX8907B_SEQCNT_PWREN_LX_V2 0x00 /* no delay */
+#define MAX8907B_SEQCNT_PWREN_LD04 0x00 /* no delay */
// Defines PMU output timing parameters. Scaling up time is dynamically
// calculated based on the slew rate maintained by MAX8907B. Turn On delay
diff --git a/arch/arm/mach-tegra/suspend.c b/arch/arm/mach-tegra/suspend.c
index 240ab30b1793..d40386313d01 100644
--- a/arch/arm/mach-tegra/suspend.c
+++ b/arch/arm/mach-tegra/suspend.c
@@ -414,6 +414,28 @@ static void tegra_suspend_dram(bool lp0_ok)
wmb();
}
+static int tegra_suspend_prepare(void)
+{
+#ifdef CONFIG_TEGRA_NVRM
+ NvOdmSocPowerState state =
+ NvOdmQueryLowestSocPowerState()->LowestPowerState;
+
+ NvRmPrivDfsSuspend(state);
+ NvRmPrivPmuLPxStateConfig(s_hRmGlobal, state, NV_TRUE);
+#endif
+ return 0;
+}
+
+static void tegra_suspend_finish(void)
+{
+#ifdef CONFIG_TEGRA_NVRM
+ NvOdmSocPowerState state =
+ NvOdmQueryLowestSocPowerState()->LowestPowerState;
+
+ NvRmPrivPmuLPxStateConfig(s_hRmGlobal, state, NV_FALSE);
+#endif
+}
+
static int tegra_suspend_prepare_late(void)
{
#ifdef CONFIG_TEGRA_NVRM
@@ -610,6 +632,8 @@ static int tegra_suspend_enter(suspend_state_t state)
static struct platform_suspend_ops tegra_suspend_ops = {
.valid = suspend_valid_only_mem,
+ .prepare = tegra_suspend_prepare,
+ .finish = tegra_suspend_finish,
.prepare_late = tegra_suspend_prepare_late,
.wake = tegra_suspend_wake,
.enter = tegra_suspend_enter,