nouveau_platform.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /*
  2. * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  17. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  20. * DEALINGS IN THE SOFTWARE.
  21. */
  22. #include <linux/clk.h>
  23. #include <linux/io.h>
  24. #include <linux/module.h>
  25. #include <linux/platform_device.h>
  26. #include <linux/of.h>
  27. #include <linux/reset.h>
  28. #include <linux/regulator/consumer.h>
  29. #include <soc/tegra/pmc.h>
  30. #include "nouveau_drm.h"
  31. #include "nouveau_platform.h"
  32. static int nouveau_platform_power_up(struct nouveau_platform_gpu *gpu)
  33. {
  34. int err;
  35. err = regulator_enable(gpu->vdd);
  36. if (err)
  37. goto err_power;
  38. err = clk_prepare_enable(gpu->clk);
  39. if (err)
  40. goto err_clk;
  41. err = clk_prepare_enable(gpu->clk_pwr);
  42. if (err)
  43. goto err_clk_pwr;
  44. clk_set_rate(gpu->clk_pwr, 204000000);
  45. udelay(10);
  46. reset_control_assert(gpu->rst);
  47. udelay(10);
  48. err = tegra_powergate_remove_clamping(TEGRA_POWERGATE_3D);
  49. if (err)
  50. goto err_clamp;
  51. udelay(10);
  52. reset_control_deassert(gpu->rst);
  53. udelay(10);
  54. return 0;
  55. err_clamp:
  56. clk_disable_unprepare(gpu->clk_pwr);
  57. err_clk_pwr:
  58. clk_disable_unprepare(gpu->clk);
  59. err_clk:
  60. regulator_disable(gpu->vdd);
  61. err_power:
  62. return err;
  63. }
  64. static int nouveau_platform_power_down(struct nouveau_platform_gpu *gpu)
  65. {
  66. int err;
  67. reset_control_assert(gpu->rst);
  68. udelay(10);
  69. clk_disable_unprepare(gpu->clk_pwr);
  70. clk_disable_unprepare(gpu->clk);
  71. udelay(10);
  72. err = regulator_disable(gpu->vdd);
  73. if (err)
  74. return err;
  75. return 0;
  76. }
  77. static int nouveau_platform_probe(struct platform_device *pdev)
  78. {
  79. struct nouveau_platform_gpu *gpu;
  80. struct nouveau_platform_device *device;
  81. struct drm_device *drm;
  82. int err;
  83. gpu = devm_kzalloc(&pdev->dev, sizeof(*gpu), GFP_KERNEL);
  84. if (!gpu)
  85. return -ENOMEM;
  86. gpu->vdd = devm_regulator_get(&pdev->dev, "vdd");
  87. if (IS_ERR(gpu->vdd))
  88. return PTR_ERR(gpu->vdd);
  89. gpu->rst = devm_reset_control_get(&pdev->dev, "gpu");
  90. if (IS_ERR(gpu->rst))
  91. return PTR_ERR(gpu->rst);
  92. gpu->clk = devm_clk_get(&pdev->dev, "gpu");
  93. if (IS_ERR(gpu->clk))
  94. return PTR_ERR(gpu->clk);
  95. gpu->clk_pwr = devm_clk_get(&pdev->dev, "pwr");
  96. if (IS_ERR(gpu->clk_pwr))
  97. return PTR_ERR(gpu->clk_pwr);
  98. err = nouveau_platform_power_up(gpu);
  99. if (err)
  100. return err;
  101. drm = nouveau_platform_device_create(pdev, &device);
  102. if (IS_ERR(drm)) {
  103. err = PTR_ERR(drm);
  104. goto power_down;
  105. }
  106. device->gpu = gpu;
  107. err = drm_dev_register(drm, 0);
  108. if (err < 0)
  109. goto err_unref;
  110. return 0;
  111. err_unref:
  112. drm_dev_unref(drm);
  113. return 0;
  114. power_down:
  115. nouveau_platform_power_down(gpu);
  116. return err;
  117. }
  118. static int nouveau_platform_remove(struct platform_device *pdev)
  119. {
  120. struct drm_device *drm_dev = platform_get_drvdata(pdev);
  121. struct nouveau_drm *drm = nouveau_drm(drm_dev);
  122. struct nouveau_device *device = nvkm_device(&drm->device);
  123. struct nouveau_platform_gpu *gpu = nv_device_to_platform(device)->gpu;
  124. nouveau_drm_device_remove(drm_dev);
  125. return nouveau_platform_power_down(gpu);
  126. }
  127. #if IS_ENABLED(CONFIG_OF)
  128. static const struct of_device_id nouveau_platform_match[] = {
  129. { .compatible = "nvidia,gk20a" },
  130. { }
  131. };
  132. MODULE_DEVICE_TABLE(of, nouveau_platform_match);
  133. #endif
  134. struct platform_driver nouveau_platform_driver = {
  135. .driver = {
  136. .name = "nouveau",
  137. .of_match_table = of_match_ptr(nouveau_platform_match),
  138. },
  139. .probe = nouveau_platform_probe,
  140. .remove = nouveau_platform_remove,
  141. };
  142. module_platform_driver(nouveau_platform_driver);
  143. MODULE_AUTHOR(DRIVER_AUTHOR);
  144. MODULE_DESCRIPTION(DRIVER_DESC);
  145. MODULE_LICENSE("GPL and additional rights");