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...@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, w...@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, <w...@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)
+
+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, <w...@denx.de>
+ * Zhi-zhou Zhang <etou...@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, <w...@denx.de>
+ * Zhi-zhou Zhang <etou...@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;
+}
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 <w...@denx.de>
+ *  Copyright (c) 2012 Zhi-zhou Zhang <etou...@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
+
+#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, w...@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

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to