From nobody Sat Feb 7 06:14:40 2026 Received: from esa.microchip.iphmx.com (esa.microchip.iphmx.com [68.232.154.123]) (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 45EC97DA9C; Tue, 8 Jul 2025 03:17:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=68.232.154.123 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751944641; cv=none; b=Mfm7QVbXtSZEKWJQcpx0GWJqiR+ar5f3ua454ER5utD7o2AVs0ky2fg9vnMIJ5l6EqmJOVGGDZamrmyp9/6U80nI8D/9tq/o25Q3D8TY39LPBGjMM2Y/SHAU1uUtQLJv/3GKuHGGTr0RsnqHoY87++Iq/Z5xN5DZN4M3wZitF/U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751944641; c=relaxed/simple; bh=TPIb0xPK187K7rLue1DLpFCg5Yh7MklSC0DJpXh+ee4=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=i06WOXWQ6TLpZUoGYElakRGIKyiAvvyoYQqLufVARxDsCdJZl6xLDkIlDIlRFo9x4WZlFKXQP55KnSWFVW0+FRkE+u733SRR9U0Lz7U6el5NHV5sDPRk7eV0MkjAiO2EQAkCbvGzFaqST0nkWMf5ilE0vjTlev2fssgA2eQ21lA= 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=fUhZlEwk; arc=none smtp.client-ip=68.232.154.123 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="fUhZlEwk" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1751944639; x=1783480639; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=TPIb0xPK187K7rLue1DLpFCg5Yh7MklSC0DJpXh+ee4=; b=fUhZlEwk723SyoIeLBZ5VU90X/XoTvz1o0DZg6+Jp7ygPx+8V5x2Ezfm ivF/EKpRhHC9iGQD/es0phRyYbadQapdWTE5ZMhEmhkX+s8mXnYWg1hWG 5Ucvfw/COwlUGkDD/g3weqOMVX9eklF+ZAEQR87jnN9pNatmEjyxhLo5P xzdvpavikS/fL/whhU5ukM4Cbq48NkpZnuQLAO5/EQ0EPzqK0r4NQ9Qz6 nIHCRD/94uSdrCPtBaEySl5Bvhp3CC/h1PcA1YBqDk6dwxbuEit4Kq2gp ZIF6VvDRiSeTVGZMPBdZMb/raJyAx2dIFH9/y0puTeSRyQemjP45TI6UY w==; X-CSE-ConnectionGUID: cVEISvaDRiehsZPvdpmZNg== X-CSE-MsgGUID: RaoMSu4ITc6n/SZ2t2Hj0w== X-IronPort-AV: E=Sophos;i="6.16,296,1744095600"; d="scan'208";a="43198301" X-Amp-Result: SKIPPED(no attachment in message) Received: from unknown (HELO email.microchip.com) ([170.129.1.10]) by esa4.microchip.iphmx.com with ESMTP/TLS/ECDHE-RSA-AES128-GCM-SHA256; 07 Jul 2025 20:17:16 -0700 Received: from chn-vm-ex04.mchp-main.com (10.10.85.152) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.44; Mon, 7 Jul 2025 20:16:46 -0700 Received: from pop-os.microchip.com (10.10.85.11) by chn-vm-ex04.mchp-main.com (10.10.85.152) with Microsoft SMTP Server id 15.1.2507.44 via Frontend Transport; Mon, 7 Jul 2025 20:16:46 -0700 From: To: Woojung Huh , Andrew Lunn , Vladimir Oltean , Rob Herring , "Krzysztof Kozlowski" , Conor Dooley CC: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Marek Vasut , , , , , Tristram Ha Subject: [PATCH net-next 4/6 v2] net: dsa: microchip: Use different registers for KSZ8463 Date: Mon, 7 Jul 2025 20:16:46 -0700 Message-ID: <20250708031648.6703-5-Tristram.Ha@microchip.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250708031648.6703-1-Tristram.Ha@microchip.com> References: <20250708031648.6703-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 --- drivers/net/dsa/microchip/ksz8.c | 78 +++++++++++++++++++------- drivers/net/dsa/microchip/ksz_common.c | 35 +++++++++--- drivers/net/dsa/microchip/ksz_dcb.c | 10 +++- 3 files changed, 94 insertions(+), 29 deletions(-) diff --git a/drivers/net/dsa/microchip/ksz8.c b/drivers/net/dsa/microchip/k= sz8.c index f0c6049afe51..904db68e11f3 100644 --- a/drivers/net/dsa/microchip/ksz8.c +++ b/drivers/net/dsa/microchip/ksz8.c @@ -143,6 +143,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, @@ -231,6 +236,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; @@ -1269,12 +1279,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) @@ -1282,6 +1295,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 @@ -1299,7 +1314,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]); @@ -1438,7 +1457,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 */ @@ -1454,9 +1473,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); } @@ -1471,7 +1493,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 @@ -1540,7 +1562,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); @@ -1570,19 +1592,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; @@ -1591,20 +1617,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 @@ -1629,17 +1658,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) @@ -1905,7 +1941,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 5261747b7753..55108237180c 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,15 @@ static int ksz_setup(struct dsa_switch *ds) } =20 /* set broadcast storm protection 10% 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 =3D BROADCAST_STORM_RATE; + storm_rate =3D (BROADCAST_STORM_VALUE * BROADCAST_STORM_PROT_RATE) / 100; + if (ksz_is_ksz8463(dev)) { + storm_mask =3D cpu_to_be16(storm_mask); + storm_rate =3D cpu_to_be16(storm_rate); + } + regmap_update_bits(ksz_regmap_16(dev), + reg16(dev, regs[S_BROADCAST_CTRL]), + storm_mask, storm_rate); =20 dev->dev_ops->config_cpu_port(ds); =20 @@ -4222,6 +4228,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 @@ -4257,6 +4274,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); @@ -4292,6 +4311,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 @@ -4439,7 +4460,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) { @@ -4453,13 +4474,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