aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHuang, Xiong <xiong@qca.qualcomm.com>2012-04-25 16:40:59 -0400
committerDavid S. Miller <davem@davemloft.net>2012-04-26 05:03:32 -0400
commit319d013af0d47e1137ac02f94ad069312514ddfa (patch)
tree4a6942fb0d2d2e85427ea924ac012e74770faea6 /drivers
parent52a12fc785ef542bc06119d2f1c8e0f7d75e4c76 (diff)
atl1c: add function atl1c_power_saving
This function is used for suspend of S1/S3/S4 and driver remove. It sets MAC/PHY based on the WoL configuation to get lower power consumption. atl1c_phy_power_saving is renamed to atl1c_phy_to_ps_link, this function is just make PHY enter a link/speed mode to eat less power. REG_MAC_CTRL register is refined as well. Signed-off-by: xiong <xiong@qca.qualcomm.com> Tested-by: Liu David <dwliu@qca.qualcomm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_hw.c73
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_hw.h72
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_main.c89
3 files changed, 108 insertions, 126 deletions
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
index 9a5b0f398f78..07f017f59b39 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
@@ -525,14 +525,7 @@ static int atl1c_phy_setup_adv(struct atl1c_hw *hw)
525 525
526void atl1c_phy_disable(struct atl1c_hw *hw) 526void atl1c_phy_disable(struct atl1c_hw *hw)
527{ 527{
528 u32 phy_ctrl_data; 528 atl1c_power_saving(hw, 0);
529
530 AT_READ_REG(hw, REG_GPHY_CTRL, &phy_ctrl_data);
531 phy_ctrl_data &= ~(GPHY_CTRL_EXT_RESET | GPHY_CTRL_CLS);
532 phy_ctrl_data |= GPHY_CTRL_SEL_ANA_RST | GPHY_CTRL_HIB_PULSE |
533 GPHY_CTRL_HIB_EN | GPHY_CTRL_PHY_IDDQ |
534 GPHY_CTRL_PWDOWN_HW;
535 AT_WRITE_REGW(hw, REG_GPHY_CTRL, phy_ctrl_data);
536} 529}
537 530
538 531
@@ -722,7 +715,8 @@ int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex)
722 return 0; 715 return 0;
723} 716}
724 717
725int atl1c_phy_power_saving(struct atl1c_hw *hw) 718/* select one link mode to get lower power consumption */
719int atl1c_phy_to_ps_link(struct atl1c_hw *hw)
726{ 720{
727 struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter; 721 struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter;
728 struct pci_dev *pdev = adapter->pdev; 722 struct pci_dev *pdev = adapter->pdev;
@@ -793,3 +787,64 @@ int atl1c_restart_autoneg(struct atl1c_hw *hw)
793 787
794 return atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data); 788 return atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data);
795} 789}
790
791int atl1c_power_saving(struct atl1c_hw *hw, u32 wufc)
792{
793 struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter;
794 struct pci_dev *pdev = adapter->pdev;
795 u32 master_ctrl, mac_ctrl, phy_ctrl;
796 u32 wol_ctrl, speed;
797 u16 phy_data;
798
799 wol_ctrl = 0;
800 speed = adapter->link_speed == SPEED_1000 ?
801 MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100;
802
803 AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl);
804 AT_READ_REG(hw, REG_MAC_CTRL, &mac_ctrl);
805 AT_READ_REG(hw, REG_GPHY_CTRL, &phy_ctrl);
806
807 master_ctrl &= ~MASTER_CTRL_CLK_SEL_DIS;
808 mac_ctrl = FIELD_SETX(mac_ctrl, MAC_CTRL_SPEED, speed);
809 mac_ctrl &= ~(MAC_CTRL_DUPLX | MAC_CTRL_RX_EN | MAC_CTRL_TX_EN);
810 if (adapter->link_duplex == FULL_DUPLEX)
811 mac_ctrl |= MAC_CTRL_DUPLX;
812 phy_ctrl &= ~(GPHY_CTRL_EXT_RESET | GPHY_CTRL_CLS);
813 phy_ctrl |= GPHY_CTRL_SEL_ANA_RST | GPHY_CTRL_HIB_PULSE |
814 GPHY_CTRL_HIB_EN;
815 if (!wufc) { /* without WoL */
816 master_ctrl |= MASTER_CTRL_CLK_SEL_DIS;
817 phy_ctrl |= GPHY_CTRL_PHY_IDDQ | GPHY_CTRL_PWDOWN_HW;
818 AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl);
819 AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl);
820 AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl);
821 AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
822 hw->phy_configured = false; /* re-init PHY when resume */
823 return 0;
824 }
825 phy_ctrl |= GPHY_CTRL_EXT_RESET;
826 if (wufc & AT_WUFC_MAG) {
827 mac_ctrl |= MAC_CTRL_RX_EN | MAC_CTRL_BC_EN;
828 wol_ctrl |= WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
829 if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V11)
830 wol_ctrl |= WOL_PATTERN_EN | WOL_PATTERN_PME_EN;
831 }
832 if (wufc & AT_WUFC_LNKC) {
833 wol_ctrl |= WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN;
834 if (atl1c_write_phy_reg(hw, MII_IER, IER_LINK_UP) != 0) {
835 dev_dbg(&pdev->dev, "%s: write phy MII_IER faild.\n",
836 atl1c_driver_name);
837 }
838 }
839 /* clear PHY interrupt */
840 atl1c_read_phy_reg(hw, MII_ISR, &phy_data);
841
842 dev_dbg(&pdev->dev, "%s: suspend MAC=%x,MASTER=%x,PHY=0x%x,WOL=%x\n",
843 atl1c_driver_name, mac_ctrl, master_ctrl, phy_ctrl, wol_ctrl);
844 AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl);
845 AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl);
846 AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl);
847 AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl);
848
849 return 0;
850}
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
index fba7eb5db2ed..0adb34131332 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h
@@ -48,7 +48,8 @@ bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value);
48int atl1c_phy_init(struct atl1c_hw *hw); 48int atl1c_phy_init(struct atl1c_hw *hw);
49int atl1c_check_eeprom_exist(struct atl1c_hw *hw); 49int atl1c_check_eeprom_exist(struct atl1c_hw *hw);
50int atl1c_restart_autoneg(struct atl1c_hw *hw); 50int atl1c_restart_autoneg(struct atl1c_hw *hw);
51int atl1c_phy_power_saving(struct atl1c_hw *hw); 51int atl1c_phy_to_ps_link(struct atl1c_hw *hw);
52int atl1c_power_saving(struct atl1c_hw *hw, u32 wufc);
52bool atl1c_wait_mdio_idle(struct atl1c_hw *hw); 53bool atl1c_wait_mdio_idle(struct atl1c_hw *hw);
53void atl1c_stop_phy_polling(struct atl1c_hw *hw); 54void atl1c_stop_phy_polling(struct atl1c_hw *hw);
54void atl1c_start_phy_polling(struct atl1c_hw *hw, u16 clk_sel); 55void atl1c_start_phy_polling(struct atl1c_hw *hw, u16 clk_sel);
@@ -63,6 +64,16 @@ int atl1c_write_phy_ext(struct atl1c_hw *hw, u8 dev_addr,
63int atl1c_read_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data); 64int atl1c_read_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data);
64int atl1c_write_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 phy_data); 65int atl1c_write_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 phy_data);
65 66
67/* hw-ids */
68#define PCI_DEVICE_ID_ATTANSIC_L2C 0x1062
69#define PCI_DEVICE_ID_ATTANSIC_L1C 0x1063
70#define PCI_DEVICE_ID_ATHEROS_L2C_B 0x2060 /* AR8152 v1.1 Fast 10/100 */
71#define PCI_DEVICE_ID_ATHEROS_L2C_B2 0x2062 /* AR8152 v2.0 Fast 10/100 */
72#define PCI_DEVICE_ID_ATHEROS_L1D 0x1073 /* AR8151 v1.0 Gigabit 1000 */
73#define PCI_DEVICE_ID_ATHEROS_L1D_2_0 0x1083 /* AR8151 v2.0 Gigabit 1000 */
74#define L2CB_V10 0xc0
75#define L2CB_V11 0xc1
76
66/* register definition */ 77/* register definition */
67#define REG_DEVICE_CAP 0x5C 78#define REG_DEVICE_CAP 0x5C
68#define DEVICE_CAP_MAX_PAYLOAD_MASK 0x7 79#define DEVICE_CAP_MAX_PAYLOAD_MASK 0x7
@@ -366,35 +377,36 @@ int atl1c_write_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 phy_data);
366 377
367/* MAC Control Register */ 378/* MAC Control Register */
368#define REG_MAC_CTRL 0x1480 379#define REG_MAC_CTRL 0x1480
369#define MAC_CTRL_TX_EN 0x1 380#define MAC_CTRL_SPEED_MODE_SW BIT(30) /* 0:phy,1:sw */
370#define MAC_CTRL_RX_EN 0x2 381#define MAC_CTRL_HASH_ALG_CRC32 BIT(29) /* 1:legacy,0:lw_5b */
371#define MAC_CTRL_TX_FLOW 0x4 382#define MAC_CTRL_SINGLE_PAUSE_EN BIT(28)
372#define MAC_CTRL_RX_FLOW 0x8 383#define MAC_CTRL_DBG BIT(27)
373#define MAC_CTRL_LOOPBACK 0x10 384#define MAC_CTRL_BC_EN BIT(26)
374#define MAC_CTRL_DUPLX 0x20 385#define MAC_CTRL_MC_ALL_EN BIT(25)
375#define MAC_CTRL_ADD_CRC 0x40 386#define MAC_CTRL_RX_CHKSUM_EN BIT(24)
376#define MAC_CTRL_PAD 0x80 387#define MAC_CTRL_TX_HUGE BIT(23)
377#define MAC_CTRL_LENCHK 0x100 388#define MAC_CTRL_DBG_TX_BKPRESURE BIT(22)
378#define MAC_CTRL_HUGE_EN 0x200 389#define MAC_CTRL_SPEED_MASK 3UL
379#define MAC_CTRL_PRMLEN_SHIFT 10 390#define MAC_CTRL_SPEED_SHIFT 20
380#define MAC_CTRL_PRMLEN_MASK 0xf 391#define MAC_CTRL_SPEED_10_100 1
381#define MAC_CTRL_RMV_VLAN 0x4000 392#define MAC_CTRL_SPEED_1000 2
382#define MAC_CTRL_PROMIS_EN 0x8000 393#define MAC_CTRL_TX_SIMURST BIT(19)
383#define MAC_CTRL_TX_PAUSE 0x10000 394#define MAC_CTRL_SCNT BIT(17)
384#define MAC_CTRL_SCNT 0x20000 395#define MAC_CTRL_TX_PAUSE BIT(16)
385#define MAC_CTRL_SRST_TX 0x40000 396#define MAC_CTRL_PROMIS_EN BIT(15)
386#define MAC_CTRL_TX_SIMURST 0x80000 397#define MAC_CTRL_RMV_VLAN BIT(14)
387#define MAC_CTRL_SPEED_SHIFT 20 398#define MAC_CTRL_PRMLEN_MASK 0xFUL
388#define MAC_CTRL_SPEED_MASK 0x3 399#define MAC_CTRL_PRMLEN_SHIFT 10
389#define MAC_CTRL_DBG_TX_BKPRESURE 0x400000 400#define MAC_CTRL_HUGE_EN BIT(9)
390#define MAC_CTRL_TX_HUGE 0x800000 401#define MAC_CTRL_LENCHK BIT(8)
391#define MAC_CTRL_RX_CHKSUM_EN 0x1000000 402#define MAC_CTRL_PAD BIT(7)
392#define MAC_CTRL_MC_ALL_EN 0x2000000 403#define MAC_CTRL_ADD_CRC BIT(6)
393#define MAC_CTRL_BC_EN 0x4000000 404#define MAC_CTRL_DUPLX BIT(5)
394#define MAC_CTRL_DBG 0x8000000 405#define MAC_CTRL_LOOPBACK BIT(4)
395#define MAC_CTRL_SINGLE_PAUSE_EN 0x10000000 406#define MAC_CTRL_RX_FLOW BIT(3)
396#define MAC_CTRL_HASH_ALG_CRC32 0x20000000 407#define MAC_CTRL_TX_FLOW BIT(2)
397#define MAC_CTRL_SPEED_MODE_SW 0x40000000 408#define MAC_CTRL_RX_EN BIT(1)
409#define MAC_CTRL_TX_EN BIT(0)
398 410
399/* MAC IPG/IFG Control Register */ 411/* MAC IPG/IFG Control Register */
400#define REG_MAC_IPG_IFG 0x1484 412#define REG_MAC_IPG_IFG 0x1484
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index cb3b3c4b5e18..d03112c3e4e9 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -24,14 +24,6 @@
24#define ATL1C_DRV_VERSION "1.0.1.0-NAPI" 24#define ATL1C_DRV_VERSION "1.0.1.0-NAPI"
25char atl1c_driver_name[] = "atl1c"; 25char atl1c_driver_name[] = "atl1c";
26char atl1c_driver_version[] = ATL1C_DRV_VERSION; 26char atl1c_driver_version[] = ATL1C_DRV_VERSION;
27#define PCI_DEVICE_ID_ATTANSIC_L2C 0x1062
28#define PCI_DEVICE_ID_ATTANSIC_L1C 0x1063
29#define PCI_DEVICE_ID_ATHEROS_L2C_B 0x2060 /* AR8152 v1.1 Fast 10/100 */
30#define PCI_DEVICE_ID_ATHEROS_L2C_B2 0x2062 /* AR8152 v2.0 Fast 10/100 */
31#define PCI_DEVICE_ID_ATHEROS_L1D 0x1073 /* AR8151 v1.0 Gigabit 1000 */
32#define PCI_DEVICE_ID_ATHEROS_L1D_2_0 0x1083 /* AR8151 v2.0 Gigabit 1000 */
33#define L2CB_V10 0xc0
34#define L2CB_V11 0xc1
35 27
36/* 28/*
37 * atl1c_pci_tbl - PCI Device ID Table 29 * atl1c_pci_tbl - PCI Device ID Table
@@ -2307,12 +2299,7 @@ static int atl1c_suspend(struct device *dev)
2307 struct net_device *netdev = pci_get_drvdata(pdev); 2299 struct net_device *netdev = pci_get_drvdata(pdev);
2308 struct atl1c_adapter *adapter = netdev_priv(netdev); 2300 struct atl1c_adapter *adapter = netdev_priv(netdev);
2309 struct atl1c_hw *hw = &adapter->hw; 2301 struct atl1c_hw *hw = &adapter->hw;
2310 u32 mac_ctrl_data = 0;
2311 u32 master_ctrl_data = 0;
2312 u32 wol_ctrl_data = 0;
2313 u16 mii_intr_status_data = 0;
2314 u32 wufc = adapter->wol; 2302 u32 wufc = adapter->wol;
2315 u32 phy_ctrl_data;
2316 2303
2317 atl1c_disable_l0s_l1(hw); 2304 atl1c_disable_l0s_l1(hw);
2318 if (netif_running(netdev)) { 2305 if (netif_running(netdev)) {
@@ -2322,82 +2309,10 @@ static int atl1c_suspend(struct device *dev)
2322 netif_device_detach(netdev); 2309 netif_device_detach(netdev);
2323 2310
2324 if (wufc) 2311 if (wufc)
2325 if (atl1c_phy_power_saving(hw) != 0) 2312 if (atl1c_phy_to_ps_link(hw) != 0)
2326 dev_dbg(&pdev->dev, "phy power saving failed"); 2313 dev_dbg(&pdev->dev, "phy power saving failed");
2327 2314
2328 AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data); 2315 atl1c_power_saving(hw, wufc);
2329 AT_READ_REG(hw, REG_MAC_CTRL, &mac_ctrl_data);
2330 AT_READ_REG(hw, REG_GPHY_CTRL, &phy_ctrl_data);
2331
2332 master_ctrl_data &= ~MASTER_CTRL_CLK_SEL_DIS;
2333 mac_ctrl_data &= ~(MAC_CTRL_PRMLEN_MASK << MAC_CTRL_PRMLEN_SHIFT);
2334 mac_ctrl_data |= (((u32)adapter->hw.preamble_len &
2335 MAC_CTRL_PRMLEN_MASK) <<
2336 MAC_CTRL_PRMLEN_SHIFT);
2337 mac_ctrl_data &= ~(MAC_CTRL_SPEED_MASK << MAC_CTRL_SPEED_SHIFT);
2338 mac_ctrl_data &= ~MAC_CTRL_DUPLX;
2339 phy_ctrl_data &= ~(GPHY_CTRL_EXT_RESET | GPHY_CTRL_CLS);
2340 phy_ctrl_data |= GPHY_CTRL_SEL_ANA_RST | GPHY_CTRL_HIB_PULSE |
2341 GPHY_CTRL_HIB_EN;
2342
2343 if (wufc) {
2344 mac_ctrl_data |= MAC_CTRL_RX_EN;
2345 phy_ctrl_data |= GPHY_CTRL_EXT_RESET;
2346 if (adapter->link_speed == SPEED_1000 ||
2347 adapter->link_speed == SPEED_0) {
2348 mac_ctrl_data |= atl1c_mac_speed_1000 <<
2349 MAC_CTRL_SPEED_SHIFT;
2350 mac_ctrl_data |= MAC_CTRL_DUPLX;
2351 } else
2352 mac_ctrl_data |= atl1c_mac_speed_10_100 <<
2353 MAC_CTRL_SPEED_SHIFT;
2354
2355 if (adapter->link_duplex == DUPLEX_FULL)
2356 mac_ctrl_data |= MAC_CTRL_DUPLX;
2357
2358 /* turn on magic packet wol */
2359 if (wufc & AT_WUFC_MAG) {
2360 wol_ctrl_data |= WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
2361 if (hw->nic_type == athr_l2c_b &&
2362 hw->revision_id == L2CB_V11) {
2363 wol_ctrl_data |=
2364 WOL_PATTERN_EN | WOL_PATTERN_PME_EN;
2365 }
2366 }
2367 if (wufc & AT_WUFC_LNKC) {
2368 wol_ctrl_data |= WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN;
2369 /* only link up can wake up */
2370 if (atl1c_write_phy_reg(hw, MII_IER, IER_LINK_UP) != 0) {
2371 dev_dbg(&pdev->dev, "%s: read write phy "
2372 "register failed.\n",
2373 atl1c_driver_name);
2374 }
2375 }
2376 /* clear phy interrupt */
2377 atl1c_read_phy_reg(hw, MII_ISR, &mii_intr_status_data);
2378 /* Config MAC Ctrl register */
2379 __atl1c_vlan_mode(netdev->features, &mac_ctrl_data);
2380
2381 /* magic packet maybe Broadcast&multicast&Unicast frame */
2382 if (wufc & AT_WUFC_MAG)
2383 mac_ctrl_data |= MAC_CTRL_BC_EN;
2384
2385 dev_dbg(&pdev->dev,
2386 "%s: suspend MAC=0x%x\n",
2387 atl1c_driver_name, mac_ctrl_data);
2388 } else {
2389 master_ctrl_data |= MASTER_CTRL_CLK_SEL_DIS;
2390 mac_ctrl_data |= atl1c_mac_speed_10_100 << MAC_CTRL_SPEED_SHIFT;
2391 mac_ctrl_data |= MAC_CTRL_DUPLX;
2392 phy_ctrl_data |= GPHY_CTRL_PHY_IDDQ | GPHY_CTRL_PWDOWN_HW;
2393 wol_ctrl_data = 0;
2394 hw->phy_configured = false; /* re-init PHY when resume */
2395 }
2396
2397 AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data);
2398 AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
2399 AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data);
2400 AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl_data);
2401 2316
2402 return 0; 2317 return 0;
2403} 2318}