blob: 655bb106cc81b6860cdd322a5cb59fd71d2ef1c7 [file] [log] [blame]
Aaron Williams3bda89d2020-12-11 17:05:24 +01001/* 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
26struct cvmx_fdt_sfp_info;
27struct cvmx_fdt_gpio_info;
28/**
29 * Connector type for module, usually we only see SFP and QSFPP
30 */
31enum 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 */
45enum 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 */
68enum 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 */
81enum 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 */
140enum 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 */
148enum 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 */
164struct 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 *
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100267 * Return: -1 if invalid bus or i2c read error, 0 for success
Aaron Williams3bda89d2020-12-11 17:05:24 +0100268 */
269int 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 *
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100278 * Return: 0 on success, -1 if error reading EEPROM or if EEPROM corrupt
Aaron Williams3bda89d2020-12-11 17:05:24 +0100279 */
280int 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 */
287void 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 *
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100294 * Return: 0 for success, -1 on error.
Aaron Williams3bda89d2020-12-11 17:05:24 +0100295 */
296int 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 *
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100303 * Return: sfp_info Pointer sfp mod info data structure
Aaron Williams3bda89d2020-12-11 17:05:24 +0100304 */
305const 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 *
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100314 * Return: 0 if absent, 1 if present, -1 on error
Aaron Williams3bda89d2020-12-11 17:05:24 +0100315 */
316int 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 *
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100326 * Return: 0 for success
Aaron Williams3bda89d2020-12-11 17:05:24 +0100327 */
328int 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 *
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100342 * Return: 0 for success
Aaron Williams3bda89d2020-12-11 17:05:24 +0100343 */
344int 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 *
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100355 * Return: 0 if signal present, 1 if signal absent, -1 on error
Aaron Williams3bda89d2020-12-11 17:05:24 +0100356 */
357int 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 *
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100365 * Return: 0 if signal present, 1 if signal absent, -1 on error
Aaron Williams3bda89d2020-12-11 17:05:24 +0100366 */
367int 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 *
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100378 * Return: 0 for success
Aaron Williams3bda89d2020-12-11 17:05:24 +0100379 */
380int 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 *
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100390 * Return: 0 for success, -1 on error
Aaron Williams3bda89d2020-12-11 17:05:24 +0100391 */
392int 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 *
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100399 * Return: pointer to SFP data structure or NULL if not found
Aaron Williams3bda89d2020-12-11 17:05:24 +0100400 */
401struct 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 *
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100408 * Return: pointer to SFP data structure or NULL if not found
Aaron Williams3bda89d2020-12-11 17:05:24 +0100409 */
410struct 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 *
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100415 * Return: 0 for success
Aaron Williams3bda89d2020-12-11 17:05:24 +0100416 */
417int 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 *
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100425 * Return: true if module is valid, false if invalid
Aaron Williams3bda89d2020-12-11 17:05:24 +0100426 * NOTE: This will also toggle the error LED, if present
427 */
428bool 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 */
435void cvmx_sfp_print_info(const struct cvmx_fdt_sfp_info *sfp);
436
437#endif /* __CVMX_HELPER_SFP_H__ */