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

