1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  ccnuma commands				File: ui_ccncmds.c
5    *
6    *  Commands and test stuff to check out ccnuma (evolving)
7    *
8    *********************************************************************
9    *
10    *  Copyright 2004,2005
11    *  Broadcom Corporation. All rights reserved.
12    *
13    *  BROADCOM PROPRIETARY AND CONFIDENTIAL
14    *
15    *  This software is furnished under license and may be used and
16    *  copied only in accordance with the license.
17    ********************************************************************* */
18
19
20#include "cfe.h"
21#include "ui_command.h"
22
23#include "lib_physio.h"
24#include "bcm1480_regs.h"
25#include "bcm1480_hsp.h"
26#include "bcm1480_rld.h"
27#include "bcm1480_scd.h"
28
29extern void ht_ccn_enable(unsigned int node, unsigned int port, int enable);
30
31
32/*  *********************************************************************
33    *  Constants
34    ********************************************************************* */
35
36typedef unsigned int uint_t;
37
38
39/*  *********************************************************************
40    *  prototypes
41    ********************************************************************* */
42
43int ui_init_ccncmds(void);
44
45
46/*  *********************************************************************
47    *  RLD stuff
48    ********************************************************************* */
49
50#define RLD_LINES 2048
51
52#define M_BCM1480_RLD_FIELD_PATTERN  (M_BCM1480_RLD_FIELD_TAG          | \
53                                      M_BCM1480_RLD_FIELD_VALID        | \
54                                      M_BCM1480_RLD_FIELD_MODIFIED     | \
55                                      M_BCM1480_RLD_FIELD_NODE_VECTOR)
56
57static void
58fill_rld(int node, uint64_t pattern, uint8_t ecc, int new_ecc, int check_ecc)
59{
60    unsigned int index, way;
61    uint64_t common_val;
62    uint64_t prefix = (uint64_t)node << 36;
63
64    common_val = ((pattern & M_BCM1480_RLD_FIELD_PATTERN) |
65		  V_BCM1480_RLD_FIELD_ECC_BITS(ecc));
66    if (new_ecc) common_val |= M_BCM1480_RLD_FIELD_NEW_ECC;
67    if (check_ecc) common_val |= M_BCM1480_RLD_FIELD_CHECK_ECC;
68
69    for (index = 0; index < RLD_LINES; index++) {
70	for (way = 0; way < 8; way++) {
71	    if (way != 3 && way != 7) {    /* unimplemented ways */
72		phys_write64(prefix | A_BCM1480_NC_RLD_FIELD,
73			     (common_val |
74			      V_BCM1480_RLD_FIELD_INDEX(index) |
75			      V_BCM1480_RLD_FIELD_WAY_SELECT(way)));
76		phys_write64(prefix | A_BCM1480_NC_RLD_TRIGGER, 0);
77		}
78	    }
79	}
80}
81
82static int
83check_rld_pattern(uint64_t pattern, uint64_t rdtrigger)
84{
85    uint64_t tagin = G_BCM1480_RLD_FIELD_TAG(pattern);
86    int validin = (pattern & M_BCM1480_RLD_FIELD_VALID) != 0;
87    int modifiedin  = (pattern & M_BCM1480_RLD_FIELD_MODIFIED) != 0;
88    uint64_t vectorin  = G_BCM1480_RLD_FIELD_NODE_VECTOR(pattern);
89    uint64_t eccin  = G_BCM1480_RLD_FIELD_ECC_BITS(pattern);
90
91    uint64_t tagout = G_BCM1480_RLD_TRIGGER_TAG(rdtrigger);
92    int validout = (rdtrigger & M_BCM1480_RLD_TRIGGER_VALID) != 0;
93    int modifiedout = (rdtrigger & M_BCM1480_RLD_TRIGGER_MODIFIED) != 0;
94    uint64_t vectorout = G_BCM1480_RLD_TRIGGER_NODE_VECTOR(rdtrigger);
95    uint64_t eccout = G_BCM1480_RLD_TRIGGER_ECC_BITS(rdtrigger);
96
97    return ((tagin != tagout) || (validin != validout) ||
98	    (vectorin !=vectorout) || (modifiedin!=modifiedout) ||
99	    (eccin != eccout)) ? -1 : 0;
100}
101
102static void
103log_rld_error(uint_t index, uint_t way, uint64_t pattern, uint64_t rdtrigger)
104{
105    uint64_t tagin = G_BCM1480_RLD_FIELD_TAG(pattern);
106    int validin = (pattern & M_BCM1480_RLD_FIELD_VALID) != 0;
107    int modifiedin  = (pattern & M_BCM1480_RLD_FIELD_MODIFIED) != 0;
108    uint64_t vectorin  = G_BCM1480_RLD_FIELD_NODE_VECTOR(pattern);
109    uint64_t eccin  = G_BCM1480_RLD_FIELD_ECC_BITS(pattern);
110
111    uint64_t tagout = G_BCM1480_RLD_TRIGGER_TAG(rdtrigger);
112    int validout = (rdtrigger & M_BCM1480_RLD_TRIGGER_VALID) != 0;
113    int modifiedout = (rdtrigger & M_BCM1480_RLD_TRIGGER_MODIFIED) != 0;
114    uint64_t vectorout = G_BCM1480_RLD_TRIGGER_NODE_VECTOR(rdtrigger);
115    uint64_t eccout = G_BCM1480_RLD_TRIGGER_ECC_BITS(rdtrigger);
116
117    printf("  failed comparison, index %d, way %d:\n", index, way);
118    printf("   pattern=%16llx, rdtrigger=%16llx\n", pattern, rdtrigger);
119    if (tagin != tagout)
120	printf("   tagin=%x, tagout=%x\n", tagin, tagout);
121    if (validin != validout)
122	printf("   validin=%x, validout=%x\n", validin, validout);
123    if (vectorin != vectorout)
124	printf("   vectorin=%x, vectorout=%x\n", vectorin, vectorout);
125    if (modifiedin != modifiedout)
126	printf("   modifiedin=%x, modifiedout=%x\n", modifiedin, modifiedout);
127    if (eccin != eccout)
128	printf("   eccin=%x, eccout=%x\n", eccin, eccout);
129}
130
131static int
132check_rld(int node, uint64_t pattern, uint8_t ecc, int new_ecc, int check_ecc)
133{
134    uint_t index, way;
135    uint64_t common_val;
136    uint64_t prefix = (uint64_t)node << 36;
137    uint64_t rdtrigger;
138    int errors;
139
140    common_val = ((pattern & M_BCM1480_RLD_FIELD_PATTERN) |
141		  V_BCM1480_RLD_FIELD_ECC_BITS(ecc));
142    if (new_ecc) common_val |= M_BCM1480_RLD_FIELD_NEW_ECC;
143    if (check_ecc) common_val |= M_BCM1480_RLD_FIELD_CHECK_ECC;
144
145    errors = 0;
146
147    for (index = 0; index < RLD_LINES; index++) {
148	for (way = 0; way < 8; way++) {
149	    if (way != 3 && way != 7) {    /* unimplemented ways */
150		phys_write64(prefix | A_BCM1480_NC_RLD_FIELD,
151			     (common_val |
152			      V_BCM1480_RLD_FIELD_INDEX(index) |
153			      V_BCM1480_RLD_FIELD_WAY_SELECT(way)));
154		rdtrigger = phys_read64(prefix | A_BCM1480_NC_RLD_TRIGGER);
155		if (check_rld_pattern(pattern, rdtrigger) != 0) {
156		    if (errors < 10)
157			log_rld_error(index, way, pattern, rdtrigger);
158		    else if (errors == 10)
159			printf("  ...\n");
160		    errors++;
161		    }
162	    }
163	}
164    }
165
166    if (errors != 0)
167	printf(" %d errors for pattern %16llx\n", errors, pattern);
168    return errors;
169}
170
171
172#if 0  /* Still useful? */
173/*  *********************************************************************
174    *  HSP commands
175    ********************************************************************* */
176
177#define TX_RAM_READCTRL(port)                                            \
178    A_BCM1480_HSP_REGISTER(port, R_BCM1480_HSP_TX_RAM_READCTL)
179#define TX_RAM_READWINDOW(port)                                          \
180    A_BCM1480_HSP_REGISTER(port, R_BCM1480_HSP_TX_RAM_READWINDOW)
181
182static uint64_t
183tx_ram_read(uint_t node, uint_t port, uint_t file, uint_t addr)
184{
185    uint64_t prefix = ((uint64_t)node) << 36;
186
187    phys_write64(prefix | TX_RAM_READCTRL(port),
188		 (V_BCM1480_HSP_TXVIS_RAM(file) |
189		  V_BCM1480_HSP_TXVIS_RAM_ADDR(addr)));
190    return phys_read64(prefix | TX_RAM_READWINDOW(port));
191}
192
193static int
194ui_cmd_ccn_txram(ui_cmdline_t *cmd,int argc,char *argv[])
195{
196    uint_t node, port;
197    uint_t low, high, idx;
198    char *x;
199
200    low = 0; high = 65535;
201
202    node = 0;
203    port = 0;
204    if (cmd_sw_value(cmd, "-n", &x)) {
205	node = atoi(x);
206	node &= 0xF;
207	}
208
209    if ((x = cmd_getarg(cmd,0))) low = xtoi(x);
210    if ((x = cmd_getarg(cmd,1))) high = xtoi(x);
211
212    for (idx = low; idx <= high; idx++) {
213	printf("%04X:  ", idx);
214	printf("%016llX   ",
215	       tx_ram_read(node, port,
216			   K_BCM1480_HSP_TXVIS_RAM_DRAM_128_151, idx));
217	printf("%016llX ",
218	       tx_ram_read(node, port,
219			   K_BCM1480_HSP_TXVIS_RAM_DRAM_64_127, idx));
220	printf("%016llX\n",
221	       tx_ram_read(node, port,
222			   K_BCM1480_HSP_TXVIS_RAM_DRAM_0_63, idx));
223	if (console_status()) break;
224	}
225
226    return 0;
227}
228
229
230#define RX_RAM_READCTRL(port)                                            \
231    A_BCM1480_HSP_REGISTER(port, R_BCM1480_HSP_RX_RAM_READCTL)
232#define RX_RAM_READWINDOW(port)                                          \
233    A_BCM1480_HSP_REGISTER(port, R_BCM1480_HSP_RX_RAM_READWINDOW)
234
235static uint64_t
236rx_ram_read(uint_t node, uint_t port, uint_t file, uint_t addr)
237{
238    uint64_t prefix = ((uint64_t)node) << 36;
239
240    phys_write64(prefix | RX_RAM_READCTRL(port),
241		 (V_BCM1480_HSP_RXVIS_RAM(file) |
242		  V_BCM1480_HSP_RXVIS_RAM_ADDR(addr)));
243    return phys_read64(prefix | RX_RAM_READWINDOW(port));
244}
245
246static int
247ui_cmd_ccn_rxram(ui_cmdline_t *cmd,int argc,char *argv[])
248{
249    uint_t node, port;
250    uint_t low, high, idx;
251    char *x;
252
253    low = 0; high = 65535;
254
255    node = 0;
256    port = 0;
257    if (cmd_sw_value(cmd, "-n", &x)) {
258	node = atoi(x);
259	node &= 0xF;
260	}
261
262    if ((x = cmd_getarg(cmd,0))) low = xtoi(x);
263    if ((x = cmd_getarg(cmd,1))) high = xtoi(x);
264
265    for (idx = low; idx <= high; idx++) {
266	printf("%04X:  ", idx);
267	printf("%016llX   ",
268	       rx_ram_read(node, port,
269			   K_BCM1480_HSP_RXVIS_RAM_DRAM_128_151, idx));
270	printf("%016llX ",
271	       rx_ram_read(node, port,
272			   K_BCM1480_HSP_RXVIS_RAM_DRAM_64_127, idx));
273	printf("%016llX\n",
274	       rx_ram_read(node, port,
275			   K_BCM1480_HSP_RXVIS_RAM_DRAM_0_63, idx));
276	if (console_status()) break;
277	}
278
279    return 0;
280
281}
282
283
284#define TX_RF_READCTRL(port)                                            \
285    A_BCM1480_HSP_REGISTER(port, R_BCM1480_HSP_TX_RF_READCTL)
286#define TX_RF_READWINDOW(port)                                          \
287    A_BCM1480_HSP_REGISTER(port, R_BCM1480_HSP_TX_RF_READWINDOW)
288
289static uint64_t
290tx_rf_read(uint_t node, uint_t port, uint_t file, uint_t addr)
291{
292    uint64_t prefix = ((uint64_t)node) << 36;
293
294    phys_write64(prefix | TX_RF_READCTRL(port),
295		 (V_BCM1480_HSP_TXRFVIS_RAM(file) |
296		  V_BCM1480_HSP_TXRFVIS_RAM_ADDR(addr)));
297    return phys_read64(prefix | TX_RF_READWINDOW(port));
298}
299
300static int
301ui_cmd_ccn_txvis(ui_cmdline_t *cmd,int argc,char *argv[])
302{
303    uint_t node, port, reg;
304    uint_t idx;
305    uint64_t val,val2,val3;
306    char *x;
307
308    if (cmd_getarg(cmd,0))
309	reg = atoi(cmd_getarg(cmd,0));
310    else
311	reg = 0;   /* Default to {head, tail, phitcnt} */
312
313    node = 0;
314    if (cmd_sw_value(cmd, "-n", &x)) {
315	node = atoi(x);
316	node &= 0xF;
317	}
318
319    port = 0;
320    if (cmd_sw_value(cmd, "-p", &x)) {
321	port = atoi(x);
322	}
323    if (port >= 3) return ui_showusage(cmd);
324
325    printf("node %d: TX port %d register file #%d\n", node, port, reg);
326
327    switch (reg) {
328	default:
329	    for (idx = 0; idx < 24; idx++) {
330		printf("Regfile[%02X] = %016llX\n",
331		       idx, tx_rf_read(node, port, reg, idx));
332		}
333
334	    break;
335	case 0:
336	    for (idx = 0; idx < 24; idx++) {
337		val =  tx_rf_read(node, port, 0, idx);
338		val2 = tx_rf_read(node, port, 1, idx);
339		val3 = tx_rf_read(node, port, 8, idx);
340		printf("Chan %2d   Head:%04X  Tail:%04X  Phit:%04X\n", idx,
341		       (uint32_t)val, (uint32_t)val2, (uint32_t)val3);
342		}
343	    break;
344
345
346	case 2: case 5:
347	    for (idx = 0; idx < 24; idx++) {
348		val =  tx_rf_read(node, port, reg+0, idx);
349		val2 = tx_rf_read(node, port, reg+1, idx);
350		val3 = tx_rf_read(node, port, reg+2, idx);
351		printf("Chan %2d   Meta:%08llX %s %s BC:%2d %s IVC:%2d Data:%02llX_%016llX\n",
352		       idx, val3,
353		       (val3 & 1) ? "SOP" : "---",
354		       (val3 & 2) ? "EOP" : "---",
355		       (int)((val3 >> 2) & 15),
356		       (val3 & 64) ? "ERR" : "OK ",
357		       (int)(val3 >> 7),
358		       val2, val);
359		}
360	    break;
361
362	case 9:
363	    for (idx = 0; idx < 24; idx++) {
364		val = tx_rf_read(node, port, reg, idx);
365		printf("Chan %2d   Push:%d   Pop:%d\n", idx,
366		       (int)(val & 0x0F), (int)((val >> 4) & 0x0F));
367		}
368	    break;
369
370	case 10:
371	    val = tx_rf_read(node, port, reg, 0);
372	    printf("Ready to pick:  %06llx\n",((val >> 32) & 0xFFFFFF));
373	    printf("IVC OK:         %06llx\n",(val & 0xFFFFFF));
374	    break;
375	}
376
377    return 0;
378}
379
380
381#define RX_RF_READCTRL(port)                                            \
382    A_BCM1480_HSP_REGISTER(port, R_BCM1480_HSP_RX_RF_READCTL)
383#define RX_RF_READWINDOW(port)                                          \
384    A_BCM1480_HSP_REGISTER(port, R_BCM1480_HSP_RX_RF_READWINDOW)
385
386static uint64_t
387rx_rf_read(uint_t node, uint_t port, uint_t file, uint_t addr)
388{
389    uint64_t prefix = ((uint64_t)node) << 36;
390
391    phys_write64(prefix | RX_RF_READCTRL(port),
392		 (V_BCM1480_HSP_RXRFVIS_RAM(file) |
393		  V_BCM1480_HSP_RXRFVIS_RAM_ADDR(addr)));
394    return phys_read64(prefix | RX_RF_READWINDOW(port));
395}
396
397static int
398ui_cmd_ccn_rxvis(ui_cmdline_t *cmd,int argc,char *argv[])
399{
400    uint_t node, port, reg;
401    uint_t idx;
402    uint64_t val, val2, val3;
403    char *x;
404
405    if (cmd_getarg(cmd,0))
406	reg = atoi(cmd_getarg(cmd,0));
407    else
408	reg = 5;   /* Default to {head, tail, phitcnt} */
409
410    node = 0;
411    if (cmd_sw_value(cmd, "-n", &x)) {
412	node = atoi(x);
413	node &= 0xF;
414	}
415
416    port = 0;
417    if (cmd_sw_value(cmd, "-p", &x)) {
418	port = atoi(x);
419	}
420    if (port >= 3) return ui_showusage(cmd);
421
422    printf("node %d: RX port %d register file #%d\n", node, port, reg);
423
424    switch (reg) {
425	case 0:
426	    for (idx = 0; idx < 24; idx++) {
427		val =  rx_rf_read(node, port, 0, idx);
428		val2 = rx_rf_read(node, port, 1, idx);
429		val3 = rx_rf_read(node, port, 2, idx);
430		printf("Chan %2d   Meta:%016llX  Data:%016llX_%016llX\n", idx,
431		       val3, val, val2);
432		}
433	    break;
434	case 5:
435	    for (idx = 0; idx < 27; idx++) {
436		val =  rx_rf_read(node, port, 5, idx);
437		val2 = rx_rf_read(node, port, 6, idx);
438		val3 = rx_rf_read(node, port, 8, idx);
439		printf("Chan %2d   Head:%04X  Tail:%04X  Phit:%04X\n",idx,
440		       (uint32_t)val, (uint32_t)val2, (uint32_t)val3);
441		}
442	    break;
443	default:
444	    for (idx = 0; idx < 32; idx++) {
445		val = rx_rf_read(node, port, reg, idx);
446		printf("Regfile[%02X] = %016llX\n", idx, val);
447		}
448	}
449
450    return 0;
451}
452#endif /* useful? */
453
454
455/*  *********************************************************************
456    *  ccnuma management commands
457    ********************************************************************* */
458
459static int
460ui_cmd_testrld(ui_cmdline_t *cmd, int argc, char *argv[])
461{
462    static const uint64_t patterns[4] = {
463	0xFFFFFFFFFFFFFFFFULL, 0xAAAAAAAAAAAAAAAAULL,
464	0x5555555555555555ULL, 0x0000000000000000ULL
465    };
466    /* Note that the final pattern is all 0's, to leave RLD entries invalid. */
467    unsigned int node;
468    char *x;
469    int errors;
470    int i;
471
472    node = 0;
473    if (argc > 0) {
474	x = cmd_getarg(cmd, 0);
475	node = atoi(x);
476	if (node < 4 || node > 14) {
477	    printf("Invalid node number %d\n", node);
478	    return CFE_ERR;
479	    }
480
481	}
482
483    errors = 0;
484    if (0)
485      printf ("%16s -> %16s\n", "write field", "read trigger");
486
487    for (i=0; i<4; ++i) {
488	fill_rld(node, patterns[i], ((patterns[i] >> 4) & 0x7f), 0, 0);
489	errors +=
490	  check_rld(node, patterns[i], ((patterns[i] >> 4) & 0x7f), 0, 0);
491	}
492
493    printf(" %d total errors\n", errors);
494    return (errors != 0 ? -1 : 0);
495}
496
497/* The following command can be issued multiple times to enable all
498   the relevant ports for a particular node. */
499static int
500ui_cmd_ccn_enable(ui_cmdline_t *cmd,int argc,char *argv[])
501{
502    unsigned int node;
503    unsigned int port;
504    uint64_t localcfg;
505    char *x;
506
507    localcfg = phys_read64(A_SCD_SYSTEM_CFG);
508    if (argc == 0) {
509	node = G_BCM1480_SYS_NODEID(localcfg);
510	}
511    else {
512	x = cmd_getarg(cmd, 0);
513	node = atoi(x);
514	if (node < 4 || node > 14) {
515	    printf("Invalid node number %d\n", node);
516	    return CFE_ERR;
517	    }
518	}
519
520    port = 0;
521    if (cmd_sw_value(cmd, "-port", &x)) {
522	port = atoi(x);
523	if (port > 2) {
524	    printf("Invalid port number %d\n", port);
525	    return CFE_ERR;
526	    }
527	}
528
529    if (node == G_BCM1480_SYS_NODEID(localcfg)) {
530	if ((localcfg & M_BCM1480_SYS_CCNUMA_EN) == 0) {
531	    /* Fill the node's rld with invalid entries. */
532	    fill_rld(0, 0, 0, 0, 0);
533
534	    /* Enable local ccnuma. */
535	    localcfg |= M_BCM1480_SYS_CCNUMA_EN;
536	    phys_write64(A_SCD_SYSTEM_CFG, localcfg);
537	    }
538	}
539    else {
540	uint64_t prefix;
541	uint64_t syscfg;
542
543	prefix = (uint64_t)node << 36;
544	syscfg = phys_read64(prefix | A_SCD_SYSTEM_CFG);
545	if ((syscfg & M_BCM1480_SYS_CCNUMA_EN) == 0) {
546	    /* Fill the node's rld with invalid entries. */
547	    fill_rld(node, 0, 0, 0, 0);
548
549	    /* Enable ccnuma for the node. */
550	    syscfg |= M_BCM1480_SYS_CCNUMA_EN;
551	    phys_write64(prefix | A_SCD_SYSTEM_CFG, syscfg);
552	    }
553	}
554
555    /* Turn on ccnuma for the port. */
556    ht_ccn_enable(node, port, 1);
557
558    return 0;
559}
560
561
562extern int cmd_ccn_test(ui_cmdline_t *cmd,int argc,char *argv[]);
563
564static int
565ui_cmd_ccn_test(ui_cmdline_t *cmd,int argc,char *argv[])
566{
567    return cmd_ccn_test(cmd,argc,argv);
568}
569
570
571/*  *********************************************************************
572    *  ui_init_ccncmds()
573    *
574    *  Add ccnuma-specific commands to the command table
575    *
576    *  Input parameters:
577    *  	   nothing
578    *
579    *  Return value:
580    *  	   0
581    ********************************************************************* */
582
583int
584ui_init_ccncmds(void)
585{
586#if 0  /* Still useful? */
587    cmd_addcmd("ccn txvis",
588	       ui_cmd_ccn_txvis,
589	       NULL,
590	       "Display TX RF Visibility",
591	       "ccn txvis [regset]",
592	       "-n=*;Specify node number|"
593	       "-p=*;Specify port number");
594
595    cmd_addcmd("ccn rxvis",
596	       ui_cmd_ccn_rxvis,
597	       NULL,
598	       "Display RX RF Visibility",
599	       "ccn rxvis [regset]",
600	       "-n=*;Specify node number|"
601	       "-p=*;Specify port number");
602
603    cmd_addcmd("ccn txram",
604	       ui_cmd_ccn_txram,
605	       NULL,
606	       "Display TX buffer RAM",
607	       "ccn txram",
608	       "-n=*;Specify node number");
609
610    cmd_addcmd("ccn rxram",
611	       ui_cmd_ccn_rxram,
612	       NULL,
613	       "Display RX buffer RAM",
614	       "ccn rxram",
615	       "-n=*;Specify node number");
616#endif /* useful? */
617
618    cmd_addcmd("ccn enable",
619	       ui_cmd_ccn_enable,
620	       NULL,
621	       "Enable ccnuma",
622	       "ccn enable [node]",
623	       "-port=*;Specify port number");
624
625    cmd_addcmd("ccn test",
626	       ui_cmd_ccn_test,
627	       NULL,
628	       "Start ccnuma test on this node",
629	       "ccn test",
630	       "");
631
632    cmd_addcmd("test rld",
633	       ui_cmd_testrld,
634	       NULL,
635	       "Check ECC for the RLD",
636	       "test rld [node]",
637	       "");
638
639    return 0;
640}
641