diff options
| author | françois romieu <romieu@fr.zoreil.com> | 2011-01-03 10:08:21 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2011-01-04 12:48:34 -0500 |
| commit | b646d90053f887c1bc243191e693a9b02d09f2c2 (patch) | |
| tree | 872afc33029335e5435ed2f5485b4c5b0339b060 | |
| parent | 065c27c184d64aeb9ae107c0ef7026ea3642b15b (diff) | |
r8169: magic.
Adapted from version 8.019.00 of Realtek's r8168 driver.
Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
Cc: Hayes <hayeswang@realtek.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | drivers/net/r8169.c | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 0ec47f463157..a73dd287fdba 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c | |||
| @@ -278,6 +278,18 @@ enum rtl8168_8101_registers { | |||
| 278 | }; | 278 | }; |
| 279 | 279 | ||
| 280 | enum rtl8168_registers { | 280 | enum rtl8168_registers { |
| 281 | ERIDR = 0x70, | ||
| 282 | ERIAR = 0x74, | ||
| 283 | #define ERIAR_FLAG 0x80000000 | ||
| 284 | #define ERIAR_WRITE_CMD 0x80000000 | ||
| 285 | #define ERIAR_READ_CMD 0x00000000 | ||
| 286 | #define ERIAR_ADDR_BYTE_ALIGN 4 | ||
| 287 | #define ERIAR_EXGMAC 0 | ||
| 288 | #define ERIAR_MSIX 1 | ||
| 289 | #define ERIAR_ASF 2 | ||
| 290 | #define ERIAR_TYPE_SHIFT 16 | ||
| 291 | #define ERIAR_BYTEEN 0x0f | ||
| 292 | #define ERIAR_BYTEEN_SHIFT 12 | ||
| 281 | EPHY_RXER_NUM = 0x7c, | 293 | EPHY_RXER_NUM = 0x7c, |
| 282 | OCPDR = 0xb0, /* OCP GPHY access */ | 294 | OCPDR = 0xb0, /* OCP GPHY access */ |
| 283 | #define OCPDR_WRITE_CMD 0x80000000 | 295 | #define OCPDR_WRITE_CMD 0x80000000 |
| @@ -572,6 +584,81 @@ static int rtl8169_poll(struct napi_struct *napi, int budget); | |||
| 572 | static const unsigned int rtl8169_rx_config = | 584 | static const unsigned int rtl8169_rx_config = |
| 573 | (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); | 585 | (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); |
| 574 | 586 | ||
| 587 | static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg) | ||
| 588 | { | ||
| 589 | void __iomem *ioaddr = tp->mmio_addr; | ||
| 590 | int i; | ||
| 591 | |||
| 592 | RTL_W32(OCPAR, ((u32)mask & 0x0f) << 12 | (reg & 0x0fff)); | ||
| 593 | for (i = 0; i < 20; i++) { | ||
| 594 | udelay(100); | ||
| 595 | if (RTL_R32(OCPAR) & OCPAR_FLAG) | ||
| 596 | break; | ||
| 597 | } | ||
| 598 | return RTL_R32(OCPDR); | ||
| 599 | } | ||
| 600 | |||
| 601 | static void ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg, u32 data) | ||
| 602 | { | ||
| 603 | void __iomem *ioaddr = tp->mmio_addr; | ||
| 604 | int i; | ||
| 605 | |||
| 606 | RTL_W32(OCPDR, data); | ||
| 607 | RTL_W32(OCPAR, OCPAR_FLAG | ((u32)mask & 0x0f) << 12 | (reg & 0x0fff)); | ||
| 608 | for (i = 0; i < 20; i++) { | ||
| 609 | udelay(100); | ||
| 610 | if ((RTL_R32(OCPAR) & OCPAR_FLAG) == 0) | ||
| 611 | break; | ||
| 612 | } | ||
| 613 | } | ||
| 614 | |||
| 615 | static void rtl8168_oob_notify(void __iomem *ioaddr, u8 cmd) | ||
| 616 | { | ||
| 617 | int i; | ||
| 618 | |||
| 619 | RTL_W8(ERIDR, cmd); | ||
| 620 | RTL_W32(ERIAR, 0x800010e8); | ||
| 621 | msleep(2); | ||
| 622 | for (i = 0; i < 5; i++) { | ||
| 623 | udelay(100); | ||
| 624 | if (!(RTL_R32(ERIDR) & ERIAR_FLAG)) | ||
| 625 | break; | ||
| 626 | } | ||
| 627 | |||
| 628 | ocp_write(ioaddr, 0x1, 0x30, 0x00000001); | ||
| 629 | } | ||
| 630 | |||
| 631 | #define OOB_CMD_RESET 0x00 | ||
| 632 | #define OOB_CMD_DRIVER_START 0x05 | ||
| 633 | #define OOB_CMD_DRIVER_STOP 0x06 | ||
| 634 | |||
| 635 | static void rtl8168_driver_start(struct rtl8169_private *tp) | ||
| 636 | { | ||
| 637 | int i; | ||
| 638 | |||
| 639 | rtl8168_oob_notify(tp, OOB_CMD_DRIVER_START); | ||
| 640 | |||
| 641 | for (i = 0; i < 10; i++) { | ||
| 642 | msleep(10); | ||
| 643 | if (ocp_read(tp, 0x0f, 0x0010) & 0x00000800) | ||
| 644 | break; | ||
| 645 | } | ||
| 646 | } | ||
| 647 | |||
| 648 | static void rtl8168_driver_stop(struct rtl8169_private *tp) | ||
| 649 | { | ||
| 650 | int i; | ||
| 651 | |||
| 652 | rtl8168_oob_notify(tp, OOB_CMD_DRIVER_STOP); | ||
| 653 | |||
| 654 | for (i = 0; i < 10; i++) { | ||
| 655 | msleep(10); | ||
| 656 | if ((ocp_read(tp, 0x0f, 0x0010) & 0x00000800) == 0) | ||
| 657 | break; | ||
| 658 | } | ||
| 659 | } | ||
| 660 | |||
| 661 | |||
| 575 | static void r8169_mdio_write(void __iomem *ioaddr, int reg_addr, int value) | 662 | static void r8169_mdio_write(void __iomem *ioaddr, int reg_addr, int value) |
| 576 | { | 663 | { |
| 577 | int i; | 664 | int i; |
| @@ -2913,6 +3000,9 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 2913 | dev->base_addr, dev->dev_addr, | 3000 | dev->base_addr, dev->dev_addr, |
| 2914 | (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), dev->irq); | 3001 | (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), dev->irq); |
| 2915 | 3002 | ||
| 3003 | if (tp->mac_version == RTL_GIGA_MAC_VER_27) | ||
| 3004 | rtl8168_driver_start(tp); | ||
| 3005 | |||
| 2916 | rtl8169_init_phy(dev, tp); | 3006 | rtl8169_init_phy(dev, tp); |
| 2917 | 3007 | ||
| 2918 | /* | 3008 | /* |
| @@ -2948,6 +3038,9 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev) | |||
| 2948 | struct net_device *dev = pci_get_drvdata(pdev); | 3038 | struct net_device *dev = pci_get_drvdata(pdev); |
| 2949 | struct rtl8169_private *tp = netdev_priv(dev); | 3039 | struct rtl8169_private *tp = netdev_priv(dev); |
| 2950 | 3040 | ||
| 3041 | if (tp->mac_version == RTL_GIGA_MAC_VER_27) | ||
| 3042 | rtl8168_driver_stop(tp); | ||
| 3043 | |||
| 2951 | cancel_delayed_work_sync(&tp->task); | 3044 | cancel_delayed_work_sync(&tp->task); |
| 2952 | 3045 | ||
| 2953 | unregister_netdev(dev); | 3046 | unregister_netdev(dev); |
