[PATCH v7 2/7] iommu/arm-smmu-qcom-tbu: Add Qualcomm TBU driver
Konrad Dybcio
konrad.dybcio at linaro.org
Wed Apr 10 05:02:18 PDT 2024
On 3/29/24 22:06, Georgi Djakov wrote:
> Operating the TBUs (Translation Buffer Units) from Linux on Qualcomm
> platforms can help with debugging context faults. To help with that,
> the TBUs can run ATOS (Address Translation Operations) to manually
> trigger address translation of IOVA to physical address in hardware
> and provide more details when a context fault happens.
>
> The driver will control the resources needed by the TBU to allow
> running the debug operations such as ATOS, check for outstanding
> transactions, do snapshot capture etc.
>
> Signed-off-by: Georgi Djakov <quic_c_gdjako at quicinc.com>
> ---
> drivers/iommu/Kconfig | 9 +
> drivers/iommu/arm/arm-smmu/Makefile | 1 +
> .../iommu/arm/arm-smmu/arm-smmu-qcom-tbu.c | 372 ++++++++++++++++++
> drivers/iommu/arm/arm-smmu/arm-smmu-qcom.h | 2 +
> drivers/iommu/arm/arm-smmu/arm-smmu.h | 2 +
> 5 files changed, 386 insertions(+)
> create mode 100644 drivers/iommu/arm/arm-smmu/arm-smmu-qcom-tbu.c
>
> diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
> index 0af39bbbe3a3..b699e88f42c5 100644
> --- a/drivers/iommu/Kconfig
> +++ b/drivers/iommu/Kconfig
> @@ -374,6 +374,15 @@ config ARM_SMMU_QCOM
> When running on a Qualcomm platform that has the custom variant
> of the ARM SMMU, this needs to be built into the SMMU driver.
>
> +config ARM_SMMU_QCOM_TBU
> + bool "Qualcomm TBU driver"
> + depends on ARM_SMMU_QCOM
> + help
> + The SMMUs on Qualcomm platforms may include Translation Buffer
> + Units (TBUs) for each master. Enabling support for these units
> + allows to operate the TBUs and obtain additional information
> + when debugging memory management issues like context faults.
> +
> config ARM_SMMU_QCOM_DEBUG
> bool "ARM SMMU QCOM implementation defined debug support"
> depends on ARM_SMMU_QCOM
> diff --git a/drivers/iommu/arm/arm-smmu/Makefile b/drivers/iommu/arm/arm-smmu/Makefile
> index 2a5a95e8e3f9..c35ff78fcfd5 100644
> --- a/drivers/iommu/arm/arm-smmu/Makefile
> +++ b/drivers/iommu/arm/arm-smmu/Makefile
> @@ -3,4 +3,5 @@ obj-$(CONFIG_QCOM_IOMMU) += qcom_iommu.o
> obj-$(CONFIG_ARM_SMMU) += arm_smmu.o
> arm_smmu-objs += arm-smmu.o arm-smmu-impl.o arm-smmu-nvidia.o
> arm_smmu-$(CONFIG_ARM_SMMU_QCOM) += arm-smmu-qcom.o
> +arm_smmu-$(CONFIG_ARM_SMMU_QCOM_TBU) += arm-smmu-qcom-tbu.o
> arm_smmu-$(CONFIG_ARM_SMMU_QCOM_DEBUG) += arm-smmu-qcom-debug.o
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-tbu.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-tbu.c
> new file mode 100644
> index 000000000000..e3202ed89566
> --- /dev/null
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-tbu.c
> @@ -0,0 +1,372 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
> + */
> +
> +#include <linux/interconnect.h>
> +#include <linux/iopoll.h>
> +#include <linux/list.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/mutex.h>
> +#include <linux/platform_device.h>
> +#include <linux/spinlock.h>
> +
> +#include "arm-smmu.h"
> +#include "arm-smmu-qcom.h"
> +
> +#define TBU_DBG_TIMEOUT_US 100
> +#define DEBUG_AXUSER_REG 0x30
> +#define DEBUG_AXUSER_CDMID GENMASK_ULL(43, 36)
> +#define DEBUG_AXUSER_CDMID_VAL 0xff
> +#define DEBUG_PAR_REG 0x28
> +#define DEBUG_PAR_FAULT_VAL BIT(0)
> +#define DEBUG_PAR_PA GENMASK_ULL(47, 12)
> +#define DEBUG_SID_HALT_REG 0x0
> +#define DEBUG_SID_HALT_VAL BIT(16)
> +#define DEBUG_SID_HALT_SID GENMASK(9, 0)
> +#define DEBUG_SR_HALT_ACK_REG 0x20
> +#define DEBUG_SR_HALT_ACK_VAL BIT(1)
> +#define DEBUG_SR_ECATS_RUNNING_VAL BIT(0)
> +#define DEBUG_TXN_AXCACHE GENMASK(5, 2)
> +#define DEBUG_TXN_AXPROT GENMASK(8, 6)
> +#define DEBUG_TXN_AXPROT_PRIV 0x1
> +#define DEBUG_TXN_AXPROT_NSEC 0x2
> +#define DEBUG_TXN_TRIGG_REG 0x18
> +#define DEBUG_TXN_TRIGGER BIT(0)
> +#define DEBUG_VA_ADDR_REG 0x8
> +
> +static LIST_HEAD(tbu_list);
> +static DEFINE_MUTEX(tbu_list_lock);
> +static DEFINE_SPINLOCK(atos_lock);
> +
> +struct qcom_tbu {
> + struct device *dev;
> + struct device_node *smmu_np;
> + u32 sid_range[2];
> + struct list_head list;
> + struct clk *clk;
> + struct icc_path *path;
> + void __iomem *base;
> + spinlock_t halt_lock; /* multiple halt or resume can't execute concurrently */
> + int halt_count;
> +};
> +
> +static struct qcom_smmu *to_qcom_smmu(struct arm_smmu_device *smmu)
> +{
> + return container_of(smmu, struct qcom_smmu, smmu);
> +}
> +
> +static struct qcom_tbu *qcom_find_tbu(struct qcom_smmu *qsmmu, u32 sid)
> +{
> + struct qcom_tbu *tbu;
> + u32 start, end;
> +
> + mutex_lock(&tbu_list_lock);
#include <linux/cleanup.h>
guard(mutex)(&tbu_list_lock);
and remove the unlocks
similarly for the spinlocks below
Konrad
More information about the linux-arm-kernel
mailing list