diff options
author | Florian Fainelli <f.fainelli@gmail.com> | 2014-11-25 21:08:49 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-11-26 12:03:56 -0500 |
commit | 33f846142919f0ecceb9fde99fecdbc307dbf541 (patch) | |
tree | 810ce217c49c63bf970fe05cddd7876723a70453 | |
parent | a566059d89139c3c3ce21b0c7cb37886b2549b78 (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.c | 52 |
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 | ||
380 | static 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 | |||
380 | static int bcm_sf2_sw_setup(struct dsa_switch *ds) | 403 | static 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 | ||
738 | static 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 | |||
761 | static int bcm_sf2_sw_resume(struct dsa_switch *ds) | 767 | static 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); |