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