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->power_off = rcar_sysc_pd_power_off; 245 genpd->power_on = rcar_sysc_pd_power_on; 246 247 if (pd->flags & (PD_CPU | PD_NO_CR)) { 248 /* Skip CPUs (handled by SMP code) and areas without control */ 249 pr_debug("%s: Not touching %s\n", __func__, genpd->name); 250 goto finalize; 251 } 252 253 if (!rcar_sysc_power_is_off(pd)) { 254 pr_debug("%s: %s is already powered\n", __func__, genpd->name); 255 goto finalize; 256 } 257 258 rcar_sysc_power(pd, true); 259 260 finalize: 261 error = pm_genpd_init(genpd, &simple_qos_governor, false); 262 if (error) 263 pr_err("Failed to init PM domain %s: %d\n", name, error); 264 265 return error; 266 } 267 268 static const struct of_device_id rcar_sysc_matches[] __initconst = { 269 #ifdef CONFIG_SYSC_R8A7742 270 { .compatible = "renesas,r8a7742-sysc", .data = &r8a7742_sysc_info }, 271 #endif 272 #ifdef CONFIG_SYSC_R8A7743 273 { .compatible = "renesas,r8a7743-sysc", .data = &r8a7743_sysc_info }, 274 /* RZ/G1N is identical to RZ/G2M w.r.t. power domains. */ 275 { .compatible = "renesas,r8a7744-sysc", .data = &r8a7743_sysc_info }, 276 #endif 277 #ifdef CONFIG_SYSC_R8A7745 278 { .compatible = "renesas,r8a7745-sysc", .data = &r8a7745_sysc_info }, 279 #endif 280 #ifdef CONFIG_SYSC_R8A77470 281 { .compatible = "renesas,r8a77470-sysc", .data = &r8a77470_sysc_info }, 282 #endif 283 #ifdef CONFIG_SYSC_R8A774A1 284 { .compatible = "renesas,r8a774a1-sysc", .data = &r8a774a1_sysc_info }, 285 #endif 286 #ifdef CONFIG_SYSC_R8A774B1 287 { .compatible = "renesas,r8a774b1-sysc", .data = &r8a774b1_sysc_info }, 288 #endif 289 #ifdef CONFIG_SYSC_R8A774C0 290 { .compatible = "renesas,r8a774c0-sysc", .data = &r8a774c0_sysc_info }, 291 #endif 292 #ifdef CONFIG_SYSC_R8A774E1 293 { .compatible = "renesas,r8a774e1-sysc", .data = &r8a774e1_sysc_info }, 294 #endif 295 #ifdef CONFIG_SYSC_R8A7779 296 { .compatible = "renesas,r8a7779-sysc", .data = &r8a7779_sysc_info }, 297 #endif 298 #ifdef CONFIG_SYSC_R8A7790 299 { .compatible = "renesas,r8a7790-sysc", .data = &r8a7790_sysc_info }, 300 #endif 301 #ifdef CONFIG_SYSC_R8A7791 302 { .compatible = "renesas,r8a7791-sysc", .data = &r8a7791_sysc_info }, 303 /* R-Car M2-N is identical to R-Car M2-W w.r.t. power domains. */ 304 { .compatible = "renesas,r8a7793-sysc", .data = &r8a7791_sysc_info }, 305 #endif 306 #ifdef CONFIG_SYSC_R8A7792 307 { .compatible = "renesas,r8a7792-sysc", .data = &r8a7792_sysc_info }, 308 #endif 309 #ifdef CONFIG_SYSC_R8A7794 310 { .compatible = "renesas,r8a7794-sysc", .data = &r8a7794_sysc_info }, 311 #endif 312 #ifdef CONFIG_SYSC_R8A7795 313 { .compatible = "renesas,r8a7795-sysc", .data = &r8a7795_sysc_info }, 314 #endif 315 #ifdef CONFIG_SYSC_R8A77960 316 { .compatible = "renesas,r8a7796-sysc", .data = &r8a77960_sysc_info }, 317 #endif 318 #ifdef CONFIG_SYSC_R8A77961 319 { .compatible = "renesas,r8a77961-sysc", .data = &r8a77961_sysc_info }, 320 #endif 321 #ifdef CONFIG_SYSC_R8A77965 322 { .compatible = "renesas,r8a77965-sysc", .data = &r8a77965_sysc_info }, 323 #endif 324 #ifdef CONFIG_SYSC_R8A77970 325 { .compatible = "renesas,r8a77970-sysc", .data = &r8a77970_sysc_info }, 326 #endif 327 #ifdef CONFIG_SYSC_R8A77980 328 { .compatible = "renesas,r8a77980-sysc", .data = &r8a77980_sysc_info }, 329 #endif 330 #ifdef CONFIG_SYSC_R8A77990 331 { .compatible = "renesas,r8a77990-sysc", .data = &r8a77990_sysc_info }, 332 #endif 333 #ifdef CONFIG_SYSC_R8A77995 334 { .compatible = "renesas,r8a77995-sysc", .data = &r8a77995_sysc_info }, 335 #endif 336 { /* sentinel */ } 337 }; 338 339 struct rcar_pm_domains { 340 struct genpd_onecell_data onecell_data; 341 struct generic_pm_domain *domains[RCAR_PD_ALWAYS_ON + 1]; 342 }; 343 344 static struct genpd_onecell_data *rcar_sysc_onecell_data; 345 346 static int __init rcar_sysc_pd_init(void) 347 { 348 const struct rcar_sysc_info *info; 349 const struct of_device_id *match; 350 struct rcar_pm_domains *domains; 351 struct device_node *np; 352 void __iomem *base; 353 unsigned int i; 354 int error; 355 356 np = of_find_matching_node_and_match(NULL, rcar_sysc_matches, &match); 357 if (!np) 358 return -ENODEV; 359 360 info = match->data; 361 362 if (info->init) { 363 error = info->init(); 364 if (error) 365 goto out_put; 366 } 367 368 has_cpg_mstp = of_find_compatible_node(NULL, NULL, 369 "renesas,cpg-mstp-clocks"); 370 371 base = of_iomap(np, 0); 372 if (!base) { 373 pr_warn("%pOF: Cannot map regs\n", np); 374 error = -ENOMEM; 375 goto out_put; 376 } 377 378 rcar_sysc_base = base; 379 380 /* Optional External Request Mask Register */ 381 rcar_sysc_extmask_offs = info->extmask_offs; 382 rcar_sysc_extmask_val = info->extmask_val; 383 384 domains = kzalloc(sizeof(*domains), GFP_KERNEL); 385 if (!domains) { 386 error = -ENOMEM; 387 goto out_put; 388 } 389 390 domains->onecell_data.domains = domains->domains; 391 domains->onecell_data.num_domains = ARRAY_SIZE(domains->domains); 392 rcar_sysc_onecell_data = &domains->onecell_data; 393 394 for (i = 0; i < info->num_areas; i++) { 395 const struct rcar_sysc_area *area = &info->areas[i]; 396 struct rcar_sysc_pd *pd; 397 size_t n; 398 399 if (!area->name) { 400 /* Skip NULLified area */ 401 continue; 402 } 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 error = of_genpd_add_provider_onecell(np, &domains->onecell_data); 437 if (!error) 438 fwnode_dev_initialized(of_fwnode_handle(np), true); 439 440 out_put: 441 of_node_put(np); 442 return error; 443 } 444 early_initcall(rcar_sysc_pd_init); 445 446 #ifdef CONFIG_ARCH_R8A7779 447 static int rcar_sysc_power_cpu(unsigned int idx, bool on) 448 { 449 struct generic_pm_domain *genpd; 450 struct rcar_sysc_pd *pd; 451 unsigned int i; 452 453 if (!rcar_sysc_onecell_data) 454 return -ENODEV; 455 456 for (i = 0; i < rcar_sysc_onecell_data->num_domains; i++) { 457 genpd = rcar_sysc_onecell_data->domains[i]; 458 if (!genpd) 459 continue; 460 461 pd = to_rcar_pd(genpd); 462 if (!(pd->flags & PD_CPU) || pd->chan_bit != idx) 463 continue; 464 465 return rcar_sysc_power(pd, on); 466 } 467 468 return -ENOENT; 469 } 470 471 int rcar_sysc_power_down_cpu(unsigned int cpu) 472 { 473 return rcar_sysc_power_cpu(cpu, false); 474 } 475 476 int rcar_sysc_power_up_cpu(unsigned int cpu) 477 { 478 return rcar_sysc_power_cpu(cpu, true); 479 } 480 #endif /* CONFIG_ARCH_R8A7779 */ 481