Updated PLL sequence and 66x and 665x devices and updated version
[keystone-rtos/ibl.git] / src / hw / plls / pll014phi / pll.c
1 /*************************************************************************************
2  * FILE PURPOSE: Provide PLL control functions
3  *************************************************************************************
4  * FILE NAME: pll.c
5  *
6  * DESCRIPTION: Provides functions to control the pll
7  *
8  *************************************************************************************/
9 #include "types.h"
10 #include "ibl.h"
11 #include "pllloc.h"
12 #include "pllapi.h"
13 #include "target.h"
15 #define DEVICE_REG32_W(x,y)   *(volatile unsigned int *)(x)=(y)
16 #define DEVICE_REG32_R(x)    (*(volatile unsigned int *)(x))
18 #define BOOTBITMASK(x,y)      (   (   (  ((UINT32)1 << (((UINT32)x)-((UINT32)y)+(UINT32)1) ) - (UINT32)1 )   )   <<  ((UINT32)y)   )
19 #define BOOT_READ_BITFIELD(z,x,y)   (((UINT32)z) & BOOTBITMASK(x,y)) >> (y)
20 #define BOOT_SET_BITFIELD(z,f,x,y)  (((UINT32)z) & ~BOOTBITMASK(x,y)) | ( (((UINT32)f) << (y)) & BOOTBITMASK(x,y) )
23 typedef enum  {
24     HW_PLL_DO_NOT_ENABLE_PLL,
25     HW_PLL_ENABLE_PLL
26 } hwPllEnable_t;
28 /*********************************************************************************
29  * FUNCTION PURPOSE: Provide a delay loop
30  *********************************************************************************
31  * DESCRIPTION: Generates a delay, units of cycles
32  *********************************************************************************/
33 void hw_pll_delay (UINT32 del)
34 {
35   UINT32 i;
36   volatile UINT32 j;
38   for (i = j = 0; i < del; i++)
39     asm (" nop ");
41 } /* hw_pll_delay */
44 /**********************************************************************************
45  * FUNCTION PURPOSE: Enables the pll to the specified multiplier
46  **********************************************************************************
47  * DESCRIPTION: Sets up the pll
48  **********************************************************************************/
49 SINT16 hwPllSetPll (UINT32 pllNum, UINT32 prediv, UINT32 mult, UINT32 postdiv)
50 {
51   UINT32 ctl, reg;
52   UINT32 secctl;
53   UINT32 status;
54   UINT32 alnctl;
55   UINT32 pmult;
56   UINT32 pdiv;
57   UINT32 pllBase;
58   UINT32 i;
59   SINT16 ret = 0;
60   UINT32 pllm_min = 10, plld_min =0, outputdiv = 9;
61   UINT32 div2=3, div5=5, div8=64;
63   /* Mutliplier/divider values of 0 are invalid */
64   if (prediv == 0)
65     prediv = 1;
67   if (mult == 0)
68     mult = 1;
70   if (postdiv == 0)
71     postdiv = 1;
73   /* Get the base address of the pll */
74   pllBase = (UINT32) DEVICE_PLL_BASE(pllNum);
76  /* 1. Wait for Stabilization time (min 100 us)             *
77   * assuming max device speed, 1.4GHz, 1 cycle = 0.714 ns   *
78   * so, 100 us = 100000 ns = 140056 cycles                  */
79   hw_pll_delay (140056);
81   /* Get the value of PLLCTL */
82   ctl = DEVICE_REG32_R (pllBase + PLL_REG_CTL);
84  /* 2. Check the status of BYPASS bit in SECCTL register,                   *
85   *    execute the following steps if                                       *
86   *    BYPASS == 1 (if bypass enabled), if BYPASS==0 then Jump to Step 3    */
87   secctl = DEVICE_REG32_R (pllBase + PLL_REG_SECCTL);
89   if ( (secctl & PLL_REG_SECCTL_FIELD_BYPASS) != 0 ) {
90     /* PLL BYPASS is turned on */
92         /* 2a. Set the ENSAT Bit */
93         /* Usage Note 9: For optimal PLL operation, the ENSAT bit in the PLL control
94          * registers for the Main PLL, DDR3 PLL, and PA PLL should be set to 1.
95          * The PLL initialization sequence in the silicon sets this bit to 0 and
96          * could lead to non-optimal PLL operation. Software can set the bit to the
97          * optimal value of 1 after boot
98      * |31...7   |6     |5 4       |3...0      |
99      * |Reserved |ENSAT |Reserved  |BWADJ[11:8]|
100          */
101     reg = DEVICE_REG32_R (DEVICE_MAIN_PLL_CTL_1);   // Read MAINPLLCTL
102     reg = reg | (1 << 6);                           // Set bit 6 (ENSAT)
103     DEVICE_REG32_W (DEVICE_MAIN_PLL_CTL_1, reg);    // Write to MAINPLLCTL
104     
105     /* 2b. Clear the PLLEN bit */
106         ctl = ctl & ~(PLL_REG_CTL_FIELD_PLLEN);
107         DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl);
109         /* 2c. Clear the PLLENSRC bit */
110         ctl = ctl & ~(PLL_REG_CTL_FIELD_PLLENSRC);
111         DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl);
113         
114         /* 2d. Wait for 4 Ref clocks */
115         /* The slowest clock can be at 25MHz, so min:160ns delay */
116         hw_pll_delay(225);
118         /* 2e. Put the PLL in Bypass mode to perform the power down mode */
119         secctl = secctl | PLL_REG_SECCTL_FIELD_BYPASS;
120         DEVICE_REG32_W (pllBase + PLL_REG_SECCTL, secctl);
122         /* 2f. Advisory 8: Multiple PLLs May Not Lock After Power-on Reset Issue
123          * In order to ensure proper PLL startup, the PLL power_down pin needs to be
124          * toggled. This is accomplished by toggling the PLLPWRDN bit in the PLLCTL
125          * register. This needs to be done before the main PLL initialization
126          * sequence
127          */
128         ctl = ctl | 0x00000002;
129         DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl);
131         /* 2g. Stay in a loop such that the bit is set for 5 ┬Ás (minimum) and
132          * then clear the bit.
133          */
134         hw_pll_delay (14005); /* waiting 10 us */
136         /* 2h. Power up the PLL */
137         ctl = ctl & ~(0x00000002);
138         DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl);
139         
140   }
141   else
142   {
143     /* 3. Enable BYPASS in the PLL controller */
144     
145     /* 3a. Clear PLLEN bit (bypass enabled in PLL controller mux) */
146     ctl = ctl & ~(PLL_REG_CTL_FIELD_PLLEN);
147         DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl);
148     
149     /* 3b. Clear PLLENSRC bit (enable PLLEN to control PLL controller mux) */
150     ctl = ctl & ~(PLL_REG_CTL_FIELD_PLLENSRC);
151         DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl);
152     
153     /* 3c. Wait for 4 RefClks (to make sure the PLL controller *
154      * mux switches properly to bypass)                        *
155      * Assuming slowest Ref clock of 25MHz, min: 160 ns delay  */
156      hw_pll_delay(225);
157   }
159         /* Program the necessary multipliers/dividers and BW adjustments
160          * This routine will subtract 1 from the mult value
161          */
162     /* 4. Program Multipliers */
163         pmult = chipPllExternalMult(pllNum, mult);
164         pmult   = pmult & PLL_REG_PLLM_FIELD_MULTm1;
165         DEVICE_REG32_W (pllBase + PLL_REG_PLLM, pmult);
167         /* 5. set the BWADJ */
168         chipPllExternalBwAdj (pllNum, mult);
170         /* 6. Set the PLL Divider */
171         chipPllSetExternalPrediv(pllNum, prediv - 1);  
173         /* 7. set the output divide */
174         secctl = BOOT_SET_BITFIELD(secctl, 1 & 0x000f, 22, 19);
175         DEVICE_REG32_W (pllBase + PLL_REG_SECCTL, secctl);
177     /* 8. Program PLLDIVn */
178   
179         /* part of 8, wait for the GOSTAT, but don't trap if lock is never read */
180         for (i = 0; i < 100; i++)  {
181                 hw_pll_delay (300);
182                 status = DEVICE_REG32_R (pllBase + PLL_REG_PLLSTAT);
183                 if ( (status & PLL_REG_STATUS_FIELD_GOSTAT) == 0 )
184                         break;
185         }
187         /* Enable the pll even if the lock failed. Return a warning. */
188         if (i == 100)  
189                 ret = -1;
190   
191         /* part of 8, Set PLL dividers if needed */
192         reg = 0x8000 | (div2 -1);
193         DEVICE_REG32_W (pllBase + PLL_REG_DIV2, reg);
195         reg = 0x8000 | (div5 -1);
196         DEVICE_REG32_W (pllBase + PLL_REG_DIV5, reg);
198         reg = 0x8000 | (div8 -1);
199         DEVICE_REG32_W (pllBase + PLL_REG_DIV8, reg);
201         /* part of 8, Program ALNCTLn registers */
202         alnctl = DEVICE_REG32_R (pllBase + PLL_REG_ALNCTL);
203         alnctl = alnctl | ((1 << 1) | (1 << 4) | (1 << 7));
204         DEVICE_REG32_W (pllBase + PLL_REG_ALNCTL, alnctl);
206         /* part of 8, Set GOSET bit in PLLCMD to initiate the GO operation to change the divide *   
207          * values and align the SYSCLKs as programmed                                           */
208         reg = DEVICE_REG32_R (pllBase + PLL_REG_CMD);
209         reg = reg | 1;
210         DEVICE_REG32_W (pllBase + PLL_REG_CMD, reg);
212         /* part of 8, wait for the GOSTAT, but don't trap if lock is never read */
213         for (i = 0; i < 100; i++)  {
214                 hw_pll_delay (300);
215                 status = DEVICE_REG32_R (pllBase + PLL_REG_PLLSTAT);
216                 if ( (status & PLL_REG_STATUS_FIELD_GOSTAT) == 0 )
217                         break;
218         }
220         if (i == 100)  
221                 ret = -1;
222         
223     /* 9. Assert PLL Reset */
224         ctl = ctl | (PLL_REG_CTL_FIELD_PLLRST);
225         DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl);
227         /* 10. Wait for a minimum of 7 us*/
228         hw_pll_delay (14006);
230         /* 11. Release PLL from Reset */
231         ctl = ctl & ~(PLL_REG_CTL_FIELD_PLLRST);
232         DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl);
234         /* 12. Wait for PLL Lock time (min 50 us) */
235         hw_pll_delay (140056 >> 1);
237         /* 13. Clear the secondary controller bypass bit */
238         secctl = secctl & ~PLL_REG_SECCTL_FIELD_BYPASS;
239         DEVICE_REG32_W (pllBase + PLL_REG_SECCTL, secctl);
242         /* 14. Set pllen to 1 to enable pll mode */
243         ctl = ctl | PLL_REG_CTL_FIELD_PLLEN;
244         DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl);
245     
246     /* 15. The PLL and PLL Controller are now initialized in PLL mode - Complete */
247   
248         return (ret);
249 } /* hwPllSetPll */