1 /********************************************************************************************************
2 * FILE PURPOSE: Config level PLL driver
3 ********************************************************************************************************
4 * FILE NAME: cfgpll.c
5 *
6 * DESCRIPTION: The boot driver for PLLs that dont have a pll controller, but are controlled
7 * by registers in config space.
8 *
9 * This driver differs from cfgpll! In this file the reset is controlled by
10 * bit 13 in register b, not bit 14!.
11 *
12 *********************************************************************************************************/
13 #include "types.h"
14 #include "target.h"
15 #include "pllapi.h"
17 #define DEVICE_REG32_W(x,y) *(volatile unsigned int *)(x)=(y)
18 #define DEVICE_REG32_R(x) (*(volatile unsigned int *)(x))
20 #define BOOTBITMASK(x,y) ( ( ( ((UINT32)1 << (((UINT32)x)-((UINT32)y)+(UINT32)1) ) - (UINT32)1 ) ) << ((UINT32)y) )
21 #define BOOT_READ_BITFIELD(z,x,y) (((UINT32)z) & BOOTBITMASK(x,y)) >> (y)
22 #define BOOT_SET_BITFIELD(z,f,x,y) (((UINT32)z) & ~BOOTBITMASK(x,y)) | ( (((UINT32)f) << (y)) & BOOTBITMASK(x,y) )
24 #define CHIP_LEVEL_REG 0x02620000
25 #define DDR3PLLCTL0 *(volatile unsigned int*)(CHIP_LEVEL_REG + 0x0330)
26 #define DDR3PLLCTL1 *(volatile unsigned int*)(CHIP_LEVEL_REG + 0x0334)
30 void ddr3_pll_delay (UINT32 del)
31 {
32 UINT32 i;
33 volatile UINT32 j;
35 for (i = j = 0; i < del; i++)
36 asm (" nop ");
38 }
40 /*********************************************************************************************************
41 * FUNCTION PURPOSE: Configure and enable a pll
42 *********************************************************************************************************
43 * DESCRIPTION: The PLL is configured. If the existing configuration matches the requested one no
44 * register write is made.
45 *********************************************************************************************************/
46 SINT16 hwPllSetCfg2Pll (UINT32 base, UINT32 prediv, UINT32 mult, UINT32 postdiv, UINT32 chipFreqMhz, UINT32 pllFreqMhz)
47 {
48 UINT32 reg;
49 UINT32 regb;
50 UINT32 bwAdj;
52 UINT16 currentPrediv;
53 UINT16 currentMult;
54 UINT16 currentPostdiv;
55 UINT16 currentBypass;
56 UINT16 currentBwAdj;
57 UINT16 currentEnable;
59 reg = DEVICE_REG32_R (base);
60 regb = DEVICE_REG32_R (base + 4);
62 currentPrediv = 1 + BOOT_READ_BITFIELD (reg, 5, 0);
63 currentMult = 1 + BOOT_READ_BITFIELD (reg, 18, 6);
64 currentPostdiv = 1 + BOOT_READ_BITFIELD (reg, 22, 19);
65 currentBypass = BOOT_READ_BITFIELD (reg, 23, 23);
66 currentBwAdj = 1 + BOOT_READ_BITFIELD (reg, 31, 24) + ((BOOT_READ_BITFIELD (regb, 3, 0)) << 8);
67 currentEnable = BOOT_READ_BITFIELD(regb, 13, 13);
69 /* The PLL is currently enabled and connected if bypass == 0, enable == 1, clkout == 1 */
71 if ( (currentBypass == 0) &&
72 (currentPrediv == prediv) &&
73 (currentMult == mult) &&
74 (currentPostdiv == postdiv) &&
75 (currentEnable == 0) &&
76 (currentBwAdj == (mult >> 1)) )
77 return (0);
80 /* bwAdj is based only on the mult value */
81 bwAdj = (mult >> 1) - 1;
83 /* Write to the ENSAT bit */
84 regb |= (1 << 6);
85 DEVICE_REG32_W (base + 4, regb);
87 /* Bypass must be enabled */
88 reg |= (1 << 23);
89 DEVICE_REG32_W (base, reg);
91 /* Set bit 13 in register 1 to disable the PLL (assert reset) */
92 regb |= (1 << 13);
93 DEVICE_REG32_W (base + 4, regb);
96 /* Configure PLLM, PPLD BWADJ */
97 reg = BOOT_SET_BITFIELD (reg, prediv - 1, 5, 0);
98 reg = BOOT_SET_BITFIELD (reg, mult - 1, 18, 6);
99 reg = BOOT_SET_BITFIELD (reg, (bwAdj & 0xff), 31, 24);
101 DEVICE_REG32_W (base, reg);
103 /* The 4 MS Bits of BWADJ */
104 regb = BOOT_SET_BITFIELD (regb, (bwAdj >> 8), 3, 0);
105 DEVICE_REG32_W (base + 4, regb);
108 /* Reset must be asserted for at least 5us */
109 ddr3_pll_delay(7000);
112 /* Clear bit 13 in register 1 to re-enable the pll */
113 regb &= ~(1 << 13);
114 DEVICE_REG32_W (base + 4, regb);
116 /* Wait for atleast 500 * REFCLK cycles * (PLLD+1) */
117 ddr3_pll_delay(70000);
119 /* Disable the bypass */
120 reg &= ~(1 << 23); /* The value 0 disables the bypass */
121 DEVICE_REG32_W (base, reg);
123 return (0);
125 } /* hwPllSetCfg2Pll */