uboot/board/gateworks/gw_ventana/eeprom.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2014 Gateworks Corporation
   4 * Author: Tim Harvey <tharvey@gateworks.com>
   5 */
   6
   7#include <common.h>
   8#include <errno.h>
   9#include <i2c.h>
  10#include <malloc.h>
  11#include <asm/bitops.h>
  12
  13#include "gsc.h"
  14#include "ventana_eeprom.h"
  15
  16/* read ventana EEPROM, check for validity, and return baseboard type */
  17int
  18read_eeprom(int bus, struct ventana_board_info *info)
  19{
  20        int i;
  21        int chksum;
  22        char baseboard;
  23        int type;
  24        unsigned char *buf = (unsigned char *)info;
  25
  26        memset(info, 0, sizeof(*info));
  27
  28        /*
  29         * On a board with a missing/depleted backup battery for GSC, the
  30         * board may be ready to probe the GSC before its firmware is
  31         * running.  We will wait here indefinately for the GSC/EEPROM.
  32         */
  33        while (1) {
  34                if (0 == i2c_set_bus_num(bus) &&
  35                    0 == i2c_probe(GSC_EEPROM_ADDR))
  36                        break;
  37                mdelay(1);
  38        }
  39
  40        /* read eeprom config section */
  41        if (gsc_i2c_read(GSC_EEPROM_ADDR, 0x00, 1, buf, sizeof(*info))) {
  42                puts("EEPROM: Failed to read EEPROM\n");
  43                return GW_UNKNOWN;
  44        }
  45
  46        /* sanity checks */
  47        if (info->model[0] != 'G' || info->model[1] != 'W') {
  48                puts("EEPROM: Invalid Model in EEPROM\n");
  49                return GW_UNKNOWN;
  50        }
  51
  52        /* validate checksum */
  53        for (chksum = 0, i = 0; i < sizeof(*info)-2; i++)
  54                chksum += buf[i];
  55        if ((info->chksum[0] != chksum>>8) ||
  56            (info->chksum[1] != (chksum&0xff))) {
  57                puts("EEPROM: Failed EEPROM checksum\n");
  58                return GW_UNKNOWN;
  59        }
  60
  61        /* original GW5400-A prototype */
  62        baseboard = info->model[3];
  63        if (strncasecmp((const char *)info->model, "GW5400-A", 8) == 0)
  64                baseboard = '0';
  65
  66        type = GW_UNKNOWN;
  67        switch (baseboard) {
  68        case '0': /* original GW5400-A prototype */
  69                type = GW54proto;
  70                break;
  71        case '1':
  72                type = GW51xx;
  73                break;
  74        case '2':
  75                type = GW52xx;
  76                break;
  77        case '3':
  78                type = GW53xx;
  79                break;
  80        case '4':
  81                type = GW54xx;
  82                break;
  83        case '5':
  84                if (info->model[4] == '1') {
  85                        type = GW551x;
  86                        break;
  87                } else if (info->model[4] == '2') {
  88                        type = GW552x;
  89                        break;
  90                } else if (info->model[4] == '3') {
  91                        type = GW553x;
  92                        break;
  93                }
  94                break;
  95        case '6':
  96                if (info->model[4] == '0')
  97                        type = GW560x;
  98                break;
  99        case '9':
 100                if (info->model[4] == '0' && info->model[5] == '3')
 101                        type = GW5903;
 102                if (info->model[4] == '0' && info->model[5] == '4')
 103                        type = GW5904;
 104                break;
 105        }
 106        return type;
 107}
 108
 109/* list of config bits that the bootloader will remove from dtb if not set */
 110struct ventana_eeprom_config econfig[] = {
 111        { "eth0", "ethernet0", EECONFIG_ETH0 },
 112        { "usb0", NULL, EECONFIG_USB0 },
 113        { "usb1", NULL, EECONFIG_USB1 },
 114        { "mmc0", NULL, EECONFIG_SD0 },
 115        { "mmc1", NULL, EECONFIG_SD1 },
 116        { "mmc2", NULL, EECONFIG_SD2 },
 117        { "mmc3", NULL, EECONFIG_SD3 },
 118        { /* Sentinel */ }
 119};
 120
 121#if defined(CONFIG_CMD_EECONFIG) && !defined(CONFIG_SPL_BUILD)
 122static struct ventana_eeprom_config *get_config(const char *name)
 123{
 124        struct ventana_eeprom_config *cfg = econfig;
 125
 126        while (cfg->name) {
 127                if (0 == strcmp(name, cfg->name))
 128                        return cfg;
 129                cfg++;
 130        }
 131        return NULL;
 132}
 133
 134static u8 econfig_bytes[sizeof(ventana_info.config)];
 135static int econfig_init = -1;
 136
 137static int do_econfig(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 138{
 139        struct ventana_eeprom_config *cfg;
 140        struct ventana_board_info *info = &ventana_info;
 141        int i;
 142
 143        if (argc < 2)
 144                return CMD_RET_USAGE;
 145
 146        /* initialize */
 147        if (econfig_init != 1) {
 148                memcpy(econfig_bytes, info->config, sizeof(econfig_bytes));
 149                econfig_init = 1;
 150        }
 151
 152        /* list configs */
 153        if ((strncmp(argv[1], "list", 4) == 0)) {
 154                cfg = econfig;
 155                while (cfg->name) {
 156                        printf("%s: %d\n", cfg->name,
 157                               test_bit(cfg->bit, econfig_bytes) ?  1 : 0);
 158                        cfg++;
 159                }
 160        }
 161
 162        /* save */
 163        else if ((strncmp(argv[1], "save", 4) == 0)) {
 164                unsigned char *buf = (unsigned char *)info;
 165                int chksum;
 166
 167                /* calculate new checksum */
 168                memcpy(info->config, econfig_bytes, sizeof(econfig_bytes));
 169                for (chksum = 0, i = 0; i < sizeof(*info)-2; i++)
 170                        chksum += buf[i];
 171                debug("old chksum:0x%04x\n",
 172                      (info->chksum[0] << 8) | info->chksum[1]);
 173                debug("new chksum:0x%04x\n", chksum);
 174                info->chksum[0] = chksum >> 8;
 175                info->chksum[1] = chksum & 0xff;
 176
 177                /* write new config data */
 178                if (gsc_i2c_write(GSC_EEPROM_ADDR, info->config - (u8 *)info,
 179                                  1, econfig_bytes, sizeof(econfig_bytes))) {
 180                        printf("EEPROM: Failed updating config\n");
 181                        return CMD_RET_FAILURE;
 182                }
 183
 184                /* write new config data */
 185                if (gsc_i2c_write(GSC_EEPROM_ADDR, info->chksum - (u8 *)info,
 186                                  1, info->chksum, 2)) {
 187                        printf("EEPROM: Failed updating checksum\n");
 188                        return CMD_RET_FAILURE;
 189                }
 190
 191                printf("Config saved to EEPROM\n");
 192        }
 193
 194        /* get config */
 195        else if (argc == 2) {
 196                cfg = get_config(argv[1]);
 197                if (cfg) {
 198                        printf("%s: %d\n", cfg->name,
 199                               test_bit(cfg->bit, econfig_bytes) ? 1 : 0);
 200                } else {
 201                        printf("invalid config: %s\n", argv[1]);
 202                        return CMD_RET_FAILURE;
 203                }
 204        }
 205
 206        /* set config */
 207        else if (argc == 3) {
 208                cfg = get_config(argv[1]);
 209                if (cfg) {
 210                        if (simple_strtol(argv[2], NULL, 10)) {
 211                                test_and_set_bit(cfg->bit, econfig_bytes);
 212                                printf("Enabled %s\n", cfg->name);
 213                        } else {
 214                                test_and_clear_bit(cfg->bit, econfig_bytes);
 215                                printf("Disabled %s\n", cfg->name);
 216                        }
 217                } else {
 218                        printf("invalid config: %s\n", argv[1]);
 219                        return CMD_RET_FAILURE;
 220                }
 221        }
 222
 223        else
 224                return CMD_RET_USAGE;
 225
 226        return CMD_RET_SUCCESS;
 227}
 228
 229U_BOOT_CMD(
 230        econfig, 3, 0, do_econfig,
 231        "EEPROM configuration",
 232        "list - list config\n"
 233        "save - save config to EEPROM\n"
 234        "<name> - get config 'name'\n"
 235        "<name> [0|1] - set config 'name' to value\n"
 236);
 237
 238#endif /* CONFIG_CMD_EECONFIG */
 239