14ce91774SJon Loeliger /* 2f098c9c8STimur Tabi * Copyright 2006, 2008-2009, 2011 Freescale Semiconductor 34ce91774SJon Loeliger * York Sun (yorksun@freescale.com) 44ce91774SJon Loeliger * Haiying Wang (haiying.wang@freescale.com) 5e2d31fb3STimur Tabi * Timur Tabi (timur@freescale.com) 64ce91774SJon Loeliger * 71a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 84ce91774SJon Loeliger */ 94ce91774SJon Loeliger 104ce91774SJon Loeliger #include <common.h> 114ce91774SJon Loeliger #include <command.h> 124ce91774SJon Loeliger #include <i2c.h> 134ce91774SJon Loeliger #include <linux/ctype.h> 144ce91774SJon Loeliger 15bfb70719STimur Tabi #ifdef CONFIG_SYS_I2C_EEPROM_CCID 16e2d31fb3STimur Tabi #include "../common/eeprom.h" 17bfb70719STimur Tabi #define MAX_NUM_PORTS 8 18e2d31fb3STimur Tabi #endif 194ce91774SJon Loeliger 20bfb70719STimur Tabi #ifdef CONFIG_SYS_I2C_EEPROM_NXID 21*5536aeb0SShengzhou Liu /* some boards with non-256-bytes EEPROM have special define */ 22*5536aeb0SShengzhou Liu /* for MAX_NUM_PORTS in board-specific file */ 23*5536aeb0SShengzhou Liu #ifndef MAX_NUM_PORTS 24bfb70719STimur Tabi #define MAX_NUM_PORTS 23 25*5536aeb0SShengzhou Liu #endif 26bfb70719STimur Tabi #define NXID_VERSION 1 27bfb70719STimur Tabi #endif 289a611089SHaiying Wang 29e2d31fb3STimur Tabi /** 30e2d31fb3STimur Tabi * static eeprom: EEPROM layout for CCID or NXID formats 31e2d31fb3STimur Tabi * 32e2d31fb3STimur Tabi * See application note AN3638 for details. 33e2d31fb3STimur Tabi */ 34e2d31fb3STimur Tabi static struct __attribute__ ((__packed__)) eeprom { 356d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_I2C_EEPROM_CCID 36e2d31fb3STimur Tabi u8 id[4]; /* 0x00 - 0x03 EEPROM Tag 'CCID' */ 37e2d31fb3STimur Tabi u8 major; /* 0x04 Board revision, major */ 38e2d31fb3STimur Tabi u8 minor; /* 0x05 Board revision, minor */ 39e2d31fb3STimur Tabi u8 sn[10]; /* 0x06 - 0x0F Serial Number*/ 40e2d31fb3STimur Tabi u8 errata[2]; /* 0x10 - 0x11 Errata Level */ 41e2d31fb3STimur Tabi u8 date[6]; /* 0x12 - 0x17 Build Date */ 42e2d31fb3STimur Tabi u8 res_0[40]; /* 0x18 - 0x3f Reserved */ 43e2d31fb3STimur Tabi u8 mac_count; /* 0x40 Number of MAC addresses */ 44e2d31fb3STimur Tabi u8 mac_flag; /* 0x41 MAC table flags */ 459a611089SHaiying Wang u8 mac[MAX_NUM_PORTS][6]; /* 0x42 - 0x71 MAC addresses */ 46e2d31fb3STimur Tabi u32 crc; /* 0x72 CRC32 checksum */ 47e2d31fb3STimur Tabi #endif 486d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_I2C_EEPROM_NXID 49e2d31fb3STimur Tabi u8 id[4]; /* 0x00 - 0x03 EEPROM Tag 'NXID' */ 50e2d31fb3STimur Tabi u8 sn[12]; /* 0x04 - 0x0F Serial Number */ 51e2d31fb3STimur Tabi u8 errata[5]; /* 0x10 - 0x14 Errata Level */ 52e2d31fb3STimur Tabi u8 date[6]; /* 0x15 - 0x1a Build Date */ 53e2d31fb3STimur Tabi u8 res_0; /* 0x1b Reserved */ 54e2d31fb3STimur Tabi u32 version; /* 0x1c - 0x1f NXID Version */ 55e2d31fb3STimur Tabi u8 tempcal[8]; /* 0x20 - 0x27 Temperature Calibration Factors */ 56e2d31fb3STimur Tabi u8 tempcalsys[2]; /* 0x28 - 0x29 System Temperature Calibration Factors */ 57e2d31fb3STimur Tabi u8 tempcalflags; /* 0x2a Temperature Calibration Flags */ 58e2d31fb3STimur Tabi u8 res_1[21]; /* 0x2b - 0x3f Reserved */ 59e2d31fb3STimur Tabi u8 mac_count; /* 0x40 Number of MAC addresses */ 60e2d31fb3STimur Tabi u8 mac_flag; /* 0x41 MAC table flags */ 61bfb70719STimur Tabi u8 mac[MAX_NUM_PORTS][6]; /* 0x42 - x MAC addresses */ 62bfb70719STimur Tabi u32 crc; /* x+1 CRC32 checksum */ 63e2d31fb3STimur Tabi #endif 64e2d31fb3STimur Tabi } e; 65e2d31fb3STimur Tabi 66e2d31fb3STimur Tabi /* Set to 1 if we've read EEPROM into memory */ 67e2d31fb3STimur Tabi static int has_been_read = 0; 68e2d31fb3STimur Tabi 696d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_I2C_EEPROM_NXID 70e2d31fb3STimur Tabi /* Is this a valid NXID EEPROM? */ 71afb0b131SKumar Gala #define is_valid ((e.id[0] == 'N') || (e.id[1] == 'X') || \ 72afb0b131SKumar Gala (e.id[2] == 'I') || (e.id[3] == 'D')) 73e2d31fb3STimur Tabi #endif 74e2d31fb3STimur Tabi 756d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_I2C_EEPROM_CCID 76e2d31fb3STimur Tabi /* Is this a valid CCID EEPROM? */ 77afb0b131SKumar Gala #define is_valid ((e.id[0] == 'C') || (e.id[1] == 'C') || \ 78afb0b131SKumar Gala (e.id[2] == 'I') || (e.id[3] == 'D')) 79e2d31fb3STimur Tabi #endif 80e2d31fb3STimur Tabi 81e2d31fb3STimur Tabi /** 82e2d31fb3STimur Tabi * show_eeprom - display the contents of the EEPROM 83e2d31fb3STimur Tabi */ 84e2d31fb3STimur Tabi static void show_eeprom(void) 854ce91774SJon Loeliger { 864ce91774SJon Loeliger int i; 87e2d31fb3STimur Tabi unsigned int crc; 884ce91774SJon Loeliger 89e2d31fb3STimur Tabi /* EEPROM tag ID, either CCID or NXID */ 906d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_I2C_EEPROM_NXID 91e2d31fb3STimur Tabi printf("ID: %c%c%c%c v%u\n", e.id[0], e.id[1], e.id[2], e.id[3], 92e2d31fb3STimur Tabi be32_to_cpu(e.version)); 93e2d31fb3STimur Tabi #else 94e2d31fb3STimur Tabi printf("ID: %c%c%c%c\n", e.id[0], e.id[1], e.id[2], e.id[3]); 95e2d31fb3STimur Tabi #endif 96d59feffbSHaiying Wang 97e2d31fb3STimur Tabi /* Serial number */ 98e2d31fb3STimur Tabi printf("SN: %s\n", e.sn); 99d59feffbSHaiying Wang 100e2d31fb3STimur Tabi /* Errata level. */ 1016d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_I2C_EEPROM_NXID 102e2d31fb3STimur Tabi printf("Errata: %s\n", e.errata); 103e2d31fb3STimur Tabi #else 104e2d31fb3STimur Tabi printf("Errata: %c%c\n", 105e2d31fb3STimur Tabi e.errata[0] ? e.errata[0] : '.', 106e2d31fb3STimur Tabi e.errata[1] ? e.errata[1] : '.'); 107e2d31fb3STimur Tabi #endif 108d59feffbSHaiying Wang 109e2d31fb3STimur Tabi /* Build date, BCD date values, as YYMMDDhhmmss */ 110e2d31fb3STimur Tabi printf("Build date: 20%02x/%02x/%02x %02x:%02x:%02x %s\n", 111e2d31fb3STimur Tabi e.date[0], e.date[1], e.date[2], 112e2d31fb3STimur Tabi e.date[3] & 0x7F, e.date[4], e.date[5], 113e2d31fb3STimur Tabi e.date[3] & 0x80 ? "PM" : ""); 114d59feffbSHaiying Wang 115e2d31fb3STimur Tabi /* Show MAC addresses */ 1169a611089SHaiying Wang for (i = 0; i < min(e.mac_count, MAX_NUM_PORTS); i++) { 1179a611089SHaiying Wang 118e2d31fb3STimur Tabi u8 *p = e.mac[i]; 119e2d31fb3STimur Tabi 120e2d31fb3STimur Tabi printf("Eth%u: %02x:%02x:%02x:%02x:%02x:%02x\n", i, 121e2d31fb3STimur Tabi p[0], p[1], p[2], p[3], p[4], p[5]); 122e2d31fb3STimur Tabi } 123e2d31fb3STimur Tabi 124e2d31fb3STimur Tabi crc = crc32(0, (void *)&e, sizeof(e) - 4); 125e2d31fb3STimur Tabi 126e2d31fb3STimur Tabi if (crc == be32_to_cpu(e.crc)) 127e2d31fb3STimur Tabi printf("CRC: %08x\n", be32_to_cpu(e.crc)); 128d59feffbSHaiying Wang else 129e2d31fb3STimur Tabi printf("CRC: %08x (should be %08x)\n", 130e2d31fb3STimur Tabi be32_to_cpu(e.crc), crc); 131d59feffbSHaiying Wang 132e2d31fb3STimur Tabi #ifdef DEBUG 133e2d31fb3STimur Tabi printf("EEPROM dump: (0x%x bytes)\n", sizeof(e)); 134e2d31fb3STimur Tabi for (i = 0; i < sizeof(e); i++) { 135e2d31fb3STimur Tabi if ((i % 16) == 0) 136e2d31fb3STimur Tabi printf("%02X: ", i); 137e2d31fb3STimur Tabi printf("%02X ", ((u8 *)&e)[i]); 138e2d31fb3STimur Tabi if (((i % 16) == 15) || (i == sizeof(e) - 1)) 139e2d31fb3STimur Tabi printf("\n"); 140e2d31fb3STimur Tabi } 141e2d31fb3STimur Tabi #endif 142d59feffbSHaiying Wang } 1434ce91774SJon Loeliger 144e2d31fb3STimur Tabi /** 145e2d31fb3STimur Tabi * read_eeprom - read the EEPROM into memory 146e2d31fb3STimur Tabi */ 147e2d31fb3STimur Tabi static int read_eeprom(void) 1484ce91774SJon Loeliger { 149e2d31fb3STimur Tabi int ret; 1506d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_EEPROM_BUS_NUM 151e2d31fb3STimur Tabi unsigned int bus; 152e2d31fb3STimur Tabi #endif 1534ce91774SJon Loeliger 154e2d31fb3STimur Tabi if (has_been_read) 1554ce91774SJon Loeliger return 0; 156e2d31fb3STimur Tabi 1576d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_EEPROM_BUS_NUM 158e2d31fb3STimur Tabi bus = i2c_get_bus_num(); 1596d0f6bcfSJean-Christophe PLAGNIOL-VILLARD i2c_set_bus_num(CONFIG_SYS_EEPROM_BUS_NUM); 160e2d31fb3STimur Tabi #endif 161e2d31fb3STimur Tabi 1626d0f6bcfSJean-Christophe PLAGNIOL-VILLARD ret = i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0, CONFIG_SYS_I2C_EEPROM_ADDR_LEN, 163e2d31fb3STimur Tabi (void *)&e, sizeof(e)); 164e2d31fb3STimur Tabi 1656d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_EEPROM_BUS_NUM 166e2d31fb3STimur Tabi i2c_set_bus_num(bus); 167e2d31fb3STimur Tabi #endif 168e2d31fb3STimur Tabi 169e2d31fb3STimur Tabi #ifdef DEBUG 170e2d31fb3STimur Tabi show_eeprom(); 171e2d31fb3STimur Tabi #endif 172e2d31fb3STimur Tabi 173e2d31fb3STimur Tabi has_been_read = (ret == 0) ? 1 : 0; 174e2d31fb3STimur Tabi 175e2d31fb3STimur Tabi return ret; 1764ce91774SJon Loeliger } 1774ce91774SJon Loeliger 178e2d31fb3STimur Tabi /** 1792d04db08STimur Tabi * update_crc - update the CRC 1802d04db08STimur Tabi * 1812d04db08STimur Tabi * This function should be called after each update to the EEPROM structure, 1822d04db08STimur Tabi * to make sure the CRC is always correct. 1832d04db08STimur Tabi */ 1842d04db08STimur Tabi static void update_crc(void) 1852d04db08STimur Tabi { 1862d04db08STimur Tabi u32 crc; 1872d04db08STimur Tabi 1882d04db08STimur Tabi crc = crc32(0, (void *)&e, sizeof(e) - 4); 1892d04db08STimur Tabi e.crc = cpu_to_be32(crc); 1902d04db08STimur Tabi } 1912d04db08STimur Tabi 1922d04db08STimur Tabi /** 193e2d31fb3STimur Tabi * prog_eeprom - write the EEPROM from memory 194e2d31fb3STimur Tabi */ 195e2d31fb3STimur Tabi static int prog_eeprom(void) 1964ce91774SJon Loeliger { 1973addcb93STimur Tabi int ret = 0; 1989c671e70SAnton Vorontsov int i; 199e2d31fb3STimur Tabi void *p; 2006d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_EEPROM_BUS_NUM 201e2d31fb3STimur Tabi unsigned int bus; 202e2d31fb3STimur Tabi #endif 2034ce91774SJon Loeliger 204e2d31fb3STimur Tabi /* Set the reserved values to 0xFF */ 2056d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_I2C_EEPROM_NXID 206e2d31fb3STimur Tabi e.res_0 = 0xFF; 207e2d31fb3STimur Tabi memset(e.res_1, 0xFF, sizeof(e.res_1)); 208e2d31fb3STimur Tabi #else 209e2d31fb3STimur Tabi memset(e.res_0, 0xFF, sizeof(e.res_0)); 210e2d31fb3STimur Tabi #endif 2112d04db08STimur Tabi update_crc(); 212e2d31fb3STimur Tabi 2136d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_EEPROM_BUS_NUM 214e2d31fb3STimur Tabi bus = i2c_get_bus_num(); 2156d0f6bcfSJean-Christophe PLAGNIOL-VILLARD i2c_set_bus_num(CONFIG_SYS_EEPROM_BUS_NUM); 216e2d31fb3STimur Tabi #endif 217e2d31fb3STimur Tabi 2183addcb93STimur Tabi /* 2193addcb93STimur Tabi * The AT24C02 datasheet says that data can only be written in page 2203addcb93STimur Tabi * mode, which means 8 bytes at a time, and it takes up to 5ms to 2213addcb93STimur Tabi * complete a given write. 2223addcb93STimur Tabi */ 2232d04db08STimur Tabi for (i = 0, p = &e; i < sizeof(e); i += 8, p += 8) { 2246d0f6bcfSJean-Christophe PLAGNIOL-VILLARD ret = i2c_write(CONFIG_SYS_I2C_EEPROM_ADDR, i, CONFIG_SYS_I2C_EEPROM_ADDR_LEN, 2252d04db08STimur Tabi p, min((sizeof(e) - i), 8)); 2264ce91774SJon Loeliger if (ret) 2274ce91774SJon Loeliger break; 228e2d31fb3STimur Tabi udelay(5000); /* 5ms write cycle timing */ 2294ce91774SJon Loeliger } 230e2d31fb3STimur Tabi 2313addcb93STimur Tabi if (!ret) { 2323addcb93STimur Tabi /* Verify the write by reading back the EEPROM and comparing */ 2333addcb93STimur Tabi struct eeprom e2; 2343addcb93STimur Tabi 2353addcb93STimur Tabi ret = i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0, 2363addcb93STimur Tabi CONFIG_SYS_I2C_EEPROM_ADDR_LEN, (void *)&e2, sizeof(e2)); 2373addcb93STimur Tabi if (!ret && memcmp(&e, &e2, sizeof(e))) 2383addcb93STimur Tabi ret = -1; 2393addcb93STimur Tabi } 2403addcb93STimur Tabi 2416d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_EEPROM_BUS_NUM 242e2d31fb3STimur Tabi i2c_set_bus_num(bus); 243e2d31fb3STimur Tabi #endif 244e2d31fb3STimur Tabi 2454ce91774SJon Loeliger if (ret) { 2464ce91774SJon Loeliger printf("Programming failed.\n"); 2473addcb93STimur Tabi has_been_read = 0; 2484ce91774SJon Loeliger return -1; 2494ce91774SJon Loeliger } 250e2d31fb3STimur Tabi 251e2d31fb3STimur Tabi printf("Programming passed.\n"); 2524ce91774SJon Loeliger return 0; 2534ce91774SJon Loeliger } 2544ce91774SJon Loeliger 255e2d31fb3STimur Tabi /** 256e2d31fb3STimur Tabi * h2i - converts hex character into a number 257e2d31fb3STimur Tabi * 258e2d31fb3STimur Tabi * This function takes a hexadecimal character (e.g. '7' or 'C') and returns 259e2d31fb3STimur Tabi * the integer equivalent. 260e2d31fb3STimur Tabi */ 261e2d31fb3STimur Tabi static inline u8 h2i(char p) 262e2d31fb3STimur Tabi { 263e2d31fb3STimur Tabi if ((p >= '0') && (p <= '9')) 264e2d31fb3STimur Tabi return p - '0'; 265e2d31fb3STimur Tabi 266e2d31fb3STimur Tabi if ((p >= 'A') && (p <= 'F')) 267e2d31fb3STimur Tabi return (p - 'A') + 10; 268e2d31fb3STimur Tabi 269e2d31fb3STimur Tabi if ((p >= 'a') && (p <= 'f')) 270e2d31fb3STimur Tabi return (p - 'a') + 10; 271e2d31fb3STimur Tabi 272e2d31fb3STimur Tabi return 0; 273e2d31fb3STimur Tabi } 274e2d31fb3STimur Tabi 275e2d31fb3STimur Tabi /** 276e2d31fb3STimur Tabi * set_date - stores the build date into the EEPROM 277e2d31fb3STimur Tabi * 278e2d31fb3STimur Tabi * This function takes a pointer to a string in the format "YYMMDDhhmmss" 279e2d31fb3STimur Tabi * (2-digit year, 2-digit month, etc), converts it to a 6-byte BCD string, 280e2d31fb3STimur Tabi * and stores it in the build date field of the EEPROM local copy. 281e2d31fb3STimur Tabi */ 282e2d31fb3STimur Tabi static void set_date(const char *string) 283e2d31fb3STimur Tabi { 284e2d31fb3STimur Tabi unsigned int i; 285e2d31fb3STimur Tabi 286e2d31fb3STimur Tabi if (strlen(string) != 12) { 287e2d31fb3STimur Tabi printf("Usage: mac date YYMMDDhhmmss\n"); 288e2d31fb3STimur Tabi return; 289e2d31fb3STimur Tabi } 290e2d31fb3STimur Tabi 291e2d31fb3STimur Tabi for (i = 0; i < 6; i++) 292e2d31fb3STimur Tabi e.date[i] = h2i(string[2 * i]) << 4 | h2i(string[2 * i + 1]); 2932d04db08STimur Tabi 2942d04db08STimur Tabi update_crc(); 295e2d31fb3STimur Tabi } 296e2d31fb3STimur Tabi 297e2d31fb3STimur Tabi /** 298e2d31fb3STimur Tabi * set_mac_address - stores a MAC address into the EEPROM 299e2d31fb3STimur Tabi * 300e2d31fb3STimur Tabi * This function takes a pointer to MAC address string 301e2d31fb3STimur Tabi * (i.e."XX:XX:XX:XX:XX:XX", where "XX" is a two-digit hex number) and 302e2d31fb3STimur Tabi * stores it in one of the MAC address fields of the EEPROM local copy. 303e2d31fb3STimur Tabi */ 304e2d31fb3STimur Tabi static void set_mac_address(unsigned int index, const char *string) 305e2d31fb3STimur Tabi { 306e2d31fb3STimur Tabi char *p = (char *) string; 307e2d31fb3STimur Tabi unsigned int i; 308e2d31fb3STimur Tabi 309bfb70719STimur Tabi if ((index >= MAX_NUM_PORTS) || !string) { 310e2d31fb3STimur Tabi printf("Usage: mac <n> XX:XX:XX:XX:XX:XX\n"); 311e2d31fb3STimur Tabi return; 312e2d31fb3STimur Tabi } 313e2d31fb3STimur Tabi 314e2d31fb3STimur Tabi for (i = 0; *p && (i < 6); i++) { 315e2d31fb3STimur Tabi e.mac[index][i] = simple_strtoul(p, &p, 16); 316e2d31fb3STimur Tabi if (*p == ':') 317e2d31fb3STimur Tabi p++; 318e2d31fb3STimur Tabi } 3192d04db08STimur Tabi 3202d04db08STimur Tabi update_crc(); 321e2d31fb3STimur Tabi } 322e2d31fb3STimur Tabi 32354841ab5SWolfgang Denk int do_mac(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 3244ce91774SJon Loeliger { 325e2d31fb3STimur Tabi char cmd; 3264ce91774SJon Loeliger 327e2d31fb3STimur Tabi if (argc == 1) { 328e2d31fb3STimur Tabi show_eeprom(); 329e2d31fb3STimur Tabi return 0; 330e2d31fb3STimur Tabi } 3314ce91774SJon Loeliger 3324ce91774SJon Loeliger cmd = argv[1][0]; 333e2d31fb3STimur Tabi 334e2d31fb3STimur Tabi if (cmd == 'r') { 335e2d31fb3STimur Tabi read_eeprom(); 336e2d31fb3STimur Tabi return 0; 337e2d31fb3STimur Tabi } 338e2d31fb3STimur Tabi 3392d04db08STimur Tabi if (cmd == 'i') { 3402d04db08STimur Tabi #ifdef CONFIG_SYS_I2C_EEPROM_NXID 3412d04db08STimur Tabi memcpy(e.id, "NXID", sizeof(e.id)); 342bfb70719STimur Tabi e.version = NXID_VERSION; 3432d04db08STimur Tabi #else 3442d04db08STimur Tabi memcpy(e.id, "CCID", sizeof(e.id)); 3452d04db08STimur Tabi #endif 3463fee334cSTimur Tabi update_crc(); 347e2d31fb3STimur Tabi return 0; 348e2d31fb3STimur Tabi } 349e2d31fb3STimur Tabi 350e2d31fb3STimur Tabi if (!is_valid) { 351e2d31fb3STimur Tabi printf("Please read the EEPROM ('r') and/or set the ID ('i') first.\n"); 352e2d31fb3STimur Tabi return 0; 353e2d31fb3STimur Tabi } 354e2d31fb3STimur Tabi 355e2d31fb3STimur Tabi if (argc == 2) { 3564ce91774SJon Loeliger switch (cmd) { 3574ce91774SJon Loeliger case 's': /* save */ 358e2d31fb3STimur Tabi prog_eeprom(); 3594ce91774SJon Loeliger break; 360e2d31fb3STimur Tabi default: 36147e26b1bSWolfgang Denk return cmd_usage(cmdtp); 3624ce91774SJon Loeliger } 363e2d31fb3STimur Tabi 364e2d31fb3STimur Tabi return 0; 365e2d31fb3STimur Tabi } 366e2d31fb3STimur Tabi 367e2d31fb3STimur Tabi /* We know we have at least one parameter */ 368e2d31fb3STimur Tabi 369e2d31fb3STimur Tabi switch (cmd) { 3704ce91774SJon Loeliger case 'n': /* serial number */ 371e2d31fb3STimur Tabi memset(e.sn, 0, sizeof(e.sn)); 372e2d31fb3STimur Tabi strncpy((char *)e.sn, argv[2], sizeof(e.sn) - 1); 3732d04db08STimur Tabi update_crc(); 3744ce91774SJon Loeliger break; 3754ce91774SJon Loeliger case 'e': /* errata */ 3766d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_I2C_EEPROM_NXID 377e2d31fb3STimur Tabi memset(e.errata, 0, 5); 378e2d31fb3STimur Tabi strncpy((char *)e.errata, argv[2], 4); 379e2d31fb3STimur Tabi #else 380e2d31fb3STimur Tabi e.errata[0] = argv[2][0]; 381e2d31fb3STimur Tabi e.errata[1] = argv[2][1]; 382e2d31fb3STimur Tabi #endif 3832d04db08STimur Tabi update_crc(); 3844ce91774SJon Loeliger break; 385e2d31fb3STimur Tabi case 'd': /* date BCD format YYMMDDhhmmss */ 386e2d31fb3STimur Tabi set_date(argv[2]); 3874ce91774SJon Loeliger break; 388e2d31fb3STimur Tabi case 'p': /* MAC table size */ 389e2d31fb3STimur Tabi e.mac_count = simple_strtoul(argv[2], NULL, 16); 3902d04db08STimur Tabi update_crc(); 3914ce91774SJon Loeliger break; 392bfb70719STimur Tabi case '0' ... '9': /* "mac 0" through "mac 22" */ 393bfb70719STimur Tabi set_mac_address(simple_strtoul(argv[1], NULL, 10), argv[2]); 3944ce91774SJon Loeliger break; 3954ce91774SJon Loeliger case 'h': /* help */ 3964ce91774SJon Loeliger default: 39747e26b1bSWolfgang Denk return cmd_usage(cmdtp); 3984ce91774SJon Loeliger } 399e2d31fb3STimur Tabi 4004ce91774SJon Loeliger return 0; 4014ce91774SJon Loeliger } 4024ce91774SJon Loeliger 403e2d31fb3STimur Tabi /** 404e2d31fb3STimur Tabi * mac_read_from_eeprom - read the MAC addresses from EEPROM 405e2d31fb3STimur Tabi * 406e2d31fb3STimur Tabi * This function reads the MAC addresses from EEPROM and sets the 407e2d31fb3STimur Tabi * appropriate environment variables for each one read. 408e2d31fb3STimur Tabi * 409e2d31fb3STimur Tabi * The environment variables are only set if they haven't been set already. 410e2d31fb3STimur Tabi * This ensures that any user-saved variables are never overwritten. 411e2d31fb3STimur Tabi * 412e2d31fb3STimur Tabi * This function must be called after relocation. 413f098c9c8STimur Tabi * 414f098c9c8STimur Tabi * For NXID v1 EEPROMs, we support loading and up-converting the older NXID v0 415f098c9c8STimur Tabi * format. In a v0 EEPROM, there are only eight MAC addresses and the CRC is 416f098c9c8STimur Tabi * located at a different offset. 417e2d31fb3STimur Tabi */ 4184ce91774SJon Loeliger int mac_read_from_eeprom(void) 4194ce91774SJon Loeliger { 420e2d31fb3STimur Tabi unsigned int i; 421f098c9c8STimur Tabi u32 crc, crc_offset = offsetof(struct eeprom, crc); 422f098c9c8STimur Tabi u32 *crcp; /* Pointer to the CRC in the data read from the EEPROM */ 4232d04db08STimur Tabi 4242d04db08STimur Tabi puts("EEPROM: "); 4254ce91774SJon Loeliger 426e2d31fb3STimur Tabi if (read_eeprom()) { 4274ce91774SJon Loeliger printf("Read failed.\n"); 4284ce91774SJon Loeliger return -1; 4294ce91774SJon Loeliger } 4304ce91774SJon Loeliger 431e2d31fb3STimur Tabi if (!is_valid) { 4322d04db08STimur Tabi printf("Invalid ID (%02x %02x %02x %02x)\n", 4332d04db08STimur Tabi e.id[0], e.id[1], e.id[2], e.id[3]); 4344ce91774SJon Loeliger return -1; 435e2d31fb3STimur Tabi } 436e2d31fb3STimur Tabi 437f098c9c8STimur Tabi #ifdef CONFIG_SYS_I2C_EEPROM_NXID 438f098c9c8STimur Tabi /* 439f098c9c8STimur Tabi * If we've read an NXID v0 EEPROM, then we need to set the CRC offset 440f098c9c8STimur Tabi * to where it is in v0. 441f098c9c8STimur Tabi */ 442f098c9c8STimur Tabi if (e.version == 0) 443f098c9c8STimur Tabi crc_offset = 0x72; 444f098c9c8STimur Tabi #endif 445f098c9c8STimur Tabi 446f098c9c8STimur Tabi crc = crc32(0, (void *)&e, crc_offset); 447f098c9c8STimur Tabi crcp = (void *)&e + crc_offset; 448f098c9c8STimur Tabi if (crc != be32_to_cpu(*crcp)) { 4492d04db08STimur Tabi printf("CRC mismatch (%08x != %08x)\n", crc, be32_to_cpu(e.crc)); 450e2d31fb3STimur Tabi return -1; 4514ce91774SJon Loeliger } 452e2d31fb3STimur Tabi 453f098c9c8STimur Tabi #ifdef CONFIG_SYS_I2C_EEPROM_NXID 454f098c9c8STimur Tabi /* 455f098c9c8STimur Tabi * MAC address #9 in v1 occupies the same position as the CRC in v0. 456f098c9c8STimur Tabi * Erase it so that it's not mistaken for a MAC address. We'll 457f098c9c8STimur Tabi * update the CRC later. 458f098c9c8STimur Tabi */ 459f098c9c8STimur Tabi if (e.version == 0) 460f098c9c8STimur Tabi memset(e.mac[8], 0xff, 6); 461f098c9c8STimur Tabi #endif 462f098c9c8STimur Tabi 4632d04db08STimur Tabi for (i = 0; i < min(e.mac_count, MAX_NUM_PORTS); i++) { 464e2d31fb3STimur Tabi if (memcmp(&e.mac[i], "\0\0\0\0\0\0", 6) && 465e2d31fb3STimur Tabi memcmp(&e.mac[i], "\xFF\xFF\xFF\xFF\xFF\xFF", 6)) { 466e2d31fb3STimur Tabi char ethaddr[18]; 467e2d31fb3STimur Tabi char enetvar[9]; 468e2d31fb3STimur Tabi 469e2d31fb3STimur Tabi sprintf(ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X", 470e2d31fb3STimur Tabi e.mac[i][0], 471e2d31fb3STimur Tabi e.mac[i][1], 472e2d31fb3STimur Tabi e.mac[i][2], 473e2d31fb3STimur Tabi e.mac[i][3], 474e2d31fb3STimur Tabi e.mac[i][4], 475e2d31fb3STimur Tabi e.mac[i][5]); 476e2d31fb3STimur Tabi sprintf(enetvar, i ? "eth%daddr" : "ethaddr", i); 477e2d31fb3STimur Tabi /* Only initialize environment variables that are blank 478e2d31fb3STimur Tabi * (i.e. have not yet been set) 479e2d31fb3STimur Tabi */ 480e2d31fb3STimur Tabi if (!getenv(enetvar)) 481e2d31fb3STimur Tabi setenv(enetvar, ethaddr); 4824ce91774SJon Loeliger } 483e2d31fb3STimur Tabi } 484e2d31fb3STimur Tabi 4852d04db08STimur Tabi #ifdef CONFIG_SYS_I2C_EEPROM_NXID 4862d04db08STimur Tabi printf("%c%c%c%c v%u\n", e.id[0], e.id[1], e.id[2], e.id[3], 4872d04db08STimur Tabi be32_to_cpu(e.version)); 4882d04db08STimur Tabi #else 4892d04db08STimur Tabi printf("%c%c%c%c\n", e.id[0], e.id[1], e.id[2], e.id[3]); 4902d04db08STimur Tabi #endif 4912d04db08STimur Tabi 492f098c9c8STimur Tabi #ifdef CONFIG_SYS_I2C_EEPROM_NXID 493f098c9c8STimur Tabi /* 494f098c9c8STimur Tabi * Now we need to upconvert the data into v1 format. We do this last so 495f098c9c8STimur Tabi * that at boot time, U-Boot will still say "NXID v0". 496f098c9c8STimur Tabi */ 497f098c9c8STimur Tabi if (e.version == 0) { 498f098c9c8STimur Tabi e.version = NXID_VERSION; 499f098c9c8STimur Tabi update_crc(); 500f098c9c8STimur Tabi } 501f098c9c8STimur Tabi #endif 502f098c9c8STimur Tabi 5034ce91774SJon Loeliger return 0; 5044ce91774SJon Loeliger } 505e2d31fb3STimur Tabi 5066d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_I2C_EEPROM_CCID 507e2d31fb3STimur Tabi 508e2d31fb3STimur Tabi /** 509e2d31fb3STimur Tabi * get_cpu_board_revision - get the CPU board revision on 85xx boards 510e2d31fb3STimur Tabi * 511e2d31fb3STimur Tabi * Read the EEPROM to determine the board revision. 512e2d31fb3STimur Tabi * 513e2d31fb3STimur Tabi * This function is called before relocation, so we need to read a private 514e2d31fb3STimur Tabi * copy of the EEPROM into a local variable on the stack. 515e2d31fb3STimur Tabi * 5166d0f6bcfSJean-Christophe PLAGNIOL-VILLARD * Also, we assume that CONFIG_SYS_EEPROM_BUS_NUM == CONFIG_SYS_SPD_BUS_NUM. The global 5176d0f6bcfSJean-Christophe PLAGNIOL-VILLARD * variable i2c_bus_num must be compile-time initialized to CONFIG_SYS_SPD_BUS_NUM, 518e2d31fb3STimur Tabi * so that the SPD code will work. This means that all pre-relocation I2C 5196d0f6bcfSJean-Christophe PLAGNIOL-VILLARD * operations can only occur on the CONFIG_SYS_SPD_BUS_NUM bus. So if 5206d0f6bcfSJean-Christophe PLAGNIOL-VILLARD * CONFIG_SYS_EEPROM_BUS_NUM != CONFIG_SYS_SPD_BUS_NUM, then we can't read the EEPROM when 521e2d31fb3STimur Tabi * this function is called. Oh well. 522e2d31fb3STimur Tabi */ 523e2d31fb3STimur Tabi unsigned int get_cpu_board_revision(void) 524e2d31fb3STimur Tabi { 525e2d31fb3STimur Tabi struct board_eeprom { 526e2d31fb3STimur Tabi u32 id; /* 0x00 - 0x03 EEPROM Tag 'CCID' */ 527e2d31fb3STimur Tabi u8 major; /* 0x04 Board revision, major */ 528e2d31fb3STimur Tabi u8 minor; /* 0x05 Board revision, minor */ 529e2d31fb3STimur Tabi } be; 530e2d31fb3STimur Tabi 5316d0f6bcfSJean-Christophe PLAGNIOL-VILLARD i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0, CONFIG_SYS_I2C_EEPROM_ADDR_LEN, 532e2d31fb3STimur Tabi (void *)&be, sizeof(be)); 533e2d31fb3STimur Tabi 534e2d31fb3STimur Tabi if (be.id != (('C' << 24) | ('C' << 16) | ('I' << 8) | 'D')) 535e2d31fb3STimur Tabi return MPC85XX_CPU_BOARD_REV(0, 0); 536e2d31fb3STimur Tabi 537e2d31fb3STimur Tabi if ((be.major == 0xff) && (be.minor == 0xff)) 538e2d31fb3STimur Tabi return MPC85XX_CPU_BOARD_REV(0, 0); 539e2d31fb3STimur Tabi 540e46c7bfbSRafal Czubak return MPC85XX_CPU_BOARD_REV(be.major, be.minor); 541e2d31fb3STimur Tabi } 542e2d31fb3STimur Tabi #endif 543