[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