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