1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * o Redistributions of source code must retain the above copyright notice, this list
9  *   of conditions and the following disclaimer.
10  *
11  * o Redistributions in binary form must reproduce the above copyright notice, this
12  *   list of conditions and the following disclaimer in the documentation and/or
13  *   other materials provided with the distribution.
14  *
15  * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
16  *   contributors may be used to endorse or promote products derived from this
17  *   software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "ccm_analog_imx7d.h"
32 
33 /*******************************************************************************
34  * Code
35  ******************************************************************************/
36 
37 /*FUNCTION**********************************************************************
38  *
39  * Function Name : CCM_ANALOG_GetArmPllFreq
40  * Description   : Get ARM PLL frequency
41  *
42  *END**************************************************************************/
CCM_ANALOG_GetArmPllFreq(CCM_ANALOG_Type * base)43 uint32_t CCM_ANALOG_GetArmPllFreq(CCM_ANALOG_Type * base)
44 {
45     if (CCM_ANALOG_IsPllBypassed(base, ccmAnalogPllArmControl))
46         return 24000000ul;
47 
48     return 12000000ul * (CCM_ANALOG_PLL_ARM & CCM_ANALOG_PLL_ARM_DIV_SELECT_MASK);
49 }
50 
51 /*FUNCTION**********************************************************************
52  *
53  * Function Name : CCM_ANALOG_GetSysPllFreq
54  * Description   : Get system PLL frequency
55  *
56  *END**************************************************************************/
CCM_ANALOG_GetSysPllFreq(CCM_ANALOG_Type * base)57 uint32_t CCM_ANALOG_GetSysPllFreq(CCM_ANALOG_Type * base)
58 {
59     if (CCM_ANALOG_IsPllBypassed(base, ccmAnalogPll480Control))
60         return 24000000ul;
61 
62     if (CCM_ANALOG_PLL_480 & CCM_ANALOG_PLL_480_DIV_SELECT_MASK)
63         return 528000000ul;
64     else
65         return 480000000ul;
66 }
67 
68 /*FUNCTION**********************************************************************
69  *
70  * Function Name : CCM_ANALOG_GetDdrPllFreq
71  * Description   : Get DDR PLL frequency
72  *
73  *END**************************************************************************/
CCM_ANALOG_GetDdrPllFreq(CCM_ANALOG_Type * base)74 uint32_t CCM_ANALOG_GetDdrPllFreq(CCM_ANALOG_Type * base)
75 {
76     uint8_t divSelect, divTestSelect;
77     float factor;
78 
79     if (CCM_ANALOG_IsPllBypassed(base, ccmAnalogPllDdrControl))
80         return 24000000ul;
81 
82     divSelect = CCM_ANALOG_PLL_DDR_REG(CCM_ANALOG) & CCM_ANALOG_PLL_DDR_DIV_SELECT_MASK;
83     divTestSelect = (CCM_ANALOG_PLL_DDR_REG(CCM_ANALOG) & CCM_ANALOG_PLL_DDR_TEST_DIV_SELECT_MASK) >>
84                      CCM_ANALOG_PLL_DDR_TEST_DIV_SELECT_SHIFT;
85 
86     switch (divTestSelect)
87     {
88         case 0x0:
89             divTestSelect = 2;
90             break;
91         case 0x1:
92             divTestSelect = 1;
93             break;
94         case 0x2:
95         case 0x3:
96             divTestSelect = 0;
97             break;
98     }
99 
100     if (CCM_ANALOG_PLL_DDR_SS_REG(base) & CCM_ANALOG_PLL_DDR_SS_ENABLE_MASK)
101     {
102         factor = ((float)(CCM_ANALOG_PLL_DDR_SS_REG(base) & CCM_ANALOG_PLL_DDR_SS_STEP_MASK)) /
103                  ((float)(CCM_ANALOG_PLL_DDR_DENOM_REG(base) & CCM_ANALOG_PLL_DDR_DENOM_B_MASK)) *
104                  ((float)(CCM_ANALOG_PLL_DDR_NUM_REG(base) & CCM_ANALOG_PLL_DDR_NUM_A_MASK));
105         return (uint32_t)((24000000ul >> divTestSelect) * (divSelect + factor));
106     }
107     else
108     {
109         return (24000000ul >> divTestSelect) * divSelect;
110     }
111 }
112 
113 /*FUNCTION**********************************************************************
114  *
115  * Function Name : CCM_ANALOG_GetEnetPllFreq
116  * Description   : Get Ethernet PLL frequency
117  *
118  *END**************************************************************************/
CCM_ANALOG_GetEnetPllFreq(CCM_ANALOG_Type * base)119 uint32_t CCM_ANALOG_GetEnetPllFreq(CCM_ANALOG_Type * base)
120 {
121     if (CCM_ANALOG_IsPllBypassed(base, ccmAnalogPllEnetControl))
122         return 24000000ul;
123 
124     return 1000000000ul;
125 }
126 
127 /*FUNCTION**********************************************************************
128  *
129  * Function Name : CCM_ANALOG_GetAudioPllFreq
130  * Description   : Get Ethernet PLL frequency
131  *
132  *END**************************************************************************/
CCM_ANALOG_GetAudioPllFreq(CCM_ANALOG_Type * base)133 uint32_t CCM_ANALOG_GetAudioPllFreq(CCM_ANALOG_Type * base)
134 {
135     uint8_t divSelect, divPostSelect, divTestSelect;
136     float factor;
137 
138     if (CCM_ANALOG_IsPllBypassed(base, ccmAnalogPllAudioControl))
139         return 24000000ul;
140 
141     divSelect = CCM_ANALOG_PLL_AUDIO_REG(CCM_ANALOG) & CCM_ANALOG_PLL_AUDIO_DIV_SELECT_MASK;
142     divPostSelect = (CCM_ANALOG_PLL_AUDIO_REG(CCM_ANALOG) & CCM_ANALOG_PLL_AUDIO_POST_DIV_SEL_MASK) >>
143                     CCM_ANALOG_PLL_AUDIO_POST_DIV_SEL_SHIFT;
144     divTestSelect = (CCM_ANALOG_PLL_AUDIO_REG(CCM_ANALOG) & CCM_ANALOG_PLL_AUDIO_TEST_DIV_SELECT_MASK) >>
145                     CCM_ANALOG_PLL_AUDIO_TEST_DIV_SELECT_SHIFT;
146 
147     switch (divPostSelect)
148     {
149         case 0x0:
150         case 0x2:
151             divPostSelect = 0;
152             break;
153         case 0x1:
154             divPostSelect = 1;
155             break;
156         case 0x3:
157             divPostSelect = 2;
158             break;
159     }
160 
161     switch (divTestSelect)
162     {
163         case 0x0:
164             divTestSelect = 2;
165             break;
166         case 0x1:
167             divTestSelect = 1;
168             break;
169         case 0x2:
170         case 0x3:
171             divTestSelect = 0;
172             break;
173     }
174 
175     if (CCM_ANALOG_PLL_AUDIO_SS_REG(base) & CCM_ANALOG_PLL_AUDIO_SS_ENABLE_MASK)
176     {
177         factor = ((float)(CCM_ANALOG_PLL_AUDIO_SS_REG(base) & CCM_ANALOG_PLL_AUDIO_SS_STEP_MASK)) /
178                  ((float)(CCM_ANALOG_PLL_AUDIO_DENOM_REG(base) & CCM_ANALOG_PLL_AUDIO_DENOM_B_MASK)) *
179                  ((float)(CCM_ANALOG_PLL_AUDIO_NUM_REG(base) & CCM_ANALOG_PLL_AUDIO_NUM_A_MASK));
180         return (uint32_t)(((24000000ul >> divTestSelect) >> divPostSelect) * (divSelect + factor));
181     }
182     else
183     {
184         return ((24000000ul >> divTestSelect) >> divPostSelect) * divSelect;
185     }
186 }
187 
188 /*FUNCTION**********************************************************************
189  *
190  * Function Name : CCM_ANALOG_GetVideoPllFreq
191  * Description   : Get Ethernet PLL frequency
192  *
193  *END**************************************************************************/
CCM_ANALOG_GetVideoPllFreq(CCM_ANALOG_Type * base)194 uint32_t CCM_ANALOG_GetVideoPllFreq(CCM_ANALOG_Type * base)
195 {
196     uint8_t divSelect, divPostSelect, divTestSelect;
197     float factor;
198 
199     if (CCM_ANALOG_IsPllBypassed(base, ccmAnalogPllVideoControl))
200         return 24000000ul;
201 
202     divSelect = CCM_ANALOG_PLL_VIDEO_REG(CCM_ANALOG) & CCM_ANALOG_PLL_VIDEO_DIV_SELECT_MASK;
203     divPostSelect = (CCM_ANALOG_PLL_VIDEO_REG(CCM_ANALOG) & CCM_ANALOG_PLL_VIDEO_POST_DIV_SEL_MASK) >>
204                     CCM_ANALOG_PLL_VIDEO_POST_DIV_SEL_SHIFT;
205     divTestSelect = (CCM_ANALOG_PLL_VIDEO_REG(CCM_ANALOG) & CCM_ANALOG_PLL_VIDEO_TEST_DIV_SELECT_MASK) >>
206                     CCM_ANALOG_PLL_VIDEO_TEST_DIV_SELECT_SHIFT;
207 
208     switch (divPostSelect)
209     {
210         case 0x0:
211         case 0x2:
212             divPostSelect = 0;
213             break;
214         case 0x1:
215             divPostSelect = 1;
216             break;
217         case 0x3:
218             divPostSelect = 2;
219             break;
220     }
221 
222     switch (divTestSelect)
223     {
224         case 0x0:
225             divTestSelect = 2;
226             break;
227         case 0x1:
228             divTestSelect = 1;
229             break;
230         case 0x2:
231         case 0x3:
232             divTestSelect = 0;
233             break;
234     }
235 
236     if (CCM_ANALOG_PLL_VIDEO_SS_REG(base) & CCM_ANALOG_PLL_VIDEO_SS_ENABLE_MASK)
237     {
238         factor = ((float)(CCM_ANALOG_PLL_VIDEO_SS_REG(base) & CCM_ANALOG_PLL_VIDEO_SS_STEP_MASK)) /
239                  ((float)(CCM_ANALOG_PLL_VIDEO_DENOM_REG(base) & CCM_ANALOG_PLL_VIDEO_DENOM_B_MASK)) *
240                  ((float)(CCM_ANALOG_PLL_VIDEO_NUM_REG(base) & CCM_ANALOG_PLL_VIDEO_NUM_A_MASK));
241         return (uint32_t)(((24000000ul >> divTestSelect) >> divPostSelect) * (divSelect + factor));
242     }
243     else
244     {
245         return ((24000000ul >> divTestSelect) >> divPostSelect) * divSelect;
246     }
247 }
248 
249 /*FUNCTION**********************************************************************
250  *
251  * Function Name : CCM_ANALOG_GetPfdFreq
252  * Description   : Get PFD frequency
253  *
254  *END**************************************************************************/
CCM_ANALOG_GetPfdFreq(CCM_ANALOG_Type * base,uint32_t pfdFrac)255 uint32_t CCM_ANALOG_GetPfdFreq(CCM_ANALOG_Type * base, uint32_t pfdFrac)
256 {
257     uint32_t main, frac;
258 
259     /* PFD should work with system PLL without bypass */
260     assert(!CCM_ANALOG_IsPllBypassed(base, ccmAnalogPll480Control));
261 
262     main = CCM_ANALOG_GetSysPllFreq(base);
263     frac = CCM_ANALOG_GetPfdFrac(base, pfdFrac);
264 
265     return main / frac * 18;
266 }
267 
268 /*******************************************************************************
269  * EOF
270  ******************************************************************************/
271