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