Commit f6d7f2c60d3a63d786feeb60628f930cd2d8e912
1 parent
c9218c3a82
Exists in
master
and in
39 other branches
ax88796: use generic mdio_bitbang driver
..instead of using hand-crafted and not proper working version. Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Showing 2 changed files with 196 additions and 200 deletions Side-by-side Diff
drivers/net/Kconfig
... | ... | @@ -238,8 +238,8 @@ |
238 | 238 | config AX88796 |
239 | 239 | tristate "ASIX AX88796 NE2000 clone support" |
240 | 240 | depends on ARM || MIPS || SUPERH |
241 | - select CRC32 | |
242 | - select MII | |
241 | + select PHYLIB | |
242 | + select MDIO_BITBANG | |
243 | 243 | help |
244 | 244 | AX88796 driver, using platform bus to provide |
245 | 245 | chip detection and resources |
drivers/net/ax88796.c
... | ... | @@ -24,7 +24,8 @@ |
24 | 24 | #include <linux/netdevice.h> |
25 | 25 | #include <linux/etherdevice.h> |
26 | 26 | #include <linux/ethtool.h> |
27 | -#include <linux/mii.h> | |
27 | +#include <linux/mdio-bitbang.h> | |
28 | +#include <linux/phy.h> | |
28 | 29 | #include <linux/eeprom_93cx6.h> |
29 | 30 | #include <linux/slab.h> |
30 | 31 | |
... | ... | @@ -32,8 +33,6 @@ |
32 | 33 | |
33 | 34 | #include <asm/system.h> |
34 | 35 | |
35 | -static int phy_debug; | |
36 | - | |
37 | 36 | /* Rename the lib8390.c functions to show that they are in this driver */ |
38 | 37 | #define __ei_open ax_ei_open |
39 | 38 | #define __ei_close ax_ei_close |
40 | 39 | |
41 | 40 | |
... | ... | @@ -78,14 +77,20 @@ |
78 | 77 | #define NESM_START_PG 0x40 /* First page of TX buffer */ |
79 | 78 | #define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ |
80 | 79 | |
80 | +#define AX_GPOC_PPDSET BIT(6) | |
81 | + | |
81 | 82 | /* device private data */ |
82 | 83 | |
83 | 84 | struct ax_device { |
84 | - struct timer_list mii_timer; | |
85 | - spinlock_t mii_lock; | |
86 | - struct mii_if_info mii; | |
85 | + struct mii_bus *mii_bus; | |
86 | + struct mdiobb_ctrl bb_ctrl; | |
87 | + struct phy_device *phy_dev; | |
88 | + void __iomem *addr_memr; | |
89 | + u8 reg_memr; | |
90 | + int link; | |
91 | + int speed; | |
92 | + int duplex; | |
87 | 93 | |
88 | - u32 msg_enable; | |
89 | 94 | void __iomem *map2; |
90 | 95 | const struct ax_plat_data *plat; |
91 | 96 | |
92 | 97 | |
93 | 98 | |
94 | 99 | |
95 | 100 | |
96 | 101 | |
97 | 102 | |
98 | 103 | |
99 | 104 | |
100 | 105 | |
101 | 106 | |
102 | 107 | |
103 | 108 | |
104 | 109 | |
105 | 110 | |
106 | 111 | |
107 | 112 | |
108 | 113 | |
109 | 114 | |
110 | 115 | |
111 | 116 | |
112 | 117 | |
113 | 118 | |
... | ... | @@ -313,159 +318,84 @@ |
313 | 318 | #define AX_MEMR_EEO BIT(6) |
314 | 319 | #define AX_MEMR_EECLK BIT(7) |
315 | 320 | |
316 | -/* | |
317 | - * ax_mii_ei_outbits | |
318 | - * | |
319 | - * write the specified set of bits to the phy | |
320 | - */ | |
321 | -static void | |
322 | -ax_mii_ei_outbits(struct net_device *dev, unsigned int bits, int len) | |
321 | +static void ax_handle_link_change(struct net_device *dev) | |
323 | 322 | { |
324 | - struct ei_device *ei_local = netdev_priv(dev); | |
325 | - void __iomem *memr_addr = (void __iomem *)dev->base_addr + AX_MEMR; | |
326 | - unsigned int memr; | |
323 | + struct ax_device *ax = to_ax_dev(dev); | |
324 | + struct phy_device *phy_dev = ax->phy_dev; | |
325 | + int status_change = 0; | |
327 | 326 | |
328 | - /* clock low, data to output mode */ | |
329 | - memr = ei_inb(memr_addr); | |
330 | - memr &= ~(AX_MEMR_MDC | AX_MEMR_MDIR); | |
331 | - ei_outb(memr, memr_addr); | |
327 | + if (phy_dev->link && ((ax->speed != phy_dev->speed) || | |
328 | + (ax->duplex != phy_dev->duplex))) { | |
332 | 329 | |
333 | - for (len--; len >= 0; len--) { | |
334 | - if (bits & (1 << len)) | |
335 | - memr |= AX_MEMR_MDO; | |
336 | - else | |
337 | - memr &= ~AX_MEMR_MDO; | |
330 | + ax->speed = phy_dev->speed; | |
331 | + ax->duplex = phy_dev->duplex; | |
332 | + status_change = 1; | |
333 | + } | |
338 | 334 | |
339 | - ei_outb(memr, memr_addr); | |
335 | + if (phy_dev->link != ax->link) { | |
336 | + if (!phy_dev->link) { | |
337 | + ax->speed = 0; | |
338 | + ax->duplex = -1; | |
339 | + } | |
340 | + ax->link = phy_dev->link; | |
340 | 341 | |
341 | - /* clock high */ | |
342 | - | |
343 | - ei_outb(memr | AX_MEMR_MDC, memr_addr); | |
344 | - udelay(1); | |
345 | - | |
346 | - /* clock low */ | |
347 | - ei_outb(memr, memr_addr); | |
342 | + status_change = 1; | |
348 | 343 | } |
349 | 344 | |
350 | - /* leaves the clock line low, mdir input */ | |
351 | - memr |= AX_MEMR_MDIR; | |
352 | - ei_outb(memr, (void __iomem *)dev->base_addr + AX_MEMR); | |
345 | + if (status_change) | |
346 | + phy_print_status(phy_dev); | |
353 | 347 | } |
354 | 348 | |
355 | -/* | |
356 | - * ax_phy_ei_inbits | |
357 | - * | |
358 | - * read a specified number of bits from the phy | |
359 | - */ | |
360 | -static unsigned int | |
361 | -ax_phy_ei_inbits(struct net_device *dev, int no) | |
349 | +static int ax_mii_probe(struct net_device *dev) | |
362 | 350 | { |
363 | - struct ei_device *ei_local = netdev_priv(dev); | |
364 | - void __iomem *memr_addr = (void __iomem *)dev->base_addr + AX_MEMR; | |
365 | - unsigned int memr; | |
366 | - unsigned int result = 0; | |
351 | + struct ax_device *ax = to_ax_dev(dev); | |
352 | + struct phy_device *phy_dev = NULL; | |
353 | + int ret; | |
367 | 354 | |
368 | - /* clock low, data to input mode */ | |
369 | - memr = ei_inb(memr_addr); | |
370 | - memr &= ~AX_MEMR_MDC; | |
371 | - memr |= AX_MEMR_MDIR; | |
372 | - ei_outb(memr, memr_addr); | |
355 | + /* find the first phy */ | |
356 | + phy_dev = phy_find_first(ax->mii_bus); | |
357 | + if (!phy_dev) { | |
358 | + netdev_err(dev, "no PHY found\n"); | |
359 | + return -ENODEV; | |
360 | + } | |
373 | 361 | |
374 | - for (no--; no >= 0; no--) { | |
375 | - ei_outb(memr | AX_MEMR_MDC, memr_addr); | |
362 | + ret = phy_connect_direct(dev, phy_dev, ax_handle_link_change, 0, | |
363 | + PHY_INTERFACE_MODE_MII); | |
364 | + if (ret) { | |
365 | + netdev_err(dev, "Could not attach to PHY\n"); | |
366 | + return ret; | |
367 | + } | |
376 | 368 | |
377 | - udelay(1); | |
369 | + /* mask with MAC supported features */ | |
370 | + phy_dev->supported &= PHY_BASIC_FEATURES; | |
371 | + phy_dev->advertising = phy_dev->supported; | |
378 | 372 | |
379 | - if (ei_inb(memr_addr) & AX_MEMR_MDI) | |
380 | - result |= (1 << no); | |
373 | + ax->phy_dev = phy_dev; | |
381 | 374 | |
382 | - ei_outb(memr, memr_addr); | |
383 | - } | |
375 | + netdev_info(dev, "PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", | |
376 | + phy_dev->drv->name, dev_name(&phy_dev->dev), phy_dev->irq); | |
384 | 377 | |
385 | - return result; | |
378 | + return 0; | |
386 | 379 | } |
387 | 380 | |
388 | -/* | |
389 | - * ax_phy_issueaddr | |
390 | - * | |
391 | - * use the low level bit shifting routines to send the address | |
392 | - * and command to the specified phy | |
393 | - */ | |
394 | -static void | |
395 | -ax_phy_issueaddr(struct net_device *dev, int phy_addr, int reg, int opc) | |
381 | +static void ax_phy_switch(struct net_device *dev, int on) | |
396 | 382 | { |
397 | - if (phy_debug) | |
398 | - netdev_dbg(dev, "%s: dev %p, %04x, %04x, %d\n", | |
399 | - __func__, dev, phy_addr, reg, opc); | |
400 | - | |
401 | - ax_mii_ei_outbits(dev, 0x3f, 6); /* pre-amble */ | |
402 | - ax_mii_ei_outbits(dev, 1, 2); /* frame-start */ | |
403 | - ax_mii_ei_outbits(dev, opc, 2); /* op code */ | |
404 | - ax_mii_ei_outbits(dev, phy_addr, 5); /* phy address */ | |
405 | - ax_mii_ei_outbits(dev, reg, 5); /* reg address */ | |
406 | -} | |
407 | - | |
408 | -static int | |
409 | -ax_phy_read(struct net_device *dev, int phy_addr, int reg) | |
410 | -{ | |
411 | 383 | struct ei_device *ei_local = netdev_priv(dev); |
412 | - unsigned long flags; | |
413 | - unsigned int result; | |
384 | + struct ax_device *ax = to_ax_dev(dev); | |
414 | 385 | |
415 | - spin_lock_irqsave(&ei_local->page_lock, flags); | |
386 | + u8 reg_gpoc = ax->plat->gpoc_val; | |
416 | 387 | |
417 | - ax_phy_issueaddr(dev, phy_addr, reg, 2); | |
388 | + if (!!on) | |
389 | + reg_gpoc &= ~AX_GPOC_PPDSET; | |
390 | + else | |
391 | + reg_gpoc |= AX_GPOC_PPDSET; | |
418 | 392 | |
419 | - result = ax_phy_ei_inbits(dev, 17); | |
420 | - result &= ~(3 << 16); | |
421 | - | |
422 | - spin_unlock_irqrestore(&ei_local->page_lock, flags); | |
423 | - | |
424 | - if (phy_debug) | |
425 | - netdev_dbg(dev, "%s: %04x.%04x => read %04x\n", __func__, | |
426 | - phy_addr, reg, result); | |
427 | - | |
428 | - return result; | |
393 | + ei_outb(reg_gpoc, ei_local->mem + EI_SHIFT(0x17)); | |
429 | 394 | } |
430 | 395 | |
431 | -static void | |
432 | -ax_phy_write(struct net_device *dev, int phy_addr, int reg, int value) | |
433 | -{ | |
434 | - struct ei_device *ei = netdev_priv(dev); | |
435 | - unsigned long flags; | |
436 | - | |
437 | - netdev_dbg(dev, "%s: %p, %04x, %04x %04x\n", | |
438 | - __func__, dev, phy_addr, reg, value); | |
439 | - | |
440 | - spin_lock_irqsave(&ei->page_lock, flags); | |
441 | - | |
442 | - ax_phy_issueaddr(dev, phy_addr, reg, 1); | |
443 | - ax_mii_ei_outbits(dev, 2, 2); /* send TA */ | |
444 | - ax_mii_ei_outbits(dev, value, 16); | |
445 | - | |
446 | - spin_unlock_irqrestore(&ei->page_lock, flags); | |
447 | -} | |
448 | - | |
449 | -static void ax_mii_expiry(unsigned long data) | |
450 | -{ | |
451 | - struct net_device *dev = (struct net_device *)data; | |
452 | - struct ax_device *ax = to_ax_dev(dev); | |
453 | - unsigned long flags; | |
454 | - | |
455 | - spin_lock_irqsave(&ax->mii_lock, flags); | |
456 | - mii_check_media(&ax->mii, netif_msg_link(ax), 0); | |
457 | - spin_unlock_irqrestore(&ax->mii_lock, flags); | |
458 | - | |
459 | - if (ax->running) { | |
460 | - ax->mii_timer.expires = jiffies + HZ*2; | |
461 | - add_timer(&ax->mii_timer); | |
462 | - } | |
463 | -} | |
464 | - | |
465 | 396 | static int ax_open(struct net_device *dev) |
466 | 397 | { |
467 | 398 | struct ax_device *ax = to_ax_dev(dev); |
468 | - struct ei_device *ei_local = netdev_priv(dev); | |
469 | 399 | int ret; |
470 | 400 | |
471 | 401 | netdev_dbg(dev, "open\n"); |
472 | 402 | |
473 | 403 | |
474 | 404 | |
475 | 405 | |
476 | 406 | |
477 | 407 | |
478 | 408 | |
479 | 409 | |
480 | 410 | |
481 | 411 | |
482 | 412 | |
... | ... | @@ -473,50 +403,48 @@ |
473 | 403 | ret = request_irq(dev->irq, ax_ei_interrupt, ax->irqflags, |
474 | 404 | dev->name, dev); |
475 | 405 | if (ret) |
476 | - return ret; | |
406 | + goto failed_request_irq; | |
477 | 407 | |
478 | - ret = ax_ei_open(dev); | |
479 | - if (ret) { | |
480 | - free_irq(dev->irq, dev); | |
481 | - return ret; | |
482 | - } | |
483 | - | |
484 | 408 | /* turn the phy on (if turned off) */ |
409 | + ax_phy_switch(dev, 1); | |
485 | 410 | |
486 | - ei_outb(ax->plat->gpoc_val, ei_local->mem + EI_SHIFT(0x17)); | |
487 | - ax->running = 1; | |
411 | + ret = ax_mii_probe(dev); | |
412 | + if (ret) | |
413 | + goto failed_mii_probe; | |
414 | + phy_start(ax->phy_dev); | |
488 | 415 | |
489 | - /* start the MII timer */ | |
416 | + ret = ax_ei_open(dev); | |
417 | + if (ret) | |
418 | + goto failed_ax_ei_open; | |
490 | 419 | |
491 | - init_timer(&ax->mii_timer); | |
420 | + ax->running = 1; | |
492 | 421 | |
493 | - ax->mii_timer.expires = jiffies + 1; | |
494 | - ax->mii_timer.data = (unsigned long) dev; | |
495 | - ax->mii_timer.function = ax_mii_expiry; | |
496 | - | |
497 | - add_timer(&ax->mii_timer); | |
498 | - | |
499 | 422 | return 0; |
423 | + | |
424 | + failed_ax_ei_open: | |
425 | + phy_disconnect(ax->phy_dev); | |
426 | + failed_mii_probe: | |
427 | + ax_phy_switch(dev, 0); | |
428 | + free_irq(dev->irq, dev); | |
429 | + failed_request_irq: | |
430 | + return ret; | |
500 | 431 | } |
501 | 432 | |
502 | 433 | static int ax_close(struct net_device *dev) |
503 | 434 | { |
504 | 435 | struct ax_device *ax = to_ax_dev(dev); |
505 | - struct ei_device *ei_local = netdev_priv(dev); | |
506 | 436 | |
507 | 437 | netdev_dbg(dev, "close\n"); |
508 | 438 | |
509 | - /* turn the phy off */ | |
510 | - | |
511 | - ei_outb(ax->plat->gpoc_val | (1 << 6), | |
512 | - ei_local->mem + EI_SHIFT(0x17)); | |
513 | - | |
514 | 439 | ax->running = 0; |
515 | 440 | wmb(); |
516 | 441 | |
517 | - del_timer_sync(&ax->mii_timer); | |
518 | 442 | ax_ei_close(dev); |
519 | 443 | |
444 | + /* turn the phy off */ | |
445 | + ax_phy_switch(dev, 0); | |
446 | + phy_disconnect(ax->phy_dev); | |
447 | + | |
520 | 448 | free_irq(dev->irq, dev); |
521 | 449 | return 0; |
522 | 450 | } |
523 | 451 | |
524 | 452 | |
... | ... | @@ -524,17 +452,15 @@ |
524 | 452 | static int ax_ioctl(struct net_device *dev, struct ifreq *req, int cmd) |
525 | 453 | { |
526 | 454 | struct ax_device *ax = to_ax_dev(dev); |
527 | - unsigned long flags; | |
528 | - int rc; | |
455 | + struct phy_device *phy_dev = ax->phy_dev; | |
529 | 456 | |
530 | 457 | if (!netif_running(dev)) |
531 | 458 | return -EINVAL; |
532 | 459 | |
533 | - spin_lock_irqsave(&ax->mii_lock, flags); | |
534 | - rc = generic_mii_ioctl(&ax->mii, if_mii(req), cmd, NULL); | |
535 | - spin_unlock_irqrestore(&ax->mii_lock, flags); | |
460 | + if (!phy_dev) | |
461 | + return -ENODEV; | |
536 | 462 | |
537 | - return rc; | |
463 | + return phy_mii_ioctl(phy_dev, req, cmd); | |
538 | 464 | } |
539 | 465 | |
540 | 466 | /* ethtool ops */ |
541 | 467 | |
542 | 468 | |
543 | 469 | |
544 | 470 | |
545 | 471 | |
546 | 472 | |
547 | 473 | |
... | ... | @@ -552,46 +478,30 @@ |
552 | 478 | static int ax_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) |
553 | 479 | { |
554 | 480 | struct ax_device *ax = to_ax_dev(dev); |
555 | - unsigned long flags; | |
481 | + struct phy_device *phy_dev = ax->phy_dev; | |
556 | 482 | |
557 | - spin_lock_irqsave(&ax->mii_lock, flags); | |
558 | - mii_ethtool_gset(&ax->mii, cmd); | |
559 | - spin_unlock_irqrestore(&ax->mii_lock, flags); | |
483 | + if (!phy_dev) | |
484 | + return -ENODEV; | |
560 | 485 | |
561 | - return 0; | |
486 | + return phy_ethtool_gset(phy_dev, cmd); | |
562 | 487 | } |
563 | 488 | |
564 | 489 | static int ax_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) |
565 | 490 | { |
566 | 491 | struct ax_device *ax = to_ax_dev(dev); |
567 | - unsigned long flags; | |
568 | - int rc; | |
492 | + struct phy_device *phy_dev = ax->phy_dev; | |
569 | 493 | |
570 | - spin_lock_irqsave(&ax->mii_lock, flags); | |
571 | - rc = mii_ethtool_sset(&ax->mii, cmd); | |
572 | - spin_unlock_irqrestore(&ax->mii_lock, flags); | |
494 | + if (!phy_dev) | |
495 | + return -ENODEV; | |
573 | 496 | |
574 | - return rc; | |
497 | + return phy_ethtool_sset(phy_dev, cmd); | |
575 | 498 | } |
576 | 499 | |
577 | -static int ax_nway_reset(struct net_device *dev) | |
578 | -{ | |
579 | - struct ax_device *ax = to_ax_dev(dev); | |
580 | - return mii_nway_restart(&ax->mii); | |
581 | -} | |
582 | - | |
583 | -static u32 ax_get_link(struct net_device *dev) | |
584 | -{ | |
585 | - struct ax_device *ax = to_ax_dev(dev); | |
586 | - return mii_link_ok(&ax->mii); | |
587 | -} | |
588 | - | |
589 | 500 | static const struct ethtool_ops ax_ethtool_ops = { |
590 | 501 | .get_drvinfo = ax_get_drvinfo, |
591 | 502 | .get_settings = ax_get_settings, |
592 | 503 | .set_settings = ax_set_settings, |
593 | - .nway_reset = ax_nway_reset, | |
594 | - .get_link = ax_get_link, | |
504 | + .get_link = ethtool_op_get_link, | |
595 | 505 | }; |
596 | 506 | |
597 | 507 | #ifdef CONFIG_AX88796_93CX6 |
598 | 508 | |
... | ... | @@ -642,8 +552,102 @@ |
642 | 552 | #endif |
643 | 553 | }; |
644 | 554 | |
555 | +static void ax_bb_mdc(struct mdiobb_ctrl *ctrl, int level) | |
556 | +{ | |
557 | + struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl); | |
558 | + | |
559 | + if (level) | |
560 | + ax->reg_memr |= AX_MEMR_MDC; | |
561 | + else | |
562 | + ax->reg_memr &= ~AX_MEMR_MDC; | |
563 | + | |
564 | + ei_outb(ax->reg_memr, ax->addr_memr); | |
565 | +} | |
566 | + | |
567 | +static void ax_bb_dir(struct mdiobb_ctrl *ctrl, int output) | |
568 | +{ | |
569 | + struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl); | |
570 | + | |
571 | + if (output) | |
572 | + ax->reg_memr &= ~AX_MEMR_MDIR; | |
573 | + else | |
574 | + ax->reg_memr |= AX_MEMR_MDIR; | |
575 | + | |
576 | + ei_outb(ax->reg_memr, ax->addr_memr); | |
577 | +} | |
578 | + | |
579 | +static void ax_bb_set_data(struct mdiobb_ctrl *ctrl, int value) | |
580 | +{ | |
581 | + struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl); | |
582 | + | |
583 | + if (value) | |
584 | + ax->reg_memr |= AX_MEMR_MDO; | |
585 | + else | |
586 | + ax->reg_memr &= ~AX_MEMR_MDO; | |
587 | + | |
588 | + ei_outb(ax->reg_memr, ax->addr_memr); | |
589 | +} | |
590 | + | |
591 | +static int ax_bb_get_data(struct mdiobb_ctrl *ctrl) | |
592 | +{ | |
593 | + struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl); | |
594 | + int reg_memr = ei_inb(ax->addr_memr); | |
595 | + | |
596 | + return reg_memr & AX_MEMR_MDI ? 1 : 0; | |
597 | +} | |
598 | + | |
599 | +static struct mdiobb_ops bb_ops = { | |
600 | + .owner = THIS_MODULE, | |
601 | + .set_mdc = ax_bb_mdc, | |
602 | + .set_mdio_dir = ax_bb_dir, | |
603 | + .set_mdio_data = ax_bb_set_data, | |
604 | + .get_mdio_data = ax_bb_get_data, | |
605 | +}; | |
606 | + | |
645 | 607 | /* setup code */ |
646 | 608 | |
609 | +static int ax_mii_init(struct net_device *dev) | |
610 | +{ | |
611 | + struct platform_device *pdev = to_platform_device(dev->dev.parent); | |
612 | + struct ei_device *ei_local = netdev_priv(dev); | |
613 | + struct ax_device *ax = to_ax_dev(dev); | |
614 | + int err, i; | |
615 | + | |
616 | + ax->bb_ctrl.ops = &bb_ops; | |
617 | + ax->addr_memr = ei_local->mem + AX_MEMR; | |
618 | + ax->mii_bus = alloc_mdio_bitbang(&ax->bb_ctrl); | |
619 | + if (!ax->mii_bus) { | |
620 | + err = -ENOMEM; | |
621 | + goto out; | |
622 | + } | |
623 | + | |
624 | + ax->mii_bus->name = "ax88796_mii_bus"; | |
625 | + ax->mii_bus->parent = dev->dev.parent; | |
626 | + snprintf(ax->mii_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id); | |
627 | + | |
628 | + ax->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); | |
629 | + if (!ax->mii_bus->irq) { | |
630 | + err = -ENOMEM; | |
631 | + goto out_free_mdio_bitbang; | |
632 | + } | |
633 | + | |
634 | + for (i = 0; i < PHY_MAX_ADDR; i++) | |
635 | + ax->mii_bus->irq[i] = PHY_POLL; | |
636 | + | |
637 | + err = mdiobus_register(ax->mii_bus); | |
638 | + if (err) | |
639 | + goto out_free_irq; | |
640 | + | |
641 | + return 0; | |
642 | + | |
643 | + out_free_irq: | |
644 | + kfree(ax->mii_bus->irq); | |
645 | + out_free_mdio_bitbang: | |
646 | + free_mdio_bitbang(ax->mii_bus); | |
647 | + out: | |
648 | + return err; | |
649 | +} | |
650 | + | |
647 | 651 | static void ax_initial_setup(struct net_device *dev, struct ei_device *ei_local) |
648 | 652 | { |
649 | 653 | void __iomem *ioaddr = ei_local->mem; |
... | ... | @@ -763,15 +767,9 @@ |
763 | 767 | dev->netdev_ops = &ax_netdev_ops; |
764 | 768 | dev->ethtool_ops = &ax_ethtool_ops; |
765 | 769 | |
766 | - ax->msg_enable = NETIF_MSG_LINK; | |
767 | - ax->mii.phy_id_mask = 0x1f; | |
768 | - ax->mii.reg_num_mask = 0x1f; | |
769 | - ax->mii.phy_id = 0x10; /* onboard phy */ | |
770 | - ax->mii.force_media = 0; | |
771 | - ax->mii.full_duplex = 0; | |
772 | - ax->mii.mdio_read = ax_phy_read; | |
773 | - ax->mii.mdio_write = ax_phy_write; | |
774 | - ax->mii.dev = dev; | |
770 | + ret = ax_mii_init(dev); | |
771 | + if (ret) | |
772 | + goto out_irq; | |
775 | 773 | |
776 | 774 | ax_NS8390_init(dev, 0); |
777 | 775 | |
... | ... | @@ -841,8 +839,6 @@ |
841 | 839 | SET_NETDEV_DEV(dev, &pdev->dev); |
842 | 840 | ei_local = netdev_priv(dev); |
843 | 841 | ax = to_ax_dev(dev); |
844 | - | |
845 | - spin_lock_init(&ax->mii_lock); | |
846 | 842 | |
847 | 843 | ax->plat = pdev->dev.platform_data; |
848 | 844 | platform_set_drvdata(pdev, dev); |