From: Lad Prabhakar Remove the locally defined ETH_P_DSA_A5PSW protocol value from tag_rzn1_a5psw.c. The macro is already provided by , which is included by this file, making the local definition redundant. Signed-off-by: Lad Prabhakar --- net/dsa/tag_rzn1_a5psw.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/dsa/tag_rzn1_a5psw.c b/net/dsa/tag_rzn1_a5psw.c index 69d51221b1e5..201782b4f8dc 100644 --- a/net/dsa/tag_rzn1_a5psw.c +++ b/net/dsa/tag_rzn1_a5psw.c @@ -24,7 +24,6 @@ #define A5PSW_NAME "a5psw" -#define ETH_P_DSA_A5PSW 0xE001 #define A5PSW_TAG_LEN 8 #define A5PSW_CTRL_DATA_FORCE_FORWARD BIT(0) /* This is both used for xmit tag and rcv tagging */ -- 2.52.0 From: Lad Prabhakar Add an explicit tag protocol for the RZ/T2H ETHSW and register a separate ethsw tag driver so the existing A5PSW tag implementation can be reused for RZ/T2H without code duplication. The ETHSW IP on RZ/T2H shares substantial commonality with the A5PSW IP on RZ/N1, and the current tag driver does not touch the register fields that differ between the two blocks. Expose a distinct DSA protocol and a second dsa_device_ops to let consumers select the RZ/T2H tag format while keeping the proven A5PSW handling unchanged. Signed-off-by: Lad Prabhakar --- include/net/dsa.h | 2 ++ include/uapi/linux/if_ether.h | 2 +- net/dsa/tag_rzn1_a5psw.c | 21 +++++++++++++++++++-- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/include/net/dsa.h b/include/net/dsa.h index 97d5f401cfcf..81302315e493 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -57,6 +57,7 @@ struct tc_action; #define DSA_TAG_PROTO_BRCM_LEGACY_FCS_VALUE 29 #define DSA_TAG_PROTO_YT921X_VALUE 30 #define DSA_TAG_PROTO_MXL_GSW1XX_VALUE 31 +#define DSA_TAG_PROTO_RZT2H_ETHSW_VALUE 32 enum dsa_tag_protocol { DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE, @@ -91,6 +92,7 @@ enum dsa_tag_protocol { DSA_TAG_PROTO_VSC73XX_8021Q = DSA_TAG_PROTO_VSC73XX_8021Q_VALUE, DSA_TAG_PROTO_YT921X = DSA_TAG_PROTO_YT921X_VALUE, DSA_TAG_PROTO_MXL_GSW1XX = DSA_TAG_PROTO_MXL_GSW1XX_VALUE, + DSA_TAG_PROTO_RZT2H_ETHSW = DSA_TAG_PROTO_RZT2H_ETHSW_VALUE, }; struct dsa_switch; diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h index 2c93b7b731c8..61f64cb38b08 100644 --- a/include/uapi/linux/if_ether.h +++ b/include/uapi/linux/if_ether.h @@ -118,7 +118,7 @@ #define ETH_P_YT921X 0x9988 /* Motorcomm YT921x DSA [ NOT AN OFFICIALLY REGISTERED ID ] */ #define ETH_P_EDSA 0xDADA /* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */ #define ETH_P_DSA_8021Q 0xDADB /* Fake VLAN Header for DSA [ NOT AN OFFICIALLY REGISTERED ID ] */ -#define ETH_P_DSA_A5PSW 0xE001 /* A5PSW Tag Value [ NOT AN OFFICIALLY REGISTERED ID ] */ +#define ETH_P_DSA_A5PSW 0xE001 /* A5PSW/ETHSW Tag Value [ NOT AN OFFICIALLY REGISTERED ID ] */ #define ETH_P_IFE 0xED3E /* ForCES inter-FE LFB type */ #define ETH_P_AF_IUCV 0xFBFB /* IBM af_iucv [ NOT AN OFFICIALLY REGISTERED ID ] */ diff --git a/net/dsa/tag_rzn1_a5psw.c b/net/dsa/tag_rzn1_a5psw.c index 201782b4f8dc..66619986fa71 100644 --- a/net/dsa/tag_rzn1_a5psw.c +++ b/net/dsa/tag_rzn1_a5psw.c @@ -23,6 +23,7 @@ */ #define A5PSW_NAME "a5psw" +#define ETHSW_NAME "ethsw" #define A5PSW_TAG_LEN 8 #define A5PSW_CTRL_DATA_FORCE_FORWARD BIT(0) @@ -108,8 +109,24 @@ static const struct dsa_device_ops a5psw_netdev_ops = { .rcv = a5psw_tag_rcv, .needed_headroom = A5PSW_TAG_LEN, }; +MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_A5PSW, A5PSW_NAME); +DSA_TAG_DRIVER(a5psw_netdev_ops); + +static const struct dsa_device_ops ethsw_netdev_ops = { + .name = ETHSW_NAME, + .proto = DSA_TAG_PROTO_RZT2H_ETHSW, + .xmit = a5psw_tag_xmit, + .rcv = a5psw_tag_rcv, + .needed_headroom = A5PSW_TAG_LEN, +}; +MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_RZT2H_ETHSW, ETHSW_NAME); +DSA_TAG_DRIVER(ethsw_netdev_ops); + +static struct dsa_tag_driver *dsa_tag_driver_array[] = { + &DSA_TAG_DRIVER_NAME(a5psw_netdev_ops), + &DSA_TAG_DRIVER_NAME(ethsw_netdev_ops), +}; +module_dsa_tag_drivers(dsa_tag_driver_array); MODULE_DESCRIPTION("DSA tag driver for Renesas RZ/N1 A5PSW switch"); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_A5PSW, A5PSW_NAME); -module_dsa_tag_driver(a5psw_netdev_ops); -- 2.52.0 From: Lad Prabhakar Update the Kconfig entry for the RZN1 A5PSW tag driver to reflect that the same tagging format is also used by the ETHSW blocks found in Renesas RZ/T2H and RZ/N2H SoCs. Signed-off-by: Lad Prabhakar --- net/dsa/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig index f86b30742122..a00eb3bdcd0f 100644 --- a/net/dsa/Kconfig +++ b/net/dsa/Kconfig @@ -159,11 +159,11 @@ config NET_DSA_TAG_RTL8_4 switches with 8 byte protocol 4 tags, such as the Realtek RTL8365MB-VC. config NET_DSA_TAG_RZN1_A5PSW - tristate "Tag driver for Renesas RZ/N1 A5PSW switch" + tristate "Tag driver for Renesas RZ/N1 A5PSW and RZ/{T2H,N2H} ETHSW switches" help Say Y or M if you want to enable support for tagging frames for - Renesas RZ/N1 embedded switch that uses an 8 byte tag located after - destination MAC address. + Renesas RZ/N1 A5PSW and RZ/{T2H,N2H} ETHSW embedded switches that use + an 8-byte tag located after the destination MAC address. config NET_DSA_TAG_LAN9303 tristate "Tag driver for SMSC/Microchip LAN9303 family of switches" -- 2.52.0 From: Lad Prabhakar Extend the A5PSW DSA binding to cover the ETHSW variant used on newer Renesas RZ/T2H and RZ/N2H SoCs. ETHSW is derived from the A5PSW switch found on RZ/N1 but differs in register layout, clocking and interrupt topology, and exposes four ports in total (including the CPU/management port) instead of five. Update the schema to describe these differences by adding dedicated compatible strings for RZ/T2H and RZ/N2H, tightening requirements on clocks, resets and interrupts, and documenting the expanded 24-interrupt set used by ETHSW for timestamping and timer functions. Conditional validation ensures that RZ/T2H/RZ/N2H instances provide the correct resources while keeping the original A5PSW constraints intact. Use the RZ/T2H compatible string as the fallback for RZ/N2H, reflecting that both SoCs integrate the same ETHSW IP. Add myself as a co-maintainer of the binding to support ongoing work on the ETHSW family across RZ/T2H and RZ/N2H devices. Signed-off-by: Lad Prabhakar --- .../bindings/net/dsa/renesas,rzn1-a5psw.yaml | 154 +++++++++++++++--- 1 file changed, 130 insertions(+), 24 deletions(-) diff --git a/Documentation/devicetree/bindings/net/dsa/renesas,rzn1-a5psw.yaml b/Documentation/devicetree/bindings/net/dsa/renesas,rzn1-a5psw.yaml index ea285ef3e64f..ec15ea4deeb0 100644 --- a/Documentation/devicetree/bindings/net/dsa/renesas,rzn1-a5psw.yaml +++ b/Documentation/devicetree/bindings/net/dsa/renesas,rzn1-a5psw.yaml @@ -4,43 +4,108 @@ $id: http://devicetree.org/schemas/net/dsa/renesas,rzn1-a5psw.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Renesas RZ/N1 Advanced 5 ports ethernet switch +title: Renesas RZ/N1 A5PSW and RZ/T2H, RZ/N2H ETHSW Ethernet Switch maintainers: - Clément Léger + - Lad Prabhakar -description: | - The advanced 5 ports switch is present on the Renesas RZ/N1 SoC family and - handles 4 ports + 1 CPU management port. +description: > + This binding describes the Ethernet switch IPs used on Renesas SoCs: -allOf: - - $ref: dsa.yaml#/$defs/ethernet-ports + - The A5PSW (Advanced 5-Port Switch) found on the RZ/N1 family, which + provides 4 external ports and 1 CPU/management port. + - The ETHSW (Ethernet Switch) found on the RZ/T2H and RZ/N2H families, + which is derived from the A5PSW IP with some register layout + differences, additional timestamping support, and a total of 4 ports + including the CPU/management port. properties: compatible: - items: - - enum: - - renesas,r9a06g032-a5psw - - const: renesas,rzn1-a5psw + oneOf: + - items: + - enum: + - renesas,r9a06g032-a5psw + - const: renesas,rzn1-a5psw + + - const: renesas,r9a09g077-ethsw + + - items: + - const: renesas,r9a09g087-ethsw + - const: renesas,r9a09g077-ethsw reg: maxItems: 1 interrupts: - items: - - description: Device Level Ring (DLR) interrupt - - description: Switch interrupt - - description: Parallel Redundancy Protocol (PRP) interrupt - - description: Integrated HUB module interrupt - - description: Receive Pattern Match interrupt + oneOf: + - items: + - description: Device Level Ring (DLR) interrupt + - description: Switch interrupt + - description: Parallel Redundancy Protocol (PRP) interrupt + - description: Integrated HUB module interrupt + - description: Receive Pattern Match interrupt + + - items: + - description: Switch interrupt + - description: Device Level Ring (DLR) interrupt + - description: Parallel Redundancy Protocol (PRP) interrupt + - description: Integrated HUB module interrupt + - description: Receive Pattern Match interrupt 0 + - description: Receive Pattern Match interrupt 1 + - description: Receive Pattern Match interrupt 2 + - description: Receive Pattern Match interrupt 3 + - description: Receive Pattern Match interrupt 4 + - description: Receive Pattern Match interrupt 5 + - description: Receive Pattern Match interrupt 6 + - description: Receive Pattern Match interrupt 7 + - description: Receive Pattern Match interrupt 8 + - description: Receive Pattern Match interrupt 9 + - description: Receive Pattern Match interrupt 10 + - description: Receive Pattern Match interrupt 11 + - description: Switch timer pulse output interrupt 0 + - description: Switch timer pulse output interrupt 1 + - description: Switch timer pulse output interrupt 2 + - description: Switch timer pulse output interrupt 3 + - description: Switch TDMA timer output interrupt 0 + - description: Switch TDMA timer output interrupt 1 + - description: Switch TDMA timer output interrupt 2 + - description: Switch TDMA timer output interrupt 3 interrupt-names: - items: - - const: dlr - - const: switch - - const: prp - - const: hub - - const: ptrn + oneOf: + - items: + - const: dlr + - const: switch + - const: prp + - const: hub + - const: ptrn + + - items: + - const: switch + - const: dlr + - const: prp + - const: hub + - const: ptrn0 + - const: ptrn1 + - const: ptrn2 + - const: ptrn3 + - const: ptrn4 + - const: ptrn5 + - const: ptrn6 + - const: ptrn7 + - const: ptrn8 + - const: ptrn9 + - const: ptrn10 + - const: ptrn11 + - const: tp0 + - const: tp1 + - const: tp2 + - const: tp3 + - const: tdma0 + - const: tdma1 + - const: tdma2 + - const: tdma3 power-domains: maxItems: 1 @@ -50,14 +115,21 @@ properties: unevaluatedProperties: false clocks: + minItems: 2 items: - description: AHB clock used for the switch register interface - description: Switch system clock + - description: Timestamp clock clock-names: + minItems: 2 items: - const: hclk - const: clk + - const: ts + + resets: + maxItems: 1 ethernet-ports: type: object @@ -73,14 +145,48 @@ properties: phandle pointing to a PCS sub-node compatible with renesas,rzn1-miic.yaml# -unevaluatedProperties: false - required: - compatible - reg - clocks - clock-names - power-domains + - interrupts + - interrupt-names + +allOf: + - $ref: dsa.yaml#/$defs/ethernet-ports + + - if: + properties: + compatible: + contains: + const: renesas,r9a09g077-ethsw + then: + properties: + interrupts: + minItems: 24 + interrupt-names: + minItems: 24 + clocks: + minItems: 3 + clock-names: + minItems: 3 + required: + - resets + else: + properties: + interrupts: + maxItems: 5 + interrupt-names: + maxItems: 5 + clocks: + maxItems: 2 + clock-names: + maxItems: 2 + resets: false + +unevaluatedProperties: false examples: - | -- 2.52.0 From: Lad Prabhakar Add support for an optional reset control to the RZN1 A5PSW driver. Obtain the reset line using devm_reset_control_get_optional_exclusive_deasserted() during probe to ensure that the Ethernet switch (ETHSW) block is properly released from reset before initialization. This change prepares the driver for use on Renesas RZ/T2H and RZ/N2H SoCs, where the ETHSW IP block is connected to a dedicated reset line that must be controlled by software. Signed-off-by: Lad Prabhakar --- drivers/net/dsa/rzn1_a5psw.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/net/dsa/rzn1_a5psw.c b/drivers/net/dsa/rzn1_a5psw.c index 1635255f58e4..7b84585a5415 100644 --- a/drivers/net/dsa/rzn1_a5psw.c +++ b/drivers/net/dsa/rzn1_a5psw.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "rzn1_a5psw.h" @@ -1205,6 +1206,7 @@ static int a5psw_pcs_get(struct a5psw *a5psw) static int a5psw_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + struct reset_control *reset; struct device_node *mdio; struct dsa_switch *ds; struct a5psw *a5psw; @@ -1241,6 +1243,12 @@ static int a5psw_probe(struct platform_device *pdev) goto free_pcs; } + reset = devm_reset_control_get_optional_exclusive_deasserted(dev, NULL); + if (IS_ERR(reset)) { + ret = PTR_ERR(reset); + goto free_pcs; + } + mdio = of_get_available_child_by_name(dev->of_node, "mdio"); if (mdio) { ret = a5psw_probe_mdio(a5psw, mdio); -- 2.52.0 From: Lad Prabhakar Add support for an optional "ts" (timestamp) clock to the RZN1 A5PSW driver. Some SoC variants provide a dedicated clock source for timestamping or time synchronization features within the Ethernet switch IP. Request and enable this clock during probe if defined in the device tree. If the clock is not present, the driver continues to operate normally. This change prepares the driver for Renesas RZ/T2H and RZ/N2H SoCs, where the Ethernet switch includes a timestamp clock input. Signed-off-by: Lad Prabhakar --- drivers/net/dsa/rzn1_a5psw.c | 7 +++++++ drivers/net/dsa/rzn1_a5psw.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/drivers/net/dsa/rzn1_a5psw.c b/drivers/net/dsa/rzn1_a5psw.c index 7b84585a5415..99098bc06efe 100644 --- a/drivers/net/dsa/rzn1_a5psw.c +++ b/drivers/net/dsa/rzn1_a5psw.c @@ -1243,6 +1243,13 @@ static int a5psw_probe(struct platform_device *pdev) goto free_pcs; } + a5psw->ts = devm_clk_get_optional_enabled(dev, "ts"); + if (IS_ERR(a5psw->ts)) { + dev_err(dev, "failed get ts clock\n"); + ret = PTR_ERR(a5psw->ts); + goto free_pcs; + } + reset = devm_reset_control_get_optional_exclusive_deasserted(dev, NULL); if (IS_ERR(reset)) { ret = PTR_ERR(reset); diff --git a/drivers/net/dsa/rzn1_a5psw.h b/drivers/net/dsa/rzn1_a5psw.h index d54acedac194..81be30d6c55f 100644 --- a/drivers/net/dsa/rzn1_a5psw.h +++ b/drivers/net/dsa/rzn1_a5psw.h @@ -236,6 +236,7 @@ union lk_data { * @base: Base address of the switch * @hclk: hclk_switch clock * @clk: clk_switch clock + * @ts: Timestamp clock * @dev: Device associated to the switch * @mii_bus: MDIO bus struct * @mdio_freq: MDIO bus frequency requested @@ -251,6 +252,7 @@ struct a5psw { void __iomem *base; struct clk *hclk; struct clk *clk; + struct clk *ts; struct device *dev; struct mii_bus *mii_bus; struct phylink_pcs *pcs[A5PSW_PORTS_NUM - 1]; -- 2.52.0 From: Lad Prabhakar Move the switch topology description-the number of ports and the CPU-port index-out of hard-coded constants and into SoC-specific OF match data. The driver previously assumed a fixed 5-port layout with the last port acting as the CPU port. That assumption does not hold for newer Renesas variants, and embedding it in the code made the driver inflexible and error-prone. Introduce a small a5psw_of_data structure carrying both the total number of ports and the CPU-port identifier, and rely on this data everywhere the driver previously used fixed values. This ensures that port loops, PCS allocation, management-port setup, and bridge bookkeeping all reflect the actual hardware configuration. Making these attributes runtime-selectable allows the driver to support RZ/T2H and RZ/N2H SoCs which use different port counts and CPU-port assignments-without rewriting common logic or forking the driver, while preserving correct behaviour on existing RZN1 systems. Signed-off-by: Lad Prabhakar --- drivers/net/dsa/rzn1_a5psw.c | 26 +++++++++++++++++--------- drivers/net/dsa/rzn1_a5psw.h | 17 ++++++++++++++--- 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/drivers/net/dsa/rzn1_a5psw.c b/drivers/net/dsa/rzn1_a5psw.c index 99098bc06efe..d957b6d40f05 100644 --- a/drivers/net/dsa/rzn1_a5psw.c +++ b/drivers/net/dsa/rzn1_a5psw.c @@ -382,13 +382,14 @@ static void a5psw_port_bridge_leave(struct dsa_switch *ds, int port, struct dsa_bridge bridge) { struct a5psw *a5psw = ds->priv; + unsigned int cpu_port = a5psw->of_data->cpu_port; a5psw->bridged_ports &= ~BIT(port); a5psw_port_set_standalone(a5psw, port, true); /* No more ports bridged */ - if (a5psw->bridged_ports == BIT(A5PSW_CPU_PORT)) + if (a5psw->bridged_ports == BIT(cpu_port)) a5psw->br_dev = NULL; } @@ -924,20 +925,21 @@ static void a5psw_vlan_setup(struct a5psw *a5psw, int port) static int a5psw_setup(struct dsa_switch *ds) { struct a5psw *a5psw = ds->priv; + unsigned int cpu_port = a5psw->of_data->cpu_port; int port, vlan, ret; struct dsa_port *dp; u32 reg; - /* Validate that there is only 1 CPU port with index A5PSW_CPU_PORT */ + /* Validate that there is only 1 CPU port with index matching cpu_port */ dsa_switch_for_each_cpu_port(dp, ds) { - if (dp->index != A5PSW_CPU_PORT) { + if (dp->index != cpu_port) { dev_err(a5psw->dev, "Invalid CPU port\n"); return -EINVAL; } } /* Configure management port */ - reg = A5PSW_CPU_PORT | A5PSW_MGMT_CFG_ENABLE; + reg = cpu_port | A5PSW_MGMT_CFG_ENABLE; a5psw_reg_writel(a5psw, A5PSW_MGMT_CFG, reg); /* Set pattern 0 to forward all frame to mgmt port */ @@ -1147,7 +1149,7 @@ static void a5psw_pcs_free(struct a5psw *a5psw) { int i; - for (i = 0; i < ARRAY_SIZE(a5psw->pcs); i++) { + for (i = 0; i < a5psw->of_data->nports - 1; i++) { if (a5psw->pcs[i]) miic_destroy(a5psw->pcs[i]); } @@ -1174,7 +1176,7 @@ static int a5psw_pcs_get(struct a5psw *a5psw) goto free_pcs; } - if (reg >= ARRAY_SIZE(a5psw->pcs)) { + if (reg >= a5psw->of_data->nports - 1) { ret = -ENODEV; goto free_pcs; } @@ -1223,7 +1225,8 @@ static int a5psw_probe(struct platform_device *pdev) if (IS_ERR(a5psw->base)) return PTR_ERR(a5psw->base); - a5psw->bridged_ports = BIT(A5PSW_CPU_PORT); + a5psw->of_data = of_device_get_match_data(dev); + a5psw->bridged_ports = BIT(a5psw->of_data->cpu_port); ret = a5psw_pcs_get(a5psw); if (ret) @@ -1268,7 +1271,7 @@ static int a5psw_probe(struct platform_device *pdev) ds = &a5psw->ds; ds->dev = dev; - ds->num_ports = A5PSW_PORTS_NUM; + ds->num_ports = a5psw->of_data->nports; ds->ops = &a5psw_switch_ops; ds->phylink_mac_ops = &a5psw_phylink_mac_ops; ds->priv = a5psw; @@ -1310,8 +1313,13 @@ static void a5psw_shutdown(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); } +static const struct a5psw_of_data rzn1_of_data = { + .nports = 5, + .cpu_port = 4, +}; + static const struct of_device_id a5psw_of_mtable[] = { - { .compatible = "renesas,rzn1-a5psw", }, + { .compatible = "renesas,rzn1-a5psw", .data = &rzn1_of_data }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, a5psw_of_mtable); diff --git a/drivers/net/dsa/rzn1_a5psw.h b/drivers/net/dsa/rzn1_a5psw.h index 81be30d6c55f..d1b2cc5b43e6 100644 --- a/drivers/net/dsa/rzn1_a5psw.h +++ b/drivers/net/dsa/rzn1_a5psw.h @@ -195,8 +195,7 @@ #define A5PSW_aCarrierSenseErrors 0x924 #define A5PSW_VLAN_TAG(prio, id) (((prio) << 12) | (id)) -#define A5PSW_PORTS_NUM 5 -#define A5PSW_CPU_PORT (A5PSW_PORTS_NUM - 1) +#define A5PSW_MAX_PORTS 4 #define A5PSW_MDIO_DEF_FREQ 2500000 #define A5PSW_MDIO_TIMEOUT 100 #define A5PSW_JUMBO_LEN (10 * SZ_1K) @@ -231,6 +230,16 @@ union lk_data { struct fdb_entry entry; }; +/** + * struct a5psw_of_data - OF data structure + * @nports: Number of ports in the switch + * @cpu_port: CPU port number + */ +struct a5psw_of_data { + unsigned int nports; + unsigned int cpu_port; +}; + /** * struct a5psw - switch struct * @base: Base address of the switch @@ -238,6 +247,7 @@ union lk_data { * @clk: clk_switch clock * @ts: Timestamp clock * @dev: Device associated to the switch + * @of_data: Pointer to OF data * @mii_bus: MDIO bus struct * @mdio_freq: MDIO bus frequency requested * @pcs: Array of PCS connected to the switch ports (not for the CPU) @@ -254,8 +264,9 @@ struct a5psw { struct clk *clk; struct clk *ts; struct device *dev; + const struct a5psw_of_data *of_data; struct mii_bus *mii_bus; - struct phylink_pcs *pcs[A5PSW_PORTS_NUM - 1]; + struct phylink_pcs *pcs[A5PSW_MAX_PORTS]; struct dsa_switch ds; struct mutex lk_lock; spinlock_t reg_lock; -- 2.52.0 From: Lad Prabhakar Update the RZN1 A5PSW driver to obtain the DSA tag protocol from device-specific data instead of using a hard-coded value. Add a new `tag_proto` field to `struct a5psw_of_data` and use it in `a5psw_get_tag_protocol()` to return the appropriate protocol for each SoC. This allows future SoCs such as RZ/T2H and RZ/N2H, which use the DSA_TAG_PROTO_RZT2H_ETHSW tag format, to share the same driver infrastructure without code duplication. Signed-off-by: Lad Prabhakar --- drivers/net/dsa/rzn1_a5psw.c | 5 ++++- drivers/net/dsa/rzn1_a5psw.h | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/dsa/rzn1_a5psw.c b/drivers/net/dsa/rzn1_a5psw.c index d957b6d40f05..dc42a409eaef 100644 --- a/drivers/net/dsa/rzn1_a5psw.c +++ b/drivers/net/dsa/rzn1_a5psw.c @@ -97,7 +97,9 @@ static enum dsa_tag_protocol a5psw_get_tag_protocol(struct dsa_switch *ds, int port, enum dsa_tag_protocol mp) { - return DSA_TAG_PROTO_RZN1_A5PSW; + struct a5psw *a5psw = ds->priv; + + return a5psw->of_data->tag_proto; } static void a5psw_port_pattern_set(struct a5psw *a5psw, int port, int pattern, @@ -1316,6 +1318,7 @@ static void a5psw_shutdown(struct platform_device *pdev) static const struct a5psw_of_data rzn1_of_data = { .nports = 5, .cpu_port = 4, + .tag_proto = DSA_TAG_PROTO_RZN1_A5PSW, }; static const struct of_device_id a5psw_of_mtable[] = { diff --git a/drivers/net/dsa/rzn1_a5psw.h b/drivers/net/dsa/rzn1_a5psw.h index d1b2cc5b43e6..0fef32451e4f 100644 --- a/drivers/net/dsa/rzn1_a5psw.h +++ b/drivers/net/dsa/rzn1_a5psw.h @@ -234,10 +234,12 @@ union lk_data { * struct a5psw_of_data - OF data structure * @nports: Number of ports in the switch * @cpu_port: CPU port number + * @tag_proto: DSA tag protocol used by the switch */ struct a5psw_of_data { unsigned int nports; unsigned int cpu_port; + enum dsa_tag_protocol tag_proto; }; /** -- 2.52.0 From: Lad Prabhakar Extend the RZN1 A5PSW driver to support SoC-specific adjustments to the management (CPU) port frame length. Some SoCs, such as the RZ/T2H and RZ/N2H, require additional headroom on the management port to account for a special management tag added to frames. Without this adjustment, frames may be incorrectly detected as oversized and subsequently discarded. Introduce a new field, `management_port_frame_len_adj`, in `struct a5psw_of_data` to represent this adjustment, and apply it in `a5psw_port_change_mtu()` when configuring the frame length for the CPU port. This change prepares the driver for use on RZ/T2H and RZ/N2H SoCs. Signed-off-by: Lad Prabhakar --- drivers/net/dsa/rzn1_a5psw.c | 4 ++++ drivers/net/dsa/rzn1_a5psw.h | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/drivers/net/dsa/rzn1_a5psw.c b/drivers/net/dsa/rzn1_a5psw.c index dc42a409eaef..82f4236a726e 100644 --- a/drivers/net/dsa/rzn1_a5psw.c +++ b/drivers/net/dsa/rzn1_a5psw.c @@ -211,6 +211,10 @@ static int a5psw_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu) struct a5psw *a5psw = ds->priv; new_mtu += ETH_HLEN + A5PSW_EXTRA_MTU_LEN + ETH_FCS_LEN; + + if (dsa_is_cpu_port(ds, port)) + new_mtu += a5psw->of_data->management_port_frame_len_adj; + a5psw_reg_writel(a5psw, A5PSW_FRM_LENGTH(port), new_mtu); return 0; diff --git a/drivers/net/dsa/rzn1_a5psw.h b/drivers/net/dsa/rzn1_a5psw.h index 0fef32451e4f..41c910d534cf 100644 --- a/drivers/net/dsa/rzn1_a5psw.h +++ b/drivers/net/dsa/rzn1_a5psw.h @@ -235,11 +235,15 @@ union lk_data { * @nports: Number of ports in the switch * @cpu_port: CPU port number * @tag_proto: DSA tag protocol used by the switch + * @management_port_frame_len_adj: Adjustment to apply to management + * port frame length to account for accepting a frame with special + * management tag. */ struct a5psw_of_data { unsigned int nports; unsigned int cpu_port; enum dsa_tag_protocol tag_proto; + unsigned int management_port_frame_len_adj; }; /** -- 2.52.0 From: Lad Prabhakar Add device tree match data and configuration for the Renesas RZ/T2H SoC Ethernet switch. The RZ/T2H uses the same A5PSW switch IP as RZ/N1 but with four ports, the DSA tagging protocol `DSA_TAG_PROTO_RZT2H_ETHSW`, and an additional 8-byte management port frame length adjustment. This prepares the driver to handle RZ/T2H and compatible RZ/N2H Ethernet switch instances. Signed-off-by: Lad Prabhakar --- drivers/net/dsa/rzn1_a5psw.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/net/dsa/rzn1_a5psw.c b/drivers/net/dsa/rzn1_a5psw.c index 82f4236a726e..9f85a4526bd2 100644 --- a/drivers/net/dsa/rzn1_a5psw.c +++ b/drivers/net/dsa/rzn1_a5psw.c @@ -1319,6 +1319,13 @@ static void a5psw_shutdown(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); } +static const struct a5psw_of_data rzt2h_of_data = { + .nports = 4, + .cpu_port = 3, + .tag_proto = DSA_TAG_PROTO_RZT2H_ETHSW, + .management_port_frame_len_adj = 40, +}; + static const struct a5psw_of_data rzn1_of_data = { .nports = 5, .cpu_port = 4, @@ -1326,6 +1333,7 @@ static const struct a5psw_of_data rzn1_of_data = { }; static const struct of_device_id a5psw_of_mtable[] = { + { .compatible = "renesas,r9a09g077-ethsw", .data = &rzt2h_of_data }, { .compatible = "renesas,rzn1-a5psw", .data = &rzn1_of_data }, { /* sentinel */ }, }; -- 2.52.0 From: Lad Prabhakar Update the Kconfig entry for the Renesas RZ/N1 A5PSW Ethernet switch driver to depend on ARCH_RENESAS instead of ARCH_RZN1. This allows the driver to be built for other Renesas SoCs that integrate a similar Ethernet switch IP, such as RZ/T2H and RZ/N2H. Also update the help text and prompt to reflect support for the ETHSW variant used on these SoCs. Signed-off-by: Lad Prabhakar --- drivers/net/dsa/Kconfig | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig index 7eb301fd987d..9c44c530ebb1 100644 --- a/drivers/net/dsa/Kconfig +++ b/drivers/net/dsa/Kconfig @@ -85,13 +85,14 @@ source "drivers/net/dsa/xrs700x/Kconfig" source "drivers/net/dsa/realtek/Kconfig" config NET_DSA_RZN1_A5PSW - tristate "Renesas RZ/N1 A5PSW Ethernet switch support" - depends on OF && (ARCH_RZN1 || COMPILE_TEST) + tristate "Renesas RZ/N1 A5PSW and RZ/{T2H,N2H} ETHSW Ethernet switch support" + depends on OF && (ARCH_RENESAS || COMPILE_TEST) select NET_DSA_TAG_RZN1_A5PSW select PCS_RZN1_MIIC help - This driver supports the A5PSW switch, which is embedded in Renesas - RZ/N1 SoC. + This driver supports the Advanced 5-Port Switch (A5PSW) found on + Renesas RZ/N1 SoCs, and the Ethernet Switch (ETHSW) found on + Renesas RZ/T2H and RZ/N2H SoCs. config NET_DSA_KS8995 tristate "Micrel KS8995 family 5-ports 10/100 Ethernet switches" -- 2.52.0