Commit c83bc86a authored by David S. Miller's avatar David S. Miller

Merge branch 'Renesas-rz-n1'

Clément Léger says:

====================
net: add support for Renesas RZ/N1 ethernet su

The Renesas RZ/N1 SoCs features an ethernet subsystem which contains
(most notably) a switch, two GMACs, and a MII converter [1]. This
series adds support for the switch and the MII converter.

The MII converter present on this SoC has been represented as a PCS
which sit between the MACs and the PHY. This PCS driver is probed from
the device-tree since it requires to be configured. Indeed the MII
converter also contains the registers that are handling the muxing of
ports (Switch, MAC, HSR, RTOS, etc) internally to the SoC.

The switch driver is based on DSA and exposes 4 ports + 1 CPU
management port. It include basic bridging support as well as FDB and
statistics support.

Link: [1] https://www.renesas.com/us/en/document/mah/rzn1d-group-rzn1s-group-rzn1l-group-users-manual-r-engine-and-ethernet-peripherals

-----
Changes in V9:
- Cover letter:
  - Remove comment about RZN1 patches that are now in the master branch.
- Commits:
  - Add Vladimir Oltean Reviewed-by
- PCS:
  - Add "Depends on OF" for PCS_RZN1_MIIC due to error found by intel
    kernel test robot <lkp@intel.com>.
  - Check return value of of_property_read_u32() for
    "renesas,miic-switch-portin" property before setting conf.
  - Return miic_parse_dt() return value in miic_probe() on error
- Switch:
  - Add "Depends on OF" for NET_DSA_RZN1_A5PSW due to errors found by
    intel kernel test robot <lkp@intel.com>.
- DT:
  - Add spaces between switch port and '{'
====================
Reviewed-by: default avatarVladimir Oltean <olteanv@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ebeae54d 717a5c56
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$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
maintainers:
- Clément Léger <clement.leger@bootlin.com>
description: |
The advanced 5 ports switch is present on the Renesas RZ/N1 SoC family and
handles 4 ports + 1 CPU management port.
allOf:
- $ref: dsa.yaml#
properties:
compatible:
items:
- enum:
- renesas,r9a06g032-a5psw
- const: renesas,rzn1-a5psw
reg:
maxItems: 1
power-domains:
maxItems: 1
mdio:
$ref: /schemas/net/mdio.yaml#
unevaluatedProperties: false
clocks:
items:
- description: AHB clock used for the switch register interface
- description: Switch system clock
clock-names:
items:
- const: hclk
- const: clk
ethernet-ports:
type: object
properties:
'#address-cells':
const: 1
'#size-cells':
const: 0
patternProperties:
"^(ethernet-)?port@[0-4]$":
type: object
description: Ethernet switch ports
properties:
pcs-handle:
description:
phandle pointing to a PCS sub-node compatible with
renesas,rzn1-miic.yaml#
$ref: /schemas/types.yaml#/definitions/phandle
unevaluatedProperties: false
required:
- compatible
- reg
- clocks
- clock-names
- power-domains
examples:
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/clock/r9a06g032-sysctrl.h>
switch@44050000 {
compatible = "renesas,r9a06g032-a5psw", "renesas,rzn1-a5psw";
reg = <0x44050000 0x10000>;
clocks = <&sysctrl R9A06G032_HCLK_SWITCH>, <&sysctrl R9A06G032_CLK_SWITCH>;
clock-names = "hclk", "clk";
power-domains = <&sysctrl>;
dsa,member = <0 0>;
ethernet-ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
label = "lan0";
phy-handle = <&switch0phy3>;
pcs-handle = <&mii_conv4>;
};
port@1 {
reg = <1>;
label = "lan1";
phy-handle = <&switch0phy1>;
pcs-handle = <&mii_conv3>;
};
port@4 {
reg = <4>;
ethernet = <&gmac2>;
label = "cpu";
fixed-link {
speed = <1000>;
full-duplex;
};
};
};
mdio {
#address-cells = <1>;
#size-cells = <0>;
reset-gpios = <&gpio0a 2 GPIO_ACTIVE_HIGH>;
reset-delay-us = <15>;
clock-frequency = <2500000>;
switch0phy1: ethernet-phy@1{
reg = <1>;
};
switch0phy3: ethernet-phy@3{
reg = <3>;
};
};
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/pcs/renesas,rzn1-miic.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Renesas RZ/N1 MII converter
maintainers:
- Clément Léger <clement.leger@bootlin.com>
description: |
This MII converter is present on the Renesas RZ/N1 SoC family. It is
responsible to do MII passthrough or convert it to RMII/RGMII.
properties:
'#address-cells':
const: 1
'#size-cells':
const: 0
compatible:
items:
- enum:
- renesas,r9a06g032-miic
- const: renesas,rzn1-miic
reg:
maxItems: 1
clocks:
items:
- description: MII reference clock
- description: RGMII reference clock
- description: RMII reference clock
- description: AHB clock used for the MII converter register interface
clock-names:
items:
- const: mii_ref
- const: rgmii_ref
- const: rmii_ref
- const: hclk
renesas,miic-switch-portin:
description: MII Switch PORTIN configuration. This value should use one of
the values defined in dt-bindings/net/pcs-rzn1-miic.h.
$ref: /schemas/types.yaml#/definitions/uint32
enum: [1, 2]
power-domains:
maxItems: 1
patternProperties:
"^mii-conv@[0-5]$":
type: object
description: MII converter port
properties:
reg:
description: MII Converter port number.
enum: [1, 2, 3, 4, 5]
renesas,miic-input:
description: Converter input port configuration. This value should use
one of the values defined in dt-bindings/net/pcs-rzn1-miic.h.
$ref: /schemas/types.yaml#/definitions/uint32
required:
- reg
- renesas,miic-input
additionalProperties: false
allOf:
- if:
properties:
reg:
const: 1
then:
properties:
renesas,miic-input:
const: 0
- if:
properties:
reg:
const: 2
then:
properties:
renesas,miic-input:
enum: [1, 11]
- if:
properties:
reg:
const: 3
then:
properties:
renesas,miic-input:
enum: [7, 10]
- if:
properties:
reg:
const: 4
then:
properties:
renesas,miic-input:
enum: [4, 6, 9, 13]
- if:
properties:
reg:
const: 5
then:
properties:
renesas,miic-input:
enum: [3, 5, 8, 12]
required:
- '#address-cells'
- '#size-cells'
- compatible
- reg
- clocks
- clock-names
- power-domains
additionalProperties: false
examples:
- |
#include <dt-bindings/net/pcs-rzn1-miic.h>
#include <dt-bindings/clock/r9a06g032-sysctrl.h>
eth-miic@44030000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "renesas,r9a06g032-miic", "renesas,rzn1-miic";
reg = <0x44030000 0x10000>;
clocks = <&sysctrl R9A06G032_CLK_MII_REF>,
<&sysctrl R9A06G032_CLK_RGMII_REF>,
<&sysctrl R9A06G032_CLK_RMII_REF>,
<&sysctrl R9A06G032_HCLK_SWITCH_RG>;
clock-names = "mii_ref", "rgmii_ref", "rmii_ref", "hclk";
renesas,miic-switch-portin = <MIIC_GMAC2_PORT>;
power-domains = <&sysctrl>;
mii_conv1: mii-conv@1 {
renesas,miic-input = <MIIC_GMAC1_PORT>;
reg = <1>;
};
mii_conv2: mii-conv@2 {
renesas,miic-input = <MIIC_SWITCH_PORTD>;
reg = <2>;
};
mii_conv3: mii-conv@3 {
renesas,miic-input = <MIIC_SWITCH_PORTC>;
reg = <3>;
};
mii_conv4: mii-conv@4 {
renesas,miic-input = <MIIC_SWITCH_PORTB>;
reg = <4>;
};
mii_conv5: mii-conv@5 {
renesas,miic-input = <MIIC_SWITCH_PORTA>;
reg = <5>;
};
};
......@@ -65,6 +65,8 @@ properties:
- ingenic,x2000-mac
- loongson,ls2k-dwmac
- loongson,ls7a-dwmac
- renesas,r9a06g032-gmac
- renesas,rzn1-gmac
- rockchip,px30-gmac
- rockchip,rk3128-gmac
- rockchip,rk3228-gmac
......@@ -135,6 +137,9 @@ properties:
reset-names:
const: stmmaceth
power-domains:
maxItems: 1
mac-mode:
$ref: ethernet-controller.yaml#/properties/phy-connection-type
description:
......
......@@ -17056,6 +17056,19 @@ S: Supported
F: Documentation/devicetree/bindings/iio/adc/renesas,rzg2l-adc.yaml
F: drivers/iio/adc/rzg2l_adc.c
RENESAS RZ/N1 A5PSW SWITCH DRIVER
M: Clément Léger <clement.leger@bootlin.com>
L: linux-renesas-soc@vger.kernel.org
L: netdev@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/net/dsa/renesas,rzn1-a5psw.yaml
F: Documentation/devicetree/bindings/net/pcs/renesas,rzn1-miic.yaml
F: drivers/net/dsa/rzn1_a5psw*
F: drivers/net/pcs/pcs-rzn1-miic.c
F: include/dt-bindings/net/pcs-rzn1-miic.h
F: include/linux/pcs-rzn1-miic.h
F: net/dsa/tag_rzn1_a5psw.c
RENESAS RZ/N1 RTC CONTROLLER DRIVER
M: Miquel Raynal <miquel.raynal@bootlin.com>
L: linux-rtc@vger.kernel.org
......
......@@ -8,6 +8,8 @@
/dts-v1/;
#include <dt-bindings/pinctrl/rzn1-pinctrl.h>
#include <dt-bindings/net/pcs-rzn1-miic.h>
#include "r9a06g032.dtsi"
/ {
......@@ -31,3 +33,118 @@ &wdt0 {
timeout-sec = <60>;
status = "okay";
};
&gmac2 {
status = "okay";
phy-mode = "gmii";
fixed-link {
speed = <1000>;
full-duplex;
};
};
&switch {
status = "okay";
#address-cells = <1>;
#size-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&pins_mdio1>, <&pins_eth3>, <&pins_eth4>;
dsa,member = <0 0>;
mdio {
clock-frequency = <2500000>;
#address-cells = <1>;
#size-cells = <0>;
switch0phy4: ethernet-phy@4 {
reg = <4>;
micrel,led-mode = <1>;
};
switch0phy5: ethernet-phy@5 {
reg = <5>;
micrel,led-mode = <1>;
};
};
};
&switch_port0 {
label = "lan0";
phy-mode = "mii";
phy-handle = <&switch0phy5>;
status = "okay";
};
&switch_port1 {
label = "lan1";
phy-mode = "mii";
phy-handle = <&switch0phy4>;
status = "okay";
};
&switch_port4 {
status = "okay";
};
&eth_miic {
status = "okay";
renesas,miic-switch-portin = <MIIC_GMAC2_PORT>;
};
&mii_conv4 {
renesas,miic-input = <MIIC_SWITCH_PORTB>;
status = "okay";
};
&mii_conv5 {
renesas,miic-input = <MIIC_SWITCH_PORTA>;
status = "okay";
};
&pinctrl{
pins_mdio1: pins_mdio1 {
pinmux = <
RZN1_PINMUX(152, RZN1_FUNC_MDIO1_SWITCH)
RZN1_PINMUX(153, RZN1_FUNC_MDIO1_SWITCH)
>;
};
pins_eth3: pins_eth3 {
pinmux = <
RZN1_PINMUX(36, RZN1_FUNC_CLK_ETH_MII_RGMII_RMII)
RZN1_PINMUX(37, RZN1_FUNC_CLK_ETH_MII_RGMII_RMII)
RZN1_PINMUX(38, RZN1_FUNC_CLK_ETH_MII_RGMII_RMII)
RZN1_PINMUX(39, RZN1_FUNC_CLK_ETH_MII_RGMII_RMII)
RZN1_PINMUX(40, RZN1_FUNC_CLK_ETH_MII_RGMII_RMII)
RZN1_PINMUX(41, RZN1_FUNC_CLK_ETH_MII_RGMII_RMII)
RZN1_PINMUX(42, RZN1_FUNC_CLK_ETH_MII_RGMII_RMII)
RZN1_PINMUX(43, RZN1_FUNC_CLK_ETH_MII_RGMII_RMII)
RZN1_PINMUX(44, RZN1_FUNC_CLK_ETH_MII_RGMII_RMII)
RZN1_PINMUX(45, RZN1_FUNC_CLK_ETH_MII_RGMII_RMII)
RZN1_PINMUX(46, RZN1_FUNC_CLK_ETH_MII_RGMII_RMII)
RZN1_PINMUX(47, RZN1_FUNC_CLK_ETH_MII_RGMII_RMII)
>;
drive-strength = <6>;
bias-disable;
};
pins_eth4: pins_eth4 {
pinmux = <
RZN1_PINMUX(48, RZN1_FUNC_CLK_ETH_MII_RGMII_RMII)
RZN1_PINMUX(49, RZN1_FUNC_CLK_ETH_MII_RGMII_RMII)
RZN1_PINMUX(50, RZN1_FUNC_CLK_ETH_MII_RGMII_RMII)
RZN1_PINMUX(51, RZN1_FUNC_CLK_ETH_MII_RGMII_RMII)
RZN1_PINMUX(52, RZN1_FUNC_CLK_ETH_MII_RGMII_RMII)
RZN1_PINMUX(53, RZN1_FUNC_CLK_ETH_MII_RGMII_RMII)
RZN1_PINMUX(54, RZN1_FUNC_CLK_ETH_MII_RGMII_RMII)
RZN1_PINMUX(55, RZN1_FUNC_CLK_ETH_MII_RGMII_RMII)
RZN1_PINMUX(56, RZN1_FUNC_CLK_ETH_MII_RGMII_RMII)
RZN1_PINMUX(57, RZN1_FUNC_CLK_ETH_MII_RGMII_RMII)
RZN1_PINMUX(58, RZN1_FUNC_CLK_ETH_MII_RGMII_RMII)
RZN1_PINMUX(59, RZN1_FUNC_CLK_ETH_MII_RGMII_RMII)
>;
drive-strength = <6>;
bias-disable;
};
};
......@@ -304,6 +304,114 @@ dma1: dma-controller@40105000 {
data-width = <8>;
};
gmac2: ethernet@44002000 {
compatible = "renesas,r9a06g032-gmac", "renesas,rzn1-gmac", "snps,dwmac";
reg = <0x44002000 0x2000>;
interrupt-parent = <&gic>;
interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "macirq", "eth_wake_irq", "eth_lpi";
clocks = <&sysctrl R9A06G032_HCLK_GMAC1>;
clock-names = "stmmaceth";
power-domains = <&sysctrl>;
snps,multicast-filter-bins = <256>;
snps,perfect-filter-entries = <128>;
tx-fifo-depth = <2048>;
rx-fifo-depth = <4096>;
status = "disabled";
};
eth_miic: eth-miic@44030000 {
compatible = "renesas,r9a06g032-miic", "renesas,rzn1-miic";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x44030000 0x10000>;
clocks = <&sysctrl R9A06G032_CLK_MII_REF>,
<&sysctrl R9A06G032_CLK_RGMII_REF>,
<&sysctrl R9A06G032_CLK_RMII_REF>,
<&sysctrl R9A06G032_HCLK_SWITCH_RG>;
clock-names = "mii_ref", "rgmii_ref", "rmii_ref", "hclk";
power-domains = <&sysctrl>;
status = "disabled";
mii_conv1: mii-conv@1 {
reg = <1>;
status = "disabled";
};
mii_conv2: mii-conv@2 {
reg = <2>;
status = "disabled";
};
mii_conv3: mii-conv@3 {
reg = <3>;
status = "disabled";
};
mii_conv4: mii-conv@4 {
reg = <4>;
status = "disabled";
};
mii_conv5: mii-conv@5 {
reg = <5>;
status = "disabled";
};
};
switch: switch@44050000 {
compatible = "renesas,r9a06g032-a5psw", "renesas,rzn1-a5psw";
reg = <0x44050000 0x10000>;
clocks = <&sysctrl R9A06G032_HCLK_SWITCH>,
<&sysctrl R9A06G032_CLK_SWITCH>;
clock-names = "hclk", "clk";
power-domains = <&sysctrl>;
status = "disabled";
ethernet-ports {
#address-cells = <1>;
#size-cells = <0>;
switch_port0: port@0 {
reg = <0>;
pcs-handle = <&mii_conv5>;
status = "disabled";
};
switch_port1: port@1 {
reg = <1>;
pcs-handle = <&mii_conv4>;
status = "disabled";
};
switch_port2: port@2 {
reg = <2>;
pcs-handle = <&mii_conv3>;
status = "disabled";
};
switch_port3: port@3 {
reg = <3>;
pcs-handle = <&mii_conv2>;
status = "disabled";
};
switch_port4: port@4 {
reg = <4>;
ethernet = <&gmac2>;
label = "cpu";
phy-mode = "internal";
status = "disabled";
fixed-link {
speed = <1000>;
full-duplex;
};
};
};
};
gic: interrupt-controller@44101000 {
compatible = "arm,gic-400", "arm,cortex-a7-gic";
interrupt-controller;
......
......@@ -70,6 +70,15 @@ config NET_DSA_QCA8K
source "drivers/net/dsa/realtek/Kconfig"
config NET_DSA_RZN1_A5PSW
tristate "Renesas RZ/N1 A5PSW Ethernet switch support"
depends on OF && ARCH_RZN1
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.
config NET_DSA_SMSC_LAN9303
tristate
select NET_DSA_TAG_LAN9303
......
......@@ -9,6 +9,7 @@ obj-$(CONFIG_NET_DSA_LANTIQ_GSWIP) += lantiq_gswip.o
obj-$(CONFIG_NET_DSA_MT7530) += mt7530.o
obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
obj-$(CONFIG_NET_DSA_QCA8K) += qca8k.o
obj-$(CONFIG_NET_DSA_RZN1_A5PSW) += rzn1_a5psw.o
obj-$(CONFIG_NET_DSA_SMSC_LAN9303) += lan9303-core.o
obj-$(CONFIG_NET_DSA_SMSC_LAN9303_I2C) += lan9303_i2c.o
obj-$(CONFIG_NET_DSA_SMSC_LAN9303_MDIO) += lan9303_mdio.o
......
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2022 Schneider Electric
*
* Clément Léger <clement.leger@bootlin.com>
*/
#include <linux/clk.h>
#include <linux/debugfs.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_mdio.h>
#include <linux/platform_device.h>
#include <linux/pcs-rzn1-miic.h>
#include <net/dsa.h>
#define A5PSW_REVISION 0x0
#define A5PSW_PORT_OFFSET(port) (0x400 * (port))
#define A5PSW_PORT_ENA 0x8
#define A5PSW_PORT_ENA_RX_SHIFT 16
#define A5PSW_PORT_ENA_TX_RX(port) (BIT((port) + A5PSW_PORT_ENA_RX_SHIFT) | \
BIT(port))
#define A5PSW_UCAST_DEF_MASK 0xC
#define A5PSW_VLAN_VERIFY 0x10
#define A5PSW_VLAN_VERI_SHIFT 0
#define A5PSW_VLAN_DISC_SHIFT 16
#define A5PSW_BCAST_DEF_MASK 0x14
#define A5PSW_MCAST_DEF_MASK 0x18
#define A5PSW_INPUT_LEARN 0x1C
#define A5PSW_INPUT_LEARN_DIS(p) BIT((p) + 16)
#define A5PSW_INPUT_LEARN_BLOCK(p) BIT(p)
#define A5PSW_MGMT_CFG 0x20
#define A5PSW_MGMT_CFG_DISCARD BIT(7)
#define A5PSW_MODE_CFG 0x24
#define A5PSW_MODE_STATS_RESET BIT(31)
#define A5PSW_VLAN_IN_MODE 0x28
#define A5PSW_VLAN_IN_MODE_PORT_SHIFT(port) ((port) * 2)
#define A5PSW_VLAN_IN_MODE_PORT(port) (GENMASK(1, 0) << \
A5PSW_VLAN_IN_MODE_PORT_SHIFT(port))
#define A5PSW_VLAN_IN_MODE_SINGLE_PASSTHROUGH 0x0
#define A5PSW_VLAN_IN_MODE_SINGLE_REPLACE 0x1
#define A5PSW_VLAN_IN_MODE_TAG_ALWAYS 0x2
#define A5PSW_VLAN_OUT_MODE 0x2C
#define A5PSW_VLAN_OUT_MODE_PORT(port) (GENMASK(1, 0) << ((port) * 2))
#define A5PSW_VLAN_OUT_MODE_DIS 0x0
#define A5PSW_VLAN_OUT_MODE_STRIP 0x1
#define A5PSW_VLAN_OUT_MODE_TAG_THROUGH 0x2
#define A5PSW_VLAN_OUT_MODE_TRANSPARENT 0x3
#define A5PSW_VLAN_IN_MODE_ENA 0x30
#define A5PSW_VLAN_TAG_ID 0x34
#define A5PSW_SYSTEM_TAGINFO(port) (0x200 + A5PSW_PORT_OFFSET(port))
#define A5PSW_AUTH_PORT(port) (0x240 + 4 * (port))
#define A5PSW_AUTH_PORT_AUTHORIZED BIT(0)
#define A5PSW_VLAN_RES(entry) (0x280 + 4 * (entry))
#define A5PSW_VLAN_RES_WR_PORTMASK BIT(30)
#define A5PSW_VLAN_RES_WR_TAGMASK BIT(29)
#define A5PSW_VLAN_RES_RD_TAGMASK BIT(28)
#define A5PSW_VLAN_RES_ID GENMASK(16, 5)
#define A5PSW_VLAN_RES_PORTMASK GENMASK(4, 0)
#define A5PSW_RXMATCH_CONFIG(port) (0x3e80 + 4 * (port))
#define A5PSW_RXMATCH_CONFIG_PATTERN(p) BIT(p)
#define A5PSW_PATTERN_CTRL(p) (0x3eb0 + 4 * (p))
#define A5PSW_PATTERN_CTRL_MGMTFWD BIT(1)
#define A5PSW_LK_CTRL 0x400
#define A5PSW_LK_ADDR_CTRL_BLOCKING BIT(0)
#define A5PSW_LK_ADDR_CTRL_LEARNING BIT(1)
#define A5PSW_LK_ADDR_CTRL_AGEING BIT(2)
#define A5PSW_LK_ADDR_CTRL_ALLOW_MIGR BIT(3)
#define A5PSW_LK_ADDR_CTRL_CLEAR_TABLE BIT(6)
#define A5PSW_LK_ADDR_CTRL 0x408
#define A5PSW_LK_ADDR_CTRL_BUSY BIT(31)
#define A5PSW_LK_ADDR_CTRL_DELETE_PORT BIT(30)
#define A5PSW_LK_ADDR_CTRL_CLEAR BIT(29)
#define A5PSW_LK_ADDR_CTRL_LOOKUP BIT(28)
#define A5PSW_LK_ADDR_CTRL_WAIT BIT(27)
#define A5PSW_LK_ADDR_CTRL_READ BIT(26)
#define A5PSW_LK_ADDR_CTRL_WRITE BIT(25)
#define A5PSW_LK_ADDR_CTRL_ADDRESS GENMASK(12, 0)
#define A5PSW_LK_DATA_LO 0x40C
#define A5PSW_LK_DATA_HI 0x410
#define A5PSW_LK_DATA_HI_VALID BIT(16)
#define A5PSW_LK_DATA_HI_PORT BIT(16)
#define A5PSW_LK_LEARNCOUNT 0x418
#define A5PSW_LK_LEARNCOUNT_COUNT GENMASK(13, 0)
#define A5PSW_LK_LEARNCOUNT_MODE GENMASK(31, 30)
#define A5PSW_LK_LEARNCOUNT_MODE_SET 0x0
#define A5PSW_LK_LEARNCOUNT_MODE_INC 0x1
#define A5PSW_LK_LEARNCOUNT_MODE_DEC 0x2
#define A5PSW_MGMT_TAG_CFG 0x480
#define A5PSW_MGMT_TAG_CFG_TAGFIELD GENMASK(31, 16)
#define A5PSW_MGMT_TAG_CFG_ALL_FRAMES BIT(1)
#define A5PSW_MGMT_TAG_CFG_ENABLE BIT(0)
#define A5PSW_LK_AGETIME 0x41C
#define A5PSW_LK_AGETIME_MASK GENMASK(23, 0)
#define A5PSW_MDIO_CFG_STATUS 0x700
#define A5PSW_MDIO_CFG_STATUS_CLKDIV GENMASK(15, 7)
#define A5PSW_MDIO_CFG_STATUS_READERR BIT(1)
#define A5PSW_MDIO_CFG_STATUS_BUSY BIT(0)
#define A5PSW_MDIO_COMMAND 0x704
/* Register is named TRAININIT in datasheet and should be set when reading */
#define A5PSW_MDIO_COMMAND_READ BIT(15)
#define A5PSW_MDIO_COMMAND_PHY_ADDR GENMASK(9, 5)
#define A5PSW_MDIO_COMMAND_REG_ADDR GENMASK(4, 0)
#define A5PSW_MDIO_DATA 0x708
#define A5PSW_MDIO_DATA_MASK GENMASK(15, 0)
#define A5PSW_CMD_CFG(port) (0x808 + A5PSW_PORT_OFFSET(port))
#define A5PSW_CMD_CFG_CNTL_FRM_ENA BIT(23)
#define A5PSW_CMD_CFG_SW_RESET BIT(13)
#define A5PSW_CMD_CFG_TX_CRC_APPEND BIT(11)
#define A5PSW_CMD_CFG_HD_ENA BIT(10)
#define A5PSW_CMD_CFG_PAUSE_IGNORE BIT(8)
#define A5PSW_CMD_CFG_CRC_FWD BIT(6)
#define A5PSW_CMD_CFG_ETH_SPEED BIT(3)
#define A5PSW_CMD_CFG_RX_ENA BIT(1)
#define A5PSW_CMD_CFG_TX_ENA BIT(0)
#define A5PSW_FRM_LENGTH(port) (0x814 + A5PSW_PORT_OFFSET(port))
#define A5PSW_FRM_LENGTH_MASK GENMASK(13, 0)
#define A5PSW_STATUS(port) (0x840 + A5PSW_PORT_OFFSET(port))
#define A5PSW_STATS_HIWORD 0x900
/* Stats */
#define A5PSW_aFramesTransmittedOK 0x868
#define A5PSW_aFramesReceivedOK 0x86C
#define A5PSW_aFrameCheckSequenceErrors 0x870
#define A5PSW_aAlignmentErrors 0x874
#define A5PSW_aOctetsTransmittedOK 0x878
#define A5PSW_aOctetsReceivedOK 0x87C
#define A5PSW_aTxPAUSEMACCtrlFrames 0x880
#define A5PSW_aRxPAUSEMACCtrlFrames 0x884
/* If */
#define A5PSW_ifInErrors 0x888
#define A5PSW_ifOutErrors 0x88C
#define A5PSW_ifInUcastPkts 0x890
#define A5PSW_ifInMulticastPkts 0x894
#define A5PSW_ifInBroadcastPkts 0x898
#define A5PSW_ifOutDiscards 0x89C
#define A5PSW_ifOutUcastPkts 0x8A0
#define A5PSW_ifOutMulticastPkts 0x8A4
#define A5PSW_ifOutBroadcastPkts 0x8A8
/* Ether */
#define A5PSW_etherStatsDropEvents 0x8AC
#define A5PSW_etherStatsOctets 0x8B0
#define A5PSW_etherStatsPkts 0x8B4
#define A5PSW_etherStatsUndersizePkts 0x8B8
#define A5PSW_etherStatsOversizePkts 0x8BC
#define A5PSW_etherStatsPkts64Octets 0x8C0
#define A5PSW_etherStatsPkts65to127Octets 0x8C4
#define A5PSW_etherStatsPkts128to255Octets 0x8C8
#define A5PSW_etherStatsPkts256to511Octets 0x8CC
#define A5PSW_etherStatsPkts512to1023Octets 0x8D0
#define A5PSW_etherStatsPkts1024to1518Octets 0x8D4
#define A5PSW_etherStatsPkts1519toXOctets 0x8D8
#define A5PSW_etherStatsJabbers 0x8DC
#define A5PSW_etherStatsFragments 0x8E0
#define A5PSW_VLANReceived 0x8E8
#define A5PSW_VLANTransmitted 0x8EC
#define A5PSW_aDeferred 0x910
#define A5PSW_aMultipleCollisions 0x914
#define A5PSW_aSingleCollisions 0x918
#define A5PSW_aLateCollisions 0x91C
#define A5PSW_aExcessiveCollisions 0x920
#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_MDIO_DEF_FREQ 2500000
#define A5PSW_MDIO_TIMEOUT 100
#define A5PSW_JUMBO_LEN (10 * SZ_1K)
#define A5PSW_MDIO_CLK_DIV_MIN 5
#define A5PSW_TAG_LEN 8
#define A5PSW_VLAN_COUNT 32
/* Ensure enough space for 2 VLAN tags */
#define A5PSW_EXTRA_MTU_LEN (A5PSW_TAG_LEN + 8)
#define A5PSW_MAX_MTU (A5PSW_JUMBO_LEN - A5PSW_EXTRA_MTU_LEN)
#define A5PSW_PATTERN_MGMTFWD 0
#define A5PSW_LK_BUSY_USEC_POLL 10
#define A5PSW_CTRL_TIMEOUT 1000
#define A5PSW_TABLE_ENTRIES 8192
struct fdb_entry {
u8 mac[ETH_ALEN];
u16 valid:1;
u16 is_static:1;
u16 prio:3;
u16 port_mask:5;
u16 reserved:6;
} __packed;
union lk_data {
struct {
u32 lo;
u32 hi;
};
struct fdb_entry entry;
};
/**
* struct a5psw - switch struct
* @base: Base address of the switch
* @hclk: hclk_switch clock
* @clk: clk_switch clock
* @dev: Device associated to the switch
* @mii_bus: MDIO bus struct
* @mdio_freq: MDIO bus frequency requested
* @pcs: Array of PCS connected to the switch ports (not for the CPU)
* @ds: DSA switch struct
* @stats_lock: lock to access statistics (shared HI counter)
* @lk_lock: Lock for the lookup table
* @reg_lock: Lock for register read-modify-write operation
* @bridged_ports: Mask of ports that are bridged and should be flooded
* @br_dev: Bridge net device
*/
struct a5psw {
void __iomem *base;
struct clk *hclk;
struct clk *clk;
struct device *dev;
struct mii_bus *mii_bus;
struct phylink_pcs *pcs[A5PSW_PORTS_NUM - 1];
struct dsa_switch ds;
struct mutex lk_lock;
spinlock_t reg_lock;
u32 bridged_ports;
struct net_device *br_dev;
};
......@@ -18,4 +18,12 @@ config PCS_LYNX
This module provides helpers to phylink for managing the Lynx PCS
which is part of the Layerscape and QorIQ Ethernet SERDES.
config PCS_RZN1_MIIC
tristate "Renesas RZ/N1 MII converter"
depends on OF && (ARCH_RZN1 || COMPILE_TEST)
help
This module provides a driver for the MII converter that is available
on RZ/N1 SoCs. This PCS converts MII to RMII/RGMII or can be set in
pass-through mode for MII.
endmenu
......@@ -5,3 +5,4 @@ pcs_xpcs-$(CONFIG_PCS_XPCS) := pcs-xpcs.o pcs-xpcs-nxp.o
obj-$(CONFIG_PCS_XPCS) += pcs_xpcs.o
obj-$(CONFIG_PCS_LYNX) += pcs-lynx.o
obj-$(CONFIG_PCS_RZN1_MIIC) += pcs-rzn1-miic.o
This diff is collapsed.
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
/*
* Copyright (C) 2022 Schneider-Electric
*
* Clément Léger <clement.leger@bootlin.com>
*/
#ifndef _DT_BINDINGS_PCS_RZN1_MIIC
#define _DT_BINDINGS_PCS_RZN1_MIIC
/*
* Reefer to the datasheet [1] section 8.2.1, Internal Connection of Ethernet
* Ports to check the available combination
*
* [1] REN_r01uh0750ej0140-rzn1-introduction_MAT_20210228.pdf
*/
#define MIIC_GMAC1_PORT 0
#define MIIC_GMAC2_PORT 1
#define MIIC_RTOS_PORT 2
#define MIIC_SERCOS_PORTA 3
#define MIIC_SERCOS_PORTB 4
#define MIIC_ETHERCAT_PORTA 5
#define MIIC_ETHERCAT_PORTB 6
#define MIIC_ETHERCAT_PORTC 7
#define MIIC_SWITCH_PORTA 8
#define MIIC_SWITCH_PORTB 9
#define MIIC_SWITCH_PORTC 10
#define MIIC_SWITCH_PORTD 11
#define MIIC_HSR_PORTA 12
#define MIIC_HSR_PORTB 13
#endif
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2022 Schneider Electric
*
* Clément Léger <clement.leger@bootlin.com>
*/
#ifndef __LINUX_PCS_MIIC_H
#define __LINUX_PCS_MIIC_H
struct phylink;
struct device_node;
struct phylink_pcs *miic_create(struct device *dev, struct device_node *np);
void miic_destroy(struct phylink_pcs *pcs);
#endif /* __LINUX_PCS_MIIC_H */
......@@ -53,6 +53,7 @@ struct phylink_link_state;
#define DSA_TAG_PROTO_SJA1110_VALUE 23
#define DSA_TAG_PROTO_RTL8_4_VALUE 24
#define DSA_TAG_PROTO_RTL8_4T_VALUE 25
#define DSA_TAG_PROTO_RZN1_A5PSW_VALUE 26
enum dsa_tag_protocol {
DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE,
......@@ -81,6 +82,7 @@ enum dsa_tag_protocol {
DSA_TAG_PROTO_SJA1110 = DSA_TAG_PROTO_SJA1110_VALUE,
DSA_TAG_PROTO_RTL8_4 = DSA_TAG_PROTO_RTL8_4_VALUE,
DSA_TAG_PROTO_RTL8_4T = DSA_TAG_PROTO_RTL8_4T_VALUE,
DSA_TAG_PROTO_RZN1_A5PSW = DSA_TAG_PROTO_RZN1_A5PSW_VALUE,
};
struct dsa_switch;
......@@ -888,6 +890,9 @@ struct dsa_switch_ops {
struct ethtool_eth_mac_stats *mac_stats);
void (*get_eth_ctrl_stats)(struct dsa_switch *ds, int port,
struct ethtool_eth_ctrl_stats *ctrl_stats);
void (*get_rmon_stats)(struct dsa_switch *ds, int port,
struct ethtool_rmon_stats *rmon_stats,
const struct ethtool_rmon_hist_range **ranges);
void (*get_stats64)(struct dsa_switch *ds, int port,
struct rtnl_link_stats64 *s);
void (*self_test)(struct dsa_switch *ds, int port,
......
......@@ -116,6 +116,7 @@
#define ETH_P_QINQ3 0x9300 /* deprecated QinQ VLAN [ 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_IFE 0xED3E /* ForCES inter-FE LFB type */
#define ETH_P_AF_IUCV 0xFBFB /* IBM af_iucv [ NOT AN OFFICIALLY REGISTERED ID ] */
......
......@@ -132,6 +132,13 @@ config NET_DSA_TAG_RTL8_4
Say Y or M if you want to enable support for tagging frames for Realtek
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"
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.
config NET_DSA_TAG_LAN9303
tristate "Tag driver for SMSC/Microchip LAN9303 family of switches"
help
......
......@@ -17,6 +17,7 @@ obj-$(CONFIG_NET_DSA_TAG_OCELOT_8021Q) += tag_ocelot_8021q.o
obj-$(CONFIG_NET_DSA_TAG_QCA) += tag_qca.o
obj-$(CONFIG_NET_DSA_TAG_RTL4_A) += tag_rtl4_a.o
obj-$(CONFIG_NET_DSA_TAG_RTL8_4) += tag_rtl8_4.o
obj-$(CONFIG_NET_DSA_TAG_RZN1_A5PSW) += tag_rzn1_a5psw.o
obj-$(CONFIG_NET_DSA_TAG_SJA1105) += tag_sja1105.o
obj-$(CONFIG_NET_DSA_TAG_TRAILER) += tag_trailer.o
obj-$(CONFIG_NET_DSA_TAG_XRS700X) += tag_xrs700x.o
......@@ -1002,6 +1002,18 @@ dsa_slave_get_eth_ctrl_stats(struct net_device *dev,
ds->ops->get_eth_ctrl_stats(ds, dp->index, ctrl_stats);
}
static void
dsa_slave_get_rmon_stats(struct net_device *dev,
struct ethtool_rmon_stats *rmon_stats,
const struct ethtool_rmon_hist_range **ranges)
{
struct dsa_port *dp = dsa_slave_to_port(dev);
struct dsa_switch *ds = dp->ds;
if (ds->ops->get_rmon_stats)
ds->ops->get_rmon_stats(ds, dp->index, rmon_stats, ranges);
}
static void dsa_slave_net_selftest(struct net_device *ndev,
struct ethtool_test *etest, u64 *buf)
{
......@@ -2081,6 +2093,7 @@ static const struct ethtool_ops dsa_slave_ethtool_ops = {
.get_eth_phy_stats = dsa_slave_get_eth_phy_stats,
.get_eth_mac_stats = dsa_slave_get_eth_mac_stats,
.get_eth_ctrl_stats = dsa_slave_get_eth_ctrl_stats,
.get_rmon_stats = dsa_slave_get_rmon_stats,
.set_wol = dsa_slave_set_wol,
.get_wol = dsa_slave_get_wol,
.set_eee = dsa_slave_set_eee,
......@@ -2460,8 +2473,9 @@ static int dsa_slave_changeupper(struct net_device *dev,
if (!err)
dsa_bridge_mtu_normalization(dp);
if (err == -EOPNOTSUPP) {
NL_SET_ERR_MSG_MOD(extack,
"Offloading not supported");
if (!extack->_msg)
NL_SET_ERR_MSG_MOD(extack,
"Offloading not supported");
err = 0;
}
err = notifier_from_errno(err);
......
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2022 Schneider Electric
*
* Clément Léger <clement.leger@bootlin.com>
*/
#include <linux/bitfield.h>
#include <linux/etherdevice.h>
#include <linux/if_ether.h>
#include <net/dsa.h>
#include "dsa_priv.h"
/* To define the outgoing port and to discover the incoming port a TAG is
* inserted after Src MAC :
*
* Dest MAC Src MAC TAG Type
* ...| 1 2 3 4 5 6 | 1 2 3 4 5 6 | 1 2 3 4 5 6 7 8 | 1 2 |...
* |<--------------->|
*
* See struct a5psw_tag for layout
*/
#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 */
#define A5PSW_CTRL_DATA_PORT GENMASK(3, 0)
struct a5psw_tag {
__be16 ctrl_tag;
__be16 ctrl_data;
__be16 ctrl_data2_hi;
__be16 ctrl_data2_lo;
};
static struct sk_buff *a5psw_tag_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct dsa_port *dp = dsa_slave_to_port(dev);
struct a5psw_tag *ptag;
u32 data2_val;
BUILD_BUG_ON(sizeof(*ptag) != A5PSW_TAG_LEN);
/* The Ethernet switch we are interfaced with needs packets to be at
* least 60 bytes otherwise they will be discarded when they enter the
* switch port logic.
*/
if (__skb_put_padto(skb, ETH_ZLEN, false))
return NULL;
/* provide 'A5PSW_TAG_LEN' bytes additional space */
skb_push(skb, A5PSW_TAG_LEN);
/* make room between MACs and Ether-Type to insert tag */
dsa_alloc_etype_header(skb, A5PSW_TAG_LEN);
ptag = dsa_etype_header_pos_tx(skb);
data2_val = FIELD_PREP(A5PSW_CTRL_DATA_PORT, BIT(dp->index));
ptag->ctrl_tag = htons(ETH_P_DSA_A5PSW);
ptag->ctrl_data = htons(A5PSW_CTRL_DATA_FORCE_FORWARD);
ptag->ctrl_data2_lo = htons(data2_val);
ptag->ctrl_data2_hi = 0;
return skb;
}
static struct sk_buff *a5psw_tag_rcv(struct sk_buff *skb,
struct net_device *dev)
{
struct a5psw_tag *tag;
int port;
if (unlikely(!pskb_may_pull(skb, A5PSW_TAG_LEN))) {
dev_warn_ratelimited(&dev->dev,
"Dropping packet, cannot pull\n");
return NULL;
}
tag = dsa_etype_header_pos_rx(skb);
if (tag->ctrl_tag != htons(ETH_P_DSA_A5PSW)) {
dev_warn_ratelimited(&dev->dev, "Dropping packet due to invalid TAG marker\n");
return NULL;
}
port = FIELD_GET(A5PSW_CTRL_DATA_PORT, ntohs(tag->ctrl_data));
skb->dev = dsa_master_find_slave(dev, 0, port);
if (!skb->dev)
return NULL;
skb_pull_rcsum(skb, A5PSW_TAG_LEN);
dsa_strip_etype_header(skb, A5PSW_TAG_LEN);
dsa_default_offload_fwd_mark(skb);
return skb;
}
static const struct dsa_device_ops a5psw_netdev_ops = {
.name = "a5psw",
.proto = DSA_TAG_PROTO_RZN1_A5PSW,
.xmit = a5psw_tag_xmit,
.rcv = a5psw_tag_rcv,
.needed_headroom = A5PSW_TAG_LEN,
};
MODULE_LICENSE("GPL v2");
MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_A5PSW);
module_dsa_tag_driver(a5psw_netdev_ops);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment