diff --git a/doc/sfp.md b/doc/sfp.md new file mode 100644 index 0000000..15fcead --- /dev/null +++ b/doc/sfp.md @@ -0,0 +1,107 @@ +# SFP+ Slots + +The RTL8372/3 provide support for 1 or 2 SFP+ slots, which support fiber and Ethernet +module with speeds of 1GBit, 2.5GBit and 10GBit. 5GBit could be possible but is not +implemented due to the lack of suitable modules. + +When a module is inserted, it directly connects to GPIO, I2C and RX/TX data lines of +the SoC. An example schematics can be found here: +(SFP Module Schematics)[https://sfp.by/source/manual/SCP6F44-GL-BWE.pdf]. Another +resources is (here)[https://www.sfptransceiver.com/product_pdf/SFP/SFP%20Design%20Guide.pdf]. +The SoC +detects the insertion because the MOD-DEF0 line is pulled low by the module. The +corresponding bit in RTL837X_REG_GPIO_B or RTL837X_REG_GPIO_C will transition from +1 to 0. At that point, the code waits for some 100ms in order for the module to power +up and then reads the EEPROM of the module to get the type of module and in particular +the bit-rate. The EEPROM can be read via the MOD-DEF1 and MOD-DEF2 lines which +provide a standard I2C interface to the standard 24C-EEPROM. The SoCs contain a simple +I2C controller for reading such EEPROMs so that interfacing is very simple. + +## I2C Controller + +The I2C controller of the RTL8372/3 is very simple and probably designed specifically +for reading 24C EEPROMs. Its use is straight-forward: Configure the I2C bus used +(the code currently uses the default already set regarding what is probably timing) +in the RTL837X_REG_I2C_CTRL register. Then set the EEPROM-register's addresss to be +read in RTL837X_REG_I2C_IN (least-significant byte). The I2C transfer is started +by setting the 0-bit of RTL837X_REG_I2C_CTRL. When this bit is cleared by the +ASIC-side of the SoC, the resulting value can be read in the LSB of RTL837X_REG_I2C_OUT. +This is the code: +``` +uint8_t sfp_read_reg(uint8_t slot, uint8_t reg) +{ + // Select I2C-bus according to slot + if (slot == 0) { + reg_read_m(RTL837X_REG_I2C_CTRL); + sfr_mask_data(1, 0xff, 0x72); + reg_write_m(RTL837X_REG_I2C_CTRL); + } else { + reg_read_m(RTL837X_REG_I2C_CTRL); + sfr_mask_data(1, 0xff, 0x6e); + reg_write_m(RTL837X_REG_I2C_CTRL); + } + + REG_WRITE(RTL837X_REG_I2C_IN, 0, 0, 0, reg); + + // Execute I2C Read + reg_bit_set(RTL837X_REG_I2C_CTRL, 0); + + // Wait for execution to finish + do { + reg_read_m(RTL837X_REG_I2C_CTRL); + } while (sfr_data[3] & 0x1); + + reg_read_m(RTL837X_REG_I2C_OUT); + return sfr_data[3]; +} +``` + +The description of the data stored in the EEPROM can be found in the +(SFF-8472 standard)[https://members.snia.org/document/dl/25916] +The most relevant is byte 12 (0x0c), which gives the signalling rate of the module in +100MBit, including the 25% overhead for error correction. Currently the code looks like +this: +``` +static inline uint8_t sfp_rate_to_sds_config(register uint8_t rate) +{ + if (rate == 0xd) + return SDS_1000BX_FIBER; + if (rate == 0x1f) // Ethernet 2.5 GBit + return SDS_HSG; + if (rate > 0x65 && rate < 0x70) + return SDS_10GR; + return 0xff; +} +``` +For example, a 1000MBit fiber module will have a rate coding of 0xd = 13 = 1300Mbit, +which is the rounded-up value for 1250MBit, the error-corrected bit-rate of +a 1000BX fiber module. + +## Interfacing the module for RX/TX + +In order to transmit data or receive data from the module, the SerDes of the SoC connected +to the module needs to e properly configured. As can be seen from the +(SFP Module Schematics)[https://sfp.by/source/manual/SCP6F44-GL-BWE.pdf], the Photo-transistor +of the module is optimized by an amplifier and quantized to bits, which directly arrive +at the SoC in a differential pair. This data still has the 25% overhead of the error correction +codes that were on the fiber. The switch needs to configure the SerDes correctl (sds_config()) +and set up the MAC on the SoC to talk to the SDS with the correct bit-rate. + +## Other SFP-module GPIOs +SFP modules also provide RX-LOS GPIOs, which pulls low when the fiber or Ethernet +cable is not attached (on either side of the link) and usually also a TX-disable GPIO, +which allows to disable the Laser in order to power down the link. There is typically +also a TX-Fault GPIO which pulls low when the laser overheated. While the RX-Los pin +is connected to the SoC and can be read for the devices with a single SFP+ slot +(for the dual-SFP+ slot KP-9000-6HX-X2 only the RX-LOS pin of the right slot seems to +be connected), the other GPIOs have not been identified and counting lines on the PCB +seems to indicate these pins are unlikely to be connected. + +The RX-LOS GPIO does not provide any further benefit, since the link status can also be +read from the link-status registers of the MAC or SDS. + +The easiest way to identifiy additional GPIOs of an SFP module is to take a cheap module +apart, solder wires to the pins of the on-board PCB which are then routed back through +the end of the module. By pulling e.g. TX-Fault low while printing out the GPIOs, the +correct GPIO can be identified. +