Commit a8583901 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'net-dsa-mv88e6xxx-prepare-Wait-Bit-operation'



Vivien Didelot says:

====================
net: dsa: mv88e6xxx: prepare Wait Bit operation

The Remote Management Interface has its own implementation of a Wait
Bit operation, which requires a bit number and a value to wait for.

In order to prepare the introduction of this implementation, rework the
code waiting for bits and masks in mv88e6xxx to match this signature.

This has the benefit to unify the implementation of wait routines while
removing obsolete wait and update functions and also reducing the code.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents eb2e7f09 eede2361
Loading
Loading
Loading
Loading
+35 −41
Original line number Original line Diff line number Diff line
@@ -10,6 +10,7 @@
 *	Vivien Didelot <vivien.didelot@savoirfairelinux.com>
 *	Vivien Didelot <vivien.didelot@savoirfairelinux.com>
 */
 */


#include <linux/bitfield.h>
#include <linux/delay.h>
#include <linux/delay.h>
#include <linux/etherdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/ethtool.h>
@@ -80,6 +81,36 @@ int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val)
	return 0;
	return 0;
}
}


int mv88e6xxx_wait_mask(struct mv88e6xxx_chip *chip, int addr, int reg,
			u16 mask, u16 val)
{
	u16 data;
	int err;
	int i;

	/* There's no bus specific operation to wait for a mask */
	for (i = 0; i < 16; i++) {
		err = mv88e6xxx_read(chip, addr, reg, &data);
		if (err)
			return err;

		if ((data & mask) == val)
			return 0;

		usleep_range(1000, 2000);
	}

	dev_err(chip->dev, "Timeout while waiting for switch\n");
	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 mii_bus *mv88e6xxx_default_mdio_bus(struct mv88e6xxx_chip *chip)
{
{
	struct mv88e6xxx_mdio_bus *mdio_bus;
	struct mv88e6xxx_mdio_bus *mdio_bus;
@@ -363,45 +394,6 @@ static void mv88e6xxx_irq_poll_free(struct mv88e6xxx_chip *chip)
	mv88e6xxx_reg_unlock(chip);
	mv88e6xxx_reg_unlock(chip);
}
}


int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask)
{
	int i;

	for (i = 0; i < 16; i++) {
		u16 val;
		int err;

		err = mv88e6xxx_read(chip, addr, reg, &val);
		if (err)
			return err;

		if (!(val & mask))
			return 0;

		usleep_range(1000, 2000);
	}

	dev_err(chip->dev, "Timeout while waiting for switch\n");
	return -ETIMEDOUT;
}

/* Indirect write to single pointer-data register with an Update bit */
int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg, u16 update)
{
	u16 val;
	int err;

	/* Wait until the previous operation is completed */
	err = mv88e6xxx_wait(chip, addr, reg, BIT(15));
	if (err)
		return err;

	/* Set the Update bit to trigger a write operation */
	val = BIT(15) | update;

	return mv88e6xxx_write(chip, addr, reg, val);
}

int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, int link,
int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, int link,
			     int speed, int duplex, int pause,
			     int speed, int duplex, int pause,
			     phy_interface_t mode)
			     phy_interface_t mode)
@@ -2354,8 +2346,10 @@ static int mv88e6390_hidden_write(struct mv88e6xxx_chip *chip, int port,


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

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




+4 −3
Original line number Original line Diff line number Diff line
@@ -588,9 +588,10 @@ static inline bool mv88e6xxx_is_invalid_port(struct mv88e6xxx_chip *chip, int po


int mv88e6xxx_read(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val);
int mv88e6xxx_read(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val);
int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val);
int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val);
int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg,
int mv88e6xxx_wait_mask(struct mv88e6xxx_chip *chip, int addr, int reg,
		     u16 update);
			u16 mask, u16 val);
int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask);
int mv88e6xxx_wait_bit(struct mv88e6xxx_chip *chip, int addr, int reg,
		       int bit, int val);
int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, int link,
int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, int link,
			     int speed, int duplex, int pause,
			     int speed, int duplex, int pause,
			     phy_interface_t mode);
			     phy_interface_t mode);
+24 −71
Original line number Original line Diff line number Diff line
@@ -27,100 +27,52 @@ int mv88e6xxx_g1_write(struct mv88e6xxx_chip *chip, int reg, u16 val)
	return mv88e6xxx_write(chip, addr, reg, val);
	return mv88e6xxx_write(chip, addr, reg, 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)
{
{
	return mv88e6xxx_wait(chip, chip->info->global1_addr, reg, mask);
	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)
{
	return mv88e6xxx_wait_mask(chip, chip->info->global1_addr, reg,
				   mask, val);
}
}


/* Offset 0x00: Switch Global Status Register */
/* Offset 0x00: Switch Global Status Register */


static int mv88e6185_g1_wait_ppu_disabled(struct mv88e6xxx_chip *chip)
static int mv88e6185_g1_wait_ppu_disabled(struct mv88e6xxx_chip *chip)
{
{
	u16 state;
	return mv88e6xxx_g1_wait_mask(chip, MV88E6XXX_G1_STS,
	int i, err;
				      MV88E6185_G1_STS_PPU_STATE_MASK,

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

		/* Check the value of the PPUState bits 15:14 */
		state &= MV88E6185_G1_STS_PPU_STATE_MASK;
		if (state != MV88E6185_G1_STS_PPU_STATE_POLLING)
			return 0;

		usleep_range(1000, 2000);
	}

	return -ETIMEDOUT;
}
}


static int mv88e6185_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip)
static int mv88e6185_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip)
{
{
	u16 state;
	return mv88e6xxx_g1_wait_mask(chip, MV88E6XXX_G1_STS,
	int i, err;
				      MV88E6185_G1_STS_PPU_STATE_MASK,

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

		/* Check the value of the PPUState bits 15:14 */
		state &= MV88E6185_G1_STS_PPU_STATE_MASK;
		if (state == MV88E6185_G1_STS_PPU_STATE_POLLING)
			return 0;

		usleep_range(1000, 2000);
	}

	return -ETIMEDOUT;
}
}


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


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

		/* 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;
}
}


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


	/* Wait up to 1 second for the switch to be ready. The InitReady bit 11
	/* 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.)
	 * is set to a one when all units inside the device (ATU, VTU, etc.)
	 * have finished their initialization and are ready to accept frames.
	 * have finished their initialization and are ready to accept frames.
	 */
	 */
	while (time_before(jiffies, timeout)) {
	return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_STS, bit, 1);
		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;
}
}


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


static int mv88e6xxx_g1_stats_wait(struct mv88e6xxx_chip *chip)
static int mv88e6xxx_g1_stats_wait(struct mv88e6xxx_chip *chip)
{
{
	return mv88e6xxx_g1_wait(chip, MV88E6XXX_G1_STATS_OP,
	int bit = __bf_shf(MV88E6XXX_G1_STATS_OP_BUSY);
				 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)
int mv88e6095_g1_stats_set_histogram(struct mv88e6xxx_chip *chip)
+4 −1
Original line number Original line Diff line number Diff line
@@ -249,7 +249,10 @@


int mv88e6xxx_g1_read(struct mv88e6xxx_chip *chip, int reg, u16 *val);
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_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);


int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr);
int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr);


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

#include <linux/bitfield.h>
#include <linux/interrupt.h>
#include <linux/interrupt.h>
#include <linux/irqdomain.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)
static int mv88e6xxx_g1_atu_op_wait(struct mv88e6xxx_chip *chip)
{
{
	return mv88e6xxx_g1_wait(chip, MV88E6XXX_G1_ATU_OP,
	int bit = __bf_shf(MV88E6XXX_G1_ATU_OP_BUSY);
				 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)
static int mv88e6xxx_g1_atu_op(struct mv88e6xxx_chip *chip, u16 fid, u16 op)
Loading