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

Lokesh Vutla a0131933 at ti.com
Thu Nov 5 07:00:20 CET 2015



On Thursday 05 November 2015 03:30 AM, Steve Kipisz wrote:
> 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

May be keep this header file under arch/arm/include/asm/ so that it can
be included properly.

Thanks and regards,
Lokesh


> @@ -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);
> +}
> 


More information about the U-Boot mailing list