From nobody Sat Feb 7 06:14:22 2026 Received: from esa.microchip.iphmx.com (esa.microchip.iphmx.com [68.232.153.233]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B8B8B1E1DE7; Wed, 23 Jul 2025 02:26:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=68.232.153.233 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753237608; cv=none; b=oj/N1VXAjrNEOk5nMPFMgcuv2ooBxYCeLdIer0GgBOjFP//kirrpLdSpc4qn1rzThz4vFH2JIkWdtuOswb/8jQdmdfCYeKqes6ZL2EZGoNsS3tKfpGwtPAf9/b6A3kiOZ5n9c9mBkz+V2ljgLW2XZr53+IIJLCMduoP9CEsKv38= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753237608; c=relaxed/simple; bh=o6Qi3qnUWB2At12o6TF/mbhaqxtO1apSMhvN2nAINBk=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=YrXOtE+Fh4sxAsMCFsyyO/Rovgc9xk9qLopzgw5WcRnaR5UmNd0p5Dzq9uHzmA+Jk432sYEq3NFKbU3w0UCLdtHIzg+nYwUmMWmckiEOTxHNfkBc4AUK/64SUiLgtUTGpG68r3HZMemJUFMvhsR7w9nC9Zvw+2/SGL8Kjf0XaAM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=microchip.com; spf=pass smtp.mailfrom=microchip.com; dkim=pass (2048-bit key) header.d=microchip.com header.i=@microchip.com header.b=R8bkm+Ae; arc=none smtp.client-ip=68.232.153.233 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=microchip.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=microchip.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=microchip.com header.i=@microchip.com header.b="R8bkm+Ae" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1753237607; x=1784773607; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=o6Qi3qnUWB2At12o6TF/mbhaqxtO1apSMhvN2nAINBk=; b=R8bkm+Ae764JxGKlZd7a1v9w+m/MIUeTy0FWMFHgvmf3EsYCyXFv4nHK 0JpX2GroRzfc8Y6ghHJZYKsTiskO8ihb9XDvOlvitvj68DJp3u7y7kU/X c4t+jt+EG1qIaD6PaBjWizcwXT98zvKSbGSBt2vhBiZaSZ37k1H4HpONb 7bMlL8cdmdMLEXyB5Wf7aSRvAAo/pIBAUL9SExRpFaQUyJUQwMlF1t6hM jyHAPPAE/E2t13IDziGK/7EvK0EPdf5GtK5WrOpZvlVvRTMUNXWmFByH8 /OnyLgfC6cbezvmNojQ0w6Tr9ZNjv0Ym5CYRD0dductNHINjGZdgkk7ey A==; X-CSE-ConnectionGUID: ol8zE+5pQbyz8nKT026TwA== X-CSE-MsgGUID: iLlyKP7YTgOm7p5QGtPKIg== X-IronPort-AV: E=Sophos;i="6.16,333,1744095600"; d="scan'208";a="275694685" X-Amp-Result: SKIPPED(no attachment in message) Received: from unknown (HELO email.microchip.com) ([170.129.1.10]) by esa5.microchip.iphmx.com with ESMTP/TLS/ECDHE-RSA-AES128-GCM-SHA256; 22 Jul 2025 19:26:38 -0700 Received: from chn-vm-ex02.mchp-main.com (10.10.87.72) by chn-vm-ex02.mchp-main.com (10.10.87.72) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.44; Tue, 22 Jul 2025 19:26:15 -0700 Received: from pop-os.microchip.com (10.10.85.11) by chn-vm-ex02.mchp-main.com (10.10.85.144) with Microsoft SMTP Server id 15.1.2507.44 via Frontend Transport; Tue, 22 Jul 2025 19:26:14 -0700 From: To: Woojung Huh , Andrew Lunn , Vladimir Oltean , Jakub Kicinski , "Rob Herring" , Krzysztof Kozlowski , "Conor Dooley" CC: Maxime Chevallier , Simon Horman , "David S. Miller" , Eric Dumazet , Paolo Abeni , Marek Vasut , , , , , Tristram Ha Subject: [PATCH net-next v5 3/6] net: dsa: microchip: Use different registers for KSZ8463 Date: Tue, 22 Jul 2025 19:26:09 -0700 Message-ID: <20250723022612.38535-4-Tristram.Ha@microchip.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250723022612.38535-1-Tristram.Ha@microchip.com> References: <20250723022612.38535-1-Tristram.Ha@microchip.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Tristram Ha 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 --- v3 - Replace cpu_to_be16() with swab16() to avoid compiler warning drivers/net/dsa/microchip/ksz8.c | 78 +++++++++++++++++++------- drivers/net/dsa/microchip/ksz_common.c | 32 +++++++++-- drivers/net/dsa/microchip/ksz_dcb.c | 10 +++- 3 files changed, 92 insertions(+), 28 deletions(-) diff --git a/drivers/net/dsa/microchip/ksz8.c b/drivers/net/dsa/microchip/k= sz8.c index 3761a81a7320..55c1460b8b2e 100644 --- a/drivers/net/dsa/microchip/ksz8.c +++ b/drivers/net/dsa/microchip/ksz8.c @@ -142,6 +142,11 @@ int ksz8_reset_switch(struct ksz_device *dev) KSZ8863_GLOBAL_SOFTWARE_RESET | KSZ8863_PCS_RESET, true); ksz_cfg(dev, KSZ8863_REG_SW_RESET, KSZ8863_GLOBAL_SOFTWARE_RESET | KSZ8863_PCS_RESET, false); + } else if (ksz_is_ksz8463(dev)) { + ksz_cfg(dev, KSZ8463_REG_SW_RESET, + KSZ8463_GLOBAL_SOFTWARE_RESET, true); + ksz_cfg(dev, KSZ8463_REG_SW_RESET, + KSZ8463_GLOBAL_SOFTWARE_RESET, false); } else { /* reset switch */ ksz_write8(dev, REG_POWER_MANAGEMENT_1, @@ -230,6 +235,11 @@ static int ksz8_port_queue_split(struct ksz_device *de= v, int port, int queues) WEIGHTED_FAIR_QUEUE_ENABLE); if (ret) return ret; + } else if (ksz_is_ksz8463(dev)) { + mask_4q =3D KSZ8873_PORT_4QUEUE_SPLIT_EN; + mask_2q =3D KSZ8873_PORT_2QUEUE_SPLIT_EN; + reg_4q =3D P1CR1; + reg_2q =3D P1CR1 + 1; } else { mask_4q =3D KSZ8795_PORT_4QUEUE_SPLIT_EN; mask_2q =3D KSZ8795_PORT_2QUEUE_SPLIT_EN; @@ -1268,12 +1278,15 @@ int ksz8_w_phy(struct ksz_device *dev, u16 phy, u16= reg, u16 val) =20 void ksz8_cfg_port_member(struct ksz_device *dev, int port, u8 member) { + int offset =3D P_MIRROR_CTRL; u8 data; =20 - ksz_pread8(dev, port, P_MIRROR_CTRL, &data); - data &=3D ~PORT_VLAN_MEMBERSHIP; + if (ksz_is_ksz8463(dev)) + offset =3D P1CR2; + ksz_pread8(dev, port, offset, &data); + data &=3D ~dev->port_mask; data |=3D (member & dev->port_mask); - ksz_pwrite8(dev, port, P_MIRROR_CTRL, data); + ksz_pwrite8(dev, port, offset, data); } =20 void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port) @@ -1281,6 +1294,8 @@ void ksz8_flush_dyn_mac_table(struct ksz_device *dev,= int port) u8 learn[DSA_MAX_PORTS]; int first, index, cnt; const u16 *regs; + int reg =3D S_FLUSH_TABLE_CTRL; + int mask =3D SW_FLUSH_DYN_MAC_TABLE; =20 regs =3D dev->info->regs; =20 @@ -1298,7 +1313,11 @@ void ksz8_flush_dyn_mac_table(struct ksz_device *dev= , int port) ksz_pwrite8(dev, index, regs[P_STP_CTRL], learn[index] | PORT_LEARN_DISABLE); } - ksz_cfg(dev, S_FLUSH_TABLE_CTRL, SW_FLUSH_DYN_MAC_TABLE, true); + if (ksz_is_ksz8463(dev)) { + reg =3D KSZ8463_FLUSH_TABLE_CTRL; + mask =3D KSZ8463_FLUSH_DYN_MAC_TABLE; + } + ksz_cfg(dev, reg, mask, true); for (index =3D first; index < cnt; index++) { if (!(learn[index] & PORT_LEARN_DISABLE)) ksz_pwrite8(dev, index, regs[P_STP_CTRL], learn[index]); @@ -1437,7 +1456,7 @@ int ksz8_fdb_del(struct ksz_device *dev, int port, co= nst unsigned char *addr, int ksz8_port_vlan_filtering(struct ksz_device *dev, int port, bool flag, struct netlink_ext_ack *extack) { - if (ksz_is_ksz88x3(dev)) + if (ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev)) return -ENOTSUPP; =20 /* Discard packets with VID not enabled on the switch */ @@ -1453,9 +1472,12 @@ int ksz8_port_vlan_filtering(struct ksz_device *dev,= int port, bool flag, =20 static void ksz8_port_enable_pvid(struct ksz_device *dev, int port, bool s= tate) { - if (ksz_is_ksz88x3(dev)) { - ksz_cfg(dev, REG_SW_INSERT_SRC_PVID, - 0x03 << (4 - 2 * port), state); + if (ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev)) { + int reg =3D REG_SW_INSERT_SRC_PVID; + + if (ksz_is_ksz8463(dev)) + reg =3D KSZ8463_REG_SW_CTRL_9; + ksz_cfg(dev, reg, 0x03 << (4 - 2 * port), state); } else { ksz_pwrite8(dev, port, REG_PORT_CTRL_12, state ? 0x0f : 0x00); } @@ -1470,7 +1492,7 @@ int ksz8_port_vlan_add(struct ksz_device *dev, int po= rt, u16 data, new_pvid =3D 0; u8 fid, member, valid; =20 - if (ksz_is_ksz88x3(dev)) + if (ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev)) return -ENOTSUPP; =20 /* If a VLAN is added with untagged flag different from the @@ -1539,7 +1561,7 @@ int ksz8_port_vlan_del(struct ksz_device *dev, int po= rt, u16 data, pvid; u8 fid, member, valid; =20 - if (ksz_is_ksz88x3(dev)) + if (ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev)) return -ENOTSUPP; =20 ksz_pread16(dev, port, REG_PORT_CTRL_VID, &pvid); @@ -1569,19 +1591,23 @@ int ksz8_port_mirror_add(struct ksz_device *dev, in= t port, struct dsa_mall_mirror_tc_entry *mirror, bool ingress, struct netlink_ext_ack *extack) { + int offset =3D P_MIRROR_CTRL; + + if (ksz_is_ksz8463(dev)) + offset =3D P1CR2; if (ingress) { - ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_RX, true); + ksz_port_cfg(dev, port, offset, PORT_MIRROR_RX, true); dev->mirror_rx |=3D BIT(port); } else { - ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_TX, true); + ksz_port_cfg(dev, port, offset, PORT_MIRROR_TX, true); dev->mirror_tx |=3D BIT(port); } =20 - ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_SNIFFER, false); + ksz_port_cfg(dev, port, offset, PORT_MIRROR_SNIFFER, false); =20 /* configure mirror port */ if (dev->mirror_rx || dev->mirror_tx) - ksz_port_cfg(dev, mirror->to_local_port, P_MIRROR_CTRL, + ksz_port_cfg(dev, mirror->to_local_port, offset, PORT_MIRROR_SNIFFER, true); =20 return 0; @@ -1590,20 +1616,23 @@ int ksz8_port_mirror_add(struct ksz_device *dev, in= t port, void ksz8_port_mirror_del(struct ksz_device *dev, int port, struct dsa_mall_mirror_tc_entry *mirror) { + int offset =3D P_MIRROR_CTRL; u8 data; =20 + if (ksz_is_ksz8463(dev)) + offset =3D P1CR2; if (mirror->ingress) { - ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_RX, false); + ksz_port_cfg(dev, port, offset, PORT_MIRROR_RX, false); dev->mirror_rx &=3D ~BIT(port); } else { - ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_TX, false); + ksz_port_cfg(dev, port, offset, PORT_MIRROR_TX, false); dev->mirror_tx &=3D ~BIT(port); } =20 - ksz_pread8(dev, port, P_MIRROR_CTRL, &data); + ksz_pread8(dev, port, offset, &data); =20 if (!dev->mirror_rx && !dev->mirror_tx) - ksz_port_cfg(dev, mirror->to_local_port, P_MIRROR_CTRL, + ksz_port_cfg(dev, mirror->to_local_port, offset, PORT_MIRROR_SNIFFER, false); } =20 @@ -1628,17 +1657,24 @@ void ksz8_port_setup(struct ksz_device *dev, int po= rt, bool cpu_port) const u16 *regs =3D dev->info->regs; struct dsa_switch *ds =3D dev->ds; const u32 *masks; + int offset; u8 member; =20 masks =3D dev->info->masks; =20 /* enable broadcast storm limit */ - ksz_port_cfg(dev, port, P_BCAST_STORM_CTRL, PORT_BROADCAST_STORM, true); + offset =3D P_BCAST_STORM_CTRL; + if (ksz_is_ksz8463(dev)) + offset =3D P1CR1; + ksz_port_cfg(dev, port, offset, PORT_BROADCAST_STORM, true); =20 ksz8_port_queue_split(dev, port, dev->info->num_tx_queues); =20 /* replace priority */ - ksz_port_cfg(dev, port, P_802_1P_CTRL, + offset =3D P_802_1P_CTRL; + if (ksz_is_ksz8463(dev)) + offset =3D P1CR2; + ksz_port_cfg(dev, port, offset, masks[PORT_802_1P_REMAPPING], false); =20 if (cpu_port) @@ -1904,7 +1940,7 @@ int ksz8_setup(struct dsa_switch *ds) =20 ksz_cfg(dev, S_MIRROR_CTRL, SW_MIRROR_RX_TX, false); =20 - if (!ksz_is_ksz88x3(dev)) + if (!ksz_is_ksz88x3(dev) && !ksz_is_ksz8463(dev)) ksz_cfg(dev, REG_SW_CTRL_19, SW_INS_TAG_ENABLE, true); =20 for (i =3D 0; i < (dev->info->num_vlans / 4); i++) diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/micro= chip/ksz_common.c index 095e647b3897..552c993b6519 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -2951,6 +2951,7 @@ static int ksz_parse_drive_strength(struct ksz_device= *dev); static int ksz_setup(struct dsa_switch *ds) { struct ksz_device *dev =3D ds->priv; + u16 storm_mask, storm_rate; struct dsa_port *dp; struct ksz_port *p; const u16 *regs; @@ -2980,10 +2981,14 @@ static int ksz_setup(struct dsa_switch *ds) } =20 /* set broadcast storm protection 10% rate */ + storm_mask =3D BROADCAST_STORM_RATE; + storm_rate =3D (BROADCAST_STORM_VALUE * BROADCAST_STORM_PROT_RATE) / 100; + if (ksz_is_ksz8463(dev)) { + storm_mask =3D swab16(storm_mask); + storm_rate =3D swab16(storm_rate); + } regmap_update_bits(ksz_regmap_16(dev), regs[S_BROADCAST_CTRL], - BROADCAST_STORM_RATE, - (BROADCAST_STORM_VALUE * - BROADCAST_STORM_PROT_RATE) / 100); + storm_mask, storm_rate); =20 dev->dev_ops->config_cpu_port(ds); =20 @@ -4221,6 +4226,17 @@ static int ksz_ets_band_to_queue(struct tc_ets_qopt_= offload_replace_params *p, return p->bands - 1 - band; } =20 +static u8 ksz8463_tc_ctrl(int port, int queue) +{ + u8 reg; + + reg =3D 0xC8 + port * 4; + reg +=3D ((3 - queue) / 2) * 2; + reg++; + reg -=3D (queue & 1); + return reg; +} + /** * ksz88x3_tc_ets_add - Configure ETS (Enhanced Transmission Selection) * for a port on KSZ88x3 switch @@ -4256,6 +4272,8 @@ static int ksz88x3_tc_ets_add(struct ksz_device *dev,= int port, * port/queue */ reg =3D KSZ8873_TXQ_SPLIT_CTRL_REG(port, queue); + if (ksz_is_ksz8463(dev)) + reg =3D ksz8463_tc_ctrl(port, queue); =20 /* Clear WFQ enable bit to select strict priority scheduling */ ret =3D ksz_rmw8(dev, reg, KSZ8873_TXQ_WFQ_ENABLE, 0); @@ -4291,6 +4309,8 @@ static int ksz88x3_tc_ets_del(struct ksz_device *dev,= int port) * port/queue */ reg =3D KSZ8873_TXQ_SPLIT_CTRL_REG(port, queue); + if (ksz_is_ksz8463(dev)) + reg =3D ksz8463_tc_ctrl(port, queue); =20 /* Set WFQ enable bit to revert back to default scheduling * mode @@ -4438,7 +4458,7 @@ static int ksz_tc_setup_qdisc_ets(struct dsa_switch *= ds, int port, struct ksz_device *dev =3D ds->priv; int ret; =20 - if (is_ksz8(dev) && !ksz_is_ksz88x3(dev)) + if (is_ksz8(dev) && !(ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev))) return -EOPNOTSUPP; =20 if (qopt->parent !=3D TC_H_ROOT) { @@ -4452,13 +4472,13 @@ static int ksz_tc_setup_qdisc_ets(struct dsa_switch= *ds, int port, if (ret) return ret; =20 - if (ksz_is_ksz88x3(dev)) + if (ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev)) return ksz88x3_tc_ets_add(dev, port, &qopt->replace_params); else return ksz_tc_ets_add(dev, port, &qopt->replace_params); case TC_ETS_DESTROY: - if (ksz_is_ksz88x3(dev)) + if (ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev)) return ksz88x3_tc_ets_del(dev, port); else return ksz_tc_ets_del(dev, port); diff --git a/drivers/net/dsa/microchip/ksz_dcb.c b/drivers/net/dsa/microchi= p/ksz_dcb.c index c3b501997ac9..7131c5caac54 100644 --- a/drivers/net/dsa/microchip/ksz_dcb.c +++ b/drivers/net/dsa/microchip/ksz_dcb.c @@ -16,10 +16,12 @@ * Therefore, we define the base offset as 0x00 here to align with that lo= gic. */ #define KSZ8_REG_PORT_1_CTRL_0 0x00 +#define KSZ8463_REG_PORT_1_CTRL_0 0x6C #define KSZ8_PORT_DIFFSERV_ENABLE BIT(6) #define KSZ8_PORT_802_1P_ENABLE BIT(5) #define KSZ8_PORT_BASED_PRIO_M GENMASK(4, 3) =20 +#define KSZ8463_REG_TOS_DSCP_CTRL 0x16 #define KSZ88X3_REG_TOS_DSCP_CTRL 0x60 #define KSZ8765_REG_TOS_DSCP_CTRL 0x90 =20 @@ -98,6 +100,8 @@ static void ksz_get_default_port_prio_reg(struct ksz_dev= ice *dev, int *reg, *reg =3D KSZ8_REG_PORT_1_CTRL_0; *mask =3D KSZ8_PORT_BASED_PRIO_M; *shift =3D __bf_shf(KSZ8_PORT_BASED_PRIO_M); + if (ksz_is_ksz8463(dev)) + *reg =3D KSZ8463_REG_PORT_1_CTRL_0; } else { *reg =3D KSZ9477_REG_PORT_MRI_MAC_CTRL; *mask =3D KSZ9477_PORT_BASED_PRIO_M; @@ -122,10 +126,12 @@ static void ksz_get_dscp_prio_reg(struct ksz_device *= dev, int *reg, *reg =3D KSZ8765_REG_TOS_DSCP_CTRL; *per_reg =3D 4; *mask =3D GENMASK(1, 0); - } else if (ksz_is_ksz88x3(dev)) { + } else if (ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev)) { *reg =3D KSZ88X3_REG_TOS_DSCP_CTRL; *per_reg =3D 4; *mask =3D GENMASK(1, 0); + if (ksz_is_ksz8463(dev)) + *reg =3D KSZ8463_REG_TOS_DSCP_CTRL; } else { *reg =3D KSZ9477_REG_DIFFSERV_PRIO_MAP; *per_reg =3D 2; @@ -151,6 +157,8 @@ static void ksz_get_apptrust_map_and_reg(struct ksz_dev= ice *dev, *map =3D ksz8_apptrust_map_to_bit; *reg =3D KSZ8_REG_PORT_1_CTRL_0; *mask =3D KSZ8_PORT_DIFFSERV_ENABLE | KSZ8_PORT_802_1P_ENABLE; + if (ksz_is_ksz8463(dev)) + *reg =3D KSZ8463_REG_PORT_1_CTRL_0; } else { *map =3D ksz9477_apptrust_map_to_bit; *reg =3D KSZ9477_REG_PORT_MRI_PRIO_CTRL; --=20 2.34.1