All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 0/6] microchip: add support for ksz88x3 driver family
@ 2020-12-07 12:56 Michael Grzeschik
  2020-12-07 12:56 ` [PATCH v5 1/6] net: dsa: microchip: ksz8795: change drivers prefix to be generic Michael Grzeschik
                   ` (5 more replies)
  0 siblings, 6 replies; 17+ messages in thread
From: Michael Grzeschik @ 2020-12-07 12:56 UTC (permalink / raw)
  To: netdev
  Cc: andrew, f.fainelli, davem, kernel, matthias.schiffer,
	woojung.huh, UNGLinuxDriver

This series adds support for the ksz88x3 driver family to the dsa based ksz
drivers. The driver is making use of the already available ksz8795 driver
and moves it to an generic driver for the ksz8 based chips which have
similar functions but an totaly different register layout.

This branch is to be rebased on net-next/master

The mainlining discussion history of this branch:

v1: https://lore.kernel.org/netdev/20191107110030.25199-1-m.grzeschik@pengutronix.de/
v2: https://lore.kernel.org/netdev/20191218200831.13796-1-m.grzeschik@pengutronix.de/
v3: https://lore.kernel.org/netdev/20200508154343.6074-1-m.grzeschik@pengutronix.de/
v4: https://lore.kernel.org/netdev/20200803054442.20089-1-m.grzeschik@pengutronix.de/

Michael Grzeschik (6):
  net: dsa: microchip: ksz8795: change drivers prefix to be generic
  net: dsa: microchip: ksz8795: move cpu_select_interface to extra function
  net: dsa: microchip: ksz8795: move register offsets and shifts to separate struct
  net: dsa: microchip: ksz8795: add support for ksz88xx chips
  net: dsa: microchip: Add Microchip KSZ8863 SPI based driver support
  dt-bindings: net: dsa: document additional Microchip KSZ8863/8873 switch

 .../bindings/net/dsa/microchip,ksz.yaml       |   2 +
 drivers/net/dsa/microchip/ksz8.h              |  69 ++
 drivers/net/dsa/microchip/ksz8795.c           | 888 ++++++++++++------
 drivers/net/dsa/microchip/ksz8795_reg.h       | 125 +--
 drivers/net/dsa/microchip/ksz8795_spi.c       |  46 +-
 drivers/net/dsa/microchip/ksz_common.h        |   3 +-
 6 files changed, 730 insertions(+), 403 deletions(-)
 create mode 100644 drivers/net/dsa/microchip/ksz8.h

-- 
2.29.2


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v5 1/6] net: dsa: microchip: ksz8795: change drivers prefix to be generic
  2020-12-07 12:56 [PATCH v5 0/6] microchip: add support for ksz88x3 driver family Michael Grzeschik
@ 2020-12-07 12:56 ` Michael Grzeschik
  2020-12-07 12:56 ` [PATCH v5 2/6] net: dsa: microchip: ksz8795: move cpu_select_interface to extra function Michael Grzeschik
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 17+ messages in thread
From: Michael Grzeschik @ 2020-12-07 12:56 UTC (permalink / raw)
  To: netdev
  Cc: andrew, f.fainelli, davem, kernel, matthias.schiffer,
	woojung.huh, UNGLinuxDriver

The driver can be used on other chips of this type. To reflect
this we rename the drivers prefix from ksz8795 to ksz8.

Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>

---
v1 -> v4: - extracted this change from bigger previous patch
v4 -> v5: - removed extra unavailable variables in ksz8_r_vlan_entries
---
 drivers/net/dsa/microchip/ksz8795.c     | 222 ++++++++++++------------
 drivers/net/dsa/microchip/ksz8795_spi.c |   2 +-
 drivers/net/dsa/microchip/ksz_common.h  |   2 +-
 3 files changed, 110 insertions(+), 116 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c
index c973db101b729..1d12597a1c8a4 100644
--- a/drivers/net/dsa/microchip/ksz8795.c
+++ b/drivers/net/dsa/microchip/ksz8795.c
@@ -74,7 +74,7 @@ static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits,
 			   bits, set ? bits : 0);
 }
 
-static int ksz8795_reset_switch(struct ksz_device *dev)
+static int ksz8_reset_switch(struct ksz_device *dev)
 {
 	/* reset switch */
 	ksz_write8(dev, REG_POWER_MANAGEMENT_1,
@@ -117,8 +117,7 @@ static void ksz8795_set_prio_queue(struct ksz_device *dev, int port, int queue)
 			true);
 }
 
-static void ksz8795_r_mib_cnt(struct ksz_device *dev, int port, u16 addr,
-			      u64 *cnt)
+static void ksz8_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt)
 {
 	u16 ctrl_addr;
 	u32 data;
@@ -148,8 +147,8 @@ static void ksz8795_r_mib_cnt(struct ksz_device *dev, int port, u16 addr,
 	mutex_unlock(&dev->alu_mutex);
 }
 
-static void ksz8795_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
-			      u64 *dropped, u64 *cnt)
+static void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
+			   u64 *dropped, u64 *cnt)
 {
 	u16 ctrl_addr;
 	u32 data;
@@ -195,7 +194,7 @@ static void ksz8795_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
 	mutex_unlock(&dev->alu_mutex);
 }
 
-static void ksz8795_freeze_mib(struct ksz_device *dev, int port, bool freeze)
+static void ksz8_freeze_mib(struct ksz_device *dev, int port, bool freeze)
 {
 	/* enable the port for flush/freeze function */
 	if (freeze)
@@ -207,7 +206,7 @@ static void ksz8795_freeze_mib(struct ksz_device *dev, int port, bool freeze)
 		ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), false);
 }
 
-static void ksz8795_port_init_cnt(struct ksz_device *dev, int port)
+static void ksz8_port_init_cnt(struct ksz_device *dev, int port)
 {
 	struct ksz_port_mib *mib = &dev->ports[port].mib;
 
@@ -235,8 +234,7 @@ static void ksz8795_port_init_cnt(struct ksz_device *dev, int port)
 	memset(mib->counters, 0, dev->mib_cnt * sizeof(u64));
 }
 
-static void ksz8795_r_table(struct ksz_device *dev, int table, u16 addr,
-			    u64 *data)
+static void ksz8_r_table(struct ksz_device *dev, int table, u16 addr, u64 *data)
 {
 	u16 ctrl_addr;
 
@@ -248,8 +246,7 @@ static void ksz8795_r_table(struct ksz_device *dev, int table, u16 addr,
 	mutex_unlock(&dev->alu_mutex);
 }
 
-static void ksz8795_w_table(struct ksz_device *dev, int table, u16 addr,
-			    u64 data)
+static void ksz8_w_table(struct ksz_device *dev, int table, u16 addr, u64 data)
 {
 	u16 ctrl_addr;
 
@@ -261,7 +258,7 @@ static void ksz8795_w_table(struct ksz_device *dev, int table, u16 addr,
 	mutex_unlock(&dev->alu_mutex);
 }
 
-static int ksz8795_valid_dyn_entry(struct ksz_device *dev, u8 *data)
+static int ksz8_valid_dyn_entry(struct ksz_device *dev, u8 *data)
 {
 	int timeout = 100;
 
@@ -284,9 +281,9 @@ static int ksz8795_valid_dyn_entry(struct ksz_device *dev, u8 *data)
 	return 0;
 }
 
-static int ksz8795_r_dyn_mac_table(struct ksz_device *dev, u16 addr,
-				   u8 *mac_addr, u8 *fid, u8 *src_port,
-				   u8 *timestamp, u16 *entries)
+static int ksz8_r_dyn_mac_table(struct ksz_device *dev, u16 addr,
+				u8 *mac_addr, u8 *fid, u8 *src_port,
+				u8 *timestamp, u16 *entries)
 {
 	u32 data_hi, data_lo;
 	u16 ctrl_addr;
@@ -298,7 +295,7 @@ static int ksz8795_r_dyn_mac_table(struct ksz_device *dev, u16 addr,
 	mutex_lock(&dev->alu_mutex);
 	ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr);
 
-	rc = ksz8795_valid_dyn_entry(dev, &data);
+	rc = ksz8_valid_dyn_entry(dev, &data);
 	if (rc == -EAGAIN) {
 		if (addr == 0)
 			*entries = 0;
@@ -341,13 +338,13 @@ static int ksz8795_r_dyn_mac_table(struct ksz_device *dev, u16 addr,
 	return rc;
 }
 
-static int ksz8795_r_sta_mac_table(struct ksz_device *dev, u16 addr,
-				   struct alu_struct *alu)
+static int ksz8_r_sta_mac_table(struct ksz_device *dev, u16 addr,
+				struct alu_struct *alu)
 {
 	u32 data_hi, data_lo;
 	u64 data;
 
-	ksz8795_r_table(dev, TABLE_STATIC_MAC, addr, &data);
+	ksz8_r_table(dev, TABLE_STATIC_MAC, addr, &data);
 	data_hi = data >> 32;
 	data_lo = (u32)data;
 	if (data_hi & (STATIC_MAC_TABLE_VALID | STATIC_MAC_TABLE_OVERRIDE)) {
@@ -370,8 +367,8 @@ static int ksz8795_r_sta_mac_table(struct ksz_device *dev, u16 addr,
 	return -ENXIO;
 }
 
-static void ksz8795_w_sta_mac_table(struct ksz_device *dev, u16 addr,
-				    struct alu_struct *alu)
+static void ksz8_w_sta_mac_table(struct ksz_device *dev, u16 addr,
+				 struct alu_struct *alu)
 {
 	u32 data_hi, data_lo;
 	u64 data;
@@ -394,17 +391,17 @@ static void ksz8795_w_sta_mac_table(struct ksz_device *dev, u16 addr,
 		data_hi &= ~STATIC_MAC_TABLE_OVERRIDE;
 
 	data = (u64)data_hi << 32 | data_lo;
-	ksz8795_w_table(dev, TABLE_STATIC_MAC, addr, data);
+	ksz8_w_table(dev, TABLE_STATIC_MAC, addr, data);
 }
 
-static void ksz8795_from_vlan(u16 vlan, u8 *fid, u8 *member, u8 *valid)
+static void ksz8_from_vlan(u16 vlan, u8 *fid, u8 *member, u8 *valid)
 {
 	*fid = vlan & VLAN_TABLE_FID;
 	*member = (vlan & VLAN_TABLE_MEMBERSHIP) >> VLAN_TABLE_MEMBERSHIP_S;
 	*valid = !!(vlan & VLAN_TABLE_VALID);
 }
 
-static void ksz8795_to_vlan(u8 fid, u8 member, u8 valid, u16 *vlan)
+static void ksz8_to_vlan(u8 fid, u8 member, u8 valid, u16 *vlan)
 {
 	*vlan = fid;
 	*vlan |= (u16)member << VLAN_TABLE_MEMBERSHIP_S;
@@ -412,12 +409,12 @@ static void ksz8795_to_vlan(u8 fid, u8 member, u8 valid, u16 *vlan)
 		*vlan |= VLAN_TABLE_VALID;
 }
 
-static void ksz8795_r_vlan_entries(struct ksz_device *dev, u16 addr)
+static void ksz8_r_vlan_entries(struct ksz_device *dev, u16 addr)
 {
 	u64 data;
 	int i;
 
-	ksz8795_r_table(dev, TABLE_VLAN, addr, &data);
+	ksz8_r_table(dev, TABLE_VLAN, addr, &data);
 	addr *= dev->phy_port_cnt;
 	for (i = 0; i < dev->phy_port_cnt; i++) {
 		dev->vlan_cache[addr + i].table[0] = (u16)data;
@@ -425,7 +422,7 @@ static void ksz8795_r_vlan_entries(struct ksz_device *dev, u16 addr)
 	}
 }
 
-static void ksz8795_r_vlan_table(struct ksz_device *dev, u16 vid, u16 *vlan)
+static void ksz8_r_vlan_table(struct ksz_device *dev, u16 vid, u32 *vlan)
 {
 	int index;
 	u16 *data;
@@ -435,11 +432,11 @@ static void ksz8795_r_vlan_table(struct ksz_device *dev, u16 vid, u16 *vlan)
 	data = (u16 *)&buf;
 	addr = vid / dev->phy_port_cnt;
 	index = vid & 3;
-	ksz8795_r_table(dev, TABLE_VLAN, addr, &buf);
+	ksz8_r_table(dev, TABLE_VLAN, addr, &buf);
 	*vlan = data[index];
 }
 
-static void ksz8795_w_vlan_table(struct ksz_device *dev, u16 vid, u16 vlan)
+static void ksz8_w_vlan_table(struct ksz_device *dev, u16 vid, u32 vlan)
 {
 	int index;
 	u16 *data;
@@ -449,13 +446,13 @@ static void ksz8795_w_vlan_table(struct ksz_device *dev, u16 vid, u16 vlan)
 	data = (u16 *)&buf;
 	addr = vid / dev->phy_port_cnt;
 	index = vid & 3;
-	ksz8795_r_table(dev, TABLE_VLAN, addr, &buf);
+	ksz8_r_table(dev, TABLE_VLAN, addr, &buf);
 	data[index] = vlan;
 	dev->vlan_cache[vid].table[0] = vlan;
-	ksz8795_w_table(dev, TABLE_VLAN, addr, buf);
+	ksz8_w_table(dev, TABLE_VLAN, addr, buf);
 }
 
-static void ksz8795_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
+static void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
 {
 	u8 restart, speed, ctrl, link;
 	int processed = true;
@@ -546,7 +543,7 @@ static void ksz8795_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
 		*val = data;
 }
 
-static void ksz8795_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
+static void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
 {
 	u8 p = phy;
 	u8 restart, speed, ctrl, data;
@@ -644,15 +641,15 @@ static void ksz8795_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
 	}
 }
 
-static enum dsa_tag_protocol ksz8795_get_tag_protocol(struct dsa_switch *ds,
-						      int port,
-						      enum dsa_tag_protocol mp)
+static enum dsa_tag_protocol ksz8_get_tag_protocol(struct dsa_switch *ds,
+						   int port,
+						   enum dsa_tag_protocol mp)
 {
 	return DSA_TAG_PROTO_KSZ8795;
 }
 
-static void ksz8795_get_strings(struct dsa_switch *ds, int port,
-				u32 stringset, uint8_t *buf)
+static void ksz8_get_strings(struct dsa_switch *ds, int port,
+			     u32 stringset, uint8_t *buf)
 {
 	struct ksz_device *dev = ds->priv;
 	int i;
@@ -663,8 +660,7 @@ static void ksz8795_get_strings(struct dsa_switch *ds, int port,
 	}
 }
 
-static void ksz8795_cfg_port_member(struct ksz_device *dev, int port,
-				    u8 member)
+static void ksz8_cfg_port_member(struct ksz_device *dev, int port, u8 member)
 {
 	u8 data;
 
@@ -675,8 +671,7 @@ static void ksz8795_cfg_port_member(struct ksz_device *dev, int port,
 	dev->ports[port].member = member;
 }
 
-static void ksz8795_port_stp_state_set(struct dsa_switch *ds, int port,
-				       u8 state)
+static void ksz8_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
 {
 	struct ksz_device *dev = ds->priv;
 	int forward = dev->member;
@@ -734,7 +729,7 @@ static void ksz8795_port_stp_state_set(struct dsa_switch *ds, int port,
 	p->stp_state = state;
 	/* Port membership may share register with STP state. */
 	if (member >= 0 && member != p->member)
-		ksz8795_cfg_port_member(dev, port, (u8)member);
+		ksz8_cfg_port_member(dev, port, (u8)member);
 
 	/* Check if forwarding needs to be updated. */
 	if (state != BR_STATE_FORWARDING) {
@@ -749,7 +744,7 @@ static void ksz8795_port_stp_state_set(struct dsa_switch *ds, int port,
 		ksz_update_port_member(dev, port);
 }
 
-static void ksz8795_flush_dyn_mac_table(struct ksz_device *dev, int port)
+static void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port)
 {
 	u8 learn[DSA_MAX_PORTS];
 	int first, index, cnt;
@@ -782,9 +777,8 @@ static void ksz8795_flush_dyn_mac_table(struct ksz_device *dev, int port)
 	}
 }
 
-static int ksz8795_port_vlan_filtering(struct dsa_switch *ds, int port,
-				       bool flag,
-				       struct switchdev_trans *trans)
+static int ksz8_port_vlan_filtering(struct dsa_switch *ds, int port, bool flag,
+				    struct switchdev_trans *trans)
 {
 	struct ksz_device *dev = ds->priv;
 
@@ -796,8 +790,8 @@ static int ksz8795_port_vlan_filtering(struct dsa_switch *ds, int port,
 	return 0;
 }
 
-static void ksz8795_port_vlan_add(struct dsa_switch *ds, int port,
-				  const struct switchdev_obj_port_vlan *vlan)
+static void ksz8_port_vlan_add(struct dsa_switch *ds, int port,
+			       const struct switchdev_obj_port_vlan *vlan)
 {
 	bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
 	struct ksz_device *dev = ds->priv;
@@ -807,8 +801,8 @@ static void ksz8795_port_vlan_add(struct dsa_switch *ds, int port,
 	ksz_port_cfg(dev, port, P_TAG_CTRL, PORT_REMOVE_TAG, untagged);
 
 	for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
-		ksz8795_r_vlan_table(dev, vid, &data);
-		ksz8795_from_vlan(data, &fid, &member, &valid);
+		ksz8_r_vlan_table(dev, vid, &data);
+		ksz8_from_vlan(data, &fid, &member, &valid);
 
 		/* First time to setup the VLAN entry. */
 		if (!valid) {
@@ -818,8 +812,8 @@ static void ksz8795_port_vlan_add(struct dsa_switch *ds, int port,
 		}
 		member |= BIT(port);
 
-		ksz8795_to_vlan(fid, member, valid, &data);
-		ksz8795_w_vlan_table(dev, vid, data);
+		ksz8_to_vlan(fid, member, valid, &data);
+		ksz8_w_vlan_table(dev, vid, data);
 
 		/* change PVID */
 		if (vlan->flags & BRIDGE_VLAN_INFO_PVID)
@@ -834,8 +828,8 @@ static void ksz8795_port_vlan_add(struct dsa_switch *ds, int port,
 	}
 }
 
-static int ksz8795_port_vlan_del(struct dsa_switch *ds, int port,
-				 const struct switchdev_obj_port_vlan *vlan)
+static int ksz8_port_vlan_del(struct dsa_switch *ds, int port,
+			      const struct switchdev_obj_port_vlan *vlan)
 {
 	bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
 	struct ksz_device *dev = ds->priv;
@@ -848,8 +842,8 @@ static int ksz8795_port_vlan_del(struct dsa_switch *ds, int port,
 	ksz_port_cfg(dev, port, P_TAG_CTRL, PORT_REMOVE_TAG, untagged);
 
 	for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
-		ksz8795_r_vlan_table(dev, vid, &data);
-		ksz8795_from_vlan(data, &fid, &member, &valid);
+		ksz8_r_vlan_table(dev, vid, &data);
+		ksz8_from_vlan(data, &fid, &member, &valid);
 
 		member &= ~BIT(port);
 
@@ -862,8 +856,8 @@ static int ksz8795_port_vlan_del(struct dsa_switch *ds, int port,
 		if (pvid == vid)
 			new_pvid = 1;
 
-		ksz8795_to_vlan(fid, member, valid, &data);
-		ksz8795_w_vlan_table(dev, vid, data);
+		ksz8_to_vlan(fid, member, valid, &data);
+		ksz8_w_vlan_table(dev, vid, data);
 	}
 
 	if (new_pvid != pvid)
@@ -872,9 +866,9 @@ static int ksz8795_port_vlan_del(struct dsa_switch *ds, int port,
 	return 0;
 }
 
-static int ksz8795_port_mirror_add(struct dsa_switch *ds, int port,
-				   struct dsa_mall_mirror_tc_entry *mirror,
-				   bool ingress)
+static int ksz8_port_mirror_add(struct dsa_switch *ds, int port,
+				struct dsa_mall_mirror_tc_entry *mirror,
+				bool ingress)
 {
 	struct ksz_device *dev = ds->priv;
 
@@ -896,8 +890,8 @@ static int ksz8795_port_mirror_add(struct dsa_switch *ds, int port,
 	return 0;
 }
 
-static void ksz8795_port_mirror_del(struct dsa_switch *ds, int port,
-				    struct dsa_mall_mirror_tc_entry *mirror)
+static void ksz8_port_mirror_del(struct dsa_switch *ds, int port,
+				 struct dsa_mall_mirror_tc_entry *mirror)
 {
 	struct ksz_device *dev = ds->priv;
 	u8 data;
@@ -917,7 +911,7 @@ static void ksz8795_port_mirror_del(struct dsa_switch *ds, int port,
 			     PORT_MIRROR_SNIFFER, false);
 }
 
-static void ksz8795_port_setup(struct ksz_device *dev, int port, bool cpu_port)
+static void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port)
 {
 	struct ksz_port *p = &dev->ports[port];
 	u8 data8, member;
@@ -983,10 +977,10 @@ static void ksz8795_port_setup(struct ksz_device *dev, int port, bool cpu_port)
 	} else {
 		member = dev->host_mask | p->vid_member;
 	}
-	ksz8795_cfg_port_member(dev, port, member);
+	ksz8_cfg_port_member(dev, port, member);
 }
 
-static void ksz8795_config_cpu_port(struct dsa_switch *ds)
+static void ksz8_config_cpu_port(struct dsa_switch *ds)
 {
 	struct ksz_device *dev = ds->priv;
 	struct ksz_port *p;
@@ -1001,7 +995,7 @@ static void ksz8795_config_cpu_port(struct dsa_switch *ds)
 	p->vid_member = dev->port_mask;
 	p->on = 1;
 
-	ksz8795_port_setup(dev, dev->cpu_port, true);
+	ksz8_port_setup(dev, dev->cpu_port, true);
 	dev->member = dev->host_mask;
 
 	for (i = 0; i < dev->phy_port_cnt; i++) {
@@ -1012,7 +1006,7 @@ static void ksz8795_config_cpu_port(struct dsa_switch *ds)
 		 */
 		p->vid_member = BIT(i);
 		p->member = dev->port_mask;
-		ksz8795_port_stp_state_set(ds, i, BR_STATE_DISABLED);
+		ksz8_port_stp_state_set(ds, i, BR_STATE_DISABLED);
 
 		/* Last port may be disabled. */
 		if (i == dev->phy_port_cnt)
@@ -1036,7 +1030,7 @@ static void ksz8795_config_cpu_port(struct dsa_switch *ds)
 	}
 }
 
-static int ksz8795_setup(struct dsa_switch *ds)
+static int ksz8_setup(struct dsa_switch *ds)
 {
 	struct ksz_device *dev = ds->priv;
 	struct alu_struct alu;
@@ -1047,7 +1041,7 @@ static int ksz8795_setup(struct dsa_switch *ds)
 	if (!dev->vlan_cache)
 		return -ENOMEM;
 
-	ret = ksz8795_reset_switch(dev);
+	ret = ksz8_reset_switch(dev);
 	if (ret) {
 		dev_err(ds->dev, "failed to reset switch\n");
 		return ret;
@@ -1070,7 +1064,7 @@ static int ksz8795_setup(struct dsa_switch *ds)
 			   UNICAST_VLAN_BOUNDARY | NO_EXC_COLLISION_DROP,
 			   UNICAST_VLAN_BOUNDARY | NO_EXC_COLLISION_DROP);
 
-	ksz8795_config_cpu_port(ds);
+	ksz8_config_cpu_port(ds);
 
 	ksz_cfg(dev, REG_SW_CTRL_2, MULTICAST_STORM_DISABLE, true);
 
@@ -1085,7 +1079,7 @@ static int ksz8795_setup(struct dsa_switch *ds)
 			   BROADCAST_STORM_PROT_RATE) / 100);
 
 	for (i = 0; i < (dev->num_vlans / 4); i++)
-		ksz8795_r_vlan_entries(dev, i);
+		ksz8_r_vlan_entries(dev, i);
 
 	/* Setup STP address for STP operation. */
 	memset(&alu, 0, sizeof(alu));
@@ -1094,45 +1088,45 @@ static int ksz8795_setup(struct dsa_switch *ds)
 	alu.is_override = true;
 	alu.port_forward = dev->host_mask;
 
-	ksz8795_w_sta_mac_table(dev, 0, &alu);
+	ksz8_w_sta_mac_table(dev, 0, &alu);
 
 	ksz_init_mib_timer(dev);
 
 	return 0;
 }
 
-static const struct dsa_switch_ops ksz8795_switch_ops = {
-	.get_tag_protocol	= ksz8795_get_tag_protocol,
-	.setup			= ksz8795_setup,
+static const struct dsa_switch_ops ksz8_switch_ops = {
+	.get_tag_protocol	= ksz8_get_tag_protocol,
+	.setup			= ksz8_setup,
 	.phy_read		= ksz_phy_read16,
 	.phy_write		= ksz_phy_write16,
 	.phylink_mac_link_down	= ksz_mac_link_down,
 	.port_enable		= ksz_enable_port,
-	.get_strings		= ksz8795_get_strings,
+	.get_strings		= ksz8_get_strings,
 	.get_ethtool_stats	= ksz_get_ethtool_stats,
 	.get_sset_count		= ksz_sset_count,
 	.port_bridge_join	= ksz_port_bridge_join,
 	.port_bridge_leave	= ksz_port_bridge_leave,
-	.port_stp_state_set	= ksz8795_port_stp_state_set,
+	.port_stp_state_set	= ksz8_port_stp_state_set,
 	.port_fast_age		= ksz_port_fast_age,
-	.port_vlan_filtering	= ksz8795_port_vlan_filtering,
+	.port_vlan_filtering	= ksz8_port_vlan_filtering,
 	.port_vlan_prepare	= ksz_port_vlan_prepare,
-	.port_vlan_add		= ksz8795_port_vlan_add,
-	.port_vlan_del		= ksz8795_port_vlan_del,
+	.port_vlan_add		= ksz8_port_vlan_add,
+	.port_vlan_del		= ksz8_port_vlan_del,
 	.port_fdb_dump		= ksz_port_fdb_dump,
 	.port_mdb_prepare       = ksz_port_mdb_prepare,
 	.port_mdb_add           = ksz_port_mdb_add,
 	.port_mdb_del           = ksz_port_mdb_del,
-	.port_mirror_add	= ksz8795_port_mirror_add,
-	.port_mirror_del	= ksz8795_port_mirror_del,
+	.port_mirror_add	= ksz8_port_mirror_add,
+	.port_mirror_del	= ksz8_port_mirror_del,
 };
 
-static u32 ksz8795_get_port_addr(int port, int offset)
+static u32 ksz8_get_port_addr(int port, int offset)
 {
 	return PORT_CTRL_ADDR(port, offset);
 }
 
-static int ksz8795_switch_detect(struct ksz_device *dev)
+static int ksz8_switch_detect(struct ksz_device *dev)
 {
 	u8 id1, id2;
 	u16 id16;
@@ -1176,7 +1170,7 @@ struct ksz_chip_data {
 	int port_cnt;
 };
 
-static const struct ksz_chip_data ksz8795_switch_chips[] = {
+static const struct ksz_chip_data ksz8_switch_chips[] = {
 	{
 		.chip_id = 0x8795,
 		.dev_name = "KSZ8795",
@@ -1206,14 +1200,14 @@ static const struct ksz_chip_data ksz8795_switch_chips[] = {
 	},
 };
 
-static int ksz8795_switch_init(struct ksz_device *dev)
+static int ksz8_switch_init(struct ksz_device *dev)
 {
 	int i;
 
-	dev->ds->ops = &ksz8795_switch_ops;
+	dev->ds->ops = &ksz8_switch_ops;
 
-	for (i = 0; i < ARRAY_SIZE(ksz8795_switch_chips); i++) {
-		const struct ksz_chip_data *chip = &ksz8795_switch_chips[i];
+	for (i = 0; i < ARRAY_SIZE(ksz8_switch_chips); i++) {
+		const struct ksz_chip_data *chip = &ksz8_switch_chips[i];
 
 		if (dev->chip_id == chip->chip_id) {
 			dev->name = chip->dev_name;
@@ -1264,36 +1258,36 @@ static int ksz8795_switch_init(struct ksz_device *dev)
 	return 0;
 }
 
-static void ksz8795_switch_exit(struct ksz_device *dev)
+static void ksz8_switch_exit(struct ksz_device *dev)
 {
-	ksz8795_reset_switch(dev);
+	ksz8_reset_switch(dev);
 }
 
-static const struct ksz_dev_ops ksz8795_dev_ops = {
-	.get_port_addr = ksz8795_get_port_addr,
-	.cfg_port_member = ksz8795_cfg_port_member,
-	.flush_dyn_mac_table = ksz8795_flush_dyn_mac_table,
-	.port_setup = ksz8795_port_setup,
-	.r_phy = ksz8795_r_phy,
-	.w_phy = ksz8795_w_phy,
-	.r_dyn_mac_table = ksz8795_r_dyn_mac_table,
-	.r_sta_mac_table = ksz8795_r_sta_mac_table,
-	.w_sta_mac_table = ksz8795_w_sta_mac_table,
-	.r_mib_cnt = ksz8795_r_mib_cnt,
-	.r_mib_pkt = ksz8795_r_mib_pkt,
-	.freeze_mib = ksz8795_freeze_mib,
-	.port_init_cnt = ksz8795_port_init_cnt,
-	.shutdown = ksz8795_reset_switch,
-	.detect = ksz8795_switch_detect,
-	.init = ksz8795_switch_init,
-	.exit = ksz8795_switch_exit,
+static const struct ksz_dev_ops ksz8_dev_ops = {
+	.get_port_addr = ksz8_get_port_addr,
+	.cfg_port_member = ksz8_cfg_port_member,
+	.flush_dyn_mac_table = ksz8_flush_dyn_mac_table,
+	.port_setup = ksz8_port_setup,
+	.r_phy = ksz8_r_phy,
+	.w_phy = ksz8_w_phy,
+	.r_dyn_mac_table = ksz8_r_dyn_mac_table,
+	.r_sta_mac_table = ksz8_r_sta_mac_table,
+	.w_sta_mac_table = ksz8_w_sta_mac_table,
+	.r_mib_cnt = ksz8_r_mib_cnt,
+	.r_mib_pkt = ksz8_r_mib_pkt,
+	.freeze_mib = ksz8_freeze_mib,
+	.port_init_cnt = ksz8_port_init_cnt,
+	.shutdown = ksz8_reset_switch,
+	.detect = ksz8_switch_detect,
+	.init = ksz8_switch_init,
+	.exit = ksz8_switch_exit,
 };
 
-int ksz8795_switch_register(struct ksz_device *dev)
+int ksz8_switch_register(struct ksz_device *dev)
 {
-	return ksz_switch_register(dev, &ksz8795_dev_ops);
+	return ksz_switch_register(dev, &ksz8_dev_ops);
 }
-EXPORT_SYMBOL(ksz8795_switch_register);
+EXPORT_SYMBOL(ksz8_switch_register);
 
 MODULE_AUTHOR("Tristram Ha <Tristram.Ha@microchip.com>");
 MODULE_DESCRIPTION("Microchip KSZ8795 Series Switch DSA Driver");
diff --git a/drivers/net/dsa/microchip/ksz8795_spi.c b/drivers/net/dsa/microchip/ksz8795_spi.c
index f98432a3e2b55..45420c07c99fc 100644
--- a/drivers/net/dsa/microchip/ksz8795_spi.c
+++ b/drivers/net/dsa/microchip/ksz8795_spi.c
@@ -55,7 +55,7 @@ static int ksz8795_spi_probe(struct spi_device *spi)
 	if (ret)
 		return ret;
 
-	ret = ksz8795_switch_register(dev);
+	ret = ksz8_switch_register(dev);
 
 	/* Main DSA driver may not be started yet. */
 	if (ret)
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index 720f22275c844..49f4b882bd708 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -142,7 +142,7 @@ int ksz_switch_register(struct ksz_device *dev,
 			const struct ksz_dev_ops *ops);
 void ksz_switch_remove(struct ksz_device *dev);
 
-int ksz8795_switch_register(struct ksz_device *dev);
+int ksz8_switch_register(struct ksz_device *dev);
 int ksz9477_switch_register(struct ksz_device *dev);
 
 void ksz_update_port_member(struct ksz_device *dev, int port);
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v5 2/6] net: dsa: microchip: ksz8795: move cpu_select_interface to extra function
  2020-12-07 12:56 [PATCH v5 0/6] microchip: add support for ksz88x3 driver family Michael Grzeschik
  2020-12-07 12:56 ` [PATCH v5 1/6] net: dsa: microchip: ksz8795: change drivers prefix to be generic Michael Grzeschik
@ 2020-12-07 12:56 ` Michael Grzeschik
  2020-12-07 12:56 ` [PATCH v5 3/6] net: dsa: microchip: ksz8795: move register offsets and shifts to separate struct Michael Grzeschik
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 17+ messages in thread
From: Michael Grzeschik @ 2020-12-07 12:56 UTC (permalink / raw)
  To: netdev
  Cc: andrew, f.fainelli, davem, kernel, matthias.schiffer,
	woojung.huh, UNGLinuxDriver

This patch moves the cpu interface selection code to a individual
function specific for ksz8795. It will make it simpler to customize the
code path for different switches supported by this driver.

Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>

---
v1 -> v5: - extracted this from previous bigger patch
---
 drivers/net/dsa/microchip/ksz8795.c | 92 ++++++++++++++++-------------
 1 file changed, 50 insertions(+), 42 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c
index 1d12597a1c8a4..53cb41087a594 100644
--- a/drivers/net/dsa/microchip/ksz8795.c
+++ b/drivers/net/dsa/microchip/ksz8795.c
@@ -911,10 +911,58 @@ static void ksz8_port_mirror_del(struct dsa_switch *ds, int port,
 			     PORT_MIRROR_SNIFFER, false);
 }
 
+static void ksz8795_cpu_interface_select(struct ksz_device *dev, int port)
+{
+	struct ksz_port *p = &dev->ports[port];
+	u8 data8;
+
+	if (!p->interface && dev->compat_interface) {
+		dev_warn(dev->dev,
+			 "Using legacy switch \"phy-mode\" property, because it is missing on port %d node. "
+			 "Please update your device tree.\n",
+			 port);
+		p->interface = dev->compat_interface;
+	}
+
+	/* Configure MII interface for proper network communication. */
+	ksz_read8(dev, REG_PORT_5_CTRL_6, &data8);
+	data8 &= ~PORT_INTERFACE_TYPE;
+	data8 &= ~PORT_GMII_1GPS_MODE;
+	switch (p->interface) {
+	case PHY_INTERFACE_MODE_MII:
+		p->phydev.speed = SPEED_100;
+		break;
+	case PHY_INTERFACE_MODE_RMII:
+		data8 |= PORT_INTERFACE_RMII;
+		p->phydev.speed = SPEED_100;
+		break;
+	case PHY_INTERFACE_MODE_GMII:
+		data8 |= PORT_GMII_1GPS_MODE;
+		data8 |= PORT_INTERFACE_GMII;
+		p->phydev.speed = SPEED_1000;
+		break;
+	default:
+		data8 &= ~PORT_RGMII_ID_IN_ENABLE;
+		data8 &= ~PORT_RGMII_ID_OUT_ENABLE;
+		if (p->interface == PHY_INTERFACE_MODE_RGMII_ID ||
+		    p->interface == PHY_INTERFACE_MODE_RGMII_RXID)
+			data8 |= PORT_RGMII_ID_IN_ENABLE;
+		if (p->interface == PHY_INTERFACE_MODE_RGMII_ID ||
+		    p->interface == PHY_INTERFACE_MODE_RGMII_TXID)
+			data8 |= PORT_RGMII_ID_OUT_ENABLE;
+		data8 |= PORT_GMII_1GPS_MODE;
+		data8 |= PORT_INTERFACE_RGMII;
+		p->phydev.speed = SPEED_1000;
+		break;
+	}
+	ksz_write8(dev, REG_PORT_5_CTRL_6, data8);
+	p->phydev.duplex = 1;
+}
+
 static void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port)
 {
 	struct ksz_port *p = &dev->ports[port];
-	u8 data8, member;
+	u8 member;
 
 	/* enable broadcast storm limit */
 	ksz_port_cfg(dev, port, P_BCAST_STORM_CTRL, PORT_BROADCAST_STORM, true);
@@ -931,47 +979,7 @@ static void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port)
 	ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_802_1P_ENABLE, true);
 
 	if (cpu_port) {
-		if (!p->interface && dev->compat_interface) {
-			dev_warn(dev->dev,
-				 "Using legacy switch \"phy-mode\" property, because it is missing on port %d node. "
-				 "Please update your device tree.\n",
-				 port);
-			p->interface = dev->compat_interface;
-		}
-
-		/* Configure MII interface for proper network communication. */
-		ksz_read8(dev, REG_PORT_5_CTRL_6, &data8);
-		data8 &= ~PORT_INTERFACE_TYPE;
-		data8 &= ~PORT_GMII_1GPS_MODE;
-		switch (p->interface) {
-		case PHY_INTERFACE_MODE_MII:
-			p->phydev.speed = SPEED_100;
-			break;
-		case PHY_INTERFACE_MODE_RMII:
-			data8 |= PORT_INTERFACE_RMII;
-			p->phydev.speed = SPEED_100;
-			break;
-		case PHY_INTERFACE_MODE_GMII:
-			data8 |= PORT_GMII_1GPS_MODE;
-			data8 |= PORT_INTERFACE_GMII;
-			p->phydev.speed = SPEED_1000;
-			break;
-		default:
-			data8 &= ~PORT_RGMII_ID_IN_ENABLE;
-			data8 &= ~PORT_RGMII_ID_OUT_ENABLE;
-			if (p->interface == PHY_INTERFACE_MODE_RGMII_ID ||
-			    p->interface == PHY_INTERFACE_MODE_RGMII_RXID)
-				data8 |= PORT_RGMII_ID_IN_ENABLE;
-			if (p->interface == PHY_INTERFACE_MODE_RGMII_ID ||
-			    p->interface == PHY_INTERFACE_MODE_RGMII_TXID)
-				data8 |= PORT_RGMII_ID_OUT_ENABLE;
-			data8 |= PORT_GMII_1GPS_MODE;
-			data8 |= PORT_INTERFACE_RGMII;
-			p->phydev.speed = SPEED_1000;
-			break;
-		}
-		ksz_write8(dev, REG_PORT_5_CTRL_6, data8);
-		p->phydev.duplex = 1;
+		ksz8795_cpu_interface_select(dev, port);
 
 		member = dev->port_mask;
 	} else {
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v5 3/6] net: dsa: microchip: ksz8795: move register offsets and shifts to separate struct
  2020-12-07 12:56 [PATCH v5 0/6] microchip: add support for ksz88x3 driver family Michael Grzeschik
  2020-12-07 12:56 ` [PATCH v5 1/6] net: dsa: microchip: ksz8795: change drivers prefix to be generic Michael Grzeschik
  2020-12-07 12:56 ` [PATCH v5 2/6] net: dsa: microchip: ksz8795: move cpu_select_interface to extra function Michael Grzeschik
@ 2020-12-07 12:56 ` Michael Grzeschik
  2020-12-07 14:11     ` kernel test robot
                     ` (3 more replies)
  2020-12-07 12:56 ` [PATCH v5 4/6] net: dsa: microchip: ksz8795: add support for ksz88xx chips Michael Grzeschik
                   ` (2 subsequent siblings)
  5 siblings, 4 replies; 17+ messages in thread
From: Michael Grzeschik @ 2020-12-07 12:56 UTC (permalink / raw)
  To: netdev
  Cc: andrew, f.fainelli, davem, kernel, matthias.schiffer,
	woojung.huh, UNGLinuxDriver

In order to get this driver used with other switches the functions need
to use different offsets and register shifts. This patch changes the
direct use of the register defines to register description structures,
which can be set depending on the chips register layout.

Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>

---
v1 -> v4: - extracted this change from bigger previous patch
v4 -> v5: - added missing variables in ksz8_r_vlan_entries
          - moved shifts, masks and registers to arrays indexed by enums
	  - using unsigned types where possible
---
 drivers/net/dsa/microchip/ksz8.h        |  69 +++++++
 drivers/net/dsa/microchip/ksz8795.c     | 261 +++++++++++++++++-------
 drivers/net/dsa/microchip/ksz8795_reg.h |  85 --------
 3 files changed, 253 insertions(+), 162 deletions(-)
 create mode 100644 drivers/net/dsa/microchip/ksz8.h

diff --git a/drivers/net/dsa/microchip/ksz8.h b/drivers/net/dsa/microchip/ksz8.h
new file mode 100644
index 0000000000000..d3e89c27e22aa
--- /dev/null
+++ b/drivers/net/dsa/microchip/ksz8.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Microchip KSZ8XXX series register access
+ *
+ * Copyright (C) 2019 Pengutronix, Michael Grzeschik <kernel@pengutronix.de>
+ */
+
+#ifndef __KSZ8XXX_H
+#define __KSZ8XXX_H
+#include <linux/kernel.h>
+
+enum ksz_regs {
+	REG_IND_CTRL_0,
+	REG_IND_DATA_8,
+	REG_IND_DATA_CHECK,
+	REG_IND_DATA_HI,
+	REG_IND_DATA_LO,
+	REG_IND_MIB_CHECK,
+	P_FORCE_CTRL,
+	P_LINK_STATUS,
+	P_LOCAL_CTRL,
+	P_NEG_RESTART_CTRL,
+	P_REMOTE_STATUS,
+	P_SPEED_STATUS,
+	S_TAIL_TAG_CTRL,
+};
+
+enum ksz_masks {
+	PORT_802_1P_REMAPPING,
+	SW_TAIL_TAG_ENABLE,
+	MIB_COUNTER_OVERFLOW,
+	MIB_COUNTER_VALID,
+	VLAN_TABLE_FID,
+	VLAN_TABLE_MEMBERSHIP,
+	VLAN_TABLE_VALID,
+	STATIC_MAC_TABLE_VALID,
+	STATIC_MAC_TABLE_USE_FID,
+	STATIC_MAC_TABLE_FID,
+	STATIC_MAC_TABLE_OVERRIDE,
+	STATIC_MAC_TABLE_FWD_PORTS,
+	DYNAMIC_MAC_TABLE_ENTRIES_H,
+	DYNAMIC_MAC_TABLE_MAC_EMPTY,
+	DYNAMIC_MAC_TABLE_NOT_READY,
+	DYNAMIC_MAC_TABLE_ENTRIES,
+	DYNAMIC_MAC_TABLE_FID,
+	DYNAMIC_MAC_TABLE_SRC_PORT,
+	DYNAMIC_MAC_TABLE_TIMESTAMP,
+};
+
+enum ksz_shifts {
+	VLAN_TABLE_MEMBERSHIP_S,
+	VLAN_TABLE,
+	STATIC_MAC_FWD_PORTS,
+	STATIC_MAC_FID,
+	DYNAMIC_MAC_ENTRIES_H,
+	DYNAMIC_MAC_ENTRIES,
+	DYNAMIC_MAC_FID,
+	DYNAMIC_MAC_TIMESTAMP,
+	DYNAMIC_MAC_SRC_PORT,
+};
+
+struct ksz8 {
+	const u8 *regs;
+	const u32 *masks;
+	const u8 *shifts;
+	void *priv;
+};
+
+#endif
diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c
index 53cb41087a594..127498a9b8f72 100644
--- a/drivers/net/dsa/microchip/ksz8795.c
+++ b/drivers/net/dsa/microchip/ksz8795.c
@@ -20,6 +20,57 @@
 
 #include "ksz_common.h"
 #include "ksz8795_reg.h"
+#include "ksz8.h"
+
+static const u8 ksz8795_regs[] = {
+	[REG_IND_CTRL_0]		= 0x6E,
+	[REG_IND_DATA_8]		= 0x70,
+	[REG_IND_DATA_CHECK]		= 0x72,
+	[REG_IND_DATA_HI]		= 0x71,
+	[REG_IND_DATA_LO]		= 0x75,
+	[REG_IND_MIB_CHECK]		= 0x74,
+	[P_FORCE_CTRL]			= 0x0C,
+	[P_LINK_STATUS]			= 0x0E,
+	[P_LOCAL_CTRL]			= 0x07,
+	[P_NEG_RESTART_CTRL]		= 0x0D,
+	[P_REMOTE_STATUS]		= 0x08,
+	[P_SPEED_STATUS]		= 0x09,
+	[S_TAIL_TAG_CTRL]		= 0x0C,
+};
+
+static const u32 ksz8795_masks[] = {
+	[PORT_802_1P_REMAPPING]		= BIT(7),
+	[SW_TAIL_TAG_ENABLE]		= BIT(1),
+	[MIB_COUNTER_OVERFLOW]		= BIT(6),
+	[MIB_COUNTER_VALID]		= BIT(5),
+	[VLAN_TABLE_FID]		= GENMASK(6, 0),
+	[VLAN_TABLE_MEMBERSHIP]		= GENMASK(11, 7),
+	[VLAN_TABLE_VALID]		= BIT(12),
+	[STATIC_MAC_TABLE_VALID]	= BIT(21),
+	[STATIC_MAC_TABLE_USE_FID]	= BIT(23),
+	[STATIC_MAC_TABLE_FID]		= GENMASK(30, 24),
+	[STATIC_MAC_TABLE_OVERRIDE]	= BIT(26),
+	[STATIC_MAC_TABLE_FWD_PORTS]	= GENMASK(24, 20),
+	[DYNAMIC_MAC_TABLE_ENTRIES_H]	= GENMASK(6, 0),
+	[DYNAMIC_MAC_TABLE_MAC_EMPTY]	= BIT(8),
+	[DYNAMIC_MAC_TABLE_NOT_READY]	= BIT(7),
+	[DYNAMIC_MAC_TABLE_ENTRIES]	= GENMASK(31, 29),
+	[DYNAMIC_MAC_TABLE_FID]		= GENMASK(26, 20),
+	[DYNAMIC_MAC_TABLE_SRC_PORT]	= GENMASK(26, 24),
+	[DYNAMIC_MAC_TABLE_TIMESTAMP]	= GENMASK(28, 27),
+};
+
+static const u8 ksz8795_shifts[] = {
+	[VLAN_TABLE_MEMBERSHIP]		= 7,
+	[VLAN_TABLE]			= 16,
+	[STATIC_MAC_FWD_PORTS]		= 16,
+	[STATIC_MAC_FID]		= 24,
+	[DYNAMIC_MAC_ENTRIES_H]		= 3,
+	[DYNAMIC_MAC_ENTRIES]		= 29,
+	[DYNAMIC_MAC_FID]		= 16,
+	[DYNAMIC_MAC_TIMESTAMP]		= 27,
+	[DYNAMIC_MAC_SRC_PORT]		= 24,
+};
 
 static const struct {
 	char string[ETH_GSTRING_LEN];
@@ -119,6 +170,9 @@ static void ksz8795_set_prio_queue(struct ksz_device *dev, int port, int queue)
 
 static void ksz8_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt)
 {
+	struct ksz8 *ksz8 = dev->priv;
+	const u8 *regs = ksz8->regs;
+	const u32 *masks = ksz8->masks;
 	u16 ctrl_addr;
 	u32 data;
 	u8 check;
@@ -128,17 +182,17 @@ static void ksz8_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt)
 	ctrl_addr |= IND_ACC_TABLE(TABLE_MIB | TABLE_READ);
 
 	mutex_lock(&dev->alu_mutex);
-	ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr);
+	ksz_write16(dev, regs[REG_IND_CTRL_0], ctrl_addr);
 
 	/* It is almost guaranteed to always read the valid bit because of
 	 * slow SPI speed.
 	 */
 	for (loop = 2; loop > 0; loop--) {
-		ksz_read8(dev, REG_IND_MIB_CHECK, &check);
+		ksz_read8(dev, regs[REG_IND_MIB_CHECK], &check);
 
-		if (check & MIB_COUNTER_VALID) {
-			ksz_read32(dev, REG_IND_DATA_LO, &data);
-			if (check & MIB_COUNTER_OVERFLOW)
+		if (check & masks[MIB_COUNTER_VALID]) {
+			ksz_read32(dev, regs[REG_IND_DATA_LO], &data);
+			if (check & masks[MIB_COUNTER_OVERFLOW])
 				*cnt += MIB_COUNTER_VALUE + 1;
 			*cnt += data & MIB_COUNTER_VALUE;
 			break;
@@ -150,6 +204,9 @@ static void ksz8_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt)
 static void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
 			   u64 *dropped, u64 *cnt)
 {
+	struct ksz8 *ksz8 = dev->priv;
+	const u8 *regs = ksz8->regs;
+	const u32 *masks = ksz8->masks;
 	u16 ctrl_addr;
 	u32 data;
 	u8 check;
@@ -161,16 +218,16 @@ static void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
 	ctrl_addr |= IND_ACC_TABLE(TABLE_MIB | TABLE_READ);
 
 	mutex_lock(&dev->alu_mutex);
-	ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr);
+	ksz_write16(dev, regs[REG_IND_CTRL_0], ctrl_addr);
 
 	/* It is almost guaranteed to always read the valid bit because of
 	 * slow SPI speed.
 	 */
 	for (loop = 2; loop > 0; loop--) {
-		ksz_read8(dev, REG_IND_MIB_CHECK, &check);
+		ksz_read8(dev, regs[REG_IND_MIB_CHECK], &check);
 
-		if (check & MIB_COUNTER_VALID) {
-			ksz_read32(dev, REG_IND_DATA_LO, &data);
+		if (check & masks[MIB_COUNTER_VALID]) {
+			ksz_read32(dev, regs[REG_IND_DATA_LO], &data);
 			if (addr < 2) {
 				u64 total;
 
@@ -178,13 +235,13 @@ static void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
 				total <<= 32;
 				*cnt += total;
 				*cnt += data;
-				if (check & MIB_COUNTER_OVERFLOW) {
+				if (check & masks[MIB_COUNTER_OVERFLOW]) {
 					total = MIB_TOTAL_BYTES_H + 1;
 					total <<= 32;
 					*cnt += total;
 				}
 			} else {
-				if (check & MIB_COUNTER_OVERFLOW)
+				if (check & masks[MIB_COUNTER_OVERFLOW])
 					*cnt += MIB_PACKET_DROPPED + 1;
 				*cnt += data & MIB_PACKET_DROPPED;
 			}
@@ -236,46 +293,53 @@ static void ksz8_port_init_cnt(struct ksz_device *dev, int port)
 
 static void ksz8_r_table(struct ksz_device *dev, int table, u16 addr, u64 *data)
 {
+	struct ksz8 *ksz8 = dev->priv;
+	const u8 *regs = ksz8->regs;
 	u16 ctrl_addr;
 
 	ctrl_addr = IND_ACC_TABLE(table | TABLE_READ) | addr;
 
 	mutex_lock(&dev->alu_mutex);
-	ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr);
-	ksz_read64(dev, REG_IND_DATA_HI, data);
+	ksz_write16(dev, regs[REG_IND_CTRL_0], ctrl_addr);
+	ksz_read64(dev, regs[REG_IND_DATA_HI], data);
 	mutex_unlock(&dev->alu_mutex);
 }
 
 static void ksz8_w_table(struct ksz_device *dev, int table, u16 addr, u64 data)
 {
+	struct ksz8 *ksz8 = dev->priv;
+	const u8 *regs = ksz8->regs;
 	u16 ctrl_addr;
 
 	ctrl_addr = IND_ACC_TABLE(table) | addr;
 
 	mutex_lock(&dev->alu_mutex);
-	ksz_write64(dev, REG_IND_DATA_HI, data);
-	ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr);
+	ksz_write64(dev, regs[REG_IND_DATA_HI], data);
+	ksz_write16(dev, regs[REG_IND_CTRL_0], ctrl_addr);
 	mutex_unlock(&dev->alu_mutex);
 }
 
 static int ksz8_valid_dyn_entry(struct ksz_device *dev, u8 *data)
 {
+	struct ksz8 *ksz8 = dev->priv;
+	const u8 *regs = ksz8->regs;
+	const u32 *masks = ksz8->masks;
 	int timeout = 100;
 
 	do {
-		ksz_read8(dev, REG_IND_DATA_CHECK, data);
+		ksz_read8(dev, regs[REG_IND_DATA_CHECK], data);
 		timeout--;
-	} while ((*data & DYNAMIC_MAC_TABLE_NOT_READY) && timeout);
+	} while ((*data & masks[DYNAMIC_MAC_TABLE_NOT_READY]) && timeout);
 
 	/* Entry is not ready for accessing. */
-	if (*data & DYNAMIC_MAC_TABLE_NOT_READY) {
+	if (*data & masks[DYNAMIC_MAC_TABLE_NOT_READY]) {
 		return -EAGAIN;
 	/* Entry is ready for accessing. */
 	} else {
-		ksz_read8(dev, REG_IND_DATA_8, data);
+		ksz_read8(dev, regs[REG_IND_DATA_8], data);
 
 		/* There is no valid entry in the table. */
-		if (*data & DYNAMIC_MAC_TABLE_MAC_EMPTY)
+		if (*data & masks[DYNAMIC_MAC_TABLE_MAC_EMPTY])
 			return -ENXIO;
 	}
 	return 0;
@@ -285,6 +349,10 @@ static int ksz8_r_dyn_mac_table(struct ksz_device *dev, u16 addr,
 				u8 *mac_addr, u8 *fid, u8 *src_port,
 				u8 *timestamp, u16 *entries)
 {
+	struct ksz8 *ksz8 = dev->priv;
+	const u8 *regs = ksz8->regs;
+	const u32 *masks = ksz8->masks;
+	const u8 *shifts = ksz8->shifts;
 	u32 data_hi, data_lo;
 	u16 ctrl_addr;
 	u8 data;
@@ -293,7 +361,7 @@ static int ksz8_r_dyn_mac_table(struct ksz_device *dev, u16 addr,
 	ctrl_addr = IND_ACC_TABLE(TABLE_DYNAMIC_MAC | TABLE_READ) | addr;
 
 	mutex_lock(&dev->alu_mutex);
-	ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr);
+	ksz_write16(dev, regs[REG_IND_CTRL_0], ctrl_addr);
 
 	rc = ksz8_valid_dyn_entry(dev, &data);
 	if (rc == -EAGAIN) {
@@ -306,23 +374,23 @@ static int ksz8_r_dyn_mac_table(struct ksz_device *dev, u16 addr,
 		u64 buf = 0;
 		int cnt;
 
-		ksz_read64(dev, REG_IND_DATA_HI, &buf);
+		ksz_read64(dev, regs[REG_IND_DATA_HI], &buf);
 		data_hi = (u32)(buf >> 32);
 		data_lo = (u32)buf;
 
 		/* Check out how many valid entry in the table. */
-		cnt = data & DYNAMIC_MAC_TABLE_ENTRIES_H;
-		cnt <<= DYNAMIC_MAC_ENTRIES_H_S;
-		cnt |= (data_hi & DYNAMIC_MAC_TABLE_ENTRIES) >>
-			DYNAMIC_MAC_ENTRIES_S;
+		cnt = data & masks[DYNAMIC_MAC_TABLE_ENTRIES_H];
+		cnt <<= shifts[DYNAMIC_MAC_ENTRIES_H];
+		cnt |= (data_hi & masks[DYNAMIC_MAC_TABLE_ENTRIES]) >>
+			shifts[DYNAMIC_MAC_ENTRIES];
 		*entries = cnt + 1;
 
-		*fid = (data_hi & DYNAMIC_MAC_TABLE_FID) >>
-			DYNAMIC_MAC_FID_S;
-		*src_port = (data_hi & DYNAMIC_MAC_TABLE_SRC_PORT) >>
-			DYNAMIC_MAC_SRC_PORT_S;
-		*timestamp = (data_hi & DYNAMIC_MAC_TABLE_TIMESTAMP) >>
-			DYNAMIC_MAC_TIMESTAMP_S;
+		*fid = (data_hi & masks[DYNAMIC_MAC_TABLE_FID]) >>
+			shifts[DYNAMIC_MAC_FID];
+		*src_port = (data_hi & masks[DYNAMIC_MAC_TABLE_SRC_PORT]) >>
+			shifts[DYNAMIC_MAC_SRC_PORT];
+		*timestamp = (data_hi & masks[DYNAMIC_MAC_TABLE_TIMESTAMP]) >>
+			shifts[DYNAMIC_MAC_TIMESTAMP];
 
 		mac_addr[5] = (u8)data_lo;
 		mac_addr[4] = (u8)(data_lo >> 8);
@@ -341,27 +409,34 @@ static int ksz8_r_dyn_mac_table(struct ksz_device *dev, u16 addr,
 static int ksz8_r_sta_mac_table(struct ksz_device *dev, u16 addr,
 				struct alu_struct *alu)
 {
+	struct ksz8 *ksz8 = dev->priv;
+	const u32 *masks = ksz8->masks;
+	const u8 *shifts = ksz8->shifts;
 	u32 data_hi, data_lo;
 	u64 data;
 
 	ksz8_r_table(dev, TABLE_STATIC_MAC, addr, &data);
 	data_hi = data >> 32;
 	data_lo = (u32)data;
-	if (data_hi & (STATIC_MAC_TABLE_VALID | STATIC_MAC_TABLE_OVERRIDE)) {
+	if (data_hi & (masks[STATIC_MAC_TABLE_VALID] |
+			masks[STATIC_MAC_TABLE_OVERRIDE])) {
 		alu->mac[5] = (u8)data_lo;
 		alu->mac[4] = (u8)(data_lo >> 8);
 		alu->mac[3] = (u8)(data_lo >> 16);
 		alu->mac[2] = (u8)(data_lo >> 24);
 		alu->mac[1] = (u8)data_hi;
 		alu->mac[0] = (u8)(data_hi >> 8);
-		alu->port_forward = (data_hi & STATIC_MAC_TABLE_FWD_PORTS) >>
-			STATIC_MAC_FWD_PORTS_S;
+		alu->port_forward =
+			(data_hi & masks[STATIC_MAC_TABLE_FWD_PORTS]) >>
+				shifts[STATIC_MAC_FWD_PORTS];
 		alu->is_override =
-			(data_hi & STATIC_MAC_TABLE_OVERRIDE) ? 1 : 0;
+			(data_hi & masks[STATIC_MAC_TABLE_OVERRIDE]) ? 1 : 0;
 		data_hi >>= 1;
-		alu->is_use_fid = (data_hi & STATIC_MAC_TABLE_USE_FID) ? 1 : 0;
-		alu->fid = (data_hi & STATIC_MAC_TABLE_FID) >>
-			STATIC_MAC_FID_S;
+		alu->is_static = true;
+		alu->is_use_fid =
+			(data_hi & masks[STATIC_MAC_TABLE_USE_FID]) ? 1 : 0;
+		alu->fid = (data_hi & masks[STATIC_MAC_TABLE_FID]) >>
+				shifts[STATIC_MAC_FID];
 		return 0;
 	}
 	return -ENXIO;
@@ -370,6 +445,9 @@ static int ksz8_r_sta_mac_table(struct ksz_device *dev, u16 addr,
 static void ksz8_w_sta_mac_table(struct ksz_device *dev, u16 addr,
 				 struct alu_struct *alu)
 {
+	struct ksz8 *ksz8 = dev->priv;
+	const u32 *masks = ksz8->masks;
+	const u8 *shifts = ksz8->shifts;
 	u32 data_hi, data_lo;
 	u64 data;
 
@@ -377,40 +455,53 @@ static void ksz8_w_sta_mac_table(struct ksz_device *dev, u16 addr,
 		((u32)alu->mac[3] << 16) |
 		((u32)alu->mac[4] << 8) | alu->mac[5];
 	data_hi = ((u32)alu->mac[0] << 8) | alu->mac[1];
-	data_hi |= (u32)alu->port_forward << STATIC_MAC_FWD_PORTS_S;
+	data_hi |= (u32)alu->port_forward << shifts[STATIC_MAC_FWD_PORTS];
 
 	if (alu->is_override)
-		data_hi |= STATIC_MAC_TABLE_OVERRIDE;
+		data_hi |= masks[STATIC_MAC_TABLE_OVERRIDE];
 	if (alu->is_use_fid) {
-		data_hi |= STATIC_MAC_TABLE_USE_FID;
-		data_hi |= (u32)alu->fid << STATIC_MAC_FID_S;
+		data_hi |= masks[STATIC_MAC_TABLE_USE_FID];
+		data_hi |= (u32)alu->fid << shifts[STATIC_MAC_FID];
 	}
 	if (alu->is_static)
-		data_hi |= STATIC_MAC_TABLE_VALID;
+		data_hi |= masks[STATIC_MAC_TABLE_VALID];
 	else
-		data_hi &= ~STATIC_MAC_TABLE_OVERRIDE;
+		data_hi &= ~masks[STATIC_MAC_TABLE_OVERRIDE];
 
 	data = (u64)data_hi << 32 | data_lo;
 	ksz8_w_table(dev, TABLE_STATIC_MAC, addr, data);
 }
 
-static void ksz8_from_vlan(u16 vlan, u8 *fid, u8 *member, u8 *valid)
+static void ksz8_from_vlan(struct ksz_device *dev, u32 vlan, u8 *fid,
+			   u8 *member, u8 *valid)
 {
-	*fid = vlan & VLAN_TABLE_FID;
-	*member = (vlan & VLAN_TABLE_MEMBERSHIP) >> VLAN_TABLE_MEMBERSHIP_S;
-	*valid = !!(vlan & VLAN_TABLE_VALID);
+	struct ksz8 *ksz8 = dev->priv;
+	const u32 *masks = ksz8->masks;
+	const u8 *shifts = ksz8->shifts;
+
+	*fid = vlan & masks[VLAN_TABLE_FID];
+	*member = (vlan & masks[VLAN_TABLE_MEMBERSHIP]) >>
+			shifts[VLAN_TABLE_MEMBERSHIP_S];
+	*valid = !!(vlan & masks[VLAN_TABLE_VALID]);
 }
 
-static void ksz8_to_vlan(u8 fid, u8 member, u8 valid, u16 *vlan)
+static void ksz8_to_vlan(struct ksz_device *dev, u8 fid, u8 member, u8 valid,
+			 u32 *vlan)
 {
+	struct ksz8 *ksz8 = dev->priv;
+	const u32 *masks = ksz8->masks;
+	const u8 *shifts = ksz8->shifts;
+
 	*vlan = fid;
-	*vlan |= (u16)member << VLAN_TABLE_MEMBERSHIP_S;
+	*vlan |= (u16)member << shifts[VLAN_TABLE_MEMBERSHIP_S];
 	if (valid)
-		*vlan |= VLAN_TABLE_VALID;
+		*vlan |= masks[VLAN_TABLE_VALID];
 }
 
 static void ksz8_r_vlan_entries(struct ksz_device *dev, u16 addr)
 {
+	struct ksz8 *ksz8 = dev->priv;
+	const u8 *shifts = ksz8->shifts;
 	u64 data;
 	int i;
 
@@ -418,7 +509,7 @@ static void ksz8_r_vlan_entries(struct ksz_device *dev, u16 addr)
 	addr *= dev->phy_port_cnt;
 	for (i = 0; i < dev->phy_port_cnt; i++) {
 		dev->vlan_cache[addr + i].table[0] = (u16)data;
-		data >>= VLAN_TABLE_S;
+		data >>= shifts[VLAN_TABLE];
 	}
 }
 
@@ -454,6 +545,8 @@ static void ksz8_w_vlan_table(struct ksz_device *dev, u16 vid, u32 vlan)
 
 static void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
 {
+	struct ksz8 *ksz8 = dev->priv;
+	const u8 *regs = ksz8->regs;
 	u8 restart, speed, ctrl, link;
 	int processed = true;
 	u16 data = 0;
@@ -461,9 +554,9 @@ static void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
 
 	switch (reg) {
 	case PHY_REG_CTRL:
-		ksz_pread8(dev, p, P_NEG_RESTART_CTRL, &restart);
-		ksz_pread8(dev, p, P_SPEED_STATUS, &speed);
-		ksz_pread8(dev, p, P_FORCE_CTRL, &ctrl);
+		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);
 		if (restart & PORT_PHY_LOOPBACK)
 			data |= PHY_LOOPBACK;
 		if (ctrl & PORT_FORCE_100_MBIT)
@@ -488,7 +581,7 @@ static void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
 			data |= PHY_LED_DISABLE;
 		break;
 	case PHY_REG_STATUS:
-		ksz_pread8(dev, p, P_LINK_STATUS, &link);
+		ksz_pread8(dev, p, regs[P_LINK_STATUS], &link);
 		data = PHY_100BTX_FD_CAPABLE |
 		       PHY_100BTX_CAPABLE |
 		       PHY_10BT_FD_CAPABLE |
@@ -506,7 +599,7 @@ static void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
 		data = KSZ8795_ID_LO;
 		break;
 	case PHY_REG_AUTO_NEGOTIATION:
-		ksz_pread8(dev, p, P_LOCAL_CTRL, &ctrl);
+		ksz_pread8(dev, p, regs[P_LOCAL_CTRL], &ctrl);
 		data = PHY_AUTO_NEG_802_3;
 		if (ctrl & PORT_AUTO_NEG_SYM_PAUSE)
 			data |= PHY_AUTO_NEG_SYM_PAUSE;
@@ -520,7 +613,7 @@ static void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
 			data |= PHY_AUTO_NEG_10BT;
 		break;
 	case PHY_REG_REMOTE_CAPABILITY:
-		ksz_pread8(dev, p, P_REMOTE_STATUS, &link);
+		ksz_pread8(dev, p, regs[P_REMOTE_STATUS], &link);
 		data = PHY_AUTO_NEG_802_3;
 		if (link & PORT_REMOTE_SYM_PAUSE)
 			data |= PHY_AUTO_NEG_SYM_PAUSE;
@@ -546,6 +639,8 @@ static void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
 static void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
 {
 	u8 p = phy;
+	struct ksz8 *ksz8 = dev->priv;
+	const u8 *regs = ksz8->regs;
 	u8 restart, speed, ctrl, data;
 
 	switch (reg) {
@@ -554,15 +649,15 @@ static void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
 		/* Do not support PHY reset function. */
 		if (val & PHY_RESET)
 			break;
-		ksz_pread8(dev, p, P_SPEED_STATUS, &speed);
+		ksz_pread8(dev, p, regs[P_SPEED_STATUS], &speed);
 		data = speed;
 		if (val & PHY_HP_MDIX)
 			data |= PORT_HP_MDIX;
 		else
 			data &= ~PORT_HP_MDIX;
 		if (data != speed)
-			ksz_pwrite8(dev, p, P_SPEED_STATUS, data);
-		ksz_pread8(dev, p, P_FORCE_CTRL, &ctrl);
+			ksz_pwrite8(dev, p, regs[P_SPEED_STATUS], data);
+		ksz_pread8(dev, p, regs[P_FORCE_CTRL], &ctrl);
 		data = ctrl;
 		if (!(val & PHY_AUTO_NEG_ENABLE))
 			data |= PORT_AUTO_NEG_DISABLE;
@@ -581,8 +676,8 @@ static void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
 		else
 			data &= ~PORT_FORCE_FULL_DUPLEX;
 		if (data != ctrl)
-			ksz_pwrite8(dev, p, P_FORCE_CTRL, data);
-		ksz_pread8(dev, p, P_NEG_RESTART_CTRL, &restart);
+			ksz_pwrite8(dev, p, regs[P_FORCE_CTRL], data);
+		ksz_pread8(dev, p, regs[P_NEG_RESTART_CTRL], &restart);
 		data = restart;
 		if (val & PHY_LED_DISABLE)
 			data |= PORT_LED_OFF;
@@ -613,10 +708,10 @@ static void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
 		else
 			data &= ~PORT_PHY_LOOPBACK;
 		if (data != restart)
-			ksz_pwrite8(dev, p, P_NEG_RESTART_CTRL, data);
+			ksz_pwrite8(dev, p, regs[P_NEG_RESTART_CTRL], data);
 		break;
 	case PHY_REG_AUTO_NEGOTIATION:
-		ksz_pread8(dev, p, P_LOCAL_CTRL, &ctrl);
+		ksz_pread8(dev, p, regs[P_LOCAL_CTRL], &ctrl);
 		data = ctrl;
 		data &= ~(PORT_AUTO_NEG_SYM_PAUSE |
 			  PORT_AUTO_NEG_100BTX_FD |
@@ -634,7 +729,7 @@ static void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
 		if (val & PHY_AUTO_NEG_10BT)
 			data |= PORT_AUTO_NEG_10BT;
 		if (data != ctrl)
-			ksz_pwrite8(dev, p, P_LOCAL_CTRL, data);
+			ksz_pwrite8(dev, p, regs[P_LOCAL_CTRL], data);
 		break;
 	default:
 		break;
@@ -795,14 +890,15 @@ static void ksz8_port_vlan_add(struct dsa_switch *ds, int port,
 {
 	bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
 	struct ksz_device *dev = ds->priv;
-	u16 data, vid, new_pvid = 0;
+	u16 vid, new_pvid = 0;
+	u32 data = 0;
 	u8 fid, member, valid;
 
 	ksz_port_cfg(dev, port, P_TAG_CTRL, PORT_REMOVE_TAG, untagged);
 
 	for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
 		ksz8_r_vlan_table(dev, vid, &data);
-		ksz8_from_vlan(data, &fid, &member, &valid);
+		ksz8_from_vlan(dev, data, &fid, &member, &valid);
 
 		/* First time to setup the VLAN entry. */
 		if (!valid) {
@@ -812,9 +908,8 @@ static void ksz8_port_vlan_add(struct dsa_switch *ds, int port,
 		}
 		member |= BIT(port);
 
-		ksz8_to_vlan(fid, member, valid, &data);
+		ksz8_to_vlan(dev, fid, member, valid, &data);
 		ksz8_w_vlan_table(dev, vid, data);
-
 		/* change PVID */
 		if (vlan->flags & BRIDGE_VLAN_INFO_PVID)
 			new_pvid = vid;
@@ -833,7 +928,8 @@ static int ksz8_port_vlan_del(struct dsa_switch *ds, int port,
 {
 	bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
 	struct ksz_device *dev = ds->priv;
-	u16 data, vid, pvid, new_pvid = 0;
+	u32 data = 0;
+	u16 vid, pvid, new_pvid = 0;
 	u8 fid, member, valid;
 
 	ksz_pread16(dev, port, REG_PORT_CTRL_VID, &pvid);
@@ -843,7 +939,7 @@ static int ksz8_port_vlan_del(struct dsa_switch *ds, int port,
 
 	for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
 		ksz8_r_vlan_table(dev, vid, &data);
-		ksz8_from_vlan(data, &fid, &member, &valid);
+		ksz8_from_vlan(dev, data, &fid, &member, &valid);
 
 		member &= ~BIT(port);
 
@@ -856,7 +952,7 @@ static int ksz8_port_vlan_del(struct dsa_switch *ds, int port,
 		if (pvid == vid)
 			new_pvid = 1;
 
-		ksz8_to_vlan(fid, member, valid, &data);
+		ksz8_to_vlan(dev, fid, member, valid, &data);
 		ksz8_w_vlan_table(dev, vid, data);
 	}
 
@@ -963,6 +1059,8 @@ static void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port)
 {
 	struct ksz_port *p = &dev->ports[port];
 	u8 member;
+	struct ksz8 *ksz8 = dev->priv;
+	const u32 *masks = ksz8->masks;
 
 	/* enable broadcast storm limit */
 	ksz_port_cfg(dev, port, P_BCAST_STORM_CTRL, PORT_BROADCAST_STORM, true);
@@ -973,7 +1071,8 @@ static void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port)
 	ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_DIFFSERV_ENABLE, false);
 
 	/* replace priority */
-	ksz_port_cfg(dev, port, P_802_1P_CTRL, PORT_802_1P_REMAPPING, false);
+	ksz_port_cfg(dev, port, P_802_1P_CTRL,
+		     masks[PORT_802_1P_REMAPPING], false);
 
 	/* enable 802.1p priority */
 	ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_802_1P_ENABLE, true);
@@ -991,13 +1090,16 @@ static void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port)
 static void ksz8_config_cpu_port(struct dsa_switch *ds)
 {
 	struct ksz_device *dev = ds->priv;
+	struct ksz8 *ksz8 = dev->priv;
+	const u8 *regs = ksz8->regs;
+	const u32 *masks = ksz8->masks;
 	struct ksz_port *p;
 	u8 remote;
 	int i;
 
 	/* Switch marks the maximum frame with extra byte as oversize. */
 	ksz_cfg(dev, REG_SW_CTRL_2, SW_LEGAL_PACKET_DISABLE, true);
-	ksz_cfg(dev, S_TAIL_TAG_CTRL, SW_TAIL_TAG_ENABLE, true);
+	ksz_cfg(dev, regs[S_TAIL_TAG_CTRL], masks[SW_TAIL_TAG_ENABLE], true);
 
 	p = &dev->ports[dev->cpu_port];
 	p->vid_member = dev->port_mask;
@@ -1026,7 +1128,7 @@ static void ksz8_config_cpu_port(struct dsa_switch *ds)
 		p = &dev->ports[i];
 		if (!p->on)
 			continue;
-		ksz_pread8(dev, i, P_REMOTE_STATUS, &remote);
+		ksz_pread8(dev, i, regs[P_REMOTE_STATUS], &remote);
 		if (remote & PORT_FIBER_MODE)
 			p->fiber = 1;
 		if (p->fiber)
@@ -1211,6 +1313,7 @@ static const struct ksz_chip_data ksz8_switch_chips[] = {
 static int ksz8_switch_init(struct ksz_device *dev)
 {
 	int i;
+	struct ksz8 *ksz8 = dev->priv;
 
 	dev->ds->ops = &ksz8_switch_ops;
 
@@ -1233,6 +1336,10 @@ static int ksz8_switch_init(struct ksz_device *dev)
 	if (!dev->cpu_ports)
 		return -ENODEV;
 
+	ksz8->regs = ksz8795_regs;
+	ksz8->masks = ksz8795_masks;
+	ksz8->shifts = ksz8795_shifts;
+
 	dev->port_mask = BIT(dev->port_cnt) - 1;
 	dev->port_mask |= dev->host_mask;
 
diff --git a/drivers/net/dsa/microchip/ksz8795_reg.h b/drivers/net/dsa/microchip/ksz8795_reg.h
index 40372047d40d8..eea78c5636a0f 100644
--- a/drivers/net/dsa/microchip/ksz8795_reg.h
+++ b/drivers/net/dsa/microchip/ksz8795_reg.h
@@ -98,7 +98,6 @@
 
 #define REG_SW_CTRL_10			0x0C
 
-#define SW_TAIL_TAG_ENABLE		BIT(1)
 #define SW_PASS_PAUSE			BIT(0)
 
 #define REG_SW_CTRL_11			0x0D
@@ -150,7 +149,6 @@
 #define REG_PORT_4_CTRL_2		0x42
 #define REG_PORT_5_CTRL_2		0x52
 
-#define PORT_802_1P_REMAPPING		BIT(7)
 #define PORT_INGRESS_FILTER		BIT(6)
 #define PORT_DISCARD_NON_VID		BIT(5)
 #define PORT_FORCE_FLOW_CTRL		BIT(4)
@@ -319,14 +317,12 @@
 
 #define REG_PORT_CTRL_5			0x05
 
-#define REG_PORT_CTRL_7			0x07
 #define REG_PORT_STATUS_0		0x08
 #define REG_PORT_STATUS_1		0x09
 #define REG_PORT_LINK_MD_CTRL		0x0A
 #define REG_PORT_LINK_MD_RESULT		0x0B
 #define REG_PORT_CTRL_9			0x0C
 #define REG_PORT_CTRL_10		0x0D
-#define REG_PORT_STATUS_2		0x0E
 #define REG_PORT_STATUS_3		0x0F
 
 #define REG_PORT_CTRL_12		0xA0
@@ -356,8 +352,6 @@
 #define REG_SW_MAC_ADDR_4		0x6C
 #define REG_SW_MAC_ADDR_5		0x6D
 
-#define REG_IND_CTRL_0			0x6E
-
 #define TABLE_EXT_SELECT_S		5
 #define TABLE_EEE_V			1
 #define TABLE_ACL_V			2
@@ -383,23 +377,13 @@
 #define TABLE_ENTRY_MASK		0x03FF
 #define TABLE_EXT_ENTRY_MASK		0x0FFF
 
-#define REG_IND_DATA_8			0x70
-#define REG_IND_DATA_7			0x71
-#define REG_IND_DATA_6			0x72
 #define REG_IND_DATA_5			0x73
-#define REG_IND_DATA_4			0x74
-#define REG_IND_DATA_3			0x75
 #define REG_IND_DATA_2			0x76
 #define REG_IND_DATA_1			0x77
 #define REG_IND_DATA_0			0x78
 
 #define REG_IND_DATA_PME_EEE_ACL	0xA0
 
-#define REG_IND_DATA_CHECK		REG_IND_DATA_6
-#define REG_IND_MIB_CHECK		REG_IND_DATA_4
-#define REG_IND_DATA_HI			REG_IND_DATA_7
-#define REG_IND_DATA_LO			REG_IND_DATA_3
-
 #define REG_INT_STATUS			0x7C
 #define REG_INT_ENABLE			0x7D
 
@@ -856,12 +840,6 @@
 #define P_MIRROR_CTRL			REG_PORT_CTRL_1
 #define P_802_1P_CTRL			REG_PORT_CTRL_2
 #define P_STP_CTRL			REG_PORT_CTRL_2
-#define P_LOCAL_CTRL			REG_PORT_CTRL_7
-#define P_REMOTE_STATUS			REG_PORT_STATUS_0
-#define P_FORCE_CTRL			REG_PORT_CTRL_9
-#define P_NEG_RESTART_CTRL		REG_PORT_CTRL_10
-#define P_SPEED_STATUS			REG_PORT_STATUS_1
-#define P_LINK_STATUS			REG_PORT_STATUS_2
 #define P_PASS_ALL_CTRL			REG_PORT_CTRL_12
 #define P_INS_SRC_PVID_CTRL		REG_PORT_CTRL_12
 #define P_DROP_TAG_CTRL			REG_PORT_CTRL_13
@@ -876,7 +854,6 @@
 #define S_MIRROR_CTRL			REG_SW_CTRL_3
 #define S_REPLACE_VID_CTRL		REG_SW_CTRL_4
 #define S_PASS_PAUSE_CTRL		REG_SW_CTRL_10
-#define S_TAIL_TAG_CTRL			REG_SW_CTRL_10
 #define S_802_1P_PRIO_CTRL		REG_SW_CTRL_12
 #define S_TOS_PRIO_CTRL			REG_TOS_PRIO_CTRL_0
 #define S_IPV6_MLD_CTRL			REG_SW_CTRL_21
@@ -889,65 +866,6 @@
 /* 148,800 frames * 67 ms / 100 */
 #define BROADCAST_STORM_VALUE		9969
 
-/**
- * STATIC_MAC_TABLE_ADDR		00-0000FFFF-FFFFFFFF
- * STATIC_MAC_TABLE_FWD_PORTS		00-001F0000-00000000
- * STATIC_MAC_TABLE_VALID		00-00200000-00000000
- * STATIC_MAC_TABLE_OVERRIDE		00-00400000-00000000
- * STATIC_MAC_TABLE_USE_FID		00-00800000-00000000
- * STATIC_MAC_TABLE_FID			00-7F000000-00000000
- */
-
-#define STATIC_MAC_TABLE_ADDR		0x0000FFFF
-#define STATIC_MAC_TABLE_FWD_PORTS	0x001F0000
-#define STATIC_MAC_TABLE_VALID		0x00200000
-#define STATIC_MAC_TABLE_OVERRIDE	0x00400000
-#define STATIC_MAC_TABLE_USE_FID	0x00800000
-#define STATIC_MAC_TABLE_FID		0x7F000000
-
-#define STATIC_MAC_FWD_PORTS_S		16
-#define STATIC_MAC_FID_S		24
-
-/**
- * VLAN_TABLE_FID			00-007F007F-007F007F
- * VLAN_TABLE_MEMBERSHIP		00-0F800F80-0F800F80
- * VLAN_TABLE_VALID			00-10001000-10001000
- */
-
-#define VLAN_TABLE_FID			0x007F
-#define VLAN_TABLE_MEMBERSHIP		0x0F80
-#define VLAN_TABLE_VALID		0x1000
-
-#define VLAN_TABLE_MEMBERSHIP_S		7
-#define VLAN_TABLE_S			16
-
-/**
- * DYNAMIC_MAC_TABLE_ADDR		00-0000FFFF-FFFFFFFF
- * DYNAMIC_MAC_TABLE_FID		00-007F0000-00000000
- * DYNAMIC_MAC_TABLE_NOT_READY		00-00800000-00000000
- * DYNAMIC_MAC_TABLE_SRC_PORT		00-07000000-00000000
- * DYNAMIC_MAC_TABLE_TIMESTAMP		00-18000000-00000000
- * DYNAMIC_MAC_TABLE_ENTRIES		7F-E0000000-00000000
- * DYNAMIC_MAC_TABLE_MAC_EMPTY		80-00000000-00000000
- */
-
-#define DYNAMIC_MAC_TABLE_ADDR		0x0000FFFF
-#define DYNAMIC_MAC_TABLE_FID		0x007F0000
-#define DYNAMIC_MAC_TABLE_SRC_PORT	0x07000000
-#define DYNAMIC_MAC_TABLE_TIMESTAMP	0x18000000
-#define DYNAMIC_MAC_TABLE_ENTRIES	0xE0000000
-
-#define DYNAMIC_MAC_TABLE_NOT_READY	0x80
-
-#define DYNAMIC_MAC_TABLE_ENTRIES_H	0x7F
-#define DYNAMIC_MAC_TABLE_MAC_EMPTY	0x80
-
-#define DYNAMIC_MAC_FID_S		16
-#define DYNAMIC_MAC_SRC_PORT_S		24
-#define DYNAMIC_MAC_TIMESTAMP_S		27
-#define DYNAMIC_MAC_ENTRIES_S		29
-#define DYNAMIC_MAC_ENTRIES_H_S		3
-
 /**
  * MIB_COUNTER_VALUE			00-00000000-3FFFFFFF
  * MIB_TOTAL_BYTES			00-0000000F-FFFFFFFF
@@ -956,9 +874,6 @@
  * MIB_COUNTER_OVERFLOW			00-00000040-00000000
  */
 
-#define MIB_COUNTER_OVERFLOW		BIT(6)
-#define MIB_COUNTER_VALID		BIT(5)
-
 #define MIB_COUNTER_VALUE		0x3FFFFFFF
 
 #define KS_MIB_TOTAL_RX_0		0x100
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v5 4/6] net: dsa: microchip: ksz8795: add support for ksz88xx chips
  2020-12-07 12:56 [PATCH v5 0/6] microchip: add support for ksz88x3 driver family Michael Grzeschik
                   ` (2 preceding siblings ...)
  2020-12-07 12:56 ` [PATCH v5 3/6] net: dsa: microchip: ksz8795: move register offsets and shifts to separate struct Michael Grzeschik
@ 2020-12-07 12:56 ` Michael Grzeschik
  2020-12-16  6:33   ` Tristram.Ha
  2020-12-07 12:56 ` [PATCH v5 5/6] net: dsa: microchip: Add Microchip KSZ8863 SPI based driver support Michael Grzeschik
  2020-12-07 12:56 ` [PATCH v5 6/6] dt-bindings: net: dsa: document additional Microchip KSZ8863/8873 switch Michael Grzeschik
  5 siblings, 1 reply; 17+ messages in thread
From: Michael Grzeschik @ 2020-12-07 12:56 UTC (permalink / raw)
  To: netdev
  Cc: andrew, f.fainelli, davem, kernel, matthias.schiffer,
	woojung.huh, UNGLinuxDriver

We add support for the ksz8863 and ksz8873 chips which are
using the same register patterns but other offsets as the
ksz8795.

Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>

---
v1 -> v4: - extracted this change from bigger previous patch
v4 -> v5: - added clear of reset bit for ksz8863 reset code
          - using extra device flag IS_KSZ88x3 instead of is_ksz8795 function
	  - using DSA_TAG_PROTO_KSZ9893 protocol for ksz88x3 instead
---
 drivers/net/dsa/microchip/ksz8795.c     | 345 +++++++++++++++++++-----
 drivers/net/dsa/microchip/ksz8795_reg.h |  40 ++-
 drivers/net/dsa/microchip/ksz_common.h  |   1 +
 3 files changed, 299 insertions(+), 87 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c
index 127498a9b8f72..9484667a29a35 100644
--- a/drivers/net/dsa/microchip/ksz8795.c
+++ b/drivers/net/dsa/microchip/ksz8795.c
@@ -22,6 +22,9 @@
 #include "ksz8795_reg.h"
 #include "ksz8.h"
 
+/* Used with variable features to indicate capabilities. */
+#define IS_88X3				BIT(0)
+
 static const u8 ksz8795_regs[] = {
 	[REG_IND_CTRL_0]		= 0x6E,
 	[REG_IND_DATA_8]		= 0x70,
@@ -72,9 +75,60 @@ static const u8 ksz8795_shifts[] = {
 	[DYNAMIC_MAC_SRC_PORT]		= 24,
 };
 
-static const struct {
+static const u8 ksz8863_regs[] = {
+	[REG_IND_CTRL_0]		= 0x79,
+	[REG_IND_DATA_8]		= 0x7B,
+	[REG_IND_DATA_CHECK]		= 0x7B,
+	[REG_IND_DATA_HI]		= 0x7C,
+	[REG_IND_DATA_LO]		= 0x80,
+	[REG_IND_MIB_CHECK]		= 0x80,
+	[P_FORCE_CTRL]			= 0x0C,
+	[P_LINK_STATUS]			= 0x0E,
+	[P_LOCAL_CTRL]			= 0x0C,
+	[P_NEG_RESTART_CTRL]		= 0x0D,
+	[P_REMOTE_STATUS]		= 0x0E,
+	[P_SPEED_STATUS]		= 0x0F,
+	[S_TAIL_TAG_CTRL]		= 0x03,
+};
+
+static const u32 ksz8863_masks[] = {
+	[PORT_802_1P_REMAPPING]		= BIT(3),
+	[SW_TAIL_TAG_ENABLE]		= BIT(6),
+	[MIB_COUNTER_OVERFLOW]		= BIT(7),
+	[MIB_COUNTER_VALID]		= BIT(6),
+	[VLAN_TABLE_FID]		= GENMASK(15, 12),
+	[VLAN_TABLE_MEMBERSHIP]		= GENMASK(18, 16),
+	[VLAN_TABLE_VALID]		= BIT(19),
+	[STATIC_MAC_TABLE_VALID]	= BIT(19),
+	[STATIC_MAC_TABLE_USE_FID]	= BIT(21),
+	[STATIC_MAC_TABLE_FID]		= GENMASK(29, 26),
+	[STATIC_MAC_TABLE_OVERRIDE]	= BIT(20),
+	[STATIC_MAC_TABLE_FWD_PORTS]	= GENMASK(18, 16),
+	[DYNAMIC_MAC_TABLE_ENTRIES_H]	= GENMASK(5, 0),
+	[DYNAMIC_MAC_TABLE_MAC_EMPTY]	= BIT(7),
+	[DYNAMIC_MAC_TABLE_NOT_READY]	= BIT(7),
+	[DYNAMIC_MAC_TABLE_ENTRIES]	= GENMASK(31, 28),
+	[DYNAMIC_MAC_TABLE_FID]		= GENMASK(19, 16),
+	[DYNAMIC_MAC_TABLE_SRC_PORT]	= GENMASK(21, 20),
+	[DYNAMIC_MAC_TABLE_TIMESTAMP]	= GENMASK(23, 22),
+};
+
+static u8 ksz8863_shifts[] = {
+	[VLAN_TABLE_MEMBERSHIP]		= 16,
+	[STATIC_MAC_FWD_PORTS]		= 16,
+	[STATIC_MAC_FID]		= 22,
+	[DYNAMIC_MAC_ENTRIES_H]		= 3,
+	[DYNAMIC_MAC_ENTRIES]		= 24,
+	[DYNAMIC_MAC_FID]		= 16,
+	[DYNAMIC_MAC_TIMESTAMP]		= 24,
+	[DYNAMIC_MAC_SRC_PORT]		= 20,
+};
+
+struct mib_names {
 	char string[ETH_GSTRING_LEN];
-} mib_names[] = {
+};
+
+static const struct mib_names ksz87xx_mib_names[] = {
 	{ "rx_hi" },
 	{ "rx_undersize" },
 	{ "rx_fragments" },
@@ -113,6 +167,43 @@ static const struct {
 	{ "tx_discards" },
 };
 
+static const struct mib_names ksz88xx_mib_names[] = {
+	{ "rx" },
+	{ "rx_hi" },
+	{ "rx_undersize" },
+	{ "rx_fragments" },
+	{ "rx_oversize" },
+	{ "rx_jabbers" },
+	{ "rx_symbol_err" },
+	{ "rx_crc_err" },
+	{ "rx_align_err" },
+	{ "rx_mac_ctrl" },
+	{ "rx_pause" },
+	{ "rx_bcast" },
+	{ "rx_mcast" },
+	{ "rx_ucast" },
+	{ "rx_64_or_less" },
+	{ "rx_65_127" },
+	{ "rx_128_255" },
+	{ "rx_256_511" },
+	{ "rx_512_1023" },
+	{ "rx_1024_1522" },
+	{ "tx" },
+	{ "tx_hi" },
+	{ "tx_late_col" },
+	{ "tx_pause" },
+	{ "tx_bcast" },
+	{ "tx_mcast" },
+	{ "tx_ucast" },
+	{ "tx_deferred" },
+	{ "tx_total_col" },
+	{ "tx_exc_col" },
+	{ "tx_single_col" },
+	{ "tx_mult_col" },
+	{ "rx_discards" },
+	{ "tx_discards" },
+};
+
 static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set)
 {
 	regmap_update_bits(dev->regmap[0], addr, bits, set ? bits : 0);
@@ -127,10 +218,18 @@ static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits,
 
 static int ksz8_reset_switch(struct ksz_device *dev)
 {
-	/* reset switch */
-	ksz_write8(dev, REG_POWER_MANAGEMENT_1,
-		   SW_SOFTWARE_POWER_DOWN << SW_POWER_MANAGEMENT_MODE_S);
-	ksz_write8(dev, REG_POWER_MANAGEMENT_1, 0);
+	if (dev->features & IS_88X3) {
+		/* reset switch */
+		ksz_cfg(dev, KSZ8863_REG_SW_RESET,
+			KSZ8863_GLOBAL_SOFTWARE_RESET | KSZ8863_PCS_RESET, true);
+		ksz_cfg(dev, KSZ8863_REG_SW_RESET,
+			KSZ8863_GLOBAL_SOFTWARE_RESET | KSZ8863_PCS_RESET, false);
+	} else {
+		/* reset switch */
+		ksz_write8(dev, REG_POWER_MANAGEMENT_1,
+			   SW_SOFTWARE_POWER_DOWN << SW_POWER_MANAGEMENT_MODE_S);
+		ksz_write8(dev, REG_POWER_MANAGEMENT_1, 0);
+	}
 
 	return 0;
 }
@@ -201,8 +300,8 @@ static void ksz8_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt)
 	mutex_unlock(&dev->alu_mutex);
 }
 
-static void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
-			   u64 *dropped, u64 *cnt)
+static void ksz8795_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
+			      u64 *dropped, u64 *cnt)
 {
 	struct ksz8 *ksz8 = dev->priv;
 	const u8 *regs = ksz8->regs;
@@ -213,8 +312,8 @@ static void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
 	int loop;
 
 	addr -= dev->reg_mib_cnt;
-	ctrl_addr = (KS_MIB_TOTAL_RX_1 - KS_MIB_TOTAL_RX_0) * port;
-	ctrl_addr += addr + KS_MIB_TOTAL_RX_0;
+	ctrl_addr = (KSZ8795_MIB_TOTAL_RX_1 - KSZ8795_MIB_TOTAL_RX_0) * port;
+	ctrl_addr += addr + KSZ8795_MIB_TOTAL_RX_0;
 	ctrl_addr |= IND_ACC_TABLE(TABLE_MIB | TABLE_READ);
 
 	mutex_lock(&dev->alu_mutex);
@@ -251,8 +350,53 @@ static void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
 	mutex_unlock(&dev->alu_mutex);
 }
 
+static void ksz8863_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
+			      u64 *dropped, u64 *cnt)
+{
+	struct ksz8 *ksz8 = dev->priv;
+	const u8 *regs = ksz8->regs;
+	u32 *last = (u32 *)dropped;
+	u16 ctrl_addr;
+	u32 data;
+	u32 cur;
+
+	addr -= dev->reg_mib_cnt;
+	ctrl_addr = addr ? KSZ8863_MIB_PACKET_DROPPED_TX_0 :
+			   KSZ8863_MIB_PACKET_DROPPED_RX_0;
+	ctrl_addr += port;
+	ctrl_addr |= IND_ACC_TABLE(TABLE_MIB | TABLE_READ);
+
+	mutex_lock(&dev->alu_mutex);
+	ksz_write16(dev, regs[REG_IND_CTRL_0], ctrl_addr);
+	ksz_read32(dev, regs[REG_IND_DATA_LO], &data);
+	mutex_unlock(&dev->alu_mutex);
+
+	data &= MIB_PACKET_DROPPED;
+	cur = last[addr];
+	if (data != cur) {
+		last[addr] = data;
+		if (data < cur)
+			data += MIB_PACKET_DROPPED + 1;
+		data -= cur;
+		*cnt += data;
+	}
+}
+
+static void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
+			   u64 *dropped, u64 *cnt)
+{
+	if (dev->features & IS_88X3) {
+		ksz8863_r_mib_pkt(dev, port, addr, dropped, cnt);
+	} else {
+		ksz8795_r_mib_pkt(dev, port, addr, dropped, cnt);
+	}
+}
+
 static void ksz8_freeze_mib(struct ksz_device *dev, int port, bool freeze)
 {
+	if (dev->features & IS_88X3)
+		return;
+
 	/* enable the port for flush/freeze function */
 	if (freeze)
 		ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), true);
@@ -267,10 +411,12 @@ static void ksz8_port_init_cnt(struct ksz_device *dev, int port)
 {
 	struct ksz_port_mib *mib = &dev->ports[port].mib;
 
-	/* flush all enabled port MIB counters */
-	ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), true);
-	ksz_cfg(dev, REG_SW_CTRL_6, SW_MIB_COUNTER_FLUSH, true);
-	ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), false);
+	if (!(dev->features & IS_88X3)) {
+		/* flush all enabled port MIB counters */
+		ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), true);
+		ksz_cfg(dev, REG_SW_CTRL_6, SW_MIB_COUNTER_FLUSH, true);
+		ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), false);
+	}
 
 	mib->cnt_ptr = 0;
 
@@ -508,37 +654,46 @@ static void ksz8_r_vlan_entries(struct ksz_device *dev, u16 addr)
 	ksz8_r_table(dev, TABLE_VLAN, addr, &data);
 	addr *= dev->phy_port_cnt;
 	for (i = 0; i < dev->phy_port_cnt; i++) {
-		dev->vlan_cache[addr + i].table[0] = (u16)data;
-		data >>= shifts[VLAN_TABLE];
+		if (dev->features & IS_88X3) {
+			dev->vlan_cache[addr + i].table[0] = (u32)data;
+		} else {
+			dev->vlan_cache[addr + i].table[0] = (u16)data;
+			data >>= shifts[VLAN_TABLE];
+		}
+
 	}
 }
 
 static void ksz8_r_vlan_table(struct ksz_device *dev, u16 vid, u32 *vlan)
 {
-	int index;
-	u16 *data;
-	u16 addr;
+	u16 addr = vid / dev->phy_port_cnt;
 	u64 buf;
 
-	data = (u16 *)&buf;
-	addr = vid / dev->phy_port_cnt;
-	index = vid & 3;
 	ksz8_r_table(dev, TABLE_VLAN, addr, &buf);
-	*vlan = data[index];
+	if (dev->features & IS_88X3) {
+		*vlan = (u32)buf;
+	} else {
+		u16 *data = (u16 *)&buf;
+
+		*vlan = data[vid & 3];
+	}
 }
 
 static void ksz8_w_vlan_table(struct ksz_device *dev, u16 vid, u32 vlan)
 {
-	int index;
-	u16 *data;
-	u16 addr;
+	u16 addr = vid / dev->phy_port_cnt;
 	u64 buf;
 
-	data = (u16 *)&buf;
-	addr = vid / dev->phy_port_cnt;
-	index = vid & 3;
 	ksz8_r_table(dev, TABLE_VLAN, addr, &buf);
-	data[index] = vlan;
+
+	if (dev->features & IS_88X3) {
+		buf = vlan;
+	} else {
+		u16 *data = (u16 *)&buf;
+
+		data[vid & 3] = vlan;
+	}
+
 	dev->vlan_cache[vid].table[0] = vlan;
 	ksz8_w_table(dev, TABLE_VLAN, addr, buf);
 }
@@ -561,8 +716,13 @@ static void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
 			data |= PHY_LOOPBACK;
 		if (ctrl & PORT_FORCE_100_MBIT)
 			data |= PHY_SPEED_100MBIT;
-		if (!(ctrl & PORT_AUTO_NEG_DISABLE))
-			data |= PHY_AUTO_NEG_ENABLE;
+		if (dev->features & IS_88X3) {
+			if ((ctrl & PORT_AUTO_NEG_ENABLE))
+				data |= PHY_AUTO_NEG_ENABLE;
+		} else {
+			if (!(ctrl & PORT_AUTO_NEG_DISABLE))
+				data |= PHY_AUTO_NEG_ENABLE;
+		}
 		if (restart & PORT_POWER_DOWN)
 			data |= PHY_POWER_DOWN;
 		if (restart & PORT_AUTO_NEG_RESTART)
@@ -596,7 +756,10 @@ static void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
 		data = KSZ8795_ID_HI;
 		break;
 	case PHY_REG_ID_2:
-		data = KSZ8795_ID_LO;
+		if (dev->features & IS_88X3)
+			data = KSZ8863_ID_LO;
+		else
+			data = KSZ8795_ID_LO;
 		break;
 	case PHY_REG_AUTO_NEGOTIATION:
 		ksz_pread8(dev, p, regs[P_LOCAL_CTRL], &ctrl);
@@ -659,14 +822,22 @@ static void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
 			ksz_pwrite8(dev, p, regs[P_SPEED_STATUS], data);
 		ksz_pread8(dev, p, regs[P_FORCE_CTRL], &ctrl);
 		data = ctrl;
-		if (!(val & PHY_AUTO_NEG_ENABLE))
-			data |= PORT_AUTO_NEG_DISABLE;
-		else
-			data &= ~PORT_AUTO_NEG_DISABLE;
+		if (dev->features & IS_88X3) {
+			if ((val & PHY_AUTO_NEG_ENABLE))
+				data |= PORT_AUTO_NEG_ENABLE;
+			else
+				data &= ~PORT_AUTO_NEG_ENABLE;
+		} else {
+			if (!(val & PHY_AUTO_NEG_ENABLE))
+				data |= PORT_AUTO_NEG_DISABLE;
+			else
+				data &= ~PORT_AUTO_NEG_DISABLE;
+
+			/* Fiber port does not support auto-negotiation. */
+			if (dev->ports[p].fiber)
+				data |= PORT_AUTO_NEG_DISABLE;
+		}
 
-		/* Fiber port does not support auto-negotiation. */
-		if (dev->ports[p].fiber)
-			data |= PORT_AUTO_NEG_DISABLE;
 		if (val & PHY_SPEED_100MBIT)
 			data |= PORT_FORCE_100_MBIT;
 		else
@@ -740,7 +911,11 @@ static enum dsa_tag_protocol ksz8_get_tag_protocol(struct dsa_switch *ds,
 						   int port,
 						   enum dsa_tag_protocol mp)
 {
-	return DSA_TAG_PROTO_KSZ8795;
+	struct ksz_device *dev = ds->priv;
+
+	/* ksz88x3 uses the same tag schema as KSZ9893 */
+	return (dev->features & IS_88X3)  ?
+		DSA_TAG_PROTO_KSZ9893 : DSA_TAG_PROTO_KSZ8795;
 }
 
 static void ksz8_get_strings(struct dsa_switch *ds, int port,
@@ -750,17 +925,21 @@ static void ksz8_get_strings(struct dsa_switch *ds, int port,
 	int i;
 
 	for (i = 0; i < dev->mib_cnt; i++) {
-		memcpy(buf + i * ETH_GSTRING_LEN, mib_names[i].string,
-		       ETH_GSTRING_LEN);
+		memcpy(buf + i * ETH_GSTRING_LEN,
+		       dev->mib_names[i].string, ETH_GSTRING_LEN);
 	}
 }
 
 static void ksz8_cfg_port_member(struct ksz_device *dev, int port, u8 member)
 {
+	int membership = PORT_VLAN_MEMBERSHIP;
 	u8 data;
 
+	if (dev->features & IS_88X3)
+		membership = (membership >> 2);
+
 	ksz_pread8(dev, port, P_MIRROR_CTRL, &data);
-	data &= ~PORT_VLAN_MEMBERSHIP;
+	data &= ~(membership);
 	data |= (member & dev->port_mask);
 	ksz_pwrite8(dev, port, P_MIRROR_CTRL, data);
 	dev->ports[port].member = member;
@@ -1065,7 +1244,8 @@ static void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port)
 	/* enable broadcast storm limit */
 	ksz_port_cfg(dev, port, P_BCAST_STORM_CTRL, PORT_BROADCAST_STORM, true);
 
-	ksz8795_set_prio_queue(dev, port, 4);
+	if (!(dev->features & IS_88X3))
+		ksz8795_set_prio_queue(dev, port, 4);
 
 	/* disable DiffServ priority */
 	ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_DIFFSERV_ENABLE, false);
@@ -1078,7 +1258,8 @@ static void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port)
 	ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_802_1P_ENABLE, true);
 
 	if (cpu_port) {
-		ksz8795_cpu_interface_select(dev, port);
+		if (!(dev->features & IS_88X3))
+			ksz8795_cpu_interface_select(dev, port);
 
 		member = dev->port_mask;
 	} else {
@@ -1128,9 +1309,11 @@ static void ksz8_config_cpu_port(struct dsa_switch *ds)
 		p = &dev->ports[i];
 		if (!p->on)
 			continue;
-		ksz_pread8(dev, i, regs[P_REMOTE_STATUS], &remote);
-		if (remote & PORT_FIBER_MODE)
-			p->fiber = 1;
+		if (!(dev->features & IS_88X3)) {
+			ksz_pread8(dev, i, regs[P_REMOTE_STATUS], &remote);
+			if (remote & PORT_FIBER_MODE)
+				p->fiber = 1;
+		}
 		if (p->fiber)
 			ksz_port_cfg(dev, i, P_STP_CTRL, PORT_FORCE_FLOW_CTRL,
 				     true);
@@ -1249,19 +1432,33 @@ static int ksz8_switch_detect(struct ksz_device *dev)
 
 	id1 = id16 >> 8;
 	id2 = id16 & SW_CHIP_ID_M;
-	if (id1 != FAMILY_ID ||
-	    (id2 != CHIP_ID_94 && id2 != CHIP_ID_95))
-		return -ENODEV;
 
-	if (id2 == CHIP_ID_95) {
-		u8 val;
+	switch (id1) {
+	case KSZ87_FAMILY_ID:
+		if ((id2 != CHIP_ID_94 && id2 != CHIP_ID_95))
+			return -ENODEV;
 
-		id2 = 0x95;
-		ksz_read8(dev, REG_PORT_1_STATUS_0, &val);
-		if (val & PORT_FIBER_MODE)
-			id2 = 0x65;
-	} else if (id2 == CHIP_ID_94) {
-		id2 = 0x94;
+		if (id2 == CHIP_ID_95) {
+			u8 val;
+
+			id2 = 0x95;
+			ksz_read8(dev, REG_PORT_STATUS_0, &val);
+			if (val & PORT_FIBER_MODE)
+				id2 = 0x65;
+		} else if (id2 == CHIP_ID_94) {
+			id2 = 0x94;
+		}
+		break;
+	case KSZ88_FAMILY_ID:
+		if (id2 != CHIP_ID_63)
+			return -ENODEV;
+
+		dev->features |= IS_88X3;
+
+		break;
+	default:
+		dev_err(dev->dev, "invalid family id: %d\n", id1);
+		return -ENODEV;
 	}
 	id16 &= ~0xff;
 	id16 |= id2;
@@ -1308,6 +1505,15 @@ static const struct ksz_chip_data ksz8_switch_chips[] = {
 		.cpu_ports = 0x10,	/* can be configured as cpu port */
 		.port_cnt = 5,		/* total cpu and user ports */
 	},
+	{
+		.chip_id = 0x8830,
+		.dev_name = "KSZ8863/KSZ8873",
+		.num_vlans = 16,
+		.num_alus = 0,
+		.num_statics = 8,
+		.cpu_ports = 0x4,	/* can be configured as cpu port */
+		.port_cnt = 3,
+	},
 };
 
 static int ksz8_switch_init(struct ksz_device *dev)
@@ -1336,15 +1542,24 @@ static int ksz8_switch_init(struct ksz_device *dev)
 	if (!dev->cpu_ports)
 		return -ENODEV;
 
-	ksz8->regs = ksz8795_regs;
-	ksz8->masks = ksz8795_masks;
-	ksz8->shifts = ksz8795_shifts;
+	if (dev->features & IS_88X3) {
+		ksz8->regs = ksz8863_regs;
+		ksz8->masks = ksz8863_masks;
+		ksz8->shifts = ksz8863_shifts;
+		dev->mib_cnt = ARRAY_SIZE(ksz88xx_mib_names);
+		dev->mib_names = ksz88xx_mib_names;
+	} else {
+		ksz8->regs = ksz8795_regs;
+		ksz8->masks = ksz8795_masks;
+		ksz8->shifts = ksz8795_shifts;
+		dev->mib_cnt = ARRAY_SIZE(ksz87xx_mib_names);
+		dev->mib_names = ksz87xx_mib_names;
+	}
 
 	dev->port_mask = BIT(dev->port_cnt) - 1;
 	dev->port_mask |= dev->host_mask;
 
-	dev->reg_mib_cnt = KSZ8795_COUNTER_NUM;
-	dev->mib_cnt = ARRAY_SIZE(mib_names);
+	dev->reg_mib_cnt = MIB_COUNTER_NUM;
 
 	dev->phy_port_cnt = dev->port_cnt - 1;
 
diff --git a/drivers/net/dsa/microchip/ksz8795_reg.h b/drivers/net/dsa/microchip/ksz8795_reg.h
index eea78c5636a0f..c2e52c40a54c5 100644
--- a/drivers/net/dsa/microchip/ksz8795_reg.h
+++ b/drivers/net/dsa/microchip/ksz8795_reg.h
@@ -16,7 +16,8 @@
 
 #define REG_CHIP_ID0			0x00
 
-#define FAMILY_ID			0x87
+#define KSZ87_FAMILY_ID			0x87
+#define KSZ88_FAMILY_ID			0x88
 
 #define REG_CHIP_ID1			0x01
 
@@ -28,6 +29,12 @@
 
 #define CHIP_ID_94			0x60
 #define CHIP_ID_95			0x90
+#define CHIP_ID_63			0x30
+
+#define KSZ8863_REG_SW_RESET		0x43
+
+#define KSZ8863_GLOBAL_SOFTWARE_RESET	BIT(4)
+#define KSZ8863_PCS_RESET		BIT(0)
 
 #define REG_SW_CTRL_0			0x02
 
@@ -267,6 +274,7 @@
 #define REG_PORT_3_CTRL_9		0x3C
 #define REG_PORT_4_CTRL_9		0x4C
 
+#define PORT_AUTO_NEG_ENABLE		BIT(7)
 #define PORT_AUTO_NEG_DISABLE		BIT(7)
 #define PORT_FORCE_100_MBIT		BIT(6)
 #define PORT_FORCE_FULL_DUPLEX		BIT(5)
@@ -800,6 +808,7 @@
 
 #define KSZ8795_ID_HI			0x0022
 #define KSZ8795_ID_LO			0x1550
+#define KSZ8863_ID_LO			0x1430
 
 #define KSZ8795_SW_ID			0x8795
 
@@ -830,7 +839,7 @@
 
 #define KS_PRIO_IN_REG			4
 
-#define KSZ8795_COUNTER_NUM		0x20
+#define MIB_COUNTER_NUM		0x20
 
 /* Common names used by other drivers */
 
@@ -876,26 +885,13 @@
 
 #define MIB_COUNTER_VALUE		0x3FFFFFFF
 
-#define KS_MIB_TOTAL_RX_0		0x100
-#define KS_MIB_TOTAL_TX_0		0x101
-#define KS_MIB_PACKET_DROPPED_RX_0	0x102
-#define KS_MIB_PACKET_DROPPED_TX_0	0x103
-#define KS_MIB_TOTAL_RX_1		0x104
-#define KS_MIB_TOTAL_TX_1		0x105
-#define KS_MIB_PACKET_DROPPED_TX_1	0x106
-#define KS_MIB_PACKET_DROPPED_RX_1	0x107
-#define KS_MIB_TOTAL_RX_2		0x108
-#define KS_MIB_TOTAL_TX_2		0x109
-#define KS_MIB_PACKET_DROPPED_TX_2	0x10A
-#define KS_MIB_PACKET_DROPPED_RX_2	0x10B
-#define KS_MIB_TOTAL_RX_3		0x10C
-#define KS_MIB_TOTAL_TX_3		0x10D
-#define KS_MIB_PACKET_DROPPED_TX_3	0x10E
-#define KS_MIB_PACKET_DROPPED_RX_3	0x10F
-#define KS_MIB_TOTAL_RX_4		0x110
-#define KS_MIB_TOTAL_TX_4		0x111
-#define KS_MIB_PACKET_DROPPED_TX_4	0x112
-#define KS_MIB_PACKET_DROPPED_RX_4	0x113
+#define KSZ8795_MIB_TOTAL_RX_0		0x100
+#define KSZ8795_MIB_TOTAL_TX_0		0x101
+#define KSZ8795_MIB_TOTAL_RX_1		0x104
+#define KSZ8795_MIB_TOTAL_TX_1		0x105
+
+#define KSZ8863_MIB_PACKET_DROPPED_TX_0 0x100
+#define KSZ8863_MIB_PACKET_DROPPED_RX_0 0x105
 
 #define MIB_PACKET_DROPPED		0x0000FFFF
 
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index 49f4b882bd708..af9e94049912d 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -71,6 +71,7 @@ struct ksz_device {
 	int port_cnt;
 	int reg_mib_cnt;
 	int mib_cnt;
+	const struct mib_names *mib_names;
 	phy_interface_t compat_interface;
 	u32 regs_size;
 	bool phy_errata_9477;
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v5 5/6] net: dsa: microchip: Add Microchip KSZ8863 SPI based driver support
  2020-12-07 12:56 [PATCH v5 0/6] microchip: add support for ksz88x3 driver family Michael Grzeschik
                   ` (3 preceding siblings ...)
  2020-12-07 12:56 ` [PATCH v5 4/6] net: dsa: microchip: ksz8795: add support for ksz88xx chips Michael Grzeschik
@ 2020-12-07 12:56 ` Michael Grzeschik
  2020-12-07 12:56 ` [PATCH v5 6/6] dt-bindings: net: dsa: document additional Microchip KSZ8863/8873 switch Michael Grzeschik
  5 siblings, 0 replies; 17+ messages in thread
From: Michael Grzeschik @ 2020-12-07 12:56 UTC (permalink / raw)
  To: netdev
  Cc: andrew, f.fainelli, davem, kernel, matthias.schiffer,
	woojung.huh, UNGLinuxDriver

Add KSZ88X3 driver support. We add support for the KXZ88X3 three port
switches using the SPI Interface.

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>

---
v1 -> v2: - this glue was not implemented
v2 -> v3: - this glue was part of previous bigger patch
v3 -> v4: - this glue was moved to this separate patch
v4 -> v5: - added reviewed by from f.fainelli
          - using device_get_match_data instead of own matching code
---
 drivers/net/dsa/microchip/ksz8795_spi.c | 44 ++++++++++++++++++-------
 1 file changed, 32 insertions(+), 12 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz8795_spi.c b/drivers/net/dsa/microchip/ksz8795_spi.c
index 45420c07c99fc..708f8daaedbc2 100644
--- a/drivers/net/dsa/microchip/ksz8795_spi.c
+++ b/drivers/net/dsa/microchip/ksz8795_spi.c
@@ -14,34 +14,52 @@
 #include <linux/regmap.h>
 #include <linux/spi/spi.h>
 
+#include "ksz8.h"
 #include "ksz_common.h"
 
-#define SPI_ADDR_SHIFT			12
-#define SPI_ADDR_ALIGN			3
-#define SPI_TURNAROUND_SHIFT		1
+#define KSZ8795_SPI_ADDR_SHIFT			12
+#define KSZ8795_SPI_ADDR_ALIGN			3
+#define KSZ8795_SPI_TURNAROUND_SHIFT		1
 
-KSZ_REGMAP_TABLE(ksz8795, 16, SPI_ADDR_SHIFT,
-		 SPI_TURNAROUND_SHIFT, SPI_ADDR_ALIGN);
+#define KSZ8863_SPI_ADDR_SHIFT			8
+#define KSZ8863_SPI_ADDR_ALIGN			8
+#define KSZ8863_SPI_TURNAROUND_SHIFT		0
+
+KSZ_REGMAP_TABLE(ksz8795, 16, KSZ8795_SPI_ADDR_SHIFT,
+		 KSZ8795_SPI_TURNAROUND_SHIFT, KSZ8795_SPI_ADDR_ALIGN);
+
+KSZ_REGMAP_TABLE(ksz8863, 16, KSZ8863_SPI_ADDR_SHIFT,
+		 KSZ8863_SPI_TURNAROUND_SHIFT, KSZ8863_SPI_ADDR_ALIGN);
 
 static int ksz8795_spi_probe(struct spi_device *spi)
 {
+	const struct regmap_config *regmap_config;
+	struct device *ddev = &spi->dev;
+	struct ksz8 *ksz8;
 	struct regmap_config rc;
 	struct ksz_device *dev;
-	int i, ret;
+	int i, ret = 0;
 
-	dev = ksz_switch_alloc(&spi->dev, spi);
+	ksz8 = devm_kzalloc(&spi->dev, sizeof(struct ksz8), GFP_KERNEL);
+	ksz8->priv = spi;
+
+	dev = ksz_switch_alloc(&spi->dev, ksz8);
 	if (!dev)
 		return -ENOMEM;
 
+	regmap_config = device_get_match_data(ddev);
+	if (!regmap_config)
+		return -EINVAL;
+
 	for (i = 0; i < ARRAY_SIZE(ksz8795_regmap_config); i++) {
-		rc = ksz8795_regmap_config[i];
+		rc = regmap_config[i];
 		rc.lock_arg = &dev->regmap_mutex;
 		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,
 				"Failed to initialize regmap%i: %d\n",
-				ksz8795_regmap_config[i].val_bits, ret);
+				regmap_config[i].val_bits, ret);
 			return ret;
 		}
 	}
@@ -85,9 +103,11 @@ static void ksz8795_spi_shutdown(struct spi_device *spi)
 }
 
 static const struct of_device_id ksz8795_dt_ids[] = {
-	{ .compatible = "microchip,ksz8765" },
-	{ .compatible = "microchip,ksz8794" },
-	{ .compatible = "microchip,ksz8795" },
+	{ .compatible = "microchip,ksz8765", .data = &ksz8795_regmap_config },
+	{ .compatible = "microchip,ksz8794", .data = &ksz8795_regmap_config },
+	{ .compatible = "microchip,ksz8795", .data = &ksz8795_regmap_config },
+	{ .compatible = "microchip,ksz8863", .data = &ksz8863_regmap_config },
+	{ .compatible = "microchip,ksz8873", .data = &ksz8863_regmap_config },
 	{},
 };
 MODULE_DEVICE_TABLE(of, ksz8795_dt_ids);
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v5 6/6] dt-bindings: net: dsa: document additional Microchip KSZ8863/8873 switch
  2020-12-07 12:56 [PATCH v5 0/6] microchip: add support for ksz88x3 driver family Michael Grzeschik
                   ` (4 preceding siblings ...)
  2020-12-07 12:56 ` [PATCH v5 5/6] net: dsa: microchip: Add Microchip KSZ8863 SPI based driver support Michael Grzeschik
@ 2020-12-07 12:56 ` Michael Grzeschik
  5 siblings, 0 replies; 17+ messages in thread
From: Michael Grzeschik @ 2020-12-07 12:56 UTC (permalink / raw)
  To: netdev
  Cc: andrew, f.fainelli, davem, kernel, matthias.schiffer,
	woojung.huh, UNGLinuxDriver, devicetree, Rob Herring

It is a 3-Port 10/100 Ethernet Switch. One CPU-Port and two
Switch-Ports.

Cc: devicetree@vger.kernel.org
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Acked-by: Rob Herring <robh@kernel.org>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>

---
v1 -> v3: - nothing changes
          - already Acked-by Rob Herring
v1 -> v4: - nothing changes
v4 -> v5: - nothing changes
---
 Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml b/Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml
index 9f7d131bbcef0..84985f53bffd4 100644
--- a/Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml
+++ b/Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml
@@ -21,6 +21,8 @@ properties:
       - microchip,ksz8765
       - microchip,ksz8794
       - microchip,ksz8795
+      - microchip,ksz8863
+      - microchip,ksz8873
       - microchip,ksz9477
       - microchip,ksz9897
       - microchip,ksz9896
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH v5 3/6] net: dsa: microchip: ksz8795: move register offsets and shifts to separate struct
  2020-12-07 12:56 ` [PATCH v5 3/6] net: dsa: microchip: ksz8795: move register offsets and shifts to separate struct Michael Grzeschik
@ 2020-12-07 14:11     ` kernel test robot
  2020-12-07 15:01   ` David Miller
                       ` (2 subsequent siblings)
  3 siblings, 0 replies; 17+ messages in thread
From: kernel test robot @ 2020-12-07 14:11 UTC (permalink / raw)
  To: Michael Grzeschik, netdev
  Cc: kbuild-all, andrew, f.fainelli, davem, kernel, matthias.schiffer,
	woojung.huh, UNGLinuxDriver

[-- Attachment #1: Type: text/plain, Size: 2373 bytes --]

Hi Michael,

I love your patch! Perhaps something to improve:

[auto build test WARNING on net-next/master]
[also build test WARNING on next-20201207]
[cannot apply to net/master ipvs/master linus/master v5.10-rc7]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Michael-Grzeschik/microchip-add-support-for-ksz88x3-driver-family/20201207-205945
base:   https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git af3f4a85d90218bb59315d591bd2bffa5e646466
config: arc-allyesconfig (attached as .config)
compiler: arceb-elf-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/db1f7322c8fa2c28587f13ab3eebbb6ee02874b1
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Michael-Grzeschik/microchip-add-support-for-ksz88x3-driver-family/20201207-205945
        git checkout db1f7322c8fa2c28587f13ab3eebbb6ee02874b1
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=arc 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/net/dsa/microchip/ksz8795.c:69:27: warning: initialized field overwritten [-Woverride-init]
      69 |  [DYNAMIC_MAC_ENTRIES]  = 29,
         |                           ^~
   drivers/net/dsa/microchip/ksz8795.c:69:27: note: (near initialization for 'ksz8795_shifts[5]')

vim +69 drivers/net/dsa/microchip/ksz8795.c

    62	
    63	static const u8 ksz8795_shifts[] = {
    64		[VLAN_TABLE_MEMBERSHIP]		= 7,
    65		[VLAN_TABLE]			= 16,
    66		[STATIC_MAC_FWD_PORTS]		= 16,
    67		[STATIC_MAC_FID]		= 24,
    68		[DYNAMIC_MAC_ENTRIES_H]		= 3,
  > 69		[DYNAMIC_MAC_ENTRIES]		= 29,
    70		[DYNAMIC_MAC_FID]		= 16,
    71		[DYNAMIC_MAC_TIMESTAMP]		= 27,
    72		[DYNAMIC_MAC_SRC_PORT]		= 24,
    73	};
    74	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 66553 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v5 3/6] net: dsa: microchip: ksz8795: move register offsets and shifts to separate struct
@ 2020-12-07 14:11     ` kernel test robot
  0 siblings, 0 replies; 17+ messages in thread
From: kernel test robot @ 2020-12-07 14:11 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 2429 bytes --]

Hi Michael,

I love your patch! Perhaps something to improve:

[auto build test WARNING on net-next/master]
[also build test WARNING on next-20201207]
[cannot apply to net/master ipvs/master linus/master v5.10-rc7]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Michael-Grzeschik/microchip-add-support-for-ksz88x3-driver-family/20201207-205945
base:   https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git af3f4a85d90218bb59315d591bd2bffa5e646466
config: arc-allyesconfig (attached as .config)
compiler: arceb-elf-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/db1f7322c8fa2c28587f13ab3eebbb6ee02874b1
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Michael-Grzeschik/microchip-add-support-for-ksz88x3-driver-family/20201207-205945
        git checkout db1f7322c8fa2c28587f13ab3eebbb6ee02874b1
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=arc 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/net/dsa/microchip/ksz8795.c:69:27: warning: initialized field overwritten [-Woverride-init]
      69 |  [DYNAMIC_MAC_ENTRIES]  = 29,
         |                           ^~
   drivers/net/dsa/microchip/ksz8795.c:69:27: note: (near initialization for 'ksz8795_shifts[5]')

vim +69 drivers/net/dsa/microchip/ksz8795.c

    62	
    63	static const u8 ksz8795_shifts[] = {
    64		[VLAN_TABLE_MEMBERSHIP]		= 7,
    65		[VLAN_TABLE]			= 16,
    66		[STATIC_MAC_FWD_PORTS]		= 16,
    67		[STATIC_MAC_FID]		= 24,
    68		[DYNAMIC_MAC_ENTRIES_H]		= 3,
  > 69		[DYNAMIC_MAC_ENTRIES]		= 29,
    70		[DYNAMIC_MAC_FID]		= 16,
    71		[DYNAMIC_MAC_TIMESTAMP]		= 27,
    72		[DYNAMIC_MAC_SRC_PORT]		= 24,
    73	};
    74	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 66553 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v5 3/6] net: dsa: microchip: ksz8795: move register offsets and shifts to separate struct
  2020-12-07 12:56 ` [PATCH v5 3/6] net: dsa: microchip: ksz8795: move register offsets and shifts to separate struct Michael Grzeschik
  2020-12-07 14:11     ` kernel test robot
@ 2020-12-07 15:01   ` David Miller
  2020-12-07 20:02   ` Tristram.Ha
  2020-12-11  4:21     ` kernel test robot
  3 siblings, 0 replies; 17+ messages in thread
From: David Miller @ 2020-12-07 15:01 UTC (permalink / raw)
  To: m.grzeschik
  Cc: netdev, andrew, f.fainelli, kernel, matthias.schiffer,
	woojung.huh, UNGLinuxDriver

From: Michael Grzeschik <m.grzeschik@pengutronix.de>
Date: Mon,  7 Dec 2020 13:56:24 +0100

> @@ -991,13 +1090,16 @@ static void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port)
>  static void ksz8_config_cpu_port(struct dsa_switch *ds)
>  {
>  	struct ksz_device *dev = ds->priv;
> +	struct ksz8 *ksz8 = dev->priv;
> +	const u8 *regs = ksz8->regs;
> +	const u32 *masks = ksz8->masks;
>  	struct ksz_port *p;
>  	u8 remote;
>  	int i;
>  

Please use reverse christmas tree ordering for local variables.

Thank you.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [PATCH v5 3/6] net: dsa: microchip: ksz8795: move register offsets and shifts to separate struct
  2020-12-07 12:56 ` [PATCH v5 3/6] net: dsa: microchip: ksz8795: move register offsets and shifts to separate struct Michael Grzeschik
  2020-12-07 14:11     ` kernel test robot
  2020-12-07 15:01   ` David Miller
@ 2020-12-07 20:02   ` Tristram.Ha
  2020-12-07 21:44     ` Michael Grzeschik
  2020-12-11  4:21     ` kernel test robot
  3 siblings, 1 reply; 17+ messages in thread
From: Tristram.Ha @ 2020-12-07 20:02 UTC (permalink / raw)
  To: m.grzeschik
  Cc: andrew, f.fainelli, davem, kernel, netdev, matthias.schiffer,
	Woojung.Huh, UNGLinuxDriver

> In order to get this driver used with other switches the functions need
> to use different offsets and register shifts. This patch changes the
> direct use of the register defines to register description structures,
> which can be set depending on the chips register layout.
> 
> Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
> 
> ---
> v1 -> v4: - extracted this change from bigger previous patch
> v4 -> v5: - added missing variables in ksz8_r_vlan_entries
>           - moved shifts, masks and registers to arrays indexed by enums
>           - using unsigned types where possible
> ---
>  drivers/net/dsa/microchip/ksz8.h        |  69 +++++++
>  drivers/net/dsa/microchip/ksz8795.c     | 261 +++++++++++++++++-------
>  drivers/net/dsa/microchip/ksz8795_reg.h |  85 --------
>  3 files changed, 253 insertions(+), 162 deletions(-)
>  create mode 100644 drivers/net/dsa/microchip/ksz8.h

Sorry for not respond to these patches sooner.

There are 3 older KSZ switch families: KSZ8863/73, KSZ8895/64, and KSZ8795/94.
The newer KSZ8795 is not considered an upgrade for KSZ8895, so some of
these switch registers are moved around and some features are dropped.

It is best to have one driver to support all 3 switches, but some operations are
Incompatible so it may be better to keep the drivers separate for now.

For basic operations those issues may not occur so it seems simple to have
one driver handling all 3 switches.  I will come up with a list of those
incompatibilities.

The tail tag format of KSZ8863 is different from KSZ8895 and KSZ8795, but
because of the DSA driver implementation that issue never comes up.

> -static void ksz8_from_vlan(u16 vlan, u8 *fid, u8 *member, u8 *valid)
> +static void ksz8_from_vlan(struct ksz_device *dev, u32 vlan, u8 *fid,
> +                          u8 *member, u8 *valid)
>  {
> -       *fid = vlan & VLAN_TABLE_FID;
> -       *member = (vlan & VLAN_TABLE_MEMBERSHIP) >>
> VLAN_TABLE_MEMBERSHIP_S;
> -       *valid = !!(vlan & VLAN_TABLE_VALID);
> +       struct ksz8 *ksz8 = dev->priv;
> +       const u32 *masks = ksz8->masks;
> +       const u8 *shifts = ksz8->shifts;
> +
> +       *fid = vlan & masks[VLAN_TABLE_FID];
> +       *member = (vlan & masks[VLAN_TABLE_MEMBERSHIP]) >>
> +                       shifts[VLAN_TABLE_MEMBERSHIP_S];
> +       *valid = !!(vlan & masks[VLAN_TABLE_VALID]);
>  }
> 
> -static void ksz8_to_vlan(u8 fid, u8 member, u8 valid, u16 *vlan)
> +static void ksz8_to_vlan(struct ksz_device *dev, u8 fid, u8 member, u8
> valid,
> +                        u32 *vlan)
>  {
> +       struct ksz8 *ksz8 = dev->priv;
> +       const u32 *masks = ksz8->masks;
> +       const u8 *shifts = ksz8->shifts;
> +
>         *vlan = fid;
> -       *vlan |= (u16)member << VLAN_TABLE_MEMBERSHIP_S;
> +       *vlan |= (u16)member << shifts[VLAN_TABLE_MEMBERSHIP_S];
>         if (valid)
> -               *vlan |= VLAN_TABLE_VALID;
> +               *vlan |= masks[VLAN_TABLE_VALID];
>  }
> 
>  static void ksz8_r_vlan_entries(struct ksz_device *dev, u16 addr)
>  {
> +       struct ksz8 *ksz8 = dev->priv;
> +       const u8 *shifts = ksz8->shifts;
>         u64 data;
>         int i;
> 
> @@ -418,7 +509,7 @@ static void ksz8_r_vlan_entries(struct ksz_device
> *dev, u16 addr)
>         addr *= dev->phy_port_cnt;
>         for (i = 0; i < dev->phy_port_cnt; i++) {
>                 dev->vlan_cache[addr + i].table[0] = (u16)data;
> -               data >>= VLAN_TABLE_S;
> +               data >>= shifts[VLAN_TABLE];
>         }
>  }
> 
> @@ -454,6 +545,8 @@ static void ksz8_w_vlan_table(struct ksz_device *dev,
> u16 vid, u32 vlan)
> 

The VLAN table operation in KSZ8863 is completely different from KSZ8795.

> -/**
> - * VLAN_TABLE_FID                      00-007F007F-007F007F
> - * VLAN_TABLE_MEMBERSHIP               00-0F800F80-0F800F80
> - * VLAN_TABLE_VALID                    00-10001000-10001000
> - */
> -
> -#define VLAN_TABLE_FID                 0x007F
> -#define VLAN_TABLE_MEMBERSHIP          0x0F80
> -#define VLAN_TABLE_VALID               0x1000
> -
> -#define VLAN_TABLE_MEMBERSHIP_S                7
> -#define VLAN_TABLE_S                   16
> -

In KSZ8795 you can use all 4096 VLAN id.  Each entry in the table contains
4 VID.  The FID is actually used for lookup and there is a limit, so you need
to convert VID to FID when programming the VLAN table.

The only effect of using FID is the same MAC address can be used in
different VLANs.

In KSZ8863 there are only 16 entries in the VLAN table.  Just like static
MAC table each entry is programmed using an index.  The entry contains
the VID, which does not have any relationship with the index unlike in
KSZ8795.

The number of FID is also limited to 16.  So the maximum VLAN used is 16.

>  /**
>   * MIB_COUNTER_VALUE                   00-00000000-3FFFFFFF
>   * MIB_TOTAL_BYTES                     00-0000000F-FFFFFFFF
> @@ -956,9 +874,6 @@
>   * MIB_COUNTER_OVERFLOW                        00-00000040-00000000
>   */
> 
> -#define MIB_COUNTER_OVERFLOW           BIT(6)
> -#define MIB_COUNTER_VALID              BIT(5)
> -
>  #define MIB_COUNTER_VALUE              0x3FFFFFFF

The MIB counters are also a little different in KSZ8863 and KSZ8795.
KSZ8863 may have smaller total bytes.  In normal operation this issue may
not come up.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v5 3/6] net: dsa: microchip: ksz8795: move register offsets and shifts to separate struct
  2020-12-07 20:02   ` Tristram.Ha
@ 2020-12-07 21:44     ` Michael Grzeschik
  2020-12-15 16:31       ` Michael Grzeschik
  0 siblings, 1 reply; 17+ messages in thread
From: Michael Grzeschik @ 2020-12-07 21:44 UTC (permalink / raw)
  To: Tristram.Ha
  Cc: andrew, f.fainelli, davem, kernel, netdev, matthias.schiffer,
	Woojung.Huh, UNGLinuxDriver

[-- Attachment #1: Type: text/plain, Size: 7131 bytes --]

On Mon, Dec 07, 2020 at 08:02:57PM +0000, Tristram.Ha@microchip.com wrote:
>> In order to get this driver used with other switches the functions need
>> to use different offsets and register shifts. This patch changes the
>> direct use of the register defines to register description structures,
>> which can be set depending on the chips register layout.
>>
>> Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
>>
>> ---
>> v1 -> v4: - extracted this change from bigger previous patch
>> v4 -> v5: - added missing variables in ksz8_r_vlan_entries
>>           - moved shifts, masks and registers to arrays indexed by enums
>>           - using unsigned types where possible
>> ---
>>  drivers/net/dsa/microchip/ksz8.h        |  69 +++++++
>>  drivers/net/dsa/microchip/ksz8795.c     | 261 +++++++++++++++++-------
>>  drivers/net/dsa/microchip/ksz8795_reg.h |  85 --------
>>  3 files changed, 253 insertions(+), 162 deletions(-)
>>  create mode 100644 drivers/net/dsa/microchip/ksz8.h
>
>Sorry for not respond to these patches sooner.
>
>There are 3 older KSZ switch families: KSZ8863/73, KSZ8895/64, and KSZ8795/94.
>The newer KSZ8795 is not considered an upgrade for KSZ8895, so some of
>these switch registers are moved around and some features are dropped.
>
>It is best to have one driver to support all 3 switches, but some operations are
>Incompatible so it may be better to keep the drivers separate for now.
>
>For basic operations those issues may not occur so it seems simple to have
>one driver handling all 3 switches.  I will come up with a list of those
>incompatibilities.

Look into the next patch. I handled many special cases for the ksz8863
in the "net: dsa: microchip: ksz8795: add support for ksz88xx chips".
These cases, including the VLAN, Tagging ... are handled by checking if
the feautre IS_88X3 is set. This can be extended to other types as well.

My first version of the patches was an RFC series that was mentioning
that it is based on your RFC series for the ksz8895.

8863 RFC: https://patchwork.ozlabs.org/project/netdev/cover/20190508211330.19328-1-m.grzeschik@pengutronix.de/

8895 RFC: https://patchwork.ozlabs.org/patch/822712/

I remember, that I was reading the datasheets of all three chips,
8895, 8863 and 8795. After the 8795 series was mainline, the
obvious next step was to get the 8863 into the 8795 code. The result
is this series.

So the obvious question is, how far does your 8895 series differ
from the 8863 switches?

>The tail tag format of KSZ8863 is different from KSZ8895 and KSZ8795, but
>because of the DSA driver implementation that issue never comes up.

Right. In the first four series I kept an extra tail tag patch. But
after cleaning up I figured that the Implementation matched the
one for the KSZ9893. Therefor I reused the tag code.

>> -static void ksz8_from_vlan(u16 vlan, u8 *fid, u8 *member, u8 *valid)
>> +static void ksz8_from_vlan(struct ksz_device *dev, u32 vlan, u8 *fid,
>> +                          u8 *member, u8 *valid)
>>  {
>> -       *fid = vlan & VLAN_TABLE_FID;
>> -       *member = (vlan & VLAN_TABLE_MEMBERSHIP) >>
>> VLAN_TABLE_MEMBERSHIP_S;
>> -       *valid = !!(vlan & VLAN_TABLE_VALID);
>> +       struct ksz8 *ksz8 = dev->priv;
>> +       const u32 *masks = ksz8->masks;
>> +       const u8 *shifts = ksz8->shifts;
>> +
>> +       *fid = vlan & masks[VLAN_TABLE_FID];
>> +       *member = (vlan & masks[VLAN_TABLE_MEMBERSHIP]) >>
>> +                       shifts[VLAN_TABLE_MEMBERSHIP_S];
>> +       *valid = !!(vlan & masks[VLAN_TABLE_VALID]);
>>  }
>>
>> -static void ksz8_to_vlan(u8 fid, u8 member, u8 valid, u16 *vlan)
>> +static void ksz8_to_vlan(struct ksz_device *dev, u8 fid, u8 member, u8
>> valid,
>> +                        u32 *vlan)
>>  {
>> +       struct ksz8 *ksz8 = dev->priv;
>> +       const u32 *masks = ksz8->masks;
>> +       const u8 *shifts = ksz8->shifts;
>> +
>>         *vlan = fid;
>> -       *vlan |= (u16)member << VLAN_TABLE_MEMBERSHIP_S;
>> +       *vlan |= (u16)member << shifts[VLAN_TABLE_MEMBERSHIP_S];
>>         if (valid)
>> -               *vlan |= VLAN_TABLE_VALID;
>> +               *vlan |= masks[VLAN_TABLE_VALID];
>>  }
>>
>>  static void ksz8_r_vlan_entries(struct ksz_device *dev, u16 addr)
>>  {
>> +       struct ksz8 *ksz8 = dev->priv;
>> +       const u8 *shifts = ksz8->shifts;
>>         u64 data;
>>         int i;
>>
>> @@ -418,7 +509,7 @@ static void ksz8_r_vlan_entries(struct ksz_device
>> *dev, u16 addr)
>>         addr *= dev->phy_port_cnt;
>>         for (i = 0; i < dev->phy_port_cnt; i++) {
>>                 dev->vlan_cache[addr + i].table[0] = (u16)data;
>> -               data >>= VLAN_TABLE_S;
>> +               data >>= shifts[VLAN_TABLE];
>>         }
>>  }
>>
>> @@ -454,6 +545,8 @@ static void ksz8_w_vlan_table(struct ksz_device *dev,
>> u16 vid, u32 vlan)
>>
>
>The VLAN table operation in KSZ8863 is completely different from KSZ8795.
>
>> -/**
>> - * VLAN_TABLE_FID                      00-007F007F-007F007F
>> - * VLAN_TABLE_MEMBERSHIP               00-0F800F80-0F800F80
>> - * VLAN_TABLE_VALID                    00-10001000-10001000
>> - */
>> -
>> -#define VLAN_TABLE_FID                 0x007F
>> -#define VLAN_TABLE_MEMBERSHIP          0x0F80
>> -#define VLAN_TABLE_VALID               0x1000
>> -
>> -#define VLAN_TABLE_MEMBERSHIP_S                7
>> -#define VLAN_TABLE_S                   16
>> -
>
>In KSZ8795 you can use all 4096 VLAN id.  Each entry in the table contains
>4 VID.  The FID is actually used for lookup and there is a limit, so you need
>to convert VID to FID when programming the VLAN table.
>
>The only effect of using FID is the same MAC address can be used in
>different VLANs.
>
>In KSZ8863 there are only 16 entries in the VLAN table.  Just like static
>MAC table each entry is programmed using an index.  The entry contains
>the VID, which does not have any relationship with the index unlike in
>KSZ8795.
>
>The number of FID is also limited to 16.  So the maximum VLAN used is 16.
>
>>  /**
>>   * MIB_COUNTER_VALUE                   00-00000000-3FFFFFFF
>>   * MIB_TOTAL_BYTES                     00-0000000F-FFFFFFFF
>> @@ -956,9 +874,6 @@
>>   * MIB_COUNTER_OVERFLOW                        00-00000040-00000000
>>   */
>>
>> -#define MIB_COUNTER_OVERFLOW           BIT(6)
>> -#define MIB_COUNTER_VALID              BIT(5)
>> -
>>  #define MIB_COUNTER_VALUE              0x3FFFFFFF
>
>The MIB counters are also a little different in KSZ8863 and KSZ8795.
>KSZ8863 may have smaller total bytes.  In normal operation this issue may
>not come up.

As mentioned before, these cases are handled differently for both
types of drivers.

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v5 3/6] net: dsa: microchip: ksz8795: move register offsets and shifts to separate struct
  2020-12-07 12:56 ` [PATCH v5 3/6] net: dsa: microchip: ksz8795: move register offsets and shifts to separate struct Michael Grzeschik
@ 2020-12-11  4:21     ` kernel test robot
  2020-12-07 15:01   ` David Miller
                       ` (2 subsequent siblings)
  3 siblings, 0 replies; 17+ messages in thread
From: kernel test robot @ 2020-12-11  4:21 UTC (permalink / raw)
  To: Michael Grzeschik, netdev
  Cc: kbuild-all, clang-built-linux, andrew, f.fainelli, davem, kernel,
	matthias.schiffer, woojung.huh, UNGLinuxDriver

[-- Attachment #1: Type: text/plain, Size: 11611 bytes --]

Hi Michael,

I love your patch! Perhaps something to improve:

[auto build test WARNING on net-next/master]
[also build test WARNING on next-20201210]
[cannot apply to net/master ipvs/master linus/master v5.10-rc7]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Michael-Grzeschik/microchip-add-support-for-ksz88x3-driver-family/20201207-205945
base:   https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git af3f4a85d90218bb59315d591bd2bffa5e646466
config: riscv-randconfig-r003-20201210 (attached as .config)
compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project 1968804ac726e7674d5de22bc2204b45857da344)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install riscv cross compiling tool for clang build
        # apt-get install binutils-riscv64-linux-gnu
        # https://github.com/0day-ci/linux/commit/db1f7322c8fa2c28587f13ab3eebbb6ee02874b1
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Michael-Grzeschik/microchip-add-support-for-ksz88x3-driver-family/20201207-205945
        git checkout db1f7322c8fa2c28587f13ab3eebbb6ee02874b1
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=riscv 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

                                                                           ~~~~~~~~~~ ^
   arch/riscv/include/asm/mmio.h:87:48: note: expanded from macro 'readb_cpu'
   #define readb_cpu(c)            ({ u8  __r = __raw_readb(c); __r; })
                                                            ^
   In file included from drivers/net/dsa/microchip/ksz8795.c:11:
   In file included from include/linux/gpio.h:62:
   In file included from include/asm-generic/gpio.h:11:
   In file included from include/linux/gpio/driver.h:7:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:564:9: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           return inw(addr);
                  ^~~~~~~~~
   arch/riscv/include/asm/io.h:56:76: note: expanded from macro 'inw'
   #define inw(c)          ({ u16 __v; __io_pbr(); __v = readw_cpu((void*)(PCI_IOBASE + (c))); __io_par(__v); __v; })
                                                                           ~~~~~~~~~~ ^
   arch/riscv/include/asm/mmio.h:88:76: note: expanded from macro 'readw_cpu'
   #define readw_cpu(c)            ({ u16 __r = le16_to_cpu((__force __le16)__raw_readw(c)); __r; })
                                                                                        ^
   include/uapi/linux/byteorder/little_endian.h:36:51: note: expanded from macro '__le16_to_cpu'
   #define __le16_to_cpu(x) ((__force __u16)(__le16)(x))
                                                     ^
   In file included from drivers/net/dsa/microchip/ksz8795.c:11:
   In file included from include/linux/gpio.h:62:
   In file included from include/asm-generic/gpio.h:11:
   In file included from include/linux/gpio/driver.h:7:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:572:9: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           return inl(addr);
                  ^~~~~~~~~
   arch/riscv/include/asm/io.h:57:76: note: expanded from macro 'inl'
   #define inl(c)          ({ u32 __v; __io_pbr(); __v = readl_cpu((void*)(PCI_IOBASE + (c))); __io_par(__v); __v; })
                                                                           ~~~~~~~~~~ ^
   arch/riscv/include/asm/mmio.h:89:76: note: expanded from macro 'readl_cpu'
   #define readl_cpu(c)            ({ u32 __r = le32_to_cpu((__force __le32)__raw_readl(c)); __r; })
                                                                                        ^
   include/uapi/linux/byteorder/little_endian.h:34:51: note: expanded from macro '__le32_to_cpu'
   #define __le32_to_cpu(x) ((__force __u32)(__le32)(x))
                                                     ^
   In file included from drivers/net/dsa/microchip/ksz8795.c:11:
   In file included from include/linux/gpio.h:62:
   In file included from include/asm-generic/gpio.h:11:
   In file included from include/linux/gpio/driver.h:7:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:580:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           outb(value, addr);
           ^~~~~~~~~~~~~~~~~
   arch/riscv/include/asm/io.h:59:68: note: expanded from macro 'outb'
   #define outb(v,c)       ({ __io_pbw(); writeb_cpu((v),(void*)(PCI_IOBASE + (c))); __io_paw(); })
                                                                 ~~~~~~~~~~ ^
   arch/riscv/include/asm/mmio.h:91:52: note: expanded from macro 'writeb_cpu'
   #define writeb_cpu(v, c)        ((void)__raw_writeb((v), (c)))
                                                             ^
   In file included from drivers/net/dsa/microchip/ksz8795.c:11:
   In file included from include/linux/gpio.h:62:
   In file included from include/asm-generic/gpio.h:11:
   In file included from include/linux/gpio/driver.h:7:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:588:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           outw(value, addr);
           ^~~~~~~~~~~~~~~~~
   arch/riscv/include/asm/io.h:60:68: note: expanded from macro 'outw'
   #define outw(v,c)       ({ __io_pbw(); writew_cpu((v),(void*)(PCI_IOBASE + (c))); __io_paw(); })
                                                                 ~~~~~~~~~~ ^
   arch/riscv/include/asm/mmio.h:92:76: note: expanded from macro 'writew_cpu'
   #define writew_cpu(v, c)        ((void)__raw_writew((__force u16)cpu_to_le16(v), (c)))
                                                                                     ^
   In file included from drivers/net/dsa/microchip/ksz8795.c:11:
   In file included from include/linux/gpio.h:62:
   In file included from include/asm-generic/gpio.h:11:
   In file included from include/linux/gpio/driver.h:7:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:596:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           outl(value, addr);
           ^~~~~~~~~~~~~~~~~
   arch/riscv/include/asm/io.h:61:68: note: expanded from macro 'outl'
   #define outl(v,c)       ({ __io_pbw(); writel_cpu((v),(void*)(PCI_IOBASE + (c))); __io_paw(); })
                                                                 ~~~~~~~~~~ ^
   arch/riscv/include/asm/mmio.h:93:76: note: expanded from macro 'writel_cpu'
   #define writel_cpu(v, c)        ((void)__raw_writel((__force u32)cpu_to_le32(v), (c)))
                                                                                     ^
   In file included from drivers/net/dsa/microchip/ksz8795.c:11:
   In file included from include/linux/gpio.h:62:
   In file included from include/asm-generic/gpio.h:11:
   In file included from include/linux/gpio/driver.h:7:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:1005:55: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           return (port > MMIO_UPPER_LIMIT) ? NULL : PCI_IOBASE + port;
                                                     ~~~~~~~~~~ ^
>> drivers/net/dsa/microchip/ksz8795.c:69:27: warning: initializer overrides prior initialization of this subobject [-Winitializer-overrides]
           [DYNAMIC_MAC_ENTRIES]           = 29,
                                             ^~
   drivers/net/dsa/microchip/ksz8795.c:64:29: note: previous initialization is here
           [VLAN_TABLE_MEMBERSHIP]         = 7,
                                             ^
   8 warnings generated.
   /tmp/ksz8795-ce9b6a.s: Assembler messages:
   /tmp/ksz8795-ce9b6a.s:183: Error: unrecognized opcode `zext.b a2,s9'
   /tmp/ksz8795-ce9b6a.s:447: Error: unrecognized opcode `zext.b a2,a1'
   /tmp/ksz8795-ce9b6a.s:454: Error: unrecognized opcode `zext.b a2,a0'
   /tmp/ksz8795-ce9b6a.s:521: Error: unrecognized opcode `zext.b a0,s3'
   /tmp/ksz8795-ce9b6a.s:555: Error: unrecognized opcode `zext.b s6,s3'
   /tmp/ksz8795-ce9b6a.s:568: Error: unrecognized opcode `zext.b s3,s1'
   /tmp/ksz8795-ce9b6a.s:635: Error: unrecognized opcode `zext.b a0,s3'
   /tmp/ksz8795-ce9b6a.s:654: Error: unrecognized opcode `zext.b a0,s3'
   /tmp/ksz8795-ce9b6a.s:737: Error: unrecognized opcode `zext.b s3,s3'
   /tmp/ksz8795-ce9b6a.s:753: Error: unrecognized opcode `zext.b s1,a1'
   /tmp/ksz8795-ce9b6a.s:794: Error: unrecognized opcode `zext.b s3,s3'
   /tmp/ksz8795-ce9b6a.s:836: Error: unrecognized opcode `zext.b s1,a1'
   /tmp/ksz8795-ce9b6a.s:880: Error: unrecognized opcode `zext.b s1,a1'
   /tmp/ksz8795-ce9b6a.s:1548: Error: unrecognized opcode `zext.b a2,a1'
   /tmp/ksz8795-ce9b6a.s:1572: Error: unrecognized opcode `zext.b a2,a1'
   /tmp/ksz8795-ce9b6a.s:1610: Error: unrecognized opcode `zext.b s3,a1'
   /tmp/ksz8795-ce9b6a.s:1648: Error: unrecognized opcode `zext.b a2,a0'
   /tmp/ksz8795-ce9b6a.s:1658: Error: unrecognized opcode `zext.b a2,a0'
   /tmp/ksz8795-ce9b6a.s:1665: Error: unrecognized opcode `zext.b a2,a0'
   /tmp/ksz8795-ce9b6a.s:1676: Error: unrecognized opcode `zext.b a2,a0'
   /tmp/ksz8795-ce9b6a.s:1687: Error: unrecognized opcode `zext.b a2,a0'
   /tmp/ksz8795-ce9b6a.s:2701: Error: unrecognized opcode `zext.b a2,s7'
   /tmp/ksz8795-ce9b6a.s:2868: Error: unrecognized opcode `zext.b a4,a4'
   /tmp/ksz8795-ce9b6a.s:2876: Error: unrecognized opcode `zext.b a1,a1'
   /tmp/ksz8795-ce9b6a.s:3027: Error: unrecognized opcode `zext.b a1,a1'
   /tmp/ksz8795-ce9b6a.s:3049: Error: unrecognized opcode `zext.b a2,a2'
   clang-12: error: assembler command failed with exit code 1 (use -v to see invocation)

vim +69 drivers/net/dsa/microchip/ksz8795.c

    62	
    63	static const u8 ksz8795_shifts[] = {
    64		[VLAN_TABLE_MEMBERSHIP]		= 7,
    65		[VLAN_TABLE]			= 16,
    66		[STATIC_MAC_FWD_PORTS]		= 16,
    67		[STATIC_MAC_FID]		= 24,
    68		[DYNAMIC_MAC_ENTRIES_H]		= 3,
  > 69		[DYNAMIC_MAC_ENTRIES]		= 29,
    70		[DYNAMIC_MAC_FID]		= 16,
    71		[DYNAMIC_MAC_TIMESTAMP]		= 27,
    72		[DYNAMIC_MAC_SRC_PORT]		= 24,
    73	};
    74	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 36204 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v5 3/6] net: dsa: microchip: ksz8795: move register offsets and shifts to separate struct
@ 2020-12-11  4:21     ` kernel test robot
  0 siblings, 0 replies; 17+ messages in thread
From: kernel test robot @ 2020-12-11  4:21 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 11800 bytes --]

Hi Michael,

I love your patch! Perhaps something to improve:

[auto build test WARNING on net-next/master]
[also build test WARNING on next-20201210]
[cannot apply to net/master ipvs/master linus/master v5.10-rc7]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Michael-Grzeschik/microchip-add-support-for-ksz88x3-driver-family/20201207-205945
base:   https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git af3f4a85d90218bb59315d591bd2bffa5e646466
config: riscv-randconfig-r003-20201210 (attached as .config)
compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project 1968804ac726e7674d5de22bc2204b45857da344)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install riscv cross compiling tool for clang build
        # apt-get install binutils-riscv64-linux-gnu
        # https://github.com/0day-ci/linux/commit/db1f7322c8fa2c28587f13ab3eebbb6ee02874b1
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Michael-Grzeschik/microchip-add-support-for-ksz88x3-driver-family/20201207-205945
        git checkout db1f7322c8fa2c28587f13ab3eebbb6ee02874b1
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=riscv 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

                                                                           ~~~~~~~~~~ ^
   arch/riscv/include/asm/mmio.h:87:48: note: expanded from macro 'readb_cpu'
   #define readb_cpu(c)            ({ u8  __r = __raw_readb(c); __r; })
                                                            ^
   In file included from drivers/net/dsa/microchip/ksz8795.c:11:
   In file included from include/linux/gpio.h:62:
   In file included from include/asm-generic/gpio.h:11:
   In file included from include/linux/gpio/driver.h:7:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:564:9: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           return inw(addr);
                  ^~~~~~~~~
   arch/riscv/include/asm/io.h:56:76: note: expanded from macro 'inw'
   #define inw(c)          ({ u16 __v; __io_pbr(); __v = readw_cpu((void*)(PCI_IOBASE + (c))); __io_par(__v); __v; })
                                                                           ~~~~~~~~~~ ^
   arch/riscv/include/asm/mmio.h:88:76: note: expanded from macro 'readw_cpu'
   #define readw_cpu(c)            ({ u16 __r = le16_to_cpu((__force __le16)__raw_readw(c)); __r; })
                                                                                        ^
   include/uapi/linux/byteorder/little_endian.h:36:51: note: expanded from macro '__le16_to_cpu'
   #define __le16_to_cpu(x) ((__force __u16)(__le16)(x))
                                                     ^
   In file included from drivers/net/dsa/microchip/ksz8795.c:11:
   In file included from include/linux/gpio.h:62:
   In file included from include/asm-generic/gpio.h:11:
   In file included from include/linux/gpio/driver.h:7:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:572:9: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           return inl(addr);
                  ^~~~~~~~~
   arch/riscv/include/asm/io.h:57:76: note: expanded from macro 'inl'
   #define inl(c)          ({ u32 __v; __io_pbr(); __v = readl_cpu((void*)(PCI_IOBASE + (c))); __io_par(__v); __v; })
                                                                           ~~~~~~~~~~ ^
   arch/riscv/include/asm/mmio.h:89:76: note: expanded from macro 'readl_cpu'
   #define readl_cpu(c)            ({ u32 __r = le32_to_cpu((__force __le32)__raw_readl(c)); __r; })
                                                                                        ^
   include/uapi/linux/byteorder/little_endian.h:34:51: note: expanded from macro '__le32_to_cpu'
   #define __le32_to_cpu(x) ((__force __u32)(__le32)(x))
                                                     ^
   In file included from drivers/net/dsa/microchip/ksz8795.c:11:
   In file included from include/linux/gpio.h:62:
   In file included from include/asm-generic/gpio.h:11:
   In file included from include/linux/gpio/driver.h:7:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:580:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           outb(value, addr);
           ^~~~~~~~~~~~~~~~~
   arch/riscv/include/asm/io.h:59:68: note: expanded from macro 'outb'
   #define outb(v,c)       ({ __io_pbw(); writeb_cpu((v),(void*)(PCI_IOBASE + (c))); __io_paw(); })
                                                                 ~~~~~~~~~~ ^
   arch/riscv/include/asm/mmio.h:91:52: note: expanded from macro 'writeb_cpu'
   #define writeb_cpu(v, c)        ((void)__raw_writeb((v), (c)))
                                                             ^
   In file included from drivers/net/dsa/microchip/ksz8795.c:11:
   In file included from include/linux/gpio.h:62:
   In file included from include/asm-generic/gpio.h:11:
   In file included from include/linux/gpio/driver.h:7:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:588:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           outw(value, addr);
           ^~~~~~~~~~~~~~~~~
   arch/riscv/include/asm/io.h:60:68: note: expanded from macro 'outw'
   #define outw(v,c)       ({ __io_pbw(); writew_cpu((v),(void*)(PCI_IOBASE + (c))); __io_paw(); })
                                                                 ~~~~~~~~~~ ^
   arch/riscv/include/asm/mmio.h:92:76: note: expanded from macro 'writew_cpu'
   #define writew_cpu(v, c)        ((void)__raw_writew((__force u16)cpu_to_le16(v), (c)))
                                                                                     ^
   In file included from drivers/net/dsa/microchip/ksz8795.c:11:
   In file included from include/linux/gpio.h:62:
   In file included from include/asm-generic/gpio.h:11:
   In file included from include/linux/gpio/driver.h:7:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:596:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           outl(value, addr);
           ^~~~~~~~~~~~~~~~~
   arch/riscv/include/asm/io.h:61:68: note: expanded from macro 'outl'
   #define outl(v,c)       ({ __io_pbw(); writel_cpu((v),(void*)(PCI_IOBASE + (c))); __io_paw(); })
                                                                 ~~~~~~~~~~ ^
   arch/riscv/include/asm/mmio.h:93:76: note: expanded from macro 'writel_cpu'
   #define writel_cpu(v, c)        ((void)__raw_writel((__force u32)cpu_to_le32(v), (c)))
                                                                                     ^
   In file included from drivers/net/dsa/microchip/ksz8795.c:11:
   In file included from include/linux/gpio.h:62:
   In file included from include/asm-generic/gpio.h:11:
   In file included from include/linux/gpio/driver.h:7:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:1005:55: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           return (port > MMIO_UPPER_LIMIT) ? NULL : PCI_IOBASE + port;
                                                     ~~~~~~~~~~ ^
>> drivers/net/dsa/microchip/ksz8795.c:69:27: warning: initializer overrides prior initialization of this subobject [-Winitializer-overrides]
           [DYNAMIC_MAC_ENTRIES]           = 29,
                                             ^~
   drivers/net/dsa/microchip/ksz8795.c:64:29: note: previous initialization is here
           [VLAN_TABLE_MEMBERSHIP]         = 7,
                                             ^
   8 warnings generated.
   /tmp/ksz8795-ce9b6a.s: Assembler messages:
   /tmp/ksz8795-ce9b6a.s:183: Error: unrecognized opcode `zext.b a2,s9'
   /tmp/ksz8795-ce9b6a.s:447: Error: unrecognized opcode `zext.b a2,a1'
   /tmp/ksz8795-ce9b6a.s:454: Error: unrecognized opcode `zext.b a2,a0'
   /tmp/ksz8795-ce9b6a.s:521: Error: unrecognized opcode `zext.b a0,s3'
   /tmp/ksz8795-ce9b6a.s:555: Error: unrecognized opcode `zext.b s6,s3'
   /tmp/ksz8795-ce9b6a.s:568: Error: unrecognized opcode `zext.b s3,s1'
   /tmp/ksz8795-ce9b6a.s:635: Error: unrecognized opcode `zext.b a0,s3'
   /tmp/ksz8795-ce9b6a.s:654: Error: unrecognized opcode `zext.b a0,s3'
   /tmp/ksz8795-ce9b6a.s:737: Error: unrecognized opcode `zext.b s3,s3'
   /tmp/ksz8795-ce9b6a.s:753: Error: unrecognized opcode `zext.b s1,a1'
   /tmp/ksz8795-ce9b6a.s:794: Error: unrecognized opcode `zext.b s3,s3'
   /tmp/ksz8795-ce9b6a.s:836: Error: unrecognized opcode `zext.b s1,a1'
   /tmp/ksz8795-ce9b6a.s:880: Error: unrecognized opcode `zext.b s1,a1'
   /tmp/ksz8795-ce9b6a.s:1548: Error: unrecognized opcode `zext.b a2,a1'
   /tmp/ksz8795-ce9b6a.s:1572: Error: unrecognized opcode `zext.b a2,a1'
   /tmp/ksz8795-ce9b6a.s:1610: Error: unrecognized opcode `zext.b s3,a1'
   /tmp/ksz8795-ce9b6a.s:1648: Error: unrecognized opcode `zext.b a2,a0'
   /tmp/ksz8795-ce9b6a.s:1658: Error: unrecognized opcode `zext.b a2,a0'
   /tmp/ksz8795-ce9b6a.s:1665: Error: unrecognized opcode `zext.b a2,a0'
   /tmp/ksz8795-ce9b6a.s:1676: Error: unrecognized opcode `zext.b a2,a0'
   /tmp/ksz8795-ce9b6a.s:1687: Error: unrecognized opcode `zext.b a2,a0'
   /tmp/ksz8795-ce9b6a.s:2701: Error: unrecognized opcode `zext.b a2,s7'
   /tmp/ksz8795-ce9b6a.s:2868: Error: unrecognized opcode `zext.b a4,a4'
   /tmp/ksz8795-ce9b6a.s:2876: Error: unrecognized opcode `zext.b a1,a1'
   /tmp/ksz8795-ce9b6a.s:3027: Error: unrecognized opcode `zext.b a1,a1'
   /tmp/ksz8795-ce9b6a.s:3049: Error: unrecognized opcode `zext.b a2,a2'
   clang-12: error: assembler command failed with exit code 1 (use -v to see invocation)

vim +69 drivers/net/dsa/microchip/ksz8795.c

    62	
    63	static const u8 ksz8795_shifts[] = {
    64		[VLAN_TABLE_MEMBERSHIP]		= 7,
    65		[VLAN_TABLE]			= 16,
    66		[STATIC_MAC_FWD_PORTS]		= 16,
    67		[STATIC_MAC_FID]		= 24,
    68		[DYNAMIC_MAC_ENTRIES_H]		= 3,
  > 69		[DYNAMIC_MAC_ENTRIES]		= 29,
    70		[DYNAMIC_MAC_FID]		= 16,
    71		[DYNAMIC_MAC_TIMESTAMP]		= 27,
    72		[DYNAMIC_MAC_SRC_PORT]		= 24,
    73	};
    74	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 36204 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v5 3/6] net: dsa: microchip: ksz8795: move register offsets and shifts to separate struct
  2020-12-07 21:44     ` Michael Grzeschik
@ 2020-12-15 16:31       ` Michael Grzeschik
  0 siblings, 0 replies; 17+ messages in thread
From: Michael Grzeschik @ 2020-12-15 16:31 UTC (permalink / raw)
  To: Tristram.Ha
  Cc: andrew, f.fainelli, davem, kernel, netdev, matthias.schiffer,
	Woojung.Huh, UNGLinuxDriver

[-- Attachment #1: Type: text/plain, Size: 7732 bytes --]

Gentle Ping. Did you find time to look into my other patches of the
series. I really would like to send the next version.

Thanks!

On Mon, Dec 07, 2020 at 10:44:15PM +0100, Michael Grzeschik wrote:
>On Mon, Dec 07, 2020 at 08:02:57PM +0000, Tristram.Ha@microchip.com wrote:
>>>In order to get this driver used with other switches the functions need
>>>to use different offsets and register shifts. This patch changes the
>>>direct use of the register defines to register description structures,
>>>which can be set depending on the chips register layout.
>>>
>>>Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
>>>
>>>---
>>>v1 -> v4: - extracted this change from bigger previous patch
>>>v4 -> v5: - added missing variables in ksz8_r_vlan_entries
>>>          - moved shifts, masks and registers to arrays indexed by enums
>>>          - using unsigned types where possible
>>>---
>>> drivers/net/dsa/microchip/ksz8.h        |  69 +++++++
>>> drivers/net/dsa/microchip/ksz8795.c     | 261 +++++++++++++++++-------
>>> drivers/net/dsa/microchip/ksz8795_reg.h |  85 --------
>>> 3 files changed, 253 insertions(+), 162 deletions(-)
>>> create mode 100644 drivers/net/dsa/microchip/ksz8.h
>>
>>Sorry for not respond to these patches sooner.
>>
>>There are 3 older KSZ switch families: KSZ8863/73, KSZ8895/64, and KSZ8795/94.
>>The newer KSZ8795 is not considered an upgrade for KSZ8895, so some of
>>these switch registers are moved around and some features are dropped.
>>
>>It is best to have one driver to support all 3 switches, but some operations are
>>Incompatible so it may be better to keep the drivers separate for now.
>>
>>For basic operations those issues may not occur so it seems simple to have
>>one driver handling all 3 switches.  I will come up with a list of those
>>incompatibilities.
>
>Look into the next patch. I handled many special cases for the ksz8863
>in the "net: dsa: microchip: ksz8795: add support for ksz88xx chips".
>These cases, including the VLAN, Tagging ... are handled by checking if
>the feautre IS_88X3 is set. This can be extended to other types as well.
>
>My first version of the patches was an RFC series that was mentioning
>that it is based on your RFC series for the ksz8895.
>
>8863 RFC: https://patchwork.ozlabs.org/project/netdev/cover/20190508211330.19328-1-m.grzeschik@pengutronix.de/
>
>8895 RFC: https://patchwork.ozlabs.org/patch/822712/
>
>I remember, that I was reading the datasheets of all three chips,
>8895, 8863 and 8795. After the 8795 series was mainline, the
>obvious next step was to get the 8863 into the 8795 code. The result
>is this series.
>
>So the obvious question is, how far does your 8895 series differ
>from the 8863 switches?
>
>>The tail tag format of KSZ8863 is different from KSZ8895 and KSZ8795, but
>>because of the DSA driver implementation that issue never comes up.
>
>Right. In the first four series I kept an extra tail tag patch. But
>after cleaning up I figured that the Implementation matched the
>one for the KSZ9893. Therefor I reused the tag code.
>
>>>-static void ksz8_from_vlan(u16 vlan, u8 *fid, u8 *member, u8 *valid)
>>>+static void ksz8_from_vlan(struct ksz_device *dev, u32 vlan, u8 *fid,
>>>+                          u8 *member, u8 *valid)
>>> {
>>>-       *fid = vlan & VLAN_TABLE_FID;
>>>-       *member = (vlan & VLAN_TABLE_MEMBERSHIP) >>
>>>VLAN_TABLE_MEMBERSHIP_S;
>>>-       *valid = !!(vlan & VLAN_TABLE_VALID);
>>>+       struct ksz8 *ksz8 = dev->priv;
>>>+       const u32 *masks = ksz8->masks;
>>>+       const u8 *shifts = ksz8->shifts;
>>>+
>>>+       *fid = vlan & masks[VLAN_TABLE_FID];
>>>+       *member = (vlan & masks[VLAN_TABLE_MEMBERSHIP]) >>
>>>+                       shifts[VLAN_TABLE_MEMBERSHIP_S];
>>>+       *valid = !!(vlan & masks[VLAN_TABLE_VALID]);
>>> }
>>>
>>>-static void ksz8_to_vlan(u8 fid, u8 member, u8 valid, u16 *vlan)
>>>+static void ksz8_to_vlan(struct ksz_device *dev, u8 fid, u8 member, u8
>>>valid,
>>>+                        u32 *vlan)
>>> {
>>>+       struct ksz8 *ksz8 = dev->priv;
>>>+       const u32 *masks = ksz8->masks;
>>>+       const u8 *shifts = ksz8->shifts;
>>>+
>>>        *vlan = fid;
>>>-       *vlan |= (u16)member << VLAN_TABLE_MEMBERSHIP_S;
>>>+       *vlan |= (u16)member << shifts[VLAN_TABLE_MEMBERSHIP_S];
>>>        if (valid)
>>>-               *vlan |= VLAN_TABLE_VALID;
>>>+               *vlan |= masks[VLAN_TABLE_VALID];
>>> }
>>>
>>> static void ksz8_r_vlan_entries(struct ksz_device *dev, u16 addr)
>>> {
>>>+       struct ksz8 *ksz8 = dev->priv;
>>>+       const u8 *shifts = ksz8->shifts;
>>>        u64 data;
>>>        int i;
>>>
>>>@@ -418,7 +509,7 @@ static void ksz8_r_vlan_entries(struct ksz_device
>>>*dev, u16 addr)
>>>        addr *= dev->phy_port_cnt;
>>>        for (i = 0; i < dev->phy_port_cnt; i++) {
>>>                dev->vlan_cache[addr + i].table[0] = (u16)data;
>>>-               data >>= VLAN_TABLE_S;
>>>+               data >>= shifts[VLAN_TABLE];
>>>        }
>>> }
>>>
>>>@@ -454,6 +545,8 @@ static void ksz8_w_vlan_table(struct ksz_device *dev,
>>>u16 vid, u32 vlan)
>>>
>>
>>The VLAN table operation in KSZ8863 is completely different from KSZ8795.
>>
>>>-/**
>>>- * VLAN_TABLE_FID                      00-007F007F-007F007F
>>>- * VLAN_TABLE_MEMBERSHIP               00-0F800F80-0F800F80
>>>- * VLAN_TABLE_VALID                    00-10001000-10001000
>>>- */
>>>-
>>>-#define VLAN_TABLE_FID                 0x007F
>>>-#define VLAN_TABLE_MEMBERSHIP          0x0F80
>>>-#define VLAN_TABLE_VALID               0x1000
>>>-
>>>-#define VLAN_TABLE_MEMBERSHIP_S                7
>>>-#define VLAN_TABLE_S                   16
>>>-
>>
>>In KSZ8795 you can use all 4096 VLAN id.  Each entry in the table contains
>>4 VID.  The FID is actually used for lookup and there is a limit, so you need
>>to convert VID to FID when programming the VLAN table.
>>
>>The only effect of using FID is the same MAC address can be used in
>>different VLANs.
>>
>>In KSZ8863 there are only 16 entries in the VLAN table.  Just like static
>>MAC table each entry is programmed using an index.  The entry contains
>>the VID, which does not have any relationship with the index unlike in
>>KSZ8795.
>>
>>The number of FID is also limited to 16.  So the maximum VLAN used is 16.
>>
>>> /**
>>>  * MIB_COUNTER_VALUE                   00-00000000-3FFFFFFF
>>>  * MIB_TOTAL_BYTES                     00-0000000F-FFFFFFFF
>>>@@ -956,9 +874,6 @@
>>>  * MIB_COUNTER_OVERFLOW                        00-00000040-00000000
>>>  */
>>>
>>>-#define MIB_COUNTER_OVERFLOW           BIT(6)
>>>-#define MIB_COUNTER_VALID              BIT(5)
>>>-
>>> #define MIB_COUNTER_VALUE              0x3FFFFFFF
>>
>>The MIB counters are also a little different in KSZ8863 and KSZ8795.
>>KSZ8863 may have smaller total bytes.  In normal operation this issue may
>>not come up.
>
>As mentioned before, these cases are handled differently for both
>types of drivers.
>
>-- 
>Pengutronix e.K.                           |                             |
>Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
>31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
>Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |



-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [PATCH v5 4/6] net: dsa: microchip: ksz8795: add support for ksz88xx chips
  2020-12-07 12:56 ` [PATCH v5 4/6] net: dsa: microchip: ksz8795: add support for ksz88xx chips Michael Grzeschik
@ 2020-12-16  6:33   ` Tristram.Ha
  2021-02-01 18:37     ` Michael Grzeschik
  0 siblings, 1 reply; 17+ messages in thread
From: Tristram.Ha @ 2020-12-16  6:33 UTC (permalink / raw)
  To: m.grzeschik
  Cc: andrew, f.fainelli, davem, kernel, netdev, matthias.schiffer,
	Woojung.Huh, UNGLinuxDriver

>  static void ksz8_r_vlan_table(struct ksz_device *dev, u16 vid, u32 *vlan)
>  {
> -       int index;
> -       u16 *data;
> -       u16 addr;
> +       u16 addr = vid / dev->phy_port_cnt;
>         u64 buf;
> 
> -       data = (u16 *)&buf;
> -       addr = vid / dev->phy_port_cnt;
> -       index = vid & 3;
>         ksz8_r_table(dev, TABLE_VLAN, addr, &buf);
> -       *vlan = data[index];
> +       if (dev->features & IS_88X3) {
> +               *vlan = (u32)buf;
> +       } else {
> +               u16 *data = (u16 *)&buf;
> +
> +               *vlan = data[vid & 3];
> +       }
>  }
> 
>  static void ksz8_w_vlan_table(struct ksz_device *dev, u16 vid, u32 vlan)
>  {
> -       int index;
> -       u16 *data;
> -       u16 addr;
> +       u16 addr = vid / dev->phy_port_cnt;
>         u64 buf;
> 
> -       data = (u16 *)&buf;
> -       addr = vid / dev->phy_port_cnt;
> -       index = vid & 3;
>         ksz8_r_table(dev, TABLE_VLAN, addr, &buf);
> -       data[index] = vlan;
> +
> +       if (dev->features & IS_88X3) {
> +               buf = vlan;
> +       } else {
> +               u16 *data = (u16 *)&buf;
> +
> +               data[vid & 3] = vlan;
> +       }
> +
>         dev->vlan_cache[vid].table[0] = vlan;
>         ksz8_w_table(dev, TABLE_VLAN, addr, buf);
>  }

I am confused about how the addr is derived.

In KSZ8795 vid is in range of 0-4095.  The addr is just (vid / 4) as there
are 4 entries in one access.  The data are lined up in 16-bit boundary
so that the VLAN information can be accessed using the array.

For KSZ8895 the VLAN data are not lined up so the 64-bit variable
needs to be shifted accordingly and masked.

For KSZ8863 the addr is a hard value from 0 to 15.  The data buffer is just
32-bit.  The vid value is contained in the entry.  You need to match that vid
with the input vid to return the right information.

You need a different VLAN read function to check if the VLAN is already
programmed in the VLAN table by searching all 16 entries.

For the VLAN write function you need to check if there is available space
to add a new entry.  The VID range is still 0-4095, but the FID range is 0-15.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v5 4/6] net: dsa: microchip: ksz8795: add support for ksz88xx chips
  2020-12-16  6:33   ` Tristram.Ha
@ 2021-02-01 18:37     ` Michael Grzeschik
  0 siblings, 0 replies; 17+ messages in thread
From: Michael Grzeschik @ 2021-02-01 18:37 UTC (permalink / raw)
  To: Tristram.Ha
  Cc: andrew, f.fainelli, davem, kernel, netdev, matthias.schiffer,
	Woojung.Huh, UNGLinuxDriver

[-- Attachment #1: Type: text/plain, Size: 3109 bytes --]

Hi Tristam!

On Wed, Dec 16, 2020 at 06:33:06AM +0000, Tristram.Ha@microchip.com wrote:
>>  static void ksz8_r_vlan_table(struct ksz_device *dev, u16 vid, u32 *vlan)
>>  {
>> -       int index;
>> -       u16 *data;
>> -       u16 addr;
>> +       u16 addr = vid / dev->phy_port_cnt;
>>         u64 buf;
>>
>> -       data = (u16 *)&buf;
>> -       addr = vid / dev->phy_port_cnt;
>> -       index = vid & 3;
>>         ksz8_r_table(dev, TABLE_VLAN, addr, &buf);
>> -       *vlan = data[index];
>> +       if (dev->features & IS_88X3) {
>> +               *vlan = (u32)buf;
>> +       } else {
>> +               u16 *data = (u16 *)&buf;
>> +
>> +               *vlan = data[vid & 3];
>> +       }
>>  }
>>
>>  static void ksz8_w_vlan_table(struct ksz_device *dev, u16 vid, u32 vlan)
>>  {
>> -       int index;
>> -       u16 *data;
>> -       u16 addr;
>> +       u16 addr = vid / dev->phy_port_cnt;
>>         u64 buf;
>>
>> -       data = (u16 *)&buf;
>> -       addr = vid / dev->phy_port_cnt;
>> -       index = vid & 3;
>>         ksz8_r_table(dev, TABLE_VLAN, addr, &buf);
>> -       data[index] = vlan;
>> +
>> +       if (dev->features & IS_88X3) {
>> +               buf = vlan;
>> +       } else {
>> +               u16 *data = (u16 *)&buf;
>> +
>> +               data[vid & 3] = vlan;
>> +       }
>> +
>>         dev->vlan_cache[vid].table[0] = vlan;
>>         ksz8_w_table(dev, TABLE_VLAN, addr, buf);
>>  }
>
>I am confused about how the addr is derived.
>
>In KSZ8795 vid is in range of 0-4095.  The addr is just (vid / 4) as there
>are 4 entries in one access.  The data are lined up in 16-bit boundary
>so that the VLAN information can be accessed using the array.
>
>For KSZ8895 the VLAN data are not lined up so the 64-bit variable
>needs to be shifted accordingly and masked.
>
>For KSZ8863 the addr is a hard value from 0 to 15.  The data buffer is just
>32-bit.  The vid value is contained in the entry.  You need to match that vid
>with the input vid to return the right information.
>
>You need a different VLAN read function to check if the VLAN is already
>programmed in the VLAN table by searching all 16 entries.
>
>For the VLAN write function you need to check if there is available space
>to add a new entry.  The VID range is still 0-4095, but the FID range is 0-15.

Thanks for the clarification. Its possible that I missed that when
porting this from your first RFC.

Regarding the drivers for ksz88{6,7}3, did you also plan to mainline
some work? Do you have some code that could be shared? If so I would
not need to implement everything again. In case you have some work
pending, please let me know. Than we could colaborate to get this
chips finaly mainline.

Thanks,
Michael

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2021-02-01 18:39 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-07 12:56 [PATCH v5 0/6] microchip: add support for ksz88x3 driver family Michael Grzeschik
2020-12-07 12:56 ` [PATCH v5 1/6] net: dsa: microchip: ksz8795: change drivers prefix to be generic Michael Grzeschik
2020-12-07 12:56 ` [PATCH v5 2/6] net: dsa: microchip: ksz8795: move cpu_select_interface to extra function Michael Grzeschik
2020-12-07 12:56 ` [PATCH v5 3/6] net: dsa: microchip: ksz8795: move register offsets and shifts to separate struct Michael Grzeschik
2020-12-07 14:11   ` kernel test robot
2020-12-07 14:11     ` kernel test robot
2020-12-07 15:01   ` David Miller
2020-12-07 20:02   ` Tristram.Ha
2020-12-07 21:44     ` Michael Grzeschik
2020-12-15 16:31       ` Michael Grzeschik
2020-12-11  4:21   ` kernel test robot
2020-12-11  4:21     ` kernel test robot
2020-12-07 12:56 ` [PATCH v5 4/6] net: dsa: microchip: ksz8795: add support for ksz88xx chips Michael Grzeschik
2020-12-16  6:33   ` Tristram.Ha
2021-02-01 18:37     ` Michael Grzeschik
2020-12-07 12:56 ` [PATCH v5 5/6] net: dsa: microchip: Add Microchip KSZ8863 SPI based driver support Michael Grzeschik
2020-12-07 12:56 ` [PATCH v5 6/6] dt-bindings: net: dsa: document additional Microchip KSZ8863/8873 switch Michael Grzeschik

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.