diff options
author | Gary King <gking@nvidia.com> | 2009-12-23 14:29:17 -0800 |
---|---|---|
committer | Gary King <gking@nvidia.com> | 2009-12-23 17:54:12 -0800 |
commit | 022b97f21665deea09e2303defbc718639d2c04d (patch) | |
tree | 13b74670c77f934bc68915da0917da31053c16c2 | |
parent | c8855f2847834bf9db39940c12a73389da4ad9c6 (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.h | 11 | ||||
-rw-r--r-- | arch/arm/mach-tegra/nvos/nvos.c | 22 | ||||
-rw-r--r-- | arch/arm/mach-tegra/nvrm/core/ap15/nvrm_clocks.c | 39 | ||||
-rw-r--r-- | arch/arm/mach-tegra/nvrm/core/common/nvrm_clocks.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-tegra/nvrm/core/common/nvrm_clocks_limits.c | 105 |
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; |