xref: /linux/drivers/gpu/host1x/hw/debug_hw_1x01.c (revision 3d0fe49454652117522f60bfbefb978ba0e5300b)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2010 Google, Inc.
4  * Author: Erik Gilling <konkers@android.com>
5  *
6  * Copyright (C) 2011-2013 NVIDIA Corporation
7  */
8 
9 #include "../dev.h"
10 #include "../debug.h"
11 #include "../cdma.h"
12 #include "../channel.h"
13 
14 static void host1x_debug_show_channel_cdma(struct host1x *host,
15 					   struct host1x_channel *ch,
16 					   struct output *o)
17 {
18 	struct host1x_cdma *cdma = &ch->cdma;
19 	dma_addr_t dmastart, dmaend;
20 	u32 dmaput, dmaget, dmactrl;
21 	u32 cbstat, cbread;
22 	u32 val, base, baseval;
23 
24 	dmastart = host1x_ch_readl(ch, HOST1X_CHANNEL_DMASTART);
25 	dmaend = host1x_ch_readl(ch, HOST1X_CHANNEL_DMAEND);
26 	dmaput = host1x_ch_readl(ch, HOST1X_CHANNEL_DMAPUT);
27 	dmaget = host1x_ch_readl(ch, HOST1X_CHANNEL_DMAGET);
28 	dmactrl = host1x_ch_readl(ch, HOST1X_CHANNEL_DMACTRL);
29 	cbread = host1x_sync_readl(host, HOST1X_SYNC_CBREAD(ch->id));
30 	cbstat = host1x_sync_readl(host, HOST1X_SYNC_CBSTAT(ch->id));
31 
32 	host1x_debug_output(o, "%u-%s: ", ch->id, dev_name(ch->dev));
33 
34 	if (HOST1X_CHANNEL_DMACTRL_DMASTOP_V(dmactrl) ||
35 	    !ch->cdma.push_buffer.mapped) {
36 		host1x_debug_output(o, "inactive\n\n");
37 		return;
38 	}
39 
40 	if (HOST1X_SYNC_CBSTAT_CBCLASS_V(cbstat) == HOST1X_CLASS_HOST1X &&
41 	    HOST1X_SYNC_CBSTAT_CBOFFSET_V(cbstat) ==
42 			HOST1X_UCLASS_WAIT_SYNCPT)
43 		host1x_debug_output(o, "waiting on syncpt %d val %d\n",
44 				    cbread >> 24, cbread & 0xffffff);
45 	else if (HOST1X_SYNC_CBSTAT_CBCLASS_V(cbstat) ==
46 				HOST1X_CLASS_HOST1X &&
47 		 HOST1X_SYNC_CBSTAT_CBOFFSET_V(cbstat) ==
48 				HOST1X_UCLASS_WAIT_SYNCPT_BASE) {
49 		base = (cbread >> 16) & 0xff;
50 		baseval =
51 			host1x_sync_readl(host, HOST1X_SYNC_SYNCPT_BASE(base));
52 		val = cbread & 0xffff;
53 		host1x_debug_output(o, "waiting on syncpt %d val %d (base %d = %d; offset = %d)\n",
54 				    cbread >> 24, baseval + val, base,
55 				    baseval, val);
56 	} else
57 		host1x_debug_output(o, "active class %02x, offset %04x, val %08x\n",
58 				    HOST1X_SYNC_CBSTAT_CBCLASS_V(cbstat),
59 				    HOST1X_SYNC_CBSTAT_CBOFFSET_V(cbstat),
60 				    cbread);
61 
62 	host1x_debug_output(o, "DMASTART %pad, DMAEND %pad\n", &dmastart, &dmaend);
63 	host1x_debug_output(o, "DMAPUT %08x DMAGET %08x DMACTL %08x\n",
64 			    dmaput, dmaget, dmactrl);
65 	host1x_debug_output(o, "CBREAD %08x CBSTAT %08x\n", cbread, cbstat);
66 
67 	show_channel_gathers(o, cdma);
68 	host1x_debug_output(o, "\n");
69 }
70 
71 static void host1x_debug_show_channel_fifo(struct host1x *host,
72 					   struct host1x_channel *ch,
73 					   struct output *o)
74 {
75 	u32 val, rd_ptr, wr_ptr, start, end;
76 	unsigned int data_count = 0;
77 
78 	host1x_debug_output(o, "%u: fifo:\n", ch->id);
79 
80 	val = host1x_ch_readl(ch, HOST1X_CHANNEL_FIFOSTAT);
81 	host1x_debug_output(o, "FIFOSTAT %08x\n", val);
82 	if (HOST1X_CHANNEL_FIFOSTAT_CFEMPTY_V(val)) {
83 		host1x_debug_output(o, "[empty]\n");
84 		return;
85 	}
86 
87 	host1x_sync_writel(host, 0x0, HOST1X_SYNC_CFPEEK_CTRL);
88 	host1x_sync_writel(host, HOST1X_SYNC_CFPEEK_CTRL_ENA_F(1) |
89 			   HOST1X_SYNC_CFPEEK_CTRL_CHANNR_F(ch->id),
90 			   HOST1X_SYNC_CFPEEK_CTRL);
91 
92 	val = host1x_sync_readl(host, HOST1X_SYNC_CFPEEK_PTRS);
93 	rd_ptr = HOST1X_SYNC_CFPEEK_PTRS_CF_RD_PTR_V(val);
94 	wr_ptr = HOST1X_SYNC_CFPEEK_PTRS_CF_WR_PTR_V(val);
95 
96 	val = host1x_sync_readl(host, HOST1X_SYNC_CF_SETUP(ch->id));
97 	start = HOST1X_SYNC_CF_SETUP_BASE_V(val);
98 	end = HOST1X_SYNC_CF_SETUP_LIMIT_V(val);
99 
100 	do {
101 		host1x_sync_writel(host, 0x0, HOST1X_SYNC_CFPEEK_CTRL);
102 		host1x_sync_writel(host, HOST1X_SYNC_CFPEEK_CTRL_ENA_F(1) |
103 				   HOST1X_SYNC_CFPEEK_CTRL_CHANNR_F(ch->id) |
104 				   HOST1X_SYNC_CFPEEK_CTRL_ADDR_F(rd_ptr),
105 				   HOST1X_SYNC_CFPEEK_CTRL);
106 		val = host1x_sync_readl(host, HOST1X_SYNC_CFPEEK_READ);
107 
108 		if (!data_count) {
109 			host1x_debug_output(o, "%08x: ", val);
110 			data_count = show_channel_command(o, val, NULL);
111 		} else {
112 			host1x_debug_cont(o, "%08x%s", val,
113 					  data_count > 1 ? ", " : "])\n");
114 			data_count--;
115 		}
116 
117 		if (rd_ptr == end)
118 			rd_ptr = start;
119 		else
120 			rd_ptr++;
121 	} while (rd_ptr != wr_ptr);
122 
123 	if (data_count)
124 		host1x_debug_cont(o, ", ...])\n");
125 	host1x_debug_output(o, "\n");
126 
127 	host1x_sync_writel(host, 0x0, HOST1X_SYNC_CFPEEK_CTRL);
128 }
129 
130 static void host1x_debug_show_mlocks(struct host1x *host, struct output *o)
131 {
132 	unsigned int i;
133 
134 	host1x_debug_output(o, "---- mlocks ----\n");
135 
136 	for (i = 0; i < host1x_syncpt_nb_mlocks(host); i++) {
137 		u32 owner =
138 			host1x_sync_readl(host, HOST1X_SYNC_MLOCK_OWNER(i));
139 		if (HOST1X_SYNC_MLOCK_OWNER_CH_OWNS_V(owner))
140 			host1x_debug_output(o, "%u: locked by channel %u\n",
141 				i, HOST1X_SYNC_MLOCK_OWNER_CHID_V(owner));
142 		else if (HOST1X_SYNC_MLOCK_OWNER_CPU_OWNS_V(owner))
143 			host1x_debug_output(o, "%u: locked by cpu\n", i);
144 		else
145 			host1x_debug_output(o, "%u: unlocked\n", i);
146 	}
147 
148 	host1x_debug_output(o, "\n");
149 }
150