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_R8A774B1 288 { .compatible = "renesas,r8a774b1-sysc", .data = &r8a774b1_sysc_info }, 289 #endif 290 #ifdef CONFIG_SYSC_R8A774C0 291 { .compatible = "renesas,r8a774c0-sysc", .data = &r8a774c0_sysc_info }, 292 #endif 293 #ifdef CONFIG_SYSC_R8A774E1 294 { .compatible = "renesas,r8a774e1-sysc", .data = &r8a774e1_sysc_info }, 295 #endif 296 #ifdef CONFIG_SYSC_R8A7779 297 { .compatible = "renesas,r8a7779-sysc", .data = &r8a7779_sysc_info }, 298 #endif 299 #ifdef CONFIG_SYSC_R8A7790 300 { .compatible = "renesas,r8a7790-sysc", .data = &r8a7790_sysc_info }, 301 #endif 302 #ifdef CONFIG_SYSC_R8A7791 303 { .compatible = "renesas,r8a7791-sysc", .data = &r8a7791_sysc_info }, 304 /* R-Car M2-N is identical to R-Car M2-W w.r.t. power domains. */ 305 { .compatible = "renesas,r8a7793-sysc", .data = &r8a7791_sysc_info }, 306 #endif 307 #ifdef CONFIG_SYSC_R8A7792 308 { .compatible = "renesas,r8a7792-sysc", .data = &r8a7792_sysc_info }, 309 #endif 310 #ifdef CONFIG_SYSC_R8A7794 311 { .compatible = "renesas,r8a7794-sysc", .data = &r8a7794_sysc_info }, 312 #endif 313 #ifdef CONFIG_SYSC_R8A7795 314 { .compatible = "renesas,r8a7795-sysc", .data = &r8a7795_sysc_info }, 315 #endif 316 #ifdef CONFIG_SYSC_R8A77960 317 { .compatible = "renesas,r8a7796-sysc", .data = &r8a77960_sysc_info }, 318 #endif 319 #ifdef CONFIG_SYSC_R8A77961 320 { .compatible = "renesas,r8a77961-sysc", .data = &r8a77961_sysc_info }, 321 #endif 322 #ifdef CONFIG_SYSC_R8A77965 323 { .compatible = "renesas,r8a77965-sysc", .data = &r8a77965_sysc_info }, 324 #endif 325 #ifdef CONFIG_SYSC_R8A77970 326 { .compatible = "renesas,r8a77970-sysc", .data = &r8a77970_sysc_info }, 327 #endif 328 #ifdef CONFIG_SYSC_R8A77980 329 { .compatible = "renesas,r8a77980-sysc", .data = &r8a77980_sysc_info }, 330 #endif 331 #ifdef CONFIG_SYSC_R8A77990 332 { .compatible = "renesas,r8a77990-sysc", .data = &r8a77990_sysc_info }, 333 #endif 334 #ifdef CONFIG_SYSC_R8A77995 335 { .compatible = "renesas,r8a77995-sysc", .data = &r8a77995_sysc_info }, 336 #endif 337 { /* sentinel */ } 338 }; 339 340 struct rcar_pm_domains { 341 struct genpd_onecell_data onecell_data; 342 struct generic_pm_domain *domains[RCAR_PD_ALWAYS_ON + 1]; 343 }; 344 345 static struct genpd_onecell_data *rcar_sysc_onecell_data; 346 static struct device_node *rcar_sysc_onecell_np __initdata = NULL; 347 348 static int __init rcar_sysc_pd_init(void) 349 { 350 const struct rcar_sysc_info *info; 351 const struct of_device_id *match; 352 struct rcar_pm_domains *domains; 353 struct device_node *np; 354 void __iomem *base; 355 unsigned int i; 356 int error; 357 358 np = of_find_matching_node_and_match(NULL, rcar_sysc_matches, &match); 359 if (!np) 360 return -ENODEV; 361 362 info = match->data; 363 364 if (info->init) { 365 error = info->init(); 366 if (error) 367 goto out_put; 368 } 369 370 has_cpg_mstp = of_find_compatible_node(NULL, NULL, 371 "renesas,cpg-mstp-clocks"); 372 373 base = of_iomap(np, 0); 374 if (!base) { 375 pr_warn("%pOF: Cannot map regs\n", np); 376 error = -ENOMEM; 377 goto out_put; 378 } 379 380 rcar_sysc_base = base; 381 382 /* Optional External Request Mask Register */ 383 rcar_sysc_extmask_offs = info->extmask_offs; 384 rcar_sysc_extmask_val = info->extmask_val; 385 386 domains = kzalloc(sizeof(*domains), GFP_KERNEL); 387 if (!domains) { 388 error = -ENOMEM; 389 goto out_put; 390 } 391 392 domains->onecell_data.domains = domains->domains; 393 domains->onecell_data.num_domains = ARRAY_SIZE(domains->domains); 394 rcar_sysc_onecell_data = &domains->onecell_data; 395 396 for (i = 0; i < info->num_areas; i++) { 397 const struct rcar_sysc_area *area = &info->areas[i]; 398 struct rcar_sysc_pd *pd; 399 size_t n; 400 401 n = strlen(area->name) + 1; 402 pd = kzalloc(sizeof(*pd) + n, GFP_KERNEL); 403 if (!pd) { 404 error = -ENOMEM; 405 goto out_put; 406 } 407 408 memcpy(pd->name, area->name, n); 409 pd->genpd.name = pd->name; 410 pd->chan_offs = area->chan_offs; 411 pd->chan_bit = area->chan_bit; 412 pd->isr_bit = area->isr_bit; 413 pd->flags = area->flags; 414 415 error = rcar_sysc_pd_setup(pd); 416 if (error) 417 goto out_put; 418 419 domains->domains[area->isr_bit] = &pd->genpd; 420 421 if (area->parent < 0) 422 continue; 423 424 error = pm_genpd_add_subdomain(domains->domains[area->parent], 425 &pd->genpd); 426 if (error) { 427 pr_warn("Failed to add PM subdomain %s to parent %u\n", 428 area->name, area->parent); 429 goto out_put; 430 } 431 } 432 433 rcar_sysc_onecell_np = np; 434 return 0; 435 436 out_put: 437 of_node_put(np); 438 return error; 439 } 440 early_initcall(rcar_sysc_pd_init); 441 442 static int __init rcar_sysc_pd_init_provider(void) 443 { 444 int error; 445 446 if (!rcar_sysc_onecell_np) 447 return -ENODEV; 448 449 error = of_genpd_add_provider_onecell(rcar_sysc_onecell_np, 450 rcar_sysc_onecell_data); 451 452 of_node_put(rcar_sysc_onecell_np); 453 return error; 454 } 455 postcore_initcall(rcar_sysc_pd_init_provider); 456 457 #ifdef CONFIG_ARCH_R8A7779 458 static int rcar_sysc_power_cpu(unsigned int idx, bool on) 459 { 460 struct generic_pm_domain *genpd; 461 struct rcar_sysc_pd *pd; 462 unsigned int i; 463 464 if (!rcar_sysc_onecell_data) 465 return -ENODEV; 466 467 for (i = 0; i < rcar_sysc_onecell_data->num_domains; i++) { 468 genpd = rcar_sysc_onecell_data->domains[i]; 469 if (!genpd) 470 continue; 471 472 pd = to_rcar_pd(genpd); 473 if (!(pd->flags & PD_CPU) || pd->chan_bit != idx) 474 continue; 475 476 return rcar_sysc_power(pd, on); 477 } 478 479 return -ENOENT; 480 } 481 482 int rcar_sysc_power_down_cpu(unsigned int cpu) 483 { 484 return rcar_sysc_power_cpu(cpu, false); 485 } 486 487 int rcar_sysc_power_up_cpu(unsigned int cpu) 488 { 489 return rcar_sysc_power_cpu(cpu, true); 490 } 491 #endif /* CONFIG_ARCH_R8A7779 */ 492