Skip to content

Commit

Permalink
jme: PHY Power control for new chip
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Guo-Fu Tseng authored and David S. Miller committed Feb 14, 2011
1 parent 19d9601 commit 4872b11
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 14 deletions.
68 changes: 54 additions & 14 deletions drivers/net/jme.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
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);
reg &= ~PE1_GPREG0_PBG;
reg |= PE1_GPREG0_PDD3COLD;
pci_write_config_dword(jme->pdev, PCI_PRIV_PE1, reg);
}

static inline void
jme_phy_on(struct jme_adapter *jme)
{
Expand All @@ -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 &= ~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_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
Expand All @@ -1606,12 +1654,11 @@ jme_open(struct net_device *netdev)

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);
} else {
else
jme_reset_phy_processor(jme);
}

jme_reset_link(jme);

Expand Down Expand Up @@ -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
jme_powersave_phy(struct jme_adapter *jme)
{
Expand Down Expand Up @@ -3068,12 +3109,11 @@ jme_resume(struct pci_dev *pdev)
jme_clear_pm(jme);
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);
} else {
else
jme_reset_phy_processor(jme);
}

jme_start_irq(jme);
netif_device_attach(netdev);
Expand Down
52 changes: 52 additions & 0 deletions drivers/net/jme.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,37 @@ enum jme_spi_op_bits {
#define HALF_US 500 /* 500 ns */
#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
*/
Expand Down Expand Up @@ -499,6 +530,7 @@ enum jme_iomap_regs {
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_LINK = JME_PHY | 0x30, /* PHY Link Status Register */
JME_SMBCSR = JME_PHY | 0x40, /* SMB Control and Status */
Expand Down Expand Up @@ -834,6 +866,21 @@ enum jme_pmcs_bit_masks {
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
*/
Expand Down Expand Up @@ -1191,6 +1238,11 @@ static inline int is_buggy250(unsigned short device, u8 chiprev)
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
*/
Expand Down

0 comments on commit 4872b11

Please sign in to comment.