summaryrefslogtreecommitdiff
path: root/target/linux/brcm47xx/patches-3.10/770-bgmac-phylib.patch
diff options
context:
space:
mode:
authorhauke <hauke@3c298f89-4303-0410-b956-a3cf2f4a3e73>2013-07-14 14:11:17 +0000
committerhauke <hauke@3c298f89-4303-0410-b956-a3cf2f4a3e73>2013-07-14 14:11:17 +0000
commit35105c1dc8f39291c36e259395609526a3a2b379 (patch)
treead814fb72ced6e4876aae62bf0d3a5aec6fba17d /target/linux/brcm47xx/patches-3.10/770-bgmac-phylib.patch
parent3608b41c366112ace92c00b16a818727c4881240 (diff)
brcm47xx: use b53 phy driver for the switch in kernel 3.10
This makes it possible to use swconfig to controll the switch. This was tested with devices using b43 and bgmac. This was not tested on devices using tg3. This does not support the adm switch used in some very old devices. git-svn-id: svn://svn.openwrt.org/openwrt/trunk@37304 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/brcm47xx/patches-3.10/770-bgmac-phylib.patch')
-rw-r--r--target/linux/brcm47xx/patches-3.10/770-bgmac-phylib.patch208
1 files changed, 208 insertions, 0 deletions
diff --git a/target/linux/brcm47xx/patches-3.10/770-bgmac-phylib.patch b/target/linux/brcm47xx/patches-3.10/770-bgmac-phylib.patch
new file mode 100644
index 0000000000..6041d2a77a
--- /dev/null
+++ b/target/linux/brcm47xx/patches-3.10/770-bgmac-phylib.patch
@@ -0,0 +1,208 @@
+--- a/drivers/net/ethernet/broadcom/Kconfig
++++ b/drivers/net/ethernet/broadcom/Kconfig
+@@ -133,6 +133,7 @@ config BNX2X_SRIOV
+ config BGMAC
+ tristate "BCMA bus GBit core support"
+ depends on BCMA_HOST_SOC && HAS_DMA
++ select PHYLIB
+ ---help---
+ This driver supports GBit MAC and BCM4706 GBit MAC cores on BCMA bus.
+ They can be found on BCM47xx SoCs and provide gigabit ethernet.
+--- a/drivers/net/ethernet/broadcom/bgmac.c
++++ b/drivers/net/ethernet/broadcom/bgmac.c
+@@ -1201,27 +1201,14 @@ static int bgmac_set_mac_address(struct
+ static int bgmac_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
+ {
+ struct bgmac *bgmac = netdev_priv(net_dev);
+- struct mii_ioctl_data *data = if_mii(ifr);
+
+- switch (cmd) {
+- case SIOCGMIIPHY:
+- data->phy_id = bgmac->phyaddr;
+- /* fallthru */
+- case SIOCGMIIREG:
+- if (!netif_running(net_dev))
+- return -EAGAIN;
+- data->val_out = bgmac_phy_read(bgmac, data->phy_id,
+- data->reg_num & 0x1f);
+- return 0;
+- case SIOCSMIIREG:
+- if (!netif_running(net_dev))
+- return -EAGAIN;
+- bgmac_phy_write(bgmac, data->phy_id, data->reg_num & 0x1f,
+- data->val_in);
+- return 0;
+- default:
+- return -EOPNOTSUPP;
+- }
++ if (!netif_running(net_dev))
++ return -EINVAL;
++
++ if (!bgmac->phydev)
++ return -EINVAL;
++
++ return phy_mii_ioctl(bgmac->phydev, ifr, cmd);
+ }
+
+ static const struct net_device_ops bgmac_netdev_ops = {
+@@ -1243,61 +1230,18 @@ static int bgmac_get_settings(struct net
+ {
+ struct bgmac *bgmac = netdev_priv(net_dev);
+
+- cmd->supported = SUPPORTED_10baseT_Half |
+- SUPPORTED_10baseT_Full |
+- SUPPORTED_100baseT_Half |
+- SUPPORTED_100baseT_Full |
+- SUPPORTED_1000baseT_Half |
+- SUPPORTED_1000baseT_Full |
+- SUPPORTED_Autoneg;
+-
+- if (bgmac->autoneg) {
+- WARN_ON(cmd->advertising);
+- if (bgmac->full_duplex) {
+- if (bgmac->speed & BGMAC_SPEED_10)
+- cmd->advertising |= ADVERTISED_10baseT_Full;
+- if (bgmac->speed & BGMAC_SPEED_100)
+- cmd->advertising |= ADVERTISED_100baseT_Full;
+- if (bgmac->speed & BGMAC_SPEED_1000)
+- cmd->advertising |= ADVERTISED_1000baseT_Full;
+- } else {
+- if (bgmac->speed & BGMAC_SPEED_10)
+- cmd->advertising |= ADVERTISED_10baseT_Half;
+- if (bgmac->speed & BGMAC_SPEED_100)
+- cmd->advertising |= ADVERTISED_100baseT_Half;
+- if (bgmac->speed & BGMAC_SPEED_1000)
+- cmd->advertising |= ADVERTISED_1000baseT_Half;
+- }
+- } else {
+- switch (bgmac->speed) {
+- case BGMAC_SPEED_10:
+- ethtool_cmd_speed_set(cmd, SPEED_10);
+- break;
+- case BGMAC_SPEED_100:
+- ethtool_cmd_speed_set(cmd, SPEED_100);
+- break;
+- case BGMAC_SPEED_1000:
+- ethtool_cmd_speed_set(cmd, SPEED_1000);
+- break;
+- }
+- }
+-
+- cmd->duplex = bgmac->full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
+-
+- cmd->autoneg = bgmac->autoneg;
+-
+- return 0;
++ return phy_ethtool_gset(bgmac->phydev, cmd);
+ }
+
+-#if 0
++
+ static int bgmac_set_settings(struct net_device *net_dev,
+ struct ethtool_cmd *cmd)
+ {
+ struct bgmac *bgmac = netdev_priv(net_dev);
+
+- return -1;
++ return phy_ethtool_sset(bgmac->phydev, cmd);
+ }
+-#endif
++
+
+ static void bgmac_get_drvinfo(struct net_device *net_dev,
+ struct ethtool_drvinfo *info)
+@@ -1308,6 +1252,7 @@ static void bgmac_get_drvinfo(struct net
+
+ static const struct ethtool_ops bgmac_ethtool_ops = {
+ .get_settings = bgmac_get_settings,
++ .set_settings = bgmac_set_settings,
+ .get_drvinfo = bgmac_get_drvinfo,
+ };
+
+@@ -1326,10 +1271,42 @@ static int bgmac_mii_write(struct mii_bu
+ return bgmac_phy_write(bus->priv, mii_id, regnum, value);
+ }
+
++static void bgmac_adjust_link(struct net_device *dev)
++{
++ struct bgmac *bgmac = netdev_priv(dev);
++ struct phy_device *phydev = bgmac->phydev;
++ int status_changed = 0;
++
++ BUG_ON(!phydev);
++
++ if (bgmac->old_link != phydev->link) {
++ status_changed = 1;
++ bgmac->old_link = phydev->link;
++ }
++
++ /* reflect duplex change */
++ if (phydev->link && (bgmac->old_duplex != phydev->duplex)) {
++ status_changed = 1;
++ bgmac->old_duplex = phydev->duplex;
++ }
++
++ if (status_changed) {
++ pr_info("%s: link %s", dev->name, phydev->link ?
++ "UP" : "DOWN");
++ if (phydev->link)
++ pr_cont(" - %d/%s", phydev->speed,
++ phydev->duplex == DUPLEX_FULL ? "full" : "half");
++ pr_cont("\n");
++ }
++}
++
+ static int bgmac_mii_register(struct bgmac *bgmac)
+ {
+ struct mii_bus *mii_bus;
+ int i, err = 0;
++ struct phy_device *phydev = NULL;
++ char phy_id[MII_BUS_ID_SIZE + 3];
++ struct net_device *net_dev = bgmac->net_dev;
+
+ mii_bus = mdiobus_alloc();
+ if (!mii_bus)
+@@ -1360,7 +1337,29 @@ static int bgmac_mii_register(struct bgm
+
+ bgmac->mii_bus = mii_bus;
+
+- return err;
++ /* connect to PHY */
++ snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
++ mii_bus->id, bgmac->phyaddr);
++
++ phydev = phy_connect(net_dev, phy_id, &bgmac_adjust_link,
++ PHY_INTERFACE_MODE_MII);
++
++ if (IS_ERR(phydev)) {
++ netdev_err(net_dev, "could not attach PHY: %s", phy_id);
++ bgmac->phyaddr = BGMAC_PHY_NOREGS;
++ return PTR_ERR(phydev);
++ }
++
++ bgmac->phydev = phydev;
++ bgmac->old_link = 0;
++ bgmac->old_duplex = -1;
++ bgmac->phyaddr = phydev->addr;
++
++ netdev_info(net_dev, "attached PHY driver [%s] "
++ "(mii_bus:phy_addr=%s)\n",
++ phydev->drv->name, dev_name(&phydev->dev));
++
++ return 0;
+
+ err_free_irq:
+ kfree(mii_bus->irq);
+--- a/drivers/net/ethernet/broadcom/bgmac.h
++++ b/drivers/net/ethernet/broadcom/bgmac.h
+@@ -399,7 +399,10 @@ struct bgmac {
+ struct bcma_device *cmn; /* Reference to CMN core for BCM4706 */
+ struct net_device *net_dev;
+ struct napi_struct napi;
++ struct phy_device *phydev;
+ struct mii_bus *mii_bus;
++ int old_link;
++ int old_duplex;
+
+ /* DMA */
+ struct bgmac_dma_ring tx_ring[BGMAC_MAX_TX_RINGS];