summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGary King <gking@nvidia.com>2009-12-23 14:29:17 -0800
committerGary King <gking@nvidia.com>2009-12-23 17:54:12 -0800
commit022b97f21665deea09e2303defbc718639d2c04d (patch)
tree13b74670c77f934bc68915da0917da31053c16c2
parentc8855f2847834bf9db39940c12a73389da4ad9c6 (diff)
tegra RM: clock API improvements
allow passing of shmoo data as a preserved memory handle in carveout reinitialize scaled clocks when resuming from LP0 add first reference indicator to module clock state Change-Id: Ifea8901b6924b9992885bd10fa07991fe55a06de
-rw-r--r--arch/arm/mach-tegra/include/nvbootargs.h11
-rw-r--r--arch/arm/mach-tegra/nvos/nvos.c22
-rw-r--r--arch/arm/mach-tegra/nvrm/core/ap15/nvrm_clocks.c39
-rw-r--r--arch/arm/mach-tegra/nvrm/core/common/nvrm_clocks.h1
-rw-r--r--arch/arm/mach-tegra/nvrm/core/common/nvrm_clocks_limits.c105
5 files changed, 141 insertions, 37 deletions
diff --git a/arch/arm/mach-tegra/include/nvbootargs.h b/arch/arm/mach-tegra/include/nvbootargs.h
index f685923d0b67..7cfa00f3506a 100644
--- a/arch/arm/mach-tegra/include/nvbootargs.h
+++ b/arch/arm/mach-tegra/include/nvbootargs.h
@@ -58,6 +58,7 @@ typedef enum
NvBootArgKey_Display,
NvBootArgKey_Framebuffer,
NvBootArgKey_ChipShmoo,
+ NvBootArgKey_ChipShmooPhys,
NvBootArgKey_PreservedMemHandle_0 = 0x10000,
NvBootArgKey_PreservedMemHandle_Num = (NvBootArgKey_PreservedMemHandle_0 +
NV_BOOTARGS_MAX_PRESERVED_MEMHANDLES),
@@ -178,6 +179,15 @@ typedef struct NvBootArgsChipShmooRec
NvU32 SvopHighSetting;
} NvBootArgsChipShmoo;
+/**
+ * Chip chatcterization shmoo data indexed by NvBootArgKey_ChipShmooPhys
+ */
+typedef struct NvBootArgsChipShmooPhysRec
+{
+ NvU32 PhysShmooPtr;
+ NvU32 Size;
+} NvBootArgsChipShmooPhys;
+
#define NVBOOTARG_NUM_PRESERVED_HANDLES (NvBootArgKey_PreservedMemHandle_Num - \
NvBootArgKey_PreservedMemHandle_0)
@@ -190,6 +200,7 @@ typedef struct NvBootArgsRec
NvBootArgsDisplay DisplayArgs;
NvBootArgsFramebuffer FramebufferArgs;
NvBootArgsChipShmoo ChipShmooArgs;
+ NvBootArgsChipShmooPhys ChipShmooPhysArgs;
NvBootArgsPreservedMemHandle MemHandleArgs[NVBOOTARG_NUM_PRESERVED_HANDLES];
} NvBootArgs;
diff --git a/arch/arm/mach-tegra/nvos/nvos.c b/arch/arm/mach-tegra/nvos/nvos.c
index baa6b339bd7d..4049772c890a 100644
--- a/arch/arm/mach-tegra/nvos/nvos.c
+++ b/arch/arm/mach-tegra/nvos/nvos.c
@@ -161,7 +161,7 @@ typedef struct NvOsInterruptBlockRec
static NvOsInterruptBlock *s_pIrqList[NVOS_MAX_SYSTEM_IRQS] = { NULL };
-static NvBootArgs s_BootArgs = { {0}, {0}, {0}, {{0}} };
+static NvBootArgs s_BootArgs = { {0}, {0}, {0}, {0}, {0}, {{0}} };
/* Defined in mach-tegra/irq.c. Stores the number of native (non-GPIO) SoC
* IRQs. */
@@ -1692,6 +1692,10 @@ NvError NvOsBootArgGet(NvU32 key, void *arg, NvU32 size)
src = &s_BootArgs.RmArgs;
size_src = sizeof(NvBootArgsRm);
break;
+ case NvBootArgKey_ChipShmooPhys:
+ src = &s_BootArgs.ChipShmooPhysArgs;
+ size_src = sizeof(NvBootArgsChipShmooPhys);
+ break;
default:
src = NULL;
size_src = 0;
@@ -1831,6 +1835,22 @@ static int __init parse_tegra_tag(const struct tag *tag)
*dst = *src;
return 0;
}
+ case NvBootArgKey_ChipShmooPhys:
+ {
+ NvBootArgsChipShmooPhys *dst = &s_BootArgs.ChipShmooPhysArgs;
+ const NvBootArgsChipShmooPhys *src =
+ (const NvBootArgsChipShmooPhys *)nvtag->bootarg;
+
+ if (nvtag->bootarg_len != sizeof(NvBootArgsChipShmooPhys))
+ printk("Unexpected phys shmoo tag length!\n");
+ else
+ {
+ printk("Phys shmoo tag with pointer 0x%X and length %u\n",
+ src->PhysShmooPtr, src->Size);
+ *dst = *src;
+ }
+ return 0;
+ }
default:
return 0;
}
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 92e06db73ce6..87775f87a4db 100644
--- a/arch/arm/mach-tegra/nvrm/core/ap15/nvrm_clocks.c
+++ b/arch/arm/mach-tegra/nvrm/core/ap15/nvrm_clocks.c
@@ -359,9 +359,9 @@ NvRmPrivMemoryClockReAttach(
NvU32 i;
NvRmClockSource SourceId = cinfo->Sources[state->SourceClock];
- // MC clock on AP20 is always the same as EMC1x domain clock - no need for
- // source reference double-counting.
- if ((hDevice->ChipId.Id == 0x20) &&
+ // MC clock on AP20 and newer chips is always the same as EMC1x domain clock
+ // So there is no need for source reference double-counting.
+ if ((hDevice->ChipId.Id >= 0x20) &&
(cinfo->Module == NvRmPrivModuleID_MemoryController))
return;
@@ -487,6 +487,13 @@ NvError NvRmPowerModuleClockControl(
}
NvOsMutexLock(s_hClockMutex);
+ // Restart reference counting if it is the 1st clock control call
+ if (!state->FirstReference)
+ {
+ state->FirstReference = NV_TRUE;
+ state->refCount = 0;
+ }
+
// Update reference count, and exit if
// - clock enable requested and module clock is already enabled
// - clock disable requested, but not all enable requests have been matched
@@ -855,7 +862,10 @@ static void ModuleClockStateInit(NvRmDeviceHandle hRmDevice)
else
{
// Check implicit attachment to PLLs for main clocks only
- ImplicitPll = NvRmPrivGetImplicitPllSource(hRmDevice, cinfo->Module);
+ ImplicitPll =
+ NvRmPrivGetImplicitPllSource(hRmDevice, cinfo->Module);
+ NV_ASSERT((ImplicitPll == NvRmClockSource_Invalid) ||
+ (cinfo->ClkEnableOffset));
}
// Fill in module clock state, attach explicit PLL sources for clocks
@@ -884,12 +894,15 @@ static void ModuleClockStateInit(NvRmDeviceHandle hRmDevice)
NvRmPrivCoreClockReAttach(hRmDevice, pCore->SourceId, SourceId);
}
- // Attach implicit PLL sources
- if (ImplicitPll != NvRmClockSource_Invalid)
+ // Attach implicit PLL sources and update reference count
+ // for enabled main clocks
+ if (flags == NvRmClockConfig_SubConfig)
+ continue;
+
+ if (cinfo->ClkEnableOffset)
{
- NV_ASSERT(cinfo->ClkEnableOffset);
- reg = NV_REGR(hRmDevice, NvRmPrivModuleID_ClockAndReset, 0,
- cinfo->ClkEnableOffset);
+ reg = NV_REGR(hRmDevice, NvRmPrivModuleID_ClockAndReset, 0,
+ cinfo->ClkEnableOffset);
if ((reg & cinfo->ClkEnableField) == cinfo->ClkEnableField)
{
for (j = 0; j < s_PllReferencesTableSize; j++)
@@ -898,8 +911,11 @@ static void ModuleClockStateInit(NvRmDeviceHandle hRmDevice)
NvRmPrivPllRefUpdate(
hRmDevice, &s_PllReferencesTable[j], NV_TRUE);
}
+ state->refCount = 1;
}
}
+ else
+ state->refCount = 1; // free running clock
}
}
@@ -1280,10 +1296,11 @@ NvRmPrivClocksResume(NvRmDeviceHandle hRmDevice)
{
// Sync clock sources after LP0
NvRmPrivClockSourceFreqInit(hRmDevice, s_ClockSourceFreq);
+ ScaledClockConfigInit(hRmDevice);
if ((hRmDevice->ChipId.Id == 0x15) || (hRmDevice->ChipId.Id == 0x16))
NvRmPrivAp15FastClockConfig(hRmDevice);
- // else if (hRmDevice->ChipId.Id == 0x20)
- // TODO: NvRmPrivAp20FastClockConfig(hRmDevice);
+ else if (hRmDevice->ChipId.Id == 0x20)
+ NvRmPrivAp20FastClockConfig(hRmDevice);
}
diff --git a/arch/arm/mach-tegra/nvrm/core/common/nvrm_clocks.h b/arch/arm/mach-tegra/nvrm/core/common/nvrm_clocks.h
index 2f3cb8837c51..c2ee7d82734a 100644
--- a/arch/arm/mach-tegra/nvrm/core/common/nvrm_clocks.h
+++ b/arch/arm/mach-tegra/nvrm/core/common/nvrm_clocks.h
@@ -374,6 +374,7 @@ typedef struct NvRmModuleClockStateRec
NvU32 refCount;
NvU32 Vstep;
NvBool Vscale;
+ NvBool FirstReference;
#if NVRM_DIAG_LOCK_SUPPORTED
NvBool DiagLock; // once locked, can not be changed
#endif
diff --git a/arch/arm/mach-tegra/nvrm/core/common/nvrm_clocks_limits.c b/arch/arm/mach-tegra/nvrm/core/common/nvrm_clocks_limits.c
index c6be024d198b..08e93fb28841 100644
--- a/arch/arm/mach-tegra/nvrm/core/common/nvrm_clocks_limits.c
+++ b/arch/arm/mach-tegra/nvrm/core/common/nvrm_clocks_limits.c
@@ -27,7 +27,7 @@
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
- * *
+ *
*/
#include "nvcommon.h"
@@ -95,6 +95,7 @@ NvRmBootArgChipShmooGet(
NvRmDeviceHandle hRmDevice,
NvRmChipFlavor* pChipFlavor);
+static void NvRmPrivChipFlavorInit(NvRmDeviceHandle hRmDevice);
static void NvRmPrivChipFlavorInit(NvRmDeviceHandle hRmDevice)
{
NvOsMemset((void*)&s_ChipFlavor, 0, sizeof(s_ChipFlavor));
@@ -431,7 +432,7 @@ NvRmPrivModuleVscaleAttach(
// enabled || if clock still enabled => if enabled)
NV_ASSERT(pCinfo->ClkEnableOffset);
reg = NV_REGR(hRmDevice, NvRmPrivModuleID_ClockAndReset, 0,
- pCinfo->ClkEnableOffset);
+ pCinfo->ClkEnableOffset);
Enabled = ((reg & pCinfo->ClkEnableField) == pCinfo->ClkEnableField);
if (Enabled)
return VoltageRequirement;
@@ -540,7 +541,7 @@ NvRmPrivModuleVscaleReAttach(
{
NV_ASSERT(pCinfo->ClkEnableOffset);
reg = NV_REGR(hRmDevice, NvRmPrivModuleID_ClockAndReset, 0,
- pCinfo->ClkEnableOffset);
+ pCinfo->ClkEnableOffset);
if ((reg & pCinfo->ClkEnableField) == pCinfo->ClkEnableField)
{
NV_ASSERT(s_VoltageStepRefCounts[pCstate->Vstep]);
@@ -582,7 +583,8 @@ NvRmPrivModuleSetScalingAttribute(
}
// Memory controller scale is specified separately on ODM layer, as
- // it is board dependent; PMU transport must work at any volatge - no
+ // it is board dependent; TVDAC scaling always follow CVE (TV) or
+ // display (CRT); PMU transport must work at any volatge - no
// v-scale attribute for these modules
switch (pCinfo->Module)
{
@@ -591,6 +593,13 @@ NvRmPrivModuleSetScalingAttribute(
case NvRmPrivModuleID_ExternalMemoryController:
pCstate->Vscale = NV_FALSE;
return;
+ case NvRmModuleID_Tvo:
+ if (pCinfo->SubClockId == 2)
+ { // TVDAC is TVO subclock 2
+ pCstate->Vscale = NV_FALSE;
+ return;
+ }
+ break;
default:
break;
}
@@ -668,42 +677,88 @@ static NvError NvRmBootArgChipShmooGet(
NvU32 offset, size, TotalSize = 0;
NvBootArgsChipShmoo BootArgSh;
+ NvBootArgsChipShmooPhys BootArgShPhys;
void* pBootShmooData = NULL;
NvRmMemHandle hMem = NULL;
NvError err = NvSuccess;
+ ExecPlatform env;
// Retrieve shmoo data
err = NvOsBootArgGet(NvBootArgKey_ChipShmoo, &BootArgSh, sizeof(BootArgSh));
- if ((err != NvSuccess) || (BootArgSh.MemHandleKey == 0))
+ if (err != NvSuccess)
{
err = NvError_BadParameter;
goto fail;
}
- err = NvRmMemHandleClaimPreservedHandle(
- hRmDevice, BootArgSh.MemHandleKey, &hMem);
- if (err != NvSuccess)
- {
- goto fail;
- }
- TotalSize = NvRmMemGetSize(hMem);
- NV_ASSERT(TotalSize);
- err = NvRmMemMap(hMem, 0, TotalSize, NVOS_MEM_READ, &pBootShmooData);
- if( err != NvSuccess )
+ if (BootArgSh.MemHandleKey != 0)
{
- goto fail;
- }
+ err = NvRmMemHandleClaimPreservedHandle(
+ hRmDevice, BootArgSh.MemHandleKey, &hMem);
+ if (err != NvSuccess)
+ {
+ goto fail;
+ }
+
+ TotalSize = NvRmMemGetSize(hMem);
+ NV_ASSERT(TotalSize);
+ err = NvRmMemMap(hMem, 0, TotalSize, NVOS_MEM_READ, &pBootShmooData);
+ if( err != NvSuccess )
+ {
+ goto fail;
+ }
- // Use OS memory to keep shmoo data, and release carveout buffer
- s_pShmooData = NvOsAlloc(TotalSize);
- if (!s_pShmooData)
+ // Use OS memory to keep shmoo data, and release carveout buffer
+ s_pShmooData = NvOsAlloc(TotalSize);
+ if (!s_pShmooData)
+ {
+ err = NvError_InsufficientMemory;
+ goto fail;
+ }
+ NvOsMemcpy(s_pShmooData, pBootShmooData, TotalSize);
+ NvRmMemUnmap(hMem, pBootShmooData, TotalSize);
+ NvRmMemHandleFree(hMem);
+ }
+ else
{
- err = NvError_InsufficientMemory;
- goto fail;
+ env = NvRmPrivGetExecPlatform(hRmDevice);
+ if (env != ExecPlatform_Fpga)
+ {
+ err = NvError_BadParameter;
+ goto fail;
+ }
+
+ err = NvOsBootArgGet(NvBootArgKey_ChipShmooPhys, &BootArgShPhys, sizeof(BootArgShPhys));
+ if ((err != NvSuccess) || (BootArgShPhys.PhysShmooPtr == 0))
+ {
+ err = NvError_BadParameter;
+ goto fail;
+ }
+
+ TotalSize = BootArgShPhys.Size;
+ NV_ASSERT(TotalSize);
+
+ // Use OS memory to keep shmoo data
+ s_pShmooData = NvOsAlloc(TotalSize);
+ if (!s_pShmooData)
+ {
+ err = NvError_InsufficientMemory;
+ goto fail;
+ }
+
+ // Map the physical shmoo address passed by the backdoor loader
+ err = NvOsPhysicalMemMap(BootArgShPhys.PhysShmooPtr, TotalSize,
+ NvOsMemAttribute_WriteBack, 0, &pBootShmooData);
+ if (err != NvSuccess)
+ {
+ goto fail;
+ }
+
+ // Copy the shmoo data and unmap the backdoor shmoo pointer.
+ NvOsMemcpy(s_pShmooData, pBootShmooData, TotalSize);
+ NvOsPhysicalMemUnmap(pBootShmooData, TotalSize);
+ pBootShmooData = NULL;
}
- NvOsMemcpy(s_pShmooData, pBootShmooData, TotalSize);
- NvRmMemUnmap(hMem, pBootShmooData, TotalSize);
- NvRmMemHandleFree(hMem);
// Fill in shmoo data records
pChipFlavor->sku = hRmDevice->ChipId.SKU;