Commit 23c3320c authored by Ben Hutchings's avatar Ben Hutchings Committed by David S. Miller

chelsio: Use generic MDIO definitions and mdio_mii_ioctl()

Compile-tested only.
Signed-off-by: default avatarBen Hutchings <bhutchings@solarflare.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 68e7f45e
......@@ -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,
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,
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);
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;
struct mdio_if_info *mdio = &adapter->port[dev->if_port].phy->mdio;
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) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment