aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Fainelli <f.fainelli@gmail.com>2014-11-25 21:08:49 -0500
committerDavid S. Miller <davem@davemloft.net>2014-11-26 12:03:56 -0500
commit33f846142919f0ecceb9fde99fecdbc307dbf541 (patch)
tree810ce217c49c63bf970fe05cddd7876723a70453
parenta566059d89139c3c3ce21b0c7cb37886b2549b78 (diff)
net: dsa: bcm_sf2: reset switch prior to initialization
Our boot agent may have left the switch in an certain configuration state, make sure we issue a software reset prior to configuring the switch in order to ensure the HW is in a consistent state, in particular transmit queues and internal buffers. Fixes: 246d7f773c13 ("net: dsa: add Broadcom SF2 switch driver") Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/dsa/bcm_sf2.c52
1 files changed, 29 insertions, 23 deletions
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 46632e8b6336..4f4c2a7888e5 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -377,6 +377,29 @@ static irqreturn_t bcm_sf2_switch_1_isr(int irq, void *dev_id)
377 return IRQ_HANDLED; 377 return IRQ_HANDLED;
378} 378}
379 379
380static int bcm_sf2_sw_rst(struct bcm_sf2_priv *priv)
381{
382 unsigned int timeout = 1000;
383 u32 reg;
384
385 reg = core_readl(priv, CORE_WATCHDOG_CTRL);
386 reg |= SOFTWARE_RESET | EN_CHIP_RST | EN_SW_RESET;
387 core_writel(priv, reg, CORE_WATCHDOG_CTRL);
388
389 do {
390 reg = core_readl(priv, CORE_WATCHDOG_CTRL);
391 if (!(reg & SOFTWARE_RESET))
392 break;
393
394 usleep_range(1000, 2000);
395 } while (timeout-- > 0);
396
397 if (timeout == 0)
398 return -ETIMEDOUT;
399
400 return 0;
401}
402
380static int bcm_sf2_sw_setup(struct dsa_switch *ds) 403static int bcm_sf2_sw_setup(struct dsa_switch *ds)
381{ 404{
382 const char *reg_names[BCM_SF2_REGS_NUM] = BCM_SF2_REGS_NAME; 405 const char *reg_names[BCM_SF2_REGS_NUM] = BCM_SF2_REGS_NAME;
@@ -410,6 +433,12 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds)
410 base++; 433 base++;
411 } 434 }
412 435
436 ret = bcm_sf2_sw_rst(priv);
437 if (ret) {
438 pr_err("unable to software reset switch: %d\n", ret);
439 goto out_unmap;
440 }
441
413 /* Disable all interrupts and request them */ 442 /* Disable all interrupts and request them */
414 intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_MASK_SET); 443 intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_MASK_SET);
415 intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_CLEAR); 444 intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_CLEAR);
@@ -735,29 +764,6 @@ static int bcm_sf2_sw_suspend(struct dsa_switch *ds)
735 return 0; 764 return 0;
736} 765}
737 766
738static int bcm_sf2_sw_rst(struct bcm_sf2_priv *priv)
739{
740 unsigned int timeout = 1000;
741 u32 reg;
742
743 reg = core_readl(priv, CORE_WATCHDOG_CTRL);
744 reg |= SOFTWARE_RESET | EN_CHIP_RST | EN_SW_RESET;
745 core_writel(priv, reg, CORE_WATCHDOG_CTRL);
746
747 do {
748 reg = core_readl(priv, CORE_WATCHDOG_CTRL);
749 if (!(reg & SOFTWARE_RESET))
750 break;
751
752 usleep_range(1000, 2000);
753 } while (timeout-- > 0);
754
755 if (timeout == 0)
756 return -ETIMEDOUT;
757
758 return 0;
759}
760
761static int bcm_sf2_sw_resume(struct dsa_switch *ds) 767static int bcm_sf2_sw_resume(struct dsa_switch *ds)
762{ 768{
763 struct bcm_sf2_priv *priv = ds_to_priv(ds); 769 struct bcm_sf2_priv *priv = ds_to_priv(ds);