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

Commit 2d6411ad authored by Benjamin Chan's avatar Benjamin Chan Committed by Alan Kwong
Browse files

msm: sde: Add extra debug capabilities for SDE rotator



Add SDE rotator debugbus dumping capability during rotator hang panic
dump. Also add debugfs support to allow disabling auto clock gating to
VBIF and rotator clock. Increase NRT VBIF debugbus dump range from 16 to
512.

CRs-Fixed: 2027559
Change-Id: I49beb9342042b4b613177fd5931ed0f0e3f6731d
Signed-off-by: default avatarBenjamin Chan <bkchan@codeaurora.org>
parent cbac0b3a
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -140,6 +140,18 @@ struct sde_smmu_client {
	int domain;
};

/*
 * struct sde_rot_debug_bus: rotator debugbus header structure
 * @wr_addr: write address for debugbus controller
 * @block_id: rotator debugbus block id
 * @test_id: rotator debugbus test id
 */
struct sde_rot_debug_bus {
	u32 wr_addr;
	u32 block_id;
	u32 test_id;
};

struct sde_rot_vbif_debug_bus {
	u32 disable_bus_addr;
	u32 block_bus_addr;
@@ -191,6 +203,8 @@ struct sde_rot_data_type {

	struct sde_rot_vbif_debug_bus *nrt_vbif_dbg_bus;
	u32 nrt_vbif_dbg_bus_size;
	struct sde_rot_debug_bus *rot_dbg_bus;
	u32 rot_dbg_bus_size;

	struct sde_rot_regdump *regdump;
	u32 regdump_size;
@@ -199,6 +213,8 @@ struct sde_rot_data_type {
	int sec_cam_en;

	struct ion_client *iclient;

	bool clk_always_on;
};

int sde_rotator_base_init(struct sde_rot_data_type **pmdata,
+110 −5
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#define SDE_EVTLOG_DEFAULT_PANIC 1
#define SDE_EVTLOG_DEFAULT_REGDUMP SDE_ROT_DBG_DUMP_IN_MEM
#define SDE_EVTLOG_DEFAULT_VBIF_DBGBUSDUMP SDE_ROT_DBG_DUMP_IN_MEM
#define SDE_EVTLOG_DEFAULT_ROT_DBGBUSDUMP SDE_ROT_DBG_DUMP_IN_MEM

/*
 * evtlog will print this number of entries when it is called through
@@ -53,6 +54,8 @@
#define GROUP_BYTES 4
#define ROW_BYTES 16

#define SDE_ROT_TEST_MASK(id, tp)	((id << 4) | (tp << 1) | BIT(0))

static DEFINE_SPINLOCK(sde_rot_xlock);

/*
@@ -86,11 +89,14 @@ struct tlog {
 * @panic_on_err - boolean indicates issue panic after EVTLOG dump
 * @enable_reg_dump - control in-log/memory dump for rotator registers
 * @enable_vbif_dbgbus_dump - control in-log/memory dump for VBIF debug bus
 * @enable_rot_dbgbus_dump - control in-log/memroy dump for rotator debug bus
 * @evtlog_dump_work - schedule work strucutre for timeout handler
 * @work_dump_reg - storage for register dump control in schedule work
 * @work_panic - storage for panic control in schedule work
 * @work_vbif_dbgbus - storage for VBIF debug bus control in schedule work
 * @work_rot_dbgbus - storage for rotator debug bus control in schedule work
 * @nrt_vbif_dbgbus_dump - memory buffer for VBIF debug bus dumping
 * @rot_dbgbus_dump - memory buffer for rotator debug bus dumping
 * @reg_dump_array - memory buffer for rotator registers dumping
 */
struct sde_rot_dbg_evtlog {
@@ -103,14 +109,88 @@ struct sde_rot_dbg_evtlog {
	u32 panic_on_err;
	u32 enable_reg_dump;
	u32 enable_vbif_dbgbus_dump;
	u32 enable_rot_dbgbus_dump;
	struct work_struct evtlog_dump_work;
	bool work_dump_reg;
	bool work_panic;
	bool work_vbif_dbgbus;
	bool work_rot_dbgbus;
	u32 *nrt_vbif_dbgbus_dump; /* address for the nrt vbif debug bus dump */
	u32 *rot_dbgbus_dump;
	u32 *reg_dump_array[SDE_ROT_DEBUG_BASE_MAX];
} sde_rot_dbg_evtlog;

static void sde_rot_dump_debug_bus(u32 bus_dump_flag, u32 **dump_mem)
{
	struct sde_rot_data_type *mdata = sde_rot_get_mdata();
	bool in_log, in_mem;
	u32 *dump_addr = NULL;
	u32 status = 0;
	struct sde_rot_debug_bus *head;
	phys_addr_t phys = 0;
	int i;
	u32 offset;
	void __iomem *base;

	in_log = (bus_dump_flag & SDE_ROT_DBG_DUMP_IN_LOG);
	in_mem = (bus_dump_flag & SDE_ROT_DBG_DUMP_IN_MEM);
	base = mdata->sde_io.base;

	if (!base || !mdata->rot_dbg_bus || !mdata->rot_dbg_bus_size)
		return;

	pr_info("======== SDE Rotator Debug bus DUMP =========\n");

	if (in_mem) {
		if (!(*dump_mem))
			*dump_mem = dma_alloc_coherent(&mdata->pdev->dev,
				mdata->rot_dbg_bus_size * 4 * sizeof(u32),
				&phys, GFP_KERNEL);

		if (*dump_mem) {
			dump_addr = *dump_mem;
			pr_info("%s: start_addr:0x%pK end_addr:0x%pK\n",
				__func__, dump_addr,
				dump_addr + (u32)mdata->rot_dbg_bus_size * 16);
		} else {
			in_mem = false;
			pr_err("dump_mem: allocation fails\n");
		}
	}

	sde_smmu_ctrl(1);

	for (i = 0; i < mdata->rot_dbg_bus_size; i++) {
		head = mdata->rot_dbg_bus + i;
		writel_relaxed(SDE_ROT_TEST_MASK(head->block_id, head->test_id),
				base + head->wr_addr);
		wmb(); /* make sure test bits were written */

		offset = head->wr_addr + 0x4;

		status = readl_relaxed(base + offset);

		if (in_log)
			pr_err("waddr=0x%x blk=%d tst=%d val=0x%x\n",
				head->wr_addr, head->block_id, head->test_id,
				status);

		if (dump_addr && in_mem) {
			dump_addr[i*4]     = head->wr_addr;
			dump_addr[i*4 + 1] = head->block_id;
			dump_addr[i*4 + 2] = head->test_id;
			dump_addr[i*4 + 3] = status;
		}

		/* Disable debug bus once we are done */
		writel_relaxed(0, base + head->wr_addr);
	}

	sde_smmu_ctrl(0);

	pr_info("========End Debug bus=========\n");
}

/*
 * sde_rot_evtlog_is_enabled - helper function for checking EVTLOG
 *                             enable/disable
@@ -518,18 +598,26 @@ static ssize_t sde_rot_evtlog_dump_write(struct file *file,
 * @dump_vbif_debug_bus: boolean indicates VBIF debug bus dump
 */
static void sde_rot_evtlog_dump_helper(bool dead, const char *panic_name,
	bool dump_rot, bool dump_vbif_debug_bus)
	bool dump_rot, bool dump_vbif_debug_bus, bool dump_rot_debug_bus)
{
	sde_rot_evtlog_dump_all();

	if (dump_rot)
		sde_rot_dump_reg_all();
	if (dump_rot_debug_bus)
		sde_rot_dump_debug_bus(
				sde_rot_dbg_evtlog.enable_rot_dbgbus_dump,
				&sde_rot_dbg_evtlog.rot_dbgbus_dump);

	if (dump_vbif_debug_bus)
		sde_rot_dump_vbif_debug_bus(
				sde_rot_dbg_evtlog.enable_vbif_dbgbus_dump,
				&sde_rot_dbg_evtlog.nrt_vbif_dbgbus_dump);

	/*
	 * Rotator registers always dump last
	 */
	if (dump_rot)
		sde_rot_dump_reg_all();

	if (dead)
		panic(panic_name);
}
@@ -544,7 +632,8 @@ static void sde_rot_evtlog_debug_work(struct work_struct *work)
		sde_rot_dbg_evtlog.work_panic,
		"evtlog_workitem",
		sde_rot_dbg_evtlog.work_dump_reg,
		sde_rot_dbg_evtlog.work_vbif_dbgbus);
		sde_rot_dbg_evtlog.work_vbif_dbgbus,
		sde_rot_dbg_evtlog.work_rot_dbgbus);
}

/*
@@ -569,6 +658,7 @@ void sde_rot_evtlog_tout_handler(bool queue, const char *name, ...)
	bool dead = false;
	bool dump_rot = false;
	bool dump_vbif_dbgbus = false;
	bool dump_rot_dbgbus = false;
	char *blk_name = NULL;
	va_list args;

@@ -590,6 +680,9 @@ void sde_rot_evtlog_tout_handler(bool queue, const char *name, ...)
		if (!strcmp(blk_name, "vbif_dbg_bus"))
			dump_vbif_dbgbus = true;

		if (!strcmp(blk_name, "rot_dbg_bus"))
			dump_rot_dbgbus = true;

		if (!strcmp(blk_name, "panic"))
			dead = true;
	}
@@ -600,10 +693,11 @@ void sde_rot_evtlog_tout_handler(bool queue, const char *name, ...)
		sde_rot_dbg_evtlog.work_panic = dead;
		sde_rot_dbg_evtlog.work_dump_reg = dump_rot;
		sde_rot_dbg_evtlog.work_vbif_dbgbus = dump_vbif_dbgbus;
		sde_rot_dbg_evtlog.work_rot_dbgbus = dump_rot_dbgbus;
		schedule_work(&sde_rot_dbg_evtlog.evtlog_dump_work);
	} else {
		sde_rot_evtlog_dump_helper(dead, name, dump_rot,
			dump_vbif_dbgbus);
			dump_vbif_dbgbus, dump_rot_dbgbus);
	}
}

@@ -836,6 +930,13 @@ static int sde_rotator_base_create_debugfs(
		return -EINVAL;
	}

	mdata->clk_always_on = false;
	if (!debugfs_create_bool("clk_always_on", 0644,
			debugfs_root, &mdata->clk_always_on)) {
		SDEROT_WARN("failed to create debugfs clk_always_on\n");
		return -EINVAL;
	}

	return 0;
}

@@ -919,12 +1020,16 @@ static int sde_rotator_evtlog_create_debugfs(
			    &sde_rot_dbg_evtlog.enable_reg_dump);
	debugfs_create_u32("vbif_dbgbus_dump", 0644, sde_rot_dbg_evtlog.evtlog,
			    &sde_rot_dbg_evtlog.enable_vbif_dbgbus_dump);
	debugfs_create_u32("rot_dbgbus_dump", 0644, sde_rot_dbg_evtlog.evtlog,
			    &sde_rot_dbg_evtlog.enable_rot_dbgbus_dump);

	sde_rot_dbg_evtlog.evtlog_enable = SDE_EVTLOG_DEFAULT_ENABLE;
	sde_rot_dbg_evtlog.panic_on_err = SDE_EVTLOG_DEFAULT_PANIC;
	sde_rot_dbg_evtlog.enable_reg_dump = SDE_EVTLOG_DEFAULT_REGDUMP;
	sde_rot_dbg_evtlog.enable_vbif_dbgbus_dump =
		SDE_EVTLOG_DEFAULT_VBIF_DBGBUSDUMP;
	sde_rot_dbg_evtlog.enable_rot_dbgbus_dump =
		SDE_EVTLOG_DEFAULT_ROT_DBGBUSDUMP;

	pr_info("evtlog_status: enable:%d, panic:%d, dump:%d\n",
			sde_rot_dbg_evtlog.evtlog_enable,
+103 −4
Original line number Diff line number Diff line
@@ -385,11 +385,95 @@ static u32 sde_hw_rotator_v4_outpixfmts[] = {
};

static struct sde_rot_vbif_debug_bus nrt_vbif_dbg_bus_r3[] = {
	{0x214, 0x21c, 16, 1, 0x10}, /* arb clients */
	{0x214, 0x21c, 16, 1, 0x200}, /* arb clients main */
	{0x214, 0x21c, 0, 12, 0x13}, /* xin blocks - axi side */
	{0x21c, 0x214, 0, 12, 0xc}, /* xin blocks - clock side */
};

static struct sde_rot_debug_bus rot_dbgbus_r3[] = {
	/*
	 * rottop - 0xA8850
	 */
	/* REGDMA */
	{ 0XA8850, 0, 0 },
	{ 0XA8850, 0, 1 },
	{ 0XA8850, 0, 2 },
	{ 0XA8850, 0, 3 },
	{ 0XA8850, 0, 4 },

	/* ROT_WB */
	{ 0XA8850, 1, 0 },
	{ 0XA8850, 1, 1 },
	{ 0XA8850, 1, 2 },
	{ 0XA8850, 1, 3 },
	{ 0XA8850, 1, 4 },
	{ 0XA8850, 1, 5 },
	{ 0XA8850, 1, 6 },
	{ 0XA8850, 1, 7 },

	/* UBWC_DEC */
	{ 0XA8850, 2, 0 },

	/* UBWC_ENC */
	{ 0XA8850, 3, 0 },

	/* ROT_FETCH_0 */
	{ 0XA8850, 4, 0 },
	{ 0XA8850, 4, 1 },
	{ 0XA8850, 4, 2 },
	{ 0XA8850, 4, 3 },
	{ 0XA8850, 4, 4 },
	{ 0XA8850, 4, 5 },
	{ 0XA8850, 4, 6 },
	{ 0XA8850, 4, 7 },

	/* ROT_FETCH_1 */
	{ 0XA8850, 5, 0 },
	{ 0XA8850, 5, 1 },
	{ 0XA8850, 5, 2 },
	{ 0XA8850, 5, 3 },
	{ 0XA8850, 5, 4 },
	{ 0XA8850, 5, 5 },
	{ 0XA8850, 5, 6 },
	{ 0XA8850, 5, 7 },

	/* ROT_FETCH_2 */
	{ 0XA8850, 6, 0 },
	{ 0XA8850, 6, 1 },
	{ 0XA8850, 6, 2 },
	{ 0XA8850, 6, 3 },
	{ 0XA8850, 6, 4 },
	{ 0XA8850, 6, 5 },
	{ 0XA8850, 6, 6 },
	{ 0XA8850, 6, 7 },

	/* ROT_FETCH_3 */
	{ 0XA8850, 7, 0 },
	{ 0XA8850, 7, 1 },
	{ 0XA8850, 7, 2 },
	{ 0XA8850, 7, 3 },
	{ 0XA8850, 7, 4 },
	{ 0XA8850, 7, 5 },
	{ 0XA8850, 7, 6 },
	{ 0XA8850, 7, 7 },

	/* ROT_FETCH_4 */
	{ 0XA8850, 8, 0 },
	{ 0XA8850, 8, 1 },
	{ 0XA8850, 8, 2 },
	{ 0XA8850, 8, 3 },
	{ 0XA8850, 8, 4 },
	{ 0XA8850, 8, 5 },
	{ 0XA8850, 8, 6 },
	{ 0XA8850, 8, 7 },

	/* ROT_UNPACK_0*/
	{ 0XA8850, 9, 0 },
	{ 0XA8850, 9, 1 },
	{ 0XA8850, 9, 2 },
	{ 0XA8850, 9, 3 },
};

static struct sde_rot_regdump sde_rot_r3_regdump[] = {
	{ "SDEROT_ROTTOP", SDE_ROT_ROTTOP_OFFSET, 0x100, SDE_ROT_REGDUMP_READ },
	{ "SDEROT_SSPP", SDE_ROT_SSPP_OFFSET, 0x200, SDE_ROT_REGDUMP_READ },
@@ -1430,7 +1514,8 @@ static u32 sde_hw_rotator_wait_done_regdma(
	sts = (status & ROT_ERROR_BIT) ? -ENODEV : 0;

	if (status & ROT_ERROR_BIT)
		SDEROT_EVTLOG_TOUT_HANDLER("rot", "vbif_dbg_bus", "panic");
		SDEROT_EVTLOG_TOUT_HANDLER("rot", "rot_dbg_bus",
				"vbif_dbg_bus", "panic");

	return sts;
}
@@ -1614,8 +1699,8 @@ void sde_hw_rotator_pre_pmevent(struct sde_rot_mgr *mgr, bool pmon)
			SDEROT_ERR(
				"Mismatch SWTS with HWTS: swts:0x%x, hwts:0x%x, regdma-sts:0x%x, rottop-sts:0x%x\n",
				swts, hwts, regdmasts, rotsts);
			SDEROT_EVTLOG_TOUT_HANDLER("rot", "vbif_dbg_bus",
					"panic");
			SDEROT_EVTLOG_TOUT_HANDLER("rot", "rot_dbg_bus",
					"vbif_dbg_bus", "panic");
		}

		/* Turn off rotator clock after checking rotator registers */
@@ -2134,6 +2219,17 @@ static int sde_hw_rotator_config(struct sde_rot_hw_resource *hw,
	SDE_VBIF_WRITE(mdata, MMSS_VBIF_NRT_VBIF_WRITE_GATHTER_EN,
			BIT(XIN_WRITEBACK));

	/*
	 * For debug purpose, disable clock gating, i.e. Clocks always on
	 */
	if (mdata->clk_always_on) {
		SDE_VBIF_WRITE(mdata, MMSS_VBIF_CLKON, 0x3);
		SDE_VBIF_WRITE(mdata, MMSS_VBIF_NRT_VBIF_CLK_FORCE_CTRL0, 0x3);
		SDE_VBIF_WRITE(mdata, MMSS_VBIF_NRT_VBIF_CLK_FORCE_CTRL1,
				0xFFFF);
		SDE_ROTREG_WRITE(rot->mdss_base, ROTTOP_CLK_CTRL, 1);
	}

	return 0;

error:
@@ -2260,6 +2356,9 @@ static int sde_rotator_hw_rev_init(struct sde_hw_rotator *rot)
	mdata->nrt_vbif_dbg_bus_size =
			ARRAY_SIZE(nrt_vbif_dbg_bus_r3);

	mdata->rot_dbg_bus = rot_dbgbus_r3;
	mdata->rot_dbg_bus_size = ARRAY_SIZE(rot_dbgbus_r3);

	mdata->regdump = sde_rot_r3_regdump;
	mdata->regdump_size = ARRAY_SIZE(sde_rot_r3_regdump);
	SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_TIMESTAMP_REG, 0);