The AM654x EVM based on the TI K3 family of SoCs have an updated board
detection EEPROM structure, now comprising variable-sized TLV-type
records, containing a superset of what is already being provided on
earlier platforms such as DRA7. Add basic support for parsing the new
data structures contained on the base board into the common TI EEPROM
structure while also providing infrastructure that can be used later on
to parse data from additional EEPROMs such as the ones that are used on
daughtercards for this platform.
Signed-off-by: Andreas Dannenberg
Reviewed-by: Lokesh Vutla
---
board/ti/common/board_detect.c | 214 +
board/ti/common/board_detect.h | 194 ++
2 files changed, 408 insertions(+)
diff --git a/board/ti/common/board_detect.c b/board/ti/common/board_detect.c
index e258e22f37..fea39f21e8 100644
--- a/board/ti/common/board_detect.c
+++ b/board/ti/common/board_detect.c
@@ -8,6 +8,7 @@
*/
#include
+#include
#include
#include
#include
@@ -284,6 +285,191 @@ int __maybe_unused ti_i2c_eeprom_dra7_get(int bus_addr,
int dev_addr)
return 0;
}
+static int ti_i2c_eeprom_am6_parse_record(struct ti_am6_eeprom_record *record,
+ struct ti_am6_eeprom *ep,
+ char **mac_addr,
+ u8 mac_addr_max_cnt,
+ u8 *mac_addr_cnt)
+{
+ switch (record->header.id) {
+ case TI_AM6_EEPROM_RECORD_BOARD_INFO:
+ if (record->header.len != sizeof(record->data.board_info))
+ return -EINVAL;
+
+ if (!ep)
+ break;
+
+ /* Populate (and clean, if needed) the board name */
+ strlcpy(ep->name, record->data.board_info.name,
+ sizeof(ep->name));
+ ti_eeprom_string_cleanup(ep->name);
+
+ /* Populate selected other fields from the board info record */
+ strlcpy(ep->version, record->data.board_info.version,
+ sizeof(ep->version));
+ strlcpy(ep->software_revision,
+ record->data.board_info.software_revision,
+ sizeof(ep->software_revision));
+ strlcpy(ep->serial, record->data.board_info.serial,
+ sizeof(ep->serial));
+ break;
+ case TI_AM6_EEPROM_RECORD_MAC_INFO:
+ if (record->header.len != sizeof(record->data.mac_info))
+ return -EINVAL;
+
+ if (!mac_addr || !mac_addr_max_cnt)
+ break;
+
+ *mac_addr_cnt = ((record->data.mac_info.mac_control &
+TI_AM6_EEPROM_MAC_ADDR_COUNT_MASK) >>
+TI_AM6_EEPROM_MAC_ADDR_COUNT_SHIFT) + 1;
+
+ /*
+* The EEPROM can (but may not) hold a very large amount
+* of MAC addresses, by far exceeding what we want/can store
+* in the common memory array, so only grab what we can fit.
+* Note that a value of 0 means 1 MAC address, and so on.
+*/
+ *mac_addr_cnt = min(*mac_addr_cnt, mac_addr_max_cnt);
+
+ memcpy(mac_addr, record->data.mac_info.mac_addr,
+ *mac_addr_cnt * TI_EEPROM_HDR_ETH_ALEN);
+ break;
+ case 0x00:
+ /* Illegal value... Fall through... */
+ case 0xFF:
+ /* Illegal value... Something went horribly wrong... */
+ return -EINVAL;
+ default:
+ pr_warn("%s: Ignoring record id %u\n", __func__,
+ record->header.id);
+ }
+
+ return 0;
+}
+
+int __maybe_unused ti_i2c_eeprom_am6_get(int bus_addr, int dev_addr,
+struct ti_am6_eeprom *ep,
+char **mac_addr,
+u8 mac_addr_max_cnt,
+u8 *mac_addr_cnt)
+{
+ struct udevice *dev;
+ struct udevice *bus;
+ unsigned int eeprom_addr;
+ struct ti_am6_eeprom_record_board_id board_id;
+ struct ti_am6_eeprom_record record;
+ int rc;
+
+ /* Initialize with a known bad marker for i2c fails.. */
+ memset(ep, 0, sizeof(*ep));
+ ep->header = TI_DEAD_EEPROM_MAGIC;
+
+ /* Read the board ID record which is always the first EEPROM record */
+ rc = ti_i2c_eeprom_get(bus_addr, dev_addr, TI_EEPROM_HEADER_MAGIC,
+ sizeof(board_id), (uint8_t *)&board_id);
+ if (rc)
+ return rc;
+
+ if (board_id.header.id != TI_AM6_EEPROM_RECORD_BOARD_ID) {
+ pr_err("%s: Invalid board ID record!\n", __func__);
+ return -EINVAL;
+ }
+
+ /* Establish