sh: Update core code of SuperH.
Signed-off-by: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
diff --git a/cpu/sh4/Makefile b/cpu/sh4/Makefile
index b24a280..1bb8bd7 100644
--- a/cpu/sh4/Makefile
+++ b/cpu/sh4/Makefile
@@ -29,7 +29,7 @@
LIB = $(obj)lib$(CPU).a
START = start.o
-OBJS = cpu.o interrupts.o watchdog.o time.o
+OBJS = cpu.o interrupts.o watchdog.o time.o cache.o
all: .depend $(START) $(LIB)
diff --git a/cpu/sh4/cache.c b/cpu/sh4/cache.c
new file mode 100644
index 0000000..55acb31
--- /dev/null
+++ b/cpu/sh4/cache.c
@@ -0,0 +1,108 @@
+/*
+ * (C) Copyright 2007
+ * Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
+ *
+ * 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/processor.h>
+#include <asm/io.h>
+
+/*
+ * Jump to P2 area.
+ * When handling TLB or caches, we need to do it from P2 area.
+ */
+#define jump_to_P2() \
+ do { \
+ unsigned long __dummy; \
+ __asm__ __volatile__( \
+ "mov.l 1f, %0\n\t" \
+ "or %1, %0\n\t" \
+ "jmp @%0\n\t" \
+ " nop\n\t" \
+ ".balign 4\n" \
+ "1: .long 2f\n" \
+ "2:" \
+ : "=&r" (__dummy) \
+ : "r" (0x20000000)); \
+ } while (0)
+
+/*
+ * Back to P1 area.
+ */
+#define back_to_P1() \
+ do { \
+ unsigned long __dummy; \
+ __asm__ __volatile__( \
+ "nop;nop;nop;nop;nop;nop;nop\n\t" \
+ "mov.l 1f, %0\n\t" \
+ "jmp @%0\n\t" \
+ " nop\n\t" \
+ ".balign 4\n" \
+ "1: .long 2f\n" \
+ "2:" \
+ : "=&r" (__dummy)); \
+ } while (0)
+
+#define CACHE_VALID 1
+#define CACHE_UPDATED 2
+
+static inline void cache_wback_all(void)
+{
+ unsigned long addr, data, i, j;
+
+ jump_to_P2();
+ for (i = 0; i < CACHE_OC_NUM_ENTRIES; i++){
+ for (j = 0; j < CACHE_OC_NUM_WAYS; j++) {
+ addr = CACHE_OC_ADDRESS_ARRAY | (j << CACHE_OC_WAY_SHIFT)
+ | (i << CACHE_OC_ENTRY_SHIFT);
+ data = inl(addr);
+ if (data & CACHE_UPDATED) {
+ data &= ~CACHE_UPDATED;
+ outl(data, addr);
+ }
+ }
+ }
+ back_to_P1();
+}
+
+
+#define CACHE_ENABLE 0
+#define CACHE_DISABLE 1
+
+int cache_control(unsigned int cmd)
+{
+ unsigned long ccr;
+
+ jump_to_P2();
+ ccr = inl(CCR);
+
+ if (ccr & CCR_CACHE_ENABLE)
+ cache_wback_all();
+
+ if (cmd == CACHE_DISABLE)
+ outl(CCR_CACHE_STOP, CCR);
+ else
+ outl(CCR_CACHE_INIT, CCR);
+ back_to_P1();
+
+ return 0;
+}
diff --git a/cpu/sh4/cpu.c b/cpu/sh4/cpu.c
index 70df45e..d76d518 100644
--- a/cpu/sh4/cpu.c
+++ b/cpu/sh4/cpu.c
@@ -23,6 +23,7 @@
#include <common.h>
#include <command.h>
+#include <asm/processor.h>
int checkcpu(void)
{
@@ -48,20 +49,35 @@
return 0;
}
-void flush_cache (unsigned long addr, unsigned long size){}
+void flush_cache (unsigned long addr, unsigned long size)
+{
+
+}
void icache_enable (void)
{
-
+ cache_control(0);
}
void icache_disable (void)
{
-
+ cache_control(1);
}
-
int icache_status (void)
{
return 0;
}
+
+void dcache_enable (void)
+{
+}
+
+void dcache_disable (void)
+{
+}
+
+int dcache_status (void)
+{
+ return 0;
+}
diff --git a/cpu/sh4/time.c b/cpu/sh4/time.c
index b6e4d02..5f8a3a0 100644
--- a/cpu/sh4/time.c
+++ b/cpu/sh4/time.c
@@ -1,4 +1,7 @@
/*
+ * (C) Copyright 2007
+ * Nobobuhiro Iwamatsu <iwamatsu@nigauri.org>
+ *
* (C) Copyright 2003
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
@@ -31,7 +34,15 @@
if (timer > 2)
return;
- *((volatile unsigned char *) TSTR0) |= (1 << timer);
+ *((volatile unsigned char *) TSTR) |= (1 << timer);
+}
+
+static void tmu_timer_stop (unsigned int timer)
+{
+ u8 val = *((volatile u8 *)TSTR);
+ if (timer > 2)
+ return;
+ *((volatile unsigned char *)TSTR) = val &~(1 << timer);
}
int timer_init (void)
@@ -39,7 +50,8 @@
/* Divide clock by 4 */
*(volatile u16 *)TCR0 = 0;
- tmu_timer_start (0);
+ tmu_timer_stop(0);
+ tmu_timer_start(0);
return 0;
}
@@ -51,15 +63,12 @@
*/
unsigned long long get_ticks (void)
{
- return (0 - *((volatile unsigned int *) TCNT0));
+ return (0 - *((volatile u32 *) TCNT0));
}
unsigned long get_timer (unsigned long base)
{
- unsigned long n =
- *((volatile unsigned int *)TCNT0) ;
-
- return ((int)n - base ) < 0 ? ( TMU_MAX_COUNTER - ( base -n )):(n - base );
+ return ((0 - *((volatile u32 *) TCNT0)) - base);
}
void set_timer (unsigned long t)
@@ -69,19 +78,15 @@
void reset_timer (void)
{
+ tmu_timer_stop(0);
set_timer (0);
+ tmu_timer_start(0);
}
void udelay (unsigned long usec)
{
unsigned int start = get_timer (0);
- unsigned int end = 0;
- if (usec > 1000000)
- end = ((usec/100000) * CFG_HZ) / 10;
- else if (usec > 1000)
- end = ((usec/100) * CFG_HZ) / 10000;
- else
- end = (usec * CFG_HZ) / 1000000;
+ unsigned int end = start + (usec * ((CFG_HZ + 500000) / 1000000));
while (get_timer (0) < end)
continue;
@@ -91,4 +96,3 @@
{
return CFG_HZ;
}
-
diff --git a/cpu/sh4/watchdog.c b/cpu/sh4/watchdog.c
index e2bc820..04723a7 100644
--- a/cpu/sh4/watchdog.c
+++ b/cpu/sh4/watchdog.c
@@ -32,11 +32,13 @@
while (csr_read() & (1 << 5)) {
/* delay */
}
- *((volatile unsigned short *)(WDT_BASE + 0x00)) = ((unsigned short) value) | 0x5A00;
+ *((volatile unsigned short *)(WDT_BASE + 0x00))
+ = ((unsigned short) value) | 0x5A00;
}
static void csr_write (unsigned char value){
- *((volatile unsigned short *)(WDT_BASE + 0x04)) = ((unsigned short) value) | 0xA500;
+ *((volatile unsigned short *)(WDT_BASE + 0x04))
+ = ((unsigned short) value) | 0xA500;
}