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