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