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) )
25 /*********************************************************************************************************
26 * FUNCTION PURPOSE: Configure and enable a pll
27 *********************************************************************************************************
28 * DESCRIPTION: The PLL is configured. If the existing configuration matches the requested one no
29 * register write is made.
30 *********************************************************************************************************/
31 SINT16 hwPllSetCfg2Pll (UINT32 base, UINT16 prediv, UINT16 mult, UINT16 postdiv, UINT32 chipFreqMhz, UINT32 pllFreqMhz)
32 {
33 UINT32 reg;
34 UINT32 regb;
35 UINT32 bwAdj;
37 UINT16 currentPrediv;
38 UINT16 currentMult;
39 UINT16 currentPostdiv;
40 UINT16 currentBypass;
41 UINT16 currentBwAdj;
42 UINT16 currentEnable;
44 reg = DEVICE_REG32_R (base);
45 regb = DEVICE_REG32_R (base + 4);
47 currentPrediv = 1 + BOOT_READ_BITFIELD (reg, 5, 0);
48 currentMult = 1 + BOOT_READ_BITFIELD (reg, 18, 6);
49 currentPostdiv = 1 + BOOT_READ_BITFIELD (reg, 22, 19);
50 currentBypass = BOOT_READ_BITFIELD (reg, 23, 23);
51 currentBwAdj = 1 + BOOT_READ_BITFIELD (reg, 31, 24) + ((BOOT_READ_BITFIELD (regb, 3, 0)) << 8);
52 currentEnable = BOOT_READ_BITFIELD(regb, 13, 13);
54 /* The PLL is currently enabled and connected if bypass == 0, enable == 1, clkout == 1 */
56 if ( (currentBypass == 0) &&
57 (currentPrediv == prediv) &&
58 (currentMult == mult) &&
59 (currentPostdiv == postdiv) &&
60 (currentEnable == 0) &&
61 (currentBwAdj == (mult >> 1)) )
62 return (0);
65 /* bwAdj is based only on the mult value */
66 bwAdj = (mult >> 1) - 1;
68 /* Multiplier / divider values are input as 1 less then the desired value */
69 if (prediv > 0)
70 prediv -= 1;
72 if (mult > 0)
73 mult -= 1;
75 if (postdiv > 0)
76 postdiv -= 1;
78 /* Set bit 13 in register 1 to disable the PLL (assert reset) */
79 regb = BOOT_SET_BITFIELD(regb, 1, 13, 13);
80 DEVICE_REG32_W (base + 4, regb);
82 /* Setup the PLL. Assert bypass */
83 reg = BOOT_SET_BITFIELD (reg, prediv, 5, 0);
84 reg = BOOT_SET_BITFIELD (reg, mult, 18, 6);
85 reg = BOOT_SET_BITFIELD (reg, postdiv, 22, 19);
86 reg = BOOT_SET_BITFIELD (reg, 1, 23, 23); /* Bypass must be enabled */
87 reg = BOOT_SET_BITFIELD (reg, (bwAdj & 0xff), 31, 24);
89 DEVICE_REG32_W (base, reg);
91 /* The 4 MS Bits of bwadj */
92 regb = BOOT_SET_BITFIELD (regb, (bwAdj >> 8), 3, 0);
93 DEVICE_REG32_W (base + 4, regb);
96 /* Reset must be asserted for at least 5us. Give a huge amount of padding here to be safe
97 * (the factor of 100) */
98 chipDelay32 (5 * chipFreqMhz * 100);
101 /* Clear bit 13 in register 1 to re-enable the pll */
102 regb = BOOT_SET_BITFIELD(regb, 0, 13, 13);
103 DEVICE_REG32_W (base + 4, regb);
105 /* Need to wait 100,000 output PLL cycles before releasing bypass and setting
106 * up the clk output */
107 chipDelay32 (chipFreqMhz * 100000 / pllFreqMhz);
110 /* Disable the bypass */
111 reg = BOOT_SET_BITFIELD (reg, 0, 23, 23); /* The value 0 disables the bypass */
112 DEVICE_REG32_W (base, reg);
114 return (0);
116 } /* hwPllSetCfg2Pll */