zx296702-pm-domain.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /*
  2. * Copyright (C) 2015 Linaro Ltd.
  3. *
  4. * Author: Jun Nie <jun.nie@linaro.org>
  5. * License terms: GNU General Public License (GPL) version 2
  6. */
  7. #include <linux/delay.h>
  8. #include <linux/err.h>
  9. #include <linux/io.h>
  10. #include <linux/of.h>
  11. #include <linux/platform_device.h>
  12. #include <linux/pm_domain.h>
  13. #include <linux/slab.h>
  14. #define PCU_DM_CLKEN 0x18
  15. #define PCU_DM_RSTEN 0x1C
  16. #define PCU_DM_ISOEN 0x20
  17. #define PCU_DM_PWRDN 0x24
  18. #define PCU_DM_ACK_SYNC 0x28
  19. enum {
  20. PCU_DM_NEON0 = 0,
  21. PCU_DM_NEON1,
  22. PCU_DM_GPU,
  23. PCU_DM_DECPPU,
  24. PCU_DM_VOU,
  25. PCU_DM_R2D,
  26. PCU_DM_TOP,
  27. };
  28. static void __iomem *pcubase;
  29. struct zx_pm_domain {
  30. struct generic_pm_domain dm;
  31. unsigned int bit;
  32. };
  33. static int normal_power_off(struct generic_pm_domain *domain)
  34. {
  35. struct zx_pm_domain *zpd = (struct zx_pm_domain *)domain;
  36. unsigned long loop = 1000;
  37. u32 tmp;
  38. tmp = readl_relaxed(pcubase + PCU_DM_CLKEN);
  39. tmp &= ~BIT(zpd->bit);
  40. writel_relaxed(tmp, pcubase + PCU_DM_CLKEN);
  41. udelay(5);
  42. tmp = readl_relaxed(pcubase + PCU_DM_ISOEN);
  43. tmp &= ~BIT(zpd->bit);
  44. writel_relaxed(tmp | BIT(zpd->bit), pcubase + PCU_DM_ISOEN);
  45. udelay(5);
  46. tmp = readl_relaxed(pcubase + PCU_DM_RSTEN);
  47. tmp &= ~BIT(zpd->bit);
  48. writel_relaxed(tmp, pcubase + PCU_DM_RSTEN);
  49. udelay(5);
  50. tmp = readl_relaxed(pcubase + PCU_DM_PWRDN);
  51. tmp &= ~BIT(zpd->bit);
  52. writel_relaxed(tmp | BIT(zpd->bit), pcubase + PCU_DM_PWRDN);
  53. do {
  54. tmp = readl_relaxed(pcubase + PCU_DM_ACK_SYNC) & BIT(zpd->bit);
  55. } while (--loop && !tmp);
  56. if (!loop) {
  57. pr_err("Error: %s %s fail\n", __func__, domain->name);
  58. return -EIO;
  59. }
  60. return 0;
  61. }
  62. static int normal_power_on(struct generic_pm_domain *domain)
  63. {
  64. struct zx_pm_domain *zpd = (struct zx_pm_domain *)domain;
  65. unsigned long loop = 10000;
  66. u32 tmp;
  67. tmp = readl_relaxed(pcubase + PCU_DM_PWRDN);
  68. tmp &= ~BIT(zpd->bit);
  69. writel_relaxed(tmp, pcubase + PCU_DM_PWRDN);
  70. do {
  71. tmp = readl_relaxed(pcubase + PCU_DM_ACK_SYNC) & BIT(zpd->bit);
  72. } while (--loop && tmp);
  73. if (!loop) {
  74. pr_err("Error: %s %s fail\n", __func__, domain->name);
  75. return -EIO;
  76. }
  77. tmp = readl_relaxed(pcubase + PCU_DM_RSTEN);
  78. tmp &= ~BIT(zpd->bit);
  79. writel_relaxed(tmp | BIT(zpd->bit), pcubase + PCU_DM_RSTEN);
  80. udelay(5);
  81. tmp = readl_relaxed(pcubase + PCU_DM_ISOEN);
  82. tmp &= ~BIT(zpd->bit);
  83. writel_relaxed(tmp, pcubase + PCU_DM_ISOEN);
  84. udelay(5);
  85. tmp = readl_relaxed(pcubase + PCU_DM_CLKEN);
  86. tmp &= ~BIT(zpd->bit);
  87. writel_relaxed(tmp | BIT(zpd->bit), pcubase + PCU_DM_CLKEN);
  88. udelay(5);
  89. return 0;
  90. }
  91. static struct zx_pm_domain gpu_domain = {
  92. .dm = {
  93. .name = "gpu_domain",
  94. .power_off = normal_power_off,
  95. .power_on = normal_power_on,
  96. },
  97. .bit = PCU_DM_GPU,
  98. };
  99. static struct zx_pm_domain decppu_domain = {
  100. .dm = {
  101. .name = "decppu_domain",
  102. .power_off = normal_power_off,
  103. .power_on = normal_power_on,
  104. },
  105. .bit = PCU_DM_DECPPU,
  106. };
  107. static struct zx_pm_domain vou_domain = {
  108. .dm = {
  109. .name = "vou_domain",
  110. .power_off = normal_power_off,
  111. .power_on = normal_power_on,
  112. },
  113. .bit = PCU_DM_VOU,
  114. };
  115. static struct zx_pm_domain r2d_domain = {
  116. .dm = {
  117. .name = "r2d_domain",
  118. .power_off = normal_power_off,
  119. .power_on = normal_power_on,
  120. },
  121. .bit = PCU_DM_R2D,
  122. };
  123. static struct generic_pm_domain *zx296702_pm_domains[] = {
  124. &vou_domain.dm,
  125. &gpu_domain.dm,
  126. &decppu_domain.dm,
  127. &r2d_domain.dm,
  128. };
  129. static int zx296702_pd_probe(struct platform_device *pdev)
  130. {
  131. struct genpd_onecell_data *genpd_data;
  132. struct resource *res;
  133. int i;
  134. genpd_data = devm_kzalloc(&pdev->dev, sizeof(*genpd_data), GFP_KERNEL);
  135. if (!genpd_data)
  136. return -ENOMEM;
  137. genpd_data->domains = zx296702_pm_domains;
  138. genpd_data->num_domains = ARRAY_SIZE(zx296702_pm_domains);
  139. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  140. if (!res) {
  141. dev_err(&pdev->dev, "no memory resource defined\n");
  142. return -ENODEV;
  143. }
  144. pcubase = devm_ioremap_resource(&pdev->dev, res);
  145. if (!pcubase) {
  146. dev_err(&pdev->dev, "ioremap fail.\n");
  147. return -EIO;
  148. }
  149. for (i = 0; i < ARRAY_SIZE(zx296702_pm_domains); ++i)
  150. pm_genpd_init(zx296702_pm_domains[i], NULL, false);
  151. of_genpd_add_provider_onecell(pdev->dev.of_node, genpd_data);
  152. return 0;
  153. }
  154. static const struct of_device_id zx296702_pm_domain_matches[] __initconst = {
  155. { .compatible = "zte,zx296702-pcu", },
  156. { },
  157. };
  158. static struct platform_driver zx296702_pd_driver __initdata = {
  159. .driver = {
  160. .name = "zx-powerdomain",
  161. .owner = THIS_MODULE,
  162. .of_match_table = zx296702_pm_domain_matches,
  163. },
  164. .probe = zx296702_pd_probe,
  165. };
  166. static int __init zx296702_pd_init(void)
  167. {
  168. return platform_driver_register(&zx296702_pd_driver);
  169. }
  170. subsys_initcall(zx296702_pd_init);