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

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

Merge "iommu: arm-smmu: update access to SMMU TCU testbus registers with scm call"

parents 20dce713 f83ed5b3
Loading
Loading
Loading
Loading
+42 −33
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2020, The Linux Foundation. All rights reserved.
 */

#include <linux/kernel.h>
@@ -8,6 +8,7 @@
#include <linux/device.h>
#include "arm-smmu-regs.h"
#include "arm-smmu-debug.h"
#include <soc/qcom/scm.h>

u32 arm_smmu_debug_tbu_testbus_select(void __iomem *tbu_base,
		void __iomem *tcu_base, u32 testbus_version,
@@ -43,33 +44,39 @@ u32 arm_smmu_debug_tbu_testbus_output(void __iomem *tbu_base,
	return readl_relaxed(tbu_base + offset);
}

u32 arm_smmu_debug_tcu_testbus_select(void __iomem *base,
u32 arm_smmu_debug_tcu_testbus_select(phys_addr_t phys_addr,
		void __iomem *tcu_base, enum tcu_testbus testbus,
		bool write, u32 val)
{
	int offset;

	if (testbus == CLK_TESTBUS) {
		base = tcu_base;
		offset = ARM_SMMU_TESTBUS_SEL_HLOS1_NS;
		if (write) {
			writel_relaxed(val, tcu_base + offset);
			/* Make sure tcu select register is written to */
			wmb();
		} else {
		offset = ARM_SMMU_TESTBUS_SEL;
			return readl_relaxed(tcu_base + offset);
		}

	} else {
		offset = ARM_SMMU_TESTBUS_SEL;
		if (write) {
		writel_relaxed(val, base + offset);
			scm_io_write((phys_addr + offset), val);
			/* Make sure tcu select register is written to */
			wmb();
		} else {
		return readl_relaxed(base + offset);
			return scm_io_read(phys_addr + offset);
		}
	}


	return 0;
}

u32 arm_smmu_debug_tcu_testbus_output(void __iomem *base)
u32 arm_smmu_debug_tcu_testbus_output(phys_addr_t phys_addr)
{
	return readl_relaxed(base + ARM_SMMU_TESTBUS);
	return scm_io_read(phys_addr + ARM_SMMU_TESTBUS);
}

static void arm_smmu_debug_dump_tbu_qns4_testbus(struct device *dev,
@@ -157,7 +164,7 @@ void arm_smmu_debug_dump_tbu_testbus(struct device *dev, void __iomem *tbu_base,
}

static void arm_smmu_debug_program_tcu_testbus(struct device *dev,
		void __iomem *base, void __iomem *tcu_base,
		phys_addr_t phys_addr, void __iomem *tcu_base,
		unsigned long mask, int start, int end, int shift,
		bool print)
{
@@ -165,62 +172,64 @@ static void arm_smmu_debug_program_tcu_testbus(struct device *dev,
	int i;

	for (i = start; i < end; i++) {
		reg = arm_smmu_debug_tcu_testbus_select(base, tcu_base,
		reg = arm_smmu_debug_tcu_testbus_select(phys_addr, tcu_base,
				PTW_AND_CACHE_TESTBUS, READ, 0);
		reg &= mask;
		reg |= i << shift;
		arm_smmu_debug_tcu_testbus_select(base, tcu_base,
		arm_smmu_debug_tcu_testbus_select(phys_addr, tcu_base,
				PTW_AND_CACHE_TESTBUS, WRITE, reg);
		if (print)
			dev_info(dev, "testbus_sel: 0x%lx Index: %d val: 0x%lx\n",
				 arm_smmu_debug_tcu_testbus_select(base,
				 tcu_base, PTW_AND_CACHE_TESTBUS, READ, 0),
				 i, arm_smmu_debug_tcu_testbus_output(base));
				 arm_smmu_debug_tcu_testbus_select(phys_addr,
				 tcu_base, PTW_AND_CACHE_TESTBUS, READ, 0), i,
				 arm_smmu_debug_tcu_testbus_output(phys_addr));
	}
}

void arm_smmu_debug_dump_tcu_testbus(struct device *dev, void __iomem *base,
void arm_smmu_debug_dump_tcu_testbus(struct device *dev, phys_addr_t phys_addr,
			void __iomem *tcu_base,	int tcu_testbus_sel)
{
	int i;

	if (tcu_testbus_sel & TCU_CACHE_TESTBUS_SEL) {
		dev_info(dev, "Dumping TCU cache testbus:\n");
		arm_smmu_debug_program_tcu_testbus(dev, base, tcu_base,
		arm_smmu_debug_program_tcu_testbus(dev, phys_addr, tcu_base,
				TCU_CACHE_TESTBUS, 0, 1, 0, false);
		arm_smmu_debug_program_tcu_testbus(dev, base, tcu_base,
		arm_smmu_debug_program_tcu_testbus(dev, phys_addr, tcu_base,
				~GENMASK(7, 0), 0, TCU_CACHE_LOOKUP_QUEUE_SIZE,
				2, true);
	}

	if (tcu_testbus_sel & TCU_PTW_TESTBUS_SEL) {
		dev_info(dev, "Dumping TCU PTW test bus:\n");
		arm_smmu_debug_program_tcu_testbus(dev, base, tcu_base, 1,
		arm_smmu_debug_program_tcu_testbus(dev, phys_addr, tcu_base, 1,
				TCU_PTW_TESTBUS, TCU_PTW_TESTBUS + 1, 0, false);

		arm_smmu_debug_program_tcu_testbus(dev, base, tcu_base,
		arm_smmu_debug_program_tcu_testbus(dev, phys_addr, tcu_base,
				~GENMASK(7, 2), 0, TCU_PTW_INTERNAL_STATES,
				2, true);

		for (i = TCU_PTW_QUEUE_START;
			i < TCU_PTW_QUEUE_START + TCU_PTW_QUEUE_SIZE; ++i) {
			arm_smmu_debug_program_tcu_testbus(dev, base, tcu_base,
					~GENMASK(7, 0), i, i + 1, 2, true);
			arm_smmu_debug_program_tcu_testbus(dev, base, tcu_base,
					~GENMASK(1, 0), TCU_PTW_TESTBUS_SEL2,
			arm_smmu_debug_program_tcu_testbus(dev, phys_addr,
					tcu_base, ~GENMASK(7, 0), i, i + 1, 2,
					true);
			arm_smmu_debug_program_tcu_testbus(dev, phys_addr,
					tcu_base, ~GENMASK(1, 0),
					TCU_PTW_TESTBUS_SEL2,
					TCU_PTW_TESTBUS_SEL2 + 1, 0, false);
			dev_info(dev, "testbus_sel: 0x%lx Index: %d val: 0x%lx\n",
				 arm_smmu_debug_tcu_testbus_select(base,
				 tcu_base, PTW_AND_CACHE_TESTBUS, READ, 0),
				 i, arm_smmu_debug_tcu_testbus_output(base));
				 arm_smmu_debug_tcu_testbus_select(phys_addr,
				 tcu_base, PTW_AND_CACHE_TESTBUS, READ, 0), i,
				 arm_smmu_debug_tcu_testbus_output(phys_addr));
		}
	}

	/* program ARM_SMMU_TESTBUS_SEL_HLOS1_NS to select TCU clk testbus*/
	arm_smmu_debug_tcu_testbus_select(base, tcu_base,
	arm_smmu_debug_tcu_testbus_select(phys_addr, tcu_base,
			CLK_TESTBUS, WRITE, TCU_CLK_TESTBUS_SEL);
	dev_info(dev, "Programming Tcu clk gate controller: testbus_sel: 0x%lx\n",
		arm_smmu_debug_tcu_testbus_select(base, tcu_base,
		arm_smmu_debug_tcu_testbus_select(phys_addr, tcu_base,
						CLK_TESTBUS, READ, 0));
}

+8 −8
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2020, The Linux Foundation. All rights reserved.
 */

#define ARM_SMMU_TESTBUS_SEL			0x25E4
@@ -65,14 +65,14 @@ u32 arm_smmu_debug_tbu_testbus_select(void __iomem *tbu_base,
		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,
u32 arm_smmu_debug_tcu_testbus_select(phys_addr_t phys_addr,
		void __iomem *tcu_base, enum tcu_testbus testbus,
		bool write, u32 val);
u32 arm_smmu_debug_tcu_testbus_output(void __iomem *base);
u32 arm_smmu_debug_tcu_testbus_output(phys_addr_t phys_addr);
void arm_smmu_debug_dump_tbu_testbus(struct device *dev, void __iomem *tbu_base,
		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 arm_smmu_debug_dump_tcu_testbus(struct device *dev, phys_addr_t phys_addr,
			void __iomem *tcu_base, int tcu_testbus_sel);
void arm_smmu_debug_set_tnx_tcr_cntl(void __iomem *tbu_base, u64 val);
unsigned long arm_smmu_debug_get_tnx_tcr_cntl(void __iomem *tbu_base);
@@ -94,12 +94,12 @@ 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,
u32 arm_smmu_debug_tcu_testbus_select(phys_addr_t phys_addr,
		void __iomem *tcu_base,	enum tcu_testbus testbus,
		bool write, u32 val)
{
}
static inline u32 arm_smmu_debug_tcu_testbus_output(void __iomem *base)
static inline u32 arm_smmu_debug_tcu_testbus_output(phys_addr_t phys_addr)
{
}
static inline void arm_smmu_debug_dump_tbu_testbus(struct device *dev,
@@ -108,7 +108,7 @@ static inline void arm_smmu_debug_dump_tbu_testbus(struct device *dev,
{
}
static inline void arm_smmu_debug_dump_tcu_testbus(struct device *dev,
			void __iomem *base, void __iomem *tcu_base,
			phys_addr_t phys_addr, void __iomem *tcu_base,
			int tcu_testbus_sel)
{
}
+10 −9
Original line number Diff line number Diff line
@@ -1462,7 +1462,7 @@ static void arm_smmu_testbus_dump(struct arm_smmu_device *smmu, u16 sid)
							data->testbus_version);
		else
			arm_smmu_debug_dump_tcu_testbus(smmu->dev,
							ARM_SMMU_GR0(smmu),
							smmu->phys_addr,
							data->tcu_base,
							tcu_testbus_sel);
		spin_unlock(&testbus_lock);
@@ -6427,23 +6427,23 @@ static ssize_t arm_smmu_debug_testbus_read(struct file *file,

		struct arm_smmu_device *smmu = file->private_data;
		struct qsmmuv500_archdata *data = smmu->archdata;
		void __iomem *base = ARM_SMMU_GR0(smmu);
		phys_addr_t phys_addr = smmu->phys_addr;
		void __iomem *tcu_base = data->tcu_base;

		arm_smmu_power_on(smmu->pwr);

		if (ops == TESTBUS_SELECT) {
			snprintf(buf, buf_len, "TCU clk testbus sel: 0x%0x\n",
				arm_smmu_debug_tcu_testbus_select(base,
				arm_smmu_debug_tcu_testbus_select(phys_addr,
					tcu_base, CLK_TESTBUS, READ, 0));
			snprintf(buf + strlen(buf), buf_len - strlen(buf),
				 "TCU testbus sel : 0x%0x\n",
				 arm_smmu_debug_tcu_testbus_select(base,
				 arm_smmu_debug_tcu_testbus_select(phys_addr,
					 tcu_base, PTW_AND_CACHE_TESTBUS,
					 READ, 0));
		} else {
			snprintf(buf, buf_len, "0x%0x\n",
				 arm_smmu_debug_tcu_testbus_output(base));
				 arm_smmu_debug_tcu_testbus_output(phys_addr));
		}

		arm_smmu_power_off(smmu->pwr);
@@ -6465,7 +6465,7 @@ static ssize_t arm_smmu_debug_tcu_testbus_sel_write(struct file *file,
	struct arm_smmu_device *smmu = file->private_data;
	struct qsmmuv500_archdata *data = smmu->archdata;
	void __iomem *tcu_base = data->tcu_base;
	void __iomem *base = ARM_SMMU_GR0(smmu);
	phys_addr_t phys_addr = smmu->phys_addr;
	char *comma;
	char buf[100];
	u64 sel, val;
@@ -6501,11 +6501,12 @@ static ssize_t arm_smmu_debug_tcu_testbus_sel_write(struct file *file,
	arm_smmu_power_on(smmu->pwr);

	if (sel == 1)
		arm_smmu_debug_tcu_testbus_select(base,
		arm_smmu_debug_tcu_testbus_select(phys_addr,
				tcu_base, CLK_TESTBUS, WRITE, val);
	else if (sel == 2)
		arm_smmu_debug_tcu_testbus_select(base,
				tcu_base, PTW_AND_CACHE_TESTBUS, WRITE, val);
		arm_smmu_debug_tcu_testbus_select(phys_addr,
				tcu_base, PTW_AND_CACHE_TESTBUS,
				WRITE, val);

	arm_smmu_power_off(smmu->pwr);