hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/soc/renesas/rcar-sysc.c
....@@ -1,12 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0
12 /*
23 * R-Car SYSC Power management support
34 *
45 * Copyright (C) 2014 Magnus Damm
56 * Copyright (C) 2015-2017 Glider bvba
6
- *
7
- * This file is subject to the terms and conditions of the GNU General Public
8
- * License. See the file "COPYING" in the main directory of this archive
9
- * for more details.
107 */
118
129 #include <linux/clk/renesas.h>
....@@ -66,6 +63,7 @@
6663
6764 static void __iomem *rcar_sysc_base;
6865 static DEFINE_SPINLOCK(rcar_sysc_lock); /* SMP CPUs + I/O devices */
66
+static u32 rcar_sysc_extmask_offs, rcar_sysc_extmask_val;
6967
7068 static int rcar_sysc_pwr_on_off(const struct rcar_sysc_ch *sysc_ch, bool on)
7169 {
....@@ -108,6 +106,23 @@
108106
109107 spin_lock_irqsave(&rcar_sysc_lock, flags);
110108
109
+ /*
110
+ * Mask external power requests for CPU or 3DG domains
111
+ */
112
+ if (rcar_sysc_extmask_val) {
113
+ iowrite32(rcar_sysc_extmask_val,
114
+ rcar_sysc_base + rcar_sysc_extmask_offs);
115
+ }
116
+
117
+ /*
118
+ * The interrupt source needs to be enabled, but masked, to prevent the
119
+ * CPU from receiving it.
120
+ */
121
+ iowrite32(ioread32(rcar_sysc_base + SYSCIMR) | isr_mask,
122
+ rcar_sysc_base + SYSCIMR);
123
+ iowrite32(ioread32(rcar_sysc_base + SYSCIER) | isr_mask,
124
+ rcar_sysc_base + SYSCIER);
125
+
111126 iowrite32(isr_mask, rcar_sysc_base + SYSCISCR);
112127
113128 /* Submit power shutoff or resume request until it was accepted */
....@@ -142,21 +157,14 @@
142157 iowrite32(isr_mask, rcar_sysc_base + SYSCISCR);
143158
144159 out:
160
+ if (rcar_sysc_extmask_val)
161
+ iowrite32(0, rcar_sysc_base + rcar_sysc_extmask_offs);
162
+
145163 spin_unlock_irqrestore(&rcar_sysc_lock, flags);
146164
147165 pr_debug("sysc power %s domain %d: %08x -> %d\n", on ? "on" : "off",
148166 sysc_ch->isr_bit, ioread32(rcar_sysc_base + SYSCISR), ret);
149167 return ret;
150
-}
151
-
152
-static int rcar_sysc_power_down(const struct rcar_sysc_ch *sysc_ch)
153
-{
154
- return rcar_sysc_power(sysc_ch, false);
155
-}
156
-
157
-static int rcar_sysc_power_up(const struct rcar_sysc_ch *sysc_ch)
158
-{
159
- return rcar_sysc_power(sysc_ch, true);
160168 }
161169
162170 static bool rcar_sysc_power_is_off(const struct rcar_sysc_ch *sysc_ch)
....@@ -174,7 +182,7 @@
174182 struct generic_pm_domain genpd;
175183 struct rcar_sysc_ch ch;
176184 unsigned int flags;
177
- char name[0];
185
+ char name[];
178186 };
179187
180188 static inline struct rcar_sysc_pd *to_rcar_pd(struct generic_pm_domain *d)
....@@ -187,7 +195,7 @@
187195 struct rcar_sysc_pd *pd = to_rcar_pd(genpd);
188196
189197 pr_debug("%s: %s\n", __func__, genpd->name);
190
- return rcar_sysc_power_down(&pd->ch);
198
+ return rcar_sysc_power(&pd->ch, false);
191199 }
192200
193201 static int rcar_sysc_pd_power_on(struct generic_pm_domain *genpd)
....@@ -195,7 +203,7 @@
195203 struct rcar_sysc_pd *pd = to_rcar_pd(genpd);
196204
197205 pr_debug("%s: %s\n", __func__, genpd->name);
198
- return rcar_sysc_power_up(&pd->ch);
206
+ return rcar_sysc_power(&pd->ch, true);
199207 }
200208
201209 static bool has_cpg_mstp;
....@@ -204,7 +212,6 @@
204212 {
205213 struct generic_pm_domain *genpd = &pd->genpd;
206214 const char *name = pd->genpd.name;
207
- struct dev_power_governor *gov = &simple_qos_governor;
208215 int error;
209216
210217 if (pd->flags & PD_CPU) {
....@@ -255,10 +262,10 @@
255262 goto finalize;
256263 }
257264
258
- rcar_sysc_power_up(&pd->ch);
265
+ rcar_sysc_power(&pd->ch, true);
259266
260267 finalize:
261
- error = pm_genpd_init(genpd, gov, false);
268
+ error = pm_genpd_init(genpd, &simple_qos_governor, false);
262269 if (error)
263270 pr_err("Failed to init PM domain %s: %d\n", name, error);
264271
....@@ -266,14 +273,31 @@
266273 }
267274
268275 static const struct of_device_id rcar_sysc_matches[] __initconst = {
276
+#ifdef CONFIG_SYSC_R8A7742
277
+ { .compatible = "renesas,r8a7742-sysc", .data = &r8a7742_sysc_info },
278
+#endif
269279 #ifdef CONFIG_SYSC_R8A7743
270280 { .compatible = "renesas,r8a7743-sysc", .data = &r8a7743_sysc_info },
281
+ /* RZ/G1N is identical to RZ/G2M w.r.t. power domains. */
282
+ { .compatible = "renesas,r8a7744-sysc", .data = &r8a7743_sysc_info },
271283 #endif
272284 #ifdef CONFIG_SYSC_R8A7745
273285 { .compatible = "renesas,r8a7745-sysc", .data = &r8a7745_sysc_info },
274286 #endif
275287 #ifdef CONFIG_SYSC_R8A77470
276288 { .compatible = "renesas,r8a77470-sysc", .data = &r8a77470_sysc_info },
289
+#endif
290
+#ifdef CONFIG_SYSC_R8A774A1
291
+ { .compatible = "renesas,r8a774a1-sysc", .data = &r8a774a1_sysc_info },
292
+#endif
293
+#ifdef CONFIG_SYSC_R8A774B1
294
+ { .compatible = "renesas,r8a774b1-sysc", .data = &r8a774b1_sysc_info },
295
+#endif
296
+#ifdef CONFIG_SYSC_R8A774C0
297
+ { .compatible = "renesas,r8a774c0-sysc", .data = &r8a774c0_sysc_info },
298
+#endif
299
+#ifdef CONFIG_SYSC_R8A774E1
300
+ { .compatible = "renesas,r8a774e1-sysc", .data = &r8a774e1_sysc_info },
277301 #endif
278302 #ifdef CONFIG_SYSC_R8A7779
279303 { .compatible = "renesas,r8a7779-sysc", .data = &r8a7779_sysc_info },
....@@ -295,8 +319,11 @@
295319 #ifdef CONFIG_SYSC_R8A7795
296320 { .compatible = "renesas,r8a7795-sysc", .data = &r8a7795_sysc_info },
297321 #endif
298
-#ifdef CONFIG_SYSC_R8A7796
299
- { .compatible = "renesas,r8a7796-sysc", .data = &r8a7796_sysc_info },
322
+#ifdef CONFIG_SYSC_R8A77960
323
+ { .compatible = "renesas,r8a7796-sysc", .data = &r8a77960_sysc_info },
324
+#endif
325
+#ifdef CONFIG_SYSC_R8A77961
326
+ { .compatible = "renesas,r8a77961-sysc", .data = &r8a77961_sysc_info },
300327 #endif
301328 #ifdef CONFIG_SYSC_R8A77965
302329 { .compatible = "renesas,r8a77965-sysc", .data = &r8a77965_sysc_info },
....@@ -329,7 +356,6 @@
329356 const struct of_device_id *match;
330357 struct rcar_pm_domains *domains;
331358 struct device_node *np;
332
- u32 syscier, syscimr;
333359 void __iomem *base;
334360 unsigned int i;
335361 int error;
....@@ -343,7 +369,7 @@
343369 if (info->init) {
344370 error = info->init();
345371 if (error)
346
- return error;
372
+ goto out_put;
347373 }
348374
349375 has_cpg_mstp = of_find_compatible_node(NULL, NULL,
....@@ -358,6 +384,10 @@
358384
359385 rcar_sysc_base = base;
360386
387
+ /* Optional External Request Mask Register */
388
+ rcar_sysc_extmask_offs = info->extmask_offs;
389
+ rcar_sysc_extmask_val = info->extmask_val;
390
+
361391 domains = kzalloc(sizeof(*domains), GFP_KERNEL);
362392 if (!domains) {
363393 error = -ENOMEM;
....@@ -368,27 +398,6 @@
368398 domains->onecell_data.num_domains = ARRAY_SIZE(domains->domains);
369399 rcar_sysc_onecell_data = &domains->onecell_data;
370400
371
- for (i = 0, syscier = 0; i < info->num_areas; i++)
372
- syscier |= BIT(info->areas[i].isr_bit);
373
-
374
- /*
375
- * Mask all interrupt sources to prevent the CPU from receiving them.
376
- * Make sure not to clear reserved bits that were set before.
377
- */
378
- syscimr = ioread32(base + SYSCIMR);
379
- syscimr |= syscier;
380
- pr_debug("%pOF: syscimr = 0x%08x\n", np, syscimr);
381
- iowrite32(syscimr, base + SYSCIMR);
382
-
383
- /*
384
- * SYSC needs all interrupt sources enabled to control power.
385
- */
386
- pr_debug("%pOF: syscier = 0x%08x\n", np, syscier);
387
- iowrite32(syscier, base + SYSCIER);
388
-
389
- /*
390
- * First, create all PM domains
391
- */
392401 for (i = 0; i < info->num_areas; i++) {
393402 const struct rcar_sysc_area *area = &info->areas[i];
394403 struct rcar_sysc_pd *pd;
....@@ -416,22 +425,17 @@
416425 goto out_put;
417426
418427 domains->domains[area->isr_bit] = &pd->genpd;
419
- }
420428
421
- /*
422
- * Second, link all PM domains to their parents
423
- */
424
- for (i = 0; i < info->num_areas; i++) {
425
- const struct rcar_sysc_area *area = &info->areas[i];
426
-
427
- if (!area->name || area->parent < 0)
429
+ if (area->parent < 0)
428430 continue;
429431
430432 error = pm_genpd_add_subdomain(domains->domains[area->parent],
431
- domains->domains[area->isr_bit]);
432
- if (error)
433
+ &pd->genpd);
434
+ if (error) {
433435 pr_warn("Failed to add PM subdomain %s to parent %u\n",
434436 area->name, area->parent);
437
+ goto out_put;
438
+ }
435439 }
436440
437441 error = of_genpd_add_provider_onecell(np, &domains->onecell_data);
....@@ -473,8 +477,7 @@
473477 if (!(pd->flags & PD_CPU) || pd->ch.chan_bit != idx)
474478 continue;
475479
476
- return on ? rcar_sysc_power_up(&pd->ch)
477
- : rcar_sysc_power_down(&pd->ch);
480
+ return rcar_sysc_power(&pd->ch, on);
478481 }
479482
480483 return -ENOENT;