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