From: Heiko Schocher <hs@denx.de>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH] mgcoge, mgsuvd: added support for the IVM EEprom.
Date: Mon, 29 Sep 2008 09:56:49 +0200 [thread overview]
Message-ID: <48E08A41.1090708@denx.de> (raw)
The EEprom contains some Manufacturerinformation,
which are read from u-boot at boot time, and saved
in same Environmentvars.
Signed-off-by: Heiko Schocher <hs@denx.de>
---
board/keymile/common/common.c | 285 +++++++++++++++++++++++++++++++++++++++++
include/configs/mgcoge.h | 5 +
include/configs/mgsuvd.h | 5 +
lib_ppc/board.c | 6 +
4 files changed, 301 insertions(+), 0 deletions(-)
diff --git a/board/keymile/common/common.c b/board/keymile/common/common.c
index a6ed379..25c5900 100644
--- a/board/keymile/common/common.c
+++ b/board/keymile/common/common.c
@@ -38,6 +38,291 @@
extern int i2c_mgsuvd_read (void);
#endif
+int ivm_calc_crc (unsigned char *buf, int len)
+{
+ const unsigned short cCrc16Table[16] = {
+ 0x0000, 0xCC01, 0xD801, 0x1400,
+ 0xF001, 0x3C00, 0x2800, 0xE401,
+ 0xA001, 0x6C00, 0x7800, 0xB401,
+ 0x5000, 0x9C01, 0x8801, 0x4400};
+
+ unsigned short crc = 0; /* final result */
+ unsigned short r1 = 0; /* temp */
+ unsigned char byte = 0; /* input buffer */
+ int i;
+
+ /* calculate CRC from array data */
+ for (i = 0; i < len; i++) {
+ byte = buf[i];
+
+ /* lower 4 bits */
+ r1 = cCrc16Table[crc & 0xF];
+ crc = ((crc) >> 4) & 0x0FFF;
+ crc = crc ^ r1 ^ cCrc16Table[byte & 0xF];
+
+ /* upper 4 bits */
+ r1 = cCrc16Table[crc & 0xF];
+ crc = (crc >> 4) & 0x0FFF;
+ crc = crc ^ r1 ^ cCrc16Table[(byte >> 4) & 0xF];
+ }
+ return crc;
+}
+
+
+static int ivm_get_value (unsigned char *buf, int len, char *name, int off, int check)
+{
+ unsigned short val;
+ unsigned char valbuf[30];
+
+ if ((buf[off + 0] != buf[off + 2]) && (buf[off + 2] != buf[off + 4])) {
+ printf ("%s Error corrupted %s\n", __FUNCTION__, name);
+ val = -1;
+ } else {
+ val = buf[off + 0] + (buf[off + 1] << 8);
+ if ((val == 0) && (check == 1))
+ val = -1;
+ }
+ sprintf ((char *)valbuf, "%x", val);
+ setenv (name, (char *)valbuf);
+ return val;
+}
+
+#define BTChar unsigned char
+
+#define INVENTORYBLOCKSIZE 0x100
+#define INVENTORYDATAADDRESS 0x21
+#define INVENTORYDATASIZE (INVENTORYBLOCKSIZE - INVENTORYDATAADDRESS - 3)
+typedef enum {
+ eSymbolShortText = 0, /* Symbol;ShortText */
+ eManufId = 1, /* ManufacturerId */
+ eManufSerialNumber = 2, /* ManufacturerSerialNumber */
+ eManufPartNumber = 3, /* ManufacturerPartNumber */
+ eManufBuildState = 4, /* ManufacturerBuildState */
+ eSuplierPartNumber = 5, /* SuplierPartNumber */
+ eDeliveryDate = 6, /* DeliveryDate */
+ eSupplierBuildState = 7, /* SupplierBuildState */
+ eCustomerId = 8, /* CustomerId */
+ eCustomerProdId = 9, /* CustomerProdId */
+ eChangeHistory = 10, /* ChangeHistory (not used) */
+ eSymbolOnly
+} InventoryData;
+
+static char toAscii(char c)
+{
+ return (c<' ' || c>'~') ? '.' : c;
+}
+
+static int ivm_findInventoryString (InventoryData aType, BTChar* const aString,
+ unsigned long maxLength, unsigned char *buf)
+{
+ int xcode = 0;
+ BTChar cr = '\r';
+ /* Semikolon char */
+ BTChar sc = ';';
+ /* Number of CR found */
+ unsigned long crFound = 0;
+ /* Current address */
+ unsigned long address = INVENTORYDATAADDRESS;
+ /* String length */
+ unsigned long strSize = 0;
+ /* Number of CR to skip */
+ unsigned long nbrOfCR = aType;
+ /* Semicolon to end */
+ int endWithSemikolon = 0;
+
+ /* initialise string */
+ memset(aString, '\0', maxLength);
+
+ switch (aType)
+ {
+ case eSymbolOnly:
+ nbrOfCR = 0;
+ endWithSemikolon = 1;
+ break;
+ default:
+ nbrOfCR = aType;
+ endWithSemikolon = 0;
+ }
+
+ /* Look for the requested number of CR. */
+ while ((crFound != nbrOfCR) && (address < INVENTORYDATASIZE))
+ {
+ if ((buf[address] == cr)) {
+ crFound++;
+ }
+ address++;
+ }
+
+ /* the expected number of CR was found until the end of the IVM
+ * content --> fill string */
+ if (address < INVENTORYDATASIZE)
+ {
+ /* Copy the IVM string in the corresponding string */
+ for (; (buf[address] != cr) && /* not cr found */
+ ((buf[address] != sc) || (!endWithSemikolon)) && /* not semikolon found */
+ (strSize < (maxLength-1) &&
+ (address < INVENTORYDATASIZE)); address++)
+ {
+ strSize += sprintf((char *)aString + strSize, "%c", toAscii(buf[address]));
+ }
+
+ /* copy phase is done: check if everything is ok. If not, the inventory
+ * data is most probably corrupted: tell the world there is a problem! */
+ if (address == INVENTORYDATASIZE)
+ {
+ xcode = -1;
+ printf ("Error end of string not found\n");
+ } else if ((strSize >= (maxLength-1)) && (buf[address] != cr)) {
+ xcode = -1;
+ printf ("string too long till next CR\n");
+ }
+ } else {
+ /* some CR are missing... the inventory data is most probably corrupted */
+ xcode = -1;
+ printf ("not enough cr found\n");
+ }
+ return xcode;
+}
+
+#define GET_STRING(name, which, len) \
+ if (ivm_findInventoryString (which, valbuf, len, buf) == 0) { \
+ setenv (name, (char *)valbuf); \
+ }
+
+static int ivm_check_crc (unsigned char *buf, int block)
+{
+ unsigned long crc;
+ unsigned long crceeprom;
+
+ crc = ivm_calc_crc (buf, CFG_IVM_EEPROM_PAGE_LEN - 2);
+ crceeprom = (buf[CFG_IVM_EEPROM_PAGE_LEN - 1] + \
+ buf[CFG_IVM_EEPROM_PAGE_LEN - 2] * 256);
+ if (crc != crceeprom) {
+ printf ("Error CRC Block: %d EEprom: calculated: %lx EEprom: %lx\n",
+ block, crc, crceeprom);
+ return -1;
+ }
+ return 0;
+}
+
+static int ivm_analyse_block2 (unsigned char *buf, int len)
+{
+ unsigned char valbuf[CFG_IVM_EEPROM_PAGE_LEN];
+ unsigned long nbrsAdrs;
+
+ /* IVM_MacAddress */
+ sprintf ((char *)valbuf, "%02X:%02X:%02X:%02X:%02X:%02X",
+ buf[1],
+ buf[2],
+ buf[3],
+ buf[4],
+ buf[5],
+ buf[6]);
+ setenv ("IVM_MacAddress", (char *)valbuf);
+ if (getenv ("ethaddr") == NULL)
+ setenv ((char *)"ethaddr", (char *)valbuf);
+ /* IVM_MacCount */
+ nbrsAdrs = (buf[10] << 24) +
+ (buf[11] << 16) +
+ (buf[12] << 8) +
+ buf[13];
+ if (nbrsAdrs == 0xffffffff)
+ nbrsAdrs = 1;
+ sprintf ((char *)valbuf, "%lx", nbrsAdrs);
+ setenv ("IVM_MacCount", (char *)valbuf);
+ return 0;
+}
+
+int ivm_analyse_eeprom (unsigned char *buf, int len)
+{
+ unsigned short val;
+ unsigned char valbuf[CFG_IVM_EEPROM_PAGE_LEN];
+ unsigned char *tmp;
+
+ /* used Code from ivm/src/devsrv_baseproductdata.cpp */
+ if (ivm_check_crc (buf, 0) != 0)
+ return -1;
+
+ ivm_get_value (buf, CFG_IVM_EEPROM_PAGE_LEN, "IVM_BoardId", 0, 1);
+ val = ivm_get_value (buf, CFG_IVM_EEPROM_PAGE_LEN, "IVM_HWKey", 6, 1);
+ if (val != 0xffff) {
+ sprintf ((char *)valbuf, "%x", ((val /100) % 10));
+ setenv ("IVM_HWVariant", (char *)valbuf);
+ sprintf ((char *)valbuf, "%x", (val % 100));
+ setenv ("IVM_HWVersion", (char *)valbuf);
+ }
+ ivm_get_value (buf, CFG_IVM_EEPROM_PAGE_LEN, "IVM_Functions", 12, 0);
+
+ GET_STRING("IVM_Symbol", eSymbolOnly, 8)
+ GET_STRING("IVM_DeviceName", eSymbolShortText, 64)
+ tmp = (unsigned char *) getenv("IVM_DeviceName");
+ if (tmp) {
+ int len = strlen ((char *)tmp);
+ int i = 0;
+
+ while (i < len) {
+ if (tmp[i] == ';') {
+ setenv ("IVM_ShortText", (char *)&tmp[i + 1]);
+ break;
+ }
+ i++;
+ }
+ if (i >= len)
+ setenv ("IVM_ShortText", NULL);
+ } else {
+ setenv ("IVM_ShortText", NULL);
+ }
+ GET_STRING("IVM_ManufacturerID", eManufId, 32)
+ GET_STRING("IVM_ManufacturerSerialNumber", eManufSerialNumber, 20)
+ GET_STRING("IVM_ManufacturerPartNumber", eManufPartNumber, 32)
+ GET_STRING("IVM_ManufacturerBuildState", eManufBuildState, 32)
+ GET_STRING("IVM_SupplierPartNumber", eSuplierPartNumber, 32)
+ GET_STRING("IVM_DelieveryDate", eDeliveryDate, 32)
+ GET_STRING("IVM_SupplierBuildState", eSupplierBuildState, 32)
+ GET_STRING("IVM_CustomerID", eCustomerId, 32)
+ GET_STRING("IVM_CustomerProductID", eCustomerProdId, 32)
+
+ if (ivm_check_crc (&buf[CFG_IVM_EEPROM_PAGE_LEN * 2], 2) != 0)
+ return -2;
+ ivm_analyse_block2 (&buf[CFG_IVM_EEPROM_PAGE_LEN * 2], CFG_IVM_EEPROM_PAGE_LEN);
+
+ return 0;
+}
+
+int ivm_read_eeprom(void)
+{
+ I2C_MUX_DEVICE *dev = NULL;
+ uchar i2c_buffer[CFG_IVM_EEPROM_MAX_LEN];
+ uchar *buf;
+ unsigned dev_addr = CFG_IVM_EEPROM_ADR;
+
+ /* First init the Bus, select the Bus */
+#if defined(CFG_I2C_IVM_BUS)
+ dev = i2c_mux_ident_muxstring ((uchar *)CFG_I2C_IVM_BUS);
+#else
+ buf = (unsigned char *) getenv ("EEprom_ivm");
+ if (buf != NULL)
+ dev = i2c_mux_ident_muxstring (buf);
+#endif
+ if (dev == NULL) {
+ printf ("Error couldnt add Bus for IVM\n");
+ return -1;
+ }
+ i2c_set_bus_num (dev->busid);
+
+ buf = (unsigned char *) getenv ("EEprom_ivm_addr");
+ if (buf != NULL)
+ dev_addr = simple_strtoul ((char *)buf, NULL, 16);
+
+ if (eeprom_read (dev_addr, 0, i2c_buffer, CFG_IVM_EEPROM_MAX_LEN) != 0) {
+ printf ("Error reading EEprom\n");
+ return -2;
+ }
+
+ return ivm_analyse_eeprom (i2c_buffer, CFG_IVM_EEPROM_MAX_LEN);
+
+}
+
#if defined(CFG_I2C_INIT_BOARD)
#define DELAY_ABORT_SEQ 62
#define DELAY_HALF_PERIOD (500 / (CFG_I2C_SPEED / 1000))
diff --git a/include/configs/mgcoge.h b/include/configs/mgcoge.h
index 6564c15..b32eb80 100644
--- a/include/configs/mgcoge.h
+++ b/include/configs/mgcoge.h
@@ -212,6 +212,11 @@
#define CFG_EEPROM_PAGE_WRITE_BITS 3
#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 10
+/* Support the IVM EEprom */
+#define CFG_IVM_EEPROM_ADR 0x50
+#define CFG_IVM_EEPROM_MAX_LEN 0x400
+#define CFG_IVM_EEPROM_PAGE_LEN 0x100
+
/* I2C SYSMON (LM75, AD7414 is almost compatible) */
#define CONFIG_DTT_LM75 1 /* ON Semi's LM75 */
#define CONFIG_DTT_SENSORS {0} /* Sensor addresses */
diff --git a/include/configs/mgsuvd.h b/include/configs/mgsuvd.h
index 79954fe..36c7f26 100644
--- a/include/configs/mgsuvd.h
+++ b/include/configs/mgsuvd.h
@@ -382,6 +382,11 @@
#define CFG_EEPROM_PAGE_WRITE_BITS 3
#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 10
+/* Support the IVM EEprom */
+#define CFG_IVM_EEPROM_ADR 0x50
+#define CFG_IVM_EEPROM_MAX_LEN 0x400
+#define CFG_IVM_EEPROM_PAGE_LEN 0x100
+
/* I2C SYSMON (LM75, AD7414 is almost compatible) */
#define CONFIG_DTT_LM75 1 /* ON Semi's LM75 */
#define CONFIG_DTT_SENSORS {0, 2, 4, 6} /* Sensor addresses */
diff --git a/lib_ppc/board.c b/lib_ppc/board.c
index c02ac62..9b5ff41 100644
--- a/lib_ppc/board.c
+++ b/lib_ppc/board.c
@@ -79,6 +79,9 @@
extern int update_flash_size (int flash_size);
#endif
+#if defined(CONFIG_MGCOGE) || defined(CONFIG_MGSUVD)
+extern int ivm_read_eeprom(void);
+#endif
#if defined(CONFIG_SC3)
extern void sc3_read_eeprom(void);
#endif
@@ -869,6 +872,9 @@ void board_init_r (gd_t *id, ulong dest_addr)
#endif /* CONFIG_405GP, CONFIG_405EP */
#endif /* CFG_EXTBDINFO */
+#if defined(CONFIG_MGCOGE) || defined(CONFIG_MGSUVD)
+ ivm_read_eeprom();
+#endif
#if defined(CONFIG_SC3)
sc3_read_eeprom();
#endif
--
1.5.6.1
--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
next reply other threads:[~2008-09-29 7:56 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-09-29 7:56 Heiko Schocher [this message]
2008-09-29 9:10 ` [U-Boot] [PATCH] mgcoge, mgsuvd: added support for the IVM EEprom Wolfgang Denk
2008-09-29 9:57 ` Heiko Schocher
2008-09-29 11:49 ` Jerry Van Baren
2008-10-14 16:32 ` Wolfgang Denk
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=48E08A41.1090708@denx.de \
--to=hs@denx.de \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.