This is a forward port / upstream refactor of code delivered
downstream by Qualcomm over at [0] to enable the DWMAC5 based
implementation called EMAC3 on the sa8540p-ride dev board.
From what I can tell with the board schematic in hand,
as well as the code delivered, the main changes needed are:
1. A new address space layout for /dwmac5/EMAC3 MTL/DMA regs
2. A new programming sequence required for the EMAC3 base platforms
This series makes those adaptations as well as other housekeeping items
such as converting dt-bindings to yaml, adding clock descriptions, etc.
[0] https://git.codelinaro.org/clo/la/kernel/ark-5.14/-/commit/510235ad02d7f0df478146fb00d7a4ba74821b17
Thanks,
Andrew
Bhupesh Sharma (3):
dt-bindings: net: snps,dwmac: Update interrupt-names
dt-bindings: net: snps,dwmac: Add Qualcomm Ethernet ETHQOS compatibles
dt-bindings: net: qcom,ethqos: Convert bindings to yaml
Brian Masney (1):
net: stmmac: Add EMAC3 variant of dwmac4
.../devicetree/bindings/net/qcom,ethqos.txt | 66 ----
.../devicetree/bindings/net/qcom,ethqos.yaml | 113 ++++++
.../devicetree/bindings/net/snps,dwmac.yaml | 11 +-
MAINTAINERS | 2 +-
arch/arm64/boot/dts/qcom/sa8540p-ride.dts | 181 ++++++++++
arch/arm64/boot/dts/qcom/sc8280xp.dtsi | 53 +++
drivers/clk/qcom/gcc-sc8280xp.c | 18 +
.../stmicro/stmmac/dwmac-qcom-ethqos.c | 161 ++++++---
drivers/net/ethernet/stmicro/stmmac/dwmac4.h | 32 +-
.../net/ethernet/stmicro/stmmac/dwmac4_core.c | 190 ++++++++--
.../net/ethernet/stmicro/stmmac/dwmac4_dma.c | 336 ++++++++++++++----
.../net/ethernet/stmicro/stmmac/dwmac4_dma.h | 38 ++
.../net/ethernet/stmicro/stmmac/dwmac4_lib.c | 144 ++++++--
drivers/net/ethernet/stmicro/stmmac/hwif.c | 29 +-
drivers/net/ethernet/stmicro/stmmac/hwif.h | 2 +
.../ethernet/stmicro/stmmac/stmmac_ethtool.c | 6 +-
.../net/ethernet/stmicro/stmmac/stmmac_main.c | 17 +-
.../net/ethernet/stmicro/stmmac/stmmac_mdio.c | 9 +-
.../net/ethernet/stmicro/stmmac/stmmac_ptp.c | 4 +-
include/dt-bindings/clock/qcom,gcc-sc8280xp.h | 2 +
include/linux/stmmac.h | 1 +
21 files changed, 1164 insertions(+), 251 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/net/qcom,ethqos.txt
create mode 100644 Documentation/devicetree/bindings/net/qcom,ethqos.yaml
--
2.39.2
From: Bhupesh Sharma <[email protected]>
Add Qualcomm Ethernet ETHQOS compatible checks
in snps,dwmac YAML binding document.
Reviewed-by: Krzysztof Kozlowski <[email protected]>
Signed-off-by: Bhupesh Sharma <[email protected]>
Signed-off-by: Andrew Halaney <[email protected]>
---
I picked this up from:
https://lore.kernel.org/netdev/[email protected]/
No changes except the Reviewed-by collection.
Documentation/devicetree/bindings/net/snps,dwmac.yaml | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
index 52ce14a4bea7..3ca1239da448 100644
--- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml
+++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
@@ -65,6 +65,8 @@ properties:
- ingenic,x2000-mac
- loongson,ls2k-dwmac
- loongson,ls7a-dwmac
+ - qcom,qcs404-ethqos
+ - qcom,sm8150-ethqos
- renesas,r9a06g032-gmac
- renesas,rzn1-gmac
- rockchip,px30-gmac
@@ -625,6 +627,8 @@ allOf:
- ingenic,x1600-mac
- ingenic,x1830-mac
- ingenic,x2000-mac
+ - qcom,qcs404-ethqos
+ - qcom,sm8150-ethqos
- snps,dwmac-4.00
- snps,dwmac-4.10a
- snps,dwmac-4.20a
--
2.39.2
Add the EMAC GDSCs to allow the EMAC hardware to be enabled.
Signed-off-by: Andrew Halaney <[email protected]>
---
drivers/clk/qcom/gcc-sc8280xp.c | 18 ++++++++++++++++++
include/dt-bindings/clock/qcom,gcc-sc8280xp.h | 2 ++
2 files changed, 20 insertions(+)
diff --git a/drivers/clk/qcom/gcc-sc8280xp.c b/drivers/clk/qcom/gcc-sc8280xp.c
index b3198784e1c3..04a99dbaa57e 100644
--- a/drivers/clk/qcom/gcc-sc8280xp.c
+++ b/drivers/clk/qcom/gcc-sc8280xp.c
@@ -6873,6 +6873,22 @@ static struct gdsc usb30_sec_gdsc = {
.pwrsts = PWRSTS_RET_ON,
};
+static struct gdsc emac_0_gdsc = {
+ .gdscr = 0xaa004,
+ .pd = {
+ .name = "emac_0_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
+static struct gdsc emac_1_gdsc = {
+ .gdscr = 0xba004,
+ .pd = {
+ .name = "emac_1_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+};
+
static struct clk_regmap *gcc_sc8280xp_clocks[] = {
[GCC_AGGRE_NOC_PCIE0_TUNNEL_AXI_CLK] = &gcc_aggre_noc_pcie0_tunnel_axi_clk.clkr,
[GCC_AGGRE_NOC_PCIE1_TUNNEL_AXI_CLK] = &gcc_aggre_noc_pcie1_tunnel_axi_clk.clkr,
@@ -7351,6 +7367,8 @@ static struct gdsc *gcc_sc8280xp_gdscs[] = {
[USB30_MP_GDSC] = &usb30_mp_gdsc,
[USB30_PRIM_GDSC] = &usb30_prim_gdsc,
[USB30_SEC_GDSC] = &usb30_sec_gdsc,
+ [EMAC_0_GDSC] = &emac_0_gdsc,
+ [EMAC_1_GDSC] = &emac_1_gdsc,
};
static const struct clk_rcg_dfs_data gcc_dfs_clocks[] = {
diff --git a/include/dt-bindings/clock/qcom,gcc-sc8280xp.h b/include/dt-bindings/clock/qcom,gcc-sc8280xp.h
index cb2fb638825c..721105ea4fad 100644
--- a/include/dt-bindings/clock/qcom,gcc-sc8280xp.h
+++ b/include/dt-bindings/clock/qcom,gcc-sc8280xp.h
@@ -492,5 +492,7 @@
#define USB30_MP_GDSC 9
#define USB30_PRIM_GDSC 10
#define USB30_SEC_GDSC 11
+#define EMAC_0_GDSC 12
+#define EMAC_1_GDSC 13
#endif
--
2.39.2
From: Bhupesh Sharma <[email protected]>
Convert Qualcomm ETHQOS Ethernet devicetree binding to YAML.
While at it, also update the MAINTAINERS file to point to the yaml
version of the bindings.
Signed-off-by: Bhupesh Sharma <[email protected]>
[halaney: Remove duplicated snps,dwmac.yaml properties, add MAINTAINERS]
Signed-off-by: Andrew Halaney <[email protected]>
---
I picked this up from:
https://lore.kernel.org/netdev/[email protected]/
Changes since then include:
* Change MAINTAINERS atomically with the filename change
* Remove duplicated snps,dwmac.yaml properties
As listed on that thread, the issues Bhupesh saw were due to a bug in
dtschema that has since been fixed.
.../devicetree/bindings/net/qcom,ethqos.txt | 66 -----------
.../devicetree/bindings/net/qcom,ethqos.yaml | 112 ++++++++++++++++++
MAINTAINERS | 2 +-
3 files changed, 113 insertions(+), 67 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/net/qcom,ethqos.txt
create mode 100644 Documentation/devicetree/bindings/net/qcom,ethqos.yaml
diff --git a/Documentation/devicetree/bindings/net/qcom,ethqos.txt b/Documentation/devicetree/bindings/net/qcom,ethqos.txt
deleted file mode 100644
index 1f5746849a71..000000000000
--- a/Documentation/devicetree/bindings/net/qcom,ethqos.txt
+++ /dev/null
@@ -1,66 +0,0 @@
-Qualcomm Ethernet ETHQOS device
-
-This documents dwmmac based ethernet device which supports Gigabit
-ethernet for version v2.3.0 onwards.
-
-This device has following properties:
-
-Required properties:
-
-- compatible: Should be one of:
- "qcom,qcs404-ethqos"
- "qcom,sm8150-ethqos"
-
-- reg: Address and length of the register set for the device
-
-- reg-names: Should contain register names "stmmaceth", "rgmii"
-
-- clocks: Should contain phandle to clocks
-
-- clock-names: Should contain clock names "stmmaceth", "pclk",
- "ptp_ref", "rgmii"
-
-- interrupts: Should contain phandle to interrupts
-
-- interrupt-names: Should contain interrupt names "macirq", "eth_lpi"
-
-Rest of the properties are defined in stmmac.txt file in same directory
-
-
-Example:
-
-ethernet: ethernet@7a80000 {
- compatible = "qcom,qcs404-ethqos";
- reg = <0x07a80000 0x10000>,
- <0x07a96000 0x100>;
- reg-names = "stmmaceth", "rgmii";
- clock-names = "stmmaceth", "pclk", "ptp_ref", "rgmii";
- clocks = <&gcc GCC_ETH_AXI_CLK>,
- <&gcc GCC_ETH_SLAVE_AHB_CLK>,
- <&gcc GCC_ETH_PTP_CLK>,
- <&gcc GCC_ETH_RGMII_CLK>;
- interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "macirq", "eth_lpi";
- snps,reset-gpio = <&tlmm 60 GPIO_ACTIVE_LOW>;
- snps,reset-active-low;
-
- snps,txpbl = <8>;
- snps,rxpbl = <2>;
- snps,aal;
- snps,tso;
-
- phy-handle = <&phy1>;
- phy-mode = "rgmii";
-
- mdio {
- #address-cells = <0x1>;
- #size-cells = <0x0>;
- compatible = "snps,dwmac-mdio";
- phy1: phy@4 {
- device_type = "ethernet-phy";
- reg = <0x4>;
- };
- };
-
-};
diff --git a/Documentation/devicetree/bindings/net/qcom,ethqos.yaml b/Documentation/devicetree/bindings/net/qcom,ethqos.yaml
new file mode 100644
index 000000000000..68ef43fb283d
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/qcom,ethqos.yaml
@@ -0,0 +1,112 @@
+# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/qcom,ethqos.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Ethernet ETHQOS device
+
+maintainers:
+ - Bhupesh Sharma <[email protected]>
+
+description:
+ This binding describes the dwmmac based Qualcomm ethernet devices which
+ support Gigabit ethernet (version v2.3.0 onwards).
+
+ So, this file documents platform glue layer for dwmmac stmmac based Qualcomm
+ ethernet devices.
+
+allOf:
+ - $ref: snps,dwmac.yaml#
+
+properties:
+ compatible:
+ enum:
+ - qcom,qcs404-ethqos
+ - qcom,sm8150-ethqos
+
+ reg:
+ maxItems: 2
+
+ reg-names:
+ items:
+ - const: stmmaceth
+ - const: rgmii
+
+ interrupts:
+ items:
+ - description: Combined signal for various interrupt events
+ - description: The interrupt that occurs when Rx exits the LPI state
+
+ interrupt-names:
+ items:
+ - const: macirq
+ - const: eth_lpi
+
+ clocks:
+ maxItems: 4
+
+ clock-names:
+ items:
+ - const: stmmaceth
+ - const: pclk
+ - const: ptp_ref
+ - const: rgmii
+
+ iommus:
+ maxItems: 1
+
+required:
+ - compatible
+ - clocks
+ - clock-names
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/clock/qcom,gcc-qcs404.h>
+ #include <dt-bindings/gpio/gpio.h>
+
+ ethernet: ethernet@7a80000 {
+ compatible = "qcom,qcs404-ethqos";
+ reg = <0x07a80000 0x10000>,
+ <0x07a96000 0x100>;
+ reg-names = "stmmaceth", "rgmii";
+ clock-names = "stmmaceth", "pclk", "ptp_ref", "rgmii";
+ clocks = <&gcc GCC_ETH_AXI_CLK>,
+ <&gcc GCC_ETH_SLAVE_AHB_CLK>,
+ <&gcc GCC_ETH_PTP_CLK>,
+ <&gcc GCC_ETH_RGMII_CLK>;
+ interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq", "eth_lpi";
+
+ rx-fifo-depth = <4096>;
+ tx-fifo-depth = <4096>;
+
+ snps,tso;
+ snps,reset-gpio = <&tlmm 60 GPIO_ACTIVE_LOW>;
+ snps,reset-active-low;
+ snps,reset-delays-us = <0 10000 10000>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <ðernet_defaults>;
+
+ phy-handle = <&phy1>;
+ phy-mode = "rgmii";
+ mdio {
+ #address-cells = <0x1>;
+ #size-cells = <0x0>;
+
+ compatible = "snps,dwmac-mdio";
+ phy1: phy@4 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ device_type = "ethernet-phy";
+ reg = <0x4>;
+
+ #phy-cells = <0>;
+ };
+ };
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index 8d5bc223f305..720ae2f1bf95 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17282,7 +17282,7 @@ M: Vinod Koul <[email protected]>
R: Bhupesh Sharma <[email protected]>
L: [email protected]
S: Maintained
-F: Documentation/devicetree/bindings/net/qcom,ethqos.txt
+F: Documentation/devicetree/bindings/net/qcom,ethqos.yaml
F: drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
QUALCOMM FASTRPC DRIVER
--
2.39.2
This platform has 2 MACs integrated in it, go ahead and describe them.
Signed-off-by: Andrew Halaney <[email protected]>
---
arch/arm64/boot/dts/qcom/sc8280xp.dtsi | 53 ++++++++++++++++++++++++++
1 file changed, 53 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/sc8280xp.dtsi b/arch/arm64/boot/dts/qcom/sc8280xp.dtsi
index 0d02599d8867..a63e8e81a8c4 100644
--- a/arch/arm64/boot/dts/qcom/sc8280xp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc8280xp.dtsi
@@ -761,6 +761,59 @@ soc: soc@0 {
ranges = <0 0 0 0 0x10 0>;
dma-ranges = <0 0 0 0 0x10 0>;
+ ethernet0: ethernet@20000 {
+ compatible = "qcom,sc8280xp-ethqos";
+ reg = <0x0 0x00020000 0x0 0x10000>,
+ <0x0 0x00036000 0x0 0x100>;
+ reg-names = "stmmaceth", "rgmii";
+
+ clocks = <&gcc GCC_EMAC0_AXI_CLK>,
+ <&gcc GCC_EMAC0_SLV_AHB_CLK>,
+ <&gcc GCC_EMAC0_PTP_CLK>,
+ <&gcc GCC_EMAC0_RGMII_CLK>;
+ clock-names = "stmmaceth", "pclk", "ptp_ref", "rgmii";
+
+ interrupts = <GIC_SPI 946 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 936 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq", "eth_lpi";
+ iommus = <&apps_smmu 0x4c0 0xf>;
+ power-domains = <&gcc EMAC_0_GDSC>;
+
+ snps,tso;
+ snps,pbl = <32>;
+ rx-fifo-depth = <4096>;
+ tx-fifo-depth = <4096>;
+
+ status = "disabled";
+ };
+
+ ethernet1: ethernet@23000000 {
+ compatible = "qcom,sc8280xp-ethqos";
+ reg = <0x0 0x23000000 0x0 0x10000>,
+ <0x0 0x23016000 0x0 0x100>;
+ reg-names = "stmmaceth", "rgmii";
+
+ clocks = <&gcc GCC_EMAC1_AXI_CLK>,
+ <&gcc GCC_EMAC1_SLV_AHB_CLK>,
+ <&gcc GCC_EMAC1_PTP_CLK>,
+ <&gcc GCC_EMAC1_RGMII_CLK>;
+ clock-names = "stmmaceth", "pclk", "ptp_ref", "rgmii";
+
+ interrupts = <GIC_SPI 929 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 919 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq", "eth_lpi";
+
+ iommus = <&apps_smmu 0x40 0xf>;
+ power-domains = <&gcc EMAC_1_GDSC>;
+
+ snps,tso;
+ snps,pbl = <32>;
+ rx-fifo-depth = <4096>;
+ tx-fifo-depth = <4096>;
+
+ status = "disabled";
+ };
+
gcc: clock-controller@100000 {
compatible = "qcom,gcc-sc8280xp";
reg = <0x0 0x00100000 0x0 0x1f0000>;
--
2.39.2
The sc8280xp has a new version of the ETHQOS hardware in it, EMAC v3.
Add a compatible for this.
Signed-off-by: Andrew Halaney <[email protected]>
---
Documentation/devicetree/bindings/net/qcom,ethqos.yaml | 1 +
Documentation/devicetree/bindings/net/snps,dwmac.yaml | 3 +++
2 files changed, 4 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/qcom,ethqos.yaml b/Documentation/devicetree/bindings/net/qcom,ethqos.yaml
index 68ef43fb283d..89c17ed0442f 100644
--- a/Documentation/devicetree/bindings/net/qcom,ethqos.yaml
+++ b/Documentation/devicetree/bindings/net/qcom,ethqos.yaml
@@ -24,6 +24,7 @@ properties:
enum:
- qcom,qcs404-ethqos
- qcom,sm8150-ethqos
+ - qcom,sc8280xp-ethqos
reg:
maxItems: 2
diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
index 3ca1239da448..f981a89ab2a5 100644
--- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml
+++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
@@ -67,6 +67,7 @@ properties:
- loongson,ls7a-dwmac
- qcom,qcs404-ethqos
- qcom,sm8150-ethqos
+ - qcom,sc8280xp-ethqos
- renesas,r9a06g032-gmac
- renesas,rzn1-gmac
- rockchip,px30-gmac
@@ -574,6 +575,7 @@ allOf:
- ingenic,x1600-mac
- ingenic,x1830-mac
- ingenic,x2000-mac
+ - qcom,sc8280xp-ethqos
- snps,dwmac-3.50a
- snps,dwmac-4.10a
- snps,dwmac-4.20a
@@ -629,6 +631,7 @@ allOf:
- ingenic,x2000-mac
- qcom,qcs404-ethqos
- qcom,sm8150-ethqos
+ - qcom,sc8280xp-ethqos
- snps,dwmac-4.00
- snps,dwmac-4.10a
- snps,dwmac-4.20a
--
2.39.2
Enable both the MACs found on the board.
ethernet0 and ethernet1 both ultimately go to a series of on board
switches which aren't managed by this processor.
ethernet0 is connected to a Marvell 88EA1512 phy via RGMII. That goes to
the series of switches via SGMII on the "media" side of the phy.
RGMII_SGMII mode is enabled via devicetree register descriptions.
The switch on the "media" side has auto-negotiation disabled, so
configuration from userspace similar to:
ethtool -s eth0 autoneg off speed 1000 duplex full
is necessary to get traffic flowing on that interface.
ethernet1 is in a mac2mac/fixed-link configuration going to the same
series of switches directly via RGMII.
Signed-off-by: Andrew Halaney <[email protected]>
---
arch/arm64/boot/dts/qcom/sa8540p-ride.dts | 181 ++++++++++++++++++++++
1 file changed, 181 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/sa8540p-ride.dts b/arch/arm64/boot/dts/qcom/sa8540p-ride.dts
index 8b7555f22528..b874f3909382 100644
--- a/arch/arm64/boot/dts/qcom/sa8540p-ride.dts
+++ b/arch/arm64/boot/dts/qcom/sa8540p-ride.dts
@@ -28,6 +28,65 @@ aliases {
chosen {
stdout-path = "serial0:115200n8";
};
+
+ mtl_rx_setup: rx-queues-config {
+ snps,rx-queues-to-use = <1>;
+ snps,rx-sched-sp;
+
+ queue0 {
+ snps,dcb-algorithm;
+ snps,map-to-dma-channel = <0x0>;
+ snps,route-up;
+ snps,priority = <0x1>;
+ };
+
+ queue1 {
+ snps,dcb-algorithm;
+ snps,map-to-dma-channel = <0x1>;
+ snps,route-ptp;
+ };
+
+ queue2 {
+ snps,avb-algorithm;
+ snps,map-to-dma-channel = <0x2>;
+ snps,route-avcp;
+ };
+
+ queue3 {
+ snps,avb-algorithm;
+ snps,map-to-dma-channel = <0x3>;
+ snps,priority = <0xc>;
+ };
+ };
+
+ mtl_tx_setup: tx-queues-config {
+ snps,tx-queues-to-use = <1>;
+ snps,tx-sched-sp;
+
+ queue0 {
+ snps,dcb-algorithm;
+ };
+
+ queue1 {
+ snps,dcb-algorithm;
+ };
+
+ queue2 {
+ snps,avb-algorithm;
+ snps,send_slope = <0x1000>;
+ snps,idle_slope = <0x1000>;
+ snps,high_credit = <0x3e800>;
+ snps,low_credit = <0xffc18000>;
+ };
+
+ queue3 {
+ snps,avb-algorithm;
+ snps,send_slope = <0x1000>;
+ snps,idle_slope = <0x1000>;
+ snps,high_credit = <0x3e800>;
+ snps,low_credit = <0xffc18000>;
+ };
+ };
};
&apps_rsc {
@@ -151,6 +210,68 @@ vreg_l8g: ldo8 {
};
};
+ðernet0 {
+ snps,mtl-rx-config = <&mtl_rx_setup>;
+ snps,mtl-tx-config = <&mtl_tx_setup>;
+
+ max-speed = <1000>;
+ phy-handle = <&rgmii_phy>;
+ phy-mode = "rgmii-txid";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <ðernet0_default>;
+
+ status = "okay";
+
+ mdio {
+ #address-cells = <0x1>;
+ #size-cells = <0x0>;
+
+ compatible = "snps,dwmac-mdio";
+
+ /* Marvell 88EA1512 */
+ rgmii_phy: phy@8 {
+ reg = <0x8>;
+
+ interrupt-parent = <&tlmm>;
+ interrupts-extended = <&tlmm 127 IRQ_TYPE_EDGE_FALLING>;
+
+ reset-gpios = <&pmm8540c_gpios 1 GPIO_ACTIVE_LOW>;
+ reset-assert-us = <11000>;
+ reset-deassert-us = <70000>;
+
+ device_type = "ethernet-phy";
+
+ /* Set to RGMII_SGMII mode and soft reset. Turn off auto-negotiation
+ * from userspace to talk to the switch on the SGMII side of things
+ */
+ marvell,reg-init =
+ /* Set MODE[2:0] to RGMII_SGMII */
+ <0x12 0x14 0xfff8 0x4>,
+ /* Soft reset required after changing MODE[2:0] */
+ <0x12 0x14 0x7fff 0x8000>;
+ };
+ };
+};
+
+ðernet1 {
+ snps,mtl-rx-config = <&mtl_rx_setup>;
+ snps,mtl-tx-config = <&mtl_tx_setup>;
+
+ max-speed = <1000>;
+ phy-mode = "rgmii-txid";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <ðernet1_default>;
+
+ status = "okay";
+
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ };
+};
+
&i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0_default>;
@@ -316,6 +437,66 @@ &xo_board_clk {
/* PINCTRL */
&tlmm {
+ ethernet0_default: ethernet0-default-state {
+ mdc-pins {
+ pins = "gpio175";
+ function = "rgmii_0";
+ drive-strength = <16>;
+ bias-pull-up;
+ };
+
+ mdio-pins {
+ pins = "gpio176";
+ function = "rgmii_0";
+ drive-strength = <16>;
+ bias-pull-up;
+ };
+
+ rgmii-tx-pins {
+ pins = "gpio183", "gpio184", "gpio185", "gpio186", "gpio187", "gpio188";
+ function = "rgmii_0";
+ drive-strength = <16>;
+ bias-pull-up;
+ };
+
+ rgmii-rx-pins {
+ pins = "gpio177", "gpio178", "gpio179", "gpio180", "gpio181", "gpio182";
+ function = "rgmii_0";
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ ethernet1_default: ethernet1-default-state {
+ mdc-pins {
+ pins = "gpio97";
+ function = "rgmii_1";
+ drive-strength = <16>;
+ bias-pull-up;
+ };
+
+ mdio-pins {
+ pins = "gpio98";
+ function = "rgmii_1";
+ drive-strength = <16>;
+ bias-pull-up;
+ };
+
+ rgmii-tx-pins {
+ pins = "gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110";
+ function = "rgmii_1";
+ drive-strength = <16>;
+ bias-pull-up;
+ };
+
+ rgmii-rx-pins {
+ pins = "gpio99", "gpio100", "gpio101", "gpio102", "gpio103", "gpio104";
+ function = "rgmii_1";
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
i2c0_default: i2c0-default-state {
/* To USB7002T-I/KDXVA0 USB hub (SIP1 only) */
pins = "gpio135", "gpio136";
--
2.39.2
The driver currently sets a MAC TX delay of 2 ns no matter what the
phy-mode is. If the phy-mode indicates the phy is in charge of the
TX delay (rgmii-txid, rgmii-id), don't do it in the MAC.
Signed-off-by: Andrew Halaney <[email protected]>
---
.../stmicro/stmmac/dwmac-qcom-ethqos.c | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
index 732774645c1a..6f272cae330d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
@@ -279,6 +279,16 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos)
static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
{
+ int phy_mode;
+ int phase_shift;
+
+ /* Determine if the PHY adds a 2 ns TX delay or the MAC handles it */
+ phy_mode = device_get_phy_mode(ðqos->pdev->dev);
+ if (phy_mode == PHY_INTERFACE_MODE_RGMII_ID || phy_mode == PHY_INTERFACE_MODE_RGMII_TXID)
+ phase_shift = 0;
+ else
+ phase_shift = RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN;
+
/* Disable loopback mode */
rgmii_updatel(ethqos, RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN,
0, RGMII_IO_MACRO_CONFIG2);
@@ -300,9 +310,9 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
RGMII_CONFIG_PROG_SWAP, RGMII_IO_MACRO_CONFIG);
rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL,
0, RGMII_IO_MACRO_CONFIG2);
+
rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
- RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
- RGMII_IO_MACRO_CONFIG2);
+ phase_shift, RGMII_IO_MACRO_CONFIG2);
rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15,
0, RGMII_IO_MACRO_CONFIG2);
rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
@@ -336,8 +346,7 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL,
0, RGMII_IO_MACRO_CONFIG2);
rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
- RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
- RGMII_IO_MACRO_CONFIG2);
+ phase_shift, RGMII_IO_MACRO_CONFIG2);
rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_2,
BIT(6), RGMII_IO_MACRO_CONFIG);
rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15,
@@ -375,7 +384,7 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL,
0, RGMII_IO_MACRO_CONFIG2);
rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
- 0, RGMII_IO_MACRO_CONFIG2);
+ phase_shift, RGMII_IO_MACRO_CONFIG2);
rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_9,
BIT(12) | GENMASK(9, 8),
RGMII_IO_MACRO_CONFIG);
--
2.39.2
It seems that this variable should be used for all speeds, not just
1000/100.
While at it refactor it slightly to be more readable, including fixing
the typo in the variable name.
Signed-off-by: Andrew Halaney <[email protected]>
---
.../stmicro/stmmac/dwmac-qcom-ethqos.c | 36 +++++++++----------
1 file changed, 17 insertions(+), 19 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
index 6f272cae330d..778852934e36 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
@@ -78,7 +78,7 @@ struct ethqos_emac_por {
struct ethqos_emac_driver_data {
const struct ethqos_emac_por *por;
unsigned int num_por;
- bool rgmii_config_looback_en;
+ bool rgmii_config_loopback_en;
};
struct qcom_ethqos {
@@ -91,7 +91,7 @@ struct qcom_ethqos {
const struct ethqos_emac_por *por;
unsigned int num_por;
- bool rgmii_config_looback_en;
+ bool rgmii_config_loopback_en;
};
static int rgmii_readl(struct qcom_ethqos *ethqos, unsigned int offset)
@@ -183,7 +183,7 @@ static const struct ethqos_emac_por emac_v2_3_0_por[] = {
static const struct ethqos_emac_driver_data emac_v2_3_0_data = {
.por = emac_v2_3_0_por,
.num_por = ARRAY_SIZE(emac_v2_3_0_por),
- .rgmii_config_looback_en = true,
+ .rgmii_config_loopback_en = true,
};
static const struct ethqos_emac_por emac_v2_1_0_por[] = {
@@ -198,7 +198,7 @@ static const struct ethqos_emac_por emac_v2_1_0_por[] = {
static const struct ethqos_emac_driver_data emac_v2_1_0_data = {
.por = emac_v2_1_0_por,
.num_por = ARRAY_SIZE(emac_v2_1_0_por),
- .rgmii_config_looback_en = false,
+ .rgmii_config_loopback_en = false,
};
static int ethqos_dll_configure(struct qcom_ethqos *ethqos)
@@ -281,6 +281,7 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
{
int phy_mode;
int phase_shift;
+ int loopback;
/* Determine if the PHY adds a 2 ns TX delay or the MAC handles it */
phy_mode = device_get_phy_mode(ðqos->pdev->dev);
@@ -293,6 +294,12 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
rgmii_updatel(ethqos, RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN,
0, RGMII_IO_MACRO_CONFIG2);
+ /* Determine if this platform wants loopback enabled after programming */
+ if (ethqos->rgmii_config_loopback_en)
+ loopback = RGMII_CONFIG_LOOPBACK_EN;
+ else
+ loopback = 0;
+
/* Select RGMII, write 0 to interface select */
rgmii_updatel(ethqos, RGMII_CONFIG_INTF_SEL,
0, RGMII_IO_MACRO_CONFIG);
@@ -325,12 +332,8 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_DLY_EN,
SDCC_DDR_CONFIG_PRG_DLY_EN,
SDCC_HC_REG_DDR_CONFIG);
- if (ethqos->rgmii_config_looback_en)
- rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN,
- RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG);
- else
- rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN,
- 0, RGMII_IO_MACRO_CONFIG);
+ rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN,
+ loopback, RGMII_IO_MACRO_CONFIG);
break;
case SPEED_100:
@@ -362,13 +365,8 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN,
SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN,
SDCC_HC_REG_DDR_CONFIG);
- if (ethqos->rgmii_config_looback_en)
- rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN,
- RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG);
- else
- rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN,
- 0, RGMII_IO_MACRO_CONFIG);
-
+ rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN,
+ loopback, RGMII_IO_MACRO_CONFIG);
break;
case SPEED_10:
@@ -402,7 +400,7 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN,
SDCC_HC_REG_DDR_CONFIG);
rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN,
- RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG);
+ loopback, RGMII_IO_MACRO_CONFIG);
break;
default:
dev_err(ðqos->pdev->dev,
@@ -547,7 +545,7 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
data = of_device_get_match_data(&pdev->dev);
ethqos->por = data->por;
ethqos->num_por = data->num_por;
- ethqos->rgmii_config_looback_en = data->rgmii_config_looback_en;
+ ethqos->rgmii_config_loopback_en = data->rgmii_config_loopback_en;
ethqos->rgmii_clk = devm_clk_get(&pdev->dev, "rgmii");
if (IS_ERR(ethqos->rgmii_clk)) {
--
2.39.2
From: Brian Masney <[email protected]>
EMAC3 is a Qualcomm variant of dwmac4 that functions the same, but has a
different address space layout for MTL and DMA registers. This makes the
patch a bit more complicated than we would like so let's explain why the
current approach was used.
The different address ranges between the two variants can be represented
with 7 different sets of #ifdefs like the following:
#if IS_ENABLED(CONFIG_DWMAC_QCOM_VER3)
# define MTL_CHAN_BASE_ADDR 0x00008000
# define MTL_CHAN_BASE_OFFSET 0x1000
#else
# define MTL_CHAN_BASE_ADDR 0x00000d00
# define MTL_CHAN_BASE_OFFSET 0x40
#endif
This won't be acceptable for upstream inclusion since it would be nice
to enable both variants simultaneously without recompiling.
The next approach that was checked was to have a function pointer
embedded inside a structure that does the appropriate conversion based
on the variant that's in use. However, some of the function definitions
are like the following:
void emac3_set_rx_ring_len(void __iomem *ioaddr, u32 len, u32 chan)
We can't do a container_of() with an __iomem address. Changing these
functions to pass in an extra regular structure had a cascading effect
across the different variants, and the change was quickly becoming
large. It would also be hard to test and review.
So the approach that was decided to go with here is to take the existing
dwmac4_XXX callbacks, rename it to do_XXX, and do the following:
static void do_XXX(..., int addr_offset)
{
// Code from existing dwmac4 implementation.
}
static inline void emac3_XXX(...)
{
do_XXX(..., EMAC3_ADDR_OFFSET(...));
}
static inline void dwmac4_XXX(...)
{
do_XXX(..., DWMAC4_ADDR_OFFSET(...));
}
Prior to the introduction of this patch, dwmac4_dma_init_channel() and
dwmac410_dma_init_channel() already had the problem of copy and paste
with trivial changes made.
While changes are being made here, this patch also fixes a bad comment
that was in dwmac4_config_cbs (s/high/low).
Signed-off-by: Brian Masney <[email protected]>
Co-developed-by: Andrew Halaney <[email protected]>
Signed-off-by: Andrew Halaney <[email protected]>
---
drivers/net/ethernet/stmicro/stmmac/dwmac4.h | 32 +-
.../net/ethernet/stmicro/stmmac/dwmac4_core.c | 190 ++++++++--
.../net/ethernet/stmicro/stmmac/dwmac4_dma.c | 336 ++++++++++++++----
.../net/ethernet/stmicro/stmmac/dwmac4_dma.h | 38 ++
.../net/ethernet/stmicro/stmmac/dwmac4_lib.c | 144 ++++++--
drivers/net/ethernet/stmicro/stmmac/hwif.c | 29 +-
drivers/net/ethernet/stmicro/stmmac/hwif.h | 2 +
.../ethernet/stmicro/stmmac/stmmac_ethtool.c | 6 +-
.../net/ethernet/stmicro/stmmac/stmmac_main.c | 17 +-
.../net/ethernet/stmicro/stmmac/stmmac_mdio.c | 9 +-
.../net/ethernet/stmicro/stmmac/stmmac_ptp.c | 4 +-
include/linux/stmmac.h | 1 +
12 files changed, 672 insertions(+), 136 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
index ccd49346d3b3..56355d65fa4b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
@@ -333,7 +333,16 @@ enum power_event {
#define MTL_RXQ_DMA_MAP1 0x00000c34 /* queue 4 to 7 */
#define MTL_RXQ_DMA_QXMDMACH_MASK(x) (0xf << 8 * (x))
#define MTL_RXQ_DMA_QXMDMACH(chan, q) ((chan) << (8 * (q)))
-
+#define EMAC3_MTL_CHAN_BASE_ADDR 0x00008000
+#define EMAC3_MTL_CHAN_BASE_OFFSET 0x1000
+#define EMAC3_MTL_CHANX_BASE_ADDR(x) (EMAC3_MTL_CHAN_BASE_ADDR + \
+ ((x) * EMAC3_MTL_CHAN_BASE_OFFSET))
+
+#define EMAC3_MTL_CHAN_TX_OP_MODE(x) EMAC3_MTL_CHANX_BASE_ADDR(x)
+#define EMAC3_MTL_CHAN_TX_DEBUG(x) (EMAC3_MTL_CHANX_BASE_ADDR(x) + 0x8)
+#define EMAC3_MTL_CHAN_INT_CTRL(x) (EMAC3_MTL_CHANX_BASE_ADDR(x) + 0x2c)
+#define EMAC3_MTL_CHAN_RX_OP_MODE(x) (EMAC3_MTL_CHANX_BASE_ADDR(x) + 0x30)
+#define EMAC3_MTL_CHAN_RX_DEBUG(x) (EMAC3_MTL_CHANX_BASE_ADDR(x) + 0x38)
#define MTL_CHAN_BASE_ADDR 0x00000d00
#define MTL_CHAN_BASE_OFFSET 0x40
#define MTL_CHANX_BASE_ADDR(x) (MTL_CHAN_BASE_ADDR + \
@@ -386,6 +395,10 @@ enum power_event {
#define MTL_OP_MODE_RTC_128 (3 << MTL_OP_MODE_RTC_SHIFT)
/* MTL ETS Control register */
+#define EMAC3_MTL_ETS_CTRL_BASE_ADDR 0x00008010
+#define EMAC3_MTL_ETS_CTRL_BASE_OFFSET 0x1000
+#define EMAC3_MTL_ETSX_CTRL_BASE_ADDR(x) (EMAC3_MTL_ETS_CTRL_BASE_ADDR + \
+ ((x) * EMAC3_MTL_ETS_CTRL_BASE_OFFSET))
#define MTL_ETS_CTRL_BASE_ADDR 0x00000d10
#define MTL_ETS_CTRL_BASE_OFFSET 0x40
#define MTL_ETSX_CTRL_BASE_ADDR(x) (MTL_ETS_CTRL_BASE_ADDR + \
@@ -395,6 +408,10 @@ enum power_event {
#define MTL_ETS_CTRL_AVALG BIT(2)
/* MTL Queue Quantum Weight */
+#define EMAC3_MTL_TXQ_WEIGHT_BASE_ADDR 0x00008018
+#define EMAC3_MTL_TXQ_WEIGHT_BASE_OFFSET 0x1000
+#define EMAC3_MTL_TXQX_WEIGHT_BASE_ADDR(x) (EMAC3_MTL_TXQ_WEIGHT_BASE_ADDR + \
+ ((x) * EMAC3_MTL_TXQ_WEIGHT_BASE_OFFSET))
#define MTL_TXQ_WEIGHT_BASE_ADDR 0x00000d18
#define MTL_TXQ_WEIGHT_BASE_OFFSET 0x40
#define MTL_TXQX_WEIGHT_BASE_ADDR(x) (MTL_TXQ_WEIGHT_BASE_ADDR + \
@@ -402,6 +419,11 @@ enum power_event {
#define MTL_TXQ_WEIGHT_ISCQW_MASK GENMASK(20, 0)
/* MTL sendSlopeCredit register */
+
+#define EMAC3_MTL_SEND_SLP_CRED_BASE_ADDR 0x0000801c
+#define EMAC3_MTL_SEND_SLP_CRED_OFFSET 0x1000
+#define EMAC3_MTL_SEND_SLP_CREDX_BASE_ADDR(x) (EMAC3_MTL_SEND_SLP_CRED_BASE_ADDR + \
+ ((x) * EMAC3_MTL_SEND_SLP_CRED_OFFSET))
#define MTL_SEND_SLP_CRED_BASE_ADDR 0x00000d1c
#define MTL_SEND_SLP_CRED_OFFSET 0x40
#define MTL_SEND_SLP_CREDX_BASE_ADDR(x) (MTL_SEND_SLP_CRED_BASE_ADDR + \
@@ -410,6 +432,10 @@ enum power_event {
#define MTL_SEND_SLP_CRED_SSC_MASK GENMASK(13, 0)
/* MTL hiCredit register */
+#define EMAC3_MTL_HIGH_CRED_BASE_ADDR 0x00008020
+#define EMAC3_MTL_HIGH_CRED_OFFSET 0x1000
+#define EMAC3_MTL_HIGH_CREDX_BASE_ADDR(x) (EMAC3_MTL_HIGH_CRED_BASE_ADDR + \
+ ((x) * EMAC3_MTL_HIGH_CRED_OFFSET))
#define MTL_HIGH_CRED_BASE_ADDR 0x00000d20
#define MTL_HIGH_CRED_OFFSET 0x40
#define MTL_HIGH_CREDX_BASE_ADDR(x) (MTL_HIGH_CRED_BASE_ADDR + \
@@ -418,6 +444,10 @@ enum power_event {
#define MTL_HIGH_CRED_HC_MASK GENMASK(28, 0)
/* MTL loCredit register */
+#define EMAC3_MTL_LOW_CRED_BASE_ADDR 0x00008024
+#define EMAC3_MTL_LOW_CRED_OFFSET 0x1000
+#define EMAC3_MTL_LOW_CREDX_BASE_ADDR(x) (EMAC3_MTL_LOW_CRED_BASE_ADDR + \
+ ((x) * EMAC3_MTL_LOW_CRED_OFFSET))
#define MTL_LOW_CRED_BASE_ADDR 0x00000d24
#define MTL_LOW_CRED_OFFSET 0x40
#define MTL_LOW_CREDX_BASE_ADDR(x) (MTL_LOW_CRED_BASE_ADDR + \
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
index 8c7a0b7c9952..88df064b52ea 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
@@ -198,15 +198,28 @@ static void dwmac4_prog_mtl_tx_algorithms(struct mac_device_info *hw,
writel(value, ioaddr + MTL_OPERATION_MODE);
}
-static void dwmac4_set_mtl_tx_queue_weight(struct mac_device_info *hw,
- u32 weight, u32 queue)
+static void do_set_mtl_tx_queue_weight(struct mac_device_info *hw,
+ u32 addr_offset, u32 weight)
{
void __iomem *ioaddr = hw->pcsr;
- u32 value = readl(ioaddr + MTL_TXQX_WEIGHT_BASE_ADDR(queue));
+ u32 value = readl(ioaddr + addr_offset);
value &= ~MTL_TXQ_WEIGHT_ISCQW_MASK;
value |= weight & MTL_TXQ_WEIGHT_ISCQW_MASK;
- writel(value, ioaddr + MTL_TXQX_WEIGHT_BASE_ADDR(queue));
+ writel(value, ioaddr + addr_offset);
+}
+
+static inline void emac3_set_mtl_tx_queue_weight(struct mac_device_info *hw,
+ u32 weight, u32 queue)
+{
+ do_set_mtl_tx_queue_weight(hw, EMAC3_MTL_TXQX_WEIGHT_BASE_ADDR(queue),
+ weight);
+}
+
+static inline void dwmac4_set_mtl_tx_queue_weight(struct mac_device_info *hw,
+ u32 weight, u32 queue)
+{
+ do_set_mtl_tx_queue_weight(hw, MTL_TXQX_WEIGHT_BASE_ADDR(queue), weight);
}
static void dwmac4_map_mtl_dma(struct mac_device_info *hw, u32 queue, u32 chan)
@@ -227,9 +240,13 @@ static void dwmac4_map_mtl_dma(struct mac_device_info *hw, u32 queue, u32 chan)
}
}
-static void dwmac4_config_cbs(struct mac_device_info *hw,
- u32 send_slope, u32 idle_slope,
- u32 high_credit, u32 low_credit, u32 queue)
+static void do_config_cbs(struct mac_device_info *hw, u32 send_slope,
+ u32 idle_slope, u32 high_credit, u32 low_credit,
+ u32 queue, u32 etsx_ctrl_base_addr,
+ u32 send_slp_credx_base_addr,
+ u32 high_credx_base_addr, u32 low_credx_base_addr,
+ void (*set_mtl_tx_queue_weight)(struct mac_device_info *hw,
+ u32 weight, u32 queue))
{
void __iomem *ioaddr = hw->pcsr;
u32 value;
@@ -241,31 +258,55 @@ static void dwmac4_config_cbs(struct mac_device_info *hw,
pr_debug("\tlow_credit: 0x%08x\n", low_credit);
/* enable AV algorithm */
- value = readl(ioaddr + MTL_ETSX_CTRL_BASE_ADDR(queue));
+ value = readl(ioaddr + etsx_ctrl_base_addr);
value |= MTL_ETS_CTRL_AVALG;
value |= MTL_ETS_CTRL_CC;
- writel(value, ioaddr + MTL_ETSX_CTRL_BASE_ADDR(queue));
+ writel(value, ioaddr + etsx_ctrl_base_addr);
/* configure send slope */
- value = readl(ioaddr + MTL_SEND_SLP_CREDX_BASE_ADDR(queue));
+ value = readl(ioaddr + send_slp_credx_base_addr);
value &= ~MTL_SEND_SLP_CRED_SSC_MASK;
value |= send_slope & MTL_SEND_SLP_CRED_SSC_MASK;
- writel(value, ioaddr + MTL_SEND_SLP_CREDX_BASE_ADDR(queue));
+ writel(value, ioaddr + send_slp_credx_base_addr);
/* configure idle slope (same register as tx weight) */
- dwmac4_set_mtl_tx_queue_weight(hw, idle_slope, queue);
+ set_mtl_tx_queue_weight(hw, idle_slope, queue);
/* configure high credit */
- value = readl(ioaddr + MTL_HIGH_CREDX_BASE_ADDR(queue));
+ value = readl(ioaddr + high_credx_base_addr);
value &= ~MTL_HIGH_CRED_HC_MASK;
value |= high_credit & MTL_HIGH_CRED_HC_MASK;
- writel(value, ioaddr + MTL_HIGH_CREDX_BASE_ADDR(queue));
+ writel(value, ioaddr + high_credx_base_addr);
- /* configure high credit */
- value = readl(ioaddr + MTL_LOW_CREDX_BASE_ADDR(queue));
+ /* configure low credit */
+ value = readl(ioaddr + low_credx_base_addr);
value &= ~MTL_HIGH_CRED_LC_MASK;
value |= low_credit & MTL_HIGH_CRED_LC_MASK;
- writel(value, ioaddr + MTL_LOW_CREDX_BASE_ADDR(queue));
+ writel(value, ioaddr + low_credx_base_addr);
+}
+
+static inline void emac3_config_cbs(struct mac_device_info *hw, u32 send_slope,
+ u32 idle_slope, u32 high_credit,
+ u32 low_credit, u32 queue)
+{
+ do_config_cbs(hw, send_slope, idle_slope, high_credit, low_credit,
+ queue, EMAC3_MTL_ETSX_CTRL_BASE_ADDR(queue),
+ EMAC3_MTL_SEND_SLP_CREDX_BASE_ADDR(queue),
+ EMAC3_MTL_HIGH_CREDX_BASE_ADDR(queue),
+ EMAC3_MTL_LOW_CREDX_BASE_ADDR(queue),
+ emac3_set_mtl_tx_queue_weight);
+}
+
+static inline void dwmac4_config_cbs(struct mac_device_info *hw, u32 send_slope,
+ u32 idle_slope, u32 high_credit,
+ u32 low_credit, u32 queue)
+{
+ do_config_cbs(hw, send_slope, idle_slope, high_credit, low_credit,
+ queue, MTL_ETSX_CTRL_BASE_ADDR(queue),
+ MTL_SEND_SLP_CREDX_BASE_ADDR(queue),
+ MTL_HIGH_CREDX_BASE_ADDR(queue),
+ MTL_LOW_CREDX_BASE_ADDR(queue),
+ dwmac4_set_mtl_tx_queue_weight);
}
static void dwmac4_dump_regs(struct mac_device_info *hw, u32 *reg_space)
@@ -814,7 +855,8 @@ static void dwmac4_phystatus(void __iomem *ioaddr, struct stmmac_extra_stats *x)
}
}
-static int dwmac4_irq_mtl_status(struct mac_device_info *hw, u32 chan)
+static int do_irq_mtl_status(struct mac_device_info *hw, u32 chan,
+ u32 addr_offset)
{
void __iomem *ioaddr = hw->pcsr;
u32 mtl_int_qx_status;
@@ -825,12 +867,12 @@ static int dwmac4_irq_mtl_status(struct mac_device_info *hw, u32 chan)
/* Check MTL Interrupt */
if (mtl_int_qx_status & MTL_INT_QX(chan)) {
/* read Queue x Interrupt status */
- u32 status = readl(ioaddr + MTL_CHAN_INT_CTRL(chan));
+ u32 status = readl(ioaddr + addr_offset);
if (status & MTL_RX_OVERFLOW_INT) {
/* clear Interrupt */
writel(status | MTL_RX_OVERFLOW_INT,
- ioaddr + MTL_CHAN_INT_CTRL(chan));
+ ioaddr + addr_offset);
ret = CORE_IRQ_MTL_RX_OVERFLOW;
}
}
@@ -838,6 +880,16 @@ static int dwmac4_irq_mtl_status(struct mac_device_info *hw, u32 chan)
return ret;
}
+static inline int emac3_irq_mtl_status(struct mac_device_info *hw, u32 chan)
+{
+ return do_irq_mtl_status(hw, chan, EMAC3_MTL_CHAN_INT_CTRL(chan));
+}
+
+static inline int dwmac4_irq_mtl_status(struct mac_device_info *hw, u32 chan)
+{
+ return do_irq_mtl_status(hw, chan, MTL_CHAN_INT_CTRL(chan));
+}
+
static int dwmac4_irq_status(struct mac_device_info *hw,
struct stmmac_extra_stats *x)
{
@@ -888,14 +940,16 @@ static int dwmac4_irq_status(struct mac_device_info *hw,
return ret;
}
-static void dwmac4_debug(void __iomem *ioaddr, struct stmmac_extra_stats *x,
- u32 rx_queues, u32 tx_queues)
+static void do_debug(void __iomem *ioaddr, struct stmmac_extra_stats *x,
+ u32 rx_queues, u32 tx_queues,
+ u32 (*rx_addr_offset)(u32 queue),
+ u32 (*tx_addr_offset)(u32 queue))
{
u32 value;
u32 queue;
for (queue = 0; queue < tx_queues; queue++) {
- value = readl(ioaddr + MTL_CHAN_TX_DEBUG(queue));
+ value = readl(ioaddr + tx_addr_offset(queue));
if (value & MTL_DEBUG_TXSTSFSTS)
x->mtl_tx_status_fifo_full++;
@@ -920,7 +974,7 @@ static void dwmac4_debug(void __iomem *ioaddr, struct stmmac_extra_stats *x,
}
for (queue = 0; queue < rx_queues; queue++) {
- value = readl(ioaddr + MTL_CHAN_RX_DEBUG(queue));
+ value = readl(ioaddr + rx_addr_offset(queue));
if (value & MTL_DEBUG_RXFSTS_MASK) {
u32 rxfsts = (value & MTL_DEBUG_RXFSTS_MASK)
@@ -977,6 +1031,42 @@ static void dwmac4_debug(void __iomem *ioaddr, struct stmmac_extra_stats *x,
x->mac_gmii_rx_proto_engine++;
}
+static inline u32 emac3_debug_rx_addr_offset(u32 queue)
+{
+ return EMAC3_MTL_CHAN_RX_DEBUG(queue);
+}
+
+static inline u32 emac3_debug_tx_addr_offset(u32 queue)
+{
+ return EMAC3_MTL_CHAN_TX_DEBUG(queue);
+}
+
+static inline void emac3_debug(void __iomem *ioaddr,
+ struct stmmac_extra_stats *x, u32 rx_queues,
+ u32 tx_queues)
+{
+ do_debug(ioaddr, x, rx_queues, tx_queues, emac3_debug_rx_addr_offset,
+ emac3_debug_tx_addr_offset);
+}
+
+static inline u32 dwmac4_debug_rx_addr_offset(u32 queue)
+{
+ return MTL_CHAN_RX_DEBUG(queue);
+}
+
+static inline u32 dwmac4_debug_tx_addr_offset(u32 queue)
+{
+ return MTL_CHAN_TX_DEBUG(queue);
+}
+
+static inline void dwmac4_debug(void __iomem *ioaddr,
+ struct stmmac_extra_stats *x, u32 rx_queues,
+ u32 tx_queues)
+{
+ do_debug(ioaddr, x, rx_queues, tx_queues, dwmac4_debug_rx_addr_offset,
+ dwmac4_debug_tx_addr_offset);
+}
+
static void dwmac4_set_mac_loopback(void __iomem *ioaddr, bool enable)
{
u32 value = readl(ioaddr + GMAC_CONFIG);
@@ -1309,6 +1399,58 @@ const struct stmmac_ops dwmac510_ops = {
.restore_hw_vlan_rx_fltr = dwmac4_restore_hw_vlan_rx_fltr,
};
+const struct stmmac_ops emac3_ops = {
+ .core_init = dwmac4_core_init,
+ .set_mac = stmmac_dwmac4_set_mac,
+ .rx_ipc = dwmac4_rx_ipc_enable,
+ .rx_queue_enable = dwmac4_rx_queue_enable,
+ .rx_queue_prio = dwmac4_rx_queue_priority,
+ .tx_queue_prio = dwmac4_tx_queue_priority,
+ .rx_queue_routing = dwmac4_rx_queue_routing,
+ .prog_mtl_rx_algorithms = dwmac4_prog_mtl_rx_algorithms,
+ .prog_mtl_tx_algorithms = dwmac4_prog_mtl_tx_algorithms,
+ .set_mtl_tx_queue_weight = emac3_set_mtl_tx_queue_weight,
+ .map_mtl_to_dma = dwmac4_map_mtl_dma,
+ .config_cbs = emac3_config_cbs,
+ .dump_regs = dwmac4_dump_regs,
+ .host_irq_status = dwmac4_irq_status,
+ .host_mtl_irq_status = emac3_irq_mtl_status,
+ .flow_ctrl = dwmac4_flow_ctrl,
+ .pmt = dwmac4_pmt,
+ .set_umac_addr = dwmac4_set_umac_addr,
+ .get_umac_addr = dwmac4_get_umac_addr,
+ .set_eee_mode = dwmac4_set_eee_mode,
+ .reset_eee_mode = dwmac4_reset_eee_mode,
+ .set_eee_lpi_entry_timer = dwmac4_set_eee_lpi_entry_timer,
+ .set_eee_timer = dwmac4_set_eee_timer,
+ .set_eee_pls = dwmac4_set_eee_pls,
+ .pcs_ctrl_ane = dwmac4_ctrl_ane,
+ .pcs_rane = dwmac4_rane,
+ .pcs_get_adv_lp = dwmac4_get_adv_lp,
+ .debug = emac3_debug,
+ .set_filter = dwmac4_set_filter,
+ .safety_feat_config = dwmac5_safety_feat_config,
+ .safety_feat_irq_status = dwmac5_safety_feat_irq_status,
+ .safety_feat_dump = dwmac5_safety_feat_dump,
+ .rxp_config = dwmac5_rxp_config,
+ .flex_pps_config = dwmac5_flex_pps_config,
+ .set_mac_loopback = dwmac4_set_mac_loopback,
+ .update_vlan_hash = dwmac4_update_vlan_hash,
+ .sarc_configure = dwmac4_sarc_configure,
+ .enable_vlan = dwmac4_enable_vlan,
+ .set_arp_offload = dwmac4_set_arp_offload,
+ .config_l3_filter = dwmac4_config_l3_filter,
+ .config_l4_filter = dwmac4_config_l4_filter,
+ .est_configure = dwmac5_est_configure,
+ .est_irq_status = dwmac5_est_irq_status,
+ .fpe_configure = dwmac5_fpe_configure,
+ .fpe_send_mpacket = dwmac5_fpe_send_mpacket,
+ .fpe_irq_status = dwmac5_fpe_irq_status,
+ .add_hw_vlan_rx_fltr = dwmac4_add_hw_vlan_rx_fltr,
+ .del_hw_vlan_rx_fltr = dwmac4_del_hw_vlan_rx_fltr,
+ .restore_hw_vlan_rx_fltr = dwmac4_restore_hw_vlan_rx_fltr,
+};
+
static u32 dwmac4_get_num_vlan(void __iomem *ioaddr)
{
u32 val, num_vlan;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
index d99fa028c646..789657b837fc 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
@@ -68,77 +68,127 @@ static void dwmac4_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
writel(value, ioaddr + DMA_SYS_BUS_MODE);
}
-static void dwmac4_dma_init_rx_chan(void __iomem *ioaddr,
- struct stmmac_dma_cfg *dma_cfg,
- dma_addr_t dma_rx_phy, u32 chan)
+static void do_dma_init_rx_chan(void __iomem *ioaddr, u32 rx_ctl_offset,
+ u32 rx_high_offset, u32 rx_base_offset,
+ struct stmmac_dma_cfg *dma_cfg,
+ dma_addr_t dma_rx_phy)
{
u32 value;
u32 rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl;
- value = readl(ioaddr + DMA_CHAN_RX_CONTROL(chan));
+ value = readl(ioaddr + rx_ctl_offset);
value = value | (rxpbl << DMA_BUS_MODE_RPBL_SHIFT);
- writel(value, ioaddr + DMA_CHAN_RX_CONTROL(chan));
+ writel(value, ioaddr + rx_ctl_offset);
if (IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT) && likely(dma_cfg->eame))
- writel(upper_32_bits(dma_rx_phy),
- ioaddr + DMA_CHAN_RX_BASE_ADDR_HI(chan));
+ writel(upper_32_bits(dma_rx_phy), ioaddr + rx_high_offset);
- writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_CHAN_RX_BASE_ADDR(chan));
+ writel(lower_32_bits(dma_rx_phy), ioaddr + rx_base_offset);
}
-static void dwmac4_dma_init_tx_chan(void __iomem *ioaddr,
- struct stmmac_dma_cfg *dma_cfg,
- dma_addr_t dma_tx_phy, u32 chan)
+static inline void emac3_dma_init_rx_chan(void __iomem *ioaddr,
+ struct stmmac_dma_cfg *dma_cfg,
+ dma_addr_t dma_rx_phy, u32 chan)
+{
+ do_dma_init_rx_chan(ioaddr, EMAC3_DMA_CHAN_RX_CONTROL(chan),
+ EMAC3_DMA_CHAN_RX_BASE_ADDR_HI(chan),
+ EMAC3_DMA_CHAN_RX_BASE_ADDR(chan),
+ dma_cfg, dma_rx_phy);
+}
+
+static inline void dwmac4_dma_init_rx_chan(void __iomem *ioaddr,
+ struct stmmac_dma_cfg *dma_cfg,
+ dma_addr_t dma_rx_phy, u32 chan)
+{
+ do_dma_init_rx_chan(ioaddr, DMA_CHAN_RX_CONTROL(chan),
+ DMA_CHAN_RX_BASE_ADDR_HI(chan),
+ DMA_CHAN_RX_BASE_ADDR(chan),
+ dma_cfg, dma_rx_phy);
+}
+
+static void do_dma_init_tx_chan(void __iomem *ioaddr, u32 tx_ctl_offset,
+ u32 tx_high_offset, u32 tx_base_offset,
+ struct stmmac_dma_cfg *dma_cfg,
+ dma_addr_t dma_tx_phy)
{
u32 value;
u32 txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
- value = readl(ioaddr + DMA_CHAN_TX_CONTROL(chan));
+ value = readl(ioaddr + tx_ctl_offset);
value = value | (txpbl << DMA_BUS_MODE_PBL_SHIFT);
/* Enable OSP to get best performance */
value |= DMA_CONTROL_OSP;
- writel(value, ioaddr + DMA_CHAN_TX_CONTROL(chan));
+ writel(value, ioaddr + tx_ctl_offset);
if (IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT) && likely(dma_cfg->eame))
- writel(upper_32_bits(dma_tx_phy),
- ioaddr + DMA_CHAN_TX_BASE_ADDR_HI(chan));
+ writel(upper_32_bits(dma_tx_phy), ioaddr + tx_high_offset);
+
+ writel(lower_32_bits(dma_tx_phy), ioaddr + tx_base_offset);
+}
- writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_CHAN_TX_BASE_ADDR(chan));
+static inline void emac3_dma_init_tx_chan(void __iomem *ioaddr,
+ struct stmmac_dma_cfg *dma_cfg,
+ dma_addr_t dma_tx_phy, u32 chan)
+{
+ do_dma_init_tx_chan(ioaddr, EMAC3_DMA_CHAN_TX_CONTROL(chan),
+ EMAC3_DMA_CHAN_TX_BASE_ADDR_HI(chan),
+ EMAC3_DMA_CHAN_TX_BASE_ADDR(chan),
+ dma_cfg, dma_tx_phy);
}
-static void dwmac4_dma_init_channel(void __iomem *ioaddr,
- struct stmmac_dma_cfg *dma_cfg, u32 chan)
+static inline void dwmac4_dma_init_tx_chan(void __iomem *ioaddr,
+ struct stmmac_dma_cfg *dma_cfg,
+ dma_addr_t dma_tx_phy, u32 chan)
+{
+ do_dma_init_tx_chan(ioaddr, DMA_CHAN_TX_CONTROL(chan),
+ DMA_CHAN_TX_BASE_ADDR_HI(chan),
+ DMA_CHAN_TX_BASE_ADDR(chan),
+ dma_cfg, dma_tx_phy);
+}
+
+static void do_dma_init_channel(void __iomem *ioaddr,
+ struct stmmac_dma_cfg *dma_cfg,
+ u32 addr_offset, u32 intr_addr_offset,
+ u32 intr_addr_mask)
{
u32 value;
/* common channel control register config */
- value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
+ value = readl(ioaddr + addr_offset);
if (dma_cfg->pblx8)
value = value | DMA_BUS_MODE_PBL;
- writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
+ writel(value, ioaddr + addr_offset);
/* Mask interrupts by writing to CSR7 */
- writel(DMA_CHAN_INTR_DEFAULT_MASK,
- ioaddr + DMA_CHAN_INTR_ENA(chan));
+ writel(intr_addr_mask, ioaddr + intr_addr_offset);
}
-static void dwmac410_dma_init_channel(void __iomem *ioaddr,
- struct stmmac_dma_cfg *dma_cfg, u32 chan)
+static inline void emac3_dma_init_channel(void __iomem *ioaddr,
+ struct stmmac_dma_cfg *dma_cfg,
+ u32 chan)
{
- u32 value;
-
- /* common channel control register config */
- value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
- if (dma_cfg->pblx8)
- value = value | DMA_BUS_MODE_PBL;
+ do_dma_init_channel(ioaddr, dma_cfg, EMAC3_DMA_CHAN_CONTROL(chan),
+ EMAC3_DMA_CHAN_INTR_ENA(chan),
+ DMA_CHAN_INTR_DEFAULT_MASK_4_10);
+}
- writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
+static inline void dwmac4_dma_init_channel(void __iomem *ioaddr,
+ struct stmmac_dma_cfg *dma_cfg,
+ u32 chan)
+{
+ do_dma_init_channel(ioaddr, dma_cfg, DMA_CHAN_CONTROL(chan),
+ DMA_CHAN_INTR_ENA(chan),
+ DMA_CHAN_INTR_DEFAULT_MASK);
+}
- /* Mask interrupts by writing to CSR7 */
- writel(DMA_CHAN_INTR_DEFAULT_MASK_4_10,
- ioaddr + DMA_CHAN_INTR_ENA(chan));
+static void dwmac410_dma_init_channel(void __iomem *ioaddr,
+ struct stmmac_dma_cfg *dma_cfg, u32 chan)
+{
+ do_dma_init_channel(ioaddr, dma_cfg, DMA_CHAN_CONTROL(chan),
+ DMA_CHAN_INTR_ENA(chan),
+ DMA_CHAN_INTR_DEFAULT_MASK_4_10);
}
static void dwmac4_dma_init(void __iomem *ioaddr,
@@ -176,6 +226,46 @@ static void dwmac4_dma_init(void __iomem *ioaddr,
}
+static void _emac3_dump_dma_regs(void __iomem *ioaddr, u32 channel,
+ u32 *reg_space)
+{
+ /* Use dwmac4's reg_space offsets to reuse common stmmac_ethtool code */
+ reg_space[DMA_CHAN_CONTROL(channel) / 4] =
+ readl(ioaddr + EMAC3_DMA_CHAN_CONTROL(channel));
+ reg_space[DMA_CHAN_TX_CONTROL(channel) / 4] =
+ readl(ioaddr + EMAC3_DMA_CHAN_TX_CONTROL(channel));
+ reg_space[DMA_CHAN_RX_CONTROL(channel) / 4] =
+ readl(ioaddr + EMAC3_DMA_CHAN_RX_CONTROL(channel));
+ reg_space[DMA_CHAN_TX_BASE_ADDR(channel) / 4] =
+ readl(ioaddr + EMAC3_DMA_CHAN_TX_BASE_ADDR(channel));
+ reg_space[DMA_CHAN_RX_BASE_ADDR(channel) / 4] =
+ readl(ioaddr + EMAC3_DMA_CHAN_RX_BASE_ADDR(channel));
+ reg_space[DMA_CHAN_TX_END_ADDR(channel) / 4] =
+ readl(ioaddr + EMAC3_DMA_CHAN_TX_END_ADDR(channel));
+ reg_space[DMA_CHAN_RX_END_ADDR(channel) / 4] =
+ readl(ioaddr + EMAC3_DMA_CHAN_RX_END_ADDR(channel));
+ reg_space[DMA_CHAN_TX_RING_LEN(channel) / 4] =
+ readl(ioaddr + EMAC3_DMA_CHAN_TX_RING_LEN(channel));
+ reg_space[DMA_CHAN_RX_RING_LEN(channel) / 4] =
+ readl(ioaddr + EMAC3_DMA_CHAN_RX_RING_LEN(channel));
+ reg_space[DMA_CHAN_INTR_ENA(channel) / 4] =
+ readl(ioaddr + EMAC3_DMA_CHAN_INTR_ENA(channel));
+ reg_space[DMA_CHAN_RX_WATCHDOG(channel) / 4] =
+ readl(ioaddr + EMAC3_DMA_CHAN_RX_WATCHDOG(channel));
+ reg_space[DMA_CHAN_SLOT_CTRL_STATUS(channel) / 4] =
+ readl(ioaddr + EMAC3_DMA_CHAN_SLOT_CTRL_STATUS(channel));
+ reg_space[DMA_CHAN_CUR_TX_DESC(channel) / 4] =
+ readl(ioaddr + EMAC3_DMA_CHAN_CUR_TX_DESC(channel));
+ reg_space[DMA_CHAN_CUR_RX_DESC(channel) / 4] =
+ readl(ioaddr + EMAC3_DMA_CHAN_CUR_RX_DESC(channel));
+ reg_space[DMA_CHAN_CUR_TX_BUF_ADDR(channel) / 4] =
+ readl(ioaddr + EMAC3_DMA_CHAN_CUR_TX_BUF_ADDR(channel));
+ reg_space[DMA_CHAN_CUR_RX_BUF_ADDR(channel) / 4] =
+ readl(ioaddr + EMAC3_DMA_CHAN_CUR_RX_BUF_ADDR(channel));
+ reg_space[DMA_CHAN_STATUS(channel) / 4] =
+ readl(ioaddr + EMAC3_DMA_CHAN_STATUS(channel));
+}
+
static void _dwmac4_dump_dma_regs(void __iomem *ioaddr, u32 channel,
u32 *reg_space)
{
@@ -215,6 +305,12 @@ static void _dwmac4_dump_dma_regs(void __iomem *ioaddr, u32 channel,
readl(ioaddr + DMA_CHAN_STATUS(channel));
}
+static void emac3_dump_dma_regs(void __iomem *ioaddr, u32 *reg_space)
+{
+ for (int i = 0; i < DMA_CHANNEL_NB_MAX; i++)
+ _emac3_dump_dma_regs(ioaddr, i, reg_space);
+}
+
static void dwmac4_dump_dma_regs(void __iomem *ioaddr, u32 *reg_space)
{
int i;
@@ -223,18 +319,23 @@ static void dwmac4_dump_dma_regs(void __iomem *ioaddr, u32 *reg_space)
_dwmac4_dump_dma_regs(ioaddr, i, reg_space);
}
+static void emac3_rx_watchdog(void __iomem *ioaddr, u32 riwt, u32 queue)
+{
+ writel(riwt, ioaddr + EMAC3_DMA_CHAN_RX_WATCHDOG(queue));
+}
+
static void dwmac4_rx_watchdog(void __iomem *ioaddr, u32 riwt, u32 queue)
{
writel(riwt, ioaddr + DMA_CHAN_RX_WATCHDOG(queue));
}
-static void dwmac4_dma_rx_chan_op_mode(void __iomem *ioaddr, int mode,
- u32 channel, int fifosz, u8 qmode)
+static void do_dma_rx_chan_op_mode(void __iomem *ioaddr, int mode, int fifosz,
+ u8 qmode, u32 addr_offset)
{
unsigned int rqs = fifosz / 256 - 1;
u32 mtl_rx_op;
- mtl_rx_op = readl(ioaddr + MTL_CHAN_RX_OP_MODE(channel));
+ mtl_rx_op = readl(ioaddr + addr_offset);
if (mode == SF_DMA_MODE) {
pr_debug("GMAC: enable RX store and forward mode\n");
@@ -292,13 +393,27 @@ static void dwmac4_dma_rx_chan_op_mode(void __iomem *ioaddr, int mode,
mtl_rx_op |= rfa << MTL_OP_MODE_RFA_SHIFT;
}
- writel(mtl_rx_op, ioaddr + MTL_CHAN_RX_OP_MODE(channel));
+ writel(mtl_rx_op, ioaddr + addr_offset);
}
-static void dwmac4_dma_tx_chan_op_mode(void __iomem *ioaddr, int mode,
+static void emac3_dma_rx_chan_op_mode(void __iomem *ioaddr, int mode,
+ u32 channel, int fifosz, u8 qmode)
+{
+ do_dma_rx_chan_op_mode(ioaddr, mode, fifosz, qmode,
+ EMAC3_MTL_CHAN_RX_OP_MODE(channel));
+}
+
+static void dwmac4_dma_rx_chan_op_mode(void __iomem *ioaddr, int mode,
u32 channel, int fifosz, u8 qmode)
{
- u32 mtl_tx_op = readl(ioaddr + MTL_CHAN_TX_OP_MODE(channel));
+ do_dma_rx_chan_op_mode(ioaddr, mode, fifosz, qmode,
+ MTL_CHAN_RX_OP_MODE(channel));
+}
+
+static void do_dma_tx_chan_op_mode(void __iomem *ioaddr, int mode, int fifosz,
+ u8 qmode, u32 addr_offset)
+{
+ u32 mtl_tx_op = readl(ioaddr + addr_offset);
unsigned int tqs = fifosz / 256 - 1;
if (mode == SF_DMA_MODE) {
@@ -344,7 +459,21 @@ static void dwmac4_dma_tx_chan_op_mode(void __iomem *ioaddr, int mode,
mtl_tx_op &= ~MTL_OP_MODE_TQS_MASK;
mtl_tx_op |= tqs << MTL_OP_MODE_TQS_SHIFT;
- writel(mtl_tx_op, ioaddr + MTL_CHAN_TX_OP_MODE(channel));
+ writel(mtl_tx_op, ioaddr + addr_offset);
+}
+
+static inline void emac3_dma_tx_chan_op_mode(void __iomem *ioaddr, int mode,
+ u32 channel, int fifosz, u8 qmode)
+{
+ do_dma_tx_chan_op_mode(ioaddr, mode, fifosz, qmode,
+ EMAC3_MTL_CHAN_TX_OP_MODE(channel));
+}
+
+static inline void dwmac4_dma_tx_chan_op_mode(void __iomem *ioaddr, int mode,
+ u32 channel, int fifosz, u8 qmode)
+{
+ do_dma_tx_chan_op_mode(ioaddr, mode, fifosz, qmode,
+ MTL_CHAN_TX_OP_MODE(channel));
}
static int dwmac4_get_hw_feature(void __iomem *ioaddr,
@@ -442,26 +571,29 @@ static int dwmac4_get_hw_feature(void __iomem *ioaddr,
}
/* Enable/disable TSO feature and set MSS */
-static void dwmac4_enable_tso(void __iomem *ioaddr, bool en, u32 chan)
+static void do_enable_tso(void __iomem *ioaddr, bool en, u32 addr_offset)
{
- u32 value;
+ u32 value = readl(ioaddr + addr_offset);
- if (en) {
- /* enable TSO */
- value = readl(ioaddr + DMA_CHAN_TX_CONTROL(chan));
- writel(value | DMA_CONTROL_TSE,
- ioaddr + DMA_CHAN_TX_CONTROL(chan));
- } else {
- /* enable TSO */
- value = readl(ioaddr + DMA_CHAN_TX_CONTROL(chan));
- writel(value & ~DMA_CONTROL_TSE,
- ioaddr + DMA_CHAN_TX_CONTROL(chan));
- }
+ if (en)
+ writel(value | DMA_CONTROL_TSE, ioaddr + addr_offset);
+ else
+ writel(value & ~DMA_CONTROL_TSE, ioaddr + addr_offset);
}
-static void dwmac4_qmode(void __iomem *ioaddr, u32 channel, u8 qmode)
+static inline void emac3_enable_tso(void __iomem *ioaddr, bool en, u32 chan)
{
- u32 mtl_tx_op = readl(ioaddr + MTL_CHAN_TX_OP_MODE(channel));
+ do_enable_tso(ioaddr, en, EMAC3_DMA_CHAN_TX_CONTROL(chan));
+}
+
+static inline void dwmac4_enable_tso(void __iomem *ioaddr, bool en, u32 chan)
+{
+ do_enable_tso(ioaddr, en, DMA_CHAN_TX_CONTROL(chan));
+}
+
+static void do_qmode(void __iomem *ioaddr, u8 qmode, u32 addr_offset)
+{
+ u32 mtl_tx_op = readl(ioaddr + addr_offset);
mtl_tx_op &= ~MTL_OP_MODE_TXQEN_MASK;
if (qmode != MTL_QUEUE_AVB)
@@ -469,20 +601,40 @@ static void dwmac4_qmode(void __iomem *ioaddr, u32 channel, u8 qmode)
else
mtl_tx_op |= MTL_OP_MODE_TXQEN_AV;
- writel(mtl_tx_op, ioaddr + MTL_CHAN_TX_OP_MODE(channel));
+ writel(mtl_tx_op, ioaddr + addr_offset);
+}
+
+static inline void emac3_qmode(void __iomem *ioaddr, u32 channel, u8 qmode)
+{
+ do_qmode(ioaddr, qmode, EMAC3_MTL_CHAN_TX_OP_MODE(channel));
+}
+
+static inline void dwmac4_qmode(void __iomem *ioaddr, u32 channel, u8 qmode)
+{
+ do_qmode(ioaddr, qmode, MTL_CHAN_TX_OP_MODE(channel));
}
-static void dwmac4_set_bfsize(void __iomem *ioaddr, int bfsize, u32 chan)
+static void do_set_bfsize(void __iomem *ioaddr, int bfsize, u32 addr_offset)
{
- u32 value = readl(ioaddr + DMA_CHAN_RX_CONTROL(chan));
+ u32 value = readl(ioaddr + addr_offset);
value &= ~DMA_RBSZ_MASK;
value |= (bfsize << DMA_RBSZ_SHIFT) & DMA_RBSZ_MASK;
- writel(value, ioaddr + DMA_CHAN_RX_CONTROL(chan));
+ writel(value, ioaddr + addr_offset);
+}
+
+static inline void emac3_set_bfsize(void __iomem *ioaddr, int bfsize, u32 chan)
+{
+ do_set_bfsize(ioaddr, bfsize, EMAC3_DMA_CHAN_RX_CONTROL(chan));
+}
+
+static inline void dwmac4_set_bfsize(void __iomem *ioaddr, int bfsize, u32 chan)
+{
+ do_set_bfsize(ioaddr, bfsize, DMA_CHAN_RX_CONTROL(chan));
}
-static void dwmac4_enable_sph(void __iomem *ioaddr, bool en, u32 chan)
+static void do_enable_sph(void __iomem *ioaddr, bool en, u32 addr_offset)
{
u32 value = readl(ioaddr + GMAC_EXT_CONFIG);
@@ -490,26 +642,36 @@ static void dwmac4_enable_sph(void __iomem *ioaddr, bool en, u32 chan)
value |= GMAC_CONFIG_HDSMS_256; /* Segment max 256 bytes */
writel(value, ioaddr + GMAC_EXT_CONFIG);
- value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
+ value = readl(ioaddr + addr_offset);
if (en)
value |= DMA_CONTROL_SPH;
else
value &= ~DMA_CONTROL_SPH;
- writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
+ writel(value, ioaddr + addr_offset);
}
-static int dwmac4_enable_tbs(void __iomem *ioaddr, bool en, u32 chan)
+static inline void emac3_enable_sph(void __iomem *ioaddr, bool en, u32 chan)
{
- u32 value = readl(ioaddr + DMA_CHAN_TX_CONTROL(chan));
+ do_enable_sph(ioaddr, en, EMAC3_DMA_CHAN_CONTROL(chan));
+}
+
+static inline void dwmac4_enable_sph(void __iomem *ioaddr, bool en, u32 chan)
+{
+ do_enable_sph(ioaddr, en, DMA_CHAN_CONTROL(chan));
+}
+
+static int do_enable_tbs(void __iomem *ioaddr, bool en, u32 addr_offset)
+{
+ u32 value = readl(ioaddr + addr_offset);
if (en)
value |= DMA_CONTROL_EDSE;
else
value &= ~DMA_CONTROL_EDSE;
- writel(value, ioaddr + DMA_CHAN_TX_CONTROL(chan));
+ writel(value, ioaddr + addr_offset);
- value = readl(ioaddr + DMA_CHAN_TX_CONTROL(chan)) & DMA_CONTROL_EDSE;
+ value = readl(ioaddr + addr_offset) & DMA_CONTROL_EDSE;
if (en && !value)
return -EIO;
@@ -517,6 +679,16 @@ static int dwmac4_enable_tbs(void __iomem *ioaddr, bool en, u32 chan)
return 0;
}
+static inline int emac3_enable_tbs(void __iomem *ioaddr, bool en, u32 chan)
+{
+ return do_enable_tbs(ioaddr, en, EMAC3_DMA_CHAN_TX_CONTROL(chan));
+}
+
+static inline int dwmac4_enable_tbs(void __iomem *ioaddr, bool en, u32 chan)
+{
+ return do_enable_tbs(ioaddr, en, DMA_CHAN_TX_CONTROL(chan));
+}
+
const struct stmmac_dma_ops dwmac4_dma_ops = {
.reset = dwmac4_dma_reset,
.init = dwmac4_dma_init,
@@ -575,3 +747,33 @@ const struct stmmac_dma_ops dwmac410_dma_ops = {
.enable_sph = dwmac4_enable_sph,
.enable_tbs = dwmac4_enable_tbs,
};
+
+const struct stmmac_dma_ops emac3_dma_ops = {
+ .reset = dwmac4_dma_reset,
+ .init = dwmac4_dma_init,
+ .init_chan = emac3_dma_init_channel,
+ .init_rx_chan = emac3_dma_init_rx_chan,
+ .init_tx_chan = emac3_dma_init_tx_chan,
+ .axi = dwmac4_dma_axi,
+ .dump_regs = emac3_dump_dma_regs,
+ .dma_rx_mode = emac3_dma_rx_chan_op_mode,
+ .dma_tx_mode = emac3_dma_tx_chan_op_mode,
+ .enable_dma_irq = emac3_enable_dma_irq,
+ .disable_dma_irq = emac3_disable_dma_irq,
+ .start_tx = emac3_dma_start_tx,
+ .stop_tx = emac3_dma_stop_tx,
+ .start_rx = emac3_dma_start_rx,
+ .stop_rx = emac3_dma_stop_rx,
+ .dma_interrupt = emac3_dma_interrupt,
+ .get_hw_feature = dwmac4_get_hw_feature,
+ .rx_watchdog = emac3_rx_watchdog,
+ .set_rx_ring_len = emac3_set_rx_ring_len,
+ .set_tx_ring_len = emac3_set_tx_ring_len,
+ .set_rx_tail_ptr = emac3_set_rx_tail_ptr,
+ .set_tx_tail_ptr = emac3_set_tx_tail_ptr,
+ .enable_tso = emac3_enable_tso,
+ .qmode = emac3_qmode,
+ .set_bfsize = emac3_set_bfsize,
+ .enable_sph = emac3_enable_sph,
+ .enable_tbs = emac3_enable_tbs,
+};
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h
index 9321879b599c..c9899eefba6c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h
@@ -93,8 +93,11 @@
#define DMA_TBS_DEF_FTOS (DMA_TBS_FTOS | DMA_TBS_FTOV)
/* Following DMA defines are chanels oriented */
+#define EMAC3_DMA_CHAN_BASE_ADDR 0x00008100
+#define EMAC3_DMA_CHAN_BASE_OFFSET 0x1000
#define DMA_CHAN_BASE_ADDR 0x00001100
#define DMA_CHAN_BASE_OFFSET 0x80
+
#define DMA_CHANX_BASE_ADDR(x) (DMA_CHAN_BASE_ADDR + \
(x * DMA_CHAN_BASE_OFFSET))
#define DMA_CHAN_REG_NUMBER 17
@@ -119,6 +122,29 @@
#define DMA_CHAN_CUR_RX_BUF_ADDR(x) (DMA_CHANX_BASE_ADDR(x) + 0x5c)
#define DMA_CHAN_STATUS(x) (DMA_CHANX_BASE_ADDR(x) + 0x60)
+#define EMAC3_DMA_CHANX_BASE_ADDR(x) (EMAC3_DMA_CHAN_BASE_ADDR + \
+ ((x) * EMAC3_DMA_CHAN_BASE_OFFSET))
+
+#define EMAC3_DMA_CHAN_CONTROL(x) EMAC3_DMA_CHANX_BASE_ADDR(x)
+#define EMAC3_DMA_CHAN_TX_CONTROL(x) (EMAC3_DMA_CHANX_BASE_ADDR(x) + 0x4)
+#define EMAC3_DMA_CHAN_RX_CONTROL(x) (EMAC3_DMA_CHANX_BASE_ADDR(x) + 0x8)
+#define EMAC3_DMA_CHAN_TX_BASE_ADDR_HI(x) (EMAC3_DMA_CHANX_BASE_ADDR(x) + 0x10)
+#define EMAC3_DMA_CHAN_TX_BASE_ADDR(x) (EMAC3_DMA_CHANX_BASE_ADDR(x) + 0x14)
+#define EMAC3_DMA_CHAN_RX_BASE_ADDR_HI(x) (EMAC3_DMA_CHANX_BASE_ADDR(x) + 0x18)
+#define EMAC3_DMA_CHAN_RX_BASE_ADDR(x) (EMAC3_DMA_CHANX_BASE_ADDR(x) + 0x1c)
+#define EMAC3_DMA_CHAN_TX_END_ADDR(x) (EMAC3_DMA_CHANX_BASE_ADDR(x) + 0x20)
+#define EMAC3_DMA_CHAN_RX_END_ADDR(x) (EMAC3_DMA_CHANX_BASE_ADDR(x) + 0x28)
+#define EMAC3_DMA_CHAN_TX_RING_LEN(x) (EMAC3_DMA_CHANX_BASE_ADDR(x) + 0x2c)
+#define EMAC3_DMA_CHAN_RX_RING_LEN(x) (EMAC3_DMA_CHANX_BASE_ADDR(x) + 0x30)
+#define EMAC3_DMA_CHAN_INTR_ENA(x) (EMAC3_DMA_CHANX_BASE_ADDR(x) + 0x34)
+#define EMAC3_DMA_CHAN_RX_WATCHDOG(x) (EMAC3_DMA_CHANX_BASE_ADDR(x) + 0x38)
+#define EMAC3_DMA_CHAN_SLOT_CTRL_STATUS(x) (EMAC3_DMA_CHANX_BASE_ADDR(x) + 0x3c)
+#define EMAC3_DMA_CHAN_CUR_TX_DESC(x) (EMAC3_DMA_CHANX_BASE_ADDR(x) + 0x44)
+#define EMAC3_DMA_CHAN_CUR_RX_DESC(x) (EMAC3_DMA_CHANX_BASE_ADDR(x) + 0x4c)
+#define EMAC3_DMA_CHAN_CUR_TX_BUF_ADDR(x) (EMAC3_DMA_CHANX_BASE_ADDR(x) + 0x54)
+#define EMAC3_DMA_CHAN_CUR_RX_BUF_ADDR(x) (EMAC3_DMA_CHANX_BASE_ADDR(x) + 0x5c)
+#define EMAC3_DMA_CHAN_STATUS(x) (EMAC3_DMA_CHANX_BASE_ADDR(x) + 0x60)
+
/* DMA Control X */
#define DMA_CONTROL_SPH BIT(24)
#define DMA_CONTROL_MSS_MASK GENMASK(13, 0)
@@ -220,19 +246,31 @@
#define DMA_CHAN0_DBG_STAT_RPS_SHIFT 8
int dwmac4_dma_reset(void __iomem *ioaddr);
+void emac3_enable_dma_irq(void __iomem *ioaddr, u32 chan, bool rx, bool tx);
void dwmac4_enable_dma_irq(void __iomem *ioaddr, u32 chan, bool rx, bool tx);
void dwmac410_enable_dma_irq(void __iomem *ioaddr, u32 chan, bool rx, bool tx);
+void emac3_disable_dma_irq(void __iomem *ioaddr, u32 chan, bool rx, bool tx);
void dwmac4_disable_dma_irq(void __iomem *ioaddr, u32 chan, bool rx, bool tx);
void dwmac410_disable_dma_irq(void __iomem *ioaddr, u32 chan, bool rx, bool tx);
+void emac3_dma_start_tx(void __iomem *ioaddr, u32 chan);
void dwmac4_dma_start_tx(void __iomem *ioaddr, u32 chan);
+void emac3_dma_stop_tx(void __iomem *ioaddr, u32 chan);
void dwmac4_dma_stop_tx(void __iomem *ioaddr, u32 chan);
+void emac3_dma_start_rx(void __iomem *ioaddr, u32 chan);
void dwmac4_dma_start_rx(void __iomem *ioaddr, u32 chan);
+void emac3_dma_stop_rx(void __iomem *ioaddr, u32 chan);
void dwmac4_dma_stop_rx(void __iomem *ioaddr, u32 chan);
+int emac3_dma_interrupt(void __iomem *ioaddr, struct stmmac_extra_stats *x,
+ u32 chan, u32 dir);
int dwmac4_dma_interrupt(void __iomem *ioaddr,
struct stmmac_extra_stats *x, u32 chan, u32 dir);
+void emac3_set_rx_ring_len(void __iomem *ioaddr, u32 len, u32 chan);
void dwmac4_set_rx_ring_len(void __iomem *ioaddr, u32 len, u32 chan);
+void emac3_set_tx_ring_len(void __iomem *ioaddr, u32 len, u32 chan);
void dwmac4_set_tx_ring_len(void __iomem *ioaddr, u32 len, u32 chan);
+void emac3_set_rx_tail_ptr(void __iomem *ioaddr, u32 tail_ptr, u32 chan);
void dwmac4_set_rx_tail_ptr(void __iomem *ioaddr, u32 tail_ptr, u32 chan);
+void emac3_set_tx_tail_ptr(void __iomem *ioaddr, u32 tail_ptr, u32 chan);
void dwmac4_set_tx_tail_ptr(void __iomem *ioaddr, u32 tail_ptr, u32 chan);
#endif /* __DWMAC4_DMA_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
index d1c605777985..3cbcc595bdfc 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
@@ -25,55 +25,110 @@ int dwmac4_dma_reset(void __iomem *ioaddr)
10000, 1000000);
}
+void emac3_set_rx_tail_ptr(void __iomem *ioaddr, u32 tail_ptr, u32 chan)
+{
+ writel(tail_ptr, ioaddr + EMAC3_DMA_CHAN_RX_END_ADDR(chan));
+}
+
void dwmac4_set_rx_tail_ptr(void __iomem *ioaddr, u32 tail_ptr, u32 chan)
{
writel(tail_ptr, ioaddr + DMA_CHAN_RX_END_ADDR(chan));
}
+void emac3_set_tx_tail_ptr(void __iomem *ioaddr, u32 tail_ptr, u32 chan)
+{
+ writel(tail_ptr, ioaddr + EMAC3_DMA_CHAN_TX_END_ADDR(chan));
+}
+
void dwmac4_set_tx_tail_ptr(void __iomem *ioaddr, u32 tail_ptr, u32 chan)
{
writel(tail_ptr, ioaddr + DMA_CHAN_TX_END_ADDR(chan));
}
-void dwmac4_dma_start_tx(void __iomem *ioaddr, u32 chan)
+static void do_dma_start_tx(void __iomem *ioaddr, u32 addr_offset)
{
- u32 value = readl(ioaddr + DMA_CHAN_TX_CONTROL(chan));
+ u32 value = readl(ioaddr + addr_offset);
value |= DMA_CONTROL_ST;
- writel(value, ioaddr + DMA_CHAN_TX_CONTROL(chan));
+ writel(value, ioaddr + addr_offset);
value = readl(ioaddr + GMAC_CONFIG);
value |= GMAC_CONFIG_TE;
writel(value, ioaddr + GMAC_CONFIG);
}
-void dwmac4_dma_stop_tx(void __iomem *ioaddr, u32 chan)
+void emac3_dma_start_tx(void __iomem *ioaddr, u32 chan)
+{
+ do_dma_start_tx(ioaddr, EMAC3_DMA_CHAN_TX_CONTROL(chan));
+}
+
+void dwmac4_dma_start_tx(void __iomem *ioaddr, u32 chan)
{
- u32 value = readl(ioaddr + DMA_CHAN_TX_CONTROL(chan));
+ do_dma_start_tx(ioaddr, DMA_CHAN_TX_CONTROL(chan));
+}
+
+static void do_dma_stop_tx(void __iomem *ioaddr, u32 addr_offset)
+{
+ u32 value = readl(ioaddr + addr_offset);
value &= ~DMA_CONTROL_ST;
- writel(value, ioaddr + DMA_CHAN_TX_CONTROL(chan));
+ writel(value, ioaddr + addr_offset);
}
-void dwmac4_dma_start_rx(void __iomem *ioaddr, u32 chan)
+void emac3_dma_stop_tx(void __iomem *ioaddr, u32 chan)
{
- u32 value = readl(ioaddr + DMA_CHAN_RX_CONTROL(chan));
+ do_dma_stop_tx(ioaddr, EMAC3_DMA_CHAN_TX_CONTROL(chan));
+}
+
+void dwmac4_dma_stop_tx(void __iomem *ioaddr, u32 chan)
+{
+ do_dma_stop_tx(ioaddr, DMA_CHAN_TX_CONTROL(chan));
+}
+
+static void do_dma_start_rx(void __iomem *ioaddr, u32 addr_offset)
+{
+ u32 value = readl(ioaddr + addr_offset);
value |= DMA_CONTROL_SR;
- writel(value, ioaddr + DMA_CHAN_RX_CONTROL(chan));
+ writel(value, ioaddr + addr_offset);
value = readl(ioaddr + GMAC_CONFIG);
value |= GMAC_CONFIG_RE;
writel(value, ioaddr + GMAC_CONFIG);
}
-void dwmac4_dma_stop_rx(void __iomem *ioaddr, u32 chan)
+void emac3_dma_start_rx(void __iomem *ioaddr, u32 chan)
{
- u32 value = readl(ioaddr + DMA_CHAN_RX_CONTROL(chan));
+ do_dma_start_rx(ioaddr, EMAC3_DMA_CHAN_RX_CONTROL(chan));
+}
+
+void dwmac4_dma_start_rx(void __iomem *ioaddr, u32 chan)
+{
+ do_dma_start_rx(ioaddr, DMA_CHAN_RX_CONTROL(chan));
+}
+
+static void do_dma_stop_rx(void __iomem *ioaddr, u32 addr_offset)
+{
+ u32 value = readl(ioaddr + addr_offset);
value &= ~DMA_CONTROL_SR;
- writel(value, ioaddr + DMA_CHAN_RX_CONTROL(chan));
+ writel(value, ioaddr + addr_offset);
+}
+
+void emac3_dma_stop_rx(void __iomem *ioaddr, u32 chan)
+{
+ do_dma_stop_rx(ioaddr, EMAC3_DMA_CHAN_RX_CONTROL(chan));
+}
+
+void dwmac4_dma_stop_rx(void __iomem *ioaddr, u32 chan)
+{
+ do_dma_stop_rx(ioaddr, DMA_CHAN_RX_CONTROL(chan));
+}
+
+void emac3_set_tx_ring_len(void __iomem *ioaddr, u32 len, u32 chan)
+{
+ writel(len, ioaddr + EMAC3_DMA_CHAN_TX_RING_LEN(chan));
}
void dwmac4_set_tx_ring_len(void __iomem *ioaddr, u32 len, u32 chan)
@@ -81,6 +136,11 @@ void dwmac4_set_tx_ring_len(void __iomem *ioaddr, u32 len, u32 chan)
writel(len, ioaddr + DMA_CHAN_TX_RING_LEN(chan));
}
+void emac3_set_rx_ring_len(void __iomem *ioaddr, u32 len, u32 chan)
+{
+ writel(len, ioaddr + EMAC3_DMA_CHAN_RX_RING_LEN(chan));
+}
+
void dwmac4_set_rx_ring_len(void __iomem *ioaddr, u32 len, u32 chan)
{
writel(len, ioaddr + DMA_CHAN_RX_RING_LEN(chan));
@@ -98,16 +158,27 @@ void dwmac4_enable_dma_irq(void __iomem *ioaddr, u32 chan, bool rx, bool tx)
writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan));
}
-void dwmac410_enable_dma_irq(void __iomem *ioaddr, u32 chan, bool rx, bool tx)
+static void do_enable_dma_irq(void __iomem *ioaddr, bool rx, bool tx,
+ u32 addr_offset)
{
- u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
+ u32 value = readl(ioaddr + addr_offset);
if (rx)
value |= DMA_CHAN_INTR_DEFAULT_RX_4_10;
if (tx)
value |= DMA_CHAN_INTR_DEFAULT_TX_4_10;
- writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan));
+ writel(value, ioaddr + addr_offset);
+}
+
+void emac3_enable_dma_irq(void __iomem *ioaddr, u32 chan, bool rx, bool tx)
+{
+ do_enable_dma_irq(ioaddr, rx, tx, EMAC3_DMA_CHAN_INTR_ENA(chan));
+}
+
+void dwmac410_enable_dma_irq(void __iomem *ioaddr, u32 chan, bool rx, bool tx)
+{
+ do_enable_dma_irq(ioaddr, rx, tx, DMA_CHAN_INTR_ENA(chan));
}
void dwmac4_disable_dma_irq(void __iomem *ioaddr, u32 chan, bool rx, bool tx)
@@ -122,23 +193,35 @@ void dwmac4_disable_dma_irq(void __iomem *ioaddr, u32 chan, bool rx, bool tx)
writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan));
}
-void dwmac410_disable_dma_irq(void __iomem *ioaddr, u32 chan, bool rx, bool tx)
+static void do_disable_dma_irq(void __iomem *ioaddr, bool rx, bool tx,
+ u32 addr_offset)
{
- u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
+ u32 value = readl(ioaddr + addr_offset);
if (rx)
value &= ~DMA_CHAN_INTR_DEFAULT_RX_4_10;
if (tx)
value &= ~DMA_CHAN_INTR_DEFAULT_TX_4_10;
- writel(value, ioaddr + DMA_CHAN_INTR_ENA(chan));
+ writel(value, ioaddr + addr_offset);
}
-int dwmac4_dma_interrupt(void __iomem *ioaddr,
- struct stmmac_extra_stats *x, u32 chan, u32 dir)
+void emac3_disable_dma_irq(void __iomem *ioaddr, u32 chan, bool rx, bool tx)
{
- u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan));
- u32 intr_en = readl(ioaddr + DMA_CHAN_INTR_ENA(chan));
+ do_disable_dma_irq(ioaddr, rx, tx, EMAC3_DMA_CHAN_INTR_ENA(chan));
+}
+
+void dwmac410_disable_dma_irq(void __iomem *ioaddr, u32 chan, bool rx, bool tx)
+{
+ do_disable_dma_irq(ioaddr, rx, tx, DMA_CHAN_INTR_ENA(chan));
+}
+
+static int do_dma_interrupt(void __iomem *ioaddr, struct stmmac_extra_stats *x,
+ u32 chan, u32 dir, u32 addr_offset,
+ u32 intr_addr_offset)
+{
+ u32 intr_status = readl(ioaddr + addr_offset);
+ u32 intr_en = readl(ioaddr + intr_addr_offset);
int ret = 0;
if (dir == DMA_DIR_RX)
@@ -183,10 +266,25 @@ int dwmac4_dma_interrupt(void __iomem *ioaddr,
if (unlikely(intr_status & DMA_CHAN_STATUS_ERI))
x->rx_early_irq++;
- writel(intr_status & intr_en, ioaddr + DMA_CHAN_STATUS(chan));
+ writel(intr_status & intr_en, ioaddr + addr_offset);
return ret;
}
+int emac3_dma_interrupt(void __iomem *ioaddr, struct stmmac_extra_stats *x,
+ u32 chan, u32 dir)
+{
+ return do_dma_interrupt(ioaddr, x, chan, dir,
+ EMAC3_DMA_CHAN_STATUS(chan),
+ EMAC3_DMA_CHAN_INTR_ENA(chan));
+}
+
+int dwmac4_dma_interrupt(void __iomem *ioaddr, struct stmmac_extra_stats *x,
+ u32 chan, u32 dir)
+{
+ return do_dma_interrupt(ioaddr, x, chan, dir, DMA_CHAN_STATUS(chan),
+ DMA_CHAN_INTR_ENA(chan));
+}
+
void stmmac_dwmac4_set_mac_addr(void __iomem *ioaddr, const u8 addr[6],
unsigned int high, unsigned int low)
{
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
index bb7114f970f8..7d8aa5e316cf 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
@@ -91,6 +91,7 @@ static const struct stmmac_hwif_entry {
bool gmac;
bool gmac4;
bool xgmac;
+ bool emac3;
u32 min_id;
u32 dev_id;
const struct stmmac_regs_off regs;
@@ -251,6 +252,25 @@ static const struct stmmac_hwif_entry {
.mmc = &dwxgmac_mmc_ops,
.setup = dwxlgmac2_setup,
.quirks = stmmac_dwxlgmac_quirks,
+ }, {
+ .gmac = false,
+ .gmac4 = false,
+ .xgmac = false,
+ .emac3 = true,
+ .min_id = DWMAC_CORE_5_10,
+ .regs = {
+ .ptp_off = PTP_GMAC4_OFFSET,
+ .mmc_off = MMC_GMAC4_OFFSET,
+ },
+ .desc = &dwmac4_desc_ops,
+ .dma = &emac3_dma_ops,
+ .mac = &emac3_ops,
+ .hwtimestamp = &stmmac_ptp,
+ .mode = &dwmac4_ring_mode_ops,
+ .tc = &dwmac510_tc_ops,
+ .mmc = &dwmac_mmc_ops,
+ .setup = dwmac4_setup,
+ .quirks = NULL,
},
};
@@ -259,6 +279,7 @@ int stmmac_hwif_init(struct stmmac_priv *priv)
bool needs_xgmac = priv->plat->has_xgmac;
bool needs_gmac4 = priv->plat->has_gmac4;
bool needs_gmac = priv->plat->has_gmac;
+ bool needs_emac3 = priv->plat->has_emac3;
const struct stmmac_hwif_entry *entry;
struct mac_device_info *mac;
bool needs_setup = true;
@@ -267,7 +288,7 @@ int stmmac_hwif_init(struct stmmac_priv *priv)
if (needs_gmac) {
id = stmmac_get_id(priv, GMAC_VERSION);
- } else if (needs_gmac4 || needs_xgmac) {
+ } else if (needs_gmac4 || needs_xgmac || needs_emac3) {
id = stmmac_get_id(priv, GMAC4_VERSION);
if (needs_xgmac)
dev_id = stmmac_get_dev_id(priv, GMAC4_VERSION);
@@ -280,9 +301,9 @@ int stmmac_hwif_init(struct stmmac_priv *priv)
/* Lets assume some safe values first */
priv->ptpaddr = priv->ioaddr +
- (needs_gmac4 ? PTP_GMAC4_OFFSET : PTP_GMAC3_X_OFFSET);
+ ((needs_gmac4 || needs_emac3) ? PTP_GMAC4_OFFSET : PTP_GMAC3_X_OFFSET);
priv->mmcaddr = priv->ioaddr +
- (needs_gmac4 ? MMC_GMAC4_OFFSET : MMC_GMAC3_X_OFFSET);
+ ((needs_gmac4 || needs_emac3) ? MMC_GMAC4_OFFSET : MMC_GMAC3_X_OFFSET);
/* Check for HW specific setup first */
if (priv->plat->setup) {
@@ -305,6 +326,8 @@ int stmmac_hwif_init(struct stmmac_priv *priv)
continue;
if (needs_xgmac ^ entry->xgmac)
continue;
+ if (needs_emac3 ^ entry->emac3)
+ continue;
/* Use synopsys_id var because some setups can override this */
if (priv->synopsys_id < entry->min_id)
continue;
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
index 16a7421715cb..44d77ced27cc 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -620,6 +620,8 @@ struct stmmac_regs_off {
u32 mmc_off;
};
+extern const struct stmmac_ops emac3_ops;
+extern const struct stmmac_dma_ops emac3_dma_ops;
extern const struct stmmac_ops dwmac100_ops;
extern const struct stmmac_dma_ops dwmac100_dma_ops;
extern const struct stmmac_ops dwmac1000_ops;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index 35c8dd92d369..0f62e5f85b60 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -286,7 +286,7 @@ static void stmmac_ethtool_getdrvinfo(struct net_device *dev,
{
struct stmmac_priv *priv = netdev_priv(dev);
- if (priv->plat->has_gmac || priv->plat->has_gmac4)
+ if (priv->plat->has_gmac || priv->plat->has_gmac4 || priv->plat->has_emac3)
strscpy(info->driver, GMAC_ETHTOOL_NAME, sizeof(info->driver));
else if (priv->plat->has_xgmac)
strscpy(info->driver, XGMAC_ETHTOOL_NAME, sizeof(info->driver));
@@ -442,7 +442,7 @@ static int stmmac_ethtool_get_regs_len(struct net_device *dev)
if (priv->plat->has_xgmac)
return XGMAC_REGSIZE * 4;
- else if (priv->plat->has_gmac4)
+ else if (priv->plat->has_gmac4 || priv->plat->has_emac3)
return GMAC4_REG_SPACE_SIZE;
return REG_SPACE_SIZE;
}
@@ -457,7 +457,7 @@ static void stmmac_ethtool_gregs(struct net_device *dev,
stmmac_dump_dma_regs(priv, priv->ioaddr, reg_space);
/* Copy DMA registers to where ethtool expects them */
- if (priv->plat->has_gmac4) {
+ if (priv->plat->has_gmac4 || priv->plat->has_emac3) {
/* GMAC4 dumps its DMA registers at its DMA_CHAN_BASE_ADDR */
memcpy(®_space[ETHTOOL_DMA_OFFSET],
®_space[GMAC4_DMA_CHAN_BASE_ADDR / 4],
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 8f543c3ab5c5..d086fe811b67 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -509,7 +509,8 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
true);
}
- if (priv->plat->has_gmac4 && priv->tx_lpi_timer <= STMMAC_ET_MAX) {
+ if ((priv->plat->has_gmac4 || priv->plat->has_emac3) &&
+ priv->tx_lpi_timer <= STMMAC_ET_MAX) {
del_timer_sync(&priv->eee_ctrl_timer);
priv->tx_path_in_lpi_mode = false;
stmmac_lpi_entry_timer_config(priv, 1);
@@ -585,7 +586,7 @@ static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p,
if (!priv->hwts_rx_en)
return;
/* For GMAC4, the valid timestamp is from CTX next desc. */
- if (priv->plat->has_gmac4 || priv->plat->has_xgmac)
+ if (priv->plat->has_gmac4 || priv->plat->has_emac3 || priv->plat->has_xgmac)
desc = np;
/* Check if timestamp is available */
@@ -833,7 +834,7 @@ static int stmmac_hwtstamp_get(struct net_device *dev, struct ifreq *ifr)
*/
int stmmac_init_tstamp_counter(struct stmmac_priv *priv, u32 systime_flags)
{
- bool xmac = priv->plat->has_gmac4 || priv->plat->has_xgmac;
+ bool xmac = priv->plat->has_gmac4 || priv->plat->has_emac3 || priv->plat->has_xgmac;
struct timespec64 now;
u32 sec_inc = 0;
u64 temp = 0;
@@ -881,7 +882,7 @@ EXPORT_SYMBOL_GPL(stmmac_init_tstamp_counter);
*/
static int stmmac_init_ptp(struct stmmac_priv *priv)
{
- bool xmac = priv->plat->has_gmac4 || priv->plat->has_xgmac;
+ bool xmac = priv->plat->has_gmac4 || priv->plat->has_emac3 || priv->plat->has_xgmac;
int ret;
if (priv->plat->ptp_clk_freq_config)
@@ -1207,7 +1208,7 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
if (!max_speed || max_speed >= 1000)
priv->phylink_config.mac_capabilities |= MAC_1000;
- if (priv->plat->has_gmac4) {
+ if (priv->plat->has_gmac4 || priv->plat->has_emac3) {
if (!max_speed || max_speed >= 2500)
priv->phylink_config.mac_capabilities |= MAC_2500FD;
} else if (priv->plat->has_xgmac) {
@@ -4343,7 +4344,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
if (skb_is_gso(skb) && priv->tso) {
if (gso & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))
return stmmac_tso_xmit(skb, dev);
- if (priv->plat->has_gmac4 && (gso & SKB_GSO_UDP_L4))
+ if ((priv->plat->has_gmac4 || priv->plat->has_emac3) && (gso & SKB_GSO_UDP_L4))
return stmmac_tso_xmit(skb, dev);
}
@@ -5721,7 +5722,7 @@ static void stmmac_common_interrupt(struct stmmac_priv *priv)
u32 queue;
bool xmac;
- xmac = priv->plat->has_gmac4 || priv->plat->has_xgmac;
+ xmac = priv->plat->has_gmac4 || priv->plat->has_emac3 || priv->plat->has_xgmac;
queues_count = (rx_cnt > tx_cnt) ? rx_cnt : tx_cnt;
if (priv->irq_wake)
@@ -7165,7 +7166,7 @@ int stmmac_dvr_probe(struct device *device,
if ((priv->plat->tso_en) && (priv->dma_cap.tsoen)) {
ndev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6;
- if (priv->plat->has_gmac4)
+ if (priv->plat->has_gmac4 || priv->plat->has_emac3)
ndev->hw_features |= NETIF_F_GSO_UDP_L4;
priv->tso = true;
dev_info(priv->device, "TSO feature enabled\n");
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
index 21aaa2730ac8..9e3d8e1202bd 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
@@ -281,9 +281,8 @@ static int stmmac_mdio_read_c22(struct mii_bus *bus, int phyaddr, int phyreg)
value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask;
value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift)
& priv->hw->mii.clk_csr_mask;
- if (priv->plat->has_gmac4) {
+ if (priv->plat->has_gmac4 || priv->plat->has_emac3)
value |= MII_GMAC4_READ;
- }
data = stmmac_mdio_read(priv, data, value);
@@ -382,7 +381,7 @@ static int stmmac_mdio_write_c22(struct mii_bus *bus, int phyaddr, int phyreg,
value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift)
& priv->hw->mii.clk_csr_mask;
- if (priv->plat->has_gmac4)
+ if (priv->plat->has_gmac4 || priv->plat->has_emac3)
value |= MII_GMAC4_WRITE;
else
value |= MII_WRITE;
@@ -483,7 +482,7 @@ int stmmac_mdio_reset(struct mii_bus *bus)
* on MDC, so perform a dummy mdio read. To be updated for GMAC4
* if needed.
*/
- if (!priv->plat->has_gmac4)
+ if (!priv->plat->has_gmac4 && !priv->plat->has_emac3)
writel(0, priv->ioaddr + mii_address);
#endif
return 0;
@@ -569,7 +568,7 @@ int stmmac_mdio_register(struct net_device *ndev)
} else {
new_bus->read = &stmmac_mdio_read_c22;
new_bus->write = &stmmac_mdio_write_c22;
- if (priv->plat->has_gmac4) {
+ if (priv->plat->has_gmac4 || priv->plat->has_emac3) {
new_bus->read_c45 = &stmmac_mdio_read_c45;
new_bus->write_c45 = &stmmac_mdio_write_c45;
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
index b4388ca8d211..9a8f9630d6af 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
@@ -56,7 +56,7 @@ static int stmmac_adjust_time(struct ptp_clock_info *ptp, s64 delta)
bool xmac, est_rst = false;
int ret;
- xmac = priv->plat->has_gmac4 || priv->plat->has_xgmac;
+ xmac = priv->plat->has_gmac4 || priv->plat->has_emac3 || priv->plat->has_xgmac;
if (delta < 0) {
neg_adj = 1;
@@ -292,7 +292,7 @@ void stmmac_ptp_register(struct stmmac_priv *priv)
/* Calculate the clock domain crossing (CDC) error if necessary */
priv->plat->cdc_error_adj = 0;
- if (priv->plat->has_gmac4 && priv->plat->clk_ptp_rate)
+ if ((priv->plat->has_gmac4 || priv->plat->has_emac3) && priv->plat->clk_ptp_rate)
priv->plat->cdc_error_adj = (2 * NSEC_PER_SEC) / priv->plat->clk_ptp_rate;
stmmac_ptp_clock_ops.n_per_out = priv->dma_cap.pps_out_num;
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index a152678b82b7..de2d0a8693c8 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -248,6 +248,7 @@ struct plat_stmmacenet_data {
struct stmmac_axi *axi;
int has_gmac4;
bool has_sun8i;
+ bool has_emac3;
bool tso_en;
int rss_en;
int mac_port_sel_speed;
--
2.39.2
Add the new programming sequence needed for EMAC3 based platforms such
as the sc8280xp family.
Signed-off-by: Andrew Halaney <[email protected]>
---
.../stmicro/stmmac/dwmac-qcom-ethqos.c | 106 ++++++++++++++----
1 file changed, 84 insertions(+), 22 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
index 778852934e36..2b22469c59cf 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
@@ -11,6 +11,7 @@
#define RGMII_IO_MACRO_CONFIG 0x0
#define SDCC_HC_REG_DLL_CONFIG 0x4
+#define SDCC_TEST_CTL 0x8
#define SDCC_HC_REG_DDR_CONFIG 0xC
#define SDCC_HC_REG_DLL_CONFIG2 0x10
#define SDC4_STATUS 0x14
@@ -49,6 +50,7 @@
#define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY GENMASK(26, 21)
#define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE GENMASK(29, 27)
#define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN BIT(30)
+#define SDCC_DDR_CONFIG_TCXO_CYCLES_CNT GENMASK(11, 9)
#define SDCC_DDR_CONFIG_PRG_RCLK_DLY GENMASK(8, 0)
/* SDCC_HC_REG_DLL_CONFIG2 fields */
@@ -79,6 +81,7 @@ struct ethqos_emac_driver_data {
const struct ethqos_emac_por *por;
unsigned int num_por;
bool rgmii_config_loopback_en;
+ bool has_emac3;
};
struct qcom_ethqos {
@@ -92,6 +95,7 @@ struct qcom_ethqos {
const struct ethqos_emac_por *por;
unsigned int num_por;
bool rgmii_config_loopback_en;
+ bool has_emac3;
};
static int rgmii_readl(struct qcom_ethqos *ethqos, unsigned int offset)
@@ -184,6 +188,7 @@ static const struct ethqos_emac_driver_data emac_v2_3_0_data = {
.por = emac_v2_3_0_por,
.num_por = ARRAY_SIZE(emac_v2_3_0_por),
.rgmii_config_loopback_en = true,
+ .has_emac3 = false,
};
static const struct ethqos_emac_por emac_v2_1_0_por[] = {
@@ -199,6 +204,23 @@ static const struct ethqos_emac_driver_data emac_v2_1_0_data = {
.por = emac_v2_1_0_por,
.num_por = ARRAY_SIZE(emac_v2_1_0_por),
.rgmii_config_loopback_en = false,
+ .has_emac3 = false,
+};
+
+static const struct ethqos_emac_por emac_v3_0_0_por[] = {
+ { .offset = RGMII_IO_MACRO_CONFIG, .value = 0x40c01343 },
+ { .offset = SDCC_HC_REG_DLL_CONFIG, .value = 0x2004642c },
+ { .offset = SDCC_HC_REG_DDR_CONFIG, .value = 0x80040800 },
+ { .offset = SDCC_HC_REG_DLL_CONFIG2, .value = 0x00200000 },
+ { .offset = SDCC_USR_CTL, .value = 0x00010800 },
+ { .offset = RGMII_IO_MACRO_CONFIG2, .value = 0x00002060 },
+};
+
+static const struct ethqos_emac_driver_data emac_v3_0_0_data = {
+ .por = emac_v3_0_0_por,
+ .num_por = ARRAY_SIZE(emac_v3_0_0_por),
+ .rgmii_config_loopback_en = false,
+ .has_emac3 = true,
};
static int ethqos_dll_configure(struct qcom_ethqos *ethqos)
@@ -222,11 +244,13 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos)
rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_EN,
SDCC_DLL_CONFIG_DLL_EN, SDCC_HC_REG_DLL_CONFIG);
- rgmii_updatel(ethqos, SDCC_DLL_MCLK_GATING_EN,
- 0, SDCC_HC_REG_DLL_CONFIG);
+ if (!ethqos->has_emac3) {
+ rgmii_updatel(ethqos, SDCC_DLL_MCLK_GATING_EN,
+ 0, SDCC_HC_REG_DLL_CONFIG);
- rgmii_updatel(ethqos, SDCC_DLL_CDR_FINE_PHASE,
- 0, SDCC_HC_REG_DLL_CONFIG);
+ rgmii_updatel(ethqos, SDCC_DLL_CDR_FINE_PHASE,
+ 0, SDCC_HC_REG_DLL_CONFIG);
+ }
/* Wait for CK_OUT_EN clear */
do {
@@ -261,18 +285,20 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos)
rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_CAL_EN,
SDCC_DLL_CONFIG2_DDR_CAL_EN, SDCC_HC_REG_DLL_CONFIG2);
- rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DLL_CLOCK_DIS,
- 0, SDCC_HC_REG_DLL_CONFIG2);
+ if (!ethqos->has_emac3) {
+ rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DLL_CLOCK_DIS,
+ 0, SDCC_HC_REG_DLL_CONFIG2);
- rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_MCLK_FREQ_CALC,
- 0x1A << 10, SDCC_HC_REG_DLL_CONFIG2);
+ rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_MCLK_FREQ_CALC,
+ 0x1A << 10, SDCC_HC_REG_DLL_CONFIG2);
- rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SEL,
- BIT(2), SDCC_HC_REG_DLL_CONFIG2);
+ rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SEL,
+ BIT(2), SDCC_HC_REG_DLL_CONFIG2);
- rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW,
- SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW,
- SDCC_HC_REG_DLL_CONFIG2);
+ rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW,
+ SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW,
+ SDCC_HC_REG_DLL_CONFIG2);
+ }
return 0;
}
@@ -326,9 +352,17 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
RGMII_CONFIG2_RX_PROG_SWAP,
RGMII_IO_MACRO_CONFIG2);
- /* Set PRG_RCLK_DLY to 57 for 1.8 ns delay */
- rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY,
- 57, SDCC_HC_REG_DDR_CONFIG);
+ /* PRG_RCLK_DLY = TCXO period * TCXO_CYCLES_CNT / 2 * RX delay ns,
+ * in practice this becomes PRG_RCLK_DLY = 52 * 4 / 2 * RX delay ns
+ */
+ if (ethqos->has_emac3)
+ /* 0.9 ns */
+ rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY,
+ 115, SDCC_HC_REG_DDR_CONFIG);
+ else
+ /* 1.8 ns */
+ rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY,
+ 57, SDCC_HC_REG_DDR_CONFIG);
rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_DLY_EN,
SDCC_DDR_CONFIG_PRG_DLY_EN,
SDCC_HC_REG_DDR_CONFIG);
@@ -354,8 +388,15 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
BIT(6), RGMII_IO_MACRO_CONFIG);
rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15,
0, RGMII_IO_MACRO_CONFIG2);
- rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
- 0, RGMII_IO_MACRO_CONFIG2);
+
+ if (ethqos->has_emac3)
+ rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
+ RGMII_CONFIG2_RX_PROG_SWAP,
+ RGMII_IO_MACRO_CONFIG2);
+ else
+ rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
+ 0, RGMII_IO_MACRO_CONFIG2);
+
/* Write 0x5 to PRG_RCLK_DLY_CODE */
rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE,
(BIT(29) | BIT(27)), SDCC_HC_REG_DDR_CONFIG);
@@ -388,8 +429,13 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
RGMII_IO_MACRO_CONFIG);
rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15,
0, RGMII_IO_MACRO_CONFIG2);
- rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
- 0, RGMII_IO_MACRO_CONFIG2);
+ if (ethqos->has_emac3)
+ rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
+ RGMII_CONFIG2_RX_PROG_SWAP,
+ RGMII_IO_MACRO_CONFIG2);
+ else
+ rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
+ 0, RGMII_IO_MACRO_CONFIG2);
/* Write 0x5 to PRG_RCLK_DLY_CODE */
rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE,
(BIT(29) | BIT(27)), SDCC_HC_REG_DDR_CONFIG);
@@ -432,6 +478,17 @@ static int ethqos_configure(struct qcom_ethqos *ethqos)
rgmii_updatel(ethqos, SDCC_DLL_CONFIG_PDN,
SDCC_DLL_CONFIG_PDN, SDCC_HC_REG_DLL_CONFIG);
+ if (ethqos->has_emac3) {
+ if (ethqos->speed == SPEED_1000) {
+ rgmii_writel(ethqos, 0x1800000, SDCC_TEST_CTL);
+ rgmii_writel(ethqos, 0x2C010800, SDCC_USR_CTL);
+ rgmii_writel(ethqos, 0xA001, SDCC_HC_REG_DLL_CONFIG2);
+ } else {
+ rgmii_writel(ethqos, 0x40010800, SDCC_USR_CTL);
+ rgmii_writel(ethqos, 0xA001, SDCC_HC_REG_DLL_CONFIG2);
+ }
+ }
+
/* Clear DLL_RST */
rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_RST, 0,
SDCC_HC_REG_DLL_CONFIG);
@@ -451,7 +508,9 @@ static int ethqos_configure(struct qcom_ethqos *ethqos)
SDCC_HC_REG_DLL_CONFIG);
/* Set USR_CTL bit 26 with mask of 3 bits */
- rgmii_updatel(ethqos, GENMASK(26, 24), BIT(26), SDCC_USR_CTL);
+ if (!ethqos->has_emac3)
+ rgmii_updatel(ethqos, GENMASK(26, 24), BIT(26),
+ SDCC_USR_CTL);
/* wait for DLL LOCK */
do {
@@ -546,6 +605,7 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
ethqos->por = data->por;
ethqos->num_por = data->num_por;
ethqos->rgmii_config_loopback_en = data->rgmii_config_loopback_en;
+ ethqos->has_emac3 = data->has_emac3;
ethqos->rgmii_clk = devm_clk_get(&pdev->dev, "rgmii");
if (IS_ERR(ethqos->rgmii_clk)) {
@@ -564,7 +624,8 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
plat_dat->bsp_priv = ethqos;
plat_dat->fix_mac_speed = ethqos_fix_mac_speed;
plat_dat->dump_debug_regs = rgmii_dump;
- plat_dat->has_gmac4 = 1;
+ plat_dat->has_gmac4 = !data->has_emac3;
+ plat_dat->has_emac3 = data->has_emac3;
plat_dat->pmt = 1;
plat_dat->tso_en = of_property_read_bool(np, "snps,tso");
if (of_device_is_compatible(np, "qcom,qcs404-ethqos"))
@@ -603,6 +664,7 @@ static int qcom_ethqos_remove(struct platform_device *pdev)
static const struct of_device_id qcom_ethqos_match[] = {
{ .compatible = "qcom,qcs404-ethqos", .data = &emac_v2_3_0_data},
{ .compatible = "qcom,sm8150-ethqos", .data = &emac_v2_1_0_data},
+ { .compatible = "qcom,sc8280xp-ethqos", &emac_v3_0_0_data},
{ }
};
MODULE_DEVICE_TABLE(of, qcom_ethqos_match);
--
2.39.2
From: Bhupesh Sharma <[email protected]>
As commit fc191af1bb0d ("net: stmmac: platform: Fix misleading
interrupt error msg") noted, not every stmmac based platform
makes use of the 'eth_wake_irq' or 'eth_lpi' interrupts.
So, update the 'interrupt-names' inside 'snps,dwmac' YAML
bindings to reflect the same.
Acked-by: Krzysztof Kozlowski <[email protected]>
Signed-off-by: Bhupesh Sharma <[email protected]>
Signed-off-by: Andrew Halaney <[email protected]>
---
I picked this up from:
https://lore.kernel.org/netdev/[email protected]/
No changes other than collecting the Acked-by.
Documentation/devicetree/bindings/net/snps,dwmac.yaml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
index 16b7d2904696..52ce14a4bea7 100644
--- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml
+++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
@@ -105,8 +105,8 @@ properties:
minItems: 1
items:
- const: macirq
- - const: eth_wake_irq
- - const: eth_lpi
+ - enum: [eth_wake_irq, eth_lpi]
+ - enum: [eth_wake_irq, eth_lpi]
clocks:
minItems: 1
--
2.39.2
Quoting Andrew Halaney (2023-03-13 09:56:14)
> Add the EMAC GDSCs to allow the EMAC hardware to be enabled.
>
> Signed-off-by: Andrew Halaney <[email protected]>
> ---
Acked-by: Stephen Boyd <[email protected]>
I'm not sure if Bjorn Andersson is planning on modifying this file too,
so please confirm it can go through netdev tree.
On Mon, 13 Mar 2023 11:56:17 -0500 Andrew Halaney wrote:
> EMAC3 is a Qualcomm variant of dwmac4 that functions the same, but has a
> different address space layout for MTL and DMA registers. This makes the
> patch a bit more complicated than we would like so let's explain why the
> current approach was used.
Please drop all the static inlines in C sources, you're wrapping
a single function call, the compiler will do the right thing.
Please no more than 6 function arguments.
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
> index 21aaa2730ac8..9e3d8e1202bd 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
> @@ -281,9 +281,8 @@ static int stmmac_mdio_read_c22(struct mii_bus *bus, int phyaddr, int phyreg)
> value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask;
> value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift)
> & priv->hw->mii.clk_csr_mask;
> - if (priv->plat->has_gmac4) {
> + if (priv->plat->has_gmac4 || priv->plat->has_emac3)
> value |= MII_GMAC4_READ;
> - }
Removing the {} is correct in terms of the coding style, but it should
be done as part of a separate patch.
Andrew
Bjorn,
On Mon, Mar 13, 2023 at 03:57:27PM -0700, Stephen Boyd wrote:
> Quoting Andrew Halaney (2023-03-13 09:56:14)
> > Add the EMAC GDSCs to allow the EMAC hardware to be enabled.
> >
> > Signed-off-by: Andrew Halaney <[email protected]>
> > ---
>
> Acked-by: Stephen Boyd <[email protected]>
>
> I'm not sure if Bjorn Andersson is planning on modifying this file too,
> so please confirm it can go through netdev tree.
>
Can you please help respond to Stephen's comment above? I admittedly
don't have much experience sending patch series that span across
multiple subsystems, so if there's something I should be doing
differently (to indicate who takes what patches, etc) in submission
please do not hesitate to be overly verbose in instructing me!
Thanks,
Andrew
On 13.03.2023 17:56, Andrew Halaney wrote:
> Add the EMAC GDSCs to allow the EMAC hardware to be enabled.
>
> Signed-off-by: Andrew Halaney <[email protected]>
> ---
Was it tested to not cause issues on access on "normal" 8280xp?
AFAICS if there would be any, they would happen at registration
time, as gdsc_init already accesses its registers
Konrad
> drivers/clk/qcom/gcc-sc8280xp.c | 18 ++++++++++++++++++
> include/dt-bindings/clock/qcom,gcc-sc8280xp.h | 2 ++
> 2 files changed, 20 insertions(+)
>
> diff --git a/drivers/clk/qcom/gcc-sc8280xp.c b/drivers/clk/qcom/gcc-sc8280xp.c
> index b3198784e1c3..04a99dbaa57e 100644
> --- a/drivers/clk/qcom/gcc-sc8280xp.c
> +++ b/drivers/clk/qcom/gcc-sc8280xp.c
> @@ -6873,6 +6873,22 @@ static struct gdsc usb30_sec_gdsc = {
> .pwrsts = PWRSTS_RET_ON,
> };
>
> +static struct gdsc emac_0_gdsc = {
> + .gdscr = 0xaa004,
> + .pd = {
> + .name = "emac_0_gdsc",
> + },
> + .pwrsts = PWRSTS_OFF_ON,
> +};
> +
> +static struct gdsc emac_1_gdsc = {
> + .gdscr = 0xba004,
> + .pd = {
> + .name = "emac_1_gdsc",
> + },
> + .pwrsts = PWRSTS_OFF_ON,
> +};
> +
> static struct clk_regmap *gcc_sc8280xp_clocks[] = {
> [GCC_AGGRE_NOC_PCIE0_TUNNEL_AXI_CLK] = &gcc_aggre_noc_pcie0_tunnel_axi_clk.clkr,
> [GCC_AGGRE_NOC_PCIE1_TUNNEL_AXI_CLK] = &gcc_aggre_noc_pcie1_tunnel_axi_clk.clkr,
> @@ -7351,6 +7367,8 @@ static struct gdsc *gcc_sc8280xp_gdscs[] = {
> [USB30_MP_GDSC] = &usb30_mp_gdsc,
> [USB30_PRIM_GDSC] = &usb30_prim_gdsc,
> [USB30_SEC_GDSC] = &usb30_sec_gdsc,
> + [EMAC_0_GDSC] = &emac_0_gdsc,
> + [EMAC_1_GDSC] = &emac_1_gdsc,
> };
>
> static const struct clk_rcg_dfs_data gcc_dfs_clocks[] = {
> diff --git a/include/dt-bindings/clock/qcom,gcc-sc8280xp.h b/include/dt-bindings/clock/qcom,gcc-sc8280xp.h
> index cb2fb638825c..721105ea4fad 100644
> --- a/include/dt-bindings/clock/qcom,gcc-sc8280xp.h
> +++ b/include/dt-bindings/clock/qcom,gcc-sc8280xp.h
> @@ -492,5 +492,7 @@
> #define USB30_MP_GDSC 9
> #define USB30_PRIM_GDSC 10
> #define USB30_SEC_GDSC 11
> +#define EMAC_0_GDSC 12
> +#define EMAC_1_GDSC 13
>
> #endif
On Tue, Mar 14, 2023 at 04:13:18PM +0100, Konrad Dybcio wrote:
>
>
> On 13.03.2023 17:56, Andrew Halaney wrote:
> > Add the EMAC GDSCs to allow the EMAC hardware to be enabled.
> >
> > Signed-off-by: Andrew Halaney <[email protected]>
> > ---
> Was it tested to not cause issues on access on "normal" 8280xp?
> AFAICS if there would be any, they would happen at registration
> time, as gdsc_init already accesses its registers
No, I've only tested this series on the sa8540p-ride. I luckily also am
working from an x13s, I will use that to confirm nothing strange happens
with this applied before sending v2 and confirm the results.
Thanks for the idea,
Andrew
>
> Konrad
> > drivers/clk/qcom/gcc-sc8280xp.c | 18 ++++++++++++++++++
> > include/dt-bindings/clock/qcom,gcc-sc8280xp.h | 2 ++
> > 2 files changed, 20 insertions(+)
> >
> > diff --git a/drivers/clk/qcom/gcc-sc8280xp.c b/drivers/clk/qcom/gcc-sc8280xp.c
> > index b3198784e1c3..04a99dbaa57e 100644
> > --- a/drivers/clk/qcom/gcc-sc8280xp.c
> > +++ b/drivers/clk/qcom/gcc-sc8280xp.c
> > @@ -6873,6 +6873,22 @@ static struct gdsc usb30_sec_gdsc = {
> > .pwrsts = PWRSTS_RET_ON,
> > };
> >
> > +static struct gdsc emac_0_gdsc = {
> > + .gdscr = 0xaa004,
> > + .pd = {
> > + .name = "emac_0_gdsc",
> > + },
> > + .pwrsts = PWRSTS_OFF_ON,
> > +};
> > +
> > +static struct gdsc emac_1_gdsc = {
> > + .gdscr = 0xba004,
> > + .pd = {
> > + .name = "emac_1_gdsc",
> > + },
> > + .pwrsts = PWRSTS_OFF_ON,
> > +};
> > +
> > static struct clk_regmap *gcc_sc8280xp_clocks[] = {
> > [GCC_AGGRE_NOC_PCIE0_TUNNEL_AXI_CLK] = &gcc_aggre_noc_pcie0_tunnel_axi_clk.clkr,
> > [GCC_AGGRE_NOC_PCIE1_TUNNEL_AXI_CLK] = &gcc_aggre_noc_pcie1_tunnel_axi_clk.clkr,
> > @@ -7351,6 +7367,8 @@ static struct gdsc *gcc_sc8280xp_gdscs[] = {
> > [USB30_MP_GDSC] = &usb30_mp_gdsc,
> > [USB30_PRIM_GDSC] = &usb30_prim_gdsc,
> > [USB30_SEC_GDSC] = &usb30_sec_gdsc,
> > + [EMAC_0_GDSC] = &emac_0_gdsc,
> > + [EMAC_1_GDSC] = &emac_1_gdsc,
> > };
> >
> > static const struct clk_rcg_dfs_data gcc_dfs_clocks[] = {
> > diff --git a/include/dt-bindings/clock/qcom,gcc-sc8280xp.h b/include/dt-bindings/clock/qcom,gcc-sc8280xp.h
> > index cb2fb638825c..721105ea4fad 100644
> > --- a/include/dt-bindings/clock/qcom,gcc-sc8280xp.h
> > +++ b/include/dt-bindings/clock/qcom,gcc-sc8280xp.h
> > @@ -492,5 +492,7 @@
> > #define USB30_MP_GDSC 9
> > #define USB30_PRIM_GDSC 10
> > #define USB30_SEC_GDSC 11
> > +#define EMAC_0_GDSC 12
> > +#define EMAC_1_GDSC 13
> >
> > #endif
>
On 13/03/2023 17:56, Andrew Halaney wrote:
> From: Bhupesh Sharma <[email protected]>
>
> As commit fc191af1bb0d ("net: stmmac: platform: Fix misleading
> interrupt error msg") noted, not every stmmac based platform
> makes use of the 'eth_wake_irq' or 'eth_lpi' interrupts.
>
> So, update the 'interrupt-names' inside 'snps,dwmac' YAML
> bindings to reflect the same.
>
> Acked-by: Krzysztof Kozlowski <[email protected]>
> Signed-off-by: Bhupesh Sharma <[email protected]>
> Signed-off-by: Andrew Halaney <[email protected]>
> ---
>
> I picked this up from:
> https://lore.kernel.org/netdev/[email protected]/
> No changes other than collecting the Acked-by.
>
> Documentation/devicetree/bindings/net/snps,dwmac.yaml | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
> index 16b7d2904696..52ce14a4bea7 100644
> --- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml
> +++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
> @@ -105,8 +105,8 @@ properties:
> minItems: 1
> items:
> - const: macirq
> - - const: eth_wake_irq
> - - const: eth_lpi
> + - enum: [eth_wake_irq, eth_lpi]
> + - enum: [eth_wake_irq, eth_lpi]
I acked it before but this is not correct. This should be:
+ - enum: [eth_wake_irq, eth_lpi]
+ - enum: eth_lpi
Best regards,
Krzysztof
On 13/03/2023 17:56, Andrew Halaney wrote:
> From: Bhupesh Sharma <[email protected]>
>
> Convert Qualcomm ETHQOS Ethernet devicetree binding to YAML.
>
(...)
> diff --git a/Documentation/devicetree/bindings/net/qcom,ethqos.yaml b/Documentation/devicetree/bindings/net/qcom,ethqos.yaml
> new file mode 100644
> index 000000000000..68ef43fb283d
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/qcom,ethqos.yaml
> @@ -0,0 +1,112 @@
> +# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/net/qcom,ethqos.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Qualcomm Ethernet ETHQOS device
> +
> +maintainers:
> + - Bhupesh Sharma <[email protected]>
> +
> +description:
> + This binding describes the dwmmac based Qualcomm ethernet devices which
Drio "This binding describes", but say what is the hardware here.
> + support Gigabit ethernet (version v2.3.0 onwards).
> +
> + So, this file documents platform glue layer for dwmmac stmmac based Qualcomm
> + ethernet devices.
> +
> +allOf:
> + - $ref: snps,dwmac.yaml#
> +
> +properties:
> + compatible:
> + enum:
> + - qcom,qcs404-ethqos
> + - qcom,sm8150-ethqos
> +
> + reg:
> + maxItems: 2
> +
> + reg-names:
> + items:
> + - const: stmmaceth
> + - const: rgmii
> +
> + interrupts:
> + items:
> + - description: Combined signal for various interrupt events
> + - description: The interrupt that occurs when Rx exits the LPI state
> +
> + interrupt-names:
> + items:
> + - const: macirq
> + - const: eth_lpi
> +
> + clocks:
> + maxItems: 4
> +
> + clock-names:
> + items:
> + - const: stmmaceth
> + - const: pclk
> + - const: ptp_ref
> + - const: rgmii
> +
> + iommus:
> + maxItems: 1
Isn't this new property? Last time I asked to mention the changes to the
binding done during conversion. Explain shortly why you are adding new
properties.
> +
> +required:
> + - compatible
> + - clocks
> + - clock-names
reg-names
> +
> +unevaluatedProperties: false
> +
Best regards,
Krzysztof
On 13/03/2023 17:56, Andrew Halaney wrote:
> The sc8280xp has a new version of the ETHQOS hardware in it, EMAC v3.
> Add a compatible for this.
>
> Signed-off-by: Andrew Halaney <[email protected]>
> ---
> Documentation/devicetree/bindings/net/qcom,ethqos.yaml | 1 +
> Documentation/devicetree/bindings/net/snps,dwmac.yaml | 3 +++
> 2 files changed, 4 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/net/qcom,ethqos.yaml b/Documentation/devicetree/bindings/net/qcom,ethqos.yaml
> index 68ef43fb283d..89c17ed0442f 100644
> --- a/Documentation/devicetree/bindings/net/qcom,ethqos.yaml
> +++ b/Documentation/devicetree/bindings/net/qcom,ethqos.yaml
> @@ -24,6 +24,7 @@ properties:
> enum:
> - qcom,qcs404-ethqos
> - qcom,sm8150-ethqos
> + - qcom,sc8280xp-ethqos
Alphabetical order, same in other places.
Best regards,
Krzysztof
On Thu, Mar 16, 2023 at 08:13:24AM +0100, Krzysztof Kozlowski wrote:
> On 13/03/2023 17:56, Andrew Halaney wrote:
> > From: Bhupesh Sharma <[email protected]>
> >
> > As commit fc191af1bb0d ("net: stmmac: platform: Fix misleading
> > interrupt error msg") noted, not every stmmac based platform
> > makes use of the 'eth_wake_irq' or 'eth_lpi' interrupts.
> >
> > So, update the 'interrupt-names' inside 'snps,dwmac' YAML
> > bindings to reflect the same.
> >
> > Acked-by: Krzysztof Kozlowski <[email protected]>
> > Signed-off-by: Bhupesh Sharma <[email protected]>
> > Signed-off-by: Andrew Halaney <[email protected]>
> > ---
> >
> > I picked this up from:
> > https://lore.kernel.org/netdev/[email protected]/
> > No changes other than collecting the Acked-by.
> >
> > Documentation/devicetree/bindings/net/snps,dwmac.yaml | 4 ++--
> > 1 file changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
> > index 16b7d2904696..52ce14a4bea7 100644
> > --- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml
> > +++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
> > @@ -105,8 +105,8 @@ properties:
> > minItems: 1
> > items:
> > - const: macirq
> > - - const: eth_wake_irq
> > - - const: eth_lpi
> > + - enum: [eth_wake_irq, eth_lpi]
> > + - enum: [eth_wake_irq, eth_lpi]
>
> I acked it before but this is not correct. This should be:
> + - enum: [eth_wake_irq, eth_lpi]
> + - enum: eth_lpi
Would
+ - enum: [eth_wake_irq, eth_lpi]
+ - const: eth_lpi
be more appropriate? With the suggested change above I get the following
error, but with the above things seem to work as I expect:
(dtschema) ahalaney@halaney-x13s ~/git/redhat/stmmac (git)-[stmmac|rebase-i] % git diff HEAD~
diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
index 16b7d2904696..ca199a17f83d 100644
--- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml
+++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
@@ -105,8 +105,8 @@ properties:
minItems: 1
items:
- const: macirq
- - const: eth_wake_irq
- - const: eth_lpi
+ - enum: [eth_wake_irq, eth_lpi]
+ - enum: eth_lpi
clocks:
minItems: 1
(dtschema) ahalaney@halaney-x13s ~/git/redhat/stmmac (git)-[stmmac|rebase-i] % make dt_binding_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/net/snps,dwmac.yaml
DTEX Documentation/devicetree/bindings/net/snps,dwmac.example.dts
LINT Documentation/devicetree/bindings
CHKDT Documentation/devicetree/bindings/processed-schema.json
/home/ahalaney/git/redhat/stmmac/Documentation/devicetree/bindings/net/snps,dwmac.yaml: properties:interrupt-names:items: 'anyOf' conditional failed, one must be fixed:
[{'const': 'macirq'}, {'enum': ['eth_wake_irq', 'eth_lpi']}, {'enum': 'eth_lpi'}] is not of type 'object', 'boolean'
'eth_lpi' is not of type 'array'
from schema $id: http://json-schema.org/draft-07/schema#
/home/ahalaney/git/redhat/stmmac/Documentation/devicetree/bindings/net/snps,dwmac.yaml: properties:interrupt-names:items: 'oneOf' conditional failed, one must be fixed:
[{'const': 'macirq'}, {'enum': ['eth_wake_irq', 'eth_lpi']}, {'enum': 'eth_lpi'}] is not of type 'object'
'eth_lpi' is not of type 'array'
from schema $id: http://devicetree.org/meta-schemas/keywords.yaml#
/home/ahalaney/git/redhat/stmmac/Documentation/devicetree/bindings/net/snps,dwmac.yaml: properties:interrupt-names:items: 'oneOf' conditional failed, one must be fixed:
[{'const': 'macirq'}, {'enum': ['eth_wake_irq', 'eth_lpi']}, {'enum': 'eth_lpi'}] is not of type 'object'
'eth_lpi' is not of type 'array'
from schema $id: http://devicetree.org/meta-schemas/string-array.yaml#
SCHEMA Documentation/devicetree/bindings/processed-schema.json
/home/ahalaney/git/redhat/stmmac/Documentation/devicetree/bindings/net/snps,dwmac.yaml: ignoring, error in schema: properties: interrupt-names: items
DTC_CHK Documentation/devicetree/bindings/net/snps,dwmac.example.dtb
Thanks,
Andrew
On Mon, Mar 13, 2023 at 05:39:04PM -0700, Jakub Kicinski wrote:
> On Mon, 13 Mar 2023 11:56:17 -0500 Andrew Halaney wrote:
> > EMAC3 is a Qualcomm variant of dwmac4 that functions the same, but has a
> > different address space layout for MTL and DMA registers. This makes the
> > patch a bit more complicated than we would like so let's explain why the
> > current approach was used.
>
> Please drop all the static inlines in C sources, you're wrapping
> a single function call, the compiler will do the right thing.
>
> Please no more than 6 function arguments.
>
Thanks for the feedback! With respect to <= 6 function arguments, if I
counted right the only violation is this:
static void do_config_cbs(struct mac_device_info *hw, u32 send_slope,
u32 idle_slope, u32 high_credit, u32 low_credit,
u32 queue, u32 etsx_ctrl_base_addr,
u32 send_slp_credx_base_addr,
u32 high_credx_base_addr, u32 low_credx_base_addr,
void (*set_mtl_tx_queue_weight)(struct mac_device_info *hw,
u32 weight, u32 queue))
(...)
static void emac3_config_cbs(struct mac_device_info *hw, u32 send_slope,
u32 idle_slope, u32 high_credit,
u32 low_credit, u32 queue)
I agree, that's quite gnarly to read. the emac3_config_cbs is the
callback, so it's already at 6 arguments, so there's nothing I can
trim there. I could create some struct for readability, populate that,
then call the do_config_cbs() func with it from emac3_config_cbs.
Is that the sort of thing you want to see?
Thanks,
Andrew
On Thu, 16 Mar 2023 13:36:09 -0500 Andrew Halaney wrote:
> static void emac3_config_cbs(struct mac_device_info *hw, u32 send_slope,
> u32 idle_slope, u32 high_credit,
> u32 low_credit, u32 queue)
>
> I agree, that's quite gnarly to read. the emac3_config_cbs is the
> callback, so it's already at 6 arguments, so there's nothing I can
> trim there. I could create some struct for readability, populate that,
> then call the do_config_cbs() func with it from emac3_config_cbs.
> Is that the sort of thing you want to see?
Yes, a structure is much better, because it can be initialized member
by member,
struct bla my_bla = { .this = 1, .that = 2, .and = 3, another = 4, };
That's much easier to read. A poor man's version of Python's keyword
arguments, if you will.
On 16/03/2023 17:15, Andrew Halaney wrote:
> On Thu, Mar 16, 2023 at 08:13:24AM +0100, Krzysztof Kozlowski wrote:
>> On 13/03/2023 17:56, Andrew Halaney wrote:
>>> From: Bhupesh Sharma <[email protected]>
>>>
>>> As commit fc191af1bb0d ("net: stmmac: platform: Fix misleading
>>> interrupt error msg") noted, not every stmmac based platform
>>> makes use of the 'eth_wake_irq' or 'eth_lpi' interrupts.
>>>
>>> So, update the 'interrupt-names' inside 'snps,dwmac' YAML
>>> bindings to reflect the same.
>>>
>>> Acked-by: Krzysztof Kozlowski <[email protected]>
>>> Signed-off-by: Bhupesh Sharma <[email protected]>
>>> Signed-off-by: Andrew Halaney <[email protected]>
>>> ---
>>>
>>> I picked this up from:
>>> https://lore.kernel.org/netdev/[email protected]/
>>> No changes other than collecting the Acked-by.
>>>
>>> Documentation/devicetree/bindings/net/snps,dwmac.yaml | 4 ++--
>>> 1 file changed, 2 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
>>> index 16b7d2904696..52ce14a4bea7 100644
>>> --- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml
>>> +++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
>>> @@ -105,8 +105,8 @@ properties:
>>> minItems: 1
>>> items:
>>> - const: macirq
>>> - - const: eth_wake_irq
>>> - - const: eth_lpi
>>> + - enum: [eth_wake_irq, eth_lpi]
>>> + - enum: [eth_wake_irq, eth_lpi]
>>
>> I acked it before but this is not correct. This should be:
>> + - enum: [eth_wake_irq, eth_lpi]
>> + - enum: eth_lpi
>
> Would
> + - enum: [eth_wake_irq, eth_lpi]
> + - const: eth_lpi
> be more appropriate? With the suggested change above I get the following
> error, but with the above things seem to work as I expect:
>
> (dtschema) ahalaney@halaney-x13s ~/git/redhat/stmmac (git)-[stmmac|rebase-i] % git diff HEAD~
> diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
> index 16b7d2904696..ca199a17f83d 100644
> --- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml
> +++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
> @@ -105,8 +105,8 @@ properties:
> minItems: 1
> items:
> - const: macirq
> - - const: eth_wake_irq
> - - const: eth_lpi
> + - enum: [eth_wake_irq, eth_lpi]
> + - enum: eth_lpi
Eh, right, obviously should be here const, so:
- const: eth_lpi
Best regards,
Krzysztof
On Tue, Mar 14, 2023 at 11:08:18AM -0500, Andrew Halaney wrote:
> On Tue, Mar 14, 2023 at 04:13:18PM +0100, Konrad Dybcio wrote:
> >
> >
> > On 13.03.2023 17:56, Andrew Halaney wrote:
> > > Add the EMAC GDSCs to allow the EMAC hardware to be enabled.
> > >
> > > Signed-off-by: Andrew Halaney <[email protected]>
> > > ---
> > Was it tested to not cause issues on access on "normal" 8280xp?
> > AFAICS if there would be any, they would happen at registration
> > time, as gdsc_init already accesses its registers
>
> No, I've only tested this series on the sa8540p-ride. I luckily also am
> working from an x13s, I will use that to confirm nothing strange happens
> with this applied before sending v2 and confirm the results.
>
Writing from my x13s with this applied, things seem ok to me :)
Thanks,
Andrew
On Thu, Mar 16, 2023 at 11:52:34AM -0700, Jakub Kicinski wrote:
> On Thu, 16 Mar 2023 13:36:09 -0500 Andrew Halaney wrote:
> > static void emac3_config_cbs(struct mac_device_info *hw, u32 send_slope,
> > u32 idle_slope, u32 high_credit,
> > u32 low_credit, u32 queue)
> >
> > I agree, that's quite gnarly to read. the emac3_config_cbs is the
> > callback, so it's already at 6 arguments, so there's nothing I can
> > trim there. I could create some struct for readability, populate that,
> > then call the do_config_cbs() func with it from emac3_config_cbs.
> > Is that the sort of thing you want to see?
>
> Yes, a structure is much better, because it can be initialized member
> by member,
>
> struct bla my_bla = { .this = 1, .that = 2, .and = 3, another = 4, };
>
> That's much easier to read. A poor man's version of Python's keyword
> arguments, if you will.
What I would say is be careful with that - make sure "struct bla" is
specific to the interface being called and not generic.
I had that mistake with struct phylink_state... and there is an
endless stream of people who don't seem to bother reading the
documentation, who blindly access whatever members of that they
damn well please because it suits them, even when either they
shouldn't be writing to them, or when phylink doesn't guarantee
their contents, they read them.
As a result, I'm now of the opinion that using a struct to pass
arguments is in principle a bad idea.
There's other reasons why it's a bad idea. Many ABIs are capable of
passing arguments to functions via processor registers. As soon as
one uses a struct, they typically end up being written to memory.
Not only does that potentially cause cache line churn, it also
means that there could be more slow memory accesses that have to be
made at some point, potentially making other accesses slow.
So, all in all, I'm really not a fan of the struct approach for
all the reasons above.
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!
On Thu, 16 Mar 2023 23:01:13 +0000 Russell King (Oracle) wrote:
> What I would say is be careful with that - make sure "struct bla" is
> specific to the interface being called and not generic.
>
> I had that mistake with struct phylink_state... and there is an
> endless stream of people who don't seem to bother reading the
> documentation, who blindly access whatever members of that they
> damn well please because it suits them, even when either they
> shouldn't be writing to them, or when phylink doesn't guarantee
> their contents, they read them.
Right, gotta take it case by case. I really like structs for
const capabilities of the driver / device, which need to be
communicated to the core.
> As a result, I'm now of the opinion that using a struct to pass
> arguments is in principle a bad idea.
>
> There's other reasons why it's a bad idea. Many ABIs are capable of
> passing arguments to functions via processor registers. As soon as
> one uses a struct, they typically end up being written to memory.
> Not only does that potentially cause cache line churn, it also
> means that there could be more slow memory accesses that have to be
> made at some point, potentially making other accesses slow.
>
> So, all in all, I'm really not a fan of the struct approach for
> all the reasons above.
Also true, one has to be careful on the fast paths. There are cases
where similar set of arguments is passed multiple functions down.
Making the code hard to follow and extend. But you're right, structs
will be slower for the most part.
For stmmac I figured it can only help. The driver is touched my very
many people, it has layers and confusions...