diff options
Diffstat (limited to 'board')
-rw-r--r-- | board/phytec/common/Kconfig | 18 | ||||
-rw-r--r-- | board/phytec/common/Makefile | 1 | ||||
-rw-r--r-- | board/phytec/common/am6_som_detection.c | 159 | ||||
-rw-r--r-- | board/phytec/common/am6_som_detection.h | 36 | ||||
-rw-r--r-- | board/phytec/common/imx8m_som_detection.c | 13 | ||||
-rw-r--r-- | board/phytec/common/phytec_som_detection.c | 97 | ||||
-rw-r--r-- | board/phytec/common/phytec_som_detection.h | 16 | ||||
-rw-r--r-- | board/phytec/phycore_am62x/Kconfig | 4 | ||||
-rw-r--r-- | board/phytec/phycore_am64x/Kconfig | 4 |
9 files changed, 314 insertions, 34 deletions
diff --git a/board/phytec/common/Kconfig b/board/phytec/common/Kconfig index 3b1c5aa0d02..1077f0f4b61 100644 --- a/board/phytec/common/Kconfig +++ b/board/phytec/common/Kconfig @@ -11,3 +11,21 @@ config PHYTEC_IMX8M_SOM_DETECTION help Support of I2C EEPROM based SoM detection. Supported for PHYTEC i.MX8MM/i.MX8MP boards + +config PHYTEC_AM62_SOM_DETECTION + bool "Support SoM detection for AM62x PHYTEC platforms" + depends on (TARGET_PHYCORE_AM62X_A53 || TARGET_PHYCORE_AM62X_R5) && \ + PHYTEC_SOM_DETECTION + default y + help + Support of I2C EEPROM based SoM detection. Supported + for PHYTEC AM62x boards. + +config PHYTEC_AM64_SOM_DETECTION + bool "Support SoM detection for AM64x PHYTEC platforms" + depends on (TARGET_PHYCORE_AM64X_A53 || TARGET_PHYCORE_AM64X_R5) && \ + PHYTEC_SOM_DETECTION + default y + help + Support of I2C EEPROM based SoM detection. Supported + for PHYTEC AM64x boards. diff --git a/board/phytec/common/Makefile b/board/phytec/common/Makefile index 35c81741306..3feb00fd1ec 100644 --- a/board/phytec/common/Makefile +++ b/board/phytec/common/Makefile @@ -8,4 +8,5 @@ obj- := __dummy__.o endif obj-y += phytec_som_detection.o +obj-$(CONFIG_ARCH_K3) += am6_som_detection.o obj-$(CONFIG_ARCH_IMX8M) += imx8m_som_detection.o diff --git a/board/phytec/common/am6_som_detection.c b/board/phytec/common/am6_som_detection.c new file mode 100644 index 00000000000..2e9884dab44 --- /dev/null +++ b/board/phytec/common/am6_som_detection.c @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2024 PHYTEC Messtechnik GmbH + * Author: Daniel Schultz <d.schultz@phytec.de> + */ + +#include <asm/arch/hardware.h> + +#include "am6_som_detection.h" + +extern struct phytec_eeprom_data eeprom_data; + +#if IS_ENABLED(CONFIG_PHYTEC_AM62_SOM_DETECTION) || \ + IS_ENABLED(CONFIG_PHYTEC_AM64_SOM_DETECTION) + +/* Check if the SoM is actually one of the following products: + * - phyCORE-AM62x + * - phyCORE-AM64x + * + * Returns 0 in case it's a known SoM. Otherwise, returns -1. + */ +int phytec_am6_detect(struct phytec_eeprom_data *data) +{ + char *opt; + u8 som; + + if (!data) + data = &eeprom_data; + + /* We cannot do the check for early API revisions */ + if (!data->valid || data->payload.api_rev < PHYTEC_API_REV2) + return -1; + + som = data->payload.data.data_api2.som_no; + debug("%s: som id: %u\n", __func__, som); + + opt = phytec_get_opt(data); + if (!opt) + return -1; + + if (som == PHYTEC_AM62X_SOM && soc_is_am62x()) + return 0; + + if (som == PHYTEC_AM64X_SOM && soc_is_am64x()) + return 0; + + return -1; +} + +static u8 phytec_check_opt(struct phytec_eeprom_data *data, u8 option) +{ + char *opt; + + if (!data) + data = &eeprom_data; + + if (!data->valid || data->payload.api_rev < PHYTEC_API_REV2) + return PHYTEC_EEPROM_INVAL; + + if (option > 8) + return PHYTEC_EEPROM_INVAL; + + opt = phytec_get_opt(data); + if (opt) + return PHYTEC_GET_OPTION(opt[option]); + return PHYTEC_EEPROM_INVAL; +} + +/* + * Reads LPDDR4 ram size from EEPROM. + * + * returns: + * - The size + * - PHYTEC_EEPROM_INVAL when the data is invalid. + */ +u8 __maybe_unused phytec_get_am62_ddr_size(struct phytec_eeprom_data *data) +{ + u8 ddr_id = phytec_check_opt(data, 3); + + pr_debug("%s: ddr id: %u\n", __func__, ddr_id); + return ddr_id; +} + +/* + * Reads SPI-NOR flash size and type from EEPROM. + * + * returns: + * - PHYTEC_EEPROM_VALUE_X if no SPI is poulated. + * - Otherwise a board depended code for the size. + * - PHYTEC_EEPROM_INVAL when the data is invalid. + */ +u8 __maybe_unused phytec_get_am62_spi(struct phytec_eeprom_data *data) +{ + u8 spi = phytec_check_opt(data, 5); + + pr_debug("%s: spi: %u\n", __func__, spi); + return spi; +} + +/* + * Reads Ethernet phy information from EEPROM. + * + * returns: + * - 0x0 no ethernet phy is populated. + * - 0x1 if 10/100/1000 MBit Phy is populated. + * - PHYTEC_EEPROM_INVAL when the data is invalid. + */ +u8 __maybe_unused phytec_get_am62_eth(struct phytec_eeprom_data *data) +{ + u8 eth = phytec_check_opt(data, 6); + + pr_debug("%s: eth: %u\n", __func__, eth); + return eth; +} + +/* + * Reads RTC information from EEPROM. + * + * returns: + * - 0 if no RTC is poulated. + * - 1 if it is populated. + * - PHYTEC_EEPROM_INVAL when the data is invalid. + */ +u8 __maybe_unused phytec_get_am62_rtc(struct phytec_eeprom_data *data) +{ + u8 rtc = phytec_check_opt(data, 7); + + pr_debug("%s: rtc: %u\n", __func__, rtc); + return rtc; +} + +#else + +inline int __maybe_unused phytec_am62_detect(struct phytec_eeprom_data *data) +{ + return -1; +} + +inline u8 __maybe_unused +phytec_get_am62_ddr_size(struct phytec_eeprom_data *data) +{ + return PHYTEC_EEPROM_INVAL; +} + +inline u8 __maybe_unused phytec_get_am62_spi(struct phytec_eeprom_data *data) +{ + return PHYTEC_EEPROM_INVAL; +} + +inline u8 __maybe_unused phytec_get_am62_eth(struct phytec_eeprom_data *data) +{ + return PHYTEC_EEPROM_INVAL; +} + +inline u8 __maybe_unused phytec_get_am62_rtc(struct phytec_eeprom_data *data) +{ + return PHYTEC_EEPROM_INVAL; +} +#endif diff --git a/board/phytec/common/am6_som_detection.h b/board/phytec/common/am6_som_detection.h new file mode 100644 index 00000000000..032f9da3aab --- /dev/null +++ b/board/phytec/common/am6_som_detection.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2024 PHYTEC Messtechnik GmbH + * Author: Daniel Schultz <d.schultz@phytec.de> + */ + +#ifndef _PHYTEC_AM6_SOM_DETECTION_H +#define _PHYTEC_AM6_SOM_DETECTION_H + +#include "phytec_som_detection.h" + +#define PHYTEC_AM62X_SOM 71 +#define PHYTEC_AM64X_SOM 72 +#define PHYTEC_EEPROM_VALUE_X 0x21 +#define PHYTEC_EEPROM_NOR_FLASH_64MB_QSPI 0xC + +int __maybe_unused phytec_am6_detect(struct phytec_eeprom_data *data); +u8 __maybe_unused phytec_get_am6_ddr_size(struct phytec_eeprom_data *data); +u8 __maybe_unused phytec_get_am6_spi(struct phytec_eeprom_data *data); +u8 __maybe_unused phytec_get_am6_eth(struct phytec_eeprom_data *data); +u8 __maybe_unused phytec_get_am6_rtc(struct phytec_eeprom_data *data); + +static inline int phytec_am6_is_qspi(struct phytec_eeprom_data *data) +{ + u8 spi = phytec_get_am6_spi(data); + + if (spi == PHYTEC_EEPROM_VALUE_X) + return 0; + return spi <= PHYTEC_EEPROM_NOR_FLASH_64MB_QSPI; +} + +static inline int phytec_am6_is_ospi(struct phytec_eeprom_data *data) +{ + return phytec_get_am6_spi(data) > PHYTEC_EEPROM_NOR_FLASH_64MB_QSPI; +} +#endif /* _PHYTEC_AM6_SOM_DETECTION_H */ diff --git a/board/phytec/common/imx8m_som_detection.c b/board/phytec/common/imx8m_som_detection.c index 214b75db3b0..ee34a5b9579 100644 --- a/board/phytec/common/imx8m_som_detection.c +++ b/board/phytec/common/imx8m_som_detection.c @@ -34,10 +34,10 @@ int __maybe_unused phytec_imx8m_detect(struct phytec_eeprom_data *data) data = &eeprom_data; /* We can not do the check for early API revisions */ - if (data->api_rev < PHYTEC_API_REV2) + if (!data->valid || data->payload.api_rev < PHYTEC_API_REV2) return -1; - som = data->data.data_api2.som_no; + som = data->payload.data.data_api2.som_no; debug("%s: som id: %u\n", __func__, som); opt = phytec_get_opt(data); @@ -75,6 +75,9 @@ u8 __maybe_unused phytec_get_imx8m_ddr_size(struct phytec_eeprom_data *data) if (!data) data = &eeprom_data; + if (!data->valid || data->payload.api_rev < PHYTEC_API_REV2) + return PHYTEC_EEPROM_INVAL; + opt = phytec_get_opt(data); if (opt) ddr_id = PHYTEC_GET_OPTION(opt[2]); @@ -99,7 +102,7 @@ u8 __maybe_unused phytec_get_imx8m_spi(struct phytec_eeprom_data *data) if (!data) data = &eeprom_data; - if (data->api_rev < PHYTEC_API_REV2) + if (!data->valid || data->payload.api_rev < PHYTEC_API_REV2) return PHYTEC_EEPROM_INVAL; opt = phytec_get_opt(data); @@ -126,7 +129,7 @@ u8 __maybe_unused phytec_get_imx8m_eth(struct phytec_eeprom_data *data) if (!data) data = &eeprom_data; - if (data->api_rev < PHYTEC_API_REV2) + if (!data->valid || data->payload.api_rev < PHYTEC_API_REV2) return PHYTEC_EEPROM_INVAL; opt = phytec_get_opt(data); @@ -154,7 +157,7 @@ u8 __maybe_unused phytec_get_imx8mp_rtc(struct phytec_eeprom_data *data) if (!data) data = &eeprom_data; - if (data->api_rev < PHYTEC_API_REV2) + if (!data->valid || data->payload.api_rev < PHYTEC_API_REV2) return PHYTEC_EEPROM_INVAL; opt = phytec_get_opt(data); diff --git a/board/phytec/common/phytec_som_detection.c b/board/phytec/common/phytec_som_detection.c index a56e0f60d62..78c173df20d 100644 --- a/board/phytec/common/phytec_som_detection.c +++ b/board/phytec/common/phytec_som_detection.c @@ -9,6 +9,8 @@ #include <dm/uclass.h> #include <i2c.h> #include <u-boot/crc.h> +#include <malloc.h> +#include <extension_board.h> #include "phytec_som_detection.h" @@ -51,7 +53,8 @@ int phytec_eeprom_data_init(struct phytec_eeprom_data *data, { int ret, i; unsigned int crc; - int *ptr; + u8 *ptr; + const unsigned int payload_size = sizeof(struct phytec_eeprom_payload); if (!data) data = &eeprom_data; @@ -62,14 +65,13 @@ int phytec_eeprom_data_init(struct phytec_eeprom_data *data, ret = i2c_get_chip_for_busnum(bus_num, addr, 2, &dev); if (ret) { pr_err("%s: i2c EEPROM not found: %i.\n", __func__, ret); - return ret; + goto err; } - ret = dm_i2c_read(dev, 0, (uint8_t *)data, - sizeof(struct phytec_eeprom_data)); + ret = dm_i2c_read(dev, 0, (uint8_t *)data, payload_size); if (ret) { - pr_err("%s: Unable to read EEPROM data\n", __func__); - return ret; + pr_err("%s: Unable to read EEPROM data: %i\n", __func__, ret); + goto err; } #else i2c_set_bus_num(bus_num); @@ -77,36 +79,44 @@ int phytec_eeprom_data_init(struct phytec_eeprom_data *data, sizeof(struct phytec_eeprom_data)); #endif - if (data->api_rev == 0xff) { + if (data->payload.api_rev == 0xff) { pr_err("%s: EEPROM is not flashed. Prototype?\n", __func__); - return -EINVAL; + ret = -EINVAL; + goto err; } - ptr = (int *)data; - for (i = 0; i < sizeof(struct phytec_eeprom_data); i++) + ptr = (u8 *)data; + for (i = 0; i < payload_size; ++i) if (ptr[i] != 0x0) break; - if (i == sizeof(struct phytec_eeprom_data)) { + if (i == payload_size) { pr_err("%s: EEPROM data is all zero. Erased?\n", __func__); - return -EINVAL; + ret = -EINVAL; + goto err; } /* We are done here for early revisions */ - if (data->api_rev <= PHYTEC_API_REV1) + if (data->payload.api_rev <= PHYTEC_API_REV1) { + data->valid = true; return 0; + } - crc = crc8(0, (const unsigned char *)data, - sizeof(struct phytec_eeprom_data)); + crc = crc8(0, (const unsigned char *)&data->payload, payload_size); debug("%s: crc: %x\n", __func__, crc); if (crc) { - pr_err("%s: CRC mismatch. EEPROM data is not usable\n", + pr_err("%s: CRC mismatch. EEPROM data is not usable.\n", __func__); - return -EINVAL; + ret = -EINVAL; + goto err; } + data->valid = true; return 0; +err: + data->valid = false; + return ret; } void __maybe_unused phytec_print_som_info(struct phytec_eeprom_data *data) @@ -118,10 +128,10 @@ void __maybe_unused phytec_print_som_info(struct phytec_eeprom_data *data) if (!data) data = &eeprom_data; - if (data->api_rev < PHYTEC_API_REV2) + if (!data->valid || data->payload.api_rev < PHYTEC_API_REV2) return; - api2 = &data->data.data_api2; + api2 = &data->payload.data.data_api2; /* Calculate PCB subrevision */ pcb_sub_rev = api2->pcb_sub_opt_rev & 0x0f; @@ -180,10 +190,13 @@ char * __maybe_unused phytec_get_opt(struct phytec_eeprom_data *data) if (!data) data = &eeprom_data; - if (data->api_rev < PHYTEC_API_REV2) - opt = data->data.data_api0.opt; + if (!data->valid) + return NULL; + + if (data->payload.api_rev < PHYTEC_API_REV2) + opt = data->payload.data.data_api0.opt; else - opt = data->data.data_api2.opt; + opt = data->payload.data.data_api2.opt; return opt; } @@ -195,10 +208,10 @@ u8 __maybe_unused phytec_get_rev(struct phytec_eeprom_data *data) if (!data) data = &eeprom_data; - if (data->api_rev < PHYTEC_API_REV2) + if (!data->valid || data->payload.api_rev < PHYTEC_API_REV2) return PHYTEC_EEPROM_INVAL; - api2 = &data->data.data_api2; + api2 = &data->payload.data.data_api2; return api2->pcb_rev; } @@ -207,12 +220,35 @@ u8 __maybe_unused phytec_get_som_type(struct phytec_eeprom_data *data) { if (!data) data = &eeprom_data; - if (data->api_rev < PHYTEC_API_REV2) + + if (!data->valid || data->payload.api_rev < PHYTEC_API_REV2) return PHYTEC_EEPROM_INVAL; - return data->data.data_api2.som_type; + return data->payload.data.data_api2.som_type; } +#if IS_ENABLED(CONFIG_CMD_EXTENSION) +struct extension *phytec_add_extension(const char *name, const char *overlay, + const char *other) +{ + struct extension *extension; + + if (strlen(overlay) > sizeof(extension->overlay)) { + pr_err("Overlay name %s is longer than %lu.\n", overlay, + sizeof(extension->overlay)); + return NULL; + } + + extension = calloc(1, sizeof(struct extension)); + snprintf(extension->name, sizeof(extension->name), name); + snprintf(extension->overlay, sizeof(extension->overlay), overlay); + snprintf(extension->other, sizeof(extension->other), other); + snprintf(extension->owner, sizeof(extension->owner), "PHYTEC"); + + return extension; +} +#endif /* IS_ENABLED(CONFIG_CMD_EXTENSION) */ + #else inline int phytec_eeprom_data_setup(struct phytec_eeprom_data *data, @@ -253,4 +289,13 @@ u8 __maybe_unused phytec_get_som_type(struct phytec_eeprom_data *data) return PHYTEC_EEPROM_INVAL; } +#if IS_ENABLED(CONFIG_CMD_EXTENSION) +inline struct extension *phytec_add_extension(const char *name, + const char *overlay, + const char *other) +{ + return NULL; +} +#endif /* IS_ENABLED(CONFIG_CMD_EXTENSION) */ + #endif /* IS_ENABLED(CONFIG_PHYTEC_SOM_DETECTION) */ diff --git a/board/phytec/common/phytec_som_detection.h b/board/phytec/common/phytec_som_detection.h index 7edbfa3ca5c..0ad5c14ef4e 100644 --- a/board/phytec/common/phytec_som_detection.h +++ b/board/phytec/common/phytec_som_detection.h @@ -55,7 +55,7 @@ struct phytec_api2_data { u8 crc8; /* checksum */ } __packed; -struct phytec_eeprom_data { +struct phytec_eeprom_payload { u8 api_rev; union { struct phytec_api0_data data_api0; @@ -63,17 +63,27 @@ struct phytec_eeprom_data { } data; } __packed; +struct phytec_eeprom_data { + struct phytec_eeprom_payload payload; + bool valid; +}; + int phytec_eeprom_data_setup_fallback(struct phytec_eeprom_data *data, int bus_num, int addr, int addr_fallback); int phytec_eeprom_data_setup(struct phytec_eeprom_data *data, int bus_num, int addr); -int phytec_eeprom_data_init(struct phytec_eeprom_data *data, - int bus_num, int addr); +int phytec_eeprom_data_init(struct phytec_eeprom_data *data, int bus_num, + int addr); void __maybe_unused phytec_print_som_info(struct phytec_eeprom_data *data); char * __maybe_unused phytec_get_opt(struct phytec_eeprom_data *data); u8 __maybe_unused phytec_get_rev(struct phytec_eeprom_data *data); u8 __maybe_unused phytec_get_som_type(struct phytec_eeprom_data *data); +#if IS_ENABLED(CONFIG_CMD_EXTENSION) +struct extension *phytec_add_extension(const char *name, const char *overlay, + const char *other); +#endif /* IS_ENABLED(CONFIG_CMD_EXTENSION) */ + #endif /* _PHYTEC_SOM_DETECTION_H */ diff --git a/board/phytec/phycore_am62x/Kconfig b/board/phytec/phycore_am62x/Kconfig index b64c3451389..1de8850c6c4 100644 --- a/board/phytec/phycore_am62x/Kconfig +++ b/board/phytec/phycore_am62x/Kconfig @@ -14,6 +14,8 @@ config SYS_VENDOR config SYS_CONFIG_NAME default "phycore_am62x" +source "board/phytec/common/Kconfig" + endif if TARGET_PHYCORE_AM62X_R5 @@ -30,4 +32,6 @@ config SYS_CONFIG_NAME config SPL_LDSCRIPT default "arch/arm/mach-omap2/u-boot-spl.lds" +source "board/phytec/common/Kconfig" + endif diff --git a/board/phytec/phycore_am64x/Kconfig b/board/phytec/phycore_am64x/Kconfig index 427adb6fedd..829526c3295 100644 --- a/board/phytec/phycore_am64x/Kconfig +++ b/board/phytec/phycore_am64x/Kconfig @@ -17,6 +17,8 @@ config SYS_VENDOR config SYS_CONFIG_NAME default "phycore_am64x" +source "board/phytec/common/Kconfig" + endif if TARGET_PHYCORE_AM64X_R5 @@ -30,4 +32,6 @@ config SYS_VENDOR config SYS_CONFIG_NAME default "phycore_am64x" +source "board/phytec/common/Kconfig" + endif |