diff options
Diffstat (limited to 'board/solidrun')
-rw-r--r-- | board/solidrun/clearfog/clearfog.c | 28 | ||||
-rw-r--r-- | board/solidrun/common/Makefile | 5 | ||||
-rw-r--r-- | board/solidrun/common/tlv_data.c | 102 | ||||
-rw-r--r-- | board/solidrun/common/tlv_data.h | 18 |
4 files changed, 153 insertions, 0 deletions
diff --git a/board/solidrun/clearfog/clearfog.c b/board/solidrun/clearfog/clearfog.c index 8b63811946..39a24aa69a 100644 --- a/board/solidrun/clearfog/clearfog.c +++ b/board/solidrun/clearfog/clearfog.c @@ -10,6 +10,7 @@ #include <asm/io.h> #include <asm/arch/cpu.h> #include <asm/arch/soc.h> +#include "../common/tlv_data.h" #include "../drivers/ddr/marvell/a38x/ddr3_init.h" #include <../serdes/a38x/high_speed_env_spec.h> @@ -28,6 +29,19 @@ DECLARE_GLOBAL_DATA_PTR; #define BOARD_GPP_POL_LOW 0x0 #define BOARD_GPP_POL_MID 0x0 +static struct tlv_data cf_tlv_data; + +static void cf_read_tlv_data(void) +{ + static bool read_once; + + if (read_once) + return; + read_once = true; + + read_tlv_data(&cf_tlv_data); +} + static struct serdes_map board_serdes_map[] = { {SATA0, SERDES_SPEED_3_GBPS, SERDES_DEFAULT_MODE, 0, 0}, {SGMII1, SERDES_SPEED_1_25_GBPS, SERDES_DEFAULT_MODE, 0, 0}, @@ -76,6 +90,20 @@ static struct mv_ddr_topology_map board_topology_map = { struct mv_ddr_topology_map *mv_ddr_topology_map_get(void) { + struct if_params *ifp = &board_topology_map.interface_params[0]; + + cf_read_tlv_data(); + + switch (cf_tlv_data.ram_size) { + case 4: + default: + ifp->memory_size = MV_DDR_DIE_CAP_4GBIT; + break; + case 8: + ifp->memory_size = MV_DDR_DIE_CAP_8GBIT; + break; + } + /* Return the board topology as defined in the board code */ return &board_topology_map; } diff --git a/board/solidrun/common/Makefile b/board/solidrun/common/Makefile new file mode 100644 index 0000000000..a72ac1b7b9 --- /dev/null +++ b/board/solidrun/common/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) SolidRun + +obj-$(CONFIG_TARGET_CLEARFOG) += tlv_data.o diff --git a/board/solidrun/common/tlv_data.c b/board/solidrun/common/tlv_data.c new file mode 100644 index 0000000000..f08ac8975a --- /dev/null +++ b/board/solidrun/common/tlv_data.c @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2020 SolidRun + */ + +#include <common.h> +#include <tlv_eeprom.h> +#include "tlv_data.h" + +#define SR_TLV_CODE_RAM_SIZE 0x81 + +static void store_product_name(struct tlvinfo_tlv *tlv_entry, + struct tlv_data *td) +{ + int len; + char *dest; + + if (strlen(td->tlv_product_name[0]) == 0) + dest = td->tlv_product_name[0]; + else if (strlen(td->tlv_product_name[1]) == 0) + dest = td->tlv_product_name[1]; + else + return; + + len = min_t(unsigned int, tlv_entry->length, + sizeof(td->tlv_product_name[0]) - 1); + memcpy(dest, tlv_entry->value, len); +} + +static void parse_tlv_vendor_ext(struct tlvinfo_tlv *tlv_entry, + struct tlv_data *td) +{ + u8 *val = tlv_entry->value; + u32 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; + + if (val[4] != SR_TLV_CODE_RAM_SIZE) + return; + if (tlv_entry->length != 6) + return; + td->ram_size = val[5]; +} + +static void parse_tlv_data(u8 *eeprom, struct tlvinfo_header *hdr, + struct tlvinfo_tlv *entry, struct tlv_data *td) +{ + unsigned int tlv_offset, tlv_len; + + tlv_offset = sizeof(struct tlvinfo_header); + tlv_len = sizeof(struct tlvinfo_header) + be16_to_cpu(hdr->totallen); + while (tlv_offset < tlv_len) { + entry = (struct tlvinfo_tlv *)&eeprom[tlv_offset]; + + switch (entry->type) { + case TLV_CODE_PRODUCT_NAME: + store_product_name(entry, td); + break; + case TLV_CODE_VENDOR_EXT: + parse_tlv_vendor_ext(entry, td); + break; + default: + break; + } + + tlv_offset += sizeof(struct tlvinfo_tlv) + entry->length; + } +} + +void read_tlv_data(struct tlv_data *td) +{ + u8 eeprom_data[TLV_TOTAL_LEN_MAX]; + struct tlvinfo_header *tlv_hdr; + struct tlvinfo_tlv *tlv_entry; + int ret, i; + + for (i = 0; i < 2; i++) { + ret = read_tlvinfo_tlv_eeprom(eeprom_data, &tlv_hdr, + &tlv_entry, i); + if (ret < 0) + continue; + parse_tlv_data(eeprom_data, tlv_hdr, tlv_entry, td); + } +} + +bool sr_product_is(const struct tlv_data *td, const char *product) +{ + /* Allow prefix sub-string match */ + if (strncmp(td->tlv_product_name[0], product, strlen(product)) == 0) + return true; + if (strncmp(td->tlv_product_name[1], product, strlen(product)) == 0) + return true; + + return false; +} diff --git a/board/solidrun/common/tlv_data.h b/board/solidrun/common/tlv_data.h new file mode 100644 index 0000000000..a1432e4b8e --- /dev/null +++ b/board/solidrun/common/tlv_data.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2020 SolidRun + */ + +#ifndef __BOARD_SR_COMMON_H_ +#define __BOARD_SR_COMMON_H_ + +struct tlv_data { + /* Store product name of both SOM and carrier */ + char tlv_product_name[2][32]; + unsigned int ram_size; +}; + +void read_tlv_data(struct tlv_data *td); +bool sr_product_is(const struct tlv_data *td, const char *product); + +#endif /* __BOARD_SR_COMMON_H_ */ |