14ce91774SJon Loeliger /* 2*f098c9c8STimur 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 * 74ce91774SJon Loeliger * See file CREDITS for list of people who contributed to this 84ce91774SJon Loeliger * project. 94ce91774SJon Loeliger * 104ce91774SJon Loeliger * This program is free software; you can redistribute it and/or 114ce91774SJon Loeliger * modify it under the terms of the GNU General Public License as 124ce91774SJon Loeliger * published by the Free Software Foundation; either version 2 of 134ce91774SJon Loeliger * the License, or (at your option) any later version. 144ce91774SJon Loeliger * 154ce91774SJon Loeliger * This program is distributed in the hope that it will be useful, 164ce91774SJon Loeliger * but WITHOUT ANY WARRANTY; without even the implied warranty of 174ce91774SJon Loeliger * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 184ce91774SJon Loeliger * GNU General Public License for more details. 194ce91774SJon Loeliger * 204ce91774SJon Loeliger * You should have received a copy of the GNU General Public License 214ce91774SJon Loeliger * along with this program; if not, write to the Free Software 224ce91774SJon Loeliger * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 234ce91774SJon Loeliger * MA 02111-1307 USA 244ce91774SJon Loeliger */ 254ce91774SJon Loeliger 264ce91774SJon Loeliger #include <common.h> 274ce91774SJon Loeliger #include <command.h> 284ce91774SJon Loeliger #include <i2c.h> 294ce91774SJon Loeliger #include <linux/ctype.h> 304ce91774SJon Loeliger 31bfb70719STimur Tabi #ifdef CONFIG_SYS_I2C_EEPROM_CCID 32e2d31fb3STimur Tabi #include "../common/eeprom.h" 33bfb70719STimur Tabi #define MAX_NUM_PORTS 8 34e2d31fb3STimur Tabi #endif 354ce91774SJon Loeliger 36bfb70719STimur Tabi #ifdef CONFIG_SYS_I2C_EEPROM_NXID 37bfb70719STimur Tabi #define MAX_NUM_PORTS 23 38bfb70719STimur Tabi #define NXID_VERSION 1 39bfb70719STimur Tabi #endif 409a611089SHaiying Wang 41e2d31fb3STimur Tabi /** 42e2d31fb3STimur Tabi * static eeprom: EEPROM layout for CCID or NXID formats 43e2d31fb3STimur Tabi * 44e2d31fb3STimur Tabi * See application note AN3638 for details. 45e2d31fb3STimur Tabi */ 46e2d31fb3STimur Tabi static struct __attribute__ ((__packed__)) eeprom { 476d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_I2C_EEPROM_CCID 48e2d31fb3STimur Tabi u8 id[4]; /* 0x00 - 0x03 EEPROM Tag 'CCID' */ 49e2d31fb3STimur Tabi u8 major; /* 0x04 Board revision, major */ 50e2d31fb3STimur Tabi u8 minor; /* 0x05 Board revision, minor */ 51e2d31fb3STimur Tabi u8 sn[10]; /* 0x06 - 0x0F Serial Number*/ 52e2d31fb3STimur Tabi u8 errata[2]; /* 0x10 - 0x11 Errata Level */ 53e2d31fb3STimur Tabi u8 date[6]; /* 0x12 - 0x17 Build Date */ 54e2d31fb3STimur Tabi u8 res_0[40]; /* 0x18 - 0x3f Reserved */ 55e2d31fb3STimur Tabi u8 mac_count; /* 0x40 Number of MAC addresses */ 56e2d31fb3STimur Tabi u8 mac_flag; /* 0x41 MAC table flags */ 579a611089SHaiying Wang u8 mac[MAX_NUM_PORTS][6]; /* 0x42 - 0x71 MAC addresses */ 58e2d31fb3STimur Tabi u32 crc; /* 0x72 CRC32 checksum */ 59e2d31fb3STimur Tabi #endif 606d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_I2C_EEPROM_NXID 61e2d31fb3STimur Tabi u8 id[4]; /* 0x00 - 0x03 EEPROM Tag 'NXID' */ 62e2d31fb3STimur Tabi u8 sn[12]; /* 0x04 - 0x0F Serial Number */ 63e2d31fb3STimur Tabi u8 errata[5]; /* 0x10 - 0x14 Errata Level */ 64e2d31fb3STimur Tabi u8 date[6]; /* 0x15 - 0x1a Build Date */ 65e2d31fb3STimur Tabi u8 res_0; /* 0x1b Reserved */ 66e2d31fb3STimur Tabi u32 version; /* 0x1c - 0x1f NXID Version */ 67e2d31fb3STimur Tabi u8 tempcal[8]; /* 0x20 - 0x27 Temperature Calibration Factors */ 68e2d31fb3STimur Tabi u8 tempcalsys[2]; /* 0x28 - 0x29 System Temperature Calibration Factors */ 69e2d31fb3STimur Tabi u8 tempcalflags; /* 0x2a Temperature Calibration Flags */ 70e2d31fb3STimur Tabi u8 res_1[21]; /* 0x2b - 0x3f Reserved */ 71e2d31fb3STimur Tabi u8 mac_count; /* 0x40 Number of MAC addresses */ 72e2d31fb3STimur Tabi u8 mac_flag; /* 0x41 MAC table flags */ 73bfb70719STimur Tabi u8 mac[MAX_NUM_PORTS][6]; /* 0x42 - x MAC addresses */ 74bfb70719STimur Tabi u32 crc; /* x+1 CRC32 checksum */ 75e2d31fb3STimur Tabi #endif 76e2d31fb3STimur Tabi } e; 77e2d31fb3STimur Tabi 78e2d31fb3STimur Tabi /* Set to 1 if we've read EEPROM into memory */ 79e2d31fb3STimur Tabi static int has_been_read = 0; 80e2d31fb3STimur Tabi 816d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_I2C_EEPROM_NXID 82e2d31fb3STimur Tabi /* Is this a valid NXID EEPROM? */ 83afb0b131SKumar Gala #define is_valid ((e.id[0] == 'N') || (e.id[1] == 'X') || \ 84afb0b131SKumar Gala (e.id[2] == 'I') || (e.id[3] == 'D')) 85e2d31fb3STimur Tabi #endif 86e2d31fb3STimur Tabi 876d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_I2C_EEPROM_CCID 88e2d31fb3STimur Tabi /* Is this a valid CCID EEPROM? */ 89afb0b131SKumar Gala #define is_valid ((e.id[0] == 'C') || (e.id[1] == 'C') || \ 90afb0b131SKumar Gala (e.id[2] == 'I') || (e.id[3] == 'D')) 91e2d31fb3STimur Tabi #endif 92e2d31fb3STimur Tabi 93e2d31fb3STimur Tabi /** 94e2d31fb3STimur Tabi * show_eeprom - display the contents of the EEPROM 95e2d31fb3STimur Tabi */ 96e2d31fb3STimur Tabi static void show_eeprom(void) 974ce91774SJon Loeliger { 984ce91774SJon Loeliger int i; 99e2d31fb3STimur Tabi unsigned int crc; 1004ce91774SJon Loeliger 101e2d31fb3STimur Tabi /* EEPROM tag ID, either CCID or NXID */ 1026d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_I2C_EEPROM_NXID 103e2d31fb3STimur Tabi printf("ID: %c%c%c%c v%u\n", e.id[0], e.id[1], e.id[2], e.id[3], 104e2d31fb3STimur Tabi be32_to_cpu(e.version)); 105e2d31fb3STimur Tabi #else 106e2d31fb3STimur Tabi printf("ID: %c%c%c%c\n", e.id[0], e.id[1], e.id[2], e.id[3]); 107e2d31fb3STimur Tabi #endif 108d59feffbSHaiying Wang 109e2d31fb3STimur Tabi /* Serial number */ 110e2d31fb3STimur Tabi printf("SN: %s\n", e.sn); 111d59feffbSHaiying Wang 112e2d31fb3STimur Tabi /* Errata level. */ 1136d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_I2C_EEPROM_NXID 114e2d31fb3STimur Tabi printf("Errata: %s\n", e.errata); 115e2d31fb3STimur Tabi #else 116e2d31fb3STimur Tabi printf("Errata: %c%c\n", 117e2d31fb3STimur Tabi e.errata[0] ? e.errata[0] : '.', 118e2d31fb3STimur Tabi e.errata[1] ? e.errata[1] : '.'); 119e2d31fb3STimur Tabi #endif 120d59feffbSHaiying Wang 121e2d31fb3STimur Tabi /* Build date, BCD date values, as YYMMDDhhmmss */ 122e2d31fb3STimur Tabi printf("Build date: 20%02x/%02x/%02x %02x:%02x:%02x %s\n", 123e2d31fb3STimur Tabi e.date[0], e.date[1], e.date[2], 124e2d31fb3STimur Tabi e.date[3] & 0x7F, e.date[4], e.date[5], 125e2d31fb3STimur Tabi e.date[3] & 0x80 ? "PM" : ""); 126d59feffbSHaiying Wang 127e2d31fb3STimur Tabi /* Show MAC addresses */ 1289a611089SHaiying Wang for (i = 0; i < min(e.mac_count, MAX_NUM_PORTS); i++) { 1299a611089SHaiying Wang 130e2d31fb3STimur Tabi u8 *p = e.mac[i]; 131e2d31fb3STimur Tabi 132e2d31fb3STimur Tabi printf("Eth%u: %02x:%02x:%02x:%02x:%02x:%02x\n", i, 133e2d31fb3STimur Tabi p[0], p[1], p[2], p[3], p[4], p[5]); 134e2d31fb3STimur Tabi } 135e2d31fb3STimur Tabi 136e2d31fb3STimur Tabi crc = crc32(0, (void *)&e, sizeof(e) - 4); 137e2d31fb3STimur Tabi 138e2d31fb3STimur Tabi if (crc == be32_to_cpu(e.crc)) 139e2d31fb3STimur Tabi printf("CRC: %08x\n", be32_to_cpu(e.crc)); 140d59feffbSHaiying Wang else 141e2d31fb3STimur Tabi printf("CRC: %08x (should be %08x)\n", 142e2d31fb3STimur Tabi be32_to_cpu(e.crc), crc); 143d59feffbSHaiying Wang 144e2d31fb3STimur Tabi #ifdef DEBUG 145e2d31fb3STimur Tabi printf("EEPROM dump: (0x%x bytes)\n", sizeof(e)); 146e2d31fb3STimur Tabi for (i = 0; i < sizeof(e); i++) { 147e2d31fb3STimur Tabi if ((i % 16) == 0) 148e2d31fb3STimur Tabi printf("%02X: ", i); 149e2d31fb3STimur Tabi printf("%02X ", ((u8 *)&e)[i]); 150e2d31fb3STimur Tabi if (((i % 16) == 15) || (i == sizeof(e) - 1)) 151e2d31fb3STimur Tabi printf("\n"); 152e2d31fb3STimur Tabi } 153e2d31fb3STimur Tabi #endif 154d59feffbSHaiying Wang } 1554ce91774SJon Loeliger 156e2d31fb3STimur Tabi /** 157e2d31fb3STimur Tabi * read_eeprom - read the EEPROM into memory 158e2d31fb3STimur Tabi */ 159e2d31fb3STimur Tabi static int read_eeprom(void) 1604ce91774SJon Loeliger { 161e2d31fb3STimur Tabi int ret; 1626d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_EEPROM_BUS_NUM 163e2d31fb3STimur Tabi unsigned int bus; 164e2d31fb3STimur Tabi #endif 1654ce91774SJon Loeliger 166e2d31fb3STimur Tabi if (has_been_read) 1674ce91774SJon Loeliger return 0; 168e2d31fb3STimur Tabi 1696d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_EEPROM_BUS_NUM 170e2d31fb3STimur Tabi bus = i2c_get_bus_num(); 1716d0f6bcfSJean-Christophe PLAGNIOL-VILLARD i2c_set_bus_num(CONFIG_SYS_EEPROM_BUS_NUM); 172e2d31fb3STimur Tabi #endif 173e2d31fb3STimur Tabi 1746d0f6bcfSJean-Christophe PLAGNIOL-VILLARD ret = i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0, CONFIG_SYS_I2C_EEPROM_ADDR_LEN, 175e2d31fb3STimur Tabi (void *)&e, sizeof(e)); 176e2d31fb3STimur Tabi 1776d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_EEPROM_BUS_NUM 178e2d31fb3STimur Tabi i2c_set_bus_num(bus); 179e2d31fb3STimur Tabi #endif 180e2d31fb3STimur Tabi 181e2d31fb3STimur Tabi #ifdef DEBUG 182e2d31fb3STimur Tabi show_eeprom(); 183e2d31fb3STimur Tabi #endif 184e2d31fb3STimur Tabi 185e2d31fb3STimur Tabi has_been_read = (ret == 0) ? 1 : 0; 186e2d31fb3STimur Tabi 187e2d31fb3STimur Tabi return ret; 1884ce91774SJon Loeliger } 1894ce91774SJon Loeliger 190e2d31fb3STimur Tabi /** 1912d04db08STimur Tabi * update_crc - update the CRC 1922d04db08STimur Tabi * 1932d04db08STimur Tabi * This function should be called after each update to the EEPROM structure, 1942d04db08STimur Tabi * to make sure the CRC is always correct. 1952d04db08STimur Tabi */ 1962d04db08STimur Tabi static void update_crc(void) 1972d04db08STimur Tabi { 1982d04db08STimur Tabi u32 crc; 1992d04db08STimur Tabi 2002d04db08STimur Tabi crc = crc32(0, (void *)&e, sizeof(e) - 4); 2012d04db08STimur Tabi e.crc = cpu_to_be32(crc); 2022d04db08STimur Tabi } 2032d04db08STimur Tabi 2042d04db08STimur Tabi /** 205e2d31fb3STimur Tabi * prog_eeprom - write the EEPROM from memory 206e2d31fb3STimur Tabi */ 207e2d31fb3STimur Tabi static int prog_eeprom(void) 2084ce91774SJon Loeliger { 2093addcb93STimur Tabi int ret = 0; 2109c671e70SAnton Vorontsov int i; 211e2d31fb3STimur Tabi void *p; 2126d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_EEPROM_BUS_NUM 213e2d31fb3STimur Tabi unsigned int bus; 214e2d31fb3STimur Tabi #endif 2154ce91774SJon Loeliger 216e2d31fb3STimur Tabi /* Set the reserved values to 0xFF */ 2176d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_I2C_EEPROM_NXID 218e2d31fb3STimur Tabi e.res_0 = 0xFF; 219e2d31fb3STimur Tabi memset(e.res_1, 0xFF, sizeof(e.res_1)); 220e2d31fb3STimur Tabi #else 221e2d31fb3STimur Tabi memset(e.res_0, 0xFF, sizeof(e.res_0)); 222e2d31fb3STimur Tabi #endif 2232d04db08STimur Tabi update_crc(); 224e2d31fb3STimur Tabi 2256d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_EEPROM_BUS_NUM 226e2d31fb3STimur Tabi bus = i2c_get_bus_num(); 2276d0f6bcfSJean-Christophe PLAGNIOL-VILLARD i2c_set_bus_num(CONFIG_SYS_EEPROM_BUS_NUM); 228e2d31fb3STimur Tabi #endif 229e2d31fb3STimur Tabi 2303addcb93STimur Tabi /* 2313addcb93STimur Tabi * The AT24C02 datasheet says that data can only be written in page 2323addcb93STimur Tabi * mode, which means 8 bytes at a time, and it takes up to 5ms to 2333addcb93STimur Tabi * complete a given write. 2343addcb93STimur Tabi */ 2352d04db08STimur Tabi for (i = 0, p = &e; i < sizeof(e); i += 8, p += 8) { 2366d0f6bcfSJean-Christophe PLAGNIOL-VILLARD ret = i2c_write(CONFIG_SYS_I2C_EEPROM_ADDR, i, CONFIG_SYS_I2C_EEPROM_ADDR_LEN, 2372d04db08STimur Tabi p, min((sizeof(e) - i), 8)); 2384ce91774SJon Loeliger if (ret) 2394ce91774SJon Loeliger break; 240e2d31fb3STimur Tabi udelay(5000); /* 5ms write cycle timing */ 2414ce91774SJon Loeliger } 242e2d31fb3STimur Tabi 2433addcb93STimur Tabi if (!ret) { 2443addcb93STimur Tabi /* Verify the write by reading back the EEPROM and comparing */ 2453addcb93STimur Tabi struct eeprom e2; 2463addcb93STimur Tabi 2473addcb93STimur Tabi ret = i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0, 2483addcb93STimur Tabi CONFIG_SYS_I2C_EEPROM_ADDR_LEN, (void *)&e2, sizeof(e2)); 2493addcb93STimur Tabi if (!ret && memcmp(&e, &e2, sizeof(e))) 2503addcb93STimur Tabi ret = -1; 2513addcb93STimur Tabi } 2523addcb93STimur Tabi 2536d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_EEPROM_BUS_NUM 254e2d31fb3STimur Tabi i2c_set_bus_num(bus); 255e2d31fb3STimur Tabi #endif 256e2d31fb3STimur Tabi 2574ce91774SJon Loeliger if (ret) { 2584ce91774SJon Loeliger printf("Programming failed.\n"); 2593addcb93STimur Tabi has_been_read = 0; 2604ce91774SJon Loeliger return -1; 2614ce91774SJon Loeliger } 262e2d31fb3STimur Tabi 263e2d31fb3STimur Tabi printf("Programming passed.\n"); 2644ce91774SJon Loeliger return 0; 2654ce91774SJon Loeliger } 2664ce91774SJon Loeliger 267e2d31fb3STimur Tabi /** 268e2d31fb3STimur Tabi * h2i - converts hex character into a number 269e2d31fb3STimur Tabi * 270e2d31fb3STimur Tabi * This function takes a hexadecimal character (e.g. '7' or 'C') and returns 271e2d31fb3STimur Tabi * the integer equivalent. 272e2d31fb3STimur Tabi */ 273e2d31fb3STimur Tabi static inline u8 h2i(char p) 274e2d31fb3STimur Tabi { 275e2d31fb3STimur Tabi if ((p >= '0') && (p <= '9')) 276e2d31fb3STimur Tabi return p - '0'; 277e2d31fb3STimur Tabi 278e2d31fb3STimur Tabi if ((p >= 'A') && (p <= 'F')) 279e2d31fb3STimur Tabi return (p - 'A') + 10; 280e2d31fb3STimur Tabi 281e2d31fb3STimur Tabi if ((p >= 'a') && (p <= 'f')) 282e2d31fb3STimur Tabi return (p - 'a') + 10; 283e2d31fb3STimur Tabi 284e2d31fb3STimur Tabi return 0; 285e2d31fb3STimur Tabi } 286e2d31fb3STimur Tabi 287e2d31fb3STimur Tabi /** 288e2d31fb3STimur Tabi * set_date - stores the build date into the EEPROM 289e2d31fb3STimur Tabi * 290e2d31fb3STimur Tabi * This function takes a pointer to a string in the format "YYMMDDhhmmss" 291e2d31fb3STimur Tabi * (2-digit year, 2-digit month, etc), converts it to a 6-byte BCD string, 292e2d31fb3STimur Tabi * and stores it in the build date field of the EEPROM local copy. 293e2d31fb3STimur Tabi */ 294e2d31fb3STimur Tabi static void set_date(const char *string) 295e2d31fb3STimur Tabi { 296e2d31fb3STimur Tabi unsigned int i; 297e2d31fb3STimur Tabi 298e2d31fb3STimur Tabi if (strlen(string) != 12) { 299e2d31fb3STimur Tabi printf("Usage: mac date YYMMDDhhmmss\n"); 300e2d31fb3STimur Tabi return; 301e2d31fb3STimur Tabi } 302e2d31fb3STimur Tabi 303e2d31fb3STimur Tabi for (i = 0; i < 6; i++) 304e2d31fb3STimur Tabi e.date[i] = h2i(string[2 * i]) << 4 | h2i(string[2 * i + 1]); 3052d04db08STimur Tabi 3062d04db08STimur Tabi update_crc(); 307e2d31fb3STimur Tabi } 308e2d31fb3STimur Tabi 309e2d31fb3STimur Tabi /** 310e2d31fb3STimur Tabi * set_mac_address - stores a MAC address into the EEPROM 311e2d31fb3STimur Tabi * 312e2d31fb3STimur Tabi * This function takes a pointer to MAC address string 313e2d31fb3STimur Tabi * (i.e."XX:XX:XX:XX:XX:XX", where "XX" is a two-digit hex number) and 314e2d31fb3STimur Tabi * stores it in one of the MAC address fields of the EEPROM local copy. 315e2d31fb3STimur Tabi */ 316e2d31fb3STimur Tabi static void set_mac_address(unsigned int index, const char *string) 317e2d31fb3STimur Tabi { 318e2d31fb3STimur Tabi char *p = (char *) string; 319e2d31fb3STimur Tabi unsigned int i; 320e2d31fb3STimur Tabi 321bfb70719STimur Tabi if ((index >= MAX_NUM_PORTS) || !string) { 322e2d31fb3STimur Tabi printf("Usage: mac <n> XX:XX:XX:XX:XX:XX\n"); 323e2d31fb3STimur Tabi return; 324e2d31fb3STimur Tabi } 325e2d31fb3STimur Tabi 326e2d31fb3STimur Tabi for (i = 0; *p && (i < 6); i++) { 327e2d31fb3STimur Tabi e.mac[index][i] = simple_strtoul(p, &p, 16); 328e2d31fb3STimur Tabi if (*p == ':') 329e2d31fb3STimur Tabi p++; 330e2d31fb3STimur Tabi } 3312d04db08STimur Tabi 3322d04db08STimur Tabi update_crc(); 333e2d31fb3STimur Tabi } 334e2d31fb3STimur Tabi 33554841ab5SWolfgang Denk int do_mac(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 3364ce91774SJon Loeliger { 337e2d31fb3STimur Tabi char cmd; 3384ce91774SJon Loeliger 339e2d31fb3STimur Tabi if (argc == 1) { 340e2d31fb3STimur Tabi show_eeprom(); 341e2d31fb3STimur Tabi return 0; 342e2d31fb3STimur Tabi } 3434ce91774SJon Loeliger 3444ce91774SJon Loeliger cmd = argv[1][0]; 345e2d31fb3STimur Tabi 346e2d31fb3STimur Tabi if (cmd == 'r') { 347e2d31fb3STimur Tabi read_eeprom(); 348e2d31fb3STimur Tabi return 0; 349e2d31fb3STimur Tabi } 350e2d31fb3STimur Tabi 3512d04db08STimur Tabi if (cmd == 'i') { 3522d04db08STimur Tabi #ifdef CONFIG_SYS_I2C_EEPROM_NXID 3532d04db08STimur Tabi memcpy(e.id, "NXID", sizeof(e.id)); 354bfb70719STimur Tabi e.version = NXID_VERSION; 3552d04db08STimur Tabi #else 3562d04db08STimur Tabi memcpy(e.id, "CCID", sizeof(e.id)); 3572d04db08STimur Tabi #endif 3583fee334cSTimur Tabi update_crc(); 359e2d31fb3STimur Tabi return 0; 360e2d31fb3STimur Tabi } 361e2d31fb3STimur Tabi 362e2d31fb3STimur Tabi if (!is_valid) { 363e2d31fb3STimur Tabi printf("Please read the EEPROM ('r') and/or set the ID ('i') first.\n"); 364e2d31fb3STimur Tabi return 0; 365e2d31fb3STimur Tabi } 366e2d31fb3STimur Tabi 367e2d31fb3STimur Tabi if (argc == 2) { 3684ce91774SJon Loeliger switch (cmd) { 3694ce91774SJon Loeliger case 's': /* save */ 370e2d31fb3STimur Tabi prog_eeprom(); 3714ce91774SJon Loeliger break; 372e2d31fb3STimur Tabi default: 37347e26b1bSWolfgang Denk return cmd_usage(cmdtp); 3744ce91774SJon Loeliger } 375e2d31fb3STimur Tabi 376e2d31fb3STimur Tabi return 0; 377e2d31fb3STimur Tabi } 378e2d31fb3STimur Tabi 379e2d31fb3STimur Tabi /* We know we have at least one parameter */ 380e2d31fb3STimur Tabi 381e2d31fb3STimur Tabi switch (cmd) { 3824ce91774SJon Loeliger case 'n': /* serial number */ 383e2d31fb3STimur Tabi memset(e.sn, 0, sizeof(e.sn)); 384e2d31fb3STimur Tabi strncpy((char *)e.sn, argv[2], sizeof(e.sn) - 1); 3852d04db08STimur Tabi update_crc(); 3864ce91774SJon Loeliger break; 3874ce91774SJon Loeliger case 'e': /* errata */ 3886d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_I2C_EEPROM_NXID 389e2d31fb3STimur Tabi memset(e.errata, 0, 5); 390e2d31fb3STimur Tabi strncpy((char *)e.errata, argv[2], 4); 391e2d31fb3STimur Tabi #else 392e2d31fb3STimur Tabi e.errata[0] = argv[2][0]; 393e2d31fb3STimur Tabi e.errata[1] = argv[2][1]; 394e2d31fb3STimur Tabi #endif 3952d04db08STimur Tabi update_crc(); 3964ce91774SJon Loeliger break; 397e2d31fb3STimur Tabi case 'd': /* date BCD format YYMMDDhhmmss */ 398e2d31fb3STimur Tabi set_date(argv[2]); 3994ce91774SJon Loeliger break; 400e2d31fb3STimur Tabi case 'p': /* MAC table size */ 401e2d31fb3STimur Tabi e.mac_count = simple_strtoul(argv[2], NULL, 16); 4022d04db08STimur Tabi update_crc(); 4034ce91774SJon Loeliger break; 404bfb70719STimur Tabi case '0' ... '9': /* "mac 0" through "mac 22" */ 405bfb70719STimur Tabi set_mac_address(simple_strtoul(argv[1], NULL, 10), argv[2]); 4064ce91774SJon Loeliger break; 4074ce91774SJon Loeliger case 'h': /* help */ 4084ce91774SJon Loeliger default: 40947e26b1bSWolfgang Denk return cmd_usage(cmdtp); 4104ce91774SJon Loeliger } 411e2d31fb3STimur Tabi 4124ce91774SJon Loeliger return 0; 4134ce91774SJon Loeliger } 4144ce91774SJon Loeliger 415e2d31fb3STimur Tabi /** 416e2d31fb3STimur Tabi * mac_read_from_eeprom - read the MAC addresses from EEPROM 417e2d31fb3STimur Tabi * 418e2d31fb3STimur Tabi * This function reads the MAC addresses from EEPROM and sets the 419e2d31fb3STimur Tabi * appropriate environment variables for each one read. 420e2d31fb3STimur Tabi * 421e2d31fb3STimur Tabi * The environment variables are only set if they haven't been set already. 422e2d31fb3STimur Tabi * This ensures that any user-saved variables are never overwritten. 423e2d31fb3STimur Tabi * 424e2d31fb3STimur Tabi * This function must be called after relocation. 425*f098c9c8STimur Tabi * 426*f098c9c8STimur Tabi * For NXID v1 EEPROMs, we support loading and up-converting the older NXID v0 427*f098c9c8STimur Tabi * format. In a v0 EEPROM, there are only eight MAC addresses and the CRC is 428*f098c9c8STimur Tabi * located at a different offset. 429e2d31fb3STimur Tabi */ 4304ce91774SJon Loeliger int mac_read_from_eeprom(void) 4314ce91774SJon Loeliger { 432e2d31fb3STimur Tabi unsigned int i; 433*f098c9c8STimur Tabi u32 crc, crc_offset = offsetof(struct eeprom, crc); 434*f098c9c8STimur Tabi u32 *crcp; /* Pointer to the CRC in the data read from the EEPROM */ 4352d04db08STimur Tabi 4362d04db08STimur Tabi puts("EEPROM: "); 4374ce91774SJon Loeliger 438e2d31fb3STimur Tabi if (read_eeprom()) { 4394ce91774SJon Loeliger printf("Read failed.\n"); 4404ce91774SJon Loeliger return -1; 4414ce91774SJon Loeliger } 4424ce91774SJon Loeliger 443e2d31fb3STimur Tabi if (!is_valid) { 4442d04db08STimur Tabi printf("Invalid ID (%02x %02x %02x %02x)\n", 4452d04db08STimur Tabi e.id[0], e.id[1], e.id[2], e.id[3]); 4464ce91774SJon Loeliger return -1; 447e2d31fb3STimur Tabi } 448e2d31fb3STimur Tabi 449*f098c9c8STimur Tabi #ifdef CONFIG_SYS_I2C_EEPROM_NXID 450*f098c9c8STimur Tabi /* 451*f098c9c8STimur Tabi * If we've read an NXID v0 EEPROM, then we need to set the CRC offset 452*f098c9c8STimur Tabi * to where it is in v0. 453*f098c9c8STimur Tabi */ 454*f098c9c8STimur Tabi if (e.version == 0) 455*f098c9c8STimur Tabi crc_offset = 0x72; 456*f098c9c8STimur Tabi #endif 457*f098c9c8STimur Tabi 458*f098c9c8STimur Tabi crc = crc32(0, (void *)&e, crc_offset); 459*f098c9c8STimur Tabi crcp = (void *)&e + crc_offset; 460*f098c9c8STimur Tabi if (crc != be32_to_cpu(*crcp)) { 4612d04db08STimur Tabi printf("CRC mismatch (%08x != %08x)\n", crc, be32_to_cpu(e.crc)); 462e2d31fb3STimur Tabi return -1; 4634ce91774SJon Loeliger } 464e2d31fb3STimur Tabi 465*f098c9c8STimur Tabi #ifdef CONFIG_SYS_I2C_EEPROM_NXID 466*f098c9c8STimur Tabi /* 467*f098c9c8STimur Tabi * MAC address #9 in v1 occupies the same position as the CRC in v0. 468*f098c9c8STimur Tabi * Erase it so that it's not mistaken for a MAC address. We'll 469*f098c9c8STimur Tabi * update the CRC later. 470*f098c9c8STimur Tabi */ 471*f098c9c8STimur Tabi if (e.version == 0) 472*f098c9c8STimur Tabi memset(e.mac[8], 0xff, 6); 473*f098c9c8STimur Tabi #endif 474*f098c9c8STimur Tabi 4752d04db08STimur Tabi for (i = 0; i < min(e.mac_count, MAX_NUM_PORTS); i++) { 476e2d31fb3STimur Tabi if (memcmp(&e.mac[i], "\0\0\0\0\0\0", 6) && 477e2d31fb3STimur Tabi memcmp(&e.mac[i], "\xFF\xFF\xFF\xFF\xFF\xFF", 6)) { 478e2d31fb3STimur Tabi char ethaddr[18]; 479e2d31fb3STimur Tabi char enetvar[9]; 480e2d31fb3STimur Tabi 481e2d31fb3STimur Tabi sprintf(ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X", 482e2d31fb3STimur Tabi e.mac[i][0], 483e2d31fb3STimur Tabi e.mac[i][1], 484e2d31fb3STimur Tabi e.mac[i][2], 485e2d31fb3STimur Tabi e.mac[i][3], 486e2d31fb3STimur Tabi e.mac[i][4], 487e2d31fb3STimur Tabi e.mac[i][5]); 488e2d31fb3STimur Tabi sprintf(enetvar, i ? "eth%daddr" : "ethaddr", i); 489e2d31fb3STimur Tabi /* Only initialize environment variables that are blank 490e2d31fb3STimur Tabi * (i.e. have not yet been set) 491e2d31fb3STimur Tabi */ 492e2d31fb3STimur Tabi if (!getenv(enetvar)) 493e2d31fb3STimur Tabi setenv(enetvar, ethaddr); 4944ce91774SJon Loeliger } 495e2d31fb3STimur Tabi } 496e2d31fb3STimur Tabi 4972d04db08STimur Tabi #ifdef CONFIG_SYS_I2C_EEPROM_NXID 4982d04db08STimur Tabi printf("%c%c%c%c v%u\n", e.id[0], e.id[1], e.id[2], e.id[3], 4992d04db08STimur Tabi be32_to_cpu(e.version)); 5002d04db08STimur Tabi #else 5012d04db08STimur Tabi printf("%c%c%c%c\n", e.id[0], e.id[1], e.id[2], e.id[3]); 5022d04db08STimur Tabi #endif 5032d04db08STimur Tabi 504*f098c9c8STimur Tabi #ifdef CONFIG_SYS_I2C_EEPROM_NXID 505*f098c9c8STimur Tabi /* 506*f098c9c8STimur Tabi * Now we need to upconvert the data into v1 format. We do this last so 507*f098c9c8STimur Tabi * that at boot time, U-Boot will still say "NXID v0". 508*f098c9c8STimur Tabi */ 509*f098c9c8STimur Tabi if (e.version == 0) { 510*f098c9c8STimur Tabi e.version = NXID_VERSION; 511*f098c9c8STimur Tabi update_crc(); 512*f098c9c8STimur Tabi } 513*f098c9c8STimur Tabi #endif 514*f098c9c8STimur Tabi 5154ce91774SJon Loeliger return 0; 5164ce91774SJon Loeliger } 517e2d31fb3STimur Tabi 5186d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_I2C_EEPROM_CCID 519e2d31fb3STimur Tabi 520e2d31fb3STimur Tabi /** 521e2d31fb3STimur Tabi * get_cpu_board_revision - get the CPU board revision on 85xx boards 522e2d31fb3STimur Tabi * 523e2d31fb3STimur Tabi * Read the EEPROM to determine the board revision. 524e2d31fb3STimur Tabi * 525e2d31fb3STimur Tabi * This function is called before relocation, so we need to read a private 526e2d31fb3STimur Tabi * copy of the EEPROM into a local variable on the stack. 527e2d31fb3STimur Tabi * 5286d0f6bcfSJean-Christophe PLAGNIOL-VILLARD * Also, we assume that CONFIG_SYS_EEPROM_BUS_NUM == CONFIG_SYS_SPD_BUS_NUM. The global 5296d0f6bcfSJean-Christophe PLAGNIOL-VILLARD * variable i2c_bus_num must be compile-time initialized to CONFIG_SYS_SPD_BUS_NUM, 530e2d31fb3STimur Tabi * so that the SPD code will work. This means that all pre-relocation I2C 5316d0f6bcfSJean-Christophe PLAGNIOL-VILLARD * operations can only occur on the CONFIG_SYS_SPD_BUS_NUM bus. So if 5326d0f6bcfSJean-Christophe PLAGNIOL-VILLARD * CONFIG_SYS_EEPROM_BUS_NUM != CONFIG_SYS_SPD_BUS_NUM, then we can't read the EEPROM when 533e2d31fb3STimur Tabi * this function is called. Oh well. 534e2d31fb3STimur Tabi */ 535e2d31fb3STimur Tabi unsigned int get_cpu_board_revision(void) 536e2d31fb3STimur Tabi { 537e2d31fb3STimur Tabi struct board_eeprom { 538e2d31fb3STimur Tabi u32 id; /* 0x00 - 0x03 EEPROM Tag 'CCID' */ 539e2d31fb3STimur Tabi u8 major; /* 0x04 Board revision, major */ 540e2d31fb3STimur Tabi u8 minor; /* 0x05 Board revision, minor */ 541e2d31fb3STimur Tabi } be; 542e2d31fb3STimur Tabi 5436d0f6bcfSJean-Christophe PLAGNIOL-VILLARD i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0, CONFIG_SYS_I2C_EEPROM_ADDR_LEN, 544e2d31fb3STimur Tabi (void *)&be, sizeof(be)); 545e2d31fb3STimur Tabi 546e2d31fb3STimur Tabi if (be.id != (('C' << 24) | ('C' << 16) | ('I' << 8) | 'D')) 547e2d31fb3STimur Tabi return MPC85XX_CPU_BOARD_REV(0, 0); 548e2d31fb3STimur Tabi 549e2d31fb3STimur Tabi if ((be.major == 0xff) && (be.minor == 0xff)) 550e2d31fb3STimur Tabi return MPC85XX_CPU_BOARD_REV(0, 0); 551e2d31fb3STimur Tabi 552e46c7bfbSRafal Czubak return MPC85XX_CPU_BOARD_REV(be.major, be.minor); 553e2d31fb3STimur Tabi } 554e2d31fb3STimur Tabi #endif 555