[U-Boot] [PATCH 1/3] net: designware: socfpga: Add Arria10 extras

Add wrapper around the designware MAC driver to handle the SoCFPGA specific configuration bits. On Arria10, this is configuration of syscon phy_intf.
Signed-off-by: Marek Vasut marex@denx.de Cc: Chin Liang See chin.liang.see@intel.com Cc: Dinh Nguyen dinguyen@kernel.org Cc: Ley Foon Tan ley.foon.tan@intel.com Cc: Joe Hershberger joe.hershberger@ni.com --- NOTE: This driver is not enabled on Gen5 or Stratix10 as the implementation for its specifics is missing thus far. The driver can be safely enabled though, as the behavior of the plain designware mac driver will be retained. --- drivers/net/Kconfig | 8 +++ drivers/net/Makefile | 1 + drivers/net/dwmac_socfpga.c | 143 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 152 insertions(+) create mode 100644 drivers/net/dwmac_socfpga.c
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index f762b0898d..d86da7760e 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -150,6 +150,14 @@ config ETH_DESIGNWARE 100Mbit and 1 Gbit operation. You must enable CONFIG_PHYLIB to provide the PHY (physical media interface).
+config ETH_DESIGNWARE_SOCFPGA + bool "Altera SoCFPGA extras for Synopsys Designware Ethernet MAC" + depends on DM_ETH && ETH_DESIGNWARE + help + The Altera SoCFPGA requires additional configuration of the + Altera system manager to correctly interface with the PHY. + This code handles those SoC specifics. + config ETHOC bool "OpenCores 10/100 Mbps Ethernet MAC" help diff --git a/drivers/net/Makefile b/drivers/net/Makefile index c1ed44e21f..48a2878071 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_CALXEDA_XGMAC) += calxedaxgmac.o obj-$(CONFIG_CS8900) += cs8900.o obj-$(CONFIG_TULIP) += dc2114x.o obj-$(CONFIG_ETH_DESIGNWARE) += designware.o +obj-$(CONFIG_ETH_DESIGNWARE_SOCFPGA) += dwmac_socfpga.o obj-$(CONFIG_DRIVER_DM9000) += dm9000x.o obj-$(CONFIG_DNET) += dnet.o obj-$(CONFIG_E1000) += e1000.o diff --git a/drivers/net/dwmac_socfpga.c b/drivers/net/dwmac_socfpga.c new file mode 100644 index 0000000000..08fc9677c4 --- /dev/null +++ b/drivers/net/dwmac_socfpga.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Marek Vasut marex@denx.de + * + * Altera SoCFPGA EMAC extras + */ + +#include <common.h> +#include <asm/io.h> +#include <dm.h> +#include <clk.h> +#include <phy.h> +#include <regmap.h> +#include <reset.h> +#include <syscon.h> +#include "designware.h" + +#include <asm/arch/system_manager.h> + +enum dwmac_type { + DWMAC_SOCFPGA_GEN5 = 0, + DWMAC_SOCFPGA_ARRIA10, + DWMAC_SOCFPGA_STRATIX10, +}; + +struct dwmac_socfpga_platdata { + struct dw_eth_pdata dw_eth_pdata; + enum dwmac_type type; + void *phy_intf; +}; + +static int dwmac_socfpga_ofdata_to_platdata(struct udevice *dev) +{ + struct dwmac_socfpga_platdata *pdata = dev_get_platdata(dev); + struct regmap *regmap; + struct ofnode_phandle_args args; + void *range; + int ret; + + ret = dev_read_phandle_with_args(dev, "altr,sysmgr-syscon", NULL, + 2, 0, &args); + if (ret) { + dev_err(dev, "Failed to get syscon: %d\n", ret); + return ret; + } + + if (args.args_count != 2) { + dev_err(dev, "Invalid number of syscon args\n"); + return -EINVAL; + } + + regmap = syscon_node_to_regmap(args.node); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); + dev_err(dev, "Failed to get regmap: %d\n", ret); + return ret; + } + + range = regmap_get_range(regmap, 0); + if (!range) { + dev_err(dev, "Failed to get regmap range\n"); + return -ENOMEM; + } + + pdata->phy_intf = range + args.args[0]; + + /* + * Sadly, the Altera DT bindings don't have SoC-specific compatibles, + * so we have to guesstimate which SoC we are running on from the + * DWMAC version. Luckily, Altera at least updated the DWMAC with + * each SoC. + */ + if (ofnode_device_is_compatible(dev->node, "snps,dwmac-3.70a")) + pdata->type = DWMAC_SOCFPGA_GEN5; + + if (ofnode_device_is_compatible(dev->node, "snps,dwmac-3.72a")) + pdata->type = DWMAC_SOCFPGA_ARRIA10; + + if (ofnode_device_is_compatible(dev->node, "snps,dwmac-3.74a")) + pdata->type = DWMAC_SOCFPGA_STRATIX10; + + return designware_eth_ofdata_to_platdata(dev); +} + +static int dwmac_socfpga_probe(struct udevice *dev) +{ + struct dwmac_socfpga_platdata *pdata = dev_get_platdata(dev); + struct eth_pdata *edata = &pdata->dw_eth_pdata.eth_pdata; + struct reset_ctl_bulk reset_bulk; + int ret; + u8 modereg; + + if (pdata->type == DWMAC_SOCFPGA_ARRIA10) { + switch (edata->phy_interface) { + case PHY_INTERFACE_MODE_MII: + case PHY_INTERFACE_MODE_GMII: + modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII; + break; + case PHY_INTERFACE_MODE_RMII: + modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII; + break; + case PHY_INTERFACE_MODE_RGMII: + modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII; + break; + default: + dev_err(dev, "Unsupported PHY mode\n"); + return -EINVAL; + } + + ret = reset_get_bulk(dev, &reset_bulk); + if (ret) { + dev_err(dev, "Failed to get reset: %d\n", ret); + return ret; + } + + reset_assert_bulk(&reset_bulk); + + clrsetbits_le32(pdata->phy_intf, + SYSMGR_EMACGRP_CTRL_PHYSEL_MASK, + modereg); + + reset_release_bulk(&reset_bulk); + } + + return designware_eth_probe(dev); +} + +static const struct udevice_id dwmac_socfpga_ids[] = { + { .compatible = "altr,socfpga-stmmac" }, + { } +}; + +U_BOOT_DRIVER(dwmac_socfpga) = { + .name = "dwmac_socfpga", + .id = UCLASS_ETH, + .of_match = dwmac_socfpga_ids, + .ofdata_to_platdata = dwmac_socfpga_ofdata_to_platdata, + .probe = dwmac_socfpga_probe, + .ops = &designware_eth_ops, + .priv_auto_alloc_size = sizeof(struct dw_eth_dev), + .platdata_auto_alloc_size = sizeof(struct dwmac_socfpga_platdata), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +};

Remove code from the reset manager that is never called.
Signed-off-by: Marek Vasut marex@denx.de Cc: Chin Liang See chin.liang.see@intel.com Cc: Dinh Nguyen dinguyen@kernel.org Cc: Ley Foon Tan ley.foon.tan@intel.com --- .../include/mach/reset_manager_arria10.h | 3 - arch/arm/mach-socfpga/reset_manager_arria10.c | 123 --------------------- 2 files changed, 126 deletions(-)
diff --git a/arch/arm/mach-socfpga/include/mach/reset_manager_arria10.h b/arch/arm/mach-socfpga/include/mach/reset_manager_arria10.h index 66c70128b4..6623ebee65 100644 --- a/arch/arm/mach-socfpga/include/mach/reset_manager_arria10.h +++ b/arch/arm/mach-socfpga/include/mach/reset_manager_arria10.h @@ -10,10 +10,7 @@
void socfpga_watchdog_disable(void); void socfpga_reset_deassert_noc_ddr_scheduler(void); -int socfpga_is_wdt_in_reset(void); -void socfpga_emac_manage_reset(ulong emacbase, u32 state); int socfpga_reset_deassert_bridges_handoff(void); -void socfpga_reset_assert_fpga_connected_peripherals(void); void socfpga_reset_deassert_osc1wd0(void); int socfpga_bridges_reset(void);
diff --git a/arch/arm/mach-socfpga/reset_manager_arria10.c b/arch/arm/mach-socfpga/reset_manager_arria10.c index bcdb349752..471a3045af 100644 --- a/arch/arm/mach-socfpga/reset_manager_arria10.c +++ b/arch/arm/mach-socfpga/reset_manager_arria10.c @@ -20,59 +20,6 @@ static const struct socfpga_reset_manager *reset_manager_base = static const struct socfpga_system_manager *sysmgr_regs = (struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS;
-#define ECC_MASK (ALT_RSTMGR_PER0MODRST_EMACECC0_SET_MSK | \ - ALT_RSTMGR_PER0MODRST_EMACECC1_SET_MSK | \ - ALT_RSTMGR_PER0MODRST_EMACECC2_SET_MSK | \ - ALT_RSTMGR_PER0MODRST_NANDECC_SET_MSK | \ - ALT_RSTMGR_PER0MODRST_QSPIECC_SET_MSK | \ - ALT_RSTMGR_PER0MODRST_SDMMCECC_SET_MSK) - -static const u32 per0fpgamasks[] = { - ALT_RSTMGR_PER0MODRST_EMACECC0_SET_MSK | - ALT_RSTMGR_PER0MODRST_EMAC0_SET_MSK, - ALT_RSTMGR_PER0MODRST_EMACECC1_SET_MSK | - ALT_RSTMGR_PER0MODRST_EMAC1_SET_MSK, - ALT_RSTMGR_PER0MODRST_EMACECC2_SET_MSK | - ALT_RSTMGR_PER0MODRST_EMAC2_SET_MSK, - 0, /* i2c0 per1mod */ - 0, /* i2c1 per1mod */ - 0, /* i2c0_emac */ - 0, /* i2c1_emac */ - 0, /* i2c2_emac */ - ALT_RSTMGR_PER0MODRST_NANDECC_SET_MSK | - ALT_RSTMGR_PER0MODRST_NAND_SET_MSK, - ALT_RSTMGR_PER0MODRST_QSPIECC_SET_MSK | - ALT_RSTMGR_PER0MODRST_QSPI_SET_MSK, - ALT_RSTMGR_PER0MODRST_SDMMCECC_SET_MSK | - ALT_RSTMGR_PER0MODRST_SDMMC_SET_MSK, - ALT_RSTMGR_PER0MODRST_SPIM0_SET_MSK, - ALT_RSTMGR_PER0MODRST_SPIM1_SET_MSK, - ALT_RSTMGR_PER0MODRST_SPIS0_SET_MSK, - ALT_RSTMGR_PER0MODRST_SPIS1_SET_MSK, - 0, /* uart0 per1mod */ - 0, /* uart1 per1mod */ -}; - -static const u32 per1fpgamasks[] = { - 0, /* emac0 per0mod */ - 0, /* emac1 per0mod */ - 0, /* emac2 per0mod */ - ALT_RSTMGR_PER1MODRST_I2C0_SET_MSK, - ALT_RSTMGR_PER1MODRST_I2C1_SET_MSK, - ALT_RSTMGR_PER1MODRST_I2C2_SET_MSK, /* i2c0_emac */ - ALT_RSTMGR_PER1MODRST_I2C3_SET_MSK, /* i2c1_emac */ - ALT_RSTMGR_PER1MODRST_I2C4_SET_MSK, /* i2c2_emac */ - 0, /* nand per0mod */ - 0, /* qspi per0mod */ - 0, /* sdmmc per0mod */ - 0, /* spim0 per0mod */ - 0, /* spim1 per0mod */ - 0, /* spis0 per0mod */ - 0, /* spis1 per0mod */ - ALT_RSTMGR_PER1MODRST_UART0_SET_MSK, - ALT_RSTMGR_PER1MODRST_UART1_SET_MSK, -}; - struct bridge_cfg { int compat_id; u32 mask_noc; @@ -127,56 +74,6 @@ void socfpga_reset_deassert_noc_ddr_scheduler(void) ALT_RSTMGR_BRGMODRST_DDRSCH_SET_MSK); }
-/* Check whether Watchdog in reset state? */ -int socfpga_is_wdt_in_reset(void) -{ - u32 val; - - val = readl(&reset_manager_base->per1modrst); - val &= ALT_RSTMGR_PER1MODRST_WD0_SET_MSK; - - /* return 0x1 if watchdog in reset */ - return val; -} - -/* emacbase: base address of emac to enable/disable reset - * state: 0 - disable reset, !0 - enable reset - */ -void socfpga_emac_manage_reset(ulong emacbase, u32 state) -{ - ulong eccmask; - ulong emacmask; - - switch (emacbase) { - case SOCFPGA_EMAC0_ADDRESS: - eccmask = ALT_RSTMGR_PER0MODRST_EMACECC0_SET_MSK; - emacmask = ALT_RSTMGR_PER0MODRST_EMAC0_SET_MSK; - break; - case SOCFPGA_EMAC1_ADDRESS: - eccmask = ALT_RSTMGR_PER0MODRST_EMACECC1_SET_MSK; - emacmask = ALT_RSTMGR_PER0MODRST_EMAC1_SET_MSK; - break; - case SOCFPGA_EMAC2_ADDRESS: - eccmask = ALT_RSTMGR_PER0MODRST_EMACECC2_SET_MSK; - emacmask = ALT_RSTMGR_PER0MODRST_EMAC2_SET_MSK; - break; - default: - pr_err("emac base address unexpected! %lx", emacbase); - hang(); - break; - } - - if (state) { - /* Enable ECC OCP first */ - setbits_le32(&reset_manager_base->per0modrst, eccmask); - setbits_le32(&reset_manager_base->per0modrst, emacmask); - } else { - /* Disable ECC OCP first */ - clrbits_le32(&reset_manager_base->per0modrst, emacmask); - clrbits_le32(&reset_manager_base->per0modrst, eccmask); - } -} - static int get_bridge_init_val(const void *blob, int compat_id) { int node; @@ -213,26 +110,6 @@ int socfpga_reset_deassert_bridges_handoff(void) false, 1000, false); }
-void socfpga_reset_assert_fpga_connected_peripherals(void) -{ - u32 mask0 = 0; - u32 mask1 = 0; - u32 fpga_pinux_addr = SOCFPGA_PINMUX_FPGA_INTERFACE_ADDRESS; - int i; - - for (i = 0; i < ARRAY_SIZE(per1fpgamasks); i++) { - if (readl(fpga_pinux_addr)) { - mask0 |= per0fpgamasks[i]; - mask1 |= per1fpgamasks[i]; - } - fpga_pinux_addr += sizeof(u32); - } - - setbits_le32(&reset_manager_base->per0modrst, mask0 & ECC_MASK); - setbits_le32(&reset_manager_base->per1modrst, mask1); - setbits_le32(&reset_manager_base->per0modrst, mask0); -} - /* Release L4 OSC1 Watchdog Timer 0 from reset through reset manager */ void socfpga_reset_deassert_osc1wd0(void) {

Remove ad-hoc ethernet syscon registers configuration and reset support. Reset is now handled by the reset framework and the syscon registers are set in the dwmac_socfpga.c driver.
Signed-off-by: Marek Vasut marex@denx.de Cc: Chin Liang See chin.liang.see@intel.com Cc: Dinh Nguyen dinguyen@kernel.org Cc: Ley Foon Tan ley.foon.tan@intel.com --- arch/arm/Kconfig | 2 +- arch/arm/mach-socfpga/Kconfig | 5 ++++ arch/arm/mach-socfpga/misc_arria10.c | 49 ------------------------------------ 3 files changed, 6 insertions(+), 50 deletions(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 63ec02403a..9f5eaf8591 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -772,7 +772,7 @@ config ARCH_SNAPDRAGON config ARCH_SOCFPGA bool "Altera SOCFPGA family" select ARCH_EARLY_INIT_R - select ARCH_MISC_INIT + select ARCH_MISC_INIT if !TARGET_SOCFPGA_ARRIA10 select ARM64 if TARGET_SOCFPGA_STRATIX10 select CPU_V7A if TARGET_SOCFPGA_GEN5 || TARGET_SOCFPGA_ARRIA10 select DM diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig index 63ce32ff66..80be1dc30a 100644 --- a/arch/arm/mach-socfpga/Kconfig +++ b/arch/arm/mach-socfpga/Kconfig @@ -14,6 +14,11 @@ config TARGET_SOCFPGA_ARRIA10 select DM_I2C select DM_RESET select SPL_DM_RESET if SPL + select REGMAP + select SPL_REGMAP if SPL + select SYSCON + select SPL_SYSCON if SPL + select ETH_DESIGNWARE_SOCFPGA
config TARGET_SOCFPGA_CYCLONE5 bool diff --git a/arch/arm/mach-socfpga/misc_arria10.c b/arch/arm/mach-socfpga/misc_arria10.c index b59953068d..284e076ad6 100644 --- a/arch/arm/mach-socfpga/misc_arria10.c +++ b/arch/arm/mach-socfpga/misc_arria10.c @@ -38,48 +38,6 @@ static const struct socfpga_noc_fw_ocram *noc_fw_ocram_base = static struct socfpga_system_manager *sysmgr_regs = (struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS;
-/* - * DesignWare Ethernet initialization - */ -#ifdef CONFIG_ETH_DESIGNWARE -static void arria10_dwmac_reset(const u8 of_reset_id, const u8 phymode) -{ - u32 reset; - - if (of_reset_id == EMAC0_RESET) { - reset = SOCFPGA_RESET(EMAC0); - } else if (of_reset_id == EMAC1_RESET) { - reset = SOCFPGA_RESET(EMAC1); - } else if (of_reset_id == EMAC2_RESET) { - reset = SOCFPGA_RESET(EMAC2); - } else { - printf("GMAC: Invalid reset ID (%i)!\n", of_reset_id); - return; - } - - clrsetbits_le32(&sysmgr_regs->emac[of_reset_id - EMAC0_RESET], - SYSMGR_EMACGRP_CTRL_PHYSEL_MASK, - phymode); - - /* Release the EMAC controller from reset */ - socfpga_per_reset(reset, 0); -} - -static int socfpga_eth_reset(void) -{ - /* Put all GMACs into RESET state. */ - socfpga_per_reset(SOCFPGA_RESET(EMAC0), 1); - socfpga_per_reset(SOCFPGA_RESET(EMAC1), 1); - socfpga_per_reset(SOCFPGA_RESET(EMAC2), 1); - return socfpga_eth_reset_common(arria10_dwmac_reset); -}; -#else -static int socfpga_eth_reset(void) -{ - return 0; -}; -#endif - #if defined(CONFIG_SPL_BUILD) /* + * This function initializes security policies to be consistent across @@ -143,13 +101,6 @@ int print_cpuinfo(void) } #endif
-#ifdef CONFIG_ARCH_MISC_INIT -int arch_misc_init(void) -{ - return socfpga_eth_reset(); -} -#endif - void do_bridge_reset(int enable) { if (enable)

Hi Marek,
On Mon, Aug 13, 2018 at 1:56 PM, Marek Vasut marex@denx.de wrote:
Add wrapper around the designware MAC driver to handle the SoCFPGA specific configuration bits. On Arria10, this is configuration of syscon phy_intf.
Signed-off-by: Marek Vasut marex@denx.de Cc: Chin Liang See chin.liang.see@intel.com Cc: Dinh Nguyen dinguyen@kernel.org Cc: Ley Foon Tan ley.foon.tan@intel.com Cc: Joe Hershberger joe.hershberger@ni.com
Looks good, but can you add something in doc/device-tree-bindings?
Acked-by: Joe Hershberger joe.hershberger@ni.com
NOTE: This driver is not enabled on Gen5 or Stratix10 as the implementation for its specifics is missing thus far. The driver can be safely enabled though, as the behavior of the plain designware mac driver will be retained.
participants (2)
-
Joe Hershberger
-
Marek Vasut