tscbh_sim.c (23695B)
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 * 8 * This software simulator can emulate basic register access for the 9 * TSC/Eagle SerDes PHY. 10 * 11 * The simulator suppor both IEEE clause 22/45 access and Broadcom 12 * proprietary SBUS access. 13 * 14 * Clause 22 address format: 15 * Bits [4:0] : Clause 22 register address 16 * Bits [31:5] : Unused 17 * 18 * Clause 45 address format: 19 * Bits [15:0] : Clause 45 register address 20 * Bits [20:16] : Clause 45 DEVAD 21 * Bits [23:21] : Clause 45 indicator (001b) 22 * Bits [31:24] : Unused 23 * 24 * SBUS address format: 25 * Bits [15:0] : Clause 45 register address 26 * Bits [18:16] : Lane control 27 * Bits [26:19] : Lane multicast (old format) 28 * Bits [31:27] : Clause 45 DEVAD 29 * 30 * The upper 16 bits if the SBUS address format is identical to the 31 * Broadcom Address Extension Register (AER) format. 32 * 33 * The clause 45 indicator serves two purposes which is to ensure that 34 * the upper 16 bits are never zero for a clause 45 address, but it 35 * also makes it possible for the PHY bus driver to distinguish 36 * between a clause 45 DEVAD and the old AER multicast format. 37 */ 38 39 #include <phymod/phymod_system.h> 40 #include <phymod/phymod_sim.h> 41 42 /* Convenience macro */ 43 #define DBG_VERB PHYMOD_DEBUG_VERBOSE 44 45 /* Bit field get/set macros */ 46 #define TSCBH_BF_SET(_val, _mask, _shift) _val |= ((_mask) << (_shift)) 47 #define TSCBH_BF_GET(_val, _mask, _shift) (((_val) >> (_shift)) & (_mask)) 48 49 /* 50 * Raw 32-bit address consists of AER value in upper 16 bits and 51 * clause 45 address in lower 16 bits. 52 */ 53 #define TSCBH_DEVAD_SHIFT 27 54 #define TSCBH_DEVAD_MASK 0x1f 55 #define TSCBH_DEVAD_GET(_addr) \ 56 TSCBH_BF_GET(_addr, TSCBH_DEVAD_MASK, TSCBH_DEVAD_SHIFT) 57 #define TSCBH_LANE_SHIFT 16 58 #define TSCBH_LANE_MASK 0xff 59 #define TSCBH_LANE_GET(_addr) \ 60 TSCBH_BF_GET(_addr, TSCBH_LANE_MASK, TSCBH_LANE_SHIFT) 61 #define TSCBH_PLL_ID_SHIFT 24 62 #define TSCBH_PLL_ID_MASK 0x3 63 #define TSCBH_PLL_ID_GET(_addr) \ 64 TSCBH_BF_GET(_addr, TSCBH_PLL_ID_MASK, TSCBH_PLL_ID_SHIFT) 65 #define TSCBH_REG_SHIFT 0 66 #define TSCBH_REG_MASK 0xffff 67 #define TSCBH_REG_GET(_addr) \ 68 TSCBH_BF_GET(_addr, TSCBH_REG_MASK, TSCBH_REG_SHIFT) 69 #define TSCBH_MPP_ID_SHIFT 24 70 #define TSCBH_MPP_ID_MASK 0x3 71 #define TSCBH_MPP_ID_GET(_addr) \ 72 TSCBH_BF_GET(_addr, TSCBH_MPP_ID_MASK, TSCBH_MPP_ID_SHIFT) 73 74 #define TSCBH_ADDR(_devad, _pll_id, _lane, _reg) \ 75 (((_devad) << TSCBH_DEVAD_SHIFT) + \ 76 ((_pll_id) << TSCBH_PLL_ID_SHIFT) + \ 77 ((_lane) << TSCBH_LANE_SHIFT) + \ 78 ((_reg) << TSCBH_REG_SHIFT)) 79 80 #define TSCBH_ADDR_PCS(_devad, _mpp_id, _lane, _reg) \ 81 (((_devad) << TSCBH_DEVAD_SHIFT) + \ 82 ((_mpp_id) << TSCBH_MPP_ID_SHIFT) + \ 83 ((_lane) << TSCBH_LANE_SHIFT) + \ 84 ((_reg) << TSCBH_REG_SHIFT)) 85 86 #define TSCBH_AER TSCBH_ADDR(0, 0, 0, 0xffde) 87 #define TSCBH_BLK TSCBH_ADDR(0, 0, 0, 0x001f) 88 89 /* 90 * The CL45 indicator is used to determine whether the upper 16 bits 91 * of the address is an AER value or a clause 45 DEVAD. 92 */ 93 #define TSCBH_CL45 (0x20 << 16) 94 #define TSCBH_CL45_MASK (0xe0 << 16) 95 96 #define TSCBH_ID0 0x600d 97 #define TSCBH_ID1 0x8770 98 #define TSCBH_MODEL 0x26 99 #define TSCBH_SERDES_ID 0x0325 /* 0x9008 Main0_serdesID - Serdes ID Register */ 100 101 #define TSCBH_MPP_0 0x1 102 #define TSCBH_MPP_1 0x2 103 #define TSCBH_MPP_0_1 0x3 104 105 #define TSCBH_SIM_FW_LOAD_DONE_REG_ADDR (0x800d203) 106 107 /*RAM sim*/ 108 #define TSCBH_RAM_WR_ADDR_REG_MS (0xd205) 109 #define TSCBH_RAM_WR_ADDR_REG_LS (0xd204) 110 #define TSCBH_RAM_WR_DATA_REG_MS (0xd207) 111 #define TSCBH_RAM_WR_DATA_REG_LS (0xd206) 112 #define TSCBH_RAM_RD_ADDR_REG_MS (0xd209) 113 #define TSCBH_RAM_RD_ADDR_REG_LS (0xd208) 114 #define TSCBH_RAM_RD_DATA_REG_MS (0xd20b) 115 #define TSCBH_RAM_RD_DATA_REG_LS (0xd20a) 116 #define TSCBH_IS_RAM_ADDR_REG(reg) (reg == TSCBH_RAM_WR_ADDR_REG_MS || reg == TSCBH_RAM_WR_ADDR_REG_LS || reg == TSCBH_RAM_RD_ADDR_REG_MS || reg == TSCBH_RAM_RD_ADDR_REG_LS) 117 #define TSCBH_IS_RAM_DATA_REG(reg) (reg == TSCBH_RAM_WR_DATA_REG_MS || reg == TSCBH_RAM_WR_DATA_REG_LS || reg == TSCBH_RAM_RD_DATA_REG_MS || reg == TSCBH_RAM_RD_DATA_REG_LS) 118 119 #define TSCBH_SIM_ENTRY_F_RAM_LS_DATA_ENTRY (0x1) 120 #define TSCBH_SIM_ENTRY_F_RAM_MS_DATA_ENTRY (0x2) 121 #define TSCBH_SIM_ENTRY_F_RAM_LS_ADDR_ENTRY (0x4) 122 #define TSCBH_SIM_ENTRY_F_RAM_MS_ADDR_ENTRY (0x8) 123 124 125 /* Forward declarations */ 126 STATIC int 127 tscbh_sim_write(phymod_sim_data_t *pms_data, uint32_t addr, uint32_t data); 128 STATIC int 129 tscbh_sim_read(phymod_sim_data_t *pms_data, uint32_t addr, uint32_t *data); 130 131 132 STATIC uint32_t 133 tscbh_sim_default_data_get(uint32_t addr) 134 { 135 uint32_t reg; 136 137 reg = TSCBH_REG_GET(addr); 138 139 /*force FW load success */ 140 if(addr == TSCBH_SIM_FW_LOAD_DONE_REG_ADDR) { 141 return 1; 142 } 143 switch (reg) { 144 case 0x0002: 145 return TSCBH_ID0; 146 case 0x0003: 147 return TSCBH_ID1; 148 case 0x9000: 149 return 0x80; 150 case 0x9008: /* Main0_serdesID - Serdes ID Register */ 151 return TSCBH_SERDES_ID; 152 case 0xd03d: 153 /* 154 * This is DSC_A_DSC_UC_CTRL for Falcon. Make sure 155 * The 'ready' bit is set. 156 */ 157 return 0x0080; 158 case 0xd0b9: /* RXTXCOM_CKRST_CTRL_sinai_LANE_DP_RESET_STATE_STATUS */ 159 return 0x7; 160 case 0xd100: 161 return TSCBH_MODEL; 162 case 0xd10a: /* DIG_COM_REVID1 - REVID1 */ 163 return 0x803c; 164 case 0xd147: 165 return 0x7; 166 case 0xd188: 167 /* 168 * Reset check 169 */ 170 return 0x7; 171 case 0xd170: /* TLB_TX_patt_gen_config - Pattern Generator Control */ 172 return 0xb000; 173 case 0xd1c9: /* LANE_DP_RESET_STATUS */ 174 return 0x7; 175 default: 176 break; 177 } 178 179 return 0; 180 } 181 182 STATIC uint32_t 183 tscbh_sim_write_adjust(phymod_sim_data_t *pms_data, uint32_t addr, uint32_t data) 184 { 185 uint32_t devad, reg, val; 186 187 devad = TSCBH_DEVAD_GET(addr); 188 reg = TSCBH_REG_GET(addr); 189 190 if (devad == 0) { 191 switch (reg) { 192 case 0xc050: 193 /* Sync configured speed into final speed status register 194 * 0x20 = 0xc070 - 0xc050 */ 195 tscbh_sim_read(pms_data, addr + 0x20, &val); 196 val = (val & 0xffff03ff) | ((data & 0x3f) << 10); 197 tscbh_sim_write(pms_data, addr + 0x20, val); 198 break; 199 default: 200 break; 201 } 202 } 203 204 return data; 205 } 206 207 STATIC int 208 _tscbh_sim_write(phymod_sim_data_t *pms_data, uint32_t addr, uint32_t data) 209 { 210 int idx; 211 uint32_t mask; 212 213 phymod_sim_entry_t *pse; 214 215 if (pms_data == NULL || pms_data->entries == NULL) { 216 return PHYMOD_E_INIT; 217 } 218 219 /* Support optional write mask in upper 16 bits */ 220 mask = (data >> 16); 221 if (mask == 0) { 222 mask = 0xffff; 223 } 224 data &= mask; 225 226 /* Check if this register has been written already */ 227 for (idx = 0; idx < pms_data->entries_used; idx++) { 228 pse = &pms_data->entries[idx]; 229 if (pse->addr == addr) { 230 pse->data &= ~mask; 231 pse->data |= data; 232 DBG_VERB(("_tscbh_sim_write 0x%08"PRIx32" = 0x%04"PRIx32"\n", 233 addr, pse->data)); 234 return PHYMOD_E_NONE; 235 } 236 } 237 238 /* Check if database is full */ 239 if (pms_data->entries_used >= pms_data->num_entries) { 240 PHYMOD_DEBUG_ERROR(("phy sim ERROR: Nof modified registers is larger than phy sim database. Please increase PHY_NUM_SIM_ENTRIES.\n")); 241 return PHYMOD_E_RESOURCE; 242 } 243 244 /* Check if new data matches default value */ 245 if (data == tscbh_sim_default_data_get(addr)) { 246 return PHYMOD_E_NONE; 247 } 248 249 /* Add new register value */ 250 pse = &pms_data->entries[pms_data->entries_used++]; 251 pse->addr = addr; 252 pse->data = data; 253 254 DBG_VERB(("_tscbh_sim_write 0x%08"PRIx32" = 0x%04"PRIx32" (new)\n", 255 addr, pse->data)); 256 257 return PHYMOD_E_NONE; 258 } 259 260 261 262 STATIC uint32_t 263 tscbh_sim_reg_copies_get(uint32_t addr) 264 { 265 uint32_t devad, reg; 266 267 devad = TSCBH_DEVAD_GET(addr); 268 reg = TSCBH_REG_GET(addr); 269 270 if (reg == TSCBH_AER || reg == TSCBH_BLK) { 271 return 1; 272 } 273 274 if (devad == 0) { 275 if ((reg & 0xf000) == 0x9000) { 276 return 2; 277 } 278 if ((reg & 0xf000) == 0xc000) { 279 return 4; 280 } 281 } 282 else if (devad == 1) { 283 if ((reg & 0xfff0) == 0xd100) { 284 return 1; 285 } 286 if ((reg & 0xfff0) == 0xd190) { 287 return 1; 288 } 289 if ((reg & 0xfff0) == 0xd180) { 290 return 2; 291 } 292 if ((reg & 0xfff0) == 0xd140) { 293 return 2; 294 } 295 if ((reg & 0xfff0) == 0xd110) { 296 return 2; 297 } 298 return 8; 299 } 300 return 0; 301 } 302 303 STATIC int 304 tscbh_sim_init(phymod_sim_data_t *pms_data, 305 int num_entries, phymod_sim_entry_t *entries) 306 { 307 if (pms_data != NULL) { 308 PHYMOD_MEMSET(pms_data, 0, sizeof(*pms_data)); 309 pms_data->num_entries = num_entries; 310 pms_data->entries = entries; 311 } 312 return PHYMOD_E_NONE; 313 } 314 315 STATIC int 316 tscbh_sim_reset(phymod_sim_data_t *pms_data) 317 { 318 uint32_t sim_size; 319 320 if (pms_data == NULL || pms_data->entries == NULL) { 321 return PHYMOD_E_INIT; 322 } 323 324 pms_data->entries_used = 0; 325 sim_size = pms_data->num_entries * sizeof(phymod_sim_entry_t); 326 PHYMOD_MEMSET(pms_data->entries, 0, sim_size); 327 328 return PHYMOD_E_NONE; 329 } 330 331 STATIC int 332 tscbh_sim_read(phymod_sim_data_t *pms_data, uint32_t addr, uint32_t *data) 333 { 334 int idx; 335 uint32_t aer, blk, devad, reg, copies, pll_id=0; 336 uint32_t lane = 0; 337 uint32_t mpp_id=0; 338 phymod_sim_entry_t *pse; 339 uint32_t pse_flag = 0; 340 uint32_t addr_ms, addr_ls; 341 342 if (pms_data == NULL || pms_data->entries == NULL) { 343 return PHYMOD_E_INIT; 344 } 345 346 devad = 0; 347 348 349 if (addr < TSCBH_BLK) { 350 /* Assume clause 22 access */ 351 (void)tscbh_sim_read(pms_data, TSCBH_BLK, &blk); 352 if (addr & 0x10) { 353 /* IEEE bit */ 354 blk |= 0x8000; 355 } 356 addr = (addr & 0xf) | (blk & 0xfff0); 357 if (addr != TSCBH_AER && addr != TSCBH_BLK) { 358 (void)tscbh_sim_read(pms_data, TSCBH_AER, &aer); 359 addr |= (aer << 16); 360 } 361 } else { 362 /* Extract devad if clause 45 address format */ 363 if ((addr & TSCBH_CL45_MASK) == TSCBH_CL45) { 364 devad = (addr >> 16) & 0x1f; 365 addr &= 0xffff; 366 } 367 } 368 369 if (addr != TSCBH_AER && addr != TSCBH_BLK) { 370 /* Assume AER is in upper 16 bits */ 371 aer = (addr >> 16); 372 if (aer == 0) { 373 /* Try reading real AER instead */ 374 (void)tscbh_sim_read(pms_data, TSCBH_AER, &aer); 375 } 376 /* Add clause 45 devad (if used) */ 377 aer |= (devad << 11); 378 addr = (addr & 0xffff) | (aer << 16); 379 380 lane = (aer & 0x7); 381 382 if (devad != 1) { /* PCS registers */ 383 mpp_id = TSCBH_MPP_ID_GET(addr); 384 if (mpp_id == TSCBH_MPP_0_1) { 385 /* Force mpp0 if mpp is invalid */ 386 addr = TSCBH_ADDR_PCS(TSCBH_DEVAD_GET(addr), TSCBH_MPP_0, lane, TSCBH_REG_GET(addr)); 387 } 388 if (lane > 3) { 389 /* Force lane 0 if lane is invalid */ 390 lane = 0; 391 addr = TSCBH_ADDR_PCS(TSCBH_DEVAD_GET(addr), TSCBH_MPP_ID_GET(addr), lane, TSCBH_REG_GET(addr)); 392 } 393 } 394 } 395 396 /* Adjust lane according to number of copies */ 397 devad = TSCBH_DEVAD_GET(addr); 398 reg = TSCBH_REG_GET(addr); 399 copies = tscbh_sim_reg_copies_get(addr); 400 if (devad == 1) { /* PMD register */ 401 if (copies == 1) { 402 lane = 0; 403 } else if (copies == 2) { 404 pll_id = TSCBH_PLL_ID_GET(addr); 405 lane = (pll_id == 0) ? 0 : 1; 406 } 407 } else { /* PCS register */ 408 mpp_id = TSCBH_MPP_ID_GET(addr); 409 if (copies == 2) { 410 lane = 0; 411 } 412 } 413 414 /*handle ram read/write*/ 415 if (TSCBH_IS_RAM_DATA_REG(reg) || TSCBH_IS_RAM_ADDR_REG(reg)) { 416 417 if (TSCBH_IS_RAM_DATA_REG(reg)) { 418 (void)tscbh_sim_read(pms_data, TSCBH_ADDR(devad, pll_id, lane, TSCBH_RAM_RD_ADDR_REG_LS), &addr_ls); 419 (void)tscbh_sim_read(pms_data, TSCBH_ADDR(devad, pll_id, lane, TSCBH_RAM_RD_ADDR_REG_MS), &addr_ms); 420 addr = addr_ls | (addr_ms << 16); 421 if (reg == TSCBH_RAM_RD_DATA_REG_LS || reg == TSCBH_RAM_WR_DATA_REG_LS) { 422 pse_flag |= TSCBH_SIM_ENTRY_F_RAM_LS_DATA_ENTRY; 423 } else { 424 pse_flag |= TSCBH_SIM_ENTRY_F_RAM_MS_DATA_ENTRY; 425 } 426 } else { /*TSCBH_IS_RAM_ADDR_REG*/ 427 addr = TSCBH_ADDR(devad, 0, lane, 0 /*dummy*/); 428 if (reg == TSCBH_RAM_RD_ADDR_REG_LS || reg == TSCBH_RAM_WR_ADDR_REG_LS) { 429 pse_flag |= TSCBH_SIM_ENTRY_F_RAM_LS_DATA_ENTRY; 430 } else { 431 pse_flag |= TSCBH_SIM_ENTRY_F_RAM_MS_DATA_ENTRY; 432 } 433 } 434 435 /* Check if this register has been written already */ 436 for (idx = 0; idx < pms_data->entries_used; idx++) { 437 pse = &pms_data->entries[idx]; 438 if ((pse->addr == addr) && (pse->flags == pse_flag)) { 439 *data = pse->data; 440 DBG_VERB(("tscbh_sim_read 0x%08"PRIx32" = 0x%04"PRIx32"\n", 441 addr, *data)); 442 return PHYMOD_E_NONE; 443 } 444 } 445 446 *data = 0; 447 return PHYMOD_E_NONE; 448 } 449 450 451 if (devad == 1) { 452 addr = TSCBH_ADDR(devad, pll_id, lane, reg); 453 } else { 454 addr = TSCBH_ADDR_PCS(devad, mpp_id, lane, reg); 455 } 456 457 /* Check if this register has been written already */ 458 for (idx = 0; idx < pms_data->entries_used; idx++) { 459 pse = &pms_data->entries[idx]; 460 if ((pse->addr == addr) && (pse->flags == pse_flag)) { 461 *data = pse->data; 462 DBG_VERB(("tscbh_sim_read 0x%08"PRIx32" = 0x%04"PRIx32"\n", 463 addr, *data)); 464 return PHYMOD_E_NONE; 465 } 466 } 467 468 /* Return default value if register was never written */ 469 *data = tscbh_sim_default_data_get(addr); 470 471 DBG_VERB(("tscbh_sim_read 0x%08"PRIx32" = [0x%04"PRIx32"]\n", 472 addr, *data)); 473 474 return PHYMOD_E_NONE; 475 } 476 477 STATIC int 478 tscbh_sim_write(phymod_sim_data_t *pms_data, uint32_t addr, uint32_t data) 479 { 480 uint32_t aer, blk, devad, reg, copies, pll_id=0; 481 uint32_t lane = 0; 482 uint32_t mpp_id; 483 484 if (pms_data == NULL || pms_data->entries == NULL) { 485 return PHYMOD_E_INIT; 486 } 487 488 devad = 0; 489 490 if (addr < TSCBH_BLK) { 491 /* Assume clause 22 access */ 492 (void)tscbh_sim_read(pms_data, TSCBH_BLK, &blk); 493 /* IEEE bit */ 494 if (addr & 0x10) { 495 blk |= 0x8000; 496 } else { 497 blk &= ~0x8000; 498 } 499 addr = (addr & 0xf) | (blk & 0xfff0); 500 if (addr != TSCBH_AER && addr != TSCBH_BLK) { 501 (void)tscbh_sim_read(pms_data, TSCBH_AER, &aer); 502 addr |= (aer << 16); 503 } 504 } else { 505 /* Extract devad if clause 45 address format */ 506 if ((addr & TSCBH_CL45_MASK) == TSCBH_CL45) { 507 devad = (addr >> 16) & 0x1f; 508 addr &= 0xffff; 509 } 510 } 511 512 if (addr != TSCBH_AER && addr != TSCBH_BLK) { 513 /* Assume AER is in upper 16 bits */ 514 aer = (addr >> 16); 515 if (aer == 0) { 516 /* Try reading real AER instead */ 517 (void)tscbh_sim_read(pms_data, TSCBH_AER, &aer); 518 } 519 520 /* Add clause 45 devad (if used) */ 521 aer |= (devad << 11); 522 addr = (addr & 0xffff) | (aer << 16); 523 devad = TSCBH_DEVAD_GET(addr); 524 reg = TSCBH_REG_GET(addr); 525 526 if (devad == 1) { /* Access PMD registers */ 527 lane = (aer & 0xff); 528 if (lane > 7) { 529 /* 530 * Handle lane broadcast 531 * 532 * Note that we use lane 8 instead of lane 0 to prevent a 533 * broadcast loop. The value 8 will become 0 when masked 534 * with 0x7, but it prevents the AER in the upper 16 bits 535 * from being zero, which will cause the code above to 536 * obtain the AER value from register 0xffde. 537 */ 538 539 pll_id = TSCBH_PLL_ID_GET(addr); 540 if (lane == 0x20) { 541 /* Write lanes 0 and 1 */ 542 addr = TSCBH_ADDR(devad, pll_id, 0, reg); 543 (void)tscbh_sim_write(pms_data, addr, data); 544 addr = TSCBH_ADDR(devad, pll_id, 1, reg); 545 (void)tscbh_sim_write(pms_data, addr, data); 546 } 547 if (lane == 0x21) { 548 /* Write lanes 2 and 3 */ 549 addr = TSCBH_ADDR(devad, pll_id, 2, reg); 550 (void)tscbh_sim_write(pms_data, addr, data); 551 addr = TSCBH_ADDR(devad, pll_id, 3, reg); 552 (void)tscbh_sim_write(pms_data, addr, data); 553 } 554 if (lane == 0x22) { 555 /* Write lanes 4 and 5 */ 556 addr = TSCBH_ADDR(devad, pll_id, 4, reg); 557 (void)tscbh_sim_write(pms_data, addr, data); 558 addr = TSCBH_ADDR(devad, pll_id, 5, reg); 559 (void)tscbh_sim_write(pms_data, addr, data); 560 } 561 if (lane == 0x23) { 562 /* Write lanes 6 and 7 */ 563 addr = TSCBH_ADDR(devad, pll_id, 6, reg); 564 (void)tscbh_sim_write(pms_data, addr, data); 565 addr = TSCBH_ADDR(devad, pll_id, 7, reg); 566 (void)tscbh_sim_write(pms_data, addr, data); 567 } 568 if (lane == 0x40) { 569 /* Write lanes 0,1,2,and 3 */ 570 addr = TSCBH_ADDR(devad, pll_id, 0, reg); 571 (void)tscbh_sim_write(pms_data, addr, data); 572 addr = TSCBH_ADDR(devad, pll_id, 1, reg); 573 (void)tscbh_sim_write(pms_data, addr, data); 574 addr = TSCBH_ADDR(devad, pll_id, 2, reg); 575 (void)tscbh_sim_write(pms_data, addr, data); 576 addr = TSCBH_ADDR(devad, pll_id, 3, reg); 577 (void)tscbh_sim_write(pms_data, addr, data); 578 } 579 if (lane == 0x41) { 580 /* Write lanes 4,5,6 and 7 */ 581 addr = TSCBH_ADDR(devad, pll_id, 4, reg); 582 (void)tscbh_sim_write(pms_data, addr, data); 583 addr = TSCBH_ADDR(devad, pll_id, 5, reg); 584 (void)tscbh_sim_write(pms_data, addr, data); 585 addr = TSCBH_ADDR(devad, pll_id, 6, reg); 586 (void)tscbh_sim_write(pms_data, addr, data); 587 addr = TSCBH_ADDR(devad, pll_id, 7, reg); 588 (void)tscbh_sim_write(pms_data, addr, data); 589 } 590 if (lane == 0xff) { 591 /* Write lanes 2 and 3 */ 592 addr = TSCBH_ADDR(devad, pll_id, 0, reg); 593 (void)tscbh_sim_write(pms_data, addr, data); 594 addr = TSCBH_ADDR(devad, pll_id, 1, reg); 595 (void)tscbh_sim_write(pms_data, addr, data); 596 addr = TSCBH_ADDR(devad, pll_id, 2, reg); 597 (void)tscbh_sim_write(pms_data, addr, data); 598 addr = TSCBH_ADDR(devad, pll_id, 3, reg); 599 (void)tscbh_sim_write(pms_data, addr, data); 600 addr = TSCBH_ADDR(devad, pll_id, 4, reg); 601 (void)tscbh_sim_write(pms_data, addr, data); 602 addr = TSCBH_ADDR(devad, pll_id, 5, reg); 603 (void)tscbh_sim_write(pms_data, addr, data); 604 addr = TSCBH_ADDR(devad, pll_id, 6, reg); 605 (void)tscbh_sim_write(pms_data, addr, data); 606 addr = TSCBH_ADDR(devad, pll_id, 7, reg); 607 (void)tscbh_sim_write(pms_data, addr, data); 608 } 609 return PHYMOD_E_NONE; 610 } 611 } else { /* Access PCS registers */ 612 mpp_id = TSCBH_MPP_ID_GET(addr); 613 lane = aer & 0x7; 614 if (lane > 0x6) { 615 return PHYMOD_E_PARAM; 616 } 617 if (mpp_id == TSCBH_MPP_0_1) { 618 addr = TSCBH_ADDR_PCS(devad, TSCBH_MPP_0, lane, reg); 619 (void)tscbh_sim_write(pms_data, addr, data); 620 addr = TSCBH_ADDR_PCS(devad, TSCBH_MPP_1, lane, reg); 621 (void)tscbh_sim_write(pms_data, addr, data); 622 return PHYMOD_E_NONE; 623 } else { 624 if (lane > 3) { 625 if (lane == 0x4) { 626 /* Write lanes 0 and 1 */ 627 addr = TSCBH_ADDR_PCS(devad, mpp_id, 0, reg); 628 (void)tscbh_sim_write(pms_data, addr, data); 629 addr = TSCBH_ADDR_PCS(devad, mpp_id, 1, reg); 630 (void)tscbh_sim_write(pms_data, addr, data); 631 } 632 if (lane == 0x5) { 633 /* Write lanes 2 and 3 */ 634 addr = TSCBH_ADDR_PCS(devad, mpp_id, 2, reg); 635 (void)tscbh_sim_write(pms_data, addr, data); 636 addr = TSCBH_ADDR_PCS(devad, mpp_id, 3, reg); 637 (void)tscbh_sim_write(pms_data, addr, data); 638 } 639 if (lane == 0x6) { 640 /* Write lanes 0, 1, 2 and 3 */ 641 addr = TSCBH_ADDR_PCS(devad, mpp_id, 0, reg); 642 (void)tscbh_sim_write(pms_data, addr, data); 643 addr = TSCBH_ADDR_PCS(devad, mpp_id, 1, reg); 644 (void)tscbh_sim_write(pms_data, addr, data); 645 addr = TSCBH_ADDR_PCS(devad, mpp_id, 2, reg); 646 (void)tscbh_sim_write(pms_data, addr, data); 647 addr = TSCBH_ADDR_PCS(devad, mpp_id, 3, reg); 648 (void)tscbh_sim_write(pms_data, addr, data); 649 } 650 return PHYMOD_E_NONE; 651 } 652 } 653 } 654 } 655 656 /* Adjust data and/or related registers */ 657 data = tscbh_sim_write_adjust(pms_data, addr, data); 658 659 /* Adjust lane according to number of copies */ 660 devad = TSCBH_DEVAD_GET(addr); 661 reg = TSCBH_REG_GET(addr); 662 copies = tscbh_sim_reg_copies_get(addr); 663 664 if (devad == 1) { /* PMD registers */ 665 if (copies == 1) { 666 lane = 0; 667 } else if (copies == 2) { 668 pll_id = TSCBH_PLL_ID_GET(addr); 669 lane = (pll_id == 0) ? 0 : 1; 670 } 671 addr = TSCBH_ADDR(devad, pll_id, lane, reg); 672 } else { /* PCS registers */ 673 mpp_id = TSCBH_MPP_ID_GET(addr); 674 if (copies == 2) { 675 lane = 0; 676 } 677 addr = TSCBH_ADDR_PCS(devad, mpp_id, lane, reg); 678 } 679 680 return _tscbh_sim_write(pms_data, addr, data); 681 } 682 683 STATIC int 684 tscbh_sim_event(phymod_sim_data_t *pms_data, phymod_sim_event_t event) 685 { 686 if (pms_data == NULL || pms_data->entries == NULL) { 687 return PHYMOD_E_INIT; 688 } 689 690 return PHYMOD_E_NONE; 691 } 692 693 phymod_sim_drv_t tscbh_sim_drv = { 694 tscbh_sim_init, 695 tscbh_sim_reset, 696 tscbh_sim_read, 697 tscbh_sim_write, 698 tscbh_sim_event 699 };