Commit 2d919d39 authored by David S. Miller's avatar David S. Miller

Merge branch 'net-dsa-microchip-error-hndling-reg-access-validation'

Oleksij Rempel says:

====================
net: dsa: microchip: add error handling and register access validation

changes v4:
- add Reviewed-by: Vladimir Oltean <olteanv@gmail.com> to all patches
- fix checkpatch warnings.

changes v3:
- fix build error in the middle of the patch stack.

changes v2:
- add regmap_ranges for KSZ9477
- drop output clock devicetree in driver validation patches. DTs need
  some more refactoring and can be done in a separate patch set.
- remove some unused variables.

This patch series adds error handling for the PHY read/write path and optional
register access validation.
After adding regmap_ranges for KSZ8563 some bugs was detected, so
critical bug fixes are sorted before ragmap_range patch.

Potentially this bug fixes can be ported to stable kernels, but need to be
reworked.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 21cb860c 32cbac21
...@@ -17,8 +17,8 @@ u32 ksz8_get_port_addr(int port, int offset); ...@@ -17,8 +17,8 @@ u32 ksz8_get_port_addr(int port, int offset);
void ksz8_cfg_port_member(struct ksz_device *dev, int port, u8 member); void ksz8_cfg_port_member(struct ksz_device *dev, int port, u8 member);
void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port); void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port);
void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port); void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port);
void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val); int ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val);
void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val); int ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val);
int ksz8_r_dyn_mac_table(struct ksz_device *dev, u16 addr, u8 *mac_addr, int ksz8_r_dyn_mac_table(struct ksz_device *dev, u16 addr, u8 *mac_addr,
u8 *fid, u8 *src_port, u8 *timestamp, u16 *entries); u8 *fid, u8 *src_port, u8 *timestamp, u16 *entries);
int ksz8_r_sta_mac_table(struct ksz_device *dev, u16 addr, int ksz8_r_sta_mac_table(struct ksz_device *dev, u16 addr,
......
...@@ -552,7 +552,7 @@ static void ksz8_w_vlan_table(struct ksz_device *dev, u16 vid, u16 vlan) ...@@ -552,7 +552,7 @@ static void ksz8_w_vlan_table(struct ksz_device *dev, u16 vid, u16 vlan)
ksz8_w_table(dev, TABLE_VLAN, addr, buf); ksz8_w_table(dev, TABLE_VLAN, addr, buf);
} }
void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val) int ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
{ {
u8 restart, speed, ctrl, link; u8 restart, speed, ctrl, link;
int processed = true; int processed = true;
...@@ -560,14 +560,24 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val) ...@@ -560,14 +560,24 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
u8 val1, val2; u8 val1, val2;
u16 data = 0; u16 data = 0;
u8 p = phy; u8 p = phy;
int ret;
regs = dev->info->regs; regs = dev->info->regs;
switch (reg) { switch (reg) {
case MII_BMCR: case MII_BMCR:
ksz_pread8(dev, p, regs[P_NEG_RESTART_CTRL], &restart); ret = ksz_pread8(dev, p, regs[P_NEG_RESTART_CTRL], &restart);
ksz_pread8(dev, p, regs[P_SPEED_STATUS], &speed); if (ret)
ksz_pread8(dev, p, regs[P_FORCE_CTRL], &ctrl); return ret;
ret = ksz_pread8(dev, p, regs[P_SPEED_STATUS], &speed);
if (ret)
return ret;
ret = ksz_pread8(dev, p, regs[P_FORCE_CTRL], &ctrl);
if (ret)
return ret;
if (restart & PORT_PHY_LOOPBACK) if (restart & PORT_PHY_LOOPBACK)
data |= BMCR_LOOPBACK; data |= BMCR_LOOPBACK;
if (ctrl & PORT_FORCE_100_MBIT) if (ctrl & PORT_FORCE_100_MBIT)
...@@ -597,7 +607,10 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val) ...@@ -597,7 +607,10 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
data |= KSZ886X_BMCR_DISABLE_LED; data |= KSZ886X_BMCR_DISABLE_LED;
break; break;
case MII_BMSR: case MII_BMSR:
ksz_pread8(dev, p, regs[P_LINK_STATUS], &link); ret = ksz_pread8(dev, p, regs[P_LINK_STATUS], &link);
if (ret)
return ret;
data = BMSR_100FULL | data = BMSR_100FULL |
BMSR_100HALF | BMSR_100HALF |
BMSR_10FULL | BMSR_10FULL |
...@@ -618,7 +631,10 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val) ...@@ -618,7 +631,10 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
data = KSZ8795_ID_LO; data = KSZ8795_ID_LO;
break; break;
case MII_ADVERTISE: case MII_ADVERTISE:
ksz_pread8(dev, p, regs[P_LOCAL_CTRL], &ctrl); ret = ksz_pread8(dev, p, regs[P_LOCAL_CTRL], &ctrl);
if (ret)
return ret;
data = ADVERTISE_CSMA; data = ADVERTISE_CSMA;
if (ctrl & PORT_AUTO_NEG_SYM_PAUSE) if (ctrl & PORT_AUTO_NEG_SYM_PAUSE)
data |= ADVERTISE_PAUSE_CAP; data |= ADVERTISE_PAUSE_CAP;
...@@ -632,7 +648,10 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val) ...@@ -632,7 +648,10 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
data |= ADVERTISE_10HALF; data |= ADVERTISE_10HALF;
break; break;
case MII_LPA: case MII_LPA:
ksz_pread8(dev, p, regs[P_REMOTE_STATUS], &link); ret = ksz_pread8(dev, p, regs[P_REMOTE_STATUS], &link);
if (ret)
return ret;
data = LPA_SLCT; data = LPA_SLCT;
if (link & PORT_REMOTE_SYM_PAUSE) if (link & PORT_REMOTE_SYM_PAUSE)
data |= LPA_PAUSE_CAP; data |= LPA_PAUSE_CAP;
...@@ -648,8 +667,14 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val) ...@@ -648,8 +667,14 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
data |= LPA_LPACK; data |= LPA_LPACK;
break; break;
case PHY_REG_LINK_MD: case PHY_REG_LINK_MD:
ksz_pread8(dev, p, REG_PORT_LINK_MD_CTRL, &val1); ret = ksz_pread8(dev, p, REG_PORT_LINK_MD_CTRL, &val1);
ksz_pread8(dev, p, REG_PORT_LINK_MD_RESULT, &val2); if (ret)
return ret;
ret = ksz_pread8(dev, p, REG_PORT_LINK_MD_RESULT, &val2);
if (ret)
return ret;
if (val1 & PORT_START_CABLE_DIAG) if (val1 & PORT_START_CABLE_DIAG)
data |= PHY_START_CABLE_DIAG; data |= PHY_START_CABLE_DIAG;
...@@ -664,7 +689,10 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val) ...@@ -664,7 +689,10 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
FIELD_GET(PORT_CABLE_FAULT_COUNTER_L, val2)); FIELD_GET(PORT_CABLE_FAULT_COUNTER_L, val2));
break; break;
case PHY_REG_PHY_CTRL: case PHY_REG_PHY_CTRL:
ksz_pread8(dev, p, regs[P_LINK_STATUS], &link); ret = ksz_pread8(dev, p, regs[P_LINK_STATUS], &link);
if (ret)
return ret;
if (link & PORT_MDIX_STATUS) if (link & PORT_MDIX_STATUS)
data |= KSZ886X_CTRL_MDIX_STAT; data |= KSZ886X_CTRL_MDIX_STAT;
break; break;
...@@ -674,13 +702,16 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val) ...@@ -674,13 +702,16 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
} }
if (processed) if (processed)
*val = data; *val = data;
return 0;
} }
void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val) int ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
{ {
u8 restart, speed, ctrl, data; u8 restart, speed, ctrl, data;
const u16 *regs; const u16 *regs;
u8 p = phy; u8 p = phy;
int ret;
regs = dev->info->regs; regs = dev->info->regs;
...@@ -690,15 +721,26 @@ void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val) ...@@ -690,15 +721,26 @@ void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
/* Do not support PHY reset function. */ /* Do not support PHY reset function. */
if (val & BMCR_RESET) if (val & BMCR_RESET)
break; break;
ksz_pread8(dev, p, regs[P_SPEED_STATUS], &speed); ret = ksz_pread8(dev, p, regs[P_SPEED_STATUS], &speed);
if (ret)
return ret;
data = speed; data = speed;
if (val & KSZ886X_BMCR_HP_MDIX) if (val & KSZ886X_BMCR_HP_MDIX)
data |= PORT_HP_MDIX; data |= PORT_HP_MDIX;
else else
data &= ~PORT_HP_MDIX; data &= ~PORT_HP_MDIX;
if (data != speed)
ksz_pwrite8(dev, p, regs[P_SPEED_STATUS], data); if (data != speed) {
ksz_pread8(dev, p, regs[P_FORCE_CTRL], &ctrl); ret = ksz_pwrite8(dev, p, regs[P_SPEED_STATUS], data);
if (ret)
return ret;
}
ret = ksz_pread8(dev, p, regs[P_FORCE_CTRL], &ctrl);
if (ret)
return ret;
data = ctrl; data = ctrl;
if (ksz_is_ksz88x3(dev)) { if (ksz_is_ksz88x3(dev)) {
if ((val & BMCR_ANENABLE)) if ((val & BMCR_ANENABLE))
...@@ -724,9 +766,17 @@ void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val) ...@@ -724,9 +766,17 @@ void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
data |= PORT_FORCE_FULL_DUPLEX; data |= PORT_FORCE_FULL_DUPLEX;
else else
data &= ~PORT_FORCE_FULL_DUPLEX; data &= ~PORT_FORCE_FULL_DUPLEX;
if (data != ctrl)
ksz_pwrite8(dev, p, regs[P_FORCE_CTRL], data); if (data != ctrl) {
ksz_pread8(dev, p, regs[P_NEG_RESTART_CTRL], &restart); ret = ksz_pwrite8(dev, p, regs[P_FORCE_CTRL], data);
if (ret)
return ret;
}
ret = ksz_pread8(dev, p, regs[P_NEG_RESTART_CTRL], &restart);
if (ret)
return ret;
data = restart; data = restart;
if (val & KSZ886X_BMCR_DISABLE_LED) if (val & KSZ886X_BMCR_DISABLE_LED)
data |= PORT_LED_OFF; data |= PORT_LED_OFF;
...@@ -756,11 +806,19 @@ void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val) ...@@ -756,11 +806,19 @@ void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
data |= PORT_PHY_LOOPBACK; data |= PORT_PHY_LOOPBACK;
else else
data &= ~PORT_PHY_LOOPBACK; data &= ~PORT_PHY_LOOPBACK;
if (data != restart)
ksz_pwrite8(dev, p, regs[P_NEG_RESTART_CTRL], data); if (data != restart) {
ret = ksz_pwrite8(dev, p, regs[P_NEG_RESTART_CTRL],
data);
if (ret)
return ret;
}
break; break;
case MII_ADVERTISE: case MII_ADVERTISE:
ksz_pread8(dev, p, regs[P_LOCAL_CTRL], &ctrl); ret = ksz_pread8(dev, p, regs[P_LOCAL_CTRL], &ctrl);
if (ret)
return ret;
data = ctrl; data = ctrl;
data &= ~(PORT_AUTO_NEG_SYM_PAUSE | data &= ~(PORT_AUTO_NEG_SYM_PAUSE |
PORT_AUTO_NEG_100BTX_FD | PORT_AUTO_NEG_100BTX_FD |
...@@ -777,8 +835,12 @@ void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val) ...@@ -777,8 +835,12 @@ void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
data |= PORT_AUTO_NEG_10BT_FD; data |= PORT_AUTO_NEG_10BT_FD;
if (val & ADVERTISE_10HALF) if (val & ADVERTISE_10HALF)
data |= PORT_AUTO_NEG_10BT; data |= PORT_AUTO_NEG_10BT;
if (data != ctrl)
ksz_pwrite8(dev, p, regs[P_LOCAL_CTRL], data); if (data != ctrl) {
ret = ksz_pwrite8(dev, p, regs[P_LOCAL_CTRL], data);
if (ret)
return ret;
}
break; break;
case PHY_REG_LINK_MD: case PHY_REG_LINK_MD:
if (val & PHY_START_CABLE_DIAG) if (val & PHY_START_CABLE_DIAG)
...@@ -787,6 +849,8 @@ void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val) ...@@ -787,6 +849,8 @@ void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
default: default:
break; break;
} }
return 0;
} }
void ksz8_cfg_port_member(struct ksz_device *dev, int port, u8 member) void ksz8_cfg_port_member(struct ksz_device *dev, int port, u8 member)
...@@ -1187,7 +1251,6 @@ void ksz8_config_cpu_port(struct dsa_switch *ds) ...@@ -1187,7 +1251,6 @@ void ksz8_config_cpu_port(struct dsa_switch *ds)
if (i == dev->phy_port_cnt) if (i == dev->phy_port_cnt)
break; break;
p->on = 1; p->on = 1;
p->phy = 1;
} }
for (i = 0; i < dev->phy_port_cnt; i++) { for (i = 0; i < dev->phy_port_cnt; i++) {
p = &dev->ports[i]; p = &dev->ports[i];
......
...@@ -193,6 +193,11 @@ int ksz9477_reset_switch(struct ksz_device *dev) ...@@ -193,6 +193,11 @@ int ksz9477_reset_switch(struct ksz_device *dev)
ksz_write32(dev, REG_SW_PORT_INT_MASK__4, 0x7F); ksz_write32(dev, REG_SW_PORT_INT_MASK__4, 0x7F);
ksz_read32(dev, REG_SW_PORT_INT_STATUS__4, &data32); ksz_read32(dev, REG_SW_PORT_INT_STATUS__4, &data32);
/* KSZ9893 compatible chips do not support refclk configuration */
if (dev->chip_id == KSZ9893_CHIP_ID ||
dev->chip_id == KSZ8563_CHIP_ID)
return 0;
data8 = SW_ENABLE_REFCLKO; data8 = SW_ENABLE_REFCLKO;
if (dev->synclko_disable) if (dev->synclko_disable)
data8 = 0; data8 = 0;
...@@ -264,9 +269,20 @@ void ksz9477_port_init_cnt(struct ksz_device *dev, int port) ...@@ -264,9 +269,20 @@ void ksz9477_port_init_cnt(struct ksz_device *dev, int port)
mutex_unlock(&mib->cnt_mutex); mutex_unlock(&mib->cnt_mutex);
} }
void ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data) static void ksz9477_r_phy_quirks(struct ksz_device *dev, u16 addr, u16 reg,
u16 *data)
{
/* KSZ8563R do not have extended registers but BMSR_ESTATEN and
* BMSR_ERCAP bits are set.
*/
if (dev->chip_id == KSZ8563_CHIP_ID && reg == MII_BMSR)
*data &= ~(BMSR_ESTATEN | BMSR_ERCAP);
}
int ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data)
{ {
u16 val = 0xffff; u16 val = 0xffff;
int ret;
/* No real PHY after this. Simulate the PHY. /* No real PHY after this. Simulate the PHY.
* A fixed PHY can be setup in the device tree, but this function is * A fixed PHY can be setup in the device tree, but this function is
...@@ -274,7 +290,7 @@ void ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data) ...@@ -274,7 +290,7 @@ void ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data)
* For RGMII PHY there is no way to access it so the fixed PHY should * For RGMII PHY there is no way to access it so the fixed PHY should
* be used. For SGMII PHY the supporting code will be added later. * be used. For SGMII PHY the supporting code will be added later.
*/ */
if (addr >= dev->phy_port_cnt) { if (!dev->info->internal_phy[addr]) {
struct ksz_port *p = &dev->ports[addr]; struct ksz_port *p = &dev->ports[addr];
switch (reg) { switch (reg) {
...@@ -307,23 +323,25 @@ void ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data) ...@@ -307,23 +323,25 @@ void ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data)
break; break;
} }
} else { } else {
ksz_pread16(dev, addr, 0x100 + (reg << 1), &val); ret = ksz_pread16(dev, addr, 0x100 + (reg << 1), &val);
if (ret)
return ret;
ksz9477_r_phy_quirks(dev, addr, reg, &val);
} }
*data = val; *data = val;
return 0;
} }
void ksz9477_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val) int ksz9477_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val)
{ {
/* No real PHY after this. */ /* No real PHY after this. */
if (addr >= dev->phy_port_cnt) if (!dev->info->internal_phy[addr])
return; return 0;
/* No gigabit support. Do not write to this register. */
if (!(dev->features & GBIT_SUPPORT) && reg == MII_CTRL1000)
return;
ksz_pwrite16(dev, addr, 0x100 + (reg << 1), val); return ksz_pwrite16(dev, addr, 0x100 + (reg << 1), val);
} }
void ksz9477_cfg_port_member(struct ksz_device *dev, int port, u8 member) void ksz9477_cfg_port_member(struct ksz_device *dev, int port, u8 member)
...@@ -869,7 +887,7 @@ static phy_interface_t ksz9477_get_interface(struct ksz_device *dev, int port) ...@@ -869,7 +887,7 @@ static phy_interface_t ksz9477_get_interface(struct ksz_device *dev, int port)
phy_interface_t interface; phy_interface_t interface;
bool gbit; bool gbit;
if (port < dev->phy_port_cnt) if (dev->info->internal_phy[port])
return PHY_INTERFACE_MODE_NA; return PHY_INTERFACE_MODE_NA;
gbit = ksz_get_gbit(dev, port); gbit = ksz_get_gbit(dev, port);
...@@ -914,7 +932,7 @@ static void ksz9477_phy_errata_setup(struct ksz_device *dev, int port) ...@@ -914,7 +932,7 @@ static void ksz9477_phy_errata_setup(struct ksz_device *dev, int port)
/* Energy Efficient Ethernet (EEE) feature select must /* Energy Efficient Ethernet (EEE) feature select must
* be manually disabled (except on KSZ8565 which is 100Mbit) * be manually disabled (except on KSZ8565 which is 100Mbit)
*/ */
if (dev->features & GBIT_SUPPORT) if (dev->info->gbit_capable[port])
ksz9477_port_mmd_write(dev, port, 0x07, 0x3c, 0x0000); ksz9477_port_mmd_write(dev, port, 0x07, 0x3c, 0x0000);
/* Register settings are required to meet data sheet /* Register settings are required to meet data sheet
...@@ -941,7 +959,7 @@ void ksz9477_get_caps(struct ksz_device *dev, int port, ...@@ -941,7 +959,7 @@ void ksz9477_get_caps(struct ksz_device *dev, int port,
config->mac_capabilities = MAC_10 | MAC_100 | MAC_ASYM_PAUSE | config->mac_capabilities = MAC_10 | MAC_100 | MAC_ASYM_PAUSE |
MAC_SYM_PAUSE; MAC_SYM_PAUSE;
if (dev->features & GBIT_SUPPORT) if (dev->info->gbit_capable[port])
config->mac_capabilities |= MAC_1000FD; config->mac_capabilities |= MAC_1000FD;
} }
...@@ -976,7 +994,7 @@ void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port) ...@@ -976,7 +994,7 @@ void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
/* enable 802.1p priority */ /* enable 802.1p priority */
ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_802_1P_PRIO_ENABLE, true); ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_802_1P_PRIO_ENABLE, true);
if (port < dev->phy_port_cnt) { if (dev->info->internal_phy[port]) {
/* do not force flow control */ /* do not force flow control */
ksz_port_cfg(dev, port, REG_PORT_CTRL_0, ksz_port_cfg(dev, port, REG_PORT_CTRL_0,
PORT_FORCE_TX_FLOW_CTRL | PORT_FORCE_RX_FLOW_CTRL, PORT_FORCE_TX_FLOW_CTRL | PORT_FORCE_RX_FLOW_CTRL,
...@@ -999,7 +1017,7 @@ void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port) ...@@ -999,7 +1017,7 @@ void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
ksz9477_cfg_port_member(dev, port, member); ksz9477_cfg_port_member(dev, port, member);
/* clear pending interrupts */ /* clear pending interrupts */
if (port < dev->phy_port_cnt) if (dev->info->internal_phy[port])
ksz_pread16(dev, port, REG_PORT_PHY_INT_ENABLE, &data16); ksz_pread16(dev, port, REG_PORT_PHY_INT_ENABLE, &data16);
} }
...@@ -1051,25 +1069,13 @@ void ksz9477_config_cpu_port(struct dsa_switch *ds) ...@@ -1051,25 +1069,13 @@ void ksz9477_config_cpu_port(struct dsa_switch *ds)
/* enable cpu port */ /* enable cpu port */
ksz9477_port_setup(dev, i, true); ksz9477_port_setup(dev, i, true);
p->on = 1;
} }
} }
for (i = 0; i < dev->info->port_cnt; i++) { for (i = 0; i < dev->info->port_cnt; i++) {
if (i == dev->cpu_port) if (i == dev->cpu_port)
continue; continue;
p = &dev->ports[i];
ksz_port_stp_state_set(ds, i, BR_STATE_DISABLED); ksz_port_stp_state_set(ds, i, BR_STATE_DISABLED);
p->on = 1;
if (i < dev->phy_port_cnt)
p->phy = 1;
if (dev->chip_id == 0x00947700 && i == 6) {
p->sgmii = 1;
/* SGMII PHY detection code is not implemented yet. */
p->phy = 0;
}
} }
} }
...@@ -1158,29 +1164,6 @@ int ksz9477_switch_init(struct ksz_device *dev) ...@@ -1158,29 +1164,6 @@ int ksz9477_switch_init(struct ksz_device *dev)
if (ret) if (ret)
return ret; return ret;
ret = ksz_read8(dev, REG_GLOBAL_OPTIONS, &data8);
if (ret)
return ret;
/* Number of ports can be reduced depending on chip. */
dev->phy_port_cnt = 5;
/* Default capability is gigabit capable. */
dev->features = GBIT_SUPPORT;
if (dev->chip_id == KSZ9893_CHIP_ID) {
dev->features |= IS_9893;
/* Chip does not support gigabit. */
if (data8 & SW_QW_ABLE)
dev->features &= ~GBIT_SUPPORT;
dev->phy_port_cnt = 2;
} else {
/* Chip does not support gigabit. */
if (!(data8 & SW_GIGABIT_ABLE))
dev->features &= ~GBIT_SUPPORT;
}
return 0; return 0;
} }
......
...@@ -16,8 +16,8 @@ u32 ksz9477_get_port_addr(int port, int offset); ...@@ -16,8 +16,8 @@ u32 ksz9477_get_port_addr(int port, int offset);
void ksz9477_cfg_port_member(struct ksz_device *dev, int port, u8 member); void ksz9477_cfg_port_member(struct ksz_device *dev, int port, u8 member);
void ksz9477_flush_dyn_mac_table(struct ksz_device *dev, int port); void ksz9477_flush_dyn_mac_table(struct ksz_device *dev, int port);
void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port); void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port);
void ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data); int ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data);
void ksz9477_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val); int ksz9477_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val);
void ksz9477_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt); void ksz9477_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt);
void ksz9477_r_mib_pkt(struct ksz_device *dev, int port, u16 addr, void ksz9477_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
u64 *dropped, u64 *cnt); u64 *dropped, u64 *cnt);
......
This diff is collapsed.
...@@ -61,6 +61,9 @@ struct ksz_chip_data { ...@@ -61,6 +61,9 @@ struct ksz_chip_data {
bool supports_rmii[KSZ_MAX_NUM_PORTS]; bool supports_rmii[KSZ_MAX_NUM_PORTS];
bool supports_rgmii[KSZ_MAX_NUM_PORTS]; bool supports_rgmii[KSZ_MAX_NUM_PORTS];
bool internal_phy[KSZ_MAX_NUM_PORTS]; bool internal_phy[KSZ_MAX_NUM_PORTS];
bool gbit_capable[KSZ_MAX_NUM_PORTS];
const struct regmap_access_table *wr_table;
const struct regmap_access_table *rd_table;
}; };
struct ksz_port { struct ksz_port {
...@@ -70,9 +73,7 @@ struct ksz_port { ...@@ -70,9 +73,7 @@ struct ksz_port {
struct phy_device phydev; struct phy_device phydev;
u32 on:1; /* port is not disabled by hardware */ u32 on:1; /* port is not disabled by hardware */
u32 phy:1; /* port has a PHY */
u32 fiber:1; /* port is fiber */ u32 fiber:1; /* port is fiber */
u32 sgmii:1; /* port is SGMII */
u32 force:1; u32 force:1;
u32 read:1; /* read MIB counters in background */ u32 read:1; /* read MIB counters in background */
u32 freeze:1; /* MIB counter freeze is enabled */ u32 freeze:1; /* MIB counter freeze is enabled */
...@@ -118,12 +119,12 @@ struct ksz_device { ...@@ -118,12 +119,12 @@ struct ksz_device {
unsigned long mib_read_interval; unsigned long mib_read_interval;
u16 mirror_rx; u16 mirror_rx;
u16 mirror_tx; u16 mirror_tx;
u32 features; /* chip specific features */
u16 port_mask; u16 port_mask;
}; };
/* List of supported models */ /* List of supported models */
enum ksz_model { enum ksz_model {
KSZ8563,
KSZ8795, KSZ8795,
KSZ8794, KSZ8794,
KSZ8765, KSZ8765,
...@@ -140,6 +141,7 @@ enum ksz_model { ...@@ -140,6 +141,7 @@ enum ksz_model {
}; };
enum ksz_chip_id { enum ksz_chip_id {
KSZ8563_CHIP_ID = 0x8563,
KSZ8795_CHIP_ID = 0x8795, KSZ8795_CHIP_ID = 0x8795,
KSZ8794_CHIP_ID = 0x8794, KSZ8794_CHIP_ID = 0x8794,
KSZ8765_CHIP_ID = 0x8765, KSZ8765_CHIP_ID = 0x8765,
...@@ -259,8 +261,8 @@ struct ksz_dev_ops { ...@@ -259,8 +261,8 @@ struct ksz_dev_ops {
void (*flush_dyn_mac_table)(struct ksz_device *dev, int port); void (*flush_dyn_mac_table)(struct ksz_device *dev, int port);
void (*port_cleanup)(struct ksz_device *dev, int port); void (*port_cleanup)(struct ksz_device *dev, int port);
void (*port_setup)(struct ksz_device *dev, int port, bool cpu_port); void (*port_setup)(struct ksz_device *dev, int port, bool cpu_port);
void (*r_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 *val); int (*r_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 *val);
void (*w_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 val); int (*w_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 val);
void (*r_mib_cnt)(struct ksz_device *dev, int port, u16 addr, void (*r_mib_cnt)(struct ksz_device *dev, int port, u16 addr,
u64 *cnt); u64 *cnt);
void (*r_mib_pkt)(struct ksz_device *dev, int port, u16 addr, void (*r_mib_pkt)(struct ksz_device *dev, int port, u16 addr,
...@@ -330,6 +332,10 @@ static inline int ksz_read8(struct ksz_device *dev, u32 reg, u8 *val) ...@@ -330,6 +332,10 @@ static inline int ksz_read8(struct ksz_device *dev, u32 reg, u8 *val)
unsigned int value; unsigned int value;
int ret = regmap_read(dev->regmap[0], reg, &value); int ret = regmap_read(dev->regmap[0], reg, &value);
if (ret)
dev_err(dev->dev, "can't read 8bit reg: 0x%x %pe\n", reg,
ERR_PTR(ret));
*val = value; *val = value;
return ret; return ret;
} }
...@@ -339,6 +345,10 @@ static inline int ksz_read16(struct ksz_device *dev, u32 reg, u16 *val) ...@@ -339,6 +345,10 @@ static inline int ksz_read16(struct ksz_device *dev, u32 reg, u16 *val)
unsigned int value; unsigned int value;
int ret = regmap_read(dev->regmap[1], reg, &value); int ret = regmap_read(dev->regmap[1], reg, &value);
if (ret)
dev_err(dev->dev, "can't read 16bit reg: 0x%x %pe\n", reg,
ERR_PTR(ret));
*val = value; *val = value;
return ret; return ret;
} }
...@@ -348,6 +358,10 @@ static inline int ksz_read32(struct ksz_device *dev, u32 reg, u32 *val) ...@@ -348,6 +358,10 @@ static inline int ksz_read32(struct ksz_device *dev, u32 reg, u32 *val)
unsigned int value; unsigned int value;
int ret = regmap_read(dev->regmap[2], reg, &value); int ret = regmap_read(dev->regmap[2], reg, &value);
if (ret)
dev_err(dev->dev, "can't read 32bit reg: 0x%x %pe\n", reg,
ERR_PTR(ret));
*val = value; *val = value;
return ret; return ret;
} }
...@@ -358,7 +372,10 @@ static inline int ksz_read64(struct ksz_device *dev, u32 reg, u64 *val) ...@@ -358,7 +372,10 @@ static inline int ksz_read64(struct ksz_device *dev, u32 reg, u64 *val)
int ret; int ret;
ret = regmap_bulk_read(dev->regmap[2], reg, value, 2); ret = regmap_bulk_read(dev->regmap[2], reg, value, 2);
if (!ret) if (ret)
dev_err(dev->dev, "can't read 64bit reg: 0x%x %pe\n", reg,
ERR_PTR(ret));
else
*val = (u64)value[0] << 32 | value[1]; *val = (u64)value[0] << 32 | value[1];
return ret; return ret;
...@@ -366,17 +383,38 @@ static inline int ksz_read64(struct ksz_device *dev, u32 reg, u64 *val) ...@@ -366,17 +383,38 @@ static inline int ksz_read64(struct ksz_device *dev, u32 reg, u64 *val)
static inline int ksz_write8(struct ksz_device *dev, u32 reg, u8 value) static inline int ksz_write8(struct ksz_device *dev, u32 reg, u8 value)
{ {
return regmap_write(dev->regmap[0], reg, value); int ret;
ret = regmap_write(dev->regmap[0], reg, value);
if (ret)
dev_err(dev->dev, "can't write 8bit reg: 0x%x %pe\n", reg,
ERR_PTR(ret));
return ret;
} }
static inline int ksz_write16(struct ksz_device *dev, u32 reg, u16 value) static inline int ksz_write16(struct ksz_device *dev, u32 reg, u16 value)
{ {
return regmap_write(dev->regmap[1], reg, value); int ret;
ret = regmap_write(dev->regmap[1], reg, value);
if (ret)
dev_err(dev->dev, "can't write 16bit reg: 0x%x %pe\n", reg,
ERR_PTR(ret));
return ret;
} }
static inline int ksz_write32(struct ksz_device *dev, u32 reg, u32 value) static inline int ksz_write32(struct ksz_device *dev, u32 reg, u32 value)
{ {
return regmap_write(dev->regmap[2], reg, value); int ret;
ret = regmap_write(dev->regmap[2], reg, value);
if (ret)
dev_err(dev->dev, "can't write 32bit reg: 0x%x %pe\n", reg,
ERR_PTR(ret));
return ret;
} }
static inline int ksz_write64(struct ksz_device *dev, u32 reg, u64 value) static inline int ksz_write64(struct ksz_device *dev, u32 reg, u64 value)
...@@ -391,40 +429,42 @@ static inline int ksz_write64(struct ksz_device *dev, u32 reg, u64 value) ...@@ -391,40 +429,42 @@ static inline int ksz_write64(struct ksz_device *dev, u32 reg, u64 value)
return regmap_bulk_write(dev->regmap[2], reg, val, 2); return regmap_bulk_write(dev->regmap[2], reg, val, 2);
} }
static inline void ksz_pread8(struct ksz_device *dev, int port, int offset, static inline int ksz_pread8(struct ksz_device *dev, int port, int offset,
u8 *data) u8 *data)
{ {
ksz_read8(dev, dev->dev_ops->get_port_addr(port, offset), data); return ksz_read8(dev, dev->dev_ops->get_port_addr(port, offset), data);
} }
static inline void ksz_pread16(struct ksz_device *dev, int port, int offset, static inline int ksz_pread16(struct ksz_device *dev, int port, int offset,
u16 *data) u16 *data)
{ {
ksz_read16(dev, dev->dev_ops->get_port_addr(port, offset), data); return ksz_read16(dev, dev->dev_ops->get_port_addr(port, offset), data);
} }
static inline void ksz_pread32(struct ksz_device *dev, int port, int offset, static inline int ksz_pread32(struct ksz_device *dev, int port, int offset,
u32 *data) u32 *data)
{ {
ksz_read32(dev, dev->dev_ops->get_port_addr(port, offset), data); return ksz_read32(dev, dev->dev_ops->get_port_addr(port, offset), data);
} }
static inline void ksz_pwrite8(struct ksz_device *dev, int port, int offset, static inline int ksz_pwrite8(struct ksz_device *dev, int port, int offset,
u8 data) u8 data)
{ {
ksz_write8(dev, dev->dev_ops->get_port_addr(port, offset), data); return ksz_write8(dev, dev->dev_ops->get_port_addr(port, offset), data);
} }
static inline void ksz_pwrite16(struct ksz_device *dev, int port, int offset, static inline int ksz_pwrite16(struct ksz_device *dev, int port, int offset,
u16 data) u16 data)
{ {
ksz_write16(dev, dev->dev_ops->get_port_addr(port, offset), data); return ksz_write16(dev, dev->dev_ops->get_port_addr(port, offset),
data);
} }
static inline void ksz_pwrite32(struct ksz_device *dev, int port, int offset, static inline int ksz_pwrite32(struct ksz_device *dev, int port, int offset,
u32 data) u32 data)
{ {
ksz_write32(dev, dev->dev_ops->get_port_addr(port, offset), data); return ksz_write32(dev, dev->dev_ops->get_port_addr(port, offset),
data);
} }
static inline void ksz_prmw8(struct ksz_device *dev, int port, int offset, static inline void ksz_prmw8(struct ksz_device *dev, int port, int offset,
...@@ -483,6 +523,10 @@ static inline int is_lan937x(struct ksz_device *dev) ...@@ -483,6 +523,10 @@ static inline int is_lan937x(struct ksz_device *dev)
#define SW_REV_ID_M GENMASK(7, 4) #define SW_REV_ID_M GENMASK(7, 4)
/* KSZ9893, KSZ9563, KSZ8563 specific register */
#define REG_CHIP_ID4 0x0f
#define SKU_ID_KSZ8563 0x3c
/* 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
...@@ -497,10 +541,6 @@ static inline int is_lan937x(struct ksz_device *dev) ...@@ -497,10 +541,6 @@ static inline int is_lan937x(struct ksz_device *dev)
#define SW_START 0x01 #define SW_START 0x01
/* Used with variable features to indicate capabilities. */
#define GBIT_SUPPORT BIT(0)
#define IS_9893 BIT(2)
/* xMII configuration */ /* xMII configuration */
#define P_MII_DUPLEX_M BIT(6) #define P_MII_DUPLEX_M BIT(6)
#define P_MII_100MBIT_M BIT(4) #define P_MII_100MBIT_M BIT(4)
......
...@@ -66,7 +66,10 @@ static int ksz_spi_probe(struct spi_device *spi) ...@@ -66,7 +66,10 @@ static int ksz_spi_probe(struct spi_device *spi)
for (i = 0; i < ARRAY_SIZE(ksz8795_regmap_config); i++) { for (i = 0; i < ARRAY_SIZE(ksz8795_regmap_config); i++) {
rc = regmap_config[i]; rc = regmap_config[i];
rc.lock_arg = &dev->regmap_mutex; rc.lock_arg = &dev->regmap_mutex;
rc.wr_table = chip->wr_table;
rc.rd_table = chip->rd_table;
dev->regmap[i] = devm_regmap_init_spi(spi, &rc); dev->regmap[i] = devm_regmap_init_spi(spi, &rc);
if (IS_ERR(dev->regmap[i])) { if (IS_ERR(dev->regmap[i])) {
ret = PTR_ERR(dev->regmap[i]); ret = PTR_ERR(dev->regmap[i]);
dev_err(&spi->dev, dev_err(&spi->dev,
...@@ -160,7 +163,7 @@ static const struct of_device_id ksz_dt_ids[] = { ...@@ -160,7 +163,7 @@ static const struct of_device_id ksz_dt_ids[] = {
}, },
{ {
.compatible = "microchip,ksz8563", .compatible = "microchip,ksz8563",
.data = &ksz_switch_chips[KSZ9893] .data = &ksz_switch_chips[KSZ8563]
}, },
{ {
.compatible = "microchip,ksz9567", .compatible = "microchip,ksz9567",
......
...@@ -12,8 +12,8 @@ void lan937x_port_setup(struct ksz_device *dev, int port, bool cpu_port); ...@@ -12,8 +12,8 @@ void lan937x_port_setup(struct ksz_device *dev, int port, bool cpu_port);
void lan937x_config_cpu_port(struct dsa_switch *ds); void lan937x_config_cpu_port(struct dsa_switch *ds);
int lan937x_switch_init(struct ksz_device *dev); int lan937x_switch_init(struct ksz_device *dev);
void lan937x_switch_exit(struct ksz_device *dev); void lan937x_switch_exit(struct ksz_device *dev);
void lan937x_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data); int lan937x_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data);
void lan937x_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val); int lan937x_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val);
int lan937x_change_mtu(struct ksz_device *dev, int port, int new_mtu); int lan937x_change_mtu(struct ksz_device *dev, int port, int new_mtu);
void lan937x_phylink_get_caps(struct ksz_device *dev, int port, void lan937x_phylink_get_caps(struct ksz_device *dev, int port,
struct phylink_config *config); struct phylink_config *config);
......
...@@ -128,14 +128,14 @@ static int lan937x_internal_phy_read(struct ksz_device *dev, int addr, int reg, ...@@ -128,14 +128,14 @@ static int lan937x_internal_phy_read(struct ksz_device *dev, int addr, int reg,
return ksz_read16(dev, REG_VPHY_IND_DATA__2, val); return ksz_read16(dev, REG_VPHY_IND_DATA__2, val);
} }
void lan937x_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data) int lan937x_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data)
{ {
lan937x_internal_phy_read(dev, addr, reg, data); return lan937x_internal_phy_read(dev, addr, reg, data);
} }
void lan937x_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val) int lan937x_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val)
{ {
lan937x_internal_phy_write(dev, addr, reg, val); return lan937x_internal_phy_write(dev, addr, reg, val);
} }
static int lan937x_sw_mdio_read(struct mii_bus *bus, int addr, int regnum) static int lan937x_sw_mdio_read(struct mii_bus *bus, int addr, int regnum)
......
...@@ -66,7 +66,7 @@ struct update_classid_context { ...@@ -66,7 +66,7 @@ struct update_classid_context {
#define UPDATE_CLASSID_BATCH 1000 #define UPDATE_CLASSID_BATCH 1000
static int update_classid_sock(const void *v, struct file *file, unsigned n) static int update_classid_sock(const void *v, struct file *file, unsigned int n)
{ {
struct update_classid_context *ctx = (void *)v; struct update_classid_context *ctx = (void *)v;
struct socket *sock = sock_from_file(file); struct socket *sock = sock_from_file(file);
......
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