Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
0004  */
0005 
0006 #include <linux/of_device.h>
0007 #include <linux/qcom_scm.h>
0008 #include <linux/ratelimit.h>
0009 
0010 #include "arm-smmu.h"
0011 #include "arm-smmu-qcom.h"
0012 
0013 enum qcom_smmu_impl_reg_offset {
0014     QCOM_SMMU_TBU_PWR_STATUS,
0015     QCOM_SMMU_STATS_SYNC_INV_TBU_ACK,
0016     QCOM_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR,
0017 };
0018 
0019 struct qcom_smmu_config {
0020     const u32 *reg_offset;
0021 };
0022 
0023 void qcom_smmu_tlb_sync_debug(struct arm_smmu_device *smmu)
0024 {
0025     int ret;
0026     u32 tbu_pwr_status, sync_inv_ack, sync_inv_progress;
0027     struct qcom_smmu *qsmmu = container_of(smmu, struct qcom_smmu, smmu);
0028     const struct qcom_smmu_config *cfg;
0029     static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL,
0030                       DEFAULT_RATELIMIT_BURST);
0031 
0032     if (__ratelimit(&rs)) {
0033         dev_err(smmu->dev, "TLB sync timed out -- SMMU may be deadlocked\n");
0034 
0035         cfg = qsmmu->cfg;
0036         if (!cfg)
0037             return;
0038 
0039         ret = qcom_scm_io_readl(smmu->ioaddr + cfg->reg_offset[QCOM_SMMU_TBU_PWR_STATUS],
0040                     &tbu_pwr_status);
0041         if (ret)
0042             dev_err(smmu->dev,
0043                 "Failed to read TBU power status: %d\n", ret);
0044 
0045         ret = qcom_scm_io_readl(smmu->ioaddr + cfg->reg_offset[QCOM_SMMU_STATS_SYNC_INV_TBU_ACK],
0046                     &sync_inv_ack);
0047         if (ret)
0048             dev_err(smmu->dev,
0049                 "Failed to read TBU sync/inv ack status: %d\n", ret);
0050 
0051         ret = qcom_scm_io_readl(smmu->ioaddr + cfg->reg_offset[QCOM_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR],
0052                     &sync_inv_progress);
0053         if (ret)
0054             dev_err(smmu->dev,
0055                 "Failed to read TCU syn/inv progress: %d\n", ret);
0056 
0057         dev_err(smmu->dev,
0058             "TBU: power_status %#x sync_inv_ack %#x sync_inv_progress %#x\n",
0059             tbu_pwr_status, sync_inv_ack, sync_inv_progress);
0060     }
0061 }
0062 
0063 /* Implementation Defined Register Space 0 register offsets */
0064 static const u32 qcom_smmu_impl0_reg_offset[] = {
0065     [QCOM_SMMU_TBU_PWR_STATUS]      = 0x2204,
0066     [QCOM_SMMU_STATS_SYNC_INV_TBU_ACK]  = 0x25dc,
0067     [QCOM_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR]  = 0x2670,
0068 };
0069 
0070 static const struct qcom_smmu_config qcm2290_smmu_cfg = {
0071     .reg_offset = qcom_smmu_impl0_reg_offset,
0072 };
0073 
0074 static const struct qcom_smmu_config sc7180_smmu_cfg = {
0075     .reg_offset = qcom_smmu_impl0_reg_offset,
0076 };
0077 
0078 static const struct qcom_smmu_config sc7280_smmu_cfg = {
0079     .reg_offset = qcom_smmu_impl0_reg_offset,
0080 };
0081 
0082 static const struct qcom_smmu_config sc8180x_smmu_cfg = {
0083     .reg_offset = qcom_smmu_impl0_reg_offset,
0084 };
0085 
0086 static const struct qcom_smmu_config sc8280xp_smmu_cfg = {
0087     .reg_offset = qcom_smmu_impl0_reg_offset,
0088 };
0089 
0090 static const struct qcom_smmu_config sm6125_smmu_cfg = {
0091     .reg_offset = qcom_smmu_impl0_reg_offset,
0092 };
0093 
0094 static const struct qcom_smmu_config sm6350_smmu_cfg = {
0095     .reg_offset = qcom_smmu_impl0_reg_offset,
0096 };
0097 
0098 static const struct qcom_smmu_config sm8150_smmu_cfg = {
0099     .reg_offset = qcom_smmu_impl0_reg_offset,
0100 };
0101 
0102 static const struct qcom_smmu_config sm8250_smmu_cfg = {
0103     .reg_offset = qcom_smmu_impl0_reg_offset,
0104 };
0105 
0106 static const struct qcom_smmu_config sm8350_smmu_cfg = {
0107     .reg_offset = qcom_smmu_impl0_reg_offset,
0108 };
0109 
0110 static const struct qcom_smmu_config sm8450_smmu_cfg = {
0111     .reg_offset = qcom_smmu_impl0_reg_offset,
0112 };
0113 
0114 static const struct of_device_id __maybe_unused qcom_smmu_impl_debug_match[] = {
0115     { .compatible = "qcom,msm8998-smmu-v2" },
0116     { .compatible = "qcom,qcm2290-smmu-500", .data = &qcm2290_smmu_cfg },
0117     { .compatible = "qcom,sc7180-smmu-500", .data = &sc7180_smmu_cfg },
0118     { .compatible = "qcom,sc7280-smmu-500", .data = &sc7280_smmu_cfg},
0119     { .compatible = "qcom,sc8180x-smmu-500", .data = &sc8180x_smmu_cfg },
0120     { .compatible = "qcom,sc8280xp-smmu-500", .data = &sc8280xp_smmu_cfg },
0121     { .compatible = "qcom,sdm630-smmu-v2" },
0122     { .compatible = "qcom,sdm845-smmu-500" },
0123     { .compatible = "qcom,sm6125-smmu-500", .data = &sm6125_smmu_cfg},
0124     { .compatible = "qcom,sm6350-smmu-500", .data = &sm6350_smmu_cfg},
0125     { .compatible = "qcom,sm8150-smmu-500", .data = &sm8150_smmu_cfg },
0126     { .compatible = "qcom,sm8250-smmu-500", .data = &sm8250_smmu_cfg },
0127     { .compatible = "qcom,sm8350-smmu-500", .data = &sm8350_smmu_cfg },
0128     { .compatible = "qcom,sm8450-smmu-500", .data = &sm8450_smmu_cfg },
0129     { }
0130 };
0131 
0132 const void *qcom_smmu_impl_data(struct arm_smmu_device *smmu)
0133 {
0134     const struct of_device_id *match;
0135     const struct device_node *np = smmu->dev->of_node;
0136 
0137     match = of_match_node(qcom_smmu_impl_debug_match, np);
0138     if (!match)
0139         return NULL;
0140 
0141     return match->data;
0142 }