summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2010-04-02 14:15:19 -0700
committerGary King <gking@nvidia.com>2010-04-06 20:21:39 -0700
commitb01be20bf4a6dd5273747cdda308bd24187de813 (patch)
tree2f37bdca7b455a03cd2701a3cd10550f63797367 /arch
parent6dbb4916287e842f3e8541a980e30ee0cc9479b4 (diff)
tegra RM: Power gated core partitions on suspend entry.
Power gated all core partitions (except L2C) when entering suspend. During resume ungate those partitions that were powered before suspend. Change-Id: I6559f7d314df5904acc8f639efe953d8382925ac Reviewed-on: http://git-master/r/1046 Tested-by: Aleksandr Frid <afrid@nvidia.com> Reviewed-by: Narendra Damahe <ndamahe@nvidia.com> Tested-by: Narendra Damahe <ndamahe@nvidia.com> Reviewed-by: Gary King <gking@nvidia.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-tegra/include/nvrm_power_private.h9
-rw-r--r--arch/arm/mach-tegra/nvrm/core/ap15/ap15rm_power.c102
-rw-r--r--arch/arm/mach-tegra/nvrm/core/common/nvrm_power.c9
3 files changed, 107 insertions, 13 deletions
diff --git a/arch/arm/mach-tegra/include/nvrm_power_private.h b/arch/arm/mach-tegra/include/nvrm_power_private.h
index 87a6ca6ef69b..f4adaa0c64ca 100644
--- a/arch/arm/mach-tegra/include/nvrm_power_private.h
+++ b/arch/arm/mach-tegra/include/nvrm_power_private.h
@@ -407,6 +407,15 @@ NvRmPrivPowerGroupGetVoltage(
NvRmDeviceHandle hRmDeviceHandle,
NvU32 PowerGroup);
+
+/**
+ * Gate/ungate power groups on entry/exit to/from low power state.
+ *
+ * @param hRmDeviceHandle The RM device handle.
+ */
+void NvRmPrivPowerGroupSuspend(NvRmDeviceHandle hRmDeviceHandle);
+void NvRmPrivPowerGroupResume(NvRmDeviceHandle hRmDeviceHandle);
+
/**
* Controls power state and clamping for PCIEXCLK/PLLE (chip-specific).
*
diff --git a/arch/arm/mach-tegra/nvrm/core/ap15/ap15rm_power.c b/arch/arm/mach-tegra/nvrm/core/ap15/ap15rm_power.c
index 116e4148a474..d9fd9f3d1251 100644
--- a/arch/arm/mach-tegra/nvrm/core/ap15/ap15rm_power.c
+++ b/arch/arm/mach-tegra/nvrm/core/ap15/ap15rm_power.c
@@ -75,10 +75,11 @@
// Power Group -to- Power Gating Ids mapping
static const NvU32* s_PowerGroupIds = NULL;
+static NvBool s_UngateOnResume[NV_POWERGROUP_MAX] = {0};
/*****************************************************************************/
-static NvBool IsPowerGateSupported(NvU32 PowerGroup)
+static NvBool IsRunTimePowerGateSupported(NvU32 PowerGroup)
{
// 1st check h/w support capabilities
NV_ASSERT(s_PowerGroupIds);
@@ -101,6 +102,27 @@ static NvBool IsPowerGateSupported(NvU32 PowerGroup)
}
}
+static NvBool IsSuspendPowerGateForced(NvU32 PowerGroup)
+{
+ // 1st check h/w support capabilities
+ NV_ASSERT(s_PowerGroupIds);
+ if (s_PowerGroupIds[PowerGroup] == NV_POWERGROUP_INVALID)
+ return NV_FALSE;
+
+ // now check s/w support
+ switch (PowerGroup)
+ {
+ case NV_POWERGROUP_TD:
+ case NV_POWERGROUP_PCIE:
+ case NV_POWERGROUP_VDE:
+ case NV_POWERGROUP_VE:
+ case NV_POWERGROUP_MPE:
+ return NV_TRUE;
+ default:
+ return NV_FALSE;
+ }
+}
+
static void PowerGroupResetControl(
NvRmDeviceHandle hRmDeviceHandle,
NvU32 PowerGroup,
@@ -126,6 +148,12 @@ static void PowerGroupResetControl(
case NV_POWERGROUP_VDE:
NvRmModuleResetWithHold(hRmDeviceHandle, NvRmModuleID_Vde, Assert);
break;
+ case NV_POWERGROUP_VE:
+ NvRmModuleResetWithHold(hRmDeviceHandle, NvRmModuleID_Vi, Assert);
+ NvRmModuleResetWithHold(hRmDeviceHandle, NvRmModuleID_Csi, Assert);
+ NvRmModuleResetWithHold(hRmDeviceHandle, NvRmModuleID_Isp, Assert);
+ NvRmModuleResetWithHold(hRmDeviceHandle, NvRmModuleID_Epp, Assert);
+ break;
case NV_POWERGROUP_MPE:
NvRmModuleResetWithHold(hRmDeviceHandle, NvRmModuleID_Mpe, Assert);
break;
@@ -156,6 +184,16 @@ static void PowerGroupClockControl(
NvRmPrivEnableModuleClock(
hRmDeviceHandle, NvRmModuleID_Vde, ClockState);
break;
+ case NV_POWERGROUP_VE:
+ NvRmPrivEnableModuleClock(
+ hRmDeviceHandle, NvRmModuleID_Vi, ClockState);
+ NvRmPrivEnableModuleClock(
+ hRmDeviceHandle, NvRmModuleID_Csi, ClockState);
+ NvRmPrivEnableModuleClock(
+ hRmDeviceHandle, NvRmModuleID_Isp, ClockState);
+ NvRmPrivEnableModuleClock(
+ hRmDeviceHandle, NvRmModuleID_Epp, ClockState);
+ break;
case NV_POWERGROUP_MPE:
NvRmPrivEnableModuleClock(
hRmDeviceHandle, NvRmModuleID_Mpe, ClockState);
@@ -165,27 +203,19 @@ static void PowerGroupClockControl(
}
}
-void
-NvRmPrivPowerGroupControl(
+static void
+PowerGroupPowerControl(
NvRmDeviceHandle hRmDeviceHandle,
NvU32 PowerGroup,
NvBool Enable)
{
NvU32 reg, Id, Mask, Status;
- NVRM_POWER_PRINTF(("%s Power Group %d\n",
- (Enable ? "Enable" : "Disable"), PowerGroup));
// Do nothing if not SoC platform
NV_ASSERT(hRmDeviceHandle);
if (NvRmPrivGetExecPlatform(hRmDeviceHandle) != ExecPlatform_Soc)
return;
- // Do nothing if power gating is not supported for this group
- if (PowerGroup >= NV_POWERGROUP_MAX)
- return; // "virtual" groups are always On
- if (!IsPowerGateSupported(PowerGroup))
- return;
-
// Do nothing if power group is already in requested state
NV_ASSERT(s_PowerGroupIds[PowerGroup] != NV_POWERGROUP_INVALID);
Id = s_PowerGroupIds[PowerGroup];
@@ -250,6 +280,25 @@ NvRmPrivPowerGroupControl(
}
}
+void
+NvRmPrivPowerGroupControl(
+ NvRmDeviceHandle hRmDeviceHandle,
+ NvU32 PowerGroup,
+ NvBool Enable)
+{
+ NVRM_POWER_PRINTF(("%s Power Group %d\n",
+ (Enable ? "Enable" : "Disable"), PowerGroup));
+
+ // Do nothing if dynamic power gating is not supported for this group
+ if (PowerGroup >= NV_POWERGROUP_MAX)
+ return; // "virtual" groups are always On
+ if (!IsRunTimePowerGateSupported(PowerGroup))
+ return;
+
+ // Gate/ungate the group
+ PowerGroupPowerControl(hRmDeviceHandle, PowerGroup, Enable);
+}
+
NvRmMilliVolts
NvRmPrivPowerGroupGetVoltage(
NvRmDeviceHandle hRmDeviceHandle,
@@ -273,6 +322,37 @@ NvRmPrivPowerGroupGetVoltage(
return Voltage;
}
+void NvRmPrivPowerGroupSuspend(NvRmDeviceHandle hRmDeviceHandle)
+{
+ NvU32 i;
+
+ // On suspend entry power gate core group that is still On, but must be Off
+ for (i = 0; i < NV_POWERGROUP_MAX; i++)
+ {
+ if (!IsSuspendPowerGateForced(i) ||
+ (NvRmPrivPowerGroupGetVoltage(hRmDeviceHandle, i) == NvRmVoltsOff))
+ {
+ s_UngateOnResume[i] = NV_FALSE;
+ continue;
+ }
+
+ s_UngateOnResume[i] = NV_TRUE;
+ PowerGroupPowerControl(hRmDeviceHandle, i, NV_FALSE);
+ }
+}
+
+void NvRmPrivPowerGroupResume(NvRmDeviceHandle hRmDeviceHandle)
+{
+ NvU32 i;
+
+ // On resume ungate core group that was forcefully gated on suspend entry
+ for (i = 0; i < NV_POWERGROUP_MAX; i++)
+ {
+ if (s_UngateOnResume[i] == NV_TRUE)
+ PowerGroupPowerControl(hRmDeviceHandle, i, NV_TRUE);
+ }
+}
+
void NvRmPrivPowerGroupControlInit(NvRmDeviceHandle hRmDeviceHandle)
{
NvU32 i, Size;
diff --git a/arch/arm/mach-tegra/nvrm/core/common/nvrm_power.c b/arch/arm/mach-tegra/nvrm/core/common/nvrm_power.c
index 9bb8ae412807..e748aa2e563d 100644
--- a/arch/arm/mach-tegra/nvrm/core/common/nvrm_power.c
+++ b/arch/arm/mach-tegra/nvrm/core/common/nvrm_power.c
@@ -688,8 +688,11 @@ PowerEventNotify(
}
else if (Event == NvRmPowerEvent_WakeLP1)
{
- // LP1: core power is preserved; modules in powered down
- // groups are tracked via RecordPowerCycle()
+ // LP1: core power is preserved; but all power groups
+ // except AO and NPG group are power gated
+ if ((pVoltageReq->PowerGroup != NV_POWERGROUP_AO) &&
+ (pVoltageReq->PowerGroup != NV_POWERGROUP_NPG))
+ pVoltageReq->PowerCycled = NV_TRUE;
}
pVoltageReq = pVoltageReq->pNext;
}
@@ -1476,6 +1479,7 @@ NvRmKernelPowerSuspend( NvRmDeviceHandle hRmDeviceHandle )
NvRmPrivPmuInterruptMask(hRmDeviceHandle, NV_TRUE);
NvRmPrivDfsSuspend(NvOdmQueryLowestSocPowerState()->LowestPowerState);
+ NvRmPrivPowerGroupSuspend(hRmDeviceHandle);
#if NVRM_POWER_DEBUG_SUSPEND_ENTRY
NvOsMutexLock(s_hPowerClientMutex);
@@ -1522,6 +1526,7 @@ NvError
NvRmKernelPowerResume( NvRmDeviceHandle hRmDeviceHandle )
{
NvRmPrivPmuInterruptMask(hRmDeviceHandle, NV_FALSE);
+ NvRmPrivPowerGroupResume(hRmDeviceHandle);
return NvSuccess;
}