// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (C) 2023 PHYTEC Messtechnik GmbH * Author: Teresa Remmet */ #include #include #include #include #include #include #include "imx8m_som_detection.h" extern struct phytec_eeprom_data eeprom_data; /* 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. */ u8 __maybe_unused phytec_imx8m_detect(struct phytec_eeprom_data *data) { char *opt; u8 som; /* We can not do the check for early API revisions */ if (data->api_rev < PHYTEC_API_REV2) return -1; if (!data) data = &eeprom_data; som = data->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; 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->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->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->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; }