/*
 * (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 */
		*(int *) &eerev.res[0] = 0;

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

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