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