diff options
author | Florian Fainelli <f.fainelli@gmail.com> | 2019-11-04 13:51:39 -0800 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-11-05 18:06:38 -0800 |
commit | eee87e4377a4b86dc2eea0ade162b0dc33f40576 (patch) | |
tree | a5c32c181178bec55759b98097d19a2e4c206791 /drivers | |
parent | 9482d036cc02848f7001f2cc13e417fae0f4a1e8 (diff) |
net: dsa: bcm_sf2: Add support for optional reset controller line
Grab an optional and exclusive reset controller line for the switch and
manage it during probe/remove functions accordingly. For 7278 devices we
change bcm_sf2_sw_rst() to use the reset controller line since the
WATCHDOG_CTRL register does not reset the switch contrary to stated
documentation.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/dsa/bcm_sf2.c | 19 | ||||
-rw-r--r-- | drivers/net/dsa/bcm_sf2.h | 3 |
2 files changed, 22 insertions, 0 deletions
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 67125a5487e1..9ce5a0dbcde1 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -350,6 +350,18 @@ static int bcm_sf2_sw_rst(struct bcm_sf2_priv *priv) { unsigned int timeout = 1000; u32 reg; + int ret; + + /* The watchdog reset does not work on 7278, we need to hit the + * "external" reset line through the reset controller. + */ + if (priv->type == BCM7278_DEVICE_ID && !IS_ERR(priv->rcdev)) { + ret = reset_control_assert(priv->rcdev); + if (ret) + return ret; + + return reset_control_deassert(priv->rcdev); + } reg = core_readl(priv, CORE_WATCHDOG_CTRL); reg |= SOFTWARE_RESET | EN_CHIP_RST | EN_SW_RESET; @@ -1092,6 +1104,11 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev) priv->core_reg_align = data->core_reg_align; priv->num_cfp_rules = data->num_cfp_rules; + priv->rcdev = devm_reset_control_get_optional_exclusive(&pdev->dev, + "switch"); + if (PTR_ERR(priv->rcdev) == -EPROBE_DEFER) + return PTR_ERR(priv->rcdev); + /* Auto-detection using standard registers will not work, so * provide an indication of what kind of device we are for * b53_common to work with @@ -1224,6 +1241,8 @@ static int bcm_sf2_sw_remove(struct platform_device *pdev) /* Disable all ports and interrupts */ bcm_sf2_sw_suspend(priv->dev->ds); bcm_sf2_mdio_unregister(priv); + if (priv->type == BCM7278_DEVICE_ID && !IS_ERR(priv->rcdev)) + reset_control_assert(priv->rcdev); return 0; } diff --git a/drivers/net/dsa/bcm_sf2.h b/drivers/net/dsa/bcm_sf2.h index 1df30ccec42d..de386dd96d66 100644 --- a/drivers/net/dsa/bcm_sf2.h +++ b/drivers/net/dsa/bcm_sf2.h @@ -18,6 +18,7 @@ #include <linux/types.h> #include <linux/bitops.h> #include <linux/if_vlan.h> +#include <linux/reset.h> #include <net/dsa.h> @@ -64,6 +65,8 @@ struct bcm_sf2_priv { void __iomem *fcb; void __iomem *acb; + struct reset_control *rcdev; + /* Register offsets indirection tables */ u32 type; const u16 *reg_offsets; |