1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (C) 2015 Freescale Semiconductor, Inc.
4 *
5 * Author:
6 * Peng Fan <Peng.Fan@freescale.com>
7 */
8
9 #include <common.h>
10 #include <div64.h>
11 #include <asm/io.h>
12 #include <linux/errno.h>
13 #include <asm/arch/imx-regs.h>
14 #include <asm/arch/crm_regs.h>
15 #include <asm/arch/clock.h>
16 #include <asm/arch/sys_proto.h>
17
18 struct mxc_ccm_reg *imx_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
19
20 static struct clk_root_map root_array[] = {
21 {ARM_A7_CLK_ROOT, CCM_CORE_CHANNEL,
22 {OSC_24M_CLK, PLL_ARM_MAIN_800M_CLK, PLL_ENET_MAIN_500M_CLK,
23 PLL_DRAM_MAIN_1066M_CLK, PLL_SYS_MAIN_480M_CLK,
24 PLL_SYS_PFD0_392M_CLK, PLL_AUDIO_MAIN_CLK, PLL_USB_MAIN_480M_CLK}
25 },
26 {ARM_M4_CLK_ROOT, CCM_BUS_CHANNEL,
27 {OSC_24M_CLK, PLL_SYS_MAIN_240M_CLK, PLL_ENET_MAIN_250M_CLK,
28 PLL_SYS_PFD2_270M_CLK, PLL_DRAM_MAIN_533M_CLK, PLL_AUDIO_MAIN_CLK,
29 PLL_VIDEO_MAIN_CLK, PLL_USB_MAIN_480M_CLK}
30 },
31 {ARM_M0_CLK_ROOT, CCM_BUS_CHANNEL,
32 {OSC_24M_CLK, PLL_SYS_MAIN_120M_CLK, PLL_ENET_MAIN_125M_CLK,
33 PLL_SYS_PFD2_135M_CLK, PLL_DRAM_MAIN_533M_CLK, PLL_AUDIO_MAIN_CLK,
34 PLL_VIDEO_MAIN_CLK, PLL_USB_MAIN_480M_CLK}
35 },
36 {MAIN_AXI_CLK_ROOT, CCM_BUS_CHANNEL,
37 {OSC_24M_CLK, PLL_SYS_PFD1_332M_CLK, PLL_DRAM_MAIN_533M_CLK,
38 PLL_ENET_MAIN_250M_CLK, PLL_SYS_PFD5_CLK, PLL_AUDIO_MAIN_CLK,
39 PLL_VIDEO_MAIN_CLK, PLL_SYS_PFD7_CLK}
40 },
41 {DISP_AXI_CLK_ROOT, CCM_BUS_CHANNEL,
42 {OSC_24M_CLK, PLL_SYS_PFD1_332M_CLK, PLL_DRAM_MAIN_533M_CLK,
43 PLL_ENET_MAIN_250M_CLK, PLL_SYS_PFD6_CLK, PLL_SYS_PFD7_CLK,
44 PLL_AUDIO_MAIN_CLK, PLL_VIDEO_MAIN_CLK}
45 },
46 {ENET_AXI_CLK_ROOT, CCM_IP_CHANNEL,
47 {OSC_24M_CLK, PLL_SYS_PFD2_270M_CLK, PLL_DRAM_MAIN_533M_CLK,
48 PLL_ENET_MAIN_250M_CLK, PLL_SYS_MAIN_240M_CLK, PLL_AUDIO_MAIN_CLK,
49 PLL_VIDEO_MAIN_CLK, PLL_SYS_PFD4_CLK}
50 },
51 {NAND_USDHC_BUS_CLK_ROOT, CCM_IP_CHANNEL,
52 {OSC_24M_CLK, PLL_SYS_PFD2_270M_CLK, PLL_DRAM_MAIN_533M_CLK,
53 PLL_SYS_MAIN_240M_CLK, PLL_SYS_PFD2_135M_CLK, PLL_SYS_PFD6_CLK,
54 PLL_ENET_MAIN_250M_CLK, PLL_AUDIO_MAIN_CLK}
55 },
56 {AHB_CLK_ROOT, CCM_AHB_CHANNEL,
57 {OSC_24M_CLK, PLL_SYS_PFD2_270M_CLK, PLL_DRAM_MAIN_533M_CLK,
58 PLL_SYS_PFD0_392M_CLK, PLL_ENET_MAIN_125M_CLK, PLL_USB_MAIN_480M_CLK,
59 PLL_AUDIO_MAIN_CLK, PLL_VIDEO_MAIN_CLK}
60 },
61 {DRAM_PHYM_CLK_ROOT, CCM_DRAM_PHYM_CHANNEL,
62 {PLL_DRAM_MAIN_1066M_CLK, DRAM_PHYM_ALT_CLK_ROOT}
63 },
64 {DRAM_CLK_ROOT, CCM_DRAM_CHANNEL,
65 {PLL_DRAM_MAIN_1066M_CLK, DRAM_ALT_CLK_ROOT}
66 },
67 {DRAM_PHYM_ALT_CLK_ROOT, CCM_IP_CHANNEL,
68 {OSC_24M_CLK, PLL_DRAM_MAIN_533M_CLK, PLL_SYS_MAIN_480M_CLK,
69 PLL_ENET_MAIN_500M_CLK, PLL_USB_MAIN_480M_CLK, PLL_SYS_PFD7_CLK,
70 PLL_AUDIO_MAIN_CLK, PLL_VIDEO_MAIN_CLK}
71 },
72 {DRAM_ALT_CLK_ROOT, CCM_IP_CHANNEL,
73 {OSC_24M_CLK, PLL_DRAM_MAIN_533M_CLK, PLL_SYS_MAIN_480M_CLK,
74 PLL_ENET_MAIN_500M_CLK, PLL_ENET_MAIN_250M_CLK,
75 PLL_SYS_PFD0_392M_CLK, PLL_AUDIO_MAIN_CLK, PLL_SYS_PFD2_270M_CLK}
76 },
77 {USB_HSIC_CLK_ROOT, CCM_IP_CHANNEL,
78 {OSC_24M_CLK, PLL_SYS_MAIN_480M_CLK, PLL_USB_MAIN_480M_CLK,
79 PLL_SYS_PFD3_CLK, PLL_SYS_PFD4_CLK, PLL_SYS_PFD5_CLK,
80 PLL_SYS_PFD6_CLK, PLL_SYS_PFD7_CLK}
81 },
82 {PCIE_CTRL_CLK_ROOT, CCM_IP_CHANNEL,
83 {OSC_24M_CLK, PLL_ENET_MAIN_250M_CLK, PLL_SYS_MAIN_240M_CLK,
84 PLL_SYS_PFD2_270M_CLK, PLL_DRAM_MAIN_533M_CLK,
85 PLL_ENET_MAIN_500M_CLK, PLL_SYS_PFD1_332M_CLK, PLL_SYS_PFD6_CLK}
86 },
87 {PCIE_PHY_CLK_ROOT, CCM_IP_CHANNEL,
88 {OSC_24M_CLK, PLL_ENET_MAIN_100M_CLK, PLL_ENET_MAIN_500M_CLK,
89 EXT_CLK_1, EXT_CLK_2, EXT_CLK_3,
90 EXT_CLK_4, PLL_SYS_PFD0_392M_CLK}
91 },
92 {EPDC_PIXEL_CLK_ROOT, CCM_IP_CHANNEL,
93 {OSC_24M_CLK, PLL_SYS_PFD1_332M_CLK, PLL_DRAM_MAIN_533M_CLK,
94 PLL_SYS_MAIN_480M_CLK, PLL_SYS_PFD5_CLK, PLL_SYS_PFD6_CLK,
95 PLL_SYS_PFD7_CLK, PLL_VIDEO_MAIN_CLK}
96 },
97 {LCDIF_PIXEL_CLK_ROOT, CCM_IP_CHANNEL,
98 {OSC_24M_CLK, PLL_SYS_PFD5_CLK, PLL_DRAM_MAIN_533M_CLK,
99 EXT_CLK_3, PLL_SYS_PFD4_CLK, PLL_SYS_PFD2_270M_CLK,
100 PLL_VIDEO_MAIN_CLK, PLL_USB_MAIN_480M_CLK}
101 },
102 {MIPI_DSI_EXTSER_CLK_ROOT, CCM_IP_CHANNEL,
103 {OSC_24M_CLK, PLL_SYS_PFD5_CLK, PLL_SYS_PFD3_CLK,
104 PLL_SYS_MAIN_480M_CLK, PLL_SYS_PFD0_196M_CLK, PLL_DRAM_MAIN_533M_CLK,
105 PLL_VIDEO_MAIN_CLK, PLL_AUDIO_MAIN_CLK}
106 },
107 {MIPI_CSI_WARP_CLK_ROOT, CCM_IP_CHANNEL,
108 {OSC_24M_CLK, PLL_SYS_PFD4_CLK, PLL_SYS_PFD3_CLK,
109 PLL_SYS_MAIN_480M_CLK, PLL_SYS_PFD0_196M_CLK, PLL_DRAM_MAIN_533M_CLK,
110 PLL_VIDEO_MAIN_CLK, PLL_AUDIO_MAIN_CLK}
111 },
112 {MIPI_DPHY_REF_CLK_ROOT, CCM_IP_CHANNEL,
113 {OSC_24M_CLK, PLL_SYS_MAIN_120M_CLK, PLL_DRAM_MAIN_533M_CLK,
114 PLL_SYS_PFD5_CLK, REF_1M_CLK, EXT_CLK_2,
115 PLL_VIDEO_MAIN_CLK, EXT_CLK_3}
116 },
117 {SAI1_CLK_ROOT, CCM_IP_CHANNEL,
118 {OSC_24M_CLK, PLL_SYS_PFD2_135M_CLK, PLL_AUDIO_MAIN_CLK,
119 PLL_DRAM_MAIN_533M_CLK, PLL_VIDEO_MAIN_CLK, PLL_SYS_PFD4_CLK,
120 PLL_ENET_MAIN_125M_CLK, EXT_CLK_2}
121 },
122 {SAI2_CLK_ROOT, CCM_IP_CHANNEL,
123 {OSC_24M_CLK, PLL_SYS_PFD2_135M_CLK, PLL_AUDIO_MAIN_CLK,
124 PLL_DRAM_MAIN_533M_CLK, PLL_VIDEO_MAIN_CLK, PLL_SYS_PFD4_CLK,
125 PLL_ENET_MAIN_125M_CLK, EXT_CLK_2}
126 },
127 {SAI3_CLK_ROOT, CCM_IP_CHANNEL,
128 {OSC_24M_CLK, PLL_SYS_PFD2_135M_CLK, PLL_AUDIO_MAIN_CLK,
129 PLL_DRAM_MAIN_533M_CLK, PLL_VIDEO_MAIN_CLK, PLL_SYS_PFD4_CLK,
130 PLL_ENET_MAIN_125M_CLK, EXT_CLK_3}
131 },
132 {SPDIF_CLK_ROOT, CCM_IP_CHANNEL,
133 {OSC_24M_CLK, PLL_SYS_PFD2_135M_CLK, PLL_AUDIO_MAIN_CLK,
134 PLL_DRAM_MAIN_533M_CLK, PLL_VIDEO_MAIN_CLK, PLL_SYS_PFD4_CLK,
135 PLL_ENET_MAIN_125M_CLK, EXT_CLK_3}
136 },
137 {ENET1_REF_CLK_ROOT, CCM_IP_CHANNEL,
138 {OSC_24M_CLK, PLL_ENET_MAIN_125M_CLK, PLL_ENET_MAIN_50M_CLK,
139 PLL_ENET_MAIN_25M_CLK, PLL_SYS_MAIN_120M_CLK, PLL_AUDIO_MAIN_CLK,
140 PLL_VIDEO_MAIN_CLK, EXT_CLK_4}
141 },
142 {ENET1_TIME_CLK_ROOT, CCM_IP_CHANNEL,
143 {OSC_24M_CLK, PLL_ENET_MAIN_100M_CLK, PLL_AUDIO_MAIN_CLK,
144 EXT_CLK_1, EXT_CLK_2, EXT_CLK_3,
145 EXT_CLK_4, PLL_VIDEO_MAIN_CLK}
146 },
147 {ENET2_REF_CLK_ROOT, CCM_IP_CHANNEL,
148 {OSC_24M_CLK, PLL_ENET_MAIN_125M_CLK, PLL_ENET_MAIN_50M_CLK,
149 PLL_ENET_MAIN_25M_CLK, PLL_SYS_MAIN_120M_CLK, PLL_AUDIO_MAIN_CLK,
150 PLL_VIDEO_MAIN_CLK, EXT_CLK_4}
151 },
152 {ENET2_TIME_CLK_ROOT, CCM_IP_CHANNEL,
153 {OSC_24M_CLK, PLL_ENET_MAIN_100M_CLK, PLL_AUDIO_MAIN_CLK,
154 EXT_CLK_1, EXT_CLK_2, EXT_CLK_3,
155 EXT_CLK_4, PLL_VIDEO_MAIN_CLK}
156 },
157 {ENET_PHY_REF_CLK_ROOT, CCM_IP_CHANNEL,
158 {OSC_24M_CLK, PLL_ENET_MAIN_25M_CLK, PLL_ENET_MAIN_50M_CLK,
159 PLL_ENET_MAIN_125M_CLK, PLL_DRAM_MAIN_533M_CLK, PLL_AUDIO_MAIN_CLK,
160 PLL_VIDEO_MAIN_CLK, PLL_SYS_PFD3_CLK}
161 },
162 {EIM_CLK_ROOT, CCM_IP_CHANNEL,
163 {OSC_24M_CLK, PLL_SYS_PFD2_135M_CLK, PLL_SYS_MAIN_120M_CLK,
164 PLL_DRAM_MAIN_533M_CLK, PLL_SYS_PFD2_270M_CLK, PLL_SYS_PFD3_CLK,
165 PLL_ENET_MAIN_125M_CLK, PLL_USB_MAIN_480M_CLK}
166 },
167 {NAND_CLK_ROOT, CCM_IP_CHANNEL,
168 {OSC_24M_CLK, PLL_SYS_MAIN_480M_CLK, PLL_DRAM_MAIN_533M_CLK,
169 PLL_SYS_PFD0_392M_CLK, PLL_SYS_PFD3_CLK, PLL_ENET_MAIN_500M_CLK,
170 PLL_ENET_MAIN_250M_CLK, PLL_VIDEO_MAIN_CLK}
171 },
172 {QSPI_CLK_ROOT, CCM_IP_CHANNEL,
173 {OSC_24M_CLK, PLL_SYS_PFD4_CLK, PLL_DRAM_MAIN_533M_CLK,
174 PLL_ENET_MAIN_500M_CLK, PLL_SYS_PFD3_CLK, PLL_SYS_PFD2_270M_CLK,
175 PLL_SYS_PFD6_CLK, PLL_SYS_PFD7_CLK}
176 },
177 {USDHC1_CLK_ROOT, CCM_IP_CHANNEL,
178 {OSC_24M_CLK, PLL_SYS_PFD0_392M_CLK, PLL_DRAM_MAIN_533M_CLK,
179 PLL_ENET_MAIN_500M_CLK, PLL_SYS_PFD4_CLK, PLL_SYS_PFD2_270M_CLK,
180 PLL_SYS_PFD6_CLK, PLL_SYS_PFD7_CLK}
181 },
182 {USDHC2_CLK_ROOT, CCM_IP_CHANNEL,
183 {OSC_24M_CLK, PLL_SYS_PFD0_392M_CLK, PLL_DRAM_MAIN_533M_CLK,
184 PLL_ENET_MAIN_500M_CLK, PLL_SYS_PFD4_CLK, PLL_SYS_PFD2_270M_CLK,
185 PLL_SYS_PFD6_CLK, PLL_SYS_PFD7_CLK}
186 },
187 {USDHC3_CLK_ROOT, CCM_IP_CHANNEL,
188 {OSC_24M_CLK, PLL_SYS_PFD0_392M_CLK, PLL_DRAM_MAIN_533M_CLK,
189 PLL_ENET_MAIN_500M_CLK, PLL_SYS_PFD4_CLK, PLL_SYS_PFD2_270M_CLK,
190 PLL_SYS_PFD6_CLK, PLL_SYS_PFD7_CLK}
191 },
192 {CAN1_CLK_ROOT, CCM_IP_CHANNEL,
193 {OSC_24M_CLK, PLL_SYS_MAIN_120M_CLK, PLL_DRAM_MAIN_533M_CLK,
194 PLL_SYS_MAIN_480M_CLK, PLL_ENET_MAIN_40M_CLK, PLL_USB_MAIN_480M_CLK,
195 EXT_CLK_1, EXT_CLK_4}
196 },
197 {CAN2_CLK_ROOT, CCM_IP_CHANNEL,
198 {OSC_24M_CLK, PLL_SYS_MAIN_120M_CLK, PLL_DRAM_MAIN_533M_CLK,
199 PLL_SYS_MAIN_480M_CLK, PLL_ENET_MAIN_40M_CLK, PLL_USB_MAIN_480M_CLK,
200 EXT_CLK_1, EXT_CLK_3}
201 },
202 {I2C1_CLK_ROOT, CCM_IP_CHANNEL,
203 {OSC_24M_CLK, PLL_SYS_MAIN_120M_CLK, PLL_ENET_MAIN_50M_CLK,
204 PLL_DRAM_MAIN_533M_CLK, PLL_AUDIO_MAIN_CLK, PLL_VIDEO_MAIN_CLK,
205 PLL_USB_MAIN_480M_CLK, PLL_SYS_PFD2_135M_CLK}
206 },
207 {I2C2_CLK_ROOT, CCM_IP_CHANNEL,
208 {OSC_24M_CLK, PLL_SYS_MAIN_120M_CLK, PLL_ENET_MAIN_50M_CLK,
209 PLL_DRAM_MAIN_533M_CLK, PLL_AUDIO_MAIN_CLK, PLL_VIDEO_MAIN_CLK,
210 PLL_USB_MAIN_480M_CLK, PLL_SYS_PFD2_135M_CLK}
211 },
212 {I2C3_CLK_ROOT, CCM_IP_CHANNEL,
213 {OSC_24M_CLK, PLL_SYS_MAIN_120M_CLK, PLL_ENET_MAIN_50M_CLK,
214 PLL_DRAM_MAIN_533M_CLK, PLL_AUDIO_MAIN_CLK, PLL_VIDEO_MAIN_CLK,
215 PLL_USB_MAIN_480M_CLK, PLL_SYS_PFD2_135M_CLK}
216 },
217 {I2C4_CLK_ROOT, CCM_IP_CHANNEL,
218 {OSC_24M_CLK, PLL_SYS_MAIN_120M_CLK, PLL_ENET_MAIN_50M_CLK,
219 PLL_DRAM_MAIN_533M_CLK, PLL_AUDIO_MAIN_CLK, PLL_VIDEO_MAIN_CLK,
220 PLL_USB_MAIN_480M_CLK, PLL_SYS_PFD2_135M_CLK}
221 },
222 {UART1_CLK_ROOT, CCM_IP_CHANNEL,
223 {OSC_24M_CLK, PLL_SYS_MAIN_240M_CLK, PLL_ENET_MAIN_40M_CLK,
224 PLL_ENET_MAIN_100M_CLK, PLL_SYS_MAIN_480M_CLK, EXT_CLK_2,
225 EXT_CLK_4, PLL_USB_MAIN_480M_CLK}
226 },
227 {UART2_CLK_ROOT, CCM_IP_CHANNEL,
228 {OSC_24M_CLK, PLL_SYS_MAIN_240M_CLK, PLL_ENET_MAIN_40M_CLK,
229 PLL_ENET_MAIN_100M_CLK, PLL_SYS_MAIN_480M_CLK, EXT_CLK_2,
230 EXT_CLK_3, PLL_USB_MAIN_480M_CLK}
231 },
232 {UART3_CLK_ROOT, CCM_IP_CHANNEL,
233 {OSC_24M_CLK, PLL_SYS_MAIN_240M_CLK, PLL_ENET_MAIN_40M_CLK,
234 PLL_ENET_MAIN_100M_CLK, PLL_SYS_MAIN_480M_CLK, EXT_CLK_2,
235 EXT_CLK_4, PLL_USB_MAIN_480M_CLK}
236 },
237 {UART4_CLK_ROOT, CCM_IP_CHANNEL,
238 {OSC_24M_CLK, PLL_SYS_MAIN_240M_CLK, PLL_ENET_MAIN_40M_CLK,
239 PLL_ENET_MAIN_100M_CLK, PLL_SYS_MAIN_480M_CLK, EXT_CLK_2,
240 EXT_CLK_3, PLL_USB_MAIN_480M_CLK}
241 },
242 {UART5_CLK_ROOT, CCM_IP_CHANNEL,
243 {OSC_24M_CLK, PLL_SYS_MAIN_240M_CLK, PLL_ENET_MAIN_40M_CLK,
244 PLL_ENET_MAIN_100M_CLK, PLL_SYS_MAIN_480M_CLK, EXT_CLK_2,
245 EXT_CLK_4, PLL_USB_MAIN_480M_CLK}
246 },
247 {UART6_CLK_ROOT, CCM_IP_CHANNEL,
248 {OSC_24M_CLK, PLL_SYS_MAIN_240M_CLK, PLL_ENET_MAIN_40M_CLK,
249 PLL_ENET_MAIN_100M_CLK, PLL_SYS_MAIN_480M_CLK, EXT_CLK_2,
250 EXT_CLK_3, PLL_USB_MAIN_480M_CLK}
251 },
252 {UART7_CLK_ROOT, CCM_IP_CHANNEL,
253 {OSC_24M_CLK, PLL_SYS_MAIN_240M_CLK, PLL_ENET_MAIN_40M_CLK,
254 PLL_ENET_MAIN_100M_CLK, PLL_SYS_MAIN_480M_CLK, EXT_CLK_2,
255 EXT_CLK_4, PLL_USB_MAIN_480M_CLK}
256 },
257 {ECSPI1_CLK_ROOT, CCM_IP_CHANNEL,
258 {OSC_24M_CLK, PLL_SYS_MAIN_240M_CLK, PLL_ENET_MAIN_40M_CLK,
259 PLL_SYS_MAIN_120M_CLK, PLL_SYS_MAIN_480M_CLK, PLL_SYS_PFD4_CLK,
260 PLL_ENET_MAIN_250M_CLK, PLL_USB_MAIN_480M_CLK}
261 },
262 {ECSPI2_CLK_ROOT, CCM_IP_CHANNEL,
263 {OSC_24M_CLK, PLL_SYS_MAIN_240M_CLK, PLL_ENET_MAIN_40M_CLK,
264 PLL_SYS_MAIN_120M_CLK, PLL_SYS_MAIN_480M_CLK, PLL_SYS_PFD4_CLK,
265 PLL_ENET_MAIN_250M_CLK, PLL_USB_MAIN_480M_CLK}
266 },
267 {ECSPI3_CLK_ROOT, CCM_IP_CHANNEL,
268 {OSC_24M_CLK, PLL_SYS_MAIN_240M_CLK, PLL_ENET_MAIN_40M_CLK,
269 PLL_SYS_MAIN_120M_CLK, PLL_SYS_MAIN_480M_CLK, PLL_SYS_PFD4_CLK,
270 PLL_ENET_MAIN_250M_CLK, PLL_USB_MAIN_480M_CLK}
271 },
272 {ECSPI4_CLK_ROOT, CCM_IP_CHANNEL,
273 {OSC_24M_CLK, PLL_SYS_MAIN_240M_CLK, PLL_ENET_MAIN_40M_CLK,
274 PLL_SYS_MAIN_120M_CLK, PLL_SYS_MAIN_480M_CLK, PLL_SYS_PFD4_CLK,
275 PLL_ENET_MAIN_250M_CLK, PLL_USB_MAIN_480M_CLK}
276 },
277 {PWM1_CLK_ROOT, CCM_IP_CHANNEL,
278 {OSC_24M_CLK, PLL_ENET_MAIN_100M_CLK, PLL_SYS_MAIN_120M_CLK,
279 PLL_ENET_MAIN_40M_CLK, PLL_AUDIO_MAIN_CLK, EXT_CLK_1,
280 REF_1M_CLK, PLL_VIDEO_MAIN_CLK}
281 },
282 {PWM2_CLK_ROOT, CCM_IP_CHANNEL,
283 {OSC_24M_CLK, PLL_ENET_MAIN_100M_CLK, PLL_SYS_MAIN_120M_CLK,
284 PLL_ENET_MAIN_40M_CLK, PLL_AUDIO_MAIN_CLK, EXT_CLK_1,
285 REF_1M_CLK, PLL_VIDEO_MAIN_CLK}
286 },
287 {PWM3_CLK_ROOT, CCM_IP_CHANNEL,
288 {OSC_24M_CLK, PLL_ENET_MAIN_100M_CLK, PLL_SYS_MAIN_120M_CLK,
289 PLL_ENET_MAIN_40M_CLK, PLL_AUDIO_MAIN_CLK, EXT_CLK_2,
290 REF_1M_CLK, PLL_VIDEO_MAIN_CLK}
291 },
292 {PWM4_CLK_ROOT, CCM_IP_CHANNEL,
293 {OSC_24M_CLK, PLL_ENET_MAIN_100M_CLK, PLL_SYS_MAIN_120M_CLK,
294 PLL_ENET_MAIN_40M_CLK, PLL_AUDIO_MAIN_CLK, EXT_CLK_2,
295 REF_1M_CLK, PLL_VIDEO_MAIN_CLK}
296 },
297 {FLEXTIMER1_CLK_ROOT, CCM_IP_CHANNEL,
298 {OSC_24M_CLK, PLL_ENET_MAIN_100M_CLK, PLL_SYS_MAIN_120M_CLK,
299 PLL_ENET_MAIN_40M_CLK, PLL_AUDIO_MAIN_CLK, EXT_CLK_3,
300 REF_1M_CLK, PLL_VIDEO_MAIN_CLK}
301 },
302 {FLEXTIMER2_CLK_ROOT, CCM_IP_CHANNEL,
303 {OSC_24M_CLK, PLL_ENET_MAIN_100M_CLK, PLL_SYS_MAIN_120M_CLK,
304 PLL_ENET_MAIN_40M_CLK, PLL_AUDIO_MAIN_CLK, EXT_CLK_3,
305 REF_1M_CLK, PLL_VIDEO_MAIN_CLK}
306 },
307 {SIM1_CLK_ROOT, CCM_IP_CHANNEL,
308 {OSC_24M_CLK, PLL_SYS_PFD2_135M_CLK, PLL_SYS_MAIN_120M_CLK,
309 PLL_DRAM_MAIN_533M_CLK, PLL_USB_MAIN_480M_CLK, PLL_AUDIO_MAIN_CLK,
310 PLL_ENET_MAIN_125M_CLK, PLL_SYS_PFD7_CLK}
311 },
312 {SIM2_CLK_ROOT, CCM_IP_CHANNEL,
313 {OSC_24M_CLK, PLL_SYS_PFD2_135M_CLK, PLL_SYS_MAIN_120M_CLK,
314 PLL_DRAM_MAIN_533M_CLK, PLL_USB_MAIN_480M_CLK, PLL_VIDEO_MAIN_CLK,
315 PLL_ENET_MAIN_125M_CLK, PLL_SYS_PFD7_CLK}
316 },
317 {GPT1_CLK_ROOT, CCM_IP_CHANNEL,
318 {OSC_24M_CLK, PLL_ENET_MAIN_100M_CLK, PLL_SYS_PFD0_392M_CLK,
319 PLL_ENET_MAIN_40M_CLK, PLL_VIDEO_MAIN_CLK, REF_1M_CLK,
320 PLL_AUDIO_MAIN_CLK, EXT_CLK_1}
321 },
322 {GPT2_CLK_ROOT, CCM_IP_CHANNEL,
323 {OSC_24M_CLK, PLL_ENET_MAIN_100M_CLK, PLL_SYS_PFD0_392M_CLK,
324 PLL_ENET_MAIN_40M_CLK, PLL_VIDEO_MAIN_CLK, REF_1M_CLK,
325 PLL_AUDIO_MAIN_CLK, EXT_CLK_2}
326 },
327 {GPT3_CLK_ROOT, CCM_IP_CHANNEL,
328 {OSC_24M_CLK, PLL_ENET_MAIN_100M_CLK, PLL_SYS_PFD0_392M_CLK,
329 PLL_ENET_MAIN_40M_CLK, PLL_VIDEO_MAIN_CLK, REF_1M_CLK,
330 PLL_AUDIO_MAIN_CLK, EXT_CLK_3}
331 },
332 {GPT4_CLK_ROOT, CCM_IP_CHANNEL,
333 {OSC_24M_CLK, PLL_ENET_MAIN_100M_CLK, PLL_SYS_PFD0_392M_CLK,
334 PLL_ENET_MAIN_40M_CLK, PLL_VIDEO_MAIN_CLK, REF_1M_CLK,
335 PLL_AUDIO_MAIN_CLK, EXT_CLK_4}
336 },
337 {TRACE_CLK_ROOT, CCM_IP_CHANNEL,
338 {OSC_24M_CLK, PLL_SYS_PFD2_135M_CLK, PLL_SYS_MAIN_120M_CLK,
339 PLL_DRAM_MAIN_533M_CLK, PLL_ENET_MAIN_125M_CLK, PLL_USB_MAIN_480M_CLK,
340 EXT_CLK_1, EXT_CLK_3}
341 },
342 {WDOG_CLK_ROOT, CCM_IP_CHANNEL,
343 {OSC_24M_CLK, PLL_SYS_PFD2_135M_CLK, PLL_SYS_MAIN_120M_CLK,
344 PLL_DRAM_MAIN_533M_CLK, PLL_ENET_MAIN_125M_CLK, PLL_USB_MAIN_480M_CLK,
345 REF_1M_CLK, PLL_SYS_PFD1_166M_CLK}
346 },
347 {CSI_MCLK_CLK_ROOT, CCM_IP_CHANNEL,
348 {OSC_24M_CLK, PLL_SYS_PFD2_135M_CLK, PLL_SYS_MAIN_120M_CLK,
349 PLL_DRAM_MAIN_533M_CLK, PLL_ENET_MAIN_125M_CLK, PLL_AUDIO_MAIN_CLK,
350 PLL_VIDEO_MAIN_CLK, PLL_USB_MAIN_480M_CLK}
351 },
352 {AUDIO_MCLK_CLK_ROOT, CCM_IP_CHANNEL,
353 {OSC_24M_CLK, PLL_SYS_PFD2_135M_CLK, PLL_SYS_MAIN_120M_CLK,
354 PLL_DRAM_MAIN_533M_CLK, PLL_ENET_MAIN_125M_CLK, PLL_AUDIO_MAIN_CLK,
355 PLL_VIDEO_MAIN_CLK, PLL_USB_MAIN_480M_CLK}
356 },
357 {WRCLK_CLK_ROOT, CCM_IP_CHANNEL,
358 {OSC_24M_CLK, PLL_ENET_MAIN_40M_CLK, PLL_DRAM_MAIN_533M_CLK,
359 PLL_USB_MAIN_480M_CLK, PLL_SYS_MAIN_240M_CLK, PLL_SYS_PFD2_270M_CLK,
360 PLL_ENET_MAIN_500M_CLK, PLL_SYS_PFD7_CLK}
361 },
362 {IPP_DO_CLKO1, CCM_IP_CHANNEL,
363 {OSC_24M_CLK, PLL_SYS_MAIN_480M_CLK, PLL_SYS_MAIN_240M_CLK,
364 PLL_SYS_PFD0_196M_CLK, PLL_SYS_PFD3_CLK, PLL_ENET_MAIN_500M_CLK,
365 PLL_DRAM_MAIN_533M_CLK, REF_1M_CLK}
366 },
367 {IPP_DO_CLKO2, CCM_IP_CHANNEL,
368 {OSC_24M_CLK, PLL_SYS_MAIN_240M_CLK, PLL_SYS_PFD0_392M_CLK,
369 PLL_SYS_PFD1_166M_CLK, PLL_SYS_PFD4_CLK, PLL_AUDIO_MAIN_CLK,
370 PLL_VIDEO_MAIN_CLK, OSC_32K_CLK}
371 },
372 };
373
374 /* select which entry of root_array */
select(enum clk_root_index clock_id)375 static int select(enum clk_root_index clock_id)
376 {
377 int i, size;
378 struct clk_root_map *p = root_array;
379
380 size = ARRAY_SIZE(root_array);
381
382 for (i = 0; i < size; i++, p++) {
383 if (clock_id == p->entry)
384 return i;
385 }
386
387 return -EINVAL;
388 }
389
src_supported(int entry,enum clk_root_src clock_src)390 static int src_supported(int entry, enum clk_root_src clock_src)
391 {
392 int i, size;
393 struct clk_root_map *p = &root_array[entry];
394
395 if ((p->type == CCM_DRAM_PHYM_CHANNEL) || (p->type == CCM_DRAM_CHANNEL))
396 size = 2;
397 else
398 size = 8;
399
400 for (i = 0; i < size; i++) {
401 if (p->src_mux[i] == clock_src)
402 return i;
403 }
404
405 return -EINVAL;
406 }
407
408 /* Set src for clock root slice. */
clock_set_src(enum clk_root_index clock_id,enum clk_root_src clock_src)409 int clock_set_src(enum clk_root_index clock_id, enum clk_root_src clock_src)
410 {
411 int root_entry, src_entry;
412 u32 reg;
413
414 if (clock_id >= CLK_ROOT_MAX)
415 return -EINVAL;
416
417 root_entry = select(clock_id);
418 if (root_entry < 0)
419 return -EINVAL;
420
421 src_entry = src_supported(root_entry, clock_src);
422 if (src_entry < 0)
423 return -EINVAL;
424
425 reg = __raw_readl(&imx_ccm->root[clock_id].target_root);
426 reg &= ~CLK_ROOT_MUX_MASK;
427 reg |= src_entry << CLK_ROOT_MUX_SHIFT;
428 __raw_writel(reg, &imx_ccm->root[clock_id].target_root);
429
430 return 0;
431 }
432
433 /* Get src of a clock root slice. */
clock_get_src(enum clk_root_index clock_id,enum clk_root_src * p_clock_src)434 int clock_get_src(enum clk_root_index clock_id, enum clk_root_src *p_clock_src)
435 {
436 u32 val;
437 int root_entry;
438 struct clk_root_map *p;
439
440 if (clock_id >= CLK_ROOT_MAX)
441 return -EINVAL;
442
443 val = __raw_readl(&imx_ccm->root[clock_id].target_root);
444 val &= CLK_ROOT_MUX_MASK;
445 val >>= CLK_ROOT_MUX_SHIFT;
446
447 root_entry = select(clock_id);
448 if (root_entry < 0)
449 return -EINVAL;
450
451 p = &root_array[root_entry];
452 *p_clock_src = p->src_mux[val];
453
454 return 0;
455 }
456
clock_set_prediv(enum clk_root_index clock_id,enum root_pre_div pre_div)457 int clock_set_prediv(enum clk_root_index clock_id, enum root_pre_div pre_div)
458 {
459 int root_entry;
460 struct clk_root_map *p;
461 u32 reg;
462
463 if (clock_id >= CLK_ROOT_MAX)
464 return -EINVAL;
465
466 root_entry = select(clock_id);
467 if (root_entry < 0)
468 return -EINVAL;
469
470 p = &root_array[root_entry];
471
472 if ((p->type == CCM_CORE_CHANNEL) ||
473 (p->type == CCM_DRAM_PHYM_CHANNEL) ||
474 (p->type == CCM_DRAM_CHANNEL)) {
475 if (pre_div != CLK_ROOT_PRE_DIV1) {
476 printf("Error pre div!\n");
477 return -EINVAL;
478 }
479 }
480
481 reg = __raw_readl(&imx_ccm->root[clock_id].target_root);
482 reg &= ~CLK_ROOT_PRE_DIV_MASK;
483 reg |= pre_div << CLK_ROOT_PRE_DIV_SHIFT;
484 __raw_writel(reg, &imx_ccm->root[clock_id].target_root);
485
486 return 0;
487 }
488
clock_get_prediv(enum clk_root_index clock_id,enum root_pre_div * pre_div)489 int clock_get_prediv(enum clk_root_index clock_id, enum root_pre_div *pre_div)
490 {
491 u32 val;
492 int root_entry;
493 struct clk_root_map *p;
494
495 if (clock_id >= CLK_ROOT_MAX)
496 return -EINVAL;
497
498 root_entry = select(clock_id);
499 if (root_entry < 0)
500 return -EINVAL;
501
502 p = &root_array[root_entry];
503
504 if ((p->type == CCM_CORE_CHANNEL) ||
505 (p->type == CCM_DRAM_PHYM_CHANNEL) ||
506 (p->type == CCM_DRAM_CHANNEL)) {
507 *pre_div = 0;
508 return 0;
509 }
510
511 val = __raw_readl(&imx_ccm->root[clock_id].target_root);
512 val &= CLK_ROOT_PRE_DIV_MASK;
513 val >>= CLK_ROOT_PRE_DIV_SHIFT;
514
515 *pre_div = val;
516
517 return 0;
518 }
519
clock_set_postdiv(enum clk_root_index clock_id,enum root_post_div div)520 int clock_set_postdiv(enum clk_root_index clock_id, enum root_post_div div)
521 {
522 u32 reg;
523
524 if (clock_id >= CLK_ROOT_MAX)
525 return -EINVAL;
526
527 if (clock_id == DRAM_PHYM_CLK_ROOT) {
528 if (div != CLK_ROOT_POST_DIV1) {
529 printf("Error post div!\n");
530 return -EINVAL;
531 }
532 }
533
534 /* Only 3 bit post div. */
535 if ((clock_id == DRAM_CLK_ROOT) && (div > CLK_ROOT_POST_DIV7)) {
536 printf("Error post div!\n");
537 return -EINVAL;
538 }
539
540 reg = __raw_readl(&imx_ccm->root[clock_id].target_root);
541 reg &= ~CLK_ROOT_POST_DIV_MASK;
542 reg |= div << CLK_ROOT_POST_DIV_SHIFT;
543 __raw_writel(reg, &imx_ccm->root[clock_id].target_root);
544
545 return 0;
546 }
547
clock_get_postdiv(enum clk_root_index clock_id,enum root_post_div * div)548 int clock_get_postdiv(enum clk_root_index clock_id, enum root_post_div *div)
549 {
550 u32 val;
551
552 if (clock_id >= CLK_ROOT_MAX)
553 return -EINVAL;
554
555 if (clock_id == DRAM_PHYM_CLK_ROOT) {
556 *div = 0;
557 return 0;
558 }
559
560 val = __raw_readl(&imx_ccm->root[clock_id].target_root);
561 if (clock_id == DRAM_CLK_ROOT)
562 val &= DRAM_CLK_ROOT_POST_DIV_MASK;
563 else
564 val &= CLK_ROOT_POST_DIV_MASK;
565 val >>= CLK_ROOT_POST_DIV_SHIFT;
566
567 *div = val;
568
569 return 0;
570 }
571
clock_set_autopostdiv(enum clk_root_index clock_id,enum root_auto_div div,int auto_en)572 int clock_set_autopostdiv(enum clk_root_index clock_id, enum root_auto_div div,
573 int auto_en)
574 {
575 u32 val;
576 int root_entry;
577 struct clk_root_map *p;
578
579 if (clock_id >= CLK_ROOT_MAX)
580 return -EINVAL;
581
582 root_entry = select(clock_id);
583 if (root_entry < 0)
584 return -EINVAL;
585
586 p = &root_array[root_entry];
587
588 if ((p->type != CCM_BUS_CHANNEL) && (p->type != CCM_AHB_CHANNEL)) {
589 printf("Auto postdiv not supported.!\n");
590 return -EINVAL;
591 }
592
593 /*
594 * Each time only one filed can be changed, no use target_root_set.
595 */
596 val = __raw_readl(&imx_ccm->root[clock_id].target_root);
597 val &= ~CLK_ROOT_AUTO_DIV_MASK;
598 val |= (div << CLK_ROOT_AUTO_DIV_SHIFT);
599
600 if (auto_en)
601 val |= CLK_ROOT_AUTO_EN;
602 else
603 val &= ~CLK_ROOT_AUTO_EN;
604
605 __raw_writel(val, &imx_ccm->root[clock_id].target_root);
606
607 return 0;
608 }
609
clock_get_autopostdiv(enum clk_root_index clock_id,enum root_auto_div * div,int * auto_en)610 int clock_get_autopostdiv(enum clk_root_index clock_id, enum root_auto_div *div,
611 int *auto_en)
612 {
613 u32 val;
614 int root_entry;
615 struct clk_root_map *p;
616
617 if (clock_id >= CLK_ROOT_MAX)
618 return -EINVAL;
619
620 root_entry = select(clock_id);
621 if (root_entry < 0)
622 return -EINVAL;
623
624 p = &root_array[root_entry];
625
626 /*
627 * Only bus/ahb channel supports auto div.
628 * If unsupported, just set auto_en and div with 0.
629 */
630 if ((p->type != CCM_BUS_CHANNEL) && (p->type != CCM_AHB_CHANNEL)) {
631 *auto_en = 0;
632 *div = 0;
633 return 0;
634 }
635
636 val = __raw_readl(&imx_ccm->root[clock_id].target_root);
637 if ((val & CLK_ROOT_AUTO_EN_MASK) == 0)
638 *auto_en = 0;
639 else
640 *auto_en = 1;
641
642 val &= CLK_ROOT_AUTO_DIV_MASK;
643 val >>= CLK_ROOT_AUTO_DIV_SHIFT;
644
645 *div = val;
646
647 return 0;
648 }
649
clock_get_target_val(enum clk_root_index clock_id,u32 * val)650 int clock_get_target_val(enum clk_root_index clock_id, u32 *val)
651 {
652 if (clock_id >= CLK_ROOT_MAX)
653 return -EINVAL;
654
655 *val = __raw_readl(&imx_ccm->root[clock_id].target_root);
656
657 return 0;
658 }
659
clock_set_target_val(enum clk_root_index clock_id,u32 val)660 int clock_set_target_val(enum clk_root_index clock_id, u32 val)
661 {
662 if (clock_id >= CLK_ROOT_MAX)
663 return -EINVAL;
664
665 __raw_writel(val, &imx_ccm->root[clock_id].target_root);
666
667 return 0;
668 }
669
670 /* Auto_div and auto_en is ignored, they are rarely used. */
clock_root_cfg(enum clk_root_index clock_id,enum root_pre_div pre_div,enum root_post_div post_div,enum clk_root_src clock_src)671 int clock_root_cfg(enum clk_root_index clock_id, enum root_pre_div pre_div,
672 enum root_post_div post_div, enum clk_root_src clock_src)
673 {
674 u32 val;
675 int root_entry, src_entry;
676 struct clk_root_map *p;
677
678 if (clock_id >= CLK_ROOT_MAX)
679 return -EINVAL;
680
681 root_entry = select(clock_id);
682 if (root_entry < 0)
683 return -EINVAL;
684
685 p = &root_array[root_entry];
686
687 if ((p->type == CCM_CORE_CHANNEL) ||
688 (p->type == CCM_DRAM_PHYM_CHANNEL) ||
689 (p->type == CCM_DRAM_CHANNEL)) {
690 if (pre_div != CLK_ROOT_PRE_DIV1) {
691 printf("Error pre div!\n");
692 return -EINVAL;
693 }
694 }
695
696 /* Only 3 bit post div. */
697 if (p->type == CCM_DRAM_CHANNEL) {
698 if (post_div > CLK_ROOT_POST_DIV7) {
699 printf("Error post div!\n");
700 return -EINVAL;
701 }
702 }
703
704 if (p->type == CCM_DRAM_PHYM_CHANNEL) {
705 if (post_div != CLK_ROOT_POST_DIV1) {
706 printf("Error post div!\n");
707 return -EINVAL;
708 }
709 }
710
711 src_entry = src_supported(root_entry, clock_src);
712 if (src_entry < 0)
713 return -EINVAL;
714
715 val = CLK_ROOT_ON | pre_div << CLK_ROOT_PRE_DIV_SHIFT |
716 post_div << CLK_ROOT_POST_DIV_SHIFT |
717 src_entry << CLK_ROOT_MUX_SHIFT;
718
719 __raw_writel(val, &imx_ccm->root[clock_id].target_root);
720
721 return 0;
722 }
723
clock_root_enabled(enum clk_root_index clock_id)724 int clock_root_enabled(enum clk_root_index clock_id)
725 {
726 u32 val;
727
728 if (clock_id >= CLK_ROOT_MAX)
729 return -EINVAL;
730
731 /*
732 * No enable bit for DRAM controller and PHY. Just return enabled.
733 */
734 if ((clock_id == DRAM_PHYM_CLK_ROOT) || (clock_id == DRAM_CLK_ROOT))
735 return 1;
736
737 val = __raw_readl(&imx_ccm->root[clock_id].target_root);
738
739 return (val & CLK_ROOT_ENABLE_MASK) ? 1 : 0;
740 }
741
742 /* CCGR gate operation */
clock_enable(enum clk_ccgr_index index,bool enable)743 int clock_enable(enum clk_ccgr_index index, bool enable)
744 {
745 if (index >= CCGR_MAX)
746 return -EINVAL;
747
748 if (enable)
749 __raw_writel(CCM_CLK_ON_MSK,
750 &imx_ccm->ccgr_array[index].ccgr_set);
751 else
752 __raw_writel(CCM_CLK_ON_MSK,
753 &imx_ccm->ccgr_array[index].ccgr_clr);
754
755 return 0;
756 }
757