diff options
-rw-r--r-- | arch/arm/mach-k3/include/mach/j721e_hardware.h | 3 | ||||
-rw-r--r-- | arch/arm/mach-k3/j721e_init.c | 3 | ||||
-rw-r--r-- | board/ti/common/board_detect.c | 9 | ||||
-rw-r--r-- | board/ti/common/board_detect.h | 9 | ||||
-rw-r--r-- | board/ti/j721e/Kconfig | 7 | ||||
-rw-r--r-- | board/ti/j721e/evm.c | 251 |
6 files changed, 282 insertions, 0 deletions
diff --git a/arch/arm/mach-k3/include/mach/j721e_hardware.h b/arch/arm/mach-k3/include/mach/j721e_hardware.h index 8d42977..ead136e 100644 --- a/arch/arm/mach-k3/include/mach/j721e_hardware.h +++ b/arch/arm/mach-k3/include/mach/j721e_hardware.h @@ -46,4 +46,7 @@ #define CTRLMMR_LOCK_KICK1 0x0100c #define CTRLMMR_LOCK_KICK1_UNLOCK_VAL 0xd172bc5a +/* MCU SCRATCHPAD usage */ +#define TI_SRAM_SCRATCH_BOARD_EEPROM_START CONFIG_SYS_K3_MCU_SCRATCHPAD_BASE + #endif /* __ASM_ARCH_J721E_HARDWARE_H */ diff --git a/arch/arm/mach-k3/j721e_init.c b/arch/arm/mach-k3/j721e_init.c index 4758739..8d562e4 100644 --- a/arch/arm/mach-k3/j721e_init.c +++ b/arch/arm/mach-k3/j721e_init.c @@ -119,6 +119,9 @@ void board_init_f(ulong dummy) preloader_console_init(); #endif + /* Perform EEPROM-based board detection */ + do_board_detect(); + #if defined(CONFIG_CPU_V7R) && defined(CONFIG_K3_AVS0) ret = uclass_get_device_by_driver(UCLASS_MISC, DM_GET_DRIVER(k3_avs), &dev); diff --git a/board/ti/common/board_detect.c b/board/ti/common/board_detect.c index b230bb6..cbd35f2 100644 --- a/board/ti/common/board_detect.c +++ b/board/ti/common/board_detect.c @@ -548,6 +548,15 @@ int __maybe_unused ti_i2c_eeprom_am6_get_base(int bus_addr, int dev_addr) return ret; } +bool __maybe_unused board_ti_k3_is(char *name_tag) +{ + struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA; + + if (ep->header == TI_DEAD_EEPROM_MAGIC) + return false; + return !strncmp(ep->name, name_tag, AM6_EEPROM_HDR_NAME_LEN); +} + bool __maybe_unused board_ti_is(char *name_tag) { struct ti_common_eeprom *ep = TI_EEPROM_DATA; diff --git a/board/ti/common/board_detect.h b/board/ti/common/board_detect.h index 1a85b7f..5835af5 100644 --- a/board/ti/common/board_detect.h +++ b/board/ti/common/board_detect.h @@ -320,6 +320,15 @@ int __maybe_unused ti_i2c_eeprom_am6_get_base(int bus_addr, int dev_addr); bool board_ti_is(char *name_tag); /** + * board_ti_k3_is() - Board detection logic for TI K3 EVMs + * @name_tag: Tag used in eeprom for the board + * + * Return: false if board information does not match OR eeprom wasn't read. + * true otherwise + */ +bool board_ti_k3_is(char *name_tag); + +/** * board_ti_rev_is() - Compare board revision for TI EVMs * @rev_tag: Revision tag to check in eeprom * @cmp_len: How many chars to compare? diff --git a/board/ti/j721e/Kconfig b/board/ti/j721e/Kconfig index 88097df..e56dc53 100644 --- a/board/ti/j721e/Kconfig +++ b/board/ti/j721e/Kconfig @@ -11,6 +11,8 @@ config TARGET_J721E_A72_EVM bool "TI K3 based J721E EVM running on A72" select ARM64 select SOC_K3_J721E + select BOARD_LATE_INIT + imply TI_I2C_BOARD_DETECT select SYS_DISABLE_DCACHE_OPS config TARGET_J721E_R5_EVM @@ -23,6 +25,7 @@ config TARGET_J721E_R5_EVM select SPL_RAM select K3_J721E_DDRSS imply SYS_K3_SPL_ATF + imply TI_I2C_BOARD_DETECT endchoice @@ -37,6 +40,8 @@ config SYS_VENDOR config SYS_CONFIG_NAME default "j721e_evm" +source "board/ti/common/Kconfig" + endif if TARGET_J721E_R5_EVM @@ -53,4 +58,6 @@ config SYS_CONFIG_NAME config SPL_LDSCRIPT default "arch/arm/mach-omap2/u-boot-spl.lds" +source "board/ti/common/Kconfig" + endif diff --git a/board/ti/j721e/evm.c b/board/ti/j721e/evm.c index 51b121c..7327c96 100644 --- a/board/ti/j721e/evm.c +++ b/board/ti/j721e/evm.c @@ -9,10 +9,21 @@ #include <common.h> #include <init.h> +#include <asm/arch/sys_proto.h> +#include <asm/arch/hardware.h> +#include <asm/gpio.h> #include <asm/io.h> #include <spl.h> #include <asm/arch/sys_proto.h> +#include "../common/board_detect.h" + +#define board_is_j721e_som() (board_ti_k3_is("J721EX-PM1-SOM") || \ + board_ti_k3_is("J721EX-PM2-SOM")) + +/* Max number of MAC addresses that are parsed/processed per daughter card */ +#define DAUGHTER_CARD_NO_OF_MAC_ADDR 8 + DECLARE_GLOBAL_DATA_PTR; int board_init(void) @@ -81,3 +92,243 @@ int ft_board_setup(void *blob, bd_t *bd) return ret; } #endif + +int do_board_detect(void) +{ + int ret; + + ret = ti_i2c_eeprom_am6_get_base(CONFIG_EEPROM_BUS_ADDRESS, + CONFIG_EEPROM_CHIP_ADDRESS); + if (ret) + pr_err("Reading on-board EEPROM at 0x%02x failed %d\n", + CONFIG_EEPROM_CHIP_ADDRESS, ret); + + return ret; +} + +static void setup_board_eeprom_env(void) +{ + char *name = "j721e"; + + if (do_board_detect()) + goto invalid_eeprom; + + if (board_is_j721e_som()) + name = "j721e"; + else + printf("Unidentified board claims %s in eeprom header\n", + board_ti_get_name()); + +invalid_eeprom: + set_board_info_env_am6(name); +} + +static void setup_serial(void) +{ + struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA; + unsigned long board_serial; + char *endp; + char serial_string[17] = { 0 }; + + if (env_get("serial#")) + return; + + board_serial = simple_strtoul(ep->serial, &endp, 16); + if (*endp != '\0') { + pr_err("Error: Can't set serial# to %s\n", ep->serial); + return; + } + + snprintf(serial_string, sizeof(serial_string), "%016lx", board_serial); + env_set("serial#", serial_string); +} + +/* + * Declaration of daughtercards to probe. Note that when adding more + * cards they should be grouped by the 'i2c_addr' field to allow for a + * more efficient probing process. + */ +static const struct { + u8 i2c_addr; /* I2C address of card EEPROM */ + char *card_name; /* EEPROM-programmed card name */ + char *dtbo_name; /* Device tree overlay to apply */ + u8 eth_offset; /* ethXaddr MAC address index offset */ +} ext_cards[] = { + { + 0x51, + "J7X-BASE-CPB", + "", /* No dtbo for this board */ + 0, + }, + { + 0x52, + "J7X-INFOTAN-EXP", + "", /* No dtbo for this board */ + 0, + }, + { + 0x52, + "J7X-GESI-EXP", + "", /* No dtbo for this board */ + 5, /* Start populating from eth5addr */ + }, + { + 0x54, + "J7X-VSC8514-ETH", + "", /* No dtbo for this board */ + 1, /* Start populating from eth1addr */ + }, +}; + +static bool daughter_card_detect_flags[ARRAY_SIZE(ext_cards)]; + +const char *board_fit_get_additionnal_images(int index, const char *type) +{ + int i, j; + + if (strcmp(type, FIT_FDT_PROP)) + return NULL; + + j = 0; + for (i = 0; i < ARRAY_SIZE(ext_cards); i++) { + if (daughter_card_detect_flags[i]) { + if (j == index) { + /* + * Return dtbo name only if populated, + * otherwise stop parsing here. + */ + if (strlen(ext_cards[i].dtbo_name)) + return ext_cards[i].dtbo_name; + else + return NULL; + }; + + j++; + } + } + + return NULL; +} + +static int probe_daughtercards(void) +{ + char mac_addr[DAUGHTER_CARD_NO_OF_MAC_ADDR][TI_EEPROM_HDR_ETH_ALEN]; + bool eeprom_read_success; + struct ti_am6_eeprom ep; + u8 previous_i2c_addr; + u8 mac_addr_cnt; + int i; + int ret; + + /* Mark previous I2C address variable as not populated */ + previous_i2c_addr = 0xff; + + /* No EEPROM data was read yet */ + eeprom_read_success = false; + + /* Iterate through list of daughtercards */ + for (i = 0; i < ARRAY_SIZE(ext_cards); i++) { + /* Obtain card-specific I2C address */ + u8 i2c_addr = ext_cards[i].i2c_addr; + + /* Read card EEPROM if not already read previously */ + if (i2c_addr != previous_i2c_addr) { + /* Store I2C address so we can avoid reading twice */ + previous_i2c_addr = i2c_addr; + + /* Get and parse the daughter card EEPROM record */ + ret = ti_i2c_eeprom_am6_get(CONFIG_EEPROM_BUS_ADDRESS, + i2c_addr, + &ep, + (char **)mac_addr, + DAUGHTER_CARD_NO_OF_MAC_ADDR, + &mac_addr_cnt); + if (ret) { + debug("%s: No daughtercard EEPROM at 0x%02x found %d\n", + __func__, i2c_addr, ret); + eeprom_read_success = false; + /* Skip to the next daughtercard to probe */ + continue; + } + + /* EEPROM read successful, okay to further process. */ + eeprom_read_success = true; + } + + /* Only continue processing if EEPROM data was read */ + if (!eeprom_read_success) + continue; + + /* Only process the parsed data if we found a match */ + if (strncmp(ep.name, ext_cards[i].card_name, sizeof(ep.name))) + continue; + + printf("Detected: %s rev %s\n", ep.name, ep.version); + daughter_card_detect_flags[i] = true; + +#ifndef CONFIG_SPL_BUILD + int j; + /* + * Populate any MAC addresses from daughtercard into the U-Boot + * environment, starting with a card-specific offset so we can + * have multiple ext_cards contribute to the MAC pool in a well- + * defined manner. + */ + for (j = 0; j < mac_addr_cnt; j++) { + if (!is_valid_ethaddr((u8 *)mac_addr[j])) + continue; + + eth_env_set_enetaddr_by_index("eth", + ext_cards[i].eth_offset + j, + (uchar *)mac_addr[j]); + } +#endif + } +#ifndef CONFIG_SPL_BUILD + char name_overlays[1024] = { 0 }; + + for (i = 0; i < ARRAY_SIZE(ext_cards); i++) { + if (!daughter_card_detect_flags[i]) + continue; + + /* Skip if no overlays are to be added */ + if (!strlen(ext_cards[i].dtbo_name)) + continue; + + /* + * Make sure we are not running out of buffer space by checking + * if we can fit the new overlay, a trailing space to be used + * as a separator, plus the terminating zero. + */ + if (strlen(name_overlays) + strlen(ext_cards[i].dtbo_name) + 2 > + sizeof(name_overlays)) + return -ENOMEM; + + /* Append to our list of overlays */ + strcat(name_overlays, ext_cards[i].dtbo_name); + strcat(name_overlays, " "); + } + + /* Apply device tree overlay(s) to the U-Boot environment, if any */ + if (strlen(name_overlays)) + return env_set("name_overlays", name_overlays); +#endif + + return 0; +} + +int board_late_init(void) +{ + setup_board_eeprom_env(); + setup_serial(); + + /* Check for and probe any plugged-in daughtercards */ + probe_daughtercards(); + + return 0; +} + +void spl_board_init(void) +{ + probe_daughtercards(); +} |