[PATCH v1] ARM: omap-common: Add support for EEPROM

Add support for EEPROM init and read. The am57xx boards have EEPROMs
that have board name, version, serial data and other data. The init
routine will initialize an i2c bus and then probe for the EEPROM
device. The read routine will read data from the EEPROM and store
it in an omap_eeprom structure. The data read will be used later in
board detection of TI EVMs.

This code is in omap-common since it can be reused by other TI EVMs
that have EEPROMs that use the same format. The onboard EEPROM on the
Beaglebone Black, Bealgebone, AM335x EVM, AM34x GP EVM, DRA-74 EVM also
follows the same format. So its better to define a common function,
insted of redefining everywhere.

Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
Signed-off-by: Steve Kipisz <s-kipisz2@ti.com>

From: Lokesh Vutla <lokeshvutla@ti.com>

Add support for EEPROM init and read. The am57xx boards have EEPROMs
that have board name, version, serial data and other data. The init
routine will initialize an i2c bus and then probe for the EEPROM
device. The read routine will read data from the EEPROM and store
it in an omap_eeprom structure. The data read will be used later in
board detection of TI EVMs.

This code is in omap-common since it can be reused by other TI EVMs
that have EEPROMs that use the same format. The onboard EEPROM on the
Beaglebone Black, Bealgebone, AM335x EVM, AM34x GP EVM, DRA-74 EVM also
follows the same format. So its better to define a common function,
insted of redefining everywhere.

Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
Signed-off-by: Steve Kipisz <s-kipisz2@ti.com>
---
arch/arm/cpu/armv7/omap-common/Makefile | 1 +
arch/arm/cpu/armv7/omap-common/omap_eeprom.c | 54 +++++++++++++++++++++++++++
arch/arm/include/asm/omap_common.h | 55 ++++++++++++++++++++++++++++
include/configs/am57xx_evm.h | 10 +++++
4 files changed, 120 insertions(+)
create mode 100644 arch/arm/cpu/armv7/omap-common/omap_eeprom.c

diff --git a/arch/arm/cpu/armv7/omap-common/Makefile b/arch/arm/cpu/armv7/omap-common/Makefile
index 464a5d1..99ea897 100644
--- a/arch/arm/cpu/armv7/omap-common/Makefile
+++ b/arch/arm/cpu/armv7/omap-common/Makefile
@@ -30,3 +30,4 @@ obj-y += boot-common.o
obj-y += lowlevel_init.o

obj-y += mem-common.o
+obj-$(CONFIG_ENV_EEPROM_IS_ON_I2C) += omap_eeprom.o
diff --git a/arch/arm/cpu/armv7/omap-common/omap_eeprom.c b/arch/arm/cpu/armv7/omap-common/omap_eeprom.c
new file mode 100644
index 0000000..98de51e
--- /dev/null
+++ b/arch/arm/cpu/armv7/omap-common/omap_eeprom.c
@@ -0,0 +1,54 @@
+/*
+ * omap_eeprom.c
+ *
+ * Copyright (C) 2015 Texas Instruments Incorporated -
+ * http://www.ti.com/
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <asm/omap_common.h>
+
+int omap_eeprom_init(int i2c_bus, int dev_addr)
+{
+ int rc = 0;
+
+ rc = i2c_set_bus_num(i2c_bus);
+ if (rc) {
+ printf("I2C bus %d Initialization failed err=%d\n",
+ i2c_bus, rc);
+ return -1;
+ }
+
+ rc = i2c_probe(dev_addr);
+ if (rc) {
+ printf("I2c probe at address %d on bus %d failed err=%d\n",
+ dev_addr, i2c_bus, rc);
+ return -1;
+ }
+
+ return 0;
+}
+
+int omap_eeprom_read(int dev_addr, int offset, struct omap_eeprom *ep)
+{
+ int ret = 0;
+
+ ret = i2c_read(dev_addr, offset, 2, (uchar *)ep,
+ sizeof(struct omap_eeprom));
+
+ if (!ret) {
+ /*
+ * Return error if proper header
+ * is not found.
+ */
+ if (ep->header != OMAP_EEPROM_HEADER)
+ ret = -1;
+ } else {
+ printf("i2c read error err=%d\n", ret);
+ }
+
+ return ret;
+}
diff --git a/arch/arm/include/asm/omap_common.h b/arch/arm/include/asm/omap_common.h
index d7b81c1..9a9b154 100644
--- a/arch/arm/include/asm/omap_common.h
+++ b/arch/arm/include/asm/omap_common.h
@@ -552,6 +552,61 @@ struct vcores_data {
   struct volts iva;
};

+/*
+ * TI AM57xx EVMs define a system EEPROM that defines certain sub-fields.
+ * We use these fields to in turn see what board we are on, and what
+ * that might require us to set or not set.
+ */
+
+#define HDR_NO_OF_MAC_ADDR 3
+#define HDR_ETH_ALEN 6
+#define HDR_NAME_LEN 8
+#define OMAP_EEPROM_HEADER 0xEE3355AA
+
+/**
+ * struct omap_eeprom - This structure holds data read in from the
+ * EEPROM.
+ * @header: This holds the magic number
+ * @name: The name of the board
+ * @version: Board revision
+ * @serail: Board serial number
+ * @config: Reserved
+ * @mac_addr: Any MAC addresses written in the EEPROM
+ *
+ * The data is this struction is read from the EEPROM on the board.
+ * It is used for board detection which is based on name. It is used
+ * to configure specific TI boards. This allows booting of multible
+ * TI boards with a single MLO and u-boot.
+ */
+struct omap_eeprom {
+ unsigned int header;
+ char name[HDR_NAME_LEN];
+ char version[4];
+ char serial[12];
+ char config[32];
+ char mac_addr[HDR_NO_OF_MAC_ADDR][HDR_ETH_ALEN];
+};

This structure is not generic to all platforms -> DRA7-evm for example
uses a completely different eeprom organization.

+
+/**
+ * omap_eeprom_init - Initialize an i2c bus and probe for a device
+ * @i2c_bus: i2c bus number to initialize
+ * @dev_addr: Device address to probe for
+ *
+ * Return: 0 on success or -1 on failure.
+ */
+int omap_eeprom_init(int i2c_bus, int dev_addr);
+
+/**
+ * omap_eeprom_read - Read data from an EEPROM
+ * @dev_addr: The device address of the EEPROM
+ * @offset: Offset to start reading in the EEPROM
+ * @ep: Pointer to the omap_eeprom structure to read into
+ *
+ * Return: 0 on success, -1 if the header is invalid, or the non-zero
+ * return code of a failed i2c_read
+ */
+int omap_eeprom_read(int dev_addr, int offset, struct omap_eeprom *ep);
+
extern struct prcm_regs const **prcm;
extern struct prcm_regs const omap5_es1_prcm;
extern struct prcm_regs const omap5_es2_prcm;
diff --git a/include/configs/am57xx_evm.h b/include/configs/am57xx_evm.h
index 6308cab..1b70923 100644
--- a/include/configs/am57xx_evm.h
+++ b/include/configs/am57xx_evm.h
@@ -87,5 +87,15 @@
#define CONFIG_SYS_SCSI_MAX_LUN 1
#define CONFIG_SYS_SCSI_MAX_DEVICE (CONFIG_SYS_SCSI_MAX_SCSI_ID * \
             CONFIG_SYS_SCSI_MAX_LUN)
+/* EEPROM Support */
+#undef CONFIG_SPI
+#define CONFIG_CMD_EEPROM
+#define CONFIG_ENV_EEPROM_IS_ON_I2C
+#define CONFIG_SYS_I2C_MULTI_EEPROMS
+#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2
+#define CONFIG_EEPROM_CHIP_ADDR 0x50
+
+#define CONFIG_SYS_OMAP_I2C0 0
+#define CONFIG_SYS_OMAP24_I2C_SPEED4 400000

#endif /* __CONFIG_AM57XX_EVM_H */

Introduce this as part of AM57xx eeprom detection.