mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 17:30:02 +00:00
chelsio: Use generic MDIO definitions and mdio_mii_ioctl()
Compile-tested only. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
68e7f45e11
commit
23c3320cb0
7 changed files with 82 additions and 100 deletions
|
@ -2450,6 +2450,7 @@ config CHELSIO_T1
|
|||
tristate "Chelsio 10Gb Ethernet support"
|
||||
depends on PCI
|
||||
select CRC32
|
||||
select MDIO
|
||||
help
|
||||
This driver supports Chelsio gigabit and 10-gigabit
|
||||
Ethernet cards. More information about adapter features and
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/mdio.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/io.h>
|
||||
|
|
|
@ -43,10 +43,11 @@
|
|||
|
||||
struct mdio_ops {
|
||||
void (*init)(adapter_t *adapter, const struct board_info *bi);
|
||||
int (*read)(adapter_t *adapter, int phy_addr, int mmd_addr,
|
||||
int reg_addr, unsigned int *val);
|
||||
int (*write)(adapter_t *adapter, int phy_addr, int mmd_addr,
|
||||
int reg_addr, unsigned int val);
|
||||
int (*read)(struct net_device *dev, int phy_addr, int mmd_addr,
|
||||
u16 reg_addr);
|
||||
int (*write)(struct net_device *dev, int phy_addr, int mmd_addr,
|
||||
u16 reg_addr, u16 val);
|
||||
unsigned mode_support;
|
||||
};
|
||||
|
||||
/* PHY interrupt types */
|
||||
|
@ -83,11 +84,12 @@ struct cphy_ops {
|
|||
int (*set_speed_duplex)(struct cphy *phy, int speed, int duplex);
|
||||
int (*get_link_status)(struct cphy *phy, int *link_ok, int *speed,
|
||||
int *duplex, int *fc);
|
||||
|
||||
u32 mmds;
|
||||
};
|
||||
|
||||
/* A PHY instance */
|
||||
struct cphy {
|
||||
int addr; /* PHY address */
|
||||
int state; /* Link status state machine */
|
||||
adapter_t *adapter; /* associated adapter */
|
||||
|
||||
|
@ -101,36 +103,37 @@ struct cphy {
|
|||
u32 elmer_gpo;
|
||||
|
||||
const struct cphy_ops *ops; /* PHY operations */
|
||||
int (*mdio_read)(adapter_t *adapter, int phy_addr, int mmd_addr,
|
||||
int reg_addr, unsigned int *val);
|
||||
int (*mdio_write)(adapter_t *adapter, int phy_addr, int mmd_addr,
|
||||
int reg_addr, unsigned int val);
|
||||
struct mdio_if_info mdio;
|
||||
struct cphy_instance *instance;
|
||||
};
|
||||
|
||||
/* Convenience MDIO read/write wrappers */
|
||||
static inline int mdio_read(struct cphy *cphy, int mmd, int reg,
|
||||
unsigned int *valp)
|
||||
static inline int cphy_mdio_read(struct cphy *cphy, int mmd, int reg,
|
||||
unsigned int *valp)
|
||||
{
|
||||
return cphy->mdio_read(cphy->adapter, cphy->addr, mmd, reg, valp);
|
||||
int rc = cphy->mdio.mdio_read(cphy->mdio.dev, cphy->mdio.prtad, mmd,
|
||||
reg);
|
||||
*valp = (rc >= 0) ? rc : -1;
|
||||
return (rc >= 0) ? 0 : rc;
|
||||
}
|
||||
|
||||
static inline int mdio_write(struct cphy *cphy, int mmd, int reg,
|
||||
unsigned int val)
|
||||
static inline int cphy_mdio_write(struct cphy *cphy, int mmd, int reg,
|
||||
unsigned int val)
|
||||
{
|
||||
return cphy->mdio_write(cphy->adapter, cphy->addr, mmd, reg, val);
|
||||
return cphy->mdio.mdio_write(cphy->mdio.dev, cphy->mdio.prtad, mmd,
|
||||
reg, val);
|
||||
}
|
||||
|
||||
static inline int simple_mdio_read(struct cphy *cphy, int reg,
|
||||
unsigned int *valp)
|
||||
{
|
||||
return mdio_read(cphy, 0, reg, valp);
|
||||
return cphy_mdio_read(cphy, MDIO_DEVAD_NONE, reg, valp);
|
||||
}
|
||||
|
||||
static inline int simple_mdio_write(struct cphy *cphy, int reg,
|
||||
unsigned int val)
|
||||
{
|
||||
return mdio_write(cphy, 0, reg, val);
|
||||
return cphy_mdio_write(cphy, MDIO_DEVAD_NONE, reg, val);
|
||||
}
|
||||
|
||||
/* Convenience initializer */
|
||||
|
@ -139,11 +142,13 @@ static inline void cphy_init(struct cphy *phy, adapter_t *adapter,
|
|||
const struct mdio_ops *mdio_ops)
|
||||
{
|
||||
phy->adapter = adapter;
|
||||
phy->addr = phy_addr;
|
||||
phy->ops = phy_ops;
|
||||
if (mdio_ops) {
|
||||
phy->mdio_read = mdio_ops->read;
|
||||
phy->mdio_write = mdio_ops->write;
|
||||
phy->mdio.prtad = phy_addr;
|
||||
phy->mdio.mmds = phy_ops->mmds;
|
||||
phy->mdio.mode_support = mdio_ops->mode_support;
|
||||
phy->mdio.mdio_read = mdio_ops->read;
|
||||
phy->mdio.mdio_write = mdio_ops->write;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -589,7 +589,7 @@ static int get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
|
|||
}
|
||||
|
||||
cmd->port = (cmd->supported & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE;
|
||||
cmd->phy_address = p->phy->addr;
|
||||
cmd->phy_address = p->phy->mdio.prtad;
|
||||
cmd->transceiver = XCVR_EXTERNAL;
|
||||
cmd->autoneg = p->link_config.autoneg;
|
||||
cmd->maxtxpkt = 0;
|
||||
|
@ -849,39 +849,9 @@ static const struct ethtool_ops t1_ethtool_ops = {
|
|||
static int t1_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
|
||||
{
|
||||
struct adapter *adapter = dev->ml_priv;
|
||||
struct mii_ioctl_data *data = if_mii(req);
|
||||
struct mdio_if_info *mdio = &adapter->port[dev->if_port].phy->mdio;
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCGMIIPHY:
|
||||
data->phy_id = adapter->port[dev->if_port].phy->addr;
|
||||
/* FALLTHRU */
|
||||
case SIOCGMIIREG: {
|
||||
struct cphy *phy = adapter->port[dev->if_port].phy;
|
||||
u32 val;
|
||||
|
||||
if (!phy->mdio_read)
|
||||
return -EOPNOTSUPP;
|
||||
phy->mdio_read(adapter, data->phy_id, 0, data->reg_num & 0x1f,
|
||||
&val);
|
||||
data->val_out = val;
|
||||
break;
|
||||
}
|
||||
case SIOCSMIIREG: {
|
||||
struct cphy *phy = adapter->port[dev->if_port].phy;
|
||||
|
||||
if (!capable(CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
if (!phy->mdio_write)
|
||||
return -EOPNOTSUPP;
|
||||
phy->mdio_write(adapter, data->phy_id, 0, data->reg_num & 0x1f,
|
||||
data->val_in);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
return 0;
|
||||
return mdio_mii_ioctl(mdio, if_mii(req), cmd);
|
||||
}
|
||||
|
||||
static int t1_change_mtu(struct net_device *dev, int new_mtu)
|
||||
|
|
|
@ -53,7 +53,7 @@ static int led_init(struct cphy *cphy)
|
|||
* Writing these bits maps control to another
|
||||
* register. mmd(0x1) addr(0x7)
|
||||
*/
|
||||
mdio_write(cphy, 0x3, 0x8304, 0xdddd);
|
||||
cphy_mdio_write(cphy, MDIO_MMD_PCS, 0x8304, 0xdddd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -62,14 +62,14 @@ static int led_link(struct cphy *cphy, u32 do_enable)
|
|||
u32 led = 0;
|
||||
#define LINK_ENABLE_BIT 0x1
|
||||
|
||||
mdio_read(cphy, 0x1, 0x7, &led);
|
||||
cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_CTRL2, &led);
|
||||
|
||||
if (do_enable & LINK_ENABLE_BIT) {
|
||||
led |= LINK_ENABLE_BIT;
|
||||
mdio_write(cphy, 0x1, 0x7, led);
|
||||
cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, MDIO_CTRL2, led);
|
||||
} else {
|
||||
led &= ~LINK_ENABLE_BIT;
|
||||
mdio_write(cphy, 0x1, 0x7, led);
|
||||
cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, MDIO_CTRL2, led);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ static int mv88x201x_reset(struct cphy *cphy, int wait)
|
|||
static int mv88x201x_interrupt_enable(struct cphy *cphy)
|
||||
{
|
||||
/* Enable PHY LASI interrupts. */
|
||||
mdio_write(cphy, 0x1, 0x9002, 0x1);
|
||||
cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, 0x9002, 0x1);
|
||||
|
||||
/* Enable Marvell interrupts through Elmer0. */
|
||||
if (t1_is_asic(cphy->adapter)) {
|
||||
|
@ -102,7 +102,7 @@ static int mv88x201x_interrupt_enable(struct cphy *cphy)
|
|||
static int mv88x201x_interrupt_disable(struct cphy *cphy)
|
||||
{
|
||||
/* Disable PHY LASI interrupts. */
|
||||
mdio_write(cphy, 0x1, 0x9002, 0x0);
|
||||
cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, 0x9002, 0x0);
|
||||
|
||||
/* Disable Marvell interrupts through Elmer0. */
|
||||
if (t1_is_asic(cphy->adapter)) {
|
||||
|
@ -122,25 +122,25 @@ static int mv88x201x_interrupt_clear(struct cphy *cphy)
|
|||
|
||||
#ifdef MV88x2010_LINK_STATUS_BUGS
|
||||
/* Required to read twice before clear takes affect. */
|
||||
mdio_read(cphy, 0x1, 0x9003, &val);
|
||||
mdio_read(cphy, 0x1, 0x9004, &val);
|
||||
mdio_read(cphy, 0x1, 0x9005, &val);
|
||||
cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, 0x9003, &val);
|
||||
cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, 0x9004, &val);
|
||||
cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, 0x9005, &val);
|
||||
|
||||
/* Read this register after the others above it else
|
||||
* the register doesn't clear correctly.
|
||||
*/
|
||||
mdio_read(cphy, 0x1, 0x1, &val);
|
||||
cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val);
|
||||
#endif
|
||||
|
||||
/* Clear link status. */
|
||||
mdio_read(cphy, 0x1, 0x1, &val);
|
||||
cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val);
|
||||
/* Clear PHY LASI interrupts. */
|
||||
mdio_read(cphy, 0x1, 0x9005, &val);
|
||||
cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, 0x9005, &val);
|
||||
|
||||
#ifdef MV88x2010_LINK_STATUS_BUGS
|
||||
/* Do it again. */
|
||||
mdio_read(cphy, 0x1, 0x9003, &val);
|
||||
mdio_read(cphy, 0x1, 0x9004, &val);
|
||||
cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, 0x9003, &val);
|
||||
cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, 0x9004, &val);
|
||||
#endif
|
||||
|
||||
/* Clear Marvell interrupts through Elmer0. */
|
||||
|
@ -172,13 +172,12 @@ static int mv88x201x_get_link_status(struct cphy *cphy, int *link_ok,
|
|||
int *speed, int *duplex, int *fc)
|
||||
{
|
||||
u32 val = 0;
|
||||
#define LINK_STATUS_BIT 0x4
|
||||
|
||||
if (link_ok) {
|
||||
/* Read link status. */
|
||||
mdio_read(cphy, 0x1, 0x1, &val);
|
||||
val &= LINK_STATUS_BIT;
|
||||
*link_ok = (val == LINK_STATUS_BIT);
|
||||
cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val);
|
||||
val &= MDIO_STAT1_LSTATUS;
|
||||
*link_ok = (val == MDIO_STAT1_LSTATUS);
|
||||
/* Turn on/off Link LED */
|
||||
led_link(cphy, *link_ok);
|
||||
}
|
||||
|
@ -205,6 +204,8 @@ static struct cphy_ops mv88x201x_ops = {
|
|||
.interrupt_handler = mv88x201x_interrupt_handler,
|
||||
.get_link_status = mv88x201x_get_link_status,
|
||||
.set_loopback = mv88x201x_set_loopback,
|
||||
.mmds = (MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS |
|
||||
MDIO_DEVS_PHYXS | MDIO_DEVS_WIS),
|
||||
};
|
||||
|
||||
static struct cphy *mv88x201x_phy_create(adapter_t *adapter, int phy_addr,
|
||||
|
@ -219,12 +220,12 @@ static struct cphy *mv88x201x_phy_create(adapter_t *adapter, int phy_addr,
|
|||
cphy_init(cphy, adapter, phy_addr, &mv88x201x_ops, mdio_ops);
|
||||
|
||||
/* Commands the PHY to enable XFP's clock. */
|
||||
mdio_read(cphy, 0x3, 0x8300, &val);
|
||||
mdio_write(cphy, 0x3, 0x8300, val | 1);
|
||||
cphy_mdio_read(cphy, MDIO_MMD_PCS, 0x8300, &val);
|
||||
cphy_mdio_write(cphy, MDIO_MMD_PCS, 0x8300, val | 1);
|
||||
|
||||
/* Clear link status. Required because of a bug in the PHY. */
|
||||
mdio_read(cphy, 0x1, 0x8, &val);
|
||||
mdio_read(cphy, 0x3, 0x8, &val);
|
||||
cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT2, &val);
|
||||
cphy_mdio_read(cphy, MDIO_MMD_PCS, MDIO_STAT2, &val);
|
||||
|
||||
/* Allows for Link,Ack LED turn on/off */
|
||||
led_init(cphy);
|
||||
|
|
|
@ -43,11 +43,11 @@ static int my3126_interrupt_handler(struct cphy *cphy)
|
|||
adapter = cphy->adapter;
|
||||
|
||||
if (cphy->count == 50) {
|
||||
mdio_read(cphy, 0x1, 0x1, &val);
|
||||
cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val);
|
||||
val16 = (u16) val;
|
||||
status = cphy->bmsr ^ val16;
|
||||
|
||||
if (status & BMSR_LSTATUS)
|
||||
if (status & MDIO_STAT1_LSTATUS)
|
||||
t1_link_changed(adapter, 0);
|
||||
cphy->bmsr = val16;
|
||||
|
||||
|
@ -114,14 +114,14 @@ static int my3126_get_link_status(struct cphy *cphy,
|
|||
adapter_t *adapter;
|
||||
|
||||
adapter = cphy->adapter;
|
||||
mdio_read(cphy, 0x1, 0x1, &val);
|
||||
cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val);
|
||||
val16 = (u16) val;
|
||||
|
||||
/* Populate elmer_gpo with the register value */
|
||||
t1_tpi_read(adapter, A_ELMER0_GPO, &val);
|
||||
cphy->elmer_gpo = val;
|
||||
|
||||
*link_ok = (val16 & BMSR_LSTATUS);
|
||||
*link_ok = (val16 & MDIO_STAT1_LSTATUS);
|
||||
|
||||
if (*link_ok) {
|
||||
/* Turn on the LED. */
|
||||
|
@ -163,6 +163,8 @@ static struct cphy_ops my3126_ops = {
|
|||
.interrupt_handler = my3126_interrupt_handler,
|
||||
.get_link_status = my3126_get_link_status,
|
||||
.set_loopback = my3126_set_loopback,
|
||||
.mmds = (MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS |
|
||||
MDIO_DEVS_PHYXS),
|
||||
};
|
||||
|
||||
static struct cphy *my3126_phy_create(adapter_t *adapter,
|
||||
|
|
|
@ -284,32 +284,29 @@ static void mi1_mdio_init(adapter_t *adapter, const struct board_info *bi)
|
|||
/*
|
||||
* Elmer MI1 MDIO read/write operations.
|
||||
*/
|
||||
static int mi1_mdio_read(adapter_t *adapter, int phy_addr, int mmd_addr,
|
||||
int reg_addr, unsigned int *valp)
|
||||
static int mi1_mdio_read(struct net_device *dev, int phy_addr, int mmd_addr,
|
||||
u16 reg_addr)
|
||||
{
|
||||
struct adapter *adapter = dev->ml_priv;
|
||||
u32 addr = V_MI1_REG_ADDR(reg_addr) | V_MI1_PHY_ADDR(phy_addr);
|
||||
|
||||
if (mmd_addr)
|
||||
return -EINVAL;
|
||||
unsigned int val;
|
||||
|
||||
spin_lock(&adapter->tpi_lock);
|
||||
__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
|
||||
__t1_tpi_write(adapter,
|
||||
A_ELMER0_PORT0_MI1_OP, MI1_OP_DIRECT_READ);
|
||||
mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
|
||||
__t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, valp);
|
||||
__t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, &val);
|
||||
spin_unlock(&adapter->tpi_lock);
|
||||
return 0;
|
||||
return val;
|
||||
}
|
||||
|
||||
static int mi1_mdio_write(adapter_t *adapter, int phy_addr, int mmd_addr,
|
||||
int reg_addr, unsigned int val)
|
||||
static int mi1_mdio_write(struct net_device *dev, int phy_addr, int mmd_addr,
|
||||
u16 reg_addr, u16 val)
|
||||
{
|
||||
struct adapter *adapter = dev->ml_priv;
|
||||
u32 addr = V_MI1_REG_ADDR(reg_addr) | V_MI1_PHY_ADDR(phy_addr);
|
||||
|
||||
if (mmd_addr)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock(&adapter->tpi_lock);
|
||||
__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
|
||||
__t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, val);
|
||||
|
@ -324,16 +321,19 @@ static int mi1_mdio_write(adapter_t *adapter, int phy_addr, int mmd_addr,
|
|||
static const struct mdio_ops mi1_mdio_ops = {
|
||||
.init = mi1_mdio_init,
|
||||
.read = mi1_mdio_read,
|
||||
.write = mi1_mdio_write
|
||||
.write = mi1_mdio_write,
|
||||
.mode_support = MDIO_SUPPORTS_C22
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
static int mi1_mdio_ext_read(adapter_t *adapter, int phy_addr, int mmd_addr,
|
||||
int reg_addr, unsigned int *valp)
|
||||
static int mi1_mdio_ext_read(struct net_device *dev, int phy_addr, int mmd_addr,
|
||||
u16 reg_addr)
|
||||
{
|
||||
struct adapter *adapter = dev->ml_priv;
|
||||
u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr);
|
||||
unsigned int val;
|
||||
|
||||
spin_lock(&adapter->tpi_lock);
|
||||
|
||||
|
@ -350,14 +350,15 @@ static int mi1_mdio_ext_read(adapter_t *adapter, int phy_addr, int mmd_addr,
|
|||
mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
|
||||
|
||||
/* Read the data. */
|
||||
__t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, valp);
|
||||
__t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, &val);
|
||||
spin_unlock(&adapter->tpi_lock);
|
||||
return 0;
|
||||
return val;
|
||||
}
|
||||
|
||||
static int mi1_mdio_ext_write(adapter_t *adapter, int phy_addr, int mmd_addr,
|
||||
int reg_addr, unsigned int val)
|
||||
static int mi1_mdio_ext_write(struct net_device *dev, int phy_addr,
|
||||
int mmd_addr, u16 reg_addr, u16 val)
|
||||
{
|
||||
struct adapter *adapter = dev->ml_priv;
|
||||
u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr);
|
||||
|
||||
spin_lock(&adapter->tpi_lock);
|
||||
|
@ -380,7 +381,8 @@ static int mi1_mdio_ext_write(adapter_t *adapter, int phy_addr, int mmd_addr,
|
|||
static const struct mdio_ops mi1_mdio_ext_ops = {
|
||||
.init = mi1_mdio_init,
|
||||
.read = mi1_mdio_ext_read,
|
||||
.write = mi1_mdio_ext_write
|
||||
.write = mi1_mdio_ext_write,
|
||||
.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -1140,6 +1142,7 @@ int __devinit t1_init_sw_modules(adapter_t *adapter,
|
|||
adapter->name, i);
|
||||
goto error;
|
||||
}
|
||||
adapter->port[i].phy->mdio.dev = adapter->port[i].dev;
|
||||
|
||||
adapter->port[i].mac = mac = bi->gmac->create(adapter, i);
|
||||
if (!mac) {
|
||||
|
|
Loading…
Reference in a new issue