static int bcma_hcd_probe(struct bcma_device *core) { int err; struct bcma_hcd_device *usb_dev; /* TODO: Probably need checks here; is the core connected? */ usb_dev = devm_kzalloc(&core->dev, sizeof(struct bcma_hcd_device), GFP_KERNEL); if (!usb_dev) return -ENOMEM; usb_dev->core = core; if (core->dev.of_node) usb_dev->gpio_desc = devm_get_gpiod_from_child(&core->dev, "vcc", &core->dev.of_node->fwnode); if (!IS_ERR_OR_NULL(usb_dev->gpio_desc)) gpiod_direction_output(usb_dev->gpio_desc, 1); switch (core->id.id) { case BCMA_CORE_USB20_HOST: case BCMA_CORE_NS_USB20: err = bcma_hcd_usb20_init(usb_dev); if (err) return err; break; default: return -ENODEV; } bcma_set_drvdata(core, usb_dev); return 0; }
static int wl_glue_bcma_probe(struct bcma_device *dev) { void *mmio; void *wldev; if (!attach_cb) { pr_err("No attach callback registered\n"); return -ENOSYS; } if (dev->bus->hosttype != BCMA_HOSTTYPE_SOC) { pr_err("Unsupported BCMA bus type %d\n", dev->bus->hosttype); return -EINVAL; } /* * NB: * 0x18000000 = BCMA_ADDR_BASE * 0x1000 = BCMA_CORE_SIZE */ mmio = (void *) 0x18000000 + dev->core_index * 0x1000; wldev = attach_cb(dev->id.manuf, dev->id.id, (ulong)mmio, dev, dev->irq); if (!wldev) { pr_err("The attach callback failed, BCMA probe aborted\n"); return -ENODEV; } bcma_set_drvdata(dev, wldev); return 0; }
/** * determines if a device is a WL device, and if so, attaches it. * * This function determines if a device pointed to by pdev is a WL device, * and if so, performs a brcms_attach() on it. * * Perimeter lock is initialized in the course of this function. */ static int brcms_bcma_probe(struct bcma_device *pdev) { struct brcms_info *wl; struct ieee80211_hw *hw; dev_info(&pdev->dev, "mfg %x core %x rev %d class %d irq %d\n", pdev->id.manuf, pdev->id.id, pdev->id.rev, pdev->id.class, pdev->irq); if ((pdev->id.manuf != BCMA_MANUF_BCM) || (pdev->id.id != BCMA_CORE_80211)) return -ENODEV; hw = ieee80211_alloc_hw(sizeof(struct brcms_info), &brcms_ops); if (!hw) { pr_err("%s: ieee80211_alloc_hw failed\n", __func__); return -ENOMEM; } SET_IEEE80211_DEV(hw, &pdev->dev); bcma_set_drvdata(pdev, hw); memset(hw->priv, 0, sizeof(*wl)); wl = brcms_attach(pdev); if (!wl) { pr_err("%s: brcms_attach failed!\n", __func__); return -ENODEV; } brcms_led_register(wl); return 0; }
static int bcma_hcd_probe(struct bcma_device *dev) { int err; u32 ohci_addr; struct bcma_hcd_device *usb_dev; struct bcma_chipinfo *chipinfo; chipinfo = &dev->bus->chipinfo; /* TODO: Probably need checks here; is the core connected? */ if (dma_set_mask_and_coherent(dev->dma_dev, DMA_BIT_MASK(32))) return -EOPNOTSUPP; usb_dev = devm_kzalloc(&dev->dev, sizeof(struct bcma_hcd_device), GFP_KERNEL); if (!usb_dev) return -ENOMEM; if (dev->dev.of_node) usb_dev->gpio_desc = devm_get_gpiod_from_child(&dev->dev, "vcc", &dev->dev.of_node->fwnode); if (!IS_ERR_OR_NULL(usb_dev->gpio_desc)) gpiod_direction_output(usb_dev->gpio_desc, 1); switch (dev->id.id) { case BCMA_CORE_NS_USB20: bcma_hcd_init_chip_arm(dev); break; case BCMA_CORE_USB20_HOST: bcma_hcd_init_chip_mips(dev); break; default: return -ENODEV; } /* In AI chips EHCI is addrspace 0, OHCI is 1 */ ohci_addr = dev->addr_s[0]; if ((chipinfo->id == BCMA_CHIP_ID_BCM5357 || chipinfo->id == BCMA_CHIP_ID_BCM4749) && chipinfo->rev == 0) ohci_addr = 0x18009000; usb_dev->ohci_dev = bcma_hcd_create_pdev(dev, true, ohci_addr); if (IS_ERR(usb_dev->ohci_dev)) return PTR_ERR(usb_dev->ohci_dev); usb_dev->ehci_dev = bcma_hcd_create_pdev(dev, false, dev->addr); if (IS_ERR(usb_dev->ehci_dev)) { err = PTR_ERR(usb_dev->ehci_dev); goto err_unregister_ohci_dev; } bcma_set_drvdata(dev, usb_dev); return 0; err_unregister_ohci_dev: platform_device_unregister(usb_dev->ohci_dev); return err; }
static void wl_glue_bcma_remove(struct bcma_device *dev) { void *wldev = bcma_get_drvdata(dev); if (remove_cb) remove_cb(wldev); bcma_set_drvdata(dev, NULL); }
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 void bgmac_remove(struct bcma_device *core) { struct bgmac *bgmac = bcma_get_drvdata(core); netif_napi_del(&bgmac->napi); unregister_netdev(bgmac->net_dev); bgmac_mii_unregister(bgmac); bgmac_dma_free(bgmac); bcma_set_drvdata(core, NULL); free_netdev(bgmac->net_dev); }
void b43_bus_set_wldev(struct b43_bus_dev *dev, void *wldev) { switch (dev->bus_type) { #ifdef CONFIG_B43_BCMA case B43_BUS_BCMA: bcma_set_drvdata(dev->bdev, wldev); break; #endif #ifdef CONFIG_B43_SSB case B43_BUS_SSB: ssb_set_drvdata(dev->sdev, wldev); break; #endif } }
static int bcm53xxspi_bcma_probe(struct bcma_device *core) { struct bcm53xxspi *b53spi; struct spi_master *master; int err; if (core->bus->drv_cc.core->id.rev != 42) { pr_err("SPI on SoC with unsupported ChipCommon rev\n"); return -ENOTSUPP; } master = spi_alloc_master(&core->dev, sizeof(*b53spi)); if (!master) return -ENOMEM; b53spi = spi_master_get_devdata(master); b53spi->master = master; b53spi->core = core; master->transfer_one = bcm53xxspi_transfer_one; bcma_set_drvdata(core, b53spi); err = devm_spi_register_master(&core->dev, master); if (err) { spi_master_put(master); bcma_set_drvdata(core, NULL); goto out; } /* Broadcom SoCs (at least with the CC rev 42) use SPI for flash only */ spi_new_device(master, &bcm53xx_info); out: return err; }
/* * called from both kernel as from this kernel module (error flow on attach) * precondition: perimeter lock is not acquired. */ static void brcms_remove(struct bcma_device *pdev) { struct ieee80211_hw *hw = bcma_get_drvdata(pdev); struct brcms_info *wl = hw->priv; if (wl->wlc) { wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false); wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); ieee80211_unregister_hw(hw); } brcms_free(wl); bcma_set_drvdata(pdev, NULL); ieee80211_free_hw(hw); }
static int bgmac_fixed_phy_register(struct bgmac *bgmac) { struct fixed_phy_status fphy_status = { .link = 1, .speed = SPEED_1000, .duplex = DUPLEX_FULL, }; struct phy_device *phy_dev; int err; phy_dev = fixed_phy_register(PHY_POLL, &fphy_status, -1, NULL); if (!phy_dev || IS_ERR(phy_dev)) { bgmac_err(bgmac, "Failed to register fixed PHY device\n"); return -ENODEV; } err = phy_connect_direct(bgmac->net_dev, phy_dev, bgmac_adjust_link, PHY_INTERFACE_MODE_MII); if (err) { bgmac_err(bgmac, "Connecting PHY failed\n"); return err; } bgmac->phy_dev = phy_dev; return err; } static int bgmac_mii_register(struct bgmac *bgmac) { struct mii_bus *mii_bus; struct phy_device *phy_dev; char bus_id[MII_BUS_ID_SIZE + 3]; int 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); err = mdiobus_register(mii_bus); if (err) { bgmac_err(bgmac, "Registration of mii bus failed\n"); goto err_free_bus; } bgmac->mii_bus = mii_bus; /* Connect to the PHY */ snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, 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)) { bgmac_err(bgmac, "PHY connection failed\n"); err = PTR_ERR(phy_dev); goto err_unregister_bus; } bgmac->phy_dev = phy_dev; return err; err_unregister_bus: mdiobus_unregister(mii_bus); 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); mdiobus_free(mii_bus); } /************************************************** * 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; 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: pr_err("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->net_dev = net_dev; bgmac->core = core; bcma_set_drvdata(core, bgmac); /* 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) { bgmac_err(bgmac, "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) { bgmac_err(bgmac, "No PHY found\n"); err = -ENODEV; goto err_netdev_free; } bgmac_info(bgmac, "Found PHY addr: %d%s\n", bgmac->phyaddr, bgmac->phyaddr == BGMAC_PHY_NOREGS ? " (NOREGS)" : ""); if (core->bus->hosttype == BCMA_HOSTTYPE_PCI) { bgmac_err(bgmac, "PCI setup not implemented\n"); err = -ENOTSUPP; goto err_netdev_free; } 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) { bgmac_err(bgmac, "Unable to alloc memory for DMA\n"); goto err_netdev_free; } bgmac->int_mask = BGMAC_IS_ERRMASK | BGMAC_IS_RX | BGMAC_IS_TX_MASK; 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) bgmac_warn(bgmac, "Support for Roboswitch not implemented\n"); if (core->bus->sprom.boardflags_lo & BGMAC_BFL_ENETADM) bgmac_warn(bgmac, "Support for ADMtek ethernet switch not implemented\n"); netif_napi_add(net_dev, &bgmac->napi, bgmac_poll, BGMAC_WEIGHT); err = bgmac_mii_register(bgmac); if (err) { bgmac_err(bgmac, "Cannot register MDIO\n"); goto err_dma_free; } net_dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; net_dev->hw_features = net_dev->features; net_dev->vlan_features = net_dev->features; err = register_netdev(bgmac->net_dev); if (err) { bgmac_err(bgmac, "Cannot register net device\n"); goto err_mii_unregister; } netif_carrier_off(net_dev); return 0; err_mii_unregister: bgmac_mii_unregister(bgmac); err_dma_free: bgmac_dma_free(bgmac); err_netdev_free: bcma_set_drvdata(core, NULL); free_netdev(net_dev); return err; } static void bgmac_remove(struct bcma_device *core) { struct bgmac *bgmac = bcma_get_drvdata(core); unregister_netdev(bgmac->net_dev); bgmac_mii_unregister(bgmac); 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; }
/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipattach */ static int bgmac_probe(struct bcma_device *core) { struct net_device *net_dev; struct bgmac *bgmac; struct ssb_sprom *sprom = &core->bus->sprom; u8 *mac = core->core_unit ? sprom->et1mac : sprom->et0mac; int err; /* We don't support 2nd, 3rd, ... units, SPROM has to be adjusted */ if (core->core_unit > 1) { pr_err("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); } /* 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; SET_ETHTOOL_OPS(net_dev, &bgmac_ethtool_ops); bgmac = netdev_priv(net_dev); bgmac->net_dev = net_dev; bgmac->core = core; bcma_set_drvdata(core, bgmac); /* 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) { bgmac_err(bgmac, "GMAC CMN core not found (required for BCM4706)\n"); err = -ENODEV; goto err_netdev_free; } bgmac->cmn = core->bus->drv_gmac_cmn.core; bgmac->phyaddr = core->core_unit ? sprom->et1phyaddr : sprom->et0phyaddr; bgmac->phyaddr &= BGMAC_PHY_MASK; if (bgmac->phyaddr == BGMAC_PHY_MASK) { bgmac_err(bgmac, "No PHY found\n"); err = -ENODEV; goto err_netdev_free; } bgmac_info(bgmac, "Found PHY addr: %d%s\n", bgmac->phyaddr, bgmac->phyaddr == BGMAC_PHY_NOREGS ? " (NOREGS)" : ""); if (core->bus->hosttype == BCMA_HOSTTYPE_PCI) { bgmac_err(bgmac, "PCI setup not implemented\n"); err = -ENOTSUPP; goto err_netdev_free; } bgmac_chip_reset(bgmac); /* For Northstar, we have to take all GMAC core out of reset */ if (core->id.id == BCMA_CHIP_ID_BCM4707 || core->id.id == BCMA_CHIP_ID_BCM53018) { 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) { bgmac_err(bgmac, "Unable to alloc memory for DMA\n"); goto err_netdev_free; } bgmac->int_mask = BGMAC_IS_ERRMASK | BGMAC_IS_RX | BGMAC_IS_TX_MASK; 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) bgmac_warn(bgmac, "Support for Roboswitch not implemented\n"); if (core->bus->sprom.boardflags_lo & BGMAC_BFL_ENETADM) bgmac_warn(bgmac, "Support for ADMtek ethernet switch not implemented\n"); err = bgmac_mii_register(bgmac); if (err) { bgmac_err(bgmac, "Cannot register MDIO\n"); goto err_dma_free; } err = register_netdev(bgmac->net_dev); if (err) { bgmac_err(bgmac, "Cannot register net device\n"); goto err_mii_unregister; } netif_carrier_off(net_dev); netif_napi_add(net_dev, &bgmac->napi, bgmac_poll, BGMAC_WEIGHT); return 0; err_mii_unregister: bgmac_mii_unregister(bgmac); err_dma_free: bgmac_dma_free(bgmac); err_netdev_free: bcma_set_drvdata(core, NULL); free_netdev(net_dev); return err; }
/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipattach */ static int bgmac_probe(struct bcma_device *core) { struct bcma_chipinfo *ci = &core->bus->chipinfo; struct ssb_sprom *sprom = &core->bus->sprom; struct mii_bus *mii_bus; struct bgmac *bgmac; const u8 *mac = NULL; int err; bgmac = bgmac_alloc(&core->dev); if (!bgmac) return -ENOMEM; bgmac->bcma.core = core; bgmac->dma_dev = core->dma_dev; bgmac->irq = core->irq; bcma_set_drvdata(core, bgmac); if (bgmac->dev->of_node) mac = of_get_mac_address(bgmac->dev->of_node); /* If no MAC address assigned via device tree, check SPROM */ if (IS_ERR_OR_NULL(mac)) { 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->net_dev->dev_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) && !(ci->id == BCMA_CHIP_ID_BCM53573 && core->core_unit == 1)) { struct phy_device *phydev; mii_bus = bcma_mdio_mii_register(bgmac); if (IS_ERR(mii_bus)) { err = PTR_ERR(mii_bus); goto err; } bgmac->mii_bus = mii_bus; phydev = mdiobus_get_phy(bgmac->mii_bus, bgmac->phyaddr); if (ci->id == BCMA_CHIP_ID_BCM53573 && phydev && (phydev->drv->phy_id & phydev->drv->phy_id_mask) == PHY_ID_BCM54210E) phydev->dev_flags |= PHY_BRCM_EN_MASTER_MODE; } if (core->bus->hosttype == BCMA_HOSTTYPE_PCI) { dev_err(bgmac->dev, "PCI setup not implemented\n"); err = -ENOTSUPP; goto err1; } bgmac->has_robosw = !!(sprom->boardflags_lo & BGMAC_BFL_ENETROBO); if (bgmac->has_robosw) dev_warn(bgmac->dev, "Support for Roboswitch not implemented\n"); if (sprom->boardflags_lo & BGMAC_BFL_ENETADM) dev_warn(bgmac->dev, "Support for ADMtek ethernet switch not implemented\n"); /* Feature Flags */ switch (ci->id) { /* BCM 471X/535X family */ 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; case BCMA_CHIP_ID_BCM5357: 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 (ci->pkg == BCMA_PKG_ID_BCM47188 || ci->pkg == BCMA_PKG_ID_BCM47186) { bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_RGMII; bgmac->feature_flags |= BGMAC_FEAT_IOST_ATTACHED; } if (ci->pkg == BCMA_PKG_ID_BCM5358) bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_EPHYRMII; break; case BCMA_CHIP_ID_BCM53573: bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST; bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK; if (ci->pkg == BCMA_PKG_ID_BCM47189) bgmac->feature_flags |= BGMAC_FEAT_IOST_ATTACHED; if (core->core_unit == 0) { bgmac->feature_flags |= BGMAC_FEAT_CC4_IF_SW_TYPE; if (ci->pkg == BCMA_PKG_ID_BCM47189) bgmac->feature_flags |= BGMAC_FEAT_CC4_IF_SW_TYPE_RGMII; } else if (core->core_unit == 1) { bgmac->feature_flags |= BGMAC_FEAT_IRQ_ID_OOB_6; bgmac->feature_flags |= BGMAC_FEAT_CC7_IF_TYPE_RGMII; } 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 (ci->pkg == 10) { bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_RGMII; bgmac->feature_flags |= BGMAC_FEAT_IOST_ATTACHED; } 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; if (bgmac->mii_bus) bgmac->phy_connect = bcma_phy_connect; else bgmac->phy_connect = bgmac_phy_connect_direct; err = bgmac_enet_probe(bgmac); if (err) goto err1; return 0; err1: bcma_mdio_mii_unregister(bgmac->mii_bus); err: bcma_set_drvdata(core, NULL); return err; }