summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--[-rwxr-xr-x]arch/arm/mach-tegra/nvddk/nvddk_usbphy.c75
-rw-r--r--arch/arm/mach-tegra/nvrm/core/ap15/ap15rm_clock_config.c3
-rw-r--r--arch/arm/mach-tegra/nvrm/core/ap15/nvrm_clocks.c14
-rw-r--r--arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_i2c.c177
-rw-r--r--arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_rtc.c192
-rw-r--r--arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_rtc.c81
6 files changed, 355 insertions, 187 deletions
diff --git a/arch/arm/mach-tegra/nvddk/nvddk_usbphy.c b/arch/arm/mach-tegra/nvddk/nvddk_usbphy.c
index fe3c3252d39f..435ff7dcc54c 100755..100644
--- a/arch/arm/mach-tegra/nvddk/nvddk_usbphy.c
+++ b/arch/arm/mach-tegra/nvddk/nvddk_usbphy.c
@@ -47,6 +47,10 @@
#define MAX_USB_INSTANCES 5
+// On platforms that never disable USB controller clock, use 1KHz as an
+// indicator that USB controller is idle, and core voltage can be scaled down
+#define USBC_IDLE_KHZ (1)
+
static NvDdkUsbPhy *s_pUsbPhy = NULL;
static NvDdkUsbPhyUtmiPadConfig *s_pUtmiPadConfig = NULL;
@@ -247,22 +251,54 @@ UsbPhyDfsBusyHint(
{ NvRmDfsClockId_Emc, 0, 0, NV_TRUE },
{ NvRmDfsClockId_Ahb, 0, 0, NV_TRUE }
};
+ NvError e = NvSuccess;
pUsbHintOn[0].BoostDurationMs = BoostDurationMs;
pUsbHintOn[1].BoostDurationMs = BoostDurationMs;
if (DfsOn)
+ {
+ if (hUsbPhy->Caps.PhyRegInController)
+ {
+ // Indicate USB controller is active
+ NvRmFreqKHz PrefFreq = NvRmPowerModuleGetMaxFrequency(
+ hUsbPhy->hRmDevice,
+ NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, hUsbPhy->Instance));
+
+ NV_CHECK_ERROR_CLEANUP(
+ NvRmPowerModuleClockConfig(hUsbPhy->hRmDevice,
+ NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, hUsbPhy->Instance),
+ hUsbPhy->RmPowerClientId, PrefFreq, PrefFreq, &PrefFreq,
+ 1, NULL, 0));
+ }
return NvRmPowerBusyHintMulti(hUsbPhy->hRmDevice,
hUsbPhy->RmPowerClientId,
pUsbHintOn,
NV_ARRAY_SIZE(pUsbHintOn),
NvRmDfsBusyHintSyncMode_Async);
+ }
else
+ {
+ if (hUsbPhy->Caps.PhyRegInController)
+ {
+ // Indicate USB controller is idle
+ NvRmFreqKHz PrefFreq = USBC_IDLE_KHZ;
+
+ NV_CHECK_ERROR_CLEANUP(
+ NvRmPowerModuleClockConfig(hUsbPhy->hRmDevice,
+ NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, hUsbPhy->Instance),
+ hUsbPhy->RmPowerClientId, PrefFreq, PrefFreq, &PrefFreq,
+ 1, NULL, 0));
+ }
return NvRmPowerBusyHintMulti(hUsbPhy->hRmDevice,
hUsbPhy->RmPowerClientId,
pUsbHintOff,
NV_ARRAY_SIZE(pUsbHintOff),
NvRmDfsBusyHintSyncMode_Async);
+ }
+
+fail:
+ return e;
}
@@ -274,7 +310,8 @@ UsbPhyInitialize(
NvRmFreqKHz CurrentFreq = 0;
NvRmFreqKHz PrefFreqList[3] = {12000, 60000, NvRmFreqUnspecified};
- //NvOsDebugPrintf("UsbPhyInitialize::VOLTAGE ON\n");
+ // NvOsDebugPrintf("UsbPhyInitialize::VOLTAGE ON, instance %d\n",
+ // hUsbPhy->Instance);
// request power
NV_CHECK_ERROR_CLEANUP(
NvRmPowerVoltageControl(hUsbPhy->hRmDevice,
@@ -288,23 +325,31 @@ UsbPhyInitialize(
NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, hUsbPhy->Instance),
hUsbPhy->RmPowerClientId, NV_TRUE));
- if (hUsbPhy->pProperty->UsbInterfaceType == NvOdmUsbInterfaceType_UlpiNullPhy)
+ if (!hUsbPhy->Caps.PhyRegInController)
{
- /* Request for 60MHz clk */
- NV_CHECK_ERROR_CLEANUP(
- NvRmPowerModuleClockConfig(hUsbPhy->hRmDevice,
- NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, hUsbPhy->Instance),
- hUsbPhy->RmPowerClientId, PrefFreqList[1],
- PrefFreqList[1], &PrefFreqList[1], 1, &CurrentFreq, 0));
+ if (hUsbPhy->pProperty->UsbInterfaceType == NvOdmUsbInterfaceType_UlpiNullPhy)
+ {
+ /* Request for 60MHz clk */
+ NV_CHECK_ERROR_CLEANUP(
+ NvRmPowerModuleClockConfig(hUsbPhy->hRmDevice,
+ NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, hUsbPhy->Instance),
+ hUsbPhy->RmPowerClientId, PrefFreqList[1],
+ PrefFreqList[1], &PrefFreqList[1], 1, &CurrentFreq, 0));
+ }
+ else
+ {
+ /* Request for 12 MHz clk */
+ NV_CHECK_ERROR_CLEANUP(
+ NvRmPowerModuleClockConfig(hUsbPhy->hRmDevice,
+ NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, hUsbPhy->Instance),
+ hUsbPhy->RmPowerClientId, PrefFreqList[0],
+ PrefFreqList[0], &PrefFreqList[0], 1, &CurrentFreq, 0));
+ }
}
- else
+ // else
{
- /* Request for 12 MHz clk */
- NV_CHECK_ERROR_CLEANUP(
- NvRmPowerModuleClockConfig(hUsbPhy->hRmDevice,
- NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, hUsbPhy->Instance),
- hUsbPhy->RmPowerClientId, PrefFreqList[0],
- PrefFreqList[0], &PrefFreqList[0], 1, &CurrentFreq, 0));
+ /* No need for actual clock configuration - all USB PLL frequencies
+ are available concurrently in this case. */
}
// Reset controller
diff --git a/arch/arm/mach-tegra/nvrm/core/ap15/ap15rm_clock_config.c b/arch/arm/mach-tegra/nvrm/core/ap15/ap15rm_clock_config.c
index 198a2b20ce3d..70138eae4d7c 100644
--- a/arch/arm/mach-tegra/nvrm/core/ap15/ap15rm_clock_config.c
+++ b/arch/arm/mach-tegra/nvrm/core/ap15/ap15rm_clock_config.c
@@ -1279,7 +1279,8 @@ NvRmPrivAp15IsModuleClockException(
Ap15PllUConfigure(hRmDevice, PrefFreqList[0]);
pCstate->SourceClock = 0;
pCstate->Divider = 1;
- pCstate->actual_freq = PrefFreqList[0];
+ pCstate->actual_freq =
+ NvRmPrivGetClockSourceFreq(pCinfo->Sources[0]);
return NV_TRUE;
default:
diff --git a/arch/arm/mach-tegra/nvrm/core/ap15/nvrm_clocks.c b/arch/arm/mach-tegra/nvrm/core/ap15/nvrm_clocks.c
index 87775f87a4db..8ae5c9dfba72 100644
--- a/arch/arm/mach-tegra/nvrm/core/ap15/nvrm_clocks.c
+++ b/arch/arm/mach-tegra/nvrm/core/ap15/nvrm_clocks.c
@@ -1471,9 +1471,9 @@ NvRmPowerModuleClockConfig (
// Display configuration always at nominal voltage. UART divider is not
// in CAR, and clock state contains source, rather than UART frequency.
- // Hence, get ready for fastest clock. For other modules use maximum of
- // target and current frequency. Make sure voltage is high enough for
- // maximum module source frequency.
+ // Hence, get ready for fastest clock. Same for USB clock. For other
+ // modules use maximum of target and current frequency. Make sure that
+ // voltage is high enough for maximum module source frequency.
if ((ModuleName == NvRmModuleID_Display) ||
(ModuleName == NvRmModuleID_Dsi))
{
@@ -1482,7 +1482,8 @@ NvRmPowerModuleClockConfig (
}
else
{
- if (ModuleName == NvRmModuleID_Uart)
+ if ((ModuleName == NvRmModuleID_Uart) ||
+ (ModuleName == NvRmModuleID_Usb2Otg))
f = NvRmFreqMaximum;
else
f = NV_MAX(MaxFreq, state->actual_freq);
@@ -1664,7 +1665,7 @@ leave:
(ModuleName == NvRmModuleID_Dsi) || state->Vscale))
{
// Tune voltage level to the actually configured frequency; for Display
- // and UART, use maximum requested frequency. Make sure voltage is
+ // UART, and USB use maximum requested frequency. Make sure voltage is
// updated after display configuration, which may change DVFS clocks.
SourceClockFreq =
s_ClockSourceFreq[(cinfo->Sources[state->SourceClock])];
@@ -1685,7 +1686,8 @@ leave:
}
else
{
- if (ModuleName == NvRmModuleID_Uart)
+ if ((ModuleName == NvRmModuleID_Uart) ||
+ (ModuleName == NvRmModuleID_Usb2Otg))
f = MaxFreq;
else
f = state->actual_freq;
diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_i2c.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_i2c.c
index 6e61ddd95135..0f7a09446876 100644
--- a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_i2c.c
+++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_i2c.c
@@ -37,6 +37,9 @@
#define MAX8907B_I2C_SPEED_KHZ 400
#define MAX8907B_I2C_RETRY_CNT 2
+// Maximum i2c transaction count
+#define MAX_TRANSACTION_COUNT 5
+
NvBool Max8907bI2cWrite8(
NvOdmPmuDeviceHandle hDevice,
NvU8 Addr,
@@ -45,14 +48,14 @@ NvBool Max8907bI2cWrite8(
NvU32 i;
NvU8 WriteBuffer[2];
NvOdmI2cTransactionInfo TransactionInfo;
- NvOdmI2cStatus status = NvOdmI2cStatus_Success;
+ NvOdmI2cStatus status = NvOdmI2cStatus_Success;
Max8907bPrivData *hPmu = (Max8907bPrivData*)hDevice->pPrivate;
for (i = 0; i < MAX8907B_I2C_RETRY_CNT; i++)
{
WriteBuffer[0] = Addr & 0xFF; // PMU offset
WriteBuffer[1] = Data & 0xFF; // written data
-
+
TransactionInfo.Address = hPmu->DeviceAddr;
TransactionInfo.Buf = &WriteBuffer[0];
TransactionInfo.Flags = NVODM_I2C_IS_WRITE;
@@ -69,12 +72,12 @@ NvBool Max8907bI2cWrite8(
switch (status)
{
case NvOdmI2cStatus_Timeout:
- NVODMPMU_PRINTF(("NvOdmPmuI2cWrite8 Failed: Timeout\n"));
+ NVODMPMU_PRINTF(("NvOdmPmuI2cWrite8 Failed: Timeout\n"));
break;
case NvOdmI2cStatus_SlaveNotFound:
default:
NVODMPMU_PRINTF(("NvOdmPmuI2cWrite8 Failed: SlaveNotFound\n"));
- break;
+ break;
}
return NV_FALSE;
}
@@ -86,28 +89,30 @@ NvBool Max8907bI2cRead8(
{
NvU32 i;
NvU8 ReadBuffer = 0;
- NvOdmI2cStatus status = NvOdmI2cStatus_Success;
+ NvOdmI2cStatus status = NvOdmI2cStatus_Success;
Max8907bPrivData *hPmu = (Max8907bPrivData*)hDevice->pPrivate;
NvOdmI2cTransactionInfo TransactionInfo[2];
for (i = 0; i < MAX8907B_I2C_RETRY_CNT; i++)
{
+ NvU32 TransactionCount = 0;
// Write the PMU offset
ReadBuffer = Addr & 0xFF;
- TransactionInfo[0].Address = hPmu->DeviceAddr;
- TransactionInfo[0].Buf = &ReadBuffer;
- TransactionInfo[0].Flags = NVODM_I2C_IS_WRITE | NVODM_I2C_USE_REPEATED_START;
- TransactionInfo[0].NumBytes = 1;
+ TransactionInfo[TransactionCount].Address = hPmu->DeviceAddr;
+ TransactionInfo[TransactionCount].Buf = &ReadBuffer;
+ TransactionInfo[TransactionCount].Flags =
+ NVODM_I2C_IS_WRITE | NVODM_I2C_USE_REPEATED_START;
+ TransactionInfo[TransactionCount++].NumBytes = 1;
- TransactionInfo[1].Address = (hPmu->DeviceAddr | 0x1);
- TransactionInfo[1].Buf = &ReadBuffer;
- TransactionInfo[1].Flags = 0;
- TransactionInfo[1].NumBytes = 1;
+ TransactionInfo[TransactionCount].Address = (hPmu->DeviceAddr | 0x1);
+ TransactionInfo[TransactionCount].Buf = &ReadBuffer;
+ TransactionInfo[TransactionCount].Flags = 0;
+ TransactionInfo[TransactionCount++].NumBytes = 1;
// Read data from PMU at the specified offset
- status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo[0], 2,
- MAX8907B_I2C_SPEED_KHZ, NV_WAIT_INFINITE);
+ status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo[0],
+ TransactionCount, MAX8907B_I2C_SPEED_KHZ, NV_WAIT_INFINITE);
if (status == NvOdmI2cStatus_Success)
{
@@ -120,12 +125,12 @@ NvBool Max8907bI2cRead8(
switch (status)
{
case NvOdmI2cStatus_Timeout:
- NVODMPMU_PRINTF(("NvOdmPmuI2cRead8 Failed: Timeout\n"));
+ NVODMPMU_PRINTF(("NvOdmPmuI2cRead8 Failed: Timeout\n"));
break;
case NvOdmI2cStatus_SlaveNotFound:
default:
NVODMPMU_PRINTF(("NvOdmPmuI2cRead8 Failed: SlaveNotFound\n"));
- break;
+ break;
}
return NV_FALSE;
}
@@ -137,13 +142,13 @@ NvBool Max8907bI2cWrite32(
{
NvU32 i;
NvU8 WriteBuffer[5];
- NvOdmI2cStatus status = NvOdmI2cStatus_Success;
+ NvOdmI2cStatus status = NvOdmI2cStatus_Success;
Max8907bPrivData *hPmu = (Max8907bPrivData*)hDevice->pPrivate;
NvOdmI2cTransactionInfo TransactionInfo;
for (i = 0; i < MAX8907B_I2C_RETRY_CNT; i++)
{
- WriteBuffer[0] = (NvU8)(Addr & 0xFF);
+ WriteBuffer[0] = (NvU8)(Addr & 0xFF);
WriteBuffer[1] = (NvU8)((Data >> 24) & 0xFF);
WriteBuffer[2] = (NvU8)((Data >> 16) & 0xFF);
WriteBuffer[3] = (NvU8)((Data >> 8) & 0xFF);
@@ -154,7 +159,7 @@ NvBool Max8907bI2cWrite32(
TransactionInfo.Flags = NVODM_I2C_IS_WRITE;
TransactionInfo.NumBytes = 5;
- status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo, 1,
+ status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo, 1,
MAX8907B_I2C_SPEED_KHZ, NV_WAIT_INFINITE);
if (status == NvOdmI2cStatus_Success)
@@ -165,12 +170,12 @@ NvBool Max8907bI2cWrite32(
switch (status)
{
case NvOdmI2cStatus_Timeout:
- NVODMPMU_PRINTF(("NvOdmPmuI2cWrite32 Failed: Timeout\n"));
+ NVODMPMU_PRINTF(("NvOdmPmuI2cWrite32 Failed: Timeout\n"));
break;
case NvOdmI2cStatus_SlaveNotFound:
default:
NVODMPMU_PRINTF(("NvOdmPmuI2cWrite32 Failed: SlaveNotFound\n"));
- break;
+ break;
}
return NV_FALSE;
}
@@ -182,30 +187,32 @@ NvBool Max8907bI2cRead32(
{
NvU32 i;
NvU8 ReadBuffer[5];
- NvOdmI2cStatus status = NvOdmI2cStatus_Success;
+ NvOdmI2cStatus status = NvOdmI2cStatus_Success;
Max8907bPrivData *hPmu = (Max8907bPrivData*)hDevice->pPrivate;
NvOdmI2cTransactionInfo TransactionInfo[2];
for (i = 0; i < MAX8907B_I2C_RETRY_CNT; i++)
{
+ NvU32 TransactionCount = 0;
ReadBuffer[0] = Addr & 0xFF;
- TransactionInfo[0].Address = hPmu->DeviceAddr;
- TransactionInfo[0].Buf = &ReadBuffer[0];
- TransactionInfo[0].Flags = NVODM_I2C_IS_WRITE | NVODM_I2C_USE_REPEATED_START;
- TransactionInfo[0].NumBytes = 1;
+ TransactionInfo[TransactionCount].Address = hPmu->DeviceAddr;
+ TransactionInfo[TransactionCount].Buf = &ReadBuffer[0];
+ TransactionInfo[TransactionCount].Flags =
+ NVODM_I2C_IS_WRITE | NVODM_I2C_USE_REPEATED_START;
+ TransactionInfo[TransactionCount++].NumBytes = 1;
- TransactionInfo[1].Address = (hPmu->DeviceAddr | 0x1);
- TransactionInfo[1].Buf = &ReadBuffer[0];
- TransactionInfo[1].Flags = 0;
- TransactionInfo[1].NumBytes = 4;
+ TransactionInfo[TransactionCount].Address = (hPmu->DeviceAddr | 0x1);
+ TransactionInfo[TransactionCount].Buf = &ReadBuffer[0];
+ TransactionInfo[TransactionCount].Flags = 0;
+ TransactionInfo[TransactionCount++].NumBytes = 4;
- status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo[0], 2,
- MAX8907B_I2C_SPEED_KHZ, NV_WAIT_INFINITE);
+ status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo[0],
+ TransactionCount, MAX8907B_I2C_SPEED_KHZ, NV_WAIT_INFINITE);
if (status == NvOdmI2cStatus_Success)
{
- *Data = (ReadBuffer[0] << 24) | (ReadBuffer[1] << 16) |
+ *Data = (ReadBuffer[0] << 24) | (ReadBuffer[1] << 16) |
(ReadBuffer[2] << 8) | ReadBuffer[3];
return NV_TRUE;
@@ -216,12 +223,12 @@ NvBool Max8907bI2cRead32(
switch (status)
{
case NvOdmI2cStatus_Timeout:
- NVODMPMU_PRINTF(("NvOdmPmuI2cRead32 Failed: Timeout\n"));
+ NVODMPMU_PRINTF(("NvOdmPmuI2cRead32 Failed: Timeout\n"));
break;
case NvOdmI2cStatus_SlaveNotFound:
default:
NVODMPMU_PRINTF(("NvOdmPmuI2cRead32 Failed: SlaveNotFound\n"));
- break;
+ break;
}
return NV_FALSE;
}
@@ -233,13 +240,14 @@ NvBool Max8907bRtcI2cWriteTime(
{
NvU32 i;
NvU8 WriteBuffer[5];
- NvOdmI2cStatus status = NvOdmI2cStatus_Success;
+ NvOdmI2cStatus status = NvOdmI2cStatus_Success;
Max8907bPrivData *hPmu = (Max8907bPrivData*)hDevice->pPrivate;
NvOdmI2cTransactionInfo TransactionInfo;
+ NVODMPMU_PRINTF(("\n RTC I2C write: Addr=0x%x, Data=0x%x ", Addr, Data));
for (i = 0; i < MAX8907B_I2C_RETRY_CNT; i++)
{
- WriteBuffer[0] = (NvU8)(Addr & 0xFF);
+ WriteBuffer[0] = (NvU8)(Addr & 0xFF);
WriteBuffer[1] = (NvU8)((Data >> 24) & 0xFF);
WriteBuffer[2] = (NvU8)((Data >> 16) & 0xFF);
WriteBuffer[3] = (NvU8)((Data >> 8) & 0xFF);
@@ -250,7 +258,7 @@ NvBool Max8907bRtcI2cWriteTime(
TransactionInfo.Flags = NVODM_I2C_IS_WRITE;
TransactionInfo.NumBytes = 5;
- status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo, 1,
+ status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo, 1,
MAX8907B_I2C_SPEED_KHZ, NV_WAIT_INFINITE);
if (status == NvOdmI2cStatus_Success)
@@ -261,12 +269,12 @@ NvBool Max8907bRtcI2cWriteTime(
switch (status)
{
case NvOdmI2cStatus_Timeout:
- NVODMPMU_PRINTF(("Max8907bRtcI2cWrite32 Failed: Timeout\n"));
+ NVODMPMU_PRINTF(("Max8907bRtcI2cWrite32 Failed: Timeout\n"));
break;
case NvOdmI2cStatus_SlaveNotFound:
default:
NVODMPMU_PRINTF(("Max8907bRtcI2cWrite32 Failed: SlaveNotFound\n"));
- break;
+ break;
}
return NV_FALSE;
}
@@ -278,46 +286,63 @@ NvBool Max8907bRtcI2cReadTime(
{
NvU32 i;
NvU8 ReadBuffer[4];
- NvOdmI2cStatus status = NvOdmI2cStatus_Success;
+ NvOdmI2cStatus status = NvOdmI2cStatus_Success;
Max8907bPrivData *hPmu = (Max8907bPrivData*)hDevice->pPrivate;
- NvOdmI2cTransactionInfo TransactionInfo[4];
+ NvOdmI2cTransactionInfo TransactionInfo[MAX_TRANSACTION_COUNT];
+ NVODMPMU_PRINTF(("\n RTC I2C read: Addr=0x%x ", Addr));
for (i = 0; i < MAX8907B_I2C_RETRY_CNT; i++)
{
- ReadBuffer[0] = Addr++ & 0xFF;
- ReadBuffer[1] = Addr++ & 0xFF;
- ReadBuffer[2] = Addr++ & 0xFF;
- ReadBuffer[3] = 0;
-
- TransactionInfo[0].Address = MAX8907B_RTC_SLAVE_ADDR;
- TransactionInfo[0].Buf = &ReadBuffer[0];
- TransactionInfo[0].Flags = NVODM_I2C_IS_WRITE | NVODM_I2C_USE_REPEATED_START;
- TransactionInfo[0].NumBytes = 1;
-
- // Seconds
- TransactionInfo[1].Address = (MAX8907B_RTC_SLAVE_ADDR | 0x1);
- TransactionInfo[1].Buf = &ReadBuffer[0];
- TransactionInfo[1].Flags = 0;
- TransactionInfo[1].NumBytes = 1;
-
- // Minutes
- TransactionInfo[2].Address = (MAX8907B_RTC_SLAVE_ADDR | 0x1);
- TransactionInfo[2].Buf = &ReadBuffer[1];
- TransactionInfo[2].Flags = 0;
- TransactionInfo[2].NumBytes = 1;
-
- // Hours
- TransactionInfo[3].Address = (MAX8907B_RTC_SLAVE_ADDR | 0x1);
- TransactionInfo[3].Buf = &ReadBuffer[2];
- TransactionInfo[3].Flags = 0;
- TransactionInfo[3].NumBytes = 1;
-
- status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo[0], 4,
- MAX8907B_I2C_SPEED_KHZ, NV_WAIT_INFINITE);
+ NvU32 TransactionCount = 0;
+ ReadBuffer[0] = Addr & 0xFF;
+ TransactionInfo[TransactionCount].Address = MAX8907B_RTC_SLAVE_ADDR;
+ TransactionInfo[TransactionCount].Buf = &ReadBuffer[0];
+ TransactionInfo[TransactionCount].Flags =
+ NVODM_I2C_IS_WRITE | NVODM_I2C_USE_REPEATED_START;
+ TransactionInfo[TransactionCount++].NumBytes = 1;
+
+ // Seconds / day
+ if (TransactionCount >= MAX_TRANSACTION_COUNT)
+ return NV_FALSE;
+ TransactionInfo[TransactionCount].Address =
+ (MAX8907B_RTC_SLAVE_ADDR | 0x1);
+ TransactionInfo[TransactionCount].Buf = &ReadBuffer[0];
+ TransactionInfo[TransactionCount].Flags = 0;
+ TransactionInfo[TransactionCount++].NumBytes = 1;
+
+ // Minutes / month
+ if (TransactionCount >= MAX_TRANSACTION_COUNT)
+ return NV_FALSE;
+ TransactionInfo[TransactionCount].Address =
+ (MAX8907B_RTC_SLAVE_ADDR | 0x1);
+ TransactionInfo[TransactionCount].Buf = &ReadBuffer[1];
+ TransactionInfo[TransactionCount].Flags = 0;
+ TransactionInfo[TransactionCount++].NumBytes = 1;
+
+ // Hours / YY1
+ if (TransactionCount >= MAX_TRANSACTION_COUNT)
+ return NV_FALSE;
+ TransactionInfo[TransactionCount].Address =
+ (MAX8907B_RTC_SLAVE_ADDR | 0x1);
+ TransactionInfo[TransactionCount].Buf = &ReadBuffer[2];
+ TransactionInfo[TransactionCount].Flags = 0;
+ TransactionInfo[TransactionCount++].NumBytes = 1;
+
+ // Weekday / YY2
+ if (TransactionCount >= MAX_TRANSACTION_COUNT)
+ return NV_FALSE;
+ TransactionInfo[TransactionCount].Address =
+ (MAX8907B_RTC_SLAVE_ADDR | 0x1);
+ TransactionInfo[TransactionCount].Buf = &ReadBuffer[3];
+ TransactionInfo[TransactionCount].Flags = 0;
+ TransactionInfo[TransactionCount++].NumBytes = 1;
+
+ status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo[0],
+ TransactionCount, MAX8907B_I2C_SPEED_KHZ, NV_WAIT_INFINITE);
if (status == NvOdmI2cStatus_Success)
{
- *Data = (ReadBuffer[0] << 24) | (ReadBuffer[1] << 16) |
+ *Data = (ReadBuffer[0] << 24) | (ReadBuffer[1] << 16) |
(ReadBuffer[2] << 8) | ReadBuffer[3];
return NV_TRUE;
@@ -328,12 +353,12 @@ NvBool Max8907bRtcI2cReadTime(
switch (status)
{
case NvOdmI2cStatus_Timeout:
- NVODMPMU_PRINTF(("Max8907bRtcI2cRead32 Failed: Timeout\n"));
+ NVODMPMU_PRINTF(("Max8907bRtcI2cRead32 Failed: Timeout\n"));
break;
case NvOdmI2cStatus_SlaveNotFound:
default:
NVODMPMU_PRINTF(("Max8907bRtcI2cRead32 Failed: SlaveNotFound\n"));
- break;
+ break;
}
return NV_FALSE;
}
diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_rtc.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_rtc.c
index 0c179efdf21c..50afb66beba3 100644
--- a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_rtc.c
+++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_rtc.c
@@ -30,151 +30,215 @@
*
*/
+#include <linux/time.h>
+#include <linux/rtc.h>
#include "max8907b.h"
#include "max8907b_rtc.h"
#include "max8907b_i2c.h"
#include "max8907b_reg.h"
-/**
+/**
* The Maxim 8907B does not have an RTC that simply counts
* seconds from some time t0 (as defined by the OS API).
* Instead, this RTC contains several BCD (Binary Coded Decimal)
* registers, including: seconds, minutes, hours, days, day of
* week, date, etc... These registers account for leap year and
* the various days of the month as well.
-*
+*
* Since the OS interpretation of seconds to a particular
* date/time from some OS-defined t0 is unknown at this level of
* the implementation, it is not possible to translate the given
* seconds into these registers (at least, not without a
* dependency on some OS-specific information).
-*
-* Therefore, this implementation contains a static variable
-* (RtcDays) which is derived from the number of seconds given
-* when Max8907bRtcCountWrite() is called. The seconds, minutes
-* and hours are then programmed to the RTC and used to keep
-* track of the current time within the day.
-*
-* TO DO: Increment the day whenever it rolls over (requires
-* handling an interrupt at midnight each day).
+*
*/
#define MAX8907B_SECONDS_PER_DAY (60*60*24)
#define MAX8907B_SECONDS_PER_HOUR (60*60)
#define MAX8907B_SECONDS_PER_MINUTE (60)
+#define LINUX_RTC_BASE_YEAR 1900
+
static NvBool bRtcNotInitialized = NV_TRUE;
-static NvU32 RtcDays = 0;
-NvBool
+NvBool
Max8907bRtcCountRead(
- NvOdmPmuDeviceHandle hDevice,
+ NvOdmPmuDeviceHandle hDevice,
NvU32* Count)
{
NvU32 data = 0;
NvU32 BcdHours, BcdMinutes, BcdSeconds;
NvU32 Hours, Minutes, Seconds;
+ NvU32 BcdDD, BcdMM, BcdYY1, BcdYY2;
+ NvU32 DD, MM, YY1, YY2, YYYY;
+ // struct rtc_time tm;
- if (Max8907bRtcWasStartUpFromNoPower(hDevice) && bRtcNotInitialized)
- {
- Max8907bRtcCountWrite(hDevice, 0);
- *Count = 0;
- }
- else
+ *Count = 0;
+ // Read seconds, minute, hour and weekday data from RTC registers
+ if (Max8907bRtcI2cReadTime(hDevice, MAX8907B_RTC_SEC, &data))
{
- if (Max8907bRtcI2cReadTime(hDevice, MAX8907B_RTC_SEC, &data))
+ NVODMPMU_PRINTF(("\n Read time data-sec=0x%x ", data));
+ // Extract seconds, minute and hour data from RTC registers read
+ BcdHours = (data >> 8) & 0xFF;
+ BcdMinutes = (data >> 16) & 0xFF;
+ BcdSeconds = (data >> 24) & 0xFF;
+
+ // Convert BCT time into decimal values
+ Hours = ((BcdHours & 0xF0)>>4)*10 + (BcdHours & 0xF);
+ Minutes = ((BcdMinutes & 0xF0)>>4)*10 + (BcdMinutes & 0xF);
+ Seconds = ((BcdSeconds & 0xF0)>>4)*10 + (BcdSeconds & 0xF);
+
+ // Read day, month, yy1 and yy2 data from RTC registers
+ if (Max8907bRtcI2cReadTime(hDevice, MAX8907B_RTC_DATE, &data))
{
-
- BcdHours = (data >> 8) & 0xFF;
- BcdMinutes = (data >> 16) & 0xFF;
- BcdSeconds = (data >> 24) & 0xFF;
-
- Hours = ((BcdHours & 0xF0)>>4)*10 + (BcdHours & 0xF);
- Minutes = ((BcdMinutes & 0xF0)>>4)*10 + (BcdMinutes & 0xF);
- Seconds = ((BcdSeconds & 0xF0)>>4)*10 + (BcdSeconds & 0xF);
-
- *Count = (Hours * MAX8907B_SECONDS_PER_HOUR) +
- (Minutes * MAX8907B_SECONDS_PER_MINUTE) + Seconds;
+ NVODMPMU_PRINTF(("\n Read time data-year=0x%x ", data));
+ // Extract day, month, yy1 and yy2 data from RTC registers read
+ BcdYY2 = (data & 0xFF);
+ BcdYY1 = (data >> 8) & 0xFF;
+ BcdMM = (data >> 16) & 0xFF;
+ BcdDD = (data >> 24) & 0xFF;
+ // convert bct day/month/year data to decimal values
+ YY2 = ((BcdYY2 & 0xF0)>>4)*10 + (BcdYY2 & 0xF);
+ YY1 = ((BcdYY1 & 0xF0)>>4)*10 + (BcdYY1 & 0xF);
+ YYYY = (YY2 * 100 + YY1) & 0xFFFF;
+ MM = ((BcdMM & 0xF0)>>4)*10 + (BcdMM & 0xF);
+ DD = ((BcdDD & 0xF0)>>4)*10 + (BcdDD & 0xF);
+ // get seconds since reference time value given
+ // year, month, day, hour, minutes and seconds
+ // NOTE: Using linux specific API mktime for conversion
+ *Count = mktime(YYYY, (MM + 1), DD, Hours, Minutes, Seconds);
+ NVODMPMU_PRINTF(("\n Rtc read count=0x%x ", *Count));
+ NVODMPMU_PRINTF(("\n mktime: YYYY=%d MM=%d DD=%d Hr=%d Min=%d "
+ "Sec=%d, *Count=0x%x ", YYYY, (MM + 1), DD, Hours, Minutes,
+ Seconds, *Count));
+#if NV_DEBUG
+ // Call to verify that reverse conversion of seconds matches date
+ rtc_time_to_tm(*Count, &tm);
+ // Check if Local_rtc_time_to_tm can return values sent to mktime
+ NVODMPMU_PRINTF(("\n rtc_time_to_tm: YYYY=%d MM=%d DD=%d Hr=%d "
+ "Min=%d Sec=%d, *Count=0x%x ", (tm.tm_year +
+ LINUX_RTC_BASE_YEAR), tm.tm_mon, tm.tm_mday, tm.tm_hour,
+ tm.tm_min, tm.tm_sec, *Count));
+#endif
}
else
{
- NvOdmOsDebugPrintf("Max8907bRtcCountRead() error. ");
+ NVODMPMU_PRINTF(("\n Max8907bRtcCountRead() error. "));
return NV_FALSE;
}
}
+ else
+ {
+ NVODMPMU_PRINTF(("\n Max8907bRtcCountRead() error. "));
+ return NV_FALSE;
+ }
+ NVODMPMU_PRINTF(("\n *Count=0x%x ", *Count));
return NV_TRUE;
}
-NvBool
+NvBool
Max8907bRtcAlarmCountRead(
- NvOdmPmuDeviceHandle hDevice,
+ NvOdmPmuDeviceHandle hDevice,
NvU32* Count)
{
return NV_FALSE;
}
-NvBool
+NvBool
Max8907bRtcCountWrite(
- NvOdmPmuDeviceHandle hDevice,
+ NvOdmPmuDeviceHandle hDevice,
NvU32 Count)
{
- NvU32 Hours, Minutes, Seconds;
NvU32 BcdHours, BcdMinutes, BcdSeconds;
NvU32 data = 0;
-
- BcdHours = BcdMinutes = BcdSeconds = 0;
-
- RtcDays = Count / MAX8907B_SECONDS_PER_DAY;
-
- Hours = (Count % MAX8907B_SECONDS_PER_DAY) / MAX8907B_SECONDS_PER_HOUR;
- Minutes = ((Count % MAX8907B_SECONDS_PER_DAY) % MAX8907B_SECONDS_PER_HOUR) / MAX8907B_SECONDS_PER_MINUTE;
- Seconds = Count % MAX8907B_SECONDS_PER_MINUTE;
-
- BcdHours = (( Hours/10) << 4) | ( Hours%10);
- BcdMinutes = ((Minutes/10) << 4) | (Minutes%10);
- BcdSeconds = ((Seconds/10) << 4) | (Seconds%10);
+ NvU8 BcdDD, BcdMM, BcdYY1, BcdYY2;
+ NvU16 YYYY;
+ struct rtc_time tm;
+ NvU32 data1;
+
+ NVODMPMU_PRINTF(("\n Rtc write count=0x%x ", Count));
+ // convert seconds since reference time into date
+ // NOTE: using linux specific convert function rtc_time_to_tm
+ rtc_time_to_tm(Count, &tm);
+ NVODMPMU_PRINTF(("\n rtc_time_to_tm: YYYY=%d MM=%d DD=%d Hr=%d Min=%d "
+ "Sec=%d, *Count=0x%x ", (tm.tm_year + LINUX_RTC_BASE_YEAR),
+ (tm.tm_mon + 1), tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec, Count));
+
+ // Convert time to bcd format
+ BcdHours = ((tm.tm_hour / 10) << 4) | (tm.tm_hour % 10);
+ BcdMinutes = ((tm.tm_min/10) << 4) | (tm.tm_min%10);
+ BcdSeconds = ((tm.tm_sec/10) << 4) | (tm.tm_sec%10);
data = (BcdSeconds << 24) | (BcdMinutes << 16) | (BcdHours << 8);
+ // write time - seconds, minutes and hours in a day to RTC registers
if (Max8907bRtcI2cWriteTime(hDevice, MAX8907B_RTC_SEC, data))
{
- bRtcNotInitialized = NV_FALSE;
- return NV_TRUE;
+ // set the day, month, year
+ // Assuming we get the days since 1 Jan 1970
+
+ // convert date to bct format
+ BcdDD = (((NvU8)tm.tm_mday / 10) << 4) | ((NvU8)tm.tm_mday % 10);
+ BcdMM = (((NvU8)tm.tm_mon / 10) << 4) | ((NvU8)tm.tm_mon % 10);
+ YYYY = (NvU16)tm.tm_year + LINUX_RTC_BASE_YEAR;
+ BcdYY1 = (((NvU8)(YYYY % 100) / 10) << 4) | ((NvU8)(YYYY % 100) % 10);
+ BcdYY2 = (((NvU8)(YYYY / 100) / 10) << 4) | ((NvU8)(YYYY / 100) % 10);
+ data = (NvU32)((BcdDD << 24) | (BcdMM << 16) | (BcdYY1 << 8) | BcdYY2);
+ // write date - day, month, and year to RTC registers
+ if (!(Max8907bRtcI2cWriteTime(hDevice, MAX8907B_RTC_DATE, data)))
+ {
+ NVODMPMU_PRINTF(("\n Max8907bRtcCountWrite() error. "));
+ return NV_FALSE;
+ }
+#if NV_DEBUG
+ // verify that read back values from RTC matches written values
+ if (!(Max8907bRtcI2cReadTime(hDevice, MAX8907B_RTC_DATE, &data1)))
+ {
+ NVODMPMU_PRINTF(("\n Max8907bRtcCountRead() error. "));
+ return NV_FALSE;
+ }
+ if (data1 == data)
+ {
+ NVODMPMU_PRINTF(("\n Write read Success. "));
+ return NV_TRUE;
+ }
+ else
+ {
+ // return error when read data does not match written data
+ NVODMPMU_PRINTF(("\n Error: write data=0x%x, rd data=0x%x. ", data, data1));
+ return NV_FALSE;
+ }
+#endif
}
else
{
- NvOdmOsDebugPrintf("Max8907bRtcCountWrite() error. ");
+ NVODMPMU_PRINTF(("\n Max8907bRtcCountWrite() error. "));
return NV_FALSE;
}
}
-NvBool
+NvBool
Max8907bRtcAlarmCountWrite(
- NvOdmPmuDeviceHandle hDevice,
+ NvOdmPmuDeviceHandle hDevice,
NvU32 Count)
{
return NV_FALSE;
}
-NvBool
+NvBool
Max8907bRtcIsAlarmIntEnabled(NvOdmPmuDeviceHandle hDevice)
{
return NV_FALSE;
}
-NvBool
+NvBool
Max8907bRtcAlarmIntEnable(
- NvOdmPmuDeviceHandle hDevice,
+ NvOdmPmuDeviceHandle hDevice,
NvBool Enable)
{
return NV_FALSE;
}
-NvBool
-Max8907bRtcWasStartUpFromNoPower(NvOdmPmuDeviceHandle hDevice)
-{
- return NV_TRUE;
-}
-
NvBool
Max8907bIsRtcInitialized(NvOdmPmuDeviceHandle hDevice)
{
diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_rtc.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_rtc.c
index d897eb9f4ee3..29f52e2d7ae0 100644
--- a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_rtc.c
+++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_rtc.c
@@ -30,10 +30,20 @@
*
*/
+#include <linux/time.h>
#include "nvodm_pmu_tps6586x_rtc.h"
#include "nvodm_pmu_tps6586x_i2c.h"
#include "tps6586x_reg.h"
+// macro SHIFT_TO_2009 if 1, uses 2009 as reference year instead of 1970
+// This is because RTC in PMU TPS6586x can store duration of 34 years,
+// else we cannot retain date beyond 2004
+#define SHIFT_TO_2009 1
+#if SHIFT_TO_2009
+static unsigned long epoch = 2009;
+static unsigned long epoch_sec = 0;
+#endif
+
static NvBool bRtcNotInitialized = NV_TRUE;
/* Read RTC count register */
@@ -43,12 +53,12 @@ Tps6586xRtcCountRead(
NvU32* Count)
{
NvU32 ReadBuffer[2];
-
+
// 1) The I2C address pointer must not be left pointing in the range 0xC6 to 0xCA
// 2) The maximum time for the address pointer to be in this range is 1ms
// 3) Always read RTC_ALARM2 in the following order to prevent the address pointer
- // from stopping at 0xC6: RTC_ALARM2_LO, then RTC_ALARM2_HI
-
+ // from stopping at 0xC6: RTC_ALARM2_LO, then RTC_ALARM2_HI
+
if (Tps6586xRtcWasStartUpFromNoPower(hDevice) && bRtcNotInitialized)
{
Tps6586xRtcCountWrite(hDevice, 0);
@@ -59,55 +69,76 @@ Tps6586xRtcCountRead(
// The unit of the RTC count is second!!! 1024 tick = 1s.
// Read all 40 bit and right move 10 = Read the hightest 32bit and right move 2
Tps6586xI2cRead32(hDevice, TPS6586x_RC6_RTC_COUNT4, &ReadBuffer[0]);
-
+
Tps6586xI2cRead8(hDevice, TPS6586x_RCA_RTC_COUNT0, &ReadBuffer[1]);
-
+
Tps6586xI2cRead8(hDevice, TPS6586x_RC0_RTC_CTRL, &ReadBuffer[1]);
-
+
// return second
*Count = ReadBuffer[0]>>2;
}
-
+#if SHIFT_TO_2009
+ // calculate epoch_sec once
+ if (!epoch_sec)
+ epoch_sec = mktime(epoch,1,1,0,0,0);
+ *Count += epoch_sec;
+#endif
+
return NV_TRUE;
}
/* Write RTC count register */
-NvBool
+NvBool
Tps6586xRtcCountWrite(
- NvOdmPmuDeviceHandle hDevice,
+ NvOdmPmuDeviceHandle hDevice,
NvU32 Count)
{
NvU32 ReadBuffer = 0;
-
+#if SHIFT_TO_2009
+ // calculate epoch_sec once
+ if (!epoch_sec)
+ epoch_sec = mktime(epoch,1,1,0,0,0);
+ if (Count < (NvU32)epoch_sec)
+ {
+ // prevent setting date earlier than 'epoch'
+ pr_warning("\n Date being set cannot be earlier than least year=%d. "
+ "Setting as least year. ", (int)epoch);
+ // base year seconds count is 0
+ Count = 0;
+ }
+ else
+ Count -= (NvU32)epoch_sec;
+#endif
+
// To enable incrementing of the RTC_COUNT[39:0] from an initial value set by the host,
- // the RTC_ENABLE bit should be written to 1 only after the RTC_OUT voltage reaches
+ // the RTC_ENABLE bit should be written to 1 only after the RTC_OUT voltage reaches
// the operating range
-
+
// Clear RTC_ENABLE before writing RTC_COUNT
Tps6586xI2cRead8(hDevice, TPS6586x_RC0_RTC_CTRL, &ReadBuffer);
ReadBuffer = ReadBuffer & 0xDF;
Tps6586xI2cWrite8(hDevice, TPS6586x_RC0_RTC_CTRL, ReadBuffer);
-
+
Tps6586xI2cWrite32(hDevice, TPS6586x_RC6_RTC_COUNT4, (Count<<2));
- Tps6586xI2cWrite8(hDevice, TPS6586x_RCA_RTC_COUNT0, 0);
-
+ Tps6586xI2cWrite8(hDevice, TPS6586x_RCA_RTC_COUNT0, 0);
+
// Set RTC_ENABLE after writing RTC_COUNT
Tps6586xI2cRead8(hDevice, TPS6586x_RC0_RTC_CTRL, &ReadBuffer);
ReadBuffer = ReadBuffer | 0x20;
Tps6586xI2cWrite8(hDevice, TPS6586x_RC0_RTC_CTRL, ReadBuffer);
-
+
if (bRtcNotInitialized)
bRtcNotInitialized = NV_FALSE;
-
+
return NV_TRUE;
}
/* Read RTC alarm count register */
-NvBool
+NvBool
Tps6586xRtcAlarmCountRead(
- NvOdmPmuDeviceHandle hDevice,
+ NvOdmPmuDeviceHandle hDevice,
NvU32* Count)
{
return NV_FALSE;
@@ -115,9 +146,9 @@ Tps6586xRtcAlarmCountRead(
/* Write RTC alarm count register */
-NvBool
+NvBool
Tps6586xRtcAlarmCountWrite(
- NvOdmPmuDeviceHandle hDevice,
+ NvOdmPmuDeviceHandle hDevice,
NvU32 Count)
{
return NV_FALSE;
@@ -125,7 +156,7 @@ Tps6586xRtcAlarmCountWrite(
/* Reads RTC alarm interrupt mask status */
-NvBool
+NvBool
Tps6586xRtcIsAlarmIntEnabled(NvOdmPmuDeviceHandle hDevice)
{
return NV_FALSE;
@@ -133,9 +164,9 @@ Tps6586xRtcIsAlarmIntEnabled(NvOdmPmuDeviceHandle hDevice)
/* Enables / Disables the RTC alarm interrupt */
-NvBool
+NvBool
Tps6586xRtcAlarmIntEnable(
- NvOdmPmuDeviceHandle hDevice,
+ NvOdmPmuDeviceHandle hDevice,
NvBool Enable)
{
return NV_FALSE;
@@ -143,7 +174,7 @@ Tps6586xRtcAlarmIntEnable(
/* Checks if boot was from nopower / powered state */
-NvBool
+NvBool
Tps6586xRtcWasStartUpFromNoPower(NvOdmPmuDeviceHandle hDevice)
{
NvU32 Data = 0;