msm_io_utils.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2016-2018, 2020-2021 The Linux Foundation. All rights reserved.
  4. * Copyright (C) 2013 Red Hat
  5. * Author: Rob Clark <robdclark@gmail.com>
  6. */
  7. #include <linux/interconnect.h>
  8. #include <linux/io.h>
  9. #include "msm_drv.h"
  10. /*
  11. * Util/helpers:
  12. */
  13. struct clk *msm_clk_bulk_get_clock(struct clk_bulk_data *bulk, int count,
  14. const char *name)
  15. {
  16. int i;
  17. char n[32];
  18. snprintf(n, sizeof(n), "%s_clk", name);
  19. for (i = 0; bulk && i < count; i++) {
  20. if (!strcmp(bulk[i].id, name) || !strcmp(bulk[i].id, n))
  21. return bulk[i].clk;
  22. }
  23. return NULL;
  24. }
  25. struct clk *msm_clk_get(struct platform_device *pdev, const char *name)
  26. {
  27. struct clk *clk;
  28. char name2[32];
  29. clk = devm_clk_get(&pdev->dev, name);
  30. if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER)
  31. return clk;
  32. snprintf(name2, sizeof(name2), "%s_clk", name);
  33. clk = devm_clk_get(&pdev->dev, name2);
  34. if (!IS_ERR(clk))
  35. dev_warn(&pdev->dev, "Using legacy clk name binding. Use "
  36. "\"%s\" instead of \"%s\"\n", name, name2);
  37. return clk;
  38. }
  39. void __iomem *msm_ioremap_mdss(struct platform_device *mdss_pdev,
  40. struct platform_device *pdev,
  41. const char *name)
  42. {
  43. struct resource *res;
  44. res = platform_get_resource_byname(mdss_pdev, IORESOURCE_MEM, name);
  45. if (!res)
  46. return ERR_PTR(-EINVAL);
  47. return devm_ioremap_resource(&pdev->dev, res);
  48. }
  49. static void __iomem *_msm_ioremap(struct platform_device *pdev, const char *name,
  50. bool quiet, phys_addr_t *psize)
  51. {
  52. struct resource *res;
  53. unsigned long size;
  54. void __iomem *ptr;
  55. if (name)
  56. res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
  57. else
  58. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  59. if (!res) {
  60. if (!quiet)
  61. DRM_DEV_ERROR(&pdev->dev, "failed to get memory resource: %s\n", name);
  62. return ERR_PTR(-EINVAL);
  63. }
  64. size = resource_size(res);
  65. ptr = devm_ioremap(&pdev->dev, res->start, size);
  66. if (!ptr) {
  67. if (!quiet)
  68. DRM_DEV_ERROR(&pdev->dev, "failed to ioremap: %s\n", name);
  69. return ERR_PTR(-ENOMEM);
  70. }
  71. if (psize)
  72. *psize = size;
  73. return ptr;
  74. }
  75. void __iomem *msm_ioremap(struct platform_device *pdev, const char *name)
  76. {
  77. return _msm_ioremap(pdev, name, false, NULL);
  78. }
  79. void __iomem *msm_ioremap_quiet(struct platform_device *pdev, const char *name)
  80. {
  81. return _msm_ioremap(pdev, name, true, NULL);
  82. }
  83. void __iomem *msm_ioremap_size(struct platform_device *pdev, const char *name,
  84. phys_addr_t *psize)
  85. {
  86. return _msm_ioremap(pdev, name, false, psize);
  87. }
  88. static enum hrtimer_restart msm_hrtimer_worktimer(struct hrtimer *t)
  89. {
  90. struct msm_hrtimer_work *work = container_of(t,
  91. struct msm_hrtimer_work, timer);
  92. kthread_queue_work(work->worker, &work->work);
  93. return HRTIMER_NORESTART;
  94. }
  95. void msm_hrtimer_queue_work(struct msm_hrtimer_work *work,
  96. ktime_t wakeup_time,
  97. enum hrtimer_mode mode)
  98. {
  99. hrtimer_start(&work->timer, wakeup_time, mode);
  100. }
  101. void msm_hrtimer_work_init(struct msm_hrtimer_work *work,
  102. struct kthread_worker *worker,
  103. kthread_work_func_t fn,
  104. clockid_t clock_id,
  105. enum hrtimer_mode mode)
  106. {
  107. hrtimer_setup(&work->timer, msm_hrtimer_worktimer, clock_id, mode);
  108. work->worker = worker;
  109. kthread_init_work(&work->work, fn);
  110. }
  111. struct icc_path *msm_icc_get(struct device *dev, const char *name)
  112. {
  113. struct device *mdss_dev = dev->parent;
  114. struct icc_path *path;
  115. path = of_icc_get(dev, name);
  116. if (path)
  117. return path;
  118. /*
  119. * If there are no interconnects attached to the corresponding device
  120. * node, of_icc_get() will return NULL.
  121. *
  122. * If the MDP5/DPU device node doesn't have interconnects, lookup the
  123. * path in the parent (MDSS) device.
  124. */
  125. return of_icc_get(mdss_dev, name);
  126. }