diff options
author | Ayaz Abdulla <aabdulla@nvidia.com> | 2009-04-30 21:41:50 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-05-01 18:30:45 -0400 |
commit | 88d7d8b00cdc3117150faab4c4ace6d464b71c22 (patch) | |
tree | 86e114a66f9fb2e76a892876101f8a5e4959ac20 /drivers/net/forcedeth.c | |
parent | 1aec5bdfed91b50aedbcad43393bcb05033c7ef3 (diff) |
forcedeth: add clock gating feature <resend>
This patch adds new logic to support a clock gating feature found on the
latest set of chipsets. The clock gating is performed on the tx/rx
engines when the link is disconnected. Clock gating helps in reducing
power consumption.
* modified based on comments from netdev
Signed-off-by: Ayaz Abdulla <aabdulla@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/forcedeth.c')
-rw-r--r-- | drivers/net/forcedeth.c | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index f9a846b1b92f..d0b1d9f17a5d 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c | |||
@@ -343,6 +343,7 @@ enum { | |||
343 | #define NVREG_POWERSTATE2_POWERUP_MASK 0x0F15 | 343 | #define NVREG_POWERSTATE2_POWERUP_MASK 0x0F15 |
344 | #define NVREG_POWERSTATE2_POWERUP_REV_A3 0x0001 | 344 | #define NVREG_POWERSTATE2_POWERUP_REV_A3 0x0001 |
345 | #define NVREG_POWERSTATE2_PHY_RESET 0x0004 | 345 | #define NVREG_POWERSTATE2_PHY_RESET 0x0004 |
346 | #define NVREG_POWERSTATE2_GATE_CLOCKS 0x0F00 | ||
346 | }; | 347 | }; |
347 | 348 | ||
348 | /* Big endian: should work, but is untested */ | 349 | /* Big endian: should work, but is untested */ |
@@ -1017,6 +1018,23 @@ static int using_multi_irqs(struct net_device *dev) | |||
1017 | return 1; | 1018 | return 1; |
1018 | } | 1019 | } |
1019 | 1020 | ||
1021 | static void nv_txrx_gate(struct net_device *dev, bool gate) | ||
1022 | { | ||
1023 | struct fe_priv *np = get_nvpriv(dev); | ||
1024 | u8 __iomem *base = get_hwbase(dev); | ||
1025 | u32 powerstate; | ||
1026 | |||
1027 | if (!np->mac_in_use && | ||
1028 | (np->driver_data & DEV_HAS_POWER_CNTRL)) { | ||
1029 | powerstate = readl(base + NvRegPowerState2); | ||
1030 | if (gate) | ||
1031 | powerstate |= NVREG_POWERSTATE2_GATE_CLOCKS; | ||
1032 | else | ||
1033 | powerstate &= ~NVREG_POWERSTATE2_GATE_CLOCKS; | ||
1034 | writel(powerstate, base + NvRegPowerState2); | ||
1035 | } | ||
1036 | } | ||
1037 | |||
1020 | static void nv_enable_irq(struct net_device *dev) | 1038 | static void nv_enable_irq(struct net_device *dev) |
1021 | { | 1039 | { |
1022 | struct fe_priv *np = get_nvpriv(dev); | 1040 | struct fe_priv *np = get_nvpriv(dev); |
@@ -3394,12 +3412,14 @@ static void nv_linkchange(struct net_device *dev) | |||
3394 | if (!netif_carrier_ok(dev)) { | 3412 | if (!netif_carrier_ok(dev)) { |
3395 | netif_carrier_on(dev); | 3413 | netif_carrier_on(dev); |
3396 | printk(KERN_INFO "%s: link up.\n", dev->name); | 3414 | printk(KERN_INFO "%s: link up.\n", dev->name); |
3415 | nv_txrx_gate(dev, false); | ||
3397 | nv_start_rx(dev); | 3416 | nv_start_rx(dev); |
3398 | } | 3417 | } |
3399 | } else { | 3418 | } else { |
3400 | if (netif_carrier_ok(dev)) { | 3419 | if (netif_carrier_ok(dev)) { |
3401 | netif_carrier_off(dev); | 3420 | netif_carrier_off(dev); |
3402 | printk(KERN_INFO "%s: link down.\n", dev->name); | 3421 | printk(KERN_INFO "%s: link down.\n", dev->name); |
3422 | nv_txrx_gate(dev, true); | ||
3403 | nv_stop_rx(dev); | 3423 | nv_stop_rx(dev); |
3404 | } | 3424 | } |
3405 | } | 3425 | } |
@@ -5327,6 +5347,7 @@ static int nv_open(struct net_device *dev) | |||
5327 | mii_rw(dev, np->phyaddr, MII_BMCR, | 5347 | mii_rw(dev, np->phyaddr, MII_BMCR, |
5328 | mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ) & ~BMCR_PDOWN); | 5348 | mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ) & ~BMCR_PDOWN); |
5329 | 5349 | ||
5350 | nv_txrx_gate(dev, false); | ||
5330 | /* erase previous misconfiguration */ | 5351 | /* erase previous misconfiguration */ |
5331 | if (np->driver_data & DEV_HAS_POWER_CNTRL) | 5352 | if (np->driver_data & DEV_HAS_POWER_CNTRL) |
5332 | nv_mac_reset(dev); | 5353 | nv_mac_reset(dev); |
@@ -5514,12 +5535,14 @@ static int nv_close(struct net_device *dev) | |||
5514 | nv_drain_rxtx(dev); | 5535 | nv_drain_rxtx(dev); |
5515 | 5536 | ||
5516 | if (np->wolenabled) { | 5537 | if (np->wolenabled) { |
5538 | nv_txrx_gate(dev, false); | ||
5517 | writel(NVREG_PFF_ALWAYS|NVREG_PFF_MYADDR, base + NvRegPacketFilterFlags); | 5539 | writel(NVREG_PFF_ALWAYS|NVREG_PFF_MYADDR, base + NvRegPacketFilterFlags); |
5518 | nv_start_rx(dev); | 5540 | nv_start_rx(dev); |
5519 | } else { | 5541 | } else { |
5520 | /* power down phy */ | 5542 | /* power down phy */ |
5521 | mii_rw(dev, np->phyaddr, MII_BMCR, | 5543 | mii_rw(dev, np->phyaddr, MII_BMCR, |
5522 | mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ)|BMCR_PDOWN); | 5544 | mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ)|BMCR_PDOWN); |
5545 | nv_txrx_gate(dev, true); | ||
5523 | } | 5546 | } |
5524 | 5547 | ||
5525 | /* FIXME: power down nic */ | 5548 | /* FIXME: power down nic */ |