/*
 * (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 */
