u-boot/board/phytec/common/imx8m_som_detection.c
Yannic Moog 1e5de690f3 board: phytec: check eeprom_data validity
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: dc22188cdc ("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>
2024-04-29 10:55:57 -06:00

203 lines
4.3 KiB
C

// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2023 PHYTEC Messtechnik GmbH
* Author: Teresa Remmet <t.remmet@phytec.de>
*/
#include <common.h>
#include <asm/arch/sys_proto.h>
#include <dm/device.h>
#include <dm/uclass.h>
#include <i2c.h>
#include <u-boot/crc.h>
#include "imx8m_som_detection.h"
extern struct phytec_eeprom_data eeprom_data;
#if IS_ENABLED(CONFIG_PHYTEC_IMX8M_SOM_DETECTION)
/* Check if the SoM is actually one of the following products:
* - i.MX8MM
* - i.MX8MN
* - i.MX8MP
* - i.MX8MQ
*
* Returns 0 in case it's a known SoM. Otherwise, returns -1.
*/
int __maybe_unused phytec_imx8m_detect(struct phytec_eeprom_data *data)
{
char *opt;
u8 som;
if (!data)
data = &eeprom_data;
/* We can not 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_IMX8MP_SOM && is_imx8mp())
return 0;
if (som == PHYTEC_IMX8MM_SOM) {
if ((PHYTEC_GET_OPTION(opt[0]) != 0) &&
(PHYTEC_GET_OPTION(opt[1]) == 0) && is_imx8mm())
return 0;
else if ((PHYTEC_GET_OPTION(opt[0]) == 0) &&
(PHYTEC_GET_OPTION(opt[1]) != 0) && is_imx8mn())
return 0;
}
if (som == PHYTEC_IMX8MQ_SOM && is_imx8mq())
return 0;
pr_err("%s: SoM ID does not match. Wrong EEPROM data?\n", __func__);
return -1;
}
/*
* All PHYTEC i.MX8M boards have RAM size definition at the
* same location.
*/
u8 __maybe_unused phytec_get_imx8m_ddr_size(struct phytec_eeprom_data *data)
{
char *opt;
u8 ddr_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)
ddr_id = PHYTEC_GET_OPTION(opt[2]);
else
ddr_id = PHYTEC_EEPROM_INVAL;
debug("%s: ddr id: %u\n", __func__, ddr_id);
return ddr_id;
}
/*
* Filter SPI-NOR flash information. All i.MX8M boards have this at
* the same location.
* returns: 0x0 if no SPI is populated. Otherwise a board depended
* code for the size. PHYTEC_EEPROM_INVAL when the data is invalid.
*/
u8 __maybe_unused phytec_get_imx8m_spi(struct phytec_eeprom_data *data)
{
char *opt;
u8 spi;
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)
spi = PHYTEC_GET_OPTION(opt[4]);
else
spi = PHYTEC_EEPROM_INVAL;
debug("%s: spi: %u\n", __func__, spi);
return spi;
}
/*
* Filter ethernet phy information. All i.MX8M boards have this at
* the same location.
* returns: 0x0 if no ethernet phy is populated. 0x1 if it is populated.
* PHYTEC_EEPROM_INVAL when the data is invalid.
*/
u8 __maybe_unused phytec_get_imx8m_eth(struct phytec_eeprom_data *data)
{
char *opt;
u8 eth;
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) {
eth = PHYTEC_GET_OPTION(opt[5]);
eth &= 0x1;
} else {
eth = PHYTEC_EEPROM_INVAL;
}
debug("%s: eth: %u\n", __func__, eth);
return eth;
}
/*
* Filter RTC information for phyCORE-i.MX8MP.
* returns: 0 if no RTC is populated. 1 if it is populated.
* PHYTEC_EEPROM_INVAL when the data is invalid.
*/
u8 __maybe_unused phytec_get_imx8mp_rtc(struct phytec_eeprom_data *data)
{
char *opt;
u8 rtc;
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) {
rtc = PHYTEC_GET_OPTION(opt[5]);
rtc &= 0x4;
rtc = !(rtc >> 2);
} else {
rtc = PHYTEC_EEPROM_INVAL;
}
debug("%s: rtc: %u\n", __func__, rtc);
return rtc;
}
#else
inline int __maybe_unused phytec_imx8m_detect(struct phytec_eeprom_data *data)
{
return -1;
}
inline u8 __maybe_unused
phytec_get_imx8m_ddr_size(struct phytec_eeprom_data *data)
{
return PHYTEC_EEPROM_INVAL;
}
inline u8 __maybe_unused phytec_get_imx8mp_rtc(struct phytec_eeprom_data *data)
{
return PHYTEC_EEPROM_INVAL;
}
inline u8 __maybe_unused phytec_get_imx8m_spi(struct phytec_eeprom_data *data)
{
return PHYTEC_EEPROM_INVAL;
}
inline u8 __maybe_unused phytec_get_imx8m_eth(struct phytec_eeprom_data *data)
{
return PHYTEC_EEPROM_INVAL;
}
#endif /* IS_ENABLED(CONFIG_PHYTEC_IMX8M_SOM_DETECTION) */