xref: /openbmc/u-boot/drivers/net/pfe_eth/pfe_cmd.c (revision 6281a769)
1*6281a769SCalvin Johnson /*
2*6281a769SCalvin Johnson  * Copyright 2015-2016 Freescale Semiconductor, Inc.
3*6281a769SCalvin Johnson  * Copyright 2017 NXP
4*6281a769SCalvin Johnson  *
5*6281a769SCalvin Johnson  * SPDX-License-Identifier:	GPL-2.0+
6*6281a769SCalvin Johnson  */
7*6281a769SCalvin Johnson 
8*6281a769SCalvin Johnson /*
9*6281a769SCalvin Johnson  * @file
10*6281a769SCalvin Johnson  * @brief PFE utility commands
11*6281a769SCalvin Johnson  */
12*6281a769SCalvin Johnson 
13*6281a769SCalvin Johnson #include <net/pfe_eth/pfe_eth.h>
14*6281a769SCalvin Johnson 
15*6281a769SCalvin Johnson static inline void pfe_command_help(void)
16*6281a769SCalvin Johnson {
17*6281a769SCalvin Johnson 	printf("Usage: pfe [pe | status | expt ] <options>\n");
18*6281a769SCalvin Johnson }
19*6281a769SCalvin Johnson 
20*6281a769SCalvin Johnson static void pfe_command_pe(int argc, char * const argv[])
21*6281a769SCalvin Johnson {
22*6281a769SCalvin Johnson 	if (argc >= 3 && strcmp(argv[2], "pmem") == 0) {
23*6281a769SCalvin Johnson 		if (argc >= 4 && strcmp(argv[3], "read") == 0) {
24*6281a769SCalvin Johnson 			int i;
25*6281a769SCalvin Johnson 			int num;
26*6281a769SCalvin Johnson 			int id;
27*6281a769SCalvin Johnson 			u32 addr;
28*6281a769SCalvin Johnson 			u32 size;
29*6281a769SCalvin Johnson 			u32 val;
30*6281a769SCalvin Johnson 
31*6281a769SCalvin Johnson 			if (argc == 7) {
32*6281a769SCalvin Johnson 				num = simple_strtoul(argv[6], NULL, 0);
33*6281a769SCalvin Johnson 			} else if (argc == 6) {
34*6281a769SCalvin Johnson 				num = 1;
35*6281a769SCalvin Johnson 			} else {
36*6281a769SCalvin Johnson 				printf("Usage: pfe pe pmem read <id> <addr> [<num>]\n");
37*6281a769SCalvin Johnson 				return;
38*6281a769SCalvin Johnson 			}
39*6281a769SCalvin Johnson 
40*6281a769SCalvin Johnson 			id = simple_strtoul(argv[4], NULL, 0);
41*6281a769SCalvin Johnson 			addr = simple_strtoul(argv[5], NULL, 16);
42*6281a769SCalvin Johnson 			size = 4;
43*6281a769SCalvin Johnson 
44*6281a769SCalvin Johnson 			for (i = 0; i < num; i++, addr += 4) {
45*6281a769SCalvin Johnson 				val = pe_pmem_read(id, addr, size);
46*6281a769SCalvin Johnson 				val = be32_to_cpu(val);
47*6281a769SCalvin Johnson 				if (!(i & 3))
48*6281a769SCalvin Johnson 					printf("%08x: ", addr);
49*6281a769SCalvin Johnson 				printf("%08x%s", val, i == num - 1 || (i & 3)
50*6281a769SCalvin Johnson 				       == 3 ? "\n" : " ");
51*6281a769SCalvin Johnson 			}
52*6281a769SCalvin Johnson 
53*6281a769SCalvin Johnson 		} else {
54*6281a769SCalvin Johnson 			printf("Usage: pfe pe pmem read <parameters>\n");
55*6281a769SCalvin Johnson 		}
56*6281a769SCalvin Johnson 	} else if (argc >= 3 && strcmp(argv[2], "dmem") == 0) {
57*6281a769SCalvin Johnson 		if (argc >= 4 && strcmp(argv[3], "read") == 0) {
58*6281a769SCalvin Johnson 			int i;
59*6281a769SCalvin Johnson 			int num;
60*6281a769SCalvin Johnson 			int id;
61*6281a769SCalvin Johnson 			u32 addr;
62*6281a769SCalvin Johnson 			u32 size;
63*6281a769SCalvin Johnson 			u32 val;
64*6281a769SCalvin Johnson 
65*6281a769SCalvin Johnson 			if (argc == 7) {
66*6281a769SCalvin Johnson 				num = simple_strtoul(argv[6], NULL, 0);
67*6281a769SCalvin Johnson 			} else if (argc == 6) {
68*6281a769SCalvin Johnson 				num = 1;
69*6281a769SCalvin Johnson 			} else {
70*6281a769SCalvin Johnson 				printf("Usage: pfe pe dmem read <id> <addr> [<num>]\n");
71*6281a769SCalvin Johnson 				return;
72*6281a769SCalvin Johnson 			}
73*6281a769SCalvin Johnson 
74*6281a769SCalvin Johnson 			id = simple_strtoul(argv[4], NULL, 0);
75*6281a769SCalvin Johnson 			addr = simple_strtoul(argv[5], NULL, 16);
76*6281a769SCalvin Johnson 			size = 4;
77*6281a769SCalvin Johnson 
78*6281a769SCalvin Johnson 			for (i = 0; i < num; i++, addr += 4) {
79*6281a769SCalvin Johnson 				val = pe_dmem_read(id, addr, size);
80*6281a769SCalvin Johnson 				val = be32_to_cpu(val);
81*6281a769SCalvin Johnson 				if (!(i & 3))
82*6281a769SCalvin Johnson 					printf("%08x: ", addr);
83*6281a769SCalvin Johnson 				printf("%08x%s", val, i == num - 1 || (i & 3)
84*6281a769SCalvin Johnson 				       == 3 ? "\n" : " ");
85*6281a769SCalvin Johnson 			}
86*6281a769SCalvin Johnson 
87*6281a769SCalvin Johnson 		} else if (argc >= 4 && strcmp(argv[3], "write") == 0) {
88*6281a769SCalvin Johnson 			int id;
89*6281a769SCalvin Johnson 			u32 val;
90*6281a769SCalvin Johnson 			u32 addr;
91*6281a769SCalvin Johnson 			u32 size;
92*6281a769SCalvin Johnson 
93*6281a769SCalvin Johnson 			if (argc != 7) {
94*6281a769SCalvin Johnson 				printf("Usage: pfe pe dmem write <id> <val> <addr>\n");
95*6281a769SCalvin Johnson 				return;
96*6281a769SCalvin Johnson 			}
97*6281a769SCalvin Johnson 
98*6281a769SCalvin Johnson 			id = simple_strtoul(argv[4], NULL, 0);
99*6281a769SCalvin Johnson 			val = simple_strtoul(argv[5], NULL, 16);
100*6281a769SCalvin Johnson 			val = cpu_to_be32(val);
101*6281a769SCalvin Johnson 			addr = simple_strtoul(argv[6], NULL, 16);
102*6281a769SCalvin Johnson 			size = 4;
103*6281a769SCalvin Johnson 			pe_dmem_write(id, val, addr, size);
104*6281a769SCalvin Johnson 		} else {
105*6281a769SCalvin Johnson 			printf("Usage: pfe pe dmem [read | write] <parameters>\n");
106*6281a769SCalvin Johnson 		}
107*6281a769SCalvin Johnson 	} else if (argc >= 3 && strcmp(argv[2], "lmem") == 0) {
108*6281a769SCalvin Johnson 		if (argc >= 4 && strcmp(argv[3], "read") == 0) {
109*6281a769SCalvin Johnson 			int i;
110*6281a769SCalvin Johnson 			int num;
111*6281a769SCalvin Johnson 			u32 val;
112*6281a769SCalvin Johnson 			u32 offset;
113*6281a769SCalvin Johnson 
114*6281a769SCalvin Johnson 			if (argc == 6) {
115*6281a769SCalvin Johnson 				num = simple_strtoul(argv[5], NULL, 0);
116*6281a769SCalvin Johnson 			} else if (argc == 5) {
117*6281a769SCalvin Johnson 				num = 1;
118*6281a769SCalvin Johnson 			} else {
119*6281a769SCalvin Johnson 				printf("Usage: pfe pe lmem read <offset> [<num>]\n");
120*6281a769SCalvin Johnson 				return;
121*6281a769SCalvin Johnson 			}
122*6281a769SCalvin Johnson 
123*6281a769SCalvin Johnson 			offset = simple_strtoul(argv[4], NULL, 16);
124*6281a769SCalvin Johnson 
125*6281a769SCalvin Johnson 			for (i = 0; i < num; i++, offset += 4) {
126*6281a769SCalvin Johnson 				pe_lmem_read(&val, 4, offset);
127*6281a769SCalvin Johnson 				val = be32_to_cpu(val);
128*6281a769SCalvin Johnson 				printf("%08x%s", val, i == num - 1 || (i & 7)
129*6281a769SCalvin Johnson 				       == 7 ? "\n" : " ");
130*6281a769SCalvin Johnson 			}
131*6281a769SCalvin Johnson 
132*6281a769SCalvin Johnson 		} else if (argc >= 4 && strcmp(argv[3], "write") == 0)	{
133*6281a769SCalvin Johnson 			u32 val;
134*6281a769SCalvin Johnson 			u32 offset;
135*6281a769SCalvin Johnson 
136*6281a769SCalvin Johnson 			if (argc != 6) {
137*6281a769SCalvin Johnson 				printf("Usage: pfe pe lmem write <val> <offset>\n");
138*6281a769SCalvin Johnson 				return;
139*6281a769SCalvin Johnson 			}
140*6281a769SCalvin Johnson 
141*6281a769SCalvin Johnson 			val = simple_strtoul(argv[4], NULL, 16);
142*6281a769SCalvin Johnson 			val = cpu_to_be32(val);
143*6281a769SCalvin Johnson 			offset = simple_strtoul(argv[5], NULL, 16);
144*6281a769SCalvin Johnson 			pe_lmem_write(&val, 4, offset);
145*6281a769SCalvin Johnson 		} else {
146*6281a769SCalvin Johnson 			printf("Usage: pfe pe lmem [read | write] <parameters>\n");
147*6281a769SCalvin Johnson 		}
148*6281a769SCalvin Johnson 	} else {
149*6281a769SCalvin Johnson 		if (strcmp(argv[2], "help") != 0)
150*6281a769SCalvin Johnson 			printf("Unknown option: %s\n", argv[2]);
151*6281a769SCalvin Johnson 
152*6281a769SCalvin Johnson 		printf("Usage: pfe pe <parameters>\n");
153*6281a769SCalvin Johnson 	}
154*6281a769SCalvin Johnson }
155*6281a769SCalvin Johnson 
156*6281a769SCalvin Johnson #define NUM_QUEUES		16
157*6281a769SCalvin Johnson 
158*6281a769SCalvin Johnson /*
159*6281a769SCalvin Johnson  * qm_read_drop_stat
160*6281a769SCalvin Johnson  * This function is used to read the drop statistics from the TMU
161*6281a769SCalvin Johnson  * hw drop counter.  Since the hw counter is always cleared afer
162*6281a769SCalvin Johnson  * reading, this function maintains the previous drop count, and
163*6281a769SCalvin Johnson  * adds the new value to it.  That value can be retrieved by
164*6281a769SCalvin Johnson  * passing a pointer to it with the total_drops arg.
165*6281a769SCalvin Johnson  *
166*6281a769SCalvin Johnson  * @param tmu           TMU number (0 - 3)
167*6281a769SCalvin Johnson  * @param queue         queue number (0 - 15)
168*6281a769SCalvin Johnson  * @param total_drops   pointer to location to store total drops (or NULL)
169*6281a769SCalvin Johnson  * @param do_reset      if TRUE, clear total drops after updating
170*6281a769SCalvin Johnson  *
171*6281a769SCalvin Johnson  */
172*6281a769SCalvin Johnson u32 qm_read_drop_stat(u32 tmu, u32 queue, u32 *total_drops, int do_reset)
173*6281a769SCalvin Johnson {
174*6281a769SCalvin Johnson 	static u32 qtotal[TMU_MAX_ID + 1][NUM_QUEUES];
175*6281a769SCalvin Johnson 	u32 val;
176*6281a769SCalvin Johnson 
177*6281a769SCalvin Johnson 	writel((tmu << 8) | queue, TMU_TEQ_CTRL);
178*6281a769SCalvin Johnson 	writel((tmu << 8) | queue, TMU_LLM_CTRL);
179*6281a769SCalvin Johnson 	val = readl(TMU_TEQ_DROP_STAT);
180*6281a769SCalvin Johnson 	qtotal[tmu][queue] += val;
181*6281a769SCalvin Johnson 	if (total_drops)
182*6281a769SCalvin Johnson 		*total_drops = qtotal[tmu][queue];
183*6281a769SCalvin Johnson 	if (do_reset)
184*6281a769SCalvin Johnson 		qtotal[tmu][queue] = 0;
185*6281a769SCalvin Johnson 	return val;
186*6281a769SCalvin Johnson }
187*6281a769SCalvin Johnson 
188*6281a769SCalvin Johnson static ssize_t tmu_queue_stats(char *buf, int tmu, int queue)
189*6281a769SCalvin Johnson {
190*6281a769SCalvin Johnson 	ssize_t len = 0;
191*6281a769SCalvin Johnson 	u32 drops;
192*6281a769SCalvin Johnson 
193*6281a769SCalvin Johnson 	printf("%d-%02d, ", tmu, queue);
194*6281a769SCalvin Johnson 
195*6281a769SCalvin Johnson 	drops = qm_read_drop_stat(tmu, queue, NULL, 0);
196*6281a769SCalvin Johnson 
197*6281a769SCalvin Johnson 	/* Select queue */
198*6281a769SCalvin Johnson 	writel((tmu << 8) | queue, TMU_TEQ_CTRL);
199*6281a769SCalvin Johnson 	writel((tmu << 8) | queue, TMU_LLM_CTRL);
200*6281a769SCalvin Johnson 
201*6281a769SCalvin Johnson 	printf("(teq) drop: %10u, tx: %10u (llm) head: %08x, tail: %08x, drop: %10u\n",
202*6281a769SCalvin Johnson 	       drops, readl(TMU_TEQ_TRANS_STAT),
203*6281a769SCalvin Johnson 	       readl(TMU_LLM_QUE_HEADPTR), readl(TMU_LLM_QUE_TAILPTR),
204*6281a769SCalvin Johnson 	       readl(TMU_LLM_QUE_DROPCNT));
205*6281a769SCalvin Johnson 
206*6281a769SCalvin Johnson 	return len;
207*6281a769SCalvin Johnson }
208*6281a769SCalvin Johnson 
209*6281a769SCalvin Johnson static ssize_t tmu_queues(char *buf, int tmu)
210*6281a769SCalvin Johnson {
211*6281a769SCalvin Johnson 	ssize_t len = 0;
212*6281a769SCalvin Johnson 	int queue;
213*6281a769SCalvin Johnson 
214*6281a769SCalvin Johnson 	for (queue = 0; queue < 16; queue++)
215*6281a769SCalvin Johnson 		len += tmu_queue_stats(buf + len, tmu, queue);
216*6281a769SCalvin Johnson 
217*6281a769SCalvin Johnson 	return len;
218*6281a769SCalvin Johnson }
219*6281a769SCalvin Johnson 
220*6281a769SCalvin Johnson static inline void hif_status(void)
221*6281a769SCalvin Johnson {
222*6281a769SCalvin Johnson 	printf("hif:\n");
223*6281a769SCalvin Johnson 
224*6281a769SCalvin Johnson 	printf("  tx curr bd:    %x\n", readl(HIF_TX_CURR_BD_ADDR));
225*6281a769SCalvin Johnson 	printf("  tx status:     %x\n", readl(HIF_TX_STATUS));
226*6281a769SCalvin Johnson 	printf("  tx dma status: %x\n", readl(HIF_TX_DMA_STATUS));
227*6281a769SCalvin Johnson 
228*6281a769SCalvin Johnson 	printf("  rx curr bd:    %x\n", readl(HIF_RX_CURR_BD_ADDR));
229*6281a769SCalvin Johnson 	printf("  rx status:     %x\n", readl(HIF_RX_STATUS));
230*6281a769SCalvin Johnson 	printf("  rx dma status: %x\n", readl(HIF_RX_DMA_STATUS));
231*6281a769SCalvin Johnson 
232*6281a769SCalvin Johnson 	printf("hif nocopy:\n");
233*6281a769SCalvin Johnson 
234*6281a769SCalvin Johnson 	printf("  tx curr bd:    %x\n", readl(HIF_NOCPY_TX_CURR_BD_ADDR));
235*6281a769SCalvin Johnson 	printf("  tx status:     %x\n", readl(HIF_NOCPY_TX_STATUS));
236*6281a769SCalvin Johnson 	printf("  tx dma status: %x\n", readl(HIF_NOCPY_TX_DMA_STATUS));
237*6281a769SCalvin Johnson 
238*6281a769SCalvin Johnson 	printf("  rx curr bd:    %x\n", readl(HIF_NOCPY_RX_CURR_BD_ADDR));
239*6281a769SCalvin Johnson 	printf("  rx status:     %x\n", readl(HIF_NOCPY_RX_STATUS));
240*6281a769SCalvin Johnson 	printf("  rx dma status: %x\n", readl(HIF_NOCPY_RX_DMA_STATUS));
241*6281a769SCalvin Johnson }
242*6281a769SCalvin Johnson 
243*6281a769SCalvin Johnson static void gpi(int id, void *base)
244*6281a769SCalvin Johnson {
245*6281a769SCalvin Johnson 	u32 val;
246*6281a769SCalvin Johnson 
247*6281a769SCalvin Johnson 	printf("%s%d:\n", __func__, id);
248*6281a769SCalvin Johnson 
249*6281a769SCalvin Johnson 	printf("  tx under stick: %x\n", readl(base + GPI_FIFO_STATUS));
250*6281a769SCalvin Johnson 	val = readl(base + GPI_FIFO_DEBUG);
251*6281a769SCalvin Johnson 	printf("  tx pkts:        %x\n", (val >> 23) & 0x3f);
252*6281a769SCalvin Johnson 	printf("  rx pkts:        %x\n", (val >> 18) & 0x3f);
253*6281a769SCalvin Johnson 	printf("  tx bytes:       %x\n", (val >> 9) & 0x1ff);
254*6281a769SCalvin Johnson 	printf("  rx bytes:       %x\n", (val >> 0) & 0x1ff);
255*6281a769SCalvin Johnson 	printf("  overrun:        %x\n", readl(base + GPI_OVERRUN_DROPCNT));
256*6281a769SCalvin Johnson }
257*6281a769SCalvin Johnson 
258*6281a769SCalvin Johnson static void  bmu(int id, void *base)
259*6281a769SCalvin Johnson {
260*6281a769SCalvin Johnson 	printf("%s%d:\n", __func__, id);
261*6281a769SCalvin Johnson 
262*6281a769SCalvin Johnson 	printf("  buf size:  %x\n", (1 << readl(base + BMU_BUF_SIZE)));
263*6281a769SCalvin Johnson 	printf("  buf count: %x\n", readl(base + BMU_BUF_CNT));
264*6281a769SCalvin Johnson 	printf("  buf rem:   %x\n", readl(base + BMU_REM_BUF_CNT));
265*6281a769SCalvin Johnson 	printf("  buf curr:  %x\n", readl(base + BMU_CURR_BUF_CNT));
266*6281a769SCalvin Johnson 	printf("  free err:  %x\n", readl(base + BMU_FREE_ERR_ADDR));
267*6281a769SCalvin Johnson }
268*6281a769SCalvin Johnson 
269*6281a769SCalvin Johnson #define	PESTATUS_ADDR_CLASS	0x800
270*6281a769SCalvin Johnson #define PEMBOX_ADDR_CLASS	0x890
271*6281a769SCalvin Johnson #define	PESTATUS_ADDR_TMU	0x80
272*6281a769SCalvin Johnson #define PEMBOX_ADDR_TMU		0x290
273*6281a769SCalvin Johnson #define	PESTATUS_ADDR_UTIL	0x0
274*6281a769SCalvin Johnson 
275*6281a769SCalvin Johnson static void pfe_pe_status(int argc, char * const argv[])
276*6281a769SCalvin Johnson {
277*6281a769SCalvin Johnson 	int do_clear = 0;
278*6281a769SCalvin Johnson 	u32 id;
279*6281a769SCalvin Johnson 	u32 dmem_addr;
280*6281a769SCalvin Johnson 	u32 cpu_state;
281*6281a769SCalvin Johnson 	u32 activity_counter;
282*6281a769SCalvin Johnson 	u32 rx;
283*6281a769SCalvin Johnson 	u32 tx;
284*6281a769SCalvin Johnson 	u32 drop;
285*6281a769SCalvin Johnson 	char statebuf[5];
286*6281a769SCalvin Johnson 	u32 class_debug_reg = 0;
287*6281a769SCalvin Johnson 
288*6281a769SCalvin Johnson 	if (argc == 4 && strcmp(argv[3], "clear") == 0)
289*6281a769SCalvin Johnson 		do_clear = 1;
290*6281a769SCalvin Johnson 
291*6281a769SCalvin Johnson 	for (id = CLASS0_ID; id < MAX_PE; id++) {
292*6281a769SCalvin Johnson 		if (id >= TMU0_ID) {
293*6281a769SCalvin Johnson 			if (id == TMU2_ID)
294*6281a769SCalvin Johnson 				continue;
295*6281a769SCalvin Johnson 			if (id == TMU0_ID)
296*6281a769SCalvin Johnson 				printf("tmu:\n");
297*6281a769SCalvin Johnson 			dmem_addr = PESTATUS_ADDR_TMU;
298*6281a769SCalvin Johnson 		} else {
299*6281a769SCalvin Johnson 			if (id == CLASS0_ID)
300*6281a769SCalvin Johnson 				printf("class:\n");
301*6281a769SCalvin Johnson 			dmem_addr = PESTATUS_ADDR_CLASS;
302*6281a769SCalvin Johnson 			class_debug_reg = readl(CLASS_PE0_DEBUG + id * 4);
303*6281a769SCalvin Johnson 		}
304*6281a769SCalvin Johnson 
305*6281a769SCalvin Johnson 		cpu_state = pe_dmem_read(id, dmem_addr, 4);
306*6281a769SCalvin Johnson 		dmem_addr += 4;
307*6281a769SCalvin Johnson 		memcpy(statebuf, (char *)&cpu_state, 4);
308*6281a769SCalvin Johnson 		statebuf[4] = '\0';
309*6281a769SCalvin Johnson 		activity_counter = pe_dmem_read(id, dmem_addr, 4);
310*6281a769SCalvin Johnson 		dmem_addr += 4;
311*6281a769SCalvin Johnson 		rx = pe_dmem_read(id, dmem_addr, 4);
312*6281a769SCalvin Johnson 		if (do_clear)
313*6281a769SCalvin Johnson 			pe_dmem_write(id, 0, dmem_addr, 4);
314*6281a769SCalvin Johnson 		dmem_addr += 4;
315*6281a769SCalvin Johnson 		tx = pe_dmem_read(id, dmem_addr, 4);
316*6281a769SCalvin Johnson 		if (do_clear)
317*6281a769SCalvin Johnson 			pe_dmem_write(id, 0, dmem_addr, 4);
318*6281a769SCalvin Johnson 		dmem_addr += 4;
319*6281a769SCalvin Johnson 		drop = pe_dmem_read(id, dmem_addr, 4);
320*6281a769SCalvin Johnson 		if (do_clear)
321*6281a769SCalvin Johnson 			pe_dmem_write(id, 0, dmem_addr, 4);
322*6281a769SCalvin Johnson 		dmem_addr += 4;
323*6281a769SCalvin Johnson 
324*6281a769SCalvin Johnson 		if (id >= TMU0_ID) {
325*6281a769SCalvin Johnson 			printf("%d: state=%4s ctr=%08x rx=%x qstatus=%x\n",
326*6281a769SCalvin Johnson 			       id - TMU0_ID, statebuf,
327*6281a769SCalvin Johnson 			       cpu_to_be32(activity_counter),
328*6281a769SCalvin Johnson 			       cpu_to_be32(rx), cpu_to_be32(tx));
329*6281a769SCalvin Johnson 		} else {
330*6281a769SCalvin Johnson 			printf("%d: pc=1%04x ldst=%04x state=%4s ctr=%08x rx=%x tx=%x drop=%x\n",
331*6281a769SCalvin Johnson 			       id - CLASS0_ID, class_debug_reg & 0xFFFF,
332*6281a769SCalvin Johnson 			       class_debug_reg >> 16,
333*6281a769SCalvin Johnson 			       statebuf, cpu_to_be32(activity_counter),
334*6281a769SCalvin Johnson 			       cpu_to_be32(rx), cpu_to_be32(tx),
335*6281a769SCalvin Johnson 			       cpu_to_be32(drop));
336*6281a769SCalvin Johnson 		}
337*6281a769SCalvin Johnson 	}
338*6281a769SCalvin Johnson }
339*6281a769SCalvin Johnson 
340*6281a769SCalvin Johnson static void pfe_command_status(int argc, char * const argv[])
341*6281a769SCalvin Johnson {
342*6281a769SCalvin Johnson 	if (argc >= 3 && strcmp(argv[2], "pe") == 0) {
343*6281a769SCalvin Johnson 		pfe_pe_status(argc, argv);
344*6281a769SCalvin Johnson 	} else if (argc == 3 && strcmp(argv[2], "bmu") == 0) {
345*6281a769SCalvin Johnson 		bmu(1, BMU1_BASE_ADDR);
346*6281a769SCalvin Johnson 		bmu(2, BMU2_BASE_ADDR);
347*6281a769SCalvin Johnson 	} else if (argc == 3 && strcmp(argv[2], "hif") == 0) {
348*6281a769SCalvin Johnson 		hif_status();
349*6281a769SCalvin Johnson 	} else if (argc == 3 && strcmp(argv[2], "gpi") == 0) {
350*6281a769SCalvin Johnson 		gpi(0, EGPI1_BASE_ADDR);
351*6281a769SCalvin Johnson 		gpi(1, EGPI2_BASE_ADDR);
352*6281a769SCalvin Johnson 		gpi(3, HGPI_BASE_ADDR);
353*6281a769SCalvin Johnson 	} else if (argc == 3 && strcmp(argv[2], "tmu0_queues") == 0) {
354*6281a769SCalvin Johnson 		tmu_queues(NULL, 0);
355*6281a769SCalvin Johnson 	} else if (argc == 3 && strcmp(argv[2], "tmu1_queues") == 0) {
356*6281a769SCalvin Johnson 		tmu_queues(NULL, 1);
357*6281a769SCalvin Johnson 	} else if (argc == 3 && strcmp(argv[2], "tmu3_queues") == 0) {
358*6281a769SCalvin Johnson 		tmu_queues(NULL, 3);
359*6281a769SCalvin Johnson 	} else {
360*6281a769SCalvin Johnson 		printf("Usage: pfe status [pe <clear> | bmu | gpi | hif | tmuX_queues ]\n");
361*6281a769SCalvin Johnson 	}
362*6281a769SCalvin Johnson }
363*6281a769SCalvin Johnson 
364*6281a769SCalvin Johnson #define EXPT_DUMP_ADDR 0x1fa8
365*6281a769SCalvin Johnson #define EXPT_REG_COUNT 20
366*6281a769SCalvin Johnson static const char *register_names[EXPT_REG_COUNT] = {
367*6281a769SCalvin Johnson 		"  pc", "ECAS", " EID", "  ED",
368*6281a769SCalvin Johnson 		"  sp", "  r1", "  r2", "  r3",
369*6281a769SCalvin Johnson 		"  r4", "  r5", "  r6", "  r7",
370*6281a769SCalvin Johnson 		"  r8", "  r9", " r10", " r11",
371*6281a769SCalvin Johnson 		" r12", " r13", " r14", " r15"
372*6281a769SCalvin Johnson };
373*6281a769SCalvin Johnson 
374*6281a769SCalvin Johnson static void pfe_command_expt(int argc, char * const argv[])
375*6281a769SCalvin Johnson {
376*6281a769SCalvin Johnson 	unsigned int id, i, val, addr;
377*6281a769SCalvin Johnson 
378*6281a769SCalvin Johnson 	if (argc == 3) {
379*6281a769SCalvin Johnson 		id = simple_strtoul(argv[2], NULL, 0);
380*6281a769SCalvin Johnson 		addr = EXPT_DUMP_ADDR;
381*6281a769SCalvin Johnson 		printf("Exception information for PE %d:\n", id);
382*6281a769SCalvin Johnson 		for (i = 0; i < EXPT_REG_COUNT; i++) {
383*6281a769SCalvin Johnson 			val = pe_dmem_read(id, addr, 4);
384*6281a769SCalvin Johnson 			val = be32_to_cpu(val);
385*6281a769SCalvin Johnson 			printf("%s:%08x%s", register_names[i], val,
386*6281a769SCalvin Johnson 			       (i & 3) == 3 ? "\n" : " ");
387*6281a769SCalvin Johnson 			addr += 4;
388*6281a769SCalvin Johnson 		}
389*6281a769SCalvin Johnson 	} else {
390*6281a769SCalvin Johnson 		printf("Usage: pfe expt <id>\n");
391*6281a769SCalvin Johnson 	}
392*6281a769SCalvin Johnson }
393*6281a769SCalvin Johnson 
394*6281a769SCalvin Johnson #ifdef PFE_RESET_WA
395*6281a769SCalvin Johnson /*This function sends a dummy packet to HIF through TMU3 */
396*6281a769SCalvin Johnson static void send_dummy_pkt_to_hif(void)
397*6281a769SCalvin Johnson {
398*6281a769SCalvin Johnson 	u32 buf;
399*6281a769SCalvin Johnson 	static u32 dummy_pkt[] =  {
400*6281a769SCalvin Johnson 		0x4200800a, 0x01000003, 0x00018100, 0x00000000,
401*6281a769SCalvin Johnson 		0x33221100, 0x2b785544, 0xd73093cb, 0x01000608,
402*6281a769SCalvin Johnson 		0x04060008, 0x2b780200, 0xd73093cb, 0x0a01a8c0,
403*6281a769SCalvin Johnson 		0x33221100, 0xa8c05544, 0x00000301, 0x00000000,
404*6281a769SCalvin Johnson 		0x00000000, 0x00000000, 0x00000000, 0xbe86c51f };
405*6281a769SCalvin Johnson 
406*6281a769SCalvin Johnson 	/*Allocate BMU2 buffer */
407*6281a769SCalvin Johnson 	buf = readl(BMU2_BASE_ADDR + BMU_ALLOC_CTRL);
408*6281a769SCalvin Johnson 
409*6281a769SCalvin Johnson 	debug("Sending a dummy pkt to HIF %x\n", buf);
410*6281a769SCalvin Johnson 	buf += 0x80;
411*6281a769SCalvin Johnson 	memcpy((void *)DDR_PFE_TO_VIRT(buf), dummy_pkt, sizeof(dummy_pkt));
412*6281a769SCalvin Johnson 
413*6281a769SCalvin Johnson 	/*Write length and pkt to TMU*/
414*6281a769SCalvin Johnson 	writel(0x03000042, TMU_PHY_INQ_PKTPTR);
415*6281a769SCalvin Johnson 	writel(buf, TMU_PHY_INQ_PKTINFO);
416*6281a769SCalvin Johnson }
417*6281a769SCalvin Johnson 
418*6281a769SCalvin Johnson static void pfe_command_stop(int argc, char * const argv[])
419*6281a769SCalvin Johnson {
420*6281a769SCalvin Johnson 	int pfe_pe_id, hif_stop_loop = 10;
421*6281a769SCalvin Johnson 	u32 rx_status;
422*6281a769SCalvin Johnson 
423*6281a769SCalvin Johnson 	printf("Stopping PFE...\n");
424*6281a769SCalvin Johnson 
425*6281a769SCalvin Johnson 	/*Mark all descriptors as LAST_BD */
426*6281a769SCalvin Johnson 	hif_rx_desc_disable();
427*6281a769SCalvin Johnson 
428*6281a769SCalvin Johnson 	/*If HIF Rx BDP is busy send a dummy packet */
429*6281a769SCalvin Johnson 	do {
430*6281a769SCalvin Johnson 		rx_status = readl(HIF_RX_STATUS);
431*6281a769SCalvin Johnson 		if (rx_status & BDP_CSR_RX_DMA_ACTV)
432*6281a769SCalvin Johnson 			send_dummy_pkt_to_hif();
433*6281a769SCalvin Johnson 		udelay(10);
434*6281a769SCalvin Johnson 	} while (hif_stop_loop--);
435*6281a769SCalvin Johnson 
436*6281a769SCalvin Johnson 	if (readl(HIF_RX_STATUS) & BDP_CSR_RX_DMA_ACTV)
437*6281a769SCalvin Johnson 		printf("Unable to stop HIF\n");
438*6281a769SCalvin Johnson 
439*6281a769SCalvin Johnson 	/*Disable Class PEs */
440*6281a769SCalvin Johnson 	for (pfe_pe_id = CLASS0_ID; pfe_pe_id <= CLASS_MAX_ID; pfe_pe_id++) {
441*6281a769SCalvin Johnson 		/*Inform PE to stop */
442*6281a769SCalvin Johnson 		pe_dmem_write(pfe_pe_id, cpu_to_be32(1), PEMBOX_ADDR_CLASS, 4);
443*6281a769SCalvin Johnson 		udelay(10);
444*6281a769SCalvin Johnson 
445*6281a769SCalvin Johnson 		/*Read status */
446*6281a769SCalvin Johnson 		if (!pe_dmem_read(pfe_pe_id, PEMBOX_ADDR_CLASS + 4, 4))
447*6281a769SCalvin Johnson 			printf("Failed to stop PE%d\n", pfe_pe_id);
448*6281a769SCalvin Johnson 	}
449*6281a769SCalvin Johnson 
450*6281a769SCalvin Johnson 	/*Disable TMU PEs */
451*6281a769SCalvin Johnson 	for (pfe_pe_id = TMU0_ID; pfe_pe_id <= TMU_MAX_ID; pfe_pe_id++) {
452*6281a769SCalvin Johnson 		if (pfe_pe_id == TMU2_ID)
453*6281a769SCalvin Johnson 			continue;
454*6281a769SCalvin Johnson 
455*6281a769SCalvin Johnson 		/*Inform PE to stop */
456*6281a769SCalvin Johnson 		pe_dmem_write(pfe_pe_id, 1, PEMBOX_ADDR_TMU, 4);
457*6281a769SCalvin Johnson 		udelay(10);
458*6281a769SCalvin Johnson 
459*6281a769SCalvin Johnson 		/*Read status */
460*6281a769SCalvin Johnson 		if (!pe_dmem_read(pfe_pe_id, PEMBOX_ADDR_TMU + 4, 4))
461*6281a769SCalvin Johnson 			printf("Failed to stop PE%d\n", pfe_pe_id);
462*6281a769SCalvin Johnson 	}
463*6281a769SCalvin Johnson }
464*6281a769SCalvin Johnson #endif
465*6281a769SCalvin Johnson 
466*6281a769SCalvin Johnson static int pfe_command(cmd_tbl_t *cmdtp, int flag, int argc,
467*6281a769SCalvin Johnson 		       char * const argv[])
468*6281a769SCalvin Johnson {
469*6281a769SCalvin Johnson 	if (argc == 1 || strcmp(argv[1], "help") == 0) {
470*6281a769SCalvin Johnson 		pfe_command_help();
471*6281a769SCalvin Johnson 		return CMD_RET_SUCCESS;
472*6281a769SCalvin Johnson 	}
473*6281a769SCalvin Johnson 
474*6281a769SCalvin Johnson 	if (strcmp(argv[1], "pe") == 0) {
475*6281a769SCalvin Johnson 		pfe_command_pe(argc, argv);
476*6281a769SCalvin Johnson 	} else if (strcmp(argv[1], "status") == 0) {
477*6281a769SCalvin Johnson 		pfe_command_status(argc, argv);
478*6281a769SCalvin Johnson 	} else if (strcmp(argv[1], "expt") == 0) {
479*6281a769SCalvin Johnson 		pfe_command_expt(argc, argv);
480*6281a769SCalvin Johnson #ifdef PFE_RESET_WA
481*6281a769SCalvin Johnson 	} else if (strcmp(argv[1], "stop") == 0) {
482*6281a769SCalvin Johnson 		pfe_command_stop(argc, argv);
483*6281a769SCalvin Johnson #endif
484*6281a769SCalvin Johnson 	} else {
485*6281a769SCalvin Johnson 		printf("Unknown option: %s\n", argv[1]);
486*6281a769SCalvin Johnson 		pfe_command_help();
487*6281a769SCalvin Johnson 		return CMD_RET_FAILURE;
488*6281a769SCalvin Johnson 	}
489*6281a769SCalvin Johnson 	return CMD_RET_SUCCESS;
490*6281a769SCalvin Johnson }
491*6281a769SCalvin Johnson 
492*6281a769SCalvin Johnson U_BOOT_CMD(
493*6281a769SCalvin Johnson 	pfe,	7,	1,	pfe_command,
494*6281a769SCalvin Johnson 	"Performs PFE lib utility functions",
495*6281a769SCalvin Johnson 	"Usage:\n"
496*6281a769SCalvin Johnson 	"pfe <options>"
497*6281a769SCalvin Johnson );
498