Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: dsa: microchip: Use different registers for KSZ8463

KSZ8463 does not use same set of registers as KSZ8863 so it is necessary
to change some registers when using KSZ8463.

Signed-off-by: Tristram Ha <tristram.ha@microchip.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/20250725001753.6330-4-Tristram.Ha@microchip.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Tristram Ha and committed by
Jakub Kicinski
15b8d3e3 84c47bfc

+92 -28
+57 -21
drivers/net/dsa/microchip/ksz8.c
··· 142 142 KSZ8863_GLOBAL_SOFTWARE_RESET | KSZ8863_PCS_RESET, true); 143 143 ksz_cfg(dev, KSZ8863_REG_SW_RESET, 144 144 KSZ8863_GLOBAL_SOFTWARE_RESET | KSZ8863_PCS_RESET, false); 145 + } else if (ksz_is_ksz8463(dev)) { 146 + ksz_cfg(dev, KSZ8463_REG_SW_RESET, 147 + KSZ8463_GLOBAL_SOFTWARE_RESET, true); 148 + ksz_cfg(dev, KSZ8463_REG_SW_RESET, 149 + KSZ8463_GLOBAL_SOFTWARE_RESET, false); 145 150 } else { 146 151 /* reset switch */ 147 152 ksz_write8(dev, REG_POWER_MANAGEMENT_1, ··· 235 230 WEIGHTED_FAIR_QUEUE_ENABLE); 236 231 if (ret) 237 232 return ret; 233 + } else if (ksz_is_ksz8463(dev)) { 234 + mask_4q = KSZ8873_PORT_4QUEUE_SPLIT_EN; 235 + mask_2q = KSZ8873_PORT_2QUEUE_SPLIT_EN; 236 + reg_4q = P1CR1; 237 + reg_2q = P1CR1 + 1; 238 238 } else { 239 239 mask_4q = KSZ8795_PORT_4QUEUE_SPLIT_EN; 240 240 mask_2q = KSZ8795_PORT_2QUEUE_SPLIT_EN; ··· 1278 1268 1279 1269 void ksz8_cfg_port_member(struct ksz_device *dev, int port, u8 member) 1280 1270 { 1271 + int offset = P_MIRROR_CTRL; 1281 1272 u8 data; 1282 1273 1283 - ksz_pread8(dev, port, P_MIRROR_CTRL, &data); 1284 - data &= ~PORT_VLAN_MEMBERSHIP; 1274 + if (ksz_is_ksz8463(dev)) 1275 + offset = P1CR2; 1276 + ksz_pread8(dev, port, offset, &data); 1277 + data &= ~dev->port_mask; 1285 1278 data |= (member & dev->port_mask); 1286 - ksz_pwrite8(dev, port, P_MIRROR_CTRL, data); 1279 + ksz_pwrite8(dev, port, offset, data); 1287 1280 } 1288 1281 1289 1282 void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port) ··· 1294 1281 u8 learn[DSA_MAX_PORTS]; 1295 1282 int first, index, cnt; 1296 1283 const u16 *regs; 1284 + int reg = S_FLUSH_TABLE_CTRL; 1285 + int mask = SW_FLUSH_DYN_MAC_TABLE; 1297 1286 1298 1287 regs = dev->info->regs; 1299 1288 ··· 1313 1298 ksz_pwrite8(dev, index, regs[P_STP_CTRL], 1314 1299 learn[index] | PORT_LEARN_DISABLE); 1315 1300 } 1316 - ksz_cfg(dev, S_FLUSH_TABLE_CTRL, SW_FLUSH_DYN_MAC_TABLE, true); 1301 + if (ksz_is_ksz8463(dev)) { 1302 + reg = KSZ8463_FLUSH_TABLE_CTRL; 1303 + mask = KSZ8463_FLUSH_DYN_MAC_TABLE; 1304 + } 1305 + ksz_cfg(dev, reg, mask, true); 1317 1306 for (index = first; index < cnt; index++) { 1318 1307 if (!(learn[index] & PORT_LEARN_DISABLE)) 1319 1308 ksz_pwrite8(dev, index, regs[P_STP_CTRL], learn[index]); ··· 1456 1437 int ksz8_port_vlan_filtering(struct ksz_device *dev, int port, bool flag, 1457 1438 struct netlink_ext_ack *extack) 1458 1439 { 1459 - if (ksz_is_ksz88x3(dev)) 1440 + if (ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev)) 1460 1441 return -ENOTSUPP; 1461 1442 1462 1443 /* Discard packets with VID not enabled on the switch */ ··· 1472 1453 1473 1454 static void ksz8_port_enable_pvid(struct ksz_device *dev, int port, bool state) 1474 1455 { 1475 - if (ksz_is_ksz88x3(dev)) { 1476 - ksz_cfg(dev, REG_SW_INSERT_SRC_PVID, 1477 - 0x03 << (4 - 2 * port), state); 1456 + if (ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev)) { 1457 + int reg = REG_SW_INSERT_SRC_PVID; 1458 + 1459 + if (ksz_is_ksz8463(dev)) 1460 + reg = KSZ8463_REG_SW_CTRL_9; 1461 + ksz_cfg(dev, reg, 0x03 << (4 - 2 * port), state); 1478 1462 } else { 1479 1463 ksz_pwrite8(dev, port, REG_PORT_CTRL_12, state ? 0x0f : 0x00); 1480 1464 } ··· 1492 1470 u16 data, new_pvid = 0; 1493 1471 u8 fid, member, valid; 1494 1472 1495 - if (ksz_is_ksz88x3(dev)) 1473 + if (ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev)) 1496 1474 return -ENOTSUPP; 1497 1475 1498 1476 /* If a VLAN is added with untagged flag different from the ··· 1561 1539 u16 data, pvid; 1562 1540 u8 fid, member, valid; 1563 1541 1564 - if (ksz_is_ksz88x3(dev)) 1542 + if (ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev)) 1565 1543 return -ENOTSUPP; 1566 1544 1567 1545 ksz_pread16(dev, port, REG_PORT_CTRL_VID, &pvid); ··· 1591 1569 struct dsa_mall_mirror_tc_entry *mirror, 1592 1570 bool ingress, struct netlink_ext_ack *extack) 1593 1571 { 1572 + int offset = P_MIRROR_CTRL; 1573 + 1574 + if (ksz_is_ksz8463(dev)) 1575 + offset = P1CR2; 1594 1576 if (ingress) { 1595 - ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_RX, true); 1577 + ksz_port_cfg(dev, port, offset, PORT_MIRROR_RX, true); 1596 1578 dev->mirror_rx |= BIT(port); 1597 1579 } else { 1598 - ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_TX, true); 1580 + ksz_port_cfg(dev, port, offset, PORT_MIRROR_TX, true); 1599 1581 dev->mirror_tx |= BIT(port); 1600 1582 } 1601 1583 1602 - ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_SNIFFER, false); 1584 + ksz_port_cfg(dev, port, offset, PORT_MIRROR_SNIFFER, false); 1603 1585 1604 1586 /* configure mirror port */ 1605 1587 if (dev->mirror_rx || dev->mirror_tx) 1606 - ksz_port_cfg(dev, mirror->to_local_port, P_MIRROR_CTRL, 1588 + ksz_port_cfg(dev, mirror->to_local_port, offset, 1607 1589 PORT_MIRROR_SNIFFER, true); 1608 1590 1609 1591 return 0; ··· 1616 1590 void ksz8_port_mirror_del(struct ksz_device *dev, int port, 1617 1591 struct dsa_mall_mirror_tc_entry *mirror) 1618 1592 { 1593 + int offset = P_MIRROR_CTRL; 1619 1594 u8 data; 1620 1595 1596 + if (ksz_is_ksz8463(dev)) 1597 + offset = P1CR2; 1621 1598 if (mirror->ingress) { 1622 - ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_RX, false); 1599 + ksz_port_cfg(dev, port, offset, PORT_MIRROR_RX, false); 1623 1600 dev->mirror_rx &= ~BIT(port); 1624 1601 } else { 1625 - ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_TX, false); 1602 + ksz_port_cfg(dev, port, offset, PORT_MIRROR_TX, false); 1626 1603 dev->mirror_tx &= ~BIT(port); 1627 1604 } 1628 1605 1629 - ksz_pread8(dev, port, P_MIRROR_CTRL, &data); 1606 + ksz_pread8(dev, port, offset, &data); 1630 1607 1631 1608 if (!dev->mirror_rx && !dev->mirror_tx) 1632 - ksz_port_cfg(dev, mirror->to_local_port, P_MIRROR_CTRL, 1609 + ksz_port_cfg(dev, mirror->to_local_port, offset, 1633 1610 PORT_MIRROR_SNIFFER, false); 1634 1611 } 1635 1612 ··· 1657 1628 const u16 *regs = dev->info->regs; 1658 1629 struct dsa_switch *ds = dev->ds; 1659 1630 const u32 *masks; 1631 + int offset; 1660 1632 u8 member; 1661 1633 1662 1634 masks = dev->info->masks; 1663 1635 1664 1636 /* enable broadcast storm limit */ 1665 - ksz_port_cfg(dev, port, P_BCAST_STORM_CTRL, PORT_BROADCAST_STORM, true); 1637 + offset = P_BCAST_STORM_CTRL; 1638 + if (ksz_is_ksz8463(dev)) 1639 + offset = P1CR1; 1640 + ksz_port_cfg(dev, port, offset, PORT_BROADCAST_STORM, true); 1666 1641 1667 1642 ksz8_port_queue_split(dev, port, dev->info->num_tx_queues); 1668 1643 1669 1644 /* replace priority */ 1670 - ksz_port_cfg(dev, port, P_802_1P_CTRL, 1645 + offset = P_802_1P_CTRL; 1646 + if (ksz_is_ksz8463(dev)) 1647 + offset = P1CR2; 1648 + ksz_port_cfg(dev, port, offset, 1671 1649 masks[PORT_802_1P_REMAPPING], false); 1672 1650 1673 1651 if (cpu_port) ··· 1940 1904 1941 1905 ksz_cfg(dev, S_MIRROR_CTRL, SW_MIRROR_RX_TX, false); 1942 1906 1943 - if (!ksz_is_ksz88x3(dev)) 1907 + if (!ksz_is_ksz88x3(dev) && !ksz_is_ksz8463(dev)) 1944 1908 ksz_cfg(dev, REG_SW_CTRL_19, SW_INS_TAG_ENABLE, true); 1945 1909 1946 1910 for (i = 0; i < (dev->info->num_vlans / 4); i++)
+26 -6
drivers/net/dsa/microchip/ksz_common.c
··· 2951 2951 static int ksz_setup(struct dsa_switch *ds) 2952 2952 { 2953 2953 struct ksz_device *dev = ds->priv; 2954 + u16 storm_mask, storm_rate; 2954 2955 struct dsa_port *dp; 2955 2956 struct ksz_port *p; 2956 2957 const u16 *regs; ··· 2981 2980 } 2982 2981 2983 2982 /* set broadcast storm protection 10% rate */ 2983 + storm_mask = BROADCAST_STORM_RATE; 2984 + storm_rate = (BROADCAST_STORM_VALUE * BROADCAST_STORM_PROT_RATE) / 100; 2985 + if (ksz_is_ksz8463(dev)) { 2986 + storm_mask = swab16(storm_mask); 2987 + storm_rate = swab16(storm_rate); 2988 + } 2984 2989 regmap_update_bits(ksz_regmap_16(dev), regs[S_BROADCAST_CTRL], 2985 - BROADCAST_STORM_RATE, 2986 - (BROADCAST_STORM_VALUE * 2987 - BROADCAST_STORM_PROT_RATE) / 100); 2990 + storm_mask, storm_rate); 2988 2991 2989 2992 dev->dev_ops->config_cpu_port(ds); 2990 2993 ··· 4226 4221 return p->bands - 1 - band; 4227 4222 } 4228 4223 4224 + static u8 ksz8463_tc_ctrl(int port, int queue) 4225 + { 4226 + u8 reg; 4227 + 4228 + reg = 0xC8 + port * 4; 4229 + reg += ((3 - queue) / 2) * 2; 4230 + reg++; 4231 + reg -= (queue & 1); 4232 + return reg; 4233 + } 4234 + 4229 4235 /** 4230 4236 * ksz88x3_tc_ets_add - Configure ETS (Enhanced Transmission Selection) 4231 4237 * for a port on KSZ88x3 switch ··· 4272 4256 * port/queue 4273 4257 */ 4274 4258 reg = KSZ8873_TXQ_SPLIT_CTRL_REG(port, queue); 4259 + if (ksz_is_ksz8463(dev)) 4260 + reg = ksz8463_tc_ctrl(port, queue); 4275 4261 4276 4262 /* Clear WFQ enable bit to select strict priority scheduling */ 4277 4263 ret = ksz_rmw8(dev, reg, KSZ8873_TXQ_WFQ_ENABLE, 0); ··· 4309 4291 * port/queue 4310 4292 */ 4311 4293 reg = KSZ8873_TXQ_SPLIT_CTRL_REG(port, queue); 4294 + if (ksz_is_ksz8463(dev)) 4295 + reg = ksz8463_tc_ctrl(port, queue); 4312 4296 4313 4297 /* Set WFQ enable bit to revert back to default scheduling 4314 4298 * mode ··· 4458 4438 struct ksz_device *dev = ds->priv; 4459 4439 int ret; 4460 4440 4461 - if (is_ksz8(dev) && !ksz_is_ksz88x3(dev)) 4441 + if (is_ksz8(dev) && !(ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev))) 4462 4442 return -EOPNOTSUPP; 4463 4443 4464 4444 if (qopt->parent != TC_H_ROOT) { ··· 4472 4452 if (ret) 4473 4453 return ret; 4474 4454 4475 - if (ksz_is_ksz88x3(dev)) 4455 + if (ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev)) 4476 4456 return ksz88x3_tc_ets_add(dev, port, 4477 4457 &qopt->replace_params); 4478 4458 else 4479 4459 return ksz_tc_ets_add(dev, port, &qopt->replace_params); 4480 4460 case TC_ETS_DESTROY: 4481 - if (ksz_is_ksz88x3(dev)) 4461 + if (ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev)) 4482 4462 return ksz88x3_tc_ets_del(dev, port); 4483 4463 else 4484 4464 return ksz_tc_ets_del(dev, port);
+9 -1
drivers/net/dsa/microchip/ksz_dcb.c
··· 16 16 * Therefore, we define the base offset as 0x00 here to align with that logic. 17 17 */ 18 18 #define KSZ8_REG_PORT_1_CTRL_0 0x00 19 + #define KSZ8463_REG_PORT_1_CTRL_0 0x6C 19 20 #define KSZ8_PORT_DIFFSERV_ENABLE BIT(6) 20 21 #define KSZ8_PORT_802_1P_ENABLE BIT(5) 21 22 #define KSZ8_PORT_BASED_PRIO_M GENMASK(4, 3) 22 23 24 + #define KSZ8463_REG_TOS_DSCP_CTRL 0x16 23 25 #define KSZ88X3_REG_TOS_DSCP_CTRL 0x60 24 26 #define KSZ8765_REG_TOS_DSCP_CTRL 0x90 25 27 ··· 100 98 *reg = KSZ8_REG_PORT_1_CTRL_0; 101 99 *mask = KSZ8_PORT_BASED_PRIO_M; 102 100 *shift = __bf_shf(KSZ8_PORT_BASED_PRIO_M); 101 + if (ksz_is_ksz8463(dev)) 102 + *reg = KSZ8463_REG_PORT_1_CTRL_0; 103 103 } else { 104 104 *reg = KSZ9477_REG_PORT_MRI_MAC_CTRL; 105 105 *mask = KSZ9477_PORT_BASED_PRIO_M; ··· 126 122 *reg = KSZ8765_REG_TOS_DSCP_CTRL; 127 123 *per_reg = 4; 128 124 *mask = GENMASK(1, 0); 129 - } else if (ksz_is_ksz88x3(dev)) { 125 + } else if (ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev)) { 130 126 *reg = KSZ88X3_REG_TOS_DSCP_CTRL; 131 127 *per_reg = 4; 132 128 *mask = GENMASK(1, 0); 129 + if (ksz_is_ksz8463(dev)) 130 + *reg = KSZ8463_REG_TOS_DSCP_CTRL; 133 131 } else { 134 132 *reg = KSZ9477_REG_DIFFSERV_PRIO_MAP; 135 133 *per_reg = 2; ··· 157 151 *map = ksz8_apptrust_map_to_bit; 158 152 *reg = KSZ8_REG_PORT_1_CTRL_0; 159 153 *mask = KSZ8_PORT_DIFFSERV_ENABLE | KSZ8_PORT_802_1P_ENABLE; 154 + if (ksz_is_ksz8463(dev)) 155 + *reg = KSZ8463_REG_PORT_1_CTRL_0; 160 156 } else { 161 157 *map = ksz9477_apptrust_map_to_bit; 162 158 *reg = KSZ9477_REG_PORT_MRI_PRIO_CTRL;