<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p>Dear Paul,</p>
    <p>Thank you for the reply!<br>
    </p>
    <div class="moz-cite-prefix">Paul Menzel 於 1/14/2025 9:49 AM 寫道:<br>
    </div>
    <blockquote type="cite"
      cite="mid:a30b338f-0a6f-47e7-922b-c637a6648a6d@molgen.mpg.de">Dear
      Joey,
      <br>
      <br>
      <br>
      Thank you for your patch.
      <br>
      <br>
      Am 13.01.25 um 00:54 schrieb Joey Lu:
      <br>
      <blockquote type="cite">Add support for Gigabit Ethernet on
        Nuvoton MA35 series using dwmac driver.
        <br>
      </blockquote>
      <br>
      It’d be great if you added the datasheet name and revision to the
      commit message.
      <br>
    </blockquote>
    <br>
    <p>I will update the commit message in the next patch.</p>
    <p>For reference, the datasheet is <strong>MA35D1 Series Datasheet</strong>.</p>
    <blockquote type="cite"
      cite="mid:a30b338f-0a6f-47e7-922b-c637a6648a6d@molgen.mpg.de">
      <br>
      Also, please document how tested the driver. Maybe even paste new
      log messages.
      <br>
    </blockquote>
    <p>These are the kernel configurations for testing the MA35D1 GMAC
      driver: ARCH_MA35, STMMAC_PLATFORM, DWMAC_NUVOTON.<br>
    </p>
    <p>I'm not sure if this information is sufficient, so please provide
      some guidance on what else I should include to meet your
      requirements.</p>
    <p>I will include the log messages at the end of the email.</p>
    <blockquote type="cite"
      cite="mid:a30b338f-0a6f-47e7-922b-c637a6648a6d@molgen.mpg.de">
      <br>
      <blockquote type="cite">Reviewed-by: Andrew Lunn
        <a class="moz-txt-link-rfc2396E" href="mailto:andrew@lunn.ch"><andrew@lunn.ch></a>
        <br>
        Signed-off-by: Joey Lu <a class="moz-txt-link-rfc2396E" href="mailto:a0987203069@gmail.com"><a0987203069@gmail.com></a>
        <br>
      </blockquote>
      <br>
      As you use your company email address in the AUTHOR line below,
      please also add that email address to the commit message (and
      maybe even as the author).
      <br>
      <br>
    </blockquote>
    I will update the AUTHOR to use my personal email address instead of
    the company email.
    <blockquote type="cite"
      cite="mid:a30b338f-0a6f-47e7-922b-c637a6648a6d@molgen.mpg.de">
      <blockquote type="cite">---
        <br>
          drivers/net/ethernet/stmicro/stmmac/Kconfig   |  11 ++
        <br>
          drivers/net/ethernet/stmicro/stmmac/Makefile  |   1 +
        <br>
          .../ethernet/stmicro/stmmac/dwmac-nuvoton.c   | 179
        ++++++++++++++++++
        <br>
          3 files changed, 191 insertions(+)
        <br>
          create mode 100644
        drivers/net/ethernet/stmicro/stmmac/dwmac-nuvoton.c
        <br>
        <br>
        diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig
        b/drivers/net/ethernet/stmicro/stmmac/Kconfig
        <br>
        index 4cc85a36a1ab..2b424544cf6f 100644
        <br>
        --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
        <br>
        +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
        <br>
        @@ -121,6 +121,17 @@ config DWMAC_MESON
        <br>
                the stmmac device driver. This driver is used for
        Meson6,
        <br>
                Meson8, Meson8b and GXBB SoCs.
        <br>
          +config DWMAC_NUVOTON
        <br>
        +    tristate "Nuvoton MA35 dwmac support"
        <br>
        +    default ARCH_MA35
        <br>
        +    depends on OF && (ARCH_MA35 || COMPILE_TEST)
        <br>
        +    select MFD_SYSCON
        <br>
        +    help
        <br>
        +      Support for Ethernet controller on Nuvoton MA35 series
        SoC.
        <br>
        +
        <br>
        +      This selects the Nuvoton MA35 series SoC glue layer
        support
        <br>
        +      for the stmmac device driver.
        <br>
      </blockquote>
      <br>
      Also mention the module name `dwmac-nuvoton`?
      <br>
      <br>
    </blockquote>
    Got it!<br>
    <blockquote type="cite"
      cite="mid:a30b338f-0a6f-47e7-922b-c637a6648a6d@molgen.mpg.de">
      <blockquote type="cite">+
        <br>
          config DWMAC_QCOM_ETHQOS
        <br>
              tristate "Qualcomm ETHQOS support"
        <br>
              default ARCH_QCOM
        <br>
        diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile
        b/drivers/net/ethernet/stmicro/stmmac/Makefile
        <br>
        index b26f0e79c2b3..48e25b85ea06 100644
        <br>
        --- a/drivers/net/ethernet/stmicro/stmmac/Makefile
        <br>
        +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
        <br>
        @@ -19,6 +19,7 @@ obj-$(CONFIG_DWMAC_IPQ806X)    +=
        dwmac-ipq806x.o
        <br>
          obj-$(CONFIG_DWMAC_LPC18XX)    += dwmac-lpc18xx.o
        <br>
          obj-$(CONFIG_DWMAC_MEDIATEK)    += dwmac-mediatek.o
        <br>
          obj-$(CONFIG_DWMAC_MESON)    += dwmac-meson.o dwmac-meson8b.o
        <br>
        +obj-$(CONFIG_DWMAC_NUVOTON)    += dwmac-nuvoton.o
        <br>
          obj-$(CONFIG_DWMAC_QCOM_ETHQOS)    += dwmac-qcom-ethqos.o
        <br>
          obj-$(CONFIG_DWMAC_ROCKCHIP)    += dwmac-rk.o
        <br>
          obj-$(CONFIG_DWMAC_RZN1)    += dwmac-rzn1.o
        <br>
        diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-nuvoton.c
        b/drivers/net/ethernet/stmicro/stmmac/dwmac-nuvoton.c
        <br>
        new file mode 100644
        <br>
        index 000000000000..edf1b88ce1cd
        <br>
        --- /dev/null
        <br>
        +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-nuvoton.c
        <br>
        @@ -0,0 +1,179 @@
        <br>
        +// SPDX-License-Identifier: GPL-2.0-only
        <br>
        +/*
        <br>
        + * Nuvoton DWMAC specific glue layer
        <br>
        + *
        <br>
        + * Copyright (C) 2024 Nuvoton Technology Corp.
        <br>
        + *
        <br>
        + * Author: Joey Lu <a class="moz-txt-link-rfc2396E" href="mailto:yclu4@nuvoton.com"><yclu4@nuvoton.com></a>
        <br>
        + */
        <br>
        +
        <br>
        +#include <linux/mfd/syscon.h>
        <br>
        +#include <linux/of_device.h>
        <br>
        +#include <linux/of_net.h>
        <br>
        +#include <linux/platform_device.h>
        <br>
        +#include <linux/regmap.h>
        <br>
        +#include <linux/stmmac.h>
        <br>
        +
        <br>
        +#include "stmmac.h"
        <br>
        +#include "stmmac_platform.h"
        <br>
        +
        <br>
        +#define NVT_REG_SYS_GMAC0MISCR  0x108
        <br>
        +#define NVT_REG_SYS_GMAC1MISCR  0x10C
        <br>
        +
        <br>
        +#define NVT_MISCR_RMII          BIT(0)
        <br>
        +
        <br>
        +/* 2000ps is mapped to 0x0 ~ 0xF */
        <br>
      </blockquote>
      <br>
      Excuse my ignorance: What is ps?
      <br>
      <br>
    </blockquote>
    Sorry for the confusion. I will include a complete and clear
    description in the next patch.
    <blockquote type="cite"
      cite="mid:a30b338f-0a6f-47e7-922b-c637a6648a6d@molgen.mpg.de">
      <blockquote type="cite">+#define NVT_PATH_DELAY_DEC      134
        <br>
        +#define NVT_TX_DELAY_MASK       GENMASK(19, 16)
        <br>
        +#define NVT_RX_DELAY_MASK       GENMASK(23, 20)
        <br>
        +
        <br>
        +struct nvt_priv_data {
        <br>
        +    struct platform_device *pdev;
        <br>
        +    struct regmap *regmap;
        <br>
        +};
        <br>
        +
        <br>
        +static struct nvt_priv_data *
        <br>
        +nvt_gmac_setup(struct platform_device *pdev, struct
        plat_stmmacenet_data *plat)
        <br>
        +{
        <br>
        +    struct device *dev = &pdev->dev;
        <br>
        +    struct nvt_priv_data *bsp_priv;
        <br>
        +    phy_interface_t phy_mode;
        <br>
        +    u32 tx_delay, rx_delay;
        <br>
      </blockquote>
      <br>
      Please append the unit to the variable name.
      <br>
      <br>
    </blockquote>
    Got it!<br>
    <blockquote type="cite"
      cite="mid:a30b338f-0a6f-47e7-922b-c637a6648a6d@molgen.mpg.de">
      <blockquote type="cite">+    u32 macid, arg, reg;
        <br>
        +
        <br>
        +    bsp_priv = devm_kzalloc(dev, sizeof(*bsp_priv),
        GFP_KERNEL);
        <br>
        +    if (!bsp_priv)
        <br>
        +        return ERR_PTR(-ENOMEM);
        <br>
        +
        <br>
        +    bsp_priv->regmap =
        <br>
        +        syscon_regmap_lookup_by_phandle_args(dev->of_node,
        "nuvoton,sys", 1, &macid);
        <br>
        +    if (IS_ERR(bsp_priv->regmap)) {
        <br>
        +        dev_err_probe(dev, PTR_ERR(bsp_priv->regmap),
        "Failed to get sys register\n");
        <br>
        +        return ERR_PTR(-ENODEV);
        <br>
        +    }
        <br>
        +    if (macid > 1) {
        <br>
        +        dev_err_probe(dev, -EINVAL, "Invalid sys arguments\n");
        <br>
        +        return ERR_PTR(-EINVAL);
        <br>
        +    }
        <br>
        +
        <br>
        +    if (of_property_read_u32(dev->of_node,
        "tx-internal-delay-ps", &arg)) {
        <br>
        +        tx_delay = 0;
        <br>
        +    } else {
        <br>
        +        if (arg <= 2000) {
        <br>
        +            tx_delay = (arg == 2000) ? 0xF : (arg /
        NVT_PATH_DELAY_DEC);
        <br>
      </blockquote>
      <br>
      Write hexcharacters lowercase?
      <br>
      <br>
    </blockquote>
    Got it!<br>
    <blockquote type="cite"
      cite="mid:a30b338f-0a6f-47e7-922b-c637a6648a6d@molgen.mpg.de">
      <blockquote type="cite">+            dev_dbg(dev, "Set Tx path
        delay to 0x%x\n", tx_delay);
        <br>
        +        } else {
        <br>
        +            dev_err(dev, "Invalid Tx path delay argument.\n");
        <br>
        +            return ERR_PTR(-EINVAL);
        <br>
        +        }
        <br>
        +    }
        <br>
        +    if (of_property_read_u32(dev->of_node,
        "rx-internal-delay-ps", &arg)) {
        <br>
        +        rx_delay = 0;
        <br>
        +    } else {
        <br>
        +        if (arg <= 2000) {
        <br>
        +            rx_delay = (arg == 2000) ? 0xF : (arg /
        NVT_PATH_DELAY_DEC);
        <br>
        +            dev_dbg(dev, "Set Rx path delay to 0x%x\n",
        rx_delay);
        <br>
        +        } else {
        <br>
        +            dev_err(dev, "Invalid Rx path delay argument.\n");
        <br>
        +            return ERR_PTR(-EINVAL);
        <br>
        +        }
        <br>
        +    }
        <br>
        +
        <br>
        +    regmap_read(bsp_priv->regmap,
        <br>
        +            macid == 0 ? NVT_REG_SYS_GMAC0MISCR :
        NVT_REG_SYS_GMAC1MISCR, &reg);
        <br>
        +    reg &= ~(NVT_TX_DELAY_MASK | NVT_RX_DELAY_MASK);
        <br>
        +
        <br>
        +    if (of_get_phy_mode(pdev->dev.of_node, &phy_mode)) {
        <br>
        +        dev_err(dev, "missing phy mode property\n");
        <br>
        +        return ERR_PTR(-EINVAL);
        <br>
        +    }
        <br>
        +
        <br>
        +    switch (phy_mode) {
        <br>
        +    case PHY_INTERFACE_MODE_RGMII:
        <br>
        +    case PHY_INTERFACE_MODE_RGMII_ID:
        <br>
        +    case PHY_INTERFACE_MODE_RGMII_RXID:
        <br>
        +    case PHY_INTERFACE_MODE_RGMII_TXID:
        <br>
        +        reg &= ~NVT_MISCR_RMII;
        <br>
        +        break;
        <br>
        +    case PHY_INTERFACE_MODE_RMII:
        <br>
        +        reg |= NVT_MISCR_RMII;
        <br>
        +        break;
        <br>
        +    default:
        <br>
        +        dev_err(dev, "Unsupported phy-mode (%d)\n", phy_mode);
        <br>
        +        return ERR_PTR(-EINVAL);
        <br>
        +    }
        <br>
        +
        <br>
        +    if (!(reg & NVT_MISCR_RMII)) {
        <br>
        +        reg |= FIELD_PREP(NVT_TX_DELAY_MASK, tx_delay);
        <br>
        +        reg |= FIELD_PREP(NVT_RX_DELAY_MASK, rx_delay);
        <br>
        +    }
        <br>
        +
        <br>
        +    regmap_write(bsp_priv->regmap,
        <br>
        +             macid == 0 ? NVT_REG_SYS_GMAC0MISCR :
        NVT_REG_SYS_GMAC1MISCR, reg);
        <br>
        +
        <br>
        +    bsp_priv->pdev = pdev;
        <br>
        +
        <br>
        +    return bsp_priv;
        <br>
        +}
        <br>
        +
        <br>
        +static int nvt_gmac_probe(struct platform_device *pdev)
        <br>
        +{
        <br>
        +    struct plat_stmmacenet_data *plat_dat;
        <br>
        +    struct stmmac_resources stmmac_res;
        <br>
        +    struct nvt_priv_data *priv_data;
        <br>
        +    int ret;
        <br>
        +
        <br>
        +    ret = stmmac_get_platform_resources(pdev, &stmmac_res);
        <br>
        +    if (ret)
        <br>
        +        return ret;
        <br>
        +
        <br>
        +    plat_dat = devm_stmmac_probe_config_dt(pdev,
        stmmac_res.mac);
        <br>
        +    if (IS_ERR(plat_dat))
        <br>
        +        return PTR_ERR(plat_dat);
        <br>
        +
        <br>
        +    /* Nuvoton DWMAC configs */
        <br>
        +    plat_dat->has_gmac = 1;
        <br>
        +    plat_dat->tx_fifo_size = 2048;
        <br>
        +    plat_dat->rx_fifo_size = 4096;
        <br>
        +    plat_dat->multicast_filter_bins = 0;
        <br>
        +    plat_dat->unicast_filter_entries = 8;
        <br>
        +    plat_dat->flags &= ~STMMAC_FLAG_USE_PHY_WOL;
        <br>
        +
        <br>
        +    priv_data = nvt_gmac_setup(pdev, plat_dat);
        <br>
        +    if (IS_ERR(priv_data))
        <br>
        +        return PTR_ERR(priv_data);
        <br>
        +
        <br>
        +    ret = stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res);
        <br>
        +    if (ret)
        <br>
        +        return ret;
        <br>
        +
        <br>
        +    /* The PMT flag is determined by the RWK property.
        <br>
        +     * However, our hardware is configured to support only MGK.
        <br>
        +     * This is an override on PMT to enable WoL capability.
        <br>
        +     */
        <br>
        +    plat_dat->pmt = 1;
        <br>
        +    device_set_wakeup_capable(&pdev->dev, 1);
        <br>
        +
        <br>
        +    return 0;
        <br>
        +}
        <br>
        +
        <br>
        +static const struct of_device_id nvt_dwmac_match[] = {
        <br>
        +    { .compatible = "nuvoton,ma35d1-dwmac"},
        <br>
        +    { }
        <br>
        +};
        <br>
        +MODULE_DEVICE_TABLE(of, nvt_dwmac_match);
        <br>
        +
        <br>
        +static struct platform_driver nvt_dwmac_driver = {
        <br>
        +    .probe  = nvt_gmac_probe,
        <br>
        +    .remove = stmmac_pltfr_remove,
        <br>
        +    .driver = {
        <br>
        +        .name           = "nuvoton-dwmac",
        <br>
        +        .pm        = &stmmac_pltfr_pm_ops,
        <br>
        +        .of_match_table = nvt_dwmac_match,
        <br>
        +    },
        <br>
        +};
        <br>
        +module_platform_driver(nvt_dwmac_driver);
        <br>
        +
        <br>
        +MODULE_AUTHOR("Joey Lu <a class="moz-txt-link-rfc2396E" href="mailto:yclu4@nuvoton.com"><yclu4@nuvoton.com></a>");
        <br>
      </blockquote>
      <br>
      Maybe Nuvoton can set up a generic address?
      <br>
      <br>
    </blockquote>
    I will switch to using my personal email instead.🙂
    <blockquote type="cite"
      cite="mid:a30b338f-0a6f-47e7-922b-c637a6648a6d@molgen.mpg.de">
      <blockquote type="cite">+MODULE_DESCRIPTION("Nuvoton DWMAC
        specific glue layer");
        <br>
        +MODULE_LICENSE("GPL v2");
        <br>
      </blockquote>
      <br>
      <br>
      Kind regards,
      <br>
      <br>
      Paul
      <br>
    </blockquote>
    <p>BR,</p>
    <p>Joey</p>
    <p><br>
    </p>
    <p>log:<br>
    </p>
    <p>[    T0] Booting Linux on physical CPU 0x0000000000 [0x411fd040]<br>
      [    T0] Linux version 6.13.0-rc7 (joeylu@ubuntu)
      (aarch64-nuvoton-linux-gnu-gcc.br_real (Buildroot 2021.02.6)
      9.4.0, GNU ld (GNU Binutils) 2.35.2)<br>
      [    T0] Machine model: Nuvoton MA35D1-SOM<br>
      [    T0] Memory limited to 248MB<br>
      ...</p>
    <p>[    T1] nuvoton-dwmac 40120000.ethernet: IRQ eth_wake_irq not
      found<br>
      [    T1] nuvoton-dwmac 40120000.ethernet: IRQ eth_lpi not found<br>
      [    T1] nuvoton-dwmac 40120000.ethernet: IRQ sfty not found<br>
      [    T1] nuvoton-dwmac 40120000.ethernet: User ID: 0x10, Synopsys
      ID: 0x37<br>
      [    T1] nuvoton-dwmac 40120000.ethernet:       DWMAC1000<br>
      [    T1] nuvoton-dwmac 40120000.ethernet: DMA HW capability
      register supported<br>
      [    T1] nuvoton-dwmac 40120000.ethernet: RX Checksum Offload
      Engine supported<br>
      [    T1] nuvoton-dwmac 40120000.ethernet: COE Type 2<br>
      [    T1] nuvoton-dwmac 40120000.ethernet: TX Checksum insertion
      supported<br>
      [    T1] nuvoton-dwmac 40120000.ethernet: Enhanced/Alternate
      descriptors<br>
      [    T1] nuvoton-dwmac 40120000.ethernet: Enabled extended
      descriptors<br>
      [    T1] nuvoton-dwmac 40120000.ethernet: Ring mode enabled<br>
      [    T1] nuvoton-dwmac 40120000.ethernet: Enable RX Mitigation via
      HW Watchdog Timer<br>
      [    T1] nuvoton-dwmac 40130000.ethernet: IRQ eth_wake_irq not
      found<br>
      [    T1] nuvoton-dwmac 40130000.ethernet: IRQ eth_lpi not found<br>
      [    T1] nuvoton-dwmac 40130000.ethernet: IRQ sfty not found<br>
      [    T1] nuvoton-dwmac 40130000.ethernet: User ID: 0x10, Synopsys
      ID: 0x37<br>
      [    T1] nuvoton-dwmac 40130000.ethernet:       DWMAC1000<br>
      [    T1] nuvoton-dwmac 40130000.ethernet: DMA HW capability
      register supported<br>
      [    T1] nuvoton-dwmac 40130000.ethernet: RX Checksum Offload
      Engine supported<br>
      [    T1] nuvoton-dwmac 40130000.ethernet: COE Type 2<br>
      [    T1] nuvoton-dwmac 40130000.ethernet: TX Checksum insertion
      supported<br>
      [    T1] nuvoton-dwmac 40130000.ethernet: Enhanced/Alternate
      descriptors<br>
      [    T1] nuvoton-dwmac 40130000.ethernet: Enabled extended
      descriptors<br>
      [    T1] nuvoton-dwmac 40130000.ethernet: Ring mode enabled<br>
      [    T1] nuvoton-dwmac 40130000.ethernet: Enable RX Mitigation via
      HW Watchdog Timer<br>
      ...<br>
      <br>
      # udhcpc -i eth0<br>
      udhcpc: started, v1.33.1<br>
      [   T93] nuvoton-dwmac 40120000.ethernet eth0: Register
      MEM_TYPE_PAGE_POOL RxQ-0<br>
      [   T93] nuvoton-dwmac 40120000.ethernet eth0: PHY [stmmac-0:00]
      driver [Generic PHY] (irq=POLL)<br>
      [   T93] nuvoton-dwmac 40120000.ethernet eth0: No Safety Features
      support found<br>
      [   T93] nuvoton-dwmac 40120000.ethernet eth0: No MAC Management
      Counters available<br>
      [   T93] nuvoton-dwmac 40120000.ethernet eth0: IEEE 1588-2008
      Advanced Timestamp supported<br>
      [   T93] nuvoton-dwmac 40120000.ethernet eth0: registered PTP
      clock<br>
      [   T93] nuvoton-dwmac 40120000.ethernet eth0: configuring for
      phy/rgmii-id link mode<br>
      udhcpc: sending discover<br>
      udhcpc: sending discover<br>
      [   T33] nuvoton-dwmac 40120000.ethernet eth0: Link is Up -
      1Gbps/Full - flow control rx/tx<br>
      udhcpc: sending discover<br>
      udhcpc: sending select for 192.168.0.103<br>
      udhcpc: lease of 192.168.0.103 obtained, lease time 86400<br>
      deleting routers<br>
      adding dns 192.168.0.1<br>
      <br>
    </p>
  </body>
</html>