mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-31 14:04:26 -04:00 
			
		
		
		
	It also reworks bcma support by moving specific code to separated file. Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
		
			
				
	
	
		
			1261 lines
		
	
	
		
			37 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			1261 lines
		
	
	
		
			37 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From f6a95a24957aec5bb488c3f978c4ed508177998f Mon Sep 17 00:00:00 2001
 | |
| From: Jon Mason <jon.mason@broadcom.com>
 | |
| Date: Thu, 7 Jul 2016 19:08:57 -0400
 | |
| Subject: [PATCH 5/5] net: ethernet: bgmac: Add platform device support
 | |
| 
 | |
| The bcma portion of the driver has been split off into a bcma specific
 | |
| driver.  This has been mirrored for the platform driver.  The last
 | |
| references to the bcma core struct have been changed into a generic
 | |
| function call.  These function calls are wrappers to either the original
 | |
| bcma code or new platform functions that access the same areas via MMIO.
 | |
| This necessitated adding function pointers for both platform and bcma to
 | |
| hide which backend is being used from the generic bgmac code.
 | |
| 
 | |
| 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/Kconfig           |  23 +-
 | |
|  drivers/net/ethernet/broadcom/Makefile          |   4 +-
 | |
|  drivers/net/ethernet/broadcom/bgmac-bcma-mdio.c |   2 +
 | |
|  drivers/net/ethernet/broadcom/bgmac-bcma.c      | 315 +++++++++++++++++++++++
 | |
|  drivers/net/ethernet/broadcom/bgmac-platform.c  | 189 ++++++++++++++
 | |
|  drivers/net/ethernet/broadcom/bgmac.c           | 329 ++++--------------------
 | |
|  drivers/net/ethernet/broadcom/bgmac.h           |  73 +++++-
 | |
|  7 files changed, 650 insertions(+), 285 deletions(-)
 | |
|  create mode 100644 drivers/net/ethernet/broadcom/bgmac-bcma.c
 | |
|  create mode 100644 drivers/net/ethernet/broadcom/bgmac-platform.c
 | |
| 
 | |
| --- a/drivers/net/ethernet/broadcom/Kconfig
 | |
| +++ b/drivers/net/ethernet/broadcom/Kconfig
 | |
| @@ -150,10 +150,18 @@ config BNX2X_VXLAN
 | |
|  	  Virtual eXtensible Local Area Network (VXLAN) in the driver.
 | |
|  
 | |
|  config BGMAC
 | |
| -	tristate "BCMA bus GBit core support"
 | |
| +	tristate
 | |
| +	help
 | |
| +	  This enables the integrated ethernet controller support for many
 | |
| +	  Broadcom (mostly iProc) SoCs. An appropriate bus interface driver
 | |
| +	  needs to be enabled to select this.
 | |
| +
 | |
| +config BGMAC_BCMA
 | |
| +	tristate "Broadcom iProc GBit BCMA support"
 | |
|  	depends on BCMA && BCMA_HOST_SOC
 | |
|  	depends on HAS_DMA
 | |
|  	depends on BCM47XX || ARCH_BCM_5301X || COMPILE_TEST
 | |
| +	select BGMAC
 | |
|  	select PHYLIB
 | |
|  	select FIXED_PHY
 | |
|  	---help---
 | |
| @@ -162,6 +170,19 @@ config BGMAC
 | |
|  	  In case of using this driver on BCM4706 it's also requires to enable
 | |
|  	  BCMA_DRIVER_GMAC_CMN to make it work.
 | |
|  
 | |
| +config BGMAC_PLATFORM
 | |
| +	tristate "Broadcom iProc GBit platform support"
 | |
| +	depends on HAS_DMA
 | |
| +	depends on ARCH_BCM_IPROC || COMPILE_TEST
 | |
| +	depends on OF
 | |
| +	select BGMAC
 | |
| +	select PHYLIB
 | |
| +	select FIXED_PHY
 | |
| +	default ARCH_BCM_IPROC
 | |
| +	---help---
 | |
| +	  Say Y here if you want to use the Broadcom iProc Gigabit Ethernet
 | |
| +	  controller through the generic platform interface
 | |
| +
 | |
|  config SYSTEMPORT
 | |
|  	tristate "Broadcom SYSTEMPORT internal MAC support"
 | |
|  	depends on OF
 | |
| --- a/drivers/net/ethernet/broadcom/Makefile
 | |
| +++ b/drivers/net/ethernet/broadcom/Makefile
 | |
| @@ -10,6 +10,8 @@ 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 bgmac-bcma-mdio.o
 | |
| +obj-$(CONFIG_BGMAC) += bgmac.o
 | |
| +obj-$(CONFIG_BGMAC_BCMA) += bgmac-bcma.o bgmac-bcma-mdio.o
 | |
| +obj-$(CONFIG_BGMAC_PLATFORM) += bgmac-platform.o
 | |
|  obj-$(CONFIG_SYSTEMPORT) += bcmsysport.o
 | |
|  obj-$(CONFIG_BNXT) += bnxt/
 | |
| --- a/drivers/net/ethernet/broadcom/bgmac-bcma-mdio.c
 | |
| +++ b/drivers/net/ethernet/broadcom/bgmac-bcma-mdio.c
 | |
| @@ -255,6 +255,7 @@ err:
 | |
|  	kfree(bcma_mdio);
 | |
|  	return ERR_PTR(err);
 | |
|  }
 | |
| +EXPORT_SYMBOL_GPL(bcma_mdio_mii_register);
 | |
|  
 | |
|  void bcma_mdio_mii_unregister(struct mii_bus *mii_bus)
 | |
|  {
 | |
| @@ -270,6 +271,7 @@ void bcma_mdio_mii_unregister(struct mii
 | |
|  	mdiobus_free(mii_bus);
 | |
|  	kfree(bcma_mdio);
 | |
|  }
 | |
| +EXPORT_SYMBOL_GPL(bcma_mdio_mii_unregister);
 | |
|  
 | |
|  MODULE_AUTHOR("Rafał Miłecki");
 | |
|  MODULE_LICENSE("GPL");
 | |
| --- /dev/null
 | |
| +++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c
 | |
| @@ -0,0 +1,315 @@
 | |
| +/*
 | |
| + * 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 <linux/etherdevice.h>
 | |
| +#include "bgmac.h"
 | |
| +
 | |
| +static inline bool bgmac_is_bcm4707_family(struct bcma_device *core)
 | |
| +{
 | |
| +	switch (core->bus->chipinfo.id) {
 | |
| +	case BCMA_CHIP_ID_BCM4707:
 | |
| +	case BCMA_CHIP_ID_BCM47094:
 | |
| +	case BCMA_CHIP_ID_BCM53018:
 | |
| +		return true;
 | |
| +	default:
 | |
| +		return false;
 | |
| +	}
 | |
| +}
 | |
| +
 | |
| +/**************************************************
 | |
| + * BCMA bus ops
 | |
| + **************************************************/
 | |
| +
 | |
| +static u32 bcma_bgmac_read(struct bgmac *bgmac, u16 offset)
 | |
| +{
 | |
| +	return bcma_read32(bgmac->bcma.core, offset);
 | |
| +}
 | |
| +
 | |
| +static void bcma_bgmac_write(struct bgmac *bgmac, u16 offset, u32 value)
 | |
| +{
 | |
| +	bcma_write32(bgmac->bcma.core, offset, value);
 | |
| +}
 | |
| +
 | |
| +static u32 bcma_bgmac_idm_read(struct bgmac *bgmac, u16 offset)
 | |
| +{
 | |
| +	return bcma_aread32(bgmac->bcma.core, offset);
 | |
| +}
 | |
| +
 | |
| +static void bcma_bgmac_idm_write(struct bgmac *bgmac, u16 offset, u32 value)
 | |
| +{
 | |
| +	return bcma_awrite32(bgmac->bcma.core, offset, value);
 | |
| +}
 | |
| +
 | |
| +static bool bcma_bgmac_clk_enabled(struct bgmac *bgmac)
 | |
| +{
 | |
| +	return bcma_core_is_enabled(bgmac->bcma.core);
 | |
| +}
 | |
| +
 | |
| +static void bcma_bgmac_clk_enable(struct bgmac *bgmac, u32 flags)
 | |
| +{
 | |
| +	bcma_core_enable(bgmac->bcma.core, flags);
 | |
| +}
 | |
| +
 | |
| +static void bcma_bgmac_cco_ctl_maskset(struct bgmac *bgmac, u32 offset,
 | |
| +				       u32 mask, u32 set)
 | |
| +{
 | |
| +	struct bcma_drv_cc *cc = &bgmac->bcma.core->bus->drv_cc;
 | |
| +
 | |
| +	bcma_chipco_chipctl_maskset(cc, offset, mask, set);
 | |
| +}
 | |
| +
 | |
| +static u32 bcma_bgmac_get_bus_clock(struct bgmac *bgmac)
 | |
| +{
 | |
| +	struct bcma_drv_cc *cc = &bgmac->bcma.core->bus->drv_cc;
 | |
| +
 | |
| +	return bcma_pmu_get_bus_clock(cc);
 | |
| +}
 | |
| +
 | |
| +static void bcma_bgmac_cmn_maskset32(struct bgmac *bgmac, u16 offset, u32 mask,
 | |
| +				     u32 set)
 | |
| +{
 | |
| +	bcma_maskset32(bgmac->bcma.cmn, offset, mask, set);
 | |
| +}
 | |
| +
 | |
| +static const struct bcma_device_id bgmac_bcma_tbl[] = {
 | |
| +	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_4706_MAC_GBIT,
 | |
| +		  BCMA_ANY_REV, BCMA_ANY_CLASS),
 | |
| +	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_MAC_GBIT, BCMA_ANY_REV,
 | |
| +		  BCMA_ANY_CLASS),
 | |
| +	{},
 | |
| +};
 | |
| +MODULE_DEVICE_TABLE(bcma, bgmac_bcma_tbl);
 | |
| +
 | |
| +/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipattach */
 | |
| +static int bgmac_probe(struct bcma_device *core)
 | |
| +{
 | |
| +	struct ssb_sprom *sprom = &core->bus->sprom;
 | |
| +	struct mii_bus *mii_bus;
 | |
| +	struct bgmac *bgmac;
 | |
| +	u8 *mac;
 | |
| +	int err;
 | |
| +
 | |
| +	bgmac = kzalloc(sizeof(*bgmac), GFP_KERNEL);
 | |
| +	if (!bgmac)
 | |
| +		return -ENOMEM;
 | |
| +
 | |
| +	bgmac->bcma.core = core;
 | |
| +	bgmac->dev = &core->dev;
 | |
| +	bgmac->dma_dev = core->dma_dev;
 | |
| +	bgmac->irq = core->irq;
 | |
| +
 | |
| +	bcma_set_drvdata(core, bgmac);
 | |
| +
 | |
| +	switch (core->core_unit) {
 | |
| +	case 0:
 | |
| +		mac = sprom->et0mac;
 | |
| +		break;
 | |
| +	case 1:
 | |
| +		mac = sprom->et1mac;
 | |
| +		break;
 | |
| +	case 2:
 | |
| +		mac = sprom->et2mac;
 | |
| +		break;
 | |
| +	default:
 | |
| +		dev_err(bgmac->dev, "Unsupported core_unit %d\n",
 | |
| +			core->core_unit);
 | |
| +		err = -ENOTSUPP;
 | |
| +		goto err;
 | |
| +	}
 | |
| +
 | |
| +	ether_addr_copy(bgmac->mac_addr, mac);
 | |
| +
 | |
| +	/* On BCM4706 we need common core to access PHY */
 | |
| +	if (core->id.id == BCMA_CORE_4706_MAC_GBIT &&
 | |
| +	    !core->bus->drv_gmac_cmn.core) {
 | |
| +		dev_err(bgmac->dev, "GMAC CMN core not found (required for BCM4706)\n");
 | |
| +		err = -ENODEV;
 | |
| +		goto err;
 | |
| +	}
 | |
| +	bgmac->bcma.cmn = core->bus->drv_gmac_cmn.core;
 | |
| +
 | |
| +	switch (core->core_unit) {
 | |
| +	case 0:
 | |
| +		bgmac->phyaddr = sprom->et0phyaddr;
 | |
| +		break;
 | |
| +	case 1:
 | |
| +		bgmac->phyaddr = sprom->et1phyaddr;
 | |
| +		break;
 | |
| +	case 2:
 | |
| +		bgmac->phyaddr = sprom->et2phyaddr;
 | |
| +		break;
 | |
| +	}
 | |
| +	bgmac->phyaddr &= BGMAC_PHY_MASK;
 | |
| +	if (bgmac->phyaddr == BGMAC_PHY_MASK) {
 | |
| +		dev_err(bgmac->dev, "No PHY found\n");
 | |
| +		err = -ENODEV;
 | |
| +		goto err;
 | |
| +	}
 | |
| +	dev_info(bgmac->dev, "Found PHY addr: %d%s\n", bgmac->phyaddr,
 | |
| +		 bgmac->phyaddr == BGMAC_PHY_NOREGS ? " (NOREGS)" : "");
 | |
| +
 | |
| +	if (!bgmac_is_bcm4707_family(core)) {
 | |
| +		mii_bus = bcma_mdio_mii_register(core, bgmac->phyaddr);
 | |
| +		if (!IS_ERR(mii_bus)) {
 | |
| +			err = PTR_ERR(mii_bus);
 | |
| +			goto err;
 | |
| +		}
 | |
| +
 | |
| +		bgmac->mii_bus = mii_bus;
 | |
| +	}
 | |
| +
 | |
| +	if (core->bus->hosttype == BCMA_HOSTTYPE_PCI) {
 | |
| +		dev_err(bgmac->dev, "PCI setup not implemented\n");
 | |
| +		err = -ENOTSUPP;
 | |
| +		goto err1;
 | |
| +	}
 | |
| +
 | |
| +	bgmac->has_robosw = !!(core->bus->sprom.boardflags_lo &
 | |
| +			       BGMAC_BFL_ENETROBO);
 | |
| +	if (bgmac->has_robosw)
 | |
| +		dev_warn(bgmac->dev, "Support for Roboswitch not implemented\n");
 | |
| +
 | |
| +	if (core->bus->sprom.boardflags_lo & BGMAC_BFL_ENETADM)
 | |
| +		dev_warn(bgmac->dev, "Support for ADMtek ethernet switch not implemented\n");
 | |
| +
 | |
| +	/* Feature Flags */
 | |
| +	switch (core->bus->chipinfo.id) {
 | |
| +	case BCMA_CHIP_ID_BCM5357:
 | |
| +		bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK;
 | |
| +		bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
 | |
| +		bgmac->feature_flags |= BGMAC_FEAT_FLW_CTRL1;
 | |
| +		bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_PHY;
 | |
| +		if (core->bus->chipinfo.pkg == BCMA_PKG_ID_BCM47186) {
 | |
| +			bgmac->feature_flags |= BGMAC_FEAT_IOST_ATTACHED;
 | |
| +			bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_RGMII;
 | |
| +		}
 | |
| +		if (core->bus->chipinfo.pkg == BCMA_PKG_ID_BCM5358)
 | |
| +			bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_EPHYRMII;
 | |
| +		break;
 | |
| +	case BCMA_CHIP_ID_BCM53572:
 | |
| +		bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK;
 | |
| +		bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
 | |
| +		bgmac->feature_flags |= BGMAC_FEAT_FLW_CTRL1;
 | |
| +		bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_PHY;
 | |
| +		if (core->bus->chipinfo.pkg == BCMA_PKG_ID_BCM47188) {
 | |
| +			bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_RGMII;
 | |
| +			bgmac->feature_flags |= BGMAC_FEAT_IOST_ATTACHED;
 | |
| +		}
 | |
| +		break;
 | |
| +	case BCMA_CHIP_ID_BCM4749:
 | |
| +		bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK;
 | |
| +		bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
 | |
| +		bgmac->feature_flags |= BGMAC_FEAT_FLW_CTRL1;
 | |
| +		bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_PHY;
 | |
| +		if (core->bus->chipinfo.pkg == 10) {
 | |
| +			bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_RGMII;
 | |
| +			bgmac->feature_flags |= BGMAC_FEAT_IOST_ATTACHED;
 | |
| +		}
 | |
| +		break;
 | |
| +	case BCMA_CHIP_ID_BCM4716:
 | |
| +		bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
 | |
| +		/* fallthrough */
 | |
| +	case BCMA_CHIP_ID_BCM47162:
 | |
| +		bgmac->feature_flags |= BGMAC_FEAT_FLW_CTRL2;
 | |
| +		bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK;
 | |
| +		break;
 | |
| +	/* bcm4707_family */
 | |
| +	case BCMA_CHIP_ID_BCM4707:
 | |
| +	case BCMA_CHIP_ID_BCM47094:
 | |
| +	case BCMA_CHIP_ID_BCM53018:
 | |
| +		bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
 | |
| +		bgmac->feature_flags |= BGMAC_FEAT_NO_RESET;
 | |
| +		bgmac->feature_flags |= BGMAC_FEAT_FORCE_SPEED_2500;
 | |
| +		break;
 | |
| +	default:
 | |
| +		bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
 | |
| +		bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK;
 | |
| +	}
 | |
| +
 | |
| +	if (!bgmac_is_bcm4707_family(core) && core->id.rev > 2)
 | |
| +		bgmac->feature_flags |= BGMAC_FEAT_MISC_PLL_REQ;
 | |
| +
 | |
| +	if (core->id.id == BCMA_CORE_4706_MAC_GBIT) {
 | |
| +		bgmac->feature_flags |= BGMAC_FEAT_CMN_PHY_CTL;
 | |
| +		bgmac->feature_flags |= BGMAC_FEAT_NO_CLR_MIB;
 | |
| +	}
 | |
| +
 | |
| +	if (core->id.rev >= 4) {
 | |
| +		bgmac->feature_flags |= BGMAC_FEAT_CMDCFG_SR_REV4;
 | |
| +		bgmac->feature_flags |= BGMAC_FEAT_TX_MASK_SETUP;
 | |
| +		bgmac->feature_flags |= BGMAC_FEAT_RX_MASK_SETUP;
 | |
| +	}
 | |
| +
 | |
| +	bgmac->read = bcma_bgmac_read;
 | |
| +	bgmac->write = bcma_bgmac_write;
 | |
| +	bgmac->idm_read = bcma_bgmac_idm_read;
 | |
| +	bgmac->idm_write = bcma_bgmac_idm_write;
 | |
| +	bgmac->clk_enabled = bcma_bgmac_clk_enabled;
 | |
| +	bgmac->clk_enable = bcma_bgmac_clk_enable;
 | |
| +	bgmac->cco_ctl_maskset = bcma_bgmac_cco_ctl_maskset;
 | |
| +	bgmac->get_bus_clock = bcma_bgmac_get_bus_clock;
 | |
| +	bgmac->cmn_maskset32 = bcma_bgmac_cmn_maskset32;
 | |
| +
 | |
| +	err = bgmac_enet_probe(bgmac);
 | |
| +	if (err)
 | |
| +		goto err1;
 | |
| +
 | |
| +	return 0;
 | |
| +
 | |
| +err1:
 | |
| +	bcma_mdio_mii_unregister(bgmac->mii_bus);
 | |
| +err:
 | |
| +	kfree(bgmac);
 | |
| +	bcma_set_drvdata(core, NULL);
 | |
| +
 | |
| +	return err;
 | |
| +}
 | |
| +
 | |
| +static void bgmac_remove(struct bcma_device *core)
 | |
| +{
 | |
| +	struct bgmac *bgmac = bcma_get_drvdata(core);
 | |
| +
 | |
| +	bcma_mdio_mii_unregister(bgmac->mii_bus);
 | |
| +	bgmac_enet_remove(bgmac);
 | |
| +	bcma_set_drvdata(core, NULL);
 | |
| +	kfree(bgmac);
 | |
| +}
 | |
| +
 | |
| +static struct bcma_driver bgmac_bcma_driver = {
 | |
| +	.name		= KBUILD_MODNAME,
 | |
| +	.id_table	= bgmac_bcma_tbl,
 | |
| +	.probe		= bgmac_probe,
 | |
| +	.remove		= bgmac_remove,
 | |
| +};
 | |
| +
 | |
| +static int __init bgmac_init(void)
 | |
| +{
 | |
| +	int err;
 | |
| +
 | |
| +	err = bcma_driver_register(&bgmac_bcma_driver);
 | |
| +	if (err)
 | |
| +		return err;
 | |
| +	pr_info("Broadcom 47xx GBit MAC driver loaded\n");
 | |
| +
 | |
| +	return 0;
 | |
| +}
 | |
| +
 | |
| +static void __exit bgmac_exit(void)
 | |
| +{
 | |
| +	bcma_driver_unregister(&bgmac_bcma_driver);
 | |
| +}
 | |
| +
 | |
| +module_init(bgmac_init)
 | |
| +module_exit(bgmac_exit)
 | |
| +
 | |
| +MODULE_AUTHOR("Rafał Miłecki");
 | |
| +MODULE_LICENSE("GPL");
 | |
| --- /dev/null
 | |
| +++ b/drivers/net/ethernet/broadcom/bgmac-platform.c
 | |
| @@ -0,0 +1,189 @@
 | |
| +/*
 | |
| + * Copyright (C) 2016 Broadcom
 | |
| + *
 | |
| + * 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 the Free Software Foundation version 2.
 | |
| + *
 | |
| + * This program is distributed "as is" WITHOUT ANY WARRANTY of any
 | |
| + * kind, whether express or implied; without even the implied warranty
 | |
| + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
| + * GNU General Public License for more details.
 | |
| + */
 | |
| +
 | |
| +#define pr_fmt(fmt)		KBUILD_MODNAME ": " fmt
 | |
| +
 | |
| +#include <linux/bcma/bcma.h>
 | |
| +#include <linux/etherdevice.h>
 | |
| +#include <linux/of_address.h>
 | |
| +#include <linux/of_net.h>
 | |
| +#include "bgmac.h"
 | |
| +
 | |
| +static u32 platform_bgmac_read(struct bgmac *bgmac, u16 offset)
 | |
| +{
 | |
| +	return readl(bgmac->plat.base + offset);
 | |
| +}
 | |
| +
 | |
| +static void platform_bgmac_write(struct bgmac *bgmac, u16 offset, u32 value)
 | |
| +{
 | |
| +	writel(value, bgmac->plat.base + offset);
 | |
| +}
 | |
| +
 | |
| +static u32 platform_bgmac_idm_read(struct bgmac *bgmac, u16 offset)
 | |
| +{
 | |
| +	return readl(bgmac->plat.idm_base + offset);
 | |
| +}
 | |
| +
 | |
| +static void platform_bgmac_idm_write(struct bgmac *bgmac, u16 offset, u32 value)
 | |
| +{
 | |
| +	return writel(value, bgmac->plat.idm_base + offset);
 | |
| +}
 | |
| +
 | |
| +static bool platform_bgmac_clk_enabled(struct bgmac *bgmac)
 | |
| +{
 | |
| +	if ((bgmac_idm_read(bgmac, BCMA_IOCTL) &
 | |
| +	     (BCMA_IOCTL_CLK | BCMA_IOCTL_FGC)) != BCMA_IOCTL_CLK)
 | |
| +		return false;
 | |
| +	if (bgmac_idm_read(bgmac, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET)
 | |
| +		return false;
 | |
| +	return true;
 | |
| +}
 | |
| +
 | |
| +static void platform_bgmac_clk_enable(struct bgmac *bgmac, u32 flags)
 | |
| +{
 | |
| +	bgmac_idm_write(bgmac, BCMA_IOCTL,
 | |
| +			(BCMA_IOCTL_CLK | BCMA_IOCTL_FGC | flags));
 | |
| +	bgmac_idm_read(bgmac, BCMA_IOCTL);
 | |
| +
 | |
| +	bgmac_idm_write(bgmac, BCMA_RESET_CTL, 0);
 | |
| +	bgmac_idm_read(bgmac, BCMA_RESET_CTL);
 | |
| +	udelay(1);
 | |
| +
 | |
| +	bgmac_idm_write(bgmac, BCMA_IOCTL, (BCMA_IOCTL_CLK | flags));
 | |
| +	bgmac_idm_read(bgmac, BCMA_IOCTL);
 | |
| +	udelay(1);
 | |
| +}
 | |
| +
 | |
| +static void platform_bgmac_cco_ctl_maskset(struct bgmac *bgmac, u32 offset,
 | |
| +					   u32 mask, u32 set)
 | |
| +{
 | |
| +	/* This shouldn't be encountered */
 | |
| +	WARN_ON(1);
 | |
| +}
 | |
| +
 | |
| +static u32 platform_bgmac_get_bus_clock(struct bgmac *bgmac)
 | |
| +{
 | |
| +	/* This shouldn't be encountered */
 | |
| +	WARN_ON(1);
 | |
| +
 | |
| +	return 0;
 | |
| +}
 | |
| +
 | |
| +static void platform_bgmac_cmn_maskset32(struct bgmac *bgmac, u16 offset,
 | |
| +					 u32 mask, u32 set)
 | |
| +{
 | |
| +	/* This shouldn't be encountered */
 | |
| +	WARN_ON(1);
 | |
| +}
 | |
| +
 | |
| +static int bgmac_probe(struct platform_device *pdev)
 | |
| +{
 | |
| +	struct device_node *np = pdev->dev.of_node;
 | |
| +	struct bgmac *bgmac;
 | |
| +	struct resource *regs;
 | |
| +	const u8 *mac_addr;
 | |
| +
 | |
| +	bgmac = devm_kzalloc(&pdev->dev, sizeof(*bgmac), GFP_KERNEL);
 | |
| +	if (!bgmac)
 | |
| +		return -ENOMEM;
 | |
| +
 | |
| +	platform_set_drvdata(pdev, bgmac);
 | |
| +
 | |
| +	/* Set the features of the 4707 family */
 | |
| +	bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
 | |
| +	bgmac->feature_flags |= BGMAC_FEAT_NO_RESET;
 | |
| +	bgmac->feature_flags |= BGMAC_FEAT_FORCE_SPEED_2500;
 | |
| +	bgmac->feature_flags |= BGMAC_FEAT_CMDCFG_SR_REV4;
 | |
| +	bgmac->feature_flags |= BGMAC_FEAT_TX_MASK_SETUP;
 | |
| +	bgmac->feature_flags |= BGMAC_FEAT_RX_MASK_SETUP;
 | |
| +
 | |
| +	bgmac->dev = &pdev->dev;
 | |
| +	bgmac->dma_dev = &pdev->dev;
 | |
| +
 | |
| +	mac_addr = of_get_mac_address(np);
 | |
| +	if (mac_addr)
 | |
| +		ether_addr_copy(bgmac->mac_addr, mac_addr);
 | |
| +	else
 | |
| +		dev_warn(&pdev->dev, "MAC address not present in device tree\n");
 | |
| +
 | |
| +	bgmac->irq = platform_get_irq(pdev, 0);
 | |
| +	if (bgmac->irq < 0) {
 | |
| +		dev_err(&pdev->dev, "Unable to obtain IRQ\n");
 | |
| +		return bgmac->irq;
 | |
| +	}
 | |
| +
 | |
| +	regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "amac_base");
 | |
| +	if (!regs) {
 | |
| +		dev_err(&pdev->dev, "Unable to obtain base resource\n");
 | |
| +		return -EINVAL;
 | |
| +	}
 | |
| +
 | |
| +	bgmac->plat.base = devm_ioremap_resource(&pdev->dev, regs);
 | |
| +	if (IS_ERR(bgmac->plat.base)) {
 | |
| +		dev_err(&pdev->dev, "Unable to map base resource\n");
 | |
| +		return PTR_ERR(bgmac->plat.base);
 | |
| +	}
 | |
| +
 | |
| +	regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "idm_base");
 | |
| +	if (!regs) {
 | |
| +		dev_err(&pdev->dev, "Unable to obtain idm resource\n");
 | |
| +		return -EINVAL;
 | |
| +	}
 | |
| +
 | |
| +	bgmac->plat.idm_base = devm_ioremap_resource(&pdev->dev, regs);
 | |
| +	if (!bgmac->plat.idm_base) {
 | |
| +		dev_err(&pdev->dev, "Unable to map idm resource\n");
 | |
| +		return PTR_ERR(bgmac->plat.idm_base);
 | |
| +	}
 | |
| +
 | |
| +	bgmac->read = platform_bgmac_read;
 | |
| +	bgmac->write = platform_bgmac_write;
 | |
| +	bgmac->idm_read = platform_bgmac_idm_read;
 | |
| +	bgmac->idm_write = platform_bgmac_idm_write;
 | |
| +	bgmac->clk_enabled = platform_bgmac_clk_enabled;
 | |
| +	bgmac->clk_enable = platform_bgmac_clk_enable;
 | |
| +	bgmac->cco_ctl_maskset = platform_bgmac_cco_ctl_maskset;
 | |
| +	bgmac->get_bus_clock = platform_bgmac_get_bus_clock;
 | |
| +	bgmac->cmn_maskset32 = platform_bgmac_cmn_maskset32;
 | |
| +
 | |
| +	return bgmac_enet_probe(bgmac);
 | |
| +}
 | |
| +
 | |
| +static int bgmac_remove(struct platform_device *pdev)
 | |
| +{
 | |
| +	struct bgmac *bgmac = platform_get_drvdata(pdev);
 | |
| +
 | |
| +	bgmac_enet_remove(bgmac);
 | |
| +
 | |
| +	return 0;
 | |
| +}
 | |
| +
 | |
| +static const struct of_device_id bgmac_of_enet_match[] = {
 | |
| +	{.compatible = "brcm,amac",},
 | |
| +	{.compatible = "brcm,nsp-amac",},
 | |
| +	{},
 | |
| +};
 | |
| +
 | |
| +MODULE_DEVICE_TABLE(of, bgmac_of_enet_match);
 | |
| +
 | |
| +static struct platform_driver bgmac_enet_driver = {
 | |
| +	.driver = {
 | |
| +		.name  = "bgmac-enet",
 | |
| +		.of_match_table = bgmac_of_enet_match,
 | |
| +	},
 | |
| +	.probe = bgmac_probe,
 | |
| +	.remove = bgmac_remove,
 | |
| +};
 | |
| +
 | |
| +module_platform_driver(bgmac_enet_driver);
 | |
| +MODULE_LICENSE("GPL");
 | |
| --- a/drivers/net/ethernet/broadcom/bgmac.c
 | |
| +++ b/drivers/net/ethernet/broadcom/bgmac.c
 | |
| @@ -6,51 +6,27 @@
 | |
|   * Licensed under the GNU/GPL. See COPYING for details.
 | |
|   */
 | |
|  
 | |
| -#include "bgmac.h"
 | |
|  
 | |
| -#include <linux/kernel.h>
 | |
| -#include <linux/module.h>
 | |
| -#include <linux/delay.h>
 | |
| +#define pr_fmt(fmt)		KBUILD_MODNAME ": " fmt
 | |
| +
 | |
| +#include <linux/bcma/bcma.h>
 | |
|  #include <linux/etherdevice.h>
 | |
| -#include <linux/mii.h>
 | |
| -#include <linux/phy.h>
 | |
| -#include <linux/phy_fixed.h>
 | |
| -#include <linux/interrupt.h>
 | |
| -#include <linux/dma-mapping.h>
 | |
|  #include <linux/bcm47xx_nvram.h>
 | |
| +#include "bgmac.h"
 | |
|  
 | |
| -static const struct bcma_device_id bgmac_bcma_tbl[] = {
 | |
| -	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_4706_MAC_GBIT, BCMA_ANY_REV, BCMA_ANY_CLASS),
 | |
| -	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_MAC_GBIT, BCMA_ANY_REV, BCMA_ANY_CLASS),
 | |
| -	{},
 | |
| -};
 | |
| -MODULE_DEVICE_TABLE(bcma, bgmac_bcma_tbl);
 | |
| -
 | |
| -static inline bool bgmac_is_bcm4707_family(struct bgmac *bgmac)
 | |
| -{
 | |
| -	switch (bgmac->core->bus->chipinfo.id) {
 | |
| -	case BCMA_CHIP_ID_BCM4707:
 | |
| -	case BCMA_CHIP_ID_BCM47094:
 | |
| -	case BCMA_CHIP_ID_BCM53018:
 | |
| -		return true;
 | |
| -	default:
 | |
| -		return false;
 | |
| -	}
 | |
| -}
 | |
| -
 | |
| -static bool bgmac_wait_value(struct bcma_device *core, u16 reg, u32 mask,
 | |
| +static bool bgmac_wait_value(struct bgmac *bgmac, u16 reg, u32 mask,
 | |
|  			     u32 value, int timeout)
 | |
|  {
 | |
|  	u32 val;
 | |
|  	int i;
 | |
|  
 | |
|  	for (i = 0; i < timeout / 10; i++) {
 | |
| -		val = bcma_read32(core, reg);
 | |
| +		val = bgmac_read(bgmac, reg);
 | |
|  		if ((val & mask) == value)
 | |
|  			return true;
 | |
|  		udelay(10);
 | |
|  	}
 | |
| -	dev_err(&core->dev, "Timeout waiting for reg 0x%X\n", reg);
 | |
| +	dev_err(bgmac->dev, "Timeout waiting for reg 0x%X\n", reg);
 | |
|  	return false;
 | |
|  }
 | |
|  
 | |
| @@ -89,7 +65,7 @@ static void bgmac_dma_tx_reset(struct bg
 | |
|  
 | |
|  	/* Remove SUSPEND bit */
 | |
|  	bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_CTL, 0);
 | |
| -	if (!bgmac_wait_value(bgmac->core,
 | |
| +	if (!bgmac_wait_value(bgmac,
 | |
|  			      ring->mmio_base + BGMAC_DMA_TX_STATUS,
 | |
|  			      BGMAC_DMA_TX_STAT, BGMAC_DMA_TX_STAT_DISABLED,
 | |
|  			      10000)) {
 | |
| @@ -317,7 +293,7 @@ static void bgmac_dma_rx_reset(struct bg
 | |
|  		return;
 | |
|  
 | |
|  	bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_CTL, 0);
 | |
| -	if (!bgmac_wait_value(bgmac->core,
 | |
| +	if (!bgmac_wait_value(bgmac,
 | |
|  			      ring->mmio_base + BGMAC_DMA_RX_STATUS,
 | |
|  			      BGMAC_DMA_RX_STAT, BGMAC_DMA_RX_STAT_DISABLED,
 | |
|  			      10000))
 | |
| @@ -640,7 +616,7 @@ static int bgmac_dma_alloc(struct bgmac
 | |
|  	BUILD_BUG_ON(BGMAC_MAX_TX_RINGS > ARRAY_SIZE(ring_base));
 | |
|  	BUILD_BUG_ON(BGMAC_MAX_RX_RINGS > ARRAY_SIZE(ring_base));
 | |
|  
 | |
| -	if (!(bcma_aread32(bgmac->core, BCMA_IOST) & BCMA_IOST_DMA64)) {
 | |
| +	if (!(bgmac_idm_read(bgmac, BCMA_IOST) & BCMA_IOST_DMA64)) {
 | |
|  		dev_err(bgmac->dev, "Core does not report 64-bit DMA\n");
 | |
|  		return -ENOTSUPP;
 | |
|  	}
 | |
| @@ -872,12 +848,10 @@ static void bgmac_mac_speed(struct bgmac
 | |
|  
 | |
|  static void bgmac_miiconfig(struct bgmac *bgmac)
 | |
|  {
 | |
| -	struct bcma_device *core = bgmac->core;
 | |
| -
 | |
|  	if (bgmac->feature_flags & BGMAC_FEAT_FORCE_SPEED_2500) {
 | |
| -		bcma_awrite32(core, BCMA_IOCTL,
 | |
| -			      bcma_aread32(core, BCMA_IOCTL) | 0x40 |
 | |
| -			      BGMAC_BCMA_IOCTL_SW_CLKEN);
 | |
| +		bgmac_idm_write(bgmac, BCMA_IOCTL,
 | |
| +				bgmac_idm_read(bgmac, BCMA_IOCTL) | 0x40 |
 | |
| +				BGMAC_BCMA_IOCTL_SW_CLKEN);
 | |
|  		bgmac->mac_speed = SPEED_2500;
 | |
|  		bgmac->mac_duplex = DUPLEX_FULL;
 | |
|  		bgmac_mac_speed(bgmac);
 | |
| @@ -897,12 +871,11 @@ static void bgmac_miiconfig(struct bgmac
 | |
|  /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipreset */
 | |
|  static void bgmac_chip_reset(struct bgmac *bgmac)
 | |
|  {
 | |
| -	struct bcma_device *core = bgmac->core;
 | |
|  	u32 cmdcfg_sr;
 | |
|  	u32 iost;
 | |
|  	int i;
 | |
|  
 | |
| -	if (bcma_core_is_enabled(core)) {
 | |
| +	if (bgmac_clk_enabled(bgmac)) {
 | |
|  		if (!bgmac->stats_grabbed) {
 | |
|  			/* bgmac_chip_stats_update(bgmac); */
 | |
|  			bgmac->stats_grabbed = true;
 | |
| @@ -920,7 +893,7 @@ static void bgmac_chip_reset(struct bgma
 | |
|  		/* TODO: Clear software multicast filter list */
 | |
|  	}
 | |
|  
 | |
| -	iost = bcma_aread32(core, BCMA_IOST);
 | |
| +	iost = bgmac_idm_read(bgmac, BCMA_IOST);
 | |
|  	if (bgmac->feature_flags & BGMAC_FEAT_IOST_ATTACHED)
 | |
|  		iost &= ~BGMAC_BCMA_IOST_ATTACHED;
 | |
|  
 | |
| @@ -932,21 +905,20 @@ static void bgmac_chip_reset(struct bgma
 | |
|  			if (!bgmac->has_robosw)
 | |
|  				flags |= BGMAC_BCMA_IOCTL_SW_RESET;
 | |
|  		}
 | |
| -		bcma_core_enable(core, flags);
 | |
| +		bgmac_clk_enable(bgmac, flags);
 | |
|  	}
 | |
|  
 | |
|  	/* Request Misc PLL for corerev > 2 */
 | |
|  	if (bgmac->feature_flags & BGMAC_FEAT_MISC_PLL_REQ) {
 | |
|  		bgmac_set(bgmac, BCMA_CLKCTLST,
 | |
|  			  BGMAC_BCMA_CLKCTLST_MISC_PLL_REQ);
 | |
| -		bgmac_wait_value(bgmac->core, BCMA_CLKCTLST,
 | |
| +		bgmac_wait_value(bgmac, BCMA_CLKCTLST,
 | |
|  				 BGMAC_BCMA_CLKCTLST_MISC_PLL_ST,
 | |
|  				 BGMAC_BCMA_CLKCTLST_MISC_PLL_ST,
 | |
|  				 1000);
 | |
|  	}
 | |
|  
 | |
|  	if (bgmac->feature_flags & BGMAC_FEAT_SW_TYPE_PHY) {
 | |
| -		struct bcma_drv_cc *cc = &bgmac->core->bus->drv_cc;
 | |
|  		u8 et_swtype = 0;
 | |
|  		u8 sw_type = BGMAC_CHIPCTL_1_SW_TYPE_EPHY |
 | |
|  			     BGMAC_CHIPCTL_1_IF_TYPE_MII;
 | |
| @@ -965,16 +937,15 @@ static void bgmac_chip_reset(struct bgma
 | |
|  			sw_type = BGMAC_CHIPCTL_1_IF_TYPE_RGMII |
 | |
|  				  BGMAC_CHIPCTL_1_SW_TYPE_RGMII;
 | |
|  		}
 | |
| -		bcma_chipco_chipctl_maskset(cc, 1,
 | |
| -					    ~(BGMAC_CHIPCTL_1_IF_TYPE_MASK |
 | |
| -					      BGMAC_CHIPCTL_1_SW_TYPE_MASK),
 | |
| -					    sw_type);
 | |
| +		bgmac_cco_ctl_maskset(bgmac, 1, ~(BGMAC_CHIPCTL_1_IF_TYPE_MASK |
 | |
| +						  BGMAC_CHIPCTL_1_SW_TYPE_MASK),
 | |
| +				      sw_type);
 | |
|  	}
 | |
|  
 | |
|  	if (iost & BGMAC_BCMA_IOST_ATTACHED && !bgmac->has_robosw)
 | |
| -		bcma_awrite32(core, BCMA_IOCTL,
 | |
| -			      bcma_aread32(core, BCMA_IOCTL) &
 | |
| -			      ~BGMAC_BCMA_IOCTL_SW_RESET);
 | |
| +		bgmac_idm_write(bgmac, BCMA_IOCTL,
 | |
| +				bgmac_idm_read(bgmac, BCMA_IOCTL) &
 | |
| +				~BGMAC_BCMA_IOCTL_SW_RESET);
 | |
|  
 | |
|  	/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/gmac_reset
 | |
|  	 * Specs don't say about using BGMAC_CMDCFG_SR, but in this routine
 | |
| @@ -1010,8 +981,8 @@ static void bgmac_chip_reset(struct bgma
 | |
|  
 | |
|  	bgmac_clear_mib(bgmac);
 | |
|  	if (bgmac->feature_flags & BGMAC_FEAT_CMN_PHY_CTL)
 | |
| -		bcma_maskset32(bgmac->cmn, BCMA_GMAC_CMN_PHY_CTL, ~0,
 | |
| -			       BCMA_GMAC_CMN_PC_MTE);
 | |
| +		bgmac_cmn_maskset32(bgmac, BCMA_GMAC_CMN_PHY_CTL, ~0,
 | |
| +				    BCMA_GMAC_CMN_PC_MTE);
 | |
|  	else
 | |
|  		bgmac_set(bgmac, BGMAC_PHY_CNTL, BGMAC_PC_MTE);
 | |
|  	bgmac_miiconfig(bgmac);
 | |
| @@ -1056,8 +1027,8 @@ static void bgmac_enable(struct bgmac *b
 | |
|  	if (bgmac->feature_flags & BGMAC_FEAT_CLKCTLST || mode != 0)
 | |
|  		bgmac_set(bgmac, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT);
 | |
|  	if (bgmac->feature_flags & BGMAC_FEAT_CLKCTLST && mode == 2)
 | |
| -		bcma_chipco_chipctl_maskset(&bgmac->core->bus->drv_cc, 1, ~0,
 | |
| -					    BGMAC_CHIPCTL_1_RXC_DLL_BYPASS);
 | |
| +		bgmac_cco_ctl_maskset(bgmac, 1, ~0,
 | |
| +				      BGMAC_CHIPCTL_1_RXC_DLL_BYPASS);
 | |
|  
 | |
|  	if (bgmac->feature_flags & (BGMAC_FEAT_FLW_CTRL1 |
 | |
|  				    BGMAC_FEAT_FLW_CTRL2)) {
 | |
| @@ -1079,8 +1050,7 @@ static void bgmac_enable(struct bgmac *b
 | |
|  
 | |
|  		rxq_ctl = bgmac_read(bgmac, BGMAC_RXQ_CTL);
 | |
|  		rxq_ctl &= ~BGMAC_RXQ_CTL_MDP_MASK;
 | |
| -		bp_clk = bcma_pmu_get_bus_clock(&bgmac->core->bus->drv_cc) /
 | |
| -				1000000;
 | |
| +		bp_clk = bgmac_get_bus_clock(bgmac) / 1000000;
 | |
|  		mdp = (bp_clk * 128 / 1000) - 3;
 | |
|  		rxq_ctl |= (mdp << BGMAC_RXQ_CTL_MDP_SHIFT);
 | |
|  		bgmac_write(bgmac, BGMAC_RXQ_CTL, rxq_ctl);
 | |
| @@ -1175,7 +1145,7 @@ static int bgmac_open(struct net_device
 | |
|  	/* Specs say about reclaiming rings here, but we do that in DMA init */
 | |
|  	bgmac_chip_init(bgmac);
 | |
|  
 | |
| -	err = request_irq(bgmac->core->irq, bgmac_interrupt, IRQF_SHARED,
 | |
| +	err = request_irq(bgmac->irq, bgmac_interrupt, IRQF_SHARED,
 | |
|  			  KBUILD_MODNAME, net_dev);
 | |
|  	if (err < 0) {
 | |
|  		dev_err(bgmac->dev, "IRQ request error: %d!\n", err);
 | |
| @@ -1201,7 +1171,7 @@ static int bgmac_stop(struct net_device
 | |
|  
 | |
|  	napi_disable(&bgmac->napi);
 | |
|  	bgmac_chip_intrs_off(bgmac);
 | |
| -	free_irq(bgmac->core->irq, net_dev);
 | |
| +	free_irq(bgmac->irq, net_dev);
 | |
|  
 | |
|  	bgmac_chip_reset(bgmac);
 | |
|  	bgmac_dma_cleanup(bgmac);
 | |
| @@ -1396,7 +1366,7 @@ static void bgmac_get_drvinfo(struct net
 | |
|  			      struct ethtool_drvinfo *info)
 | |
|  {
 | |
|  	strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
 | |
| -	strlcpy(info->bus_info, "BCMA", sizeof(info->bus_info));
 | |
| +	strlcpy(info->bus_info, "AXI", sizeof(info->bus_info));
 | |
|  }
 | |
|  
 | |
|  static const struct ethtool_ops bgmac_ethtool_ops = {
 | |
| @@ -1480,116 +1450,41 @@ static int bgmac_phy_connect(struct bgma
 | |
|  	return 0;
 | |
|  }
 | |
|  
 | |
| -static int bgmac_probe(struct bcma_device *core)
 | |
| +int bgmac_enet_probe(struct bgmac *info)
 | |
|  {
 | |
|  	struct net_device *net_dev;
 | |
|  	struct bgmac *bgmac;
 | |
| -	struct ssb_sprom *sprom = &core->bus->sprom;
 | |
| -	u8 *mac;
 | |
|  	int err;
 | |
|  
 | |
| -	switch (core->core_unit) {
 | |
| -	case 0:
 | |
| -		mac = sprom->et0mac;
 | |
| -		break;
 | |
| -	case 1:
 | |
| -		mac = sprom->et1mac;
 | |
| -		break;
 | |
| -	case 2:
 | |
| -		mac = sprom->et2mac;
 | |
| -		break;
 | |
| -	default:
 | |
| -		dev_err(&core->dev, "Unsupported core_unit %d\n",
 | |
| -			core->core_unit);
 | |
| -		return -ENOTSUPP;
 | |
| -	}
 | |
| -
 | |
| -	if (!is_valid_ether_addr(mac)) {
 | |
| -		dev_err(&core->dev, "Invalid MAC addr: %pM\n", mac);
 | |
| -		eth_random_addr(mac);
 | |
| -		dev_warn(&core->dev, "Using random MAC: %pM\n", mac);
 | |
| -	}
 | |
| -
 | |
| -	/* This (reset &) enable is not preset in specs or reference driver but
 | |
| -	 * Broadcom does it in arch PCI code when enabling fake PCI device.
 | |
| -	 */
 | |
| -	bcma_core_enable(core, 0);
 | |
| -
 | |
|  	/* Allocation and references */
 | |
|  	net_dev = alloc_etherdev(sizeof(*bgmac));
 | |
|  	if (!net_dev)
 | |
|  		return -ENOMEM;
 | |
| +
 | |
|  	net_dev->netdev_ops = &bgmac_netdev_ops;
 | |
| -	net_dev->irq = core->irq;
 | |
|  	net_dev->ethtool_ops = &bgmac_ethtool_ops;
 | |
|  	bgmac = netdev_priv(net_dev);
 | |
| -	bgmac->dev = &core->dev;
 | |
| -	bgmac->dma_dev = core->dma_dev;
 | |
| +	memcpy(bgmac, info, sizeof(*bgmac));
 | |
|  	bgmac->net_dev = net_dev;
 | |
| -	bgmac->core = core;
 | |
| -	bcma_set_drvdata(core, bgmac);
 | |
| -	SET_NETDEV_DEV(net_dev, &core->dev);
 | |
| -
 | |
| -	/* Defaults */
 | |
| -	memcpy(bgmac->net_dev->dev_addr, mac, ETH_ALEN);
 | |
| -
 | |
| -	/* On BCM4706 we need common core to access PHY */
 | |
| -	if (core->id.id == BCMA_CORE_4706_MAC_GBIT &&
 | |
| -	    !core->bus->drv_gmac_cmn.core) {
 | |
| -		dev_err(bgmac->dev, "GMAC CMN core not found (required for BCM4706)\n");
 | |
| -		err = -ENODEV;
 | |
| -		goto err_netdev_free;
 | |
| -	}
 | |
| -	bgmac->cmn = core->bus->drv_gmac_cmn.core;
 | |
| +	net_dev->irq = bgmac->irq;
 | |
| +	SET_NETDEV_DEV(net_dev, bgmac->dev);
 | |
|  
 | |
| -	switch (core->core_unit) {
 | |
| -	case 0:
 | |
| -		bgmac->phyaddr = sprom->et0phyaddr;
 | |
| -		break;
 | |
| -	case 1:
 | |
| -		bgmac->phyaddr = sprom->et1phyaddr;
 | |
| -		break;
 | |
| -	case 2:
 | |
| -		bgmac->phyaddr = sprom->et2phyaddr;
 | |
| -		break;
 | |
| +	if (!is_valid_ether_addr(bgmac->mac_addr)) {
 | |
| +		dev_err(bgmac->dev, "Invalid MAC addr: %pM\n",
 | |
| +			bgmac->mac_addr);
 | |
| +		eth_random_addr(bgmac->mac_addr);
 | |
| +		dev_warn(bgmac->dev, "Using random MAC: %pM\n",
 | |
| +			 bgmac->mac_addr);
 | |
|  	}
 | |
| -	bgmac->phyaddr &= BGMAC_PHY_MASK;
 | |
| -	if (bgmac->phyaddr == BGMAC_PHY_MASK) {
 | |
| -		dev_err(bgmac->dev, "No PHY found\n");
 | |
| -		err = -ENODEV;
 | |
| -		goto err_netdev_free;
 | |
| -	}
 | |
| -	dev_info(bgmac->dev, "Found PHY addr: %d%s\n", bgmac->phyaddr,
 | |
| -		 bgmac->phyaddr == BGMAC_PHY_NOREGS ? " (NOREGS)" : "");
 | |
| +	ether_addr_copy(net_dev->dev_addr, bgmac->mac_addr);
 | |
|  
 | |
| -	if (core->bus->hosttype == BCMA_HOSTTYPE_PCI) {
 | |
| -		dev_err(bgmac->dev, "PCI setup not implemented\n");
 | |
| -		err = -ENOTSUPP;
 | |
| -		goto err_netdev_free;
 | |
| -	}
 | |
| +	/* This (reset &) enable is not preset in specs or reference driver but
 | |
| +	 * Broadcom does it in arch PCI code when enabling fake PCI device.
 | |
| +	 */
 | |
| +	bgmac_clk_enable(bgmac, 0);
 | |
|  
 | |
|  	bgmac_chip_reset(bgmac);
 | |
|  
 | |
| -	/* For Northstar, we have to take all GMAC core out of reset */
 | |
| -	if (bgmac_is_bcm4707_family(bgmac)) {
 | |
| -		struct bcma_device *ns_core;
 | |
| -		int ns_gmac;
 | |
| -
 | |
| -		/* Northstar has 4 GMAC cores */
 | |
| -		for (ns_gmac = 0; ns_gmac < 4; ns_gmac++) {
 | |
| -			/* As Northstar requirement, we have to reset all GMACs
 | |
| -			 * before accessing one. bgmac_chip_reset() call
 | |
| -			 * bcma_core_enable() for this core. Then the other
 | |
| -			 * three GMACs didn't reset.  We do it here.
 | |
| -			 */
 | |
| -			ns_core = bcma_find_core_unit(core->bus,
 | |
| -						      BCMA_CORE_MAC_GBIT,
 | |
| -						      ns_gmac);
 | |
| -			if (ns_core && !bcma_core_is_enabled(ns_core))
 | |
| -				bcma_core_enable(ns_core, 0);
 | |
| -		}
 | |
| -	}
 | |
| -
 | |
|  	err = bgmac_dma_alloc(bgmac);
 | |
|  	if (err) {
 | |
|  		dev_err(bgmac->dev, "Unable to alloc memory for DMA\n");
 | |
| @@ -1600,103 +1495,15 @@ static int bgmac_probe(struct bcma_devic
 | |
|  	if (bcm47xx_nvram_getenv("et0_no_txint", NULL, 0) == 0)
 | |
|  		bgmac->int_mask &= ~BGMAC_IS_TX_MASK;
 | |
|  
 | |
| -	bgmac->has_robosw = !!(core->bus->sprom.boardflags_lo &
 | |
| -			       BGMAC_BFL_ENETROBO);
 | |
| -	if (bgmac->has_robosw)
 | |
| -		dev_warn(bgmac->dev, "Support for Roboswitch not implemented\n");
 | |
| -
 | |
| -	if (core->bus->sprom.boardflags_lo & BGMAC_BFL_ENETADM)
 | |
| -		dev_warn(bgmac->dev, "Support for ADMtek ethernet switch not implemented\n");
 | |
| -
 | |
| -	/* Feature Flags */
 | |
| -	switch (core->bus->chipinfo.id) {
 | |
| -	case BCMA_CHIP_ID_BCM5357:
 | |
| -		bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK;
 | |
| -		bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
 | |
| -		bgmac->feature_flags |= BGMAC_FEAT_FLW_CTRL1;
 | |
| -		bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_PHY;
 | |
| -		if (core->bus->chipinfo.pkg == BCMA_PKG_ID_BCM47186) {
 | |
| -			bgmac->feature_flags |= BGMAC_FEAT_IOST_ATTACHED;
 | |
| -			bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_RGMII;
 | |
| -		}
 | |
| -		if (core->bus->chipinfo.pkg == BCMA_PKG_ID_BCM5358)
 | |
| -			bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_EPHYRMII;
 | |
| -		break;
 | |
| -	case BCMA_CHIP_ID_BCM53572:
 | |
| -		bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK;
 | |
| -		bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
 | |
| -		bgmac->feature_flags |= BGMAC_FEAT_FLW_CTRL1;
 | |
| -		bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_PHY;
 | |
| -		if (core->bus->chipinfo.pkg == BCMA_PKG_ID_BCM47188) {
 | |
| -			bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_RGMII;
 | |
| -			bgmac->feature_flags |= BGMAC_FEAT_IOST_ATTACHED;
 | |
| -		}
 | |
| -		break;
 | |
| -	case BCMA_CHIP_ID_BCM4749:
 | |
| -		bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK;
 | |
| -		bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
 | |
| -		bgmac->feature_flags |= BGMAC_FEAT_FLW_CTRL1;
 | |
| -		bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_PHY;
 | |
| -		if (core->bus->chipinfo.pkg == 10) {
 | |
| -			bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_RGMII;
 | |
| -			bgmac->feature_flags |= BGMAC_FEAT_IOST_ATTACHED;
 | |
| -		}
 | |
| -		break;
 | |
| -	case BCMA_CHIP_ID_BCM4716:
 | |
| -		bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
 | |
| -		/* fallthrough */
 | |
| -	case BCMA_CHIP_ID_BCM47162:
 | |
| -		bgmac->feature_flags |= BGMAC_FEAT_FLW_CTRL2;
 | |
| -		bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK;
 | |
| -		break;
 | |
| -	/* bcm4707_family */
 | |
| -	case BCMA_CHIP_ID_BCM4707:
 | |
| -	case BCMA_CHIP_ID_BCM47094:
 | |
| -	case BCMA_CHIP_ID_BCM53018:
 | |
| -		bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
 | |
| -		bgmac->feature_flags |= BGMAC_FEAT_NO_RESET;
 | |
| -		bgmac->feature_flags |= BGMAC_FEAT_FORCE_SPEED_2500;
 | |
| -		break;
 | |
| -	default:
 | |
| -		bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
 | |
| -		bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK;
 | |
| -	}
 | |
| -
 | |
| -	if (!bgmac_is_bcm4707_family(bgmac) && core->id.rev > 2)
 | |
| -		bgmac->feature_flags |= BGMAC_FEAT_MISC_PLL_REQ;
 | |
| -
 | |
| -	if (core->id.id == BCMA_CORE_4706_MAC_GBIT) {
 | |
| -		bgmac->feature_flags |= BGMAC_FEAT_CMN_PHY_CTL;
 | |
| -		bgmac->feature_flags |= BGMAC_FEAT_NO_CLR_MIB;
 | |
| -	}
 | |
| -
 | |
| -	if (core->id.rev >= 4) {
 | |
| -		bgmac->feature_flags |= BGMAC_FEAT_CMDCFG_SR_REV4;
 | |
| -		bgmac->feature_flags |= BGMAC_FEAT_TX_MASK_SETUP;
 | |
| -		bgmac->feature_flags |= BGMAC_FEAT_RX_MASK_SETUP;
 | |
| -	}
 | |
| -
 | |
|  	netif_napi_add(net_dev, &bgmac->napi, bgmac_poll, BGMAC_WEIGHT);
 | |
|  
 | |
| -	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_mii_unregister;
 | |
| +		goto err_dma_free;
 | |
|  	}
 | |
|  
 | |
|  	net_dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
 | |
| @@ -1715,56 +1522,24 @@ static int bgmac_probe(struct bcma_devic
 | |
|  
 | |
|  err_phy_disconnect:
 | |
|  	phy_disconnect(net_dev->phydev);
 | |
| -err_mii_unregister:
 | |
| -	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);
 | |
|  
 | |
|  	return err;
 | |
|  }
 | |
| +EXPORT_SYMBOL_GPL(bgmac_enet_probe);
 | |
|  
 | |
| -static void bgmac_remove(struct bcma_device *core)
 | |
| +void bgmac_enet_remove(struct bgmac *bgmac)
 | |
|  {
 | |
| -	struct bgmac *bgmac = bcma_get_drvdata(core);
 | |
| -
 | |
|  	unregister_netdev(bgmac->net_dev);
 | |
|  	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);
 | |
|  	free_netdev(bgmac->net_dev);
 | |
|  }
 | |
| -
 | |
| -static struct bcma_driver bgmac_bcma_driver = {
 | |
| -	.name		= KBUILD_MODNAME,
 | |
| -	.id_table	= bgmac_bcma_tbl,
 | |
| -	.probe		= bgmac_probe,
 | |
| -	.remove		= bgmac_remove,
 | |
| -};
 | |
| -
 | |
| -static int __init bgmac_init(void)
 | |
| -{
 | |
| -	int err;
 | |
| -
 | |
| -	err = bcma_driver_register(&bgmac_bcma_driver);
 | |
| -	if (err)
 | |
| -		return err;
 | |
| -	pr_info("Broadcom 47xx GBit MAC driver loaded\n");
 | |
| -
 | |
| -	return 0;
 | |
| -}
 | |
| -
 | |
| -static void __exit bgmac_exit(void)
 | |
| -{
 | |
| -	bcma_driver_unregister(&bgmac_bcma_driver);
 | |
| -}
 | |
| -
 | |
| -module_init(bgmac_init)
 | |
| -module_exit(bgmac_exit)
 | |
| +EXPORT_SYMBOL_GPL(bgmac_enet_remove);
 | |
|  
 | |
|  MODULE_AUTHOR("Rafał Miłecki");
 | |
|  MODULE_LICENSE("GPL");
 | |
| --- a/drivers/net/ethernet/broadcom/bgmac.h
 | |
| +++ b/drivers/net/ethernet/broadcom/bgmac.h
 | |
| @@ -1,8 +1,6 @@
 | |
|  #ifndef _BGMAC_H
 | |
|  #define _BGMAC_H
 | |
|  
 | |
| -#include <linux/bcma/bcma.h>
 | |
| -#include <linux/brcmphy.h>
 | |
|  #include <linux/netdevice.h>
 | |
|  
 | |
|  #define BGMAC_DEV_CTL				0x000
 | |
| @@ -442,11 +440,21 @@ struct bgmac_rx_header {
 | |
|  };
 | |
|  
 | |
|  struct bgmac {
 | |
| -	struct bcma_device *core;
 | |
| -	struct bcma_device *cmn; /* Reference to CMN core for BCM4706 */
 | |
| +	union {
 | |
| +		struct {
 | |
| +			void *base;
 | |
| +			void *idm_base;
 | |
| +		} plat;
 | |
| +		struct {
 | |
| +			struct bcma_device *core;
 | |
| +			/* Reference to CMN core for BCM4706 */
 | |
| +			struct bcma_device *cmn;
 | |
| +		} bcma;
 | |
| +	};
 | |
|  
 | |
|  	struct device *dev;
 | |
|  	struct device *dma_dev;
 | |
| +	unsigned char mac_addr[ETH_ALEN];
 | |
|  	u32 feature_flags;
 | |
|  
 | |
|  	struct net_device *net_dev;
 | |
| @@ -463,6 +471,7 @@ struct bgmac {
 | |
|  	u32 mib_rx_regs[BGMAC_NUM_MIB_RX_REGS];
 | |
|  
 | |
|  	/* Int */
 | |
| +	int irq;
 | |
|  	u32 int_mask;
 | |
|  
 | |
|  	/* Current MAC state */
 | |
| @@ -473,19 +482,71 @@ struct bgmac {
 | |
|  	bool has_robosw;
 | |
|  
 | |
|  	bool loopback;
 | |
| +
 | |
| +	u32 (*read)(struct bgmac *bgmac, u16 offset);
 | |
| +	void (*write)(struct bgmac *bgmac, u16 offset, u32 value);
 | |
| +	u32 (*idm_read)(struct bgmac *bgmac, u16 offset);
 | |
| +	void (*idm_write)(struct bgmac *bgmac, u16 offset, u32 value);
 | |
| +	bool (*clk_enabled)(struct bgmac *bgmac);
 | |
| +	void (*clk_enable)(struct bgmac *bgmac, u32 flags);
 | |
| +	void (*cco_ctl_maskset)(struct bgmac *bgmac, u32 offset, u32 mask,
 | |
| +				u32 set);
 | |
| +	u32 (*get_bus_clock)(struct bgmac *bgmac);
 | |
| +	void (*cmn_maskset32)(struct bgmac *bgmac, u16 offset, u32 mask,
 | |
| +			      u32 set);
 | |
|  };
 | |
|  
 | |
| +int bgmac_enet_probe(struct bgmac *info);
 | |
| +void bgmac_enet_remove(struct bgmac *bgmac);
 | |
| +
 | |
|  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);
 | |
| +	return bgmac->read(bgmac, offset);
 | |
|  }
 | |
|  
 | |
|  static inline void bgmac_write(struct bgmac *bgmac, u16 offset, u32 value)
 | |
|  {
 | |
| -	bcma_write32(bgmac->core, offset, value);
 | |
| +	bgmac->write(bgmac, offset, value);
 | |
| +}
 | |
| +
 | |
| +static inline u32 bgmac_idm_read(struct bgmac *bgmac, u16 offset)
 | |
| +{
 | |
| +	return bgmac->idm_read(bgmac, offset);
 | |
| +}
 | |
| +
 | |
| +static inline void bgmac_idm_write(struct bgmac *bgmac, u16 offset, u32 value)
 | |
| +{
 | |
| +	bgmac->idm_write(bgmac, offset, value);
 | |
| +}
 | |
| +
 | |
| +static inline bool bgmac_clk_enabled(struct bgmac *bgmac)
 | |
| +{
 | |
| +	return bgmac->clk_enabled(bgmac);
 | |
| +}
 | |
| +
 | |
| +static inline void bgmac_clk_enable(struct bgmac *bgmac, u32 flags)
 | |
| +{
 | |
| +	bgmac->clk_enable(bgmac, flags);
 | |
| +}
 | |
| +
 | |
| +static inline void bgmac_cco_ctl_maskset(struct bgmac *bgmac, u32 offset,
 | |
| +					 u32 mask, u32 set)
 | |
| +{
 | |
| +	bgmac->cco_ctl_maskset(bgmac, offset, mask, set);
 | |
| +}
 | |
| +
 | |
| +static inline u32 bgmac_get_bus_clock(struct bgmac *bgmac)
 | |
| +{
 | |
| +	return bgmac->get_bus_clock(bgmac);
 | |
| +}
 | |
| +
 | |
| +static inline void bgmac_cmn_maskset32(struct bgmac *bgmac, u16 offset,
 | |
| +				       u32 mask, u32 set)
 | |
| +{
 | |
| +	bgmac->cmn_maskset32(bgmac, offset, mask, set);
 | |
|  }
 | |
|  
 | |
|  static inline void bgmac_maskset(struct bgmac *bgmac, u16 offset, u32 mask,
 |