[U-Boot] [PATCH 06/10] ARM: mvebu: clearfog: read basic TLV data

Baruch Siach baruch at tkos.co.il
Mon Nov 25 10:30:46 UTC 2019


Read RAM die capacity from the EEPROM TLV.

Follow the ONIE standard that defines the Vendor Extension entry type
for vendor specific data. We have no Private Enterprise Number at the
moment as the standard requires. Use the dummy all 0xff value for now.

Signed-off-by: Baruch Siach <baruch at tkos.co.il>
---
 board/solidrun/clearfog/clearfog.c | 118 +++++++++++++++++++++++++++++
 1 file changed, 118 insertions(+)

diff --git a/board/solidrun/clearfog/clearfog.c b/board/solidrun/clearfog/clearfog.c
index 8b6381194688..707afabb11a7 100644
--- a/board/solidrun/clearfog/clearfog.c
+++ b/board/solidrun/clearfog/clearfog.c
@@ -7,6 +7,7 @@
 #include <i2c.h>
 #include <miiphy.h>
 #include <netdev.h>
+#include <sys_eeprom.h>
 #include <asm/io.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/soc.h>
@@ -16,6 +17,14 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#define SR_TLV_CODE_RAM_DIE_SIZE	0x81
+
+/*
+ * Some Clearfog variants have TLV on SOM and on carrier, with separate
+ * product name entries.
+ */
+static char tlv_product_name[2][32];
+
 /*
  * Those values and defines are taken from the Marvell U-Boot version
  * "u-boot-2013.01-15t1-clearfog"
@@ -74,8 +83,117 @@ static struct mv_ddr_topology_map board_topology_map = {
 	0x3,				/* clock enable mask */
 };
 
+static void store_product_name(tlvinfo_tlv_t *tlv_entry)
+{
+	int len;
+	char *dest;
+
+	if (strlen(tlv_product_name[0]) == 0)
+		dest = tlv_product_name[0];
+	else if (strlen(tlv_product_name[1]) == 0)
+		dest = tlv_product_name[1];
+	else
+		return;
+
+	len = min_t(unsigned, tlv_entry->length,
+			sizeof(tlv_product_name[0])-1);
+	memcpy(dest, tlv_entry->value, len);
+}
+
+static bool sr_product_is(const char *product)
+{
+	/* Allow prefix sub-string match */
+	if (strncmp(tlv_product_name[0], product, strlen(product)) == 0)
+		return true;
+	if (strncmp(tlv_product_name[1], product, strlen(product)) == 0)
+		return true;
+
+	return false;
+}
+
+static void parse_tlv_vendor_ext(tlvinfo_tlv_t *tlv_entry)
+{
+	struct if_params *ifp = &board_topology_map.interface_params[0];
+	u8 *val = tlv_entry->value;
+	uint32_t pen; /* IANA Private Enterprise Numbers */
+
+	if (tlv_entry->length < 5) /* 4 bytes PEN + at least 1 byte type */
+		return;
+
+	/* PEN is big endian */
+	pen = (val[0] << 24) | (val[1] << 16) | (val[2] << 8) | val[3];
+	/* Not a real PEN */
+	if (pen != 0xffffffff)
+		return;
+
+	switch (val[4]) {
+	case SR_TLV_CODE_RAM_DIE_SIZE:
+		if (tlv_entry->length != 6)
+			break;
+		switch (val[5]) {
+		case 4:
+		default:
+			ifp->memory_size = MV_DDR_DIE_CAP_4GBIT;
+			break;
+		case 8:
+			ifp->memory_size = MV_DDR_DIE_CAP_8GBIT;
+			break;
+		}
+	default:
+		break;
+	}
+}
+
+static void parse_tlv_data(uint8_t *eeprom, tlvinfo_header_t *hdr,
+		tlvinfo_tlv_t *entry)
+{
+	unsigned tlv_offset, tlv_len;
+
+	tlv_offset = sizeof(tlvinfo_header_t);
+	tlv_len = sizeof(tlvinfo_header_t) + be16_to_cpu(hdr->totallen);
+	while (tlv_offset < tlv_len) {
+		entry = (tlvinfo_tlv_t *) &eeprom[tlv_offset];
+
+		switch (entry->type) {
+		case TLV_CODE_PRODUCT_NAME:
+			store_product_name(entry);
+			break;
+		case TLV_CODE_VENDOR_EXT:
+			parse_tlv_vendor_ext(entry);
+			break;
+		default:
+			break;
+		}
+
+		tlv_offset += sizeof(tlvinfo_tlv_t) + entry->length;
+	}
+}
+
+static void read_tlv_data(void)
+{
+	uint8_t eeprom_data[TLV_TOTAL_LEN_MAX];
+	tlvinfo_header_t *tlv_hdr;
+	tlvinfo_tlv_t *tlv_entry;
+	static bool ran_once;
+	int ret, i;
+
+	if (ran_once)
+		return;
+	ran_once = true;
+
+	for (i = 0; i < 2; i++) {
+		ret = read_tlvinfo_sys_eeprom_dev(eeprom_data, &tlv_hdr,
+				&tlv_entry, i);
+		if (ret < 0)
+			continue;
+		parse_tlv_data(eeprom_data, tlv_hdr, tlv_entry);
+	}
+}
+
 struct mv_ddr_topology_map *mv_ddr_topology_map_get(void)
 {
+	read_tlv_data();
+
 	/* Return the board topology as defined in the board code */
 	return &board_topology_map;
 }
-- 
2.24.0



More information about the U-Boot mailing list