/*
 * (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)
{
	unsigned int bus = i2c_get_bus_num();
	i2c_set_bus_num(CONFIG_SYS_EEPROM_BUS_NUM);

	memset(eeprom, 0, TRICORDER_EEPROM_SIZE);

	i2c_read(addr, 0, 2, (unsigned char *)eeprom, TRICORDER_EEPROM_SIZE);
	i2c_set_bus_num(bus);

	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;

	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

	eeprom_init(CONFIG_SYS_EEPROM_BUS_NUM);

	ret = eeprom_write(devaddr, 0, (unsigned char *)&eeprom,
			TRICORDER_EEPROM_SIZE);
	if (ret)
		printf("Tricorder: Could not write EEPROM content!\n");

	ret = eeprom_read(devaddr, 0, (unsigned char *)&eeprom_verify,
			TRICORDER_EEPROM_SIZE);
	if (ret)
		printf("Tricorder: Could not read EEPROM content!\n");

	if (memcmp(&eeprom, &eeprom_verify, sizeof(eeprom)) != 0) {
		printf("Tricorder: Could not verify EEPROM content!\n");
		ret = 1;
	}

	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);

		if (strcmp(argv[1], "read") == 0)
			return tricorder_eeprom_read(dev_addr);
	} 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;

		if (argc == 7)
			interface = argv[6];

		if (strcmp(argv[1], "write") == 0)
			return tricorder_eeprom_write(dev_addr, name, version,
						      serial, interface);
	}

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