xref: /linux/drivers/clk/renesas/r9a09g077-cpg.c (revision 502d45774af09f1c681c754c4b7cdfb5d7f72fd9)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * r9a09g077 Clock Pulse Generator / Module Standby and Software Reset
4  *
5  * Copyright (C) 2025 Renesas Electronics Corp.
6  *
7  */
8 
9 #include <linux/bitfield.h>
10 #include <linux/clk-provider.h>
11 #include <linux/clk/renesas.h>
12 #include <linux/device.h>
13 #include <linux/init.h>
14 #include <linux/io.h>
15 #include <linux/iopoll.h>
16 #include <linux/kernel.h>
17 #include <linux/math.h>
18 #include <linux/module.h>
19 #include <linux/types.h>
20 #include <linux/units.h>
21 
22 #include <dt-bindings/clock/renesas,r9a09g077-cpg-mssr.h>
23 #include <dt-bindings/clock/renesas,r9a09g087-cpg-mssr.h>
24 #include "renesas-cpg-mssr.h"
25 
26 MODULE_IMPORT_NS("RZV2H_CPG");
27 
28 #define RZT2H_REG_BLOCK_SHIFT	11
29 #define RZT2H_REG_OFFSET_MASK	GENMASK(10, 0)
30 #define RZT2H_REG_CONF(block, offset)	(((block) << RZT2H_REG_BLOCK_SHIFT) | \
31 					((offset) & RZT2H_REG_OFFSET_MASK))
32 
33 #define RZT2H_REG_BLOCK(x)		((x) >> RZT2H_REG_BLOCK_SHIFT)
34 #define RZT2H_REG_OFFSET(x)		((x) & RZT2H_REG_OFFSET_MASK)
35 
36 #define SCKCR		RZT2H_REG_CONF(0, 0x00)
37 #define SCKCR2		RZT2H_REG_CONF(1, 0x04)
38 #define SCKCR3		RZT2H_REG_CONF(0, 0x08)
39 
40 #define OFFSET_MASK	GENMASK(31, 20)
41 #define SHIFT_MASK	GENMASK(19, 12)
42 #define WIDTH_MASK	GENMASK(11, 8)
43 
44 #define CONF_PACK(offset, shift, width)  \
45 	(FIELD_PREP_CONST(OFFSET_MASK, (offset)) | \
46 	FIELD_PREP_CONST(SHIFT_MASK, (shift)) | \
47 	FIELD_PREP_CONST(WIDTH_MASK, (width)))
48 
49 #define GET_SHIFT(val)         FIELD_GET(SHIFT_MASK, val)
50 #define GET_WIDTH(val)         FIELD_GET(WIDTH_MASK, val)
51 #define GET_REG_OFFSET(val)    FIELD_GET(OFFSET_MASK, val)
52 
53 #define FSELXSPI0	CONF_PACK(SCKCR, 0, 3)
54 #define FSELXSPI1	CONF_PACK(SCKCR, 8, 3)
55 #define DIVSEL_XSPI0	CONF_PACK(SCKCR, 6, 1)
56 #define DIVSEL_XSPI1	CONF_PACK(SCKCR, 14, 1)
57 #define FSELCANFD	CONF_PACK(SCKCR, 20, 1)
58 #define SEL_PLL		CONF_PACK(SCKCR, 22, 1)
59 
60 #define DIVCA55C0	CONF_PACK(SCKCR2, 8, 1)
61 #define DIVCA55C1	CONF_PACK(SCKCR2, 9, 1)
62 #define DIVCA55C2	CONF_PACK(SCKCR2, 10, 1)
63 #define DIVCA55C3	CONF_PACK(SCKCR2, 11, 1)
64 #define DIVCA55S	CONF_PACK(SCKCR2, 12, 1)
65 #define DIVSPI3ASYNC	CONF_PACK(SCKCR2, 16, 2)
66 #define DIVSCI5ASYNC	CONF_PACK(SCKCR2, 18, 2)
67 
68 #define DIVSPI0ASYNC	CONF_PACK(SCKCR3, 0, 2)
69 #define DIVSPI1ASYNC	CONF_PACK(SCKCR3, 2, 2)
70 #define DIVSPI2ASYNC	CONF_PACK(SCKCR3, 4, 2)
71 #define DIVSCI0ASYNC	CONF_PACK(SCKCR3, 6, 2)
72 #define DIVSCI1ASYNC	CONF_PACK(SCKCR3, 8, 2)
73 #define DIVSCI2ASYNC	CONF_PACK(SCKCR3, 10, 2)
74 #define DIVSCI3ASYNC	CONF_PACK(SCKCR3, 12, 2)
75 #define DIVSCI4ASYNC	CONF_PACK(SCKCR3, 14, 2)
76 #define LCDCDIVSEL	CONF_PACK(SCKCR3, 20, 4)
77 
78 #define PLL3EN		FIELD_PREP_CONST(OFFSET_MASK, (0xc0))
79 
80 #define CPG_PLL_EN_EN		BIT(0)
81 #define CPG_PLL3_VCO_CTR0(x)	((x) + 0x4)
82 #define CPG_PLL3_VCO_CTR0_PDIV	GENMASK(21, 16)
83 #define CPG_PLL3_VCO_CTR0_MDIV	GENMASK(9, 0)
84 #define CPG_PLL3_VCO_CTR1(x)	((x) + 0x8)
85 #define CPG_PLL3_VCO_CTR1_KDIV	GENMASK(31, 16)
86 #define CPG_PLL3_VCO_CTR1_SDIV	GENMASK(2, 0)
87 #define CPG_PLL_MON(x)		((x) - 0x10)
88 #define CPG_PLL_MON_LOCK	BIT(0)
89 
90 enum rzt2h_clk_types {
91 	CLK_TYPE_RZT2H_DIV = CLK_TYPE_CUSTOM,	/* Clock with divider */
92 	CLK_TYPE_RZT2H_MUX,			/* Clock with clock source selector */
93 	CLK_TYPE_RZT2H_FSELXSPI,		/* Clock with FSELXSPIn source selector */
94 	CLK_TYPE_RZT2H_PLL3,			/* PLL3 Clock */
95 	CLK_TYPE_RZT2H_LCDCDIV,			/* LCDC divider clock */
96 };
97 
98 #define DEF_DIV(_name, _id, _parent, _conf, _dtable) \
99 	DEF_TYPE(_name, _id, CLK_TYPE_RZT2H_DIV, .conf = _conf, \
100 		 .parent = _parent, .dtable = _dtable, .flag = 0)
101 #define DEF_MUX(_name, _id, _conf, _parent_names, _num_parents, _mux_flags) \
102 	DEF_TYPE(_name, _id, CLK_TYPE_RZT2H_MUX, .conf = _conf, \
103 		 .parent_names = _parent_names, .num_parents = _num_parents, \
104 		 .flag = CLK_SET_RATE_PARENT, .mux_flags = _mux_flags)
105 #define DEF_DIV_FSELXSPI(_name, _id, _parent, _conf, _dtable) \
106 	DEF_TYPE(_name, _id, CLK_TYPE_RZT2H_FSELXSPI, .conf = _conf, \
107 		 .parent = _parent, .dtable = _dtable, .flag = 0)
108 #define DEF_PLL3(_name, _id, _parent, _conf) \
109 	DEF_TYPE(_name, _id, CLK_TYPE_RZT2H_PLL3, .conf = _conf, \
110 		 .parent = _parent)
111 #define DEF_DIV_LCDC(_name, _id, _parent, _conf, _dtable) \
112 	DEF_TYPE(_name, _id, CLK_TYPE_RZT2H_LCDCDIV, .conf = _conf, \
113 		 .parent = _parent, .dtable = _dtable, .flag = CLK_SET_RATE_PARENT)
114 
115 struct pll_clk {
116 	void __iomem *reg;
117 	const struct rzv2h_pll_limits *limits;
118 	struct device *dev;
119 	struct rzv2h_pll_pars pll_parameters;
120 	struct clk_hw hw;
121 	unsigned long cur_rate;
122 };
123 
124 #define to_pll(_hw)	container_of(_hw, struct pll_clk, hw)
125 
126 struct r9a09g077_lcdc_div_clk {
127 	const struct clk_div_table *dtable;
128 	void __iomem *reg;
129 	struct device *dev;
130 	struct clk_hw hw;
131 	u32 conf;
132 	u8 divider;
133 };
134 
135 #define to_lcdc_div_clk(_hw) \
136 	container_of(_hw, struct r9a09g077_lcdc_div_clk, hw)
137 
138 #define RZT2H_MAX_LCDC_DIV_TABLES	16
139 
140 static const struct rzv2h_pll_limits r9a09g077_cpg_pll3_limits = {
141 	.input_fref = 48 * MEGA,
142 	.fout = { .min = 25 * MEGA, .max = 430 * MEGA },
143 	.fvco = { .min = 1600 * MEGA, .max = 3200 * MEGA },
144 	.m = { .min = 0x40, .max = 0x3ff },
145 	.p = { .min = 0x2, .max = 0x8 },
146 	.s = { .min = 0x0, .max = 0x6 },
147 	.k = { .min = -32768, .max = 32767 },
148 };
149 
150 enum clk_ids {
151 	/* Core Clock Outputs exported to DT */
152 	LAST_DT_CORE_CLK = R9A09G077_PCLKRTC,
153 
154 	/* External Input Clocks */
155 	CLK_EXTAL,
156 
157 	/* Internal Core Clocks */
158 	CLK_LOCO,
159 	CLK_PLL0,
160 	CLK_PLL1,
161 	CLK_PLL2,
162 	CLK_PLL3,
163 	CLK_PLL4,
164 	CLK_SEL_CLK_PLL0,
165 	CLK_SEL_CLK_PLL1,
166 	CLK_SEL_CLK_PLL2,
167 	CLK_SEL_CLK_PLL3,
168 	CLK_SEL_CLK_PLL4,
169 	CLK_PLL4D1,
170 	CLK_PLL4D1_DIV3,
171 	CLK_PLL4D1_DIV4,
172 	CLK_PLL4D3,
173 	CLK_PLL4D3_DIV10,
174 	CLK_PLL4D3_DIV20,
175 	CLK_PLL4D50,
176 	CLK_SCI0ASYNC,
177 	CLK_SCI1ASYNC,
178 	CLK_SCI2ASYNC,
179 	CLK_SCI3ASYNC,
180 	CLK_SCI4ASYNC,
181 	CLK_SCI5ASYNC,
182 	CLK_SPI0ASYNC,
183 	CLK_SPI1ASYNC,
184 	CLK_SPI2ASYNC,
185 	CLK_SPI3ASYNC,
186 	CLK_DIVSELXSPI0_SCKCR,
187 	CLK_DIVSELXSPI1_SCKCR,
188 	CLK_LCDDIVSEL,
189 
190 	/* Module Clocks */
191 	MOD_CLK_BASE,
192 };
193 
194 static const struct clk_div_table dtable_1_2[] = {
195 	{0, 2},
196 	{1, 1},
197 	{0, 0},
198 };
199 
200 static const struct clk_div_table dtable_2_32[] = {
201 	{0, 2},
202 	{1, 4},
203 	{2, 6},
204 	{3, 8},
205 	{4, 10},
206 	{5, 12},
207 	{6, 14},
208 	{7, 16},
209 	{8, 18},
210 	{9, 20},
211 	{10, 22},
212 	{11, 24},
213 	{12, 26},
214 	{13, 28},
215 	{14, 30},
216 	{15, 32},
217 	{0, 0},
218 };
219 
220 static const struct clk_div_table dtable_6_8_16_32_64[] = {
221 	{6, 64},
222 	{5, 32},
223 	{4, 16},
224 	{3, 8},
225 	{2, 6},
226 	{0, 0},
227 };
228 
229 static const struct clk_div_table dtable_24_25_30_32[] = {
230 	{0, 32},
231 	{1, 30},
232 	{2, 25},
233 	{3, 24},
234 	{0, 0},
235 };
236 
237 /* Mux clock tables */
238 
239 static const char * const sel_clk_pll0[] = { ".loco", ".pll0" };
240 static const char * const sel_clk_pll1[] = { ".loco", ".pll1" };
241 static const char * const sel_clk_pll2[] = { ".loco", ".pll2" };
242 static const char * const sel_clk_pll3[] = { ".loco", ".pll3" };
243 static const char * const sel_clk_pll4[] = { ".loco", ".pll4" };
244 static const char * const sel_clk_pll4d1_div3_div4[] = { ".pll4d1_div3", ".pll4d1_div4" };
245 static const char * const sel_clk_pll4d3_div10_div20[] = { ".pll4d3_div10", ".pll4d3_div20" };
246 
247 static const struct cpg_core_clk r9a09g077_core_clks[] __initconst = {
248 	/* External Clock Inputs */
249 	DEF_INPUT("extal", CLK_EXTAL),
250 
251 	/* Internal Core Clocks */
252 	DEF_RATE(".loco", CLK_LOCO, 1000 * 1000),
253 	DEF_FIXED(".pll0", CLK_PLL0, CLK_EXTAL, 1, 48),
254 	DEF_FIXED(".pll1", CLK_PLL1, CLK_EXTAL, 1, 40),
255 	DEF_FIXED(".pll2", CLK_PLL2, CLK_EXTAL, 1, 32),
256 	DEF_FIXED(".pll4", CLK_PLL4, CLK_EXTAL, 1, 96),
257 
258 	DEF_MUX(".sel_clk_pll0", CLK_SEL_CLK_PLL0, SEL_PLL,
259 		sel_clk_pll0, ARRAY_SIZE(sel_clk_pll0), CLK_MUX_READ_ONLY),
260 	DEF_MUX(".sel_clk_pll1", CLK_SEL_CLK_PLL1, SEL_PLL,
261 		sel_clk_pll1, ARRAY_SIZE(sel_clk_pll1), CLK_MUX_READ_ONLY),
262 	DEF_MUX(".sel_clk_pll2", CLK_SEL_CLK_PLL2, SEL_PLL,
263 		sel_clk_pll2, ARRAY_SIZE(sel_clk_pll2), CLK_MUX_READ_ONLY),
264 	DEF_MUX(".sel_clk_pll3", CLK_SEL_CLK_PLL3, SEL_PLL,
265 		sel_clk_pll3, ARRAY_SIZE(sel_clk_pll3), CLK_MUX_READ_ONLY),
266 	DEF_MUX(".sel_clk_pll4", CLK_SEL_CLK_PLL4, SEL_PLL,
267 		sel_clk_pll4, ARRAY_SIZE(sel_clk_pll4), CLK_MUX_READ_ONLY),
268 
269 	DEF_FIXED(".pll4d1", CLK_PLL4D1, CLK_SEL_CLK_PLL4, 1, 1),
270 	DEF_FIXED(".pll4d50", CLK_PLL4D50, CLK_SEL_CLK_PLL4, 50, 1),
271 	DEF_PLL3(".pll3", CLK_PLL3, CLK_PLL4D50, PLL3EN),
272 	DEF_FIXED(".pll4d1_div3", CLK_PLL4D1_DIV3, CLK_PLL4D1, 3, 1),
273 	DEF_FIXED(".pll4d1_div4", CLK_PLL4D1_DIV4, CLK_PLL4D1, 4, 1),
274 	DEF_FIXED(".pll4d3", CLK_PLL4D3, CLK_SEL_CLK_PLL4, 3, 1),
275 	DEF_FIXED(".pll4d3_div10", CLK_PLL4D3_DIV10, CLK_PLL4D3, 10, 1),
276 	DEF_FIXED(".pll4d3_div20", CLK_PLL4D3_DIV20, CLK_PLL4D3, 20, 1),
277 
278 	DEF_DIV(".sci0async", CLK_SCI0ASYNC, CLK_PLL4D1, DIVSCI0ASYNC,
279 		dtable_24_25_30_32),
280 	DEF_DIV(".sci1async", CLK_SCI1ASYNC, CLK_PLL4D1, DIVSCI1ASYNC,
281 		dtable_24_25_30_32),
282 	DEF_DIV(".sci2async", CLK_SCI2ASYNC, CLK_PLL4D1, DIVSCI2ASYNC,
283 		dtable_24_25_30_32),
284 	DEF_DIV(".sci3async", CLK_SCI3ASYNC, CLK_PLL4D1, DIVSCI3ASYNC,
285 		dtable_24_25_30_32),
286 	DEF_DIV(".sci4async", CLK_SCI4ASYNC, CLK_PLL4D1, DIVSCI4ASYNC,
287 		dtable_24_25_30_32),
288 	DEF_DIV(".sci5async", CLK_SCI5ASYNC, CLK_PLL4D1, DIVSCI5ASYNC,
289 		dtable_24_25_30_32),
290 
291 	DEF_DIV(".spi0async", CLK_SPI0ASYNC, CLK_PLL4D1, DIVSPI0ASYNC,
292 		dtable_24_25_30_32),
293 	DEF_DIV(".spi1async", CLK_SPI1ASYNC, CLK_PLL4D1, DIVSPI1ASYNC,
294 		dtable_24_25_30_32),
295 	DEF_DIV(".spi2async", CLK_SPI2ASYNC, CLK_PLL4D1, DIVSPI2ASYNC,
296 		dtable_24_25_30_32),
297 	DEF_DIV(".spi3async", CLK_SPI3ASYNC, CLK_PLL4D1, DIVSPI3ASYNC,
298 		dtable_24_25_30_32),
299 
300 	DEF_MUX(".divselxspi0", CLK_DIVSELXSPI0_SCKCR, DIVSEL_XSPI0,
301 		sel_clk_pll4d1_div3_div4,
302 		ARRAY_SIZE(sel_clk_pll4d1_div3_div4), 0),
303 	DEF_MUX(".divselxspi1", CLK_DIVSELXSPI1_SCKCR, DIVSEL_XSPI1,
304 		sel_clk_pll4d1_div3_div4,
305 		ARRAY_SIZE(sel_clk_pll4d1_div3_div4), 0),
306 
307 	/* Core output clk */
308 	DEF_DIV("CA55C0", R9A09G077_CLK_CA55C0, CLK_SEL_CLK_PLL0, DIVCA55C0,
309 		dtable_1_2),
310 	DEF_DIV("CA55C1", R9A09G077_CLK_CA55C1, CLK_SEL_CLK_PLL0, DIVCA55C1,
311 		dtable_1_2),
312 	DEF_DIV("CA55C2", R9A09G077_CLK_CA55C2, CLK_SEL_CLK_PLL0, DIVCA55C2,
313 		dtable_1_2),
314 	DEF_DIV("CA55C3", R9A09G077_CLK_CA55C3, CLK_SEL_CLK_PLL0, DIVCA55C3,
315 		dtable_1_2),
316 	DEF_DIV("CA55S", R9A09G077_CLK_CA55S, CLK_SEL_CLK_PLL0, DIVCA55S,
317 		dtable_1_2),
318 	DEF_FIXED("PCLKGPTL", R9A09G077_CLK_PCLKGPTL, CLK_SEL_CLK_PLL1, 2, 1),
319 	DEF_FIXED("PCLKH", R9A09G077_CLK_PCLKH, CLK_SEL_CLK_PLL1, 4, 1),
320 	DEF_FIXED("PCLKM", R9A09G077_CLK_PCLKM, CLK_SEL_CLK_PLL1, 8, 1),
321 	DEF_FIXED("PCLKL", R9A09G077_CLK_PCLKL, CLK_SEL_CLK_PLL1, 16, 1),
322 	DEF_FIXED("PCLKAH", R9A09G077_CLK_PCLKAH, CLK_PLL4D1, 6, 1),
323 	DEF_FIXED("PCLKAM", R9A09G077_CLK_PCLKAM, CLK_PLL4D1, 12, 1),
324 	DEF_FIXED("PCLKAL", R9A09G077_CLK_PCLKAL, CLK_PLL4D1, 24, 1),
325 	DEF_FIXED("SDHI_CLKHS", R9A09G077_SDHI_CLKHS, CLK_SEL_CLK_PLL2, 1, 1),
326 	DEF_FIXED("USB_CLK", R9A09G077_USB_CLK, CLK_PLL4D1, 48, 1),
327 	DEF_FIXED("ETCLKA", R9A09G077_ETCLKA, CLK_SEL_CLK_PLL1, 5, 1),
328 	DEF_FIXED("ETCLKB", R9A09G077_ETCLKB, CLK_SEL_CLK_PLL1, 8, 1),
329 	DEF_FIXED("ETCLKC", R9A09G077_ETCLKC, CLK_SEL_CLK_PLL1, 10, 1),
330 	DEF_FIXED("ETCLKD", R9A09G077_ETCLKD, CLK_SEL_CLK_PLL1, 20, 1),
331 	DEF_FIXED("ETCLKE", R9A09G077_ETCLKE, CLK_SEL_CLK_PLL1, 40, 1),
332 	DEF_DIV_FSELXSPI("XSPI_CLK0", R9A09G077_XSPI_CLK0, CLK_DIVSELXSPI0_SCKCR,
333 			 FSELXSPI0, dtable_6_8_16_32_64),
334 	DEF_DIV_FSELXSPI("XSPI_CLK1", R9A09G077_XSPI_CLK1, CLK_DIVSELXSPI1_SCKCR,
335 			 FSELXSPI1, dtable_6_8_16_32_64),
336 	DEF_MUX("PCLKCAN", R9A09G077_PCLKCAN, FSELCANFD,
337 		sel_clk_pll4d3_div10_div20, ARRAY_SIZE(sel_clk_pll4d3_div10_div20), 0),
338 	DEF_DIV_LCDC("LCDC_CLKD", R9A09G077_LCDC_CLKD, CLK_SEL_CLK_PLL3, LCDCDIVSEL,
339 		     dtable_2_32),
340 	DEF_FIXED("PCLKRTC", R9A09G077_PCLKRTC, CLK_EXTAL, 128, 1),
341 };
342 
343 static const struct mssr_mod_clk r9a09g077_mod_clks[] __initconst = {
344 	DEF_MOD("xspi0", 4, R9A09G077_CLK_PCLKH),
345 	DEF_MOD("xspi1", 5, R9A09G077_CLK_PCLKH),
346 	DEF_MOD("sci0fck", 8, CLK_SCI0ASYNC),
347 	DEF_MOD("sci1fck", 9, CLK_SCI1ASYNC),
348 	DEF_MOD("sci2fck", 10, CLK_SCI2ASYNC),
349 	DEF_MOD("sci3fck", 11, CLK_SCI3ASYNC),
350 	DEF_MOD("sci4fck", 12, CLK_SCI4ASYNC),
351 	DEF_MOD("iic0", 100, R9A09G077_CLK_PCLKL),
352 	DEF_MOD("iic1", 101, R9A09G077_CLK_PCLKL),
353 	DEF_MOD("spi0", 104, CLK_SPI0ASYNC),
354 	DEF_MOD("spi1", 105, CLK_SPI1ASYNC),
355 	DEF_MOD("spi2", 106, CLK_SPI2ASYNC),
356 	DEF_MOD("mtu3", 200, R9A09G077_CLK_PCLKH),
357 	DEF_MOD("adc0", 206, R9A09G077_CLK_PCLKH),
358 	DEF_MOD("adc1", 207, R9A09G077_CLK_PCLKH),
359 	DEF_MOD("adc2", 225, R9A09G077_CLK_PCLKM),
360 	DEF_MOD("tsu", 307, R9A09G077_CLK_PCLKL),
361 	DEF_MOD("canfd", 310, R9A09G077_CLK_PCLKM),
362 	DEF_MOD("gmac0", 400, R9A09G077_CLK_PCLKM),
363 	DEF_MOD("ethsw", 401, R9A09G077_CLK_PCLKM),
364 	DEF_MOD("ethss", 403, R9A09G077_CLK_PCLKM),
365 	DEF_MOD("usb", 408, R9A09G077_CLK_PCLKAM),
366 	DEF_MOD("gmac1", 416, R9A09G077_CLK_PCLKAM),
367 	DEF_MOD("gmac2", 417, R9A09G077_CLK_PCLKAM),
368 	DEF_MOD("sci5fck", 600, CLK_SCI5ASYNC),
369 	DEF_MOD("iic2", 601, R9A09G077_CLK_PCLKL),
370 	DEF_MOD("spi3", 602, CLK_SPI3ASYNC),
371 	DEF_MOD("rtc", 605, R9A09G077_CLK_PCLKL),
372 	DEF_MOD("lcdc", 1204, R9A09G077_CLK_PCLKAL),
373 	DEF_MOD("sdhi0", 1212, R9A09G077_CLK_PCLKAM),
374 	DEF_MOD("sdhi1", 1213, R9A09G077_CLK_PCLKAM),
375 };
376 
377 static struct clk * __init
r9a09g077_cpg_div_clk_register(struct device * dev,const struct cpg_core_clk * core,void __iomem * addr,struct cpg_mssr_pub * pub)378 r9a09g077_cpg_div_clk_register(struct device *dev,
379 			       const struct cpg_core_clk *core,
380 			       void __iomem *addr, struct cpg_mssr_pub *pub)
381 {
382 	const struct clk *parent;
383 	const char *parent_name;
384 	struct clk_hw *clk_hw;
385 
386 	parent = pub->clks[core->parent];
387 	if (IS_ERR(parent))
388 		return ERR_CAST(parent);
389 
390 	parent_name = __clk_get_name(parent);
391 
392 	if (core->dtable)
393 		clk_hw = devm_clk_hw_register_divider_table(dev, core->name,
394 							    parent_name,
395 							    CLK_SET_RATE_PARENT,
396 							    addr,
397 							    GET_SHIFT(core->conf),
398 							    GET_WIDTH(core->conf),
399 							    core->flag,
400 							    core->dtable,
401 							    &pub->rmw_lock);
402 	else
403 		clk_hw = devm_clk_hw_register_divider(dev, core->name,
404 						      parent_name,
405 						      CLK_SET_RATE_PARENT,
406 						      addr,
407 						      GET_SHIFT(core->conf),
408 						      GET_WIDTH(core->conf),
409 						      core->flag, &pub->rmw_lock);
410 
411 	if (IS_ERR(clk_hw))
412 		return ERR_CAST(clk_hw);
413 
414 	return clk_hw->clk;
415 }
416 
417 static struct clk * __init
r9a09g077_cpg_mux_clk_register(struct device * dev,const struct cpg_core_clk * core,void __iomem * addr,struct cpg_mssr_pub * pub)418 r9a09g077_cpg_mux_clk_register(struct device *dev,
419 			       const struct cpg_core_clk *core,
420 			       void __iomem *addr, struct cpg_mssr_pub *pub)
421 {
422 	struct clk_hw *clk_hw;
423 
424 	clk_hw = devm_clk_hw_register_mux(dev, core->name,
425 					  core->parent_names, core->num_parents,
426 					  core->flag,
427 					  addr,
428 					  GET_SHIFT(core->conf),
429 					  GET_WIDTH(core->conf),
430 					  core->mux_flags, &pub->rmw_lock);
431 	if (IS_ERR(clk_hw))
432 		return ERR_CAST(clk_hw);
433 
434 	return clk_hw->clk;
435 }
436 
r9a09g077_cpg_fselxspi_get_divider(struct clk_hw * hw,unsigned long rate,unsigned int num_parents)437 static unsigned int r9a09g077_cpg_fselxspi_get_divider(struct clk_hw *hw, unsigned long rate,
438 						       unsigned int num_parents)
439 {
440 	struct clk_fixed_factor *ff;
441 	struct clk_hw *parent_hw;
442 	unsigned long best_rate;
443 	unsigned int i;
444 
445 	for (i = 0; i < num_parents; i++) {
446 		parent_hw = clk_hw_get_parent_by_index(hw, i);
447 		best_rate = clk_hw_round_rate(parent_hw, rate);
448 
449 		if (best_rate == rate) {
450 			ff = to_clk_fixed_factor(parent_hw);
451 			return ff->div;
452 		}
453 	}
454 
455 	/* No parent could provide the exact rate - this should not happen */
456 	return 0;
457 }
458 
r9a09g077_cpg_fselxspi_determine_rate(struct clk_hw * hw,struct clk_rate_request * req)459 static int r9a09g077_cpg_fselxspi_determine_rate(struct clk_hw *hw,
460 						 struct clk_rate_request *req)
461 {
462 	struct clk_divider *divider = to_clk_divider(hw);
463 	unsigned long parent_rate, best = 0, now;
464 	const struct clk_div_table *clkt;
465 	unsigned long rate = req->rate;
466 	unsigned int num_parents;
467 	unsigned int divselxspi;
468 	unsigned int div = 0;
469 
470 	if (!rate)
471 		rate = 1;
472 
473 	/* Get the number of parents for FSELXSPIn */
474 	num_parents = clk_hw_get_num_parents(req->best_parent_hw);
475 
476 	for (clkt = divider->table; clkt->div; clkt++) {
477 		parent_rate = clk_hw_round_rate(req->best_parent_hw, rate * clkt->div);
478 		/* Skip if parent can't provide any valid rate */
479 		if (!parent_rate)
480 			continue;
481 
482 		/* Determine which DIVSELXSPIn divider (3 or 4) provides this parent_rate */
483 		divselxspi = r9a09g077_cpg_fselxspi_get_divider(req->best_parent_hw, parent_rate,
484 								num_parents);
485 		if (!divselxspi)
486 			continue;
487 
488 		/*
489 		 * DIVSELXSPIx supports 800MHz and 600MHz operation.
490 		 * When divselxspi is 4 (600MHz operation), only FSELXSPIn dividers of 8 and 16
491 		 * are supported. Otherwise, when divselxspi is 3 (800MHz operation),
492 		 * dividers of 6, 8, 16, 32, and 64 are supported. This check ensures that
493 		 * FSELXSPIx is set correctly based on hardware limitations.
494 		 */
495 		if (divselxspi == 4 && (clkt->div != 8 && clkt->div != 16))
496 			continue;
497 
498 		now = DIV_ROUND_UP_ULL(parent_rate, clkt->div);
499 		if (abs(rate - now) < abs(rate - best)) {
500 			div = clkt->div;
501 			best = now;
502 			req->best_parent_rate = parent_rate;
503 		}
504 	}
505 
506 	if (!div) {
507 		req->best_parent_rate = clk_hw_round_rate(req->best_parent_hw, 1);
508 		divselxspi = r9a09g077_cpg_fselxspi_get_divider(req->best_parent_hw,
509 								req->best_parent_rate,
510 								num_parents);
511 		/* default to divider 3 which will result DIVSELXSPIn = 800 MHz */
512 		if (!divselxspi)
513 			divselxspi = 3;
514 
515 		/*
516 		 * Use the maximum divider based on the parent clock rate:
517 		 *  - 64 when DIVSELXSPIx is 800 MHz (divider = 3)
518 		 *  - 16 when DIVSELXSPIx is 600 MHz (divider = 4)
519 		 */
520 		div = divselxspi == 3 ? 64 : 16;
521 	}
522 
523 	req->rate = DIV_ROUND_UP_ULL(req->best_parent_rate, div);
524 
525 	return 0;
526 }
527 
528 static struct clk * __init
r9a09g077_cpg_fselxspi_div_clk_register(struct device * dev,const struct cpg_core_clk * core,void __iomem * addr,struct cpg_mssr_pub * pub)529 r9a09g077_cpg_fselxspi_div_clk_register(struct device *dev,
530 					const struct cpg_core_clk *core,
531 					void __iomem *addr,
532 					struct cpg_mssr_pub *pub)
533 {
534 	static struct clk_ops *xspi_div_ops;
535 	struct clk_init_data init = {};
536 	const struct clk *parent;
537 	const char *parent_name;
538 	struct clk_divider *div;
539 	struct clk_hw *hw;
540 	int ret;
541 
542 	parent = pub->clks[core->parent];
543 	if (IS_ERR(parent))
544 		return ERR_CAST(parent);
545 
546 	div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL);
547 	if (!div)
548 		return ERR_PTR(-ENOMEM);
549 
550 	if (!xspi_div_ops) {
551 		xspi_div_ops = devm_kzalloc(dev, sizeof(*xspi_div_ops), GFP_KERNEL);
552 		if (!xspi_div_ops)
553 			return  ERR_PTR(-ENOMEM);
554 		memcpy(xspi_div_ops, &clk_divider_ops,
555 		       sizeof(const struct clk_ops));
556 		xspi_div_ops->determine_rate = r9a09g077_cpg_fselxspi_determine_rate;
557 	}
558 
559 	parent_name = __clk_get_name(parent);
560 	init.name = core->name;
561 	init.ops = xspi_div_ops;
562 	init.flags = CLK_SET_RATE_PARENT;
563 	init.parent_names = &parent_name;
564 	init.num_parents = 1;
565 
566 	div->reg = addr;
567 	div->shift = GET_SHIFT(core->conf);
568 	div->width = GET_WIDTH(core->conf);
569 	div->flags = core->flag;
570 	div->lock = &pub->rmw_lock;
571 	div->hw.init = &init;
572 	div->table = core->dtable;
573 
574 	hw = &div->hw;
575 	ret = devm_clk_hw_register(dev, hw);
576 	if (ret)
577 		return ERR_PTR(ret);
578 
579 	return hw->clk;
580 }
581 
r9a09g077_cpg_pll3_clk_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)582 static unsigned long r9a09g077_cpg_pll3_clk_recalc_rate(struct clk_hw *hw,
583 							unsigned long parent_rate)
584 {
585 	struct pll_clk *pll_clk = to_pll(hw);
586 	u32 ctr0, ctr1;
587 	u8 pdiv, sdiv;
588 	u64 rate;
589 	u16 mdiv;
590 	s16 kdiv;
591 
592 	ctr0 = readl(CPG_PLL3_VCO_CTR0(pll_clk->reg));
593 	ctr1 = readl(CPG_PLL3_VCO_CTR1(pll_clk->reg));
594 
595 	pdiv = FIELD_GET(CPG_PLL3_VCO_CTR0_PDIV, ctr0);
596 	mdiv = FIELD_GET(CPG_PLL3_VCO_CTR0_MDIV, ctr0);
597 	kdiv = (s16)FIELD_GET(CPG_PLL3_VCO_CTR1_KDIV, ctr1);
598 	sdiv = FIELD_GET(CPG_PLL3_VCO_CTR1_SDIV, ctr1);
599 
600 	rate = mul_u64_u32_shr(parent_rate, (mdiv << 16) + kdiv, 16 + sdiv);
601 
602 	return DIV_ROUND_CLOSEST_ULL(rate, pdiv);
603 }
604 
r9a09g077_cpg_pll3_determine_rate(struct clk_hw * hw,struct clk_rate_request * req)605 static int r9a09g077_cpg_pll3_determine_rate(struct clk_hw *hw,
606 					     struct clk_rate_request *req)
607 {
608 	struct pll_clk *pll_clk = to_pll(hw);
609 	u64 rate_millihz;
610 
611 	if (req->rate == pll_clk->cur_rate)
612 		return 0;
613 
614 	rate_millihz = mul_u32_u32(req->rate, MILLI);
615 	if (!rzv2h_cpg_get_pll_pars(pll_clk->limits, &pll_clk->pll_parameters,
616 				    rate_millihz)) {
617 		dev_dbg(pll_clk->dev,
618 			"failed to determine rate for req->rate: %lu\n",
619 			req->rate);
620 		return -EINVAL;
621 	}
622 	req->rate = DIV_ROUND_CLOSEST_ULL(pll_clk->pll_parameters.freq_millihz, MILLI);
623 	pll_clk->cur_rate = req->rate;
624 
625 	return 0;
626 }
627 
r9a09g077_cpg_pll3_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)628 static int r9a09g077_cpg_pll3_set_rate(struct clk_hw *hw, unsigned long rate,
629 				       unsigned long parent_rate)
630 {
631 	struct pll_clk *pll_clk = to_pll(hw);
632 	struct rzv2h_pll_pars *params = &pll_clk->pll_parameters;
633 	void __iomem *offset = pll_clk->reg;
634 	u32 val;
635 	int ret;
636 
637 	/* Put PLL into standby mode */
638 	writel(0, offset);
639 	ret = readl_poll_timeout_atomic(CPG_PLL_MON(offset),
640 					val, !(val & CPG_PLL_MON_LOCK),
641 					100, 2000);
642 	if (ret) {
643 		dev_err(pll_clk->dev, "Failed to put PLL into standby mode");
644 		return ret;
645 	}
646 
647 	/* Output clock setting 1 */
648 	val = readl(CPG_PLL3_VCO_CTR0(offset));
649 	FIELD_MODIFY(CPG_PLL3_VCO_CTR0_MDIV, &val, params->m);
650 	FIELD_MODIFY(CPG_PLL3_VCO_CTR0_PDIV, &val, params->p);
651 	writel(val, CPG_PLL3_VCO_CTR0(offset));
652 
653 	/* Output clock setting 2 */
654 	val = readl(CPG_PLL3_VCO_CTR1(offset));
655 	FIELD_MODIFY(CPG_PLL3_VCO_CTR1_KDIV, &val, params->k);
656 	FIELD_MODIFY(CPG_PLL3_VCO_CTR1_SDIV, &val, params->s);
657 	writel(val, CPG_PLL3_VCO_CTR1(offset));
658 
659 	writel(CPG_PLL_EN_EN, offset);
660 
661 	/* PLL normal mode transition, output clock stability check */
662 	ret = readl_poll_timeout_atomic(CPG_PLL_MON(offset),
663 					val, (val & CPG_PLL_MON_LOCK),
664 					100, 2000);
665 	if (ret) {
666 		writel(0, offset);
667 		dev_err(pll_clk->dev, "Failed to put PLL into normal mode");
668 		return ret;
669 	}
670 
671 	return 0;
672 }
673 
674 static const struct clk_ops r9a09g077_cpg_pll3_ops = {
675 	.recalc_rate = r9a09g077_cpg_pll3_clk_recalc_rate,
676 	.determine_rate = r9a09g077_cpg_pll3_determine_rate,
677 	.set_rate = r9a09g077_cpg_pll3_set_rate,
678 };
679 
680 static struct clk * __init
r9a09g077_cpg_pll3_clk_register(struct device * dev,const struct cpg_core_clk * core,void __iomem * addr,struct cpg_mssr_pub * pub,const struct rzv2h_pll_limits * limits)681 r9a09g077_cpg_pll3_clk_register(struct device *dev,
682 				const struct cpg_core_clk *core,
683 				void __iomem *addr,
684 				struct cpg_mssr_pub *pub,
685 				const struct rzv2h_pll_limits *limits)
686 {
687 	struct clk_init_data init = {};
688 	const struct clk *parent;
689 	const char *parent_name;
690 	struct pll_clk *pll_clk;
691 	int ret;
692 
693 	parent = pub->clks[core->parent];
694 	if (IS_ERR(parent))
695 		return ERR_CAST(parent);
696 
697 	pll_clk = devm_kzalloc(dev, sizeof(*pll_clk), GFP_KERNEL);
698 	if (!pll_clk)
699 		return ERR_PTR(-ENOMEM);
700 
701 	parent_name = __clk_get_name(parent);
702 	init.name = core->name;
703 	init.ops = &r9a09g077_cpg_pll3_ops;
704 	init.parent_names = &parent_name;
705 	init.num_parents = 1;
706 
707 	pll_clk->dev = dev;
708 	pll_clk->hw.init = &init;
709 	pll_clk->reg = addr;
710 	pll_clk->limits = limits;
711 
712 	ret = devm_clk_hw_register(dev, &pll_clk->hw);
713 	if (ret)
714 		return ERR_PTR(ret);
715 
716 	return pll_clk->hw.clk;
717 }
718 
r9a09g077_cpg_lcdc_div_determine_rate(struct clk_hw * hw,struct clk_rate_request * req)719 static int r9a09g077_cpg_lcdc_div_determine_rate(struct clk_hw *hw,
720 						 struct clk_rate_request *req)
721 {
722 	struct r9a09g077_lcdc_div_clk *dsi_div = to_lcdc_div_clk(hw);
723 	struct clk_hw *mux_hw = clk_hw_get_parent(hw);
724 	u8 table[RZT2H_MAX_LCDC_DIV_TABLES] = { 0 };
725 	struct rzv2h_pll_div_pars dsi_params;
726 	const struct clk_div_table *div;
727 	struct pll_clk *pll_clk;
728 	unsigned int i = 0;
729 	u64 freq_millihz;
730 
731 	/* index 1 is always .pll3 in sel_clk_pll3[] */
732 	pll_clk = to_pll(clk_hw_get_parent_by_index(mux_hw, 1));
733 
734 	for (div = dsi_div->dtable; div->div; div++) {
735 		if (i >= RZT2H_MAX_LCDC_DIV_TABLES)
736 			return -EINVAL;
737 		table[i++] = div->div;
738 	}
739 
740 	freq_millihz = mul_u32_u32(req->rate, MILLI);
741 
742 	if (!rzv2h_cpg_get_pll_divs_pars(pll_clk->limits, &dsi_params, table,
743 					 i, freq_millihz)) {
744 		dev_err(dsi_div->dev,
745 			"LCDC divider failed to determine rate for req->rate: %lu\n",
746 			req->rate);
747 		return -EINVAL;
748 	}
749 
750 	req->rate = DIV_ROUND_CLOSEST_ULL(dsi_params.div.freq_millihz, MILLI);
751 	req->best_parent_rate = req->rate * dsi_params.div.divider_value;
752 	dsi_div->divider = dsi_params.div.divider_value;
753 	pll_clk->cur_rate = req->best_parent_rate;
754 	pll_clk->pll_parameters = dsi_params.pll;
755 
756 	return 0;
757 }
758 
r9a09g077_cpg_lcdc_div_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)759 static int r9a09g077_cpg_lcdc_div_set_rate(struct clk_hw *hw,
760 					   unsigned long rate,
761 					   unsigned long parent_rate)
762 {
763 	struct r9a09g077_lcdc_div_clk *dsi_div = to_lcdc_div_clk(hw);
764 	const struct clk_div_table *clkt;
765 	bool divider_found = false;
766 	u32 val, shift;
767 
768 	for (clkt = dsi_div->dtable; clkt->div; clkt++) {
769 		if (clkt->div == dsi_div->divider) {
770 			divider_found = true;
771 			break;
772 		}
773 	}
774 
775 	if (!divider_found)
776 		return -EINVAL;
777 
778 	shift = GET_SHIFT(dsi_div->conf);
779 	val = readl(dsi_div->reg);
780 	val &= ~(clk_div_mask(GET_WIDTH(dsi_div->conf)) << shift);
781 	val |= clkt->val << shift;
782 	writel(val, dsi_div->reg);
783 
784 	return 0;
785 }
786 
787 static unsigned long
r9a09g077_cpg_lcdc_div_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)788 r9a09g077_cpg_lcdc_div_recalc_rate(struct clk_hw *hw,
789 				   unsigned long parent_rate)
790 {
791 	struct r9a09g077_lcdc_div_clk *dsi_div = to_lcdc_div_clk(hw);
792 	u32 div;
793 
794 	div = readl(dsi_div->reg);
795 	div >>= GET_SHIFT(dsi_div->conf);
796 	div &= clk_div_mask(GET_WIDTH(dsi_div->conf));
797 	div = dsi_div->dtable[div].div;
798 
799 	return DIV_ROUND_CLOSEST_ULL(parent_rate, div);
800 }
801 
802 static const struct clk_ops r9a09g077_cpg_lcdc_div_ops = {
803 	.recalc_rate = r9a09g077_cpg_lcdc_div_recalc_rate,
804 	.determine_rate = r9a09g077_cpg_lcdc_div_determine_rate,
805 	.set_rate = r9a09g077_cpg_lcdc_div_set_rate,
806 };
807 
808 static struct clk * __init
r9a09g077_cpg_lcdc_div_clk_register(struct device * dev,const struct cpg_core_clk * core,void __iomem * addr,struct cpg_mssr_pub * pub)809 r9a09g077_cpg_lcdc_div_clk_register(struct device *dev,
810 				    const struct cpg_core_clk *core,
811 				    void __iomem *addr,
812 				    struct cpg_mssr_pub *pub)
813 {
814 	struct r9a09g077_lcdc_div_clk *clk_hw_data;
815 	struct clk_init_data init = {};
816 	struct clk **clks = pub->clks;
817 	const struct clk *parent;
818 	const char *parent_name;
819 	struct clk_hw *hw;
820 	int ret;
821 
822 	parent = clks[core->parent];
823 	if (IS_ERR(parent))
824 		return ERR_CAST(parent);
825 
826 	clk_hw_data = devm_kzalloc(dev, sizeof(*clk_hw_data), GFP_KERNEL);
827 	if (!clk_hw_data)
828 		return ERR_PTR(-ENOMEM);
829 
830 	clk_hw_data->dtable = core->dtable;
831 	clk_hw_data->reg = addr;
832 	clk_hw_data->conf = core->conf;
833 	clk_hw_data->dev = dev;
834 	clk_hw_data->divider = 32; /* Initialize divider for LCDC */
835 
836 	parent_name = __clk_get_name(parent);
837 	init.name = core->name;
838 	init.ops = &r9a09g077_cpg_lcdc_div_ops;
839 	init.flags = core->flag;
840 	init.parent_names = &parent_name;
841 	init.num_parents = 1;
842 
843 	hw = &clk_hw_data->hw;
844 	hw->init = &init;
845 	ret = devm_clk_hw_register(dev, hw);
846 	if (ret)
847 		return ERR_PTR(ret);
848 
849 	return hw->clk;
850 }
851 
852 static struct clk * __init
r9a09g077_cpg_clk_register(struct device * dev,const struct cpg_core_clk * core,const struct cpg_mssr_info * info,struct cpg_mssr_pub * pub)853 r9a09g077_cpg_clk_register(struct device *dev, const struct cpg_core_clk *core,
854 			   const struct cpg_mssr_info *info,
855 			   struct cpg_mssr_pub *pub)
856 {
857 	u32 offset = GET_REG_OFFSET(core->conf);
858 	void __iomem *base = RZT2H_REG_BLOCK(offset) ? pub->base1 : pub->base0;
859 	void __iomem *addr = base + RZT2H_REG_OFFSET(offset);
860 
861 	switch (core->type) {
862 	case CLK_TYPE_RZT2H_DIV:
863 		return r9a09g077_cpg_div_clk_register(dev, core, addr, pub);
864 	case CLK_TYPE_RZT2H_MUX:
865 		return r9a09g077_cpg_mux_clk_register(dev, core, addr, pub);
866 	case CLK_TYPE_RZT2H_FSELXSPI:
867 		return r9a09g077_cpg_fselxspi_div_clk_register(dev, core, addr, pub);
868 	case CLK_TYPE_RZT2H_PLL3:
869 		return r9a09g077_cpg_pll3_clk_register(dev, core, pub->base1 + offset,
870 						       pub, &r9a09g077_cpg_pll3_limits);
871 	case CLK_TYPE_RZT2H_LCDCDIV:
872 		return r9a09g077_cpg_lcdc_div_clk_register(dev, core, addr, pub);
873 	default:
874 		return ERR_PTR(-EINVAL);
875 	}
876 }
877 
878 const struct cpg_mssr_info r9a09g077_cpg_mssr_info = {
879 	/* Core Clocks */
880 	.core_clks = r9a09g077_core_clks,
881 	.num_core_clks = ARRAY_SIZE(r9a09g077_core_clks),
882 	.last_dt_core_clk = LAST_DT_CORE_CLK,
883 	.num_total_core_clks = MOD_CLK_BASE,
884 
885 	/* Module Clocks */
886 	.mod_clks = r9a09g077_mod_clks,
887 	.num_mod_clks = ARRAY_SIZE(r9a09g077_mod_clks),
888 	.num_hw_mod_clks = 14 * 32,
889 
890 	.reg_layout = CLK_REG_LAYOUT_RZ_T2H,
891 	.cpg_clk_register = r9a09g077_cpg_clk_register,
892 };
893