devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/5] Move Loongson1 MAC arch-code to the driver dir
@ 2023-08-12 15:11 Keguang Zhang
  2023-08-12 15:11 ` [PATCH 1/5] MIPS: loongson32: Remove Loongson1 MAC arch-code Keguang Zhang
                   ` (5 more replies)
  0 siblings, 6 replies; 28+ messages in thread
From: Keguang Zhang @ 2023-08-12 15:11 UTC (permalink / raw)
  To: netdev, devicetree, linux-mips, linux-kernel
  Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Thomas Bogendoerfer, Giuseppe Cavallaro, Alexandre Torgue,
	Jose Abreu, Serge Semin, Kelvin Zhang

From: Kelvin Zhang <kelvin.zhang@amlogic.com>

In order to convert Loongson1 MAC platform devices to the devicetree
nodes, Loongson1 MAC arch-code should be moved to the driver dir.
    
In other words, this patchset is a preparation for converting
Loongson1 platform devices to devicetree.

Keguang Zhang (5):
  MIPS: loongson32: Remove Loongson1 MAC arch-code
  dt-bindings: mfd: syscon: Add compatibles for Loongson-1 syscon
  dt-bindings: net: Add Loongson-1 DWMAC glue layer
  net: stmmac: Add glue layer for Loongson-1 SoC
  MAINTAINERS: Add entry for Loongson-1 DWMAC

 .../devicetree/bindings/mfd/syscon.yaml       |   2 +
 .../bindings/net/loongson,ls1x-dwmac.yaml     |  98 +++++++
 .../devicetree/bindings/net/snps,dwmac.yaml   |   2 +
 MAINTAINERS                                   |   2 +
 arch/mips/loongson32/common/platform.c        | 127 ++-------
 drivers/net/ethernet/stmicro/stmmac/Kconfig   |  11 +
 drivers/net/ethernet/stmicro/stmmac/Makefile  |   1 +
 .../ethernet/stmicro/stmmac/dwmac-loongson1.c | 257 ++++++++++++++++++
 8 files changed, 396 insertions(+), 104 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/net/loongson,ls1x-dwmac.yaml
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c


base-commit: 21ef7b1e17d039053edaeaf41142423810572741
-- 
2.39.2


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

* [PATCH 1/5] MIPS: loongson32: Remove Loongson1 MAC arch-code
  2023-08-12 15:11 [PATCH 0/5] Move Loongson1 MAC arch-code to the driver dir Keguang Zhang
@ 2023-08-12 15:11 ` Keguang Zhang
  2023-08-12 15:11 ` [PATCH 2/5] dt-bindings: mfd: syscon: Add compatibles for Loongson-1 syscon Keguang Zhang
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 28+ messages in thread
From: Keguang Zhang @ 2023-08-12 15:11 UTC (permalink / raw)
  To: netdev, devicetree, linux-mips, linux-kernel
  Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Thomas Bogendoerfer, Giuseppe Cavallaro, Alexandre Torgue,
	Jose Abreu, Serge Semin, Keguang Zhang

Loongson1 MAC arch-code should be moved to the driver dir.
Therefore, remove the deprecated implementation.

Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
---
 arch/mips/loongson32/common/platform.c | 127 +++++--------------------
 1 file changed, 23 insertions(+), 104 deletions(-)

diff --git a/arch/mips/loongson32/common/platform.c b/arch/mips/loongson32/common/platform.c
index 8075590a9f83..37dcda402680 100644
--- a/arch/mips/loongson32/common/platform.c
+++ b/arch/mips/loongson32/common/platform.c
@@ -10,7 +10,6 @@
 #include <linux/sizes.h>
 #include <linux/phy.h>
 #include <linux/serial_8250.h>
-#include <linux/stmmac.h>
 #include <linux/usb/ehci_pdriver.h>
 
 #include <platform.h>
@@ -62,87 +61,7 @@ void __init ls1x_serial_set_uartclk(struct platform_device *pdev)
 }
 
 /* Synopsys Ethernet GMAC */
-static struct stmmac_mdio_bus_data ls1x_mdio_bus_data = {
-	.phy_mask	= 0,
-};
-
-static struct stmmac_dma_cfg ls1x_eth_dma_cfg = {
-	.pbl		= 1,
-};
-
-int ls1x_eth_mux_init(struct platform_device *pdev, void *priv)
-{
-	struct plat_stmmacenet_data *plat_dat = NULL;
-	u32 val;
-
-	val = __raw_readl(LS1X_MUX_CTRL1);
-
-#if defined(CONFIG_LOONGSON1_LS1B)
-	plat_dat = dev_get_platdata(&pdev->dev);
-	if (plat_dat->bus_id) {
-		__raw_writel(__raw_readl(LS1X_MUX_CTRL0) | GMAC1_USE_UART1 |
-			     GMAC1_USE_UART0, LS1X_MUX_CTRL0);
-		switch (plat_dat->phy_interface) {
-		case PHY_INTERFACE_MODE_RGMII:
-			val &= ~(GMAC1_USE_TXCLK | GMAC1_USE_PWM23);
-			break;
-		case PHY_INTERFACE_MODE_MII:
-			val |= (GMAC1_USE_TXCLK | GMAC1_USE_PWM23);
-			break;
-		default:
-			pr_err("unsupported mii mode %d\n",
-			       plat_dat->phy_interface);
-			return -ENOTSUPP;
-		}
-		val &= ~GMAC1_SHUT;
-	} else {
-		switch (plat_dat->phy_interface) {
-		case PHY_INTERFACE_MODE_RGMII:
-			val &= ~(GMAC0_USE_TXCLK | GMAC0_USE_PWM01);
-			break;
-		case PHY_INTERFACE_MODE_MII:
-			val |= (GMAC0_USE_TXCLK | GMAC0_USE_PWM01);
-			break;
-		default:
-			pr_err("unsupported mii mode %d\n",
-			       plat_dat->phy_interface);
-			return -ENOTSUPP;
-		}
-		val &= ~GMAC0_SHUT;
-	}
-	__raw_writel(val, LS1X_MUX_CTRL1);
-#elif defined(CONFIG_LOONGSON1_LS1C)
-	plat_dat = dev_get_platdata(&pdev->dev);
-
-	val &= ~PHY_INTF_SELI;
-	if (plat_dat->phy_interface == PHY_INTERFACE_MODE_RMII)
-		val |= 0x4 << PHY_INTF_SELI_SHIFT;
-	__raw_writel(val, LS1X_MUX_CTRL1);
-
-	val = __raw_readl(LS1X_MUX_CTRL0);
-	__raw_writel(val & (~GMAC_SHUT), LS1X_MUX_CTRL0);
-#endif
-
-	return 0;
-}
-
-static struct plat_stmmacenet_data ls1x_eth0_pdata = {
-	.bus_id			= 0,
-	.phy_addr		= -1,
-#if defined(CONFIG_LOONGSON1_LS1B)
-	.phy_interface		= PHY_INTERFACE_MODE_MII,
-#elif defined(CONFIG_LOONGSON1_LS1C)
-	.phy_interface		= PHY_INTERFACE_MODE_RMII,
-#endif
-	.mdio_bus_data		= &ls1x_mdio_bus_data,
-	.dma_cfg		= &ls1x_eth_dma_cfg,
-	.has_gmac		= 1,
-	.tx_coe			= 1,
-	.rx_queues_to_use	= 1,
-	.tx_queues_to_use	= 1,
-	.init			= ls1x_eth_mux_init,
-};
-
+#ifdef CONFIG_LOONGSON1_LS1B
 static struct resource ls1x_eth0_resources[] = {
 	[0] = {
 		.start	= LS1X_GMAC0_BASE,
@@ -157,27 +76,10 @@ static struct resource ls1x_eth0_resources[] = {
 };
 
 struct platform_device ls1x_eth0_pdev = {
-	.name		= "stmmaceth",
+	.name		= "loongson,ls1b-dwmac",
 	.id		= 0,
 	.num_resources	= ARRAY_SIZE(ls1x_eth0_resources),
 	.resource	= ls1x_eth0_resources,
-	.dev		= {
-		.platform_data = &ls1x_eth0_pdata,
-	},
-};
-
-#ifdef CONFIG_LOONGSON1_LS1B
-static struct plat_stmmacenet_data ls1x_eth1_pdata = {
-	.bus_id			= 1,
-	.phy_addr		= -1,
-	.phy_interface		= PHY_INTERFACE_MODE_MII,
-	.mdio_bus_data		= &ls1x_mdio_bus_data,
-	.dma_cfg		= &ls1x_eth_dma_cfg,
-	.has_gmac		= 1,
-	.tx_coe			= 1,
-	.rx_queues_to_use	= 1,
-	.tx_queues_to_use	= 1,
-	.init			= ls1x_eth_mux_init,
 };
 
 static struct resource ls1x_eth1_resources[] = {
@@ -194,15 +96,32 @@ static struct resource ls1x_eth1_resources[] = {
 };
 
 struct platform_device ls1x_eth1_pdev = {
-	.name		= "stmmaceth",
+	.name		= "loongson,ls1b-dwmac",
 	.id		= 1,
 	.num_resources	= ARRAY_SIZE(ls1x_eth1_resources),
 	.resource	= ls1x_eth1_resources,
-	.dev		= {
-		.platform_data = &ls1x_eth1_pdata,
+};
+#elif defined(CONFIG_LOONGSON1_LS1C)
+static struct resource ls1x_eth0_resources[] = {
+	[0] = {
+		.start	= LS1X_GMAC0_BASE,
+		.end	= LS1X_GMAC0_BASE + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.name	= "macirq",
+		.start	= LS1X_GMAC0_IRQ,
+		.flags	= IORESOURCE_IRQ,
 	},
 };
-#endif	/* CONFIG_LOONGSON1_LS1B */
+
+struct platform_device ls1x_eth0_pdev = {
+	.name		= "loongson,ls1c-dwmac",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(ls1x_eth0_resources),
+	.resource	= ls1x_eth0_resources,
+};
+#endif
 
 /* GPIO */
 static struct resource ls1x_gpio0_resources[] = {
-- 
2.39.2


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

* [PATCH 2/5] dt-bindings: mfd: syscon: Add compatibles for Loongson-1 syscon
  2023-08-12 15:11 [PATCH 0/5] Move Loongson1 MAC arch-code to the driver dir Keguang Zhang
  2023-08-12 15:11 ` [PATCH 1/5] MIPS: loongson32: Remove Loongson1 MAC arch-code Keguang Zhang
@ 2023-08-12 15:11 ` Keguang Zhang
  2023-08-14 19:06   ` Krzysztof Kozlowski
  2023-08-12 15:11 ` [PATCH 3/5] dt-bindings: net: Add Loongson-1 DWMAC glue layer Keguang Zhang
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 28+ messages in thread
From: Keguang Zhang @ 2023-08-12 15:11 UTC (permalink / raw)
  To: netdev, devicetree, linux-mips, linux-kernel
  Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Thomas Bogendoerfer, Giuseppe Cavallaro, Alexandre Torgue,
	Jose Abreu, Serge Semin, Keguang Zhang

Add Loongson LS1B and LS1C compatibles for system controller.

Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
---
 Documentation/devicetree/bindings/mfd/syscon.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/mfd/syscon.yaml b/Documentation/devicetree/bindings/mfd/syscon.yaml
index 8103154bbb52..c77d7b155a4c 100644
--- a/Documentation/devicetree/bindings/mfd/syscon.yaml
+++ b/Documentation/devicetree/bindings/mfd/syscon.yaml
@@ -49,6 +49,8 @@ properties:
               - hisilicon,peri-subctrl
               - hpe,gxp-sysreg
               - intel,lgm-syscon
+              - loongson,ls1b-syscon
+              - loongson,ls1c-syscon
               - marvell,armada-3700-usb2-host-misc
               - mediatek,mt8135-pctl-a-syscfg
               - mediatek,mt8135-pctl-b-syscfg
-- 
2.39.2


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

* [PATCH 3/5] dt-bindings: net: Add Loongson-1 DWMAC glue layer
  2023-08-12 15:11 [PATCH 0/5] Move Loongson1 MAC arch-code to the driver dir Keguang Zhang
  2023-08-12 15:11 ` [PATCH 1/5] MIPS: loongson32: Remove Loongson1 MAC arch-code Keguang Zhang
  2023-08-12 15:11 ` [PATCH 2/5] dt-bindings: mfd: syscon: Add compatibles for Loongson-1 syscon Keguang Zhang
@ 2023-08-12 15:11 ` Keguang Zhang
  2023-08-14 19:11   ` Krzysztof Kozlowski
  2023-08-16 12:54   ` Serge Semin
  2023-08-12 15:11 ` [PATCH 4/5] net: stmmac: Add glue layer for Loongson-1 SoC Keguang Zhang
                   ` (2 subsequent siblings)
  5 siblings, 2 replies; 28+ messages in thread
From: Keguang Zhang @ 2023-08-12 15:11 UTC (permalink / raw)
  To: netdev, devicetree, linux-mips, linux-kernel
  Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Thomas Bogendoerfer, Giuseppe Cavallaro, Alexandre Torgue,
	Jose Abreu, Serge Semin, Keguang Zhang

Add devicetree binding document for Loongson-1 DWMAC glue layer.

Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
---
 .../bindings/net/loongson,ls1x-dwmac.yaml     | 98 +++++++++++++++++++
 .../devicetree/bindings/net/snps,dwmac.yaml   |  2 +
 2 files changed, 100 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/loongson,ls1x-dwmac.yaml

diff --git a/Documentation/devicetree/bindings/net/loongson,ls1x-dwmac.yaml b/Documentation/devicetree/bindings/net/loongson,ls1x-dwmac.yaml
new file mode 100644
index 000000000000..150799460599
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/loongson,ls1x-dwmac.yaml
@@ -0,0 +1,98 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/loongson,ls1x-dwmac.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Loongson-1 DWMAC glue layer
+
+maintainers:
+  - Keguang Zhang <keguang.zhang@gmail.com>
+
+select:
+  properties:
+    compatible:
+      contains:
+        enum:
+          - loongson,ls1b-dwmac
+          - loongson,ls1c-dwmac
+  required:
+    - compatible
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - loongson,ls1b-dwmac
+          - loongson,ls1c-dwmac
+      - const: snps,dwmac-3.50a
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  clock-names:
+    const: stmmaceth
+
+  interrupts:
+    maxItems: 1
+
+  interrupt-names:
+    const: macirq
+
+  syscon:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      Phandle to the syscon containing some extra configurations
+      including PHY interface mode.
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - interrupts
+  - interrupt-names
+  - phy-handle
+  - phy-mode
+  - syscon
+
+allOf:
+  - $ref: snps,dwmac.yaml#
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/loongson,ls1x-clk.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    gmac0: ethernet@1fe10000 {
+        compatible = "loongson,ls1b-dwmac", "snps,dwmac-3.50a";
+        reg = <0x1fe10000 0x10000>;
+
+        clocks = <&clkc LS1X_CLKID_AHB>;
+        clock-names = "stmmaceth";
+
+        interrupt-parent = <&intc1>;
+        interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
+        interrupt-names = "macirq";
+
+        phy-handle = <&phy0>;
+        phy-mode = "mii";
+
+        snps,pbl = <1>;
+        syscon = <&syscon>;
+
+        mdio {
+            #address-cells = <1>;
+            #size-cells = <0>;
+            compatible = "snps,dwmac-mdio";
+
+            phy0: ethernet-phy@0 {
+                reg = <0x0>;
+            };
+        };
+    };
diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
index ddf9522a5dc2..e1a956cf171e 100644
--- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml
+++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
@@ -66,6 +66,8 @@ properties:
         - ingenic,x2000-mac
         - loongson,ls2k-dwmac
         - loongson,ls7a-dwmac
+        - loongson,ls1b-dwmac
+        - loongson,ls1c-dwmac
         - qcom,qcs404-ethqos
         - qcom,sa8775p-ethqos
         - qcom,sc8280xp-ethqos
-- 
2.39.2


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

* [PATCH 4/5] net: stmmac: Add glue layer for Loongson-1 SoC
  2023-08-12 15:11 [PATCH 0/5] Move Loongson1 MAC arch-code to the driver dir Keguang Zhang
                   ` (2 preceding siblings ...)
  2023-08-12 15:11 ` [PATCH 3/5] dt-bindings: net: Add Loongson-1 DWMAC glue layer Keguang Zhang
@ 2023-08-12 15:11 ` Keguang Zhang
  2023-08-12 21:30   ` kernel test robot
                     ` (3 more replies)
  2023-08-12 15:11 ` [PATCH 5/5] MAINTAINERS: Add entry for Loongson-1 DWMAC Keguang Zhang
  2023-08-13 15:24 ` [PATCH 0/5] Move Loongson1 MAC arch-code to the driver dir Andrew Lunn
  5 siblings, 4 replies; 28+ messages in thread
From: Keguang Zhang @ 2023-08-12 15:11 UTC (permalink / raw)
  To: netdev, devicetree, linux-mips, linux-kernel
  Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Thomas Bogendoerfer, Giuseppe Cavallaro, Alexandre Torgue,
	Jose Abreu, Serge Semin, Keguang Zhang

This glue driver is created based on the arch-code
implemented earlier with the platform-specific settings.

Use syscon for SYSCON register access.

Partialy based on the previous work by Serge Semin.

Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
---
 drivers/net/ethernet/stmicro/stmmac/Kconfig   |  11 +
 drivers/net/ethernet/stmicro/stmmac/Makefile  |   1 +
 .../ethernet/stmicro/stmmac/dwmac-loongson1.c | 257 ++++++++++++++++++
 3 files changed, 269 insertions(+)
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c

diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 06c6871f8788..a2b9e289aa36 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -239,6 +239,17 @@ config DWMAC_INTEL_PLAT
 	  the stmmac device driver. This driver is used for the Intel Keem Bay
 	  SoC.
 
+config DWMAC_LOONGSON1
+	tristate "Loongson1 GMAC support"
+	default MACH_LOONGSON32
+	depends on OF && (MACH_LOONGSON32 || COMPILE_TEST)
+	help
+	  Support for ethernet controller on Loongson1 SoC.
+
+	  This selects Loongson1 SoC glue layer support for the stmmac
+	  device driver. This driver is used for Loongson1-based boards
+	  like Loongson LS1B/LS1C.
+
 config DWMAC_TEGRA
 	tristate "NVIDIA Tegra MGBE support"
 	depends on ARCH_TEGRA || COMPILE_TEST
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index 5b57aee19267..80e598bd4255 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_DWMAC_SUNXI)	+= dwmac-sunxi.o
 obj-$(CONFIG_DWMAC_SUN8I)	+= dwmac-sun8i.o
 obj-$(CONFIG_DWMAC_DWC_QOS_ETH)	+= dwmac-dwc-qos-eth.o
 obj-$(CONFIG_DWMAC_INTEL_PLAT)	+= dwmac-intel-plat.o
+obj-$(CONFIG_DWMAC_LOONGSON1)	+= dwmac-loongson1.o
 obj-$(CONFIG_DWMAC_GENERIC)	+= dwmac-generic.o
 obj-$(CONFIG_DWMAC_IMX8)	+= dwmac-imx.o
 obj-$(CONFIG_DWMAC_TEGRA)	+= dwmac-tegra.o
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
new file mode 100644
index 000000000000..368d6cd2cb78
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
@@ -0,0 +1,257 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Loongson-1 DWMAC glue layer
+ *
+ * Copyright (C) 2011-2023 Keguang Zhang <keguang.zhang@gmail.com>
+ */
+
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include "stmmac.h"
+#include "stmmac_platform.h"
+
+/* Loongson-1 SYSCON Registers */
+#define LS1X_SYSCON0		(0x0)
+#define LS1X_SYSCON1		(0x4)
+
+struct ls1x_dwmac_syscon {
+	const struct reg_field *reg_fields;
+	unsigned int nr_reg_fields;
+	int (*syscon_init)(struct plat_stmmacenet_data *plat);
+};
+
+struct ls1x_dwmac {
+	struct device *dev;
+	struct plat_stmmacenet_data *plat_dat;
+	const struct ls1x_dwmac_syscon *syscon;
+	struct regmap *regmap;
+	struct regmap_field *regmap_fields[];
+};
+
+enum ls1b_dwmac_syscon_regfield {
+	GMAC1_USE_UART1,
+	GMAC1_USE_UART0,
+	GMAC1_SHUT,
+	GMAC0_SHUT,
+	GMAC1_USE_TXCLK,
+	GMAC0_USE_TXCLK,
+	GMAC1_USE_PWM23,
+	GMAC0_USE_PWM01,
+};
+
+enum ls1c_dwmac_syscon_regfield {
+	GMAC_SHUT,
+	PHY_INTF_SELI,
+};
+
+const struct reg_field ls1b_dwmac_syscon_regfields[] = {
+	[GMAC1_USE_UART1]	= REG_FIELD(LS1X_SYSCON0, 4, 4),
+	[GMAC1_USE_UART0]	= REG_FIELD(LS1X_SYSCON0, 3, 3),
+	[GMAC1_SHUT]		= REG_FIELD(LS1X_SYSCON1, 13, 13),
+	[GMAC0_SHUT]		= REG_FIELD(LS1X_SYSCON1, 12, 12),
+	[GMAC1_USE_TXCLK]	= REG_FIELD(LS1X_SYSCON1, 3, 3),
+	[GMAC0_USE_TXCLK]	= REG_FIELD(LS1X_SYSCON1, 2, 2),
+	[GMAC1_USE_PWM23]	= REG_FIELD(LS1X_SYSCON1, 1, 1),
+	[GMAC0_USE_PWM01]	= REG_FIELD(LS1X_SYSCON1, 0, 0)
+};
+
+const struct reg_field ls1c_dwmac_syscon_regfields[] = {
+	[GMAC_SHUT]		= REG_FIELD(LS1X_SYSCON0, 6, 6),
+	[PHY_INTF_SELI]		= REG_FIELD(LS1X_SYSCON1, 28, 30)
+};
+
+static int ls1b_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
+{
+	struct ls1x_dwmac *dwmac = plat->bsp_priv;
+	struct regmap_field **regmap_fields = dwmac->regmap_fields;
+
+	if (plat->bus_id) {
+		regmap_field_write(regmap_fields[GMAC1_USE_UART1], 1);
+		regmap_field_write(regmap_fields[GMAC1_USE_UART0], 1);
+
+		switch (plat->phy_interface) {
+		case PHY_INTERFACE_MODE_RGMII:
+			regmap_field_write(regmap_fields[GMAC1_USE_TXCLK], 0);
+			regmap_field_write(regmap_fields[GMAC1_USE_PWM23], 0);
+			break;
+		case PHY_INTERFACE_MODE_MII:
+			regmap_field_write(regmap_fields[GMAC1_USE_TXCLK], 1);
+			regmap_field_write(regmap_fields[GMAC1_USE_PWM23], 1);
+			break;
+		default:
+			dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
+				plat->phy_interface);
+			return -EOPNOTSUPP;
+		}
+
+		regmap_field_write(regmap_fields[GMAC1_SHUT], 0);
+	} else {
+		switch (plat->phy_interface) {
+		case PHY_INTERFACE_MODE_RGMII:
+			regmap_field_write(regmap_fields[GMAC0_USE_TXCLK], 0);
+			regmap_field_write(regmap_fields[GMAC0_USE_PWM01], 0);
+			break;
+		case PHY_INTERFACE_MODE_MII:
+			regmap_field_write(regmap_fields[GMAC0_USE_TXCLK], 1);
+			regmap_field_write(regmap_fields[GMAC0_USE_PWM01], 1);
+			break;
+		default:
+			dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
+				plat->phy_interface);
+			return -EOPNOTSUPP;
+		}
+
+		regmap_field_write(regmap_fields[GMAC0_SHUT], 0);
+	}
+
+	return 0;
+}
+
+static int ls1c_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
+{
+	struct ls1x_dwmac *dwmac = plat->bsp_priv;
+	struct regmap_field **regmap_fields = dwmac->regmap_fields;
+
+	if (plat->phy_interface == PHY_INTERFACE_MODE_RMII) {
+		regmap_field_write(regmap_fields[PHY_INTF_SELI], 0x4);
+	} else {
+		dev_err(dwmac->dev, "Unsupported PHY-mode %u\n",
+			plat->phy_interface);
+		return -EOPNOTSUPP;
+	}
+
+	regmap_field_write(regmap_fields[GMAC_SHUT], 0);
+
+	return 0;
+}
+
+static const struct ls1x_dwmac_syscon ls1b_dwmac_syscon = {
+	.reg_fields = ls1b_dwmac_syscon_regfields,
+	.nr_reg_fields = ARRAY_SIZE(ls1b_dwmac_syscon_regfields),
+	.syscon_init = ls1b_dwmac_syscon_init,
+};
+
+static const struct ls1x_dwmac_syscon ls1c_dwmac_syscon = {
+	.reg_fields = ls1c_dwmac_syscon_regfields,
+	.nr_reg_fields = ARRAY_SIZE(ls1c_dwmac_syscon_regfields),
+	.syscon_init = ls1c_dwmac_syscon_init,
+};
+
+static int ls1x_dwmac_init(struct platform_device *pdev, void *priv)
+{
+	struct ls1x_dwmac *dwmac = priv;
+	int ret;
+
+	ret = devm_regmap_field_bulk_alloc(dwmac->dev, dwmac->regmap,
+					   dwmac->regmap_fields,
+					   dwmac->syscon->reg_fields,
+					   dwmac->syscon->nr_reg_fields);
+	if (ret)
+		return ret;
+
+	if (dwmac->syscon->syscon_init) {
+		ret = dwmac->syscon->syscon_init(dwmac->plat_dat);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static const struct of_device_id ls1x_dwmac_syscon_match[] = {
+	{ .compatible = "loongson,ls1b-syscon", .data = &ls1b_dwmac_syscon },
+	{ .compatible = "loongson,ls1c-syscon", .data = &ls1c_dwmac_syscon },
+	{ }
+};
+
+static int ls1x_dwmac_probe(struct platform_device *pdev)
+{
+	struct plat_stmmacenet_data *plat_dat;
+	struct stmmac_resources stmmac_res;
+	struct device_node *syscon_np;
+	const struct of_device_id *match;
+	struct regmap *regmap;
+	struct ls1x_dwmac *dwmac;
+	const struct ls1x_dwmac_syscon *syscon;
+	size_t size;
+	int ret;
+
+	ret = stmmac_get_platform_resources(pdev, &stmmac_res);
+	if (ret)
+		return ret;
+
+	/* Probe syscon */
+	syscon_np = of_parse_phandle(pdev->dev.of_node, "syscon", 0);
+	if (!syscon_np)
+		return -ENODEV;
+
+	match = of_match_node(ls1x_dwmac_syscon_match, syscon_np);
+	if (!match) {
+		of_node_put(syscon_np);
+		return -EINVAL;
+	}
+	syscon = (const struct ls1x_dwmac_syscon *)match->data;
+
+	regmap = syscon_node_to_regmap(syscon_np);
+	of_node_put(syscon_np);
+	if (IS_ERR(regmap)) {
+		ret = PTR_ERR(regmap);
+		dev_err(&pdev->dev, "Unable to map syscon: %d\n", ret);
+		return ret;
+	}
+
+	size = syscon->nr_reg_fields * sizeof(struct regmap_field *);
+	dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac) + size, GFP_KERNEL);
+	if (!dwmac)
+		return -ENOMEM;
+
+	plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
+	if (IS_ERR(plat_dat)) {
+		dev_err(&pdev->dev, "dt configuration failed\n");
+		return PTR_ERR(plat_dat);
+	}
+
+	plat_dat->bsp_priv = dwmac;
+	plat_dat->init = ls1x_dwmac_init;
+	dwmac->dev = &pdev->dev;
+	dwmac->plat_dat = plat_dat;
+	dwmac->syscon = syscon;
+	dwmac->regmap = regmap;
+
+	ret = stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res);
+	if (ret)
+		goto err_remove_config_dt;
+
+	return 0;
+
+err_remove_config_dt:
+	if (pdev->dev.of_node)
+		stmmac_remove_config_dt(pdev, plat_dat);
+
+	return ret;
+}
+
+static const struct of_device_id ls1x_dwmac_match[] = {
+	{ .compatible = "loongson,ls1b-dwmac" },
+	{ .compatible = "loongson,ls1c-dwmac" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, ls1x_dwmac_match);
+
+static struct platform_driver ls1x_dwmac_driver = {
+	.probe = ls1x_dwmac_probe,
+	.remove_new = stmmac_pltfr_remove,
+	.driver = {
+		.name = "loongson1-dwmac",
+		.of_match_table = ls1x_dwmac_match,
+	},
+};
+module_platform_driver(ls1x_dwmac_driver);
+
+MODULE_AUTHOR("Keguang Zhang <keguang.zhang@gmail.com>");
+MODULE_DESCRIPTION("Loongson1 DWMAC glue layer");
+MODULE_LICENSE("GPL");
-- 
2.39.2


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

* [PATCH 5/5] MAINTAINERS: Add entry for Loongson-1 DWMAC
  2023-08-12 15:11 [PATCH 0/5] Move Loongson1 MAC arch-code to the driver dir Keguang Zhang
                   ` (3 preceding siblings ...)
  2023-08-12 15:11 ` [PATCH 4/5] net: stmmac: Add glue layer for Loongson-1 SoC Keguang Zhang
@ 2023-08-12 15:11 ` Keguang Zhang
  2023-08-14 19:16   ` Krzysztof Kozlowski
  2023-08-13 15:24 ` [PATCH 0/5] Move Loongson1 MAC arch-code to the driver dir Andrew Lunn
  5 siblings, 1 reply; 28+ messages in thread
From: Keguang Zhang @ 2023-08-12 15:11 UTC (permalink / raw)
  To: netdev, devicetree, linux-mips, linux-kernel
  Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Thomas Bogendoerfer, Giuseppe Cavallaro, Alexandre Torgue,
	Jose Abreu, Serge Semin, Keguang Zhang

Update MAINTAINERS to add Loongson-1 DWMAC entry.

Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
---
 MAINTAINERS | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 02a3192195af..3f47f2a43b41 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14309,9 +14309,11 @@ MIPS/LOONGSON1 ARCHITECTURE
 M:	Keguang Zhang <keguang.zhang@gmail.com>
 L:	linux-mips@vger.kernel.org
 S:	Maintained
+F:	Documentation/devicetree/bindings/*/loongson,ls1x-*.yaml
 F:	arch/mips/include/asm/mach-loongson32/
 F:	arch/mips/loongson32/
 F:	drivers/*/*loongson1*
+F:	drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
 
 MIPS/LOONGSON2EF ARCHITECTURE
 M:	Jiaxun Yang <jiaxun.yang@flygoat.com>
-- 
2.39.2


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

* Re: [PATCH 4/5] net: stmmac: Add glue layer for Loongson-1 SoC
  2023-08-12 15:11 ` [PATCH 4/5] net: stmmac: Add glue layer for Loongson-1 SoC Keguang Zhang
@ 2023-08-12 21:30   ` kernel test robot
  2023-08-13  8:28   ` kernel test robot
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 28+ messages in thread
From: kernel test robot @ 2023-08-12 21:30 UTC (permalink / raw)
  To: Keguang Zhang, netdev, devicetree, linux-mips, linux-kernel
  Cc: oe-kbuild-all, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, David S . Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Thomas Bogendoerfer, Giuseppe Cavallaro,
	Alexandre Torgue, Jose Abreu, Serge Semin, Keguang Zhang

Hi Keguang,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 21ef7b1e17d039053edaeaf41142423810572741]

url:    https://github.com/intel-lab-lkp/linux/commits/Keguang-Zhang/MIPS-loongson32-Remove-Loongson1-MAC-arch-code/20230812-231420
base:   21ef7b1e17d039053edaeaf41142423810572741
patch link:    https://lore.kernel.org/r/20230812151135.1028780-5-keguang.zhang%40gmail.com
patch subject: [PATCH 4/5] net: stmmac: Add glue layer for Loongson-1 SoC
config: parisc-allyesconfig (https://download.01.org/0day-ci/archive/20230813/202308130554.Rbxxtltt-lkp@intel.com/config)
compiler: hppa-linux-gcc (GCC) 12.3.0
reproduce: (https://download.01.org/0day-ci/archive/20230813/202308130554.Rbxxtltt-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202308130554.Rbxxtltt-lkp@intel.com/

All warnings (new ones prefixed by >>):

   drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c: In function 'ls1x_dwmac_probe':
   drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c:188:21: error: implicit declaration of function 'of_parse_phandle' [-Werror=implicit-function-declaration]
     188 |         syscon_np = of_parse_phandle(pdev->dev.of_node, "syscon", 0);
         |                     ^~~~~~~~~~~~~~~~
>> drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c:188:19: warning: assignment to 'struct device_node *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
     188 |         syscon_np = of_parse_phandle(pdev->dev.of_node, "syscon", 0);
         |                   ^
   drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c:192:17: error: implicit declaration of function 'of_match_node'; did you mean 'for_each_node'? [-Werror=implicit-function-declaration]
     192 |         match = of_match_node(ls1x_dwmac_syscon_match, syscon_np);
         |                 ^~~~~~~~~~~~~
         |                 for_each_node
>> drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c:192:15: warning: assignment to 'const struct of_device_id *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
     192 |         match = of_match_node(ls1x_dwmac_syscon_match, syscon_np);
         |               ^
   drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c:194:17: error: implicit declaration of function 'of_node_put'; did you mean 'bpf_module_put'? [-Werror=implicit-function-declaration]
     194 |                 of_node_put(syscon_np);
         |                 ^~~~~~~~~~~
         |                 bpf_module_put
   cc1: some warnings being treated as errors


vim +188 drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c

   170	
   171	static int ls1x_dwmac_probe(struct platform_device *pdev)
   172	{
   173		struct plat_stmmacenet_data *plat_dat;
   174		struct stmmac_resources stmmac_res;
   175		struct device_node *syscon_np;
   176		const struct of_device_id *match;
   177		struct regmap *regmap;
   178		struct ls1x_dwmac *dwmac;
   179		const struct ls1x_dwmac_syscon *syscon;
   180		size_t size;
   181		int ret;
   182	
   183		ret = stmmac_get_platform_resources(pdev, &stmmac_res);
   184		if (ret)
   185			return ret;
   186	
   187		/* Probe syscon */
 > 188		syscon_np = of_parse_phandle(pdev->dev.of_node, "syscon", 0);
   189		if (!syscon_np)
   190			return -ENODEV;
   191	
 > 192		match = of_match_node(ls1x_dwmac_syscon_match, syscon_np);
   193		if (!match) {
   194			of_node_put(syscon_np);
   195			return -EINVAL;
   196		}
   197		syscon = (const struct ls1x_dwmac_syscon *)match->data;
   198	
   199		regmap = syscon_node_to_regmap(syscon_np);
   200		of_node_put(syscon_np);
   201		if (IS_ERR(regmap)) {
   202			ret = PTR_ERR(regmap);
   203			dev_err(&pdev->dev, "Unable to map syscon: %d\n", ret);
   204			return ret;
   205		}
   206	
   207		size = syscon->nr_reg_fields * sizeof(struct regmap_field *);
   208		dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac) + size, GFP_KERNEL);
   209		if (!dwmac)
   210			return -ENOMEM;
   211	
   212		plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
   213		if (IS_ERR(plat_dat)) {
   214			dev_err(&pdev->dev, "dt configuration failed\n");
   215			return PTR_ERR(plat_dat);
   216		}
   217	
   218		plat_dat->bsp_priv = dwmac;
   219		plat_dat->init = ls1x_dwmac_init;
   220		dwmac->dev = &pdev->dev;
   221		dwmac->plat_dat = plat_dat;
   222		dwmac->syscon = syscon;
   223		dwmac->regmap = regmap;
   224	
   225		ret = stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res);
   226		if (ret)
   227			goto err_remove_config_dt;
   228	
   229		return 0;
   230	
   231	err_remove_config_dt:
   232		if (pdev->dev.of_node)
   233			stmmac_remove_config_dt(pdev, plat_dat);
   234	
   235		return ret;
   236	}
   237	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

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

* Re: [PATCH 4/5] net: stmmac: Add glue layer for Loongson-1 SoC
  2023-08-12 15:11 ` [PATCH 4/5] net: stmmac: Add glue layer for Loongson-1 SoC Keguang Zhang
  2023-08-12 21:30   ` kernel test robot
@ 2023-08-13  8:28   ` kernel test robot
  2023-08-13 18:24   ` Simon Horman
  2023-08-16 13:30   ` Serge Semin
  3 siblings, 0 replies; 28+ messages in thread
From: kernel test robot @ 2023-08-13  8:28 UTC (permalink / raw)
  To: Keguang Zhang, netdev, devicetree, linux-mips, linux-kernel
  Cc: oe-kbuild-all, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, David S . Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Thomas Bogendoerfer, Giuseppe Cavallaro,
	Alexandre Torgue, Jose Abreu, Serge Semin, Keguang Zhang

Hi Keguang,

kernel test robot noticed the following build errors:

[auto build test ERROR on 21ef7b1e17d039053edaeaf41142423810572741]

url:    https://github.com/intel-lab-lkp/linux/commits/Keguang-Zhang/MIPS-loongson32-Remove-Loongson1-MAC-arch-code/20230812-231420
base:   21ef7b1e17d039053edaeaf41142423810572741
patch link:    https://lore.kernel.org/r/20230812151135.1028780-5-keguang.zhang%40gmail.com
patch subject: [PATCH 4/5] net: stmmac: Add glue layer for Loongson-1 SoC
config: parisc-allyesconfig (https://download.01.org/0day-ci/archive/20230813/202308131600.I6iscZMl-lkp@intel.com/config)
compiler: hppa-linux-gcc (GCC) 12.3.0
reproduce: (https://download.01.org/0day-ci/archive/20230813/202308131600.I6iscZMl-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202308131600.I6iscZMl-lkp@intel.com/

All errors (new ones prefixed by >>):

   drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c: In function 'ls1x_dwmac_probe':
>> drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c:188:21: error: implicit declaration of function 'of_parse_phandle' [-Werror=implicit-function-declaration]
     188 |         syscon_np = of_parse_phandle(pdev->dev.of_node, "syscon", 0);
         |                     ^~~~~~~~~~~~~~~~
   drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c:188:19: warning: assignment to 'struct device_node *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
     188 |         syscon_np = of_parse_phandle(pdev->dev.of_node, "syscon", 0);
         |                   ^
>> drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c:192:17: error: implicit declaration of function 'of_match_node'; did you mean 'for_each_node'? [-Werror=implicit-function-declaration]
     192 |         match = of_match_node(ls1x_dwmac_syscon_match, syscon_np);
         |                 ^~~~~~~~~~~~~
         |                 for_each_node
   drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c:192:15: warning: assignment to 'const struct of_device_id *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
     192 |         match = of_match_node(ls1x_dwmac_syscon_match, syscon_np);
         |               ^
>> drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c:194:17: error: implicit declaration of function 'of_node_put'; did you mean 'bpf_module_put'? [-Werror=implicit-function-declaration]
     194 |                 of_node_put(syscon_np);
         |                 ^~~~~~~~~~~
         |                 bpf_module_put
   cc1: some warnings being treated as errors


vim +/of_parse_phandle +188 drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c

   170	
   171	static int ls1x_dwmac_probe(struct platform_device *pdev)
   172	{
   173		struct plat_stmmacenet_data *plat_dat;
   174		struct stmmac_resources stmmac_res;
   175		struct device_node *syscon_np;
   176		const struct of_device_id *match;
   177		struct regmap *regmap;
   178		struct ls1x_dwmac *dwmac;
   179		const struct ls1x_dwmac_syscon *syscon;
   180		size_t size;
   181		int ret;
   182	
   183		ret = stmmac_get_platform_resources(pdev, &stmmac_res);
   184		if (ret)
   185			return ret;
   186	
   187		/* Probe syscon */
 > 188		syscon_np = of_parse_phandle(pdev->dev.of_node, "syscon", 0);
   189		if (!syscon_np)
   190			return -ENODEV;
   191	
 > 192		match = of_match_node(ls1x_dwmac_syscon_match, syscon_np);
   193		if (!match) {
 > 194			of_node_put(syscon_np);
   195			return -EINVAL;
   196		}
   197		syscon = (const struct ls1x_dwmac_syscon *)match->data;
   198	
   199		regmap = syscon_node_to_regmap(syscon_np);
   200		of_node_put(syscon_np);
   201		if (IS_ERR(regmap)) {
   202			ret = PTR_ERR(regmap);
   203			dev_err(&pdev->dev, "Unable to map syscon: %d\n", ret);
   204			return ret;
   205		}
   206	
   207		size = syscon->nr_reg_fields * sizeof(struct regmap_field *);
   208		dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac) + size, GFP_KERNEL);
   209		if (!dwmac)
   210			return -ENOMEM;
   211	
   212		plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
   213		if (IS_ERR(plat_dat)) {
   214			dev_err(&pdev->dev, "dt configuration failed\n");
   215			return PTR_ERR(plat_dat);
   216		}
   217	
   218		plat_dat->bsp_priv = dwmac;
   219		plat_dat->init = ls1x_dwmac_init;
   220		dwmac->dev = &pdev->dev;
   221		dwmac->plat_dat = plat_dat;
   222		dwmac->syscon = syscon;
   223		dwmac->regmap = regmap;
   224	
   225		ret = stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res);
   226		if (ret)
   227			goto err_remove_config_dt;
   228	
   229		return 0;
   230	
   231	err_remove_config_dt:
   232		if (pdev->dev.of_node)
   233			stmmac_remove_config_dt(pdev, plat_dat);
   234	
   235		return ret;
   236	}
   237	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

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

* Re: [PATCH 0/5] Move Loongson1 MAC arch-code to the driver dir
  2023-08-12 15:11 [PATCH 0/5] Move Loongson1 MAC arch-code to the driver dir Keguang Zhang
                   ` (4 preceding siblings ...)
  2023-08-12 15:11 ` [PATCH 5/5] MAINTAINERS: Add entry for Loongson-1 DWMAC Keguang Zhang
@ 2023-08-13 15:24 ` Andrew Lunn
  2023-08-14  2:39   ` Keguang Zhang
  5 siblings, 1 reply; 28+ messages in thread
From: Andrew Lunn @ 2023-08-13 15:24 UTC (permalink / raw)
  To: Keguang Zhang
  Cc: netdev, devicetree, linux-mips, linux-kernel, Lee Jones,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, David S . Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Thomas Bogendoerfer,
	Giuseppe Cavallaro, Alexandre Torgue, Jose Abreu, Serge Semin,
	Kelvin Zhang

On Sat, Aug 12, 2023 at 11:11:30PM +0800, Keguang Zhang wrote:
> From: Kelvin Zhang <kelvin.zhang@amlogic.com>
> 
> In order to convert Loongson1 MAC platform devices to the devicetree
> nodes, Loongson1 MAC arch-code should be moved to the driver dir.
>     
> In other words, this patchset is a preparation for converting
> Loongson1 platform devices to devicetree.

It is a long time since i converted an ARM system from platform data
to DT. But what we tended to do was to allow both for a period of
time.

Does a system using platform data still work after this change? The
first patch seems to delete a lot of code, not just move it around.

Can you restructure this patchset to add the glue layer and DT binding
in parallel with platform data. Then have a patchset which convert all
in tree machines to using DT. And then a patchset, submitted in maybe
6 months time, to remove support for platform data.

	Andrew

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

* Re: [PATCH 4/5] net: stmmac: Add glue layer for Loongson-1 SoC
  2023-08-12 15:11 ` [PATCH 4/5] net: stmmac: Add glue layer for Loongson-1 SoC Keguang Zhang
  2023-08-12 21:30   ` kernel test robot
  2023-08-13  8:28   ` kernel test robot
@ 2023-08-13 18:24   ` Simon Horman
  2023-08-14 10:50     ` Keguang Zhang
  2023-08-16 13:30   ` Serge Semin
  3 siblings, 1 reply; 28+ messages in thread
From: Simon Horman @ 2023-08-13 18:24 UTC (permalink / raw)
  To: Keguang Zhang
  Cc: netdev, devicetree, linux-mips, linux-kernel, Lee Jones,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Thomas Bogendoerfer,
	Giuseppe Cavallaro, Alexandre Torgue, Jose Abreu, Serge Semin

On Sat, Aug 12, 2023 at 11:11:34PM +0800, Keguang Zhang wrote:
> This glue driver is created based on the arch-code
> implemented earlier with the platform-specific settings.
> 
> Use syscon for SYSCON register access.
> 
> Partialy based on the previous work by Serge Semin.
> 
> Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>

...

Hi Keguang Zhang,

some minor feedback from my side.

> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c

...

> +const struct reg_field ls1b_dwmac_syscon_regfields[] = {
> +	[GMAC1_USE_UART1]	= REG_FIELD(LS1X_SYSCON0, 4, 4),
> +	[GMAC1_USE_UART0]	= REG_FIELD(LS1X_SYSCON0, 3, 3),
> +	[GMAC1_SHUT]		= REG_FIELD(LS1X_SYSCON1, 13, 13),
> +	[GMAC0_SHUT]		= REG_FIELD(LS1X_SYSCON1, 12, 12),
> +	[GMAC1_USE_TXCLK]	= REG_FIELD(LS1X_SYSCON1, 3, 3),
> +	[GMAC0_USE_TXCLK]	= REG_FIELD(LS1X_SYSCON1, 2, 2),
> +	[GMAC1_USE_PWM23]	= REG_FIELD(LS1X_SYSCON1, 1, 1),
> +	[GMAC0_USE_PWM01]	= REG_FIELD(LS1X_SYSCON1, 0, 0)
> +};

nit: Perhaps ls1b_dwmac_syscon_regfields should be static.

> +
> +const struct reg_field ls1c_dwmac_syscon_regfields[] = {
> +	[GMAC_SHUT]		= REG_FIELD(LS1X_SYSCON0, 6, 6),
> +	[PHY_INTF_SELI]		= REG_FIELD(LS1X_SYSCON1, 28, 30)
> +};

Likewise, perhaps ls1c_dwmac_syscon_regfields should be static.

...

> +static const struct of_device_id ls1x_dwmac_syscon_match[] = {
> +	{ .compatible = "loongson,ls1b-syscon", .data = &ls1b_dwmac_syscon },
> +	{ .compatible = "loongson,ls1c-syscon", .data = &ls1c_dwmac_syscon },
> +	{ }
> +};o

I am seeing a warning about ls1x_dwmac_syscon_match being unused.
I think this is due to CONFIG_OF being unset.

> +
> +static int ls1x_dwmac_probe(struct platform_device *pdev)
> +{
> +	struct plat_stmmacenet_data *plat_dat;
> +	struct stmmac_resources stmmac_res;
> +	struct device_node *syscon_np;
> +	const struct of_device_id *match;
> +	struct regmap *regmap;
> +	struct ls1x_dwmac *dwmac;
> +	const struct ls1x_dwmac_syscon *syscon;
> +	size_t size;
> +	int ret;
> +
> +	ret = stmmac_get_platform_resources(pdev, &stmmac_res);
> +	if (ret)
> +		return ret;
> +
> +	/* Probe syscon */
> +	syscon_np = of_parse_phandle(pdev->dev.of_node, "syscon", 0);
> +	if (!syscon_np)
> +		return -ENODEV;
> +
> +	match = of_match_node(ls1x_dwmac_syscon_match, syscon_np);
> +	if (!match) {
> +		of_node_put(syscon_np);
> +		return -EINVAL;
> +	}
> +	syscon = (const struct ls1x_dwmac_syscon *)match->data;
> +
> +	regmap = syscon_node_to_regmap(syscon_np);
> +	of_node_put(syscon_np);
> +	if (IS_ERR(regmap)) {
> +		ret = PTR_ERR(regmap);
> +		dev_err(&pdev->dev, "Unable to map syscon: %d\n", ret);
> +		return ret;
> +	}
> +
> +	size = syscon->nr_reg_fields * sizeof(struct regmap_field *);
> +	dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac) + size, GFP_KERNEL);
> +	if (!dwmac)
> +		return -ENOMEM;
> +
> +	plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
> +	if (IS_ERR(plat_dat)) {
> +		dev_err(&pdev->dev, "dt configuration failed\n");
> +		return PTR_ERR(plat_dat);
> +	}
> +
> +	plat_dat->bsp_priv = dwmac;
> +	plat_dat->init = ls1x_dwmac_init;
> +	dwmac->dev = &pdev->dev;
> +	dwmac->plat_dat = plat_dat;
> +	dwmac->syscon = syscon;
> +	dwmac->regmap = regmap;
> +
> +	ret = stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res);
> +	if (ret)
> +		goto err_remove_config_dt;
> +
> +	return 0;
> +
> +err_remove_config_dt:
> +	if (pdev->dev.of_node)
> +		stmmac_remove_config_dt(pdev, plat_dat);
> +
> +	return ret;
> +}

...

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

* Re: [PATCH 0/5] Move Loongson1 MAC arch-code to the driver dir
  2023-08-13 15:24 ` [PATCH 0/5] Move Loongson1 MAC arch-code to the driver dir Andrew Lunn
@ 2023-08-14  2:39   ` Keguang Zhang
  0 siblings, 0 replies; 28+ messages in thread
From: Keguang Zhang @ 2023-08-14  2:39 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: netdev, devicetree, linux-mips, linux-kernel, Lee Jones,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, David S . Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Thomas Bogendoerfer,
	Giuseppe Cavallaro, Alexandre Torgue, Jose Abreu, Serge Semin

On Sun, Aug 13, 2023 at 11:24 PM Andrew Lunn <andrew@lunn.ch> wrote:
>
> On Sat, Aug 12, 2023 at 11:11:30PM +0800, Keguang Zhang wrote:
> > From: Kelvin Zhang <kelvin.zhang@amlogic.com>
> >
> > In order to convert Loongson1 MAC platform devices to the devicetree
> > nodes, Loongson1 MAC arch-code should be moved to the driver dir.
> >
> > In other words, this patchset is a preparation for converting
> > Loongson1 platform devices to devicetree.
>
> It is a long time since i converted an ARM system from platform data
> to DT. But what we tended to do was to allow both for a period of
> time.
>
> Does a system using platform data still work after this change? The
> first patch seems to delete a lot of code, not just move it around.
>
> Can you restructure this patchset to add the glue layer and DT binding
> in parallel with platform data. Then have a patchset which convert all
> in tree machines to using DT. And then a patchset, submitted in maybe
> 6 months time, to remove support for platform data.
>
Sure, I will keep the platform data from the next version.
Thanks!

>         Andrew



-- 
Best regards,

Keguang Zhang

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

* Re: [PATCH 4/5] net: stmmac: Add glue layer for Loongson-1 SoC
  2023-08-13 18:24   ` Simon Horman
@ 2023-08-14 10:50     ` Keguang Zhang
  0 siblings, 0 replies; 28+ messages in thread
From: Keguang Zhang @ 2023-08-14 10:50 UTC (permalink / raw)
  To: Simon Horman
  Cc: netdev, devicetree, linux-mips, linux-kernel, Lee Jones,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Thomas Bogendoerfer,
	Giuseppe Cavallaro, Alexandre Torgue, Jose Abreu, Serge Semin

On Mon, Aug 14, 2023 at 2:24 AM Simon Horman <horms@kernel.org> wrote:
>
> On Sat, Aug 12, 2023 at 11:11:34PM +0800, Keguang Zhang wrote:
> > This glue driver is created based on the arch-code
> > implemented earlier with the platform-specific settings.
> >
> > Use syscon for SYSCON register access.
> >
> > Partialy based on the previous work by Serge Semin.
> >
> > Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
>
> ...
>
> Hi Keguang Zhang,
>
> some minor feedback from my side.
>
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
>
> ...
>
> > +const struct reg_field ls1b_dwmac_syscon_regfields[] = {
> > +     [GMAC1_USE_UART1]       = REG_FIELD(LS1X_SYSCON0, 4, 4),
> > +     [GMAC1_USE_UART0]       = REG_FIELD(LS1X_SYSCON0, 3, 3),
> > +     [GMAC1_SHUT]            = REG_FIELD(LS1X_SYSCON1, 13, 13),
> > +     [GMAC0_SHUT]            = REG_FIELD(LS1X_SYSCON1, 12, 12),
> > +     [GMAC1_USE_TXCLK]       = REG_FIELD(LS1X_SYSCON1, 3, 3),
> > +     [GMAC0_USE_TXCLK]       = REG_FIELD(LS1X_SYSCON1, 2, 2),
> > +     [GMAC1_USE_PWM23]       = REG_FIELD(LS1X_SYSCON1, 1, 1),
> > +     [GMAC0_USE_PWM01]       = REG_FIELD(LS1X_SYSCON1, 0, 0)
> > +};
>
> nit: Perhaps ls1b_dwmac_syscon_regfields should be static.
>
> > +
> > +const struct reg_field ls1c_dwmac_syscon_regfields[] = {
> > +     [GMAC_SHUT]             = REG_FIELD(LS1X_SYSCON0, 6, 6),
> > +     [PHY_INTF_SELI]         = REG_FIELD(LS1X_SYSCON1, 28, 30)
> > +};
>
> Likewise, perhaps ls1c_dwmac_syscon_regfields should be static.
>
Will do.
Thanks!
> ...
>
> > +static const struct of_device_id ls1x_dwmac_syscon_match[] = {
> > +     { .compatible = "loongson,ls1b-syscon", .data = &ls1b_dwmac_syscon },
> > +     { .compatible = "loongson,ls1c-syscon", .data = &ls1c_dwmac_syscon },
> > +     { }
> > +};o
>
> I am seeing a warning about ls1x_dwmac_syscon_match being unused.
> I think this is due to CONFIG_OF being unset.

Will fix these warnings.
>
> > +
> > +static int ls1x_dwmac_probe(struct platform_device *pdev)
> > +{
> > +     struct plat_stmmacenet_data *plat_dat;
> > +     struct stmmac_resources stmmac_res;
> > +     struct device_node *syscon_np;
> > +     const struct of_device_id *match;
> > +     struct regmap *regmap;
> > +     struct ls1x_dwmac *dwmac;
> > +     const struct ls1x_dwmac_syscon *syscon;
> > +     size_t size;
> > +     int ret;
> > +
> > +     ret = stmmac_get_platform_resources(pdev, &stmmac_res);
> > +     if (ret)
> > +             return ret;
> > +
> > +     /* Probe syscon */
> > +     syscon_np = of_parse_phandle(pdev->dev.of_node, "syscon", 0);
> > +     if (!syscon_np)
> > +             return -ENODEV;
> > +
> > +     match = of_match_node(ls1x_dwmac_syscon_match, syscon_np);
> > +     if (!match) {
> > +             of_node_put(syscon_np);
> > +             return -EINVAL;
> > +     }
> > +     syscon = (const struct ls1x_dwmac_syscon *)match->data;
> > +
> > +     regmap = syscon_node_to_regmap(syscon_np);
> > +     of_node_put(syscon_np);
> > +     if (IS_ERR(regmap)) {
> > +             ret = PTR_ERR(regmap);
> > +             dev_err(&pdev->dev, "Unable to map syscon: %d\n", ret);
> > +             return ret;
> > +     }
> > +
> > +     size = syscon->nr_reg_fields * sizeof(struct regmap_field *);
> > +     dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac) + size, GFP_KERNEL);
> > +     if (!dwmac)
> > +             return -ENOMEM;
> > +
> > +     plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
> > +     if (IS_ERR(plat_dat)) {
> > +             dev_err(&pdev->dev, "dt configuration failed\n");
> > +             return PTR_ERR(plat_dat);
> > +     }
> > +
> > +     plat_dat->bsp_priv = dwmac;
> > +     plat_dat->init = ls1x_dwmac_init;
> > +     dwmac->dev = &pdev->dev;
> > +     dwmac->plat_dat = plat_dat;
> > +     dwmac->syscon = syscon;
> > +     dwmac->regmap = regmap;
> > +
> > +     ret = stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res);
> > +     if (ret)
> > +             goto err_remove_config_dt;
> > +
> > +     return 0;
> > +
> > +err_remove_config_dt:
> > +     if (pdev->dev.of_node)
> > +             stmmac_remove_config_dt(pdev, plat_dat);
> > +
> > +     return ret;
> > +}
>
> ...



-- 
Best regards,

Keguang Zhang

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

* Re: [PATCH 2/5] dt-bindings: mfd: syscon: Add compatibles for Loongson-1 syscon
  2023-08-12 15:11 ` [PATCH 2/5] dt-bindings: mfd: syscon: Add compatibles for Loongson-1 syscon Keguang Zhang
@ 2023-08-14 19:06   ` Krzysztof Kozlowski
  0 siblings, 0 replies; 28+ messages in thread
From: Krzysztof Kozlowski @ 2023-08-14 19:06 UTC (permalink / raw)
  To: Keguang Zhang, netdev, devicetree, linux-mips, linux-kernel
  Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Thomas Bogendoerfer, Giuseppe Cavallaro, Alexandre Torgue,
	Jose Abreu, Serge Semin

On 12/08/2023 17:11, Keguang Zhang wrote:
> Add Loongson LS1B and LS1C compatibles for system controller.
> 
> Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
> ---
>  Documentation/devicetree/bindings/mfd/syscon.yaml | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/mfd/syscon.yaml b/Documentation/devicetree/bindings/mfd/syscon.yaml
> index 8103154bbb52..c77d7b155a4c 100644
> --- a/Documentation/devicetree/bindings/mfd/syscon.yaml
> +++ b/Documentation/devicetree/bindings/mfd/syscon.yaml
> @@ -49,6 +49,8 @@ properties:
>                - hisilicon,peri-subctrl
>                - hpe,gxp-sysreg
>                - intel,lgm-syscon
> +              - loongson,ls1b-syscon
> +              - loongson,ls1c-syscon

It seems each SoC has multiple syscons so using the same compatible is
wrong. Different devices should have different compatibles.

Best regards,
Krzysztof


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

* Re: [PATCH 3/5] dt-bindings: net: Add Loongson-1 DWMAC glue layer
  2023-08-12 15:11 ` [PATCH 3/5] dt-bindings: net: Add Loongson-1 DWMAC glue layer Keguang Zhang
@ 2023-08-14 19:11   ` Krzysztof Kozlowski
  2023-08-16 12:54   ` Serge Semin
  1 sibling, 0 replies; 28+ messages in thread
From: Krzysztof Kozlowski @ 2023-08-14 19:11 UTC (permalink / raw)
  To: Keguang Zhang, netdev, devicetree, linux-mips, linux-kernel
  Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Thomas Bogendoerfer, Giuseppe Cavallaro, Alexandre Torgue,
	Jose Abreu, Serge Semin

On 12/08/2023 17:11, Keguang Zhang wrote:
> Add devicetree binding document for Loongson-1 DWMAC glue layer.
> 
> Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
> ---
>  .../bindings/net/loongson,ls1x-dwmac.yaml     | 98 +++++++++++++++++++
>  .../devicetree/bindings/net/snps,dwmac.yaml   |  2 +
>  2 files changed, 100 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/net/loongson,ls1x-dwmac.yaml
> 
> diff --git a/Documentation/devicetree/bindings/net/loongson,ls1x-dwmac.yaml b/Documentation/devicetree/bindings/net/loongson,ls1x-dwmac.yaml
> new file mode 100644
> index 000000000000..150799460599
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/loongson,ls1x-dwmac.yaml
> @@ -0,0 +1,98 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/net/loongson,ls1x-dwmac.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Loongson-1 DWMAC glue layer
> +
> +maintainers:
> +  - Keguang Zhang <keguang.zhang@gmail.com>
> +
> +select:
> +  properties:
> +    compatible:
> +      contains:
> +        enum:
> +          - loongson,ls1b-dwmac
> +          - loongson,ls1c-dwmac
> +  required:
> +    - compatible
> +
> +properties:
> +  compatible:
> +    items:
> +      - enum:
> +          - loongson,ls1b-dwmac
> +          - loongson,ls1c-dwmac
> +      - const: snps,dwmac-3.50a
> +
> +  reg:
> +    maxItems: 1
> +
> +  clocks:
> +    maxItems: 1
> +
> +  clock-names:
> +    const: stmmaceth

This should be list (items) with one const item.

> +
> +  interrupts:
> +    maxItems: 1
> +
> +  interrupt-names:
> +    const: macirq

Ditto

> +
> +  syscon:

Let me quote:

"Phandle to syscon device requires a vendor, descriptive name and a
description"

You only got description right.

> +    $ref: /schemas/types.yaml#/definitions/phandle
> +    description:
> +      Phandle to the syscon containing some extra configurations
> +      including PHY interface mode.
> +
> +required:
> +  - compatible
> +  - reg
> +  - clocks
> +  - clock-names
> +  - interrupts
> +  - interrupt-names
> +  - phy-handle
> +  - phy-mode

Drop, it is not defined here and already required by snps,dwmac.

> +  - syscon
> +
> +allOf:
> +  - $ref: snps,dwmac.yaml#
> +
> +unevaluatedProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/clock/loongson,ls1x-clk.h>
> +    #include <dt-bindings/interrupt-controller/irq.h>
> +
> +    gmac0: ethernet@1fe10000 {
> +        compatible = "loongson,ls1b-dwmac", "snps,dwmac-3.50a";
> +        reg = <0x1fe10000 0x10000>;
> +
> +        clocks = <&clkc LS1X_CLKID_AHB>;
> +        clock-names = "stmmaceth";
> +
> +        interrupt-parent = <&intc1>;
> +        interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
> +        interrupt-names = "macirq";
> +
> +        phy-handle = <&phy0>;
> +        phy-mode = "mii";
> +
> +        snps,pbl = <1>;
> +        syscon = <&syscon>;
> +
> +        mdio {
> +            #address-cells = <1>;
> +            #size-cells = <0>;
> +            compatible = "snps,dwmac-mdio";
> +
> +            phy0: ethernet-phy@0 {
> +                reg = <0x0>;
> +            };
> +        };
> +    };
> diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
> index ddf9522a5dc2..e1a956cf171e 100644
> --- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml
> +++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
> @@ -66,6 +66,8 @@ properties:
>          - ingenic,x2000-mac
>          - loongson,ls2k-dwmac
>          - loongson,ls7a-dwmac
> +        - loongson,ls1b-dwmac
> +        - loongson,ls1c-dwmac

You should not need it. Isn't snps,dwmac-3.50a already there? Anyway,
not alphabetically ordered...

>          - qcom,qcs404-ethqos
>          - qcom,sa8775p-ethqos
>          - qcom,sc8280xp-ethqos

Best regards,
Krzysztof


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

* Re: [PATCH 5/5] MAINTAINERS: Add entry for Loongson-1 DWMAC
  2023-08-12 15:11 ` [PATCH 5/5] MAINTAINERS: Add entry for Loongson-1 DWMAC Keguang Zhang
@ 2023-08-14 19:16   ` Krzysztof Kozlowski
  0 siblings, 0 replies; 28+ messages in thread
From: Krzysztof Kozlowski @ 2023-08-14 19:16 UTC (permalink / raw)
  To: Keguang Zhang, netdev, devicetree, linux-mips, linux-kernel
  Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Thomas Bogendoerfer, Giuseppe Cavallaro, Alexandre Torgue,
	Jose Abreu, Serge Semin

On 12/08/2023 17:11, Keguang Zhang wrote:
> Update MAINTAINERS to add Loongson-1 DWMAC entry.
> 
> Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
> ---
>  MAINTAINERS | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 02a3192195af..3f47f2a43b41 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -14309,9 +14309,11 @@ MIPS/LOONGSON1 ARCHITECTURE
>  M:	Keguang Zhang <keguang.zhang@gmail.com>
>  L:	linux-mips@vger.kernel.org
>  S:	Maintained
> +F:	Documentation/devicetree/bindings/*/loongson,ls1x-*.yaml
>  F:	arch/mips/include/asm/mach-loongson32/
>  F:	arch/mips/loongson32/
>  F:	drivers/*/*loongson1*
> +F:	drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c

Since you do not add dedicated entry, just squash each part with commit
adding this file.

Best regards,
Krzysztof


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

* Re: [PATCH 3/5] dt-bindings: net: Add Loongson-1 DWMAC glue layer
  2023-08-12 15:11 ` [PATCH 3/5] dt-bindings: net: Add Loongson-1 DWMAC glue layer Keguang Zhang
  2023-08-14 19:11   ` Krzysztof Kozlowski
@ 2023-08-16 12:54   ` Serge Semin
  2023-08-18 10:42     ` Keguang Zhang
  1 sibling, 1 reply; 28+ messages in thread
From: Serge Semin @ 2023-08-16 12:54 UTC (permalink / raw)
  To: Keguang Zhang
  Cc: netdev, devicetree, linux-mips, linux-kernel, Lee Jones,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, David S . Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Thomas Bogendoerfer,
	Giuseppe Cavallaro, Alexandre Torgue, Jose Abreu, Serge Semin

Hi Keguang

On Sat, Aug 12, 2023 at 11:11:33PM +0800, Keguang Zhang wrote:
> Add devicetree binding document for Loongson-1 DWMAC glue layer.
> 
> Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
> ---
>  .../bindings/net/loongson,ls1x-dwmac.yaml     | 98 +++++++++++++++++++
>  .../devicetree/bindings/net/snps,dwmac.yaml   |  2 +
>  2 files changed, 100 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/net/loongson,ls1x-dwmac.yaml
> 
> diff --git a/Documentation/devicetree/bindings/net/loongson,ls1x-dwmac.yaml b/Documentation/devicetree/bindings/net/loongson,ls1x-dwmac.yaml
> new file mode 100644
> index 000000000000..150799460599
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/loongson,ls1x-dwmac.yaml
> @@ -0,0 +1,98 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/net/loongson,ls1x-dwmac.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +

> +title: Loongson-1 DWMAC glue layer

DT-schemas describe a device. It has nothing to do with the glue
driver/layer/whatever.

Also I suggest to add a brief device description in the
"description:" property and add there a brief info regarding the SoCs
the controllers can be found on, the DW (G)MAC IP-core version the
ethernet controllers are based on and if possible some data about the
synthesize parameters: SMA (MDIO-bus), Tx/Rx COE, DMA FIFOs size,
perfect and hash MAC-filters size, L3L4 frame filters availability,
PHY interfaces (MII, RMII, RGMII, etc), EEE support, IEEE 1588(-2008)
Timestamping support, PMT and Wake-up frame support, MAC Management
counters (MMC).

Note DMA FIFO sizes can be also constrained in the properties
"rx-fifo-depth" and "tx-fifo-depth"; perfect and hash MAC-filter sizes -
in "snps,perfect-filter-entries" and "snps,multicast-filter-bins".

> +
> +maintainers:
> +  - Keguang Zhang <keguang.zhang@gmail.com>
> +
> +select:
> +  properties:
> +    compatible:
> +      contains:
> +        enum:
> +          - loongson,ls1b-dwmac
> +          - loongson,ls1c-dwmac
> +  required:
> +    - compatible
> +
> +properties:
> +  compatible:
> +    items:
> +      - enum:
> +          - loongson,ls1b-dwmac
> +          - loongson,ls1c-dwmac
> +      - const: snps,dwmac-3.50a
> +
> +  reg:
> +    maxItems: 1
> +
> +  clocks:
> +    maxItems: 1
> +
> +  clock-names:
> +    const: stmmaceth
> +
> +  interrupts:
> +    maxItems: 1
> +
> +  interrupt-names:
> +    const: macirq
> +

> +  syscon:
> +    $ref: /schemas/types.yaml#/definitions/phandle
> +    description:
> +      Phandle to the syscon containing some extra configurations
> +      including PHY interface mode.

I believe the property is supposed to have a vendor-specific name like
"loongson,ls1-syscon" or similar.

> +
> +required:
> +  - compatible
> +  - reg
> +  - clocks
> +  - clock-names
> +  - interrupts
> +  - interrupt-names
> +  - phy-handle

> +  - phy-mode

You may want to specify the enum-constraints with the value permitted
for the particular Loongson (G)MAC controller. Seeing ls1b and ls1c
imply different sets of the PHY-modes the constraints are better to be
defined in the allOf sub-schemas. Alternatively you can split the
DT-schema file into two: one for ls1b-dwmac, another one for
ls1c-dwmac. IMO the later option seems better.

-Serge(y)

> +  - syscon
> +
> +allOf:
> +  - $ref: snps,dwmac.yaml#
> +
> +unevaluatedProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/clock/loongson,ls1x-clk.h>
> +    #include <dt-bindings/interrupt-controller/irq.h>
> +
> +    gmac0: ethernet@1fe10000 {
> +        compatible = "loongson,ls1b-dwmac", "snps,dwmac-3.50a";
> +        reg = <0x1fe10000 0x10000>;
> +
> +        clocks = <&clkc LS1X_CLKID_AHB>;
> +        clock-names = "stmmaceth";
> +
> +        interrupt-parent = <&intc1>;
> +        interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
> +        interrupt-names = "macirq";
> +
> +        phy-handle = <&phy0>;
> +        phy-mode = "mii";
> +
> +        snps,pbl = <1>;
> +        syscon = <&syscon>;
> +
> +        mdio {
> +            #address-cells = <1>;
> +            #size-cells = <0>;
> +            compatible = "snps,dwmac-mdio";
> +
> +            phy0: ethernet-phy@0 {
> +                reg = <0x0>;
> +            };
> +        };
> +    };
> diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
> index ddf9522a5dc2..e1a956cf171e 100644
> --- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml
> +++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
> @@ -66,6 +66,8 @@ properties:
>          - ingenic,x2000-mac
>          - loongson,ls2k-dwmac
>          - loongson,ls7a-dwmac
> +        - loongson,ls1b-dwmac
> +        - loongson,ls1c-dwmac
>          - qcom,qcs404-ethqos
>          - qcom,sa8775p-ethqos
>          - qcom,sc8280xp-ethqos
> -- 
> 2.39.2
> 

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

* Re: [PATCH 4/5] net: stmmac: Add glue layer for Loongson-1 SoC
  2023-08-12 15:11 ` [PATCH 4/5] net: stmmac: Add glue layer for Loongson-1 SoC Keguang Zhang
                     ` (2 preceding siblings ...)
  2023-08-13 18:24   ` Simon Horman
@ 2023-08-16 13:30   ` Serge Semin
  2023-08-18 12:37     ` Keguang Zhang
  3 siblings, 1 reply; 28+ messages in thread
From: Serge Semin @ 2023-08-16 13:30 UTC (permalink / raw)
  To: Keguang Zhang
  Cc: netdev, devicetree, linux-mips, linux-kernel, Lee Jones,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, David S . Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Thomas Bogendoerfer,
	Giuseppe Cavallaro, Alexandre Torgue, Jose Abreu, Serge Semin

On Sat, Aug 12, 2023 at 11:11:34PM +0800, Keguang Zhang wrote:
> This glue driver is created based on the arch-code
> implemented earlier with the platform-specific settings.
> 
> Use syscon for SYSCON register access.
> 
> Partialy based on the previous work by Serge Semin.
> 
> Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
> ---
>  drivers/net/ethernet/stmicro/stmmac/Kconfig   |  11 +
>  drivers/net/ethernet/stmicro/stmmac/Makefile  |   1 +
>  .../ethernet/stmicro/stmmac/dwmac-loongson1.c | 257 ++++++++++++++++++
>  3 files changed, 269 insertions(+)
>  create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> index 06c6871f8788..a2b9e289aa36 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
> +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> @@ -239,6 +239,17 @@ config DWMAC_INTEL_PLAT
>  	  the stmmac device driver. This driver is used for the Intel Keem Bay
>  	  SoC.
>  
> +config DWMAC_LOONGSON1
> +	tristate "Loongson1 GMAC support"
> +	default MACH_LOONGSON32
> +	depends on OF && (MACH_LOONGSON32 || COMPILE_TEST)
> +	help
> +	  Support for ethernet controller on Loongson1 SoC.
> +
> +	  This selects Loongson1 SoC glue layer support for the stmmac
> +	  device driver. This driver is used for Loongson1-based boards
> +	  like Loongson LS1B/LS1C.
> +
>  config DWMAC_TEGRA
>  	tristate "NVIDIA Tegra MGBE support"
>  	depends on ARCH_TEGRA || COMPILE_TEST
> diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
> index 5b57aee19267..80e598bd4255 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/Makefile
> +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
> @@ -29,6 +29,7 @@ obj-$(CONFIG_DWMAC_SUNXI)	+= dwmac-sunxi.o
>  obj-$(CONFIG_DWMAC_SUN8I)	+= dwmac-sun8i.o
>  obj-$(CONFIG_DWMAC_DWC_QOS_ETH)	+= dwmac-dwc-qos-eth.o
>  obj-$(CONFIG_DWMAC_INTEL_PLAT)	+= dwmac-intel-plat.o
> +obj-$(CONFIG_DWMAC_LOONGSON1)	+= dwmac-loongson1.o
>  obj-$(CONFIG_DWMAC_GENERIC)	+= dwmac-generic.o
>  obj-$(CONFIG_DWMAC_IMX8)	+= dwmac-imx.o
>  obj-$(CONFIG_DWMAC_TEGRA)	+= dwmac-tegra.o
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> new file mode 100644
> index 000000000000..368d6cd2cb78
> --- /dev/null
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> @@ -0,0 +1,257 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Loongson-1 DWMAC glue layer
> + *
> + * Copyright (C) 2011-2023 Keguang Zhang <keguang.zhang@gmail.com>
> + */
> +
> +#include <linux/mfd/syscon.h>
> +#include <linux/module.h>
> +#include <linux/phy.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +
> +#include "stmmac.h"
> +#include "stmmac_platform.h"
> +
> +/* Loongson-1 SYSCON Registers */
> +#define LS1X_SYSCON0		(0x0)
> +#define LS1X_SYSCON1		(0x4)
> +
> +struct ls1x_dwmac_syscon {
> +	const struct reg_field *reg_fields;
> +	unsigned int nr_reg_fields;
> +	int (*syscon_init)(struct plat_stmmacenet_data *plat);
> +};
> +
> +struct ls1x_dwmac {
> +	struct device *dev;
> +	struct plat_stmmacenet_data *plat_dat;
> +	const struct ls1x_dwmac_syscon *syscon;
> +	struct regmap *regmap;
> +	struct regmap_field *regmap_fields[];
> +};
> +
> +enum ls1b_dwmac_syscon_regfield {
> +	GMAC1_USE_UART1,
> +	GMAC1_USE_UART0,
> +	GMAC1_SHUT,
> +	GMAC0_SHUT,
> +	GMAC1_USE_TXCLK,
> +	GMAC0_USE_TXCLK,
> +	GMAC1_USE_PWM23,
> +	GMAC0_USE_PWM01,
> +};
> +
> +enum ls1c_dwmac_syscon_regfield {
> +	GMAC_SHUT,
> +	PHY_INTF_SELI,
> +};
> +
> +const struct reg_field ls1b_dwmac_syscon_regfields[] = {
> +	[GMAC1_USE_UART1]	= REG_FIELD(LS1X_SYSCON0, 4, 4),
> +	[GMAC1_USE_UART0]	= REG_FIELD(LS1X_SYSCON0, 3, 3),
> +	[GMAC1_SHUT]		= REG_FIELD(LS1X_SYSCON1, 13, 13),
> +	[GMAC0_SHUT]		= REG_FIELD(LS1X_SYSCON1, 12, 12),
> +	[GMAC1_USE_TXCLK]	= REG_FIELD(LS1X_SYSCON1, 3, 3),
> +	[GMAC0_USE_TXCLK]	= REG_FIELD(LS1X_SYSCON1, 2, 2),
> +	[GMAC1_USE_PWM23]	= REG_FIELD(LS1X_SYSCON1, 1, 1),
> +	[GMAC0_USE_PWM01]	= REG_FIELD(LS1X_SYSCON1, 0, 0)
> +};
> +
> +const struct reg_field ls1c_dwmac_syscon_regfields[] = {
> +	[GMAC_SHUT]		= REG_FIELD(LS1X_SYSCON0, 6, 6),
> +	[PHY_INTF_SELI]		= REG_FIELD(LS1X_SYSCON1, 28, 30)
> +};

Emm, using regmap fields looks so over-complicated in this case seeing
you only need to set/clear several bits in the syscon. What about
defining macros with the particular flag as it's already done in the
"asm/mach-loongson32/regs-mux.h" file and using regmap_update_bits()?

> +

> +static int ls1b_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
> +{

As I already told you this part is better to be called from the
plat_stmmacenet_data.fix_mac_speed() because PHY interface mode can
differ from one interface open cycle to another as per the phylink
design.

> +	struct ls1x_dwmac *dwmac = plat->bsp_priv;
> +	struct regmap_field **regmap_fields = dwmac->regmap_fields;
> +

> +	if (plat->bus_id) {

Using bus_id doesn't look correct to determine the CSRs responsible
for the interface mode selection because it's calculated based on the
DT ethernet-alias which doesn't guarantee to have a particular device
assigned with the alias. Alias node can be absent after all. What
could be better in this case is for instance to use the regs physical
address. Any better idea?

> +		regmap_field_write(regmap_fields[GMAC1_USE_UART1], 1);
> +		regmap_field_write(regmap_fields[GMAC1_USE_UART0], 1);
> +
> +		switch (plat->phy_interface) {
> +		case PHY_INTERFACE_MODE_RGMII:
> +			regmap_field_write(regmap_fields[GMAC1_USE_TXCLK], 0);
> +			regmap_field_write(regmap_fields[GMAC1_USE_PWM23], 0);
> +			break;
> +		case PHY_INTERFACE_MODE_MII:
> +			regmap_field_write(regmap_fields[GMAC1_USE_TXCLK], 1);
> +			regmap_field_write(regmap_fields[GMAC1_USE_PWM23], 1);
> +			break;
> +		default:
> +			dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
> +				plat->phy_interface);
> +			return -EOPNOTSUPP;
> +		}
> +
> +		regmap_field_write(regmap_fields[GMAC1_SHUT], 0);
> +	} else {
> +		switch (plat->phy_interface) {
> +		case PHY_INTERFACE_MODE_RGMII:
> +			regmap_field_write(regmap_fields[GMAC0_USE_TXCLK], 0);
> +			regmap_field_write(regmap_fields[GMAC0_USE_PWM01], 0);
> +			break;
> +		case PHY_INTERFACE_MODE_MII:
> +			regmap_field_write(regmap_fields[GMAC0_USE_TXCLK], 1);
> +			regmap_field_write(regmap_fields[GMAC0_USE_PWM01], 1);
> +			break;
> +		default:
> +			dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
> +				plat->phy_interface);
> +			return -EOPNOTSUPP;
> +		}
> +
> +		regmap_field_write(regmap_fields[GMAC0_SHUT], 0);
> +	}
> +
> +	return 0;
> +}
> +
> +static int ls1c_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
> +{
> +	struct ls1x_dwmac *dwmac = plat->bsp_priv;
> +	struct regmap_field **regmap_fields = dwmac->regmap_fields;
> +
> +	if (plat->phy_interface == PHY_INTERFACE_MODE_RMII) {
> +		regmap_field_write(regmap_fields[PHY_INTF_SELI], 0x4);
> +	} else {
> +		dev_err(dwmac->dev, "Unsupported PHY-mode %u\n",
> +			plat->phy_interface);
> +		return -EOPNOTSUPP;
> +	}
> +
> +	regmap_field_write(regmap_fields[GMAC_SHUT], 0);
> +
> +	return 0;
> +}
> +
> +static const struct ls1x_dwmac_syscon ls1b_dwmac_syscon = {
> +	.reg_fields = ls1b_dwmac_syscon_regfields,
> +	.nr_reg_fields = ARRAY_SIZE(ls1b_dwmac_syscon_regfields),
> +	.syscon_init = ls1b_dwmac_syscon_init,
> +};
> +
> +static const struct ls1x_dwmac_syscon ls1c_dwmac_syscon = {
> +	.reg_fields = ls1c_dwmac_syscon_regfields,
> +	.nr_reg_fields = ARRAY_SIZE(ls1c_dwmac_syscon_regfields),
> +	.syscon_init = ls1c_dwmac_syscon_init,
> +};
> +
> +static int ls1x_dwmac_init(struct platform_device *pdev, void *priv)
> +{
> +	struct ls1x_dwmac *dwmac = priv;
> +	int ret;
> +

> +	ret = devm_regmap_field_bulk_alloc(dwmac->dev, dwmac->regmap,
> +					   dwmac->regmap_fields,
> +					   dwmac->syscon->reg_fields,
> +					   dwmac->syscon->nr_reg_fields);

Please see my first comment about this.

> +	if (ret)
> +		return ret;
> +
> +	if (dwmac->syscon->syscon_init) {
> +		ret = dwmac->syscon->syscon_init(dwmac->plat_dat);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id ls1x_dwmac_syscon_match[] = {
> +	{ .compatible = "loongson,ls1b-syscon", .data = &ls1b_dwmac_syscon },
> +	{ .compatible = "loongson,ls1c-syscon", .data = &ls1c_dwmac_syscon },
> +	{ }
> +};
> +
> +static int ls1x_dwmac_probe(struct platform_device *pdev)
> +{
> +	struct plat_stmmacenet_data *plat_dat;
> +	struct stmmac_resources stmmac_res;
> +	struct device_node *syscon_np;
> +	const struct of_device_id *match;
> +	struct regmap *regmap;
> +	struct ls1x_dwmac *dwmac;
> +	const struct ls1x_dwmac_syscon *syscon;
> +	size_t size;
> +	int ret;
> +
> +	ret = stmmac_get_platform_resources(pdev, &stmmac_res);
> +	if (ret)
> +		return ret;
> +

> +	/* Probe syscon */
> +	syscon_np = of_parse_phandle(pdev->dev.of_node, "syscon", 0);

it's vendor-specific property so it is supposed to have a
vendor-specific prefix and possibly ls1-specific name.

> +	if (!syscon_np)
> +		return -ENODEV;
> +
> +	match = of_match_node(ls1x_dwmac_syscon_match, syscon_np);
> +	if (!match) {
> +		of_node_put(syscon_np);
> +		return -EINVAL;
> +	}
> +	syscon = (const struct ls1x_dwmac_syscon *)match->data;
> +
> +	regmap = syscon_node_to_regmap(syscon_np);
> +	of_node_put(syscon_np);
> +	if (IS_ERR(regmap)) {
> +		ret = PTR_ERR(regmap);
> +		dev_err(&pdev->dev, "Unable to map syscon: %d\n", ret);
> +		return ret;
> +	}

or you can use syscon_regmap_lookup_by_phandle(). Using
of_match_node() doesn't seem necessary since it's unlikely to have
moee than one system controller available on the LS1b or LS1c chips.

> +
> +	size = syscon->nr_reg_fields * sizeof(struct regmap_field *);
> +	dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac) + size, GFP_KERNEL);
> +	if (!dwmac)
> +		return -ENOMEM;
> +
> +	plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
> +	if (IS_ERR(plat_dat)) {
> +		dev_err(&pdev->dev, "dt configuration failed\n");
> +		return PTR_ERR(plat_dat);
> +	}
> +
> +	plat_dat->bsp_priv = dwmac;
> +	plat_dat->init = ls1x_dwmac_init;
> +	dwmac->dev = &pdev->dev;
> +	dwmac->plat_dat = plat_dat;
> +	dwmac->syscon = syscon;
> +	dwmac->regmap = regmap;
> +
> +	ret = stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res);
> +	if (ret)
> +		goto err_remove_config_dt;
> +
> +	return 0;
> +
> +err_remove_config_dt:

> +	if (pdev->dev.of_node)

Is this conditional statement necessary here?

-Serge

> +		stmmac_remove_config_dt(pdev, plat_dat);
> +
> +	return ret;
> +}
> +
> +static const struct of_device_id ls1x_dwmac_match[] = {
> +	{ .compatible = "loongson,ls1b-dwmac" },
> +	{ .compatible = "loongson,ls1c-dwmac" },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, ls1x_dwmac_match);
> +
> +static struct platform_driver ls1x_dwmac_driver = {
> +	.probe = ls1x_dwmac_probe,
> +	.remove_new = stmmac_pltfr_remove,
> +	.driver = {
> +		.name = "loongson1-dwmac",
> +		.of_match_table = ls1x_dwmac_match,
> +	},
> +};
> +module_platform_driver(ls1x_dwmac_driver);
> +
> +MODULE_AUTHOR("Keguang Zhang <keguang.zhang@gmail.com>");
> +MODULE_DESCRIPTION("Loongson1 DWMAC glue layer");
> +MODULE_LICENSE("GPL");
> -- 
> 2.39.2
> 

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

* Re: [PATCH 3/5] dt-bindings: net: Add Loongson-1 DWMAC glue layer
  2023-08-16 12:54   ` Serge Semin
@ 2023-08-18 10:42     ` Keguang Zhang
  2023-08-18 13:48       ` Serge Semin
  0 siblings, 1 reply; 28+ messages in thread
From: Keguang Zhang @ 2023-08-18 10:42 UTC (permalink / raw)
  To: Serge Semin
  Cc: netdev, devicetree, linux-mips, linux-kernel, Lee Jones,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, David S . Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Thomas Bogendoerfer,
	Giuseppe Cavallaro, Alexandre Torgue, Jose Abreu, Serge Semin

On Wed, Aug 16, 2023 at 8:54 PM Serge Semin <fancer.lancer@gmail.com> wrote:
>
> Hi Keguang
>
> On Sat, Aug 12, 2023 at 11:11:33PM +0800, Keguang Zhang wrote:
> > Add devicetree binding document for Loongson-1 DWMAC glue layer.
> >
> > Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
> > ---
> >  .../bindings/net/loongson,ls1x-dwmac.yaml     | 98 +++++++++++++++++++
> >  .../devicetree/bindings/net/snps,dwmac.yaml   |  2 +
> >  2 files changed, 100 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/net/loongson,ls1x-dwmac.yaml
> >
> > diff --git a/Documentation/devicetree/bindings/net/loongson,ls1x-dwmac.yaml b/Documentation/devicetree/bindings/net/loongson,ls1x-dwmac.yaml
> > new file mode 100644
> > index 000000000000..150799460599
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/net/loongson,ls1x-dwmac.yaml
> > @@ -0,0 +1,98 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/net/loongson,ls1x-dwmac.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
>
> > +title: Loongson-1 DWMAC glue layer
>
> DT-schemas describe a device. It has nothing to do with the glue
> driver/layer/whatever.
>
OK. But what about the MODULE_DESCRIPTION in dwmac-loongson1.c
MODULE_DESCRIPTION("Loongson1 DWMAC glue layer");
Should the two parts be aligned with each other?
If not, what's your suggestion then?

> Also I suggest to add a brief device description in the
> "description:" property and add there a brief info regarding the SoCs
> the controllers can be found on, the DW (G)MAC IP-core version the
> ethernet controllers are based on and if possible some data about the
> synthesize parameters: SMA (MDIO-bus), Tx/Rx COE, DMA FIFOs size,
> perfect and hash MAC-filters size, L3L4 frame filters availability,
> PHY interfaces (MII, RMII, RGMII, etc), EEE support, IEEE 1588(-2008)
> Timestamping support, PMT and Wake-up frame support, MAC Management
> counters (MMC).
>
> Note DMA FIFO sizes can be also constrained in the properties
> "rx-fifo-depth" and "tx-fifo-depth"; perfect and hash MAC-filter sizes -
> in "snps,perfect-filter-entries" and "snps,multicast-filter-bins".
>
OK. The description could be added in next version.

> > +
> > +maintainers:
> > +  - Keguang Zhang <keguang.zhang@gmail.com>
> > +
> > +select:
> > +  properties:
> > +    compatible:
> > +      contains:
> > +        enum:
> > +          - loongson,ls1b-dwmac
> > +          - loongson,ls1c-dwmac
> > +  required:
> > +    - compatible
> > +
> > +properties:
> > +  compatible:
> > +    items:
> > +      - enum:
> > +          - loongson,ls1b-dwmac
> > +          - loongson,ls1c-dwmac
> > +      - const: snps,dwmac-3.50a
> > +
> > +  reg:
> > +    maxItems: 1
> > +
> > +  clocks:
> > +    maxItems: 1
> > +
> > +  clock-names:
> > +    const: stmmaceth
> > +
> > +  interrupts:
> > +    maxItems: 1
> > +
> > +  interrupt-names:
> > +    const: macirq
> > +
>
> > +  syscon:
> > +    $ref: /schemas/types.yaml#/definitions/phandle
> > +    description:
> > +      Phandle to the syscon containing some extra configurations
> > +      including PHY interface mode.
>
> I believe the property is supposed to have a vendor-specific name like
> "loongson,ls1-syscon" or similar.

This has been fixed in v2.
Could you please review v2?
Thanks!
>
> > +
> > +required:
> > +  - compatible
> > +  - reg
> > +  - clocks
> > +  - clock-names
> > +  - interrupts
> > +  - interrupt-names
> > +  - phy-handle
>
> > +  - phy-mode
>
> You may want to specify the enum-constraints with the value permitted
> for the particular Loongson (G)MAC controller. Seeing ls1b and ls1c
> imply different sets of the PHY-modes the constraints are better to be
> defined in the allOf sub-schemas. Alternatively you can split the
> DT-schema file into two: one for ls1b-dwmac, another one for
> ls1c-dwmac. IMO the later option seems better.
>
The "phy-mode", as pointed by Krzysztof, is defined in
ethernet-controller and already required by snps,dwmac.
So I have dropped it in v2.
For allOf sub-schemas, do you mean something below?
allOf:
 - $ref: snps,dwmac.yaml#

 - if:
     properties:
       compatible:
         contains:
           const: loongson,ls1b-dwmac
   then:
     properties:
       phy-mode:
         enum:
           - mii
           - rgmii

 - if:
     properties:
       compatible:
         contains:
           const: loongson,ls1c-dwmac
   then:
     properties:
       phy-mode:
         enum:
           - mii
           - rmii

> -Serge(y)
>
> > +  - syscon
> > +
> > +allOf:
> > +  - $ref: snps,dwmac.yaml#
> > +
> > +unevaluatedProperties: false
> > +
> > +examples:
> > +  - |
> > +    #include <dt-bindings/clock/loongson,ls1x-clk.h>
> > +    #include <dt-bindings/interrupt-controller/irq.h>
> > +
> > +    gmac0: ethernet@1fe10000 {
> > +        compatible = "loongson,ls1b-dwmac", "snps,dwmac-3.50a";
> > +        reg = <0x1fe10000 0x10000>;
> > +
> > +        clocks = <&clkc LS1X_CLKID_AHB>;
> > +        clock-names = "stmmaceth";
> > +
> > +        interrupt-parent = <&intc1>;
> > +        interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
> > +        interrupt-names = "macirq";
> > +
> > +        phy-handle = <&phy0>;
> > +        phy-mode = "mii";
> > +
> > +        snps,pbl = <1>;
> > +        syscon = <&syscon>;
> > +
> > +        mdio {
> > +            #address-cells = <1>;
> > +            #size-cells = <0>;
> > +            compatible = "snps,dwmac-mdio";
> > +
> > +            phy0: ethernet-phy@0 {
> > +                reg = <0x0>;
> > +            };
> > +        };
> > +    };
> > diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
> > index ddf9522a5dc2..e1a956cf171e 100644
> > --- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml
> > +++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
> > @@ -66,6 +66,8 @@ properties:
> >          - ingenic,x2000-mac
> >          - loongson,ls2k-dwmac
> >          - loongson,ls7a-dwmac
> > +        - loongson,ls1b-dwmac
> > +        - loongson,ls1c-dwmac
> >          - qcom,qcs404-ethqos
> >          - qcom,sa8775p-ethqos
> >          - qcom,sc8280xp-ethqos
> > --
> > 2.39.2
> >



--
Best regards,

Keguang Zhang

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

* Re: [PATCH 4/5] net: stmmac: Add glue layer for Loongson-1 SoC
  2023-08-16 13:30   ` Serge Semin
@ 2023-08-18 12:37     ` Keguang Zhang
  2023-08-18 16:19       ` Serge Semin
  0 siblings, 1 reply; 28+ messages in thread
From: Keguang Zhang @ 2023-08-18 12:37 UTC (permalink / raw)
  To: Serge Semin
  Cc: netdev, devicetree, linux-mips, linux-kernel, Lee Jones,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, David S . Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Thomas Bogendoerfer,
	Giuseppe Cavallaro, Alexandre Torgue, Jose Abreu, Serge Semin

On Wed, Aug 16, 2023 at 9:30 PM Serge Semin <fancer.lancer@gmail.com> wrote:
>
> On Sat, Aug 12, 2023 at 11:11:34PM +0800, Keguang Zhang wrote:
> > This glue driver is created based on the arch-code
> > implemented earlier with the platform-specific settings.
> >
> > Use syscon for SYSCON register access.
> >
> > Partialy based on the previous work by Serge Semin.
> >
> > Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
> > ---
> >  drivers/net/ethernet/stmicro/stmmac/Kconfig   |  11 +
> >  drivers/net/ethernet/stmicro/stmmac/Makefile  |   1 +
> >  .../ethernet/stmicro/stmmac/dwmac-loongson1.c | 257 ++++++++++++++++++
> >  3 files changed, 269 insertions(+)
> >  create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> >
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> > index 06c6871f8788..a2b9e289aa36 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
> > +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> > @@ -239,6 +239,17 @@ config DWMAC_INTEL_PLAT
> >         the stmmac device driver. This driver is used for the Intel Keem Bay
> >         SoC.
> >
> > +config DWMAC_LOONGSON1
> > +     tristate "Loongson1 GMAC support"
> > +     default MACH_LOONGSON32
> > +     depends on OF && (MACH_LOONGSON32 || COMPILE_TEST)
> > +     help
> > +       Support for ethernet controller on Loongson1 SoC.
> > +
> > +       This selects Loongson1 SoC glue layer support for the stmmac
> > +       device driver. This driver is used for Loongson1-based boards
> > +       like Loongson LS1B/LS1C.
> > +
> >  config DWMAC_TEGRA
> >       tristate "NVIDIA Tegra MGBE support"
> >       depends on ARCH_TEGRA || COMPILE_TEST
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
> > index 5b57aee19267..80e598bd4255 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/Makefile
> > +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
> > @@ -29,6 +29,7 @@ obj-$(CONFIG_DWMAC_SUNXI)   += dwmac-sunxi.o
> >  obj-$(CONFIG_DWMAC_SUN8I)    += dwmac-sun8i.o
> >  obj-$(CONFIG_DWMAC_DWC_QOS_ETH)      += dwmac-dwc-qos-eth.o
> >  obj-$(CONFIG_DWMAC_INTEL_PLAT)       += dwmac-intel-plat.o
> > +obj-$(CONFIG_DWMAC_LOONGSON1)        += dwmac-loongson1.o
> >  obj-$(CONFIG_DWMAC_GENERIC)  += dwmac-generic.o
> >  obj-$(CONFIG_DWMAC_IMX8)     += dwmac-imx.o
> >  obj-$(CONFIG_DWMAC_TEGRA)    += dwmac-tegra.o
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> > new file mode 100644
> > index 000000000000..368d6cd2cb78
> > --- /dev/null
> > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> > @@ -0,0 +1,257 @@
> > +// SPDX-License-Identifier: GPL-2.0-or-later
> > +/*
> > + * Loongson-1 DWMAC glue layer
> > + *
> > + * Copyright (C) 2011-2023 Keguang Zhang <keguang.zhang@gmail.com>
> > + */
> > +
> > +#include <linux/mfd/syscon.h>
> > +#include <linux/module.h>
> > +#include <linux/phy.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regmap.h>
> > +
> > +#include "stmmac.h"
> > +#include "stmmac_platform.h"
> > +
> > +/* Loongson-1 SYSCON Registers */
> > +#define LS1X_SYSCON0         (0x0)
> > +#define LS1X_SYSCON1         (0x4)
> > +
> > +struct ls1x_dwmac_syscon {
> > +     const struct reg_field *reg_fields;
> > +     unsigned int nr_reg_fields;
> > +     int (*syscon_init)(struct plat_stmmacenet_data *plat);
> > +};
> > +
> > +struct ls1x_dwmac {
> > +     struct device *dev;
> > +     struct plat_stmmacenet_data *plat_dat;
> > +     const struct ls1x_dwmac_syscon *syscon;
> > +     struct regmap *regmap;
> > +     struct regmap_field *regmap_fields[];
> > +};
> > +
> > +enum ls1b_dwmac_syscon_regfield {
> > +     GMAC1_USE_UART1,
> > +     GMAC1_USE_UART0,
> > +     GMAC1_SHUT,
> > +     GMAC0_SHUT,
> > +     GMAC1_USE_TXCLK,
> > +     GMAC0_USE_TXCLK,
> > +     GMAC1_USE_PWM23,
> > +     GMAC0_USE_PWM01,
> > +};
> > +
> > +enum ls1c_dwmac_syscon_regfield {
> > +     GMAC_SHUT,
> > +     PHY_INTF_SELI,
> > +};
> > +
> > +const struct reg_field ls1b_dwmac_syscon_regfields[] = {
> > +     [GMAC1_USE_UART1]       = REG_FIELD(LS1X_SYSCON0, 4, 4),
> > +     [GMAC1_USE_UART0]       = REG_FIELD(LS1X_SYSCON0, 3, 3),
> > +     [GMAC1_SHUT]            = REG_FIELD(LS1X_SYSCON1, 13, 13),
> > +     [GMAC0_SHUT]            = REG_FIELD(LS1X_SYSCON1, 12, 12),
> > +     [GMAC1_USE_TXCLK]       = REG_FIELD(LS1X_SYSCON1, 3, 3),
> > +     [GMAC0_USE_TXCLK]       = REG_FIELD(LS1X_SYSCON1, 2, 2),
> > +     [GMAC1_USE_PWM23]       = REG_FIELD(LS1X_SYSCON1, 1, 1),
> > +     [GMAC0_USE_PWM01]       = REG_FIELD(LS1X_SYSCON1, 0, 0)
> > +};
> > +
> > +const struct reg_field ls1c_dwmac_syscon_regfields[] = {
> > +     [GMAC_SHUT]             = REG_FIELD(LS1X_SYSCON0, 6, 6),
> > +     [PHY_INTF_SELI]         = REG_FIELD(LS1X_SYSCON1, 28, 30)
> > +};
>
> Emm, using regmap fields looks so over-complicated in this case seeing
> you only need to set/clear several bits in the syscon. What about
> defining macros with the particular flag as it's already done in the
> "asm/mach-loongson32/regs-mux.h" file and using regmap_update_bits()?
>
To use regmap_update_bits(), I have to store and pass reg_offset and
mask, which is similar to the definition of regmap fields.
In addition, the regmap fields are very clear and leave the trouble to
the internal implementation.

> > +
>
> > +static int ls1b_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
> > +{
>
> As I already told you this part is better to be called from the
> plat_stmmacenet_data.fix_mac_speed() because PHY interface mode can
> differ from one interface open cycle to another as per the phylink
> design.
>
I have considered .fix_mac_speed(), which will be called every time
the link is up, and passes the current speed.
However, the PHY interface mode is determined by the hardware design -
the schematic.
In other words, once the schematic is done, the PHY interface mode is fixed.
Therefore, PHY interface mode should be configured one time at the
initialization.
And the plat_stmmacenet_data.init() is the proper place to do this.

> > +     struct ls1x_dwmac *dwmac = plat->bsp_priv;
> > +     struct regmap_field **regmap_fields = dwmac->regmap_fields;
> > +
>
> > +     if (plat->bus_id) {
>
> Using bus_id doesn't look correct to determine the CSRs responsible
> for the interface mode selection because it's calculated based on the
> DT ethernet-alias which doesn't guarantee to have a particular device
> assigned with the alias. Alias node can be absent after all. What
> could be better in this case is for instance to use the regs physical
> address. Any better idea?
>
The purpose of alias is to bind the a particular device with a
particular alias even some aliases are absent.
Because of_alias_get_id() gets the alias id.
For example, LS1B has two GMAC controllers, gmac0 and gmac1.
I have tried the Ethernet with only one alias as follows.
       aliases {
               ethernet1 = &gmac1;
       };
In this case, plat->bus_id is still 1.
And both gmac0 and gmac1 work.

> > +             regmap_field_write(regmap_fields[GMAC1_USE_UART1], 1);
> > +             regmap_field_write(regmap_fields[GMAC1_USE_UART0], 1);
> > +
> > +             switch (plat->phy_interface) {
> > +             case PHY_INTERFACE_MODE_RGMII:
> > +                     regmap_field_write(regmap_fields[GMAC1_USE_TXCLK], 0);
> > +                     regmap_field_write(regmap_fields[GMAC1_USE_PWM23], 0);
> > +                     break;
> > +             case PHY_INTERFACE_MODE_MII:
> > +                     regmap_field_write(regmap_fields[GMAC1_USE_TXCLK], 1);
> > +                     regmap_field_write(regmap_fields[GMAC1_USE_PWM23], 1);
> > +                     break;
> > +             default:
> > +                     dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
> > +                             plat->phy_interface);
> > +                     return -EOPNOTSUPP;
> > +             }
> > +
> > +             regmap_field_write(regmap_fields[GMAC1_SHUT], 0);
> > +     } else {
> > +             switch (plat->phy_interface) {
> > +             case PHY_INTERFACE_MODE_RGMII:
> > +                     regmap_field_write(regmap_fields[GMAC0_USE_TXCLK], 0);
> > +                     regmap_field_write(regmap_fields[GMAC0_USE_PWM01], 0);
> > +                     break;
> > +             case PHY_INTERFACE_MODE_MII:
> > +                     regmap_field_write(regmap_fields[GMAC0_USE_TXCLK], 1);
> > +                     regmap_field_write(regmap_fields[GMAC0_USE_PWM01], 1);
> > +                     break;
> > +             default:
> > +                     dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
> > +                             plat->phy_interface);
> > +                     return -EOPNOTSUPP;
> > +             }
> > +
> > +             regmap_field_write(regmap_fields[GMAC0_SHUT], 0);
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> > +static int ls1c_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
> > +{
> > +     struct ls1x_dwmac *dwmac = plat->bsp_priv;
> > +     struct regmap_field **regmap_fields = dwmac->regmap_fields;
> > +
> > +     if (plat->phy_interface == PHY_INTERFACE_MODE_RMII) {
> > +             regmap_field_write(regmap_fields[PHY_INTF_SELI], 0x4);
> > +     } else {
> > +             dev_err(dwmac->dev, "Unsupported PHY-mode %u\n",
> > +                     plat->phy_interface);
> > +             return -EOPNOTSUPP;
> > +     }
> > +
> > +     regmap_field_write(regmap_fields[GMAC_SHUT], 0);
> > +
> > +     return 0;
> > +}
> > +
> > +static const struct ls1x_dwmac_syscon ls1b_dwmac_syscon = {
> > +     .reg_fields = ls1b_dwmac_syscon_regfields,
> > +     .nr_reg_fields = ARRAY_SIZE(ls1b_dwmac_syscon_regfields),
> > +     .syscon_init = ls1b_dwmac_syscon_init,
> > +};
> > +
> > +static const struct ls1x_dwmac_syscon ls1c_dwmac_syscon = {
> > +     .reg_fields = ls1c_dwmac_syscon_regfields,
> > +     .nr_reg_fields = ARRAY_SIZE(ls1c_dwmac_syscon_regfields),
> > +     .syscon_init = ls1c_dwmac_syscon_init,
> > +};
> > +
> > +static int ls1x_dwmac_init(struct platform_device *pdev, void *priv)
> > +{
> > +     struct ls1x_dwmac *dwmac = priv;
> > +     int ret;
> > +
>
> > +     ret = devm_regmap_field_bulk_alloc(dwmac->dev, dwmac->regmap,
> > +                                        dwmac->regmap_fields,
> > +                                        dwmac->syscon->reg_fields,
> > +                                        dwmac->syscon->nr_reg_fields);
>
> Please see my first comment about this.
>
> > +     if (ret)
> > +             return ret;
> > +
> > +     if (dwmac->syscon->syscon_init) {
> > +             ret = dwmac->syscon->syscon_init(dwmac->plat_dat);
> > +             if (ret)
> > +                     return ret;
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> > +static const struct of_device_id ls1x_dwmac_syscon_match[] = {
> > +     { .compatible = "loongson,ls1b-syscon", .data = &ls1b_dwmac_syscon },
> > +     { .compatible = "loongson,ls1c-syscon", .data = &ls1c_dwmac_syscon },
> > +     { }
> > +};
> > +
> > +static int ls1x_dwmac_probe(struct platform_device *pdev)
> > +{
> > +     struct plat_stmmacenet_data *plat_dat;
> > +     struct stmmac_resources stmmac_res;
> > +     struct device_node *syscon_np;
> > +     const struct of_device_id *match;
> > +     struct regmap *regmap;
> > +     struct ls1x_dwmac *dwmac;
> > +     const struct ls1x_dwmac_syscon *syscon;
> > +     size_t size;
> > +     int ret;
> > +
> > +     ret = stmmac_get_platform_resources(pdev, &stmmac_res);
> > +     if (ret)
> > +             return ret;
> > +
>
> > +     /* Probe syscon */
> > +     syscon_np = of_parse_phandle(pdev->dev.of_node, "syscon", 0);
>
> it's vendor-specific property so it is supposed to have a
> vendor-specific prefix and possibly ls1-specific name.
>
This has been fixed in v2.
Could you please review v2?
Thanks!

> > +     if (!syscon_np)
> > +             return -ENODEV;
> > +
> > +     match = of_match_node(ls1x_dwmac_syscon_match, syscon_np);
> > +     if (!match) {
> > +             of_node_put(syscon_np);
> > +             return -EINVAL;
> > +     }
> > +     syscon = (const struct ls1x_dwmac_syscon *)match->data;
> > +
> > +     regmap = syscon_node_to_regmap(syscon_np);
> > +     of_node_put(syscon_np);
> > +     if (IS_ERR(regmap)) {
> > +             ret = PTR_ERR(regmap);
> > +             dev_err(&pdev->dev, "Unable to map syscon: %d\n", ret);
> > +             return ret;
> > +     }
>
> or you can use syscon_regmap_lookup_by_phandle(). Using
> of_match_node() doesn't seem necessary since it's unlikely to have
> moee than one system controller available on the LS1b or LS1c chips.
>
I planned to use syscon_regmap_lookup_by_phandle().
Thus the compatible
"loongson,ls1b-dwmac-syscon"/"loongson,ls1c-dwmac-syscon" would become
useless.
I'm not sure about this.

> > +
> > +     size = syscon->nr_reg_fields * sizeof(struct regmap_field *);
> > +     dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac) + size, GFP_KERNEL);
> > +     if (!dwmac)
> > +             return -ENOMEM;
> > +
> > +     plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
> > +     if (IS_ERR(plat_dat)) {
> > +             dev_err(&pdev->dev, "dt configuration failed\n");
> > +             return PTR_ERR(plat_dat);
> > +     }
> > +
> > +     plat_dat->bsp_priv = dwmac;
> > +     plat_dat->init = ls1x_dwmac_init;
> > +     dwmac->dev = &pdev->dev;
> > +     dwmac->plat_dat = plat_dat;
> > +     dwmac->syscon = syscon;
> > +     dwmac->regmap = regmap;
> > +
> > +     ret = stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res);
> > +     if (ret)
> > +             goto err_remove_config_dt;
> > +
> > +     return 0;
> > +
> > +err_remove_config_dt:
>
> > +     if (pdev->dev.of_node)
>
> Is this conditional statement necessary here?
>
You're right.
Will remove this condition in next version.
Thanks!

> -Serge
>
> > +             stmmac_remove_config_dt(pdev, plat_dat);
> > +
> > +     return ret;
> > +}
> > +
> > +static const struct of_device_id ls1x_dwmac_match[] = {
> > +     { .compatible = "loongson,ls1b-dwmac" },
> > +     { .compatible = "loongson,ls1c-dwmac" },
> > +     { }
> > +};
> > +MODULE_DEVICE_TABLE(of, ls1x_dwmac_match);
> > +
> > +static struct platform_driver ls1x_dwmac_driver = {
> > +     .probe = ls1x_dwmac_probe,
> > +     .remove_new = stmmac_pltfr_remove,
> > +     .driver = {
> > +             .name = "loongson1-dwmac",
> > +             .of_match_table = ls1x_dwmac_match,
> > +     },
> > +};
> > +module_platform_driver(ls1x_dwmac_driver);
> > +
> > +MODULE_AUTHOR("Keguang Zhang <keguang.zhang@gmail.com>");
> > +MODULE_DESCRIPTION("Loongson1 DWMAC glue layer");
> > +MODULE_LICENSE("GPL");
> > --
> > 2.39.2
> >



--
Best regards,

Keguang Zhang

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

* Re: [PATCH 3/5] dt-bindings: net: Add Loongson-1 DWMAC glue layer
  2023-08-18 10:42     ` Keguang Zhang
@ 2023-08-18 13:48       ` Serge Semin
  2023-08-21 13:13         ` Keguang Zhang
  0 siblings, 1 reply; 28+ messages in thread
From: Serge Semin @ 2023-08-18 13:48 UTC (permalink / raw)
  To: Keguang Zhang
  Cc: netdev, devicetree, linux-mips, linux-kernel, Lee Jones,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, David S . Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Thomas Bogendoerfer,
	Giuseppe Cavallaro, Alexandre Torgue, Jose Abreu, Serge Semin

On Fri, Aug 18, 2023 at 06:42:42PM +0800, Keguang Zhang wrote:
> On Wed, Aug 16, 2023 at 8:54 PM Serge Semin <fancer.lancer@gmail.com> wrote:
> >
> > Hi Keguang
> >
> > On Sat, Aug 12, 2023 at 11:11:33PM +0800, Keguang Zhang wrote:
> > > Add devicetree binding document for Loongson-1 DWMAC glue layer.
> > >
> > > Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
> > > ---
> > >  .../bindings/net/loongson,ls1x-dwmac.yaml     | 98 +++++++++++++++++++
> > >  .../devicetree/bindings/net/snps,dwmac.yaml   |  2 +
> > >  2 files changed, 100 insertions(+)
> > >  create mode 100644 Documentation/devicetree/bindings/net/loongson,ls1x-dwmac.yaml
> > >
> > > diff --git a/Documentation/devicetree/bindings/net/loongson,ls1x-dwmac.yaml b/Documentation/devicetree/bindings/net/loongson,ls1x-dwmac.yaml
> > > new file mode 100644
> > > index 000000000000..150799460599
> > > --- /dev/null
> > > +++ b/Documentation/devicetree/bindings/net/loongson,ls1x-dwmac.yaml
> > > @@ -0,0 +1,98 @@
> > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > > +%YAML 1.2
> > > +---
> > > +$id: http://devicetree.org/schemas/net/loongson,ls1x-dwmac.yaml#
> > > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > > +
> >
> > > +title: Loongson-1 DWMAC glue layer
> >
> > DT-schemas describe a device. It has nothing to do with the glue
> > driver/layer/whatever.
> >

> OK. But what about the MODULE_DESCRIPTION in dwmac-loongson1.c
> MODULE_DESCRIPTION("Loongson1 DWMAC glue layer");
> Should the two parts be aligned with each other?

No they shouldn't. MODULE_DESCRIPTION() describes the driver module.
"Loongson1 (G)MAC glue layer" is a correct description of the kernel
driver module.

> If not, what's your suggestion then?

Something like "Loongson-1 Ethernet controller" or "Loongson-1 (G)MAC
controller". A name which would refer to the device itself
irrespective to the driver name, driver design, etc.

* Note the already available DW (XG)MAC vendor-specific DT-bindings
* referring to the glue layer/driver in the title property are wrong
* in doing that.

> 
> > Also I suggest to add a brief device description in the
> > "description:" property and add there a brief info regarding the SoCs
> > the controllers can be found on, the DW (G)MAC IP-core version the
> > ethernet controllers are based on and if possible some data about the
> > synthesize parameters: SMA (MDIO-bus), Tx/Rx COE, DMA FIFOs size,
> > perfect and hash MAC-filters size, L3L4 frame filters availability,
> > PHY interfaces (MII, RMII, RGMII, etc), EEE support, IEEE 1588(-2008)
> > Timestamping support, PMT and Wake-up frame support, MAC Management
> > counters (MMC).
> >
> > Note DMA FIFO sizes can be also constrained in the properties
> > "rx-fifo-depth" and "tx-fifo-depth"; perfect and hash MAC-filter sizes -
> > in "snps,perfect-filter-entries" and "snps,multicast-filter-bins".
> >
> OK. The description could be added in next version.
> 
> > > +
> > > +maintainers:
> > > +  - Keguang Zhang <keguang.zhang@gmail.com>
> > > +
> > > +select:
> > > +  properties:
> > > +    compatible:
> > > +      contains:
> > > +        enum:
> > > +          - loongson,ls1b-dwmac
> > > +          - loongson,ls1c-dwmac
> > > +  required:
> > > +    - compatible
> > > +
> > > +properties:
> > > +  compatible:
> > > +    items:
> > > +      - enum:

> > > +          - loongson,ls1b-dwmac
> > > +          - loongson,ls1c-dwmac

BTW referring to the DW IP-core in the compatible string isn't very
much useful especially seeing you have a generic fallback compatible.

The next names would be more descriptive:
loongson,ls1b-gmac - seeing MAC supports 10/100/1000 speed modes
loongson,ls1c-mac - seeing MAC support 10/100 speed modes only


> > > +      - const: snps,dwmac-3.50a
> > > +
> > > +  reg:
> > > +    maxItems: 1
> > > +
> > > +  clocks:
> > > +    maxItems: 1
> > > +
> > > +  clock-names:
> > > +    const: stmmaceth
> > > +
> > > +  interrupts:
> > > +    maxItems: 1
> > > +
> > > +  interrupt-names:
> > > +    const: macirq
> > > +
> >
> > > +  syscon:
> > > +    $ref: /schemas/types.yaml#/definitions/phandle
> > > +    description:
> > > +      Phandle to the syscon containing some extra configurations
> > > +      including PHY interface mode.
> >
> > I believe the property is supposed to have a vendor-specific name like
> > "loongson,ls1-syscon" or similar.
> 

> This has been fixed in v2.

The name "loongson,dwmac-syscon" doesn't look correct because "dwmac-"
prefix refer to some DWMAC system controller meanwhile the phandle
passed to the device is a generic Loongson1 SoC system controller. So
"loongson,ls1-syscon" looks more suitable.

> Could you please review v2?
> Thanks!

I'll have a look at v3 since v2 doesn't have my comments taken into
account. BTW don't rush with resubmitting your series. Give it at
least one week or so to hang out in the reviewers mail boxes as the
Linux kernel patches review process suggests.

> >
> > > +
> > > +required:
> > > +  - compatible
> > > +  - reg
> > > +  - clocks
> > > +  - clock-names
> > > +  - interrupts
> > > +  - interrupt-names
> > > +  - phy-handle
> >
> > > +  - phy-mode
> >
> > You may want to specify the enum-constraints with the value permitted
> > for the particular Loongson (G)MAC controller. Seeing ls1b and ls1c
> > imply different sets of the PHY-modes the constraints are better to be
> > defined in the allOf sub-schemas. Alternatively you can split the
> > DT-schema file into two: one for ls1b-dwmac, another one for
> > ls1c-dwmac. IMO the later option seems better.
> >

> The "phy-mode", as pointed by Krzysztof, is defined in
> ethernet-controller and already required by snps,dwmac.
> So I have dropped it in v2.

My point was in specifying a particular constraints on the "phy-mode"
property. Krzysztof correctly suggested to drop the property from the
"required" list since it's already required by the snps,dwmac.yaml
schema. One doesn't contradict to another.

> For allOf sub-schemas, do you mean something below?
> allOf:
>  - $ref: snps,dwmac.yaml#
> 
>  - if:
>      properties:
>        compatible:
>          contains:
>            const: loongson,ls1b-dwmac
>    then:
>      properties:
>        phy-mode:
>          enum:
>            - mii
>            - rgmii
> 
>  - if:
>      properties:
>        compatible:
>          contains:
>            const: loongson,ls1c-dwmac
>    then:
>      properties:
>        phy-mode:
>          enum:
>            - mii
>            - rmii

Yes. But IMO in order to prevent having such complicated multi-level
schemas you can just split up your bindings into two:
loongson,ls1b-dwmac.yaml
and
loongson,ls1c-dwmac.yaml

Thus you'll be able to have a device-specific generic "title" and
"description" in each of them (especially seeing LS1-C MAC lacks of
1000Mbps mode support which you said you would add to the bindings
description), simpler "compatible" and "phy-mode" property
constraints.

-Serge(y)

> 
> > -Serge(y)
> >
> > > +  - syscon
> > > +
> > > +allOf:
> > > +  - $ref: snps,dwmac.yaml#
> > > +
> > > +unevaluatedProperties: false
> > > +
> > > +examples:
> > > +  - |
> > > +    #include <dt-bindings/clock/loongson,ls1x-clk.h>
> > > +    #include <dt-bindings/interrupt-controller/irq.h>
> > > +
> > > +    gmac0: ethernet@1fe10000 {
> > > +        compatible = "loongson,ls1b-dwmac", "snps,dwmac-3.50a";
> > > +        reg = <0x1fe10000 0x10000>;
> > > +
> > > +        clocks = <&clkc LS1X_CLKID_AHB>;
> > > +        clock-names = "stmmaceth";
> > > +
> > > +        interrupt-parent = <&intc1>;
> > > +        interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
> > > +        interrupt-names = "macirq";
> > > +
> > > +        phy-handle = <&phy0>;
> > > +        phy-mode = "mii";
> > > +
> > > +        snps,pbl = <1>;
> > > +        syscon = <&syscon>;
> > > +
> > > +        mdio {
> > > +            #address-cells = <1>;
> > > +            #size-cells = <0>;
> > > +            compatible = "snps,dwmac-mdio";
> > > +
> > > +            phy0: ethernet-phy@0 {
> > > +                reg = <0x0>;
> > > +            };
> > > +        };
> > > +    };
> > > diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
> > > index ddf9522a5dc2..e1a956cf171e 100644
> > > --- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml
> > > +++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
> > > @@ -66,6 +66,8 @@ properties:
> > >          - ingenic,x2000-mac
> > >          - loongson,ls2k-dwmac
> > >          - loongson,ls7a-dwmac
> > > +        - loongson,ls1b-dwmac
> > > +        - loongson,ls1c-dwmac
> > >          - qcom,qcs404-ethqos
> > >          - qcom,sa8775p-ethqos
> > >          - qcom,sc8280xp-ethqos
> > > --
> > > 2.39.2
> > >
> 
> 
> 
> --
> Best regards,
> 
> Keguang Zhang

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

* Re: [PATCH 4/5] net: stmmac: Add glue layer for Loongson-1 SoC
  2023-08-18 12:37     ` Keguang Zhang
@ 2023-08-18 16:19       ` Serge Semin
  2023-08-21 13:24         ` Keguang Zhang
  0 siblings, 1 reply; 28+ messages in thread
From: Serge Semin @ 2023-08-18 16:19 UTC (permalink / raw)
  To: Keguang Zhang
  Cc: netdev, devicetree, linux-mips, linux-kernel, Lee Jones,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, David S . Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Thomas Bogendoerfer,
	Giuseppe Cavallaro, Alexandre Torgue, Jose Abreu, Serge Semin

On Fri, Aug 18, 2023 at 08:37:27PM +0800, Keguang Zhang wrote:
> On Wed, Aug 16, 2023 at 9:30 PM Serge Semin <fancer.lancer@gmail.com> wrote:
> >
> > On Sat, Aug 12, 2023 at 11:11:34PM +0800, Keguang Zhang wrote:
> > > This glue driver is created based on the arch-code
> > > implemented earlier with the platform-specific settings.
> > >
> > > Use syscon for SYSCON register access.
> > >
> > > Partialy based on the previous work by Serge Semin.
> > >
> > > Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
> > > ---
> > >  drivers/net/ethernet/stmicro/stmmac/Kconfig   |  11 +
> > >  drivers/net/ethernet/stmicro/stmmac/Makefile  |   1 +
> > >  .../ethernet/stmicro/stmmac/dwmac-loongson1.c | 257 ++++++++++++++++++
> > >  3 files changed, 269 insertions(+)
> > >  create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> > >
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> > > index 06c6871f8788..a2b9e289aa36 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> > > @@ -239,6 +239,17 @@ config DWMAC_INTEL_PLAT
> > >         the stmmac device driver. This driver is used for the Intel Keem Bay
> > >         SoC.
> > >
> > > +config DWMAC_LOONGSON1
> > > +     tristate "Loongson1 GMAC support"
> > > +     default MACH_LOONGSON32
> > > +     depends on OF && (MACH_LOONGSON32 || COMPILE_TEST)
> > > +     help
> > > +       Support for ethernet controller on Loongson1 SoC.
> > > +
> > > +       This selects Loongson1 SoC glue layer support for the stmmac
> > > +       device driver. This driver is used for Loongson1-based boards
> > > +       like Loongson LS1B/LS1C.
> > > +
> > >  config DWMAC_TEGRA
> > >       tristate "NVIDIA Tegra MGBE support"
> > >       depends on ARCH_TEGRA || COMPILE_TEST
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
> > > index 5b57aee19267..80e598bd4255 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/Makefile
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
> > > @@ -29,6 +29,7 @@ obj-$(CONFIG_DWMAC_SUNXI)   += dwmac-sunxi.o
> > >  obj-$(CONFIG_DWMAC_SUN8I)    += dwmac-sun8i.o
> > >  obj-$(CONFIG_DWMAC_DWC_QOS_ETH)      += dwmac-dwc-qos-eth.o
> > >  obj-$(CONFIG_DWMAC_INTEL_PLAT)       += dwmac-intel-plat.o
> > > +obj-$(CONFIG_DWMAC_LOONGSON1)        += dwmac-loongson1.o
> > >  obj-$(CONFIG_DWMAC_GENERIC)  += dwmac-generic.o
> > >  obj-$(CONFIG_DWMAC_IMX8)     += dwmac-imx.o
> > >  obj-$(CONFIG_DWMAC_TEGRA)    += dwmac-tegra.o
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> > > new file mode 100644
> > > index 000000000000..368d6cd2cb78
> > > --- /dev/null
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> > > @@ -0,0 +1,257 @@
> > > +// SPDX-License-Identifier: GPL-2.0-or-later
> > > +/*
> > > + * Loongson-1 DWMAC glue layer
> > > + *
> > > + * Copyright (C) 2011-2023 Keguang Zhang <keguang.zhang@gmail.com>
> > > + */
> > > +
> > > +#include <linux/mfd/syscon.h>
> > > +#include <linux/module.h>
> > > +#include <linux/phy.h>
> > > +#include <linux/platform_device.h>
> > > +#include <linux/regmap.h>
> > > +
> > > +#include "stmmac.h"
> > > +#include "stmmac_platform.h"
> > > +
> > > +/* Loongson-1 SYSCON Registers */
> > > +#define LS1X_SYSCON0         (0x0)
> > > +#define LS1X_SYSCON1         (0x4)
> > > +
> > > +struct ls1x_dwmac_syscon {
> > > +     const struct reg_field *reg_fields;
> > > +     unsigned int nr_reg_fields;
> > > +     int (*syscon_init)(struct plat_stmmacenet_data *plat);
> > > +};
> > > +
> > > +struct ls1x_dwmac {
> > > +     struct device *dev;
> > > +     struct plat_stmmacenet_data *plat_dat;
> > > +     const struct ls1x_dwmac_syscon *syscon;
> > > +     struct regmap *regmap;
> > > +     struct regmap_field *regmap_fields[];
> > > +};
> > > +
> > > +enum ls1b_dwmac_syscon_regfield {
> > > +     GMAC1_USE_UART1,
> > > +     GMAC1_USE_UART0,
> > > +     GMAC1_SHUT,
> > > +     GMAC0_SHUT,
> > > +     GMAC1_USE_TXCLK,
> > > +     GMAC0_USE_TXCLK,
> > > +     GMAC1_USE_PWM23,
> > > +     GMAC0_USE_PWM01,
> > > +};
> > > +
> > > +enum ls1c_dwmac_syscon_regfield {
> > > +     GMAC_SHUT,
> > > +     PHY_INTF_SELI,
> > > +};
> > > +
> > > +const struct reg_field ls1b_dwmac_syscon_regfields[] = {
> > > +     [GMAC1_USE_UART1]       = REG_FIELD(LS1X_SYSCON0, 4, 4),
> > > +     [GMAC1_USE_UART0]       = REG_FIELD(LS1X_SYSCON0, 3, 3),
> > > +     [GMAC1_SHUT]            = REG_FIELD(LS1X_SYSCON1, 13, 13),
> > > +     [GMAC0_SHUT]            = REG_FIELD(LS1X_SYSCON1, 12, 12),
> > > +     [GMAC1_USE_TXCLK]       = REG_FIELD(LS1X_SYSCON1, 3, 3),
> > > +     [GMAC0_USE_TXCLK]       = REG_FIELD(LS1X_SYSCON1, 2, 2),
> > > +     [GMAC1_USE_PWM23]       = REG_FIELD(LS1X_SYSCON1, 1, 1),
> > > +     [GMAC0_USE_PWM01]       = REG_FIELD(LS1X_SYSCON1, 0, 0)
> > > +};
> > > +
> > > +const struct reg_field ls1c_dwmac_syscon_regfields[] = {
> > > +     [GMAC_SHUT]             = REG_FIELD(LS1X_SYSCON0, 6, 6),
> > > +     [PHY_INTF_SELI]         = REG_FIELD(LS1X_SYSCON1, 28, 30)
> > > +};
> >
> > Emm, using regmap fields looks so over-complicated in this case seeing
> > you only need to set/clear several bits in the syscon. What about
> > defining macros with the particular flag as it's already done in the
> > "asm/mach-loongson32/regs-mux.h" file and using regmap_update_bits()?
> >

> To use regmap_update_bits(), I have to store and pass reg_offset and
> mask, which is similar to the definition of regmap fields.

Em, not really. And what offset are you talking about? Anyway you
don't need one. Moreover you'll be able to reduce the number of IOs:

+#define GMAC1_USE_UART1                 BIT(4)
+#define GMAC1_USE_UART0                 BIT(3)
...
+#define GMAC1_SHUT                      BIT(13)
...
+#define GMAC1_USE_TXCLK                 BIT(3)
+#define GMAC1_USE_PWM23                 BIT(1)

+static int ls1b_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
+{
+	struct ls1x_dwmac *dwmac = plat->bsp_priv;
+	struct regmap *syscon = dwmac->regmap;
+
+	if (plat->bus_id) {
+		regmap_update_bits(syscon, LS1X_SYSCON0,
+				   GMAC1_USE_UART1 | GMAC1_USE_UART0,
+				   GMAC1_USE_UART1 | GMAC1_USE_UART0);
+
+		switch (plat->phy_interface) {
+		case PHY_INTERFACE_MODE_RGMII:
+			regmap_update_bits(syscon, LS1X_SYSCON1,
+					   GMAC1_USE_TXCLK | GMAC1_USE_TXCLK, 0);
+			break;
+		case PHY_INTERFACE_MODE_MII:
+			regmap_update_bits(syscon, LS1X_SYSCON1,
+					   GMAC1_USE_TXCLK | GMAC1_USE_TXCLK
+					   GMAC1_USE_TXCLK | GMAC1_USE_TXCLK);
+			break;
+		default:
+			dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
+				plat->phy_interface);
+			return -EOPNOTSUPP;
+		}
+
+		regmap_field_write(syscon, LS1X_SYSCON1, GMAC1_SHUT, 0);
+	} //...
+
+	return 0;
+}

This doesn't look in anyway less readable then your implementation
but in fact simpler.

> In addition, the regmap fields are very clear and leave the trouble to
> the internal implementation.

In this case it brings much more troubles and no clarity. You need to create
an additional mainly redundant abstraction, waste memory for it,
define additional const arrays. Using it won't improve the code
readability seeing you need to set/clear a few flags only. So all of
the troubles for nothing. See the code above. It's simple and clear.
Just several regmap_update_bits().

BTW why have you chosen to define syscon instead of creating a pinctrl
driver? What if Loongson1 is embedded into a platform with, for
instance, UART0 and UART1 utilized instead of the GMAC1?

> 
> > > +
> >
> > > +static int ls1b_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
> > > +{
> >
> > As I already told you this part is better to be called from the
> > plat_stmmacenet_data.fix_mac_speed() because PHY interface mode can
> > differ from one interface open cycle to another as per the phylink
> > design.
> >
> I have considered .fix_mac_speed(), which will be called every time
> the link is up, and passes the current speed.
> However, the PHY interface mode is determined by the hardware design -
> the schematic.
> In other words, once the schematic is done, the PHY interface mode is fixed.
> Therefore, PHY interface mode should be configured one time at the
> initialization.
> And the plat_stmmacenet_data.init() is the proper place to do this.

Ok. If no actual clock change is needed then indeed init() will be the
proper place.

> 
> > > +     struct ls1x_dwmac *dwmac = plat->bsp_priv;
> > > +     struct regmap_field **regmap_fields = dwmac->regmap_fields;
> > > +
> >
> > > +     if (plat->bus_id) {
> >
> > Using bus_id doesn't look correct to determine the CSRs responsible
> > for the interface mode selection because it's calculated based on the
> > DT ethernet-alias which doesn't guarantee to have a particular device
> > assigned with the alias. Alias node can be absent after all. What
> > could be better in this case is for instance to use the regs physical
> > address. Any better idea?
> >

> The purpose of alias is to bind the a particular device with a
> particular alias even some aliases are absent.
> Because of_alias_get_id() gets the alias id.
> For example, LS1B has two GMAC controllers, gmac0 and gmac1.
> I have tried the Ethernet with only one alias as follows.
>        aliases {
>                ethernet1 = &gmac1;
>        };
> In this case, plat->bus_id is still 1.
> And both gmac0 and gmac1 work.

If no alias specified? If both aliases a non zero? If the IDs are
confused? If any of these is true you are in trouble. Your code
shouldn't rely on the aliases in this case. You need to come up with a
way to certainly distinguish one MAC from another. A physical base
address is one possible option.

Note the /alias node is an informational node. It doesn't describe
devices. Just recent Krzysztof comment in a similar situation:
https://lore.kernel.org/netdev/20230814112539.70453-1-sriranjani.p@samsung.com/T/#m3972e40bd2fa323a3bdb2fbf07bde47ba6752439

Aliases are normally used by OS to for instance fix the device
enumeration (see SPI, I2C, I3C, MTD, MMC, RTC, TTY/Serial, Watchdog,
MDIO-GPIO, etc) - pre-define the device ID from the kernel or OS point
of view. In your case the IDs can't be changed. GMAC0 must be assigned
with ID0 and GMAC1 must be assigned with non-zero. Doing otherwise
will be break the interfaces functionality which isn't acceptable.

> 
> > > +             regmap_field_write(regmap_fields[GMAC1_USE_UART1], 1);
> > > +             regmap_field_write(regmap_fields[GMAC1_USE_UART0], 1);
> > > +
> > > +             switch (plat->phy_interface) {
> > > +             case PHY_INTERFACE_MODE_RGMII:
> > > +                     regmap_field_write(regmap_fields[GMAC1_USE_TXCLK], 0);
> > > +                     regmap_field_write(regmap_fields[GMAC1_USE_PWM23], 0);
> > > +                     break;
> > > +             case PHY_INTERFACE_MODE_MII:
> > > +                     regmap_field_write(regmap_fields[GMAC1_USE_TXCLK], 1);
> > > +                     regmap_field_write(regmap_fields[GMAC1_USE_PWM23], 1);
> > > +                     break;
> > > +             default:
> > > +                     dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
> > > +                             plat->phy_interface);
> > > +                     return -EOPNOTSUPP;
> > > +             }
> > > +
> > > +             regmap_field_write(regmap_fields[GMAC1_SHUT], 0);
> > > +     } else {
> > > +             switch (plat->phy_interface) {
> > > +             case PHY_INTERFACE_MODE_RGMII:
> > > +                     regmap_field_write(regmap_fields[GMAC0_USE_TXCLK], 0);
> > > +                     regmap_field_write(regmap_fields[GMAC0_USE_PWM01], 0);
> > > +                     break;
> > > +             case PHY_INTERFACE_MODE_MII:
> > > +                     regmap_field_write(regmap_fields[GMAC0_USE_TXCLK], 1);
> > > +                     regmap_field_write(regmap_fields[GMAC0_USE_PWM01], 1);
> > > +                     break;
> > > +             default:
> > > +                     dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
> > > +                             plat->phy_interface);
> > > +                     return -EOPNOTSUPP;
> > > +             }
> > > +
> > > +             regmap_field_write(regmap_fields[GMAC0_SHUT], 0);
> > > +     }
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static int ls1c_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
> > > +{
> > > +     struct ls1x_dwmac *dwmac = plat->bsp_priv;
> > > +     struct regmap_field **regmap_fields = dwmac->regmap_fields;
> > > +
> > > +     if (plat->phy_interface == PHY_INTERFACE_MODE_RMII) {
> > > +             regmap_field_write(regmap_fields[PHY_INTF_SELI], 0x4);
> > > +     } else {
> > > +             dev_err(dwmac->dev, "Unsupported PHY-mode %u\n",
> > > +                     plat->phy_interface);
> > > +             return -EOPNOTSUPP;
> > > +     }
> > > +
> > > +     regmap_field_write(regmap_fields[GMAC_SHUT], 0);
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static const struct ls1x_dwmac_syscon ls1b_dwmac_syscon = {
> > > +     .reg_fields = ls1b_dwmac_syscon_regfields,
> > > +     .nr_reg_fields = ARRAY_SIZE(ls1b_dwmac_syscon_regfields),
> > > +     .syscon_init = ls1b_dwmac_syscon_init,
> > > +};
> > > +
> > > +static const struct ls1x_dwmac_syscon ls1c_dwmac_syscon = {
> > > +     .reg_fields = ls1c_dwmac_syscon_regfields,
> > > +     .nr_reg_fields = ARRAY_SIZE(ls1c_dwmac_syscon_regfields),
> > > +     .syscon_init = ls1c_dwmac_syscon_init,
> > > +};
> > > +
> > > +static int ls1x_dwmac_init(struct platform_device *pdev, void *priv)
> > > +{
> > > +     struct ls1x_dwmac *dwmac = priv;
> > > +     int ret;
> > > +
> >
> > > +     ret = devm_regmap_field_bulk_alloc(dwmac->dev, dwmac->regmap,
> > > +                                        dwmac->regmap_fields,
> > > +                                        dwmac->syscon->reg_fields,
> > > +                                        dwmac->syscon->nr_reg_fields);
> >
> > Please see my first comment about this.
> >
> > > +     if (ret)
> > > +             return ret;
> > > +
> > > +     if (dwmac->syscon->syscon_init) {
> > > +             ret = dwmac->syscon->syscon_init(dwmac->plat_dat);
> > > +             if (ret)
> > > +                     return ret;
> > > +     }
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static const struct of_device_id ls1x_dwmac_syscon_match[] = {
> > > +     { .compatible = "loongson,ls1b-syscon", .data = &ls1b_dwmac_syscon },
> > > +     { .compatible = "loongson,ls1c-syscon", .data = &ls1c_dwmac_syscon },
> > > +     { }
> > > +};
> > > +
> > > +static int ls1x_dwmac_probe(struct platform_device *pdev)
> > > +{
> > > +     struct plat_stmmacenet_data *plat_dat;
> > > +     struct stmmac_resources stmmac_res;
> > > +     struct device_node *syscon_np;
> > > +     const struct of_device_id *match;
> > > +     struct regmap *regmap;
> > > +     struct ls1x_dwmac *dwmac;
> > > +     const struct ls1x_dwmac_syscon *syscon;
> > > +     size_t size;
> > > +     int ret;
> > > +
> > > +     ret = stmmac_get_platform_resources(pdev, &stmmac_res);
> > > +     if (ret)
> > > +             return ret;
> > > +
> >
> > > +     /* Probe syscon */
> > > +     syscon_np = of_parse_phandle(pdev->dev.of_node, "syscon", 0);
> >
> > it's vendor-specific property so it is supposed to have a
> > vendor-specific prefix and possibly ls1-specific name.
> >
> This has been fixed in v2.
> Could you please review v2?
> Thanks!
> 
> > > +     if (!syscon_np)
> > > +             return -ENODEV;
> > > +
> > > +     match = of_match_node(ls1x_dwmac_syscon_match, syscon_np);
> > > +     if (!match) {
> > > +             of_node_put(syscon_np);
> > > +             return -EINVAL;
> > > +     }
> > > +     syscon = (const struct ls1x_dwmac_syscon *)match->data;
> > > +
> > > +     regmap = syscon_node_to_regmap(syscon_np);
> > > +     of_node_put(syscon_np);
> > > +     if (IS_ERR(regmap)) {
> > > +             ret = PTR_ERR(regmap);
> > > +             dev_err(&pdev->dev, "Unable to map syscon: %d\n", ret);
> > > +             return ret;
> > > +     }
> >
> > or you can use syscon_regmap_lookup_by_phandle(). Using
> > of_match_node() doesn't seem necessary since it's unlikely to have
> > moee than one system controller available on the LS1b or LS1c chips.
> >

> I planned to use syscon_regmap_lookup_by_phandle().
> Thus the compatible
> "loongson,ls1b-dwmac-syscon"/"loongson,ls1c-dwmac-syscon" would become
> useless.
> I'm not sure about this.

The compatible strings should be left despite of the
syscon_regmap_lookup_by_phandle() usage. But again "dwmac" suffix is
redundant. Based on the CSRs definition in regs-mux.h, selecting
(G)MAC pins mode is only a small part of the Loongson1 SoC system
controllers functionality.
"loongson,ls1b-syscon"/"loongson,ls1c-syscon" looks more appropriate.

-Serge(y)

> 
> > > +
> > > +     size = syscon->nr_reg_fields * sizeof(struct regmap_field *);
> > > +     dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac) + size, GFP_KERNEL);
> > > +     if (!dwmac)
> > > +             return -ENOMEM;
> > > +
> > > +     plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
> > > +     if (IS_ERR(plat_dat)) {
> > > +             dev_err(&pdev->dev, "dt configuration failed\n");
> > > +             return PTR_ERR(plat_dat);
> > > +     }
> > > +
> > > +     plat_dat->bsp_priv = dwmac;
> > > +     plat_dat->init = ls1x_dwmac_init;
> > > +     dwmac->dev = &pdev->dev;
> > > +     dwmac->plat_dat = plat_dat;
> > > +     dwmac->syscon = syscon;
> > > +     dwmac->regmap = regmap;
> > > +
> > > +     ret = stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res);
> > > +     if (ret)
> > > +             goto err_remove_config_dt;
> > > +
> > > +     return 0;
> > > +
> > > +err_remove_config_dt:
> >
> > > +     if (pdev->dev.of_node)
> >
> > Is this conditional statement necessary here?
> >
> You're right.
> Will remove this condition in next version.
> Thanks!
> 
> > -Serge
> >
> > > +             stmmac_remove_config_dt(pdev, plat_dat);
> > > +
> > > +     return ret;
> > > +}
> > > +
> > > +static const struct of_device_id ls1x_dwmac_match[] = {
> > > +     { .compatible = "loongson,ls1b-dwmac" },
> > > +     { .compatible = "loongson,ls1c-dwmac" },
> > > +     { }
> > > +};
> > > +MODULE_DEVICE_TABLE(of, ls1x_dwmac_match);
> > > +
> > > +static struct platform_driver ls1x_dwmac_driver = {
> > > +     .probe = ls1x_dwmac_probe,
> > > +     .remove_new = stmmac_pltfr_remove,
> > > +     .driver = {
> > > +             .name = "loongson1-dwmac",
> > > +             .of_match_table = ls1x_dwmac_match,
> > > +     },
> > > +};
> > > +module_platform_driver(ls1x_dwmac_driver);
> > > +
> > > +MODULE_AUTHOR("Keguang Zhang <keguang.zhang@gmail.com>");
> > > +MODULE_DESCRIPTION("Loongson1 DWMAC glue layer");
> > > +MODULE_LICENSE("GPL");
> > > --
> > > 2.39.2
> > >
> 
> 
> 
> --
> Best regards,
> 
> Keguang Zhang

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

* Re: [PATCH 3/5] dt-bindings: net: Add Loongson-1 DWMAC glue layer
  2023-08-18 13:48       ` Serge Semin
@ 2023-08-21 13:13         ` Keguang Zhang
  0 siblings, 0 replies; 28+ messages in thread
From: Keguang Zhang @ 2023-08-21 13:13 UTC (permalink / raw)
  To: Serge Semin
  Cc: netdev, devicetree, linux-mips, linux-kernel, Lee Jones,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, David S . Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Thomas Bogendoerfer,
	Giuseppe Cavallaro, Alexandre Torgue, Jose Abreu, Serge Semin

On Fri, Aug 18, 2023 at 9:48 PM Serge Semin <fancer.lancer@gmail.com> wrote:
>
> On Fri, Aug 18, 2023 at 06:42:42PM +0800, Keguang Zhang wrote:
> > On Wed, Aug 16, 2023 at 8:54 PM Serge Semin <fancer.lancer@gmail.com> wrote:
> > >
> > > Hi Keguang
> > >
> > > On Sat, Aug 12, 2023 at 11:11:33PM +0800, Keguang Zhang wrote:
> > > > Add devicetree binding document for Loongson-1 DWMAC glue layer.
> > > >
> > > > Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
> > > > ---
> > > >  .../bindings/net/loongson,ls1x-dwmac.yaml     | 98 +++++++++++++++++++
> > > >  .../devicetree/bindings/net/snps,dwmac.yaml   |  2 +
> > > >  2 files changed, 100 insertions(+)
> > > >  create mode 100644 Documentation/devicetree/bindings/net/loongson,ls1x-dwmac.yaml
> > > >
> > > > diff --git a/Documentation/devicetree/bindings/net/loongson,ls1x-dwmac.yaml b/Documentation/devicetree/bindings/net/loongson,ls1x-dwmac.yaml
> > > > new file mode 100644
> > > > index 000000000000..150799460599
> > > > --- /dev/null
> > > > +++ b/Documentation/devicetree/bindings/net/loongson,ls1x-dwmac.yaml
> > > > @@ -0,0 +1,98 @@
> > > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > > > +%YAML 1.2
> > > > +---
> > > > +$id: http://devicetree.org/schemas/net/loongson,ls1x-dwmac.yaml#
> > > > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > > > +
> > >
> > > > +title: Loongson-1 DWMAC glue layer
> > >
> > > DT-schemas describe a device. It has nothing to do with the glue
> > > driver/layer/whatever.
> > >
>
> > OK. But what about the MODULE_DESCRIPTION in dwmac-loongson1.c
> > MODULE_DESCRIPTION("Loongson1 DWMAC glue layer");
> > Should the two parts be aligned with each other?
>
> No they shouldn't. MODULE_DESCRIPTION() describes the driver module.
> "Loongson1 (G)MAC glue layer" is a correct description of the kernel
> driver module.
>
> > If not, what's your suggestion then?
>
> Something like "Loongson-1 Ethernet controller" or "Loongson-1 (G)MAC
> controller". A name which would refer to the device itself
> irrespective to the driver name, driver design, etc.
>
> * Note the already available DW (XG)MAC vendor-specific DT-bindings
> * referring to the glue layer/driver in the title property are wrong
> * in doing that.
>
> >
> > > Also I suggest to add a brief device description in the
> > > "description:" property and add there a brief info regarding the SoCs
> > > the controllers can be found on, the DW (G)MAC IP-core version the
> > > ethernet controllers are based on and if possible some data about the
> > > synthesize parameters: SMA (MDIO-bus), Tx/Rx COE, DMA FIFOs size,
> > > perfect and hash MAC-filters size, L3L4 frame filters availability,
> > > PHY interfaces (MII, RMII, RGMII, etc), EEE support, IEEE 1588(-2008)
> > > Timestamping support, PMT and Wake-up frame support, MAC Management
> > > counters (MMC).
> > >
> > > Note DMA FIFO sizes can be also constrained in the properties
> > > "rx-fifo-depth" and "tx-fifo-depth"; perfect and hash MAC-filter sizes -
> > > in "snps,perfect-filter-entries" and "snps,multicast-filter-bins".
> > >
> > OK. The description could be added in next version.
> >
> > > > +
> > > > +maintainers:
> > > > +  - Keguang Zhang <keguang.zhang@gmail.com>
> > > > +
> > > > +select:
> > > > +  properties:
> > > > +    compatible:
> > > > +      contains:
> > > > +        enum:
> > > > +          - loongson,ls1b-dwmac
> > > > +          - loongson,ls1c-dwmac
> > > > +  required:
> > > > +    - compatible
> > > > +
> > > > +properties:
> > > > +  compatible:
> > > > +    items:
> > > > +      - enum:
>
> > > > +          - loongson,ls1b-dwmac
> > > > +          - loongson,ls1c-dwmac
>
> BTW referring to the DW IP-core in the compatible string isn't very
> much useful especially seeing you have a generic fallback compatible.
>
> The next names would be more descriptive:
> loongson,ls1b-gmac - seeing MAC supports 10/100/1000 speed modes
> loongson,ls1c-mac - seeing MAC support 10/100 speed modes only
>
>
> > > > +      - const: snps,dwmac-3.50a
> > > > +
> > > > +  reg:
> > > > +    maxItems: 1
> > > > +
> > > > +  clocks:
> > > > +    maxItems: 1
> > > > +
> > > > +  clock-names:
> > > > +    const: stmmaceth
> > > > +
> > > > +  interrupts:
> > > > +    maxItems: 1
> > > > +
> > > > +  interrupt-names:
> > > > +    const: macirq
> > > > +
> > >
> > > > +  syscon:
> > > > +    $ref: /schemas/types.yaml#/definitions/phandle
> > > > +    description:
> > > > +      Phandle to the syscon containing some extra configurations
> > > > +      including PHY interface mode.
> > >
> > > I believe the property is supposed to have a vendor-specific name like
> > > "loongson,ls1-syscon" or similar.
> >
>
> > This has been fixed in v2.
>
> The name "loongson,dwmac-syscon" doesn't look correct because "dwmac-"
> prefix refer to some DWMAC system controller meanwhile the phandle
> passed to the device is a generic Loongson1 SoC system controller. So
> "loongson,ls1-syscon" looks more suitable.
>
Will do.

> > Could you please review v2?
> > Thanks!
>
> I'll have a look at v3 since v2 doesn't have my comments taken into
> account. BTW don't rush with resubmitting your series. Give it at
> least one week or so to hang out in the reviewers mail boxes as the
> Linux kernel patches review process suggests.
>
> > >
> > > > +
> > > > +required:
> > > > +  - compatible
> > > > +  - reg
> > > > +  - clocks
> > > > +  - clock-names
> > > > +  - interrupts
> > > > +  - interrupt-names
> > > > +  - phy-handle
> > >
> > > > +  - phy-mode
> > >
> > > You may want to specify the enum-constraints with the value permitted
> > > for the particular Loongson (G)MAC controller. Seeing ls1b and ls1c
> > > imply different sets of the PHY-modes the constraints are better to be
> > > defined in the allOf sub-schemas. Alternatively you can split the
> > > DT-schema file into two: one for ls1b-dwmac, another one for
> > > ls1c-dwmac. IMO the later option seems better.
> > >
>
> > The "phy-mode", as pointed by Krzysztof, is defined in
> > ethernet-controller and already required by snps,dwmac.
> > So I have dropped it in v2.
>
> My point was in specifying a particular constraints on the "phy-mode"
> property. Krzysztof correctly suggested to drop the property from the
> "required" list since it's already required by the snps,dwmac.yaml
> schema. One doesn't contradict to another.
>
> > For allOf sub-schemas, do you mean something below?
> > allOf:
> >  - $ref: snps,dwmac.yaml#
> >
> >  - if:
> >      properties:
> >        compatible:
> >          contains:
> >            const: loongson,ls1b-dwmac
> >    then:
> >      properties:
> >        phy-mode:
> >          enum:
> >            - mii
> >            - rgmii
> >
> >  - if:
> >      properties:
> >        compatible:
> >          contains:
> >            const: loongson,ls1c-dwmac
> >    then:
> >      properties:
> >        phy-mode:
> >          enum:
> >            - mii
> >            - rmii
>
> Yes. But IMO in order to prevent having such complicated multi-level
> schemas you can just split up your bindings into two:
> loongson,ls1b-dwmac.yaml
> and
> loongson,ls1c-dwmac.yaml
>
> Thus you'll be able to have a device-specific generic "title" and
> "description" in each of them (especially seeing LS1-C MAC lacks of
> 1000Mbps mode support which you said you would add to the bindings
> description), simpler "compatible" and "phy-mode" property
> constraints.
>
OK. I will split this file into loongson,ls1b-gmac.yaml and
loongson,ls1c-mac.yaml.
Thanks for your review!



> -Serge(y)
>
> >
> > > -Serge(y)
> > >
> > > > +  - syscon
> > > > +
> > > > +allOf:
> > > > +  - $ref: snps,dwmac.yaml#
> > > > +
> > > > +unevaluatedProperties: false
> > > > +
> > > > +examples:
> > > > +  - |
> > > > +    #include <dt-bindings/clock/loongson,ls1x-clk.h>
> > > > +    #include <dt-bindings/interrupt-controller/irq.h>
> > > > +
> > > > +    gmac0: ethernet@1fe10000 {
> > > > +        compatible = "loongson,ls1b-dwmac", "snps,dwmac-3.50a";
> > > > +        reg = <0x1fe10000 0x10000>;
> > > > +
> > > > +        clocks = <&clkc LS1X_CLKID_AHB>;
> > > > +        clock-names = "stmmaceth";
> > > > +
> > > > +        interrupt-parent = <&intc1>;
> > > > +        interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
> > > > +        interrupt-names = "macirq";
> > > > +
> > > > +        phy-handle = <&phy0>;
> > > > +        phy-mode = "mii";
> > > > +
> > > > +        snps,pbl = <1>;
> > > > +        syscon = <&syscon>;
> > > > +
> > > > +        mdio {
> > > > +            #address-cells = <1>;
> > > > +            #size-cells = <0>;
> > > > +            compatible = "snps,dwmac-mdio";
> > > > +
> > > > +            phy0: ethernet-phy@0 {
> > > > +                reg = <0x0>;
> > > > +            };
> > > > +        };
> > > > +    };
> > > > diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
> > > > index ddf9522a5dc2..e1a956cf171e 100644
> > > > --- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml
> > > > +++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
> > > > @@ -66,6 +66,8 @@ properties:
> > > >          - ingenic,x2000-mac
> > > >          - loongson,ls2k-dwmac
> > > >          - loongson,ls7a-dwmac
> > > > +        - loongson,ls1b-dwmac
> > > > +        - loongson,ls1c-dwmac
> > > >          - qcom,qcs404-ethqos
> > > >          - qcom,sa8775p-ethqos
> > > >          - qcom,sc8280xp-ethqos
> > > > --
> > > > 2.39.2
> > > >
> >
> >
> >
> > --
> > Best regards,
> >
> > Keguang Zhang



--
Best regards,

Keguang Zhang

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

* Re: [PATCH 4/5] net: stmmac: Add glue layer for Loongson-1 SoC
  2023-08-18 16:19       ` Serge Semin
@ 2023-08-21 13:24         ` Keguang Zhang
  2023-08-21 14:16           ` Serge Semin
  0 siblings, 1 reply; 28+ messages in thread
From: Keguang Zhang @ 2023-08-21 13:24 UTC (permalink / raw)
  To: Serge Semin
  Cc: netdev, devicetree, linux-mips, linux-kernel, Lee Jones,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, David S . Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Thomas Bogendoerfer,
	Giuseppe Cavallaro, Alexandre Torgue, Jose Abreu, Serge Semin

On Sat, Aug 19, 2023 at 12:19 AM Serge Semin <fancer.lancer@gmail.com> wrote:
>
> On Fri, Aug 18, 2023 at 08:37:27PM +0800, Keguang Zhang wrote:
> > On Wed, Aug 16, 2023 at 9:30 PM Serge Semin <fancer.lancer@gmail.com> wrote:
> > >
> > > On Sat, Aug 12, 2023 at 11:11:34PM +0800, Keguang Zhang wrote:
> > > > This glue driver is created based on the arch-code
> > > > implemented earlier with the platform-specific settings.
> > > >
> > > > Use syscon for SYSCON register access.
> > > >
> > > > Partialy based on the previous work by Serge Semin.
> > > >
> > > > Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
> > > > ---
> > > >  drivers/net/ethernet/stmicro/stmmac/Kconfig   |  11 +
> > > >  drivers/net/ethernet/stmicro/stmmac/Makefile  |   1 +
> > > >  .../ethernet/stmicro/stmmac/dwmac-loongson1.c | 257 ++++++++++++++++++
> > > >  3 files changed, 269 insertions(+)
> > > >  create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> > > >
> > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> > > > index 06c6871f8788..a2b9e289aa36 100644
> > > > --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
> > > > +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> > > > @@ -239,6 +239,17 @@ config DWMAC_INTEL_PLAT
> > > >         the stmmac device driver. This driver is used for the Intel Keem Bay
> > > >         SoC.
> > > >
> > > > +config DWMAC_LOONGSON1
> > > > +     tristate "Loongson1 GMAC support"
> > > > +     default MACH_LOONGSON32
> > > > +     depends on OF && (MACH_LOONGSON32 || COMPILE_TEST)
> > > > +     help
> > > > +       Support for ethernet controller on Loongson1 SoC.
> > > > +
> > > > +       This selects Loongson1 SoC glue layer support for the stmmac
> > > > +       device driver. This driver is used for Loongson1-based boards
> > > > +       like Loongson LS1B/LS1C.
> > > > +
> > > >  config DWMAC_TEGRA
> > > >       tristate "NVIDIA Tegra MGBE support"
> > > >       depends on ARCH_TEGRA || COMPILE_TEST
> > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
> > > > index 5b57aee19267..80e598bd4255 100644
> > > > --- a/drivers/net/ethernet/stmicro/stmmac/Makefile
> > > > +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
> > > > @@ -29,6 +29,7 @@ obj-$(CONFIG_DWMAC_SUNXI)   += dwmac-sunxi.o
> > > >  obj-$(CONFIG_DWMAC_SUN8I)    += dwmac-sun8i.o
> > > >  obj-$(CONFIG_DWMAC_DWC_QOS_ETH)      += dwmac-dwc-qos-eth.o
> > > >  obj-$(CONFIG_DWMAC_INTEL_PLAT)       += dwmac-intel-plat.o
> > > > +obj-$(CONFIG_DWMAC_LOONGSON1)        += dwmac-loongson1.o
> > > >  obj-$(CONFIG_DWMAC_GENERIC)  += dwmac-generic.o
> > > >  obj-$(CONFIG_DWMAC_IMX8)     += dwmac-imx.o
> > > >  obj-$(CONFIG_DWMAC_TEGRA)    += dwmac-tegra.o
> > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> > > > new file mode 100644
> > > > index 000000000000..368d6cd2cb78
> > > > --- /dev/null
> > > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> > > > @@ -0,0 +1,257 @@
> > > > +// SPDX-License-Identifier: GPL-2.0-or-later
> > > > +/*
> > > > + * Loongson-1 DWMAC glue layer
> > > > + *
> > > > + * Copyright (C) 2011-2023 Keguang Zhang <keguang.zhang@gmail.com>
> > > > + */
> > > > +
> > > > +#include <linux/mfd/syscon.h>
> > > > +#include <linux/module.h>
> > > > +#include <linux/phy.h>
> > > > +#include <linux/platform_device.h>
> > > > +#include <linux/regmap.h>
> > > > +
> > > > +#include "stmmac.h"
> > > > +#include "stmmac_platform.h"
> > > > +
> > > > +/* Loongson-1 SYSCON Registers */
> > > > +#define LS1X_SYSCON0         (0x0)
> > > > +#define LS1X_SYSCON1         (0x4)
> > > > +
> > > > +struct ls1x_dwmac_syscon {
> > > > +     const struct reg_field *reg_fields;
> > > > +     unsigned int nr_reg_fields;
> > > > +     int (*syscon_init)(struct plat_stmmacenet_data *plat);
> > > > +};
> > > > +
> > > > +struct ls1x_dwmac {
> > > > +     struct device *dev;
> > > > +     struct plat_stmmacenet_data *plat_dat;
> > > > +     const struct ls1x_dwmac_syscon *syscon;
> > > > +     struct regmap *regmap;
> > > > +     struct regmap_field *regmap_fields[];
> > > > +};
> > > > +
> > > > +enum ls1b_dwmac_syscon_regfield {
> > > > +     GMAC1_USE_UART1,
> > > > +     GMAC1_USE_UART0,
> > > > +     GMAC1_SHUT,
> > > > +     GMAC0_SHUT,
> > > > +     GMAC1_USE_TXCLK,
> > > > +     GMAC0_USE_TXCLK,
> > > > +     GMAC1_USE_PWM23,
> > > > +     GMAC0_USE_PWM01,
> > > > +};
> > > > +
> > > > +enum ls1c_dwmac_syscon_regfield {
> > > > +     GMAC_SHUT,
> > > > +     PHY_INTF_SELI,
> > > > +};
> > > > +
> > > > +const struct reg_field ls1b_dwmac_syscon_regfields[] = {
> > > > +     [GMAC1_USE_UART1]       = REG_FIELD(LS1X_SYSCON0, 4, 4),
> > > > +     [GMAC1_USE_UART0]       = REG_FIELD(LS1X_SYSCON0, 3, 3),
> > > > +     [GMAC1_SHUT]            = REG_FIELD(LS1X_SYSCON1, 13, 13),
> > > > +     [GMAC0_SHUT]            = REG_FIELD(LS1X_SYSCON1, 12, 12),
> > > > +     [GMAC1_USE_TXCLK]       = REG_FIELD(LS1X_SYSCON1, 3, 3),
> > > > +     [GMAC0_USE_TXCLK]       = REG_FIELD(LS1X_SYSCON1, 2, 2),
> > > > +     [GMAC1_USE_PWM23]       = REG_FIELD(LS1X_SYSCON1, 1, 1),
> > > > +     [GMAC0_USE_PWM01]       = REG_FIELD(LS1X_SYSCON1, 0, 0)
> > > > +};
> > > > +
> > > > +const struct reg_field ls1c_dwmac_syscon_regfields[] = {
> > > > +     [GMAC_SHUT]             = REG_FIELD(LS1X_SYSCON0, 6, 6),
> > > > +     [PHY_INTF_SELI]         = REG_FIELD(LS1X_SYSCON1, 28, 30)
> > > > +};
> > >
> > > Emm, using regmap fields looks so over-complicated in this case seeing
> > > you only need to set/clear several bits in the syscon. What about
> > > defining macros with the particular flag as it's already done in the
> > > "asm/mach-loongson32/regs-mux.h" file and using regmap_update_bits()?
> > >
>
> > To use regmap_update_bits(), I have to store and pass reg_offset and
> > mask, which is similar to the definition of regmap fields.
>
> Em, not really. And what offset are you talking about? Anyway you
> don't need one. Moreover you'll be able to reduce the number of IOs:
>
> +#define GMAC1_USE_UART1                 BIT(4)
> +#define GMAC1_USE_UART0                 BIT(3)
> ...
> +#define GMAC1_SHUT                      BIT(13)
> ...
> +#define GMAC1_USE_TXCLK                 BIT(3)
> +#define GMAC1_USE_PWM23                 BIT(1)
>
> +static int ls1b_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
> +{
> +       struct ls1x_dwmac *dwmac = plat->bsp_priv;
> +       struct regmap *syscon = dwmac->regmap;
> +
> +       if (plat->bus_id) {
> +               regmap_update_bits(syscon, LS1X_SYSCON0,
> +                                  GMAC1_USE_UART1 | GMAC1_USE_UART0,
> +                                  GMAC1_USE_UART1 | GMAC1_USE_UART0);
> +
> +               switch (plat->phy_interface) {
> +               case PHY_INTERFACE_MODE_RGMII:
> +                       regmap_update_bits(syscon, LS1X_SYSCON1,
> +                                          GMAC1_USE_TXCLK | GMAC1_USE_TXCLK, 0);
> +                       break;
> +               case PHY_INTERFACE_MODE_MII:
> +                       regmap_update_bits(syscon, LS1X_SYSCON1,
> +                                          GMAC1_USE_TXCLK | GMAC1_USE_TXCLK
> +                                          GMAC1_USE_TXCLK | GMAC1_USE_TXCLK);
> +                       break;
> +               default:
> +                       dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
> +                               plat->phy_interface);
> +                       return -EOPNOTSUPP;
> +               }
> +
> +               regmap_field_write(syscon, LS1X_SYSCON1, GMAC1_SHUT, 0);
> +       } //...
> +
> +       return 0;
> +}
>
> This doesn't look in anyway less readable then your implementation
> but in fact simpler.
>
> > In addition, the regmap fields are very clear and leave the trouble to
> > the internal implementation.
>
> In this case it brings much more troubles and no clarity. You need to create
> an additional mainly redundant abstraction, waste memory for it,
> define additional const arrays. Using it won't improve the code
> readability seeing you need to set/clear a few flags only. So all of
> the troubles for nothing. See the code above. It's simple and clear.
> Just several regmap_update_bits()..
>
OK. I will use regmap instead of regmap fields.

> BTW why have you chosen to define syscon instead of creating a pinctrl
> driver? What if Loongson1 is embedded into a platform with, for
> instance, UART0 and UART1 utilized instead of the GMAC1?
>
As you can see, the two registers contains miscellaneous settings.
Besides ‘USE’ bits, there are ‘RESET‘ bits, 'EN' bits, 'SHUT' bits, ...
So they are not pinctrl registers.
Actually, there is a dedicated pin controller which controls the
multiplexing of pads.

> >
> > > > +
> > >
> > > > +static int ls1b_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
> > > > +{
> > >
> > > As I already told you this part is better to be called from the
> > > plat_stmmacenet_data.fix_mac_speed() because PHY interface mode can
> > > differ from one interface open cycle to another as per the phylink
> > > design.
> > >
> > I have considered .fix_mac_speed(), which will be called every time
> > the link is up, and passes the current speed.
> > However, the PHY interface mode is determined by the hardware design -
> > the schematic.
> > In other words, once the schematic is done, the PHY interface mode is fixed.
> > Therefore, PHY interface mode should be configured one time at the
> > initialization.
> > And the plat_stmmacenet_data.init() is the proper place to do this.
>
> Ok. If no actual clock change is needed then indeed init() will be the
> proper place.
>
> >
> > > > +     struct ls1x_dwmac *dwmac = plat->bsp_priv;
> > > > +     struct regmap_field **regmap_fields = dwmac->regmap_fields;
> > > > +
> > >
> > > > +     if (plat->bus_id) {
> > >
> > > Using bus_id doesn't look correct to determine the CSRs responsible
> > > for the interface mode selection because it's calculated based on the
> > > DT ethernet-alias which doesn't guarantee to have a particular device
> > > assigned with the alias. Alias node can be absent after all. What
> > > could be better in this case is for instance to use the regs physical
> > > address. Any better idea?
> > >
>
> > The purpose of alias is to bind the a particular device with a
> > particular alias even some aliases are absent.
> > Because of_alias_get_id() gets the alias id.
> > For example, LS1B has two GMAC controllers, gmac0 and gmac1.
> > I have tried the Ethernet with only one alias as follows.
> >        aliases {
> >                ethernet1 = &gmac1;
> >        };
> > In this case, plat->bus_id is still 1.
> > And both gmac0 and gmac1 work.
>
> If no alias specified? If both aliases a non zero? If the IDs are
> confused? If any of these is true you are in trouble. Your code
> shouldn't rely on the aliases in this case. You need to come up with a
> way to certainly distinguish one MAC from another. A physical base
> address is one possible option.
>
I see.
But It seems unusual to determine device IDs by physical base address.
What about adding a new property? such as loongson,dwmac-id

> Note the /alias node is an informational node. It doesn't describe
> devices. Just recent Krzysztof comment in a similar situation:
> https://lore.kernel.org/netdev/20230814112539.70453-1-sriranjani.p@samsung.com/T/#m3972e40bd2fa323a3bdb2fbf07bde47ba6752439
>
> Aliases are normally used by OS to for instance fix the device
> enumeration (see SPI, I2C, I3C, MTD, MMC, RTC, TTY/Serial, Watchdog,
> MDIO-GPIO, etc) - pre-define the device ID from the kernel or OS point
> of view. In your case the IDs can't be changed. GMAC0 must be assigned
> with ID0 and GMAC1 must be assigned with non-zero. Doing otherwise
> will be break the interfaces functionality which isn't acceptable.
>
> >
> > > > +             regmap_field_write(regmap_fields[GMAC1_USE_UART1], 1);
> > > > +             regmap_field_write(regmap_fields[GMAC1_USE_UART0], 1);
> > > > +
> > > > +             switch (plat->phy_interface) {
> > > > +             case PHY_INTERFACE_MODE_RGMII:
> > > > +                     regmap_field_write(regmap_fields[GMAC1_USE_TXCLK], 0);
> > > > +                     regmap_field_write(regmap_fields[GMAC1_USE_PWM23], 0);
> > > > +                     break;
> > > > +             case PHY_INTERFACE_MODE_MII:
> > > > +                     regmap_field_write(regmap_fields[GMAC1_USE_TXCLK], 1);
> > > > +                     regmap_field_write(regmap_fields[GMAC1_USE_PWM23], 1);
> > > > +                     break;
> > > > +             default:
> > > > +                     dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
> > > > +                             plat->phy_interface);
> > > > +                     return -EOPNOTSUPP;
> > > > +             }
> > > > +
> > > > +             regmap_field_write(regmap_fields[GMAC1_SHUT], 0);
> > > > +     } else {
> > > > +             switch (plat->phy_interface) {
> > > > +             case PHY_INTERFACE_MODE_RGMII:
> > > > +                     regmap_field_write(regmap_fields[GMAC0_USE_TXCLK], 0);
> > > > +                     regmap_field_write(regmap_fields[GMAC0_USE_PWM01], 0);
> > > > +                     break;
> > > > +             case PHY_INTERFACE_MODE_MII:
> > > > +                     regmap_field_write(regmap_fields[GMAC0_USE_TXCLK], 1);
> > > > +                     regmap_field_write(regmap_fields[GMAC0_USE_PWM01], 1);
> > > > +                     break;
> > > > +             default:
> > > > +                     dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
> > > > +                             plat->phy_interface);
> > > > +                     return -EOPNOTSUPP;
> > > > +             }
> > > > +
> > > > +             regmap_field_write(regmap_fields[GMAC0_SHUT], 0);
> > > > +     }
> > > > +
> > > > +     return 0;
> > > > +}
> > > > +
> > > > +static int ls1c_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
> > > > +{
> > > > +     struct ls1x_dwmac *dwmac = plat->bsp_priv;
> > > > +     struct regmap_field **regmap_fields = dwmac->regmap_fields;
> > > > +
> > > > +     if (plat->phy_interface == PHY_INTERFACE_MODE_RMII) {
> > > > +             regmap_field_write(regmap_fields[PHY_INTF_SELI], 0x4);
> > > > +     } else {
> > > > +             dev_err(dwmac->dev, "Unsupported PHY-mode %u\n",
> > > > +                     plat->phy_interface);
> > > > +             return -EOPNOTSUPP;
> > > > +     }
> > > > +
> > > > +     regmap_field_write(regmap_fields[GMAC_SHUT], 0);
> > > > +
> > > > +     return 0;
> > > > +}
> > > > +
> > > > +static const struct ls1x_dwmac_syscon ls1b_dwmac_syscon = {
> > > > +     .reg_fields = ls1b_dwmac_syscon_regfields,
> > > > +     .nr_reg_fields = ARRAY_SIZE(ls1b_dwmac_syscon_regfields),
> > > > +     .syscon_init = ls1b_dwmac_syscon_init,
> > > > +};
> > > > +
> > > > +static const struct ls1x_dwmac_syscon ls1c_dwmac_syscon = {
> > > > +     .reg_fields = ls1c_dwmac_syscon_regfields,
> > > > +     .nr_reg_fields = ARRAY_SIZE(ls1c_dwmac_syscon_regfields),
> > > > +     .syscon_init = ls1c_dwmac_syscon_init,
> > > > +};
> > > > +
> > > > +static int ls1x_dwmac_init(struct platform_device *pdev, void *priv)
> > > > +{
> > > > +     struct ls1x_dwmac *dwmac = priv;
> > > > +     int ret;
> > > > +
> > >
> > > > +     ret = devm_regmap_field_bulk_alloc(dwmac->dev, dwmac->regmap,
> > > > +                                        dwmac->regmap_fields,
> > > > +                                        dwmac->syscon->reg_fields,
> > > > +                                        dwmac->syscon->nr_reg_fields);
> > >
> > > Please see my first comment about this.
> > >
> > > > +     if (ret)
> > > > +             return ret;
> > > > +
> > > > +     if (dwmac->syscon->syscon_init) {
> > > > +             ret = dwmac->syscon->syscon_init(dwmac->plat_dat);
> > > > +             if (ret)
> > > > +                     return ret;
> > > > +     }
> > > > +
> > > > +     return 0;
> > > > +}
> > > > +
> > > > +static const struct of_device_id ls1x_dwmac_syscon_match[] = {
> > > > +     { .compatible = "loongson,ls1b-syscon", .data = &ls1b_dwmac_syscon },
> > > > +     { .compatible = "loongson,ls1c-syscon", .data = &ls1c_dwmac_syscon },
> > > > +     { }
> > > > +};
> > > > +
> > > > +static int ls1x_dwmac_probe(struct platform_device *pdev)
> > > > +{
> > > > +     struct plat_stmmacenet_data *plat_dat;
> > > > +     struct stmmac_resources stmmac_res;
> > > > +     struct device_node *syscon_np;
> > > > +     const struct of_device_id *match;
> > > > +     struct regmap *regmap;
> > > > +     struct ls1x_dwmac *dwmac;
> > > > +     const struct ls1x_dwmac_syscon *syscon;
> > > > +     size_t size;
> > > > +     int ret;
> > > > +
> > > > +     ret = stmmac_get_platform_resources(pdev, &stmmac_res);
> > > > +     if (ret)
> > > > +             return ret;
> > > > +
> > >
> > > > +     /* Probe syscon */
> > > > +     syscon_np = of_parse_phandle(pdev->dev.of_node, "syscon", 0);
> > >
> > > it's vendor-specific property so it is supposed to have a
> > > vendor-specific prefix and possibly ls1-specific name.
> > >
> > This has been fixed in v2.
> > Could you please review v2?
> > Thanks!
> >
> > > > +     if (!syscon_np)
> > > > +             return -ENODEV;
> > > > +
> > > > +     match = of_match_node(ls1x_dwmac_syscon_match, syscon_np);
> > > > +     if (!match) {
> > > > +             of_node_put(syscon_np);
> > > > +             return -EINVAL;
> > > > +     }
> > > > +     syscon = (const struct ls1x_dwmac_syscon *)match->data;

Please note that of_match_node() is used for syscon matching.

> > > > +
> > > > +     regmap = syscon_node_to_regmap(syscon_np);
> > > > +     of_node_put(syscon_np);
> > > > +     if (IS_ERR(regmap)) {
> > > > +             ret = PTR_ERR(regmap);
> > > > +             dev_err(&pdev->dev, "Unable to map syscon: %d\n", ret);
> > > > +             return ret;
> > > > +     }
> > >
> > > or you can use syscon_regmap_lookup_by_phandle(). Using
> > > of_match_node() doesn't seem necessary since it's unlikely to have
> > > moee than one system controller available on the LS1b or LS1c chips.
> > >
>
> > I planned to use syscon_regmap_lookup_by_phandle().
> > Thus the compatible
> > "loongson,ls1b-dwmac-syscon"/"loongson,ls1c-dwmac-syscon" would become
> > useless.
> > I'm not sure about this.
>
> The compatible strings should be left despite of the
> syscon_regmap_lookup_by_phandle() usage. But again "dwmac" suffix is
> redundant. Based on the CSRs definition in regs-mux.h, selecting
> (G)MAC pins mode is only a small part of the Loongson1 SoC system
> controllers functionality.
> "loongson,ls1b-syscon"/"loongson,ls1c-syscon" looks more appropriate.
>
That's what I did in PATCH 2/5.
I've just explained this to Krzysztof.
And will change back to "loongson,ls1b-syscon"/"loongson,ls1c-syscon"
in next version.

In addition, syscon_regmap_lookup_by_phandle() returns regmap pointer directly.
Then, there wil be no way to do syscon matching without its device_node.
How will I know whether the syscon is loongson,ls1b-syscon or
loongson,ls1c-syscon?

Thanks for your review!





> -Serge(y)
>
> >
> > > > +
> > > > +     size = syscon->nr_reg_fields * sizeof(struct regmap_field *);
> > > > +     dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac) + size, GFP_KERNEL);
> > > > +     if (!dwmac)
> > > > +             return -ENOMEM;
> > > > +
> > > > +     plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
> > > > +     if (IS_ERR(plat_dat)) {
> > > > +             dev_err(&pdev->dev, "dt configuration failed\n");
> > > > +             return PTR_ERR(plat_dat);
> > > > +     }
> > > > +
> > > > +     plat_dat->bsp_priv = dwmac;
> > > > +     plat_dat->init = ls1x_dwmac_init;
> > > > +     dwmac->dev = &pdev->dev;
> > > > +     dwmac->plat_dat = plat_dat;
> > > > +     dwmac->syscon = syscon;
> > > > +     dwmac->regmap = regmap;
> > > > +
> > > > +     ret = stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res);
> > > > +     if (ret)
> > > > +             goto err_remove_config_dt;
> > > > +
> > > > +     return 0;
> > > > +
> > > > +err_remove_config_dt:
> > >
> > > > +     if (pdev->dev.of_node)
> > >
> > > Is this conditional statement necessary here?
> > >
> > You're right.
> > Will remove this condition in next version.
> > Thanks!
> >
> > > -Serge
> > >
> > > > +             stmmac_remove_config_dt(pdev, plat_dat);
> > > > +
> > > > +     return ret;
> > > > +}
> > > > +
> > > > +static const struct of_device_id ls1x_dwmac_match[] = {
> > > > +     { .compatible = "loongson,ls1b-dwmac" },
> > > > +     { .compatible = "loongson,ls1c-dwmac" },
> > > > +     { }
> > > > +};
> > > > +MODULE_DEVICE_TABLE(of, ls1x_dwmac_match);
> > > > +
> > > > +static struct platform_driver ls1x_dwmac_driver = {
> > > > +     .probe = ls1x_dwmac_probe,
> > > > +     .remove_new = stmmac_pltfr_remove,
> > > > +     .driver = {
> > > > +             .name = "loongson1-dwmac",
> > > > +             .of_match_table = ls1x_dwmac_match,
> > > > +     },
> > > > +};
> > > > +module_platform_driver(ls1x_dwmac_driver);
> > > > +
> > > > +MODULE_AUTHOR("Keguang Zhang <keguang.zhang@gmail.com>");
> > > > +MODULE_DESCRIPTION("Loongson1 DWMAC glue layer");
> > > > +MODULE_LICENSE("GPL");
> > > > --
> > > > 2.39.2
> > > >
> >
> >
> >
> > --
> > Best regards,
> >
> > Keguang Zhang



--
Best regards,

Keguang Zhang

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

* Re: [PATCH 4/5] net: stmmac: Add glue layer for Loongson-1 SoC
  2023-08-21 13:24         ` Keguang Zhang
@ 2023-08-21 14:16           ` Serge Semin
  2023-08-22  7:58             ` Keguang Zhang
  0 siblings, 1 reply; 28+ messages in thread
From: Serge Semin @ 2023-08-21 14:16 UTC (permalink / raw)
  To: Keguang Zhang
  Cc: netdev, devicetree, linux-mips, linux-kernel, Lee Jones,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, David S . Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Thomas Bogendoerfer,
	Giuseppe Cavallaro, Alexandre Torgue, Jose Abreu, Serge Semin

On Mon, Aug 21, 2023 at 09:24:17PM +0800, Keguang Zhang wrote:
> On Sat, Aug 19, 2023 at 12:19 AM Serge Semin <fancer.lancer@gmail.com> wrote:
> >
> > On Fri, Aug 18, 2023 at 08:37:27PM +0800, Keguang Zhang wrote:
> > > On Wed, Aug 16, 2023 at 9:30 PM Serge Semin <fancer.lancer@gmail.com> wrote:
> > > >
> > > > On Sat, Aug 12, 2023 at 11:11:34PM +0800, Keguang Zhang wrote:
> > > > > This glue driver is created based on the arch-code
> > > > > implemented earlier with the platform-specific settings.
> > > > >
> > > > > Use syscon for SYSCON register access.
> > > > >
> > > > > Partialy based on the previous work by Serge Semin.
> > > > >
> > > > > Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
> > > > > ---
> > > > >  drivers/net/ethernet/stmicro/stmmac/Kconfig   |  11 +
> > > > >  drivers/net/ethernet/stmicro/stmmac/Makefile  |   1 +
> > > > >  .../ethernet/stmicro/stmmac/dwmac-loongson1.c | 257 ++++++++++++++++++
> > > > >  3 files changed, 269 insertions(+)
> > > > >  create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> > > > >
> > > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> > > > > index 06c6871f8788..a2b9e289aa36 100644
> > > > > --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
> > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> > > > > @@ -239,6 +239,17 @@ config DWMAC_INTEL_PLAT
> > > > >         the stmmac device driver. This driver is used for the Intel Keem Bay
> > > > >         SoC.
> > > > >
> > > > > +config DWMAC_LOONGSON1
> > > > > +     tristate "Loongson1 GMAC support"
> > > > > +     default MACH_LOONGSON32
> > > > > +     depends on OF && (MACH_LOONGSON32 || COMPILE_TEST)
> > > > > +     help
> > > > > +       Support for ethernet controller on Loongson1 SoC.
> > > > > +
> > > > > +       This selects Loongson1 SoC glue layer support for the stmmac
> > > > > +       device driver. This driver is used for Loongson1-based boards
> > > > > +       like Loongson LS1B/LS1C.
> > > > > +
> > > > >  config DWMAC_TEGRA
> > > > >       tristate "NVIDIA Tegra MGBE support"
> > > > >       depends on ARCH_TEGRA || COMPILE_TEST
> > > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
> > > > > index 5b57aee19267..80e598bd4255 100644
> > > > > --- a/drivers/net/ethernet/stmicro/stmmac/Makefile
> > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
> > > > > @@ -29,6 +29,7 @@ obj-$(CONFIG_DWMAC_SUNXI)   += dwmac-sunxi.o
> > > > >  obj-$(CONFIG_DWMAC_SUN8I)    += dwmac-sun8i.o
> > > > >  obj-$(CONFIG_DWMAC_DWC_QOS_ETH)      += dwmac-dwc-qos-eth.o
> > > > >  obj-$(CONFIG_DWMAC_INTEL_PLAT)       += dwmac-intel-plat.o
> > > > > +obj-$(CONFIG_DWMAC_LOONGSON1)        += dwmac-loongson1.o
> > > > >  obj-$(CONFIG_DWMAC_GENERIC)  += dwmac-generic.o
> > > > >  obj-$(CONFIG_DWMAC_IMX8)     += dwmac-imx.o
> > > > >  obj-$(CONFIG_DWMAC_TEGRA)    += dwmac-tegra.o
> > > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> > > > > new file mode 100644
> > > > > index 000000000000..368d6cd2cb78
> > > > > --- /dev/null
> > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> > > > > @@ -0,0 +1,257 @@
> > > > > +// SPDX-License-Identifier: GPL-2.0-or-later
> > > > > +/*
> > > > > + * Loongson-1 DWMAC glue layer
> > > > > + *
> > > > > + * Copyright (C) 2011-2023 Keguang Zhang <keguang.zhang@gmail.com>
> > > > > + */
> > > > > +
> > > > > +#include <linux/mfd/syscon.h>
> > > > > +#include <linux/module.h>
> > > > > +#include <linux/phy.h>
> > > > > +#include <linux/platform_device.h>
> > > > > +#include <linux/regmap.h>
> > > > > +
> > > > > +#include "stmmac.h"
> > > > > +#include "stmmac_platform.h"
> > > > > +
> > > > > +/* Loongson-1 SYSCON Registers */
> > > > > +#define LS1X_SYSCON0         (0x0)
> > > > > +#define LS1X_SYSCON1         (0x4)
> > > > > +
> > > > > +struct ls1x_dwmac_syscon {
> > > > > +     const struct reg_field *reg_fields;
> > > > > +     unsigned int nr_reg_fields;
> > > > > +     int (*syscon_init)(struct plat_stmmacenet_data *plat);
> > > > > +};
> > > > > +
> > > > > +struct ls1x_dwmac {
> > > > > +     struct device *dev;
> > > > > +     struct plat_stmmacenet_data *plat_dat;
> > > > > +     const struct ls1x_dwmac_syscon *syscon;
> > > > > +     struct regmap *regmap;
> > > > > +     struct regmap_field *regmap_fields[];
> > > > > +};
> > > > > +
> > > > > +enum ls1b_dwmac_syscon_regfield {
> > > > > +     GMAC1_USE_UART1,
> > > > > +     GMAC1_USE_UART0,
> > > > > +     GMAC1_SHUT,
> > > > > +     GMAC0_SHUT,
> > > > > +     GMAC1_USE_TXCLK,
> > > > > +     GMAC0_USE_TXCLK,
> > > > > +     GMAC1_USE_PWM23,
> > > > > +     GMAC0_USE_PWM01,
> > > > > +};
> > > > > +
> > > > > +enum ls1c_dwmac_syscon_regfield {
> > > > > +     GMAC_SHUT,
> > > > > +     PHY_INTF_SELI,
> > > > > +};
> > > > > +
> > > > > +const struct reg_field ls1b_dwmac_syscon_regfields[] = {
> > > > > +     [GMAC1_USE_UART1]       = REG_FIELD(LS1X_SYSCON0, 4, 4),
> > > > > +     [GMAC1_USE_UART0]       = REG_FIELD(LS1X_SYSCON0, 3, 3),
> > > > > +     [GMAC1_SHUT]            = REG_FIELD(LS1X_SYSCON1, 13, 13),
> > > > > +     [GMAC0_SHUT]            = REG_FIELD(LS1X_SYSCON1, 12, 12),
> > > > > +     [GMAC1_USE_TXCLK]       = REG_FIELD(LS1X_SYSCON1, 3, 3),
> > > > > +     [GMAC0_USE_TXCLK]       = REG_FIELD(LS1X_SYSCON1, 2, 2),
> > > > > +     [GMAC1_USE_PWM23]       = REG_FIELD(LS1X_SYSCON1, 1, 1),
> > > > > +     [GMAC0_USE_PWM01]       = REG_FIELD(LS1X_SYSCON1, 0, 0)
> > > > > +};
> > > > > +
> > > > > +const struct reg_field ls1c_dwmac_syscon_regfields[] = {
> > > > > +     [GMAC_SHUT]             = REG_FIELD(LS1X_SYSCON0, 6, 6),
> > > > > +     [PHY_INTF_SELI]         = REG_FIELD(LS1X_SYSCON1, 28, 30)
> > > > > +};
> > > >
> > > > Emm, using regmap fields looks so over-complicated in this case seeing
> > > > you only need to set/clear several bits in the syscon. What about
> > > > defining macros with the particular flag as it's already done in the
> > > > "asm/mach-loongson32/regs-mux.h" file and using regmap_update_bits()?
> > > >
> >
> > > To use regmap_update_bits(), I have to store and pass reg_offset and
> > > mask, which is similar to the definition of regmap fields.
> >
> > Em, not really. And what offset are you talking about? Anyway you
> > don't need one. Moreover you'll be able to reduce the number of IOs:
> >
> > +#define GMAC1_USE_UART1                 BIT(4)
> > +#define GMAC1_USE_UART0                 BIT(3)
> > ...
> > +#define GMAC1_SHUT                      BIT(13)
> > ...
> > +#define GMAC1_USE_TXCLK                 BIT(3)
> > +#define GMAC1_USE_PWM23                 BIT(1)
> >
> > +static int ls1b_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
> > +{
> > +       struct ls1x_dwmac *dwmac = plat->bsp_priv;
> > +       struct regmap *syscon = dwmac->regmap;
> > +
> > +       if (plat->bus_id) {
> > +               regmap_update_bits(syscon, LS1X_SYSCON0,
> > +                                  GMAC1_USE_UART1 | GMAC1_USE_UART0,
> > +                                  GMAC1_USE_UART1 | GMAC1_USE_UART0);
> > +
> > +               switch (plat->phy_interface) {
> > +               case PHY_INTERFACE_MODE_RGMII:
> > +                       regmap_update_bits(syscon, LS1X_SYSCON1,
> > +                                          GMAC1_USE_TXCLK | GMAC1_USE_TXCLK, 0);
> > +                       break;
> > +               case PHY_INTERFACE_MODE_MII:
> > +                       regmap_update_bits(syscon, LS1X_SYSCON1,
> > +                                          GMAC1_USE_TXCLK | GMAC1_USE_TXCLK
> > +                                          GMAC1_USE_TXCLK | GMAC1_USE_TXCLK);
> > +                       break;
> > +               default:
> > +                       dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
> > +                               plat->phy_interface);
> > +                       return -EOPNOTSUPP;
> > +               }
> > +
> > +               regmap_field_write(syscon, LS1X_SYSCON1, GMAC1_SHUT, 0);
> > +       } //...
> > +
> > +       return 0;
> > +}
> >
> > This doesn't look in anyway less readable then your implementation
> > but in fact simpler.
> >
> > > In addition, the regmap fields are very clear and leave the trouble to
> > > the internal implementation.
> >
> > In this case it brings much more troubles and no clarity. You need to create
> > an additional mainly redundant abstraction, waste memory for it,
> > define additional const arrays. Using it won't improve the code
> > readability seeing you need to set/clear a few flags only. So all of
> > the troubles for nothing. See the code above. It's simple and clear.
> > Just several regmap_update_bits()..
> >
> OK. I will use regmap instead of regmap fields.
> 
> > BTW why have you chosen to define syscon instead of creating a pinctrl
> > driver? What if Loongson1 is embedded into a platform with, for
> > instance, UART0 and UART1 utilized instead of the GMAC1?
> >

> As you can see, the two registers contains miscellaneous settings.
> Besides ‘USE’ bits, there are ‘RESET‘ bits, 'EN' bits, 'SHUT' bits, ...
> So they are not pinctrl registers.

You could have defined a device node which would export "reset",
"power" and "pinctrl" functionality, like it's normally done for the
RCU devices (Reset and Clock unit devices).

> Actually, there is a dedicated pin controller which controls the
> multiplexing of pads.

Do you mean that there is another controller in the Loongson1 SoC
which controls the pads multiplexing?

If so what is the purpose of the GMAC1_USE_UART1, GMAC1_USE_UART0 and
GMAC1_USE_TXCLK, GMAC1_USE_PWM23 flags in MUX controller then? Is it
just another pinctl space with additional reset/power controls or what?

> 
> > >
> > > > > +
> > > >
> > > > > +static int ls1b_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
> > > > > +{
> > > >
> > > > As I already told you this part is better to be called from the
> > > > plat_stmmacenet_data.fix_mac_speed() because PHY interface mode can
> > > > differ from one interface open cycle to another as per the phylink
> > > > design.
> > > >
> > > I have considered .fix_mac_speed(), which will be called every time
> > > the link is up, and passes the current speed.
> > > However, the PHY interface mode is determined by the hardware design -
> > > the schematic.
> > > In other words, once the schematic is done, the PHY interface mode is fixed.
> > > Therefore, PHY interface mode should be configured one time at the
> > > initialization.
> > > And the plat_stmmacenet_data.init() is the proper place to do this.
> >
> > Ok. If no actual clock change is needed then indeed init() will be the
> > proper place.
> >
> > >
> > > > > +     struct ls1x_dwmac *dwmac = plat->bsp_priv;
> > > > > +     struct regmap_field **regmap_fields = dwmac->regmap_fields;
> > > > > +
> > > >
> > > > > +     if (plat->bus_id) {
> > > >
> > > > Using bus_id doesn't look correct to determine the CSRs responsible
> > > > for the interface mode selection because it's calculated based on the
> > > > DT ethernet-alias which doesn't guarantee to have a particular device
> > > > assigned with the alias. Alias node can be absent after all. What
> > > > could be better in this case is for instance to use the regs physical
> > > > address. Any better idea?
> > > >
> >
> > > The purpose of alias is to bind the a particular device with a
> > > particular alias even some aliases are absent.
> > > Because of_alias_get_id() gets the alias id.
> > > For example, LS1B has two GMAC controllers, gmac0 and gmac1.
> > > I have tried the Ethernet with only one alias as follows.
> > >        aliases {
> > >                ethernet1 = &gmac1;
> > >        };
> > > In this case, plat->bus_id is still 1.
> > > And both gmac0 and gmac1 work.
> >
> > If no alias specified? If both aliases a non zero? If the IDs are
> > confused? If any of these is true you are in trouble. Your code
> > shouldn't rely on the aliases in this case. You need to come up with a
> > way to certainly distinguish one MAC from another. A physical base
> > address is one possible option.
> >

> I see.
> But It seems unusual to determine device IDs by physical base address.
> What about adding a new property? such as loongson,dwmac-id

IMO It's better to have a DT-property-independent way for it. If I
were you I would have utilized the reg-space
physical-base-address-based approach since you need to have it
specified anyway and it determines the particular MAC for sure.
Thus your driver won't be dependent in the device tree in that aspect.

Some DW *MAC drivers pass additional number to the syscon phandle node
in the syscon-property to identify the MAC on the board, like
dwmac-socfpga.c or dwmac-sti.c. If you get to implement a similar way
then you'll need to have the DT-bindings properly describing that. But
IMO my approach seems less clumsy and simpler.

> 
> > Note the /alias node is an informational node. It doesn't describe
> > devices. Just recent Krzysztof comment in a similar situation:
> > https://lore.kernel.org/netdev/20230814112539.70453-1-sriranjani.p@samsung.com/T/#m3972e40bd2fa323a3bdb2fbf07bde47ba6752439
> >
> > Aliases are normally used by OS to for instance fix the device
> > enumeration (see SPI, I2C, I3C, MTD, MMC, RTC, TTY/Serial, Watchdog,
> > MDIO-GPIO, etc) - pre-define the device ID from the kernel or OS point
> > of view. In your case the IDs can't be changed. GMAC0 must be assigned
> > with ID0 and GMAC1 must be assigned with non-zero. Doing otherwise
> > will be break the interfaces functionality which isn't acceptable.
> >
> > >
> > > > > +             regmap_field_write(regmap_fields[GMAC1_USE_UART1], 1);
> > > > > +             regmap_field_write(regmap_fields[GMAC1_USE_UART0], 1);
> > > > > +
> > > > > +             switch (plat->phy_interface) {
> > > > > +             case PHY_INTERFACE_MODE_RGMII:
> > > > > +                     regmap_field_write(regmap_fields[GMAC1_USE_TXCLK], 0);
> > > > > +                     regmap_field_write(regmap_fields[GMAC1_USE_PWM23], 0);
> > > > > +                     break;
> > > > > +             case PHY_INTERFACE_MODE_MII:
> > > > > +                     regmap_field_write(regmap_fields[GMAC1_USE_TXCLK], 1);
> > > > > +                     regmap_field_write(regmap_fields[GMAC1_USE_PWM23], 1);
> > > > > +                     break;
> > > > > +             default:
> > > > > +                     dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
> > > > > +                             plat->phy_interface);
> > > > > +                     return -EOPNOTSUPP;
> > > > > +             }
> > > > > +
> > > > > +             regmap_field_write(regmap_fields[GMAC1_SHUT], 0);
> > > > > +     } else {
> > > > > +             switch (plat->phy_interface) {
> > > > > +             case PHY_INTERFACE_MODE_RGMII:
> > > > > +                     regmap_field_write(regmap_fields[GMAC0_USE_TXCLK], 0);
> > > > > +                     regmap_field_write(regmap_fields[GMAC0_USE_PWM01], 0);
> > > > > +                     break;
> > > > > +             case PHY_INTERFACE_MODE_MII:
> > > > > +                     regmap_field_write(regmap_fields[GMAC0_USE_TXCLK], 1);
> > > > > +                     regmap_field_write(regmap_fields[GMAC0_USE_PWM01], 1);
> > > > > +                     break;
> > > > > +             default:
> > > > > +                     dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
> > > > > +                             plat->phy_interface);
> > > > > +                     return -EOPNOTSUPP;
> > > > > +             }
> > > > > +
> > > > > +             regmap_field_write(regmap_fields[GMAC0_SHUT], 0);
> > > > > +     }
> > > > > +
> > > > > +     return 0;
> > > > > +}
> > > > > +
> > > > > +static int ls1c_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
> > > > > +{
> > > > > +     struct ls1x_dwmac *dwmac = plat->bsp_priv;
> > > > > +     struct regmap_field **regmap_fields = dwmac->regmap_fields;
> > > > > +
> > > > > +     if (plat->phy_interface == PHY_INTERFACE_MODE_RMII) {
> > > > > +             regmap_field_write(regmap_fields[PHY_INTF_SELI], 0x4);
> > > > > +     } else {
> > > > > +             dev_err(dwmac->dev, "Unsupported PHY-mode %u\n",
> > > > > +                     plat->phy_interface);
> > > > > +             return -EOPNOTSUPP;
> > > > > +     }
> > > > > +
> > > > > +     regmap_field_write(regmap_fields[GMAC_SHUT], 0);
> > > > > +
> > > > > +     return 0;
> > > > > +}
> > > > > +
> > > > > +static const struct ls1x_dwmac_syscon ls1b_dwmac_syscon = {
> > > > > +     .reg_fields = ls1b_dwmac_syscon_regfields,
> > > > > +     .nr_reg_fields = ARRAY_SIZE(ls1b_dwmac_syscon_regfields),
> > > > > +     .syscon_init = ls1b_dwmac_syscon_init,
> > > > > +};
> > > > > +
> > > > > +static const struct ls1x_dwmac_syscon ls1c_dwmac_syscon = {
> > > > > +     .reg_fields = ls1c_dwmac_syscon_regfields,
> > > > > +     .nr_reg_fields = ARRAY_SIZE(ls1c_dwmac_syscon_regfields),
> > > > > +     .syscon_init = ls1c_dwmac_syscon_init,
> > > > > +};
> > > > > +
> > > > > +static int ls1x_dwmac_init(struct platform_device *pdev, void *priv)
> > > > > +{
> > > > > +     struct ls1x_dwmac *dwmac = priv;
> > > > > +     int ret;
> > > > > +
> > > >
> > > > > +     ret = devm_regmap_field_bulk_alloc(dwmac->dev, dwmac->regmap,
> > > > > +                                        dwmac->regmap_fields,
> > > > > +                                        dwmac->syscon->reg_fields,
> > > > > +                                        dwmac->syscon->nr_reg_fields);
> > > >
> > > > Please see my first comment about this.
> > > >
> > > > > +     if (ret)
> > > > > +             return ret;
> > > > > +
> > > > > +     if (dwmac->syscon->syscon_init) {
> > > > > +             ret = dwmac->syscon->syscon_init(dwmac->plat_dat);
> > > > > +             if (ret)
> > > > > +                     return ret;
> > > > > +     }
> > > > > +
> > > > > +     return 0;
> > > > > +}
> > > > > +
> > > > > +static const struct of_device_id ls1x_dwmac_syscon_match[] = {
> > > > > +     { .compatible = "loongson,ls1b-syscon", .data = &ls1b_dwmac_syscon },
> > > > > +     { .compatible = "loongson,ls1c-syscon", .data = &ls1c_dwmac_syscon },
> > > > > +     { }
> > > > > +};
> > > > > +
> > > > > +static int ls1x_dwmac_probe(struct platform_device *pdev)
> > > > > +{
> > > > > +     struct plat_stmmacenet_data *plat_dat;
> > > > > +     struct stmmac_resources stmmac_res;
> > > > > +     struct device_node *syscon_np;
> > > > > +     const struct of_device_id *match;
> > > > > +     struct regmap *regmap;
> > > > > +     struct ls1x_dwmac *dwmac;
> > > > > +     const struct ls1x_dwmac_syscon *syscon;
> > > > > +     size_t size;
> > > > > +     int ret;
> > > > > +
> > > > > +     ret = stmmac_get_platform_resources(pdev, &stmmac_res);
> > > > > +     if (ret)
> > > > > +             return ret;
> > > > > +
> > > >
> > > > > +     /* Probe syscon */
> > > > > +     syscon_np = of_parse_phandle(pdev->dev.of_node, "syscon", 0);
> > > >
> > > > it's vendor-specific property so it is supposed to have a
> > > > vendor-specific prefix and possibly ls1-specific name.
> > > >
> > > This has been fixed in v2.
> > > Could you please review v2?
> > > Thanks!
> > >
> > > > > +     if (!syscon_np)
> > > > > +             return -ENODEV;
> > > > > +
> > > > > +     match = of_match_node(ls1x_dwmac_syscon_match, syscon_np);
> > > > > +     if (!match) {
> > > > > +             of_node_put(syscon_np);
> > > > > +             return -EINVAL;
> > > > > +     }
> > > > > +     syscon = (const struct ls1x_dwmac_syscon *)match->data;
> 

> Please note that of_match_node() is used for syscon matching.

I noticed it in the first place. Please see my next comment.

> 
> > > > > +
> > > > > +     regmap = syscon_node_to_regmap(syscon_np);
> > > > > +     of_node_put(syscon_np);
> > > > > +     if (IS_ERR(regmap)) {
> > > > > +             ret = PTR_ERR(regmap);
> > > > > +             dev_err(&pdev->dev, "Unable to map syscon: %d\n", ret);
> > > > > +             return ret;
> > > > > +     }
> > > >
> > > > or you can use syscon_regmap_lookup_by_phandle(). Using
> > > > of_match_node() doesn't seem necessary since it's unlikely to have
> > > > moee than one system controller available on the LS1b or LS1c chips.
> > > >
> >
> > > I planned to use syscon_regmap_lookup_by_phandle().
> > > Thus the compatible
> > > "loongson,ls1b-dwmac-syscon"/"loongson,ls1c-dwmac-syscon" would become
> > > useless.
> > > I'm not sure about this.
> >
> > The compatible strings should be left despite of the
> > syscon_regmap_lookup_by_phandle() usage. But again "dwmac" suffix is
> > redundant. Based on the CSRs definition in regs-mux.h, selecting
> > (G)MAC pins mode is only a small part of the Loongson1 SoC system
> > controllers functionality.
> > "loongson,ls1b-syscon"/"loongson,ls1c-syscon" looks more appropriate.
> >
> That's what I did in PATCH 2/5.
> I've just explained this to Krzysztof.
> And will change back to "loongson,ls1b-syscon"/"loongson,ls1c-syscon"
> in next version.
> 

> In addition, syscon_regmap_lookup_by_phandle() returns regmap pointer directly.
> Then, there wil be no way to do syscon matching without its device_node.
> How will I know whether the syscon is loongson,ls1b-syscon or
> loongson,ls1c-syscon?

Do you have both of these syscons available in the same SoC? I don't
think so. Thus you don't need such validation since the LS1C SoC dts
file will have the "loongson,ls1c-syscon" syscon node defined only and
the LS1B SoC dts file - "loongson,ls1b-syscon" only.

-Serge(y)

> 
> Thanks for your review!
> 
> 
> 
> 
> 
> > -Serge(y)
> >
> > >
> > > > > +
> > > > > +     size = syscon->nr_reg_fields * sizeof(struct regmap_field *);
> > > > > +     dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac) + size, GFP_KERNEL);
> > > > > +     if (!dwmac)
> > > > > +             return -ENOMEM;
> > > > > +
> > > > > +     plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
> > > > > +     if (IS_ERR(plat_dat)) {
> > > > > +             dev_err(&pdev->dev, "dt configuration failed\n");
> > > > > +             return PTR_ERR(plat_dat);
> > > > > +     }
> > > > > +
> > > > > +     plat_dat->bsp_priv = dwmac;
> > > > > +     plat_dat->init = ls1x_dwmac_init;
> > > > > +     dwmac->dev = &pdev->dev;
> > > > > +     dwmac->plat_dat = plat_dat;
> > > > > +     dwmac->syscon = syscon;
> > > > > +     dwmac->regmap = regmap;
> > > > > +
> > > > > +     ret = stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res);
> > > > > +     if (ret)
> > > > > +             goto err_remove_config_dt;
> > > > > +
> > > > > +     return 0;
> > > > > +
> > > > > +err_remove_config_dt:
> > > >
> > > > > +     if (pdev->dev.of_node)
> > > >
> > > > Is this conditional statement necessary here?
> > > >
> > > You're right.
> > > Will remove this condition in next version.
> > > Thanks!
> > >
> > > > -Serge
> > > >
> > > > > +             stmmac_remove_config_dt(pdev, plat_dat);
> > > > > +
> > > > > +     return ret;
> > > > > +}
> > > > > +
> > > > > +static const struct of_device_id ls1x_dwmac_match[] = {
> > > > > +     { .compatible = "loongson,ls1b-dwmac" },
> > > > > +     { .compatible = "loongson,ls1c-dwmac" },
> > > > > +     { }
> > > > > +};
> > > > > +MODULE_DEVICE_TABLE(of, ls1x_dwmac_match);
> > > > > +
> > > > > +static struct platform_driver ls1x_dwmac_driver = {
> > > > > +     .probe = ls1x_dwmac_probe,
> > > > > +     .remove_new = stmmac_pltfr_remove,
> > > > > +     .driver = {
> > > > > +             .name = "loongson1-dwmac",
> > > > > +             .of_match_table = ls1x_dwmac_match,
> > > > > +     },
> > > > > +};
> > > > > +module_platform_driver(ls1x_dwmac_driver);
> > > > > +
> > > > > +MODULE_AUTHOR("Keguang Zhang <keguang.zhang@gmail.com>");
> > > > > +MODULE_DESCRIPTION("Loongson1 DWMAC glue layer");
> > > > > +MODULE_LICENSE("GPL");
> > > > > --
> > > > > 2.39.2
> > > > >
> > >
> > >
> > >
> > > --
> > > Best regards,
> > >
> > > Keguang Zhang
> 
> 
> 
> --
> Best regards,
> 
> Keguang Zhang

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

* Re: [PATCH 4/5] net: stmmac: Add glue layer for Loongson-1 SoC
  2023-08-21 14:16           ` Serge Semin
@ 2023-08-22  7:58             ` Keguang Zhang
  2023-08-22 10:53               ` Serge Semin
  0 siblings, 1 reply; 28+ messages in thread
From: Keguang Zhang @ 2023-08-22  7:58 UTC (permalink / raw)
  To: Serge Semin
  Cc: netdev, devicetree, linux-mips, linux-kernel, Lee Jones,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, David S . Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Thomas Bogendoerfer,
	Giuseppe Cavallaro, Alexandre Torgue, Jose Abreu, Serge Semin

On Mon, Aug 21, 2023 at 10:16 PM Serge Semin <fancer.lancer@gmail.com> wrote:
>
> On Mon, Aug 21, 2023 at 09:24:17PM +0800, Keguang Zhang wrote:
> > On Sat, Aug 19, 2023 at 12:19 AM Serge Semin <fancer.lancer@gmail.com> wrote:
> > >
> > > On Fri, Aug 18, 2023 at 08:37:27PM +0800, Keguang Zhang wrote:
> > > > On Wed, Aug 16, 2023 at 9:30 PM Serge Semin <fancer.lancer@gmail.com> wrote:
> > > > >
> > > > > On Sat, Aug 12, 2023 at 11:11:34PM +0800, Keguang Zhang wrote:
> > > > > > This glue driver is created based on the arch-code
> > > > > > implemented earlier with the platform-specific settings.
> > > > > >
> > > > > > Use syscon for SYSCON register access.
> > > > > >
> > > > > > Partialy based on the previous work by Serge Semin.
> > > > > >
> > > > > > Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
> > > > > > ---
> > > > > >  drivers/net/ethernet/stmicro/stmmac/Kconfig   |  11 +
> > > > > >  drivers/net/ethernet/stmicro/stmmac/Makefile  |   1 +
> > > > > >  .../ethernet/stmicro/stmmac/dwmac-loongson1.c | 257 ++++++++++++++++++
> > > > > >  3 files changed, 269 insertions(+)
> > > > > >  create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> > > > > >
> > > > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> > > > > > index 06c6871f8788..a2b9e289aa36 100644
> > > > > > --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
> > > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> > > > > > @@ -239,6 +239,17 @@ config DWMAC_INTEL_PLAT
> > > > > >         the stmmac device driver. This driver is used for the Intel Keem Bay
> > > > > >         SoC.
> > > > > >
> > > > > > +config DWMAC_LOONGSON1
> > > > > > +     tristate "Loongson1 GMAC support"
> > > > > > +     default MACH_LOONGSON32
> > > > > > +     depends on OF && (MACH_LOONGSON32 || COMPILE_TEST)
> > > > > > +     help
> > > > > > +       Support for ethernet controller on Loongson1 SoC.
> > > > > > +
> > > > > > +       This selects Loongson1 SoC glue layer support for the stmmac
> > > > > > +       device driver. This driver is used for Loongson1-based boards
> > > > > > +       like Loongson LS1B/LS1C.
> > > > > > +
> > > > > >  config DWMAC_TEGRA
> > > > > >       tristate "NVIDIA Tegra MGBE support"
> > > > > >       depends on ARCH_TEGRA || COMPILE_TEST
> > > > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
> > > > > > index 5b57aee19267..80e598bd4255 100644
> > > > > > --- a/drivers/net/ethernet/stmicro/stmmac/Makefile
> > > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
> > > > > > @@ -29,6 +29,7 @@ obj-$(CONFIG_DWMAC_SUNXI)   += dwmac-sunxi.o
> > > > > >  obj-$(CONFIG_DWMAC_SUN8I)    += dwmac-sun8i.o
> > > > > >  obj-$(CONFIG_DWMAC_DWC_QOS_ETH)      += dwmac-dwc-qos-eth.o
> > > > > >  obj-$(CONFIG_DWMAC_INTEL_PLAT)       += dwmac-intel-plat.o
> > > > > > +obj-$(CONFIG_DWMAC_LOONGSON1)        += dwmac-loongson1.o
> > > > > >  obj-$(CONFIG_DWMAC_GENERIC)  += dwmac-generic.o
> > > > > >  obj-$(CONFIG_DWMAC_IMX8)     += dwmac-imx.o
> > > > > >  obj-$(CONFIG_DWMAC_TEGRA)    += dwmac-tegra.o
> > > > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> > > > > > new file mode 100644
> > > > > > index 000000000000..368d6cd2cb78
> > > > > > --- /dev/null
> > > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> > > > > > @@ -0,0 +1,257 @@
> > > > > > +// SPDX-License-Identifier: GPL-2.0-or-later
> > > > > > +/*
> > > > > > + * Loongson-1 DWMAC glue layer
> > > > > > + *
> > > > > > + * Copyright (C) 2011-2023 Keguang Zhang <keguang.zhang@gmail.com>
> > > > > > + */
> > > > > > +
> > > > > > +#include <linux/mfd/syscon.h>
> > > > > > +#include <linux/module.h>
> > > > > > +#include <linux/phy.h>
> > > > > > +#include <linux/platform_device.h>
> > > > > > +#include <linux/regmap.h>
> > > > > > +
> > > > > > +#include "stmmac.h"
> > > > > > +#include "stmmac_platform.h"
> > > > > > +
> > > > > > +/* Loongson-1 SYSCON Registers */
> > > > > > +#define LS1X_SYSCON0         (0x0)
> > > > > > +#define LS1X_SYSCON1         (0x4)
> > > > > > +
> > > > > > +struct ls1x_dwmac_syscon {
> > > > > > +     const struct reg_field *reg_fields;
> > > > > > +     unsigned int nr_reg_fields;
> > > > > > +     int (*syscon_init)(struct plat_stmmacenet_data *plat);
> > > > > > +};
> > > > > > +
> > > > > > +struct ls1x_dwmac {
> > > > > > +     struct device *dev;
> > > > > > +     struct plat_stmmacenet_data *plat_dat;
> > > > > > +     const struct ls1x_dwmac_syscon *syscon;
> > > > > > +     struct regmap *regmap;
> > > > > > +     struct regmap_field *regmap_fields[];
> > > > > > +};
> > > > > > +
> > > > > > +enum ls1b_dwmac_syscon_regfield {
> > > > > > +     GMAC1_USE_UART1,
> > > > > > +     GMAC1_USE_UART0,
> > > > > > +     GMAC1_SHUT,
> > > > > > +     GMAC0_SHUT,
> > > > > > +     GMAC1_USE_TXCLK,
> > > > > > +     GMAC0_USE_TXCLK,
> > > > > > +     GMAC1_USE_PWM23,
> > > > > > +     GMAC0_USE_PWM01,
> > > > > > +};
> > > > > > +
> > > > > > +enum ls1c_dwmac_syscon_regfield {
> > > > > > +     GMAC_SHUT,
> > > > > > +     PHY_INTF_SELI,
> > > > > > +};
> > > > > > +
> > > > > > +const struct reg_field ls1b_dwmac_syscon_regfields[] = {
> > > > > > +     [GMAC1_USE_UART1]       = REG_FIELD(LS1X_SYSCON0, 4, 4),
> > > > > > +     [GMAC1_USE_UART0]       = REG_FIELD(LS1X_SYSCON0, 3, 3),
> > > > > > +     [GMAC1_SHUT]            = REG_FIELD(LS1X_SYSCON1, 13, 13),
> > > > > > +     [GMAC0_SHUT]            = REG_FIELD(LS1X_SYSCON1, 12, 12),
> > > > > > +     [GMAC1_USE_TXCLK]       = REG_FIELD(LS1X_SYSCON1, 3, 3),
> > > > > > +     [GMAC0_USE_TXCLK]       = REG_FIELD(LS1X_SYSCON1, 2, 2),
> > > > > > +     [GMAC1_USE_PWM23]       = REG_FIELD(LS1X_SYSCON1, 1, 1),
> > > > > > +     [GMAC0_USE_PWM01]       = REG_FIELD(LS1X_SYSCON1, 0, 0)
> > > > > > +};
> > > > > > +
> > > > > > +const struct reg_field ls1c_dwmac_syscon_regfields[] = {
> > > > > > +     [GMAC_SHUT]             = REG_FIELD(LS1X_SYSCON0, 6, 6),
> > > > > > +     [PHY_INTF_SELI]         = REG_FIELD(LS1X_SYSCON1, 28, 30)
> > > > > > +};
> > > > >
> > > > > Emm, using regmap fields looks so over-complicated in this case seeing
> > > > > you only need to set/clear several bits in the syscon. What about
> > > > > defining macros with the particular flag as it's already done in the
> > > > > "asm/mach-loongson32/regs-mux.h" file and using regmap_update_bits()?
> > > > >
> > >
> > > > To use regmap_update_bits(), I have to store and pass reg_offset and
> > > > mask, which is similar to the definition of regmap fields.
> > >
> > > Em, not really. And what offset are you talking about? Anyway you
> > > don't need one. Moreover you'll be able to reduce the number of IOs:
> > >
> > > +#define GMAC1_USE_UART1                 BIT(4)
> > > +#define GMAC1_USE_UART0                 BIT(3)
> > > ...
> > > +#define GMAC1_SHUT                      BIT(13)
> > > ...
> > > +#define GMAC1_USE_TXCLK                 BIT(3)
> > > +#define GMAC1_USE_PWM23                 BIT(1)
> > >
> > > +static int ls1b_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
> > > +{
> > > +       struct ls1x_dwmac *dwmac = plat->bsp_priv;
> > > +       struct regmap *syscon = dwmac->regmap;
> > > +
> > > +       if (plat->bus_id) {
> > > +               regmap_update_bits(syscon, LS1X_SYSCON0,
> > > +                                  GMAC1_USE_UART1 | GMAC1_USE_UART0,
> > > +                                  GMAC1_USE_UART1 | GMAC1_USE_UART0);
> > > +
> > > +               switch (plat->phy_interface) {
> > > +               case PHY_INTERFACE_MODE_RGMII:
> > > +                       regmap_update_bits(syscon, LS1X_SYSCON1,
> > > +                                          GMAC1_USE_TXCLK | GMAC1_USE_TXCLK, 0);
> > > +                       break;
> > > +               case PHY_INTERFACE_MODE_MII:
> > > +                       regmap_update_bits(syscon, LS1X_SYSCON1,
> > > +                                          GMAC1_USE_TXCLK | GMAC1_USE_TXCLK
> > > +                                          GMAC1_USE_TXCLK | GMAC1_USE_TXCLK);
> > > +                       break;
> > > +               default:
> > > +                       dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
> > > +                               plat->phy_interface);
> > > +                       return -EOPNOTSUPP;
> > > +               }
> > > +
> > > +               regmap_field_write(syscon, LS1X_SYSCON1, GMAC1_SHUT, 0);
> > > +       } //...
> > > +
> > > +       return 0;
> > > +}
> > >
> > > This doesn't look in anyway less readable then your implementation
> > > but in fact simpler.
> > >
> > > > In addition, the regmap fields are very clear and leave the trouble to
> > > > the internal implementation.
> > >
> > > In this case it brings much more troubles and no clarity. You need to create
> > > an additional mainly redundant abstraction, waste memory for it,
> > > define additional const arrays. Using it won't improve the code
> > > readability seeing you need to set/clear a few flags only. So all of
> > > the troubles for nothing. See the code above. It's simple and clear.
> > > Just several regmap_update_bits()..
> > >
> > OK. I will use regmap instead of regmap fields.
> >
> > > BTW why have you chosen to define syscon instead of creating a pinctrl
> > > driver? What if Loongson1 is embedded into a platform with, for
> > > instance, UART0 and UART1 utilized instead of the GMAC1?
> > >
>
> > As you can see, the two registers contains miscellaneous settings.
> > Besides ‘USE’ bits, there are ‘RESET‘ bits, 'EN' bits, 'SHUT' bits, ...
> > So they are not pinctrl registers.
>
> You could have defined a device node which would export "reset",
> "power" and "pinctrl" functionality, like it's normally done for the
> RCU devices (Reset and Clock unit devices).
>
> > Actually, there is a dedicated pin controller which controls the
> > multiplexing of pads.
>
> Do you mean that there is another controller in the Loongson1 SoC
> which controls the pads multiplexing?
>
Yes. There is another contoller that really controls the pads multiplexing.

> If so what is the purpose of the GMAC1_USE_UART1, GMAC1_USE_UART0 and
> GMAC1_USE_TXCLK, GMAC1_USE_PWM23 flags in MUX controller then? Is it
> just another pinctl space with additional reset/power controls or what?
>
From my perspective, these ‘USE’ bits should be regarded as
device/module multiplexing rather than pads multiplexing.
Although the two registers were called MUX_CTRL in LS1B datasheet,
they had beed renamed to MISC_CTRL in LS1C datasheet.
So it is supposed to be considered syscon.
> >
> > > >
> > > > > > +
> > > > >
> > > > > > +static int ls1b_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
> > > > > > +{
> > > > >
> > > > > As I already told you this part is better to be called from the
> > > > > plat_stmmacenet_data.fix_mac_speed() because PHY interface mode can
> > > > > differ from one interface open cycle to another as per the phylink
> > > > > design.
> > > > >
> > > > I have considered .fix_mac_speed(), which will be called every time
> > > > the link is up, and passes the current speed.
> > > > However, the PHY interface mode is determined by the hardware design -
> > > > the schematic.
> > > > In other words, once the schematic is done, the PHY interface mode is fixed.
> > > > Therefore, PHY interface mode should be configured one time at the
> > > > initialization.
> > > > And the plat_stmmacenet_data.init() is the proper place to do this.
> > >
> > > Ok. If no actual clock change is needed then indeed init() will be the
> > > proper place.
> > >
> > > >
> > > > > > +     struct ls1x_dwmac *dwmac = plat->bsp_priv;
> > > > > > +     struct regmap_field **regmap_fields = dwmac->regmap_fields;
> > > > > > +
> > > > >
> > > > > > +     if (plat->bus_id) {
> > > > >
> > > > > Using bus_id doesn't look correct to determine the CSRs responsible
> > > > > for the interface mode selection because it's calculated based on the
> > > > > DT ethernet-alias which doesn't guarantee to have a particular device
> > > > > assigned with the alias. Alias node can be absent after all. What
> > > > > could be better in this case is for instance to use the regs physical
> > > > > address. Any better idea?
> > > > >
> > >
> > > > The purpose of alias is to bind the a particular device with a
> > > > particular alias even some aliases are absent.
> > > > Because of_alias_get_id() gets the alias id.
> > > > For example, LS1B has two GMAC controllers, gmac0 and gmac1.
> > > > I have tried the Ethernet with only one alias as follows.
> > > >        aliases {
> > > >                ethernet1 = &gmac1;
> > > >        };
> > > > In this case, plat->bus_id is still 1.
> > > > And both gmac0 and gmac1 work.
> > >
> > > If no alias specified? If both aliases a non zero? If the IDs are
> > > confused? If any of these is true you are in trouble. Your code
> > > shouldn't rely on the aliases in this case. You need to come up with a
> > > way to certainly distinguish one MAC from another. A physical base
> > > address is one possible option.
> > >
>
> > I see.
> > But It seems unusual to determine device IDs by physical base address.
> > What about adding a new property? such as loongson,dwmac-id
>
> IMO It's better to have a DT-property-independent way for it. If I
> were you I would have utilized the reg-space
> physical-base-address-based approach since you need to have it
> specified anyway and it determines the particular MAC for sure.
> Thus your driver won't be dependent in the device tree in that aspect.
>
The physical base address may vary from SoC to SoC.
It means that the driver has to remember MAC base addresses for different SoCs.

> Some DW *MAC drivers pass additional number to the syscon phandle node
> in the syscon-property to identify the MAC on the board, like
> dwmac-socfpga.c or dwmac-sti.c. If you get to implement a similar way
> then you'll need to have the DT-bindings properly describing that. But
> IMO my approach seems less clumsy and simpler.
>
I prefer the DT-bindings property way. At least many off-the-shelf
examples can be found.

> >
> > > Note the /alias node is an informational node. It doesn't describe
> > > devices. Just recent Krzysztof comment in a similar situation:
> > > https://lore.kernel.org/netdev/20230814112539.70453-1-sriranjani.p@samsung.com/T/#m3972e40bd2fa323a3bdb2fbf07bde47ba6752439
> > >
> > > Aliases are normally used by OS to for instance fix the device
> > > enumeration (see SPI, I2C, I3C, MTD, MMC, RTC, TTY/Serial, Watchdog,
> > > MDIO-GPIO, etc) - pre-define the device ID from the kernel or OS point
> > > of view. In your case the IDs can't be changed. GMAC0 must be assigned
> > > with ID0 and GMAC1 must be assigned with non-zero. Doing otherwise
> > > will be break the interfaces functionality which isn't acceptable.
> > >
> > > >
> > > > > > +             regmap_field_write(regmap_fields[GMAC1_USE_UART1], 1);
> > > > > > +             regmap_field_write(regmap_fields[GMAC1_USE_UART0], 1);
> > > > > > +
> > > > > > +             switch (plat->phy_interface) {
> > > > > > +             case PHY_INTERFACE_MODE_RGMII:
> > > > > > +                     regmap_field_write(regmap_fields[GMAC1_USE_TXCLK], 0);
> > > > > > +                     regmap_field_write(regmap_fields[GMAC1_USE_PWM23], 0);
> > > > > > +                     break;
> > > > > > +             case PHY_INTERFACE_MODE_MII:
> > > > > > +                     regmap_field_write(regmap_fields[GMAC1_USE_TXCLK], 1);
> > > > > > +                     regmap_field_write(regmap_fields[GMAC1_USE_PWM23], 1);
> > > > > > +                     break;
> > > > > > +             default:
> > > > > > +                     dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
> > > > > > +                             plat->phy_interface);
> > > > > > +                     return -EOPNOTSUPP;
> > > > > > +             }
> > > > > > +
> > > > > > +             regmap_field_write(regmap_fields[GMAC1_SHUT], 0);
> > > > > > +     } else {
> > > > > > +             switch (plat->phy_interface) {
> > > > > > +             case PHY_INTERFACE_MODE_RGMII:
> > > > > > +                     regmap_field_write(regmap_fields[GMAC0_USE_TXCLK], 0);
> > > > > > +                     regmap_field_write(regmap_fields[GMAC0_USE_PWM01], 0);
> > > > > > +                     break;
> > > > > > +             case PHY_INTERFACE_MODE_MII:
> > > > > > +                     regmap_field_write(regmap_fields[GMAC0_USE_TXCLK], 1);
> > > > > > +                     regmap_field_write(regmap_fields[GMAC0_USE_PWM01], 1);
> > > > > > +                     break;
> > > > > > +             default:
> > > > > > +                     dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
> > > > > > +                             plat->phy_interface);
> > > > > > +                     return -EOPNOTSUPP;
> > > > > > +             }
> > > > > > +
> > > > > > +             regmap_field_write(regmap_fields[GMAC0_SHUT], 0);
> > > > > > +     }
> > > > > > +
> > > > > > +     return 0;
> > > > > > +}
> > > > > > +
> > > > > > +static int ls1c_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
> > > > > > +{
> > > > > > +     struct ls1x_dwmac *dwmac = plat->bsp_priv;
> > > > > > +     struct regmap_field **regmap_fields = dwmac->regmap_fields;
> > > > > > +
> > > > > > +     if (plat->phy_interface == PHY_INTERFACE_MODE_RMII) {
> > > > > > +             regmap_field_write(regmap_fields[PHY_INTF_SELI], 0x4);
> > > > > > +     } else {
> > > > > > +             dev_err(dwmac->dev, "Unsupported PHY-mode %u\n",
> > > > > > +                     plat->phy_interface);
> > > > > > +             return -EOPNOTSUPP;
> > > > > > +     }
> > > > > > +
> > > > > > +     regmap_field_write(regmap_fields[GMAC_SHUT], 0);
> > > > > > +
> > > > > > +     return 0;
> > > > > > +}
> > > > > > +
> > > > > > +static const struct ls1x_dwmac_syscon ls1b_dwmac_syscon = {
> > > > > > +     .reg_fields = ls1b_dwmac_syscon_regfields,
> > > > > > +     .nr_reg_fields = ARRAY_SIZE(ls1b_dwmac_syscon_regfields),
> > > > > > +     .syscon_init = ls1b_dwmac_syscon_init,
> > > > > > +};
> > > > > > +
> > > > > > +static const struct ls1x_dwmac_syscon ls1c_dwmac_syscon = {
> > > > > > +     .reg_fields = ls1c_dwmac_syscon_regfields,
> > > > > > +     .nr_reg_fields = ARRAY_SIZE(ls1c_dwmac_syscon_regfields),
> > > > > > +     .syscon_init = ls1c_dwmac_syscon_init,
> > > > > > +};
> > > > > > +
> > > > > > +static int ls1x_dwmac_init(struct platform_device *pdev, void *priv)
> > > > > > +{
> > > > > > +     struct ls1x_dwmac *dwmac = priv;
> > > > > > +     int ret;
> > > > > > +
> > > > >
> > > > > > +     ret = devm_regmap_field_bulk_alloc(dwmac->dev, dwmac->regmap,
> > > > > > +                                        dwmac->regmap_fields,
> > > > > > +                                        dwmac->syscon->reg_fields,
> > > > > > +                                        dwmac->syscon->nr_reg_fields);
> > > > >
> > > > > Please see my first comment about this.
> > > > >
> > > > > > +     if (ret)
> > > > > > +             return ret;
> > > > > > +
> > > > > > +     if (dwmac->syscon->syscon_init) {
> > > > > > +             ret = dwmac->syscon->syscon_init(dwmac->plat_dat);
> > > > > > +             if (ret)
> > > > > > +                     return ret;
> > > > > > +     }
> > > > > > +
> > > > > > +     return 0;
> > > > > > +}
> > > > > > +
> > > > > > +static const struct of_device_id ls1x_dwmac_syscon_match[] = {
> > > > > > +     { .compatible = "loongson,ls1b-syscon", .data = &ls1b_dwmac_syscon },
> > > > > > +     { .compatible = "loongson,ls1c-syscon", .data = &ls1c_dwmac_syscon },
> > > > > > +     { }
> > > > > > +};
> > > > > > +
> > > > > > +static int ls1x_dwmac_probe(struct platform_device *pdev)
> > > > > > +{
> > > > > > +     struct plat_stmmacenet_data *plat_dat;
> > > > > > +     struct stmmac_resources stmmac_res;
> > > > > > +     struct device_node *syscon_np;
> > > > > > +     const struct of_device_id *match;
> > > > > > +     struct regmap *regmap;
> > > > > > +     struct ls1x_dwmac *dwmac;
> > > > > > +     const struct ls1x_dwmac_syscon *syscon;
> > > > > > +     size_t size;
> > > > > > +     int ret;
> > > > > > +
> > > > > > +     ret = stmmac_get_platform_resources(pdev, &stmmac_res);
> > > > > > +     if (ret)
> > > > > > +             return ret;
> > > > > > +
> > > > >
> > > > > > +     /* Probe syscon */
> > > > > > +     syscon_np = of_parse_phandle(pdev->dev.of_node, "syscon", 0);
> > > > >
> > > > > it's vendor-specific property so it is supposed to have a
> > > > > vendor-specific prefix and possibly ls1-specific name.
> > > > >
> > > > This has been fixed in v2.
> > > > Could you please review v2?
> > > > Thanks!
> > > >
> > > > > > +     if (!syscon_np)
> > > > > > +             return -ENODEV;
> > > > > > +
> > > > > > +     match = of_match_node(ls1x_dwmac_syscon_match, syscon_np);
> > > > > > +     if (!match) {
> > > > > > +             of_node_put(syscon_np);
> > > > > > +             return -EINVAL;
> > > > > > +     }
> > > > > > +     syscon = (const struct ls1x_dwmac_syscon *)match->data;
> >
>
> > Please note that of_match_node() is used for syscon matching.
>
> I noticed it in the first place. Please see my next comment.
>
> >
> > > > > > +
> > > > > > +     regmap = syscon_node_to_regmap(syscon_np);
> > > > > > +     of_node_put(syscon_np);
> > > > > > +     if (IS_ERR(regmap)) {
> > > > > > +             ret = PTR_ERR(regmap);
> > > > > > +             dev_err(&pdev->dev, "Unable to map syscon: %d\n", ret);
> > > > > > +             return ret;
> > > > > > +     }
> > > > >
> > > > > or you can use syscon_regmap_lookup_by_phandle(). Using
> > > > > of_match_node() doesn't seem necessary since it's unlikely to have
> > > > > moee than one system controller available on the LS1b or LS1c chips.
> > > > >
> > >
> > > > I planned to use syscon_regmap_lookup_by_phandle().
> > > > Thus the compatible
> > > > "loongson,ls1b-dwmac-syscon"/"loongson,ls1c-dwmac-syscon" would become
> > > > useless.
> > > > I'm not sure about this.
> > >
> > > The compatible strings should be left despite of the
> > > syscon_regmap_lookup_by_phandle() usage. But again "dwmac" suffix is
> > > redundant. Based on the CSRs definition in regs-mux.h, selecting
> > > (G)MAC pins mode is only a small part of the Loongson1 SoC system
> > > controllers functionality.
> > > "loongson,ls1b-syscon"/"loongson,ls1c-syscon" looks more appropriate.
> > >
> > That's what I did in PATCH 2/5.
> > I've just explained this to Krzysztof.
> > And will change back to "loongson,ls1b-syscon"/"loongson,ls1c-syscon"
> > in next version.
> >
>
> > In addition, syscon_regmap_lookup_by_phandle() returns regmap pointer directly.
> > Then, there wil be no way to do syscon matching without its device_node.
> > How will I know whether the syscon is loongson,ls1b-syscon or
> > loongson,ls1c-syscon?
>
> Do you have both of these syscons available in the same SoC? I don't
> think so. Thus you don't need such validation since the LS1C SoC dts
> file will have the "loongson,ls1c-syscon" syscon node defined only and
> the LS1B SoC dts file - "loongson,ls1b-syscon" only.
>
I believe you have noticed the difference of syscon_init() between
LS1B and LS1C.
The syscon matching is for finding the right syscon_init().

Thanks for your review!

> -Serge(y)
>
> >
> > Thanks for your review!
> >
> >
> >
> >
> >
> > > -Serge(y)
> > >
> > > >
> > > > > > +
> > > > > > +     size = syscon->nr_reg_fields * sizeof(struct regmap_field *);
> > > > > > +     dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac) + size, GFP_KERNEL);
> > > > > > +     if (!dwmac)
> > > > > > +             return -ENOMEM;
> > > > > > +
> > > > > > +     plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
> > > > > > +     if (IS_ERR(plat_dat)) {
> > > > > > +             dev_err(&pdev->dev, "dt configuration failed\n");
> > > > > > +             return PTR_ERR(plat_dat);
> > > > > > +     }
> > > > > > +
> > > > > > +     plat_dat->bsp_priv = dwmac;
> > > > > > +     plat_dat->init = ls1x_dwmac_init;
> > > > > > +     dwmac->dev = &pdev->dev;
> > > > > > +     dwmac->plat_dat = plat_dat;
> > > > > > +     dwmac->syscon = syscon;
> > > > > > +     dwmac->regmap = regmap;
> > > > > > +
> > > > > > +     ret = stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res);
> > > > > > +     if (ret)
> > > > > > +             goto err_remove_config_dt;
> > > > > > +
> > > > > > +     return 0;
> > > > > > +
> > > > > > +err_remove_config_dt:
> > > > >
> > > > > > +     if (pdev->dev.of_node)
> > > > >
> > > > > Is this conditional statement necessary here?
> > > > >
> > > > You're right.
> > > > Will remove this condition in next version.
> > > > Thanks!
> > > >
> > > > > -Serge
> > > > >
> > > > > > +             stmmac_remove_config_dt(pdev, plat_dat);
> > > > > > +
> > > > > > +     return ret;
> > > > > > +}
> > > > > > +
> > > > > > +static const struct of_device_id ls1x_dwmac_match[] = {
> > > > > > +     { .compatible = "loongson,ls1b-dwmac" },
> > > > > > +     { .compatible = "loongson,ls1c-dwmac" },
> > > > > > +     { }
> > > > > > +};
> > > > > > +MODULE_DEVICE_TABLE(of, ls1x_dwmac_match);
> > > > > > +
> > > > > > +static struct platform_driver ls1x_dwmac_driver = {
> > > > > > +     .probe = ls1x_dwmac_probe,
> > > > > > +     .remove_new = stmmac_pltfr_remove,
> > > > > > +     .driver = {
> > > > > > +             .name = "loongson1-dwmac",
> > > > > > +             .of_match_table = ls1x_dwmac_match,
> > > > > > +     },
> > > > > > +};
> > > > > > +module_platform_driver(ls1x_dwmac_driver);
> > > > > > +
> > > > > > +MODULE_AUTHOR("Keguang Zhang <keguang.zhang@gmail.com>");
> > > > > > +MODULE_DESCRIPTION("Loongson1 DWMAC glue layer");
> > > > > > +MODULE_LICENSE("GPL");
> > > > > > --
> > > > > > 2.39.2
> > > > > >
> > > >
> > > >
> > > >
> > > > --
> > > > Best regards,
> > > >
> > > > Keguang Zhang
> >
> >
> >
> > --
> > Best regards,
> >
> > Keguang Zhang



-- 
Best regards,

Keguang Zhang

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

* Re: [PATCH 4/5] net: stmmac: Add glue layer for Loongson-1 SoC
  2023-08-22  7:58             ` Keguang Zhang
@ 2023-08-22 10:53               ` Serge Semin
  2023-08-22 12:09                 ` Keguang Zhang
  0 siblings, 1 reply; 28+ messages in thread
From: Serge Semin @ 2023-08-22 10:53 UTC (permalink / raw)
  To: Keguang Zhang
  Cc: netdev, devicetree, linux-mips, linux-kernel, Lee Jones,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, David S . Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Thomas Bogendoerfer,
	Giuseppe Cavallaro, Alexandre Torgue, Jose Abreu, Serge Semin

On Tue, Aug 22, 2023 at 03:58:32PM +0800, Keguang Zhang wrote:
> On Mon, Aug 21, 2023 at 10:16 PM Serge Semin <fancer.lancer@gmail.com> wrote:
> >
> > On Mon, Aug 21, 2023 at 09:24:17PM +0800, Keguang Zhang wrote:
> > > On Sat, Aug 19, 2023 at 12:19 AM Serge Semin <fancer.lancer@gmail.com> wrote:
> > > >
> > > > On Fri, Aug 18, 2023 at 08:37:27PM +0800, Keguang Zhang wrote:
> > > > > On Wed, Aug 16, 2023 at 9:30 PM Serge Semin <fancer.lancer@gmail.com> wrote:
> > > > > >
> > > > > > On Sat, Aug 12, 2023 at 11:11:34PM +0800, Keguang Zhang wrote:
> > > > > > > This glue driver is created based on the arch-code
> > > > > > > implemented earlier with the platform-specific settings.
> > > > > > >
> > > > > > > Use syscon for SYSCON register access.
> > > > > > >
> > > > > > > Partialy based on the previous work by Serge Semin.
> > > > > > >
> > > > > > > Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
> > > > > > > ---
> > > > > > >  drivers/net/ethernet/stmicro/stmmac/Kconfig   |  11 +
> > > > > > >  drivers/net/ethernet/stmicro/stmmac/Makefile  |   1 +
> > > > > > >  .../ethernet/stmicro/stmmac/dwmac-loongson1.c | 257 ++++++++++++++++++
> > > > > > >  3 files changed, 269 insertions(+)
> > > > > > >  create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> > > > > > >
> > > > > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> > > > > > > index 06c6871f8788..a2b9e289aa36 100644
> > > > > > > --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
> > > > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> > > > > > > @@ -239,6 +239,17 @@ config DWMAC_INTEL_PLAT
> > > > > > >         the stmmac device driver. This driver is used for the Intel Keem Bay
> > > > > > >         SoC.
> > > > > > >
> > > > > > > +config DWMAC_LOONGSON1
> > > > > > > +     tristate "Loongson1 GMAC support"
> > > > > > > +     default MACH_LOONGSON32
> > > > > > > +     depends on OF && (MACH_LOONGSON32 || COMPILE_TEST)
> > > > > > > +     help
> > > > > > > +       Support for ethernet controller on Loongson1 SoC.
> > > > > > > +
> > > > > > > +       This selects Loongson1 SoC glue layer support for the stmmac
> > > > > > > +       device driver. This driver is used for Loongson1-based boards
> > > > > > > +       like Loongson LS1B/LS1C.
> > > > > > > +
> > > > > > >  config DWMAC_TEGRA
> > > > > > >       tristate "NVIDIA Tegra MGBE support"
> > > > > > >       depends on ARCH_TEGRA || COMPILE_TEST
> > > > > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
> > > > > > > index 5b57aee19267..80e598bd4255 100644
> > > > > > > --- a/drivers/net/ethernet/stmicro/stmmac/Makefile
> > > > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
> > > > > > > @@ -29,6 +29,7 @@ obj-$(CONFIG_DWMAC_SUNXI)   += dwmac-sunxi.o
> > > > > > >  obj-$(CONFIG_DWMAC_SUN8I)    += dwmac-sun8i.o
> > > > > > >  obj-$(CONFIG_DWMAC_DWC_QOS_ETH)      += dwmac-dwc-qos-eth.o
> > > > > > >  obj-$(CONFIG_DWMAC_INTEL_PLAT)       += dwmac-intel-plat.o
> > > > > > > +obj-$(CONFIG_DWMAC_LOONGSON1)        += dwmac-loongson1.o
> > > > > > >  obj-$(CONFIG_DWMAC_GENERIC)  += dwmac-generic.o
> > > > > > >  obj-$(CONFIG_DWMAC_IMX8)     += dwmac-imx.o
> > > > > > >  obj-$(CONFIG_DWMAC_TEGRA)    += dwmac-tegra.o
> > > > > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> > > > > > > new file mode 100644
> > > > > > > index 000000000000..368d6cd2cb78
> > > > > > > --- /dev/null
> > > > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> > > > > > > @@ -0,0 +1,257 @@
> > > > > > > +// SPDX-License-Identifier: GPL-2.0-or-later
> > > > > > > +/*
> > > > > > > + * Loongson-1 DWMAC glue layer
> > > > > > > + *
> > > > > > > + * Copyright (C) 2011-2023 Keguang Zhang <keguang.zhang@gmail.com>
> > > > > > > + */
> > > > > > > +
> > > > > > > +#include <linux/mfd/syscon.h>
> > > > > > > +#include <linux/module.h>
> > > > > > > +#include <linux/phy.h>
> > > > > > > +#include <linux/platform_device.h>
> > > > > > > +#include <linux/regmap.h>
> > > > > > > +
> > > > > > > +#include "stmmac.h"
> > > > > > > +#include "stmmac_platform.h"
> > > > > > > +
> > > > > > > +/* Loongson-1 SYSCON Registers */
> > > > > > > +#define LS1X_SYSCON0         (0x0)
> > > > > > > +#define LS1X_SYSCON1         (0x4)
> > > > > > > +
> > > > > > > +struct ls1x_dwmac_syscon {
> > > > > > > +     const struct reg_field *reg_fields;
> > > > > > > +     unsigned int nr_reg_fields;
> > > > > > > +     int (*syscon_init)(struct plat_stmmacenet_data *plat);
> > > > > > > +};
> > > > > > > +
> > > > > > > +struct ls1x_dwmac {
> > > > > > > +     struct device *dev;
> > > > > > > +     struct plat_stmmacenet_data *plat_dat;
> > > > > > > +     const struct ls1x_dwmac_syscon *syscon;
> > > > > > > +     struct regmap *regmap;
> > > > > > > +     struct regmap_field *regmap_fields[];
> > > > > > > +};
> > > > > > > +
> > > > > > > +enum ls1b_dwmac_syscon_regfield {
> > > > > > > +     GMAC1_USE_UART1,
> > > > > > > +     GMAC1_USE_UART0,
> > > > > > > +     GMAC1_SHUT,
> > > > > > > +     GMAC0_SHUT,
> > > > > > > +     GMAC1_USE_TXCLK,
> > > > > > > +     GMAC0_USE_TXCLK,
> > > > > > > +     GMAC1_USE_PWM23,
> > > > > > > +     GMAC0_USE_PWM01,
> > > > > > > +};
> > > > > > > +
> > > > > > > +enum ls1c_dwmac_syscon_regfield {
> > > > > > > +     GMAC_SHUT,
> > > > > > > +     PHY_INTF_SELI,
> > > > > > > +};
> > > > > > > +
> > > > > > > +const struct reg_field ls1b_dwmac_syscon_regfields[] = {
> > > > > > > +     [GMAC1_USE_UART1]       = REG_FIELD(LS1X_SYSCON0, 4, 4),
> > > > > > > +     [GMAC1_USE_UART0]       = REG_FIELD(LS1X_SYSCON0, 3, 3),
> > > > > > > +     [GMAC1_SHUT]            = REG_FIELD(LS1X_SYSCON1, 13, 13),
> > > > > > > +     [GMAC0_SHUT]            = REG_FIELD(LS1X_SYSCON1, 12, 12),
> > > > > > > +     [GMAC1_USE_TXCLK]       = REG_FIELD(LS1X_SYSCON1, 3, 3),
> > > > > > > +     [GMAC0_USE_TXCLK]       = REG_FIELD(LS1X_SYSCON1, 2, 2),
> > > > > > > +     [GMAC1_USE_PWM23]       = REG_FIELD(LS1X_SYSCON1, 1, 1),
> > > > > > > +     [GMAC0_USE_PWM01]       = REG_FIELD(LS1X_SYSCON1, 0, 0)
> > > > > > > +};
> > > > > > > +
> > > > > > > +const struct reg_field ls1c_dwmac_syscon_regfields[] = {
> > > > > > > +     [GMAC_SHUT]             = REG_FIELD(LS1X_SYSCON0, 6, 6),
> > > > > > > +     [PHY_INTF_SELI]         = REG_FIELD(LS1X_SYSCON1, 28, 30)
> > > > > > > +};
> > > > > >
> > > > > > Emm, using regmap fields looks so over-complicated in this case seeing
> > > > > > you only need to set/clear several bits in the syscon. What about
> > > > > > defining macros with the particular flag as it's already done in the
> > > > > > "asm/mach-loongson32/regs-mux.h" file and using regmap_update_bits()?
> > > > > >
> > > >
> > > > > To use regmap_update_bits(), I have to store and pass reg_offset and
> > > > > mask, which is similar to the definition of regmap fields.
> > > >
> > > > Em, not really. And what offset are you talking about? Anyway you
> > > > don't need one. Moreover you'll be able to reduce the number of IOs:
> > > >
> > > > +#define GMAC1_USE_UART1                 BIT(4)
> > > > +#define GMAC1_USE_UART0                 BIT(3)
> > > > ...
> > > > +#define GMAC1_SHUT                      BIT(13)
> > > > ...
> > > > +#define GMAC1_USE_TXCLK                 BIT(3)
> > > > +#define GMAC1_USE_PWM23                 BIT(1)
> > > >
> > > > +static int ls1b_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
> > > > +{
> > > > +       struct ls1x_dwmac *dwmac = plat->bsp_priv;
> > > > +       struct regmap *syscon = dwmac->regmap;
> > > > +
> > > > +       if (plat->bus_id) {
> > > > +               regmap_update_bits(syscon, LS1X_SYSCON0,
> > > > +                                  GMAC1_USE_UART1 | GMAC1_USE_UART0,
> > > > +                                  GMAC1_USE_UART1 | GMAC1_USE_UART0);
> > > > +
> > > > +               switch (plat->phy_interface) {
> > > > +               case PHY_INTERFACE_MODE_RGMII:
> > > > +                       regmap_update_bits(syscon, LS1X_SYSCON1,
> > > > +                                          GMAC1_USE_TXCLK | GMAC1_USE_TXCLK, 0);
> > > > +                       break;
> > > > +               case PHY_INTERFACE_MODE_MII:
> > > > +                       regmap_update_bits(syscon, LS1X_SYSCON1,
> > > > +                                          GMAC1_USE_TXCLK | GMAC1_USE_TXCLK
> > > > +                                          GMAC1_USE_TXCLK | GMAC1_USE_TXCLK);
> > > > +                       break;
> > > > +               default:
> > > > +                       dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
> > > > +                               plat->phy_interface);
> > > > +                       return -EOPNOTSUPP;
> > > > +               }
> > > > +
> > > > +               regmap_field_write(syscon, LS1X_SYSCON1, GMAC1_SHUT, 0);
> > > > +       } //...
> > > > +
> > > > +       return 0;
> > > > +}
> > > >
> > > > This doesn't look in anyway less readable then your implementation
> > > > but in fact simpler.
> > > >
> > > > > In addition, the regmap fields are very clear and leave the trouble to
> > > > > the internal implementation.
> > > >
> > > > In this case it brings much more troubles and no clarity. You need to create
> > > > an additional mainly redundant abstraction, waste memory for it,
> > > > define additional const arrays. Using it won't improve the code
> > > > readability seeing you need to set/clear a few flags only. So all of
> > > > the troubles for nothing. See the code above. It's simple and clear.
> > > > Just several regmap_update_bits()..
> > > >
> > > OK. I will use regmap instead of regmap fields.
> > >
> > > > BTW why have you chosen to define syscon instead of creating a pinctrl
> > > > driver? What if Loongson1 is embedded into a platform with, for
> > > > instance, UART0 and UART1 utilized instead of the GMAC1?
> > > >
> >
> > > As you can see, the two registers contains miscellaneous settings.
> > > Besides ‘USE’ bits, there are ‘RESET‘ bits, 'EN' bits, 'SHUT' bits, ...
> > > So they are not pinctrl registers.
> >
> > You could have defined a device node which would export "reset",
> > "power" and "pinctrl" functionality, like it's normally done for the
> > RCU devices (Reset and Clock unit devices).
> >
> > > Actually, there is a dedicated pin controller which controls the
> > > multiplexing of pads.
> >
> > Do you mean that there is another controller in the Loongson1 SoC
> > which controls the pads multiplexing?
> >
> Yes. There is another contoller that really controls the pads multiplexing.
> 
> > If so what is the purpose of the GMAC1_USE_UART1, GMAC1_USE_UART0 and
> > GMAC1_USE_TXCLK, GMAC1_USE_PWM23 flags in MUX controller then? Is it
> > just another pinctl space with additional reset/power controls or what?
> >

> From my perspective, these ‘USE’ bits should be regarded as
> device/module multiplexing rather than pads multiplexing.

Could you elaborate what does "device/module multiplexing" mean?

> Although the two registers were called MUX_CTRL in LS1B datasheet,
> they had beed renamed to MISC_CTRL in LS1C datasheet.
> So it is supposed to be considered syscon.
> > >
> > > > >
> > > > > > > +
> > > > > >
> > > > > > > +static int ls1b_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
> > > > > > > +{
> > > > > >
> > > > > > As I already told you this part is better to be called from the
> > > > > > plat_stmmacenet_data.fix_mac_speed() because PHY interface mode can
> > > > > > differ from one interface open cycle to another as per the phylink
> > > > > > design.
> > > > > >
> > > > > I have considered .fix_mac_speed(), which will be called every time
> > > > > the link is up, and passes the current speed.
> > > > > However, the PHY interface mode is determined by the hardware design -
> > > > > the schematic.
> > > > > In other words, once the schematic is done, the PHY interface mode is fixed.
> > > > > Therefore, PHY interface mode should be configured one time at the
> > > > > initialization.
> > > > > And the plat_stmmacenet_data.init() is the proper place to do this.
> > > >
> > > > Ok. If no actual clock change is needed then indeed init() will be the
> > > > proper place.
> > > >
> > > > >
> > > > > > > +     struct ls1x_dwmac *dwmac = plat->bsp_priv;
> > > > > > > +     struct regmap_field **regmap_fields = dwmac->regmap_fields;
> > > > > > > +
> > > > > >
> > > > > > > +     if (plat->bus_id) {
> > > > > >
> > > > > > Using bus_id doesn't look correct to determine the CSRs responsible
> > > > > > for the interface mode selection because it's calculated based on the
> > > > > > DT ethernet-alias which doesn't guarantee to have a particular device
> > > > > > assigned with the alias. Alias node can be absent after all. What
> > > > > > could be better in this case is for instance to use the regs physical
> > > > > > address. Any better idea?
> > > > > >
> > > >
> > > > > The purpose of alias is to bind the a particular device with a
> > > > > particular alias even some aliases are absent.
> > > > > Because of_alias_get_id() gets the alias id.
> > > > > For example, LS1B has two GMAC controllers, gmac0 and gmac1.
> > > > > I have tried the Ethernet with only one alias as follows.
> > > > >        aliases {
> > > > >                ethernet1 = &gmac1;
> > > > >        };
> > > > > In this case, plat->bus_id is still 1.
> > > > > And both gmac0 and gmac1 work.
> > > >
> > > > If no alias specified? If both aliases a non zero? If the IDs are
> > > > confused? If any of these is true you are in trouble. Your code
> > > > shouldn't rely on the aliases in this case. You need to come up with a
> > > > way to certainly distinguish one MAC from another. A physical base
> > > > address is one possible option.
> > > >
> >
> > > I see.
> > > But It seems unusual to determine device IDs by physical base address.
> > > What about adding a new property? such as loongson,dwmac-id
> >
> > IMO It's better to have a DT-property-independent way for it. If I
> > were you I would have utilized the reg-space
> > physical-base-address-based approach since you need to have it
> > specified anyway and it determines the particular MAC for sure.
> > Thus your driver won't be dependent in the device tree in that aspect.
> >

> The physical base address may vary from SoC to SoC.

You've got only two SoCs, right? LS1C and LS1B. Each of them has
a specific set of NICs: two loongson,ls1b-gmac on LS1B and
one loongson,ls1c-mac on LS1C. So LS1B has only two physical addresses
you can use to distinguish one interface from another and find out
what flags to toggle in the syscon. LS1C has a single MAC so you won't
even need any additional info since there is only one flag to
toggle.

Physical address is constant from one LS1C instance to another, and
similarly from one LS1B instance to another. It's defined by means
of the macros:
LS1X_GMAC0_BASE
LS1X_GMAC1_BASE
What physical address varying are you talking about? I don't see that
in the current platform driver.

> It means that the driver has to remember MAC base addresses for different SoCs.

Yes. Just two physical addresses.

> 
> > Some DW *MAC drivers pass additional number to the syscon phandle node
> > in the syscon-property to identify the MAC on the board, like
> > dwmac-socfpga.c or dwmac-sti.c. If you get to implement a similar way
> > then you'll need to have the DT-bindings properly describing that. But
> > IMO my approach seems less clumsy and simpler.
> >

> I prefer the DT-bindings property way. At least many off-the-shelf
> examples can be found.

Just two examples with not the best solution implemented.

Anyway it's up to you to decide after all. I don't mind if it will be
the property-based way. But as for me it looks redundant seeing there
is base address always available and which you can utilise. Moreover
if you get to add any new Loongson MAC to the driver you'll need to
update it anyway at least in a way the syscon flags are toggled. So
even from that perspective using the physical base address seems as at
least the equally complex and maintainable solution.

> 
> > >
> > > > Note the /alias node is an informational node. It doesn't describe
> > > > devices. Just recent Krzysztof comment in a similar situation:
> > > > https://lore.kernel.org/netdev/20230814112539.70453-1-sriranjani.p@samsung.com/T/#m3972e40bd2fa323a3bdb2fbf07bde47ba6752439
> > > >
> > > > Aliases are normally used by OS to for instance fix the device
> > > > enumeration (see SPI, I2C, I3C, MTD, MMC, RTC, TTY/Serial, Watchdog,
> > > > MDIO-GPIO, etc) - pre-define the device ID from the kernel or OS point
> > > > of view. In your case the IDs can't be changed. GMAC0 must be assigned
> > > > with ID0 and GMAC1 must be assigned with non-zero. Doing otherwise
> > > > will be break the interfaces functionality which isn't acceptable.
> > > >
> > > > >
> > > > > > > +             regmap_field_write(regmap_fields[GMAC1_USE_UART1], 1);
> > > > > > > +             regmap_field_write(regmap_fields[GMAC1_USE_UART0], 1);
> > > > > > > +
> > > > > > > +             switch (plat->phy_interface) {
> > > > > > > +             case PHY_INTERFACE_MODE_RGMII:
> > > > > > > +                     regmap_field_write(regmap_fields[GMAC1_USE_TXCLK], 0);
> > > > > > > +                     regmap_field_write(regmap_fields[GMAC1_USE_PWM23], 0);
> > > > > > > +                     break;
> > > > > > > +             case PHY_INTERFACE_MODE_MII:
> > > > > > > +                     regmap_field_write(regmap_fields[GMAC1_USE_TXCLK], 1);
> > > > > > > +                     regmap_field_write(regmap_fields[GMAC1_USE_PWM23], 1);
> > > > > > > +                     break;
> > > > > > > +             default:
> > > > > > > +                     dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
> > > > > > > +                             plat->phy_interface);
> > > > > > > +                     return -EOPNOTSUPP;
> > > > > > > +             }
> > > > > > > +
> > > > > > > +             regmap_field_write(regmap_fields[GMAC1_SHUT], 0);
> > > > > > > +     } else {
> > > > > > > +             switch (plat->phy_interface) {
> > > > > > > +             case PHY_INTERFACE_MODE_RGMII:
> > > > > > > +                     regmap_field_write(regmap_fields[GMAC0_USE_TXCLK], 0);
> > > > > > > +                     regmap_field_write(regmap_fields[GMAC0_USE_PWM01], 0);
> > > > > > > +                     break;
> > > > > > > +             case PHY_INTERFACE_MODE_MII:
> > > > > > > +                     regmap_field_write(regmap_fields[GMAC0_USE_TXCLK], 1);
> > > > > > > +                     regmap_field_write(regmap_fields[GMAC0_USE_PWM01], 1);
> > > > > > > +                     break;
> > > > > > > +             default:
> > > > > > > +                     dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
> > > > > > > +                             plat->phy_interface);
> > > > > > > +                     return -EOPNOTSUPP;
> > > > > > > +             }
> > > > > > > +
> > > > > > > +             regmap_field_write(regmap_fields[GMAC0_SHUT], 0);
> > > > > > > +     }
> > > > > > > +
> > > > > > > +     return 0;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static int ls1c_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
> > > > > > > +{
> > > > > > > +     struct ls1x_dwmac *dwmac = plat->bsp_priv;
> > > > > > > +     struct regmap_field **regmap_fields = dwmac->regmap_fields;
> > > > > > > +
> > > > > > > +     if (plat->phy_interface == PHY_INTERFACE_MODE_RMII) {
> > > > > > > +             regmap_field_write(regmap_fields[PHY_INTF_SELI], 0x4);
> > > > > > > +     } else {
> > > > > > > +             dev_err(dwmac->dev, "Unsupported PHY-mode %u\n",
> > > > > > > +                     plat->phy_interface);
> > > > > > > +             return -EOPNOTSUPP;
> > > > > > > +     }
> > > > > > > +
> > > > > > > +     regmap_field_write(regmap_fields[GMAC_SHUT], 0);
> > > > > > > +
> > > > > > > +     return 0;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static const struct ls1x_dwmac_syscon ls1b_dwmac_syscon = {
> > > > > > > +     .reg_fields = ls1b_dwmac_syscon_regfields,
> > > > > > > +     .nr_reg_fields = ARRAY_SIZE(ls1b_dwmac_syscon_regfields),
> > > > > > > +     .syscon_init = ls1b_dwmac_syscon_init,
> > > > > > > +};
> > > > > > > +
> > > > > > > +static const struct ls1x_dwmac_syscon ls1c_dwmac_syscon = {
> > > > > > > +     .reg_fields = ls1c_dwmac_syscon_regfields,
> > > > > > > +     .nr_reg_fields = ARRAY_SIZE(ls1c_dwmac_syscon_regfields),
> > > > > > > +     .syscon_init = ls1c_dwmac_syscon_init,
> > > > > > > +};
> > > > > > > +
> > > > > > > +static int ls1x_dwmac_init(struct platform_device *pdev, void *priv)
> > > > > > > +{
> > > > > > > +     struct ls1x_dwmac *dwmac = priv;
> > > > > > > +     int ret;
> > > > > > > +
> > > > > >
> > > > > > > +     ret = devm_regmap_field_bulk_alloc(dwmac->dev, dwmac->regmap,
> > > > > > > +                                        dwmac->regmap_fields,
> > > > > > > +                                        dwmac->syscon->reg_fields,
> > > > > > > +                                        dwmac->syscon->nr_reg_fields);
> > > > > >
> > > > > > Please see my first comment about this.
> > > > > >
> > > > > > > +     if (ret)
> > > > > > > +             return ret;
> > > > > > > +
> > > > > > > +     if (dwmac->syscon->syscon_init) {
> > > > > > > +             ret = dwmac->syscon->syscon_init(dwmac->plat_dat);
> > > > > > > +             if (ret)
> > > > > > > +                     return ret;
> > > > > > > +     }
> > > > > > > +
> > > > > > > +     return 0;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static const struct of_device_id ls1x_dwmac_syscon_match[] = {
> > > > > > > +     { .compatible = "loongson,ls1b-syscon", .data = &ls1b_dwmac_syscon },
> > > > > > > +     { .compatible = "loongson,ls1c-syscon", .data = &ls1c_dwmac_syscon },
> > > > > > > +     { }
> > > > > > > +};
> > > > > > > +
> > > > > > > +static int ls1x_dwmac_probe(struct platform_device *pdev)
> > > > > > > +{
> > > > > > > +     struct plat_stmmacenet_data *plat_dat;
> > > > > > > +     struct stmmac_resources stmmac_res;
> > > > > > > +     struct device_node *syscon_np;
> > > > > > > +     const struct of_device_id *match;
> > > > > > > +     struct regmap *regmap;
> > > > > > > +     struct ls1x_dwmac *dwmac;
> > > > > > > +     const struct ls1x_dwmac_syscon *syscon;
> > > > > > > +     size_t size;
> > > > > > > +     int ret;
> > > > > > > +
> > > > > > > +     ret = stmmac_get_platform_resources(pdev, &stmmac_res);
> > > > > > > +     if (ret)
> > > > > > > +             return ret;
> > > > > > > +
> > > > > >
> > > > > > > +     /* Probe syscon */
> > > > > > > +     syscon_np = of_parse_phandle(pdev->dev.of_node, "syscon", 0);
> > > > > >
> > > > > > it's vendor-specific property so it is supposed to have a
> > > > > > vendor-specific prefix and possibly ls1-specific name.
> > > > > >
> > > > > This has been fixed in v2.
> > > > > Could you please review v2?
> > > > > Thanks!
> > > > >
> > > > > > > +     if (!syscon_np)
> > > > > > > +             return -ENODEV;
> > > > > > > +
> > > > > > > +     match = of_match_node(ls1x_dwmac_syscon_match, syscon_np);
> > > > > > > +     if (!match) {
> > > > > > > +             of_node_put(syscon_np);
> > > > > > > +             return -EINVAL;
> > > > > > > +     }
> > > > > > > +     syscon = (const struct ls1x_dwmac_syscon *)match->data;
> > >
> >
> > > Please note that of_match_node() is used for syscon matching.
> >
> > I noticed it in the first place. Please see my next comment.
> >
> > >
> > > > > > > +
> > > > > > > +     regmap = syscon_node_to_regmap(syscon_np);
> > > > > > > +     of_node_put(syscon_np);
> > > > > > > +     if (IS_ERR(regmap)) {
> > > > > > > +             ret = PTR_ERR(regmap);
> > > > > > > +             dev_err(&pdev->dev, "Unable to map syscon: %d\n", ret);
> > > > > > > +             return ret;
> > > > > > > +     }
> > > > > >
> > > > > > or you can use syscon_regmap_lookup_by_phandle(). Using
> > > > > > of_match_node() doesn't seem necessary since it's unlikely to have
> > > > > > moee than one system controller available on the LS1b or LS1c chips.
> > > > > >
> > > >
> > > > > I planned to use syscon_regmap_lookup_by_phandle().
> > > > > Thus the compatible
> > > > > "loongson,ls1b-dwmac-syscon"/"loongson,ls1c-dwmac-syscon" would become
> > > > > useless.
> > > > > I'm not sure about this.
> > > >
> > > > The compatible strings should be left despite of the
> > > > syscon_regmap_lookup_by_phandle() usage. But again "dwmac" suffix is
> > > > redundant. Based on the CSRs definition in regs-mux.h, selecting
> > > > (G)MAC pins mode is only a small part of the Loongson1 SoC system
> > > > controllers functionality.
> > > > "loongson,ls1b-syscon"/"loongson,ls1c-syscon" looks more appropriate.
> > > >
> > > That's what I did in PATCH 2/5.
> > > I've just explained this to Krzysztof.
> > > And will change back to "loongson,ls1b-syscon"/"loongson,ls1c-syscon"
> > > in next version.
> > >
> >
> > > In addition, syscon_regmap_lookup_by_phandle() returns regmap pointer directly.
> > > Then, there wil be no way to do syscon matching without its device_node.
> > > How will I know whether the syscon is loongson,ls1b-syscon or
> > > loongson,ls1c-syscon?
> >
> > Do you have both of these syscons available in the same SoC? I don't
> > think so. Thus you don't need such validation since the LS1C SoC dts
> > file will have the "loongson,ls1c-syscon" syscon node defined only and
> > the LS1B SoC dts file - "loongson,ls1b-syscon" only.
> >

> I believe you have noticed the difference of syscon_init() between
> LS1B and LS1C.
> The syscon matching is for finding the right syscon_init().

There are other ways to select syscon_init(). Syscon node compatible
string is just one of them. You can do that by one of the next way:
1. Based on the syscon-property name: "loongson,ls1b-syscon" property
always points to the LS1B syscon phandle so the
ls1b_dwmac_syscon_init() function is supposed to be selected;
"loongson,ls1c-syscon" property always points to the LS1C syscon so
ls1c_dwmac_syscon_init() is supposed to be utilized.
2. Based on the MAC compatible string. loongson,ls1b-gmac can be found
on the LS1B SoC only which is equipped with the ls1b-syscon system
controller only so ls1b_dwmac_syscon_init() must be selected. Likewise
you can determine the init function on the LS1C SoC.

-Serge(y)

> 
> Thanks for your review!
> 
> > -Serge(y)
> >
> > >
> > > Thanks for your review!
> > >
> > >
> > >
> > >
> > >
> > > > -Serge(y)
> > > >
> > > > >
> > > > > > > +
> > > > > > > +     size = syscon->nr_reg_fields * sizeof(struct regmap_field *);
> > > > > > > +     dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac) + size, GFP_KERNEL);
> > > > > > > +     if (!dwmac)
> > > > > > > +             return -ENOMEM;
> > > > > > > +
> > > > > > > +     plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
> > > > > > > +     if (IS_ERR(plat_dat)) {
> > > > > > > +             dev_err(&pdev->dev, "dt configuration failed\n");
> > > > > > > +             return PTR_ERR(plat_dat);
> > > > > > > +     }
> > > > > > > +
> > > > > > > +     plat_dat->bsp_priv = dwmac;
> > > > > > > +     plat_dat->init = ls1x_dwmac_init;
> > > > > > > +     dwmac->dev = &pdev->dev;
> > > > > > > +     dwmac->plat_dat = plat_dat;
> > > > > > > +     dwmac->syscon = syscon;
> > > > > > > +     dwmac->regmap = regmap;
> > > > > > > +
> > > > > > > +     ret = stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res);
> > > > > > > +     if (ret)
> > > > > > > +             goto err_remove_config_dt;
> > > > > > > +
> > > > > > > +     return 0;
> > > > > > > +
> > > > > > > +err_remove_config_dt:
> > > > > >
> > > > > > > +     if (pdev->dev.of_node)
> > > > > >
> > > > > > Is this conditional statement necessary here?
> > > > > >
> > > > > You're right.
> > > > > Will remove this condition in next version.
> > > > > Thanks!
> > > > >
> > > > > > -Serge
> > > > > >
> > > > > > > +             stmmac_remove_config_dt(pdev, plat_dat);
> > > > > > > +
> > > > > > > +     return ret;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static const struct of_device_id ls1x_dwmac_match[] = {
> > > > > > > +     { .compatible = "loongson,ls1b-dwmac" },
> > > > > > > +     { .compatible = "loongson,ls1c-dwmac" },
> > > > > > > +     { }
> > > > > > > +};
> > > > > > > +MODULE_DEVICE_TABLE(of, ls1x_dwmac_match);
> > > > > > > +
> > > > > > > +static struct platform_driver ls1x_dwmac_driver = {
> > > > > > > +     .probe = ls1x_dwmac_probe,
> > > > > > > +     .remove_new = stmmac_pltfr_remove,
> > > > > > > +     .driver = {
> > > > > > > +             .name = "loongson1-dwmac",
> > > > > > > +             .of_match_table = ls1x_dwmac_match,
> > > > > > > +     },
> > > > > > > +};
> > > > > > > +module_platform_driver(ls1x_dwmac_driver);
> > > > > > > +
> > > > > > > +MODULE_AUTHOR("Keguang Zhang <keguang.zhang@gmail.com>");
> > > > > > > +MODULE_DESCRIPTION("Loongson1 DWMAC glue layer");
> > > > > > > +MODULE_LICENSE("GPL");
> > > > > > > --
> > > > > > > 2.39.2
> > > > > > >
> > > > >
> > > > >
> > > > >
> > > > > --
> > > > > Best regards,
> > > > >
> > > > > Keguang Zhang
> > >
> > >
> > >
> > > --
> > > Best regards,
> > >
> > > Keguang Zhang
> 
> 
> 
> -- 
> Best regards,
> 
> Keguang Zhang

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

* Re: [PATCH 4/5] net: stmmac: Add glue layer for Loongson-1 SoC
  2023-08-22 10:53               ` Serge Semin
@ 2023-08-22 12:09                 ` Keguang Zhang
  2023-08-22 14:20                   ` Serge Semin
  0 siblings, 1 reply; 28+ messages in thread
From: Keguang Zhang @ 2023-08-22 12:09 UTC (permalink / raw)
  To: Serge Semin
  Cc: netdev, devicetree, linux-mips, linux-kernel, Lee Jones,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, David S . Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Thomas Bogendoerfer,
	Giuseppe Cavallaro, Alexandre Torgue, Jose Abreu, Serge Semin

On Tue, Aug 22, 2023 at 6:53 PM Serge Semin <fancer.lancer@gmail.com> wrote:
>
> On Tue, Aug 22, 2023 at 03:58:32PM +0800, Keguang Zhang wrote:
> > On Mon, Aug 21, 2023 at 10:16 PM Serge Semin <fancer.lancer@gmail.com> wrote:
> > >
> > > On Mon, Aug 21, 2023 at 09:24:17PM +0800, Keguang Zhang wrote:
> > > > On Sat, Aug 19, 2023 at 12:19 AM Serge Semin <fancer.lancer@gmail.com> wrote:
> > > > >
> > > > > On Fri, Aug 18, 2023 at 08:37:27PM +0800, Keguang Zhang wrote:
> > > > > > On Wed, Aug 16, 2023 at 9:30 PM Serge Semin <fancer.lancer@gmail.com> wrote:
> > > > > > >
> > > > > > > On Sat, Aug 12, 2023 at 11:11:34PM +0800, Keguang Zhang wrote:
> > > > > > > > This glue driver is created based on the arch-code
> > > > > > > > implemented earlier with the platform-specific settings.
> > > > > > > >
> > > > > > > > Use syscon for SYSCON register access.
> > > > > > > >
> > > > > > > > Partialy based on the previous work by Serge Semin.
> > > > > > > >
> > > > > > > > Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
> > > > > > > > ---
> > > > > > > >  drivers/net/ethernet/stmicro/stmmac/Kconfig   |  11 +
> > > > > > > >  drivers/net/ethernet/stmicro/stmmac/Makefile  |   1 +
> > > > > > > >  .../ethernet/stmicro/stmmac/dwmac-loongson1.c | 257 ++++++++++++++++++
> > > > > > > >  3 files changed, 269 insertions(+)
> > > > > > > >  create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> > > > > > > >
> > > > > > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> > > > > > > > index 06c6871f8788..a2b9e289aa36 100644
> > > > > > > > --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
> > > > > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> > > > > > > > @@ -239,6 +239,17 @@ config DWMAC_INTEL_PLAT
> > > > > > > >         the stmmac device driver. This driver is used for the Intel Keem Bay
> > > > > > > >         SoC.
> > > > > > > >
> > > > > > > > +config DWMAC_LOONGSON1
> > > > > > > > +     tristate "Loongson1 GMAC support"
> > > > > > > > +     default MACH_LOONGSON32
> > > > > > > > +     depends on OF && (MACH_LOONGSON32 || COMPILE_TEST)
> > > > > > > > +     help
> > > > > > > > +       Support for ethernet controller on Loongson1 SoC.
> > > > > > > > +
> > > > > > > > +       This selects Loongson1 SoC glue layer support for the stmmac
> > > > > > > > +       device driver. This driver is used for Loongson1-based boards
> > > > > > > > +       like Loongson LS1B/LS1C.
> > > > > > > > +
> > > > > > > >  config DWMAC_TEGRA
> > > > > > > >       tristate "NVIDIA Tegra MGBE support"
> > > > > > > >       depends on ARCH_TEGRA || COMPILE_TEST
> > > > > > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
> > > > > > > > index 5b57aee19267..80e598bd4255 100644
> > > > > > > > --- a/drivers/net/ethernet/stmicro/stmmac/Makefile
> > > > > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
> > > > > > > > @@ -29,6 +29,7 @@ obj-$(CONFIG_DWMAC_SUNXI)   += dwmac-sunxi.o
> > > > > > > >  obj-$(CONFIG_DWMAC_SUN8I)    += dwmac-sun8i.o
> > > > > > > >  obj-$(CONFIG_DWMAC_DWC_QOS_ETH)      += dwmac-dwc-qos-eth.o
> > > > > > > >  obj-$(CONFIG_DWMAC_INTEL_PLAT)       += dwmac-intel-plat.o
> > > > > > > > +obj-$(CONFIG_DWMAC_LOONGSON1)        += dwmac-loongson1.o
> > > > > > > >  obj-$(CONFIG_DWMAC_GENERIC)  += dwmac-generic.o
> > > > > > > >  obj-$(CONFIG_DWMAC_IMX8)     += dwmac-imx.o
> > > > > > > >  obj-$(CONFIG_DWMAC_TEGRA)    += dwmac-tegra.o
> > > > > > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> > > > > > > > new file mode 100644
> > > > > > > > index 000000000000..368d6cd2cb78
> > > > > > > > --- /dev/null
> > > > > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> > > > > > > > @@ -0,0 +1,257 @@
> > > > > > > > +// SPDX-License-Identifier: GPL-2.0-or-later
> > > > > > > > +/*
> > > > > > > > + * Loongson-1 DWMAC glue layer
> > > > > > > > + *
> > > > > > > > + * Copyright (C) 2011-2023 Keguang Zhang <keguang.zhang@gmail.com>
> > > > > > > > + */
> > > > > > > > +
> > > > > > > > +#include <linux/mfd/syscon.h>
> > > > > > > > +#include <linux/module.h>
> > > > > > > > +#include <linux/phy.h>
> > > > > > > > +#include <linux/platform_device.h>
> > > > > > > > +#include <linux/regmap.h>
> > > > > > > > +
> > > > > > > > +#include "stmmac.h"
> > > > > > > > +#include "stmmac_platform.h"
> > > > > > > > +
> > > > > > > > +/* Loongson-1 SYSCON Registers */
> > > > > > > > +#define LS1X_SYSCON0         (0x0)
> > > > > > > > +#define LS1X_SYSCON1         (0x4)
> > > > > > > > +
> > > > > > > > +struct ls1x_dwmac_syscon {
> > > > > > > > +     const struct reg_field *reg_fields;
> > > > > > > > +     unsigned int nr_reg_fields;
> > > > > > > > +     int (*syscon_init)(struct plat_stmmacenet_data *plat);
> > > > > > > > +};
> > > > > > > > +
> > > > > > > > +struct ls1x_dwmac {
> > > > > > > > +     struct device *dev;
> > > > > > > > +     struct plat_stmmacenet_data *plat_dat;
> > > > > > > > +     const struct ls1x_dwmac_syscon *syscon;
> > > > > > > > +     struct regmap *regmap;
> > > > > > > > +     struct regmap_field *regmap_fields[];
> > > > > > > > +};
> > > > > > > > +
> > > > > > > > +enum ls1b_dwmac_syscon_regfield {
> > > > > > > > +     GMAC1_USE_UART1,
> > > > > > > > +     GMAC1_USE_UART0,
> > > > > > > > +     GMAC1_SHUT,
> > > > > > > > +     GMAC0_SHUT,
> > > > > > > > +     GMAC1_USE_TXCLK,
> > > > > > > > +     GMAC0_USE_TXCLK,
> > > > > > > > +     GMAC1_USE_PWM23,
> > > > > > > > +     GMAC0_USE_PWM01,
> > > > > > > > +};
> > > > > > > > +
> > > > > > > > +enum ls1c_dwmac_syscon_regfield {
> > > > > > > > +     GMAC_SHUT,
> > > > > > > > +     PHY_INTF_SELI,
> > > > > > > > +};
> > > > > > > > +
> > > > > > > > +const struct reg_field ls1b_dwmac_syscon_regfields[] = {
> > > > > > > > +     [GMAC1_USE_UART1]       = REG_FIELD(LS1X_SYSCON0, 4, 4),
> > > > > > > > +     [GMAC1_USE_UART0]       = REG_FIELD(LS1X_SYSCON0, 3, 3),
> > > > > > > > +     [GMAC1_SHUT]            = REG_FIELD(LS1X_SYSCON1, 13, 13),
> > > > > > > > +     [GMAC0_SHUT]            = REG_FIELD(LS1X_SYSCON1, 12, 12),
> > > > > > > > +     [GMAC1_USE_TXCLK]       = REG_FIELD(LS1X_SYSCON1, 3, 3),
> > > > > > > > +     [GMAC0_USE_TXCLK]       = REG_FIELD(LS1X_SYSCON1, 2, 2),
> > > > > > > > +     [GMAC1_USE_PWM23]       = REG_FIELD(LS1X_SYSCON1, 1, 1),
> > > > > > > > +     [GMAC0_USE_PWM01]       = REG_FIELD(LS1X_SYSCON1, 0, 0)
> > > > > > > > +};
> > > > > > > > +
> > > > > > > > +const struct reg_field ls1c_dwmac_syscon_regfields[] = {
> > > > > > > > +     [GMAC_SHUT]             = REG_FIELD(LS1X_SYSCON0, 6, 6),
> > > > > > > > +     [PHY_INTF_SELI]         = REG_FIELD(LS1X_SYSCON1, 28, 30)
> > > > > > > > +};
> > > > > > >
> > > > > > > Emm, using regmap fields looks so over-complicated in this case seeing
> > > > > > > you only need to set/clear several bits in the syscon. What about
> > > > > > > defining macros with the particular flag as it's already done in the
> > > > > > > "asm/mach-loongson32/regs-mux.h" file and using regmap_update_bits()?
> > > > > > >
> > > > >
> > > > > > To use regmap_update_bits(), I have to store and pass reg_offset and
> > > > > > mask, which is similar to the definition of regmap fields.
> > > > >
> > > > > Em, not really. And what offset are you talking about? Anyway you
> > > > > don't need one. Moreover you'll be able to reduce the number of IOs:
> > > > >
> > > > > +#define GMAC1_USE_UART1                 BIT(4)
> > > > > +#define GMAC1_USE_UART0                 BIT(3)
> > > > > ...
> > > > > +#define GMAC1_SHUT                      BIT(13)
> > > > > ...
> > > > > +#define GMAC1_USE_TXCLK                 BIT(3)
> > > > > +#define GMAC1_USE_PWM23                 BIT(1)
> > > > >
> > > > > +static int ls1b_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
> > > > > +{
> > > > > +       struct ls1x_dwmac *dwmac = plat->bsp_priv;
> > > > > +       struct regmap *syscon = dwmac->regmap;
> > > > > +
> > > > > +       if (plat->bus_id) {
> > > > > +               regmap_update_bits(syscon, LS1X_SYSCON0,
> > > > > +                                  GMAC1_USE_UART1 | GMAC1_USE_UART0,
> > > > > +                                  GMAC1_USE_UART1 | GMAC1_USE_UART0);
> > > > > +
> > > > > +               switch (plat->phy_interface) {
> > > > > +               case PHY_INTERFACE_MODE_RGMII:
> > > > > +                       regmap_update_bits(syscon, LS1X_SYSCON1,
> > > > > +                                          GMAC1_USE_TXCLK | GMAC1_USE_TXCLK, 0);
> > > > > +                       break;
> > > > > +               case PHY_INTERFACE_MODE_MII:
> > > > > +                       regmap_update_bits(syscon, LS1X_SYSCON1,
> > > > > +                                          GMAC1_USE_TXCLK | GMAC1_USE_TXCLK
> > > > > +                                          GMAC1_USE_TXCLK | GMAC1_USE_TXCLK);
> > > > > +                       break;
> > > > > +               default:
> > > > > +                       dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
> > > > > +                               plat->phy_interface);
> > > > > +                       return -EOPNOTSUPP;
> > > > > +               }
> > > > > +
> > > > > +               regmap_field_write(syscon, LS1X_SYSCON1, GMAC1_SHUT, 0);
> > > > > +       } //...
> > > > > +
> > > > > +       return 0;
> > > > > +}
> > > > >
> > > > > This doesn't look in anyway less readable then your implementation
> > > > > but in fact simpler.
> > > > >
> > > > > > In addition, the regmap fields are very clear and leave the trouble to
> > > > > > the internal implementation.
> > > > >
> > > > > In this case it brings much more troubles and no clarity. You need to create
> > > > > an additional mainly redundant abstraction, waste memory for it,
> > > > > define additional const arrays. Using it won't improve the code
> > > > > readability seeing you need to set/clear a few flags only. So all of
> > > > > the troubles for nothing. See the code above. It's simple and clear.
> > > > > Just several regmap_update_bits()..
> > > > >
> > > > OK. I will use regmap instead of regmap fields.
> > > >
> > > > > BTW why have you chosen to define syscon instead of creating a pinctrl
> > > > > driver? What if Loongson1 is embedded into a platform with, for
> > > > > instance, UART0 and UART1 utilized instead of the GMAC1?
> > > > >
> > >
> > > > As you can see, the two registers contains miscellaneous settings.
> > > > Besides ‘USE’ bits, there are ‘RESET‘ bits, 'EN' bits, 'SHUT' bits, ...
> > > > So they are not pinctrl registers.
> > >
> > > You could have defined a device node which would export "reset",
> > > "power" and "pinctrl" functionality, like it's normally done for the
> > > RCU devices (Reset and Clock unit devices).
> > >
> > > > Actually, there is a dedicated pin controller which controls the
> > > > multiplexing of pads.
> > >
> > > Do you mean that there is another controller in the Loongson1 SoC
> > > which controls the pads multiplexing?
> > >
> > Yes. There is another contoller that really controls the pads multiplexing.
> >
> > > If so what is the purpose of the GMAC1_USE_UART1, GMAC1_USE_UART0 and
> > > GMAC1_USE_TXCLK, GMAC1_USE_PWM23 flags in MUX controller then? Is it
> > > just another pinctl space with additional reset/power controls or what?
> > >
>
> > From my perspective, these ‘USE’ bits should be regarded as
> > device/module multiplexing rather than pads multiplexing.
>
> Could you elaborate what does "device/module multiplexing" mean?
>
Pherhaps the device switch is more accurate.
Just means which devices could not work at the time.

> > Although the two registers were called MUX_CTRL in LS1B datasheet,
> > they had beed renamed to MISC_CTRL in LS1C datasheet.
> > So it is supposed to be considered syscon.
> > > >
> > > > > >
> > > > > > > > +
> > > > > > >
> > > > > > > > +static int ls1b_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
> > > > > > > > +{
> > > > > > >
> > > > > > > As I already told you this part is better to be called from the
> > > > > > > plat_stmmacenet_data.fix_mac_speed() because PHY interface mode can
> > > > > > > differ from one interface open cycle to another as per the phylink
> > > > > > > design.
> > > > > > >
> > > > > > I have considered .fix_mac_speed(), which will be called every time
> > > > > > the link is up, and passes the current speed.
> > > > > > However, the PHY interface mode is determined by the hardware design -
> > > > > > the schematic.
> > > > > > In other words, once the schematic is done, the PHY interface mode is fixed.
> > > > > > Therefore, PHY interface mode should be configured one time at the
> > > > > > initialization.
> > > > > > And the plat_stmmacenet_data.init() is the proper place to do this.
> > > > >
> > > > > Ok. If no actual clock change is needed then indeed init() will be the
> > > > > proper place.
> > > > >
> > > > > >
> > > > > > > > +     struct ls1x_dwmac *dwmac = plat->bsp_priv;
> > > > > > > > +     struct regmap_field **regmap_fields = dwmac->regmap_fields;
> > > > > > > > +
> > > > > > >
> > > > > > > > +     if (plat->bus_id) {
> > > > > > >
> > > > > > > Using bus_id doesn't look correct to determine the CSRs responsible
> > > > > > > for the interface mode selection because it's calculated based on the
> > > > > > > DT ethernet-alias which doesn't guarantee to have a particular device
> > > > > > > assigned with the alias. Alias node can be absent after all. What
> > > > > > > could be better in this case is for instance to use the regs physical
> > > > > > > address. Any better idea?
> > > > > > >
> > > > >
> > > > > > The purpose of alias is to bind the a particular device with a
> > > > > > particular alias even some aliases are absent.
> > > > > > Because of_alias_get_id() gets the alias id.
> > > > > > For example, LS1B has two GMAC controllers, gmac0 and gmac1.
> > > > > > I have tried the Ethernet with only one alias as follows.
> > > > > >        aliases {
> > > > > >                ethernet1 = &gmac1;
> > > > > >        };
> > > > > > In this case, plat->bus_id is still 1.
> > > > > > And both gmac0 and gmac1 work.
> > > > >
> > > > > If no alias specified? If both aliases a non zero? If the IDs are
> > > > > confused? If any of these is true you are in trouble. Your code
> > > > > shouldn't rely on the aliases in this case. You need to come up with a
> > > > > way to certainly distinguish one MAC from another. A physical base
> > > > > address is one possible option.
> > > > >
> > >
> > > > I see.
> > > > But It seems unusual to determine device IDs by physical base address.
> > > > What about adding a new property? such as loongson,dwmac-id
> > >
> > > IMO It's better to have a DT-property-independent way for it. If I
> > > were you I would have utilized the reg-space
> > > physical-base-address-based approach since you need to have it
> > > specified anyway and it determines the particular MAC for sure.
> > > Thus your driver won't be dependent in the device tree in that aspect.
> > >
>
> > The physical base address may vary from SoC to SoC.
>
> You've got only two SoCs, right? LS1C and LS1B. Each of them has
> a specific set of NICs: two loongson,ls1b-gmac on LS1B and
> one loongson,ls1c-mac on LS1C. So LS1B has only two physical addresses
> you can use to distinguish one interface from another and find out
> what flags to toggle in the syscon. LS1C has a single MAC so you won't
> even need any additional info since there is only one flag to
> toggle.
>
Is there any driver that uses the physical-base-address way?
Could you provide me some existing examples?
Thanks!

> Physical address is constant from one LS1C instance to another, and
> similarly from one LS1B instance to another. It's defined by means
> of the macros:
> LS1X_GMAC0_BASE
> LS1X_GMAC1_BASE
> What physical address varying are you talking about? I don't see that
> in the current platform driver.
>
> > It means that the driver has to remember MAC base addresses for different SoCs.
>
> Yes. Just two physical addresses.
>
Two chips for now.
What about the future chips?
> >
> > > Some DW *MAC drivers pass additional number to the syscon phandle node
> > > in the syscon-property to identify the MAC on the board, like
> > > dwmac-socfpga.c or dwmac-sti.c. If you get to implement a similar way
> > > then you'll need to have the DT-bindings properly describing that. But
> > > IMO my approach seems less clumsy and simpler.
> > >
>
> > I prefer the DT-bindings property way. At least many off-the-shelf
> > examples can be found.
>
> Just two examples with not the best solution implemented.
>
> Anyway it's up to you to decide after all. I don't mind if it will be
> the property-based way. But as for me it looks redundant seeing there
> is base address always available and which you can utilise. Moreover
> if you get to add any new Loongson MAC to the driver you'll need to
> update it anyway at least in a way the syscon flags are toggled. So
> even from that perspective using the physical base address seems as at
> least the equally complex and maintainable solution.
>
> >
> > > >
> > > > > Note the /alias node is an informational node. It doesn't describe
> > > > > devices. Just recent Krzysztof comment in a similar situation:
> > > > > https://lore.kernel.org/netdev/20230814112539.70453-1-sriranjani.p@samsung.com/T/#m3972e40bd2fa323a3bdb2fbf07bde47ba6752439
> > > > >
> > > > > Aliases are normally used by OS to for instance fix the device
> > > > > enumeration (see SPI, I2C, I3C, MTD, MMC, RTC, TTY/Serial, Watchdog,
> > > > > MDIO-GPIO, etc) - pre-define the device ID from the kernel or OS point
> > > > > of view. In your case the IDs can't be changed. GMAC0 must be assigned
> > > > > with ID0 and GMAC1 must be assigned with non-zero. Doing otherwise
> > > > > will be break the interfaces functionality which isn't acceptable.
> > > > >
> > > > > >
> > > > > > > > +             regmap_field_write(regmap_fields[GMAC1_USE_UART1], 1);
> > > > > > > > +             regmap_field_write(regmap_fields[GMAC1_USE_UART0], 1);
> > > > > > > > +
> > > > > > > > +             switch (plat->phy_interface) {
> > > > > > > > +             case PHY_INTERFACE_MODE_RGMII:
> > > > > > > > +                     regmap_field_write(regmap_fields[GMAC1_USE_TXCLK], 0);
> > > > > > > > +                     regmap_field_write(regmap_fields[GMAC1_USE_PWM23], 0);
> > > > > > > > +                     break;
> > > > > > > > +             case PHY_INTERFACE_MODE_MII:
> > > > > > > > +                     regmap_field_write(regmap_fields[GMAC1_USE_TXCLK], 1);
> > > > > > > > +                     regmap_field_write(regmap_fields[GMAC1_USE_PWM23], 1);
> > > > > > > > +                     break;
> > > > > > > > +             default:
> > > > > > > > +                     dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
> > > > > > > > +                             plat->phy_interface);
> > > > > > > > +                     return -EOPNOTSUPP;
> > > > > > > > +             }
> > > > > > > > +
> > > > > > > > +             regmap_field_write(regmap_fields[GMAC1_SHUT], 0);
> > > > > > > > +     } else {
> > > > > > > > +             switch (plat->phy_interface) {
> > > > > > > > +             case PHY_INTERFACE_MODE_RGMII:
> > > > > > > > +                     regmap_field_write(regmap_fields[GMAC0_USE_TXCLK], 0);
> > > > > > > > +                     regmap_field_write(regmap_fields[GMAC0_USE_PWM01], 0);
> > > > > > > > +                     break;
> > > > > > > > +             case PHY_INTERFACE_MODE_MII:
> > > > > > > > +                     regmap_field_write(regmap_fields[GMAC0_USE_TXCLK], 1);
> > > > > > > > +                     regmap_field_write(regmap_fields[GMAC0_USE_PWM01], 1);
> > > > > > > > +                     break;
> > > > > > > > +             default:
> > > > > > > > +                     dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
> > > > > > > > +                             plat->phy_interface);
> > > > > > > > +                     return -EOPNOTSUPP;
> > > > > > > > +             }
> > > > > > > > +
> > > > > > > > +             regmap_field_write(regmap_fields[GMAC0_SHUT], 0);
> > > > > > > > +     }
> > > > > > > > +
> > > > > > > > +     return 0;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +static int ls1c_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
> > > > > > > > +{
> > > > > > > > +     struct ls1x_dwmac *dwmac = plat->bsp_priv;
> > > > > > > > +     struct regmap_field **regmap_fields = dwmac->regmap_fields;
> > > > > > > > +
> > > > > > > > +     if (plat->phy_interface == PHY_INTERFACE_MODE_RMII) {
> > > > > > > > +             regmap_field_write(regmap_fields[PHY_INTF_SELI], 0x4);
> > > > > > > > +     } else {
> > > > > > > > +             dev_err(dwmac->dev, "Unsupported PHY-mode %u\n",
> > > > > > > > +                     plat->phy_interface);
> > > > > > > > +             return -EOPNOTSUPP;
> > > > > > > > +     }
> > > > > > > > +
> > > > > > > > +     regmap_field_write(regmap_fields[GMAC_SHUT], 0);
> > > > > > > > +
> > > > > > > > +     return 0;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +static const struct ls1x_dwmac_syscon ls1b_dwmac_syscon = {
> > > > > > > > +     .reg_fields = ls1b_dwmac_syscon_regfields,
> > > > > > > > +     .nr_reg_fields = ARRAY_SIZE(ls1b_dwmac_syscon_regfields),
> > > > > > > > +     .syscon_init = ls1b_dwmac_syscon_init,
> > > > > > > > +};
> > > > > > > > +
> > > > > > > > +static const struct ls1x_dwmac_syscon ls1c_dwmac_syscon = {
> > > > > > > > +     .reg_fields = ls1c_dwmac_syscon_regfields,
> > > > > > > > +     .nr_reg_fields = ARRAY_SIZE(ls1c_dwmac_syscon_regfields),
> > > > > > > > +     .syscon_init = ls1c_dwmac_syscon_init,
> > > > > > > > +};
> > > > > > > > +
> > > > > > > > +static int ls1x_dwmac_init(struct platform_device *pdev, void *priv)
> > > > > > > > +{
> > > > > > > > +     struct ls1x_dwmac *dwmac = priv;
> > > > > > > > +     int ret;
> > > > > > > > +
> > > > > > >
> > > > > > > > +     ret = devm_regmap_field_bulk_alloc(dwmac->dev, dwmac->regmap,
> > > > > > > > +                                        dwmac->regmap_fields,
> > > > > > > > +                                        dwmac->syscon->reg_fields,
> > > > > > > > +                                        dwmac->syscon->nr_reg_fields);
> > > > > > >
> > > > > > > Please see my first comment about this.
> > > > > > >
> > > > > > > > +     if (ret)
> > > > > > > > +             return ret;
> > > > > > > > +
> > > > > > > > +     if (dwmac->syscon->syscon_init) {
> > > > > > > > +             ret = dwmac->syscon->syscon_init(dwmac->plat_dat);
> > > > > > > > +             if (ret)
> > > > > > > > +                     return ret;
> > > > > > > > +     }
> > > > > > > > +
> > > > > > > > +     return 0;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +static const struct of_device_id ls1x_dwmac_syscon_match[] = {
> > > > > > > > +     { .compatible = "loongson,ls1b-syscon", .data = &ls1b_dwmac_syscon },
> > > > > > > > +     { .compatible = "loongson,ls1c-syscon", .data = &ls1c_dwmac_syscon },
> > > > > > > > +     { }
> > > > > > > > +};
> > > > > > > > +
> > > > > > > > +static int ls1x_dwmac_probe(struct platform_device *pdev)
> > > > > > > > +{
> > > > > > > > +     struct plat_stmmacenet_data *plat_dat;
> > > > > > > > +     struct stmmac_resources stmmac_res;
> > > > > > > > +     struct device_node *syscon_np;
> > > > > > > > +     const struct of_device_id *match;
> > > > > > > > +     struct regmap *regmap;
> > > > > > > > +     struct ls1x_dwmac *dwmac;
> > > > > > > > +     const struct ls1x_dwmac_syscon *syscon;
> > > > > > > > +     size_t size;
> > > > > > > > +     int ret;
> > > > > > > > +
> > > > > > > > +     ret = stmmac_get_platform_resources(pdev, &stmmac_res);
> > > > > > > > +     if (ret)
> > > > > > > > +             return ret;
> > > > > > > > +
> > > > > > >
> > > > > > > > +     /* Probe syscon */
> > > > > > > > +     syscon_np = of_parse_phandle(pdev->dev.of_node, "syscon", 0);
> > > > > > >
> > > > > > > it's vendor-specific property so it is supposed to have a
> > > > > > > vendor-specific prefix and possibly ls1-specific name.
> > > > > > >
> > > > > > This has been fixed in v2.
> > > > > > Could you please review v2?
> > > > > > Thanks!
> > > > > >
> > > > > > > > +     if (!syscon_np)
> > > > > > > > +             return -ENODEV;
> > > > > > > > +
> > > > > > > > +     match = of_match_node(ls1x_dwmac_syscon_match, syscon_np);
> > > > > > > > +     if (!match) {
> > > > > > > > +             of_node_put(syscon_np);
> > > > > > > > +             return -EINVAL;
> > > > > > > > +     }
> > > > > > > > +     syscon = (const struct ls1x_dwmac_syscon *)match->data;
> > > >
> > >
> > > > Please note that of_match_node() is used for syscon matching.
> > >
> > > I noticed it in the first place. Please see my next comment.
> > >
> > > >
> > > > > > > > +
> > > > > > > > +     regmap = syscon_node_to_regmap(syscon_np);
> > > > > > > > +     of_node_put(syscon_np);
> > > > > > > > +     if (IS_ERR(regmap)) {
> > > > > > > > +             ret = PTR_ERR(regmap);
> > > > > > > > +             dev_err(&pdev->dev, "Unable to map syscon: %d\n", ret);
> > > > > > > > +             return ret;
> > > > > > > > +     }
> > > > > > >
> > > > > > > or you can use syscon_regmap_lookup_by_phandle(). Using
> > > > > > > of_match_node() doesn't seem necessary since it's unlikely to have
> > > > > > > moee than one system controller available on the LS1b or LS1c chips.
> > > > > > >
> > > > >
> > > > > > I planned to use syscon_regmap_lookup_by_phandle().
> > > > > > Thus the compatible
> > > > > > "loongson,ls1b-dwmac-syscon"/"loongson,ls1c-dwmac-syscon" would become
> > > > > > useless.
> > > > > > I'm not sure about this.
> > > > >
> > > > > The compatible strings should be left despite of the
> > > > > syscon_regmap_lookup_by_phandle() usage. But again "dwmac" suffix is
> > > > > redundant. Based on the CSRs definition in regs-mux.h, selecting
> > > > > (G)MAC pins mode is only a small part of the Loongson1 SoC system
> > > > > controllers functionality.
> > > > > "loongson,ls1b-syscon"/"loongson,ls1c-syscon" looks more appropriate.
> > > > >
> > > > That's what I did in PATCH 2/5.
> > > > I've just explained this to Krzysztof.
> > > > And will change back to "loongson,ls1b-syscon"/"loongson,ls1c-syscon"
> > > > in next version.
> > > >
> > >
> > > > In addition, syscon_regmap_lookup_by_phandle() returns regmap pointer directly.
> > > > Then, there wil be no way to do syscon matching without its device_node.
> > > > How will I know whether the syscon is loongson,ls1b-syscon or
> > > > loongson,ls1c-syscon?
> > >
> > > Do you have both of these syscons available in the same SoC? I don't
> > > think so. Thus you don't need such validation since the LS1C SoC dts
> > > file will have the "loongson,ls1c-syscon" syscon node defined only and
> > > the LS1B SoC dts file - "loongson,ls1b-syscon" only.
> > >
>
> > I believe you have noticed the difference of syscon_init() between
> > LS1B and LS1C.
> > The syscon matching is for finding the right syscon_init().
>
> There are other ways to select syscon_init(). Syscon node compatible
> string is just one of them. You can do that by one of the next way:
> 1. Based on the syscon-property name: "loongson,ls1b-syscon" property
> always points to the LS1B syscon phandle so the
> ls1b_dwmac_syscon_init() function is supposed to be selected;
> "loongson,ls1c-syscon" property always points to the LS1C syscon so
> ls1c_dwmac_syscon_init() is supposed to be utilized.
> 2. Based on the MAC compatible string. loongson,ls1b-gmac can be found
> on the LS1B SoC only which is equipped with the ls1b-syscon system
> controller only so ls1b_dwmac_syscon_init() must be selected. Likewise
> you can determine the init function on the LS1C SoC.
>
OK. I once used the second way for my draft version.
static const struct of_device_id ls1x_dwmac_match[] = {
       { .compatible = "loongson,ls1b-gmac", .data = &ls1b_dwmac_syscon, },
       { .compatible = "loongson,ls1c-mac" .data = &ls1c_dwmac_syscon,
},
       { }
};
Then, I will change back to this implementation in the next version.

> -Serge(y)
>
> >
> > Thanks for your review!
> >
> > > -Serge(y)
> > >
> > > >
> > > > Thanks for your review!
> > > >
> > > >
> > > >
> > > >
> > > >
> > > > > -Serge(y)
> > > > >
> > > > > >
> > > > > > > > +
> > > > > > > > +     size = syscon->nr_reg_fields * sizeof(struct regmap_field *);
> > > > > > > > +     dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac) + size, GFP_KERNEL);
> > > > > > > > +     if (!dwmac)
> > > > > > > > +             return -ENOMEM;
> > > > > > > > +
> > > > > > > > +     plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
> > > > > > > > +     if (IS_ERR(plat_dat)) {
> > > > > > > > +             dev_err(&pdev->dev, "dt configuration failed\n");
> > > > > > > > +             return PTR_ERR(plat_dat);
> > > > > > > > +     }
> > > > > > > > +
> > > > > > > > +     plat_dat->bsp_priv = dwmac;
> > > > > > > > +     plat_dat->init = ls1x_dwmac_init;
> > > > > > > > +     dwmac->dev = &pdev->dev;
> > > > > > > > +     dwmac->plat_dat = plat_dat;
> > > > > > > > +     dwmac->syscon = syscon;
> > > > > > > > +     dwmac->regmap = regmap;
> > > > > > > > +
> > > > > > > > +     ret = stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res);
> > > > > > > > +     if (ret)
> > > > > > > > +             goto err_remove_config_dt;
> > > > > > > > +
> > > > > > > > +     return 0;
> > > > > > > > +
> > > > > > > > +err_remove_config_dt:
> > > > > > >
> > > > > > > > +     if (pdev->dev.of_node)
> > > > > > >
> > > > > > > Is this conditional statement necessary here?
> > > > > > >
> > > > > > You're right.
> > > > > > Will remove this condition in next version.
> > > > > > Thanks!
> > > > > >
> > > > > > > -Serge
> > > > > > >
> > > > > > > > +             stmmac_remove_config_dt(pdev, plat_dat);
> > > > > > > > +
> > > > > > > > +     return ret;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +static const struct of_device_id ls1x_dwmac_match[] = {
> > > > > > > > +     { .compatible = "loongson,ls1b-dwmac" },
> > > > > > > > +     { .compatible = "loongson,ls1c-dwmac" },
> > > > > > > > +     { }
> > > > > > > > +};
> > > > > > > > +MODULE_DEVICE_TABLE(of, ls1x_dwmac_match);
> > > > > > > > +
> > > > > > > > +static struct platform_driver ls1x_dwmac_driver = {
> > > > > > > > +     .probe = ls1x_dwmac_probe,
> > > > > > > > +     .remove_new = stmmac_pltfr_remove,
> > > > > > > > +     .driver = {
> > > > > > > > +             .name = "loongson1-dwmac",
> > > > > > > > +             .of_match_table = ls1x_dwmac_match,
> > > > > > > > +     },
> > > > > > > > +};
> > > > > > > > +module_platform_driver(ls1x_dwmac_driver);
> > > > > > > > +
> > > > > > > > +MODULE_AUTHOR("Keguang Zhang <keguang.zhang@gmail.com>");
> > > > > > > > +MODULE_DESCRIPTION("Loongson1 DWMAC glue layer");
> > > > > > > > +MODULE_LICENSE("GPL");
> > > > > > > > --
> > > > > > > > 2.39.2
> > > > > > > >
> > > > > >
> > > > > >
> > > > > >
> > > > > > --
> > > > > > Best regards,
> > > > > >
> > > > > > Keguang Zhang
> > > >
> > > >
> > > >
> > > > --
> > > > Best regards,
> > > >
> > > > Keguang Zhang
> >
> >
> >
> > --
> > Best regards,
> >
> > Keguang Zhang



-- 
Best regards,

Keguang Zhang

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

* Re: [PATCH 4/5] net: stmmac: Add glue layer for Loongson-1 SoC
  2023-08-22 12:09                 ` Keguang Zhang
@ 2023-08-22 14:20                   ` Serge Semin
  0 siblings, 0 replies; 28+ messages in thread
From: Serge Semin @ 2023-08-22 14:20 UTC (permalink / raw)
  To: Keguang Zhang
  Cc: netdev, devicetree, linux-mips, linux-kernel, Lee Jones,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, David S . Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Thomas Bogendoerfer,
	Giuseppe Cavallaro, Alexandre Torgue, Jose Abreu, Serge Semin

On Tue, Aug 22, 2023 at 08:09:12PM +0800, Keguang Zhang wrote:
> On Tue, Aug 22, 2023 at 6:53 PM Serge Semin <fancer.lancer@gmail.com> wrote:
> >
> > On Tue, Aug 22, 2023 at 03:58:32PM +0800, Keguang Zhang wrote:
> > > On Mon, Aug 21, 2023 at 10:16 PM Serge Semin <fancer.lancer@gmail.com> wrote:
> > > >
> > > > On Mon, Aug 21, 2023 at 09:24:17PM +0800, Keguang Zhang wrote:
> > > > > On Sat, Aug 19, 2023 at 12:19 AM Serge Semin <fancer.lancer@gmail.com> wrote:
> > > > > >
> > > > > > On Fri, Aug 18, 2023 at 08:37:27PM +0800, Keguang Zhang wrote:
> > > > > > > On Wed, Aug 16, 2023 at 9:30 PM Serge Semin <fancer.lancer@gmail.com> wrote:
> > > > > > > >
> > > > > > > > On Sat, Aug 12, 2023 at 11:11:34PM +0800, Keguang Zhang wrote:
> > > > > > > > > This glue driver is created based on the arch-code
> > > > > > > > > implemented earlier with the platform-specific settings.
> > > > > > > > >
> > > > > > > > > Use syscon for SYSCON register access.
> > > > > > > > >
> > > > > > > > > Partialy based on the previous work by Serge Semin.
> > > > > > > > >
> > > > > > > > > Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
> > > > > > > > > ---
> > > > > > > > >  drivers/net/ethernet/stmicro/stmmac/Kconfig   |  11 +
> > > > > > > > >  drivers/net/ethernet/stmicro/stmmac/Makefile  |   1 +
> > > > > > > > >  .../ethernet/stmicro/stmmac/dwmac-loongson1.c | 257 ++++++++++++++++++
> > > > > > > > >  3 files changed, 269 insertions(+)
> > > > > > > > >  create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> > > > > > > > >
> > > > > > > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> > > > > > > > > index 06c6871f8788..a2b9e289aa36 100644
> > > > > > > > > --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
> > > > > > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> > > > > > > > > @@ -239,6 +239,17 @@ config DWMAC_INTEL_PLAT
> > > > > > > > >         the stmmac device driver. This driver is used for the Intel Keem Bay
> > > > > > > > >         SoC.
> > > > > > > > >
> > > > > > > > > +config DWMAC_LOONGSON1
> > > > > > > > > +     tristate "Loongson1 GMAC support"
> > > > > > > > > +     default MACH_LOONGSON32
> > > > > > > > > +     depends on OF && (MACH_LOONGSON32 || COMPILE_TEST)
> > > > > > > > > +     help
> > > > > > > > > +       Support for ethernet controller on Loongson1 SoC.
> > > > > > > > > +
> > > > > > > > > +       This selects Loongson1 SoC glue layer support for the stmmac
> > > > > > > > > +       device driver. This driver is used for Loongson1-based boards
> > > > > > > > > +       like Loongson LS1B/LS1C.
> > > > > > > > > +
> > > > > > > > >  config DWMAC_TEGRA
> > > > > > > > >       tristate "NVIDIA Tegra MGBE support"
> > > > > > > > >       depends on ARCH_TEGRA || COMPILE_TEST
> > > > > > > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
> > > > > > > > > index 5b57aee19267..80e598bd4255 100644
> > > > > > > > > --- a/drivers/net/ethernet/stmicro/stmmac/Makefile
> > > > > > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
> > > > > > > > > @@ -29,6 +29,7 @@ obj-$(CONFIG_DWMAC_SUNXI)   += dwmac-sunxi.o
> > > > > > > > >  obj-$(CONFIG_DWMAC_SUN8I)    += dwmac-sun8i.o
> > > > > > > > >  obj-$(CONFIG_DWMAC_DWC_QOS_ETH)      += dwmac-dwc-qos-eth.o
> > > > > > > > >  obj-$(CONFIG_DWMAC_INTEL_PLAT)       += dwmac-intel-plat.o
> > > > > > > > > +obj-$(CONFIG_DWMAC_LOONGSON1)        += dwmac-loongson1.o
> > > > > > > > >  obj-$(CONFIG_DWMAC_GENERIC)  += dwmac-generic.o
> > > > > > > > >  obj-$(CONFIG_DWMAC_IMX8)     += dwmac-imx.o
> > > > > > > > >  obj-$(CONFIG_DWMAC_TEGRA)    += dwmac-tegra.o
> > > > > > > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> > > > > > > > > new file mode 100644
> > > > > > > > > index 000000000000..368d6cd2cb78
> > > > > > > > > --- /dev/null
> > > > > > > > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> > > > > > > > > @@ -0,0 +1,257 @@
> > > > > > > > > +// SPDX-License-Identifier: GPL-2.0-or-later
> > > > > > > > > +/*
> > > > > > > > > + * Loongson-1 DWMAC glue layer
> > > > > > > > > + *
> > > > > > > > > + * Copyright (C) 2011-2023 Keguang Zhang <keguang.zhang@gmail.com>
> > > > > > > > > + */
> > > > > > > > > +
> > > > > > > > > +#include <linux/mfd/syscon.h>
> > > > > > > > > +#include <linux/module.h>
> > > > > > > > > +#include <linux/phy.h>
> > > > > > > > > +#include <linux/platform_device.h>
> > > > > > > > > +#include <linux/regmap.h>
> > > > > > > > > +
> > > > > > > > > +#include "stmmac.h"
> > > > > > > > > +#include "stmmac_platform.h"
> > > > > > > > > +
> > > > > > > > > +/* Loongson-1 SYSCON Registers */
> > > > > > > > > +#define LS1X_SYSCON0         (0x0)
> > > > > > > > > +#define LS1X_SYSCON1         (0x4)
> > > > > > > > > +
> > > > > > > > > +struct ls1x_dwmac_syscon {
> > > > > > > > > +     const struct reg_field *reg_fields;
> > > > > > > > > +     unsigned int nr_reg_fields;
> > > > > > > > > +     int (*syscon_init)(struct plat_stmmacenet_data *plat);
> > > > > > > > > +};
> > > > > > > > > +
> > > > > > > > > +struct ls1x_dwmac {
> > > > > > > > > +     struct device *dev;
> > > > > > > > > +     struct plat_stmmacenet_data *plat_dat;
> > > > > > > > > +     const struct ls1x_dwmac_syscon *syscon;
> > > > > > > > > +     struct regmap *regmap;
> > > > > > > > > +     struct regmap_field *regmap_fields[];
> > > > > > > > > +};
> > > > > > > > > +
> > > > > > > > > +enum ls1b_dwmac_syscon_regfield {
> > > > > > > > > +     GMAC1_USE_UART1,
> > > > > > > > > +     GMAC1_USE_UART0,
> > > > > > > > > +     GMAC1_SHUT,
> > > > > > > > > +     GMAC0_SHUT,
> > > > > > > > > +     GMAC1_USE_TXCLK,
> > > > > > > > > +     GMAC0_USE_TXCLK,
> > > > > > > > > +     GMAC1_USE_PWM23,
> > > > > > > > > +     GMAC0_USE_PWM01,
> > > > > > > > > +};
> > > > > > > > > +
> > > > > > > > > +enum ls1c_dwmac_syscon_regfield {
> > > > > > > > > +     GMAC_SHUT,
> > > > > > > > > +     PHY_INTF_SELI,
> > > > > > > > > +};
> > > > > > > > > +
> > > > > > > > > +const struct reg_field ls1b_dwmac_syscon_regfields[] = {
> > > > > > > > > +     [GMAC1_USE_UART1]       = REG_FIELD(LS1X_SYSCON0, 4, 4),
> > > > > > > > > +     [GMAC1_USE_UART0]       = REG_FIELD(LS1X_SYSCON0, 3, 3),
> > > > > > > > > +     [GMAC1_SHUT]            = REG_FIELD(LS1X_SYSCON1, 13, 13),
> > > > > > > > > +     [GMAC0_SHUT]            = REG_FIELD(LS1X_SYSCON1, 12, 12),
> > > > > > > > > +     [GMAC1_USE_TXCLK]       = REG_FIELD(LS1X_SYSCON1, 3, 3),
> > > > > > > > > +     [GMAC0_USE_TXCLK]       = REG_FIELD(LS1X_SYSCON1, 2, 2),
> > > > > > > > > +     [GMAC1_USE_PWM23]       = REG_FIELD(LS1X_SYSCON1, 1, 1),
> > > > > > > > > +     [GMAC0_USE_PWM01]       = REG_FIELD(LS1X_SYSCON1, 0, 0)
> > > > > > > > > +};
> > > > > > > > > +
> > > > > > > > > +const struct reg_field ls1c_dwmac_syscon_regfields[] = {
> > > > > > > > > +     [GMAC_SHUT]             = REG_FIELD(LS1X_SYSCON0, 6, 6),
> > > > > > > > > +     [PHY_INTF_SELI]         = REG_FIELD(LS1X_SYSCON1, 28, 30)
> > > > > > > > > +};
> > > > > > > >
> > > > > > > > Emm, using regmap fields looks so over-complicated in this case seeing
> > > > > > > > you only need to set/clear several bits in the syscon. What about
> > > > > > > > defining macros with the particular flag as it's already done in the
> > > > > > > > "asm/mach-loongson32/regs-mux.h" file and using regmap_update_bits()?
> > > > > > > >
> > > > > >
> > > > > > > To use regmap_update_bits(), I have to store and pass reg_offset and
> > > > > > > mask, which is similar to the definition of regmap fields.
> > > > > >
> > > > > > Em, not really. And what offset are you talking about? Anyway you
> > > > > > don't need one. Moreover you'll be able to reduce the number of IOs:
> > > > > >
> > > > > > +#define GMAC1_USE_UART1                 BIT(4)
> > > > > > +#define GMAC1_USE_UART0                 BIT(3)
> > > > > > ...
> > > > > > +#define GMAC1_SHUT                      BIT(13)
> > > > > > ...
> > > > > > +#define GMAC1_USE_TXCLK                 BIT(3)
> > > > > > +#define GMAC1_USE_PWM23                 BIT(1)
> > > > > >
> > > > > > +static int ls1b_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
> > > > > > +{
> > > > > > +       struct ls1x_dwmac *dwmac = plat->bsp_priv;
> > > > > > +       struct regmap *syscon = dwmac->regmap;
> > > > > > +
> > > > > > +       if (plat->bus_id) {
> > > > > > +               regmap_update_bits(syscon, LS1X_SYSCON0,
> > > > > > +                                  GMAC1_USE_UART1 | GMAC1_USE_UART0,
> > > > > > +                                  GMAC1_USE_UART1 | GMAC1_USE_UART0);
> > > > > > +
> > > > > > +               switch (plat->phy_interface) {
> > > > > > +               case PHY_INTERFACE_MODE_RGMII:
> > > > > > +                       regmap_update_bits(syscon, LS1X_SYSCON1,
> > > > > > +                                          GMAC1_USE_TXCLK | GMAC1_USE_TXCLK, 0);
> > > > > > +                       break;
> > > > > > +               case PHY_INTERFACE_MODE_MII:
> > > > > > +                       regmap_update_bits(syscon, LS1X_SYSCON1,
> > > > > > +                                          GMAC1_USE_TXCLK | GMAC1_USE_TXCLK
> > > > > > +                                          GMAC1_USE_TXCLK | GMAC1_USE_TXCLK);
> > > > > > +                       break;
> > > > > > +               default:
> > > > > > +                       dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
> > > > > > +                               plat->phy_interface);
> > > > > > +                       return -EOPNOTSUPP;
> > > > > > +               }
> > > > > > +
> > > > > > +               regmap_field_write(syscon, LS1X_SYSCON1, GMAC1_SHUT, 0);
> > > > > > +       } //...
> > > > > > +
> > > > > > +       return 0;
> > > > > > +}
> > > > > >
> > > > > > This doesn't look in anyway less readable then your implementation
> > > > > > but in fact simpler.
> > > > > >
> > > > > > > In addition, the regmap fields are very clear and leave the trouble to
> > > > > > > the internal implementation.
> > > > > >
> > > > > > In this case it brings much more troubles and no clarity. You need to create
> > > > > > an additional mainly redundant abstraction, waste memory for it,
> > > > > > define additional const arrays. Using it won't improve the code
> > > > > > readability seeing you need to set/clear a few flags only. So all of
> > > > > > the troubles for nothing. See the code above. It's simple and clear.
> > > > > > Just several regmap_update_bits()..
> > > > > >
> > > > > OK. I will use regmap instead of regmap fields.
> > > > >
> > > > > > BTW why have you chosen to define syscon instead of creating a pinctrl
> > > > > > driver? What if Loongson1 is embedded into a platform with, for
> > > > > > instance, UART0 and UART1 utilized instead of the GMAC1?
> > > > > >
> > > >
> > > > > As you can see, the two registers contains miscellaneous settings.
> > > > > Besides ‘USE’ bits, there are ‘RESET‘ bits, 'EN' bits, 'SHUT' bits, ...
> > > > > So they are not pinctrl registers.
> > > >
> > > > You could have defined a device node which would export "reset",
> > > > "power" and "pinctrl" functionality, like it's normally done for the
> > > > RCU devices (Reset and Clock unit devices).
> > > >
> > > > > Actually, there is a dedicated pin controller which controls the
> > > > > multiplexing of pads.
> > > >
> > > > Do you mean that there is another controller in the Loongson1 SoC
> > > > which controls the pads multiplexing?
> > > >
> > > Yes. There is another contoller that really controls the pads multiplexing.
> > >
> > > > If so what is the purpose of the GMAC1_USE_UART1, GMAC1_USE_UART0 and
> > > > GMAC1_USE_TXCLK, GMAC1_USE_PWM23 flags in MUX controller then? Is it
> > > > just another pinctl space with additional reset/power controls or what?
> > > >
> >
> > > From my perspective, these ‘USE’ bits should be regarded as
> > > device/module multiplexing rather than pads multiplexing.
> >
> > Could you elaborate what does "device/module multiplexing" mean?
> >

> Pherhaps the device switch is more accurate.
> Just means which devices could not work at the time.

What does it mean exactly? What changes if you get to set these flags
and get them cleared? Are the CSRs still accessible? Does the pads
function change? What the HW-manual say about for instance the
GMAC1_USE_UART1, GMAC1_USE_UART0, GMAC1_USE_TXCLK and GMAC1_USE_PWM23
flags? What does your "not working at the time" mean? What happens if
you get to access and use the devices simultaneously?

I don't understand what is the point of having the deviceis toggle
functionality if there is already pin-controller available. If it doesn't
switch the pins function, if it doesn't switch the CSRs space mapping,
then what is it needed for?

> 
> > > Although the two registers were called MUX_CTRL in LS1B datasheet,
> > > they had beed renamed to MISC_CTRL in LS1C datasheet.
> > > So it is supposed to be considered syscon.
> > > > >
> > > > > > >
> > > > > > > > > +
> > > > > > > >
> > > > > > > > > +static int ls1b_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
> > > > > > > > > +{
> > > > > > > >
> > > > > > > > As I already told you this part is better to be called from the
> > > > > > > > plat_stmmacenet_data.fix_mac_speed() because PHY interface mode can
> > > > > > > > differ from one interface open cycle to another as per the phylink
> > > > > > > > design.
> > > > > > > >
> > > > > > > I have considered .fix_mac_speed(), which will be called every time
> > > > > > > the link is up, and passes the current speed.
> > > > > > > However, the PHY interface mode is determined by the hardware design -
> > > > > > > the schematic.
> > > > > > > In other words, once the schematic is done, the PHY interface mode is fixed.
> > > > > > > Therefore, PHY interface mode should be configured one time at the
> > > > > > > initialization.
> > > > > > > And the plat_stmmacenet_data.init() is the proper place to do this.
> > > > > >
> > > > > > Ok. If no actual clock change is needed then indeed init() will be the
> > > > > > proper place.
> > > > > >
> > > > > > >
> > > > > > > > > +     struct ls1x_dwmac *dwmac = plat->bsp_priv;
> > > > > > > > > +     struct regmap_field **regmap_fields = dwmac->regmap_fields;
> > > > > > > > > +
> > > > > > > >
> > > > > > > > > +     if (plat->bus_id) {
> > > > > > > >
> > > > > > > > Using bus_id doesn't look correct to determine the CSRs responsible
> > > > > > > > for the interface mode selection because it's calculated based on the
> > > > > > > > DT ethernet-alias which doesn't guarantee to have a particular device
> > > > > > > > assigned with the alias. Alias node can be absent after all. What
> > > > > > > > could be better in this case is for instance to use the regs physical
> > > > > > > > address. Any better idea?
> > > > > > > >
> > > > > >
> > > > > > > The purpose of alias is to bind the a particular device with a
> > > > > > > particular alias even some aliases are absent.
> > > > > > > Because of_alias_get_id() gets the alias id.
> > > > > > > For example, LS1B has two GMAC controllers, gmac0 and gmac1.
> > > > > > > I have tried the Ethernet with only one alias as follows.
> > > > > > >        aliases {
> > > > > > >                ethernet1 = &gmac1;
> > > > > > >        };
> > > > > > > In this case, plat->bus_id is still 1.
> > > > > > > And both gmac0 and gmac1 work.
> > > > > >
> > > > > > If no alias specified? If both aliases a non zero? If the IDs are
> > > > > > confused? If any of these is true you are in trouble. Your code
> > > > > > shouldn't rely on the aliases in this case. You need to come up with a
> > > > > > way to certainly distinguish one MAC from another. A physical base
> > > > > > address is one possible option.
> > > > > >
> > > >
> > > > > I see.
> > > > > But It seems unusual to determine device IDs by physical base address.
> > > > > What about adding a new property? such as loongson,dwmac-id
> > > >
> > > > IMO It's better to have a DT-property-independent way for it. If I
> > > > were you I would have utilized the reg-space
> > > > physical-base-address-based approach since you need to have it
> > > > specified anyway and it determines the particular MAC for sure.
> > > > Thus your driver won't be dependent in the device tree in that aspect.
> > > >
> >
> > > The physical base address may vary from SoC to SoC.
> >
> > You've got only two SoCs, right? LS1C and LS1B. Each of them has
> > a specific set of NICs: two loongson,ls1b-gmac on LS1B and
> > one loongson,ls1c-mac on LS1C. So LS1B has only two physical addresses
> > you can use to distinguish one interface from another and find out
> > what flags to toggle in the syscon. LS1C has a single MAC so you won't
> > even need any additional info since there is only one flag to
> > toggle.
> >

> Is there any driver that uses the physical-base-address way?
> Could you provide me some existing examples?

For what? Do you need a reference of how to implement that? Or do you
want a proof that it's eligible just because somebody sometime ago has
developed such approach and it was merged into the kernel? Just for
the record even if something can be found in the kernel it doesn't
mean it's always the best practice especially if we are considering
the STMMAC driver which is full of weak and bogus patterns.

Anyway, see my comment in the previous message which you skipped for
some reason +-------------------------------------------------------------------+
                                                                                |
> Thanks                                                                        |
>                                                                               |
> > Physical address is constant from one LS1C instance to another, and         |
> > similarly from one LS1B instance to another. It's defined by means          |
> > of the macros:                                                              |
> > LS1X_GMAC0_BASE                                                             |
> > LS1X_GMAC1_BASE                                                             |
> > What physical address varying are you talking about? I don't see that       |
> > in the current platform driver.                                             |
> >                                                                             |
> > > It means that the driver has to remember MAC base addresses for different |
> > > SoCs.                                                                     |
> >                                                                             |
> > Yes. Just two physical addresses.                                           |
> >                                                                             |
                                                                                |
> Two chips for now.                                                            |
> What about the future chips?                                                  |
                                                                                |
Any future chips will require the driver update anyway because of               |
the way your syscon-related code is designed and considering the                |
fact that they will have specific system controller anyway. But                 |
again see my comment in the previous message +----------------------------------+
                                                                                |
> > >                                                                           |
> > > > Some DW *MAC drivers pass additional number to the syscon phandle node  |
> > > > in the syscon-property to identify the MAC on the board, like           |
> > > > dwmac-socfpga.c or dwmac-sti.c. If you get to implement a similar way   |
> > > > then you'll need to have the DT-bindings properly describing that. But  |
> > > > IMO my approach seems less clumsy and simpler.                          |
> > > >                                                                         |
> >                                                                             |
> > > I prefer the DT-bindings property way. At least many off-the-shelf        |
> > > examples can be found.                                                    |
> >                                                                             |
> > Just two examples with not the best solution implemented.                   |
> >                                                                             |
                                                                                |
> > Anyway it's up to you to decide after all. I don't mind if it will be  <----+
> > the property-based way. But as for me it looks redundant seeing there
> > is base address always available and which you can utilise. Moreover
> > if you get to add any new Loongson MAC to the driver you'll need to
> > update it anyway at least in a way the syscon flags are toggled. So
> > even from that perspective using the physical base address seems as at
> > least the equally complex and maintainable solution.

-Serge(y)

> >
> > >
> > > > >
> > > > > > Note the /alias node is an informational node. It doesn't describe
> > > > > > devices. Just recent Krzysztof comment in a similar situation:
> > > > > > https://lore.kernel.org/netdev/20230814112539.70453-1-sriranjani.p@samsung.com/T/#m3972e40bd2fa323a3bdb2fbf07bde47ba6752439
> > > > > >
> > > > > > Aliases are normally used by OS to for instance fix the device
> > > > > > enumeration (see SPI, I2C, I3C, MTD, MMC, RTC, TTY/Serial, Watchdog,
> > > > > > MDIO-GPIO, etc) - pre-define the device ID from the kernel or OS point
> > > > > > of view. In your case the IDs can't be changed. GMAC0 must be assigned
> > > > > > with ID0 and GMAC1 must be assigned with non-zero. Doing otherwise
> > > > > > will be break the interfaces functionality which isn't acceptable.
> > > > > >
> > > > > > >
> > > > > > > > > +             regmap_field_write(regmap_fields[GMAC1_USE_UART1], 1);
> > > > > > > > > +             regmap_field_write(regmap_fields[GMAC1_USE_UART0], 1);
> > > > > > > > > +
> > > > > > > > > +             switch (plat->phy_interface) {
> > > > > > > > > +             case PHY_INTERFACE_MODE_RGMII:
> > > > > > > > > +                     regmap_field_write(regmap_fields[GMAC1_USE_TXCLK], 0);
> > > > > > > > > +                     regmap_field_write(regmap_fields[GMAC1_USE_PWM23], 0);
> > > > > > > > > +                     break;
> > > > > > > > > +             case PHY_INTERFACE_MODE_MII:
> > > > > > > > > +                     regmap_field_write(regmap_fields[GMAC1_USE_TXCLK], 1);
> > > > > > > > > +                     regmap_field_write(regmap_fields[GMAC1_USE_PWM23], 1);
> > > > > > > > > +                     break;
> > > > > > > > > +             default:
> > > > > > > > > +                     dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
> > > > > > > > > +                             plat->phy_interface);
> > > > > > > > > +                     return -EOPNOTSUPP;
> > > > > > > > > +             }
> > > > > > > > > +
> > > > > > > > > +             regmap_field_write(regmap_fields[GMAC1_SHUT], 0);
> > > > > > > > > +     } else {
> > > > > > > > > +             switch (plat->phy_interface) {
> > > > > > > > > +             case PHY_INTERFACE_MODE_RGMII:
> > > > > > > > > +                     regmap_field_write(regmap_fields[GMAC0_USE_TXCLK], 0);
> > > > > > > > > +                     regmap_field_write(regmap_fields[GMAC0_USE_PWM01], 0);
> > > > > > > > > +                     break;
> > > > > > > > > +             case PHY_INTERFACE_MODE_MII:
> > > > > > > > > +                     regmap_field_write(regmap_fields[GMAC0_USE_TXCLK], 1);
> > > > > > > > > +                     regmap_field_write(regmap_fields[GMAC0_USE_PWM01], 1);
> > > > > > > > > +                     break;
> > > > > > > > > +             default:
> > > > > > > > > +                     dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
> > > > > > > > > +                             plat->phy_interface);
> > > > > > > > > +                     return -EOPNOTSUPP;
> > > > > > > > > +             }
> > > > > > > > > +
> > > > > > > > > +             regmap_field_write(regmap_fields[GMAC0_SHUT], 0);
> > > > > > > > > +     }
> > > > > > > > > +
> > > > > > > > > +     return 0;
> > > > > > > > > +}
> > > > > > > > > +
> > > > > > > > > +static int ls1c_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
> > > > > > > > > +{
> > > > > > > > > +     struct ls1x_dwmac *dwmac = plat->bsp_priv;
> > > > > > > > > +     struct regmap_field **regmap_fields = dwmac->regmap_fields;
> > > > > > > > > +
> > > > > > > > > +     if (plat->phy_interface == PHY_INTERFACE_MODE_RMII) {
> > > > > > > > > +             regmap_field_write(regmap_fields[PHY_INTF_SELI], 0x4);
> > > > > > > > > +     } else {
> > > > > > > > > +             dev_err(dwmac->dev, "Unsupported PHY-mode %u\n",
> > > > > > > > > +                     plat->phy_interface);
> > > > > > > > > +             return -EOPNOTSUPP;
> > > > > > > > > +     }
> > > > > > > > > +
> > > > > > > > > +     regmap_field_write(regmap_fields[GMAC_SHUT], 0);
> > > > > > > > > +
> > > > > > > > > +     return 0;
> > > > > > > > > +}
> > > > > > > > > +
> > > > > > > > > +static const struct ls1x_dwmac_syscon ls1b_dwmac_syscon = {
> > > > > > > > > +     .reg_fields = ls1b_dwmac_syscon_regfields,
> > > > > > > > > +     .nr_reg_fields = ARRAY_SIZE(ls1b_dwmac_syscon_regfields),
> > > > > > > > > +     .syscon_init = ls1b_dwmac_syscon_init,
> > > > > > > > > +};
> > > > > > > > > +
> > > > > > > > > +static const struct ls1x_dwmac_syscon ls1c_dwmac_syscon = {
> > > > > > > > > +     .reg_fields = ls1c_dwmac_syscon_regfields,
> > > > > > > > > +     .nr_reg_fields = ARRAY_SIZE(ls1c_dwmac_syscon_regfields),
> > > > > > > > > +     .syscon_init = ls1c_dwmac_syscon_init,
> > > > > > > > > +};
> > > > > > > > > +
> > > > > > > > > +static int ls1x_dwmac_init(struct platform_device *pdev, void *priv)
> > > > > > > > > +{
> > > > > > > > > +     struct ls1x_dwmac *dwmac = priv;
> > > > > > > > > +     int ret;
> > > > > > > > > +
> > > > > > > >
> > > > > > > > > +     ret = devm_regmap_field_bulk_alloc(dwmac->dev, dwmac->regmap,
> > > > > > > > > +                                        dwmac->regmap_fields,
> > > > > > > > > +                                        dwmac->syscon->reg_fields,
> > > > > > > > > +                                        dwmac->syscon->nr_reg_fields);
> > > > > > > >
> > > > > > > > Please see my first comment about this.
> > > > > > > >
> > > > > > > > > +     if (ret)
> > > > > > > > > +             return ret;
> > > > > > > > > +
> > > > > > > > > +     if (dwmac->syscon->syscon_init) {
> > > > > > > > > +             ret = dwmac->syscon->syscon_init(dwmac->plat_dat);
> > > > > > > > > +             if (ret)
> > > > > > > > > +                     return ret;
> > > > > > > > > +     }
> > > > > > > > > +
> > > > > > > > > +     return 0;
> > > > > > > > > +}
> > > > > > > > > +
> > > > > > > > > +static const struct of_device_id ls1x_dwmac_syscon_match[] = {
> > > > > > > > > +     { .compatible = "loongson,ls1b-syscon", .data = &ls1b_dwmac_syscon },
> > > > > > > > > +     { .compatible = "loongson,ls1c-syscon", .data = &ls1c_dwmac_syscon },
> > > > > > > > > +     { }
> > > > > > > > > +};
> > > > > > > > > +
> > > > > > > > > +static int ls1x_dwmac_probe(struct platform_device *pdev)
> > > > > > > > > +{
> > > > > > > > > +     struct plat_stmmacenet_data *plat_dat;
> > > > > > > > > +     struct stmmac_resources stmmac_res;
> > > > > > > > > +     struct device_node *syscon_np;
> > > > > > > > > +     const struct of_device_id *match;
> > > > > > > > > +     struct regmap *regmap;
> > > > > > > > > +     struct ls1x_dwmac *dwmac;
> > > > > > > > > +     const struct ls1x_dwmac_syscon *syscon;
> > > > > > > > > +     size_t size;
> > > > > > > > > +     int ret;
> > > > > > > > > +
> > > > > > > > > +     ret = stmmac_get_platform_resources(pdev, &stmmac_res);
> > > > > > > > > +     if (ret)
> > > > > > > > > +             return ret;
> > > > > > > > > +
> > > > > > > >
> > > > > > > > > +     /* Probe syscon */
> > > > > > > > > +     syscon_np = of_parse_phandle(pdev->dev.of_node, "syscon", 0);
> > > > > > > >
> > > > > > > > it's vendor-specific property so it is supposed to have a
> > > > > > > > vendor-specific prefix and possibly ls1-specific name.
> > > > > > > >
> > > > > > > This has been fixed in v2.
> > > > > > > Could you please review v2?
> > > > > > > Thanks!
> > > > > > >
> > > > > > > > > +     if (!syscon_np)
> > > > > > > > > +             return -ENODEV;
> > > > > > > > > +
> > > > > > > > > +     match = of_match_node(ls1x_dwmac_syscon_match, syscon_np);
> > > > > > > > > +     if (!match) {
> > > > > > > > > +             of_node_put(syscon_np);
> > > > > > > > > +             return -EINVAL;
> > > > > > > > > +     }
> > > > > > > > > +     syscon = (const struct ls1x_dwmac_syscon *)match->data;
> > > > >
> > > >
> > > > > Please note that of_match_node() is used for syscon matching.
> > > >
> > > > I noticed it in the first place. Please see my next comment.
> > > >
> > > > >
> > > > > > > > > +
> > > > > > > > > +     regmap = syscon_node_to_regmap(syscon_np);
> > > > > > > > > +     of_node_put(syscon_np);
> > > > > > > > > +     if (IS_ERR(regmap)) {
> > > > > > > > > +             ret = PTR_ERR(regmap);
> > > > > > > > > +             dev_err(&pdev->dev, "Unable to map syscon: %d\n", ret);
> > > > > > > > > +             return ret;
> > > > > > > > > +     }
> > > > > > > >
> > > > > > > > or you can use syscon_regmap_lookup_by_phandle(). Using
> > > > > > > > of_match_node() doesn't seem necessary since it's unlikely to have
> > > > > > > > moee than one system controller available on the LS1b or LS1c chips.
> > > > > > > >
> > > > > >
> > > > > > > I planned to use syscon_regmap_lookup_by_phandle().
> > > > > > > Thus the compatible
> > > > > > > "loongson,ls1b-dwmac-syscon"/"loongson,ls1c-dwmac-syscon" would become
> > > > > > > useless.
> > > > > > > I'm not sure about this.
> > > > > >
> > > > > > The compatible strings should be left despite of the
> > > > > > syscon_regmap_lookup_by_phandle() usage. But again "dwmac" suffix is
> > > > > > redundant. Based on the CSRs definition in regs-mux.h, selecting
> > > > > > (G)MAC pins mode is only a small part of the Loongson1 SoC system
> > > > > > controllers functionality.
> > > > > > "loongson,ls1b-syscon"/"loongson,ls1c-syscon" looks more appropriate.
> > > > > >
> > > > > That's what I did in PATCH 2/5.
> > > > > I've just explained this to Krzysztof.
> > > > > And will change back to "loongson,ls1b-syscon"/"loongson,ls1c-syscon"
> > > > > in next version.
> > > > >
> > > >
> > > > > In addition, syscon_regmap_lookup_by_phandle() returns regmap pointer directly.
> > > > > Then, there wil be no way to do syscon matching without its device_node.
> > > > > How will I know whether the syscon is loongson,ls1b-syscon or
> > > > > loongson,ls1c-syscon?
> > > >
> > > > Do you have both of these syscons available in the same SoC? I don't
> > > > think so. Thus you don't need such validation since the LS1C SoC dts
> > > > file will have the "loongson,ls1c-syscon" syscon node defined only and
> > > > the LS1B SoC dts file - "loongson,ls1b-syscon" only.
> > > >
> >
> > > I believe you have noticed the difference of syscon_init() between
> > > LS1B and LS1C.
> > > The syscon matching is for finding the right syscon_init().
> >
> > There are other ways to select syscon_init(). Syscon node compatible
> > string is just one of them. You can do that by one of the next way:
> > 1. Based on the syscon-property name: "loongson,ls1b-syscon" property
> > always points to the LS1B syscon phandle so the
> > ls1b_dwmac_syscon_init() function is supposed to be selected;
> > "loongson,ls1c-syscon" property always points to the LS1C syscon so
> > ls1c_dwmac_syscon_init() is supposed to be utilized.
> > 2. Based on the MAC compatible string. loongson,ls1b-gmac can be found
> > on the LS1B SoC only which is equipped with the ls1b-syscon system
> > controller only so ls1b_dwmac_syscon_init() must be selected. Likewise
> > you can determine the init function on the LS1C SoC.
> >
> OK. I once used the second way for my draft version.
> static const struct of_device_id ls1x_dwmac_match[] = {
>        { .compatible = "loongson,ls1b-gmac", .data = &ls1b_dwmac_syscon, },
>        { .compatible = "loongson,ls1c-mac" .data = &ls1c_dwmac_syscon,
> },
>        { }
> };
> Then, I will change back to this implementation in the next version.
> 
> > -Serge(y)
> >
> > >
> > > Thanks for your review!
> > >
> > > > -Serge(y)
> > > >
> > > > >
> > > > > Thanks for your review!
> > > > >
> > > > >
> > > > >
> > > > >
> > > > >
> > > > > > -Serge(y)
> > > > > >
> > > > > > >
> > > > > > > > > +
> > > > > > > > > +     size = syscon->nr_reg_fields * sizeof(struct regmap_field *);
> > > > > > > > > +     dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac) + size, GFP_KERNEL);
> > > > > > > > > +     if (!dwmac)
> > > > > > > > > +             return -ENOMEM;
> > > > > > > > > +
> > > > > > > > > +     plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
> > > > > > > > > +     if (IS_ERR(plat_dat)) {
> > > > > > > > > +             dev_err(&pdev->dev, "dt configuration failed\n");
> > > > > > > > > +             return PTR_ERR(plat_dat);
> > > > > > > > > +     }
> > > > > > > > > +
> > > > > > > > > +     plat_dat->bsp_priv = dwmac;
> > > > > > > > > +     plat_dat->init = ls1x_dwmac_init;
> > > > > > > > > +     dwmac->dev = &pdev->dev;
> > > > > > > > > +     dwmac->plat_dat = plat_dat;
> > > > > > > > > +     dwmac->syscon = syscon;
> > > > > > > > > +     dwmac->regmap = regmap;
> > > > > > > > > +
> > > > > > > > > +     ret = stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res);
> > > > > > > > > +     if (ret)
> > > > > > > > > +             goto err_remove_config_dt;
> > > > > > > > > +
> > > > > > > > > +     return 0;
> > > > > > > > > +
> > > > > > > > > +err_remove_config_dt:
> > > > > > > >
> > > > > > > > > +     if (pdev->dev.of_node)
> > > > > > > >
> > > > > > > > Is this conditional statement necessary here?
> > > > > > > >
> > > > > > > You're right.
> > > > > > > Will remove this condition in next version.
> > > > > > > Thanks!
> > > > > > >
> > > > > > > > -Serge
> > > > > > > >
> > > > > > > > > +             stmmac_remove_config_dt(pdev, plat_dat);
> > > > > > > > > +
> > > > > > > > > +     return ret;
> > > > > > > > > +}
> > > > > > > > > +
> > > > > > > > > +static const struct of_device_id ls1x_dwmac_match[] = {
> > > > > > > > > +     { .compatible = "loongson,ls1b-dwmac" },
> > > > > > > > > +     { .compatible = "loongson,ls1c-dwmac" },
> > > > > > > > > +     { }
> > > > > > > > > +};
> > > > > > > > > +MODULE_DEVICE_TABLE(of, ls1x_dwmac_match);
> > > > > > > > > +
> > > > > > > > > +static struct platform_driver ls1x_dwmac_driver = {
> > > > > > > > > +     .probe = ls1x_dwmac_probe,
> > > > > > > > > +     .remove_new = stmmac_pltfr_remove,
> > > > > > > > > +     .driver = {
> > > > > > > > > +             .name = "loongson1-dwmac",
> > > > > > > > > +             .of_match_table = ls1x_dwmac_match,
> > > > > > > > > +     },
> > > > > > > > > +};
> > > > > > > > > +module_platform_driver(ls1x_dwmac_driver);
> > > > > > > > > +
> > > > > > > > > +MODULE_AUTHOR("Keguang Zhang <keguang.zhang@gmail.com>");
> > > > > > > > > +MODULE_DESCRIPTION("Loongson1 DWMAC glue layer");
> > > > > > > > > +MODULE_LICENSE("GPL");
> > > > > > > > > --
> > > > > > > > > 2.39.2
> > > > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > --
> > > > > > > Best regards,
> > > > > > >
> > > > > > > Keguang Zhang
> > > > >
> > > > >
> > > > >
> > > > > --
> > > > > Best regards,
> > > > >
> > > > > Keguang Zhang
> > >
> > >
> > >
> > > --
> > > Best regards,
> > >
> > > Keguang Zhang
> 
> 
> 
> -- 
> Best regards,
> 
> Keguang Zhang

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

end of thread, other threads:[~2023-08-22 14:20 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-08-12 15:11 [PATCH 0/5] Move Loongson1 MAC arch-code to the driver dir Keguang Zhang
2023-08-12 15:11 ` [PATCH 1/5] MIPS: loongson32: Remove Loongson1 MAC arch-code Keguang Zhang
2023-08-12 15:11 ` [PATCH 2/5] dt-bindings: mfd: syscon: Add compatibles for Loongson-1 syscon Keguang Zhang
2023-08-14 19:06   ` Krzysztof Kozlowski
2023-08-12 15:11 ` [PATCH 3/5] dt-bindings: net: Add Loongson-1 DWMAC glue layer Keguang Zhang
2023-08-14 19:11   ` Krzysztof Kozlowski
2023-08-16 12:54   ` Serge Semin
2023-08-18 10:42     ` Keguang Zhang
2023-08-18 13:48       ` Serge Semin
2023-08-21 13:13         ` Keguang Zhang
2023-08-12 15:11 ` [PATCH 4/5] net: stmmac: Add glue layer for Loongson-1 SoC Keguang Zhang
2023-08-12 21:30   ` kernel test robot
2023-08-13  8:28   ` kernel test robot
2023-08-13 18:24   ` Simon Horman
2023-08-14 10:50     ` Keguang Zhang
2023-08-16 13:30   ` Serge Semin
2023-08-18 12:37     ` Keguang Zhang
2023-08-18 16:19       ` Serge Semin
2023-08-21 13:24         ` Keguang Zhang
2023-08-21 14:16           ` Serge Semin
2023-08-22  7:58             ` Keguang Zhang
2023-08-22 10:53               ` Serge Semin
2023-08-22 12:09                 ` Keguang Zhang
2023-08-22 14:20                   ` Serge Semin
2023-08-12 15:11 ` [PATCH 5/5] MAINTAINERS: Add entry for Loongson-1 DWMAC Keguang Zhang
2023-08-14 19:16   ` Krzysztof Kozlowski
2023-08-13 15:24 ` [PATCH 0/5] Move Loongson1 MAC arch-code to the driver dir Andrew Lunn
2023-08-14  2:39   ` Keguang Zhang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).