/*
 * (C) Copyright 2003
 * 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 <command.h>
#include <asm/inca-ip.h>
#include <asm/regdef.h>
#include <asm/mipsregs.h>
#include <asm/io.h>
#include <asm/addrspace.h>
#include <asm/cacheops.h>
#include <asm/reboot.h>

#include "sconsole.h"

#define cache_unroll(base,op)	        	\
	__asm__ __volatile__("	         	\
		.set noreorder;		        \
		.set mips3;		        \
		cache %1, (%0);	                \
		.set mips0;			\
		.set reorder"			\
		:				\
		: "r" (base),			\
		  "i" (op));

typedef void (*FUNCPTR)(ulong *source, ulong *destination, ulong nlongs);

extern void	asc_serial_init		(void);
extern void	asc_serial_putc 	(char);
extern void	asc_serial_puts 	(const char *);
extern int	asc_serial_getc 	(void);
extern int	asc_serial_tstc 	(void);
extern void	asc_serial_setbrg 	(void);

void _machine_restart(void)
{
	void (*f)(void) = (void *) 0xbfc00000;

	f();
}

static void sdram_timing_init (ulong size)
{
	register uint pass;
	register uint done;
	register uint count;
	register uint p0, p1, p2, p3, p4;
	register uint addr;

#define WRITE_MC_IOGP_1 *(uint *)0xbf800800 = (p1<<14)+(p2<<13)+(p4<<8)+(p0<<4)+p3;
#define WRITE_MC_IOGP_2 *(uint *)0xbf800800 = (p1<<14)+(p2<<13)+((p4-16)<<8)+(p0<<4)+p3;

	done = 0;
	p0 = 2;
	while (p0 < 4 && done == 0) {
	    p1 = 0;
	    while (p1 < 2 && done == 0) {
		p2 = 0;
		while (p2 < 2 && done == 0) {
		    p3 = 0;
		    while (p3 < 16 && done == 0) {
			count = 0;
			p4 = 0;
			while (p4 < 32 && done == 0) {
			    WRITE_MC_IOGP_1;

			    for (addr = KSEG1 + 0x4000;
				 addr < KSEG1ADDR (size);
				 addr = addr + 4) {
					*(uint *) addr = 0xaa55aa55;
			    }

			    pass = 1;

			    for (addr = KSEG1 + 0x4000;
				 addr < KSEG1ADDR (size) && pass == 1;
				 addr = addr + 4) {
					if (*(uint *) addr != 0xaa55aa55)
						pass = 0;
			    }

			    if (pass == 1) {
				count++;
			    } else {
				count = 0;
			    }

			    if (count == 32) {
				WRITE_MC_IOGP_2;
				done = 1;
			    }
			    p4++;
			}
			p3++;
		    }
		    p2++;
		}
		p1++;
	    }
	    p0++;
	    if (p0 == 1)
		p0++;
	}
}

long int initdram(int board_type)
{
	/* The only supported number of SDRAM banks is 4.
	 */
#define CFG_NB	4

	ulong	cfgpb0	= *INCA_IP_SDRAM_MC_CFGPB0;
	ulong	cfgdw	= *INCA_IP_SDRAM_MC_CFGDW;
	int	cols	= cfgpb0 & 0xF;
	int	rows	= (cfgpb0 & 0xF0) >> 4;
	int	dw	= cfgdw & 0xF;
	ulong	size	= (1 << (rows + cols)) * (1 << (dw - 1)) * CFG_NB;
	void (*  sdram_init) (ulong);

	sdram_init = (void (*)(ulong)) KSEG0ADDR(&sdram_timing_init);

	sdram_init(0x10000);

	return size;
}

int checkboard (void)
{

	unsigned long chipid = *(unsigned long *)0xB800C800;

	printf ("Board: Purple PLB 2800 chip version %ld, ", chipid & 0xF);

	printf("CPU Speed %d MHz\n", CPU_CLOCK_RATE/1000000);

	set_io_port_base(0);

	return 0;
}

int misc_init_r (void)
{
	asc_serial_init ();

	sconsole_putc   = asc_serial_putc;
	sconsole_puts   = asc_serial_puts;
	sconsole_getc   = asc_serial_getc;
	sconsole_tstc   = asc_serial_tstc;
	sconsole_setbrg = asc_serial_setbrg;

	sconsole_flush ();
	return (0);
}

/*******************************************************************************
*
* copydwords - copy one buffer to another a long at a time
*
* This routine copies the first <nlongs> longs from <source> to <destination>.
*/
static void copydwords (ulong *source, ulong *destination, ulong nlongs)
{
	ulong temp,temp1;
	ulong *dstend = destination + nlongs;

	while (destination < dstend)
	{
		temp = *source++;
		/* dummy read from sdram */
		temp1 = *(ulong *)0xa0000000;
		/* avoid optimization from compliler */
		*(ulong *)0xbf0081f8 = temp1 + temp;
		*destination++ = temp;

	}
}

/*******************************************************************************
*
* copyLongs - copy one buffer to another a long at a time
*
* This routine copies the first <nlongs> longs from <source> to <destination>.
*/
static void copyLongs (ulong *source, ulong *destination, ulong nlongs)
{
	FUNCPTR absEntry;

	absEntry = (FUNCPTR)(0xbf008000+((ulong)copydwords & 0x7));
	absEntry(source, destination, nlongs);
}

/*******************************************************************************
*
* programLoad - load program into ram
*
* This routine load copydwords into ram
*
*/
static void programLoad(void)
{
	FUNCPTR absEntry;
	ulong *src,*dst;

	src = (ulong *)(TEXT_BASE + 0x428);
	dst = (ulong *)0xbf0081d0;

	absEntry = (FUNCPTR)(TEXT_BASE + 0x400);
	absEntry(src,dst,0x6);

	src = (ulong *)((ulong)copydwords & 0xfffffff8);
	dst = (ulong *)0xbf008000;

	absEntry(src,dst,0x38);
}

/*******************************************************************************
*
* copy_code - copy u-boot image from flash to RAM
*
* This routine is needed to solve flash problems on this board
*
*/
void copy_code (ulong dest_addr)
{
	extern long uboot_end_data;
	unsigned long start;
	unsigned long end;

	/* load copydwords into ram
	 */
	programLoad();

	/* copy u-boot code
	 */
	copyLongs((ulong *)CFG_MONITOR_BASE,
		  (ulong *)dest_addr,
		  ((ulong)&uboot_end_data - CFG_MONITOR_BASE + 3) / 4);


	/* flush caches
	 */

	start = KSEG0;
	end = start + CFG_DCACHE_SIZE;
	while(start < end) {
		cache_unroll(start,Index_Writeback_Inv_D);
		start += CFG_CACHELINE_SIZE;
	}

	start = KSEG0;
	end = start + CFG_ICACHE_SIZE;
	while(start < end) {
		cache_unroll(start,Index_Invalidate_I);
		start += CFG_CACHELINE_SIZE;
	}
}
