bc7b246cc1be0eec6bb17e2c895dd2757a12b8cd
[librecmc/librecmc.git] /
1 From 55954f3bfdacc5908515b0c306cea23e77fab740 Mon Sep 17 00:00:00 2001
2 From: Jon Mason <jon.mason@broadcom.com>
3 Date: Thu, 7 Jul 2016 19:08:55 -0400
4 Subject: [PATCH 3/5] net: ethernet: bgmac: move BCMA MDIO Phy code into a
5  separate file
6
7 Move the BCMA MDIO phy into a separate file, as it is very tightly
8 coupled with the BCMA bus.  This will help with the upcoming BCMA
9 removal from the bgmac driver.  Optimally, this should be moved into
10 phy drivers, but it is too tightly coupled with the bgmac driver to
11 effectively move it without more changes to the driver.
12
13 Note: the phy_reset was intentionally removed, as the mdio phy subsystem
14 automatically resets the phy if a reset function pointer is present.  In
15 addition to the moving of the driver, this reset function is added.
16
17 Signed-off-by: Jon Mason <jon.mason@broadcom.com>
18 Acked-by: Arnd Bergmann <arnd@arndb.de>
19 Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
20 Tested-by: Florian Fainelli <f.fainelli@gmail.com>
21 Signed-off-by: David S. Miller <davem@davemloft.net>
22 ---
23  drivers/net/ethernet/broadcom/Makefile          |   2 +-
24  drivers/net/ethernet/broadcom/bgmac-bcma-mdio.c | 264 ++++++++++++++++++++++++
25  drivers/net/ethernet/broadcom/bgmac.c           | 246 +++-------------------
26  drivers/net/ethernet/broadcom/bgmac.h           |   3 +
27  4 files changed, 298 insertions(+), 217 deletions(-)
28  create mode 100644 drivers/net/ethernet/broadcom/bgmac-bcma-mdio.c
29
30 --- a/drivers/net/ethernet/broadcom/Makefile
31 +++ b/drivers/net/ethernet/broadcom/Makefile
32 @@ -10,6 +10,6 @@ obj-$(CONFIG_CNIC) += cnic.o
33  obj-$(CONFIG_BNX2X) += bnx2x/
34  obj-$(CONFIG_SB1250_MAC) += sb1250-mac.o
35  obj-$(CONFIG_TIGON3) += tg3.o
36 -obj-$(CONFIG_BGMAC) += bgmac.o
37 +obj-$(CONFIG_BGMAC) += bgmac.o bgmac-bcma-mdio.o
38  obj-$(CONFIG_SYSTEMPORT) += bcmsysport.o
39  obj-$(CONFIG_BNXT) += bnxt/
40 --- /dev/null
41 +++ b/drivers/net/ethernet/broadcom/bgmac-bcma-mdio.c
42 @@ -0,0 +1,275 @@
43 +/*
44 + * Driver for (BCM4706)? GBit MAC core on BCMA bus.
45 + *
46 + * Copyright (C) 2012 Rafał Miłecki <zajec5@gmail.com>
47 + *
48 + * Licensed under the GNU/GPL. See COPYING for details.
49 + */
50 +
51 +#define pr_fmt(fmt)            KBUILD_MODNAME ": " fmt
52 +
53 +#include <linux/bcma/bcma.h>
54 +#include <linux/brcmphy.h>
55 +#include "bgmac.h"
56 +
57 +struct bcma_mdio {
58 +       struct bcma_device *core;
59 +       u8 phyaddr;
60 +};
61 +
62 +static bool bcma_mdio_wait_value(struct bcma_device *core, u16 reg, u32 mask,
63 +                                u32 value, int timeout)
64 +{
65 +       u32 val;
66 +       int i;
67 +
68 +       for (i = 0; i < timeout / 10; i++) {
69 +               val = bcma_read32(core, reg);
70 +               if ((val & mask) == value)
71 +                       return true;
72 +               udelay(10);
73 +       }
74 +       dev_err(&core->dev, "Timeout waiting for reg 0x%X\n", reg);
75 +       return false;
76 +}
77 +
78 +/**************************************************
79 + * PHY ops
80 + **************************************************/
81 +
82 +static u16 bcma_mdio_phy_read(struct bcma_mdio *bcma_mdio, u8 phyaddr, u8 reg)
83 +{
84 +       struct bcma_device *core;
85 +       u16 phy_access_addr;
86 +       u16 phy_ctl_addr;
87 +       u32 tmp;
88 +
89 +       BUILD_BUG_ON(BGMAC_PA_DATA_MASK != BCMA_GMAC_CMN_PA_DATA_MASK);
90 +       BUILD_BUG_ON(BGMAC_PA_ADDR_MASK != BCMA_GMAC_CMN_PA_ADDR_MASK);
91 +       BUILD_BUG_ON(BGMAC_PA_ADDR_SHIFT != BCMA_GMAC_CMN_PA_ADDR_SHIFT);
92 +       BUILD_BUG_ON(BGMAC_PA_REG_MASK != BCMA_GMAC_CMN_PA_REG_MASK);
93 +       BUILD_BUG_ON(BGMAC_PA_REG_SHIFT != BCMA_GMAC_CMN_PA_REG_SHIFT);
94 +       BUILD_BUG_ON(BGMAC_PA_WRITE != BCMA_GMAC_CMN_PA_WRITE);
95 +       BUILD_BUG_ON(BGMAC_PA_START != BCMA_GMAC_CMN_PA_START);
96 +       BUILD_BUG_ON(BGMAC_PC_EPA_MASK != BCMA_GMAC_CMN_PC_EPA_MASK);
97 +       BUILD_BUG_ON(BGMAC_PC_MCT_MASK != BCMA_GMAC_CMN_PC_MCT_MASK);
98 +       BUILD_BUG_ON(BGMAC_PC_MCT_SHIFT != BCMA_GMAC_CMN_PC_MCT_SHIFT);
99 +       BUILD_BUG_ON(BGMAC_PC_MTE != BCMA_GMAC_CMN_PC_MTE);
100 +
101 +       if (bcma_mdio->core->id.id == BCMA_CORE_4706_MAC_GBIT) {
102 +               core = bcma_mdio->core->bus->drv_gmac_cmn.core;
103 +               phy_access_addr = BCMA_GMAC_CMN_PHY_ACCESS;
104 +               phy_ctl_addr = BCMA_GMAC_CMN_PHY_CTL;
105 +       } else {
106 +               core = bcma_mdio->core;
107 +               phy_access_addr = BGMAC_PHY_ACCESS;
108 +               phy_ctl_addr = BGMAC_PHY_CNTL;
109 +       }
110 +
111 +       tmp = bcma_read32(core, phy_ctl_addr);
112 +       tmp &= ~BGMAC_PC_EPA_MASK;
113 +       tmp |= phyaddr;
114 +       bcma_write32(core, phy_ctl_addr, tmp);
115 +
116 +       tmp = BGMAC_PA_START;
117 +       tmp |= phyaddr << BGMAC_PA_ADDR_SHIFT;
118 +       tmp |= reg << BGMAC_PA_REG_SHIFT;
119 +       bcma_write32(core, phy_access_addr, tmp);
120 +
121 +       if (!bcma_mdio_wait_value(core, phy_access_addr, BGMAC_PA_START, 0,
122 +                                 1000)) {
123 +               dev_err(&core->dev, "Reading PHY %d register 0x%X failed\n",
124 +                       phyaddr, reg);
125 +               return 0xffff;
126 +       }
127 +
128 +       return bcma_read32(core, phy_access_addr) & BGMAC_PA_DATA_MASK;
129 +}
130 +
131 +/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphywr */
132 +static int bcma_mdio_phy_write(struct bcma_mdio *bcma_mdio, u8 phyaddr, u8 reg,
133 +                              u16 value)
134 +{
135 +       struct bcma_device *core;
136 +       u16 phy_access_addr;
137 +       u16 phy_ctl_addr;
138 +       u32 tmp;
139 +
140 +       if (bcma_mdio->core->id.id == BCMA_CORE_4706_MAC_GBIT) {
141 +               core = bcma_mdio->core->bus->drv_gmac_cmn.core;
142 +               phy_access_addr = BCMA_GMAC_CMN_PHY_ACCESS;
143 +               phy_ctl_addr = BCMA_GMAC_CMN_PHY_CTL;
144 +       } else {
145 +               core = bcma_mdio->core;
146 +               phy_access_addr = BGMAC_PHY_ACCESS;
147 +               phy_ctl_addr = BGMAC_PHY_CNTL;
148 +       }
149 +
150 +       tmp = bcma_read32(core, phy_ctl_addr);
151 +       tmp &= ~BGMAC_PC_EPA_MASK;
152 +       tmp |= phyaddr;
153 +       bcma_write32(core, phy_ctl_addr, tmp);
154 +
155 +       bcma_write32(bcma_mdio->core, BGMAC_INT_STATUS, BGMAC_IS_MDIO);
156 +       if (bcma_read32(bcma_mdio->core, BGMAC_INT_STATUS) & BGMAC_IS_MDIO)
157 +               dev_warn(&core->dev, "Error setting MDIO int\n");
158 +
159 +       tmp = BGMAC_PA_START;
160 +       tmp |= BGMAC_PA_WRITE;
161 +       tmp |= phyaddr << BGMAC_PA_ADDR_SHIFT;
162 +       tmp |= reg << BGMAC_PA_REG_SHIFT;
163 +       tmp |= value;
164 +       bcma_write32(core, phy_access_addr, tmp);
165 +
166 +       if (!bcma_mdio_wait_value(core, phy_access_addr, BGMAC_PA_START, 0,
167 +                                 1000)) {
168 +               dev_err(&core->dev, "Writing to PHY %d register 0x%X failed\n",
169 +                       phyaddr, reg);
170 +               return -ETIMEDOUT;
171 +       }
172 +
173 +       return 0;
174 +}
175 +
176 +/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphyinit */
177 +static void bcma_mdio_phy_init(struct bcma_mdio *bcma_mdio)
178 +{
179 +       struct bcma_chipinfo *ci = &bcma_mdio->core->bus->chipinfo;
180 +       u8 i;
181 +
182 +       if (ci->id == BCMA_CHIP_ID_BCM5356) {
183 +               for (i = 0; i < 5; i++) {
184 +                       bcma_mdio_phy_write(bcma_mdio, i, 0x1f, 0x008b);
185 +                       bcma_mdio_phy_write(bcma_mdio, i, 0x15, 0x0100);
186 +                       bcma_mdio_phy_write(bcma_mdio, i, 0x1f, 0x000f);
187 +                       bcma_mdio_phy_write(bcma_mdio, i, 0x12, 0x2aaa);
188 +                       bcma_mdio_phy_write(bcma_mdio, i, 0x1f, 0x000b);
189 +               }
190 +       }
191 +       if ((ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg != 10) ||
192 +           (ci->id == BCMA_CHIP_ID_BCM4749 && ci->pkg != 10) ||
193 +           (ci->id == BCMA_CHIP_ID_BCM53572 && ci->pkg != 9)) {
194 +               struct bcma_drv_cc *cc = &bcma_mdio->core->bus->drv_cc;
195 +
196 +               bcma_chipco_chipctl_maskset(cc, 2, ~0xc0000000, 0);
197 +               bcma_chipco_chipctl_maskset(cc, 4, ~0x80000000, 0);
198 +               for (i = 0; i < 5; i++) {
199 +                       bcma_mdio_phy_write(bcma_mdio, i, 0x1f, 0x000f);
200 +                       bcma_mdio_phy_write(bcma_mdio, i, 0x16, 0x5284);
201 +                       bcma_mdio_phy_write(bcma_mdio, i, 0x1f, 0x000b);
202 +                       bcma_mdio_phy_write(bcma_mdio, i, 0x17, 0x0010);
203 +                       bcma_mdio_phy_write(bcma_mdio, i, 0x1f, 0x000f);
204 +                       bcma_mdio_phy_write(bcma_mdio, i, 0x16, 0x5296);
205 +                       bcma_mdio_phy_write(bcma_mdio, i, 0x17, 0x1073);
206 +                       bcma_mdio_phy_write(bcma_mdio, i, 0x17, 0x9073);
207 +                       bcma_mdio_phy_write(bcma_mdio, i, 0x16, 0x52b6);
208 +                       bcma_mdio_phy_write(bcma_mdio, i, 0x17, 0x9273);
209 +                       bcma_mdio_phy_write(bcma_mdio, i, 0x1f, 0x000b);
210 +               }
211 +       }
212 +}
213 +
214 +/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphyreset */
215 +static int bcma_mdio_phy_reset(struct mii_bus *bus)
216 +{
217 +       struct bcma_mdio *bcma_mdio = bus->priv;
218 +       u8 phyaddr = bcma_mdio->phyaddr;
219 +
220 +       if (bcma_mdio->phyaddr == BGMAC_PHY_NOREGS)
221 +               return 0;
222 +
223 +       bcma_mdio_phy_write(bcma_mdio, phyaddr, MII_BMCR, BMCR_RESET);
224 +       udelay(100);
225 +       if (bcma_mdio_phy_read(bcma_mdio, phyaddr, MII_BMCR) & BMCR_RESET)
226 +               dev_err(&bcma_mdio->core->dev, "PHY reset failed\n");
227 +       bcma_mdio_phy_init(bcma_mdio);
228 +
229 +       return 0;
230 +}
231 +
232 +/**************************************************
233 + * MII
234 + **************************************************/
235 +
236 +static int bcma_mdio_mii_read(struct mii_bus *bus, int mii_id, int regnum)
237 +{
238 +       return bcma_mdio_phy_read(bus->priv, mii_id, regnum);
239 +}
240 +
241 +static int bcma_mdio_mii_write(struct mii_bus *bus, int mii_id, int regnum,
242 +                              u16 value)
243 +{
244 +       return bcma_mdio_phy_write(bus->priv, mii_id, regnum, value);
245 +}
246 +
247 +struct mii_bus *bcma_mdio_mii_register(struct bcma_device *core, u8 phyaddr)
248 +{
249 +       struct bcma_mdio *bcma_mdio;
250 +       struct mii_bus *mii_bus;
251 +       int i, err;
252 +
253 +       bcma_mdio = kzalloc(sizeof(*bcma_mdio), GFP_KERNEL);
254 +       if (!bcma_mdio)
255 +               return ERR_PTR(-ENOMEM);
256 +
257 +       mii_bus = mdiobus_alloc();
258 +       if (!mii_bus) {
259 +               err = -ENOMEM;
260 +               goto err;
261 +       }
262 +
263 +       mii_bus->name = "bcma_mdio mii bus";
264 +       sprintf(mii_bus->id, "%s-%d-%d", "bcma_mdio", core->bus->num,
265 +               core->core_unit);
266 +       mii_bus->priv = bcma_mdio;
267 +       mii_bus->read = bcma_mdio_mii_read;
268 +       mii_bus->write = bcma_mdio_mii_write;
269 +       mii_bus->reset = bcma_mdio_phy_reset;
270 +       mii_bus->parent = &core->dev;
271 +       mii_bus->phy_mask = ~(1 << phyaddr);
272
273 +       mii_bus->irq = kmalloc_array(PHY_MAX_ADDR, sizeof(int), GFP_KERNEL);
274 +       if (!mii_bus->irq) {
275 +               err = -ENOMEM;
276 +               goto err_free_bus;
277 +       }
278 +       for (i = 0; i < PHY_MAX_ADDR; i++)
279 +               mii_bus->irq[i] = PHY_POLL;
280 +
281 +       bcma_mdio->core = core;
282 +       bcma_mdio->phyaddr = phyaddr;
283 +
284 +       err = mdiobus_register(mii_bus);
285 +       if (err) {
286 +               dev_err(&core->dev, "Registration of mii bus failed\n");
287 +               goto err_free_irq;
288 +       }
289 +
290 +       return mii_bus;
291 +
292 +err_free_irq:
293 +       kfree(mii_bus->irq);
294 +err_free_bus:
295 +       mdiobus_free(mii_bus);
296 +err:
297 +       kfree(bcma_mdio);
298 +       return ERR_PTR(err);
299 +}
300 +
301 +void bcma_mdio_mii_unregister(struct mii_bus *mii_bus)
302 +{
303 +       struct bcma_mdio *bcma_mdio;
304 +
305 +       if (!mii_bus)
306 +               return;
307 +
308 +       bcma_mdio = mii_bus->priv;
309 +
310 +       mdiobus_unregister(mii_bus);
311 +       kfree(mii_bus->irq);
312 +       mdiobus_free(mii_bus);
313 +       kfree(bcma_mdio);
314 +}
315 +
316 +MODULE_AUTHOR("Rafał Miłecki");
317 +MODULE_LICENSE("GPL");
318 --- a/drivers/net/ethernet/broadcom/bgmac.c
319 +++ b/drivers/net/ethernet/broadcom/bgmac.c
320 @@ -759,150 +759,6 @@ error:
321         return err;
322  }
323  
324 -/**************************************************
325 - * PHY ops
326 - **************************************************/
327 -
328 -static u16 bgmac_phy_read(struct bgmac *bgmac, u8 phyaddr, u8 reg)
329 -{
330 -       struct bcma_device *core;
331 -       u16 phy_access_addr;
332 -       u16 phy_ctl_addr;
333 -       u32 tmp;
334 -
335 -       BUILD_BUG_ON(BGMAC_PA_DATA_MASK != BCMA_GMAC_CMN_PA_DATA_MASK);
336 -       BUILD_BUG_ON(BGMAC_PA_ADDR_MASK != BCMA_GMAC_CMN_PA_ADDR_MASK);
337 -       BUILD_BUG_ON(BGMAC_PA_ADDR_SHIFT != BCMA_GMAC_CMN_PA_ADDR_SHIFT);
338 -       BUILD_BUG_ON(BGMAC_PA_REG_MASK != BCMA_GMAC_CMN_PA_REG_MASK);
339 -       BUILD_BUG_ON(BGMAC_PA_REG_SHIFT != BCMA_GMAC_CMN_PA_REG_SHIFT);
340 -       BUILD_BUG_ON(BGMAC_PA_WRITE != BCMA_GMAC_CMN_PA_WRITE);
341 -       BUILD_BUG_ON(BGMAC_PA_START != BCMA_GMAC_CMN_PA_START);
342 -       BUILD_BUG_ON(BGMAC_PC_EPA_MASK != BCMA_GMAC_CMN_PC_EPA_MASK);
343 -       BUILD_BUG_ON(BGMAC_PC_MCT_MASK != BCMA_GMAC_CMN_PC_MCT_MASK);
344 -       BUILD_BUG_ON(BGMAC_PC_MCT_SHIFT != BCMA_GMAC_CMN_PC_MCT_SHIFT);
345 -       BUILD_BUG_ON(BGMAC_PC_MTE != BCMA_GMAC_CMN_PC_MTE);
346 -
347 -       if (bgmac->core->id.id == BCMA_CORE_4706_MAC_GBIT) {
348 -               core = bgmac->core->bus->drv_gmac_cmn.core;
349 -               phy_access_addr = BCMA_GMAC_CMN_PHY_ACCESS;
350 -               phy_ctl_addr = BCMA_GMAC_CMN_PHY_CTL;
351 -       } else {
352 -               core = bgmac->core;
353 -               phy_access_addr = BGMAC_PHY_ACCESS;
354 -               phy_ctl_addr = BGMAC_PHY_CNTL;
355 -       }
356 -
357 -       tmp = bcma_read32(core, phy_ctl_addr);
358 -       tmp &= ~BGMAC_PC_EPA_MASK;
359 -       tmp |= phyaddr;
360 -       bcma_write32(core, phy_ctl_addr, tmp);
361 -
362 -       tmp = BGMAC_PA_START;
363 -       tmp |= phyaddr << BGMAC_PA_ADDR_SHIFT;
364 -       tmp |= reg << BGMAC_PA_REG_SHIFT;
365 -       bcma_write32(core, phy_access_addr, tmp);
366 -
367 -       if (!bgmac_wait_value(core, phy_access_addr, BGMAC_PA_START, 0, 1000)) {
368 -               dev_err(bgmac->dev, "Reading PHY %d register 0x%X failed\n",
369 -                       phyaddr, reg);
370 -               return 0xffff;
371 -       }
372 -
373 -       return bcma_read32(core, phy_access_addr) & BGMAC_PA_DATA_MASK;
374 -}
375 -
376 -/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphywr */
377 -static int bgmac_phy_write(struct bgmac *bgmac, u8 phyaddr, u8 reg, u16 value)
378 -{
379 -       struct bcma_device *core;
380 -       u16 phy_access_addr;
381 -       u16 phy_ctl_addr;
382 -       u32 tmp;
383 -
384 -       if (bgmac->core->id.id == BCMA_CORE_4706_MAC_GBIT) {
385 -               core = bgmac->core->bus->drv_gmac_cmn.core;
386 -               phy_access_addr = BCMA_GMAC_CMN_PHY_ACCESS;
387 -               phy_ctl_addr = BCMA_GMAC_CMN_PHY_CTL;
388 -       } else {
389 -               core = bgmac->core;
390 -               phy_access_addr = BGMAC_PHY_ACCESS;
391 -               phy_ctl_addr = BGMAC_PHY_CNTL;
392 -       }
393 -
394 -       tmp = bcma_read32(core, phy_ctl_addr);
395 -       tmp &= ~BGMAC_PC_EPA_MASK;
396 -       tmp |= phyaddr;
397 -       bcma_write32(core, phy_ctl_addr, tmp);
398 -
399 -       bgmac_write(bgmac, BGMAC_INT_STATUS, BGMAC_IS_MDIO);
400 -       if (bgmac_read(bgmac, BGMAC_INT_STATUS) & BGMAC_IS_MDIO)
401 -               dev_warn(bgmac->dev, "Error setting MDIO int\n");
402 -
403 -       tmp = BGMAC_PA_START;
404 -       tmp |= BGMAC_PA_WRITE;
405 -       tmp |= phyaddr << BGMAC_PA_ADDR_SHIFT;
406 -       tmp |= reg << BGMAC_PA_REG_SHIFT;
407 -       tmp |= value;
408 -       bcma_write32(core, phy_access_addr, tmp);
409 -
410 -       if (!bgmac_wait_value(core, phy_access_addr, BGMAC_PA_START, 0, 1000)) {
411 -               dev_err(bgmac->dev, "Writing to PHY %d register 0x%X failed\n",
412 -                       phyaddr, reg);
413 -               return -ETIMEDOUT;
414 -       }
415 -
416 -       return 0;
417 -}
418 -
419 -/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphyinit */
420 -static void bgmac_phy_init(struct bgmac *bgmac)
421 -{
422 -       struct bcma_chipinfo *ci = &bgmac->core->bus->chipinfo;
423 -       struct bcma_drv_cc *cc = &bgmac->core->bus->drv_cc;
424 -       u8 i;
425 -
426 -       if (ci->id == BCMA_CHIP_ID_BCM5356) {
427 -               for (i = 0; i < 5; i++) {
428 -                       bgmac_phy_write(bgmac, i, 0x1f, 0x008b);
429 -                       bgmac_phy_write(bgmac, i, 0x15, 0x0100);
430 -                       bgmac_phy_write(bgmac, i, 0x1f, 0x000f);
431 -                       bgmac_phy_write(bgmac, i, 0x12, 0x2aaa);
432 -                       bgmac_phy_write(bgmac, i, 0x1f, 0x000b);
433 -               }
434 -       }
435 -       if ((ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg != 10) ||
436 -           (ci->id == BCMA_CHIP_ID_BCM4749 && ci->pkg != 10) ||
437 -           (ci->id == BCMA_CHIP_ID_BCM53572 && ci->pkg != 9)) {
438 -               bcma_chipco_chipctl_maskset(cc, 2, ~0xc0000000, 0);
439 -               bcma_chipco_chipctl_maskset(cc, 4, ~0x80000000, 0);
440 -               for (i = 0; i < 5; i++) {
441 -                       bgmac_phy_write(bgmac, i, 0x1f, 0x000f);
442 -                       bgmac_phy_write(bgmac, i, 0x16, 0x5284);
443 -                       bgmac_phy_write(bgmac, i, 0x1f, 0x000b);
444 -                       bgmac_phy_write(bgmac, i, 0x17, 0x0010);
445 -                       bgmac_phy_write(bgmac, i, 0x1f, 0x000f);
446 -                       bgmac_phy_write(bgmac, i, 0x16, 0x5296);
447 -                       bgmac_phy_write(bgmac, i, 0x17, 0x1073);
448 -                       bgmac_phy_write(bgmac, i, 0x17, 0x9073);
449 -                       bgmac_phy_write(bgmac, i, 0x16, 0x52b6);
450 -                       bgmac_phy_write(bgmac, i, 0x17, 0x9273);
451 -                       bgmac_phy_write(bgmac, i, 0x1f, 0x000b);
452 -               }
453 -       }
454 -}
455 -
456 -/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphyreset */
457 -static void bgmac_phy_reset(struct bgmac *bgmac)
458 -{
459 -       if (bgmac->phyaddr == BGMAC_PHY_NOREGS)
460 -               return;
461 -
462 -       bgmac_phy_write(bgmac, bgmac->phyaddr, MII_BMCR, BMCR_RESET);
463 -       udelay(100);
464 -       if (bgmac_phy_read(bgmac, bgmac->phyaddr, MII_BMCR) & BMCR_RESET)
465 -               dev_err(bgmac->dev, "PHY reset failed\n");
466 -       bgmac_phy_init(bgmac);
467 -}
468  
469  /**************************************************
470   * Chip ops
471 @@ -1159,7 +1015,8 @@ static void bgmac_chip_reset(struct bgma
472         else
473                 bgmac_set(bgmac, BGMAC_PHY_CNTL, BGMAC_PC_MTE);
474         bgmac_miiconfig(bgmac);
475 -       bgmac_phy_init(bgmac);
476 +       if (bgmac->mii_bus)
477 +               bgmac->mii_bus->reset(bgmac->mii_bus);
478  
479         netdev_reset_queue(bgmac->net_dev);
480  }
481 @@ -1553,17 +1410,6 @@ static const struct ethtool_ops bgmac_et
482   * MII
483   **************************************************/
484  
485 -static int bgmac_mii_read(struct mii_bus *bus, int mii_id, int regnum)
486 -{
487 -       return bgmac_phy_read(bus->priv, mii_id, regnum);
488 -}
489 -
490 -static int bgmac_mii_write(struct mii_bus *bus, int mii_id, int regnum,
491 -                          u16 value)
492 -{
493 -       return bgmac_phy_write(bus->priv, mii_id, regnum, value);
494 -}
495 -
496  static void bgmac_adjust_link(struct net_device *net_dev)
497  {
498         struct bgmac *bgmac = netdev_priv(net_dev);
499 @@ -1588,7 +1434,7 @@ static void bgmac_adjust_link(struct net
500         }
501  }
502  
503 -static int bgmac_fixed_phy_register(struct bgmac *bgmac)
504 +static int bgmac_phy_connect_direct(struct bgmac *bgmac)
505  {
506         struct fixed_phy_status fphy_status = {
507                 .link = 1,
508 @@ -1614,81 +1460,24 @@ static int bgmac_fixed_phy_register(stru
509         return err;
510  }
511  
512 -static int bgmac_mii_register(struct bgmac *bgmac)
513 +static int bgmac_phy_connect(struct bgmac *bgmac)
514  {
515 -       struct mii_bus *mii_bus;
516         struct phy_device *phy_dev;
517         char bus_id[MII_BUS_ID_SIZE + 3];
518 -       int i, err = 0;
519 -
520 -       if (bgmac_is_bcm4707_family(bgmac))
521 -               return bgmac_fixed_phy_register(bgmac);
522 -
523 -       mii_bus = mdiobus_alloc();
524 -       if (!mii_bus)
525 -               return -ENOMEM;
526 -
527 -       mii_bus->name = "bgmac mii bus";
528 -       sprintf(mii_bus->id, "%s-%d-%d", "bgmac", bgmac->core->bus->num,
529 -               bgmac->core->core_unit);
530 -       mii_bus->priv = bgmac;
531 -       mii_bus->read = bgmac_mii_read;
532 -       mii_bus->write = bgmac_mii_write;
533 -       mii_bus->parent = &bgmac->core->dev;
534 -       mii_bus->phy_mask = ~(1 << bgmac->phyaddr);
535 -
536 -       mii_bus->irq = kmalloc_array(PHY_MAX_ADDR, sizeof(int), GFP_KERNEL);
537 -       if (!mii_bus->irq) {
538 -               err = -ENOMEM;
539 -               goto err_free_bus;
540 -       }
541 -       for (i = 0; i < PHY_MAX_ADDR; i++)
542 -               mii_bus->irq[i] = PHY_POLL;
543 -
544 -       err = mdiobus_register(mii_bus);
545 -       if (err) {
546 -               dev_err(bgmac->dev, "Registration of mii bus failed\n");
547 -               goto err_free_irq;
548 -       }
549 -
550 -       bgmac->mii_bus = mii_bus;
551  
552         /* Connect to the PHY */
553 -       snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, mii_bus->id,
554 +       snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, bgmac->mii_bus->id,
555                  bgmac->phyaddr);
556         phy_dev = phy_connect(bgmac->net_dev, bus_id, &bgmac_adjust_link,
557                               PHY_INTERFACE_MODE_MII);
558         if (IS_ERR(phy_dev)) {
559                 dev_err(bgmac->dev, "PHY connecton failed\n");
560 -               err = PTR_ERR(phy_dev);
561 -               goto err_unregister_bus;
562 +               return PTR_ERR(phy_dev);
563         }
564  
565 -       return err;
566 -
567 -err_unregister_bus:
568 -       mdiobus_unregister(mii_bus);
569 -err_free_irq:
570 -       kfree(mii_bus->irq);
571 -err_free_bus:
572 -       mdiobus_free(mii_bus);
573 -       return err;
574 -}
575 -
576 -static void bgmac_mii_unregister(struct bgmac *bgmac)
577 -{
578 -       struct mii_bus *mii_bus = bgmac->mii_bus;
579 -
580 -       mdiobus_unregister(mii_bus);
581 -       kfree(mii_bus->irq);
582 -       mdiobus_free(mii_bus);
583 +       return 0;
584  }
585  
586 -/**************************************************
587 - * BCMA bus ops
588 - **************************************************/
589 -
590 -/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipattach */
591  static int bgmac_probe(struct bcma_device *core)
592  {
593         struct net_device *net_dev;
594 @@ -1809,9 +1598,6 @@ static int bgmac_probe(struct bcma_devic
595         if (bcm47xx_nvram_getenv("et0_no_txint", NULL, 0) == 0)
596                 bgmac->int_mask &= ~BGMAC_IS_TX_MASK;
597  
598 -       /* TODO: reset the external phy. Specs are needed */
599 -       bgmac_phy_reset(bgmac);
600 -
601         bgmac->has_robosw = !!(core->bus->sprom.boardflags_lo &
602                                BGMAC_BFL_ENETROBO);
603         if (bgmac->has_robosw)
604 @@ -1822,10 +1608,25 @@ static int bgmac_probe(struct bcma_devic
605  
606         netif_napi_add(net_dev, &bgmac->napi, bgmac_poll, BGMAC_WEIGHT);
607  
608 -       err = bgmac_mii_register(bgmac);
609 +       if (!bgmac_is_bcm4707_family(bgmac)) {
610 +               struct mii_bus *mii_bus;
611 +
612 +               mii_bus = bcma_mdio_mii_register(core, bgmac->phyaddr);
613 +               if (!IS_ERR(mii_bus)) {
614 +                       err = PTR_ERR(mii_bus);
615 +                       goto err_dma_free;
616 +               }
617 +
618 +               bgmac->mii_bus = mii_bus;
619 +       }
620 +
621 +       if (!bgmac->mii_bus)
622 +               err = bgmac_phy_connect_direct(bgmac);
623 +       else
624 +               err = bgmac_phy_connect(bgmac);
625         if (err) {
626                 dev_err(bgmac->dev, "Cannot connect to phy\n");
627 -               goto err_dma_free;
628 +               goto err_mii_unregister;
629         }
630  
631         net_dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
632 @@ -1835,18 +1636,19 @@ static int bgmac_probe(struct bcma_devic
633         err = register_netdev(bgmac->net_dev);
634         if (err) {
635                 dev_err(bgmac->dev, "Cannot register net device\n");
636 -               goto err_mii_unregister;
637 +               goto err_phy_disconnect;
638         }
639  
640         netif_carrier_off(net_dev);
641  
642         return 0;
643  
644 +err_phy_disconnect:
645 +       phy_disconnect(net_dev->phydev);
646  err_mii_unregister:
647 -       bgmac_mii_unregister(bgmac);
648 +       bcma_mdio_mii_unregister(bgmac->mii_bus);
649  err_dma_free:
650         bgmac_dma_free(bgmac);
651 -
652  err_netdev_free:
653         bcma_set_drvdata(core, NULL);
654         free_netdev(net_dev);
655 @@ -1859,7 +1661,8 @@ static void bgmac_remove(struct bcma_dev
656         struct bgmac *bgmac = bcma_get_drvdata(core);
657  
658         unregister_netdev(bgmac->net_dev);
659 -       bgmac_mii_unregister(bgmac);
660 +       phy_disconnect(bgmac->net_dev->phydev);
661 +       bcma_mdio_mii_unregister(bgmac->mii_bus);
662         netif_napi_del(&bgmac->napi);
663         bgmac_dma_free(bgmac);
664         bcma_set_drvdata(core, NULL);
665 --- a/drivers/net/ethernet/broadcom/bgmac.h
666 +++ b/drivers/net/ethernet/broadcom/bgmac.h
667 @@ -456,6 +456,9 @@ struct bgmac {
668         bool loopback;
669  };
670  
671 +struct mii_bus *bcma_mdio_mii_register(struct bcma_device *core, u8 phyaddr);
672 +void bcma_mdio_mii_unregister(struct mii_bus *mii_bus);
673 +
674  static inline u32 bgmac_read(struct bgmac *bgmac, u16 offset)
675  {
676         return bcma_read32(bgmac->core, offset);