This glue driver is created based on the arch-code
implemented earlier with the platform-specific settings.
Use syscon for SYSCON register access.
Partialy based on the previous work by Serge Semin.
Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
---
drivers/net/ethernet/stmicro/stmmac/Kconfig | 11 +
drivers/net/ethernet/stmicro/stmmac/Makefile | 1 +
.../ethernet/stmicro/stmmac/dwmac-loongson1.c | 257 ++++++++++++++++++
3 files changed, 269 insertions(+)
create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 06c6871f8788..a2b9e289aa36 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -239,6 +239,17 @@ config DWMAC_INTEL_PLAT
the stmmac device driver. This driver is used for the Intel Keem Bay
SoC.
+config DWMAC_LOONGSON1
+ tristate "Loongson1 GMAC support"
+ default MACH_LOONGSON32
+ depends on OF && (MACH_LOONGSON32 || COMPILE_TEST)
+ help
+ Support for ethernet controller on Loongson1 SoC.
+
+ This selects Loongson1 SoC glue layer support for the stmmac
+ device driver. This driver is used for Loongson1-based boards
+ like Loongson LS1B/LS1C.
+
config DWMAC_TEGRA
tristate "NVIDIA Tegra MGBE support"
depends on ARCH_TEGRA || COMPILE_TEST
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index 5b57aee19267..80e598bd4255 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o
obj-$(CONFIG_DWMAC_SUN8I) += dwmac-sun8i.o
obj-$(CONFIG_DWMAC_DWC_QOS_ETH) += dwmac-dwc-qos-eth.o
obj-$(CONFIG_DWMAC_INTEL_PLAT) += dwmac-intel-plat.o
+obj-$(CONFIG_DWMAC_LOONGSON1) += dwmac-loongson1.o
obj-$(CONFIG_DWMAC_GENERIC) += dwmac-generic.o
obj-$(CONFIG_DWMAC_IMX8) += dwmac-imx.o
obj-$(CONFIG_DWMAC_TEGRA) += dwmac-tegra.o
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
new file mode 100644
index 000000000000..368d6cd2cb78
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
@@ -0,0 +1,257 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Loongson-1 DWMAC glue layer
+ *
+ * Copyright (C) 2011-2023 Keguang Zhang <keguang.zhang@gmail.com>
+ */
+
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include "stmmac.h"
+#include "stmmac_platform.h"
+
+/* Loongson-1 SYSCON Registers */
+#define LS1X_SYSCON0 (0x0)
+#define LS1X_SYSCON1 (0x4)
+
+struct ls1x_dwmac_syscon {
+ const struct reg_field *reg_fields;
+ unsigned int nr_reg_fields;
+ int (*syscon_init)(struct plat_stmmacenet_data *plat);
+};
+
+struct ls1x_dwmac {
+ struct device *dev;
+ struct plat_stmmacenet_data *plat_dat;
+ const struct ls1x_dwmac_syscon *syscon;
+ struct regmap *regmap;
+ struct regmap_field *regmap_fields[];
+};
+
+enum ls1b_dwmac_syscon_regfield {
+ GMAC1_USE_UART1,
+ GMAC1_USE_UART0,
+ GMAC1_SHUT,
+ GMAC0_SHUT,
+ GMAC1_USE_TXCLK,
+ GMAC0_USE_TXCLK,
+ GMAC1_USE_PWM23,
+ GMAC0_USE_PWM01,
+};
+
+enum ls1c_dwmac_syscon_regfield {
+ GMAC_SHUT,
+ PHY_INTF_SELI,
+};
+
+const struct reg_field ls1b_dwmac_syscon_regfields[] = {
+ [GMAC1_USE_UART1] = REG_FIELD(LS1X_SYSCON0, 4, 4),
+ [GMAC1_USE_UART0] = REG_FIELD(LS1X_SYSCON0, 3, 3),
+ [GMAC1_SHUT] = REG_FIELD(LS1X_SYSCON1, 13, 13),
+ [GMAC0_SHUT] = REG_FIELD(LS1X_SYSCON1, 12, 12),
+ [GMAC1_USE_TXCLK] = REG_FIELD(LS1X_SYSCON1, 3, 3),
+ [GMAC0_USE_TXCLK] = REG_FIELD(LS1X_SYSCON1, 2, 2),
+ [GMAC1_USE_PWM23] = REG_FIELD(LS1X_SYSCON1, 1, 1),
+ [GMAC0_USE_PWM01] = REG_FIELD(LS1X_SYSCON1, 0, 0)
+};
+
+const struct reg_field ls1c_dwmac_syscon_regfields[] = {
+ [GMAC_SHUT] = REG_FIELD(LS1X_SYSCON0, 6, 6),
+ [PHY_INTF_SELI] = REG_FIELD(LS1X_SYSCON1, 28, 30)
+};
+
+static int ls1b_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
+{
+ struct ls1x_dwmac *dwmac = plat->bsp_priv;
+ struct regmap_field **regmap_fields = dwmac->regmap_fields;
+
+ if (plat->bus_id) {
+ regmap_field_write(regmap_fields[GMAC1_USE_UART1], 1);
+ regmap_field_write(regmap_fields[GMAC1_USE_UART0], 1);
+
+ switch (plat->phy_interface) {
+ case PHY_INTERFACE_MODE_RGMII:
+ regmap_field_write(regmap_fields[GMAC1_USE_TXCLK], 0);
+ regmap_field_write(regmap_fields[GMAC1_USE_PWM23], 0);
+ break;
+ case PHY_INTERFACE_MODE_MII:
+ regmap_field_write(regmap_fields[GMAC1_USE_TXCLK], 1);
+ regmap_field_write(regmap_fields[GMAC1_USE_PWM23], 1);
+ break;
+ default:
+ dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
+ plat->phy_interface);
+ return -EOPNOTSUPP;
+ }
+
+ regmap_field_write(regmap_fields[GMAC1_SHUT], 0);
+ } else {
+ switch (plat->phy_interface) {
+ case PHY_INTERFACE_MODE_RGMII:
+ regmap_field_write(regmap_fields[GMAC0_USE_TXCLK], 0);
+ regmap_field_write(regmap_fields[GMAC0_USE_PWM01], 0);
+ break;
+ case PHY_INTERFACE_MODE_MII:
+ regmap_field_write(regmap_fields[GMAC0_USE_TXCLK], 1);
+ regmap_field_write(regmap_fields[GMAC0_USE_PWM01], 1);
+ break;
+ default:
+ dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
+ plat->phy_interface);
+ return -EOPNOTSUPP;
+ }
+
+ regmap_field_write(regmap_fields[GMAC0_SHUT], 0);
+ }
+
+ return 0;
+}
+
+static int ls1c_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
+{
+ struct ls1x_dwmac *dwmac = plat->bsp_priv;
+ struct regmap_field **regmap_fields = dwmac->regmap_fields;
+
+ if (plat->phy_interface == PHY_INTERFACE_MODE_RMII) {
+ regmap_field_write(regmap_fields[PHY_INTF_SELI], 0x4);
+ } else {
+ dev_err(dwmac->dev, "Unsupported PHY-mode %u\n",
+ plat->phy_interface);
+ return -EOPNOTSUPP;
+ }
+
+ regmap_field_write(regmap_fields[GMAC_SHUT], 0);
+
+ return 0;
+}
+
+static const struct ls1x_dwmac_syscon ls1b_dwmac_syscon = {
+ .reg_fields = ls1b_dwmac_syscon_regfields,
+ .nr_reg_fields = ARRAY_SIZE(ls1b_dwmac_syscon_regfields),
+ .syscon_init = ls1b_dwmac_syscon_init,
+};
+
+static const struct ls1x_dwmac_syscon ls1c_dwmac_syscon = {
+ .reg_fields = ls1c_dwmac_syscon_regfields,
+ .nr_reg_fields = ARRAY_SIZE(ls1c_dwmac_syscon_regfields),
+ .syscon_init = ls1c_dwmac_syscon_init,
+};
+
+static int ls1x_dwmac_init(struct platform_device *pdev, void *priv)
+{
+ struct ls1x_dwmac *dwmac = priv;
+ int ret;
+
+ ret = devm_regmap_field_bulk_alloc(dwmac->dev, dwmac->regmap,
+ dwmac->regmap_fields,
+ dwmac->syscon->reg_fields,
+ dwmac->syscon->nr_reg_fields);
+ if (ret)
+ return ret;
+
+ if (dwmac->syscon->syscon_init) {
+ ret = dwmac->syscon->syscon_init(dwmac->plat_dat);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct of_device_id ls1x_dwmac_syscon_match[] = {
+ { .compatible = "loongson,ls1b-syscon", .data = &ls1b_dwmac_syscon },
+ { .compatible = "loongson,ls1c-syscon", .data = &ls1c_dwmac_syscon },
+ { }
+};
+
+static int ls1x_dwmac_probe(struct platform_device *pdev)
+{
+ struct plat_stmmacenet_data *plat_dat;
+ struct stmmac_resources stmmac_res;
+ struct device_node *syscon_np;
+ const struct of_device_id *match;
+ struct regmap *regmap;
+ struct ls1x_dwmac *dwmac;
+ const struct ls1x_dwmac_syscon *syscon;
+ size_t size;
+ int ret;
+
+ ret = stmmac_get_platform_resources(pdev, &stmmac_res);
+ if (ret)
+ return ret;
+
+ /* Probe syscon */
+ syscon_np = of_parse_phandle(pdev->dev.of_node, "syscon", 0);
+ if (!syscon_np)
+ return -ENODEV;
+
+ match = of_match_node(ls1x_dwmac_syscon_match, syscon_np);
+ if (!match) {
+ of_node_put(syscon_np);
+ return -EINVAL;
+ }
+ syscon = (const struct ls1x_dwmac_syscon *)match->data;
+
+ regmap = syscon_node_to_regmap(syscon_np);
+ of_node_put(syscon_np);
+ if (IS_ERR(regmap)) {
+ ret = PTR_ERR(regmap);
+ dev_err(&pdev->dev, "Unable to map syscon: %d\n", ret);
+ return ret;
+ }
+
+ size = syscon->nr_reg_fields * sizeof(struct regmap_field *);
+ dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac) + size, GFP_KERNEL);
+ if (!dwmac)
+ return -ENOMEM;
+
+ plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
+ if (IS_ERR(plat_dat)) {
+ dev_err(&pdev->dev, "dt configuration failed\n");
+ return PTR_ERR(plat_dat);
+ }
+
+ plat_dat->bsp_priv = dwmac;
+ plat_dat->init = ls1x_dwmac_init;
+ dwmac->dev = &pdev->dev;
+ dwmac->plat_dat = plat_dat;
+ dwmac->syscon = syscon;
+ dwmac->regmap = regmap;
+
+ ret = stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res);
+ if (ret)
+ goto err_remove_config_dt;
+
+ return 0;
+
+err_remove_config_dt:
+ if (pdev->dev.of_node)
+ stmmac_remove_config_dt(pdev, plat_dat);
+
+ return ret;
+}
+
+static const struct of_device_id ls1x_dwmac_match[] = {
+ { .compatible = "loongson,ls1b-dwmac" },
+ { .compatible = "loongson,ls1c-dwmac" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ls1x_dwmac_match);
+
+static struct platform_driver ls1x_dwmac_driver = {
+ .probe = ls1x_dwmac_probe,
+ .remove_new = stmmac_pltfr_remove,
+ .driver = {
+ .name = "loongson1-dwmac",
+ .of_match_table = ls1x_dwmac_match,
+ },
+};
+module_platform_driver(ls1x_dwmac_driver);
+
+MODULE_AUTHOR("Keguang Zhang <keguang.zhang@gmail.com>");
+MODULE_DESCRIPTION("Loongson1 DWMAC glue layer");
+MODULE_LICENSE("GPL");
--
2.39.2
On Sat, Aug 12, 2023 at 11:11:34PM +0800, Keguang Zhang wrote:
> This glue driver is created based on the arch-code
> implemented earlier with the platform-specific settings.
>
> Use syscon for SYSCON register access.
>
> Partialy based on the previous work by Serge Semin.
>
> Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
> ---
> drivers/net/ethernet/stmicro/stmmac/Kconfig | 11 +
> drivers/net/ethernet/stmicro/stmmac/Makefile | 1 +
> .../ethernet/stmicro/stmmac/dwmac-loongson1.c | 257 ++++++++++++++++++
> 3 files changed, 269 insertions(+)
> create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> index 06c6871f8788..a2b9e289aa36 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
> +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> @@ -239,6 +239,17 @@ config DWMAC_INTEL_PLAT
> the stmmac device driver. This driver is used for the Intel Keem Bay
> SoC.
>
> +config DWMAC_LOONGSON1
> + tristate "Loongson1 GMAC support"
> + default MACH_LOONGSON32
> + depends on OF && (MACH_LOONGSON32 || COMPILE_TEST)
> + help
> + Support for ethernet controller on Loongson1 SoC.
> +
> + This selects Loongson1 SoC glue layer support for the stmmac
> + device driver. This driver is used for Loongson1-based boards
> + like Loongson LS1B/LS1C.
> +
> config DWMAC_TEGRA
> tristate "NVIDIA Tegra MGBE support"
> depends on ARCH_TEGRA || COMPILE_TEST
> diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
> index 5b57aee19267..80e598bd4255 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/Makefile
> +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
> @@ -29,6 +29,7 @@ obj-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o
> obj-$(CONFIG_DWMAC_SUN8I) += dwmac-sun8i.o
> obj-$(CONFIG_DWMAC_DWC_QOS_ETH) += dwmac-dwc-qos-eth.o
> obj-$(CONFIG_DWMAC_INTEL_PLAT) += dwmac-intel-plat.o
> +obj-$(CONFIG_DWMAC_LOONGSON1) += dwmac-loongson1.o
> obj-$(CONFIG_DWMAC_GENERIC) += dwmac-generic.o
> obj-$(CONFIG_DWMAC_IMX8) += dwmac-imx.o
> obj-$(CONFIG_DWMAC_TEGRA) += dwmac-tegra.o
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> new file mode 100644
> index 000000000000..368d6cd2cb78
> --- /dev/null
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
> @@ -0,0 +1,257 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Loongson-1 DWMAC glue layer
> + *
> + * Copyright (C) 2011-2023 Keguang Zhang <keguang.zhang@gmail.com>
> + */
> +
> +#include <linux/mfd/syscon.h>
> +#include <linux/module.h>
> +#include <linux/phy.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +
> +#include "stmmac.h"
> +#include "stmmac_platform.h"
> +
> +/* Loongson-1 SYSCON Registers */
> +#define LS1X_SYSCON0 (0x0)
> +#define LS1X_SYSCON1 (0x4)
> +
> +struct ls1x_dwmac_syscon {
> + const struct reg_field *reg_fields;
> + unsigned int nr_reg_fields;
> + int (*syscon_init)(struct plat_stmmacenet_data *plat);
> +};
> +
> +struct ls1x_dwmac {
> + struct device *dev;
> + struct plat_stmmacenet_data *plat_dat;
> + const struct ls1x_dwmac_syscon *syscon;
> + struct regmap *regmap;
> + struct regmap_field *regmap_fields[];
> +};
> +
> +enum ls1b_dwmac_syscon_regfield {
> + GMAC1_USE_UART1,
> + GMAC1_USE_UART0,
> + GMAC1_SHUT,
> + GMAC0_SHUT,
> + GMAC1_USE_TXCLK,
> + GMAC0_USE_TXCLK,
> + GMAC1_USE_PWM23,
> + GMAC0_USE_PWM01,
> +};
> +
> +enum ls1c_dwmac_syscon_regfield {
> + GMAC_SHUT,
> + PHY_INTF_SELI,
> +};
> +
> +const struct reg_field ls1b_dwmac_syscon_regfields[] = {
> + [GMAC1_USE_UART1] = REG_FIELD(LS1X_SYSCON0, 4, 4),
> + [GMAC1_USE_UART0] = REG_FIELD(LS1X_SYSCON0, 3, 3),
> + [GMAC1_SHUT] = REG_FIELD(LS1X_SYSCON1, 13, 13),
> + [GMAC0_SHUT] = REG_FIELD(LS1X_SYSCON1, 12, 12),
> + [GMAC1_USE_TXCLK] = REG_FIELD(LS1X_SYSCON1, 3, 3),
> + [GMAC0_USE_TXCLK] = REG_FIELD(LS1X_SYSCON1, 2, 2),
> + [GMAC1_USE_PWM23] = REG_FIELD(LS1X_SYSCON1, 1, 1),
> + [GMAC0_USE_PWM01] = REG_FIELD(LS1X_SYSCON1, 0, 0)
> +};
> +
> +const struct reg_field ls1c_dwmac_syscon_regfields[] = {
> + [GMAC_SHUT] = REG_FIELD(LS1X_SYSCON0, 6, 6),
> + [PHY_INTF_SELI] = REG_FIELD(LS1X_SYSCON1, 28, 30)
> +};
Emm, using regmap fields looks so over-complicated in this case seeing
you only need to set/clear several bits in the syscon. What about
defining macros with the particular flag as it's already done in the
"asm/mach-loongson32/regs-mux.h" file and using regmap_update_bits()?
> +
> +static int ls1b_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
> +{
As I already told you this part is better to be called from the
plat_stmmacenet_data.fix_mac_speed() because PHY interface mode can
differ from one interface open cycle to another as per the phylink
design.
> + struct ls1x_dwmac *dwmac = plat->bsp_priv;
> + struct regmap_field **regmap_fields = dwmac->regmap_fields;
> +
> + if (plat->bus_id) {
Using bus_id doesn't look correct to determine the CSRs responsible
for the interface mode selection because it's calculated based on the
DT ethernet-alias which doesn't guarantee to have a particular device
assigned with the alias. Alias node can be absent after all. What
could be better in this case is for instance to use the regs physical
address. Any better idea?
> + regmap_field_write(regmap_fields[GMAC1_USE_UART1], 1);
> + regmap_field_write(regmap_fields[GMAC1_USE_UART0], 1);
> +
> + switch (plat->phy_interface) {
> + case PHY_INTERFACE_MODE_RGMII:
> + regmap_field_write(regmap_fields[GMAC1_USE_TXCLK], 0);
> + regmap_field_write(regmap_fields[GMAC1_USE_PWM23], 0);
> + break;
> + case PHY_INTERFACE_MODE_MII:
> + regmap_field_write(regmap_fields[GMAC1_USE_TXCLK], 1);
> + regmap_field_write(regmap_fields[GMAC1_USE_PWM23], 1);
> + break;
> + default:
> + dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
> + plat->phy_interface);
> + return -EOPNOTSUPP;
> + }
> +
> + regmap_field_write(regmap_fields[GMAC1_SHUT], 0);
> + } else {
> + switch (plat->phy_interface) {
> + case PHY_INTERFACE_MODE_RGMII:
> + regmap_field_write(regmap_fields[GMAC0_USE_TXCLK], 0);
> + regmap_field_write(regmap_fields[GMAC0_USE_PWM01], 0);
> + break;
> + case PHY_INTERFACE_MODE_MII:
> + regmap_field_write(regmap_fields[GMAC0_USE_TXCLK], 1);
> + regmap_field_write(regmap_fields[GMAC0_USE_PWM01], 1);
> + break;
> + default:
> + dev_err(dwmac->dev, "Unsupported PHY mode %u\n",
> + plat->phy_interface);
> + return -EOPNOTSUPP;
> + }
> +
> + regmap_field_write(regmap_fields[GMAC0_SHUT], 0);
> + }
> +
> + return 0;
> +}
> +
> +static int ls1c_dwmac_syscon_init(struct plat_stmmacenet_data *plat)
> +{
> + struct ls1x_dwmac *dwmac = plat->bsp_priv;
> + struct regmap_field **regmap_fields = dwmac->regmap_fields;
> +
> + if (plat->phy_interface == PHY_INTERFACE_MODE_RMII) {
> + regmap_field_write(regmap_fields[PHY_INTF_SELI], 0x4);
> + } else {
> + dev_err(dwmac->dev, "Unsupported PHY-mode %u\n",
> + plat->phy_interface);
> + return -EOPNOTSUPP;
> + }
> +
> + regmap_field_write(regmap_fields[GMAC_SHUT], 0);
> +
> + return 0;
> +}
> +
> +static const struct ls1x_dwmac_syscon ls1b_dwmac_syscon = {
> + .reg_fields = ls1b_dwmac_syscon_regfields,
> + .nr_reg_fields = ARRAY_SIZE(ls1b_dwmac_syscon_regfields),
> + .syscon_init = ls1b_dwmac_syscon_init,
> +};
> +
> +static const struct ls1x_dwmac_syscon ls1c_dwmac_syscon = {
> + .reg_fields = ls1c_dwmac_syscon_regfields,
> + .nr_reg_fields = ARRAY_SIZE(ls1c_dwmac_syscon_regfields),
> + .syscon_init = ls1c_dwmac_syscon_init,
> +};
> +
> +static int ls1x_dwmac_init(struct platform_device *pdev, void *priv)
> +{
> + struct ls1x_dwmac *dwmac = priv;
> + int ret;
> +
> + ret = devm_regmap_field_bulk_alloc(dwmac->dev, dwmac->regmap,
> + dwmac->regmap_fields,
> + dwmac->syscon->reg_fields,
> + dwmac->syscon->nr_reg_fields);
Please see my first comment about this.
> + if (ret)
> + return ret;
> +
> + if (dwmac->syscon->syscon_init) {
> + ret = dwmac->syscon->syscon_init(dwmac->plat_dat);
> + if (ret)
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static const struct of_device_id ls1x_dwmac_syscon_match[] = {
> + { .compatible = "loongson,ls1b-syscon", .data = &ls1b_dwmac_syscon },
> + { .compatible = "loongson,ls1c-syscon", .data = &ls1c_dwmac_syscon },
> + { }
> +};
> +
> +static int ls1x_dwmac_probe(struct platform_device *pdev)
> +{
> + struct plat_stmmacenet_data *plat_dat;
> + struct stmmac_resources stmmac_res;
> + struct device_node *syscon_np;
> + const struct of_device_id *match;
> + struct regmap *regmap;
> + struct ls1x_dwmac *dwmac;
> + const struct ls1x_dwmac_syscon *syscon;
> + size_t size;
> + int ret;
> +
> + ret = stmmac_get_platform_resources(pdev, &stmmac_res);
> + if (ret)
> + return ret;
> +
> + /* Probe syscon */
> + syscon_np = of_parse_phandle(pdev->dev.of_node, "syscon", 0);
it's vendor-specific property so it is supposed to have a
vendor-specific prefix and possibly ls1-specific name.
> + if (!syscon_np)
> + return -ENODEV;
> +
> + match = of_match_node(ls1x_dwmac_syscon_match, syscon_np);
> + if (!match) {
> + of_node_put(syscon_np);
> + return -EINVAL;
> + }
> + syscon = (const struct ls1x_dwmac_syscon *)match->data;
> +
> + regmap = syscon_node_to_regmap(syscon_np);
> + of_node_put(syscon_np);
> + if (IS_ERR(regmap)) {
> + ret = PTR_ERR(regmap);
> + dev_err(&pdev->dev, "Unable to map syscon: %d\n", ret);
> + return ret;
> + }
or you can use syscon_regmap_lookup_by_phandle(). Using
of_match_node() doesn't seem necessary since it's unlikely to have
moee than one system controller available on the LS1b or LS1c chips.
> +
> + size = syscon->nr_reg_fields * sizeof(struct regmap_field *);
> + dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac) + size, GFP_KERNEL);
> + if (!dwmac)
> + return -ENOMEM;
> +
> + plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
> + if (IS_ERR(plat_dat)) {
> + dev_err(&pdev->dev, "dt configuration failed\n");
> + return PTR_ERR(plat_dat);
> + }
> +
> + plat_dat->bsp_priv = dwmac;
> + plat_dat->init = ls1x_dwmac_init;
> + dwmac->dev = &pdev->dev;
> + dwmac->plat_dat = plat_dat;
> + dwmac->syscon = syscon;
> + dwmac->regmap = regmap;
> +
> + ret = stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res);
> + if (ret)
> + goto err_remove_config_dt;
> +
> + return 0;
> +
> +err_remove_config_dt:
> + if (pdev->dev.of_node)
Is this conditional statement necessary here?
-Serge
> + stmmac_remove_config_dt(pdev, plat_dat);
> +
> + return ret;
> +}
> +
> +static const struct of_device_id ls1x_dwmac_match[] = {
> + { .compatible = "loongson,ls1b-dwmac" },
> + { .compatible = "loongson,ls1c-dwmac" },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, ls1x_dwmac_match);
> +
> +static struct platform_driver ls1x_dwmac_driver = {
> + .probe = ls1x_dwmac_probe,
> + .remove_new = stmmac_pltfr_remove,
> + .driver = {
> + .name = "loongson1-dwmac",
> + .of_match_table = ls1x_dwmac_match,
> + },
> +};
> +module_platform_driver(ls1x_dwmac_driver);
> +
> +MODULE_AUTHOR("Keguang Zhang <keguang.zhang@gmail.com>");
> +MODULE_DESCRIPTION("Loongson1 DWMAC glue layer");
> +MODULE_LICENSE("GPL");
> --
> 2.39.2
>
On Sat, Aug 12, 2023 at 11:11:34PM +0800, Keguang Zhang wrote:
> This glue driver is created based on the arch-code
> implemented earlier with the platform-specific settings.
>
> Use syscon for SYSCON register access.
>
> Partialy based on the previous work by Serge Semin.
>
> Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
...
Hi Keguang Zhang,
some minor feedback from my side.
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
...
> +const struct reg_field ls1b_dwmac_syscon_regfields[] = {
> + [GMAC1_USE_UART1] = REG_FIELD(LS1X_SYSCON0, 4, 4),
> + [GMAC1_USE_UART0] = REG_FIELD(LS1X_SYSCON0, 3, 3),
> + [GMAC1_SHUT] = REG_FIELD(LS1X_SYSCON1, 13, 13),
> + [GMAC0_SHUT] = REG_FIELD(LS1X_SYSCON1, 12, 12),
> + [GMAC1_USE_TXCLK] = REG_FIELD(LS1X_SYSCON1, 3, 3),
> + [GMAC0_USE_TXCLK] = REG_FIELD(LS1X_SYSCON1, 2, 2),
> + [GMAC1_USE_PWM23] = REG_FIELD(LS1X_SYSCON1, 1, 1),
> + [GMAC0_USE_PWM01] = REG_FIELD(LS1X_SYSCON1, 0, 0)
> +};
nit: Perhaps ls1b_dwmac_syscon_regfields should be static.
> +
> +const struct reg_field ls1c_dwmac_syscon_regfields[] = {
> + [GMAC_SHUT] = REG_FIELD(LS1X_SYSCON0, 6, 6),
> + [PHY_INTF_SELI] = REG_FIELD(LS1X_SYSCON1, 28, 30)
> +};
Likewise, perhaps ls1c_dwmac_syscon_regfields should be static.
...
> +static const struct of_device_id ls1x_dwmac_syscon_match[] = {
> + { .compatible = "loongson,ls1b-syscon", .data = &ls1b_dwmac_syscon },
> + { .compatible = "loongson,ls1c-syscon", .data = &ls1c_dwmac_syscon },
> + { }
> +};o
I am seeing a warning about ls1x_dwmac_syscon_match being unused.
I think this is due to CONFIG_OF being unset.
> +
> +static int ls1x_dwmac_probe(struct platform_device *pdev)
> +{
> + struct plat_stmmacenet_data *plat_dat;
> + struct stmmac_resources stmmac_res;
> + struct device_node *syscon_np;
> + const struct of_device_id *match;
> + struct regmap *regmap;
> + struct ls1x_dwmac *dwmac;
> + const struct ls1x_dwmac_syscon *syscon;
> + size_t size;
> + int ret;
> +
> + ret = stmmac_get_platform_resources(pdev, &stmmac_res);
> + if (ret)
> + return ret;
> +
> + /* Probe syscon */
> + syscon_np = of_parse_phandle(pdev->dev.of_node, "syscon", 0);
> + if (!syscon_np)
> + return -ENODEV;
> +
> + match = of_match_node(ls1x_dwmac_syscon_match, syscon_np);
> + if (!match) {
> + of_node_put(syscon_np);
> + return -EINVAL;
> + }
> + syscon = (const struct ls1x_dwmac_syscon *)match->data;
> +
> + regmap = syscon_node_to_regmap(syscon_np);
> + of_node_put(syscon_np);
> + if (IS_ERR(regmap)) {
> + ret = PTR_ERR(regmap);
> + dev_err(&pdev->dev, "Unable to map syscon: %d\n", ret);
> + return ret;
> + }
> +
> + size = syscon->nr_reg_fields * sizeof(struct regmap_field *);
> + dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac) + size, GFP_KERNEL);
> + if (!dwmac)
> + return -ENOMEM;
> +
> + plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
> + if (IS_ERR(plat_dat)) {
> + dev_err(&pdev->dev, "dt configuration failed\n");
> + return PTR_ERR(plat_dat);
> + }
> +
> + plat_dat->bsp_priv = dwmac;
> + plat_dat->init = ls1x_dwmac_init;
> + dwmac->dev = &pdev->dev;
> + dwmac->plat_dat = plat_dat;
> + dwmac->syscon = syscon;
> + dwmac->regmap = regmap;
> +
> + ret = stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res);
> + if (ret)
> + goto err_remove_config_dt;
> +
> + return 0;
> +
> +err_remove_config_dt:
> + if (pdev->dev.of_node)
> + stmmac_remove_config_dt(pdev, plat_dat);
> +
> + return ret;
> +}
...
On Mon, Aug 14, 2023 at 2:24 AM Simon Horman <horms@kernel.org> wrote:
>
> On Sat, Aug 12, 2023 at 11:11:34PM +0800, Keguang Zhang wrote:
> > This glue driver is created based on the arch-code
> > implemented earlier with the platform-specific settings.
> >
> > Use syscon for SYSCON register access.
> >
> > Partialy based on the previous work by Serge Semin.
> >
> > Signed-off-by: Keguang Zhang <keguang.zhang@gmail.com>
>
> ...
>
> Hi Keguang Zhang,
>
> some minor feedback from my side.
>
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
>
> ...
>
> > +const struct reg_field ls1b_dwmac_syscon_regfields[] = {
> > + [GMAC1_USE_UART1] = REG_FIELD(LS1X_SYSCON0, 4, 4),
> > + [GMAC1_USE_UART0] = REG_FIELD(LS1X_SYSCON0, 3, 3),
> > + [GMAC1_SHUT] = REG_FIELD(LS1X_SYSCON1, 13, 13),
> > + [GMAC0_SHUT] = REG_FIELD(LS1X_SYSCON1, 12, 12),
> > + [GMAC1_USE_TXCLK] = REG_FIELD(LS1X_SYSCON1, 3, 3),
> > + [GMAC0_USE_TXCLK] = REG_FIELD(LS1X_SYSCON1, 2, 2),
> > + [GMAC1_USE_PWM23] = REG_FIELD(LS1X_SYSCON1, 1, 1),
> > + [GMAC0_USE_PWM01] = REG_FIELD(LS1X_SYSCON1, 0, 0)
> > +};
>
> nit: Perhaps ls1b_dwmac_syscon_regfields should be static.
>
> > +
> > +const struct reg_field ls1c_dwmac_syscon_regfields[] = {
> > + [GMAC_SHUT] = REG_FIELD(LS1X_SYSCON0, 6, 6),
> > + [PHY_INTF_SELI] = REG_FIELD(LS1X_SYSCON1, 28, 30)
> > +};
>
> Likewise, perhaps ls1c_dwmac_syscon_regfields should be static.
>
Will do.
Thanks!
> ...
>
> > +static const struct of_device_id ls1x_dwmac_syscon_match[] = {
> > + { .compatible = "loongson,ls1b-syscon", .data = &ls1b_dwmac_syscon },
> > + { .compatible = "loongson,ls1c-syscon", .data = &ls1c_dwmac_syscon },
> > + { }
> > +};o
>
> I am seeing a warning about ls1x_dwmac_syscon_match being unused.
> I think this is due to CONFIG_OF being unset.
Will fix these warnings.
>
> > +
> > +static int ls1x_dwmac_probe(struct platform_device *pdev)
> > +{
> > + struct plat_stmmacenet_data *plat_dat;
> > + struct stmmac_resources stmmac_res;
> > + struct device_node *syscon_np;
> > + const struct of_device_id *match;
> > + struct regmap *regmap;
> > + struct ls1x_dwmac *dwmac;
> > + const struct ls1x_dwmac_syscon *syscon;
> > + size_t size;
> > + int ret;
> > +
> > + ret = stmmac_get_platform_resources(pdev, &stmmac_res);
> > + if (ret)
> > + return ret;
> > +
> > + /* Probe syscon */
> > + syscon_np = of_parse_phandle(pdev->dev.of_node, "syscon", 0);
> > + if (!syscon_np)
> > + return -ENODEV;
> > +
> > + match = of_match_node(ls1x_dwmac_syscon_match, syscon_np);
> > + if (!match) {
> > + of_node_put(syscon_np);
> > + return -EINVAL;
> > + }
> > + syscon = (const struct ls1x_dwmac_syscon *)match->data;
> > +
> > + regmap = syscon_node_to_regmap(syscon_np);
> > + of_node_put(syscon_np);
> > + if (IS_ERR(regmap)) {
> > + ret = PTR_ERR(regmap);
> > + dev_err(&pdev->dev, "Unable to map syscon: %d\n", ret);
> > + return ret;
> > + }
> > +
> > + size = syscon->nr_reg_fields * sizeof(struct regmap_field *);
> > + dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac) + size, GFP_KERNEL);
> > + if (!dwmac)
> > + return -ENOMEM;
> > +
> > + plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
> > + if (IS_ERR(plat_dat)) {
> > + dev_err(&pdev->dev, "dt configuration failed\n");
> > + return PTR_ERR(plat_dat);
> > + }
> > +
> > + plat_dat->bsp_priv = dwmac;
> > + plat_dat->init = ls1x_dwmac_init;
> > + dwmac->dev = &pdev->dev;
> > + dwmac->plat_dat = plat_dat;
> > + dwmac->syscon = syscon;
> > + dwmac->regmap = regmap;
> > +
> > + ret = stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res);
> > + if (ret)
> > + goto err_remove_config_dt;
> > +
> > + return 0;
> > +
> > +err_remove_config_dt:
> > + if (pdev->dev.of_node)
> > + stmmac_remove_config_dt(pdev, plat_dat);
> > +
> > + return ret;
> > +}
>
> ...
--
Best regards,
Keguang Zhang
Hi Keguang,
kernel test robot noticed the following build errors:
[auto build test ERROR on 21ef7b1e17d039053edaeaf41142423810572741]
url: https://github.com/intel-lab-lkp/linux/commits/Keguang-Zhang/MIPS-loongson32-Remove-Loongson1-MAC-arch-code/20230812-231420
base: 21ef7b1e17d039053edaeaf41142423810572741
patch link: https://lore.kernel.org/r/20230812151135.1028780-5-keguang.zhang%40gmail.com
patch subject: [PATCH 4/5] net: stmmac: Add glue layer for Loongson-1 SoC
config: parisc-allyesconfig (https://download.01.org/0day-ci/archive/20230813/202308131600.I6iscZMl-lkp@intel.com/config)
compiler: hppa-linux-gcc (GCC) 12.3.0
reproduce: (https://download.01.org/0day-ci/archive/20230813/202308131600.I6iscZMl-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202308131600.I6iscZMl-lkp@intel.com/
All errors (new ones prefixed by >>):
drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c: In function 'ls1x_dwmac_probe':
>> drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c:188:21: error: implicit declaration of function 'of_parse_phandle' [-Werror=implicit-function-declaration]
188 | syscon_np = of_parse_phandle(pdev->dev.of_node, "syscon", 0);
| ^~~~~~~~~~~~~~~~
drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c:188:19: warning: assignment to 'struct device_node *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
188 | syscon_np = of_parse_phandle(pdev->dev.of_node, "syscon", 0);
| ^
>> drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c:192:17: error: implicit declaration of function 'of_match_node'; did you mean 'for_each_node'? [-Werror=implicit-function-declaration]
192 | match = of_match_node(ls1x_dwmac_syscon_match, syscon_np);
| ^~~~~~~~~~~~~
| for_each_node
drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c:192:15: warning: assignment to 'const struct of_device_id *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
192 | match = of_match_node(ls1x_dwmac_syscon_match, syscon_np);
| ^
>> drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c:194:17: error: implicit declaration of function 'of_node_put'; did you mean 'bpf_module_put'? [-Werror=implicit-function-declaration]
194 | of_node_put(syscon_np);
| ^~~~~~~~~~~
| bpf_module_put
cc1: some warnings being treated as errors
vim +/of_parse_phandle +188 drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
170
171 static int ls1x_dwmac_probe(struct platform_device *pdev)
172 {
173 struct plat_stmmacenet_data *plat_dat;
174 struct stmmac_resources stmmac_res;
175 struct device_node *syscon_np;
176 const struct of_device_id *match;
177 struct regmap *regmap;
178 struct ls1x_dwmac *dwmac;
179 const struct ls1x_dwmac_syscon *syscon;
180 size_t size;
181 int ret;
182
183 ret = stmmac_get_platform_resources(pdev, &stmmac_res);
184 if (ret)
185 return ret;
186
187 /* Probe syscon */
> 188 syscon_np = of_parse_phandle(pdev->dev.of_node, "syscon", 0);
189 if (!syscon_np)
190 return -ENODEV;
191
> 192 match = of_match_node(ls1x_dwmac_syscon_match, syscon_np);
193 if (!match) {
> 194 of_node_put(syscon_np);
195 return -EINVAL;
196 }
197 syscon = (const struct ls1x_dwmac_syscon *)match->data;
198
199 regmap = syscon_node_to_regmap(syscon_np);
200 of_node_put(syscon_np);
201 if (IS_ERR(regmap)) {
202 ret = PTR_ERR(regmap);
203 dev_err(&pdev->dev, "Unable to map syscon: %d\n", ret);
204 return ret;
205 }
206
207 size = syscon->nr_reg_fields * sizeof(struct regmap_field *);
208 dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac) + size, GFP_KERNEL);
209 if (!dwmac)
210 return -ENOMEM;
211
212 plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
213 if (IS_ERR(plat_dat)) {
214 dev_err(&pdev->dev, "dt configuration failed\n");
215 return PTR_ERR(plat_dat);
216 }
217
218 plat_dat->bsp_priv = dwmac;
219 plat_dat->init = ls1x_dwmac_init;
220 dwmac->dev = &pdev->dev;
221 dwmac->plat_dat = plat_dat;
222 dwmac->syscon = syscon;
223 dwmac->regmap = regmap;
224
225 ret = stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res);
226 if (ret)
227 goto err_remove_config_dt;
228
229 return 0;
230
231 err_remove_config_dt:
232 if (pdev->dev.of_node)
233 stmmac_remove_config_dt(pdev, plat_dat);
234
235 return ret;
236 }
237
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Hi Keguang,
kernel test robot noticed the following build warnings:
[auto build test WARNING on 21ef7b1e17d039053edaeaf41142423810572741]
url: https://github.com/intel-lab-lkp/linux/commits/Keguang-Zhang/MIPS-loongson32-Remove-Loongson1-MAC-arch-code/20230812-231420
base: 21ef7b1e17d039053edaeaf41142423810572741
patch link: https://lore.kernel.org/r/20230812151135.1028780-5-keguang.zhang%40gmail.com
patch subject: [PATCH 4/5] net: stmmac: Add glue layer for Loongson-1 SoC
config: parisc-allyesconfig (https://download.01.org/0day-ci/archive/20230813/202308130554.Rbxxtltt-lkp@intel.com/config)
compiler: hppa-linux-gcc (GCC) 12.3.0
reproduce: (https://download.01.org/0day-ci/archive/20230813/202308130554.Rbxxtltt-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202308130554.Rbxxtltt-lkp@intel.com/
All warnings (new ones prefixed by >>):
drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c: In function 'ls1x_dwmac_probe':
drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c:188:21: error: implicit declaration of function 'of_parse_phandle' [-Werror=implicit-function-declaration]
188 | syscon_np = of_parse_phandle(pdev->dev.of_node, "syscon", 0);
| ^~~~~~~~~~~~~~~~
>> drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c:188:19: warning: assignment to 'struct device_node *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
188 | syscon_np = of_parse_phandle(pdev->dev.of_node, "syscon", 0);
| ^
drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c:192:17: error: implicit declaration of function 'of_match_node'; did you mean 'for_each_node'? [-Werror=implicit-function-declaration]
192 | match = of_match_node(ls1x_dwmac_syscon_match, syscon_np);
| ^~~~~~~~~~~~~
| for_each_node
>> drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c:192:15: warning: assignment to 'const struct of_device_id *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
192 | match = of_match_node(ls1x_dwmac_syscon_match, syscon_np);
| ^
drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c:194:17: error: implicit declaration of function 'of_node_put'; did you mean 'bpf_module_put'? [-Werror=implicit-function-declaration]
194 | of_node_put(syscon_np);
| ^~~~~~~~~~~
| bpf_module_put
cc1: some warnings being treated as errors
vim +188 drivers/net/ethernet/stmicro/stmmac/dwmac-loongson1.c
170
171 static int ls1x_dwmac_probe(struct platform_device *pdev)
172 {
173 struct plat_stmmacenet_data *plat_dat;
174 struct stmmac_resources stmmac_res;
175 struct device_node *syscon_np;
176 const struct of_device_id *match;
177 struct regmap *regmap;
178 struct ls1x_dwmac *dwmac;
179 const struct ls1x_dwmac_syscon *syscon;
180 size_t size;
181 int ret;
182
183 ret = stmmac_get_platform_resources(pdev, &stmmac_res);
184 if (ret)
185 return ret;
186
187 /* Probe syscon */
> 188 syscon_np = of_parse_phandle(pdev->dev.of_node, "syscon", 0);
189 if (!syscon_np)
190 return -ENODEV;
191
> 192 match = of_match_node(ls1x_dwmac_syscon_match, syscon_np);
193 if (!match) {
194 of_node_put(syscon_np);
195 return -EINVAL;
196 }
197 syscon = (const struct ls1x_dwmac_syscon *)match->data;
198
199 regmap = syscon_node_to_regmap(syscon_np);
200 of_node_put(syscon_np);
201 if (IS_ERR(regmap)) {
202 ret = PTR_ERR(regmap);
203 dev_err(&pdev->dev, "Unable to map syscon: %d\n", ret);
204 return ret;
205 }
206
207 size = syscon->nr_reg_fields * sizeof(struct regmap_field *);
208 dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac) + size, GFP_KERNEL);
209 if (!dwmac)
210 return -ENOMEM;
211
212 plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
213 if (IS_ERR(plat_dat)) {
214 dev_err(&pdev->dev, "dt configuration failed\n");
215 return PTR_ERR(plat_dat);
216 }
217
218 plat_dat->bsp_priv = dwmac;
219 plat_dat->init = ls1x_dwmac_init;
220 dwmac->dev = &pdev->dev;
221 dwmac->plat_dat = plat_dat;
222 dwmac->syscon = syscon;
223 dwmac->regmap = regmap;
224
225 ret = stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res);
226 if (ret)
227 goto err_remove_config_dt;
228
229 return 0;
230
231 err_remove_config_dt:
232 if (pdev->dev.of_node)
233 stmmac_remove_config_dt(pdev, plat_dat);
234
235 return ret;
236 }
237
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
© 2016 - 2025 Red Hat, Inc.