diff options
Diffstat (limited to 'target/linux/generic/patches-4.4/075-0003-net-ethernet-bgmac-move-BCMA-MDIO-Phy-code-into-a-se.patch')
-rw-r--r-- | target/linux/generic/patches-4.4/075-0003-net-ethernet-bgmac-move-BCMA-MDIO-Phy-code-into-a-se.patch | 676 |
1 files changed, 676 insertions, 0 deletions
diff --git a/target/linux/generic/patches-4.4/075-0003-net-ethernet-bgmac-move-BCMA-MDIO-Phy-code-into-a-se.patch b/target/linux/generic/patches-4.4/075-0003-net-ethernet-bgmac-move-BCMA-MDIO-Phy-code-into-a-se.patch new file mode 100644 index 0000000000..f698a6fca0 --- /dev/null +++ b/target/linux/generic/patches-4.4/075-0003-net-ethernet-bgmac-move-BCMA-MDIO-Phy-code-into-a-se.patch @@ -0,0 +1,676 @@ +From 55954f3bfdacc5908515b0c306cea23e77fab740 Mon Sep 17 00:00:00 2001 +From: Jon Mason <jon.mason@broadcom.com> +Date: Thu, 7 Jul 2016 19:08:55 -0400 +Subject: [PATCH 3/5] net: ethernet: bgmac: move BCMA MDIO Phy code into a + separate file + +Move the BCMA MDIO phy into a separate file, as it is very tightly +coupled with the BCMA bus. This will help with the upcoming BCMA +removal from the bgmac driver. Optimally, this should be moved into +phy drivers, but it is too tightly coupled with the bgmac driver to +effectively move it without more changes to the driver. + +Note: the phy_reset was intentionally removed, as the mdio phy subsystem +automatically resets the phy if a reset function pointer is present. In +addition to the moving of the driver, this reset function is added. + +Signed-off-by: Jon Mason <jon.mason@broadcom.com> +Acked-by: Arnd Bergmann <arnd@arndb.de> +Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> +Tested-by: Florian Fainelli <f.fainelli@gmail.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/ethernet/broadcom/Makefile | 2 +- + drivers/net/ethernet/broadcom/bgmac-bcma-mdio.c | 264 ++++++++++++++++++++++++ + drivers/net/ethernet/broadcom/bgmac.c | 246 +++------------------- + drivers/net/ethernet/broadcom/bgmac.h | 3 + + 4 files changed, 298 insertions(+), 217 deletions(-) + create mode 100644 drivers/net/ethernet/broadcom/bgmac-bcma-mdio.c + +--- a/drivers/net/ethernet/broadcom/Makefile ++++ b/drivers/net/ethernet/broadcom/Makefile +@@ -10,6 +10,6 @@ obj-$(CONFIG_CNIC) += cnic.o + obj-$(CONFIG_BNX2X) += bnx2x/ + obj-$(CONFIG_SB1250_MAC) += sb1250-mac.o + obj-$(CONFIG_TIGON3) += tg3.o +-obj-$(CONFIG_BGMAC) += bgmac.o ++obj-$(CONFIG_BGMAC) += bgmac.o bgmac-bcma-mdio.o + obj-$(CONFIG_SYSTEMPORT) += bcmsysport.o + obj-$(CONFIG_BNXT) += bnxt/ +--- /dev/null ++++ b/drivers/net/ethernet/broadcom/bgmac-bcma-mdio.c +@@ -0,0 +1,275 @@ ++/* ++ * Driver for (BCM4706)? GBit MAC core on BCMA bus. ++ * ++ * Copyright (C) 2012 Rafał Miłecki <zajec5@gmail.com> ++ * ++ * Licensed under the GNU/GPL. See COPYING for details. ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include <linux/bcma/bcma.h> ++#include <linux/brcmphy.h> ++#include "bgmac.h" ++ ++struct bcma_mdio { ++ struct bcma_device *core; ++ u8 phyaddr; ++}; ++ ++static bool bcma_mdio_wait_value(struct bcma_device *core, u16 reg, u32 mask, ++ u32 value, int timeout) ++{ ++ u32 val; ++ int i; ++ ++ for (i = 0; i < timeout / 10; i++) { ++ val = bcma_read32(core, reg); ++ if ((val & mask) == value) ++ return true; ++ udelay(10); ++ } ++ dev_err(&core->dev, "Timeout waiting for reg 0x%X\n", reg); ++ return false; ++} ++ ++/************************************************** ++ * PHY ops ++ **************************************************/ ++ ++static u16 bcma_mdio_phy_read(struct bcma_mdio *bcma_mdio, u8 phyaddr, u8 reg) ++{ ++ struct bcma_device *core; ++ u16 phy_access_addr; ++ u16 phy_ctl_addr; ++ u32 tmp; ++ ++ BUILD_BUG_ON(BGMAC_PA_DATA_MASK != BCMA_GMAC_CMN_PA_DATA_MASK); ++ BUILD_BUG_ON(BGMAC_PA_ADDR_MASK != BCMA_GMAC_CMN_PA_ADDR_MASK); ++ BUILD_BUG_ON(BGMAC_PA_ADDR_SHIFT != BCMA_GMAC_CMN_PA_ADDR_SHIFT); ++ BUILD_BUG_ON(BGMAC_PA_REG_MASK != BCMA_GMAC_CMN_PA_REG_MASK); ++ BUILD_BUG_ON(BGMAC_PA_REG_SHIFT != BCMA_GMAC_CMN_PA_REG_SHIFT); ++ BUILD_BUG_ON(BGMAC_PA_WRITE != BCMA_GMAC_CMN_PA_WRITE); ++ BUILD_BUG_ON(BGMAC_PA_START != BCMA_GMAC_CMN_PA_START); ++ BUILD_BUG_ON(BGMAC_PC_EPA_MASK != BCMA_GMAC_CMN_PC_EPA_MASK); ++ BUILD_BUG_ON(BGMAC_PC_MCT_MASK != BCMA_GMAC_CMN_PC_MCT_MASK); ++ BUILD_BUG_ON(BGMAC_PC_MCT_SHIFT != BCMA_GMAC_CMN_PC_MCT_SHIFT); ++ BUILD_BUG_ON(BGMAC_PC_MTE != BCMA_GMAC_CMN_PC_MTE); ++ ++ if (bcma_mdio->core->id.id == BCMA_CORE_4706_MAC_GBIT) { ++ core = bcma_mdio->core->bus->drv_gmac_cmn.core; ++ phy_access_addr = BCMA_GMAC_CMN_PHY_ACCESS; ++ phy_ctl_addr = BCMA_GMAC_CMN_PHY_CTL; ++ } else { ++ core = bcma_mdio->core; ++ phy_access_addr = BGMAC_PHY_ACCESS; ++ phy_ctl_addr = BGMAC_PHY_CNTL; ++ } ++ ++ tmp = bcma_read32(core, phy_ctl_addr); ++ tmp &= ~BGMAC_PC_EPA_MASK; ++ tmp |= phyaddr; ++ bcma_write32(core, phy_ctl_addr, tmp); ++ ++ tmp = BGMAC_PA_START; ++ tmp |= phyaddr << BGMAC_PA_ADDR_SHIFT; ++ tmp |= reg << BGMAC_PA_REG_SHIFT; ++ bcma_write32(core, phy_access_addr, tmp); ++ ++ if (!bcma_mdio_wait_value(core, phy_access_addr, BGMAC_PA_START, 0, ++ 1000)) { ++ dev_err(&core->dev, "Reading PHY %d register 0x%X failed\n", ++ phyaddr, reg); ++ return 0xffff; ++ } ++ ++ return bcma_read32(core, phy_access_addr) & BGMAC_PA_DATA_MASK; ++} ++ ++/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphywr */ ++static int bcma_mdio_phy_write(struct bcma_mdio *bcma_mdio, u8 phyaddr, u8 reg, ++ u16 value) ++{ ++ struct bcma_device *core; ++ u16 phy_access_addr; ++ u16 phy_ctl_addr; ++ u32 tmp; ++ ++ if (bcma_mdio->core->id.id == BCMA_CORE_4706_MAC_GBIT) { ++ core = bcma_mdio->core->bus->drv_gmac_cmn.core; ++ phy_access_addr = BCMA_GMAC_CMN_PHY_ACCESS; ++ phy_ctl_addr = BCMA_GMAC_CMN_PHY_CTL; ++ } else { ++ core = bcma_mdio->core; ++ phy_access_addr = BGMAC_PHY_ACCESS; ++ phy_ctl_addr = BGMAC_PHY_CNTL; ++ } ++ ++ tmp = bcma_read32(core, phy_ctl_addr); ++ tmp &= ~BGMAC_PC_EPA_MASK; ++ tmp |= phyaddr; ++ bcma_write32(core, phy_ctl_addr, tmp); ++ ++ bcma_write32(bcma_mdio->core, BGMAC_INT_STATUS, BGMAC_IS_MDIO); ++ if (bcma_read32(bcma_mdio->core, BGMAC_INT_STATUS) & BGMAC_IS_MDIO) ++ dev_warn(&core->dev, "Error setting MDIO int\n"); ++ ++ tmp = BGMAC_PA_START; ++ tmp |= BGMAC_PA_WRITE; ++ tmp |= phyaddr << BGMAC_PA_ADDR_SHIFT; ++ tmp |= reg << BGMAC_PA_REG_SHIFT; ++ tmp |= value; ++ bcma_write32(core, phy_access_addr, tmp); ++ ++ if (!bcma_mdio_wait_value(core, phy_access_addr, BGMAC_PA_START, 0, ++ 1000)) { ++ dev_err(&core->dev, "Writing to PHY %d register 0x%X failed\n", ++ phyaddr, reg); ++ return -ETIMEDOUT; ++ } ++ ++ return 0; ++} ++ ++/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphyinit */ ++static void bcma_mdio_phy_init(struct bcma_mdio *bcma_mdio) ++{ ++ struct bcma_chipinfo *ci = &bcma_mdio->core->bus->chipinfo; ++ u8 i; ++ ++ if (ci->id == BCMA_CHIP_ID_BCM5356) { ++ for (i = 0; i < 5; i++) { ++ bcma_mdio_phy_write(bcma_mdio, i, 0x1f, 0x008b); ++ bcma_mdio_phy_write(bcma_mdio, i, 0x15, 0x0100); ++ bcma_mdio_phy_write(bcma_mdio, i, 0x1f, 0x000f); ++ bcma_mdio_phy_write(bcma_mdio, i, 0x12, 0x2aaa); ++ bcma_mdio_phy_write(bcma_mdio, i, 0x1f, 0x000b); ++ } ++ } ++ if ((ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg != 10) || ++ (ci->id == BCMA_CHIP_ID_BCM4749 && ci->pkg != 10) || ++ (ci->id == BCMA_CHIP_ID_BCM53572 && ci->pkg != 9)) { ++ struct bcma_drv_cc *cc = &bcma_mdio->core->bus->drv_cc; ++ ++ bcma_chipco_chipctl_maskset(cc, 2, ~0xc0000000, 0); ++ bcma_chipco_chipctl_maskset(cc, 4, ~0x80000000, 0); ++ for (i = 0; i < 5; i++) { ++ bcma_mdio_phy_write(bcma_mdio, i, 0x1f, 0x000f); ++ bcma_mdio_phy_write(bcma_mdio, i, 0x16, 0x5284); ++ bcma_mdio_phy_write(bcma_mdio, i, 0x1f, 0x000b); ++ bcma_mdio_phy_write(bcma_mdio, i, 0x17, 0x0010); ++ bcma_mdio_phy_write(bcma_mdio, i, 0x1f, 0x000f); ++ bcma_mdio_phy_write(bcma_mdio, i, 0x16, 0x5296); ++ bcma_mdio_phy_write(bcma_mdio, i, 0x17, 0x1073); ++ bcma_mdio_phy_write(bcma_mdio, i, 0x17, 0x9073); ++ bcma_mdio_phy_write(bcma_mdio, i, 0x16, 0x52b6); ++ bcma_mdio_phy_write(bcma_mdio, i, 0x17, 0x9273); ++ bcma_mdio_phy_write(bcma_mdio, i, 0x1f, 0x000b); ++ } ++ } ++} ++ ++/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphyreset */ ++static int bcma_mdio_phy_reset(struct mii_bus *bus) ++{ ++ struct bcma_mdio *bcma_mdio = bus->priv; ++ u8 phyaddr = bcma_mdio->phyaddr; ++ ++ if (bcma_mdio->phyaddr == BGMAC_PHY_NOREGS) ++ return 0; ++ ++ bcma_mdio_phy_write(bcma_mdio, phyaddr, MII_BMCR, BMCR_RESET); ++ udelay(100); ++ if (bcma_mdio_phy_read(bcma_mdio, phyaddr, MII_BMCR) & BMCR_RESET) ++ dev_err(&bcma_mdio->core->dev, "PHY reset failed\n"); ++ bcma_mdio_phy_init(bcma_mdio); ++ ++ return 0; ++} ++ ++/************************************************** ++ * MII ++ **************************************************/ ++ ++static int bcma_mdio_mii_read(struct mii_bus *bus, int mii_id, int regnum) ++{ ++ return bcma_mdio_phy_read(bus->priv, mii_id, regnum); ++} ++ ++static int bcma_mdio_mii_write(struct mii_bus *bus, int mii_id, int regnum, ++ u16 value) ++{ ++ return bcma_mdio_phy_write(bus->priv, mii_id, regnum, value); ++} ++ ++struct mii_bus *bcma_mdio_mii_register(struct bcma_device *core, u8 phyaddr) ++{ ++ struct bcma_mdio *bcma_mdio; ++ struct mii_bus *mii_bus; ++ int i, err; ++ ++ bcma_mdio = kzalloc(sizeof(*bcma_mdio), GFP_KERNEL); ++ if (!bcma_mdio) ++ return ERR_PTR(-ENOMEM); ++ ++ mii_bus = mdiobus_alloc(); ++ if (!mii_bus) { ++ err = -ENOMEM; ++ goto err; ++ } ++ ++ mii_bus->name = "bcma_mdio mii bus"; ++ sprintf(mii_bus->id, "%s-%d-%d", "bcma_mdio", core->bus->num, ++ core->core_unit); ++ mii_bus->priv = bcma_mdio; ++ mii_bus->read = bcma_mdio_mii_read; ++ mii_bus->write = bcma_mdio_mii_write; ++ mii_bus->reset = bcma_mdio_phy_reset; ++ mii_bus->parent = &core->dev; ++ mii_bus->phy_mask = ~(1 << phyaddr); ++ ++ mii_bus->irq = kmalloc_array(PHY_MAX_ADDR, sizeof(int), GFP_KERNEL); ++ if (!mii_bus->irq) { ++ err = -ENOMEM; ++ goto err_free_bus; ++ } ++ for (i = 0; i < PHY_MAX_ADDR; i++) ++ mii_bus->irq[i] = PHY_POLL; ++ ++ bcma_mdio->core = core; ++ bcma_mdio->phyaddr = phyaddr; ++ ++ err = mdiobus_register(mii_bus); ++ if (err) { ++ dev_err(&core->dev, "Registration of mii bus failed\n"); ++ goto err_free_irq; ++ } ++ ++ return mii_bus; ++ ++err_free_irq: ++ kfree(mii_bus->irq); ++err_free_bus: ++ mdiobus_free(mii_bus); ++err: ++ kfree(bcma_mdio); ++ return ERR_PTR(err); ++} ++ ++void bcma_mdio_mii_unregister(struct mii_bus *mii_bus) ++{ ++ struct bcma_mdio *bcma_mdio; ++ ++ if (!mii_bus) ++ return; ++ ++ bcma_mdio = mii_bus->priv; ++ ++ mdiobus_unregister(mii_bus); ++ kfree(mii_bus->irq); ++ mdiobus_free(mii_bus); ++ kfree(bcma_mdio); ++} ++ ++MODULE_AUTHOR("Rafał Miłecki"); ++MODULE_LICENSE("GPL"); +--- a/drivers/net/ethernet/broadcom/bgmac.c ++++ b/drivers/net/ethernet/broadcom/bgmac.c +@@ -756,150 +756,6 @@ error: + return err; + } + +-/************************************************** +- * PHY ops +- **************************************************/ +- +-static u16 bgmac_phy_read(struct bgmac *bgmac, u8 phyaddr, u8 reg) +-{ +- struct bcma_device *core; +- u16 phy_access_addr; +- u16 phy_ctl_addr; +- u32 tmp; +- +- BUILD_BUG_ON(BGMAC_PA_DATA_MASK != BCMA_GMAC_CMN_PA_DATA_MASK); +- BUILD_BUG_ON(BGMAC_PA_ADDR_MASK != BCMA_GMAC_CMN_PA_ADDR_MASK); +- BUILD_BUG_ON(BGMAC_PA_ADDR_SHIFT != BCMA_GMAC_CMN_PA_ADDR_SHIFT); +- BUILD_BUG_ON(BGMAC_PA_REG_MASK != BCMA_GMAC_CMN_PA_REG_MASK); +- BUILD_BUG_ON(BGMAC_PA_REG_SHIFT != BCMA_GMAC_CMN_PA_REG_SHIFT); +- BUILD_BUG_ON(BGMAC_PA_WRITE != BCMA_GMAC_CMN_PA_WRITE); +- BUILD_BUG_ON(BGMAC_PA_START != BCMA_GMAC_CMN_PA_START); +- BUILD_BUG_ON(BGMAC_PC_EPA_MASK != BCMA_GMAC_CMN_PC_EPA_MASK); +- BUILD_BUG_ON(BGMAC_PC_MCT_MASK != BCMA_GMAC_CMN_PC_MCT_MASK); +- BUILD_BUG_ON(BGMAC_PC_MCT_SHIFT != BCMA_GMAC_CMN_PC_MCT_SHIFT); +- BUILD_BUG_ON(BGMAC_PC_MTE != BCMA_GMAC_CMN_PC_MTE); +- +- if (bgmac->core->id.id == BCMA_CORE_4706_MAC_GBIT) { +- core = bgmac->core->bus->drv_gmac_cmn.core; +- phy_access_addr = BCMA_GMAC_CMN_PHY_ACCESS; +- phy_ctl_addr = BCMA_GMAC_CMN_PHY_CTL; +- } else { +- core = bgmac->core; +- phy_access_addr = BGMAC_PHY_ACCESS; +- phy_ctl_addr = BGMAC_PHY_CNTL; +- } +- +- tmp = bcma_read32(core, phy_ctl_addr); +- tmp &= ~BGMAC_PC_EPA_MASK; +- tmp |= phyaddr; +- bcma_write32(core, phy_ctl_addr, tmp); +- +- tmp = BGMAC_PA_START; +- tmp |= phyaddr << BGMAC_PA_ADDR_SHIFT; +- tmp |= reg << BGMAC_PA_REG_SHIFT; +- bcma_write32(core, phy_access_addr, tmp); +- +- if (!bgmac_wait_value(core, phy_access_addr, BGMAC_PA_START, 0, 1000)) { +- dev_err(bgmac->dev, "Reading PHY %d register 0x%X failed\n", +- phyaddr, reg); +- return 0xffff; +- } +- +- return bcma_read32(core, phy_access_addr) & BGMAC_PA_DATA_MASK; +-} +- +-/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphywr */ +-static int bgmac_phy_write(struct bgmac *bgmac, u8 phyaddr, u8 reg, u16 value) +-{ +- struct bcma_device *core; +- u16 phy_access_addr; +- u16 phy_ctl_addr; +- u32 tmp; +- +- if (bgmac->core->id.id == BCMA_CORE_4706_MAC_GBIT) { +- core = bgmac->core->bus->drv_gmac_cmn.core; +- phy_access_addr = BCMA_GMAC_CMN_PHY_ACCESS; +- phy_ctl_addr = BCMA_GMAC_CMN_PHY_CTL; +- } else { +- core = bgmac->core; +- phy_access_addr = BGMAC_PHY_ACCESS; +- phy_ctl_addr = BGMAC_PHY_CNTL; +- } +- +- tmp = bcma_read32(core, phy_ctl_addr); +- tmp &= ~BGMAC_PC_EPA_MASK; +- tmp |= phyaddr; +- bcma_write32(core, phy_ctl_addr, tmp); +- +- bgmac_write(bgmac, BGMAC_INT_STATUS, BGMAC_IS_MDIO); +- if (bgmac_read(bgmac, BGMAC_INT_STATUS) & BGMAC_IS_MDIO) +- dev_warn(bgmac->dev, "Error setting MDIO int\n"); +- +- tmp = BGMAC_PA_START; +- tmp |= BGMAC_PA_WRITE; +- tmp |= phyaddr << BGMAC_PA_ADDR_SHIFT; +- tmp |= reg << BGMAC_PA_REG_SHIFT; +- tmp |= value; +- bcma_write32(core, phy_access_addr, tmp); +- +- if (!bgmac_wait_value(core, phy_access_addr, BGMAC_PA_START, 0, 1000)) { +- dev_err(bgmac->dev, "Writing to PHY %d register 0x%X failed\n", +- phyaddr, reg); +- return -ETIMEDOUT; +- } +- +- return 0; +-} +- +-/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphyinit */ +-static void bgmac_phy_init(struct bgmac *bgmac) +-{ +- struct bcma_chipinfo *ci = &bgmac->core->bus->chipinfo; +- struct bcma_drv_cc *cc = &bgmac->core->bus->drv_cc; +- u8 i; +- +- if (ci->id == BCMA_CHIP_ID_BCM5356) { +- for (i = 0; i < 5; i++) { +- bgmac_phy_write(bgmac, i, 0x1f, 0x008b); +- bgmac_phy_write(bgmac, i, 0x15, 0x0100); +- bgmac_phy_write(bgmac, i, 0x1f, 0x000f); +- bgmac_phy_write(bgmac, i, 0x12, 0x2aaa); +- bgmac_phy_write(bgmac, i, 0x1f, 0x000b); +- } +- } +- if ((ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg != 10) || +- (ci->id == BCMA_CHIP_ID_BCM4749 && ci->pkg != 10) || +- (ci->id == BCMA_CHIP_ID_BCM53572 && ci->pkg != 9)) { +- bcma_chipco_chipctl_maskset(cc, 2, ~0xc0000000, 0); +- bcma_chipco_chipctl_maskset(cc, 4, ~0x80000000, 0); +- for (i = 0; i < 5; i++) { +- bgmac_phy_write(bgmac, i, 0x1f, 0x000f); +- bgmac_phy_write(bgmac, i, 0x16, 0x5284); +- bgmac_phy_write(bgmac, i, 0x1f, 0x000b); +- bgmac_phy_write(bgmac, i, 0x17, 0x0010); +- bgmac_phy_write(bgmac, i, 0x1f, 0x000f); +- bgmac_phy_write(bgmac, i, 0x16, 0x5296); +- bgmac_phy_write(bgmac, i, 0x17, 0x1073); +- bgmac_phy_write(bgmac, i, 0x17, 0x9073); +- bgmac_phy_write(bgmac, i, 0x16, 0x52b6); +- bgmac_phy_write(bgmac, i, 0x17, 0x9273); +- bgmac_phy_write(bgmac, i, 0x1f, 0x000b); +- } +- } +-} +- +-/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphyreset */ +-static void bgmac_phy_reset(struct bgmac *bgmac) +-{ +- if (bgmac->phyaddr == BGMAC_PHY_NOREGS) +- return; +- +- bgmac_phy_write(bgmac, bgmac->phyaddr, MII_BMCR, BMCR_RESET); +- udelay(100); +- if (bgmac_phy_read(bgmac, bgmac->phyaddr, MII_BMCR) & BMCR_RESET) +- dev_err(bgmac->dev, "PHY reset failed\n"); +- bgmac_phy_init(bgmac); +-} + + /************************************************** + * Chip ops +@@ -1156,7 +1012,8 @@ static void bgmac_chip_reset(struct bgma + else + bgmac_set(bgmac, BGMAC_PHY_CNTL, BGMAC_PC_MTE); + bgmac_miiconfig(bgmac); +- bgmac_phy_init(bgmac); ++ if (bgmac->mii_bus) ++ bgmac->mii_bus->reset(bgmac->mii_bus); + + netdev_reset_queue(bgmac->net_dev); + } +@@ -1550,17 +1407,6 @@ static const struct ethtool_ops bgmac_et + * MII + **************************************************/ + +-static int bgmac_mii_read(struct mii_bus *bus, int mii_id, int regnum) +-{ +- return bgmac_phy_read(bus->priv, mii_id, regnum); +-} +- +-static int bgmac_mii_write(struct mii_bus *bus, int mii_id, int regnum, +- u16 value) +-{ +- return bgmac_phy_write(bus->priv, mii_id, regnum, value); +-} +- + static void bgmac_adjust_link(struct net_device *net_dev) + { + struct bgmac *bgmac = netdev_priv(net_dev); +@@ -1585,7 +1431,7 @@ static void bgmac_adjust_link(struct net + } + } + +-static int bgmac_fixed_phy_register(struct bgmac *bgmac) ++static int bgmac_phy_connect_direct(struct bgmac *bgmac) + { + struct fixed_phy_status fphy_status = { + .link = 1, +@@ -1611,81 +1457,24 @@ static int bgmac_fixed_phy_register(stru + return err; + } + +-static int bgmac_mii_register(struct bgmac *bgmac) ++static int bgmac_phy_connect(struct bgmac *bgmac) + { +- struct mii_bus *mii_bus; + struct phy_device *phy_dev; + char bus_id[MII_BUS_ID_SIZE + 3]; +- int i, err = 0; +- +- if (bgmac_is_bcm4707_family(bgmac)) +- return bgmac_fixed_phy_register(bgmac); +- +- mii_bus = mdiobus_alloc(); +- if (!mii_bus) +- return -ENOMEM; +- +- mii_bus->name = "bgmac mii bus"; +- sprintf(mii_bus->id, "%s-%d-%d", "bgmac", bgmac->core->bus->num, +- bgmac->core->core_unit); +- mii_bus->priv = bgmac; +- mii_bus->read = bgmac_mii_read; +- mii_bus->write = bgmac_mii_write; +- mii_bus->parent = &bgmac->core->dev; +- mii_bus->phy_mask = ~(1 << bgmac->phyaddr); +- +- mii_bus->irq = kmalloc_array(PHY_MAX_ADDR, sizeof(int), GFP_KERNEL); +- if (!mii_bus->irq) { +- err = -ENOMEM; +- goto err_free_bus; +- } +- for (i = 0; i < PHY_MAX_ADDR; i++) +- mii_bus->irq[i] = PHY_POLL; +- +- err = mdiobus_register(mii_bus); +- if (err) { +- dev_err(bgmac->dev, "Registration of mii bus failed\n"); +- goto err_free_irq; +- } +- +- bgmac->mii_bus = mii_bus; + + /* Connect to the PHY */ +- snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, mii_bus->id, ++ snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, bgmac->mii_bus->id, + bgmac->phyaddr); + phy_dev = phy_connect(bgmac->net_dev, bus_id, &bgmac_adjust_link, + PHY_INTERFACE_MODE_MII); + if (IS_ERR(phy_dev)) { + dev_err(bgmac->dev, "PHY connecton failed\n"); +- err = PTR_ERR(phy_dev); +- goto err_unregister_bus; ++ return PTR_ERR(phy_dev); + } + +- return err; +- +-err_unregister_bus: +- mdiobus_unregister(mii_bus); +-err_free_irq: +- kfree(mii_bus->irq); +-err_free_bus: +- mdiobus_free(mii_bus); +- return err; +-} +- +-static void bgmac_mii_unregister(struct bgmac *bgmac) +-{ +- struct mii_bus *mii_bus = bgmac->mii_bus; +- +- mdiobus_unregister(mii_bus); +- kfree(mii_bus->irq); +- mdiobus_free(mii_bus); ++ return 0; + } + +-/************************************************** +- * BCMA bus ops +- **************************************************/ +- +-/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipattach */ + static int bgmac_probe(struct bcma_device *core) + { + struct net_device *net_dev; +@@ -1806,9 +1595,6 @@ static int bgmac_probe(struct bcma_devic + if (bcm47xx_nvram_getenv("et0_no_txint", NULL, 0) == 0) + bgmac->int_mask &= ~BGMAC_IS_TX_MASK; + +- /* TODO: reset the external phy. Specs are needed */ +- bgmac_phy_reset(bgmac); +- + bgmac->has_robosw = !!(core->bus->sprom.boardflags_lo & + BGMAC_BFL_ENETROBO); + if (bgmac->has_robosw) +@@ -1819,10 +1605,25 @@ static int bgmac_probe(struct bcma_devic + + netif_napi_add(net_dev, &bgmac->napi, bgmac_poll, BGMAC_WEIGHT); + +- err = bgmac_mii_register(bgmac); ++ if (!bgmac_is_bcm4707_family(bgmac)) { ++ struct mii_bus *mii_bus; ++ ++ mii_bus = bcma_mdio_mii_register(core, bgmac->phyaddr); ++ if (!IS_ERR(mii_bus)) { ++ err = PTR_ERR(mii_bus); ++ goto err_dma_free; ++ } ++ ++ bgmac->mii_bus = mii_bus; ++ } ++ ++ if (!bgmac->mii_bus) ++ err = bgmac_phy_connect_direct(bgmac); ++ else ++ err = bgmac_phy_connect(bgmac); + if (err) { + dev_err(bgmac->dev, "Cannot connect to phy\n"); +- goto err_dma_free; ++ goto err_mii_unregister; + } + + net_dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; +@@ -1832,18 +1633,19 @@ static int bgmac_probe(struct bcma_devic + err = register_netdev(bgmac->net_dev); + if (err) { + dev_err(bgmac->dev, "Cannot register net device\n"); +- goto err_mii_unregister; ++ goto err_phy_disconnect; + } + + netif_carrier_off(net_dev); + + return 0; + ++err_phy_disconnect: ++ phy_disconnect(net_dev->phydev); + err_mii_unregister: +- bgmac_mii_unregister(bgmac); ++ bcma_mdio_mii_unregister(bgmac->mii_bus); + err_dma_free: + bgmac_dma_free(bgmac); +- + err_netdev_free: + bcma_set_drvdata(core, NULL); + free_netdev(net_dev); +@@ -1856,7 +1658,8 @@ static void bgmac_remove(struct bcma_dev + struct bgmac *bgmac = bcma_get_drvdata(core); + + unregister_netdev(bgmac->net_dev); +- bgmac_mii_unregister(bgmac); ++ phy_disconnect(bgmac->net_dev->phydev); ++ bcma_mdio_mii_unregister(bgmac->mii_bus); + netif_napi_del(&bgmac->napi); + bgmac_dma_free(bgmac); + bcma_set_drvdata(core, NULL); +--- a/drivers/net/ethernet/broadcom/bgmac.h ++++ b/drivers/net/ethernet/broadcom/bgmac.h +@@ -456,6 +456,9 @@ struct bgmac { + bool loopback; + }; + ++struct mii_bus *bcma_mdio_mii_register(struct bcma_device *core, u8 phyaddr); ++void bcma_mdio_mii_unregister(struct mii_bus *mii_bus); ++ + static inline u32 bgmac_read(struct bgmac *bgmac, u16 offset) + { + return bcma_read32(bgmac->core, offset); |