mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-11 13:27:06 +09:00
video: tegra: add channel command fifo debugging support
Change-Id: Iaab4b04aec8feb61000e5423ea32811cca007444 Signed-off-by: Erik Gilling <konkers@dirtysouth.mtv.corp.google.com>
This commit is contained in:
committed by
Colin Cross
parent
50e6eff5fb
commit
b72ee3bd9f
@@ -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
|
||||
|
||||
232
drivers/video/tegra/host/debug.c
Normal file
232
drivers/video/tegra/host/debug.c
Normal file
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* drivers/video/tegra/dc/dc.c
|
||||
*
|
||||
* Copyright (C) 2010 Google, Inc.
|
||||
* Author: Erik Gilling <konkers@android.com>
|
||||
*
|
||||
* 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 <linux/debugfs.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
#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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -46,4 +46,6 @@ struct nvhost_master {
|
||||
struct nvhost_channel channels[NVHOST_NUMCHANNELS];
|
||||
};
|
||||
|
||||
void nvhost_debug_init(struct nvhost_master *master);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user