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