Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e42c5b3a authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "iommu: arm-smmu: support different testbus implementations"

parents 9a1d1066 70a6dede
Loading
Loading
Loading
Loading
+64 −29
Original line number Diff line number Diff line
@@ -19,21 +19,37 @@
#include "arm-smmu-debug.h"

u32 arm_smmu_debug_tbu_testbus_select(void __iomem *tbu_base,
		void __iomem *tcu_base, u32 testbus_version,
		bool write, u32 val)
{
	void __iomem *base;
	int offset;

	if (testbus_version == 1) {
		base = tcu_base;
		offset = ARM_SMMU_TESTBUS_SEL_HLOS1_NS;
	} else {
		base = tbu_base;
		offset = DEBUG_TESTBUS_SEL_TBU;
	}

	if (write) {
		writel_relaxed(val, tbu_base + DEBUG_TESTBUS_SEL_TBU);
		writel_relaxed(val, base + offset);
		/* Make sure tbu select register is written to */
		wmb();
	} else {
		return readl_relaxed(tbu_base + DEBUG_TESTBUS_SEL_TBU);
		return readl_relaxed(base + offset);
	}
	return 0;
}

u32 arm_smmu_debug_tbu_testbus_output(void __iomem *tbu_base)
u32 arm_smmu_debug_tbu_testbus_output(void __iomem *tbu_base,
			u32 testbus_version)
{
	return readl_relaxed(tbu_base + DEBUG_TESTBUS_TBU);
	int offset = (testbus_version == 1) ?
			CLIENT_DEBUG_SR_HALT_ACK : DEBUG_TESTBUS_TBU;

	return readl_relaxed(tbu_base + offset);
}

u32 arm_smmu_debug_tcu_testbus_select(void __iomem *base,
@@ -66,67 +82,86 @@ u32 arm_smmu_debug_tcu_testbus_output(void __iomem *base)
}

static void arm_smmu_debug_dump_tbu_qns4_testbus(struct device *dev,
					void __iomem *tbu_base)
			void __iomem *tbu_base, void __iomem *tcu_base,
			u32  testbus_version)
{
	int i;
	u32 reg;

	for (i = 0 ; i < TBU_QNS4_BRIDGE_SIZE; ++i) {
		reg = arm_smmu_debug_tbu_testbus_select(tbu_base, READ, 0);
		reg = arm_smmu_debug_tbu_testbus_select(tbu_base, tcu_base,
				testbus_version, READ, 0);
		reg = (reg & ~GENMASK(4, 0)) | i << 0;
		arm_smmu_debug_tbu_testbus_select(tbu_base, WRITE, reg);
		arm_smmu_debug_tbu_testbus_select(tbu_base, tcu_base,
				testbus_version, WRITE, reg);
		dev_info(dev, "testbus_sel: 0x%lx Index: %d val: 0x%llx\n",
			arm_smmu_debug_tbu_testbus_select(tbu_base,
						READ, 0), i,
			arm_smmu_debug_tbu_testbus_output(tbu_base));
			arm_smmu_debug_tbu_testbus_select(tbu_base, tcu_base,
				testbus_version, READ, 0), i,
			arm_smmu_debug_tbu_testbus_output(tbu_base,
							testbus_version));
	}
}

static void arm_smmu_debug_program_tbu_testbus(void __iomem *tbu_base,
				void __iomem *tcu_base, u32 testbus_version,
				int tbu_testbus)
{
	u32 reg;

	reg = arm_smmu_debug_tbu_testbus_select(tbu_base, READ, 0);
	reg = (reg & ~GENMASK(7, 0)) | tbu_testbus;
	arm_smmu_debug_tbu_testbus_select(tbu_base, WRITE, reg);
	reg = arm_smmu_debug_tbu_testbus_select(tbu_base, tcu_base,
						testbus_version, READ, 0);
	if (testbus_version == 1)
		reg = (reg & ~GENMASK(9, 0));
	else
		reg = (reg & ~GENMASK(7, 0));

	reg |= tbu_testbus;
	arm_smmu_debug_tbu_testbus_select(tbu_base, tcu_base,
						testbus_version, WRITE, reg);
}

void arm_smmu_debug_dump_tbu_testbus(struct device *dev, void __iomem *tbu_base,
			int tbu_testbus_sel)
		void __iomem *tcu_base, int tbu_testbus_sel,
		u32 testbus_version)
{
	if (tbu_testbus_sel & TBU_CLK_GATE_CONTROLLER_TESTBUS_SEL) {
		dev_info(dev, "Dumping TBU clk gate controller:\n");
		arm_smmu_debug_program_tbu_testbus(tbu_base,
		arm_smmu_debug_program_tbu_testbus(tbu_base, tcu_base,
				testbus_version,
				TBU_CLK_GATE_CONTROLLER_TESTBUS);
		dev_info(dev, "testbus_sel: 0x%lx val: 0x%llx\n",
			arm_smmu_debug_tbu_testbus_select(tbu_base,
						READ, 0),
			arm_smmu_debug_tbu_testbus_output(tbu_base));
			arm_smmu_debug_tbu_testbus_select(tbu_base, tcu_base,
						testbus_version, READ, 0),
			arm_smmu_debug_tbu_testbus_output(tbu_base,
							testbus_version));
	}

	if (tbu_testbus_sel & TBU_QNS4_A2Q_TESTBUS_SEL) {
		dev_info(dev, "Dumping TBU qns4 a2q test bus:\n");
		arm_smmu_debug_program_tbu_testbus(tbu_base,
				TBU_QNS4_A2Q_TESTBUS);
		arm_smmu_debug_dump_tbu_qns4_testbus(dev, tbu_base);
		arm_smmu_debug_program_tbu_testbus(tbu_base, tcu_base,
				testbus_version, TBU_QNS4_A2Q_TESTBUS);
		arm_smmu_debug_dump_tbu_qns4_testbus(dev, tbu_base,
				tcu_base, testbus_version);
	}

	if (tbu_testbus_sel & TBU_QNS4_Q2A_TESTBUS_SEL) {
		dev_info(dev, "Dumping qns4 q2a test bus:\n");
		arm_smmu_debug_program_tbu_testbus(tbu_base,
				TBU_QNS4_Q2A_TESTBUS);
		arm_smmu_debug_dump_tbu_qns4_testbus(dev, tbu_base);
		arm_smmu_debug_program_tbu_testbus(tbu_base, tcu_base,
				testbus_version, TBU_QNS4_Q2A_TESTBUS);
		arm_smmu_debug_dump_tbu_qns4_testbus(dev, tbu_base,
				tcu_base, testbus_version);
	}

	if (tbu_testbus_sel & TBU_MULTIMASTER_QCHANNEL_TESTBUS_SEL) {
		dev_info(dev, "Dumping multi master qchannel:\n");
		arm_smmu_debug_program_tbu_testbus(tbu_base,
		arm_smmu_debug_program_tbu_testbus(tbu_base, tcu_base,
				testbus_version,
				TBU_MULTIMASTER_QCHANNEL_TESTBUS);
		dev_info(dev, "testbus_sel: 0x%lx val: 0x%llx\n",
			arm_smmu_debug_tbu_testbus_select(tbu_base,
						READ, 0),
			arm_smmu_debug_tbu_testbus_output(tbu_base));
				tcu_base, testbus_version, READ, 0),
			arm_smmu_debug_tbu_testbus_output(tbu_base,
							testbus_version));
	}
}

+13 −7
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#define ARM_SMMU_TESTBUS_SEL_HLOS1_NS		0x8
#define DEBUG_TESTBUS_SEL_TBU			0x50
#define DEBUG_TESTBUS_TBU			0x58
#define CLIENT_DEBUG_SR_HALT_ACK		0x24

#define TCU_PTW_TESTBUS				(0x1 << 8)
#define TCU_CACHE_TESTBUS			~TCU_PTW_TESTBUS
@@ -58,23 +59,28 @@ enum testbus_ops {
#ifdef CONFIG_ARM_SMMU

u32 arm_smmu_debug_tbu_testbus_select(void __iomem *tbu_base,
					bool write, u32 val);
u32 arm_smmu_debug_tbu_testbus_output(void __iomem *tbu_base);
		void __iomem *tcu_base, u32 testbus_version,
		bool write, u32 reg);
u32 arm_smmu_debug_tbu_testbus_output(void __iomem *tbu_base,
					u32 testbus_version);
u32 arm_smmu_debug_tcu_testbus_select(void __iomem *base,
		void __iomem *tcu_base, enum tcu_testbus testbus,
		bool write, u32 val);
u32 arm_smmu_debug_tcu_testbus_output(void __iomem *base);
void arm_smmu_debug_dump_tbu_testbus(struct device *dev, void __iomem *tbu_base,
			int tbu_testbus_sel);
		void __iomem *tcu_base, int tbu_testbus_sel,
		u32 testbus_version);
void arm_smmu_debug_dump_tcu_testbus(struct device *dev, void __iomem *base,
			void __iomem *tcu_base, int tcu_testbus_sel);

#else
static inline u32 arm_smmu_debug_tbu_testbus_select(void __iomem *tbu_base,
				bool write, u32 val)
		void __iomem *tcu_base,	u32 testbus_version, bool write,
		u32 val)
{
}
static inline u32 arm_smmu_debug_tbu_testbus_output(void __iomem *tbu_base)
static inline u32 arm_smmu_debug_tbu_testbus_output(void __iomem *tbu_base,
						u32 testbus_version)
{
}
u32 arm_smmu_debug_tcu_testbus_select(void __iomem *base,
@@ -86,7 +92,8 @@ static inline u32 arm_smmu_debug_tcu_testbus_output(void __iomem *base)
{
}
static inline void arm_smmu_debug_dump_tbu_testbus(struct device *dev,
			void __iomem *tbu_base, int tbu_testbus_sel)
			void __iomem *tbu_base, void __iomem *tcu_base,
			int tbu_testbus_sel, u32 testbus_version)
{
}
static inline void arm_smmu_debug_dump_tcu_testbus(struct device *dev,
@@ -95,4 +102,3 @@ static inline void arm_smmu_debug_dump_tcu_testbus(struct device *dev,
{
}
#endif
+54 −10
Original line number Diff line number Diff line
@@ -5080,6 +5080,7 @@ struct qsmmuv500_archdata {
	u32				version;
	struct actlr_setting		*actlrs;
	u32				actlr_tbl_size;
	u32				testbus_version;
};
#define get_qsmmuv500_archdata(smmu)				\
	((struct qsmmuv500_archdata *)(smmu->archdata))
@@ -5570,6 +5571,22 @@ static int qsmmuv500_read_actlr_tbl(struct arm_smmu_device *smmu)
	return 0;
}

static int qsmmuv500_get_testbus_version(struct arm_smmu_device *smmu)
{
	struct device *dev = smmu->dev;
	struct qsmmuv500_archdata *data = get_qsmmuv500_archdata(smmu);
	u32 testbus_version;
	const __be32 *cell;

	cell = of_get_property(dev->of_node, "qcom,testbus-version", NULL);
	if (!cell)
		return 0;

	testbus_version = of_read_number(cell, 1);

	data->testbus_version = testbus_version;
	return 0;
}
static ssize_t arm_smmu_debug_testbus_read(struct file *file,
		char __user *ubuf, size_t count, loff_t *offset,
		enum testbus_sel tbu, enum testbus_ops ops)
@@ -5587,16 +5604,28 @@ static ssize_t arm_smmu_debug_testbus_read(struct file *file,

	if (tbu == SEL_TBU) {
		struct qsmmuv500_tbu_device *tbu = file->private_data;
		struct arm_smmu_device *smmu = tbu->smmu;
		void __iomem *tbu_base = tbu->base;
		struct qsmmuv500_archdata *data = smmu->archdata;
		void __iomem *tcu_base = data->tcu_base;
		u32 testbus_version = data->testbus_version;
		struct arm_smmu_power_resources *pwr;
		long val;

		arm_smmu_power_on(tbu->pwr);
		if (testbus_version == 1)
			pwr = smmu->pwr;
		else
			pwr = tbu->pwr;

		arm_smmu_power_on(pwr);

		if (ops == TESTBUS_SELECT)
			val = arm_smmu_debug_tbu_testbus_select(tbu_base,
							READ, 0);
					tcu_base, testbus_version, READ, 0);
		else
			val = arm_smmu_debug_tbu_testbus_output(tbu_base);
		arm_smmu_power_off(tbu->pwr);
			val = arm_smmu_debug_tbu_testbus_output(tbu_base,
							testbus_version);
		arm_smmu_power_off(pwr);

		snprintf(buf, buf_len, "0x%0x\n", val);
	} else {
@@ -5767,6 +5796,11 @@ static ssize_t arm_smmu_debug_tbu_testbus_sel_write(struct file *file,
{
	struct qsmmuv500_tbu_device *tbu = file->private_data;
	void __iomem *tbu_base = tbu->base;
	struct arm_smmu_device *smmu = tbu->smmu;
	struct arm_smmu_power_resources *pwr;
	struct qsmmuv500_archdata *data = smmu->archdata;
	void __iomem *tcu_base = data->tcu_base;
	u32 testbus_version = data->testbus_version;
	u64 val;

	if (kstrtoull_from_user(ubuf, count, 0, &val)) {
@@ -5774,9 +5808,15 @@ static ssize_t arm_smmu_debug_tbu_testbus_sel_write(struct file *file,
		return -EINVAL;
	}

	arm_smmu_power_on(tbu->pwr);
	arm_smmu_debug_tbu_testbus_select(tbu_base, WRITE, val);
	arm_smmu_power_off(tbu->pwr);
	if (testbus_version == 1)
		pwr = smmu->pwr;
	else
		pwr = tbu->pwr;

	arm_smmu_power_on(pwr);
	arm_smmu_debug_tbu_testbus_select(tbu_base, tcu_base,
			testbus_version, WRITE, val);
	arm_smmu_power_off(pwr);

	return count;
}
@@ -5881,6 +5921,10 @@ static int qsmmuv500_arch_init(struct arm_smmu_device *smmu)
	data->version = readl_relaxed(data->tcu_base + TCU_HW_VERSION_HLOS1);
	smmu->archdata = data;

	ret = qsmmuv500_get_testbus_version(smmu);
	if (ret)
		return ret;

	qsmmuv500_tcu_testbus_init(smmu);

	if (arm_smmu_is_static_cb(smmu))