Lines Matching +full:cpg +full:- +full:mstp +full:- +full:clocks
1 // SPDX-License-Identifier: GPL-2.0
3 * R-Car SYSC Power management support
6 * Copyright (C) 2015-2017 Glider bvba
18 #include <linux/soc/renesas/rcar-sysc.h>
20 #include "rcar-sysc.h"
36 * Use WFI to power off, CPG/APMU to resume ARM cores on R-Car Gen2
37 * Use PSCI on R-Car Gen3
56 #define RCAR_PD_ALWAYS_ON 32 /* Always-on power area */
89 return -EAGAIN; in rcar_sysc_pwr_on_off()
92 iowrite32(BIT(sysc_ch->chan_bit), in rcar_sysc_pwr_on_off()
93 rcar_sysc_base + sysc_ch->chan_offs + reg_offs); in rcar_sysc_pwr_on_off()
100 unsigned int isr_mask = BIT(sysc_ch->isr_bit); in rcar_sysc_power()
101 unsigned int chan_mask = BIT(sysc_ch->chan_bit); in rcar_sysc_power()
135 sysc_ch->chan_offs + PWRER_OFFS); in rcar_sysc_power()
143 ret = -EIO; in rcar_sysc_power()
155 ret = -EIO; in rcar_sysc_power()
165 pr_debug("sysc power %s domain %d: %08x -> %d\n", on ? "on" : "off", in rcar_sysc_power()
166 sysc_ch->isr_bit, ioread32(rcar_sysc_base + SYSCISR), ret); in rcar_sysc_power()
174 st = ioread32(rcar_sysc_base + sysc_ch->chan_offs + PWRSR_OFFS); in rcar_sysc_power_is_off()
175 if (st & BIT(sysc_ch->chan_bit)) in rcar_sysc_power_is_off()
197 pr_debug("%s: %s\n", __func__, genpd->name); in rcar_sysc_pd_power_off()
198 return rcar_sysc_power(&pd->ch, false); in rcar_sysc_pd_power_off()
205 pr_debug("%s: %s\n", __func__, genpd->name); in rcar_sysc_pd_power_on()
206 return rcar_sysc_power(&pd->ch, true); in rcar_sysc_pd_power_on()
213 struct generic_pm_domain *genpd = &pd->genpd; in rcar_sysc_pd_setup()
214 const char *name = pd->genpd.name; in rcar_sysc_pd_setup()
217 if (pd->flags & PD_CPU) { in rcar_sysc_pd_setup()
223 genpd->flags |= GENPD_FLAG_ALWAYS_ON; in rcar_sysc_pd_setup()
224 } else if (pd->flags & PD_SCU) { in rcar_sysc_pd_setup()
226 * This domain contains an SCU and cache-controller, and in rcar_sysc_pd_setup()
231 genpd->flags |= GENPD_FLAG_ALWAYS_ON; in rcar_sysc_pd_setup()
232 } else if (pd->flags & PD_NO_CR) { in rcar_sysc_pd_setup()
236 genpd->flags |= GENPD_FLAG_ALWAYS_ON; in rcar_sysc_pd_setup()
239 if (!(pd->flags & (PD_CPU | PD_SCU))) { in rcar_sysc_pd_setup()
241 genpd->flags |= GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP; in rcar_sysc_pd_setup()
243 genpd->attach_dev = cpg_mstp_attach_dev; in rcar_sysc_pd_setup()
244 genpd->detach_dev = cpg_mstp_detach_dev; in rcar_sysc_pd_setup()
246 genpd->attach_dev = cpg_mssr_attach_dev; in rcar_sysc_pd_setup()
247 genpd->detach_dev = cpg_mssr_detach_dev; in rcar_sysc_pd_setup()
251 genpd->power_off = rcar_sysc_pd_power_off; in rcar_sysc_pd_setup()
252 genpd->power_on = rcar_sysc_pd_power_on; in rcar_sysc_pd_setup()
254 if (pd->flags & (PD_CPU | PD_NO_CR)) { in rcar_sysc_pd_setup()
256 pr_debug("%s: Not touching %s\n", __func__, genpd->name); in rcar_sysc_pd_setup()
260 if (!rcar_sysc_power_is_off(&pd->ch)) { in rcar_sysc_pd_setup()
261 pr_debug("%s: %s is already powered\n", __func__, genpd->name); in rcar_sysc_pd_setup()
265 rcar_sysc_power(&pd->ch, true); in rcar_sysc_pd_setup()
277 { .compatible = "renesas,r8a7742-sysc", .data = &r8a7742_sysc_info },
280 { .compatible = "renesas,r8a7743-sysc", .data = &r8a7743_sysc_info },
282 { .compatible = "renesas,r8a7744-sysc", .data = &r8a7743_sysc_info },
285 { .compatible = "renesas,r8a7745-sysc", .data = &r8a7745_sysc_info },
288 { .compatible = "renesas,r8a77470-sysc", .data = &r8a77470_sysc_info },
291 { .compatible = "renesas,r8a774a1-sysc", .data = &r8a774a1_sysc_info },
294 { .compatible = "renesas,r8a774b1-sysc", .data = &r8a774b1_sysc_info },
297 { .compatible = "renesas,r8a774c0-sysc", .data = &r8a774c0_sysc_info },
300 { .compatible = "renesas,r8a774e1-sysc", .data = &r8a774e1_sysc_info },
303 { .compatible = "renesas,r8a7779-sysc", .data = &r8a7779_sysc_info },
306 { .compatible = "renesas,r8a7790-sysc", .data = &r8a7790_sysc_info },
309 { .compatible = "renesas,r8a7791-sysc", .data = &r8a7791_sysc_info },
310 /* R-Car M2-N is identical to R-Car M2-W w.r.t. power domains. */
311 { .compatible = "renesas,r8a7793-sysc", .data = &r8a7791_sysc_info },
314 { .compatible = "renesas,r8a7792-sysc", .data = &r8a7792_sysc_info },
317 { .compatible = "renesas,r8a7794-sysc", .data = &r8a7794_sysc_info },
320 { .compatible = "renesas,r8a7795-sysc", .data = &r8a7795_sysc_info },
323 { .compatible = "renesas,r8a7796-sysc", .data = &r8a77960_sysc_info },
326 { .compatible = "renesas,r8a77961-sysc", .data = &r8a77961_sysc_info },
329 { .compatible = "renesas,r8a77965-sysc", .data = &r8a77965_sysc_info },
332 { .compatible = "renesas,r8a77970-sysc", .data = &r8a77970_sysc_info },
335 { .compatible = "renesas,r8a77980-sysc", .data = &r8a77980_sysc_info },
338 { .compatible = "renesas,r8a77990-sysc", .data = &r8a77990_sysc_info },
341 { .compatible = "renesas,r8a77995-sysc", .data = &r8a77995_sysc_info },
365 return -ENODEV; in rcar_sysc_pd_init()
367 info = match->data; in rcar_sysc_pd_init()
369 if (info->init) { in rcar_sysc_pd_init()
370 error = info->init(); in rcar_sysc_pd_init()
376 "renesas,cpg-mstp-clocks"); in rcar_sysc_pd_init()
381 error = -ENOMEM; in rcar_sysc_pd_init()
388 rcar_sysc_extmask_offs = info->extmask_offs; in rcar_sysc_pd_init()
389 rcar_sysc_extmask_val = info->extmask_val; in rcar_sysc_pd_init()
393 error = -ENOMEM; in rcar_sysc_pd_init()
397 domains->onecell_data.domains = domains->domains; in rcar_sysc_pd_init()
398 domains->onecell_data.num_domains = ARRAY_SIZE(domains->domains); in rcar_sysc_pd_init()
399 rcar_sysc_onecell_data = &domains->onecell_data; in rcar_sysc_pd_init()
401 for (i = 0; i < info->num_areas; i++) { in rcar_sysc_pd_init()
402 const struct rcar_sysc_area *area = &info->areas[i]; in rcar_sysc_pd_init()
405 if (!area->name) { in rcar_sysc_pd_init()
410 pd = kzalloc(sizeof(*pd) + strlen(area->name) + 1, GFP_KERNEL); in rcar_sysc_pd_init()
412 error = -ENOMEM; in rcar_sysc_pd_init()
416 strcpy(pd->name, area->name); in rcar_sysc_pd_init()
417 pd->genpd.name = pd->name; in rcar_sysc_pd_init()
418 pd->ch.chan_offs = area->chan_offs; in rcar_sysc_pd_init()
419 pd->ch.chan_bit = area->chan_bit; in rcar_sysc_pd_init()
420 pd->ch.isr_bit = area->isr_bit; in rcar_sysc_pd_init()
421 pd->flags = area->flags; in rcar_sysc_pd_init()
427 domains->domains[area->isr_bit] = &pd->genpd; in rcar_sysc_pd_init()
429 if (area->parent < 0) in rcar_sysc_pd_init()
432 error = pm_genpd_add_subdomain(domains->domains[area->parent], in rcar_sysc_pd_init()
433 &pd->genpd); in rcar_sysc_pd_init()
436 area->name, area->parent); in rcar_sysc_pd_init()
441 error = of_genpd_add_provider_onecell(np, &domains->onecell_data); in rcar_sysc_pd_init()
469 return -ENODEV; in rcar_sysc_power_cpu()
471 for (i = 0; i < rcar_sysc_onecell_data->num_domains; i++) { in rcar_sysc_power_cpu()
472 genpd = rcar_sysc_onecell_data->domains[i]; in rcar_sysc_power_cpu()
477 if (!(pd->flags & PD_CPU) || pd->ch.chan_bit != idx) in rcar_sysc_power_cpu()
480 return rcar_sysc_power(&pd->ch, on); in rcar_sysc_power_cpu()
483 return -ENOENT; in rcar_sysc_power_cpu()