[RFC PATCH net-next 11/20] net: dsa: mv88e6xxx: factorize switch reset

From: Vivien Didelot
Date: Thu May 05 2016 - 18:41:55 EST


Add a MV88E6XXX_FLAG_PPU_ACTIVE flag to describe how to reset the
switch, and merge the reset call to the common setup code.

Signed-off-by: Vivien Didelot <vivien.didelot@xxxxxxxxxxxxxxxxxxxx>
---
drivers/net/dsa/mv88e6123.c | 4 --
drivers/net/dsa/mv88e6131.c | 4 --
drivers/net/dsa/mv88e6171.c | 8 +--
drivers/net/dsa/mv88e6352.c | 10 ++--
drivers/net/dsa/mv88e6xxx.c | 137 +++++++++++++++++++++++---------------------
drivers/net/dsa/mv88e6xxx.h | 3 +-
6 files changed, 83 insertions(+), 83 deletions(-)

diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index c562c4a..f542fbf 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -102,10 +102,6 @@ static int mv88e6123_setup(struct dsa_switch *ds)
if (ret < 0)
return ret;

- ret = mv88e6xxx_switch_reset(ps, false);
- if (ret < 0)
- return ret;
-
ret = mv88e6123_setup_global(ds);
if (ret < 0)
return ret;
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index 655781f..5b33d39 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -144,10 +144,6 @@ static int mv88e6131_setup(struct dsa_switch *ds)
if (ret < 0)
return ret;

- ret = mv88e6xxx_switch_reset(ps, false);
- if (ret < 0)
- return ret;
-
ret = mv88e6131_setup_global(ds);
if (ret < 0)
return ret;
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index 66e581f..9724a25 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -26,6 +26,7 @@ static const struct mv88e6xxx_info mv88e6171_table[] = {
.num_ports = 7,
.flags = MV88E6XXX_FLAG_ATU |
MV88E6XXX_FLAG_PORTSTATE |
+ MV88E6XXX_FLAG_PPU_ACTIVE |
MV88E6XXX_FLAG_SMI_PHY |
MV88E6XXX_FLAG_SWITCH_MAC |
MV88E6XXX_FLAG_TEMP |
@@ -39,6 +40,7 @@ static const struct mv88e6xxx_info mv88e6171_table[] = {
.num_ports = 7,
.flags = MV88E6XXX_FLAG_ATU |
MV88E6XXX_FLAG_PORTSTATE |
+ MV88E6XXX_FLAG_PPU_ACTIVE |
MV88E6XXX_FLAG_SMI_PHY |
MV88E6XXX_FLAG_SWITCH_MAC |
MV88E6XXX_FLAG_TEMP |
@@ -52,6 +54,7 @@ static const struct mv88e6xxx_info mv88e6171_table[] = {
.num_ports = 7,
.flags = MV88E6XXX_FLAG_ATU |
MV88E6XXX_FLAG_PORTSTATE |
+ MV88E6XXX_FLAG_PPU_ACTIVE |
MV88E6XXX_FLAG_SMI_PHY |
MV88E6XXX_FLAG_SWITCH_MAC |
MV88E6XXX_FLAG_TEMP |
@@ -65,6 +68,7 @@ static const struct mv88e6xxx_info mv88e6171_table[] = {
.num_ports = 7,
.flags = MV88E6XXX_FLAG_ATU |
MV88E6XXX_FLAG_PORTSTATE |
+ MV88E6XXX_FLAG_PPU_ACTIVE |
MV88E6XXX_FLAG_SMI_PHY |
MV88E6XXX_FLAG_SWITCH_MAC |
MV88E6XXX_FLAG_TEMP |
@@ -132,10 +136,6 @@ static int mv88e6171_setup(struct dsa_switch *ds)
if (ret < 0)
return ret;

- ret = mv88e6xxx_switch_reset(ps, true);
- if (ret < 0)
- return ret;
-
ret = mv88e6171_setup_global(ds);
if (ret < 0)
return ret;
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index f10aaee..a9d4d47a 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -33,6 +33,7 @@ static const struct mv88e6xxx_info mv88e6352_table[] = {
MV88E6XXX_FLAG_EEE |
MV88E6XXX_FLAG_EEPROM |
MV88E6XXX_FLAG_PORTSTATE |
+ MV88E6XXX_FLAG_PPU_ACTIVE |
MV88E6XXX_FLAG_SMI_PHY |
MV88E6XXX_FLAG_SWITCH_MAC |
MV88E6XXX_FLAG_TEMP |
@@ -49,6 +50,7 @@ static const struct mv88e6xxx_info mv88e6352_table[] = {
MV88E6XXX_FLAG_EEE |
MV88E6XXX_FLAG_EEPROM |
MV88E6XXX_FLAG_PORTSTATE |
+ MV88E6XXX_FLAG_PPU_ACTIVE |
MV88E6XXX_FLAG_SMI_PHY |
MV88E6XXX_FLAG_SWITCH_MAC |
MV88E6XXX_FLAG_TEMP |
@@ -65,6 +67,7 @@ static const struct mv88e6xxx_info mv88e6352_table[] = {
MV88E6XXX_FLAG_EEE |
MV88E6XXX_FLAG_EEPROM |
MV88E6XXX_FLAG_PORTSTATE |
+ MV88E6XXX_FLAG_PPU_ACTIVE |
MV88E6XXX_FLAG_SMI_PHY |
MV88E6XXX_FLAG_SWITCH_MAC |
MV88E6XXX_FLAG_TEMP |
@@ -81,6 +84,7 @@ static const struct mv88e6xxx_info mv88e6352_table[] = {
MV88E6XXX_FLAG_EEE |
MV88E6XXX_FLAG_EEPROM |
MV88E6XXX_FLAG_PORTSTATE |
+ MV88E6XXX_FLAG_PPU_ACTIVE |
MV88E6XXX_FLAG_SMI_PHY |
MV88E6XXX_FLAG_SWITCH_MAC |
MV88E6XXX_FLAG_TEMP |
@@ -97,6 +101,7 @@ static const struct mv88e6xxx_info mv88e6352_table[] = {
MV88E6XXX_FLAG_EEE |
MV88E6XXX_FLAG_EEPROM |
MV88E6XXX_FLAG_PORTSTATE |
+ MV88E6XXX_FLAG_PPU_ACTIVE |
MV88E6XXX_FLAG_SMI_PHY |
MV88E6XXX_FLAG_SWITCH_MAC |
MV88E6XXX_FLAG_TEMP |
@@ -113,6 +118,7 @@ static const struct mv88e6xxx_info mv88e6352_table[] = {
MV88E6XXX_FLAG_EEE |
MV88E6XXX_FLAG_EEPROM |
MV88E6XXX_FLAG_PORTSTATE |
+ MV88E6XXX_FLAG_PPU_ACTIVE |
MV88E6XXX_FLAG_SMI_PHY |
MV88E6XXX_FLAG_SWITCH_MAC |
MV88E6XXX_FLAG_TEMP |
@@ -179,10 +185,6 @@ static int mv88e6352_setup(struct dsa_switch *ds)
if (ret < 0)
return ret;

- ret = mv88e6xxx_switch_reset(ps, true);
- if (ret < 0)
- return ret;
-
ret = mv88e6352_setup_global(ds);
if (ret < 0)
return ret;
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 810226d..b52e3d0 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -2549,6 +2549,68 @@ restore_page_0:
return ret;
}

+static int _mv88e6xxx_switch_reset(struct mv88e6xxx_priv_state *ps)
+{
+ bool ppu_active = mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU_ACTIVE);
+ u16 is_reset = (ppu_active ? 0x8800 : 0xc800);
+ struct gpio_desc *gpiod = ps->ds->pd->reset;
+ unsigned long timeout;
+ int ret;
+ int i;
+
+ /* Set all ports to the disabled state. */
+ for (i = 0; i < ps->info->num_ports; i++) {
+ ret = _mv88e6xxx_reg_read(ps, REG_PORT(i), PORT_CONTROL);
+ if (ret < 0)
+ return ret;
+
+ ret = _mv88e6xxx_reg_write(ps, REG_PORT(i), PORT_CONTROL,
+ ret & 0xfffc);
+ if (ret)
+ return ret;
+ }
+
+ /* Wait for transmit queues to drain. */
+ usleep_range(2000, 4000);
+
+ /* If there is a gpio connected to the reset pin, toggle it */
+ if (gpiod) {
+ gpiod_set_value_cansleep(gpiod, 1);
+ usleep_range(10000, 20000);
+ gpiod_set_value_cansleep(gpiod, 0);
+ usleep_range(10000, 20000);
+ }
+
+ /* Reset the switch. Keep the PPU active if requested. The PPU
+ * needs to be active to support indirect phy register access
+ * through global registers 0x18 and 0x19.
+ */
+ if (ppu_active)
+ ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, 0x04, 0xc000);
+ else
+ ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, 0x04, 0xc400);
+ if (ret)
+ return ret;
+
+ /* Wait up to one second for reset to complete. */
+ timeout = jiffies + 1 * HZ;
+ while (time_before(jiffies, timeout)) {
+ ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, 0x00);
+ if (ret < 0)
+ return ret;
+
+ if ((ret & is_reset) == is_reset)
+ break;
+ usleep_range(1000, 2000);
+ }
+ if (time_after(jiffies, timeout))
+ ret = -ETIMEDOUT;
+ else
+ ret = 0;
+
+ return ret;
+}
+
static int mv88e6xxx_power_on_serdes(struct mv88e6xxx_priv_state *ps)
{
int ret;
@@ -2850,6 +2912,8 @@ int mv88e6xxx_setup_ports(struct dsa_switch *ds)

int mv88e6xxx_setup_common(struct mv88e6xxx_priv_state *ps)
{
+ int err;
+
mutex_init(&ps->smi_mutex);

INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work);
@@ -2860,7 +2924,13 @@ int mv88e6xxx_setup_common(struct mv88e6xxx_priv_state *ps)
if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
mv88e6xxx_ppu_state_init(ps);

- return 0;
+ mutex_lock(&ps->smi_mutex);
+
+ err = _mv88e6xxx_switch_reset(ps);
+
+ mutex_unlock(&ps->smi_mutex);
+
+ return err;
}

int mv88e6xxx_setup_global(struct dsa_switch *ds)
@@ -3036,71 +3106,6 @@ unlock:
return err;
}

-int mv88e6xxx_switch_reset(struct mv88e6xxx_priv_state *ps, bool ppu_active)
-{
- u16 is_reset = (ppu_active ? 0x8800 : 0xc800);
- struct gpio_desc *gpiod = ps->ds->pd->reset;
- unsigned long timeout;
- int ret;
- int i;
-
- mutex_lock(&ps->smi_mutex);
-
- /* Set all ports to the disabled state. */
- for (i = 0; i < ps->info->num_ports; i++) {
- ret = _mv88e6xxx_reg_read(ps, REG_PORT(i), PORT_CONTROL);
- if (ret < 0)
- goto unlock;
-
- ret = _mv88e6xxx_reg_write(ps, REG_PORT(i), PORT_CONTROL,
- ret & 0xfffc);
- if (ret)
- goto unlock;
- }
-
- /* Wait for transmit queues to drain. */
- usleep_range(2000, 4000);
-
- /* If there is a gpio connected to the reset pin, toggle it */
- if (gpiod) {
- gpiod_set_value_cansleep(gpiod, 1);
- usleep_range(10000, 20000);
- gpiod_set_value_cansleep(gpiod, 0);
- usleep_range(10000, 20000);
- }
-
- /* Reset the switch. Keep the PPU active if requested. The PPU
- * needs to be active to support indirect phy register access
- * through global registers 0x18 and 0x19.
- */
- if (ppu_active)
- ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, 0x04, 0xc000);
- else
- ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, 0x04, 0xc400);
- if (ret)
- goto unlock;
-
- /* Wait up to one second for reset to complete. */
- timeout = jiffies + 1 * HZ;
- while (time_before(jiffies, timeout)) {
- ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, 0x00);
- if (ret < 0)
- goto unlock;
-
- if ((ret & is_reset) == is_reset)
- break;
- usleep_range(1000, 2000);
- }
- if (time_after(jiffies, timeout))
- ret = -ETIMEDOUT;
- else
- ret = 0;
-unlock:
- mutex_unlock(&ps->smi_mutex);
-
- return ret;
-}
-
int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index e639de7..7ca7230 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -374,6 +374,7 @@ enum mv88e6xxx_cap {
* See GLOBAL_CONTROL_PPU_ENABLE and GLOBAL_STATUS_PPU_POLLING.
*/
MV88E6XXX_CAP_PPU,
+ MV88E6XXX_CAP_PPU_ACTIVE,

/* SMI PHY Command and Data registers.
* This requires an indirect access to PHY registers through
@@ -412,6 +413,7 @@ enum mv88e6xxx_cap {
#define MV88E6XXX_FLAG_EEPROM BIT(MV88E6XXX_CAP_EEPROM)
#define MV88E6XXX_FLAG_PORTSTATE BIT(MV88E6XXX_CAP_PORTSTATE)
#define MV88E6XXX_FLAG_PPU BIT(MV88E6XXX_CAP_PPU)
+#define MV88E6XXX_FLAG_PPU_ACTIVE BIT(MV88E6XXX_CAP_PPU_ACTIVE)
#define MV88E6XXX_FLAG_SMI_PHY BIT(MV88E6XXX_CAP_SMI_PHY)
#define MV88E6XXX_FLAG_SWITCH_MAC BIT(MV88E6XXX_CAP_SWITCH_MAC_WOL_WOF)
#define MV88E6XXX_FLAG_TEMP BIT(MV88E6XXX_CAP_TEMP)
@@ -523,7 +525,6 @@ static inline bool mv88e6xxx_has(struct mv88e6xxx_priv_state *ps,
return (ps->info->flags & flags) == flags;
}

-int mv88e6xxx_switch_reset(struct mv88e6xxx_priv_state *ps, bool ppu_active);
const char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,
int sw_addr, void **priv,
const struct mv88e6xxx_info *table,
--
2.8.2