#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/jiffies.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/phy.h>
#include <linux/platform_device.h>
#include <linux/rtnetlink.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include "mdio-i2c.h"
#include "sfp.h"
#include "swphy.h"
enum {
GPIO_MODDEF0,
GPIO_LOS,
GPIO_TX_FAULT,
GPIO_TX_DISABLE,
GPIO_RATE_SELECT,
GPIO_MAX,
SFP_F_PRESENT = BIT(GPIO_MODDEF0),
SFP_F_LOS = BIT(GPIO_LOS),
SFP_F_TX_FAULT = BIT(GPIO_TX_FAULT),
SFP_F_TX_DISABLE = BIT(GPIO_TX_DISABLE),
SFP_F_RATE_SELECT = BIT(GPIO_RATE_SELECT),
SFP_E_INSERT = 0,
SFP_E_REMOVE,
SFP_E_DEV_DOWN,
SFP_E_DEV_UP,
SFP_E_TX_FAULT,
SFP_E_TX_CLEAR,
SFP_E_LOS_HIGH,
SFP_E_LOS_LOW,
SFP_E_TIMEOUT,
SFP_MOD_EMPTY = 0,
SFP_MOD_PROBE,
SFP_MOD_HPOWER,
SFP_MOD_PRESENT,
SFP_MOD_ERROR,
SFP_DEV_DOWN = 0,
SFP_DEV_UP,
SFP_S_DOWN = 0,
SFP_S_INIT,
SFP_S_WAIT_LOS,
SFP_S_LINK_UP,
SFP_S_TX_FAULT,
SFP_S_REINIT,
SFP_S_TX_DISABLE,
};
static const char *gpio_of_names[] = {
"mod-def0",
"los",
"tx-fault",
"tx-disable",
"rate-select0",
};
static const enum gpiod_flags gpio_flags[] = {
GPIOD_IN,
GPIOD_IN,
GPIOD_IN,
GPIOD_ASIS,
GPIOD_ASIS,
};
#define T_INIT_JIFFIES msecs_to_jiffies(300)
#define T_RESET_US 10
#define T_FAULT_RECOVER msecs_to_jiffies(1000)
/* SFP module presence detection is poor: the three MOD DEF signals are
* the same length on the PCB, which means it's possible for MOD DEF 0 to
* connect before the I2C bus on MOD DEF 1/2.
*
* The SFP MSA specifies 300ms as t_init (the time taken for TX_FAULT to
* be deasserted) but makes no mention of the earliest time before we can
* access the I2C EEPROM. However, Avago modules require 300ms.
*/
#define T_PROBE_INIT msecs_to_jiffies(300)
#define T_HPOWER_LEVEL msecs_to_jiffies(300)
#define T_PROBE_RETRY msecs_to_jiffies(100)
/* SFP modules appear to always have their PHY configured for bus address
* 0x56 (which with mdio-i2c, translates to a PHY address of 22).
*/
#define SFP_PHY_ADDR 22
/* Give this long for the PHY to reset. */
#define T_PHY_RESET_MS 50
static DEFINE_MUTEX(sfp_mutex);
struct sff_data {
unsigned int gpios;
bool (*module_supported)(const struct sfp_eeprom_id *id);
};
struct sfp {
struct device *dev;
struct i2c_adapter *i2c;
struct mii_bus *i2c_mii;
struct sfp_bus *sfp_bus;
struct phy_device *mod_phy;
const struct sff_data *type;
u32 max_power_mW;
unsigned int (*get_state)(struct sfp *);
void (*set_state)(struct sfp *, unsigned int);
int (*read)(struct sfp *, bool, u8, void *, size_t);
int (*write)(struct sfp *, bool, u8, void *, size_t);
struct gpio_desc *gpio[GPIO_MAX];
unsigned int state;
struct delayed_work poll;
struct delayed_work timeout;
struct mutex sm_mutex;
unsigned char sm_mod_state;
unsigned char sm_dev_state;
unsigned short sm_state;
unsigned int sm_retries;
struct sfp_eeprom_id id;
};
static bool sff_module_supported(const struct sfp_eeprom_id *id)
{
return id->base.phys_id == SFP_PHYS_ID_SFF &&
id->base.phys_ext_id == SFP_PHYS_EXT_ID_SFP;
}
static const struct sff_data sff_data = {
.gpios = SFP_F_LOS | SFP_F_TX_FAULT | SFP_F_TX_DISABLE,
.module_supported = sff_module_supported,
};
static bool sfp_module_supported(const struct sfp_eeprom_id *id)
{
return id->base.phys_id == SFP_PHYS_ID_SFP &&
id->base.phys_ext_id == SFP_PHYS_EXT_ID_SFP;
}
static const struct sff_data sfp_data = {
.gpios = SFP_F_PRESENT | SFP_F_LOS | SFP_F_TX_FAULT |
SFP_F_TX_DISABLE | SFP_F_RATE_SELECT,
.module_supported = sfp_module_supported,
};
static const struct of_device_id sfp_of_match[] = {
{ .compatible = "sff,sff", .data = &sff_data, },
{ .compatible = "sff,sfp", .data = &sfp_data, },
{ },
};
MODULE_DEVICE_TABLE(of, sfp_of_match);
static unsigned long poll_jiffies;
static unsigned int sfp_gpio_get_state(struct sfp *sfp)
{
unsigned int i, state, v;
for (i = state = 0; i < GPIO_MAX; i++) {
if (gpio_flags[i] != GPIOD_IN || !sfp->gpio[i])
continue;
v = gpiod_get_value_cansleep(sfp->gpio[i]);
if (v)
state |= BIT(i);