phymod_sim.c (14026B)
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 /* 9 * PHY Simulator (requires PHYMOD library) 10 */ 11 12 #include <shared/bsl.h> 13 14 #include <sal/types.h> 15 #include <sal/core/spl.h> 16 #include <soc/drv.h> 17 #include <soc/error.h> 18 #include <soc/scache.h> 19 20 #ifndef PHY_NUM_SIMS 21 #define PHY_NUM_SIMS 66 22 #endif 23 24 #if defined(PHYMOD_SUPPORT) && (PHY_NUM_SIMS > 0) 25 #define PHY_SIM_SUPPORT 26 #endif 27 28 #ifdef BCM_WARM_BOOT_SUPPORT 29 #define SOC_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 30 #define SOC_WB_DEFAULT_VERSION SOC_WB_VERSION_1_0 31 #endif 32 33 #ifdef PHY_SIM_SUPPORT 34 35 #include <phymod/phymod.h> 36 #include <phymod/chip/eagle_sim.h> 37 38 #include <phymod/chip/falcon_sim.h> 39 #include <phymod/chip/tscf_sim.h> 40 #include <phymod/chip/tsce_sim.h> 41 #include <phymod/chip/qsgmiie_sim.h> 42 #include <phymod/chip/viper_sim.h> 43 #include <phymod/chip/tscf16_sim.h> 44 #include <phymod/chip/tsce16_sim.h> 45 #include <phymod/chip/qtce_sim.h> 46 #include <phymod/chip/tscbh_sim.h> 47 #include <phymod/chip/tscf_gen3_sim.h> 48 #include <phymod/chip/tsce_dpll_sim.h> 49 #include <phymod/chip/blackhawk_sim.h> 50 #include <phymod/chip/qtce16_sim.h> 51 52 #include <soc/phy/phymod_sim.h> 53 54 #ifndef PHY_NUM_SIM_ENTRIES 55 #define PHY_NUM_SIM_ENTRIES 400 56 #endif 57 58 typedef struct soc_phy_sim_s { 59 phymod_sim_entry_t pms_entries[PHY_NUM_SIM_ENTRIES]; 60 phymod_sim_t pms; 61 int unit; 62 uint32 phy_id; 63 } soc_phy_sim_t; 64 65 static soc_phy_sim_t soc_phy_sim[PHY_NUM_SIMS]; 66 static int soc_phy_sims_used; 67 68 69 STATIC soc_phy_sim_t * 70 soc_physim_find(int unit, uint32 phy_id) 71 { 72 int idx; 73 soc_phy_sim_t *psim; 74 75 for (idx = 0; idx < soc_phy_sims_used; idx++) { 76 psim = &soc_phy_sim[idx]; 77 if (psim->unit == unit && psim->phy_id == phy_id) { 78 return psim; 79 } 80 } 81 return NULL; 82 } 83 84 int 85 soc_physim_add(int unit, uint32 phy_id, phymod_sim_drv_t *pms_drv) 86 { 87 int idx; 88 soc_phy_sim_t *psim; 89 90 /* Check if this simulator exists already */ 91 for (idx = 0; idx < soc_phy_sims_used; idx++) { 92 psim = &soc_phy_sim[idx]; 93 if (psim->unit == unit && psim->phy_id == phy_id) { 94 /* Reset simulator */ 95 SOC_IF_ERROR_RETURN( 96 phymod_sim_reset(&psim->pms)); 97 return SOC_E_NONE; 98 } 99 } 100 101 /* Any free simulators? */ 102 if (soc_phy_sims_used >= PHY_NUM_SIMS) { 103 LOG_ERROR(BSL_LS_SOC_PHY, 104 (BSL_META_U(unit, 105 "soc_physim_add: Out of resources for" 106 " unit=%d phy_id=0x%x\n"), unit, phy_id)); 107 return SOC_E_RESOURCE; 108 } 109 110 /* Add new simulator entry */ 111 psim = &soc_phy_sim[soc_phy_sims_used++]; 112 psim->unit = unit; 113 psim->phy_id = phy_id; 114 psim->pms.drv = pms_drv; 115 116 /* Initialize and reset simulator */ 117 SOC_IF_ERROR_RETURN( 118 phymod_sim_init(&psim->pms, 119 COUNTOF(psim->pms_entries), psim->pms_entries)); 120 SOC_IF_ERROR_RETURN( 121 phymod_sim_reset(&psim->pms)); 122 123 return SOC_E_NONE; 124 } 125 126 #endif /* PHY_SIM_SUPPORT */ 127 128 int 129 soc_physim_wrmask(int unit, uint32 phy_id, 130 uint32 phy_reg_addr, uint16 phy_wr_data, uint16 wr_mask) 131 { 132 #ifdef PHY_SIM_SUPPORT 133 soc_phy_sim_t *psim = soc_physim_find(unit, phy_id); 134 uint32 data32; 135 136 if (psim == NULL) { 137 return SOC_E_INIT; 138 } 139 140 data32 = wr_mask; 141 data32 <<= 16; 142 data32 |= phy_wr_data; 143 144 SOC_IF_ERROR_RETURN( 145 phymod_sim_write(&psim->pms, phy_reg_addr, data32)); 146 147 LOG_INFO(BSL_LS_SOC_PHYSIM, 148 (BSL_META_U(unit, 149 "soc_physim_wrmask 0x%03x:0x%04x = 0x%04x/0x%04x\n"), 150 phy_id, phy_reg_addr, phy_wr_data, wr_mask)); 151 return SOC_E_NONE; 152 #else 153 return SOC_E_UNAVAIL; 154 #endif 155 } 156 157 int 158 soc_physim_read(int unit, uint32 phy_id, 159 uint32 phy_reg_addr, uint16 *phy_rd_data) 160 { 161 #ifdef PHY_SIM_SUPPORT 162 soc_phy_sim_t *psim = soc_physim_find(unit, phy_id); 163 uint32 data32; 164 165 if (psim == NULL) { 166 return SOC_E_INIT; 167 } 168 169 SOC_IF_ERROR_RETURN( 170 phymod_sim_read(&psim->pms, phy_reg_addr, &data32)); 171 172 *phy_rd_data = data32; 173 174 LOG_INFO(BSL_LS_SOC_PHYSIM, 175 (BSL_META_U(unit, 176 "soc_physim_read 0x%03x:0x%04x = 0x%04x\n"), 177 phy_id, phy_reg_addr, *phy_rd_data)); 178 return SOC_E_NONE; 179 #else 180 return SOC_E_UNAVAIL; 181 #endif 182 } 183 184 int 185 soc_physim_write(int unit, uint32 phy_id, 186 uint32 phy_reg_addr, uint16 phy_wr_data) 187 { 188 return soc_physim_wrmask(unit, phy_id, phy_reg_addr, phy_wr_data, 0); 189 } 190 191 #ifdef PORTMOD_SUPPORT 192 193 #include <soc/portmod/portmod.h> 194 195 /* Default simulator bus */ 196 STATIC 197 int sim_bus_read(void* user_acc, uint32_t core_addr, uint32_t reg_addr, uint32_t* val){ 198 portmod_default_user_access_t *user_data; 199 uint16_t tmp=0; 200 int rv; 201 202 if(user_acc == NULL){ 203 return SOC_E_PARAM; 204 } 205 user_data = (portmod_default_user_access_t*)user_acc; 206 207 (*val) = 0; 208 rv = soc_physim_read(user_data->unit, core_addr, reg_addr, &tmp); 209 (*val) = tmp; 210 211 return rv; 212 } 213 214 STATIC 215 int sim_bus_write(void* user_acc, uint32_t core_addr, uint32_t reg_addr, uint32_t val){ 216 portmod_default_user_access_t *user_data; 217 uint16_t tmp = 0; 218 uint16_t msk = 0; 219 220 if(user_acc == NULL){ 221 return SOC_E_PARAM; 222 } 223 user_data = (portmod_default_user_access_t*)user_acc; 224 225 tmp = (val & 0xFFFF); 226 msk = ((val >> 16) & 0xFFFF); 227 228 return soc_physim_wrmask(user_data->unit, core_addr, reg_addr, tmp, msk); 229 } 230 231 phymod_bus_t sim_bus = { 232 "portmod_phy_sim", 233 sim_bus_read, 234 sim_bus_write, 235 NULL, 236 NULL, 237 NULL, 238 NULL, 239 NULL, 240 0 241 }; 242 243 void 244 soc_physim_enable_get(int unit, int* is_sim) 245 { 246 int use_sim; 247 248 use_sim = soc_property_get(unit, spn_PHY_SIMUL, 0) || soc_property_get(unit, spn_DIAG_EMULATOR_PARTIAL_INIT, 0); 249 250 if (use_sim || SAL_BOOT_PLISIM) { 251 (*is_sim) = 1; 252 } else { 253 (*is_sim) = 0; 254 } 255 256 return ; 257 } 258 259 /* 260 addr_ident - in some cases the access->phy_id is the same for several PMs (which are accesses from diffrent blocks). 261 In this case addr_ident is ORed with the phy_id to distinguish between the cores. 262 */ 263 int 264 soc_physim_check_sim(int unit, phymod_dispatch_type_t type, phymod_access_t* access, uint32 addr_ident, int* is_sim) 265 { 266 int use_sim; 267 phymod_sim_drv_t *sim = NULL; 268 269 use_sim = soc_property_get(unit, spn_PHY_SIMUL, 0) || soc_property_get(unit, spn_DIAG_EMULATOR_PARTIAL_INIT, 0); 270 271 if(use_sim || SAL_BOOT_PLISIM) { 272 switch(type) { 273 case phymodDispatchTypeEagle: 274 sim = &eagle_sim_drv; 275 break; 276 case phymodDispatchTypeFalcon: 277 sim = &falcon_sim_drv; 278 break; 279 case phymodDispatchTypeQsgmiie: 280 sim = &qsgmiie_sim_drv; 281 break; 282 case phymodDispatchTypeTsce: 283 sim = &tsce_sim_drv; 284 break; 285 case phymodDispatchTypeTscf: 286 sim = &tscf_sim_drv; 287 break; 288 case phymodDispatchTypeViper: 289 if (SOC_IS_GREYHOUND2(unit)) { 290 sim = &viper_sp2_sim_drv; 291 } 292 else { 293 sim = &viper_sim_drv; 294 } 295 break; 296 case phymodDispatchTypeTscf16: 297 sim = &tscf16_sim_drv; 298 break; 299 case phymodDispatchTypeTscbh: 300 sim = &tscbh_sim_drv; 301 break; 302 case phymodDispatchTypeTsce16: 303 sim = &tsce16_sim_drv; 304 break; 305 case phymodDispatchTypeQtce: 306 sim = &qtce_sim_drv; 307 break; 308 case phymodDispatchTypeBlackhawk: 309 sim = &blackhawk_sim_drv; 310 break; 311 case phymodDispatchTypeTscf_gen3: 312 sim = &tscf_gen3_sim_drv; 313 break; 314 case phymodDispatchTypeTsce_dpll: 315 sim = &tsce_dpll_sim_drv; 316 break; 317 case phymodDispatchTypeQtce16: 318 sim = &qtce16_sim_drv; 319 break; 320 default: 321 LOG_ERROR(BSL_LS_SOC_PHYSIM, 322 (BSL_META_U(unit, 323 "Invalid simulator %d\n"), type)); 324 return SOC_E_NOT_FOUND; 325 } 326 327 PHYMOD_ACC_ADDR(access) |= addr_ident; 328 SOC_IF_ERROR_RETURN(soc_physim_add(unit, PHYMOD_ACC_ADDR(access), sim)); 329 330 PHYMOD_ACC_BUS(access) = &sim_bus; 331 (*is_sim) = 1; 332 333 } else { 334 /* Not simulator - do nothing*/ 335 (*is_sim) = 0; 336 } 337 338 return SOC_E_NONE; 339 } 340 341 #ifdef BCM_WARM_BOOT_SUPPORT 342 int 343 soc_physim_scache_allocate(int unit) 344 { 345 int rv = SOC_E_NONE; 346 uint8 *physim_scache_ptr; 347 soc_scache_handle_t scache_handle; 348 uint32 alloc_size = 0; 349 int idx; 350 int default_ver = SOC_WB_DEFAULT_VERSION; 351 352 for (idx = 0; idx < soc_phy_sims_used; idx++) { 353 alloc_size += sizeof(int) + /* unit*/ 354 sizeof(int) + /* phy_id */ 355 sizeof(int) + /* num_entries */ 356 sizeof(int) + /* entries_used */ 357 (sizeof(phymod_sim_entry_t) * PHY_NUM_SIM_ENTRIES); /* pms_entries */ 358 } 359 360 SOC_SCACHE_HANDLE_SET(scache_handle, unit, SOC_SCACHE_PHYSIM_HANDLE, 0); 361 362 rv = soc_versioned_scache_ptr_get(unit, scache_handle, 363 TRUE, &alloc_size, 364 &physim_scache_ptr, 365 default_ver, 366 NULL); 367 /* Proceed with Level 1 Warm Boot */ 368 if (SOC_FAILURE(rv) && (rv != SOC_E_NOT_FOUND)) { 369 return rv; 370 } 371 372 LOG_VERBOSE(BSL_LS_SOC_COMMON, 373 (BSL_META_U(unit, 374 "%s()[LINE:%d] DONE \n"),FUNCTION_NAME(), __LINE__)); 375 376 return SOC_E_NONE; 377 } 378 379 int 380 soc_physim_scache_sync(int unit) 381 { 382 uint8 *physim_scache_ptr; 383 soc_scache_handle_t scache_handle; 384 uint32 alloc_size = 0; 385 int rv = 0; 386 int idx, idx_pms; 387 soc_phy_sim_t *psim; 388 phymod_sim_entry_t *physim_entry_scache_p; 389 uint32 *u32_scache_p; 390 391 SOC_SCACHE_HANDLE_SET(scache_handle, unit, SOC_SCACHE_PHYSIM_HANDLE, 0); 392 rv = soc_versioned_scache_ptr_get(unit, scache_handle, 393 FALSE, &alloc_size, 394 &physim_scache_ptr, 395 SOC_WB_DEFAULT_VERSION, 396 NULL); 397 /* Proceed with Level 1 Warm Boot */ 398 if (SOC_FAILURE(rv) && (rv != SOC_E_NOT_FOUND)) { 399 return rv; 400 } 401 402 u32_scache_p = (uint32 *)physim_scache_ptr; 403 for (idx = 0; idx < soc_phy_sims_used; idx++) { 404 psim = &soc_phy_sim[idx]; 405 406 *u32_scache_p = psim->unit; /* unit*/ 407 u32_scache_p++; 408 *u32_scache_p = psim->phy_id; /* phy_id */ 409 u32_scache_p++; 410 *u32_scache_p = psim->pms.data.num_entries; /* num_entries */ 411 u32_scache_p++; 412 *u32_scache_p = psim->pms.data.entries_used;/* entries_used */ 413 u32_scache_p++; 414 415 /* pms_entries */ 416 physim_entry_scache_p = (phymod_sim_entry_t *)u32_scache_p; 417 for (idx_pms = 0; idx_pms < psim->pms.data.entries_used; idx_pms++) { 418 physim_entry_scache_p->flags = psim->pms_entries[idx_pms].flags; 419 physim_entry_scache_p->addr = psim->pms_entries[idx_pms].addr; 420 physim_entry_scache_p->data = psim->pms_entries[idx_pms].data; 421 physim_entry_scache_p++; 422 } 423 u32_scache_p = (uint32 *)physim_entry_scache_p; 424 } 425 426 LOG_VERBOSE(BSL_LS_SOC_COMMON, 427 (BSL_META_U(unit, 428 "%s()[LINE:%d] \n"),FUNCTION_NAME(), __LINE__)); 429 430 return SOC_E_NONE; 431 } 432 433 int 434 soc_physim_scache_recovery(int unit) 435 { 436 uint8 *physim_scache_ptr; 437 soc_scache_handle_t scache_handle; 438 uint32 alloc_size = 0; 439 int rv = 0; 440 int idx, idx_pms; 441 soc_phy_sim_t *psim; 442 phymod_sim_entry_t *physim_entry_scache_p; 443 uint32 *u32_scache_p; 444 uint16 recovered_ver = 0; 445 446 SOC_SCACHE_HANDLE_SET(scache_handle, unit, SOC_SCACHE_PHYSIM_HANDLE, 0); 447 rv = soc_versioned_scache_ptr_get(unit, scache_handle, 448 FALSE, &alloc_size, 449 &physim_scache_ptr, 450 SOC_WB_DEFAULT_VERSION, 451 &recovered_ver); 452 /* Proceed with Level 1 Warm Boot */ 453 if (SOC_FAILURE(rv) && (rv != SOC_E_NOT_FOUND)) { 454 return rv; 455 } 456 457 if (recovered_ver >= SOC_WB_VERSION_1_0) { 458 u32_scache_p = (uint32 *)physim_scache_ptr; 459 for (idx = 0; idx < soc_phy_sims_used; idx++) { 460 psim = &soc_phy_sim[idx]; 461 462 psim->unit = *u32_scache_p; /* unit*/ 463 u32_scache_p++; 464 psim->phy_id = *u32_scache_p; /* phy_id */ 465 u32_scache_p++; 466 psim->pms.data.num_entries = *u32_scache_p; /* num_entries */ 467 u32_scache_p++; 468 psim->pms.data.entries_used = *u32_scache_p;/* entries_used */ 469 u32_scache_p++; 470 471 /* pms_entries */ 472 physim_entry_scache_p = (phymod_sim_entry_t *)u32_scache_p; 473 for (idx_pms = 0; idx_pms < psim->pms.data.entries_used; idx_pms++) { 474 psim->pms_entries[idx_pms].flags = physim_entry_scache_p->flags; 475 psim->pms_entries[idx_pms].addr = physim_entry_scache_p->addr; 476 psim->pms_entries[idx_pms].data = physim_entry_scache_p->data; 477 physim_entry_scache_p++; 478 } 479 u32_scache_p = (uint32 *)physim_entry_scache_p; 480 } 481 } 482 483 LOG_VERBOSE(BSL_LS_SOC_COMMON, 484 (BSL_META_U(unit, 485 "%s()[LINE:%d] \n"),FUNCTION_NAME(), __LINE__)); 486 487 return SOC_E_NONE; 488 } 489 #endif /* BCM_WARM_BOOT_SUPPORT */ 490 491 #endif /* PORTMOD_SUPPORT */ 492