95543b6c8e7503e72cc1daf785c53fd9ddea880e
[keystone-rtos/ibl.git] / src / hw / plls / pllxx1p8 / 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  * @file pll.c
9  *
10  * @brief
11  *  The pllhi1p8 and pllmd1ph driver
12  *
13  *************************************************************************************/
14 #include "types.h"
15 #include "pllloc.h"
16 #include "pllapi.h"
17 #include "target.h"
20 #define DEVICE_REG32_W(x,y)   *(volatile unsigned int *)(x)=(y)
21 #define DEVICE_REG32_R(x)    (*(volatile unsigned int *)(x))
23 /**************************************************************************************
24  * FUNCTION PURPOSE: Return the last boot type
25  **************************************************************************************
26  * DESCRIPTION: Returns the last boot mode type
27  **************************************************************************************/
28 uint16 hwPllResetType (uint16 pllNum)
29 {
30   if ( ((DEVICE_REG32_R (DEVICE_PLL_BASE(pllNum) + PLL_REG_RSTYPE)) & PLL_REG_RSTYPE_FIELD_POWER_ON_RESET) != 0 )
31     return (pll_POR_RESET);
33   return (pll_WARM_RESET);
35 } /* hwPllResetType */
38 /*********************************************************************************
39  * FUNCTION PURPOSE: Provide a delay loop
40  *********************************************************************************
41  * DESCRIPTION: Generates a delay, units of cycles
42  *********************************************************************************/
43 void hw_pll_delay (uint32 del)
44 {
45   uint32 i;
46   volatile uint32 j;
48   for (i = j = 0; i < del; i++)
49     j = j + 1;
51 } /* hw_pll_delay */
54 /**********************************************************************************
55  * FUNCTION PURPOSE: Enables the pll to the specified multiplier
56  **********************************************************************************
57  * DESCRIPTION: Sets up the pll
58  **********************************************************************************/
59 int16 hwPllSetPll (uint16 pllNum, uint16 prediv, uint16 mult, uint16 postdiv)
60 {
61   uint32 ctl;
62   uint32 status;
63   uint32 pmult;
64   uint32 pdiv;
65   uint32 pllBase;
66   uint32 i;
68   /* Mutliplier/divider values of 0 are invalid */
69   if (prediv == 0)
70     prediv = 1;
72   if (mult == 0)
73     mult = 1;
75   if (postdiv == 0)
76     postdiv = 1;
78   /* Get the base address of the pll */
79   pllBase = (uint32) DEVICE_PLL_BASE(pllNum);
81   /* Set pllensrc = 0 so that the register bit pllen can control the pllen mux */
82   ctl = DEVICE_REG32_R (pllBase + PLL_REG_CTL);
83   ctl = ctl & ~(PLL_REG_CTL_FIELD_PLLENSRC);
84   DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl);
87   /* Program pllen=0 (pll bypass), pllrst=1 (reset pll) */
88   ctl = ctl & ~(PLL_REG_CTL_FIELD_PLLEN);
89   ctl = ctl | PLL_REG_CTL_FIELD_PLLRST;
90   DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl);
93   /* Program prediv, pllm, postdiv */
94   pmult   = (uint32) ((mult-1)   & PLL_REG_PLLM_FIELD_MULTm1);
95   pdiv    = (uint32) (((prediv-1) & PLL_REG_PREDIV_FIELD_RATIOm1) | PLL_REG_PREDIV_FIELD_ENABLE);
97   DEVICE_REG32_W (pllBase + PLL_REG_PLLM,    pmult);
98   DEVICE_REG32_W (pllBase + PLL_REG_PREDIV,  pdiv);
100   if (postdiv != 1)  {
101     postdiv = (uint16) (((postdiv-1) & PLL_REG_POSTDIV_FIELD_RATIO) | PLL_REG_POSTDIV_FIELD_ENABLE);
102     DEVICE_REG32_W (pllBase + PLL_REG_POSTDIV, postdiv);
103   }  else  {
104     DEVICE_REG32_W (pllBase + PLL_REG_POSTDIV, PLL_REG_POSTDIV_VALUE_DISABLED);
105   }
107   /* Wait a while for the pll to reset */
108   hw_pll_delay (2000/7);
110   /* set pllrst to 0 to deassert pll reset */
111   ctl = ctl & ~(PLL_REG_CTL_FIELD_PLLRST);
112   DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl);
115   /* wait for the pll to lock, but don't trap if lock is never read */
116   for (i = 0; i < 100; i++)  {
117     hw_pll_delay (2000/7);
118     status = DEVICE_REG32_R (pllBase + PLL_REG_PLLSTAT);
119     if ( (status & PLL_REG_STATUS_FIELD_LOCK) != 0 )
120       break;
121   }
123   /* Do not enable the pll if the lock failed. Return a warning. */
124   if (i == 100)  
125     return (-1);
128   /* Set pllen to 1 to enable pll mode */
129   ctl = ctl | PLL_REG_CTL_FIELD_PLLEN;
130   DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl);
132   return (0);
135 } /* hwPllSetPll */
137  
138 /**********************************************************************************
139  * FUNCTION PURPOSE: Disable the pll
140  **********************************************************************************
141  * DESCRIPTION: The pll is put into bypass. Returns 0 on success. 
142  **********************************************************************************/
143 int16 hwPllDisable (uint16 pllNum)
145   uint32 ctl;
146   uint32 pllBase;
148   /* Get the base address of the pll */
149   pllBase = (uint32)DEVICE_PLL_BASE(pllNum);
151   /* Set pllensrc = 0 so that the register bit pllen can control the pllen mux */
152   ctl = DEVICE_REG32_R (pllBase + PLL_REG_CTL);
153   ctl = ctl & ~(PLL_REG_CTL_FIELD_PLLENSRC);
154   DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl);
157   /* Program pllen=0 (pll bypass), pllrst=1 (reset pll) */
158   ctl = ctl & ~(PLL_REG_CTL_FIELD_PLLEN);
159   ctl = ctl | PLL_REG_CTL_FIELD_PLLRST;
160   DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl);
162   return (0);
165 } /* hwPllDisable */
167 /***********************************************************************************
168  * FUNCTION PURPOSE: Enable the PLL
169  ***********************************************************************************
170  * DESCRIPTION: The PLL is enabled with no changes to multipliers or dividers
171  ***********************************************************************************/
172 int16 hwPllEnable (uint16 pllNum)
174   uint32 ctl;
175   uint32 pllBase;
176   uint32 status;
177   uint32 i;
179   /* Get the base address of the pll */
180   pllBase = (uint32)DEVICE_PLL_BASE(pllNum);
182   /* Set pllensrc = 0 so that the register bit pllen can control the pllen mux */
183   ctl = DEVICE_REG32_R (pllBase + PLL_REG_CTL);
184   ctl = ctl & ~(PLL_REG_CTL_FIELD_PLLENSRC);
185   DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl);
187   /* Program pllen=0 (pll bypass), pllrst=1 (reset pll) */
188   ctl = ctl & ~(PLL_REG_CTL_FIELD_PLLEN);
189   ctl = ctl | PLL_REG_CTL_FIELD_PLLRST;
190   DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl);
192   /* Wait a while for the pll to reset */
193   hw_pll_delay (2000/7);
195   /* set pllrst to 0 to deassert pll reset */
196   ctl = ctl & ~(PLL_REG_CTL_FIELD_PLLRST);
197   DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl);
200   /* wait for the pll to lock, but don't trap if lock is never read */
201   for (i = 0; i < 100; i++)  {
202     hw_pll_delay (2000/7);
203     status = DEVICE_REG32_R (pllBase + PLL_REG_PLLSTAT);
204     if ( (status & PLL_REG_STATUS_FIELD_LOCK) != 0 )
205       break;
206   }
208   /* Return a warning if the lock failed */
209   if (i == 100)
210     return (-1);
212   /* Set pllen to 1 to enable pll mode */
213   ctl = ctl | PLL_REG_CTL_FIELD_PLLEN;
214   DEVICE_REG32_W (pllBase + PLL_REG_CTL, ctl);
216   return (0);
218 } /* hwPllEnable */
224