From: Chester Lin <clin@suse.com>
To: Giuseppe Cavallaro <peppe.cavallaro@st.com>,
Alexandre Torgue <alexandre.torgue@foss.st.com>,
Jose Abreu <joabreu@synopsys.com>
Cc: "Chester Lin" <clin@suse.com>,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
"David S. Miller" <davem@davemloft.net>,
"Eric Dumazet" <edumazet@google.com>,
"Jakub Kicinski" <kuba@kernel.org>,
"Paolo Abeni" <pabeni@redhat.com>,
"Jan Petrous" <jan.petrous@nxp.com>,
"Ondrej Spacek" <ondrej.spacek@nxp.com>,
"Ghennadi Procopciuc" <Ghennadi.Procopciuc@nxp.com>,
"Andra-Teodora Ilie" <andra.ilie@nxp.com>,
"Andreas Färber" <afaerber@suse.de>,
"Matthias Brugger" <mbrugger@suse.com>
Subject: [PATCH 5/5] net: stmmac: Add NXP S32 SoC family support
Date: Mon, 31 Oct 2022 18:10:52 +0800 [thread overview]
Message-ID: <20221031101052.14956-6-clin@suse.com> (raw)
In-Reply-To: <20221031101052.14956-1-clin@suse.com>
Add GMAC support for NXP S32 SoC family. This driver is mainly based on
NXP's downstream implementation on CodeAurora[1].
[1] https://source.codeaurora.org/external/autobsps32/linux/tree/drivers/net/ethernet/stmicro/stmmac?h=bsp34.0-5.10.120-rt
Signed-off-by: Jan Petrous <jan.petrous@nxp.com>
Signed-off-by: Ghennadi Procopciuc <Ghennadi.Procopciuc@nxp.com>
Signed-off-by: Andra-Teodora Ilie <andra.ilie@nxp.com>
Signed-off-by: Chester Lin <clin@suse.com>
---
drivers/net/ethernet/stmicro/stmmac/Kconfig | 13 +
drivers/net/ethernet/stmicro/stmmac/Makefile | 1 +
.../net/ethernet/stmicro/stmmac/dwmac-s32cc.c | 318 ++++++++++++++++++
3 files changed, 332 insertions(+)
create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-s32cc.c
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 31ff35174034..dd3fb5e462b7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -153,6 +153,19 @@ config DWMAC_ROCKCHIP
This selects the Rockchip RK3288 SoC glue layer support for
the stmmac device driver.
+config DWMAC_S32CC
+ tristate "NXP S32 series GMAC support"
+ default ARCH_S32
+ depends on OF && (ARCH_S32 || COMPILE_TEST)
+ select MFD_SYSCON
+ 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 d4e12e9ace4f..ec92cc2becd7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_DWMAC_INTEL_PLAT) += dwmac-intel-plat.o
obj-$(CONFIG_DWMAC_GENERIC) += dwmac-generic.o
obj-$(CONFIG_DWMAC_IMX8) += dwmac-imx.o
obj-$(CONFIG_DWMAC_VISCONTI) += dwmac-visconti.o
+obj-$(CONFIG_DWMAC_S32CC) += dwmac-s32cc.o
stmmac-platform-objs:= stmmac_platform.o
dwmac-altr-socfpga-objs := altr_tse_pcs.o dwmac-socfpga.o
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-s32cc.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-s32cc.c
new file mode 100644
index 000000000000..ac274cdfbe22
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-s32cc.c
@@ -0,0 +1,318 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * DWMAC Specific Glue layer for NXP S32 Common Chassis
+ *
+ * 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 s32cc_priv_data {
+ void __iomem *ctrl_sts;
+ struct device *dev;
+ phy_interface_t intf_mode;
+ struct clk *tx_clk;
+ struct clk *rx_clk;
+};
+
+static int s32cc_gmac_init(struct platform_device *pdev, void *priv)
+{
+ struct s32cc_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 s32cc_gmac_exit(struct platform_device *pdev, void *priv)
+{
+ struct s32cc_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 s32cc_fix_speed(void *priv, unsigned int speed)
+{
+ struct s32cc_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 s32cc_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) {
+ dev_info(&pdev->dev, "Fail to allocate axi4_ace_ctrl\n");
+ 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 s32cc_dwmac_probe(struct platform_device *pdev)
+{
+ struct plat_stmmacenet_data *plat_dat;
+ struct stmmac_resources stmmac_res;
+ struct s32cc_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, "S32CC config region is missing\n");
+ return PTR_ERR(gmac->ctrl_sts);
+ }
+
+ plat_dat = 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 = s32cc_config_cache_coherency(pdev, plat_dat);
+ if (ret)
+ goto err_remove_config_dt;
+ }
+
+ /* 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 = s32cc_gmac_init(pdev, gmac);
+ if (ret)
+ goto err_remove_config_dt;
+
+ /* core feature set */
+ plat_dat->has_gmac4 = true;
+ plat_dat->pmt = 1;
+
+ plat_dat->init = s32cc_gmac_init;
+ plat_dat->exit = s32cc_gmac_exit;
+ plat_dat->fix_mac_speed = s32cc_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_info(&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:
+ s32cc_gmac_exit(pdev, plat_dat->bsp_priv);
+err_remove_config_dt:
+ stmmac_remove_config_dt(pdev, plat_dat);
+ return ret;
+}
+
+static const struct of_device_id s32_dwmac_match[] = {
+ { .compatible = "nxp,s32cc-dwmac" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, s32_dwmac_match);
+
+static struct platform_driver s32_dwmac_driver = {
+ .probe = s32cc_dwmac_probe,
+ .remove = stmmac_pltfr_remove,
+ .driver = {
+ .name = "s32cc-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 common chassis GMAC driver");
+MODULE_LICENSE("GPL v2");
--
2.37.3
next prev parent reply other threads:[~2022-10-31 10:12 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-10-31 10:10 [PATCH 0/5] Add GMAC support for S32 SoC family Chester Lin
2022-10-31 10:10 ` [PATCH 1/5] dt-bindings: net: snps, dwmac: add NXP S32CC support Chester Lin
2022-10-31 10:10 ` [PATCH 2/5] dt-bindings: net: add schema for NXP S32CC dwmac glue driver Chester Lin
2022-11-02 15:55 ` Rob Herring
2022-11-02 17:13 ` Andreas Färber
2022-11-02 21:44 ` Rob Herring
2022-11-04 10:11 ` Chester Lin
2022-11-03 22:05 ` Andrew Lunn
2022-11-04 11:39 ` Chester Lin
2022-11-04 13:30 ` Andrew Lunn
2022-11-09 8:09 ` Chester Lin
2022-11-09 22:55 ` [EXT] " Jan Petrous
2022-11-09 23:00 ` Andrew Lunn
2022-11-10 8:51 ` Jan Petrous
2022-11-10 13:04 ` Andrew Lunn
2022-11-09 22:55 ` Jan Petrous
2022-10-31 10:10 ` [PATCH 3/5] net: stmmac: Add CSR clock 500Mhz/800Mhz support Chester Lin
2022-10-31 10:10 ` [PATCH 4/5] net: stmmac: Add AXI4 ACE control support Chester Lin
2022-10-31 10:10 ` Chester Lin [this message]
2022-10-31 13:27 ` [PATCH 5/5] net: stmmac: Add NXP S32 SoC family support Andrew Lunn
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20221031101052.14956-6-clin@suse.com \
--to=clin@suse.com \
--cc=Ghennadi.Procopciuc@nxp.com \
--cc=afaerber@suse.de \
--cc=alexandre.torgue@foss.st.com \
--cc=andra.ilie@nxp.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=jan.petrous@nxp.com \
--cc=joabreu@synopsys.com \
--cc=kuba@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mbrugger@suse.com \
--cc=netdev@vger.kernel.org \
--cc=ondrej.spacek@nxp.com \
--cc=pabeni@redhat.com \
--cc=peppe.cavallaro@st.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).