diff options
Diffstat (limited to 'drivers/net/r8169.c')
-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); |