summaryrefslogtreecommitdiff
path: root/cpu/bf537/cpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpu/bf537/cpu.c')
-rw-r--r--cpu/bf537/cpu.c227
1 files changed, 227 insertions, 0 deletions
diff --git a/cpu/bf537/cpu.c b/cpu/bf537/cpu.c
new file mode 100644
index 0000000000..cb8dc3cd16
--- /dev/null
+++ b/cpu/bf537/cpu.c
@@ -0,0 +1,227 @@
+/*
+ * 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;
+}