aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ax88796.c
diff options
context:
space:
mode:
authorMarc Kleine-Budde <mkl@pengutronix.de>2011-02-21 06:41:55 -0500
committerMarc Kleine-Budde <mkl@pengutronix.de>2011-02-21 07:49:48 -0500
commitf6d7f2c60d3a63d786feeb60628f930cd2d8e912 (patch)
treef229262dec3cd9c7bca6fe5c440a4e1a76fe16fa /drivers/net/ax88796.c
parentc9218c3a8231c0a67662d85266698f2f037cac20 (diff)
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>
Diffstat (limited to 'drivers/net/ax88796.c')
-rw-r--r--drivers/net/ax88796.c392
1 files changed, 194 insertions, 198 deletions
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
35static 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
83struct ax_device { 84struct 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/* 321static 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 */
321static void
322ax_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 */
360static unsigned int
361ax_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/* 349static 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 */
394static void
395ax_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
408static int
409ax_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
431static void 362 ret = phy_connect_direct(dev, phy_dev, ax_handle_link_change, 0,
432ax_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
449static void ax_mii_expiry(unsigned long data) 381static 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
465static int ax_open(struct net_device *dev) 396static 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
502static int ax_close(struct net_device *dev) 433static 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)
524static int ax_ioctl(struct net_device *dev, struct ifreq *req, int cmd) 452static 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,
552static int ax_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) 478static 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
564static int ax_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) 489static 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
577static 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
583static 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
589static const struct ethtool_ops ax_ethtool_ops = { 500static 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
555static 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
567static 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
579static 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
591static 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
599static 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
609static 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
647static void ax_initial_setup(struct net_device *dev, struct ei_device *ei_local) 651static 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