diff options
Diffstat (limited to 'drivers/net/dsa/bcm_sf2.c')
-rw-r--r-- | drivers/net/dsa/bcm_sf2.c | 58 |
1 files changed, 33 insertions, 25 deletions
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index b9625968daac..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; |
@@ -404,11 +427,18 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds) | |||
404 | *base = of_iomap(dn, i); | 427 | *base = of_iomap(dn, i); |
405 | if (*base == NULL) { | 428 | if (*base == NULL) { |
406 | pr_err("unable to find register: %s\n", reg_names[i]); | 429 | pr_err("unable to find register: %s\n", reg_names[i]); |
407 | return -ENODEV; | 430 | ret = -ENOMEM; |
431 | goto out_unmap; | ||
408 | } | 432 | } |
409 | base++; | 433 | base++; |
410 | } | 434 | } |
411 | 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 | |||
412 | /* Disable all interrupts and request them */ | 442 | /* Disable all interrupts and request them */ |
413 | intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_MASK_SET); | 443 | intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_MASK_SET); |
414 | intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_CLEAR); | 444 | intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_CLEAR); |
@@ -484,7 +514,8 @@ out_free_irq0: | |||
484 | out_unmap: | 514 | out_unmap: |
485 | base = &priv->core; | 515 | base = &priv->core; |
486 | for (i = 0; i < BCM_SF2_REGS_NUM; i++) { | 516 | for (i = 0; i < BCM_SF2_REGS_NUM; i++) { |
487 | iounmap(*base); | 517 | if (*base) |
518 | iounmap(*base); | ||
488 | base++; | 519 | base++; |
489 | } | 520 | } |
490 | return ret; | 521 | return ret; |
@@ -733,29 +764,6 @@ static int bcm_sf2_sw_suspend(struct dsa_switch *ds) | |||
733 | return 0; | 764 | return 0; |
734 | } | 765 | } |
735 | 766 | ||
736 | static int bcm_sf2_sw_rst(struct bcm_sf2_priv *priv) | ||
737 | { | ||
738 | unsigned int timeout = 1000; | ||
739 | u32 reg; | ||
740 | |||
741 | reg = core_readl(priv, CORE_WATCHDOG_CTRL); | ||
742 | reg |= SOFTWARE_RESET | EN_CHIP_RST | EN_SW_RESET; | ||
743 | core_writel(priv, reg, CORE_WATCHDOG_CTRL); | ||
744 | |||
745 | do { | ||
746 | reg = core_readl(priv, CORE_WATCHDOG_CTRL); | ||
747 | if (!(reg & SOFTWARE_RESET)) | ||
748 | break; | ||
749 | |||
750 | usleep_range(1000, 2000); | ||
751 | } while (timeout-- > 0); | ||
752 | |||
753 | if (timeout == 0) | ||
754 | return -ETIMEDOUT; | ||
755 | |||
756 | return 0; | ||
757 | } | ||
758 | |||
759 | static int bcm_sf2_sw_resume(struct dsa_switch *ds) | 767 | static int bcm_sf2_sw_resume(struct dsa_switch *ds) |
760 | { | 768 | { |
761 | struct bcm_sf2_priv *priv = ds_to_priv(ds); | 769 | struct bcm_sf2_priv *priv = ds_to_priv(ds); |