Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 552238b5 authored by Vivien Didelot's avatar Vivien Didelot Committed by David S. Miller
Browse files

net: dsa: mv88e6xxx: factorize switch reset



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: default avatarVivien Didelot <vivien.didelot@savoirfairelinux.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2672f825
Loading
Loading
Loading
Loading
+0 −4
Original line number Diff line number Diff line
@@ -99,10 +99,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;
+0 −4
Original line number Diff line number Diff line
@@ -132,10 +132,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;
+0 −4
Original line number Diff line number Diff line
@@ -108,10 +108,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;
+0 −4
Original line number Diff line number Diff line
@@ -125,10 +125,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;
+71 −66
Original line number Diff line number Diff line
@@ -2559,6 +2559,68 @@ static int _mv88e6xxx_phy_page_read(struct mv88e6xxx_priv_state *ps,
	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;
@@ -2860,6 +2922,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);
@@ -2870,7 +2934,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)
@@ -3046,71 +3116,6 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds)
	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);
Loading