Commit 7b6e6235 authored by Oleksij Rempel's avatar Oleksij Rempel Committed by Jakub Kicinski
Browse files

net: dsa: microchip: ksz8795: handle eee specif erratum

According to erratum described in DS80000687C[1]: "Module 2: Link drops with
some EEE link partners.", we need to "Disable the EEE next page
exchange in EEE Global Register 2"

1 - https://ww1.microchip.com/downloads/en/DeviceDoc/KSZ87xx-Errata-DS80000687C.pdf



Signed-off-by: default avatarOleksij Rempel <o.rempel@pengutronix.de>
Reviewed-by: default avatarVladimir Oltean <olteanv@gmail.com>
Link: https://lore.kernel.org/r/20220316125529.1489045-1-o.rempel@pengutronix.de


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 82e94d41
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ enum ksz_regs {
	REG_IND_DATA_HI,
	REG_IND_DATA_LO,
	REG_IND_MIB_CHECK,
	REG_IND_BYTE,
	P_FORCE_CTRL,
	P_LINK_STATUS,
	P_LOCAL_CTRL,
+44 −1
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ static const u8 ksz8795_regs[] = {
	[REG_IND_DATA_HI]		= 0x71,
	[REG_IND_DATA_LO]		= 0x75,
	[REG_IND_MIB_CHECK]		= 0x74,
	[REG_IND_BYTE]			= 0xA0,
	[P_FORCE_CTRL]			= 0x0C,
	[P_LINK_STATUS]			= 0x0E,
	[P_LOCAL_CTRL]			= 0x07,
@@ -222,6 +223,25 @@ static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits,
			   bits, set ? bits : 0);
}

static int ksz8_ind_write8(struct ksz_device *dev, u8 table, u16 addr, u8 data)
{
	struct ksz8 *ksz8 = dev->priv;
	const u8 *regs = ksz8->regs;
	u16 ctrl_addr;
	int ret = 0;

	mutex_lock(&dev->alu_mutex);

	ctrl_addr = IND_ACC_TABLE(table) | addr;
	ret = ksz_write8(dev, regs[REG_IND_BYTE], data);
	if (!ret)
		ret = ksz_write16(dev, regs[REG_IND_CTRL_0], ctrl_addr);

	mutex_unlock(&dev->alu_mutex);

	return ret;
}

static int ksz8_reset_switch(struct ksz_device *dev)
{
	if (ksz_is_ksz88x3(dev)) {
@@ -1391,6 +1411,23 @@ static void ksz8_config_cpu_port(struct dsa_switch *ds)
	}
}

static int ksz8_handle_global_errata(struct dsa_switch *ds)
{
	struct ksz_device *dev = ds->priv;
	int ret = 0;

	/* KSZ87xx Errata DS80000687C.
	 * Module 2: Link drops with some EEE link partners.
	 *   An issue with the EEE next page exchange between the
	 *   KSZ879x/KSZ877x/KSZ876x and some EEE link partners may result in
	 *   the link dropping.
	 */
	if (dev->ksz87xx_eee_link_erratum)
		ret = ksz8_ind_write8(dev, TABLE_EEE, REG_IND_EEE_GLOB2_HI, 0);

	return ret;
}

static int ksz8_setup(struct dsa_switch *ds)
{
	struct ksz_device *dev = ds->priv;
@@ -1458,7 +1495,7 @@ static int ksz8_setup(struct dsa_switch *ds)

	ds->configure_vlan_while_not_filtering = false;

	return 0;
	return ksz8_handle_global_errata(ds);
}

static void ksz8_get_caps(struct dsa_switch *ds, int port,
@@ -1575,6 +1612,7 @@ struct ksz_chip_data {
	int num_statics;
	int cpu_ports;
	int port_cnt;
	bool ksz87xx_eee_link_erratum;
};

static const struct ksz_chip_data ksz8_switch_chips[] = {
@@ -1586,6 +1624,7 @@ static const struct ksz_chip_data ksz8_switch_chips[] = {
		.num_statics = 8,
		.cpu_ports = 0x10,	/* can be configured as cpu port */
		.port_cnt = 5,		/* total cpu and user ports */
		.ksz87xx_eee_link_erratum = true,
	},
	{
		/*
@@ -1609,6 +1648,7 @@ static const struct ksz_chip_data ksz8_switch_chips[] = {
		.num_statics = 8,
		.cpu_ports = 0x10,	/* can be configured as cpu port */
		.port_cnt = 4,		/* total cpu and user ports */
		.ksz87xx_eee_link_erratum = true,
	},
	{
		.chip_id = 0x8765,
@@ -1618,6 +1658,7 @@ static const struct ksz_chip_data ksz8_switch_chips[] = {
		.num_statics = 8,
		.cpu_ports = 0x10,	/* can be configured as cpu port */
		.port_cnt = 5,		/* total cpu and user ports */
		.ksz87xx_eee_link_erratum = true,
	},
	{
		.chip_id = 0x8830,
@@ -1652,6 +1693,8 @@ static int ksz8_switch_init(struct ksz_device *dev)
			dev->host_mask = chip->cpu_ports;
			dev->port_mask = (BIT(dev->phy_port_cnt) - 1) |
					 chip->cpu_ports;
			dev->ksz87xx_eee_link_erratum =
				chip->ksz87xx_eee_link_erratum;
			break;
		}
	}
+4 −0
Original line number Diff line number Diff line
@@ -812,6 +812,10 @@

#define IND_ACC_TABLE(table)		((table) << 8)

/* */
#define REG_IND_EEE_GLOB2_LO		0x34
#define REG_IND_EEE_GLOB2_HI		0x35

/* Driver set switch broadcast storm protection at 10% rate. */
#define BROADCAST_STORM_PROT_RATE	10

+1 −0
Original line number Diff line number Diff line
@@ -77,6 +77,7 @@ struct ksz_device {
	phy_interface_t compat_interface;
	u32 regs_size;
	bool phy_errata_9477;
	bool ksz87xx_eee_link_erratum;
	bool synclko_125;
	bool synclko_disable;