Skip to content
Permalink
Browse files
eeprom/optoe: driver to read/write SFP/QSFP/CMIS EEPROMS
optoe is an i2c based driver that supports read/write access to all
the pages (tables) of MSA standard SFP and similar devices (conforming
to the SFF-8472 spec), MSA standard QSFP and similar devices (conforming
to the SFF-8636 spec) and CMIS and similar devices (conforming to the
Common Management Interface Specfication).

These devices provide identification, operational status and control
registers via an EEPROM model.  These devices support one or 3 fixed pages
(128 bytes) of data, and one page that is selected via a page register on
the first fixed page.  Thus the driver's main task is to map these pages
onto a simple linear address space for user space management applications.
See the driver code for a detailed layout.

Several variants and predecessors of this driver exist outside the kernel
tree.  Some of them don't support pages at all, only accessing the first
256 bytes of EEPROM.  None of them handle all three specifications, none
of them support pages beyond page 3.  This is a problem since critical
monitoring data on CMIS devices is on page 0x11.  Some of them don't
support pages at all, only accessing the first 256 bytes of data.  optoe
supports the full architected 256 page address space of these devices.
optoe is currently in production on multiple platforms running SONiC
(Microsoft's Software for Open Networking in the Cloud) and ONL (Open
Network Linux).  They have requested that optoe be submitted upstream.

The EEPROM data is accessible to user space and kernel consumers via the
nvmem interface.

optoe devices can be configured via device tree or the 'new_device'
paradigm.

See Documentation/misc-devices/optoe.rst for details on configuring
optoe and accessing the EEPROM.

Signed-off-by: Don Bollinger <don@thebollingers.org>
  • Loading branch information
donboll authored and intel-lab-lkp committed Feb 15, 2021
1 parent a2ea4e1 commit 9089aa757bfb70c473ca54face762582908bdd28
Show file tree
Hide file tree
Showing 5 changed files with 1,109 additions and 0 deletions.
@@ -0,0 +1,26 @@
EEPROMs on SFP/QSFP/CMIS optoelectronic modules using SFF-8472, SFF-8676,
CMIS (Common Management Interface Spec) devices.

Required properties:
- compatible: shall be one of :
'optoe,optoe1' - for QSFP class devices, adhering to SFF-8636
'optoe,optoe2' - for SFP class devices, adhering to SFF-8472
'optoe,optoe3' - for CMIS devices (newer QSFP class devices)
- reg: 0x50 The only valid value is 0x50, as all three standards specify that
the device is at i2c address 0x50. (optoe allocates an i2c dummy to access
the data at i2c address 0x51.)

Optional property:
- port_name: can be set to any string up to 19 characters. Note that the
actual mapping between i2c busses and network ports is platform dependent
and varies widely. The 'port_name' property provides a way to associate
specific network ports with their associated hardware ports.

Example:
#address-cells = <1>;
#size-cells = <0>;
optoe@50 {
compatible = "optoe,optoe2";
reg = <0x50>;
port_name = "port1";
};
@@ -0,0 +1,127 @@
============================================================
optoe - EEPROMs on SFP/QSFP/CMIS optoelectronic modules
============================================================

Author: Don Bollinger (don@thebollingers.org)

Description:
============

Optoe is an i2c based driver that supports read/write access to all
the pages (tables) of MSA standard SFP and similar devices (conforming
to the SFF-8472 spec), MSA standard QSFP and similar devices (conforming
to the SFF-8436 or SFF-8636 spec) and CMIS devices (conforming to the
Common Management Interface Specification).

i2c based optoelectronic transceivers (SPF, QSFP, etc) provide identification,
operational status, and control registers via an EEPROM model. Unlike the
EEPROMs that at24 supports, these devices access data beyond byte 256 via
a page select register, which must be managed by the driver. optoe
represents the EEPROM as a linear address space, managing the page register
as needed. On QSFP and CMIS devices, the first 256 bytes are page 0, followed
by 128 byte pages 1-128. On SFP devices, the first 256 bytes are from
i2c address 0x50, followed by 256 bytes from i2c address 0x51, followed
by 128 byte pages 1-128. See the driver code for a more detailed
explanation.

The EEPROM data is accessible via an nvmem file, e.g.
/sys/bus/nvmem/devices/port1/nvmem

The EEPROM data is also accessible within the kernel via nvmem calls e.g.
nvmem = nvmem_device_get(dev, "port1");
err = nvmem_device_read(nvmem, offset, length, buffer);

The EEPROM data is also accessible via a bin_attribute file called 'eeprom',
e.g. /sys/bus/i2c/devices/24-0050/eeprom

Device class:
=============

Note that SFP, QSFP and CMIS type devices are not interchangeable. The
driver expects the correct ID (optoe<n>) for each port (each i2c device).
It does not check because the port will often be empty, and the only way
to check is to interrogate the device. Incorrect choice of ID will lead
to CORRECT data being reported for the first 256 bytes (for any ID, for
any actual class device). Data beyond 256 bytes will be INCORRECT if
the device doesn't match the optoe<n> type specified.

The device class (1 = QSFP, 2 = SFP, 3 = CMIS) can be read from
/sys/bus/i2c/devices/<i2c device>/dev_class. It can also be modified
by writing to the same file. This can be useful when upgrading from QSFP
type devices to CMIS devices (they may have the same form factor) or
when developing with plug-in adapters to convert QSFP ports for SFP
devices. It is also useful on development hardware that has both types
of connectors attached to the same i2c bus.

Port name:
==========

optoe maintains a 'port_name' for each device being managed. The port name
is the device name in the nvmem directory, and the dev_name parameter in
the nvmem_device_get() APIs.

port_name can be set via a device tree property: port_name = "port1";

port_name can also be read/changed by reading/writing to the sysfs file
/sys/bus/i2c/devices/<i2c device>/port_name. port_name can be any string,
up to 19 characters. If not initialized, port_name will match the i2c
device name e.g. 1-0050. If port_name is changed, the nvmem device will
be changed to match.

Device Tree:
============

optoe can be instantiated via Device Tree as a child of the i2c bus
that the device is attached to.

Required properties:
- compatible: shall be one of :
'optoe,optoe1' - for QSFP class devices, adhering to SFF-8636
'optoe,optoe2' - for SFP class devices, adhering to SFF-8472
'optoe,optoe3' - for CMIS devices (newer QSFP class devices)
- reg: 0x50 The only valid value is 0x50, as all three standards specify that
the device is at i2c address 0x50. (optoe allocates an i2c dummy to access
the data at i2c address 0x51.)

Optional property:
- port_name: can be set to any string up to 19 characters. Note that the
actual mapping between i2c busses and network ports is platform dependent
and varies widely. The 'port_name' property provides a way to associate
specific network ports with their associated hardware ports.

Example:
#address-cells = <1>;
#size-cells = <0>;
optoe@50 {
compatible = "optoe,optoe2";
reg = <0x50>;
port_name = "port1";
};


Dynamic installation:
=====================

Alternatively, optoe can be instantiated with 'new_device', per the convention
described in Documentation/i2c/instantiating-devices. It wants one of
three possible device identifiers, as described above under 'compatible'.
Use 'optoe1' to indicate this is a QSFP type device, use 'optoe2' to
indicate this is an SFP type device, use 'optoe3' to indicate this is a
CMIS type device.

Example:
# echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-64/new_device
# echo port54 > /sys/bus/i2c/devices/i2c-64/port_name

This will add a QSFP type device to i2c bus i2c-64, and name it 'port54'

Example:
# echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-11/new_device
# echo port1 > /sys/bus/i2c/devices/i2c-11/port_name

This will add an SFP type device to i2c bus i2c-11, and name it 'port1'

The second parameter to new_device is an i2c address, and MUST be 0x50 for
this driver to work properly. This is part of the spec for these devices.
(It is not necessary to create a device at 0x51 for SFP type devices, the
driver does that automatically.)
@@ -129,4 +129,28 @@ config EEPROM_EE1004
This driver can also be built as a module. If so, the module
will be called ee1004.

config EEPROM_OPTOE
tristate "read/write access to SFP*, QSFP* and CMIS EEPROMs"
depends on I2C && SYSFS
select NVMEM
select NVMEM_SYSFS
select REGMAP_I2C
help
If you say yes here you get support for read and write access to
the EEPROM of SFP, QSFP and CMIS type optical and copper
transceivers. This includes all devices which conform to SFF-8436
and SFF-8636 (QSFP, QSFP+, QSFP28, etc), SFF-8472 (SFP, SFP+, SFP28,
SFP-DWDM, etc) and Common Management Interface Spec (CMIS, including
QSFP-DD, OSFP, later QSFP*, etc).

These devices are usually found in network switches.

This driver only manages read/write access to the EEPROM. Access
to the I/O pins (reset, LPMODE, etc) is still platform specific.

This driver can also be built as a module. If so, the module
will be called optoe.

If unsure, say N.

endmenu
@@ -8,3 +8,4 @@ obj-$(CONFIG_EEPROM_93XX46) += eeprom_93xx46.o
obj-$(CONFIG_EEPROM_DIGSY_MTC_CFG) += digsy_mtc_eeprom.o
obj-$(CONFIG_EEPROM_IDT_89HPESX) += idt_89hpesx.o
obj-$(CONFIG_EEPROM_EE1004) += ee1004.o
obj-$(CONFIG_EEPROM_OPTOE) += optoe.o

0 comments on commit 9089aa7

Please sign in to comment.