-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'phylink-and-sfp-support'
Russell King says: ==================== phylink and sfp support This patch series introduces generic support for SFP sockets found on various Marvell based platforms. The idea here is to provide common SFP socket support which can be re-used by network drivers as appropriate, rather than each network driver having to re-implement SFP socket support. SFP sockets typically use other system resources, eg, I2C buses to read identifying information, and GPIOs to monitor socket state and control the socket. Meanwhile, some network drivers drive multiple ethernet ports from one instantiation of the driver. It is not desirable to block the initialisation of a network driver (thus denying other ports from being operational) if the resources for the SFP socket are not yet available. This means that an element of independence between the SFP support code and the driver is required. More than that, SFP modules effectively bring hotplug PHYs to networking - SFP copper modules normally contain a standard PHY accessed over the I2C bus, and it is desirable to read their state so network drivers can be appropriately configured. To add to the complexity, SFP modules can be connected in at least two places: 1. Directly to the serdes output of a MAC with no intervening PHY. For example: mvneta ----> SFP socket 2. To a PHY, for example: mvpp2 ---> PHY ---> copper | `-----> SFP socket This code supports both setups, although it's not fully implemented with scenario (2). Moreover, the link presented by the SFP module can be one of the 10Gbase-R family (for SFP+ sockets), SGMII or 1000base-X (for SFP sockets) depending on the module, and network drivers need to reconfigure themselves accordingly for the link to come up. For example, if the MAC is configured for SGMII and a fibre module is plugged in, the link won't come up until the MAC is reconfigured for 1000base-X mode. The SFP code manages the SFP socket - detecting the module, reading the identifying information, and managing the control and status signals. Importantly, it disables the SFP module transmitter when the MAC is down, so that the laser is turned off (but that is not a guarantee.) phylink provides the mechanisms necessary to manage the link modes, based on the SFP module type, and supports hot-plugging of the PHY without needing the MAC driver to be brought up and down on transitions. phylink also supports the classical static PHY and fixed-link modes. I currently (but not included in this series) have code to convert mvneta to use phylink, and the out of tree mvpp2x driver. I have nothing for the mvpp2 driver at present as that driver is only recently becoming functional on 10G hardware, and is missing a lot of features that are necessary to make things work correctly. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
- Loading branch information
Showing
14 changed files
with
3,867 additions
and
187 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
/* | ||
* MDIO I2C bridge | ||
* | ||
* Copyright (C) 2015-2016 Russell King | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
* | ||
* Network PHYs can appear on I2C buses when they are part of SFP module. | ||
* This driver exposes these PHYs to the networking PHY code, allowing | ||
* our PHY drivers access to these PHYs, and so allowing configuration | ||
* of their settings. | ||
*/ | ||
#include <linux/i2c.h> | ||
#include <linux/phy.h> | ||
|
||
#include "mdio-i2c.h" | ||
|
||
/* | ||
* I2C bus addresses 0x50 and 0x51 are normally an EEPROM, which is | ||
* specified to be present in SFP modules. These correspond with PHY | ||
* addresses 16 and 17. Disallow access to these "phy" addresses. | ||
*/ | ||
static bool i2c_mii_valid_phy_id(int phy_id) | ||
{ | ||
return phy_id != 0x10 && phy_id != 0x11; | ||
} | ||
|
||
static unsigned int i2c_mii_phy_addr(int phy_id) | ||
{ | ||
return phy_id + 0x40; | ||
} | ||
|
||
static int i2c_mii_read(struct mii_bus *bus, int phy_id, int reg) | ||
{ | ||
struct i2c_adapter *i2c = bus->priv; | ||
struct i2c_msg msgs[2]; | ||
u8 data[2], dev_addr = reg; | ||
int bus_addr, ret; | ||
|
||
if (!i2c_mii_valid_phy_id(phy_id)) | ||
return 0xffff; | ||
|
||
bus_addr = i2c_mii_phy_addr(phy_id); | ||
msgs[0].addr = bus_addr; | ||
msgs[0].flags = 0; | ||
msgs[0].len = 1; | ||
msgs[0].buf = &dev_addr; | ||
msgs[1].addr = bus_addr; | ||
msgs[1].flags = I2C_M_RD; | ||
msgs[1].len = sizeof(data); | ||
msgs[1].buf = data; | ||
|
||
ret = i2c_transfer(i2c, msgs, ARRAY_SIZE(msgs)); | ||
if (ret != ARRAY_SIZE(msgs)) | ||
return 0xffff; | ||
|
||
return data[0] << 8 | data[1]; | ||
} | ||
|
||
static int i2c_mii_write(struct mii_bus *bus, int phy_id, int reg, u16 val) | ||
{ | ||
struct i2c_adapter *i2c = bus->priv; | ||
struct i2c_msg msg; | ||
int ret; | ||
u8 data[3]; | ||
|
||
if (!i2c_mii_valid_phy_id(phy_id)) | ||
return 0; | ||
|
||
data[0] = reg; | ||
data[1] = val >> 8; | ||
data[2] = val; | ||
|
||
msg.addr = i2c_mii_phy_addr(phy_id); | ||
msg.flags = 0; | ||
msg.len = 3; | ||
msg.buf = data; | ||
|
||
ret = i2c_transfer(i2c, &msg, 1); | ||
|
||
return ret < 0 ? ret : 0; | ||
} | ||
|
||
struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c) | ||
{ | ||
struct mii_bus *mii; | ||
|
||
if (!i2c_check_functionality(i2c, I2C_FUNC_I2C)) | ||
return ERR_PTR(-EINVAL); | ||
|
||
mii = mdiobus_alloc(); | ||
if (!mii) | ||
return ERR_PTR(-ENOMEM); | ||
|
||
snprintf(mii->id, MII_BUS_ID_SIZE, "i2c:%s", dev_name(parent)); | ||
mii->parent = parent; | ||
mii->read = i2c_mii_read; | ||
mii->write = i2c_mii_write; | ||
mii->priv = i2c; | ||
|
||
return mii; | ||
} | ||
EXPORT_SYMBOL_GPL(mdio_i2c_alloc); | ||
|
||
MODULE_AUTHOR("Russell King"); | ||
MODULE_DESCRIPTION("MDIO I2C bridge library"); | ||
MODULE_LICENSE("GPL v2"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/* | ||
* MDIO I2C bridge | ||
* | ||
* Copyright (C) 2015 Russell King | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
*/ | ||
#ifndef MDIO_I2C_H | ||
#define MDIO_I2C_H | ||
|
||
struct device; | ||
struct i2c_adapter; | ||
struct mii_bus; | ||
|
||
struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.