
On Fri, Aug 24, 2012 at 8:22 AM, Daniel Schwierzeck < daniel.schwierzeck@gmail.com> wrote:
2012/8/20 Zhizhou Zhang etou.zh@gmail.com:
These files are derived from arch/mips/cpu/mips32/*. Howerver some Changes are made: *.S: changes ABI o32 to n64 config.mk: add mips64 building cflags cpu.c: add cache size probe interrupts.c: implement enable_interrupts and disable_interrupts
Signed-off-by: Zhizhou Zhang etou.zh@gmail.com
arch/mips/cpu/mips64/Makefile | 47 +++++++ arch/mips/cpu/mips64/config.mk | 39 ++++++ arch/mips/cpu/mips64/cpu.c | 124 ++++++++++++++++++ arch/mips/cpu/mips64/interrupts.c | 39 ++++++ arch/mips/cpu/mips64/start.S | 256
+++++++++++++++++++++++++++++++++++++
arch/mips/cpu/mips64/time.c | 86 +++++++++++++ 6 files changed, 591 insertions(+) create mode 100644 arch/mips/cpu/mips64/Makefile create mode 100644 arch/mips/cpu/mips64/config.mk create mode 100644 arch/mips/cpu/mips64/cpu.c create mode 100644 arch/mips/cpu/mips64/interrupts.c create mode 100644 arch/mips/cpu/mips64/start.S create mode 100644 arch/mips/cpu/mips64/time.c
diff --git a/arch/mips/cpu/mips64/Makefile
b/arch/mips/cpu/mips64/Makefile
new file mode 100644 index 0000000..335fe88 --- /dev/null +++ b/arch/mips/cpu/mips64/Makefile @@ -0,0 +1,47 @@ +# +# (C) Copyright 2003-2006 +# 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 $(TOPDIR)/config.mk
+LIB = $(obj)lib$(CPU).o
+START = start.o +COBJS-y = cpu.o interrupts.o time.o
+SRCS := $(START:.o=.S) $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y)) +START := $(addprefix $(obj),$(START))
+all: $(obj).depend $(START) $(LIB)
+$(LIB): $(OBJS)
$(call cmd_link_o_target, $(OBJS))
+#########################################################################
+# defines $(obj).depend target +include $(SRCTREE)/rules.mk
+sinclude $(obj).depend
+#########################################################################
diff --git a/arch/mips/cpu/mips64/config.mk b/arch/mips/cpu/mips64/
config.mk
new file mode 100644 index 0000000..26f79e6 --- /dev/null +++ b/arch/mips/cpu/mips64/config.mk @@ -0,0 +1,39 @@ +# +# (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 +#
+# +# Default optimization level for MIPS64 +# +# Note: Toolchains with binutils prior to v2.16 +# are no longer supported by U-Boot MIPS tree! +# +MIPSFLAGS = -march=mips64
+ENDIANNESS = -EL
+MIPSFLAGS += $(ENDIANNESS)
with current master branch in git://git.denx.de/u-boot-mips.git you can drop the endianess flags which are now handled in arch/mips/config.mk
+PLATFORM_CPPFLAGS += $(MIPSFLAGS) +PLATFORM_CPPFLAGS += -mabi=64 -DCONFIG_64BIT +PLATFORM_LDFLAGS += -m elf64ltsmip
diff --git a/arch/mips/cpu/mips64/cpu.c b/arch/mips/cpu/mips64/cpu.c new file mode 100644 index 0000000..348ccfe --- /dev/null +++ b/arch/mips/cpu/mips64/cpu.c @@ -0,0 +1,124 @@ +/*
- (C) Copyright 2003
- Wolfgang Denk, DENX Software Engineering, wd@denx.de
- Zhi-zhou Zhang etou.zh@gmail.com
- 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 <netdev.h> +#include <asm/mipsregs.h> +#include <asm/cacheops.h> +#include <asm/reboot.h> +#include <linux/compiler.h>
+void __weak _machine_restart(void) +{ +}
+int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{
_machine_restart();
fprintf(stderr, "*** reset failed ***\n");
return 0;
+}
+static struct cache_desc icache, dcache;
+void cache_probe(void) +{
int config, lsize;
config = read_c0_config1();
lsize = (config >> 19) & 7;
if (lsize) { /* icache present */
icache.linesz = 2 << lsize;
icache.sets = 32 << (((config >> 22) + 1) & 7);
icache.ways = 1 + ((config >> 16) & 7);
icache.size = icache.sets *
icache.ways *
icache.linesz;
}
lsize = (config >> 10) & 7;
if (lsize) { /* dcache present */
dcache.linesz = 2 << lsize;
dcache.sets = 32 << (((config >> 13) + 1) & 7);
dcache.ways = 1 + ((config >> 7) & 7);
dcache.size = dcache.sets *
dcache.ways *
dcache.linesz;
}
+}
+void flush_cache(ulong start_addr, ulong size) +{
unsigned long addr, aend;
/* aend will be miscalculated when size is zero, so we return
here */
if (size == 0)
return;
addr = start_addr & ~(icache.linesz - 1);
aend = (start_addr + size - 1) & ~(icache.linesz - 1);
while (1) {
cache_op(Hit_Invalidate_I, addr);
if (addr == aend)
break;
addr += icache.linesz;
}
addr = start_addr & ~(dcache.linesz - 1);
aend = (start_addr + size - 1) & ~(dcache.linesz - 1);
while (1) {
cache_op(Hit_Writeback_Inv_D, addr);
if (addr == aend)
break;
addr += dcache.linesz;
}
+}
+void flush_dcache_range(ulong start_addr, ulong stop) +{
unsigned long addr = start_addr & ~(dcache.linesz - 1);
unsigned long aend = (stop - 1) & ~(dcache.linesz - 1);
while (1) {
cache_op(Hit_Writeback_Inv_D, addr);
if (addr == aend)
break;
addr += dcache.linesz;
}
+}
+void invalidate_dcache_range(ulong start_addr, ulong stop) +{
unsigned long addr = start_addr & ~(dcache.linesz - 1);
unsigned long aend = (stop - 1) & ~(dcache.linesz - 1);
while (1) {
cache_op(Hit_Invalidate_D, addr);
if (addr == aend)
break;
addr += dcache.linesz;
}
+} diff --git a/arch/mips/cpu/mips64/interrupts.c
b/arch/mips/cpu/mips64/interrupts.c
new file mode 100644 index 0000000..f661fb0 --- /dev/null +++ b/arch/mips/cpu/mips64/interrupts.c @@ -0,0 +1,39 @@ +/*
- (C) Copyright 2003
- Wolfgang Denk, DENX Software Engineering, wd@denx.de
- Zhi-zhou Zhang etou.zh@gmail.com
- 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/mipsregs.h>
+void enable_interrupts(void) +{
int status = read_c0_status();
write_c0_status(status | ST0_IE);
+}
+int disable_interrupts(void) +{
int status = read_c0_status();
write_c0_status(status & ~ST0_IE);
return status | ST0_IE;
+}
currently we cannot use interrupts or setup any interrupt handlers in u-boot-mips. Please leave those functions empty.
diff --git a/arch/mips/cpu/mips64/start.S b/arch/mips/cpu/mips64/start.S new file mode 100644 index 0000000..b8585e7 --- /dev/null +++ b/arch/mips/cpu/mips64/start.S @@ -0,0 +1,256 @@ +/*
- Startup Code for MIPS64 CPU-core
- Copyright (c) 2003 Wolfgang Denk wd@denx.de
- Copyright (c) 2012 Zhi-zhou Zhang etou.zh@gmail.com
- 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 dlater 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 PARTICUdlaR 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 Pdlace, Suite 330, Boston,
- MA 02111-1307 USA
- */
+#include <asm-offsets.h> +#include <config.h> +#include <asm/regdef.h> +#include <asm/mipsregs.h>
+#ifndef CONFIG_SYS_MIPS_CACHE_MODE +#define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT +#endif
/*
* For the moment disable interrupts, mark the kernel mode and
* set ST0_KX so that the CPU does not spit fire when using
* 64-bit addresses.
*/
.macro setup_c0_status set clr
.set push
mfc0 t0, CP0_STATUS
or t0, ST0_CU0 | \set | 0x1f | \clr
xor t0, 0x1f | \clr
mtc0 t0, CP0_STATUS
.set noreorder
sll zero, 3 # ehb
.set pop
.endm
.set noreorder
.globl _start
.text
+_start:
.org 0x000
b reset
nop
.org 0x080
b romReserved
nop
.org 0x100
b romReserved
nop
.org 0x180
b romReserved
nop
.org 0x200
b romReserved
nop
.org 0x280
b romReserved
nop
.org 0x300
b romReserved
nop
.org 0x380
b romReserved
nop
.org 0x480
b romReserved
nop
/*
* We hope there are no more reserved vectors!
* 128 * 8 == 1024 == 0x400
* so this is address R_VEC+0x400 == 0xbfc00400
*/
.org 0x500
.align 4
+reset:
/* Clear watch registers */
dmtc0 zero, CP0_WATCHLO
dmtc0 zero, CP0_WATCHHI
/* WP(Watch Pending), SW0/1 should be cleared */
mtc0 zero, CP0_CAUSE
setup_c0_status ST0_KX 0
/* Init Timer */
mtc0 zero, CP0_COUNT
mtc0 zero, CP0_COMPARE
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
/* CONFIG0 register */
li t0, CONF_CM_UNCACHED
mtc0 t0, CP0_CONFIG
+#endif
/* Initialize $gp */
bal 1f
nop
.dword _gp
+1:
ld gp, 0(ra)
dla t9, cache_probe
jalr t9
nop
calling a C function is not supposed to work here because no stack pointer has been setup yet. I checked with Sourcery 2011.09 and 2012.03. The stack is always utilized in cache_probe. Either you rewrite the cache_probe function in assembler or you use the existing config options and you could drop the cache probing.
Thanks,
So could I put it in board/qemu-mips/qemu-mips.c? I think when power on, all cache are in invalid state, we don't need flush it at all. So only if we do cache_probe before calling flush opertaions, everything goes ok. am i right?
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
/* Initialize any external memory */
dla t9, lowlevel_init
jalr t9
nop
/* ... and enable them */
li t0, CONFIG_SYS_MIPS_CACHE_MODE
mtc0 t0, CP0_CONFIG
+#endif
/* Set up temporary stack */
li t0, CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_INIT_SP_OFFSET
dla sp, 0(t0)
dla t9, board_init_f
jr t9
nop
+/*
- void relocate_code (addr_sp, gd, addr_moni)
- This "function" does not return, instead it continues in RAM
- after relocating the monitor code.
- a0 = addr_sp
- a1 = gd
- a2 = destination address
- */
.globl relocate_code
.ent relocate_code
+relocate_code:
move sp, a0 # set new stack pointer
li t0, CONFIG_SYS_MONITOR_BASE
dla t3, in_ram
ld t2, -24(t3) # t2 <-- uboot_end_data
move t1, a2
move s2, a2 # s2 <-- destination address
/*
* Fix $gp:
*
* New $gp = (Old $gp - CONFIG_SYS_MONITOR_BASE) + Destination
Address
*/
move t8, gp
dsub gp, CONFIG_SYS_MONITOR_BASE
dadd gp, a2 # gp now adjusted
dsub s1, gp, t8 # s1 <-- relocation offset
/*
* t0 = source address
* t1 = target address
* t2 = source end address
*/
/*
* Save destination address and size for dlater usage in
flush_cache()
*/
move s0, a1 # save gd in s0
move a0, t1 # a0 <-- destination addr
dsub a1, t2, t0 # a1 <-- size
+1:
lw t3, 0(t0)
sw t3, 0(t1)
daddu t0, 4
ble t0, t2, 1b
daddu t1, 4
/* If caches were enabled, we would have to flush them here. */
/* a0 & a1 are already set up for flush_cache(start, size) */
dla t9, flush_cache
jalr t9
nop
/* Jump to where we've relocated ourselves */
daddi t0, s2, in_ram - _start
jr t0
nop
.dword _gp
.dword _GLOBAL_OFFSET_TABLE_
.dword uboot_end_data
.dword uboot_end
.dword num_got_entries
+in_ram:
/*
* Now we want to update GOT.
*
* GOT[0] is reserved. GOT[1] is also reserved for the dynamic
object
* generated by GNU ld. Skip these reserved entries from
relocation.
*/
ld t3, -8(t0) # t3 <-- num_got_entries
ld t8, -32(t0) # t8 <-- _GLOBAL_OFFSET_TABLE_
ld t9, -40(t0) # t9 <-- _gp
dsub t8, t9 # compute offset
dadd t8, t8, gp # t8 now holds relocated _G_O_T_
daddi t8, t8, 16 # skipping first two entries
li t2, 2
+1:
ld t1, 0(t8)
beqz t1, 2f
dadd t1, s1
sd t1, 0(t8)
+2:
daddi t2, 1
blt t2, t3, 1b
daddi t8, 8
/* Clear BSS */
ld t1, -24(t0) # t1 <-- uboot_end_data
ld t2, -16(t0) # t2 <-- uboot_end
dadd t1, s1 # adjust pointers
dadd t2, s1
dsub t1, 8
+1:
daddi t1, 8
bltl t1, t2, 1b
sd zero, 0(t1)
move a0, s0 # a0 <-- gd
dla t9, board_init_r
jr t9
move a1, s2
.end relocate_code
/* Exception handlers */
+romReserved:
b romReserved
diff --git a/arch/mips/cpu/mips64/time.c b/arch/mips/cpu/mips64/time.c new file mode 100644 index 0000000..350896a --- /dev/null +++ b/arch/mips/cpu/mips64/time.c @@ -0,0 +1,86 @@ +/*
- (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 <asm/mipsregs.h>
+static unsigned long timestamp;
+/* how many counter cycles in a jiffy */ +#define CYCLES_PER_JIFFY (CONFIG_SYS_MIPS_TIMER_FREQ +
CONFIG_SYS_HZ / 2) / CONFIG_SYS_HZ
+/*
- timer without interrupts
- */
+int timer_init(void) +{
/* Set up the timer for the first expiration. */
timestamp = 0;
write_c0_compare(read_c0_count() + CYCLES_PER_JIFFY);
return 0;
+}
+ulong get_timer(ulong base) +{
unsigned int count;
unsigned int expirelo = read_c0_compare();
/* Check to see if we have missed any timestamps. */
count = read_c0_count();
while ((count - expirelo) < 0x7fffffff) {
expirelo += CYCLES_PER_JIFFY;
timestamp++;
}
write_c0_compare(expirelo);
return (timestamp - base);
+}
+void __udelay(unsigned long usec) +{
unsigned int tmo;
tmo = read_c0_count() + (usec * (CONFIG_SYS_MIPS_TIMER_FREQ /
1000000));
while ((tmo - read_c0_count()) < 0x7fffffff)
/*NOP*/;
+}
+/*
- This function is derived from PowerPC code (read timebase as long
long).
- On MIPS it just returns the timer value.
- */
+unsigned long long get_ticks(void) +{
return get_timer(0);
+}
+/*
- This function is derived from PowerPC code (timebase clock
frequency).
- On MIPS it returns the number of timer ticks per second.
- */
+ulong get_tbclk(void) +{
return CONFIG_SYS_HZ;
+}
1.7.9.5
-- Best regards, Daniel