1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (C) 2018-2022 Marvell International Ltd. 4 */ 5 6#include <errno.h> 7#include <i2c.h> 8#include <log.h> 9#include <malloc.h> 10#include <linux/delay.h> 11#include <display_options.h> 12 13#include <mach/cvmx-regs.h> 14#include <mach/cvmx-csr.h> 15#include <mach/cvmx-bootmem.h> 16#include <mach/octeon-model.h> 17#include <mach/cvmx-fuse.h> 18#include <mach/octeon-feature.h> 19#include <mach/cvmx-qlm.h> 20#include <mach/octeon_qlm.h> 21#include <mach/cvmx-pcie.h> 22#include <mach/cvmx-coremask.h> 23 24#include <mach/cvmx-helper.h> 25#include <mach/cvmx-helper-board.h> 26#include <mach/cvmx-helper-fdt.h> 27#include <mach/cvmx-helper-cfg.h> 28#include <mach/cvmx-helper-gpio.h> 29#include <mach/cvmx-helper-util.h> 30 31extern void octeon_i2c_unblock(int bus); 32 33static struct cvmx_fdt_sfp_info *sfp_list; 34 35/** 36 * Local allocator to handle both SE and U-Boot that also zeroes out memory 37 * 38 * @param size number of bytes to allocate 39 * 40 * @return pointer to allocated memory or NULL if out of memory. 41 * Alignment is set to 8-bytes. 42 */ 43static void *cvm_sfp_alloc(size_t size) 44{ 45 return calloc(size, 1); 46} 47 48/** 49 * Free allocated memory. 50 * 51 * @param ptr pointer to memory to free 52 * 53 * NOTE: This only works in U-Boot since SE does not really have a freeing 54 * mechanism. In SE the memory is zeroed out and not freed so this 55 * is a memory leak if errors occur. 56 */ 57static inline void cvm_sfp_free(void *ptr, size_t size) 58{ 59 free(ptr); 60} 61 62/** 63 * Select a QSFP device before accessing the EEPROM 64 * 65 * @param sfp handle for sfp/qsfp connector 66 * @param enable Set true to select, false to deselect 67 * 68 * @return 0 on success or if SFP or no select GPIO, -1 on GPIO error 69 */ 70static int cvmx_qsfp_select(const struct cvmx_fdt_sfp_info *sfp, bool enable) 71{ 72 /* Select is only needed for QSFP modules */ 73 if (!sfp->is_qsfp) { 74 debug("%s(%s, %d): not QSFP\n", __func__, sfp->name, enable); 75 return 0; 76 } 77 78 if (dm_gpio_is_valid(&sfp->select)) { 79 /* Note that select is active low */ 80 return dm_gpio_set_value(&sfp->select, !enable); 81 } 82 83 debug("%s: select GPIO unknown\n", __func__); 84 return 0; 85} 86 87static int cvmx_sfp_parse_sfp_buffer(struct cvmx_sfp_mod_info *sfp_info, 88 const uint8_t *buffer) 89{ 90 u8 csum = 0; 91 bool csum_good = false; 92 int i; 93 94 /* Validate the checksum */ 95 for (i = 0; i < 0x3f; i++) 96 csum += buffer[i]; 97 csum_good = csum == buffer[0x3f]; 98 debug("%s: Lower checksum: 0x%02x, expected: 0x%02x\n", __func__, csum, 99 buffer[0x3f]); 100 csum = 0; 101 for (i = 0x40; i < 0x5f; i++) 102 csum += buffer[i]; 103 debug("%s: Upper checksum: 0x%02x, expected: 0x%02x\n", __func__, csum, 104 buffer[0x5f]); 105 if (csum != buffer[0x5f] || !csum_good) { 106 debug("Error: SFP EEPROM checksum information is incorrect\n"); 107 return -1; 108 } 109 110 sfp_info->conn_type = buffer[0]; 111 if (buffer[1] < 1 || buffer[1] > 7) { /* Extended ID */ 112 debug("Error: Unknown SFP extended identifier 0x%x\n", 113 buffer[1]); 114 return -1; 115 } 116 if (buffer[1] != 4) { 117 debug("Module is not SFP/SFP+/SFP28/QSFP+\n"); 118 return -1; 119 } 120 sfp_info->mod_type = buffer[2]; 121 sfp_info->eth_comp = buffer[3] & 0xf0; 122 sfp_info->cable_comp = buffer[0x24]; 123 124 /* There are several ways a cable can be marked as active or 125 * passive. 8.[2-3] specify the SFP+ cable technology. Some 126 * modules also use 3.[0-1] for Infiniband, though it's 127 * redundant. 128 */ 129 if ((buffer[8] & 0x0C) == 0x08) { 130 sfp_info->limiting = true; 131 sfp_info->active_cable = true; 132 } else if ((buffer[8] & 0xC) == 0x4) { 133 sfp_info->limiting = false; 134 sfp_info->active_cable = false; 135 } 136 if ((buffer[3] & 3) == 2) { 137 sfp_info->active_cable = true; 138 sfp_info->limiting = true; 139 } 140 141 switch (sfp_info->mod_type) { 142 case CVMX_SFP_MOD_OPTICAL_LC: 143 case CVMX_SFP_MOD_OPTICAL_PIGTAIL: 144 sfp_info->copper_cable = false; 145 break; 146 case CVMX_SFP_MOD_COPPER_PIGTAIL: 147 sfp_info->copper_cable = true; 148 break; 149 case CVMX_SFP_MOD_NO_SEP_CONN: 150 switch (sfp_info->cable_comp) { 151 case CVMX_SFP_CABLE_100G_25GAUI_C2M_AOC_HIGH_BER: 152 case CVMX_SFP_CABLE_100G_25GAUI_C2M_AOC_LOW_BER: 153 case CVMX_SFP_CABLE_100G_25GAUI_C2M_ACC_LOW_BER: 154 sfp_info->copper_cable = false; 155 sfp_info->limiting = true; 156 sfp_info->active_cable = true; 157 break; 158 159 case CVMX_SFP_CABLE_100G_SR4_25G_SR: 160 case CVMX_SFP_CABLE_100G_LR4_25G_LR: 161 case CVMX_SFP_CABLE_100G_ER4_25G_ER: 162 case CVMX_SFP_CABLE_100G_SR10: 163 case CVMX_SFP_CABLE_100G_CWDM4_MSA: 164 case CVMX_SFP_CABLE_100G_PSM4: 165 case CVMX_SFP_CABLE_100G_CWDM4: 166 case CVMX_SFP_CABLE_40G_ER4: 167 case CVMX_SFP_CABLE_4X10G_SR: 168 case CVMX_SFP_CABLE_G959_1_P1I1_2D1: 169 case CVMX_SFP_CABLE_G959_1_P1S1_2D2: 170 case CVMX_SFP_CABLE_G959_1_P1L1_2D2: 171 case CVMX_SFP_CABLE_100G_CLR4: 172 case CVMX_SFP_CABLE_100G_2_LAMBDA_DWDM: 173 case CVMX_SFP_CABLE_40G_SWDM4: 174 case CVMX_SFP_CABLE_100G_SWDM4: 175 case CVMX_SFP_CABLE_100G_PAM4_BIDI: 176 sfp_info->copper_cable = false; 177 break; 178 179 case CVMX_SFP_CABLE_100G_25GAUI_C2M_ACC_HIGH_BER: 180 case CVMX_SFP_CABLE_10GBASE_T: 181 case CVMX_SFP_CABLE_10GBASE_T_SR: 182 case CVMX_SFP_CABLE_5GBASE_T: 183 case CVMX_SFP_CABLE_2_5GBASE_T: 184 sfp_info->copper_cable = true; 185 sfp_info->limiting = true; 186 sfp_info->active_cable = true; 187 break; 188 189 case CVMX_SFP_CABLE_100G_CR4_25G_CR_CA_L: 190 case CVMX_SFP_CABLE_25G_CR_CA_S: 191 case CVMX_SFP_CABLE_25G_CR_CA_N: 192 case CVMX_SFP_CABLE_40G_PSM4: 193 sfp_info->copper_cable = true; 194 break; 195 196 default: 197 switch (sfp_info->eth_comp) { 198 case CVMX_SFP_CABLE_10GBASE_ER: 199 case CVMX_SFP_CABLE_10GBASE_LRM: 200 case CVMX_SFP_CABLE_10GBASE_LR: 201 case CVMX_SFP_CABLE_10GBASE_SR: 202 sfp_info->copper_cable = false; 203 break; 204 } 205 break; 206 } 207 break; 208 209 case CVMX_SFP_MOD_RJ45: 210 debug("%s: RJ45 adapter\n", __func__); 211 sfp_info->copper_cable = true; 212 sfp_info->active_cable = true; 213 sfp_info->limiting = true; 214 break; 215 case CVMX_SFP_MOD_UNKNOWN: 216 /* The Avago 1000Base-X to 1000Base-T module reports that it 217 * is an unknown module type but the Ethernet compliance code 218 * says it is 1000Base-T. We'll change the reporting to RJ45. 219 */ 220 if (buffer[6] & 8) { 221 debug("RJ45 gigabit module detected\n"); 222 sfp_info->mod_type = CVMX_SFP_MOD_RJ45; 223 sfp_info->copper_cable = false; 224 sfp_info->limiting = true; 225 sfp_info->active_cable = true; 226 sfp_info->max_copper_cable_len = buffer[0x12]; 227 sfp_info->rate = CVMX_SFP_RATE_1G; 228 } else { 229 debug("Unknown module type 0x%x\n", sfp_info->mod_type); 230 } 231 sfp_info->limiting = true; 232 break; 233 case CVMX_SFP_MOD_MXC_2X16: 234 debug("%s: MXC 2X16\n", __func__); 235 break; 236 default: 237 sfp_info->limiting = true; 238 break; 239 } 240 241 if (sfp_info->copper_cable) 242 sfp_info->max_copper_cable_len = buffer[0x12]; 243 else 244 sfp_info->max_50um_om4_cable_length = buffer[0x12] * 10; 245 246 if (buffer[0xe]) 247 sfp_info->max_single_mode_cable_length = buffer[0xe] * 1000; 248 else 249 sfp_info->max_single_mode_cable_length = buffer[0xf] * 100000; 250 251 sfp_info->max_50um_om2_cable_length = buffer[0x10] * 10; 252 sfp_info->max_62_5um_om1_cable_length = buffer[0x11] * 10; 253 sfp_info->max_50um_om3_cable_length = buffer[0x13] * 10; 254 255 if (buffer[0xc] == 0xff) { 256 if (buffer[0x42] >= 255) 257 sfp_info->rate = CVMX_SFP_RATE_100G; 258 else if (buffer[0x42] >= 160) 259 sfp_info->rate = CVMX_SFP_RATE_40G; 260 else if (buffer[0x42] >= 100) 261 sfp_info->rate = CVMX_SFP_RATE_25G; 262 else 263 sfp_info->rate = CVMX_SFP_RATE_UNKNOWN; 264 } else if (buffer[0xc] >= 100) { 265 sfp_info->rate = CVMX_SFP_RATE_10G; 266 } else if (buffer[0xc] >= 10) { 267 sfp_info->rate = CVMX_SFP_RATE_1G; 268 } else { 269 sfp_info->rate = CVMX_SFP_RATE_UNKNOWN; 270 } 271 272 if (sfp_info->rate == CVMX_SFP_RATE_UNKNOWN) { 273 switch (sfp_info->cable_comp) { 274 case CVMX_SFP_CABLE_100G_SR10: 275 case CVMX_SFP_CABLE_100G_CWDM4_MSA: 276 case CVMX_SFP_CABLE_100G_PSM4: 277 case CVMX_SFP_CABLE_100G_CWDM4: 278 case CVMX_SFP_CABLE_100G_CLR4: 279 case CVMX_SFP_CABLE_100G_2_LAMBDA_DWDM: 280 case CVMX_SFP_CABLE_100G_SWDM4: 281 case CVMX_SFP_CABLE_100G_PAM4_BIDI: 282 sfp_info->rate = CVMX_SFP_RATE_100G; 283 break; 284 case CVMX_SFP_CABLE_100G_25GAUI_C2M_AOC_HIGH_BER: 285 case CVMX_SFP_CABLE_100G_SR4_25G_SR: 286 case CVMX_SFP_CABLE_100G_LR4_25G_LR: 287 case CVMX_SFP_CABLE_100G_ER4_25G_ER: 288 case CVMX_SFP_CABLE_100G_25GAUI_C2M_ACC_HIGH_BER: 289 case CVMX_SFP_CABLE_100G_CR4_25G_CR_CA_L: 290 case CVMX_SFP_CABLE_25G_CR_CA_S: 291 case CVMX_SFP_CABLE_25G_CR_CA_N: 292 case CVMX_SFP_CABLE_100G_25GAUI_C2M_AOC_LOW_BER: 293 case CVMX_SFP_CABLE_100G_25GAUI_C2M_ACC_LOW_BER: 294 sfp_info->rate = CVMX_SFP_RATE_25G; 295 break; 296 case CVMX_SFP_CABLE_40G_ER4: 297 case CVMX_SFP_CABLE_4X10G_SR: 298 case CVMX_SFP_CABLE_40G_PSM4: 299 case CVMX_SFP_CABLE_40G_SWDM4: 300 sfp_info->rate = CVMX_SFP_RATE_40G; 301 break; 302 case CVMX_SFP_CABLE_G959_1_P1I1_2D1: 303 case CVMX_SFP_CABLE_G959_1_P1S1_2D2: 304 case CVMX_SFP_CABLE_G959_1_P1L1_2D2: 305 case CVMX_SFP_CABLE_10GBASE_T: 306 case CVMX_SFP_CABLE_10GBASE_T_SR: 307 case CVMX_SFP_CABLE_5GBASE_T: 308 case CVMX_SFP_CABLE_2_5GBASE_T: 309 sfp_info->rate = CVMX_SFP_RATE_10G; 310 break; 311 default: 312 switch (sfp_info->eth_comp) { 313 case CVMX_SFP_CABLE_10GBASE_ER: 314 case CVMX_SFP_CABLE_10GBASE_LRM: 315 case CVMX_SFP_CABLE_10GBASE_LR: 316 case CVMX_SFP_CABLE_10GBASE_SR: 317 sfp_info->rate = CVMX_SFP_RATE_10G; 318 break; 319 default: 320 sfp_info->rate = CVMX_SFP_RATE_UNKNOWN; 321 break; 322 } 323 break; 324 } 325 } 326 327 if (buffer[0xc] < 0xff) 328 sfp_info->bitrate_max = buffer[0xc] * 100; 329 else 330 sfp_info->bitrate_max = buffer[0x42] * 250; 331 332 if ((buffer[8] & 0xc) == 8) { 333 if (buffer[0x3c] & 0x4) 334 sfp_info->limiting = true; 335 } 336 337 /* Currently we only set this for 25G. FEC is required for CA-S cables 338 * and for cable lengths >= 5M as of this writing. 339 */ 340 if ((sfp_info->rate == CVMX_SFP_RATE_25G && 341 sfp_info->copper_cable) && 342 (sfp_info->cable_comp == CVMX_SFP_CABLE_25G_CR_CA_S || 343 sfp_info->max_copper_cable_len >= 5)) 344 sfp_info->fec_required = true; 345 346 /* copy strings and vendor info, strings will be automatically NUL 347 * terminated. 348 */ 349 memcpy(sfp_info->vendor_name, &buffer[0x14], 16); 350 memcpy(sfp_info->vendor_oui, &buffer[0x25], 3); 351 memcpy(sfp_info->vendor_pn, &buffer[0x28], 16); 352 memcpy(sfp_info->vendor_rev, &buffer[0x38], 4); 353 memcpy(sfp_info->vendor_sn, &buffer[0x44], 16); 354 memcpy(sfp_info->date_code, &buffer[0x54], 8); 355 356 sfp_info->cooled_laser = !!(buffer[0x40] & 4); 357 sfp_info->internal_cdr = !!(buffer[0x40] & 8); 358 359 if (buffer[0x40] & 0x20) 360 sfp_info->power_level = 3; 361 else 362 sfp_info->power_level = (buffer[0x40] & 2) ? 2 : 1; 363 364 sfp_info->diag_paging = !!(buffer[0x40] & 0x10); 365 sfp_info->linear_rx_output = !(buffer[0x40] & 1); 366 sfp_info->los_implemented = !!(buffer[0x41] & 2); 367 sfp_info->los_inverted = !!(buffer[0x41] & 4); 368 sfp_info->tx_fault_implemented = !!(buffer[0x41] & 8); 369 sfp_info->tx_disable_implemented = !!(buffer[0x41] & 0x10); 370 sfp_info->rate_select_implemented = !!(buffer[0x41] & 0x20); 371 sfp_info->tuneable_transmitter = !!(buffer[0x41] & 0x40); 372 sfp_info->rx_decision_threshold_implemented = !!(buffer[0x41] & 0x80); 373 374 sfp_info->diag_monitoring = !!(buffer[0x5c] & 0x40); 375 sfp_info->diag_rx_power_averaged = !!(buffer[0x5c] & 0x8); 376 sfp_info->diag_externally_calibrated = !!(buffer[0x5c] & 0x10); 377 sfp_info->diag_internally_calibrated = !!(buffer[0x5c] & 0x20); 378 sfp_info->diag_addr_change_required = !!(buffer[0x5c] & 0x4); 379 sfp_info->diag_soft_rate_select_control = !!(buffer[0x5d] & 2); 380 sfp_info->diag_app_select_control = !!(buffer[0x5d] & 4); 381 sfp_info->diag_soft_rate_select_control = !!(buffer[0x5d] & 8); 382 sfp_info->diag_soft_rx_los_implemented = !!(buffer[0x5d] & 0x10); 383 sfp_info->diag_soft_tx_fault_implemented = !!(buffer[0x5d] & 0x20); 384 sfp_info->diag_soft_tx_disable_implemented = !!(buffer[0x5d] & 0x40); 385 sfp_info->diag_alarm_warning_flags_implemented = 386 !!(buffer[0x5d] & 0x80); 387 sfp_info->diag_rev = buffer[0x5e]; 388 389 return 0; 390} 391 392static int cvmx_sfp_parse_qsfp_buffer(struct cvmx_sfp_mod_info *sfp_info, 393 const uint8_t *buffer) 394{ 395 u8 csum = 0; 396 bool csum_good = false; 397 int i; 398 399 /* Validate the checksum */ 400 for (i = 0x80; i < 0xbf; i++) 401 csum += buffer[i]; 402 csum_good = csum == buffer[0xbf]; 403 debug("%s: Lower checksum: 0x%02x, expected: 0x%02x\n", __func__, csum, 404 buffer[0xbf]); 405 csum = 0; 406 for (i = 0xc0; i < 0xdf; i++) 407 csum += buffer[i]; 408 debug("%s: Upper checksum: 0x%02x, expected: 0x%02x\n", __func__, csum, 409 buffer[0xdf]); 410 if (csum != buffer[0xdf] || !csum_good) { 411 debug("Error: SFP EEPROM checksum information is incorrect\n"); 412 return -1; 413 } 414 415 sfp_info->conn_type = buffer[0x80]; 416 sfp_info->mod_type = buffer[0x82]; 417 sfp_info->eth_comp = buffer[0x83] & 0xf0; 418 sfp_info->cable_comp = buffer[0xa4]; 419 420 switch (sfp_info->mod_type) { 421 case CVMX_SFP_MOD_COPPER_PIGTAIL: 422 case CVMX_SFP_MOD_NO_SEP_CONN: 423 debug("%s: copper pigtail or no separable cable\n", __func__); 424 /* There are several ways a cable can be marked as active or 425 * passive. 8.[2-3] specify the SFP+ cable technology. Some 426 * modules also use 3.[0-1] for Infiniband, though it's 427 * redundant. 428 */ 429 sfp_info->copper_cable = true; 430 if ((buffer[0x88] & 0x0C) == 0x08) { 431 sfp_info->limiting = true; 432 sfp_info->active_cable = true; 433 } else if ((buffer[0x88] & 0xC) == 0x4) { 434 sfp_info->limiting = false; 435 sfp_info->active_cable = false; 436 } 437 if ((buffer[0x83] & 3) == 2) { 438 sfp_info->active_cable = true; 439 sfp_info->limiting = true; 440 } 441 break; 442 case CVMX_SFP_MOD_RJ45: 443 debug("%s: RJ45 adapter\n", __func__); 444 sfp_info->copper_cable = true; 445 sfp_info->active_cable = true; 446 sfp_info->limiting = true; 447 break; 448 case CVMX_SFP_MOD_UNKNOWN: 449 debug("Unknown module type\n"); 450 /* The Avago 1000Base-X to 1000Base-T module reports that it 451 * is an unknown module type but the Ethernet compliance code 452 * says it is 1000Base-T. We'll change the reporting to RJ45. 453 */ 454 if (buffer[0x86] & 8) { 455 sfp_info->mod_type = CVMX_SFP_MOD_RJ45; 456 sfp_info->copper_cable = false; 457 sfp_info->limiting = true; 458 sfp_info->active_cable = true; 459 sfp_info->max_copper_cable_len = buffer[0x92]; 460 sfp_info->rate = CVMX_SFP_RATE_1G; 461 } 462 fallthrough; 463 default: 464 sfp_info->limiting = true; 465 break; 466 } 467 468 if (sfp_info->copper_cable) 469 sfp_info->max_copper_cable_len = buffer[0x92]; 470 else 471 sfp_info->max_50um_om4_cable_length = buffer[0x92] * 10; 472 473 debug("%s: copper cable: %d, max copper cable len: %d\n", __func__, 474 sfp_info->copper_cable, sfp_info->max_copper_cable_len); 475 if (buffer[0xe]) 476 sfp_info->max_single_mode_cable_length = buffer[0x8e] * 1000; 477 else 478 sfp_info->max_single_mode_cable_length = buffer[0x8f] * 100000; 479 480 sfp_info->max_50um_om2_cable_length = buffer[0x90] * 10; 481 sfp_info->max_62_5um_om1_cable_length = buffer[0x91] * 10; 482 sfp_info->max_50um_om3_cable_length = buffer[0x93] * 10; 483 484 if (buffer[0x8c] == 12) { 485 sfp_info->rate = CVMX_SFP_RATE_1G; 486 } else if (buffer[0x8c] == 103) { 487 sfp_info->rate = CVMX_SFP_RATE_10G; 488 } else if (buffer[0x8c] == 0xff) { 489 if (buffer[0xc2] == 103) 490 sfp_info->rate = CVMX_SFP_RATE_100G; 491 } 492 493 if (buffer[0x8c] < 0xff) 494 sfp_info->bitrate_max = buffer[0x8c] * 100; 495 else 496 sfp_info->bitrate_max = buffer[0xc2] * 250; 497 498 if ((buffer[0x88] & 0xc) == 8) { 499 if (buffer[0xbc] & 0x4) 500 sfp_info->limiting = true; 501 } 502 503 /* Currently we only set this for 25G. FEC is required for CA-S cables 504 * and for cable lengths >= 5M as of this writing. 505 */ 506 /* copy strings and vendor info, strings will be automatically NUL 507 * terminated. 508 */ 509 memcpy(sfp_info->vendor_name, &buffer[0x94], 16); 510 memcpy(sfp_info->vendor_oui, &buffer[0xa5], 3); 511 memcpy(sfp_info->vendor_pn, &buffer[0xa8], 16); 512 memcpy(sfp_info->vendor_rev, &buffer[0xb8], 4); 513 memcpy(sfp_info->vendor_sn, &buffer[0xc4], 16); 514 memcpy(sfp_info->date_code, &buffer[0xd4], 8); 515 516 sfp_info->linear_rx_output = !!(buffer[0xc0] & 1); 517 sfp_info->cooled_laser = !!(buffer[0xc0] & 4); 518 sfp_info->internal_cdr = !!(buffer[0xc0] & 8); 519 520 if (buffer[0xc0] & 0x20) 521 sfp_info->power_level = 3; 522 else 523 sfp_info->power_level = (buffer[0xc0] & 2) ? 2 : 1; 524 525 sfp_info->diag_paging = !!(buffer[0xc0] & 0x10); 526 sfp_info->los_implemented = !!(buffer[0xc1] & 2); 527 sfp_info->los_inverted = !!(buffer[0xc1] & 4); 528 sfp_info->tx_fault_implemented = !!(buffer[0xc1] & 8); 529 sfp_info->tx_disable_implemented = !!(buffer[0xc1] & 0x10); 530 sfp_info->rate_select_implemented = !!(buffer[0xc1] & 0x20); 531 sfp_info->tuneable_transmitter = !!(buffer[0xc1] & 0x40); 532 sfp_info->rx_decision_threshold_implemented = !!(buffer[0xc1] & 0x80); 533 534 sfp_info->diag_monitoring = !!(buffer[0xdc] & 0x40); 535 sfp_info->diag_rx_power_averaged = !!(buffer[0xdc] & 0x8); 536 sfp_info->diag_externally_calibrated = !!(buffer[0xdc] & 0x10); 537 sfp_info->diag_internally_calibrated = !!(buffer[0xdc] & 0x20); 538 sfp_info->diag_addr_change_required = !!(buffer[0xdc] & 0x4); 539 sfp_info->diag_soft_rate_select_control = !!(buffer[0xdd] & 2); 540 sfp_info->diag_app_select_control = !!(buffer[0xdd] & 4); 541 sfp_info->diag_soft_rate_select_control = !!(buffer[0xdd] & 8); 542 sfp_info->diag_soft_rx_los_implemented = !!(buffer[0xdd] & 0x10); 543 sfp_info->diag_soft_tx_fault_implemented = !!(buffer[0xdd] & 0x20); 544 sfp_info->diag_soft_tx_disable_implemented = !!(buffer[0xdd] & 0x40); 545 sfp_info->diag_alarm_warning_flags_implemented = 546 !!(buffer[0xdd] & 0x80); 547 sfp_info->diag_rev = buffer[0xde]; 548 549 return 0; 550} 551 552static bool sfp_verify_checksum(const uint8_t *buffer) 553{ 554 u8 csum = 0; 555 u8 offset; 556 bool csum_good = false; 557 int i; 558 559 switch (buffer[0]) { 560 case CVMX_SFP_CONN_QSFP: 561 case CVMX_SFP_CONN_QSFPP: 562 case CVMX_SFP_CONN_QSFP28: 563 case CVMX_SFP_CONN_MICRO_QSFP: 564 case CVMX_SFP_CONN_QSFP_DD: 565 offset = 0x80; 566 break; 567 default: 568 offset = 0; 569 break; 570 } 571 for (i = offset; i < offset + 0x3f; i++) 572 csum += buffer[i]; 573 csum_good = csum == buffer[offset + 0x3f]; 574 if (!csum_good) { 575 debug("%s: Lower checksum bad, got 0x%x, expected 0x%x\n", 576 __func__, csum, buffer[offset + 0x3f]); 577 return false; 578 } 579 csum = 0; 580 for (i = offset + 0x40; i < offset + 0x5f; i++) 581 csum += buffer[i]; 582 if (csum != buffer[offset + 0x5f]) { 583 debug("%s: Upper checksum bad, got 0x%x, expected 0x%x\n", 584 __func__, csum, buffer[offset + 0x5f]); 585 return false; 586 } 587 return true; 588} 589 590/** 591 * Reads and parses SFP/QSFP EEPROM 592 * 593 * @param sfp sfp handle to read 594 * 595 * @return 0 for success, -1 on error. 596 */ 597int cvmx_sfp_read_i2c_eeprom(struct cvmx_fdt_sfp_info *sfp) 598{ 599 const struct cvmx_fdt_i2c_bus_info *bus = sfp->i2c_bus; 600 int oct_bus = cvmx_fdt_i2c_get_root_bus(bus); 601 struct udevice *dev; 602 u8 buffer[256]; 603 bool is_qsfp; 604 int retry; 605 int err; 606 607 if (!bus) { 608 debug("%s(%s): Error: i2c bus undefined for eeprom\n", __func__, 609 sfp->name); 610 return -1; 611 } 612 613 is_qsfp = (sfp->sfp_info.conn_type == CVMX_SFP_CONN_QSFP || 614 sfp->sfp_info.conn_type == CVMX_SFP_CONN_QSFPP || 615 sfp->sfp_info.conn_type == CVMX_SFP_CONN_QSFP28 || 616 sfp->sfp_info.conn_type == CVMX_SFP_CONN_MICRO_QSFP) || 617 sfp->is_qsfp; 618 619 err = cvmx_qsfp_select(sfp, true); 620 if (err) { 621 debug("%s: Error selecting SFP/QSFP slot\n", __func__); 622 return err; 623 } 624 625 debug("%s: Reading eeprom from i2c address %d:0x%x\n", __func__, 626 oct_bus, sfp->i2c_eeprom_addr); 627 for (retry = 0; retry < 3; retry++) { 628 err = i2c_get_chip(bus->i2c_bus, sfp->i2c_eeprom_addr, 1, &dev); 629 if (err) { 630 debug("Cannot find I2C device: %d\n", err); 631 goto error; 632 } 633 634 err = dm_i2c_read(dev, 0, buffer, 256); 635 if (err || !sfp_verify_checksum(buffer)) { 636 debug("%s: Error %d reading eeprom at 0x%x, bus %d\n", 637 __func__, err, sfp->i2c_eeprom_addr, oct_bus); 638 debug("%s: Retry %d\n", __func__, retry + 1); 639 mdelay(1000); 640 } else { 641 break; 642 } 643 } 644 if (err) { 645 debug("%s: Error reading eeprom from SFP %s\n", __func__, 646 sfp->name); 647 return -1; 648 } 649#ifdef DEBUG 650 print_buffer(0, buffer, 1, 256, 0); 651#endif 652 memset(&sfp->sfp_info, 0, sizeof(struct cvmx_sfp_mod_info)); 653 654 switch (buffer[0]) { 655 case CVMX_SFP_CONN_SFP: 656 err = cvmx_sfp_parse_sfp_buffer(&sfp->sfp_info, buffer); 657 break; 658 case CVMX_SFP_CONN_QSFP: 659 case CVMX_SFP_CONN_QSFPP: 660 case CVMX_SFP_CONN_QSFP28: 661 case CVMX_SFP_CONN_MICRO_QSFP: 662 err = cvmx_sfp_parse_qsfp_buffer(&sfp->sfp_info, buffer); 663 break; 664 default: 665 debug("%s: Unknown SFP transceiver type 0x%x\n", __func__, 666 buffer[0]); 667 err = -1; 668 break; 669 } 670 671error: 672 if (is_qsfp) 673 err |= cvmx_qsfp_select(sfp, false); 674 675 if (!err) { 676 sfp->valid = true; 677 sfp->sfp_info.valid = true; 678 } else { 679 sfp->valid = false; 680 sfp->sfp_info.valid = false; 681 } 682 683 return err; 684} 685 686/** 687 * Function called to check and return the status of the mod_abs pin or 688 * mod_pres pin for QSFPs. 689 * 690 * @param sfp Handle to SFP information. 691 * @param data User-defined data passed to the function 692 * 693 * @return 0 if absent, 1 if present, -1 on error 694 */ 695int cvmx_sfp_check_mod_abs(struct cvmx_fdt_sfp_info *sfp, void *data) 696{ 697 int val; 698 int err = 0; 699 int mode; 700 701 if (!dm_gpio_is_valid(&sfp->mod_abs)) { 702 debug("%s: Error: mod_abs not set for %s\n", __func__, 703 sfp->name); 704 return -1; 705 } 706 val = dm_gpio_get_value(&sfp->mod_abs); 707 debug("%s(%s, %p) mod_abs: %d\n", __func__, sfp->name, data, val); 708 if (val >= 0 && val != sfp->last_mod_abs && sfp->mod_abs_changed) { 709 err = 0; 710 if (!val) { 711 err = cvmx_sfp_read_i2c_eeprom(sfp); 712 if (err) 713 debug("%s: Error reading SFP %s EEPROM\n", 714 __func__, sfp->name); 715 } 716 err = sfp->mod_abs_changed(sfp, val, sfp->mod_abs_changed_data); 717 } 718 debug("%s(%s (%p)): Last mod_abs: %d, current: %d, changed: %p, rc: %d, next: %p, caller: %p\n", 719 __func__, sfp->name, sfp, sfp->last_mod_abs, val, 720 sfp->mod_abs_changed, err, sfp->next_iface_sfp, 721 __builtin_return_address(0)); 722 723 if (err >= 0) { 724 sfp->last_mod_abs = val; 725 mode = cvmx_helper_interface_get_mode(sfp->xiface); 726 cvmx_sfp_validate_module(sfp, mode); 727 } else { 728 debug("%s: mod_abs_changed for %s returned error\n", __func__, 729 sfp->name); 730 } 731 732 return err < 0 ? err : val; 733} 734 735/** 736 * Reads the EEPROMs of all SFP modules. 737 * 738 * @return 0 for success 739 */ 740int cvmx_sfp_read_all_modules(void) 741{ 742 struct cvmx_fdt_sfp_info *sfp; 743 int val; 744 bool error = false; 745 int rc; 746 747 for (sfp = sfp_list; sfp; sfp = sfp->next) { 748 if (dm_gpio_is_valid(&sfp->mod_abs)) { 749 /* Check if module absent */ 750 val = dm_gpio_get_value(&sfp->mod_abs); 751 sfp->last_mod_abs = val; 752 if (val) 753 continue; 754 } 755 rc = cvmx_sfp_read_i2c_eeprom(sfp); 756 if (rc) { 757 debug("%s: Error reading eeprom from SFP %s\n", 758 __func__, sfp->name); 759 error = true; 760 } 761 } 762 763 return error ? -1 : 0; 764} 765 766/** 767 * Registers a function to be called whenever the mod_abs/mod_pres signal 768 * changes. 769 * 770 * @param sfp Handle to SFP data structure 771 * @param mod_abs_changed Function called whenever mod_abs is changed 772 * or NULL to remove. 773 * @param mod_abs_changed_data User-defined data passed to 774 * mod_abs_changed 775 * 776 * @return 0 for success 777 * 778 * @NOTE: If multiple SFP slots are linked together, all subsequent slots 779 * will also be registered for the same handler. 780 */ 781int cvmx_sfp_register_mod_abs_changed(struct cvmx_fdt_sfp_info *sfp, 782 int (*mod_abs_changed)(struct cvmx_fdt_sfp_info *sfp, 783 int val, void *data), 784 void *mod_abs_changed_data) 785{ 786 sfp->mod_abs_changed = mod_abs_changed; 787 sfp->mod_abs_changed_data = mod_abs_changed_data; 788 789 sfp->last_mod_abs = -2; /* undefined */ 790 791 return 0; 792} 793 794/** 795 * Parses a SFP slot from the device tree 796 * 797 * @param sfp SFP handle to store data in 798 * @param fdt_addr Address of flat device tree 799 * @param of_offset Node in device tree for SFP slot 800 * 801 * @return 0 on success, -1 on error 802 */ 803static int cvmx_sfp_parse_sfp(struct cvmx_fdt_sfp_info *sfp, ofnode node) 804{ 805 struct ofnode_phandle_args phandle; 806 int err; 807 808 sfp->name = ofnode_get_name(node); 809 sfp->of_offset = ofnode_to_offset(node); 810 811 err = gpio_request_by_name_nodev(node, "tx_disable", 0, 812 &sfp->tx_disable, GPIOD_IS_OUT); 813 if (err) { 814 printf("%s: tx_disable not found in DT!\n", __func__); 815 return -ENODEV; 816 } 817 dm_gpio_set_value(&sfp->tx_disable, 0); 818 819 err = gpio_request_by_name_nodev(node, "mod_abs", 0, 820 &sfp->mod_abs, GPIOD_IS_IN); 821 if (err) { 822 printf("%s: mod_abs not found in DT!\n", __func__); 823 return -ENODEV; 824 } 825 826 err = gpio_request_by_name_nodev(node, "tx_error", 0, 827 &sfp->tx_error, GPIOD_IS_IN); 828 if (err) { 829 printf("%s: tx_error not found in DT!\n", __func__); 830 return -ENODEV; 831 } 832 833 err = gpio_request_by_name_nodev(node, "rx_los", 0, 834 &sfp->rx_los, GPIOD_IS_IN); 835 if (err) { 836 printf("%s: rx_los not found in DT!\n", __func__); 837 return -ENODEV; 838 } 839 840 err = ofnode_parse_phandle_with_args(node, "eeprom", NULL, 0, 0, 841 &phandle); 842 if (!err) { 843 sfp->i2c_eeprom_addr = ofnode_get_addr(phandle.node); 844 debug("%s: eeprom address: 0x%x\n", __func__, 845 sfp->i2c_eeprom_addr); 846 847 debug("%s: Getting eeprom i2c bus for %s\n", __func__, 848 sfp->name); 849 sfp->i2c_bus = cvmx_ofnode_get_i2c_bus(ofnode_get_parent(phandle.node)); 850 } 851 852 err = ofnode_parse_phandle_with_args(node, "diag", NULL, 0, 0, 853 &phandle); 854 if (!err) { 855 sfp->i2c_diag_addr = ofnode_get_addr(phandle.node); 856 if (!sfp->i2c_bus) 857 sfp->i2c_bus = cvmx_ofnode_get_i2c_bus(ofnode_get_parent(phandle.node)); 858 } 859 860 sfp->last_mod_abs = -2; 861 sfp->last_rx_los = -2; 862 863 if (!sfp->i2c_bus) { 864 debug("%s(%s): Error: could not get i2c bus from device tree\n", 865 __func__, sfp->name); 866 err = -1; 867 } 868 869 if (err) { 870 dm_gpio_free(sfp->tx_disable.dev, &sfp->tx_disable); 871 dm_gpio_free(sfp->mod_abs.dev, &sfp->mod_abs); 872 dm_gpio_free(sfp->tx_error.dev, &sfp->tx_error); 873 dm_gpio_free(sfp->rx_los.dev, &sfp->rx_los); 874 } else { 875 sfp->valid = true; 876 } 877 878 return err; 879} 880 881/** 882 * Parses a QSFP slot from the device tree 883 * 884 * @param sfp SFP handle to store data in 885 * @param fdt_addr Address of flat device tree 886 * @param of_offset Node in device tree for SFP slot 887 * 888 * @return 0 on success, -1 on error 889 */ 890static int cvmx_sfp_parse_qsfp(struct cvmx_fdt_sfp_info *sfp, ofnode node) 891{ 892 struct ofnode_phandle_args phandle; 893 int err; 894 895 sfp->is_qsfp = true; 896 sfp->name = ofnode_get_name(node); 897 sfp->of_offset = ofnode_to_offset(node); 898 899 err = gpio_request_by_name_nodev(node, "lp_mode", 0, 900 &sfp->lp_mode, GPIOD_IS_OUT); 901 if (err) { 902 printf("%s: lp_mode not found in DT!\n", __func__); 903 return -ENODEV; 904 } 905 906 err = gpio_request_by_name_nodev(node, "mod_prs", 0, 907 &sfp->mod_abs, GPIOD_IS_IN); 908 if (err) { 909 printf("%s: mod_prs not found in DT!\n", __func__); 910 return -ENODEV; 911 } 912 913 err = gpio_request_by_name_nodev(node, "select", 0, 914 &sfp->select, GPIOD_IS_IN); 915 if (err) { 916 printf("%s: select not found in DT!\n", __func__); 917 return -ENODEV; 918 } 919 920 err = gpio_request_by_name_nodev(node, "reset", 0, 921 &sfp->reset, GPIOD_IS_OUT); 922 if (err) { 923 printf("%s: reset not found in DT!\n", __func__); 924 return -ENODEV; 925 } 926 927 err = gpio_request_by_name_nodev(node, "interrupt", 0, 928 &sfp->interrupt, GPIOD_IS_IN); 929 if (err) { 930 printf("%s: interrupt not found in DT!\n", __func__); 931 return -ENODEV; 932 } 933 934 err = ofnode_parse_phandle_with_args(node, "eeprom", NULL, 0, 0, 935 &phandle); 936 if (!err) { 937 sfp->i2c_eeprom_addr = ofnode_get_addr(phandle.node); 938 sfp->i2c_bus = cvmx_ofnode_get_i2c_bus(ofnode_get_parent(phandle.node)); 939 } 940 941 err = ofnode_parse_phandle_with_args(node, "diag", NULL, 0, 0, 942 &phandle); 943 if (!err) { 944 sfp->i2c_diag_addr = ofnode_get_addr(phandle.node); 945 if (!sfp->i2c_bus) 946 sfp->i2c_bus = cvmx_ofnode_get_i2c_bus(ofnode_get_parent(phandle.node)); 947 } 948 949 sfp->last_mod_abs = -2; 950 sfp->last_rx_los = -2; 951 952 if (!sfp->i2c_bus) { 953 cvmx_printf("%s(%s): Error: could not get i2c bus from device tree\n", 954 __func__, sfp->name); 955 err = -1; 956 } 957 958 if (err) { 959 dm_gpio_free(sfp->lp_mode.dev, &sfp->lp_mode); 960 dm_gpio_free(sfp->mod_abs.dev, &sfp->mod_abs); 961 dm_gpio_free(sfp->select.dev, &sfp->select); 962 dm_gpio_free(sfp->reset.dev, &sfp->reset); 963 dm_gpio_free(sfp->interrupt.dev, &sfp->interrupt); 964 } else { 965 sfp->valid = true; 966 } 967 968 return err; 969} 970 971/** 972 * Parses the device tree for SFP and QSFP slots 973 * 974 * @param fdt_addr Address of flat device-tree 975 * 976 * @return 0 for success, -1 on error 977 */ 978int cvmx_sfp_parse_device_tree(const void *fdt_addr) 979{ 980 struct cvmx_fdt_sfp_info *sfp, *first_sfp = NULL, *last_sfp = NULL; 981 ofnode node; 982 int err = 0; 983 int reg; 984 static bool parsed; 985 986 debug("%s(%p): Parsing...\n", __func__, fdt_addr); 987 if (parsed) { 988 debug("%s(%p): Already parsed\n", __func__, fdt_addr); 989 return 0; 990 } 991 992 ofnode_for_each_compatible_node(node, "ethernet,sfp-slot") { 993 if (!ofnode_valid(node)) 994 continue; 995 996 sfp = cvm_sfp_alloc(sizeof(*sfp)); 997 if (!sfp) 998 return -1; 999 1000 err = cvmx_sfp_parse_sfp(sfp, node); 1001 if (!err) { 1002 if (!sfp_list) 1003 sfp_list = sfp; 1004 if (last_sfp) 1005 last_sfp->next = sfp; 1006 sfp->prev = last_sfp; 1007 last_sfp = sfp; 1008 debug("%s: parsed %s\n", __func__, sfp->name); 1009 } else { 1010 debug("%s: Error parsing SFP at node %s\n", 1011 __func__, ofnode_get_name(node)); 1012 return err; 1013 } 1014 } 1015 1016 ofnode_for_each_compatible_node(node, "ethernet,qsfp-slot") { 1017 if (!ofnode_valid(node)) 1018 continue; 1019 1020 sfp = cvm_sfp_alloc(sizeof(*sfp)); 1021 if (!sfp) 1022 return -1; 1023 1024 err = cvmx_sfp_parse_qsfp(sfp, node); 1025 if (!err) { 1026 if (!sfp_list) 1027 sfp_list = sfp; 1028 if (last_sfp) 1029 last_sfp->next = sfp; 1030 sfp->prev = last_sfp; 1031 last_sfp = sfp; 1032 debug("%s: parsed %s\n", __func__, sfp->name); 1033 } else { 1034 debug("%s: Error parsing QSFP at node %s\n", 1035 __func__, ofnode_get_name(node)); 1036 return err; 1037 } 1038 } 1039 1040 if (!octeon_has_feature(OCTEON_FEATURE_BGX)) 1041 return 0; 1042 1043 err = 0; 1044 ofnode_for_each_compatible_node(node, "cavium,octeon-7890-bgx-port") { 1045 int sfp_nodes[4]; 1046 ofnode sfp_ofnodes[4]; 1047 int num_sfp_nodes; 1048 u64 reg_addr; 1049 struct cvmx_xiface xi; 1050 int xiface, index; 1051 cvmx_helper_interface_mode_t mode; 1052 int i; 1053 int rc; 1054 1055 if (!ofnode_valid(node)) 1056 break; 1057 1058 num_sfp_nodes = ARRAY_SIZE(sfp_nodes); 1059 rc = cvmx_ofnode_lookup_phandles(node, "sfp-slot", 1060 &num_sfp_nodes, sfp_ofnodes); 1061 if (rc != 0 || num_sfp_nodes < 1) 1062 rc = cvmx_ofnode_lookup_phandles(node, "qsfp-slot", 1063 &num_sfp_nodes, 1064 sfp_ofnodes); 1065 /* If no SFP or QSFP slot found, go to next port */ 1066 if (rc < 0) 1067 continue; 1068 1069 last_sfp = NULL; 1070 for (i = 0; i < num_sfp_nodes; i++) { 1071 sfp = cvmx_sfp_find_slot_by_fdt_node(ofnode_to_offset(sfp_ofnodes[i])); 1072 debug("%s: Adding sfp %s (%p) to BGX port\n", 1073 __func__, sfp->name, sfp); 1074 if (last_sfp) 1075 last_sfp->next_iface_sfp = sfp; 1076 else 1077 first_sfp = sfp; 1078 last_sfp = sfp; 1079 } 1080 if (!first_sfp) { 1081 debug("%s: Error: could not find SFP slot for BGX port %s\n", 1082 __func__, 1083 fdt_get_name(fdt_addr, sfp_nodes[0], 1084 NULL)); 1085 err = -1; 1086 break; 1087 } 1088 1089 /* Get the port index */ 1090 reg = ofnode_get_addr(node); 1091 if (reg < 0) { 1092 debug("%s: Error: could not get BGX port reg value\n", 1093 __func__); 1094 err = -1; 1095 break; 1096 } 1097 index = reg; 1098 1099 /* Get BGX node and address */ 1100 reg_addr = ofnode_get_addr(ofnode_get_parent(node)); 1101 /* Extrace node */ 1102 xi.node = cvmx_csr_addr_to_node(reg_addr); 1103 /* Extract reg address */ 1104 reg_addr = cvmx_csr_addr_strip_node(reg_addr); 1105 if ((reg_addr & 0xFFFFFFFFF0000000) != 1106 0x00011800E0000000) { 1107 debug("%s: Invalid BGX address 0x%llx\n", 1108 __func__, (unsigned long long)reg_addr); 1109 xi.node = -1; 1110 err = -1; 1111 break; 1112 } 1113 1114 /* Extract interface from address */ 1115 xi.interface = (reg_addr >> 24) & 0x0F; 1116 /* Convert to xiface */ 1117 xiface = cvmx_helper_node_interface_to_xiface(xi.node, 1118 xi.interface); 1119 debug("%s: Parsed %d SFP slots for interface 0x%x, index %d\n", 1120 __func__, num_sfp_nodes, xiface, index); 1121 1122 mode = cvmx_helper_interface_get_mode(xiface); 1123 for (sfp = first_sfp; sfp; sfp = sfp->next_iface_sfp) { 1124 sfp->xiface = xiface; 1125 sfp->index = index; 1126 /* Convert to IPD port */ 1127 sfp->ipd_port[0] = 1128 cvmx_helper_get_ipd_port(xiface, index); 1129 debug("%s: sfp %s (%p) xi: 0x%x, index: 0x%x, node: %d, mode: 0x%x, next: %p\n", 1130 __func__, sfp->name, sfp, sfp->xiface, 1131 sfp->index, xi.node, mode, 1132 sfp->next_iface_sfp); 1133 if (mode == CVMX_HELPER_INTERFACE_MODE_XLAUI || 1134 mode == CVMX_HELPER_INTERFACE_MODE_40G_KR4) 1135 for (i = 1; i < 4; i++) 1136 sfp->ipd_port[i] = -1; 1137 else 1138 for (i = 1; i < 4; i++) 1139 sfp->ipd_port[i] = 1140 cvmx_helper_get_ipd_port( 1141 xiface, i); 1142 } 1143 cvmx_helper_cfg_set_sfp_info(xiface, index, first_sfp); 1144 } 1145 1146 if (!err) { 1147 parsed = true; 1148 cvmx_sfp_read_all_modules(); 1149 } 1150 1151 return err; 1152} 1153 1154/** 1155 * Given a fdt node offset find the corresponding SFP or QSFP slot 1156 * 1157 * @param of_offset flat device tree node offset 1158 * 1159 * @return pointer to SFP data structure or NULL if not found 1160 */ 1161struct cvmx_fdt_sfp_info *cvmx_sfp_find_slot_by_fdt_node(int of_offset) 1162{ 1163 struct cvmx_fdt_sfp_info *sfp = sfp_list; 1164 1165 while (sfp) { 1166 if (sfp->of_offset == of_offset) 1167 return sfp; 1168 sfp = sfp->next; 1169 } 1170 return NULL; 1171} 1172 1173static bool cvmx_sfp_validate_quad(struct cvmx_fdt_sfp_info *sfp, 1174 struct cvmx_phy_gpio_leds *leds) 1175{ 1176 bool multi_led = leds && (leds->next); 1177 bool error = false; 1178 int mod_abs; 1179 1180 do { 1181 /* Skip missing modules */ 1182 if (dm_gpio_is_valid(&sfp->mod_abs)) 1183 mod_abs = dm_gpio_get_value(&sfp->mod_abs); 1184 else 1185 mod_abs = 0; 1186 if (!mod_abs) { 1187 if (cvmx_sfp_read_i2c_eeprom(sfp)) { 1188 debug("%s: Error reading eeprom for %s\n", 1189 __func__, sfp->name); 1190 } 1191 if (sfp->sfp_info.rate < CVMX_SFP_RATE_10G) { 1192 cvmx_helper_leds_show_error(leds, true); 1193 error = true; 1194 } else if (sfp->sfp_info.rate >= CVMX_SFP_RATE_10G) { 1195 /* We don't support 10GBase-T modules in 1196 * this mode. 1197 */ 1198 switch (sfp->sfp_info.cable_comp) { 1199 case CVMX_SFP_CABLE_10GBASE_T: 1200 case CVMX_SFP_CABLE_10GBASE_T_SR: 1201 case CVMX_SFP_CABLE_5GBASE_T: 1202 case CVMX_SFP_CABLE_2_5GBASE_T: 1203 cvmx_helper_leds_show_error(leds, true); 1204 error = true; 1205 break; 1206 default: 1207 break; 1208 } 1209 } 1210 } else if (multi_led) { 1211 cvmx_helper_leds_show_error(leds, false); 1212 } 1213 1214 if (multi_led && leds->next) 1215 leds = leds->next; 1216 sfp = sfp->next_iface_sfp; 1217 } while (sfp); 1218 1219 if (!multi_led) 1220 cvmx_helper_leds_show_error(leds, error); 1221 1222 return error; 1223} 1224 1225/** 1226 * Validates if the module is correct for the specified port 1227 * 1228 * @param[in] sfp SFP port to check 1229 * @param xiface interface 1230 * @param index port index 1231 * @param speed link speed, -1 if unknown 1232 * @param mode interface mode 1233 * 1234 * @return true if module is valid, false if invalid 1235 * NOTE: This will also toggle the error LED, if present 1236 */ 1237bool cvmx_sfp_validate_module(struct cvmx_fdt_sfp_info *sfp, int mode) 1238{ 1239 const struct cvmx_sfp_mod_info *mod_info = &sfp->sfp_info; 1240 int xiface = sfp->xiface; 1241 int index = sfp->index; 1242 struct cvmx_phy_gpio_leds *leds; 1243 bool error = false; 1244 bool quad_mode = false; 1245 1246 debug("%s(%s, 0x%x, 0x%x, 0x%x)\n", __func__, sfp->name, xiface, index, 1247 mode); 1248 if (!sfp) { 1249 debug("%s: Error: sfp is NULL\n", __func__); 1250 return false; 1251 } 1252 /* No module is valid */ 1253 leds = cvmx_helper_get_port_phy_leds(xiface, index); 1254 if (!leds) 1255 debug("%s: No leds for 0x%x:0x%x\n", __func__, xiface, index); 1256 1257 if (mode != CVMX_HELPER_INTERFACE_MODE_XLAUI && 1258 mode != CVMX_HELPER_INTERFACE_MODE_40G_KR4 && !sfp->is_qsfp && 1259 sfp->last_mod_abs && leds) { 1260 cvmx_helper_leds_show_error(leds, false); 1261 debug("%s: %s: last_mod_abs: %d, no error\n", __func__, 1262 sfp->name, sfp->last_mod_abs); 1263 return true; 1264 } 1265 1266 switch (mode) { 1267 case CVMX_HELPER_INTERFACE_MODE_RGMII: 1268 case CVMX_HELPER_INTERFACE_MODE_GMII: 1269 case CVMX_HELPER_INTERFACE_MODE_SGMII: 1270 case CVMX_HELPER_INTERFACE_MODE_QSGMII: 1271 case CVMX_HELPER_INTERFACE_MODE_AGL: 1272 case CVMX_HELPER_INTERFACE_MODE_SPI: 1273 if ((mod_info->active_cable && 1274 mod_info->rate != CVMX_SFP_RATE_1G) || 1275 mod_info->rate < CVMX_SFP_RATE_1G) 1276 error = true; 1277 break; 1278 case CVMX_HELPER_INTERFACE_MODE_RXAUI: 1279 case CVMX_HELPER_INTERFACE_MODE_XAUI: 1280 case CVMX_HELPER_INTERFACE_MODE_10G_KR: 1281 case CVMX_HELPER_INTERFACE_MODE_XFI: 1282 if ((mod_info->active_cable && 1283 mod_info->rate != CVMX_SFP_RATE_10G) || 1284 mod_info->rate < CVMX_SFP_RATE_10G) 1285 error = true; 1286 break; 1287 case CVMX_HELPER_INTERFACE_MODE_XLAUI: 1288 case CVMX_HELPER_INTERFACE_MODE_40G_KR4: 1289 if (!sfp->is_qsfp) { 1290 quad_mode = true; 1291 error = cvmx_sfp_validate_quad(sfp, leds); 1292 } else { 1293 if ((mod_info->active_cable && 1294 mod_info->rate != CVMX_SFP_RATE_40G) || 1295 mod_info->rate < CVMX_SFP_RATE_25G) 1296 error = true; 1297 } 1298 break; 1299 default: 1300 debug("%s: Unsupported interface mode %d on xiface 0x%x\n", 1301 __func__, mode, xiface); 1302 return false; 1303 } 1304 debug("%s: %s: error: %d\n", __func__, sfp->name, error); 1305 if (leds && !quad_mode) 1306 cvmx_helper_leds_show_error(leds, error); 1307 1308 return !error; 1309} 1310