Commit fbe4d0d6 authored by David S. Miller's avatar David S. Miller

Merge branch 'bcm_sf2'

Florian Fainelli says:

====================
net: dsa: bcm_sf2: misc bugfixes

This patch series contains two bug fixes:

- first patch fixes an issue on the error path of the driver where we could
  have left some of our registers mapped

- second patch enforces the use of a software reset of the switch to guarantee
  the HW is in a consistent state prior to software initialization
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents a620a6bc 33f84614
...@@ -377,6 +377,29 @@ static irqreturn_t bcm_sf2_switch_1_isr(int irq, void *dev_id) ...@@ -377,6 +377,29 @@ static irqreturn_t bcm_sf2_switch_1_isr(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int bcm_sf2_sw_rst(struct bcm_sf2_priv *priv)
{
unsigned int timeout = 1000;
u32 reg;
reg = core_readl(priv, CORE_WATCHDOG_CTRL);
reg |= SOFTWARE_RESET | EN_CHIP_RST | EN_SW_RESET;
core_writel(priv, reg, CORE_WATCHDOG_CTRL);
do {
reg = core_readl(priv, CORE_WATCHDOG_CTRL);
if (!(reg & SOFTWARE_RESET))
break;
usleep_range(1000, 2000);
} while (timeout-- > 0);
if (timeout == 0)
return -ETIMEDOUT;
return 0;
}
static int bcm_sf2_sw_setup(struct dsa_switch *ds) static int bcm_sf2_sw_setup(struct dsa_switch *ds)
{ {
const char *reg_names[BCM_SF2_REGS_NUM] = BCM_SF2_REGS_NAME; 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,11 +427,18 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds)
*base = of_iomap(dn, i); *base = of_iomap(dn, i);
if (*base == NULL) { if (*base == NULL) {
pr_err("unable to find register: %s\n", reg_names[i]); pr_err("unable to find register: %s\n", reg_names[i]);
return -ENODEV; ret = -ENOMEM;
goto out_unmap;
} }
base++; base++;
} }
ret = bcm_sf2_sw_rst(priv);
if (ret) {
pr_err("unable to software reset switch: %d\n", ret);
goto out_unmap;
}
/* Disable all interrupts and request them */ /* Disable all interrupts and request them */
intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_MASK_SET); intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_MASK_SET);
intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_CLEAR); intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_CLEAR);
...@@ -484,6 +514,7 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds) ...@@ -484,6 +514,7 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds)
out_unmap: out_unmap:
base = &priv->core; base = &priv->core;
for (i = 0; i < BCM_SF2_REGS_NUM; i++) { for (i = 0; i < BCM_SF2_REGS_NUM; i++) {
if (*base)
iounmap(*base); iounmap(*base);
base++; base++;
} }
...@@ -733,29 +764,6 @@ static int bcm_sf2_sw_suspend(struct dsa_switch *ds) ...@@ -733,29 +764,6 @@ static int bcm_sf2_sw_suspend(struct dsa_switch *ds)
return 0; return 0;
} }
static int bcm_sf2_sw_rst(struct bcm_sf2_priv *priv)
{
unsigned int timeout = 1000;
u32 reg;
reg = core_readl(priv, CORE_WATCHDOG_CTRL);
reg |= SOFTWARE_RESET | EN_CHIP_RST | EN_SW_RESET;
core_writel(priv, reg, CORE_WATCHDOG_CTRL);
do {
reg = core_readl(priv, CORE_WATCHDOG_CTRL);
if (!(reg & SOFTWARE_RESET))
break;
usleep_range(1000, 2000);
} while (timeout-- > 0);
if (timeout == 0)
return -ETIMEDOUT;
return 0;
}
static int bcm_sf2_sw_resume(struct dsa_switch *ds) static int bcm_sf2_sw_resume(struct dsa_switch *ds)
{ {
struct bcm_sf2_priv *priv = ds_to_priv(ds); struct bcm_sf2_priv *priv = ds_to_priv(ds);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment