1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Copyright (C) 2020 Marvell International Ltd. 4 * 5 * Helper functions to abstract SFP and QSFP connectors 6 */ 7 8 #ifndef __CVMX_HELPER_SFP_H__ 9 #define __CVMX_HELPER_SFP_H__ 10 11 /** 12 * Maximum size for the SFP EEPROM. Currently only 96 bytes are used. 13 */ 14 #define CVMX_SFP_MAX_EEPROM_SIZE 0x100 15 16 /** 17 * Default address of sfp EEPROM 18 */ 19 #define CVMX_SFP_DEFAULT_I2C_ADDR 0x50 20 21 /** 22 * Default address of SFP diagnostics chip 23 */ 24 #define CVMX_SFP_DEFAULT_DIAG_I2C_ADDR 0x51 25 26 struct cvmx_fdt_sfp_info; 27 struct cvmx_fdt_gpio_info; 28 /** 29 * Connector type for module, usually we only see SFP and QSFPP 30 */ 31 enum cvmx_phy_sfp_conn_type { 32 CVMX_SFP_CONN_GBIC = 0x01, /** GBIC */ 33 CVMX_SFP_CONN_SFP = 0x03, /** SFP/SFP+/SFP28 */ 34 CVMX_SFP_CONN_QSFP = 0x0C, /** 1G QSFP (obsolete) */ 35 CVMX_SFP_CONN_QSFPP = 0x0D, /** QSFP+ or later */ 36 CVMX_SFP_CONN_QSFP28 = 0x11, /** QSFP28 (100Gbps) */ 37 CVMX_SFP_CONN_MICRO_QSFP = 0x17, /** Micro QSFP */ 38 CVMX_SFP_CONN_QSFP_DD = 0x18, /** QSFP-DD Double Density 8X */ 39 CVMX_SFP_CONN_SFP_DD = 0x1A, /** SFP-DD Double Density 2X */ 40 }; 41 42 /** 43 * module type plugged into a SFP/SFP+/QSFP+ port 44 */ 45 enum cvmx_phy_sfp_mod_type { 46 CVMX_SFP_MOD_UNKNOWN = 0, /** Unknown or unspecified */ 47 /** Fiber optic module (LC connector) */ 48 CVMX_SFP_MOD_OPTICAL_LC = 0x7, 49 /** Multiple optical */ 50 CVMX_SFP_MOD_MULTIPLE_OPTICAL = 0x9, 51 /** Fiber optic module (pigtail, no connector) */ 52 CVMX_SFP_MOD_OPTICAL_PIGTAIL = 0xB, 53 CVMX_SFP_MOD_COPPER_PIGTAIL = 0x21, /** copper module */ 54 CVMX_SFP_MOD_RJ45 = 0x22, /** RJ45 (i.e. 10GBase-T) */ 55 /** No separable connector (SFP28/copper) */ 56 CVMX_SFP_MOD_NO_SEP_CONN = 0x23, 57 /** MXC 2X16 */ 58 CVMX_SFP_MOD_MXC_2X16 = 0x24, 59 /** CS optical connector */ 60 CVMX_SFP_MOD_CS_OPTICAL = 0x25, 61 /** Mini CS optical connector */ 62 CVMX_SFP_MOD_MINI_CS_OPTICAL = 0x26, 63 /** Unknown/other module type */ 64 CVMX_SFP_MOD_OTHER 65 }; 66 67 /** Peak rate supported by SFP cable */ 68 enum cvmx_phy_sfp_rate { 69 CVMX_SFP_RATE_UNKNOWN, /** Unknown rate */ 70 CVMX_SFP_RATE_1G, /** 1Gbps */ 71 CVMX_SFP_RATE_10G, /** 10Gbps */ 72 CVMX_SFP_RATE_25G, /** 25Gbps */ 73 CVMX_SFP_RATE_40G, /** 40Gbps */ 74 CVMX_SFP_RATE_100G /** 100Gbps */ 75 }; 76 77 /** 78 * Cable compliance specification 79 * See table 4-4 from SFF-8024 for the extended specification compliance codes 80 */ 81 enum cvmx_phy_sfp_cable_ext_compliance { 82 CVMX_SFP_CABLE_UNSPEC = 0, 83 CVMX_SFP_CABLE_100G_25GAUI_C2M_AOC_HIGH_BER = 0x01, /** Active optical cable */ 84 CVMX_SFP_CABLE_100G_SR4_25G_SR = 0x2, 85 CVMX_SFP_CABLE_100G_LR4_25G_LR = 0x3, 86 CVMX_SFP_CABLE_100G_ER4_25G_ER = 0x4, 87 CVMX_SFP_CABLE_100G_SR10 = 0x5, 88 CVMX_SFP_CABLE_100G_CWDM4_MSA = 0x6, 89 CVMX_SFP_CABLE_100G_PSM4 = 0x7, 90 CVMX_SFP_CABLE_100G_25GAUI_C2M_ACC_HIGH_BER = 0x8, 91 CVMX_SFP_CABLE_100G_CWDM4 = 0x9, 92 CVMX_SFP_CABLE_100G_CR4_25G_CR_CA_L = 0xB, 93 CVMX_SFP_CABLE_25G_CR_CA_S = 0xC, 94 CVMX_SFP_CABLE_25G_CR_CA_N = 0xD, 95 CVMX_SFP_CABLE_40G_ER4 = 0x10, 96 CVMX_SFP_CABLE_4X10G_SR = 0x11, 97 CVMX_SFP_CABLE_40G_PSM4 = 0x12, 98 CVMX_SFP_CABLE_G959_1_P1I1_2D1 = 0x13, 99 CVMX_SFP_CABLE_G959_1_P1S1_2D2 = 0x14, 100 CVMX_SFP_CABLE_G959_1_P1L1_2D2 = 0x15, 101 CVMX_SFP_CABLE_10GBASE_T = 0x16, 102 CVMX_SFP_CABLE_100G_CLR4 = 0x17, 103 CVMX_SFP_CABLE_100G_25GAUI_C2M_AOC_LOW_BER = 0x18, 104 CVMX_SFP_CABLE_100G_25GAUI_C2M_ACC_LOW_BER = 0x19, 105 CVMX_SFP_CABLE_100G_2_LAMBDA_DWDM = 0x1a, 106 CVMX_SFP_CABLE_100G_1550NM_WDM = 0x1b, 107 CVMX_SFP_CABLE_10GBASE_T_SR = 0x1c, 108 CVMX_SFP_CABLE_5GBASE_T = 0x1d, 109 CVMX_SFP_CABLE_2_5GBASE_T = 0x1e, 110 CVMX_SFP_CABLE_40G_SWDM4 = 0x1f, 111 CVMX_SFP_CABLE_100G_SWDM4 = 0x20, 112 CVMX_SFP_CABLE_100G_PAM4_BIDI = 0x21, 113 CVMX_SFP_CABLE_100G_4WDM_10_FEC_HOST = 0x22, 114 CVMX_SFP_CABLE_100G_4WDM_20_FEC_HOST = 0x23, 115 CVMX_SFP_CABLE_100G_4WDM_40_FEC_HOST = 0x24, 116 CVMX_SFP_CABLE_100GBASE_DR_CAUI4_NO_FEC = 0x25, 117 CVMX_SFP_CABLE_100G_FR_CAUI4_NO_FEC = 0x26, 118 CVMX_SFP_CABLE_100G_LR_CAUI4_NO_FEC = 0x27, 119 CVMX_SFP_CABLE_ACTIVE_COPPER_50_100_200GAUI_LOW_BER = 0x30, 120 CVMX_SFP_CABLE_ACTIVE_OPTICAL_50_100_200GAUI_LOW_BER = 0x31, 121 CVMX_SFP_CABLE_ACTIVE_COPPER_50_100_200GAUI_HI_BER = 0x32, 122 CVMX_SFP_CABLE_ACTIVE_OPTICAL_50_100_200GAUI_HI_BER = 0x33, 123 CVMX_SFP_CABLE_50_100_200G_CR = 0x40, 124 CVMX_SFP_CABLE_50_100_200G_SR = 0x41, 125 CVMX_SFP_CABLE_50GBASE_FR_200GBASE_DR4 = 0x42, 126 CVMX_SFP_CABLE_200GBASE_FR4 = 0x43, 127 CVMX_SFP_CABLE_200G_1550NM_PSM4 = 0x44, 128 CVMX_SFP_CABLE_50GBASE_LR = 0x45, 129 CVMX_SFP_CABLE_200GBASE_LR4 = 0x46, 130 CVMX_SFP_CABLE_64GFC_EA = 0x50, 131 CVMX_SFP_CABLE_64GFC_SW = 0x51, 132 CVMX_SFP_CABLE_64GFC_LW = 0x52, 133 CVMX_SFP_CABLE_128GFC_EA = 0x53, 134 CVMX_SFP_CABLE_128GFC_SW = 0x54, 135 CVMX_SFP_CABLE_128GFC_LW = 0x55, 136 137 }; 138 139 /** Optical modes module is compliant with */ 140 enum cvmx_phy_sfp_10g_eth_compliance { 141 CVMX_SFP_CABLE_10GBASE_ER = 0x80, /** 10G ER */ 142 CVMX_SFP_CABLE_10GBASE_LRM = 0x40, /** 10G LRM */ 143 CVMX_SFP_CABLE_10GBASE_LR = 0x20, /** 10G LR */ 144 CVMX_SFP_CABLE_10GBASE_SR = 0x10 /** 10G SR */ 145 }; 146 147 /** Diagnostic ASIC compatibility */ 148 enum cvmx_phy_sfp_sff_8472_diag_rev { 149 CVMX_SFP_SFF_8472_NO_DIAG = 0x00, 150 CVMX_SFP_SFF_8472_REV_9_3 = 0x01, 151 CVMX_SFP_SFF_8472_REV_9_5 = 0x02, 152 CVMX_SFP_SFF_8472_REV_10_2 = 0x03, 153 CVMX_SFP_SFF_8472_REV_10_4 = 0x04, 154 CVMX_SFP_SFF_8472_REV_11_0 = 0x05, 155 CVMX_SFP_SFF_8472_REV_11_3 = 0x06, 156 CVMX_SFP_SFF_8472_REV_11_4 = 0x07, 157 CVMX_SFP_SFF_8472_REV_12_0 = 0x08, 158 CVMX_SFP_SFF_8472_REV_UNALLOCATED = 0xff 159 }; 160 161 /** 162 * Data structure describing the current SFP or QSFP EEPROM 163 */ 164 struct cvmx_sfp_mod_info { 165 enum cvmx_phy_sfp_conn_type conn_type; /** Connector type */ 166 enum cvmx_phy_sfp_mod_type mod_type; /** Module type */ 167 enum cvmx_phy_sfp_rate rate; /** Rate of module */ 168 /** 10G Ethernet Compliance codes (logical OR) */ 169 enum cvmx_phy_sfp_10g_eth_compliance eth_comp; 170 /** Extended Cable compliance */ 171 enum cvmx_phy_sfp_cable_ext_compliance cable_comp; 172 u8 vendor_name[17]; /** Module vendor name */ 173 u8 vendor_oui[3]; /** vendor OUI */ 174 u8 vendor_pn[17]; /** Vendor part number */ 175 u8 vendor_rev[5]; /** Vendor revision */ 176 u8 vendor_sn[17]; /** Vendor serial number */ 177 u8 date_code[9]; /** Date code */ 178 bool valid; /** True if module is valid */ 179 bool active_cable; /** False for passive copper */ 180 bool copper_cable; /** True if cable is copper */ 181 /** True if module is limiting (i.e. not passive copper) */ 182 bool limiting; 183 /** Maximum length of copper cable in meters */ 184 int max_copper_cable_len; 185 /** Max single mode cable length in meters */ 186 int max_single_mode_cable_length; 187 /** Max 50um OM2 cable length */ 188 int max_50um_om2_cable_length; 189 /** Max 62.5um OM1 cable length */ 190 int max_62_5um_om1_cable_length; 191 /** Max 50um OM4 cable length */ 192 int max_50um_om4_cable_length; 193 /** Max 50um OM3 cable length */ 194 int max_50um_om3_cable_length; 195 /** Minimum bitrate in Mbps */ 196 int bitrate_min; 197 /** Maximum bitrate in Mbps */ 198 int bitrate_max; 199 /** 200 * Set to true if forward error correction is required, 201 * for example, a 25GBase-CR CA-S cable. 202 * 203 * FEC should only be disabled at 25G with CA-N cables. FEC is required 204 * with 5M and longer cables. 205 */ 206 bool fec_required; 207 /** True if RX output is linear */ 208 bool linear_rx_output; 209 /** Power level, can be 1, 2 or 3 */ 210 int power_level; 211 /** False if conventional cooling is used, true for active cooling */ 212 bool cooled_laser; 213 /** True if internal retimer or clock and data recovery circuit */ 214 bool internal_cdr; 215 /** True if LoS is implemented */ 216 bool los_implemented; 217 /** True if LoS is inverted from the standard */ 218 bool los_inverted; 219 /** True if TX_FAULT is implemented */ 220 bool tx_fault_implemented; 221 /** True if TX_DISABLE is implemented */ 222 bool tx_disable_implemented; 223 /** True if RATE_SELECT is implemented */ 224 bool rate_select_implemented; 225 /** True if tuneable transmitter technology is used */ 226 bool tuneable_transmitter; 227 /** True if receiver decision threshold is implemented */ 228 bool rx_decision_threshold_implemented; 229 /** True if diagnostic monitoring present */ 230 bool diag_monitoring; 231 /** True if diagnostic address 0x7f is used for selecting the page */ 232 bool diag_paging; 233 /** Diagnostic feature revision */ 234 enum cvmx_phy_sfp_sff_8472_diag_rev diag_rev; 235 /** True if an address change sequence is required for diagnostics */ 236 bool diag_addr_change_required; 237 /** True if RX power is averaged, false if OMA */ 238 bool diag_rx_power_averaged; 239 /** True if diagnostics are externally calibrated */ 240 bool diag_externally_calibrated; 241 /** True if diagnostics are internally calibrated */ 242 bool diag_internally_calibrated; 243 /** True of soft rate select control implemented per SFF-8431 */ 244 bool diag_soft_rate_select_control; 245 /** True if application select control implemented per SFF-8079 */ 246 bool diag_app_select_control; 247 /** True if soft RATE_SELECT control and moonitoring implemented */ 248 bool diag_soft_rate_select_implemented; 249 /** True if soft RX_LOS monitoring implemented */ 250 bool diag_soft_rx_los_implemented; 251 /** True if soft TX_FAULT monitoring implemented */ 252 bool diag_soft_tx_fault_implemented; 253 /** True if soft TX_DISABLE control and monitoring implemented */ 254 bool diag_soft_tx_disable_implemented; 255 /** True if alarm/warning flags implemented */ 256 bool diag_alarm_warning_flags_implemented; 257 }; 258 259 /** 260 * Reads the SFP EEPROM using the i2c bus 261 * 262 * @param[out] buffer Buffer to store SFP EEPROM data in 263 * The buffer should be SFP_MAX_EEPROM_SIZE bytes. 264 * @param i2c_bus i2c bus number to read from for SFP port 265 * @param i2c_addr i2c address to use, 0 for default 266 * 267 * @return -1 if invalid bus or i2c read error, 0 for success 268 */ 269 int cvmx_phy_sfp_read_i2c_eeprom(u8 *buffer, int i2c_bus, int i2c_addr); 270 271 /** 272 * Reads the SFP/SFP+/QSFP EEPROM and outputs the type of module or cable 273 * plugged in 274 * 275 * @param[out] sfp_info Info about SFP module 276 * @param[in] buffer SFP EEPROM buffer to parse 277 * 278 * @return 0 on success, -1 if error reading EEPROM or if EEPROM corrupt 279 */ 280 int cvmx_phy_sfp_parse_eeprom(struct cvmx_sfp_mod_info *sfp_info, const u8 *buffer); 281 282 /** 283 * Prints out information about a SFP/QSFP device 284 * 285 * @param[in] sfp_info data structure to print 286 */ 287 void cvmx_phy_sfp_print_info(const struct cvmx_sfp_mod_info *sfp_info); 288 289 /** 290 * Reads and parses SFP/QSFP EEPROM 291 * 292 * @param sfp sfp handle to read 293 * 294 * @return 0 for success, -1 on error. 295 */ 296 int cvmx_sfp_read_i2c_eeprom(struct cvmx_fdt_sfp_info *sfp); 297 298 /** 299 * Returns the information about a SFP/QSFP device 300 * 301 * @param sfp sfp handle 302 * 303 * @return sfp_info Pointer sfp mod info data structure 304 */ 305 const struct cvmx_sfp_mod_info *cvmx_phy_get_sfp_mod_info(const struct cvmx_fdt_sfp_info *sfp); 306 307 /** 308 * Function called to check and return the status of the mod_abs pin or 309 * mod_pres pin for QSFPs. 310 * 311 * @param sfp Handle to SFP information. 312 * @param data User-defined data passed to the function 313 * 314 * @return 0 if absent, 1 if present, -1 on error 315 */ 316 int cvmx_sfp_check_mod_abs(struct cvmx_fdt_sfp_info *sfp, void *data); 317 318 /** 319 * Registers a function to be called to check mod_abs/mod_pres for a SFP/QSFP 320 * slot. 321 * 322 * @param sfp Handle to SFP data structure 323 * @param check_mod_abs Function to be called or NULL to remove 324 * @param mod_abs_data User-defined data to be passed to check_mod_abs 325 * 326 * @return 0 for success 327 */ 328 int cvmx_sfp_register_check_mod_abs(struct cvmx_fdt_sfp_info *sfp, 329 int (*check_mod_abs)(struct cvmx_fdt_sfp_info *sfp, void *data), 330 void *mod_abs_data); 331 332 /** 333 * Registers a function to be called whenever the mod_abs/mod_pres signal 334 * changes. 335 * 336 * @param sfp Handle to SFP data structure 337 * @param mod_abs_changed Function called whenever mod_abs is changed 338 * or NULL to remove. 339 * @param mod_abs_changed_data User-defined data passed to 340 * mod_abs_changed 341 * 342 * @return 0 for success 343 */ 344 int cvmx_sfp_register_mod_abs_changed(struct cvmx_fdt_sfp_info *sfp, 345 int (*mod_abs_changed)(struct cvmx_fdt_sfp_info *sfp, int val, 346 void *data), 347 void *mod_abs_changed_data); 348 349 /** 350 * Function called to check and return the status of the tx_fault pin 351 * 352 * @param sfp Handle to SFP information. 353 * @param data User-defined data passed to the function 354 * 355 * @return 0 if signal present, 1 if signal absent, -1 on error 356 */ 357 int cvmx_sfp_check_tx_fault(struct cvmx_fdt_sfp_info *sfp, void *data); 358 359 /** 360 * Function called to check and return the status of the rx_los pin 361 * 362 * @param sfp Handle to SFP information. 363 * @param data User-defined data passed to the function 364 * 365 * @return 0 if signal present, 1 if signal absent, -1 on error 366 */ 367 int cvmx_sfp_check_rx_los(struct cvmx_fdt_sfp_info *sfp, void *data); 368 369 /** 370 * Registers a function to be called whenever rx_los changes 371 * 372 * @param sfp Handle to SFP data structure 373 * @param rx_los_changed Function to be called when rx_los changes 374 * or NULL to remove the function 375 * @param rx_los_changed_data User-defined data passed to 376 * rx_los_changed 377 * 378 * @return 0 for success 379 */ 380 int cvmx_sfp_register_rx_los_changed(struct cvmx_fdt_sfp_info *sfp, 381 int (*rx_los_changed)(struct cvmx_fdt_sfp_info *sfp, int val, 382 void *data), 383 void *rx_los_changed_data); 384 385 /** 386 * Parses the device tree for SFP and QSFP slots 387 * 388 * @param fdt_addr Address of flat device-tree 389 * 390 * @return 0 for success, -1 on error 391 */ 392 int cvmx_sfp_parse_device_tree(const void *fdt_addr); 393 394 /** 395 * Given an IPD port number find the corresponding SFP or QSFP slot 396 * 397 * @param ipd_port IPD port number to search for 398 * 399 * @return pointer to SFP data structure or NULL if not found 400 */ 401 struct cvmx_fdt_sfp_info *cvmx_sfp_find_slot_by_port(int ipd_port); 402 403 /** 404 * Given a fdt node offset find the corresponding SFP or QSFP slot 405 * 406 * @param of_offset flat device tree node offset 407 * 408 * @return pointer to SFP data structure or NULL if not found 409 */ 410 struct cvmx_fdt_sfp_info *cvmx_sfp_find_slot_by_fdt_node(int of_offset); 411 412 /** 413 * Reads the EEPROMs of all SFP modules. 414 * 415 * @return 0 for success 416 */ 417 int cvmx_sfp_read_all_modules(void); 418 419 /** 420 * Validates if the module is correct for the specified port 421 * 422 * @param[in] sfp SFP port to check 423 * @param mode interface mode 424 * 425 * @return true if module is valid, false if invalid 426 * NOTE: This will also toggle the error LED, if present 427 */ 428 bool cvmx_sfp_validate_module(struct cvmx_fdt_sfp_info *sfp, int mode); 429 430 /** 431 * Prints information about the SFP module 432 * 433 * @param[in] sfp sfp data structure 434 */ 435 void cvmx_sfp_print_info(const struct cvmx_fdt_sfp_info *sfp); 436 437 #endif /* __CVMX_HELPER_SFP_H__ */ 438