summaryrefslogtreecommitdiff
path: root/board
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2020-01-22 02:10:28 +0300
committerTom Rini <trini@konsulko.com>2020-01-22 02:10:28 +0300
commit75dd53055a33f5bdb8ee2f53ce76c67052dfca7e (patch)
tree2ee907d73cbd5882455cc62fc9ac5724b983112e /board
parentad647690b1346f57847d4c9251293293af8928a8 (diff)
parent584a3d2622e9107d09434b05df8b6c50e25fe73f (diff)
downloadu-boot-75dd53055a33f5bdb8ee2f53ce76c67052dfca7e.tar.xz
Merge https://gitlab.denx.de/u-boot/custodians/u-boot-marvell
- Clearfog: Add run-time board detection with TLV EEPROM support (Baruch)
Diffstat (limited to 'board')
-rw-r--r--board/solidrun/clearfog/clearfog.c72
-rw-r--r--board/solidrun/common/Makefile5
-rw-r--r--board/solidrun/common/tlv_data.c102
-rw-r--r--board/solidrun/common/tlv_data.h18
4 files changed, 195 insertions, 2 deletions
diff --git a/board/solidrun/clearfog/clearfog.c b/board/solidrun/clearfog/clearfog.c
index 03724fee10..e268ef55a2 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},
@@ -39,6 +53,20 @@ static struct serdes_map board_serdes_map[] = {
int hws_board_topology_load(struct serdes_map **serdes_map_array, u8 *count)
{
+ cf_read_tlv_data();
+
+ if (sr_product_is(&cf_tlv_data, "Clearfog GTR")) {
+ board_serdes_map[0].serdes_type = PEX0;
+ board_serdes_map[0].serdes_speed = SERDES_SPEED_5_GBPS;
+ board_serdes_map[0].serdes_mode = PEX_ROOT_COMPLEX_X1;
+ }
+
+ if (sr_product_is(&cf_tlv_data, "Clearfog Base")) {
+ board_serdes_map[4].serdes_type = USB3_HOST0;
+ board_serdes_map[4].serdes_speed = SERDES_SPEED_5_GBPS;
+ board_serdes_map[4].serdes_mode = SERDES_DEFAULT_MODE;
+ }
+
*serdes_map_array = board_serdes_map;
*count = ARRAY_SIZE(board_serdes_map);
return 0;
@@ -68,11 +96,28 @@ static struct mv_ddr_topology_map board_topology_map = {
BUS_MASK_32BIT, /* Busses mask */
MV_DDR_CFG_DEFAULT, /* ddr configuration data source */
{ {0} }, /* raw spd data */
- {0} /* timing parameters */
+ {0}, /* timing parameters */
+ { {0} }, /* electrical configuration */
+ {0,}, /* electrical parameters */
+ 0x3, /* clock enable mask */
};
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;
}
@@ -125,7 +170,16 @@ int board_init(void)
int checkboard(void)
{
- puts("Board: SolidRun ClearFog\n");
+ char *board = "ClearFog";
+
+ cf_read_tlv_data();
+ if (strlen(cf_tlv_data.tlv_product_name[0]) > 0)
+ board = cf_tlv_data.tlv_product_name[0];
+
+ printf("Board: SolidRun %s", board);
+ if (strlen(cf_tlv_data.tlv_product_name[1]) > 0)
+ printf(", %s", cf_tlv_data.tlv_product_name[1]);
+ puts("\n");
return 0;
}
@@ -135,3 +189,17 @@ int board_eth_init(bd_t *bis)
cpu_eth_init(bis); /* Built in controller(s) come first */
return pci_eth_init(bis);
}
+
+int board_late_init(void)
+{
+ cf_read_tlv_data();
+
+ if (sr_product_is(&cf_tlv_data, "Clearfog Base"))
+ env_set("fdtfile", "armada-388-clearfog-base.dtb");
+ else if (sr_product_is(&cf_tlv_data, "Clearfog GTR S4"))
+ env_set("fdtfile", "armada-385-clearfog-gtr-s4.dtb");
+ else if (sr_product_is(&cf_tlv_data, "Clearfog GTR L8"))
+ env_set("fdtfile", "armada-385-clearfog-gtr-l8.dtb");
+
+ return 0;
+}
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_ */