summaryrefslogtreecommitdiff
path: root/board/phytec/common
diff options
context:
space:
mode:
Diffstat (limited to 'board/phytec/common')
-rw-r--r--board/phytec/common/Kconfig8
-rw-r--r--board/phytec/common/Makefile1
-rw-r--r--board/phytec/common/imx93_som_detection.c111
-rw-r--r--board/phytec/common/imx93_som_detection.h51
-rw-r--r--board/phytec/common/k3/board.c73
5 files changed, 244 insertions, 0 deletions
diff --git a/board/phytec/common/Kconfig b/board/phytec/common/Kconfig
index f394ace786a..bc5511707ac 100644
--- a/board/phytec/common/Kconfig
+++ b/board/phytec/common/Kconfig
@@ -19,6 +19,14 @@ config PHYTEC_IMX8M_SOM_DETECTION
Support of I2C EEPROM based SoM detection. Supported
for PHYTEC i.MX8MM/i.MX8MP boards
+config PHYTEC_IMX93_SOM_DETECTION
+ bool "Support SoM detection for i.MX93 PHYTEC platforms"
+ depends on ARCH_IMX9 && PHYTEC_SOM_DETECTION
+ default y
+ help
+ Support of I2C EEPROM based SoM detection. Supported
+ for PHYTEC i.MX93 based boards
+
config PHYTEC_AM62_SOM_DETECTION
bool "Support SoM detection for AM62x PHYTEC platforms"
depends on (TARGET_PHYCORE_AM62X_A53 || TARGET_PHYCORE_AM62X_R5) && \
diff --git a/board/phytec/common/Makefile b/board/phytec/common/Makefile
index cd78f7686fe..8126f7356e1 100644
--- a/board/phytec/common/Makefile
+++ b/board/phytec/common/Makefile
@@ -10,3 +10,4 @@ endif
obj-y += phytec_som_detection.o phytec_som_detection_blocks.o
obj-$(CONFIG_ARCH_K3) += am6_som_detection.o k3/
obj-$(CONFIG_ARCH_IMX8M) += imx8m_som_detection.o
+obj-$(CONFIG_ARCH_IMX9) += imx93_som_detection.o
diff --git a/board/phytec/common/imx93_som_detection.c b/board/phytec/common/imx93_som_detection.c
new file mode 100644
index 00000000000..eb9574d43b5
--- /dev/null
+++ b/board/phytec/common/imx93_som_detection.c
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2024 PHYTEC Messtechnik GmbH
+ * Author: Primoz Fiser <primoz.fiser@norik.com>
+ */
+
+#include <asm/arch/sys_proto.h>
+#include <dm/device.h>
+#include <dm/uclass.h>
+#include <i2c.h>
+#include <u-boot/crc.h>
+
+#include "imx93_som_detection.h"
+
+extern struct phytec_eeprom_data eeprom_data;
+
+#if IS_ENABLED(CONFIG_PHYTEC_IMX93_SOM_DETECTION)
+
+/* Check if the SoM is actually one of the following products:
+ * - i.MX93
+ *
+ * Returns 0 in case it's a known SoM. Otherwise, returns 1.
+ */
+u8 __maybe_unused phytec_imx93_detect(struct phytec_eeprom_data *data)
+{
+ u8 som;
+
+ if (!data)
+ data = &eeprom_data;
+
+ /* Early API revisions are not supported */
+ 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);
+
+ if (som == PHYTEC_IMX93_SOM && is_imx93())
+ return 0;
+
+ pr_err("%s: SoM ID does not match. Wrong EEPROM data?\n", __func__);
+ return 1;
+}
+
+/*
+ * Filter PHYTEC i.MX93 SoM options by option index
+ *
+ * Returns:
+ * - option value
+ * - PHYTEC_EEPROM_INVAL when the data is invalid
+ *
+ */
+u8 __maybe_unused phytec_imx93_get_opt(struct phytec_eeprom_data *data,
+ enum phytec_imx93_option_index idx)
+{
+ char *opt;
+ u8 opt_id;
+
+ 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)
+ opt_id = PHYTEC_GET_OPTION(opt[idx]);
+ else
+ opt_id = PHYTEC_EEPROM_INVAL;
+
+ debug("%s: opt[%d] id: %u\n", __func__, idx, opt_id);
+ return opt_id;
+}
+
+/*
+ * Filter PHYTEC i.MX93 SoM voltage
+ *
+ * Returns:
+ * - PHYTEC_IMX93_VOLTAGE_1V8 or PHYTEC_IMX93_VOLTAGE_3V3
+ * - PHYTEC_EEPROM_INVAL when the data is invalid
+ *
+ */
+enum phytec_imx93_voltage __maybe_unused phytec_imx93_get_voltage(struct phytec_eeprom_data *data)
+{
+ u8 option = phytec_imx93_get_opt(data, PHYTEC_IMX93_OPT_FEAT);
+
+ if (option == PHYTEC_EEPROM_INVAL)
+ return PHYTEC_IMX93_VOLTAGE_INVALID;
+ return (option & 0x01) ? PHYTEC_IMX93_VOLTAGE_1V8 : PHYTEC_IMX93_VOLTAGE_3V3;
+}
+
+#else
+
+inline u8 __maybe_unused phytec_imx93_detect(struct phytec_eeprom_data *data)
+{
+ return 1;
+}
+
+inline u8 __maybe_unused phytec_imx93_get_opt(struct phytec_eeprom_data *data,
+ enum phytec_imx93_option_index idx)
+{
+ return PHYTEC_EEPROM_INVAL;
+}
+
+inline enum phytec_imx93_voltage __maybe_unused phytec_imx93_get_voltage
+ (struct phytec_eeprom_data *data)
+{
+ return PHYTEC_EEPROM_INVAL;
+}
+
+#endif /* IS_ENABLED(CONFIG_PHYTEC_IMX93_SOM_DETECTION) */
diff --git a/board/phytec/common/imx93_som_detection.h b/board/phytec/common/imx93_som_detection.h
new file mode 100644
index 00000000000..a0803b47cbe
--- /dev/null
+++ b/board/phytec/common/imx93_som_detection.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2024 PHYTEC Messtechnik GmbH
+ * Author: Primoz Fiser <primoz.fiser@norik.com>
+ */
+
+#ifndef _PHYTEC_IMX93_SOM_DETECTION_H
+#define _PHYTEC_IMX93_SOM_DETECTION_H
+
+#include "phytec_som_detection.h"
+
+#define PHYTEC_IMX93_SOM 77
+
+enum phytec_imx93_option_index {
+ PHYTEC_IMX93_OPT_DDR = 0,
+ PHYTEC_IMX93_OPT_EMMC = 1,
+ PHYTEC_IMX93_OPT_CPU = 2,
+ PHYTEC_IMX93_OPT_FREQ = 3,
+ PHYTEC_IMX93_OPT_NPU = 4,
+ PHYTEC_IMX93_OPT_DISP = 5,
+ PHYTEC_IMX93_OPT_ETH = 6,
+ PHYTEC_IMX93_OPT_FEAT = 7,
+ PHYTEC_IMX93_OPT_TEMP = 8,
+ PHYTEC_IMX93_OPT_BOOT = 9,
+ PHYTEC_IMX93_OPT_LED = 10,
+ PHYTEC_IMX93_OPT_EEPROM = 11,
+};
+
+enum phytec_imx93_voltage {
+ PHYTEC_IMX93_VOLTAGE_INVALID = PHYTEC_EEPROM_INVAL,
+ PHYTEC_IMX93_VOLTAGE_3V3 = 0,
+ PHYTEC_IMX93_VOLTAGE_1V8 = 1,
+};
+
+enum phytec_imx93_ddr_eeprom_code {
+ PHYTEC_IMX93_DDR_INVALID = PHYTEC_EEPROM_INVAL,
+ PHYTEC_IMX93_LPDDR4X_512MB = 0,
+ PHYTEC_IMX93_LPDDR4X_1GB = 1,
+ PHYTEC_IMX93_LPDDR4X_2GB = 2,
+ PHYTEC_IMX93_LPDDR4_512MB = 3,
+ PHYTEC_IMX93_LPDDR4_1GB = 4,
+ PHYTEC_IMX93_LPDDR4_2GB = 5,
+};
+
+u8 __maybe_unused phytec_imx93_detect(struct phytec_eeprom_data *data);
+u8 __maybe_unused phytec_imx93_get_opt(struct phytec_eeprom_data *data,
+ enum phytec_imx93_option_index idx);
+enum phytec_imx93_voltage __maybe_unused phytec_imx93_get_voltage
+ (struct phytec_eeprom_data *data);
+
+#endif /* _PHYTEC_IMX93_SOM_DETECTION_H */
diff --git a/board/phytec/common/k3/board.c b/board/phytec/common/k3/board.c
index 3d7e090ccaa..346b2b6491a 100644
--- a/board/phytec/common/k3/board.c
+++ b/board/phytec/common/k3/board.c
@@ -6,7 +6,9 @@
#include <env_internal.h>
#include <fdt_support.h>
+#include <dm/ofnode.h>
#include <spl.h>
+#include <malloc.h>
#include <asm/arch/hardware.h>
#include "../am6_som_detection.h"
@@ -97,8 +99,79 @@ int board_late_init(void)
#endif
#if IS_ENABLED(CONFIG_OF_LIBFDT) && IS_ENABLED(CONFIG_OF_BOARD_SETUP)
+static int fdt_apply_overlay_from_fit(const char *overlay_path, void *fdt)
+{
+ u64 loadaddr;
+ ofnode node;
+ int ret;
+
+ node = ofnode_path(overlay_path);
+ if (!ofnode_valid(node))
+ return -FDT_ERR_NOTFOUND;
+
+ ret = ofnode_read_u64(node, "load", &loadaddr);
+ if (ret)
+ return ret;
+
+ return fdt_overlay_apply_verbose(fdt, (void *)loadaddr);
+}
+
+static void fdt_apply_som_overlays(void *blob)
+{
+ void *fdt_copy;
+ u32 fdt_size;
+ struct phytec_eeprom_data data;
+ int err;
+
+ fdt_size = fdt_totalsize(blob);
+ fdt_copy = malloc(fdt_size);
+ if (!fdt_copy)
+ goto fixup_error;
+
+ memcpy(fdt_copy, blob, fdt_size);
+
+ err = phytec_eeprom_data_setup(&data, 0, EEPROM_ADDR);
+ if (err)
+ goto fixup_error;
+
+ if (phytec_get_am6_rtc(&data) == 0) {
+ err = fdt_apply_overlay_from_fit("/fit-images/som-no-rtc", fdt_copy);
+ if (err)
+ goto fixup_error;
+ }
+
+ if (phytec_get_am6_spi(&data) == PHYTEC_EEPROM_VALUE_X) {
+ err = fdt_apply_overlay_from_fit("/fit-images/som-no-spi", fdt_copy);
+ if (err)
+ goto fixup_error;
+ }
+
+ if (phytec_get_am6_eth(&data) == 0) {
+ err = fdt_apply_overlay_from_fit("/fit-images/som-no-eth", fdt_copy);
+ if (err)
+ goto fixup_error;
+ }
+
+ if (phytec_am6_is_qspi(&data)) {
+ err = fdt_apply_overlay_from_fit("/fit-images/som-qspi-nor", fdt_copy);
+ if (err)
+ goto fixup_error;
+ }
+
+ memcpy(blob, fdt_copy, fdt_size);
+
+cleanup:
+ free(fdt_copy);
+ return;
+
+fixup_error:
+ pr_err("Failed to apply SoM overlays\n");
+ goto cleanup;
+}
+
int ft_board_setup(void *blob, struct bd_info *bd)
{
+ fdt_apply_som_overlays(blob);
fdt_copy_fixed_partitions(blob);
return 0;