1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  Trace commands				File: cfe_trace.c
5    *
6    *  A minimal interface for running the SB-1250 trace buffer under CFE
7    *
8    *********************************************************************
9    *
10    *  Copyright 2000,2001,2002,2003
11    *  Broadcom Corporation. All rights reserved.
12    *
13    *  This software is furnished under license and may be used and
14    *  copied only in accordance with the following terms and
15    *  conditions.  Subject to these conditions, you may download,
16    *  copy, install, use, modify and distribute modified or unmodified
17    *  copies of this software in source and/or binary form.  No title
18    *  or ownership is transferred hereby.
19    *
20    *  1) Any source code used, modified or distributed must reproduce
21    *     and retain this copyright notice and list of conditions
22    *     as they appear in the source file.
23    *
24    *  2) No right is granted to use any trade name, trademark, or
25    *     logo of Broadcom Corporation.  The "Broadcom Corporation"
26    *     name may not be used to endorse or promote products derived
27    *     from this software without the prior written permission of
28    *     Broadcom Corporation.
29    *
30    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
31    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
32    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
33    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
34    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
35    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
36    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
38    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
39    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
40    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
41    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
42    *     THE POSSIBILITY OF SUCH DAMAGE.
43    ********************************************************************* */
44
45
46#include "sbmips.h"
47#include "sb1250_regs.h"
48#include "sb1250_scd.h"
49
50#include "lib_types.h"
51#include "lib_string.h"
52#include "lib_malloc.h"
53#include "lib_printf.h"
54
55#include "ui_command.h"
56
57int ui_init_tracecmds(void);
58static int ui_cmd_tracestart(ui_cmdline_t *cmd,int argc,char *argv[]);
59static int ui_cmd_tracestop(ui_cmdline_t *cmd,int argc,char *argv[]);
60static int ui_cmd_tracefreeze(ui_cmdline_t *cmd,int argc,char *argv[]);
61static int ui_cmd_traceread(ui_cmdline_t *cmd,int argc,char *argv[]);
62
63
64int ui_init_tracecmds(void)
65{
66
67    cmd_addcmd("trace start",
68	       ui_cmd_tracestart,
69	       NULL,
70	       "Start trace buffer data collection",
71	       "trace start [n [agent]]\n\n"
72	       "Start tracing ZBbus transactions, using the n-th canned\n"
73               "trigger/filter condition\n"
74	       " n = 0: <agent>-mastered transactions\n"
75	       " n = 1: CPU0 accesses to LDT dual-hosted region\n",
76	       "");
77    cmd_addcmd("trace stop",
78	       ui_cmd_tracestop,
79	       NULL,
80	       "Stop trace buffer data collection",
81	       "trace stop\n\n"
82	       "Stop tracing ZBbus transactions",
83	       "");
84    cmd_addcmd("trace freeze",
85	       ui_cmd_tracefreeze,
86	       NULL,
87	       "Freeze trace buffer",
88	       "trace freeze\n\n"
89	       "Freeze the trace buffer",
90	       "");
91    cmd_addcmd("trace read",
92	       ui_cmd_traceread,
93	       NULL,
94	       "Read trace buffer into memory",
95	       "trace read\n\n"
96	       "Allocate a block of memory, copy the unprocessed contents\n"
97	       "of the trace buffer into it, and generate a command template\n"
98	       "for writing it to a file via TFTP.",
99	       "");
100
101    return 0;
102}
103
104#define TB_SIZE (256*48)    /* 256 entries, 384 bits/entry */
105#define ZB_AGENT_CPU0 0
106#define ZB_AGENT_CPU1 1
107#define ZB_AGENT_IOB0 2
108#define ZB_AGENT_IOB1 3
109#define ZB_AGENT_SCD  4
110#define ZB_AGENT_L2C  6
111#define ZB_AGENT_MC   7
112
113static const struct {
114    const char *id;
115    int         code;
116} agent_id[] = {
117    { "cpu0", ZB_AGENT_CPU0 },
118    { "cpu1", ZB_AGENT_CPU1 },
119    { "iob0", ZB_AGENT_IOB0 },
120    { "iob1", ZB_AGENT_IOB1 },
121    { "scd",  ZB_AGENT_SCD  },
122    { "l2c",  ZB_AGENT_L2C  },
123    { "mc",   ZB_AGENT_MC   },
124    { NULL,   0             }
125};
126
127static int
128getagentarg (const char *id, int *agent)
129{
130    int  i;
131
132    for (i = 0; agent_id[i].id != NULL; i++) {
133	if (strcmp(id, agent_id[i].id) == 0) {
134	    *agent = agent_id[i].code;
135	    return 1;
136	    }
137	}
138    return 0;
139}
140
141static int
142getaddrarg (const char *x, long *addr)
143{
144    int res;
145
146    res = 0;
147    *addr = 0;
148
149    if (x) {
150	/*
151	 * Following gdb, we make 64-bit addresses expressed as
152	 * 8-digit numbers sign extend automagically.  Saves
153	 * typing, but is very gross.
154	 */
155	int longaddr;
156
157	longaddr = strlen(x);
158	if (memcmp(x,"0x",2) == 0) longaddr -= 2;
159
160	*addr = (longaddr > 8) ? (long) xtoq(x) : (long) xtoi(x);
161	res = 1;
162	}
163
164    return res;
165}
166
167
168static int ui_cmd_tracestart(ui_cmdline_t *cmd, int argc, char *argv[])
169{
170    volatile uint64_t *tb_cfg;
171
172    tb_cfg = (volatile uint64_t *) PHYS_TO_K1(A_SCD_TRACE_CFG);
173
174    if (argc != 0) {
175        volatile uint64_t *at_down_0, *at_up_0, *at_cfg_0;
176        volatile uint64_t *tb_evt_0, *tb_evt_4;
177	volatile uint64_t *tb_seq_0, *tb_seq_4;
178	int i, n;
179	int found;
180	int agent;
181
182	/* Place holder: parse new trace spec (select an option for now) */
183
184	n = atoi(cmd_getarg(cmd,0));
185
186	at_down_0 = (volatile uint64_t *) PHYS_TO_K1(A_ADDR_TRAP_DOWN_0);
187	at_up_0   = (volatile uint64_t *) PHYS_TO_K1(A_ADDR_TRAP_UP_0);
188	at_cfg_0  = (volatile uint64_t *) PHYS_TO_K1(A_ADDR_TRAP_CFG_0);
189
190	tb_evt_0 = (volatile uint64_t *) PHYS_TO_K1(A_SCD_TRACE_EVENT_0);
191	tb_evt_4 = (volatile uint64_t *) PHYS_TO_K1(A_SCD_TRACE_EVENT_4);
192	tb_seq_0 = (volatile uint64_t *) PHYS_TO_K1(A_SCD_TRACE_SEQUENCE_0);
193	tb_seq_4 = (volatile uint64_t *) PHYS_TO_K1(A_SCD_TRACE_SEQUENCE_4);
194
195	/* Reset everything */
196	*tb_cfg = M_SCD_TRACE_CFG_RESET;
197	__asm__ __volatile__ ("sync" : : : "memory");
198
199	for (i = 0; i < 4; i++) {
200	    tb_evt_0[i] = 0;  tb_evt_4[i] = 0;
201	    tb_seq_0[i] = 0;  tb_seq_4[i] = 0;
202	}
203	__asm__ __volatile__ ("sync" : : : "memory");
204
205	switch (n) {
206	case 0:
207	    /* Filter on agent request or response */
208	    if (argc > 1)
209		found = getagentarg(cmd_getarg(cmd,1), &agent);
210	    else
211		found = 0;
212	    if (!found)
213	        agent = ZB_AGENT_IOB0;   /* temporary, for backward compat */
214
215	    tb_evt_0[0] = M_SCD_TREVT_REQID_MATCH
216	                | (M_SCD_TREVT_READ | M_SCD_TREVT_WRITE)
217	       	        | V_SCD_TREVT_REQID(agent);
218	    tb_evt_0[1] = M_SCD_TREVT_DATAID_MATCH
219	                | V_SCD_TREVT_DATAID(agent);
220
221	    tb_seq_0[0] = 0x0fff
222                        | M_SCD_TRSEQ_ASAMPLE;
223	    tb_seq_0[1] = 0x1fff
224                        | M_SCD_TRSEQ_DSAMPLE;
225	    break;
226	case 1:
227	    /* Filter on CPU accesses in LDT mirror region. */
228	    (void)getaddrarg;
229
230	    at_down_0[0] = 0xe000000000;
231	    at_up_0[0]   = 0xefffffffff;
232	    at_cfg_0[0]  = M_ATRAP_CFG_ALL;
233
234	    tb_evt_0[0] = M_SCD_TREVT_REQID_MATCH
235	                | V_SCD_TREVT_ADDR_MATCH(0x1) /* addr trap 0 */
236	                | (M_SCD_TREVT_READ | M_SCD_TREVT_WRITE)
237	                | V_SCD_TREVT_REQID(ZB_AGENT_CPU0);
238	    tb_evt_0[1] = M_SCD_TREVT_RESPID_MATCH
239	                | V_SCD_TREVT_RESPID(ZB_AGENT_IOB0);
240
241	    tb_seq_0[0] = 0x0fff
242	                | M_SCD_TRSEQ_ASAMPLE;
243	    tb_seq_0[1] = 0x1fff
244	                | M_SCD_TRSEQ_DSAMPLE;
245	    break;
246	default:
247	    break;
248	}
249
250	__asm__ __volatile__ ("sync" : : : "memory");
251printf("trace start: trace 0: %llx 1: %llx\n", tb_evt_0[0], tb_evt_0[1]);
252printf("             seq   0: %llx 1: %llx\n", tb_seq_0[0], tb_seq_0[1]);
253    }
254
255    *tb_cfg = M_SCD_TRACE_CFG_START;
256    __asm__ __volatile__ ("sync" : : : "memory");
257
258printf("trace start: cfg %llx\n", *tb_cfg);
259    return 0;
260}
261
262static int ui_cmd_tracestop(ui_cmdline_t *cmd, int argc, char *argv[])
263{
264    volatile uint64_t *tb_cfg;
265
266    tb_cfg = (volatile uint64_t *) PHYS_TO_K1(A_SCD_TRACE_CFG);
267    *tb_cfg = M_SCD_TRACE_CFG_STOP;
268    __asm__ __volatile__ ("sync" : : : "memory");
269
270printf("trace stop: cfg %llx\n", *tb_cfg);
271    return 0;
272}
273
274static int ui_cmd_tracefreeze(ui_cmdline_t *cmd, int argc, char *argv[])
275{
276    volatile uint64_t *tb_cfg;
277
278    tb_cfg = (volatile uint64_t *) PHYS_TO_K1(A_SCD_TRACE_CFG);
279    *tb_cfg = M_SCD_TRACE_CFG_FREEZE;
280    __asm__ __volatile__ ("sync" : : : "memory");
281
282printf("trace freeze: cfg %llx\n", *tb_cfg);
283    return 0;
284}
285
286/* read out trace buffer to dump to a file */
287
288static int ui_cmd_traceread(ui_cmdline_t *cmd, int argc, char *argv[])
289{
290    uint64_t *p;
291    volatile uint64_t *tb_cfg;
292    volatile uint64_t *tb_read;
293    int  i;
294
295    p = KMALLOC(TB_SIZE, 0);
296    if (!p) {
297	printf("trace read: buffer allocation failed\n");
298	return -1;
299	}
300
301    tb_cfg = (volatile uint64_t *) PHYS_TO_K1(A_SCD_TRACE_CFG);
302    tb_read = (volatile uint64_t *) PHYS_TO_K1(A_SCD_TRACE_READ);
303
304    while ((*tb_cfg & M_SCD_TRACE_CFG_FREEZE) == 0) {
305        *tb_cfg = M_SCD_TRACE_CFG_FREEZE;
306	__asm__ __volatile__ ("sync" : : : "memory");
307	}
308
309    *tb_cfg = M_SCD_TRACE_CFG_START_READ;
310    __asm__ __volatile__ ("sync" : : : "memory");
311
312    /* Loop runs backward because bundles are read out in reverse order. */
313    for (i = 256*6; i > 0; i -= 6) {
314        /* Subscripts decrease to put bundle in order. */
315	p[i-1] = *tb_read;    /* t2 hi */
316        p[i-2] = *tb_read;    /* t2 lo */
317        p[i-3] = *tb_read;    /* t1 hi */
318        p[i-4] = *tb_read;    /* t1 lo */
319        p[i-5] = *tb_read;    /* t0 hi */
320        p[i-6] = *tb_read;    /* t0 lo */
321	}
322
323    printf("save hardy:ehs/sample.trace %p 0x%lx\n", p, TB_SIZE);
324
325    return 0;
326}
327