diff options
author | Alex Frid <afrid@nvidia.com> | 2010-02-04 16:55:30 -0800 |
---|---|---|
committer | Alex Frid <afrid@nvidia.com> | 2010-02-04 21:24:52 -0800 |
commit | 5ad55dc6486d49a9c09c26531a14699b2593dd05 (patch) | |
tree | b6d2663d47d74391cdfd2a4b9cbdc7768da3ebc9 /arch/arm/mach-tegra/odm_kit | |
parent | b7ede6ae31fd044cd41946f4234442c5c6b25204 (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')
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 |