[U-Boot] [PATCH v3 3/5] ARM: omap-common: Add standard access for board description EEPROM

Steve Kipisz s-kipisz2 at ti.com
Wed Nov 4 23:00:11 CET 2015


From: Lokesh Vutla <lokeshvutla at ti.com>

Several TI EVMs have EEPROM that can contain board description information
such as revision, DDR definition, serial number, etc. In just about all
cases, these EEPROM are on the I2C bus and provides us the opportunity
to centralize the generic operations involved.

The on-board EEPROM on the BeagleBone Black, BeagleBone, AM335x EVM,
AM43x GP EVM, AM57xx-evm, BeagleBoard-X15 share the same format.
However, DRA-7* EVMs, OMAP4SDP use a modified format.

We hence introduce logic which is generic between these platforms
without enforcing any specific format. This allows the boards to use the
relevant format for operations that they might choose.

This module will compile for all TI SoC based boards when I2C is enabled,
even non-TI boards that do not have the EEPROM. If the functions are not
used, they will not be linked in.

It is important to note that this logic is fundamental to the board
configuration process such as DDR configuration which is needed in
SPL, hence cannot be part of the standard u-boot driver model (which
is available later in the process). Hence, to aid efficiency, the
eeprom contents are copied over to SRAM scratchpad memory area at the
first invocation to retrieve data.

The follow on patches introduce the use of this library for AM57x
platform support. AM335x/AM43xx cleanups need to first ensure usage of
omap_common prior to switch over to this generic solution.

Signed-off-by: Lokesh Vutla <lokeshvutla at ti.com>
Signed-off-by: Steve Kipisz <s-kipisz2 at ti.com>
---
v3 Based on:
 master      83bf0057 arm: at91: reworked meesc board support

Changes in v3 (since v2):
 - Create a new directory board/ti/common for code common to TI board
 - Move the EEPROM code to the new directory
 - Move the inline code that access the EEPROM data from omap_common.h
   to new files in the common directory

v2:  http://marc.info/?t=144655344800001&r=1&w=2
       (mailing list squashed original submission)

Changes in v2:
 - New Patch

 arch/arm/include/asm/omap_common.h |   5 +-
 board/ti/am57xx/Makefile           |   2 +
 board/ti/common/board.c            |  54 ++++++++++++++
 board/ti/common/board.h            | 117 +++++++++++++++++++++++++++++
 board/ti/common/ti-i2c-eeprom.c    | 148 +++++++++++++++++++++++++++++++++++++
 5 files changed, 325 insertions(+), 1 deletion(-)
 create mode 100644 board/ti/common/board.c
 create mode 100644 board/ti/common/board.h
 create mode 100644 board/ti/common/ti-i2c-eeprom.c

diff --git a/arch/arm/include/asm/omap_common.h b/arch/arm/include/asm/omap_common.h
index d773b0430ad4..f6d929b15e82 100644
--- a/arch/arm/include/asm/omap_common.h
+++ b/arch/arm/include/asm/omap_common.h
@@ -713,7 +713,9 @@ static inline u8 is_dra72x(void)
 #define OMAP_SRAM_SCRATCH_VCORES_PTR    (SRAM_SCRATCH_SPACE_ADDR + 0x1C)
 #define OMAP_SRAM_SCRATCH_SYS_CTRL	(SRAM_SCRATCH_SPACE_ADDR + 0x20)
 #define OMAP_SRAM_SCRATCH_BOOT_PARAMS	(SRAM_SCRATCH_SPACE_ADDR + 0x24)
-#define OMAP5_SRAM_SCRATCH_SPACE_END	(SRAM_SCRATCH_SPACE_ADDR + 0x28)
+#define OMAP_SRAM_SCRATCH_BOARD_EEPROM_START (SRAM_SCRATCH_SPACE_ADDR + 0x28)
+#define OMAP_SRAM_SCRATCH_BOARD_EEPROM_END (SRAM_SCRATCH_SPACE_ADDR + 0x200)
+#define OMAP_SRAM_SCRATCH_SPACE_END	(OMAP_SRAM_SCRATCH_BOARD_EEPROM_END)
 
 /* Boot parameters */
 #define DEVICE_DATA_OFFSET	0x18
@@ -728,4 +730,5 @@ static inline u8 is_dra72x(void)
 u32 omap_sys_boot_device(void);
 #endif
 
+
 #endif /* _OMAP_COMMON_H_ */
diff --git a/board/ti/am57xx/Makefile b/board/ti/am57xx/Makefile
index 5cd6873f5e97..9d85d31b2cf1 100644
--- a/board/ti/am57xx/Makefile
+++ b/board/ti/am57xx/Makefile
@@ -6,3 +6,5 @@
 #
 
 obj-y	:= board.o
+obj-y	+= ../common/board.o
+obj-${CONFIG_I2C} += ../common/ti-i2c-eeprom.o
diff --git a/board/ti/common/board.c b/board/ti/common/board.c
new file mode 100644
index 000000000000..1c02e44916f0
--- /dev/null
+++ b/board/ti/common/board.c
@@ -0,0 +1,54 @@
+/*
+ * board.c
+ *
+ * Common board functions for TI AMxxxx based boards.
+ *
+ * Copyright (C) 2015, Texas Instruments Incorporated - http://www.ti.com
+ *
+ * Author: Steven Kipisz <s-kipisz2 at ti.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/omap_common.h>
+
+#include "board.h"
+
+/**
+ * board_am_is() - Generic Board detection logic
+ * @name_tag:	Tag used in eeprom for the board
+ *
+ * Return: false if board information does not match OR eeprom was'nt read.
+ *	   true otherwise
+ */
+bool board_am_is(char *name_tag)
+{
+	struct ti_am_eeprom *ep = TI_AM_EEPROM_DATA;
+
+	if (ep->header != TI_EEPROM_HEADER_MAGIC)
+		return false;
+	return !strncmp(ep->name, name_tag, TI_EEPROM_HDR_NAME_LEN);
+}
+
+/**
+ * board_am_rev_is() - Compare board revision
+ * @rev_tag:	Revision tag to check in eeprom
+ * @cmp_len:	How many chars to compare?
+ *
+ * NOTE: revision information is often messed up (hence the str len match) :(
+ *
+ * Return: false if board information does not match OR eeprom was'nt read.
+ *	   true otherwise
+ */
+bool board_am_rev_is(char *rev_tag, int cmp_len)
+{
+	struct ti_am_eeprom *ep = TI_AM_EEPROM_DATA;
+	int l;
+
+	if (ep->header != TI_EEPROM_HEADER_MAGIC)
+		return false;
+
+	l = cmp_len > TI_EEPROM_HDR_REV_LEN ? TI_EEPROM_HDR_NAME_LEN : cmp_len;
+	return !strncmp(ep->version, rev_tag, l);
+}
diff --git a/board/ti/common/board.h b/board/ti/common/board.h
new file mode 100644
index 000000000000..19d63cad82f9
--- /dev/null
+++ b/board/ti/common/board.h
@@ -0,0 +1,117 @@
+/*
+ * board.h
+ * TI AMxxxx common board information header
+ *
+ * Copyright (C) 2015, Texas Instruments, Incorporated - http://www.ti.com
+ *
+ * SPDX-L	icense-Identifier:	GPL-2.0+
+ */
+
+/* Common I2C eeprom definitions */
+#ifndef __ASSEMBLY__
+
+/* TI EEPROM MAGIC Header identifier */
+#define TI_EEPROM_HEADER_MAGIC	0xEE3355AA
+
+#define TI_EEPROM_HDR_NAME_LEN		8
+#define TI_EEPROM_HDR_REV_LEN		12
+#define TI_EEPROM_HDR_SERIAL_LEN	4
+#define TI_EEPROM_HDR_CONFIG_LEN	32
+#define TI_EEPROM_HDR_NO_OF_MAC_ADDR	3
+#define TI_EEPROM_HDR_ETH_ALEN		6
+
+/**
+ * struct ti_am_eeprom - This structure holds data read in from the
+ *                     AM335x, AM437x, AM57xx TI EVM EEPROMs.
+ * @header: This holds the magic number
+ * @name: The name of the board
+ * @version: Board revision
+ * @serial: Board serial number
+ * @config: Reserved
+ * @mac_addr: Any MAC addresses written in the EEPROM
+ *
+ * The data is this structure 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 multiple
+ * TI boards with a single MLO and u-boot.
+ */
+struct ti_am_eeprom {
+	unsigned int header;
+	char name[TI_EEPROM_HDR_NAME_LEN];
+	char version[TI_EEPROM_HDR_REV_LEN];
+	char serial[TI_EEPROM_HDR_SERIAL_LEN];
+	char config[TI_EEPROM_HDR_CONFIG_LEN];
+	char mac_addr[TI_EEPROM_HDR_NO_OF_MAC_ADDR][TI_EEPROM_HDR_ETH_ALEN];
+} __attribute__ ((__packed__));
+
+/**
+ * struct ti_am_eeprom_printable - Null terminated, printable EEPROM contents
+ * @name:	NULL terminated name
+ * @version:	NULL terminated version
+ * @serial:	NULL terminated serial number
+ */
+struct ti_am_eeprom_printable {
+	char name[TI_EEPROM_HDR_NAME_LEN + 1];
+	char version[TI_EEPROM_HDR_REV_LEN + 1];
+	char serial[TI_EEPROM_HDR_SERIAL_LEN + 1];
+};
+#define TI_AM_EEPROM_DATA ((struct ti_am_eeprom *)\
+				OMAP_SRAM_SCRATCH_BOARD_EEPROM_START)
+
+/**
+ * ti_i2c_eeprom_am_get() - Consolidated eeprom data collection for AM* TI EVMs
+ * @bus_addr:	I2C bus address
+ * @dev_addr:	I2C slave address
+ * @ep:		Pointer to eeprom structure
+ *
+ * *ep is populated by the this AM generic function that consolidates
+ * the basic initialization logic common accross all AM* platforms.
+ */
+int ti_i2c_eeprom_am_get(int bus_addr, int dev_addr, struct ti_am_eeprom **epp);
+
+/**
+ * ti_i2c_eeprom_am_get_print() - Get a printable representation of eeprom data
+ * @bus_addr:	I2C bus address
+ * @dev_addr:	I2C slave address
+ * @p:		Pointer to eeprom structure
+ *
+ * This reads the eeprom and converts the data into a printable string for
+ * further processing.
+ */
+int ti_i2c_eeprom_am_get_print(int bus_addr, int dev_addr,
+			       struct ti_am_eeprom_printable *p);
+
+/**
+ * set_board_info_env() - Setup commonly used board information environment vars
+ * @name:	Name of the board
+ * @revision:	Revision of the board
+ * @serial:	Serial Number of the board
+ *
+ * In case of NULL revision or serial information "unknown" is setup.
+ * If name is NULL, default_name is used.
+ */
+void set_board_info_env(char *name, char *revision,
+			char *serial);
+
+/**
+ * board_am_is() - Generic Board detection logic
+ * @name_tag:	Tag used in eeprom for the board
+ *
+ * Return: false if board information does not match OR eeprom was'nt read.
+ *	   true otherwise
+ */
+bool board_am_is(char *name_tag);
+
+/**
+ * board_am_rev_is() - Compare board revision
+ * @rev_tag:	Revision tag to check in eeprom
+ * @cmp_len:	How many chars to compare?
+ *
+ * NOTE: revision information is often messed up (hence the str len match) :(
+ *
+ * Return: false if board information does not match OR eeprom was'nt read.
+ *	   true otherwise
+ */
+bool board_am_rev_is(char *rev_tag, int cmp_len);
+
+#endif	/* __ASSEMBLY__ */
diff --git a/board/ti/common/ti-i2c-eeprom.c b/board/ti/common/ti-i2c-eeprom.c
new file mode 100644
index 000000000000..5ec499b51a5d
--- /dev/null
+++ b/board/ti/common/ti-i2c-eeprom.c
@@ -0,0 +1,148 @@
+/*
+ * Library to support early TI EVM EEPROM handling
+ *
+ * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
+ *	Lokesh Vutla
+ *	Steve Kipisz
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/omap_common.h>
+#include <i2c.h>
+
+#include "board.h"
+
+/**
+ * ti_i2c_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 corresponding error on failure.
+ */
+int __maybe_unused ti_i2c_eeprom_init(int i2c_bus, int dev_addr)
+{
+	int rc;
+
+	rc = i2c_set_bus_num(i2c_bus);
+	if (rc)
+		return rc;
+
+	return i2c_probe(dev_addr);
+}
+
+/**
+ * ti_i2c_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 a buffer to read into
+ * @epsize: Size of buffer
+ *
+ * Return: 0 on success or corresponding result of i2c_read
+ */
+int __maybe_unused ti_i2c_eeprom_read(int dev_addr, int offset, uchar *ep,
+				     int epsize)
+{
+	return i2c_read(dev_addr, offset, 2, ep, epsize);
+}
+
+/**
+ * ti_eeprom_string_cleanup() - Handle eeprom programming errors
+ * @s:	eeprom string (should be NULL terminated)
+ *
+ * Some Board manufacturers do not add a NULL termination at the
+ * end of string, instead some binary information is kludged in, hence
+ * convert the string to just printable characters of ASCII chart.
+ */
+void __maybe_unused ti_eeprom_string_cleanup(char *s)
+{
+	int i, l;
+
+	l = strlen(s);
+	for (i = 0; i < l; i++, s++)
+		if (*s < ' ' || *s > '~') {
+			*s = 0;
+			break;
+		}
+}
+
+int __maybe_unused ti_i2c_eeprom_am_get(int bus_addr, int dev_addr,
+					struct ti_am_eeprom **epp)
+{
+	int rc;
+	struct ti_am_eeprom *ep;
+
+	if (!epp)
+		return -1;
+
+	ep = TI_AM_EEPROM_DATA;
+	if (ep->header == TI_EEPROM_HEADER_MAGIC)
+		goto already_read;
+
+	/* Initialize with a known bad marker for i2c fails.. */
+	ep->header = 0xADEAD12C;
+
+	gpi2c_init();
+	rc = ti_i2c_eeprom_init(bus_addr, dev_addr);
+	if (rc)
+		return rc;
+	rc = i2c_read(dev_addr, 0x0, 2, (uint8_t *)ep, sizeof(*ep));
+	if (rc)
+		return rc;
+
+	/* Corrupted data??? */
+	if (ep->header != TI_EEPROM_HEADER_MAGIC)
+		return -1;
+
+already_read:
+	*epp = ep;
+
+	return 0;
+}
+
+int __maybe_unused ti_i2c_eeprom_am_get_print(int bus_addr, int dev_addr,
+					      struct ti_am_eeprom_printable *p)
+{
+	struct ti_am_eeprom *ep;
+	int rc;
+
+	/* Incase of invalid eeprom contents */
+	p->name[0] = 0x00;
+	p->version[0] = 0x00;
+	p->serial[0] = 0x00;
+
+	rc = ti_i2c_eeprom_am_get(bus_addr, dev_addr, &ep);
+	if (rc)
+		return rc;
+
+	/*
+	 * Alas! we have to null terminate and cleanup the strings!
+	 */
+	strlcpy(p->name, ep->name, TI_EEPROM_HDR_NAME_LEN);
+	ti_eeprom_string_cleanup(p->name);
+	strlcpy(p->version, ep->version, TI_EEPROM_HDR_NAME_LEN);
+	ti_eeprom_string_cleanup(p->version);
+	strlcpy(p->serial, ep->serial, TI_EEPROM_HDR_NAME_LEN);
+	ti_eeprom_string_cleanup(p->serial);
+	return 0;
+}
+
+void __maybe_unused set_board_info_env(char *name, char *revision,
+				       char *serial)
+{
+	char *unknown = "unknown";
+
+	if (name)
+		setenv("board_name", name);
+
+	if (revision)
+		setenv("board_revision", revision);
+	else
+		setenv("board_revision", unknown);
+
+	if (serial)
+		setenv("board_serial", serial);
+	else
+		setenv("board_serial", unknown);
+}
-- 
1.9.1



More information about the U-Boot mailing list