From 32f99757f4af48d1e51fdc8817bfed4337dead42 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 23 Apr 2018 22:49:31 +0200 Subject: [PATCH] ARM: socfpga: Repair A10 EMAC reset handling The EMAC reset and PHY mode configuration was never working on the Arria10 SoC, fix this. This patch pulls out the common code into misc.c and passes the SoC-specific function call in as a function pointer. Signed-off-by: Marek Vasut Cc: Chin Liang See Cc: Dinh Nguyen --- .../mach-socfpga/include/mach/reset_manager.h | 2 + arch/arm/mach-socfpga/misc.c | 65 ++++++++++++++++++ arch/arm/mach-socfpga/misc_arria10.c | 19 +++++- arch/arm/mach-socfpga/misc_gen5.c | 67 ++----------------- 4 files changed, 87 insertions(+), 66 deletions(-) diff --git a/arch/arm/mach-socfpga/include/mach/reset_manager.h b/arch/arm/mach-socfpga/include/mach/reset_manager.h index d3ae80bc27..8ee801c635 100644 --- a/arch/arm/mach-socfpga/include/mach/reset_manager.h +++ b/arch/arm/mach-socfpga/include/mach/reset_manager.h @@ -10,6 +10,8 @@ void reset_cpu(ulong addr); void socfpga_per_reset(u32 reset, int set); void socfpga_per_reset_all(void); +int socfpga_eth_reset_common(void (*resetfn)(const u8 of_reset_id, + const u8 phymode)); #define RSTMGR_CTRL_SWWARMRSTREQ_LSB 1 diff --git a/arch/arm/mach-socfpga/misc.c b/arch/arm/mach-socfpga/misc.c index 5c27f1984e..7bedcb36f4 100644 --- a/arch/arm/mach-socfpga/misc.c +++ b/arch/arm/mach-socfpga/misc.c @@ -135,3 +135,68 @@ int arch_cpu_init(void) return 0; } + +#ifdef CONFIG_ETH_DESIGNWARE +static int dwmac_phymode_to_modereg(const char *phymode, u32 *modereg) +{ + if (!phymode) + return -EINVAL; + + if (!strcmp(phymode, "mii") || !strcmp(phymode, "gmii")) { + *modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII; + return 0; + } + + if (!strcmp(phymode, "rgmii")) { + *modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII; + return 0; + } + + if (!strcmp(phymode, "rmii")) { + *modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII; + return 0; + } + + return -EINVAL; +} + +int socfpga_eth_reset_common(void (*resetfn)(const u8 of_reset_id, + const u8 phymode)) +{ + const void *fdt = gd->fdt_blob; + struct fdtdec_phandle_args args; + const char *phy_mode; + u32 phy_modereg; + int nodes[2]; /* Max. two GMACs */ + int ret, count; + int i, node; + + count = fdtdec_find_aliases_for_id(fdt, "ethernet", + COMPAT_ALTERA_SOCFPGA_DWMAC, + nodes, ARRAY_SIZE(nodes)); + for (i = 0; i < count; i++) { + node = nodes[i]; + if (node <= 0) + continue; + + ret = fdtdec_parse_phandle_with_args(fdt, node, "resets", + "#reset-cells", 1, 0, + &args); + if (ret || (args.args_count != 1)) { + debug("GMAC%i: Failed to parse DT 'resets'!\n", i); + continue; + } + + phy_mode = fdt_getprop(fdt, node, "phy-mode", NULL); + ret = dwmac_phymode_to_modereg(phy_mode, &phy_modereg); + if (ret) { + debug("GMAC%i: Failed to parse DT 'phy-mode'!\n", i); + continue; + } + + resetfn(args.args[0], phy_modereg); + } + + return 0; +} +#endif diff --git a/arch/arm/mach-socfpga/misc_arria10.c b/arch/arm/mach-socfpga/misc_arria10.c index f909568312..e1d80a5a76 100644 --- a/arch/arm/mach-socfpga/misc_arria10.c +++ b/arch/arm/mach-socfpga/misc_arria10.c @@ -41,8 +41,7 @@ static struct socfpga_system_manager *sysmgr_regs = * DesignWare Ethernet initialization */ #ifdef CONFIG_ETH_DESIGNWARE -void dwmac_deassert_reset(const unsigned int of_reset_id, - const u32 phymode) +static void arria10_dwmac_reset(const u8 of_reset_id, const u8 phymode) { u32 reset; @@ -64,6 +63,20 @@ void dwmac_deassert_reset(const unsigned int of_reset_id, /* 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) @@ -251,6 +264,6 @@ int print_cpuinfo(void) #ifdef CONFIG_ARCH_MISC_INIT int arch_misc_init(void) { - return 0; + return socfpga_eth_reset(); } #endif diff --git a/arch/arm/mach-socfpga/misc_gen5.c b/arch/arm/mach-socfpga/misc_gen5.c index efec58d555..434373404e 100644 --- a/arch/arm/mach-socfpga/misc_gen5.c +++ b/arch/arm/mach-socfpga/misc_gen5.c @@ -38,8 +38,7 @@ static struct scu_registers *scu_regs = * DesignWare Ethernet initialization */ #ifdef CONFIG_ETH_DESIGNWARE -void dwmac_deassert_reset(const unsigned int of_reset_id, - const u32 phymode) +static void gen5_dwmac_reset(const u8 of_reset_id, const u8 phymode) { u32 physhift, reset; @@ -63,71 +62,13 @@ void dwmac_deassert_reset(const unsigned int of_reset_id, socfpga_per_reset(reset, 0); } -static u32 dwmac_phymode_to_modereg(const char *phymode, u32 *modereg) -{ - if (!phymode) - return -EINVAL; - - if (!strcmp(phymode, "mii") || !strcmp(phymode, "gmii")) { - *modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII; - return 0; - } - - if (!strcmp(phymode, "rgmii")) { - *modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII; - return 0; - } - - if (!strcmp(phymode, "rmii")) { - *modereg = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII; - return 0; - } - - return -EINVAL; -} - static int socfpga_eth_reset(void) { - const void *fdt = gd->fdt_blob; - struct fdtdec_phandle_args args; - const char *phy_mode; - u32 phy_modereg; - int nodes[2]; /* Max. two GMACs */ - int ret, count; - int i, node; - - /* Put both GMACs into RESET state. */ + /* Put all GMACs into RESET state. */ socfpga_per_reset(SOCFPGA_RESET(EMAC0), 1); socfpga_per_reset(SOCFPGA_RESET(EMAC1), 1); - - count = fdtdec_find_aliases_for_id(fdt, "ethernet", - COMPAT_ALTERA_SOCFPGA_DWMAC, - nodes, ARRAY_SIZE(nodes)); - for (i = 0; i < count; i++) { - node = nodes[i]; - if (node <= 0) - continue; - - ret = fdtdec_parse_phandle_with_args(fdt, node, "resets", - "#reset-cells", 1, 0, - &args); - if (ret || (args.args_count != 1)) { - debug("GMAC%i: Failed to parse DT 'resets'!\n", i); - continue; - } - - phy_mode = fdt_getprop(fdt, node, "phy-mode", NULL); - ret = dwmac_phymode_to_modereg(phy_mode, &phy_modereg); - if (ret) { - debug("GMAC%i: Failed to parse DT 'phy-mode'!\n", i); - continue; - } - - dwmac_deassert_reset(args.args[0], phy_modereg); - } - - return 0; -} + return socfpga_eth_reset_common(gen5_dwmac_reset); +}; #else static int socfpga_eth_reset(void) { -- 2.39.2