diff options
Diffstat (limited to 'arch/arm/mach-tegra/nvrm/core/ap15/ap15rm_clocks.c')
-rw-r--r-- | arch/arm/mach-tegra/nvrm/core/ap15/ap15rm_clocks.c | 924 |
1 files changed, 924 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/nvrm/core/ap15/ap15rm_clocks.c b/arch/arm/mach-tegra/nvrm/core/ap15/ap15rm_clocks.c new file mode 100644 index 000000000000..8c428b93f85a --- /dev/null +++ b/arch/arm/mach-tegra/nvrm/core/ap15/ap15rm_clocks.c @@ -0,0 +1,924 @@ +/* + * Copyright (c) 2007-2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * 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" +#include "nvassert.h" +#include "nvrm_clocks.h" +#include "nvrm_hwintf.h" +#include "nvrm_module.h" +#include "nvrm_drf.h" +#include "ap15/aremc.h" +#include "ap15/arclk_rst.h" +#include "ap15/arapbpm.h" +#include "ap16/arapb_misc.h" +#include "ap15rm_clocks.h" +#include "ap15rm_private.h" + + + +/*****************************************************************************/ + +static void NvRmPrivWaitUS( + NvRmDeviceHandle hDevice, + NvU32 usec) +{ + NvU32 t, start; + + start = NV_REGR(hDevice, NvRmModuleID_TimerUs, 0, 0); + for (;;) + { + t = NV_REGR(hDevice, NvRmModuleID_TimerUs, 0, 0); + if ( ((NvU32)(t - start)) >= usec ) + break; + } +} + +#define CLOCK_ENABLE( rm, offset, field, EnableState ) \ + do { \ + regaddr = (CLK_RST_CONTROLLER_##offset##_0); \ + NvOsMutexLock((rm)->CarMutex); \ + reg = NV_REGR((rm), NvRmPrivModuleID_ClockAndReset, 0, regaddr); \ + reg = NV_FLD_SET_DRF_NUM(CLK_RST_CONTROLLER, offset, field, EnableState, reg); \ + NV_REGW((rm), NvRmPrivModuleID_ClockAndReset, 0, regaddr, reg); \ + NvOsMutexUnlock((rm)->CarMutex); \ + } while( 0 ) + +/*****************************************************************************/ +void +Ap15EnableModuleClock( + NvRmDeviceHandle hDevice, + NvRmModuleID ModuleId, + ModuleClockState ClockState) +{ + // Extract module and instance from composite module id. + NvU32 Module = NVRM_MODULE_ID_MODULE( ModuleId ); + NvU32 Instance = NVRM_MODULE_ID_INSTANCE( ModuleId ); + NvU32 reg; + NvU32 regaddr; + + if (ClockState == ModuleClockState_Enable) + { + NvRmPrivConfigureClockSource(hDevice, ModuleId, NV_TRUE); + } + + switch ( Module ) { + case NvRmModuleID_CacheMemCtrl: + NV_ASSERT( Instance < 2 ); + if( Instance == 0 ) + { + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_CACHE1, ClockState ); + } + else if( Instance == 1 ) + { + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_CACHE2, ClockState ); + } + break; + case NvRmModuleID_Vcp: + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_VCP, ClockState ); + break; + case NvRmModuleID_GraphicsHost: + // FIXME: should this be allowed? + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_HOST1X, ClockState ); + break; + case NvRmModuleID_Display: + NV_ASSERT( Instance < 2 ); + if( Instance == 0 ) + { + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_DISP1, ClockState ); + } + else if( Instance == 1 ) + { + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_DISP2, ClockState ); + } + break; + case NvRmModuleID_Ide: + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_IDE, ClockState ); + break; + case NvRmModuleID_3D: + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_3D, ClockState ); + break; + case NvRmModuleID_Isp: + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_ISP, ClockState ); + break; + case NvRmModuleID_Usb2Otg: + NV_ASSERT( Instance < 2 ); + if ((hDevice->ChipId.Id == 0x16) && (ClockState == NV_FALSE)) + { + NvU32 RegVal = 0; + // On AP16 USB clock source is shared for both USB controllers + // Disabling the main clock source will disable both controllers + // when disabling the clock make sure that both controllers are disabled. + RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0, APB_MISC_PP_MISC_USB_CLK_RST_CTL_0); + + if (!(NV_DRF_VAL(APB_MISC_PP, MISC_USB_CLK_RST_CTL, MISC_USB_CE, RegVal)) && + !(NV_DRF_VAL(APB_MISC_PP, MISC_USB_CLK_RST_CTL, MISC_USB2_CE, RegVal)) ) + { + /// Disable USBD clock for both the instances 0 and 1 + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_USBD, ClockState ); + } + } + else + { + /// Enable/Disable USBD clock + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_USBD, ClockState ); + } + break; + case NvRmModuleID_2D: + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_2D, ClockState ); + break; + case NvRmModuleID_Epp: + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_EPP, ClockState ); + break; + case NvRmModuleID_Vi: + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_VI, ClockState ); + break; + case NvRmModuleID_I2s: + NV_ASSERT( Instance < 2 ); + if( Instance == 0 ) + { + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_I2S1, ClockState ); + } + else if( Instance == 1 ) + { + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_I2S2, ClockState ); + } + break; + case NvRmModuleID_Hsmmc: + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_HSMMC, ClockState ); + break; + case NvRmModuleID_Twc: + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_TWC, ClockState ); + break; + case NvRmModuleID_Pwm: + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_PWM, ClockState ); + break; + case NvRmModuleID_Sdio: + NV_ASSERT( Instance < 2 ); + if( Instance == 0 ) + { + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_SDIO1, ClockState ); + } + else if( Instance == 1 ) + { + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_SDIO2, ClockState ); + } + break; + case NvRmModuleID_Spdif: + NV_ASSERT( Instance < 1 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_SPDIF, ClockState ); + break; + case NvRmModuleID_Nand: + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_NDFLASH, ClockState ); + break; + case NvRmModuleID_I2c: + NV_ASSERT( Instance < 2 ); + if( Instance == 0 ) + { + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_I2C1, ClockState ); + } + else if( Instance == 1 ) + { + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_H, CLK_ENB_I2C2, ClockState ); + } + break; + case NvRmPrivModuleID_Gpio: + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_GPIO, ClockState ); + break; + case NvRmModuleID_Uart: + NV_ASSERT( Instance < 3 ); + if( Instance == 0 ) + { + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_UARTA, ClockState ); + } + else if( Instance == 1 ) + { + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_UARTB, ClockState ); + } + else if ( Instance == 2) + { + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_H, CLK_ENB_UARTC, ClockState ); + } + break; + case NvRmModuleID_Vfir: + // Same as UARTB + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_UARTB, ClockState ); + break; + case NvRmModuleID_Ac97: + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_AC97, ClockState ); + break; + case NvRmModuleID_Rtc: + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_RTC, ClockState ); + break; + case NvRmModuleID_Timer: + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_TMR, ClockState ); + break; + case NvRmModuleID_BseA: + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_H, CLK_ENB_BSEA, ClockState ); + break; + case NvRmModuleID_Vde: + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_H, CLK_ENB_VDE, ClockState ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_H, CLK_ENB_BSEV, ClockState ); + break; + case NvRmModuleID_Mpe: + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_H, CLK_ENB_MPE, ClockState ); + break; + case NvRmModuleID_Tvo: + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_H, CLK_ENB_TVO, ClockState ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_H, CLK_ENB_TVDAC, ClockState ); + break; + case NvRmModuleID_Csi: + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_H, CLK_ENB_CSI, ClockState ); + break; + case NvRmModuleID_Hdmi: + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_H, CLK_ENB_HDMI, ClockState ); + break; + case NvRmModuleID_Mipi: + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_H, CLK_ENB_MIPI, ClockState ); + break; + case NvRmModuleID_Dsi: + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_H, CLK_ENB_DSI, ClockState ); + break; + case NvRmModuleID_Xio: + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_H, CLK_ENB_XIO, ClockState ); + break; + case NvRmModuleID_Spi: + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_H, CLK_ENB_SPI1, ClockState ); + break; + case NvRmModuleID_Fuse: + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_H, CLK_ENB_FUSE, ClockState ); + break; + case NvRmModuleID_Slink: + // Supporting only the slink controller. + NV_ASSERT( Instance < 3 ); + if( Instance == 0 ) + { + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_H, CLK_ENB_SBC1, ClockState ); + } + else if( Instance == 1 ) + { + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_H, CLK_ENB_SBC2, ClockState ); + } + else if ( Instance == 2) + { + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_H, CLK_ENB_SBC3, ClockState ); + } + break; + case NvRmModuleID_Dvc: + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_H, CLK_ENB_DVC_I2C, ClockState ); + break; + case NvRmModuleID_Pmif: + NV_ASSERT( Instance == 0 ); + // PMC clock must not be disabled + if (ClockState == ModuleClockState_Enable) + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_H, CLK_ENB_PMC, ClockState ); + break; + case NvRmModuleID_SysStatMonitor: + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_H, CLK_ENB_STAT_MON, ClockState ); + break; + case NvRmModuleID_Kbc: + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_H, CLK_ENB_KBC, ClockState ); + break; + case NvRmPrivModuleID_ApbDma: + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_H, CLK_ENB_APBDMA, ClockState ); + break; + case NvRmPrivModuleID_MemoryController: + // FIXME: should this be allowed? + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_H, CLK_ENB_MEM, ClockState ); + break; + case NvRmPrivModuleID_ExternalMemoryController: + // FIXME: should this be allowed? + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_H, CLK_ENB_EMC, ClockState ); + CLOCK_ENABLE( hDevice, CLK_SOURCE_EMC, EMC_2X_CLK_ENB, ClockState ); + CLOCK_ENABLE( hDevice, CLK_SOURCE_EMC, EMC_1X_CLK_ENB, ClockState ); + break; + case NvRmModuleID_Cpu: + // FIXME: should this be allowed? + NV_ASSERT( Instance == 0 ); + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_L, CLK_ENB_CPU, ClockState ); + break; + default: + NV_ASSERT(!" Unknown NvRmModuleID passed to Ap15EnableModuleClock(). "); + } + + if (ClockState == ModuleClockState_Disable) + { + NvRmPrivConfigureClockSource(hDevice, ModuleId, NV_FALSE); + } +} + +void +Ap15EnableTvDacClock( + NvRmDeviceHandle hDevice, + ModuleClockState ClockState) +{ + NvU32 reg; + NvU32 regaddr; + + CLOCK_ENABLE( hDevice, CLK_OUT_ENB_H, CLK_ENB_TVDAC, ClockState ); +} + +/*****************************************************************************/ + + // Note that VDE has different reset sequence requirement + // FIMXE: NV blocks - hot reset issues + #define RESET( rm, offset, field, delay ) \ + do { \ + regaddr = (CLK_RST_CONTROLLER_##offset##_0); \ + NvOsMutexLock((rm)->CarMutex); \ + reg = NV_REGR((rm), NvRmPrivModuleID_ClockAndReset, 0, regaddr); \ + reg = NV_FLD_SET_DRF_NUM( \ + CLK_RST_CONTROLLER, offset, field, 1, reg); \ + NV_REGW((rm), NvRmPrivModuleID_ClockAndReset, 0, regaddr, reg); \ + if (Hold) \ + {\ + NvOsMutexUnlock((rm)->CarMutex); \ + break; \ + }\ + NvRmPrivWaitUS( (rm), (delay) ); \ + reg = NV_FLD_SET_DRF_NUM( \ + CLK_RST_CONTROLLER, offset, field, 0, reg); \ + NV_REGW((rm), NvRmPrivModuleID_ClockAndReset, 0, regaddr, reg); \ + NvOsMutexUnlock((rm)->CarMutex); \ + } while( 0 ) + +// KBC reset is available in the pmc control register. +#define RESET_KBC( rm, delay ) \ + do { \ + regaddr = (APBDEV_PMC_CNTRL_0); \ + NvOsMutexLock((rm)->CarMutex); \ + reg = NV_REGR((rm), NvRmModuleID_Pmif, 0, regaddr); \ + reg = NV_FLD_SET_DRF_DEF(APBDEV_PMC, CNTRL, KBC_RST, ENABLE, reg); \ + NV_REGW((rm), NvRmModuleID_Pmif, 0, regaddr, reg); \ + if (Hold) \ + {\ + NvOsMutexUnlock((rm)->CarMutex); \ + break; \ + }\ + NvRmPrivWaitUS( (rm), (delay) ); \ + reg = NV_FLD_SET_DRF_DEF(APBDEV_PMC, CNTRL, KBC_RST, DISABLE, reg); \ + NV_REGW((rm), NvRmModuleID_Pmif, 0, regaddr, reg); \ + NvOsMutexUnlock((rm)->CarMutex); \ + } while( 0 ) + + +// Use PMC control to reset the entire SoC. Just wait forever after reset is +// issued - h/w would auto-clear it and restart SoC +#define RESET_SOC( rm ) \ + do { \ + regaddr = (APBDEV_PMC_CNTRL_0); \ + reg = NV_REGR((rm), NvRmModuleID_Pmif, 0, regaddr); \ + reg = NV_FLD_SET_DRF_DEF(APBDEV_PMC, CNTRL, MAIN_RST, ENABLE, reg); \ + NV_REGW((rm), NvRmModuleID_Pmif, 0, regaddr, reg); \ + for (;;) ; \ + } while( 0 ) + + +void AP15ModuleReset( + NvRmDeviceHandle hDevice, + NvRmModuleID ModuleId, + NvBool Hold) +{ + // Extract module and instance from composite module id. + NvU32 Module = NVRM_MODULE_ID_MODULE( ModuleId ); + NvU32 Instance = NVRM_MODULE_ID_INSTANCE( ModuleId ); + NvU32 reg; + NvU32 regaddr; + + switch( Module ) { + case NvRmPrivModuleID_MemoryController: + // FIXME: should this be allowed? + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_H, SWR_MEM_RST, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_Kbc: + NV_ASSERT( Instance == 0 ); + RESET_KBC(hDevice, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_SysStatMonitor: + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_H, SWR_STAT_MON_RST, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_Pmif: + NV_ASSERT( Instance == 0 ); + NV_ASSERT(!"PMC reset is not allowed, and does nothing on AP15"); + // RESET( hDevice, RST_DEVICES_H, SWR_PMC_RST, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_Fuse: + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_H, SWR_FUSE_RST, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_Slink: + // Supporting only the slink controller. + NV_ASSERT( Instance < 3 ); + if( Instance == 0 ) + { + RESET( hDevice, RST_DEVICES_H, SWR_SBC1_RST, NVRM_RESET_DELAY ); + } + else if( Instance == 1 ) + { + RESET( hDevice, RST_DEVICES_H, SWR_SBC2_RST, NVRM_RESET_DELAY ); + } + else if ( Instance == 2) + { + RESET( hDevice, RST_DEVICES_H, SWR_SBC3_RST, NVRM_RESET_DELAY ); + } + break; + case NvRmModuleID_Spi: + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_H, SWR_SPI1_RST, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_Xio: + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_H, SWR_XIO_RST, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_Dvc: + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_H, SWR_DVC_I2C_RST, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_Dsi: + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_H, SWR_DSI_RST, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_Tvo: + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_H, SWR_TVO_RST, NVRM_RESET_DELAY ); + RESET( hDevice, RST_DEVICES_H, SWR_TVDAC_RST, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_Mipi: + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_H, SWR_MIPI_RST, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_Hdmi: + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_H, SWR_HDMI_RST, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_Csi: + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_H, SWR_CSI_RST, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_I2c: + NV_ASSERT( Instance < 2 ); + if( Instance == 0 ) + { + RESET( hDevice, RST_DEVICES_L, SWR_I2C1_RST, NVRM_RESET_DELAY ); + } + else if( Instance == 1 ) + { + RESET( hDevice, RST_DEVICES_H, SWR_I2C2_RST, NVRM_RESET_DELAY ); + } + break; + case NvRmModuleID_Mpe: + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_H, SWR_MPE_RST, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_Vde: + NV_ASSERT( Instance == 0 ); + { + NvU32 reg; + NvOsMutexLock(hDevice->CarMutex); + reg = NV_REGR(hDevice, NvRmPrivModuleID_ClockAndReset, 0, + CLK_RST_CONTROLLER_RST_DEVICES_H_0); + reg = NV_FLD_SET_DRF_NUM(CLK_RST_CONTROLLER, RST_DEVICES_H, + SWR_VDE_RST, 1, reg); + NV_REGW(hDevice, NvRmPrivModuleID_ClockAndReset, 0, + CLK_RST_CONTROLLER_RST_DEVICES_H_0, reg); + reg = NV_FLD_SET_DRF_NUM(CLK_RST_CONTROLLER, RST_DEVICES_H, + SWR_BSEV_RST, 1, reg); + NV_REGW(hDevice, NvRmPrivModuleID_ClockAndReset, 0, + CLK_RST_CONTROLLER_RST_DEVICES_H_0, reg); + if (Hold) + { + NvOsMutexUnlock(hDevice->CarMutex); + break; + } + NvRmPrivWaitUS( hDevice, NVRM_RESET_DELAY ); + reg = NV_FLD_SET_DRF_NUM(CLK_RST_CONTROLLER, RST_DEVICES_H, + SWR_BSEV_RST, 0, reg); + NV_REGW(hDevice, NvRmPrivModuleID_ClockAndReset, 0, + CLK_RST_CONTROLLER_RST_DEVICES_H_0, reg); + reg = NV_FLD_SET_DRF_NUM(CLK_RST_CONTROLLER, RST_DEVICES_H, + SWR_VDE_RST, 0, reg); + NV_REGW(hDevice, NvRmPrivModuleID_ClockAndReset, 0, + CLK_RST_CONTROLLER_RST_DEVICES_H_0, reg); + NvOsMutexUnlock(hDevice->CarMutex); + } + break; + case NvRmModuleID_BseA: + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_H, SWR_BSEA_RST, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_Cpu: + // FIXME: should this be allowed? + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_L, SWR_CPU_RST, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_Avp: + // FIXME: should this be allowed? + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_L, SWR_COP_RST, NVRM_RESET_DELAY ); + break; + case NvRmPrivModuleID_System: + // THIS WILL DO A FULL SYSTEM RESET + NV_ASSERT( Instance == 0 ); + RESET_SOC(hDevice); + break; + case NvRmModuleID_Ac97: + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_L, SWR_AC97_RST, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_Rtc: + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_L, SWR_RTC_RST, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_Timer: + NV_ASSERT( Instance == 0 ); + // Timer reset (which also affects microsecond timer) is not allowed + // RESET( hDevice, RST_DEVICES_L, SWR_TMR_RST, NVRM_RESET_DELAY ); + NV_ASSERT(!"Timer reset is not allowed"); + break; + case NvRmModuleID_Uart: + NV_ASSERT( Instance < 3 ); + if( Instance == 0 ) + { + RESET( hDevice, RST_DEVICES_L, SWR_UARTA_RST, NVRM_RESET_DELAY ); + } + else if( Instance == 1 ) + { + RESET( hDevice, RST_DEVICES_L, SWR_UARTB_RST, NVRM_RESET_DELAY ); + } + else if ( Instance == 2) + { + RESET( hDevice, RST_DEVICES_H, SWR_UARTC_RST, NVRM_RESET_DELAY ); + } + break; + case NvRmModuleID_Vfir: + // Same as UARTB + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_L, SWR_UARTB_RST, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_Sdio: + NV_ASSERT( Instance < 2 ); + if( Instance == 0 ) + { + RESET( hDevice, RST_DEVICES_L, SWR_SDIO1_RST, NVRM_RESET_DELAY ); + } + else if( Instance == 1 ) + { + RESET( hDevice, RST_DEVICES_L, SWR_SDIO2_RST, NVRM_RESET_DELAY ); + } + break; + case NvRmModuleID_Spdif: + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_L, SWR_SPDIF_RST, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_I2s: + NV_ASSERT( Instance < 2 ); + if( Instance == 0 ) + { + RESET( hDevice, RST_DEVICES_L, SWR_I2S1_RST, NVRM_RESET_DELAY ); + } + else if( Instance == 1 ) + { + RESET( hDevice, RST_DEVICES_L, SWR_I2S2_RST, NVRM_RESET_DELAY ); + } + break; + case NvRmModuleID_Nand: + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_L, SWR_NDFLASH_RST, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_Hsmmc: + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_L, SWR_HSMMC_RST, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_Twc: + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_L, SWR_TWC_RST, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_Pwm: + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_L, SWR_PWM_RST, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_Epp: + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_L, SWR_EPP_RST, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_Vi: + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_L, SWR_VI_RST, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_3D: + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_L, SWR_3D_RST, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_2D: + NV_ASSERT( Instance == 0 ); + // RESET( hDevice, RST_DEVICES_L, SWR_2D_RST, NVRM_RESET_DELAY ); + // WAR for bug 364497, se also NvRmPrivAP15Reset2D() + NV_ASSERT(!"2D reset after RM open is no longer allowed"); + break; + case NvRmModuleID_Usb2Otg: + { +#if !NV_OAL + NvU32 RegVal = 0; + NV_ASSERT( Instance < 2 ); + if (hDevice->ChipId.Id == 0x16) + { + RegVal = NV_REGR(hDevice, NvRmModuleID_Misc, 0, APB_MISC_PP_MISC_USB_CLK_RST_CTL_0); + if (!(NV_DRF_VAL(APB_MISC_PP, MISC_USB_CLK_RST_CTL, MISC_USB_CE, RegVal)) && + !(NV_DRF_VAL(APB_MISC_PP, MISC_USB_CLK_RST_CTL, MISC_USB2_CE, RegVal)) ) + { + /// Reset USBD if USB1/USB2 is not enabled already + RESET( hDevice, RST_DEVICES_L, SWR_USBD_RST, NVRM_RESET_DELAY ); + } + } + else + { + /// Reset USBD + RESET( hDevice, RST_DEVICES_L, SWR_USBD_RST, NVRM_RESET_DELAY ); + } +#else + /// Reset USBD + RESET( hDevice, RST_DEVICES_L, SWR_USBD_RST, NVRM_RESET_DELAY ); +#endif + } + break; + case NvRmModuleID_Isp: + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_L, SWR_ISP_RST, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_Ide: + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_L, SWR_IDE_RST, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_Display: + NV_ASSERT( Instance < 2 ); + if( Instance == 0 ) + { + RESET( hDevice, RST_DEVICES_L, SWR_DISP1_RST, NVRM_RESET_DELAY ); + } + else if( Instance == 1 ) + { + RESET( hDevice, RST_DEVICES_L, SWR_DISP2_RST, NVRM_RESET_DELAY ); + } + break; + case NvRmModuleID_Vcp: + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_L, SWR_VCP_RST, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_CacheMemCtrl: + NV_ASSERT( Instance < 2 ); + if( Instance == 0 ) + { + RESET( hDevice, RST_DEVICES_L, SWR_CACHE1_RST, NVRM_RESET_DELAY ); + } + else if( Instance == 1 ) + { + RESET( hDevice, RST_DEVICES_L, SWR_CACHE2_RST, NVRM_RESET_DELAY ); + } + break; + case NvRmPrivModuleID_ApbDma: + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_H, SWR_APBDMA_RST, NVRM_RESET_DELAY ); + break; + case NvRmPrivModuleID_Gpio: + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_L, SWR_GPIO_RST, NVRM_RESET_DELAY ); + break; + case NvRmModuleID_GraphicsHost: + // FIXME: should this be allowed? + NV_ASSERT( Instance == 0 ); + RESET( hDevice, RST_DEVICES_L, SWR_HOST1X_RST, NVRM_RESET_DELAY ); + break; + default: + NV_ASSERT(!"Invalid ModuleId"); + } + + #undef RESET +} + +/*****************************************************************************/ + +void +NvRmPrivAp15Reset2D(NvRmDeviceHandle hRmDevice) +{ +#if !NV_OAL + NvU32 reg, offset; + /* + * WAR for bug 364497: 2D can not be taken out of reset if VI clock is + * running. Therefore, make sure VI clock is disabled and reset 2D here + * during RM initialization. + */ + Ap15EnableModuleClock(hRmDevice, NvRmModuleID_Vi, ModuleClockState_Disable); + + // Assert reset to 2D module + offset = CLK_RST_CONTROLLER_RST_DEVICES_L_0; + reg = NV_REGR(hRmDevice, NvRmPrivModuleID_ClockAndReset, 0, offset); + reg = NV_FLD_SET_DRF_DEF( + CLK_RST_CONTROLLER, RST_DEVICES_L, SWR_2D_RST, ENABLE, reg); + NV_REGW(hRmDevice, NvRmPrivModuleID_ClockAndReset, 0, offset, reg); + + // Enable "known good" configuartion for 2D clock (PLLM divided by 2) + offset = CLK_RST_CONTROLLER_CLK_SOURCE_G2D_0; + NV_REGW(hRmDevice, NvRmPrivModuleID_ClockAndReset, 0, offset, + (NV_DRF_NUM(CLK_RST_CONTROLLER, CLK_SOURCE_G2D, G2D_CLK_DIVISOR, 2) | + NV_DRF_DEF(CLK_RST_CONTROLLER, CLK_SOURCE_G2D, G2D_CLK_SRC, PLLM_OUT0))); + Ap15EnableModuleClock(hRmDevice, NvRmModuleID_2D, ModuleClockState_Enable); + NvOsWaitUS(NVRM_RESET_DELAY); + + // Take 2D out of reset and disable 2D clock. Both VI and 2D clocks are + // left disabled -it is up to the resepctive drivers to configure and enable + // them later. + offset = CLK_RST_CONTROLLER_RST_DEVICES_L_0; + reg = NV_FLD_SET_DRF_DEF( + CLK_RST_CONTROLLER, RST_DEVICES_L, SWR_2D_RST, DISABLE, reg); + NV_REGW(hRmDevice, NvRmPrivModuleID_ClockAndReset, 0, offset, reg); + Ap15EnableModuleClock(hRmDevice, NvRmModuleID_2D, ModuleClockState_Disable); +#endif +} + +void +NvRmPrivAp15ClockConfigEx( + NvRmDeviceHandle hDevice, + NvRmModuleID Module, + NvU32 ClkSourceOffset, + NvU32 flags) +{ + NvU32 reg; + + if ((Module == NvRmModuleID_Vi) && + (!(flags & NvRmClockConfig_SubConfig)) && + (flags & (NvRmClockConfig_InternalClockForPads | + NvRmClockConfig_ExternalClockForPads | + NvRmClockConfig_InternalClockForCore | + NvRmClockConfig_ExternalClockForCore))) + { +#ifdef CLK_RST_CONTROLLER_CLK_SOURCE_VI_0_PD2VI_CLK_SEL_FIELD + reg = NV_REGR( + hDevice, NvRmPrivModuleID_ClockAndReset, 0, ClkSourceOffset); + + /* Default is pads use External and Core use internal */ + reg = NV_FLD_SET_DRF_NUM( + CLK_RST_CONTROLLER, CLK_SOURCE_VI, PD2VI_CLK_SEL, 0, reg); + reg = NV_FLD_SET_DRF_NUM( + CLK_RST_CONTROLLER, CLK_SOURCE_VI, VI_CLK_SEL, 0, reg); + + /* This is an invalid setting. */ + NV_ASSERT(!((flags & NvRmClockConfig_InternalClockForPads) && + (flags & NvRmClockConfig_ExternalClockForCore))); + + if (flags & NvRmClockConfig_InternalClockForPads) + reg = NV_FLD_SET_DRF_NUM( + CLK_RST_CONTROLLER, CLK_SOURCE_VI, PD2VI_CLK_SEL, 1, reg); + if (flags & NvRmClockConfig_ExternalClockForCore) + reg = NV_FLD_SET_DRF_NUM( + CLK_RST_CONTROLLER, CLK_SOURCE_VI, VI_CLK_SEL, 1, reg); + + NV_REGW(hDevice, NvRmPrivModuleID_ClockAndReset, 0, + ClkSourceOffset, reg); +#endif + } + if (Module == NvRmModuleID_I2s) + { + reg = NV_REGR( + hDevice, NvRmPrivModuleID_ClockAndReset, 0, ClkSourceOffset); + + if (flags & NvRmClockConfig_ExternalClockForCore) + { + // Set I2S in slave mode (field definition is the same for I2S1 and I2S2) + reg = NV_FLD_SET_DRF_NUM( + CLK_RST_CONTROLLER, CLK_SOURCE_I2S1, I2S1_MASTER_CLKEN, 0, reg); + NV_REGW(hDevice, NvRmPrivModuleID_ClockAndReset, 0, + ClkSourceOffset, reg); + } + else if (flags & NvRmClockConfig_InternalClockForCore) + { + // Set I2S in master mode (field definition is the same for I2S1 and I2S2) + reg = NV_FLD_SET_DRF_NUM( + CLK_RST_CONTROLLER, CLK_SOURCE_I2S1, I2S1_MASTER_CLKEN, 1, reg); + NV_REGW(hDevice, NvRmPrivModuleID_ClockAndReset, 0, + ClkSourceOffset, reg); + } + } +} + +void NvRmPrivAp15SimPllInit(NvRmDeviceHandle hRmDevice) +{ + NvU32 RegData; + + //Enable the plls in simulation. We can just use PLLC as the template + //and replicate across pllM and pllP since the offsets are the same. + RegData = NV_DRF_NUM (CLK_RST_CONTROLLER, PLLC_BASE, PLLC_DIVP, 0) + | NV_DRF_NUM (CLK_RST_CONTROLLER, PLLC_BASE, PLLC_DIVM, 0) + | NV_DRF_NUM (CLK_RST_CONTROLLER, PLLC_BASE, PLLC_DIVN, 0) + | NV_DRF_DEF (CLK_RST_CONTROLLER, PLLC_BASE, PLLC_BYPASS, DISABLE) + | NV_DRF_DEF (CLK_RST_CONTROLLER, PLLC_BASE, PLLC_ENABLE, ENABLE) ; + + NV_REGW(hRmDevice, NvRmPrivModuleID_ClockAndReset, 0, + CLK_RST_CONTROLLER_PLLM_BASE_0, RegData); + NV_REGW(hRmDevice, NvRmPrivModuleID_ClockAndReset, 0, + CLK_RST_CONTROLLER_PLLC_BASE_0, RegData); + NV_REGW(hRmDevice, NvRmPrivModuleID_ClockAndReset, 0, + CLK_RST_CONTROLLER_PLLP_BASE_0, RegData); +} + +NvError +NvRmPrivAp15OscDoublerConfigure( + NvRmDeviceHandle hRmDevice, + NvRmFreqKHz OscKHz) +{ + NvU32 reg, Taps; + NvError error = NvRmPrivGetOscDoublerTaps(hRmDevice, OscKHz, &Taps); + + if (error == NvSuccess) + { + // Program delay + reg = NV_REGR(hRmDevice, NvRmPrivModuleID_ClockAndReset, 0, + CLK_RST_CONTROLLER_PROG_DLY_CLK_0); + reg = NV_FLD_SET_DRF_NUM( + CLK_RST_CONTROLLER, PROG_DLY_CLK, CLK_D_DELCLK_SEL, Taps, reg); + NV_REGW(hRmDevice, NvRmPrivModuleID_ClockAndReset, 0, + CLK_RST_CONTROLLER_PROG_DLY_CLK_0, reg); + // Enable doubler + reg = NV_REGR(hRmDevice, NvRmPrivModuleID_ClockAndReset, 0, + CLK_RST_CONTROLLER_MISC_CLK_ENB_0); + reg = NV_FLD_SET_DRF_NUM( + CLK_RST_CONTROLLER, MISC_CLK_ENB, CLK_M_DOUBLER_ENB, 1, reg); + } + else + { + // Disable doubler + reg = NV_REGR(hRmDevice, NvRmPrivModuleID_ClockAndReset, 0, + CLK_RST_CONTROLLER_MISC_CLK_ENB_0); + reg = NV_FLD_SET_DRF_NUM( + CLK_RST_CONTROLLER, MISC_CLK_ENB, CLK_M_DOUBLER_ENB, 0, reg); + } + NV_REGW(hRmDevice, NvRmPrivModuleID_ClockAndReset, 0, + CLK_RST_CONTROLLER_MISC_CLK_ENB_0, reg); + return error; +} + +/*****************************************************************************/ + |