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 <marex@denx.de>
Cc: Chin Liang See <chin.liang.see@intel.com>
Cc: Dinh Nguyen <dinguyen@kernel.org>
This commit is contained in:
Marek Vasut 2018-04-23 22:49:31 +02:00
parent 6b49cdd27e
commit 32f99757f4
4 changed files with 87 additions and 66 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)
{