From: Sandeep Paulraj Date: Wed, 2 Nov 2011 21:26:16 +0000 (-0400) Subject: c66x: PLL init code update based on latest review X-Git-Tag: IBL_EXP_11_08~10 X-Git-Url: https://git.ti.com/gitweb?p=keystone-rtos%2Fibl.git;a=commitdiff_plain;h=71dc296cb9006dc7b7163ae40a49f1e0c2d2d536 c66x: PLL init code update based on latest review Signed-off-by: Sandeep Paulraj --- diff --git a/src/hw/plls/pll014phi/pll.c b/src/hw/plls/pll014phi/pll.c index 8de03f6..266af2f 100644 --- a/src/hw/plls/pll014phi/pll.c +++ b/src/hw/plls/pll014phi/pll.c @@ -46,7 +46,6 @@ void hw_pll_delay (UINT32 del) ********************************************************************************** * DESCRIPTION: Sets up the pll **********************************************************************************/ -/* latest Sequence as provided by Tom during 10/27 */ SINT16 hwPllSetPll (UINT32 pllNum, UINT32 prediv, UINT32 mult, UINT32 postdiv) { UINT32 ctl, reg; @@ -88,139 +87,150 @@ SINT16 hwPllSetPll (UINT32 pllNum, UINT32 prediv, UINT32 mult, UINT32 postdiv) if ( (secctl & PLL_REG_SECCTL_FIELD_BYPASS) != 0 ) { /* PLL BYPASS is turned on */ - /* Clear the PLLENSRC bit */ - ctl = ctl & ~(PLL_REG_CTL_FIELD_PLLENSRC); - DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl); - - /* Clear the PLLEN bit */ - ctl = ctl & ~(PLL_REG_CTL_FIELD_PLLEN); - DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl); - - /* Wait for 4 Ref clocks */ - /* The slowest clock can be at 24MHz, so min:160ns delay */ - hw_pll_delay(225); - - /* Put the PLL in Bypass mode to perform the power down mode */ - secctl = secctl | PLL_REG_SECCTL_FIELD_BYPASS; - DEVICE_REG32_W (pllBase + PLL_REG_SECCTL, secctl); - - /* Advisory 8: Multiple PLLs May Not Lock After Power-on Reset Issue * - * In order to ensure proper PLL startup, the PLL power_down pin needs to be * - * toggled. This is accomplished by toggling the PLLPWRDN bit in the PLLCTL * - * register. This needs to be done before the main PLL initialization * - * sequence */ - ctl = ctl | 2; - DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl); - - /* Stay in a loop such that the bit is set for 5 µs (minimum) and * - * then clear the bit. */ - hw_pll_delay (14005); /* waiting 10 us */ - - /* Power up the PLL */ - ctl = ctl & ~2; - DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl); - - /* Set the ENSAT Bit */ - /* Usage Note 9: For optimal PLL operation, the ENSAT bit in the PLL control * - * registers for the Main PLL, DDR3 PLL, and PA PLL should be set to 1. * - * The PLL initialization sequence in the boot ROM sets this bit to 0 and * - * could lead to non-optimal PLL operation. Software can set the bit to the * - * optimal value of 1 after boot */ + /* Set the ENSAT Bit */ + /* Usage Note 9: For optimal PLL operation, the ENSAT bit in the PLL control + * registers for the Main PLL, DDR3 PLL, and PA PLL should be set to 1. + * The PLL initialization sequence in the boot ROM sets this bit to 0 and + * could lead to non-optimal PLL operation. Software can set the bit to the + * optimal value of 1 after boot + */ reg = DEVICE_REG32_R (DEVICE_MAIN_PLL_CTL_1); reg = reg | (1 << 6); DEVICE_REG32_W (DEVICE_MAIN_PLL_CTL_1, reg); - } - /* Program the necessary multipliers/dividers and BW adjustments */ - /* This routine will subtract 1 from the mult value */ - pmult = chipPllExternalMult(pllNum, mult); - pmult = pmult & PLL_REG_PLLM_FIELD_MULTm1; - DEVICE_REG32_W (pllBase + PLL_REG_PLLM, pmult); - - /* Set the PLL Divider */ - chipPllSetExternalPrediv(pllNum, prediv - 1); - - /* set the output divide */ - secctl = BOOT_SET_BITFIELD(secctl, 1 & 0x000f, 22, 19); - DEVICE_REG32_W (pllBase + PLL_REG_SECCTL, secctl); - - /* set the BWADJ */ - chipPllExternalBwAdj (pllNum, mult); - - /* WAIT FOR THE go STAT BIT HERE (50 us) */ - hw_pll_delay (140056 >> 1); - /* wait for the GOSTAT, but don't trap if lock is never read */ - for (i = 0; i < 100; i++) { - hw_pll_delay (300); - status = DEVICE_REG32_R (pllBase + PLL_REG_PLLSTAT); - if ( (status & PLL_REG_STATUS_FIELD_GOSTAT) == 0 ) - break; - } - /* Enable the pll even if the lock failed. Return a warning. */ - if (i == 100) - ret = -1; - - /* Set PLL dividers if needed */ - reg = 0x8000 | (div2 -1); - DEVICE_REG32_W (pllBase + PLL_REG_DIV2, reg); - - reg = 0x8000 | (div5 -1); - DEVICE_REG32_W (pllBase + PLL_REG_DIV5, reg); - - reg = 0x8000 | (div8 -1); - DEVICE_REG32_W (pllBase + PLL_REG_DIV8, reg); - - /* Program ALNCTLn registers */ - alnctl = DEVICE_REG32_R (pllBase + PLL_REG_ALNCTL); - alnctl = alnctl | ((1 << 1) | (1 << 4) | (1 << 7)); - DEVICE_REG32_W (pllBase + PLL_REG_ALNCTL, alnctl); - - /* Set GOSET bit in PLLCMD to initiate the GO operation to change the divide * - * values and align the SYSCLKs as programmed */ - reg = DEVICE_REG32_R (pllBase + PLL_REG_CMD); - reg = reg | 1; - DEVICE_REG32_W (pllBase + PLL_REG_CMD, reg); - - /* wait for the GOSTAT, but don't trap if lock is never read */ - for (i = 0; i < 100; i++) { - hw_pll_delay (300); - status = DEVICE_REG32_R (pllBase + PLL_REG_PLLSTAT); - if ( (status & PLL_REG_STATUS_FIELD_GOSTAT) == 0 ) - break; + /* Clear the PLLENSRC bit */ + ctl = ctl & ~(PLL_REG_CTL_FIELD_PLLENSRC); + DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl); + + /* Clear the PLLEN bit */ + ctl = ctl & ~(PLL_REG_CTL_FIELD_PLLEN); + DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl); + + + /* Wait for 4 Ref clocks */ + /* The slowest clock can be at 24MHz, so min:160ns delay */ + hw_pll_delay(225); + + /* Put the PLL in Bypass mode to perform the power down mode */ + secctl = secctl | PLL_REG_SECCTL_FIELD_BYPASS; + DEVICE_REG32_W (pllBase + PLL_REG_SECCTL, secctl); + + /* Advisory 8: Multiple PLLs May Not Lock After Power-on Reset Issue + * In order to ensure proper PLL startup, the PLL power_down pin needs to be + * toggled. This is accomplished by toggling the PLLPWRDN bit in the PLLCTL + * register. This needs to be done before the main PLL initialization + * sequence + */ + ctl = ctl | 2; + DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl); + + /* Stay in a loop such that the bit is set for 5 µs (minimum) and + * then clear the bit. + */ + hw_pll_delay (14005); /* waiting 10 us */ + + /* Power up the PLL */ + ctl = ctl & ~2; + DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl); + } - /* Wait for the PLL Reset duration time (min: 1000 ns) */ - hw_pll_delay (1400); - - /* Release PLL from Reset */ - ctl = ctl & ~(PLL_REG_CTL_FIELD_PLLRST); - DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl); - - /* Wait for PLL Lock time (min 50 us) */ - hw_pll_delay (140056 >> 1); + /* Assert PLL Reset */ + ctl = ctl | (PLL_REG_CTL_FIELD_PLLRST); + DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl); + + /* Program the necessary multipliers/dividers and BW adjustments + * This routine will subtract 1 from the mult value + */ + pmult = chipPllExternalMult(pllNum, mult); + pmult = pmult & PLL_REG_PLLM_FIELD_MULTm1; + DEVICE_REG32_W (pllBase + PLL_REG_PLLM, pmult); + + /* set the BWADJ */ + chipPllExternalBwAdj (pllNum, mult); + + /* Set the PLL Divider */ + chipPllSetExternalPrediv(pllNum, prediv - 1); + + /* set the output divide */ + secctl = BOOT_SET_BITFIELD(secctl, 1 & 0x000f, 22, 19); + DEVICE_REG32_W (pllBase + PLL_REG_SECCTL, secctl); + + /* WAIT FOR THE go STAT BIT HERE (50 us) */ + hw_pll_delay (140056 >> 1); + /* wait for the GOSTAT, but don't trap if lock is never read */ + for (i = 0; i < 100; i++) { + hw_pll_delay (300); + status = DEVICE_REG32_R (pllBase + PLL_REG_PLLSTAT); + if ( (status & PLL_REG_STATUS_FIELD_GOSTAT) == 0 ) + break; + } + + /* Enable the pll even if the lock failed. Return a warning. */ + if (i == 100) + ret = -1; + + /* Set PLL dividers if needed */ + reg = 0x8000 | (div2 -1); + DEVICE_REG32_W (pllBase + PLL_REG_DIV2, reg); + + reg = 0x8000 | (div5 -1); + DEVICE_REG32_W (pllBase + PLL_REG_DIV5, reg); + + reg = 0x8000 | (div8 -1); + DEVICE_REG32_W (pllBase + PLL_REG_DIV8, reg); + + /* Program ALNCTLn registers */ + alnctl = DEVICE_REG32_R (pllBase + PLL_REG_ALNCTL); + alnctl = alnctl | ((1 << 1) | (1 << 4) | (1 << 7)); + DEVICE_REG32_W (pllBase + PLL_REG_ALNCTL, alnctl); + + /* Set GOSET bit in PLLCMD to initiate the GO operation to change the divide * + * values and align the SYSCLKs as programmed */ + reg = DEVICE_REG32_R (pllBase + PLL_REG_CMD); + reg = reg | 1; + DEVICE_REG32_W (pllBase + PLL_REG_CMD, reg); + + /* wait for the GOSTAT, but don't trap if lock is never read */ + for (i = 0; i < 100; i++) { + hw_pll_delay (300); + status = DEVICE_REG32_R (pllBase + PLL_REG_PLLSTAT); + if ( (status & PLL_REG_STATUS_FIELD_GOSTAT) == 0 ) + break; + } + + /* Wait for 7 us, use 10 us*/ + hw_pll_delay (14006); + + /* Release PLL from Reset */ + ctl = ctl & ~(PLL_REG_CTL_FIELD_PLLRST); + DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl); + + /* Wait for PLL Lock time (min 50 us) */ + hw_pll_delay (140056 >> 1); - /* wait for the pll to lock, but don't trap if lock is never read */ - for (i = 0; i < 100; i++) { - hw_pll_delay (2000/7); - status = DEVICE_REG32_R (pllBase + PLL_REG_PLLSTAT); - if ( (status & PLL_REG_STATUS_FIELD_LOCK) != 0 ) - break; - } - - /* Enable the pll even if the lock failed. Return a warning. */ - if (i == 100) - ret = -1; - - /* Clear the secondary controller bypass bit */ - secctl = secctl & ~PLL_REG_SECCTL_FIELD_BYPASS; - DEVICE_REG32_W (pllBase + PLL_REG_SECCTL, secctl); - - - /* Set pllen to 1 to enable pll mode */ - ctl = ctl | PLL_REG_CTL_FIELD_PLLEN; - DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl); + /* wait for the pll to lock, but don't trap if lock is never read */ + for (i = 0; i < 100; i++) { + hw_pll_delay (2000/7); + status = DEVICE_REG32_R (pllBase + PLL_REG_PLLSTAT); + if ( (status & PLL_REG_STATUS_FIELD_LOCK) != 0 ) + break; + } + + /* Enable the pll even if the lock failed. Return a warning. */ + if (i == 100) + ret = -1; + + /* Clear the secondary controller bypass bit */ + secctl = secctl & ~PLL_REG_SECCTL_FIELD_BYPASS; + DEVICE_REG32_W (pllBase + PLL_REG_SECCTL, secctl); + + + /* Set pllen to 1 to enable pll mode */ + ctl = ctl | PLL_REG_CTL_FIELD_PLLEN; + DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl); - return (ret); + return (ret); } /* hwPllSetPll */