1/* 2 * rmobile power management support 3 * 4 * Copyright (C) 2012 Renesas Solutions Corp. 5 * Copyright (C) 2012 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 6 * Copyright (C) 2014 Glider bvba 7 * 8 * based on pm-sh7372.c 9 * Copyright (C) 2011 Magnus Damm 10 * 11 * This file is subject to the terms and conditions of the GNU General Public 12 * License. See the file "COPYING" in the main directory of this archive 13 * for more details. 14 */ 15#include <linux/clk/shmobile.h> 16#include <linux/console.h> 17#include <linux/delay.h> 18#include <linux/of.h> 19#include <linux/of_address.h> 20#include <linux/of_platform.h> 21#include <linux/platform_device.h> 22#include <linux/pm.h> 23#include <linux/pm_clock.h> 24#include <linux/slab.h> 25 26#include <asm/io.h> 27 28#include "pm-rmobile.h" 29 30/* SYSC */ 31#define SPDCR 0x08 /* SYS Power Down Control Register */ 32#define SWUCR 0x14 /* SYS Wakeup Control Register */ 33#define PSTR 0x80 /* Power Status Register */ 34 35#define PSTR_RETRIES 100 36#define PSTR_DELAY_US 10 37 38static inline 39struct rmobile_pm_domain *to_rmobile_pd(struct generic_pm_domain *d) 40{ 41 return container_of(d, struct rmobile_pm_domain, genpd); 42} 43 44static int rmobile_pd_power_down(struct generic_pm_domain *genpd) 45{ 46 struct rmobile_pm_domain *rmobile_pd = to_rmobile_pd(genpd); 47 unsigned int mask; 48 49 if (rmobile_pd->bit_shift == ~0) 50 return -EBUSY; 51 52 mask = BIT(rmobile_pd->bit_shift); 53 if (rmobile_pd->suspend) { 54 int ret = rmobile_pd->suspend(); 55 56 if (ret) 57 return ret; 58 } 59 60 if (__raw_readl(rmobile_pd->base + PSTR) & mask) { 61 unsigned int retry_count; 62 __raw_writel(mask, rmobile_pd->base + SPDCR); 63 64 for (retry_count = PSTR_RETRIES; retry_count; retry_count--) { 65 if (!(__raw_readl(rmobile_pd->base + SPDCR) & mask)) 66 break; 67 cpu_relax(); 68 } 69 } 70 71 if (!rmobile_pd->no_debug) 72 pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n", 73 genpd->name, mask, 74 __raw_readl(rmobile_pd->base + PSTR)); 75 76 return 0; 77} 78 79static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd, 80 bool do_resume) 81{ 82 unsigned int mask; 83 unsigned int retry_count; 84 int ret = 0; 85 86 if (rmobile_pd->bit_shift == ~0) 87 return 0; 88 89 mask = BIT(rmobile_pd->bit_shift); 90 if (__raw_readl(rmobile_pd->base + PSTR) & mask) 91 goto out; 92 93 __raw_writel(mask, rmobile_pd->base + SWUCR); 94 95 for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) { 96 if (!(__raw_readl(rmobile_pd->base + SWUCR) & mask)) 97 break; 98 if (retry_count > PSTR_RETRIES) 99 udelay(PSTR_DELAY_US); 100 else 101 cpu_relax(); 102 } 103 if (!retry_count) 104 ret = -EIO; 105 106 if (!rmobile_pd->no_debug) 107 pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n", 108 rmobile_pd->genpd.name, mask, 109 __raw_readl(rmobile_pd->base + PSTR)); 110 111out: 112 if (ret == 0 && rmobile_pd->resume && do_resume) 113 rmobile_pd->resume(); 114 115 return ret; 116} 117 118static int rmobile_pd_power_up(struct generic_pm_domain *genpd) 119{ 120 return __rmobile_pd_power_up(to_rmobile_pd(genpd), true); 121} 122 123static bool rmobile_pd_active_wakeup(struct device *dev) 124{ 125 return true; 126} 127 128static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd) 129{ 130 struct generic_pm_domain *genpd = &rmobile_pd->genpd; 131 struct dev_power_governor *gov = rmobile_pd->gov; 132 133 genpd->flags = GENPD_FLAG_PM_CLK; 134 pm_genpd_init(genpd, gov ? : &simple_qos_governor, false); 135 genpd->dev_ops.active_wakeup = rmobile_pd_active_wakeup; 136 genpd->power_off = rmobile_pd_power_down; 137 genpd->power_on = rmobile_pd_power_up; 138 genpd->attach_dev = cpg_mstp_attach_dev; 139 genpd->detach_dev = cpg_mstp_detach_dev; 140 __rmobile_pd_power_up(rmobile_pd, false); 141} 142 143static int rmobile_pd_suspend_busy(void) 144{ 145 /* 146 * This domain should not be turned off. 147 */ 148 return -EBUSY; 149} 150 151static int rmobile_pd_suspend_console(void) 152{ 153 /* 154 * Serial consoles make use of SCIF hardware located in this domain, 155 * hence keep the power domain on if "no_console_suspend" is set. 156 */ 157 return console_suspend_enabled ? 0 : -EBUSY; 158} 159 160enum pd_types { 161 PD_NORMAL, 162 PD_CPU, 163 PD_CONSOLE, 164 PD_DEBUG, 165 PD_MEMCTL, 166}; 167 168#define MAX_NUM_SPECIAL_PDS 16 169 170static struct special_pd { 171 struct device_node *pd; 172 enum pd_types type; 173} special_pds[MAX_NUM_SPECIAL_PDS] __initdata; 174 175static unsigned int num_special_pds __initdata; 176 177static const struct of_device_id special_ids[] __initconst = { 178 { .compatible = "arm,coresight-etm3x", .data = (void *)PD_DEBUG }, 179 { .compatible = "renesas,dbsc-r8a73a4", .data = (void *)PD_MEMCTL, }, 180 { .compatible = "renesas,dbsc3-r8a7740", .data = (void *)PD_MEMCTL, }, 181 { .compatible = "renesas,sbsc-sh73a0", .data = (void *)PD_MEMCTL, }, 182 { /* sentinel */ }, 183}; 184 185static void __init add_special_pd(struct device_node *np, enum pd_types type) 186{ 187 unsigned int i; 188 struct device_node *pd; 189 190 pd = of_parse_phandle(np, "power-domains", 0); 191 if (!pd) 192 return; 193 194 for (i = 0; i < num_special_pds; i++) 195 if (pd == special_pds[i].pd && type == special_pds[i].type) { 196 of_node_put(pd); 197 return; 198 } 199 200 if (num_special_pds == ARRAY_SIZE(special_pds)) { 201 pr_warn("Too many special PM domains\n"); 202 of_node_put(pd); 203 return; 204 } 205 206 pr_debug("Special PM domain %s type %d for %s\n", pd->name, type, 207 np->full_name); 208 209 special_pds[num_special_pds].pd = pd; 210 special_pds[num_special_pds].type = type; 211 num_special_pds++; 212} 213 214static void __init get_special_pds(void) 215{ 216 struct device_node *np; 217 const struct of_device_id *id; 218 219 /* PM domains containing CPUs */ 220 for_each_node_by_type(np, "cpu") 221 add_special_pd(np, PD_CPU); 222 223 /* PM domain containing console */ 224 if (of_stdout) 225 add_special_pd(of_stdout, PD_CONSOLE); 226 227 /* PM domains containing other special devices */ 228 for_each_matching_node_and_match(np, special_ids, &id) 229 add_special_pd(np, (enum pd_types)id->data); 230} 231 232static void __init put_special_pds(void) 233{ 234 unsigned int i; 235 236 for (i = 0; i < num_special_pds; i++) 237 of_node_put(special_pds[i].pd); 238} 239 240static enum pd_types __init pd_type(const struct device_node *pd) 241{ 242 unsigned int i; 243 244 for (i = 0; i < num_special_pds; i++) 245 if (pd == special_pds[i].pd) 246 return special_pds[i].type; 247 248 return PD_NORMAL; 249} 250 251static void __init rmobile_setup_pm_domain(struct device_node *np, 252 struct rmobile_pm_domain *pd) 253{ 254 const char *name = pd->genpd.name; 255 256 switch (pd_type(np)) { 257 case PD_CPU: 258 /* 259 * This domain contains the CPU core and therefore it should 260 * only be turned off if the CPU is not in use. 261 */ 262 pr_debug("PM domain %s contains CPU\n", name); 263 pd->gov = &pm_domain_always_on_gov; 264 pd->suspend = rmobile_pd_suspend_busy; 265 break; 266 267 case PD_CONSOLE: 268 pr_debug("PM domain %s contains serial console\n", name); 269 pd->gov = &pm_domain_always_on_gov; 270 pd->suspend = rmobile_pd_suspend_console; 271 break; 272 273 case PD_DEBUG: 274 /* 275 * This domain contains the Coresight-ETM hardware block and 276 * therefore it should only be turned off if the debug module 277 * is not in use. 278 */ 279 pr_debug("PM domain %s contains Coresight-ETM\n", name); 280 pd->gov = &pm_domain_always_on_gov; 281 pd->suspend = rmobile_pd_suspend_busy; 282 break; 283 284 case PD_MEMCTL: 285 /* 286 * This domain contains a memory-controller and therefore it 287 * should only be turned off if memory is not in use. 288 */ 289 pr_debug("PM domain %s contains MEMCTL\n", name); 290 pd->gov = &pm_domain_always_on_gov; 291 pd->suspend = rmobile_pd_suspend_busy; 292 break; 293 294 case PD_NORMAL: 295 break; 296 } 297 298 rmobile_init_pm_domain(pd); 299} 300 301static int __init rmobile_add_pm_domains(void __iomem *base, 302 struct device_node *parent, 303 struct generic_pm_domain *genpd_parent) 304{ 305 struct device_node *np; 306 307 for_each_child_of_node(parent, np) { 308 struct rmobile_pm_domain *pd; 309 u32 idx = ~0; 310 311 if (of_property_read_u32(np, "reg", &idx)) { 312 /* always-on domain */ 313 } 314 315 pd = kzalloc(sizeof(*pd), GFP_KERNEL); 316 if (!pd) { 317 of_node_put(np); 318 return -ENOMEM; 319 } 320 321 pd->genpd.name = np->name; 322 pd->base = base; 323 pd->bit_shift = idx; 324 325 rmobile_setup_pm_domain(np, pd); 326 if (genpd_parent) 327 pm_genpd_add_subdomain(genpd_parent, &pd->genpd); 328 of_genpd_add_provider_simple(np, &pd->genpd); 329 330 rmobile_add_pm_domains(base, np, &pd->genpd); 331 } 332 return 0; 333} 334 335static int __init rmobile_init_pm_domains(void) 336{ 337 struct device_node *np, *pmd; 338 bool scanned = false; 339 void __iomem *base; 340 int ret = 0; 341 342 for_each_compatible_node(np, NULL, "renesas,sysc-rmobile") { 343 base = of_iomap(np, 0); 344 if (!base) { 345 pr_warn("%s cannot map reg 0\n", np->full_name); 346 continue; 347 } 348 349 pmd = of_get_child_by_name(np, "pm-domains"); 350 if (!pmd) { 351 pr_warn("%s lacks pm-domains node\n", np->full_name); 352 continue; 353 } 354 355 if (!scanned) { 356 /* Find PM domains containing special blocks */ 357 get_special_pds(); 358 scanned = true; 359 } 360 361 ret = rmobile_add_pm_domains(base, pmd, NULL); 362 of_node_put(pmd); 363 if (ret) { 364 of_node_put(np); 365 break; 366 } 367 } 368 369 put_special_pds(); 370 371 return ret; 372} 373 374core_initcall(rmobile_init_pm_domains); 375