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

Commit 4c764244 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: sde: Add extra debug capabilities for SDE rotator" into msm-4.9

parents 8295f19e 2d6411ad
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);