162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <linux/device.h>
762306a36Sopenharmony_ci#include <linux/firmware/qcom/qcom_scm.h>
862306a36Sopenharmony_ci#include <linux/ratelimit.h>
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include "arm-smmu.h"
1162306a36Sopenharmony_ci#include "arm-smmu-qcom.h"
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_civoid qcom_smmu_tlb_sync_debug(struct arm_smmu_device *smmu)
1462306a36Sopenharmony_ci{
1562306a36Sopenharmony_ci	int ret;
1662306a36Sopenharmony_ci	u32 tbu_pwr_status, sync_inv_ack, sync_inv_progress;
1762306a36Sopenharmony_ci	struct qcom_smmu *qsmmu = container_of(smmu, struct qcom_smmu, smmu);
1862306a36Sopenharmony_ci	const struct qcom_smmu_config *cfg;
1962306a36Sopenharmony_ci	static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL,
2062306a36Sopenharmony_ci				      DEFAULT_RATELIMIT_BURST);
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci	if (__ratelimit(&rs)) {
2362306a36Sopenharmony_ci		dev_err(smmu->dev, "TLB sync timed out -- SMMU may be deadlocked\n");
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci		cfg = qsmmu->cfg;
2662306a36Sopenharmony_ci		if (!cfg)
2762306a36Sopenharmony_ci			return;
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci		ret = qcom_scm_io_readl(smmu->ioaddr + cfg->reg_offset[QCOM_SMMU_TBU_PWR_STATUS],
3062306a36Sopenharmony_ci					&tbu_pwr_status);
3162306a36Sopenharmony_ci		if (ret)
3262306a36Sopenharmony_ci			dev_err(smmu->dev,
3362306a36Sopenharmony_ci				"Failed to read TBU power status: %d\n", ret);
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci		ret = qcom_scm_io_readl(smmu->ioaddr + cfg->reg_offset[QCOM_SMMU_STATS_SYNC_INV_TBU_ACK],
3662306a36Sopenharmony_ci					&sync_inv_ack);
3762306a36Sopenharmony_ci		if (ret)
3862306a36Sopenharmony_ci			dev_err(smmu->dev,
3962306a36Sopenharmony_ci				"Failed to read TBU sync/inv ack status: %d\n", ret);
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci		ret = qcom_scm_io_readl(smmu->ioaddr + cfg->reg_offset[QCOM_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR],
4262306a36Sopenharmony_ci					&sync_inv_progress);
4362306a36Sopenharmony_ci		if (ret)
4462306a36Sopenharmony_ci			dev_err(smmu->dev,
4562306a36Sopenharmony_ci				"Failed to read TCU syn/inv progress: %d\n", ret);
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci		dev_err(smmu->dev,
4862306a36Sopenharmony_ci			"TBU: power_status %#x sync_inv_ack %#x sync_inv_progress %#x\n",
4962306a36Sopenharmony_ci			tbu_pwr_status, sync_inv_ack, sync_inv_progress);
5062306a36Sopenharmony_ci	}
5162306a36Sopenharmony_ci}
52