blob: 4ba38f98cc7bab8296631c04e1d3901870e4891e [file] [log] [blame]
Wolfram Sange848c2e2018-08-22 00:02:14 +02001// SPDX-License-Identifier: GPL-2.0
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +02002/*
3 * R-Car Gen3 Clock Pulse Generator
4 *
Geert Uytterhoevenb9d0b842018-07-11 13:54:30 +02005 * Copyright (C) 2015-2018 Glider bvba
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +02006 *
7 * Based on clk-rcar-gen3.c
8 *
9 * Copyright (C) 2015 Renesas Electronics Corp.
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +020010 */
11
12#include <linux/bug.h>
Takeshi Kihara33918912018-01-29 19:01:49 +010013#include <linux/bitfield.h>
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +020014#include <linux/clk.h>
15#include <linux/clk-provider.h>
16#include <linux/device.h>
17#include <linux/err.h>
18#include <linux/init.h>
19#include <linux/io.h>
Geert Uytterhoeven9f55b172017-06-21 22:51:21 +020020#include <linux/pm.h>
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +020021#include <linux/slab.h>
Geert Uytterhoevencecbe872017-03-10 11:46:10 +010022#include <linux/sys_soc.h>
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +020023
24#include "renesas-cpg-mssr.h"
25#include "rcar-gen3-cpg.h"
26
27#define CPG_PLL0CR 0x00d8
28#define CPG_PLL2CR 0x002c
29#define CPG_PLL4CR 0x01f4
30
Geert Uytterhoevenb9d0b842018-07-11 13:54:30 +020031#define CPG_RCKCR_CKSEL BIT(15) /* RCLK Clock Source Select */
32
Geert Uytterhoeven9f55b172017-06-21 22:51:21 +020033struct cpg_simple_notifier {
34 struct notifier_block nb;
35 void __iomem *reg;
36 u32 saved;
37};
38
39static int cpg_simple_notifier_call(struct notifier_block *nb,
40 unsigned long action, void *data)
41{
42 struct cpg_simple_notifier *csn =
43 container_of(nb, struct cpg_simple_notifier, nb);
44
45 switch (action) {
46 case PM_EVENT_SUSPEND:
47 csn->saved = readl(csn->reg);
48 return NOTIFY_OK;
49
50 case PM_EVENT_RESUME:
51 writel(csn->saved, csn->reg);
52 return NOTIFY_OK;
53 }
54 return NOTIFY_DONE;
55}
56
57static void cpg_simple_notifier_register(struct raw_notifier_head *notifiers,
58 struct cpg_simple_notifier *csn)
59{
60 csn->nb.notifier_call = cpg_simple_notifier_call;
61 raw_notifier_chain_register(notifiers, &csn->nb);
62}
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +020063
64/*
Takeshi Kihara41ceeb52018-01-29 19:01:50 +010065 * Z Clock & Z2 Clock
Takeshi Kihara33918912018-01-29 19:01:49 +010066 *
67 * Traits of this clock:
68 * prepare - clk_prepare only ensures that parents are prepared
69 * enable - clk_enable only ensures that parents are enabled
70 * rate - rate is adjustable. clk->rate = (parent->rate * mult / 32 ) / 2
71 * parent - fixed parent. No clk_set_parent support
72 */
73#define CPG_FRQCRB 0x00000004
74#define CPG_FRQCRB_KICK BIT(31)
75#define CPG_FRQCRC 0x000000e0
76#define CPG_FRQCRC_ZFC_MASK GENMASK(12, 8)
Takeshi Kihara41ceeb52018-01-29 19:01:50 +010077#define CPG_FRQCRC_Z2FC_MASK GENMASK(4, 0)
Takeshi Kihara33918912018-01-29 19:01:49 +010078
79struct cpg_z_clk {
80 struct clk_hw hw;
81 void __iomem *reg;
82 void __iomem *kick_reg;
Takeshi Kihara41ceeb52018-01-29 19:01:50 +010083 unsigned long mask;
Takeshi Kihara33918912018-01-29 19:01:49 +010084};
85
86#define to_z_clk(_hw) container_of(_hw, struct cpg_z_clk, hw)
87
88static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw,
89 unsigned long parent_rate)
90{
91 struct cpg_z_clk *zclk = to_z_clk(hw);
92 unsigned int mult;
Takeshi Kihara41ceeb52018-01-29 19:01:50 +010093 u32 val;
Takeshi Kihara33918912018-01-29 19:01:49 +010094
Geert Uytterhoeven2b935d52018-03-15 10:44:37 +010095 val = readl(zclk->reg) & zclk->mask;
Takeshi Kihara41ceeb52018-01-29 19:01:50 +010096 mult = 32 - (val >> __ffs(zclk->mask));
Takeshi Kihara33918912018-01-29 19:01:49 +010097
98 /* Factor of 2 is for fixed divider */
99 return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * mult, 32 * 2);
100}
101
102static long cpg_z_clk_round_rate(struct clk_hw *hw, unsigned long rate,
103 unsigned long *parent_rate)
104{
105 /* Factor of 2 is for fixed divider */
106 unsigned long prate = *parent_rate / 2;
107 unsigned int mult;
108
109 mult = div_u64(rate * 32ULL, prate);
110 mult = clamp(mult, 1U, 32U);
111
112 return (u64)prate * mult / 32;
113}
114
115static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
116 unsigned long parent_rate)
117{
118 struct cpg_z_clk *zclk = to_z_clk(hw);
119 unsigned int mult;
120 unsigned int i;
121 u32 val, kick;
122
123 /* Factor of 2 is for fixed divider */
124 mult = DIV_ROUND_CLOSEST_ULL(rate * 32ULL * 2, parent_rate);
125 mult = clamp(mult, 1U, 32U);
126
Geert Uytterhoeven2b935d52018-03-15 10:44:37 +0100127 if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
Takeshi Kihara33918912018-01-29 19:01:49 +0100128 return -EBUSY;
129
Geert Uytterhoeven2b935d52018-03-15 10:44:37 +0100130 val = readl(zclk->reg) & ~zclk->mask;
Takeshi Kihara41ceeb52018-01-29 19:01:50 +0100131 val |= ((32 - mult) << __ffs(zclk->mask)) & zclk->mask;
Geert Uytterhoeven2b935d52018-03-15 10:44:37 +0100132 writel(val, zclk->reg);
Takeshi Kihara33918912018-01-29 19:01:49 +0100133
134 /*
135 * Set KICK bit in FRQCRB to update hardware setting and wait for
136 * clock change completion.
137 */
Geert Uytterhoeven2b935d52018-03-15 10:44:37 +0100138 kick = readl(zclk->kick_reg);
Takeshi Kihara33918912018-01-29 19:01:49 +0100139 kick |= CPG_FRQCRB_KICK;
Geert Uytterhoeven2b935d52018-03-15 10:44:37 +0100140 writel(kick, zclk->kick_reg);
Takeshi Kihara33918912018-01-29 19:01:49 +0100141
142 /*
143 * Note: There is no HW information about the worst case latency.
144 *
145 * Using experimental measurements, it seems that no more than
146 * ~10 iterations are needed, independently of the CPU rate.
147 * Since this value might be dependent of external xtal rate, pll1
148 * rate or even the other emulation clocks rate, use 1000 as a
149 * "super" safe value.
150 */
151 for (i = 1000; i; i--) {
Geert Uytterhoeven2b935d52018-03-15 10:44:37 +0100152 if (!(readl(zclk->kick_reg) & CPG_FRQCRB_KICK))
Takeshi Kihara33918912018-01-29 19:01:49 +0100153 return 0;
154
155 cpu_relax();
156 }
157
158 return -ETIMEDOUT;
159}
160
161static const struct clk_ops cpg_z_clk_ops = {
162 .recalc_rate = cpg_z_clk_recalc_rate,
163 .round_rate = cpg_z_clk_round_rate,
164 .set_rate = cpg_z_clk_set_rate,
165};
166
167static struct clk * __init cpg_z_clk_register(const char *name,
168 const char *parent_name,
Takeshi Kihara41ceeb52018-01-29 19:01:50 +0100169 void __iomem *reg,
170 unsigned long mask)
Takeshi Kihara33918912018-01-29 19:01:49 +0100171{
172 struct clk_init_data init;
173 struct cpg_z_clk *zclk;
174 struct clk *clk;
175
176 zclk = kzalloc(sizeof(*zclk), GFP_KERNEL);
177 if (!zclk)
178 return ERR_PTR(-ENOMEM);
179
180 init.name = name;
181 init.ops = &cpg_z_clk_ops;
182 init.flags = 0;
183 init.parent_names = &parent_name;
184 init.num_parents = 1;
185
186 zclk->reg = reg + CPG_FRQCRC;
187 zclk->kick_reg = reg + CPG_FRQCRB;
188 zclk->hw.init = &init;
Takeshi Kihara41ceeb52018-01-29 19:01:50 +0100189 zclk->mask = mask;
Takeshi Kihara33918912018-01-29 19:01:49 +0100190
191 clk = clk_register(NULL, &zclk->hw);
192 if (IS_ERR(clk))
193 kfree(zclk);
194
195 return clk;
196}
197
198/*
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200199 * SDn Clock
200 */
201#define CPG_SD_STP_HCK BIT(9)
202#define CPG_SD_STP_CK BIT(8)
203
204#define CPG_SD_STP_MASK (CPG_SD_STP_HCK | CPG_SD_STP_CK)
205#define CPG_SD_FC_MASK (0x7 << 2 | 0x3 << 0)
206
207#define CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) \
208{ \
209 .val = ((stp_hck) ? CPG_SD_STP_HCK : 0) | \
210 ((stp_ck) ? CPG_SD_STP_CK : 0) | \
211 ((sd_srcfc) << 2) | \
212 ((sd_fc) << 0), \
213 .div = (sd_div), \
214}
215
216struct sd_div_table {
217 u32 val;
218 unsigned int div;
219};
220
221struct sd_clock {
222 struct clk_hw hw;
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200223 const struct sd_div_table *div_table;
Geert Uytterhoeven9f55b172017-06-21 22:51:21 +0200224 struct cpg_simple_notifier csn;
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200225 unsigned int div_num;
226 unsigned int div_min;
227 unsigned int div_max;
Wolfram Sang2d6f2572017-07-18 18:44:07 +0200228 unsigned int cur_div_idx;
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200229};
230
231/* SDn divider
232 * sd_srcfc sd_fc div
233 * stp_hck stp_ck (div) (div) = sd_srcfc x sd_fc
234 *-------------------------------------------------------------------
235 * 0 0 0 (1) 1 (4) 4
236 * 0 0 1 (2) 1 (4) 8
237 * 1 0 2 (4) 1 (4) 16
238 * 1 0 3 (8) 1 (4) 32
239 * 1 0 4 (16) 1 (4) 64
240 * 0 0 0 (1) 0 (2) 2
241 * 0 0 1 (2) 0 (2) 4
242 * 1 0 2 (4) 0 (2) 8
243 * 1 0 3 (8) 0 (2) 16
244 * 1 0 4 (16) 0 (2) 32
245 */
246static const struct sd_div_table cpg_sd_div_table[] = {
247/* CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) */
248 CPG_SD_DIV_TABLE_DATA(0, 0, 0, 1, 4),
249 CPG_SD_DIV_TABLE_DATA(0, 0, 1, 1, 8),
250 CPG_SD_DIV_TABLE_DATA(1, 0, 2, 1, 16),
251 CPG_SD_DIV_TABLE_DATA(1, 0, 3, 1, 32),
252 CPG_SD_DIV_TABLE_DATA(1, 0, 4, 1, 64),
253 CPG_SD_DIV_TABLE_DATA(0, 0, 0, 0, 2),
254 CPG_SD_DIV_TABLE_DATA(0, 0, 1, 0, 4),
255 CPG_SD_DIV_TABLE_DATA(1, 0, 2, 0, 8),
256 CPG_SD_DIV_TABLE_DATA(1, 0, 3, 0, 16),
257 CPG_SD_DIV_TABLE_DATA(1, 0, 4, 0, 32),
258};
259
260#define to_sd_clock(_hw) container_of(_hw, struct sd_clock, hw)
261
262static int cpg_sd_clock_enable(struct clk_hw *hw)
263{
264 struct sd_clock *clock = to_sd_clock(hw);
Geert Uytterhoeven9f55b172017-06-21 22:51:21 +0200265 u32 val = readl(clock->csn.reg);
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200266
267 val &= ~(CPG_SD_STP_MASK);
Wolfram Sang2d6f2572017-07-18 18:44:07 +0200268 val |= clock->div_table[clock->cur_div_idx].val & CPG_SD_STP_MASK;
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200269
Geert Uytterhoeven9f55b172017-06-21 22:51:21 +0200270 writel(val, clock->csn.reg);
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200271
272 return 0;
273}
274
275static void cpg_sd_clock_disable(struct clk_hw *hw)
276{
277 struct sd_clock *clock = to_sd_clock(hw);
278
Geert Uytterhoeven9f55b172017-06-21 22:51:21 +0200279 writel(readl(clock->csn.reg) | CPG_SD_STP_MASK, clock->csn.reg);
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200280}
281
282static int cpg_sd_clock_is_enabled(struct clk_hw *hw)
283{
284 struct sd_clock *clock = to_sd_clock(hw);
285
Geert Uytterhoeven9f55b172017-06-21 22:51:21 +0200286 return !(readl(clock->csn.reg) & CPG_SD_STP_MASK);
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200287}
288
289static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw,
290 unsigned long parent_rate)
291{
292 struct sd_clock *clock = to_sd_clock(hw);
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200293
Wolfram Sang2d6f2572017-07-18 18:44:07 +0200294 return DIV_ROUND_CLOSEST(parent_rate,
295 clock->div_table[clock->cur_div_idx].div);
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200296}
297
298static unsigned int cpg_sd_clock_calc_div(struct sd_clock *clock,
299 unsigned long rate,
300 unsigned long parent_rate)
301{
302 unsigned int div;
303
304 if (!rate)
305 rate = 1;
306
307 div = DIV_ROUND_CLOSEST(parent_rate, rate);
308
309 return clamp_t(unsigned int, div, clock->div_min, clock->div_max);
310}
311
312static long cpg_sd_clock_round_rate(struct clk_hw *hw, unsigned long rate,
313 unsigned long *parent_rate)
314{
315 struct sd_clock *clock = to_sd_clock(hw);
316 unsigned int div = cpg_sd_clock_calc_div(clock, rate, *parent_rate);
317
318 return DIV_ROUND_CLOSEST(*parent_rate, div);
319}
320
321static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate,
322 unsigned long parent_rate)
323{
324 struct sd_clock *clock = to_sd_clock(hw);
325 unsigned int div = cpg_sd_clock_calc_div(clock, rate, parent_rate);
326 u32 val;
327 unsigned int i;
328
329 for (i = 0; i < clock->div_num; i++)
330 if (div == clock->div_table[i].div)
331 break;
332
333 if (i >= clock->div_num)
334 return -EINVAL;
335
Wolfram Sang2d6f2572017-07-18 18:44:07 +0200336 clock->cur_div_idx = i;
337
Geert Uytterhoeven9f55b172017-06-21 22:51:21 +0200338 val = readl(clock->csn.reg);
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200339 val &= ~(CPG_SD_STP_MASK | CPG_SD_FC_MASK);
340 val |= clock->div_table[i].val & (CPG_SD_STP_MASK | CPG_SD_FC_MASK);
Geert Uytterhoeven9f55b172017-06-21 22:51:21 +0200341 writel(val, clock->csn.reg);
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200342
343 return 0;
344}
345
346static const struct clk_ops cpg_sd_clock_ops = {
347 .enable = cpg_sd_clock_enable,
348 .disable = cpg_sd_clock_disable,
349 .is_enabled = cpg_sd_clock_is_enabled,
350 .recalc_rate = cpg_sd_clock_recalc_rate,
351 .round_rate = cpg_sd_clock_round_rate,
352 .set_rate = cpg_sd_clock_set_rate,
353};
354
355static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core,
Geert Uytterhoeven9f55b172017-06-21 22:51:21 +0200356 void __iomem *base, const char *parent_name,
357 struct raw_notifier_head *notifiers)
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200358{
359 struct clk_init_data init;
360 struct sd_clock *clock;
361 struct clk *clk;
362 unsigned int i;
Wolfram Sang2d6f2572017-07-18 18:44:07 +0200363 u32 sd_fc;
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200364
365 clock = kzalloc(sizeof(*clock), GFP_KERNEL);
366 if (!clock)
367 return ERR_PTR(-ENOMEM);
368
369 init.name = core->name;
370 init.ops = &cpg_sd_clock_ops;
371 init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT;
372 init.parent_names = &parent_name;
373 init.num_parents = 1;
374
Geert Uytterhoeven9f55b172017-06-21 22:51:21 +0200375 clock->csn.reg = base + core->offset;
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200376 clock->hw.init = &init;
377 clock->div_table = cpg_sd_div_table;
378 clock->div_num = ARRAY_SIZE(cpg_sd_div_table);
379
Geert Uytterhoeven9f55b172017-06-21 22:51:21 +0200380 sd_fc = readl(clock->csn.reg) & CPG_SD_FC_MASK;
Wolfram Sang2d6f2572017-07-18 18:44:07 +0200381 for (i = 0; i < clock->div_num; i++)
382 if (sd_fc == (clock->div_table[i].val & CPG_SD_FC_MASK))
383 break;
384
385 if (WARN_ON(i >= clock->div_num)) {
386 kfree(clock);
387 return ERR_PTR(-EINVAL);
388 }
389
390 clock->cur_div_idx = i;
391
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200392 clock->div_max = clock->div_table[0].div;
393 clock->div_min = clock->div_max;
394 for (i = 1; i < clock->div_num; i++) {
395 clock->div_max = max(clock->div_max, clock->div_table[i].div);
396 clock->div_min = min(clock->div_min, clock->div_table[i].div);
397 }
398
399 clk = clk_register(NULL, &clock->hw);
400 if (IS_ERR(clk))
Geert Uytterhoeven9f55b172017-06-21 22:51:21 +0200401 goto free_clock;
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200402
Geert Uytterhoeven9f55b172017-06-21 22:51:21 +0200403 cpg_simple_notifier_register(notifiers, &clock->csn);
404 return clk;
405
406free_clock:
407 kfree(clock);
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200408 return clk;
409}
410
411
412static const struct rcar_gen3_cpg_pll_config *cpg_pll_config __initdata;
413static unsigned int cpg_clk_extalr __initdata;
Geert Uytterhoeven5f3a4322017-03-10 11:36:33 +0100414static u32 cpg_mode __initdata;
Geert Uytterhoevencecbe872017-03-10 11:46:10 +0100415static u32 cpg_quirks __initdata;
416
417#define PLL_ERRATA BIT(0) /* Missing PLL0/2/4 post-divider */
Geert Uytterhoevenbb195302017-03-10 12:13:37 +0100418#define RCKCR_CKSEL BIT(1) /* Manual RCLK parent selection */
Geert Uytterhoevencecbe872017-03-10 11:46:10 +0100419
420static const struct soc_device_attribute cpg_quirks_match[] __initconst = {
421 {
422 .soc_id = "r8a7795", .revision = "ES1.0",
Geert Uytterhoevenbb195302017-03-10 12:13:37 +0100423 .data = (void *)(PLL_ERRATA | RCKCR_CKSEL),
424 },
425 {
426 .soc_id = "r8a7795", .revision = "ES1.*",
427 .data = (void *)RCKCR_CKSEL,
428 },
429 {
430 .soc_id = "r8a7796", .revision = "ES1.0",
431 .data = (void *)RCKCR_CKSEL,
Geert Uytterhoevencecbe872017-03-10 11:46:10 +0100432 },
433 { /* sentinel */ }
434};
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200435
436struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
437 const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
Geert Uytterhoeven1f4023c2017-06-21 22:24:15 +0200438 struct clk **clks, void __iomem *base,
439 struct raw_notifier_head *notifiers)
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200440{
441 const struct clk *parent;
442 unsigned int mult = 1;
443 unsigned int div = 1;
444 u32 value;
445
Geert Uytterhoevenb9d0b842018-07-11 13:54:30 +0200446 parent = clks[core->parent & 0xffff]; /* some types use high bits */
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200447 if (IS_ERR(parent))
448 return ERR_CAST(parent);
449
450 switch (core->type) {
451 case CLK_TYPE_GEN3_MAIN:
452 div = cpg_pll_config->extal_div;
453 break;
454
455 case CLK_TYPE_GEN3_PLL0:
456 /*
457 * PLL0 is a configurable multiplier clock. Register it as a
458 * fixed factor clock for now as there's no generic multiplier
459 * clock implementation and we currently have no need to change
460 * the multiplier value.
461 */
462 value = readl(base + CPG_PLL0CR);
463 mult = (((value >> 24) & 0x7f) + 1) * 2;
Geert Uytterhoevencecbe872017-03-10 11:46:10 +0100464 if (cpg_quirks & PLL_ERRATA)
465 mult *= 2;
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200466 break;
467
468 case CLK_TYPE_GEN3_PLL1:
469 mult = cpg_pll_config->pll1_mult;
Geert Uytterhoeven09a7dea2017-07-19 16:30:45 +0200470 div = cpg_pll_config->pll1_div;
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200471 break;
472
473 case CLK_TYPE_GEN3_PLL2:
474 /*
475 * PLL2 is a configurable multiplier clock. Register it as a
476 * fixed factor clock for now as there's no generic multiplier
477 * clock implementation and we currently have no need to change
478 * the multiplier value.
479 */
480 value = readl(base + CPG_PLL2CR);
481 mult = (((value >> 24) & 0x7f) + 1) * 2;
Geert Uytterhoevencecbe872017-03-10 11:46:10 +0100482 if (cpg_quirks & PLL_ERRATA)
483 mult *= 2;
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200484 break;
485
486 case CLK_TYPE_GEN3_PLL3:
487 mult = cpg_pll_config->pll3_mult;
Geert Uytterhoeven09a7dea2017-07-19 16:30:45 +0200488 div = cpg_pll_config->pll3_div;
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200489 break;
490
491 case CLK_TYPE_GEN3_PLL4:
492 /*
493 * PLL4 is a configurable multiplier clock. Register it as a
494 * fixed factor clock for now as there's no generic multiplier
495 * clock implementation and we currently have no need to change
496 * the multiplier value.
497 */
498 value = readl(base + CPG_PLL4CR);
499 mult = (((value >> 24) & 0x7f) + 1) * 2;
Geert Uytterhoevencecbe872017-03-10 11:46:10 +0100500 if (cpg_quirks & PLL_ERRATA)
501 mult *= 2;
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200502 break;
503
504 case CLK_TYPE_GEN3_SD:
Geert Uytterhoeven9f55b172017-06-21 22:51:21 +0200505 return cpg_sd_clk_register(core, base, __clk_get_name(parent),
506 notifiers);
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200507
508 case CLK_TYPE_GEN3_R:
Geert Uytterhoevenbb195302017-03-10 12:13:37 +0100509 if (cpg_quirks & RCKCR_CKSEL) {
Geert Uytterhoeven3f7a4d02017-06-28 21:15:49 +0200510 struct cpg_simple_notifier *csn;
511
512 csn = kzalloc(sizeof(*csn), GFP_KERNEL);
513 if (!csn)
514 return ERR_PTR(-ENOMEM);
515
516 csn->reg = base + CPG_RCKCR;
517
Geert Uytterhoevenbb195302017-03-10 12:13:37 +0100518 /*
519 * RINT is default.
520 * Only if EXTALR is populated, we switch to it.
521 */
Geert Uytterhoeven3f7a4d02017-06-28 21:15:49 +0200522 value = readl(csn->reg) & 0x3f;
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200523
Geert Uytterhoevenbb195302017-03-10 12:13:37 +0100524 if (clk_get_rate(clks[cpg_clk_extalr])) {
525 parent = clks[cpg_clk_extalr];
Geert Uytterhoevenb9d0b842018-07-11 13:54:30 +0200526 value |= CPG_RCKCR_CKSEL;
Geert Uytterhoevenbb195302017-03-10 12:13:37 +0100527 }
528
Geert Uytterhoeven3f7a4d02017-06-28 21:15:49 +0200529 writel(value, csn->reg);
530 cpg_simple_notifier_register(notifiers, csn);
Geert Uytterhoevenbb195302017-03-10 12:13:37 +0100531 break;
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200532 }
533
Geert Uytterhoevenbb195302017-03-10 12:13:37 +0100534 /* Select parent clock of RCLK by MD28 */
535 if (cpg_mode & BIT(28))
536 parent = clks[cpg_clk_extalr];
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200537 break;
538
Geert Uytterhoevencd51e422018-07-11 14:19:47 +0200539 case CLK_TYPE_GEN3_MDSEL:
Geert Uytterhoeven696997e2017-07-19 17:39:54 +0200540 /*
Geert Uytterhoevencd51e422018-07-11 14:19:47 +0200541 * Clock selectable between two parents and two fixed dividers
542 * using a mode pin
Geert Uytterhoeven696997e2017-07-19 17:39:54 +0200543 */
Geert Uytterhoevencd51e422018-07-11 14:19:47 +0200544 if (cpg_mode & BIT(core->offset)) {
Geert Uytterhoeven696997e2017-07-19 17:39:54 +0200545 div = core->div & 0xffff;
546 } else {
Geert Uytterhoeven696997e2017-07-19 17:39:54 +0200547 parent = clks[core->parent >> 16];
548 if (IS_ERR(parent))
549 return ERR_CAST(parent);
550 div = core->div >> 16;
551 }
552 mult = 1;
553 break;
554
Takeshi Kihara33918912018-01-29 19:01:49 +0100555 case CLK_TYPE_GEN3_Z:
556 return cpg_z_clk_register(core->name, __clk_get_name(parent),
Takeshi Kihara41ceeb52018-01-29 19:01:50 +0100557 base, CPG_FRQCRC_ZFC_MASK);
558
559 case CLK_TYPE_GEN3_Z2:
560 return cpg_z_clk_register(core->name, __clk_get_name(parent),
561 base, CPG_FRQCRC_Z2FC_MASK);
Takeshi Kihara33918912018-01-29 19:01:49 +0100562
Geert Uytterhoeven38c79e22018-07-11 13:14:44 +0200563 case CLK_TYPE_GEN3_OSC:
564 /*
565 * Clock combining OSC EXTAL predivider and a fixed divider
566 */
567 div = cpg_pll_config->osc_prediv * core->div;
568 break;
569
Geert Uytterhoevenb9d0b842018-07-11 13:54:30 +0200570 case CLK_TYPE_GEN3_RCKSEL:
571 /*
572 * Clock selectable between two parents and two fixed dividers
573 * using RCKCR.CKSEL
574 */
575 if (readl(base + CPG_RCKCR) & CPG_RCKCR_CKSEL) {
576 div = core->div & 0xffff;
577 } else {
578 parent = clks[core->parent >> 16];
579 if (IS_ERR(parent))
580 return ERR_CAST(parent);
581 div = core->div >> 16;
582 }
583 break;
584
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200585 default:
586 return ERR_PTR(-EINVAL);
587 }
588
589 return clk_register_fixed_factor(NULL, core->name,
590 __clk_get_name(parent), 0, mult, div);
591}
592
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200593int __init rcar_gen3_cpg_init(const struct rcar_gen3_cpg_pll_config *config,
Geert Uytterhoeven5f3a4322017-03-10 11:36:33 +0100594 unsigned int clk_extalr, u32 mode)
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200595{
Geert Uytterhoevencecbe872017-03-10 11:46:10 +0100596 const struct soc_device_attribute *attr;
597
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200598 cpg_pll_config = config;
599 cpg_clk_extalr = clk_extalr;
Geert Uytterhoeven5f3a4322017-03-10 11:36:33 +0100600 cpg_mode = mode;
Geert Uytterhoevencecbe872017-03-10 11:46:10 +0100601 attr = soc_device_match(cpg_quirks_match);
602 if (attr)
603 cpg_quirks = (uintptr_t)attr->data;
604 pr_debug("%s: mode = 0x%x quirks = 0x%x\n", __func__, mode, cpg_quirks);
Geert Uytterhoeven5b1defd2016-05-04 14:32:56 +0200605 return 0;
606}