/*
 * (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 char console_buffer[CFG_CBSIZE];
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 *) (CFG_ENV_MAP_ADRS + src);

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

	return dest;
}

void nvram_write (long dest, const void *src, size_t count)
{
	uchar *d = (uchar *) (CFG_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, CFG_NV_SROM_COPY_ADDR, CFG_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, CFG_SROM_SIZE) !=
		el_srom_checksum ((u_char *) buf, CFG_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 (CFG_NV_SROM_COPY_ADDR, (void *) &eerev,
			     CFG_SROM_SIZE);

	}

	/*if (initSrom) */
	/* copy current values as shadow image to nvram */
	if (initSrom == 0 && copyNv == 1)
		nvram_write (CFG_NV_SROM_COPY_ADDR, (void *) &eerev,
			     CFG_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);
}

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