/*
 * (C) Copyright 2006
 * Wolfgang Denk, DENX Software Engineering, wd@denx.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
 */

#include <common.h>
#include <mpc5xxx.h>

/* For the V38B board the pin is GPIO_PSC_6 */
#define GPIO_PIN	GPIO_PSC6_0

#define NO_ERROR	0
#define ERR_NO_NUMBER	1
#define ERR_BAD_NUMBER	2

static int is_high(void);
static int check_device(void);
static void io_out(int value);
static void io_input(void);
static void io_output(void);
static void init_gpio(void);
static void read_byte(unsigned char *data);
static void write_byte(unsigned char command);

void read_2501_memory(unsigned char *psernum, unsigned char *perr);
void board_get_enetaddr(uchar *enetaddr);


static int is_high()
{
	return (*((vu_long *) MPC5XXX_WU_GPIO_DATA_I) & GPIO_PIN);
}

static void io_out(int value)
{
	if (value)
		*((vu_long *) MPC5XXX_WU_GPIO_DATA_O) |= GPIO_PIN;
	else
		*((vu_long *) MPC5XXX_WU_GPIO_DATA_O) &= ~GPIO_PIN;
}

static void io_input()
{
	*((vu_long *) MPC5XXX_WU_GPIO_DIR) &= ~GPIO_PIN;
	udelay(3);	/* allow input to settle */
}

static void io_output()
{
	*((vu_long *) MPC5XXX_WU_GPIO_DIR) |= GPIO_PIN;
}

static void init_gpio()
{
	*((vu_long *) MPC5XXX_WU_GPIO_ENABLE) |= GPIO_PIN;	/* Enable appropriate pin */
}

void read_2501_memory(unsigned char *psernum, unsigned char *perr)
{
#define NBYTES 28
	unsigned char crcval, i;
	unsigned char buf[NBYTES];

	*perr = 0;
	crcval = 0;

	for (i = 0; i < NBYTES; i++)
		buf[i] = 0;

	if (!check_device())
		*perr = ERR_NO_NUMBER;
	else {
		*perr = NO_ERROR;
		write_byte(0xCC);		/* skip ROM (0xCC) */
		write_byte(0xF0);		/* Read memory command 0xF0 */
		write_byte(0x00);		/* Address TA1=0, TA2=0 */
		write_byte(0x00);
		read_byte(&crcval);		/* Read CRC of address and command */

		for (i = 0; i < NBYTES; i++)
			read_byte(&buf[i]);
	}
	if (strncmp((const char *) &buf[11], "MAREL IEEE 802.3", 16)) {
		*perr = ERR_BAD_NUMBER;
		psernum[0] = 0x00;
		psernum[1] = 0xE0;
		psernum[2] = 0xEE;
		psernum[3] = 0xFF;
		psernum[4] = 0xFF;
		psernum[5] = 0xFF;
	} else {
		psernum[0] = 0x00;
		psernum[1] = 0xE0;
		psernum[2] = 0xEE;
		psernum[3] = buf[7];
		psernum[4] = buf[6];
		psernum[5] = buf[5];
	}
}

static int check_device()
{
	int found;

	io_output();
	io_out(0);
	udelay(500);  /* must be at least 480 us low pulse */

	io_input();
	udelay(60);

	found = (is_high() == 0) ? 1 : 0;
	udelay(500);  /* must be at least 480 us low pulse */

	return found;
}

static void write_byte(unsigned char command)
{
	char i;

	for (i = 0; i < 8; i++) {
		/* 1 us to 15 us low pulse starts bit slot */
		/* Start with high pulse for 3 us */
		io_input();
		udelay(3);

		io_out(0);
		io_output();
		udelay(3);

		if (command & 0x01) {
			/* 60 us high for 1-bit */
			io_input();
			udelay(60);
		} else
			/* 60 us low for 0-bit */
			udelay(60);
		/*  Leave pin as input */
		io_input();

		command = command >> 1;
	}
}

static void read_byte(unsigned char *data)
{
	unsigned char i, rdat = 0;

	for (i = 0; i < 8; i++) {
		/* read one bit from one-wire device */

		/* 1 - 15 us low starts bit slot */
		io_out(0);
		io_output();
		udelay(0);

		/* allow line to be pulled high */
		io_input();

		/* delay 10 us */
		udelay(10);

		/* now sample input status */
		if (is_high())
			rdat = (rdat >> 1) | 0x80;
		else
			rdat = rdat >> 1;

		udelay(60);	/* at least 60 us */
	}
	/* copy the return value */
	*data = rdat;
}

void board_get_enetaddr(uchar *enetaddr)
{
	unsigned char sn[6], err = NO_ERROR;

	init_gpio();

	read_2501_memory(sn, &err);

	if (err == NO_ERROR) {
		sprintf((char *)enetaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
				sn[0], sn[1], sn[2], sn[3], sn[4], sn[5]);
		printf("MAC address: %s\n", enetaddr);
		setenv("ethaddr", (char *)enetaddr);
	} else {
		sprintf((char *)enetaddr, "00:01:02:03:04:05");
		printf("Error reading MAC address.\n");
		printf("Setting default to %s\n", enetaddr);
		setenv("ethaddr", (char *)enetaddr);
	}
}
