blob: 6f151b0f717b1116ddbb37bc110562361fac8bf0 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Haiying Wang34c68782006-07-12 10:48:05 -04002/*
Timur Tabia2b41cb2011-02-09 02:00:09 +00003 * Copyright 2006, 2008-2009, 2011 Freescale Semiconductor
Haiying Wang34c68782006-07-12 10:48:05 -04004 * York Sun (yorksun@freescale.com)
5 * Haiying Wang (haiying.wang@freescale.com)
Timur Tabibdea8372008-06-19 17:56:11 -05006 * Timur Tabi (timur@freescale.com)
Haiying Wang34c68782006-07-12 10:48:05 -04007 */
8
9#include <common.h>
10#include <command.h>
Simon Glass5e6201b2019-08-01 09:46:51 -060011#include <env.h>
Haiying Wang34c68782006-07-12 10:48:05 -040012#include <i2c.h>
13#include <linux/ctype.h>
Simon Glass48b6c6b2019-11-14 12:57:16 -070014#include <u-boot/crc.h>
Haiying Wang34c68782006-07-12 10:48:05 -040015
Timur Tabi11e98e72010-09-30 15:36:50 -050016#ifdef CONFIG_SYS_I2C_EEPROM_CCID
Timur Tabibdea8372008-06-19 17:56:11 -050017#include "../common/eeprom.h"
Timur Tabi11e98e72010-09-30 15:36:50 -050018#define MAX_NUM_PORTS 8
19#endif
Haiying Wang34c68782006-07-12 10:48:05 -040020
Timur Tabi11e98e72010-09-30 15:36:50 -050021#ifdef CONFIG_SYS_I2C_EEPROM_NXID
Shengzhou Liu2fa20052013-09-13 14:46:01 +080022/* some boards with non-256-bytes EEPROM have special define */
23/* for MAX_NUM_PORTS in board-specific file */
24#ifndef MAX_NUM_PORTS
Ebony Zhu575cc912014-04-25 18:38:44 -050025#define MAX_NUM_PORTS 16
Shengzhou Liu2fa20052013-09-13 14:46:01 +080026#endif
Timur Tabi11e98e72010-09-30 15:36:50 -050027#define NXID_VERSION 1
28#endif
Haiying Wange5607542009-06-04 16:12:40 -040029
Timur Tabibdea8372008-06-19 17:56:11 -050030/**
31 * static eeprom: EEPROM layout for CCID or NXID formats
32 *
33 * See application note AN3638 for details.
34 */
35static struct __attribute__ ((__packed__)) eeprom {
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020036#ifdef CONFIG_SYS_I2C_EEPROM_CCID
Timur Tabibdea8372008-06-19 17:56:11 -050037 u8 id[4]; /* 0x00 - 0x03 EEPROM Tag 'CCID' */
38 u8 major; /* 0x04 Board revision, major */
39 u8 minor; /* 0x05 Board revision, minor */
40 u8 sn[10]; /* 0x06 - 0x0F Serial Number*/
41 u8 errata[2]; /* 0x10 - 0x11 Errata Level */
42 u8 date[6]; /* 0x12 - 0x17 Build Date */
43 u8 res_0[40]; /* 0x18 - 0x3f Reserved */
44 u8 mac_count; /* 0x40 Number of MAC addresses */
45 u8 mac_flag; /* 0x41 MAC table flags */
Haiying Wange5607542009-06-04 16:12:40 -040046 u8 mac[MAX_NUM_PORTS][6]; /* 0x42 - 0x71 MAC addresses */
Timur Tabibdea8372008-06-19 17:56:11 -050047 u32 crc; /* 0x72 CRC32 checksum */
48#endif
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020049#ifdef CONFIG_SYS_I2C_EEPROM_NXID
Timur Tabibdea8372008-06-19 17:56:11 -050050 u8 id[4]; /* 0x00 - 0x03 EEPROM Tag 'NXID' */
51 u8 sn[12]; /* 0x04 - 0x0F Serial Number */
52 u8 errata[5]; /* 0x10 - 0x14 Errata Level */
53 u8 date[6]; /* 0x15 - 0x1a Build Date */
54 u8 res_0; /* 0x1b Reserved */
55 u32 version; /* 0x1c - 0x1f NXID Version */
56 u8 tempcal[8]; /* 0x20 - 0x27 Temperature Calibration Factors */
57 u8 tempcalsys[2]; /* 0x28 - 0x29 System Temperature Calibration Factors */
58 u8 tempcalflags; /* 0x2a Temperature Calibration Flags */
59 u8 res_1[21]; /* 0x2b - 0x3f Reserved */
60 u8 mac_count; /* 0x40 Number of MAC addresses */
61 u8 mac_flag; /* 0x41 MAC table flags */
Ebony Zhu575cc912014-04-25 18:38:44 -050062 u8 mac[MAX_NUM_PORTS][6]; /* 0x42 - 0xa1 MAC addresses */
63 u8 res_2[90]; /* 0xa2 - 0xfb Reserved */
64 u32 crc; /* 0xfc - 0xff CRC32 checksum */
Timur Tabibdea8372008-06-19 17:56:11 -050065#endif
66} e;
67
68/* Set to 1 if we've read EEPROM into memory */
69static int has_been_read = 0;
70
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020071#ifdef CONFIG_SYS_I2C_EEPROM_NXID
Timur Tabibdea8372008-06-19 17:56:11 -050072/* Is this a valid NXID EEPROM? */
Kumar Gala4dc62452009-07-03 12:45:44 -050073#define is_valid ((e.id[0] == 'N') || (e.id[1] == 'X') || \
74 (e.id[2] == 'I') || (e.id[3] == 'D'))
Timur Tabibdea8372008-06-19 17:56:11 -050075#endif
76
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020077#ifdef CONFIG_SYS_I2C_EEPROM_CCID
Timur Tabibdea8372008-06-19 17:56:11 -050078/* Is this a valid CCID EEPROM? */
Kumar Gala4dc62452009-07-03 12:45:44 -050079#define is_valid ((e.id[0] == 'C') || (e.id[1] == 'C') || \
80 (e.id[2] == 'I') || (e.id[3] == 'D'))
Timur Tabibdea8372008-06-19 17:56:11 -050081#endif
82
83/**
84 * show_eeprom - display the contents of the EEPROM
85 */
86static void show_eeprom(void)
Haiying Wang34c68782006-07-12 10:48:05 -040087{
88 int i;
Timur Tabibdea8372008-06-19 17:56:11 -050089 unsigned int crc;
Haiying Wang34c68782006-07-12 10:48:05 -040090
Timur Tabibdea8372008-06-19 17:56:11 -050091 /* EEPROM tag ID, either CCID or NXID */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020092#ifdef CONFIG_SYS_I2C_EEPROM_NXID
Timur Tabibdea8372008-06-19 17:56:11 -050093 printf("ID: %c%c%c%c v%u\n", e.id[0], e.id[1], e.id[2], e.id[3],
Jaiprakash Singhe1029ef2015-05-28 14:54:03 +053094 be32_to_cpu(e.version));
Timur Tabibdea8372008-06-19 17:56:11 -050095#else
96 printf("ID: %c%c%c%c\n", e.id[0], e.id[1], e.id[2], e.id[3]);
97#endif
Haiying Wang34cf9592008-01-16 17:12:12 -050098
Timur Tabibdea8372008-06-19 17:56:11 -050099 /* Serial number */
100 printf("SN: %s\n", e.sn);
Haiying Wang34cf9592008-01-16 17:12:12 -0500101
Timur Tabibdea8372008-06-19 17:56:11 -0500102 /* Errata level. */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200103#ifdef CONFIG_SYS_I2C_EEPROM_NXID
Timur Tabibdea8372008-06-19 17:56:11 -0500104 printf("Errata: %s\n", e.errata);
105#else
106 printf("Errata: %c%c\n",
107 e.errata[0] ? e.errata[0] : '.',
108 e.errata[1] ? e.errata[1] : '.');
109#endif
Haiying Wang34cf9592008-01-16 17:12:12 -0500110
Timur Tabibdea8372008-06-19 17:56:11 -0500111 /* Build date, BCD date values, as YYMMDDhhmmss */
112 printf("Build date: 20%02x/%02x/%02x %02x:%02x:%02x %s\n",
113 e.date[0], e.date[1], e.date[2],
114 e.date[3] & 0x7F, e.date[4], e.date[5],
115 e.date[3] & 0x80 ? "PM" : "");
Haiying Wang34cf9592008-01-16 17:12:12 -0500116
Timur Tabibdea8372008-06-19 17:56:11 -0500117 /* Show MAC addresses */
Masahiro Yamadadb204642014-11-07 03:03:31 +0900118 for (i = 0; i < min(e.mac_count, (u8)MAX_NUM_PORTS); i++) {
Haiying Wange5607542009-06-04 16:12:40 -0400119
Timur Tabibdea8372008-06-19 17:56:11 -0500120 u8 *p = e.mac[i];
Haiying Wang34cf9592008-01-16 17:12:12 -0500121
Timur Tabibdea8372008-06-19 17:56:11 -0500122 printf("Eth%u: %02x:%02x:%02x:%02x:%02x:%02x\n", i,
123 p[0], p[1], p[2], p[3], p[4], p[5]);
124 }
Haiying Wang34cf9592008-01-16 17:12:12 -0500125
Timur Tabibdea8372008-06-19 17:56:11 -0500126 crc = crc32(0, (void *)&e, sizeof(e) - 4);
Haiying Wang34c68782006-07-12 10:48:05 -0400127
Timur Tabibdea8372008-06-19 17:56:11 -0500128 if (crc == be32_to_cpu(e.crc))
129 printf("CRC: %08x\n", be32_to_cpu(e.crc));
130 else
131 printf("CRC: %08x (should be %08x)\n",
132 be32_to_cpu(e.crc), crc);
Haiying Wang34c68782006-07-12 10:48:05 -0400133
Timur Tabibdea8372008-06-19 17:56:11 -0500134#ifdef DEBUG
135 printf("EEPROM dump: (0x%x bytes)\n", sizeof(e));
136 for (i = 0; i < sizeof(e); i++) {
137 if ((i % 16) == 0)
138 printf("%02X: ", i);
139 printf("%02X ", ((u8 *)&e)[i]);
140 if (((i % 16) == 15) || (i == sizeof(e) - 1))
141 printf("\n");
142 }
143#endif
Haiying Wang34c68782006-07-12 10:48:05 -0400144}
145
Timur Tabibdea8372008-06-19 17:56:11 -0500146/**
147 * read_eeprom - read the EEPROM into memory
148 */
149static int read_eeprom(void)
Haiying Wang34c68782006-07-12 10:48:05 -0400150{
Timur Tabibdea8372008-06-19 17:56:11 -0500151 int ret;
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200152#ifdef CONFIG_SYS_EEPROM_BUS_NUM
Chuanhua Han37c2c5e2019-07-10 21:00:20 +0800153#ifndef CONFIG_DM_I2C
Timur Tabibdea8372008-06-19 17:56:11 -0500154 unsigned int bus;
155#endif
Chuanhua Han37c2c5e2019-07-10 21:00:20 +0800156#endif
Haiying Wang34c68782006-07-12 10:48:05 -0400157
Timur Tabibdea8372008-06-19 17:56:11 -0500158 if (has_been_read)
159 return 0;
Haiying Wang34c68782006-07-12 10:48:05 -0400160
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200161#ifdef CONFIG_SYS_EEPROM_BUS_NUM
Chuanhua Han37c2c5e2019-07-10 21:00:20 +0800162#ifndef CONFIG_DM_I2C
Timur Tabibdea8372008-06-19 17:56:11 -0500163 bus = i2c_get_bus_num();
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200164 i2c_set_bus_num(CONFIG_SYS_EEPROM_BUS_NUM);
Timur Tabibdea8372008-06-19 17:56:11 -0500165#endif
Chuanhua Han37c2c5e2019-07-10 21:00:20 +0800166#endif
Timur Tabibdea8372008-06-19 17:56:11 -0500167
Chuanhua Han37c2c5e2019-07-10 21:00:20 +0800168#ifndef CONFIG_DM_I2C
169 ret = i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0,
170 CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
171 (void *)&e, sizeof(e));
172#else
173 struct udevice *dev;
174#ifdef CONFIG_SYS_EEPROM_BUS_NUM
175 ret = i2c_get_chip_for_busnum(CONFIG_SYS_EEPROM_BUS_NUM,
176 CONFIG_SYS_I2C_EEPROM_ADDR, 1, &dev);
177#else
178 ret = i2c_get_chip_for_busnum(0, CONFIG_SYS_I2C_EEPROM_ADDR, 1, &dev);
179#endif
180 if (!ret)
181 ret = dm_i2c_read(dev, 0, (void *)&e, sizeof(e));
182#endif
Timur Tabibdea8372008-06-19 17:56:11 -0500183
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200184#ifdef CONFIG_SYS_EEPROM_BUS_NUM
Chuanhua Han37c2c5e2019-07-10 21:00:20 +0800185#ifndef CONFIG_DM_I2C
Timur Tabibdea8372008-06-19 17:56:11 -0500186 i2c_set_bus_num(bus);
187#endif
Chuanhua Han37c2c5e2019-07-10 21:00:20 +0800188#endif
Timur Tabibdea8372008-06-19 17:56:11 -0500189
190#ifdef DEBUG
191 show_eeprom();
192#endif
193
194 has_been_read = (ret == 0) ? 1 : 0;
195
196 return ret;
Haiying Wang34c68782006-07-12 10:48:05 -0400197}
198
Timur Tabibdea8372008-06-19 17:56:11 -0500199/**
Timur Tabi13c312b2009-08-28 16:56:45 -0500200 * update_crc - update the CRC
201 *
202 * This function should be called after each update to the EEPROM structure,
203 * to make sure the CRC is always correct.
204 */
205static void update_crc(void)
206{
207 u32 crc;
208
209 crc = crc32(0, (void *)&e, sizeof(e) - 4);
210 e.crc = cpu_to_be32(crc);
211}
212
213/**
Timur Tabibdea8372008-06-19 17:56:11 -0500214 * prog_eeprom - write the EEPROM from memory
215 */
216static int prog_eeprom(void)
Haiying Wang34c68782006-07-12 10:48:05 -0400217{
Timur Tabia58e8802010-08-02 13:03:23 -0500218 int ret = 0;
Anton Vorontsovc33e3b82009-09-02 02:17:24 +0400219 int i;
Timur Tabibdea8372008-06-19 17:56:11 -0500220 void *p;
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200221#ifdef CONFIG_SYS_EEPROM_BUS_NUM
Chuanhua Han37c2c5e2019-07-10 21:00:20 +0800222#ifndef CONFIG_DM_I2C
Timur Tabibdea8372008-06-19 17:56:11 -0500223 unsigned int bus;
224#endif
Chuanhua Han37c2c5e2019-07-10 21:00:20 +0800225#endif
Haiying Wang34c68782006-07-12 10:48:05 -0400226
Timur Tabibdea8372008-06-19 17:56:11 -0500227 /* Set the reserved values to 0xFF */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200228#ifdef CONFIG_SYS_I2C_EEPROM_NXID
Timur Tabibdea8372008-06-19 17:56:11 -0500229 e.res_0 = 0xFF;
230 memset(e.res_1, 0xFF, sizeof(e.res_1));
231#else
232 memset(e.res_0, 0xFF, sizeof(e.res_0));
233#endif
Timur Tabi13c312b2009-08-28 16:56:45 -0500234 update_crc();
Timur Tabibdea8372008-06-19 17:56:11 -0500235
Chuanhua Han37c2c5e2019-07-10 21:00:20 +0800236#ifndef CONFIG_DM_I2C
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200237#ifdef CONFIG_SYS_EEPROM_BUS_NUM
Timur Tabibdea8372008-06-19 17:56:11 -0500238 bus = i2c_get_bus_num();
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200239 i2c_set_bus_num(CONFIG_SYS_EEPROM_BUS_NUM);
Timur Tabibdea8372008-06-19 17:56:11 -0500240#endif
Chuanhua Han37c2c5e2019-07-10 21:00:20 +0800241#endif
Timur Tabibdea8372008-06-19 17:56:11 -0500242
Timur Tabia58e8802010-08-02 13:03:23 -0500243 /*
244 * The AT24C02 datasheet says that data can only be written in page
245 * mode, which means 8 bytes at a time, and it takes up to 5ms to
246 * complete a given write.
247 */
Timur Tabi13c312b2009-08-28 16:56:45 -0500248 for (i = 0, p = &e; i < sizeof(e); i += 8, p += 8) {
Chuanhua Han37c2c5e2019-07-10 21:00:20 +0800249#ifndef CONFIG_DM_I2C
250 ret = i2c_write(CONFIG_SYS_I2C_EEPROM_ADDR, i,
251 CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
Masahiro Yamadadb204642014-11-07 03:03:31 +0900252 p, min((int)(sizeof(e) - i), 8));
Chuanhua Han37c2c5e2019-07-10 21:00:20 +0800253#else
254 struct udevice *dev;
255#ifdef CONFIG_SYS_EEPROM_BUS_NUM
256 ret = i2c_get_chip_for_busnum(CONFIG_SYS_EEPROM_BUS_NUM,
257 CONFIG_SYS_I2C_EEPROM_ADDR,
258 CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
259 &dev);
260#else
261 ret = i2c_get_chip_for_busnum(0, CONFIG_SYS_I2C_EEPROM_ADDR,
262 CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
263 &dev);
264#endif
265 if (!ret)
266 ret = dm_i2c_write(dev, i, p, min((int)(sizeof(e) - i),
267 8));
268#endif
Haiying Wang34c68782006-07-12 10:48:05 -0400269 if (ret)
270 break;
Timur Tabibdea8372008-06-19 17:56:11 -0500271 udelay(5000); /* 5ms write cycle timing */
Haiying Wang34c68782006-07-12 10:48:05 -0400272 }
Timur Tabibdea8372008-06-19 17:56:11 -0500273
Timur Tabia58e8802010-08-02 13:03:23 -0500274 if (!ret) {
275 /* Verify the write by reading back the EEPROM and comparing */
276 struct eeprom e2;
277
Chuanhua Han37c2c5e2019-07-10 21:00:20 +0800278#ifndef CONFIG_DM_I2C
Timur Tabia58e8802010-08-02 13:03:23 -0500279 ret = i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0,
Chuanhua Han37c2c5e2019-07-10 21:00:20 +0800280 CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
281 (void *)&e2, sizeof(e2));
282#else
283 struct udevice *dev;
284#ifdef CONFIG_SYS_EEPROM_BUS_NUM
285 ret = i2c_get_chip_for_busnum(CONFIG_SYS_EEPROM_BUS_NUM,
286 CONFIG_SYS_I2C_EEPROM_ADDR,
287 CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
288 &dev);
289#else
290 ret = i2c_get_chip_for_busnum(0, CONFIG_SYS_I2C_EEPROM_ADDR,
291 CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
292 &dev);
293#endif
294 if (!ret)
295 ret = dm_i2c_read(dev, 0, (void *)&e2, sizeof(e2));
296#endif
Timur Tabia58e8802010-08-02 13:03:23 -0500297 if (!ret && memcmp(&e, &e2, sizeof(e)))
298 ret = -1;
299 }
300
Chuanhua Han37c2c5e2019-07-10 21:00:20 +0800301#ifndef CONFIG_DM_I2C
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200302#ifdef CONFIG_SYS_EEPROM_BUS_NUM
Timur Tabibdea8372008-06-19 17:56:11 -0500303 i2c_set_bus_num(bus);
304#endif
Chuanhua Han37c2c5e2019-07-10 21:00:20 +0800305#endif
Timur Tabibdea8372008-06-19 17:56:11 -0500306
Haiying Wang34c68782006-07-12 10:48:05 -0400307 if (ret) {
308 printf("Programming failed.\n");
Timur Tabia58e8802010-08-02 13:03:23 -0500309 has_been_read = 0;
Haiying Wang34c68782006-07-12 10:48:05 -0400310 return -1;
Haiying Wang34c68782006-07-12 10:48:05 -0400311 }
Timur Tabibdea8372008-06-19 17:56:11 -0500312
313 printf("Programming passed.\n");
Haiying Wang34c68782006-07-12 10:48:05 -0400314 return 0;
315}
316
Timur Tabibdea8372008-06-19 17:56:11 -0500317/**
318 * h2i - converts hex character into a number
319 *
320 * This function takes a hexadecimal character (e.g. '7' or 'C') and returns
321 * the integer equivalent.
322 */
323static inline u8 h2i(char p)
324{
325 if ((p >= '0') && (p <= '9'))
326 return p - '0';
327
328 if ((p >= 'A') && (p <= 'F'))
329 return (p - 'A') + 10;
330
331 if ((p >= 'a') && (p <= 'f'))
332 return (p - 'a') + 10;
333
334 return 0;
335}
336
337/**
338 * set_date - stores the build date into the EEPROM
339 *
340 * This function takes a pointer to a string in the format "YYMMDDhhmmss"
341 * (2-digit year, 2-digit month, etc), converts it to a 6-byte BCD string,
342 * and stores it in the build date field of the EEPROM local copy.
343 */
344static void set_date(const char *string)
345{
346 unsigned int i;
347
348 if (strlen(string) != 12) {
349 printf("Usage: mac date YYMMDDhhmmss\n");
350 return;
351 }
352
353 for (i = 0; i < 6; i++)
354 e.date[i] = h2i(string[2 * i]) << 4 | h2i(string[2 * i + 1]);
Timur Tabi13c312b2009-08-28 16:56:45 -0500355
356 update_crc();
Timur Tabibdea8372008-06-19 17:56:11 -0500357}
358
359/**
360 * set_mac_address - stores a MAC address into the EEPROM
361 *
362 * This function takes a pointer to MAC address string
363 * (i.e."XX:XX:XX:XX:XX:XX", where "XX" is a two-digit hex number) and
364 * stores it in one of the MAC address fields of the EEPROM local copy.
365 */
366static void set_mac_address(unsigned int index, const char *string)
367{
368 char *p = (char *) string;
369 unsigned int i;
370
Timur Tabi11e98e72010-09-30 15:36:50 -0500371 if ((index >= MAX_NUM_PORTS) || !string) {
Timur Tabibdea8372008-06-19 17:56:11 -0500372 printf("Usage: mac <n> XX:XX:XX:XX:XX:XX\n");
373 return;
374 }
375
376 for (i = 0; *p && (i < 6); i++) {
377 e.mac[index][i] = simple_strtoul(p, &p, 16);
378 if (*p == ':')
379 p++;
380 }
Timur Tabi13c312b2009-08-28 16:56:45 -0500381
382 update_crc();
Timur Tabibdea8372008-06-19 17:56:11 -0500383}
384
Wolfgang Denk6262d0212010-06-28 22:00:46 +0200385int do_mac(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
Haiying Wang34c68782006-07-12 10:48:05 -0400386{
Timur Tabibdea8372008-06-19 17:56:11 -0500387 char cmd;
Haiying Wang34c68782006-07-12 10:48:05 -0400388
Timur Tabibdea8372008-06-19 17:56:11 -0500389 if (argc == 1) {
390 show_eeprom();
391 return 0;
392 }
393
394 cmd = argv[1][0];
395
396 if (cmd == 'r') {
397 read_eeprom();
398 return 0;
399 }
Haiying Wang34c68782006-07-12 10:48:05 -0400400
Timur Tabi13c312b2009-08-28 16:56:45 -0500401 if (cmd == 'i') {
402#ifdef CONFIG_SYS_I2C_EEPROM_NXID
403 memcpy(e.id, "NXID", sizeof(e.id));
Jaiprakash Singhe1029ef2015-05-28 14:54:03 +0530404 e.version = cpu_to_be32(NXID_VERSION);
Timur Tabi13c312b2009-08-28 16:56:45 -0500405#else
406 memcpy(e.id, "CCID", sizeof(e.id));
407#endif
Timur Tabi2f9f65f2011-02-09 13:40:51 -0600408 update_crc();
Timur Tabibdea8372008-06-19 17:56:11 -0500409 return 0;
410 }
411
412 if (!is_valid) {
413 printf("Please read the EEPROM ('r') and/or set the ID ('i') first.\n");
414 return 0;
415 }
416
417 if (argc == 2) {
Haiying Wang34c68782006-07-12 10:48:05 -0400418 switch (cmd) {
Jon Loeliger4fbb09c2006-08-22 12:25:27 -0500419 case 's': /* save */
Timur Tabibdea8372008-06-19 17:56:11 -0500420 prog_eeprom();
Jon Loeliger4fbb09c2006-08-22 12:25:27 -0500421 break;
Jon Loeliger4fbb09c2006-08-22 12:25:27 -0500422 default:
Wolfgang Denk3b683112010-07-17 01:06:04 +0200423 return cmd_usage(cmdtp);
Haiying Wang34c68782006-07-12 10:48:05 -0400424 }
Timur Tabibdea8372008-06-19 17:56:11 -0500425
426 return 0;
427 }
428
429 /* We know we have at least one parameter */
430
431 switch (cmd) {
432 case 'n': /* serial number */
433 memset(e.sn, 0, sizeof(e.sn));
434 strncpy((char *)e.sn, argv[2], sizeof(e.sn) - 1);
Timur Tabi13c312b2009-08-28 16:56:45 -0500435 update_crc();
Timur Tabibdea8372008-06-19 17:56:11 -0500436 break;
437 case 'e': /* errata */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200438#ifdef CONFIG_SYS_I2C_EEPROM_NXID
Timur Tabibdea8372008-06-19 17:56:11 -0500439 memset(e.errata, 0, 5);
440 strncpy((char *)e.errata, argv[2], 4);
441#else
442 e.errata[0] = argv[2][0];
443 e.errata[1] = argv[2][1];
444#endif
Timur Tabi13c312b2009-08-28 16:56:45 -0500445 update_crc();
Timur Tabibdea8372008-06-19 17:56:11 -0500446 break;
447 case 'd': /* date BCD format YYMMDDhhmmss */
448 set_date(argv[2]);
449 break;
450 case 'p': /* MAC table size */
451 e.mac_count = simple_strtoul(argv[2], NULL, 16);
Timur Tabi13c312b2009-08-28 16:56:45 -0500452 update_crc();
Timur Tabibdea8372008-06-19 17:56:11 -0500453 break;
Timur Tabi11e98e72010-09-30 15:36:50 -0500454 case '0' ... '9': /* "mac 0" through "mac 22" */
455 set_mac_address(simple_strtoul(argv[1], NULL, 10), argv[2]);
Timur Tabibdea8372008-06-19 17:56:11 -0500456 break;
457 case 'h': /* help */
458 default:
Wolfgang Denk3b683112010-07-17 01:06:04 +0200459 return cmd_usage(cmdtp);
Haiying Wang34c68782006-07-12 10:48:05 -0400460 }
Timur Tabibdea8372008-06-19 17:56:11 -0500461
Haiying Wang34c68782006-07-12 10:48:05 -0400462 return 0;
463}
464
Timur Tabibdea8372008-06-19 17:56:11 -0500465/**
466 * mac_read_from_eeprom - read the MAC addresses from EEPROM
467 *
468 * This function reads the MAC addresses from EEPROM and sets the
469 * appropriate environment variables for each one read.
470 *
471 * The environment variables are only set if they haven't been set already.
472 * This ensures that any user-saved variables are never overwritten.
473 *
474 * This function must be called after relocation.
Timur Tabia2b41cb2011-02-09 02:00:09 +0000475 *
476 * For NXID v1 EEPROMs, we support loading and up-converting the older NXID v0
477 * format. In a v0 EEPROM, there are only eight MAC addresses and the CRC is
478 * located at a different offset.
Timur Tabibdea8372008-06-19 17:56:11 -0500479 */
Haiying Wang34c68782006-07-12 10:48:05 -0400480int mac_read_from_eeprom(void)
481{
Timur Tabibdea8372008-06-19 17:56:11 -0500482 unsigned int i;
Timur Tabia2b41cb2011-02-09 02:00:09 +0000483 u32 crc, crc_offset = offsetof(struct eeprom, crc);
484 u32 *crcp; /* Pointer to the CRC in the data read from the EEPROM */
Timur Tabi13c312b2009-08-28 16:56:45 -0500485
486 puts("EEPROM: ");
Haiying Wang34c68782006-07-12 10:48:05 -0400487
Timur Tabibdea8372008-06-19 17:56:11 -0500488 if (read_eeprom()) {
Haiying Wang34c68782006-07-12 10:48:05 -0400489 printf("Read failed.\n");
York Sun9215eff2014-04-30 14:43:46 -0700490 return 0;
Haiying Wang34c68782006-07-12 10:48:05 -0400491 }
492
Timur Tabibdea8372008-06-19 17:56:11 -0500493 if (!is_valid) {
Timur Tabi13c312b2009-08-28 16:56:45 -0500494 printf("Invalid ID (%02x %02x %02x %02x)\n",
495 e.id[0], e.id[1], e.id[2], e.id[3]);
York Sun9215eff2014-04-30 14:43:46 -0700496 return 0;
Timur Tabibdea8372008-06-19 17:56:11 -0500497 }
498
Timur Tabia2b41cb2011-02-09 02:00:09 +0000499#ifdef CONFIG_SYS_I2C_EEPROM_NXID
500 /*
501 * If we've read an NXID v0 EEPROM, then we need to set the CRC offset
502 * to where it is in v0.
503 */
504 if (e.version == 0)
505 crc_offset = 0x72;
506#endif
507
508 crc = crc32(0, (void *)&e, crc_offset);
509 crcp = (void *)&e + crc_offset;
510 if (crc != be32_to_cpu(*crcp)) {
Timur Tabi13c312b2009-08-28 16:56:45 -0500511 printf("CRC mismatch (%08x != %08x)\n", crc, be32_to_cpu(e.crc));
York Sun9215eff2014-04-30 14:43:46 -0700512 return 0;
Haiying Wange5607542009-06-04 16:12:40 -0400513 }
514
Timur Tabia2b41cb2011-02-09 02:00:09 +0000515#ifdef CONFIG_SYS_I2C_EEPROM_NXID
516 /*
517 * MAC address #9 in v1 occupies the same position as the CRC in v0.
518 * Erase it so that it's not mistaken for a MAC address. We'll
519 * update the CRC later.
520 */
521 if (e.version == 0)
522 memset(e.mac[8], 0xff, 6);
523#endif
524
Masahiro Yamadadb204642014-11-07 03:03:31 +0900525 for (i = 0; i < min(e.mac_count, (u8)MAX_NUM_PORTS); i++) {
Timur Tabibdea8372008-06-19 17:56:11 -0500526 if (memcmp(&e.mac[i], "\0\0\0\0\0\0", 6) &&
527 memcmp(&e.mac[i], "\xFF\xFF\xFF\xFF\xFF\xFF", 6)) {
528 char ethaddr[18];
529 char enetvar[9];
530
531 sprintf(ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X",
532 e.mac[i][0],
533 e.mac[i][1],
534 e.mac[i][2],
535 e.mac[i][3],
536 e.mac[i][4],
537 e.mac[i][5]);
538 sprintf(enetvar, i ? "eth%daddr" : "ethaddr", i);
539 /* Only initialize environment variables that are blank
540 * (i.e. have not yet been set)
541 */
Simon Glass64b723f2017-08-03 12:22:12 -0600542 if (!env_get(enetvar))
Simon Glass6a38e412017-08-03 12:22:09 -0600543 env_set(enetvar, ethaddr);
Timur Tabibdea8372008-06-19 17:56:11 -0500544 }
545 }
546
Timur Tabi13c312b2009-08-28 16:56:45 -0500547#ifdef CONFIG_SYS_I2C_EEPROM_NXID
548 printf("%c%c%c%c v%u\n", e.id[0], e.id[1], e.id[2], e.id[3],
Jaiprakash Singhe1029ef2015-05-28 14:54:03 +0530549 be32_to_cpu(e.version));
Timur Tabi13c312b2009-08-28 16:56:45 -0500550#else
551 printf("%c%c%c%c\n", e.id[0], e.id[1], e.id[2], e.id[3]);
552#endif
553
Timur Tabia2b41cb2011-02-09 02:00:09 +0000554#ifdef CONFIG_SYS_I2C_EEPROM_NXID
555 /*
556 * Now we need to upconvert the data into v1 format. We do this last so
557 * that at boot time, U-Boot will still say "NXID v0".
558 */
559 if (e.version == 0) {
Jaiprakash Singhe1029ef2015-05-28 14:54:03 +0530560 e.version = cpu_to_be32(NXID_VERSION);
Timur Tabia2b41cb2011-02-09 02:00:09 +0000561 update_crc();
562 }
563#endif
564
Haiying Wang34c68782006-07-12 10:48:05 -0400565 return 0;
566}
Timur Tabibdea8372008-06-19 17:56:11 -0500567
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200568#ifdef CONFIG_SYS_I2C_EEPROM_CCID
Timur Tabibdea8372008-06-19 17:56:11 -0500569
570/**
571 * get_cpu_board_revision - get the CPU board revision on 85xx boards
572 *
573 * Read the EEPROM to determine the board revision.
574 *
575 * This function is called before relocation, so we need to read a private
576 * copy of the EEPROM into a local variable on the stack.
577 *
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200578 * Also, we assume that CONFIG_SYS_EEPROM_BUS_NUM == CONFIG_SYS_SPD_BUS_NUM. The global
579 * variable i2c_bus_num must be compile-time initialized to CONFIG_SYS_SPD_BUS_NUM,
Timur Tabibdea8372008-06-19 17:56:11 -0500580 * so that the SPD code will work. This means that all pre-relocation I2C
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200581 * operations can only occur on the CONFIG_SYS_SPD_BUS_NUM bus. So if
582 * CONFIG_SYS_EEPROM_BUS_NUM != CONFIG_SYS_SPD_BUS_NUM, then we can't read the EEPROM when
Timur Tabibdea8372008-06-19 17:56:11 -0500583 * this function is called. Oh well.
584 */
585unsigned int get_cpu_board_revision(void)
586{
587 struct board_eeprom {
588 u32 id; /* 0x00 - 0x03 EEPROM Tag 'CCID' */
589 u8 major; /* 0x04 Board revision, major */
590 u8 minor; /* 0x05 Board revision, minor */
591 } be;
592
Chuanhua Han37c2c5e2019-07-10 21:00:20 +0800593#ifndef CONFIG_DM_I2C
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200594 i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0, CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
Timur Tabibdea8372008-06-19 17:56:11 -0500595 (void *)&be, sizeof(be));
Chuanhua Han37c2c5e2019-07-10 21:00:20 +0800596#else
597 struct udevice *dev;
598#ifdef CONFIG_SYS_EEPROM_BUS_NUM
599 ret = i2c_get_chip_for_busnum(CONFIG_SYS_EEPROM_BUS_NUM,
600 CONFIG_SYS_I2C_EEPROM_ADDR,
601 CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
602 &dev);
603#else
604 ret = i2c_get_chip_for_busnum(0, CONFIG_SYS_I2C_EEPROM_ADDR,
605 CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
606 &dev)
607#endif
608 if (!ret)
609 dm_i2c_read(dev, 0, (void *)&be, sizeof(be));
610#endif
Timur Tabibdea8372008-06-19 17:56:11 -0500611
612 if (be.id != (('C' << 24) | ('C' << 16) | ('I' << 8) | 'D'))
613 return MPC85XX_CPU_BOARD_REV(0, 0);
614
615 if ((be.major == 0xff) && (be.minor == 0xff))
616 return MPC85XX_CPU_BOARD_REV(0, 0);
617
Rafal Czubak5c50d142008-10-08 13:41:30 +0200618 return MPC85XX_CPU_BOARD_REV(be.major, be.minor);
Timur Tabibdea8372008-06-19 17:56:11 -0500619}
Timur Tabibdea8372008-06-19 17:56:11 -0500620#endif