blob: a9c4f67b94b5dc60c67a77af482b3818f17789de [file] [log] [blame]
Wolfram Sange848c2e2018-08-22 00:02:14 +02001// SPDX-License-Identifier: GPL-2.0
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +02002/*
3 * Renesas Clock Pulse Generator / Module Standby and Software Reset
4 *
5 * Copyright (C) 2015 Glider bvba
6 *
7 * Based on clk-mstp.c, clk-rcar-gen2.c, and clk-rcar-gen3.c
8 *
9 * Copyright (C) 2013 Ideas On Board SPRL
10 * Copyright (C) 2015 Renesas Electronics Corp.
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +020011 */
12
13#include <linux/clk.h>
14#include <linux/clk-provider.h>
Geert Uytterhoeven20663902016-03-04 17:03:46 +010015#include <linux/clk/renesas.h>
Geert Uytterhoeven6197aa62017-01-20 11:03:03 +010016#include <linux/delay.h>
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +020017#include <linux/device.h>
18#include <linux/init.h>
19#include <linux/mod_devicetable.h>
20#include <linux/module.h>
21#include <linux/of_address.h>
22#include <linux/of_device.h>
23#include <linux/platform_device.h>
24#include <linux/pm_clock.h>
25#include <linux/pm_domain.h>
Geert Uytterhoeven56086912017-06-07 13:20:06 +020026#include <linux/psci.h>
Geert Uytterhoeven6197aa62017-01-20 11:03:03 +010027#include <linux/reset-controller.h>
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +020028#include <linux/slab.h>
29
30#include <dt-bindings/clock/renesas-cpg-mssr.h>
31
32#include "renesas-cpg-mssr.h"
33#include "clk-div6.h"
34
35#ifdef DEBUG
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +020036#define WARN_DEBUG(x) WARN_ON(x)
Geert Uytterhoevenbc4725d2016-10-03 13:03:38 +020037#else
38#define WARN_DEBUG(x) do { } while (0)
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +020039#endif
40
41
42/*
43 * Module Standby and Software Reset register offets.
44 *
45 * If the registers exist, these are valid for SH-Mobile, R-Mobile,
Geert Uytterhoeven67c995b2017-01-20 10:53:11 +010046 * R-Car Gen2, R-Car Gen3, and RZ/G1.
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +020047 * These are NOT valid for R-Car Gen1 and RZ/A1!
48 */
49
50/*
51 * Module Stop Status Register offsets
52 */
53
54static const u16 mstpsr[] = {
55 0x030, 0x038, 0x040, 0x048, 0x04C, 0x03C, 0x1C0, 0x1C4,
56 0x9A0, 0x9A4, 0x9A8, 0x9AC,
57};
58
59#define MSTPSR(i) mstpsr[i]
60
61
62/*
63 * System Module Stop Control Register offsets
64 */
65
66static const u16 smstpcr[] = {
67 0x130, 0x134, 0x138, 0x13C, 0x140, 0x144, 0x148, 0x14C,
68 0x990, 0x994, 0x998, 0x99C,
69};
70
71#define SMSTPCR(i) smstpcr[i]
72
73
74/*
75 * Software Reset Register offsets
76 */
77
78static const u16 srcr[] = {
79 0x0A0, 0x0A8, 0x0B0, 0x0B8, 0x0BC, 0x0C4, 0x1C8, 0x1CC,
80 0x920, 0x924, 0x928, 0x92C,
81};
82
83#define SRCR(i) srcr[i]
84
85
86/* Realtime Module Stop Control Register offsets */
87#define RMSTPCR(i) (smstpcr[i] - 0x20)
88
89/* Modem Module Stop Control Register offsets (r8a73a4) */
90#define MMSTPCR(i) (smstpcr[i] + 0x20)
91
92/* Software Reset Clearing Register offsets */
93#define SRSTCLR(i) (0x940 + (i) * 4)
94
95
96/**
97 * Clock Pulse Generator / Module Standby and Software Reset Private Data
98 *
Geert Uytterhoeven6197aa62017-01-20 11:03:03 +010099 * @rcdev: Optional reset controller entity
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200100 * @dev: CPG/MSSR device
101 * @base: CPG/MSSR register block base address
Geert Uytterhoevena4ea6a02017-01-20 10:58:11 +0100102 * @rmw_lock: protects RMW register accesses
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200103 * @clks: Array containing all Core and Module Clocks
104 * @num_core_clks: Number of Core Clocks in clks[]
105 * @num_mod_clks: Number of Module Clocks in clks[]
106 * @last_dt_core_clk: ID of the last Core Clock exported to DT
Geert Uytterhoeven1f4023c2017-06-21 22:24:15 +0200107 * @notifiers: Notifier chain to save/restore clock state for system resume
Geert Uytterhoeven56086912017-06-07 13:20:06 +0200108 * @smstpcr_saved[].mask: Mask of SMSTPCR[] bits under our control
109 * @smstpcr_saved[].val: Saved values of SMSTPCR[]
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200110 */
111struct cpg_mssr_priv {
Geert Uytterhoeven6197aa62017-01-20 11:03:03 +0100112#ifdef CONFIG_RESET_CONTROLLER
113 struct reset_controller_dev rcdev;
114#endif
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200115 struct device *dev;
116 void __iomem *base;
Geert Uytterhoevena4ea6a02017-01-20 10:58:11 +0100117 spinlock_t rmw_lock;
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200118
119 struct clk **clks;
120 unsigned int num_core_clks;
121 unsigned int num_mod_clks;
122 unsigned int last_dt_core_clk;
Geert Uytterhoeven56086912017-06-07 13:20:06 +0200123
Geert Uytterhoeven1f4023c2017-06-21 22:24:15 +0200124 struct raw_notifier_head notifiers;
Geert Uytterhoeven56086912017-06-07 13:20:06 +0200125 struct {
126 u32 mask;
127 u32 val;
128 } smstpcr_saved[ARRAY_SIZE(smstpcr)];
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200129};
130
131
132/**
133 * struct mstp_clock - MSTP gating clock
134 * @hw: handle between common and hardware-specific interfaces
135 * @index: MSTP clock number
136 * @priv: CPG/MSSR private data
137 */
138struct mstp_clock {
139 struct clk_hw hw;
140 u32 index;
141 struct cpg_mssr_priv *priv;
142};
143
144#define to_mstp_clock(_hw) container_of(_hw, struct mstp_clock, hw)
145
146static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
147{
148 struct mstp_clock *clock = to_mstp_clock(hw);
149 struct cpg_mssr_priv *priv = clock->priv;
150 unsigned int reg = clock->index / 32;
151 unsigned int bit = clock->index % 32;
152 struct device *dev = priv->dev;
153 u32 bitmask = BIT(bit);
154 unsigned long flags;
155 unsigned int i;
156 u32 value;
157
158 dev_dbg(dev, "MSTP %u%02u/%pC %s\n", reg, bit, hw->clk,
159 enable ? "ON" : "OFF");
Geert Uytterhoevena4ea6a02017-01-20 10:58:11 +0100160 spin_lock_irqsave(&priv->rmw_lock, flags);
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200161
Geert Uytterhoevenc1b53712016-09-21 16:31:41 +0200162 value = readl(priv->base + SMSTPCR(reg));
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200163 if (enable)
164 value &= ~bitmask;
165 else
166 value |= bitmask;
Geert Uytterhoevenc1b53712016-09-21 16:31:41 +0200167 writel(value, priv->base + SMSTPCR(reg));
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200168
Geert Uytterhoevena4ea6a02017-01-20 10:58:11 +0100169 spin_unlock_irqrestore(&priv->rmw_lock, flags);
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200170
171 if (!enable)
172 return 0;
173
174 for (i = 1000; i > 0; --i) {
Geert Uytterhoevenc1b53712016-09-21 16:31:41 +0200175 if (!(readl(priv->base + MSTPSR(reg)) & bitmask))
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200176 break;
177 cpu_relax();
178 }
179
180 if (!i) {
181 dev_err(dev, "Failed to enable SMSTP %p[%d]\n",
182 priv->base + SMSTPCR(reg), bit);
183 return -ETIMEDOUT;
184 }
185
186 return 0;
187}
188
189static int cpg_mstp_clock_enable(struct clk_hw *hw)
190{
191 return cpg_mstp_clock_endisable(hw, true);
192}
193
194static void cpg_mstp_clock_disable(struct clk_hw *hw)
195{
196 cpg_mstp_clock_endisable(hw, false);
197}
198
199static int cpg_mstp_clock_is_enabled(struct clk_hw *hw)
200{
201 struct mstp_clock *clock = to_mstp_clock(hw);
202 struct cpg_mssr_priv *priv = clock->priv;
203 u32 value;
204
Geert Uytterhoevenc1b53712016-09-21 16:31:41 +0200205 value = readl(priv->base + MSTPSR(clock->index / 32));
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200206
207 return !(value & BIT(clock->index % 32));
208}
209
210static const struct clk_ops cpg_mstp_clock_ops = {
211 .enable = cpg_mstp_clock_enable,
212 .disable = cpg_mstp_clock_disable,
213 .is_enabled = cpg_mstp_clock_is_enabled,
214};
215
216static
217struct clk *cpg_mssr_clk_src_twocell_get(struct of_phandle_args *clkspec,
218 void *data)
219{
220 unsigned int clkidx = clkspec->args[1];
221 struct cpg_mssr_priv *priv = data;
222 struct device *dev = priv->dev;
223 unsigned int idx;
224 const char *type;
225 struct clk *clk;
226
227 switch (clkspec->args[0]) {
228 case CPG_CORE:
229 type = "core";
230 if (clkidx > priv->last_dt_core_clk) {
231 dev_err(dev, "Invalid %s clock index %u\n", type,
232 clkidx);
233 return ERR_PTR(-EINVAL);
234 }
235 clk = priv->clks[clkidx];
236 break;
237
238 case CPG_MOD:
239 type = "module";
240 idx = MOD_CLK_PACK(clkidx);
241 if (clkidx % 100 > 31 || idx >= priv->num_mod_clks) {
242 dev_err(dev, "Invalid %s clock index %u\n", type,
243 clkidx);
244 return ERR_PTR(-EINVAL);
245 }
246 clk = priv->clks[priv->num_core_clks + idx];
247 break;
248
249 default:
250 dev_err(dev, "Invalid CPG clock type %u\n", clkspec->args[0]);
251 return ERR_PTR(-EINVAL);
252 }
253
254 if (IS_ERR(clk))
255 dev_err(dev, "Cannot get %s clock %u: %ld", type, clkidx,
256 PTR_ERR(clk));
257 else
Geert Uytterhoevenef4b0be2018-06-01 11:28:19 +0200258 dev_dbg(dev, "clock (%u, %u) is %pC at %lu Hz\n",
259 clkspec->args[0], clkspec->args[1], clk,
260 clk_get_rate(clk));
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200261 return clk;
262}
263
264static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core,
265 const struct cpg_mssr_info *info,
266 struct cpg_mssr_priv *priv)
267{
Geert Uytterhoeven76394a362017-05-17 15:43:56 +0200268 struct clk *clk = ERR_PTR(-ENOTSUPP), *parent;
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200269 struct device *dev = priv->dev;
Wolfram Sang5d3927f2016-03-30 16:58:18 +0200270 unsigned int id = core->id, div = core->div;
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200271 const char *parent_name;
272
273 WARN_DEBUG(id >= priv->num_core_clks);
274 WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT);
275
Geert Uytterhoeven48d03412016-09-29 14:47:58 +0200276 if (!core->name) {
277 /* Skip NULLified clock */
278 return;
279 }
280
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200281 switch (core->type) {
282 case CLK_TYPE_IN:
283 clk = of_clk_get_by_name(priv->dev->of_node, core->name);
284 break;
285
286 case CLK_TYPE_FF:
287 case CLK_TYPE_DIV6P1:
Wolfram Sang5d3927f2016-03-30 16:58:18 +0200288 case CLK_TYPE_DIV6_RO:
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200289 WARN_DEBUG(core->parent >= priv->num_core_clks);
290 parent = priv->clks[core->parent];
291 if (IS_ERR(parent)) {
292 clk = parent;
293 goto fail;
294 }
295
296 parent_name = __clk_get_name(parent);
Wolfram Sang5d3927f2016-03-30 16:58:18 +0200297
298 if (core->type == CLK_TYPE_DIV6_RO)
299 /* Multiply with the DIV6 register value */
300 div *= (readl(priv->base + core->offset) & 0x3f) + 1;
301
302 if (core->type == CLK_TYPE_DIV6P1) {
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200303 clk = cpg_div6_register(core->name, 1, &parent_name,
Geert Uytterhoeven9f8c71e2017-06-21 22:34:33 +0200304 priv->base + core->offset,
305 &priv->notifiers);
Wolfram Sang5d3927f2016-03-30 16:58:18 +0200306 } else {
307 clk = clk_register_fixed_factor(NULL, core->name,
308 parent_name, 0,
309 core->mult, div);
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200310 }
311 break;
312
313 default:
314 if (info->cpg_clk_register)
315 clk = info->cpg_clk_register(dev, core, info,
Geert Uytterhoeven1f4023c2017-06-21 22:24:15 +0200316 priv->clks, priv->base,
317 &priv->notifiers);
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200318 else
319 dev_err(dev, "%s has unsupported core clock type %u\n",
320 core->name, core->type);
321 break;
322 }
323
324 if (IS_ERR_OR_NULL(clk))
325 goto fail;
326
Geert Uytterhoevenef4b0be2018-06-01 11:28:19 +0200327 dev_dbg(dev, "Core clock %pC at %lu Hz\n", clk, clk_get_rate(clk));
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200328 priv->clks[id] = clk;
329 return;
330
331fail:
Geert Uytterhoeven1b9fe702016-10-18 15:59:13 +0200332 dev_err(dev, "Failed to register %s clock %s: %ld\n", "core",
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200333 core->name, PTR_ERR(clk));
334}
335
336static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod,
337 const struct cpg_mssr_info *info,
338 struct cpg_mssr_priv *priv)
339{
340 struct mstp_clock *clock = NULL;
341 struct device *dev = priv->dev;
342 unsigned int id = mod->id;
343 struct clk_init_data init;
344 struct clk *parent, *clk;
345 const char *parent_name;
346 unsigned int i;
347
348 WARN_DEBUG(id < priv->num_core_clks);
349 WARN_DEBUG(id >= priv->num_core_clks + priv->num_mod_clks);
350 WARN_DEBUG(mod->parent >= priv->num_core_clks + priv->num_mod_clks);
351 WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT);
352
Geert Uytterhoeven48d03412016-09-29 14:47:58 +0200353 if (!mod->name) {
354 /* Skip NULLified clock */
355 return;
356 }
357
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200358 parent = priv->clks[mod->parent];
359 if (IS_ERR(parent)) {
360 clk = parent;
361 goto fail;
362 }
363
364 clock = kzalloc(sizeof(*clock), GFP_KERNEL);
365 if (!clock) {
366 clk = ERR_PTR(-ENOMEM);
367 goto fail;
368 }
369
370 init.name = mod->name;
371 init.ops = &cpg_mstp_clock_ops;
372 init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT;
373 for (i = 0; i < info->num_crit_mod_clks; i++)
374 if (id == info->crit_mod_clks[i]) {
Geert Uytterhoeven72f5df2c2017-01-16 16:15:50 +0100375 dev_dbg(dev, "MSTP %s setting CLK_IS_CRITICAL\n",
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200376 mod->name);
Geert Uytterhoeven72f5df2c2017-01-16 16:15:50 +0100377 init.flags |= CLK_IS_CRITICAL;
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200378 break;
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200379 }
380
381 parent_name = __clk_get_name(parent);
382 init.parent_names = &parent_name;
383 init.num_parents = 1;
384
385 clock->index = id - priv->num_core_clks;
386 clock->priv = priv;
387 clock->hw.init = &init;
388
389 clk = clk_register(NULL, &clock->hw);
390 if (IS_ERR(clk))
391 goto fail;
392
Geert Uytterhoevenef4b0be2018-06-01 11:28:19 +0200393 dev_dbg(dev, "Module clock %pC at %lu Hz\n", clk, clk_get_rate(clk));
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200394 priv->clks[id] = clk;
Geert Uytterhoeven56086912017-06-07 13:20:06 +0200395 priv->smstpcr_saved[clock->index / 32].mask |= BIT(clock->index % 32);
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200396 return;
397
398fail:
Geert Uytterhoeven1b9fe702016-10-18 15:59:13 +0200399 dev_err(dev, "Failed to register %s clock %s: %ld\n", "module",
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200400 mod->name, PTR_ERR(clk));
401 kfree(clock);
402}
403
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200404struct cpg_mssr_clk_domain {
405 struct generic_pm_domain genpd;
406 struct device_node *np;
407 unsigned int num_core_pm_clks;
408 unsigned int core_pm_clks[0];
409};
410
Geert Uytterhoeven20663902016-03-04 17:03:46 +0100411static struct cpg_mssr_clk_domain *cpg_mssr_clk_domain;
412
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200413static bool cpg_mssr_is_pm_clk(const struct of_phandle_args *clkspec,
414 struct cpg_mssr_clk_domain *pd)
415{
416 unsigned int i;
417
418 if (clkspec->np != pd->np || clkspec->args_count != 2)
419 return false;
420
421 switch (clkspec->args[0]) {
422 case CPG_CORE:
423 for (i = 0; i < pd->num_core_pm_clks; i++)
424 if (clkspec->args[1] == pd->core_pm_clks[i])
425 return true;
426 return false;
427
428 case CPG_MOD:
429 return true;
430
431 default:
432 return false;
433 }
434}
435
Geert Uytterhoeven20663902016-03-04 17:03:46 +0100436int cpg_mssr_attach_dev(struct generic_pm_domain *unused, struct device *dev)
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200437{
Geert Uytterhoeven20663902016-03-04 17:03:46 +0100438 struct cpg_mssr_clk_domain *pd = cpg_mssr_clk_domain;
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200439 struct device_node *np = dev->of_node;
440 struct of_phandle_args clkspec;
441 struct clk *clk;
442 int i = 0;
443 int error;
444
Geert Uytterhoeven20663902016-03-04 17:03:46 +0100445 if (!pd) {
446 dev_dbg(dev, "CPG/MSSR clock domain not yet available\n");
447 return -EPROBE_DEFER;
448 }
449
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200450 while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i,
451 &clkspec)) {
452 if (cpg_mssr_is_pm_clk(&clkspec, pd))
453 goto found;
454
455 of_node_put(clkspec.np);
456 i++;
457 }
458
459 return 0;
460
461found:
462 clk = of_clk_get_from_provider(&clkspec);
463 of_node_put(clkspec.np);
464
465 if (IS_ERR(clk))
466 return PTR_ERR(clk);
467
468 error = pm_clk_create(dev);
469 if (error) {
470 dev_err(dev, "pm_clk_create failed %d\n", error);
471 goto fail_put;
472 }
473
474 error = pm_clk_add_clk(dev, clk);
475 if (error) {
476 dev_err(dev, "pm_clk_add_clk %pC failed %d\n", clk, error);
477 goto fail_destroy;
478 }
479
480 return 0;
481
482fail_destroy:
483 pm_clk_destroy(dev);
484fail_put:
485 clk_put(clk);
486 return error;
487}
488
Geert Uytterhoeven20663902016-03-04 17:03:46 +0100489void cpg_mssr_detach_dev(struct generic_pm_domain *unused, struct device *dev)
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200490{
Geert Uytterhoevene05e8532017-02-08 19:08:44 +0100491 if (!pm_clk_no_clocks(dev))
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200492 pm_clk_destroy(dev);
493}
494
495static int __init cpg_mssr_add_clk_domain(struct device *dev,
496 const unsigned int *core_pm_clks,
497 unsigned int num_core_pm_clks)
498{
499 struct device_node *np = dev->of_node;
500 struct generic_pm_domain *genpd;
501 struct cpg_mssr_clk_domain *pd;
502 size_t pm_size = num_core_pm_clks * sizeof(core_pm_clks[0]);
503
504 pd = devm_kzalloc(dev, sizeof(*pd) + pm_size, GFP_KERNEL);
505 if (!pd)
506 return -ENOMEM;
507
508 pd->np = np;
509 pd->num_core_pm_clks = num_core_pm_clks;
510 memcpy(pd->core_pm_clks, core_pm_clks, pm_size);
511
512 genpd = &pd->genpd;
513 genpd->name = np->name;
Geert Uytterhoeven7aff2662017-10-13 14:24:22 +0200514 genpd->flags = GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP;
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200515 genpd->attach_dev = cpg_mssr_attach_dev;
516 genpd->detach_dev = cpg_mssr_detach_dev;
Geert Uytterhoevend04a75a2016-04-22 14:59:10 +0200517 pm_genpd_init(genpd, &pm_domain_always_on_gov, false);
Geert Uytterhoeven20663902016-03-04 17:03:46 +0100518 cpg_mssr_clk_domain = pd;
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200519
520 of_genpd_add_provider_simple(np, genpd);
521 return 0;
522}
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200523
Geert Uytterhoeven6197aa62017-01-20 11:03:03 +0100524#ifdef CONFIG_RESET_CONTROLLER
525
526#define rcdev_to_priv(x) container_of(x, struct cpg_mssr_priv, rcdev)
527
528static int cpg_mssr_reset(struct reset_controller_dev *rcdev,
529 unsigned long id)
530{
531 struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev);
532 unsigned int reg = id / 32;
533 unsigned int bit = id % 32;
534 u32 bitmask = BIT(bit);
535 unsigned long flags;
536 u32 value;
537
538 dev_dbg(priv->dev, "reset %u%02u\n", reg, bit);
539
540 /* Reset module */
541 spin_lock_irqsave(&priv->rmw_lock, flags);
542 value = readl(priv->base + SRCR(reg));
543 value |= bitmask;
544 writel(value, priv->base + SRCR(reg));
545 spin_unlock_irqrestore(&priv->rmw_lock, flags);
546
547 /* Wait for at least one cycle of the RCLK clock (@ ca. 32 kHz) */
548 udelay(35);
549
550 /* Release module from reset state */
551 writel(bitmask, priv->base + SRSTCLR(reg));
552
553 return 0;
554}
555
556static int cpg_mssr_assert(struct reset_controller_dev *rcdev, unsigned long id)
557{
558 struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev);
559 unsigned int reg = id / 32;
560 unsigned int bit = id % 32;
561 u32 bitmask = BIT(bit);
562 unsigned long flags;
563 u32 value;
564
565 dev_dbg(priv->dev, "assert %u%02u\n", reg, bit);
566
567 spin_lock_irqsave(&priv->rmw_lock, flags);
568 value = readl(priv->base + SRCR(reg));
569 value |= bitmask;
570 writel(value, priv->base + SRCR(reg));
571 spin_unlock_irqrestore(&priv->rmw_lock, flags);
572 return 0;
573}
574
575static int cpg_mssr_deassert(struct reset_controller_dev *rcdev,
576 unsigned long id)
577{
578 struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev);
579 unsigned int reg = id / 32;
580 unsigned int bit = id % 32;
581 u32 bitmask = BIT(bit);
582
583 dev_dbg(priv->dev, "deassert %u%02u\n", reg, bit);
584
585 writel(bitmask, priv->base + SRSTCLR(reg));
586 return 0;
587}
588
589static int cpg_mssr_status(struct reset_controller_dev *rcdev,
590 unsigned long id)
591{
592 struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev);
593 unsigned int reg = id / 32;
594 unsigned int bit = id % 32;
595 u32 bitmask = BIT(bit);
596
597 return !!(readl(priv->base + SRCR(reg)) & bitmask);
598}
599
600static const struct reset_control_ops cpg_mssr_reset_ops = {
601 .reset = cpg_mssr_reset,
602 .assert = cpg_mssr_assert,
603 .deassert = cpg_mssr_deassert,
604 .status = cpg_mssr_status,
605};
606
607static int cpg_mssr_reset_xlate(struct reset_controller_dev *rcdev,
608 const struct of_phandle_args *reset_spec)
609{
610 struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev);
611 unsigned int unpacked = reset_spec->args[0];
612 unsigned int idx = MOD_CLK_PACK(unpacked);
613
614 if (unpacked % 100 > 31 || idx >= rcdev->nr_resets) {
615 dev_err(priv->dev, "Invalid reset index %u\n", unpacked);
616 return -EINVAL;
617 }
618
619 return idx;
620}
621
622static int cpg_mssr_reset_controller_register(struct cpg_mssr_priv *priv)
623{
624 priv->rcdev.ops = &cpg_mssr_reset_ops;
625 priv->rcdev.of_node = priv->dev->of_node;
626 priv->rcdev.of_reset_n_cells = 1;
627 priv->rcdev.of_xlate = cpg_mssr_reset_xlate;
628 priv->rcdev.nr_resets = priv->num_mod_clks;
629 return devm_reset_controller_register(priv->dev, &priv->rcdev);
630}
631
632#else /* !CONFIG_RESET_CONTROLLER */
633static inline int cpg_mssr_reset_controller_register(struct cpg_mssr_priv *priv)
634{
635 return 0;
636}
637#endif /* !CONFIG_RESET_CONTROLLER */
638
639
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200640static const struct of_device_id cpg_mssr_match[] = {
Geert Uytterhoeven80978a42017-04-24 16:54:14 +0200641#ifdef CONFIG_CLK_R8A7743
Sergei Shtylyovc0b2d752016-11-09 00:21:50 +0300642 {
643 .compatible = "renesas,r8a7743-cpg-mssr",
644 .data = &r8a7743_cpg_mssr_info,
645 },
646#endif
Geert Uytterhoeven80978a42017-04-24 16:54:14 +0200647#ifdef CONFIG_CLK_R8A7745
Sergei Shtylyov9127d542016-11-09 00:25:08 +0300648 {
649 .compatible = "renesas,r8a7745-cpg-mssr",
650 .data = &r8a7745_cpg_mssr_info,
651 },
652#endif
Biju Das5bf2fbb2018-03-28 20:26:12 +0100653#ifdef CONFIG_CLK_R8A77470
654 {
655 .compatible = "renesas,r8a77470-cpg-mssr",
656 .data = &r8a77470_cpg_mssr_info,
657 },
658#endif
Geert Uytterhoevend4e59f12017-03-19 18:05:42 +0100659#ifdef CONFIG_CLK_R8A7790
660 {
661 .compatible = "renesas,r8a7790-cpg-mssr",
662 .data = &r8a7790_cpg_mssr_info,
663 },
664#endif
Geert Uytterhoeven6449ab82015-10-16 11:41:19 +0200665#ifdef CONFIG_CLK_R8A7791
666 {
667 .compatible = "renesas,r8a7791-cpg-mssr",
668 .data = &r8a7791_cpg_mssr_info,
669 },
670 /* R-Car M2-N is (almost) identical to R-Car M2-W w.r.t. clocks. */
671 {
672 .compatible = "renesas,r8a7793-cpg-mssr",
673 .data = &r8a7791_cpg_mssr_info,
674 },
675#endif
Geert Uytterhoevenfd3c2f32017-03-19 18:08:59 +0100676#ifdef CONFIG_CLK_R8A7792
677 {
678 .compatible = "renesas,r8a7792-cpg-mssr",
679 .data = &r8a7792_cpg_mssr_info,
680 },
681#endif
Geert Uytterhoeven2d755882017-03-19 18:12:51 +0100682#ifdef CONFIG_CLK_R8A7794
683 {
684 .compatible = "renesas,r8a7794-cpg-mssr",
685 .data = &r8a7794_cpg_mssr_info,
686 },
687#endif
Geert Uytterhoeven80978a42017-04-24 16:54:14 +0200688#ifdef CONFIG_CLK_R8A7795
Geert Uytterhoevenc5dae0d2015-10-16 11:41:19 +0200689 {
690 .compatible = "renesas,r8a7795-cpg-mssr",
691 .data = &r8a7795_cpg_mssr_info,
692 },
693#endif
Geert Uytterhoeven80978a42017-04-24 16:54:14 +0200694#ifdef CONFIG_CLK_R8A7796
Geert Uytterhoevene4e2d7c2016-05-03 11:06:15 +0200695 {
696 .compatible = "renesas,r8a7796-cpg-mssr",
697 .data = &r8a7796_cpg_mssr_info,
698 },
699#endif
Jacopo Mondi7ce36da92018-02-20 16:12:03 +0100700#ifdef CONFIG_CLK_R8A77965
701 {
702 .compatible = "renesas,r8a77965-cpg-mssr",
703 .data = &r8a77965_cpg_mssr_info,
704 },
705#endif
Sergei Shtylyov8d46e282017-09-09 00:34:20 +0300706#ifdef CONFIG_CLK_R8A77970
707 {
708 .compatible = "renesas,r8a77970-cpg-mssr",
709 .data = &r8a77970_cpg_mssr_info,
710 },
711#endif
Magnus Damm472f5f32018-03-20 16:40:16 +0900712#ifdef CONFIG_CLK_R8A77980
Sergei Shtylyovce157832018-02-15 14:58:45 +0300713 {
714 .compatible = "renesas,r8a77980-cpg-mssr",
715 .data = &r8a77980_cpg_mssr_info,
716 },
717#endif
Yoshihiro Shimoda3570a2a2018-04-20 21:27:44 +0900718#ifdef CONFIG_CLK_R8A77990
719 {
720 .compatible = "renesas,r8a77990-cpg-mssr",
721 .data = &r8a77990_cpg_mssr_info,
722 },
723#endif
Geert Uytterhoevend71e8512017-07-12 10:47:36 +0200724#ifdef CONFIG_CLK_R8A77995
725 {
726 .compatible = "renesas,r8a77995-cpg-mssr",
727 .data = &r8a77995_cpg_mssr_info,
728 },
729#endif
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200730 { /* sentinel */ }
731};
732
733static void cpg_mssr_del_clk_provider(void *data)
734{
735 of_clk_del_provider(data);
736}
737
Geert Uytterhoeven56086912017-06-07 13:20:06 +0200738#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM_PSCI_FW)
739static int cpg_mssr_suspend_noirq(struct device *dev)
740{
741 struct cpg_mssr_priv *priv = dev_get_drvdata(dev);
742 unsigned int reg;
743
744 /* This is the best we can do to check for the presence of PSCI */
745 if (!psci_ops.cpu_suspend)
746 return 0;
747
748 /* Save module registers with bits under our control */
749 for (reg = 0; reg < ARRAY_SIZE(priv->smstpcr_saved); reg++) {
750 if (priv->smstpcr_saved[reg].mask)
751 priv->smstpcr_saved[reg].val =
752 readl(priv->base + SMSTPCR(reg));
753 }
754
Geert Uytterhoeven1f4023c2017-06-21 22:24:15 +0200755 /* Save core clocks */
756 raw_notifier_call_chain(&priv->notifiers, PM_EVENT_SUSPEND, NULL);
757
Geert Uytterhoeven56086912017-06-07 13:20:06 +0200758 return 0;
759}
760
761static int cpg_mssr_resume_noirq(struct device *dev)
762{
763 struct cpg_mssr_priv *priv = dev_get_drvdata(dev);
764 unsigned int reg, i;
765 u32 mask, oldval, newval;
766
767 /* This is the best we can do to check for the presence of PSCI */
768 if (!psci_ops.cpu_suspend)
769 return 0;
770
Geert Uytterhoeven1f4023c2017-06-21 22:24:15 +0200771 /* Restore core clocks */
772 raw_notifier_call_chain(&priv->notifiers, PM_EVENT_RESUME, NULL);
773
Geert Uytterhoeven56086912017-06-07 13:20:06 +0200774 /* Restore module clocks */
775 for (reg = 0; reg < ARRAY_SIZE(priv->smstpcr_saved); reg++) {
776 mask = priv->smstpcr_saved[reg].mask;
777 if (!mask)
778 continue;
779
780 oldval = readl(priv->base + SMSTPCR(reg));
781 newval = oldval & ~mask;
782 newval |= priv->smstpcr_saved[reg].val & mask;
783 if (newval == oldval)
784 continue;
785
786 writel(newval, priv->base + SMSTPCR(reg));
787
788 /* Wait until enabled clocks are really enabled */
789 mask &= ~priv->smstpcr_saved[reg].val;
790 if (!mask)
791 continue;
792
793 for (i = 1000; i > 0; --i) {
794 oldval = readl(priv->base + MSTPSR(reg));
795 if (!(oldval & mask))
796 break;
797 cpu_relax();
798 }
799
800 if (!i)
801 dev_warn(dev, "Failed to enable SMSTP %p[0x%x]\n",
802 priv->base + SMSTPCR(reg), oldval & mask);
803 }
804
805 return 0;
806}
807
808static const struct dev_pm_ops cpg_mssr_pm = {
809 SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(cpg_mssr_suspend_noirq,
810 cpg_mssr_resume_noirq)
811};
812#define DEV_PM_OPS &cpg_mssr_pm
813#else
814#define DEV_PM_OPS NULL
815#endif /* CONFIG_PM_SLEEP && CONFIG_ARM_PSCI_FW */
816
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200817static int __init cpg_mssr_probe(struct platform_device *pdev)
818{
819 struct device *dev = &pdev->dev;
820 struct device_node *np = dev->of_node;
821 const struct cpg_mssr_info *info;
822 struct cpg_mssr_priv *priv;
823 unsigned int nclks, i;
824 struct resource *res;
825 struct clk **clks;
826 int error;
827
Geert Uytterhoeven34deaff2017-06-09 14:49:43 +0200828 info = of_device_get_match_data(dev);
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200829 if (info->init) {
830 error = info->init(dev);
831 if (error)
832 return error;
833 }
834
835 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
836 if (!priv)
837 return -ENOMEM;
838
839 priv->dev = dev;
Geert Uytterhoevena4ea6a02017-01-20 10:58:11 +0100840 spin_lock_init(&priv->rmw_lock);
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200841
842 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
843 priv->base = devm_ioremap_resource(dev, res);
844 if (IS_ERR(priv->base))
845 return PTR_ERR(priv->base);
846
847 nclks = info->num_total_core_clks + info->num_hw_mod_clks;
848 clks = devm_kmalloc_array(dev, nclks, sizeof(*clks), GFP_KERNEL);
849 if (!clks)
850 return -ENOMEM;
851
Geert Uytterhoeven56086912017-06-07 13:20:06 +0200852 dev_set_drvdata(dev, priv);
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200853 priv->clks = clks;
854 priv->num_core_clks = info->num_total_core_clks;
855 priv->num_mod_clks = info->num_hw_mod_clks;
856 priv->last_dt_core_clk = info->last_dt_core_clk;
Geert Uytterhoeven1f4023c2017-06-21 22:24:15 +0200857 RAW_INIT_NOTIFIER_HEAD(&priv->notifiers);
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200858
859 for (i = 0; i < nclks; i++)
860 clks[i] = ERR_PTR(-ENOENT);
861
862 for (i = 0; i < info->num_core_clks; i++)
863 cpg_mssr_register_core_clk(&info->core_clks[i], info, priv);
864
865 for (i = 0; i < info->num_mod_clks; i++)
866 cpg_mssr_register_mod_clk(&info->mod_clks[i], info, priv);
867
868 error = of_clk_add_provider(np, cpg_mssr_clk_src_twocell_get, priv);
869 if (error)
870 return error;
871
Sudip Mukherjeec7f23182016-02-23 15:00:03 +0530872 error = devm_add_action_or_reset(dev,
873 cpg_mssr_del_clk_provider,
874 np);
875 if (error)
876 return error;
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200877
878 error = cpg_mssr_add_clk_domain(dev, info->core_pm_clks,
879 info->num_core_pm_clks);
880 if (error)
881 return error;
882
Geert Uytterhoeven6197aa62017-01-20 11:03:03 +0100883 error = cpg_mssr_reset_controller_register(priv);
884 if (error)
885 return error;
886
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200887 return 0;
888}
889
890static struct platform_driver cpg_mssr_driver = {
891 .driver = {
892 .name = "renesas-cpg-mssr",
893 .of_match_table = cpg_mssr_match,
Geert Uytterhoeven56086912017-06-07 13:20:06 +0200894 .pm = DEV_PM_OPS,
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200895 },
896};
897
898static int __init cpg_mssr_init(void)
899{
900 return platform_driver_probe(&cpg_mssr_driver, cpg_mssr_probe);
901}
902
903subsys_initcall(cpg_mssr_init);
904
Geert Uytterhoeven48d03412016-09-29 14:47:58 +0200905void __init cpg_core_nullify_range(struct cpg_core_clk *core_clks,
906 unsigned int num_core_clks,
907 unsigned int first_clk,
908 unsigned int last_clk)
909{
910 unsigned int i;
911
912 for (i = 0; i < num_core_clks; i++)
913 if (core_clks[i].id >= first_clk &&
914 core_clks[i].id <= last_clk)
915 core_clks[i].name = NULL;
916}
917
918void __init mssr_mod_nullify(struct mssr_mod_clk *mod_clks,
919 unsigned int num_mod_clks,
920 const unsigned int *clks, unsigned int n)
921{
922 unsigned int i, j;
923
924 for (i = 0, j = 0; i < num_mod_clks && j < n; i++)
925 if (mod_clks[i].id == clks[j]) {
926 mod_clks[i].name = NULL;
927 j++;
928 }
929}
930
931void __init mssr_mod_reparent(struct mssr_mod_clk *mod_clks,
932 unsigned int num_mod_clks,
933 const struct mssr_mod_reparent *clks,
934 unsigned int n)
935{
936 unsigned int i, j;
937
938 for (i = 0, j = 0; i < num_mod_clks && j < n; i++)
939 if (mod_clks[i].id == clks[j].clk) {
940 mod_clks[i].parent = clks[j].parent;
941 j++;
942 }
943}
944
Geert Uytterhoevenf793d1e2015-10-16 11:41:19 +0200945MODULE_DESCRIPTION("Renesas CPG/MSSR Driver");
946MODULE_LICENSE("GPL v2");