File Index
Files and directories
Sign in
FILE

x1000-cgu.c

File preview with syntax highlighting.

linux-6.19.14/drivers/clk/ingenic/x1000-cgu.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * X1000 SoC CGU driver
  4 * Copyright (c) 2019 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
  5 */
  6
  7#include <linux/clk-provider.h>
  8#include <linux/delay.h>
  9#include <linux/io.h>
 10#include <linux/of.h>
 11#include <linux/rational.h>
 12
 13#include <dt-bindings/clock/ingenic,x1000-cgu.h>
 14
 15#include "cgu.h"
 16#include "pm.h"
 17
 18/* CGU register offsets */
 19#define CGU_REG_CPCCR		0x00
 20#define CGU_REG_APLL		0x10
 21#define CGU_REG_MPLL		0x14
 22#define CGU_REG_CLKGR		0x20
 23#define CGU_REG_OPCR		0x24
 24#define CGU_REG_DDRCDR		0x2c
 25#define CGU_REG_USBPCR		0x3c
 26#define CGU_REG_USBPCR1		0x48
 27#define CGU_REG_USBCDR		0x50
 28#define CGU_REG_MACCDR		0x54
 29#define CGU_REG_I2SCDR		0x60
 30#define CGU_REG_LPCDR		0x64
 31#define CGU_REG_MSC0CDR		0x68
 32#define CGU_REG_I2SCDR1		0x70
 33#define CGU_REG_SSICDR		0x74
 34#define CGU_REG_CIMCDR		0x7c
 35#define CGU_REG_PCMCDR		0x84
 36#define CGU_REG_MSC1CDR		0xa4
 37#define CGU_REG_CMP_INTR	0xb0
 38#define CGU_REG_CMP_INTRE	0xb4
 39#define CGU_REG_DRCG		0xd0
 40#define CGU_REG_CPCSR		0xd4
 41#define CGU_REG_PCMCDR1		0xe0
 42#define CGU_REG_MACPHYC		0xe8
 43
 44/* bits within the OPCR register */
 45#define OPCR_SPENDN0		BIT(7)
 46#define OPCR_SPENDN1		BIT(6)
 47
 48/* bits within the USBPCR register */
 49#define USBPCR_SIDDQ		BIT(21)
 50#define USBPCR_OTG_DISABLE	BIT(20)
 51
 52/* bits within the USBPCR1 register */
 53#define USBPCR1_REFCLKSEL_SHIFT	26
 54#define USBPCR1_REFCLKSEL_MASK	(0x3 << USBPCR1_REFCLKSEL_SHIFT)
 55#define USBPCR1_REFCLKSEL_CORE	(0x2 << USBPCR1_REFCLKSEL_SHIFT)
 56#define USBPCR1_REFCLKDIV_SHIFT	24
 57#define USBPCR1_REFCLKDIV_MASK	(0x3 << USBPCR1_REFCLKDIV_SHIFT)
 58#define USBPCR1_REFCLKDIV_48	(0x2 << USBPCR1_REFCLKDIV_SHIFT)
 59#define USBPCR1_REFCLKDIV_24	(0x1 << USBPCR1_REFCLKDIV_SHIFT)
 60#define USBPCR1_REFCLKDIV_12	(0x0 << USBPCR1_REFCLKDIV_SHIFT)
 61
 62static struct ingenic_cgu *cgu;
 63
 64static unsigned long x1000_otg_phy_recalc_rate(struct clk_hw *hw,
 65						unsigned long parent_rate)
 66{
 67	u32 usbpcr1;
 68	unsigned refclk_div;
 69
 70	usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
 71	refclk_div = usbpcr1 & USBPCR1_REFCLKDIV_MASK;
 72
 73	switch (refclk_div) {
 74	case USBPCR1_REFCLKDIV_12:
 75		return 12000000;
 76
 77	case USBPCR1_REFCLKDIV_24:
 78		return 24000000;
 79
 80	case USBPCR1_REFCLKDIV_48:
 81		return 48000000;
 82	}
 83
 84	return parent_rate;
 85}
 86
 87static int x1000_otg_phy_determine_rate(struct clk_hw *hw,
 88					struct clk_rate_request *req)
 89{
 90	if (req->rate < 18000000)
 91		req->rate = 12000000;
 92	else if (req->rate < 36000000)
 93		req->rate = 24000000;
 94	else
 95		req->rate = 48000000;
 96
 97	return 0;
 98}
 99
100static int x1000_otg_phy_set_rate(struct clk_hw *hw, unsigned long req_rate,
101				   unsigned long parent_rate)
102{
103	unsigned long flags;
104	u32 usbpcr1, div_bits;
105
106	switch (req_rate) {
107	case 12000000:
108		div_bits = USBPCR1_REFCLKDIV_12;
109		break;
110
111	case 24000000:
112		div_bits = USBPCR1_REFCLKDIV_24;
113		break;
114
115	case 48000000:
116		div_bits = USBPCR1_REFCLKDIV_48;
117		break;
118
119	default:
120		return -EINVAL;
121	}
122
123	spin_lock_irqsave(&cgu->lock, flags);
124
125	usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
126	usbpcr1 &= ~USBPCR1_REFCLKDIV_MASK;
127	usbpcr1 |= div_bits;
128	writel(usbpcr1, cgu->base + CGU_REG_USBPCR1);
129
130	spin_unlock_irqrestore(&cgu->lock, flags);
131	return 0;
132}
133
134static int x1000_usb_phy_enable(struct clk_hw *hw)
135{
136	void __iomem *reg_opcr		= cgu->base + CGU_REG_OPCR;
137	void __iomem *reg_usbpcr	= cgu->base + CGU_REG_USBPCR;
138
139	writel(readl(reg_opcr) | OPCR_SPENDN0, reg_opcr);
140	writel(readl(reg_usbpcr) & ~USBPCR_OTG_DISABLE & ~USBPCR_SIDDQ, reg_usbpcr);
141	return 0;
142}
143
144static void x1000_usb_phy_disable(struct clk_hw *hw)
145{
146	void __iomem *reg_opcr		= cgu->base + CGU_REG_OPCR;
147	void __iomem *reg_usbpcr	= cgu->base + CGU_REG_USBPCR;
148
149	writel(readl(reg_opcr) & ~OPCR_SPENDN0, reg_opcr);
150	writel(readl(reg_usbpcr) | USBPCR_OTG_DISABLE | USBPCR_SIDDQ, reg_usbpcr);
151}
152
153static int x1000_usb_phy_is_enabled(struct clk_hw *hw)
154{
155	void __iomem *reg_opcr		= cgu->base + CGU_REG_OPCR;
156	void __iomem *reg_usbpcr	= cgu->base + CGU_REG_USBPCR;
157
158	return (readl(reg_opcr) & OPCR_SPENDN0) &&
159		!(readl(reg_usbpcr) & USBPCR_SIDDQ) &&
160		!(readl(reg_usbpcr) & USBPCR_OTG_DISABLE);
161}
162
163static const struct clk_ops x1000_otg_phy_ops = {
164	.recalc_rate = x1000_otg_phy_recalc_rate,
165	.determine_rate = x1000_otg_phy_determine_rate,
166	.set_rate = x1000_otg_phy_set_rate,
167
168	.enable		= x1000_usb_phy_enable,
169	.disable	= x1000_usb_phy_disable,
170	.is_enabled	= x1000_usb_phy_is_enabled,
171};
172
173static void
174x1000_i2spll_calc_m_n_od(const struct ingenic_cgu_pll_info *pll_info,
175			 unsigned long rate, unsigned long parent_rate,
176			 unsigned int *pm, unsigned int *pn, unsigned int *pod)
177{
178	const unsigned long m_max = GENMASK(pll_info->m_bits - 1, 0);
179	const unsigned long n_max = GENMASK(pll_info->n_bits - 1, 0);
180	unsigned long m, n;
181
182	rational_best_approximation(rate, parent_rate, m_max, n_max, &m, &n);
183
184	/* n should not be less than 2*m */
185	if (n < 2 * m)
186		n = 2 * m;
187
188	*pm = m;
189	*pn = n;
190	*pod = 1;
191}
192
193static void
194x1000_i2spll_set_rate_hook(const struct ingenic_cgu_pll_info *pll_info,
195			   unsigned long rate, unsigned long parent_rate)
196{
197	/*
198	 * Writing 0 causes I2SCDR1.I2SDIV_D to be automatically recalculated
199	 * based on the current value of I2SCDR.I2SDIV_N, which is needed for
200	 * the divider to function correctly.
201	 */
202	writel(0, cgu->base + CGU_REG_I2SCDR1);
203}
204
205static const s8 pll_od_encoding[8] = {
206	0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3,
207};
208
209static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
210
211	/* External clocks */
212
213	[X1000_CLK_EXCLK] = { "ext", CGU_CLK_EXT },
214	[X1000_CLK_RTCLK] = { "rtc", CGU_CLK_EXT },
215
216	/* PLLs */
217
218	[X1000_CLK_APLL] = {
219		"apll", CGU_CLK_PLL,
220		.parents = { X1000_CLK_EXCLK },
221		.pll = {
222			.reg = CGU_REG_APLL,
223			.rate_multiplier = 1,
224			.m_shift = 24,
225			.m_bits = 7,
226			.m_offset = 1,
227			.n_shift = 18,
228			.n_bits = 5,
229			.n_offset = 1,
230			.od_shift = 16,
231			.od_bits = 2,
232			.od_max = 8,
233			.od_encoding = pll_od_encoding,
234			.bypass_reg = CGU_REG_APLL,
235			.bypass_bit = 9,
236			.enable_bit = 8,
237			.stable_bit = 10,
238		},
239	},
240
241	[X1000_CLK_MPLL] = {
242		"mpll", CGU_CLK_PLL,
243		.parents = { X1000_CLK_EXCLK },
244		.pll = {
245			.reg = CGU_REG_MPLL,
246			.rate_multiplier = 1,
247			.m_shift = 24,
248			.m_bits = 7,
249			.m_offset = 1,
250			.n_shift = 18,
251			.n_bits = 5,
252			.n_offset = 1,
253			.od_shift = 16,
254			.od_bits = 2,
255			.od_max = 8,
256			.od_encoding = pll_od_encoding,
257			.bypass_reg = CGU_REG_MPLL,
258			.bypass_bit = 6,
259			.enable_bit = 7,
260			.stable_bit = 0,
261		},
262	},
263
264	/* Custom (SoC-specific) OTG PHY */
265
266	[X1000_CLK_OTGPHY] = {
267		"otg_phy", CGU_CLK_CUSTOM,
268		.parents = { -1, -1, X1000_CLK_EXCLK, -1 },
269		.custom = { &x1000_otg_phy_ops },
270	},
271
272	/* Muxes & dividers */
273
274	[X1000_CLK_SCLKA] = {
275		"sclk_a", CGU_CLK_MUX,
276		.parents = { -1, X1000_CLK_EXCLK, X1000_CLK_APLL, -1 },
277		.mux = { CGU_REG_CPCCR, 30, 2 },
278	},
279
280	[X1000_CLK_CPUMUX] = {
281		"cpu_mux", CGU_CLK_MUX,
282		.parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 },
283		.mux = { CGU_REG_CPCCR, 28, 2 },
284	},
285
286	[X1000_CLK_CPU] = {
287		"cpu", CGU_CLK_DIV | CGU_CLK_GATE,
288		/*
289		 * Disabling the CPU clock or any parent clocks will hang the
290		 * system; mark it critical.
291		 */
292		.flags = CLK_IS_CRITICAL,
293		.parents = { X1000_CLK_CPUMUX },
294		.div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 },
295		.gate = { CGU_REG_CLKGR, 30 },
296	},
297
298	[X1000_CLK_L2CACHE] = {
299		"l2cache", CGU_CLK_DIV,
300		/*
301		 * The L2 cache clock is critical if caches are enabled and
302		 * disabling it or any parent clocks will hang the system.
303		 */
304		.flags = CLK_IS_CRITICAL,
305		.parents = { X1000_CLK_CPUMUX },
306		.div = { CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1 },
307	},
308
309	[X1000_CLK_AHB0] = {
310		"ahb0", CGU_CLK_MUX | CGU_CLK_DIV,
311		.parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 },
312		.mux = { CGU_REG_CPCCR, 26, 2 },
313		.div = { CGU_REG_CPCCR, 8, 1, 4, 21, -1, -1 },
314	},
315
316	[X1000_CLK_AHB2PMUX] = {
317		"ahb2_apb_mux", CGU_CLK_MUX,
318		.parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 },
319		.mux = { CGU_REG_CPCCR, 24, 2 },
320	},
321
322	[X1000_CLK_AHB2] = {
323		"ahb2", CGU_CLK_DIV,
324		.parents = { X1000_CLK_AHB2PMUX },
325		.div = { CGU_REG_CPCCR, 12, 1, 4, 20, -1, -1 },
326	},
327
328	[X1000_CLK_PCLK] = {
329		"pclk", CGU_CLK_DIV | CGU_CLK_GATE,
330		.parents = { X1000_CLK_AHB2PMUX },
331		.div = { CGU_REG_CPCCR, 16, 1, 4, 20, -1, -1 },
332		.gate = { CGU_REG_CLKGR, 28 },
333	},
334
335	[X1000_CLK_DDR] = {
336		"ddr", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
337		/*
338		 * Disabling DDR clock or its parents will render DRAM
339		 * inaccessible; mark it critical.
340		 */
341		.flags = CLK_IS_CRITICAL,
342		.parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 },
343		.mux = { CGU_REG_DDRCDR, 30, 2 },
344		.div = { CGU_REG_DDRCDR, 0, 1, 4, 29, 28, 27 },
345		.gate = { CGU_REG_CLKGR, 31 },
346	},
347
348	[X1000_CLK_MAC] = {
349		"mac", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
350		.parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL },
351		.mux = { CGU_REG_MACCDR, 31, 1 },
352		.div = { CGU_REG_MACCDR, 0, 1, 8, 29, 28, 27 },
353		.gate = { CGU_REG_CLKGR, 25 },
354	},
355
356	[X1000_CLK_I2SPLLMUX] = {
357		"i2s_pll_mux", CGU_CLK_MUX,
358		.parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL },
359		.mux = { CGU_REG_I2SCDR, 31, 1 },
360	},
361
362	[X1000_CLK_I2SPLL] = {
363		"i2s_pll", CGU_CLK_PLL,
364		.parents = { X1000_CLK_I2SPLLMUX },
365		.pll = {
366			.reg = CGU_REG_I2SCDR,
367			.rate_multiplier = 1,
368			.m_shift = 13,
369			.m_bits = 9,
370			.n_shift = 0,
371			.n_bits = 13,
372			.calc_m_n_od = x1000_i2spll_calc_m_n_od,
373			.set_rate_hook = x1000_i2spll_set_rate_hook,
374		},
375	},
376
377	[X1000_CLK_I2S] = {
378		"i2s", CGU_CLK_MUX,
379		.parents = { X1000_CLK_EXCLK, -1, -1, X1000_CLK_I2SPLL },
380		/*
381		 * NOTE: the mux is at bit 30; bit 29 enables the M/N divider.
382		 * Therefore, the divider is disabled when EXCLK is selected.
383		 */
384		.mux = { CGU_REG_I2SCDR, 29, 2 },
385	},
386
387	[X1000_CLK_LCD] = {
388		"lcd", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
389		.parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL },
390		.mux = { CGU_REG_LPCDR, 31, 1 },
391		.div = { CGU_REG_LPCDR, 0, 1, 8, 28, 27, 26 },
392		.gate = { CGU_REG_CLKGR, 23 },
393	},
394
395	[X1000_CLK_MSCMUX] = {
396		"msc_mux", CGU_CLK_MUX,
397		.parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL },
398		.mux = { CGU_REG_MSC0CDR, 31, 1 },
399	},
400
401	[X1000_CLK_MSC0] = {
402		"msc0", CGU_CLK_DIV | CGU_CLK_GATE,
403		.parents = { X1000_CLK_MSCMUX },
404		.div = { CGU_REG_MSC0CDR, 0, 2, 8, 29, 28, 27 },
405		.gate = { CGU_REG_CLKGR, 4 },
406	},
407
408	[X1000_CLK_MSC1] = {
409		"msc1", CGU_CLK_DIV | CGU_CLK_GATE,
410		.parents = { X1000_CLK_MSCMUX, -1, -1, -1 },
411		.div = { CGU_REG_MSC1CDR, 0, 2, 8, 29, 28, 27 },
412		.gate = { CGU_REG_CLKGR, 5 },
413	},
414
415	[X1000_CLK_OTG] = {
416		"otg", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
417		.parents = { X1000_CLK_EXCLK, -1, X1000_CLK_APLL, X1000_CLK_MPLL },
418		.mux = { CGU_REG_USBCDR, 30, 2 },
419		.div = { CGU_REG_USBCDR, 0, 1, 8, 29, 28, 27 },
420		.gate = { CGU_REG_CLKGR, 3 },
421	},
422
423	[X1000_CLK_SSIPLL] = {
424		"ssi_pll", CGU_CLK_MUX | CGU_CLK_DIV,
425		.parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL },
426		.mux = { CGU_REG_SSICDR, 31, 1 },
427		.div = { CGU_REG_SSICDR, 0, 1, 8, 29, 28, 27 },
428	},
429
430	[X1000_CLK_SSIPLL_DIV2] = {
431		"ssi_pll_div2", CGU_CLK_FIXDIV,
432		.parents = { X1000_CLK_SSIPLL },
433		.fixdiv = { 2 },
434	},
435
436	[X1000_CLK_SSIMUX] = {
437		"ssi_mux", CGU_CLK_MUX,
438		.parents = { X1000_CLK_EXCLK, X1000_CLK_SSIPLL_DIV2 },
439		.mux = { CGU_REG_SSICDR, 30, 1 },
440	},
441
442	[X1000_CLK_EXCLK_DIV512] = {
443		"exclk_div512", CGU_CLK_FIXDIV,
444		.parents = { X1000_CLK_EXCLK },
445		.fixdiv = { 512 },
446	},
447
448	[X1000_CLK_RTC] = {
449		"rtc_ercs", CGU_CLK_MUX | CGU_CLK_GATE,
450		.parents = { X1000_CLK_EXCLK_DIV512, X1000_CLK_RTCLK },
451		.mux = { CGU_REG_OPCR, 2, 1},
452		.gate = { CGU_REG_CLKGR, 27 },
453	},
454
455	/* Gate-only clocks */
456
457	[X1000_CLK_EMC] = {
458		"emc", CGU_CLK_GATE,
459		.parents = { X1000_CLK_AHB2 },
460		.gate = { CGU_REG_CLKGR, 0 },
461	},
462
463	[X1000_CLK_EFUSE] = {
464		"efuse", CGU_CLK_GATE,
465		.parents = { X1000_CLK_AHB2 },
466		.gate = { CGU_REG_CLKGR, 1 },
467	},
468
469	[X1000_CLK_SFC] = {
470		"sfc", CGU_CLK_GATE,
471		.parents = { X1000_CLK_SSIPLL },
472		.gate = { CGU_REG_CLKGR, 2 },
473	},
474
475	[X1000_CLK_I2C0] = {
476		"i2c0", CGU_CLK_GATE,
477		.parents = { X1000_CLK_PCLK },
478		.gate = { CGU_REG_CLKGR, 7 },
479	},
480
481	[X1000_CLK_I2C1] = {
482		"i2c1", CGU_CLK_GATE,
483		.parents = { X1000_CLK_PCLK },
484		.gate = { CGU_REG_CLKGR, 8 },
485	},
486
487	[X1000_CLK_I2C2] = {
488		"i2c2", CGU_CLK_GATE,
489		.parents = { X1000_CLK_PCLK },
490		.gate = { CGU_REG_CLKGR, 9 },
491	},
492
493	[X1000_CLK_AIC] = {
494		"aic", CGU_CLK_GATE,
495		.parents = { X1000_CLK_EXCLK },
496		.gate = { CGU_REG_CLKGR, 11 },
497	},
498
499	[X1000_CLK_UART0] = {
500		"uart0", CGU_CLK_GATE,
501		.parents = { X1000_CLK_EXCLK },
502		.gate = { CGU_REG_CLKGR, 14 },
503	},
504
505	[X1000_CLK_UART1] = {
506		"uart1", CGU_CLK_GATE,
507		.parents = { X1000_CLK_EXCLK},
508		.gate = { CGU_REG_CLKGR, 15 },
509	},
510
511	[X1000_CLK_UART2] = {
512		"uart2", CGU_CLK_GATE,
513		.parents = { X1000_CLK_EXCLK },
514		.gate = { CGU_REG_CLKGR, 16 },
515	},
516
517	[X1000_CLK_TCU] = {
518		"tcu", CGU_CLK_GATE,
519		.parents = { X1000_CLK_EXCLK },
520		.gate = { CGU_REG_CLKGR, 18 },
521	},
522
523	[X1000_CLK_SSI] = {
524		"ssi", CGU_CLK_GATE,
525		.parents = { X1000_CLK_SSIMUX },
526		.gate = { CGU_REG_CLKGR, 19 },
527	},
528
529	[X1000_CLK_OST] = {
530		"ost", CGU_CLK_GATE,
531		.parents = { X1000_CLK_EXCLK },
532		.gate = { CGU_REG_CLKGR, 20 },
533	},
534
535	[X1000_CLK_PDMA] = {
536		"pdma", CGU_CLK_GATE,
537		.parents = { X1000_CLK_EXCLK },
538		.gate = { CGU_REG_CLKGR, 21 },
539	},
540};
541
542static void __init x1000_cgu_init(struct device_node *np)
543{
544	int retval;
545
546	cgu = ingenic_cgu_new(x1000_cgu_clocks,
547			      ARRAY_SIZE(x1000_cgu_clocks), np);
548	if (!cgu) {
549		pr_err("%s: failed to initialise CGU\n", __func__);
550		return;
551	}
552
553	retval = ingenic_cgu_register_clocks(cgu);
554	if (retval) {
555		pr_err("%s: failed to register CGU Clocks\n", __func__);
556		return;
557	}
558
559	ingenic_cgu_register_syscore(cgu);
560}
561/*
562 * CGU has some children devices, this is useful for probing children devices
563 * in the case where the device node is compatible with "simple-mfd".
564 */
565CLK_OF_DECLARE_DRIVER(x1000_cgu, "ingenic,x1000-cgu", x1000_cgu_init);
~/ Read-only file preview.