tricorder: add tricordereeprom command
The new tricordereeprom command can read and write the eeprom for hardware detection on tricorder devices. Signed-off-by: Andreas Bießmann <andreas.biessmann@corscience.de>
This commit is contained in:
parent
deac6d664b
commit
459f1da88b
@ -12,7 +12,7 @@ include $(TOPDIR)/config.mk
|
||||
|
||||
LIB = $(obj)lib$(BOARD).o
|
||||
|
||||
COBJS := tricorder.o
|
||||
COBJS := tricorder.o tricorder-eeprom.o
|
||||
|
||||
SRCS := $(COBJS:.o=.c)
|
||||
OBJS := $(addprefix $(obj),$(COBJS))
|
||||
|
251
board/corscience/tricorder/tricorder-eeprom.c
Normal file
251
board/corscience/tricorder/tricorder-eeprom.c
Normal file
@ -0,0 +1,251 @@
|
||||
/*
|
||||
* (C) Copyright 2013
|
||||
* Corscience GmbH & Co. KG, <www.corscience.de>
|
||||
* Andreas Bießmann <andreas.biessmann@corscience.de>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <i2c.h>
|
||||
|
||||
#include "tricorder-eeprom.h"
|
||||
|
||||
static inline void warn_wrong_value(const char *msg, unsigned int a,
|
||||
unsigned int b)
|
||||
{
|
||||
printf("Expected EEPROM %s %08x, got %08x\n", msg, a, b);
|
||||
}
|
||||
|
||||
static int handle_eeprom_v0(struct tricorder_eeprom *eeprom)
|
||||
{
|
||||
struct tricorder_eeprom_v0 {
|
||||
uint32_t magic;
|
||||
uint16_t length;
|
||||
uint16_t version;
|
||||
char board_name[TRICORDER_BOARD_NAME_LENGTH];
|
||||
char board_version[TRICORDER_BOARD_VERSION_LENGTH];
|
||||
char board_serial[TRICORDER_BOARD_SERIAL_LENGTH];
|
||||
uint32_t crc32;
|
||||
} __packed eepromv0;
|
||||
uint32_t crc;
|
||||
|
||||
printf("Old EEPROM (v0), consider rewrite!\n");
|
||||
|
||||
if (be16_to_cpu(eeprom->length) != sizeof(eepromv0)) {
|
||||
warn_wrong_value("length", sizeof(eepromv0),
|
||||
be16_to_cpu(eeprom->length));
|
||||
return 1;
|
||||
}
|
||||
|
||||
memcpy(&eepromv0, eeprom, sizeof(eepromv0));
|
||||
|
||||
crc = crc32(0L, (unsigned char *)&eepromv0,
|
||||
sizeof(eepromv0) - sizeof(eepromv0.crc32));
|
||||
if (be32_to_cpu(eepromv0.crc32) != crc) {
|
||||
warn_wrong_value("CRC", be32_to_cpu(eepromv0.crc32),
|
||||
crc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Ok the content is correct, do the conversion */
|
||||
memset(eeprom->interface_version, 0x0,
|
||||
TRICORDER_INTERFACE_VERSION_LENGTH);
|
||||
crc = crc32(0L, (unsigned char *)eeprom, TRICORDER_EEPROM_CRC_SIZE);
|
||||
eeprom->crc32 = cpu_to_be32(crc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_eeprom_v1(struct tricorder_eeprom *eeprom)
|
||||
{
|
||||
uint32_t crc;
|
||||
|
||||
if (be16_to_cpu(eeprom->length) != TRICORDER_EEPROM_SIZE) {
|
||||
warn_wrong_value("length", TRICORDER_EEPROM_SIZE,
|
||||
be16_to_cpu(eeprom->length));
|
||||
return 1;
|
||||
}
|
||||
|
||||
crc = crc32(0L, (unsigned char *)eeprom, TRICORDER_EEPROM_CRC_SIZE);
|
||||
if (be32_to_cpu(eeprom->crc32) != crc) {
|
||||
warn_wrong_value("CRC", be32_to_cpu(eeprom->crc32), crc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tricorder_get_eeprom(int addr, struct tricorder_eeprom *eeprom)
|
||||
{
|
||||
#ifdef CONFIG_SYS_EEPROM_BUS_NUM
|
||||
unsigned int bus = i2c_get_bus_num();
|
||||
i2c_set_bus_num(CONFIG_SYS_EEPROM_BUS_NUM);
|
||||
#endif
|
||||
|
||||
memset(eeprom, 0, TRICORDER_EEPROM_SIZE);
|
||||
|
||||
i2c_read(addr, 0, 2, (unsigned char *)eeprom, TRICORDER_EEPROM_SIZE);
|
||||
#ifdef CONFIG_SYS_EEPROM_BUS_NUM
|
||||
i2c_set_bus_num(bus);
|
||||
#endif
|
||||
|
||||
if (be32_to_cpu(eeprom->magic) != TRICORDER_EEPROM_MAGIC) {
|
||||
warn_wrong_value("magic", TRICORDER_EEPROM_MAGIC,
|
||||
be32_to_cpu(eeprom->magic));
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (be16_to_cpu(eeprom->version)) {
|
||||
case 0:
|
||||
return handle_eeprom_v0(eeprom);
|
||||
case 1:
|
||||
return handle_eeprom_v1(eeprom);
|
||||
default:
|
||||
warn_wrong_value("version", TRICORDER_EEPROM_VERSION,
|
||||
be16_to_cpu(eeprom->version));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_SPL)
|
||||
int tricorder_eeprom_read(unsigned devaddr)
|
||||
{
|
||||
struct tricorder_eeprom eeprom;
|
||||
int ret = tricorder_get_eeprom(devaddr, &eeprom);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
printf("Board type: %.*s\n",
|
||||
sizeof(eeprom.board_name), eeprom.board_name);
|
||||
printf("Board version: %.*s\n",
|
||||
sizeof(eeprom.board_version), eeprom.board_version);
|
||||
printf("Board serial: %.*s\n",
|
||||
sizeof(eeprom.board_serial), eeprom.board_serial);
|
||||
printf("Board interface version: %.*s\n",
|
||||
sizeof(eeprom.interface_version),
|
||||
eeprom.interface_version);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tricorder_eeprom_write(unsigned devaddr, const char *name,
|
||||
const char *version, const char *serial, const char *interface)
|
||||
{
|
||||
struct tricorder_eeprom eeprom, eeprom_verify;
|
||||
size_t length;
|
||||
uint32_t crc;
|
||||
int ret;
|
||||
unsigned char *p;
|
||||
int i;
|
||||
#ifdef CONFIG_SYS_EEPROM_BUS_NUM
|
||||
unsigned int bus;
|
||||
#endif
|
||||
|
||||
memset(eeprom, 0, TRICORDER_EEPROM_SIZE);
|
||||
memset(eeprom_verify, 0, TRICORDER_EEPROM_SIZE);
|
||||
|
||||
eeprom.magic = cpu_to_be32(TRICORDER_EEPROM_MAGIC);
|
||||
eeprom.length = cpu_to_be16(TRICORDER_EEPROM_SIZE);
|
||||
eeprom.version = cpu_to_be16(TRICORDER_EEPROM_VERSION);
|
||||
|
||||
length = min(sizeof(eeprom.board_name), strlen(name));
|
||||
strncpy(eeprom.board_name, name, length);
|
||||
|
||||
length = min(sizeof(eeprom.board_version), strlen(version));
|
||||
strncpy(eeprom.board_version, version, length);
|
||||
|
||||
length = min(sizeof(eeprom.board_serial), strlen(serial));
|
||||
strncpy(eeprom.board_serial, serial, length);
|
||||
|
||||
if (interface) {
|
||||
length = min(sizeof(eeprom.interface_version),
|
||||
strlen(interface));
|
||||
strncpy(eeprom.interface_version, interface, length);
|
||||
}
|
||||
|
||||
crc = crc32(0L, (unsigned char *)&eeprom, TRICORDER_EEPROM_CRC_SIZE);
|
||||
eeprom.crc32 = cpu_to_be32(crc);
|
||||
|
||||
#if defined(DEBUG)
|
||||
puts("Tricorder EEPROM content:\n");
|
||||
print_buffer(0, &eeprom, 1, sizeof(eeprom), 16);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_EEPROM_BUS_NUM
|
||||
bus = i2c_get_bus_num();
|
||||
i2c_set_bus_num(CONFIG_SYS_EEPROM_BUS_NUM);
|
||||
#endif
|
||||
|
||||
/* do page write to the eeprom */
|
||||
for (i = 0, p = (unsigned char *)&eeprom;
|
||||
i < sizeof(eeprom);
|
||||
i += 32, p += 32) {
|
||||
ret = i2c_write(devaddr, i, CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
|
||||
p, min(sizeof(eeprom) - i, 32));
|
||||
if (ret)
|
||||
break;
|
||||
udelay(5000); /* 5ms write cycle timing */
|
||||
}
|
||||
|
||||
ret = i2c_read(devaddr, 0, 2, (unsigned char *)&eeprom_verify,
|
||||
TRICORDER_EEPROM_SIZE);
|
||||
|
||||
if (memcmp(&eeprom, &eeprom_verify, sizeof(eeprom)) != 0) {
|
||||
printf("Tricorder: Could not verify EEPROM content!\n");
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYS_EEPROM_BUS_NUM
|
||||
i2c_set_bus_num(bus);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
int do_tricorder_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
if (argc == 3) {
|
||||
ulong dev_addr = simple_strtoul(argv[2], NULL, 16);
|
||||
eeprom_init();
|
||||
if (strcmp(argv[1], "read") == 0) {
|
||||
int rcode;
|
||||
|
||||
rcode = tricorder_eeprom_read(dev_addr);
|
||||
|
||||
return rcode;
|
||||
}
|
||||
} else if (argc == 6 || argc == 7) {
|
||||
ulong dev_addr = simple_strtoul(argv[2], NULL, 16);
|
||||
char *name = argv[3];
|
||||
char *version = argv[4];
|
||||
char *serial = argv[5];
|
||||
char *interface = NULL;
|
||||
eeprom_init();
|
||||
|
||||
if (argc == 7)
|
||||
interface = argv[6];
|
||||
|
||||
if (strcmp(argv[1], "write") == 0) {
|
||||
int rcode;
|
||||
|
||||
rcode = tricorder_eeprom_write(dev_addr, name, version,
|
||||
serial, interface);
|
||||
|
||||
return rcode;
|
||||
}
|
||||
}
|
||||
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
tricordereeprom, 7, 1, do_tricorder_eeprom,
|
||||
"Tricorder EEPROM",
|
||||
"read devaddr\n"
|
||||
" - read Tricorder EEPROM at devaddr and print content\n"
|
||||
"tricordereeprom write devaddr name version serial [interface]\n"
|
||||
" - write Tricorder EEPROM at devaddr with 'name', 'version'"
|
||||
"and 'serial'\n"
|
||||
" optional add an HW interface parameter"
|
||||
);
|
||||
#endif /* CONFIG_SPL */
|
41
board/corscience/tricorder/tricorder-eeprom.h
Normal file
41
board/corscience/tricorder/tricorder-eeprom.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* (C) Copyright 2013
|
||||
* Corscience GmbH & Co. KG, <www.corscience.de>
|
||||
* Andreas Bießmann <andreas.biessmann@corscience.de>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
#ifndef TRICORDER_EEPROM_H_
|
||||
#define TRICORDER_EEPROM_H_
|
||||
|
||||
#include <linux/compiler.h>
|
||||
|
||||
#define TRICORDER_EEPROM_MAGIC 0xc2a94f52
|
||||
#define TRICORDER_EEPROM_VERSION 1
|
||||
|
||||
#define TRICORDER_BOARD_NAME_LENGTH 12
|
||||
#define TRICORDER_BOARD_VERSION_LENGTH 4
|
||||
#define TRICORDER_BOARD_SERIAL_LENGTH 12
|
||||
#define TRICORDER_INTERFACE_VERSION_LENGTH 4
|
||||
|
||||
struct tricorder_eeprom {
|
||||
uint32_t magic;
|
||||
uint16_t length;
|
||||
uint16_t version;
|
||||
char board_name[TRICORDER_BOARD_NAME_LENGTH];
|
||||
char board_version[TRICORDER_BOARD_VERSION_LENGTH];
|
||||
char board_serial[TRICORDER_BOARD_SERIAL_LENGTH];
|
||||
char interface_version[TRICORDER_INTERFACE_VERSION_LENGTH];
|
||||
uint32_t crc32;
|
||||
} __packed;
|
||||
|
||||
#define TRICORDER_EEPROM_SIZE sizeof(struct tricorder_eeprom)
|
||||
#define TRICORDER_EEPROM_CRC_SIZE (TRICORDER_EEPROM_SIZE - \
|
||||
sizeof(uint32_t))
|
||||
|
||||
/**
|
||||
* @brief read eeprom information from a specific eeprom address
|
||||
*/
|
||||
int tricorder_get_eeprom(int addr, struct tricorder_eeprom *eeprom);
|
||||
|
||||
#endif /* TRICORDER_EEPROM_H_ */
|
@ -82,6 +82,13 @@
|
||||
#define CONFIG_SYS_I2C_SPEED 100000
|
||||
#define CONFIG_SYS_I2C_SLAVE 1
|
||||
#define CONFIG_DRIVER_OMAP34XX_I2C 1
|
||||
#define CONFIG_I2C_MULTI_BUS
|
||||
|
||||
/* EEPROM */
|
||||
#define CONFIG_SYS_I2C_MULTI_EEPROMS
|
||||
#define CONFIG_CMD_EEPROM
|
||||
#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2
|
||||
#define CONFIG_SYS_EEPROM_BUS_NUM 1
|
||||
|
||||
/* TWL4030 */
|
||||
#define CONFIG_TWL4030_POWER
|
||||
|
Loading…
Reference in New Issue
Block a user