1*1badf2f4STim Harvey /* 2*1badf2f4STim Harvey * Copyright (C) 2014 Gateworks Corporation 3*1badf2f4STim Harvey * Author: Tim Harvey <tharvey@gateworks.com> 4*1badf2f4STim Harvey * 5*1badf2f4STim Harvey * SPDX-License-Identifier: GPL-2.0+ 6*1badf2f4STim Harvey */ 7*1badf2f4STim Harvey 8*1badf2f4STim Harvey #include <common.h> 9*1badf2f4STim Harvey #include <i2c.h> 10*1badf2f4STim Harvey 11*1badf2f4STim Harvey #include "gsc.h" 12*1badf2f4STim Harvey #include "ventana_eeprom.h" 13*1badf2f4STim Harvey 14*1badf2f4STim Harvey /* read ventana EEPROM, check for validity, and return baseboard type */ 15*1badf2f4STim Harvey int 16*1badf2f4STim Harvey read_eeprom(int bus, struct ventana_board_info *info) 17*1badf2f4STim Harvey { 18*1badf2f4STim Harvey int i; 19*1badf2f4STim Harvey int chksum; 20*1badf2f4STim Harvey char baseboard; 21*1badf2f4STim Harvey int type; 22*1badf2f4STim Harvey unsigned char *buf = (unsigned char *)info; 23*1badf2f4STim Harvey 24*1badf2f4STim Harvey memset(info, 0, sizeof(*info)); 25*1badf2f4STim Harvey 26*1badf2f4STim Harvey /* 27*1badf2f4STim Harvey * On a board with a missing/depleted backup battery for GSC, the 28*1badf2f4STim Harvey * board may be ready to probe the GSC before its firmware is 29*1badf2f4STim Harvey * running. We will wait here indefinately for the GSC/EEPROM. 30*1badf2f4STim Harvey */ 31*1badf2f4STim Harvey while (1) { 32*1badf2f4STim Harvey if (0 == i2c_set_bus_num(bus) && 33*1badf2f4STim Harvey 0 == i2c_probe(GSC_EEPROM_ADDR)) 34*1badf2f4STim Harvey break; 35*1badf2f4STim Harvey mdelay(1); 36*1badf2f4STim Harvey } 37*1badf2f4STim Harvey 38*1badf2f4STim Harvey /* read eeprom config section */ 39*1badf2f4STim Harvey if (gsc_i2c_read(GSC_EEPROM_ADDR, 0x00, 1, buf, sizeof(*info))) { 40*1badf2f4STim Harvey puts("EEPROM: Failed to read EEPROM\n"); 41*1badf2f4STim Harvey info->model[0] = 0; 42*1badf2f4STim Harvey return GW_UNKNOWN; 43*1badf2f4STim Harvey } 44*1badf2f4STim Harvey 45*1badf2f4STim Harvey /* sanity checks */ 46*1badf2f4STim Harvey if (info->model[0] != 'G' || info->model[1] != 'W') { 47*1badf2f4STim Harvey puts("EEPROM: Invalid Model in EEPROM\n"); 48*1badf2f4STim Harvey info->model[0] = 0; 49*1badf2f4STim Harvey return GW_UNKNOWN; 50*1badf2f4STim Harvey } 51*1badf2f4STim Harvey 52*1badf2f4STim Harvey /* validate checksum */ 53*1badf2f4STim Harvey for (chksum = 0, i = 0; i < sizeof(*info)-2; i++) 54*1badf2f4STim Harvey chksum += buf[i]; 55*1badf2f4STim Harvey if ((info->chksum[0] != chksum>>8) || 56*1badf2f4STim Harvey (info->chksum[1] != (chksum&0xff))) { 57*1badf2f4STim Harvey puts("EEPROM: Failed EEPROM checksum\n"); 58*1badf2f4STim Harvey info->model[0] = 0; 59*1badf2f4STim Harvey return GW_UNKNOWN; 60*1badf2f4STim Harvey } 61*1badf2f4STim Harvey 62*1badf2f4STim Harvey /* original GW5400-A prototype */ 63*1badf2f4STim Harvey baseboard = info->model[3]; 64*1badf2f4STim Harvey if (strncasecmp((const char *)info->model, "GW5400-A", 8) == 0) 65*1badf2f4STim Harvey baseboard = '0'; 66*1badf2f4STim Harvey 67*1badf2f4STim Harvey switch (baseboard) { 68*1badf2f4STim Harvey case '0': /* original GW5400-A prototype */ 69*1badf2f4STim Harvey type = GW54proto; 70*1badf2f4STim Harvey break; 71*1badf2f4STim Harvey case '1': 72*1badf2f4STim Harvey type = GW51xx; 73*1badf2f4STim Harvey break; 74*1badf2f4STim Harvey case '2': 75*1badf2f4STim Harvey type = GW52xx; 76*1badf2f4STim Harvey break; 77*1badf2f4STim Harvey case '3': 78*1badf2f4STim Harvey type = GW53xx; 79*1badf2f4STim Harvey break; 80*1badf2f4STim Harvey case '4': 81*1badf2f4STim Harvey type = GW54xx; 82*1badf2f4STim Harvey break; 83*1badf2f4STim Harvey default: 84*1badf2f4STim Harvey printf("EEPROM: Unknown model in EEPROM: %s\n", info->model); 85*1badf2f4STim Harvey type = GW_UNKNOWN; 86*1badf2f4STim Harvey break; 87*1badf2f4STim Harvey } 88*1badf2f4STim Harvey return type; 89*1badf2f4STim Harvey } 90