[PATCH 0/5] Update PHYTEC SOM Detection

This patch series extends PHYTEC's SOM detection by minor fixes, a generic helper function and a new valid flag.
Moreover, it adds a module to provide access to the SOM detection for our TI AM6 products.
Daniel Schultz (3): board: phytec: common: Generic "add extension" function board: phytec: common: Fix eepom is empty check board: phytec: Add SOM detection for AM6x
Yannic Moog (2): board: phytec: introduce eeprom struct member 'valid' board: phytec: check eeprom_data validity
board/phytec/common/Kconfig | 18 +++ board/phytec/common/Makefile | 1 + board/phytec/common/am6_som_detection.c | 159 +++++++++++++++++++++ board/phytec/common/am6_som_detection.h | 36 +++++ board/phytec/common/imx8m_som_detection.c | 13 +- board/phytec/common/phytec_som_detection.c | 97 +++++++++---- board/phytec/common/phytec_som_detection.h | 16 ++- board/phytec/phycore_am62x/Kconfig | 4 + board/phytec/phycore_am64x/Kconfig | 4 + 9 files changed, 314 insertions(+), 34 deletions(-) create mode 100644 board/phytec/common/am6_som_detection.c create mode 100644 board/phytec/common/am6_som_detection.h

Add a generic function to apply overlays in our board code to not implement the same logic in different PHYTEC products.
Signed-off-by: Daniel Schultz d.schultz@phytec.de --- board/phytec/common/phytec_som_detection.c | 33 ++++++++++++++++++++++ board/phytec/common/phytec_som_detection.h | 5 ++++ 2 files changed, 38 insertions(+)
diff --git a/board/phytec/common/phytec_som_detection.c b/board/phytec/common/phytec_som_detection.c index a56e0f60d62..d167a77c25b 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"
@@ -213,6 +215,28 @@ u8 __maybe_unused phytec_get_som_type(struct phytec_eeprom_data *data) return data->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 +277,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..ea99a687fee 100644 --- a/board/phytec/common/phytec_som_detection.h +++ b/board/phytec/common/phytec_som_detection.h @@ -76,4 +76,9 @@ 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 */

Am Freitag, dem 19.04.2024 um 08:55 -0700 schrieb Daniel Schultz:
Add a generic function to apply overlays in our board code to not implement the same logic in different PHYTEC products.
Signed-off-by: Daniel Schultz d.schultz@phytec.de
Reviewed-by: Teresa Remmet t.remmet@phytec.de
board/phytec/common/phytec_som_detection.c | 33 ++++++++++++++++++++++ board/phytec/common/phytec_som_detection.h | 5 ++++ 2 files changed, 38 insertions(+)
diff --git a/board/phytec/common/phytec_som_detection.c b/board/phytec/common/phytec_som_detection.c index a56e0f60d62..d167a77c25b 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" @@ -213,6 +215,28 @@ u8 __maybe_unused phytec_get_som_type(struct phytec_eeprom_data *data) return data->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 +277,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..ea99a687fee 100644 --- a/board/phytec/common/phytec_som_detection.h +++ b/board/phytec/common/phytec_som_detection.h @@ -76,4 +76,9 @@ 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 */

From: Yannic Moog y.moog@phytec.de
Add a new nember to the eeprom_data that indicates whether the associated data is valid or not. Make use of this new member in the phytec_eeprom_data_init function by setting the valid value appropriately. Move the eeprom data to a new struct payload that holds the payload of the eeprom.
Signed-off-by: Yannic Moog y.moog@phytec.de Signed-off-by: Daniel Schultz d.schultz@phytec.de --- board/phytec/common/imx8m_som_detection.c | 10 ++-- board/phytec/common/phytec_som_detection.c | 56 ++++++++++++---------- board/phytec/common/phytec_som_detection.h | 11 +++-- 3 files changed, 45 insertions(+), 32 deletions(-)
diff --git a/board/phytec/common/imx8m_som_detection.c b/board/phytec/common/imx8m_som_detection.c index 214b75db3b0..7571076a09e 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->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); @@ -99,7 +99,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->payload.api_rev < PHYTEC_API_REV2) return PHYTEC_EEPROM_INVAL;
opt = phytec_get_opt(data); @@ -126,7 +126,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->payload.api_rev < PHYTEC_API_REV2) return PHYTEC_EEPROM_INVAL;
opt = phytec_get_opt(data); @@ -154,7 +154,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->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 d167a77c25b..7913764be0a 100644 --- a/board/phytec/common/phytec_som_detection.c +++ b/board/phytec/common/phytec_som_detection.c @@ -54,6 +54,7 @@ int phytec_eeprom_data_init(struct phytec_eeprom_data *data, int ret, i; unsigned int crc; int *ptr; + const unsigned int payload_size = sizeof(struct phytec_eeprom_payload);
if (!data) data = &eeprom_data; @@ -64,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); @@ -79,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++) + 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) @@ -120,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->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; @@ -182,10 +190,10 @@ 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->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; } @@ -197,10 +205,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->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; } @@ -209,10 +217,10 @@ 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->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) diff --git a/board/phytec/common/phytec_som_detection.h b/board/phytec/common/phytec_som_detection.h index ea99a687fee..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,13 +63,18 @@ 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);

Am Freitag, dem 19.04.2024 um 08:55 -0700 schrieb Daniel Schultz:
From: Yannic Moog y.moog@phytec.de
Add a new nember to the eeprom_data that indicates whether the associated data is valid or not. Make use of this new member in the phytec_eeprom_data_init function by setting the valid value appropriately. Move the eeprom data to a new struct payload that holds the payload of the eeprom.
Signed-off-by: Yannic Moog y.moog@phytec.de Signed-off-by: Daniel Schultz d.schultz@phytec.de
Reviewed-by: Teresa Remmet t.remmet@phytec.de
board/phytec/common/imx8m_som_detection.c | 10 ++-- board/phytec/common/phytec_som_detection.c | 56 ++++++++++++-------- -- board/phytec/common/phytec_som_detection.h | 11 +++-- 3 files changed, 45 insertions(+), 32 deletions(-)
diff --git a/board/phytec/common/imx8m_som_detection.c b/board/phytec/common/imx8m_som_detection.c index 214b75db3b0..7571076a09e 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->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); @@ -99,7 +99,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->payload.api_rev < PHYTEC_API_REV2) return PHYTEC_EEPROM_INVAL; opt = phytec_get_opt(data); @@ -126,7 +126,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->payload.api_rev < PHYTEC_API_REV2) return PHYTEC_EEPROM_INVAL; opt = phytec_get_opt(data); @@ -154,7 +154,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->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 d167a77c25b..7913764be0a 100644 --- a/board/phytec/common/phytec_som_detection.c +++ b/board/phytec/common/phytec_som_detection.c @@ -54,6 +54,7 @@ int phytec_eeprom_data_init(struct phytec_eeprom_data *data, int ret, i; unsigned int crc; int *ptr; + const unsigned int payload_size = sizeof(struct phytec_eeprom_payload); if (!data) data = &eeprom_data; @@ -64,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); @@ -79,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++) + 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) @@ -120,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->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; @@ -182,10 +190,10 @@ 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->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; } @@ -197,10 +205,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->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; } @@ -209,10 +217,10 @@ 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->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) diff --git a/board/phytec/common/phytec_som_detection.h b/board/phytec/common/phytec_som_detection.h index ea99a687fee..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,13 +63,18 @@ 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);

From: Yannic Moog y.moog@phytec.de
For all of the functions that access the eeprom_data, make sure these data are valid. Use the valid member of the phytec_eeprom_data struct. This fixes a bug where only the API revision check guarded against accessing rubbish. But if API revision was e.g. 6, eeprom setup failed before, but phytec_get_imx8m_eth would still happily access the data.
Fixes: dc22188cdc8 ("board: phytec: Add common PHYTEC SoM detection")
Signed-off-by: Yannic Moog y.moog@phytec.de Signed-off-by: Daniel Schultz d.schultz@phytec.de --- board/phytec/common/imx8m_som_detection.c | 11 +++++++---- board/phytec/common/phytec_som_detection.c | 10 +++++++--- 2 files changed, 14 insertions(+), 7 deletions(-)
diff --git a/board/phytec/common/imx8m_som_detection.c b/board/phytec/common/imx8m_som_detection.c index 7571076a09e..ee34a5b9579 100644 --- a/board/phytec/common/imx8m_som_detection.c +++ b/board/phytec/common/imx8m_som_detection.c @@ -34,7 +34,7 @@ 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->payload.api_rev < PHYTEC_API_REV2) + if (!data->valid || data->payload.api_rev < PHYTEC_API_REV2) return -1;
som = data->payload.data.data_api2.som_no; @@ -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->payload.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->payload.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->payload.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 7913764be0a..5a4cc9e8b02 100644 --- a/board/phytec/common/phytec_som_detection.c +++ b/board/phytec/common/phytec_som_detection.c @@ -128,7 +128,7 @@ void __maybe_unused phytec_print_som_info(struct phytec_eeprom_data *data) if (!data) data = &eeprom_data;
- if (data->payload.api_rev < PHYTEC_API_REV2) + if (!data->valid || data->payload.api_rev < PHYTEC_API_REV2) return;
api2 = &data->payload.data.data_api2; @@ -190,6 +190,9 @@ char * __maybe_unused phytec_get_opt(struct phytec_eeprom_data *data) if (!data) data = &eeprom_data;
+ if (!data->valid) + return NULL; + if (data->payload.api_rev < PHYTEC_API_REV2) opt = data->payload.data.data_api0.opt; else @@ -205,7 +208,7 @@ u8 __maybe_unused phytec_get_rev(struct phytec_eeprom_data *data) if (!data) data = &eeprom_data;
- if (data->payload.api_rev < PHYTEC_API_REV2) + if (!data->valid || data->payload.api_rev < PHYTEC_API_REV2) return PHYTEC_EEPROM_INVAL;
api2 = &data->payload.data.data_api2; @@ -217,7 +220,8 @@ u8 __maybe_unused phytec_get_som_type(struct phytec_eeprom_data *data) { if (!data) data = &eeprom_data; - if (data->payload.api_rev < PHYTEC_API_REV2) + + if (!data->valid || data->payload.api_rev < PHYTEC_API_REV2) return PHYTEC_EEPROM_INVAL;
return data->payload.data.data_api2.som_type;

Am Freitag, dem 19.04.2024 um 08:55 -0700 schrieb Daniel Schultz:
From: Yannic Moog y.moog@phytec.de
For all of the functions that access the eeprom_data, make sure these data are valid. Use the valid member of the phytec_eeprom_data struct. This fixes a bug where only the API revision check guarded against accessing rubbish. But if API revision was e.g. 6, eeprom setup failed before, but phytec_get_imx8m_eth would still happily access the data.
Fixes: dc22188cdc8 ("board: phytec: Add common PHYTEC SoM detection")
Signed-off-by: Yannic Moog y.moog@phytec.de Signed-off-by: Daniel Schultz d.schultz@phytec.de
Reviewed-by: Teresa Remmet t.remmet@phytec.de
board/phytec/common/imx8m_som_detection.c | 11 +++++++---- board/phytec/common/phytec_som_detection.c | 10 +++++++--- 2 files changed, 14 insertions(+), 7 deletions(-)
diff --git a/board/phytec/common/imx8m_som_detection.c b/board/phytec/common/imx8m_som_detection.c index 7571076a09e..ee34a5b9579 100644 --- a/board/phytec/common/imx8m_som_detection.c +++ b/board/phytec/common/imx8m_som_detection.c @@ -34,7 +34,7 @@ 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->payload.api_rev < PHYTEC_API_REV2) + if (!data->valid || data->payload.api_rev < PHYTEC_API_REV2) return -1; som = data->payload.data.data_api2.som_no; @@ -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->payload.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->payload.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->payload.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 7913764be0a..5a4cc9e8b02 100644 --- a/board/phytec/common/phytec_som_detection.c +++ b/board/phytec/common/phytec_som_detection.c @@ -128,7 +128,7 @@ void __maybe_unused phytec_print_som_info(struct phytec_eeprom_data *data) if (!data) data = &eeprom_data; - if (data->payload.api_rev < PHYTEC_API_REV2) + if (!data->valid || data->payload.api_rev < PHYTEC_API_REV2) return; api2 = &data->payload.data.data_api2; @@ -190,6 +190,9 @@ char * __maybe_unused phytec_get_opt(struct phytec_eeprom_data *data) if (!data) data = &eeprom_data; + if (!data->valid) + return NULL;
if (data->payload.api_rev < PHYTEC_API_REV2) opt = data->payload.data.data_api0.opt; else @@ -205,7 +208,7 @@ u8 __maybe_unused phytec_get_rev(struct phytec_eeprom_data *data) if (!data) data = &eeprom_data; - if (data->payload.api_rev < PHYTEC_API_REV2) + if (!data->valid || data->payload.api_rev < PHYTEC_API_REV2) return PHYTEC_EEPROM_INVAL; api2 = &data->payload.data.data_api2; @@ -217,7 +220,8 @@ u8 __maybe_unused phytec_get_som_type(struct phytec_eeprom_data *data) { if (!data) data = &eeprom_data; - if (data->payload.api_rev < PHYTEC_API_REV2)
+ if (!data->valid || data->payload.api_rev < PHYTEC_API_REV2) return PHYTEC_EEPROM_INVAL; return data->payload.data.data_api2.som_type;

The ptr variable is currently defined as int and sizeof returns the size of the eeprom data struct as Byte (32 in total).
In case the eeprom is empty, the check, if the eeprom is empty, will most likely stop after 8 iterations because it will continue with the stack which should contain some data. Therefore, the init function will detect an empty EEPROM as API0 and return with the valid flag set to True.
Fixes: dc22188cdc8 ("board: phytec: Add common PHYTEC SoM detection")
Signed-off-by: Daniel Schultz d.schultz@phytec.de --- board/phytec/common/phytec_som_detection.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/board/phytec/common/phytec_som_detection.c b/board/phytec/common/phytec_som_detection.c index 5a4cc9e8b02..78c173df20d 100644 --- a/board/phytec/common/phytec_som_detection.c +++ b/board/phytec/common/phytec_som_detection.c @@ -53,7 +53,7 @@ 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) @@ -85,7 +85,7 @@ int phytec_eeprom_data_init(struct phytec_eeprom_data *data, goto err; }
- ptr = (int *)data; + ptr = (u8 *)data; for (i = 0; i < payload_size; ++i) if (ptr[i] != 0x0) break;

Am Freitag, dem 19.04.2024 um 08:55 -0700 schrieb Daniel Schultz:
The ptr variable is currently defined as int and sizeof returns the size of the eeprom data struct as Byte (32 in total).
In case the eeprom is empty, the check, if the eeprom is empty, will most likely stop after 8 iterations because it will continue with the stack which should contain some data. Therefore, the init function will detect an empty EEPROM as API0 and return with the valid flag set to True.
Fixes: dc22188cdc8 ("board: phytec: Add common PHYTEC SoM detection")
Signed-off-by: Daniel Schultz d.schultz@phytec.de
Reviewed-by: Teresa Remmet t.remmet@phytec.de
board/phytec/common/phytec_som_detection.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/board/phytec/common/phytec_som_detection.c b/board/phytec/common/phytec_som_detection.c index 5a4cc9e8b02..78c173df20d 100644 --- a/board/phytec/common/phytec_som_detection.c +++ b/board/phytec/common/phytec_som_detection.c @@ -53,7 +53,7 @@ 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) @@ -85,7 +85,7 @@ int phytec_eeprom_data_init(struct phytec_eeprom_data *data, goto err; } - ptr = (int *)data; + ptr = (u8 *)data; for (i = 0; i < payload_size; ++i) if (ptr[i] != 0x0) break;

Add all functions to read each SOM option from the EEPROM image and detect whether it's the correct product for this image.
Signed-off-by: Daniel Schultz d.schultz@phytec.de --- board/phytec/common/Kconfig | 18 +++ board/phytec/common/Makefile | 1 + board/phytec/common/am6_som_detection.c | 159 ++++++++++++++++++++++++ board/phytec/common/am6_som_detection.h | 36 ++++++ board/phytec/phycore_am62x/Kconfig | 4 + board/phytec/phycore_am64x/Kconfig | 4 + 6 files changed, 222 insertions(+) create mode 100644 board/phytec/common/am6_som_detection.c create mode 100644 board/phytec/common/am6_som_detection.h
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/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

On Fri, 19 Apr 2024 08:55:35 -0700, Daniel Schultz wrote:
This patch series extends PHYTEC's SOM detection by minor fixes, a generic helper function and a new valid flag.
Moreover, it adds a module to provide access to the SOM detection for our TI AM6 products.
Daniel Schultz (3): board: phytec: common: Generic "add extension" function board: phytec: common: Fix eepom is empty check board: phytec: Add SOM detection for AM6x
[...]
Applied to u-boot/master, thanks!
participants (3)
-
Daniel Schultz
-
Teresa Remmet
-
Tom Rini