ALT Linux kernel packages development
 help / color / mirror / Atom feed
From: Daniil Gnusarev <gnusarevda@basealt.ru>
To: devel-kernel@lists.altlinux.org
Subject: [d-kernel] [PATCH 10/39] net: stmmac: support of Baikal-BE1000 SoCs GMAC
Date: Mon, 14 Oct 2024 18:01:51 +0400
Message-ID: <20241014140221.535985-11-gnusarevda@basealt.ru> (raw)
In-Reply-To: <20241014140221.535985-1-gnusarevda@basealt.ru>

The Gigabit Ethernet Controller available in the Baikal-M
SoC is a Synopsys DesignWare MAC IP core, already supported
by the stmmac driver. This add Baikal Electronics DWMAC specific glue layer.

Signed-off-by: Daniil Gnusarev <gnusarevda@basealt.ru>
Co-developed-by: Dmitry Dunaev <dmitry.dunaev@baikalelectronics.ru>
Co-developed-by: Alexey Sheplyakov <asheplyakov@basealt.ru>
---
 drivers/net/ethernet/stmicro/stmmac/Kconfig   |   8 +
 drivers/net/ethernet/stmicro/stmmac/Makefile  |   1 +
 .../ethernet/stmicro/stmmac/dwmac-baikal.c    | 542 ++++++++++++++++++
 .../ethernet/stmicro/stmmac/dwmac1000_core.c  |   1 +
 .../ethernet/stmicro/stmmac/dwmac1000_dma.c   |  56 +-
 .../ethernet/stmicro/stmmac/dwmac1000_dma.h   |  32 ++
 .../net/ethernet/stmicro/stmmac/dwmac_lib.c   |   8 +
 net/ethernet/eth.c                            |   1 +
 8 files changed, 626 insertions(+), 23 deletions(-)
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-baikal.c
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.h

diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 92d7d5a00b84c..34ea1d065fb72 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -66,6 +66,14 @@ config DWMAC_ANARION
 
 	  This selects the Anarion SoC glue layer support for the stmmac driver.
 
+config DWMAC_BAIKAL
+	tristate "Baikal Electronics DWMAC support"
+	depends on OF
+	help
+	  Support for Baikal Electronics DWMAC Ethernet.
+
+	  This selects the Baikal SoC glue layer support for the stmmac driver.
+
 config DWMAC_INGENIC
 	tristate "Ingenic MAC support"
 	default MACH_INGENIC
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index 5b57aee19267f..7c39c5a4b4d6f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -14,6 +14,7 @@ stmmac-$(CONFIG_STMMAC_SELFTESTS) += stmmac_selftests.o
 # Ordering matters. Generic driver must be last.
 obj-$(CONFIG_STMMAC_PLATFORM)	+= stmmac-platform.o
 obj-$(CONFIG_DWMAC_ANARION)	+= dwmac-anarion.o
+obj-$(CONFIG_DWMAC_BAIKAL)	+= dwmac-baikal.o
 obj-$(CONFIG_DWMAC_INGENIC)	+= dwmac-ingenic.o
 obj-$(CONFIG_DWMAC_IPQ806X)	+= dwmac-ipq806x.o
 obj-$(CONFIG_DWMAC_LPC18XX)	+= dwmac-lpc18xx.o
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-baikal.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-baikal.c
new file mode 100644
index 0000000000000..a9a66068b3f65
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-baikal.c
@@ -0,0 +1,542 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Baikal Electronics DWMAC specific glue layer
+ *
+ * Copyright (C) 2015-2022 Baikal Electronics, JSC
+ * Authors: Dmitry Dunaev <dmitry.dunaev@baikalelectronics.ru>
+ *          Alexey Sheplyakov <asheplyakov@altlinux.org>
+ */
+
+#include <linux/acpi.h>
+#include <linux/arm-smccc.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/gpio/consumer.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "stmmac.h"
+#include "stmmac_platform.h"
+#include "common.h"
+#include "dwmac_dma.h"
+#include "dwmac1000_dma.h"
+
+#define MAC_GPIO	0x00e0		/* GPIO register */
+#define MAC_GPIO_GPO	(1 << 8)	/* Output port */
+
+#define BAIKAL_SMC_GMAC_DIV2_ENABLE	0xC2000500
+#define BAIKAL_SMC_GMAC_DIV2_DISABLE	0xC2000501
+
+struct baikal_gmac {
+	struct device	*dev;
+	uint64_t	base;
+	struct clk	*axi_clk;
+	struct clk	*tx2_clk;
+	int		has_aux_div2;
+	bool		is_fixed_stmmac_clk;
+};
+
+static int baikal_gmac_dma_reset(void __iomem *ioaddr)
+{
+	int err;
+	u32 value;
+
+	/* DMA SW reset */
+	value = readl(ioaddr + DMA_BUS_MODE);
+	value |= DMA_BUS_MODE_SFT_RESET;
+	writel(value, ioaddr + DMA_BUS_MODE);
+
+	/* Software DMA reset also resets MAC, so GP_OUT is set to zero.
+	 * Which resets PHY as a side effect (if GP_OUT is connected directly
+	 * to PHY reset).
+	 * TODO: read the PHY reset duration from the device tree.
+	 * Meanwhile use 100 milliseconds which seems to be enough for
+	 * most PHYs
+	 */
+	usleep_range(100000, 120000);
+
+	/* Clear PHY reset */
+	value = readl(ioaddr + MAC_GPIO);
+	value |= MAC_GPIO_GPO;
+	writel(value, ioaddr + MAC_GPIO);
+
+	/* Many PHYs need ~100 milliseconds to calm down after PHY reset
+	 * has been cleared. And check for DMA reset below might return
+	 * much earlier (i.e. in ~20 milliseconds). As a result reading
+	 * PHY registers (after this function returns) might return garbage.
+	 * Wait a bit to avoid the problem.
+	 */
+	usleep_range(100000, 150000);
+
+	err = readl_poll_timeout(ioaddr + DMA_BUS_MODE, value,
+				 !(value & DMA_BUS_MODE_SFT_RESET),
+				 10000, 1000000);
+	if (err) {
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+static const struct stmmac_dma_ops baikal_gmac_dma_ops = {
+	.reset = baikal_gmac_dma_reset,
+	.init = dwmac1000_dma_init,
+	.init_rx_chan = dwmac1000_dma_init_rx,
+	.init_tx_chan = dwmac1000_dma_init_tx,
+	.axi = dwmac1000_dma_axi,
+	.dump_regs = dwmac1000_dump_dma_regs,
+	.dma_rx_mode = dwmac1000_dma_operation_mode_rx,
+	.dma_tx_mode = dwmac1000_dma_operation_mode_tx,
+	.enable_dma_transmission = dwmac_enable_dma_transmission,
+	.enable_dma_irq = dwmac_enable_dma_irq,
+	.disable_dma_irq = dwmac_disable_dma_irq,
+	.start_tx = dwmac_dma_start_tx,
+	.stop_tx = dwmac_dma_stop_tx,
+	.start_rx = dwmac_dma_start_rx,
+	.stop_rx = dwmac_dma_stop_rx,
+	.dma_interrupt = dwmac_dma_interrupt,
+	.get_hw_feature = dwmac1000_get_hw_feature,
+	.rx_watchdog = dwmac1000_rx_watchdog
+};
+
+static struct mac_device_info *baikal_gmac_setup(void *ppriv)
+{
+	struct mac_device_info *mac, *old_mac;
+	struct stmmac_priv *priv = ppriv;
+	struct gpio_desc *reset_gpio;
+	int err;
+	u32 value;
+
+	mac = devm_kzalloc(priv->device, sizeof(*mac), GFP_KERNEL);
+	if (!mac) {
+		return NULL;
+	}
+
+	/* Clear PHY reset */
+	value = readl(priv->ioaddr + MAC_GPIO);
+	value |= MAC_GPIO_GPO;
+	writel(value, priv->ioaddr + MAC_GPIO);
+	reset_gpio = devm_gpiod_get_optional(priv->device,
+					     "snps,reset",
+					     GPIOD_OUT_LOW);
+
+	err = readl_poll_timeout(priv->ioaddr + DMA_BUS_MODE, value,
+				 !(value & DMA_BUS_MODE_SFT_RESET),
+				 10000, 1000000);
+
+	if (reset_gpio != NULL) {
+		devm_gpiod_put(priv->device, reset_gpio);
+	}
+
+	if (err) {
+		dev_err(priv->device, "SW reset is not cleared: error %d", err);
+		return NULL;
+	}
+
+	mac->dma = &baikal_gmac_dma_ops;
+	old_mac = priv->hw;
+	priv->hw = mac;
+	err = dwmac1000_setup(priv);
+	priv->hw = old_mac;
+	if (err) {
+		dev_err(priv->device,
+			"%s: dwmac1000_setup failed with error %d",
+			__func__, err);
+		return NULL;
+	}
+
+	return mac;
+}
+
+static void baikal_gmac_fix_mac_speed(void *priv, unsigned int speed,
+				      unsigned int mode)
+{
+	struct arm_smccc_res res;
+	struct baikal_gmac *gmac = priv;
+	unsigned long tx2_clk_freq = 0;
+
+	switch (speed) {
+	case SPEED_1000:
+		tx2_clk_freq = 250000000;
+		if (gmac->has_aux_div2) {
+			arm_smccc_smc(BAIKAL_SMC_GMAC_DIV2_DISABLE,
+				      gmac->base, 0, 0, 0, 0, 0, 0, &res);
+		}
+		break;
+	case SPEED_100:
+		tx2_clk_freq = 50000000;
+		if (gmac->has_aux_div2) {
+			arm_smccc_smc(BAIKAL_SMC_GMAC_DIV2_DISABLE,
+				      gmac->base, 0, 0, 0, 0, 0, 0, &res);
+		}
+		break;
+	case SPEED_10:
+		tx2_clk_freq = 5000000;
+		if (gmac->has_aux_div2) {
+			tx2_clk_freq *= 2;
+			arm_smccc_smc(BAIKAL_SMC_GMAC_DIV2_ENABLE,
+				      gmac->base, 0, 0, 0, 0, 0, 0, &res);
+		}
+		break;
+	}
+
+	if (gmac->tx2_clk != NULL && tx2_clk_freq) {
+		clk_set_rate(gmac->tx2_clk, tx2_clk_freq);
+	}
+}
+
+#ifdef CONFIG_ACPI
+static struct plat_stmmacenet_data *baikal_stmmac_probe_config(struct device *dev,
+							       const char **mac,
+							       bool *is_fixed_stmmac_clk)
+{
+	struct plat_stmmacenet_data *plat_dat;
+	u8 nvmem_mac[ETH_ALEN];
+	int ret;
+	bool is_fixed_clk = false;
+
+	plat_dat = devm_kzalloc(dev, sizeof(*plat_dat), GFP_KERNEL);
+	if (!plat_dat) {
+		return ERR_PTR(-ENOMEM);
+	}
+
+	ret = nvmem_get_mac_address(dev, &nvmem_mac);
+	if (ret) {
+		if (ret == -EPROBE_DEFER) {
+			return ERR_PTR(ret);
+		}
+
+		*mac = NULL;
+	} else {
+		*mac = devm_kmemdup(dev, nvmem_mac, ETH_ALEN, GFP_KERNEL);
+	}
+
+	plat_dat->phy_interface = device_get_phy_mode(dev);
+	if (plat_dat->phy_interface < 0) {
+		return NULL;
+	}
+
+	plat_dat->mac_interface = plat_dat->phy_interface;
+
+	if (device_property_read_u32(dev, "max-speed", &plat_dat->max_speed)) {
+		plat_dat->max_speed = -1;
+	}
+
+	plat_dat->bus_id = ACPI_COMPANION(dev)->pnp.instance_no;
+
+	ret = device_property_read_u32(dev, "reg", &plat_dat->phy_addr);
+	if (ret) {
+		dev_err(dev, "couldn't get reg property\n");
+		return ERR_PTR(ret);
+	}
+
+	if (plat_dat->phy_addr >= PHY_MAX_ADDR) {
+		dev_err(dev, "PHY address %i is too large\n",
+				plat_dat->phy_addr);
+		return ERR_PTR(-EINVAL);
+	}
+
+	plat_dat->mdio_bus_data = devm_kzalloc(dev,
+						sizeof(*plat_dat->mdio_bus_data),
+						GFP_KERNEL);
+	if (!plat_dat->mdio_bus_data) {
+		return ERR_PTR(-ENOMEM);
+	}
+
+	plat_dat->mdio_bus_data->needs_reset = true;
+	plat_dat->maxmtu = JUMBO_LEN;
+	plat_dat->multicast_filter_bins = HASH_TABLE_SIZE;
+	plat_dat->unicast_filter_entries = 1;
+	plat_dat->bugged_jumbo = 1; /* TODO: is it really required? */
+
+	plat_dat->dma_cfg = devm_kzalloc(dev,
+					sizeof(*plat_dat->dma_cfg),
+					GFP_KERNEL);
+	if (!plat_dat->dma_cfg) {
+		return ERR_PTR(-ENOMEM);
+	}
+
+	plat_dat->dma_cfg->pbl = DEFAULT_DMA_PBL;
+	device_property_read_u32(dev, "snps,txpbl", &plat_dat->dma_cfg->txpbl);
+	device_property_read_u32(dev, "snps,rxpbl", &plat_dat->dma_cfg->rxpbl);
+	plat_dat->dma_cfg->fixed_burst = device_property_read_bool(dev,
+							"snps,fixed-burst");
+
+	plat_dat->axi = devm_kzalloc(dev, sizeof(*plat_dat->axi), GFP_KERNEL);
+	if (!plat_dat->axi) {
+		return ERR_PTR(-ENOMEM);
+	}
+
+	device_property_read_u32_array(dev, "snps,blen",
+					plat_dat->axi->axi_blen, AXI_BLEN);
+
+	plat_dat->rx_queues_to_use = 1;
+	plat_dat->tx_queues_to_use = 1;
+	plat_dat->rx_queues_cfg[0].mode_to_use = MTL_QUEUE_DCB;
+	plat_dat->tx_queues_cfg[0].mode_to_use = MTL_QUEUE_DCB;
+
+	if (device_property_read_u32(dev, "stmmac-clk", &plat_dat->clk_ptp_rate)) {
+		plat_dat->clk_ptp_rate = 50000000;
+	}
+
+	plat_dat->stmmac_clk = devm_clk_get(dev, STMMAC_RESOURCE_NAME);
+	if (IS_ERR(plat_dat->stmmac_clk)) {
+		if (!plat_dat->clk_ptp_rate) {
+			dev_err(dev, "stmmaceth clock and 'stmmac-clk' property are missed simultaneously\n");
+			return ERR_PTR(-EINVAL);
+		}
+
+		plat_dat->stmmac_clk = clk_register_fixed_rate(NULL,
+							dev_name(dev), NULL, 0,
+							plat_dat->clk_ptp_rate);
+		if (IS_ERR(plat_dat->stmmac_clk))
+			return ERR_CAST(plat_dat->stmmac_clk);
+
+		is_fixed_clk = true;
+	} else {
+		if (!plat_dat->clk_ptp_rate)
+			plat_dat->clk_ptp_rate = clk_get_rate(plat_dat->stmmac_clk);
+	}
+
+	plat_dat->clk_ptp_ref = devm_clk_get(dev, "ptp_ref");
+	if (IS_ERR(plat_dat->clk_ptp_ref)) {
+		plat_dat->clk_ptp_ref = NULL;
+	} else {
+		plat_dat->clk_ptp_rate = clk_get_rate(plat_dat->clk_ptp_ref);
+	}
+
+	clk_prepare_enable(plat_dat->stmmac_clk);
+
+	plat_dat->stmmac_rst = devm_reset_control_get(dev,
+						      STMMAC_RESOURCE_NAME);
+	if (IS_ERR(plat_dat->stmmac_rst))
+		plat_dat->stmmac_rst = NULL;
+
+	plat_dat->mdio_bus_data->phy_mask = ~0;
+
+	if (device_get_child_node_count(dev) != 1) {
+		clk_disable_unprepare(plat_dat->stmmac_clk);
+		if (is_fixed_clk)
+			clk_unregister_fixed_rate(plat_dat->stmmac_clk);
+		return ERR_PTR(-EINVAL);
+	}
+
+	*is_fixed_stmmac_clk = is_fixed_clk;
+
+	return plat_dat;
+}
+
+static int baikal_add_mdio_phy(struct device *dev)
+{
+	struct stmmac_priv *priv = netdev_priv(dev_get_drvdata(dev));
+	struct fwnode_handle *fwnode = device_get_next_child_node(dev, NULL);
+	struct phy_device *phy;
+	int ret;
+
+	phy = get_phy_device(priv->mii, priv->plat->phy_addr, 0);
+	if (IS_ERR(phy)) {
+		return PTR_ERR(phy);
+	}
+
+	phy->irq = priv->mii->irq[priv->plat->phy_addr];
+	phy->mdio.dev.fwnode = fwnode;
+
+	ret = phy_device_register(phy);
+	if (ret) {
+		phy_device_free(phy);
+		return ret;
+	}
+
+	return 0;
+}
+#else
+static struct plat_stmmacenet_data *baikal_stmmac_probe_config(struct device *dev,
+							       const char **mac,
+							       bool *is_fixed_stmmac_clk)
+{
+	return NULL;
+}
+
+static int baikal_add_mdio_phy(struct device *dev)
+{
+	return 0;
+}
+#endif
+
+static int baikal_gmac_probe(struct platform_device *pdev)
+{
+	struct plat_stmmacenet_data *plat_dat;
+	struct stmmac_resources stmmac_res;
+	struct resource *res;
+	struct baikal_gmac *gmac;
+	struct device_node *dn = NULL;
+	const char *str = NULL;
+	bool is_fixed_stmmac_clk = false;
+	int ret;
+
+	if (acpi_disabled) {
+		ret = stmmac_get_platform_resources(pdev, &stmmac_res);
+		if (ret) {
+			return ret;
+		}
+	} else {
+		memset(&stmmac_res, 0, sizeof(stmmac_res));
+		stmmac_res.irq = platform_get_irq(pdev, 0);
+		if (stmmac_res.irq < 0) {
+			return stmmac_res.irq;
+		}
+
+		stmmac_res.wol_irq = stmmac_res.irq;
+		stmmac_res.addr = devm_platform_ioremap_resource(pdev, 0);
+		if (IS_ERR(stmmac_res.addr)) {
+			return PTR_ERR(stmmac_res.addr);
+		}
+	}
+
+	ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+	if (ret) {
+		dev_warn(&pdev->dev, "no suitable DMA available\n");
+		return ret;
+	}
+
+	if (pdev->dev.of_node) {
+		plat_dat = stmmac_probe_config_dt(pdev, (u8 *)&stmmac_res.mac);
+		if (IS_ERR(plat_dat)) {
+			dev_err(&pdev->dev, "dt configuration failed\n");
+			return PTR_ERR(plat_dat);
+		}
+	} else if (!acpi_disabled) {
+		plat_dat = baikal_stmmac_probe_config(&pdev->dev,
+						      (const char **)&stmmac_res.mac,
+						      &is_fixed_stmmac_clk);
+		if (IS_ERR(plat_dat)) {
+			dev_err(&pdev->dev, "acpi configuration failed\n");
+			return PTR_ERR(plat_dat);
+		}
+
+		dn = kzalloc(sizeof(struct device_node), GFP_KERNEL);
+		if (!dn) {
+			ret = -ENOMEM;
+			goto err_remove_config_dt;
+		}
+
+		plat_dat->phy_node = dn;
+	} else {
+		plat_dat = dev_get_platdata(&pdev->dev);
+		if (!plat_dat) {
+			dev_err(&pdev->dev, "no platform data provided\n");
+			return -EINVAL;
+		}
+
+		/* Set default value for multicast hash bins */
+		plat_dat->multicast_filter_bins = HASH_TABLE_SIZE;
+
+		/* Set default value for unicast filter entries */
+		plat_dat->unicast_filter_entries = 1;
+	}
+
+	gmac = devm_kzalloc(&pdev->dev, sizeof(*gmac), GFP_KERNEL);
+	if (!gmac) {
+		ret = -ENOMEM;
+		goto err_remove_config_dt;
+	}
+
+	gmac->dev = &pdev->dev;
+	gmac->tx2_clk = devm_clk_get(gmac->dev, "tx2_clk");
+	if (IS_ERR(gmac->tx2_clk)) {
+		dev_warn(&pdev->dev, "couldn't get TX2 clock\n");
+		gmac->tx2_clk = NULL;
+	}
+
+	gmac->axi_clk = devm_clk_get(gmac->dev, "axi_clk");
+	if (IS_ERR(gmac->axi_clk)) {
+		dev_warn(&pdev->dev, "couldn't get AXI clock\n");
+		gmac->axi_clk = NULL;
+	} else {
+		clk_set_rate(gmac->axi_clk, 300000000);
+	}
+
+	if (!acpi_disabled) {
+		device_property_read_string(&pdev->dev, "compatible", &str);
+	}
+
+	if ((gmac->dev->of_node &&
+	     of_device_is_compatible(gmac->dev->of_node, "baikal,bs1000-gmac"))
+	    || (str && strcasecmp(str, "baikal,bs1000-gmac") == 0)) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		gmac->base = res->start;
+		gmac->has_aux_div2 = 1;
+	} else {
+		gmac->has_aux_div2 = 0;
+	}
+
+	plat_dat->fix_mac_speed = baikal_gmac_fix_mac_speed;
+	plat_dat->bsp_priv = gmac;
+	plat_dat->has_gmac = 1;
+	plat_dat->bugged_jumbo = 1; /* TODO: is it really required? */
+	plat_dat->setup = baikal_gmac_setup;
+
+	ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+	if (ret) {
+		goto err_remove_config_dt;
+	}
+
+	if (!acpi_disabled) {
+		ret = baikal_add_mdio_phy(&pdev->dev);
+		if (ret) {
+			goto err_remove_config_dt;
+		}
+	}
+
+	gmac->is_fixed_stmmac_clk = is_fixed_stmmac_clk;
+
+	kfree(dn);
+	return 0;
+
+err_remove_config_dt:
+	stmmac_remove_config_dt(pdev, plat_dat);
+
+	if (is_fixed_stmmac_clk)
+		clk_unregister_fixed_rate(plat_dat->stmmac_clk);
+
+	kfree(dn);
+	return ret;
+}
+
+static void baikal_gmac_remove(struct platform_device *pdev)
+{
+	struct stmmac_priv *priv = netdev_priv(dev_get_drvdata(&pdev->dev));
+	struct plat_stmmacenet_data *plat = priv->plat;
+	struct baikal_gmac *gmac = plat->bsp_priv;
+
+	if (gmac->is_fixed_stmmac_clk) {
+		clk_disable_unprepare(plat->stmmac_clk);
+		clk_unregister_fixed_rate(plat->stmmac_clk);
+		plat->stmmac_clk = NULL;
+	}
+
+	stmmac_pltfr_remove(pdev);
+}
+
+static const struct of_device_id baikal_gmac_dwmac_match[] = {
+	{ .compatible = "baikal,bm1000-gmac" },
+	{ .compatible = "baikal,bs1000-gmac" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, baikal_gmac_dwmac_match);
+
+static struct platform_driver baikal_gmac_dwmac_driver = {
+	.probe		= baikal_gmac_probe,
+	.remove_new	= baikal_gmac_remove,
+	.driver		= {
+		.name = "baikal-gmac-dwmac",
+		.pm = &stmmac_pltfr_pm_ops,
+		.of_match_table = of_match_ptr(baikal_gmac_dwmac_match)
+	}
+};
+module_platform_driver(baikal_gmac_dwmac_driver);
+
+MODULE_DESCRIPTION("Baikal DWMAC specific glue driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
index 8555299443f4e..a047cedb74abb 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
@@ -557,3 +557,4 @@ int dwmac1000_setup(struct stmmac_priv *priv)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(dwmac1000_setup);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
index daf79cdbd3ecf..1af8bb44034c0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
@@ -15,8 +15,9 @@
 #include <asm/io.h>
 #include "dwmac1000.h"
 #include "dwmac_dma.h"
+#include "dwmac1000_dma.h"
 
-static void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
+void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
 {
 	u32 value = readl(ioaddr + DMA_AXI_BUS_MODE);
 	int i;
@@ -69,9 +70,10 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
 
 	writel(value, ioaddr + DMA_AXI_BUS_MODE);
 }
+EXPORT_SYMBOL_GPL(dwmac1000_dma_axi);
 
-static void dwmac1000_dma_init(void __iomem *ioaddr,
-			       struct stmmac_dma_cfg *dma_cfg, int atds)
+void dwmac1000_dma_init(void __iomem *ioaddr,
+			struct stmmac_dma_cfg *dma_cfg, int atds)
 {
 	u32 value = readl(ioaddr + DMA_BUS_MODE);
 	int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl;
@@ -109,24 +111,27 @@ static void dwmac1000_dma_init(void __iomem *ioaddr,
 	/* Mask interrupts by writing to CSR7 */
 	writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
 }
+EXPORT_SYMBOL_GPL(dwmac1000_dma_init);
 
-static void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
-				  void __iomem *ioaddr,
-				  struct stmmac_dma_cfg *dma_cfg,
-				  dma_addr_t dma_rx_phy, u32 chan)
+void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
+			   void __iomem *ioaddr,
+			   struct stmmac_dma_cfg *dma_cfg,
+			   dma_addr_t dma_rx_phy, u32 chan)
 {
 	/* RX descriptor base address list must be written into DMA CSR3 */
 	writel(lower_32_bits(dma_rx_phy), ioaddr + DMA_RCV_BASE_ADDR);
 }
+EXPORT_SYMBOL_GPL(dwmac1000_dma_init_rx);
 
-static void dwmac1000_dma_init_tx(struct stmmac_priv *priv,
-				  void __iomem *ioaddr,
-				  struct stmmac_dma_cfg *dma_cfg,
-				  dma_addr_t dma_tx_phy, u32 chan)
+void dwmac1000_dma_init_tx(struct stmmac_priv *priv,
+			   void __iomem *ioaddr,
+			   struct stmmac_dma_cfg *dma_cfg,
+			   dma_addr_t dma_tx_phy, u32 chan)
 {
 	/* TX descriptor base address list must be written into DMA CSR4 */
 	writel(lower_32_bits(dma_tx_phy), ioaddr + DMA_TX_BASE_ADDR);
 }
+EXPORT_SYMBOL_GPL(dwmac1000_dma_init_tx);
 
 static u32 dwmac1000_configure_fc(u32 csr6, int rxfifosz)
 {
@@ -149,9 +154,9 @@ static u32 dwmac1000_configure_fc(u32 csr6, int rxfifosz)
 	return csr6;
 }
 
-static void dwmac1000_dma_operation_mode_rx(struct stmmac_priv *priv,
-					    void __iomem *ioaddr, int mode,
-					    u32 channel, int fifosz, u8 qmode)
+void dwmac1000_dma_operation_mode_rx(struct stmmac_priv *priv,
+				     void __iomem *ioaddr, int mode,
+				     u32 channel, int fifosz, u8 qmode)
 {
 	u32 csr6 = readl(ioaddr + DMA_CONTROL);
 
@@ -177,10 +182,11 @@ static void dwmac1000_dma_operation_mode_rx(struct stmmac_priv *priv,
 
 	writel(csr6, ioaddr + DMA_CONTROL);
 }
+EXPORT_SYMBOL_GPL(dwmac1000_dma_operation_mode_rx);
 
-static void dwmac1000_dma_operation_mode_tx(struct stmmac_priv *priv,
-					    void __iomem *ioaddr, int mode,
-					    u32 channel, int fifosz, u8 qmode)
+void dwmac1000_dma_operation_mode_tx(struct stmmac_priv *priv,
+				     void __iomem *ioaddr, int mode,
+				     u32 channel, int fifosz, u8 qmode)
 {
 	u32 csr6 = readl(ioaddr + DMA_CONTROL);
 
@@ -211,9 +217,10 @@ static void dwmac1000_dma_operation_mode_tx(struct stmmac_priv *priv,
 
 	writel(csr6, ioaddr + DMA_CONTROL);
 }
+EXPORT_SYMBOL_GPL(dwmac1000_dma_operation_mode_tx);
 
-static void dwmac1000_dump_dma_regs(struct stmmac_priv *priv,
-				    void __iomem *ioaddr, u32 *reg_space)
+void dwmac1000_dump_dma_regs(struct stmmac_priv *priv,
+			     void __iomem *ioaddr, u32 *reg_space)
 {
 	int i;
 
@@ -222,9 +229,10 @@ static void dwmac1000_dump_dma_regs(struct stmmac_priv *priv,
 			reg_space[DMA_BUS_MODE / 4 + i] =
 				readl(ioaddr + DMA_BUS_MODE + i * 4);
 }
+EXPORT_SYMBOL_GPL(dwmac1000_dump_dma_regs);
 
-static int dwmac1000_get_hw_feature(void __iomem *ioaddr,
-				    struct dma_features *dma_cap)
+int dwmac1000_get_hw_feature(void __iomem *ioaddr,
+			     struct dma_features *dma_cap)
 {
 	u32 hw_cap = readl(ioaddr + DMA_HW_FEATURE);
 
@@ -267,12 +275,14 @@ static int dwmac1000_get_hw_feature(void __iomem *ioaddr,
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(dwmac1000_get_hw_feature);
 
-static void dwmac1000_rx_watchdog(struct stmmac_priv *priv,
-				  void __iomem *ioaddr, u32 riwt, u32 queue)
+void dwmac1000_rx_watchdog(struct stmmac_priv *priv,
+			   void __iomem *ioaddr, u32 riwt, u32 queue)
 {
 	writel(riwt, ioaddr + DMA_RX_WATCHDOG);
 }
+EXPORT_SYMBOL_GPL(dwmac1000_rx_watchdog);
 
 const struct stmmac_dma_ops dwmac1000_dma_ops = {
 	.reset = dwmac_dma_reset,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.h
new file mode 100644
index 0000000000000..34c10eb03a10b
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __DWMAC1000_DMA_H__
+#define __DWMAC1000_DMA_H__
+#include "dwmac1000.h"
+
+void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi);
+void dwmac1000_dma_init(void __iomem *ioaddr,
+			struct stmmac_dma_cfg *dma_cfg, int atds);
+void dwmac1000_dma_init_rx(struct stmmac_priv *priv,
+			   void __iomem *ioaddr,
+			   struct stmmac_dma_cfg *dma_cfg,
+			   dma_addr_t dma_rx_phy, u32 chan);
+void dwmac1000_dma_init_tx(struct stmmac_priv *priv,
+			   void __iomem *ioaddr,
+			   struct stmmac_dma_cfg *dma_cfg,
+			   dma_addr_t dma_tx_phy, u32 chan);
+void dwmac1000_dma_operation_mode_rx(struct stmmac_priv *priv,
+				     void __iomem *ioaddr, int mode,
+				     u32 channel, int fifosz, u8 qmode);
+void dwmac1000_dma_operation_mode_tx(struct stmmac_priv *priv,
+				     void __iomem *ioaddr, int mode,
+				     u32 channel, int fifosz, u8 qmode);
+void dwmac1000_dump_dma_regs(struct stmmac_priv *priv,
+			     void __iomem *ioaddr, u32 *reg_space);
+
+int  dwmac1000_get_hw_feature(void __iomem *ioaddr,
+			      struct dma_features *dma_cap);
+
+void dwmac1000_rx_watchdog(struct stmmac_priv *priv,
+			   void __iomem *ioaddr, u32 riwt, u32 number_chan);
+#endif /* __DWMAC1000_DMA_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
index 85e18f9a22f92..12e7f2c081f93 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
@@ -32,6 +32,7 @@ void dwmac_enable_dma_transmission(void __iomem *ioaddr)
 {
 	writel(1, ioaddr + DMA_XMT_POLL_DEMAND);
 }
+EXPORT_SYMBOL_GPL(dwmac_enable_dma_transmission);
 
 void dwmac_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
 			  u32 chan, bool rx, bool tx)
@@ -45,6 +46,7 @@ void dwmac_enable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
 
 	writel(value, ioaddr + DMA_INTR_ENA);
 }
+EXPORT_SYMBOL_GPL(dwmac_enable_dma_irq);
 
 void dwmac_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
 			   u32 chan, bool rx, bool tx)
@@ -58,6 +60,7 @@ void dwmac_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr,
 
 	writel(value, ioaddr + DMA_INTR_ENA);
 }
+EXPORT_SYMBOL_GPL(dwmac_disable_dma_irq);
 
 void dwmac_dma_start_tx(struct stmmac_priv *priv, void __iomem *ioaddr,
 			u32 chan)
@@ -66,6 +69,7 @@ void dwmac_dma_start_tx(struct stmmac_priv *priv, void __iomem *ioaddr,
 	value |= DMA_CONTROL_ST;
 	writel(value, ioaddr + DMA_CONTROL);
 }
+EXPORT_SYMBOL_GPL(dwmac_dma_start_tx);
 
 void dwmac_dma_stop_tx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan)
 {
@@ -73,6 +77,7 @@ void dwmac_dma_stop_tx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan)
 	value &= ~DMA_CONTROL_ST;
 	writel(value, ioaddr + DMA_CONTROL);
 }
+EXPORT_SYMBOL_GPL(dwmac_dma_stop_tx);
 
 void dwmac_dma_start_rx(struct stmmac_priv *priv, void __iomem *ioaddr,
 			u32 chan)
@@ -81,6 +86,7 @@ void dwmac_dma_start_rx(struct stmmac_priv *priv, void __iomem *ioaddr,
 	value |= DMA_CONTROL_SR;
 	writel(value, ioaddr + DMA_CONTROL);
 }
+EXPORT_SYMBOL_GPL(dwmac_dma_start_rx);
 
 void dwmac_dma_stop_rx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan)
 {
@@ -88,6 +94,7 @@ void dwmac_dma_stop_rx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan)
 	value &= ~DMA_CONTROL_SR;
 	writel(value, ioaddr + DMA_CONTROL);
 }
+EXPORT_SYMBOL_GPL(dwmac_dma_stop_rx);
 
 #ifdef DWMAC_DMA_DEBUG
 static void show_tx_process_state(unsigned int status)
@@ -239,6 +246,7 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr,
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(dwmac_dma_interrupt);
 
 void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr)
 {
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index 049c3adeb8504..643ab458e25ef 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -560,6 +560,7 @@ int nvmem_get_mac_address(struct device *dev, void *addrbuf)
 
 	return 0;
 }
+EXPORT_SYMBOL(nvmem_get_mac_address);
 
 static int fwnode_get_mac_addr(struct fwnode_handle *fwnode,
 			       const char *name, char *addr)
-- 
2.42.2



  parent reply	other threads:[~2024-10-14 14:01 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-10-14 14:01 [d-kernel] [PATCH 00/39] Support Baikal-M in un-def in p11 Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 01/39] Baikal Electronics SoC family Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 02/39] Clk: Add clock drivers for Baikal BE-M1000 with new firmware Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 03/39] USB: Add support for Baikal USB PHY Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 04/39] PCI: Add support for PCIe controller for Baikal BE-M1000 Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 05/39] AHCI SATA: Add support " Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 06/39] UART: Add support for UART " Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 07/39] cpufreq-dt: don't load on Baikal-M SoC Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 08/39] Sound: add support for Baikal BE-M1000 I2S Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 09/39] sound: baikal-i2s: paper over RX overrun warnings on Baikal-M Daniil Gnusarev
2024-10-14 14:01 ` Daniil Gnusarev [this message]
2024-10-14 14:01 ` [d-kernel] [PATCH 11/39] net: fwnode_get_phy_id: consider all compatible strings Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 12/39] hwmon: bt1-pvt: access registers via pvt_{readl, writel} helpers Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 13/39] hwmon: bt1-pvt: define pvt_readl/pvt_writel for Baikal-M SoC Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 14/39] hwmon: bt1-pvt: adjusted probing " Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 15/39] hwmon: bt1-pvt: added compatible baikal, pvt Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 16/39] PVT: support register addressing with new firmware Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 17/39] drm: add Baikal-M SoC video display unit driver Daniil Gnusarev
2024-10-14 14:01 ` [d-kernel] [PATCH 18/39] drm/bridge: dw-hdmi: support ahb audio hw revision 0x2a Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 19/39] dt-bindings: dw-hdmi: added ahb-audio-regshift Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 20/39] drm/bridge: dw-hdmi: force ahb audio register offset for Baikal-M Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 21/39] drm/panfrost: forcibly set dma-coherent on Baikal-M Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 22/39] drm/panfrost: disable devfreq " Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 23/39] bmc: add board management controller driver Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 24/39] pm: disable all sleep states on Baikal-M based boards Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 25/39] sound: dwc-i2s: paper over RX overrun warnings on Baikal-M Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 26/39] sound: dwc-i2s: request all IRQs specified in device tree Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 27/39] usb: dwc3: of-simple: added compatible string for Baikal-M SoC Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 28/39] serial: 8250_dw: verify clock rate in dw8250_set_termios Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 29/39] clk: use "cmu-id" if there is no "reg" in devicetree Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 30/39] pci: baikal-pcie: driver compatibility with SDK earlier than 5.7 Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 31/39] pci: baikal-pcie: driver compatibility with SDK versions 5.4 Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 32/39] dw-pcie: refuse to load on Baikal-M with recent firmware Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 33/39] drm: baikal-vdu: driver compatibility with SDK earlier than 5.9 Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 34/39] input: new driver - serdev-serio Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 35/39] input: added TF307 serio PS/2 emulator driver Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 36/39] input: tp_serio: catch up API changes Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 37/39] drm: baikal-m: add vblank events, fix mode switching Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 38/39] drm: baikal-vdu: disable backlight driver loading Daniil Gnusarev
2024-10-14 14:02 ` [d-kernel] [PATCH 39/39] config-aarch64: enable more configs for baikal-m support Daniil Gnusarev
2024-10-14 14:28 ` [d-kernel] [PATCH 00/39] Support Baikal-M in un-def in p11 Vitaly Chikunov

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=20241014140221.535985-11-gnusarevda@basealt.ru \
    --to=gnusarevda@basealt.ru \
    --cc=devel-kernel@lists.altlinux.org \
    /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

ALT Linux kernel packages development

This inbox may be cloned and mirrored by anyone:

	git clone --mirror http://lore.altlinux.org/devel-kernel/0 devel-kernel/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 devel-kernel devel-kernel/ http://lore.altlinux.org/devel-kernel \
		devel-kernel@altlinux.org devel-kernel@altlinux.ru devel-kernel@altlinux.com
	public-inbox-index devel-kernel

Example config snippet for mirrors.
Newsgroup available over NNTP:
	nntp://lore.altlinux.org/org.altlinux.lists.devel-kernel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git