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 */
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 
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. */
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. */
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 
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 
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 
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 
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 
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 
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 
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 
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. */
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 
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 */
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