1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (C) 2023 PHYTEC Messtechnik GmbH 4 * Author: Teresa Remmet <t.remmet@phytec.de> 5 */ 6 7#include <common.h> 8#include <asm/arch/sys_proto.h> 9#include <dm/device.h> 10#include <dm/uclass.h> 11#include <i2c.h> 12#include <u-boot/crc.h> 13 14#include "imx8m_som_detection.h" 15 16extern struct phytec_eeprom_data eeprom_data; 17 18#if IS_ENABLED(CONFIG_PHYTEC_IMX8M_SOM_DETECTION) 19 20/* Check if the SoM is actually one of the following products: 21 * - i.MX8MM 22 * - i.MX8MN 23 * - i.MX8MP 24 * - i.MX8MQ 25 * 26 * Returns 0 in case it's a known SoM. Otherwise, returns -1. 27 */ 28int __maybe_unused phytec_imx8m_detect(struct phytec_eeprom_data *data) 29{ 30 char *opt; 31 u8 som; 32 33 if (!data) 34 data = &eeprom_data; 35 36 /* We can not do the check for early API revisions */ 37 if (!data->valid || data->payload.api_rev < PHYTEC_API_REV2) 38 return -1; 39 40 som = data->payload.data.data_api2.som_no; 41 debug("%s: som id: %u\n", __func__, som); 42 43 opt = phytec_get_opt(data); 44 if (!opt) 45 return -1; 46 47 if (som == PHYTEC_IMX8MP_SOM && is_imx8mp()) 48 return 0; 49 50 if (som == PHYTEC_IMX8MM_SOM) { 51 if ((PHYTEC_GET_OPTION(opt[0]) != 0) && 52 (PHYTEC_GET_OPTION(opt[1]) == 0) && is_imx8mm()) 53 return 0; 54 else if ((PHYTEC_GET_OPTION(opt[0]) == 0) && 55 (PHYTEC_GET_OPTION(opt[1]) != 0) && is_imx8mn()) 56 return 0; 57 } 58 59 if (som == PHYTEC_IMX8MQ_SOM && is_imx8mq()) 60 return 0; 61 62 pr_err("%s: SoM ID does not match. Wrong EEPROM data?\n", __func__); 63 return -1; 64} 65 66/* 67 * All PHYTEC i.MX8M boards have RAM size definition at the 68 * same location. 69 */ 70u8 __maybe_unused phytec_get_imx8m_ddr_size(struct phytec_eeprom_data *data) 71{ 72 char *opt; 73 u8 ddr_id; 74 75 if (!data) 76 data = &eeprom_data; 77 78 if (!data->valid || data->payload.api_rev < PHYTEC_API_REV2) 79 return PHYTEC_EEPROM_INVAL; 80 81 opt = phytec_get_opt(data); 82 if (opt) 83 ddr_id = PHYTEC_GET_OPTION(opt[2]); 84 else 85 ddr_id = PHYTEC_EEPROM_INVAL; 86 87 debug("%s: ddr id: %u\n", __func__, ddr_id); 88 return ddr_id; 89} 90 91/* 92 * Filter SPI-NOR flash information. All i.MX8M boards have this at 93 * the same location. 94 * returns: 0x0 if no SPI is populated. Otherwise a board depended 95 * code for the size. PHYTEC_EEPROM_INVAL when the data is invalid. 96 */ 97u8 __maybe_unused phytec_get_imx8m_spi(struct phytec_eeprom_data *data) 98{ 99 char *opt; 100 u8 spi; 101 102 if (!data) 103 data = &eeprom_data; 104 105 if (!data->valid || data->payload.api_rev < PHYTEC_API_REV2) 106 return PHYTEC_EEPROM_INVAL; 107 108 opt = phytec_get_opt(data); 109 if (opt) 110 spi = PHYTEC_GET_OPTION(opt[4]); 111 else 112 spi = PHYTEC_EEPROM_INVAL; 113 114 debug("%s: spi: %u\n", __func__, spi); 115 return spi; 116} 117 118/* 119 * Filter ethernet phy information. All i.MX8M boards have this at 120 * the same location. 121 * returns: 0x0 if no ethernet phy is populated. 0x1 if it is populated. 122 * PHYTEC_EEPROM_INVAL when the data is invalid. 123 */ 124u8 __maybe_unused phytec_get_imx8m_eth(struct phytec_eeprom_data *data) 125{ 126 char *opt; 127 u8 eth; 128 129 if (!data) 130 data = &eeprom_data; 131 132 if (!data->valid || data->payload.api_rev < PHYTEC_API_REV2) 133 return PHYTEC_EEPROM_INVAL; 134 135 opt = phytec_get_opt(data); 136 if (opt) { 137 eth = PHYTEC_GET_OPTION(opt[5]); 138 eth &= 0x1; 139 } else { 140 eth = PHYTEC_EEPROM_INVAL; 141 } 142 143 debug("%s: eth: %u\n", __func__, eth); 144 return eth; 145} 146 147/* 148 * Filter RTC information for phyCORE-i.MX8MP. 149 * returns: 0 if no RTC is populated. 1 if it is populated. 150 * PHYTEC_EEPROM_INVAL when the data is invalid. 151 */ 152u8 __maybe_unused phytec_get_imx8mp_rtc(struct phytec_eeprom_data *data) 153{ 154 char *opt; 155 u8 rtc; 156 157 if (!data) 158 data = &eeprom_data; 159 160 if (!data->valid || data->payload.api_rev < PHYTEC_API_REV2) 161 return PHYTEC_EEPROM_INVAL; 162 163 opt = phytec_get_opt(data); 164 if (opt) { 165 rtc = PHYTEC_GET_OPTION(opt[5]); 166 rtc &= 0x4; 167 rtc = !(rtc >> 2); 168 } else { 169 rtc = PHYTEC_EEPROM_INVAL; 170 } 171 debug("%s: rtc: %u\n", __func__, rtc); 172 return rtc; 173} 174 175#else 176 177inline int __maybe_unused phytec_imx8m_detect(struct phytec_eeprom_data *data) 178{ 179 return -1; 180} 181 182inline u8 __maybe_unused 183phytec_get_imx8m_ddr_size(struct phytec_eeprom_data *data) 184{ 185 return PHYTEC_EEPROM_INVAL; 186} 187 188inline u8 __maybe_unused phytec_get_imx8mp_rtc(struct phytec_eeprom_data *data) 189{ 190 return PHYTEC_EEPROM_INVAL; 191} 192 193inline u8 __maybe_unused phytec_get_imx8m_spi(struct phytec_eeprom_data *data) 194{ 195 return PHYTEC_EEPROM_INVAL; 196} 197 198inline u8 __maybe_unused phytec_get_imx8m_eth(struct phytec_eeprom_data *data) 199{ 200 return PHYTEC_EEPROM_INVAL; 201} 202 203#endif /* IS_ENABLED(CONFIG_PHYTEC_IMX8M_SOM_DETECTION) */ 204