xref: /linux/drivers/clk/sophgo/clk-sg2042-clkgen.c (revision a3a02a52bcfcbcc4a637d4b68bf1bc391c9fad02)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Sophgo SG2042 Clock Generator Driver
4  *
5  * Copyright (C) 2024 Sophgo Technology Inc.
6  * Copyright (C) 2024 Chen Wang <unicorn_wang@outlook.com>
7  */
8 
9 #include <linux/array_size.h>
10 #include <linux/bits.h>
11 #include <linux/clk.h>
12 #include <linux/clk-provider.h>
13 #include <linux/io.h>
14 #include <linux/platform_device.h>
15 #include <asm/div64.h>
16 
17 #include <dt-bindings/clock/sophgo,sg2042-clkgen.h>
18 
19 #include "clk-sg2042.h"
20 
21 /* Registers defined in SYS_CTRL */
22 #define R_PLL_BEGIN		0xC0
23 #define R_PLL_STAT		(0xC0 - R_PLL_BEGIN)
24 #define R_PLL_CLKEN_CONTROL	(0xC4 - R_PLL_BEGIN)
25 #define R_MPLL_CONTROL		(0xE8 - R_PLL_BEGIN)
26 #define R_FPLL_CONTROL		(0xF4 - R_PLL_BEGIN)
27 #define R_DPLL0_CONTROL		(0xF8 - R_PLL_BEGIN)
28 #define R_DPLL1_CONTROL		(0xFC - R_PLL_BEGIN)
29 
30 /* Registers defined in CLOCK */
31 #define R_CLKENREG0		0x00
32 #define R_CLKENREG1		0x04
33 #define R_CLKSELREG0		0x20
34 #define R_CLKDIVREG0		0x40
35 #define R_CLKDIVREG1		0x44
36 #define R_CLKDIVREG2		0x48
37 #define R_CLKDIVREG3		0x4C
38 #define R_CLKDIVREG4		0x50
39 #define R_CLKDIVREG5		0x54
40 #define R_CLKDIVREG6		0x58
41 #define R_CLKDIVREG7		0x5C
42 #define R_CLKDIVREG8		0x60
43 #define R_CLKDIVREG9		0x64
44 #define R_CLKDIVREG10		0x68
45 #define R_CLKDIVREG11		0x6C
46 #define R_CLKDIVREG12		0x70
47 #define R_CLKDIVREG13		0x74
48 #define R_CLKDIVREG14		0x78
49 #define R_CLKDIVREG15		0x7C
50 #define R_CLKDIVREG16		0x80
51 #define R_CLKDIVREG17		0x84
52 #define R_CLKDIVREG18		0x88
53 #define R_CLKDIVREG19		0x8C
54 #define R_CLKDIVREG20		0x90
55 #define R_CLKDIVREG21		0x94
56 #define R_CLKDIVREG22		0x98
57 #define R_CLKDIVREG23		0x9C
58 #define R_CLKDIVREG24		0xA0
59 #define R_CLKDIVREG25		0xA4
60 #define R_CLKDIVREG26		0xA8
61 #define R_CLKDIVREG27		0xAC
62 #define R_CLKDIVREG28		0xB0
63 #define R_CLKDIVREG29		0xB4
64 #define R_CLKDIVREG30		0xB8
65 
66 /* All following shift value are the same for all DIV registers */
67 #define SHIFT_DIV_RESET_CTRL	0
68 #define SHIFT_DIV_FACTOR_SEL	3
69 #define SHIFT_DIV_FACTOR	16
70 
71 /**
72  * struct sg2042_divider_clock - Divider clock
73  * @hw:			clk_hw for initialization
74  * @id:			used to map clk_onecell_data
75  * @reg:		used for readl/writel.
76  *			**NOTE**: DIV registers are ALL in CLOCK!
77  * @lock:		spinlock to protect register access, modification of
78  *			frequency can only be served one at the time
79  * @offset_ctrl:	offset of divider control registers
80  * @shift:		shift of "Clock Divider Factor" in divider control register
81  * @width:		width of "Clock Divider Factor" in divider control register
82  * @div_flags:		private flags for this clock, not for framework-specific
83  * @initval:		In the divider control register, we can configure whether
84  *			to use the value of "Clock Divider Factor" or just use
85  *			the initial value pre-configured by IC. BIT[3] controls
86  *			this and by default (value is 0), means initial value
87  *			is used.
88  *			**NOTE** that we cannot read the initial value (default
89  *			value when poweron) and default value of "Clock Divider
90  *			Factor" is zero, which I think is a hardware design flaw
91  *			and should be sync-ed with the initial value. So in
92  *			software we have to add a configuration item (initval)
93  *			to manually configure this value and use it when BIT[3]
94  *			is zero.
95  */
96 struct sg2042_divider_clock {
97 	struct clk_hw hw;
98 
99 	unsigned int id;
100 
101 	void __iomem *reg;
102 	/* protect register access */
103 	spinlock_t *lock;
104 
105 	u32 offset_ctrl;
106 	u8 shift;
107 	u8 width;
108 	u8 div_flags;
109 	u32 initval;
110 };
111 
112 #define to_sg2042_clk_divider(_hw)	\
113 	container_of(_hw, struct sg2042_divider_clock, hw)
114 
115 /**
116  * struct sg2042_gate_clock - Gate clock
117  * @hw:			clk_hw for initialization
118  * @id:			used to map clk_onecell_data
119  * @offset_enable:	offset of gate enable registers
120  * @bit_idx:		which bit in the register controls gating of this clock
121  */
122 struct sg2042_gate_clock {
123 	struct clk_hw hw;
124 
125 	unsigned int id;
126 
127 	u32 offset_enable;
128 	u8 bit_idx;
129 };
130 
131 /**
132  * struct sg2042_mux_clock - Mux clock
133  * @hw:			clk_hw for initialization
134  * @id:			used to map clk_onecell_data
135  * @offset_select:	offset of mux selection registers
136  *			**NOTE**: MUX registers are ALL in CLOCK!
137  * @shift:		shift of "Clock Select" in mux selection register
138  * @width:		width of "Clock Select" in mux selection register
139  * @clk_nb:		used for notification
140  * @original_index:	set by notifier callback
141  */
142 struct sg2042_mux_clock {
143 	struct clk_hw hw;
144 
145 	unsigned int id;
146 
147 	u32 offset_select;
148 	u8 shift;
149 	u8 width;
150 
151 	struct notifier_block clk_nb;
152 	u8 original_index;
153 };
154 
155 #define to_sg2042_mux_nb(_nb) container_of(_nb, struct sg2042_mux_clock, clk_nb)
156 
157 static unsigned long sg2042_clk_divider_recalc_rate(struct clk_hw *hw,
158 						    unsigned long parent_rate)
159 {
160 	struct sg2042_divider_clock *divider = to_sg2042_clk_divider(hw);
161 	unsigned long ret_rate;
162 	u32 val;
163 
164 	if (!(readl(divider->reg) & BIT(SHIFT_DIV_FACTOR_SEL))) {
165 		val = divider->initval;
166 	} else {
167 		val = readl(divider->reg) >> divider->shift;
168 		val &= clk_div_mask(divider->width);
169 	}
170 
171 	ret_rate = divider_recalc_rate(hw, parent_rate, val, NULL,
172 				       divider->div_flags, divider->width);
173 
174 	pr_debug("--> %s: divider_recalc_rate: ret_rate = %ld\n",
175 		 clk_hw_get_name(hw), ret_rate);
176 	return ret_rate;
177 }
178 
179 static long sg2042_clk_divider_round_rate(struct clk_hw *hw,
180 					  unsigned long rate,
181 					  unsigned long *prate)
182 {
183 	struct sg2042_divider_clock *divider = to_sg2042_clk_divider(hw);
184 	unsigned long ret_rate;
185 	u32 bestdiv;
186 
187 	/* if read only, just return current value */
188 	if (divider->div_flags & CLK_DIVIDER_READ_ONLY) {
189 		if (!(readl(divider->reg) & BIT(SHIFT_DIV_FACTOR_SEL))) {
190 			bestdiv = divider->initval;
191 		} else {
192 			bestdiv = readl(divider->reg) >> divider->shift;
193 			bestdiv &= clk_div_mask(divider->width);
194 		}
195 		ret_rate = DIV_ROUND_UP_ULL((u64)*prate, bestdiv);
196 	} else {
197 		ret_rate = divider_round_rate(hw, rate, prate, NULL,
198 					      divider->width, divider->div_flags);
199 	}
200 
201 	pr_debug("--> %s: divider_round_rate: val = %ld\n",
202 		 clk_hw_get_name(hw), ret_rate);
203 	return ret_rate;
204 }
205 
206 static int sg2042_clk_divider_set_rate(struct clk_hw *hw,
207 				       unsigned long rate,
208 				       unsigned long parent_rate)
209 {
210 	struct sg2042_divider_clock *divider = to_sg2042_clk_divider(hw);
211 	unsigned long flags = 0;
212 	u32 val, val2, value;
213 
214 	value = divider_get_val(rate, parent_rate, NULL,
215 				divider->width, divider->div_flags);
216 
217 	if (divider->lock)
218 		spin_lock_irqsave(divider->lock, flags);
219 	else
220 		__acquire(divider->lock);
221 
222 	/*
223 	 * The sequence of clock frequency modification is:
224 	 * Assert to reset divider.
225 	 * Modify the value of Clock Divide Factor (and High Wide if needed).
226 	 * De-assert to restore divided clock with new frequency.
227 	 */
228 	val = readl(divider->reg);
229 
230 	/* assert */
231 	val &= ~BIT(SHIFT_DIV_RESET_CTRL);
232 	writel(val, divider->reg);
233 
234 	if (divider->div_flags & CLK_DIVIDER_HIWORD_MASK) {
235 		val = clk_div_mask(divider->width) << (divider->shift + 16);
236 	} else {
237 		val = readl(divider->reg);
238 		val &= ~(clk_div_mask(divider->width) << divider->shift);
239 	}
240 	val |= value << divider->shift;
241 	val |= BIT(SHIFT_DIV_FACTOR_SEL);
242 	writel(val, divider->reg);
243 	val2 = val;
244 
245 	/* de-assert */
246 	val |= BIT(SHIFT_DIV_RESET_CTRL);
247 	writel(val, divider->reg);
248 
249 	if (divider->lock)
250 		spin_unlock_irqrestore(divider->lock, flags);
251 	else
252 		__release(divider->lock);
253 
254 	pr_debug("--> %s: divider_set_rate: register val = 0x%x\n",
255 		 clk_hw_get_name(hw), val2);
256 	return 0;
257 }
258 
259 static const struct clk_ops sg2042_clk_divider_ops = {
260 	.recalc_rate = sg2042_clk_divider_recalc_rate,
261 	.round_rate = sg2042_clk_divider_round_rate,
262 	.set_rate = sg2042_clk_divider_set_rate,
263 };
264 
265 static const struct clk_ops sg2042_clk_divider_ro_ops = {
266 	.recalc_rate = sg2042_clk_divider_recalc_rate,
267 	.round_rate = sg2042_clk_divider_round_rate,
268 };
269 
270 /*
271  * Clock initialization macro naming rules:
272  * FW: use CLK_HW_INIT_FW_NAME
273  * HW: use CLK_HW_INIT_HW
274  * HWS: use CLK_HW_INIT_HWS
275  * RO: means Read-Only
276  */
277 #define SG2042_DIV_FW(_id, _name, _parent,				\
278 		      _r_ctrl, _shift, _width,				\
279 		      _div_flag, _initval) {				\
280 		.id = _id,						\
281 		.hw.init = CLK_HW_INIT_FW_NAME(				\
282 				_name,					\
283 				_parent,				\
284 				&sg2042_clk_divider_ops,		\
285 				0),					\
286 		.offset_ctrl = _r_ctrl,					\
287 		.shift = _shift,					\
288 		.width = _width,					\
289 		.div_flags = _div_flag,					\
290 		.initval = _initval,					\
291 	}
292 
293 #define SG2042_DIV_FW_RO(_id, _name, _parent,				\
294 		  _r_ctrl, _shift, _width,				\
295 		  _div_flag, _initval) {				\
296 		.id = _id,						\
297 		.hw.init = CLK_HW_INIT_FW_NAME(				\
298 				_name,					\
299 				_parent,				\
300 				&sg2042_clk_divider_ro_ops,		\
301 				0),					\
302 		.offset_ctrl = _r_ctrl,					\
303 		.shift = _shift,					\
304 		.width = _width,					\
305 		.div_flags = (_div_flag) | CLK_DIVIDER_READ_ONLY,	\
306 		.initval = _initval,					\
307 	}
308 
309 #define SG2042_DIV_HW(_id, _name, _parent,				\
310 		      _r_ctrl, _shift, _width,				\
311 		      _div_flag, _initval) {				\
312 		.id = _id,						\
313 		.hw.init = CLK_HW_INIT_HW(				\
314 				_name,					\
315 				_parent,				\
316 				&sg2042_clk_divider_ops,		\
317 				0),					\
318 		.offset_ctrl = _r_ctrl,					\
319 		.shift = _shift,					\
320 		.width = _width,					\
321 		.div_flags = _div_flag,					\
322 		.initval = _initval,					\
323 	}
324 
325 #define SG2042_DIV_HW_RO(_id, _name, _parent,				\
326 			 _r_ctrl, _shift, _width,			\
327 			 _div_flag, _initval) {				\
328 		.id = _id,						\
329 		.hw.init = CLK_HW_INIT_HW(				\
330 				_name,					\
331 				_parent,				\
332 				&sg2042_clk_divider_ro_ops,		\
333 				0),					\
334 		.offset_ctrl = _r_ctrl,					\
335 		.shift = _shift,					\
336 		.width = _width,					\
337 		.div_flags = (_div_flag) | CLK_DIVIDER_READ_ONLY,	\
338 		.initval = _initval,					\
339 	}
340 
341 #define SG2042_DIV_HWS(_id, _name, _parent,				\
342 		       _r_ctrl, _shift, _width,				\
343 		       _div_flag, _initval) {				\
344 		.id = _id,						\
345 		.hw.init = CLK_HW_INIT_HWS(				\
346 				_name,					\
347 				_parent,				\
348 				&sg2042_clk_divider_ops,		\
349 				0),					\
350 		.offset_ctrl = _r_ctrl,					\
351 		.shift = _shift,					\
352 		.width = _width,					\
353 		.div_flags = _div_flag,					\
354 		.initval = _initval,					\
355 	}
356 
357 #define SG2042_DIV_HWS_RO(_id, _name, _parent,				\
358 			  _r_ctrl, _shift, _width,			\
359 			  _div_flag, _initval) {			\
360 		.id = _id,						\
361 		.hw.init = CLK_HW_INIT_HWS(				\
362 				_name,					\
363 				_parent,				\
364 				&sg2042_clk_divider_ro_ops,		\
365 				0),					\
366 		.offset_ctrl = _r_ctrl,					\
367 		.shift = _shift,					\
368 		.width = _width,					\
369 		.div_flags = (_div_flag) | CLK_DIVIDER_READ_ONLY,	\
370 		.initval = _initval,					\
371 	}
372 
373 #define SG2042_GATE_HWS(_id, _name, _parent, _flags,	\
374 			_r_enable, _bit_idx) {		\
375 		.id = _id,				\
376 		.hw.init = CLK_HW_INIT_HWS(		\
377 				_name,			\
378 				_parent,		\
379 				NULL,			\
380 				_flags),		\
381 		.offset_enable = _r_enable,		\
382 		.bit_idx = _bit_idx,			\
383 	}
384 
385 #define SG2042_GATE_HW(_id, _name, _parent, _flags,	\
386 		       _r_enable, _bit_idx) {		\
387 		.id = _id,				\
388 		.hw.init = CLK_HW_INIT_HW(		\
389 				_name,			\
390 				_parent,		\
391 				NULL,			\
392 				_flags),		\
393 		.offset_enable = _r_enable,		\
394 		.bit_idx = _bit_idx,			\
395 	}
396 
397 #define SG2042_GATE_FW(_id, _name, _parent, _flags,	\
398 		       _r_enable, _bit_idx) {		\
399 		.id = _id,				\
400 		.hw.init = CLK_HW_INIT_FW_NAME(		\
401 				_name,			\
402 				_parent,		\
403 				NULL,			\
404 				_flags),		\
405 		.offset_enable = _r_enable,		\
406 		.bit_idx = _bit_idx,			\
407 	}
408 
409 #define SG2042_MUX(_id, _name, _parents, _flags, _r_select, _shift, _width) { \
410 		.id = _id,					\
411 		.hw.init = CLK_HW_INIT_PARENTS_HW(		\
412 				_name,				\
413 				_parents,			\
414 				NULL,				\
415 				_flags),			\
416 		.offset_select = _r_select,			\
417 		.shift = _shift,				\
418 		.width = _width,				\
419 	}
420 
421 /*
422  * Clock items in the array are sorted according to the clock-tree diagram,
423  * from top to bottom, from upstream to downstream. Read TRM for details.
424  */
425 
426 /* updated during probe/registration */
427 static const struct clk_hw *clk_gate_ddr01_div0[] = { NULL };
428 static const struct clk_hw *clk_gate_ddr01_div1[] = { NULL };
429 static const struct clk_hw *clk_gate_ddr23_div0[] = { NULL };
430 static const struct clk_hw *clk_gate_ddr23_div1[] = { NULL };
431 static const struct clk_hw *clk_gate_rp_cpu_normal_div0[] = { NULL };
432 static const struct clk_hw *clk_gate_rp_cpu_normal_div1[] = { NULL };
433 static const struct clk_hw *clk_gate_axi_ddr_div0[] = { NULL };
434 static const struct clk_hw *clk_gate_axi_ddr_div1[] = { NULL };
435 
436 static const struct sg2042_gate_clock sg2042_gate_clks_level_1[] = {
437 	SG2042_GATE_FW(GATE_CLK_DDR01_DIV0, "clk_gate_ddr01_div0", "dpll0",
438 		       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
439 		       R_CLKDIVREG27, 4),
440 	SG2042_GATE_FW(GATE_CLK_DDR01_DIV1, "clk_gate_ddr01_div1", "fpll",
441 		       CLK_IS_CRITICAL,
442 		       R_CLKDIVREG28, 4),
443 
444 	SG2042_GATE_FW(GATE_CLK_DDR23_DIV0, "clk_gate_ddr23_div0", "dpll1",
445 		       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
446 		       R_CLKDIVREG29, 4),
447 	SG2042_GATE_FW(GATE_CLK_DDR23_DIV1, "clk_gate_ddr23_div1", "fpll",
448 		       CLK_IS_CRITICAL,
449 		       R_CLKDIVREG30, 4),
450 
451 	SG2042_GATE_FW(GATE_CLK_RP_CPU_NORMAL_DIV0,
452 		       "clk_gate_rp_cpu_normal_div0", "mpll",
453 		       CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
454 		       R_CLKDIVREG0, 4),
455 	SG2042_GATE_FW(GATE_CLK_RP_CPU_NORMAL_DIV1,
456 		       "clk_gate_rp_cpu_normal_div1", "fpll",
457 		       CLK_IS_CRITICAL,
458 		       R_CLKDIVREG1, 4),
459 
460 	SG2042_GATE_FW(GATE_CLK_AXI_DDR_DIV0, "clk_gate_axi_ddr_div0", "mpll",
461 		       CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
462 		       R_CLKDIVREG25, 4),
463 	SG2042_GATE_FW(GATE_CLK_AXI_DDR_DIV1, "clk_gate_axi_ddr_div1", "fpll",
464 		       CLK_IS_CRITICAL,
465 		       R_CLKDIVREG26, 4),
466 };
467 
468 #define DEF_DIVFLAG (CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO)
469 
470 static struct sg2042_divider_clock sg2042_div_clks_level_1[] = {
471 	SG2042_DIV_HWS_RO(DIV_CLK_DPLL0_DDR01_0,
472 			  "clk_div_ddr01_0", clk_gate_ddr01_div0,
473 			  R_CLKDIVREG27, 16, 5, DEF_DIVFLAG, 1),
474 	SG2042_DIV_HWS_RO(DIV_CLK_FPLL_DDR01_1,
475 			  "clk_div_ddr01_1", clk_gate_ddr01_div1,
476 			  R_CLKDIVREG28, 16, 5, DEF_DIVFLAG, 1),
477 
478 	SG2042_DIV_HWS_RO(DIV_CLK_DPLL1_DDR23_0,
479 			  "clk_div_ddr23_0", clk_gate_ddr23_div0,
480 			  R_CLKDIVREG29, 16, 5, DEF_DIVFLAG, 1),
481 	SG2042_DIV_HWS_RO(DIV_CLK_FPLL_DDR23_1,
482 			  "clk_div_ddr23_1", clk_gate_ddr23_div1,
483 			  R_CLKDIVREG30, 16, 5, DEF_DIVFLAG, 1),
484 
485 	SG2042_DIV_HWS(DIV_CLK_MPLL_RP_CPU_NORMAL_0,
486 		       "clk_div_rp_cpu_normal_0", clk_gate_rp_cpu_normal_div0,
487 		       R_CLKDIVREG0, 16, 5, DEF_DIVFLAG, 1),
488 	SG2042_DIV_HWS(DIV_CLK_FPLL_RP_CPU_NORMAL_1,
489 		       "clk_div_rp_cpu_normal_1", clk_gate_rp_cpu_normal_div1,
490 		       R_CLKDIVREG1, 16, 5, DEF_DIVFLAG, 1),
491 
492 	SG2042_DIV_HWS(DIV_CLK_MPLL_AXI_DDR_0,
493 		       "clk_div_axi_ddr_0", clk_gate_axi_ddr_div0,
494 		       R_CLKDIVREG25, 16, 5, DEF_DIVFLAG, 2),
495 	SG2042_DIV_HWS(DIV_CLK_FPLL_AXI_DDR_1,
496 		       "clk_div_axi_ddr_1", clk_gate_axi_ddr_div1,
497 		       R_CLKDIVREG26, 16, 5, DEF_DIVFLAG, 1),
498 };
499 
500 /*
501  * Note: regarding names for mux clock, "0/1" or "div0/div1" means the
502  * first/second parent input source, not the register value.
503  * For example:
504  * "clk_div_ddr01_0" is the name of Clock divider 0 control of DDR01, and
505  * "clk_gate_ddr01_div0" is the gate clock in front of the "clk_div_ddr01_0",
506  * they are both controlled by register CLKDIVREG27;
507  * "clk_div_ddr01_1" is the name of Clock divider 1 control of DDR01, and
508  * "clk_gate_ddr01_div1" is the gate clock in front of the "clk_div_ddr01_1",
509  * they are both controlled by register CLKDIVREG28;
510  * While for register value of mux selection, use Clock Select for DDR01’s clock
511  * as example, see CLKSELREG0, bit[2].
512  * 1: Select in_dpll0_clk as clock source, correspondng to the parent input
513  *    source from "clk_div_ddr01_0".
514  * 0: Select in_fpll_clk as clock source, corresponding to the parent input
515  *    source from "clk_div_ddr01_1".
516  * So we need a table to define the array of register values corresponding to
517  * the parent index and tell CCF about this when registering mux clock.
518  */
519 static const u32 sg2042_mux_table[] = {1, 0};
520 
521 /* Aliases just for easy reading */
522 #define clk_div_ddr01_0		(&sg2042_div_clks_level_1[0].hw)
523 #define clk_div_ddr01_1		(&sg2042_div_clks_level_1[1].hw)
524 #define clk_div_ddr23_0		(&sg2042_div_clks_level_1[2].hw)
525 #define clk_div_ddr23_1		(&sg2042_div_clks_level_1[3].hw)
526 #define clk_div_rp_cpu_normal_0	(&sg2042_div_clks_level_1[4].hw)
527 #define clk_div_rp_cpu_normal_1	(&sg2042_div_clks_level_1[5].hw)
528 #define clk_div_axi_ddr_0	(&sg2042_div_clks_level_1[6].hw)
529 #define clk_div_axi_ddr_1	(&sg2042_div_clks_level_1[7].hw)
530 
531 static const struct clk_hw *clk_mux_ddr01_p[] = {
532 	clk_div_ddr01_0,
533 	clk_div_ddr01_1,
534 };
535 
536 static const struct clk_hw *clk_mux_ddr23_p[] = {
537 	clk_div_ddr23_0,
538 	clk_div_ddr23_1,
539 };
540 
541 static const struct clk_hw *clk_mux_rp_cpu_normal_p[] = {
542 	clk_div_rp_cpu_normal_0,
543 	clk_div_rp_cpu_normal_1,
544 };
545 
546 static const struct clk_hw *clk_mux_axi_ddr_p[] = {
547 	clk_div_axi_ddr_0,
548 	clk_div_axi_ddr_1,
549 };
550 
551 /* Mux clocks to be updated during probe/registration */
552 static const struct clk_hw *clk_mux_ddr01[] = { NULL };
553 static const struct clk_hw *clk_mux_ddr23[] = { NULL };
554 static const struct clk_hw *clk_mux_rp_cpu_normal[] = { NULL };
555 static const struct clk_hw *clk_mux_axi_ddr[] = { NULL };
556 
557 static struct sg2042_mux_clock sg2042_mux_clks[] = {
558 	SG2042_MUX(MUX_CLK_DDR01, "clk_mux_ddr01", clk_mux_ddr01_p,
559 		   CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT | CLK_MUX_READ_ONLY,
560 		   R_CLKSELREG0, 2, 1),
561 	SG2042_MUX(MUX_CLK_DDR23, "clk_mux_ddr23", clk_mux_ddr23_p,
562 		   CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT | CLK_MUX_READ_ONLY,
563 		   R_CLKSELREG0, 3, 1),
564 	SG2042_MUX(MUX_CLK_RP_CPU_NORMAL, "clk_mux_rp_cpu_normal", clk_mux_rp_cpu_normal_p,
565 		   CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
566 		   R_CLKSELREG0, 0, 1),
567 	SG2042_MUX(MUX_CLK_AXI_DDR, "clk_mux_axi_ddr", clk_mux_axi_ddr_p,
568 		   CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
569 		   R_CLKSELREG0, 1, 1),
570 };
571 
572 /* Aliases just for easy reading */
573 #define clk_div_top_rp_cmn_div2	(&sg2042_div_clks_level_2[0].hw)
574 #define clk_div_50m_a53		(&sg2042_div_clks_level_2[1].hw)
575 #define clk_div_timer1		(&sg2042_div_clks_level_2[2].hw)
576 #define clk_div_timer2		(&sg2042_div_clks_level_2[3].hw)
577 #define clk_div_timer3		(&sg2042_div_clks_level_2[4].hw)
578 #define clk_div_timer4		(&sg2042_div_clks_level_2[5].hw)
579 #define clk_div_timer5		(&sg2042_div_clks_level_2[6].hw)
580 #define clk_div_timer6		(&sg2042_div_clks_level_2[7].hw)
581 #define clk_div_timer7		(&sg2042_div_clks_level_2[8].hw)
582 #define clk_div_timer8		(&sg2042_div_clks_level_2[9].hw)
583 #define clk_div_uart_500m	(&sg2042_div_clks_level_2[10].hw)
584 #define clk_div_ahb_lpc		(&sg2042_div_clks_level_2[11].hw)
585 #define clk_div_efuse		(&sg2042_div_clks_level_2[12].hw)
586 #define clk_div_tx_eth0		(&sg2042_div_clks_level_2[13].hw)
587 #define clk_div_ptp_ref_i_eth0	(&sg2042_div_clks_level_2[14].hw)
588 #define clk_div_ref_eth0	(&sg2042_div_clks_level_2[15].hw)
589 #define clk_div_emmc		(&sg2042_div_clks_level_2[16].hw)
590 #define clk_div_sd		(&sg2042_div_clks_level_2[17].hw)
591 #define clk_div_top_axi0	(&sg2042_div_clks_level_2[18].hw)
592 #define clk_div_100k_emmc	(&sg2042_div_clks_level_2[19].hw)
593 #define clk_div_100k_sd		(&sg2042_div_clks_level_2[20].hw)
594 #define clk_div_gpio_db		(&sg2042_div_clks_level_2[21].hw)
595 #define clk_div_top_axi_hsperi	(&sg2042_div_clks_level_2[22].hw)
596 
597 static struct sg2042_divider_clock sg2042_div_clks_level_2[] = {
598 	SG2042_DIV_HWS(DIV_CLK_FPLL_TOP_RP_CMN_DIV2,
599 		       "clk_div_top_rp_cmn_div2", clk_mux_rp_cpu_normal,
600 		       R_CLKDIVREG3, 16, 16, DEF_DIVFLAG, 2),
601 
602 	SG2042_DIV_FW(DIV_CLK_FPLL_50M_A53, "clk_div_50m_a53", "fpll",
603 		      R_CLKDIVREG2, 16, 8, DEF_DIVFLAG, 20),
604 	/* downstream of div_50m_a53 */
605 	SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER1, "clk_div_timer1", clk_div_50m_a53,
606 		      R_CLKDIVREG6, 16, 16, DEF_DIVFLAG, 1),
607 	SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER2, "clk_div_timer2", clk_div_50m_a53,
608 		      R_CLKDIVREG7, 16, 16, DEF_DIVFLAG, 1),
609 	SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER3, "clk_div_timer3", clk_div_50m_a53,
610 		      R_CLKDIVREG8, 16, 16, DEF_DIVFLAG, 1),
611 	SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER4, "clk_div_timer4", clk_div_50m_a53,
612 		      R_CLKDIVREG9, 16, 16, DEF_DIVFLAG, 1),
613 	SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER5, "clk_div_timer5", clk_div_50m_a53,
614 		      R_CLKDIVREG10, 16, 16, DEF_DIVFLAG, 1),
615 	SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER6, "clk_div_timer6", clk_div_50m_a53,
616 		      R_CLKDIVREG11, 16, 16, DEF_DIVFLAG, 1),
617 	SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER7, "clk_div_timer7", clk_div_50m_a53,
618 		      R_CLKDIVREG12, 16, 16, DEF_DIVFLAG, 1),
619 	SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER8, "clk_div_timer8", clk_div_50m_a53,
620 		      R_CLKDIVREG13, 16, 16, DEF_DIVFLAG, 1),
621 
622 	/*
623 	 * Set clk_div_uart_500m as RO, because the width of CLKDIVREG4 is too
624 	 * narrow for us to produce 115200. Use UART internal divider directly.
625 	 */
626 	SG2042_DIV_FW_RO(DIV_CLK_FPLL_UART_500M, "clk_div_uart_500m", "fpll",
627 			 R_CLKDIVREG4, 16, 7, DEF_DIVFLAG, 2),
628 	SG2042_DIV_FW(DIV_CLK_FPLL_AHB_LPC, "clk_div_ahb_lpc", "fpll",
629 		      R_CLKDIVREG5, 16, 16, DEF_DIVFLAG, 5),
630 	SG2042_DIV_FW(DIV_CLK_FPLL_EFUSE, "clk_div_efuse", "fpll",
631 		      R_CLKDIVREG14, 16, 7, DEF_DIVFLAG, 40),
632 	SG2042_DIV_FW(DIV_CLK_FPLL_TX_ETH0, "clk_div_tx_eth0", "fpll",
633 		      R_CLKDIVREG16, 16, 11, DEF_DIVFLAG, 8),
634 	SG2042_DIV_FW(DIV_CLK_FPLL_PTP_REF_I_ETH0,
635 		      "clk_div_ptp_ref_i_eth0", "fpll",
636 		      R_CLKDIVREG17, 16, 8, DEF_DIVFLAG, 20),
637 	SG2042_DIV_FW(DIV_CLK_FPLL_REF_ETH0, "clk_div_ref_eth0", "fpll",
638 		      R_CLKDIVREG18, 16, 8, DEF_DIVFLAG, 40),
639 	SG2042_DIV_FW(DIV_CLK_FPLL_EMMC, "clk_div_emmc", "fpll",
640 		      R_CLKDIVREG19, 16, 5, DEF_DIVFLAG, 10),
641 	SG2042_DIV_FW(DIV_CLK_FPLL_SD, "clk_div_sd", "fpll",
642 		      R_CLKDIVREG21, 16, 5, DEF_DIVFLAG, 10),
643 
644 	SG2042_DIV_FW(DIV_CLK_FPLL_TOP_AXI0, "clk_div_top_axi0", "fpll",
645 		      R_CLKDIVREG23, 16, 5, DEF_DIVFLAG, 10),
646 	/* downstream of div_top_axi0 */
647 	SG2042_DIV_HW(DIV_CLK_FPLL_100K_EMMC, "clk_div_100k_emmc", clk_div_top_axi0,
648 		      R_CLKDIVREG20, 16, 16, DEF_DIVFLAG, 1000),
649 	SG2042_DIV_HW(DIV_CLK_FPLL_100K_SD, "clk_div_100k_sd", clk_div_top_axi0,
650 		      R_CLKDIVREG22, 16, 16, DEF_DIVFLAG, 1000),
651 	SG2042_DIV_HW(DIV_CLK_FPLL_GPIO_DB, "clk_div_gpio_db", clk_div_top_axi0,
652 		      R_CLKDIVREG15, 16, 16, DEF_DIVFLAG, 1000),
653 
654 	SG2042_DIV_FW(DIV_CLK_FPLL_TOP_AXI_HSPERI,
655 		      "clk_div_top_axi_hsperi", "fpll",
656 		      R_CLKDIVREG24, 16, 5, DEF_DIVFLAG, 4),
657 };
658 
659 /* Gate clocks to be updated during probe/registration */
660 static const struct clk_hw *clk_gate_rp_cpu_normal[] = { NULL };
661 static const struct clk_hw *clk_gate_top_rp_cmn_div2[] = { NULL };
662 
663 static const struct sg2042_gate_clock sg2042_gate_clks_level_2[] = {
664 	SG2042_GATE_HWS(GATE_CLK_DDR01, "clk_gate_ddr01", clk_mux_ddr01,
665 			CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
666 			R_CLKENREG1, 14),
667 
668 	SG2042_GATE_HWS(GATE_CLK_DDR23, "clk_gate_ddr23", clk_mux_ddr23,
669 			CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
670 			R_CLKENREG1, 15),
671 
672 	SG2042_GATE_HWS(GATE_CLK_RP_CPU_NORMAL,
673 			"clk_gate_rp_cpu_normal", clk_mux_rp_cpu_normal,
674 			CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
675 			R_CLKENREG0, 0),
676 
677 	SG2042_GATE_HWS(GATE_CLK_AXI_DDR, "clk_gate_axi_ddr", clk_mux_axi_ddr,
678 			CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
679 			R_CLKENREG1, 13),
680 
681 	/* upon are gate clocks directly downstream of muxes */
682 
683 	/* downstream of clk_div_top_rp_cmn_div2 */
684 	SG2042_GATE_HW(GATE_CLK_TOP_RP_CMN_DIV2,
685 		       "clk_gate_top_rp_cmn_div2", clk_div_top_rp_cmn_div2,
686 		       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG0, 2),
687 	SG2042_GATE_HWS(GATE_CLK_HSDMA, "clk_gate_hsdma", clk_gate_top_rp_cmn_div2,
688 			CLK_SET_RATE_PARENT, R_CLKENREG1, 10),
689 
690 	/*
691 	 * downstream of clk_gate_rp_cpu_normal
692 	 *
693 	 * FIXME: there should be one 1/2 DIV between clk_gate_rp_cpu_normal
694 	 * and clk_gate_axi_pcie0/clk_gate_axi_pcie1.
695 	 * But the 1/2 DIV is fixed and no configurable register exported, so
696 	 * when reading from these two clocks, the rate value are still the
697 	 * same as that of clk_gate_rp_cpu_normal, it's not correct.
698 	 * This just affects the value read.
699 	 */
700 	SG2042_GATE_HWS(GATE_CLK_AXI_PCIE0,
701 			"clk_gate_axi_pcie0", clk_gate_rp_cpu_normal,
702 			CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG1, 8),
703 	SG2042_GATE_HWS(GATE_CLK_AXI_PCIE1,
704 			"clk_gate_axi_pcie1", clk_gate_rp_cpu_normal,
705 			CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG1, 9),
706 
707 	/* downstream of div_50m_a53 */
708 	SG2042_GATE_HW(GATE_CLK_A53_50M, "clk_gate_a53_50m", clk_div_50m_a53,
709 		       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG0, 1),
710 	SG2042_GATE_HW(GATE_CLK_TIMER1, "clk_gate_timer1", clk_div_timer1,
711 		       CLK_SET_RATE_PARENT, R_CLKENREG0, 12),
712 	SG2042_GATE_HW(GATE_CLK_TIMER2, "clk_gate_timer2", clk_div_timer2,
713 		       CLK_SET_RATE_PARENT, R_CLKENREG0, 13),
714 	SG2042_GATE_HW(GATE_CLK_TIMER3, "clk_gate_timer3", clk_div_timer3,
715 		       CLK_SET_RATE_PARENT, R_CLKENREG0, 14),
716 	SG2042_GATE_HW(GATE_CLK_TIMER4, "clk_gate_timer4", clk_div_timer4,
717 		       CLK_SET_RATE_PARENT, R_CLKENREG0, 15),
718 	SG2042_GATE_HW(GATE_CLK_TIMER5, "clk_gate_timer5", clk_div_timer5,
719 		       CLK_SET_RATE_PARENT, R_CLKENREG0, 16),
720 	SG2042_GATE_HW(GATE_CLK_TIMER6, "clk_gate_timer6", clk_div_timer6,
721 		       CLK_SET_RATE_PARENT, R_CLKENREG0, 17),
722 	SG2042_GATE_HW(GATE_CLK_TIMER7, "clk_gate_timer7", clk_div_timer7,
723 		       CLK_SET_RATE_PARENT, R_CLKENREG0, 18),
724 	SG2042_GATE_HW(GATE_CLK_TIMER8, "clk_gate_timer8", clk_div_timer8,
725 		       CLK_SET_RATE_PARENT, R_CLKENREG0, 19),
726 
727 	/* gate clocks downstream from div clocks one-to-one */
728 	SG2042_GATE_HW(GATE_CLK_UART_500M, "clk_gate_uart_500m", clk_div_uart_500m,
729 		       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG0, 4),
730 	SG2042_GATE_HW(GATE_CLK_AHB_LPC, "clk_gate_ahb_lpc", clk_div_ahb_lpc,
731 		       CLK_SET_RATE_PARENT, R_CLKENREG0, 7),
732 	SG2042_GATE_HW(GATE_CLK_EFUSE, "clk_gate_efuse", clk_div_efuse,
733 		       CLK_SET_RATE_PARENT, R_CLKENREG0, 20),
734 	SG2042_GATE_HW(GATE_CLK_TX_ETH0, "clk_gate_tx_eth0", clk_div_tx_eth0,
735 		       CLK_SET_RATE_PARENT, R_CLKENREG0, 30),
736 	SG2042_GATE_HW(GATE_CLK_PTP_REF_I_ETH0,
737 		       "clk_gate_ptp_ref_i_eth0", clk_div_ptp_ref_i_eth0,
738 		       CLK_SET_RATE_PARENT, R_CLKENREG1, 0),
739 	SG2042_GATE_HW(GATE_CLK_REF_ETH0, "clk_gate_ref_eth0", clk_div_ref_eth0,
740 		       CLK_SET_RATE_PARENT, R_CLKENREG1, 1),
741 	SG2042_GATE_HW(GATE_CLK_EMMC_100M, "clk_gate_emmc", clk_div_emmc,
742 		       CLK_SET_RATE_PARENT, R_CLKENREG1, 3),
743 	SG2042_GATE_HW(GATE_CLK_SD_100M, "clk_gate_sd", clk_div_sd,
744 		       CLK_SET_RATE_PARENT, R_CLKENREG1, 6),
745 
746 	/* downstream of clk_div_top_axi0 */
747 	SG2042_GATE_HW(GATE_CLK_AHB_ROM, "clk_gate_ahb_rom", clk_div_top_axi0,
748 		       0, R_CLKENREG0, 8),
749 	SG2042_GATE_HW(GATE_CLK_AHB_SF, "clk_gate_ahb_sf", clk_div_top_axi0,
750 		       0, R_CLKENREG0, 9),
751 	SG2042_GATE_HW(GATE_CLK_AXI_SRAM, "clk_gate_axi_sram", clk_div_top_axi0,
752 		       CLK_IGNORE_UNUSED, R_CLKENREG0, 10),
753 	SG2042_GATE_HW(GATE_CLK_APB_TIMER, "clk_gate_apb_timer", clk_div_top_axi0,
754 		       CLK_IGNORE_UNUSED, R_CLKENREG0, 11),
755 	SG2042_GATE_HW(GATE_CLK_APB_EFUSE, "clk_gate_apb_efuse", clk_div_top_axi0,
756 		       0, R_CLKENREG0, 21),
757 	SG2042_GATE_HW(GATE_CLK_APB_GPIO, "clk_gate_apb_gpio", clk_div_top_axi0,
758 		       0, R_CLKENREG0, 22),
759 	SG2042_GATE_HW(GATE_CLK_APB_GPIO_INTR,
760 		       "clk_gate_apb_gpio_intr", clk_div_top_axi0,
761 		       CLK_IS_CRITICAL, R_CLKENREG0, 23),
762 	SG2042_GATE_HW(GATE_CLK_APB_I2C, "clk_gate_apb_i2c", clk_div_top_axi0,
763 		       0, R_CLKENREG0, 26),
764 	SG2042_GATE_HW(GATE_CLK_APB_WDT, "clk_gate_apb_wdt", clk_div_top_axi0,
765 		       0, R_CLKENREG0, 27),
766 	SG2042_GATE_HW(GATE_CLK_APB_PWM, "clk_gate_apb_pwm", clk_div_top_axi0,
767 		       0, R_CLKENREG0, 28),
768 	SG2042_GATE_HW(GATE_CLK_APB_RTC, "clk_gate_apb_rtc", clk_div_top_axi0,
769 		       0, R_CLKENREG0, 29),
770 	SG2042_GATE_HW(GATE_CLK_TOP_AXI0, "clk_gate_top_axi0", clk_div_top_axi0,
771 		       CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
772 		       R_CLKENREG1, 11),
773 	/* downstream of DIV clocks which are sourced from clk_div_top_axi0 */
774 	SG2042_GATE_HW(GATE_CLK_GPIO_DB, "clk_gate_gpio_db", clk_div_gpio_db,
775 		       CLK_SET_RATE_PARENT, R_CLKENREG0, 24),
776 	SG2042_GATE_HW(GATE_CLK_100K_EMMC, "clk_gate_100k_emmc", clk_div_100k_emmc,
777 		       CLK_SET_RATE_PARENT, R_CLKENREG1, 4),
778 	SG2042_GATE_HW(GATE_CLK_100K_SD, "clk_gate_100k_sd", clk_div_100k_sd,
779 		       CLK_SET_RATE_PARENT, R_CLKENREG1, 7),
780 
781 	/* downstream of clk_div_top_axi_hsperi */
782 	SG2042_GATE_HW(GATE_CLK_SYSDMA_AXI,
783 		       "clk_gate_sysdma_axi", clk_div_top_axi_hsperi,
784 		       CLK_SET_RATE_PARENT, R_CLKENREG0, 3),
785 	SG2042_GATE_HW(GATE_CLK_APB_UART,
786 		       "clk_gate_apb_uart", clk_div_top_axi_hsperi,
787 		       CLK_SET_RATE_PARENT, R_CLKENREG0, 5),
788 	SG2042_GATE_HW(GATE_CLK_AXI_DBG_I2C,
789 		       "clk_gate_axi_dbg_i2c", clk_div_top_axi_hsperi,
790 		       CLK_SET_RATE_PARENT, R_CLKENREG0, 6),
791 	SG2042_GATE_HW(GATE_CLK_APB_SPI,
792 		       "clk_gate_apb_spi", clk_div_top_axi_hsperi,
793 		       CLK_SET_RATE_PARENT, R_CLKENREG0, 25),
794 	SG2042_GATE_HW(GATE_CLK_AXI_ETH0,
795 		       "clk_gate_axi_eth0", clk_div_top_axi_hsperi,
796 		       CLK_SET_RATE_PARENT, R_CLKENREG0, 31),
797 	SG2042_GATE_HW(GATE_CLK_AXI_EMMC,
798 		       "clk_gate_axi_emmc", clk_div_top_axi_hsperi,
799 		       CLK_SET_RATE_PARENT, R_CLKENREG1, 2),
800 	SG2042_GATE_HW(GATE_CLK_AXI_SD,
801 		       "clk_gate_axi_sd", clk_div_top_axi_hsperi,
802 		       CLK_SET_RATE_PARENT, R_CLKENREG1, 5),
803 	SG2042_GATE_HW(GATE_CLK_TOP_AXI_HSPERI,
804 		       "clk_gate_top_axi_hsperi", clk_div_top_axi_hsperi,
805 		       CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
806 		       R_CLKENREG1, 12),
807 };
808 
809 static DEFINE_SPINLOCK(sg2042_clk_lock);
810 
811 static int sg2042_clk_register_divs(struct device *dev,
812 				    struct sg2042_clk_data *clk_data,
813 				    struct sg2042_divider_clock div_clks[],
814 				    int num_div_clks)
815 {
816 	struct sg2042_divider_clock *div;
817 	struct clk_hw *hw;
818 	int i, ret = 0;
819 
820 	for (i = 0; i < num_div_clks; i++) {
821 		div = &div_clks[i];
822 
823 		if (div->div_flags & CLK_DIVIDER_HIWORD_MASK) {
824 			if (div->width + div->shift > 16) {
825 				pr_warn("divider value exceeds LOWORD field\n");
826 				ret = -EINVAL;
827 				break;
828 			}
829 		}
830 
831 		div->reg = clk_data->iobase + div->offset_ctrl;
832 		div->lock = &sg2042_clk_lock;
833 
834 		hw = &div->hw;
835 		ret = devm_clk_hw_register(dev, hw);
836 		if (ret) {
837 			pr_err("failed to register clock %s\n", div->hw.init->name);
838 			break;
839 		}
840 
841 		clk_data->onecell_data.hws[div->id] = hw;
842 	}
843 
844 	return ret;
845 }
846 
847 static int sg2042_clk_register_gates(struct device *dev,
848 				     struct sg2042_clk_data *clk_data,
849 				     const struct sg2042_gate_clock gate_clks[],
850 				     int num_gate_clks)
851 {
852 	const struct sg2042_gate_clock *gate;
853 	struct clk_hw *hw;
854 	int i, ret = 0;
855 
856 	for (i = 0; i < num_gate_clks; i++) {
857 		gate = &gate_clks[i];
858 		hw = __devm_clk_hw_register_gate
859 			(dev,
860 			 NULL,
861 			 gate->hw.init->name,
862 			 NULL,
863 			 gate->hw.init->parent_hws[0],
864 			 NULL,
865 			 gate->hw.init->flags,
866 			 clk_data->iobase + gate->offset_enable,
867 			 gate->bit_idx,
868 			 0,
869 			 &sg2042_clk_lock);
870 		if (IS_ERR(hw)) {
871 			pr_err("failed to register clock %s\n", gate->hw.init->name);
872 			ret = PTR_ERR(hw);
873 			break;
874 		}
875 
876 		clk_data->onecell_data.hws[gate->id] = hw;
877 
878 		/* Updated some clocks which take the role of parent */
879 		switch (gate->id) {
880 		case GATE_CLK_RP_CPU_NORMAL:
881 			*clk_gate_rp_cpu_normal = hw;
882 			break;
883 		case GATE_CLK_TOP_RP_CMN_DIV2:
884 			*clk_gate_top_rp_cmn_div2 = hw;
885 			break;
886 		}
887 	}
888 
889 	return ret;
890 }
891 
892 static int sg2042_clk_register_gates_fw(struct device *dev,
893 					struct sg2042_clk_data *clk_data,
894 					const struct sg2042_gate_clock gate_clks[],
895 					int num_gate_clks)
896 {
897 	const struct sg2042_gate_clock *gate;
898 	struct clk_hw *hw;
899 	int i, ret = 0;
900 
901 	for (i = 0; i < num_gate_clks; i++) {
902 		gate = &gate_clks[i];
903 		hw = devm_clk_hw_register_gate_parent_data
904 			(dev,
905 			 gate->hw.init->name,
906 			 gate->hw.init->parent_data,
907 			 gate->hw.init->flags,
908 			 clk_data->iobase + gate->offset_enable,
909 			 gate->bit_idx,
910 			 0,
911 			 &sg2042_clk_lock);
912 		if (IS_ERR(hw)) {
913 			pr_err("failed to register clock %s\n", gate->hw.init->name);
914 			ret = PTR_ERR(hw);
915 			break;
916 		}
917 
918 		clk_data->onecell_data.hws[gate->id] = hw;
919 
920 		/* Updated some clocks which take the role of parent */
921 		switch (gate->id) {
922 		case GATE_CLK_DDR01_DIV0:
923 			*clk_gate_ddr01_div0 = hw;
924 			break;
925 		case GATE_CLK_DDR01_DIV1:
926 			*clk_gate_ddr01_div1 = hw;
927 			break;
928 		case GATE_CLK_DDR23_DIV0:
929 			*clk_gate_ddr23_div0 = hw;
930 			break;
931 		case GATE_CLK_DDR23_DIV1:
932 			*clk_gate_ddr23_div1 = hw;
933 			break;
934 		case GATE_CLK_RP_CPU_NORMAL_DIV0:
935 			*clk_gate_rp_cpu_normal_div0 = hw;
936 			break;
937 		case GATE_CLK_RP_CPU_NORMAL_DIV1:
938 			*clk_gate_rp_cpu_normal_div1 = hw;
939 			break;
940 		case GATE_CLK_AXI_DDR_DIV0:
941 			*clk_gate_axi_ddr_div0 = hw;
942 			break;
943 		case GATE_CLK_AXI_DDR_DIV1:
944 			*clk_gate_axi_ddr_div1 = hw;
945 			break;
946 		}
947 	}
948 
949 	return ret;
950 }
951 
952 static int sg2042_mux_notifier_cb(struct notifier_block *nb,
953 				  unsigned long event,
954 				  void *data)
955 {
956 	struct sg2042_mux_clock *mux = to_sg2042_mux_nb(nb);
957 	const struct clk_ops *ops = &clk_mux_ops;
958 	struct clk_notifier_data *ndata = data;
959 	struct clk_hw *hw;
960 	int ret = 0;
961 
962 	hw = __clk_get_hw(ndata->clk);
963 
964 	/* To switch to fpll before changing rate and restore after that */
965 	if (event == PRE_RATE_CHANGE) {
966 		mux->original_index = ops->get_parent(hw);
967 
968 		/*
969 		 * "1" is the array index of the second parent input source of
970 		 * mux. For SG2042, it's fpll for all mux clocks.
971 		 * "0" is the array index of the frist parent input source of
972 		 * mux, For SG2042, it's mpll.
973 		 * FIXME, any good idea to avoid magic number?
974 		 */
975 		if (mux->original_index == 0)
976 			ret = ops->set_parent(hw, 1);
977 	} else if (event == POST_RATE_CHANGE) {
978 		ret = ops->set_parent(hw, mux->original_index);
979 	}
980 
981 	return notifier_from_errno(ret);
982 }
983 
984 static int sg2042_clk_register_muxs(struct device *dev,
985 				    struct sg2042_clk_data *clk_data,
986 				    struct sg2042_mux_clock mux_clks[],
987 				    int num_mux_clks)
988 {
989 	struct sg2042_mux_clock *mux;
990 	struct clk_hw *hw;
991 	int i, ret = 0;
992 
993 	for (i = 0; i < num_mux_clks; i++) {
994 		mux = &mux_clks[i];
995 
996 		hw = __devm_clk_hw_register_mux
997 			(dev,
998 			 NULL,
999 			 mux->hw.init->name,
1000 			 mux->hw.init->num_parents,
1001 			 NULL,
1002 			 mux->hw.init->parent_hws,
1003 			 NULL,
1004 			 mux->hw.init->flags,
1005 			 clk_data->iobase + mux->offset_select,
1006 			 mux->shift,
1007 			 BIT(mux->width) - 1,
1008 			 0,
1009 			 sg2042_mux_table,
1010 			 &sg2042_clk_lock);
1011 		if (IS_ERR(hw)) {
1012 			pr_err("failed to register clock %s\n", mux->hw.init->name);
1013 			ret = PTR_ERR(hw);
1014 			break;
1015 		}
1016 
1017 		clk_data->onecell_data.hws[mux->id] = hw;
1018 
1019 		/* Updated some clocks which takes the role of parent */
1020 		switch (mux->id) {
1021 		case MUX_CLK_DDR01:
1022 			*clk_mux_ddr01 = hw;
1023 			break;
1024 		case MUX_CLK_DDR23:
1025 			*clk_mux_ddr23 = hw;
1026 			break;
1027 		case MUX_CLK_RP_CPU_NORMAL:
1028 			*clk_mux_rp_cpu_normal = hw;
1029 			break;
1030 		case MUX_CLK_AXI_DDR:
1031 			*clk_mux_axi_ddr = hw;
1032 			break;
1033 		}
1034 
1035 		/*
1036 		 * FIXME: Theoretically, we should set parent for the
1037 		 * mux, but seems hardware has done this for us with
1038 		 * default value, so we don't set parent again here.
1039 		 */
1040 
1041 		if (!(mux->hw.init->flags & CLK_MUX_READ_ONLY)) {
1042 			mux->clk_nb.notifier_call = sg2042_mux_notifier_cb;
1043 			ret = devm_clk_notifier_register(dev, hw->clk, &mux->clk_nb);
1044 			if (ret) {
1045 				pr_err("failed to register clock notifier for %s\n",
1046 				       mux->hw.init->name);
1047 				break;
1048 			}
1049 		}
1050 	}
1051 
1052 	return ret;
1053 }
1054 
1055 static int sg2042_init_clkdata(struct platform_device *pdev,
1056 			       int num_clks,
1057 			       struct sg2042_clk_data **pp_clk_data)
1058 {
1059 	struct sg2042_clk_data *clk_data = NULL;
1060 
1061 	clk_data = devm_kzalloc(&pdev->dev,
1062 				struct_size(clk_data, onecell_data.hws, num_clks),
1063 				GFP_KERNEL);
1064 	if (!clk_data)
1065 		return -ENOMEM;
1066 
1067 	clk_data->iobase = devm_platform_ioremap_resource(pdev, 0);
1068 	if (WARN_ON(IS_ERR(clk_data->iobase)))
1069 		return PTR_ERR(clk_data->iobase);
1070 
1071 	clk_data->onecell_data.num = num_clks;
1072 
1073 	*pp_clk_data = clk_data;
1074 
1075 	return 0;
1076 }
1077 
1078 static int sg2042_clkgen_probe(struct platform_device *pdev)
1079 {
1080 	struct sg2042_clk_data *clk_data = NULL;
1081 	int num_clks;
1082 	int ret;
1083 
1084 	num_clks = ARRAY_SIZE(sg2042_div_clks_level_1) +
1085 		   ARRAY_SIZE(sg2042_div_clks_level_2) +
1086 		   ARRAY_SIZE(sg2042_gate_clks_level_1) +
1087 		   ARRAY_SIZE(sg2042_gate_clks_level_2) +
1088 		   ARRAY_SIZE(sg2042_mux_clks);
1089 
1090 	ret = sg2042_init_clkdata(pdev, num_clks, &clk_data);
1091 	if (ret)
1092 		goto error_out;
1093 
1094 	/* level-1 gates */
1095 	ret = sg2042_clk_register_gates_fw(&pdev->dev, clk_data,
1096 					   sg2042_gate_clks_level_1,
1097 					   ARRAY_SIZE(sg2042_gate_clks_level_1));
1098 	if (ret)
1099 		goto error_out;
1100 
1101 	/* level-1 div */
1102 	ret = sg2042_clk_register_divs(&pdev->dev, clk_data, sg2042_div_clks_level_1,
1103 				       ARRAY_SIZE(sg2042_div_clks_level_1));
1104 	if (ret)
1105 		goto error_out;
1106 
1107 	/* mux */
1108 	ret = sg2042_clk_register_muxs(&pdev->dev, clk_data, sg2042_mux_clks,
1109 				       ARRAY_SIZE(sg2042_mux_clks));
1110 	if (ret)
1111 		goto error_out;
1112 
1113 	/* level 2 div */
1114 	ret = sg2042_clk_register_divs(&pdev->dev, clk_data, sg2042_div_clks_level_2,
1115 				       ARRAY_SIZE(sg2042_div_clks_level_2));
1116 	if (ret)
1117 		goto error_out;
1118 
1119 	/* level 2 gate */
1120 	ret = sg2042_clk_register_gates(&pdev->dev, clk_data, sg2042_gate_clks_level_2,
1121 					ARRAY_SIZE(sg2042_gate_clks_level_2));
1122 	if (ret)
1123 		goto error_out;
1124 
1125 	return devm_of_clk_add_hw_provider(&pdev->dev,
1126 					   of_clk_hw_onecell_get,
1127 					   &clk_data->onecell_data);
1128 
1129 error_out:
1130 	pr_err("%s failed error number %d\n", __func__, ret);
1131 	return ret;
1132 }
1133 
1134 static const struct of_device_id sg2042_clkgen_match[] = {
1135 	{ .compatible = "sophgo,sg2042-clkgen" },
1136 	{ /* sentinel */ }
1137 };
1138 MODULE_DEVICE_TABLE(of, sg2042_clkgen_match);
1139 
1140 static struct platform_driver sg2042_clkgen_driver = {
1141 	.probe = sg2042_clkgen_probe,
1142 	.driver = {
1143 		.name = "clk-sophgo-sg2042-clkgen",
1144 		.of_match_table = sg2042_clkgen_match,
1145 		.suppress_bind_attrs = true,
1146 	},
1147 };
1148 module_platform_driver(sg2042_clkgen_driver);
1149 
1150 MODULE_AUTHOR("Chen Wang");
1151 MODULE_DESCRIPTION("Sophgo SG2042 clock generator driver");
1152 MODULE_LICENSE("GPL");
1153