Merge tag 'for-v6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power...
[linux-block.git] / drivers / clk / clk-nomadik.c
CommitLineData
af873fce 1// SPDX-License-Identifier: GPL-2.0-only
ef6eb322
LW
2/*
3 * Nomadik clock implementation
4 * Copyright (C) 2013 ST-Ericsson AB
ef6eb322
LW
5 * Author: Linus Walleij <linus.walleij@linaro.org>
6 */
7
8#define pr_fmt(fmt) "Nomadik SRC clocks: " fmt
9
10#include <linux/bitops.h>
aa1a7fc4 11#include <linux/slab.h>
4a31bd28
LW
12#include <linux/err.h>
13#include <linux/io.h>
14#include <linux/clk-provider.h>
6e2b07a1 15#include <linux/of.h>
ef6eb322
LW
16#include <linux/of_address.h>
17#include <linux/debugfs.h>
18#include <linux/seq_file.h>
19#include <linux/spinlock.h>
20#include <linux/reboot.h>
4a31bd28
LW
21
22/*
23 * The Nomadik clock tree is described in the STN8815A12 DB V4.2
24 * reference manual for the chip, page 94 ff.
ef6eb322
LW
25 * Clock IDs are in the STn8815 Reference Manual table 3, page 27.
26 */
27
28#define SRC_CR 0x00U
eb6b036d
LW
29#define SRC_CR_T0_ENSEL BIT(15)
30#define SRC_CR_T1_ENSEL BIT(17)
31#define SRC_CR_T2_ENSEL BIT(19)
32#define SRC_CR_T3_ENSEL BIT(21)
33#define SRC_CR_T4_ENSEL BIT(23)
34#define SRC_CR_T5_ENSEL BIT(25)
35#define SRC_CR_T6_ENSEL BIT(27)
36#define SRC_CR_T7_ENSEL BIT(29)
ef6eb322
LW
37#define SRC_XTALCR 0x0CU
38#define SRC_XTALCR_XTALTIMEN BIT(20)
39#define SRC_XTALCR_SXTALDIS BIT(19)
40#define SRC_XTALCR_MXTALSTAT BIT(2)
41#define SRC_XTALCR_MXTALEN BIT(1)
42#define SRC_XTALCR_MXTALOVER BIT(0)
43#define SRC_PLLCR 0x10U
44#define SRC_PLLCR_PLLTIMEN BIT(29)
45#define SRC_PLLCR_PLL2EN BIT(28)
46#define SRC_PLLCR_PLL1STAT BIT(2)
47#define SRC_PLLCR_PLL1EN BIT(1)
48#define SRC_PLLCR_PLL1OVER BIT(0)
49#define SRC_PLLFR 0x14U
50#define SRC_PCKEN0 0x24U
51#define SRC_PCKDIS0 0x28U
52#define SRC_PCKENSR0 0x2CU
53#define SRC_PCKSR0 0x30U
54#define SRC_PCKEN1 0x34U
55#define SRC_PCKDIS1 0x38U
56#define SRC_PCKENSR1 0x3CU
57#define SRC_PCKSR1 0x40U
58
59/* Lock protecting the SRC_CR register */
60static DEFINE_SPINLOCK(src_lock);
61/* Base address of the SRC */
62static void __iomem *src_base;
63
ea25a900
SH
64static int nomadik_clk_reboot_handler(struct notifier_block *this,
65 unsigned long code,
66 void *unused)
67{
68 u32 val;
69
70 /* The main chrystal need to be enabled for reboot to work */
71 val = readl(src_base + SRC_XTALCR);
72 val &= ~SRC_XTALCR_MXTALOVER;
73 val |= SRC_XTALCR_MXTALEN;
74 pr_crit("force-enabling MXTALO\n");
75 writel(val, src_base + SRC_XTALCR);
76 return NOTIFY_OK;
77}
78
79static struct notifier_block nomadik_clk_reboot_notifier = {
80 .notifier_call = nomadik_clk_reboot_handler,
81};
82
83static const struct of_device_id nomadik_src_match[] __initconst = {
84 { .compatible = "stericsson,nomadik-src" },
85 { /* sentinel */ }
86};
87
54bf93c4 88static void __init nomadik_src_init(void)
ea25a900
SH
89{
90 struct device_node *np;
91 u32 val;
92
93 np = of_find_matching_node(NULL, nomadik_src_match);
94 if (!np) {
95 pr_crit("no matching node for SRC, aborting clock init\n");
96 return;
97 }
98 src_base = of_iomap(np, 0);
99 if (!src_base) {
e665f029
RH
100 pr_err("%s: must have src parent node with REGS (%pOFn)\n",
101 __func__, np);
28a0b098 102 goto out_put;
ea25a900
SH
103 }
104
105 /* Set all timers to use the 2.4 MHz TIMCLK */
106 val = readl(src_base + SRC_CR);
107 val |= SRC_CR_T0_ENSEL;
108 val |= SRC_CR_T1_ENSEL;
109 val |= SRC_CR_T2_ENSEL;
110 val |= SRC_CR_T3_ENSEL;
111 val |= SRC_CR_T4_ENSEL;
112 val |= SRC_CR_T5_ENSEL;
113 val |= SRC_CR_T6_ENSEL;
114 val |= SRC_CR_T7_ENSEL;
115 writel(val, src_base + SRC_CR);
116
117 val = readl(src_base + SRC_XTALCR);
118 pr_info("SXTALO is %s\n",
119 (val & SRC_XTALCR_SXTALDIS) ? "disabled" : "enabled");
120 pr_info("MXTAL is %s\n",
121 (val & SRC_XTALCR_MXTALSTAT) ? "enabled" : "disabled");
122 if (of_property_read_bool(np, "disable-sxtalo")) {
123 /* The machine uses an external oscillator circuit */
124 val |= SRC_XTALCR_SXTALDIS;
125 pr_info("disabling SXTALO\n");
126 }
127 if (of_property_read_bool(np, "disable-mxtalo")) {
128 /* Disable this too: also run by external oscillator */
129 val |= SRC_XTALCR_MXTALOVER;
130 val &= ~SRC_XTALCR_MXTALEN;
131 pr_info("disabling MXTALO\n");
132 }
133 writel(val, src_base + SRC_XTALCR);
134 register_reboot_notifier(&nomadik_clk_reboot_notifier);
28a0b098
LH
135
136out_put:
137 of_node_put(np);
ea25a900
SH
138}
139
ef6eb322 140/**
5e57aaa8 141 * struct clk_pll - Nomadik PLL clock
ef6eb322
LW
142 * @hw: corresponding clock hardware entry
143 * @id: PLL instance: 1 or 2
144 */
145struct clk_pll {
146 struct clk_hw hw;
147 int id;
148};
149
150/**
151 * struct clk_src - Nomadik src clock
152 * @hw: corresponding clock hardware entry
153 * @id: the clock ID
154 * @group1: true if the clock is in group1, else it is in group0
155 * @clkbit: bit 0...31 corresponding to the clock in each clock register
156 */
157struct clk_src {
158 struct clk_hw hw;
159 int id;
160 bool group1;
161 u32 clkbit;
162};
163
164#define to_pll(_hw) container_of(_hw, struct clk_pll, hw)
165#define to_src(_hw) container_of(_hw, struct clk_src, hw)
166
167static int pll_clk_enable(struct clk_hw *hw)
168{
169 struct clk_pll *pll = to_pll(hw);
170 u32 val;
171
172 spin_lock(&src_lock);
173 val = readl(src_base + SRC_PLLCR);
174 if (pll->id == 1) {
175 if (val & SRC_PLLCR_PLL1OVER) {
176 val |= SRC_PLLCR_PLL1EN;
177 writel(val, src_base + SRC_PLLCR);
178 }
179 } else if (pll->id == 2) {
180 val |= SRC_PLLCR_PLL2EN;
181 writel(val, src_base + SRC_PLLCR);
182 }
183 spin_unlock(&src_lock);
184 return 0;
185}
186
187static void pll_clk_disable(struct clk_hw *hw)
188{
189 struct clk_pll *pll = to_pll(hw);
190 u32 val;
191
192 spin_lock(&src_lock);
193 val = readl(src_base + SRC_PLLCR);
194 if (pll->id == 1) {
195 if (val & SRC_PLLCR_PLL1OVER) {
196 val &= ~SRC_PLLCR_PLL1EN;
197 writel(val, src_base + SRC_PLLCR);
198 }
199 } else if (pll->id == 2) {
200 val &= ~SRC_PLLCR_PLL2EN;
201 writel(val, src_base + SRC_PLLCR);
202 }
203 spin_unlock(&src_lock);
204}
205
206static int pll_clk_is_enabled(struct clk_hw *hw)
207{
208 struct clk_pll *pll = to_pll(hw);
209 u32 val;
210
211 val = readl(src_base + SRC_PLLCR);
212 if (pll->id == 1) {
213 if (val & SRC_PLLCR_PLL1OVER)
214 return !!(val & SRC_PLLCR_PLL1EN);
215 } else if (pll->id == 2) {
216 return !!(val & SRC_PLLCR_PLL2EN);
217 }
218 return 1;
219}
220
221static unsigned long pll_clk_recalc_rate(struct clk_hw *hw,
222 unsigned long parent_rate)
223{
224 struct clk_pll *pll = to_pll(hw);
225 u32 val;
226
227 val = readl(src_base + SRC_PLLFR);
228
229 if (pll->id == 1) {
230 u8 mul;
231 u8 div;
232
233 mul = (val >> 8) & 0x3FU;
234 mul += 2;
235 div = val & 0x07U;
236 return (parent_rate * mul) >> div;
237 }
238
239 if (pll->id == 2) {
240 u8 mul;
241
242 mul = (val >> 24) & 0x3FU;
243 mul += 2;
244 return (parent_rate * mul);
245 }
246
247 /* Unknown PLL */
248 return 0;
249}
250
251
252static const struct clk_ops pll_clk_ops = {
253 .enable = pll_clk_enable,
254 .disable = pll_clk_disable,
255 .is_enabled = pll_clk_is_enabled,
256 .recalc_rate = pll_clk_recalc_rate,
257};
258
7b38d1b2 259static struct clk_hw * __init
ef6eb322
LW
260pll_clk_register(struct device *dev, const char *name,
261 const char *parent_name, u32 id)
262{
7b38d1b2 263 int ret;
ef6eb322
LW
264 struct clk_pll *pll;
265 struct clk_init_data init;
266
267 if (id != 1 && id != 2) {
268 pr_err("%s: the Nomadik has only PLL 1 & 2\n", __func__);
269 return ERR_PTR(-EINVAL);
270 }
271
272 pll = kzalloc(sizeof(*pll), GFP_KERNEL);
24f8186e 273 if (!pll)
ef6eb322 274 return ERR_PTR(-ENOMEM);
ef6eb322
LW
275
276 init.name = name;
277 init.ops = &pll_clk_ops;
278 init.parent_names = (parent_name ? &parent_name : NULL);
279 init.num_parents = (parent_name ? 1 : 0);
280 pll->hw.init = &init;
281 pll->id = id;
282
283 pr_debug("register PLL1 clock \"%s\"\n", name);
284
7b38d1b2
SB
285 ret = clk_hw_register(dev, &pll->hw);
286 if (ret) {
ef6eb322 287 kfree(pll);
7b38d1b2
SB
288 return ERR_PTR(ret);
289 }
ef6eb322 290
7b38d1b2 291 return &pll->hw;
ef6eb322
LW
292}
293
294/*
295 * The Nomadik SRC clocks are gated, but not in the sense that
296 * you read-modify-write a register. Instead there are separate
297 * clock enable and clock disable registers. Writing a '1' bit in
298 * the enable register for a certain clock ungates that clock without
299 * affecting the other clocks. The disable register works the opposite
300 * way.
4a31bd28
LW
301 */
302
ef6eb322
LW
303static int src_clk_enable(struct clk_hw *hw)
304{
305 struct clk_src *sclk = to_src(hw);
306 u32 enreg = sclk->group1 ? SRC_PCKEN1 : SRC_PCKEN0;
307 u32 sreg = sclk->group1 ? SRC_PCKSR1 : SRC_PCKSR0;
308
309 writel(sclk->clkbit, src_base + enreg);
310 /* spin until enabled */
311 while (!(readl(src_base + sreg) & sclk->clkbit))
312 cpu_relax();
313 return 0;
314}
315
316static void src_clk_disable(struct clk_hw *hw)
317{
318 struct clk_src *sclk = to_src(hw);
319 u32 disreg = sclk->group1 ? SRC_PCKDIS1 : SRC_PCKDIS0;
320 u32 sreg = sclk->group1 ? SRC_PCKSR1 : SRC_PCKSR0;
321
322 writel(sclk->clkbit, src_base + disreg);
323 /* spin until disabled */
324 while (readl(src_base + sreg) & sclk->clkbit)
325 cpu_relax();
326}
327
328static int src_clk_is_enabled(struct clk_hw *hw)
329{
330 struct clk_src *sclk = to_src(hw);
331 u32 sreg = sclk->group1 ? SRC_PCKSR1 : SRC_PCKSR0;
332 u32 val = readl(src_base + sreg);
333
334 return !!(val & sclk->clkbit);
335}
336
337static unsigned long
338src_clk_recalc_rate(struct clk_hw *hw,
339 unsigned long parent_rate)
340{
341 return parent_rate;
342}
343
344static const struct clk_ops src_clk_ops = {
345 .enable = src_clk_enable,
346 .disable = src_clk_disable,
347 .is_enabled = src_clk_is_enabled,
348 .recalc_rate = src_clk_recalc_rate,
349};
350
7b38d1b2 351static struct clk_hw * __init
ef6eb322
LW
352src_clk_register(struct device *dev, const char *name,
353 const char *parent_name, u8 id)
354{
7b38d1b2 355 int ret;
ef6eb322
LW
356 struct clk_src *sclk;
357 struct clk_init_data init;
358
359 sclk = kzalloc(sizeof(*sclk), GFP_KERNEL);
24f8186e 360 if (!sclk)
ef6eb322 361 return ERR_PTR(-ENOMEM);
24f8186e 362
ef6eb322
LW
363 init.name = name;
364 init.ops = &src_clk_ops;
365 /* Do not force-disable the static SDRAM controller */
366 if (id == 2)
367 init.flags = CLK_IGNORE_UNUSED;
368 else
369 init.flags = 0;
370 init.parent_names = (parent_name ? &parent_name : NULL);
371 init.num_parents = (parent_name ? 1 : 0);
372 sclk->hw.init = &init;
373 sclk->id = id;
374 sclk->group1 = (id > 31);
375 sclk->clkbit = BIT(id & 0x1f);
376
377 pr_debug("register clock \"%s\" ID: %d group: %d bits: %08x\n",
378 name, id, sclk->group1, sclk->clkbit);
379
7b38d1b2
SB
380 ret = clk_hw_register(dev, &sclk->hw);
381 if (ret) {
ef6eb322 382 kfree(sclk);
7b38d1b2
SB
383 return ERR_PTR(ret);
384 }
ef6eb322 385
7b38d1b2 386 return &sclk->hw;
ef6eb322
LW
387}
388
389#ifdef CONFIG_DEBUG_FS
390
391static u32 src_pcksr0_boot;
392static u32 src_pcksr1_boot;
393
394static const char * const src_clk_names[] = {
395 "HCLKDMA0 ",
396 "HCLKSMC ",
397 "HCLKSDRAM ",
398 "HCLKDMA1 ",
399 "HCLKCLCD ",
400 "PCLKIRDA ",
401 "PCLKSSP ",
402 "PCLKUART0 ",
403 "PCLKSDI ",
404 "PCLKI2C0 ",
405 "PCLKI2C1 ",
406 "PCLKUART1 ",
407 "PCLMSP0 ",
408 "HCLKUSB ",
409 "HCLKDIF ",
410 "HCLKSAA ",
411 "HCLKSVA ",
412 "PCLKHSI ",
413 "PCLKXTI ",
414 "PCLKUART2 ",
415 "PCLKMSP1 ",
416 "PCLKMSP2 ",
417 "PCLKOWM ",
418 "HCLKHPI ",
419 "PCLKSKE ",
420 "PCLKHSEM ",
421 "HCLK3D ",
422 "HCLKHASH ",
423 "HCLKCRYP ",
424 "PCLKMSHC ",
425 "HCLKUSBM ",
426 "HCLKRNG ",
427 "RESERVED ",
428 "RESERVED ",
429 "RESERVED ",
430 "RESERVED ",
431 "CLDCLK ",
432 "IRDACLK ",
433 "SSPICLK ",
434 "UART0CLK ",
435 "SDICLK ",
436 "I2C0CLK ",
437 "I2C1CLK ",
438 "UART1CLK ",
439 "MSPCLK0 ",
440 "USBCLK ",
441 "DIFCLK ",
442 "IPI2CCLK ",
443 "IPBMCCLK ",
444 "HSICLKRX ",
445 "HSICLKTX ",
446 "UART2CLK ",
447 "MSPCLK1 ",
448 "MSPCLK2 ",
449 "OWMCLK ",
450 "RESERVED ",
451 "SKECLK ",
452 "RESERVED ",
453 "3DCLK ",
454 "PCLKMSP3 ",
455 "MSPCLK3 ",
456 "MSHCCLK ",
457 "USBMCLK ",
458 "RNGCCLK ",
459};
460
9579346e 461static int nomadik_src_clk_debugfs_show(struct seq_file *s, void *what)
ef6eb322
LW
462{
463 int i;
464 u32 src_pcksr0 = readl(src_base + SRC_PCKSR0);
465 u32 src_pcksr1 = readl(src_base + SRC_PCKSR1);
466 u32 src_pckensr0 = readl(src_base + SRC_PCKENSR0);
467 u32 src_pckensr1 = readl(src_base + SRC_PCKENSR1);
468
add31511 469 seq_puts(s, "Clock: Boot: Now: Request: ASKED:\n");
ef6eb322
LW
470 for (i = 0; i < ARRAY_SIZE(src_clk_names); i++) {
471 u32 pcksrb = (i < 0x20) ? src_pcksr0_boot : src_pcksr1_boot;
472 u32 pcksr = (i < 0x20) ? src_pcksr0 : src_pcksr1;
473 u32 pckreq = (i < 0x20) ? src_pckensr0 : src_pckensr1;
474 u32 mask = BIT(i & 0x1f);
475
476 seq_printf(s, "%s %s %s %s\n",
477 src_clk_names[i],
478 (pcksrb & mask) ? "on " : "off",
479 (pcksr & mask) ? "on " : "off",
480 (pckreq & mask) ? "on " : "off");
481 }
482 return 0;
483}
484
9579346e 485DEFINE_SHOW_ATTRIBUTE(nomadik_src_clk_debugfs);
ef6eb322
LW
486
487static int __init nomadik_src_clk_init_debugfs(void)
488{
ec6deea1
LW
489 /* Vital for multiplatform */
490 if (!src_base)
491 return -ENODEV;
ef6eb322
LW
492 src_pcksr0_boot = readl(src_base + SRC_PCKSR0);
493 src_pcksr1_boot = readl(src_base + SRC_PCKSR1);
494 debugfs_create_file("nomadik-src-clk", S_IFREG | S_IRUGO,
9579346e 495 NULL, NULL, &nomadik_src_clk_debugfs_fops);
ef6eb322
LW
496 return 0;
497}
791ed0bb 498device_initcall(nomadik_src_clk_init_debugfs);
ef6eb322
LW
499
500#endif
501
502static void __init of_nomadik_pll_setup(struct device_node *np)
503{
7b38d1b2 504 struct clk_hw *hw;
ef6eb322
LW
505 const char *clk_name = np->name;
506 const char *parent_name;
507 u32 pll_id;
508
74227e65
SH
509 if (!src_base)
510 nomadik_src_init();
511
ef6eb322
LW
512 if (of_property_read_u32(np, "pll-id", &pll_id)) {
513 pr_err("%s: PLL \"%s\" missing pll-id property\n",
514 __func__, clk_name);
515 return;
516 }
517 parent_name = of_clk_get_parent_name(np, 0);
7b38d1b2
SB
518 hw = pll_clk_register(NULL, clk_name, parent_name, pll_id);
519 if (!IS_ERR(hw))
520 of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
ef6eb322 521}
74227e65
SH
522CLK_OF_DECLARE(nomadik_pll_clk,
523 "st,nomadik-pll-clock", of_nomadik_pll_setup);
ef6eb322
LW
524
525static void __init of_nomadik_hclk_setup(struct device_node *np)
526{
7b38d1b2 527 struct clk_hw *hw;
ef6eb322
LW
528 const char *clk_name = np->name;
529 const char *parent_name;
530
74227e65
SH
531 if (!src_base)
532 nomadik_src_init();
533
ef6eb322
LW
534 parent_name = of_clk_get_parent_name(np, 0);
535 /*
536 * The HCLK divides PLL1 with 1 (passthru), 2, 3 or 4.
537 */
7b38d1b2 538 hw = clk_hw_register_divider(NULL, clk_name, parent_name,
ef6eb322
LW
539 0, src_base + SRC_CR,
540 13, 2,
541 CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
542 &src_lock);
7b38d1b2
SB
543 if (!IS_ERR(hw))
544 of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
ef6eb322 545}
74227e65
SH
546CLK_OF_DECLARE(nomadik_hclk_clk,
547 "st,nomadik-hclk-clock", of_nomadik_hclk_setup);
ef6eb322
LW
548
549static void __init of_nomadik_src_clk_setup(struct device_node *np)
550{
7b38d1b2 551 struct clk_hw *hw;
ef6eb322
LW
552 const char *clk_name = np->name;
553 const char *parent_name;
554 u32 clk_id;
555
74227e65
SH
556 if (!src_base)
557 nomadik_src_init();
558
ef6eb322
LW
559 if (of_property_read_u32(np, "clock-id", &clk_id)) {
560 pr_err("%s: SRC clock \"%s\" missing clock-id property\n",
561 __func__, clk_name);
562 return;
563 }
564 parent_name = of_clk_get_parent_name(np, 0);
7b38d1b2
SB
565 hw = src_clk_register(NULL, clk_name, parent_name, clk_id);
566 if (!IS_ERR(hw))
567 of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
ef6eb322 568}
74227e65
SH
569CLK_OF_DECLARE(nomadik_src_clk,
570 "st,nomadik-src-clock", of_nomadik_src_clk_setup);