[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