pli.c (17328B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: pli.c 8 * 9 * Provides: 10 * pli_reset_service 11 * pli_getreg_service 12 * pli_setreg_service 13 * 14 * Requires: 15 * soc_internal_reset 16 * soc_internal_<mem> 17 * soc_internal_send_int 18 * pcid_dma_stat_write 19 * pcid_dma_ctrl_write 20 * soc_internal_arl_init 21 */ 22 23 #include <shared/bsl.h> 24 25 #include <sys/types.h> 26 #include <unistd.h> 27 #include <stdlib.h> 28 #include <sys/socket.h> 29 30 #include <sys/time.h> 31 #include <netinet/in.h> 32 #include <arpa/inet.h> 33 #include <memory.h> 34 35 #include <soc/debug.h> 36 #include <sal/appl/io.h> 37 #include <bde/pli/verinet.h> 38 39 #include "pcid.h" 40 #include "mem.h" 41 #include "cmicsim.h" 42 #include "dma.h" 43 #include "pli.h" 44 45 #include <soc/cmic.h> 46 #ifdef BCM_CMICM_SUPPORT 47 #include <soc/cmicm.h> 48 #endif 49 #ifdef BCM_CMICX_SUPPORT 50 #include "cmicx.h" 51 #endif /* BCM_CMICX_SUPPORT */ 52 53 /* 54 * pli_reset_service 55 * 56 * Set PCI memory state to reset defaults 57 */ 58 int pli_reset_service(pcid_info_t *pcid_info) 59 { 60 soc_internal_reset(pcid_info); 61 return 0; 62 } 63 64 65 66 /* 67 * PLI protocol compatible "get register" routines 68 */ 69 70 #ifdef BCM_CMICX_SUPPORT 71 /* cmicx getreg service */ 72 STATIC void 73 pli_cmicx_getreg_service(pcid_info_t * pcid_info, int unit, uint32 type, 74 uint32 regnum, uint32 *value) 75 { 76 uint32 r; 77 switch (type) { 78 79 case SOC_INTERNAL: 80 soc_internal_read_reg(pcid_info, regnum, value); 81 break; 82 83 case PCI_CONFIG: 84 r = regnum & 0xfff; 85 if (r < PCIC_SIZE) { 86 *value = PCIC(pcid_info, r); 87 } 88 break; 89 90 case PCI_MEMORY: 91 92 /* 93 printf("reading CMICx reg!!!!!\n"); 94 printf("0x%08X \n",regnum & 0xFFFFF); 95 */ 96 97 /* normal cmicx register read */ 98 cmicx_pcid_register_read(regnum,value); 99 break; 100 101 } 102 } 103 #endif /* BCM_CMICX_SUPPORT */ 104 105 uint32 pli_cmice_getreg_service(pcid_info_t * pcid_info, int unit, uint32 type, 106 uint32 regnum, uint32 *value) 107 { 108 uint32 r; 109 switch (type) { 110 case PCI_CONFIG: 111 r = regnum & 0xfff; 112 if (r < PCIC_SIZE) { 113 *value = PCIC(pcid_info, r); 114 } 115 break; 116 case PCI_MEMORY: 117 if (pcid_info->regmem_cb) { 118 if ((pcid_info->regmem_cb(pcid_info, BCMSIM_PCI_MEM_READ, 119 regnum, value, 120 BYTES2BITS(sizeof(uint32)))) == 0) 121 break; 122 } 123 r = regnum & 0xffff; 124 if (r == CMIC_LED_CTRL || r == CMIC_LED_STATUS) { 125 *value = 0; 126 } else if (r < PCIM_SIZE(unit)) { 127 *value = PCIM(pcid_info, r); 128 } else { 129 *value = 0xdeadbeef; 130 } 131 break; 132 case I2C_CONFIG: 133 break; 134 case PLI_CONFIG: 135 break; 136 case JTAG_CONFIG: 137 break; 138 139 case SOC_INTERNAL: 140 soc_internal_read_reg(pcid_info, regnum, value); 141 break; 142 } 143 144 return 0; 145 } 146 147 #ifdef BCM_CMICM_SUPPORT 148 STATIC void 149 pli_cmicm_getreg_service(pcid_info_t * pcid_info, int unit, uint32 type, 150 uint32 regnum, uint32 *value) 151 { 152 uint32 r; 153 switch (type) { 154 case PCI_CONFIG: 155 r = regnum & 0xfff; 156 if (r < PCIC_SIZE) { 157 *value = PCIC(pcid_info, r); 158 } 159 break; 160 case PCI_MEMORY: 161 if (pcid_info->regmem_cb) { 162 if ((pcid_info->regmem_cb(pcid_info, BCMSIM_PCI_MEM_READ, 163 regnum, value, 164 BYTES2BITS(sizeof(uint32)))) == 0) 165 break; 166 } 167 r = regnum & 0xfffff; 168 if (r < PCIM_CMICM_SIZE) { 169 *value = PCIM(pcid_info, r); 170 } else { 171 *value = 0xdeadbeef; 172 } 173 break; 174 case I2C_CONFIG: 175 break; 176 case PLI_CONFIG: 177 break; 178 case JTAG_CONFIG: 179 break; 180 181 case SOC_INTERNAL: 182 soc_internal_read_reg(pcid_info, regnum, value); 183 break; 184 } 185 } 186 #endif /* BCM_CMICM_SUPPORT */ 187 188 /* general getreg service */ 189 uint32 190 pli_getreg_service(pcid_info_t * pcid_info, int unit, uint32 type, 191 uint32 regnum) 192 { 193 char buffer[35]; 194 uint32 value, rv; 195 uint32 data[2]; 196 197 PCID_MEM_LOCK(pcid_info); 198 199 pcid_type_name(buffer, type); 200 201 if ((regnum & 3) && type != SOC_INTERNAL) { 202 sal_printf("pli_getreg_service: unaligned access, " 203 "type=0x%x addr=0x%x\n", type, regnum); 204 regnum &= ~3; 205 } 206 207 value = 0xffffffff; /* Default value */ 208 data[0] = 0xffffffff; 209 data[1] = 0xffffffff; 210 211 212 { 213 /* we have an error here - only BCM56870_A0 and BCM56980_A0 supports cmicx as of right now */ 214 } 215 216 217 /* non-cmicx case */ 218 #ifdef BCM_CMICM_SUPPORT 219 if (pcid_info->cmicm >= CMC0) { 220 /* coverity[overrun-buffer-val] */ 221 pli_cmicm_getreg_service(pcid_info, unit, type, regnum, data); 222 value = data[0]; 223 } else 224 #endif 225 #ifdef BCM_CMICX_SUPPORT 226 /* if we are dealing with the cmicx, do special stuff */ 227 if (soc_feature(pcid_info->unit, soc_feature_cmicx)) { 228 pli_cmicx_getreg_service(pcid_info, unit, type, regnum, data); 229 value = data[0]; 230 } else 231 #endif /* BCM_CMICX_SUPPORT */ 232 { 233 pli_cmice_getreg_service(pcid_info, unit, type, regnum, data); 234 value = data[0]; 235 } 236 237 if (pcid_info->opt_pli_verbose) { 238 LOG_VERBOSE(BSL_LS_SOC_COMMON, 239 (BSL_META_U(unit, 240 "%s READ @0x%x => 0x%x\n"), buffer, regnum, value)); 241 } 242 243 rv = soc_internal_endian_swap(pcid_info, value, MF_ES_PIO); 244 245 PCID_MEM_UNLOCK(pcid_info); 246 247 return rv; 248 } 249 250 251 252 /* 253 * PLI protocol compatible "set register" routines 254 */ 255 256 #ifdef BCM_CMICX_SUPPORT 257 /* cmicx setreg service */ 258 STATIC void 259 pli_cmicx_setreg_service(pcid_info_t * pcid_info, int unit, uint32 type, 260 uint32 regnum, uint32 value) 261 { 262 uint32 r; 263 uint32 data[2]; 264 265 switch (type) { 266 267 case SOC_INTERNAL: 268 data[0] = value; 269 data[1] = 0; 270 soc_internal_write_reg(pcid_info, regnum, data); 271 break; 272 273 case PCI_CONFIG: 274 r = regnum & 0xfff; 275 if (r < PCIC_SIZE) { 276 PCIC(pcid_info, r) = value; 277 } 278 break; 279 280 /* this is where we perform a normal register access with the cmicx sim */ 281 case PCI_MEMORY: 282 283 /* 284 printf("writing CMICx reg!!!!!\n"); 285 printf("0x%08X \n",regnum & 0xFFFFF); 286 */ 287 288 cmicx_pcid_register_write(regnum,value); 289 break; 290 291 } 292 293 } 294 #endif /* BCM_CMICX_SUPPORT */ 295 296 uint32 pli_cmice_setreg_service(pcid_info_t * pcid_info, int unit, uint32 type, 297 uint32 regnum, uint32 value) 298 { 299 uint32 r; 300 uint32 data[2]; 301 302 switch (type) { 303 case SOC_INTERNAL: 304 data[0] = value; 305 data[1] = 0; 306 soc_internal_write_reg(pcid_info, regnum, data); 307 break; 308 309 case PCI_CONFIG: 310 r = regnum & 0xfff; 311 if (r < PCIC_SIZE) { 312 PCIC(pcid_info, r) = value; 313 } 314 break; 315 case PCI_MEMORY: 316 r = regnum & 0xffff; 317 318 if (pcid_info->i2crom_fp) { 319 fputc((r >> 8) & 0xff, pcid_info->i2crom_fp); 320 fputc((r >> 0) & 0xff, pcid_info->i2crom_fp); 321 fputc((value >> 24) & 0xff, pcid_info->i2crom_fp); 322 fputc((value >> 16) & 0xff, pcid_info->i2crom_fp); 323 fputc((value >> 8) & 0xff, pcid_info->i2crom_fp); 324 fputc((value >> 0) & 0xff, pcid_info->i2crom_fp); 325 } 326 if (pcid_info->regmem_cb) { 327 if ((pcid_info->regmem_cb(pcid_info, BCMSIM_PCI_MEM_WRITE, 328 regnum, &value, 329 BYTES2BITS(sizeof(uint32)))) == 0) 330 break; 331 } 332 switch (r) { 333 case CMIC_SCHAN_CTRL: 334 soc_internal_schan_ctrl_write(pcid_info, value); 335 break; 336 case CMIC_CONFIG: 337 if (value & CC_RESET_CPS) { 338 soc_internal_reset(pcid_info); 339 } else { 340 PCIM(pcid_info, r) = value; 341 } 342 break; 343 case CMIC_IRQ_MASK: 344 PCIM(pcid_info, r) = value; 345 soc_internal_send_int(pcid_info); /* Send int if pending */ 346 break; 347 case CMIC_DMA_STAT: 348 pcid_dma_stat_write(pcid_info, value); 349 break; 350 case CMIC_DMA_CTRL: 351 pcid_dma_ctrl_write(pcid_info, value); 352 break; 353 case CMIC_TABLE_DMA_CFG: 354 PCIM(pcid_info, r) = value; 355 soc_internal_xgs3_table_dma(pcid_info); 356 break; 357 case CMIC_SLAM_DMA_CFG: 358 PCIM(pcid_info, r) = value; 359 soc_internal_xgs3_tslam_dma(pcid_info); 360 break; 361 case CMIC_LED_CTRL: 362 case CMIC_LED_STATUS: 363 break; 364 default: 365 if (r < PCIM_SIZE(unit)) { 366 PCIM(pcid_info, r) = value; 367 if (soc_feature(unit, soc_feature_schmsg_alias)) { 368 if (r < 0x50) { 369 PCIM(pcid_info, r + 0x800) = value; 370 } else if (r >= 0x800 && r < 0x850) { 371 PCIM(pcid_info, r - 0x800) = value; 372 } 373 } 374 } 375 break; 376 } 377 break; 378 case I2C_CONFIG: 379 break; 380 case PLI_CONFIG: 381 break; 382 case JTAG_CONFIG: 383 break; 384 } 385 386 return 0; 387 } 388 389 #ifdef BCM_CMICM_SUPPORT 390 STATIC void 391 pli_cmicm_setreg_service(pcid_info_t * pcid_info, int unit, uint32 type, 392 uint32 regnum, uint32 value) 393 { 394 uint32 r; 395 uint32 data[2]; 396 397 switch (type) { 398 case SOC_INTERNAL: 399 data[0] = value; 400 data[1] = 0; 401 soc_internal_write_reg(pcid_info, regnum, data); 402 break; 403 404 case PCI_CONFIG: 405 r = regnum & 0xfff; 406 if (r < PCIC_SIZE) { 407 PCIC(pcid_info, r) = value; 408 } 409 break; 410 411 case PCI_MEMORY: 412 r = regnum & 0xfffff; 413 if (pcid_info->i2crom_fp) { 414 fputc((r >> 8) & 0xff, pcid_info->i2crom_fp); 415 fputc((r >> 0) & 0xff, pcid_info->i2crom_fp); 416 fputc((value >> 24) & 0xff, pcid_info->i2crom_fp); 417 fputc((value >> 16) & 0xff, pcid_info->i2crom_fp); 418 fputc((value >> 8) & 0xff, pcid_info->i2crom_fp); 419 fputc((value >> 0) & 0xff, pcid_info->i2crom_fp); 420 } 421 if (pcid_info->regmem_cb) { 422 if ((pcid_info->regmem_cb(pcid_info, BCMSIM_PCI_MEM_WRITE, 423 regnum, &value, 424 BYTES2BITS(sizeof(uint32)))) == 0) 425 break; 426 } 427 switch (r) { 428 case CMIC_CMC0_SCHAN_CTRL_OFFSET: 429 soc_internal_cmicm_schan_ctrl_write(pcid_info, regnum, value); 430 break; 431 case CMIC_CPS_RESET_OFFSET: 432 if (value & CMIC_CPS_RESET) { 433 soc_internal_reset(pcid_info); 434 } else { 435 PCIM(pcid_info, r) = value; 436 } 437 break; 438 case CMIC_CMC0_PCIE_IRQ_MASK0_OFFSET: 439 case CMIC_CMC0_PCIE_IRQ_MASK1_OFFSET: 440 case CMIC_CMC0_PCIE_IRQ_MASK2_OFFSET: 441 PCIM(pcid_info, r) = value; 442 soc_internal_cmicm_send_int(pcid_info, r); /* Send int if pending */ 443 break; 444 case CMIC_CMC0_CH0_DMA_CTRL_OFFSET: 445 case CMIC_CMC0_CH1_DMA_CTRL_OFFSET: 446 case CMIC_CMC0_CH2_DMA_CTRL_OFFSET: 447 case CMIC_CMC0_CH3_DMA_CTRL_OFFSET: 448 pcid_dma_cmicm_ctrl_write(pcid_info, r, value); 449 break; 450 case CMIC_CMC0_DMA_STAT_CLR_OFFSET: 451 if (value & 0xf) { 452 PCIM(pcid_info, CMIC_CMC0_DMA_STAT_OFFSET) &= ~(value & 0xf); 453 switch (value & 0xf) { 454 case 1: 455 /* PCIM(pcid_info, CMIC_CMC0_IRQ_STAT0_OFFSET) &= ~(IRQ_CMCx_DESC_DONE(0)); */ 456 pcid_reg_and_write(pcid_info, CMIC_CMC0_IRQ_STAT0_OFFSET, IRQ_CMCx_DESC_DONE(0)); 457 break; 458 case 2: 459 /* PCIM(pcid_info, CMIC_CMC0_IRQ_STAT0_OFFSET) &= ~(IRQ_CMCx_DESC_DONE(1)); */ 460 pcid_reg_and_write(pcid_info, CMIC_CMC0_IRQ_STAT0_OFFSET, IRQ_CMCx_DESC_DONE(1)); 461 break; 462 case 4: 463 /* PCIM(pcid_info, CMIC_CMC0_IRQ_STAT0_OFFSET) &= ~(IRQ_CMCx_DESC_DONE(2)); */ 464 pcid_reg_and_write(pcid_info, CMIC_CMC0_IRQ_STAT0_OFFSET, IRQ_CMCx_DESC_DONE(2)); 465 break; 466 case 8: 467 /* PCIM(pcid_info, CMIC_CMC0_IRQ_STAT0_OFFSET) &= ~(IRQ_CMCx_DESC_DONE(3)); */ 468 pcid_reg_and_write(pcid_info, CMIC_CMC0_IRQ_STAT0_OFFSET, IRQ_CMCx_DESC_DONE(3)); 469 } 470 } 471 break; 472 case CMIC_CMC0_TABLE_DMA_CFG_OFFSET: 473 PCIM(pcid_info, r) = value; 474 soc_internal_xgs3_cmicm_table_dma(pcid_info); 475 break; 476 case CMIC_CMC0_SLAM_DMA_CFG_OFFSET: 477 PCIM(pcid_info, r) = value; 478 soc_internal_xgs3_cmicm_tslam_dma(pcid_info); 479 break; 480 case CMIC_CMCx_SBUSDMA_CH0_CONTROL_OFFSET(0): 481 case CMIC_CMCx_SBUSDMA_CH0_CONTROL_OFFSET(1): 482 case CMIC_CMCx_SBUSDMA_CH0_CONTROL_OFFSET(2): 483 case CMIC_CMCx_SBUSDMA_CH1_CONTROL_OFFSET(0): 484 case CMIC_CMCx_SBUSDMA_CH1_CONTROL_OFFSET(1): 485 case CMIC_CMCx_SBUSDMA_CH1_CONTROL_OFFSET(2): 486 case CMIC_CMCx_SBUSDMA_CH2_CONTROL_OFFSET(0): 487 case CMIC_CMCx_SBUSDMA_CH2_CONTROL_OFFSET(1): 488 case CMIC_CMCx_SBUSDMA_CH2_CONTROL_OFFSET(2): 489 PCIM(pcid_info, r) = value; 490 soc_internal_cmicm_sbusdma(pcid_info, r); 491 break; 492 case CMIC_CMCx_FIFO_CHy_RD_DMA_CFG_OFFSET(0,0): 493 case CMIC_CMCx_FIFO_CHy_RD_DMA_CFG_OFFSET(1,0): 494 case CMIC_CMCx_FIFO_CHy_RD_DMA_CFG_OFFSET(2,0): 495 case CMIC_CMCx_FIFO_CHy_RD_DMA_CFG_OFFSET(0,1): 496 case CMIC_CMCx_FIFO_CHy_RD_DMA_CFG_OFFSET(1,1): 497 case CMIC_CMCx_FIFO_CHy_RD_DMA_CFG_OFFSET(2,1): 498 case CMIC_CMCx_FIFO_CHy_RD_DMA_CFG_OFFSET(0,2): 499 case CMIC_CMCx_FIFO_CHy_RD_DMA_CFG_OFFSET(1,2): 500 case CMIC_CMCx_FIFO_CHy_RD_DMA_CFG_OFFSET(2,2): 501 case CMIC_CMCx_FIFO_CHy_RD_DMA_CFG_OFFSET(0,3): 502 case CMIC_CMCx_FIFO_CHy_RD_DMA_CFG_OFFSET(1,3): 503 case CMIC_CMCx_FIFO_CHy_RD_DMA_CFG_OFFSET(2,3): 504 PCIM(pcid_info, r) = value; 505 do { 506 int cmc, ch; 507 uint32 done = 0x10; /* bit[4:4]: DONEf */ 508 cmc = (r - CMIC_CMC0_FIFO_CH0_RD_DMA_CFG_OFFSET) / 0x1000; 509 ch = (r & 0xf) / 4; 510 511 if ((value & 0x80000001) == 0x80000001) { /* bit[31:31]: ABORTf */ 512 pcid_reg_or_write(pcid_info, 513 CMIC_CMCx_FIFO_CHy_RD_DMA_STAT_OFFSET(cmc, ch), done); 514 } else if ((value & 0x1) == 0) { /* bit[0:0]: ENABLEf */ 515 pcid_reg_and_write(pcid_info, 516 CMIC_CMCx_FIFO_CHy_RD_DMA_STAT_OFFSET(cmc, ch), done); 517 } 518 } while(0); 519 break; 520 default: 521 if (r < PCIM_CMICM_SIZE) { 522 PCIM(pcid_info, r) = value; 523 } 524 break; 525 } 526 break; 527 case I2C_CONFIG: 528 break; 529 case PLI_CONFIG: 530 break; 531 case JTAG_CONFIG: 532 break; 533 } 534 535 } 536 #endif /* BCM_CMICM_SUPPORT */ 537 538 /* setreg service */ 539 uint32 540 pli_setreg_service(pcid_info_t * pcid_info, int unit, uint32 type, 541 uint32 regnum, uint32 value) 542 { 543 char buffer[35]; 544 545 PCID_MEM_LOCK(pcid_info); 546 547 pcid_type_name(buffer, type); 548 549 value = soc_internal_endian_swap(pcid_info, value, MF_ES_PIO); 550 551 if ((regnum & 3) && type != SOC_INTERNAL) { 552 sal_printf("pli_setreg_service: unaligned access, " 553 "type=0x%x addr=0x%x value=0x%x\n", type, regnum, value); 554 regnum &= ~3; 555 } 556 557 #if 0 558 LOG_VERBOSE(BSL_LS_SOC_COMMON, 559 (BSL_META_U(unit, 560 "%s WRITE @0x%x <= 0x%x\n"), buffer, regnum, value)); 561 #endif 562 563 if (pcid_info->opt_pli_verbose) { 564 LOG_VERBOSE(BSL_LS_SOC_COMMON, 565 (BSL_META_U(unit, 566 "%s WRITE @0x%x <= 0x%x\n"), buffer, regnum, value)); 567 } 568 569 /* this is the old code that existed before adding the cmicx stuff */ 570 #ifdef BCM_CMICM_SUPPORT 571 if (pcid_info->cmicm >= CMC0) { 572 pli_cmicm_setreg_service(pcid_info, unit, type, regnum, value); 573 } else 574 #endif 575 #ifdef BCM_CMICX_SUPPORT 576 /* if we are dealing with the cmicx, do special stuff */ 577 if (soc_feature(pcid_info->unit, soc_feature_cmicx)) { 578 pli_cmicx_setreg_service(pcid_info, unit, type, regnum, value); 579 } else 580 #endif /* BCM_CMICX_SUPPORT */ 581 { 582 pli_cmice_setreg_service(pcid_info, unit, type, regnum, value); 583 } 584 585 PCID_MEM_UNLOCK(pcid_info); 586 587 return 0; 588 }