/*
 * (C) Copyright 2002 ELTEC Elektronik AG
 * Frank Gottschling <fgottschling@eltec.de>
 *
 * 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 as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * 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
 */

/* includes */
#include <common.h>
#include <linux/ctype.h>
#include <pci.h>
#include <net.h>
#include "srom.h"

/* imports  */
extern int l2_cache_enable (int l2control);
extern int eepro100_write_eeprom (struct eth_device *dev, int location,
				  int addr_len, unsigned short data);
extern int read_eeprom (struct eth_device *dev, int location, int addr_len);

/*----------------------------------------------------------------------------*/
/*
 * read/write to nvram is only byte access
 */
void *nvram_read (void *dest, const long src, size_t count)
{
	uchar *d = (uchar *) dest;
	uchar *s = (uchar *) (CONFIG_ENV_MAP_ADRS + src);

	while (count--)
		*d++ = *s++;

	return dest;
}

void nvram_write (long dest, const void *src, size_t count)
{
	uchar *d = (uchar *) (CONFIG_ENV_MAP_ADRS + dest);
	uchar *s = (uchar *) src;

	while (count--)
		*d++ = *s++;
}

/*----------------------------------------------------------------------------*/
/*
 * handle sroms on ELPPC
 * fix ether address
 * set serial console as default
 */
int misc_init_r (void)
{
	revinfo eerev;
	u_char *ptr;
	u_int i, l, initSrom, copyNv;
	char buf[256];
	char hex[23] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0,
		0, 0, 0, 0, 10, 11, 12, 13, 14, 15
	};

	/* Clock setting for MPC107 i2c */
	mpc107_i2c_init (MPC107_EUMB_ADDR, 0x2b);

	/* Reset the EPIC */
	out32r (MPC107_EUMB_GCR, 0xa0000000);
	while (in32r (MPC107_EUMB_GCR) & 0x80000000);	/* Wait for reset to complete */
	out32r (MPC107_EUMB_GCR, 0x20000000);	/* Put into into mixed mode */
	while (in32r (MPC107_EUMB_IACKR) != 0xff);	/* Clear all pending interrupts */

	/*
	 * Check/Remake revision info
	 */
	initSrom = 0;
	copyNv = 0;

	/* read out current revision srom contens */
	mpc107_srom_load (0x0000, (u_char *) & eerev, sizeof (revinfo),
			  SECOND_DEVICE, FIRST_BLOCK);

	/* read out current nvram shadow image */
	nvram_read (buf, CONFIG_SYS_NV_SROM_COPY_ADDR, CONFIG_SYS_SROM_SIZE);

	if (strcmp (eerev.magic, "ELTEC") != 0) {
		/* srom is not initialized -> create a default revision info */
		for (i = 0, ptr = (u_char *) & eerev; i < sizeof (revinfo);
		     i++)
			*ptr++ = 0x00;
		strcpy (eerev.magic, "ELTEC");
		eerev.revrev[0] = 1;
		eerev.revrev[1] = 0;
		eerev.size = 0x00E0;
		eerev.category[0] = 0x01;

		/* node id from dead e128 as default */
		eerev.etheraddr[0] = 0x00;
		eerev.etheraddr[1] = 0x00;
		eerev.etheraddr[2] = 0x5B;
		eerev.etheraddr[3] = 0x00;
		eerev.etheraddr[4] = 0x2E;
		eerev.etheraddr[5] = 0x4D;

		/* cache config word for ELPPC */
		memset(&eerev.res[0], 0, 4);

		initSrom = 1;	/* force dialog */
		copyNv = 1;	/* copy to nvram */
	}

	if ((copyNv == 0)
	    && (el_srom_checksum ((u_char *) & eerev, CONFIG_SYS_SROM_SIZE) !=
		el_srom_checksum ((u_char *) buf, CONFIG_SYS_SROM_SIZE))) {
		printf ("Invalid revision info copy in nvram !\n");
		printf ("Press key:\n  <c> to copy current revision info to nvram.\n");
		printf ("  <r> to reenter revision info.\n");
		printf ("=> ");
		if (0 != readline (NULL)) {
			switch ((char) toupper (console_buffer[0])) {
			case 'C':
				copyNv = 1;
				break;
			case 'R':
				copyNv = 1;
				initSrom = 1;
				break;
			}
		}
	}

	if (initSrom) {
		memcpy (buf, &eerev.revision[0][0], 14);	/* save all revision info */
		printf ("Enter revision number (0-9): %c  ",
			eerev.revision[0][0]);
		if (0 != readline (NULL)) {
			eerev.revision[0][0] =
				(char) toupper (console_buffer[0]);
			memcpy (&eerev.revision[1][0], buf, 12);	/* shift rest of rev info */
		}

		printf ("Enter revision character (A-Z): %c  ",
			eerev.revision[0][1]);
		if (1 == readline (NULL)) {
			eerev.revision[0][1] =
				(char) toupper (console_buffer[0]);
		}

		printf ("Enter board name (V-XXXX-XXXX): %s  ",
			(char *) &eerev.board);
		if (11 == readline (NULL)) {
			for (i = 0; i < 11; i++)
				eerev.board[i] =
					(char) toupper (console_buffer[i]);
			eerev.board[11] = '\0';
		}

		printf ("Enter serial number: %s ", (char *) &eerev.serial);
		if (6 == readline (NULL)) {
			for (i = 0; i < 6; i++)
				eerev.serial[i] = console_buffer[i];
			eerev.serial[6] = '\0';
		}

		printf ("Enter ether node ID with leading zero (HEX): %02x%02x%02x%02x%02x%02x  ", eerev.etheraddr[0], eerev.etheraddr[1], eerev.etheraddr[2], eerev.etheraddr[3], eerev.etheraddr[4], eerev.etheraddr[5]);
		if (12 == readline (NULL)) {
			for (i = 0; i < 12; i += 2)
				eerev.etheraddr[i >> 1] =
					(char) (16 *
						hex[toupper
						    (console_buffer[i]) -
						    '0'] +
						hex[toupper
						    (console_buffer[i + 1]) -
						    '0']);
		}

		l = strlen ((char *) &eerev.text);
		printf ("Add to text section (max 64 chr): %s ",
			(char *) &eerev.text);
		if (0 != readline (NULL)) {
			for (i = l; i < 63; i++)
				eerev.text[i] = console_buffer[i - l];
			eerev.text[63] = '\0';
		}

		/* prepare network eeprom */
		memset (buf, 0, 128);

		buf[0] = eerev.etheraddr[1];
		buf[1] = eerev.etheraddr[0];
		buf[2] = eerev.etheraddr[3];
		buf[3] = eerev.etheraddr[2];
		buf[4] = eerev.etheraddr[5];
		buf[5] = eerev.etheraddr[4];

		*(unsigned short *) &buf[20] = 0x48B2;
		*(unsigned short *) &buf[22] = 0x0004;
		*(unsigned short *) &buf[24] = 0x1433;

		printf ("\nSRom:  Writing i82559 info ........ ");
		if (eepro100_srom_store ((unsigned short *) buf) == -1)
			printf ("FAILED\n");
		else
			printf ("OK\n");

		/* update CRC */
		eerev.crc =
			el_srom_checksum ((u_char *) eerev.board, eerev.size);

		/* write new values */
		printf ("\nSRom:  Writing revision info ...... ");
		if (mpc107_srom_store
		    ((BLOCK_SIZE - sizeof (revinfo)), (u_char *) & eerev,
		     sizeof (revinfo), SECOND_DEVICE, FIRST_BLOCK) == -1)
			printf ("FAILED\n\n");
		else
			printf ("OK\n\n");

		/* write new values as shadow image to nvram */
		nvram_write (CONFIG_SYS_NV_SROM_COPY_ADDR, (void *) &eerev,
			     CONFIG_SYS_SROM_SIZE);

	}

	/*if (initSrom) */
	/* copy current values as shadow image to nvram */
	if (initSrom == 0 && copyNv == 1)
		nvram_write (CONFIG_SYS_NV_SROM_COPY_ADDR, (void *) &eerev,
			     CONFIG_SYS_SROM_SIZE);

	/* update environment */
	sprintf (buf, "%02x:%02x:%02x:%02x:%02x:%02x",
		 eerev.etheraddr[0], eerev.etheraddr[1],
		 eerev.etheraddr[2], eerev.etheraddr[3],
		 eerev.etheraddr[4], eerev.etheraddr[5]);
	setenv ("ethaddr", buf);

	/* print actual board identification */
	printf ("Ident: %s  Ser %s  Rev %c%c\n",
		eerev.board, (char *) &eerev.serial,
		eerev.revision[0][0], eerev.revision[0][1]);

	return (0);
}

/*----------------------------------------------------------------------------*/
