diff options
Diffstat (limited to 'board')
-rw-r--r-- | board/freescale/common/Kconfig | 1 | ||||
-rw-r--r-- | board/freescale/common/Makefile | 1 | ||||
-rw-r--r-- | board/freescale/common/i2c_mux.c | 24 | ||||
-rw-r--r-- | board/freescale/common/i2c_mux.h | 3 | ||||
-rw-r--r-- | board/freescale/common/qsfp_eeprom.c | 90 | ||||
-rw-r--r-- | board/freescale/common/qsfp_eeprom.h | 14 | ||||
-rw-r--r-- | board/freescale/ls1021aiot/ls1021aiot.c | 10 | ||||
-rw-r--r-- | board/freescale/ls1021aqds/eth.c | 5 | ||||
-rw-r--r-- | board/freescale/ls1028a/ls1028a.c | 7 | ||||
-rw-r--r-- | board/freescale/ls1043ardb/cpld.c | 6 | ||||
-rw-r--r-- | board/freescale/ls1043ardb/cpld.h | 1 | ||||
-rw-r--r-- | board/freescale/ls1043ardb/ls1043ardb.c | 79 | ||||
-rw-r--r-- | board/freescale/lx2160a/Kconfig | 9 | ||||
-rw-r--r-- | board/freescale/lx2160a/eth_lx2160aqds.c | 5 | ||||
-rw-r--r-- | board/freescale/lx2160a/eth_lx2160ardb.c | 160 | ||||
-rw-r--r-- | board/freescale/lx2160a/lx2160a.c | 57 | ||||
-rw-r--r-- | board/freescale/lx2160a/lx2160a.h | 20 |
17 files changed, 474 insertions, 18 deletions
diff --git a/board/freescale/common/Kconfig b/board/freescale/common/Kconfig index 77d5ca722c..f4ceb21469 100644 --- a/board/freescale/common/Kconfig +++ b/board/freescale/common/Kconfig @@ -3,6 +3,7 @@ config CHAIN_OF_TRUST imply CMD_BLOB imply CMD_HASH if ARM select FSL_CAAM + select ARCH_MISC_INIT select SPL_BOARD_INIT if (ARM && SPL) select SPL_HASH if (ARM && SPL) select SHA_HW_ACCEL diff --git a/board/freescale/common/Makefile b/board/freescale/common/Makefile index f285d3f3ab..18854df253 100644 --- a/board/freescale/common/Makefile +++ b/board/freescale/common/Makefile @@ -78,6 +78,7 @@ endif obj-$(CONFIG_LS102XA_STREAM_ID) += ls102xa_stream_id.o obj-$(CONFIG_EMC2305) += emc2305.o +obj-$(CONFIG_QSFP_EEPROM) += qsfp_eeprom.o # deal with common files for P-series corenet based devices obj-$(CONFIG_TARGET_P2041RDB) += p_corenet/ diff --git a/board/freescale/common/i2c_mux.c b/board/freescale/common/i2c_mux.c index 54f89e2576..9523dd0942 100644 --- a/board/freescale/common/i2c_mux.c +++ b/board/freescale/common/i2c_mux.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ /* * Copyright 2014 Freescale Semiconductor, Inc. - * Copyright 2020-21 NXP + * Copyright 2020-2022 NXP * Copyright 2021 Microsoft Corporation */ @@ -37,4 +37,26 @@ int select_i2c_ch_pca9547(u8 ch, int bus) return 0; } +#ifdef I2C_MUX_PCA_ADDR_SEC +int select_i2c_ch_pca9547_sec(u8 ch, int bus) +{ + int ret; + DEVICE_HANDLE_T dev; + + /* Open device handle */ + ret = fsl_i2c_get_device(I2C_MUX_PCA_ADDR_SEC, bus, &dev); + if (ret) { + printf("PCA: No PCA9547 device found\n"); + return ret; + } + + ret = I2C_WRITE(dev, 0, &ch, sizeof(ch)); + if (ret) { + printf("PCA: Unable to select channel %d (%d)\n", (int)ch, ret); + return ret; + } + + return 0; +} +#endif #endif diff --git a/board/freescale/common/i2c_mux.h b/board/freescale/common/i2c_mux.h index 0870c1918e..b58a284326 100644 --- a/board/freescale/common/i2c_mux.h +++ b/board/freescale/common/i2c_mux.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright 2014 Freescale Semiconductor, Inc. - * Copyright 2020-21 NXP + * Copyright 2020-2022 NXP * Copyright 2021 Microsoft Corporation */ @@ -10,6 +10,7 @@ #ifdef CONFIG_FSL_USE_PCA9547_MUX int select_i2c_ch_pca9547(u8 ch, int bus); +int select_i2c_ch_pca9547_sec(u8 ch, int bus); #endif #endif diff --git a/board/freescale/common/qsfp_eeprom.c b/board/freescale/common/qsfp_eeprom.c new file mode 100644 index 0000000000..d57a10d663 --- /dev/null +++ b/board/freescale/common/qsfp_eeprom.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2019-2022 NXP + */ +#include <common.h> +#include <command.h> +#include <i2c.h> +#include <linux/ctype.h> + +#define DEV_ID_QSFP 0x0c +#define DEV_ID_QSFP_PLUS 0x0d + +static struct __attribute__ ((__packed__)) qsfp_eeprom_map { + struct __attribute__ ((__packed__)) qsfp_low_mem { + /* field byte address */ + u8 identifier; /* 0 */ + u16 status; /* 1-2 */ + u8 reserved[124]; /* 3-126 */ + u8 page_select; /* 127 */ + } base; + + struct __attribute__ ((__packed__)) qsfp_page00_mem { + /* field byte address */ + u8 identifier; /* 128 */ + u8 ext_identifier; /* 129 */ + u8 connector; /* 130 */ + u8 compat[8]; /* 131-138 */ + u8 reserved[3]; /* 139-142 */ + u8 length_fiber[4]; + u8 length_copper; /* 146 */ + u8 tech; /* 147 */ + u8 vendor_name[16]; /* 148-163 */ + u8 reserved2; /* 164 */ + u8 oui[3]; /* 165-167 */ + u8 pn[16]; /* 168-183 */ + u8 rev[2]; /* 184-185 */ + u8 reserved3[10]; /* 186-195 */ + u8 serial[16]; /* 196-211 */ + u8 date[8]; /* 212-219 */ + u8 reserved4[35]; /* 220-255 */ + } page0; +} qsfp; + +unsigned char get_qsfp_compat0(void) +{ + int ret; + char vendor[20] = {0}; + char serial[20] = {0}; + char pname[20] = {0}; + char mfgdt[20] = {0}; +#ifdef CONFIG_DM_I2C + struct udevice *dev; +#endif + + memset(&qsfp, 0, sizeof(qsfp)); +#ifndef CONFIG_DM_I2C + ret = i2c_read(I2C_SFP_EEPROM_ADDR, + 0, + I2C_SFP_EEPROM_ADDR_LEN, + (void *)&qsfp, + sizeof(qsfp)); +#else + ret = i2c_get_chip_for_busnum(0, I2C_SFP_EEPROM_ADDR, 1, &dev); + if (!ret) + ret = dm_i2c_read(dev, 0, (void *)&qsfp, sizeof(qsfp)); +#endif + + if (ret != 0) { + debug("\nQSFP: no module detected\n"); + return 0; + } + /* check if QSFP type */ + if (qsfp.base.identifier != DEV_ID_QSFP_PLUS) { + debug("\nQSFP: unrecognized module\n"); + return 0; + } + + /* copy fields and trim the whitespaces and dump on screen */ + snprintf(vendor, sizeof(vendor), "%.16s", qsfp.page0.vendor_name); + snprintf(serial, sizeof(serial), "%.16s", qsfp.page0.serial); + snprintf(pname, sizeof(pname), "%.16s", qsfp.page0.pn); + snprintf(mfgdt, sizeof(mfgdt), "%.2s/%.2s/%.2s", + &qsfp.page0.date[0], &qsfp.page0.date[2], &qsfp.page0.date[4]); + + printf("QSFP: detected %s %s s/n: %s mfgdt: %s\n", + strim(vendor), strim(pname), strim(serial), strim(mfgdt)); + + /* return ethernet compatibility code*/ + return qsfp.page0.compat[0]; +} diff --git a/board/freescale/common/qsfp_eeprom.h b/board/freescale/common/qsfp_eeprom.h new file mode 100644 index 0000000000..4aab21997f --- /dev/null +++ b/board/freescale/common/qsfp_eeprom.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2019-2022 NXP + */ + +#ifndef __QSFP_EEPROM_H_ +#define __QSFP_EEPROM_H_ +/* + * QSFP eeprom reader external API interface. + */ + +/* return the ethernet compatibility field 0 */ +unsigned char get_qsfp_compat0(void); +#endif /* __QSFP_EEPROM_H_ */ diff --git a/board/freescale/ls1021aiot/ls1021aiot.c b/board/freescale/ls1021aiot/ls1021aiot.c index 5ab03b3340..5d0dd3afdc 100644 --- a/board/freescale/ls1021aiot/ls1021aiot.c +++ b/board/freescale/ls1021aiot/ls1021aiot.c @@ -121,7 +121,10 @@ int board_eth_init(struct bd_info *bis) if (is_serdes_configured(SGMII_TSEC1)) { puts("eTSEC1 is in sgmii mode.\n"); tsec_info[num].flags |= TSEC_SGMII; - } + tsec_info[num].interface = PHY_INTERFACE_MODE_SGMII; + } else { + tsec_info[num].interface = PHY_INTERFACE_MODE_NONE; + } num++; #endif #ifdef CONFIG_TSEC2 @@ -129,7 +132,10 @@ int board_eth_init(struct bd_info *bis) if (is_serdes_configured(SGMII_TSEC2)) { puts("eTSEC2 is in sgmii mode.\n"); tsec_info[num].flags |= TSEC_SGMII; - } + tsec_info[num].interface = PHY_INTERFACE_MODE_SGMII; + } else { + tsec_info[num].interface = PHY_INTERFACE_MODE_NONE; + } num++; #endif if (!num) { diff --git a/board/freescale/ls1021aqds/eth.c b/board/freescale/ls1021aqds/eth.c index a9f162b974..177323031c 100644 --- a/board/freescale/ls1021aqds/eth.c +++ b/board/freescale/ls1021aqds/eth.c @@ -141,8 +141,10 @@ int board_eth_init(struct bd_info *bis) puts("eTSEC1 is in sgmii mode\n"); tsec_info[num].flags |= TSEC_SGMII; tsec_info[num].mii_devname = "LS1021A_SGMII_MDIO"; + tsec_info[num].interface = PHY_INTERFACE_MODE_SGMII; } else { tsec_info[num].mii_devname = "LS1021A_RGMII_MDIO"; + tsec_info[num].interface = PHY_INTERFACE_MODE_RGMII; } num++; #endif @@ -152,14 +154,17 @@ int board_eth_init(struct bd_info *bis) puts("eTSEC2 is in sgmii mode\n"); tsec_info[num].flags |= TSEC_SGMII; tsec_info[num].mii_devname = "LS1021A_SGMII_MDIO"; + tsec_info[num].interface = PHY_INTERFACE_MODE_SGMII; } else { tsec_info[num].mii_devname = "LS1021A_RGMII_MDIO"; + tsec_info[num].interface = PHY_INTERFACE_MODE_RGMII; } num++; #endif #ifdef CONFIG_TSEC3 SET_STD_TSEC_INFO(tsec_info[num], 3); tsec_info[num].mii_devname = "LS1021A_RGMII_MDIO"; + tsec_info[num].interface = PHY_INTERFACE_MODE_RGMII; num++; #endif if (!num) { diff --git a/board/freescale/ls1028a/ls1028a.c b/board/freescale/ls1028a/ls1028a.c index 71a086ef67..1a7806fad7 100644 --- a/board/freescale/ls1028a/ls1028a.c +++ b/board/freescale/ls1028a/ls1028a.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright 2019, 2021 NXP + * Copyright 2019-2022 NXP */ #include <common.h> @@ -328,3 +328,8 @@ int checkboard(void) return 0; } #endif + +void *video_hw_init(void) +{ + return NULL; +} diff --git a/board/freescale/ls1043ardb/cpld.c b/board/freescale/ls1043ardb/cpld.c index 5d2e8015a0..bf3692a443 100644 --- a/board/freescale/ls1043ardb/cpld.c +++ b/board/freescale/ls1043ardb/cpld.c @@ -68,7 +68,11 @@ void cpld_set_defbank(void) void cpld_set_nand(void) { - u16 reg = CPLD_CFG_RCW_SRC_NAND; + u16 reg = CPLD_CFG_RCW_SRC_NAND_4K; + + if (CPLD_READ(cpld_ver) < 0x3) + reg = CPLD_CFG_RCW_SRC_NAND; + u8 reg5 = (u8)(reg >> 1); u8 reg6 = (u8)(reg & 1); diff --git a/board/freescale/ls1043ardb/cpld.h b/board/freescale/ls1043ardb/cpld.h index 2e757b557f..eed34d6354 100644 --- a/board/freescale/ls1043ardb/cpld.h +++ b/board/freescale/ls1043ardb/cpld.h @@ -41,5 +41,6 @@ void cpld_rev_bit(unsigned char *value); #define CPLD_BANK_SEL_ALTBANK 0x04 #define CPLD_CFG_RCW_SRC_NOR 0x025 #define CPLD_CFG_RCW_SRC_NAND 0x106 +#define CPLD_CFG_RCW_SRC_NAND_4K 0x118 #define CPLD_CFG_RCW_SRC_SD 0x040 #endif diff --git a/board/freescale/ls1043ardb/ls1043ardb.c b/board/freescale/ls1043ardb/ls1043ardb.c index 002869f435..51228bcf79 100644 --- a/board/freescale/ls1043ardb/ls1043ardb.c +++ b/board/freescale/ls1043ardb/ls1043ardb.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ /* * Copyright 2015 Freescale Semiconductor, Inc. - * Copyright 2021 NXP + * Copyright 2021-2022 NXP */ #include <common.h> @@ -167,7 +167,7 @@ int checkboard(void) if (cfg_rcw_src == 0x25) printf("vBank %d\n", CPLD_READ(vbank)); - else if (cfg_rcw_src == 0x106) + else if ((cfg_rcw_src == 0x106) || (cfg_rcw_src == 0x118)) puts("NAND\n"); else printf("Invalid setting of SW4\n"); @@ -272,6 +272,39 @@ void fdt_del_qe(void *blob) } } +/* Update the address of the Aquantia PHY on the MDIO bus for boards revision + * v7.0 and up. Also rename the PHY node to align with the address change. + */ +void fdt_fixup_phy_addr(void *blob) +{ + const char phy_path[] = + "/soc/fman@1a00000/mdio@fd000/ethernet-phy@1"; + int ret, offset, new_addr = AQR113C_PHY_ADDR; + char new_name[] = "ethernet-phy@00"; + + if (CPLD_READ(pcba_ver) < 0x7) + return; + + offset = fdt_path_offset(blob, phy_path); + if (offset < 0) { + printf("ethernet-phy@1 node not found in the dts\n"); + return; + } + + ret = fdt_setprop_u32(blob, offset, "reg", new_addr); + if (ret < 0) { + printf("Unable to set 'reg' for node ethernet-phy@1: %s\n", + fdt_strerror(ret)); + return; + } + + sprintf(new_name, "ethernet-phy@%x", new_addr); + ret = fdt_set_name(blob, offset, new_name); + if (ret < 0) + printf("Unable to rename node ethernet-phy@1: %s\n", + fdt_strerror(ret)); +} + int ft_board_setup(void *blob, struct bd_info *bd) { u64 base[CONFIG_NR_DRAM_BANKS]; @@ -290,6 +323,7 @@ int ft_board_setup(void *blob, struct bd_info *bd) #ifndef CONFIG_DM_ETH fdt_fixup_fman_ethernet(blob); #endif + fdt_fixup_phy_addr(blob); #endif fdt_fixup_icid(blob); @@ -313,6 +347,47 @@ int ft_board_setup(void *blob, struct bd_info *bd) return 0; } +void nand_fixup() +{ + uint32_t csor = 0; + + if (CPLD_READ(pcba_ver) < 0x7) + return; + + /* Change NAND Flash PGS/SPRZ configuration */ + csor = CONFIG_SYS_NAND_CSOR; + if ((csor & CSOR_NAND_PGS_MASK) == CSOR_NAND_PGS_2K) + csor = (csor & ~(CSOR_NAND_PGS_MASK)) | CSOR_NAND_PGS_4K; + + if ((csor & CSOR_NAND_SPRZ_MASK) == CSOR_NAND_SPRZ_64) + csor = (csor & ~(CSOR_NAND_SPRZ_MASK)) | CSOR_NAND_SPRZ_224; + +#ifdef CONFIG_TFABOOT + set_ifc_csor(IFC_CS1, csor); +#else +#ifdef CONFIG_NAND_BOOT + set_ifc_csor(IFC_CS0, csor); +#else + set_ifc_csor(IFC_CS1, csor); +#endif +#endif + + return; +} + +#if IS_ENABLED(CONFIG_OF_BOARD_FIXUP) +int board_fix_fdt(void *blob) +{ + /* nand driver fix up */ + nand_fixup(); + + /* fdt fix up */ + fdt_fixup_phy_addr(blob); + + return 0; +} +#endif + u8 flash_read8(void *addr) { return __raw_readb(addr + 1); diff --git a/board/freescale/lx2160a/Kconfig b/board/freescale/lx2160a/Kconfig index 7556f7dd21..ce2ef5d23c 100644 --- a/board/freescale/lx2160a/Kconfig +++ b/board/freescale/lx2160a/Kconfig @@ -12,6 +12,15 @@ config SYS_SOC config SYS_CONFIG_NAME default "lx2160ardb" +config QSFP_EEPROM + bool "Support for reading QSFP+ transceiver eeprom" + default y if PHY_CORTINA + help + This option enables the functionality for reading + QSFP+ cable eeprom. It can be used when PHYs are + requiring different initialization based on cable + type. + source "board/freescale/common/Kconfig" endif diff --git a/board/freescale/lx2160a/eth_lx2160aqds.c b/board/freescale/lx2160a/eth_lx2160aqds.c index 1819b27561..639ee37d52 100644 --- a/board/freescale/lx2160a/eth_lx2160aqds.c +++ b/board/freescale/lx2160a/eth_lx2160aqds.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright 2018-2020 NXP + * Copyright 2018-2022 NXP * */ @@ -25,6 +25,7 @@ #include <fsl-mc/ldpaa_wriop.h> #include <linux/libfdt.h> +#include "lx2160a.h" #include "../common/qixis.h" DECLARE_GLOBAL_DATA_PTR; @@ -878,6 +879,8 @@ static struct serdes_configuration { /* Serdes block #1 */ {1, 3, true}, {1, 7, true}, + {1, 13, true}, + {1, 14, true}, {1, 19, true}, {1, 20, true}, diff --git a/board/freescale/lx2160a/eth_lx2160ardb.c b/board/freescale/lx2160a/eth_lx2160ardb.c index 15cbc58d59..d9b3c4d78e 100644 --- a/board/freescale/lx2160a/eth_lx2160ardb.c +++ b/board/freescale/lx2160a/eth_lx2160ardb.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright 2018, 2020 NXP + * Copyright 2018-2022 NXP * */ @@ -41,6 +41,49 @@ static bool get_inphi_phy_id(struct mii_dev *bus, int addr, int devad) return false; } +int setup_eth_rev_c(u32 srds_p) +{ + struct mii_dev *bus; + int i; + + /* difference between SerDes1 protocols 18/19 is 4x10G vs. 40G */ + switch (srds_p) { + case 19: + wriop_init_dpmac_enet_if(WRIOP1_DPMAC2, + PHY_INTERFACE_MODE_XLAUI); + break; + case 18: + for (i = WRIOP1_DPMAC7; i <= WRIOP1_DPMAC10; i++) + wriop_init_dpmac_enet_if(i, PHY_INTERFACE_MODE_XGMII); + break; + default: + printf("SerDes1 protocol 0x%x is not supported on LX2160ARDB\n", + srds_p); + return -1; + } + + /* common interfaces for SerDes1 protocols 18 and 19 initialization */ + wriop_set_phy_address(WRIOP1_DPMAC3, 0, AQR113C_PHY_ADDR1); + wriop_set_phy_address(WRIOP1_DPMAC4, 0, AQR113C_PHY_ADDR2); + wriop_set_phy_address(WRIOP1_DPMAC5, 0, INPHI_PHY_ADDR1); + wriop_set_phy_address(WRIOP1_DPMAC6, 0, INPHI_PHY_ADDR1); + wriop_set_phy_address(WRIOP1_DPMAC17, 0, RGMII_PHY_ADDR1); + wriop_set_phy_address(WRIOP1_DPMAC18, 0, RGMII_PHY_ADDR2); + + /* assign DPMAC/PHY to MDIO bus */ + bus = miiphy_get_dev_by_name(DEFAULT_WRIOP_MDIO1_NAME); + wriop_set_mdio(WRIOP1_DPMAC3, bus); + wriop_set_mdio(WRIOP1_DPMAC4, bus); + wriop_set_mdio(WRIOP1_DPMAC17, bus); + wriop_set_mdio(WRIOP1_DPMAC18, bus); + + bus = miiphy_get_dev_by_name(DEFAULT_WRIOP_MDIO2_NAME); + wriop_set_mdio(WRIOP1_DPMAC5, bus); + wriop_set_mdio(WRIOP1_DPMAC6, bus); + + return 0; +} + int board_eth_init(struct bd_info *bis) { #if defined(CONFIG_FSL_MC_ENET) @@ -70,6 +113,13 @@ int board_eth_init(struct bd_info *bis) fm_memac_mdio_init(bis, &mdio_info); dev = miiphy_get_dev_by_name(DEFAULT_WRIOP_MDIO2_NAME); + + /* new LX2160A-RDB2 revC board uses phy-less 25G/40G interfaces */ + if (get_board_rev() == 'C') { + setup_eth_rev_c(srds_s1); + goto next; + } + switch (srds_s1) { case 19: wriop_set_phy_address(WRIOP1_DPMAC2, 0, @@ -181,6 +231,112 @@ void reset_phy(void) } #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); +} + int fdt_fixup_board_phy(void *fdt) { int mdio_offset; @@ -210,5 +366,5 @@ int fdt_fixup_board_phy(void *fdt) } } - return ret; + return fdt_fixup_board_phy_revc(fdt); } diff --git a/board/freescale/lx2160a/lx2160a.c b/board/freescale/lx2160a/lx2160a.c index 49d96d3fa2..6bee724896 100644 --- a/board/freescale/lx2160a/lx2160a.c +++ b/board/freescale/lx2160a/lx2160a.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright 2018-2021 NXP + * Copyright 2018-2022 NXP */ #include <common.h> @@ -35,6 +35,8 @@ #include <fsl_immap.h> #include <asm/arch-fsl-layerscape/fsl_icid.h> #include "lx2160a.h" +#include "../common/qsfp_eeprom.h" +#include "../common/i2c_mux.h" #ifdef CONFIG_EMC2305 #include "../common/emc2305.h" @@ -166,6 +168,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 @@ -541,6 +548,15 @@ int config_board_mux(void) } #endif +#if CONFIG_IS_ENABLED(TARGET_LX2160ARDB) +u8 get_board_rev(void) +{ + u8 board_rev = (QIXIS_READ(arch) & 0xf) - 1 + 'A'; + + return board_rev; +} +#endif + unsigned long get_board_sys_clk(void) { #if defined(CONFIG_TARGET_LX2160AQDS) || defined(CONFIG_TARGET_LX2162AQDS) @@ -579,6 +595,32 @@ unsigned long get_board_ddr_clk(void) #endif } +#if defined(CONFIG_TARGET_LX2160ARDB) && defined(CONFIG_QSFP_EEPROM) && defined(CONFIG_PHY_CORTINA) +void qsfp_cortina_detect(void) +{ + u8 qsfp_compat_code; + + /* read qsfp+ eeprom & update environment for cs4223 init */ + select_i2c_ch_pca9547(I2C_MUX_CH_SEC, 0); + select_i2c_ch_pca9547_sec(I2C_MUX_CH_QSFP, 0); + qsfp_compat_code = get_qsfp_compat0(); + switch (qsfp_compat_code) { + case QSFP_COMPAT_CR4: + env_set(CS4223_CONFIG_ENV, CS4223_CONFIG_CR4); + break; + case QSFP_COMPAT_XLPPI: + case QSFP_COMPAT_SR4: + env_set(CS4223_CONFIG_ENV, CS4223_CONFIG_SR4); + break; + default: + /* do nothing if detection fails or not supported*/ + break; + } + select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT, 0); +} + +#endif /* CONFIG_QSFP_EEPROM & CONFIG_PHY_CORTINA */ + int board_init(void) { #if defined(CONFIG_FSL_MC_ENET) && defined(CONFIG_TARGET_LX2160ARDB) @@ -590,6 +632,10 @@ int board_init(void) #if defined(CONFIG_FSL_MC_ENET) && defined(CONFIG_TARGET_LX2160ARDB) /* invert AQR107 IRQ pins polarity */ out_le32(irq_ccsr + IRQCR_OFFSET / 4, AQR107_IRQ_MASK); + +#if defined(CONFIG_QSFP_EEPROM) && defined(CONFIG_PHY_CORTINA) + qsfp_cortina_detect(); +#endif #endif #if !defined(CONFIG_SYS_EARLY_PCI_INIT) && defined(CONFIG_DM_ETH) @@ -684,6 +730,9 @@ void fdt_fixup_board_enet(void *fdt) fdt_status_okay(fdt, offset); #ifndef CONFIG_DM_ETH fdt_fixup_board_phy(fdt); +#else + if (IS_ENABLED(CONFIG_TARGET_LX2160ARDB)) + fdt_fixup_board_phy_revc(fdt); #endif } else { fdt_status_fail(fdt, offset); @@ -818,9 +867,6 @@ int ft_board_setup(void *blob, struct bd_info *bd) u64 mc_memory_size = 0; u16 total_memory_banks; int err; -#if CONFIG_IS_ENABLED(TARGET_LX2160ARDB) - u8 board_rev; -#endif err = fdt_increase_size(blob, 512); if (err) { @@ -883,8 +929,7 @@ int ft_board_setup(void *blob, struct bd_info *bd) fdt_fixup_icid(blob); #if CONFIG_IS_ENABLED(TARGET_LX2160ARDB) - board_rev = (QIXIS_READ(arch) & 0xf) - 1 + 'A'; - if (board_rev == 'C') + if (get_board_rev() >= 'C') fdt_fixup_i2c_thermal_node(blob); #endif diff --git a/board/freescale/lx2160a/lx2160a.h b/board/freescale/lx2160a/lx2160a.h index 52b020765d..40d4652dd6 100644 --- a/board/freescale/lx2160a/lx2160a.h +++ b/board/freescale/lx2160a/lx2160a.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * Copyright 2020 NXP + * Copyright 2020-2022 NXP */ #ifndef __LX2160_H @@ -58,4 +58,22 @@ #endif #endif +#if defined(CONFIG_QSFP_EEPROM) && defined(CONFIG_PHY_CORTINA) +#define CS4223_CONFIG_ENV "cs4223_autoconfig" +#define CS4223_CONFIG_CR4 "copper" +#define CS4223_CONFIG_SR4 "optical" + +enum qsfp_compat_codes { + QSFP_COMPAT_XLPPI = 0x01, + QSFP_COMPAT_LR4 = 0x02, + QSFP_COMPAT_SR4 = 0x04, + QSFP_COMPAT_CR4 = 0x08, +}; +#endif /* CONFIG_QSFP_EEPROM && CONFIG_PHY_CORTINA */ + +#if CONFIG_IS_ENABLED(TARGET_LX2160ARDB) +u8 get_board_rev(void); +int fdt_fixup_board_phy_revc(void *fdt); +#endif + #endif /* __LX2160_H */ |