4f2834206a12b2a990f02a0acae0ee510d36d402
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 *********************************************************************************************************/
10 #include "types.h"
11 #include "target.h"
12 #include "pllapi.h"
14 #define DEVICE_REG32_W(x,y) *(volatile unsigned int *)(x)=(y)
15 #define DEVICE_REG32_R(x) (*(volatile unsigned int *)(x))
17 #define BOOTBITMASK(x,y) ( ( ( ((UINT32)1 << (((UINT32)x)-((UINT32)y)+(UINT32)1) ) - (UINT32)1 ) ) << ((UINT32)y) )
18 #define BOOT_READ_BITFIELD(z,x,y) (((UINT32)z) & BOOTBITMASK(x,y)) >> (y)
19 #define BOOT_SET_BITFIELD(z,f,x,y) (((UINT32)z) & ~BOOTBITMASK(x,y)) | ( (((UINT32)f) << (y)) & BOOTBITMASK(x,y) )
21 void pass_pll_delay (UINT32 del)
22 {
23 UINT32 i;
24 volatile UINT32 j;
26 for (i = j = 0; i < del; i++)
27 asm (" nop ");
29 }
32 /*********************************************************************************************************
33 * FUNCTION PURPOSE: Configure and enable a pll
34 *********************************************************************************************************
35 * DESCRIPTION: The PLL is configured. If the existing configuration matches the requested one no
36 * register write is made.
37 *********************************************************************************************************/
38 SINT16 hwPllSetCfgPll (UINT32 base, UINT32 prediv, UINT32 mult, UINT32 postdiv, UINT32 chipFreqMhz, UINT32 pllFreqMhz)
39 {
40 UINT32 reg;
41 UINT32 regb;
42 UINT32 bwAdj;
44 UINT16 currentPrediv;
45 UINT16 currentMult;
46 UINT16 currentPostdiv;
47 UINT16 currentBypass;
48 UINT16 currentBwAdj;
49 UINT16 currentEnable;
50 UINT16 currentClkOut;
52 reg = DEVICE_REG32_R (base);
53 regb = DEVICE_REG32_R (base + 4);
55 currentPrediv = 1 + BOOT_READ_BITFIELD (reg, 5, 0);
56 currentMult = 1 + BOOT_READ_BITFIELD (reg, 18, 6);
57 currentPostdiv = 1 + BOOT_READ_BITFIELD (reg, 22, 19);
58 currentBypass = BOOT_READ_BITFIELD (reg, 23, 23);
59 currentBwAdj = 1 + BOOT_READ_BITFIELD (reg, 31, 24) + ((BOOT_READ_BITFIELD (regb, 3, 0)) << 8);
60 currentEnable = BOOT_READ_BITFIELD(regb, 14, 14);
61 currentClkOut = BOOT_READ_BITFIELD(regb, 13, 13);
63 /* The PLL is currently enabled and connected if bypass == 0, enable == 1, clkout == 1 */
65 if ( (currentBypass == 0) &&
66 (currentPrediv == prediv) &&
67 (currentMult == mult) &&
68 (currentPostdiv == postdiv) &&
69 (currentEnable == 0) &&
70 (currentClkOut == 1) &&
71 (currentBwAdj == (mult >> 1)) )
72 return (0);
75 /* bwAdj is based only on the mult value */
76 bwAdj = (mult >> 1) - 1;
78 /* Write to the ENSAT bit */
79 regb = BOOT_SET_BITFIELD(regb, 1, 6, 6);
80 DEVICE_REG32_W (base + 4, regb);
82 /* Setup the PLL. Assert bypass */
83 reg = BOOT_SET_BITFIELD (reg, 1, 23, 23); /* Bypass must be enabled */
84 DEVICE_REG32_W (base, reg);
86 /* Set bit 14 in register 1 to disable the PLL (assert reset) */
87 regb = BOOT_SET_BITFIELD(regb, 1, 14, 14);
88 DEVICE_REG32_W (base + 4, regb);
90 reg = BOOT_SET_BITFIELD (reg, prediv - 1, 5, 0);
91 reg = BOOT_SET_BITFIELD (reg, mult - 1, 18, 6);
92 reg = BOOT_SET_BITFIELD (reg, (bwAdj & 0xff), 31, 24);
94 DEVICE_REG32_W (base, reg);
96 /* The 4 MS Bits of bwadj */
97 regb = BOOT_SET_BITFIELD (regb, (bwAdj >> 8), 3, 0);
98 DEVICE_REG32_W (base + 4, regb);
101 /* Reset must be asserted for at least 5us. Give a huge amount of padding here to be safe
102 * (the factor of 100) */
103 pass_pll_delay(7000);
105 /* Clear bit 14 in register 1 to re-enable the pll */
106 regb = BOOT_SET_BITFIELD(regb, 0, 14, 14);
107 DEVICE_REG32_W (base + 4, regb);
109 /* Wait for 50 us */
110 pass_pll_delay(70000);
112 /* Disable the bypass */
113 reg = BOOT_SET_BITFIELD (reg, 0, 23, 23); /* The value 0 disables the bypass */
114 DEVICE_REG32_W (base, reg);
116 #if 0
117 /* Enable the output source (set bit 13) */
118 regb = BOOT_SET_BITFIELD(regb, 1, 13, 13);
119 DEVICE_REG32_W (base + 4, regb);
120 #endif
122 return (0);
124 } /* hwPllSetCfgPll */