/*
 * Thomas Horsten <thh@lasat.com>
 * Copyright (C) 2000 LASAT Networks A/S.
 *
 *  This program is free software; you can distribute 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 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.
 *
 * Routines specific to the LASAT boards
 */
#include <linux/config.h>
#include <linux/types.h>
#include <linux/crc32.h>
#include <asm/lasat/lasat.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/ctype.h>
#include <asm/bootinfo.h>
#include <asm/addrspace.h>
#include "at93c.h"
/* New model description table */
#include "lasat_models.h"

#define EEPROM_CRC(data, len) (~0 ^ crc32(~0, data, len))

struct lasat_info lasat_board_info;

void update_bcastaddr(void);

int EEPROMRead(unsigned int pos, unsigned char *data, int len)
{
	int i;

	for (i=0; i<len; i++)
		*data++ = at93c_read(pos++);

	return 0;
}
int EEPROMWrite(unsigned int pos, unsigned char *data, int len)
{
	int i;

	for (i=0; i<len; i++)
		at93c_write(pos++, *data++);

	return 0;
}

static void init_flash_sizes(void)
{
	int i;
	unsigned long *lb = lasat_board_info.li_flashpart_base;
	unsigned long *ls = lasat_board_info.li_flashpart_size;

	ls[LASAT_MTD_BOOTLOADER] = 0x40000;
	ls[LASAT_MTD_SERVICE] = 0xC0000;
	ls[LASAT_MTD_NORMAL] = 0x100000;

	if (mips_machtype == MACH_LASAT_100) {
		lasat_board_info.li_flash_base = 0x1e000000;

		lb[LASAT_MTD_BOOTLOADER] = 0x1e400000;

		if (lasat_board_info.li_flash_size > 0x200000) {
			ls[LASAT_MTD_CONFIG] = 0x100000;
			ls[LASAT_MTD_FS] = 0x500000;
		}
	} else {
		lasat_board_info.li_flash_base = 0x10000000;

		if (lasat_board_info.li_flash_size < 0x1000000) {
			lb[LASAT_MTD_BOOTLOADER] = 0x10000000;
			ls[LASAT_MTD_CONFIG] = 0x100000;
			if (lasat_board_info.li_flash_size >= 0x400000) {
				ls[LASAT_MTD_FS] = lasat_board_info.li_flash_size - 0x300000;
			}
		}
	}

	for (i = 1; i < LASAT_MTD_LAST; i++)
		lb[i] = lb[i-1] + ls[i-1];
}

int lasat_init_board_info(void)
{
	int c;
	unsigned long crc;
	unsigned long cfg0, cfg1;
	const product_info_t   *ppi;
	int i_n_base_models = N_BASE_MODELS;
	const char * const * i_txt_base_models = txt_base_models;
	int i_n_prids = N_PRIDS;

	memset(&lasat_board_info, 0, sizeof(lasat_board_info));

	/* First read the EEPROM info */
	EEPROMRead(0, (unsigned char *)&lasat_board_info.li_eeprom_info,
		   sizeof(struct lasat_eeprom_struct));

	/* Check the CRC */
	crc = EEPROM_CRC((unsigned char *)(&lasat_board_info.li_eeprom_info),
		    sizeof(struct lasat_eeprom_struct) - 4);

	if (crc != lasat_board_info.li_eeprom_info.crc32) {
		prom_printf("WARNING...\nWARNING...\nEEPROM CRC does not match calculated, attempting to soldier on...\n");
	}

	if (lasat_board_info.li_eeprom_info.version != LASAT_EEPROM_VERSION)
	{
		prom_printf("WARNING...\nWARNING...\nEEPROM version %d, wanted version %d, attempting to soldier on...\n",
		       (unsigned int)lasat_board_info.li_eeprom_info.version,
		       LASAT_EEPROM_VERSION);
	}

	cfg0 = lasat_board_info.li_eeprom_info.cfg[0];
	cfg1 = lasat_board_info.li_eeprom_info.cfg[1];

	if ( LASAT_W0_DSCTYPE(cfg0) != 1) {
		prom_printf("WARNING...\nWARNING...\nInvalid configuration read from EEPROM, attempting to soldier on...");
	}
	/* We have a valid configuration */

	switch (LASAT_W0_SDRAMBANKSZ(cfg0)) {
	case 0:
		lasat_board_info.li_memsize = 0x0800000;
		break;
	case 1:
		lasat_board_info.li_memsize = 0x1000000;
		break;
	case 2:
		lasat_board_info.li_memsize = 0x2000000;
		break;
	case 3:
		lasat_board_info.li_memsize = 0x4000000;
		break;
	case 4:
		lasat_board_info.li_memsize = 0x8000000;
		break;
	default:
		lasat_board_info.li_memsize = 0;
	}

	switch (LASAT_W0_SDRAMBANKS(cfg0)) {
	case 0:
		break;
	case 1:
		lasat_board_info.li_memsize *= 2;
		break;
	default:
		break;
	}

	switch (LASAT_W0_BUSSPEED(cfg0)) {
	case 0x0:
		lasat_board_info.li_bus_hz = 60000000;
		break;
	case 0x1:
		lasat_board_info.li_bus_hz = 66000000;
		break;
	case 0x2:
		lasat_board_info.li_bus_hz = 66666667;
		break;
	case 0x3:
		lasat_board_info.li_bus_hz = 80000000;
		break;
	case 0x4:
		lasat_board_info.li_bus_hz = 83333333;
		break;
	case 0x5:
		lasat_board_info.li_bus_hz = 100000000;
		break;
	}

	switch (LASAT_W0_CPUCLK(cfg0)) {
	case 0x0:
		lasat_board_info.li_cpu_hz =
			lasat_board_info.li_bus_hz;
		break;
	case 0x1:
		lasat_board_info.li_cpu_hz =
			lasat_board_info.li_bus_hz +
			(lasat_board_info.li_bus_hz >> 1);
		break;
	case 0x2:
		lasat_board_info.li_cpu_hz =
			lasat_board_info.li_bus_hz +
			lasat_board_info.li_bus_hz;
		break;
	case 0x3:
		lasat_board_info.li_cpu_hz =
			lasat_board_info.li_bus_hz +
			lasat_board_info.li_bus_hz +
			(lasat_board_info.li_bus_hz >> 1);
		break;
	case 0x4:
		lasat_board_info.li_cpu_hz =
			lasat_board_info.li_bus_hz +
			lasat_board_info.li_bus_hz +
			lasat_board_info.li_bus_hz;
		break;
	}

	/* Flash size */
	switch (LASAT_W1_FLASHSIZE(cfg1)) {
	case 0:
		lasat_board_info.li_flash_size = 0x200000;
		break;
	case 1:
		lasat_board_info.li_flash_size = 0x400000;
		break;
	case 2:
		lasat_board_info.li_flash_size = 0x800000;
		break;
	case 3:
		lasat_board_info.li_flash_size = 0x1000000;
		break;
	case 4:
		lasat_board_info.li_flash_size = 0x2000000;
		break;
	}

	init_flash_sizes();

	lasat_board_info.li_bmid = LASAT_W0_BMID(cfg0);
	lasat_board_info.li_prid = lasat_board_info.li_eeprom_info.prid;
	if (lasat_board_info.li_prid == 0xffff || lasat_board_info.li_prid == 0)
		lasat_board_info.li_prid = lasat_board_info.li_bmid;

	/* Base model stuff */
	if (lasat_board_info.li_bmid > i_n_base_models)
		lasat_board_info.li_bmid = i_n_base_models;
	strcpy(lasat_board_info.li_bmstr, i_txt_base_models[lasat_board_info.li_bmid]);

	/* Product ID dependent values */
	c = lasat_board_info.li_prid;
	if (c >= i_n_prids) {
		strcpy(lasat_board_info.li_namestr, "Unknown Model");
		strcpy(lasat_board_info.li_typestr, "Unknown Type");
	} else {
		ppi = &vendor_info_table[0].vi_product_info[c];
		strcpy(lasat_board_info.li_namestr, ppi->pi_name);
		if (ppi->pi_type)
			strcpy(lasat_board_info.li_typestr, ppi->pi_type);
		else
			sprintf(lasat_board_info.li_typestr, "%d",10*c);
	}

#if defined(CONFIG_INET) && defined(CONFIG_SYSCTL)
	update_bcastaddr();
#endif

	return 0;
}

void lasat_write_eeprom_info(void)
{
	unsigned long crc;

	/* Generate the CRC */
	crc = EEPROM_CRC((unsigned char *)(&lasat_board_info.li_eeprom_info),
		    sizeof(struct lasat_eeprom_struct) - 4);
	lasat_board_info.li_eeprom_info.crc32 = crc;

	/* Write the EEPROM info */
	EEPROMWrite(0, (unsigned char *)&lasat_board_info.li_eeprom_info,
		    sizeof(struct lasat_eeprom_struct));
}

