123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- From 3cb0bde365d913c484d20224367a54a0eac780a7 Mon Sep 17 00:00:00 2001
- From: Antoine Tenart <[email protected]>
- Date: Fri, 21 Feb 2020 11:55:29 +0100
- Subject: [PATCH 3/3] net: phy: sfp: add support for SMBus
- Signed-off-by: Antoine Tenart <[email protected]>
- ---
- drivers/net/phy/sfp.c | 68 ++++++++++++++++++++++++++++++++++---------
- 1 file changed, 54 insertions(+), 14 deletions(-)
- --- a/drivers/net/phy/sfp.c
- +++ b/drivers/net/phy/sfp.c
- @@ -556,32 +556,72 @@ static int sfp_i2c_write(struct sfp *sfp
- return ret == ARRAY_SIZE(msgs) ? len : 0;
- }
-
- +static int sfp_smbus_read(struct sfp *sfp, bool a2, u8 dev_addr, void *buf,
- + size_t len)
- +{
- + u8 bus_addr = a2 ? 0x51 : 0x50, *val = buf;
- +
- + bus_addr -= 0x40;
- +
- + while (len > 0) {
- + *val = sfp->i2c_mii->read(sfp->i2c_mii, bus_addr, dev_addr);
- +
- + val++;
- + dev_addr++;
- + len--;
- + }
- +
- + return val - (u8 *)buf;
- +}
- +
- +static int sfp_smbus_write(struct sfp *sfp, bool a2, u8 dev_addr, void *buf,
- + size_t len)
- +{
- + u8 bus_addr = a2 ? 0x51 : 0x50;
- + u16 val;
- +
- + memcpy(&val, buf, len);
- +
- + return sfp->i2c_mii->write(sfp->i2c_mii, bus_addr, dev_addr, val);
- +}
- +
- static int sfp_i2c_configure(struct sfp *sfp, struct i2c_adapter *i2c)
- {
- - struct mii_bus *i2c_mii;
- + struct mii_bus *mii;
- int ret;
-
- - if (!i2c_check_functionality(i2c, I2C_FUNC_I2C))
- - return -EINVAL;
- -
- sfp->i2c = i2c;
- - sfp->read = sfp_i2c_read;
- - sfp->write = sfp_i2c_write;
-
- - i2c_mii = mdio_i2c_alloc(sfp->dev, i2c);
- - if (IS_ERR(i2c_mii))
- - return PTR_ERR(i2c_mii);
- + if (i2c_check_functionality(i2c, I2C_FUNC_I2C)) {
- + sfp->read = sfp_i2c_read;
- + sfp->write = sfp_i2c_write;
- +
- + mii = mdio_i2c_alloc(sfp->dev, i2c);
- + if (IS_ERR(mii))
- + return PTR_ERR(mii);
- +
- + mii->name = "SFP I2C Bus";
- + } else if (i2c_check_functionality(i2c, I2C_FUNC_SMBUS_BYTE_DATA)) {
- + sfp->read = sfp_smbus_read;
- + sfp->write = sfp_smbus_write;
- +
- + mii = mdio_smbus_alloc(sfp->dev, i2c);
- + if (IS_ERR(mii))
- + return PTR_ERR(mii);
-
- - i2c_mii->name = "SFP I2C Bus";
- - i2c_mii->phy_mask = ~0;
- + mii->name = "SFP SMBus";
- + } else {
- + return -EINVAL;
- + }
-
- - ret = mdiobus_register(i2c_mii);
- + mii->phy_mask = ~0;
- + ret = mdiobus_register(mii);
- if (ret < 0) {
- - mdiobus_free(i2c_mii);
- + mdiobus_free(mii);
- return ret;
- }
-
- - sfp->i2c_mii = i2c_mii;
- + sfp->i2c_mii = mii;
-
- return 0;
- }
|