All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 00/11] microchip: add support for ksz88x3 driver family
@ 2020-08-03  5:44 Michael Grzeschik
  2020-08-03  5:44 ` [PATCH v4 01/11] net: phy: Add support for microchip SMI0 MDIO bus Michael Grzeschik
                   ` (11 more replies)
  0 siblings, 12 replies; 23+ messages in thread
From: Michael Grzeschik @ 2020-08-03  5:44 UTC (permalink / raw)
  To: andrew; +Cc: netdev, f.fainelli, davem, kernel

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.

Andrew Lunn (1):
  net: phy: Add support for microchip SMI0 MDIO bus

Michael Grzeschik (10):
  dt-bindings: net: mdio-gpio: add compatible for microchip,mdio-smi0
  net: tag: ksz: Add KSZ8863 tag code
  net: dsa: microchip: ksz8795: use port_cnt where possible
  net: dsa: microchip: ksz8795: dynamic allocate memory for
    flush_dyn_mac_table
  net: dsa: microchip: ksz8795: change drivers prefix to be generic
  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 SMI based driver support
  net: dsa: microchip: Add Microchip KSZ8863 SPI based driver support
  dt-bindings: net: dsa: document additional Microchip KSZ8863/8873
    switch

 .../devicetree/bindings/net/dsa/ksz.txt       |   2 +
 .../devicetree/bindings/net/mdio-gpio.txt     |   1 +
 drivers/net/dsa/microchip/Kconfig             |   9 +
 drivers/net/dsa/microchip/Makefile            |   1 +
 drivers/net/dsa/microchip/ksz8.h              |  68 ++
 drivers/net/dsa/microchip/ksz8795.c           | 926 ++++++++++++------
 drivers/net/dsa/microchip/ksz8795_reg.h       | 214 ++--
 drivers/net/dsa/microchip/ksz8795_spi.c       |  64 +-
 drivers/net/dsa/microchip/ksz8863_reg.h       | 124 +++
 drivers/net/dsa/microchip/ksz8863_smi.c       | 204 ++++
 drivers/net/dsa/microchip/ksz_common.h        |   2 +-
 drivers/net/phy/mdio-bitbang.c                |   8 +-
 drivers/net/phy/mdio-gpio.c                   |   9 +
 include/linux/mdio-bitbang.h                  |   3 +
 include/net/dsa.h                             |   2 +
 net/dsa/tag_ksz.c                             |  57 ++
 16 files changed, 1275 insertions(+), 419 deletions(-)
 create mode 100644 drivers/net/dsa/microchip/ksz8.h
 create mode 100644 drivers/net/dsa/microchip/ksz8863_reg.h
 create mode 100644 drivers/net/dsa/microchip/ksz8863_smi.c

-- 
2.28.0


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

* [PATCH v4 01/11] net: phy: Add support for microchip SMI0 MDIO bus
  2020-08-03  5:44 [PATCH v4 00/11] microchip: add support for ksz88x3 driver family Michael Grzeschik
@ 2020-08-03  5:44 ` Michael Grzeschik
  2020-08-03 17:38   ` Florian Fainelli
  2020-08-03  5:44 ` [PATCH v4 02/11] dt-bindings: net: mdio-gpio: add compatible for microchip,mdio-smi0 Michael Grzeschik
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 23+ messages in thread
From: Michael Grzeschik @ 2020-08-03  5:44 UTC (permalink / raw)
  To: andrew; +Cc: netdev, f.fainelli, davem, kernel

From: Andrew Lunn <andrew@lunn.ch>

SMI0 is a mangled version of MDIO. The main low level difference is
the MDIO C22 OP code is always 0, not 0x2 or 0x1 for Read/Write. The
read/write information is instead encoded in the PHY address.

Extend the bit-bang code to allow the op code to be overridden, but
default to normal C22 values. Add an extra compatible to the mdio-gpio
driver, and when this compatible is present, set the op codes to 0.

A higher level driver, sitting on top of the basic MDIO bus driver can
then implement the rest of the microchip SMI0 odderties.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>

---
v1 -> v2: - patch not present
v2 -> v3: - first patch
v3 -> v4: - added override_c22_op

 drivers/net/phy/mdio-bitbang.c | 8 ++++++--
 drivers/net/phy/mdio-gpio.c    | 9 +++++++++
 include/linux/mdio-bitbang.h   | 3 +++
 3 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/net/phy/mdio-bitbang.c b/drivers/net/phy/mdio-bitbang.c
index 5136275c8e7399f..528e255d1ffe77f 100644
--- a/drivers/net/phy/mdio-bitbang.c
+++ b/drivers/net/phy/mdio-bitbang.c
@@ -158,7 +158,7 @@ static int mdiobb_read(struct mii_bus *bus, int phy, int reg)
 		reg = mdiobb_cmd_addr(ctrl, phy, reg);
 		mdiobb_cmd(ctrl, MDIO_C45_READ, phy, reg);
 	} else
-		mdiobb_cmd(ctrl, MDIO_READ, phy, reg);
+		mdiobb_cmd(ctrl, ctrl->op_c22_read, phy, reg);
 
 	ctrl->ops->set_mdio_dir(ctrl, 0);
 
@@ -189,7 +189,7 @@ static int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val)
 		reg = mdiobb_cmd_addr(ctrl, phy, reg);
 		mdiobb_cmd(ctrl, MDIO_C45_WRITE, phy, reg);
 	} else
-		mdiobb_cmd(ctrl, MDIO_WRITE, phy, reg);
+		mdiobb_cmd(ctrl, ctrl->op_c22_write, phy, reg);
 
 	/* send the turnaround (10) */
 	mdiobb_send_bit(ctrl, 1);
@@ -215,6 +215,10 @@ struct mii_bus *alloc_mdio_bitbang(struct mdiobb_ctrl *ctrl)
 	bus->read = mdiobb_read;
 	bus->write = mdiobb_write;
 	bus->priv = ctrl;
+	if (!ctrl->override_op_c22) {
+		ctrl->op_c22_read = MDIO_READ;
+		ctrl->op_c22_write = MDIO_WRITE;
+	}
 
 	return bus;
 }
diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c
index 1b00235d7dc5b56..e8d83cee1bc17e1 100644
--- a/drivers/net/phy/mdio-gpio.c
+++ b/drivers/net/phy/mdio-gpio.c
@@ -132,6 +132,14 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev,
 		new_bus->phy_ignore_ta_mask = pdata->phy_ignore_ta_mask;
 	}
 
+	if (dev->of_node &&
+	    of_device_is_compatible(dev->of_node, "microchip,mdio-smi0")) {
+		bitbang->ctrl.op_c22_read = 0;
+		bitbang->ctrl.op_c22_write = 0;
+	} else {
+		bitbang->ctrl.override_op_c22 = 1;
+	}
+
 	dev_set_drvdata(dev, new_bus);
 
 	return new_bus;
@@ -196,6 +204,7 @@ static int mdio_gpio_remove(struct platform_device *pdev)
 
 static const struct of_device_id mdio_gpio_of_match[] = {
 	{ .compatible = "virtual,mdio-gpio", },
+	{ .compatible = "microchip,mdio-smi0" },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, mdio_gpio_of_match);
diff --git a/include/linux/mdio-bitbang.h b/include/linux/mdio-bitbang.h
index 5d71e8a8500f5ed..5016e6f60de38af 100644
--- a/include/linux/mdio-bitbang.h
+++ b/include/linux/mdio-bitbang.h
@@ -33,6 +33,9 @@ struct mdiobb_ops {
 
 struct mdiobb_ctrl {
 	const struct mdiobb_ops *ops;
+	unsigned int override_op_c22;
+	u8 op_c22_read;
+	u8 op_c22_write;
 };
 
 /* The returned bus is not yet registered with the phy layer. */
-- 
2.28.0


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

* [PATCH v4 02/11] dt-bindings: net: mdio-gpio: add compatible for microchip,mdio-smi0
  2020-08-03  5:44 [PATCH v4 00/11] microchip: add support for ksz88x3 driver family Michael Grzeschik
  2020-08-03  5:44 ` [PATCH v4 01/11] net: phy: Add support for microchip SMI0 MDIO bus Michael Grzeschik
@ 2020-08-03  5:44 ` Michael Grzeschik
  2020-08-03  5:44 ` [PATCH v4 03/11] net: tag: ksz: Add KSZ8863 tag code Michael Grzeschik
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 23+ messages in thread
From: Michael Grzeschik @ 2020-08-03  5:44 UTC (permalink / raw)
  To: andrew; +Cc: netdev, f.fainelli, davem, kernel, devicetree, Rob Herring

Microchip SMI0 Mode is a special mode, where the MDIO Read/Write
commands are part of the PHY Address and the OP Code is always 0. We add
the compatible for this special mode of the bitbanged mdio driver.

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

---
v1 -> v2: - patch not present
v2 -> v3: - first patch
v3 -> v4: - no changes

 Documentation/devicetree/bindings/net/mdio-gpio.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/net/mdio-gpio.txt b/Documentation/devicetree/bindings/net/mdio-gpio.txt
index 8dbcf8295c6c9ce..4d91a36c5cf5031 100644
--- a/Documentation/devicetree/bindings/net/mdio-gpio.txt
+++ b/Documentation/devicetree/bindings/net/mdio-gpio.txt
@@ -2,6 +2,7 @@ MDIO on GPIOs
 
 Currently defined compatibles:
 - virtual,gpio-mdio
+- microchip,mdio-smi0
 
 MDC and MDIO lines connected to GPIO controllers are listed in the
 gpios property as described in section VIII.1 in the following order:
-- 
2.28.0


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

* [PATCH v4 03/11] net: tag: ksz: Add KSZ8863 tag code
  2020-08-03  5:44 [PATCH v4 00/11] microchip: add support for ksz88x3 driver family Michael Grzeschik
  2020-08-03  5:44 ` [PATCH v4 01/11] net: phy: Add support for microchip SMI0 MDIO bus Michael Grzeschik
  2020-08-03  5:44 ` [PATCH v4 02/11] dt-bindings: net: mdio-gpio: add compatible for microchip,mdio-smi0 Michael Grzeschik
@ 2020-08-03  5:44 ` Michael Grzeschik
  2020-08-03  5:44 ` [PATCH v4 04/11] net: dsa: microchip: ksz8795: use port_cnt where possible Michael Grzeschik
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 23+ messages in thread
From: Michael Grzeschik @ 2020-08-03  5:44 UTC (permalink / raw)
  To: andrew; +Cc: netdev, f.fainelli, davem, kernel

Add DSA tag code for Microchip KSZ8863 switch.

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

---
v1 -> v2: - fixed __be16 handling
v2 -> v3: - no changes
v3 -> v4: - changed handling to only one padding byte

 include/net/dsa.h |  2 ++
 net/dsa/tag_ksz.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 75c8fac82017444..321ecbee0834f5e 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -45,6 +45,7 @@ struct phylink_link_state;
 #define DSA_TAG_PROTO_OCELOT_VALUE		15
 #define DSA_TAG_PROTO_AR9331_VALUE		16
 #define DSA_TAG_PROTO_RTL4_A_VALUE		17
+#define DSA_TAG_PROTO_KSZ8863_VALUE		18
 
 enum dsa_tag_protocol {
 	DSA_TAG_PROTO_NONE		= DSA_TAG_PROTO_NONE_VALUE,
@@ -65,6 +66,7 @@ enum dsa_tag_protocol {
 	DSA_TAG_PROTO_OCELOT		= DSA_TAG_PROTO_OCELOT_VALUE,
 	DSA_TAG_PROTO_AR9331		= DSA_TAG_PROTO_AR9331_VALUE,
 	DSA_TAG_PROTO_RTL4_A		= DSA_TAG_PROTO_RTL4_A_VALUE,
+	DSA_TAG_PROTO_KSZ8863		= DSA_TAG_PROTO_KSZ8863_VALUE,
 };
 
 struct packet_type;
diff --git a/net/dsa/tag_ksz.c b/net/dsa/tag_ksz.c
index bd1a3158d79a85f..fb9cc0e84288782 100644
--- a/net/dsa/tag_ksz.c
+++ b/net/dsa/tag_ksz.c
@@ -242,8 +242,65 @@ static const struct dsa_device_ops ksz9893_netdev_ops = {
 DSA_TAG_DRIVER(ksz9893_netdev_ops);
 MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ9893);
 
+/* For ingress (Host -> KSZ8863), 1 byte is added before FCS.
+ * ---------------------------------------------------------------------------
+ * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag0(1byte)|FCS(4bytes)
+ * ---------------------------------------------------------------------------
+ * tag0[1,0] : represents port
+ *             (e.g. 0b00=addr-lookup 0b01=port1, 0b10=port2, 0b11=port1+port2)
+ * tag0[3,2] : bits two and three represent prioritization
+ *             (e.g. 0b00xx=prio0, 0b01xx=prio1, 0b10xx=prio2, 0b11xx=prio3)
+ *
+ * For egress (KSZ8873 -> Host), 1 byte is added before FCS.
+ * ---------------------------------------------------------------------------
+ * DA(6bytes)|SA(6bytes)|....|Data(nbytes)|tag0(1byte)|FCS(4bytes)
+ * ---------------------------------------------------------------------------
+ * tag0[0]   : zero-based value represents port
+ *             (eg, 0b0=port1, 0b1=port2)
+ */
+
+static struct sk_buff *ksz8863_xmit(struct sk_buff *skb,
+				    struct net_device *dev)
+{
+	struct dsa_port *dp = dsa_slave_to_port(dev);
+	struct sk_buff *nskb;
+	u8 *tag;
+
+	nskb = ksz_common_xmit(skb, dev, KSZ_INGRESS_TAG_LEN);
+	if (!nskb)
+		return NULL;
+
+	/* Tag encoding */
+	tag = skb_put(nskb, KSZ_INGRESS_TAG_LEN);
+
+	*tag = BIT(dp->index); /* destination port */
+
+	return nskb;
+}
+
+static struct sk_buff *ksz8863_rcv(struct sk_buff *skb, struct net_device *dev,
+				   struct packet_type *pt)
+{
+	/* Tag decoding */
+	u8 *tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN;
+
+	return ksz_common_rcv(skb, dev, tag[0] & 1, KSZ_EGRESS_TAG_LEN);
+}
+
+static const struct dsa_device_ops ksz8863_netdev_ops = {
+	.name	= "ksz8863",
+	.proto	= DSA_TAG_PROTO_KSZ8863,
+	.xmit	= ksz8863_xmit,
+	.rcv	= ksz8863_rcv,
+	.overhead = KSZ_INGRESS_TAG_LEN,
+};
+
+DSA_TAG_DRIVER(ksz8863_netdev_ops);
+MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ8863);
+
 static struct dsa_tag_driver *dsa_tag_driver_array[] = {
 	&DSA_TAG_DRIVER_NAME(ksz8795_netdev_ops),
+	&DSA_TAG_DRIVER_NAME(ksz8863_netdev_ops),
 	&DSA_TAG_DRIVER_NAME(ksz9477_netdev_ops),
 	&DSA_TAG_DRIVER_NAME(ksz9893_netdev_ops),
 };
-- 
2.28.0


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

* [PATCH v4 04/11] net: dsa: microchip: ksz8795: use port_cnt where possible
  2020-08-03  5:44 [PATCH v4 00/11] microchip: add support for ksz88x3 driver family Michael Grzeschik
                   ` (2 preceding siblings ...)
  2020-08-03  5:44 ` [PATCH v4 03/11] net: tag: ksz: Add KSZ8863 tag code Michael Grzeschik
@ 2020-08-03  5:44 ` Michael Grzeschik
  2020-08-03 17:40   ` Florian Fainelli
  2020-08-03  5:44 ` [PATCH v4 05/11] net: dsa: microchip: ksz8795: dynamic allocate memory for flush_dyn_mac_table Michael Grzeschik
                   ` (7 subsequent siblings)
  11 siblings, 1 reply; 23+ messages in thread
From: Michael Grzeschik @ 2020-08-03  5:44 UTC (permalink / raw)
  To: andrew; +Cc: netdev, f.fainelli, davem, kernel

Since the driver can be used on more switches it needs
to use flexible port count whereever possible.

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

---
v1 -> v4: - extracted this change from bigger previous patch

 drivers/net/dsa/microchip/ksz8795.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c
index 8f1d15ea15d9a75..947ea1e45f5b2c6 100644
--- a/drivers/net/dsa/microchip/ksz8795.c
+++ b/drivers/net/dsa/microchip/ksz8795.c
@@ -418,8 +418,8 @@ static void ksz8795_r_vlan_entries(struct ksz_device *dev, u16 addr)
 	int i;
 
 	ksz8795_r_table(dev, TABLE_VLAN, addr, &data);
-	addr *= 4;
-	for (i = 0; i < 4; i++) {
+	addr *= dev->port_cnt;
+	for (i = 0; i < dev->port_cnt; i++) {
 		dev->vlan_cache[addr + i].table[0] = (u16)data;
 		data >>= VLAN_TABLE_S;
 	}
@@ -433,7 +433,7 @@ static void ksz8795_r_vlan_table(struct ksz_device *dev, u16 vid, u16 *vlan)
 	u64 buf;
 
 	data = (u16 *)&buf;
-	addr = vid / 4;
+	addr = vid / dev->port_cnt;
 	index = vid & 3;
 	ksz8795_r_table(dev, TABLE_VLAN, addr, &buf);
 	*vlan = data[index];
@@ -447,7 +447,7 @@ static void ksz8795_w_vlan_table(struct ksz_device *dev, u16 vid, u16 vlan)
 	u64 buf;
 
 	data = (u16 *)&buf;
-	addr = vid / 4;
+	addr = vid / dev->port_cnt;
 	index = vid & 3;
 	ksz8795_r_table(dev, TABLE_VLAN, addr, &buf);
 	data[index] = vlan;
@@ -691,12 +691,12 @@ static void ksz8795_port_stp_state_set(struct dsa_switch *ds, int port,
 	switch (state) {
 	case BR_STATE_DISABLED:
 		data |= PORT_LEARN_DISABLE;
-		if (port < SWITCH_PORT_NUM)
+		if (port < dev->port_cnt)
 			member = 0;
 		break;
 	case BR_STATE_LISTENING:
 		data |= (PORT_RX_ENABLE | PORT_LEARN_DISABLE);
-		if (port < SWITCH_PORT_NUM &&
+		if (port < dev->port_cnt &&
 		    p->stp_state == BR_STATE_DISABLED)
 			member = dev->host_mask | p->vid_member;
 		break;
@@ -720,7 +720,7 @@ static void ksz8795_port_stp_state_set(struct dsa_switch *ds, int port,
 		break;
 	case BR_STATE_BLOCKING:
 		data |= PORT_LEARN_DISABLE;
-		if (port < SWITCH_PORT_NUM &&
+		if (port < dev->port_cnt &&
 		    p->stp_state == BR_STATE_DISABLED)
 			member = dev->host_mask | p->vid_member;
 		break;
@@ -993,7 +993,7 @@ static void ksz8795_config_cpu_port(struct dsa_switch *ds)
 	ksz8795_port_setup(dev, dev->cpu_port, true);
 	dev->member = dev->host_mask;
 
-	for (i = 0; i < SWITCH_PORT_NUM; i++) {
+	for (i = 0; i < dev->port_cnt; i++) {
 		p = &dev->ports[i];
 
 		/* Initialize to non-zero so that ksz_cfg_port_member() will
-- 
2.28.0


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

* [PATCH v4 05/11] net: dsa: microchip: ksz8795: dynamic allocate memory for flush_dyn_mac_table
  2020-08-03  5:44 [PATCH v4 00/11] microchip: add support for ksz88x3 driver family Michael Grzeschik
                   ` (3 preceding siblings ...)
  2020-08-03  5:44 ` [PATCH v4 04/11] net: dsa: microchip: ksz8795: use port_cnt where possible Michael Grzeschik
@ 2020-08-03  5:44 ` Michael Grzeschik
  2020-08-03 17:40   ` Florian Fainelli
  2020-08-03  5:44 ` [PATCH v4 06/11] net: dsa: microchip: ksz8795: change drivers prefix to be generic Michael Grzeschik
                   ` (6 subsequent siblings)
  11 siblings, 1 reply; 23+ messages in thread
From: Michael Grzeschik @ 2020-08-03  5:44 UTC (permalink / raw)
  To: andrew; +Cc: netdev, f.fainelli, davem, kernel

To get the driver working with other chips using different port counts
the dyn_mac_table should be flushed depending on the amount of physical
ports.

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

---
v1 -> v4: - extracted this change from bigger previous patch

 drivers/net/dsa/microchip/ksz8795.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c
index 947ea1e45f5b2c6..ba722f730bf0f7b 100644
--- a/drivers/net/dsa/microchip/ksz8795.c
+++ b/drivers/net/dsa/microchip/ksz8795.c
@@ -750,11 +750,11 @@ static void ksz8795_port_stp_state_set(struct dsa_switch *ds, int port,
 
 static void ksz8795_flush_dyn_mac_table(struct ksz_device *dev, int port)
 {
-	u8 learn[TOTAL_PORT_NUM];
+	u8 *learn = kzalloc(dev->mib_port_cnt, GFP_KERNEL);
 	int first, index, cnt;
 	struct ksz_port *p;
 
-	if ((uint)port < TOTAL_PORT_NUM) {
+	if ((uint)port < dev->mib_port_cnt) {
 		first = port;
 		cnt = port + 1;
 	} else {
@@ -779,6 +779,7 @@ static void ksz8795_flush_dyn_mac_table(struct ksz_device *dev, int port)
 		if (!(learn[index] & PORT_LEARN_DISABLE))
 			ksz_pwrite8(dev, index, P_STP_CTRL, learn[index]);
 	}
+	kfree(learn);
 }
 
 static int ksz8795_port_vlan_filtering(struct dsa_switch *ds, int port,
-- 
2.28.0


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

* [PATCH v4 06/11] net: dsa: microchip: ksz8795: change drivers prefix to be generic
  2020-08-03  5:44 [PATCH v4 00/11] microchip: add support for ksz88x3 driver family Michael Grzeschik
                   ` (4 preceding siblings ...)
  2020-08-03  5:44 ` [PATCH v4 05/11] net: dsa: microchip: ksz8795: dynamic allocate memory for flush_dyn_mac_table Michael Grzeschik
@ 2020-08-03  5:44 ` Michael Grzeschik
  2020-08-03 15:42   ` Jakub Kicinski
  2020-08-03  5:44 ` [PATCH v4 07/11] net: dsa: microchip: ksz8795: move register offsets and shifts to separate struct Michael Grzeschik
                   ` (5 subsequent siblings)
  11 siblings, 1 reply; 23+ messages in thread
From: Michael Grzeschik @ 2020-08-03  5:44 UTC (permalink / raw)
  To: andrew; +Cc: netdev, f.fainelli, davem, kernel

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

 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, 111 insertions(+), 115 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c
index ba722f730bf0f7b..c21125a0b30e5c8 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,14 @@ 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)
 {
+	struct ksz8 *ksz8 = dev->priv;
+	struct ksz_shifts *shifts = ksz8->shifts;
 	u64 data;
 	int i;
 
-	ksz8795_r_table(dev, TABLE_VLAN, addr, &data);
+	ksz8_r_table(dev, TABLE_VLAN, addr, &data);
 	addr *= dev->port_cnt;
 	for (i = 0; i < dev->port_cnt; i++) {
 		dev->vlan_cache[addr + i].table[0] = (u16)data;
@@ -425,7 +424,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 +434,11 @@ static void ksz8795_r_vlan_table(struct ksz_device *dev, u16 vid, u16 *vlan)
 	data = (u16 *)&buf;
 	addr = vid / dev->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 +448,13 @@ static void ksz8795_w_vlan_table(struct ksz_device *dev, u16 vid, u16 vlan)
 	data = (u16 *)&buf;
 	addr = vid / dev->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 +545,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 +643,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)
 {
 	int i;
 
@@ -662,8 +661,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;
 
@@ -674,8 +672,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;
@@ -733,7 +730,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) {
@@ -748,7 +745,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 = kzalloc(dev->mib_port_cnt, GFP_KERNEL);
 	int first, index, cnt;
@@ -782,8 +779,7 @@ static void ksz8795_flush_dyn_mac_table(struct ksz_device *dev, int port)
 	kfree(learn);
 }
 
-static int ksz8795_port_vlan_filtering(struct dsa_switch *ds, int port,
-				       bool flag)
+static int ksz8_port_vlan_filtering(struct dsa_switch *ds, int port, bool flag)
 {
 	struct ksz_device *dev = ds->priv;
 
@@ -792,8 +788,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;
@@ -803,8 +799,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) {
@@ -814,8 +810,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)
@@ -830,8 +826,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;
@@ -844,8 +840,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);
 
@@ -858,8 +854,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)
@@ -868,9 +864,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;
 
@@ -892,8 +888,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;
@@ -913,7 +909,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;
@@ -971,10 +967,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;
@@ -991,7 +987,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->port_cnt; i++) {
@@ -1002,7 +998,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->port_cnt)
@@ -1026,7 +1022,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;
@@ -1037,7 +1033,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;
@@ -1060,7 +1056,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);
 
@@ -1075,7 +1071,7 @@ static int ksz8795_setup(struct dsa_switch *ds)
 			   BROADCAST_STORM_PROT_RATE) / 100);
 
 	for (i = 0; i < VLAN_TABLE_ENTRIES; i++)
-		ksz8795_r_vlan_entries(dev, i);
+		ksz8_r_vlan_entries(dev, i);
 
 	/* Setup STP address for STP operation. */
 	memset(&alu, 0, sizeof(alu));
@@ -1084,45 +1080,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;
@@ -1175,7 +1171,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",
@@ -1205,14 +1201,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;
@@ -1258,36 +1254,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 8b00f8e6c02f4f2..3bab09c46f6a7bd 100644
--- a/drivers/net/dsa/microchip/ksz8795_spi.c
+++ b/drivers/net/dsa/microchip/ksz8795_spi.c
@@ -49,7 +49,7 @@ static int ksz8795_spi_probe(struct spi_device *spi)
 	if (spi->dev.platform_data)
 		dev->pdata = spi->dev.platform_data;
 
-	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 206838160f4940f..cd5aec59d3978c5 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -143,7 +143,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.28.0


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

* [PATCH v4 07/11] net: dsa: microchip: ksz8795: move register offsets and shifts to separate struct
  2020-08-03  5:44 [PATCH v4 00/11] microchip: add support for ksz88x3 driver family Michael Grzeschik
                   ` (5 preceding siblings ...)
  2020-08-03  5:44 ` [PATCH v4 06/11] net: dsa: microchip: ksz8795: change drivers prefix to be generic Michael Grzeschik
@ 2020-08-03  5:44 ` Michael Grzeschik
  2020-08-03 18:21   ` Florian Fainelli
  2020-08-03  5:44 ` [PATCH v4 08/11] net: dsa: microchip: ksz8795: add support for ksz88xx chips Michael Grzeschik
                   ` (4 subsequent siblings)
  11 siblings, 1 reply; 23+ messages in thread
From: Michael Grzeschik @ 2020-08-03  5:44 UTC (permalink / raw)
  To: andrew; +Cc: netdev, f.fainelli, davem, kernel

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

 drivers/net/dsa/microchip/ksz8.h    |  68 ++++++++
 drivers/net/dsa/microchip/ksz8795.c | 242 +++++++++++++++++++---------
 2 files changed, 235 insertions(+), 75 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 000000000000000..a2fb6b9e2d1e5d5
--- /dev/null
+++ b/drivers/net/dsa/microchip/ksz8.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Microchip KSZ8863 series register access through SMI
+ *
+ * Copyright (C) 2019 Pengutronix, Michael Grzeschik <kernel@pengutronix.de>
+ */
+
+#ifndef __KSZ8XXX_H
+#define __KSZ8XXX_H
+
+struct ksz_regs {
+	int ind_ctrl_0;
+	int ind_data_8;
+	int ind_data_check;
+	int ind_data_hi;
+	int ind_data_lo;
+	int ind_mib_check;
+	int p_force_ctrl;
+	int p_link_status;
+	int p_local_ctrl;
+	int p_neg_restart_ctrl;
+	int p_remote_status;
+	int p_speed_status;
+	int s_tail_tag_ctrl;
+};
+
+struct ksz_masks {
+	int port_802_1p_remapping;
+	int sw_tail_tag_enable;
+	int mib_counter_overflow;
+	int mib_counter_valid;
+	int vlan_table_fid;
+	int vlan_table_membership;
+	int vlan_table_valid;
+	int static_mac_table_valid;
+	int static_mac_table_use_fid;
+	int static_mac_table_fid;
+	int static_mac_table_override;
+	int static_mac_table_fwd_ports;
+	int dynamic_mac_table_entries_h;
+	int dynamic_mac_table_mac_empty;
+	int dynamic_mac_table_not_ready;
+	int dynamic_mac_table_entries;
+	int dynamic_mac_table_fid;
+	int dynamic_mac_table_src_port;
+	int dynamic_mac_table_timestamp;
+};
+
+struct ksz_shifts {
+	int vlan_table_membership;
+	int vlan_table;
+	int static_mac_fwd_ports;
+	int static_mac_fid;
+	int dynamic_mac_entries_h;
+	int dynamic_mac_entries;
+	int dynamic_mac_fid;
+	int dynamic_mac_timestamp;
+	int dynamic_mac_src_port;
+};
+
+struct ksz8 {
+	struct ksz_regs *regs;
+	struct ksz_masks *masks;
+	struct ksz_shifts *shifts;
+	void *priv;
+};
+
+#endif
diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c
index c21125a0b30e5c8..480143905d75579 100644
--- a/drivers/net/dsa/microchip/ksz8795.c
+++ b/drivers/net/dsa/microchip/ksz8795.c
@@ -20,6 +20,46 @@
 
 #include "ksz_common.h"
 #include "ksz8795_reg.h"
+#include "ksz8.h"
+
+static struct ksz_regs ksz8795_regs = {
+	.ind_ctrl_0			= REG_IND_CTRL_0,
+	.ind_data_8			= REG_IND_DATA_8,
+	.ind_data_check			= REG_IND_DATA_CHECK,
+	.ind_data_hi			= REG_IND_DATA_HI,
+	.ind_data_lo			= REG_IND_DATA_LO,
+	.ind_mib_check			= REG_IND_MIB_CHECK,
+	.p_force_ctrl			= P_FORCE_CTRL,
+	.p_link_status			= P_LINK_STATUS,
+	.p_local_ctrl			= P_LOCAL_CTRL,
+	.p_neg_restart_ctrl		= P_NEG_RESTART_CTRL,
+	.p_remote_status		= P_REMOTE_STATUS,
+	.p_speed_status			= P_SPEED_STATUS,
+	.s_tail_tag_ctrl		= S_TAIL_TAG_CTRL,
+};
+
+static struct ksz_masks ksz8795_masks = {
+	.port_802_1p_remapping		= PORT_802_1P_REMAPPING,
+	.sw_tail_tag_enable		= SW_TAIL_TAG_ENABLE,
+	.mib_counter_overflow		= MIB_COUNTER_OVERFLOW,
+	.mib_counter_valid		= MIB_COUNTER_VALID,
+	.vlan_table_fid			= VLAN_TABLE_FID,
+	.vlan_table_membership		= VLAN_TABLE_MEMBERSHIP,
+	.vlan_table_valid		= VLAN_TABLE_VALID,
+	.static_mac_table_valid		= STATIC_MAC_TABLE_VALID,
+	.static_mac_table_use_fid	= STATIC_MAC_TABLE_USE_FID,
+	.static_mac_table_fid		= STATIC_MAC_TABLE_FID,
+	.static_mac_table_override	= STATIC_MAC_TABLE_OVERRIDE,
+	.static_mac_table_fwd_ports	= STATIC_MAC_TABLE_FWD_PORTS,
+	.dynamic_mac_table_entries_h	= DYNAMIC_MAC_TABLE_ENTRIES_H,
+	.dynamic_mac_table_mac_empty	= DYNAMIC_MAC_TABLE_MAC_EMPTY,
+	.dynamic_mac_table_not_ready	= DYNAMIC_MAC_TABLE_NOT_READY,
+	.dynamic_mac_table_entries	= DYNAMIC_MAC_TABLE_ENTRIES,
+	.dynamic_mac_table_fid		= DYNAMIC_MAC_TABLE_FID,
+	.dynamic_mac_table_src_port	= DYNAMIC_MAC_TABLE_SRC_PORT,
+	.dynamic_mac_table_timestamp	= DYNAMIC_MAC_TABLE_TIMESTAMP,
+};
+
 
 static const struct {
 	char string[ETH_GSTRING_LEN];
@@ -119,26 +159,29 @@ 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;
+	struct ksz_regs *regs = ksz8->regs;
+	struct ksz_masks *masks = ksz8->masks;
 	u16 ctrl_addr;
 	u32 data;
 	u8 check;
 	int loop;
 
-	ctrl_addr = addr + SWITCH_COUNTER_NUM * port;
+	ctrl_addr = addr + dev->reg_mib_cnt * port;
 	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->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->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->ind_data_lo, &data);
+			if (check & masks->mib_counter_overflow)
 				*cnt += MIB_COUNTER_VALUE + 1;
 			*cnt += data & MIB_COUNTER_VALUE;
 			break;
@@ -150,6 +193,8 @@ 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;
+	struct ksz_regs *regs = ksz8->regs;
 	u16 ctrl_addr;
 	u32 data;
 	u8 check;
@@ -161,16 +206,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->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->ind_mib_check, &check);
 
 		if (check & MIB_COUNTER_VALID) {
-			ksz_read32(dev, REG_IND_DATA_LO, &data);
+			ksz_read32(dev, regs->ind_data_lo, &data);
 			if (addr < 2) {
 				u64 total;
 
@@ -236,46 +281,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;
+	struct ksz_regs *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->ind_ctrl_0, ctrl_addr);
+	ksz_read64(dev, regs->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;
+	struct ksz_regs *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->ind_data_hi, data);
+	ksz_write16(dev, regs->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;
+	struct ksz_regs *regs = ksz8->regs;
+	struct ksz_masks *masks = ksz8->masks;
 	int timeout = 100;
 
 	do {
-		ksz_read8(dev, REG_IND_DATA_CHECK, data);
+		ksz_read8(dev, regs->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->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 +337,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;
+	struct ksz_regs *regs = ksz8->regs;
+	struct ksz_masks *masks = ksz8->masks;
+	struct ksz_shifts *shifts = ksz8->shifts;
 	u32 data_hi, data_lo;
 	u16 ctrl_addr;
 	u8 data;
@@ -293,7 +349,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->ind_ctrl_0, ctrl_addr);
 
 	rc = ksz8_valid_dyn_entry(dev, &data);
 	if (rc == -EAGAIN) {
@@ -306,23 +362,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->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 +397,33 @@ 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;
+	struct ksz_masks *masks = ksz8->masks;
+	struct ksz_shifts *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_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 +432,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;
+	struct ksz_masks *masks = ksz8->masks;
+	struct ksz_shifts *shifts = ksz8->shifts;
 	u32 data_hi, data_lo;
 	u64 data;
 
@@ -377,36 +442,47 @@ 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;
+	struct ksz_masks *masks = ksz8->masks;
+	struct ksz_shifts *shifts = ksz8->shifts;
+
+	*fid = vlan & masks->vlan_table_fid;
+	*member = (vlan & masks->vlan_table_membership) >>
+			shifts->vlan_table_membership;
+	*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;
+	struct ksz_masks *masks = ksz8->masks;
+	struct ksz_shifts *shifts = ksz8->shifts;
+
 	*vlan = fid;
-	*vlan |= (u16)member << VLAN_TABLE_MEMBERSHIP_S;
+	*vlan |= (u16)member << shifts->vlan_table_membership;
 	if (valid)
-		*vlan |= VLAN_TABLE_VALID;
+		*vlan |= masks->vlan_table_valid;
 }
 
 static void ksz8_r_vlan_entries(struct ksz_device *dev, u16 addr)
@@ -420,7 +496,7 @@ static void ksz8_r_vlan_entries(struct ksz_device *dev, u16 addr)
 	addr *= dev->port_cnt;
 	for (i = 0; i < dev->port_cnt; i++) {
 		dev->vlan_cache[addr + i].table[0] = (u16)data;
-		data >>= VLAN_TABLE_S;
+		data >>= shifts->vlan_table;
 	}
 }
 
@@ -456,6 +532,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;
+	struct ksz_regs *regs = ksz8->regs;
 	u8 restart, speed, ctrl, link;
 	int processed = true;
 	u16 data = 0;
@@ -463,9 +541,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)
@@ -490,7 +568,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 |
@@ -508,7 +586,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;
@@ -522,7 +600,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;
@@ -548,6 +626,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;
+	struct ksz_regs *regs = ksz8->regs;
 	u8 restart, speed, ctrl, data;
 
 	switch (reg) {
@@ -556,15 +636,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;
@@ -583,8 +663,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;
@@ -615,10 +695,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 |
@@ -636,7 +716,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;
@@ -793,14 +873,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) {
@@ -810,9 +891,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;
@@ -831,7 +911,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);
@@ -841,7 +922,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);
 
@@ -854,7 +935,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);
 	}
 
@@ -913,6 +994,8 @@ static void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port)
 {
 	struct ksz_port *p = &dev->ports[port];
 	u8 data8, member;
+	struct ksz8 *ksz8 = dev->priv;
+	struct ksz_masks *masks = ksz8->masks;
 
 	/* enable broadcast storm limit */
 	ksz_port_cfg(dev, port, P_BCAST_STORM_CTRL, PORT_BROADCAST_STORM, true);
@@ -923,7 +1006,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);
@@ -973,6 +1057,9 @@ 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;
+	struct ksz_regs *regs = ksz8->regs;
+	struct ksz_masks *masks = ksz8->masks;
 	struct ksz_port *p;
 	u8 remote;
 	int i;
@@ -981,7 +1068,7 @@ static void ksz8_config_cpu_port(struct dsa_switch *ds)
 
 	/* 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;
@@ -1010,7 +1097,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)
@@ -1204,6 +1291,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;
 
@@ -1226,6 +1314,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;
 
-- 
2.28.0


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

* [PATCH v4 08/11] net: dsa: microchip: ksz8795: add support for ksz88xx chips
  2020-08-03  5:44 [PATCH v4 00/11] microchip: add support for ksz88x3 driver family Michael Grzeschik
                   ` (6 preceding siblings ...)
  2020-08-03  5:44 ` [PATCH v4 07/11] net: dsa: microchip: ksz8795: move register offsets and shifts to separate struct Michael Grzeschik
@ 2020-08-03  5:44 ` Michael Grzeschik
  2020-08-03  5:44 ` [PATCH v4 09/11] net: dsa: microchip: Add Microchip KSZ8863 SMI based driver support Michael Grzeschik
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 23+ messages in thread
From: Michael Grzeschik @ 2020-08-03  5:44 UTC (permalink / raw)
  To: andrew; +Cc: netdev, f.fainelli, davem, kernel

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

 drivers/net/dsa/microchip/ksz8795.c     | 541 +++++++++++++++++-------
 drivers/net/dsa/microchip/ksz8795_reg.h | 214 +++++-----
 drivers/net/dsa/microchip/ksz8863_reg.h | 124 ++++++
 3 files changed, 629 insertions(+), 250 deletions(-)
 create mode 100644 drivers/net/dsa/microchip/ksz8863_reg.h

diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c
index 480143905d75579..4531bc413001c1e 100644
--- a/drivers/net/dsa/microchip/ksz8795.c
+++ b/drivers/net/dsa/microchip/ksz8795.c
@@ -20,50 +20,109 @@
 
 #include "ksz_common.h"
 #include "ksz8795_reg.h"
+#include "ksz8863_reg.h"
 #include "ksz8.h"
 
 static struct ksz_regs ksz8795_regs = {
-	.ind_ctrl_0			= REG_IND_CTRL_0,
-	.ind_data_8			= REG_IND_DATA_8,
-	.ind_data_check			= REG_IND_DATA_CHECK,
-	.ind_data_hi			= REG_IND_DATA_HI,
-	.ind_data_lo			= REG_IND_DATA_LO,
-	.ind_mib_check			= REG_IND_MIB_CHECK,
-	.p_force_ctrl			= P_FORCE_CTRL,
-	.p_link_status			= P_LINK_STATUS,
-	.p_local_ctrl			= P_LOCAL_CTRL,
-	.p_neg_restart_ctrl		= P_NEG_RESTART_CTRL,
-	.p_remote_status		= P_REMOTE_STATUS,
-	.p_speed_status			= P_SPEED_STATUS,
-	.s_tail_tag_ctrl		= S_TAIL_TAG_CTRL,
+	.ind_ctrl_0			= KSZ8795_REG_IND_CTRL_0,
+	.ind_data_8			= KSZ8795_REG_IND_DATA_8,
+	.ind_data_check			= KSZ8795_REG_IND_DATA_CHECK,
+	.ind_data_hi			= KSZ8795_REG_IND_DATA_HI,
+	.ind_data_lo			= KSZ8795_REG_IND_DATA_LO,
+	.ind_mib_check			= KSZ8795_REG_IND_MIB_CHECK,
+	.p_force_ctrl			= KSZ8795_P_FORCE_CTRL,
+	.p_link_status			= KSZ8795_P_LINK_STATUS,
+	.p_local_ctrl			= KSZ8795_P_LOCAL_CTRL,
+	.p_neg_restart_ctrl		= KSZ8795_P_NEG_RESTART_CTRL,
+	.p_remote_status		= KSZ8795_P_REMOTE_STATUS,
+	.p_speed_status			= KSZ8795_P_SPEED_STATUS,
+	.s_tail_tag_ctrl		= KSZ8795_S_TAIL_TAG_CTRL,
 };
 
 static struct ksz_masks ksz8795_masks = {
-	.port_802_1p_remapping		= PORT_802_1P_REMAPPING,
-	.sw_tail_tag_enable		= SW_TAIL_TAG_ENABLE,
-	.mib_counter_overflow		= MIB_COUNTER_OVERFLOW,
-	.mib_counter_valid		= MIB_COUNTER_VALID,
-	.vlan_table_fid			= VLAN_TABLE_FID,
-	.vlan_table_membership		= VLAN_TABLE_MEMBERSHIP,
-	.vlan_table_valid		= VLAN_TABLE_VALID,
-	.static_mac_table_valid		= STATIC_MAC_TABLE_VALID,
-	.static_mac_table_use_fid	= STATIC_MAC_TABLE_USE_FID,
-	.static_mac_table_fid		= STATIC_MAC_TABLE_FID,
-	.static_mac_table_override	= STATIC_MAC_TABLE_OVERRIDE,
-	.static_mac_table_fwd_ports	= STATIC_MAC_TABLE_FWD_PORTS,
-	.dynamic_mac_table_entries_h	= DYNAMIC_MAC_TABLE_ENTRIES_H,
-	.dynamic_mac_table_mac_empty	= DYNAMIC_MAC_TABLE_MAC_EMPTY,
-	.dynamic_mac_table_not_ready	= DYNAMIC_MAC_TABLE_NOT_READY,
-	.dynamic_mac_table_entries	= DYNAMIC_MAC_TABLE_ENTRIES,
-	.dynamic_mac_table_fid		= DYNAMIC_MAC_TABLE_FID,
-	.dynamic_mac_table_src_port	= DYNAMIC_MAC_TABLE_SRC_PORT,
-	.dynamic_mac_table_timestamp	= DYNAMIC_MAC_TABLE_TIMESTAMP,
+	.port_802_1p_remapping		= KSZ8795_PORT_802_1P_REMAPPING,
+	.sw_tail_tag_enable		= KSZ8795_SW_TAIL_TAG_ENABLE,
+	.mib_counter_overflow		= KSZ8795_MIB_COUNTER_OVERFLOW,
+	.mib_counter_valid		= KSZ8795_MIB_COUNTER_VALID,
+	.vlan_table_fid			= KSZ8795_VLAN_TABLE_FID,
+	.vlan_table_membership		= KSZ8795_VLAN_TABLE_MEMBERSHIP,
+	.vlan_table_valid		= KSZ8795_VLAN_TABLE_VALID,
+	.static_mac_table_valid		= KSZ8795_STATIC_MAC_TABLE_VALID,
+	.static_mac_table_use_fid	= KSZ8795_STATIC_MAC_TABLE_USE_FID,
+	.static_mac_table_fid		= KSZ8795_STATIC_MAC_TABLE_FID,
+	.static_mac_table_override	= KSZ8795_STATIC_MAC_TABLE_OVERRIDE,
+	.static_mac_table_fwd_ports	= KSZ8795_STATIC_MAC_TABLE_FWD_PORTS,
+	.dynamic_mac_table_entries_h	= KSZ8795_DYNAMIC_MAC_TABLE_ENTRIES_H,
+	.dynamic_mac_table_mac_empty	= KSZ8795_DYNAMIC_MAC_TABLE_MAC_EMPTY,
+	.dynamic_mac_table_not_ready	= KSZ8795_DYNAMIC_MAC_TABLE_NOT_READY,
+	.dynamic_mac_table_entries	= KSZ8795_DYNAMIC_MAC_TABLE_ENTRIES,
+	.dynamic_mac_table_fid		= KSZ8795_DYNAMIC_MAC_TABLE_FID,
+	.dynamic_mac_table_src_port	= KSZ8795_DYNAMIC_MAC_TABLE_SRC_PORT,
+	.dynamic_mac_table_timestamp	= KSZ8795_DYNAMIC_MAC_TABLE_TIMESTAMP,
 };
 
+static struct ksz_shifts ksz8795_shifts = {
+	.vlan_table_membership		= KSZ8795_VLAN_TABLE_MEMBERSHIP_S,
+	.vlan_table			= KSZ8795_VLAN_TABLE_S,
+	.static_mac_fwd_ports		= KSZ8795_STATIC_MAC_FWD_PORTS_S,
+	.static_mac_fid			= KSZ8795_STATIC_MAC_FID_S,
+	.dynamic_mac_entries		= KSZ8795_DYNAMIC_MAC_ENTRIES_S,
+	.dynamic_mac_fid		= KSZ8795_DYNAMIC_MAC_FID_S,
+	.dynamic_mac_timestamp		= KSZ8795_DYNAMIC_MAC_TIMESTAMP_S,
+	.dynamic_mac_src_port		= KSZ8795_DYNAMIC_MAC_SRC_PORT_S,
+};
+
+static struct ksz_regs ksz8863_regs = {
+	.ind_ctrl_0			= KSZ8863_REG_IND_CTRL_0,
+	.ind_data_8			= KSZ8863_REG_IND_DATA_8,
+	.ind_data_check			= KSZ8863_REG_IND_DATA_CHECK,
+	.ind_data_hi			= KSZ8863_REG_IND_DATA_HI,
+	.ind_data_lo			= KSZ8863_REG_IND_DATA_LO,
+	.ind_mib_check			= KSZ8863_REG_IND_MIB_CHECK,
+	.p_force_ctrl			= KSZ8863_P_FORCE_CTRL,
+	.p_link_status			= KSZ8863_P_LINK_STATUS,
+	.p_local_ctrl			= KSZ8863_P_LOCAL_CTRL,
+	.p_neg_restart_ctrl		= KSZ8863_P_NEG_RESTART_CTRL,
+	.p_remote_status		= KSZ8863_P_REMOTE_STATUS,
+	.p_speed_status			= KSZ8863_P_SPEED_STATUS,
+	.s_tail_tag_ctrl		= KSZ8863_S_TAIL_TAG_CTRL,
+};
+
+static struct ksz_masks ksz8863_masks = {
+	.port_802_1p_remapping		= KSZ8863_PORT_802_1P_REMAPPING,
+	.sw_tail_tag_enable		= KSZ8863_SW_TAIL_TAG_ENABLE,
+	.mib_counter_overflow		= KSZ8863_MIB_COUNTER_OVERFLOW,
+	.mib_counter_valid		= KSZ8863_MIB_COUNTER_VALID,
+	.vlan_table_fid			= KSZ8863_VLAN_TABLE_FID,
+	.vlan_table_membership		= KSZ8863_VLAN_TABLE_MEMBERSHIP,
+	.vlan_table_valid		= KSZ8863_VLAN_TABLE_VALID,
+	.static_mac_table_valid		= KSZ8863_STATIC_MAC_TABLE_VALID,
+	.static_mac_table_use_fid	= KSZ8863_STATIC_MAC_TABLE_USE_FID,
+	.static_mac_table_fid		= KSZ8863_STATIC_MAC_TABLE_FID,
+	.static_mac_table_override	= KSZ8863_STATIC_MAC_TABLE_OVERRIDE,
+	.static_mac_table_fwd_ports	= KSZ8863_STATIC_MAC_TABLE_FWD_PORTS,
+	.dynamic_mac_table_entries_h	= KSZ8863_DYNAMIC_MAC_TABLE_ENTRIES_H,
+	.dynamic_mac_table_mac_empty	= KSZ8863_DYNAMIC_MAC_TABLE_MAC_EMPTY,
+	.dynamic_mac_table_not_ready	= KSZ8863_DYNAMIC_MAC_TABLE_NOT_READY,
+	.dynamic_mac_table_entries	= KSZ8863_DYNAMIC_MAC_TABLE_ENTRIES,
+	.dynamic_mac_table_fid		= KSZ8863_DYNAMIC_MAC_TABLE_FID,
+	.dynamic_mac_table_src_port	= KSZ8863_DYNAMIC_MAC_TABLE_SRC_PORT,
+	.dynamic_mac_table_timestamp	= KSZ8863_DYNAMIC_MAC_TABLE_TIMESTAMP,
+};
+
+static struct ksz_shifts ksz8863_shifts = {
+	.vlan_table_membership		= KSZ8863_VLAN_TABLE_MEMBERSHIP_S,
+	.static_mac_fwd_ports		= KSZ8863_STATIC_MAC_FWD_PORTS_S,
+	.static_mac_fid			= KSZ8863_STATIC_MAC_FID_S,
+	.dynamic_mac_entries		= KSZ8863_DYNAMIC_MAC_ENTRIES_S,
+	.dynamic_mac_fid		= KSZ8863_DYNAMIC_MAC_FID_S,
+	.dynamic_mac_timestamp		= KSZ8863_DYNAMIC_MAC_TIMESTAMP_S,
+	.dynamic_mac_src_port		= KSZ8863_DYNAMIC_MAC_SRC_PORT_S,
+};
 
 static const struct {
 	char string[ETH_GSTRING_LEN];
-} mib_names[TOTAL_SWITCH_COUNTER_NUM] = {
+} ksz87xx_mib_names[TOTAL_KSZ8795_COUNTER_NUM] = {
 	{ "rx_hi" },
 	{ "rx_undersize" },
 	{ "rx_fragments" },
@@ -102,6 +161,45 @@ static const struct {
 	{ "tx_discards" },
 };
 
+static const struct {
+	char string[ETH_GSTRING_LEN];
+} ksz88xx_mib_names[TOTAL_KSZ8863_COUNTER_NUM] = {
+	{ "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);
@@ -114,12 +212,23 @@ static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits,
 			   bits, set ? bits : 0);
 }
 
+static int ksz_is_87(struct ksz_device *dev)
+{
+	return (((dev->chip_id) >> 8) == KSZ87_FAMILY_ID);
+}
+
 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 (ksz_is_87(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);
+	} else {
+		/* reset switch */
+		ksz_cfg(dev, KSZ8863_REG_SW_RESET,
+			KSZ8863_GLOBAL_SOFTWARE_RESET | KSZ8863_PCS_RESET, true);
+	}
 
 	return 0;
 }
@@ -190,8 +299,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;
 	struct ksz_regs *regs = ksz8->regs;
@@ -200,9 +309,9 @@ static void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
 	u8 check;
 	int loop;
 
-	addr -= SWITCH_COUNTER_NUM;
-	ctrl_addr = (KS_MIB_TOTAL_RX_1 - KS_MIB_TOTAL_RX_0) * port;
-	ctrl_addr += addr + KS_MIB_TOTAL_RX_0;
+	addr -= dev->reg_mib_cnt;
+	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);
@@ -214,7 +323,7 @@ static void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
 	for (loop = 2; loop > 0; loop--) {
 		ksz_read8(dev, regs->ind_mib_check, &check);
 
-		if (check & MIB_COUNTER_VALID) {
+		if (check & KSZ8795_MIB_COUNTER_VALID) {
 			ksz_read32(dev, regs->ind_data_lo, &data);
 			if (addr < 2) {
 				u64 total;
@@ -223,13 +332,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 & KSZ8795_MIB_COUNTER_OVERFLOW) {
 					total = MIB_TOTAL_BYTES_H + 1;
 					total <<= 32;
 					*cnt += total;
 				}
 			} else {
-				if (check & MIB_COUNTER_OVERFLOW)
+				if (check & KSZ8795_MIB_COUNTER_OVERFLOW)
 					*cnt += MIB_PACKET_DROPPED + 1;
 				*cnt += data & MIB_PACKET_DROPPED;
 			}
@@ -239,8 +348,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;
+	struct ksz_regs *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->ind_ctrl_0, ctrl_addr);
+	ksz_read32(dev, regs->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 (ksz_is_87(dev)) {
+		ksz8795_r_mib_pkt(dev, port, addr, dropped, cnt);
+	} else {
+		ksz8863_r_mib_pkt(dev, port, addr, dropped, cnt);
+	}
+}
+
 static void ksz8_freeze_mib(struct ksz_device *dev, int port, bool freeze)
 {
+	if (!ksz_is_87(dev))
+		return;
+
 	/* enable the port for flush/freeze function */
 	if (freeze)
 		ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), true);
@@ -254,11 +408,14 @@ static void ksz8_freeze_mib(struct ksz_device *dev, int port, bool freeze)
 static void ksz8_port_init_cnt(struct ksz_device *dev, int port)
 {
 	struct ksz_port_mib *mib = &dev->ports[port].mib;
+	u64 *dropped;
 
-	/* 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 (ksz_is_87(dev)) {
+		/* 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;
 
@@ -269,10 +426,13 @@ static void ksz8_port_init_cnt(struct ksz_device *dev, int port)
 		++mib->cnt_ptr;
 	}
 
+	/* last one in storage */
+	dropped = &mib->counters[dev->mib_cnt];
+
 	/* Some ports may not have MIB counters after SWITCH_COUNTER_NUM. */
 	while (mib->cnt_ptr < dev->mib_cnt) {
 		dev->dev_ops->r_mib_pkt(dev, port, mib->cnt_ptr,
-					NULL, &mib->counters[mib->cnt_ptr]);
+					dropped, &mib->counters[mib->cnt_ptr]);
 		++mib->cnt_ptr;
 	}
 	mib->cnt_ptr = 0;
@@ -420,6 +580,7 @@ static int ksz8_r_sta_mac_table(struct ksz_device *dev, u16 addr,
 		alu->is_override =
 			(data_hi & masks->static_mac_table_override) ? 1 : 0;
 		data_hi >>= 1;
+		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) >>
@@ -495,37 +656,45 @@ static void ksz8_r_vlan_entries(struct ksz_device *dev, u16 addr)
 	ksz8_r_table(dev, TABLE_VLAN, addr, &data);
 	addr *= dev->port_cnt;
 	for (i = 0; i < dev->port_cnt; i++) {
-		dev->vlan_cache[addr + i].table[0] = (u16)data;
-		data >>= shifts->vlan_table;
+		if (ksz_is_87(dev)) {
+			dev->vlan_cache[addr + i].table[0] = (u16)data;
+			data >>= shifts->vlan_table;
+		} else {
+			dev->vlan_cache[addr + i].table[0] = (u32)data;
+		}
 	}
 }
 
 static void ksz8_r_vlan_table(struct ksz_device *dev, u16 vid, u32 *vlan)
 {
-	int index;
-	u16 *data;
-	u16 addr;
+	u16 addr = vid / dev->port_cnt;
 	u64 buf;
 
-	data = (u16 *)&buf;
-	addr = vid / dev->port_cnt;
-	index = vid & 3;
 	ksz8_r_table(dev, TABLE_VLAN, addr, &buf);
-	*vlan = data[index];
+	if (ksz_is_87(dev)) {
+		u16 *data = (u16 *)&buf;
+
+		*vlan = data[vid & 3];
+	} else {
+		*vlan = (u32)buf;
+	}
 }
 
 static void ksz8_w_vlan_table(struct ksz_device *dev, u16 vid, u32 vlan)
 {
-	int index;
-	u16 *data;
-	u16 addr;
+	u16 addr = vid / dev->port_cnt;
 	u64 buf;
 
-	data = (u16 *)&buf;
-	addr = vid / dev->port_cnt;
-	index = vid & 3;
 	ksz8_r_table(dev, TABLE_VLAN, addr, &buf);
-	data[index] = vlan;
+
+	if (ksz_is_87(dev)) {
+		u16 *data = (u16 *)&buf;
+
+		data[vid & 3] = vlan;
+	} else {
+		buf = vlan;
+	}
+
 	dev->vlan_cache[vid].table[0] = vlan;
 	ksz8_w_table(dev, TABLE_VLAN, addr, buf);
 }
@@ -548,8 +717,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 (ksz_is_87(dev)) {
+			if (!(ctrl & PORT_AUTO_NEG_DISABLE))
+				data |= PHY_AUTO_NEG_ENABLE;
+		} else {
+			if ((ctrl & PORT_AUTO_NEG_ENABLE))
+				data |= PHY_AUTO_NEG_ENABLE;
+		}
 		if (restart & PORT_POWER_DOWN)
 			data |= PHY_POWER_DOWN;
 		if (restart & PORT_AUTO_NEG_RESTART)
@@ -580,10 +754,16 @@ static void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
 			data |= PHY_LINK_STATUS;
 		break;
 	case PHY_REG_ID_1:
-		data = KSZ8795_ID_HI;
+		if (ksz_is_87(dev))
+			data = KSZ8795_ID_HI;
+		else
+			data = KSZ8863_ID_HI;
 		break;
 	case PHY_REG_ID_2:
-		data = KSZ8795_ID_LO;
+		if (ksz_is_87(dev))
+			data = KSZ8795_ID_LO;
+		else
+			data = KSZ8863_ID_LO;
 		break;
 	case PHY_REG_AUTO_NEGOTIATION:
 		ksz_pread8(dev, p, regs->p_local_ctrl, &ctrl);
@@ -646,14 +826,21 @@ 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;
-
-		/* Fiber port does not support auto-negotiation. */
-		if (dev->ports[p].fiber)
-			data |= PORT_AUTO_NEG_DISABLE;
+		if (ksz_is_87(dev)) {
+			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;
+		} else {
+			if ((val & PHY_AUTO_NEG_ENABLE))
+				data |= PORT_AUTO_NEG_ENABLE;
+			else
+				data &= ~PORT_AUTO_NEG_ENABLE;
+		}
 		if (val & PHY_SPEED_100MBIT)
 			data |= PORT_FORCE_100_MBIT;
 		else
@@ -727,26 +914,46 @@ 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;
+
+	return ksz_is_87(dev) ?
+		DSA_TAG_PROTO_KSZ8795 : DSA_TAG_PROTO_KSZ8863;
 }
 
 static void ksz8_get_strings(struct dsa_switch *ds, int port,
 			     u32 stringset, uint8_t *buf)
 {
+	struct ksz_device *dev = ds->priv;
+	int switch_counter;
 	int i;
 
-	for (i = 0; i < TOTAL_SWITCH_COUNTER_NUM; i++) {
-		memcpy(buf + i * ETH_GSTRING_LEN, mib_names[i].string,
-		       ETH_GSTRING_LEN);
+	if (ksz_is_87(dev))
+		switch_counter = TOTAL_KSZ8795_COUNTER_NUM;
+	else
+		switch_counter = TOTAL_KSZ8863_COUNTER_NUM;
+
+	for (i = 0; i < switch_counter; i++) {
+		const char *s;
+
+		if (ksz_is_87(dev))
+			s = ksz87xx_mib_names[i].string;
+		else
+			s = ksz88xx_mib_names[i].string;
+
+		memcpy(buf + i * ETH_GSTRING_LEN, s, 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 (!ksz_is_87(dev))
+		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;
@@ -990,17 +1197,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;
+
+	/* 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 (dev->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 (dev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
+		    dev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
+			data8 |= PORT_RGMII_ID_IN_ENABLE;
+		if (dev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
+		    dev->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;
 	struct ksz8 *ksz8 = dev->priv;
 	struct ksz_masks *masks = ksz8->masks;
 
 	/* 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 (ksz_is_87(dev))
+		ksz8795_set_prio_queue(dev, port, 4);
 
 	/* disable DiffServ priority */
 	ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_DIFFSERV_ENABLE, false);
@@ -1013,39 +1261,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) {
-		/* 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 (dev->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 (dev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
-			    dev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
-				data8 |= PORT_RGMII_ID_IN_ENABLE;
-			if (dev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
-			    dev->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;
+		if (ksz_is_87(dev))
+			ksz8795_cpu_interface_select(dev, port);
 
 		member = dev->port_mask;
 	} else {
@@ -1097,9 +1314,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 (ksz_is_87(dev)) {
+			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);
@@ -1120,7 +1339,7 @@ static int ksz8_setup(struct dsa_switch *ds)
 	if (!dev->vlan_cache)
 		return -ENOMEM;
 
-	ret = ksz8_reset_switch(dev);
+	ksz8_reset_switch(dev);
 	if (ret) {
 		dev_err(ds->dev, "failed to reset switch\n");
 		return ret;
@@ -1157,7 +1376,7 @@ static int ksz8_setup(struct dsa_switch *ds)
 			   (BROADCAST_STORM_VALUE *
 			   BROADCAST_STORM_PROT_RATE) / 100);
 
-	for (i = 0; i < VLAN_TABLE_ENTRIES; i++)
+	for (i = 0; i < (dev->num_vlans / 2); i++)
 		ksz8_r_vlan_entries(dev, i);
 
 	/* Setup STP address for STP operation. */
@@ -1218,25 +1437,39 @@ 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;
 
-	dev->mib_port_cnt = TOTAL_PORT_NUM;
-	dev->phy_port_cnt = SWITCH_PORT_NUM;
-	dev->port_cnt = SWITCH_PORT_NUM;
-
-	if (id2 == CHIP_ID_95) {
-		u8 val;
-
-		id2 = 0x95;
-		ksz_read8(dev, REG_PORT_1_STATUS_0, &val);
-		if (val & PORT_FIBER_MODE)
-			id2 = 0x65;
-	} else if (id2 == CHIP_ID_94) {
-		dev->port_cnt--;
-		dev->last_port = dev->port_cnt;
-		id2 = 0x94;
+	switch (id1) {
+	case KSZ87_FAMILY_ID:
+		if ((id2 != CHIP_ID_94 && id2 != CHIP_ID_95))
+			return -ENODEV;
+
+		dev->mib_port_cnt = KSZ8795_TOTAL_PORT_NUM;
+		dev->phy_port_cnt = KSZ8795_SWITCH_PORT_NUM;
+		dev->port_cnt = KSZ8795_SWITCH_PORT_NUM;
+		if (id2 == CHIP_ID_95) {
+			u8 val;
+
+			id2 = 0x95;
+			ksz_read8(dev, KSZ8795_REG_PORT_STATUS_0, &val);
+			if (val & PORT_FIBER_MODE)
+				id2 = 0x65;
+		} else if (id2 == CHIP_ID_94) {
+			dev->port_cnt--;
+			dev->last_port = dev->port_cnt;
+			id2 = 0x94;
+		}
+		break;
+	case KSZ88_FAMILY_ID:
+		if (id2 != CHIP_ID_63)
+			return -ENODEV;
+
+		dev->mib_port_cnt = KSZ8863_TOTAL_PORT_NUM;
+		dev->phy_port_cnt = KSZ8863_SWITCH_PORT_NUM;
+		dev->port_cnt = KSZ8863_SWITCH_PORT_NUM;
+		break;
+	default:
+		dev_err(dev->dev, "invalid family id: %d\n", id1);
+		return -ENODEV;
 	}
 	id16 &= ~0xff;
 	id16 |= id2;
@@ -1286,6 +1519,15 @@ static const struct ksz_chip_data ksz8_switch_chips[] = {
 		.cpu_ports = 0x10,	/* can be configured as cpu port */
 		.port_cnt = 4,		/* total physical port count */
 	},
+	{
+		.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 = 2,		/* total physical port count */
+	},
 };
 
 static int ksz8_switch_init(struct ksz_device *dev)
@@ -1314,15 +1556,22 @@ 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 (ksz_is_87(dev)) {
+		ksz8->regs = &ksz8795_regs;
+		ksz8->masks = &ksz8795_masks;
+		ksz8->shifts = &ksz8795_shifts;
+		dev->mib_cnt = TOTAL_KSZ8795_COUNTER_NUM;
+	} else {
+		ksz8->regs = &ksz8863_regs;
+		ksz8->masks = &ksz8863_masks;
+		ksz8->shifts = &ksz8863_shifts;
+		dev->mib_cnt = TOTAL_KSZ8863_COUNTER_NUM;
+	}
 
 	dev->port_mask = BIT(dev->port_cnt) - 1;
 	dev->port_mask |= dev->host_mask;
 
 	dev->reg_mib_cnt = SWITCH_COUNTER_NUM;
-	dev->mib_cnt = TOTAL_SWITCH_COUNTER_NUM;
 
 	i = dev->mib_port_cnt;
 	dev->ports = devm_kzalloc(dev->dev, sizeof(struct ksz_port) * i,
@@ -1334,7 +1583,7 @@ static int ksz8_switch_init(struct ksz_device *dev)
 		dev->ports[i].mib.counters =
 			devm_kzalloc(dev->dev,
 				     sizeof(u64) *
-				     (TOTAL_SWITCH_COUNTER_NUM + 1),
+				     (dev->mib_cnt + 1),
 				     GFP_KERNEL);
 		if (!dev->ports[i].mib.counters)
 			return -ENOMEM;
diff --git a/drivers/net/dsa/microchip/ksz8795_reg.h b/drivers/net/dsa/microchip/ksz8795_reg.h
index 3a50462df8fa9d2..ed543ceac6b7d7b 100644
--- a/drivers/net/dsa/microchip/ksz8795_reg.h
+++ b/drivers/net/dsa/microchip/ksz8795_reg.h
@@ -16,7 +16,7 @@
 
 #define REG_CHIP_ID0			0x00
 
-#define FAMILY_ID			0x87
+#define KSZ87_FAMILY_ID			0x87
 
 #define REG_CHIP_ID1			0x01
 
@@ -32,7 +32,7 @@
 #define REG_SW_CTRL_0			0x02
 
 #define SW_NEW_BACKOFF			BIT(7)
-#define SW_GLOBAL_RESET			BIT(6)
+#define KSZ8795_SW_GLOBAL_RESET			BIT(6)
 #define SW_FLUSH_DYN_MAC_TABLE		BIT(5)
 #define SW_FLUSH_STA_MAC_TABLE		BIT(4)
 #define SW_LINK_AUTO_AGING		BIT(0)
@@ -98,7 +98,7 @@
 
 #define REG_SW_CTRL_10			0x0C
 
-#define SW_TAIL_TAG_ENABLE		BIT(1)
+#define KSZ8795_SW_TAIL_TAG_ENABLE		BIT(1)
 #define SW_PASS_PAUSE			BIT(0)
 
 #define REG_SW_CTRL_11			0x0D
@@ -150,7 +150,7 @@
 #define REG_PORT_4_CTRL_2		0x42
 #define REG_PORT_5_CTRL_2		0x52
 
-#define PORT_802_1P_REMAPPING		BIT(7)
+#define KSZ8795_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)
@@ -269,6 +269,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)
@@ -320,30 +321,36 @@
 #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 KSZ8795_REG_PORT_STATUS_0		0x08
+#define KSZ8795_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
-#define REG_PORT_CTRL_13		0xA1
-#define REG_PORT_RATE_CTRL_3		0xA2
-#define REG_PORT_RATE_CTRL_2		0xA3
-#define REG_PORT_RATE_CTRL_1		0xA4
-#define REG_PORT_RATE_CTRL_0		0xA5
-#define REG_PORT_RATE_LIMIT		0xA6
-#define REG_PORT_IN_RATE_0		0xA7
-#define REG_PORT_IN_RATE_1		0xA8
-#define REG_PORT_IN_RATE_2		0xA9
-#define REG_PORT_IN_RATE_3		0xAA
-#define REG_PORT_OUT_RATE_0		0xAB
-#define REG_PORT_OUT_RATE_1		0xAC
-#define REG_PORT_OUT_RATE_2		0xAD
-#define REG_PORT_OUT_RATE_3		0xAE
+
+#define KSZ8795_REG_PORT_CTRL_9			0x0C
+#define KSZ8795_REG_PORT_CTRL_10		0x0D
+#define KSZ8795_REG_PORT_STATUS_2		0x0E
+#define KSZ8795_REG_PORT_STATUS_3		0x0F
+
+#define REG_PORT_CTRL_12			0x0C
+#define REG_PORT_CTRL_13			0x0D
+
+#define KSZ8795_REG_PORT_CTRL_12		0xA0
+#define KSZ8795_REG_PORT_CTRL_13		0xA1
+#define KSZ8795_REG_PORT_RATE_CTRL_3		0xA2
+#define KSZ8795_REG_PORT_RATE_CTRL_2		0xA3
+#define KSZ8795_REG_PORT_RATE_CTRL_1		0xA4
+#define KSZ8795_REG_PORT_RATE_CTRL_0		0xA5
+#define KSZ8795_REG_PORT_RATE_LIMIT		0xA6
+#define KSZ8795_REG_PORT_IN_RATE_0		0xA7
+#define KSZ8795_REG_PORT_IN_RATE_1		0xA8
+#define KSZ8795_REG_PORT_IN_RATE_2		0xA9
+#define KSZ8795_REG_PORT_IN_RATE_3		0xAA
+#define KSZ8795_REG_PORT_OUT_RATE_0		0xAB
+#define KSZ8795_REG_PORT_OUT_RATE_1		0xAC
+#define KSZ8795_REG_PORT_OUT_RATE_2		0xAD
+#define KSZ8795_REG_PORT_OUT_RATE_3		0xAE
 
 #define PORT_CTRL_ADDR(port, addr)		\
 	((addr) + REG_PORT_1_CTRL_0 + (port) *	\
@@ -356,7 +363,7 @@
 #define REG_SW_MAC_ADDR_4		0x6C
 #define REG_SW_MAC_ADDR_5		0x6D
 
-#define REG_IND_CTRL_0			0x6E
+#define KSZ8795_REG_IND_CTRL_0			0x6E
 
 #define TABLE_EXT_SELECT_S		5
 #define TABLE_EEE_V			1
@@ -378,27 +385,27 @@
 #define TABLE_DYNAMIC_MAC		(TABLE_DYNAMIC_MAC_V << TABLE_SELECT_S)
 #define TABLE_MIB			(TABLE_MIB_V << TABLE_SELECT_S)
 
-#define REG_IND_CTRL_1			0x6F
+#define KSZ8795_REG_IND_CTRL_1			0x6F
 
 #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 KSZ8795_REG_IND_DATA_8		0x70
+#define KSZ8795_REG_IND_DATA_7		0x71
+#define KSZ8795_REG_IND_DATA_6		0x72
+#define KSZ8795_REG_IND_DATA_5		0x73
+#define KSZ8795_REG_IND_DATA_4		0x74
+#define KSZ8795_REG_IND_DATA_3		0x75
+#define KSZ8795_REG_IND_DATA_2		0x76
+#define KSZ8795_REG_IND_DATA_1		0x77
+#define KSZ8795_REG_IND_DATA_0		0x78
 
-#define REG_IND_DATA_PME_EEE_ACL	0xA0
+#define KSZ8795_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 KSZ8795_REG_IND_DATA_CHECK	KSZ8795_REG_IND_DATA_6
+#define KSZ8795_REG_IND_MIB_CHECK	KSZ8795_REG_IND_DATA_4
+#define KSZ8795_REG_IND_DATA_HI		KSZ8795_REG_IND_DATA_7
+#define KSZ8795_REG_IND_DATA_LO		KSZ8795_REG_IND_DATA_3
 
 #define REG_INT_STATUS			0x7C
 #define REG_INT_ENABLE			0x7D
@@ -846,16 +853,15 @@
 
 #define KS_PRIO_IN_REG			4
 
-#define TOTAL_PORT_NUM			5
+#define KSZ8795_TOTAL_PORT_NUM		5
 
 /* Host port can only be last of them. */
-#define SWITCH_PORT_NUM			(TOTAL_PORT_NUM - 1)
+#define KSZ8795_SWITCH_PORT_NUM		(KSZ8795_TOTAL_PORT_NUM - 1)
 
 #define KSZ8795_COUNTER_NUM		0x20
 #define TOTAL_KSZ8795_COUNTER_NUM	(KSZ8795_COUNTER_NUM + 4)
 
 #define SWITCH_COUNTER_NUM		KSZ8795_COUNTER_NUM
-#define TOTAL_SWITCH_COUNTER_NUM	TOTAL_KSZ8795_COUNTER_NUM
 
 /* Common names used by other drivers */
 
@@ -865,16 +871,16 @@
 #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
-#define P_RATE_LIMIT_CTRL		REG_PORT_RATE_LIMIT
+#define KSZ8795_P_LOCAL_CTRL			REG_PORT_CTRL_7
+#define KSZ8795_P_REMOTE_STATUS			KSZ8795_REG_PORT_STATUS_0
+#define KSZ8795_P_FORCE_CTRL			KSZ8795_REG_PORT_CTRL_9
+#define KSZ8795_P_NEG_RESTART_CTRL		KSZ8795_REG_PORT_CTRL_10
+#define KSZ8795_P_SPEED_STATUS			KSZ8795_REG_PORT_STATUS_1
+#define KSZ8795_P_LINK_STATUS			KSZ8795_REG_PORT_STATUS_2
+#define P_PASS_ALL_CTRL			KSZ8795_REG_PORT_CTRL_12
+#define P_INS_SRC_PVID_CTRL		KSZ8795_REG_PORT_CTRL_12
+#define P_DROP_TAG_CTRL			KSZ8795_REG_PORT_CTRL_13
+#define P_RATE_LIMIT_CTRL		KSZ8795_REG_PORT_RATE_LIMIT
 
 #define S_UNKNOWN_DA_CTRL		REG_SWITCH_CTRL_12
 #define S_FORWARD_INVALID_VID_CTRL	REG_FORWARD_INVALID_VID
@@ -885,7 +891,7 @@
 #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 KSZ8795_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
@@ -907,15 +913,15 @@
  * 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 KSZ8795_STATIC_MAC_TABLE_ADDR		0x0000FFFF
+#define KSZ8795_STATIC_MAC_TABLE_FWD_PORTS	0x001F0000
+#define KSZ8795_STATIC_MAC_TABLE_VALID		0x00200000
+#define KSZ8795_STATIC_MAC_TABLE_OVERRIDE	0x00400000
+#define KSZ8795_STATIC_MAC_TABLE_USE_FID	0x00800000
+#define KSZ8795_STATIC_MAC_TABLE_FID		0x7F000000
 
-#define STATIC_MAC_FWD_PORTS_S		16
-#define STATIC_MAC_FID_S		24
+#define KSZ8795_STATIC_MAC_FWD_PORTS_S		16
+#define KSZ8795_STATIC_MAC_FID_S		24
 
 /**
  * VLAN_TABLE_FID			00-007F007F-007F007F
@@ -923,12 +929,12 @@
  * VLAN_TABLE_VALID			00-10001000-10001000
  */
 
-#define VLAN_TABLE_FID			0x007F
-#define VLAN_TABLE_MEMBERSHIP		0x0F80
-#define VLAN_TABLE_VALID		0x1000
+#define KSZ8795_VLAN_TABLE_FID			0x007F
+#define KSZ8795_VLAN_TABLE_MEMBERSHIP		0x0F80
+#define KSZ8795_VLAN_TABLE_VALID		0x1000
 
-#define VLAN_TABLE_MEMBERSHIP_S		7
-#define VLAN_TABLE_S			16
+#define KSZ8795_VLAN_TABLE_MEMBERSHIP_S		7
+#define KSZ8795_VLAN_TABLE_S			16
 
 /**
  * DYNAMIC_MAC_TABLE_ADDR		00-0000FFFF-FFFFFFFF
@@ -940,22 +946,22 @@
  * 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 KSZ8795_DYNAMIC_MAC_TABLE_ADDR		0x0000FFFF
+#define KSZ8795_DYNAMIC_MAC_TABLE_FID		0x007F0000
+#define KSZ8795_DYNAMIC_MAC_TABLE_SRC_PORT	0x07000000
+#define KSZ8795_DYNAMIC_MAC_TABLE_TIMESTAMP	0x18000000
+#define KSZ8795_DYNAMIC_MAC_TABLE_ENTRIES	0xE0000000
 
-#define DYNAMIC_MAC_TABLE_NOT_READY	0x80
+#define KSZ8795_DYNAMIC_MAC_TABLE_NOT_READY	0x80
 
-#define DYNAMIC_MAC_TABLE_ENTRIES_H	0x7F
-#define DYNAMIC_MAC_TABLE_MAC_EMPTY	0x80
+#define KSZ8795_DYNAMIC_MAC_TABLE_ENTRIES_H	0x7F
+#define KSZ8795_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
+#define KSZ8795_DYNAMIC_MAC_FID_S		16
+#define KSZ8795_DYNAMIC_MAC_SRC_PORT_S		24
+#define KSZ8795_DYNAMIC_MAC_TIMESTAMP_S		27
+#define KSZ8795_DYNAMIC_MAC_ENTRIES_S		29
+#define KSZ8795_DYNAMIC_MAC_ENTRIES_H_S		3
 
 /**
  * MIB_COUNTER_VALUE			00-00000000-3FFFFFFF
@@ -965,31 +971,31 @@
  * MIB_COUNTER_OVERFLOW			00-00000040-00000000
  */
 
-#define MIB_COUNTER_OVERFLOW		BIT(6)
-#define MIB_COUNTER_VALID		BIT(5)
+#define KSZ8795_MIB_COUNTER_OVERFLOW		BIT(6)
+#define KSZ8795_MIB_COUNTER_VALID		BIT(5)
 
 #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_PACKET_DROPPED_RX_0	0x102
+#define KSZ8795_MIB_PACKET_DROPPED_TX_0	0x103
+#define KSZ8795_MIB_TOTAL_RX_1		0x104
+#define KSZ8795_MIB_TOTAL_TX_1		0x105
+#define KSZ8795_MIB_PACKET_DROPPED_TX_1	0x106
+#define KSZ8795_MIB_PACKET_DROPPED_RX_1	0x107
+#define KSZ8795_MIB_TOTAL_RX_2		0x108
+#define KSZ8795_MIB_TOTAL_TX_2		0x109
+#define KSZ8795_MIB_PACKET_DROPPED_TX_2	0x10A
+#define KSZ8795_MIB_PACKET_DROPPED_RX_2	0x10B
+#define KSZ8795_MIB_TOTAL_RX_3		0x10C
+#define KSZ8795_MIB_TOTAL_TX_3		0x10D
+#define KSZ8795_MIB_PACKET_DROPPED_TX_3	0x10E
+#define KSZ8795_MIB_PACKET_DROPPED_RX_3	0x10F
+#define KSZ8795_MIB_TOTAL_RX_4		0x110
+#define KSZ8795_MIB_TOTAL_TX_4		0x111
+#define KSZ8795_MIB_PACKET_DROPPED_TX_4	0x112
+#define KSZ8795_MIB_PACKET_DROPPED_RX_4	0x113
 
 #define MIB_PACKET_DROPPED		0x0000FFFF
 
diff --git a/drivers/net/dsa/microchip/ksz8863_reg.h b/drivers/net/dsa/microchip/ksz8863_reg.h
new file mode 100644
index 000000000000000..6dbe7e1cf921fc4
--- /dev/null
+++ b/drivers/net/dsa/microchip/ksz8863_reg.h
@@ -0,0 +1,124 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Microchip KSZ8863 register definitions
+ *
+ * Copyright (C) 2019 Pengutronix, Michael Grzeschik <kernel@pengutronix.de>
+ */
+
+#ifndef __KSZ8863_REG_H
+#define __KSZ8863_REG_H
+
+#define KSZ88_FAMILY_ID				0x88
+
+#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 KSZ8863_SW_TAIL_TAG_ENABLE		BIT(6)
+
+#define KSZ8863_REG_POWER_MANAGEMENT		0xC3
+
+#define KSZ8863_PORT_802_1P_REMAPPING		BIT(3)
+
+#define KSZ8863_REG_PORT_STATUS_0		0x0E
+#define KSZ8863_REG_PORT_STATUS_1		0x0F
+
+#define KSZ8863_REG_IND_CTRL_0			0x79
+
+#define KSZ8863_REG_IND_CTRL_1			0x7A
+
+#define KSZ8863_REG_IND_DATA_8			0x7B
+#define KSZ8863_REG_IND_DATA_7			0x7C
+#define KSZ8863_REG_IND_DATA_6			0x7D
+#define KSZ8863_REG_IND_DATA_5			0x7E
+#define KSZ8863_REG_IND_DATA_4			0x7F
+#define KSZ8863_REG_IND_DATA_3			0x80
+#define KSZ8863_REG_IND_DATA_2			0x81
+#define KSZ8863_REG_IND_DATA_1			0x82
+#define KSZ8863_REG_IND_DATA_0			0x83
+
+#define KSZ8863_REG_IND_DATA_CHECK		KSZ8863_REG_IND_DATA_8
+#define KSZ8863_REG_IND_MIB_CHECK		KSZ8863_REG_IND_DATA_3
+#define KSZ8863_REG_IND_DATA_HI			KSZ8863_REG_IND_DATA_7
+#define KSZ8863_REG_IND_DATA_LO			KSZ8863_REG_IND_DATA_3
+
+#define KSZ8863_ID_HI				0x0022
+#define KSZ8863_ID_LO				0x1430
+
+#define KSZ8863_TOTAL_PORT_NUM			3
+#define KSZ8863_SWITCH_PORT_NUM			(KSZ8863_TOTAL_PORT_NUM - 1)
+
+#define KSZ8863_COUNTER_NUM			0x20
+#define TOTAL_KSZ8863_COUNTER_NUM		(KSZ8863_COUNTER_NUM + 2)
+
+#define KSZ8863_P_LOCAL_CTRL			REG_PORT_CTRL_12
+#define KSZ8863_P_REMOTE_STATUS			KSZ8863_REG_PORT_STATUS_0
+#define KSZ8863_P_FORCE_CTRL			REG_PORT_CTRL_12
+#define KSZ8863_P_NEG_RESTART_CTRL		REG_PORT_CTRL_13
+#define KSZ8863_P_SPEED_STATUS			KSZ8863_REG_PORT_STATUS_1
+#define KSZ8863_P_LINK_STATUS			KSZ8863_REG_PORT_STATUS_0
+#define KSZ8863_S_TAIL_TAG_CTRL			REG_SW_CTRL_1
+
+/**
+ * STATIC_MAC_TABLE_ADDR		00-0000FFFF-FFFFFFFF
+ * STATIC_MAC_TABLE_FWD_PORTS		00-00070000-00000000
+ * STATIC_MAC_TABLE_VALID		00-00080000-00000000
+ * STATIC_MAC_TABLE_OVERRIDE		00-00100000-00000000
+ * STATIC_MAC_TABLE_USE_FID		00-00200000-00000000
+ * STATIC_MAC_TABLE_FID			00-3C000000-00000000
+ */
+
+#define KSZ8863_STATIC_MAC_TABLE_ADDR		0x0000FFFF
+#define KSZ8863_STATIC_MAC_TABLE_FWD_PORTS	0x00070000
+#define KSZ8863_STATIC_MAC_TABLE_VALID		0x00080000
+#define KSZ8863_STATIC_MAC_TABLE_OVERRIDE	0x00100000
+#define KSZ8863_STATIC_MAC_TABLE_USE_FID	0x00200000
+#define KSZ8863_STATIC_MAC_TABLE_FID		0x3C000000
+
+#define KSZ8863_STATIC_MAC_FWD_PORTS_S		16
+#define KSZ8863_STATIC_MAC_FID_S		22
+
+/**
+ * VLAN_TABLE_VID			00-00000000-00000FFF
+ * VLAN_TABLE_FID			00-00000000-0000F000
+ * VLAN_TABLE_MEMBERSHIP		00-00000000-00070000
+ * VLAN_TABLE_VALID			00-00000000-00080000
+ */
+
+#define KSZ8863_VLAN_TABLE_VID			0x00FFF
+#define KSZ8863_VLAN_TABLE_FID			0x0F000
+#define KSZ8863_VLAN_TABLE_MEMBERSHIP		0x70000
+#define KSZ8863_VLAN_TABLE_VALID		0x80000
+
+#define KSZ8863_VLAN_TABLE_MEMBERSHIP_S		16
+
+#define KSZ8863_DYNAMIC_MAC_TABLE_ADDR		0x0000FFFF
+#define KSZ8863_DYNAMIC_MAC_TABLE_FID		0x000F0000
+#define KSZ8863_DYNAMIC_MAC_TABLE_SRC_PORT	0x00300000
+#define KSZ8863_DYNAMIC_MAC_TABLE_TIMESTAMP	0x00C00000
+#define KSZ8863_DYNAMIC_MAC_TABLE_ENTRIES	0xF0000000
+
+#define KSZ8863_DYNAMIC_MAC_TABLE_NOT_READY	0x80
+
+#define KSZ8863_DYNAMIC_MAC_TABLE_ENTRIES_H	0x3F
+#define KSZ8863_DYNAMIC_MAC_TABLE_MAC_EMPTY	0x80
+
+#define KSZ8863_DYNAMIC_MAC_FID_S		16
+#define KSZ8863_DYNAMIC_MAC_SRC_PORT_S		20
+#define KSZ8863_DYNAMIC_MAC_TIMESTAMP_S		24
+#define KSZ8863_DYNAMIC_MAC_ENTRIES_S		24
+#define KSZ8863_DYNAMIC_MAC_ENTRIES_H_S		3
+
+#define KSZ8863_MIB_COUNTER_OVERFLOW		BIT(7)
+#define KSZ8863_MIB_COUNTER_VALID		BIT(6)
+
+#define KSZ8863_MIB_PACKET_DROPPED_TX_0		0x100
+#define KSZ8863_MIB_PACKET_DROPPED_RX_0		0x105
+
+#define KSZ8863_REG_INT_ENABLE			0xBB
+#define KSZ8863_REG_INT_STATUS			0xBC
+
+#endif
-- 
2.28.0


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

* [PATCH v4 09/11] net: dsa: microchip: Add Microchip KSZ8863 SMI based driver support
  2020-08-03  5:44 [PATCH v4 00/11] microchip: add support for ksz88x3 driver family Michael Grzeschik
                   ` (7 preceding siblings ...)
  2020-08-03  5:44 ` [PATCH v4 08/11] net: dsa: microchip: ksz8795: add support for ksz88xx chips Michael Grzeschik
@ 2020-08-03  5:44 ` Michael Grzeschik
  2020-08-03 13:31   ` Randy Dunlap
                     ` (2 more replies)
  2020-08-03  5:44 ` [PATCH v4 10/11] net: dsa: microchip: Add Microchip KSZ8863 SPI " Michael Grzeschik
                   ` (2 subsequent siblings)
  11 siblings, 3 replies; 23+ messages in thread
From: Michael Grzeschik @ 2020-08-03  5:44 UTC (permalink / raw)
  To: andrew; +Cc: netdev, f.fainelli, davem, kernel

Add KSZ88X3 driver support. We add support for the KXZ88X3 three port
switches using the Microchip SMI Interface. They are supported using the
MDIO-Bitbang Interface.

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

---
v1 -> v2:  - this code was part of previuos patch
v2 -> v3:  - this code was part of previuos patch
v3 -> v4:  - moved this glue code so separate patch
           - fixed locking in regmap and mdio_read/mdio_write

 drivers/net/dsa/microchip/Kconfig       |   9 ++
 drivers/net/dsa/microchip/Makefile      |   1 +
 drivers/net/dsa/microchip/ksz8863_smi.c | 204 ++++++++++++++++++++++++
 3 files changed, 214 insertions(+)
 create mode 100644 drivers/net/dsa/microchip/ksz8863_smi.c

diff --git a/drivers/net/dsa/microchip/Kconfig b/drivers/net/dsa/microchip/Kconfig
index 4ec6a47b7f7284f..c5819bd4121cc7c 100644
--- a/drivers/net/dsa/microchip/Kconfig
+++ b/drivers/net/dsa/microchip/Kconfig
@@ -40,3 +40,12 @@ config NET_DSA_MICROCHIP_KSZ8795_SPI
 
 	  It is required to use the KSZ8795 switch driver as the only access
 	  is through SPI.
+
+config NET_DSA_MICROCHIP_KSZ8863_SMI
+	tristate "KSZ series SMI connected switch driver"
+	depends on NET_DSA_MICROCHIP_KSZ8795
+	select MDIO_BITBANG
+	default y
+	help
+	  Select to enable support for registering switches configured through
+	  Microchip SMI. It Supports the KSZ8863 and KSZ8873 Switch.
diff --git a/drivers/net/dsa/microchip/Makefile b/drivers/net/dsa/microchip/Makefile
index 929caa81e782ed2..2a03b21a3386f5d 100644
--- a/drivers/net/dsa/microchip/Makefile
+++ b/drivers/net/dsa/microchip/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ9477_I2C)	+= ksz9477_i2c.o
 obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ9477_SPI)	+= ksz9477_spi.o
 obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ8795)		+= ksz8795.o
 obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ8795_SPI)	+= ksz8795_spi.o
+obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ8863_SMI)	+= ksz8863_smi.o
diff --git a/drivers/net/dsa/microchip/ksz8863_smi.c b/drivers/net/dsa/microchip/ksz8863_smi.c
new file mode 100644
index 000000000000000..fd493441d725284
--- /dev/null
+++ b/drivers/net/dsa/microchip/ksz8863_smi.c
@@ -0,0 +1,204 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Microchip KSZ8863 series register access through SMI
+ *
+ * Copyright (C) 2019 Pengutronix, Michael Grzeschik <kernel@pengutronix.de>
+ */
+
+#include "ksz8.h"
+#include "ksz_common.h"
+
+/* Serial Management Interface (SMI) uses the following frame format:
+ *
+ *       preamble|start|Read/Write|  PHY   |  REG  |TA|   Data bits      | Idle
+ *               |frame| OP code  |address |address|  |                  |
+ * read | 32x1´s | 01  |    00    | 1xRRR  | RRRRR |Z0| 00000000DDDDDDDD |  Z
+ * write| 32x1´s | 01  |    00    | 0xRRR  | RRRRR |10| xxxxxxxxDDDDDDDD |  Z
+ *
+ */
+
+static int ksz8863_mdio_read(void *ctx, const void *reg_buf, size_t reg_len,
+			     void *val_buf, size_t val_len)
+{
+	struct ksz_device *dev = (struct ksz_device *)ctx;
+	struct ksz8 *ksz8 = dev->priv;
+	struct mdio_device *mdev = ksz8->priv;
+	u8 reg = *(u8 *)reg_buf;
+	u8 *val = val_buf;
+	int ret = 0;
+	int i;
+
+	mutex_lock_nested(&mdev->bus->mdio_lock, MDIO_MUTEX_NESTED);
+	for (i = 0; i < val_len; i++) {
+		int tmp = reg + i;
+
+		ret = __mdiobus_read(mdev->bus, ((tmp & 0xE0) >> 5) |
+				     BIT(4), tmp);
+		if (ret < 0)
+			goto out;
+
+		val[i] = ret;
+	}
+	ret = 0;
+
+ out:
+	mutex_unlock(&mdev->bus->mdio_lock);
+
+	return ret;
+}
+
+static int ksz8863_mdio_write(void *ctx, const void *data, size_t count)
+{
+	struct ksz_device *dev = (struct ksz_device *)ctx;
+	struct ksz8 *ksz8 = dev->priv;
+	struct mdio_device *mdev = ksz8->priv;
+	u8 *val = (u8 *)(data + 4);
+	u32 reg = *(u32 *)data;
+	int ret = 0;
+	int i;
+
+	mutex_lock_nested(&mdev->bus->mdio_lock, MDIO_MUTEX_NESTED);
+	for (i = 0; i < (count - 4); i++) {
+		int tmp = reg + i;
+
+		ret = __mdiobus_write(mdev->bus, ((tmp & 0xE0) >> 5),
+				      tmp, val[i]);
+		if (ret < 0)
+			goto out;
+	}
+
+ out:
+	mutex_unlock(&mdev->bus->mdio_lock);
+
+	return ret;
+}
+
+static const struct regmap_bus regmap_smi[] = {
+	{
+		.read = ksz8863_mdio_read,
+		.write = ksz8863_mdio_write,
+		.max_raw_read = 1,
+		.max_raw_write = 1,
+	},
+	{
+		.read = ksz8863_mdio_read,
+		.write = ksz8863_mdio_write,
+		.val_format_endian_default = REGMAP_ENDIAN_BIG,
+		.max_raw_read = 2,
+		.max_raw_write = 2,
+	},
+	{
+		.read = ksz8863_mdio_read,
+		.write = ksz8863_mdio_write,
+		.val_format_endian_default = REGMAP_ENDIAN_BIG,
+		.max_raw_read = 4,
+		.max_raw_write = 4,
+	}
+};
+
+static const struct regmap_config ksz8863_regmap_config[] = {
+	{
+		.name = "#8",
+		.reg_bits = 8,
+		.pad_bits = 24,
+		.val_bits = 8,
+		.cache_type = REGCACHE_NONE,
+		.use_single_read = 1,
+		.lock = ksz_regmap_lock,
+		.unlock = ksz_regmap_unlock,
+	},
+	{
+		.name = "#16",
+		.reg_bits = 8,
+		.pad_bits = 24,
+		.val_bits = 16,
+		.cache_type = REGCACHE_NONE,
+		.use_single_read = 1,
+		.lock = ksz_regmap_lock,
+		.unlock = ksz_regmap_unlock,
+	},
+	{
+		.name = "#32",
+		.reg_bits = 8,
+		.pad_bits = 24,
+		.val_bits = 32,
+		.cache_type = REGCACHE_NONE,
+		.use_single_read = 1,
+		.lock = ksz_regmap_lock,
+		.unlock = ksz_regmap_unlock,
+	}
+};
+
+static int ksz8863_smi_probe(struct mdio_device *mdiodev)
+{
+	struct regmap_config rc;
+	struct ksz_device *dev;
+	struct ksz8 *ksz8;
+	int ret;
+	int i;
+
+	ksz8 = devm_kzalloc(&mdiodev->dev, sizeof(struct ksz8), GFP_KERNEL);
+	ksz8->priv = mdiodev;
+
+	dev = ksz_switch_alloc(&mdiodev->dev, ksz8);
+	if (!dev)
+		return -EINVAL;
+
+	for (i = 0; i < ARRAY_SIZE(ksz8863_regmap_config); i++) {
+		rc = ksz8863_regmap_config[i];
+		rc.lock_arg = &dev->regmap_mutex;
+		dev->regmap[i] = devm_regmap_init(&mdiodev->dev,
+						  &regmap_smi[i], dev,
+						  &rc);
+		if (IS_ERR(dev->regmap[i])) {
+			ret = PTR_ERR(dev->regmap[i]);
+			dev_err(&mdiodev->dev,
+				"Failed to initialize regmap%i: %d\n",
+				ksz8863_regmap_config[i].val_bits, ret);
+			return ret;
+		}
+	}
+
+	if (mdiodev->dev.platform_data)
+		dev->pdata = mdiodev->dev.platform_data;
+
+	ret = ksz8_switch_register(dev);
+
+	/* Main DSA driver may not be started yet. */
+	if (ret)
+		return ret;
+
+	dev_set_drvdata(&mdiodev->dev, dev);
+
+	return 0;
+}
+
+static void ksz8863_smi_remove(struct mdio_device *mdiodev)
+{
+	struct ksz_device *dev = dev_get_drvdata(&mdiodev->dev);
+
+	if (dev)
+		ksz_switch_remove(dev);
+}
+
+static const struct of_device_id ksz8863_dt_ids[] = {
+	{ .compatible = "microchip,ksz8863" },
+	{ .compatible = "microchip,ksz8873" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, ksz8863_dt_ids);
+
+static struct mdio_driver ksz8863_driver = {
+	.probe	= ksz8863_smi_probe,
+	.remove	= ksz8863_smi_remove,
+	.mdiodrv.driver = {
+		.name	= "ksz8863-switch",
+		.of_match_table = ksz8863_dt_ids,
+	},
+};
+
+mdio_module_driver(ksz8863_driver);
+
+MODULE_AUTHOR("Michael Grzeschik <m.grzeschik@pengutronix.de>");
+MODULE_DESCRIPTION("Microchip KSZ8863 SMI Switch driver");
+MODULE_LICENSE("GPL v2");
-- 
2.28.0


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

* [PATCH v4 10/11] net: dsa: microchip: Add Microchip KSZ8863 SPI based driver support
  2020-08-03  5:44 [PATCH v4 00/11] microchip: add support for ksz88x3 driver family Michael Grzeschik
                   ` (8 preceding siblings ...)
  2020-08-03  5:44 ` [PATCH v4 09/11] net: dsa: microchip: Add Microchip KSZ8863 SMI based driver support Michael Grzeschik
@ 2020-08-03  5:44 ` Michael Grzeschik
  2020-08-03 18:14   ` Florian Fainelli
  2020-08-03  5:44 ` [PATCH v4 11/11] dt-bindings: net: dsa: document additional Microchip KSZ8863/8873 switch Michael Grzeschik
  2020-09-10 11:41 ` [PATCH v4 00/11] microchip: add support for ksz88x3 driver family Matthias Schiffer
  11 siblings, 1 reply; 23+ messages in thread
From: Michael Grzeschik @ 2020-08-03  5:44 UTC (permalink / raw)
  To: andrew; +Cc: netdev, f.fainelli, davem, kernel

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

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

 drivers/net/dsa/microchip/ksz8795_spi.c | 62 ++++++++++++++++++-------
 1 file changed, 45 insertions(+), 17 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz8795_spi.c b/drivers/net/dsa/microchip/ksz8795_spi.c
index 3bab09c46f6a7bd..d13a83c27428cdc 100644
--- a/drivers/net/dsa/microchip/ksz8795_spi.c
+++ b/drivers/net/dsa/microchip/ksz8795_spi.c
@@ -14,34 +14,70 @@
 #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 const struct of_device_id ksz8795_dt_ids[] = {
+	{ .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);
 
 static int ksz8795_spi_probe(struct spi_device *spi)
 {
+	const struct regmap_config *regmap_config;
+	const struct of_device_id *match;
+	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 = ksz8795_regmap_config;
+
+	if (ddev->of_node) {
+		match = of_match_node(ksz8795_dt_ids, ddev->of_node);
+		if (!match)
+			return -ENOTSUPP;
+
+		if (match->data)
+			regmap_config = match->data;
+	}
+
 	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;
 		}
 	}
@@ -78,14 +114,6 @@ static void ksz8795_spi_shutdown(struct spi_device *spi)
 		dev->dev_ops->shutdown(dev);
 }
 
-static const struct of_device_id ksz8795_dt_ids[] = {
-	{ .compatible = "microchip,ksz8765" },
-	{ .compatible = "microchip,ksz8794" },
-	{ .compatible = "microchip,ksz8795" },
-	{},
-};
-MODULE_DEVICE_TABLE(of, ksz8795_dt_ids);
-
 static struct spi_driver ksz8795_spi_driver = {
 	.driver = {
 		.name	= "ksz8795-switch",
-- 
2.28.0


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

* [PATCH v4 11/11] dt-bindings: net: dsa: document additional Microchip KSZ8863/8873 switch
  2020-08-03  5:44 [PATCH v4 00/11] microchip: add support for ksz88x3 driver family Michael Grzeschik
                   ` (9 preceding siblings ...)
  2020-08-03  5:44 ` [PATCH v4 10/11] net: dsa: microchip: Add Microchip KSZ8863 SPI " Michael Grzeschik
@ 2020-08-03  5:44 ` Michael Grzeschik
  2020-08-03 17:41   ` Florian Fainelli
  2020-09-10 11:41 ` [PATCH v4 00/11] microchip: add support for ksz88x3 driver family Matthias Schiffer
  11 siblings, 1 reply; 23+ messages in thread
From: Michael Grzeschik @ 2020-08-03  5:44 UTC (permalink / raw)
  To: andrew; +Cc: netdev, f.fainelli, davem, kernel, 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>
Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>

---
v1 -> v3: - nothing changes
          - already Acked-by Rob Herring
v1 -> v4: - nothing changes

 Documentation/devicetree/bindings/net/dsa/ksz.txt | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/dsa/ksz.txt b/Documentation/devicetree/bindings/net/dsa/ksz.txt
index 95e91e84151c339..a5d71862f53cbcd 100644
--- a/Documentation/devicetree/bindings/net/dsa/ksz.txt
+++ b/Documentation/devicetree/bindings/net/dsa/ksz.txt
@@ -8,6 +8,8 @@ Required properties:
   - "microchip,ksz8765"
   - "microchip,ksz8794"
   - "microchip,ksz8795"
+  - "microchip,ksz8863"
+  - "microchip,ksz8873"
   - "microchip,ksz9477"
   - "microchip,ksz9897"
   - "microchip,ksz9896"
-- 
2.28.0


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

* Re: [PATCH v4 09/11] net: dsa: microchip: Add Microchip KSZ8863 SMI based driver support
  2020-08-03  5:44 ` [PATCH v4 09/11] net: dsa: microchip: Add Microchip KSZ8863 SMI based driver support Michael Grzeschik
@ 2020-08-03 13:31   ` Randy Dunlap
  2020-08-03 18:12   ` Florian Fainelli
  2020-09-10 11:44   ` Matthias Schiffer
  2 siblings, 0 replies; 23+ messages in thread
From: Randy Dunlap @ 2020-08-03 13:31 UTC (permalink / raw)
  To: Michael Grzeschik, andrew; +Cc: netdev, f.fainelli, davem, kernel

On 8/2/20 10:44 PM, Michael Grzeschik wrote:
> diff --git a/drivers/net/dsa/microchip/Kconfig b/drivers/net/dsa/microchip/Kconfig
> index 4ec6a47b7f7284f..c5819bd4121cc7c 100644
> --- a/drivers/net/dsa/microchip/Kconfig
> +++ b/drivers/net/dsa/microchip/Kconfig
> @@ -40,3 +40,12 @@ config NET_DSA_MICROCHIP_KSZ8795_SPI
>  
>  	  It is required to use the KSZ8795 switch driver as the only access
>  	  is through SPI.
> +
> +config NET_DSA_MICROCHIP_KSZ8863_SMI
> +	tristate "KSZ series SMI connected switch driver"
> +	depends on NET_DSA_MICROCHIP_KSZ8795
> +	select MDIO_BITBANG
> +	default y

huh? why?

> +	help
> +	  Select to enable support for registering switches configured through
> +	  Microchip SMI. It Supports the KSZ8863 and KSZ8873 Switch.

	                    supports                         switch.


-- 
~Randy


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

* Re: [PATCH v4 06/11] net: dsa: microchip: ksz8795: change drivers prefix to be generic
  2020-08-03  5:44 ` [PATCH v4 06/11] net: dsa: microchip: ksz8795: change drivers prefix to be generic Michael Grzeschik
@ 2020-08-03 15:42   ` Jakub Kicinski
  0 siblings, 0 replies; 23+ messages in thread
From: Jakub Kicinski @ 2020-08-03 15:42 UTC (permalink / raw)
  To: Michael Grzeschik; +Cc: andrew, netdev, f.fainelli, davem, kernel

On Mon,  3 Aug 2020 07:44:37 +0200 Michael Grzeschik wrote:
> 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>

allmodconfig:

../drivers/net/dsa/microchip/ksz8795.c:415:41: error: using member 'shifts' in incomplete struct ksz8
../drivers/net/dsa/microchip/ksz8795.c:802:46: warning: incorrect type in argument 3 (different type sizes)
../drivers/net/dsa/microchip/ksz8795.c:802:46:    expected unsigned int [usertype] *vlan
../drivers/net/dsa/microchip/ksz8795.c:802:46:    got unsigned short *
../drivers/net/dsa/microchip/ksz8795.c:843:46: warning: incorrect type in argument 3 (different type sizes)
../drivers/net/dsa/microchip/ksz8795.c:843:46:    expected unsigned int [usertype] *vlan
../drivers/net/dsa/microchip/ksz8795.c:843:46:    got unsigned short *
../drivers/net/dsa/microchip/ksz8795.c: In function ‘ksz8_r_vlan_entries’:
../drivers/net/dsa/microchip/ksz8795.c:415:34: error: invalid use of undefined type ‘struct ksz8’
  415 |  struct ksz_shifts *shifts = ksz8->shifts;
      |                                  ^~
../drivers/net/dsa/microchip/ksz8795.c:415:21: warning: unused variable ‘shifts’ [-Wunused-variable]
  415 |  struct ksz_shifts *shifts = ksz8->shifts;
      |                     ^~~~~~
../drivers/net/dsa/microchip/ksz8795.c: In function ‘ksz8_port_vlan_add’:
../drivers/net/dsa/microchip/ksz8795.c:802:31: error: passing argument 3 of ‘ksz8_r_vlan_table’ from incompatible pointer type [-Werror=incompatible-pointer-types]
  802 |   ksz8_r_vlan_table(dev, vid, &data);
      |                               ^~~~~
      |                               |
      |                               u16 * {aka short unsigned int *}
../drivers/net/dsa/microchip/ksz8795.c:427:69: note: expected ‘u32 *’ {aka ‘unsigned int *’} but argument is of type ‘u16 *’ {aka ‘short unsigned int *’}
  427 | static void ksz8_r_vlan_table(struct ksz_device *dev, u16 vid, u32 *vlan)
      |                                                                ~~~~~^~~~
../drivers/net/dsa/microchip/ksz8795.c: In function ‘ksz8_port_vlan_del’:
../drivers/net/dsa/microchip/ksz8795.c:843:31: error: passing argument 3 of ‘ksz8_r_vlan_table’ from incompatible pointer type [-Werror=incompatible-pointer-types]
  843 |   ksz8_r_vlan_table(dev, vid, &data);
      |                               ^~~~~
      |                               |
      |                               u16 * {aka short unsigned int *}
../drivers/net/dsa/microchip/ksz8795.c:427:69: note: expected ‘u32 *’ {aka ‘unsigned int *’} but argument is of type ‘u16 *’ {aka ‘short unsigned int *’}
  427 | static void ksz8_r_vlan_table(struct ksz_device *dev, u16 vid, u32 *vlan)
      |                                                                ~~~~~^~~~
cc1: some warnings being treated as errors
make[5]: *** [../scripts/Makefile.build:281: drivers/net/dsa/microchip/ksz8795.o] Error 1
make[5]: *** Waiting for unfinished jobs....
make[4]: *** [../scripts/Makefile.build:497: drivers/net/dsa/microchip] Error 2
make[3]: *** [../scripts/Makefile.build:497: drivers/net/dsa] Error 2
make[3]: *** Waiting for unfinished jobs....
make[2]: *** [../scripts/Makefile.build:497: drivers/net] Error 2
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [/netdev/net-next/Makefile:1771: drivers] Error 2

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

* Re: [PATCH v4 01/11] net: phy: Add support for microchip SMI0 MDIO bus
  2020-08-03  5:44 ` [PATCH v4 01/11] net: phy: Add support for microchip SMI0 MDIO bus Michael Grzeschik
@ 2020-08-03 17:38   ` Florian Fainelli
  0 siblings, 0 replies; 23+ messages in thread
From: Florian Fainelli @ 2020-08-03 17:38 UTC (permalink / raw)
  To: Michael Grzeschik, andrew; +Cc: netdev, davem, kernel



On 8/2/2020 10:44 PM, Michael Grzeschik wrote:
> From: Andrew Lunn <andrew@lunn.ch>
> 
> SMI0 is a mangled version of MDIO. The main low level difference is
> the MDIO C22 OP code is always 0, not 0x2 or 0x1 for Read/Write. The
> read/write information is instead encoded in the PHY address.
> 
> Extend the bit-bang code to allow the op code to be overridden, but
> default to normal C22 values. Add an extra compatible to the mdio-gpio
> driver, and when this compatible is present, set the op codes to 0.
> 
> A higher level driver, sitting on top of the basic MDIO bus driver can
> then implement the rest of the microchip SMI0 odderties.
> 
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>
> Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
> 
> ---

[snip]

> diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c
> index 1b00235d7dc5b56..e8d83cee1bc17e1 100644
> --- a/drivers/net/phy/mdio-gpio.c
> +++ b/drivers/net/phy/mdio-gpio.c
> @@ -132,6 +132,14 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev,
>  		new_bus->phy_ignore_ta_mask = pdata->phy_ignore_ta_mask;
>  	}
>  
> +	if (dev->of_node &&
> +	    of_device_is_compatible(dev->of_node, "microchip,mdio-smi0")) {
> +		bitbang->ctrl.op_c22_read = 0;
> +		bitbang->ctrl.op_c22_write = 0;
> +	} else {
> +		bitbang->ctrl.override_op_c22 = 1;

Do not you have the logic reversed here? You meant to set
ctrl.override_op_c22 to 1 *if* your compatibility string is
microchip,mdio-smi0 to indicate the use of non-standard clause 22 read
and write opcodes?
-- 
Florian

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

* Re: [PATCH v4 04/11] net: dsa: microchip: ksz8795: use port_cnt where possible
  2020-08-03  5:44 ` [PATCH v4 04/11] net: dsa: microchip: ksz8795: use port_cnt where possible Michael Grzeschik
@ 2020-08-03 17:40   ` Florian Fainelli
  0 siblings, 0 replies; 23+ messages in thread
From: Florian Fainelli @ 2020-08-03 17:40 UTC (permalink / raw)
  To: Michael Grzeschik, andrew; +Cc: netdev, davem, kernel



On 8/2/2020 10:44 PM, Michael Grzeschik wrote:
> Since the driver can be used on more switches it needs
> to use flexible port count whereever possible.
> 
> Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>

Since you appear to have access to a dsa_switch instance in most cases,
maybe consider using ds->num_ports directly? Not necessarily a big deal
and the current change is an improvement anyway.

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-- 
Florian

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

* Re: [PATCH v4 05/11] net: dsa: microchip: ksz8795: dynamic allocate memory for flush_dyn_mac_table
  2020-08-03  5:44 ` [PATCH v4 05/11] net: dsa: microchip: ksz8795: dynamic allocate memory for flush_dyn_mac_table Michael Grzeschik
@ 2020-08-03 17:40   ` Florian Fainelli
  0 siblings, 0 replies; 23+ messages in thread
From: Florian Fainelli @ 2020-08-03 17:40 UTC (permalink / raw)
  To: Michael Grzeschik, andrew; +Cc: netdev, davem, kernel



On 8/2/2020 10:44 PM, Michael Grzeschik wrote:
> To get the driver working with other chips using different port counts
> the dyn_mac_table should be flushed depending on the amount of physical
> ports.
> 
> Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
> 
> ---
> v1 -> v4: - extracted this change from bigger previous patch
> 
>  drivers/net/dsa/microchip/ksz8795.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c
> index 947ea1e45f5b2c6..ba722f730bf0f7b 100644
> --- a/drivers/net/dsa/microchip/ksz8795.c
> +++ b/drivers/net/dsa/microchip/ksz8795.c
> @@ -750,11 +750,11 @@ static void ksz8795_port_stp_state_set(struct dsa_switch *ds, int port,
>  
>  static void ksz8795_flush_dyn_mac_table(struct ksz_device *dev, int port)
>  {
> -	u8 learn[TOTAL_PORT_NUM];
> +	u8 *learn = kzalloc(dev->mib_port_cnt, GFP_KERNEL);

There is no error checking on this allocation, and you could consider
propagating an allocation failure back to the caller for graceful handling.
-- 
Florian

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

* Re: [PATCH v4 11/11] dt-bindings: net: dsa: document additional Microchip KSZ8863/8873 switch
  2020-08-03  5:44 ` [PATCH v4 11/11] dt-bindings: net: dsa: document additional Microchip KSZ8863/8873 switch Michael Grzeschik
@ 2020-08-03 17:41   ` Florian Fainelli
  0 siblings, 0 replies; 23+ messages in thread
From: Florian Fainelli @ 2020-08-03 17:41 UTC (permalink / raw)
  To: Michael Grzeschik, andrew; +Cc: netdev, davem, kernel, devicetree, Rob Herring



On 8/2/2020 10:44 PM, Michael Grzeschik wrote:
> 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>
> Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-- 
Florian

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

* Re: [PATCH v4 09/11] net: dsa: microchip: Add Microchip KSZ8863 SMI based driver support
  2020-08-03  5:44 ` [PATCH v4 09/11] net: dsa: microchip: Add Microchip KSZ8863 SMI based driver support Michael Grzeschik
  2020-08-03 13:31   ` Randy Dunlap
@ 2020-08-03 18:12   ` Florian Fainelli
  2020-09-10 11:44   ` Matthias Schiffer
  2 siblings, 0 replies; 23+ messages in thread
From: Florian Fainelli @ 2020-08-03 18:12 UTC (permalink / raw)
  To: Michael Grzeschik, andrew; +Cc: netdev, davem, kernel



On 8/2/2020 10:44 PM, Michael Grzeschik wrote:
> Add KSZ88X3 driver support. We add support for the KXZ88X3 three port
> switches using the Microchip SMI Interface. They are supported using the
> MDIO-Bitbang Interface.
> 
> Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
> 

[snip

> +
> +config NET_DSA_MICROCHIP_KSZ8863_SMI
> +	tristate "KSZ series SMI connected switch driver"
> +	depends on NET_DSA_MICROCHIP_KSZ8795
> +	select MDIO_BITBANG
> +	default y

As Randy already identified please remove this.

> +	help
> +	  Select to enable support for registering switches configured through
> +	  Microchip SMI. It Supports the KSZ8863 and KSZ8873 Switch.
> diff --git a/drivers/net/dsa/microchip/Makefile b/drivers/net/dsa/microchip/Makefile
> index 929caa81e782ed2..2a03b21a3386f5d 100644
> --- a/drivers/net/dsa/microchip/Makefile
> +++ b/drivers/net/dsa/microchip/Makefile
> @@ -5,3 +5,4 @@ obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ9477_I2C)	+= ksz9477_i2c.o
>  obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ9477_SPI)	+= ksz9477_spi.o
>  obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ8795)		+= ksz8795.o
>  obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ8795_SPI)	+= ksz8795_spi.o
> +obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ8863_SMI)	+= ksz8863_smi.o
> diff --git a/drivers/net/dsa/microchip/ksz8863_smi.c b/drivers/net/dsa/microchip/ksz8863_smi.c
> new file mode 100644
> index 000000000000000..fd493441d725284
> --- /dev/null
> +++ b/drivers/net/dsa/microchip/ksz8863_smi.c
> @@ -0,0 +1,204 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Microchip KSZ8863 series register access through SMI
> + *
> + * Copyright (C) 2019 Pengutronix, Michael Grzeschik <kernel@pengutronix.de>
> + */
> +
> +#include "ksz8.h"
> +#include "ksz_common.h"
> +
> +/* Serial Management Interface (SMI) uses the following frame format:
> + *
> + *       preamble|start|Read/Write|  PHY   |  REG  |TA|   Data bits      | Idle
> + *               |frame| OP code  |address |address|  |                  |
> + * read | 32x1´s | 01  |    00    | 1xRRR  | RRRRR |Z0| 00000000DDDDDDDD |  Z
> + * write| 32x1´s | 01  |    00    | 0xRRR  | RRRRR |10| xxxxxxxxDDDDDDDD |  Z
> + *
> + */
> +
> +static int ksz8863_mdio_read(void *ctx, const void *reg_buf, size_t reg_len,
> +			     void *val_buf, size_t val_len)
> +{
> +	struct ksz_device *dev = (struct ksz_device *)ctx;

There is no need to cast a void pointer, can you also make it a const
void *ctx?

> +	struct ksz8 *ksz8 = dev->priv;
> +	struct mdio_device *mdev = ksz8->priv;
> +	u8 reg = *(u8 *)reg_buf;
> +	u8 *val = val_buf;
> +	int ret = 0;
> +	int i;
> +
> +	mutex_lock_nested(&mdev->bus->mdio_lock, MDIO_MUTEX_NESTED);
> +	for (i = 0; i < val_len; i++) {
> +		int tmp = reg + i;

Humm, how does this work for reg_len >1 with reg being a scalar? Why not
just use reg[i]?

> +
> +		ret = __mdiobus_read(mdev->bus, ((tmp & 0xE0) >> 5) |
> +				     BIT(4), tmp);

Can we provide defines instead of these numbers?

> +		if (ret < 0)
> +			goto out;
> +
> +		val[i] = ret;
> +	}
> +	ret = 0;
> +
> + out:
> +	mutex_unlock(&mdev->bus->mdio_lock);
> +
> +	return ret;
> +}
> +
> +static int ksz8863_mdio_write(void *ctx, const void *data, size_t count)
> +{
> +	struct ksz_device *dev = (struct ksz_device *)ctx;

Likewise, no need to cast here.

> +	struct ksz8 *ksz8 = dev->priv;
> +	struct mdio_device *mdev = ksz8->priv;
> +	u8 *val = (u8 *)(data + 4);
> +	u32 reg = *(u32 *)data;

Humm, are you positive this works for all endian configurations?
-- 
Florian

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

* Re: [PATCH v4 10/11] net: dsa: microchip: Add Microchip KSZ8863 SPI based driver support
  2020-08-03  5:44 ` [PATCH v4 10/11] net: dsa: microchip: Add Microchip KSZ8863 SPI " Michael Grzeschik
@ 2020-08-03 18:14   ` Florian Fainelli
  0 siblings, 0 replies; 23+ messages in thread
From: Florian Fainelli @ 2020-08-03 18:14 UTC (permalink / raw)
  To: Michael Grzeschik, andrew; +Cc: netdev, davem, kernel



On 8/2/2020 10:44 PM, Michael Grzeschik wrote:
> Add KSZ88X3 driver support. We add support for the KXZ88X3 three port
> switches using the SPI Interface.
> 
> 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
> 
>  drivers/net/dsa/microchip/ksz8795_spi.c | 62 ++++++++++++++++++-------
>  1 file changed, 45 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/net/dsa/microchip/ksz8795_spi.c b/drivers/net/dsa/microchip/ksz8795_spi.c
> index 3bab09c46f6a7bd..d13a83c27428cdc 100644
> --- a/drivers/net/dsa/microchip/ksz8795_spi.c
> +++ b/drivers/net/dsa/microchip/ksz8795_spi.c
> @@ -14,34 +14,70 @@
>  #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);

You could fancy a macro that does all of the above, and takes a name and
a model as argument, up to you.

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-- 
Florian

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

* Re: [PATCH v4 07/11] net: dsa: microchip: ksz8795: move register offsets and shifts to separate struct
  2020-08-03  5:44 ` [PATCH v4 07/11] net: dsa: microchip: ksz8795: move register offsets and shifts to separate struct Michael Grzeschik
@ 2020-08-03 18:21   ` Florian Fainelli
  0 siblings, 0 replies; 23+ messages in thread
From: Florian Fainelli @ 2020-08-03 18:21 UTC (permalink / raw)
  To: Michael Grzeschik, andrew; +Cc: netdev, davem, kernel



On 8/2/2020 10:44 PM, Michael Grzeschik 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>
> 
> ---

[snip]

> +
> +struct ksz_regs {
> +	int ind_ctrl_0;
> +	int ind_data_8;
> +	int ind_data_check;
> +	int ind_data_hi;
> +	int ind_data_lo;
> +	int ind_mib_check;
> +	int p_force_ctrl;
> +	int p_link_status;
> +	int p_local_ctrl;
> +	int p_neg_restart_ctrl;
> +	int p_remote_status;
> +	int p_speed_status;
> +	int s_tail_tag_ctrl;
> +};

It might make more sense to define an array of registers that is indexed
by an enum token, and the array type be say, u16, such that the compiler
can tell you if you exceed what the type can represent. Then all of your
conversion looks a little more trivial to review and look like that:

-	ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr);
+	ksz_write16(dev, dev->regs[REG_IND_CTRL_0], ctrl_addr);

is more readable and easier to review IMHO.

All of your masks and shifts should also use unsigned types since they
are unsigned by definition.
-- 
Florian

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

* Re: [PATCH v4 00/11] microchip: add support for ksz88x3 driver family
  2020-08-03  5:44 [PATCH v4 00/11] microchip: add support for ksz88x3 driver family Michael Grzeschik
                   ` (10 preceding siblings ...)
  2020-08-03  5:44 ` [PATCH v4 11/11] dt-bindings: net: dsa: document additional Microchip KSZ8863/8873 switch Michael Grzeschik
@ 2020-09-10 11:41 ` Matthias Schiffer
  11 siblings, 0 replies; 23+ messages in thread
From: Matthias Schiffer @ 2020-09-10 11:41 UTC (permalink / raw)
  To: Michael Grzeschik; +Cc: netdev, f.fainelli, davem, kernel, andrew

On Mon, 2020-08-03 at 07:44 +0200, Michael Grzeschik wrote:
> 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.
> 
> Andrew Lunn (1):
>   net: phy: Add support for microchip SMI0 MDIO bus
> 
> Michael Grzeschik (10):
>   dt-bindings: net: mdio-gpio: add compatible for microchip,mdio-smi0
>   net: tag: ksz: Add KSZ8863 tag code
>   net: dsa: microchip: ksz8795: use port_cnt where possible
>   net: dsa: microchip: ksz8795: dynamic allocate memory for
>     flush_dyn_mac_table
>   net: dsa: microchip: ksz8795: change drivers prefix to be generic
>   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 SMI based driver support
>   net: dsa: microchip: Add Microchip KSZ8863 SPI based driver support
>   dt-bindings: net: dsa: document additional Microchip KSZ8863/8873
>     switch
> 
>  .../devicetree/bindings/net/dsa/ksz.txt       |   2 +
>  .../devicetree/bindings/net/mdio-gpio.txt     |   1 +
>  drivers/net/dsa/microchip/Kconfig             |   9 +
>  drivers/net/dsa/microchip/Makefile            |   1 +
>  drivers/net/dsa/microchip/ksz8.h              |  68 ++
>  drivers/net/dsa/microchip/ksz8795.c           | 926 ++++++++++++--
> ----
>  drivers/net/dsa/microchip/ksz8795_reg.h       | 214 ++--
>  drivers/net/dsa/microchip/ksz8795_spi.c       |  64 +-
>  drivers/net/dsa/microchip/ksz8863_reg.h       | 124 +++
>  drivers/net/dsa/microchip/ksz8863_smi.c       | 204 ++++
>  drivers/net/dsa/microchip/ksz_common.h        |   2 +-
>  drivers/net/phy/mdio-bitbang.c                |   8 +-
>  drivers/net/phy/mdio-gpio.c                   |   9 +
>  include/linux/mdio-bitbang.h                  |   3 +
>  include/net/dsa.h                             |   2 +
>  net/dsa/tag_ksz.c                             |  57 ++
>  16 files changed, 1275 insertions(+), 419 deletions(-)
>  create mode 100644 drivers/net/dsa/microchip/ksz8.h
>  create mode 100644 drivers/net/dsa/microchip/ksz8863_reg.h
>  create mode 100644 drivers/net/dsa/microchip/ksz8863_smi.c
> 

Hello Michael,

I've given this series a spin on a TQ-Systems ARM64 board with a
KSZ8863 switch connected via SMI (rebased onto kernel 5.4.y), and
everything seems to work as expected. Feel free to CC me for the next
revision of the series, so I can add my Tested-by.

Kind regards,
Matthias


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

* Re: [PATCH v4 09/11] net: dsa: microchip: Add Microchip KSZ8863 SMI based driver support
  2020-08-03  5:44 ` [PATCH v4 09/11] net: dsa: microchip: Add Microchip KSZ8863 SMI based driver support Michael Grzeschik
  2020-08-03 13:31   ` Randy Dunlap
  2020-08-03 18:12   ` Florian Fainelli
@ 2020-09-10 11:44   ` Matthias Schiffer
  2 siblings, 0 replies; 23+ messages in thread
From: Matthias Schiffer @ 2020-09-10 11:44 UTC (permalink / raw)
  To: Michael Grzeschik; +Cc: netdev, f.fainelli, davem, kernel, andrew

On Mon, 2020-08-03 at 07:44 +0200, Michael Grzeschik wrote:
> Add KSZ88X3 driver support. We add support for the KXZ88X3 three port
> switches using the Microchip SMI Interface. They are supported using
> the
> MDIO-Bitbang Interface.
> 
> Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
> 
> ---
> v1 -> v2:  - this code was part of previuos patch
> v2 -> v3:  - this code was part of previuos patch
> v3 -> v4:  - moved this glue code so separate patch
>            - fixed locking in regmap and mdio_read/mdio_write
> 
>  drivers/net/dsa/microchip/Kconfig       |   9 ++
>  drivers/net/dsa/microchip/Makefile      |   1 +
>  drivers/net/dsa/microchip/ksz8863_smi.c | 204
> ++++++++++++++++++++++++
>  3 files changed, 214 insertions(+)
>  create mode 100644 drivers/net/dsa/microchip/ksz8863_smi.c
> 
> diff --git a/drivers/net/dsa/microchip/Kconfig
> b/drivers/net/dsa/microchip/Kconfig
> index 4ec6a47b7f7284f..c5819bd4121cc7c 100644
> --- a/drivers/net/dsa/microchip/Kconfig
> +++ b/drivers/net/dsa/microchip/Kconfig
> @@ -40,3 +40,12 @@ config NET_DSA_MICROCHIP_KSZ8795_SPI
>  
>  	  It is required to use the KSZ8795 switch driver as the only
> access
>  	  is through SPI.
> +
> +config NET_DSA_MICROCHIP_KSZ8863_SMI
> +	tristate "KSZ series SMI connected switch driver"
> +	depends on NET_DSA_MICROCHIP_KSZ8795

Please also update the label or help text for the
NET_DSA_MICROCHIP_KSZ8795 symbol to include the KSZ88X3, so it's clear
which of the KSZ DSA drivers is the correct one for these switches.



> +	select MDIO_BITBANG
> +	default y
> +	help
> +	  Select to enable support for registering switches configured
> through
> +	  Microchip SMI. It Supports the KSZ8863 and KSZ8873 Switch.
> diff --git a/drivers/net/dsa/microchip/Makefile
> b/drivers/net/dsa/microchip/Makefile
> index 929caa81e782ed2..2a03b21a3386f5d 100644
> --- a/drivers/net/dsa/microchip/Makefile
> +++ b/drivers/net/dsa/microchip/Makefile
> @@ -5,3 +5,4 @@ obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ9477_I2C)	+=
> ksz9477_i2c.o
>  obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ9477_SPI)	+= ksz9477_spi.o
>  obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ8795)		+= ksz8795.o
>  obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ8795_SPI)	+= ksz8795_spi.o
> +obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ8863_SMI)	+= ksz8863_smi.o
> diff --git a/drivers/net/dsa/microchip/ksz8863_smi.c
> b/drivers/net/dsa/microchip/ksz8863_smi.c
> new file mode 100644
> index 000000000000000..fd493441d725284
> --- /dev/null
> +++ b/drivers/net/dsa/microchip/ksz8863_smi.c
> @@ -0,0 +1,204 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Microchip KSZ8863 series register access through SMI
> + *
> + * Copyright (C) 2019 Pengutronix, Michael Grzeschik <
> kernel@pengutronix.de>
> + */
> +
> +#include "ksz8.h"
> +#include "ksz_common.h"
> +
> +/* Serial Management Interface (SMI) uses the following frame
> format:
> + *
> + *       preamble|start|Read/Write|  PHY   |  REG  |TA|   Data
> bits      | Idle
> + *               |frame| OP code  |address
> |address|  |                  |
> + * read | 32x1´s | 01  |    00    | 1xRRR  | RRRRR |Z0|
> 00000000DDDDDDDD |  Z
> + * write| 32x1´s | 01  |    00    | 0xRRR  | RRRRR |10|
> xxxxxxxxDDDDDDDD |  Z
> + *
> + */
> +
> +static int ksz8863_mdio_read(void *ctx, const void *reg_buf, size_t
> reg_len,
> +			     void *val_buf, size_t val_len)
> +{
> +	struct ksz_device *dev = (struct ksz_device *)ctx;
> +	struct ksz8 *ksz8 = dev->priv;
> +	struct mdio_device *mdev = ksz8->priv;
> +	u8 reg = *(u8 *)reg_buf;
> +	u8 *val = val_buf;
> +	int ret = 0;
> +	int i;
> +
> +	mutex_lock_nested(&mdev->bus->mdio_lock, MDIO_MUTEX_NESTED);
> +	for (i = 0; i < val_len; i++) {
> +		int tmp = reg + i;
> +
> +		ret = __mdiobus_read(mdev->bus, ((tmp & 0xE0) >> 5) |
> +				     BIT(4), tmp);
> +		if (ret < 0)
> +			goto out;
> +
> +		val[i] = ret;
> +	}
> +	ret = 0;
> +
> + out:
> +	mutex_unlock(&mdev->bus->mdio_lock);
> +
> +	return ret;
> +}
> +
> +static int ksz8863_mdio_write(void *ctx, const void *data, size_t
> count)
> +{
> +	struct ksz_device *dev = (struct ksz_device *)ctx;
> +	struct ksz8 *ksz8 = dev->priv;
> +	struct mdio_device *mdev = ksz8->priv;
> +	u8 *val = (u8 *)(data + 4);
> +	u32 reg = *(u32 *)data;
> +	int ret = 0;
> +	int i;
> +
> +	mutex_lock_nested(&mdev->bus->mdio_lock, MDIO_MUTEX_NESTED);
> +	for (i = 0; i < (count - 4); i++) {
> +		int tmp = reg + i;
> +
> +		ret = __mdiobus_write(mdev->bus, ((tmp & 0xE0) >> 5),
> +				      tmp, val[i]);
> +		if (ret < 0)
> +			goto out;
> +	}
> +
> + out:
> +	mutex_unlock(&mdev->bus->mdio_lock);
> +
> +	return ret;
> +}
> +
> +static const struct regmap_bus regmap_smi[] = {
> +	{
> +		.read = ksz8863_mdio_read,
> +		.write = ksz8863_mdio_write,
> +		.max_raw_read = 1,
> +		.max_raw_write = 1,
> +	},
> +	{
> +		.read = ksz8863_mdio_read,
> +		.write = ksz8863_mdio_write,
> +		.val_format_endian_default = REGMAP_ENDIAN_BIG,
> +		.max_raw_read = 2,
> +		.max_raw_write = 2,
> +	},
> +	{
> +		.read = ksz8863_mdio_read,
> +		.write = ksz8863_mdio_write,
> +		.val_format_endian_default = REGMAP_ENDIAN_BIG,
> +		.max_raw_read = 4,
> +		.max_raw_write = 4,
> +	}
> +};
> +
> +static const struct regmap_config ksz8863_regmap_config[] = {
> +	{
> +		.name = "#8",
> +		.reg_bits = 8,
> +		.pad_bits = 24,
> +		.val_bits = 8,
> +		.cache_type = REGCACHE_NONE,
> +		.use_single_read = 1,
> +		.lock = ksz_regmap_lock,
> +		.unlock = ksz_regmap_unlock,
> +	},
> +	{
> +		.name = "#16",
> +		.reg_bits = 8,
> +		.pad_bits = 24,
> +		.val_bits = 16,
> +		.cache_type = REGCACHE_NONE,
> +		.use_single_read = 1,
> +		.lock = ksz_regmap_lock,
> +		.unlock = ksz_regmap_unlock,
> +	},
> +	{
> +		.name = "#32",
> +		.reg_bits = 8,
> +		.pad_bits = 24,
> +		.val_bits = 32,
> +		.cache_type = REGCACHE_NONE,
> +		.use_single_read = 1,
> +		.lock = ksz_regmap_lock,
> +		.unlock = ksz_regmap_unlock,
> +	}
> +};
> +
> +static int ksz8863_smi_probe(struct mdio_device *mdiodev)
> +{
> +	struct regmap_config rc;
> +	struct ksz_device *dev;
> +	struct ksz8 *ksz8;
> +	int ret;
> +	int i;
> +
> +	ksz8 = devm_kzalloc(&mdiodev->dev, sizeof(struct ksz8),
> GFP_KERNEL);
> +	ksz8->priv = mdiodev;
> +
> +	dev = ksz_switch_alloc(&mdiodev->dev, ksz8);
> +	if (!dev)
> +		return -EINVAL;
> +
> +	for (i = 0; i < ARRAY_SIZE(ksz8863_regmap_config); i++) {
> +		rc = ksz8863_regmap_config[i];
> +		rc.lock_arg = &dev->regmap_mutex;
> +		dev->regmap[i] = devm_regmap_init(&mdiodev->dev,
> +						  &regmap_smi[i], dev,
> +						  &rc);
> +		if (IS_ERR(dev->regmap[i])) {
> +			ret = PTR_ERR(dev->regmap[i]);
> +			dev_err(&mdiodev->dev,
> +				"Failed to initialize regmap%i: %d\n",
> +				ksz8863_regmap_config[i].val_bits,
> ret);
> +			return ret;
> +		}
> +	}
> +
> +	if (mdiodev->dev.platform_data)
> +		dev->pdata = mdiodev->dev.platform_data;
> +
> +	ret = ksz8_switch_register(dev);
> +
> +	/* Main DSA driver may not be started yet. */
> +	if (ret)
> +		return ret;
> +
> +	dev_set_drvdata(&mdiodev->dev, dev);
> +
> +	return 0;
> +}
> +
> +static void ksz8863_smi_remove(struct mdio_device *mdiodev)
> +{
> +	struct ksz_device *dev = dev_get_drvdata(&mdiodev->dev);
> +
> +	if (dev)
> +		ksz_switch_remove(dev);
> +}
> +
> +static const struct of_device_id ksz8863_dt_ids[] = {
> +	{ .compatible = "microchip,ksz8863" },
> +	{ .compatible = "microchip,ksz8873" },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, ksz8863_dt_ids);
> +
> +static struct mdio_driver ksz8863_driver = {
> +	.probe	= ksz8863_smi_probe,
> +	.remove	= ksz8863_smi_remove,
> +	.mdiodrv.driver = {
> +		.name	= "ksz8863-switch",
> +		.of_match_table = ksz8863_dt_ids,
> +	},
> +};
> +
> +mdio_module_driver(ksz8863_driver);
> +
> +MODULE_AUTHOR("Michael Grzeschik <m.grzeschik@pengutronix.de>");
> +MODULE_DESCRIPTION("Microchip KSZ8863 SMI Switch driver");
> +MODULE_LICENSE("GPL v2");


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

end of thread, other threads:[~2020-09-10 21:57 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-03  5:44 [PATCH v4 00/11] microchip: add support for ksz88x3 driver family Michael Grzeschik
2020-08-03  5:44 ` [PATCH v4 01/11] net: phy: Add support for microchip SMI0 MDIO bus Michael Grzeschik
2020-08-03 17:38   ` Florian Fainelli
2020-08-03  5:44 ` [PATCH v4 02/11] dt-bindings: net: mdio-gpio: add compatible for microchip,mdio-smi0 Michael Grzeschik
2020-08-03  5:44 ` [PATCH v4 03/11] net: tag: ksz: Add KSZ8863 tag code Michael Grzeschik
2020-08-03  5:44 ` [PATCH v4 04/11] net: dsa: microchip: ksz8795: use port_cnt where possible Michael Grzeschik
2020-08-03 17:40   ` Florian Fainelli
2020-08-03  5:44 ` [PATCH v4 05/11] net: dsa: microchip: ksz8795: dynamic allocate memory for flush_dyn_mac_table Michael Grzeschik
2020-08-03 17:40   ` Florian Fainelli
2020-08-03  5:44 ` [PATCH v4 06/11] net: dsa: microchip: ksz8795: change drivers prefix to be generic Michael Grzeschik
2020-08-03 15:42   ` Jakub Kicinski
2020-08-03  5:44 ` [PATCH v4 07/11] net: dsa: microchip: ksz8795: move register offsets and shifts to separate struct Michael Grzeschik
2020-08-03 18:21   ` Florian Fainelli
2020-08-03  5:44 ` [PATCH v4 08/11] net: dsa: microchip: ksz8795: add support for ksz88xx chips Michael Grzeschik
2020-08-03  5:44 ` [PATCH v4 09/11] net: dsa: microchip: Add Microchip KSZ8863 SMI based driver support Michael Grzeschik
2020-08-03 13:31   ` Randy Dunlap
2020-08-03 18:12   ` Florian Fainelli
2020-09-10 11:44   ` Matthias Schiffer
2020-08-03  5:44 ` [PATCH v4 10/11] net: dsa: microchip: Add Microchip KSZ8863 SPI " Michael Grzeschik
2020-08-03 18:14   ` Florian Fainelli
2020-08-03  5:44 ` [PATCH v4 11/11] dt-bindings: net: dsa: document additional Microchip KSZ8863/8873 switch Michael Grzeschik
2020-08-03 17:41   ` Florian Fainelli
2020-09-10 11:41 ` [PATCH v4 00/11] microchip: add support for ksz88x3 driver family Matthias Schiffer

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.