blob: 90e7c9100e1211240168877a8c1d08afe51eeac6 [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2018, 2020 NXP
*
*/
#include <netdev.h>
#include <exports.h>
#include <fsl-mc/fsl_mc.h>
#include "lx2160a.h"
DECLARE_GLOBAL_DATA_PTR;
int board_eth_init(struct bd_info *bis)
{
#ifdef CONFIG_PHY_AQUANTIA
/*
* Export functions to be used by AQ firmware
* upload application
*/
gd->jt->strcpy = strcpy;
gd->jt->mdelay = mdelay;
gd->jt->mdio_get_current_dev = mdio_get_current_dev;
gd->jt->phy_find_by_mask = phy_find_by_mask;
gd->jt->mdio_phydev_for_ethname = mdio_phydev_for_ethname;
gd->jt->miiphy_set_current_dev = miiphy_set_current_dev;
#endif
return pci_eth_init(bis);
}
#if defined(CONFIG_RESET_PHY_R)
void reset_phy(void)
{
#if defined(CONFIG_FSL_MC_ENET)
mc_env_boot();
#endif
}
#endif /* CONFIG_RESET_PHY_R */
static int fdt_get_dpmac_node(void *fdt, int dpmac_id)
{
char dpmac_str[11] = "dpmacs@00";
int offset, dpmacs_offset;
/* get the dpmac offset */
dpmacs_offset = fdt_path_offset(fdt, "/soc/fsl-mc/dpmacs");
if (dpmacs_offset < 0)
dpmacs_offset = fdt_path_offset(fdt, "/fsl-mc/dpmacs");
if (dpmacs_offset < 0) {
printf("dpmacs node not found in device tree\n");
return dpmacs_offset;
}
sprintf(dpmac_str, "dpmac@%x", dpmac_id);
offset = fdt_subnode_offset(fdt, dpmacs_offset, dpmac_str);
if (offset < 0) {
sprintf(dpmac_str, "ethernet@%x", dpmac_id);
offset = fdt_subnode_offset(fdt, dpmacs_offset, dpmac_str);
if (offset < 0) {
printf("dpmac@%x/ethernet@%x node not found in device tree\n",
dpmac_id, dpmac_id);
return offset;
}
}
return offset;
}
static int fdt_update_phy_addr(void *fdt, int dpmac_id, int phy_addr)
{
char dpmac_str[] = "dpmacs@00";
const u32 *phyhandle;
int offset;
int err;
/* get the dpmac offset */
offset = fdt_get_dpmac_node(fdt, dpmac_id);
if (offset < 0)
return offset;
/* get dpmac phy-handle */
sprintf(dpmac_str, "dpmac@%x", dpmac_id);
phyhandle = (u32 *)fdt_getprop(fdt, offset, "phy-handle", NULL);
if (!phyhandle) {
printf("%s node not found in device tree\n", dpmac_str);
return offset;
}
offset = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*phyhandle));
if (offset < 0) {
printf("Could not get the ph node offset for dpmac %d\n",
dpmac_id);
return offset;
}
phy_addr = cpu_to_fdt32(phy_addr);
err = fdt_setprop(fdt, offset, "reg", &phy_addr, sizeof(phy_addr));
if (err < 0) {
printf("Could not set phy node's reg for dpmac %d: %s.\n",
dpmac_id, fdt_strerror(err));
return err;
}
return 0;
}
static int fdt_delete_phy_handle(void *fdt, int dpmac_id)
{
const u32 *phyhandle;
int offset;
/* get the dpmac offset */
offset = fdt_get_dpmac_node(fdt, dpmac_id);
if (offset < 0)
return offset;
/* verify if the node has a phy-handle */
phyhandle = (u32 *)fdt_getprop(fdt, offset, "phy-handle", NULL);
if (!phyhandle)
return 0;
return fdt_delprop(fdt, offset, "phy-handle");
}
int fdt_fixup_board_phy_revc(void *fdt)
{
int ret;
if (get_board_rev() < 'C')
return 0;
/* DPMACs 3,4 have their Aquantia PHYs at new addresses */
ret = fdt_update_phy_addr(fdt, 3, AQR113C_PHY_ADDR1);
if (ret)
return ret;
ret = fdt_update_phy_addr(fdt, 4, AQR113C_PHY_ADDR2);
if (ret)
return ret;
/* There is no PHY for the DPMAC2, so remove the phy-handle */
return fdt_delete_phy_handle(fdt, 2);
}