nouveau_platform.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  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/fuse.h>
  30. #include <soc/tegra/pmc.h>
  31. #include "nouveau_drm.h"
  32. #include "nouveau_platform.h"
  33. static int nouveau_platform_power_up(struct nouveau_platform_gpu *gpu)
  34. {
  35. int err;
  36. err = regulator_enable(gpu->vdd);
  37. if (err)
  38. goto err_power;
  39. err = clk_prepare_enable(gpu->clk);
  40. if (err)
  41. goto err_clk;
  42. err = clk_prepare_enable(gpu->clk_pwr);
  43. if (err)
  44. goto err_clk_pwr;
  45. clk_set_rate(gpu->clk_pwr, 204000000);
  46. udelay(10);
  47. reset_control_assert(gpu->rst);
  48. udelay(10);
  49. err = tegra_powergate_remove_clamping(TEGRA_POWERGATE_3D);
  50. if (err)
  51. goto err_clamp;
  52. udelay(10);
  53. reset_control_deassert(gpu->rst);
  54. udelay(10);
  55. return 0;
  56. err_clamp:
  57. clk_disable_unprepare(gpu->clk_pwr);
  58. err_clk_pwr:
  59. clk_disable_unprepare(gpu->clk);
  60. err_clk:
  61. regulator_disable(gpu->vdd);
  62. err_power:
  63. return err;
  64. }
  65. static int nouveau_platform_power_down(struct nouveau_platform_gpu *gpu)
  66. {
  67. int err;
  68. reset_control_assert(gpu->rst);
  69. udelay(10);
  70. clk_disable_unprepare(gpu->clk_pwr);
  71. clk_disable_unprepare(gpu->clk);
  72. udelay(10);
  73. err = regulator_disable(gpu->vdd);
  74. if (err)
  75. return err;
  76. return 0;
  77. }
  78. static int nouveau_platform_probe(struct platform_device *pdev)
  79. {
  80. struct nouveau_platform_gpu *gpu;
  81. struct nouveau_platform_device *device;
  82. struct drm_device *drm;
  83. int err;
  84. gpu = devm_kzalloc(&pdev->dev, sizeof(*gpu), GFP_KERNEL);
  85. if (!gpu)
  86. return -ENOMEM;
  87. gpu->vdd = devm_regulator_get(&pdev->dev, "vdd");
  88. if (IS_ERR(gpu->vdd))
  89. return PTR_ERR(gpu->vdd);
  90. gpu->rst = devm_reset_control_get(&pdev->dev, "gpu");
  91. if (IS_ERR(gpu->rst))
  92. return PTR_ERR(gpu->rst);
  93. gpu->clk = devm_clk_get(&pdev->dev, "gpu");
  94. if (IS_ERR(gpu->clk))
  95. return PTR_ERR(gpu->clk);
  96. gpu->clk_pwr = devm_clk_get(&pdev->dev, "pwr");
  97. if (IS_ERR(gpu->clk_pwr))
  98. return PTR_ERR(gpu->clk_pwr);
  99. err = nouveau_platform_power_up(gpu);
  100. if (err)
  101. return err;
  102. drm = nouveau_platform_device_create(pdev, &device);
  103. if (IS_ERR(drm)) {
  104. err = PTR_ERR(drm);
  105. goto power_down;
  106. }
  107. device->gpu = gpu;
  108. device->gpu_speedo = tegra_sku_info.gpu_speedo_value;
  109. err = drm_dev_register(drm, 0);
  110. if (err < 0)
  111. goto err_unref;
  112. return 0;
  113. err_unref:
  114. drm_dev_unref(drm);
  115. return 0;
  116. power_down:
  117. nouveau_platform_power_down(gpu);
  118. return err;
  119. }
  120. static int nouveau_platform_remove(struct platform_device *pdev)
  121. {
  122. struct drm_device *drm_dev = platform_get_drvdata(pdev);
  123. struct nouveau_drm *drm = nouveau_drm(drm_dev);
  124. struct nouveau_device *device = nvkm_device(&drm->device);
  125. struct nouveau_platform_gpu *gpu = nv_device_to_platform(device)->gpu;
  126. nouveau_drm_device_remove(drm_dev);
  127. return nouveau_platform_power_down(gpu);
  128. }
  129. #if IS_ENABLED(CONFIG_OF)
  130. static const struct of_device_id nouveau_platform_match[] = {
  131. { .compatible = "nvidia,gk20a" },
  132. { }
  133. };
  134. MODULE_DEVICE_TABLE(of, nouveau_platform_match);
  135. #endif
  136. struct platform_driver nouveau_platform_driver = {
  137. .driver = {
  138. .name = "nouveau",
  139. .of_match_table = of_match_ptr(nouveau_platform_match),
  140. },
  141. .probe = nouveau_platform_probe,
  142. .remove = nouveau_platform_remove,
  143. };
  144. module_platform_driver(nouveau_platform_driver);
  145. MODULE_AUTHOR(DRIVER_AUTHOR);
  146. MODULE_DESCRIPTION(DRIVER_DESC);
  147. MODULE_LICENSE("GPL and additional rights");