diff mbox series

[2/3] net: stmmac: Add NXP S32 SoC family support

Message ID 20240315222754.22366-3-wafgo01@gmail.com (mailing list archive)
State Changes Requested
Delegated to: Netdev Maintainers
Headers show
Series NXP S32G3 SoC initial bring-up | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Guessed tree name to be net-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 965 this patch: 965
netdev/build_tools success Errors and warnings before: 0 this patch: 0
netdev/cc_maintainers success CCed 12 of 12 maintainers
netdev/build_clang success Errors and warnings before: 957 this patch: 957
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 981 this patch: 981
netdev/checkpatch fail CHECK: Alignment should match open parenthesis CHECK: Lines should not end with a '(' ERROR: code indent should use tabs where possible WARNING: DT compatible string "nxp,s32-dwmac" appears un-documented -- check ./Documentation/devicetree/bindings/ WARNING: added, moved or deleted file(s), does MAINTAINERS need updating? WARNING: line length of 82 exceeds 80 columns WARNING: please, no space before tabs WARNING: please, no spaces at the start of a line
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
netdev/contest warning net-next-2024-03-18--15-00 (tests: 908)

Commit Message

Wadim Mueller March 15, 2024, 10:27 p.m. UTC
Add support for NXP S32 SoC family's GMAC to the stmmac network driver. This driver implementation is based on the patchset originally contributed by Chester Lin [1], which itself draws heavily from NXP's downstream implementation [2]. The patchset was never merged.

The S32G2/3 SoCs feature multiple Ethernet interfaces (PFE0, PFE1, PFE2, and GMAC) which can be routed through a SerDes Subsystem, supporting various interfaces such as SGMII and RGMII. However, the current Glue Code lacks support for SerDes routing and pinctrl handling, relying solely on correct settings in U-Boot. Clock settings for this SoC are managed by the ATF Firmware.

Changes made compared to [1]:

    Rebased onto Linux 6.8-rc7
    Consolidated into a single commit
    Minor adjustments in naming and usage of dev_err()/dev_info()

Test Environment:
The driver has been successfully tested on the official S32G-VNP-RDB3 Reference Design Board from NXP, utilizing an S32G3 SoC. The firmware and U-Boot used were from the BSP39 Release. The official BSP39 Ubuntu 22.04 Release was successfully booted. A network stress test using iperf [3] was also executed without issues.

[1] https://patchwork.kernel.org/project/netdevbpf/patch/20221031101052.14956-6-clin@suse.com/#25068228
[2] https://github.com/nxp-auto-linux/linux/blob/release/bsp39.0-5.15.129-rt/drivers/net/ethernet/stmicro/stmmac/dwmac-s32cc.c
[3] https://linux.die.net/man/1/iperf
[4] https://github.com/nxp-auto-linux/u-boot
[5] https://github.com/nxp-auto-linux/arm-trusted-firmware

Signed-off-by: Wadim Mueller <wafgo01@gmail.com>
---
 drivers/net/ethernet/stmicro/stmmac/Kconfig   |  12 +
 drivers/net/ethernet/stmicro/stmmac/Makefile  |   1 +
 drivers/net/ethernet/stmicro/stmmac/common.h  |   3 +
 .../net/ethernet/stmicro/stmmac/dwmac-s32.c   | 313 ++++++++++++++++++
 .../net/ethernet/stmicro/stmmac/dwmac4_dma.c  |   9 +
 .../net/ethernet/stmicro/stmmac/dwmac4_dma.h  |   3 +
 drivers/net/ethernet/stmicro/stmmac/hwif.h    |   5 +
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |   7 +
 include/linux/stmmac.h                        |   9 +
 9 files changed, 362 insertions(+)
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-s32.c

Comments

Krzysztof Kozlowski March 17, 2024, 2:53 p.m. UTC | #1
On 15/03/2024 23:27, Wadim Mueller wrote:
> Add support for NXP S32 SoC family's GMAC to the stmmac network driver. This driver implementation is based on the patchset originally contributed by Chester Lin [1], which itself draws heavily from NXP's downstream implementation [2]. The patchset was never merged.
> 
> The S32G2/3 SoCs feature multiple Ethernet interfaces (PFE0, PFE1, PFE2, and GMAC) which can be routed through a SerDes Subsystem, supporting various interfaces such as SGMII and RGMII. However, the current Glue Code lacks support for SerDes routing and pinctrl handling, relying solely on correct settings in U-Boot. Clock settings for this SoC are managed by the ATF Firmware.


Please run scripts/checkpatch.pl and fix reported warnings. Some
warnings can be ignored, but the code here looks like it needs a fix.
Feel free to get in touch if the warning is not clear.

Read how commit msg should be wrapped.

Please wrap commit message according to Linux coding style / submission
process (neither too early nor over the limit):
https://elixir.bootlin.com/linux/v6.4-rc1/source/Documentation/process/submitting-patches.rst#L597

> 
> Changes made compared to [1]:
> 
>     Rebased onto Linux 6.8-rc7
>     Consolidated into a single commit
>     Minor adjustments in naming and usage of dev_err()/dev_info()
> 
> Test Environment:
> The driver has been successfully tested on the official S32G-VNP-RDB3 Reference Design Board from NXP, utilizing an S32G3 SoC. The firmware and U-Boot used were from the BSP39 Release. The official BSP39 Ubuntu 22.04 Release was successfully booted. A network stress test using iperf [3] was also executed without issues.
> 
> [1] https://patchwork.kernel.org/project/netdevbpf/patch/20221031101052.14956-6-clin@suse.com/#25068228
> [2] https://github.com/nxp-auto-linux/linux/blob/release/bsp39.0-5.15.129-rt/drivers/net/ethernet/stmicro/stmmac/dwmac-s32cc.c
> [3] https://linux.die.net/man/1/iperf
> [4] https://github.com/nxp-auto-linux/u-boot
> [5] https://github.com/nxp-auto-linux/arm-trusted-firmware
> 
> Signed-off-by: Wadim Mueller <wafgo01@gmail.com>
> ---
>  drivers/net/ethernet/stmicro/stmmac/Kconfig   |  12 +
>  drivers/net/ethernet/stmicro/stmmac/Makefile  |   1 +

That's totally unrelated to DTS. Do not mix independent work in one
patchset. This targets net-next, not SoC, so please send it as separate
patchset when net-next reopens, so after merge window.

>  drivers/net/ethernet/stmicro/stmmac/common.h  |   3 +
>  .../net/ethernet/stmicro/stmmac/dwmac-s32.c   | 313 ++++++++++++++++++
>  .../net/ethernet/stmicro/stmmac/dwmac4_dma.c  |   9 +
>  .../net/ethernet/stmicro/stmmac/dwmac4_dma.h  |   3 +
>  drivers/net/ethernet/stmicro/stmmac/hwif.h    |   5 +
>  .../net/ethernet/stmicro/stmmac/stmmac_main.c |   7 +
>  include/linux/stmmac.h                        |   9 +
>  9 files changed, 362 insertions(+)
>  create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-s32.c
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> index 85dcda51df05..1cdf2da0251c 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
> +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> @@ -142,6 +142,18 @@ config DWMAC_ROCKCHIP
>  	  This selects the Rockchip RK3288 SoC glue layer support for
>  	  the stmmac device drive


...

> +
> +	plat_dat->safety_feat_cfg->tsoee = 1;
> +	plat_dat->safety_feat_cfg->mrxpee = 1;
> +	plat_dat->safety_feat_cfg->mestee = 1;
> +	plat_dat->safety_feat_cfg->mrxee = 1;
> +	plat_dat->safety_feat_cfg->mtxee = 1;
> +	plat_dat->safety_feat_cfg->epsi = 1;
> +	plat_dat->safety_feat_cfg->edpp = 1;
> +	plat_dat->safety_feat_cfg->prtyen = 1;
> +	plat_dat->safety_feat_cfg->tmouten = 1;
> +
> +	ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
> +	if (ret)
> +		goto err_gmac_exit;
> +
> +	return 0;
> +
> +err_gmac_exit:
> +	s32_gmac_exit(pdev, plat_dat->bsp_priv);
> +	return ret;
> +}
> +
> +static const struct of_device_id s32_dwmac_match[] = {
> +	{ .compatible = "nxp,s32-dwmac" },


Missing bindings.

Please run scripts/checkpatch.pl and fix reported warnings. Some
warnings can be ignored, but the code here looks like it needs a fix.
Feel free to get in touch if the warning is not clear.

> +	{}
> +};



Best regards,
Krzysztof
Jan Petrous March 17, 2024, 6:26 p.m. UTC | #2
> Add support for NXP S32 SoC family's GMAC to the stmmac network driver.
> This driver implementation is based on the patchset originally contributed by
> Chester Lin [1], which itself draws heavily from NXP's downstream
> implementation [2]. The patchset was never merged.
>

Hi Wadim,

Thank you for your upstreaming activities, but I would like to note that
the old NXP S32CC  stmmac glue was rewritten lately and will be part of next
NXP BSP Linux release planned for April.

The rework was done mainly to allow simpler upstreaming process, so I would recommend
to postpone your current work.

Thanks.
/Jan

> The S32G2/3 SoCs feature multiple Ethernet interfaces (PFE0, PFE1, PFE2, and
> GMAC) which can be routed through a SerDes Subsystem, supporting various
> interfaces such as SGMII and RGMII. However, the current Glue Code lacks
> support for SerDes routing and pinctrl handling, relying solely on correct
> settings in U-Boot. Clock settings for this SoC are managed by the ATF
> Firmware.
>
> Changes made compared to [1]:
>
>     Rebased onto Linux 6.8-rc7
>     Consolidated into a single commit
>     Minor adjustments in naming and usage of dev_err()/dev_info()
>
> Test Environment:
> The driver has been successfully tested on the official S32G-VNP-RDB3
> Reference Design Board from NXP, utilizing an S32G3 SoC. The firmware and
> U-Boot used were from the BSP39 Release. The official BSP39 Ubuntu 22.04
> Release was successfully booted. A network stress test using iperf [3] was also
> executed without issues.
>
> [1]
> https://patchw/
> ork.kernel.org%2Fproject%2Fnetdevbpf%2Fpatch%2F20221031101052.14956-
> 6-
> clin%40suse.com%2F%2325068228&data=05%7C02%7Cjan.petrous%40nxp.c
> om%7C0cc5c9f3d01f4ffd9c8808dc453f46e2%7C686ea1d3bc2b4c6fa92cd99c5
> c301635%7C0%7C0%7C638461385281642147%7CUnknown%7CTWFpbGZsb3
> d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%
> 3D%7C0%7C%7C%7C&sdata=rIngeRww4WVHGJtI9z9nQssulWK772YoRkOcB0
> uKoN0%3D&reserved=0
> [2]
> https://github/.
> com%2Fnxp-auto-linux%2Flinux%2Fblob%2Frelease%2Fbsp39.0-5.15.129-
> rt%2Fdrivers%2Fnet%2Fethernet%2Fstmicro%2Fstmmac%2Fdwmac-
> s32cc.c&data=05%7C02%7Cjan.petrous%40nxp.com%7C0cc5c9f3d01f4ffd9c8
> 808dc453f46e2%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C6384
> 61385281650452%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiL
> CJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0%7C%7C%7C&sdata
> =y1EPryNiZIM4lzzTGPfcY4QGHgG8omiOKM8LfTkUqBs%3D&reserved=0
> [3]
> https://linux.di/
> e.net%2Fman%2F1%2Fiperf&data=05%7C02%7Cjan.petrous%40nxp.com%7C
> 0cc5c9f3d01f4ffd9c8808dc453f46e2%7C686ea1d3bc2b4c6fa92cd99c5c301635
> %7C0%7C0%7C638461385281656709%7CUnknown%7CTWFpbGZsb3d8eyJWI
> joiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0
> %7C%7C%7C&sdata=ydOwCmVhv4C40MIdo%2F5BCUHr588N%2B%2BqRxeKA
> gCjwlT4%3D&reserved=0
> [4]
> https://github/.
> com%2Fnxp-auto-linux%2Fu-
> boot&data=05%7C02%7Cjan.petrous%40nxp.com%7C0cc5c9f3d01f4ffd9c880
> 8dc453f46e2%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C638461
> 385281661168%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJ
> QIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0%7C%7C%7C&sdata=R
> vq1e2h%2FdF0ZAAR7rTNWDM9k4ktVlZV3D3Oi0ZDVtts%3D&reserved=0
> [5]
> https://github/.
> com%2Fnxp-auto-linux%2Farm-trusted-
> firmware&data=05%7C02%7Cjan.petrous%40nxp.com%7C0cc5c9f3d01f4ffd9c
> 8808dc453f46e2%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C638
> 461385281665752%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAi
> LCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0%7C%7C%7C&sdat
> a=YaU2kR6PC0%2FkpZ7htdJuLY555XliyI7GU%2BH6TneNSIE%3D&reserved=0
>
> Signed-off-by: Wadim Mueller <wafgo01@gmail.com>
> ---
>  drivers/net/ethernet/stmicro/stmmac/Kconfig   |  12 +
>  drivers/net/ethernet/stmicro/stmmac/Makefile  |   1 +
>  drivers/net/ethernet/stmicro/stmmac/common.h  |   3 +
>  .../net/ethernet/stmicro/stmmac/dwmac-s32.c   | 313 ++++++++++++++++++
>  .../net/ethernet/stmicro/stmmac/dwmac4_dma.c  |   9 +
>  .../net/ethernet/stmicro/stmmac/dwmac4_dma.h  |   3 +
>  drivers/net/ethernet/stmicro/stmmac/hwif.h    |   5 +
>  .../net/ethernet/stmicro/stmmac/stmmac_main.c |   7 +
>  include/linux/stmmac.h                        |   9 +
>  9 files changed, 362 insertions(+)
>  create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-s32.c
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig
> b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> index 85dcda51df05..1cdf2da0251c 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
> +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> @@ -142,6 +142,18 @@ config DWMAC_ROCKCHIP
>           This selects the Rockchip RK3288 SoC glue layer support for
>           the stmmac device driver.
>
> +config DWMAC_S32
> +       tristate "NXP S32 series GMAC support"
> +       default ARCH_S32
> +       depends on OF && (ARCH_S32 || COMPILE_TEST)
> +       select PHYLINK
> +       help
> +         Support for ethernet controller on NXP S32 series SOCs.
> +
> +         This selects NXP SoC glue layer support for the stmmac
> +         device driver. This driver is used for the S32 series
> +         SOCs GMAC ethernet controller.
> +
>  config DWMAC_SOCFPGA
>         tristate "SOCFPGA dwmac support"
>         default ARCH_INTEL_SOCFPGA
> diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile
> b/drivers/net/ethernet/stmicro/stmmac/Makefile
> index 26cad4344701..c48ff95ed972 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/Makefile
> +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
> @@ -34,6 +34,7 @@ obj-$(CONFIG_DWMAC_GENERIC)   += dwmac-generic.o
>  obj-$(CONFIG_DWMAC_IMX8)       += dwmac-imx.o
>  obj-$(CONFIG_DWMAC_TEGRA)      += dwmac-tegra.o
>  obj-$(CONFIG_DWMAC_VISCONTI)   += dwmac-visconti.o
> +obj-$(CONFIG_DWMAC_S32)        += dwmac-s32.o
>  stmmac-platform-objs:= stmmac_platform.o
>  dwmac-altr-socfpga-objs := dwmac-socfpga.o
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h
> b/drivers/net/ethernet/stmicro/stmmac/common.h
> index 5ba606a596e7..e5e23e8c07e1 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/common.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/common.h
> @@ -254,6 +254,9 @@ struct stmmac_safety_stats {
>  #define CSR_F_150M     150000000
>  #define CSR_F_250M     250000000
>  #define CSR_F_300M     300000000
> +#define CSR_F_500M     500000000
> +#define CSR_F_800M     800000000
> +
>
>  #define        MAC_CSR_H_FRQ_MASK      0x20
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-s32.c
> b/drivers/net/ethernet/stmicro/stmmac/dwmac-s32.c
> new file mode 100644
> index 000000000000..1920eeed2269
> --- /dev/null
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-s32.c
> @@ -0,0 +1,313 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * DWMAC Specific Glue layer for NXP S32 SoCs
> + *
> + * Copyright (C) 2019-2022 NXP
> + * Copyright (C) 2022 SUSE LLC
> + *
> + */
> +
> +#include <linux/device.h>
> +#include <linux/ethtool.h>
> +#include <linux/module.h>
> +#include <linux/io.h>
> +#include <linux/clk.h>
> +#include <linux/phy.h>
> +#include <linux/platform_device.h>
> +#include <linux/of.h>
> +#include <linux/of_net.h>
> +#include <linux/of_address.h>
> +#include <linux/stmmac.h>
> +#include "stmmac_platform.h"
> +
> +#define GMAC_TX_RATE_125M 125000000 /* 125MHz */
> +#define GMAC_TX_RATE_25M 25000000 /* 25MHz */
> +#define GMAC_TX_RATE_2M5 2500000 /* 2.5MHz */
> +
> +/* S32 SRC register for phyif selection */
> +#define PHY_INTF_SEL_MII 0x00
> +#define PHY_INTF_SEL_SGMII 0x01
> +#define PHY_INTF_SEL_RGMII 0x02
> +#define PHY_INTF_SEL_RMII 0x08
> +
> +/* AXI4 ACE control settings */
> +#define ACE_DOMAIN_SIGNAL 0x2
> +#define ACE_CACHE_SIGNAL 0xf
> +#define ACE_CONTROL_SIGNALS ((ACE_DOMAIN_SIGNAL << 4) |
> ACE_CACHE_SIGNAL)
> +#define ACE_PROTECTION 0x2
> +
> +struct s32_priv_data {
> +       void __iomem *ctrl_sts;
> +       struct device *dev;
> +       phy_interface_t intf_mode;
> +       struct clk *tx_clk;
> +       struct clk *rx_clk;
> +};
> +
> +static int s32_gmac_init(struct platform_device *pdev, void *priv)
> +{
> +       struct s32_priv_data *gmac = priv;
> +       u32 intf_sel;
> +       int ret;
> +
> +       if (gmac->tx_clk) {
> +               ret = clk_prepare_enable(gmac->tx_clk);
> +               if (ret) {
> +                       dev_err(&pdev->dev, "Can't set tx clock\n");
> +                       return ret;
> +               }
> +       }
> +
> +       if (gmac->rx_clk) {
> +               ret = clk_prepare_enable(gmac->rx_clk);
> +               if (ret) {
> +                       dev_err(&pdev->dev, "Can't set rx clock\n");
> +                       return ret;
> +               }
> +       }
> +
> +       /* set interface mode */
> +       if (gmac->ctrl_sts) {
> +               switch (gmac->intf_mode) {
> +               default:
> +                       dev_info(
> +                               &pdev->dev,
> +                               "unsupported mode %u, set the default phy mode.\n",
> +                               gmac->intf_mode);
> +                       fallthrough;
> +               case PHY_INTERFACE_MODE_SGMII:
> +                       dev_info(&pdev->dev, "phy mode set to SGMII\n");
> +                       intf_sel = PHY_INTF_SEL_SGMII;
> +                       break;
> +               case PHY_INTERFACE_MODE_RGMII:
> +               case PHY_INTERFACE_MODE_RGMII_ID:
> +               case PHY_INTERFACE_MODE_RGMII_TXID:
> +               case PHY_INTERFACE_MODE_RGMII_RXID:
> +                       dev_info(&pdev->dev, "phy mode set to RGMII\n");
> +                       intf_sel = PHY_INTF_SEL_RGMII;
> +                       break;
> +               case PHY_INTERFACE_MODE_RMII:
> +                       dev_info(&pdev->dev, "phy mode set to RMII\n");
> +                       intf_sel = PHY_INTF_SEL_RMII;
> +                       break;
> +               case PHY_INTERFACE_MODE_MII:
> +                       dev_info(&pdev->dev, "phy mode set to MII\n");
> +                       intf_sel = PHY_INTF_SEL_MII;
> +                       break;
> +               }
> +
> +               writel(intf_sel, gmac->ctrl_sts);
> +       }
> +
> +       return 0;
> +}
> +
> +static void s32_gmac_exit(struct platform_device *pdev, void *priv)
> +{
> +       struct s32_priv_data *gmac = priv;
> +
> +       if (gmac->tx_clk)
> +               clk_disable_unprepare(gmac->tx_clk);
> +
> +       if (gmac->rx_clk)
> +               clk_disable_unprepare(gmac->rx_clk);
> +}
> +
> +static void s32_fix_speed(void *priv, unsigned int speed, unsigned int mode)
> +{
> +       struct s32_priv_data *gmac = priv;
> +
> +       if (!gmac->tx_clk || !gmac->rx_clk)
> +               return;
> +
> +       /* SGMII mode doesn't support the clock reconfiguration */
> +       if (gmac->intf_mode == PHY_INTERFACE_MODE_SGMII)
> +               return;
> +
> +       switch (speed) {
> +       case SPEED_1000:
> +               dev_info(gmac->dev, "Set TX clock to 125M\n");
> +               clk_set_rate(gmac->tx_clk, GMAC_TX_RATE_125M);
> +               break;
> +       case SPEED_100:
> +               dev_info(gmac->dev, "Set TX clock to 25M\n");
> +               clk_set_rate(gmac->tx_clk, GMAC_TX_RATE_25M);
> +               break;
> +       case SPEED_10:
> +               dev_info(gmac->dev, "Set TX clock to 2.5M\n");
> +               clk_set_rate(gmac->tx_clk, GMAC_TX_RATE_2M5);
> +               break;
> +       default:
> +               dev_err(gmac->dev, "Unsupported/Invalid speed: %d\n", speed);
> +               return;
> +       }
> +}
> +
> +static int s32_config_cache_coherency(struct platform_device *pdev,
> +                                     struct plat_stmmacenet_data *plat_dat)
> +{
> +       plat_dat->axi4_ace_ctrl = devm_kzalloc(
> +               &pdev->dev, sizeof(struct stmmac_axi4_ace_ctrl), GFP_KERNEL);
> +
> +       if (!plat_dat->axi4_ace_ctrl)
> +               return -ENOMEM;
> +
> +       plat_dat->axi4_ace_ctrl->tx_ar_reg = (ACE_CONTROL_SIGNALS << 16) |
> +                                            (ACE_CONTROL_SIGNALS << 8) |
> +                                            ACE_CONTROL_SIGNALS;
> +
> +       plat_dat->axi4_ace_ctrl->rx_aw_reg =
> +               (ACE_CONTROL_SIGNALS << 24) | (ACE_CONTROL_SIGNALS << 16) |
> +               (ACE_CONTROL_SIGNALS << 8) | ACE_CONTROL_SIGNALS;
> +
> +       plat_dat->axi4_ace_ctrl->txrx_awar_reg =
> +               (ACE_PROTECTION << 20) | (ACE_PROTECTION << 16) |
> +               (ACE_CONTROL_SIGNALS << 8) | ACE_CONTROL_SIGNALS;
> +
> +       return 0;
> +}
> +
> +static int s32_dwmac_probe(struct platform_device *pdev)
> +{
> +       struct plat_stmmacenet_data *plat_dat;
> +       struct stmmac_resources stmmac_res;
> +       struct s32_priv_data *gmac;
> +       struct resource *res;
> +       const char *tx_clk, *rx_clk;
> +       int ret;
> +
> +       ret = stmmac_get_platform_resources(pdev, &stmmac_res);
> +       if (ret)
> +               return ret;
> +
> +       gmac = devm_kzalloc(&pdev->dev, sizeof(*gmac), GFP_KERNEL);
> +       if (!gmac)
> +               return PTR_ERR(gmac);
> +
> +       gmac->dev = &pdev->dev;
> +
> +       /* S32G control reg */
> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +       gmac->ctrl_sts = devm_ioremap_resource(&pdev->dev, res);
> +       if (IS_ERR_OR_NULL(gmac->ctrl_sts)) {
> +               dev_err(&pdev->dev, "S32G config region is missing\n");
> +               return PTR_ERR(gmac->ctrl_sts);
> +       }
> +
> +       plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac);
> +       if (IS_ERR(plat_dat))
> +               return PTR_ERR(plat_dat);
> +
> +       plat_dat->bsp_priv = gmac;
> +
> +       switch (plat_dat->phy_interface) {
> +       case PHY_INTERFACE_MODE_SGMII:
> +               tx_clk = "tx_sgmii";
> +               rx_clk = "rx_sgmii";
> +               break;
> +       case PHY_INTERFACE_MODE_RGMII:
> +       case PHY_INTERFACE_MODE_RGMII_ID:
> +       case PHY_INTERFACE_MODE_RGMII_TXID:
> +       case PHY_INTERFACE_MODE_RGMII_RXID:
> +               tx_clk = "tx_rgmii";
> +               rx_clk = "rx_rgmii";
> +               break;
> +       case PHY_INTERFACE_MODE_RMII:
> +               tx_clk = "tx_rmii";
> +               rx_clk = "rx_rmii";
> +               break;
> +       case PHY_INTERFACE_MODE_MII:
> +               tx_clk = "tx_mii";
> +               rx_clk = "rx_mii";
> +               break;
> +       default:
> +               dev_err(&pdev->dev, "Not supported phy interface mode: [%s]\n",
> +                       phy_modes(plat_dat->phy_interface));
> +               return -EINVAL;
> +       };
> +
> +       gmac->intf_mode = plat_dat->phy_interface;
> +
> +       /* DMA cache coherency settings */
> +       if (of_dma_is_coherent(pdev->dev.of_node)) {
> +               ret = s32_config_cache_coherency(pdev, plat_dat);
> +               if (ret)
> +                       return ret;
> +       }
> +
> +       /* tx clock */
> +       gmac->tx_clk = devm_clk_get(&pdev->dev, tx_clk);
> +       if (IS_ERR(gmac->tx_clk)) {
> +               dev_info(&pdev->dev, "tx clock not found\n");
> +               gmac->tx_clk = NULL;
> +       }
> +
> +       /* rx clock */
> +       gmac->rx_clk = devm_clk_get(&pdev->dev, rx_clk);
> +       if (IS_ERR(gmac->rx_clk)) {
> +               dev_info(&pdev->dev, "rx clock not found\n");
> +               gmac->rx_clk = NULL;
> +       }
> +
> +       ret = s32_gmac_init(pdev, gmac);
> +       if (ret)
> +               return ret;
> +
> +       /* core feature set */
> +       plat_dat->has_gmac4 = true;
> +       plat_dat->pmt = 1;
> +
> +       plat_dat->init = s32_gmac_init;
> +       plat_dat->exit = s32_gmac_exit;
> +       plat_dat->fix_mac_speed = s32_fix_speed;
> +
> +       /* safety feature config */
> +       plat_dat->safety_feat_cfg = devm_kzalloc(
> +               &pdev->dev, sizeof(*plat_dat->safety_feat_cfg), GFP_KERNEL);
> +
> +       if (!plat_dat->safety_feat_cfg) {
> +               dev_err(&pdev->dev, "allocate safety_feat_cfg failed\n");
> +               goto err_gmac_exit;
> +       }
> +
> +       plat_dat->safety_feat_cfg->tsoee = 1;
> +       plat_dat->safety_feat_cfg->mrxpee = 1;
> +       plat_dat->safety_feat_cfg->mestee = 1;
> +       plat_dat->safety_feat_cfg->mrxee = 1;
> +       plat_dat->safety_feat_cfg->mtxee = 1;
> +       plat_dat->safety_feat_cfg->epsi = 1;
> +       plat_dat->safety_feat_cfg->edpp = 1;
> +       plat_dat->safety_feat_cfg->prtyen = 1;
> +       plat_dat->safety_feat_cfg->tmouten = 1;
> +
> +       ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
> +       if (ret)
> +               goto err_gmac_exit;
> +
> +       return 0;
> +
> +err_gmac_exit:
> +       s32_gmac_exit(pdev, plat_dat->bsp_priv);
> +       return ret;
> +}
> +
> +static const struct of_device_id s32_dwmac_match[] = {
> +       { .compatible = "nxp,s32-dwmac" },
> +       {}
> +};
> +MODULE_DEVICE_TABLE(of, s32_dwmac_match);
> +
> +static struct platform_driver s32_dwmac_driver = {
> +       .probe  = s32_dwmac_probe,
> +       .remove_new = stmmac_pltfr_remove,
> +       .driver = {
> +               .name           = "s32-dwmac",
> +               .pm             = &stmmac_pltfr_pm_ops,
> +               .of_match_table = s32_dwmac_match,
> +       },
> +};
> +module_platform_driver(s32_dwmac_driver);
> +
> +MODULE_AUTHOR("Jan Petrous <jan.petrous@nxp.com>");
> +MODULE_DESCRIPTION("NXP S32 GMAC driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> index 84d3a8551b03..edb559c36509 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> @@ -556,6 +556,14 @@ static int dwmac4_enable_tbs(struct stmmac_priv
> *priv, void __iomem *ioaddr,
>         return 0;
>  }
>
> +static void dwmac4_set_axi4_cc(struct stmmac_priv *priv, void __iomem
> *ioaddr,
> +                          struct stmmac_axi4_ace_ctrl *acecfg)
> +{
> +       writel(acecfg->tx_ar_reg, ioaddr + DMA_AXI4_TX_AR_ACE_CONTROL);
> +       writel(acecfg->rx_aw_reg, ioaddr + DMA_AXI4_RX_AW_ACE_CONTROL);
> +       writel(acecfg->txrx_awar_reg, ioaddr +
> DMA_AXI4_TXRX_AWAR_ACE_CONTROL);
> +}
> +
>  const struct stmmac_dma_ops dwmac4_dma_ops = {
>         .reset = dwmac4_dma_reset,
>         .init = dwmac4_dma_init,
> @@ -608,6 +616,7 @@ const struct stmmac_dma_ops dwmac410_dma_ops
> = {
>         .set_tx_ring_len = dwmac4_set_tx_ring_len,
>         .set_rx_tail_ptr = dwmac4_set_rx_tail_ptr,
>         .set_tx_tail_ptr = dwmac4_set_tx_tail_ptr,
> +       .set_axi4_cc = dwmac4_set_axi4_cc,
>         .enable_tso = dwmac4_enable_tso,
>         .qmode = dwmac4_qmode,
>         .set_bfsize = dwmac4_set_bfsize,
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h
> b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h
> index 358e7dcb6a9a..7195c643774f 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h
> @@ -22,6 +22,9 @@
>  #define DMA_DEBUG_STATUS_1             0x00001010
>  #define DMA_DEBUG_STATUS_2             0x00001014
>  #define DMA_AXI_BUS_MODE               0x00001028
> +#define DMA_AXI4_TX_AR_ACE_CONTROL     0x00001020
> +#define DMA_AXI4_RX_AW_ACE_CONTROL     0x00001024
> +#define DMA_AXI4_TXRX_AWAR_ACE_CONTROL 0x00001028
>  #define DMA_TBS_CTRL                   0x00001050
>
>  /* DMA Bus Mode bitmap */
> diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h
> b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> index 7be04b54738b..6ea2d8f562d0 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> @@ -227,6 +227,9 @@ struct stmmac_dma_ops {
>                                 u32 tail_ptr, u32 chan);
>         void (*set_tx_tail_ptr)(struct stmmac_priv *priv, void __iomem *ioaddr,
>                                 u32 tail_ptr, u32 chan);
> +       /* Configure AXI4 cache coherency for Tx and Rx DMA channels */
> +        void (*set_axi4_cc)(struct stmmac_priv *priv, void __iomem *ioaddr,
> +                          struct stmmac_axi4_ace_ctrl *acecfg);
>         void (*enable_tso)(struct stmmac_priv *priv, void __iomem *ioaddr,
>                            bool en, u32 chan);
>         void (*qmode)(struct stmmac_priv *priv, void __iomem *ioaddr,
> @@ -285,6 +288,8 @@ struct stmmac_dma_ops {
>         stmmac_do_void_callback(__priv, dma, set_rx_tail_ptr, __priv, __args)
>  #define stmmac_set_tx_tail_ptr(__priv, __args...) \
>         stmmac_do_void_callback(__priv, dma, set_tx_tail_ptr, __priv, __args)
> +#define stmmac_set_axi4_cc(__priv, __args...) \
> +        stmmac_do_void_callback(__priv, dma, set_axi4_cc, __priv, __args)
>  #define stmmac_enable_tso(__priv, __args...) \
>         stmmac_do_void_callback(__priv, dma, enable_tso, __priv, __args)
>  #define stmmac_dma_qmode(__priv, __args...) \
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index 7c6aef033a45..b7b4d7dd1149 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -324,6 +324,10 @@ static void stmmac_clk_csr_set(struct stmmac_priv
> *priv)
>                         priv->clk_csr = STMMAC_CSR_150_250M;
>                 else if ((clk_rate >= CSR_F_250M) && (clk_rate <= CSR_F_300M))
>                         priv->clk_csr = STMMAC_CSR_250_300M;
> +               else if ((clk_rate >= CSR_F_300M) && (clk_rate < CSR_F_500M))
> +                       priv->clk_csr = STMMAC_CSR_300_500M;
> +               else if ((clk_rate >= CSR_F_500M) && (clk_rate < CSR_F_800M))
> +                       priv->clk_csr = STMMAC_CSR_500_800M;
>         }
>
>         if (priv->plat->flags & STMMAC_FLAG_HAS_SUN8I) {
> @@ -3030,6 +3034,9 @@ static int stmmac_init_dma_engine(struct
> stmmac_priv *priv)
>         if (priv->plat->axi)
>                 stmmac_axi(priv, priv->ioaddr, priv->plat->axi);
>
> +       if (priv->plat->axi4_ace_ctrl)
> +               stmmac_set_axi4_cc(priv, priv->ioaddr, priv->plat->axi4_ace_ctrl);
> +
>         /* DMA CSR Channel configuration */
>         for (chan = 0; chan < dma_csr_ch; chan++) {
>                 stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> index dee5ad6e48c5..a69ac8b9274e 100644
> --- a/include/linux/stmmac.h
> +++ b/include/linux/stmmac.h
> @@ -34,6 +34,8 @@
>  #define        STMMAC_CSR_35_60M       0x3     /* MDC = clk_scr_i/26 */
>  #define        STMMAC_CSR_150_250M     0x4     /* MDC = clk_scr_i/102 */
>  #define        STMMAC_CSR_250_300M     0x5     /* MDC = clk_scr_i/122 */
> +#define        STMMAC_CSR_300_500M     0x6     /* MDC = clk_scr_i/204 */
> +#define        STMMAC_CSR_500_800M     0x7     /* MDC = clk_scr_i/324 */
>
>  /* MTL algorithms identifiers */
>  #define MTL_TX_ALGORITHM_WRR   0x0
> @@ -115,6 +117,12 @@ struct stmmac_axi {
>         bool axi_rb;
>  };
>
> +struct stmmac_axi4_ace_ctrl {
> +       u32 tx_ar_reg;
> +       u32 rx_aw_reg;
> +       u32 txrx_awar_reg;
> +};
> +
>  #define EST_GCL                1024
>  struct stmmac_est {
>         struct mutex lock;
> @@ -296,6 +304,7 @@ struct plat_stmmacenet_data {
>         struct reset_control *stmmac_rst;
>         struct reset_control *stmmac_ahb_rst;
>         struct stmmac_axi *axi;
> +       struct stmmac_axi4_ace_ctrl *axi4_ace_ctrl;
>         int has_gmac4;
>         int rss_en;
>         int mac_port_sel_speed;
> --
> 2.25.1
Krzysztof Kozlowski March 17, 2024, 6:47 p.m. UTC | #3
On 17/03/2024 19:26, Jan Petrous (OSS) wrote:
>> Add support for NXP S32 SoC family's GMAC to the stmmac network driver.
>> This driver implementation is based on the patchset originally contributed by
>> Chester Lin [1], which itself draws heavily from NXP's downstream
>> implementation [2]. The patchset was never merged.
>>
> 
> Hi Wadim,
> 
> Thank you for your upstreaming activities, but I would like to note that
> the old NXP S32CC  stmmac glue was rewritten lately and will be part of next
> NXP BSP Linux release planned for April.
> 
> The rework was done mainly to allow simpler upstreaming process, so I would recommend
> to postpone your current work.

I suggest you working with upstream first instead of claiming that
upstream contributions should align with your downstream work. To be
clear: your downstream NXP BSP does not matter.

If you think this submission needs any particular changes, then please
comment on specifics, but such broad statement that community should
wait till NXP will be so kind to allow upstream work is just not acceptable.

Best regards,
Krzysztof
Wadim Mueller March 17, 2024, 11:26 p.m. UTC | #4
On Sun, Mar 17, 2024 at 03:53:19PM +0100, Krzysztof Kozlowski wrote:
> On 15/03/2024 23:27, Wadim Mueller wrote:
> > Add support for NXP S32 SoC family's GMAC to the stmmac network driver. This driver implementation is based on the patchset originally contributed by Chester Lin [1], which itself draws heavily from NXP's downstream implementation [2]. The patchset was never merged.
> > 
> > The S32G2/3 SoCs feature multiple Ethernet interfaces (PFE0, PFE1, PFE2, and GMAC) which can be routed through a SerDes Subsystem, supporting various interfaces such as SGMII and RGMII. However, the current Glue Code lacks support for SerDes routing and pinctrl handling, relying solely on correct settings in U-Boot. Clock settings for this SoC are managed by the ATF Firmware.
> 
> 
> Please run scripts/checkpatch.pl and fix reported warnings. Some
> warnings can be ignored, but the code here looks like it needs a fix.
> Feel free to get in touch if the warning is not clear.
> 
> Read how commit msg should be wrapped.
> 
> Please wrap commit message according to Linux coding style / submission
> process (neither too early nor over the limit):
> https://elixir.bootlin.com/linux/v6.4-rc1/source/Documentation/process/submitting-patches.rst#L597
> 
> > 
> > Changes made compared to [1]:
> > 
> >     Rebased onto Linux 6.8-rc7
> >     Consolidated into a single commit
> >     Minor adjustments in naming and usage of dev_err()/dev_info()
> > 
> > Test Environment:
> > The driver has been successfully tested on the official S32G-VNP-RDB3 Reference Design Board from NXP, utilizing an S32G3 SoC. The firmware and U-Boot used were from the BSP39 Release. The official BSP39 Ubuntu 22.04 Release was successfully booted. A network stress test using iperf [3] was also executed without issues.
> > 
> > [1] https://patchwork.kernel.org/project/netdevbpf/patch/20221031101052.14956-6-clin@suse.com/#25068228
> > [2] https://github.com/nxp-auto-linux/linux/blob/release/bsp39.0-5.15.129-rt/drivers/net/ethernet/stmicro/stmmac/dwmac-s32cc.c
> > [3] https://linux.die.net/man/1/iperf
> > [4] https://github.com/nxp-auto-linux/u-boot
> > [5] https://github.com/nxp-auto-linux/arm-trusted-firmware
> > 
> > Signed-off-by: Wadim Mueller <wafgo01@gmail.com>
> > ---
> >  drivers/net/ethernet/stmicro/stmmac/Kconfig   |  12 +
> >  drivers/net/ethernet/stmicro/stmmac/Makefile  |   1 +
> 
> That's totally unrelated to DTS. Do not mix independent work in one
> patchset. This targets net-next, not SoC, so please send it as separate
> patchset when net-next reopens, so after merge window.
>

Let me try to explain why I was thinking that both should be part of the
same patchset. 

The DTS file patch [1/3] is refering to a NIC for which there is no
upstream driver (or lets call it better glue code for the real driver) available. 

This patch here is supposed to add support for this driver. So without this part the DT
node named "gmac0" of [1/3] is not of much use. Thats why I was thinking they
should be part of one patchset.

But your statement also totally makes sense to me.

Thanks for the feedback!

> >  drivers/net/ethernet/stmicro/stmmac/common.h  |   3 +
> >  .../net/ethernet/stmicro/stmmac/dwmac-s32.c   | 313 ++++++++++++++++++
> >  .../net/ethernet/stmicro/stmmac/dwmac4_dma.c  |   9 +
> >  .../net/ethernet/stmicro/stmmac/dwmac4_dma.h  |   3 +
> >  drivers/net/ethernet/stmicro/stmmac/hwif.h    |   5 +
> >  .../net/ethernet/stmicro/stmmac/stmmac_main.c |   7 +
> >  include/linux/stmmac.h                        |   9 +
> >  9 files changed, 362 insertions(+)
> >  create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-s32.c
> > 
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> > index 85dcda51df05..1cdf2da0251c 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
> > +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> > @@ -142,6 +142,18 @@ config DWMAC_ROCKCHIP
> >  	  This selects the Rockchip RK3288 SoC glue layer support for
> >  	  the stmmac device drive
> 
> 
> ...
> 
> > +
> > +	plat_dat->safety_feat_cfg->tsoee = 1;
> > +	plat_dat->safety_feat_cfg->mrxpee = 1;
> > +	plat_dat->safety_feat_cfg->mestee = 1;
> > +	plat_dat->safety_feat_cfg->mrxee = 1;
> > +	plat_dat->safety_feat_cfg->mtxee = 1;
> > +	plat_dat->safety_feat_cfg->epsi = 1;
> > +	plat_dat->safety_feat_cfg->edpp = 1;
> > +	plat_dat->safety_feat_cfg->prtyen = 1;
> > +	plat_dat->safety_feat_cfg->tmouten = 1;
> > +
> > +	ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
> > +	if (ret)
> > +		goto err_gmac_exit;
> > +
> > +	return 0;
> > +
> > +err_gmac_exit:
> > +	s32_gmac_exit(pdev, plat_dat->bsp_priv);
> > +	return ret;
> > +}
> > +
> > +static const struct of_device_id s32_dwmac_match[] = {
> > +	{ .compatible = "nxp,s32-dwmac" },
> 
> 
> Missing bindings.
> 
> Please run scripts/checkpatch.pl and fix reported warnings. Some
> warnings can be ignored, but the code here looks like it needs a fix.
> Feel free to get in touch if the warning is not clear.
> 
> > +	{}
> > +};
> 
> 
> 
> Best regards,
> Krzysztof
>
Krzysztof Kozlowski March 18, 2024, 7:41 a.m. UTC | #5
On 18/03/2024 00:26, Wadim Mueller wrote:
> On Sun, Mar 17, 2024 at 03:53:19PM +0100, Krzysztof Kozlowski wrote:
>> On 15/03/2024 23:27, Wadim Mueller wrote:
>>> Add support for NXP S32 SoC family's GMAC to the stmmac network driver. This driver implementation is based on the patchset originally contributed by Chester Lin [1], which itself draws heavily from NXP's downstream implementation [2]. The patchset was never merged.
>>>
>>> The S32G2/3 SoCs feature multiple Ethernet interfaces (PFE0, PFE1, PFE2, and GMAC) which can be routed through a SerDes Subsystem, supporting various interfaces such as SGMII and RGMII. However, the current Glue Code lacks support for SerDes routing and pinctrl handling, relying solely on correct settings in U-Boot. Clock settings for this SoC are managed by the ATF Firmware.
>>
>>
>> Please run scripts/checkpatch.pl and fix reported warnings. Some
>> warnings can be ignored, but the code here looks like it needs a fix.
>> Feel free to get in touch if the warning is not clear.
>>
>> Read how commit msg should be wrapped.
>>
>> Please wrap commit message according to Linux coding style / submission
>> process (neither too early nor over the limit):
>> https://elixir.bootlin.com/linux/v6.4-rc1/source/Documentation/process/submitting-patches.rst#L597
>>
>>>
>>> Changes made compared to [1]:
>>>
>>>     Rebased onto Linux 6.8-rc7
>>>     Consolidated into a single commit
>>>     Minor adjustments in naming and usage of dev_err()/dev_info()
>>>
>>> Test Environment:
>>> The driver has been successfully tested on the official S32G-VNP-RDB3 Reference Design Board from NXP, utilizing an S32G3 SoC. The firmware and U-Boot used were from the BSP39 Release. The official BSP39 Ubuntu 22.04 Release was successfully booted. A network stress test using iperf [3] was also executed without issues.
>>>
>>> [1] https://patchwork.kernel.org/project/netdevbpf/patch/20221031101052.14956-6-clin@suse.com/#25068228
>>> [2] https://github.com/nxp-auto-linux/linux/blob/release/bsp39.0-5.15.129-rt/drivers/net/ethernet/stmicro/stmmac/dwmac-s32cc.c
>>> [3] https://linux.die.net/man/1/iperf
>>> [4] https://github.com/nxp-auto-linux/u-boot
>>> [5] https://github.com/nxp-auto-linux/arm-trusted-firmware
>>>
>>> Signed-off-by: Wadim Mueller <wafgo01@gmail.com>
>>> ---
>>>  drivers/net/ethernet/stmicro/stmmac/Kconfig   |  12 +
>>>  drivers/net/ethernet/stmicro/stmmac/Makefile  |   1 +
>>
>> That's totally unrelated to DTS. Do not mix independent work in one
>> patchset. This targets net-next, not SoC, so please send it as separate
>> patchset when net-next reopens, so after merge window.
>>
> 
> Let me try to explain why I was thinking that both should be part of the
> same patchset. 
> 
> The DTS file patch [1/3] is refering to a NIC for which there is no
> upstream driver (or lets call it better glue code for the real driver) available. 

That's not valid reason. You only need to mention where the bindings are
for dwmac.

> 
> This patch here is supposed to add support for this driver. So without this part the DT
> node named "gmac0" of [1/3] is not of much use. Thats why I was thinking they

Does not matter. DTS is independent description of hardware. Do you want
to say that without driver support in Linux you could not add the DTS?
No, that's irrelevant.


> should be part of one patchset.
> 
> But your statement also totally makes sense to me.

You unnecessary grow the CC list - it is already way too big (please
trim it to maintainers only and CC lists) - and make applying more
complicated, e.g. suggesting there is some dependency.

DTS *must* go via arm-soc, not net-next, combining it here increases the
risk it will go via wrong tree.


Best regards,
Krzysztof
Jan Petrous March 18, 2024, 7:54 a.m. UTC | #6
> On 17/03/2024 19:26, Jan Petrous (OSS) wrote:
> >> Add support for NXP S32 SoC family's GMAC to the stmmac network driver.
> >> This driver implementation is based on the patchset originally contributed
> by
> >> Chester Lin [1], which itself draws heavily from NXP's downstream
> >> implementation [2]. The patchset was never merged.
> >>
> >
> > Hi Wadim,
> >
> > Thank you for your upstreaming activities, but I would like to note that
> > the old NXP S32CC  stmmac glue was rewritten lately and will be part of next
> > NXP BSP Linux release planned for April.
> >
> > The rework was done mainly to allow simpler upstreaming process, so I
> would recommend
> > to postpone your current work.
> 
> I suggest you working with upstream first instead of claiming that
> upstream contributions should align with your downstream work. To be
> clear: your downstream NXP BSP does not matter.

Thanks for the suggestion. My intention was not to offend somebody
or break any upstreaming work, sorry if it could sound like this. 

> 
> If you think this submission needs any particular changes, then please
> comment on specifics, but such broad statement that community should
> wait till NXP will be so kind to allow upstream work is just not acceptable.
> 

Ok, I will contact Wadim directly.

BR.
/Jan
Andrew Lunn March 18, 2024, 8:50 p.m. UTC | #7
On Fri, Mar 15, 2024 at 11:27:48PM +0100, Wadim Mueller wrote:
> Add support for NXP S32 SoC family's GMAC to the stmmac network driver. This driver implementation is based on the patchset originally contributed by Chester Lin [1], which itself draws heavily from NXP's downstream implementation [2]. The patchset was never merged.

Please wrap you commit message.

 
> +#include <linux/device.h>
> +#include <linux/ethtool.h>

Is this one needed?

> +static int s32_gmac_init(struct platform_device *pdev, void *priv)
> +{
> +	struct s32_priv_data *gmac = priv;
> +	u32 intf_sel;
> +	int ret;
> +
> +	if (gmac->tx_clk) {
> +		ret = clk_prepare_enable(gmac->tx_clk);
> +		if (ret) {
> +			dev_err(&pdev->dev, "Can't set tx clock\n");
> +			return ret;
> +		}
> +	}
> +
> +	if (gmac->rx_clk) {
> +		ret = clk_prepare_enable(gmac->rx_clk);
> +		if (ret) {
> +			dev_err(&pdev->dev, "Can't set rx clock\n");
> +			return ret;
> +		}
> +	}
> +
> +	/* set interface mode */
> +	if (gmac->ctrl_sts) {
> +		switch (gmac->intf_mode) {
> +		default:
> +			dev_info(
> +				&pdev->dev,
> +				"unsupported mode %u, set the default phy mode.\n",
> +				gmac->intf_mode);
> +			fallthrough;

I would actually return -EINVAL. There is no backwards compatibility
needed here, so force that the mode is always specified.

> +		case PHY_INTERFACE_MODE_SGMII:
> +			dev_info(&pdev->dev, "phy mode set to SGMII\n");

Please don't spam the kernel log. dev_dbg(). 

> +static void s32_fix_speed(void *priv, unsigned int speed, unsigned int mode)
> +{
> +	struct s32_priv_data *gmac = priv;
> +
> +	if (!gmac->tx_clk || !gmac->rx_clk)
> +		return;
> +
> +	/* SGMII mode doesn't support the clock reconfiguration */
> +	if (gmac->intf_mode == PHY_INTERFACE_MODE_SGMII)
> +		return;
> +
> +	switch (speed) {
> +	case SPEED_1000:
> +		dev_info(gmac->dev, "Set TX clock to 125M\n");

more dev_dbg(). A driver should generally be silent, unless something
goes wrong. It is also questionable if dev_dbg() should be used. Once
the driver actually works, you can throw away a lot of debug
prints. Do you expect problems here in the future?

> +static int s32_config_cache_coherency(struct platform_device *pdev,
> +				      struct plat_stmmacenet_data *plat_dat)
> +{
> +	plat_dat->axi4_ace_ctrl = devm_kzalloc(
> +		&pdev->dev, sizeof(struct stmmac_axi4_ace_ctrl), GFP_KERNEL);
> +
> +	if (!plat_dat->axi4_ace_ctrl)
> +		return -ENOMEM;
> +
> +	plat_dat->axi4_ace_ctrl->tx_ar_reg = (ACE_CONTROL_SIGNALS << 16) |
> +					     (ACE_CONTROL_SIGNALS << 8) |
> +					     ACE_CONTROL_SIGNALS;
> +
> +	plat_dat->axi4_ace_ctrl->rx_aw_reg =
> +		(ACE_CONTROL_SIGNALS << 24) | (ACE_CONTROL_SIGNALS << 16) |
> +		(ACE_CONTROL_SIGNALS << 8) | ACE_CONTROL_SIGNALS;
> +
> +	plat_dat->axi4_ace_ctrl->txrx_awar_reg =
> +		(ACE_PROTECTION << 20) | (ACE_PROTECTION << 16) |
> +		(ACE_CONTROL_SIGNALS << 8) | ACE_CONTROL_SIGNALS;

This looks like magic. Can the various shifts be replaced my #defines?
Comments added? This makes changes in some of the core code. So it
might be better to have a prerequisite patch adding cache coherency
control, with a good commit message explaining it.

> +
> +	return 0;
> +}
> +
> +static int s32_dwmac_probe(struct platform_device *pdev)
> +{
> +	struct plat_stmmacenet_data *plat_dat;
> +	struct stmmac_resources stmmac_res;
> +	struct s32_priv_data *gmac;
> +	struct resource *res;
> +	const char *tx_clk, *rx_clk;
> +	int ret;
> +
> +	ret = stmmac_get_platform_resources(pdev, &stmmac_res);
> +	if (ret)
> +		return ret;
> +
> +	gmac = devm_kzalloc(&pdev->dev, sizeof(*gmac), GFP_KERNEL);
> +	if (!gmac)
> +		return PTR_ERR(gmac);
> +
> +	gmac->dev = &pdev->dev;
> +
> +	/* S32G control reg */
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +	gmac->ctrl_sts = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR_OR_NULL(gmac->ctrl_sts)) {
> +		dev_err(&pdev->dev, "S32G config region is missing\n");
> +		return PTR_ERR(gmac->ctrl_sts);
> +	}
> +
> +	plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac);
> +	if (IS_ERR(plat_dat))
> +		return PTR_ERR(plat_dat);
> +
> +	plat_dat->bsp_priv = gmac;
> +
> +	switch (plat_dat->phy_interface) {
> +	case PHY_INTERFACE_MODE_SGMII:
> +		tx_clk = "tx_sgmii";
> +		rx_clk = "rx_sgmii";
> +		break;
> +	case PHY_INTERFACE_MODE_RGMII:
> +	case PHY_INTERFACE_MODE_RGMII_ID:
> +	case PHY_INTERFACE_MODE_RGMII_TXID:
> +	case PHY_INTERFACE_MODE_RGMII_RXID:
> +		tx_clk = "tx_rgmii";
> +		rx_clk = "rx_rgmii";
> +		break;
> +	case PHY_INTERFACE_MODE_RMII:
> +		tx_clk = "tx_rmii";
> +		rx_clk = "rx_rmii";
> +		break;
> +	case PHY_INTERFACE_MODE_MII:
> +		tx_clk = "tx_mii";
> +		rx_clk = "rx_mii";
> +		break;
> +	default:
> +		dev_err(&pdev->dev, "Not supported phy interface mode: [%s]\n",
> +			phy_modes(plat_dat->phy_interface));
> +		return -EINVAL;
> +	};
> +
> +	gmac->intf_mode = plat_dat->phy_interface;
> +
> +	/* DMA cache coherency settings */
> +	if (of_dma_is_coherent(pdev->dev.of_node)) {
> +		ret = s32_config_cache_coherency(pdev, plat_dat);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	/* tx clock */
> +	gmac->tx_clk = devm_clk_get(&pdev->dev, tx_clk);
> +	if (IS_ERR(gmac->tx_clk)) {
> +		dev_info(&pdev->dev, "tx clock not found\n");
> +		gmac->tx_clk = NULL;

Is the clock really optional?

I would also print the name of the clock which is missing.

> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -324,6 +324,10 @@ static void stmmac_clk_csr_set(struct stmmac_priv *priv)
>  			priv->clk_csr = STMMAC_CSR_150_250M;
>  		else if ((clk_rate >= CSR_F_250M) && (clk_rate <= CSR_F_300M))
>  			priv->clk_csr = STMMAC_CSR_250_300M;
> +		else if ((clk_rate >= CSR_F_300M) && (clk_rate < CSR_F_500M))
> +			priv->clk_csr = STMMAC_CSR_300_500M;
> +		else if ((clk_rate >= CSR_F_500M) && (clk_rate < CSR_F_800M))
> +			priv->clk_csr = STMMAC_CSR_500_800M;

Also seems like something which could be a patch of its own. Ideally
you want lots of small patches which are obviously correct. Part of
being obviously correct is the commit message, which is easier to
write when the patch is small and only does one thing.

      Andrew
diff mbox series

Patch

diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 85dcda51df05..1cdf2da0251c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -142,6 +142,18 @@  config DWMAC_ROCKCHIP
 	  This selects the Rockchip RK3288 SoC glue layer support for
 	  the stmmac device driver.
 
+config DWMAC_S32
+	tristate "NXP S32 series GMAC support"
+	default ARCH_S32
+	depends on OF && (ARCH_S32 || COMPILE_TEST)
+	select PHYLINK
+	help
+	  Support for ethernet controller on NXP S32 series SOCs.
+
+	  This selects NXP SoC glue layer support for the stmmac
+	  device driver. This driver is used for the S32 series
+	  SOCs GMAC ethernet controller.
+
 config DWMAC_SOCFPGA
 	tristate "SOCFPGA dwmac support"
 	default ARCH_INTEL_SOCFPGA
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index 26cad4344701..c48ff95ed972 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -34,6 +34,7 @@  obj-$(CONFIG_DWMAC_GENERIC)	+= dwmac-generic.o
 obj-$(CONFIG_DWMAC_IMX8)	+= dwmac-imx.o
 obj-$(CONFIG_DWMAC_TEGRA)	+= dwmac-tegra.o
 obj-$(CONFIG_DWMAC_VISCONTI)	+= dwmac-visconti.o
+obj-$(CONFIG_DWMAC_S32)	+= dwmac-s32.o
 stmmac-platform-objs:= stmmac_platform.o
 dwmac-altr-socfpga-objs := dwmac-socfpga.o
 
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 5ba606a596e7..e5e23e8c07e1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -254,6 +254,9 @@  struct stmmac_safety_stats {
 #define CSR_F_150M	150000000
 #define CSR_F_250M	250000000
 #define CSR_F_300M	300000000
+#define CSR_F_500M	500000000
+#define CSR_F_800M	800000000
+
 
 #define	MAC_CSR_H_FRQ_MASK	0x20
 
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-s32.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-s32.c
new file mode 100644
index 000000000000..1920eeed2269
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-s32.c
@@ -0,0 +1,313 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * DWMAC Specific Glue layer for NXP S32 SoCs
+ *
+ * Copyright (C) 2019-2022 NXP
+ * Copyright (C) 2022 SUSE LLC
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/ethtool.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_net.h>
+#include <linux/of_address.h>
+#include <linux/stmmac.h>
+#include "stmmac_platform.h"
+
+#define GMAC_TX_RATE_125M 125000000 /* 125MHz */
+#define GMAC_TX_RATE_25M 25000000 /* 25MHz */
+#define GMAC_TX_RATE_2M5 2500000 /* 2.5MHz */
+
+/* S32 SRC register for phyif selection */
+#define PHY_INTF_SEL_MII 0x00
+#define PHY_INTF_SEL_SGMII 0x01
+#define PHY_INTF_SEL_RGMII 0x02
+#define PHY_INTF_SEL_RMII 0x08
+
+/* AXI4 ACE control settings */
+#define ACE_DOMAIN_SIGNAL 0x2
+#define ACE_CACHE_SIGNAL 0xf
+#define ACE_CONTROL_SIGNALS ((ACE_DOMAIN_SIGNAL << 4) | ACE_CACHE_SIGNAL)
+#define ACE_PROTECTION 0x2
+
+struct s32_priv_data {
+	void __iomem *ctrl_sts;
+	struct device *dev;
+	phy_interface_t intf_mode;
+	struct clk *tx_clk;
+	struct clk *rx_clk;
+};
+
+static int s32_gmac_init(struct platform_device *pdev, void *priv)
+{
+	struct s32_priv_data *gmac = priv;
+	u32 intf_sel;
+	int ret;
+
+	if (gmac->tx_clk) {
+		ret = clk_prepare_enable(gmac->tx_clk);
+		if (ret) {
+			dev_err(&pdev->dev, "Can't set tx clock\n");
+			return ret;
+		}
+	}
+
+	if (gmac->rx_clk) {
+		ret = clk_prepare_enable(gmac->rx_clk);
+		if (ret) {
+			dev_err(&pdev->dev, "Can't set rx clock\n");
+			return ret;
+		}
+	}
+
+	/* set interface mode */
+	if (gmac->ctrl_sts) {
+		switch (gmac->intf_mode) {
+		default:
+			dev_info(
+				&pdev->dev,
+				"unsupported mode %u, set the default phy mode.\n",
+				gmac->intf_mode);
+			fallthrough;
+		case PHY_INTERFACE_MODE_SGMII:
+			dev_info(&pdev->dev, "phy mode set to SGMII\n");
+			intf_sel = PHY_INTF_SEL_SGMII;
+			break;
+		case PHY_INTERFACE_MODE_RGMII:
+		case PHY_INTERFACE_MODE_RGMII_ID:
+		case PHY_INTERFACE_MODE_RGMII_TXID:
+		case PHY_INTERFACE_MODE_RGMII_RXID:
+			dev_info(&pdev->dev, "phy mode set to RGMII\n");
+			intf_sel = PHY_INTF_SEL_RGMII;
+			break;
+		case PHY_INTERFACE_MODE_RMII:
+			dev_info(&pdev->dev, "phy mode set to RMII\n");
+			intf_sel = PHY_INTF_SEL_RMII;
+			break;
+		case PHY_INTERFACE_MODE_MII:
+			dev_info(&pdev->dev, "phy mode set to MII\n");
+			intf_sel = PHY_INTF_SEL_MII;
+			break;
+		}
+
+		writel(intf_sel, gmac->ctrl_sts);
+	}
+
+	return 0;
+}
+
+static void s32_gmac_exit(struct platform_device *pdev, void *priv)
+{
+	struct s32_priv_data *gmac = priv;
+
+	if (gmac->tx_clk)
+		clk_disable_unprepare(gmac->tx_clk);
+
+	if (gmac->rx_clk)
+		clk_disable_unprepare(gmac->rx_clk);
+}
+
+static void s32_fix_speed(void *priv, unsigned int speed, unsigned int mode)
+{
+	struct s32_priv_data *gmac = priv;
+
+	if (!gmac->tx_clk || !gmac->rx_clk)
+		return;
+
+	/* SGMII mode doesn't support the clock reconfiguration */
+	if (gmac->intf_mode == PHY_INTERFACE_MODE_SGMII)
+		return;
+
+	switch (speed) {
+	case SPEED_1000:
+		dev_info(gmac->dev, "Set TX clock to 125M\n");
+		clk_set_rate(gmac->tx_clk, GMAC_TX_RATE_125M);
+		break;
+	case SPEED_100:
+		dev_info(gmac->dev, "Set TX clock to 25M\n");
+		clk_set_rate(gmac->tx_clk, GMAC_TX_RATE_25M);
+		break;
+	case SPEED_10:
+		dev_info(gmac->dev, "Set TX clock to 2.5M\n");
+		clk_set_rate(gmac->tx_clk, GMAC_TX_RATE_2M5);
+		break;
+	default:
+		dev_err(gmac->dev, "Unsupported/Invalid speed: %d\n", speed);
+		return;
+	}
+}
+
+static int s32_config_cache_coherency(struct platform_device *pdev,
+				      struct plat_stmmacenet_data *plat_dat)
+{
+	plat_dat->axi4_ace_ctrl = devm_kzalloc(
+		&pdev->dev, sizeof(struct stmmac_axi4_ace_ctrl), GFP_KERNEL);
+
+	if (!plat_dat->axi4_ace_ctrl)
+		return -ENOMEM;
+
+	plat_dat->axi4_ace_ctrl->tx_ar_reg = (ACE_CONTROL_SIGNALS << 16) |
+					     (ACE_CONTROL_SIGNALS << 8) |
+					     ACE_CONTROL_SIGNALS;
+
+	plat_dat->axi4_ace_ctrl->rx_aw_reg =
+		(ACE_CONTROL_SIGNALS << 24) | (ACE_CONTROL_SIGNALS << 16) |
+		(ACE_CONTROL_SIGNALS << 8) | ACE_CONTROL_SIGNALS;
+
+	plat_dat->axi4_ace_ctrl->txrx_awar_reg =
+		(ACE_PROTECTION << 20) | (ACE_PROTECTION << 16) |
+		(ACE_CONTROL_SIGNALS << 8) | ACE_CONTROL_SIGNALS;
+
+	return 0;
+}
+
+static int s32_dwmac_probe(struct platform_device *pdev)
+{
+	struct plat_stmmacenet_data *plat_dat;
+	struct stmmac_resources stmmac_res;
+	struct s32_priv_data *gmac;
+	struct resource *res;
+	const char *tx_clk, *rx_clk;
+	int ret;
+
+	ret = stmmac_get_platform_resources(pdev, &stmmac_res);
+	if (ret)
+		return ret;
+
+	gmac = devm_kzalloc(&pdev->dev, sizeof(*gmac), GFP_KERNEL);
+	if (!gmac)
+		return PTR_ERR(gmac);
+
+	gmac->dev = &pdev->dev;
+
+	/* S32G control reg */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	gmac->ctrl_sts = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR_OR_NULL(gmac->ctrl_sts)) {
+		dev_err(&pdev->dev, "S32G config region is missing\n");
+		return PTR_ERR(gmac->ctrl_sts);
+	}
+
+	plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac);
+	if (IS_ERR(plat_dat))
+		return PTR_ERR(plat_dat);
+
+	plat_dat->bsp_priv = gmac;
+
+	switch (plat_dat->phy_interface) {
+	case PHY_INTERFACE_MODE_SGMII:
+		tx_clk = "tx_sgmii";
+		rx_clk = "rx_sgmii";
+		break;
+	case PHY_INTERFACE_MODE_RGMII:
+	case PHY_INTERFACE_MODE_RGMII_ID:
+	case PHY_INTERFACE_MODE_RGMII_TXID:
+	case PHY_INTERFACE_MODE_RGMII_RXID:
+		tx_clk = "tx_rgmii";
+		rx_clk = "rx_rgmii";
+		break;
+	case PHY_INTERFACE_MODE_RMII:
+		tx_clk = "tx_rmii";
+		rx_clk = "rx_rmii";
+		break;
+	case PHY_INTERFACE_MODE_MII:
+		tx_clk = "tx_mii";
+		rx_clk = "rx_mii";
+		break;
+	default:
+		dev_err(&pdev->dev, "Not supported phy interface mode: [%s]\n",
+			phy_modes(plat_dat->phy_interface));
+		return -EINVAL;
+	};
+
+	gmac->intf_mode = plat_dat->phy_interface;
+
+	/* DMA cache coherency settings */
+	if (of_dma_is_coherent(pdev->dev.of_node)) {
+		ret = s32_config_cache_coherency(pdev, plat_dat);
+		if (ret)
+			return ret;
+	}
+
+	/* tx clock */
+	gmac->tx_clk = devm_clk_get(&pdev->dev, tx_clk);
+	if (IS_ERR(gmac->tx_clk)) {
+		dev_info(&pdev->dev, "tx clock not found\n");
+		gmac->tx_clk = NULL;
+	}
+
+	/* rx clock */
+	gmac->rx_clk = devm_clk_get(&pdev->dev, rx_clk);
+	if (IS_ERR(gmac->rx_clk)) {
+		dev_info(&pdev->dev, "rx clock not found\n");
+		gmac->rx_clk = NULL;
+	}
+
+	ret = s32_gmac_init(pdev, gmac);
+	if (ret)
+		return ret;
+
+	/* core feature set */
+	plat_dat->has_gmac4 = true;
+	plat_dat->pmt = 1;
+
+	plat_dat->init = s32_gmac_init;
+	plat_dat->exit = s32_gmac_exit;
+	plat_dat->fix_mac_speed = s32_fix_speed;
+
+	/* safety feature config */
+	plat_dat->safety_feat_cfg = devm_kzalloc(
+		&pdev->dev, sizeof(*plat_dat->safety_feat_cfg), GFP_KERNEL);
+
+	if (!plat_dat->safety_feat_cfg) {
+		dev_err(&pdev->dev, "allocate safety_feat_cfg failed\n");
+		goto err_gmac_exit;
+	}
+
+	plat_dat->safety_feat_cfg->tsoee = 1;
+	plat_dat->safety_feat_cfg->mrxpee = 1;
+	plat_dat->safety_feat_cfg->mestee = 1;
+	plat_dat->safety_feat_cfg->mrxee = 1;
+	plat_dat->safety_feat_cfg->mtxee = 1;
+	plat_dat->safety_feat_cfg->epsi = 1;
+	plat_dat->safety_feat_cfg->edpp = 1;
+	plat_dat->safety_feat_cfg->prtyen = 1;
+	plat_dat->safety_feat_cfg->tmouten = 1;
+
+	ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+	if (ret)
+		goto err_gmac_exit;
+
+	return 0;
+
+err_gmac_exit:
+	s32_gmac_exit(pdev, plat_dat->bsp_priv);
+	return ret;
+}
+
+static const struct of_device_id s32_dwmac_match[] = {
+	{ .compatible = "nxp,s32-dwmac" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, s32_dwmac_match);
+
+static struct platform_driver s32_dwmac_driver = {
+	.probe  = s32_dwmac_probe,
+	.remove_new = stmmac_pltfr_remove,
+	.driver = {
+		.name           = "s32-dwmac",
+		.pm		= &stmmac_pltfr_pm_ops,
+		.of_match_table = s32_dwmac_match,
+	},
+};
+module_platform_driver(s32_dwmac_driver);
+
+MODULE_AUTHOR("Jan Petrous <jan.petrous@nxp.com>");
+MODULE_DESCRIPTION("NXP S32 GMAC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
index 84d3a8551b03..edb559c36509 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
@@ -556,6 +556,14 @@  static int dwmac4_enable_tbs(struct stmmac_priv *priv, void __iomem *ioaddr,
 	return 0;
 }
 
+static void dwmac4_set_axi4_cc(struct stmmac_priv *priv, void __iomem *ioaddr,
+			   struct stmmac_axi4_ace_ctrl *acecfg)
+{
+	writel(acecfg->tx_ar_reg, ioaddr + DMA_AXI4_TX_AR_ACE_CONTROL);
+	writel(acecfg->rx_aw_reg, ioaddr + DMA_AXI4_RX_AW_ACE_CONTROL);
+	writel(acecfg->txrx_awar_reg, ioaddr + DMA_AXI4_TXRX_AWAR_ACE_CONTROL);
+}
+
 const struct stmmac_dma_ops dwmac4_dma_ops = {
 	.reset = dwmac4_dma_reset,
 	.init = dwmac4_dma_init,
@@ -608,6 +616,7 @@  const struct stmmac_dma_ops dwmac410_dma_ops = {
 	.set_tx_ring_len = dwmac4_set_tx_ring_len,
 	.set_rx_tail_ptr = dwmac4_set_rx_tail_ptr,
 	.set_tx_tail_ptr = dwmac4_set_tx_tail_ptr,
+	.set_axi4_cc = dwmac4_set_axi4_cc,
 	.enable_tso = dwmac4_enable_tso,
 	.qmode = dwmac4_qmode,
 	.set_bfsize = dwmac4_set_bfsize,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h
index 358e7dcb6a9a..7195c643774f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h
@@ -22,6 +22,9 @@ 
 #define DMA_DEBUG_STATUS_1		0x00001010
 #define DMA_DEBUG_STATUS_2		0x00001014
 #define DMA_AXI_BUS_MODE		0x00001028
+#define DMA_AXI4_TX_AR_ACE_CONTROL	0x00001020
+#define DMA_AXI4_RX_AW_ACE_CONTROL	0x00001024
+#define DMA_AXI4_TXRX_AWAR_ACE_CONTROL	0x00001028
 #define DMA_TBS_CTRL			0x00001050
 
 /* DMA Bus Mode bitmap */
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
index 7be04b54738b..6ea2d8f562d0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -227,6 +227,9 @@  struct stmmac_dma_ops {
 				u32 tail_ptr, u32 chan);
 	void (*set_tx_tail_ptr)(struct stmmac_priv *priv, void __iomem *ioaddr,
 				u32 tail_ptr, u32 chan);
+    	/* Configure AXI4 cache coherency for Tx and Rx DMA channels */
+        void (*set_axi4_cc)(struct stmmac_priv *priv, void __iomem *ioaddr,
+			   struct stmmac_axi4_ace_ctrl *acecfg);
 	void (*enable_tso)(struct stmmac_priv *priv, void __iomem *ioaddr,
 			   bool en, u32 chan);
 	void (*qmode)(struct stmmac_priv *priv, void __iomem *ioaddr,
@@ -285,6 +288,8 @@  struct stmmac_dma_ops {
 	stmmac_do_void_callback(__priv, dma, set_rx_tail_ptr, __priv, __args)
 #define stmmac_set_tx_tail_ptr(__priv, __args...) \
 	stmmac_do_void_callback(__priv, dma, set_tx_tail_ptr, __priv, __args)
+#define stmmac_set_axi4_cc(__priv, __args...) \
+        stmmac_do_void_callback(__priv, dma, set_axi4_cc, __priv, __args)
 #define stmmac_enable_tso(__priv, __args...) \
 	stmmac_do_void_callback(__priv, dma, enable_tso, __priv, __args)
 #define stmmac_dma_qmode(__priv, __args...) \
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 7c6aef033a45..b7b4d7dd1149 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -324,6 +324,10 @@  static void stmmac_clk_csr_set(struct stmmac_priv *priv)
 			priv->clk_csr = STMMAC_CSR_150_250M;
 		else if ((clk_rate >= CSR_F_250M) && (clk_rate <= CSR_F_300M))
 			priv->clk_csr = STMMAC_CSR_250_300M;
+		else if ((clk_rate >= CSR_F_300M) && (clk_rate < CSR_F_500M))
+			priv->clk_csr = STMMAC_CSR_300_500M;
+		else if ((clk_rate >= CSR_F_500M) && (clk_rate < CSR_F_800M))
+			priv->clk_csr = STMMAC_CSR_500_800M;
 	}
 
 	if (priv->plat->flags & STMMAC_FLAG_HAS_SUN8I) {
@@ -3030,6 +3034,9 @@  static int stmmac_init_dma_engine(struct stmmac_priv *priv)
 	if (priv->plat->axi)
 		stmmac_axi(priv, priv->ioaddr, priv->plat->axi);
 
+	if (priv->plat->axi4_ace_ctrl)
+		stmmac_set_axi4_cc(priv, priv->ioaddr, priv->plat->axi4_ace_ctrl);
+
 	/* DMA CSR Channel configuration */
 	for (chan = 0; chan < dma_csr_ch; chan++) {
 		stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index dee5ad6e48c5..a69ac8b9274e 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -34,6 +34,8 @@ 
 #define	STMMAC_CSR_35_60M	0x3	/* MDC = clk_scr_i/26 */
 #define	STMMAC_CSR_150_250M	0x4	/* MDC = clk_scr_i/102 */
 #define	STMMAC_CSR_250_300M	0x5	/* MDC = clk_scr_i/122 */
+#define	STMMAC_CSR_300_500M	0x6	/* MDC = clk_scr_i/204 */
+#define	STMMAC_CSR_500_800M	0x7	/* MDC = clk_scr_i/324 */
 
 /* MTL algorithms identifiers */
 #define MTL_TX_ALGORITHM_WRR	0x0
@@ -115,6 +117,12 @@  struct stmmac_axi {
 	bool axi_rb;
 };
 
+struct stmmac_axi4_ace_ctrl {
+	u32 tx_ar_reg;
+	u32 rx_aw_reg;
+	u32 txrx_awar_reg;
+};
+
 #define EST_GCL		1024
 struct stmmac_est {
 	struct mutex lock;
@@ -296,6 +304,7 @@  struct plat_stmmacenet_data {
 	struct reset_control *stmmac_rst;
 	struct reset_control *stmmac_ahb_rst;
 	struct stmmac_axi *axi;
+	struct stmmac_axi4_ace_ctrl *axi4_ace_ctrl;
 	int has_gmac4;
 	int rss_en;
 	int mac_port_sel_speed;