sde_irq.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
  4. */
  5. #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
  6. #include <linux/irqdomain.h>
  7. #include <linux/irq.h>
  8. #include <linux/kthread.h>
  9. #include "sde_irq.h"
  10. #include "sde_core_irq.h"
  11. uint32_t g_sde_irq_status;
  12. void sde_irq_update(struct msm_kms *msm_kms, bool enable)
  13. {
  14. struct sde_kms *sde_kms = to_sde_kms(msm_kms);
  15. if (!msm_kms || !sde_kms) {
  16. SDE_ERROR("invalid kms arguments\n");
  17. return;
  18. }
  19. sde_kms->irq_enabled = enable;
  20. if (enable)
  21. enable_irq(sde_kms->irq_num);
  22. else
  23. disable_irq(sde_kms->irq_num);
  24. }
  25. irqreturn_t sde_irq(struct msm_kms *kms)
  26. {
  27. struct sde_kms *sde_kms = to_sde_kms(kms);
  28. u32 interrupts;
  29. sde_kms->hw_intr->ops.get_interrupt_sources(sde_kms->hw_intr,
  30. &interrupts);
  31. /* store irq status in case of irq-storm debugging */
  32. g_sde_irq_status = interrupts;
  33. /*
  34. * Taking care of MDP interrupt
  35. */
  36. if (interrupts & IRQ_SOURCE_MDP) {
  37. interrupts &= ~IRQ_SOURCE_MDP;
  38. sde_core_irq(sde_kms);
  39. }
  40. /*
  41. * Routing all other interrupts to external drivers
  42. */
  43. while (interrupts) {
  44. irq_hw_number_t hwirq = fls(interrupts) - 1;
  45. unsigned int mapping;
  46. int rc;
  47. mapping = irq_find_mapping(sde_kms->irq_controller.domain,
  48. hwirq);
  49. if (mapping == 0) {
  50. SDE_EVT32(hwirq, SDE_EVTLOG_ERROR);
  51. goto error;
  52. }
  53. rc = generic_handle_irq(mapping);
  54. if (rc < 0) {
  55. SDE_EVT32(hwirq, mapping, rc, SDE_EVTLOG_ERROR);
  56. goto error;
  57. }
  58. interrupts &= ~(1 << hwirq);
  59. }
  60. return IRQ_HANDLED;
  61. error:
  62. /* bad situation, inform irq system, it may disable overall MDSS irq */
  63. return IRQ_NONE;
  64. }
  65. void sde_irq_preinstall(struct msm_kms *kms)
  66. {
  67. struct sde_kms *sde_kms = to_sde_kms(kms);
  68. if (!sde_kms->dev || !sde_kms->dev->dev) {
  69. pr_err("invalid device handles\n");
  70. return;
  71. }
  72. sde_core_irq_preinstall(sde_kms);
  73. sde_kms->irq_num = platform_get_irq(
  74. to_platform_device(sde_kms->dev->dev),
  75. 0);
  76. if (sde_kms->irq_num < 0) {
  77. SDE_ERROR("invalid irq number %d\n", sde_kms->irq_num);
  78. return;
  79. }
  80. /* disable irq until power event enables it */
  81. if (!sde_kms->splash_data.num_splash_displays && !sde_kms->irq_enabled)
  82. irq_set_status_flags(sde_kms->irq_num, IRQ_NOAUTOEN);
  83. }
  84. int sde_irq_postinstall(struct msm_kms *kms)
  85. {
  86. struct sde_kms *sde_kms = to_sde_kms(kms);
  87. int rc;
  88. if (!kms) {
  89. SDE_ERROR("invalid parameters\n");
  90. return -EINVAL;
  91. }
  92. rc = sde_core_irq_postinstall(sde_kms);
  93. return rc;
  94. }
  95. void sde_irq_uninstall(struct msm_kms *kms)
  96. {
  97. struct sde_kms *sde_kms = to_sde_kms(kms);
  98. if (!kms) {
  99. SDE_ERROR("invalid parameters\n");
  100. return;
  101. }
  102. sde_core_irq_uninstall(sde_kms);
  103. sde_core_irq_domain_fini(sde_kms);
  104. }