diff options
Diffstat (limited to 'board/gateworks/venice/eeprom.c')
-rw-r--r-- | board/gateworks/venice/eeprom.c | 130 |
1 files changed, 127 insertions, 3 deletions
diff --git a/board/gateworks/venice/eeprom.c b/board/gateworks/venice/eeprom.c index afaabf34879..d9a87193434 100644 --- a/board/gateworks/venice/eeprom.c +++ b/board/gateworks/venice/eeprom.c @@ -6,9 +6,11 @@ #include <gsc.h> #include <hexdump.h> #include <i2c.h> +#include <dm/device.h> #include <dm/uclass.h> #include "eeprom.h" +#include "../fsa.h" /* I2C */ #define SOM_EEPROM_BUSNO 0 @@ -18,7 +20,8 @@ struct venice_board_info som_info; struct venice_board_info base_info; -char venice_model[32]; +char venice_model[64]; +char venice_som_model[32]; char venice_baseboard_model[32]; u32 venice_serial; @@ -107,7 +110,7 @@ static int eeprom_read(int busno, int slave, int alen, struct venice_board_info /* validate checksum */ for (chksum = 0, i = 0; i < (int)sizeof(*info) - 2; i++) chksum += buf[i]; - if ((info->chksum[0] != chksum >> 8) || + if ((info->chksum[0] != ((chksum >> 8) & 0xff)) || (info->chksum[1] != (chksum & 0xff))) { printf("EEPROM: I2C%d@0x%02x: Invalid Checksum\n", busno, slave); print_hex_dump_bytes("", DUMP_PREFIX_NONE, buf, sizeof(*info)); @@ -126,6 +129,54 @@ static int eeprom_read(int busno, int slave, int alen, struct venice_board_info return 0; } +static int fsa_eeprom_read(const char *base, int fsa, struct fsa_board_info *info) +{ + int i; + int chksum; + unsigned char *buf = (unsigned char *)info; + struct udevice *dev, *bus; + int ret; + u8 reg; + + /* probe mux */ + ret = uclass_get_device_by_seq(UCLASS_I2C, 2, &bus); + if (!ret) + ret = dm_i2c_probe(bus, 0x70, 0, &dev); + if (ret) + return ret; + /* steer mux */ + if (!strncmp(base, "GW82", 4)) { + if (fsa < 3) + reg = (fsa == 1) ? BIT(1) : BIT(0); + else + return -EINVAL; + } + dm_i2c_write(dev, 0x00, ®, 1); + + /* get eeprom */ + ret = dm_i2c_probe(bus, 0x54, 0, &dev); + if (ret) + return ret; + + /* read eeprom config section */ + ret = dm_i2c_read(dev, 0x00, buf, sizeof(*info)); + if (ret) + return ret; + + /* validate checksum */ + for (chksum = 0, i = 0; i < (int)sizeof(*info) - 2; i++) + chksum += buf[i]; + if ((info->chksum[0] != ((chksum >> 8) & 0xff)) || + (info->chksum[1] != (chksum & 0xff))) { + printf("FSA%d EEPROM (board): %s: Invalid Checksum\n", fsa, dev->name); + print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, sizeof(*info)); + memset(info, 0, sizeof(*info)); + return -EINVAL; + } + + return 0; +} + /* determine BOM revision from model */ int get_bom_rev(const char *str) { @@ -299,6 +350,8 @@ static int eeprom_info(bool verbose) base_info.mfgdate[0], base_info.mfgdate[1], base_info.mfgdate[2], base_info.mfgdate[3]); } + if (verbose) + fsa_show(); return 0; } @@ -315,6 +368,7 @@ int venice_eeprom_init(int quiet) memset(&som_info, 0, sizeof(som_info)); return 0; } + strlcpy(venice_som_model, som_info.model, sizeof(venice_som_model)); /* read optional baseboard EEPROM */ eeprom_read(BASEBOARD_EEPROM_BUSNO, BASEBOARD_EEPROM_ADDR, 2, &base_info); @@ -322,7 +376,7 @@ int venice_eeprom_init(int quiet) /* create model strings */ if (base_info.model[0]) { sprintf(venice_model, "GW%c%c%c%c-%c%c-", - som_info.model[2], /* family */ + base_info.model[2], /* family */ base_info.model[3], /* baseboard */ base_info.model[4], base_info.model[5], /* subload of baseboard */ som_info.model[4], som_info.model[5]); /* last 2digits of SOM */ @@ -347,9 +401,74 @@ int venice_eeprom_init(int quiet) } venice_serial = som_info.serial; + /* GW8xxx product family naming scheme */ + if (venice_model[2] == '8') { + struct fsa_board_info fsa_info; + int i = 0; + int fsa; + + /* baseboard */ + if (base_info.model[0]) { + rev_pcb = get_pcb_rev(base_info.model); + rev_bom = get_bom_rev(base_info.model); + venice_model[i++] = 'G'; + venice_model[i++] = 'W'; + venice_model[i++] = base_info.model[2]; /* baseboard */ + venice_model[i++] = base_info.model[3]; + venice_model[i++] = base_info.model[4]; /* subload */ + venice_model[i++] = base_info.model[5]; + venice_model[i++] = rev_pcb; + if (rev_bom) + venice_model[i++] = rev_bom; + venice_model[i++] = '-'; + venice_model[i++] = 'S'; + } else { + venice_model[i++] = 'G'; + venice_model[i++] = 'W'; + } + + /* som */ + rev_pcb = get_pcb_rev(som_info.model); + rev_bom = get_bom_rev(som_info.model); + venice_model[i++] = som_info.model[4]; + venice_model[i++] = som_info.model[5]; + venice_model[i++] = rev_pcb; + if (rev_bom) + venice_model[i++] = rev_bom; + + /* fsa */ + for (fsa = 1; fsa < FSA_MAX; fsa++) { + if (!fsa_eeprom_read(venice_model, fsa, &fsa_info)) { + venice_model[i++] = '-'; + venice_model[i++] = 'F'; + venice_model[i++] = '0' + fsa; + venice_model[i++] = fsa_info.model[5]; + venice_model[i++] = fsa_info.model[6]; + venice_model[i++] = fsa_info.model[8]; + if (fsa_info.model[9]) + venice_model[i++] = fsa_info.model[9]; + } + } + + /* append extra model info */ + if (som_info.config[0] >= 32 && som_info.config[0] < 0x7f) { + venice_model[i++] = '-'; + strlcpy(venice_model + i, som_info.config, (sizeof(venice_model) - i) - 1); + i += strlen(som_info.config); + if (i >= sizeof(venice_model)) + i = sizeof(venice_model) - 1; + } + venice_model[i++] = 0; + } + if (!quiet) eeprom_info(false); + if (!strncmp(venice_model, "GW7901-SP486", 12) && + strcmp(venice_model, "GW7901-SP486-C")) { + return 2048; + } + return (16 << som_info.sdram_size); } @@ -363,6 +482,11 @@ const char *eeprom_get_model(void) return venice_model; } +const char *eeprom_get_som_model(void) +{ + return venice_som_model; +} + const char *eeprom_get_baseboard_model(void) { return venice_baseboard_model; |