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#ifdef CONFIG_SYS_EEPROM_BUS_NUM
  81        unsigned int bus = i2c_get_bus_num();
  82        i2c_set_bus_num(CONFIG_SYS_EEPROM_BUS_NUM);
  83#endif
  84
  85        memset(eeprom, 0, TRICORDER_EEPROM_SIZE);
  86
  87        i2c_read(addr, 0, 2, (unsigned char *)eeprom, TRICORDER_EEPROM_SIZE);
  88#ifdef CONFIG_SYS_EEPROM_BUS_NUM
  89        i2c_set_bus_num(bus);
  90#endif
  91
  92        if (be32_to_cpu(eeprom->magic) != TRICORDER_EEPROM_MAGIC) {
  93                warn_wrong_value("magic", TRICORDER_EEPROM_MAGIC,
  94                                 be32_to_cpu(eeprom->magic));
  95                return 1;
  96        }
  97
  98        switch (be16_to_cpu(eeprom->version)) {
  99        case 0:
 100                return handle_eeprom_v0(eeprom);
 101        case 1:
 102                return handle_eeprom_v1(eeprom);
 103        default:
 104                warn_wrong_value("version", TRICORDER_EEPROM_VERSION,
 105                                 be16_to_cpu(eeprom->version));
 106                return 1;
 107        }
 108}
 109
 110#if !defined(CONFIG_SPL)
 111int tricorder_eeprom_read(unsigned devaddr)
 112{
 113        struct tricorder_eeprom eeprom;
 114        int ret = tricorder_get_eeprom(devaddr, &eeprom);
 115
 116        if (ret)
 117                return ret;
 118
 119        printf("Board type:               %.*s\n",
 120               sizeof(eeprom.board_name), eeprom.board_name);
 121        printf("Board version:            %.*s\n",
 122               sizeof(eeprom.board_version), eeprom.board_version);
 123        printf("Board serial:             %.*s\n",
 124               sizeof(eeprom.board_serial), eeprom.board_serial);
 125        printf("Board interface version:  %.*s\n",
 126               sizeof(eeprom.interface_version),
 127               eeprom.interface_version);
 128
 129        return ret;
 130}
 131
 132int tricorder_eeprom_write(unsigned devaddr, const char *name,
 133                const char *version, const char *serial, const char *interface)
 134{
 135        struct tricorder_eeprom eeprom, eeprom_verify;
 136        size_t length;
 137        uint32_t crc;
 138        int ret;
 139        unsigned char *p;
 140        int i;
 141#ifdef CONFIG_SYS_EEPROM_BUS_NUM
 142        unsigned int bus;
 143#endif
 144
 145        memset(eeprom, 0, TRICORDER_EEPROM_SIZE);
 146        memset(eeprom_verify, 0, TRICORDER_EEPROM_SIZE);
 147
 148        eeprom.magic = cpu_to_be32(TRICORDER_EEPROM_MAGIC);
 149        eeprom.length = cpu_to_be16(TRICORDER_EEPROM_SIZE);
 150        eeprom.version = cpu_to_be16(TRICORDER_EEPROM_VERSION);
 151
 152        length = min(sizeof(eeprom.board_name), strlen(name));
 153        strncpy(eeprom.board_name, name, length);
 154
 155        length = min(sizeof(eeprom.board_version), strlen(version));
 156        strncpy(eeprom.board_version, version, length);
 157
 158        length = min(sizeof(eeprom.board_serial), strlen(serial));
 159        strncpy(eeprom.board_serial, serial, length);
 160
 161        if (interface) {
 162                length = min(sizeof(eeprom.interface_version),
 163                                strlen(interface));
 164                strncpy(eeprom.interface_version, interface, length);
 165        }
 166
 167        crc = crc32(0L, (unsigned char *)&eeprom, TRICORDER_EEPROM_CRC_SIZE);
 168        eeprom.crc32 = cpu_to_be32(crc);
 169
 170#if defined(DEBUG)
 171        puts("Tricorder EEPROM content:\n");
 172        print_buffer(0, &eeprom, 1, sizeof(eeprom), 16);
 173#endif
 174
 175#ifdef CONFIG_SYS_EEPROM_BUS_NUM
 176        bus = i2c_get_bus_num();
 177        i2c_set_bus_num(CONFIG_SYS_EEPROM_BUS_NUM);
 178#endif
 179
 180        /* do page write to the eeprom */
 181        for (i = 0, p = (unsigned char *)&eeprom;
 182             i < sizeof(eeprom);
 183             i += 32, p += 32) {
 184                ret = i2c_write(devaddr, i, CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
 185                                p, min(sizeof(eeprom) - i, 32));
 186                if (ret)
 187                        break;
 188                udelay(5000); /* 5ms write cycle timing */
 189        }
 190
 191        ret = i2c_read(devaddr, 0, 2, (unsigned char *)&eeprom_verify,
 192                        TRICORDER_EEPROM_SIZE);
 193
 194        if (memcmp(&eeprom, &eeprom_verify, sizeof(eeprom)) != 0) {
 195                printf("Tricorder: Could not verify EEPROM content!\n");
 196                ret = 1;
 197        }
 198
 199#ifdef CONFIG_SYS_EEPROM_BUS_NUM
 200        i2c_set_bus_num(bus);
 201#endif
 202        return ret;
 203}
 204
 205int do_tricorder_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 206{
 207        if (argc == 3) {
 208                ulong dev_addr = simple_strtoul(argv[2], NULL, 16);
 209                eeprom_init();
 210                if (strcmp(argv[1], "read") == 0) {
 211                        int rcode;
 212
 213                        rcode = tricorder_eeprom_read(dev_addr);
 214
 215                        return rcode;
 216                }
 217        } else if (argc == 6 || argc == 7) {
 218                ulong dev_addr = simple_strtoul(argv[2], NULL, 16);
 219                char *name = argv[3];
 220                char *version = argv[4];
 221                char *serial = argv[5];
 222                char *interface = NULL;
 223                eeprom_init();
 224
 225                if (argc == 7)
 226                        interface = argv[6];
 227
 228                if (strcmp(argv[1], "write") == 0) {
 229                        int rcode;
 230
 231                        rcode = tricorder_eeprom_write(dev_addr, name, version,
 232                                        serial, interface);
 233
 234                        return rcode;
 235                }
 236        }
 237
 238        return CMD_RET_USAGE;
 239}
 240
 241U_BOOT_CMD(
 242        tricordereeprom,        7,      1,      do_tricorder_eeprom,
 243        "Tricorder EEPROM",
 244        "read  devaddr\n"
 245        "       - read Tricorder EEPROM at devaddr and print content\n"
 246        "tricordereeprom write devaddr name version serial [interface]\n"
 247        "       - write Tricorder EEPROM at devaddr with 'name', 'version'"
 248        "and 'serial'\n"
 249        "         optional add an HW interface parameter"
 250);
 251#endif /* CONFIG_SPL */
 252