kernel: backport bgmac patch moving MDIO code into separated file
authorRafał Miłecki <rafal@milecki.pl>
Tue, 16 Aug 2016 22:06:14 +0000 (00:06 +0200)
committerRafał Miłecki <rafal@milecki.pl>
Tue, 16 Aug 2016 22:15:27 +0000 (00:15 +0200)
This prepares bgmac for the biggest change: dropping bcma dependency.

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
target/linux/generic/patches-4.4/075-0003-net-ethernet-bgmac-move-BCMA-MDIO-Phy-code-into-a-se.patch [new file with mode: 0644]
target/linux/generic/patches-4.4/773-bgmac-add-srab-switch.patch

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 (file)
index 0000000..f698a6f
--- /dev/null
@@ -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);
index 3892d8e..29e7892 100644 (file)
@@ -12,9 +12,9 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
  #include <linux/bcm47xx_nvram.h>
  
  static const struct bcma_device_id bgmac_bcma_tbl[] = {
-@@ -1681,6 +1682,17 @@ static void bgmac_mii_unregister(struct
-       mdiobus_free(mii_bus);
- }
+@@ -1403,6 +1404,17 @@ static const struct ethtool_ops bgmac_et
+       .get_drvinfo            = bgmac_get_drvinfo,
+ };
  
 +static struct b53_platform_data bgmac_b53_pdata = {
 +};
@@ -28,9 +28,9 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +};
 +
  /**************************************************
-  * BCMA bus ops
+  * MII
   **************************************************/
-@@ -1829,6 +1841,14 @@ static int bgmac_probe(struct bcma_devic
+@@ -1630,6 +1642,14 @@ static int bgmac_probe(struct bcma_devic
        net_dev->hw_features = net_dev->features;
        net_dev->vlan_features = net_dev->features;
  
@@ -45,7 +45,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
        err = register_netdev(bgmac->net_dev);
        if (err) {
                dev_err(bgmac->dev, "Cannot register net device\n");
-@@ -1855,6 +1875,10 @@ static void bgmac_remove(struct bcma_dev
+@@ -1657,6 +1677,10 @@ static void bgmac_remove(struct bcma_dev
  {
        struct bgmac *bgmac = bcma_get_drvdata(core);
  
@@ -54,8 +54,8 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +      bgmac->b53_device = NULL;
 +
        unregister_netdev(bgmac->net_dev);
-       bgmac_mii_unregister(bgmac);
-       netif_napi_del(&bgmac->napi);
+       phy_disconnect(bgmac->net_dev->phydev);
+       bcma_mdio_mii_unregister(bgmac->mii_bus);
 --- a/drivers/net/ethernet/broadcom/bgmac.h
 +++ b/drivers/net/ethernet/broadcom/bgmac.h
 @@ -454,6 +454,9 @@ struct bgmac {
@@ -67,4 +67,4 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +      struct platform_device *b53_device;
  };
  
- static inline u32 bgmac_read(struct bgmac *bgmac, u16 offset)
+ struct mii_bus *bcma_mdio_mii_register(struct bcma_device *core, u8 phyaddr);