/*
 * (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);

    /* set serial console as default */
    if ((ptr = getenv ("console")) == NULL)
	setenv ("console", "serial");

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

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