summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/odm_kit
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2010-02-04 16:55:30 -0800
committerAlex Frid <afrid@nvidia.com>2010-02-04 21:24:52 -0800
commit5ad55dc6486d49a9c09c26531a14699b2593dd05 (patch)
treeb6d2663d47d74391cdfd2a4b9cbdc7768da3ebc9 /arch/arm/mach-tegra/odm_kit
parentb7ede6ae31fd044cd41946f4234442c5c6b25204 (diff)
tegra ODM: Added PMU settling time delays.
Added settling time delays to MAXIM8907 PMU adaptation on Whistler (bug 649448). Change-Id: I339d7534f6664a963dbfca797718bb0ffb20c84d
Diffstat (limited to 'arch/arm/mach-tegra/odm_kit')
-rw-r--r--arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/ad5258_dpm.h1
-rw-r--r--arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b.c58
-rw-r--r--arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b.h3
-rw-r--r--arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_supply_info_table.h7
4 files changed, 65 insertions, 4 deletions
diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/ad5258_dpm.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/ad5258_dpm.h
index 342376d33f81..8bfd23eecf59 100644
--- a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/ad5258_dpm.h
+++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/ad5258_dpm.h
@@ -71,6 +71,7 @@ extern "C"
#define AD5258_MIN_STEP_MV ((AD5258_M2 + (0x1 << AD5258_b) - 1) >> AD5258_b)
#define AD5258_MAX_STEP_MV (50)
#define AD5258_MAX_STEP_SETTLE_TIME_US (20)
+#define AD5258_TURN_ON_TIME_US (2000)
NvBool
Ad5258I2cSetVoltage(
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 3c4c0b2c8144..f218b835ed1c 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
@@ -1078,6 +1078,8 @@ Max8907bReadVoltageReg(
if ((data & MAX8907B_OUT_VOLTAGE_CONTROL_MASK) ==
MAX8907B_OUT_VOLTAGE_CONTROL_DISABLE)
{
+ ((Max8907bPrivData*)hDevice->pPrivate)->pVoltages[vddRail] =
+ ODM_VOLTAGE_OFF;
*pMilliVolts = ODM_VOLTAGE_OFF;
return NV_TRUE;
}
@@ -1095,6 +1097,7 @@ Max8907bReadVoltageReg(
else
milliVolts = pSupplyInfo->GetVoltage(data);
+ ((Max8907bPrivData*)hDevice->pPrivate)->pVoltages[vddRail] = milliVolts;
*pMilliVolts = milliVolts;
return NV_TRUE;
}
@@ -1108,10 +1111,10 @@ Max8907bWriteVoltageReg(
{
const Max8907bPmuSupplyInfo *pSupplyInfo = &Max8907bSupplyInfoTable[vddRail];
NvU8 data = 0;
+ NvU32 SettleUS = 0;
NV_ASSERT(pSupplyInfo->supply == (Max8907bPmuSupply)vddRail);
- // TO DO: Account for reference counting
if (MilliVolts == ODM_VOLTAGE_OFF)
{
// check if the supply can be turned off
@@ -1127,11 +1130,20 @@ Max8907bWriteVoltageReg(
data |= MAX8907B_OUT_VOLTAGE_CONTROL_DISABLE;
if (!Max8907bI2cWrite8(hDevice, pSupplyInfo->ControlRegAddr, data))
return NV_FALSE;
+
+ ((Max8907bPrivData*)hDevice->pPrivate)->pVoltages[vddRail] =
+ ODM_VOLTAGE_OFF;
+ SettleUS = MAX8907B_TURN_OFF_TIME_US;
}
if (((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable[pSupplyInfo->supply] != 0)
((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable[pSupplyInfo->supply] --;
+ if (pSettleMicroSeconds)
+ *pSettleMicroSeconds = SettleUS;
+ else
+ NvOdmOsWaitUS(SettleUS);
+
return NV_TRUE;
}
@@ -1139,6 +1151,14 @@ Max8907bWriteVoltageReg(
data = pSupplyInfo->SetVoltage(MilliVolts);
if (!Max8907bI2cWrite8(hDevice, pSupplyInfo->OutputVoltageRegAddr, data))
return NV_FALSE;
+ if (MilliVolts >
+ ((Max8907bPrivData*)hDevice->pPrivate)->pVoltages[vddRail])
+ {
+ NvU32 LastMV =
+ ((Max8907bPrivData*)hDevice->pPrivate)->pVoltages[vddRail];
+ SettleUS = (MilliVolts - LastMV) * 1000 / MAX8907B_SCALE_UP_UV_PER_US;
+ }
+ ((Max8907bPrivData*)hDevice->pPrivate)->pVoltages[vddRail] = MilliVolts;
// turn on supply
if (((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable[pSupplyInfo->supply] == 0)
@@ -1156,11 +1176,18 @@ Max8907bWriteVoltageReg(
data |= MAX8907B_OUT_VOLTAGE_ENABLE_BIT;
if (!Max8907bI2cWrite8(hDevice, pSupplyInfo->ControlRegAddr, data))
return NV_FALSE;
+
+ SettleUS = MAX8907B_TURN_ON_TIME_US;
}
}
((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable[pSupplyInfo->supply] ++;
+ if (pSettleMicroSeconds)
+ *pSettleMicroSeconds = SettleUS;
+ else
+ NvOdmOsWaitUS(SettleUS);
+
return NV_TRUE;
}
@@ -1455,7 +1482,6 @@ Max8907bLxV1Ad5258WriteVoltageReg(
((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable[
pSupplyInfo->supply] --;
}
- // TODO: add external DCDC turning Off settling time
return NV_TRUE;
}
@@ -1470,7 +1496,12 @@ Max8907bLxV1Ad5258WriteVoltageReg(
if (!Max8907bWriteVoltageReg(hDevice, Max8907bPmuSupply_LX_V1,
MAX8907B_REQUESTVOLTAGE_LX_V1, pSettleMicroSeconds))
return NV_FALSE;
- // TODO: add external DCDC turning On settling time
+
+ // Add external DCDC turning On settling time
+ if (pSettleMicroSeconds)
+ *pSettleMicroSeconds += AD5258_TURN_ON_TIME_US;
+ else
+ NvOdmOsWaitUS(AD5258_TURN_ON_TIME_US);
}
((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable[
pSupplyInfo->supply] ++;
@@ -1499,17 +1530,29 @@ Max8907bSetup(NvOdmPmuDeviceHandle hDevice)
NvOdmOsMemset(hMax8907bPmu, 0, sizeof(Max8907bPrivData));
hDevice->pPrivate = hMax8907bPmu;
- ((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable = NvOdmOsAlloc(sizeof(NvU32) * Max8907bPmuSupply_Num);
+ ((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable =
+ NvOdmOsAlloc(sizeof(NvU32) * Max8907bPmuSupply_Num);
if (((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable == NULL)
{
NVODMPMU_PRINTF(("Error Allocating RefCntTable. \n"));
goto fail;
}
+ ((Max8907bPrivData*)hDevice->pPrivate)->pVoltages =
+ NvOdmOsAlloc(sizeof(NvU32) * Max8907bPmuSupply_Num);
+ if (((Max8907bPrivData*)hDevice->pPrivate)->pVoltages == NULL)
+ {
+ NVODMPMU_PRINTF(("Error Allocating shadow voltages table. \n"));
+ goto fail;
+ }
// memset
for (i = 0; i < Max8907bPmuSupply_Num; i++)
{
((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable[i] = 0;
+ // Setting shadow to 0 would cause spare delay on the 1st scaling of
+ // always On rail; however the alternative reading of initial settings
+ // over I2C is even worse.
+ ((Max8907bPrivData*)hDevice->pPrivate)->pVoltages[i] = 0;
}
if (pConnectivity != NULL) // PMU is in database
@@ -1633,6 +1676,13 @@ Max8907bRelease(NvOdmPmuDeviceHandle hDevice)
((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable = NULL;
}
+ if (((Max8907bPrivData*)hDevice->pPrivate)->pVoltages != NULL)
+ {
+ NvOdmOsFree(((Max8907bPrivData*)hDevice->pPrivate)->pVoltages);
+ ((Max8907bPrivData*)hDevice->pPrivate)->pVoltages = NULL;
+ }
+
+
NvOdmOsFree(hDevice->pPrivate);
hDevice->pPrivate = NULL;
}
diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b.h
index cb333f6b84a7..ce66a64c9716 100644
--- a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b.h
+++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b.h
@@ -86,6 +86,9 @@ typedef struct
/* The ref cnt table of the power supplies */
NvU32 *supplyRefCntTable;
+ /* The pointer to supply voltages shadow */
+ NvU32 *pVoltages;
+
} Max8907bPrivData;
NvBool
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 5a97b23985a7..91b55a082d1b 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
@@ -94,6 +94,13 @@ extern "C"
#define MAX8907B_SEQCNT_PWREN_LX_V1 0x00 /* no delay */
#define MAX8907B_SEQCNT_PWREN_LX_V2 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
+// is fixed at max. Turn Off time is "just in case" placeholder - no need
+// for s/w to track when output capacitors are discharged.
+#define MAX8907B_SCALE_UP_UV_PER_US (2500)
+#define MAX8907B_TURN_ON_TIME_US (3000)
+#define MAX8907B_TURN_OFF_TIME_US (20)
// Output voltages supplied by PMU
typedef enum