irq-gic-pm.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /*
  2. * Copyright (C) 2016 NVIDIA CORPORATION, All Rights Reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 as
  6. * published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include <linux/module.h>
  17. #include <linux/clk.h>
  18. #include <linux/of_device.h>
  19. #include <linux/of_irq.h>
  20. #include <linux/irqchip/arm-gic.h>
  21. #include <linux/platform_device.h>
  22. #include <linux/pm_clock.h>
  23. #include <linux/pm_runtime.h>
  24. #include <linux/slab.h>
  25. struct gic_clk_data {
  26. unsigned int num_clocks;
  27. const char *const *clocks;
  28. };
  29. static int gic_runtime_resume(struct device *dev)
  30. {
  31. struct gic_chip_data *gic = dev_get_drvdata(dev);
  32. int ret;
  33. ret = pm_clk_resume(dev);
  34. if (ret)
  35. return ret;
  36. /*
  37. * On the very first resume, the pointer to the driver data
  38. * will be NULL and this is intentional, because we do not
  39. * want to restore the GIC on the very first resume. So if
  40. * the pointer is not valid just return.
  41. */
  42. if (!gic)
  43. return 0;
  44. gic_dist_restore(gic);
  45. gic_cpu_restore(gic);
  46. return 0;
  47. }
  48. static int gic_runtime_suspend(struct device *dev)
  49. {
  50. struct gic_chip_data *gic = dev_get_drvdata(dev);
  51. gic_dist_save(gic);
  52. gic_cpu_save(gic);
  53. return pm_clk_suspend(dev);
  54. }
  55. static int gic_get_clocks(struct device *dev, const struct gic_clk_data *data)
  56. {
  57. unsigned int i;
  58. int ret;
  59. if (!dev || !data)
  60. return -EINVAL;
  61. ret = pm_clk_create(dev);
  62. if (ret)
  63. return ret;
  64. for (i = 0; i < data->num_clocks; i++) {
  65. ret = of_pm_clk_add_clk(dev, data->clocks[i]);
  66. if (ret) {
  67. dev_err(dev, "failed to add clock %s\n",
  68. data->clocks[i]);
  69. pm_clk_destroy(dev);
  70. return ret;
  71. }
  72. }
  73. return 0;
  74. }
  75. static int gic_probe(struct platform_device *pdev)
  76. {
  77. struct device *dev = &pdev->dev;
  78. const struct gic_clk_data *data;
  79. struct gic_chip_data *gic;
  80. int ret, irq;
  81. data = of_device_get_match_data(&pdev->dev);
  82. if (!data) {
  83. dev_err(&pdev->dev, "no device match found\n");
  84. return -ENODEV;
  85. }
  86. irq = irq_of_parse_and_map(dev->of_node, 0);
  87. if (!irq) {
  88. dev_err(dev, "no parent interrupt found!\n");
  89. return -EINVAL;
  90. }
  91. ret = gic_get_clocks(dev, data);
  92. if (ret)
  93. goto irq_dispose;
  94. pm_runtime_enable(dev);
  95. ret = pm_runtime_get_sync(dev);
  96. if (ret < 0)
  97. goto rpm_disable;
  98. ret = gic_of_init_child(dev, &gic, irq);
  99. if (ret)
  100. goto rpm_put;
  101. platform_set_drvdata(pdev, gic);
  102. pm_runtime_put(dev);
  103. dev_info(dev, "GIC IRQ controller registered\n");
  104. return 0;
  105. rpm_put:
  106. pm_runtime_put_sync(dev);
  107. rpm_disable:
  108. pm_runtime_disable(dev);
  109. pm_clk_destroy(dev);
  110. irq_dispose:
  111. irq_dispose_mapping(irq);
  112. return ret;
  113. }
  114. static const struct dev_pm_ops gic_pm_ops = {
  115. SET_RUNTIME_PM_OPS(gic_runtime_suspend,
  116. gic_runtime_resume, NULL)
  117. };
  118. static const char * const gic400_clocks[] = {
  119. "clk",
  120. };
  121. static const struct gic_clk_data gic400_data = {
  122. .num_clocks = ARRAY_SIZE(gic400_clocks),
  123. .clocks = gic400_clocks,
  124. };
  125. static const struct of_device_id gic_match[] = {
  126. { .compatible = "nvidia,tegra210-agic", .data = &gic400_data },
  127. {},
  128. };
  129. MODULE_DEVICE_TABLE(of, gic_match);
  130. static struct platform_driver gic_driver = {
  131. .probe = gic_probe,
  132. .driver = {
  133. .name = "gic",
  134. .of_match_table = gic_match,
  135. .pm = &gic_pm_ops,
  136. }
  137. };
  138. builtin_platform_driver(gic_driver);