/*
 * (C) Copyright 2005
 * Ladislav Michl, 2N Telekomunikace, michl@2n.cz
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 *
 * Some code shamelessly stolen back from Robin Getz.
 */

#define DEBUG

#include <common.h>
#include <exports.h>
#include <timestamp.h>
#include <net.h>
#include "../drivers/net/smc91111.h"

static u16 read_eeprom_reg(struct eth_device *dev, u16 reg)
{
	int timeout;

	SMC_SELECT_BANK(dev, 2);
	SMC_outw(dev, reg, PTR_REG);

	SMC_SELECT_BANK(dev, 1);
	SMC_outw(dev, SMC_inw (dev, CTL_REG) | CTL_EEPROM_SELECT | CTL_RELOAD,
		 CTL_REG);
	timeout = 100;
	while((SMC_inw (dev, CTL_REG) & CTL_RELOAD) && --timeout)
		udelay(100);
	if (timeout == 0) {
		printf("Timeout Reading EEPROM register %02x\n", reg);
		return 0;
	}

	return SMC_inw (dev, GP_REG);
}

static int write_eeprom_reg(struct eth_device *dev, u16 value, u16 reg)
{
	int timeout;

	SMC_SELECT_BANK(dev, 2);
	SMC_outw(dev, reg, PTR_REG);

	SMC_SELECT_BANK(dev, 1);
	SMC_outw(dev, value, GP_REG);
	SMC_outw(dev, SMC_inw (dev, CTL_REG) | CTL_EEPROM_SELECT | CTL_STORE, CTL_REG);
	timeout = 100;
	while ((SMC_inw(dev, CTL_REG) & CTL_STORE) && --timeout)
		udelay (100);
	if (timeout == 0) {
		printf("Timeout Writing EEPROM register %02x\n", reg);
		return 0;
	}

	return 1;
}

static int write_data(struct eth_device *dev, u16 *buf, int len)
{
	u16 reg = 0x23;

	while (len--)
		write_eeprom_reg(dev, *buf++, reg++);

	return 0;
}

static int verify_macaddr(struct eth_device *dev, char *s)
{
	u16 reg;
	int i, err = 0;

	printf("MAC Address: ");
	err = i = 0;
	for (i = 0; i < 3; i++) {
		reg = read_eeprom_reg(dev, 0x20 + i);
		printf("%02x:%02x%c", reg & 0xff, reg >> 8, i != 2 ? ':' : '\n');
		if (s)
			err |= reg != ((u16 *)s)[i];
	}

	return err ? 0 : 1;
}

static int set_mac(struct eth_device *dev, char *s)
{
	int i;
	char *e, eaddr[6];

	/* turn string into mac value */
	for (i = 0; i < 6; i++) {
		eaddr[i] = simple_strtoul(s, &e, 16);
		s = (*e) ? e+1 : e;
	}

	for (i = 0; i < 3; i++)
		write_eeprom_reg(dev, *(((u16 *)eaddr) + i), 0x20 + i);

	return 0;
}

static int parse_element(char *s, unsigned char *buf, int len)
{
	int cnt;
	char *p, num[3];
	unsigned char id;

	id = simple_strtoul(s, &p, 16);
	if (*p++ != ':')
		return -1;
	cnt = 2;
	num[2] = 0;
	for (; *p; p += 2) {
		if (p[1] == 0)
			return -2;
		if (cnt + 3 > len)
			return -3;
		num[0] = p[0];
		num[1] = p[1];
		buf[cnt++] = simple_strtoul(num, NULL, 16);
	}
	buf[0] = id;
	buf[1] = cnt - 2;

	return cnt;
}

extern int crcek(void);

int eeprom(int argc, char *argv[])
{
	int i, len, ret;
	unsigned char buf[58], *p;

	struct eth_device dev = {
		.iobase = CONFIG_SMC91111_BASE
	};

	app_startup(argv);
	if (get_version() != XF_VERSION) {
		printf("Wrong XF_VERSION.\n");
		printf("Application expects ABI version %d\n", XF_VERSION);
		printf("Actual U-Boot ABI version %d\n", (int)get_version());
		return 1;
	}

	return crcek();

	if ((SMC_inw (&dev, BANK_SELECT) & 0xFF00) != 0x3300) {
		printf("SMSC91111 not found.\n");
		return 2;
	}

	/* Called without parameters - print MAC address */
	if (argc < 2) {
		verify_macaddr(&dev, NULL);
		return 0;
	}

	/* Print help message */
	if (argv[1][1] == 'h') {
		printf("VoiceBlue EEPROM writer\n");
		printf("Built: %s at %s\n", U_BOOT_DATE, U_BOOT_TIME);
		printf("Usage:\n\t<mac_address> [<element_1>] [<...>]\n");
		return 0;
	}

	/* Try to parse information elements */
	len = sizeof(buf);
	p = buf;
	for (i = 2; i < argc; i++) {
		ret = parse_element(argv[i], p, len);
		switch (ret) {
		case -1:
			printf("Element %d: malformed\n", i - 1);
			return 3;
		case -2:
			printf("Element %d: odd character count\n", i - 1);
			return 3;
		case -3:
			printf("Out of EEPROM memory\n");
			return 3;
		default:
			p += ret;
			len -= ret;
		}
	}

	/* First argument (MAC) is mandatory */
	set_mac(&dev, argv[1]);
	if (verify_macaddr(&dev, argv[1])) {
		printf("*** MAC address does not match! ***\n");
		return 4;
	}

	while (len--)
		*p++ = 0;

	write_data(&dev, (u16 *)buf, sizeof(buf) >> 1);

	return 0;
}
