Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.4-rc3 467 lines 12 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * R-Car SYSC Power management support 4 * 5 * Copyright (C) 2014 Magnus Damm 6 * Copyright (C) 2015-2017 Glider bvba 7 */ 8 9#include <linux/clk/renesas.h> 10#include <linux/delay.h> 11#include <linux/err.h> 12#include <linux/mm.h> 13#include <linux/of_address.h> 14#include <linux/pm_domain.h> 15#include <linux/slab.h> 16#include <linux/spinlock.h> 17#include <linux/io.h> 18#include <linux/soc/renesas/rcar-sysc.h> 19 20#include "rcar-sysc.h" 21 22/* SYSC Common */ 23#define SYSCSR 0x00 /* SYSC Status Register */ 24#define SYSCISR 0x04 /* Interrupt Status Register */ 25#define SYSCISCR 0x08 /* Interrupt Status Clear Register */ 26#define SYSCIER 0x0c /* Interrupt Enable Register */ 27#define SYSCIMR 0x10 /* Interrupt Mask Register */ 28 29/* SYSC Status Register */ 30#define SYSCSR_PONENB 1 /* Ready for power resume requests */ 31#define SYSCSR_POFFENB 0 /* Ready for power shutoff requests */ 32 33/* 34 * Power Control Register Offsets inside the register block for each domain 35 * Note: The "CR" registers for ARM cores exist on H1 only 36 * Use WFI to power off, CPG/APMU to resume ARM cores on R-Car Gen2 37 * Use PSCI on R-Car Gen3 38 */ 39#define PWRSR_OFFS 0x00 /* Power Status Register */ 40#define PWROFFCR_OFFS 0x04 /* Power Shutoff Control Register */ 41#define PWROFFSR_OFFS 0x08 /* Power Shutoff Status Register */ 42#define PWRONCR_OFFS 0x0c /* Power Resume Control Register */ 43#define PWRONSR_OFFS 0x10 /* Power Resume Status Register */ 44#define PWRER_OFFS 0x14 /* Power Shutoff/Resume Error */ 45 46 47#define SYSCSR_RETRIES 100 48#define SYSCSR_DELAY_US 1 49 50#define PWRER_RETRIES 100 51#define PWRER_DELAY_US 1 52 53#define SYSCISR_RETRIES 1000 54#define SYSCISR_DELAY_US 1 55 56#define RCAR_PD_ALWAYS_ON 32 /* Always-on power area */ 57 58struct rcar_sysc_ch { 59 u16 chan_offs; 60 u8 chan_bit; 61 u8 isr_bit; 62}; 63 64static void __iomem *rcar_sysc_base; 65static DEFINE_SPINLOCK(rcar_sysc_lock); /* SMP CPUs + I/O devices */ 66 67static int rcar_sysc_pwr_on_off(const struct rcar_sysc_ch *sysc_ch, bool on) 68{ 69 unsigned int sr_bit, reg_offs; 70 int k; 71 72 if (on) { 73 sr_bit = SYSCSR_PONENB; 74 reg_offs = PWRONCR_OFFS; 75 } else { 76 sr_bit = SYSCSR_POFFENB; 77 reg_offs = PWROFFCR_OFFS; 78 } 79 80 /* Wait until SYSC is ready to accept a power request */ 81 for (k = 0; k < SYSCSR_RETRIES; k++) { 82 if (ioread32(rcar_sysc_base + SYSCSR) & BIT(sr_bit)) 83 break; 84 udelay(SYSCSR_DELAY_US); 85 } 86 87 if (k == SYSCSR_RETRIES) 88 return -EAGAIN; 89 90 /* Submit power shutoff or power resume request */ 91 iowrite32(BIT(sysc_ch->chan_bit), 92 rcar_sysc_base + sysc_ch->chan_offs + reg_offs); 93 94 return 0; 95} 96 97static int rcar_sysc_power(const struct rcar_sysc_ch *sysc_ch, bool on) 98{ 99 unsigned int isr_mask = BIT(sysc_ch->isr_bit); 100 unsigned int chan_mask = BIT(sysc_ch->chan_bit); 101 unsigned int status; 102 unsigned long flags; 103 int ret = 0; 104 int k; 105 106 spin_lock_irqsave(&rcar_sysc_lock, flags); 107 108 /* 109 * The interrupt source needs to be enabled, but masked, to prevent the 110 * CPU from receiving it. 111 */ 112 iowrite32(ioread32(rcar_sysc_base + SYSCIMR) | isr_mask, 113 rcar_sysc_base + SYSCIMR); 114 iowrite32(ioread32(rcar_sysc_base + SYSCIER) | isr_mask, 115 rcar_sysc_base + SYSCIER); 116 117 iowrite32(isr_mask, rcar_sysc_base + SYSCISCR); 118 119 /* Submit power shutoff or resume request until it was accepted */ 120 for (k = 0; k < PWRER_RETRIES; k++) { 121 ret = rcar_sysc_pwr_on_off(sysc_ch, on); 122 if (ret) 123 goto out; 124 125 status = ioread32(rcar_sysc_base + 126 sysc_ch->chan_offs + PWRER_OFFS); 127 if (!(status & chan_mask)) 128 break; 129 130 udelay(PWRER_DELAY_US); 131 } 132 133 if (k == PWRER_RETRIES) { 134 ret = -EIO; 135 goto out; 136 } 137 138 /* Wait until the power shutoff or resume request has completed * */ 139 for (k = 0; k < SYSCISR_RETRIES; k++) { 140 if (ioread32(rcar_sysc_base + SYSCISR) & isr_mask) 141 break; 142 udelay(SYSCISR_DELAY_US); 143 } 144 145 if (k == SYSCISR_RETRIES) 146 ret = -EIO; 147 148 iowrite32(isr_mask, rcar_sysc_base + SYSCISCR); 149 150 out: 151 spin_unlock_irqrestore(&rcar_sysc_lock, flags); 152 153 pr_debug("sysc power %s domain %d: %08x -> %d\n", on ? "on" : "off", 154 sysc_ch->isr_bit, ioread32(rcar_sysc_base + SYSCISR), ret); 155 return ret; 156} 157 158static bool rcar_sysc_power_is_off(const struct rcar_sysc_ch *sysc_ch) 159{ 160 unsigned int st; 161 162 st = ioread32(rcar_sysc_base + sysc_ch->chan_offs + PWRSR_OFFS); 163 if (st & BIT(sysc_ch->chan_bit)) 164 return true; 165 166 return false; 167} 168 169struct rcar_sysc_pd { 170 struct generic_pm_domain genpd; 171 struct rcar_sysc_ch ch; 172 unsigned int flags; 173 char name[]; 174}; 175 176static inline struct rcar_sysc_pd *to_rcar_pd(struct generic_pm_domain *d) 177{ 178 return container_of(d, struct rcar_sysc_pd, genpd); 179} 180 181static int rcar_sysc_pd_power_off(struct generic_pm_domain *genpd) 182{ 183 struct rcar_sysc_pd *pd = to_rcar_pd(genpd); 184 185 pr_debug("%s: %s\n", __func__, genpd->name); 186 return rcar_sysc_power(&pd->ch, false); 187} 188 189static int rcar_sysc_pd_power_on(struct generic_pm_domain *genpd) 190{ 191 struct rcar_sysc_pd *pd = to_rcar_pd(genpd); 192 193 pr_debug("%s: %s\n", __func__, genpd->name); 194 return rcar_sysc_power(&pd->ch, true); 195} 196 197static bool has_cpg_mstp; 198 199static int __init rcar_sysc_pd_setup(struct rcar_sysc_pd *pd) 200{ 201 struct generic_pm_domain *genpd = &pd->genpd; 202 const char *name = pd->genpd.name; 203 int error; 204 205 if (pd->flags & PD_CPU) { 206 /* 207 * This domain contains a CPU core and therefore it should 208 * only be turned off if the CPU is not in use. 209 */ 210 pr_debug("PM domain %s contains %s\n", name, "CPU"); 211 genpd->flags |= GENPD_FLAG_ALWAYS_ON; 212 } else if (pd->flags & PD_SCU) { 213 /* 214 * This domain contains an SCU and cache-controller, and 215 * therefore it should only be turned off if the CPU cores are 216 * not in use. 217 */ 218 pr_debug("PM domain %s contains %s\n", name, "SCU"); 219 genpd->flags |= GENPD_FLAG_ALWAYS_ON; 220 } else if (pd->flags & PD_NO_CR) { 221 /* 222 * This domain cannot be turned off. 223 */ 224 genpd->flags |= GENPD_FLAG_ALWAYS_ON; 225 } 226 227 if (!(pd->flags & (PD_CPU | PD_SCU))) { 228 /* Enable Clock Domain for I/O devices */ 229 genpd->flags |= GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP; 230 if (has_cpg_mstp) { 231 genpd->attach_dev = cpg_mstp_attach_dev; 232 genpd->detach_dev = cpg_mstp_detach_dev; 233 } else { 234 genpd->attach_dev = cpg_mssr_attach_dev; 235 genpd->detach_dev = cpg_mssr_detach_dev; 236 } 237 } 238 239 genpd->power_off = rcar_sysc_pd_power_off; 240 genpd->power_on = rcar_sysc_pd_power_on; 241 242 if (pd->flags & (PD_CPU | PD_NO_CR)) { 243 /* Skip CPUs (handled by SMP code) and areas without control */ 244 pr_debug("%s: Not touching %s\n", __func__, genpd->name); 245 goto finalize; 246 } 247 248 if (!rcar_sysc_power_is_off(&pd->ch)) { 249 pr_debug("%s: %s is already powered\n", __func__, genpd->name); 250 goto finalize; 251 } 252 253 rcar_sysc_power(&pd->ch, true); 254 255finalize: 256 error = pm_genpd_init(genpd, &simple_qos_governor, false); 257 if (error) 258 pr_err("Failed to init PM domain %s: %d\n", name, error); 259 260 return error; 261} 262 263static const struct of_device_id rcar_sysc_matches[] __initconst = { 264#ifdef CONFIG_SYSC_R8A7743 265 { .compatible = "renesas,r8a7743-sysc", .data = &r8a7743_sysc_info }, 266 /* RZ/G1N is identical to RZ/G2M w.r.t. power domains. */ 267 { .compatible = "renesas,r8a7744-sysc", .data = &r8a7743_sysc_info }, 268#endif 269#ifdef CONFIG_SYSC_R8A7745 270 { .compatible = "renesas,r8a7745-sysc", .data = &r8a7745_sysc_info }, 271#endif 272#ifdef CONFIG_SYSC_R8A77470 273 { .compatible = "renesas,r8a77470-sysc", .data = &r8a77470_sysc_info }, 274#endif 275#ifdef CONFIG_SYSC_R8A774A1 276 { .compatible = "renesas,r8a774a1-sysc", .data = &r8a774a1_sysc_info }, 277#endif 278#ifdef CONFIG_SYSC_R8A774C0 279 { .compatible = "renesas,r8a774c0-sysc", .data = &r8a774c0_sysc_info }, 280#endif 281#ifdef CONFIG_SYSC_R8A7779 282 { .compatible = "renesas,r8a7779-sysc", .data = &r8a7779_sysc_info }, 283#endif 284#ifdef CONFIG_SYSC_R8A7790 285 { .compatible = "renesas,r8a7790-sysc", .data = &r8a7790_sysc_info }, 286#endif 287#ifdef CONFIG_SYSC_R8A7791 288 { .compatible = "renesas,r8a7791-sysc", .data = &r8a7791_sysc_info }, 289 /* R-Car M2-N is identical to R-Car M2-W w.r.t. power domains. */ 290 { .compatible = "renesas,r8a7793-sysc", .data = &r8a7791_sysc_info }, 291#endif 292#ifdef CONFIG_SYSC_R8A7792 293 { .compatible = "renesas,r8a7792-sysc", .data = &r8a7792_sysc_info }, 294#endif 295#ifdef CONFIG_SYSC_R8A7794 296 { .compatible = "renesas,r8a7794-sysc", .data = &r8a7794_sysc_info }, 297#endif 298#ifdef CONFIG_SYSC_R8A7795 299 { .compatible = "renesas,r8a7795-sysc", .data = &r8a7795_sysc_info }, 300#endif 301#ifdef CONFIG_SYSC_R8A7796 302 { .compatible = "renesas,r8a7796-sysc", .data = &r8a7796_sysc_info }, 303#endif 304#ifdef CONFIG_SYSC_R8A77965 305 { .compatible = "renesas,r8a77965-sysc", .data = &r8a77965_sysc_info }, 306#endif 307#ifdef CONFIG_SYSC_R8A77970 308 { .compatible = "renesas,r8a77970-sysc", .data = &r8a77970_sysc_info }, 309#endif 310#ifdef CONFIG_SYSC_R8A77980 311 { .compatible = "renesas,r8a77980-sysc", .data = &r8a77980_sysc_info }, 312#endif 313#ifdef CONFIG_SYSC_R8A77990 314 { .compatible = "renesas,r8a77990-sysc", .data = &r8a77990_sysc_info }, 315#endif 316#ifdef CONFIG_SYSC_R8A77995 317 { .compatible = "renesas,r8a77995-sysc", .data = &r8a77995_sysc_info }, 318#endif 319 { /* sentinel */ } 320}; 321 322struct rcar_pm_domains { 323 struct genpd_onecell_data onecell_data; 324 struct generic_pm_domain *domains[RCAR_PD_ALWAYS_ON + 1]; 325}; 326 327static struct genpd_onecell_data *rcar_sysc_onecell_data; 328 329static int __init rcar_sysc_pd_init(void) 330{ 331 const struct rcar_sysc_info *info; 332 const struct of_device_id *match; 333 struct rcar_pm_domains *domains; 334 struct device_node *np; 335 void __iomem *base; 336 unsigned int i; 337 int error; 338 339 np = of_find_matching_node_and_match(NULL, rcar_sysc_matches, &match); 340 if (!np) 341 return -ENODEV; 342 343 info = match->data; 344 345 if (info->init) { 346 error = info->init(); 347 if (error) 348 goto out_put; 349 } 350 351 has_cpg_mstp = of_find_compatible_node(NULL, NULL, 352 "renesas,cpg-mstp-clocks"); 353 354 base = of_iomap(np, 0); 355 if (!base) { 356 pr_warn("%pOF: Cannot map regs\n", np); 357 error = -ENOMEM; 358 goto out_put; 359 } 360 361 rcar_sysc_base = base; 362 363 domains = kzalloc(sizeof(*domains), GFP_KERNEL); 364 if (!domains) { 365 error = -ENOMEM; 366 goto out_put; 367 } 368 369 domains->onecell_data.domains = domains->domains; 370 domains->onecell_data.num_domains = ARRAY_SIZE(domains->domains); 371 rcar_sysc_onecell_data = &domains->onecell_data; 372 373 for (i = 0; i < info->num_areas; i++) { 374 const struct rcar_sysc_area *area = &info->areas[i]; 375 struct rcar_sysc_pd *pd; 376 377 if (!area->name) { 378 /* Skip NULLified area */ 379 continue; 380 } 381 382 pd = kzalloc(sizeof(*pd) + strlen(area->name) + 1, GFP_KERNEL); 383 if (!pd) { 384 error = -ENOMEM; 385 goto out_put; 386 } 387 388 strcpy(pd->name, area->name); 389 pd->genpd.name = pd->name; 390 pd->ch.chan_offs = area->chan_offs; 391 pd->ch.chan_bit = area->chan_bit; 392 pd->ch.isr_bit = area->isr_bit; 393 pd->flags = area->flags; 394 395 error = rcar_sysc_pd_setup(pd); 396 if (error) 397 goto out_put; 398 399 domains->domains[area->isr_bit] = &pd->genpd; 400 401 if (area->parent < 0) 402 continue; 403 404 error = pm_genpd_add_subdomain(domains->domains[area->parent], 405 &pd->genpd); 406 if (error) { 407 pr_warn("Failed to add PM subdomain %s to parent %u\n", 408 area->name, area->parent); 409 goto out_put; 410 } 411 } 412 413 error = of_genpd_add_provider_onecell(np, &domains->onecell_data); 414 415out_put: 416 of_node_put(np); 417 return error; 418} 419early_initcall(rcar_sysc_pd_init); 420 421void __init rcar_sysc_nullify(struct rcar_sysc_area *areas, 422 unsigned int num_areas, u8 id) 423{ 424 unsigned int i; 425 426 for (i = 0; i < num_areas; i++) 427 if (areas[i].isr_bit == id) { 428 areas[i].name = NULL; 429 return; 430 } 431} 432 433#ifdef CONFIG_ARCH_R8A7779 434static int rcar_sysc_power_cpu(unsigned int idx, bool on) 435{ 436 struct generic_pm_domain *genpd; 437 struct rcar_sysc_pd *pd; 438 unsigned int i; 439 440 if (!rcar_sysc_onecell_data) 441 return -ENODEV; 442 443 for (i = 0; i < rcar_sysc_onecell_data->num_domains; i++) { 444 genpd = rcar_sysc_onecell_data->domains[i]; 445 if (!genpd) 446 continue; 447 448 pd = to_rcar_pd(genpd); 449 if (!(pd->flags & PD_CPU) || pd->ch.chan_bit != idx) 450 continue; 451 452 return rcar_sysc_power(&pd->ch, on); 453 } 454 455 return -ENOENT; 456} 457 458int rcar_sysc_power_down_cpu(unsigned int cpu) 459{ 460 return rcar_sysc_power_cpu(cpu, false); 461} 462 463int rcar_sysc_power_up_cpu(unsigned int cpu) 464{ 465 return rcar_sysc_power_cpu(cpu, true); 466} 467#endif /* CONFIG_ARCH_R8A7779 */