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