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_imx6sx.h"
32 
33 /*******************************************************************************
34  * Code
35  ******************************************************************************/
36 
37 /*FUNCTION**********************************************************************
38  *
39  * Function Name : CCM_ANALOG_PowerUpPll
40  * Description   : Power up PLL.
41  *
42  *END**************************************************************************/
CCM_ANALOG_PowerUpPll(CCM_ANALOG_Type * base,uint32_t pllControl)43 void CCM_ANALOG_PowerUpPll(CCM_ANALOG_Type * base, uint32_t pllControl)
44 {
45     /* Judge PLL_USB1 and PLL_USB2 according to register offset value.
46 	   Because the definition of power control bit is different from the other PLL.*/
47     if((CCM_ANALOG_TUPLE_OFFSET(pllControl) == 0x10) || (CCM_ANALOG_TUPLE_OFFSET(pllControl) == 0x20))
48         CCM_ANALOG_TUPLE_REG_SET(base, pllControl) = 1 << CCM_ANALOG_TUPLE_SHIFT(pllControl);
49     else
50         CCM_ANALOG_TUPLE_REG_CLR(base, pllControl) = 1 << CCM_ANALOG_TUPLE_SHIFT(pllControl);
51 }
52 
53 /*FUNCTION**********************************************************************
54  *
55  * Function Name : CCM_ANALOG_PowerDownPll
56  * Description   : Power down PLL.
57  *
58  *END**************************************************************************/
CCM_ANALOG_PowerDownPll(CCM_ANALOG_Type * base,uint32_t pllControl)59 void CCM_ANALOG_PowerDownPll(CCM_ANALOG_Type * base, uint32_t pllControl)
60 {
61     /* Judge PLL_USB1 and PLL_USB2 according to register offset value.
62 	   Because the definition of power control bit is different from the other PLL.*/
63     if((CCM_ANALOG_TUPLE_OFFSET(pllControl) == 0x10) || (CCM_ANALOG_TUPLE_OFFSET(pllControl) == 0x20))
64         CCM_ANALOG_TUPLE_REG_CLR(base, pllControl) = 1 << CCM_ANALOG_TUPLE_SHIFT(pllControl);
65     else
66         CCM_ANALOG_TUPLE_REG_SET(base, pllControl) = 1 << CCM_ANALOG_TUPLE_SHIFT(pllControl);
67 }
68 
69 /*FUNCTION**********************************************************************
70  *
71  * Function Name : CCM_ANALOG_SetPllBypass
72  * Description   : PLL bypass setting.
73  *
74  *END**************************************************************************/
CCM_ANALOG_SetPllBypass(CCM_ANALOG_Type * base,uint32_t pllControl,bool bypass)75 void CCM_ANALOG_SetPllBypass(CCM_ANALOG_Type * base, uint32_t pllControl, bool bypass)
76 {
77     if(bypass)
78         CCM_ANALOG_TUPLE_REG_SET(base, pllControl) = CCM_ANALOG_PLL_ARM_BYPASS_MASK;
79     else
80         CCM_ANALOG_TUPLE_REG_CLR(base, pllControl) = CCM_ANALOG_PLL_ARM_BYPASS_MASK;
81 }
82 
83 /*FUNCTION**********************************************************************
84  *
85  * Function Name : CCM_ANALOG_GetPllFreq
86  * Description   : Get PLL frequency
87  *
88  *END**************************************************************************/
CCM_ANALOG_GetPllFreq(CCM_ANALOG_Type * base,uint32_t pllControl)89 uint32_t CCM_ANALOG_GetPllFreq(CCM_ANALOG_Type * base, uint32_t pllControl)
90 {
91     uint8_t divSelect;
92     float numerator, denomitor;
93     uint32_t hz = 0;
94 
95     if (CCM_ANALOG_IsPllBypassed(base, pllControl))
96         return 24000000;
97 
98     switch(CCM_ANALOG_TUPLE_OFFSET(pllControl))
99     {
100         /* Get PLL_ARM frequency. */
101         case 0x0:
102         {
103             divSelect = CCM_ANALOG_PLL_ARM & CCM_ANALOG_PLL_ARM_DIV_SELECT_MASK;
104             hz = 24000000 * divSelect / 2;
105             break;
106         }
107         /* Get PLL_USB1(PLL3) frequency. */
108         case 0x10:
109         {
110             divSelect = CCM_ANALOG_PLL_USB1 & CCM_ANALOG_PLL_USB1_DIV_SELECT_MASK;
111             if(divSelect == 0)
112                 hz = 480000000;
113             else if(divSelect == 1)
114                 hz = 528000000;
115             break;
116         }
117         /* Get PLL_USB2 frequency. */
118         case 0x20:
119         {
120             divSelect = CCM_ANALOG_PLL_USB2 & CCM_ANALOG_PLL_USB2_DIV_SELECT_MASK;
121             if(divSelect == 0)
122                 hz = 480000000;
123             else if(divSelect == 1)
124                 hz = 528000000;
125             break;
126         }
127         /* Get PLL_SYS(PLL2) frequency. */
128         case 0x30:
129         {
130             divSelect = CCM_ANALOG_PLL_SYS & CCM_ANALOG_PLL_SYS_DIV_SELECT_MASK;
131             if(divSelect == 0)
132                 hz = 480000000;
133             else
134                 hz = 528000000;
135             break;
136         }
137         /* Get PLL_AUDIO frequency. */
138         case 0x70:
139         {
140             divSelect = CCM_ANALOG_PLL_AUDIO & CCM_ANALOG_PLL_AUDIO_DIV_SELECT_MASK;
141             numerator = CCM_ANALOG_PLL_AUDIO_NUM & CCM_ANALOG_PLL_AUDIO_NUM_A_MASK;
142             denomitor = CCM_ANALOG_PLL_AUDIO_DENOM & CCM_ANALOG_PLL_AUDIO_DENOM_B_MASK;
143             hz = (uint32_t)(24000000 * (divSelect + (numerator / denomitor)));
144             break;
145         }
146         /* Get PLL_VIDEO frequency. */
147         case 0xA0:
148         {
149             divSelect = CCM_ANALOG_PLL_VIDEO & CCM_ANALOG_PLL_VIDEO_DIV_SELECT_MASK;
150             numerator = CCM_ANALOG_PLL_VIDEO_NUM & CCM_ANALOG_PLL_VIDEO_NUM_A_MASK;
151             denomitor = CCM_ANALOG_PLL_VIDEO_DENOM & CCM_ANALOG_PLL_VIDEO_DENOM_B_MASK;
152             hz = (uint32_t)(24000000 * (divSelect + (numerator / denomitor)));
153             break;
154         }
155     }
156     return hz;
157 }
158 
159 /*FUNCTION**********************************************************************
160  *
161  * Function Name : CCM_ANALOG_GetPfdFreq
162  * Description   : Get PFD frequency
163  *
164  *END**************************************************************************/
CCM_ANALOG_GetPfdFreq(CCM_ANALOG_Type * base,uint32_t pfdFrac)165 uint32_t CCM_ANALOG_GetPfdFreq(CCM_ANALOG_Type * base, uint32_t pfdFrac)
166 {
167     uint32_t main, frac;
168 
169     /* Judge whether pfdFrac is PLL2 PFD or not. */
170     if(CCM_ANALOG_TUPLE_OFFSET(pfdFrac) == 0x100)
171     {
172         /* PFD should work with PLL2 without bypass */
173         assert(!CCM_ANALOG_IsPllBypassed(base, ccmAnalogPllSysControl));
174         main = CCM_ANALOG_GetPllFreq(base, ccmAnalogPllSysControl);
175     }
176     else if(CCM_ANALOG_TUPLE_OFFSET(pfdFrac) == 0xF0)
177     {
178         /* PFD should work with PLL3 without bypass */
179         assert(!CCM_ANALOG_IsPllBypassed(base, ccmAnalogPllUsb1Control));
180         main = CCM_ANALOG_GetPllFreq(base, ccmAnalogPllUsb1Control);
181     }
182     else
183         main = 0;
184 
185     frac = CCM_ANALOG_GetPfdFrac(base, pfdFrac);
186 
187     return main / frac * 18;
188 }
189 
190 /*******************************************************************************
191  * EOF
192  ******************************************************************************/
193