diff options
author | David S. Miller <davem@davemloft.net> | 2015-02-07 22:38:45 -0800 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-02-07 22:38:45 -0800 |
commit | 2150f984258e7909327cb90115c8ff41b4e9acb5 (patch) | |
tree | 95f757336beda2400a803524c21a5ea2e2207119 | |
parent | 3c09e92fb6b94b7597442c1f232a260c35b30698 (diff) | |
parent | 9af197a8f6ecab8c22e4ad0167616151fce5a4cb (diff) | |
download | talos-op-linux-2150f984258e7909327cb90115c8ff41b4e9acb5.tar.gz talos-op-linux-2150f984258e7909327cb90115c8ff41b4e9acb5.zip |
Merge branch 'dsa-next'
Florian Fainelli says:
====================
net: dsa: bcm_sf2: GPHY power down
This patch series implement GPHY power up and down in the SF2 switch
driver in order to conserve power whenever possible (e.g: port is brought
down or unused during Wake-on-LAN).
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/dsa/bcm_sf2.c | 64 | ||||
-rw-r--r-- | drivers/net/dsa/bcm_sf2_regs.h | 4 |
2 files changed, 56 insertions, 12 deletions
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 09f6b3cc1f66..4daffb284931 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -233,6 +233,35 @@ static void bcm_sf2_eee_enable_set(struct dsa_switch *ds, int port, bool enable) core_writel(priv, reg, CORE_EEE_EN_CTRL); } +static void bcm_sf2_gphy_enable_set(struct dsa_switch *ds, bool enable) +{ + struct bcm_sf2_priv *priv = ds_to_priv(ds); + u32 reg; + + reg = reg_readl(priv, REG_SPHY_CNTRL); + if (enable) { + reg |= PHY_RESET; + reg &= ~(EXT_PWR_DOWN | IDDQ_BIAS | CK25_DIS); + reg_writel(priv, reg, REG_SPHY_CNTRL); + udelay(21); + reg = reg_readl(priv, REG_SPHY_CNTRL); + reg &= ~PHY_RESET; + } else { + reg |= EXT_PWR_DOWN | IDDQ_BIAS | PHY_RESET; + reg_writel(priv, reg, REG_SPHY_CNTRL); + mdelay(1); + reg |= CK25_DIS; + } + reg_writel(priv, reg, REG_SPHY_CNTRL); + + /* Use PHY-driven LED signaling */ + if (!enable) { + reg = reg_readl(priv, REG_LED_CNTRL(0)); + reg |= SPDLNK_SRC_SEL; + reg_writel(priv, reg, REG_LED_CNTRL(0)); + } +} + static int bcm_sf2_port_setup(struct dsa_switch *ds, int port, struct phy_device *phy) { @@ -248,6 +277,24 @@ static int bcm_sf2_port_setup(struct dsa_switch *ds, int port, /* Clear the Rx and Tx disable bits and set to no spanning tree */ core_writel(priv, 0, CORE_G_PCTL_PORT(port)); + /* Re-enable the GPHY and re-apply workarounds */ + if (port == 0 && priv->hw_params.num_gphy == 1) { + bcm_sf2_gphy_enable_set(ds, true); + if (phy) { + /* if phy_stop() has been called before, phy + * will be in halted state, and phy_start() + * will call resume. + * + * the resume path does not configure back + * autoneg settings, and since we hard reset + * the phy manually here, we need to reset the + * state machine also. + */ + phy->state = PHY_READY; + phy_init_hw(phy); + } + } + /* Enable port 7 interrupts to get notified */ if (port == 7) intrl2_1_mask_clear(priv, P_IRQ_MASK(P7_IRQ_OFF)); @@ -281,6 +328,9 @@ static void bcm_sf2_port_disable(struct dsa_switch *ds, int port, intrl2_1_writel(priv, P_IRQ_MASK(P7_IRQ_OFF), INTRL2_CPU_CLEAR); } + if (port == 0 && priv->hw_params.num_gphy == 1) + bcm_sf2_gphy_enable_set(ds, false); + if (dsa_is_cpu_port(ds, port)) off = CORE_IMP_CTL; else @@ -771,7 +821,6 @@ static int bcm_sf2_sw_resume(struct dsa_switch *ds) { struct bcm_sf2_priv *priv = ds_to_priv(ds); unsigned int port; - u32 reg; int ret; ret = bcm_sf2_sw_rst(priv); @@ -780,17 +829,8 @@ static int bcm_sf2_sw_resume(struct dsa_switch *ds) return ret; } - /* Reinitialize the single GPHY */ - if (priv->hw_params.num_gphy == 1) { - reg = reg_readl(priv, REG_SPHY_CNTRL); - reg |= PHY_RESET; - reg &= ~(EXT_PWR_DOWN | IDDQ_BIAS); - reg_writel(priv, reg, REG_SPHY_CNTRL); - udelay(21); - reg = reg_readl(priv, REG_SPHY_CNTRL); - reg &= ~PHY_RESET; - reg_writel(priv, reg, REG_SPHY_CNTRL); - } + if (priv->hw_params.num_gphy == 1) + bcm_sf2_gphy_enable_set(ds, true); for (port = 0; port < DSA_MAX_PORTS; port++) { if ((1 << port) & ds->phys_port_mask) diff --git a/drivers/net/dsa/bcm_sf2_regs.h b/drivers/net/dsa/bcm_sf2_regs.h index 1bb49cb699ab..cabdfa5e217a 100644 --- a/drivers/net/dsa/bcm_sf2_regs.h +++ b/drivers/net/dsa/bcm_sf2_regs.h @@ -61,6 +61,10 @@ #define LPI_COUNT_SHIFT 9 #define LPI_COUNT_MASK 0x3F +#define REG_LED_CNTRL_BASE 0x90 +#define REG_LED_CNTRL(x) (REG_LED_CNTRL_BASE + (x) * 4) +#define SPDLNK_SRC_SEL (1 << 24) + /* Register set relative to 'INTRL2_0' and 'INTRL2_1' */ #define INTRL2_CPU_STATUS 0x00 #define INTRL2_CPU_SET 0x04 |