uboot/board/corscience/tricorder/tricorder-eeprom.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2013
   3 * Corscience GmbH & Co. KG, <www.corscience.de>
   4 * Andreas Bießmann <andreas.biessmann@corscience.de>
   5 *
   6 * SPDX-License-Identifier:     GPL-2.0+
   7 */
   8#include <common.h>
   9#include <i2c.h>
  10
  11#include "tricorder-eeprom.h"
  12
  13static inline void warn_wrong_value(const char *msg, unsigned int a,
  14                unsigned int b)
  15{
  16        printf("Expected EEPROM %s %08x, got %08x\n", msg, a, b);
  17}
  18
  19static int handle_eeprom_v0(struct tricorder_eeprom *eeprom)
  20{
  21        struct tricorder_eeprom_v0 {
  22                uint32_t magic;
  23                uint16_t length;
  24                uint16_t version;
  25                char board_name[TRICORDER_BOARD_NAME_LENGTH];
  26                char board_version[TRICORDER_BOARD_VERSION_LENGTH];
  27                char board_serial[TRICORDER_BOARD_SERIAL_LENGTH];
  28                uint32_t crc32;
  29        } __packed eepromv0;
  30        uint32_t crc;
  31
  32        printf("Old EEPROM (v0), consider rewrite!\n");
  33
  34        if (be16_to_cpu(eeprom->length) != sizeof(eepromv0)) {
  35                warn_wrong_value("length", sizeof(eepromv0),
  36                                 be16_to_cpu(eeprom->length));
  37                return 1;
  38        }
  39
  40        memcpy(&eepromv0, eeprom, sizeof(eepromv0));
  41
  42        crc = crc32(0L, (unsigned char *)&eepromv0,
  43                    sizeof(eepromv0) - sizeof(eepromv0.crc32));
  44        if (be32_to_cpu(eepromv0.crc32) != crc) {
  45                warn_wrong_value("CRC", be32_to_cpu(eepromv0.crc32),
  46                                 crc);
  47                return 1;
  48        }
  49
  50        /* Ok the content is correct, do the conversion */
  51        memset(eeprom->interface_version, 0x0,
  52               TRICORDER_INTERFACE_VERSION_LENGTH);
  53        crc = crc32(0L, (unsigned char *)eeprom, TRICORDER_EEPROM_CRC_SIZE);
  54        eeprom->crc32 = cpu_to_be32(crc);
  55
  56        return 0;
  57}
  58
  59static int handle_eeprom_v1(struct tricorder_eeprom *eeprom)
  60{
  61        uint32_t crc;
  62
  63        if (be16_to_cpu(eeprom->length) != TRICORDER_EEPROM_SIZE) {
  64                warn_wrong_value("length", TRICORDER_EEPROM_SIZE,
  65                                 be16_to_cpu(eeprom->length));
  66                return 1;
  67        }
  68
  69        crc = crc32(0L, (unsigned char *)eeprom, TRICORDER_EEPROM_CRC_SIZE);
  70        if (be32_to_cpu(eeprom->crc32) != crc) {
  71                warn_wrong_value("CRC", be32_to_cpu(eeprom->crc32), crc);
  72                return 1;
  73        }
  74
  75        return 0;
  76}
  77
  78int tricorder_get_eeprom(int addr, struct tricorder_eeprom *eeprom)
  79{
  80        unsigned int bus = i2c_get_bus_num();
  81        i2c_set_bus_num(CONFIG_SYS_EEPROM_BUS_NUM);
  82
  83        memset(eeprom, 0, TRICORDER_EEPROM_SIZE);
  84
  85        i2c_read(addr, 0, 2, (unsigned char *)eeprom, TRICORDER_EEPROM_SIZE);
  86        i2c_set_bus_num(bus);
  87
  88        if (be32_to_cpu(eeprom->magic) != TRICORDER_EEPROM_MAGIC) {
  89                warn_wrong_value("magic", TRICORDER_EEPROM_MAGIC,
  90                                 be32_to_cpu(eeprom->magic));
  91                return 1;
  92        }
  93
  94        switch (be16_to_cpu(eeprom->version)) {
  95        case 0:
  96                return handle_eeprom_v0(eeprom);
  97        case 1:
  98                return handle_eeprom_v1(eeprom);
  99        default:
 100                warn_wrong_value("version", TRICORDER_EEPROM_VERSION,
 101                                 be16_to_cpu(eeprom->version));
 102                return 1;
 103        }
 104}
 105
 106#if !defined(CONFIG_SPL)
 107int tricorder_eeprom_read(unsigned devaddr)
 108{
 109        struct tricorder_eeprom eeprom;
 110        int ret = tricorder_get_eeprom(devaddr, &eeprom);
 111
 112        if (ret)
 113                return ret;
 114
 115        printf("Board type:               %.*s\n",
 116               sizeof(eeprom.board_name), eeprom.board_name);
 117        printf("Board version:            %.*s\n",
 118               sizeof(eeprom.board_version), eeprom.board_version);
 119        printf("Board serial:             %.*s\n",
 120               sizeof(eeprom.board_serial), eeprom.board_serial);
 121        printf("Board interface version:  %.*s\n",
 122               sizeof(eeprom.interface_version),
 123               eeprom.interface_version);
 124
 125        return ret;
 126}
 127
 128int tricorder_eeprom_write(unsigned devaddr, const char *name,
 129                const char *version, const char *serial, const char *interface)
 130{
 131        struct tricorder_eeprom eeprom, eeprom_verify;
 132        size_t length;
 133        uint32_t crc;
 134        int ret;
 135        unsigned char *p;
 136        int i;
 137
 138        memset(eeprom, 0, TRICORDER_EEPROM_SIZE);
 139        memset(eeprom_verify, 0, TRICORDER_EEPROM_SIZE);
 140
 141        eeprom.magic = cpu_to_be32(TRICORDER_EEPROM_MAGIC);
 142        eeprom.length = cpu_to_be16(TRICORDER_EEPROM_SIZE);
 143        eeprom.version = cpu_to_be16(TRICORDER_EEPROM_VERSION);
 144
 145        length = min(sizeof(eeprom.board_name), strlen(name));
 146        strncpy(eeprom.board_name, name, length);
 147
 148        length = min(sizeof(eeprom.board_version), strlen(version));
 149        strncpy(eeprom.board_version, version, length);
 150
 151        length = min(sizeof(eeprom.board_serial), strlen(serial));
 152        strncpy(eeprom.board_serial, serial, length);
 153
 154        if (interface) {
 155                length = min(sizeof(eeprom.interface_version),
 156                                strlen(interface));
 157                strncpy(eeprom.interface_version, interface, length);
 158        }
 159
 160        crc = crc32(0L, (unsigned char *)&eeprom, TRICORDER_EEPROM_CRC_SIZE);
 161        eeprom.crc32 = cpu_to_be32(crc);
 162
 163#if defined(DEBUG)
 164        puts("Tricorder EEPROM content:\n");
 165        print_buffer(0, &eeprom, 1, sizeof(eeprom), 16);
 166#endif
 167
 168        eeprom_init(CONFIG_SYS_EEPROM_BUS_NUM);
 169
 170        ret = eeprom_write(devaddr, 0, (unsigned char *)&eeprom,
 171                        TRICORDER_EEPROM_SIZE);
 172        if (ret)
 173                printf("Tricorder: Could not write EEPROM content!\n");
 174
 175        ret = eeprom_read(devaddr, 0, (unsigned char *)&eeprom_verify,
 176                        TRICORDER_EEPROM_SIZE);
 177        if (ret)
 178                printf("Tricorder: Could not read EEPROM content!\n");
 179
 180        if (memcmp(&eeprom, &eeprom_verify, sizeof(eeprom)) != 0) {
 181                printf("Tricorder: Could not verify EEPROM content!\n");
 182                ret = 1;
 183        }
 184
 185        return ret;
 186}
 187
 188int do_tricorder_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 189{
 190        if (argc == 3) {
 191                ulong dev_addr = simple_strtoul(argv[2], NULL, 16);
 192
 193                if (strcmp(argv[1], "read") == 0) {
 194                        int rcode;
 195
 196                        rcode = tricorder_eeprom_read(dev_addr);
 197
 198                        return rcode;
 199                }
 200        } else if (argc == 6 || argc == 7) {
 201                ulong dev_addr = simple_strtoul(argv[2], NULL, 16);
 202                char *name = argv[3];
 203                char *version = argv[4];
 204                char *serial = argv[5];
 205                char *interface = NULL;
 206
 207                if (argc == 7)
 208                        interface = argv[6];
 209
 210                if (strcmp(argv[1], "write") == 0) {
 211                        int rcode;
 212
 213                        rcode = tricorder_eeprom_write(dev_addr, name, version,
 214                                        serial, interface);
 215
 216                        return rcode;
 217                }
 218        }
 219
 220        return CMD_RET_USAGE;
 221}
 222
 223U_BOOT_CMD(
 224        tricordereeprom,        7,      1,      do_tricorder_eeprom,
 225        "Tricorder EEPROM",
 226        "read  devaddr\n"
 227        "       - read Tricorder EEPROM at devaddr and print content\n"
 228        "tricordereeprom write devaddr name version serial [interface]\n"
 229        "       - write Tricorder EEPROM at devaddr with 'name', 'version'"
 230        "and 'serial'\n"
 231        "         optional add an HW interface parameter"
 232);
 233#endif /* CONFIG_SPL */
 234