Commit 19fb7f69 authored by Vivien Didelot's avatar Vivien Didelot Committed by David S. Miller
Browse files

net: dsa: mv88e6xxx: introduce wait bit routine



Many portions of the driver need to wait until a given bit is set
or cleared. Some busses even have a specific implementation for this
operation. In preparation for such variant, implement a generic Wait
Bit routine that can be used by the driver core functions.

This allows us to get rid of the custom implementations we may find
in the driver. Note that for the EEPROM bits, BUSY and RUNNING bits
are independent, thus it is more efficient to wait independently for
each bit instead of waiting for their mask.

Signed-off-by: default avatarVivien Didelot <vivien.didelot@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 683f2244
Loading
Loading
Loading
Loading
+12 −2
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@
 *	Vivien Didelot <vivien.didelot@savoirfairelinux.com>
 */

#include <linux/bitfield.h>
#include <linux/delay.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
@@ -103,6 +104,13 @@ int mv88e6xxx_wait_mask(struct mv88e6xxx_chip *chip, int addr, int reg,
	return -ETIMEDOUT;
}

int mv88e6xxx_wait_bit(struct mv88e6xxx_chip *chip, int addr, int reg,
		       int bit, int val)
{
	return mv88e6xxx_wait_mask(chip, addr, reg, BIT(bit),
				   val ? BIT(bit) : 0x0000);
}

struct mii_bus *mv88e6xxx_default_mdio_bus(struct mv88e6xxx_chip *chip)
{
	struct mv88e6xxx_mdio_bus *mdio_bus;
@@ -2360,8 +2368,10 @@ static int mv88e6390_hidden_write(struct mv88e6xxx_chip *chip, int port,

static int mv88e6390_hidden_wait(struct mv88e6xxx_chip *chip)
{
	return mv88e6xxx_wait(chip, PORT_RESERVED_1A_CTRL_PORT,
			      PORT_RESERVED_1A, PORT_RESERVED_1A_BUSY);
	int bit = __bf_shf(PORT_RESERVED_1A_BUSY);

	return mv88e6xxx_wait_bit(chip, PORT_RESERVED_1A_CTRL_PORT,
				  PORT_RESERVED_1A, bit, 0);
}


+2 −0
Original line number Diff line number Diff line
@@ -592,6 +592,8 @@ int mv88e6xxx_wait_mask(struct mv88e6xxx_chip *chip, int addr, int reg,
			u16 mask, u16 val);
int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg,
		     u16 update);
int mv88e6xxx_wait_bit(struct mv88e6xxx_chip *chip, int addr, int reg,
		       int bit, int val);
int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask);
int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, int link,
			     int speed, int duplex, int pause,
+14 −35
Original line number Diff line number Diff line
@@ -32,6 +32,13 @@ int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask)
	return mv88e6xxx_wait(chip, chip->info->global1_addr, reg, mask);
}

int mv88e6xxx_g1_wait_bit(struct mv88e6xxx_chip *chip, int reg, int
			  bit, int val)
{
	return mv88e6xxx_wait_bit(chip, chip->info->global1_addr, reg,
				  bit, val);
}

int mv88e6xxx_g1_wait_mask(struct mv88e6xxx_chip *chip, int reg,
			   u16 mask, u16 val)
{
@@ -57,49 +64,20 @@ static int mv88e6185_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip)

static int mv88e6352_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip)
{
	u16 state;
	int i, err;

	for (i = 0; i < 16; ++i) {
		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &state);
		if (err)
			return err;
	int bit = __bf_shf(MV88E6352_G1_STS_PPU_STATE);

		/* Check the value of the PPUState (or InitState) bit 15 */
		if (state & MV88E6352_G1_STS_PPU_STATE)
			return 0;

		usleep_range(1000, 2000);
	}

	return -ETIMEDOUT;
	return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_STS, bit, 1);
}

static int mv88e6xxx_g1_wait_init_ready(struct mv88e6xxx_chip *chip)
{
	const unsigned long timeout = jiffies + 1 * HZ;
	u16 val;
	int err;
	int bit = __bf_shf(MV88E6XXX_G1_STS_INIT_READY);

	/* Wait up to 1 second for the switch to be ready. The InitReady bit 11
	 * is set to a one when all units inside the device (ATU, VTU, etc.)
	 * have finished their initialization and are ready to accept frames.
	 */
	while (time_before(jiffies, timeout)) {
		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &val);
		if (err)
			return err;

		if (val & MV88E6XXX_G1_STS_INIT_READY)
			break;

		usleep_range(1000, 2000);
	}

	if (time_after(jiffies, timeout))
		return -ETIMEDOUT;

	return 0;
	return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_STS, bit, 1);
}

/* Offset 0x01: Switch MAC Address Register Bytes 0 & 1
@@ -455,8 +433,9 @@ int mv88e6xxx_g1_set_device_number(struct mv88e6xxx_chip *chip, int index)

static int mv88e6xxx_g1_stats_wait(struct mv88e6xxx_chip *chip)
{
	return mv88e6xxx_g1_wait(chip, MV88E6XXX_G1_STATS_OP,
				 MV88E6XXX_G1_STATS_OP_BUSY);
	int bit = __bf_shf(MV88E6XXX_G1_STATS_OP_BUSY);

	return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_STATS_OP, bit, 0);
}

int mv88e6095_g1_stats_set_histogram(struct mv88e6xxx_chip *chip)
+2 −0
Original line number Diff line number Diff line
@@ -250,6 +250,8 @@
int mv88e6xxx_g1_read(struct mv88e6xxx_chip *chip, int reg, u16 *val);
int mv88e6xxx_g1_write(struct mv88e6xxx_chip *chip, int reg, u16 val);
int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask);
int mv88e6xxx_g1_wait_bit(struct mv88e6xxx_chip *chip, int reg, int
			  bit, int val);
int mv88e6xxx_g1_wait_mask(struct mv88e6xxx_chip *chip, int reg,
			   u16 mask, u16 val);

+5 −2
Original line number Diff line number Diff line
@@ -5,6 +5,8 @@
 * Copyright (c) 2008 Marvell Semiconductor
 * Copyright (c) 2017 Savoir-faire Linux, Inc.
 */

#include <linux/bitfield.h>
#include <linux/interrupt.h>
#include <linux/irqdomain.h>

@@ -75,8 +77,9 @@ int mv88e6xxx_g1_atu_set_age_time(struct mv88e6xxx_chip *chip,

static int mv88e6xxx_g1_atu_op_wait(struct mv88e6xxx_chip *chip)
{
	return mv88e6xxx_g1_wait(chip, MV88E6XXX_G1_ATU_OP,
				 MV88E6XXX_G1_ATU_OP_BUSY);
	int bit = __bf_shf(MV88E6XXX_G1_ATU_OP_BUSY);

	return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_ATU_OP, bit, 0);
}

static int mv88e6xxx_g1_atu_op(struct mv88e6xxx_chip *chip, u16 fid, u16 op)
Loading