aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/mips-boards/sim
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2005-09-30 08:59:37 -0400
committerRalf Baechle <ralf@linux-mips.org>2005-10-29 14:32:30 -0400
commitc78cbf49c4edf2f9ca9e56d4b87a5d6ef08b7fed (patch)
tree44bee3daac887df59c0d69658b19c21da4e1839f /arch/mips/mips-boards/sim
parentb288f135872b651ebf6cd1565d0709a5e31997f7 (diff)
Support for MIPSsim, the cycle accurate MIPS simulator.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/mips-boards/sim')
-rw-r--r--arch/mips/mips-boards/sim/Makefile20
-rw-r--r--arch/mips/mips-boards/sim/cmdline.c59
-rw-r--r--arch/mips/mips-boards/sim/sim_IRQ.c148
-rw-r--r--arch/mips/mips-boards/sim/sim_cmdline.c33
-rw-r--r--arch/mips/mips-boards/sim/sim_int.c41
-rw-r--r--arch/mips/mips-boards/sim/sim_irq.S99
-rw-r--r--arch/mips/mips-boards/sim/sim_mem.c129
-rw-r--r--arch/mips/mips-boards/sim/sim_printf.c74
-rw-r--r--arch/mips/mips-boards/sim/sim_setup.c101
-rw-r--r--arch/mips/mips-boards/sim/sim_smp.c151
-rw-r--r--arch/mips/mips-boards/sim/sim_time.c215
11 files changed, 1070 insertions, 0 deletions
diff --git a/arch/mips/mips-boards/sim/Makefile b/arch/mips/mips-boards/sim/Makefile
new file mode 100644
index 000000000000..5b977de4ecff
--- /dev/null
+++ b/arch/mips/mips-boards/sim/Makefile
@@ -0,0 +1,20 @@
1#
2# Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved.
3#
4# This program is free software; you can distribute it and/or modify it
5# under the terms of the GNU General Public License (Version 2) as
6# published by the Free Software Foundation.
7#
8# This program is distributed in the hope it will be useful, but WITHOUT
9# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11# for more details.
12#
13# You should have received a copy of the GNU General Public License along
14# with this program; if not, write to the Free Software Foundation, Inc.,
15# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
16#
17
18obj-y := sim_setup.o sim_mem.o sim_time.o sim_printf.o sim_int.o sim_irq.o \
19 sim_cmdline.o
20obj-$(CONFIG_SMP) += sim_smp.o
diff --git a/arch/mips/mips-boards/sim/cmdline.c b/arch/mips/mips-boards/sim/cmdline.c
new file mode 100644
index 000000000000..fef9fbd8e710
--- /dev/null
+++ b/arch/mips/mips-boards/sim/cmdline.c
@@ -0,0 +1,59 @@
1/*
2 * Carsten Langgaard, carstenl@mips.com
3 * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
4 *
5 * This program is free software; you can distribute it and/or modify it
6 * under the terms of the GNU General Public License (Version 2) as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
17 *
18 * Kernel command line creation using the prom monitor (YAMON) argc/argv.
19 */
20#include <linux/init.h>
21#include <linux/string.h>
22
23#include <asm/bootinfo.h>
24
25extern int prom_argc;
26extern int *_prom_argv;
27
28/*
29 * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
30 * This macro take care of sign extension.
31 */
32#define prom_argv(index) ((char *)(((int *)(int)_prom_argv)[(index)]))
33
34char arcs_cmdline[CL_SIZE];
35
36char * __init prom_getcmdline(void)
37{
38 return &(arcs_cmdline[0]);
39}
40
41
42void __init prom_init_cmdline(void)
43{
44 char *cp;
45 int actr;
46
47 actr = 1; /* Always ignore argv[0] */
48
49 cp = &(arcs_cmdline[0]);
50 while(actr < prom_argc) {
51 strcpy(cp, prom_argv(actr));
52 cp += strlen(prom_argv(actr));
53 *cp++ = ' ';
54 actr++;
55 }
56 if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
57 --cp;
58 *cp = '\0';
59}
diff --git a/arch/mips/mips-boards/sim/sim_IRQ.c b/arch/mips/mips-boards/sim/sim_IRQ.c
new file mode 100644
index 000000000000..9987a85aabeb
--- /dev/null
+++ b/arch/mips/mips-boards/sim/sim_IRQ.c
@@ -0,0 +1,148 @@
1/*
2 * Carsten Langgaard, carstenl@mips.com
3 * Copyright (C) 1999, 2000 MIPS Technologies, Inc. All rights reserved.
4 *
5 * This program is free software; you can distribute it and/or modify it
6 * under the terms of the GNU General Public License (Version 2) as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
17 *
18 * Interrupt exception dispatch code.
19 */
20#include <linux/config.h>
21
22#include <asm/asm.h>
23#include <asm/mipsregs.h>
24#include <asm/regdef.h>
25#include <asm/stackframe.h>
26
27/* A lot of complication here is taken away because:
28 *
29 * 1) We handle one interrupt and return, sitting in a loop and moving across
30 * all the pending IRQ bits in the cause register is _NOT_ the answer, the
31 * common case is one pending IRQ so optimize in that direction.
32 *
33 * 2) We need not check against bits in the status register IRQ mask, that
34 * would make this routine slow as hell.
35 *
36 * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
37 * between like BSD spl() brain-damage.
38 *
39 * Furthermore, the IRQs on the MIPS board look basically (barring software
40 * IRQs which we don't use at all and all external interrupt sources are
41 * combined together on hardware interrupt 0 (MIPS IRQ 2)) like:
42 *
43 * MIPS IRQ Source
44 * -------- ------
45 * 0 Software (ignored)
46 * 1 Software (ignored)
47 * 2 Combined hardware interrupt (hw0)
48 * 3 Hardware (ignored)
49 * 4 Hardware (ignored)
50 * 5 Hardware (ignored)
51 * 6 Hardware (ignored)
52 * 7 R4k timer (what we use)
53 *
54 * Note: On the SEAD board thing are a little bit different.
55 * Here IRQ 2 (hw0) is wired to the UART0 and IRQ 3 (hw1) is wired
56 * wired to UART1.
57 *
58 * We handle the IRQ according to _our_ priority which is:
59 *
60 * Highest ---- R4k Timer
61 * Lowest ---- Combined hardware interrupt
62 *
63 * then we just return, if multiple IRQs are pending then we will just take
64 * another exception, big deal.
65 */
66
67 .text
68 .set noreorder
69 .set noat
70 .align 5
71 NESTED(mipsIRQ, PT_SIZE, sp)
72 SAVE_ALL
73 CLI
74 .set at
75
76 mfc0 s0, CP0_CAUSE # get irq bits
77 mfc0 s1, CP0_STATUS # get irq mask
78 and s0, s1
79
80 /* First we check for r4k counter/timer IRQ. */
81 andi a0, s0, CAUSEF_IP7
82 beq a0, zero, 1f
83 andi a0, s0, CAUSEF_IP2 # delay slot, check hw0 interrupt
84
85 /* Wheee, a timer interrupt. */
86 move a0, sp
87 jal mips_timer_interrupt
88 nop
89
90 j ret_from_irq
91 nop
92
931:
94#if defined(CONFIG_MIPS_SEAD)
95 beq a0, zero, 1f
96 andi a0, s0, CAUSEF_IP3 # delay slot, check hw1 interrupt
97#else
98 beq a0, zero, 1f # delay slot, check hw3 interrupt
99 andi a0, s0, CAUSEF_IP5
100#endif
101
102 /* Wheee, combined hardware level zero interrupt. */
103#if defined(CONFIG_MIPS_ATLAS)
104 jal atlas_hw0_irqdispatch
105#elif defined(CONFIG_MIPS_MALTA)
106 jal malta_hw0_irqdispatch
107#elif defined(CONFIG_MIPS_SEAD)
108 jal sead_hw0_irqdispatch
109#else
110#error "MIPS board not supported\n"
111#endif
112 move a0, sp # delay slot
113
114 j ret_from_irq
115 nop # delay slot
116
1171:
118#if defined(CONFIG_MIPS_SEAD)
119 beq a0, zero, 1f
120 andi a0, s0, CAUSEF_IP5 # delay slot, check hw3 interrupt
121 jal sead_hw1_irqdispatch
122 move a0, sp # delay slot
123 j ret_from_irq
124 nop # delay slot
1251:
126#endif
127#if defined(CONFIG_MIPS_MALTA)
128 beq a0, zero, 1f # check hw3 (coreHI) interrupt
129 nop
130 jal corehi_irqdispatch
131 move a0, sp
132 j ret_from_irq
133 nop
1341:
135#endif
136 /*
137 * Here by mistake? This is possible, what can happen is that by the
138 * time we take the exception the IRQ pin goes low, so just leave if
139 * this is the case.
140 */
141 move a1,s0
142 PRINT("Got interrupt: c0_cause = %08x\n")
143 mfc0 a1, CP0_EPC
144 PRINT("c0_epc = %08x\n")
145
146 j ret_from_irq
147 nop
148 END(mipsIRQ)
diff --git a/arch/mips/mips-boards/sim/sim_cmdline.c b/arch/mips/mips-boards/sim/sim_cmdline.c
new file mode 100644
index 000000000000..9df37c6fca36
--- /dev/null
+++ b/arch/mips/mips-boards/sim/sim_cmdline.c
@@ -0,0 +1,33 @@
1/*
2 * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved.
3 *
4 * This program is free software; you can distribute it and/or modify it
5 * under the terms of the GNU General Public License (Version 2) as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
16 *
17 */
18#include <linux/init.h>
19#include <linux/string.h>
20#include <asm/bootinfo.h>
21
22extern char arcs_cmdline[];
23
24char * __init prom_getcmdline(void)
25{
26 return arcs_cmdline;
27}
28
29
30void __init prom_init_cmdline(void)
31{
32 /* nothing to do */
33}
diff --git a/arch/mips/mips-boards/sim/sim_int.c b/arch/mips/mips-boards/sim/sim_int.c
new file mode 100644
index 000000000000..a4d0a2c05031
--- /dev/null
+++ b/arch/mips/mips-boards/sim/sim_int.c
@@ -0,0 +1,41 @@
1/*
2 * Copyright (C) 1999, 2005 MIPS Technologies, Inc. All rights reserved.
3 *
4 * This program is free software; you can distribute it and/or modify it
5 * under the terms of the GNU General Public License (Version 2) as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
16 *
17 */
18#include <linux/init.h>
19#include <linux/sched.h>
20#include <linux/slab.h>
21#include <linux/interrupt.h>
22#include <linux/kernel_stat.h>
23#include <asm/mips-boards/simint.h>
24
25
26extern void mips_cpu_irq_init(int);
27
28extern asmlinkage void simIRQ(void);
29
30asmlinkage void sim_hw0_irqdispatch(struct pt_regs *regs)
31{
32 do_IRQ(2, regs);
33}
34
35void __init arch_init_irq(void)
36{
37 /* Now safe to set the exception vector. */
38 set_except_vector(0, simIRQ);
39
40 mips_cpu_irq_init(MIPSCPU_INT_BASE);
41}
diff --git a/arch/mips/mips-boards/sim/sim_irq.S b/arch/mips/mips-boards/sim/sim_irq.S
new file mode 100644
index 000000000000..835f0387fcd4
--- /dev/null
+++ b/arch/mips/mips-boards/sim/sim_irq.S
@@ -0,0 +1,99 @@
1/*
2 * Copyright (C) 1999, 2005 MIPS Technologies, Inc. All rights reserved.
3 *
4 * This program is free software; you can distribute it and/or modify it
5 * under the terms of the GNU General Public License (Version 2) as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
16 *
17 * Interrupt exception dispatch code.
18 *
19 */
20#include <linux/config.h>
21
22#include <asm/asm.h>
23#include <asm/mipsregs.h>
24#include <asm/regdef.h>
25#include <asm/stackframe.h>
26
27#include <asm/mips-boards/simint.h>
28
29
30 .text
31 .set noreorder
32 .set noat
33 .align 5
34 NESTED(simIRQ, PT_SIZE, sp)
35 SAVE_ALL
36 CLI
37 .set at
38
39 mfc0 s0, CP0_CAUSE # get irq bits
40 mfc0 s1, CP0_STATUS # get irq mask
41 andi s0, ST0_IM # CAUSE.CE may be non-zero!
42 and s0, s1
43
44#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
45 .set mips32
46 clz a0, s0
47 .set mips0
48 negu a0
49 addu a0, 31-CAUSEB_IP
50 bltz a0, spurious
51#else
52 beqz s0, spurious
53 li a0, 7
54
55 and t0, s0, 0xf000
56 sltiu t0, t0, 1
57 sll t0, 2
58 subu a0, t0
59 sll s0, t0
60
61 and t0, s0, 0xc000
62 sltiu t0, t0, 1
63 sll t0, 1
64 subu a0, t0
65 sll s0, t0
66
67 and t0, s0, 0x8000
68 sltiu t0, t0, 1
69 # sll t0, 0
70 subu a0, t0
71 # sll s0, t0
72#endif
73
74#ifdef CASCADE_IRQ
75 li a1, CASCADE_IRQ
76 bne a0, a1, 1f
77 addu a0, MIPSCPU_INT_BASE
78
79 jal CASCADE_DISPATCH
80 move a0, sp
81
82 j ret_from_irq
83 nop
841:
85#else
86 addu a0, MIPSCPU_INT_BASE
87#endif
88
89 jal do_IRQ
90 move a1, sp
91
92 j ret_from_irq
93 nop
94
95
96spurious:
97 j spurious_interrupt
98 nop
99 END(simIRQ)
diff --git a/arch/mips/mips-boards/sim/sim_mem.c b/arch/mips/mips-boards/sim/sim_mem.c
new file mode 100644
index 000000000000..0dbd7435bb2a
--- /dev/null
+++ b/arch/mips/mips-boards/sim/sim_mem.c
@@ -0,0 +1,129 @@
1/*
2 * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved.
3 *
4 * This program is free software; you can distribute it and/or modify it
5 * under the terms of the GNU General Public License (Version 2) as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
16 *
17 */
18#include <linux/init.h>
19#include <linux/mm.h>
20#include <linux/bootmem.h>
21
22#include <asm/bootinfo.h>
23#include <asm/page.h>
24
25#include <asm/mips-boards/prom.h>
26
27/*#define DEBUG*/
28
29enum simmem_memtypes {
30 simmem_reserved = 0,
31 simmem_free,
32};
33struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS];
34
35#ifdef DEBUG
36static char *mtypes[3] = {
37 "SIM reserved memory",
38 "SIM free memory",
39};
40#endif
41
42/* References to section boundaries */
43extern char _end;
44
45#define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
46
47
48struct prom_pmemblock * __init prom_getmdesc(void)
49{
50 unsigned int memsize;
51
52 memsize = 0x02000000;
53 prom_printf("Setting default memory size 0x%08x\n", memsize);
54
55 memset(mdesc, 0, sizeof(mdesc));
56
57 mdesc[0].type = simmem_reserved;
58 mdesc[0].base = 0x00000000;
59 mdesc[0].size = 0x00001000;
60
61 mdesc[1].type = simmem_free;
62 mdesc[1].base = 0x00001000;
63 mdesc[1].size = 0x000ff000;
64
65 mdesc[2].type = simmem_reserved;
66 mdesc[2].base = 0x00100000;
67 mdesc[2].size = CPHYSADDR(PFN_ALIGN(&_end)) - mdesc[2].base;
68
69 mdesc[3].type = simmem_free;
70 mdesc[3].base = CPHYSADDR(PFN_ALIGN(&_end));
71 mdesc[3].size = memsize - mdesc[3].base;
72
73 return &mdesc[0];
74}
75
76static int __init prom_memtype_classify (unsigned int type)
77{
78 switch (type) {
79 case simmem_free:
80 return BOOT_MEM_RAM;
81 case simmem_reserved:
82 default:
83 return BOOT_MEM_RESERVED;
84 }
85}
86
87void __init prom_meminit(void)
88{
89 struct prom_pmemblock *p;
90
91 p = prom_getmdesc();
92
93 while (p->size) {
94 long type;
95 unsigned long base, size;
96
97 type = prom_memtype_classify (p->type);
98 base = p->base;
99 size = p->size;
100
101 add_memory_region(base, size, type);
102 p++;
103 }
104}
105
106unsigned long __init prom_free_prom_memory(void)
107{
108 int i;
109 unsigned long freed = 0;
110 unsigned long addr;
111
112 for (i = 0; i < boot_mem_map.nr_map; i++) {
113 if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
114 continue;
115
116 addr = boot_mem_map.map[i].addr;
117 while (addr < boot_mem_map.map[i].addr
118 + boot_mem_map.map[i].size) {
119 ClearPageReserved(virt_to_page(__va(addr)));
120 set_page_count(virt_to_page(__va(addr)), 1);
121 free_page((unsigned long)__va(addr));
122 addr += PAGE_SIZE;
123 freed += PAGE_SIZE;
124 }
125 }
126 printk("Freeing prom memory: %ldkb freed\n", freed >> 10);
127
128 return freed;
129}
diff --git a/arch/mips/mips-boards/sim/sim_printf.c b/arch/mips/mips-boards/sim/sim_printf.c
new file mode 100644
index 000000000000..3ee5a0b501a6
--- /dev/null
+++ b/arch/mips/mips-boards/sim/sim_printf.c
@@ -0,0 +1,74 @@
1/*
2 * Carsten Langgaard, carstenl@mips.com
3 * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
4 *
5 * This program is free software; you can distribute it and/or modify it
6 * under the terms of the GNU General Public License (Version 2) as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
17 *
18 * Putting things on the screen/serial line using YAMONs facilities.
19 */
20#include <linux/init.h>
21#include <linux/kernel.h>
22#include <linux/serial_reg.h>
23#include <linux/spinlock.h>
24#include <asm/io.h>
25#include <asm/system.h>
26
27static inline unsigned int serial_in(int offset)
28{
29 return inb(0x3f8 + offset);
30}
31
32static inline void serial_out(int offset, int value)
33{
34 outb(value, 0x3f8 + offset);
35}
36
37int putPromChar(char c)
38{
39 while ((serial_in(UART_LSR) & UART_LSR_THRE) == 0)
40 ;
41
42 serial_out(UART_TX, c);
43
44 return 1;
45}
46
47char getPromChar(void)
48{
49 while (!(serial_in(UART_LSR) & 1))
50 ;
51
52 return serial_in(UART_RX);
53}
54
55void prom_printf(char *fmt, ...)
56{
57 va_list args;
58 int l;
59 char *p, *buf_end;
60 char buf[1024];
61
62 va_start(args, fmt);
63 l = vsprintf(buf, fmt, args); /* hopefully i < sizeof(buf) */
64 va_end(args);
65
66 buf_end = buf + l;
67
68 for (p = buf; p < buf_end; p++) {
69 /* Crude cr/nl handling is better than none */
70 if (*p == '\n')
71 putPromChar('\r');
72 putPromChar(*p);
73 }
74}
diff --git a/arch/mips/mips-boards/sim/sim_setup.c b/arch/mips/mips-boards/sim/sim_setup.c
new file mode 100644
index 000000000000..485d5a58d9cf
--- /dev/null
+++ b/arch/mips/mips-boards/sim/sim_setup.c
@@ -0,0 +1,101 @@
1/*
2 * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved.
3 *
4 * This program is free software; you can distribute it and/or modify it
5 * under the terms of the GNU General Public License (Version 2) as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
16 *
17 */
18
19#include <linux/config.h>
20#include <linux/init.h>
21#include <linux/string.h>
22#include <linux/kernel.h>
23#include <linux/ioport.h>
24#include <linux/tty.h>
25#include <linux/serial.h>
26#include <linux/serial_core.h>
27
28#include <asm/cpu.h>
29#include <asm/bootinfo.h>
30#include <asm/irq.h>
31#include <asm/mips-boards/generic.h>
32#include <asm/mips-boards/prom.h>
33#include <asm/serial.h>
34#include <asm/io.h>
35#include <asm/time.h>
36#include <asm/mips-boards/sim.h>
37#include <asm/mips-boards/simint.h>
38
39
40extern void sim_time_init(void);
41extern void sim_timer_setup(struct irqaction *irq);
42static void __init serial_init(void);
43unsigned int _isbonito = 0;
44
45extern void __init sanitize_tlb_entries(void);
46
47
48const char *get_system_type(void)
49{
50 return "MIPSsim";
51}
52
53void __init plat_setup(void)
54{
55 set_io_port_base(0xbfd00000);
56
57 serial_init();
58
59 board_time_init = sim_time_init;
60 board_timer_setup = sim_timer_setup;
61 prom_printf("Linux started...\n");
62
63#ifdef CONFIG_MT_SMP
64 sanitize_tlb_entries();
65#endif
66}
67
68void prom_init(void)
69{
70 set_io_port_base(0xbfd00000);
71
72 prom_printf("\nLINUX started...\n");
73 prom_init_cmdline();
74 prom_meminit();
75}
76
77
78static void __init serial_init(void)
79{
80#ifdef CONFIG_SERIAL_8250
81 struct uart_port s;
82
83 memset(&s, 0, sizeof(s));
84
85 s.iobase = 0x3f8;
86
87 /* hardware int 4 - the serial int, is CPU int 6
88 but poll for now */
89 s.irq = 0;
90 s.uartclk = BASE_BAUD * 16;
91 s.flags = ASYNC_BOOT_AUTOCONF | UPF_SKIP_TEST;
92 s.iotype = SERIAL_IO_PORT | ASYNC_SKIP_TEST;
93 s.regshift = 0;
94 s.timeout = 4;
95
96 if (early_serial_setup(&s) != 0) {
97 prom_printf(KERN_ERR "Serial setup failed!\n");
98 }
99
100#endif
101}
diff --git a/arch/mips/mips-boards/sim/sim_smp.c b/arch/mips/mips-boards/sim/sim_smp.c
new file mode 100644
index 000000000000..19824359f5de
--- /dev/null
+++ b/arch/mips/mips-boards/sim/sim_smp.c
@@ -0,0 +1,151 @@
1/*
2 * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved.
3 *
4 * This program is free software; you can distribute it and/or modify it
5 * under the terms of the GNU General Public License (Version 2) as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
16 *
17 */
18/*
19 * Simulator Platform-specific hooks for SMP operation
20 */
21#include <linux/config.h>
22#include <linux/kernel.h>
23#include <linux/sched.h>
24#include <linux/cpumask.h>
25#include <linux/interrupt.h>
26#include <asm/atomic.h>
27#include <asm/cpu.h>
28#include <asm/processor.h>
29#include <asm/system.h>
30#include <asm/hardirq.h>
31#include <asm/mmu_context.h>
32#include <asm/smp.h>
33#ifdef CONFIG_MIPS_MT_SMTC
34#include <asm/smtc_ipi.h>
35#endif /* CONFIG_MIPS_MT_SMTC */
36
37/* VPE/SMP Prototype implements platform interfaces directly */
38#if !defined(CONFIG_MIPS_MT_SMP)
39
40/*
41 * Cause the specified action to be performed on a targeted "CPU"
42 */
43
44void core_send_ipi(int cpu, unsigned int action)
45{
46#ifdef CONFIG_MIPS_MT_SMTC
47 void smtc_send_ipi(int, int, unsigned int);
48
49 smtc_send_ipi(cpu, LINUX_SMP_IPI, action);
50#endif /* CONFIG_MIPS_MT_SMTC */
51/* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */
52
53}
54
55/*
56 * Detect available CPUs/VPEs/TCs and populate phys_cpu_present_map
57 */
58
59void __init prom_build_cpu_map(void)
60{
61#ifdef CONFIG_MIPS_MT_SMTC
62 extern int mipsmt_build_cpu_map(int startslot);
63 int nextslot;
64
65 cpus_clear(phys_cpu_present_map);
66
67 /* Register the boot CPU */
68
69 smp_prepare_boot_cpu();
70
71 /*
72 * As of November, 2004, MIPSsim only simulates one core
73 * at a time. However, that core may be a MIPS MT core
74 * with multiple virtual processors and thread contexts.
75 */
76
77 if (read_c0_config3() & (1<<2)) {
78 nextslot = mipsmt_build_cpu_map(1);
79 }
80#endif /* CONFIG_MIPS_MT_SMTC */
81}
82
83/*
84 * Platform "CPU" startup hook
85 */
86
87void prom_boot_secondary(int cpu, struct task_struct *idle)
88{
89#ifdef CONFIG_MIPS_MT_SMTC
90 extern void smtc_boot_secondary(int cpu, struct task_struct *t);
91
92 smtc_boot_secondary(cpu, idle);
93#endif /* CONFIG_MIPS_MT_SMTC */
94}
95
96/*
97 * Post-config but pre-boot cleanup entry point
98 */
99
100void prom_init_secondary(void)
101{
102#ifdef CONFIG_MIPS_MT_SMTC
103 void smtc_init_secondary(void);
104
105 smtc_init_secondary();
106#endif /* CONFIG_MIPS_MT_SMTC */
107}
108
109/*
110 * Platform SMP pre-initialization
111 */
112
113void prom_prepare_cpus(unsigned int max_cpus)
114{
115#ifdef CONFIG_MIPS_MT_SMTC
116 void mipsmt_prepare_cpus(int c);
117 /*
118 * As noted above, we can assume a single CPU for now
119 * but it may be multithreaded.
120 */
121
122 if (read_c0_config3() & (1<<2)) {
123 mipsmt_prepare_cpus(max_cpus);
124 }
125#endif /* CONFIG_MIPS_MT_SMTC */
126}
127
128/*
129 * SMP initialization finalization entry point
130 */
131
132void prom_smp_finish(void)
133{
134#ifdef CONFIG_MIPS_MT_SMTC
135 void smtc_smp_finish(void);
136
137 smtc_smp_finish();
138#endif /* CONFIG_MIPS_MT_SMTC */
139}
140
141/*
142 * Hook for after all CPUs are online
143 */
144
145void prom_cpus_done(void)
146{
147#ifdef CONFIG_MIPS_MT_SMTC
148
149#endif /* CONFIG_MIPS_MT_SMTC */
150}
151#endif /* CONFIG_MIPS32R2_MT_SMP */
diff --git a/arch/mips/mips-boards/sim/sim_time.c b/arch/mips/mips-boards/sim/sim_time.c
new file mode 100644
index 000000000000..18b968c696d1
--- /dev/null
+++ b/arch/mips/mips-boards/sim/sim_time.c
@@ -0,0 +1,215 @@
1#include <linux/types.h>
2#include <linux/config.h>
3#include <linux/init.h>
4#include <linux/kernel_stat.h>
5#include <linux/sched.h>
6#include <linux/spinlock.h>
7
8#include <asm/mipsregs.h>
9#include <asm/ptrace.h>
10#include <asm/hardirq.h>
11#include <asm/div64.h>
12#include <asm/cpu.h>
13#include <asm/time.h>
14
15#include <linux/interrupt.h>
16#include <linux/mc146818rtc.h>
17#include <linux/timex.h>
18#include <asm/mipsregs.h>
19#include <asm/ptrace.h>
20#include <asm/hardirq.h>
21#include <asm/irq.h>
22#include <asm/div64.h>
23#include <asm/cpu.h>
24#include <asm/time.h>
25#include <asm/mc146818-time.h>
26#include <asm/msc01_ic.h>
27
28#include <asm/mips-boards/generic.h>
29#include <asm/mips-boards/prom.h>
30#include <asm/mips-boards/simint.h>
31#include <asm/mc146818-time.h>
32#include <asm/smp.h>
33
34
35unsigned long cpu_khz;
36
37extern asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs);
38
39irqreturn_t sim_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
40{
41#ifdef CONFIG_SMP
42 int cpu = smp_processor_id();
43
44 /*
45 * CPU 0 handles the global timer interrupt job
46 * resets count/compare registers to trigger next timer int.
47 */
48#ifndef CONFIG_MIPS_MT_SMTC
49 if (cpu == 0) {
50 timer_interrupt(irq, dev_id, regs);
51 }
52 else {
53 /* Everyone else needs to reset the timer int here as
54 ll_local_timer_interrupt doesn't */
55 /*
56 * FIXME: need to cope with counter underflow.
57 * More support needs to be added to kernel/time for
58 * counter/timer interrupts on multiple CPU's
59 */
60 write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ));
61 }
62#else /* SMTC */
63 /*
64 * In SMTC system, one Count/Compare set exists per VPE.
65 * Which TC within a VPE gets the interrupt is essentially
66 * random - we only know that it shouldn't be one with
67 * IXMT set. Whichever TC gets the interrupt needs to
68 * send special interprocessor interrupts to the other
69 * TCs to make sure that they schedule, etc.
70 *
71 * That code is specific to the SMTC kernel, not to
72 * the simulation platform, so it's invoked from
73 * the general MIPS timer_interrupt routine.
74 *
75 * We have a problem in that the interrupt vector code
76 * had to turn off the timer IM bit to avoid redundant
77 * entries, but we may never get to mips_cpu_irq_end
78 * to turn it back on again if the scheduler gets
79 * involved. So we clear the pending timer here,
80 * and re-enable the mask...
81 */
82
83 int vpflags = dvpe();
84 write_c0_compare (read_c0_count() - 1);
85 clear_c0_cause(0x100 << MIPSCPU_INT_CPUCTR);
86 set_c0_status(0x100 << MIPSCPU_INT_CPUCTR);
87 irq_enable_hazard();
88 evpe(vpflags);
89
90 if(cpu_data[cpu].vpe_id == 0) timer_interrupt(irq, dev_id, regs);
91 else write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ));
92 smtc_timer_broadcast(cpu_data[cpu].vpe_id);
93
94#endif /* CONFIG_MIPS_MT_SMTC */
95
96 /*
97 * every CPU should do profiling and process accounting
98 */
99 local_timer_interrupt (irq, dev_id, regs);
100 return IRQ_HANDLED;
101#else
102 return timer_interrupt (irq, dev_id, regs);
103#endif
104}
105
106
107
108/*
109 * Estimate CPU frequency. Sets mips_counter_frequency as a side-effect
110 */
111static unsigned int __init estimate_cpu_frequency(void)
112{
113 unsigned int prid = read_c0_prid() & 0xffff00;
114 unsigned int count;
115
116#if 1
117 /*
118 * hardwire the board frequency to 12MHz.
119 */
120
121 if ((prid == (PRID_COMP_MIPS | PRID_IMP_20KC)) ||
122 (prid == (PRID_COMP_MIPS | PRID_IMP_25KF)))
123 count = 12000000;
124 else
125 count = 6000000;
126#else
127 unsigned int flags;
128
129 local_irq_save(flags);
130
131 /* Start counter exactly on falling edge of update flag */
132 while (CMOS_READ(RTC_REG_A) & RTC_UIP);
133 while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
134
135 /* Start r4k counter. */
136 write_c0_count(0);
137
138 /* Read counter exactly on falling edge of update flag */
139 while (CMOS_READ(RTC_REG_A) & RTC_UIP);
140 while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
141
142 count = read_c0_count();
143
144 /* restore interrupts */
145 local_irq_restore(flags);
146#endif
147
148 mips_hpt_frequency = count;
149
150 if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) &&
151 (prid != (PRID_COMP_MIPS | PRID_IMP_25KF)))
152 count *= 2;
153
154 count += 5000; /* round */
155 count -= count%10000;
156
157 return count;
158}
159
160void __init sim_time_init(void)
161{
162 unsigned int est_freq, flags;
163
164 local_irq_save(flags);
165
166
167 /* Set Data mode - binary. */
168 CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL);
169
170
171 est_freq = estimate_cpu_frequency ();
172
173 printk("CPU frequency %d.%02d MHz\n", est_freq/1000000,
174 (est_freq%1000000)*100/1000000);
175
176 cpu_khz = est_freq / 1000;
177
178 local_irq_restore(flags);
179}
180
181static int mips_cpu_timer_irq;
182
183static void mips_timer_dispatch (struct pt_regs *regs)
184{
185 do_IRQ (mips_cpu_timer_irq, regs);
186}
187
188
189void __init sim_timer_setup(struct irqaction *irq)
190{
191 if (cpu_has_veic) {
192 set_vi_handler(MSC01E_INT_CPUCTR, mips_timer_dispatch);
193 mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR;
194 }
195 else {
196 if (cpu_has_vint)
197 set_vi_handler(MIPSCPU_INT_CPUCTR, mips_timer_dispatch);
198 mips_cpu_timer_irq = MIPSCPU_INT_BASE + MIPSCPU_INT_CPUCTR;
199 }
200
201 /* we are using the cpu counter for timer interrupts */
202 irq->handler = sim_timer_interrupt;
203 setup_irq(mips_cpu_timer_irq, irq);
204
205#ifdef CONFIG_SMP
206 /* irq_desc(riptor) is a global resource, when the interrupt overlaps
207 on seperate cpu's the first one tries to handle the second interrupt.
208 The effect is that the int remains disabled on the second cpu.
209 Mark the interrupt with IRQ_PER_CPU to avoid any confusion */
210 irq_desc[mips_cpu_timer_irq].status |= IRQ_PER_CPU;
211#endif
212
213 /* to generate the first timer interrupt */
214 write_c0_compare(read_c0_count() + (mips_hpt_frequency/HZ));
215}