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

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.pdfSigned-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.deSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 82e94d41
...@@ -16,6 +16,7 @@ enum ksz_regs { ...@@ -16,6 +16,7 @@ enum ksz_regs {
REG_IND_DATA_HI, REG_IND_DATA_HI,
REG_IND_DATA_LO, REG_IND_DATA_LO,
REG_IND_MIB_CHECK, REG_IND_MIB_CHECK,
REG_IND_BYTE,
P_FORCE_CTRL, P_FORCE_CTRL,
P_LINK_STATUS, P_LINK_STATUS,
P_LOCAL_CTRL, P_LOCAL_CTRL,
......
...@@ -33,6 +33,7 @@ static const u8 ksz8795_regs[] = { ...@@ -33,6 +33,7 @@ static const u8 ksz8795_regs[] = {
[REG_IND_DATA_HI] = 0x71, [REG_IND_DATA_HI] = 0x71,
[REG_IND_DATA_LO] = 0x75, [REG_IND_DATA_LO] = 0x75,
[REG_IND_MIB_CHECK] = 0x74, [REG_IND_MIB_CHECK] = 0x74,
[REG_IND_BYTE] = 0xA0,
[P_FORCE_CTRL] = 0x0C, [P_FORCE_CTRL] = 0x0C,
[P_LINK_STATUS] = 0x0E, [P_LINK_STATUS] = 0x0E,
[P_LOCAL_CTRL] = 0x07, [P_LOCAL_CTRL] = 0x07,
...@@ -222,6 +223,25 @@ static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits, ...@@ -222,6 +223,25 @@ static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits,
bits, set ? bits : 0); 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) static int ksz8_reset_switch(struct ksz_device *dev)
{ {
if (ksz_is_ksz88x3(dev)) { if (ksz_is_ksz88x3(dev)) {
...@@ -1391,6 +1411,23 @@ static void ksz8_config_cpu_port(struct dsa_switch *ds) ...@@ -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) static int ksz8_setup(struct dsa_switch *ds)
{ {
struct ksz_device *dev = ds->priv; struct ksz_device *dev = ds->priv;
...@@ -1458,7 +1495,7 @@ static int ksz8_setup(struct dsa_switch *ds) ...@@ -1458,7 +1495,7 @@ static int ksz8_setup(struct dsa_switch *ds)
ds->configure_vlan_while_not_filtering = false; 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, static void ksz8_get_caps(struct dsa_switch *ds, int port,
...@@ -1575,6 +1612,7 @@ struct ksz_chip_data { ...@@ -1575,6 +1612,7 @@ struct ksz_chip_data {
int num_statics; int num_statics;
int cpu_ports; int cpu_ports;
int port_cnt; int port_cnt;
bool ksz87xx_eee_link_erratum;
}; };
static const struct ksz_chip_data ksz8_switch_chips[] = { static const struct ksz_chip_data ksz8_switch_chips[] = {
...@@ -1586,6 +1624,7 @@ 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, .num_statics = 8,
.cpu_ports = 0x10, /* can be configured as cpu port */ .cpu_ports = 0x10, /* can be configured as cpu port */
.port_cnt = 5, /* total cpu and user ports */ .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[] = { ...@@ -1609,6 +1648,7 @@ static const struct ksz_chip_data ksz8_switch_chips[] = {
.num_statics = 8, .num_statics = 8,
.cpu_ports = 0x10, /* can be configured as cpu port */ .cpu_ports = 0x10, /* can be configured as cpu port */
.port_cnt = 4, /* total cpu and user ports */ .port_cnt = 4, /* total cpu and user ports */
.ksz87xx_eee_link_erratum = true,
}, },
{ {
.chip_id = 0x8765, .chip_id = 0x8765,
...@@ -1618,6 +1658,7 @@ static const struct ksz_chip_data ksz8_switch_chips[] = { ...@@ -1618,6 +1658,7 @@ static const struct ksz_chip_data ksz8_switch_chips[] = {
.num_statics = 8, .num_statics = 8,
.cpu_ports = 0x10, /* can be configured as cpu port */ .cpu_ports = 0x10, /* can be configured as cpu port */
.port_cnt = 5, /* total cpu and user ports */ .port_cnt = 5, /* total cpu and user ports */
.ksz87xx_eee_link_erratum = true,
}, },
{ {
.chip_id = 0x8830, .chip_id = 0x8830,
...@@ -1652,6 +1693,8 @@ static int ksz8_switch_init(struct ksz_device *dev) ...@@ -1652,6 +1693,8 @@ static int ksz8_switch_init(struct ksz_device *dev)
dev->host_mask = chip->cpu_ports; dev->host_mask = chip->cpu_ports;
dev->port_mask = (BIT(dev->phy_port_cnt) - 1) | dev->port_mask = (BIT(dev->phy_port_cnt) - 1) |
chip->cpu_ports; chip->cpu_ports;
dev->ksz87xx_eee_link_erratum =
chip->ksz87xx_eee_link_erratum;
break; break;
} }
} }
......
...@@ -812,6 +812,10 @@ ...@@ -812,6 +812,10 @@
#define IND_ACC_TABLE(table) ((table) << 8) #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. */ /* Driver set switch broadcast storm protection at 10% rate. */
#define BROADCAST_STORM_PROT_RATE 10 #define BROADCAST_STORM_PROT_RATE 10
......
...@@ -77,6 +77,7 @@ struct ksz_device { ...@@ -77,6 +77,7 @@ struct ksz_device {
phy_interface_t compat_interface; phy_interface_t compat_interface;
u32 regs_size; u32 regs_size;
bool phy_errata_9477; bool phy_errata_9477;
bool ksz87xx_eee_link_erratum;
bool synclko_125; bool synclko_125;
bool synclko_disable; bool synclko_disable;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment