diff options
Diffstat (limited to 'drivers/net/ethernet/broadcom/bgmac.c')
-rw-r--r-- | drivers/net/ethernet/broadcom/bgmac.c | 329 |
1 files changed, 52 insertions, 277 deletions
diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c index 770796a628e5..13b072591332 100644 --- 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 bgmac *bgmac, struct bgmac_dma_ring *ring) /* 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 bgmac *bgmac, struct bgmac_dma_ring *ring) 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 *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 *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 *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 bgmac *bgmac) /* 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 bgmac *bgmac) 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 bgmac *bgmac) 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 bgmac *bgmac) 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 *bgmac) 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 *bgmac) 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 *net_dev) /* 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 *net_dev) 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); @@ -1380,7 +1350,7 @@ static void bgmac_get_drvinfo(struct net_device *net_dev, 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 = { @@ -1464,116 +1434,41 @@ static int bgmac_phy_connect(struct bgmac *bgmac) 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; - - 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_netdev_free; + net_dev->irq = bgmac->irq; + SET_NETDEV_DEV(net_dev, bgmac->dev); + + 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); } - 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"); @@ -1584,103 +1479,15 @@ static int bgmac_probe(struct bcma_device *core) 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; @@ -1699,56 +1506,24 @@ static int bgmac_probe(struct bcma_device *core) 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"); |