From dc667aa725cd6900fd17ab51e03613cbe9afa566 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Wed, 24 Mar 2010 15:53:05 +0000 Subject: [PATCH] [ifxmips] add phylib support to ethernet driver git-svn-id: svn://svn.openwrt.org/openwrt/trunk@20400 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../ifxmips/patches-2.6.30/130-ethernet.patch | 123 ++++++++++++++++-- 1 file changed, 112 insertions(+), 11 deletions(-) diff --git a/target/linux/ifxmips/patches-2.6.30/130-ethernet.patch b/target/linux/ifxmips/patches-2.6.30/130-ethernet.patch index b49589dd94..30f169304e 100644 --- a/target/linux/ifxmips/patches-2.6.30/130-ethernet.patch +++ b/target/linux/ifxmips/patches-2.6.30/130-ethernet.patch @@ -29,9 +29,9 @@ Index: linux-2.6.30.8/drivers/net/Makefile Index: linux-2.6.30.8/drivers/net/ifxmips_mii0.c =================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.30.8/drivers/net/ifxmips_mii0.c 2009-10-19 21:41:10.000000000 +0200 -@@ -0,0 +1,389 @@ +--- /dev/null 2010-01-25 20:01:36.843225078 +0100 ++++ linux-2.6.30.10/drivers/net/ifxmips_mii0.c 2010-03-13 19:04:25.000000000 +0100 +@@ -0,0 +1,489 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -60,6 +60,7 @@ Index: linux-2.6.30.8/drivers/net/ifxmips_mii0.c +#include +#include +#include ++#include +#include +#include +#include @@ -79,12 +80,17 @@ Index: linux-2.6.30.8/drivers/net/ifxmips_mii0.c + struct net_device_stats stats; + struct dma_device_info *dma_device; + struct sk_buff *skb; ++ ++ struct mii_bus *mii_bus; ++ struct phy_device *phydev; ++ int oldlink, oldspeed, oldduplex; +}; + +static struct net_device *ifxmips_mii0_dev; +static unsigned char mac_addr[MAX_ADDR_LEN]; + -+void ifxmips_write_mdio(u32 phy_addr, u32 phy_reg, u16 phy_data) ++static int ifxmips_mdiobus_write(struct mii_bus *bus, int phy_addr, ++ int phy_reg, u16 phy_data) +{ + u32 val = MDIO_ACC_REQUEST | + ((phy_addr & MDIO_ACC_ADDR_MASK) << MDIO_ACC_ADDR_OFFSET) | @@ -94,10 +100,11 @@ Index: linux-2.6.30.8/drivers/net/ifxmips_mii0.c + while (ifxmips_r32(IFXMIPS_PPE32_MDIO_ACC) & MDIO_ACC_REQUEST) + ; + ifxmips_w32(val, IFXMIPS_PPE32_MDIO_ACC); -+} -+EXPORT_SYMBOL(ifxmips_write_mdio); + -+unsigned short ifxmips_read_mdio(u32 phy_addr, u32 phy_reg) ++ return 0; ++} ++ ++static int ifxmips_mdiobus_read(struct mii_bus *bus, int phy_addr, int phy_reg) +{ + u32 val = MDIO_ACC_REQUEST | MDIO_ACC_READ | + ((phy_addr & MDIO_ACC_ADDR_MASK) << MDIO_ACC_ADDR_OFFSET) | @@ -111,7 +118,6 @@ Index: linux-2.6.30.8/drivers/net/ifxmips_mii0.c + val = ifxmips_r32(IFXMIPS_PPE32_MDIO_ACC) & MDIO_ACC_VAL_MASK; + return val; +} -+EXPORT_SYMBOL(ifxmips_read_mdio); + +int ifxmips_ifxmips_mii_open(struct net_device *dev) +{ @@ -300,12 +306,91 @@ Index: linux-2.6.30.8/drivers/net/ifxmips_mii0.c + return &((struct ifxmips_mii_priv *)netdev_priv(dev))->stats; +} + ++static void ++ifxmips_adjust_link(struct net_device *dev) ++{ ++ struct ifxmips_mii_priv *priv = netdev_priv(dev); ++ struct phy_device *phydev = priv->phydev; ++ int new_state = 0; ++ ++ /* Did anything change? */ ++ if (priv->oldlink != phydev->link || ++ priv->oldduplex != phydev->duplex || ++ priv->oldspeed != phydev->speed) { ++ /* Yes, so update status and mark as changed */ ++ new_state = 1; ++ priv->oldduplex = phydev->duplex; ++ priv->oldspeed = phydev->speed; ++ priv->oldlink = phydev->link; ++ } ++ ++ /* If link status changed, show new status */ ++ if (new_state) ++ phy_print_status(phydev); ++} ++ ++static int mii_probe(struct net_device *dev) ++{ ++ struct ifxmips_mii_priv *priv = netdev_priv(dev); ++ struct phy_device *phydev = NULL; ++ int phy_addr; ++ ++ priv->oldlink = 0; ++ priv->oldspeed = 0; ++ priv->oldduplex = -1; ++ ++ /* find the first (lowest address) PHY on the current MAC's MII bus */ ++ for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { ++ if (priv->mii_bus->phy_map[phy_addr]) { ++ phydev = priv->mii_bus->phy_map[phy_addr]; ++ break; /* break out with first one found */ ++ } ++ } ++ ++ if (!phydev) { ++ printk (KERN_ERR "%s: no PHY found\n", dev->name); ++ return -ENODEV; ++ } ++ ++ /* now we are supposed to have a proper phydev, to attach to... */ ++ BUG_ON(!phydev); ++ BUG_ON(phydev->attached_dev); ++ ++ phydev = phy_connect(dev, dev_name(&phydev->dev), &ifxmips_adjust_link, ++ 0, PHY_INTERFACE_MODE_MII); ++ ++ if (IS_ERR(phydev)) { ++ printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); ++ return PTR_ERR(phydev); ++ } ++ ++ /* mask with MAC supported features */ ++ phydev->supported &= (SUPPORTED_10baseT_Half ++ | SUPPORTED_10baseT_Full ++ | SUPPORTED_100baseT_Half ++ | SUPPORTED_100baseT_Full ++ | SUPPORTED_Autoneg ++ /* | SUPPORTED_Pause | SUPPORTED_Asym_Pause */ ++ | SUPPORTED_MII ++ | SUPPORTED_TP); ++ ++ phydev->advertising = phydev->supported; ++ ++ priv->phydev = phydev; ++ ++ printk(KERN_INFO "%s: attached PHY driver [%s] " ++ "(mii_bus:phy_addr=%s, irq=%d)\n", ++ dev->name, phydev->drv->name, dev_name(&phydev->dev), phydev->irq); ++ ++ return 0; ++} ++ ++ +static int ifxmips_mii_dev_init(struct net_device *dev) +{ + int i; + struct ifxmips_mii_priv *priv = (struct ifxmips_mii_priv *)netdev_priv(dev); + ether_setup(dev); -+ printk(KERN_INFO "ifxmips_mii0: %s is up\n", dev->name); + dev->open = ifxmips_ifxmips_mii_open; + dev->stop = ifxmips_mii_release; + dev->hard_start_xmit = ifxmips_mii_tx; @@ -336,12 +421,28 @@ Index: linux-2.6.30.8/drivers/net/ifxmips_mii0.c + + dma_device_register(priv->dma_device); + -+ printk(KERN_INFO "ifxmips_mii0: using mac="); ++ printk(KERN_INFO "%s: using mac=", dev->name); + for (i = 0; i < 6; i++) { + dev->dev_addr[i] = mac_addr[i]; + printk("%02X%c", dev->dev_addr[i], (i == 5) ? ('\n') : (':')); + } -+ return 0; ++ ++ priv->mii_bus = mdiobus_alloc(); ++ if (priv->mii_bus == NULL) ++ return -ENOMEM; ++ ++ priv->mii_bus->priv = dev; ++ priv->mii_bus->read = ifxmips_mdiobus_read; ++ priv->mii_bus->write = ifxmips_mdiobus_write; ++ priv->mii_bus->name = "ifxmips_mii"; ++ snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%x", 0); ++ priv->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); ++ for(i = 0; i < PHY_MAX_ADDR; ++i) ++ priv->mii_bus->irq[i] = PHY_POLL; ++ ++ mdiobus_register(priv->mii_bus); ++ ++ return mii_probe(dev); +} + +static void ifxmips_mii_chip_init(int mode)