diff options
author | Guo-Fu Tseng <cooldavid@cooldavid.org> | 2011-02-13 13:27:35 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-02-13 23:43:20 -0500 |
commit | 4872b11fdbbf78665230b2bb5864b1611dcb4a25 (patch) | |
tree | daa51591b2f7f2b515a549d98ed92d61f66475fb /drivers | |
parent | 19d96017d1b5b1c9b709bc21a398ea793256644c (diff) |
jme: PHY Power control for new chip
After main chip rev 5, the hardware support more power saving
control registers.
Some Non-Linux drivers might turn off the phy power with new
interfaces, this patch makes it possible for Linux to turn it
on again.
Signed-off-by: Guo-Fu Tseng <cooldavid@cooldavid.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/jme.c | 68 | ||||
-rw-r--r-- | drivers/net/jme.h | 52 |
2 files changed, 106 insertions, 14 deletions
diff --git a/drivers/net/jme.c b/drivers/net/jme.c index d44716e804b6..d446fdb89f68 100644 --- a/drivers/net/jme.c +++ b/drivers/net/jme.c | |||
@@ -1577,6 +1577,38 @@ jme_free_irq(struct jme_adapter *jme) | |||
1577 | } | 1577 | } |
1578 | 1578 | ||
1579 | static inline void | 1579 | static inline void |
1580 | jme_new_phy_on(struct jme_adapter *jme) | ||
1581 | { | ||
1582 | u32 reg; | ||
1583 | |||
1584 | reg = jread32(jme, JME_PHY_PWR); | ||
1585 | reg &= ~(PHY_PWR_DWN1SEL | PHY_PWR_DWN1SW | | ||
1586 | PHY_PWR_DWN2 | PHY_PWR_CLKSEL); | ||
1587 | jwrite32(jme, JME_PHY_PWR, reg); | ||
1588 | |||
1589 | pci_read_config_dword(jme->pdev, PCI_PRIV_PE1, ®); | ||
1590 | reg &= ~PE1_GPREG0_PBG; | ||
1591 | reg |= PE1_GPREG0_ENBG; | ||
1592 | pci_write_config_dword(jme->pdev, PCI_PRIV_PE1, reg); | ||
1593 | } | ||
1594 | |||
1595 | static inline void | ||
1596 | jme_new_phy_off(struct jme_adapter *jme) | ||
1597 | { | ||
1598 | u32 reg; | ||
1599 | |||
1600 | reg = jread32(jme, JME_PHY_PWR); | ||
1601 | reg |= PHY_PWR_DWN1SEL | PHY_PWR_DWN1SW | | ||
1602 | PHY_PWR_DWN2 | PHY_PWR_CLKSEL; | ||
1603 | jwrite32(jme, JME_PHY_PWR, reg); | ||
1604 | |||
1605 | pci_read_config_dword(jme->pdev, PCI_PRIV_PE1, ®); | ||
1606 | reg &= ~PE1_GPREG0_PBG; | ||
1607 | reg |= PE1_GPREG0_PDD3COLD; | ||
1608 | pci_write_config_dword(jme->pdev, PCI_PRIV_PE1, reg); | ||
1609 | } | ||
1610 | |||
1611 | static inline void | ||
1580 | jme_phy_on(struct jme_adapter *jme) | 1612 | jme_phy_on(struct jme_adapter *jme) |
1581 | { | 1613 | { |
1582 | u32 bmcr; | 1614 | u32 bmcr; |
@@ -1584,6 +1616,22 @@ jme_phy_on(struct jme_adapter *jme) | |||
1584 | bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR); | 1616 | bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR); |
1585 | bmcr &= ~BMCR_PDOWN; | 1617 | bmcr &= ~BMCR_PDOWN; |
1586 | jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr); | 1618 | jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr); |
1619 | |||
1620 | if (new_phy_power_ctrl(jme->chip_main_rev)) | ||
1621 | jme_new_phy_on(jme); | ||
1622 | } | ||
1623 | |||
1624 | static inline void | ||
1625 | jme_phy_off(struct jme_adapter *jme) | ||
1626 | { | ||
1627 | u32 bmcr; | ||
1628 | |||
1629 | bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR); | ||
1630 | bmcr |= BMCR_PDOWN; | ||
1631 | jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr); | ||
1632 | |||
1633 | if (new_phy_power_ctrl(jme->chip_main_rev)) | ||
1634 | jme_new_phy_off(jme); | ||
1587 | } | 1635 | } |
1588 | 1636 | ||
1589 | static int | 1637 | static int |
@@ -1606,12 +1654,11 @@ jme_open(struct net_device *netdev) | |||
1606 | 1654 | ||
1607 | jme_start_irq(jme); | 1655 | jme_start_irq(jme); |
1608 | 1656 | ||
1609 | if (test_bit(JME_FLAG_SSET, &jme->flags)) { | 1657 | jme_phy_on(jme); |
1610 | jme_phy_on(jme); | 1658 | if (test_bit(JME_FLAG_SSET, &jme->flags)) |
1611 | jme_set_settings(netdev, &jme->old_ecmd); | 1659 | jme_set_settings(netdev, &jme->old_ecmd); |
1612 | } else { | 1660 | else |
1613 | jme_reset_phy_processor(jme); | 1661 | jme_reset_phy_processor(jme); |
1614 | } | ||
1615 | 1662 | ||
1616 | jme_reset_link(jme); | 1663 | jme_reset_link(jme); |
1617 | 1664 | ||
@@ -1657,12 +1704,6 @@ jme_wait_link(struct jme_adapter *jme) | |||
1657 | } | 1704 | } |
1658 | } | 1705 | } |
1659 | 1706 | ||
1660 | static inline void | ||
1661 | jme_phy_off(struct jme_adapter *jme) | ||
1662 | { | ||
1663 | jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, BMCR_PDOWN); | ||
1664 | } | ||
1665 | |||
1666 | static void | 1707 | static void |
1667 | jme_powersave_phy(struct jme_adapter *jme) | 1708 | jme_powersave_phy(struct jme_adapter *jme) |
1668 | { | 1709 | { |
@@ -3068,12 +3109,11 @@ jme_resume(struct pci_dev *pdev) | |||
3068 | jme_clear_pm(jme); | 3109 | jme_clear_pm(jme); |
3069 | pci_restore_state(pdev); | 3110 | pci_restore_state(pdev); |
3070 | 3111 | ||
3071 | if (test_bit(JME_FLAG_SSET, &jme->flags)) { | 3112 | jme_phy_on(jme); |
3072 | jme_phy_on(jme); | 3113 | if (test_bit(JME_FLAG_SSET, &jme->flags)) |
3073 | jme_set_settings(netdev, &jme->old_ecmd); | 3114 | jme_set_settings(netdev, &jme->old_ecmd); |
3074 | } else { | 3115 | else |
3075 | jme_reset_phy_processor(jme); | 3116 | jme_reset_phy_processor(jme); |
3076 | } | ||
3077 | 3117 | ||
3078 | jme_start_irq(jme); | 3118 | jme_start_irq(jme); |
3079 | netif_device_attach(netdev); | 3119 | netif_device_attach(netdev); |
diff --git a/drivers/net/jme.h b/drivers/net/jme.h index 32b2a9ddbcd6..c3764fc151c9 100644 --- a/drivers/net/jme.h +++ b/drivers/net/jme.h | |||
@@ -103,6 +103,37 @@ enum jme_spi_op_bits { | |||
103 | #define HALF_US 500 /* 500 ns */ | 103 | #define HALF_US 500 /* 500 ns */ |
104 | #define JMESPIIOCTL SIOCDEVPRIVATE | 104 | #define JMESPIIOCTL SIOCDEVPRIVATE |
105 | 105 | ||
106 | #define PCI_PRIV_PE1 0xE4 | ||
107 | |||
108 | enum pci_priv_pe1_bit_masks { | ||
109 | PE1_ASPMSUPRT = 0x00000003, /* | ||
110 | * RW: | ||
111 | * Aspm_support[1:0] | ||
112 | * (R/W Port of 5C[11:10]) | ||
113 | */ | ||
114 | PE1_MULTIFUN = 0x00000004, /* RW: Multi_fun_bit */ | ||
115 | PE1_RDYDMA = 0x00000008, /* RO: ~link.rdy_for_dma */ | ||
116 | PE1_ASPMOPTL = 0x00000030, /* RW: link.rx10s_option[1:0] */ | ||
117 | PE1_ASPMOPTH = 0x000000C0, /* RW: 10_req=[3]?HW:[2] */ | ||
118 | PE1_GPREG0 = 0x0000FF00, /* | ||
119 | * SRW: | ||
120 | * Cfg_gp_reg0 | ||
121 | * [7:6] phy_giga BG control | ||
122 | * [5] CREQ_N as CREQ_N1 (CPPE# as CREQ#) | ||
123 | * [4:0] Reserved | ||
124 | */ | ||
125 | PE1_GPREG0_PBG = 0x0000C000, /* phy_giga BG control */ | ||
126 | PE1_GPREG1 = 0x00FF0000, /* RW: Cfg_gp_reg1 */ | ||
127 | PE1_REVID = 0xFF000000, /* RO: Rev ID */ | ||
128 | }; | ||
129 | |||
130 | enum pci_priv_pe1_values { | ||
131 | PE1_GPREG0_ENBG = 0x00000000, /* en BG */ | ||
132 | PE1_GPREG0_PDD3COLD = 0x00004000, /* giga_PD + d3cold */ | ||
133 | PE1_GPREG0_PDPCIESD = 0x00008000, /* giga_PD + pcie_shutdown */ | ||
134 | PE1_GPREG0_PDPCIEIDDQ = 0x0000C000, /* giga_PD + pcie_iddq */ | ||
135 | }; | ||
136 | |||
106 | /* | 137 | /* |
107 | * Dynamic(adaptive)/Static PCC values | 138 | * Dynamic(adaptive)/Static PCC values |
108 | */ | 139 | */ |
@@ -499,6 +530,7 @@ enum jme_iomap_regs { | |||
499 | JME_PMCS = JME_MAC | 0x60, /* Power Management Control/Stat */ | 530 | JME_PMCS = JME_MAC | 0x60, /* Power Management Control/Stat */ |
500 | 531 | ||
501 | 532 | ||
533 | JME_PHY_PWR = JME_PHY | 0x24, /* New PHY Power Ctrl Register */ | ||
502 | JME_PHY_CS = JME_PHY | 0x28, /* PHY Ctrl and Status Register */ | 534 | JME_PHY_CS = JME_PHY | 0x28, /* PHY Ctrl and Status Register */ |
503 | JME_PHY_LINK = JME_PHY | 0x30, /* PHY Link Status Register */ | 535 | JME_PHY_LINK = JME_PHY | 0x30, /* PHY Link Status Register */ |
504 | JME_SMBCSR = JME_PHY | 0x40, /* SMB Control and Status */ | 536 | JME_SMBCSR = JME_PHY | 0x40, /* SMB Control and Status */ |
@@ -835,6 +867,21 @@ enum jme_pmcs_bit_masks { | |||
835 | }; | 867 | }; |
836 | 868 | ||
837 | /* | 869 | /* |
870 | * New PHY Power Control Register | ||
871 | */ | ||
872 | enum jme_phy_pwr_bit_masks { | ||
873 | PHY_PWR_DWN1SEL = 0x01000000, /* Phy_giga.p_PWR_DOWN1_SEL */ | ||
874 | PHY_PWR_DWN1SW = 0x02000000, /* Phy_giga.p_PWR_DOWN1_SW */ | ||
875 | PHY_PWR_DWN2 = 0x04000000, /* Phy_giga.p_PWR_DOWN2 */ | ||
876 | PHY_PWR_CLKSEL = 0x08000000, /* | ||
877 | * XTL_OUT Clock select | ||
878 | * (an internal free-running clock) | ||
879 | * 0: xtl_out = phy_giga.A_XTL25_O | ||
880 | * 1: xtl_out = phy_giga.PD_OSC | ||
881 | */ | ||
882 | }; | ||
883 | |||
884 | /* | ||
838 | * Giga PHY Status Registers | 885 | * Giga PHY Status Registers |
839 | */ | 886 | */ |
840 | enum jme_phy_link_bit_mask { | 887 | enum jme_phy_link_bit_mask { |
@@ -1191,6 +1238,11 @@ static inline int is_buggy250(unsigned short device, u8 chiprev) | |||
1191 | return device == PCI_DEVICE_ID_JMICRON_JMC250 && chiprev == 0x11; | 1238 | return device == PCI_DEVICE_ID_JMICRON_JMC250 && chiprev == 0x11; |
1192 | } | 1239 | } |
1193 | 1240 | ||
1241 | static inline int new_phy_power_ctrl(u8 chip_main_rev) | ||
1242 | { | ||
1243 | return chip_main_rev >= 5; | ||
1244 | } | ||
1245 | |||
1194 | /* | 1246 | /* |
1195 | * Function prototypes | 1247 | * Function prototypes |
1196 | */ | 1248 | */ |