diff options
-rw-r--r-- | drivers/net/Kconfig | 4 | ||||
-rw-r--r-- | drivers/net/ax88796.c | 392 |
2 files changed, 196 insertions, 200 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 65027a72ca93..f4b39274308a 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
@@ -238,8 +238,8 @@ source "drivers/net/arm/Kconfig" | |||
238 | config AX88796 | 238 | config AX88796 |
239 | tristate "ASIX AX88796 NE2000 clone support" | 239 | tristate "ASIX AX88796 NE2000 clone support" |
240 | depends on ARM || MIPS || SUPERH | 240 | depends on ARM || MIPS || SUPERH |
241 | select CRC32 | 241 | select PHYLIB |
242 | select MII | 242 | select MDIO_BITBANG |
243 | help | 243 | help |
244 | AX88796 driver, using platform bus to provide | 244 | AX88796 driver, using platform bus to provide |
245 | chip detection and resources | 245 | chip detection and resources |
diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c index e62d0ba891e8..e7cb8c8b9776 100644 --- a/drivers/net/ax88796.c +++ b/drivers/net/ax88796.c | |||
@@ -24,7 +24,8 @@ | |||
24 | #include <linux/netdevice.h> | 24 | #include <linux/netdevice.h> |
25 | #include <linux/etherdevice.h> | 25 | #include <linux/etherdevice.h> |
26 | #include <linux/ethtool.h> | 26 | #include <linux/ethtool.h> |
27 | #include <linux/mii.h> | 27 | #include <linux/mdio-bitbang.h> |
28 | #include <linux/phy.h> | ||
28 | #include <linux/eeprom_93cx6.h> | 29 | #include <linux/eeprom_93cx6.h> |
29 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
30 | 31 | ||
@@ -32,8 +33,6 @@ | |||
32 | 33 | ||
33 | #include <asm/system.h> | 34 | #include <asm/system.h> |
34 | 35 | ||
35 | static int phy_debug; | ||
36 | |||
37 | /* Rename the lib8390.c functions to show that they are in this driver */ | 36 | /* Rename the lib8390.c functions to show that they are in this driver */ |
38 | #define __ei_open ax_ei_open | 37 | #define __ei_open ax_ei_open |
39 | #define __ei_close ax_ei_close | 38 | #define __ei_close ax_ei_close |
@@ -78,14 +77,20 @@ static unsigned char version[] = "ax88796.c: Copyright 2005,2007 Simtec Electron | |||
78 | #define NESM_START_PG 0x40 /* First page of TX buffer */ | 77 | #define NESM_START_PG 0x40 /* First page of TX buffer */ |
79 | #define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ | 78 | #define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ |
80 | 79 | ||
80 | #define AX_GPOC_PPDSET BIT(6) | ||
81 | |||
81 | /* device private data */ | 82 | /* device private data */ |
82 | 83 | ||
83 | struct ax_device { | 84 | struct ax_device { |
84 | struct timer_list mii_timer; | 85 | struct mii_bus *mii_bus; |
85 | spinlock_t mii_lock; | 86 | struct mdiobb_ctrl bb_ctrl; |
86 | struct mii_if_info mii; | 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 | void __iomem *map2; | 94 | void __iomem *map2; |
90 | const struct ax_plat_data *plat; | 95 | const struct ax_plat_data *plat; |
91 | 96 | ||
@@ -313,159 +318,84 @@ static void ax_block_output(struct net_device *dev, int count, | |||
313 | #define AX_MEMR_EEO BIT(6) | 318 | #define AX_MEMR_EEO BIT(6) |
314 | #define AX_MEMR_EECLK BIT(7) | 319 | #define AX_MEMR_EECLK BIT(7) |
315 | 320 | ||
316 | /* | 321 | static void ax_handle_link_change(struct net_device *dev) |
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) | ||
323 | { | 322 | { |
324 | struct ei_device *ei_local = netdev_priv(dev); | 323 | struct ax_device *ax = to_ax_dev(dev); |
325 | void __iomem *memr_addr = (void __iomem *)dev->base_addr + AX_MEMR; | 324 | struct phy_device *phy_dev = ax->phy_dev; |
326 | unsigned int memr; | 325 | int status_change = 0; |
327 | |||
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); | ||
332 | |||
333 | for (len--; len >= 0; len--) { | ||
334 | if (bits & (1 << len)) | ||
335 | memr |= AX_MEMR_MDO; | ||
336 | else | ||
337 | memr &= ~AX_MEMR_MDO; | ||
338 | 326 | ||
339 | ei_outb(memr, memr_addr); | 327 | if (phy_dev->link && ((ax->speed != phy_dev->speed) || |
328 | (ax->duplex != phy_dev->duplex))) { | ||
340 | 329 | ||
341 | /* clock high */ | 330 | ax->speed = phy_dev->speed; |
342 | 331 | ax->duplex = phy_dev->duplex; | |
343 | ei_outb(memr | AX_MEMR_MDC, memr_addr); | 332 | status_change = 1; |
344 | udelay(1); | ||
345 | |||
346 | /* clock low */ | ||
347 | ei_outb(memr, memr_addr); | ||
348 | } | 333 | } |
349 | 334 | ||
350 | /* leaves the clock line low, mdir input */ | 335 | if (phy_dev->link != ax->link) { |
351 | memr |= AX_MEMR_MDIR; | 336 | if (!phy_dev->link) { |
352 | ei_outb(memr, (void __iomem *)dev->base_addr + AX_MEMR); | 337 | ax->speed = 0; |
353 | } | 338 | ax->duplex = -1; |
354 | 339 | } | |
355 | /* | 340 | ax->link = phy_dev->link; |
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) | ||
362 | { | ||
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; | ||
367 | |||
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); | ||
373 | |||
374 | for (no--; no >= 0; no--) { | ||
375 | ei_outb(memr | AX_MEMR_MDC, memr_addr); | ||
376 | |||
377 | udelay(1); | ||
378 | |||
379 | if (ei_inb(memr_addr) & AX_MEMR_MDI) | ||
380 | result |= (1 << no); | ||
381 | 341 | ||
382 | ei_outb(memr, memr_addr); | 342 | status_change = 1; |
383 | } | 343 | } |
384 | 344 | ||
385 | return result; | 345 | if (status_change) |
346 | phy_print_status(phy_dev); | ||
386 | } | 347 | } |
387 | 348 | ||
388 | /* | 349 | static int ax_mii_probe(struct net_device *dev) |
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) | ||
396 | { | ||
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 | { | 350 | { |
411 | struct ei_device *ei_local = netdev_priv(dev); | 351 | struct ax_device *ax = to_ax_dev(dev); |
412 | unsigned long flags; | 352 | struct phy_device *phy_dev = NULL; |
413 | unsigned int result; | 353 | int ret; |
414 | |||
415 | spin_lock_irqsave(&ei_local->page_lock, flags); | ||
416 | |||
417 | ax_phy_issueaddr(dev, phy_addr, reg, 2); | ||
418 | |||
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 | 354 | ||
428 | return result; | 355 | /* find the first phy */ |
429 | } | 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 | } | ||
430 | 361 | ||
431 | static void | 362 | ret = phy_connect_direct(dev, phy_dev, ax_handle_link_change, 0, |
432 | ax_phy_write(struct net_device *dev, int phy_addr, int reg, int value) | 363 | PHY_INTERFACE_MODE_MII); |
433 | { | 364 | if (ret) { |
434 | struct ei_device *ei = netdev_priv(dev); | 365 | netdev_err(dev, "Could not attach to PHY\n"); |
435 | unsigned long flags; | 366 | return ret; |
367 | } | ||
436 | 368 | ||
437 | netdev_dbg(dev, "%s: %p, %04x, %04x %04x\n", | 369 | /* mask with MAC supported features */ |
438 | __func__, dev, phy_addr, reg, value); | 370 | phy_dev->supported &= PHY_BASIC_FEATURES; |
371 | phy_dev->advertising = phy_dev->supported; | ||
439 | 372 | ||
440 | spin_lock_irqsave(&ei->page_lock, flags); | 373 | ax->phy_dev = phy_dev; |
441 | 374 | ||
442 | ax_phy_issueaddr(dev, phy_addr, reg, 1); | 375 | netdev_info(dev, "PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", |
443 | ax_mii_ei_outbits(dev, 2, 2); /* send TA */ | 376 | phy_dev->drv->name, dev_name(&phy_dev->dev), phy_dev->irq); |
444 | ax_mii_ei_outbits(dev, value, 16); | ||
445 | 377 | ||
446 | spin_unlock_irqrestore(&ei->page_lock, flags); | 378 | return 0; |
447 | } | 379 | } |
448 | 380 | ||
449 | static void ax_mii_expiry(unsigned long data) | 381 | static void ax_phy_switch(struct net_device *dev, int on) |
450 | { | 382 | { |
451 | struct net_device *dev = (struct net_device *)data; | 383 | struct ei_device *ei_local = netdev_priv(dev); |
452 | struct ax_device *ax = to_ax_dev(dev); | 384 | struct ax_device *ax = to_ax_dev(dev); |
453 | unsigned long flags; | ||
454 | 385 | ||
455 | spin_lock_irqsave(&ax->mii_lock, flags); | 386 | u8 reg_gpoc = ax->plat->gpoc_val; |
456 | mii_check_media(&ax->mii, netif_msg_link(ax), 0); | ||
457 | spin_unlock_irqrestore(&ax->mii_lock, flags); | ||
458 | 387 | ||
459 | if (ax->running) { | 388 | if (!!on) |
460 | ax->mii_timer.expires = jiffies + HZ*2; | 389 | reg_gpoc &= ~AX_GPOC_PPDSET; |
461 | add_timer(&ax->mii_timer); | 390 | else |
462 | } | 391 | reg_gpoc |= AX_GPOC_PPDSET; |
392 | |||
393 | ei_outb(reg_gpoc, ei_local->mem + EI_SHIFT(0x17)); | ||
463 | } | 394 | } |
464 | 395 | ||
465 | static int ax_open(struct net_device *dev) | 396 | static int ax_open(struct net_device *dev) |
466 | { | 397 | { |
467 | struct ax_device *ax = to_ax_dev(dev); | 398 | struct ax_device *ax = to_ax_dev(dev); |
468 | struct ei_device *ei_local = netdev_priv(dev); | ||
469 | int ret; | 399 | int ret; |
470 | 400 | ||
471 | netdev_dbg(dev, "open\n"); | 401 | netdev_dbg(dev, "open\n"); |
@@ -473,50 +403,48 @@ static int ax_open(struct net_device *dev) | |||
473 | ret = request_irq(dev->irq, ax_ei_interrupt, ax->irqflags, | 403 | ret = request_irq(dev->irq, ax_ei_interrupt, ax->irqflags, |
474 | dev->name, dev); | 404 | dev->name, dev); |
475 | if (ret) | 405 | if (ret) |
476 | return ret; | 406 | goto failed_request_irq; |
477 | |||
478 | ret = ax_ei_open(dev); | ||
479 | if (ret) { | ||
480 | free_irq(dev->irq, dev); | ||
481 | return ret; | ||
482 | } | ||
483 | 407 | ||
484 | /* turn the phy on (if turned off) */ | 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)); | 411 | ret = ax_mii_probe(dev); |
487 | ax->running = 1; | 412 | if (ret) |
488 | 413 | goto failed_mii_probe; | |
489 | /* start the MII timer */ | 414 | phy_start(ax->phy_dev); |
490 | |||
491 | init_timer(&ax->mii_timer); | ||
492 | 415 | ||
493 | ax->mii_timer.expires = jiffies + 1; | 416 | ret = ax_ei_open(dev); |
494 | ax->mii_timer.data = (unsigned long) dev; | 417 | if (ret) |
495 | ax->mii_timer.function = ax_mii_expiry; | 418 | goto failed_ax_ei_open; |
496 | 419 | ||
497 | add_timer(&ax->mii_timer); | 420 | ax->running = 1; |
498 | 421 | ||
499 | return 0; | 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 | static int ax_close(struct net_device *dev) | 433 | static int ax_close(struct net_device *dev) |
503 | { | 434 | { |
504 | struct ax_device *ax = to_ax_dev(dev); | 435 | struct ax_device *ax = to_ax_dev(dev); |
505 | struct ei_device *ei_local = netdev_priv(dev); | ||
506 | 436 | ||
507 | netdev_dbg(dev, "close\n"); | 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 | ax->running = 0; | 439 | ax->running = 0; |
515 | wmb(); | 440 | wmb(); |
516 | 441 | ||
517 | del_timer_sync(&ax->mii_timer); | ||
518 | ax_ei_close(dev); | 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 | free_irq(dev->irq, dev); | 448 | free_irq(dev->irq, dev); |
521 | return 0; | 449 | return 0; |
522 | } | 450 | } |
@@ -524,17 +452,15 @@ static int ax_close(struct net_device *dev) | |||
524 | static int ax_ioctl(struct net_device *dev, struct ifreq *req, int cmd) | 452 | static int ax_ioctl(struct net_device *dev, struct ifreq *req, int cmd) |
525 | { | 453 | { |
526 | struct ax_device *ax = to_ax_dev(dev); | 454 | struct ax_device *ax = to_ax_dev(dev); |
527 | unsigned long flags; | 455 | struct phy_device *phy_dev = ax->phy_dev; |
528 | int rc; | ||
529 | 456 | ||
530 | if (!netif_running(dev)) | 457 | if (!netif_running(dev)) |
531 | return -EINVAL; | 458 | return -EINVAL; |
532 | 459 | ||
533 | spin_lock_irqsave(&ax->mii_lock, flags); | 460 | if (!phy_dev) |
534 | rc = generic_mii_ioctl(&ax->mii, if_mii(req), cmd, NULL); | 461 | return -ENODEV; |
535 | spin_unlock_irqrestore(&ax->mii_lock, flags); | ||
536 | 462 | ||
537 | return rc; | 463 | return phy_mii_ioctl(phy_dev, req, cmd); |
538 | } | 464 | } |
539 | 465 | ||
540 | /* ethtool ops */ | 466 | /* ethtool ops */ |
@@ -552,46 +478,30 @@ static void ax_get_drvinfo(struct net_device *dev, | |||
552 | static int ax_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | 478 | static int ax_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) |
553 | { | 479 | { |
554 | struct ax_device *ax = to_ax_dev(dev); | 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); | 483 | if (!phy_dev) |
558 | mii_ethtool_gset(&ax->mii, cmd); | 484 | return -ENODEV; |
559 | spin_unlock_irqrestore(&ax->mii_lock, flags); | ||
560 | 485 | ||
561 | return 0; | 486 | return phy_ethtool_gset(phy_dev, cmd); |
562 | } | 487 | } |
563 | 488 | ||
564 | static int ax_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | 489 | static int ax_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) |
565 | { | 490 | { |
566 | struct ax_device *ax = to_ax_dev(dev); | 491 | struct ax_device *ax = to_ax_dev(dev); |
567 | unsigned long flags; | 492 | struct phy_device *phy_dev = ax->phy_dev; |
568 | int rc; | ||
569 | |||
570 | spin_lock_irqsave(&ax->mii_lock, flags); | ||
571 | rc = mii_ethtool_sset(&ax->mii, cmd); | ||
572 | spin_unlock_irqrestore(&ax->mii_lock, flags); | ||
573 | 493 | ||
574 | return rc; | 494 | if (!phy_dev) |
575 | } | 495 | return -ENODEV; |
576 | |||
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 | 496 | ||
583 | static u32 ax_get_link(struct net_device *dev) | 497 | return phy_ethtool_sset(phy_dev, cmd); |
584 | { | ||
585 | struct ax_device *ax = to_ax_dev(dev); | ||
586 | return mii_link_ok(&ax->mii); | ||
587 | } | 498 | } |
588 | 499 | ||
589 | static const struct ethtool_ops ax_ethtool_ops = { | 500 | static const struct ethtool_ops ax_ethtool_ops = { |
590 | .get_drvinfo = ax_get_drvinfo, | 501 | .get_drvinfo = ax_get_drvinfo, |
591 | .get_settings = ax_get_settings, | 502 | .get_settings = ax_get_settings, |
592 | .set_settings = ax_set_settings, | 503 | .set_settings = ax_set_settings, |
593 | .nway_reset = ax_nway_reset, | 504 | .get_link = ethtool_op_get_link, |
594 | .get_link = ax_get_link, | ||
595 | }; | 505 | }; |
596 | 506 | ||
597 | #ifdef CONFIG_AX88796_93CX6 | 507 | #ifdef CONFIG_AX88796_93CX6 |
@@ -642,8 +552,102 @@ static const struct net_device_ops ax_netdev_ops = { | |||
642 | #endif | 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 | /* setup code */ | 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 | static void ax_initial_setup(struct net_device *dev, struct ei_device *ei_local) | 651 | static void ax_initial_setup(struct net_device *dev, struct ei_device *ei_local) |
648 | { | 652 | { |
649 | void __iomem *ioaddr = ei_local->mem; | 653 | void __iomem *ioaddr = ei_local->mem; |
@@ -763,15 +767,9 @@ static int ax_init_dev(struct net_device *dev) | |||
763 | dev->netdev_ops = &ax_netdev_ops; | 767 | dev->netdev_ops = &ax_netdev_ops; |
764 | dev->ethtool_ops = &ax_ethtool_ops; | 768 | dev->ethtool_ops = &ax_ethtool_ops; |
765 | 769 | ||
766 | ax->msg_enable = NETIF_MSG_LINK; | 770 | ret = ax_mii_init(dev); |
767 | ax->mii.phy_id_mask = 0x1f; | 771 | if (ret) |
768 | ax->mii.reg_num_mask = 0x1f; | 772 | goto out_irq; |
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; | ||
775 | 773 | ||
776 | ax_NS8390_init(dev, 0); | 774 | ax_NS8390_init(dev, 0); |
777 | 775 | ||
@@ -842,8 +840,6 @@ static int ax_probe(struct platform_device *pdev) | |||
842 | ei_local = netdev_priv(dev); | 840 | ei_local = netdev_priv(dev); |
843 | ax = to_ax_dev(dev); | 841 | ax = to_ax_dev(dev); |
844 | 842 | ||
845 | spin_lock_init(&ax->mii_lock); | ||
846 | |||
847 | ax->plat = pdev->dev.platform_data; | 843 | ax->plat = pdev->dev.platform_data; |
848 | platform_set_drvdata(pdev, dev); | 844 | platform_set_drvdata(pdev, dev); |
849 | 845 | ||