Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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
+1 −1
Original line number Diff line number Diff line
@@ -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>
+25 −20
Original line number Diff line number Diff line
@@ -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;
	}
}

+3 −33
Original line number Diff line number Diff line
@@ -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)
+23 −22
Original line number Diff line number Diff line
@@ -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);
Loading