Module Name: src
Committed By: macallan
Date: Fri Jan 29 01:54:14 UTC 2016
Modified Files:
src/sys/arch/evbmips/conf: CI20 files.ingenic
src/sys/arch/evbmips/ingenic: clock.c intr.c machdep.c mainbus.c
Added Files:
src/sys/arch/evbmips/ingenic: cpu.c cpu_startup.S
Log Message:
first shot at SMP support, very much broken and experimental
So far the 2nd core wakes up, makes its way to the idle loop, and things lock
up when we start the timer interrupt.
To generate a diff of this commit:
cvs rdiff -u -r1.20 -r1.21 src/sys/arch/evbmips/conf/CI20
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/evbmips/conf/files.ingenic
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/evbmips/ingenic/clock.c
cvs rdiff -u -r0 -r1.1 src/sys/arch/evbmips/ingenic/cpu.c \
src/sys/arch/evbmips/ingenic/cpu_startup.S
cvs rdiff -u -r1.9 -r1.10 src/sys/arch/evbmips/ingenic/intr.c \
src/sys/arch/evbmips/ingenic/machdep.c
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/evbmips/ingenic/mainbus.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/evbmips/conf/CI20
diff -u src/sys/arch/evbmips/conf/CI20:1.20 src/sys/arch/evbmips/conf/CI20:1.21
--- src/sys/arch/evbmips/conf/CI20:1.20 Sun Jan 3 06:23:25 2016
+++ src/sys/arch/evbmips/conf/CI20 Fri Jan 29 01:54:13 2016
@@ -1,4 +1,4 @@
-# $NetBSD: CI20,v 1.20 2016/01/03 06:23:25 macallan Exp $
+# $NetBSD: CI20,v 1.21 2016/01/29 01:54:13 macallan Exp $
#
# MIPS Creator CI20
#
@@ -7,7 +7,7 @@ include "arch/evbmips/conf/std.ingenic"
#options INCLUDE_CONFIG_FILE # embed config file in kernel binary
-#ident "CI20-$Revision: 1.20 $"
+#ident "CI20-$Revision: 1.21 $"
maxusers 32
@@ -138,7 +138,7 @@ config netbsd root on sd0a type ffs
mainbus0 at root
#options MULTIPROCESSOR
-cpu0 at mainbus?
+cpu* at mainbus?
#wdog0 at mainbus?
apbus0 at mainbus?
Index: src/sys/arch/evbmips/conf/files.ingenic
diff -u src/sys/arch/evbmips/conf/files.ingenic:1.5 src/sys/arch/evbmips/conf/files.ingenic:1.6
--- src/sys/arch/evbmips/conf/files.ingenic:1.5 Fri Dec 26 17:45:27 2014
+++ src/sys/arch/evbmips/conf/files.ingenic Fri Jan 29 01:54:13 2016
@@ -1,4 +1,4 @@
-# $NetBSD: files.ingenic,v 1.5 2014/12/26 17:45:27 macallan Exp $
+# $NetBSD: files.ingenic,v 1.6 2016/01/29 01:54:13 macallan Exp $
file arch/mips/mips/bus_dma.c
@@ -12,6 +12,7 @@ file arch/evbmips/ingenic/autoconf.c
file arch/evbmips/ingenic/machdep.c
file arch/evbmips/ingenic/intr.c
file arch/evbmips/ingenic/clock.c
+file arch/evbmips/ingenic/cpu_startup.S
# System bus
device mainbus { }
@@ -20,7 +21,7 @@ file arch/evbmips/ingenic/mainbus.c mai
device cpu
attach cpu at mainbus
-file arch/evbmips/evbmips/cpu.c cpu
+file arch/evbmips/ingenic/cpu.c cpu
# Memory Disk
file dev/md_root.c memory_disk_hooks
Index: src/sys/arch/evbmips/ingenic/clock.c
diff -u src/sys/arch/evbmips/ingenic/clock.c:1.6 src/sys/arch/evbmips/ingenic/clock.c:1.7
--- src/sys/arch/evbmips/ingenic/clock.c:1.6 Tue Jun 30 04:10:10 2015
+++ src/sys/arch/evbmips/ingenic/clock.c Fri Jan 29 01:54:14 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: clock.c,v 1.6 2015/06/30 04:10:10 macallan Exp $ */
+/* $NetBSD: clock.c,v 1.7 2016/01/29 01:54:14 macallan Exp $ */
/*-
* Copyright (c) 2014 Michael Lorenz
@@ -27,7 +27,9 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.6 2015/06/30 04:10:10 macallan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.7 2016/01/29 01:54:14 macallan Exp $");
+
+#include "opt_multiprocessor.h"
#include <sys/param.h>
#include <sys/cpu.h>
@@ -130,6 +132,8 @@ cpu_initclocks(void)
printf("INTC %08x %08x\n", readreg(JZ_ICSR0), readreg(JZ_ICSR1));
delay(3000000);
+ printf("%s %d\n", __func__, MFC0(12, 3));
+ printf("%s %08x\n", __func__, MFC0(12, 4));
#endif
}
@@ -190,6 +194,7 @@ void
ingenic_clockintr(uint32_t id)
{
extern struct clockframe cf;
+ int s = splsched();
struct cpu_info * const ci = curcpu();
#ifdef USE_OST
uint32_t new_cnt;
@@ -198,7 +203,6 @@ ingenic_clockintr(uint32_t id)
/* clear flags */
writereg(JZ_TC_TFCR, TFR_OSTFLAG);
- KASSERT((ci->ci_cycles_per_hz & ~(0xffffffff)) == 0);
ci->ci_next_cp0_clk_intr += (uint32_t)(ci->ci_cycles_per_hz & 0xffffffff);
#ifdef USE_OST
writereg(JZ_OST_DATA, ci->ci_next_cp0_clk_intr);
@@ -228,5 +232,13 @@ ingenic_clockintr(uint32_t id)
ingenic_puts("+");
}
#endif
+#ifdef MULTIPROCESSOR
+ /*
+ * XXX
+ * needs to take the IPI lock and ping all online CPUs, not just core 1
+ */
+ MTC0(1 << IPI_CLOCK, 20, 1);
+#endif
hardclock(&cf);
+ splx(s);
}
Index: src/sys/arch/evbmips/ingenic/intr.c
diff -u src/sys/arch/evbmips/ingenic/intr.c:1.9 src/sys/arch/evbmips/ingenic/intr.c:1.10
--- src/sys/arch/evbmips/ingenic/intr.c:1.9 Sat Apr 4 13:06:01 2015
+++ src/sys/arch/evbmips/ingenic/intr.c Fri Jan 29 01:54:14 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: intr.c,v 1.9 2015/04/04 13:06:01 macallan Exp $ */
+/* $NetBSD: intr.c,v 1.10 2016/01/29 01:54:14 macallan Exp $ */
/*-
* Copyright (c) 2014 Michael Lorenz
@@ -27,10 +27,12 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.9 2015/04/04 13:06:01 macallan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.10 2016/01/29 01:54:14 macallan Exp $");
#define __INTR_PRIVATE
+#include "opt_multiprocessor.h"
+
#include <sys/param.h>
#include <sys/cpu.h>
#include <sys/device.h>
@@ -46,9 +48,15 @@ __KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.9
#include "opt_ingenic.h"
+#ifdef INGENIC_INTR_DEBUG
+#define DPRINTF printf
+#else
+#define DPRINTF while (0) printf
+#endif
+
extern void ingenic_clockintr(uint32_t);
extern void ingenic_puts(const char *);
-
+extern struct clockframe cf;
/*
* This is a mask of bits to clear in the SR when we go to a
* given hardware interrupt priority level.
@@ -122,7 +130,12 @@ evbmips_intr_init(void)
reg = MFC0(12, 4); /* reset entry and interrupts */
reg &= 0xffff0000;
reg |= REIM_IRQ0_M | REIM_MIRQ0_M;
+#ifdef MULTIPROCESSOR
+ reg |= REIM_MIRQ1_M;
+#endif
MTC0(reg, 12, 4);
+ MTC0(0, 20, 1); /* ping the 2nd core */
+ DPRINTF("%s %08x\n", __func__, reg);
}
void
@@ -143,7 +156,7 @@ evbmips_iointr(int ipl, vaddr_t pc, uint
/*
* XXX
- * the manual counts the softint bits as INT0 and INT1, out headers
+ * the manual counts the softint bits as INT0 and INT1, our headers
* don't so everything here looks off by two
*/
if (ipending & MIPS_INT_MASK_1) {
@@ -151,6 +164,7 @@ evbmips_iointr(int ipl, vaddr_t pc, uint
* this is a mailbox interrupt / IPI
*/
uint32_t reg;
+ int s = splsched();
/* read pending IPIs */
reg = MFC0(12, 3);
@@ -176,7 +190,10 @@ evbmips_iointr(int ipl, vaddr_t pc, uint
#ifdef MULTIPROCESSOR
uint32_t tag;
tag = MFC0(CP0_CORE_MBOX, 1);
- ipi_process(curcpu(), tag);
+ ingenic_puts("1");
+ if (tag & 0x400)
+ hardclock(&cf);
+ //ipi_process(curcpu(), tag);
#ifdef INGENIC_INTR_DEBUG
snprintf(buffer, 256,
"IPI for core 1, msg %08x\n", tag);
@@ -188,6 +205,7 @@ evbmips_iointr(int ipl, vaddr_t pc, uint
MTC0(reg, 12, 3);
}
}
+ splx(s);
}
if (ipending & MIPS_INT_MASK_2) {
/* this is a timer interrupt */
@@ -211,9 +229,9 @@ evbmips_iointr(int ipl, vaddr_t pc, uint
*/
mask = readreg(JZ_ICPR0);
if (mask & 0x0c000000) {
- writereg(JZ_ICMSR0, mask);
+ writereg(JZ_ICMSR0, 0x0c000000);
ingenic_clockintr(id);
- writereg(JZ_ICMCR0, mask);
+ writereg(JZ_ICMCR0, 0x0c000000);
clockintrs.ev_count++;
}
ingenic_irq(ipl);
Index: src/sys/arch/evbmips/ingenic/machdep.c
diff -u src/sys/arch/evbmips/ingenic/machdep.c:1.9 src/sys/arch/evbmips/ingenic/machdep.c:1.10
--- src/sys/arch/evbmips/ingenic/machdep.c:1.9 Sat Jul 11 19:00:04 2015
+++ src/sys/arch/evbmips/ingenic/machdep.c Fri Jan 29 01:54:14 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: machdep.c,v 1.9 2015/07/11 19:00:04 macallan Exp $ */
+/* $NetBSD: machdep.c,v 1.10 2016/01/29 01:54:14 macallan Exp $ */
/*-
* Copyright (c) 2014 Michael Lorenz
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.9 2015/07/11 19:00:04 macallan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.10 2016/01/29 01:54:14 macallan Exp $");
#include "opt_ddb.h"
#include "opt_kgdb.h"
@@ -43,6 +43,7 @@ __KERNEL_RCSID(0, "$NetBSD: machdep.c,v
#include <sys/reboot.h>
#include <sys/cpu.h>
#include <sys/bus.h>
+#include <sys/mutex.h>
#include <uvm/uvm_extern.h>
@@ -79,6 +80,10 @@ void ingenic_putchar_init(void);
void ingenic_puts(const char *);
void ingenic_com_cnattach(void);
+#ifdef MULTIPROCESSOR
+kmutex_t ingenic_ipi_lock;
+#endif
+
static void
cal_timer(void)
{
@@ -123,12 +128,12 @@ ingenic_cpu_init(struct cpu_info *ci)
/* enable IPIs for this core */
reg = MFC0(12, 4); /* reset entry and interrupts */
- reg &= 0xffff0000;
if (cpu_index(ci) == 1) {
reg |= REIM_MIRQ1_M;
} else
reg |= REIM_MIRQ0_M;
MTC0(reg, 12, 4);
+ printf("%s %d %08x\n", __func__, cpu_index(ci), reg);
}
static int
@@ -138,6 +143,7 @@ ingenic_send_ipi(struct cpu_info *ci, in
msg = 1 << tag;
+ mutex_enter(&ingenic_ipi_lock);
if (kcpuset_isset(cpus_running, cpu_index(ci))) {
if (cpu_index(ci) == 0) {
MTC0(msg, CP0_CORE_MBOX, 0);
@@ -145,9 +151,10 @@ ingenic_send_ipi(struct cpu_info *ci, in
MTC0(msg, CP0_CORE_MBOX, 1);
}
}
+ mutex_exit(&ingenic_ipi_lock);
return 0;
}
-#endif
+#endif /* MULTIPROCESSOR */
void
mach_init(void)
@@ -221,6 +228,7 @@ mach_init(void)
mips_init_lwp0_uarea();
#ifdef MULTIPROCESSOR
+ mutex_init(&ingenic_ipi_lock, MUTEX_DEFAULT, IPL_HIGH);
mips_locoresw.lsw_send_ipi = ingenic_send_ipi;
mips_locoresw.lsw_cpu_init = ingenic_cpu_init;
#endif
Index: src/sys/arch/evbmips/ingenic/mainbus.c
diff -u src/sys/arch/evbmips/ingenic/mainbus.c:1.4 src/sys/arch/evbmips/ingenic/mainbus.c:1.5
--- src/sys/arch/evbmips/ingenic/mainbus.c:1.4 Sat Apr 4 13:06:01 2015
+++ src/sys/arch/evbmips/ingenic/mainbus.c Fri Jan 29 01:54:14 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: mainbus.c,v 1.4 2015/04/04 13:06:01 macallan Exp $ */
+/* $NetBSD: mainbus.c,v 1.5 2016/01/29 01:54:14 macallan Exp $ */
/*-
* Copyright (c) 2014 Michael Lorenz
@@ -27,7 +27,9 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.4 2015/04/04 13:06:01 macallan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.5 2016/01/29 01:54:14 macallan Exp $");
+
+#include "opt_multiprocessor.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -58,7 +60,9 @@ struct mainbusdev {
struct mainbusdev mainbusdevs[] = {
{ "cpu", },
- { "com", },
+#ifdef MULTIPROCESSOR
+ { "cpu", },
+#endif
{ "apbus", },
{ NULL, }
};
Added files:
Index: src/sys/arch/evbmips/ingenic/cpu.c
diff -u /dev/null src/sys/arch/evbmips/ingenic/cpu.c:1.1
--- /dev/null Fri Jan 29 01:54:14 2016
+++ src/sys/arch/evbmips/ingenic/cpu.c Fri Jan 29 01:54:14 2016
@@ -0,0 +1,122 @@
+/* $NetBSD: cpu.c,v 1.1 2016/01/29 01:54:14 macallan Exp $ */
+
+/*
+ * Copyright 2002 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Simon Burge for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.1 2016/01/29 01:54:14 macallan Exp $");
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+#include <sys/cpu.h>
+
+#include <mips/locore.h>
+#include <mips/asm.h>
+#include <mips/ingenic/ingenic_regs.h>
+
+#include "opt_ingenic.h"
+
+static int cpu_match(device_t, cfdata_t, void *);
+static void cpu_attach(device_t, device_t, void *);
+
+CFATTACH_DECL_NEW(cpu, 0,
+ cpu_match, cpu_attach, NULL, NULL);
+
+struct cpu_info *startup_cpu_info;
+extern void *ingenic_wakeup;
+
+static int
+cpu_match(device_t parent, cfdata_t match, void *aux)
+{
+ struct mainbusdev {
+ const char *md_name;
+ } *aa = aux;
+ if (strcmp(aa->md_name, "cpu") == 0) return 1;
+ return 0;
+}
+
+static void
+cpu_attach(device_t parent, device_t self, void *aux)
+{
+ struct cpu_info *ci = curcpu();
+ int unit;
+
+ if ((unit = device_unit(self)) > 0) {
+#ifdef MULTIPROCESSOR
+ uint32_t vec, reg;
+ int bail = 10000;
+
+ startup_cpu_info = cpu_info_alloc(NULL, unit, 0, unit, 0);
+ startup_cpu_info->ci_cpu_freq = ci->ci_cpu_freq;
+ ci = startup_cpu_info;
+ wbflush();
+ vec = (uint32_t)&ingenic_wakeup;
+ reg = MFC0(12, 4); /* reset entry reg */
+ reg &= ~REIM_ENTRY_M;
+ reg |= vec;
+ MTC0(reg, 12, 4);
+ reg = MFC0(12, 2); /* core control reg */
+ reg |= CC_RPC1; /* use our exception vector */
+ reg &= ~CC_SW_RST1; /* get core 1 out of reset */
+ MTC0(reg, 12, 2);
+ while ((!kcpuset_isset(cpus_hatched, cpu_index(startup_cpu_info))) && (bail > 0)) {
+ delay(1000);
+ bail--;
+ }
+ if (!kcpuset_isset(cpus_hatched, cpu_index(startup_cpu_info))) {
+ aprint_error_dev(self, "did not hatch\n");
+ return;
+ }
+#else
+ aprint_normal_dev(self,
+ "processor off-line; "
+ "multiprocessor support not present in kernel\n");
+ return;
+#endif
+
+ }
+ ci->ci_dev = self;
+ self->dv_private = ci;
+
+ aprint_normal(": %lu.%02luMHz (hz cycles = %lu, delay divisor = %lu)\n",
+ ci->ci_cpu_freq / 1000000,
+ (ci->ci_cpu_freq % 1000000) / 10000,
+ ci->ci_cycles_per_hz, ci->ci_divisor_delay);
+
+ aprint_normal_dev(self, "");
+ cpu_identify(self);
+ cpu_attach_common(self, ci);
+}
Index: src/sys/arch/evbmips/ingenic/cpu_startup.S
diff -u /dev/null src/sys/arch/evbmips/ingenic/cpu_startup.S:1.1
--- /dev/null Fri Jan 29 01:54:14 2016
+++ src/sys/arch/evbmips/ingenic/cpu_startup.S Fri Jan 29 01:54:14 2016
@@ -0,0 +1,130 @@
+/* $NetBSD: cpu_startup.S,v 1.1 2016/01/29 01:54:14 macallan Exp $ */
+
+/*-
+ * Copyright (c) 2015 Michael Lorenz
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opt_cputype.h"
+#include "opt_multiprocessor.h"
+
+#include <sys/cdefs.h>
+#include <sys/endian.h>
+
+#include <mips/asm.h>
+RCSID("$NetBSD: cpu_startup.S,v 1.1 2016/01/29 01:54:14 macallan Exp $");
+
+#ifdef MULTIPROCESSOR
+
+#include <mips/cpuregs.h>
+#include <mips/cache_r4k.h>
+
+#include "assym.h"
+
+#define CACHE_SIZE (32 * 1024)
+#define CACHE_LINESIZE 32
+
+NESTED_NOPROFILE(ingenic_trampoline, 0, ra)
+ /*
+ * We act as the idle lwp so make it CURLWP. When know
+ * that the cpu_info is a KSEG0 address.
+ */
+ move a0, a1
+ // Loop until idlelwp is filled in.
+1: PTR_L MIPS_CURLWP, CPU_INFO_IDLELWP(a0)
+ nop
+ beqz MIPS_CURLWP, 1b
+ nop
+ PTR_S MIPS_CURLWP, CPU_INFO_CURLWP(a0)
+
+ li v0, 0
+ mtc0 v0, MIPS_COP_0_STATUS # reset to known state
+ COP0_SYNC
+
+ PTR_L sp, L_MD_UTF(MIPS_CURLWP) # fetch KSP
+
+ /*
+ * Indicate that no one has called us.
+ */
+ move ra, zero
+ REG_S ra, CALLFRAME_RA(sp)
+
+ /*
+ * New execution constant needs GP to be loaded.
+ */
+ PTR_LA gp, _C_LABEL(_gp)
+
+ /*
+ * and off we go.
+ */
+ j _C_LABEL(cpu_hatch) # does everything
+ nop
+END(ingenic_trampoline)
+
+
+/*
+ * exception vector secondary CPUs take when started
+ */
+.p2align 16
+VECTOR(ingenic_wakeup, unknown)
+ .set noat
+
+ mtc0 zero, MIPS_COP_0_CAUSE
+ COP0_SYNC
+
+ /* init caches */
+ li t0, MIPS_KSEG0_START
+ ori t1, t0, CACHE_SIZE
+ mtc0 zero, MIPS_COP_0_TAG_LO, 0
+ COP0_SYNC
+1: cache CACHEOP_R4K_INDEX_STORE_TAG | CACHE_R4K_I, 0(t0)
+ cache CACHEOP_R4K_INDEX_STORE_TAG | CACHE_R4K_D, 0(t0)
+ addiu t0, t0, CACHE_LINESIZE
+ bne t0, t1, 1b
+ nop
+
+ /* kseg0 cache attribute */
+ mfc0 t0, MIPS_COP_0_CONFIG, 0
+ ori t0, t0, MIPS3_TLB_ATTR_WB_NONCOHERENT
+ mtc0 t0, MIPS_COP_0_CONFIG, 0
+ COP0_SYNC
+
+ /* pagemask */
+ mtc0 zero, MIPS_COP_0_TLB_PG_MASK, 0
+ COP0_SYNC
+
+ /*
+ * - set a1 to corresponding cpu_info
+ * - set sp to ci->ci_data.cpu_idlelwp->l_md.md_utf
+ * - jump to cpu_trampoline
+ */
+ PTR_L a1, _C_LABEL(startup_cpu_info)
+ nop
+
+ j ingenic_trampoline
+ nop
+ .set at
+VECTOR_END(ingenic_wakeup)
+
+#endif /* MULTIPROCESSOR */