arm-smmu-qcom-debug.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  4. */
  5. #include <linux/of_device.h>
  6. #include <linux/qcom_scm.h>
  7. #include <linux/ratelimit.h>
  8. #include "arm-smmu.h"
  9. #include "arm-smmu-qcom.h"
  10. enum qcom_smmu_impl_reg_offset {
  11. QCOM_SMMU_TBU_PWR_STATUS,
  12. QCOM_SMMU_STATS_SYNC_INV_TBU_ACK,
  13. QCOM_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR,
  14. };
  15. struct qcom_smmu_config {
  16. const u32 *reg_offset;
  17. };
  18. void qcom_smmu_tlb_sync_debug(struct arm_smmu_device *smmu)
  19. {
  20. int ret;
  21. u32 tbu_pwr_status, sync_inv_ack, sync_inv_progress;
  22. struct qcom_smmu *qsmmu = container_of(smmu, struct qcom_smmu, smmu);
  23. const struct qcom_smmu_config *cfg;
  24. static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL,
  25. DEFAULT_RATELIMIT_BURST);
  26. if (__ratelimit(&rs)) {
  27. dev_err(smmu->dev, "TLB sync timed out -- SMMU may be deadlocked\n");
  28. cfg = qsmmu->cfg;
  29. if (!cfg)
  30. return;
  31. ret = qcom_scm_io_readl(smmu->ioaddr + cfg->reg_offset[QCOM_SMMU_TBU_PWR_STATUS],
  32. &tbu_pwr_status);
  33. if (ret)
  34. dev_err(smmu->dev,
  35. "Failed to read TBU power status: %d\n", ret);
  36. ret = qcom_scm_io_readl(smmu->ioaddr + cfg->reg_offset[QCOM_SMMU_STATS_SYNC_INV_TBU_ACK],
  37. &sync_inv_ack);
  38. if (ret)
  39. dev_err(smmu->dev,
  40. "Failed to read TBU sync/inv ack status: %d\n", ret);
  41. ret = qcom_scm_io_readl(smmu->ioaddr + cfg->reg_offset[QCOM_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR],
  42. &sync_inv_progress);
  43. if (ret)
  44. dev_err(smmu->dev,
  45. "Failed to read TCU syn/inv progress: %d\n", ret);
  46. dev_err(smmu->dev,
  47. "TBU: power_status %#x sync_inv_ack %#x sync_inv_progress %#x\n",
  48. tbu_pwr_status, sync_inv_ack, sync_inv_progress);
  49. }
  50. }
  51. /* Implementation Defined Register Space 0 register offsets */
  52. static const u32 qcom_smmu_impl0_reg_offset[] = {
  53. [QCOM_SMMU_TBU_PWR_STATUS] = 0x2204,
  54. [QCOM_SMMU_STATS_SYNC_INV_TBU_ACK] = 0x25dc,
  55. [QCOM_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR] = 0x2670,
  56. };
  57. static const struct qcom_smmu_config qcm2290_smmu_cfg = {
  58. .reg_offset = qcom_smmu_impl0_reg_offset,
  59. };
  60. static const struct qcom_smmu_config sc7180_smmu_cfg = {
  61. .reg_offset = qcom_smmu_impl0_reg_offset,
  62. };
  63. static const struct qcom_smmu_config sc7280_smmu_cfg = {
  64. .reg_offset = qcom_smmu_impl0_reg_offset,
  65. };
  66. static const struct qcom_smmu_config sc8180x_smmu_cfg = {
  67. .reg_offset = qcom_smmu_impl0_reg_offset,
  68. };
  69. static const struct qcom_smmu_config sc8280xp_smmu_cfg = {
  70. .reg_offset = qcom_smmu_impl0_reg_offset,
  71. };
  72. static const struct qcom_smmu_config sm6125_smmu_cfg = {
  73. .reg_offset = qcom_smmu_impl0_reg_offset,
  74. };
  75. static const struct qcom_smmu_config sm6350_smmu_cfg = {
  76. .reg_offset = qcom_smmu_impl0_reg_offset,
  77. };
  78. static const struct qcom_smmu_config sm8150_smmu_cfg = {
  79. .reg_offset = qcom_smmu_impl0_reg_offset,
  80. };
  81. static const struct qcom_smmu_config sm8250_smmu_cfg = {
  82. .reg_offset = qcom_smmu_impl0_reg_offset,
  83. };
  84. static const struct qcom_smmu_config sm8350_smmu_cfg = {
  85. .reg_offset = qcom_smmu_impl0_reg_offset,
  86. };
  87. static const struct qcom_smmu_config sm8450_smmu_cfg = {
  88. .reg_offset = qcom_smmu_impl0_reg_offset,
  89. };
  90. static const struct of_device_id __maybe_unused qcom_smmu_impl_debug_match[] = {
  91. { .compatible = "qcom,msm8998-smmu-v2" },
  92. { .compatible = "qcom,qcm2290-smmu-500", .data = &qcm2290_smmu_cfg },
  93. { .compatible = "qcom,sc7180-smmu-500", .data = &sc7180_smmu_cfg },
  94. { .compatible = "qcom,sc7280-smmu-500", .data = &sc7280_smmu_cfg},
  95. { .compatible = "qcom,sc8180x-smmu-500", .data = &sc8180x_smmu_cfg },
  96. { .compatible = "qcom,sc8280xp-smmu-500", .data = &sc8280xp_smmu_cfg },
  97. { .compatible = "qcom,sdm630-smmu-v2" },
  98. { .compatible = "qcom,sdm845-smmu-500" },
  99. { .compatible = "qcom,sm6125-smmu-500", .data = &sm6125_smmu_cfg},
  100. { .compatible = "qcom,sm6350-smmu-500", .data = &sm6350_smmu_cfg},
  101. { .compatible = "qcom,sm8150-smmu-500", .data = &sm8150_smmu_cfg },
  102. { .compatible = "qcom,sm8250-smmu-500", .data = &sm8250_smmu_cfg },
  103. { .compatible = "qcom,sm8350-smmu-500", .data = &sm8350_smmu_cfg },
  104. { .compatible = "qcom,sm8450-smmu-500", .data = &sm8450_smmu_cfg },
  105. { }
  106. };
  107. const void *qcom_smmu_impl_data(struct arm_smmu_device *smmu)
  108. {
  109. const struct of_device_id *match;
  110. const struct device_node *np = smmu->dev->of_node;
  111. match = of_match_node(qcom_smmu_impl_debug_match, np);
  112. if (!match)
  113. return NULL;
  114. return match->data;
  115. }