/*
 * U-boot - cpu.c CPU specific functions
 *
 * Copyright (c) 2005 blackfin.uclinux.org
 *
 * (C) Copyright 2000-2004
 * 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 <asm/blackfin.h>
#include <command.h>
#include <asm/entry.h>
#include <asm/cplb.h>
#include <asm/io.h>

#define CACHE_ON 1
#define CACHE_OFF 0

extern unsigned int icplb_table[page_descriptor_table_size][2];
extern unsigned int dcplb_table[page_descriptor_table_size][2];

int do_reset(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
	__asm__ __volatile__("cli r3;" "P0 = %0;" "JUMP (P0);"::"r"(L1_ISRAM)
	    );

	return 0;
}

/* These functions are just used to satisfy the linker */
int cpu_init(void)
{
	return 0;
}

int cleanup_before_linux(void)
{
	return 0;
}

void icache_enable(void)
{
	unsigned int *I0, *I1;
	int i, j = 0;

	if ((*pCHIPID >> 28) < 2)
		return;

	/* Before enable icache, disable it first */
	icache_disable();
	I0 = (unsigned int *)ICPLB_ADDR0;
	I1 = (unsigned int *)ICPLB_DATA0;

	/* make sure the locked ones go in first */
	for (i = 0; i < page_descriptor_table_size; i++) {
		if (CPLB_LOCK & icplb_table[i][1]) {
			debug("adding %02i %02i 0x%08x 0x%08x\n", i, j,
				 icplb_table[i][0], icplb_table[i][1]);
			*I0++ = icplb_table[i][0];
			*I1++ = icplb_table[i][1];
			j++;
		}
	}

	for (i = 0; i < page_descriptor_table_size; i++) {
		if (!(CPLB_LOCK & icplb_table[i][1])) {
			debug("adding %02i %02i 0x%08x 0x%08x\n", i, j,
				 icplb_table[i][0], icplb_table[i][1]);
			*I0++ = icplb_table[i][0];
			*I1++ = icplb_table[i][1];
			j++;
			if (j == 16) {
				break;
			}
		}
	}

	/* Fill the rest with invalid entry */
	if (j <= 15) {
		for (; j < 16; j++) {
			debug("filling %i with 0", j);
			*I1++ = 0x0;
		}

	}

	cli();
	sync();
	asm(" .align 8; ");
	*(unsigned int *)IMEM_CONTROL = IMC | ENICPLB;
	sync();
	sti();
}

void icache_disable(void)
{
	if ((*pCHIPID >> 28) < 2)
		return;
	cli();
	sync();
	asm(" .align 8; ");
	*(unsigned int *)IMEM_CONTROL &= ~(IMC | ENICPLB);
	sync();
	sti();
}

int icache_status(void)
{
	unsigned int value;
	value = *(unsigned int *)IMEM_CONTROL;

	if (value & (IMC | ENICPLB))
		return CACHE_ON;
	else
		return CACHE_OFF;
}

void dcache_enable(void)
{
	unsigned int *I0, *I1;
	unsigned int temp;
	int i, j = 0;

	/* Before enable dcache, disable it first */
	dcache_disable();
	I0 = (unsigned int *)DCPLB_ADDR0;
	I1 = (unsigned int *)DCPLB_DATA0;

	/* make sure the locked ones go in first */
	for (i = 0; i < page_descriptor_table_size; i++) {
		if (CPLB_LOCK & dcplb_table[i][1]) {
			debug("adding %02i %02i 0x%08x 0x%08x\n", i, j,
				 dcplb_table[i][0], dcplb_table[i][1]);
			*I0++ = dcplb_table[i][0];
			*I1++ = dcplb_table[i][1];
			j++;
		} else {
			debug("skip   %02i %02i 0x%08x 0x%08x\n", i, j,
				 dcplb_table[i][0], dcplb_table[i][1]);
		}
	}

	for (i = 0; i < page_descriptor_table_size; i++) {
		if (!(CPLB_LOCK & dcplb_table[i][1])) {
			debug("adding %02i %02i 0x%08x 0x%08x\n", i, j,
				 dcplb_table[i][0], dcplb_table[i][1]);
			*I0++ = dcplb_table[i][0];
			*I1++ = dcplb_table[i][1];
			j++;
			if (j == 16) {
				break;
			}
		}
	}

	/* Fill the rest with invalid entry */
	if (j <= 15) {
		for (; j < 16; j++) {
			debug("filling %i with 0", j);
			*I1++ = 0x0;
		}
	}

	cli();
	temp = *(unsigned int *)DMEM_CONTROL;
	sync();
	asm(" .align 8; ");
	*(unsigned int *)DMEM_CONTROL =
	    ACACHE_BCACHE | ENDCPLB | PORT_PREF0 | temp;
	sync();
	sti();
}

void dcache_disable(void)
{
	unsigned int *I0, *I1;
	int i;

	cli();
	sync();
	asm(" .align 8; ");
	*(unsigned int *)DMEM_CONTROL &=
	    ~(ACACHE_BCACHE | ENDCPLB | PORT_PREF0);
	sync();
	sti();

	/* after disable dcache,
	 * clear it so we don't confuse the next application
	 */
	I0 = (unsigned int *)DCPLB_ADDR0;
	I1 = (unsigned int *)DCPLB_DATA0;

	for (i = 0; i < 16; i++) {
		*I0++ = 0x0;
		*I1++ = 0x0;
	}
}

int dcache_status(void)
{
	unsigned int value;
	value = *(unsigned int *)DMEM_CONTROL;

	if (value & (ENDCPLB))
		return CACHE_ON;
	else
		return CACHE_OFF;
}
