xref: /openbmc/linux/drivers/clk/clk-nomadik.c (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
1  // SPDX-License-Identifier: GPL-2.0-only
2  /*
3   * Nomadik clock implementation
4   * Copyright (C) 2013 ST-Ericsson AB
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>
11  #include <linux/slab.h>
12  #include <linux/err.h>
13  #include <linux/io.h>
14  #include <linux/clk-provider.h>
15  #include <linux/of.h>
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>
21  
22  /*
23   * The Nomadik clock tree is described in the STN8815A12 DB V4.2
24   * reference manual for the chip, page 94 ff.
25   * Clock IDs are in the STn8815 Reference Manual table 3, page 27.
26   */
27  
28  #define SRC_CR			0x00U
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)
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 */
60  static DEFINE_SPINLOCK(src_lock);
61  /* Base address of the SRC */
62  static void __iomem *src_base;
63  
nomadik_clk_reboot_handler(struct notifier_block * this,unsigned long code,void * unused)64  static 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  
79  static struct notifier_block nomadik_clk_reboot_notifier = {
80  	.notifier_call = nomadik_clk_reboot_handler,
81  };
82  
83  static const struct of_device_id nomadik_src_match[] __initconst = {
84  	{ .compatible = "stericsson,nomadik-src" },
85  	{ /* sentinel */ }
86  };
87  
nomadik_src_init(void)88  static void __init nomadik_src_init(void)
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) {
100  		pr_err("%s: must have src parent node with REGS (%pOFn)\n",
101  		       __func__, np);
102  		goto out_put;
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);
135  
136  out_put:
137  	of_node_put(np);
138  }
139  
140  /**
141   * struct clk_pll - Nomadik PLL clock
142   * @hw: corresponding clock hardware entry
143   * @id: PLL instance: 1 or 2
144   */
145  struct 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   */
157  struct 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  
pll_clk_enable(struct clk_hw * hw)167  static 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  
pll_clk_disable(struct clk_hw * hw)187  static 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  
pll_clk_is_enabled(struct clk_hw * hw)206  static 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  
pll_clk_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)221  static 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  
252  static 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  
259  static struct clk_hw * __init
pll_clk_register(struct device * dev,const char * name,const char * parent_name,u32 id)260  pll_clk_register(struct device *dev, const char *name,
261  		 const char *parent_name, u32 id)
262  {
263  	int ret;
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);
273  	if (!pll)
274  		return ERR_PTR(-ENOMEM);
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  
285  	ret = clk_hw_register(dev, &pll->hw);
286  	if (ret) {
287  		kfree(pll);
288  		return ERR_PTR(ret);
289  	}
290  
291  	return &pll->hw;
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.
301   */
302  
src_clk_enable(struct clk_hw * hw)303  static 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  
src_clk_disable(struct clk_hw * hw)316  static 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  
src_clk_is_enabled(struct clk_hw * hw)328  static 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  
337  static unsigned long
src_clk_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)338  src_clk_recalc_rate(struct clk_hw *hw,
339  		    unsigned long parent_rate)
340  {
341  	return parent_rate;
342  }
343  
344  static 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  
351  static struct clk_hw * __init
src_clk_register(struct device * dev,const char * name,const char * parent_name,u8 id)352  src_clk_register(struct device *dev, const char *name,
353  		 const char *parent_name, u8 id)
354  {
355  	int ret;
356  	struct clk_src *sclk;
357  	struct clk_init_data init;
358  
359  	sclk = kzalloc(sizeof(*sclk), GFP_KERNEL);
360  	if (!sclk)
361  		return ERR_PTR(-ENOMEM);
362  
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  
380  	ret = clk_hw_register(dev, &sclk->hw);
381  	if (ret) {
382  		kfree(sclk);
383  		return ERR_PTR(ret);
384  	}
385  
386  	return &sclk->hw;
387  }
388  
389  #ifdef CONFIG_DEBUG_FS
390  
391  static u32 src_pcksr0_boot;
392  static u32 src_pcksr1_boot;
393  
394  static 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  
nomadik_src_clk_debugfs_show(struct seq_file * s,void * what)461  static int nomadik_src_clk_debugfs_show(struct seq_file *s, void *what)
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  
469  	seq_puts(s, "Clock:      Boot:   Now:    Request: ASKED:\n");
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  
485  DEFINE_SHOW_ATTRIBUTE(nomadik_src_clk_debugfs);
486  
nomadik_src_clk_init_debugfs(void)487  static int __init nomadik_src_clk_init_debugfs(void)
488  {
489  	/* Vital for multiplatform */
490  	if (!src_base)
491  		return -ENODEV;
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,
495  			    NULL, NULL, &nomadik_src_clk_debugfs_fops);
496  	return 0;
497  }
498  device_initcall(nomadik_src_clk_init_debugfs);
499  
500  #endif
501  
of_nomadik_pll_setup(struct device_node * np)502  static void __init of_nomadik_pll_setup(struct device_node *np)
503  {
504  	struct clk_hw *hw;
505  	const char *clk_name = np->name;
506  	const char *parent_name;
507  	u32 pll_id;
508  
509  	if (!src_base)
510  		nomadik_src_init();
511  
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);
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);
521  }
522  CLK_OF_DECLARE(nomadik_pll_clk,
523  	"st,nomadik-pll-clock", of_nomadik_pll_setup);
524  
of_nomadik_hclk_setup(struct device_node * np)525  static void __init of_nomadik_hclk_setup(struct device_node *np)
526  {
527  	struct clk_hw *hw;
528  	const char *clk_name = np->name;
529  	const char *parent_name;
530  
531  	if (!src_base)
532  		nomadik_src_init();
533  
534  	parent_name = of_clk_get_parent_name(np, 0);
535  	/*
536  	 * The HCLK divides PLL1 with 1 (passthru), 2, 3 or 4.
537  	 */
538  	hw = clk_hw_register_divider(NULL, clk_name, parent_name,
539  			   0, src_base + SRC_CR,
540  			   13, 2,
541  			   CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
542  			   &src_lock);
543  	if (!IS_ERR(hw))
544  		of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
545  }
546  CLK_OF_DECLARE(nomadik_hclk_clk,
547  	"st,nomadik-hclk-clock", of_nomadik_hclk_setup);
548  
of_nomadik_src_clk_setup(struct device_node * np)549  static void __init of_nomadik_src_clk_setup(struct device_node *np)
550  {
551  	struct clk_hw *hw;
552  	const char *clk_name = np->name;
553  	const char *parent_name;
554  	u32 clk_id;
555  
556  	if (!src_base)
557  		nomadik_src_init();
558  
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);
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);
568  }
569  CLK_OF_DECLARE(nomadik_src_clk,
570  	"st,nomadik-src-clock", of_nomadik_src_clk_setup);
571