From c761028e34fe18e0cd63fd80d1317cf17c8895bf Mon Sep 17 00:00:00 2001 From: Florin Chiculita Date: Wed, 31 May 2023 18:02:18 +0300 Subject: [PATCH] board: fsl: lx2160ardb: add dts fixup function for RevC and newer Since the new RevC LX2160A-RDB board has its 10G Aquantia PHYs at different MDIO bus addresses, we must update both the kernel DTS and u-boot's DTS (in case of DM_ETH) in case the board is indeed RevC or newer. Use the newly introduced get_board_rev() function to trigger a fixup of the kernel DTS to properly match the actual PHY addresses. All this is encapsulated in the fdt_fixup_board_phy_revc() function which will be used in the next patch. Use the newly fdt_fixup_board_phy_revc() function introduced to update both kernel's DTS and u-boot's DTS. Signed-off-by: Florin Chiculita Signed-off-by: Ioana Ciornei Reviewed-by: Peng Fan Signed-off-by: Peng Fan --- board/freescale/lx2160a/eth_lx2160ardb.c | 107 +++++++++++++++++++++++++++++++ board/freescale/lx2160a/lx2160a.c | 7 ++ board/freescale/lx2160a/lx2160a.h | 6 ++ include/configs/lx2160ardb.h | 5 ++ 4 files changed, 125 insertions(+) diff --git a/board/freescale/lx2160a/eth_lx2160ardb.c b/board/freescale/lx2160a/eth_lx2160ardb.c index 533f606..c5dfefe 100644 --- a/board/freescale/lx2160a/eth_lx2160ardb.c +++ b/board/freescale/lx2160a/eth_lx2160ardb.c @@ -8,6 +8,7 @@ #include #include #include +#include "lx2160a.h" DECLARE_GLOBAL_DATA_PTR; @@ -36,3 +37,109 @@ void reset_phy(void) #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); +} diff --git a/board/freescale/lx2160a/lx2160a.c b/board/freescale/lx2160a/lx2160a.c index 4d406ac8..d631a11 100644 --- a/board/freescale/lx2160a/lx2160a.c +++ b/board/freescale/lx2160a/lx2160a.c @@ -133,6 +133,11 @@ int board_fix_fdt(void *fdt) fdt_setprop(fdt, off, "reg-names", reg_names, names_len); } + /* Fixup u-boot's DTS in case this is a revC board and + * we're using DM_ETH. + */ + if (IS_ENABLED(CONFIG_TARGET_LX2160ARDB) && IS_ENABLED(CONFIG_DM_ETH)) + fdt_fixup_board_phy_revc(fdt); return 0; } #endif @@ -636,6 +641,8 @@ void fdt_fixup_board_enet(void *fdt) if (get_mc_boot_status() == 0 && (is_lazy_dpl_addr_valid() || get_dpl_apply_status() == 0)) { fdt_status_okay(fdt, offset); + if (IS_ENABLED(CONFIG_TARGET_LX2160ARDB)) + fdt_fixup_board_phy_revc(fdt); } else { fdt_status_fail(fdt, offset); } diff --git a/board/freescale/lx2160a/lx2160a.h b/board/freescale/lx2160a/lx2160a.h index 13673fc..61a8bb9 100644 --- a/board/freescale/lx2160a/lx2160a.h +++ b/board/freescale/lx2160a/lx2160a.h @@ -60,11 +60,17 @@ #if IS_ENABLED(CONFIG_TARGET_LX2160ARDB) u8 get_board_rev(void); +int fdt_fixup_board_phy_revc(void *fdt); #else static inline u8 get_board_rev(void) { return 0; } + +static inline int fdt_fixup_board_phy_revc(void *fdt) +{ + return 0; +} #endif #endif /* __LX2160_H */ diff --git a/include/configs/lx2160ardb.h b/include/configs/lx2160ardb.h index 8cc4e0d..6404b35 100644 --- a/include/configs/lx2160ardb.h +++ b/include/configs/lx2160ardb.h @@ -11,6 +11,11 @@ /* RTC */ #define CFG_SYS_RTC_BUS_NUM 4 +#if defined(CONFIG_FSL_MC_ENET) +#define AQR113C_PHY_ADDR1 0x0 +#define AQR113C_PHY_ADDR2 0x08 +#endif + /* EMC2305 */ #define I2C_MUX_CH_EMC2305 0x09 #define I2C_EMC2305_ADDR 0x4D -- 2.7.4