/*
 * (C) Copyright 2002
 * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch
 *
 * adapted for VCMA9
 * David Mueller, ELSOFT AG, d.mueller@elsoft.ch
 *
 * 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
 *
 */

#include <common.h>
#include <command.h>
#include "vcma9.h"
#include "../common/common_util.h"

#if defined(CONFIG_DRIVER_CS8900)
#include <../drivers/net/cs8900.h>

static uchar cs8900_chksum(ushort data)
{
	return((data >> 8) & 0x00FF) + (data & 0x00FF);
}

#endif

DECLARE_GLOBAL_DATA_PTR;

extern void print_vcma9_info(void);
extern int vcma9_cantest(int);
extern int vcma9_nandtest(void);
extern int vcma9_nanderase(void);
extern int vcma9_nandread(ulong);
extern int vcma9_nandwrite(ulong);
extern int vcma9_dactest(int);
extern int do_mplcommon(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);

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

int do_vcma9(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
	if (strcmp(argv[1], "info") == 0)
	{
		print_vcma9_info();
		return 0;
	}
#if defined(CONFIG_DRIVER_CS8900)
	if (strcmp(argv[1], "cs8900") == 0) {
		if (strcmp(argv[2], "read") == 0) {
			uchar addr; ushort data;

			addr = simple_strtoul(argv[3], NULL, 16);
			cs8900_e2prom_read(addr, &data);
			printf("0x%2.2X: 0x%4.4X\n", addr, data);
		} else if (strcmp(argv[2], "write") == 0) {
			uchar addr; ushort data;

			addr = simple_strtoul(argv[3], NULL, 16);
			data = simple_strtoul(argv[4], NULL, 16);
			cs8900_e2prom_write(addr, data);
		} else if (strcmp(argv[2], "setaddr") == 0) {
			uchar addr, i, csum; ushort data;

			/* check for valid ethaddr */
			for (i = 0; i < 6; i++)
				if (gd->bd->bi_enetaddr[i] != 0)
					break;

			if (i < 6) {
				addr = 1;
				data = 0x2158;
				cs8900_e2prom_write(addr, data);
				csum = cs8900_chksum(data);
				addr++;
				for (i = 0; i < 6; i+=2) {
					data = gd->bd->bi_enetaddr[i+1] << 8 |
					       gd->bd->bi_enetaddr[i];
					cs8900_e2prom_write(addr, data);
					csum += cs8900_chksum(data);
					addr++;
				}
				/* calculate header link byte */
				data = 0xA100 | (addr * 2);
				cs8900_e2prom_write(0, data);
				csum += cs8900_chksum(data);
				/* write checksum word */
				cs8900_e2prom_write(addr, (0 - csum) << 8);
			} else {
				puts("\nplease defined 'ethaddr'\n");
			}
		} else if (strcmp(argv[2], "dump") == 0) {
			uchar addr = 0, endaddr, csum; ushort data;

			puts("Dump of CS8900 config device: ");
			cs8900_e2prom_read(addr, &data);
			if ((data & 0xE000) == 0xA000) {
				endaddr = (data & 0x00FF) / 2;
				csum = cs8900_chksum(data);
				for (addr = 1; addr <= endaddr; addr++) {
					cs8900_e2prom_read(addr, &data);
					printf("\n0x%2.2X: 0x%4.4X", addr, data);
					csum += cs8900_chksum(data);
				}
				printf("\nChecksum: %s", (csum == 0) ? "ok" : "wrong");
			} else {
				puts("no valid config found");
			}
			puts("\n");
		}

		return 0;
	}
#endif
#if 0
	if (strcmp(argv[1], "cantest") == 0) {
		if (argc >= 3)
			vcma9_cantest(strcmp(argv[2], "s") ? 0 : 1);
		else
			vcma9_cantest(0);
		return 0;
	}
	if (strcmp(argv[1], "nandtest") == 0) {
		vcma9_nandtest();
		return 0;
	}
	if (strcmp(argv[1], "nanderase") == 0) {
		vcma9_nanderase();
		return 0;
	}
	if (strcmp(argv[1], "nandread") == 0) {
		ulong offset = 0;

		if (argc >= 3)
			offset = simple_strtoul(argv[2], NULL, 16);

		vcma9_nandread(offset);
		return 0;
	}
	if (strcmp(argv[1], "nandwrite") == 0) {
		ulong offset = 0;

		if (argc >= 3)
			offset = simple_strtoul(argv[2], NULL, 16);

		vcma9_nandwrite(offset);
		return 0;
	}
	if (strcmp(argv[1], "dactest") == 0) {
		if (argc >= 3)
			vcma9_dactest(strcmp(argv[2], "s") ? 0 : 1);
		else
		vcma9_dactest(0);
		return 0;
	}
#endif

	return (do_mplcommon(cmdtp, flag, argc, argv));
}

U_BOOT_CMD(
	vcma9, 6, 1, do_vcma9,
	"vcma9   - VCMA9 specific commands\n",
	"flash mem [SrcAddr]\n    - updates U-Boot with image in memory\n"
);
