aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/dsa/bcm_sf2.c
diff options
context:
space:
mode:
authorFlorian Fainelli <f.fainelli@gmail.com>2014-09-18 20:31:23 -0400
committerDavid S. Miller <davem@davemloft.net>2014-09-22 14:41:23 -0400
commit8cfa94984c9cfdd5f5af2af4f161176cb7256d44 (patch)
tree8a41b591a41f652361fde48ca0916da8fd466497 /drivers/net/dsa/bcm_sf2.c
parent2446254915a7d6f08bba9a755a34cc0402880472 (diff)
net: dsa: bcm_sf2: add suspend/resume callbacks
Implement the suspend/resume callbacks for the Broadcom Starfighter 2 switch driver. Suspending the switch requires masking interrupts and shutting down ports. Resuming the switch requires a software reset since we do not know which power-sate we might be coming from, and re-enabling the physical ports that are used. Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/dsa/bcm_sf2.c')
-rw-r--r--drivers/net/dsa/bcm_sf2.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index a97ba2548ea5..29ceee366e44 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -606,6 +606,89 @@ static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port,
606 status->pause = 1; 606 status->pause = 1;
607} 607}
608 608
609static int bcm_sf2_sw_suspend(struct dsa_switch *ds)
610{
611 struct bcm_sf2_priv *priv = ds_to_priv(ds);
612 unsigned int port;
613
614 intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_MASK_SET);
615 intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_CLEAR);
616 intrl2_0_writel(priv, 0, INTRL2_CPU_MASK_CLEAR);
617 intrl2_1_writel(priv, 0xffffffff, INTRL2_CPU_MASK_SET);
618 intrl2_1_writel(priv, 0xffffffff, INTRL2_CPU_CLEAR);
619 intrl2_1_writel(priv, 0, INTRL2_CPU_MASK_CLEAR);
620
621 /* Disable all ports physically present including the IMP
622 * port, the other ones have already been disabled during
623 * bcm_sf2_sw_setup
624 */
625 for (port = 0; port < DSA_MAX_PORTS; port++) {
626 if ((1 << port) & ds->phys_port_mask ||
627 dsa_is_cpu_port(ds, port))
628 bcm_sf2_port_disable(ds, port);
629 }
630
631 return 0;
632}
633
634static int bcm_sf2_sw_rst(struct bcm_sf2_priv *priv)
635{
636 unsigned int timeout = 1000;
637 u32 reg;
638
639 reg = core_readl(priv, CORE_WATCHDOG_CTRL);
640 reg |= SOFTWARE_RESET | EN_CHIP_RST | EN_SW_RESET;
641 core_writel(priv, reg, CORE_WATCHDOG_CTRL);
642
643 do {
644 reg = core_readl(priv, CORE_WATCHDOG_CTRL);
645 if (!(reg & SOFTWARE_RESET))
646 break;
647
648 usleep_range(1000, 2000);
649 } while (timeout-- > 0);
650
651 if (timeout == 0)
652 return -ETIMEDOUT;
653
654 return 0;
655}
656
657static int bcm_sf2_sw_resume(struct dsa_switch *ds)
658{
659 struct bcm_sf2_priv *priv = ds_to_priv(ds);
660 unsigned int port;
661 u32 reg;
662 int ret;
663
664 ret = bcm_sf2_sw_rst(priv);
665 if (ret) {
666 pr_err("%s: failed to software reset switch\n", __func__);
667 return ret;
668 }
669
670 /* Reinitialize the single GPHY */
671 if (priv->hw_params.num_gphy == 1) {
672 reg = reg_readl(priv, REG_SPHY_CNTRL);
673 reg |= PHY_RESET;
674 reg &= ~(EXT_PWR_DOWN | IDDQ_BIAS);
675 reg_writel(priv, reg, REG_SPHY_CNTRL);
676 udelay(21);
677 reg = reg_readl(priv, REG_SPHY_CNTRL);
678 reg &= ~PHY_RESET;
679 reg_writel(priv, reg, REG_SPHY_CNTRL);
680 }
681
682 for (port = 0; port < DSA_MAX_PORTS; port++) {
683 if ((1 << port) & ds->phys_port_mask)
684 bcm_sf2_port_setup(ds, port);
685 else if (dsa_is_cpu_port(ds, port))
686 bcm_sf2_imp_setup(ds, port);
687 }
688
689 return 0;
690}
691
609static struct dsa_switch_driver bcm_sf2_switch_driver = { 692static struct dsa_switch_driver bcm_sf2_switch_driver = {
610 .tag_protocol = DSA_TAG_PROTO_BRCM, 693 .tag_protocol = DSA_TAG_PROTO_BRCM,
611 .priv_size = sizeof(struct bcm_sf2_priv), 694 .priv_size = sizeof(struct bcm_sf2_priv),
@@ -620,6 +703,8 @@ static struct dsa_switch_driver bcm_sf2_switch_driver = {
620 .get_sset_count = bcm_sf2_sw_get_sset_count, 703 .get_sset_count = bcm_sf2_sw_get_sset_count,
621 .adjust_link = bcm_sf2_sw_adjust_link, 704 .adjust_link = bcm_sf2_sw_adjust_link,
622 .fixed_link_update = bcm_sf2_sw_fixed_link_update, 705 .fixed_link_update = bcm_sf2_sw_fixed_link_update,
706 .suspend = bcm_sf2_sw_suspend,
707 .resume = bcm_sf2_sw_resume,
623}; 708};
624 709
625static int __init bcm_sf2_init(void) 710static int __init bcm_sf2_init(void)