[PATCH] net: designware: add Amlogic Meson8b & later glue driver

This adds a proper glue driver for the Designware DWMAC ethernet MAC IP found in the Amlogic Meson8, GXBB, GXL, GXM, G12A, G12B & SM1 SoCs.
This is aimed to replace the static ethernet link setup found on the board init code for the Amlogic SoC based boards.
Tested on a libretech-cc (S905x Internal RMII 10/100 PHY) and Khadas VIM3 (A113d with external 10/100/1000 RGMII PHY) to cover the most extreme setups.
Signed-off-by: Neil Armstrong narmstrong@baylibre.com --- drivers/net/Kconfig | 8 ++ drivers/net/Makefile | 1 + drivers/net/dwmac_meson8b.c | 150 ++++++++++++++++++++++++++++++++++++ 3 files changed, 159 insertions(+) create mode 100644 drivers/net/dwmac_meson8b.c
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index e1d3b26687..cf062fad4d 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -271,6 +271,14 @@ config ETH_DESIGNWARE 100Mbit and 1 Gbit operation. You must enable CONFIG_PHYLIB to provide the PHY (physical media interface).
+config ETH_DESIGNWARE_MESON8B + bool "Amlogic Meson8b and later glue driver for Synopsys Designware Ethernet MAC" + depends on DM_ETH + select ETH_DESIGNWARE + help + This provides glue layer to use Synopsys Designware Ethernet MAC + present on the Amlogic Meson8b, GX, AXG & G12A SoCs. + config ETH_DESIGNWARE_SOCFPGA select REGMAP select SYSCON diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 070ae7662c..ce7b9e3478 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_CORTINA_NI_ENET) += cortina_ni.o obj-$(CONFIG_CS8900) += cs8900.o obj-$(CONFIG_TULIP) += dc2114x.o obj-$(CONFIG_ETH_DESIGNWARE) += designware.o +obj-$(CONFIG_ETH_DESIGNWARE_MESON8B) += dwmac_meson8b.o obj-$(CONFIG_ETH_DESIGNWARE_SOCFPGA) += dwmac_socfpga.o obj-$(CONFIG_ETH_DESIGNWARE_S700) += dwmac_s700.o obj-$(CONFIG_DRIVER_DM9000) += dm9000x.o diff --git a/drivers/net/dwmac_meson8b.c b/drivers/net/dwmac_meson8b.c new file mode 100644 index 0000000000..c0b6ef4994 --- /dev/null +++ b/drivers/net/dwmac_meson8b.c @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2021 BayLibre, SAS + */ + +#include <common.h> +#include <asm/io.h> +#include <dm.h> +#include <phy.h> +#include "designware.h" +#include <dm/device_compat.h> +#include <linux/err.h> + +#define ETH_REG_0 0x0 +#define ETH_REG_1 0x4 +#define ETH_REG_2 0x18 +#define ETH_REG_3 0x1c + +#define GX_ETH_REG_0_PHY_INTF BIT(0) +#define GX_ETH_REG_0_TX_PHASE(x) (((x) & 3) << 5) +#define GX_ETH_REG_0_TX_RATIO(x) (((x) & 7) << 7) +#define GX_ETH_REG_0_PHY_CLK_EN BIT(10) +#define GX_ETH_REG_0_INVERT_RMII_CLK BIT(11) +#define GX_ETH_REG_0_CLK_EN BIT(12) + +#define AXG_ETH_REG_0_PHY_INTF_RGMII BIT(0) +#define AXG_ETH_REG_0_PHY_INTF_RMII BIT(2) +#define AXG_ETH_REG_0_TX_PHASE(x) (((x) & 3) << 5) +#define AXG_ETH_REG_0_TX_RATIO(x) (((x) & 7) << 7) +#define AXG_ETH_REG_0_PHY_CLK_EN BIT(10) +#define AXG_ETH_REG_0_INVERT_RMII_CLK BIT(11) +#define AXG_ETH_REG_0_CLK_EN BIT(12) + +struct dwmac_meson8b_plat { + struct dw_eth_pdata dw_eth_pdata; + int (*dwmac_setup)(struct udevice *dev, struct eth_pdata *edata); + void *regs; +}; + +static int dwmac_meson8b_of_to_plat(struct udevice *dev) +{ + struct dwmac_meson8b_plat *pdata = dev_get_plat(dev); + + pdata->regs = (void *)dev_read_addr_index(dev, 1); + if ((fdt_addr_t)pdata->regs == FDT_ADDR_T_NONE) + return -EINVAL; + + pdata->dwmac_setup = (void *)dev_get_driver_data(dev); + if (!pdata->dwmac_setup) + return -EINVAL; + + return designware_eth_of_to_plat(dev); +} + +static int dwmac_setup_axg(struct udevice *dev, struct eth_pdata *edata) +{ + struct dwmac_meson8b_plat *plat = dev_get_plat(dev); + + switch (edata->phy_interface) { + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: + /* Set RGMII mode */ + setbits_le32(plat->regs + ETH_REG_0, AXG_ETH_REG_0_PHY_INTF_RGMII | + AXG_ETH_REG_0_TX_PHASE(1) | + AXG_ETH_REG_0_TX_RATIO(4) | + AXG_ETH_REG_0_PHY_CLK_EN | + AXG_ETH_REG_0_CLK_EN); + break; + + case PHY_INTERFACE_MODE_RMII: + /* Set RMII mode */ + out_le32(plat->regs + ETH_REG_0, AXG_ETH_REG_0_PHY_INTF_RMII | + AXG_ETH_REG_0_INVERT_RMII_CLK | + AXG_ETH_REG_0_CLK_EN); + break; + default: + dev_err(dev, "Unsupported PHY mode\n"); + return -EINVAL; + } + + return 0; +} + +static int dwmac_setup_gx(struct udevice *dev, struct eth_pdata *edata) +{ + struct dwmac_meson8b_plat *plat = dev_get_plat(dev); + + switch (edata->phy_interface) { + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: + /* Set RGMII mode */ + setbits_le32(plat->regs + ETH_REG_0, GX_ETH_REG_0_PHY_INTF | + GX_ETH_REG_0_TX_PHASE(1) | + GX_ETH_REG_0_TX_RATIO(4) | + GX_ETH_REG_0_PHY_CLK_EN | + GX_ETH_REG_0_CLK_EN); + + break; + + case PHY_INTERFACE_MODE_RMII: + /* Set RMII mode */ + out_le32(plat->regs + ETH_REG_0, GX_ETH_REG_0_INVERT_RMII_CLK | + GX_ETH_REG_0_CLK_EN); + + if (!IS_ENABLED(CONFIG_MESON_GXBB)) + writel(0x10110181, plat->regs + ETH_REG_2); + + break; + default: + dev_err(dev, "Unsupported PHY mode\n"); + return -EINVAL; + } + + return 0; +} + +static int dwmac_meson8b_probe(struct udevice *dev) +{ + struct dwmac_meson8b_plat *pdata = dev_get_plat(dev); + struct eth_pdata *edata = &pdata->dw_eth_pdata.eth_pdata; + int ret; + + ret = pdata->dwmac_setup(dev, edata); + if (ret) + return ret; + + return designware_eth_probe(dev); +} + +static const struct udevice_id dwmac_meson8b_ids[] = { + { .compatible = "amlogic,meson-gxbb-dwmac", .data = (ulong)dwmac_setup_gx }, + { .compatible = "amlogic,meson-axg-dwmac", .data = (ulong)dwmac_setup_axg }, + { } +}; + +U_BOOT_DRIVER(dwmac_meson8b) = { + .name = "dwmac_meson8b", + .id = UCLASS_ETH, + .of_match = dwmac_meson8b_ids, + .of_to_plat = dwmac_meson8b_of_to_plat, + .probe = dwmac_meson8b_probe, + .ops = &designware_eth_ops, + .priv_auto = sizeof(struct dw_eth_dev), + .plat_auto = sizeof(struct dwmac_meson8b_plat), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +};

On 24/02/2021 20:33, Neil Armstrong wrote:
This adds a proper glue driver for the Designware DWMAC ethernet MAC IP found in the Amlogic Meson8, GXBB, GXL, GXM, G12A, G12B & SM1 SoCs.
This is aimed to replace the static ethernet link setup found on the board init code for the Amlogic SoC based boards.
Tested on a libretech-cc (S905x Internal RMII 10/100 PHY) and Khadas VIM3 (A113d with external 10/100/1000 RGMII PHY) to cover the most extreme setups.
Signed-off-by: Neil Armstrong narmstrong@baylibre.com
drivers/net/Kconfig | 8 ++ drivers/net/Makefile | 1 + drivers/net/dwmac_meson8b.c | 150 ++++++++++++++++++++++++++++++++++++ 3 files changed, 159 insertions(+) create mode 100644 drivers/net/dwmac_meson8b.c
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index e1d3b26687..cf062fad4d 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -271,6 +271,14 @@ config ETH_DESIGNWARE 100Mbit and 1 Gbit operation. You must enable CONFIG_PHYLIB to provide the PHY (physical media interface).
+config ETH_DESIGNWARE_MESON8B
- bool "Amlogic Meson8b and later glue driver for Synopsys Designware Ethernet MAC"
- depends on DM_ETH
- select ETH_DESIGNWARE
- help
This provides glue layer to use Synopsys Designware Ethernet MAC
present on the Amlogic Meson8b, GX, AXG & G12A SoCs.
config ETH_DESIGNWARE_SOCFPGA select REGMAP select SYSCON diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 070ae7662c..ce7b9e3478 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_CORTINA_NI_ENET) += cortina_ni.o obj-$(CONFIG_CS8900) += cs8900.o obj-$(CONFIG_TULIP) += dc2114x.o obj-$(CONFIG_ETH_DESIGNWARE) += designware.o +obj-$(CONFIG_ETH_DESIGNWARE_MESON8B) += dwmac_meson8b.o obj-$(CONFIG_ETH_DESIGNWARE_SOCFPGA) += dwmac_socfpga.o obj-$(CONFIG_ETH_DESIGNWARE_S700) += dwmac_s700.o obj-$(CONFIG_DRIVER_DM9000) += dm9000x.o diff --git a/drivers/net/dwmac_meson8b.c b/drivers/net/dwmac_meson8b.c new file mode 100644 index 0000000000..c0b6ef4994 --- /dev/null +++ b/drivers/net/dwmac_meson8b.c @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright (C) 2021 BayLibre, SAS
- */
+#include <common.h> +#include <asm/io.h> +#include <dm.h> +#include <phy.h> +#include "designware.h" +#include <dm/device_compat.h> +#include <linux/err.h>
+#define ETH_REG_0 0x0 +#define ETH_REG_1 0x4 +#define ETH_REG_2 0x18 +#define ETH_REG_3 0x1c
+#define GX_ETH_REG_0_PHY_INTF BIT(0) +#define GX_ETH_REG_0_TX_PHASE(x) (((x) & 3) << 5) +#define GX_ETH_REG_0_TX_RATIO(x) (((x) & 7) << 7) +#define GX_ETH_REG_0_PHY_CLK_EN BIT(10) +#define GX_ETH_REG_0_INVERT_RMII_CLK BIT(11) +#define GX_ETH_REG_0_CLK_EN BIT(12)
+#define AXG_ETH_REG_0_PHY_INTF_RGMII BIT(0) +#define AXG_ETH_REG_0_PHY_INTF_RMII BIT(2) +#define AXG_ETH_REG_0_TX_PHASE(x) (((x) & 3) << 5) +#define AXG_ETH_REG_0_TX_RATIO(x) (((x) & 7) << 7) +#define AXG_ETH_REG_0_PHY_CLK_EN BIT(10) +#define AXG_ETH_REG_0_INVERT_RMII_CLK BIT(11) +#define AXG_ETH_REG_0_CLK_EN BIT(12)
+struct dwmac_meson8b_plat {
- struct dw_eth_pdata dw_eth_pdata;
- int (*dwmac_setup)(struct udevice *dev, struct eth_pdata *edata);
- void *regs;
+};
+static int dwmac_meson8b_of_to_plat(struct udevice *dev) +{
- struct dwmac_meson8b_plat *pdata = dev_get_plat(dev);
- pdata->regs = (void *)dev_read_addr_index(dev, 1);
- if ((fdt_addr_t)pdata->regs == FDT_ADDR_T_NONE)
return -EINVAL;
- pdata->dwmac_setup = (void *)dev_get_driver_data(dev);
- if (!pdata->dwmac_setup)
return -EINVAL;
- return designware_eth_of_to_plat(dev);
+}
+static int dwmac_setup_axg(struct udevice *dev, struct eth_pdata *edata) +{
- struct dwmac_meson8b_plat *plat = dev_get_plat(dev);
- switch (edata->phy_interface) {
- case PHY_INTERFACE_MODE_RGMII:
- case PHY_INTERFACE_MODE_RGMII_ID:
- case PHY_INTERFACE_MODE_RGMII_RXID:
- case PHY_INTERFACE_MODE_RGMII_TXID:
/* Set RGMII mode */
setbits_le32(plat->regs + ETH_REG_0, AXG_ETH_REG_0_PHY_INTF_RGMII |
AXG_ETH_REG_0_TX_PHASE(1) |
AXG_ETH_REG_0_TX_RATIO(4) |
AXG_ETH_REG_0_PHY_CLK_EN |
AXG_ETH_REG_0_CLK_EN);
break;
- case PHY_INTERFACE_MODE_RMII:
/* Set RMII mode */
out_le32(plat->regs + ETH_REG_0, AXG_ETH_REG_0_PHY_INTF_RMII |
AXG_ETH_REG_0_INVERT_RMII_CLK |
AXG_ETH_REG_0_CLK_EN);
break;
- default:
dev_err(dev, "Unsupported PHY mode\n");
return -EINVAL;
- }
- return 0;
+}
+static int dwmac_setup_gx(struct udevice *dev, struct eth_pdata *edata) +{
- struct dwmac_meson8b_plat *plat = dev_get_plat(dev);
- switch (edata->phy_interface) {
- case PHY_INTERFACE_MODE_RGMII:
- case PHY_INTERFACE_MODE_RGMII_ID:
- case PHY_INTERFACE_MODE_RGMII_RXID:
- case PHY_INTERFACE_MODE_RGMII_TXID:
/* Set RGMII mode */
setbits_le32(plat->regs + ETH_REG_0, GX_ETH_REG_0_PHY_INTF |
GX_ETH_REG_0_TX_PHASE(1) |
GX_ETH_REG_0_TX_RATIO(4) |
GX_ETH_REG_0_PHY_CLK_EN |
GX_ETH_REG_0_CLK_EN);
break;
- case PHY_INTERFACE_MODE_RMII:
/* Set RMII mode */
out_le32(plat->regs + ETH_REG_0, GX_ETH_REG_0_INVERT_RMII_CLK |
GX_ETH_REG_0_CLK_EN);
if (!IS_ENABLED(CONFIG_MESON_GXBB))
writel(0x10110181, plat->regs + ETH_REG_2);
break;
- default:
dev_err(dev, "Unsupported PHY mode\n");
return -EINVAL;
- }
- return 0;
+}
+static int dwmac_meson8b_probe(struct udevice *dev) +{
- struct dwmac_meson8b_plat *pdata = dev_get_plat(dev);
- struct eth_pdata *edata = &pdata->dw_eth_pdata.eth_pdata;
- int ret;
- ret = pdata->dwmac_setup(dev, edata);
- if (ret)
return ret;
- return designware_eth_probe(dev);
+}
+static const struct udevice_id dwmac_meson8b_ids[] = {
- { .compatible = "amlogic,meson-gxbb-dwmac", .data = (ulong)dwmac_setup_gx },
- { .compatible = "amlogic,meson-axg-dwmac", .data = (ulong)dwmac_setup_axg },
- { }
+};
+U_BOOT_DRIVER(dwmac_meson8b) = {
- .name = "dwmac_meson8b",
- .id = UCLASS_ETH,
- .of_match = dwmac_meson8b_ids,
- .of_to_plat = dwmac_meson8b_of_to_plat,
- .probe = dwmac_meson8b_probe,
- .ops = &designware_eth_ops,
- .priv_auto = sizeof(struct dw_eth_dev),
- .plat_auto = sizeof(struct dwmac_meson8b_plat),
- .flags = DM_FLAG_ALLOC_PRIV_DMA,
+};
Applied to u-boot-amlogic-next
participants (1)
-
Neil Armstrong