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