gpc.c (e98bdb3059cbf2b1cd4261e126b08429f64466c3) | gpc.c (721cabf6c6600dbe689ee2782bc087270e97e652) |
---|---|
1/* 2 * Copyright 2011-2013 Freescale Semiconductor, Inc. 3 * Copyright 2011 Linaro Ltd. 4 * 5 * The code contained herein is licensed under the GNU General Public 6 * License. You may obtain a copy of the GNU General Public License 7 * Version 2 or later at the following locations: 8 * 9 * http://www.opensource.org/licenses/gpl-license.html 10 * http://www.gnu.org/copyleft/gpl.html 11 */ 12 | 1/* 2 * Copyright 2011-2013 Freescale Semiconductor, Inc. 3 * Copyright 2011 Linaro Ltd. 4 * 5 * The code contained herein is licensed under the GNU General Public 6 * License. You may obtain a copy of the GNU General Public License 7 * Version 2 or later at the following locations: 8 * 9 * http://www.opensource.org/licenses/gpl-license.html 10 * http://www.gnu.org/copyleft/gpl.html 11 */ 12 |
13#include <linux/clk.h> 14#include <linux/delay.h> | |
15#include <linux/io.h> 16#include <linux/irq.h> 17#include <linux/irqchip.h> 18#include <linux/of.h> 19#include <linux/of_address.h> 20#include <linux/of_irq.h> | 13#include <linux/io.h> 14#include <linux/irq.h> 15#include <linux/irqchip.h> 16#include <linux/of.h> 17#include <linux/of_address.h> 18#include <linux/of_irq.h> |
21#include <linux/platform_device.h> 22#include <linux/pm_domain.h> 23#include <linux/regulator/consumer.h> | |
24#include <linux/irqchip/arm-gic.h> 25#include "common.h" 26#include "hardware.h" 27 | 19#include <linux/irqchip/arm-gic.h> 20#include "common.h" 21#include "hardware.h" 22 |
28#define GPC_CNTR 0x000 | |
29#define GPC_IMR1 0x008 | 23#define GPC_IMR1 0x008 |
30#define GPC_PGC_GPU_PDN 0x260 31#define GPC_PGC_GPU_PUPSCR 0x264 32#define GPC_PGC_GPU_PDNSCR 0x268 | |
33#define GPC_PGC_CPU_PDN 0x2a0 34#define GPC_PGC_CPU_PUPSCR 0x2a4 35#define GPC_PGC_CPU_PDNSCR 0x2a8 36#define GPC_PGC_SW2ISO_SHIFT 0x8 37#define GPC_PGC_SW_SHIFT 0x0 38 39#define IMR_NUM 4 40#define GPC_MAX_IRQS (IMR_NUM * 32) 41 | 24#define GPC_PGC_CPU_PDN 0x2a0 25#define GPC_PGC_CPU_PUPSCR 0x2a4 26#define GPC_PGC_CPU_PDNSCR 0x2a8 27#define GPC_PGC_SW2ISO_SHIFT 0x8 28#define GPC_PGC_SW_SHIFT 0x0 29 30#define IMR_NUM 4 31#define GPC_MAX_IRQS (IMR_NUM * 32) 32 |
42#define GPU_VPU_PUP_REQ BIT(1) 43#define GPU_VPU_PDN_REQ BIT(0) 44 45#define GPC_CLK_MAX 6 46 47struct pu_domain { 48 struct generic_pm_domain base; 49 struct regulator *reg; 50 struct clk *clk[GPC_CLK_MAX]; 51 int num_clks; 52}; 53 | |
54static void __iomem *gpc_base; 55static u32 gpc_wake_irqs[IMR_NUM]; 56static u32 gpc_saved_imrs[IMR_NUM]; 57 58void imx_gpc_set_arm_power_up_timing(u32 sw2iso, u32 sw) 59{ 60 writel_relaxed((sw2iso << GPC_PGC_SW2ISO_SHIFT) | 61 (sw << GPC_PGC_SW_SHIFT), gpc_base + GPC_PGC_CPU_PUPSCR); --- 229 unchanged lines hidden (view full) --- 291 292 if (WARN_ON(!of_find_property(np, "interrupt-controller", NULL))) { 293 pr_warn("Outdated DT detected, suspend/resume will NOT work\n"); 294 295 /* map GPC, so that at least CPUidle and WARs keep working */ 296 gpc_base = of_iomap(np, 0); 297 } 298} | 33static void __iomem *gpc_base; 34static u32 gpc_wake_irqs[IMR_NUM]; 35static u32 gpc_saved_imrs[IMR_NUM]; 36 37void imx_gpc_set_arm_power_up_timing(u32 sw2iso, u32 sw) 38{ 39 writel_relaxed((sw2iso << GPC_PGC_SW2ISO_SHIFT) | 40 (sw << GPC_PGC_SW_SHIFT), gpc_base + GPC_PGC_CPU_PUPSCR); --- 229 unchanged lines hidden (view full) --- 270 271 if (WARN_ON(!of_find_property(np, "interrupt-controller", NULL))) { 272 pr_warn("Outdated DT detected, suspend/resume will NOT work\n"); 273 274 /* map GPC, so that at least CPUidle and WARs keep working */ 275 gpc_base = of_iomap(np, 0); 276 } 277} |
299 300static void _imx6q_pm_pu_power_off(struct generic_pm_domain *genpd) 301{ 302 int iso, iso2sw; 303 u32 val; 304 305 /* Read ISO and ISO2SW power down delays */ 306 val = readl_relaxed(gpc_base + GPC_PGC_GPU_PDNSCR); 307 iso = val & 0x3f; 308 iso2sw = (val >> 8) & 0x3f; 309 310 /* Gate off PU domain when GPU/VPU when powered down */ 311 writel_relaxed(0x1, gpc_base + GPC_PGC_GPU_PDN); 312 313 /* Request GPC to power down GPU/VPU */ 314 val = readl_relaxed(gpc_base + GPC_CNTR); 315 val |= GPU_VPU_PDN_REQ; 316 writel_relaxed(val, gpc_base + GPC_CNTR); 317 318 /* Wait ISO + ISO2SW IPG clock cycles */ 319 ndelay((iso + iso2sw) * 1000 / 66); 320} 321 322static int imx6q_pm_pu_power_off(struct generic_pm_domain *genpd) 323{ 324 struct pu_domain *pu = container_of(genpd, struct pu_domain, base); 325 326 _imx6q_pm_pu_power_off(genpd); 327 328 if (pu->reg) 329 regulator_disable(pu->reg); 330 331 return 0; 332} 333 334static int imx6q_pm_pu_power_on(struct generic_pm_domain *genpd) 335{ 336 struct pu_domain *pu = container_of(genpd, struct pu_domain, base); 337 int i, ret, sw, sw2iso; 338 u32 val; 339 340 if (pu->reg) 341 ret = regulator_enable(pu->reg); 342 if (pu->reg && ret) { 343 pr_err("%s: failed to enable regulator: %d\n", __func__, ret); 344 return ret; 345 } 346 347 /* Enable reset clocks for all devices in the PU domain */ 348 for (i = 0; i < pu->num_clks; i++) 349 clk_prepare_enable(pu->clk[i]); 350 351 /* Gate off PU domain when GPU/VPU when powered down */ 352 writel_relaxed(0x1, gpc_base + GPC_PGC_GPU_PDN); 353 354 /* Read ISO and ISO2SW power down delays */ 355 val = readl_relaxed(gpc_base + GPC_PGC_GPU_PUPSCR); 356 sw = val & 0x3f; 357 sw2iso = (val >> 8) & 0x3f; 358 359 /* Request GPC to power up GPU/VPU */ 360 val = readl_relaxed(gpc_base + GPC_CNTR); 361 val |= GPU_VPU_PUP_REQ; 362 writel_relaxed(val, gpc_base + GPC_CNTR); 363 364 /* Wait ISO + ISO2SW IPG clock cycles */ 365 ndelay((sw + sw2iso) * 1000 / 66); 366 367 /* Disable reset clocks for all devices in the PU domain */ 368 for (i = 0; i < pu->num_clks; i++) 369 clk_disable_unprepare(pu->clk[i]); 370 371 return 0; 372} 373 374static struct generic_pm_domain imx6q_arm_domain = { 375 .name = "ARM", 376}; 377 378static struct pu_domain imx6q_pu_domain = { 379 .base = { 380 .name = "PU", 381 .power_off = imx6q_pm_pu_power_off, 382 .power_on = imx6q_pm_pu_power_on, 383 }, 384}; 385 386static struct generic_pm_domain imx6sl_display_domain = { 387 .name = "DISPLAY", 388}; 389 390static struct generic_pm_domain *imx_gpc_domains[] = { 391 &imx6q_arm_domain, 392 &imx6q_pu_domain.base, 393 &imx6sl_display_domain, 394}; 395 396static struct genpd_onecell_data imx_gpc_onecell_data = { 397 .domains = imx_gpc_domains, 398 .num_domains = ARRAY_SIZE(imx_gpc_domains), 399}; 400 401static int imx_gpc_genpd_init(struct device *dev, struct regulator *pu_reg) 402{ 403 struct clk *clk; 404 int i, ret; 405 406 imx6q_pu_domain.reg = pu_reg; 407 408 for (i = 0; ; i++) { 409 clk = of_clk_get(dev->of_node, i); 410 if (IS_ERR(clk)) 411 break; 412 if (i >= GPC_CLK_MAX) { 413 dev_err(dev, "more than %d clocks\n", GPC_CLK_MAX); 414 goto clk_err; 415 } 416 imx6q_pu_domain.clk[i] = clk; 417 } 418 imx6q_pu_domain.num_clks = i; 419 420 /* Enable power always in case bootloader disabled it. */ 421 imx6q_pm_pu_power_on(&imx6q_pu_domain.base); 422 423 if (!IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) 424 return 0; 425 426 imx6q_pu_domain.base.states = devm_kzalloc(dev, 427 sizeof(*imx6q_pu_domain.base.states), 428 GFP_KERNEL); 429 if (!imx6q_pu_domain.base.states) 430 return -ENOMEM; 431 432 imx6q_pu_domain.base.states[0].power_off_latency_ns = 25000; 433 imx6q_pu_domain.base.states[0].power_on_latency_ns = 2000000; 434 imx6q_pu_domain.base.state_count = 1; 435 436 for (i = 0; i < ARRAY_SIZE(imx_gpc_domains); i++) 437 pm_genpd_init(imx_gpc_domains[i], NULL, false); 438 439 ret = of_genpd_add_provider_onecell(dev->of_node, 440 &imx_gpc_onecell_data); 441 if (ret) 442 goto power_off; 443 444 return 0; 445 446power_off: 447 imx6q_pm_pu_power_off(&imx6q_pu_domain.base); 448clk_err: 449 while (i--) 450 clk_put(imx6q_pu_domain.clk[i]); 451 imx6q_pu_domain.reg = NULL; 452 return -EINVAL; 453} 454 455static int imx_gpc_probe(struct platform_device *pdev) 456{ 457 struct regulator *pu_reg; 458 int ret; 459 460 /* bail out if DT too old and doesn't provide the necessary info */ 461 if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells")) 462 return 0; 463 464 pu_reg = devm_regulator_get_optional(&pdev->dev, "pu"); 465 if (PTR_ERR(pu_reg) == -ENODEV) 466 pu_reg = NULL; 467 if (IS_ERR(pu_reg)) { 468 ret = PTR_ERR(pu_reg); 469 dev_err(&pdev->dev, "failed to get pu regulator: %d\n", ret); 470 return ret; 471 } 472 473 return imx_gpc_genpd_init(&pdev->dev, pu_reg); 474} 475 476static const struct of_device_id imx_gpc_dt_ids[] = { 477 { .compatible = "fsl,imx6q-gpc" }, 478 { .compatible = "fsl,imx6sl-gpc" }, 479 { } 480}; 481 482static struct platform_driver imx_gpc_driver = { 483 .driver = { 484 .name = "imx-gpc", 485 .of_match_table = imx_gpc_dt_ids, 486 }, 487 .probe = imx_gpc_probe, 488}; 489 490static int __init imx_pgc_init(void) 491{ 492 return platform_driver_register(&imx_gpc_driver); 493} 494subsys_initcall(imx_pgc_init); | |