hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/clk/renesas/rcar-gen3-cpg.c
....@@ -1,15 +1,13 @@
1
+// SPDX-License-Identifier: GPL-2.0
12 /*
23 * R-Car Gen3 Clock Pulse Generator
34 *
4
- * Copyright (C) 2015-2016 Glider bvba
5
+ * Copyright (C) 2015-2018 Glider bvba
6
+ * Copyright (C) 2019 Renesas Electronics Corp.
57 *
68 * Based on clk-rcar-gen3.c
79 *
810 * Copyright (C) 2015 Renesas Electronics Corp.
9
- *
10
- * This program is free software; you can redistribute it and/or modify
11
- * it under the terms of the GNU General Public License as published by
12
- * the Free Software Foundation; version 2 of the License.
1311 */
1412
1513 #include <linux/bug.h>
....@@ -30,6 +28,23 @@
3028 #define CPG_PLL0CR 0x00d8
3129 #define CPG_PLL2CR 0x002c
3230 #define CPG_PLL4CR 0x01f4
31
+
32
+#define CPG_RCKCR_CKSEL BIT(15) /* RCLK Clock Source Select */
33
+
34
+static spinlock_t cpg_lock;
35
+
36
+static void cpg_reg_modify(void __iomem *reg, u32 clear, u32 set)
37
+{
38
+ unsigned long flags;
39
+ u32 val;
40
+
41
+ spin_lock_irqsave(&cpg_lock, flags);
42
+ val = readl(reg);
43
+ val &= ~clear;
44
+ val |= set;
45
+ writel(val, reg);
46
+ spin_unlock_irqrestore(&cpg_lock, flags);
47
+};
3348
3449 struct cpg_simple_notifier {
3550 struct notifier_block nb;
....@@ -74,14 +89,13 @@
7489 #define CPG_FRQCRB 0x00000004
7590 #define CPG_FRQCRB_KICK BIT(31)
7691 #define CPG_FRQCRC 0x000000e0
77
-#define CPG_FRQCRC_ZFC_MASK GENMASK(12, 8)
78
-#define CPG_FRQCRC_Z2FC_MASK GENMASK(4, 0)
7992
8093 struct cpg_z_clk {
8194 struct clk_hw hw;
8295 void __iomem *reg;
8396 void __iomem *kick_reg;
8497 unsigned long mask;
98
+ unsigned int fixed_div;
8599 };
86100
87101 #define to_z_clk(_hw) container_of(_hw, struct cpg_z_clk, hw)
....@@ -96,21 +110,28 @@
96110 val = readl(zclk->reg) & zclk->mask;
97111 mult = 32 - (val >> __ffs(zclk->mask));
98112
99
- /* Factor of 2 is for fixed divider */
100
- return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * mult, 32 * 2);
113
+ return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * mult,
114
+ 32 * zclk->fixed_div);
101115 }
102116
103
-static long cpg_z_clk_round_rate(struct clk_hw *hw, unsigned long rate,
104
- unsigned long *parent_rate)
117
+static int cpg_z_clk_determine_rate(struct clk_hw *hw,
118
+ struct clk_rate_request *req)
105119 {
106
- /* Factor of 2 is for fixed divider */
107
- unsigned long prate = *parent_rate / 2;
108
- unsigned int mult;
120
+ struct cpg_z_clk *zclk = to_z_clk(hw);
121
+ unsigned int min_mult, max_mult, mult;
122
+ unsigned long prate;
109123
110
- mult = div_u64(rate * 32ULL, prate);
111
- mult = clamp(mult, 1U, 32U);
124
+ prate = req->best_parent_rate / zclk->fixed_div;
125
+ min_mult = max(div64_ul(req->min_rate * 32ULL, prate), 1ULL);
126
+ max_mult = min(div64_ul(req->max_rate * 32ULL, prate), 32ULL);
127
+ if (max_mult < min_mult)
128
+ return -EINVAL;
112129
113
- return (u64)prate * mult / 32;
130
+ mult = div64_ul(req->rate * 32ULL, prate);
131
+ mult = clamp(mult, min_mult, max_mult);
132
+
133
+ req->rate = div_u64((u64)prate * mult, 32);
134
+ return 0;
114135 }
115136
116137 static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
....@@ -119,26 +140,22 @@
119140 struct cpg_z_clk *zclk = to_z_clk(hw);
120141 unsigned int mult;
121142 unsigned int i;
122
- u32 val, kick;
123143
124
- /* Factor of 2 is for fixed divider */
125
- mult = DIV_ROUND_CLOSEST_ULL(rate * 32ULL * 2, parent_rate);
144
+ mult = DIV64_U64_ROUND_CLOSEST(rate * 32ULL * zclk->fixed_div,
145
+ parent_rate);
126146 mult = clamp(mult, 1U, 32U);
127147
128148 if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
129149 return -EBUSY;
130150
131
- val = readl(zclk->reg) & ~zclk->mask;
132
- val |= ((32 - mult) << __ffs(zclk->mask)) & zclk->mask;
133
- writel(val, zclk->reg);
151
+ cpg_reg_modify(zclk->reg, zclk->mask,
152
+ ((32 - mult) << __ffs(zclk->mask)) & zclk->mask);
134153
135154 /*
136155 * Set KICK bit in FRQCRB to update hardware setting and wait for
137156 * clock change completion.
138157 */
139
- kick = readl(zclk->kick_reg);
140
- kick |= CPG_FRQCRB_KICK;
141
- writel(kick, zclk->kick_reg);
158
+ cpg_reg_modify(zclk->kick_reg, 0, CPG_FRQCRB_KICK);
142159
143160 /*
144161 * Note: There is no HW information about the worst case latency.
....@@ -161,16 +178,17 @@
161178
162179 static const struct clk_ops cpg_z_clk_ops = {
163180 .recalc_rate = cpg_z_clk_recalc_rate,
164
- .round_rate = cpg_z_clk_round_rate,
181
+ .determine_rate = cpg_z_clk_determine_rate,
165182 .set_rate = cpg_z_clk_set_rate,
166183 };
167184
168185 static struct clk * __init cpg_z_clk_register(const char *name,
169186 const char *parent_name,
170187 void __iomem *reg,
171
- unsigned long mask)
188
+ unsigned int div,
189
+ unsigned int offset)
172190 {
173
- struct clk_init_data init = {};
191
+ struct clk_init_data init;
174192 struct cpg_z_clk *zclk;
175193 struct clk *clk;
176194
....@@ -187,7 +205,8 @@
187205 zclk->reg = reg + CPG_FRQCRC;
188206 zclk->kick_reg = reg + CPG_FRQCRB;
189207 zclk->hw.init = &init;
190
- zclk->mask = mask;
208
+ zclk->mask = GENMASK(offset + 4, offset);
209
+ zclk->fixed_div = div; /* PLLVCO x 1/div x SYS-CPU divider */
191210
192211 clk = clk_register(NULL, &zclk->hw);
193212 if (IS_ERR(clk))
....@@ -224,8 +243,6 @@
224243 const struct sd_div_table *div_table;
225244 struct cpg_simple_notifier csn;
226245 unsigned int div_num;
227
- unsigned int div_min;
228
- unsigned int div_max;
229246 unsigned int cur_div_idx;
230247 };
231248
....@@ -233,16 +250,20 @@
233250 * sd_srcfc sd_fc div
234251 * stp_hck stp_ck (div) (div) = sd_srcfc x sd_fc
235252 *-------------------------------------------------------------------
236
- * 0 0 0 (1) 1 (4) 4
237
- * 0 0 1 (2) 1 (4) 8
238
- * 1 0 2 (4) 1 (4) 16
239
- * 1 0 3 (8) 1 (4) 32
253
+ * 0 0 0 (1) 1 (4) 4 : SDR104 / HS200 / HS400 (8 TAP)
254
+ * 0 0 1 (2) 1 (4) 8 : SDR50
255
+ * 1 0 2 (4) 1 (4) 16 : HS / SDR25
256
+ * 1 0 3 (8) 1 (4) 32 : NS / SDR12
240257 * 1 0 4 (16) 1 (4) 64
241258 * 0 0 0 (1) 0 (2) 2
242
- * 0 0 1 (2) 0 (2) 4
259
+ * 0 0 1 (2) 0 (2) 4 : SDR104 / HS200 / HS400 (4 TAP)
243260 * 1 0 2 (4) 0 (2) 8
244261 * 1 0 3 (8) 0 (2) 16
245262 * 1 0 4 (16) 0 (2) 32
263
+ *
264
+ * NOTE: There is a quirk option to ignore the first row of the dividers
265
+ * table when searching for suitable settings. This is because HS400 on
266
+ * early ES versions of H3 and M3-W requires a specific setting to work.
246267 */
247268 static const struct sd_div_table cpg_sd_div_table[] = {
248269 /* CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) */
....@@ -263,12 +284,10 @@
263284 static int cpg_sd_clock_enable(struct clk_hw *hw)
264285 {
265286 struct sd_clock *clock = to_sd_clock(hw);
266
- u32 val = readl(clock->csn.reg);
267287
268
- val &= ~(CPG_SD_STP_MASK);
269
- val |= clock->div_table[clock->cur_div_idx].val & CPG_SD_STP_MASK;
270
-
271
- writel(val, clock->csn.reg);
288
+ cpg_reg_modify(clock->csn.reg, CPG_SD_STP_MASK,
289
+ clock->div_table[clock->cur_div_idx].val &
290
+ CPG_SD_STP_MASK);
272291
273292 return 0;
274293 }
....@@ -277,7 +296,7 @@
277296 {
278297 struct sd_clock *clock = to_sd_clock(hw);
279298
280
- writel(readl(clock->csn.reg) | CPG_SD_STP_MASK, clock->csn.reg);
299
+ cpg_reg_modify(clock->csn.reg, 0, CPG_SD_STP_MASK);
281300 }
282301
283302 static int cpg_sd_clock_is_enabled(struct clk_hw *hw)
....@@ -296,39 +315,44 @@
296315 clock->div_table[clock->cur_div_idx].div);
297316 }
298317
299
-static unsigned int cpg_sd_clock_calc_div(struct sd_clock *clock,
300
- unsigned long rate,
301
- unsigned long parent_rate)
318
+static int cpg_sd_clock_determine_rate(struct clk_hw *hw,
319
+ struct clk_rate_request *req)
302320 {
303
- unsigned int div;
304
-
305
- if (!rate)
306
- rate = 1;
307
-
308
- div = DIV_ROUND_CLOSEST(parent_rate, rate);
309
-
310
- return clamp_t(unsigned int, div, clock->div_min, clock->div_max);
311
-}
312
-
313
-static long cpg_sd_clock_round_rate(struct clk_hw *hw, unsigned long rate,
314
- unsigned long *parent_rate)
315
-{
321
+ unsigned long best_rate = ULONG_MAX, diff_min = ULONG_MAX;
316322 struct sd_clock *clock = to_sd_clock(hw);
317
- unsigned int div = cpg_sd_clock_calc_div(clock, rate, *parent_rate);
323
+ unsigned long calc_rate, diff;
324
+ unsigned int i;
318325
319
- return DIV_ROUND_CLOSEST(*parent_rate, div);
326
+ for (i = 0; i < clock->div_num; i++) {
327
+ calc_rate = DIV_ROUND_CLOSEST(req->best_parent_rate,
328
+ clock->div_table[i].div);
329
+ if (calc_rate < req->min_rate || calc_rate > req->max_rate)
330
+ continue;
331
+
332
+ diff = calc_rate > req->rate ? calc_rate - req->rate
333
+ : req->rate - calc_rate;
334
+ if (diff < diff_min) {
335
+ best_rate = calc_rate;
336
+ diff_min = diff;
337
+ }
338
+ }
339
+
340
+ if (best_rate == ULONG_MAX)
341
+ return -EINVAL;
342
+
343
+ req->rate = best_rate;
344
+ return 0;
320345 }
321346
322347 static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate,
323
- unsigned long parent_rate)
348
+ unsigned long parent_rate)
324349 {
325350 struct sd_clock *clock = to_sd_clock(hw);
326
- unsigned int div = cpg_sd_clock_calc_div(clock, rate, parent_rate);
327
- u32 val;
328351 unsigned int i;
329352
330353 for (i = 0; i < clock->div_num; i++)
331
- if (div == clock->div_table[i].div)
354
+ if (rate == DIV_ROUND_CLOSEST(parent_rate,
355
+ clock->div_table[i].div))
332356 break;
333357
334358 if (i >= clock->div_num)
....@@ -336,10 +360,9 @@
336360
337361 clock->cur_div_idx = i;
338362
339
- val = readl(clock->csn.reg);
340
- val &= ~(CPG_SD_STP_MASK | CPG_SD_FC_MASK);
341
- val |= clock->div_table[i].val & (CPG_SD_STP_MASK | CPG_SD_FC_MASK);
342
- writel(val, clock->csn.reg);
363
+ cpg_reg_modify(clock->csn.reg, CPG_SD_STP_MASK | CPG_SD_FC_MASK,
364
+ clock->div_table[i].val &
365
+ (CPG_SD_STP_MASK | CPG_SD_FC_MASK));
343366
344367 return 0;
345368 }
....@@ -349,45 +372,48 @@
349372 .disable = cpg_sd_clock_disable,
350373 .is_enabled = cpg_sd_clock_is_enabled,
351374 .recalc_rate = cpg_sd_clock_recalc_rate,
352
- .round_rate = cpg_sd_clock_round_rate,
375
+ .determine_rate = cpg_sd_clock_determine_rate,
353376 .set_rate = cpg_sd_clock_set_rate,
354377 };
355378
356
-static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core,
357
- void __iomem *base, const char *parent_name,
379
+static u32 cpg_quirks __initdata;
380
+
381
+#define PLL_ERRATA BIT(0) /* Missing PLL0/2/4 post-divider */
382
+#define RCKCR_CKSEL BIT(1) /* Manual RCLK parent selection */
383
+#define SD_SKIP_FIRST BIT(2) /* Skip first clock in SD table */
384
+
385
+static struct clk * __init cpg_sd_clk_register(const char *name,
386
+ void __iomem *base, unsigned int offset, const char *parent_name,
358387 struct raw_notifier_head *notifiers)
359388 {
360
- struct clk_init_data init = {};
389
+ struct clk_init_data init;
361390 struct sd_clock *clock;
362391 struct clk *clk;
363
- unsigned int i;
364392 u32 val;
365393
366394 clock = kzalloc(sizeof(*clock), GFP_KERNEL);
367395 if (!clock)
368396 return ERR_PTR(-ENOMEM);
369397
370
- init.name = core->name;
398
+ init.name = name;
371399 init.ops = &cpg_sd_clock_ops;
372
- init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT;
400
+ init.flags = CLK_SET_RATE_PARENT;
373401 init.parent_names = &parent_name;
374402 init.num_parents = 1;
375403
376
- clock->csn.reg = base + core->offset;
404
+ clock->csn.reg = base + offset;
377405 clock->hw.init = &init;
378406 clock->div_table = cpg_sd_div_table;
379407 clock->div_num = ARRAY_SIZE(cpg_sd_div_table);
380408
409
+ if (cpg_quirks & SD_SKIP_FIRST) {
410
+ clock->div_table++;
411
+ clock->div_num--;
412
+ }
413
+
381414 val = readl(clock->csn.reg) & ~CPG_SD_FC_MASK;
382415 val |= CPG_SD_STP_MASK | (clock->div_table[0].val & CPG_SD_FC_MASK);
383416 writel(val, clock->csn.reg);
384
-
385
- clock->div_max = clock->div_table[0].div;
386
- clock->div_min = clock->div_max;
387
- for (i = 1; i < clock->div_num; i++) {
388
- clock->div_max = max(clock->div_max, clock->div_table[i].div);
389
- clock->div_min = min(clock->div_min, clock->div_table[i].div);
390
- }
391417
392418 clk = clk_register(NULL, &clock->hw);
393419 if (IS_ERR(clk))
....@@ -401,27 +427,119 @@
401427 return clk;
402428 }
403429
430
+struct rpc_clock {
431
+ struct clk_divider div;
432
+ struct clk_gate gate;
433
+ /*
434
+ * One notifier covers both RPC and RPCD2 clocks as they are both
435
+ * controlled by the same RPCCKCR register...
436
+ */
437
+ struct cpg_simple_notifier csn;
438
+};
439
+
440
+static const struct clk_div_table cpg_rpcsrc_div_table[] = {
441
+ { 2, 5 }, { 3, 6 }, { 0, 0 },
442
+};
443
+
444
+static const struct clk_div_table cpg_rpc_div_table[] = {
445
+ { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 }, { 0, 0 },
446
+};
447
+
448
+static struct clk * __init cpg_rpc_clk_register(const char *name,
449
+ void __iomem *base, const char *parent_name,
450
+ struct raw_notifier_head *notifiers)
451
+{
452
+ struct rpc_clock *rpc;
453
+ struct clk *clk;
454
+
455
+ rpc = kzalloc(sizeof(*rpc), GFP_KERNEL);
456
+ if (!rpc)
457
+ return ERR_PTR(-ENOMEM);
458
+
459
+ rpc->div.reg = base + CPG_RPCCKCR;
460
+ rpc->div.width = 3;
461
+ rpc->div.table = cpg_rpc_div_table;
462
+ rpc->div.lock = &cpg_lock;
463
+
464
+ rpc->gate.reg = base + CPG_RPCCKCR;
465
+ rpc->gate.bit_idx = 8;
466
+ rpc->gate.flags = CLK_GATE_SET_TO_DISABLE;
467
+ rpc->gate.lock = &cpg_lock;
468
+
469
+ rpc->csn.reg = base + CPG_RPCCKCR;
470
+
471
+ clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
472
+ &rpc->div.hw, &clk_divider_ops,
473
+ &rpc->gate.hw, &clk_gate_ops,
474
+ CLK_SET_RATE_PARENT);
475
+ if (IS_ERR(clk)) {
476
+ kfree(rpc);
477
+ return clk;
478
+ }
479
+
480
+ cpg_simple_notifier_register(notifiers, &rpc->csn);
481
+ return clk;
482
+}
483
+
484
+struct rpcd2_clock {
485
+ struct clk_fixed_factor fixed;
486
+ struct clk_gate gate;
487
+};
488
+
489
+static struct clk * __init cpg_rpcd2_clk_register(const char *name,
490
+ void __iomem *base,
491
+ const char *parent_name)
492
+{
493
+ struct rpcd2_clock *rpcd2;
494
+ struct clk *clk;
495
+
496
+ rpcd2 = kzalloc(sizeof(*rpcd2), GFP_KERNEL);
497
+ if (!rpcd2)
498
+ return ERR_PTR(-ENOMEM);
499
+
500
+ rpcd2->fixed.mult = 1;
501
+ rpcd2->fixed.div = 2;
502
+
503
+ rpcd2->gate.reg = base + CPG_RPCCKCR;
504
+ rpcd2->gate.bit_idx = 9;
505
+ rpcd2->gate.flags = CLK_GATE_SET_TO_DISABLE;
506
+ rpcd2->gate.lock = &cpg_lock;
507
+
508
+ clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
509
+ &rpcd2->fixed.hw, &clk_fixed_factor_ops,
510
+ &rpcd2->gate.hw, &clk_gate_ops,
511
+ CLK_SET_RATE_PARENT);
512
+ if (IS_ERR(clk))
513
+ kfree(rpcd2);
514
+
515
+ return clk;
516
+}
517
+
404518
405519 static const struct rcar_gen3_cpg_pll_config *cpg_pll_config __initdata;
406520 static unsigned int cpg_clk_extalr __initdata;
407521 static u32 cpg_mode __initdata;
408
-static u32 cpg_quirks __initdata;
409
-
410
-#define PLL_ERRATA BIT(0) /* Missing PLL0/2/4 post-divider */
411
-#define RCKCR_CKSEL BIT(1) /* Manual RCLK parent selection */
412522
413523 static const struct soc_device_attribute cpg_quirks_match[] __initconst = {
414524 {
415525 .soc_id = "r8a7795", .revision = "ES1.0",
416
- .data = (void *)(PLL_ERRATA | RCKCR_CKSEL),
526
+ .data = (void *)(PLL_ERRATA | RCKCR_CKSEL | SD_SKIP_FIRST),
417527 },
418528 {
419529 .soc_id = "r8a7795", .revision = "ES1.*",
420
- .data = (void *)RCKCR_CKSEL,
530
+ .data = (void *)(RCKCR_CKSEL | SD_SKIP_FIRST),
531
+ },
532
+ {
533
+ .soc_id = "r8a7795", .revision = "ES2.0",
534
+ .data = (void *)SD_SKIP_FIRST,
421535 },
422536 {
423537 .soc_id = "r8a7796", .revision = "ES1.0",
424
- .data = (void *)RCKCR_CKSEL,
538
+ .data = (void *)(RCKCR_CKSEL | SD_SKIP_FIRST),
539
+ },
540
+ {
541
+ .soc_id = "r8a7796", .revision = "ES1.1",
542
+ .data = (void *)SD_SKIP_FIRST,
425543 },
426544 { /* sentinel */ }
427545 };
....@@ -436,7 +554,7 @@
436554 unsigned int div = 1;
437555 u32 value;
438556
439
- parent = clks[core->parent & 0xffff]; /* CLK_TYPE_PE uses high bits */
557
+ parent = clks[core->parent & 0xffff]; /* some types use high bits */
440558 if (IS_ERR(parent))
441559 return ERR_CAST(parent);
442560
....@@ -495,8 +613,8 @@
495613 break;
496614
497615 case CLK_TYPE_GEN3_SD:
498
- return cpg_sd_clk_register(core, base, __clk_get_name(parent),
499
- notifiers);
616
+ return cpg_sd_clk_register(core->name, base, core->offset,
617
+ __clk_get_name(parent), notifiers);
500618
501619 case CLK_TYPE_GEN3_R:
502620 if (cpg_quirks & RCKCR_CKSEL) {
....@@ -516,7 +634,7 @@
516634
517635 if (clk_get_rate(clks[cpg_clk_extalr])) {
518636 parent = clks[cpg_clk_extalr];
519
- value |= BIT(15);
637
+ value |= CPG_RCKCR_CKSEL;
520638 }
521639
522640 writel(value, csn->reg);
....@@ -529,16 +647,14 @@
529647 parent = clks[cpg_clk_extalr];
530648 break;
531649
532
- case CLK_TYPE_GEN3_PE:
650
+ case CLK_TYPE_GEN3_MDSEL:
533651 /*
534
- * Peripheral clock with a fixed divider, selectable between
535
- * clean and spread spectrum parents using MD12
652
+ * Clock selectable between two parents and two fixed dividers
653
+ * using a mode pin
536654 */
537
- if (cpg_mode & BIT(12)) {
538
- /* Clean */
655
+ if (cpg_mode & BIT(core->offset)) {
539656 div = core->div & 0xffff;
540657 } else {
541
- /* SCCG */
542658 parent = clks[core->parent >> 16];
543659 if (IS_ERR(parent))
544660 return ERR_CAST(parent);
....@@ -549,11 +665,44 @@
549665
550666 case CLK_TYPE_GEN3_Z:
551667 return cpg_z_clk_register(core->name, __clk_get_name(parent),
552
- base, CPG_FRQCRC_ZFC_MASK);
668
+ base, core->div, core->offset);
553669
554
- case CLK_TYPE_GEN3_Z2:
555
- return cpg_z_clk_register(core->name, __clk_get_name(parent),
556
- base, CPG_FRQCRC_Z2FC_MASK);
670
+ case CLK_TYPE_GEN3_OSC:
671
+ /*
672
+ * Clock combining OSC EXTAL predivider and a fixed divider
673
+ */
674
+ div = cpg_pll_config->osc_prediv * core->div;
675
+ break;
676
+
677
+ case CLK_TYPE_GEN3_RCKSEL:
678
+ /*
679
+ * Clock selectable between two parents and two fixed dividers
680
+ * using RCKCR.CKSEL
681
+ */
682
+ if (readl(base + CPG_RCKCR) & CPG_RCKCR_CKSEL) {
683
+ div = core->div & 0xffff;
684
+ } else {
685
+ parent = clks[core->parent >> 16];
686
+ if (IS_ERR(parent))
687
+ return ERR_CAST(parent);
688
+ div = core->div >> 16;
689
+ }
690
+ break;
691
+
692
+ case CLK_TYPE_GEN3_RPCSRC:
693
+ return clk_register_divider_table(NULL, core->name,
694
+ __clk_get_name(parent), 0,
695
+ base + CPG_RPCCKCR, 3, 2, 0,
696
+ cpg_rpcsrc_div_table,
697
+ &cpg_lock);
698
+
699
+ case CLK_TYPE_GEN3_RPC:
700
+ return cpg_rpc_clk_register(core->name, base,
701
+ __clk_get_name(parent), notifiers);
702
+
703
+ case CLK_TYPE_GEN3_RPCD2:
704
+ return cpg_rpcd2_clk_register(core->name, base,
705
+ __clk_get_name(parent));
557706
558707 default:
559708 return ERR_PTR(-EINVAL);
....@@ -575,5 +724,8 @@
575724 if (attr)
576725 cpg_quirks = (uintptr_t)attr->data;
577726 pr_debug("%s: mode = 0x%x quirks = 0x%x\n", __func__, mode, cpg_quirks);
727
+
728
+ spin_lock_init(&cpg_lock);
729
+
578730 return 0;
579731 }