brcm47xx: use b53 phy driver for the switch in kernel 3.10
[openwrt.git] / target / linux / brcm47xx / patches-3.10 / 770-bgmac-phylib.patch
1 --- a/drivers/net/ethernet/broadcom/Kconfig
2 +++ b/drivers/net/ethernet/broadcom/Kconfig
3 @@ -133,6 +133,7 @@ config BNX2X_SRIOV
4  config BGMAC
5         tristate "BCMA bus GBit core support"
6         depends on BCMA_HOST_SOC && HAS_DMA
7 +       select PHYLIB
8         ---help---
9           This driver supports GBit MAC and BCM4706 GBit MAC cores on BCMA bus.
10           They can be found on BCM47xx SoCs and provide gigabit ethernet.
11 --- a/drivers/net/ethernet/broadcom/bgmac.c
12 +++ b/drivers/net/ethernet/broadcom/bgmac.c
13 @@ -1201,27 +1201,14 @@ static int bgmac_set_mac_address(struct
14  static int bgmac_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
15  {
16         struct bgmac *bgmac = netdev_priv(net_dev);
17 -       struct mii_ioctl_data *data = if_mii(ifr);
18  
19 -       switch (cmd) {
20 -       case SIOCGMIIPHY:
21 -               data->phy_id = bgmac->phyaddr;
22 -               /* fallthru */
23 -       case SIOCGMIIREG:
24 -               if (!netif_running(net_dev))
25 -                       return -EAGAIN;
26 -               data->val_out = bgmac_phy_read(bgmac, data->phy_id,
27 -                                              data->reg_num & 0x1f);
28 -               return 0;
29 -       case SIOCSMIIREG:
30 -               if (!netif_running(net_dev))
31 -                       return -EAGAIN;
32 -               bgmac_phy_write(bgmac, data->phy_id, data->reg_num & 0x1f,
33 -                               data->val_in);
34 -               return 0;
35 -       default:
36 -               return -EOPNOTSUPP;
37 -       }
38 +       if (!netif_running(net_dev))
39 +               return -EINVAL;
40 +
41 +       if (!bgmac->phydev)
42 +               return -EINVAL;
43 +
44 +       return phy_mii_ioctl(bgmac->phydev, ifr, cmd);
45  }
46  
47  static const struct net_device_ops bgmac_netdev_ops = {
48 @@ -1243,61 +1230,18 @@ static int bgmac_get_settings(struct net
49  {
50         struct bgmac *bgmac = netdev_priv(net_dev);
51  
52 -       cmd->supported = SUPPORTED_10baseT_Half |
53 -                        SUPPORTED_10baseT_Full |
54 -                        SUPPORTED_100baseT_Half |
55 -                        SUPPORTED_100baseT_Full |
56 -                        SUPPORTED_1000baseT_Half |
57 -                        SUPPORTED_1000baseT_Full |
58 -                        SUPPORTED_Autoneg;
59 -
60 -       if (bgmac->autoneg) {
61 -               WARN_ON(cmd->advertising);
62 -               if (bgmac->full_duplex) {
63 -                       if (bgmac->speed & BGMAC_SPEED_10)
64 -                               cmd->advertising |= ADVERTISED_10baseT_Full;
65 -                       if (bgmac->speed & BGMAC_SPEED_100)
66 -                               cmd->advertising |= ADVERTISED_100baseT_Full;
67 -                       if (bgmac->speed & BGMAC_SPEED_1000)
68 -                               cmd->advertising |= ADVERTISED_1000baseT_Full;
69 -               } else {
70 -                       if (bgmac->speed & BGMAC_SPEED_10)
71 -                               cmd->advertising |= ADVERTISED_10baseT_Half;
72 -                       if (bgmac->speed & BGMAC_SPEED_100)
73 -                               cmd->advertising |= ADVERTISED_100baseT_Half;
74 -                       if (bgmac->speed & BGMAC_SPEED_1000)
75 -                               cmd->advertising |= ADVERTISED_1000baseT_Half;
76 -               }
77 -       } else {
78 -               switch (bgmac->speed) {
79 -               case BGMAC_SPEED_10:
80 -                       ethtool_cmd_speed_set(cmd, SPEED_10);
81 -                       break;
82 -               case BGMAC_SPEED_100:
83 -                       ethtool_cmd_speed_set(cmd, SPEED_100);
84 -                       break;
85 -               case BGMAC_SPEED_1000:
86 -                       ethtool_cmd_speed_set(cmd, SPEED_1000);
87 -                       break;
88 -               }
89 -       }
90 -
91 -       cmd->duplex = bgmac->full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
92 -
93 -       cmd->autoneg = bgmac->autoneg;
94 -
95 -       return 0;
96 +       return phy_ethtool_gset(bgmac->phydev, cmd);
97  }
98  
99 -#if 0
100 +
101  static int bgmac_set_settings(struct net_device *net_dev,
102                               struct ethtool_cmd *cmd)
103  {
104         struct bgmac *bgmac = netdev_priv(net_dev);
105  
106 -       return -1;
107 +       return phy_ethtool_sset(bgmac->phydev, cmd);
108  }
109 -#endif
110 +
111  
112  static void bgmac_get_drvinfo(struct net_device *net_dev,
113                               struct ethtool_drvinfo *info)
114 @@ -1308,6 +1252,7 @@ static void bgmac_get_drvinfo(struct net
115  
116  static const struct ethtool_ops bgmac_ethtool_ops = {
117         .get_settings           = bgmac_get_settings,
118 +       .set_settings           = bgmac_set_settings,
119         .get_drvinfo            = bgmac_get_drvinfo,
120  };
121  
122 @@ -1326,10 +1271,42 @@ static int bgmac_mii_write(struct mii_bu
123         return bgmac_phy_write(bus->priv, mii_id, regnum, value);
124  }
125  
126 +static void bgmac_adjust_link(struct net_device *dev)
127 +{
128 +       struct bgmac *bgmac = netdev_priv(dev);
129 +       struct phy_device *phydev = bgmac->phydev;
130 +       int status_changed = 0;
131 +
132 +       BUG_ON(!phydev);
133 +
134 +       if (bgmac->old_link != phydev->link) {
135 +               status_changed = 1;
136 +               bgmac->old_link = phydev->link;
137 +       }
138 +
139 +       /* reflect duplex change */
140 +       if (phydev->link && (bgmac->old_duplex != phydev->duplex)) {
141 +               status_changed = 1;
142 +               bgmac->old_duplex = phydev->duplex;
143 +       }
144 +
145 +       if (status_changed) {
146 +               pr_info("%s: link %s", dev->name, phydev->link ?
147 +                       "UP" : "DOWN");
148 +               if (phydev->link)
149 +                       pr_cont(" - %d/%s", phydev->speed,
150 +                       phydev->duplex == DUPLEX_FULL ? "full" : "half");
151 +               pr_cont("\n");
152 +       }
153 +}
154 +
155  static int bgmac_mii_register(struct bgmac *bgmac)
156  {
157         struct mii_bus *mii_bus;
158         int i, err = 0;
159 +       struct phy_device *phydev = NULL;
160 +       char phy_id[MII_BUS_ID_SIZE + 3];
161 +       struct net_device *net_dev = bgmac->net_dev;
162  
163         mii_bus = mdiobus_alloc();
164         if (!mii_bus)
165 @@ -1360,7 +1337,29 @@ static int bgmac_mii_register(struct bgm
166  
167         bgmac->mii_bus = mii_bus;
168  
169 -       return err;
170 +       /* connect to PHY */
171 +       snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
172 +                mii_bus->id, bgmac->phyaddr);
173 +
174 +       phydev = phy_connect(net_dev, phy_id, &bgmac_adjust_link,
175 +                            PHY_INTERFACE_MODE_MII);
176 +
177 +       if (IS_ERR(phydev)) {
178 +               netdev_err(net_dev, "could not attach PHY: %s", phy_id);
179 +               bgmac->phyaddr = BGMAC_PHY_NOREGS;
180 +               return PTR_ERR(phydev);
181 +       }
182 +
183 +       bgmac->phydev = phydev;
184 +       bgmac->old_link = 0;
185 +       bgmac->old_duplex = -1;
186 +       bgmac->phyaddr = phydev->addr;
187 +
188 +       netdev_info(net_dev, "attached PHY driver [%s] "
189 +               "(mii_bus:phy_addr=%s)\n",
190 +               phydev->drv->name, dev_name(&phydev->dev));
191 +
192 +       return 0;
193  
194  err_free_irq:
195         kfree(mii_bus->irq);
196 --- a/drivers/net/ethernet/broadcom/bgmac.h
197 +++ b/drivers/net/ethernet/broadcom/bgmac.h
198 @@ -399,7 +399,10 @@ struct bgmac {
199         struct bcma_device *cmn; /* Reference to CMN core for BCM4706 */
200         struct net_device *net_dev;
201         struct napi_struct napi;
202 +       struct phy_device *phydev;
203         struct mii_bus *mii_bus;
204 +       int old_link;
205 +       int old_duplex;
206  
207         /* DMA */
208         struct bgmac_dma_ring tx_ring[BGMAC_MAX_TX_RINGS];