index 8de03f6ce1bf075709ead16ebce57cac01ceb4cb..d7ce8289d98028ca026e7bbf8890cb85437fc549 100644 (file)
**********************************************************************************
* 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,139 @@ 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 silicon 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;
+ /* 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 25MHz, 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);
+
}
- /* Enable the pll even if the lock failed. Return a warning. */
- if (i == 100)
- ret = -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);
- /* 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 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);
- /* 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);
-
- /* 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;
- }
+ 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;
+ }
+
+ if (i == 100)
+ ret = -1;
+
+ /* Wait for a minimum of 7 us*/
+ hw_pll_delay (14006);
+
+ /* Release PLL from Reset */
+ ctl = ctl & ~(PLL_REG_CTL_FIELD_PLLRST);
+ DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl);
- /* Enable the pll even if the lock failed. Return a warning. */
- if (i == 100)
- ret = -1;
+ /* Wait for PLL Lock time (min 50 us) */
+ hw_pll_delay (140056 >> 1);
- /* Clear the secondary controller bypass bit */
- secctl = secctl & ~PLL_REG_SECCTL_FIELD_BYPASS;
- DEVICE_REG32_W (pllBase + PLL_REG_SECCTL, secctl);
+ /* 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);
+ /* 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 */