diff options
author | françois romieu <romieu@fr.zoreil.com> | 2011-01-03 10:08:12 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-01-04 12:48:33 -0500 |
commit | 065c27c184d64aeb9ae107c0ef7026ea3642b15b (patch) | |
tree | fbb2d63530efae5bbe38241abdc301ac223f717b /drivers/net/r8169.c | |
parent | c0e45c1ca3162acb2e77b3d9e152ce6e7b6fa3f5 (diff) |
r8169: phy power ops
Bits from :
- version 8.019.00 of Realtek's 8168 driver
- version 1.019.00 of Realtek's 8101 driver
Plain old 8169 (PCI) devices do not seem to need anything akin to it.
Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
Cc: Hayes <hayeswang@realtek.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/r8169.c')
-rw-r--r-- | drivers/net/r8169.c | 167 |
1 files changed, 166 insertions, 1 deletions
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 3a63363e47cc..0ec47f463157 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c | |||
@@ -258,7 +258,7 @@ enum rtl8168_8101_registers { | |||
258 | #define CSIAR_BYTE_ENABLE 0x0f | 258 | #define CSIAR_BYTE_ENABLE 0x0f |
259 | #define CSIAR_BYTE_ENABLE_SHIFT 12 | 259 | #define CSIAR_BYTE_ENABLE_SHIFT 12 |
260 | #define CSIAR_ADDR_MASK 0x0fff | 260 | #define CSIAR_ADDR_MASK 0x0fff |
261 | 261 | PMCH = 0x6f, | |
262 | EPHYAR = 0x80, | 262 | EPHYAR = 0x80, |
263 | #define EPHYAR_FLAG 0x80000000 | 263 | #define EPHYAR_FLAG 0x80000000 |
264 | #define EPHYAR_WRITE_CMD 0x80000000 | 264 | #define EPHYAR_WRITE_CMD 0x80000000 |
@@ -520,6 +520,11 @@ struct rtl8169_private { | |||
520 | int (*read)(void __iomem *, int); | 520 | int (*read)(void __iomem *, int); |
521 | } mdio_ops; | 521 | } mdio_ops; |
522 | 522 | ||
523 | struct pll_power_ops { | ||
524 | void (*down)(struct rtl8169_private *); | ||
525 | void (*up)(struct rtl8169_private *); | ||
526 | } pll_power_ops; | ||
527 | |||
523 | int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); | 528 | int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); |
524 | int (*get_settings)(struct net_device *, struct ethtool_cmd *); | 529 | int (*get_settings)(struct net_device *, struct ethtool_cmd *); |
525 | void (*phy_reset_enable)(struct rtl8169_private *tp); | 530 | void (*phy_reset_enable)(struct rtl8169_private *tp); |
@@ -2551,6 +2556,152 @@ static void __devinit rtl_init_mdio_ops(struct rtl8169_private *tp) | |||
2551 | } | 2556 | } |
2552 | } | 2557 | } |
2553 | 2558 | ||
2559 | static void r810x_phy_power_down(struct rtl8169_private *tp) | ||
2560 | { | ||
2561 | rtl_writephy(tp, 0x1f, 0x0000); | ||
2562 | rtl_writephy(tp, MII_BMCR, BMCR_PDOWN); | ||
2563 | } | ||
2564 | |||
2565 | static void r810x_phy_power_up(struct rtl8169_private *tp) | ||
2566 | { | ||
2567 | rtl_writephy(tp, 0x1f, 0x0000); | ||
2568 | rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE); | ||
2569 | } | ||
2570 | |||
2571 | static void r810x_pll_power_down(struct rtl8169_private *tp) | ||
2572 | { | ||
2573 | if (__rtl8169_get_wol(tp) & WAKE_ANY) { | ||
2574 | rtl_writephy(tp, 0x1f, 0x0000); | ||
2575 | rtl_writephy(tp, MII_BMCR, 0x0000); | ||
2576 | return; | ||
2577 | } | ||
2578 | |||
2579 | r810x_phy_power_down(tp); | ||
2580 | } | ||
2581 | |||
2582 | static void r810x_pll_power_up(struct rtl8169_private *tp) | ||
2583 | { | ||
2584 | r810x_phy_power_up(tp); | ||
2585 | } | ||
2586 | |||
2587 | static void r8168_phy_power_up(struct rtl8169_private *tp) | ||
2588 | { | ||
2589 | rtl_writephy(tp, 0x1f, 0x0000); | ||
2590 | rtl_writephy(tp, 0x0e, 0x0000); | ||
2591 | rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE); | ||
2592 | } | ||
2593 | |||
2594 | static void r8168_phy_power_down(struct rtl8169_private *tp) | ||
2595 | { | ||
2596 | rtl_writephy(tp, 0x1f, 0x0000); | ||
2597 | rtl_writephy(tp, 0x0e, 0x0200); | ||
2598 | rtl_writephy(tp, MII_BMCR, BMCR_PDOWN); | ||
2599 | } | ||
2600 | |||
2601 | static void r8168_pll_power_down(struct rtl8169_private *tp) | ||
2602 | { | ||
2603 | void __iomem *ioaddr = tp->mmio_addr; | ||
2604 | |||
2605 | if (tp->mac_version == RTL_GIGA_MAC_VER_27) | ||
2606 | return; | ||
2607 | |||
2608 | if (((tp->mac_version == RTL_GIGA_MAC_VER_23) || | ||
2609 | (tp->mac_version == RTL_GIGA_MAC_VER_24)) && | ||
2610 | (RTL_R16(CPlusCmd) & ASF)) { | ||
2611 | return; | ||
2612 | } | ||
2613 | |||
2614 | if (__rtl8169_get_wol(tp) & WAKE_ANY) { | ||
2615 | rtl_writephy(tp, 0x1f, 0x0000); | ||
2616 | rtl_writephy(tp, MII_BMCR, 0x0000); | ||
2617 | |||
2618 | RTL_W32(RxConfig, RTL_R32(RxConfig) | | ||
2619 | AcceptBroadcast | AcceptMulticast | AcceptMyPhys); | ||
2620 | return; | ||
2621 | } | ||
2622 | |||
2623 | r8168_phy_power_down(tp); | ||
2624 | |||
2625 | switch (tp->mac_version) { | ||
2626 | case RTL_GIGA_MAC_VER_25: | ||
2627 | case RTL_GIGA_MAC_VER_26: | ||
2628 | RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80); | ||
2629 | break; | ||
2630 | } | ||
2631 | } | ||
2632 | |||
2633 | static void r8168_pll_power_up(struct rtl8169_private *tp) | ||
2634 | { | ||
2635 | void __iomem *ioaddr = tp->mmio_addr; | ||
2636 | |||
2637 | if (tp->mac_version == RTL_GIGA_MAC_VER_27) | ||
2638 | return; | ||
2639 | |||
2640 | switch (tp->mac_version) { | ||
2641 | case RTL_GIGA_MAC_VER_25: | ||
2642 | case RTL_GIGA_MAC_VER_26: | ||
2643 | RTL_W8(PMCH, RTL_R8(PMCH) | 0x80); | ||
2644 | break; | ||
2645 | } | ||
2646 | |||
2647 | r8168_phy_power_up(tp); | ||
2648 | } | ||
2649 | |||
2650 | static void rtl_pll_power_op(struct rtl8169_private *tp, | ||
2651 | void (*op)(struct rtl8169_private *)) | ||
2652 | { | ||
2653 | if (op) | ||
2654 | op(tp); | ||
2655 | } | ||
2656 | |||
2657 | static void rtl_pll_power_down(struct rtl8169_private *tp) | ||
2658 | { | ||
2659 | rtl_pll_power_op(tp, tp->pll_power_ops.down); | ||
2660 | } | ||
2661 | |||
2662 | static void rtl_pll_power_up(struct rtl8169_private *tp) | ||
2663 | { | ||
2664 | rtl_pll_power_op(tp, tp->pll_power_ops.up); | ||
2665 | } | ||
2666 | |||
2667 | static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp) | ||
2668 | { | ||
2669 | struct pll_power_ops *ops = &tp->pll_power_ops; | ||
2670 | |||
2671 | switch (tp->mac_version) { | ||
2672 | case RTL_GIGA_MAC_VER_07: | ||
2673 | case RTL_GIGA_MAC_VER_08: | ||
2674 | case RTL_GIGA_MAC_VER_09: | ||
2675 | case RTL_GIGA_MAC_VER_10: | ||
2676 | case RTL_GIGA_MAC_VER_16: | ||
2677 | ops->down = r810x_pll_power_down; | ||
2678 | ops->up = r810x_pll_power_up; | ||
2679 | break; | ||
2680 | |||
2681 | case RTL_GIGA_MAC_VER_11: | ||
2682 | case RTL_GIGA_MAC_VER_12: | ||
2683 | case RTL_GIGA_MAC_VER_17: | ||
2684 | case RTL_GIGA_MAC_VER_18: | ||
2685 | case RTL_GIGA_MAC_VER_19: | ||
2686 | case RTL_GIGA_MAC_VER_20: | ||
2687 | case RTL_GIGA_MAC_VER_21: | ||
2688 | case RTL_GIGA_MAC_VER_22: | ||
2689 | case RTL_GIGA_MAC_VER_23: | ||
2690 | case RTL_GIGA_MAC_VER_24: | ||
2691 | case RTL_GIGA_MAC_VER_25: | ||
2692 | case RTL_GIGA_MAC_VER_26: | ||
2693 | case RTL_GIGA_MAC_VER_27: | ||
2694 | ops->down = r8168_pll_power_down; | ||
2695 | ops->up = r8168_pll_power_up; | ||
2696 | break; | ||
2697 | |||
2698 | default: | ||
2699 | ops->down = NULL; | ||
2700 | ops->up = NULL; | ||
2701 | break; | ||
2702 | } | ||
2703 | } | ||
2704 | |||
2554 | static int __devinit | 2705 | static int __devinit |
2555 | rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | 2706 | rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) |
2556 | { | 2707 | { |
@@ -2670,6 +2821,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2670 | rtl8169_get_mac_version(tp, ioaddr); | 2821 | rtl8169_get_mac_version(tp, ioaddr); |
2671 | 2822 | ||
2672 | rtl_init_mdio_ops(tp); | 2823 | rtl_init_mdio_ops(tp); |
2824 | rtl_init_pll_power_ops(tp); | ||
2673 | 2825 | ||
2674 | /* Use appropriate default if unknown */ | 2826 | /* Use appropriate default if unknown */ |
2675 | if (tp->mac_version == RTL_GIGA_MAC_NONE) { | 2827 | if (tp->mac_version == RTL_GIGA_MAC_NONE) { |
@@ -2849,6 +3001,8 @@ static int rtl8169_open(struct net_device *dev) | |||
2849 | 3001 | ||
2850 | napi_enable(&tp->napi); | 3002 | napi_enable(&tp->napi); |
2851 | 3003 | ||
3004 | rtl_pll_power_up(tp); | ||
3005 | |||
2852 | rtl_hw_start(dev); | 3006 | rtl_hw_start(dev); |
2853 | 3007 | ||
2854 | rtl8169_request_timer(dev); | 3008 | rtl8169_request_timer(dev); |
@@ -4257,6 +4411,8 @@ static void rtl8169_down(struct net_device *dev) | |||
4257 | rtl8169_tx_clear(tp); | 4411 | rtl8169_tx_clear(tp); |
4258 | 4412 | ||
4259 | rtl8169_rx_clear(tp); | 4413 | rtl8169_rx_clear(tp); |
4414 | |||
4415 | rtl_pll_power_down(tp); | ||
4260 | } | 4416 | } |
4261 | 4417 | ||
4262 | static int rtl8169_close(struct net_device *dev) | 4418 | static int rtl8169_close(struct net_device *dev) |
@@ -4361,9 +4517,13 @@ static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) | |||
4361 | 4517 | ||
4362 | static void rtl8169_net_suspend(struct net_device *dev) | 4518 | static void rtl8169_net_suspend(struct net_device *dev) |
4363 | { | 4519 | { |
4520 | struct rtl8169_private *tp = netdev_priv(dev); | ||
4521 | |||
4364 | if (!netif_running(dev)) | 4522 | if (!netif_running(dev)) |
4365 | return; | 4523 | return; |
4366 | 4524 | ||
4525 | rtl_pll_power_down(tp); | ||
4526 | |||
4367 | netif_device_detach(dev); | 4527 | netif_device_detach(dev); |
4368 | netif_stop_queue(dev); | 4528 | netif_stop_queue(dev); |
4369 | } | 4529 | } |
@@ -4382,7 +4542,12 @@ static int rtl8169_suspend(struct device *device) | |||
4382 | 4542 | ||
4383 | static void __rtl8169_resume(struct net_device *dev) | 4543 | static void __rtl8169_resume(struct net_device *dev) |
4384 | { | 4544 | { |
4545 | struct rtl8169_private *tp = netdev_priv(dev); | ||
4546 | |||
4385 | netif_device_attach(dev); | 4547 | netif_device_attach(dev); |
4548 | |||
4549 | rtl_pll_power_up(tp); | ||
4550 | |||
4386 | rtl8169_schedule_work(dev, rtl8169_reset_task); | 4551 | rtl8169_schedule_work(dev, rtl8169_reset_task); |
4387 | } | 4552 | } |
4388 | 4553 | ||