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>
This commit is contained in:
parent
19d96017d1
commit
4872b11fdb
2 changed files with 106 additions and 14 deletions
|
@ -1576,6 +1576,38 @@ jme_free_irq(struct jme_adapter *jme)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
jme_new_phy_on(struct jme_adapter *jme)
|
||||||
|
{
|
||||||
|
u32 reg;
|
||||||
|
|
||||||
|
reg = jread32(jme, JME_PHY_PWR);
|
||||||
|
reg &= ~(PHY_PWR_DWN1SEL | PHY_PWR_DWN1SW |
|
||||||
|
PHY_PWR_DWN2 | PHY_PWR_CLKSEL);
|
||||||
|
jwrite32(jme, JME_PHY_PWR, reg);
|
||||||
|
|
||||||
|
pci_read_config_dword(jme->pdev, PCI_PRIV_PE1, ®);
|
||||||
|
reg &= ~PE1_GPREG0_PBG;
|
||||||
|
reg |= PE1_GPREG0_ENBG;
|
||||||
|
pci_write_config_dword(jme->pdev, PCI_PRIV_PE1, reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
jme_new_phy_off(struct jme_adapter *jme)
|
||||||
|
{
|
||||||
|
u32 reg;
|
||||||
|
|
||||||
|
reg = jread32(jme, JME_PHY_PWR);
|
||||||
|
reg |= PHY_PWR_DWN1SEL | PHY_PWR_DWN1SW |
|
||||||
|
PHY_PWR_DWN2 | PHY_PWR_CLKSEL;
|
||||||
|
jwrite32(jme, JME_PHY_PWR, reg);
|
||||||
|
|
||||||
|
pci_read_config_dword(jme->pdev, PCI_PRIV_PE1, ®);
|
||||||
|
reg &= ~PE1_GPREG0_PBG;
|
||||||
|
reg |= PE1_GPREG0_PDD3COLD;
|
||||||
|
pci_write_config_dword(jme->pdev, PCI_PRIV_PE1, reg);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
jme_phy_on(struct jme_adapter *jme)
|
jme_phy_on(struct jme_adapter *jme)
|
||||||
{
|
{
|
||||||
|
@ -1584,6 +1616,22 @@ jme_phy_on(struct jme_adapter *jme)
|
||||||
bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR);
|
bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR);
|
||||||
bmcr &= ~BMCR_PDOWN;
|
bmcr &= ~BMCR_PDOWN;
|
||||||
jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr);
|
jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr);
|
||||||
|
|
||||||
|
if (new_phy_power_ctrl(jme->chip_main_rev))
|
||||||
|
jme_new_phy_on(jme);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
jme_phy_off(struct jme_adapter *jme)
|
||||||
|
{
|
||||||
|
u32 bmcr;
|
||||||
|
|
||||||
|
bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR);
|
||||||
|
bmcr |= BMCR_PDOWN;
|
||||||
|
jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr);
|
||||||
|
|
||||||
|
if (new_phy_power_ctrl(jme->chip_main_rev))
|
||||||
|
jme_new_phy_off(jme);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -1606,12 +1654,11 @@ jme_open(struct net_device *netdev)
|
||||||
|
|
||||||
jme_start_irq(jme);
|
jme_start_irq(jme);
|
||||||
|
|
||||||
if (test_bit(JME_FLAG_SSET, &jme->flags)) {
|
jme_phy_on(jme);
|
||||||
jme_phy_on(jme);
|
if (test_bit(JME_FLAG_SSET, &jme->flags))
|
||||||
jme_set_settings(netdev, &jme->old_ecmd);
|
jme_set_settings(netdev, &jme->old_ecmd);
|
||||||
} else {
|
else
|
||||||
jme_reset_phy_processor(jme);
|
jme_reset_phy_processor(jme);
|
||||||
}
|
|
||||||
|
|
||||||
jme_reset_link(jme);
|
jme_reset_link(jme);
|
||||||
|
|
||||||
|
@ -1657,12 +1704,6 @@ jme_wait_link(struct jme_adapter *jme)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
|
||||||
jme_phy_off(struct jme_adapter *jme)
|
|
||||||
{
|
|
||||||
jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, BMCR_PDOWN);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
jme_powersave_phy(struct jme_adapter *jme)
|
jme_powersave_phy(struct jme_adapter *jme)
|
||||||
{
|
{
|
||||||
|
@ -3068,12 +3109,11 @@ jme_resume(struct pci_dev *pdev)
|
||||||
jme_clear_pm(jme);
|
jme_clear_pm(jme);
|
||||||
pci_restore_state(pdev);
|
pci_restore_state(pdev);
|
||||||
|
|
||||||
if (test_bit(JME_FLAG_SSET, &jme->flags)) {
|
jme_phy_on(jme);
|
||||||
jme_phy_on(jme);
|
if (test_bit(JME_FLAG_SSET, &jme->flags))
|
||||||
jme_set_settings(netdev, &jme->old_ecmd);
|
jme_set_settings(netdev, &jme->old_ecmd);
|
||||||
} else {
|
else
|
||||||
jme_reset_phy_processor(jme);
|
jme_reset_phy_processor(jme);
|
||||||
}
|
|
||||||
|
|
||||||
jme_start_irq(jme);
|
jme_start_irq(jme);
|
||||||
netif_device_attach(netdev);
|
netif_device_attach(netdev);
|
||||||
|
|
|
@ -103,6 +103,37 @@ enum jme_spi_op_bits {
|
||||||
#define HALF_US 500 /* 500 ns */
|
#define HALF_US 500 /* 500 ns */
|
||||||
#define JMESPIIOCTL SIOCDEVPRIVATE
|
#define JMESPIIOCTL SIOCDEVPRIVATE
|
||||||
|
|
||||||
|
#define PCI_PRIV_PE1 0xE4
|
||||||
|
|
||||||
|
enum pci_priv_pe1_bit_masks {
|
||||||
|
PE1_ASPMSUPRT = 0x00000003, /*
|
||||||
|
* RW:
|
||||||
|
* Aspm_support[1:0]
|
||||||
|
* (R/W Port of 5C[11:10])
|
||||||
|
*/
|
||||||
|
PE1_MULTIFUN = 0x00000004, /* RW: Multi_fun_bit */
|
||||||
|
PE1_RDYDMA = 0x00000008, /* RO: ~link.rdy_for_dma */
|
||||||
|
PE1_ASPMOPTL = 0x00000030, /* RW: link.rx10s_option[1:0] */
|
||||||
|
PE1_ASPMOPTH = 0x000000C0, /* RW: 10_req=[3]?HW:[2] */
|
||||||
|
PE1_GPREG0 = 0x0000FF00, /*
|
||||||
|
* SRW:
|
||||||
|
* Cfg_gp_reg0
|
||||||
|
* [7:6] phy_giga BG control
|
||||||
|
* [5] CREQ_N as CREQ_N1 (CPPE# as CREQ#)
|
||||||
|
* [4:0] Reserved
|
||||||
|
*/
|
||||||
|
PE1_GPREG0_PBG = 0x0000C000, /* phy_giga BG control */
|
||||||
|
PE1_GPREG1 = 0x00FF0000, /* RW: Cfg_gp_reg1 */
|
||||||
|
PE1_REVID = 0xFF000000, /* RO: Rev ID */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum pci_priv_pe1_values {
|
||||||
|
PE1_GPREG0_ENBG = 0x00000000, /* en BG */
|
||||||
|
PE1_GPREG0_PDD3COLD = 0x00004000, /* giga_PD + d3cold */
|
||||||
|
PE1_GPREG0_PDPCIESD = 0x00008000, /* giga_PD + pcie_shutdown */
|
||||||
|
PE1_GPREG0_PDPCIEIDDQ = 0x0000C000, /* giga_PD + pcie_iddq */
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Dynamic(adaptive)/Static PCC values
|
* Dynamic(adaptive)/Static PCC values
|
||||||
*/
|
*/
|
||||||
|
@ -499,6 +530,7 @@ enum jme_iomap_regs {
|
||||||
JME_PMCS = JME_MAC | 0x60, /* Power Management Control/Stat */
|
JME_PMCS = JME_MAC | 0x60, /* Power Management Control/Stat */
|
||||||
|
|
||||||
|
|
||||||
|
JME_PHY_PWR = JME_PHY | 0x24, /* New PHY Power Ctrl Register */
|
||||||
JME_PHY_CS = JME_PHY | 0x28, /* PHY Ctrl and Status Register */
|
JME_PHY_CS = JME_PHY | 0x28, /* PHY Ctrl and Status Register */
|
||||||
JME_PHY_LINK = JME_PHY | 0x30, /* PHY Link Status Register */
|
JME_PHY_LINK = JME_PHY | 0x30, /* PHY Link Status Register */
|
||||||
JME_SMBCSR = JME_PHY | 0x40, /* SMB Control and Status */
|
JME_SMBCSR = JME_PHY | 0x40, /* SMB Control and Status */
|
||||||
|
@ -834,6 +866,21 @@ enum jme_pmcs_bit_masks {
|
||||||
PMCS_MFEN = 0x00000001,
|
PMCS_MFEN = 0x00000001,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* New PHY Power Control Register
|
||||||
|
*/
|
||||||
|
enum jme_phy_pwr_bit_masks {
|
||||||
|
PHY_PWR_DWN1SEL = 0x01000000, /* Phy_giga.p_PWR_DOWN1_SEL */
|
||||||
|
PHY_PWR_DWN1SW = 0x02000000, /* Phy_giga.p_PWR_DOWN1_SW */
|
||||||
|
PHY_PWR_DWN2 = 0x04000000, /* Phy_giga.p_PWR_DOWN2 */
|
||||||
|
PHY_PWR_CLKSEL = 0x08000000, /*
|
||||||
|
* XTL_OUT Clock select
|
||||||
|
* (an internal free-running clock)
|
||||||
|
* 0: xtl_out = phy_giga.A_XTL25_O
|
||||||
|
* 1: xtl_out = phy_giga.PD_OSC
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Giga PHY Status Registers
|
* Giga PHY Status Registers
|
||||||
*/
|
*/
|
||||||
|
@ -1191,6 +1238,11 @@ static inline int is_buggy250(unsigned short device, u8 chiprev)
|
||||||
return device == PCI_DEVICE_ID_JMICRON_JMC250 && chiprev == 0x11;
|
return device == PCI_DEVICE_ID_JMICRON_JMC250 && chiprev == 0x11;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int new_phy_power_ctrl(u8 chip_main_rev)
|
||||||
|
{
|
||||||
|
return chip_main_rev >= 5;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Function prototypes
|
* Function prototypes
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue