1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. 4 */ 5 6 #include <linux/device.h> 7 #include <linux/firmware/qcom/qcom_scm.h> 8 #include <linux/ratelimit.h> 9 10 #include "arm-smmu.h" 11 #include "arm-smmu-qcom.h" 12 13 void qcom_smmu_tlb_sync_debug(struct arm_smmu_device *smmu) 14 { 15 int ret; 16 u32 tbu_pwr_status, sync_inv_ack, sync_inv_progress; 17 struct qcom_smmu *qsmmu = container_of(smmu, struct qcom_smmu, smmu); 18 const struct qcom_smmu_config *cfg; 19 static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL, 20 DEFAULT_RATELIMIT_BURST); 21 22 if (__ratelimit(&rs)) { 23 dev_err(smmu->dev, "TLB sync timed out -- SMMU may be deadlocked\n"); 24 25 cfg = qsmmu->cfg; 26 if (!cfg) 27 return; 28 29 ret = qcom_scm_io_readl(smmu->ioaddr + cfg->reg_offset[QCOM_SMMU_TBU_PWR_STATUS], 30 &tbu_pwr_status); 31 if (ret) 32 dev_err(smmu->dev, 33 "Failed to read TBU power status: %d\n", ret); 34 35 ret = qcom_scm_io_readl(smmu->ioaddr + cfg->reg_offset[QCOM_SMMU_STATS_SYNC_INV_TBU_ACK], 36 &sync_inv_ack); 37 if (ret) 38 dev_err(smmu->dev, 39 "Failed to read TBU sync/inv ack status: %d\n", ret); 40 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 47 dev_err(smmu->dev, 48 "TBU: power_status %#x sync_inv_ack %#x sync_inv_progress %#x\n", 49 tbu_pwr_status, sync_inv_ack, sync_inv_progress); 50 } 51 } 52