uboot/board/varisys/common/sys_eeprom.c
<<
>>
Prefs
   1/*
   2 * Based on board/freescale/common/sys_eeprom.c
   3 * Copyright 2006, 2008-2009, 2011 Freescale Semiconductor
   4 *
   5 * This defines the API for storing board information in the
   6 * eeprom. It has been adapted from an earlier version of the
   7 * Freescale API, but has a number of key differences. Because
   8 * the two APIs are independent and may diverge further, the
   9 * Varisys version of the API is implemented separately here.
  10 *
  11 * SPDX-License-Identifier:    GPL-2.0+
  12 */
  13
  14#include <common.h>
  15#include <command.h>
  16#include <i2c.h>
  17#include <linux/ctype.h>
  18
  19#include "eeprom.h"
  20
  21#ifdef CONFIG_SYS_I2C_EEPROM_NXID_MAC
  22#define MAX_NUM_PORTS   CONFIG_SYS_I2C_EEPROM_NXID_MAC
  23#else
  24#define MAX_NUM_PORTS   8
  25#endif
  26#define NXID_VERSION    0
  27
  28/**
  29 * static eeprom: EEPROM layout for NXID formats
  30 *
  31 * See Freescale application note AN3638 for details.
  32 */
  33static struct __attribute__ ((__packed__)) eeprom {
  34        u8 id[4];         /* 0x00 - 0x03 EEPROM Tag 'NXID' */
  35        u8 sn[12];        /* 0x04 - 0x0F Serial Number */
  36        u8 errata[5];     /* 0x10 - 0x14 Errata Level */
  37        u8 date[6];       /* 0x15 - 0x1a Build Date */
  38        u8 res_0;         /* 0x1b        Reserved */
  39        u32 version;      /* 0x1c - 0x1f NXID Version */
  40        u8 tempcal[8];    /* 0x20 - 0x27 Temperature Calibration Factors */
  41        u8 tempcalsys[2]; /* 0x28 - 0x29 System Temperature Calibration Factors */
  42        u8 tempcalflags;  /* 0x2a        Temperature Calibration Flags */
  43        u8 res_1[21];     /* 0x2b - 0x3f Reserved */
  44        u8 mac_count;     /* 0x40        Number of MAC addresses */
  45        u8 mac_flag;      /* 0x41        MAC table flags */
  46        u8 mac[MAX_NUM_PORTS][6];     /* 0x42 - x MAC addresses */
  47        u32 crc;          /* x+1         CRC32 checksum */
  48} e;
  49
  50/* Set to 1 if we've read EEPROM into memory */
  51static int has_been_read;
  52
  53/* Is this a valid NXID EEPROM? */
  54#define is_valid ((e.id[0] == 'N') || (e.id[1] == 'X') || \
  55                  (e.id[2] == 'I') || (e.id[3] == 'D'))
  56
  57/** Fixed ID field in EEPROM */
  58static unsigned char uid[16];
  59
  60static int eeprom_bus_num = -1;
  61static int eeprom_addr;
  62static int eeprom_addr_len;
  63
  64/**
  65 * This must be called before any eeprom access.
  66 */
  67void init_eeprom(int bus_num, int addr, int addr_len)
  68{
  69        eeprom_bus_num = bus_num;
  70        eeprom_addr = addr;
  71        eeprom_addr_len = addr_len;
  72}
  73
  74/**
  75 * show_eeprom - display the contents of the EEPROM
  76 */
  77void show_eeprom(void)
  78{
  79        int i;
  80        unsigned int crc;
  81
  82        /* EEPROM tag ID, either CCID or NXID */
  83        printf("ID: %c%c%c%c v%u\n", e.id[0], e.id[1], e.id[2], e.id[3],
  84                be32_to_cpu(e.version));
  85
  86        /* Serial number */
  87        printf("SN: %s\n", e.sn);
  88
  89        printf("UID: ");
  90        for (i = 0; i < 16; i++)
  91                printf("%02x", uid[i]);
  92        printf("\n");
  93
  94        /* Errata level. */
  95        printf("Errata: %s\n", e.errata);
  96
  97        /* Build date, BCD date values, as YYMMDDhhmmss */
  98        printf("Build date: 20%02x/%02x/%02x %02x:%02x:%02x %s\n",
  99                e.date[0], e.date[1], e.date[2],
 100                e.date[3] & 0x7F, e.date[4], e.date[5],
 101                e.date[3] & 0x80 ? "PM" : "");
 102
 103        /* Show MAC addresses  */
 104        for (i = 0; i < min(e.mac_count, (u8)MAX_NUM_PORTS); i++) {
 105                u8 *p = e.mac[i];
 106
 107                printf("Eth%u: %02x:%02x:%02x:%02x:%02x:%02x\n", i,
 108                       p[0], p[1], p[2], p[3], p[4], p[5]);
 109        }
 110
 111        crc = crc32(0, (void *)&e, sizeof(e) - 4);
 112
 113        if (crc == be32_to_cpu(e.crc))
 114                printf("CRC: %08x\n", be32_to_cpu(e.crc));
 115        else
 116                printf("CRC: %08x (should be %08x)\n",
 117                       be32_to_cpu(e.crc), crc);
 118
 119#ifdef DEBUG
 120        printf("EEPROM dump: (0x%x bytes)\n", sizeof(e));
 121        for (i = 0; i < sizeof(e); i++) {
 122                if ((i % 16) == 0)
 123                        printf("%02X: ", i);
 124                printf("%02X ", ((u8 *)&e)[i]);
 125                if (((i % 16) == 15) || (i == sizeof(e) - 1))
 126                        printf("\n");
 127        }
 128#endif
 129}
 130
 131/**
 132 * read_eeprom - read the EEPROM into memory
 133 */
 134int read_eeprom(void)
 135{
 136        int ret;
 137        unsigned int bus;
 138
 139        if (eeprom_bus_num < 0) {
 140                printf("EEPROM not configured\n");
 141                return -1;
 142        }
 143
 144        if (has_been_read)
 145                return 0;
 146
 147        bus = i2c_get_bus_num();
 148        i2c_set_bus_num(eeprom_bus_num);
 149
 150        ret = i2c_read(eeprom_addr, 0, eeprom_addr_len,
 151                (void *)&e, sizeof(e));
 152
 153
 154        /* Fixed address of ID field */
 155        i2c_read(0x5f, 0x80, 1, uid, 16);
 156
 157        i2c_set_bus_num(bus);
 158
 159#ifdef DEBUG
 160        show_eeprom();
 161#endif
 162
 163        has_been_read = (ret == 0) ? 1 : 0;
 164
 165        return ret;
 166}
 167
 168/**
 169 *  update_crc - update the CRC
 170 *
 171 *  This function should be called after each update to the EEPROM structure,
 172 *  to make sure the CRC is always correct.
 173 */
 174static void update_crc(void)
 175{
 176        u32 crc, crc_offset = offsetof(struct eeprom, crc);
 177
 178        crc = crc32(0, (void *)&e, crc_offset);
 179        e.crc = cpu_to_be32(crc);
 180}
 181
 182/**
 183 * prog_eeprom - write the EEPROM from memory
 184 */
 185static int prog_eeprom(void)
 186{
 187        int ret = 0;
 188        int i;
 189        void *p;
 190        unsigned int bus;
 191
 192        if (eeprom_bus_num < 0) {
 193                printf("EEPROM not configured\n");
 194                return -1;
 195        }
 196
 197        /* Set the reserved values to 0xFF   */
 198        e.res_0 = 0xFF;
 199        memset(e.res_1, 0xFF, sizeof(e.res_1));
 200        update_crc();
 201
 202        bus = i2c_get_bus_num();
 203        i2c_set_bus_num(eeprom_bus_num);
 204
 205        /*
 206         * The AT24C02 datasheet says that data can only be written in page
 207         * mode, which means 8 bytes at a time, and it takes up to 5ms to
 208         * complete a given write.
 209         */
 210        for (i = 0, p = &e; i < sizeof(e); i += 8, p += 8) {
 211                ret = i2c_write(eeprom_addr, i, eeprom_addr_len,
 212                        p, min((int)(sizeof(e) - i), 8));
 213                if (ret)
 214                        break;
 215                udelay(5000);   /* 5ms write cycle timing */
 216        }
 217
 218        if (!ret) {
 219                /* Verify the write by reading back the EEPROM and comparing */
 220                struct eeprom e2;
 221
 222                ret = i2c_read(eeprom_addr, 0,
 223                        eeprom_addr_len, (void *)&e2, sizeof(e2));
 224                if (!ret && memcmp(&e, &e2, sizeof(e)))
 225                        ret = -1;
 226        }
 227
 228        i2c_set_bus_num(bus);
 229
 230        if (ret) {
 231                printf("Programming failed.\n");
 232                has_been_read = 0;
 233                return -1;
 234        }
 235
 236        printf("Programming passed.\n");
 237        return 0;
 238}
 239
 240/**
 241 * h2i - converts hex character into a number
 242 *
 243 * This function takes a hexadecimal character (e.g. '7' or 'C') and returns
 244 * the integer equivalent.
 245 */
 246static inline u8 h2i(char p)
 247{
 248        if ((p >= '0') && (p <= '9'))
 249                return p - '0';
 250
 251        if ((p >= 'A') && (p <= 'F'))
 252                return (p - 'A') + 10;
 253
 254        if ((p >= 'a') && (p <= 'f'))
 255                return (p - 'a') + 10;
 256
 257        return 0;
 258}
 259
 260/**
 261 * set_date - stores the build date into the EEPROM
 262 *
 263 * This function takes a pointer to a string in the format "YYMMDDhhmmss"
 264 * (2-digit year, 2-digit month, etc), converts it to a 6-byte BCD string,
 265 * and stores it in the build date field of the EEPROM local copy.
 266 */
 267static void set_date(const char *string)
 268{
 269        unsigned int i;
 270
 271        if (strlen(string) != 12) {
 272                printf("Usage: mac date YYMMDDhhmmss\n");
 273                return;
 274        }
 275
 276        for (i = 0; i < 6; i++)
 277                e.date[i] = h2i(string[2 * i]) << 4 | h2i(string[2 * i + 1]);
 278
 279        update_crc();
 280}
 281
 282/**
 283 * set_mac_address - stores a MAC address into the EEPROM
 284 *
 285 * This function takes a pointer to MAC address string
 286 * (i.e."XX:XX:XX:XX:XX:XX", where "XX" is a two-digit hex number) and
 287 * stores it in one of the MAC address fields of the EEPROM local copy.
 288 */
 289static void set_mac_address(unsigned int index, const char *string)
 290{
 291        char *p = (char *)string;
 292        unsigned int i;
 293
 294        if ((index >= MAX_NUM_PORTS) || !string) {
 295                printf("Usage: mac <n> XX:XX:XX:XX:XX:XX\n");
 296                return;
 297        }
 298
 299        for (i = 0; *p && (i < 6); i++) {
 300                e.mac[index][i] = simple_strtoul(p, &p, 16);
 301                if (*p == ':')
 302                        p++;
 303        }
 304
 305        update_crc();
 306}
 307
 308int do_mac(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 309{
 310        char cmd;
 311
 312        if (argc == 1) {
 313                show_eeprom();
 314                return 0;
 315        }
 316
 317        cmd = argv[1][0];
 318
 319        if (cmd == 'r') {
 320                read_eeprom();
 321                return 0;
 322        }
 323
 324        if (cmd == 'i') {
 325                memcpy(e.id, "NXID", sizeof(e.id));
 326                e.version = NXID_VERSION;
 327                update_crc();
 328                return 0;
 329        }
 330
 331        if (!is_valid) {
 332                printf("Please read the EEPROM ('r') and/or set the ID ('i') first.\n");
 333                return 0;
 334        }
 335
 336        if (argc == 2) {
 337                switch (cmd) {
 338                case 's':       /* save */
 339                        prog_eeprom();
 340                        break;
 341                default:
 342                        return cmd_usage(cmdtp);
 343                }
 344
 345                return 0;
 346        }
 347
 348        /* We know we have at least one parameter  */
 349
 350        switch (cmd) {
 351        case 'n':       /* serial number */
 352                memset(e.sn, 0, sizeof(e.sn));
 353                strncpy((char *)e.sn, argv[2], sizeof(e.sn) - 1);
 354                update_crc();
 355                break;
 356        case 'e':       /* errata */
 357                memset(e.errata, 0, 5);
 358                strncpy((char *)e.errata, argv[2], 4);
 359                update_crc();
 360                break;
 361        case 'd':       /* date BCD format YYMMDDhhmmss */
 362                set_date(argv[2]);
 363                break;
 364        case 'p':       /* MAC table size */
 365                e.mac_count = simple_strtoul(argv[2], NULL, 16);
 366                update_crc();
 367                break;
 368        case '0' ... '9':       /* "mac 0" through "mac 22" */
 369                set_mac_address(simple_strtoul(argv[1], NULL, 10), argv[2]);
 370                break;
 371        case 'h':       /* help */
 372        default:
 373                return cmd_usage(cmdtp);
 374        }
 375
 376        return 0;
 377}
 378
 379int mac_read_from_generic_eeprom(const char *envvar, int chip,
 380        int address, int mac_bus)
 381{
 382        int ret;
 383        unsigned int bus;
 384        unsigned char mac[6];
 385        char ethaddr[18];
 386
 387        bus = i2c_get_bus_num();
 388        i2c_set_bus_num(mac_bus);
 389
 390        ret = i2c_read(chip, address, 1, mac, 6);
 391
 392        i2c_set_bus_num(bus);
 393
 394        if (!ret) {
 395                sprintf(ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X",
 396                        mac[0],
 397                        mac[1],
 398                        mac[2],
 399                        mac[3],
 400                        mac[4],
 401                        mac[5]);
 402
 403                printf("MAC: %s\n", ethaddr);
 404                setenv(envvar, ethaddr);
 405        }
 406
 407        return ret;
 408}
 409
 410void mac_read_from_fixed_id(void)
 411{
 412#ifdef CONFIG_SYS_I2C_MAC1_CHIP_ADDR
 413        mac_read_from_generic_eeprom("ethaddr", CONFIG_SYS_I2C_MAC1_CHIP_ADDR,
 414                CONFIG_SYS_I2C_MAC1_DATA_ADDR, CONFIG_SYS_I2C_MAC1_BUS);
 415#endif
 416#ifdef CONFIG_SYS_I2C_MAC2_CHIP_ADDR
 417        mac_read_from_generic_eeprom("eth1addr", CONFIG_SYS_I2C_MAC2_CHIP_ADDR,
 418                CONFIG_SYS_I2C_MAC2_DATA_ADDR, CONFIG_SYS_I2C_MAC2_BUS);
 419#endif
 420}
 421
 422/**
 423 * mac_read_from_eeprom - read the MAC addresses from EEPROM
 424 *
 425 * This function reads the MAC addresses from EEPROM and sets the
 426 * appropriate environment variables for each one read.
 427 *
 428 * The environment variables are only set if they haven't been set already.
 429 * This ensures that any user-saved variables are never overwritten.
 430 *
 431 * This function must be called after relocation.
 432 *
 433 * For NXID v1 EEPROMs, we support loading and up-converting the older NXID v0
 434 * format.  In a v0 EEPROM, there are only eight MAC addresses and the CRC is
 435 * located at a different offset.
 436 */
 437int mac_read_from_eeprom_common(void)
 438{
 439        unsigned int i;
 440        u32 crc, crc_offset = offsetof(struct eeprom, crc);
 441        u32 *crcp; /* Pointer to the CRC in the data read from the EEPROM */
 442
 443        puts("EEPROM: ");
 444
 445        if (read_eeprom()) {
 446                printf("Read failed.\n");
 447                return 0;
 448        }
 449
 450        if (!is_valid) {
 451                printf("Invalid ID (%02x %02x %02x %02x)\n",
 452                       e.id[0], e.id[1], e.id[2], e.id[3]);
 453                return 0;
 454        }
 455
 456        crc = crc32(0, (void *)&e, crc_offset);
 457        crcp = (void *)&e + crc_offset;
 458        if (crc != be32_to_cpu(*crcp)) {
 459                printf("CRC mismatch (%08x != %08x)\n", crc,
 460                        be32_to_cpu(e.crc));
 461                return 0;
 462        }
 463
 464        /*
 465         * MAC address #9 in v1 occupies the same position as the CRC in v0.
 466         * Erase it so that it's not mistaken for a MAC address.  We'll
 467         * update the CRC later.
 468         */
 469        if (e.version == 0)
 470                memset(e.mac[8], 0xff, 6);
 471
 472        for (i = 0; i < min(e.mac_count, (u8)MAX_NUM_PORTS); i++) {
 473                if (memcmp(&e.mac[i], "\0\0\0\0\0\0", 6) &&
 474                    memcmp(&e.mac[i], "\xFF\xFF\xFF\xFF\xFF\xFF", 6)) {
 475                        char ethaddr[18];
 476                        char enetvar[9];
 477
 478                        sprintf(ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X",
 479                                e.mac[i][0],
 480                                e.mac[i][1],
 481                                e.mac[i][2],
 482                                e.mac[i][3],
 483                                e.mac[i][4],
 484                                e.mac[i][5]);
 485                        sprintf(enetvar, i ? "eth%daddr" : "ethaddr", i);
 486                        /* Only initialize environment variables that are blank
 487                         * (i.e. have not yet been set)
 488                         */
 489                        if (!getenv(enetvar))
 490                                setenv(enetvar, ethaddr);
 491                }
 492        }
 493
 494        printf("%c%c%c%c v%u\n", e.id[0], e.id[1], e.id[2], e.id[3],
 495                be32_to_cpu(e.version));
 496
 497        return 0;
 498}
 499