rcpu.c (20260B)
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 * Utility routines for RCPU packets encap/decap 8 */ 9 10 #include <sal/core/libc.h> 11 #include <shared/bsl.h> 12 #include <soc/util.h> 13 #include <soc/drv.h> 14 15 #ifdef INCLUDE_RCPU 16 17 #define SOC_RCPU_BENCHMARK 1 18 #define MAX_RETRY_ATTEMPTS 3 19 #define SOC_RCPU_F_INITED 0x1 20 21 /* The data length of CMIC request packet */ 22 #define CMIC_REQUEST_DATA_LEN 0x8 23 24 soc_rcpu_control_t *soc_rcpu_control[SOC_MAX_NUM_DEVICES]; 25 26 #define SOC_RCPU_CONTROL(_unit) soc_rcpu_control[_unit] 27 #define RCPU_TRANS_PTR_SET(unit) _rcpu_trans_ptr = CMVEC(unit).rcpu_tp; 28 29 /* 30 * Data format of CMIC request packet: 31 * The first word of each pair is an address/operation word. 32 * The bottom 24 bits of the word are the address in CMIC register space. 33 * The top 8 bits encode the operation type and the size of the request: 34 * ED00 00SS 35 * 0 bits are reserved and must be zero. 36 * E is an error bit and must be 0 in a CMIC_REQUEST. 37 * D is a direction bit (0 means read, 1 means write) 38 * SS are the size of the operation (00 is reserved, 01 is 1 byte, 39 * 10 is 2 bytes, 11 is 4 bytes) 40 */ 41 #if defined(LE_HOST) 42 #define CMIC_REQ_ADDR_OP_SET(ptr, addr, read_op) \ 43 (((uint32 *)(ptr))[0] = (soc_htonl(addr) | 0x3 | \ 44 ((0 == read_op)? (1 << 6) : 0))) 45 46 #define CMIC_REQ_VALUE_SET(ptr, read_op, val) \ 47 (((uint32 *)(ptr))[1] = ((0 == read_op)? soc_htonl(*val): 0)) 48 #else 49 #define CMIC_REQ_ADDR_OP_SET(ptr, addr, read_op) \ 50 (((uint32 *)(ptr))[0] = (addr | 0x3000000 | \ 51 ((0 == read_op)? (1 << 30): 0))) 52 53 #define CMIC_REQ_VALUE_SET(ptr, read_op, val) \ 54 (((uint32 *)(ptr))[1] = ((0 == read_op)? *val: 0)) 55 #endif 56 57 /*********************************************************** 58 * 59 * Functions: 60 * _soc_rcpu_tp_rx 61 * Purpose: 62 * Main entry for all received RCPU packets. 63 * 1. Perform decapsulation to find which unit this packet belongs to. 64 * 2. Handle SCHAN or CMIC reply packets. 65 * 3. Disptach ToCPU and Interrupt packets. 66 * 67 * Parameters: 68 * rx_unit - (IN) Recevie tp unit number 69 * pkt - (IN) Packet buffer where to decap header 70 * pkt_len - (IN) Packet length 71 * cookie - (IN) Callback cookie 72 * Returns: 73 * SOC_E_NONE 74 * -1 : Not RCPU packets or error case 75 * Notes: 76 * Assumes buffers are valid and contain enough memory space. 77 */ 78 STATIC int 79 _soc_rcpu_tp_rx(int rx_unit, uint8 *pkt, int pkt_len, void *cookie) 80 { 81 int unit; 82 rcpu_encap_info_t info; 83 84 SOC_IF_ERROR_RETURN(soc_rcpu_decap(pkt, &unit, &info)); 85 86 if (NULL == SOC_RCPU_CONTROL(unit)) { 87 /* Not initialized */ 88 return -1; 89 } 90 91 if ((SOC_RCPU_OP_SCHAN_REPLY == info.operation) || 92 (SOC_RCPU_OP_CMIC_REPLY == info.operation)) { 93 94 if (info.flags & SOC_RCPU_FLAG_BUSY) { 95 if (LOG_CHECK(BSL_LS_SOC_RCPU | BSL_INFO)) { 96 LOG_CLI((BSL_META_U(unit, 97 "****RCPU REPLY BUSY****\n"))); 98 } 99 /* Let it timeout and retry. */ 100 return -1; 101 } 102 103 /* 104 * Check Fail flag 105 * If FAIL, then set length appropriately 106 */ 107 if (info.flags & SOC_RCPU_FLAG_FAIL) { 108 if (LOG_CHECK(BSL_LS_SOC_RCPU | BSL_INFO)) { 109 LOG_CLI((BSL_META_U(unit, 110 "****RCPU REPLY FAIL****\n"))); 111 soc_dma_ether_dump(unit, "RCPU_REP ", pkt, pkt_len, 0); 112 } 113 info.datalen = pkt_len - info.cmic_hdr_size; 114 } 115 116 if (++info.transid == SOC_RCPU_CONTROL(unit)->transid) { 117 sal_memcpy(SOC_RCPU_CONTROL(unit)->reply_data, 118 pkt + info.cmic_hdr_size, 119 info.datalen); 120 if (SOC_RCPU_CONTROL(unit)->schan_reply) { 121 sal_sem_give(SOC_RCPU_CONTROL(unit)->schan_reply); 122 } 123 } 124 return SOC_E_NONE; 125 } 126 127 /* Handle ToCPU packets */ 128 if (SOC_RCPU_OP_TOCPU_PKT == info.operation) { 129 if (SOC_RCPU_CONTROL(unit)->tocpu_cb != NULL) { 130 SOC_RCPU_CONTROL(unit)->tocpu_cb(unit, pkt, pkt_len, &info); 131 } 132 return SOC_E_NONE; 133 } 134 135 #ifdef BCM_CMICM_SUPPORT 136 /* Handle Remote Interrupt packets */ 137 if (SOC_RCPU_OP_INTR_PKT == info.operation) { 138 soc_cmicm_rcpu_intr(unit, (soc_rcpu_intr_packet_t *)(pkt + info.cmic_hdr_size)); 139 return SOC_E_NONE; 140 } 141 #endif /* BCM_CMICM_SUPPORT */ 142 143 return -1; 144 145 } 146 147 /*********************************************************** 148 * 149 * Functions: 150 * soc_rcpu_encap 151 * Purpose: 152 * Encap RCPU CMIC header into the buffer 153 * 154 * Parameters: 155 * unit - (IN) device number 156 * buf - (IN) Buffer where to encap header. 157 * info - (IN) Encap CMIC packet header information. 158 * Returns: 159 * SOC_E_NONE 160 * SOC_E_PARAM 161 * Notes: 162 * Assumes buffers are valid and contain enough memory space. 163 */ 164 int 165 soc_rcpu_encap(int unit, uint8 *buf, rcpu_encap_info_t *info) 166 { 167 soc_rcpu_cfg_t rcpu_cfg; 168 rcpu1_cmic_pkt_hdr_t *hdr = (rcpu1_cmic_pkt_hdr_t *)buf; 169 170 if (!SOC_IS_RCPU_ONLY(unit)) { 171 return SOC_E_PARAM; 172 } 173 174 SOC_IF_ERROR_RETURN(soc_cm_get_rcpu_cfg(unit, &rcpu_cfg)); 175 176 sal_memcpy(hdr->dst_mac, rcpu_cfg.dst_mac, 6); 177 sal_memcpy(hdr->src_mac, rcpu_cfg.src_mac, 6); 178 hdr->tpid = soc_htons(rcpu_cfg.tpid); 179 hdr->vlan = soc_htons(rcpu_cfg.vlan); 180 hdr->ethertype = soc_htons(rcpu_cfg.ether_type); 181 hdr->signature = soc_htons(rcpu_cfg.signature); 182 183 hdr->operation = info->operation; 184 hdr->flags = info->flags; 185 hdr->transid = soc_htons(info->transid); 186 hdr->datalen = soc_htons(info->datalen); 187 hdr->replen = soc_htons(info->replen); 188 hdr->reserved = 0; 189 190 return SOC_E_NONE; 191 } 192 193 /*********************************************************** 194 * RCPU CMIC header Decap 195 * 196 * Functions: 197 * soc_rcpu_decap 198 * Purpose: 199 * Parse input buffer and decide to which device number 200 * it should go. 201 * Parameters: 202 * buf - (IN) Buffer where to decap message. 203 * runit - (OUT) Device unit number to which this message belogs. 204 * info - (OUT) Decap CMIC packet header information. 205 * 206 * Returns: 207 * SOC_E_NONE 208 * SOC_E_NOT_FOUND 209 * Notes: 210 * Assumes pointers are valid and contain enough memory space. 211 */ 212 int 213 soc_rcpu_decap(uint8 *buf, int *runit, rcpu_encap_info_t *info) 214 { 215 int rv, unit; 216 soc_rcpu_cfg_t rcpu_cfg; 217 rcpu1_cmic_pkt_hdr_t *hdr = (rcpu1_cmic_pkt_hdr_t *)buf; 218 219 for (unit = 0; unit < soc_cm_get_num_devices(); unit++) { 220 221 if (!SOC_IS_RCPU_ONLY(unit)) { 222 continue; 223 } 224 225 rv = soc_cm_get_rcpu_cfg(unit, &rcpu_cfg); 226 227 if (SOC_E_NONE != rv) { 228 continue; 229 } 230 231 if (sal_memcmp(buf+6, rcpu_cfg.dst_mac, 6)) { 232 continue; 233 } 234 235 if (rcpu_cfg.tpid != soc_ntohs(hdr->tpid) && 236 rcpu_cfg.ether_type != soc_ntohs(hdr->tpid)) { 237 continue; 238 } 239 240 info->cmic_hdr_size = sizeof(rcpu1_cmic_pkt_hdr_t); 241 242 if (rcpu_cfg.tpid == soc_ntohs(hdr->tpid)) { 243 if ((rcpu_cfg.vlan != soc_ntohs(hdr->vlan)) || 244 (rcpu_cfg.ether_type != soc_ntohs(hdr->ethertype))) { 245 /* Could be double tagged */ 246 hdr = (rcpu1_cmic_pkt_hdr_t *)(buf + 4); 247 if (rcpu_cfg.ether_type != soc_ntohs(hdr->ethertype)) { 248 continue; 249 } 250 info->cmic_hdr_size += 4; 251 } 252 } else { 253 /* Could have no vlan tag. */ 254 info->cmic_hdr_size -= 4; 255 hdr = (rcpu1_cmic_pkt_hdr_t *)(buf - 4); 256 } 257 258 if (rcpu_cfg.signature != soc_ntohs(hdr->signature)) { 259 continue; 260 } 261 262 info->operation = hdr->operation; 263 info->flags = hdr->flags; 264 info->transid = soc_ntohs(hdr->transid); 265 info->datalen = soc_ntohs(hdr->datalen); 266 if (hdr->operation == SOC_RCPU_OP_TOCPU_PKT) { 267 /* Count dcb size */ 268 info->dcb_size = (SOC_DCB_SIZE(unit) == 64)? 64:32; 269 } else { 270 info->dcb_size = 0; 271 } 272 *runit = unit; 273 return SOC_E_NONE; 274 } 275 return SOC_E_NOT_FOUND; 276 } 277 278 /* 279 * Function: 280 * soc_rcpu_init 281 * Purpose: 282 * Initialize RCPU master units before BCM module init so each bcm module 283 * can access s-channel registers/tables via RCPU mechanism 284 * Parameters: 285 * unit - (IN) unit number 286 * Returns: 287 * SOC_E_XXX 288 */ 289 int 290 soc_rcpu_init(int unit) 291 { 292 int rv = SOC_E_NONE; 293 rcpu_trans_ptr_t *_rcpu_trans_ptr; 294 295 if (!SOC_UNIT_VALID(unit)){ 296 return SOC_E_UNIT; 297 } 298 299 if (!soc_feature(unit, soc_feature_rcpu_1)) { 300 return SOC_E_NONE; 301 } 302 303 if (SOC_RCPU_CONTROL(unit) && 304 (SOC_RCPU_CONTROL(unit)->flags & SOC_RCPU_F_INITED)) { 305 return SOC_E_NONE; 306 } 307 308 if (SOC_RCPU_CONTROL(unit) == NULL) { 309 SOC_RCPU_CONTROL(unit) = sal_alloc(sizeof(soc_rcpu_control_t), 310 "soc_rcpu_control"); 311 if (SOC_RCPU_CONTROL(unit) == NULL) { 312 return SOC_E_MEMORY; 313 } 314 sal_memset(SOC_RCPU_CONTROL(unit), 0, sizeof(soc_rcpu_control_t)); 315 316 SOC_RCPU_CONTROL(unit)->lock = sal_mutex_create("rcpu_unit_mutex"); 317 if (SOC_RCPU_CONTROL(unit)->lock == NULL) { 318 LOG_ERROR(BSL_LS_SOC_RCPU, 319 (BSL_META_U(unit, 320 "soc_rcpu_init: Failed to create mutex.\n"))); 321 return SOC_E_MEMORY; 322 } 323 324 if ((SOC_RCPU_CONTROL(unit)->schan_reply = 325 sal_sem_create("RCPU SCHAN", sal_sem_BINARY, 0)) == NULL) { 326 LOG_ERROR(BSL_LS_SOC_RCPU, 327 (BSL_META_U(unit, 328 "soc_rcpu_init: Failed to create semaphore.\n"))); 329 return SOC_E_MEMORY; 330 } 331 } 332 333 RCPU_TRANS_PTR_SET(unit); 334 rv = _rcpu_trans_ptr->rcpu_tp_rx_register(_rcpu_trans_ptr->tp_unit, 335 _soc_rcpu_tp_rx, 336 NULL); 337 338 if (SOC_SUCCESS(rv)) { 339 _rcpu_trans_ptr->ref_count++; 340 } 341 342 if (SOC_IS_RCPU_ONLY(unit)) { 343 soc_rcpu_schan_op_register(unit, soc_rcpu_schan_op); 344 } 345 346 SOC_RCPU_CONTROL(unit)->flags |= SOC_RCPU_F_INITED; 347 348 return rv; 349 } 350 /* 351 * Function: 352 * soc_rcpu_deinit 353 * Purpose: 354 * Deinitialize resources of RCPU master units 355 * Parameters: 356 * unit - (IN) unit number 357 * Returns: 358 * SOC_E_XXX 359 */ 360 int 361 soc_rcpu_deinit(int unit) 362 { 363 rcpu_trans_ptr_t *_rcpu_trans_ptr; 364 365 if (!SOC_UNIT_VALID(unit)){ 366 return SOC_E_UNIT; 367 } 368 369 if (!soc_feature(unit, soc_feature_rcpu_1)) { 370 return SOC_E_NONE; 371 } 372 373 (void)soc_rcpu_schan_op_unregister(unit); 374 375 if (SOC_RCPU_CONTROL(unit)) { 376 377 RCPU_TRANS_PTR_SET(unit); 378 379 if (_rcpu_trans_ptr->ref_count > 0) { 380 _rcpu_trans_ptr->ref_count--; 381 if (0 == _rcpu_trans_ptr->ref_count) { 382 _rcpu_trans_ptr->rcpu_tp_rx_unregister(_rcpu_trans_ptr->tp_unit, 383 _soc_rcpu_tp_rx); 384 } 385 } 386 387 if (SOC_RCPU_CONTROL(unit)->lock) { 388 sal_mutex_destroy(SOC_RCPU_CONTROL(unit)->lock); 389 } 390 391 if (SOC_RCPU_CONTROL(unit)->schan_reply) { 392 sal_sem_destroy(SOC_RCPU_CONTROL(unit)->schan_reply); 393 } 394 395 sal_free(SOC_RCPU_CONTROL(unit)); 396 SOC_RCPU_CONTROL(unit) = NULL; 397 } 398 399 return SOC_E_NONE; 400 } 401 402 /* 403 * Function: 404 * soc_rcpu_tocpu_cb_register 405 * Purpose: 406 * Registers ToCPU packet handler 407 * Parameters: 408 * unit - SOC unit # 409 * f - (IN) Function to be called for ToCPU packets 410 * Returns: 411 * SOC_E_XXX 412 */ 413 int 414 soc_rcpu_tocpu_cb_register(int unit, rcpu_tocpu_cb_f f) 415 { 416 if (!SOC_IS_RCPU_UNIT(unit) && !SOC_IS_RCPU_ONLY(unit)) { 417 return SOC_E_UNAVAIL; 418 } 419 420 if (SOC_RCPU_CONTROL(unit) == NULL) { 421 return SOC_E_INIT; 422 } 423 424 if (NULL == f) { 425 return SOC_E_PARAM; 426 } 427 428 SOC_RCPU_CONTROL(unit)->tocpu_cb = f; 429 430 return SOC_E_NONE; 431 } 432 433 /* 434 * Function: 435 * soc_rcpu_tocpu_cb_unregister 436 * Purpose: 437 * Unregisters ToCPU packet handler 438 * 439 * Parameters: 440 * unit - SOC unit # 441 * Returns: 442 * SOC_E_XXX 443 */ 444 int 445 soc_rcpu_tocpu_cb_unregister(int unit) 446 { 447 if (!SOC_IS_RCPU_UNIT(unit) && !SOC_IS_RCPU_ONLY(unit)) { 448 return SOC_E_UNAVAIL; 449 } 450 451 if (SOC_RCPU_CONTROL(unit) == NULL) { 452 return SOC_E_INIT; 453 } 454 455 SOC_RCPU_CONTROL(unit)->tocpu_cb = NULL; 456 457 return SOC_E_NONE; 458 } 459 /* 460 * Function: 461 * soc_rcpu_schan_op 462 * Purpose: 463 * RCPU version of soc_schan_op function 464 * 465 * Returns: 466 * SOC_E_XXX 467 */ 468 int 469 soc_rcpu_schan_op(int unit, schan_msg_t *msg, int dwc_write, int dwc_read) 470 { 471 uint8 *tx_buf; 472 uint32 *buf_ptr; 473 int i, rcpu_schan_pkt_len = 0; 474 int rv = SOC_E_NONE, num_retries; 475 rcpu_encap_info_t info; 476 #if defined(SOC_RCPU_BENCHMARK) 477 sal_usecs_t time_start = 0; 478 sal_usecs_t time_end = 0; 479 #endif /* SOC_RCPU_BENCHMARK */ 480 rcpu_trans_ptr_t *_rcpu_trans_ptr; 481 482 if (SOC_RCPU_CONTROL(unit) == NULL) { 483 return SOC_E_INIT; 484 } 485 486 #if defined(SOC_RCPU_BENCHMARK) 487 if (LOG_CHECK(BSL_LS_SOC_RCPU | BSL_INFO) && 488 LOG_CHECK(BSL_LS_SOC_SCHAN | BSL_INFO)) { 489 time_start = sal_time_usecs(); 490 } 491 #endif /* SOC_RCPU_BENCHMARK */ 492 493 rcpu_schan_pkt_len = sizeof(rcpu1_cmic_pkt_hdr_t) + 4 * dwc_write; 494 rcpu_schan_pkt_len = (rcpu_schan_pkt_len < ENET_MIN_PKT_SIZE)? ENET_MIN_PKT_SIZE:rcpu_schan_pkt_len; 495 496 info.datalen = 4 * dwc_write; 497 info.flags = SOC_RCPU_FLAG_REPLY; 498 info.operation = SOC_RCPU_OP_SCHAN_REQ; 499 /* If dwc_read is 0, get a SCHAN_REPLY as an ACK (1 word) */ 500 info.replen = dwc_read ? 4 * dwc_read : 4; 501 502 SCHAN_LOCK(unit); 503 504 info.transid = SOC_RCPU_CONTROL(unit)->transid++; 505 506 RCPU_TRANS_PTR_SET(unit); 507 508 for (num_retries = 0; num_retries < MAX_RETRY_ATTEMPTS; num_retries++) { 509 510 _rcpu_trans_ptr->rcpu_tp_data_alloc(_rcpu_trans_ptr->tp_unit, 511 rcpu_schan_pkt_len, 512 (void*)&tx_buf); 513 514 if (!tx_buf) { 515 SCHAN_UNLOCK(unit); 516 return SOC_E_MEMORY; 517 } 518 519 /* Construct CMIC header */ 520 soc_rcpu_encap(unit, tx_buf, &info); 521 522 buf_ptr = (uint32 *)(tx_buf + sizeof(rcpu1_cmic_pkt_hdr_t)); 523 524 for (i = 0; i < dwc_write; i++) { 525 buf_ptr[i] = soc_htonl(msg->dwords[i]); 526 } 527 528 _rcpu_trans_ptr->rcpu_tp_tx(_rcpu_trans_ptr->tp_unit, 529 (void*)tx_buf, 530 rcpu_schan_pkt_len, 531 NULL); 532 533 if (sal_sem_take(SOC_RCPU_CONTROL(unit)->schan_reply, 534 SOC_CONTROL(unit)->schanTimeout) == 0) { 535 uint32 *pdata = (uint32 *)SOC_RCPU_CONTROL(unit)->reply_data; 536 for (i = 0; i < dwc_read; i++) { 537 msg->dwords[i] = soc_ntohl(pdata[i]); 538 } 539 rv = SOC_E_NONE; 540 break; 541 } else { 542 rv = SOC_E_TIMEOUT; 543 } 544 } 545 546 SCHAN_UNLOCK(unit); 547 548 #if defined(SOC_RCPU_BENCHMARK) 549 if (LOG_CHECK(BSL_LS_SOC_RCPU | BSL_INFO) && 550 LOG_CHECK(BSL_LS_SOC_SCHAN | BSL_INFO)) { 551 time_end = sal_time_usecs(); 552 LOG_CLI((BSL_META_U(unit, 553 "RCPU schan-op (%d, %d) took %d usecs\n"), 554 dwc_write, dwc_read, SAL_USECS_SUB(time_end, time_start))); 555 } 556 #endif /* SOC_RCPU_BENCHMARK */ 557 558 return rv; 559 } 560 561 #ifdef BCM_CMICM_SUPPORT 562 /* 563 * Functions: 564 * _soc_rcpu_cmic_op 565 * Purpose: 566 * Handling CMIC request packets 567 * Parameters: 568 * unit - (IN) device number 569 * read_op - (IN) 1 = read operation; 0 = write operation 570 * addr - (IN) CMIC address to access 571 * val32 - (IN/OUT) Input for write operation; Output for read operation 572 * 573 * Returns: 574 * SOC_E_XXXE 575 */ 576 STATIC int 577 _soc_rcpu_cmic_op(int unit, int read_op, uint32 addr, uint32 *val32) 578 { 579 uint8 *tx_buf; 580 uint32 *addr_ptr; 581 int rcpu_cmic_pkt_len = 0; 582 int rv = SOC_E_NONE, num_retries; 583 rcpu_encap_info_t info; 584 #if defined(SOC_RCPU_BENCHMARK) 585 sal_usecs_t time_start = 0; 586 sal_usecs_t time_end = 0; 587 #endif /* SOC_RCPU_BENCHMARK */ 588 rcpu_trans_ptr_t *_rcpu_trans_ptr; 589 590 if (SOC_RCPU_CONTROL(unit) == NULL) { 591 return SOC_E_INIT; 592 } 593 594 if (!soc_feature(unit, soc_feature_cmicm)) { 595 return SOC_E_UNIT; 596 } 597 598 #if defined(SOC_RCPU_BENCHMARK) 599 if (LOG_CHECK(BSL_LS_SOC_RCPU | BSL_INFO) && 600 LOG_CHECK(BSL_LS_SOC_PCI | BSL_INFO)) { 601 time_start = sal_time_usecs(); 602 } 603 #endif /* SOC_RCPU_BENCHMARK */ 604 605 /* Use minimum size since the packet length for one operation is 40 bytes. */ 606 rcpu_cmic_pkt_len = ENET_MIN_PKT_SIZE; 607 608 info.datalen = CMIC_REQUEST_DATA_LEN; 609 info.flags = SOC_RCPU_FLAG_REPLY; 610 info.operation = SOC_RCPU_OP_CMIC_REQ; 611 /* Reply length must be the same value as datalen */ 612 info.replen = CMIC_REQUEST_DATA_LEN; 613 614 SCHAN_LOCK(unit); 615 616 info.transid = SOC_RCPU_CONTROL(unit)->transid++; 617 618 RCPU_TRANS_PTR_SET(unit); 619 620 for (num_retries = 0; num_retries < MAX_RETRY_ATTEMPTS; num_retries++) { 621 622 _rcpu_trans_ptr->rcpu_tp_data_alloc(_rcpu_trans_ptr->tp_unit, 623 rcpu_cmic_pkt_len, 624 (void*)&tx_buf); 625 626 if (!tx_buf) { 627 LOG_ERROR(BSL_LS_SOC_RCPU, 628 (BSL_META_U(unit, 629 "rcpu_cmic_read: Failed to allocate memory.\n"))); 630 SCHAN_UNLOCK(unit); 631 return SOC_E_MEMORY; 632 } 633 634 /* Construct CMIC header */ 635 rv = soc_rcpu_encap(unit, tx_buf, &info); 636 637 addr_ptr = (uint32 *)(tx_buf + sizeof(rcpu1_cmic_pkt_hdr_t)); 638 639 CMIC_REQ_ADDR_OP_SET(addr_ptr, addr, read_op); 640 641 CMIC_REQ_VALUE_SET(addr_ptr, read_op, val32); 642 643 rv = _rcpu_trans_ptr->rcpu_tp_tx(_rcpu_trans_ptr->tp_unit, 644 (void*)tx_buf, 645 rcpu_cmic_pkt_len, 646 NULL); 647 648 if (sal_sem_take(SOC_RCPU_CONTROL(unit)->schan_reply, 649 SOC_CONTROL(unit)->schanTimeout) == 0) { 650 uint32 *pdata = (uint32 *)SOC_RCPU_CONTROL(unit)->reply_data; 651 *val32 = soc_ntohl(pdata[1]); 652 rv = SOC_E_NONE; 653 break; 654 } else { 655 rv = SOC_E_TIMEOUT; 656 } 657 } 658 659 SCHAN_UNLOCK(unit); 660 661 #if defined(SOC_RCPU_BENCHMARK) 662 if (LOG_CHECK(BSL_LS_SOC_RCPU | BSL_INFO) && 663 LOG_CHECK(BSL_LS_SOC_PCI | BSL_INFO)) { 664 time_end = sal_time_usecs(); 665 LOG_CLI((BSL_META_U(unit, 666 "RCPU cmic-op took %d usecs\n"), 667 SAL_USECS_SUB(time_end, time_start))); 668 } 669 #endif /* SOC_RCPU_BENCHMARK */ 670 671 return rv; 672 } 673 /* 674 * Functions: 675 * _soc_rcpu_cmic_op 676 * Purpose: 677 * RCPU version for CMIC read operation 678 * Parameters: 679 * unit - (IN) device number 680 * addr - (IN) CMIC address to access 681 * 682 * Returns: 683 * Register value or zero 684 */ 685 uint32 686 soc_rcpu_cmic_read(int unit, uint32 addr) 687 { 688 int rv; 689 uint32 data; 690 691 rv = _soc_rcpu_cmic_op(unit, 1, addr, &data); 692 693 return (SOC_E_NONE == rv)? data : 0; 694 } 695 /* 696 * Functions: 697 * soc_rcpu_cmic_write 698 * Purpose: 699 * RCPU version for CMIC write operation 700 * Parameters: 701 * unit - (IN) device number 702 * addr - (IN) CMIC address to access 703 * data - (IN) Data to write 704 * 705 * Returns: 706 * SOC_E_XXXE 707 */ 708 int 709 soc_rcpu_cmic_write(int unit, uint32 addr, uint32 data) 710 { 711 _soc_rcpu_cmic_op(unit, 0, addr, &data); 712 return 0; 713 } 714 #endif /* BCM_CMICM_SUPPORT */ 715 716 #endif /* INCLUDE_RCPU */