aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/dsa/bcm_sf2.c50
-rw-r--r--drivers/net/dsa/bcm_sf2_regs.h4
2 files changed, 45 insertions, 9 deletions
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 45c0e2b97f5f..4daffb284931 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -238,17 +238,28 @@ static void bcm_sf2_gphy_enable_set(struct dsa_switch *ds, bool enable)
238 struct bcm_sf2_priv *priv = ds_to_priv(ds); 238 struct bcm_sf2_priv *priv = ds_to_priv(ds);
239 u32 reg; 239 u32 reg;
240 240
241 if (!enable)
242 return;
243
244 reg = reg_readl(priv, REG_SPHY_CNTRL);
245 reg |= PHY_RESET;
246 reg &= ~(EXT_PWR_DOWN | IDDQ_BIAS);
247 reg_writel(priv, reg, REG_SPHY_CNTRL);
248 udelay(21);
249 reg = reg_readl(priv, REG_SPHY_CNTRL); 241 reg = reg_readl(priv, REG_SPHY_CNTRL);
250 reg &= ~PHY_RESET; 242 if (enable) {
243 reg |= PHY_RESET;
244 reg &= ~(EXT_PWR_DOWN | IDDQ_BIAS | CK25_DIS);
245 reg_writel(priv, reg, REG_SPHY_CNTRL);
246 udelay(21);
247 reg = reg_readl(priv, REG_SPHY_CNTRL);
248 reg &= ~PHY_RESET;
249 } else {
250 reg |= EXT_PWR_DOWN | IDDQ_BIAS | PHY_RESET;
251 reg_writel(priv, reg, REG_SPHY_CNTRL);
252 mdelay(1);
253 reg |= CK25_DIS;
254 }
251 reg_writel(priv, reg, REG_SPHY_CNTRL); 255 reg_writel(priv, reg, REG_SPHY_CNTRL);
256
257 /* Use PHY-driven LED signaling */
258 if (!enable) {
259 reg = reg_readl(priv, REG_LED_CNTRL(0));
260 reg |= SPDLNK_SRC_SEL;
261 reg_writel(priv, reg, REG_LED_CNTRL(0));
262 }
252} 263}
253 264
254static int bcm_sf2_port_setup(struct dsa_switch *ds, int port, 265static int bcm_sf2_port_setup(struct dsa_switch *ds, int port,
@@ -266,6 +277,24 @@ static int bcm_sf2_port_setup(struct dsa_switch *ds, int port,
266 /* Clear the Rx and Tx disable bits and set to no spanning tree */ 277 /* Clear the Rx and Tx disable bits and set to no spanning tree */
267 core_writel(priv, 0, CORE_G_PCTL_PORT(port)); 278 core_writel(priv, 0, CORE_G_PCTL_PORT(port));
268 279
280 /* Re-enable the GPHY and re-apply workarounds */
281 if (port == 0 && priv->hw_params.num_gphy == 1) {
282 bcm_sf2_gphy_enable_set(ds, true);
283 if (phy) {
284 /* if phy_stop() has been called before, phy
285 * will be in halted state, and phy_start()
286 * will call resume.
287 *
288 * the resume path does not configure back
289 * autoneg settings, and since we hard reset
290 * the phy manually here, we need to reset the
291 * state machine also.
292 */
293 phy->state = PHY_READY;
294 phy_init_hw(phy);
295 }
296 }
297
269 /* Enable port 7 interrupts to get notified */ 298 /* Enable port 7 interrupts to get notified */
270 if (port == 7) 299 if (port == 7)
271 intrl2_1_mask_clear(priv, P_IRQ_MASK(P7_IRQ_OFF)); 300 intrl2_1_mask_clear(priv, P_IRQ_MASK(P7_IRQ_OFF));
@@ -299,6 +328,9 @@ static void bcm_sf2_port_disable(struct dsa_switch *ds, int port,
299 intrl2_1_writel(priv, P_IRQ_MASK(P7_IRQ_OFF), INTRL2_CPU_CLEAR); 328 intrl2_1_writel(priv, P_IRQ_MASK(P7_IRQ_OFF), INTRL2_CPU_CLEAR);
300 } 329 }
301 330
331 if (port == 0 && priv->hw_params.num_gphy == 1)
332 bcm_sf2_gphy_enable_set(ds, false);
333
302 if (dsa_is_cpu_port(ds, port)) 334 if (dsa_is_cpu_port(ds, port))
303 off = CORE_IMP_CTL; 335 off = CORE_IMP_CTL;
304 else 336 else
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 @@
61#define LPI_COUNT_SHIFT 9 61#define LPI_COUNT_SHIFT 9
62#define LPI_COUNT_MASK 0x3F 62#define LPI_COUNT_MASK 0x3F
63 63
64#define REG_LED_CNTRL_BASE 0x90
65#define REG_LED_CNTRL(x) (REG_LED_CNTRL_BASE + (x) * 4)
66#define SPDLNK_SRC_SEL (1 << 24)
67
64/* Register set relative to 'INTRL2_0' and 'INTRL2_1' */ 68/* Register set relative to 'INTRL2_0' and 'INTRL2_1' */
65#define INTRL2_CPU_STATUS 0x00 69#define INTRL2_CPU_STATUS 0x00
66#define INTRL2_CPU_SET 0x04 70#define INTRL2_CPU_SET 0x04