From 0ae049b500c1105e19ae0685f32877e295b17b79 Mon Sep 17 00:00:00 2001 From: juhosg Date: Wed, 29 Apr 2009 20:31:27 +0000 Subject: [PATCH] [ixp4xx] experimental multiphy support for 2.6.29 git-svn-id: svn://svn.openwrt.org/openwrt/trunk@15491 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- ...t.patch => 202-npe_driver_ixp43x_support.patch} | 0 .../202-npe_driver_switch_support.patch | 20 --- .../203-npe_driver_mask_phy_features.patch | 13 ++ ...204-npe_driver_add_missing_phy_disconnect.patch | 10 ++ .../205-npe_driver_separate_phy_functions.patch | 118 ++++++++++++++++ .../206-npe_driver_add_update_link_function.patch | 98 +++++++++++++ .../207-npe_driver_multiphy_support.patch | 155 +++++++++++++++++++++ 7 files changed, 394 insertions(+), 20 deletions(-) rename target/linux/ixp4xx/patches-2.6.29/{204-npe_driver_ixp43x_support.patch => 202-npe_driver_ixp43x_support.patch} (100%) delete mode 100644 target/linux/ixp4xx/patches-2.6.29/202-npe_driver_switch_support.patch create mode 100644 target/linux/ixp4xx/patches-2.6.29/203-npe_driver_mask_phy_features.patch create mode 100644 target/linux/ixp4xx/patches-2.6.29/204-npe_driver_add_missing_phy_disconnect.patch create mode 100644 target/linux/ixp4xx/patches-2.6.29/205-npe_driver_separate_phy_functions.patch create mode 100644 target/linux/ixp4xx/patches-2.6.29/206-npe_driver_add_update_link_function.patch create mode 100644 target/linux/ixp4xx/patches-2.6.29/207-npe_driver_multiphy_support.patch diff --git a/target/linux/ixp4xx/patches-2.6.29/204-npe_driver_ixp43x_support.patch b/target/linux/ixp4xx/patches-2.6.29/202-npe_driver_ixp43x_support.patch similarity index 100% rename from target/linux/ixp4xx/patches-2.6.29/204-npe_driver_ixp43x_support.patch rename to target/linux/ixp4xx/patches-2.6.29/202-npe_driver_ixp43x_support.patch diff --git a/target/linux/ixp4xx/patches-2.6.29/202-npe_driver_switch_support.patch b/target/linux/ixp4xx/patches-2.6.29/202-npe_driver_switch_support.patch deleted file mode 100644 index ba1efd8430..0000000000 --- a/target/linux/ixp4xx/patches-2.6.29/202-npe_driver_switch_support.patch +++ /dev/null @@ -1,20 +0,0 @@ -TODO: take care of additional PHYs through the PHY abstraction layer - ---- a/arch/arm/mach-ixp4xx/include/mach/platform.h -+++ b/arch/arm/mach-ixp4xx/include/mach/platform.h -@@ -95,12 +95,15 @@ struct sys_timer; - #define IXP4XX_ETH_NPEB 0x10 - #define IXP4XX_ETH_NPEC 0x20 - -+#define IXP4XX_ETH_PHY_MAX_ADDR 32 -+ - /* Information about built-in Ethernet MAC interfaces */ - struct eth_plat_info { - u8 phy; /* MII PHY ID, 0 - 31 */ - u8 rxq; /* configurable, currently 0 - 31 only */ - u8 txreadyq; - u8 hwaddr[6]; -+ u32 phy_mask; - }; - - /* Information about built-in HSS (synchronous serial) interfaces */ diff --git a/target/linux/ixp4xx/patches-2.6.29/203-npe_driver_mask_phy_features.patch b/target/linux/ixp4xx/patches-2.6.29/203-npe_driver_mask_phy_features.patch new file mode 100644 index 0000000000..0e8729ac20 --- /dev/null +++ b/target/linux/ixp4xx/patches-2.6.29/203-npe_driver_mask_phy_features.patch @@ -0,0 +1,13 @@ +--- a/drivers/net/arm/ixp4xx_eth.c ++++ b/drivers/net/arm/ixp4xx_eth.c +@@ -1218,6 +1218,10 @@ static int __devinit eth_init_one(struct + return PTR_ERR(port->phydev); + } + ++ /* mask with MAC supported features */ ++ port->phydev->supported &= PHY_BASIC_FEATURES; ++ port->phydev->advertising = port->phydev->supported; ++ + port->phydev->irq = PHY_POLL; + + printk(KERN_INFO "%s: MII PHY %i on %s\n", dev->name, plat->phy, diff --git a/target/linux/ixp4xx/patches-2.6.29/204-npe_driver_add_missing_phy_disconnect.patch b/target/linux/ixp4xx/patches-2.6.29/204-npe_driver_add_missing_phy_disconnect.patch new file mode 100644 index 0000000000..eb9cf869a2 --- /dev/null +++ b/target/linux/ixp4xx/patches-2.6.29/204-npe_driver_add_missing_phy_disconnect.patch @@ -0,0 +1,10 @@ +--- a/drivers/net/arm/ixp4xx_eth.c ++++ b/drivers/net/arm/ixp4xx_eth.c +@@ -1243,6 +1243,7 @@ static int __devexit eth_remove_one(stru + struct net_device *dev = platform_get_drvdata(pdev); + struct port *port = netdev_priv(dev); + ++ phy_disconnect(port->phydev); + unregister_netdev(dev); + npe_port_tab[NPE_ID(port->id)] = NULL; + platform_set_drvdata(pdev, NULL); diff --git a/target/linux/ixp4xx/patches-2.6.29/205-npe_driver_separate_phy_functions.patch b/target/linux/ixp4xx/patches-2.6.29/205-npe_driver_separate_phy_functions.patch new file mode 100644 index 0000000000..d3e6314a9d --- /dev/null +++ b/target/linux/ixp4xx/patches-2.6.29/205-npe_driver_separate_phy_functions.patch @@ -0,0 +1,118 @@ +--- a/drivers/net/arm/ixp4xx_eth.c ++++ b/drivers/net/arm/ixp4xx_eth.c +@@ -394,6 +394,53 @@ static void ixp4xx_adjust_link(struct ne + dev->name, port->speed, port->duplex ? "full" : "half"); + } + ++static int ixp4xx_phy_connect(struct net_device *dev) ++{ ++ struct port *port = netdev_priv(dev); ++ struct eth_plat_info *plat = port->plat; ++ char phy_id[BUS_ID_SIZE]; ++ ++ snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, "0", plat->phy); ++ port->phydev = phy_connect(dev, phy_id, &ixp4xx_adjust_link, 0, ++ PHY_INTERFACE_MODE_MII); ++ if (IS_ERR(port->phydev)) { ++ printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); ++ return PTR_ERR(port->phydev); ++ } ++ ++ /* mask with MAC supported features */ ++ port->phydev->supported &= PHY_BASIC_FEATURES; ++ port->phydev->advertising = port->phydev->supported; ++ ++ port->phydev->irq = PHY_POLL; ++ ++ printk(KERN_INFO "%s: MII PHY %i on %s\n", dev->name, plat->phy, ++ npe_name(port->npe)); ++ ++ return 0; ++} ++ ++static void ixp4xx_phy_disconnect(struct net_device *dev) ++{ ++ struct port *port = netdev_priv(dev); ++ ++ phy_disconnect(port->phydev); ++} ++ ++static void ixp4xx_phy_start(struct net_device *dev) ++{ ++ struct port *port = netdev_priv(dev); ++ ++ port->speed = 0; /* force "link up" message */ ++ phy_start(port->phydev); ++} ++ ++static void ixp4xx_phy_stop(struct net_device *dev) ++{ ++ struct port *port = netdev_priv(dev); ++ ++ phy_stop(port->phydev); ++} + + static inline void debug_pkt(struct net_device *dev, const char *func, + u8 *data, int len) +@@ -1001,8 +1048,7 @@ static int eth_open(struct net_device *d + return err; + } + +- port->speed = 0; /* force "link up" message */ +- phy_start(port->phydev); ++ ixp4xx_phy_start(dev); + + for (i = 0; i < ETH_ALEN; i++) + __raw_writel(dev->dev_addr[i], &port->regs->hw_addr[i]); +@@ -1123,7 +1169,7 @@ static int eth_close(struct net_device * + printk(KERN_CRIT "%s: unable to disable loopback\n", + dev->name); + +- phy_stop(port->phydev); ++ ixp4xx_phy_stop(dev); + + if (!ports_open) + qmgr_disable_irq(TXDONE_QUEUE); +@@ -1147,7 +1193,6 @@ static int __devinit eth_init_one(struct + struct net_device *dev; + struct eth_plat_info *plat = pdev->dev.platform_data; + u32 regs_phys; +- char phy_id[BUS_ID_SIZE]; + int err; + + if (!(dev = alloc_etherdev(sizeof(struct port)))) +@@ -1210,22 +1255,9 @@ static int __devinit eth_init_one(struct + __raw_writel(DEFAULT_CORE_CNTRL, &port->regs->core_control); + udelay(50); + +- snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, "0", plat->phy); +- port->phydev = phy_connect(dev, phy_id, &ixp4xx_adjust_link, 0, +- PHY_INTERFACE_MODE_MII); +- if (IS_ERR(port->phydev)) { +- printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); +- return PTR_ERR(port->phydev); +- } +- +- /* mask with MAC supported features */ +- port->phydev->supported &= PHY_BASIC_FEATURES; +- port->phydev->advertising = port->phydev->supported; +- +- port->phydev->irq = PHY_POLL; +- +- printk(KERN_INFO "%s: MII PHY %i on %s\n", dev->name, plat->phy, +- npe_name(port->npe)); ++ err = ixp4xx_phy_connect(dev); ++ if (err) ++ goto err_unreg; + + return 0; + +@@ -1243,7 +1275,7 @@ static int __devexit eth_remove_one(stru + struct net_device *dev = platform_get_drvdata(pdev); + struct port *port = netdev_priv(dev); + +- phy_disconnect(port->phydev); ++ ixp4xx_phy_disconnect(dev); + unregister_netdev(dev); + npe_port_tab[NPE_ID(port->id)] = NULL; + platform_set_drvdata(pdev, NULL); diff --git a/target/linux/ixp4xx/patches-2.6.29/206-npe_driver_add_update_link_function.patch b/target/linux/ixp4xx/patches-2.6.29/206-npe_driver_add_update_link_function.patch new file mode 100644 index 0000000000..2071d23263 --- /dev/null +++ b/target/linux/ixp4xx/patches-2.6.29/206-npe_driver_add_update_link_function.patch @@ -0,0 +1,98 @@ +--- a/drivers/net/arm/ixp4xx_eth.c ++++ b/drivers/net/arm/ixp4xx_eth.c +@@ -169,7 +169,7 @@ struct port { + struct desc *desc_tab; /* coherent */ + u32 desc_tab_phys; + int id; /* logical port ID */ +- int speed, duplex; ++ int link, speed, duplex; + u8 firmware[4]; + }; + +@@ -363,37 +363,52 @@ static void ixp4xx_mdio_remove(void) + mdiobus_free(mdio_bus); + } + +- +-static void ixp4xx_adjust_link(struct net_device *dev) ++static void ixp4xx_update_link(struct net_device *dev) + { + struct port *port = netdev_priv(dev); +- struct phy_device *phydev = port->phydev; + +- if (!phydev->link) { +- if (port->speed) { +- port->speed = 0; +- printk(KERN_INFO "%s: link down\n", dev->name); +- } ++ if (!port->link) { ++ netif_carrier_off(dev); ++ printk(KERN_INFO "%s: link down\n", dev->name); + return; + } + +- if (port->speed == phydev->speed && port->duplex == phydev->duplex) +- return; +- +- port->speed = phydev->speed; +- port->duplex = phydev->duplex; +- +- if (port->duplex) ++ if (port->duplex == DUPLEX_FULL) + __raw_writel(DEFAULT_TX_CNTRL0 & ~TX_CNTRL0_HALFDUPLEX, + &port->regs->tx_control[0]); + else + __raw_writel(DEFAULT_TX_CNTRL0 | TX_CNTRL0_HALFDUPLEX, + &port->regs->tx_control[0]); + ++ netif_carrier_on(dev); + printk(KERN_INFO "%s: link up, speed %u Mb/s, %s duplex\n", + dev->name, port->speed, port->duplex ? "full" : "half"); + } + ++static void ixp4xx_adjust_link(struct net_device *dev) ++{ ++ struct port *port = netdev_priv(dev); ++ struct phy_device *phydev = port->phydev; ++ int status_change = 0; ++ ++ if (phydev->link) { ++ if (port->duplex != phydev->duplex ++ || port->speed != phydev->speed) { ++ status_change = 1; ++ } ++ } ++ ++ if (phydev->link != port->link) ++ status_change = 1; ++ ++ port->link = phydev->link; ++ port->speed = phydev->speed; ++ port->duplex = phydev->duplex; ++ ++ if (status_change) ++ ixp4xx_update_link(dev); ++} ++ + static int ixp4xx_phy_connect(struct net_device *dev) + { + struct port *port = netdev_priv(dev); +@@ -414,6 +429,10 @@ static int ixp4xx_phy_connect(struct net + + port->phydev->irq = PHY_POLL; + ++ port->link = 0; ++ port->speed = 0; ++ port->duplex = -1; ++ + printk(KERN_INFO "%s: MII PHY %i on %s\n", dev->name, plat->phy, + npe_name(port->npe)); + +@@ -431,7 +450,6 @@ static void ixp4xx_phy_start(struct net_ + { + struct port *port = netdev_priv(dev); + +- port->speed = 0; /* force "link up" message */ + phy_start(port->phydev); + } + diff --git a/target/linux/ixp4xx/patches-2.6.29/207-npe_driver_multiphy_support.patch b/target/linux/ixp4xx/patches-2.6.29/207-npe_driver_multiphy_support.patch new file mode 100644 index 0000000000..89ff69f266 --- /dev/null +++ b/target/linux/ixp4xx/patches-2.6.29/207-npe_driver_multiphy_support.patch @@ -0,0 +1,155 @@ +TODO: take care of additional PHYs through the PHY abstraction layer + +--- a/arch/arm/mach-ixp4xx/include/mach/platform.h ++++ b/arch/arm/mach-ixp4xx/include/mach/platform.h +@@ -72,7 +72,7 @@ extern unsigned long ixp4xx_exp_bus_size + /* + * Clock Speed Definitions. + */ +-#define IXP4XX_PERIPHERAL_BUS_CLOCK (66) /* 66Mhzi APB BUS */ ++#define IXP4XX_PERIPHERAL_BUS_CLOCK (66) /* 66Mhzi APB BUS */ + #define IXP4XX_UART_XTAL 14745600 + + /* +@@ -95,12 +95,23 @@ struct sys_timer; + #define IXP4XX_ETH_NPEB 0x10 + #define IXP4XX_ETH_NPEC 0x20 + ++#define IXP4XX_ETH_PHY_MAX_ADDR 32 ++ + /* Information about built-in Ethernet MAC interfaces */ + struct eth_plat_info { + u8 phy; /* MII PHY ID, 0 - 31 */ + u8 rxq; /* configurable, currently 0 - 31 only */ + u8 txreadyq; + u8 hwaddr[6]; ++ ++ u32 phy_mask; ++#if 0 ++ int speed; ++ int duplex; ++#else ++ int speed_10; ++ int half_duplex; ++#endif + }; + + /* Information about built-in HSS (synchronous serial) interfaces */ +--- a/drivers/net/arm/ixp4xx_eth.c ++++ b/drivers/net/arm/ixp4xx_eth.c +@@ -415,6 +415,37 @@ static int ixp4xx_phy_connect(struct net + struct eth_plat_info *plat = port->plat; + char phy_id[BUS_ID_SIZE]; + ++ if (plat->phy == IXP4XX_ETH_PHY_MAX_ADDR) { ++#if 0 ++ switch (plat->speed) { ++ case SPEED_10: ++ case SPEED_100: ++ break; ++ default: ++ printk(KERN_ERR "%s: invalid speed (%d)\n", ++ dev->name, plat->speed); ++ return -EINVAL; ++ } ++ ++ switch (plat->duplex) { ++ case DUPLEX_HALF: ++ case DUPLEX_FULL: ++ break; ++ default: ++ printk(KERN_ERR "%s: invalid duplex mode (%d)\n", ++ dev->name, plat->duplex); ++ return -EINVAL; ++ } ++ port->speed = plat->speed; ++ port->duplex = plat->duplex; ++#else ++ port->speed = plat->speed_10 ? SPEED_10 : SPEED_100; ++ port->duplex = plat->half_duplex ? DUPLEX_HALF : DUPLEX_FULL; ++#endif ++ ++ return 0; ++ } ++ + snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, "0", plat->phy); + port->phydev = phy_connect(dev, phy_id, &ixp4xx_adjust_link, 0, + PHY_INTERFACE_MODE_MII); +@@ -443,21 +474,32 @@ static void ixp4xx_phy_disconnect(struct + { + struct port *port = netdev_priv(dev); + +- phy_disconnect(port->phydev); ++ if (port->phydev) ++ phy_disconnect(port->phydev); + } + + static void ixp4xx_phy_start(struct net_device *dev) + { + struct port *port = netdev_priv(dev); + +- phy_start(port->phydev); ++ if (port->phydev) { ++ phy_start(port->phydev); ++ } else { ++ port->link = 1; ++ ixp4xx_update_link(dev); ++ } + } + + static void ixp4xx_phy_stop(struct net_device *dev) + { + struct port *port = netdev_priv(dev); + +- phy_stop(port->phydev); ++ if (port->phydev) { ++ phy_stop(port->phydev); ++ } else { ++ port->link = 0; ++ ixp4xx_update_link(dev); ++ } + } + + static inline void debug_pkt(struct net_device *dev, const char *func, +@@ -829,6 +871,10 @@ static int eth_ioctl(struct net_device * + + if (!netif_running(dev)) + return -EINVAL; ++ ++ if (!port->phydev) ++ return -EOPNOTSUPP; ++ + return phy_mii_ioctl(port->phydev, if_mii(req), cmd); + } + +@@ -848,18 +894,30 @@ static void ixp4xx_get_drvinfo(struct ne + static int ixp4xx_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) + { + struct port *port = netdev_priv(dev); ++ ++ if (!port->phydev) ++ return -EOPNOTSUPP; ++ + return phy_ethtool_gset(port->phydev, cmd); + } + + static int ixp4xx_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) + { + struct port *port = netdev_priv(dev); ++ ++ if (!port->phydev) ++ return -EOPNOTSUPP; ++ + return phy_ethtool_sset(port->phydev, cmd); + } + + static int ixp4xx_nway_reset(struct net_device *dev) + { + struct port *port = netdev_priv(dev); ++ ++ if (!port->phydev) ++ return -EOPNOTSUPP; ++ + return phy_start_aneg(port->phydev); + } + -- 2.11.0