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

Stefan Roese sr at denx.de
Mon Jan 13 08:22:18 CET 2020


On 25.11.19 11:30, Baruch Siach wrote:
> 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);

Nitpicking: Space missing around "-". Please run checkpatch.

> +	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;

AFAIK, using typedefs (in the sys_eeprom header most likely) is frowned
upon nowadays. Not sure if it makes sense to remove these typedefs as
this might make the code incompatible with other potential users.

> +	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;
>   }
> 

Other than my comments above:

Reviewed-by: Stefan Roese <sr at denx.de>

Thanks,
Stefan


More information about the U-Boot mailing list