[U-Boot] [PATCH v4 2/5] net: fec_mxc: add PHYLIB support

Troy Kisky troy.kisky at boundarydevices.com
Fri Feb 3 01:22:46 CET 2012


Surround non PHYLIB routines miiphy_restart_aneg
and miiphy_wait_aneg with ifndef CONFIG_PHYLIB.
When later PHYLIB is required it is easy to delete
the non-PHYLIB code. This separation idea
came from Andy Fleming.

fec_miiphy_read, and fec_miiphy_write changed to
fec_phy_read, and fec_phy_write with argument changes.

Deprecated miiphy_register is no longer used. Both
old and new PHYLIB code now use mdio_register.

Cleanup some debug prints.

Inline function fec_miiphy_fec_to_eth is no longer necessary.
Moved to the single call location.

Signed-off-by: Troy Kisky <troy.kisky at boundarydevices.com>
---
 drivers/net/fec_mxc.c |  144 ++++++++++++++++++++++++++++++++----------------
 drivers/net/fec_mxc.h |    5 ++
 2 files changed, 101 insertions(+), 48 deletions(-)

diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index 7c42b87..039e13b 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -70,34 +70,15 @@ static void swap_packet(uint32_t *packet, int length)
 #endif
 
 /*
- * The i.MX28 has two ethernet interfaces, but they are not equal.
- * Only the first one can access the MDIO bus.
- */
-#ifdef	CONFIG_MX28
-static inline struct ethernet_regs *fec_miiphy_fec_to_eth(struct fec_priv *fec)
-{
-	return (struct ethernet_regs *)MXS_ENET0_BASE;
-}
-#else
-static inline struct ethernet_regs *fec_miiphy_fec_to_eth(struct fec_priv *fec)
-{
-	return fec->eth;
-}
-#endif
-
-/*
  * MII-interface related functions
  */
-static int fec_miiphy_read(const char *dev, uint8_t phyAddr, uint8_t regAddr,
-		uint16_t *retVal)
+static int fec_mdio_read(struct ethernet_regs *eth, uint8_t phyAddr,
+		uint8_t regAddr)
 {
-	struct eth_device *edev = eth_get_dev_by_name(dev);
-	struct fec_priv *fec = (struct fec_priv *)edev->priv;
-	struct ethernet_regs *eth = fec_miiphy_fec_to_eth(fec);
-
 	uint32_t reg;		/* convenient holder for the PHY register */
 	uint32_t phy;		/* convenient holder for the PHY */
 	uint32_t start;
+	int val;
 
 	/*
 	 * reading from any PHY's register is done by properly
@@ -129,10 +110,10 @@ static int fec_miiphy_read(const char *dev, uint8_t phyAddr, uint8_t regAddr,
 	/*
 	 * it's now safe to read the PHY's register
 	 */
-	*retVal = readl(&eth->mii_data);
-	debug("fec_miiphy_read: phy: %02x reg:%02x val:%#x\n", phyAddr,
-			regAddr, *retVal);
-	return 0;
+	val = (unsigned short)readl(&eth->mii_data);
+	debug("%s: phy: %02x reg:%02x val:%#x\n", __func__, phyAddr,
+			regAddr, val);
+	return val;
 }
 
 static void fec_mii_setspeed(struct fec_priv *fec)
@@ -143,16 +124,12 @@ static void fec_mii_setspeed(struct fec_priv *fec)
 	 */
 	writel((((imx_get_fecclk() / 1000000) + 2) / 5) << 1,
 			&fec->eth->mii_speed);
-	debug("fec_init: mii_speed %08x\n",
-			readl(&fec->eth->mii_speed));
+	debug("%s: mii_speed %08x\n", __func__, readl(&fec->eth->mii_speed));
 }
-static int fec_miiphy_write(const char *dev, uint8_t phyAddr, uint8_t regAddr,
-		uint16_t data)
-{
-	struct eth_device *edev = eth_get_dev_by_name(dev);
-	struct fec_priv *fec = (struct fec_priv *)edev->priv;
-	struct ethernet_regs *eth = fec_miiphy_fec_to_eth(fec);
 
+static int fec_mdio_write(struct ethernet_regs *eth, uint8_t phyAddr,
+		uint8_t regAddr, uint16_t data)
+{
 	uint32_t reg;		/* convenient holder for the PHY register */
 	uint32_t phy;		/* convenient holder for the PHY */
 	uint32_t start;
@@ -178,15 +155,28 @@ static int fec_miiphy_write(const char *dev, uint8_t phyAddr, uint8_t regAddr,
 	 * clear MII interrupt bit
 	 */
 	writel(FEC_IEVENT_MII, &eth->ievent);
-	debug("fec_miiphy_write: phy: %02x reg:%02x val:%#x\n", phyAddr,
+	debug("%s: phy: %02x reg:%02x val:%#x\n", __func__, phyAddr,
 			regAddr, data);
 
 	return 0;
 }
 
+int fec_phy_read(struct mii_dev *bus, int phyAddr, int dev_addr, int regAddr)
+{
+	return fec_mdio_read(bus->priv, phyAddr, regAddr);
+}
+
+int fec_phy_write(struct mii_dev *bus, int phyAddr, int dev_addr, int regAddr,
+		u16 data)
+{
+	return fec_mdio_write(bus->priv, phyAddr, regAddr, data);
+}
+
+#ifndef CONFIG_PHYLIB
 static int miiphy_restart_aneg(struct eth_device *dev)
 {
 	struct fec_priv *fec = (struct fec_priv *)dev->priv;
+	struct ethernet_regs *eth = fec->bus->priv;
 	int ret = 0;
 
 	/*
@@ -194,19 +184,18 @@ static int miiphy_restart_aneg(struct eth_device *dev)
 	 * Reset PHY, then delay 300ns
 	 */
 #ifdef CONFIG_MX27
-	miiphy_write(dev->name, fec->phy_id, MII_DCOUNTER, 0x00FF);
+	fec_mdio_write(eth, fec->phy_id, MII_DCOUNTER, 0x00FF);
 #endif
-	miiphy_write(dev->name, fec->phy_id, MII_BMCR,
-			BMCR_RESET);
+	fec_mdio_write(eth, fec->phy_id, MII_BMCR, BMCR_RESET);
 	udelay(1000);
 
 	/*
 	 * Set the auto-negotiation advertisement register bits
 	 */
-	miiphy_write(dev->name, fec->phy_id, MII_ADVERTISE,
+	fec_mdio_write(eth, fec->phy_id, MII_ADVERTISE,
 			LPA_100FULL | LPA_100HALF | LPA_10FULL |
 			LPA_10HALF | PHY_ANLPAR_PSB_802_3);
-	miiphy_write(dev->name, fec->phy_id, MII_BMCR,
+	fec_mdio_write(eth, fec->phy_id, MII_BMCR,
 			BMCR_ANENABLE | BMCR_ANRESTART);
 
 	if (fec->mii_postcall)
@@ -218,8 +207,9 @@ static int miiphy_restart_aneg(struct eth_device *dev)
 static int miiphy_wait_aneg(struct eth_device *dev)
 {
 	uint32_t start;
-	uint16_t status;
+	int status;
 	struct fec_priv *fec = (struct fec_priv *)dev->priv;
+	struct ethernet_regs *eth = fec->bus->priv;
 
 	/*
 	 * Wait for AN completion
@@ -231,9 +221,9 @@ static int miiphy_wait_aneg(struct eth_device *dev)
 			return -1;
 		}
 
-		if (miiphy_read(dev->name, fec->phy_id,
-					MII_BMSR, &status)) {
-			printf("%s: Autonegotiation failed. status: 0x%04x\n",
+		status = fec_mdio_read(eth, fec->phy_id, MII_BMSR);
+		if (status < 0) {
+			printf("%s: Autonegotiation failed. status: %d\n",
 					dev->name, status);
 			return -1;
 		}
@@ -241,6 +231,8 @@ static int miiphy_wait_aneg(struct eth_device *dev)
 
 	return 0;
 }
+#endif
+
 static int fec_rx_task_enable(struct fec_priv *fec)
 {
 	writel(1 << 24, &fec->eth->r_des_active);
@@ -372,6 +364,21 @@ static int fec_set_hwaddr(struct eth_device *dev)
 	return 0;
 }
 
+static void fec_eth_phy_config(struct eth_device *dev)
+{
+#ifdef CONFIG_PHYLIB
+	struct fec_priv *fec = (struct fec_priv *)dev->priv;
+	struct phy_device *phydev;
+
+	phydev = phy_connect(fec->bus, fec->phy_id, dev,
+			PHY_INTERFACE_MODE_RGMII);
+	if (phydev) {
+		fec->phydev = phydev;
+		phy_config(phydev);
+	}
+#endif
+}
+
 /**
  * Start the FEC engine
  * @param[in] dev Our device to handle
@@ -428,9 +435,21 @@ static int fec_open(struct eth_device *edev)
 	}
 #endif
 
+#ifdef CONFIG_PHYLIB
+	if (!fec->phydev)
+		fec_eth_phy_config(edev);
+	if (fec->phydev) {
+		/* Start up the PHY */
+		phy_startup(fec->phydev);
+		speed = fec->phydev->speed;
+	} else {
+		speed = _100BASET;
+	}
+#else
 	miiphy_wait_aneg(edev);
 	speed = miiphy_speed(edev->name, fec->phy_id);
 	miiphy_duplex(edev->name, fec->phy_id);
+#endif
 
 #ifdef CONFIG_FEC_QUIRK_ENET_MAC
 	{
@@ -558,9 +577,10 @@ static int fec_init(struct eth_device *dev, bd_t* bd)
 	fec_tbd_init(fec);
 
 
+#ifndef CONFIG_PHYLIB
 	if (fec->xcv_type != SEVENWIRE)
 		miiphy_restart_aneg(dev);
-
+#endif
 	fec_open(dev);
 	return 0;
 }
@@ -762,6 +782,7 @@ static int fec_probe(bd_t *bd, int dev_id, int phy_id, uint32_t base_addr)
 {
 	struct eth_device *edev;
 	struct fec_priv *fec;
+	struct mii_dev *bus;
 	unsigned char ethaddr[6];
 	uint32_t start;
 	int ret = 0;
@@ -836,15 +857,40 @@ static int fec_probe(bd_t *bd, int dev_id, int phy_id, uint32_t base_addr)
 	}
 	fec->phy_id = phy_id;
 
-	miiphy_register(edev->name, fec_miiphy_read, fec_miiphy_write);
-
+	bus = mdio_alloc();
+	if (!bus) {
+		printf("mdio_alloc failed\n");
+		ret = -ENOMEM;
+		goto err3;
+	}
+	bus->read = fec_phy_read;
+	bus->write = fec_phy_write;
+	sprintf(bus->name, edev->name);
+#ifdef	CONFIG_MX28
+	/*
+	 * The i.MX28 has two ethernet interfaces, but they are not equal.
+	 * Only the first one can access the MDIO bus.
+	 */
+	bus->priv = (struct ethernet_regs *)MXS_ENET0_BASE;
+#else
+	bus->priv = fec->eth;
+#endif
+	ret = mdio_register(bus);
+	if (ret) {
+		printf("mdio_register failed\n");
+		free(bus);
+		ret = -ENOMEM;
+		goto err3;
+	}
+	fec->bus = bus;
 	eth_register(edev);
 
 	if (fec_get_hwaddr(edev, dev_id, ethaddr) == 0) {
 		debug("got MAC%d address from fuse: %pM\n", dev_id, ethaddr);
 		memcpy(edev->enetaddr, ethaddr, 6);
 	}
-
+	/* Configure phy */
+	fec_eth_phy_config(edev);
 	return ret;
 
 err3:
@@ -877,9 +923,11 @@ int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr)
 	return lout;
 }
 
+#ifndef CONFIG_PHYLIB
 int fecmxc_register_mii_postcall(struct eth_device *dev, int (*cb)(int))
 {
 	struct fec_priv *fec = (struct fec_priv *)dev->priv;
 	fec->mii_postcall = cb;
 	return 0;
 }
+#endif
diff --git a/drivers/net/fec_mxc.h b/drivers/net/fec_mxc.h
index af33d21..2eb7803 100644
--- a/drivers/net/fec_mxc.h
+++ b/drivers/net/fec_mxc.h
@@ -286,7 +286,12 @@ struct fec_priv {
 	void *base_ptr;
 	int dev_id;
 	int phy_id;
+	struct mii_dev *bus;
+#ifdef CONFIG_PHYLIB
+	struct phy_device *phydev;
+#else
 	int (*mii_postcall)(int);
+#endif
 };
 
 /**
-- 
1.7.5.4



More information about the U-Boot mailing list