1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Clk driver for NXP LPC18xx/LPC43xx Clock Generation Unit (CGU) |
4 | * |
5 | * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com> |
6 | */ |
7 | |
8 | #include <linux/clk-provider.h> |
9 | #include <linux/delay.h> |
10 | #include <linux/io.h> |
11 | #include <linux/kernel.h> |
12 | #include <linux/of.h> |
13 | #include <linux/of_address.h> |
14 | |
15 | #include <dt-bindings/clock/lpc18xx-cgu.h> |
16 | |
17 | /* Clock Generation Unit (CGU) registers */ |
18 | #define LPC18XX_CGU_XTAL_OSC_CTRL 0x018 |
19 | #define LPC18XX_CGU_PLL0USB_STAT 0x01c |
20 | #define LPC18XX_CGU_PLL0USB_CTRL 0x020 |
21 | #define LPC18XX_CGU_PLL0USB_MDIV 0x024 |
22 | #define LPC18XX_CGU_PLL0USB_NP_DIV 0x028 |
23 | #define LPC18XX_CGU_PLL0AUDIO_STAT 0x02c |
24 | #define LPC18XX_CGU_PLL0AUDIO_CTRL 0x030 |
25 | #define LPC18XX_CGU_PLL0AUDIO_MDIV 0x034 |
26 | #define LPC18XX_CGU_PLL0AUDIO_NP_DIV 0x038 |
27 | #define LPC18XX_CGU_PLL0AUDIO_FRAC 0x03c |
28 | #define LPC18XX_CGU_PLL1_STAT 0x040 |
29 | #define LPC18XX_CGU_PLL1_CTRL 0x044 |
30 | #define LPC18XX_PLL1_CTRL_FBSEL BIT(6) |
31 | #define LPC18XX_PLL1_CTRL_DIRECT BIT(7) |
32 | #define LPC18XX_CGU_IDIV_CTRL(n) (0x048 + (n) * sizeof(u32)) |
33 | #define LPC18XX_CGU_BASE_CLK(id) (0x05c + (id) * sizeof(u32)) |
34 | #define LPC18XX_CGU_PLL_CTRL_OFFSET 0x4 |
35 | |
36 | /* PLL0 bits common to both audio and USB PLL */ |
37 | #define LPC18XX_PLL0_STAT_LOCK BIT(0) |
38 | #define LPC18XX_PLL0_CTRL_PD BIT(0) |
39 | #define LPC18XX_PLL0_CTRL_BYPASS BIT(1) |
40 | #define LPC18XX_PLL0_CTRL_DIRECTI BIT(2) |
41 | #define LPC18XX_PLL0_CTRL_DIRECTO BIT(3) |
42 | #define LPC18XX_PLL0_CTRL_CLKEN BIT(4) |
43 | #define LPC18XX_PLL0_MDIV_MDEC_MASK 0x1ffff |
44 | #define LPC18XX_PLL0_MDIV_SELP_SHIFT 17 |
45 | #define LPC18XX_PLL0_MDIV_SELI_SHIFT 22 |
46 | #define LPC18XX_PLL0_MSEL_MAX BIT(15) |
47 | |
48 | /* Register value that gives PLL0 post/pre dividers equal to 1 */ |
49 | #define LPC18XX_PLL0_NP_DIVS_1 0x00302062 |
50 | |
51 | enum { |
52 | CLK_SRC_OSC32, |
53 | CLK_SRC_IRC, |
54 | CLK_SRC_ENET_RX_CLK, |
55 | CLK_SRC_ENET_TX_CLK, |
56 | CLK_SRC_GP_CLKIN, |
57 | CLK_SRC_RESERVED1, |
58 | CLK_SRC_OSC, |
59 | CLK_SRC_PLL0USB, |
60 | CLK_SRC_PLL0AUDIO, |
61 | CLK_SRC_PLL1, |
62 | CLK_SRC_RESERVED2, |
63 | CLK_SRC_RESERVED3, |
64 | CLK_SRC_IDIVA, |
65 | CLK_SRC_IDIVB, |
66 | CLK_SRC_IDIVC, |
67 | CLK_SRC_IDIVD, |
68 | CLK_SRC_IDIVE, |
69 | CLK_SRC_MAX |
70 | }; |
71 | |
72 | static const char *clk_src_names[CLK_SRC_MAX] = { |
73 | [CLK_SRC_OSC32] = "osc32" , |
74 | [CLK_SRC_IRC] = "irc" , |
75 | [CLK_SRC_ENET_RX_CLK] = "enet_rx_clk" , |
76 | [CLK_SRC_ENET_TX_CLK] = "enet_tx_clk" , |
77 | [CLK_SRC_GP_CLKIN] = "gp_clkin" , |
78 | [CLK_SRC_OSC] = "osc" , |
79 | [CLK_SRC_PLL0USB] = "pll0usb" , |
80 | [CLK_SRC_PLL0AUDIO] = "pll0audio" , |
81 | [CLK_SRC_PLL1] = "pll1" , |
82 | [CLK_SRC_IDIVA] = "idiva" , |
83 | [CLK_SRC_IDIVB] = "idivb" , |
84 | [CLK_SRC_IDIVC] = "idivc" , |
85 | [CLK_SRC_IDIVD] = "idivd" , |
86 | [CLK_SRC_IDIVE] = "idive" , |
87 | }; |
88 | |
89 | static const char *clk_base_names[BASE_CLK_MAX] = { |
90 | [BASE_SAFE_CLK] = "base_safe_clk" , |
91 | [BASE_USB0_CLK] = "base_usb0_clk" , |
92 | [BASE_PERIPH_CLK] = "base_periph_clk" , |
93 | [BASE_USB1_CLK] = "base_usb1_clk" , |
94 | [BASE_CPU_CLK] = "base_cpu_clk" , |
95 | [BASE_SPIFI_CLK] = "base_spifi_clk" , |
96 | [BASE_SPI_CLK] = "base_spi_clk" , |
97 | [BASE_PHY_RX_CLK] = "base_phy_rx_clk" , |
98 | [BASE_PHY_TX_CLK] = "base_phy_tx_clk" , |
99 | [BASE_APB1_CLK] = "base_apb1_clk" , |
100 | [BASE_APB3_CLK] = "base_apb3_clk" , |
101 | [BASE_LCD_CLK] = "base_lcd_clk" , |
102 | [BASE_ADCHS_CLK] = "base_adchs_clk" , |
103 | [BASE_SDIO_CLK] = "base_sdio_clk" , |
104 | [BASE_SSP0_CLK] = "base_ssp0_clk" , |
105 | [BASE_SSP1_CLK] = "base_ssp1_clk" , |
106 | [BASE_UART0_CLK] = "base_uart0_clk" , |
107 | [BASE_UART1_CLK] = "base_uart1_clk" , |
108 | [BASE_UART2_CLK] = "base_uart2_clk" , |
109 | [BASE_UART3_CLK] = "base_uart3_clk" , |
110 | [BASE_OUT_CLK] = "base_out_clk" , |
111 | [BASE_AUDIO_CLK] = "base_audio_clk" , |
112 | [BASE_CGU_OUT0_CLK] = "base_cgu_out0_clk" , |
113 | [BASE_CGU_OUT1_CLK] = "base_cgu_out1_clk" , |
114 | }; |
115 | |
116 | static u32 lpc18xx_cgu_pll0_src_ids[] = { |
117 | CLK_SRC_OSC32, CLK_SRC_IRC, CLK_SRC_ENET_RX_CLK, |
118 | CLK_SRC_ENET_TX_CLK, CLK_SRC_GP_CLKIN, CLK_SRC_OSC, |
119 | CLK_SRC_PLL1, CLK_SRC_IDIVA, CLK_SRC_IDIVB, CLK_SRC_IDIVC, |
120 | CLK_SRC_IDIVD, CLK_SRC_IDIVE, |
121 | }; |
122 | |
123 | static u32 lpc18xx_cgu_pll1_src_ids[] = { |
124 | CLK_SRC_OSC32, CLK_SRC_IRC, CLK_SRC_ENET_RX_CLK, |
125 | CLK_SRC_ENET_TX_CLK, CLK_SRC_GP_CLKIN, CLK_SRC_OSC, |
126 | CLK_SRC_PLL0USB, CLK_SRC_PLL0AUDIO, CLK_SRC_IDIVA, |
127 | CLK_SRC_IDIVB, CLK_SRC_IDIVC, CLK_SRC_IDIVD, CLK_SRC_IDIVE, |
128 | }; |
129 | |
130 | static u32 lpc18xx_cgu_idiva_src_ids[] = { |
131 | CLK_SRC_OSC32, CLK_SRC_IRC, CLK_SRC_ENET_RX_CLK, |
132 | CLK_SRC_ENET_TX_CLK, CLK_SRC_GP_CLKIN, CLK_SRC_OSC, |
133 | CLK_SRC_PLL0USB, CLK_SRC_PLL0AUDIO, CLK_SRC_PLL1 |
134 | }; |
135 | |
136 | static u32 lpc18xx_cgu_idivbcde_src_ids[] = { |
137 | CLK_SRC_OSC32, CLK_SRC_IRC, CLK_SRC_ENET_RX_CLK, |
138 | CLK_SRC_ENET_TX_CLK, CLK_SRC_GP_CLKIN, CLK_SRC_OSC, |
139 | CLK_SRC_PLL0AUDIO, CLK_SRC_PLL1, CLK_SRC_IDIVA, |
140 | }; |
141 | |
142 | static u32 lpc18xx_cgu_base_irc_src_ids[] = {CLK_SRC_IRC}; |
143 | |
144 | static u32 lpc18xx_cgu_base_usb0_src_ids[] = {CLK_SRC_PLL0USB}; |
145 | |
146 | static u32 lpc18xx_cgu_base_common_src_ids[] = { |
147 | CLK_SRC_OSC32, CLK_SRC_IRC, CLK_SRC_ENET_RX_CLK, |
148 | CLK_SRC_ENET_TX_CLK, CLK_SRC_GP_CLKIN, CLK_SRC_OSC, |
149 | CLK_SRC_PLL0AUDIO, CLK_SRC_PLL1, CLK_SRC_IDIVA, |
150 | CLK_SRC_IDIVB, CLK_SRC_IDIVC, CLK_SRC_IDIVD, CLK_SRC_IDIVE, |
151 | }; |
152 | |
153 | static u32 lpc18xx_cgu_base_all_src_ids[] = { |
154 | CLK_SRC_OSC32, CLK_SRC_IRC, CLK_SRC_ENET_RX_CLK, |
155 | CLK_SRC_ENET_TX_CLK, CLK_SRC_GP_CLKIN, CLK_SRC_OSC, |
156 | CLK_SRC_PLL0USB, CLK_SRC_PLL0AUDIO, CLK_SRC_PLL1, |
157 | CLK_SRC_IDIVA, CLK_SRC_IDIVB, CLK_SRC_IDIVC, |
158 | CLK_SRC_IDIVD, CLK_SRC_IDIVE, |
159 | }; |
160 | |
161 | struct lpc18xx_cgu_src_clk_div { |
162 | u8 clk_id; |
163 | u8 n_parents; |
164 | struct clk_divider div; |
165 | struct clk_mux mux; |
166 | struct clk_gate gate; |
167 | }; |
168 | |
169 | #define LPC1XX_CGU_SRC_CLK_DIV(_id, _width, _table) \ |
170 | { \ |
171 | .clk_id = CLK_SRC_ ##_id, \ |
172 | .n_parents = ARRAY_SIZE(lpc18xx_cgu_ ##_table), \ |
173 | .div = { \ |
174 | .shift = 2, \ |
175 | .width = _width, \ |
176 | }, \ |
177 | .mux = { \ |
178 | .mask = 0x1f, \ |
179 | .shift = 24, \ |
180 | .table = lpc18xx_cgu_ ##_table, \ |
181 | }, \ |
182 | .gate = { \ |
183 | .bit_idx = 0, \ |
184 | .flags = CLK_GATE_SET_TO_DISABLE, \ |
185 | }, \ |
186 | } |
187 | |
188 | static struct lpc18xx_cgu_src_clk_div lpc18xx_cgu_src_clk_divs[] = { |
189 | LPC1XX_CGU_SRC_CLK_DIV(IDIVA, 2, idiva_src_ids), |
190 | LPC1XX_CGU_SRC_CLK_DIV(IDIVB, 4, idivbcde_src_ids), |
191 | LPC1XX_CGU_SRC_CLK_DIV(IDIVC, 4, idivbcde_src_ids), |
192 | LPC1XX_CGU_SRC_CLK_DIV(IDIVD, 4, idivbcde_src_ids), |
193 | LPC1XX_CGU_SRC_CLK_DIV(IDIVE, 8, idivbcde_src_ids), |
194 | }; |
195 | |
196 | struct lpc18xx_cgu_base_clk { |
197 | u8 clk_id; |
198 | u8 n_parents; |
199 | struct clk_mux mux; |
200 | struct clk_gate gate; |
201 | }; |
202 | |
203 | #define LPC1XX_CGU_BASE_CLK(_id, _table, _flags) \ |
204 | { \ |
205 | .clk_id = BASE_ ##_id ##_CLK, \ |
206 | .n_parents = ARRAY_SIZE(lpc18xx_cgu_ ##_table), \ |
207 | .mux = { \ |
208 | .mask = 0x1f, \ |
209 | .shift = 24, \ |
210 | .table = lpc18xx_cgu_ ##_table, \ |
211 | .flags = _flags, \ |
212 | }, \ |
213 | .gate = { \ |
214 | .bit_idx = 0, \ |
215 | .flags = CLK_GATE_SET_TO_DISABLE, \ |
216 | }, \ |
217 | } |
218 | |
219 | static struct lpc18xx_cgu_base_clk lpc18xx_cgu_base_clks[] = { |
220 | LPC1XX_CGU_BASE_CLK(SAFE, base_irc_src_ids, CLK_MUX_READ_ONLY), |
221 | LPC1XX_CGU_BASE_CLK(USB0, base_usb0_src_ids, 0), |
222 | LPC1XX_CGU_BASE_CLK(PERIPH, base_common_src_ids, 0), |
223 | LPC1XX_CGU_BASE_CLK(USB1, base_all_src_ids, 0), |
224 | LPC1XX_CGU_BASE_CLK(CPU, base_common_src_ids, 0), |
225 | LPC1XX_CGU_BASE_CLK(SPIFI, base_common_src_ids, 0), |
226 | LPC1XX_CGU_BASE_CLK(SPI, base_common_src_ids, 0), |
227 | LPC1XX_CGU_BASE_CLK(PHY_RX, base_common_src_ids, 0), |
228 | LPC1XX_CGU_BASE_CLK(PHY_TX, base_common_src_ids, 0), |
229 | LPC1XX_CGU_BASE_CLK(APB1, base_common_src_ids, 0), |
230 | LPC1XX_CGU_BASE_CLK(APB3, base_common_src_ids, 0), |
231 | LPC1XX_CGU_BASE_CLK(LCD, base_common_src_ids, 0), |
232 | LPC1XX_CGU_BASE_CLK(ADCHS, base_common_src_ids, 0), |
233 | LPC1XX_CGU_BASE_CLK(SDIO, base_common_src_ids, 0), |
234 | LPC1XX_CGU_BASE_CLK(SSP0, base_common_src_ids, 0), |
235 | LPC1XX_CGU_BASE_CLK(SSP1, base_common_src_ids, 0), |
236 | LPC1XX_CGU_BASE_CLK(UART0, base_common_src_ids, 0), |
237 | LPC1XX_CGU_BASE_CLK(UART1, base_common_src_ids, 0), |
238 | LPC1XX_CGU_BASE_CLK(UART2, base_common_src_ids, 0), |
239 | LPC1XX_CGU_BASE_CLK(UART3, base_common_src_ids, 0), |
240 | LPC1XX_CGU_BASE_CLK(OUT, base_all_src_ids, 0), |
241 | { /* 21 reserved */ }, |
242 | { /* 22 reserved */ }, |
243 | { /* 23 reserved */ }, |
244 | { /* 24 reserved */ }, |
245 | LPC1XX_CGU_BASE_CLK(AUDIO, base_common_src_ids, 0), |
246 | LPC1XX_CGU_BASE_CLK(CGU_OUT0, base_all_src_ids, 0), |
247 | LPC1XX_CGU_BASE_CLK(CGU_OUT1, base_all_src_ids, 0), |
248 | }; |
249 | |
250 | struct lpc18xx_pll { |
251 | struct clk_hw hw; |
252 | void __iomem *reg; |
253 | spinlock_t *lock; |
254 | u8 flags; |
255 | }; |
256 | |
257 | #define to_lpc_pll(hw) container_of(hw, struct lpc18xx_pll, hw) |
258 | |
259 | struct lpc18xx_cgu_pll_clk { |
260 | u8 clk_id; |
261 | u8 n_parents; |
262 | u8 reg_offset; |
263 | struct clk_mux mux; |
264 | struct clk_gate gate; |
265 | struct lpc18xx_pll pll; |
266 | const struct clk_ops *pll_ops; |
267 | }; |
268 | |
269 | #define LPC1XX_CGU_CLK_PLL(_id, _table, _pll_ops) \ |
270 | { \ |
271 | .clk_id = CLK_SRC_ ##_id, \ |
272 | .n_parents = ARRAY_SIZE(lpc18xx_cgu_ ##_table), \ |
273 | .reg_offset = LPC18XX_CGU_ ##_id ##_STAT, \ |
274 | .mux = { \ |
275 | .mask = 0x1f, \ |
276 | .shift = 24, \ |
277 | .table = lpc18xx_cgu_ ##_table, \ |
278 | }, \ |
279 | .gate = { \ |
280 | .bit_idx = 0, \ |
281 | .flags = CLK_GATE_SET_TO_DISABLE, \ |
282 | }, \ |
283 | .pll_ops = &lpc18xx_ ##_pll_ops, \ |
284 | } |
285 | |
286 | /* |
287 | * PLL0 uses a special register value encoding. The compute functions below |
288 | * are taken or derived from the LPC1850 user manual (section 12.6.3.3). |
289 | */ |
290 | |
291 | /* Compute PLL0 multiplier from decoded version */ |
292 | static u32 lpc18xx_pll0_mdec2msel(u32 x) |
293 | { |
294 | int i; |
295 | |
296 | switch (x) { |
297 | case 0x18003: return 1; |
298 | case 0x10003: return 2; |
299 | default: |
300 | for (i = LPC18XX_PLL0_MSEL_MAX + 1; x != 0x4000 && i > 0; i--) |
301 | x = ((x ^ x >> 14) & 1) | (x << 1 & 0x7fff); |
302 | return i; |
303 | } |
304 | } |
305 | /* Compute PLL0 decoded multiplier from binary version */ |
306 | static u32 lpc18xx_pll0_msel2mdec(u32 msel) |
307 | { |
308 | u32 i, x = 0x4000; |
309 | |
310 | switch (msel) { |
311 | case 0: return 0; |
312 | case 1: return 0x18003; |
313 | case 2: return 0x10003; |
314 | default: |
315 | for (i = msel; i <= LPC18XX_PLL0_MSEL_MAX; i++) |
316 | x = ((x ^ x >> 1) & 1) << 14 | (x >> 1 & 0xffff); |
317 | return x; |
318 | } |
319 | } |
320 | |
321 | /* Compute PLL0 bandwidth SELI reg from multiplier */ |
322 | static u32 lpc18xx_pll0_msel2seli(u32 msel) |
323 | { |
324 | u32 tmp; |
325 | |
326 | if (msel > 16384) return 1; |
327 | if (msel > 8192) return 2; |
328 | if (msel > 2048) return 4; |
329 | if (msel >= 501) return 8; |
330 | if (msel >= 60) { |
331 | tmp = 1024 / (msel + 9); |
332 | return ((1024 == (tmp * (msel + 9))) == 0) ? tmp * 4 : (tmp + 1) * 4; |
333 | } |
334 | |
335 | return (msel & 0x3c) + 4; |
336 | } |
337 | |
338 | /* Compute PLL0 bandwidth SELP reg from multiplier */ |
339 | static u32 lpc18xx_pll0_msel2selp(u32 msel) |
340 | { |
341 | if (msel < 60) |
342 | return (msel >> 1) + 1; |
343 | |
344 | return 31; |
345 | } |
346 | |
347 | static unsigned long lpc18xx_pll0_recalc_rate(struct clk_hw *hw, |
348 | unsigned long parent_rate) |
349 | { |
350 | struct lpc18xx_pll *pll = to_lpc_pll(hw); |
351 | u32 ctrl, mdiv, msel, npdiv; |
352 | |
353 | ctrl = readl(addr: pll->reg + LPC18XX_CGU_PLL0USB_CTRL); |
354 | mdiv = readl(addr: pll->reg + LPC18XX_CGU_PLL0USB_MDIV); |
355 | npdiv = readl(addr: pll->reg + LPC18XX_CGU_PLL0USB_NP_DIV); |
356 | |
357 | if (ctrl & LPC18XX_PLL0_CTRL_BYPASS) |
358 | return parent_rate; |
359 | |
360 | if (npdiv != LPC18XX_PLL0_NP_DIVS_1) { |
361 | pr_warn("%s: pre/post dividers not supported\n" , __func__); |
362 | return 0; |
363 | } |
364 | |
365 | msel = lpc18xx_pll0_mdec2msel(x: mdiv & LPC18XX_PLL0_MDIV_MDEC_MASK); |
366 | if (msel) |
367 | return 2 * msel * parent_rate; |
368 | |
369 | pr_warn("%s: unable to calculate rate\n" , __func__); |
370 | |
371 | return 0; |
372 | } |
373 | |
374 | static long lpc18xx_pll0_round_rate(struct clk_hw *hw, unsigned long rate, |
375 | unsigned long *prate) |
376 | { |
377 | unsigned long m; |
378 | |
379 | if (*prate < rate) { |
380 | pr_warn("%s: pll dividers not supported\n" , __func__); |
381 | return -EINVAL; |
382 | } |
383 | |
384 | m = DIV_ROUND_UP_ULL(*prate, rate * 2); |
385 | if (m <= 0 && m > LPC18XX_PLL0_MSEL_MAX) { |
386 | pr_warn("%s: unable to support rate %lu\n" , __func__, rate); |
387 | return -EINVAL; |
388 | } |
389 | |
390 | return 2 * *prate * m; |
391 | } |
392 | |
393 | static int lpc18xx_pll0_set_rate(struct clk_hw *hw, unsigned long rate, |
394 | unsigned long parent_rate) |
395 | { |
396 | struct lpc18xx_pll *pll = to_lpc_pll(hw); |
397 | u32 ctrl, stat, m; |
398 | int retry = 3; |
399 | |
400 | if (parent_rate < rate) { |
401 | pr_warn("%s: pll dividers not supported\n" , __func__); |
402 | return -EINVAL; |
403 | } |
404 | |
405 | m = DIV_ROUND_UP_ULL(parent_rate, rate * 2); |
406 | if (m <= 0 && m > LPC18XX_PLL0_MSEL_MAX) { |
407 | pr_warn("%s: unable to support rate %lu\n" , __func__, rate); |
408 | return -EINVAL; |
409 | } |
410 | |
411 | m = lpc18xx_pll0_msel2mdec(msel: m); |
412 | m |= lpc18xx_pll0_msel2selp(msel: m) << LPC18XX_PLL0_MDIV_SELP_SHIFT; |
413 | m |= lpc18xx_pll0_msel2seli(msel: m) << LPC18XX_PLL0_MDIV_SELI_SHIFT; |
414 | |
415 | /* Power down PLL, disable clk output and dividers */ |
416 | ctrl = readl(addr: pll->reg + LPC18XX_CGU_PLL0USB_CTRL); |
417 | ctrl |= LPC18XX_PLL0_CTRL_PD; |
418 | ctrl &= ~(LPC18XX_PLL0_CTRL_BYPASS | LPC18XX_PLL0_CTRL_DIRECTI | |
419 | LPC18XX_PLL0_CTRL_DIRECTO | LPC18XX_PLL0_CTRL_CLKEN); |
420 | writel(val: ctrl, addr: pll->reg + LPC18XX_CGU_PLL0USB_CTRL); |
421 | |
422 | /* Configure new PLL settings */ |
423 | writel(val: m, addr: pll->reg + LPC18XX_CGU_PLL0USB_MDIV); |
424 | writel(LPC18XX_PLL0_NP_DIVS_1, addr: pll->reg + LPC18XX_CGU_PLL0USB_NP_DIV); |
425 | |
426 | /* Power up PLL and wait for lock */ |
427 | ctrl &= ~LPC18XX_PLL0_CTRL_PD; |
428 | writel(val: ctrl, addr: pll->reg + LPC18XX_CGU_PLL0USB_CTRL); |
429 | do { |
430 | udelay(10); |
431 | stat = readl(addr: pll->reg + LPC18XX_CGU_PLL0USB_STAT); |
432 | if (stat & LPC18XX_PLL0_STAT_LOCK) { |
433 | ctrl |= LPC18XX_PLL0_CTRL_CLKEN; |
434 | writel(val: ctrl, addr: pll->reg + LPC18XX_CGU_PLL0USB_CTRL); |
435 | |
436 | return 0; |
437 | } |
438 | } while (retry--); |
439 | |
440 | pr_warn("%s: unable to lock pll\n" , __func__); |
441 | |
442 | return -EINVAL; |
443 | } |
444 | |
445 | static const struct clk_ops lpc18xx_pll0_ops = { |
446 | .recalc_rate = lpc18xx_pll0_recalc_rate, |
447 | .round_rate = lpc18xx_pll0_round_rate, |
448 | .set_rate = lpc18xx_pll0_set_rate, |
449 | }; |
450 | |
451 | static unsigned long lpc18xx_pll1_recalc_rate(struct clk_hw *hw, |
452 | unsigned long parent_rate) |
453 | { |
454 | struct lpc18xx_pll *pll = to_lpc_pll(hw); |
455 | u16 msel, nsel, psel; |
456 | bool direct, fbsel; |
457 | u32 ctrl; |
458 | |
459 | ctrl = readl(addr: pll->reg + LPC18XX_CGU_PLL1_CTRL); |
460 | |
461 | direct = (ctrl & LPC18XX_PLL1_CTRL_DIRECT) ? true : false; |
462 | fbsel = (ctrl & LPC18XX_PLL1_CTRL_FBSEL) ? true : false; |
463 | |
464 | msel = ((ctrl >> 16) & 0xff) + 1; |
465 | nsel = ((ctrl >> 12) & 0x3) + 1; |
466 | |
467 | if (direct || fbsel) |
468 | return msel * (parent_rate / nsel); |
469 | |
470 | psel = (ctrl >> 8) & 0x3; |
471 | psel = 1 << psel; |
472 | |
473 | return (msel / (2 * psel)) * (parent_rate / nsel); |
474 | } |
475 | |
476 | static const struct clk_ops lpc18xx_pll1_ops = { |
477 | .recalc_rate = lpc18xx_pll1_recalc_rate, |
478 | }; |
479 | |
480 | static int lpc18xx_cgu_gate_enable(struct clk_hw *hw) |
481 | { |
482 | return clk_gate_ops.enable(hw); |
483 | } |
484 | |
485 | static void lpc18xx_cgu_gate_disable(struct clk_hw *hw) |
486 | { |
487 | clk_gate_ops.disable(hw); |
488 | } |
489 | |
490 | static int lpc18xx_cgu_gate_is_enabled(struct clk_hw *hw) |
491 | { |
492 | const struct clk_hw *parent; |
493 | |
494 | /* |
495 | * The consumer of base clocks needs know if the |
496 | * base clock is really enabled before it can be |
497 | * accessed. It is therefore necessary to verify |
498 | * this all the way up. |
499 | */ |
500 | parent = clk_hw_get_parent(hw); |
501 | if (!parent) |
502 | return 0; |
503 | |
504 | if (!clk_hw_is_enabled(hw: parent)) |
505 | return 0; |
506 | |
507 | return clk_gate_ops.is_enabled(hw); |
508 | } |
509 | |
510 | static const struct clk_ops lpc18xx_gate_ops = { |
511 | .enable = lpc18xx_cgu_gate_enable, |
512 | .disable = lpc18xx_cgu_gate_disable, |
513 | .is_enabled = lpc18xx_cgu_gate_is_enabled, |
514 | }; |
515 | |
516 | static struct lpc18xx_cgu_pll_clk lpc18xx_cgu_src_clk_plls[] = { |
517 | LPC1XX_CGU_CLK_PLL(PLL0USB, pll0_src_ids, pll0_ops), |
518 | LPC1XX_CGU_CLK_PLL(PLL0AUDIO, pll0_src_ids, pll0_ops), |
519 | LPC1XX_CGU_CLK_PLL(PLL1, pll1_src_ids, pll1_ops), |
520 | }; |
521 | |
522 | static void lpc18xx_fill_parent_names(const char **parent, const u32 *id, int size) |
523 | { |
524 | int i; |
525 | |
526 | for (i = 0; i < size; i++) |
527 | parent[i] = clk_src_names[id[i]]; |
528 | } |
529 | |
530 | static struct clk *lpc18xx_cgu_register_div(struct lpc18xx_cgu_src_clk_div *clk, |
531 | void __iomem *base, int n) |
532 | { |
533 | void __iomem *reg = base + LPC18XX_CGU_IDIV_CTRL(n); |
534 | const char *name = clk_src_names[clk->clk_id]; |
535 | const char *parents[CLK_SRC_MAX]; |
536 | |
537 | clk->div.reg = reg; |
538 | clk->mux.reg = reg; |
539 | clk->gate.reg = reg; |
540 | |
541 | lpc18xx_fill_parent_names(parent: parents, id: clk->mux.table, size: clk->n_parents); |
542 | |
543 | return clk_register_composite(NULL, name, parent_names: parents, num_parents: clk->n_parents, |
544 | mux_hw: &clk->mux.hw, mux_ops: &clk_mux_ops, |
545 | rate_hw: &clk->div.hw, rate_ops: &clk_divider_ops, |
546 | gate_hw: &clk->gate.hw, gate_ops: &lpc18xx_gate_ops, flags: 0); |
547 | } |
548 | |
549 | |
550 | static struct clk *lpc18xx_register_base_clk(struct lpc18xx_cgu_base_clk *clk, |
551 | void __iomem *reg_base, int n) |
552 | { |
553 | void __iomem *reg = reg_base + LPC18XX_CGU_BASE_CLK(n); |
554 | const char *name = clk_base_names[clk->clk_id]; |
555 | const char *parents[CLK_SRC_MAX]; |
556 | |
557 | if (clk->n_parents == 0) |
558 | return ERR_PTR(error: -ENOENT); |
559 | |
560 | clk->mux.reg = reg; |
561 | clk->gate.reg = reg; |
562 | |
563 | lpc18xx_fill_parent_names(parent: parents, id: clk->mux.table, size: clk->n_parents); |
564 | |
565 | /* SAFE_CLK can not be turned off */ |
566 | if (n == BASE_SAFE_CLK) |
567 | return clk_register_composite(NULL, name, parent_names: parents, num_parents: clk->n_parents, |
568 | mux_hw: &clk->mux.hw, mux_ops: &clk_mux_ops, |
569 | NULL, NULL, NULL, NULL, flags: 0); |
570 | |
571 | return clk_register_composite(NULL, name, parent_names: parents, num_parents: clk->n_parents, |
572 | mux_hw: &clk->mux.hw, mux_ops: &clk_mux_ops, |
573 | NULL, NULL, |
574 | gate_hw: &clk->gate.hw, gate_ops: &lpc18xx_gate_ops, flags: 0); |
575 | } |
576 | |
577 | |
578 | static struct clk *lpc18xx_cgu_register_pll(struct lpc18xx_cgu_pll_clk *clk, |
579 | void __iomem *base) |
580 | { |
581 | const char *name = clk_src_names[clk->clk_id]; |
582 | const char *parents[CLK_SRC_MAX]; |
583 | |
584 | clk->pll.reg = base; |
585 | clk->mux.reg = base + clk->reg_offset + LPC18XX_CGU_PLL_CTRL_OFFSET; |
586 | clk->gate.reg = base + clk->reg_offset + LPC18XX_CGU_PLL_CTRL_OFFSET; |
587 | |
588 | lpc18xx_fill_parent_names(parent: parents, id: clk->mux.table, size: clk->n_parents); |
589 | |
590 | return clk_register_composite(NULL, name, parent_names: parents, num_parents: clk->n_parents, |
591 | mux_hw: &clk->mux.hw, mux_ops: &clk_mux_ops, |
592 | rate_hw: &clk->pll.hw, rate_ops: clk->pll_ops, |
593 | gate_hw: &clk->gate.hw, gate_ops: &lpc18xx_gate_ops, flags: 0); |
594 | } |
595 | |
596 | static void __init lpc18xx_cgu_register_source_clks(struct device_node *np, |
597 | void __iomem *base) |
598 | { |
599 | const char *parents[CLK_SRC_MAX]; |
600 | struct clk *clk; |
601 | int i; |
602 | |
603 | /* Register the internal 12 MHz RC oscillator (IRC) */ |
604 | clk = clk_register_fixed_rate(NULL, name: clk_src_names[CLK_SRC_IRC], |
605 | NULL, flags: 0, fixed_rate: 12000000); |
606 | if (IS_ERR(ptr: clk)) |
607 | pr_warn("%s: failed to register irc clk\n" , __func__); |
608 | |
609 | /* Register crystal oscillator controller */ |
610 | parents[0] = of_clk_get_parent_name(np, index: 0); |
611 | clk = clk_register_gate(NULL, name: clk_src_names[CLK_SRC_OSC], parent_name: parents[0], |
612 | flags: 0, reg: base + LPC18XX_CGU_XTAL_OSC_CTRL, |
613 | bit_idx: 0, CLK_GATE_SET_TO_DISABLE, NULL); |
614 | if (IS_ERR(ptr: clk)) |
615 | pr_warn("%s: failed to register osc clk\n" , __func__); |
616 | |
617 | /* Register all PLLs */ |
618 | for (i = 0; i < ARRAY_SIZE(lpc18xx_cgu_src_clk_plls); i++) { |
619 | clk = lpc18xx_cgu_register_pll(clk: &lpc18xx_cgu_src_clk_plls[i], |
620 | base); |
621 | if (IS_ERR(ptr: clk)) |
622 | pr_warn("%s: failed to register pll (%d)\n" , __func__, i); |
623 | } |
624 | |
625 | /* Register all clock dividers A-E */ |
626 | for (i = 0; i < ARRAY_SIZE(lpc18xx_cgu_src_clk_divs); i++) { |
627 | clk = lpc18xx_cgu_register_div(clk: &lpc18xx_cgu_src_clk_divs[i], |
628 | base, n: i); |
629 | if (IS_ERR(ptr: clk)) |
630 | pr_warn("%s: failed to register div %d\n" , __func__, i); |
631 | } |
632 | } |
633 | |
634 | static struct clk *clk_base[BASE_CLK_MAX]; |
635 | static struct clk_onecell_data clk_base_data = { |
636 | .clks = clk_base, |
637 | .clk_num = BASE_CLK_MAX, |
638 | }; |
639 | |
640 | static void __init lpc18xx_cgu_register_base_clks(void __iomem *reg_base) |
641 | { |
642 | int i; |
643 | |
644 | for (i = BASE_SAFE_CLK; i < BASE_CLK_MAX; i++) { |
645 | clk_base[i] = lpc18xx_register_base_clk(clk: &lpc18xx_cgu_base_clks[i], |
646 | reg_base, n: i); |
647 | if (IS_ERR(ptr: clk_base[i]) && PTR_ERR(ptr: clk_base[i]) != -ENOENT) |
648 | pr_warn("%s: register base clk %d failed\n" , __func__, i); |
649 | } |
650 | } |
651 | |
652 | static void __init lpc18xx_cgu_init(struct device_node *np) |
653 | { |
654 | void __iomem *reg_base; |
655 | |
656 | reg_base = of_iomap(node: np, index: 0); |
657 | if (!reg_base) { |
658 | pr_warn("%s: failed to map address range\n" , __func__); |
659 | return; |
660 | } |
661 | |
662 | lpc18xx_cgu_register_source_clks(np, base: reg_base); |
663 | lpc18xx_cgu_register_base_clks(reg_base); |
664 | |
665 | of_clk_add_provider(np, clk_src_get: of_clk_src_onecell_get, data: &clk_base_data); |
666 | } |
667 | CLK_OF_DECLARE(lpc18xx_cgu, "nxp,lpc1850-cgu" , lpc18xx_cgu_init); |
668 | |