blob: ac8ec517ff63c1145b838234d379c38a8316f2e0 [file] [log] [blame]
/*
* 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;
/* 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)
{
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;
}