board: phytec: imx93: Add eeprom-based hardware introspection

The phyCORE-i.MX 93 is available in various variants. Relevant variant
options for the spl/u-boot are:
- with or without HS400 support for the eMMC
- with 1GB ram chip, or 2GB ram chip

The phyCORE's eeprom contains all information about the existing variant
options. Add evaluation of the eeprom data to the spl/u-boot to
enable/disable HS400 and to select the appropriate ram configuration at
startup.

Signed-off-by: Christoph Stoidner <c.stoidner@phytec.de>
Reviewed-by: Wadim Egorov <w.egorov@phytec.de>
Reviewed-by: Yannic Moog <y.moog@phytec.de>
Tested-by: Primoz Fiser <primoz.fiser@norik.com>
This commit is contained in:
Christoph Stoidner 2024-11-20 17:31:42 +01:00 committed by Fabio Estevam
parent 29d4a73bd0
commit d3b9b79968
11 changed files with 363 additions and 2 deletions

View file

@ -139,6 +139,13 @@
&usdhc1 {
bootph-pre-ram;
bootph-some-ram;
/*
* Remove pinctrl assignments once they are added to imx93-phycore-som.dtsi
*/
pinctrl-names = "default", "state_100mhz", "state_200mhz";
pinctrl-0 = <&pinctrl_usdhc1>;
pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
};
&usdhc2 {
@ -215,6 +222,48 @@
MX93_PAD_ENET2_RD3__GPIO4_IO27 0x31e
>;
};
/*
* Remove pinctrl_usdhc1_100mhz and pinctrl_usdhc1_200mhz once they
* are added to imx93-phycore-som.dtsi
*/
/* need to config the SION for data and cmd pad, refer to ERR052021 */
pinctrl_usdhc1_100mhz: usdhc1-100mhzgrp {
bootph-pre-ram;
bootph-some-ram;
fsl,pins = <
MX93_PAD_SD1_CLK__USDHC1_CLK 0x17be
MX93_PAD_SD1_CMD__USDHC1_CMD 0x4000139e
MX93_PAD_SD1_DATA0__USDHC1_DATA0 0x4000138e
MX93_PAD_SD1_DATA1__USDHC1_DATA1 0x4000139e
MX93_PAD_SD1_DATA2__USDHC1_DATA2 0x400013be
MX93_PAD_SD1_DATA3__USDHC1_DATA3 0x4000139e
MX93_PAD_SD1_DATA4__USDHC1_DATA4 0x4000139e
MX93_PAD_SD1_DATA5__USDHC1_DATA5 0x4000139e
MX93_PAD_SD1_DATA6__USDHC1_DATA6 0x4000139e
MX93_PAD_SD1_DATA7__USDHC1_DATA7 0x4000139e
MX93_PAD_SD1_STROBE__USDHC1_STROBE 0x179e
>;
};
/* need to config the SION for data and cmd pad, refer to ERR052021 */
pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp {
bootph-pre-ram;
bootph-some-ram;
fsl,pins = <
MX93_PAD_SD1_CLK__USDHC1_CLK 0x17be
MX93_PAD_SD1_CMD__USDHC1_CMD 0x4000139e
MX93_PAD_SD1_DATA0__USDHC1_DATA0 0x4000139e
MX93_PAD_SD1_DATA1__USDHC1_DATA1 0x400013be
MX93_PAD_SD1_DATA2__USDHC1_DATA2 0x400013be
MX93_PAD_SD1_DATA3__USDHC1_DATA3 0x400013be
MX93_PAD_SD1_DATA4__USDHC1_DATA4 0x400013be
MX93_PAD_SD1_DATA5__USDHC1_DATA5 0x400013be
MX93_PAD_SD1_DATA6__USDHC1_DATA6 0x400013be
MX93_PAD_SD1_DATA7__USDHC1_DATA7 0x400013be
MX93_PAD_SD1_STROBE__USDHC1_STROBE 0x179e
>;
};
};
&lpi2c3 {
@ -305,4 +354,13 @@
};
};
};
eeprom@50 {
bootph-pre-ram;
bootph-some-ram;
compatible = "atmel,24c32";
reg = <0x50>;
pagesize = <32>;
vcc-supply = <&buck4>;
};
};

View file

@ -45,6 +45,8 @@ config TARGET_PHYCORE_IMX93
bool "phycore_imx93"
select IMX93
select IMX9_LPDDR4X
select OF_BOARD_FIXUP
select OF_BOARD_SETUP
endchoice

View file

@ -634,7 +634,7 @@ static int low_drive_freq_update(void *blob)
return 0;
}
#ifdef CONFIG_OF_BOARD_FIXUP
#if defined(CONFIG_OF_BOARD_FIXUP) && !defined(CONFIG_TARGET_PHYCORE_IMX93)
#ifndef CONFIG_XPL_BUILD
int board_fix_fdt(void *fdt)
{

View file

@ -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) && \

View file

@ -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

View file

@ -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) */

View file

@ -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 */

View file

@ -10,4 +10,32 @@ config SYS_VENDOR
config SYS_CONFIG_NAME
default "phycore_imx93"
config PHYCORE_IMX93_RAM_TYPE_FIX
bool "Set phyCORE-i.MX93 RAM type and size fix instead of detecting"
default false
help
RAM type and size is being automatically detected with the help
of the PHYTEC EEPROM introspection data.
Set RAM type to a fix value instead.
choice
prompt "phyCORE-i.MX93 RAM type"
depends on PHYCORE_IMX93_RAM_TYPE_FIX
default PHYCORE_IMX93_RAM_TYPE_LPDDR4X_1GB
config PHYCORE_IMX93_RAM_TYPE_LPDDR4X_1GB
bool "LPDDR4X 1GB RAM"
help
Set RAM type fixed to LPDDR4X and RAM size fixed to 1GB
for phyCORE-i.MX93.
config PHYCORE_IMX93_RAM_TYPE_LPDDR4X_2GB
bool "LPDDR4X 2GB RAM"
help
Set RAM type fixed to LPDDR4X and RAM size fixed to 2GB
for phyCORE-i.MX93.
endchoice
source "board/phytec/common/Kconfig"
endif

View file

@ -1,10 +1,13 @@
phyCORE-i.MX93
M: Mathieu Othacehe <m.othacehe@gmail.com>
R: Christoph Stoidner <c.stoidner@phytec.de>
W: https://www.phytec.eu/en/produkte/system-on-modules/phycore-imx-91-93/
S: Maintained
F: arch/arm/dts/imx93-phyboard-segin.dts
F: arch/arm/dts/imx93-phycore-som.dtsi
F: arch/arm/dts/imx93-phyboard-segin-u-boot.dtsi
F: board/phytec/phycore_imx93/
F: board/phytec/common/imx93_som_detection.c
F: board/phytec/common/imx93_som_detection.h
F: configs/imx93-phyboard-segin_defconfig
F: include/configs/phycore_imx93.h

View file

@ -3,6 +3,7 @@
* Copyright (C) 2023 PHYTEC Messtechnik GmbH
* Author: Christoph Stoidner <c.stoidner@phytec.de>
* Copyright (C) 2024 Mathieu Othacehe <m.othacehe@gmail.com>
* Copyright (C) 2024 PHYTEC Messtechnik GmbH
*/
#include <asm/arch-imx9/ccm_regs.h>
@ -12,11 +13,21 @@
#include <asm/global_data.h>
#include <asm/mach-imx/boot_mode.h>
#include <env.h>
#include <fdt_support.h>
#include "../common/imx93_som_detection.h"
DECLARE_GLOBAL_DATA_PTR;
#define EEPROM_ADDR 0x50
int board_init(void)
{
int ret = phytec_eeprom_data_setup(NULL, 2, EEPROM_ADDR);
if (ret)
printf("%s: EEPROM data init failed\n", __func__);
return 0;
}
@ -40,3 +51,43 @@ int board_late_init(void)
return 0;
}
static void emmc_fixup(void *blob, struct phytec_eeprom_data *data)
{
enum phytec_imx93_voltage voltage = phytec_imx93_get_voltage(data);
int offset;
if (voltage == PHYTEC_IMX93_VOLTAGE_INVALID)
goto err;
if (voltage == PHYTEC_IMX93_VOLTAGE_1V8) {
offset = fdt_node_offset_by_compat_reg(blob, "fsl,imx93-usdhc",
0x42850000);
if (offset)
fdt_delprop(blob, offset, "no-1-8-v");
else
goto err;
}
return;
err:
printf("Could not detect eMMC VDD-IO. Fall back to default.\n");
}
int board_fix_fdt(void *blob)
{
struct phytec_eeprom_data data;
phytec_eeprom_data_setup(&data, 2, EEPROM_ADDR);
emmc_fixup(blob, &data);
return 0;
}
int ft_board_setup(void *blob, struct bd_info *bd)
{
emmc_fixup(blob, NULL);
return 0;
}

View file

@ -3,6 +3,7 @@
* Copyright (C) 2023 PHYTEC Messtechnik GmbH
* Author: Christoph Stoidner <c.stoidner@phytec.de>
* Copyright (C) 2024 Mathieu Othacehe <m.othacehe@gmail.com>
* Copyright (C) 2024 PHYTEC Messtechnik GmbH
*/
#include <asm/arch/clock.h>
@ -20,6 +21,8 @@
#include <power/pca9450.h>
#include <spl.h>
#include "../common/imx93_som_detection.h"
DECLARE_GLOBAL_DATA_PTR;
/*
@ -27,6 +30,13 @@ DECLARE_GLOBAL_DATA_PTR;
* when pca9451a support is added.
*/
#define PCA9450_REG_PWRCTRL_TOFF_DEB BIT(5)
#define EEPROM_ADDR 0x50
/*
* Prototypes of automatically generated ram config file
*/
void set_dram_timings_2gb_lpddr4x(void);
void set_dram_timings_1gb_lpddr4x_900mhz(void);
int spl_board_boot_device(enum boot_device boot_dev_spl)
{
@ -46,6 +56,44 @@ void spl_board_init(void)
void spl_dram_init(void)
{
int ret;
enum phytec_imx93_ddr_eeprom_code ddr_opt = PHYTEC_IMX93_DDR_INVALID;
/* NOTE: In SPL lpi2c3 is mapped to bus 0 */
ret = phytec_eeprom_data_setup(NULL, 0, EEPROM_ADDR);
if (ret && !IS_ENABLED(CONFIG_PHYCORE_IMX93_RAM_TYPE_FIX))
goto out;
ret = phytec_imx93_detect(NULL);
if (!ret)
phytec_print_som_info(NULL);
if (IS_ENABLED(CONFIG_PHYCORE_IMX93_RAM_TYPE_FIX)) {
if (IS_ENABLED(CONFIG_PHYCORE_IMX93_RAM_TYPE_LPDDR4X_1GB))
ddr_opt = PHYTEC_IMX93_LPDDR4X_1GB;
else if (IS_ENABLED(CONFIG_PHYCORE_IMX93_RAM_TYPE_LPDDR4X_2GB))
ddr_opt = PHYTEC_IMX93_LPDDR4X_2GB;
} else {
ddr_opt = phytec_imx93_get_opt(NULL, PHYTEC_IMX93_OPT_DDR);
}
switch (ddr_opt) {
case PHYTEC_IMX93_LPDDR4X_1GB:
if (is_voltage_mode(VOLT_LOW_DRIVE))
set_dram_timings_1gb_lpddr4x_900mhz();
break;
case PHYTEC_IMX93_LPDDR4X_2GB:
set_dram_timings_2gb_lpddr4x();
break;
default:
goto out;
}
ddr_init(&dram_timing);
return;
out:
puts("Could not detect correct RAM type and size. Fall back to default.\n");
if (is_voltage_mode(VOLT_LOW_DRIVE))
set_dram_timings_1gb_lpddr4x_900mhz();
ddr_init(&dram_timing);
}