pm-r8a7779.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /*
  2. * r8a7779 Power management support
  3. *
  4. * Copyright (C) 2011 Renesas Solutions Corp.
  5. * Copyright (C) 2011 Magnus Damm
  6. *
  7. * This file is subject to the terms and conditions of the GNU General Public
  8. * License. See the file "COPYING" in the main directory of this archive
  9. * for more details.
  10. */
  11. #include <linux/pm.h>
  12. #include <linux/suspend.h>
  13. #include <linux/err.h>
  14. #include <linux/pm_clock.h>
  15. #include <linux/platform_device.h>
  16. #include <linux/delay.h>
  17. #include <linux/irq.h>
  18. #include <linux/interrupt.h>
  19. #include <linux/console.h>
  20. #include <asm/io.h>
  21. #include <mach/common.h>
  22. #include <mach/pm-rcar.h>
  23. #include <mach/r8a7779.h>
  24. /* SYSC */
  25. #define SYSCIER 0x0c
  26. #define SYSCIMR 0x10
  27. #if defined(CONFIG_PM) || defined(CONFIG_SMP)
  28. static void __init r8a7779_sysc_init(void)
  29. {
  30. void __iomem *base = rcar_sysc_init(0xffd85000);
  31. /* enable all interrupt sources, but do not use interrupt handler */
  32. iowrite32(0x0131000e, base + SYSCIER);
  33. iowrite32(0, base + SYSCIMR);
  34. }
  35. #else /* CONFIG_PM || CONFIG_SMP */
  36. static inline void r8a7779_sysc_init(void) {}
  37. #endif /* CONFIG_PM || CONFIG_SMP */
  38. #ifdef CONFIG_PM
  39. static int pd_power_down(struct generic_pm_domain *genpd)
  40. {
  41. return rcar_sysc_power_down(to_r8a7779_ch(genpd));
  42. }
  43. static int pd_power_up(struct generic_pm_domain *genpd)
  44. {
  45. return rcar_sysc_power_up(to_r8a7779_ch(genpd));
  46. }
  47. static bool pd_is_off(struct generic_pm_domain *genpd)
  48. {
  49. return rcar_sysc_power_is_off(to_r8a7779_ch(genpd));
  50. }
  51. static bool pd_active_wakeup(struct device *dev)
  52. {
  53. return true;
  54. }
  55. static void r8a7779_init_pm_domain(struct r8a7779_pm_domain *r8a7779_pd)
  56. {
  57. struct generic_pm_domain *genpd = &r8a7779_pd->genpd;
  58. pm_genpd_init(genpd, NULL, false);
  59. genpd->dev_ops.stop = pm_clk_suspend;
  60. genpd->dev_ops.start = pm_clk_resume;
  61. genpd->dev_ops.active_wakeup = pd_active_wakeup;
  62. genpd->dev_irq_safe = true;
  63. genpd->power_off = pd_power_down;
  64. genpd->power_on = pd_power_up;
  65. if (pd_is_off(&r8a7779_pd->genpd))
  66. pd_power_up(&r8a7779_pd->genpd);
  67. }
  68. static struct r8a7779_pm_domain r8a7779_pm_domains[] = {
  69. {
  70. .genpd.name = "SH4A",
  71. .ch = {
  72. .chan_offs = 0x80, /* PWRSR1 .. PWRER1 */
  73. .isr_bit = 16, /* SH4A */
  74. },
  75. },
  76. {
  77. .genpd.name = "SGX",
  78. .ch = {
  79. .chan_offs = 0xc0, /* PWRSR2 .. PWRER2 */
  80. .isr_bit = 20, /* SGX */
  81. },
  82. },
  83. {
  84. .genpd.name = "VDP1",
  85. .ch = {
  86. .chan_offs = 0x100, /* PWRSR3 .. PWRER3 */
  87. .isr_bit = 21, /* VDP */
  88. },
  89. },
  90. {
  91. .genpd.name = "IMPX3",
  92. .ch = {
  93. .chan_offs = 0x140, /* PWRSR4 .. PWRER4 */
  94. .isr_bit = 24, /* IMP */
  95. },
  96. },
  97. };
  98. void __init r8a7779_init_pm_domains(void)
  99. {
  100. int j;
  101. for (j = 0; j < ARRAY_SIZE(r8a7779_pm_domains); j++)
  102. r8a7779_init_pm_domain(&r8a7779_pm_domains[j]);
  103. }
  104. #endif /* CONFIG_PM */
  105. void __init r8a7779_pm_init(void)
  106. {
  107. static int once;
  108. if (!once++)
  109. r8a7779_sysc_init();
  110. }