From: Erik Gilling Date: Wed, 15 Sep 2010 21:37:10 +0000 (-0700) Subject: video: tegra: add channel command fifo debugging support X-Git-Tag: firefly_0821_release~9834^2~558 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=b72ee3bd9f23800042129cd4b14212e34a33439c;p=firefly-linux-kernel-4.4.55.git video: tegra: add channel command fifo debugging support Change-Id: Iaab4b04aec8feb61000e5423ea32811cca007444 Signed-off-by: Erik Gilling --- diff --git a/drivers/video/tegra/host/Makefile b/drivers/video/tegra/host/Makefile index 6357c8835585..c13f8348ed9c 100644 --- a/drivers/video/tegra/host/Makefile +++ b/drivers/video/tegra/host/Makefile @@ -7,6 +7,7 @@ nvhost-objs = \ nvhost_channel.o \ nvhost_3dctx.o \ dev.o \ - bus.o + bus.o \ + debug.o obj-$(CONFIG_TEGRA_GRHOST) += nvhost.o diff --git a/drivers/video/tegra/host/debug.c b/drivers/video/tegra/host/debug.c new file mode 100644 index 000000000000..c2dfe3156df3 --- /dev/null +++ b/drivers/video/tegra/host/debug.c @@ -0,0 +1,232 @@ +/* + * drivers/video/tegra/dc/dc.c + * + * Copyright (C) 2010 Google, Inc. + * Author: Erik Gilling + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include + +#include + +#include "dev.h" + +#ifdef CONFIG_DEBUG_FS + +enum { + NVHOST_DBG_STATE_CMD = 0, + NVHOST_DBG_STATE_DATA = 1, +}; + +static int nvhost_debug_handle_cmd(struct seq_file *s, u32 val, int *count) +{ + unsigned mask; + unsigned subop; + + switch (val >> 28) { + case 0x0: + mask = val & 0x3f; + if (mask) { + seq_printf(s, "SETCL(class=%03x, offset=%03x, mask=%02x, [", + val >> 6 & 0x3ff, val >> 16 & 0xfff, mask); + *count = hweight8(mask); + return NVHOST_DBG_STATE_DATA; + } else { + seq_printf(s, "SETCL(class=%03x)\n", val >> 6 & 0x3ff); + return NVHOST_DBG_STATE_CMD; + } + + case 0x1: + seq_printf(s, "INCR(offset=%03x, [", val >> 16 & 0x3ff); + *count = val & 0xffff; + return NVHOST_DBG_STATE_DATA; + + case 0x2: + seq_printf(s, "NOMINCR(offset=%03x, [", val >> 16 & 0x3ff); + *count = val & 0xffff; + return NVHOST_DBG_STATE_DATA; + + case 0x3: + mask = val & 0xffff; + seq_printf(s, "MASK(offset=%03x, mask=%03x, [", + val >> 16 & 0x3ff, mask); + *count = hweight16(mask); + return NVHOST_DBG_STATE_DATA; + + case 0x4: + seq_printf(s, "IMM(offset=%03x, data=%03x)\n", + val >> 16 & 0x3ff, val & 0xffff); + return NVHOST_DBG_STATE_CMD; + + case 0x5: + seq_printf(s, "RESTART(offset=%08x)\n", val << 4); + return NVHOST_DBG_STATE_CMD; + + case 0x6: + seq_printf(s, "GATHER(offset=%03x, insert=%d, type=%d, count=%04x, addr=[", + val >> 16 & 0x3ff, val >> 15 & 0x1, val >> 15 & 0x1, + val & 0x3fff); + *count = 1; + return NVHOST_DBG_STATE_DATA; + + case 0xe: + subop = val >> 24 & 0xf; + if (subop == 0) + seq_printf(s, "ACQUIRE_MLOCK(index=%d)\n", val & 0xff); + else if (subop == 1) + seq_printf(s, "RELEASE_MLOCK(index=%d)\n", val & 0xff); + else + seq_printf(s, "EXTEND_UNKNOWN(%08x)\n", val); + + return NVHOST_DBG_STATE_CMD; + + case 0xf: + seq_printf(s, "DONE()\n"); + return NVHOST_DBG_STATE_CMD; + + default: + return NVHOST_DBG_STATE_CMD; + } +} + +static int nvhost_debug_show(struct seq_file *s, void *unused) +{ + struct nvhost_master *m = s->private; + int i; + + nvhost_module_busy(&m->mod); + + for (i = 0; i < NVHOST_NUMCHANNELS; i++) { + void __iomem *regs = m->channels[i].aperture; + u32 dmaput, dmaget, dmactrl; + u32 cbstat, cbread; + u32 fifostat; + u32 val, base; + unsigned start, end; + unsigned wr_ptr, rd_ptr; + int state; + int count = 0; + + dmaput = readl(regs + HOST1X_CHANNEL_DMAPUT); + dmaget = readl(regs + HOST1X_CHANNEL_DMAGET); + dmactrl = readl(regs + HOST1X_CHANNEL_DMACTRL); + cbread = readl(m->aperture + HOST1X_SYNC_CBREAD(i)); + cbstat = readl(m->aperture + HOST1X_SYNC_CBSTAT(i)); + + if (dmactrl != 0x0 || !m->channels[i].cdma.push_buffer.mapped) { + seq_printf(s, "%d: inactive\n\n", i); + continue; + } + + switch (cbstat) { + case 0x00010008: + seq_printf(s, "%d: waiting on syncpt %d val %d\n", + i, cbread >> 24, cbread & 0xffffff); + break; + + case 0x00010009: + base = cbread >> 15 & 0xf; + + val = readl(m->aperture + HOST1X_SYNC_SYNCPT_BASE(base)) & 0xffff; + val += cbread & 0xffff; + + seq_printf(s, "%d: waiting on syncpt %d val %d\n", + i, cbread >> 24, val); + break; + + default: + seq_printf(s, "%d: active class %02x, offset %04x, val %08x\n", + i, cbstat >> 16, cbstat & 0xffff, cbread); + break; + } + + fifostat = readl(regs + HOST1X_CHANNEL_FIFOSTAT); + if ((fifostat & 1 << 10) == 0 ) { + + writel(0x0, m->aperture + HOST1X_SYNC_CFPEEK_CTRL); + writel(1 << 31 | i << 16, m->aperture + HOST1X_SYNC_CFPEEK_CTRL); + rd_ptr = readl(m->aperture + HOST1X_SYNC_CFPEEK_PTRS) & 0x1ff; + wr_ptr = readl(m->aperture + HOST1X_SYNC_CFPEEK_PTRS) >> 16 & 0x1ff; + + start = readl(m->aperture + HOST1X_SYNC_CF_SETUP(i)) & 0x1ff; + end = (readl(m->aperture + HOST1X_SYNC_CF_SETUP(i)) >> 16) & 0x1ff; + + state = NVHOST_DBG_STATE_CMD; + + do { + writel(0x0, m->aperture + HOST1X_SYNC_CFPEEK_CTRL); + writel(1 << 31 | i << 16 | rd_ptr, m->aperture + HOST1X_SYNC_CFPEEK_CTRL); + val = readl(m->aperture + HOST1X_SYNC_CFPEEK_READ); + + switch (state) { + case NVHOST_DBG_STATE_CMD: + seq_printf(s, "%d: %08x:", i, val); + + state = nvhost_debug_handle_cmd(s, val, &count); + if (state == NVHOST_DBG_STATE_DATA && count == 0) { + state = NVHOST_DBG_STATE_CMD; + seq_printf(s, "])\n"); + } + break; + + case NVHOST_DBG_STATE_DATA: + count--; + seq_printf(s, "%08x%s", val, count > 0 ? ", " : "])\n"); + if (count == 0) + state = NVHOST_DBG_STATE_CMD; + break; + } + + if (rd_ptr == end) + rd_ptr = start; + else + rd_ptr++; + + + } while (rd_ptr != wr_ptr); + + if (state == NVHOST_DBG_STATE_DATA) + seq_printf(s, ", ...])\n"); + } + seq_printf(s, "\n"); + } + + nvhost_module_idle(&m->mod); + return 0; +} + + +static int nvhost_debug_open(struct inode *inode, struct file *file) +{ + return single_open(file, nvhost_debug_show, inode->i_private); +} + +static const struct file_operations nvhost_debug_fops = { + .open = nvhost_debug_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +void nvhost_debug_init(struct nvhost_master *master) +{ + debugfs_create_file("tegra_host", S_IRUGO, NULL, master, &nvhost_debug_fops); +} +#else +void nvhost_debug_add(struct nvhost_master *master) +{ +} + +#endif + diff --git a/drivers/video/tegra/host/dev.c b/drivers/video/tegra/host/dev.c index 61ccc1e1bfae..721504671bd9 100644 --- a/drivers/video/tegra/host/dev.c +++ b/drivers/video/tegra/host/dev.c @@ -700,6 +700,8 @@ static int __devinit nvhost_probe(struct platform_device *pdev) nvhost_bus_register(host); + nvhost_debug_init(host); + dev_info(&pdev->dev, "initialized\n"); return 0; diff --git a/drivers/video/tegra/host/dev.h b/drivers/video/tegra/host/dev.h index 4529cf0ba481..fdf755f1af9f 100644 --- a/drivers/video/tegra/host/dev.h +++ b/drivers/video/tegra/host/dev.h @@ -46,4 +46,6 @@ struct nvhost_master { struct nvhost_channel channels[NVHOST_NUMCHANNELS]; }; +void nvhost_debug_init(struct nvhost_master *master); + #endif diff --git a/drivers/video/tegra/host/nvhost_hardware.h b/drivers/video/tegra/host/nvhost_hardware.h index d1d4ede89e06..f69f467dd64e 100644 --- a/drivers/video/tegra/host/nvhost_hardware.h +++ b/drivers/video/tegra/host/nvhost_hardware.h @@ -39,14 +39,24 @@ enum { #define NV_HOST1X_CHANNEL0_BASE 0 #define NV_HOST1X_CHANNEL_MAP_SIZE_BYTES 16384 -enum { - HOST1X_CHANNEL_FIFOSTAT = 0x00, - HOST1X_CHANNEL_INDDATA = 0x0c, - HOST1X_CHANNEL_DMASTART = 0x14, - HOST1X_CHANNEL_DMAPUT = 0x18, - HOST1X_CHANNEL_DMAEND = 0x20, - HOST1X_CHANNEL_DMACTRL = 0x24 -}; + +#define HOST1X_CHANNEL_FIFOSTAT 0x00 +#define HOST1X_CHANNEL_INDDATA 0x0c +#define HOST1X_CHANNEL_DMASTART 0x14 +#define HOST1X_CHANNEL_DMAPUT 0x18 +#define HOST1X_CHANNEL_DMAGET 0x1c +#define HOST1X_CHANNEL_DMAEND 0x20 +#define HOST1X_CHANNEL_DMACTRL 0x24 + +#define HOST1X_SYNC_CF_SETUP(x) (0x3080 + (4 * (x))) + +#define HOST1X_SYNC_SYNCPT_BASE(x) (0x3600 + (4 * (x))) + +#define HOST1X_SYNC_CBREAD(x) (0x3720 + (4 * (x))) +#define HOST1X_SYNC_CFPEEK_CTRL 0x374c +#define HOST1X_SYNC_CFPEEK_READ 0x3750 +#define HOST1X_SYNC_CFPEEK_PTRS 0x3754 +#define HOST1X_SYNC_CBSTAT(x) (0x3758 + (4 * (x))) static inline unsigned nvhost_channel_fifostat_outfentries(u32 reg) {