Path: blob/master/arch/arm/mach-bcmring/csp/chipc/chipcHw_init.c
10820 views
/*****************************************************************************1* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved.2*3* Unless you and Broadcom execute a separate written software license4* agreement governing use of this software, this software is licensed to you5* under the terms of the GNU General Public License version 2, available at6* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").7*8* Notwithstanding the above, under no circumstances may you combine this9* software in any way with any other Broadcom software provided under a10* license other than the GPL, without Broadcom's express prior written11* consent.12*****************************************************************************/1314/****************************************************************************/15/**16* @file chipcHw_init.c17*18* @brief Low level CHIPC PLL configuration functions19*20* @note21*22* These routines provide basic PLL controlling functionality only.23*/24/****************************************************************************/2526/* ---- Include Files ---------------------------------------------------- */2728#include <csp/errno.h>29#include <csp/stdint.h>30#include <csp/module.h>3132#include <mach/csp/chipcHw_def.h>33#include <mach/csp/chipcHw_inline.h>3435#include <csp/reg.h>36#include <csp/delay.h>37/* ---- Private Constants and Types --------------------------------------- */3839/*40Calculation for NDIV_i to obtain VCO frequency41-----------------------------------------------4243Freq_vco = Freq_ref * (P2 / P1) * (PLL_NDIV_i + PLL_NDIV_f)44for Freq_vco = VCO_FREQ_MHz45Freq_ref = chipcHw_XTAL_FREQ_Hz46PLL_P1 = PLL_P2 = 147and48PLL_NDIV_f = 04950We get:51PLL_NDIV_i = Freq_vco / Freq_ref = VCO_FREQ_MHz / chipcHw_XTAL_FREQ_Hz5253Calculation for PLL MDIV to obtain frequency Freq_x for channel x54-----------------------------------------------------------------55Freq_x = chipcHw_XTAL_FREQ_Hz * PLL_NDIV_i / PLL_MDIV_x = VCO_FREQ_MHz / PLL_MDIV_x5657PLL_MDIV_x = VCO_FREQ_MHz / Freq_x58*/5960/* ---- Private Variables ------------------------------------------------- */61/****************************************************************************/62/**63* @brief Initializes the PLL264*65* This function initializes the PLL266*67*/68/****************************************************************************/69void chipcHw_pll2Enable(uint32_t vcoFreqHz)70{71uint32_t pllPreDivider2 = 0;7273{74REG_LOCAL_IRQ_SAVE;75pChipcHw->PLLConfig2 =76chipcHw_REG_PLL_CONFIG_D_RESET |77chipcHw_REG_PLL_CONFIG_A_RESET;7879pllPreDivider2 = chipcHw_REG_PLL_PREDIVIDER_POWER_DOWN |80chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_INTEGER |81(chipcHw_REG_PLL_PREDIVIDER_NDIV_i(vcoFreqHz) <<82chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT) |83(chipcHw_REG_PLL_PREDIVIDER_P1 <<84chipcHw_REG_PLL_PREDIVIDER_P1_SHIFT) |85(chipcHw_REG_PLL_PREDIVIDER_P2 <<86chipcHw_REG_PLL_PREDIVIDER_P2_SHIFT);8788/* Enable CHIPC registers to control the PLL */89pChipcHw->PLLStatus |= chipcHw_REG_PLL_STATUS_CONTROL_ENABLE;9091/* Set pre divider to get desired VCO frequency */92pChipcHw->PLLPreDivider2 = pllPreDivider2;93/* Set NDIV Frac */94pChipcHw->PLLDivider2 = chipcHw_REG_PLL_DIVIDER_NDIV_f;9596/* This has to be removed once the default values are fixed for PLL2. */97pChipcHw->PLLControl12 = 0x38000700;98pChipcHw->PLLControl22 = 0x00000015;99100/* Reset PLL2 */101if (vcoFreqHz > chipcHw_REG_PLL_CONFIG_VCO_SPLIT_FREQ) {102pChipcHw->PLLConfig2 = chipcHw_REG_PLL_CONFIG_D_RESET |103chipcHw_REG_PLL_CONFIG_A_RESET |104chipcHw_REG_PLL_CONFIG_VCO_1601_3200 |105chipcHw_REG_PLL_CONFIG_POWER_DOWN;106} else {107pChipcHw->PLLConfig2 = chipcHw_REG_PLL_CONFIG_D_RESET |108chipcHw_REG_PLL_CONFIG_A_RESET |109chipcHw_REG_PLL_CONFIG_VCO_800_1600 |110chipcHw_REG_PLL_CONFIG_POWER_DOWN;111}112REG_LOCAL_IRQ_RESTORE;113}114115/* Insert certain amount of delay before deasserting ARESET. */116udelay(1);117118{119REG_LOCAL_IRQ_SAVE;120/* Remove analog reset and Power on the PLL */121pChipcHw->PLLConfig2 &=122~(chipcHw_REG_PLL_CONFIG_A_RESET |123chipcHw_REG_PLL_CONFIG_POWER_DOWN);124125REG_LOCAL_IRQ_RESTORE;126127}128129/* Wait until PLL is locked */130while (!(pChipcHw->PLLStatus2 & chipcHw_REG_PLL_STATUS_LOCKED))131;132133{134REG_LOCAL_IRQ_SAVE;135/* Remove digital reset */136pChipcHw->PLLConfig2 &= ~chipcHw_REG_PLL_CONFIG_D_RESET;137138REG_LOCAL_IRQ_RESTORE;139}140}141142EXPORT_SYMBOL(chipcHw_pll2Enable);143144/****************************************************************************/145/**146* @brief Initializes the PLL1147*148* This function initializes the PLL1149*150*/151/****************************************************************************/152void chipcHw_pll1Enable(uint32_t vcoFreqHz, chipcHw_SPREAD_SPECTRUM_e ssSupport)153{154uint32_t pllPreDivider = 0;155156{157REG_LOCAL_IRQ_SAVE;158159pChipcHw->PLLConfig =160chipcHw_REG_PLL_CONFIG_D_RESET |161chipcHw_REG_PLL_CONFIG_A_RESET;162/* Setting VCO frequency */163if (ssSupport == chipcHw_SPREAD_SPECTRUM_ALLOW) {164pllPreDivider =165chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_MASH_1_8 |166((chipcHw_REG_PLL_PREDIVIDER_NDIV_i(vcoFreqHz) -1671) << chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT) |168(chipcHw_REG_PLL_PREDIVIDER_P1 <<169chipcHw_REG_PLL_PREDIVIDER_P1_SHIFT) |170(chipcHw_REG_PLL_PREDIVIDER_P2 <<171chipcHw_REG_PLL_PREDIVIDER_P2_SHIFT);172} else {173pllPreDivider = chipcHw_REG_PLL_PREDIVIDER_POWER_DOWN |174chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_INTEGER |175(chipcHw_REG_PLL_PREDIVIDER_NDIV_i(vcoFreqHz) <<176chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT) |177(chipcHw_REG_PLL_PREDIVIDER_P1 <<178chipcHw_REG_PLL_PREDIVIDER_P1_SHIFT) |179(chipcHw_REG_PLL_PREDIVIDER_P2 <<180chipcHw_REG_PLL_PREDIVIDER_P2_SHIFT);181}182183/* Enable CHIPC registers to control the PLL */184pChipcHw->PLLStatus |= chipcHw_REG_PLL_STATUS_CONTROL_ENABLE;185186/* Set pre divider to get desired VCO frequency */187pChipcHw->PLLPreDivider = pllPreDivider;188/* Set NDIV Frac */189if (ssSupport == chipcHw_SPREAD_SPECTRUM_ALLOW) {190pChipcHw->PLLDivider = chipcHw_REG_PLL_DIVIDER_M1DIV |191chipcHw_REG_PLL_DIVIDER_NDIV_f_SS;192} else {193pChipcHw->PLLDivider = chipcHw_REG_PLL_DIVIDER_M1DIV |194chipcHw_REG_PLL_DIVIDER_NDIV_f;195}196197/* Reset PLL1 */198if (vcoFreqHz > chipcHw_REG_PLL_CONFIG_VCO_SPLIT_FREQ) {199pChipcHw->PLLConfig = chipcHw_REG_PLL_CONFIG_D_RESET |200chipcHw_REG_PLL_CONFIG_A_RESET |201chipcHw_REG_PLL_CONFIG_VCO_1601_3200 |202chipcHw_REG_PLL_CONFIG_POWER_DOWN;203} else {204pChipcHw->PLLConfig = chipcHw_REG_PLL_CONFIG_D_RESET |205chipcHw_REG_PLL_CONFIG_A_RESET |206chipcHw_REG_PLL_CONFIG_VCO_800_1600 |207chipcHw_REG_PLL_CONFIG_POWER_DOWN;208}209210REG_LOCAL_IRQ_RESTORE;211212/* Insert certain amount of delay before deasserting ARESET. */213udelay(1);214215{216REG_LOCAL_IRQ_SAVE;217/* Remove analog reset and Power on the PLL */218pChipcHw->PLLConfig &=219~(chipcHw_REG_PLL_CONFIG_A_RESET |220chipcHw_REG_PLL_CONFIG_POWER_DOWN);221REG_LOCAL_IRQ_RESTORE;222}223224/* Wait until PLL is locked */225while (!(pChipcHw->PLLStatus & chipcHw_REG_PLL_STATUS_LOCKED)226|| !(pChipcHw->227PLLStatus2 & chipcHw_REG_PLL_STATUS_LOCKED))228;229230/* Remove digital reset */231{232REG_LOCAL_IRQ_SAVE;233pChipcHw->PLLConfig &= ~chipcHw_REG_PLL_CONFIG_D_RESET;234REG_LOCAL_IRQ_RESTORE;235}236}237}238239EXPORT_SYMBOL(chipcHw_pll1Enable);240241/****************************************************************************/242/**243* @brief Initializes the chipc module244*245* This function initializes the PLLs and core system clocks246*247*/248/****************************************************************************/249250void chipcHw_Init(chipcHw_INIT_PARAM_t *initParam /* [ IN ] Misc chip initialization parameter */251) {252#if !(defined(__KERNEL__) && !defined(STANDALONE))253delay_init();254#endif255256/* Do not program PLL, when warm reset */257if (!(chipcHw_getStickyBits() & chipcHw_REG_STICKY_CHIP_WARM_RESET)) {258chipcHw_pll1Enable(initParam->pllVcoFreqHz,259initParam->ssSupport);260chipcHw_pll2Enable(initParam->pll2VcoFreqHz);261} else {262/* Clear sticky bits */263chipcHw_clearStickyBits(chipcHw_REG_STICKY_CHIP_WARM_RESET);264}265/* Clear sticky bits */266chipcHw_clearStickyBits(chipcHw_REG_STICKY_CHIP_SOFT_RESET);267268/* Before configuring the ARM clock, atleast we need to make sure BUS clock maintains the proper ratio with ARM clock */269pChipcHw->ACLKClock =270(pChipcHw->271ACLKClock & ~chipcHw_REG_ACLKClock_CLK_DIV_MASK) | (initParam->272armBusRatio &273chipcHw_REG_ACLKClock_CLK_DIV_MASK);274275/* Set various core component frequencies. The order in which this is done is important for some. */276/* The RTBUS (DDR PHY) is derived from the BUS, and the BUS from the ARM, and VPM needs to know BUS */277/* frequency to find its ratio with the BUS. Hence we must set the ARM first, followed by the BUS, */278/* then VPM and RTBUS. */279280chipcHw_setClockFrequency(chipcHw_CLOCK_ARM,281initParam->busClockFreqHz *282initParam->armBusRatio);283chipcHw_setClockFrequency(chipcHw_CLOCK_BUS, initParam->busClockFreqHz);284chipcHw_setClockFrequency(chipcHw_CLOCK_VPM,285initParam->busClockFreqHz *286initParam->vpmBusRatio);287chipcHw_setClockFrequency(chipcHw_CLOCK_DDR,288initParam->busClockFreqHz *289initParam->ddrBusRatio);290chipcHw_setClockFrequency(chipcHw_CLOCK_RTBUS,291initParam->busClockFreqHz / 2);292}293294295