[U-Boot] [PATCH v3 3/5] ARM: omap-common: Add standard access for board description EEPROM
Nishanth Menon
nm at ti.com
Thu Nov 5 00:43:41 CET 2015
On 11/04/2015 04:00 PM, 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
>
> +
Umm.. I think you should not have this.
> #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
please drop this.
> + *
> + * Common board functions for TI AMxxxx based boards.
why just AMxxxx? it is called board.c and can extend to dra7 platforms
as well. why not call merge this with the eeprom code and call it
board-detect.c ?
> + *
> + * 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
> + *
Document that this is for AM* TI EVM platforms
> + * Return: false if board information does not match OR eeprom was'nt read.
> + * true otherwise
> + */
> +bool board_am_is(char *name_tag)
I dont see a usage on dra7 evm for example -> why not use unused for
compile time optimization?
> +{
> + 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) :(
Document that this is for AM* TI EVM platforms
> + *
> + * 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)
here as well.
> +{
> + 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
I dont think this is needed: i can read the file name :)
> + * 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__
you should not need this anymore. you should use a proper header guard
instead.
> +
> +/* 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__ */
use a proper header guard
> 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);
> +}
>
I just think a single file should be sufficient here.
--
Regards,
Nishanth Menon
More information about the U-Boot
mailing list