[PATCH 1/3] dt-bindings: net: dsa: ksz: document Microchip KSZ87xx family switches

2019-07-24 Thread Marek Vasut
Document Microchip KSZ87xx family switches. These include
KSZ8765 - 5 port switch
KSZ8794 - 4 port switch
KSZ8795 - 5 port switch

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: David S. Miller 
Cc: Florian Fainelli 
Cc: Rob Herring 
Cc: Tristram Ha 
Cc: Vivien Didelot 
Cc: Woojung Huh 
Cc: devicet...@vger.kernel.org
---
 Documentation/devicetree/bindings/net/dsa/ksz.txt | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/dsa/ksz.txt 
b/Documentation/devicetree/bindings/net/dsa/ksz.txt
index 4ac21cef370e..5e8429b6f9ca 100644
--- a/Documentation/devicetree/bindings/net/dsa/ksz.txt
+++ b/Documentation/devicetree/bindings/net/dsa/ksz.txt
@@ -5,6 +5,9 @@ Required properties:
 
 - compatible: For external switch chips, compatible string must be exactly one
   of the following:
+  - "microchip,ksz8765"
+  - "microchip,ksz8794"
+  - "microchip,ksz8795"
   - "microchip,ksz9477"
   - "microchip,ksz9897"
   - "microchip,ksz9896"
-- 
2.20.1



[PATCH 0/3] net: dsa: ksz: Add Microchip KSZ87xx support

2019-07-24 Thread Marek Vasut
This series adds support for Microchip KSZ87xx switches, which are
slightly simpler compared to KSZ9xxx .

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: David S. Miller 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Vivien Didelot 
Cc: Woojung Huh 

Marek Vasut (1):
  dt-bindings: net: dsa: ksz: document Microchip KSZ87xx family switches

Tristram Ha (2):
  net: dsa: ksz: Add KSZ8795 tag code
  net: dsa: ksz: Add Microchip KSZ8795 DSA driver

 .../devicetree/bindings/net/dsa/ksz.txt   |3 +
 drivers/net/dsa/microchip/Kconfig |   18 +
 drivers/net/dsa/microchip/Makefile|2 +
 drivers/net/dsa/microchip/ksz8795.c   | 1360 +
 drivers/net/dsa/microchip/ksz8795_reg.h   | 1004 
 drivers/net/dsa/microchip/ksz8795_spi.c   |  104 ++
 drivers/net/dsa/microchip/ksz_common.h|   28 +
 drivers/net/dsa/microchip/ksz_priv.h  |1 +
 include/net/dsa.h |2 +
 net/dsa/Kconfig   |7 +
 net/dsa/tag_ksz.c |   62 +
 11 files changed, 2591 insertions(+)
 create mode 100644 drivers/net/dsa/microchip/ksz8795.c
 create mode 100644 drivers/net/dsa/microchip/ksz8795_reg.h
 create mode 100644 drivers/net/dsa/microchip/ksz8795_spi.c

-- 
2.20.1



[PATCH 2/3] net: dsa: ksz: Add KSZ8795 tag code

2019-07-24 Thread Marek Vasut
From: Tristram Ha 

Add DSA tag code for Microchip KSZ8795 switch. The switch is simpler
and the tag is only 1 byte, instead of 2 as is the case with KSZ9477.

Signed-off-by: Tristram Ha 
Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: David S. Miller 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Vivien Didelot 
Cc: Woojung Huh 
---
 include/net/dsa.h |  2 ++
 net/dsa/Kconfig   |  7 ++
 net/dsa/tag_ksz.c | 62 +++
 3 files changed, 71 insertions(+)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 1e8650fa8acc..147b757ef8ea 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -41,6 +41,7 @@ struct phylink_link_state;
 #define DSA_TAG_PROTO_TRAILER_VALUE11
 #define DSA_TAG_PROTO_8021Q_VALUE  12
 #define DSA_TAG_PROTO_SJA1105_VALUE13
+#define DSA_TAG_PROTO_KSZ8795_VALUE14
 
 enum dsa_tag_protocol {
DSA_TAG_PROTO_NONE  = DSA_TAG_PROTO_NONE_VALUE,
@@ -57,6 +58,7 @@ enum dsa_tag_protocol {
DSA_TAG_PROTO_TRAILER   = DSA_TAG_PROTO_TRAILER_VALUE,
DSA_TAG_PROTO_8021Q = DSA_TAG_PROTO_8021Q_VALUE,
DSA_TAG_PROTO_SJA1105   = DSA_TAG_PROTO_SJA1105_VALUE,
+   DSA_TAG_PROTO_KSZ8795   = DSA_TAG_PROTO_KSZ8795_VALUE,
 };
 
 struct packet_type;
diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig
index 6e942dda1bcd..423fa4370608 100644
--- a/net/dsa/Kconfig
+++ b/net/dsa/Kconfig
@@ -77,6 +77,13 @@ config NET_DSA_TAG_KSZ_COMMON
tristate
default n
 
+config NET_DSA_TAG_KSZ8795
+   tristate "Tag driver for Microchip 8795 family of switches"
+   select NET_DSA_TAG_KSZ_COMMON
+   help
+ Say Y if you want to enable support for tagging frames for the
+ Microchip 8795 family of switches.
+
 config NET_DSA_TAG_KSZ
tristate "Tag driver for Microchip 9893 family of switches"
select NET_DSA_TAG_KSZ_COMMON
diff --git a/net/dsa/tag_ksz.c b/net/dsa/tag_ksz.c
index adc6c1e03a4c..dd5ac64b4748 100644
--- a/net/dsa/tag_ksz.c
+++ b/net/dsa/tag_ksz.c
@@ -69,6 +69,67 @@ static struct sk_buff *ksz_common_rcv(struct sk_buff *skb,
return skb;
 }
 
+/*
+ * For Ingress (Host -> KSZ8795), 1 byte is added before FCS.
+ * ---
+ * DA(6bytes)|SA(6bytes)||Data(nbytes)|tag(1byte)|FCS(4bytes)
+ * ---
+ * tag : each bit represents port (eg, 0x01=port1, 0x02=port2, 0x10=port5)
+ *
+ * For Egress (KSZ8795 -> Host), 1 byte is added before FCS.
+ * ---
+ * DA(6bytes)|SA(6bytes)||Data(nbytes)|tag0(1byte)|FCS(4bytes)
+ * ---
+ * tag0 : zero-based value represents port
+ *   (eg, 0x00=port1, 0x02=port3, 0x06=port7)
+ */
+
+#define KSZ8795_INGRESS_TAG_LEN1
+
+#define KSZ8795_TAIL_TAG_OVERRIDE  BIT(6)
+#define KSZ8795_TAIL_TAG_LOOKUPBIT(7)
+
+static struct sk_buff *ksz8795_xmit(struct sk_buff *skb, struct net_device 
*dev)
+{
+   struct dsa_port *dp = dsa_slave_to_port(dev);
+   struct sk_buff *nskb;
+   u8 *tag;
+   u8 *addr;
+
+   nskb = ksz_common_xmit(skb, dev, KSZ8795_INGRESS_TAG_LEN);
+   if (!nskb)
+   return NULL;
+
+   /* Tag encoding */
+   tag = skb_put(nskb, KSZ8795_INGRESS_TAG_LEN);
+   addr = skb_mac_header(nskb);
+
+   *tag = 1 << dp->index;
+   if (is_link_local_ether_addr(addr))
+   *tag |= KSZ8795_TAIL_TAG_OVERRIDE;
+
+   return nskb;
+}
+
+static struct sk_buff *ksz8795_rcv(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *pt)
+{
+   u8 *tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN;
+
+   return ksz_common_rcv(skb, dev, tag[0] & 7, KSZ_EGRESS_TAG_LEN);
+}
+
+static const struct dsa_device_ops ksz8795_netdev_ops = {
+   .name   = "ksz8795",
+   .proto  = DSA_TAG_PROTO_KSZ8795,
+   .xmit   = ksz8795_xmit,
+   .rcv= ksz8795_rcv,
+   .overhead = KSZ8795_INGRESS_TAG_LEN,
+};
+
+DSA_TAG_DRIVER(ksz8795_netdev_ops);
+MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ8795);
+
 /*
  * For Ingress (Host -> KSZ9477), 2 bytes are added before FCS.
  * ---
@@ -183,6 +244,7 @@ DSA_TAG_DRIVER(ksz9893_netdev_ops);
 MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ9893);
 
 static struct dsa_tag_driver *dsa_tag_driver_array[] = {
+   &DSA_TAG_DRIVER_NAME(ksz8795_netdev_ops),
&DSA_TAG_DRIVER_NAME(ksz9477_netdev_ops),
&DSA_TAG_DRIVER_NAME(ksz9893_netdev_ops),
 };
-- 
2.20.1



[PATCH 3/3] net: dsa: ksz: Add Microchip KSZ8795 DSA driver

2019-07-24 Thread Marek Vasut
From: Tristram Ha 

Add Microchip KSZ8795 DSA driver.

Signed-off-by: Tristram Ha 
Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: David S. Miller 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Vivien Didelot 
Cc: Woojung Huh 
---
 drivers/net/dsa/microchip/Kconfig   |   18 +
 drivers/net/dsa/microchip/Makefile  |2 +
 drivers/net/dsa/microchip/ksz8795.c | 1360 +++
 drivers/net/dsa/microchip/ksz8795_reg.h | 1004 +
 drivers/net/dsa/microchip/ksz8795_spi.c |  104 ++
 drivers/net/dsa/microchip/ksz_common.h  |   28 +
 drivers/net/dsa/microchip/ksz_priv.h|1 +
 7 files changed, 2517 insertions(+)
 create mode 100644 drivers/net/dsa/microchip/ksz8795.c
 create mode 100644 drivers/net/dsa/microchip/ksz8795_reg.h
 create mode 100644 drivers/net/dsa/microchip/ksz8795_spi.c

diff --git a/drivers/net/dsa/microchip/Kconfig 
b/drivers/net/dsa/microchip/Kconfig
index fe0a13b79c4b..d990c7128991 100644
--- a/drivers/net/dsa/microchip/Kconfig
+++ b/drivers/net/dsa/microchip/Kconfig
@@ -16,3 +16,21 @@ config NET_DSA_MICROCHIP_KSZ9477_SPI
select REGMAP_SPI
help
  Select to enable support for registering switches configured through 
SPI.
+
+menuconfig NET_DSA_MICROCHIP_KSZ8795
+   tristate "Microchip KSZ8795 series switch support"
+   depends on NET_DSA
+   select NET_DSA_TAG_KSZ8795
+   select NET_DSA_MICROCHIP_KSZ_COMMON
+   help
+ This driver adds support for Microchip KSZ8795 switch chips.
+
+config NET_DSA_MICROCHIP_KSZ8795_SPI
+   tristate "KSZ8795 series SPI connected switch driver"
+   depends on NET_DSA_MICROCHIP_KSZ8795 && SPI
+   select REGMAP_SPI
+   help
+ This driver accesses KSZ8795 chip through SPI.
+
+ It is required to use the KSZ8795 switch driver as the only access
+ is through SPI.
diff --git a/drivers/net/dsa/microchip/Makefile 
b/drivers/net/dsa/microchip/Makefile
index 68451b02f775..e3d799b95d7d 100644
--- a/drivers/net/dsa/microchip/Makefile
+++ b/drivers/net/dsa/microchip/Makefile
@@ -2,3 +2,5 @@
 obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ_COMMON) += ksz_common.o
 obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ9477)+= ksz9477.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
diff --git a/drivers/net/dsa/microchip/ksz8795.c 
b/drivers/net/dsa/microchip/ksz8795.c
new file mode 100644
index ..c26aedf41a5f
--- /dev/null
+++ b/drivers/net/dsa/microchip/ksz8795.c
@@ -0,0 +1,1360 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Microchip KSZ8795 switch driver
+ *
+ * Copyright (C) 2017 Microchip Technology Inc.
+ * Tristram Ha 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "ksz_priv.h"
+#include "ksz_common.h"
+#include "ksz8795_reg.h"
+
+static const struct {
+   char string[ETH_GSTRING_LEN];
+} mib_names[TOTAL_SWITCH_COUNTER_NUM] = {
+   { "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" },
+   { "rx_1523_2000" },
+   { "rx_2001" },
+   { "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_total" },
+   { "tx_total" },
+   { "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);
+}
+
+static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits,
+bool set)
+{
+   regmap_update_bits(dev->regmap[0], PORT_CTRL_ADDR(port, offset),
+  bits, set ? bits : 0);
+}
+
+static int ksz8795_reset_switch(struct ksz_device *dev)
+{
+   /* reset switch */
+   ksz_write8(dev, REG_POWER_MANAGEMENT_

Re: [PATCH 3/3] net: dsa: ksz: Add Microchip KSZ8795 DSA driver

2019-07-25 Thread Marek Vasut
On 7/25/19 4:03 PM, Andrew Lunn wrote:
> On Wed, Jul 24, 2019 at 03:40:48PM +0200, Marek Vasut wrote:
>> From: Tristram Ha 
>> +static void ksz8795_phy_setup(struct ksz_device *dev, int port,
>> +  struct phy_device *phy)
>> +{
>> +if (port < dev->phy_port_cnt) {
>> +/*
>> + * SUPPORTED_Asym_Pause and SUPPORTED_Pause can be removed to
>> + * disable flow control when rate limiting is used.
>> + */
>> +linkmode_copy(phy->advertising, phy->supported);
>> +}
>> +}
> 
> Hi Marek
> 
> Do you know why this is needed?

Unfortunately, no.

It seems it copies supported features of the PHY to advertised features
of the PHY for ports which are downstream (i.e. not the CPU port).


[PATCH V2 0/3] net: dsa: ksz: Add Microchip KSZ87xx support

2019-07-25 Thread Marek Vasut
This series adds support for Microchip KSZ87xx switches, which are
slightly simpler compared to KSZ9xxx .

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: David S. Miller 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Vivien Didelot 
Cc: Woojung Huh 

Marek Vasut (1):
  dt-bindings: net: dsa: ksz: document Microchip KSZ87xx family switches

Tristram Ha (2):
  net: dsa: ksz: Add KSZ8795 tag code
  net: dsa: ksz: Add Microchip KSZ8795 DSA driver

 .../devicetree/bindings/net/dsa/ksz.txt   |3 +
 drivers/net/dsa/microchip/Kconfig |   18 +
 drivers/net/dsa/microchip/Makefile|2 +
 drivers/net/dsa/microchip/ksz8795.c   | 1324 +
 drivers/net/dsa/microchip/ksz8795_reg.h   | 1004 +
 drivers/net/dsa/microchip/ksz8795_spi.c   |  104 ++
 drivers/net/dsa/microchip/ksz_common.h|   28 +
 drivers/net/dsa/microchip/ksz_priv.h  |1 +
 include/net/dsa.h |2 +
 net/dsa/Kconfig   |7 +
 net/dsa/tag_ksz.c |   62 +
 11 files changed, 2555 insertions(+)
 create mode 100644 drivers/net/dsa/microchip/ksz8795.c
 create mode 100644 drivers/net/dsa/microchip/ksz8795_reg.h
 create mode 100644 drivers/net/dsa/microchip/ksz8795_spi.c

-- 
2.20.1



[PATCH V2 1/3] dt-bindings: net: dsa: ksz: document Microchip KSZ87xx family switches

2019-07-25 Thread Marek Vasut
Document Microchip KSZ87xx family switches. These include
KSZ8765 - 5 port switch
KSZ8794 - 4 port switch
KSZ8795 - 5 port switch

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: David S. Miller 
Cc: Florian Fainelli 
Cc: Rob Herring 
Cc: Tristram Ha 
Cc: Vivien Didelot 
Cc: Woojung Huh 
Cc: devicet...@vger.kernel.org
---
V2: No change
---
 Documentation/devicetree/bindings/net/dsa/ksz.txt | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/dsa/ksz.txt 
b/Documentation/devicetree/bindings/net/dsa/ksz.txt
index 4ac21cef370e..5e8429b6f9ca 100644
--- a/Documentation/devicetree/bindings/net/dsa/ksz.txt
+++ b/Documentation/devicetree/bindings/net/dsa/ksz.txt
@@ -5,6 +5,9 @@ Required properties:
 
 - compatible: For external switch chips, compatible string must be exactly one
   of the following:
+  - "microchip,ksz8765"
+  - "microchip,ksz8794"
+  - "microchip,ksz8795"
   - "microchip,ksz9477"
   - "microchip,ksz9897"
   - "microchip,ksz9896"
-- 
2.20.1



[PATCH V2 2/3] net: dsa: ksz: Add KSZ8795 tag code

2019-07-25 Thread Marek Vasut
From: Tristram Ha 

Add DSA tag code for Microchip KSZ8795 switch. The switch is simpler
and the tag is only 1 byte, instead of 2 as is the case with KSZ9477.

Signed-off-by: Tristram Ha 
Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: David S. Miller 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Vivien Didelot 
Cc: Woojung Huh 
---
V2: No change
---
 include/net/dsa.h |  2 ++
 net/dsa/Kconfig   |  7 ++
 net/dsa/tag_ksz.c | 62 +++
 3 files changed, 71 insertions(+)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 1e8650fa8acc..147b757ef8ea 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -41,6 +41,7 @@ struct phylink_link_state;
 #define DSA_TAG_PROTO_TRAILER_VALUE11
 #define DSA_TAG_PROTO_8021Q_VALUE  12
 #define DSA_TAG_PROTO_SJA1105_VALUE13
+#define DSA_TAG_PROTO_KSZ8795_VALUE14
 
 enum dsa_tag_protocol {
DSA_TAG_PROTO_NONE  = DSA_TAG_PROTO_NONE_VALUE,
@@ -57,6 +58,7 @@ enum dsa_tag_protocol {
DSA_TAG_PROTO_TRAILER   = DSA_TAG_PROTO_TRAILER_VALUE,
DSA_TAG_PROTO_8021Q = DSA_TAG_PROTO_8021Q_VALUE,
DSA_TAG_PROTO_SJA1105   = DSA_TAG_PROTO_SJA1105_VALUE,
+   DSA_TAG_PROTO_KSZ8795   = DSA_TAG_PROTO_KSZ8795_VALUE,
 };
 
 struct packet_type;
diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig
index 6e942dda1bcd..423fa4370608 100644
--- a/net/dsa/Kconfig
+++ b/net/dsa/Kconfig
@@ -77,6 +77,13 @@ config NET_DSA_TAG_KSZ_COMMON
tristate
default n
 
+config NET_DSA_TAG_KSZ8795
+   tristate "Tag driver for Microchip 8795 family of switches"
+   select NET_DSA_TAG_KSZ_COMMON
+   help
+ Say Y if you want to enable support for tagging frames for the
+ Microchip 8795 family of switches.
+
 config NET_DSA_TAG_KSZ
tristate "Tag driver for Microchip 9893 family of switches"
select NET_DSA_TAG_KSZ_COMMON
diff --git a/net/dsa/tag_ksz.c b/net/dsa/tag_ksz.c
index adc6c1e03a4c..7af71db91c54 100644
--- a/net/dsa/tag_ksz.c
+++ b/net/dsa/tag_ksz.c
@@ -69,6 +69,67 @@ static struct sk_buff *ksz_common_rcv(struct sk_buff *skb,
return skb;
 }
 
+/*
+ * For Ingress (Host -> KSZ8795), 1 byte is added before FCS.
+ * ---
+ * DA(6bytes)|SA(6bytes)||Data(nbytes)|tag(1byte)|FCS(4bytes)
+ * ---
+ * tag : each bit represents port (eg, 0x01=port1, 0x02=port2, 0x10=port5)
+ *
+ * For Egress (KSZ8795 -> Host), 1 byte is added before FCS.
+ * ---
+ * DA(6bytes)|SA(6bytes)||Data(nbytes)|tag0(1byte)|FCS(4bytes)
+ * ---
+ * tag0 : zero-based value represents port
+ *   (eg, 0x00=port1, 0x02=port3, 0x06=port7)
+ */
+
+#define KSZ8795_INGRESS_TAG_LEN1
+
+#define KSZ8795_TAIL_TAG_OVERRIDE  BIT(6)
+#define KSZ8795_TAIL_TAG_LOOKUPBIT(7)
+
+static struct sk_buff *ksz8795_xmit(struct sk_buff *skb, struct net_device 
*dev)
+{
+   struct dsa_port *dp = dsa_slave_to_port(dev);
+   struct sk_buff *nskb;
+   u8 *tag;
+   u8 *addr;
+
+   nskb = ksz_common_xmit(skb, dev, KSZ8795_INGRESS_TAG_LEN);
+   if (!nskb)
+   return NULL;
+
+   /* Tag encoding */
+   tag = skb_put(nskb, KSZ8795_INGRESS_TAG_LEN);
+   addr = skb_mac_header(nskb);
+
+   *tag = 1 << dp->index;
+   if (is_link_local_ether_addr(addr))
+   *tag |= KSZ8795_TAIL_TAG_OVERRIDE;
+
+   return nskb;
+}
+
+static struct sk_buff *ksz8795_rcv(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *pt)
+{
+   u8 *tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN;
+
+   return ksz_common_rcv(skb, dev, tag[0] & 7, KSZ_EGRESS_TAG_LEN);
+}
+
+static const struct dsa_device_ops ksz8795_netdev_ops = {
+   .name   = "ksz8795",
+   .proto  = DSA_TAG_PROTO_KSZ8795,
+   .xmit   = ksz8795_xmit,
+   .rcv= ksz8795_rcv,
+   .overhead = KSZ8795_INGRESS_TAG_LEN,
+};
+
+DSA_TAG_DRIVER(ksz8795_netdev_ops);
+MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ8795);
+
 /*
  * For Ingress (Host -> KSZ9477), 2 bytes are added before FCS.
  * ---
@@ -183,6 +244,7 @@ DSA_TAG_DRIVER(ksz9893_netdev_ops);
 MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ9893);
 
 static struct dsa_tag_driver *dsa_tag_driver_array[] = {
+   &DSA_TAG_DRIVER_NAME(ksz8795_netdev_ops),
&DSA_TAG_DRIVER_NAME(ksz9477_netdev_ops),
&DSA_TAG_DRIVER_NAME(ksz9893_netdev_ops),
 };
-- 
2.20.1



[PATCH V2 3/3] net: dsa: ksz: Add Microchip KSZ8795 DSA driver

2019-07-25 Thread Marek Vasut
From: Tristram Ha 

Add Microchip KSZ8795 DSA driver.

Signed-off-by: Tristram Ha 
Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: David S. Miller 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Vivien Didelot 
Cc: Woojung Huh 
---
V2: - Use reverse xmas tree for variable declaration
- Use BIT() macro where applicable
- Use regmap_update_bits() where applicable
- Replace ad-hoc stp_multicast_addr[] with ether_addr_copy(..., 
eth_stp_addr)
---
 drivers/net/dsa/microchip/Kconfig   |   18 +
 drivers/net/dsa/microchip/Makefile  |2 +
 drivers/net/dsa/microchip/ksz8795.c | 1324 +++
 drivers/net/dsa/microchip/ksz8795_reg.h | 1004 +
 drivers/net/dsa/microchip/ksz8795_spi.c |  104 ++
 drivers/net/dsa/microchip/ksz_common.h  |   28 +
 drivers/net/dsa/microchip/ksz_priv.h|1 +
 7 files changed, 2481 insertions(+)
 create mode 100644 drivers/net/dsa/microchip/ksz8795.c
 create mode 100644 drivers/net/dsa/microchip/ksz8795_reg.h
 create mode 100644 drivers/net/dsa/microchip/ksz8795_spi.c

diff --git a/drivers/net/dsa/microchip/Kconfig 
b/drivers/net/dsa/microchip/Kconfig
index fe0a13b79c4b..d990c7128991 100644
--- a/drivers/net/dsa/microchip/Kconfig
+++ b/drivers/net/dsa/microchip/Kconfig
@@ -16,3 +16,21 @@ config NET_DSA_MICROCHIP_KSZ9477_SPI
select REGMAP_SPI
help
  Select to enable support for registering switches configured through 
SPI.
+
+menuconfig NET_DSA_MICROCHIP_KSZ8795
+   tristate "Microchip KSZ8795 series switch support"
+   depends on NET_DSA
+   select NET_DSA_TAG_KSZ8795
+   select NET_DSA_MICROCHIP_KSZ_COMMON
+   help
+ This driver adds support for Microchip KSZ8795 switch chips.
+
+config NET_DSA_MICROCHIP_KSZ8795_SPI
+   tristate "KSZ8795 series SPI connected switch driver"
+   depends on NET_DSA_MICROCHIP_KSZ8795 && SPI
+   select REGMAP_SPI
+   help
+ This driver accesses KSZ8795 chip through SPI.
+
+ It is required to use the KSZ8795 switch driver as the only access
+ is through SPI.
diff --git a/drivers/net/dsa/microchip/Makefile 
b/drivers/net/dsa/microchip/Makefile
index 68451b02f775..e3d799b95d7d 100644
--- a/drivers/net/dsa/microchip/Makefile
+++ b/drivers/net/dsa/microchip/Makefile
@@ -2,3 +2,5 @@
 obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ_COMMON) += ksz_common.o
 obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ9477)+= ksz9477.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
diff --git a/drivers/net/dsa/microchip/ksz8795.c 
b/drivers/net/dsa/microchip/ksz8795.c
new file mode 100644
index ..f2408d5943db
--- /dev/null
+++ b/drivers/net/dsa/microchip/ksz8795.c
@@ -0,0 +1,1324 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Microchip KSZ8795 switch driver
+ *
+ * Copyright (C) 2017 Microchip Technology Inc.
+ * Tristram Ha 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "ksz_priv.h"
+#include "ksz_common.h"
+#include "ksz8795_reg.h"
+
+static const struct {
+   char string[ETH_GSTRING_LEN];
+} mib_names[TOTAL_SWITCH_COUNTER_NUM] = {
+   { "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" },
+   { "rx_1523_2000" },
+   { "rx_2001" },
+   { "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_total" },
+   { "tx_total" },
+   { "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);
+}
+
+static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits,
+bool set)
+{
+   regmap_update_bits(dev->regmap[0], 

Re: [PATCH 3/3] net: dsa: ksz: Add Microchip KSZ8795 DSA driver

2019-07-25 Thread Marek Vasut
On 7/25/19 4:59 PM, Andrew Lunn wrote:
> On Thu, Jul 25, 2019 at 04:56:37PM +0200, Marek Vasut wrote:
>> On 7/25/19 4:03 PM, Andrew Lunn wrote:
>>> On Wed, Jul 24, 2019 at 03:40:48PM +0200, Marek Vasut wrote:
>>>> From: Tristram Ha 
>>>> +static void ksz8795_phy_setup(struct ksz_device *dev, int port,
>>>> +struct phy_device *phy)
>>>> +{
>>>> +  if (port < dev->phy_port_cnt) {
>>>> +  /*
>>>> +   * SUPPORTED_Asym_Pause and SUPPORTED_Pause can be removed to
>>>> +   * disable flow control when rate limiting is used.
>>>> +   */
>>>> +  linkmode_copy(phy->advertising, phy->supported);
>>>> +  }
>>>> +}
>>>
>>> Hi Marek
>>>
>>> Do you know why this is needed?
>>
>> Unfortunately, no.
>>
>> It seems it copies supported features of the PHY to advertised features
>> of the PHY for ports which are downstream (i.e. not the CPU port).
> 
> Hi Marek
> 
> Could you test it without this copy? Do you get sensible values from
> ethtool? Does the pause configuration look sensible?

They do look OK even without the code.


[PATCH V3 0/3] net: dsa: ksz: Add Microchip KSZ87xx support

2019-07-26 Thread Marek Vasut
This series adds support for Microchip KSZ87xx switches, which are
slightly simpler compared to KSZ9xxx .

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: David S. Miller 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Vivien Didelot 
Cc: Woojung Huh 

Marek Vasut (1):
  dt-bindings: net: dsa: ksz: document Microchip KSZ87xx family switches

Tristram Ha (2):
  net: dsa: ksz: Add KSZ8795 tag code
  net: dsa: ksz: Add Microchip KSZ8795 DSA driver

 .../devicetree/bindings/net/dsa/ksz.txt   |3 +
 drivers/net/dsa/microchip/Kconfig |   18 +
 drivers/net/dsa/microchip/Makefile|2 +
 drivers/net/dsa/microchip/ksz8795.c   | 1311 +
 drivers/net/dsa/microchip/ksz8795_reg.h   | 1004 +
 drivers/net/dsa/microchip/ksz8795_spi.c   |  104 ++
 drivers/net/dsa/microchip/ksz_common.c|3 +-
 drivers/net/dsa/microchip/ksz_common.h|   28 +
 drivers/net/dsa/microchip/ksz_priv.h  |1 +
 include/net/dsa.h |2 +
 net/dsa/Kconfig   |7 +
 net/dsa/tag_ksz.c |   62 +
 12 files changed, 2544 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/dsa/microchip/ksz8795.c
 create mode 100644 drivers/net/dsa/microchip/ksz8795_reg.h
 create mode 100644 drivers/net/dsa/microchip/ksz8795_spi.c

-- 
2.20.1



[PATCH V3 1/3] dt-bindings: net: dsa: ksz: document Microchip KSZ87xx family switches

2019-07-26 Thread Marek Vasut
Document Microchip KSZ87xx family switches. These include
KSZ8765 - 5 port switch
KSZ8794 - 4 port switch
KSZ8795 - 5 port switch

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: David S. Miller 
Cc: Florian Fainelli 
Cc: Rob Herring 
Cc: Tristram Ha 
Cc: Vivien Didelot 
Cc: Woojung Huh 
Cc: devicet...@vger.kernel.org
---
V2: No change
V3: No change
---
 Documentation/devicetree/bindings/net/dsa/ksz.txt | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/dsa/ksz.txt 
b/Documentation/devicetree/bindings/net/dsa/ksz.txt
index 4ac21cef370e..5e8429b6f9ca 100644
--- a/Documentation/devicetree/bindings/net/dsa/ksz.txt
+++ b/Documentation/devicetree/bindings/net/dsa/ksz.txt
@@ -5,6 +5,9 @@ Required properties:
 
 - compatible: For external switch chips, compatible string must be exactly one
   of the following:
+  - "microchip,ksz8765"
+  - "microchip,ksz8794"
+  - "microchip,ksz8795"
   - "microchip,ksz9477"
   - "microchip,ksz9897"
   - "microchip,ksz9896"
-- 
2.20.1



[PATCH V3 2/3] net: dsa: ksz: Add KSZ8795 tag code

2019-07-26 Thread Marek Vasut
From: Tristram Ha 

Add DSA tag code for Microchip KSZ8795 switch. The switch is simpler
and the tag is only 1 byte, instead of 2 as is the case with KSZ9477.

Signed-off-by: Tristram Ha 
Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: David S. Miller 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Vivien Didelot 
Cc: Woojung Huh 
---
V2: No change
V3: No change
---
 include/net/dsa.h |  2 ++
 net/dsa/Kconfig   |  7 ++
 net/dsa/tag_ksz.c | 62 +++
 3 files changed, 71 insertions(+)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 1e8650fa8acc..147b757ef8ea 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -41,6 +41,7 @@ struct phylink_link_state;
 #define DSA_TAG_PROTO_TRAILER_VALUE11
 #define DSA_TAG_PROTO_8021Q_VALUE  12
 #define DSA_TAG_PROTO_SJA1105_VALUE13
+#define DSA_TAG_PROTO_KSZ8795_VALUE14
 
 enum dsa_tag_protocol {
DSA_TAG_PROTO_NONE  = DSA_TAG_PROTO_NONE_VALUE,
@@ -57,6 +58,7 @@ enum dsa_tag_protocol {
DSA_TAG_PROTO_TRAILER   = DSA_TAG_PROTO_TRAILER_VALUE,
DSA_TAG_PROTO_8021Q = DSA_TAG_PROTO_8021Q_VALUE,
DSA_TAG_PROTO_SJA1105   = DSA_TAG_PROTO_SJA1105_VALUE,
+   DSA_TAG_PROTO_KSZ8795   = DSA_TAG_PROTO_KSZ8795_VALUE,
 };
 
 struct packet_type;
diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig
index 6e942dda1bcd..423fa4370608 100644
--- a/net/dsa/Kconfig
+++ b/net/dsa/Kconfig
@@ -77,6 +77,13 @@ config NET_DSA_TAG_KSZ_COMMON
tristate
default n
 
+config NET_DSA_TAG_KSZ8795
+   tristate "Tag driver for Microchip 8795 family of switches"
+   select NET_DSA_TAG_KSZ_COMMON
+   help
+ Say Y if you want to enable support for tagging frames for the
+ Microchip 8795 family of switches.
+
 config NET_DSA_TAG_KSZ
tristate "Tag driver for Microchip 9893 family of switches"
select NET_DSA_TAG_KSZ_COMMON
diff --git a/net/dsa/tag_ksz.c b/net/dsa/tag_ksz.c
index adc6c1e03a4c..7af71db91c54 100644
--- a/net/dsa/tag_ksz.c
+++ b/net/dsa/tag_ksz.c
@@ -69,6 +69,67 @@ static struct sk_buff *ksz_common_rcv(struct sk_buff *skb,
return skb;
 }
 
+/*
+ * For Ingress (Host -> KSZ8795), 1 byte is added before FCS.
+ * ---
+ * DA(6bytes)|SA(6bytes)||Data(nbytes)|tag(1byte)|FCS(4bytes)
+ * ---
+ * tag : each bit represents port (eg, 0x01=port1, 0x02=port2, 0x10=port5)
+ *
+ * For Egress (KSZ8795 -> Host), 1 byte is added before FCS.
+ * ---
+ * DA(6bytes)|SA(6bytes)||Data(nbytes)|tag0(1byte)|FCS(4bytes)
+ * ---
+ * tag0 : zero-based value represents port
+ *   (eg, 0x00=port1, 0x02=port3, 0x06=port7)
+ */
+
+#define KSZ8795_INGRESS_TAG_LEN1
+
+#define KSZ8795_TAIL_TAG_OVERRIDE  BIT(6)
+#define KSZ8795_TAIL_TAG_LOOKUPBIT(7)
+
+static struct sk_buff *ksz8795_xmit(struct sk_buff *skb, struct net_device 
*dev)
+{
+   struct dsa_port *dp = dsa_slave_to_port(dev);
+   struct sk_buff *nskb;
+   u8 *tag;
+   u8 *addr;
+
+   nskb = ksz_common_xmit(skb, dev, KSZ8795_INGRESS_TAG_LEN);
+   if (!nskb)
+   return NULL;
+
+   /* Tag encoding */
+   tag = skb_put(nskb, KSZ8795_INGRESS_TAG_LEN);
+   addr = skb_mac_header(nskb);
+
+   *tag = 1 << dp->index;
+   if (is_link_local_ether_addr(addr))
+   *tag |= KSZ8795_TAIL_TAG_OVERRIDE;
+
+   return nskb;
+}
+
+static struct sk_buff *ksz8795_rcv(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *pt)
+{
+   u8 *tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN;
+
+   return ksz_common_rcv(skb, dev, tag[0] & 7, KSZ_EGRESS_TAG_LEN);
+}
+
+static const struct dsa_device_ops ksz8795_netdev_ops = {
+   .name   = "ksz8795",
+   .proto  = DSA_TAG_PROTO_KSZ8795,
+   .xmit   = ksz8795_xmit,
+   .rcv= ksz8795_rcv,
+   .overhead = KSZ8795_INGRESS_TAG_LEN,
+};
+
+DSA_TAG_DRIVER(ksz8795_netdev_ops);
+MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ8795);
+
 /*
  * For Ingress (Host -> KSZ9477), 2 bytes are added before FCS.
  * ---
@@ -183,6 +244,7 @@ DSA_TAG_DRIVER(ksz9893_netdev_ops);
 MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ9893);
 
 static struct dsa_tag_driver *dsa_tag_driver_array[] = {
+   &DSA_TAG_DRIVER_NAME(ksz8795_netdev_ops),
&DSA_TAG_DRIVER_NAME(ksz9477_netdev_ops),
&DSA_TAG_DRIVER_NAME(ksz9893_netdev_ops),
 };
-- 
2.20.1



[PATCH V3 3/3] net: dsa: ksz: Add Microchip KSZ8795 DSA driver

2019-07-26 Thread Marek Vasut
From: Tristram Ha 

Add Microchip KSZ8795 DSA driver.

Signed-off-by: Tristram Ha 
Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: David S. Miller 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Vivien Didelot 
Cc: Woojung Huh 
---
V2: - Use reverse xmas tree for variable declaration
- Use BIT() macro where applicable
- Use regmap_update_bits() where applicable
- Replace ad-hoc stp_multicast_addr[] with ether_addr_copy(..., 
eth_stp_addr)
V3: - Drop ksz8795_phy_setup()
---
 drivers/net/dsa/microchip/Kconfig   |   18 +
 drivers/net/dsa/microchip/Makefile  |2 +
 drivers/net/dsa/microchip/ksz8795.c | 1311 +++
 drivers/net/dsa/microchip/ksz8795_reg.h | 1004 +
 drivers/net/dsa/microchip/ksz8795_spi.c |  104 ++
 drivers/net/dsa/microchip/ksz_common.c  |3 +-
 drivers/net/dsa/microchip/ksz_common.h  |   28 +
 drivers/net/dsa/microchip/ksz_priv.h|1 +
 8 files changed, 2470 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/dsa/microchip/ksz8795.c
 create mode 100644 drivers/net/dsa/microchip/ksz8795_reg.h
 create mode 100644 drivers/net/dsa/microchip/ksz8795_spi.c

diff --git a/drivers/net/dsa/microchip/Kconfig 
b/drivers/net/dsa/microchip/Kconfig
index fe0a13b79c4b..d990c7128991 100644
--- a/drivers/net/dsa/microchip/Kconfig
+++ b/drivers/net/dsa/microchip/Kconfig
@@ -16,3 +16,21 @@ config NET_DSA_MICROCHIP_KSZ9477_SPI
select REGMAP_SPI
help
  Select to enable support for registering switches configured through 
SPI.
+
+menuconfig NET_DSA_MICROCHIP_KSZ8795
+   tristate "Microchip KSZ8795 series switch support"
+   depends on NET_DSA
+   select NET_DSA_TAG_KSZ8795
+   select NET_DSA_MICROCHIP_KSZ_COMMON
+   help
+ This driver adds support for Microchip KSZ8795 switch chips.
+
+config NET_DSA_MICROCHIP_KSZ8795_SPI
+   tristate "KSZ8795 series SPI connected switch driver"
+   depends on NET_DSA_MICROCHIP_KSZ8795 && SPI
+   select REGMAP_SPI
+   help
+ This driver accesses KSZ8795 chip through SPI.
+
+ It is required to use the KSZ8795 switch driver as the only access
+ is through SPI.
diff --git a/drivers/net/dsa/microchip/Makefile 
b/drivers/net/dsa/microchip/Makefile
index 68451b02f775..e3d799b95d7d 100644
--- a/drivers/net/dsa/microchip/Makefile
+++ b/drivers/net/dsa/microchip/Makefile
@@ -2,3 +2,5 @@
 obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ_COMMON) += ksz_common.o
 obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ9477)+= ksz9477.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
diff --git a/drivers/net/dsa/microchip/ksz8795.c 
b/drivers/net/dsa/microchip/ksz8795.c
new file mode 100644
index ..ae80b3c6dea2
--- /dev/null
+++ b/drivers/net/dsa/microchip/ksz8795.c
@@ -0,0 +1,1311 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Microchip KSZ8795 switch driver
+ *
+ * Copyright (C) 2017 Microchip Technology Inc.
+ * Tristram Ha 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "ksz_priv.h"
+#include "ksz_common.h"
+#include "ksz8795_reg.h"
+
+static const struct {
+   char string[ETH_GSTRING_LEN];
+} mib_names[TOTAL_SWITCH_COUNTER_NUM] = {
+   { "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" },
+   { "rx_1523_2000" },
+   { "rx_2001" },
+   { "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_total" },
+   { "tx_total" },
+   { "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);
+}
+
+static void ksz_port_cfg(struct ksz_device *dev, int por

[PATCH V4 2/3] net: dsa: ksz: Add KSZ8795 tag code

2019-07-29 Thread Marek Vasut
From: Tristram Ha 

Add DSA tag code for Microchip KSZ8795 switch. The switch is simpler
and the tag is only 1 byte, instead of 2 as is the case with KSZ9477.

Signed-off-by: Tristram Ha 
Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: David S. Miller 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Vivien Didelot 
Cc: Woojung Huh 
---
V2: No change
V3: No change
V4: Drop Kconfig entry
---
 include/net/dsa.h |  2 ++
 net/dsa/tag_ksz.c | 62 +++
 2 files changed, 64 insertions(+)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 1e8650fa8acc..147b757ef8ea 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -41,6 +41,7 @@ struct phylink_link_state;
 #define DSA_TAG_PROTO_TRAILER_VALUE11
 #define DSA_TAG_PROTO_8021Q_VALUE  12
 #define DSA_TAG_PROTO_SJA1105_VALUE13
+#define DSA_TAG_PROTO_KSZ8795_VALUE14
 
 enum dsa_tag_protocol {
DSA_TAG_PROTO_NONE  = DSA_TAG_PROTO_NONE_VALUE,
@@ -57,6 +58,7 @@ enum dsa_tag_protocol {
DSA_TAG_PROTO_TRAILER   = DSA_TAG_PROTO_TRAILER_VALUE,
DSA_TAG_PROTO_8021Q = DSA_TAG_PROTO_8021Q_VALUE,
DSA_TAG_PROTO_SJA1105   = DSA_TAG_PROTO_SJA1105_VALUE,
+   DSA_TAG_PROTO_KSZ8795   = DSA_TAG_PROTO_KSZ8795_VALUE,
 };
 
 struct packet_type;
diff --git a/net/dsa/tag_ksz.c b/net/dsa/tag_ksz.c
index adc6c1e03a4c..7af71db91c54 100644
--- a/net/dsa/tag_ksz.c
+++ b/net/dsa/tag_ksz.c
@@ -69,6 +69,67 @@ static struct sk_buff *ksz_common_rcv(struct sk_buff *skb,
return skb;
 }
 
+/*
+ * For Ingress (Host -> KSZ8795), 1 byte is added before FCS.
+ * ---
+ * DA(6bytes)|SA(6bytes)||Data(nbytes)|tag(1byte)|FCS(4bytes)
+ * ---
+ * tag : each bit represents port (eg, 0x01=port1, 0x02=port2, 0x10=port5)
+ *
+ * For Egress (KSZ8795 -> Host), 1 byte is added before FCS.
+ * ---
+ * DA(6bytes)|SA(6bytes)||Data(nbytes)|tag0(1byte)|FCS(4bytes)
+ * ---
+ * tag0 : zero-based value represents port
+ *   (eg, 0x00=port1, 0x02=port3, 0x06=port7)
+ */
+
+#define KSZ8795_INGRESS_TAG_LEN1
+
+#define KSZ8795_TAIL_TAG_OVERRIDE  BIT(6)
+#define KSZ8795_TAIL_TAG_LOOKUPBIT(7)
+
+static struct sk_buff *ksz8795_xmit(struct sk_buff *skb, struct net_device 
*dev)
+{
+   struct dsa_port *dp = dsa_slave_to_port(dev);
+   struct sk_buff *nskb;
+   u8 *tag;
+   u8 *addr;
+
+   nskb = ksz_common_xmit(skb, dev, KSZ8795_INGRESS_TAG_LEN);
+   if (!nskb)
+   return NULL;
+
+   /* Tag encoding */
+   tag = skb_put(nskb, KSZ8795_INGRESS_TAG_LEN);
+   addr = skb_mac_header(nskb);
+
+   *tag = 1 << dp->index;
+   if (is_link_local_ether_addr(addr))
+   *tag |= KSZ8795_TAIL_TAG_OVERRIDE;
+
+   return nskb;
+}
+
+static struct sk_buff *ksz8795_rcv(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *pt)
+{
+   u8 *tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN;
+
+   return ksz_common_rcv(skb, dev, tag[0] & 7, KSZ_EGRESS_TAG_LEN);
+}
+
+static const struct dsa_device_ops ksz8795_netdev_ops = {
+   .name   = "ksz8795",
+   .proto  = DSA_TAG_PROTO_KSZ8795,
+   .xmit   = ksz8795_xmit,
+   .rcv= ksz8795_rcv,
+   .overhead = KSZ8795_INGRESS_TAG_LEN,
+};
+
+DSA_TAG_DRIVER(ksz8795_netdev_ops);
+MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ8795);
+
 /*
  * For Ingress (Host -> KSZ9477), 2 bytes are added before FCS.
  * ---
@@ -183,6 +244,7 @@ DSA_TAG_DRIVER(ksz9893_netdev_ops);
 MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_KSZ9893);
 
 static struct dsa_tag_driver *dsa_tag_driver_array[] = {
+   &DSA_TAG_DRIVER_NAME(ksz8795_netdev_ops),
&DSA_TAG_DRIVER_NAME(ksz9477_netdev_ops),
&DSA_TAG_DRIVER_NAME(ksz9893_netdev_ops),
 };
-- 
2.20.1



[PATCH V4 0/3] net: dsa: ksz: Add Microchip KSZ87xx support

2019-07-29 Thread Marek Vasut
This series adds support for Microchip KSZ87xx switches, which are
slightly simpler compared to KSZ9xxx .

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: David S. Miller 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Vivien Didelot 
Cc: Woojung Huh 

Marek Vasut (1):
  dt-bindings: net: dsa: ksz: document Microchip KSZ87xx family switches

Tristram Ha (2):
  net: dsa: ksz: Add KSZ8795 tag code
  net: dsa: ksz: Add Microchip KSZ8795 DSA driver

 .../devicetree/bindings/net/dsa/ksz.txt   |3 +
 drivers/net/dsa/microchip/Kconfig |   17 +
 drivers/net/dsa/microchip/Makefile|2 +
 drivers/net/dsa/microchip/ksz8795.c   | 1311 +
 drivers/net/dsa/microchip/ksz8795_reg.h   | 1004 +
 drivers/net/dsa/microchip/ksz8795_spi.c   |  104 ++
 drivers/net/dsa/microchip/ksz_common.c|3 +-
 drivers/net/dsa/microchip/ksz_common.h|   28 +
 drivers/net/dsa/microchip/ksz_priv.h  |1 +
 include/net/dsa.h |2 +
 net/dsa/tag_ksz.c |   62 +
 11 files changed, 2536 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/dsa/microchip/ksz8795.c
 create mode 100644 drivers/net/dsa/microchip/ksz8795_reg.h
 create mode 100644 drivers/net/dsa/microchip/ksz8795_spi.c

-- 
2.20.1



[PATCH V4 3/3] net: dsa: ksz: Add Microchip KSZ8795 DSA driver

2019-07-29 Thread Marek Vasut
From: Tristram Ha 

Add Microchip KSZ8795 DSA driver.

Signed-off-by: Tristram Ha 
Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: David S. Miller 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Vivien Didelot 
Cc: Woojung Huh 
---
V2: - Use reverse xmas tree for variable declaration
- Use BIT() macro where applicable
- Use regmap_update_bits() where applicable
- Replace ad-hoc stp_multicast_addr[] with ether_addr_copy(..., 
eth_stp_addr)
V3: - Drop ksz8795_phy_setup()
V4: - Update Kconfig entries, to not select the KSZ8795_DSA_TAG, which was 
removed
---
 drivers/net/dsa/microchip/Kconfig   |   17 +
 drivers/net/dsa/microchip/Makefile  |2 +
 drivers/net/dsa/microchip/ksz8795.c | 1311 +++
 drivers/net/dsa/microchip/ksz8795_reg.h | 1004 +
 drivers/net/dsa/microchip/ksz8795_spi.c |  104 ++
 drivers/net/dsa/microchip/ksz_common.c  |3 +-
 drivers/net/dsa/microchip/ksz_common.h  |   28 +
 drivers/net/dsa/microchip/ksz_priv.h|1 +
 8 files changed, 2469 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/dsa/microchip/ksz8795.c
 create mode 100644 drivers/net/dsa/microchip/ksz8795_reg.h
 create mode 100644 drivers/net/dsa/microchip/ksz8795_spi.c

diff --git a/drivers/net/dsa/microchip/Kconfig 
b/drivers/net/dsa/microchip/Kconfig
index fe0a13b79c4b..5e4f74286ea3 100644
--- a/drivers/net/dsa/microchip/Kconfig
+++ b/drivers/net/dsa/microchip/Kconfig
@@ -16,3 +16,20 @@ config NET_DSA_MICROCHIP_KSZ9477_SPI
select REGMAP_SPI
help
  Select to enable support for registering switches configured through 
SPI.
+
+menuconfig NET_DSA_MICROCHIP_KSZ8795
+   tristate "Microchip KSZ8795 series switch support"
+   depends on NET_DSA
+   select NET_DSA_MICROCHIP_KSZ_COMMON
+   help
+ This driver adds support for Microchip KSZ8795 switch chips.
+
+config NET_DSA_MICROCHIP_KSZ8795_SPI
+   tristate "KSZ8795 series SPI connected switch driver"
+   depends on NET_DSA_MICROCHIP_KSZ8795 && SPI
+   select REGMAP_SPI
+   help
+ This driver accesses KSZ8795 chip through SPI.
+
+ It is required to use the KSZ8795 switch driver as the only access
+ is through SPI.
diff --git a/drivers/net/dsa/microchip/Makefile 
b/drivers/net/dsa/microchip/Makefile
index 68451b02f775..e3d799b95d7d 100644
--- a/drivers/net/dsa/microchip/Makefile
+++ b/drivers/net/dsa/microchip/Makefile
@@ -2,3 +2,5 @@
 obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ_COMMON) += ksz_common.o
 obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ9477)+= ksz9477.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
diff --git a/drivers/net/dsa/microchip/ksz8795.c 
b/drivers/net/dsa/microchip/ksz8795.c
new file mode 100644
index ..ae80b3c6dea2
--- /dev/null
+++ b/drivers/net/dsa/microchip/ksz8795.c
@@ -0,0 +1,1311 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Microchip KSZ8795 switch driver
+ *
+ * Copyright (C) 2017 Microchip Technology Inc.
+ * Tristram Ha 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "ksz_priv.h"
+#include "ksz_common.h"
+#include "ksz8795_reg.h"
+
+static const struct {
+   char string[ETH_GSTRING_LEN];
+} mib_names[TOTAL_SWITCH_COUNTER_NUM] = {
+   { "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" },
+   { "rx_1523_2000" },
+   { "rx_2001" },
+   { "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_total" },
+   { "tx_total" },
+   { "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);
+}
+
+s

[PATCH V4 1/3] dt-bindings: net: dsa: ksz: document Microchip KSZ87xx family switches

2019-07-29 Thread Marek Vasut
Document Microchip KSZ87xx family switches. These include
KSZ8765 - 5 port switch
KSZ8794 - 4 port switch
KSZ8795 - 5 port switch

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: David S. Miller 
Cc: Florian Fainelli 
Cc: Rob Herring 
Cc: Tristram Ha 
Cc: Vivien Didelot 
Cc: Woojung Huh 
Cc: devicet...@vger.kernel.org
---
V2: No change
V3: No change
V4: No change
---
 Documentation/devicetree/bindings/net/dsa/ksz.txt | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/dsa/ksz.txt 
b/Documentation/devicetree/bindings/net/dsa/ksz.txt
index 4ac21cef370e..5e8429b6f9ca 100644
--- a/Documentation/devicetree/bindings/net/dsa/ksz.txt
+++ b/Documentation/devicetree/bindings/net/dsa/ksz.txt
@@ -5,6 +5,9 @@ Required properties:
 
 - compatible: For external switch chips, compatible string must be exactly one
   of the following:
+  - "microchip,ksz8765"
+  - "microchip,ksz8794"
+  - "microchip,ksz8795"
   - "microchip,ksz9477"
   - "microchip,ksz9897"
   - "microchip,ksz9896"
-- 
2.20.1



[PATCH 3/3] net: dsa: ksz: Drop NET_DSA_TAG_KSZ9477

2019-08-06 Thread Marek Vasut
This Kconfig option is unused, drop it.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: David S. Miller 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Vivien Didelot 
Cc: Woojung Huh 
---
 drivers/net/dsa/microchip/Kconfig | 1 -
 net/dsa/Kconfig   | 7 ---
 2 files changed, 8 deletions(-)

diff --git a/drivers/net/dsa/microchip/Kconfig 
b/drivers/net/dsa/microchip/Kconfig
index 5e4f74286ea3..e1c23d1e91e6 100644
--- a/drivers/net/dsa/microchip/Kconfig
+++ b/drivers/net/dsa/microchip/Kconfig
@@ -5,7 +5,6 @@ config NET_DSA_MICROCHIP_KSZ_COMMON
 menuconfig NET_DSA_MICROCHIP_KSZ9477
tristate "Microchip KSZ9477 series switch support"
depends on NET_DSA
-   select NET_DSA_TAG_KSZ9477
select NET_DSA_MICROCHIP_KSZ_COMMON
help
  This driver adds support for Microchip KSZ9477 switch chips.
diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig
index 6e942dda1bcd..2f69d4b53d46 100644
--- a/net/dsa/Kconfig
+++ b/net/dsa/Kconfig
@@ -84,13 +84,6 @@ config NET_DSA_TAG_KSZ
  Say Y if you want to enable support for tagging frames for the
  Microchip 9893 family of switches.
 
-config NET_DSA_TAG_KSZ9477
-   tristate "Tag driver for Microchip 9477 family of switches"
-   select NET_DSA_TAG_KSZ_COMMON
-   help
- Say Y if you want to enable support for tagging frames for the
- Microchip 9477 family of switches.
-
 config NET_DSA_TAG_QCA
tristate "Tag driver for Qualcomm Atheros QCA8K switches"
help
-- 
2.20.1



[PATCH 2/3] net: dsa: ksz: Merge ksz_priv.h into ksz_common.h

2019-08-06 Thread Marek Vasut
Merge the two headers into one, no functional change.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: David S. Miller 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Vivien Didelot 
Cc: Woojung Huh 
---
 drivers/net/dsa/microchip/ksz8795.c |   1 -
 drivers/net/dsa/microchip/ksz8795_spi.c |   1 -
 drivers/net/dsa/microchip/ksz9477.c |   1 -
 drivers/net/dsa/microchip/ksz9477_spi.c |   1 -
 drivers/net/dsa/microchip/ksz_common.c  |   1 -
 drivers/net/dsa/microchip/ksz_common.h  | 144 ++
 drivers/net/dsa/microchip/ksz_priv.h| 156 
 7 files changed, 144 insertions(+), 161 deletions(-)
 delete mode 100644 drivers/net/dsa/microchip/ksz_priv.h

diff --git a/drivers/net/dsa/microchip/ksz8795.c 
b/drivers/net/dsa/microchip/ksz8795.c
index ae80b3c6dea2..a23d3ffdf0c4 100644
--- a/drivers/net/dsa/microchip/ksz8795.c
+++ b/drivers/net/dsa/microchip/ksz8795.c
@@ -18,7 +18,6 @@
 #include 
 #include 
 
-#include "ksz_priv.h"
 #include "ksz_common.h"
 #include "ksz8795_reg.h"
 
diff --git a/drivers/net/dsa/microchip/ksz8795_spi.c 
b/drivers/net/dsa/microchip/ksz8795_spi.c
index 50aa0d24effb..d0f8153e86b7 100644
--- a/drivers/net/dsa/microchip/ksz8795_spi.c
+++ b/drivers/net/dsa/microchip/ksz8795_spi.c
@@ -14,7 +14,6 @@
 #include 
 #include 
 
-#include "ksz_priv.h"
 #include "ksz_common.h"
 
 #define SPI_ADDR_SHIFT 12
diff --git a/drivers/net/dsa/microchip/ksz9477.c 
b/drivers/net/dsa/microchip/ksz9477.c
index a8c97f7a79b7..187be42de5f1 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -14,7 +14,6 @@
 #include 
 #include 
 
-#include "ksz_priv.h"
 #include "ksz9477_reg.h"
 #include "ksz_common.h"
 
diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c 
b/drivers/net/dsa/microchip/ksz9477_spi.c
index 5a9e27b337a8..a226b389e12d 100644
--- a/drivers/net/dsa/microchip/ksz9477_spi.c
+++ b/drivers/net/dsa/microchip/ksz9477_spi.c
@@ -13,7 +13,6 @@
 #include 
 #include 
 
-#include "ksz_priv.h"
 #include "ksz_common.h"
 
 #define SPI_ADDR_SHIFT 24
diff --git a/drivers/net/dsa/microchip/ksz_common.c 
b/drivers/net/dsa/microchip/ksz_common.c
index a1e6e560fde8..b45c7b972cec 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -18,7 +18,6 @@
 #include 
 #include 
 
-#include "ksz_priv.h"
 #include "ksz_common.h"
 
 void ksz_update_port_member(struct ksz_device *dev, int port)
diff --git a/drivers/net/dsa/microchip/ksz_common.h 
b/drivers/net/dsa/microchip/ksz_common.h
index 9f9ff0fb3b53..c44a8d23d973 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -7,7 +7,151 @@
 #ifndef __KSZ_COMMON_H
 #define __KSZ_COMMON_H
 
+#include 
+#include 
+#include 
+#include 
 #include 
+#include 
+
+struct vlan_table {
+   u32 table[3];
+};
+
+struct ksz_port_mib {
+   struct mutex cnt_mutex; /* structure access */
+   u8 cnt_ptr;
+   u64 *counters;
+};
+
+struct ksz_port {
+   u16 member;
+   u16 vid_member;
+   int stp_state;
+   struct phy_device phydev;
+
+   u32 on:1;   /* port is not disabled by hardware */
+   u32 phy:1;  /* port has a PHY */
+   u32 fiber:1;/* port is fiber */
+   u32 sgmii:1;/* port is SGMII */
+   u32 force:1;
+   u32 read:1; /* read MIB counters in background */
+   u32 freeze:1;   /* MIB counter freeze is enabled */
+
+   struct ksz_port_mib mib;
+};
+
+struct ksz_device {
+   struct dsa_switch *ds;
+   struct ksz_platform_data *pdata;
+   const char *name;
+
+   struct mutex dev_mutex; /* device access */
+   struct mutex stats_mutex;   /* status access */
+   struct mutex alu_mutex; /* ALU access */
+   struct mutex vlan_mutex;/* vlan access */
+   const struct ksz_dev_ops *dev_ops;
+
+   struct device *dev;
+   struct regmap *regmap[3];
+
+   void *priv;
+
+   struct gpio_desc *reset_gpio;   /* Optional reset GPIO */
+
+   /* chip specific data */
+   u32 chip_id;
+   int num_vlans;
+   int num_alus;
+   int num_statics;
+   int cpu_port;   /* port connected to CPU */
+   int cpu_ports;  /* port bitmap can be cpu port */
+   int phy_port_cnt;
+   int port_cnt;
+   int reg_mib_cnt;
+   int mib_cnt;
+   int mib_port_cnt;
+   int last_port;  /* ports after that not used */
+   phy_interface_t interface;
+   u32 regs_size;
+   bool phy_errata_9477;
+   bool synclko_125;
+
+   struct vlan_table *vlan_cache;
+
+   struct ksz_port *ports;
+   struct timer_list mib_read_timer;
+   struct work_str

[PATCH 1/3] net: dsa: ksz: Remove dead code and fix warnings

2019-08-06 Thread Marek Vasut
Remove ksz_port_cleanup(), which is unused. Add missing include
"ksz_common.h", which fixes the following warning when built with
make ... W=1

drivers/net/dsa/microchip/ksz_common.c:23:6: warning: no previous prototype for 
‘...’ [-Wmissing-prototypes]

Note that the order of the headers cannot be swapped, as that would
trigger missing forward declaration errors, which would indicate the
way forward is to merge the two headers into one.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: David S. Miller 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Vivien Didelot 
Cc: Woojung Huh 
---
 drivers/net/dsa/microchip/ksz_common.c | 11 +--
 drivers/net/dsa/microchip/ksz_common.h |  1 -
 2 files changed, 1 insertion(+), 11 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz_common.c 
b/drivers/net/dsa/microchip/ksz_common.c
index ce20cc90f9ef..a1e6e560fde8 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -19,16 +19,7 @@
 #include 
 
 #include "ksz_priv.h"
-
-void ksz_port_cleanup(struct ksz_device *dev, int port)
-{
-   /* Common code for port cleanup. */
-   mutex_lock(&dev->dev_mutex);
-   dev->on_ports &= ~(1 << port);
-   dev->live_ports &= ~(1 << port);
-   mutex_unlock(&dev->dev_mutex);
-}
-EXPORT_SYMBOL_GPL(ksz_port_cleanup);
+#include "ksz_common.h"
 
 void ksz_update_port_member(struct ksz_device *dev, int port)
 {
diff --git a/drivers/net/dsa/microchip/ksz_common.h 
b/drivers/net/dsa/microchip/ksz_common.h
index 84fed4a2578b..9f9ff0fb3b53 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -9,7 +9,6 @@
 
 #include 
 
-void ksz_port_cleanup(struct ksz_device *dev, int port);
 void ksz_update_port_member(struct ksz_device *dev, int port);
 void ksz_init_mib_timer(struct ksz_device *dev);
 
-- 
2.20.1



Re: [PATCH net-next] net: ks8851: Connect and start/stop the internal PHY

2021-01-12 Thread Marek Vasut

On 1/11/21 3:47 PM, Andrew Lunn wrote:

On Mon, Jan 11, 2021 at 01:53:37PM +0100, Marek Vasut wrote:

Unless the internal PHY is connected and started, the phylib will not
poll the PHY for state and produce state updates. Connect the PHY and
start/stop it.


Hi Marek

Please continue the conversion and remove all mii_calls.

ks8851_set_link_ksettings() calling mii_ethtool_set_link_ksettings()
is not good, phylib will not know about changes which we made to the
PHY etc.


Hi,

I noticed a couple of drivers implement both the mii and mdiobus 
options, I was pondering why is that. Is there some legacy backward 
compatibility reason for keeping both or is it safe to remove the mii 
support completely from the driver?


Either way, I will do that in a separate patch, so it could be reverted 
if it breaks something.


Re: [PATCH net-next] net: ks8851: Connect and start/stop the internal PHY

2021-01-12 Thread Marek Vasut

On 1/11/21 3:43 PM, Heiner Kallweit wrote:

On 11.01.2021 15:10, Marek Vasut wrote:

On 1/11/21 2:50 PM, Heiner Kallweit wrote:

On 11.01.2021 14:38, Marek Vasut wrote:

On 1/11/21 2:26 PM, Heiner Kallweit wrote:
[...]


LGTM. When having a brief look at the driver I stumbled across two things:

1. Do MAC/PHY support any pause mode? Then a call to
  phy_support_(a)sym_pause() would be missing.


https://ww1.microchip.com/downloads/en/DeviceDoc/KSZ8851-16MLL-Single-Port-Ethernet-MAC-Controller-with-8-Bit-or-16-Bit-Non-PCI-Interface-DS2357B.pdf
page 64

https://www.mouser.com/datasheet/2/268/ksz8851-16mll_ds-776208.pdf
page 65

The later is more complete.

Apparently it does support pause.


Based on the datasheet, does it support sym or asym pause ?



According to the description of flow control on p.23 it can support asym pause.
However on the MAC side flow control doesn't seem to be always active, it's
controlled by these two bits:

p.49, TXCR, bit 3
p.50, RXCR1, bit 10

Default seems to be that flow control is disabled.


So I guess this patch is OK as-is ?


Re: [PATCH net-next] net: ks8851: Connect and start/stop the internal PHY

2021-01-15 Thread Marek Vasut

On 1/14/21 2:54 PM, Andrew Lunn wrote:

On Tue, Jan 12, 2021 at 11:28:00PM +0100, Marek Vasut wrote:

On 1/11/21 3:47 PM, Andrew Lunn wrote:

On Mon, Jan 11, 2021 at 01:53:37PM +0100, Marek Vasut wrote:

Unless the internal PHY is connected and started, the phylib will not
poll the PHY for state and produce state updates. Connect the PHY and
start/stop it.


Hi Marek

Please continue the conversion and remove all mii_calls.

ks8851_set_link_ksettings() calling mii_ethtool_set_link_ksettings()
is not good, phylib will not know about changes which we made to the
PHY etc.


Hi,

I noticed a couple of drivers implement both the mii and mdiobus options.


Which ones?


boardcom b44.c and bcm63xx_enet.c for example


Simply getting the link status might be safe, but if
set_link_ksettings() or get_link_ksettings() is used, phylib is going
to get confused when the PHY is changed without it knowing.. So please
do remove all the mii calls as part of the patchset.


Isn't that gonna break some ABI ?

Also, is separate patch OK ?


[PATCH net-next] net: ks8851: Fix mixed module/builtin build

2021-01-15 Thread Marek Vasut
When either the SPI or PAR variant is compiled as module AND the other
variant is compiled as built-in, the following build error occurs:

arm-linux-gnueabi-ld: drivers/net/ethernet/micrel/ks8851_common.o: in function 
`ks8851_probe_common':
ks8851_common.c:(.text+0x1564): undefined reference to `__this_module'

Fix this by including the ks8851_common.c in both ks8851_spi.c and
ks8851_par.c. The DEBUG macro is defined in ks8851_common.c, so it
does not have to be defined again.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Heiner Kallweit 
Cc: Jakub Kicinski 
Cc: Lukas Wunner 
---
NOTE: Maybe there is a better way?
---
 drivers/net/ethernet/micrel/Makefile | 4 ++--
 drivers/net/ethernet/micrel/ks8851_par.c | 2 +-
 drivers/net/ethernet/micrel/ks8851_spi.c | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/micrel/Makefile 
b/drivers/net/ethernet/micrel/Makefile
index 5cc00d22c708..1aedfe0ecaf1 100644
--- a/drivers/net/ethernet/micrel/Makefile
+++ b/drivers/net/ethernet/micrel/Makefile
@@ -5,7 +5,7 @@
 
 obj-$(CONFIG_KS8842) += ks8842.o
 obj-$(CONFIG_KS8851) += ks8851.o
-ks8851-objs = ks8851_common.o ks8851_spi.o
+ks8851-objs = ks8851_spi.o
 obj-$(CONFIG_KS8851_MLL) += ks8851_mll.o
-ks8851_mll-objs = ks8851_common.o ks8851_par.o
+ks8851_mll-objs = ks8851_par.o
 obj-$(CONFIG_KSZ884X_PCI) += ksz884x.o
diff --git a/drivers/net/ethernet/micrel/ks8851_par.c 
b/drivers/net/ethernet/micrel/ks8851_par.c
index 3bab0cb2b1a5..e9131cc8a57b 100644
--- a/drivers/net/ethernet/micrel/ks8851_par.c
+++ b/drivers/net/ethernet/micrel/ks8851_par.c
@@ -8,7 +8,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#define DEBUG
+#include "ks8851_common.c"
 
 #include 
 #include 
diff --git a/drivers/net/ethernet/micrel/ks8851_spi.c 
b/drivers/net/ethernet/micrel/ks8851_spi.c
index 4ec7f1615977..53779d66f747 100644
--- a/drivers/net/ethernet/micrel/ks8851_spi.c
+++ b/drivers/net/ethernet/micrel/ks8851_spi.c
@@ -8,7 +8,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#define DEBUG
+#include "ks8851_common.c"
 
 #include 
 #include 
-- 
2.29.2



Re: [PATCH net-next] net: ks8851: Fix mixed module/builtin build

2021-01-15 Thread Marek Vasut

On 1/15/21 4:00 PM, Andrew Lunn wrote:

On Fri, Jan 15, 2021 at 02:42:39PM +0100, Marek Vasut wrote:

When either the SPI or PAR variant is compiled as module AND the other
variant is compiled as built-in, the following build error occurs:

arm-linux-gnueabi-ld: drivers/net/ethernet/micrel/ks8851_common.o: in function 
`ks8851_probe_common':
ks8851_common.c:(.text+0x1564): undefined reference to `__this_module'

Fix this by including the ks8851_common.c in both ks8851_spi.c and
ks8851_par.c. The DEBUG macro is defined in ks8851_common.c, so it
does not have to be defined again.


DEBUG should not be defined for production code. So i would remove it
altogether.

There is kconfig'ury you can use to make them both the same. But i'm
not particularly good with it.


We had discussion about this module/builtin topic in ks8851 before, so I 
was hoping someone might provide a better suggestion.


Re: [PATCH net-next] net: ks8851: Fix mixed module/builtin build

2021-01-15 Thread Marek Vasut

On 1/15/21 4:59 PM, Andrew Lunn wrote:

On Fri, Jan 15, 2021 at 04:05:57PM +0100, Marek Vasut wrote:

On 1/15/21 4:00 PM, Andrew Lunn wrote:

On Fri, Jan 15, 2021 at 02:42:39PM +0100, Marek Vasut wrote:

When either the SPI or PAR variant is compiled as module AND the other
variant is compiled as built-in, the following build error occurs:

arm-linux-gnueabi-ld: drivers/net/ethernet/micrel/ks8851_common.o: in function 
`ks8851_probe_common':
ks8851_common.c:(.text+0x1564): undefined reference to `__this_module'

Fix this by including the ks8851_common.c in both ks8851_spi.c and
ks8851_par.c. The DEBUG macro is defined in ks8851_common.c, so it
does not have to be defined again.


DEBUG should not be defined for production code. So i would remove it
altogether.

There is kconfig'ury you can use to make them both the same. But i'm
not particularly good with it.


We had discussion about this module/builtin topic in ks8851 before, so I was
hoping someone might provide a better suggestion.


Try Arnd Bergmann. He is good with this sort of thing.


Adding to CC.


Re: [PATCH] net: ks8851: remove definition of DEBUG

2021-01-15 Thread Marek Vasut

On 1/15/21 4:31 PM, t...@redhat.com wrote:

From: Tom Rix 

Defining DEBUG should only be done in development.
So remove DEBUG.

Signed-off-by: Tom Rix 


Reviewed-by: Marek Vasut 

Thanks


[PATCH net-next V2] net: ks8851: Fix mixed module/builtin build

2021-01-16 Thread Marek Vasut
When either the SPI or PAR variant is compiled as module AND the other
variant is compiled as built-in, the following build error occurs:

arm-linux-gnueabi-ld: drivers/net/ethernet/micrel/ks8851_common.o: in function 
`ks8851_probe_common':
ks8851_common.c:(.text+0x1564): undefined reference to `__this_module'

Fix this by passing THIS_MODULE as argument to ks8851_probe_common(),
ks8851_register_mdiobus(), and ultimately __mdiobus_register() in the
ks8851_common.c.

Fixes: ef3631220d2b ("net: ks8851: Register MDIO bus and the internal PHY")
Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Arnd Bergmann 
Cc: Heiner Kallweit 
Cc: Jakub Kicinski 
Cc: Lukas Wunner 
---
V2: Pass the THIS_MODULE into ks8851_common.c
---
 drivers/net/ethernet/micrel/ks8851.h| 2 +-
 drivers/net/ethernet/micrel/ks8851_common.c | 9 +
 drivers/net/ethernet/micrel/ks8851_par.c| 2 +-
 drivers/net/ethernet/micrel/ks8851_spi.c| 2 +-
 4 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/micrel/ks8851.h 
b/drivers/net/ethernet/micrel/ks8851.h
index ef13929036cf..037138fc6cb4 100644
--- a/drivers/net/ethernet/micrel/ks8851.h
+++ b/drivers/net/ethernet/micrel/ks8851.h
@@ -428,7 +428,7 @@ struct ks8851_net {
 };
 
 int ks8851_probe_common(struct net_device *netdev, struct device *dev,
-   int msg_en);
+   int msg_en, struct module *owner);
 int ks8851_remove_common(struct device *dev);
 int ks8851_suspend(struct device *dev);
 int ks8851_resume(struct device *dev);
diff --git a/drivers/net/ethernet/micrel/ks8851_common.c 
b/drivers/net/ethernet/micrel/ks8851_common.c
index f1996787bba5..88303ba4869d 100644
--- a/drivers/net/ethernet/micrel/ks8851_common.c
+++ b/drivers/net/ethernet/micrel/ks8851_common.c
@@ -1104,7 +1104,8 @@ int ks8851_resume(struct device *dev)
 }
 #endif
 
-static int ks8851_register_mdiobus(struct ks8851_net *ks, struct device *dev)
+static int ks8851_register_mdiobus(struct ks8851_net *ks, struct device *dev,
+  struct module *owner)
 {
struct phy_device *phy_dev;
struct mii_bus *mii_bus;
@@ -1122,7 +1123,7 @@ static int ks8851_register_mdiobus(struct ks8851_net *ks, 
struct device *dev)
mii_bus->phy_mask = ~((u32)BIT(0));
snprintf(mii_bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev));
 
-   ret = mdiobus_register(mii_bus);
+   ret = __mdiobus_register(mii_bus, owner);
if (ret)
goto err_mdiobus_register;
 
@@ -1149,7 +1150,7 @@ static void ks8851_unregister_mdiobus(struct ks8851_net 
*ks)
 }
 
 int ks8851_probe_common(struct net_device *netdev, struct device *dev,
-   int msg_en)
+   int msg_en, struct module *owner)
 {
struct ks8851_net *ks = netdev_priv(netdev);
unsigned cider;
@@ -1224,7 +1225,7 @@ int ks8851_probe_common(struct net_device *netdev, struct 
device *dev,
 
dev_info(dev, "message enable is %d\n", msg_en);
 
-   ret = ks8851_register_mdiobus(ks, dev);
+   ret = ks8851_register_mdiobus(ks, dev, owner);
if (ret)
goto err_mdio;
 
diff --git a/drivers/net/ethernet/micrel/ks8851_par.c 
b/drivers/net/ethernet/micrel/ks8851_par.c
index 3bab0cb2b1a5..d6fc53d3efbb 100644
--- a/drivers/net/ethernet/micrel/ks8851_par.c
+++ b/drivers/net/ethernet/micrel/ks8851_par.c
@@ -324,7 +324,7 @@ static int ks8851_probe_par(struct platform_device *pdev)
 
netdev->irq = platform_get_irq(pdev, 0);
 
-   return ks8851_probe_common(netdev, dev, msg_enable);
+   return ks8851_probe_common(netdev, dev, msg_enable, THIS_MODULE);
 }
 
 static int ks8851_remove_par(struct platform_device *pdev)
diff --git a/drivers/net/ethernet/micrel/ks8851_spi.c 
b/drivers/net/ethernet/micrel/ks8851_spi.c
index 4ec7f1615977..9fbb7a548580 100644
--- a/drivers/net/ethernet/micrel/ks8851_spi.c
+++ b/drivers/net/ethernet/micrel/ks8851_spi.c
@@ -451,7 +451,7 @@ static int ks8851_probe_spi(struct spi_device *spi)
 
netdev->irq = spi->irq;
 
-   return ks8851_probe_common(netdev, dev, msg_enable);
+   return ks8851_probe_common(netdev, dev, msg_enable, THIS_MODULE);
 }
 
 static int ks8851_remove_spi(struct spi_device *spi)
-- 
2.29.2



Re: [PATCH net-next] net: ks8851: Fix mixed module/builtin build

2021-01-16 Thread Marek Vasut

On 1/15/21 10:36 PM, Arnd Bergmann wrote:

On Fri, Jan 15, 2021 at 6:24 PM Heiner Kallweit  wrote:

On 15.01.2021 16:59, Andrew Lunn wrote:

On Fri, Jan 15, 2021 at 04:05:57PM +0100, Marek Vasut wrote:

On 1/15/21 4:00 PM, Andrew Lunn wrote:

On Fri, Jan 15, 2021 at 02:42:39PM +0100, Marek Vasut wrote:

When either the SPI or PAR variant is compiled as module AND the other
variant is compiled as built-in, the following build error occurs:

arm-linux-gnueabi-ld: drivers/net/ethernet/micrel/ks8851_common.o: in function 
`ks8851_probe_common':
ks8851_common.c:(.text+0x1564): undefined reference to `__this_module'

Fix this by including the ks8851_common.c in both ks8851_spi.c and
ks8851_par.c. The DEBUG macro is defined in ks8851_common.c, so it
does not have to be defined again.


DEBUG should not be defined for production code. So i would remove it
altogether.

There is kconfig'ury you can use to make them both the same. But i'm
not particularly good with it.


We had discussion about this module/builtin topic in ks8851 before, so I was
hoping someone might provide a better suggestion.


Try Arnd Bergmann. He is good with this sort of thing.


I'd say make ks8851_common.c a separate module. Then, if one of SPI / PAR
is built in, ks8851_common needs to be built in too. To do so you'd have
export all symbols from ks8851_common that you want to use in SPI /PAR.


Yes, that should work, as long the common module does not reference
any symbols from the other two modules (it normally wouldn't), and all
globals in the common one are exported.

You can also link everything into a single module, but then you have
to deal with registering two device_driver structures from a single
init function, which would undo some of cleanup.


Maybe just passing THIS_MODULE around is even better way to do it, I 
CCed you on the V2, [PATCH net-next V2] net: ks8851: Fix mixed 
module/builtin build .


Re: [PATCH net-next V2] net: ks8851: Fix mixed module/builtin build

2021-01-16 Thread Marek Vasut

On 1/16/21 6:04 PM, Arnd Bergmann wrote:

On Sat, Jan 16, 2021 at 5:48 PM Marek Vasut  wrote:


When either the SPI or PAR variant is compiled as module AND the other
variant is compiled as built-in, the following build error occurs:

arm-linux-gnueabi-ld: drivers/net/ethernet/micrel/ks8851_common.o: in function 
`ks8851_probe_common':
ks8851_common.c:(.text+0x1564): undefined reference to `__this_module'

Fix this by passing THIS_MODULE as argument to ks8851_probe_common(),
ks8851_register_mdiobus(), and ultimately __mdiobus_register() in the
ks8851_common.c.

Fixes: ef3631220d2b ("net: ks8851: Register MDIO bus and the internal PHY")
Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Arnd Bergmann 
Cc: Heiner Kallweit 
Cc: Jakub Kicinski 
Cc: Lukas Wunner 


I don't really like this version, as it does not actually solve the problem of
linking the same object file into both vmlinux and a loadable module, which
can have all kinds of side-effects besides that link failure you saw.

If you want to avoid exporting all those symbols, a simpler hack would
be to '#include "ks8851_common.c" from each of the two files, which
then always duplicates the contents (even when both are built-in), but
at least builds the file the correct way.


That's the same as V1, isn't it ?


Re: [PATCH net-next V2] net: ks8851: Fix mixed module/builtin build

2021-01-16 Thread Marek Vasut

On 1/16/21 9:39 PM, Lukas Wunner wrote:

On Sat, Jan 16, 2021 at 08:26:22PM +0100, Arnd Bergmann wrote:

On Sat, Jan 16, 2021 at 6:56 PM Marek Vasut  wrote:

On 1/16/21 6:04 PM, Arnd Bergmann wrote:

On Sat, Jan 16, 2021 at 5:48 PM Marek Vasut  wrote:



I don't really like this version, as it does not actually solve the problem of
linking the same object file into both vmlinux and a loadable module, which
can have all kinds of side-effects besides that link failure you saw.

If you want to avoid exporting all those symbols, a simpler hack would
be to '#include "ks8851_common.c" from each of the two files, which
then always duplicates the contents (even when both are built-in), but
at least builds the file the correct way.


That's the same as V1, isn't it ?


Ah, I had not actually looked at the original submission, but yes, that
was slightly better than v2, provided you make all symbols static to
avoid the new link error.

I still think that having three modules and exporting the symbols from
the common part as Heiner Kallweit suggested would be the best
way to do it.


FWIW I'd prefer V1 (the #include approach) as it allows going back to
using static inlines for register access.  That's what we had before
7a552c850c45.

It seems unlikely that a system uses both, the parallel *and* the SPI
variant of the ks8851.  So the additional memory necessary because of
code duplication wouldn't matter in practice.


I have a board with both options populated on my desk, sorry.


[PATCH net-next] net: dsa: microchip: ksz8795: Fix KSZ8794 port map again

2021-01-19 Thread Marek Vasut
The KSZ8795 switch has 4 external ports {0,1,2,3} and 1 CPU port {4}, so
does the KSZ8765. The KSZ8794 seems to be repackaged KSZ8795 with different
ID and port 3 not routed out, however the port 3 registers are present in
the silicon, so the KSZ8794 switch has 3 external ports {0,1,2} and 1 CPU
port {4}. Currently the driver always uses the last port as CPU port, on
KSZ8795/KSZ8765 that is port 4 and that is OK, but on KSZ8794 that is port
3 and that is not OK, as it must also be port 4.

This patch adjusts the driver such that it always registers a switch with
5 ports total (4 external ports, 1 CPU port), always sets the CPU port to
switch port 4, and then configures the external port mask according to
the switch model -- 3 ports for KSZ8794 and 4 for KSZ8795/KSZ8765.

Fixes: 68a1b676db52 ("net: dsa: microchip: ksz8795: remove superfluous port_cnt 
assignment")
Fixes: 4ce2a984abd8 ("net: dsa: microchip: ksz8795: use phy_port_cnt where 
possible")
Fixes: 241ed719bc98 ("net: dsa: microchip: ksz8795: use port_cnt instead of 
TOTOAL_PORT_NUM")
Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Michael Grzeschik 
Cc: Jakub Kicinski 
---
NOTE: In case of KSZ8794, the DT node port@4 is the CPU port and
  port@3 should not be defined.
---
 drivers/net/dsa/microchip/ksz8795.c | 30 +++--
 1 file changed, 20 insertions(+), 10 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz8795.c 
b/drivers/net/dsa/microchip/ksz8795.c
index c973db101b72..a4570ba29c83 100644
--- a/drivers/net/dsa/microchip/ksz8795.c
+++ b/drivers/net/dsa/microchip/ksz8795.c
@@ -1187,6 +1187,20 @@ static const struct ksz_chip_data ksz8795_switch_chips[] 
= {
.port_cnt = 5,  /* total cpu and user ports */
},
{
+   /*
+* WARNING
+* ===
+* KSZ8794 is similar to KSZ8795, except the port map
+* contains a gap between external and CPU ports, the
+* port map is NOT continuous. The per-port register
+* map is shifted accordingly too, i.e. registers at
+* offset 0x40 are NOT used on KSZ8794 and they ARE
+* used on KSZ8795 for external port 3.
+*   external  cpu
+* KSZ8794   0,1,2  4
+* KSZ8795   0,1,2,34
+* KSZ8765   0,1,2,34
+*/
.chip_id = 0x8794,
.dev_name = "KSZ8794",
.num_vlans = 4096,
@@ -1220,9 +1234,13 @@ static int ksz8795_switch_init(struct ksz_device *dev)
dev->num_vlans = chip->num_vlans;
dev->num_alus = chip->num_alus;
dev->num_statics = chip->num_statics;
-   dev->port_cnt = chip->port_cnt;
+   dev->port_cnt = fls(chip->cpu_ports);
+   dev->cpu_port = fls(chip->cpu_ports) - 1;
+   dev->phy_port_cnt = dev->port_cnt - 1;
dev->cpu_ports = chip->cpu_ports;
-
+   dev->host_mask = chip->cpu_ports;
+   dev->port_mask = (BIT(dev->phy_port_cnt) - 1) |
+chip->cpu_ports;
break;
}
}
@@ -1231,17 +1249,9 @@ static int ksz8795_switch_init(struct ksz_device *dev)
if (!dev->cpu_ports)
return -ENODEV;
 
-   dev->port_mask = BIT(dev->port_cnt) - 1;
-   dev->port_mask |= dev->host_mask;
-
dev->reg_mib_cnt = KSZ8795_COUNTER_NUM;
dev->mib_cnt = ARRAY_SIZE(mib_names);
 
-   dev->phy_port_cnt = dev->port_cnt - 1;
-
-   dev->cpu_port = dev->port_cnt - 1;
-   dev->host_mask = BIT(dev->cpu_port);
-
dev->ports = devm_kzalloc(dev->dev,
  dev->port_cnt * sizeof(struct ksz_port),
  GFP_KERNEL);
-- 
2.29.2



[PATCH net-next V2] net: dsa: microchip: ksz8795: Fix KSZ8794 port map again

2021-01-19 Thread Marek Vasut
The KSZ8795 switch has 4 external ports {0,1,2,3} and 1 CPU port {4}, so
does the KSZ8765. The KSZ8794 seems to be repackaged KSZ8795 with different
ID and port 3 not routed out, however the port 3 registers are present in
the silicon, so the KSZ8794 switch has 3 external ports {0,1,2} and 1 CPU
port {4}. Currently the driver always uses the last port as CPU port, on
KSZ8795/KSZ8765 that is port 4 and that is OK, but on KSZ8794 that is port
3 and that is not OK, as it must also be port 4.

This patch adjusts the driver such that it always registers a switch with
5 ports total (4 external ports, 1 CPU port), always sets the CPU port to
switch port 4, and then configures the external port mask according to
the switch model -- 3 ports for KSZ8794 and 4 for KSZ8795/KSZ8765.

Fixes: 68a1b676db52 ("net: dsa: microchip: ksz8795: remove superfluous port_cnt 
assignment")
Fixes: 4ce2a984abd8 ("net: dsa: microchip: ksz8795: use phy_port_cnt where 
possible")
Fixes: 241ed719bc98 ("net: dsa: microchip: ksz8795: use port_cnt instead of 
TOTOAL_PORT_NUM")
Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Michael Grzeschik 
Cc: Jakub Kicinski 
---
V2: - In case of KSZ8794, the DT node port@4 is the CPU port and
  port@3 should not be defined. Validate this condition in
  ksz_common.c
---
 drivers/net/dsa/microchip/ksz8795.c| 30 +-
 drivers/net/dsa/microchip/ksz_common.c |  2 +-
 2 files changed, 21 insertions(+), 11 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz8795.c 
b/drivers/net/dsa/microchip/ksz8795.c
index c973db101b72..a4570ba29c83 100644
--- a/drivers/net/dsa/microchip/ksz8795.c
+++ b/drivers/net/dsa/microchip/ksz8795.c
@@ -1187,6 +1187,20 @@ static const struct ksz_chip_data ksz8795_switch_chips[] 
= {
.port_cnt = 5,  /* total cpu and user ports */
},
{
+   /*
+* WARNING
+* ===
+* KSZ8794 is similar to KSZ8795, except the port map
+* contains a gap between external and CPU ports, the
+* port map is NOT continuous. The per-port register
+* map is shifted accordingly too, i.e. registers at
+* offset 0x40 are NOT used on KSZ8794 and they ARE
+* used on KSZ8795 for external port 3.
+*   external  cpu
+* KSZ8794   0,1,2  4
+* KSZ8795   0,1,2,34
+* KSZ8765   0,1,2,34
+*/
.chip_id = 0x8794,
.dev_name = "KSZ8794",
.num_vlans = 4096,
@@ -1220,9 +1234,13 @@ static int ksz8795_switch_init(struct ksz_device *dev)
dev->num_vlans = chip->num_vlans;
dev->num_alus = chip->num_alus;
dev->num_statics = chip->num_statics;
-   dev->port_cnt = chip->port_cnt;
+   dev->port_cnt = fls(chip->cpu_ports);
+   dev->cpu_port = fls(chip->cpu_ports) - 1;
+   dev->phy_port_cnt = dev->port_cnt - 1;
dev->cpu_ports = chip->cpu_ports;
-
+   dev->host_mask = chip->cpu_ports;
+   dev->port_mask = (BIT(dev->phy_port_cnt) - 1) |
+chip->cpu_ports;
break;
}
}
@@ -1231,17 +1249,9 @@ static int ksz8795_switch_init(struct ksz_device *dev)
if (!dev->cpu_ports)
return -ENODEV;
 
-   dev->port_mask = BIT(dev->port_cnt) - 1;
-   dev->port_mask |= dev->host_mask;
-
dev->reg_mib_cnt = KSZ8795_COUNTER_NUM;
dev->mib_cnt = ARRAY_SIZE(mib_names);
 
-   dev->phy_port_cnt = dev->port_cnt - 1;
-
-   dev->cpu_port = dev->port_cnt - 1;
-   dev->host_mask = BIT(dev->cpu_port);
-
dev->ports = devm_kzalloc(dev->dev,
  dev->port_cnt * sizeof(struct ksz_port),
  GFP_KERNEL);
diff --git a/drivers/net/dsa/microchip/ksz_common.c 
b/drivers/net/dsa/microchip/ksz_common.c
index a2aa83d82edd..9ab81f903606 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -434,7 +434,7 @@ int ksz_switch_register(struct ksz_device *dev,
if (of_property_read_u32(port, "reg",
 &port_num))
continue;
-   if (port_num >= dev->port_cnt)
+   if (!(dev->port_mask & BIT(port_num)))
return -EINVAL;
of_get_phy_mode(port,

&dev->ports[port_num].interface);
-- 
2.29.2



[PATCH net-next] net: dsa: microchip: Adjust reset release timing to match reference reset circuit

2021-01-19 Thread Marek Vasut
KSZ8794CNX datasheet section 8.0 RESET CIRCUIT describes recommended
circuit for interfacing with CPU/FPGA reset consisting of 10k pullup
resistor and 10uF capacitor to ground. This circuit takes ~100 mS to
rise enough to release the reset.

For maximum supply voltage VDDIO=3.3V VIH=2.0V R=10kR C=10uF that is
VDDIO - VIH
  t = R * C * -ln( - ) = 1*0.1*-(-0.93)=0.093 S
   VDDIO
so we need ~95 mS for the reset to really de-assert, and then the
original 100uS for the switch itself to come out of reset. Simply
msleep() for 100 mS which fits the constraint with a bit of extra
space.

Fixes: 5b797980908a ("net: dsa: microchip: Implement recommended reset timing")
Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Jakub Kicinski 
Cc: Michael Grzeschik 
Cc: Paul Barker 
---
 drivers/net/dsa/microchip/ksz_common.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/dsa/microchip/ksz_common.c 
b/drivers/net/dsa/microchip/ksz_common.c
index 489963664443..389abfd27770 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -400,7 +400,7 @@ int ksz_switch_register(struct ksz_device *dev,
gpiod_set_value_cansleep(dev->reset_gpio, 1);
usleep_range(1, 12000);
gpiod_set_value_cansleep(dev->reset_gpio, 0);
-   usleep_range(100, 1000);
+   msleep(100);
}
 
mutex_init(&dev->dev_mutex);
-- 
2.29.2



[PATCH net-next V2] net: dsa: microchip: Adjust reset release timing to match reference reset circuit

2021-01-19 Thread Marek Vasut
KSZ8794CNX datasheet section 8.0 RESET CIRCUIT describes recommended
circuit for interfacing with CPU/FPGA reset consisting of 10k pullup
resistor and 10uF capacitor to ground. This circuit takes ~100 ms to
rise enough to release the reset.

For maximum supply voltage VDDIO=3.3V VIH=2.0V R=10kR C=10uF that is
VDDIO - VIH
  t = R * C * -ln( - ) = 1*0.1*-(-0.93)=0.093 s
   VDDIO
so we need ~95 ms for the reset to really de-assert, and then the
original 100us for the switch itself to come out of reset. Simply
msleep() for 100 ms which fits the constraint with a bit of extra
space.

Fixes: 5b797980908a ("net: dsa: microchip: Implement recommended reset timing")
Reviewed-by: Florian Fainelli 
Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Jakub Kicinski 
Cc: Michael Grzeschik 
Cc: Paul Barker 
---
V2: Use lowercase 's' for second
---
 drivers/net/dsa/microchip/ksz_common.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/dsa/microchip/ksz_common.c 
b/drivers/net/dsa/microchip/ksz_common.c
index 489963664443..389abfd27770 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -400,7 +400,7 @@ int ksz_switch_register(struct ksz_device *dev,
gpiod_set_value_cansleep(dev->reset_gpio, 1);
usleep_range(1, 12000);
gpiod_set_value_cansleep(dev->reset_gpio, 0);
-   usleep_range(100, 1000);
+   msleep(100);
}
 
mutex_init(&dev->dev_mutex);
-- 
2.29.2



Re: [PATCH net-next V2] net: dsa: microchip: Adjust reset release timing to match reference reset circuit

2021-01-20 Thread Marek Vasut

On 1/21/21 2:31 AM, Jakub Kicinski wrote:

On Wed, 20 Jan 2021 04:05:02 +0100 Marek Vasut wrote:

KSZ8794CNX datasheet section 8.0 RESET CIRCUIT describes recommended
circuit for interfacing with CPU/FPGA reset consisting of 10k pullup
resistor and 10uF capacitor to ground. This circuit takes ~100 ms to
rise enough to release the reset.

For maximum supply voltage VDDIO=3.3V VIH=2.0V R=10kR C=10uF that is
 VDDIO - VIH
   t = R * C * -ln( - ) = 1*0.1*-(-0.93)=0.093 s
VDDIO
so we need ~95 ms for the reset to really de-assert, and then the
original 100us for the switch itself to come out of reset. Simply
msleep() for 100 ms which fits the constraint with a bit of extra
space.

Fixes: 5b797980908a ("net: dsa: microchip: Implement recommended reset timing")
Reviewed-by: Florian Fainelli 
Signed-off-by: Marek Vasut 


I'm slightly confused whether this is just future proofing or you
actually have a board where this matters. The tree is tagged as
net-next but there is a Fixes tag which normally indicates net+stable.


I have a board where I trigger this problem, that's how I found it. It 
should be passed to stable too. So the correct tree / tag is "net" ?


[PATCH 2/2] net: ks8851: Register MDIO bus and the internal PHY

2020-12-30 Thread Marek Vasut
The KS8851 has a reduced internal PHY, which is accessible through its
registers at offset 0xe4. The PHY is compatible with KS886x PHY present
in Micrel switches, except the PHY ID Low/High registers are swapped.
Register MDIO bus so this PHY can be detected and probed by phylib.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Heiner Kallweit 
Cc: Lukas Wunner 
To: netdev@vger.kernel.org
---
 drivers/net/ethernet/micrel/ks8851.h|  1 +
 drivers/net/ethernet/micrel/ks8851_common.c | 69 -
 2 files changed, 67 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/micrel/ks8851.h 
b/drivers/net/ethernet/micrel/ks8851.h
index 2b319e451121..9bed9e024d81 100644
--- a/drivers/net/ethernet/micrel/ks8851.h
+++ b/drivers/net/ethernet/micrel/ks8851.h
@@ -403,6 +403,7 @@ struct ks8851_net {
struct regulator*vdd_reg;
struct regulator*vdd_io;
int gpio;
+   struct mii_bus  *mii_bus;
 
void(*lock)(struct ks8851_net *ks,
unsigned long *flags);
diff --git a/drivers/net/ethernet/micrel/ks8851_common.c 
b/drivers/net/ethernet/micrel/ks8851_common.c
index 6fc7483aea03..c4f5cb9768ef 100644
--- a/drivers/net/ethernet/micrel/ks8851_common.c
+++ b/drivers/net/ethernet/micrel/ks8851_common.c
@@ -23,6 +23,7 @@
 
 #include 
 #include 
+#include 
 #include 
 
 #include "ks8851.h"
@@ -983,6 +984,24 @@ static void ks8851_phy_write(struct net_device *dev,
}
 }
 
+static int ks8851_mdio_read(struct mii_bus *bus, int phy_id, int reg)
+{
+   struct ks8851_net *ks = bus->priv;
+
+   if (phy_id != 0)
+   return 0x;
+
+   return ks8851_phy_read(ks->netdev, phy_id, reg);
+}
+
+static int ks8851_mdio_write(struct mii_bus *bus, int phy_id, int reg, u16 val)
+{
+   struct ks8851_net *ks = bus->priv;
+
+   ks8851_phy_write(ks->netdev, phy_id, reg, val);
+   return 0;
+}
+
 /**
  * ks8851_read_selftest - read the selftest memory info.
  * @ks: The device state
@@ -1046,6 +1065,42 @@ int ks8851_resume(struct device *dev)
 }
 #endif
 
+static int ks8851_register_mdiobus(struct ks8851_net *ks, struct device *dev)
+{
+   struct mii_bus *mii_bus;
+   int ret;
+
+   mii_bus = mdiobus_alloc();
+   if (!mii_bus)
+   return -ENOMEM;
+
+   mii_bus->name = "ks8851_eth_mii";
+   mii_bus->read = ks8851_mdio_read;
+   mii_bus->write = ks8851_mdio_write;
+   mii_bus->priv = ks;
+   mii_bus->parent = dev;
+   mii_bus->phy_mask = ~BIT(0);
+   snprintf(mii_bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev));
+
+   ret = mdiobus_register(mii_bus);
+   if (ret)
+   goto err_mdiobus_register;
+
+   ks->mii_bus = mii_bus;
+
+   return 0;
+
+err_mdiobus_register:
+   mdiobus_free(mii_bus);
+   return ret;
+}
+
+static void ks8851_unregister_mdiobus(struct ks8851_net *ks)
+{
+   mdiobus_unregister(ks->mii_bus);
+   mdiobus_free(ks->mii_bus);
+}
+
 int ks8851_probe_common(struct net_device *netdev, struct device *dev,
int msg_en)
 {
@@ -1104,6 +1159,8 @@ int ks8851_probe_common(struct net_device *netdev, struct 
device *dev,
 
INIT_WORK(&ks->rxctrl_work, ks8851_rxctrl_work);
 
+   SET_NETDEV_DEV(netdev, dev);
+
/* setup EEPROM state */
ks->eeprom.data = ks;
ks->eeprom.width = PCI_EEPROM_WIDTH_93C46;
@@ -1120,6 +1177,10 @@ int ks8851_probe_common(struct net_device *netdev, 
struct device *dev,
 
dev_info(dev, "message enable is %d\n", msg_en);
 
+   ret = ks8851_register_mdiobus(ks, dev);
+   if (ret)
+   goto err_mdio;
+
/* set the default message enable */
ks->msg_enable = netif_msg_init(msg_en, NETIF_MSG_DRV |
NETIF_MSG_PROBE |
@@ -1128,7 +1189,6 @@ int ks8851_probe_common(struct net_device *netdev, struct 
device *dev,
skb_queue_head_init(&ks->txq);
 
netdev->ethtool_ops = &ks8851_ethtool_ops;
-   SET_NETDEV_DEV(netdev, dev);
 
dev_set_drvdata(dev, ks);
 
@@ -1156,7 +1216,7 @@ int ks8851_probe_common(struct net_device *netdev, struct 
device *dev,
ret = register_netdev(netdev);
if (ret) {
dev_err(dev, "failed to register network device\n");
-   goto err_netdev;
+   goto err_id;
}
 
netdev_info(netdev, "revision %d, MAC %pM, IRQ %d, %s EEPROM\n",
@@ -1165,8 +1225,9 @@ int ks8851_probe_common(struct net_device *netdev, struct 
device *dev,
 
return 0;
 
-err_netdev:
 err_id:
+   ks8851_unregister_mdiobus(ks);
+err_mdio:
if (gpio_is_valid(gpio))
gpio_set_value(gpio, 0);
regulator_disable(ks->vdd_reg);
@@ -1180,6 +1241,8 @@ int 

[PATCH 1/2] net: phy: micrel: Add KS8851 PHY support

2020-12-30 Thread Marek Vasut
The KS8851 has a reduced internal PHY, which is accessible through its
registers at offset 0xe4. The PHY is compatible with KS886x PHY present
in Micrel switches, except the PHY ID Low/High registers are swapped.
Add PHY ID for this KS8851 PHY and use custom PHY ID mask due to the swap.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Heiner Kallweit 
Cc: Lukas Wunner 
To: netdev@vger.kernel.org
---
 drivers/net/phy/micrel.c   | 9 +
 include/linux/micrel_phy.h | 2 ++
 2 files changed, 11 insertions(+)

diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 54e0d75203da..ca6da128e37a 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -1386,6 +1386,14 @@ static struct phy_driver ksphy_driver[] = {
.read_status= ksz8873mll_read_status,
.suspend= genphy_suspend,
.resume = genphy_resume,
+}, {
+   .phy_id = PHY_ID_KSZ8851,
+   .phy_id_mask= 0xfff000ff,
+   .name   = "Micrel KSZ8851 Ethernet MAC",
+   /* PHY_BASIC_FEATURES */
+   .config_init= kszphy_config_init,
+   .suspend= genphy_suspend,
+   .resume = genphy_resume,
 }, {
.phy_id = PHY_ID_KSZ886X,
.phy_id_mask= MICREL_PHY_ID_MASK,
@@ -1432,6 +1440,7 @@ static struct mdio_device_id __maybe_unused micrel_tbl[] 
= {
{ PHY_ID_KSZ8061, MICREL_PHY_ID_MASK },
{ PHY_ID_KSZ8081, MICREL_PHY_ID_MASK },
{ PHY_ID_KSZ8873MLL, MICREL_PHY_ID_MASK },
+   { PHY_ID_KSZ8851, 0xfff000ff },
{ PHY_ID_KSZ886X, MICREL_PHY_ID_MASK },
{ PHY_ID_LAN8814, MICREL_PHY_ID_MASK },
{ }
diff --git a/include/linux/micrel_phy.h b/include/linux/micrel_phy.h
index 416ee6dd2574..1c26e4ac0dc9 100644
--- a/include/linux/micrel_phy.h
+++ b/include/linux/micrel_phy.h
@@ -29,6 +29,8 @@
 #define PHY_ID_KSZ9131 0x00221640
 #define PHY_ID_LAN8814 0x00221660
 
+/* The PHY ID Low/High registers are swapped on KSZ8851 */
+#define PHY_ID_KSZ8851 0x14300022
 #define PHY_ID_KSZ886X 0x00221430
 #define PHY_ID_KSZ8863 0x00221435
 
-- 
2.29.2



Re: [PATCH 1/2] net: phy: micrel: Add KS8851 PHY support

2021-01-03 Thread Marek Vasut

On 12/30/20 4:43 PM, Andrew Lunn wrote:

On Wed, Dec 30, 2020 at 01:53:57PM +0100, Marek Vasut wrote:

The KS8851 has a reduced internal PHY, which is accessible through its
registers at offset 0xe4. The PHY is compatible with KS886x PHY present
in Micrel switches, except the PHY ID Low/High registers are swapped.


Can you intercept the reads in the KS8851 driver and swap them back
again? The mv88e6xxx driver does something similar. The mv88e6393
family of switches have PHYs with the Marvell OUI but no device ID. So
the code traps these reads and provides an ID.


I would prefer to keep this as-is, since then the PHY driver can match 
on these swapped IDs and discern the PHY from PHY present in the KS886x 
switch.


Re: [PATCH 2/2] net: ks8851: Register MDIO bus and the internal PHY

2021-01-03 Thread Marek Vasut

On 12/30/20 5:00 PM, Andrew Lunn wrote:

+static int ks8851_mdio_read(struct mii_bus *bus, int phy_id, int reg)
+{
+   struct ks8851_net *ks = bus->priv;
+
+   if (phy_id != 0)
+   return 0x;
+


Please check for C45 and return -EOPNOTSUPP.


The ks8851_reg_read() does all the register checking already.


Re: [PATCH 1/2] net: phy: micrel: Add KS8851 PHY support

2021-01-03 Thread Marek Vasut

On 1/3/21 5:55 PM, Andrew Lunn wrote:

On Sun, Jan 03, 2021 at 01:55:22PM +0100, Marek Vasut wrote:

On 12/30/20 4:43 PM, Andrew Lunn wrote:

On Wed, Dec 30, 2020 at 01:53:57PM +0100, Marek Vasut wrote:

The KS8851 has a reduced internal PHY, which is accessible through its
registers at offset 0xe4. The PHY is compatible with KS886x PHY present
in Micrel switches, except the PHY ID Low/High registers are swapped.


Can you intercept the reads in the KS8851 driver and swap them back
again? The mv88e6xxx driver does something similar. The mv88e6393
family of switches have PHYs with the Marvell OUI but no device ID. So
the code traps these reads and provides an ID.


I would prefer to keep this as-is, since then the PHY driver can match on
these swapped IDs and discern the PHY from PHY present in the KS886x switch.


The problem is, this ID contains an OUI. Well, part of an OUI, the top
two bits of the OUI are removed, leaving 22 bits of a 24 bit
OUI. These OUIs are assigned to companies, well organisations. If you
look at the reversed PHY ID, what are the 4 possible OUIs? Who are
they assigned to? Are they ever likely to manufacture a PHY?


Are these OUIs used for anything else than identifying the PHY though ?


[PATCH V2 2/2] net: ks8851: Register MDIO bus and the internal PHY

2021-01-04 Thread Marek Vasut
The KS8851 has a reduced internal PHY, which is accessible through its
registers at offset 0xe4. The PHY is compatible with KS886x PHY present
in Micrel switches, except the PHY ID Low/High registers are swapped.
Register MDIO bus so this PHY can be detected and probed by phylib.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Heiner Kallweit 
Cc: Lukas Wunner 
To: netdev@vger.kernel.org
---
V2: - Cast the BIT(0) to u32 to avoid build warnings
- Swap PHY ID Hi/Lo registers for MDIO bus access
  (retain old behavior for MII bus access)
- Return -EOPNOTSUPP on read from nonexisting PHY registers
---
 drivers/net/ethernet/micrel/ks8851.h|   1 +
 drivers/net/ethernet/micrel/ks8851_common.c | 113 +---
 2 files changed, 98 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ethernet/micrel/ks8851.h 
b/drivers/net/ethernet/micrel/ks8851.h
index 2b319e451121..9bed9e024d81 100644
--- a/drivers/net/ethernet/micrel/ks8851.h
+++ b/drivers/net/ethernet/micrel/ks8851.h
@@ -403,6 +403,7 @@ struct ks8851_net {
struct regulator*vdd_reg;
struct regulator*vdd_io;
int gpio;
+   struct mii_bus  *mii_bus;
 
void(*lock)(struct ks8851_net *ks,
unsigned long *flags);
diff --git a/drivers/net/ethernet/micrel/ks8851_common.c 
b/drivers/net/ethernet/micrel/ks8851_common.c
index 6fc7483aea03..e0de9c4c98d1 100644
--- a/drivers/net/ethernet/micrel/ks8851_common.c
+++ b/drivers/net/ethernet/micrel/ks8851_common.c
@@ -23,6 +23,7 @@
 
 #include 
 #include 
+#include 
 #include 
 
 #include "ks8851.h"
@@ -932,7 +933,25 @@ static int ks8851_phy_reg(int reg)
return KS_P1ANLPR;
}
 
-   return 0x0;
+   return -EOPNOTSUPP;
+}
+
+static int ks8851_phy_read_common(struct net_device *dev, int phy_addr, int 
reg)
+{
+   struct ks8851_net *ks = netdev_priv(dev);
+   unsigned long flags;
+   int result;
+   int ksreg;
+
+   ksreg = ks8851_phy_reg(reg);
+   if (ksreg < 0)
+   return ksreg;
+
+   ks8851_lock(ks, &flags);
+   result = ks8851_rdreg16(ks, ksreg);
+   ks8851_unlock(ks, &flags);
+
+   return result;
 }
 
 /**
@@ -952,20 +971,13 @@ static int ks8851_phy_reg(int reg)
  */
 static int ks8851_phy_read(struct net_device *dev, int phy_addr, int reg)
 {
-   struct ks8851_net *ks = netdev_priv(dev);
-   unsigned long flags;
-   int ksreg;
-   int result;
+   int ret;
 
-   ksreg = ks8851_phy_reg(reg);
-   if (!ksreg)
+   ret = ks8851_phy_read_common(dev, phy_addr, reg);
+   if (ret < 0)
return 0x0; /* no error return allowed, so use zero */
 
-   ks8851_lock(ks, &flags);
-   result = ks8851_rdreg16(ks, ksreg);
-   ks8851_unlock(ks, &flags);
-
-   return result;
+   return ret;
 }
 
 static void ks8851_phy_write(struct net_device *dev,
@@ -976,13 +988,38 @@ static void ks8851_phy_write(struct net_device *dev,
int ksreg;
 
ksreg = ks8851_phy_reg(reg);
-   if (ksreg) {
+   if (ksreg >= 0) {
ks8851_lock(ks, &flags);
ks8851_wrreg16(ks, ksreg, value);
ks8851_unlock(ks, &flags);
}
 }
 
+static int ks8851_mdio_read(struct mii_bus *bus, int phy_id, int reg)
+{
+   struct ks8851_net *ks = bus->priv;
+   int ret;
+
+   if (phy_id != 0)
+   return -EOPNOTSUPP;
+
+   /* KS8851 PHY ID registers are swapped in HW, swap them back. */
+   if (reg == MII_PHYSID1)
+   reg = MII_PHYSID2;
+   else if (reg == MII_PHYSID2)
+   reg = MII_PHYSID1;
+
+   return ks8851_phy_read_common(ks->netdev, phy_id, reg);
+}
+
+static int ks8851_mdio_write(struct mii_bus *bus, int phy_id, int reg, u16 val)
+{
+   struct ks8851_net *ks = bus->priv;
+
+   ks8851_phy_write(ks->netdev, phy_id, reg, val);
+   return 0;
+}
+
 /**
  * ks8851_read_selftest - read the selftest memory info.
  * @ks: The device state
@@ -1046,6 +1083,42 @@ int ks8851_resume(struct device *dev)
 }
 #endif
 
+static int ks8851_register_mdiobus(struct ks8851_net *ks, struct device *dev)
+{
+   struct mii_bus *mii_bus;
+   int ret;
+
+   mii_bus = mdiobus_alloc();
+   if (!mii_bus)
+   return -ENOMEM;
+
+   mii_bus->name = "ks8851_eth_mii";
+   mii_bus->read = ks8851_mdio_read;
+   mii_bus->write = ks8851_mdio_write;
+   mii_bus->priv = ks;
+   mii_bus->parent = dev;
+   mii_bus->phy_mask = ~((u32)BIT(0));
+   snprintf(mii_bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev));
+
+   ret = mdiobus_register(mii_bus);
+   if (ret)
+   goto err_mdiobus_register;
+
+   ks->mii_bus = mii_bus;
+
+   return 0;
+
+err_mdiobus_register:
+   mdiobus_f

[PATCH V2 1/2] net: phy: micrel: Add KS8851 PHY support

2021-01-04 Thread Marek Vasut
The KS8851 has a reduced internal PHY, which is accessible through its
registers at offset 0xe4. The PHY is compatible with KS886x PHY present
in Micrel switches, including the PHY ID Low/High registers swap, which
is present both in the MAC and the switch.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Heiner Kallweit 
Cc: Lukas Wunner 
To: netdev@vger.kernel.org
---
V2: Merge the KSZ8851 and KS886X entries, as those PHYs cannot be discerned
---
 drivers/net/phy/micrel.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 54e0d75203da..39c7c786a912 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -1389,7 +1389,7 @@ static struct phy_driver ksphy_driver[] = {
 }, {
.phy_id = PHY_ID_KSZ886X,
.phy_id_mask= MICREL_PHY_ID_MASK,
-   .name   = "Micrel KSZ886X Switch",
+   .name   = "Micrel KSZ8851 Ethernet MAC or KSZ886X Switch",
/* PHY_BASIC_FEATURES */
.config_init= kszphy_config_init,
.suspend= genphy_suspend,
-- 
2.29.2



[PATCH net-next V3 0/2] net: ks8851: Add KS8851 PHY support

2021-01-05 Thread Marek Vasut
The KS8851 has a reduced internal PHY, which is accessible through its
registers at offset 0xe4. The PHY is compatible with KS886x PHY present
in Micrel switches, including the PHY ID Low/High registers swap, which
is present both in the MAC and the switch.

Marek Vasut (2):
  net: phy: micrel: Add KS8851 PHY support
  net: ks8851: Register MDIO bus and the internal PHY

 drivers/net/ethernet/micrel/ks8851.h|   2 +
 drivers/net/ethernet/micrel/ks8851_common.c | 112 +---
 drivers/net/phy/micrel.c|   2 +-
 3 files changed, 99 insertions(+), 17 deletions(-)

Cc: Andrew Lunn 
Cc: Heiner Kallweit 
Cc: Lukas Wunner 

-- 
2.29.2



[PATCH net-next V3 1/2] net: phy: micrel: Add KS8851 PHY support

2021-01-05 Thread Marek Vasut
The KS8851 has a reduced internal PHY, which is accessible through its
registers at offset 0xe4. The PHY is compatible with KS886x PHY present
in Micrel switches, including the PHY ID Low/High registers swap, which
is present both in the MAC and the switch.

Reviewed-by: Andrew Lunn 
Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Heiner Kallweit 
Cc: Lukas Wunner 
---
V2: Merge the KSZ8851 and KS886X entries, as those PHYs cannot be discerned
V3: Add RB from Andrew
---
 drivers/net/phy/micrel.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 54e0d75203da..39c7c786a912 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -1389,7 +1389,7 @@ static struct phy_driver ksphy_driver[] = {
 }, {
.phy_id = PHY_ID_KSZ886X,
.phy_id_mask= MICREL_PHY_ID_MASK,
-   .name   = "Micrel KSZ886X Switch",
+   .name   = "Micrel KSZ8851 Ethernet MAC or KSZ886X Switch",
/* PHY_BASIC_FEATURES */
.config_init= kszphy_config_init,
.suspend= genphy_suspend,
-- 
2.29.2



[PATCH net-next V3 2/2] net: ks8851: Register MDIO bus and the internal PHY

2021-01-05 Thread Marek Vasut
The KS8851 has a reduced internal PHY, which is accessible through its
registers at offset 0xe4. The PHY is compatible with KS886x PHY present
in Micrel switches, except the PHY ID Low/High registers are swapped.
Register MDIO bus so this PHY can be detected and probed by phylib.

Reviewed-by: Andrew Lunn 
Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Heiner Kallweit 
Cc: Lukas Wunner 
---
V2: - Cast the BIT(0) to u32 to avoid build warnings
- Swap PHY ID Hi/Lo registers for MDIO bus access
  (retain old behavior for MII bus access)
- Return -EOPNOTSUPP on read from nonexisting PHY registers
V3: - Add RB from Andrew
- Drop unused ret variable from ks8851_mdio_read()
- Document new mii_bus entry in ks8851_net {}
---
 drivers/net/ethernet/micrel/ks8851.h|   2 +
 drivers/net/ethernet/micrel/ks8851_common.c | 112 +---
 2 files changed, 98 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ethernet/micrel/ks8851.h 
b/drivers/net/ethernet/micrel/ks8851.h
index 2b319e451121..e2eb0caeac82 100644
--- a/drivers/net/ethernet/micrel/ks8851.h
+++ b/drivers/net/ethernet/micrel/ks8851.h
@@ -358,6 +358,7 @@ union ks8851_tx_hdr {
  * @vdd_reg:   Optional regulator supplying the chip
  * @vdd_io: Optional digital power supply for IO
  * @gpio: Optional reset_n gpio
+ * @mii_bus: Pointer to MII bus structure
  * @lock: Bus access lock callback
  * @unlock: Bus access unlock callback
  * @rdreg16: 16bit register read callback
@@ -403,6 +404,7 @@ struct ks8851_net {
struct regulator*vdd_reg;
struct regulator*vdd_io;
int gpio;
+   struct mii_bus  *mii_bus;
 
void(*lock)(struct ks8851_net *ks,
unsigned long *flags);
diff --git a/drivers/net/ethernet/micrel/ks8851_common.c 
b/drivers/net/ethernet/micrel/ks8851_common.c
index 6fc7483aea03..058fd99bd483 100644
--- a/drivers/net/ethernet/micrel/ks8851_common.c
+++ b/drivers/net/ethernet/micrel/ks8851_common.c
@@ -23,6 +23,7 @@
 
 #include 
 #include 
+#include 
 #include 
 
 #include "ks8851.h"
@@ -932,7 +933,25 @@ static int ks8851_phy_reg(int reg)
return KS_P1ANLPR;
}
 
-   return 0x0;
+   return -EOPNOTSUPP;
+}
+
+static int ks8851_phy_read_common(struct net_device *dev, int phy_addr, int 
reg)
+{
+   struct ks8851_net *ks = netdev_priv(dev);
+   unsigned long flags;
+   int result;
+   int ksreg;
+
+   ksreg = ks8851_phy_reg(reg);
+   if (ksreg < 0)
+   return ksreg;
+
+   ks8851_lock(ks, &flags);
+   result = ks8851_rdreg16(ks, ksreg);
+   ks8851_unlock(ks, &flags);
+
+   return result;
 }
 
 /**
@@ -952,20 +971,13 @@ static int ks8851_phy_reg(int reg)
  */
 static int ks8851_phy_read(struct net_device *dev, int phy_addr, int reg)
 {
-   struct ks8851_net *ks = netdev_priv(dev);
-   unsigned long flags;
-   int ksreg;
-   int result;
+   int ret;
 
-   ksreg = ks8851_phy_reg(reg);
-   if (!ksreg)
+   ret = ks8851_phy_read_common(dev, phy_addr, reg);
+   if (ret < 0)
return 0x0; /* no error return allowed, so use zero */
 
-   ks8851_lock(ks, &flags);
-   result = ks8851_rdreg16(ks, ksreg);
-   ks8851_unlock(ks, &flags);
-
-   return result;
+   return ret;
 }
 
 static void ks8851_phy_write(struct net_device *dev,
@@ -976,13 +988,37 @@ static void ks8851_phy_write(struct net_device *dev,
int ksreg;
 
ksreg = ks8851_phy_reg(reg);
-   if (ksreg) {
+   if (ksreg >= 0) {
ks8851_lock(ks, &flags);
ks8851_wrreg16(ks, ksreg, value);
ks8851_unlock(ks, &flags);
}
 }
 
+static int ks8851_mdio_read(struct mii_bus *bus, int phy_id, int reg)
+{
+   struct ks8851_net *ks = bus->priv;
+
+   if (phy_id != 0)
+   return -EOPNOTSUPP;
+
+   /* KS8851 PHY ID registers are swapped in HW, swap them back. */
+   if (reg == MII_PHYSID1)
+   reg = MII_PHYSID2;
+   else if (reg == MII_PHYSID2)
+   reg = MII_PHYSID1;
+
+   return ks8851_phy_read_common(ks->netdev, phy_id, reg);
+}
+
+static int ks8851_mdio_write(struct mii_bus *bus, int phy_id, int reg, u16 val)
+{
+   struct ks8851_net *ks = bus->priv;
+
+   ks8851_phy_write(ks->netdev, phy_id, reg, val);
+   return 0;
+}
+
 /**
  * ks8851_read_selftest - read the selftest memory info.
  * @ks: The device state
@@ -1046,6 +1082,42 @@ int ks8851_resume(struct device *dev)
 }
 #endif
 
+static int ks8851_register_mdiobus(struct ks8851_net *ks, struct device *dev)
+{
+   struct mii_bus *mii_bus;
+   int ret;
+
+   mii_bus = mdiobus_alloc();
+   if (!mii_bus)
+   return -ENOMEM;
+
+   mii_bus->name = "ks8851_eth_mii";
+   mii_bus->read = ks8851_mdio_read;

[PATCH] net: phy: Trigger link_change_notify on PHY_HALTED

2021-01-05 Thread Marek Vasut
In case the PHY transitions to PHY_HALTED state in phy_stop(), the
link_change_notify callback is not triggered. That's because the
phydev->state = PHY_HALTED in phy_stop() is assigned first, and
phy_state_machine() is called afterward. For phy_state_machine(),
no state transition happens, because old_state = PHY_HALTED and
phy_dev->state = PHY_HALTED.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: David S. Miller 
Cc: Heiner Kallweit 
---
 drivers/net/phy/phy.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 45f75533c47c..fca8c3eebc5d 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -1004,6 +1004,7 @@ EXPORT_SYMBOL(phy_free_interrupt);
 void phy_stop(struct phy_device *phydev)
 {
struct net_device *dev = phydev->attached_dev;
+   enum phy_state old_state;
 
if (!phy_is_started(phydev) && phydev->state != PHY_DOWN) {
WARN(1, "called from state %s\n",
@@ -1021,8 +1022,17 @@ void phy_stop(struct phy_device *phydev)
if (phydev->sfp_bus)
sfp_upstream_stop(phydev->sfp_bus);
 
+   old_state = phydev->state;
phydev->state = PHY_HALTED;
 
+   if (old_state != phydev->state) {
+   phydev_err(phydev, "PHY state change %s -> %s\n",
+  phy_state_to_str(old_state),
+  phy_state_to_str(phydev->state));
+   if (phydev->drv && phydev->drv->link_change_notify)
+   phydev->drv->link_change_notify(phydev);
+   }
+
mutex_unlock(&phydev->lock);
 
phy_state_machine(&phydev->state_queue.work);
-- 
2.29.2



[PATCH] [RFC] net: phy: smsc: Add magnetics VIO regulator support

2021-01-05 Thread Marek Vasut
Add support for controlling regulator powering the magnetics. In case
the interface is down, it is possible to save considerable power by
turning the regulator supplying the magnetics off.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: David S. Miller 
Cc: Heiner Kallweit 
---
 drivers/net/phy/smsc.c | 24 +++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
index 33372756a451..edc2bd7d8100 100644
--- a/drivers/net/phy/smsc.c
+++ b/drivers/net/phy/smsc.c
@@ -20,6 +20,9 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
 #include 
 
 /* Vendor-specific PHY Definitions */
@@ -46,6 +49,7 @@ static struct smsc_hw_stat smsc_hw_stats[] = {
 struct smsc_phy_priv {
bool energy_enable;
struct clk *refclk;
+   struct regulator *vddio;
 };
 
 static int smsc_phy_ack_interrupt(struct phy_device *phydev)
@@ -288,6 +292,20 @@ static void smsc_get_stats(struct phy_device *phydev,
data[i] = smsc_get_stat(phydev, i);
 }
 
+static void smsc_link_change_notify(struct phy_device *phydev)
+{
+   struct smsc_phy_priv *priv = phydev->priv;
+
+   if (!priv->vddio)
+   return;
+
+   if (phydev->state == PHY_HALTED)
+   regulator_disable(priv->vddio);
+
+   if (phydev->state == PHY_NOLINK)
+   regulator_enable(priv->vddio);
+}
+
 static void smsc_phy_remove(struct phy_device *phydev)
 {
struct smsc_phy_priv *priv = phydev->priv;
@@ -309,6 +327,10 @@ static int smsc_phy_probe(struct phy_device *phydev)
 
priv->energy_enable = true;
 
+   priv->vddio = devm_regulator_get_optional(&phydev->mdio.dev, "vddio");
+   if (IS_ERR(priv->vddio))
+   return PTR_ERR(priv->vddio);
+
if (of_property_read_bool(of_node, "smsc,disable-energy-detect"))
priv->energy_enable = false;
 
@@ -432,7 +454,7 @@ static struct phy_driver smsc_phy_driver[] = {
.name   = "SMSC LAN8710/LAN8720",
 
/* PHY_BASIC_FEATURES */
-
+   .link_change_notify = smsc_link_change_notify,
.probe  = smsc_phy_probe,
.remove = smsc_phy_remove,
 
-- 
2.29.2



Re: [PATCH] [RFC] net: phy: smsc: Add magnetics VIO regulator support

2021-01-05 Thread Marek Vasut

On 1/5/21 6:38 PM, Andrew Lunn wrote:

+static void smsc_link_change_notify(struct phy_device *phydev)
+{
+   struct smsc_phy_priv *priv = phydev->priv;
+
+   if (!priv->vddio)
+   return;
+
+   if (phydev->state == PHY_HALTED)
+   regulator_disable(priv->vddio);
+
+   if (phydev->state == PHY_NOLINK)
+   regulator_enable(priv->vddio);


NOLINK is an interesting choice. Could you explain that please.


It's the first state after interface is up.


I fear this is not going to be very robust to state machine
changes. And since it is hidden away in a driver, it is going to be
forgotten about. You might want to think about making it more robust.


I marked the patch as RFC because I would like input on how to implement 
this properly. Note that since the regulator supplies the magnetics, 
which might be shared between multiple ports with different PHYs, I 
don't think this code should even be in the PHY driver, but somewhere 
else -- but I don't know where.


Re: [PATCH] [RFC] net: phy: smsc: Add magnetics VIO regulator support

2021-01-05 Thread Marek Vasut

On 1/5/21 8:03 PM, Andrew Lunn wrote:

On Tue, Jan 05, 2021 at 06:53:48PM +0100, Marek Vasut wrote:

On 1/5/21 6:38 PM, Andrew Lunn wrote:

+static void smsc_link_change_notify(struct phy_device *phydev)
+{
+   struct smsc_phy_priv *priv = phydev->priv;
+
+   if (!priv->vddio)
+   return;
+
+   if (phydev->state == PHY_HALTED)
+   regulator_disable(priv->vddio);
+
+   if (phydev->state == PHY_NOLINK)
+   regulator_enable(priv->vddio);


NOLINK is an interesting choice. Could you explain that please.


It's the first state after interface is up.


No, not really. phy_start() actually sets it to PHY_UP. When the state
machine runs, it kicks off auto-neg and immediately reads the link
state. If the link is down, it transitions to PHY_NOLINK, at which
point this code will enable the regulator.


I fear this is not going to be very robust to state machine
changes. And since it is hidden away in a driver, it is going to be
forgotten about. You might want to think about making it more robust.


I marked the patch as RFC because I would like input on how to implement
this properly. Note that since the regulator supplies the magnetics, which
might be shared between multiple ports with different PHYs, I don't think
this code should even be in the PHY driver, but somewhere else -- but I
don't know where.


Being shared should not be a problem. The regulator API does reference
counting. Any one driver turning the regulator on will enable it. But
it will not be turned off until all the drivers disable it after
enabling it. But that also means you need to balance the calls to
regulator_enable() and regulator_disable().

If for whatever reason this function is called for PHY_HALTED more
times than for PHY_NOLINK, the counter can go negative, and bad things
would happen. So i would actually had a bool to smsc_phy_priv
indicating if the regulator has been enabled. And for each
phydev->state, decide if the regulator should be enabled, check if it
is enabled according to the bool, and enable it is not. Same with
states which indicate it should be disabled. The code is then not
dependent on specific transitions, but on actual states. That should
be more robust to changes.

You also need to think about this regulator being shared. Say some
other PHY has enabled the regulator. phy_start() might be able to skip
PHY_NOLINK state and so this PHY never calls regulator_enable(). If
that other PHY is then configured down, it will disable the regulator,
and this PHY looses link. That probably is enough for this PHY to
re-enable the regulator, but it is not ideal.


I think you are completely missing the point, the regulator is just an 
implementation detail. I am more interested in the implementation 
itself, which I suspect should not even be in the PHY driver, but rather 
somewhere closer to the core (where?), because the supply to magnetics 
is not part of the PHY, any PHY can be used with magnetics which need a 
regulator.


[PATCH net-next] net: ks8851: Select PHYLIB and MICREL_PHY in Kconfig

2021-01-11 Thread Marek Vasut
The PHYLIB must be selected to provide mdiobus_*() functions, and the
MICREL_PHY is necessary too, as that is the only possible PHY attached
to the KS8851 (it is the internal PHY).

Fixes: ef3631220d2b ("net: ks8851: Register MDIO bus and the internal PHY")
Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Heiner Kallweit 
Cc: Lukas Wunner 
---
 drivers/net/ethernet/micrel/Kconfig | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/ethernet/micrel/Kconfig 
b/drivers/net/ethernet/micrel/Kconfig
index 42bc014136fe..93df3049cdc0 100644
--- a/drivers/net/ethernet/micrel/Kconfig
+++ b/drivers/net/ethernet/micrel/Kconfig
@@ -31,6 +31,8 @@ config KS8851
select MII
select CRC32
select EEPROM_93CX6
+   select PHYLIB
+   select MICREL_PHY
help
  SPI driver for Micrel KS8851 SPI attached network chip.
 
@@ -40,6 +42,8 @@ config KS8851_MLL
select MII
select CRC32
select EEPROM_93CX6
+   select PHYLIB
+   select MICREL_PHY
help
  This platform driver is for Micrel KS8851 Address/data bus
  multiplexed network chip.
-- 
2.29.2



[PATCH net-next] net: ks8851: Connect and start/stop the internal PHY

2021-01-11 Thread Marek Vasut
Unless the internal PHY is connected and started, the phylib will not
poll the PHY for state and produce state updates. Connect the PHY and
start/stop it.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Heiner Kallweit 
Cc: Lukas Wunner 
---
 drivers/net/ethernet/micrel/ks8851.h|  2 ++
 drivers/net/ethernet/micrel/ks8851_common.c | 28 +
 2 files changed, 30 insertions(+)

diff --git a/drivers/net/ethernet/micrel/ks8851.h 
b/drivers/net/ethernet/micrel/ks8851.h
index e2eb0caeac82..ef13929036cf 100644
--- a/drivers/net/ethernet/micrel/ks8851.h
+++ b/drivers/net/ethernet/micrel/ks8851.h
@@ -359,6 +359,7 @@ union ks8851_tx_hdr {
  * @vdd_io: Optional digital power supply for IO
  * @gpio: Optional reset_n gpio
  * @mii_bus: Pointer to MII bus structure
+ * @phy_dev: Pointer to PHY device structure
  * @lock: Bus access lock callback
  * @unlock: Bus access unlock callback
  * @rdreg16: 16bit register read callback
@@ -405,6 +406,7 @@ struct ks8851_net {
struct regulator*vdd_io;
int gpio;
struct mii_bus  *mii_bus;
+   struct phy_device   *phy_dev;
 
void(*lock)(struct ks8851_net *ks,
unsigned long *flags);
diff --git a/drivers/net/ethernet/micrel/ks8851_common.c 
b/drivers/net/ethernet/micrel/ks8851_common.c
index 058fd99bd483..a3716fd2d858 100644
--- a/drivers/net/ethernet/micrel/ks8851_common.c
+++ b/drivers/net/ethernet/micrel/ks8851_common.c
@@ -432,6 +432,11 @@ static void ks8851_flush_tx_work(struct ks8851_net *ks)
ks->flush_tx_work(ks);
 }
 
+static void ks8851_handle_link_change(struct net_device *net)
+{
+   phy_print_status(net->phydev);
+}
+
 /**
  * ks8851_net_open - open network device
  * @dev: The network device being opened.
@@ -445,11 +450,22 @@ static int ks8851_net_open(struct net_device *dev)
unsigned long flags;
int ret;
 
+   ret = phy_connect_direct(ks->netdev, ks->phy_dev,
+&ks8851_handle_link_change,
+PHY_INTERFACE_MODE_INTERNAL);
+   if (ret) {
+   netdev_err(dev, "failed to attach PHY\n");
+   return ret;
+   }
+
+   phy_attached_info(ks->phy_dev);
+
ret = request_threaded_irq(dev->irq, NULL, ks8851_irq,
   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
   dev->name, ks);
if (ret < 0) {
netdev_err(dev, "failed to get irq\n");
+   phy_disconnect(ks->phy_dev);
return ret;
}
 
@@ -507,6 +523,7 @@ static int ks8851_net_open(struct net_device *dev)
netif_dbg(ks, ifup, ks->netdev, "network device up\n");
 
ks8851_unlock(ks, &flags);
+   phy_start(ks->phy_dev);
mii_check_link(&ks->mii);
return 0;
 }
@@ -528,6 +545,9 @@ static int ks8851_net_stop(struct net_device *dev)
 
netif_stop_queue(dev);
 
+   phy_stop(ks->phy_dev);
+   phy_disconnect(ks->phy_dev);
+
ks8851_lock(ks, &flags);
/* turn off the IRQs and ack any outstanding */
ks8851_wrreg16(ks, KS_IER, 0x);
@@ -1084,6 +1104,7 @@ int ks8851_resume(struct device *dev)
 
 static int ks8851_register_mdiobus(struct ks8851_net *ks, struct device *dev)
 {
+   struct phy_device *phy_dev;
struct mii_bus *mii_bus;
int ret;
 
@@ -1103,10 +1124,17 @@ static int ks8851_register_mdiobus(struct ks8851_net 
*ks, struct device *dev)
if (ret)
goto err_mdiobus_register;
 
+   phy_dev = phy_find_first(mii_bus);
+   if (!phy_dev)
+   goto err_find_phy;
+
ks->mii_bus = mii_bus;
+   ks->phy_dev = phy_dev;
 
return 0;
 
+err_find_phy:
+   mdiobus_unregister(mii_bus);
 err_mdiobus_register:
mdiobus_free(mii_bus);
return ret;
-- 
2.29.2



Re: [PATCH net-next] net: ks8851: Connect and start/stop the internal PHY

2021-01-11 Thread Marek Vasut

On 1/11/21 2:26 PM, Heiner Kallweit wrote:
[...]


LGTM. When having a brief look at the driver I stumbled across two things:

1. Do MAC/PHY support any pause mode? Then a call to
phy_support_(a)sym_pause() would be missing.


https://ww1.microchip.com/downloads/en/DeviceDoc/KSZ8851-16MLL-Single-Port-Ethernet-MAC-Controller-with-8-Bit-or-16-Bit-Non-PCI-Interface-DS2357B.pdf
page 64

https://www.mouser.com/datasheet/2/268/ksz8851-16mll_ds-776208.pdf
page 65

The later is more complete.

Apparently it does support pause.


2. Don't have the datasheet, but IRQ_LCI seems to be the link change
interrupt. So far it's ignored by the driver. You could configure
it and use phy_mac_interrupt() to operate the internal PHY in
interrupt mode.


That's only for link state change, shouldn't the PHY interrupt trigger 
on other things as well ?


Re: [PATCH net-next] net: ks8851: Connect and start/stop the internal PHY

2021-01-11 Thread Marek Vasut

On 1/11/21 2:50 PM, Heiner Kallweit wrote:

On 11.01.2021 14:38, Marek Vasut wrote:

On 1/11/21 2:26 PM, Heiner Kallweit wrote:
[...]


LGTM. When having a brief look at the driver I stumbled across two things:

1. Do MAC/PHY support any pause mode? Then a call to
     phy_support_(a)sym_pause() would be missing.


https://ww1.microchip.com/downloads/en/DeviceDoc/KSZ8851-16MLL-Single-Port-Ethernet-MAC-Controller-with-8-Bit-or-16-Bit-Non-PCI-Interface-DS2357B.pdf
page 64

https://www.mouser.com/datasheet/2/268/ksz8851-16mll_ds-776208.pdf
page 65

The later is more complete.

Apparently it does support pause.


Based on the datasheet, does it support sym or asym pause ?


2. Don't have the datasheet, but IRQ_LCI seems to be the link change
     interrupt. So far it's ignored by the driver. You could configure
     it and use phy_mac_interrupt() to operate the internal PHY in
     interrupt mode.


That's only for link state change, shouldn't the PHY interrupt trigger on other 
things as well ?


No, it's sufficient if the interrupt can signal link state change.
In r8169 I have exactly that case.


I'll do that in a subsequent patch, once I verify it works as it should.


[PATCH 1/2] rsi: Move card interrupt handling to RX thread

2020-11-03 Thread Marek Vasut
The interrupt handling of the RS911x is particularly heavy. For each RX
packet, the card does three SDIO transactions, one to read interrupt
status register, one to RX buffer length, one to read the RX packet(s).
This translates to ~330 uS per one cycle of interrupt handler. In case
there is more incoming traffic, this will be more.

The drivers/mmc/core/sdio_irq.c has the following comment, quote "Just
like traditional hard IRQ handlers, we expect SDIO IRQ handlers to be
quick and to the point, so that the holding of the host lock does not
cover too much work that doesn't require that lock to be held."

The RS911x interrupt handler does not fit that. This patch therefore
changes it such that the entire IRQ handler is moved to the RX thread
instead, and the interrupt handler only wakes the RX thread.

This is OK, because the interrupt handler only does things which can
also be done in the RX thread, that is, it checks for firmware loading
error(s), it checks buffer status, it checks whether a packet arrived
and if so, reads out the packet and passes it to network stack.

Moreover, this change permits removal of a code which allocated an
skbuff only to get 4-byte-aligned buffer, read up to 8kiB of data
into the skbuff, queue this skbuff into local private queue, then in
RX thread, this buffer is dequeued, the data in the skbuff as passed
to the RSI driver core, and the skbuff is deallocated. All this is
replaced by directly calling the RSI driver core with local buffer.

Signed-off-by: Marek Vasut 
Cc: Angus Ainslie 
Cc: David S. Miller 
Cc: Jakub Kicinski 
Cc: Kalle Valo 
Cc: Lee Jones 
Cc: Martin Kepplinger 
Cc: Sebastian Krzyszkowiak 
Cc: Siva Rebbagondla 
Cc: linux-wirel...@vger.kernel.org
Cc: netdev@vger.kernel.org
---
 drivers/net/wireless/rsi/rsi_91x_sdio.c |  6 +--
 drivers/net/wireless/rsi/rsi_91x_sdio_ops.c | 52 ++---
 drivers/net/wireless/rsi/rsi_sdio.h |  8 +---
 3 files changed, 15 insertions(+), 51 deletions(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c 
b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index 78ad605081ae..d81874eee4b3 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -153,9 +153,7 @@ static void rsi_handle_interrupt(struct sdio_func *function)
if (adapter->priv->fsm_state == FSM_FW_NOT_LOADED)
return;
 
-   dev->sdio_irq_task = current;
-   rsi_interrupt_handler(adapter);
-   dev->sdio_irq_task = NULL;
+   rsi_set_event(&dev->rx_thread.event);
 }
 
 /**
@@ -1058,8 +1056,6 @@ static int rsi_probe(struct sdio_func *pfunction,
rsi_dbg(ERR_ZONE, "%s: Unable to init rx thrd\n", __func__);
goto fail_kill_thread;
}
-   skb_queue_head_init(&sdev->rx_q.head);
-   sdev->rx_q.num_rx_pkts = 0;
 
sdio_claim_host(pfunction);
if (sdio_claim_irq(pfunction, rsi_handle_interrupt)) {
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c 
b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
index 7825c9a889d3..23e709aabd1f 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
@@ -60,39 +60,20 @@ int rsi_sdio_master_access_msword(struct rsi_hw *adapter, 
u16 ms_word)
return status;
 }
 
+static void rsi_rx_handler(struct rsi_hw *adapter);
+
 void rsi_sdio_rx_thread(struct rsi_common *common)
 {
struct rsi_hw *adapter = common->priv;
struct rsi_91x_sdiodev *sdev = adapter->rsi_dev;
-   struct sk_buff *skb;
-   int status;
 
do {
rsi_wait_event(&sdev->rx_thread.event, EVENT_WAIT_FOREVER);
rsi_reset_event(&sdev->rx_thread.event);
+   rsi_rx_handler(adapter);
+   } while (!atomic_read(&sdev->rx_thread.thread_done));
 
-   while (true) {
-   if (atomic_read(&sdev->rx_thread.thread_done))
-   goto out;
-
-   skb = skb_dequeue(&sdev->rx_q.head);
-   if (!skb)
-   break;
-   if (sdev->rx_q.num_rx_pkts > 0)
-   sdev->rx_q.num_rx_pkts--;
-   status = rsi_read_pkt(common, skb->data, skb->len);
-   if (status) {
-   rsi_dbg(ERR_ZONE, "Failed to read the 
packet\n");
-   dev_kfree_skb(skb);
-   break;
-   }
-   dev_kfree_skb(skb);
-   }
-   } while (1);
-
-out:
rsi_dbg(INFO_ZONE, "%s: Terminated SDIO RX thread\n", __func__);
-   skb_queue_purge(&sdev->rx_q.head);
atomic_inc(&sdev->rx_thread.thread_done);
complete_and_exit(&sdev->rx_thread.completion, 0);

[PATCH 2/2] rsi: Clean up loop in the interrupt handler

2020-11-03 Thread Marek Vasut
The inner do { ... } while loop is completely useless, all it does
is iterate over a switch-case statement, one bit at a time. This
can easily be replaced by simple if (status & bit) { ... } tests
for each bit. No functional change.

Signed-off-by: Marek Vasut 
Cc: Angus Ainslie 
Cc: David S. Miller 
Cc: Jakub Kicinski 
Cc: Kalle Valo 
Cc: Lee Jones 
Cc: Martin Kepplinger 
Cc: Sebastian Krzyszkowiak 
Cc: Siva Rebbagondla 
Cc: linux-wirel...@vger.kernel.org
Cc: netdev@vger.kernel.org
---
 drivers/net/wireless/rsi/rsi_91x_sdio_ops.c | 121 ++--
 1 file changed, 58 insertions(+), 63 deletions(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c 
b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
index 23e709aabd1f..8ace1874e5cb 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
@@ -236,7 +236,6 @@ static void rsi_rx_handler(struct rsi_hw *adapter)
struct rsi_91x_sdiodev *dev =
(struct rsi_91x_sdiodev *)adapter->rsi_dev;
int status;
-   enum sdio_interrupt_type isr_type;
u8 isr_status = 0;
u8 fw_status = 0;
 
@@ -267,73 +266,69 @@ static void rsi_rx_handler(struct rsi_hw *adapter)
__func__, isr_status, (1 << MSDU_PKT_PENDING),
(1 << FW_ASSERT_IND));
 
-   do {
-   RSI_GET_SDIO_INTERRUPT_TYPE(isr_status, isr_type);
-
-   switch (isr_type) {
-   case BUFFER_AVAILABLE:
-   status = rsi_sdio_check_buffer_status(adapter,
- 0);
-   if (status < 0)
-   rsi_dbg(ERR_ZONE,
-   "%s: Failed to check buffer 
status\n",
-   __func__);
-   rsi_sdio_ack_intr(common->priv,
- (1 << PKT_BUFF_AVAILABLE));
-   rsi_set_event(&common->tx_thread.event);
-
-   rsi_dbg(ISR_ZONE,
-   "%s: ==> BUFFER_AVAILABLE <==\n",
-   __func__);
-   dev->buff_status_updated = true;
-   break;
-
-   case FIRMWARE_ASSERT_IND:
+   if (isr_status & BIT(PKT_BUFF_AVAILABLE)) {
+   status = rsi_sdio_check_buffer_status(adapter, 0);
+   if (status < 0)
rsi_dbg(ERR_ZONE,
-   "%s: ==> FIRMWARE Assert <==\n",
+   "%s: Failed to check buffer status\n",
__func__);
-   status = rsi_sdio_read_register(common->priv,
+   rsi_sdio_ack_intr(common->priv,
+ BIT(PKT_BUFF_AVAILABLE));
+   rsi_set_event(&common->tx_thread.event);
+
+   rsi_dbg(ISR_ZONE, "%s: ==> BUFFER_AVAILABLE <==\n",
+   __func__);
+   dev->buff_status_updated = true;
+
+   isr_status &= ~BIT(PKT_BUFF_AVAILABLE);
+   }
+
+   if (isr_status & BIT(FW_ASSERT_IND)) {
+   rsi_dbg(ERR_ZONE, "%s: ==> FIRMWARE Assert <==\n",
+   __func__);
+   status = rsi_sdio_read_register(common->priv,
SDIO_FW_STATUS_REG,
&fw_status);
-   if (status) {
-   rsi_dbg(ERR_ZONE,
-   "%s: Failed to read f/w reg\n",
-   __func__);
-   } else {
-   rsi_dbg(ERR_ZONE,
-   "%s: Firmware Status is 0x%x\n",
-   __func__ , fw_status);
-   rsi_sdio_ack_intr(common->priv,
- (1 << FW_ASSERT_IND));
-   }
-
-   common->fsm_state = FSM_CARD_NOT_READY;
-   break;
-
-   case MSDU_PACKET_PENDING:
-   rsi_dbg(ISR_ZONE, "Pkt pending interrupt\n");
-   d

Re: [PATCH 1/2] rsi: Move card interrupt handling to RX thread

2020-11-04 Thread Marek Vasut

On 11/4/20 4:21 PM, Martin Kepplinger wrote:

On 03.11.20 19:09, Marek Vasut wrote:

The interrupt handling of the RS911x is particularly heavy. For each RX
packet, the card does three SDIO transactions, one to read interrupt
status register, one to RX buffer length, one to read the RX packet(s).
This translates to ~330 uS per one cycle of interrupt handler. In case
there is more incoming traffic, this will be more.

The drivers/mmc/core/sdio_irq.c has the following comment, quote "Just
like traditional hard IRQ handlers, we expect SDIO IRQ handlers to be
quick and to the point, so that the holding of the host lock does not
cover too much work that doesn't require that lock to be held."

The RS911x interrupt handler does not fit that. This patch therefore
changes it such that the entire IRQ handler is moved to the RX thread
instead, and the interrupt handler only wakes the RX thread.

This is OK, because the interrupt handler only does things which can
also be done in the RX thread, that is, it checks for firmware loading
error(s), it checks buffer status, it checks whether a packet arrived
and if so, reads out the packet and passes it to network stack.

Moreover, this change permits removal of a code which allocated an
skbuff only to get 4-byte-aligned buffer, read up to 8kiB of data
into the skbuff, queue this skbuff into local private queue, then in
RX thread, this buffer is dequeued, the data in the skbuff as passed
to the RSI driver core, and the skbuff is deallocated. All this is
replaced by directly calling the RSI driver core with local buffer.

Signed-off-by: Marek Vasut 
Cc: Angus Ainslie 
Cc: David S. Miller 
Cc: Jakub Kicinski 
Cc: Kalle Valo 
Cc: Lee Jones 
Cc: Martin Kepplinger 
Cc: Sebastian Krzyszkowiak 
Cc: Siva Rebbagondla 
Cc: linux-wirel...@vger.kernel.org
Cc: netdev@vger.kernel.org
---
  drivers/net/wireless/rsi/rsi_91x_sdio.c |  6 +--
  drivers/net/wireless/rsi/rsi_91x_sdio_ops.c | 52 ++---
  drivers/net/wireless/rsi/rsi_sdio.h |  8 +---
  3 files changed, 15 insertions(+), 51 deletions(-)



hi Marek,


Hi,


I'm running this without problems, so feel free to add

Tested-by: Martin Kepplinger 


Thank you.

Do you observe better RX performance ? For me, without this patch, 
iperf3 -R did ~4 Mbit/s on iwlwifi AP running hostap in 802.11n mode 
(wpa2 tkip), with this patch I see 40 Mbit/s (10x better, yes). However, 
the poor rx performance did depend on the kernel configuration (HZ, 
preemption settings) before, now it does not.


[PATCH] rsi: Use resume_noirq for SDIO

2021-03-27 Thread Marek Vasut
The rsi_resume() does access the bus to enable interrupts on the RSI
SDIO WiFi card, however when calling sdio_claim_host() in the resume
path, it is possible the bus is already claimed and sdio_claim_host()
spins indefinitelly. Enable the SDIO card interrupts in resume_noirq
instead to prevent anything else from claiming the SDIO bus first.

Fixes: 20db07332736 ("rsi: sdio suspend and resume support")
Signed-off-by: Marek Vasut 
Cc: Amitkumar Karwar 
Cc: Angus Ainslie 
Cc: David S. Miller 
Cc: Jakub Kicinski 
Cc: Kalle Valo 
Cc: Karun Eagalapati 
Cc: Martin Kepplinger 
Cc: Sebastian Krzyszkowiak 
Cc: Siva Rebbagondla 
Cc: netdev@vger.kernel.org
Cc: sta...@vger.kernel.org
---
 drivers/net/wireless/rsi/rsi_91x_sdio.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c 
b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index 122174fca672..8465a4ee9b61 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -1513,7 +1513,7 @@ static int rsi_restore(struct device *dev)
 }
 static const struct dev_pm_ops rsi_pm_ops = {
.suspend = rsi_suspend,
-   .resume = rsi_resume,
+   .resume_noirq = rsi_resume,
.freeze = rsi_freeze,
.thaw = rsi_thaw,
.restore = rsi_restore,
-- 
2.30.2



Re: [PATCH] [5.8 regression] net: ks8851: fix link error

2021-01-26 Thread Marek Vasut

On 1/25/21 1:19 PM, Arnd Bergmann wrote:

From: Arnd Bergmann 

An object file cannot be built for both loadable module and built-in
use at the same time:

arm-linux-gnueabi-ld: drivers/net/ethernet/micrel/ks8851_common.o: in function 
`ks8851_probe_common':
ks8851_common.c:(.text+0xf80): undefined reference to `__this_module'

Change the ks8851_common code to be a standalone module instead,
and use Makefile logic to ensure this is built-in if at least one
of its two users is.

Fixes: 797047f875b5 ("net: ks8851: Implement Parallel bus operations")
Signed-off-by: Arnd Bergmann 
---
Marek sent two other patches to address the problem:
https://lore.kernel.org/netdev/20210116164828.40545-1-ma...@denx.de/
https://lore.kernel.org/netdev/20210115134239.126152-1-ma...@denx.de/

My version is what I applied locally to my randconfig tree, and
I think this is the cleanest solution.


If this version works for all the configuration combinations, then 
that's perfect, thanks.


Re: [PATCH AUTOSEL 5.10 050/217] rsi: Fix TX EAPOL packet handling against iwlwifi AP

2021-03-02 Thread Marek Vasut

On 12/23/20 3:13 AM, Sasha Levin wrote:

Hello Sasha,


From: Marek Vasut 

[ Upstream commit 65277100caa2f2c62b6f3c4648b90d6f0435f3bc ]

In case RSI9116 SDIO WiFi operates in STA mode against Intel 9260 in AP mode,
the association fails. The former is using wpa_supplicant during association,
the later is set up using hostapd:


[...]

Was this patch possibly missed from 5.10.y ?

Also, while at it, I think it might make sense to pick the following two 
patches as well, they dramatically reduce interrupt rate of the RSI WiFi 
device, so it stops overloading lower-end devices:

287431463e786 ("rsi: Move card interrupt handling to RX thread")
abd131a19f6b8 ("rsi: Clean up loop in the interrupt handler")


Re: [PATCH AUTOSEL 5.10 050/217] rsi: Fix TX EAPOL packet handling against iwlwifi AP

2021-03-04 Thread Marek Vasut

On 3/4/21 9:47 PM, Sasha Levin wrote:

On Tue, Mar 02, 2021 at 08:25:49PM +0100, Marek Vasut wrote:

On 12/23/20 3:13 AM, Sasha Levin wrote:

Hello Sasha,


From: Marek Vasut 

[ Upstream commit 65277100caa2f2c62b6f3c4648b90d6f0435f3bc ]

In case RSI9116 SDIO WiFi operates in STA mode against Intel 9260 in 
AP mode,
the association fails. The former is using wpa_supplicant during 
association,

the later is set up using hostapd:


[...]

Was this patch possibly missed from 5.10.y ?


I'm not sure what happened there, but I can queue it up.


Thank you

Also, while at it, I think it might make sense to pick the following 
two patches as well, they dramatically reduce interrupt rate of the 
RSI WiFi device, so it stops overloading lower-end devices:

287431463e786 ("rsi: Move card interrupt handling to RX thread")


And this one too.


Thanks


abd131a19f6b8 ("rsi: Clean up loop in the interrupt handler")


But not this one, it looks like just a cleanup. Why is it needed?


Now I got confused, yes, please skip abd131a19f6b8, thanks for spotting 
it. (I still have one more patch for the RSI wifi which I need to send 
out, but that's for later)


[PATCH] net: dsa: microchip: Use gpiod_set_value_cansleep()

2019-06-23 Thread Marek Vasut
Replace gpiod_set_value() with gpiod_set_value_cansleep(), as the switch
reset GPIO can be connected to e.g. I2C GPIO expander and it is perfectly
fine for the kernel to sleep for a bit in ksz_switch_register().

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Linus Walleij 
Cc: Tristram Ha 
Cc: Woojung Huh 
---
 drivers/net/dsa/microchip/ksz_common.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz_common.c 
b/drivers/net/dsa/microchip/ksz_common.c
index 4f6648d5ac8b..bc81806dd75e 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -436,9 +436,9 @@ int ksz_switch_register(struct ksz_device *dev,
return PTR_ERR(dev->reset_gpio);
 
if (dev->reset_gpio) {
-   gpiod_set_value(dev->reset_gpio, 1);
+   gpiod_set_value_cansleep(dev->reset_gpio, 1);
mdelay(10);
-   gpiod_set_value(dev->reset_gpio, 0);
+   gpiod_set_value_cansleep(dev->reset_gpio, 0);
}
 
mutex_init(&dev->dev_mutex);
-- 
2.20.1



[PATCH] net: ethernet: ti: cpsw: Assign OF node to slave devices

2019-06-23 Thread Marek Vasut
Assign OF node to CPSW slave devices, otherwise it is not possible to
bind e.g. DSA switch to them. Without this patch, the DSA code tries
to find the ethernet device by OF match, but fails to do so because
the slave device has NULL OF node.

Signed-off-by: Marek Vasut 
Cc: David S. Miller 
Cc: Ivan Khoronzhuk 
---
 drivers/net/ethernet/ti/cpsw.c  | 3 +++
 drivers/net/ethernet/ti/cpsw_priv.h | 1 +
 2 files changed, 4 insertions(+)

diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 7bdd287074fc..c39790e21276 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -2179,6 +2179,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
return ret;
}
 
+   slave_data->slave_node = slave_node;
slave_data->phy_node = of_parse_phandle(slave_node,
"phy-handle", 0);
parp = of_get_property(slave_node, "phy_id", &lenp);
@@ -2329,6 +2330,7 @@ static int cpsw_probe_dual_emac(struct cpsw_priv *priv)
 
/* register the network device */
SET_NETDEV_DEV(ndev, cpsw->dev);
+   ndev->dev.of_node = cpsw->slaves[1].data->slave_node;
ret = register_netdev(ndev);
if (ret)
dev_err(cpsw->dev, "cpsw: error registering net device\n");
@@ -2506,6 +2508,7 @@ static int cpsw_probe(struct platform_device *pdev)
 
/* register the network device */
SET_NETDEV_DEV(ndev, dev);
+   ndev->dev.of_node = cpsw->slaves[0].data->slave_node;
ret = register_netdev(ndev);
if (ret) {
dev_err(dev, "error registering net device\n");
diff --git a/drivers/net/ethernet/ti/cpsw_priv.h 
b/drivers/net/ethernet/ti/cpsw_priv.h
index 04795b97ee71..e32f11da2dce 100644
--- a/drivers/net/ethernet/ti/cpsw_priv.h
+++ b/drivers/net/ethernet/ti/cpsw_priv.h
@@ -272,6 +272,7 @@ struct cpsw_host_regs {
 };
 
 struct cpsw_slave_data {
+   struct device_node *slave_node;
struct device_node *phy_node;
charphy_id[MII_BUS_ID_SIZE];
int phy_if;
-- 
2.20.1



Re: [PATCH] net: dsa: microchip: Use gpiod_set_value_cansleep()

2019-06-23 Thread Marek Vasut
On 6/23/19 5:09 PM, Andrew Lunn wrote:
> On Sun, Jun 23, 2019 at 02:10:36PM +0200, Marek Vasut wrote:
>> Replace gpiod_set_value() with gpiod_set_value_cansleep(), as the switch
>> reset GPIO can be connected to e.g. I2C GPIO expander and it is perfectly
>> fine for the kernel to sleep for a bit in ksz_switch_register().
>>
>> Signed-off-by: Marek Vasut 
> 
> Reviewed-by: Andrew Lunn 

Actually, no, I missed a change in .remove , so I'll send a V2 with this
RB if you don't mind.

-- 
Best regards,
Marek Vasut


[PATCH V2] net: dsa: microchip: Use gpiod_set_value_cansleep()

2019-06-23 Thread Marek Vasut
Replace gpiod_set_value() with gpiod_set_value_cansleep(), as the switch
reset GPIO can be connected to e.g. I2C GPIO expander and it is perfectly
fine for the kernel to sleep for a bit in ksz_switch_register().

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Linus Walleij 
Cc: Tristram Ha 
Cc: Woojung Huh 
Reviewed-by: Andrew Lunn 
---
V2: use _cansleep in .remove as well
---
 drivers/net/dsa/microchip/ksz_common.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz_common.c 
b/drivers/net/dsa/microchip/ksz_common.c
index 4f6648d5ac8b..978c59aa8efb 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -436,9 +436,9 @@ int ksz_switch_register(struct ksz_device *dev,
return PTR_ERR(dev->reset_gpio);
 
if (dev->reset_gpio) {
-   gpiod_set_value(dev->reset_gpio, 1);
+   gpiod_set_value_cansleep(dev->reset_gpio, 1);
mdelay(10);
-   gpiod_set_value(dev->reset_gpio, 0);
+   gpiod_set_value_cansleep(dev->reset_gpio, 0);
}
 
mutex_init(&dev->dev_mutex);
@@ -489,7 +489,7 @@ void ksz_switch_remove(struct ksz_device *dev)
dsa_unregister_switch(dev->ds);
 
if (dev->reset_gpio)
-   gpiod_set_value(dev->reset_gpio, 1);
+   gpiod_set_value_cansleep(dev->reset_gpio, 1);
 
 }
 EXPORT_SYMBOL(ksz_switch_remove);
-- 
2.20.1



[PATCH V3 06/10] net: dsa: microchip: Factor out register access opcode generation

2019-06-23 Thread Marek Vasut
Factor out the code which sends out the register read/write opcodes
to the switch, since the code differs in single bit between read and
write.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Woojung Huh 
---
V2: New patch
V3: - Rebase on next/master
- Test on KSZ9477EVB
---
 drivers/net/dsa/microchip/ksz9477_spi.c | 22 --
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c 
b/drivers/net/dsa/microchip/ksz9477_spi.c
index a34e66eccbcd..49aeb92d36fc 100644
--- a/drivers/net/dsa/microchip/ksz9477_spi.c
+++ b/drivers/net/dsa/microchip/ksz9477_spi.c
@@ -25,19 +25,24 @@
 /* Enough to read all switch port registers. */
 #define SPI_TX_BUF_LEN 0x100
 
-static int ksz9477_spi_read_reg(struct spi_device *spi, u32 reg, u8 *val,
-   unsigned int len)
+static u32 ksz9477_spi_cmd(u32 reg, bool read)
 {
u32 txbuf;
-   int ret;
 
txbuf = reg & SPI_ADDR_MASK;
-   txbuf |= KS_SPIOP_RD << SPI_ADDR_SHIFT;
+   txbuf |= (read ? KS_SPIOP_RD : KS_SPIOP_WR) << SPI_ADDR_SHIFT;
txbuf <<= SPI_TURNAROUND_SHIFT;
txbuf = cpu_to_be32(txbuf);
 
-   ret = spi_write_then_read(spi, &txbuf, 4, val, len);
-   return ret;
+   return txbuf;
+}
+
+static int ksz9477_spi_read_reg(struct spi_device *spi, u32 reg, u8 *val,
+   unsigned int len)
+{
+   u32 txbuf = ksz9477_spi_cmd(reg, true);
+
+   return spi_write_then_read(spi, &txbuf, 4, val, len);
 }
 
 static int ksz9477_spi_write_reg(struct spi_device *spi, u32 reg, u8 *val,
@@ -45,10 +50,7 @@ static int ksz9477_spi_write_reg(struct spi_device *spi, u32 
reg, u8 *val,
 {
u32 *txbuf = (u32 *)val;
 
-   *txbuf = reg & SPI_ADDR_MASK;
-   *txbuf |= (KS_SPIOP_WR << SPI_ADDR_SHIFT);
-   *txbuf <<= SPI_TURNAROUND_SHIFT;
-   *txbuf = cpu_to_be32(*txbuf);
+   *txbuf = ksz9477_spi_cmd(reg, false);
 
return spi_write(spi, txbuf, 4 + len);
 }
-- 
2.20.1



[PATCH V3 09/10] net: dsa: microchip: Factor out regmap config generation into common header

2019-06-23 Thread Marek Vasut
The regmap config tables are rather similar for various generations of
the KSZ8xxx/KSZ9xxx switches. Introduce a macro which allows generating
those tables without duplication. Note that $regalign parameter is not
used right now, but will be used in KSZ87xx series switches.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Woojung Huh 
---
V2: New patch
V3: - Rebase on next/master
- Test on KSZ9477EVB
- Increase regmap max register, to cover all switch registers
- Make register swabbing configurable, to allow handling switches
  with only 16bit registers as well as switches with some 32bit ones
---
 drivers/net/dsa/microchip/ksz9477_spi.c | 29 +++---
 drivers/net/dsa/microchip/ksz_common.h  | 32 +
 2 files changed, 35 insertions(+), 26 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c 
b/drivers/net/dsa/microchip/ksz9477_spi.c
index 8c8bf3237013..5a9e27b337a8 100644
--- a/drivers/net/dsa/microchip/ksz9477_spi.c
+++ b/drivers/net/dsa/microchip/ksz9477_spi.c
@@ -14,37 +14,14 @@
 #include 
 
 #include "ksz_priv.h"
+#include "ksz_common.h"
 
 #define SPI_ADDR_SHIFT 24
 #define SPI_ADDR_ALIGN 3
 #define SPI_TURNAROUND_SHIFT   5
 
-/* SPI frame opcodes */
-#define KS_SPIOP_RD3
-#define KS_SPIOP_WR2
-
-#define KS_SPIOP_FLAG_MASK(opcode) \
-   cpu_to_be32((opcode) << (SPI_ADDR_SHIFT + SPI_TURNAROUND_SHIFT))
-
-#define KSZ_REGMAP_COMMON(width)   \
-   {   \
-   .val_bits = (width),\
-   .reg_stride = (width) / 8,  \
-   .reg_bits = SPI_ADDR_SHIFT + SPI_ADDR_ALIGN,\
-   .pad_bits = SPI_TURNAROUND_SHIFT,   \
-   .max_register = BIT(SPI_ADDR_SHIFT) - 1,\
-   .cache_type = REGCACHE_NONE,\
-   .read_flag_mask = KS_SPIOP_FLAG_MASK(KS_SPIOP_RD),  \
-   .write_flag_mask = KS_SPIOP_FLAG_MASK(KS_SPIOP_WR), \
-   .reg_format_endian = REGMAP_ENDIAN_BIG, \
-   .val_format_endian = REGMAP_ENDIAN_BIG  \
-   }
-
-static const struct regmap_config ksz9477_regmap_config[] = {
-   KSZ_REGMAP_COMMON(8),
-   KSZ_REGMAP_COMMON(16),
-   KSZ_REGMAP_COMMON(32),
-};
+KSZ_REGMAP_TABLE(ksz9477, 32, SPI_ADDR_SHIFT,
+SPI_TURNAROUND_SHIFT, SPI_ADDR_ALIGN);
 
 static int ksz9477_spi_probe(struct spi_device *spi)
 {
diff --git a/drivers/net/dsa/microchip/ksz_common.h 
b/drivers/net/dsa/microchip/ksz_common.h
index c3871ed9b097..78b5ab7db403 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -133,4 +133,36 @@ static inline u32 ksz_pread32_poll(struct ksz_poll_ctx 
*ctx)
return data;
 }
 
+/* Regmap tables generation */
+#define KSZ_SPI_OP_RD  3
+#define KSZ_SPI_OP_WR  2
+
+#define KSZ_SPI_OP_FLAG_MASK(opcode, swp, regbits, regpad) \
+   cpu_to_be##swp((opcode) << ((regbits) + (regpad)))
+
+#define KSZ_REGMAP_ENTRY(width, swp, regbits, regpad, regalign)
\
+   {   \
+   .val_bits = (width),\
+   .reg_stride = (width) / 8,  \
+   .reg_bits = (regbits) + (regalign), \
+   .pad_bits = (regpad),   \
+   .max_register = BIT(regbits) - 1,   \
+   .cache_type = REGCACHE_NONE,\
+   .read_flag_mask =   \
+   KSZ_SPI_OP_FLAG_MASK(KSZ_SPI_OP_RD, swp,\
+regbits, regpad),  \
+   .write_flag_mask =  \
+   KSZ_SPI_OP_FLAG_MASK(KSZ_SPI_OP_WR, swp,\
+regbits, regpad),  \
+   .reg_format_endian = REGMAP_ENDIAN_BIG, \
+   .val_format_endian = REGMAP_ENDIAN_BIG  \
+   }
+
+#define KSZ_REGMAP_TABLE(ksz, swp, regbits, regpad, regalign)  \
+   static const struct regmap_config ksz##_regmap_config[] = { \
+   KSZ_REGMAP_ENTRY(8, swp, (regbits), (regpad), (regalign)), \
+   KSZ_REGMAP_ENTRY(16, swp, (regbits), (regpad), (regalign)), \
+   KSZ_REGMAP_ENTRY(32, swp, (regbits), (regpad), (regalign)), \
+   }
+
 #endif
-- 
2.20.1



[PATCH V3 01/10] net: dsa: microchip: Remove ksz_{read,write}24()

2019-06-23 Thread Marek Vasut
These functions and callbacks are never used, remove them.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Woojung Huh 
---
V2: No change
V3: - Rebase on next/master
- Test on KSZ9477EVB
---
 drivers/net/dsa/microchip/ksz9477_spi.c | 25 -
 drivers/net/dsa/microchip/ksz_common.h  | 22 --
 drivers/net/dsa/microchip/ksz_priv.h|  2 --
 3 files changed, 49 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c 
b/drivers/net/dsa/microchip/ksz9477_spi.c
index 75178624d3f5..e7118319c192 100644
--- a/drivers/net/dsa/microchip/ksz9477_spi.c
+++ b/drivers/net/dsa/microchip/ksz9477_spi.c
@@ -73,37 +73,12 @@ static int ksz_spi_write(struct ksz_device *dev, u32 reg, 
void *data,
return ksz9477_spi_write_reg(spi, reg, dev->txbuf, len);
 }
 
-static int ksz_spi_read24(struct ksz_device *dev, u32 reg, u32 *val)
-{
-   int ret;
-
-   *val = 0;
-   ret = ksz_spi_read(dev, reg, (u8 *)val, 3);
-   if (!ret) {
-   *val = be32_to_cpu(*val);
-   /* convert to 24bit */
-   *val >>= 8;
-   }
-
-   return ret;
-}
-
-static int ksz_spi_write24(struct ksz_device *dev, u32 reg, u32 value)
-{
-   /* make it to big endian 24bit from MSB */
-   value <<= 8;
-   value = cpu_to_be32(value);
-   return ksz_spi_write(dev, reg, &value, 3);
-}
-
 static const struct ksz_io_ops ksz9477_spi_ops = {
.read8 = ksz_spi_read8,
.read16 = ksz_spi_read16,
-   .read24 = ksz_spi_read24,
.read32 = ksz_spi_read32,
.write8 = ksz_spi_write8,
.write16 = ksz_spi_write16,
-   .write24 = ksz_spi_write24,
.write32 = ksz_spi_write32,
.get = ksz_spi_get,
.set = ksz_spi_set,
diff --git a/drivers/net/dsa/microchip/ksz_common.h 
b/drivers/net/dsa/microchip/ksz_common.h
index 21cd794e18f1..1781539c3a81 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -61,17 +61,6 @@ static inline int ksz_read16(struct ksz_device *dev, u32 
reg, u16 *val)
return ret;
 }
 
-static inline int ksz_read24(struct ksz_device *dev, u32 reg, u32 *val)
-{
-   int ret;
-
-   mutex_lock(&dev->reg_mutex);
-   ret = dev->ops->read24(dev, reg, val);
-   mutex_unlock(&dev->reg_mutex);
-
-   return ret;
-}
-
 static inline int ksz_read32(struct ksz_device *dev, u32 reg, u32 *val)
 {
int ret;
@@ -105,17 +94,6 @@ static inline int ksz_write16(struct ksz_device *dev, u32 
reg, u16 value)
return ret;
 }
 
-static inline int ksz_write24(struct ksz_device *dev, u32 reg, u32 value)
-{
-   int ret;
-
-   mutex_lock(&dev->reg_mutex);
-   ret = dev->ops->write24(dev, reg, value);
-   mutex_unlock(&dev->reg_mutex);
-
-   return ret;
-}
-
 static inline int ksz_write32(struct ksz_device *dev, u32 reg, u32 value)
 {
int ret;
diff --git a/drivers/net/dsa/microchip/ksz_priv.h 
b/drivers/net/dsa/microchip/ksz_priv.h
index c615d2a81dd5..5ef6153bd2cc 100644
--- a/drivers/net/dsa/microchip/ksz_priv.h
+++ b/drivers/net/dsa/microchip/ksz_priv.h
@@ -105,11 +105,9 @@ struct ksz_device {
 struct ksz_io_ops {
int (*read8)(struct ksz_device *dev, u32 reg, u8 *value);
int (*read16)(struct ksz_device *dev, u32 reg, u16 *value);
-   int (*read24)(struct ksz_device *dev, u32 reg, u32 *value);
int (*read32)(struct ksz_device *dev, u32 reg, u32 *value);
int (*write8)(struct ksz_device *dev, u32 reg, u8 value);
int (*write16)(struct ksz_device *dev, u32 reg, u16 value);
-   int (*write24)(struct ksz_device *dev, u32 reg, u32 value);
int (*write32)(struct ksz_device *dev, u32 reg, u32 value);
int (*get)(struct ksz_device *dev, u32 reg, void *data, size_t len);
int (*set)(struct ksz_device *dev, u32 reg, void *data, size_t len);
-- 
2.20.1



[PATCH V3 08/10] net: dsa: microchip: Dispose of ksz_io_ops

2019-06-23 Thread Marek Vasut
Since the driver now uses regmap , get rid of ad-hoc ksz_io_ops
abstraction, which no longer has any meaning. Moreover, since regmap
has it's own locking, get rid of the register access mutex.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Woojung Huh 
---
V2: Use separate regmaps for 8/16/32bit registers
V3: - Rebase on next/master
- Test on KSZ9477EVB
---
 drivers/net/dsa/microchip/ksz9477_spi.c | 57 +
 drivers/net/dsa/microchip/ksz_common.c  |  6 +--
 drivers/net/dsa/microchip/ksz_common.h  | 50 ++
 drivers/net/dsa/microchip/ksz_priv.h| 16 +--
 4 files changed, 17 insertions(+), 112 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c 
b/drivers/net/dsa/microchip/ksz9477_spi.c
index 77e3cb100eae..8c8bf3237013 100644
--- a/drivers/net/dsa/microchip/ksz9477_spi.c
+++ b/drivers/net/dsa/microchip/ksz9477_spi.c
@@ -46,67 +46,12 @@ static const struct regmap_config ksz9477_regmap_config[] = 
{
KSZ_REGMAP_COMMON(32),
 };
 
-static int ksz_spi_read8(struct ksz_device *dev, u32 reg, u8 *val)
-{
-   unsigned int value;
-   int ret = regmap_read(dev->regmap, reg, &value);
-
-   *val = value;
-   return ret;
-}
-
-static int ksz_spi_read16(struct ksz_device *dev, u32 reg, u16 *val)
-{
-   int ret = regmap_bulk_read(dev->regmap, reg, val, 2);
-
-   if (!ret)
-   *val = be16_to_cpu(*val);
-
-   return ret;
-}
-
-static int ksz_spi_read32(struct ksz_device *dev, u32 reg, u32 *val)
-{
-   int ret = regmap_bulk_read(dev->regmap, reg, val, 4);
-
-   if (!ret)
-   *val = be32_to_cpu(*val);
-
-   return ret;
-}
-
-static int ksz_spi_write8(struct ksz_device *dev, u32 reg, u8 value)
-{
-   return regmap_write(dev->regmap, reg, value);
-}
-
-static int ksz_spi_write16(struct ksz_device *dev, u32 reg, u16 value)
-{
-   value = cpu_to_be16(value);
-   return regmap_bulk_write(dev->regmap, reg, &value, 2);
-}
-
-static int ksz_spi_write32(struct ksz_device *dev, u32 reg, u32 value)
-{
-   value = cpu_to_be32(value);
-   return regmap_bulk_write(dev->regmap, reg, &value, 4);
-}
-
-static const struct ksz_io_ops ksz9477_spi_ops = {
-   .read8 = ksz_spi_read8,
-   .read16 = ksz_spi_read16,
-   .read32 = ksz_spi_read32,
-   .write8 = ksz_spi_write8,
-   .write16 = ksz_spi_write16,
-   .write32 = ksz_spi_write32,
-};
-
 static int ksz9477_spi_probe(struct spi_device *spi)
 {
struct ksz_device *dev;
int i, ret;
 
-   dev = ksz_switch_alloc(&spi->dev, &ksz9477_spi_ops, spi);
+   dev = ksz_switch_alloc(&spi->dev, spi);
if (!dev)
return -ENOMEM;
 
diff --git a/drivers/net/dsa/microchip/ksz_common.c 
b/drivers/net/dsa/microchip/ksz_common.c
index 978c59aa8efb..a3d2d67894bd 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -396,9 +396,7 @@ void ksz_disable_port(struct dsa_switch *ds, int port)
 }
 EXPORT_SYMBOL_GPL(ksz_disable_port);
 
-struct ksz_device *ksz_switch_alloc(struct device *base,
-   const struct ksz_io_ops *ops,
-   void *priv)
+struct ksz_device *ksz_switch_alloc(struct device *base, void *priv)
 {
struct dsa_switch *ds;
struct ksz_device *swdev;
@@ -416,7 +414,6 @@ struct ksz_device *ksz_switch_alloc(struct device *base,
 
swdev->ds = ds;
swdev->priv = priv;
-   swdev->ops = ops;
 
return swdev;
 }
@@ -442,7 +439,6 @@ int ksz_switch_register(struct ksz_device *dev,
}
 
mutex_init(&dev->dev_mutex);
-   mutex_init(&dev->reg_mutex);
mutex_init(&dev->stats_mutex);
mutex_init(&dev->alu_mutex);
mutex_init(&dev->vlan_mutex);
diff --git a/drivers/net/dsa/microchip/ksz_common.h 
b/drivers/net/dsa/microchip/ksz_common.h
index fe576a00facf..c3871ed9b097 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -7,6 +7,8 @@
 #ifndef __KSZ_COMMON_H
 #define __KSZ_COMMON_H
 
+#include 
+
 void ksz_port_cleanup(struct ksz_device *dev, int port);
 void ksz_update_port_member(struct ksz_device *dev, int port);
 void ksz_init_mib_timer(struct ksz_device *dev);
@@ -41,68 +43,44 @@ void ksz_disable_port(struct dsa_switch *ds, int port);
 
 static inline int ksz_read8(struct ksz_device *dev, u32 reg, u8 *val)
 {
-   int ret;
-
-   mutex_lock(&dev->reg_mutex);
-   ret = dev->ops->read8(dev, reg, val);
-   mutex_unlock(&dev->reg_mutex);
+   unsigned int value;
+   int ret = regmap_read(dev->regmap[0], reg, &value);
 
+   *val = value;
return ret;
 }
 
 static inline int ksz_read16(struct ksz_device *dev, u32 reg, u16 *val)
 {
-   int ret;
-
-   mutex_lock(&d

[PATCH V3 10/10] net: dsa: microchip: Replace ad-hoc bit manipulation with regmap

2019-06-23 Thread Marek Vasut
Regmap provides bit manipulation functions to set/clear bits, use those
insted of reimplementing them.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Woojung Huh 
---
V2: New patch
V3: - Rebase on next/master
- Test on KSZ9477EVB
---
 drivers/net/dsa/microchip/ksz9477.c | 46 -
 1 file changed, 6 insertions(+), 40 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz9477.c 
b/drivers/net/dsa/microchip/ksz9477.c
index 7d209fd9f26f..8f13dcc05a10 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -67,60 +67,26 @@ static const struct {
 
 static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set)
 {
-   u8 data;
-
-   ksz_read8(dev, addr, &data);
-   if (set)
-   data |= bits;
-   else
-   data &= ~bits;
-   ksz_write8(dev, addr, data);
+   regmap_update_bits(dev->regmap[0], addr, bits, set ? bits : 0);
 }
 
 static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits,
 bool set)
 {
-   u32 addr;
-   u8 data;
-
-   addr = PORT_CTRL_ADDR(port, offset);
-   ksz_read8(dev, addr, &data);
-
-   if (set)
-   data |= bits;
-   else
-   data &= ~bits;
-
-   ksz_write8(dev, addr, data);
+   regmap_update_bits(dev->regmap[0], PORT_CTRL_ADDR(port, offset),
+  bits, set ? bits : 0);
 }
 
 static void ksz9477_cfg32(struct ksz_device *dev, u32 addr, u32 bits, bool set)
 {
-   u32 data;
-
-   ksz_read32(dev, addr, &data);
-   if (set)
-   data |= bits;
-   else
-   data &= ~bits;
-   ksz_write32(dev, addr, data);
+   regmap_update_bits(dev->regmap[2], addr, bits, set ? bits : 0);
 }
 
 static void ksz9477_port_cfg32(struct ksz_device *dev, int port, int offset,
   u32 bits, bool set)
 {
-   u32 addr;
-   u32 data;
-
-   addr = PORT_CTRL_ADDR(port, offset);
-   ksz_read32(dev, addr, &data);
-
-   if (set)
-   data |= bits;
-   else
-   data &= ~bits;
-
-   ksz_write32(dev, addr, data);
+   regmap_update_bits(dev->regmap[2], PORT_CTRL_ADDR(port, offset),
+  bits, set ? bits : 0);
 }
 
 static int ksz9477_wait_vlan_ctrl_ready(struct ksz_device *dev, u32 waiton,
-- 
2.20.1



[PATCH V3 07/10] net: dsa: microchip: Initial SPI regmap support

2019-06-23 Thread Marek Vasut
Add basic SPI regmap support into the driver.

Previous patches unconver that ksz_spi_write() is always ever called
with len = 1, 2 or 4. We can thus drop the if (len > SPI_TX_BUF_LEN)
check and we can also drop the allocation of the txbuf which is part
of the driver data and wastes 256 bytes for no reason. Regmap covers
the whole thing now.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Woojung Huh 
---
V2: - Squash with "net: dsa: microchip: Remove dev->txbuf"
- Use separate regmaps for 8/16/32bit registers
- Increase the regmap size to 0xd00 to cover the entire register area
V3: - Rebase on next/master
- Test on KSZ9477EVB
- Increase regmap max register, to cover all switch registers
- Correct regmap reg_bits value to match the hardware
- Use cpu_to_be32() instead of cpu_to_le16() in register masks, since
  the KSZ9477 has some 32bit registers.
---
 drivers/net/dsa/microchip/Kconfig   |   1 +
 drivers/net/dsa/microchip/ksz9477_spi.c | 114 +++-
 drivers/net/dsa/microchip/ksz_priv.h|   3 +-
 3 files changed, 52 insertions(+), 66 deletions(-)

diff --git a/drivers/net/dsa/microchip/Kconfig 
b/drivers/net/dsa/microchip/Kconfig
index 2c3a6751bdaf..56790d544eb2 100644
--- a/drivers/net/dsa/microchip/Kconfig
+++ b/drivers/net/dsa/microchip/Kconfig
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 config NET_DSA_MICROCHIP_KSZ_COMMON
+   select REGMAP_SPI
tristate
 
 menuconfig NET_DSA_MICROCHIP_KSZ9477
diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c 
b/drivers/net/dsa/microchip/ksz9477_spi.c
index 49aeb92d36fc..77e3cb100eae 100644
--- a/drivers/net/dsa/microchip/ksz9477_spi.c
+++ b/drivers/net/dsa/microchip/ksz9477_spi.c
@@ -10,78 +10,54 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "ksz_priv.h"
 
-/* SPI frame opcodes */
-#define KS_SPIOP_RD3
-#define KS_SPIOP_WR2
-
 #define SPI_ADDR_SHIFT 24
-#define SPI_ADDR_MASK  (BIT(SPI_ADDR_SHIFT) - 1)
+#define SPI_ADDR_ALIGN 3
 #define SPI_TURNAROUND_SHIFT   5
 
-/* Enough to read all switch port registers. */
-#define SPI_TX_BUF_LEN 0x100
-
-static u32 ksz9477_spi_cmd(u32 reg, bool read)
-{
-   u32 txbuf;
-
-   txbuf = reg & SPI_ADDR_MASK;
-   txbuf |= (read ? KS_SPIOP_RD : KS_SPIOP_WR) << SPI_ADDR_SHIFT;
-   txbuf <<= SPI_TURNAROUND_SHIFT;
-   txbuf = cpu_to_be32(txbuf);
-
-   return txbuf;
-}
-
-static int ksz9477_spi_read_reg(struct spi_device *spi, u32 reg, u8 *val,
-   unsigned int len)
-{
-   u32 txbuf = ksz9477_spi_cmd(reg, true);
-
-   return spi_write_then_read(spi, &txbuf, 4, val, len);
-}
-
-static int ksz9477_spi_write_reg(struct spi_device *spi, u32 reg, u8 *val,
-unsigned int len)
-{
-   u32 *txbuf = (u32 *)val;
-
-   *txbuf = ksz9477_spi_cmd(reg, false);
-
-   return spi_write(spi, txbuf, 4 + len);
-}
-
-static int ksz_spi_read(struct ksz_device *dev, u32 reg, u8 *data,
-   unsigned int len)
-{
-   struct spi_device *spi = dev->priv;
-
-   return ksz9477_spi_read_reg(spi, reg, data, len);
-}
-
-static int ksz_spi_write(struct ksz_device *dev, u32 reg, void *data,
-unsigned int len)
-{
-   struct spi_device *spi = dev->priv;
+/* SPI frame opcodes */
+#define KS_SPIOP_RD3
+#define KS_SPIOP_WR2
 
-   if (len > SPI_TX_BUF_LEN)
-   len = SPI_TX_BUF_LEN;
-   memcpy(&dev->txbuf[4], data, len);
-   return ksz9477_spi_write_reg(spi, reg, dev->txbuf, len);
-}
+#define KS_SPIOP_FLAG_MASK(opcode) \
+   cpu_to_be32((opcode) << (SPI_ADDR_SHIFT + SPI_TURNAROUND_SHIFT))
+
+#define KSZ_REGMAP_COMMON(width)   \
+   {   \
+   .val_bits = (width),\
+   .reg_stride = (width) / 8,  \
+   .reg_bits = SPI_ADDR_SHIFT + SPI_ADDR_ALIGN,\
+   .pad_bits = SPI_TURNAROUND_SHIFT,   \
+   .max_register = BIT(SPI_ADDR_SHIFT) - 1,\
+   .cache_type = REGCACHE_NONE,\
+   .read_flag_mask = KS_SPIOP_FLAG_MASK(KS_SPIOP_RD),  \
+   .write_flag_mask = KS_SPIOP_FLAG_MASK(KS_SPIOP_WR), \
+   .reg_format_endian = REGMAP_ENDIAN_BIG, \
+   .val_format_endian = REGMAP_ENDIAN_BIG  \
+   }
+
+static const struct regmap_config ksz9477_regmap_config[] = {
+   KSZ_REGMAP_COMMON(8),
+   KSZ_REGMAP_COMMON(16),
+   KSZ_REGMAP_COMMON(32),
+

[PATCH V3 04/10] net: dsa: microchip: Move ksz_cfg and ksz_port_cfg to ksz9477.c

2019-06-23 Thread Marek Vasut
These functions are only used by the KSZ9477 code, move them from
the header into that code. Note that these functions will be soon
replaced by regmap equivalents.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Woojung Huh 
---
V2: New patch
V3: - Rebase on next/master
- Test on KSZ9477EVB
---
 drivers/net/dsa/microchip/ksz9477.c| 29 ++
 drivers/net/dsa/microchip/ksz_common.h | 29 --
 2 files changed, 29 insertions(+), 29 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz9477.c 
b/drivers/net/dsa/microchip/ksz9477.c
index 508380f80875..e8b96566abd9 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -65,6 +65,35 @@ static const struct {
{ 0x83, "tx_discards" },
 };
 
+static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set)
+{
+   u8 data;
+
+   ksz_read8(dev, addr, &data);
+   if (set)
+   data |= bits;
+   else
+   data &= ~bits;
+   ksz_write8(dev, addr, data);
+}
+
+static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits,
+bool set)
+{
+   u32 addr;
+   u8 data;
+
+   addr = dev->dev_ops->get_port_addr(port, offset);
+   ksz_read8(dev, addr, &data);
+
+   if (set)
+   data |= bits;
+   else
+   data &= ~bits;
+
+   ksz_write8(dev, addr, data);
+}
+
 static void ksz9477_cfg32(struct ksz_device *dev, u32 addr, u32 bits, bool set)
 {
u32 data;
diff --git a/drivers/net/dsa/microchip/ksz_common.h 
b/drivers/net/dsa/microchip/ksz_common.h
index c15b49528bad..fe576a00facf 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -141,35 +141,6 @@ static inline void ksz_pwrite32(struct ksz_device *dev, 
int port, int offset,
ksz_write32(dev, dev->dev_ops->get_port_addr(port, offset), data);
 }
 
-static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set)
-{
-   u8 data;
-
-   ksz_read8(dev, addr, &data);
-   if (set)
-   data |= bits;
-   else
-   data &= ~bits;
-   ksz_write8(dev, addr, data);
-}
-
-static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits,
-bool set)
-{
-   u32 addr;
-   u8 data;
-
-   addr = dev->dev_ops->get_port_addr(port, offset);
-   ksz_read8(dev, addr, &data);
-
-   if (set)
-   data |= bits;
-   else
-   data &= ~bits;
-
-   ksz_write8(dev, addr, data);
-}
-
 struct ksz_poll_ctx {
struct ksz_device *dev;
int port;
-- 
2.20.1



[PATCH V3 00/10] net: dsa: microchip: Convert to regmap

2019-06-23 Thread Marek Vasut
This patchset converts KSZ9477 switch driver to regmap.

This was tested with extra patches on KSZ8795. This was also tested
on KSZ9477 on Microchip KSZ9477EVB board, which I now have.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Woojung Huh 

Marek Vasut (10):
  net: dsa: microchip: Remove ksz_{read,write}24()
  net: dsa: microchip: Remove ksz_{get,set}()
  net: dsa: microchip: Inline ksz_spi.h
  net: dsa: microchip: Move ksz_cfg and ksz_port_cfg to ksz9477.c
  net: dsa: microchip: Use PORT_CTRL_ADDR() instead of indirect function
call
  net: dsa: microchip: Factor out register access opcode generation
  net: dsa: microchip: Initial SPI regmap support
  net: dsa: microchip: Dispose of ksz_io_ops
  net: dsa: microchip: Factor out regmap config generation into common
header
  net: dsa: microchip: Replace ad-hoc bit manipulation with regmap

 drivers/net/dsa/microchip/Kconfig   |   1 +
 drivers/net/dsa/microchip/ksz9477.c |  35 +++---
 drivers/net/dsa/microchip/ksz9477_spi.c | 114 +++--
 drivers/net/dsa/microchip/ksz_common.c  |   6 +-
 drivers/net/dsa/microchip/ksz_common.h  | 157 +++-
 drivers/net/dsa/microchip/ksz_priv.h|  23 +---
 drivers/net/dsa/microchip/ksz_spi.h |  69 ---
 7 files changed, 84 insertions(+), 321 deletions(-)
 delete mode 100644 drivers/net/dsa/microchip/ksz_spi.h

-- 
2.20.1



[PATCH V3 03/10] net: dsa: microchip: Inline ksz_spi.h

2019-06-23 Thread Marek Vasut
The functions in the header file are static, and the header file is
included from single C file, just inline the code into the C file.
The bonus is that it's easier to spot further content to clean up.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Woojung Huh 
---
V2: No change
V3: - Rebase on next/master
- Test on KSZ9477EVB
---
 drivers/net/dsa/microchip/ksz9477_spi.c | 43 +-
 drivers/net/dsa/microchip/ksz_spi.h | 59 -
 2 files changed, 42 insertions(+), 60 deletions(-)
 delete mode 100644 drivers/net/dsa/microchip/ksz_spi.h

diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c 
b/drivers/net/dsa/microchip/ksz9477_spi.c
index 86d12d48a2a9..a34e66eccbcd 100644
--- a/drivers/net/dsa/microchip/ksz9477_spi.c
+++ b/drivers/net/dsa/microchip/ksz9477_spi.c
@@ -13,7 +13,6 @@
 #include 
 
 #include "ksz_priv.h"
-#include "ksz_spi.h"
 
 /* SPI frame opcodes */
 #define KS_SPIOP_RD3
@@ -73,6 +72,48 @@ static int ksz_spi_write(struct ksz_device *dev, u32 reg, 
void *data,
return ksz9477_spi_write_reg(spi, reg, dev->txbuf, len);
 }
 
+static int ksz_spi_read8(struct ksz_device *dev, u32 reg, u8 *val)
+{
+   return ksz_spi_read(dev, reg, val, 1);
+}
+
+static int ksz_spi_read16(struct ksz_device *dev, u32 reg, u16 *val)
+{
+   int ret = ksz_spi_read(dev, reg, (u8 *)val, 2);
+
+   if (!ret)
+   *val = be16_to_cpu(*val);
+
+   return ret;
+}
+
+static int ksz_spi_read32(struct ksz_device *dev, u32 reg, u32 *val)
+{
+   int ret = ksz_spi_read(dev, reg, (u8 *)val, 4);
+
+   if (!ret)
+   *val = be32_to_cpu(*val);
+
+   return ret;
+}
+
+static int ksz_spi_write8(struct ksz_device *dev, u32 reg, u8 value)
+{
+   return ksz_spi_write(dev, reg, &value, 1);
+}
+
+static int ksz_spi_write16(struct ksz_device *dev, u32 reg, u16 value)
+{
+   value = cpu_to_be16(value);
+   return ksz_spi_write(dev, reg, &value, 2);
+}
+
+static int ksz_spi_write32(struct ksz_device *dev, u32 reg, u32 value)
+{
+   value = cpu_to_be32(value);
+   return ksz_spi_write(dev, reg, &value, 4);
+}
+
 static const struct ksz_io_ops ksz9477_spi_ops = {
.read8 = ksz_spi_read8,
.read16 = ksz_spi_read16,
diff --git a/drivers/net/dsa/microchip/ksz_spi.h 
b/drivers/net/dsa/microchip/ksz_spi.h
deleted file mode 100644
index 976bace31f37..
--- a/drivers/net/dsa/microchip/ksz_spi.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0
- * Microchip KSZ series SPI access common header
- *
- * Copyright (C) 2017-2018 Microchip Technology Inc.
- * Tristram Ha 
- */
-
-#ifndef __KSZ_SPI_H
-#define __KSZ_SPI_H
-
-/* Chip dependent SPI access */
-static int ksz_spi_read(struct ksz_device *dev, u32 reg, u8 *data,
-   unsigned int len);
-static int ksz_spi_write(struct ksz_device *dev, u32 reg, void *data,
-unsigned int len);
-
-static int ksz_spi_read8(struct ksz_device *dev, u32 reg, u8 *val)
-{
-   return ksz_spi_read(dev, reg, val, 1);
-}
-
-static int ksz_spi_read16(struct ksz_device *dev, u32 reg, u16 *val)
-{
-   int ret = ksz_spi_read(dev, reg, (u8 *)val, 2);
-
-   if (!ret)
-   *val = be16_to_cpu(*val);
-
-   return ret;
-}
-
-static int ksz_spi_read32(struct ksz_device *dev, u32 reg, u32 *val)
-{
-   int ret = ksz_spi_read(dev, reg, (u8 *)val, 4);
-
-   if (!ret)
-   *val = be32_to_cpu(*val);
-
-   return ret;
-}
-
-static int ksz_spi_write8(struct ksz_device *dev, u32 reg, u8 value)
-{
-   return ksz_spi_write(dev, reg, &value, 1);
-}
-
-static int ksz_spi_write16(struct ksz_device *dev, u32 reg, u16 value)
-{
-   value = cpu_to_be16(value);
-   return ksz_spi_write(dev, reg, &value, 2);
-}
-
-static int ksz_spi_write32(struct ksz_device *dev, u32 reg, u32 value)
-{
-   value = cpu_to_be32(value);
-   return ksz_spi_write(dev, reg, &value, 4);
-}
-
-#endif
-- 
2.20.1



[PATCH V3 02/10] net: dsa: microchip: Remove ksz_{get,set}()

2019-06-23 Thread Marek Vasut
These functions and callbacks are never used, remove them.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Woojung Huh 
---
V2: No change
V3: - Rebase on next/master
- Test on KSZ9477EVB
---
 drivers/net/dsa/microchip/ksz9477_spi.c |  2 --
 drivers/net/dsa/microchip/ksz_common.h  | 24 
 drivers/net/dsa/microchip/ksz_priv.h|  2 --
 drivers/net/dsa/microchip/ksz_spi.h | 10 --
 4 files changed, 38 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c 
b/drivers/net/dsa/microchip/ksz9477_spi.c
index e7118319c192..86d12d48a2a9 100644
--- a/drivers/net/dsa/microchip/ksz9477_spi.c
+++ b/drivers/net/dsa/microchip/ksz9477_spi.c
@@ -80,8 +80,6 @@ static const struct ksz_io_ops ksz9477_spi_ops = {
.write8 = ksz_spi_write8,
.write16 = ksz_spi_write16,
.write32 = ksz_spi_write32,
-   .get = ksz_spi_get,
-   .set = ksz_spi_set,
 };
 
 static int ksz9477_spi_probe(struct spi_device *spi)
diff --git a/drivers/net/dsa/microchip/ksz_common.h 
b/drivers/net/dsa/microchip/ksz_common.h
index 1781539c3a81..c15b49528bad 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -105,30 +105,6 @@ static inline int ksz_write32(struct ksz_device *dev, u32 
reg, u32 value)
return ret;
 }
 
-static inline int ksz_get(struct ksz_device *dev, u32 reg, void *data,
- size_t len)
-{
-   int ret;
-
-   mutex_lock(&dev->reg_mutex);
-   ret = dev->ops->get(dev, reg, data, len);
-   mutex_unlock(&dev->reg_mutex);
-
-   return ret;
-}
-
-static inline int ksz_set(struct ksz_device *dev, u32 reg, void *data,
- size_t len)
-{
-   int ret;
-
-   mutex_lock(&dev->reg_mutex);
-   ret = dev->ops->set(dev, reg, data, len);
-   mutex_unlock(&dev->reg_mutex);
-
-   return ret;
-}
-
 static inline void ksz_pread8(struct ksz_device *dev, int port, int offset,
  u8 *data)
 {
diff --git a/drivers/net/dsa/microchip/ksz_priv.h 
b/drivers/net/dsa/microchip/ksz_priv.h
index 5ef6153bd2cc..d3ddf98156bb 100644
--- a/drivers/net/dsa/microchip/ksz_priv.h
+++ b/drivers/net/dsa/microchip/ksz_priv.h
@@ -109,8 +109,6 @@ struct ksz_io_ops {
int (*write8)(struct ksz_device *dev, u32 reg, u8 value);
int (*write16)(struct ksz_device *dev, u32 reg, u16 value);
int (*write32)(struct ksz_device *dev, u32 reg, u32 value);
-   int (*get)(struct ksz_device *dev, u32 reg, void *data, size_t len);
-   int (*set)(struct ksz_device *dev, u32 reg, void *data, size_t len);
 };
 
 struct alu_struct {
diff --git a/drivers/net/dsa/microchip/ksz_spi.h 
b/drivers/net/dsa/microchip/ksz_spi.h
index 427811bd60b3..976bace31f37 100644
--- a/drivers/net/dsa/microchip/ksz_spi.h
+++ b/drivers/net/dsa/microchip/ksz_spi.h
@@ -56,14 +56,4 @@ static int ksz_spi_write32(struct ksz_device *dev, u32 reg, 
u32 value)
return ksz_spi_write(dev, reg, &value, 4);
 }
 
-static int ksz_spi_get(struct ksz_device *dev, u32 reg, void *data, size_t len)
-{
-   return ksz_spi_read(dev, reg, data, len);
-}
-
-static int ksz_spi_set(struct ksz_device *dev, u32 reg, void *data, size_t len)
-{
-   return ksz_spi_write(dev, reg, data, len);
-}
-
 #endif
-- 
2.20.1



[PATCH V3 05/10] net: dsa: microchip: Use PORT_CTRL_ADDR() instead of indirect function call

2019-06-23 Thread Marek Vasut
The indirect function call to dev->dev_ops->get_port_addr() is expensive
especially if called for every single register access, and only returns
the value of PORT_CTRL_ADDR() macro. Use PORT_CTRL_ADDR() macro directly
instead.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Woojung Huh 
---
V2: New patch
V3: - Rebase on next/master
- Test on KSZ9477EVB
---
 drivers/net/dsa/microchip/ksz9477.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/dsa/microchip/ksz9477.c 
b/drivers/net/dsa/microchip/ksz9477.c
index e8b96566abd9..7d209fd9f26f 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -83,7 +83,7 @@ static void ksz_port_cfg(struct ksz_device *dev, int port, 
int offset, u8 bits,
u32 addr;
u8 data;
 
-   addr = dev->dev_ops->get_port_addr(port, offset);
+   addr = PORT_CTRL_ADDR(port, offset);
ksz_read8(dev, addr, &data);
 
if (set)
-- 
2.20.1



Re: [PATCH V3 07/10] net: dsa: microchip: Initial SPI regmap support

2019-06-24 Thread Marek Vasut
On 6/24/19 12:35 AM, Marek Vasut wrote:
> Add basic SPI regmap support into the driver.
> 
> Previous patches unconver that ksz_spi_write() is always ever called
> with len = 1, 2 or 4. We can thus drop the if (len > SPI_TX_BUF_LEN)
> check and we can also drop the allocation of the txbuf which is part
> of the driver data and wastes 256 bytes for no reason. Regmap covers
> the whole thing now.
> 
> Signed-off-by: Marek Vasut 
> Cc: Andrew Lunn 
> Cc: Florian Fainelli 
> Cc: Tristram Ha 
> Cc: Woojung Huh 

[...]

> +#define KS_SPIOP_FLAG_MASK(opcode)   \
> + cpu_to_be32((opcode) << (SPI_ADDR_SHIFT + SPI_TURNAROUND_SHIFT))

So the robot is complaining about this. I believe this is correct, as
the mask should be in native endianness on the register and NOT the
native endianness of the CPU.

I think a cast would help here, e.g.:
-   cpu_to_be32((opcode) << (SPI_ADDR_SHIFT + SPI_TURNAROUND_SHIFT))
-   (__force unsigned long)cpu_to_be32((opcode) << (SPI_ADDR_SHIFT +
SPI_TURNAROUND_SHIFT))

Does this make sense ?

> +#define KSZ_REGMAP_COMMON(width) \
> + {   \
> + .val_bits = (width),\
> + .reg_stride = (width) / 8,  \
> + .reg_bits = SPI_ADDR_SHIFT + SPI_ADDR_ALIGN,\
> + .pad_bits = SPI_TURNAROUND_SHIFT,   \
> + .max_register = BIT(SPI_ADDR_SHIFT) - 1,\
> + .cache_type = REGCACHE_NONE,\
> + .read_flag_mask = KS_SPIOP_FLAG_MASK(KS_SPIOP_RD),  \
> +     .write_flag_mask = KS_SPIOP_FLAG_MASK(KS_SPIOP_WR), \

[...]

-- 
Best regards,
Marek Vasut


Re: [PATCH V3 05/10] net: dsa: microchip: Use PORT_CTRL_ADDR() instead of indirect function call

2019-06-24 Thread Marek Vasut
On 6/24/19 5:20 AM, Andrew Lunn wrote:
> On Mon, Jun 24, 2019 at 12:35:03AM +0200, Marek Vasut wrote:
>> The indirect function call to dev->dev_ops->get_port_addr() is expensive
>> especially if called for every single register access, and only returns
>> the value of PORT_CTRL_ADDR() macro. Use PORT_CTRL_ADDR() macro directly
>> instead.
> 
> Hi Marek
> 
> Rather than change just one instance, it would be better to change
> them all. And then remove dev_ops->get_port_addr().

So that actually doesn't work. The rest of the calls are in common code
(ksz_common.h) and I plan to add the KSZ8795, which has different
spacing between the ports, so those have to stay.

Although, depending on how things look, I will do more regmap cleanups,
the driver needs it. Since I have the KSZ9477 devkit, that also makes it
much easier to test the changes. I think inlining those custom accessors
would be high on the list, because they are just a mess. But that's for
another series.

-- 
Best regards,
Marek Vasut


Re: [PATCH V3 07/10] net: dsa: microchip: Initial SPI regmap support

2019-06-25 Thread Marek Vasut
On 6/25/19 1:59 AM, Vladimir Oltean wrote:
> On Tue, 25 Jun 2019 at 01:17, Marek Vasut  wrote:
>>
>> On 6/24/19 12:35 AM, Marek Vasut wrote:
>>> Add basic SPI regmap support into the driver.
>>>
>>> Previous patches unconver that ksz_spi_write() is always ever called
>>> with len = 1, 2 or 4. We can thus drop the if (len > SPI_TX_BUF_LEN)
>>> check and we can also drop the allocation of the txbuf which is part
>>> of the driver data and wastes 256 bytes for no reason. Regmap covers
>>> the whole thing now.
>>>
>>> Signed-off-by: Marek Vasut 
>>> Cc: Andrew Lunn 
>>> Cc: Florian Fainelli 
>>> Cc: Tristram Ha 
>>> Cc: Woojung Huh 
>>
>> [...]
>>
>>> +#define KS_SPIOP_FLAG_MASK(opcode)   \
>>> + cpu_to_be32((opcode) << (SPI_ADDR_SHIFT + SPI_TURNAROUND_SHIFT))
>>
>> So the robot is complaining about this. I believe this is correct, as
>> the mask should be in native endianness on the register and NOT the
>> native endianness of the CPU.
>>
>> I think a cast would help here, e.g.:
>> -   cpu_to_be32((opcode) << (SPI_ADDR_SHIFT + SPI_TURNAROUND_SHIFT))
>> -   (__force unsigned long)cpu_to_be32((opcode) << (SPI_ADDR_SHIFT +
>> SPI_TURNAROUND_SHIFT))
>>
>> Does this make sense ?
>>
>>> +#define KSZ_REGMAP_COMMON(width) \
>>> + {   \
>>> + .val_bits = (width),\
>>> + .reg_stride = (width) / 8,  \
>>> + .reg_bits = SPI_ADDR_SHIFT + SPI_ADDR_ALIGN,\
>>> + .pad_bits = SPI_TURNAROUND_SHIFT,   \
>>> + .max_register = BIT(SPI_ADDR_SHIFT) - 1,\
>>> + .cache_type = REGCACHE_NONE,\
>>> + .read_flag_mask = KS_SPIOP_FLAG_MASK(KS_SPIOP_RD),  \
>>> + .write_flag_mask = KS_SPIOP_FLAG_MASK(KS_SPIOP_WR), \
>>
>> [...]
>>
>> --
>> Best regards,
>> Marek Vasut
> 
> Hi Marek,
> 
> I saw SPI buffers and endianness and got triggered :)
> Would it make sense to take a look at CONFIG_PACKING for the KSZ9477 driver?
> I don't know how bad the field alignment issue is on that hardware,
> but on SJA1105 it was such a disaster that I couldn't have managed it
> any other way.

How does that help me here ? All I really need is a static constant mask
for the register/flags , 32bit for KSZ9xxx and 16bit for KSZ87xx. I
don't need any dynamic stuff, luckily.

But I'm glad to see TJA1105 driver mainline :)

-- 
Best regards,
Marek Vasut


Re: [PATCH V3 07/10] net: dsa: microchip: Initial SPI regmap support

2019-06-25 Thread Marek Vasut
On 6/25/19 2:40 PM, Vladimir Oltean wrote:
> On Tue, 25 Jun 2019 at 15:06, Marek Vasut  wrote:
>>
>> On 6/25/19 1:59 AM, Vladimir Oltean wrote:
>>> On Tue, 25 Jun 2019 at 01:17, Marek Vasut  wrote:
>>>>
>>>> On 6/24/19 12:35 AM, Marek Vasut wrote:
>>>>> Add basic SPI regmap support into the driver.
>>>>>
>>>>> Previous patches unconver that ksz_spi_write() is always ever called
>>>>> with len = 1, 2 or 4. We can thus drop the if (len > SPI_TX_BUF_LEN)
>>>>> check and we can also drop the allocation of the txbuf which is part
>>>>> of the driver data and wastes 256 bytes for no reason. Regmap covers
>>>>> the whole thing now.
>>>>>
>>>>> Signed-off-by: Marek Vasut 
>>>>> Cc: Andrew Lunn 
>>>>> Cc: Florian Fainelli 
>>>>> Cc: Tristram Ha 
>>>>> Cc: Woojung Huh 
>>>>
>>>> [...]
>>>>
>>>>> +#define KS_SPIOP_FLAG_MASK(opcode)   \
>>>>> + cpu_to_be32((opcode) << (SPI_ADDR_SHIFT + SPI_TURNAROUND_SHIFT))
>>>>
>>>> So the robot is complaining about this. I believe this is correct, as
>>>> the mask should be in native endianness on the register and NOT the
>>>> native endianness of the CPU.
>>>>
>>>> I think a cast would help here, e.g.:
>>>> -   cpu_to_be32((opcode) << (SPI_ADDR_SHIFT + SPI_TURNAROUND_SHIFT))
>>>> -   (__force unsigned long)cpu_to_be32((opcode) << (SPI_ADDR_SHIFT +
>>>> SPI_TURNAROUND_SHIFT))
>>>>
>>>> Does this make sense ?
>>>>
>>>>> +#define KSZ_REGMAP_COMMON(width) \
>>>>> + {   \
>>>>> + .val_bits = (width),\
>>>>> + .reg_stride = (width) / 8,      \
>>>>> + .reg_bits = SPI_ADDR_SHIFT + SPI_ADDR_ALIGN,\
>>>>> + .pad_bits = SPI_TURNAROUND_SHIFT,   \
>>>>> + .max_register = BIT(SPI_ADDR_SHIFT) - 1,\
>>>>> + .cache_type = REGCACHE_NONE,\
>>>>> + .read_flag_mask = KS_SPIOP_FLAG_MASK(KS_SPIOP_RD),  \
>>>>> + .write_flag_mask = KS_SPIOP_FLAG_MASK(KS_SPIOP_WR), \
>>>>
>>>> [...]
>>>>
>>>> --
>>>> Best regards,
>>>> Marek Vasut
>>>
>>> Hi Marek,
>>>
>>> I saw SPI buffers and endianness and got triggered :)
>>> Would it make sense to take a look at CONFIG_PACKING for the KSZ9477 driver?
>>> I don't know how bad the field alignment issue is on that hardware,
>>> but on SJA1105 it was such a disaster that I couldn't have managed it
>>> any other way.
>>
>> How does that help me here ? All I really need is a static constant mask
>> for the register/flags , 32bit for KSZ9xxx and 16bit for KSZ87xx. I
>> don't need any dynamic stuff, luckily.
>>
> 
> Ok. I was thinking *instead of* regmap.
> On the SJA1105 I couldn't use a spi regmap because:
> * the enum regmap_endian wasn't enough to describe the hardware's bit
> layout (it is big endian, but high-order and low-order 32 bit words
> are swapped)

Oof. Is the switch development some competition in register layout
braindeath ? What's it gonna be next ... I was gonna suggest something,
but then reconsidered, better not give them any wild ideas :-)

> * it doesn't really expose a well-defined register map, but rather,
> you're supposed to dynamically construct a TLV-type buffer and write
> it starting with a fixed address.
> I just thought you were facing some of these problems as well with
> regmap. If not, that's perfectly fine!

All right, that's not the case here, whew.

-- 
Best regards,
Marek Vasut


[PATCH V4 09/10] net: dsa: microchip: Factor out regmap config generation into common header

2019-06-25 Thread Marek Vasut
The regmap config tables are rather similar for various generations of
the KSZ8xxx/KSZ9xxx switches. Introduce a macro which allows generating
those tables without duplication. Note that $regalign parameter is not
used right now, but will be used in KSZ87xx series switches.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Woojung Huh 
---
V2: New patch
V3: - Rebase on next/master
- Test on KSZ9477EVB
- Increase regmap max register, to cover all switch registers
- Make register swabbing configurable, to allow handling switches
  with only 16bit registers as well as switches with some 32bit ones
V4: No change
---
 drivers/net/dsa/microchip/ksz9477_spi.c | 29 +++---
 drivers/net/dsa/microchip/ksz_common.h  | 32 +
 2 files changed, 35 insertions(+), 26 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c 
b/drivers/net/dsa/microchip/ksz9477_spi.c
index d1ffdf51d58c..5a9e27b337a8 100644
--- a/drivers/net/dsa/microchip/ksz9477_spi.c
+++ b/drivers/net/dsa/microchip/ksz9477_spi.c
@@ -14,37 +14,14 @@
 #include 
 
 #include "ksz_priv.h"
+#include "ksz_common.h"
 
 #define SPI_ADDR_SHIFT 24
 #define SPI_ADDR_ALIGN 3
 #define SPI_TURNAROUND_SHIFT   5
 
-/* SPI frame opcodes */
-#define KS_SPIOP_RD3
-#define KS_SPIOP_WR2
-
-#define KS_SPIOP_FLAG_MASK(opcode) \
-   swab32((opcode) << (SPI_ADDR_SHIFT + SPI_TURNAROUND_SHIFT))
-
-#define KSZ_REGMAP_COMMON(width)   \
-   {   \
-   .val_bits = (width),\
-   .reg_stride = (width) / 8,  \
-   .reg_bits = SPI_ADDR_SHIFT + SPI_ADDR_ALIGN,\
-   .pad_bits = SPI_TURNAROUND_SHIFT,   \
-   .max_register = BIT(SPI_ADDR_SHIFT) - 1,\
-   .cache_type = REGCACHE_NONE,\
-   .read_flag_mask = KS_SPIOP_FLAG_MASK(KS_SPIOP_RD),  \
-   .write_flag_mask = KS_SPIOP_FLAG_MASK(KS_SPIOP_WR), \
-   .reg_format_endian = REGMAP_ENDIAN_BIG, \
-   .val_format_endian = REGMAP_ENDIAN_BIG  \
-   }
-
-static const struct regmap_config ksz9477_regmap_config[] = {
-   KSZ_REGMAP_COMMON(8),
-   KSZ_REGMAP_COMMON(16),
-   KSZ_REGMAP_COMMON(32),
-};
+KSZ_REGMAP_TABLE(ksz9477, 32, SPI_ADDR_SHIFT,
+SPI_TURNAROUND_SHIFT, SPI_ADDR_ALIGN);
 
 static int ksz9477_spi_probe(struct spi_device *spi)
 {
diff --git a/drivers/net/dsa/microchip/ksz_common.h 
b/drivers/net/dsa/microchip/ksz_common.h
index c3871ed9b097..745318424f71 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -133,4 +133,36 @@ static inline u32 ksz_pread32_poll(struct ksz_poll_ctx 
*ctx)
return data;
 }
 
+/* Regmap tables generation */
+#define KSZ_SPI_OP_RD  3
+#define KSZ_SPI_OP_WR  2
+
+#define KSZ_SPI_OP_FLAG_MASK(opcode, swp, regbits, regpad) \
+   swab##swp((opcode) << ((regbits) + (regpad)))
+
+#define KSZ_REGMAP_ENTRY(width, swp, regbits, regpad, regalign)
\
+   {   \
+   .val_bits = (width),\
+   .reg_stride = (width) / 8,  \
+   .reg_bits = (regbits) + (regalign), \
+   .pad_bits = (regpad),   \
+   .max_register = BIT(regbits) - 1,   \
+   .cache_type = REGCACHE_NONE,\
+   .read_flag_mask =   \
+   KSZ_SPI_OP_FLAG_MASK(KSZ_SPI_OP_RD, swp,\
+regbits, regpad),  \
+   .write_flag_mask =  \
+   KSZ_SPI_OP_FLAG_MASK(KSZ_SPI_OP_WR, swp,\
+regbits, regpad),  \
+   .reg_format_endian = REGMAP_ENDIAN_BIG, \
+   .val_format_endian = REGMAP_ENDIAN_BIG  \
+   }
+
+#define KSZ_REGMAP_TABLE(ksz, swp, regbits, regpad, regalign)  \
+   static const struct regmap_config ksz##_regmap_config[] = { \
+   KSZ_REGMAP_ENTRY(8, swp, (regbits), (regpad), (regalign)), \
+   KSZ_REGMAP_ENTRY(16, swp, (regbits), (regpad), (regalign)), \
+   KSZ_REGMAP_ENTRY(32, swp, (regbits), (regpad), (regalign)), \
+   }
+
 #endif
-- 
2.20.1



[PATCH V4 10/10] net: dsa: microchip: Replace ad-hoc bit manipulation with regmap

2019-06-25 Thread Marek Vasut
Regmap provides bit manipulation functions to set/clear bits, use those
insted of reimplementing them.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Woojung Huh 
---
V2: New patch
V3: - Rebase on next/master
- Test on KSZ9477EVB
V4: No change
---
 drivers/net/dsa/microchip/ksz9477.c | 46 -
 1 file changed, 6 insertions(+), 40 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz9477.c 
b/drivers/net/dsa/microchip/ksz9477.c
index 7d209fd9f26f..8f13dcc05a10 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -67,60 +67,26 @@ static const struct {
 
 static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set)
 {
-   u8 data;
-
-   ksz_read8(dev, addr, &data);
-   if (set)
-   data |= bits;
-   else
-   data &= ~bits;
-   ksz_write8(dev, addr, data);
+   regmap_update_bits(dev->regmap[0], addr, bits, set ? bits : 0);
 }
 
 static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits,
 bool set)
 {
-   u32 addr;
-   u8 data;
-
-   addr = PORT_CTRL_ADDR(port, offset);
-   ksz_read8(dev, addr, &data);
-
-   if (set)
-   data |= bits;
-   else
-   data &= ~bits;
-
-   ksz_write8(dev, addr, data);
+   regmap_update_bits(dev->regmap[0], PORT_CTRL_ADDR(port, offset),
+  bits, set ? bits : 0);
 }
 
 static void ksz9477_cfg32(struct ksz_device *dev, u32 addr, u32 bits, bool set)
 {
-   u32 data;
-
-   ksz_read32(dev, addr, &data);
-   if (set)
-   data |= bits;
-   else
-   data &= ~bits;
-   ksz_write32(dev, addr, data);
+   regmap_update_bits(dev->regmap[2], addr, bits, set ? bits : 0);
 }
 
 static void ksz9477_port_cfg32(struct ksz_device *dev, int port, int offset,
   u32 bits, bool set)
 {
-   u32 addr;
-   u32 data;
-
-   addr = PORT_CTRL_ADDR(port, offset);
-   ksz_read32(dev, addr, &data);
-
-   if (set)
-   data |= bits;
-   else
-   data &= ~bits;
-
-   ksz_write32(dev, addr, data);
+   regmap_update_bits(dev->regmap[2], PORT_CTRL_ADDR(port, offset),
+  bits, set ? bits : 0);
 }
 
 static int ksz9477_wait_vlan_ctrl_ready(struct ksz_device *dev, u32 waiton,
-- 
2.20.1



[PATCH V4 06/10] net: dsa: microchip: Factor out register access opcode generation

2019-06-25 Thread Marek Vasut
Factor out the code which sends out the register read/write opcodes
to the switch, since the code differs in single bit between read and
write.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Woojung Huh 
Reviewed-by: Andrew Lunn 
---
V2: New patch
V3: - Rebase on next/master
- Test on KSZ9477EVB
V4: Add RB
---
 drivers/net/dsa/microchip/ksz9477_spi.c | 22 --
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c 
b/drivers/net/dsa/microchip/ksz9477_spi.c
index a34e66eccbcd..49aeb92d36fc 100644
--- a/drivers/net/dsa/microchip/ksz9477_spi.c
+++ b/drivers/net/dsa/microchip/ksz9477_spi.c
@@ -25,19 +25,24 @@
 /* Enough to read all switch port registers. */
 #define SPI_TX_BUF_LEN 0x100
 
-static int ksz9477_spi_read_reg(struct spi_device *spi, u32 reg, u8 *val,
-   unsigned int len)
+static u32 ksz9477_spi_cmd(u32 reg, bool read)
 {
u32 txbuf;
-   int ret;
 
txbuf = reg & SPI_ADDR_MASK;
-   txbuf |= KS_SPIOP_RD << SPI_ADDR_SHIFT;
+   txbuf |= (read ? KS_SPIOP_RD : KS_SPIOP_WR) << SPI_ADDR_SHIFT;
txbuf <<= SPI_TURNAROUND_SHIFT;
txbuf = cpu_to_be32(txbuf);
 
-   ret = spi_write_then_read(spi, &txbuf, 4, val, len);
-   return ret;
+   return txbuf;
+}
+
+static int ksz9477_spi_read_reg(struct spi_device *spi, u32 reg, u8 *val,
+   unsigned int len)
+{
+   u32 txbuf = ksz9477_spi_cmd(reg, true);
+
+   return spi_write_then_read(spi, &txbuf, 4, val, len);
 }
 
 static int ksz9477_spi_write_reg(struct spi_device *spi, u32 reg, u8 *val,
@@ -45,10 +50,7 @@ static int ksz9477_spi_write_reg(struct spi_device *spi, u32 
reg, u8 *val,
 {
u32 *txbuf = (u32 *)val;
 
-   *txbuf = reg & SPI_ADDR_MASK;
-   *txbuf |= (KS_SPIOP_WR << SPI_ADDR_SHIFT);
-   *txbuf <<= SPI_TURNAROUND_SHIFT;
-   *txbuf = cpu_to_be32(*txbuf);
+   *txbuf = ksz9477_spi_cmd(reg, false);
 
return spi_write(spi, txbuf, 4 + len);
 }
-- 
2.20.1



[PATCH V4 08/10] net: dsa: microchip: Dispose of ksz_io_ops

2019-06-25 Thread Marek Vasut
Since the driver now uses regmap , get rid of ad-hoc ksz_io_ops
abstraction, which no longer has any meaning. Moreover, since regmap
has it's own locking, get rid of the register access mutex.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Woojung Huh 
---
V2: Use separate regmaps for 8/16/32bit registers
V3: - Rebase on next/master
- Test on KSZ9477EVB
V4: No change
---
 drivers/net/dsa/microchip/ksz9477_spi.c | 57 +
 drivers/net/dsa/microchip/ksz_common.c  |  6 +--
 drivers/net/dsa/microchip/ksz_common.h  | 50 ++
 drivers/net/dsa/microchip/ksz_priv.h| 16 +--
 4 files changed, 17 insertions(+), 112 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c 
b/drivers/net/dsa/microchip/ksz9477_spi.c
index c72645354dc2..d1ffdf51d58c 100644
--- a/drivers/net/dsa/microchip/ksz9477_spi.c
+++ b/drivers/net/dsa/microchip/ksz9477_spi.c
@@ -46,67 +46,12 @@ static const struct regmap_config ksz9477_regmap_config[] = 
{
KSZ_REGMAP_COMMON(32),
 };
 
-static int ksz_spi_read8(struct ksz_device *dev, u32 reg, u8 *val)
-{
-   unsigned int value;
-   int ret = regmap_read(dev->regmap, reg, &value);
-
-   *val = value;
-   return ret;
-}
-
-static int ksz_spi_read16(struct ksz_device *dev, u32 reg, u16 *val)
-{
-   int ret = regmap_bulk_read(dev->regmap, reg, val, 2);
-
-   if (!ret)
-   *val = be16_to_cpu(*val);
-
-   return ret;
-}
-
-static int ksz_spi_read32(struct ksz_device *dev, u32 reg, u32 *val)
-{
-   int ret = regmap_bulk_read(dev->regmap, reg, val, 4);
-
-   if (!ret)
-   *val = be32_to_cpu(*val);
-
-   return ret;
-}
-
-static int ksz_spi_write8(struct ksz_device *dev, u32 reg, u8 value)
-{
-   return regmap_write(dev->regmap, reg, value);
-}
-
-static int ksz_spi_write16(struct ksz_device *dev, u32 reg, u16 value)
-{
-   value = cpu_to_be16(value);
-   return regmap_bulk_write(dev->regmap, reg, &value, 2);
-}
-
-static int ksz_spi_write32(struct ksz_device *dev, u32 reg, u32 value)
-{
-   value = cpu_to_be32(value);
-   return regmap_bulk_write(dev->regmap, reg, &value, 4);
-}
-
-static const struct ksz_io_ops ksz9477_spi_ops = {
-   .read8 = ksz_spi_read8,
-   .read16 = ksz_spi_read16,
-   .read32 = ksz_spi_read32,
-   .write8 = ksz_spi_write8,
-   .write16 = ksz_spi_write16,
-   .write32 = ksz_spi_write32,
-};
-
 static int ksz9477_spi_probe(struct spi_device *spi)
 {
struct ksz_device *dev;
int i, ret;
 
-   dev = ksz_switch_alloc(&spi->dev, &ksz9477_spi_ops, spi);
+   dev = ksz_switch_alloc(&spi->dev, spi);
if (!dev)
return -ENOMEM;
 
diff --git a/drivers/net/dsa/microchip/ksz_common.c 
b/drivers/net/dsa/microchip/ksz_common.c
index 978c59aa8efb..a3d2d67894bd 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -396,9 +396,7 @@ void ksz_disable_port(struct dsa_switch *ds, int port)
 }
 EXPORT_SYMBOL_GPL(ksz_disable_port);
 
-struct ksz_device *ksz_switch_alloc(struct device *base,
-   const struct ksz_io_ops *ops,
-   void *priv)
+struct ksz_device *ksz_switch_alloc(struct device *base, void *priv)
 {
struct dsa_switch *ds;
struct ksz_device *swdev;
@@ -416,7 +414,6 @@ struct ksz_device *ksz_switch_alloc(struct device *base,
 
swdev->ds = ds;
swdev->priv = priv;
-   swdev->ops = ops;
 
return swdev;
 }
@@ -442,7 +439,6 @@ int ksz_switch_register(struct ksz_device *dev,
}
 
mutex_init(&dev->dev_mutex);
-   mutex_init(&dev->reg_mutex);
mutex_init(&dev->stats_mutex);
mutex_init(&dev->alu_mutex);
mutex_init(&dev->vlan_mutex);
diff --git a/drivers/net/dsa/microchip/ksz_common.h 
b/drivers/net/dsa/microchip/ksz_common.h
index fe576a00facf..c3871ed9b097 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -7,6 +7,8 @@
 #ifndef __KSZ_COMMON_H
 #define __KSZ_COMMON_H
 
+#include 
+
 void ksz_port_cleanup(struct ksz_device *dev, int port);
 void ksz_update_port_member(struct ksz_device *dev, int port);
 void ksz_init_mib_timer(struct ksz_device *dev);
@@ -41,68 +43,44 @@ void ksz_disable_port(struct dsa_switch *ds, int port);
 
 static inline int ksz_read8(struct ksz_device *dev, u32 reg, u8 *val)
 {
-   int ret;
-
-   mutex_lock(&dev->reg_mutex);
-   ret = dev->ops->read8(dev, reg, val);
-   mutex_unlock(&dev->reg_mutex);
+   unsigned int value;
+   int ret = regmap_read(dev->regmap[0], reg, &value);
 
+   *val = value;
return ret;
 }
 
 static inline int ksz_read16(struct ksz_device *dev, u32 reg, u16 *val)
 {
-   int ret;
-
-   mutex_lock(

[PATCH V4 04/10] net: dsa: microchip: Move ksz_cfg and ksz_port_cfg to ksz9477.c

2019-06-25 Thread Marek Vasut
These functions are only used by the KSZ9477 code, move them from
the header into that code. Note that these functions will be soon
replaced by regmap equivalents.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Woojung Huh 
Reviewed-by: Andrew Lunn 
---
V2: New patch
V3: - Rebase on next/master
- Test on KSZ9477EVB
V4: Add RB
---
 drivers/net/dsa/microchip/ksz9477.c| 29 ++
 drivers/net/dsa/microchip/ksz_common.h | 29 --
 2 files changed, 29 insertions(+), 29 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz9477.c 
b/drivers/net/dsa/microchip/ksz9477.c
index 508380f80875..e8b96566abd9 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -65,6 +65,35 @@ static const struct {
{ 0x83, "tx_discards" },
 };
 
+static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set)
+{
+   u8 data;
+
+   ksz_read8(dev, addr, &data);
+   if (set)
+   data |= bits;
+   else
+   data &= ~bits;
+   ksz_write8(dev, addr, data);
+}
+
+static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits,
+bool set)
+{
+   u32 addr;
+   u8 data;
+
+   addr = dev->dev_ops->get_port_addr(port, offset);
+   ksz_read8(dev, addr, &data);
+
+   if (set)
+   data |= bits;
+   else
+   data &= ~bits;
+
+   ksz_write8(dev, addr, data);
+}
+
 static void ksz9477_cfg32(struct ksz_device *dev, u32 addr, u32 bits, bool set)
 {
u32 data;
diff --git a/drivers/net/dsa/microchip/ksz_common.h 
b/drivers/net/dsa/microchip/ksz_common.h
index c15b49528bad..fe576a00facf 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -141,35 +141,6 @@ static inline void ksz_pwrite32(struct ksz_device *dev, 
int port, int offset,
ksz_write32(dev, dev->dev_ops->get_port_addr(port, offset), data);
 }
 
-static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set)
-{
-   u8 data;
-
-   ksz_read8(dev, addr, &data);
-   if (set)
-   data |= bits;
-   else
-   data &= ~bits;
-   ksz_write8(dev, addr, data);
-}
-
-static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits,
-bool set)
-{
-   u32 addr;
-   u8 data;
-
-   addr = dev->dev_ops->get_port_addr(port, offset);
-   ksz_read8(dev, addr, &data);
-
-   if (set)
-   data |= bits;
-   else
-   data &= ~bits;
-
-   ksz_write8(dev, addr, data);
-}
-
 struct ksz_poll_ctx {
struct ksz_device *dev;
int port;
-- 
2.20.1



[PATCH V4 00/10] net: dsa: microchip: Convert to regmap

2019-06-25 Thread Marek Vasut
This patchset converts KSZ9477 switch driver to regmap.

This was tested with extra patches on KSZ8795. This was also tested
on KSZ9477 on Microchip KSZ9477EVB board, which I now have.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Woojung Huh 

Marek Vasut (10):
  net: dsa: microchip: Remove ksz_{read,write}24()
  net: dsa: microchip: Remove ksz_{get,set}()
  net: dsa: microchip: Inline ksz_spi.h
  net: dsa: microchip: Move ksz_cfg and ksz_port_cfg to ksz9477.c
  net: dsa: microchip: Use PORT_CTRL_ADDR() instead of indirect function
call
  net: dsa: microchip: Factor out register access opcode generation
  net: dsa: microchip: Initial SPI regmap support
  net: dsa: microchip: Dispose of ksz_io_ops
  net: dsa: microchip: Factor out regmap config generation into common
header
  net: dsa: microchip: Replace ad-hoc bit manipulation with regmap

 drivers/net/dsa/microchip/Kconfig   |   1 +
 drivers/net/dsa/microchip/ksz9477.c |  35 +++---
 drivers/net/dsa/microchip/ksz9477_spi.c | 114 +++--
 drivers/net/dsa/microchip/ksz_common.c  |   6 +-
 drivers/net/dsa/microchip/ksz_common.h  | 157 +++-
 drivers/net/dsa/microchip/ksz_priv.h|  23 +---
 drivers/net/dsa/microchip/ksz_spi.h |  69 ---
 7 files changed, 84 insertions(+), 321 deletions(-)
 delete mode 100644 drivers/net/dsa/microchip/ksz_spi.h

-- 
2.20.1



[PATCH V4 07/10] net: dsa: microchip: Initial SPI regmap support

2019-06-25 Thread Marek Vasut
Add basic SPI regmap support into the driver.

Previous patches unconver that ksz_spi_write() is always ever called
with len = 1, 2 or 4. We can thus drop the if (len > SPI_TX_BUF_LEN)
check and we can also drop the allocation of the txbuf which is part
of the driver data and wastes 256 bytes for no reason. Regmap covers
the whole thing now.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Woojung Huh 
---
V2: - Squash with "net: dsa: microchip: Remove dev->txbuf"
- Use separate regmaps for 8/16/32bit registers
- Increase the regmap size to 0xd00 to cover the entire register area
V3: - Rebase on next/master
- Test on KSZ9477EVB
- Increase regmap max register, to cover all switch registers
- Correct regmap reg_bits value to match the hardware
- Use cpu_to_be32() instead of cpu_to_le16() in register masks, since
  the KSZ9477 has some 32bit registers.
V4: - Replace cpu_to_be32() with swab32() in regmap read/write_flag_masks.
- Move REGMAP_SPI to NET_DSA_MICROCHIP_KSZ9477_SPI in Kconfig
---
 drivers/net/dsa/microchip/Kconfig   |   1 +
 drivers/net/dsa/microchip/ksz9477_spi.c | 114 +++-
 drivers/net/dsa/microchip/ksz_priv.h|   3 +-
 3 files changed, 52 insertions(+), 66 deletions(-)

diff --git a/drivers/net/dsa/microchip/Kconfig 
b/drivers/net/dsa/microchip/Kconfig
index 2c3a6751bdaf..fe0a13b79c4b 100644
--- a/drivers/net/dsa/microchip/Kconfig
+++ b/drivers/net/dsa/microchip/Kconfig
@@ -13,5 +13,6 @@ menuconfig NET_DSA_MICROCHIP_KSZ9477
 config NET_DSA_MICROCHIP_KSZ9477_SPI
tristate "KSZ9477 series SPI connected switch driver"
depends on NET_DSA_MICROCHIP_KSZ9477 && SPI
+   select REGMAP_SPI
help
  Select to enable support for registering switches configured through 
SPI.
diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c 
b/drivers/net/dsa/microchip/ksz9477_spi.c
index 49aeb92d36fc..c72645354dc2 100644
--- a/drivers/net/dsa/microchip/ksz9477_spi.c
+++ b/drivers/net/dsa/microchip/ksz9477_spi.c
@@ -10,78 +10,54 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "ksz_priv.h"
 
-/* SPI frame opcodes */
-#define KS_SPIOP_RD3
-#define KS_SPIOP_WR2
-
 #define SPI_ADDR_SHIFT 24
-#define SPI_ADDR_MASK  (BIT(SPI_ADDR_SHIFT) - 1)
+#define SPI_ADDR_ALIGN 3
 #define SPI_TURNAROUND_SHIFT   5
 
-/* Enough to read all switch port registers. */
-#define SPI_TX_BUF_LEN 0x100
-
-static u32 ksz9477_spi_cmd(u32 reg, bool read)
-{
-   u32 txbuf;
-
-   txbuf = reg & SPI_ADDR_MASK;
-   txbuf |= (read ? KS_SPIOP_RD : KS_SPIOP_WR) << SPI_ADDR_SHIFT;
-   txbuf <<= SPI_TURNAROUND_SHIFT;
-   txbuf = cpu_to_be32(txbuf);
-
-   return txbuf;
-}
-
-static int ksz9477_spi_read_reg(struct spi_device *spi, u32 reg, u8 *val,
-   unsigned int len)
-{
-   u32 txbuf = ksz9477_spi_cmd(reg, true);
-
-   return spi_write_then_read(spi, &txbuf, 4, val, len);
-}
-
-static int ksz9477_spi_write_reg(struct spi_device *spi, u32 reg, u8 *val,
-unsigned int len)
-{
-   u32 *txbuf = (u32 *)val;
-
-   *txbuf = ksz9477_spi_cmd(reg, false);
-
-   return spi_write(spi, txbuf, 4 + len);
-}
-
-static int ksz_spi_read(struct ksz_device *dev, u32 reg, u8 *data,
-   unsigned int len)
-{
-   struct spi_device *spi = dev->priv;
-
-   return ksz9477_spi_read_reg(spi, reg, data, len);
-}
-
-static int ksz_spi_write(struct ksz_device *dev, u32 reg, void *data,
-unsigned int len)
-{
-   struct spi_device *spi = dev->priv;
+/* SPI frame opcodes */
+#define KS_SPIOP_RD3
+#define KS_SPIOP_WR2
 
-   if (len > SPI_TX_BUF_LEN)
-   len = SPI_TX_BUF_LEN;
-   memcpy(&dev->txbuf[4], data, len);
-   return ksz9477_spi_write_reg(spi, reg, dev->txbuf, len);
-}
+#define KS_SPIOP_FLAG_MASK(opcode) \
+   swab32((opcode) << (SPI_ADDR_SHIFT + SPI_TURNAROUND_SHIFT))
+
+#define KSZ_REGMAP_COMMON(width)   \
+   {   \
+   .val_bits = (width),\
+   .reg_stride = (width) / 8,  \
+   .reg_bits = SPI_ADDR_SHIFT + SPI_ADDR_ALIGN,\
+   .pad_bits = SPI_TURNAROUND_SHIFT,   \
+   .max_register = BIT(SPI_ADDR_SHIFT) - 1,\
+   .cache_type = REGCACHE_NONE,\
+   .read_flag_mask = KS_SPIOP_FLAG_MASK(KS_SPIOP_RD),  \
+   .write_flag_mask = KS_S

[PATCH V4 01/10] net: dsa: microchip: Remove ksz_{read,write}24()

2019-06-25 Thread Marek Vasut
These functions and callbacks are never used, remove them.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Woojung Huh 
Reviewed-by: Andrew Lunn 
---
V2: No change
V3: - Rebase on next/master
- Test on KSZ9477EVB
V4: Add RB
---
 drivers/net/dsa/microchip/ksz9477_spi.c | 25 -
 drivers/net/dsa/microchip/ksz_common.h  | 22 --
 drivers/net/dsa/microchip/ksz_priv.h|  2 --
 3 files changed, 49 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c 
b/drivers/net/dsa/microchip/ksz9477_spi.c
index 75178624d3f5..e7118319c192 100644
--- a/drivers/net/dsa/microchip/ksz9477_spi.c
+++ b/drivers/net/dsa/microchip/ksz9477_spi.c
@@ -73,37 +73,12 @@ static int ksz_spi_write(struct ksz_device *dev, u32 reg, 
void *data,
return ksz9477_spi_write_reg(spi, reg, dev->txbuf, len);
 }
 
-static int ksz_spi_read24(struct ksz_device *dev, u32 reg, u32 *val)
-{
-   int ret;
-
-   *val = 0;
-   ret = ksz_spi_read(dev, reg, (u8 *)val, 3);
-   if (!ret) {
-   *val = be32_to_cpu(*val);
-   /* convert to 24bit */
-   *val >>= 8;
-   }
-
-   return ret;
-}
-
-static int ksz_spi_write24(struct ksz_device *dev, u32 reg, u32 value)
-{
-   /* make it to big endian 24bit from MSB */
-   value <<= 8;
-   value = cpu_to_be32(value);
-   return ksz_spi_write(dev, reg, &value, 3);
-}
-
 static const struct ksz_io_ops ksz9477_spi_ops = {
.read8 = ksz_spi_read8,
.read16 = ksz_spi_read16,
-   .read24 = ksz_spi_read24,
.read32 = ksz_spi_read32,
.write8 = ksz_spi_write8,
.write16 = ksz_spi_write16,
-   .write24 = ksz_spi_write24,
.write32 = ksz_spi_write32,
.get = ksz_spi_get,
.set = ksz_spi_set,
diff --git a/drivers/net/dsa/microchip/ksz_common.h 
b/drivers/net/dsa/microchip/ksz_common.h
index 21cd794e18f1..1781539c3a81 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -61,17 +61,6 @@ static inline int ksz_read16(struct ksz_device *dev, u32 
reg, u16 *val)
return ret;
 }
 
-static inline int ksz_read24(struct ksz_device *dev, u32 reg, u32 *val)
-{
-   int ret;
-
-   mutex_lock(&dev->reg_mutex);
-   ret = dev->ops->read24(dev, reg, val);
-   mutex_unlock(&dev->reg_mutex);
-
-   return ret;
-}
-
 static inline int ksz_read32(struct ksz_device *dev, u32 reg, u32 *val)
 {
int ret;
@@ -105,17 +94,6 @@ static inline int ksz_write16(struct ksz_device *dev, u32 
reg, u16 value)
return ret;
 }
 
-static inline int ksz_write24(struct ksz_device *dev, u32 reg, u32 value)
-{
-   int ret;
-
-   mutex_lock(&dev->reg_mutex);
-   ret = dev->ops->write24(dev, reg, value);
-   mutex_unlock(&dev->reg_mutex);
-
-   return ret;
-}
-
 static inline int ksz_write32(struct ksz_device *dev, u32 reg, u32 value)
 {
int ret;
diff --git a/drivers/net/dsa/microchip/ksz_priv.h 
b/drivers/net/dsa/microchip/ksz_priv.h
index c615d2a81dd5..5ef6153bd2cc 100644
--- a/drivers/net/dsa/microchip/ksz_priv.h
+++ b/drivers/net/dsa/microchip/ksz_priv.h
@@ -105,11 +105,9 @@ struct ksz_device {
 struct ksz_io_ops {
int (*read8)(struct ksz_device *dev, u32 reg, u8 *value);
int (*read16)(struct ksz_device *dev, u32 reg, u16 *value);
-   int (*read24)(struct ksz_device *dev, u32 reg, u32 *value);
int (*read32)(struct ksz_device *dev, u32 reg, u32 *value);
int (*write8)(struct ksz_device *dev, u32 reg, u8 value);
int (*write16)(struct ksz_device *dev, u32 reg, u16 value);
-   int (*write24)(struct ksz_device *dev, u32 reg, u32 value);
int (*write32)(struct ksz_device *dev, u32 reg, u32 value);
int (*get)(struct ksz_device *dev, u32 reg, void *data, size_t len);
int (*set)(struct ksz_device *dev, u32 reg, void *data, size_t len);
-- 
2.20.1



[PATCH V4 05/10] net: dsa: microchip: Use PORT_CTRL_ADDR() instead of indirect function call

2019-06-25 Thread Marek Vasut
The indirect function call to dev->dev_ops->get_port_addr() is expensive
especially if called for every single register access, and only returns
the value of PORT_CTRL_ADDR() macro. Use PORT_CTRL_ADDR() macro directly
instead.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Woojung Huh 
---
V2: New patch
V3: - Rebase on next/master
- Test on KSZ9477EVB
V4: No change
---
 drivers/net/dsa/microchip/ksz9477.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/dsa/microchip/ksz9477.c 
b/drivers/net/dsa/microchip/ksz9477.c
index e8b96566abd9..7d209fd9f26f 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -83,7 +83,7 @@ static void ksz_port_cfg(struct ksz_device *dev, int port, 
int offset, u8 bits,
u32 addr;
u8 data;
 
-   addr = dev->dev_ops->get_port_addr(port, offset);
+   addr = PORT_CTRL_ADDR(port, offset);
ksz_read8(dev, addr, &data);
 
if (set)
-- 
2.20.1



[PATCH V4 03/10] net: dsa: microchip: Inline ksz_spi.h

2019-06-25 Thread Marek Vasut
The functions in the header file are static, and the header file is
included from single C file, just inline the code into the C file.
The bonus is that it's easier to spot further content to clean up.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Woojung Huh 
Reviewed-by: Andrew Lunn 
---
V2: No change
V3: - Rebase on next/master
- Test on KSZ9477EVB
V4: Add RB
---
 drivers/net/dsa/microchip/ksz9477_spi.c | 43 +-
 drivers/net/dsa/microchip/ksz_spi.h | 59 -
 2 files changed, 42 insertions(+), 60 deletions(-)
 delete mode 100644 drivers/net/dsa/microchip/ksz_spi.h

diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c 
b/drivers/net/dsa/microchip/ksz9477_spi.c
index 86d12d48a2a9..a34e66eccbcd 100644
--- a/drivers/net/dsa/microchip/ksz9477_spi.c
+++ b/drivers/net/dsa/microchip/ksz9477_spi.c
@@ -13,7 +13,6 @@
 #include 
 
 #include "ksz_priv.h"
-#include "ksz_spi.h"
 
 /* SPI frame opcodes */
 #define KS_SPIOP_RD3
@@ -73,6 +72,48 @@ static int ksz_spi_write(struct ksz_device *dev, u32 reg, 
void *data,
return ksz9477_spi_write_reg(spi, reg, dev->txbuf, len);
 }
 
+static int ksz_spi_read8(struct ksz_device *dev, u32 reg, u8 *val)
+{
+   return ksz_spi_read(dev, reg, val, 1);
+}
+
+static int ksz_spi_read16(struct ksz_device *dev, u32 reg, u16 *val)
+{
+   int ret = ksz_spi_read(dev, reg, (u8 *)val, 2);
+
+   if (!ret)
+   *val = be16_to_cpu(*val);
+
+   return ret;
+}
+
+static int ksz_spi_read32(struct ksz_device *dev, u32 reg, u32 *val)
+{
+   int ret = ksz_spi_read(dev, reg, (u8 *)val, 4);
+
+   if (!ret)
+   *val = be32_to_cpu(*val);
+
+   return ret;
+}
+
+static int ksz_spi_write8(struct ksz_device *dev, u32 reg, u8 value)
+{
+   return ksz_spi_write(dev, reg, &value, 1);
+}
+
+static int ksz_spi_write16(struct ksz_device *dev, u32 reg, u16 value)
+{
+   value = cpu_to_be16(value);
+   return ksz_spi_write(dev, reg, &value, 2);
+}
+
+static int ksz_spi_write32(struct ksz_device *dev, u32 reg, u32 value)
+{
+   value = cpu_to_be32(value);
+   return ksz_spi_write(dev, reg, &value, 4);
+}
+
 static const struct ksz_io_ops ksz9477_spi_ops = {
.read8 = ksz_spi_read8,
.read16 = ksz_spi_read16,
diff --git a/drivers/net/dsa/microchip/ksz_spi.h 
b/drivers/net/dsa/microchip/ksz_spi.h
deleted file mode 100644
index 976bace31f37..
--- a/drivers/net/dsa/microchip/ksz_spi.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0
- * Microchip KSZ series SPI access common header
- *
- * Copyright (C) 2017-2018 Microchip Technology Inc.
- * Tristram Ha 
- */
-
-#ifndef __KSZ_SPI_H
-#define __KSZ_SPI_H
-
-/* Chip dependent SPI access */
-static int ksz_spi_read(struct ksz_device *dev, u32 reg, u8 *data,
-   unsigned int len);
-static int ksz_spi_write(struct ksz_device *dev, u32 reg, void *data,
-unsigned int len);
-
-static int ksz_spi_read8(struct ksz_device *dev, u32 reg, u8 *val)
-{
-   return ksz_spi_read(dev, reg, val, 1);
-}
-
-static int ksz_spi_read16(struct ksz_device *dev, u32 reg, u16 *val)
-{
-   int ret = ksz_spi_read(dev, reg, (u8 *)val, 2);
-
-   if (!ret)
-   *val = be16_to_cpu(*val);
-
-   return ret;
-}
-
-static int ksz_spi_read32(struct ksz_device *dev, u32 reg, u32 *val)
-{
-   int ret = ksz_spi_read(dev, reg, (u8 *)val, 4);
-
-   if (!ret)
-   *val = be32_to_cpu(*val);
-
-   return ret;
-}
-
-static int ksz_spi_write8(struct ksz_device *dev, u32 reg, u8 value)
-{
-   return ksz_spi_write(dev, reg, &value, 1);
-}
-
-static int ksz_spi_write16(struct ksz_device *dev, u32 reg, u16 value)
-{
-   value = cpu_to_be16(value);
-   return ksz_spi_write(dev, reg, &value, 2);
-}
-
-static int ksz_spi_write32(struct ksz_device *dev, u32 reg, u32 value)
-{
-   value = cpu_to_be32(value);
-   return ksz_spi_write(dev, reg, &value, 4);
-}
-
-#endif
-- 
2.20.1



[PATCH V4 02/10] net: dsa: microchip: Remove ksz_{get,set}()

2019-06-25 Thread Marek Vasut
These functions and callbacks are never used, remove them.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Woojung Huh 
Reviewed-by: Andrew Lunn 
---
V2: No change
V3: - Rebase on next/master
- Test on KSZ9477EVB
V4: Add RB
---
 drivers/net/dsa/microchip/ksz9477_spi.c |  2 --
 drivers/net/dsa/microchip/ksz_common.h  | 24 
 drivers/net/dsa/microchip/ksz_priv.h|  2 --
 drivers/net/dsa/microchip/ksz_spi.h | 10 --
 4 files changed, 38 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c 
b/drivers/net/dsa/microchip/ksz9477_spi.c
index e7118319c192..86d12d48a2a9 100644
--- a/drivers/net/dsa/microchip/ksz9477_spi.c
+++ b/drivers/net/dsa/microchip/ksz9477_spi.c
@@ -80,8 +80,6 @@ static const struct ksz_io_ops ksz9477_spi_ops = {
.write8 = ksz_spi_write8,
.write16 = ksz_spi_write16,
.write32 = ksz_spi_write32,
-   .get = ksz_spi_get,
-   .set = ksz_spi_set,
 };
 
 static int ksz9477_spi_probe(struct spi_device *spi)
diff --git a/drivers/net/dsa/microchip/ksz_common.h 
b/drivers/net/dsa/microchip/ksz_common.h
index 1781539c3a81..c15b49528bad 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -105,30 +105,6 @@ static inline int ksz_write32(struct ksz_device *dev, u32 
reg, u32 value)
return ret;
 }
 
-static inline int ksz_get(struct ksz_device *dev, u32 reg, void *data,
- size_t len)
-{
-   int ret;
-
-   mutex_lock(&dev->reg_mutex);
-   ret = dev->ops->get(dev, reg, data, len);
-   mutex_unlock(&dev->reg_mutex);
-
-   return ret;
-}
-
-static inline int ksz_set(struct ksz_device *dev, u32 reg, void *data,
- size_t len)
-{
-   int ret;
-
-   mutex_lock(&dev->reg_mutex);
-   ret = dev->ops->set(dev, reg, data, len);
-   mutex_unlock(&dev->reg_mutex);
-
-   return ret;
-}
-
 static inline void ksz_pread8(struct ksz_device *dev, int port, int offset,
  u8 *data)
 {
diff --git a/drivers/net/dsa/microchip/ksz_priv.h 
b/drivers/net/dsa/microchip/ksz_priv.h
index 5ef6153bd2cc..d3ddf98156bb 100644
--- a/drivers/net/dsa/microchip/ksz_priv.h
+++ b/drivers/net/dsa/microchip/ksz_priv.h
@@ -109,8 +109,6 @@ struct ksz_io_ops {
int (*write8)(struct ksz_device *dev, u32 reg, u8 value);
int (*write16)(struct ksz_device *dev, u32 reg, u16 value);
int (*write32)(struct ksz_device *dev, u32 reg, u32 value);
-   int (*get)(struct ksz_device *dev, u32 reg, void *data, size_t len);
-   int (*set)(struct ksz_device *dev, u32 reg, void *data, size_t len);
 };
 
 struct alu_struct {
diff --git a/drivers/net/dsa/microchip/ksz_spi.h 
b/drivers/net/dsa/microchip/ksz_spi.h
index 427811bd60b3..976bace31f37 100644
--- a/drivers/net/dsa/microchip/ksz_spi.h
+++ b/drivers/net/dsa/microchip/ksz_spi.h
@@ -56,14 +56,4 @@ static int ksz_spi_write32(struct ksz_device *dev, u32 reg, 
u32 value)
return ksz_spi_write(dev, reg, &value, 4);
 }
 
-static int ksz_spi_get(struct ksz_device *dev, u32 reg, void *data, size_t len)
-{
-   return ksz_spi_read(dev, reg, data, len);
-}
-
-static int ksz_spi_set(struct ksz_device *dev, u32 reg, void *data, size_t len)
-{
-   return ksz_spi_write(dev, reg, data, len);
-}
-
 #endif
-- 
2.20.1



[PATCH 1/5] net: dsa: microchip: Replace ad-hoc polling with regmap

2019-06-27 Thread Marek Vasut
Regmap provides polling function to poll for bits in a register,
use in instead of reimplementing it.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Woojung Huh 
---
 drivers/net/dsa/microchip/ksz9477.c| 14 +-
 drivers/net/dsa/microchip/ksz_common.h | 14 --
 2 files changed, 5 insertions(+), 23 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz9477.c 
b/drivers/net/dsa/microchip/ksz9477.c
index 8f13dcc05a10..ece25f38e02a 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -263,12 +263,8 @@ static int ksz9477_reset_switch(struct ksz_device *dev)
 static void ksz9477_r_mib_cnt(struct ksz_device *dev, int port, u16 addr,
  u64 *cnt)
 {
-   struct ksz_poll_ctx ctx = {
-   .dev = dev,
-   .port = port,
-   .offset = REG_PORT_MIB_CTRL_STAT__4,
-   };
struct ksz_port *p = &dev->ports[port];
+   unsigned int val;
u32 data;
int ret;
 
@@ -278,11 +274,11 @@ static void ksz9477_r_mib_cnt(struct ksz_device *dev, int 
port, u16 addr,
data |= (addr << MIB_COUNTER_INDEX_S);
ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, data);
 
-   ret = readx_poll_timeout(ksz_pread32_poll, &ctx, data,
-!(data & MIB_COUNTER_READ), 10, 1000);
-
+   ret = regmap_read_poll_timeout(dev->regmap[2],
+   PORT_CTRL_ADDR(port, REG_PORT_MIB_CTRL_STAT__4),
+   val, !(val & MIB_COUNTER_READ), 10, 1000);
/* failed to read MIB. get out of loop */
-   if (ret < 0) {
+   if (ret) {
dev_dbg(dev->dev, "Failed to get MIB\n");
return;
}
diff --git a/drivers/net/dsa/microchip/ksz_common.h 
b/drivers/net/dsa/microchip/ksz_common.h
index 745318424f71..ee7096d8af07 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -119,20 +119,6 @@ static inline void ksz_pwrite32(struct ksz_device *dev, 
int port, int offset,
ksz_write32(dev, dev->dev_ops->get_port_addr(port, offset), data);
 }
 
-struct ksz_poll_ctx {
-   struct ksz_device *dev;
-   int port;
-   int offset;
-};
-
-static inline u32 ksz_pread32_poll(struct ksz_poll_ctx *ctx)
-{
-   u32 data;
-
-   ksz_pread32(ctx->dev, ctx->port, ctx->offset, &data);
-   return data;
-}
-
 /* Regmap tables generation */
 #define KSZ_SPI_OP_RD  3
 #define KSZ_SPI_OP_WR  2
-- 
2.20.1



[PATCH 2/5] net: dsa: microchip: Replace ksz9477_wait_vlan_ctrl_ready polling with regmap

2019-06-27 Thread Marek Vasut
Regmap provides polling function to poll for bits in a register. This
function is another reimplementation of polling for bit being clear in
a register. Replace this with regmap polling function. Moreover, inline
the function parameters, as the function is never called with any other
parameter values than this one.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Woojung Huh 
---
 drivers/net/dsa/microchip/ksz9477.c | 26 --
 1 file changed, 8 insertions(+), 18 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz9477.c 
b/drivers/net/dsa/microchip/ksz9477.c
index ece25f38e02a..0aab00bf23b9 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -89,22 +89,12 @@ static void ksz9477_port_cfg32(struct ksz_device *dev, int 
port, int offset,
   bits, set ? bits : 0);
 }
 
-static int ksz9477_wait_vlan_ctrl_ready(struct ksz_device *dev, u32 waiton,
-   int timeout)
+static int ksz9477_wait_vlan_ctrl_ready(struct ksz_device *dev)
 {
-   u8 data;
-
-   do {
-   ksz_read8(dev, REG_SW_VLAN_CTRL, &data);
-   if (!(data & waiton))
-   break;
-   usleep_range(1, 10);
-   } while (timeout-- > 0);
-
-   if (timeout <= 0)
-   return -ETIMEDOUT;
+   unsigned int val;
 
-   return 0;
+   return regmap_read_poll_timeout(dev->regmap[0], REG_SW_VLAN_CTRL,
+   val, !(val & VLAN_START), 10, 1000);
 }
 
 static int ksz9477_get_vlan_table(struct ksz_device *dev, u16 vid,
@@ -118,8 +108,8 @@ static int ksz9477_get_vlan_table(struct ksz_device *dev, 
u16 vid,
ksz_write8(dev, REG_SW_VLAN_CTRL, VLAN_READ | VLAN_START);
 
/* wait to be cleared */
-   ret = ksz9477_wait_vlan_ctrl_ready(dev, VLAN_START, 1000);
-   if (ret < 0) {
+   ret = ksz9477_wait_vlan_ctrl_ready(dev);
+   if (ret) {
dev_dbg(dev->dev, "Failed to read vlan table\n");
goto exit;
}
@@ -151,8 +141,8 @@ static int ksz9477_set_vlan_table(struct ksz_device *dev, 
u16 vid,
ksz_write8(dev, REG_SW_VLAN_CTRL, VLAN_START | VLAN_WRITE);
 
/* wait to be cleared */
-   ret = ksz9477_wait_vlan_ctrl_ready(dev, VLAN_START, 1000);
-   if (ret < 0) {
+   ret = ksz9477_wait_vlan_ctrl_ready(dev);
+   if (ret) {
dev_dbg(dev->dev, "Failed to write vlan table\n");
goto exit;
}
-- 
2.20.1



[PATCH 4/5] net: dsa: microchip: Replace ksz9477_wait_alu_sta_ready polling with regmap

2019-06-27 Thread Marek Vasut
Regmap provides polling function to poll for bits in a register. This
function is another reimplementation of polling for bit being clear in
a register. Replace this with regmap polling function. Moreover, inline
the function parameters, as the function is never called with any other
parameter values than this one.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Woojung Huh 
---
 drivers/net/dsa/microchip/ksz9477.c | 32 +++--
 1 file changed, 12 insertions(+), 20 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz9477.c 
b/drivers/net/dsa/microchip/ksz9477.c
index e5b2f3e45db6..bfc44799854c 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -184,22 +184,14 @@ static int ksz9477_wait_alu_ready(struct ksz_device *dev)
val, !(val & ALU_START), 10, 1000);
 }
 
-static int ksz9477_wait_alu_sta_ready(struct ksz_device *dev, u32 waiton,
- int timeout)
+static int ksz9477_wait_alu_sta_ready(struct ksz_device *dev)
 {
-   u32 data;
-
-   do {
-   ksz_read32(dev, REG_SW_ALU_STAT_CTRL__4, &data);
-   if (!(data & waiton))
-   break;
-   usleep_range(1, 10);
-   } while (timeout-- > 0);
-
-   if (timeout <= 0)
-   return -ETIMEDOUT;
+   unsigned int val;
 
-   return 0;
+   return regmap_read_poll_timeout(dev->regmap[2],
+   REG_SW_ALU_STAT_CTRL__4,
+   val, !(val & ALU_STAT_START),
+   10, 1000);
 }
 
 static int ksz9477_reset_switch(struct ksz_device *dev)
@@ -821,7 +813,7 @@ static void ksz9477_port_mdb_add(struct dsa_switch *ds, int 
port,
ksz_write32(dev, REG_SW_ALU_STAT_CTRL__4, data);
 
/* wait to be finished */
-   if (ksz9477_wait_alu_sta_ready(dev, ALU_STAT_START, 1000) < 0) {
+   if (ksz9477_wait_alu_sta_ready(dev)) {
dev_dbg(dev->dev, "Failed to read ALU STATIC\n");
goto exit;
}
@@ -862,7 +854,7 @@ static void ksz9477_port_mdb_add(struct dsa_switch *ds, int 
port,
ksz_write32(dev, REG_SW_ALU_STAT_CTRL__4, data);
 
/* wait to be finished */
-   if (ksz9477_wait_alu_sta_ready(dev, ALU_STAT_START, 1000) < 0)
+   if (ksz9477_wait_alu_sta_ready(dev))
dev_dbg(dev->dev, "Failed to read ALU STATIC\n");
 
 exit:
@@ -892,8 +884,8 @@ static int ksz9477_port_mdb_del(struct dsa_switch *ds, int 
port,
ksz_write32(dev, REG_SW_ALU_STAT_CTRL__4, data);
 
/* wait to be finished */
-   ret = ksz9477_wait_alu_sta_ready(dev, ALU_STAT_START, 1000);
-   if (ret < 0) {
+   ret = ksz9477_wait_alu_sta_ready(dev);
+   if (ret) {
dev_dbg(dev->dev, "Failed to read ALU STATIC\n");
goto exit;
}
@@ -934,8 +926,8 @@ static int ksz9477_port_mdb_del(struct dsa_switch *ds, int 
port,
ksz_write32(dev, REG_SW_ALU_STAT_CTRL__4, data);
 
/* wait to be finished */
-   ret = ksz9477_wait_alu_sta_ready(dev, ALU_STAT_START, 1000);
-   if (ret < 0)
+   ret = ksz9477_wait_alu_sta_ready(dev);
+   if (ret)
dev_dbg(dev->dev, "Failed to read ALU STATIC\n");
 
 exit:
-- 
2.20.1



[PATCH 5/5] net: dsa: microchip: Replace bit RMW with regmap

2019-06-27 Thread Marek Vasut
Regmap provides read-modify-write function to update bitfields in
registers. Replace ad-hoc read-modify-write with regmap_update_bits()
where applicable.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Woojung Huh 
---
 drivers/net/dsa/microchip/ksz9477.c | 22 ++
 1 file changed, 10 insertions(+), 12 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz9477.c 
b/drivers/net/dsa/microchip/ksz9477.c
index bfc44799854c..a8c97f7a79b7 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -197,16 +197,14 @@ static int ksz9477_wait_alu_sta_ready(struct ksz_device 
*dev)
 static int ksz9477_reset_switch(struct ksz_device *dev)
 {
u8 data8;
-   u16 data16;
u32 data32;
 
/* reset switch */
ksz_cfg(dev, REG_SW_OPERATION, SW_RESET, true);
 
/* turn off SPI DO Edge select */
-   ksz_read8(dev, REG_SW_GLOBAL_SERIAL_CTRL_0, &data8);
-   data8 &= ~SPI_AUTO_EDGE_DETECTION;
-   ksz_write8(dev, REG_SW_GLOBAL_SERIAL_CTRL_0, data8);
+   regmap_update_bits(dev->regmap[0], REG_SW_GLOBAL_SERIAL_CTRL_0,
+  SPI_AUTO_EDGE_DETECTION, 0);
 
/* default configuration */
ksz_read8(dev, REG_SW_LUE_CTRL_1, &data8);
@@ -220,10 +218,10 @@ static int ksz9477_reset_switch(struct ksz_device *dev)
ksz_read32(dev, REG_SW_PORT_INT_STATUS__4, &data32);
 
/* set broadcast storm protection 10% rate */
-   ksz_read16(dev, REG_SW_MAC_CTRL_2, &data16);
-   data16 &= ~BROADCAST_STORM_RATE;
-   data16 |= (BROADCAST_STORM_VALUE * BROADCAST_STORM_PROT_RATE) / 100;
-   ksz_write16(dev, REG_SW_MAC_CTRL_2, data16);
+   regmap_update_bits(dev->regmap[1], REG_SW_MAC_CTRL_2,
+  BROADCAST_STORM_RATE,
+  (BROADCAST_STORM_VALUE *
+  BROADCAST_STORM_PROT_RATE) / 100);
 
if (dev->synclko_125)
ksz_write8(dev, REG_SW_GLOBAL_OUTPUT_CTRL__1,
@@ -485,10 +483,10 @@ static void ksz9477_flush_dyn_mac_table(struct ksz_device 
*dev, int port)
 {
u8 data;
 
-   ksz_read8(dev, REG_SW_LUE_CTRL_2, &data);
-   data &= ~(SW_FLUSH_OPTION_M << SW_FLUSH_OPTION_S);
-   data |= (SW_FLUSH_OPTION_DYN_MAC << SW_FLUSH_OPTION_S);
-   ksz_write8(dev, REG_SW_LUE_CTRL_2, data);
+   regmap_update_bits(dev->regmap[0], REG_SW_LUE_CTRL_2,
+  SW_FLUSH_OPTION_M << SW_FLUSH_OPTION_S,
+  SW_FLUSH_OPTION_DYN_MAC << SW_FLUSH_OPTION_S);
+
if (port < dev->mib_port_cnt) {
/* flush individual port */
ksz_pread8(dev, port, P_STP_CTRL, &data);
-- 
2.20.1



[PATCH 0/5] net: dsa: microchip: Further regmap cleanups

2019-06-27 Thread Marek Vasut
This patchset cleans up KSZ9477 switch driver by replacing various
ad-hoc polling implementations and register RMW with regmap functions.

Each polling function is replaced separately to make it easier to review
and possibly bisect, but maybe the patches can be squashed.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Woojung Huh 

Marek Vasut (5):
  net: dsa: microchip: Replace ad-hoc polling with regmap
  net: dsa: microchip: Replace ksz9477_wait_vlan_ctrl_ready polling with
regmap
  net: dsa: microchip: Replace ksz9477_wait_alu_ready polling with
regmap
  net: dsa: microchip: Replace ksz9477_wait_alu_sta_ready polling with
regmap
  net: dsa: microchip: Replace bit RMW with regmap

 drivers/net/dsa/microchip/ksz9477.c| 128 +
 drivers/net/dsa/microchip/ksz_common.h |  14 ---
 2 files changed, 47 insertions(+), 95 deletions(-)

-- 
2.20.1



[PATCH 3/5] net: dsa: microchip: Replace ksz9477_wait_alu_ready polling with regmap

2019-06-27 Thread Marek Vasut
Regmap provides polling function to poll for bits in a register. This
function is another reimplementation of polling for bit being clear in
a register. Replace this with regmap polling function. Moreover, inline
the function parameters, as the function is never called with any other
parameter values than this one.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Tristram Ha 
Cc: Woojung Huh 
---
 drivers/net/dsa/microchip/ksz9477.c | 34 ++---
 1 file changed, 12 insertions(+), 22 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz9477.c 
b/drivers/net/dsa/microchip/ksz9477.c
index 0aab00bf23b9..e5b2f3e45db6 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -176,22 +176,12 @@ static void ksz9477_write_table(struct ksz_device *dev, 
u32 *table)
ksz_write32(dev, REG_SW_ALU_VAL_D, table[3]);
 }
 
-static int ksz9477_wait_alu_ready(struct ksz_device *dev, u32 waiton,
- int timeout)
+static int ksz9477_wait_alu_ready(struct ksz_device *dev)
 {
-   u32 data;
-
-   do {
-   ksz_read32(dev, REG_SW_ALU_CTRL__4, &data);
-   if (!(data & waiton))
-   break;
-   usleep_range(1, 10);
-   } while (timeout-- > 0);
-
-   if (timeout <= 0)
-   return -ETIMEDOUT;
+   unsigned int val;
 
-   return 0;
+   return regmap_read_poll_timeout(dev->regmap[2], REG_SW_ALU_CTRL__4,
+   val, !(val & ALU_START), 10, 1000);
 }
 
 static int ksz9477_wait_alu_sta_ready(struct ksz_device *dev, u32 waiton,
@@ -633,8 +623,8 @@ static int ksz9477_port_fdb_add(struct dsa_switch *ds, int 
port,
ksz_write32(dev, REG_SW_ALU_CTRL__4, ALU_READ | ALU_START);
 
/* wait to be finished */
-   ret = ksz9477_wait_alu_ready(dev, ALU_START, 1000);
-   if (ret < 0) {
+   ret = ksz9477_wait_alu_ready(dev);
+   if (ret) {
dev_dbg(dev->dev, "Failed to read ALU\n");
goto exit;
}
@@ -657,8 +647,8 @@ static int ksz9477_port_fdb_add(struct dsa_switch *ds, int 
port,
ksz_write32(dev, REG_SW_ALU_CTRL__4, ALU_WRITE | ALU_START);
 
/* wait to be finished */
-   ret = ksz9477_wait_alu_ready(dev, ALU_START, 1000);
-   if (ret < 0)
+   ret = ksz9477_wait_alu_ready(dev);
+   if (ret)
dev_dbg(dev->dev, "Failed to write ALU\n");
 
 exit:
@@ -690,8 +680,8 @@ static int ksz9477_port_fdb_del(struct dsa_switch *ds, int 
port,
ksz_write32(dev, REG_SW_ALU_CTRL__4, ALU_READ | ALU_START);
 
/* wait to be finished */
-   ret = ksz9477_wait_alu_ready(dev, ALU_START, 1000);
-   if (ret < 0) {
+   ret = ksz9477_wait_alu_ready(dev);
+   if (ret) {
dev_dbg(dev->dev, "Failed to read ALU\n");
goto exit;
}
@@ -724,8 +714,8 @@ static int ksz9477_port_fdb_del(struct dsa_switch *ds, int 
port,
ksz_write32(dev, REG_SW_ALU_CTRL__4, ALU_WRITE | ALU_START);
 
/* wait to be finished */
-   ret = ksz9477_wait_alu_ready(dev, ALU_START, 1000);
-   if (ret < 0)
+   ret = ksz9477_wait_alu_ready(dev);
+   if (ret)
dev_dbg(dev->dev, "Failed to write ALU\n");
 
 exit:
-- 
2.20.1



Re: [PATCH 0/5] net: dsa: microchip: Further regmap cleanups

2019-06-28 Thread Marek Vasut
On 6/28/19 5:31 PM, Vivien Didelot wrote:
> Hi Marek,
> 
> On Thu, 27 Jun 2019 23:55:51 +0200, Marek Vasut  wrote:
>> This patchset cleans up KSZ9477 switch driver by replacing various
>> ad-hoc polling implementations and register RMW with regmap functions.
>>
>> Each polling function is replaced separately to make it easier to review
>> and possibly bisect, but maybe the patches can be squashed.
>>
>> Signed-off-by: Marek Vasut 
>> Cc: Andrew Lunn 
>> Cc: Florian Fainelli 
>> Cc: Tristram Ha 
>> Cc: Woojung Huh 
> 
> Please copy me next time, as per the MAINTAINERS file.

Will do. I plan to submit KSZ8795 support next.

-- 
Best regards,
Marek Vasut


[PATCH V5] net: phy: tja11xx: Add TJA11xx PHY driver

2019-05-17 Thread Marek Vasut
Add driver for the NXP TJA1100 and TJA1101 PHYs. These PHYs are special
BroadRReach 100BaseT1 PHYs used in automotive.

Signed-off-by: Marek Vasut 
Cc: Andrew Lunn 
Cc: Florian Fainelli 
Cc: Guenter Roeck 
Cc: Heiner Kallweit 
Cc: Jean Delvare 
Cc: linux-hw...@vger.kernel.org
---
V2: - Use phy_modify(), phy_{set,clear}_bits()
- Drop enable argument of tja11xx_enable_link_control()
- Use PHY_BASIC_T1_FEATURES and dont modify supported/advertised
  features in config_init callback
- Use genphy_soft_reset() instead of opencoding the reset sequence.
- Drop the aneg parts, since the PHY datasheet claims it does not
  support aneg
V3: - Replace clr with mask
- Add hwmon support
- Check commstat in tja11xx_read_status() only if link is up
- Use PHY_ID_MATCH_MODEL()
V4: - Use correct bit in tja11xx_hwmon_read() hwmon_temp_crit_alarm
- Use ENOMEM if devm_kstrdup() fails
- Check $type in tja11xx_hwmon_read() in addition to $attr
V5: - Drop assignment of phydev->irq,pause,asym_pause
---
 drivers/net/phy/Kconfig   |   6 +
 drivers/net/phy/Makefile  |   1 +
 drivers/net/phy/nxp-tja11xx.c | 423 ++
 3 files changed, 430 insertions(+)
 create mode 100644 drivers/net/phy/nxp-tja11xx.c

diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index d6299710d634..31478d8b3c0c 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -415,6 +415,12 @@ config NATIONAL_PHY
---help---
  Currently supports the DP83865 PHY.
 
+config NXP_TJA11XX_PHY
+   tristate "NXP TJA11xx PHYs support"
+   depends on HWMON
+   ---help---
+ Currently supports the NXP TJA1100 and TJA1101 PHY.
+
 config QSEMI_PHY
tristate "Quality Semiconductor PHYs"
---help---
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 27d7f9f3b0de..bac339e09042 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -82,6 +82,7 @@ obj-$(CONFIG_MICROCHIP_PHY)   += microchip.o
 obj-$(CONFIG_MICROCHIP_T1_PHY) += microchip_t1.o
 obj-$(CONFIG_MICROSEMI_PHY)+= mscc.o
 obj-$(CONFIG_NATIONAL_PHY) += national.o
+obj-$(CONFIG_NXP_TJA11XX_PHY)  += nxp-tja11xx.o
 obj-$(CONFIG_QSEMI_PHY)+= qsemi.o
 obj-$(CONFIG_REALTEK_PHY)  += realtek.o
 obj-$(CONFIG_RENESAS_PHY)  += uPD60620.o
diff --git a/drivers/net/phy/nxp-tja11xx.c b/drivers/net/phy/nxp-tja11xx.c
new file mode 100644
index ..11b8701e78fd
--- /dev/null
+++ b/drivers/net/phy/nxp-tja11xx.c
@@ -0,0 +1,423 @@
+// SPDX-License-Identifier: GPL-2.0
+/* NXP TJA1100 BroadRReach PHY driver
+ *
+ * Copyright (C) 2018 Marek Vasut 
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define PHY_ID_MASK0xfff0
+#define PHY_ID_TJA1100 0x0180dc40
+#define PHY_ID_TJA1101 0x0180dd00
+
+#define MII_ECTRL  17
+#define MII_ECTRL_LINK_CONTROL BIT(15)
+#define MII_ECTRL_POWER_MODE_MASK  GENMASK(14, 11)
+#define MII_ECTRL_POWER_MODE_NO_CHANGE (0x0 << 11)
+#define MII_ECTRL_POWER_MODE_NORMAL(0x3 << 11)
+#define MII_ECTRL_POWER_MODE_STANDBY   (0xc << 11)
+#define MII_ECTRL_CONFIG_ENBIT(2)
+#define MII_ECTRL_WAKE_REQUEST BIT(0)
+
+#define MII_CFG1   18
+#define MII_CFG1_AUTO_OP   BIT(14)
+#define MII_CFG1_SLEEP_CONFIRM BIT(6)
+#define MII_CFG1_LED_MODE_MASK GENMASK(5, 4)
+#define MII_CFG1_LED_MODE_LINKUP   0
+#define MII_CFG1_LED_ENABLEBIT(3)
+
+#define MII_CFG2   19
+#define MII_CFG2_SLEEP_REQUEST_TO  GENMASK(1, 0)
+#define MII_CFG2_SLEEP_REQUEST_TO_16MS 0x3
+
+#define MII_INTSRC 21
+#define MII_INTSRC_TEMP_ERRBIT(1)
+#define MII_INTSRC_UV_ERR  BIT(3)
+
+#define MII_COMMSTAT   23
+#define MII_COMMSTAT_LINK_UP   BIT(15)
+
+#define MII_GENSTAT24
+#define MII_GENSTAT_PLL_LOCKED BIT(14)
+
+#define MII_COMMCFG27
+#define MII_COMMCFG_AUTO_OPBIT(15)
+
+struct tja11xx_priv {
+   char*hwmon_name;
+   struct device   *hwmon_dev;
+};
+
+struct tja11xx_phy_stats {
+   const char  *string;
+   u8  reg;
+   u8  off;
+   u16 mask;
+};
+
+static struct tja11xx_phy_stats tja11xx_hw_stats[] = {
+   { "phy_symbol_error_count", 20, 0, GENMASK(15, 0) },
+   { "phy_polarity_detect", 25, 6, BIT(6) },
+   { "phy_open_detect", 25, 7, BIT(7) },
+   { "phy_short_detect", 25, 8, BIT(8) },
+   { "phy_rem_rcvr_count", 26, 0, GENMASK(7, 0) },
+   { "phy_loc_rcvr_count", 26, 8, GENMASK(15, 8) },
+};
+
+static int tja11xx_check(struct phy_device *phydev, u8 reg, u16 mask, u16 set)
+{

  1   2   3   4   5   >