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);
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_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);
void ksz8_w_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);
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,
u8 *fid, u8 *src_port, u8 *timestamp, u16 *entries);
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)
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;
int processed = true;
......@@ -560,14 +560,24 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
u8 val1, val2;
u16 data = 0;
u8 p = phy;
int ret;
regs = dev->info->regs;
switch (reg) {
case MII_BMCR:
ksz_pread8(dev, p, regs[P_NEG_RESTART_CTRL], &restart);
ksz_pread8(dev, p, regs[P_SPEED_STATUS], &speed);
ksz_pread8(dev, p, regs[P_FORCE_CTRL], &ctrl);
ret = ksz_pread8(dev, p, regs[P_NEG_RESTART_CTRL], &restart);
if (ret)
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)
data |= BMCR_LOOPBACK;
if (ctrl & PORT_FORCE_100_MBIT)
......@@ -597,7 +607,10 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
data |= KSZ886X_BMCR_DISABLE_LED;
break;
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 |
BMSR_100HALF |
BMSR_10FULL |
......@@ -618,7 +631,10 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
data = KSZ8795_ID_LO;
break;
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;
if (ctrl & PORT_AUTO_NEG_SYM_PAUSE)
data |= ADVERTISE_PAUSE_CAP;
......@@ -632,7 +648,10 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
data |= ADVERTISE_10HALF;
break;
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;
if (link & PORT_REMOTE_SYM_PAUSE)
data |= LPA_PAUSE_CAP;
......@@ -648,8 +667,14 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
data |= LPA_LPACK;
break;
case PHY_REG_LINK_MD:
ksz_pread8(dev, p, REG_PORT_LINK_MD_CTRL, &val1);
ksz_pread8(dev, p, REG_PORT_LINK_MD_RESULT, &val2);
ret = ksz_pread8(dev, p, REG_PORT_LINK_MD_CTRL, &val1);
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)
data |= PHY_START_CABLE_DIAG;
......@@ -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));
break;
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)
data |= KSZ886X_CTRL_MDIX_STAT;
break;
......@@ -674,13 +702,16 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
}
if (processed)
*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;
const u16 *regs;
u8 p = phy;
int ret;
regs = dev->info->regs;
......@@ -690,15 +721,26 @@ void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
/* Do not support PHY reset function. */
if (val & BMCR_RESET)
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;
if (val & KSZ886X_BMCR_HP_MDIX)
data |= PORT_HP_MDIX;
else
data &= ~PORT_HP_MDIX;
if (data != speed)
ksz_pwrite8(dev, p, regs[P_SPEED_STATUS], data);
ksz_pread8(dev, p, regs[P_FORCE_CTRL], &ctrl);
if (data != speed) {
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;
if (ksz_is_ksz88x3(dev)) {
if ((val & BMCR_ANENABLE))
......@@ -724,9 +766,17 @@ void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
data |= PORT_FORCE_FULL_DUPLEX;
else
data &= ~PORT_FORCE_FULL_DUPLEX;
if (data != ctrl)
ksz_pwrite8(dev, p, regs[P_FORCE_CTRL], data);
ksz_pread8(dev, p, regs[P_NEG_RESTART_CTRL], &restart);
if (data != ctrl) {
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;
if (val & KSZ886X_BMCR_DISABLE_LED)
data |= PORT_LED_OFF;
......@@ -756,11 +806,19 @@ void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
data |= PORT_PHY_LOOPBACK;
else
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;
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 &= ~(PORT_AUTO_NEG_SYM_PAUSE |
PORT_AUTO_NEG_100BTX_FD |
......@@ -777,8 +835,12 @@ void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
data |= PORT_AUTO_NEG_10BT_FD;
if (val & ADVERTISE_10HALF)
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;
case PHY_REG_LINK_MD:
if (val & PHY_START_CABLE_DIAG)
......@@ -787,6 +849,8 @@ void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
default:
break;
}
return 0;
}
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)
if (i == dev->phy_port_cnt)
break;
p->on = 1;
p->phy = 1;
}
for (i = 0; i < dev->phy_port_cnt; i++) {
p = &dev->ports[i];
......
......@@ -193,6 +193,11 @@ int ksz9477_reset_switch(struct ksz_device *dev)
ksz_write32(dev, REG_SW_PORT_INT_MASK__4, 0x7F);
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;
if (dev->synclko_disable)
data8 = 0;
......@@ -264,9 +269,20 @@ void ksz9477_port_init_cnt(struct ksz_device *dev, int port)
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;
int ret;
/* No real PHY after this. Simulate the PHY.
* 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)
* 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.
*/
if (addr >= dev->phy_port_cnt) {
if (!dev->info->internal_phy[addr]) {
struct ksz_port *p = &dev->ports[addr];
switch (reg) {
......@@ -307,23 +323,25 @@ void ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data)
break;
}
} 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;
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. */
if (addr >= dev->phy_port_cnt)
return;
/* No gigabit support. Do not write to this register. */
if (!(dev->features & GBIT_SUPPORT) && reg == MII_CTRL1000)
return;
if (!dev->info->internal_phy[addr])
return 0;
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)
......@@ -869,7 +887,7 @@ static phy_interface_t ksz9477_get_interface(struct ksz_device *dev, int port)
phy_interface_t interface;
bool gbit;
if (port < dev->phy_port_cnt)
if (dev->info->internal_phy[port])
return PHY_INTERFACE_MODE_NA;
gbit = ksz_get_gbit(dev, port);
......@@ -914,7 +932,7 @@ static void ksz9477_phy_errata_setup(struct ksz_device *dev, int port)
/* Energy Efficient Ethernet (EEE) feature select must
* 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);
/* Register settings are required to meet data sheet
......@@ -941,7 +959,7 @@ void ksz9477_get_caps(struct ksz_device *dev, int port,
config->mac_capabilities = MAC_10 | MAC_100 | MAC_ASYM_PAUSE |
MAC_SYM_PAUSE;
if (dev->features & GBIT_SUPPORT)
if (dev->info->gbit_capable[port])
config->mac_capabilities |= MAC_1000FD;
}
......@@ -976,7 +994,7 @@ void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
/* enable 802.1p priority */
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 */
ksz_port_cfg(dev, port, REG_PORT_CTRL_0,
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)
ksz9477_cfg_port_member(dev, port, member);
/* 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);
}
......@@ -1051,25 +1069,13 @@ void ksz9477_config_cpu_port(struct dsa_switch *ds)
/* enable cpu port */
ksz9477_port_setup(dev, i, true);
p->on = 1;
}
}
for (i = 0; i < dev->info->port_cnt; i++) {
if (i == dev->cpu_port)
continue;
p = &dev->ports[i];
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)
if (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;
}
......
......@@ -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_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_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_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data);
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_pkt(struct ksz_device *dev, int port, u16 addr,
u64 *dropped, u64 *cnt);
......
......@@ -412,7 +412,422 @@ static const u8 lan937x_shifts[] = {
[ALU_STAT_INDEX] = 8,
};
static const struct regmap_range ksz8563_valid_regs[] = {
regmap_reg_range(0x0000, 0x0003),
regmap_reg_range(0x0006, 0x0006),
regmap_reg_range(0x000f, 0x001f),
regmap_reg_range(0x0100, 0x0100),
regmap_reg_range(0x0104, 0x0107),
regmap_reg_range(0x010d, 0x010d),
regmap_reg_range(0x0110, 0x0113),
regmap_reg_range(0x0120, 0x012b),
regmap_reg_range(0x0201, 0x0201),
regmap_reg_range(0x0210, 0x0213),
regmap_reg_range(0x0300, 0x0300),
regmap_reg_range(0x0302, 0x031b),
regmap_reg_range(0x0320, 0x032b),
regmap_reg_range(0x0330, 0x0336),
regmap_reg_range(0x0338, 0x033e),
regmap_reg_range(0x0340, 0x035f),
regmap_reg_range(0x0370, 0x0370),
regmap_reg_range(0x0378, 0x0378),
regmap_reg_range(0x037c, 0x037d),
regmap_reg_range(0x0390, 0x0393),
regmap_reg_range(0x0400, 0x040e),
regmap_reg_range(0x0410, 0x042f),
regmap_reg_range(0x0500, 0x0519),
regmap_reg_range(0x0520, 0x054b),
regmap_reg_range(0x0550, 0x05b3),
/* port 1 */
regmap_reg_range(0x1000, 0x1001),
regmap_reg_range(0x1004, 0x100b),
regmap_reg_range(0x1013, 0x1013),
regmap_reg_range(0x1017, 0x1017),
regmap_reg_range(0x101b, 0x101b),
regmap_reg_range(0x101f, 0x1021),
regmap_reg_range(0x1030, 0x1030),
regmap_reg_range(0x1100, 0x1111),
regmap_reg_range(0x111a, 0x111d),
regmap_reg_range(0x1122, 0x1127),
regmap_reg_range(0x112a, 0x112b),
regmap_reg_range(0x1136, 0x1139),
regmap_reg_range(0x113e, 0x113f),
regmap_reg_range(0x1400, 0x1401),
regmap_reg_range(0x1403, 0x1403),
regmap_reg_range(0x1410, 0x1417),
regmap_reg_range(0x1420, 0x1423),
regmap_reg_range(0x1500, 0x1507),
regmap_reg_range(0x1600, 0x1612),
regmap_reg_range(0x1800, 0x180f),
regmap_reg_range(0x1900, 0x1907),
regmap_reg_range(0x1914, 0x191b),
regmap_reg_range(0x1a00, 0x1a03),
regmap_reg_range(0x1a04, 0x1a08),
regmap_reg_range(0x1b00, 0x1b01),
regmap_reg_range(0x1b04, 0x1b04),
regmap_reg_range(0x1c00, 0x1c05),
regmap_reg_range(0x1c08, 0x1c1b),
/* port 2 */
regmap_reg_range(0x2000, 0x2001),
regmap_reg_range(0x2004, 0x200b),
regmap_reg_range(0x2013, 0x2013),
regmap_reg_range(0x2017, 0x2017),
regmap_reg_range(0x201b, 0x201b),
regmap_reg_range(0x201f, 0x2021),
regmap_reg_range(0x2030, 0x2030),
regmap_reg_range(0x2100, 0x2111),
regmap_reg_range(0x211a, 0x211d),
regmap_reg_range(0x2122, 0x2127),
regmap_reg_range(0x212a, 0x212b),
regmap_reg_range(0x2136, 0x2139),
regmap_reg_range(0x213e, 0x213f),
regmap_reg_range(0x2400, 0x2401),
regmap_reg_range(0x2403, 0x2403),
regmap_reg_range(0x2410, 0x2417),
regmap_reg_range(0x2420, 0x2423),
regmap_reg_range(0x2500, 0x2507),
regmap_reg_range(0x2600, 0x2612),
regmap_reg_range(0x2800, 0x280f),
regmap_reg_range(0x2900, 0x2907),
regmap_reg_range(0x2914, 0x291b),
regmap_reg_range(0x2a00, 0x2a03),
regmap_reg_range(0x2a04, 0x2a08),
regmap_reg_range(0x2b00, 0x2b01),
regmap_reg_range(0x2b04, 0x2b04),
regmap_reg_range(0x2c00, 0x2c05),
regmap_reg_range(0x2c08, 0x2c1b),
/* port 3 */
regmap_reg_range(0x3000, 0x3001),
regmap_reg_range(0x3004, 0x300b),
regmap_reg_range(0x3013, 0x3013),
regmap_reg_range(0x3017, 0x3017),
regmap_reg_range(0x301b, 0x301b),
regmap_reg_range(0x301f, 0x3021),
regmap_reg_range(0x3030, 0x3030),
regmap_reg_range(0x3300, 0x3301),
regmap_reg_range(0x3303, 0x3303),
regmap_reg_range(0x3400, 0x3401),
regmap_reg_range(0x3403, 0x3403),
regmap_reg_range(0x3410, 0x3417),
regmap_reg_range(0x3420, 0x3423),
regmap_reg_range(0x3500, 0x3507),
regmap_reg_range(0x3600, 0x3612),
regmap_reg_range(0x3800, 0x380f),
regmap_reg_range(0x3900, 0x3907),
regmap_reg_range(0x3914, 0x391b),
regmap_reg_range(0x3a00, 0x3a03),
regmap_reg_range(0x3a04, 0x3a08),
regmap_reg_range(0x3b00, 0x3b01),
regmap_reg_range(0x3b04, 0x3b04),
regmap_reg_range(0x3c00, 0x3c05),
regmap_reg_range(0x3c08, 0x3c1b),
};
static const struct regmap_access_table ksz8563_register_set = {
.yes_ranges = ksz8563_valid_regs,
.n_yes_ranges = ARRAY_SIZE(ksz8563_valid_regs),
};
static const struct regmap_range ksz9477_valid_regs[] = {
regmap_reg_range(0x0000, 0x0003),
regmap_reg_range(0x0006, 0x0006),
regmap_reg_range(0x0010, 0x001f),
regmap_reg_range(0x0100, 0x0100),
regmap_reg_range(0x0103, 0x0107),
regmap_reg_range(0x010d, 0x010d),
regmap_reg_range(0x0110, 0x0113),
regmap_reg_range(0x0120, 0x012b),
regmap_reg_range(0x0201, 0x0201),
regmap_reg_range(0x0210, 0x0213),
regmap_reg_range(0x0300, 0x0300),
regmap_reg_range(0x0302, 0x031b),
regmap_reg_range(0x0320, 0x032b),
regmap_reg_range(0x0330, 0x0336),
regmap_reg_range(0x0338, 0x033e),
regmap_reg_range(0x0340, 0x035f),
regmap_reg_range(0x0370, 0x0370),
regmap_reg_range(0x0378, 0x0378),
regmap_reg_range(0x037c, 0x037d),
regmap_reg_range(0x0390, 0x0393),
regmap_reg_range(0x0400, 0x040e),
regmap_reg_range(0x0410, 0x042f),
regmap_reg_range(0x0444, 0x044b),
regmap_reg_range(0x0450, 0x046f),
regmap_reg_range(0x0500, 0x0519),
regmap_reg_range(0x0520, 0x054b),
regmap_reg_range(0x0550, 0x05b3),
regmap_reg_range(0x0604, 0x060b),
regmap_reg_range(0x0610, 0x0612),
regmap_reg_range(0x0614, 0x062c),
regmap_reg_range(0x0640, 0x0645),
regmap_reg_range(0x0648, 0x064d),
/* port 1 */
regmap_reg_range(0x1000, 0x1001),
regmap_reg_range(0x1013, 0x1013),
regmap_reg_range(0x1017, 0x1017),
regmap_reg_range(0x101b, 0x101b),
regmap_reg_range(0x101f, 0x1020),
regmap_reg_range(0x1030, 0x1030),
regmap_reg_range(0x1100, 0x1115),
regmap_reg_range(0x111a, 0x111f),
regmap_reg_range(0x1122, 0x1127),
regmap_reg_range(0x112a, 0x112b),
regmap_reg_range(0x1136, 0x1139),
regmap_reg_range(0x113e, 0x113f),
regmap_reg_range(0x1400, 0x1401),
regmap_reg_range(0x1403, 0x1403),
regmap_reg_range(0x1410, 0x1417),
regmap_reg_range(0x1420, 0x1423),
regmap_reg_range(0x1500, 0x1507),
regmap_reg_range(0x1600, 0x1613),
regmap_reg_range(0x1800, 0x180f),
regmap_reg_range(0x1820, 0x1827),
regmap_reg_range(0x1830, 0x1837),
regmap_reg_range(0x1840, 0x184b),
regmap_reg_range(0x1900, 0x1907),
regmap_reg_range(0x1914, 0x191b),
regmap_reg_range(0x1920, 0x1920),
regmap_reg_range(0x1923, 0x1927),
regmap_reg_range(0x1a00, 0x1a03),
regmap_reg_range(0x1a04, 0x1a07),
regmap_reg_range(0x1b00, 0x1b01),
regmap_reg_range(0x1b04, 0x1b04),
regmap_reg_range(0x1c00, 0x1c05),
regmap_reg_range(0x1c08, 0x1c1b),
/* port 2 */
regmap_reg_range(0x2000, 0x2001),
regmap_reg_range(0x2013, 0x2013),
regmap_reg_range(0x2017, 0x2017),
regmap_reg_range(0x201b, 0x201b),
regmap_reg_range(0x201f, 0x2020),
regmap_reg_range(0x2030, 0x2030),
regmap_reg_range(0x2100, 0x2115),
regmap_reg_range(0x211a, 0x211f),
regmap_reg_range(0x2122, 0x2127),
regmap_reg_range(0x212a, 0x212b),
regmap_reg_range(0x2136, 0x2139),
regmap_reg_range(0x213e, 0x213f),
regmap_reg_range(0x2400, 0x2401),
regmap_reg_range(0x2403, 0x2403),
regmap_reg_range(0x2410, 0x2417),
regmap_reg_range(0x2420, 0x2423),
regmap_reg_range(0x2500, 0x2507),
regmap_reg_range(0x2600, 0x2613),
regmap_reg_range(0x2800, 0x280f),
regmap_reg_range(0x2820, 0x2827),
regmap_reg_range(0x2830, 0x2837),
regmap_reg_range(0x2840, 0x284b),
regmap_reg_range(0x2900, 0x2907),
regmap_reg_range(0x2914, 0x291b),
regmap_reg_range(0x2920, 0x2920),
regmap_reg_range(0x2923, 0x2927),
regmap_reg_range(0x2a00, 0x2a03),
regmap_reg_range(0x2a04, 0x2a07),
regmap_reg_range(0x2b00, 0x2b01),
regmap_reg_range(0x2b04, 0x2b04),
regmap_reg_range(0x2c00, 0x2c05),
regmap_reg_range(0x2c08, 0x2c1b),
/* port 3 */
regmap_reg_range(0x3000, 0x3001),
regmap_reg_range(0x3013, 0x3013),
regmap_reg_range(0x3017, 0x3017),
regmap_reg_range(0x301b, 0x301b),
regmap_reg_range(0x301f, 0x3020),
regmap_reg_range(0x3030, 0x3030),
regmap_reg_range(0x3100, 0x3115),
regmap_reg_range(0x311a, 0x311f),
regmap_reg_range(0x3122, 0x3127),
regmap_reg_range(0x312a, 0x312b),
regmap_reg_range(0x3136, 0x3139),
regmap_reg_range(0x313e, 0x313f),
regmap_reg_range(0x3400, 0x3401),
regmap_reg_range(0x3403, 0x3403),
regmap_reg_range(0x3410, 0x3417),
regmap_reg_range(0x3420, 0x3423),
regmap_reg_range(0x3500, 0x3507),
regmap_reg_range(0x3600, 0x3613),
regmap_reg_range(0x3800, 0x380f),
regmap_reg_range(0x3820, 0x3827),
regmap_reg_range(0x3830, 0x3837),
regmap_reg_range(0x3840, 0x384b),
regmap_reg_range(0x3900, 0x3907),
regmap_reg_range(0x3914, 0x391b),
regmap_reg_range(0x3920, 0x3920),
regmap_reg_range(0x3923, 0x3927),
regmap_reg_range(0x3a00, 0x3a03),
regmap_reg_range(0x3a04, 0x3a07),
regmap_reg_range(0x3b00, 0x3b01),
regmap_reg_range(0x3b04, 0x3b04),
regmap_reg_range(0x3c00, 0x3c05),
regmap_reg_range(0x3c08, 0x3c1b),
/* port 4 */
regmap_reg_range(0x4000, 0x4001),
regmap_reg_range(0x4013, 0x4013),
regmap_reg_range(0x4017, 0x4017),
regmap_reg_range(0x401b, 0x401b),
regmap_reg_range(0x401f, 0x4020),
regmap_reg_range(0x4030, 0x4030),
regmap_reg_range(0x4100, 0x4115),
regmap_reg_range(0x411a, 0x411f),
regmap_reg_range(0x4122, 0x4127),
regmap_reg_range(0x412a, 0x412b),
regmap_reg_range(0x4136, 0x4139),
regmap_reg_range(0x413e, 0x413f),
regmap_reg_range(0x4400, 0x4401),
regmap_reg_range(0x4403, 0x4403),
regmap_reg_range(0x4410, 0x4417),
regmap_reg_range(0x4420, 0x4423),
regmap_reg_range(0x4500, 0x4507),
regmap_reg_range(0x4600, 0x4613),
regmap_reg_range(0x4800, 0x480f),
regmap_reg_range(0x4820, 0x4827),
regmap_reg_range(0x4830, 0x4837),
regmap_reg_range(0x4840, 0x484b),
regmap_reg_range(0x4900, 0x4907),
regmap_reg_range(0x4914, 0x491b),
regmap_reg_range(0x4920, 0x4920),
regmap_reg_range(0x4923, 0x4927),
regmap_reg_range(0x4a00, 0x4a03),
regmap_reg_range(0x4a04, 0x4a07),
regmap_reg_range(0x4b00, 0x4b01),
regmap_reg_range(0x4b04, 0x4b04),
regmap_reg_range(0x4c00, 0x4c05),
regmap_reg_range(0x4c08, 0x4c1b),
/* port 5 */
regmap_reg_range(0x5000, 0x5001),
regmap_reg_range(0x5013, 0x5013),
regmap_reg_range(0x5017, 0x5017),
regmap_reg_range(0x501b, 0x501b),
regmap_reg_range(0x501f, 0x5020),
regmap_reg_range(0x5030, 0x5030),
regmap_reg_range(0x5100, 0x5115),
regmap_reg_range(0x511a, 0x511f),
regmap_reg_range(0x5122, 0x5127),
regmap_reg_range(0x512a, 0x512b),
regmap_reg_range(0x5136, 0x5139),
regmap_reg_range(0x513e, 0x513f),
regmap_reg_range(0x5400, 0x5401),
regmap_reg_range(0x5403, 0x5403),
regmap_reg_range(0x5410, 0x5417),
regmap_reg_range(0x5420, 0x5423),
regmap_reg_range(0x5500, 0x5507),
regmap_reg_range(0x5600, 0x5613),
regmap_reg_range(0x5800, 0x580f),
regmap_reg_range(0x5820, 0x5827),
regmap_reg_range(0x5830, 0x5837),
regmap_reg_range(0x5840, 0x584b),
regmap_reg_range(0x5900, 0x5907),
regmap_reg_range(0x5914, 0x591b),
regmap_reg_range(0x5920, 0x5920),
regmap_reg_range(0x5923, 0x5927),
regmap_reg_range(0x5a00, 0x5a03),
regmap_reg_range(0x5a04, 0x5a07),
regmap_reg_range(0x5b00, 0x5b01),
regmap_reg_range(0x5b04, 0x5b04),
regmap_reg_range(0x5c00, 0x5c05),
regmap_reg_range(0x5c08, 0x5c1b),
/* port 6 */
regmap_reg_range(0x6000, 0x6001),
regmap_reg_range(0x6013, 0x6013),
regmap_reg_range(0x6017, 0x6017),
regmap_reg_range(0x601b, 0x601b),
regmap_reg_range(0x601f, 0x6020),
regmap_reg_range(0x6030, 0x6030),
regmap_reg_range(0x6300, 0x6301),
regmap_reg_range(0x6400, 0x6401),
regmap_reg_range(0x6403, 0x6403),
regmap_reg_range(0x6410, 0x6417),
regmap_reg_range(0x6420, 0x6423),
regmap_reg_range(0x6500, 0x6507),
regmap_reg_range(0x6600, 0x6613),
regmap_reg_range(0x6800, 0x680f),
regmap_reg_range(0x6820, 0x6827),
regmap_reg_range(0x6830, 0x6837),
regmap_reg_range(0x6840, 0x684b),
regmap_reg_range(0x6900, 0x6907),
regmap_reg_range(0x6914, 0x691b),
regmap_reg_range(0x6920, 0x6920),
regmap_reg_range(0x6923, 0x6927),
regmap_reg_range(0x6a00, 0x6a03),
regmap_reg_range(0x6a04, 0x6a07),
regmap_reg_range(0x6b00, 0x6b01),
regmap_reg_range(0x6b04, 0x6b04),
regmap_reg_range(0x6c00, 0x6c05),
regmap_reg_range(0x6c08, 0x6c1b),
/* port 7 */
regmap_reg_range(0x7000, 0x7001),
regmap_reg_range(0x7013, 0x7013),
regmap_reg_range(0x7017, 0x7017),
regmap_reg_range(0x701b, 0x701b),
regmap_reg_range(0x701f, 0x7020),
regmap_reg_range(0x7030, 0x7030),
regmap_reg_range(0x7200, 0x7203),
regmap_reg_range(0x7206, 0x7207),
regmap_reg_range(0x7300, 0x7301),
regmap_reg_range(0x7400, 0x7401),
regmap_reg_range(0x7403, 0x7403),
regmap_reg_range(0x7410, 0x7417),
regmap_reg_range(0x7420, 0x7423),
regmap_reg_range(0x7500, 0x7507),
regmap_reg_range(0x7600, 0x7613),
regmap_reg_range(0x7800, 0x780f),
regmap_reg_range(0x7820, 0x7827),
regmap_reg_range(0x7830, 0x7837),
regmap_reg_range(0x7840, 0x784b),
regmap_reg_range(0x7900, 0x7907),
regmap_reg_range(0x7914, 0x791b),
regmap_reg_range(0x7920, 0x7920),
regmap_reg_range(0x7923, 0x7927),
regmap_reg_range(0x7a00, 0x7a03),
regmap_reg_range(0x7a04, 0x7a07),
regmap_reg_range(0x7b00, 0x7b01),
regmap_reg_range(0x7b04, 0x7b04),
regmap_reg_range(0x7c00, 0x7c05),
regmap_reg_range(0x7c08, 0x7c1b),
};
static const struct regmap_access_table ksz9477_register_set = {
.yes_ranges = ksz9477_valid_regs,
.n_yes_ranges = ARRAY_SIZE(ksz9477_valid_regs),
};
const struct ksz_chip_data ksz_switch_chips[] = {
[KSZ8563] = {
.chip_id = KSZ8563_CHIP_ID,
.dev_name = "KSZ8563",
.num_vlans = 4096,
.num_alus = 4096,
.num_statics = 16,
.cpu_ports = 0x07, /* can be configured as cpu port */
.port_cnt = 3, /* total port count */
.ops = &ksz9477_dev_ops,
.mib_names = ksz9477_mib_names,
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
.reg_mib_cnt = MIB_COUNTER_NUM,
.regs = ksz9477_regs,
.masks = ksz9477_masks,
.shifts = ksz9477_shifts,
.xmii_ctrl0 = ksz9477_xmii_ctrl0,
.xmii_ctrl1 = ksz8795_xmii_ctrl1, /* Same as ksz8795 */
.supports_mii = {false, false, true},
.supports_rmii = {false, false, true},
.supports_rgmii = {false, false, true},
.internal_phy = {true, true, false},
.gbit_capable = {false, false, true},
.wr_table = &ksz8563_register_set,
.rd_table = &ksz8563_register_set,
},
[KSZ8795] = {
.chip_id = KSZ8795_CHIP_ID,
.dev_name = "KSZ8795",
......@@ -545,6 +960,9 @@ const struct ksz_chip_data ksz_switch_chips[] = {
false, true, false},
.internal_phy = {true, true, true, true,
true, false, false},
.gbit_capable = {true, true, true, true, true, true, true},
.wr_table = &ksz9477_register_set,
.rd_table = &ksz9477_register_set,
},
[KSZ9897] = {
......@@ -573,6 +991,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
false, true, true},
.internal_phy = {true, true, true, true,
true, false, false},
.gbit_capable = {true, true, true, true, true, true, true},
},
[KSZ9893] = {
......@@ -596,6 +1015,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.supports_rmii = {false, false, true},
.supports_rgmii = {false, false, true},
.internal_phy = {true, true, false},
.gbit_capable = {true, true, true},
},
[KSZ9567] = {
......@@ -624,6 +1044,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
false, true, true},
.internal_phy = {true, true, true, true,
true, false, false},
.gbit_capable = {true, true, true, true, true, true, true},
},
[LAN9370] = {
......@@ -1104,8 +1525,11 @@ static int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg)
{
struct ksz_device *dev = ds->priv;
u16 val = 0xffff;
int ret;
dev->dev_ops->r_phy(dev, addr, reg, &val);
ret = dev->dev_ops->r_phy(dev, addr, reg, &val);
if (ret)
return ret;
return val;
}
......@@ -1113,8 +1537,11 @@ static int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg)
static int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val)
{
struct ksz_device *dev = ds->priv;
int ret;
dev->dev_ops->w_phy(dev, addr, reg, val);
ret = dev->dev_ops->w_phy(dev, addr, reg, val);
if (ret)
return ret;
return 0;
}
......@@ -1366,6 +1793,7 @@ static enum dsa_tag_protocol ksz_get_tag_protocol(struct dsa_switch *ds,
proto = DSA_TAG_PROTO_KSZ8795;
if (dev->chip_id == KSZ8830_CHIP_ID ||
dev->chip_id == KSZ8563_CHIP_ID ||
dev->chip_id == KSZ9893_CHIP_ID)
proto = DSA_TAG_PROTO_KSZ9893;
......@@ -1484,7 +1912,8 @@ static void ksz_set_xmii(struct ksz_device *dev, int port,
case PHY_INTERFACE_MODE_RGMII_RXID:
data8 |= bitval[P_RGMII_SEL];
/* On KSZ9893, disable RGMII in-band status support */
if (dev->features & IS_9893)
if (dev->chip_id == KSZ9893_CHIP_ID ||
dev->chip_id == KSZ8563_CHIP_ID)
data8 &= ~P_MII_MAC_MODE;
break;
default:
......@@ -1685,7 +2114,7 @@ static void ksz_phylink_mac_link_up(struct dsa_switch *ds, int port,
static int ksz_switch_detect(struct ksz_device *dev)
{
u8 id1, id2;
u8 id1, id2, id4;
u16 id16;
u32 id32;
int ret;
......@@ -1731,7 +2160,6 @@ static int ksz_switch_detect(struct ksz_device *dev)
switch (id32) {
case KSZ9477_CHIP_ID:
case KSZ9897_CHIP_ID:
case KSZ9893_CHIP_ID:
case KSZ9567_CHIP_ID:
case LAN9370_CHIP_ID:
case LAN9371_CHIP_ID:
......@@ -1739,6 +2167,18 @@ static int ksz_switch_detect(struct ksz_device *dev)
case LAN9373_CHIP_ID:
case LAN9374_CHIP_ID:
dev->chip_id = id32;
break;
case KSZ9893_CHIP_ID:
ret = ksz_read8(dev, REG_CHIP_ID4,
&id4);
if (ret)
return ret;
if (id4 == SKU_ID_KSZ8563)
dev->chip_id = KSZ8563_CHIP_ID;
else
dev->chip_id = KSZ9893_CHIP_ID;
break;
default:
dev_err(dev->dev,
......
......@@ -61,6 +61,9 @@ struct ksz_chip_data {
bool supports_rmii[KSZ_MAX_NUM_PORTS];
bool supports_rgmii[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 {
......@@ -70,9 +73,7 @@ struct ksz_port {
struct phy_device phydev;
u32 on:1; /* port is not disabled by hardware */
u32 phy:1; /* port has a PHY */
u32 fiber:1; /* port is fiber */
u32 sgmii:1; /* port is SGMII */
u32 force:1;
u32 read:1; /* read MIB counters in background */
u32 freeze:1; /* MIB counter freeze is enabled */
......@@ -118,12 +119,12 @@ struct ksz_device {
unsigned long mib_read_interval;
u16 mirror_rx;
u16 mirror_tx;
u32 features; /* chip specific features */
u16 port_mask;
};
/* List of supported models */
enum ksz_model {
KSZ8563,
KSZ8795,
KSZ8794,
KSZ8765,
......@@ -140,6 +141,7 @@ enum ksz_model {
};
enum ksz_chip_id {
KSZ8563_CHIP_ID = 0x8563,
KSZ8795_CHIP_ID = 0x8795,
KSZ8794_CHIP_ID = 0x8794,
KSZ8765_CHIP_ID = 0x8765,
......@@ -259,8 +261,8 @@ struct ksz_dev_ops {
void (*flush_dyn_mac_table)(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 (*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 (*r_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,
u64 *cnt);
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)
unsigned int 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;
return ret;
}
......@@ -339,6 +345,10 @@ static inline int ksz_read16(struct ksz_device *dev, u32 reg, u16 *val)
unsigned int 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;
return ret;
}
......@@ -348,6 +358,10 @@ static inline int ksz_read32(struct ksz_device *dev, u32 reg, u32 *val)
unsigned int 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;
return ret;
}
......@@ -358,7 +372,10 @@ static inline int ksz_read64(struct ksz_device *dev, u32 reg, u64 *val)
int ret;
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];
return ret;
......@@ -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)
{
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)
{
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)
{
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)
......@@ -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);
}
static inline void ksz_pread8(struct ksz_device *dev, int port, int offset,
u8 *data)
static inline int ksz_pread8(struct ksz_device *dev, int port, int offset,
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,
u16 *data)
static inline int ksz_pread16(struct ksz_device *dev, int port, int offset,
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,
u32 *data)
static inline int ksz_pread32(struct ksz_device *dev, int port, int offset,
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,
u8 data)
static inline int ksz_pwrite8(struct ksz_device *dev, int port, int offset,
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,
u16 data)
static inline int ksz_pwrite16(struct ksz_device *dev, int port, int offset,
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,
u32 data)
static inline int ksz_pwrite32(struct ksz_device *dev, int port, int offset,
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,
......@@ -483,6 +523,10 @@ static inline int is_lan937x(struct ksz_device *dev)
#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. */
#define BROADCAST_STORM_PROT_RATE 10
......@@ -497,10 +541,6 @@ static inline int is_lan937x(struct ksz_device *dev)
#define SW_START 0x01
/* Used with variable features to indicate capabilities. */
#define GBIT_SUPPORT BIT(0)
#define IS_9893 BIT(2)
/* xMII configuration */
#define P_MII_DUPLEX_M BIT(6)
#define P_MII_100MBIT_M BIT(4)
......
......@@ -66,7 +66,10 @@ static int ksz_spi_probe(struct spi_device *spi)
for (i = 0; i < ARRAY_SIZE(ksz8795_regmap_config); i++) {
rc = regmap_config[i];
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);
if (IS_ERR(dev->regmap[i])) {
ret = PTR_ERR(dev->regmap[i]);
dev_err(&spi->dev,
......@@ -160,7 +163,7 @@ static const struct of_device_id ksz_dt_ids[] = {
},
{
.compatible = "microchip,ksz8563",
.data = &ksz_switch_chips[KSZ9893]
.data = &ksz_switch_chips[KSZ8563]
},
{
.compatible = "microchip,ksz9567",
......
......@@ -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);
int lan937x_switch_init(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);
void lan937x_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val);
int lan937x_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data);
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);
void lan937x_phylink_get_caps(struct ksz_device *dev, int port,
struct phylink_config *config);
......
......@@ -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);
}
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)
......
......@@ -66,7 +66,7 @@ struct update_classid_context {
#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 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