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