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