aboutsummaryrefslogtreecommitdiffstats
path: root/arch/v850
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/v850
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/v850')
-rw-r--r--arch/v850/Kconfig316
-rw-r--r--arch/v850/Kconfig.debug10
-rw-r--r--arch/v850/Makefile63
-rw-r--r--arch/v850/README32
-rw-r--r--arch/v850/kernel/Makefile40
-rw-r--r--arch/v850/kernel/anna-rom.ld16
-rw-r--r--arch/v850/kernel/anna.c208
-rw-r--r--arch/v850/kernel/anna.ld20
-rw-r--r--arch/v850/kernel/as85ep1-rom.ld21
-rw-r--r--arch/v850/kernel/as85ep1.c240
-rw-r--r--arch/v850/kernel/as85ep1.ld49
-rw-r--r--arch/v850/kernel/asm-consts.c61
-rw-r--r--arch/v850/kernel/bug.c142
-rw-r--r--arch/v850/kernel/entry.S1121
-rw-r--r--arch/v850/kernel/fpga85e2c.c171
-rw-r--r--arch/v850/kernel/fpga85e2c.ld62
-rw-r--r--arch/v850/kernel/gbus_int.c271
-rw-r--r--arch/v850/kernel/head.S128
-rw-r--r--arch/v850/kernel/highres_timer.c132
-rw-r--r--arch/v850/kernel/init_task.c49
-rw-r--r--arch/v850/kernel/intv.S87
-rw-r--r--arch/v850/kernel/irq.c744
-rw-r--r--arch/v850/kernel/ma.c70
-rw-r--r--arch/v850/kernel/mach.c17
-rw-r--r--arch/v850/kernel/mach.h56
-rw-r--r--arch/v850/kernel/me2.c74
-rw-r--r--arch/v850/kernel/memcons.c135
-rw-r--r--arch/v850/kernel/module.c237
-rw-r--r--arch/v850/kernel/process.c236
-rw-r--r--arch/v850/kernel/procfs.c67
-rw-r--r--arch/v850/kernel/ptrace.c282
-rw-r--r--arch/v850/kernel/rte_cb.c200
-rw-r--r--arch/v850/kernel/rte_cb_leds.c138
-rw-r--r--arch/v850/kernel/rte_cb_multi.c121
-rw-r--r--arch/v850/kernel/rte_ma1_cb-rom.ld14
-rw-r--r--arch/v850/kernel/rte_ma1_cb.c106
-rw-r--r--arch/v850/kernel/rte_ma1_cb.ld57
-rw-r--r--arch/v850/kernel/rte_mb_a_pci.c796
-rw-r--r--arch/v850/kernel/rte_me2_cb.c300
-rw-r--r--arch/v850/kernel/rte_me2_cb.ld30
-rw-r--r--arch/v850/kernel/rte_nb85e_cb-multi.ld57
-rw-r--r--arch/v850/kernel/rte_nb85e_cb.c82
-rw-r--r--arch/v850/kernel/rte_nb85e_cb.ld22
-rw-r--r--arch/v850/kernel/semaphore.c166
-rw-r--r--arch/v850/kernel/setup.c286
-rw-r--r--arch/v850/kernel/signal.c525
-rw-r--r--arch/v850/kernel/sim.c179
-rw-r--r--arch/v850/kernel/sim.ld13
-rw-r--r--arch/v850/kernel/sim85e2.c201
-rw-r--r--arch/v850/kernel/sim85e2.ld36
-rw-r--r--arch/v850/kernel/simcons.c166
-rw-r--r--arch/v850/kernel/syscalls.c197
-rw-r--r--arch/v850/kernel/teg.c63
-rw-r--r--arch/v850/kernel/time.c198
-rw-r--r--arch/v850/kernel/v850_ksyms.c78
-rw-r--r--arch/v850/kernel/v850e2_cache.c127
-rw-r--r--arch/v850/kernel/v850e_cache.c174
-rw-r--r--arch/v850/kernel/v850e_intc.c104
-rw-r--r--arch/v850/kernel/v850e_timer_d.c54
-rw-r--r--arch/v850/kernel/v850e_utils.c62
-rw-r--r--arch/v850/kernel/vmlinux.lds.S285
-rw-r--r--arch/v850/lib/Makefile6
-rw-r--r--arch/v850/lib/ashldi3.c62
-rw-r--r--arch/v850/lib/ashrdi3.c63
-rw-r--r--arch/v850/lib/checksum.c154
-rw-r--r--arch/v850/lib/lshrdi3.c62
-rw-r--r--arch/v850/lib/memcpy.c92
-rw-r--r--arch/v850/lib/memset.c68
-rw-r--r--arch/v850/lib/muldi3.c61
-rw-r--r--arch/v850/lib/negdi2.c25
70 files changed, 10587 insertions, 0 deletions
diff --git a/arch/v850/Kconfig b/arch/v850/Kconfig
new file mode 100644
index 000000000000..90cd4baa75ee
--- /dev/null
+++ b/arch/v850/Kconfig
@@ -0,0 +1,316 @@
1#############################################################################
2#
3# For a description of the syntax of this configuration file,
4# see Documentation/kbuild/kconfig-language.txt.
5#
6#############################################################################
7
8mainmenu "uClinux/v850 (w/o MMU) Kernel Configuration"
9
10config MMU
11 bool
12 default n
13config UID16
14 bool
15 default n
16config RWSEM_GENERIC_SPINLOCK
17 bool
18 default y
19config RWSEM_XCHGADD_ALGORITHM
20 bool
21 default n
22config GENERIC_CALIBRATE_DELAY
23 bool
24 default y
25
26# Turn off some random 386 crap that can affect device config
27config ISA
28 bool
29 default n
30config ISAPNP
31 bool
32 default n
33config EISA
34 bool
35 default n
36config MCA
37 bool
38 default n
39
40
41#############################################################################
42#### v850-specific config
43
44# Define the architecture
45config V850
46 bool
47 default y
48
49menu "Processor type and features"
50
51 choice
52 prompt "Platform"
53 default GDB
54 config V850E_SIM
55 bool "GDB"
56 config RTE_CB_MA1
57 bool "RTE-V850E/MA1-CB"
58 config RTE_CB_NB85E
59 bool "RTE-V850E/NB85E-CB"
60 config RTE_CB_ME2
61 bool "RTE-V850E/ME2-CB"
62 config V850E_AS85EP1
63 bool "AS85EP1"
64 config V850E2_SIM85E2C
65 bool "sim85e2c"
66 config V850E2_SIM85E2S
67 bool "sim85e2s"
68 config V850E2_FPGA85E2C
69 bool "NA85E2C-FPGA"
70 config V850E2_ANNA
71 bool "Anna"
72 endchoice
73
74 #### V850E processor-specific config
75
76 # All CPUs currently supported use the v850e architecture
77 config V850E
78 bool
79 default y
80
81 # The RTE-V850E/MA1-CB is the only type of V850E/MA1 platform we
82 # currently support
83 config V850E_MA1
84 bool
85 depends RTE_CB_MA1
86 default y
87 # Similarly for the RTE-V850E/NB85E-CB - V850E/TEG
88 config V850E_TEG
89 bool
90 depends RTE_CB_NB85E
91 default y
92 # ... and the RTE-V850E/ME2-CB - V850E/ME2
93 config V850E_ME2
94 bool
95 depends RTE_CB_ME2
96 default y
97
98
99 #### sim85e2-specific config
100
101 config V850E2_SIM85E2
102 bool
103 depends V850E2_SIM85E2C || V850E2_SIM85E2S
104 default y
105
106
107 #### V850E2 processor-specific config
108
109 # V850E2 processors
110 config V850E2
111 bool
112 depends V850E2_SIM85E2 || V850E2_FPGA85E2C || V850E2_ANNA
113 default y
114
115
116 #### RTE-CB platform-specific config
117
118 # Boards in the RTE-x-CB series
119 config RTE_CB
120 bool
121 depends RTE_CB_MA1 || RTE_CB_NB85E || RTE_CB_ME2
122 default y
123
124 config RTE_CB_MULTI
125 bool
126 # RTE_CB_NB85E can either have multi ROM support or not, but
127 # other platforms (currently only RTE_CB_MA1) require it.
128 prompt "Multi monitor ROM support" if RTE_CB_NB85E
129 depends RTE_CB_MA1 || RTE_CB_NB85E
130 default y
131
132 config RTE_CB_MULTI_DBTRAP
133 bool "Pass illegal insn trap / dbtrap to kernel"
134 depends RTE_CB_MULTI
135 default n
136
137 config RTE_CB_MA1_KSRAM
138 bool "Kernel in SRAM (limits size of kernel)"
139 depends RTE_CB_MA1 && RTE_CB_MULTI
140 default n
141
142 config RTE_MB_A_PCI
143 bool "Mother-A PCI support"
144 depends RTE_CB
145 default y
146
147 # The GBUS is used to talk to the RTE-MOTHER-A board
148 config RTE_GBUS_INT
149 bool
150 depends RTE_MB_A_PCI
151 default y
152
153 # The only PCI bus we support is on the RTE-MOTHER-A board
154 config PCI
155 bool
156 default RTE_MB_A_PCI
157
158 #### Some feature-specific configs
159
160 # Everything except for the GDB simulator uses the same interrupt controller
161 config V850E_INTC
162 bool
163 default !V850E_SIM
164
165 # Everything except for the various simulators uses the "Timer D" unit
166 config V850E_TIMER_D
167 bool
168 default !V850E_SIM && !V850E2_SIM85E2
169
170 # Cache control used on some v850e1 processors
171 config V850E_CACHE
172 bool
173 default V850E_TEG || V850E_ME2
174
175 # Cache control used on v850e2 processors; I think this should
176 # actually apply to more, but currently only the SIM85E2S uses it
177 config V850E2_CACHE
178 bool
179 default V850E2_SIM85E2S
180
181 config NO_CACHE
182 bool
183 default !V850E_CACHE && !V850E2_CACHE
184
185 #### Misc config
186
187 config ROM_KERNEL
188 bool "Kernel in ROM"
189 depends V850E2_ANNA || V850E_AS85EP1 || RTE_CB_ME2
190
191 # Some platforms pre-zero memory, in which case the kernel doesn't need to
192 config ZERO_BSS
193 bool
194 depends !V850E2_SIM85E2C
195 default y
196
197 # The crappy-ass zone allocator requires that the start of allocatable
198 # memory be aligned to the largest possible allocation.
199 config FORCE_MAX_ZONEORDER
200 int
201 default 8 if V850E2_SIM85E2C || V850E2_FPGA85E2C
202
203 config V850E_HIGHRES_TIMER
204 bool "High resolution timer support"
205 depends V850E_TIMER_D
206 config TIME_BOOTUP
207 bool "Time bootup"
208 depends V850E_HIGHRES_TIMER
209
210 config RESET_GUARD
211 bool "Reset Guard"
212
213 config LARGE_ALLOCS
214 bool "Allow allocating large blocks (> 1MB) of memory"
215 help
216 Allow the slab memory allocator to keep chains for very large
217 memory sizes - upto 32MB. You may need this if your system has
218 a lot of RAM, and you need to able to allocate very large
219 contiguous chunks. If unsure, say N.
220
221endmenu
222
223
224#############################################################################
225
226source init/Kconfig
227
228#############################################################################
229
230menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
231
232# config PCI
233# bool "PCI support"
234# help
235# Support for PCI bus.
236
237source "drivers/pci/Kconfig"
238
239source "drivers/pcmcia/Kconfig"
240
241source "drivers/pci/hotplug/Kconfig"
242
243endmenu
244
245menu "Executable file formats"
246
247source "fs/Kconfig.binfmt"
248
249endmenu
250
251#############################################################################
252
253source "drivers/base/Kconfig"
254
255source drivers/mtd/Kconfig
256
257source drivers/parport/Kconfig
258
259#source drivers/pnp/Kconfig
260
261source drivers/block/Kconfig
262
263#############################################################################
264
265menu "Disk device support"
266
267source "drivers/ide/Kconfig"
268
269source "drivers/scsi/Kconfig"
270
271endmenu
272
273#############################################################################
274
275
276source "drivers/md/Kconfig"
277
278source "drivers/message/fusion/Kconfig"
279
280source "drivers/ieee1394/Kconfig"
281
282source "drivers/message/i2o/Kconfig"
283
284source "net/Kconfig"
285
286source "drivers/isdn/Kconfig"
287
288#source "drivers/telephony/Kconfig"
289
290#
291# input before char - char/joystick depends on it. As does USB.
292#
293source "drivers/input/Kconfig"
294
295source "drivers/char/Kconfig"
296
297#source drivers/misc/Config.in
298source "drivers/media/Kconfig"
299
300source "fs/Kconfig"
301
302source "drivers/video/Kconfig"
303
304source "sound/Kconfig"
305
306source "drivers/usb/Kconfig"
307
308source "arch/v850/Kconfig.debug"
309
310source "security/Kconfig"
311
312source "crypto/Kconfig"
313
314source "lib/Kconfig"
315
316#############################################################################
diff --git a/arch/v850/Kconfig.debug b/arch/v850/Kconfig.debug
new file mode 100644
index 000000000000..4acfb9cca1ca
--- /dev/null
+++ b/arch/v850/Kconfig.debug
@@ -0,0 +1,10 @@
1menu "Kernel hacking"
2
3source "lib/Kconfig.debug"
4
5config NO_KERNEL_MSG
6 bool "Suppress Kernel BUG Messages"
7 help
8 Do not output any debug BUG messages within the kernel.
9
10endmenu
diff --git a/arch/v850/Makefile b/arch/v850/Makefile
new file mode 100644
index 000000000000..6edaed4a310e
--- /dev/null
+++ b/arch/v850/Makefile
@@ -0,0 +1,63 @@
1#
2# arch/v850/Makefile
3#
4# Copyright (C) 2001,02,03 NEC Corporation
5# Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
6#
7# This file is included by the global makefile so that you can add your own
8# architecture-specific flags and dependencies. Remember to do have actions
9# for "archclean" and "archdep" for cleaning up and making dependencies for
10# this architecture
11#
12# This file is subject to the terms and conditions of the GNU General Public
13# License. See the file "COPYING" in the main directory of this archive
14# for more details.
15#
16
17arch_dir = arch/v850
18
19CFLAGS += -mv850e
20# r16 is a fixed pointer to the current task
21CFLAGS += -ffixed-r16 -mno-prolog-function
22CFLAGS += -fno-builtin
23CFLAGS += -D__linux__ -DUTS_SYSNAME=\"uClinux\"
24
25# This prevents the linker from consolidating the .gnu.linkonce.this_module
26# section into .text (which the v850 default linker script for -r does for
27# some reason)
28LDFLAGS_MODULE += --unique=.gnu.linkonce.this_module
29
30OBJCOPY_FLAGS_BLOB := -I binary -O elf32-little -B v850e
31
32
33head-y := $(arch_dir)/kernel/head.o $(arch_dir)/kernel/init_task.o
34core-y += $(arch_dir)/kernel/
35libs-y += $(arch_dir)/lib/
36
37
38# Deal with the initial contents of the root device
39ifdef ROOT_FS_IMAGE
40core-y += root_fs_image.o
41
42# Because the kernel build-system erases all explicit .o build rules, we
43# have to use an intermediate target to fool it into building for us.
44# This results in it being built anew each time, but that's alright.
45root_fs_image.o: root_fs_image_force
46
47root_fs_image_force: $(ROOT_FS_IMAGE)
48 $(OBJCOPY) $(OBJCOPY_FLAGS_BLOB) --rename-section .data=.root,alloc,load,readonly,data,contents $< root_fs_image.o
49endif
50
51
52prepare: include/asm-$(ARCH)/asm-consts.h
53
54# Generate constants from C code for use by asm files
55arch/$(ARCH)/kernel/asm-consts.s: include/asm include/linux/version.h \
56 include/config/MARKER
57
58include/asm-$(ARCH)/asm-consts.h: arch/$(ARCH)/kernel/asm-consts.s
59 $(call filechk,gen-asm-offsets)
60
61CLEAN_FILES += include/asm-$(ARCH)/asm-consts.h \
62 arch/$(ARCH)/kernel/asm-consts.s \
63 root_fs_image.o
diff --git a/arch/v850/README b/arch/v850/README
new file mode 100644
index 000000000000..01b98e290d4a
--- /dev/null
+++ b/arch/v850/README
@@ -0,0 +1,32 @@
1This port to the NEC V850E processor supports the following platforms:
2
3 + The gdb v850e simulator (CONFIG_V850E_SIM).
4
5 + The Midas labs RTE-V850E/MA1-CB and RTE-V850E/NB85E-CB evaluation boards
6 (CONFIG_RTE_CB_MA1 and CONFIG_RTE_CB_NB85E). This support has only been
7 tested when running with the Multi-debugger monitor ROM (for the Green
8 Hills Multi debugger). The optional NEC Solution Gear RTE-MOTHER-A
9 motherboard is also supported, which allows PCI boards to be used
10 (CONFIG_RTE_MB_A_PCI).
11
12 + The Midas labs RTE-V850E/ME2-CB evaluation board (CONFIG_RTE_CB_ME2).
13 This has only been tested using a kernel downloaded via an ICE connection
14 using the Multi debugger. Support for the RTE-MOTHER-A is present, but
15 hasn't been tested (unlike the other Midas labs cpu boards, the
16 RTE-V850E/ME2-CB includes an ethernet adaptor).
17
18 + The NEC AS85EP1 V850E evaluation chip/board (CONFIG_V850E_AS85EP1).
19
20 + The NEC `Anna' (board/chip) implementation of the V850E2 processor
21 (CONFIG_V850E2_ANNA).
22
23 + The sim85e2c and sim85e2s simulators, which are verilog simulations of
24 the V850E2 NA85E2C/NA85E2S cpu cores (CONFIG_V850E2_SIM85E2C and
25 CONFIG_V850E2_SIM85E2S).
26
27 + A FPGA implementation of the V850E2 NA85E2C cpu core
28 (CONFIG_V850E2_FPGA85E2C).
29
30Porting to anything with a V850E/MA1 or MA2 processor should be simple.
31See the file <asm-v850/machdep.h> and the files it includes for an example of
32how to add platform/chip-specific support.
diff --git a/arch/v850/kernel/Makefile b/arch/v850/kernel/Makefile
new file mode 100644
index 000000000000..3930482bddc4
--- /dev/null
+++ b/arch/v850/kernel/Makefile
@@ -0,0 +1,40 @@
1#
2# arch/v850/kernel/Makefile
3#
4# Copyright (C) 2001,02,03 NEC Electronics Corporation
5# Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
6#
7# This file is subject to the terms and conditions of the GNU General Public
8# License. See the file "COPYING" in the main directory of this archive
9# for more details.
10#
11
12extra-y := head.o init_task.o vmlinux.lds
13
14obj-y += intv.o entry.o process.o syscalls.o time.o semaphore.o setup.o \
15 signal.o irq.o mach.o ptrace.o bug.o
16obj-$(CONFIG_MODULES) += module.o v850_ksyms.o
17# chip-specific code
18obj-$(CONFIG_V850E_MA1) += ma.o
19obj-$(CONFIG_V850E_ME2) += me2.o
20obj-$(CONFIG_V850E_TEG) += teg.o
21obj-$(CONFIG_V850E_AS85EP1) += as85ep1.o
22obj-$(CONFIG_V850E2_ANNA) += anna.o
23# platform-specific code
24obj-$(CONFIG_V850E_SIM) += sim.o simcons.o
25obj-$(CONFIG_V850E2_SIM85E2) += sim85e2.o memcons.o
26obj-$(CONFIG_V850E2_FPGA85E2C) += fpga85e2c.o memcons.o
27obj-$(CONFIG_RTE_CB) += rte_cb.o rte_cb_leds.o
28obj-$(CONFIG_RTE_CB_MA1) += rte_ma1_cb.o
29obj-$(CONFIG_RTE_CB_ME2) += rte_me2_cb.o
30obj-$(CONFIG_RTE_CB_NB85E) += rte_nb85e_cb.o
31obj-$(CONFIG_RTE_CB_MULTI) += rte_cb_multi.o
32obj-$(CONFIG_RTE_MB_A_PCI) += rte_mb_a_pci.o
33obj-$(CONFIG_RTE_GBUS_INT) += gbus_int.o
34# feature-specific code
35obj-$(CONFIG_V850E_INTC) += v850e_intc.o
36obj-$(CONFIG_V850E_TIMER_D) += v850e_timer_d.o v850e_utils.o
37obj-$(CONFIG_V850E_CACHE) += v850e_cache.o
38obj-$(CONFIG_V850E2_CACHE) += v850e2_cache.o
39obj-$(CONFIG_V850E_HIGHRES_TIMER) += highres_timer.o
40obj-$(CONFIG_PROC_FS) += procfs.o
diff --git a/arch/v850/kernel/anna-rom.ld b/arch/v850/kernel/anna-rom.ld
new file mode 100644
index 000000000000..7c54e7e3f1b1
--- /dev/null
+++ b/arch/v850/kernel/anna-rom.ld
@@ -0,0 +1,16 @@
1/* Linker script for the Midas labs Anna V850E2 evaluation board
2 (CONFIG_V850E2_ANNA), with kernel in ROM (CONFIG_ROM_KERNEL). */
3
4MEMORY {
5 /* 8MB of flash ROM. */
6 ROM : ORIGIN = 0, LENGTH = 0x00800000
7
8 /* 1MB of static RAM. This memory is mirrored 64 times. */
9 SRAM : ORIGIN = SRAM_ADDR, LENGTH = SRAM_SIZE
10 /* 64MB of DRAM. */
11 SDRAM : ORIGIN = SDRAM_ADDR, LENGTH = SDRAM_SIZE
12}
13
14SECTIONS {
15 ROMK_SECTIONS(ROM, SRAM)
16}
diff --git a/arch/v850/kernel/anna.c b/arch/v850/kernel/anna.c
new file mode 100644
index 000000000000..6aaeab5e8a40
--- /dev/null
+++ b/arch/v850/kernel/anna.c
@@ -0,0 +1,208 @@
1/*
2 * arch/v850/kernel/anna.c -- Anna V850E2 evaluation chip/board
3 *
4 * Copyright (C) 2002,03 NEC Electronics Corporation
5 * Copyright (C) 2002,03 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14#include <linux/config.h>
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/init.h>
18#include <linux/bootmem.h>
19#include <linux/major.h>
20#include <linux/irq.h>
21
22#include <asm/machdep.h>
23#include <asm/atomic.h>
24#include <asm/page.h>
25#include <asm/v850e_timer_d.h>
26#include <asm/v850e_uart.h>
27
28#include "mach.h"
29
30
31/* SRAM and SDRAM are vaguely contiguous (with a big hole in between; see
32 mach_reserve_bootmem for details); use both as one big area. */
33#define RAM_START SRAM_ADDR
34#define RAM_END (SDRAM_ADDR + SDRAM_SIZE)
35
36/* The bits of this port are connected to an 8-LED bar-graph. */
37#define LEDS_PORT 0
38
39
40static void anna_led_tick (void);
41
42
43void __init mach_early_init (void)
44{
45 ANNA_ILBEN = 0;
46
47 V850E2_CSC(0) = 0x402F;
48 V850E2_CSC(1) = 0x4000;
49 V850E2_BPC = 0;
50 V850E2_BSC = 0xAAAA;
51 V850E2_BEC = 0;
52
53#if 0
54 V850E2_BHC = 0xFFFF; /* icache all memory, dcache all */
55#else
56 V850E2_BHC = 0; /* cache no memory */
57#endif
58 V850E2_BCT(0) = 0xB088;
59 V850E2_BCT(1) = 0x0008;
60 V850E2_DWC(0) = 0x0027;
61 V850E2_DWC(1) = 0;
62 V850E2_BCC = 0x0006;
63 V850E2_ASC = 0;
64 V850E2_LBS = 0x0089;
65 V850E2_SCR(3) = 0x21A9;
66 V850E2_RFS(3) = 0x8121;
67
68 v850e_intc_disable_irqs ();
69}
70
71void __init mach_setup (char **cmdline)
72{
73 ANNA_PORT_PM (LEDS_PORT) = 0; /* Make all LED pins output pins. */
74 mach_tick = anna_led_tick;
75}
76
77void __init mach_get_physical_ram (unsigned long *ram_start,
78 unsigned long *ram_len)
79{
80 *ram_start = RAM_START;
81 *ram_len = RAM_END - RAM_START;
82}
83
84void __init mach_reserve_bootmem ()
85{
86 /* The space between SRAM and SDRAM is filled with duplicate
87 images of SRAM. Prevent the kernel from using them. */
88 reserve_bootmem (SRAM_ADDR + SRAM_SIZE,
89 SDRAM_ADDR - (SRAM_ADDR + SRAM_SIZE));
90}
91
92void mach_gettimeofday (struct timespec *tv)
93{
94 tv->tv_sec = 0;
95 tv->tv_nsec = 0;
96}
97
98void __init mach_sched_init (struct irqaction *timer_action)
99{
100 /* Start hardware timer. */
101 v850e_timer_d_configure (0, HZ);
102 /* Install timer interrupt handler. */
103 setup_irq (IRQ_INTCMD(0), timer_action);
104}
105
106static struct v850e_intc_irq_init irq_inits[] = {
107 { "IRQ", 0, NUM_MACH_IRQS, 1, 7 },
108 { "PIN", IRQ_INTP(0), IRQ_INTP_NUM, 1, 4 },
109 { "CCC", IRQ_INTCCC(0), IRQ_INTCCC_NUM, 1, 5 },
110 { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 5 },
111 { "DMA", IRQ_INTDMA(0), IRQ_INTDMA_NUM, 1, 2 },
112 { "DMXER", IRQ_INTDMXER,1, 1, 2 },
113 { "SRE", IRQ_INTSRE(0), IRQ_INTSRE_NUM, 3, 3 },
114 { "SR", IRQ_INTSR(0), IRQ_INTSR_NUM, 3, 4 },
115 { "ST", IRQ_INTST(0), IRQ_INTST_NUM, 3, 5 },
116 { 0 }
117};
118#define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1)
119
120static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
121
122void __init mach_init_irqs (void)
123{
124 v850e_intc_init_irq_types (irq_inits, hw_itypes);
125}
126
127void machine_restart (char *__unused)
128{
129#ifdef CONFIG_RESET_GUARD
130 disable_reset_guard ();
131#endif
132 asm ("jmp r0"); /* Jump to the reset vector. */
133}
134
135EXPORT_SYMBOL(machine_restart);
136
137void machine_halt (void)
138{
139#ifdef CONFIG_RESET_GUARD
140 disable_reset_guard ();
141#endif
142 local_irq_disable (); /* Ignore all interrupts. */
143 ANNA_PORT_IO(LEDS_PORT) = 0xAA; /* Note that we halted. */
144 for (;;)
145 asm ("halt; nop; nop; nop; nop; nop");
146}
147
148EXPORT_SYMBOL(machine_halt);
149
150void machine_power_off (void)
151{
152 machine_halt ();
153}
154
155EXPORT_SYMBOL(machine_power_off);
156
157/* Called before configuring an on-chip UART. */
158void anna_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud)
159{
160 /* The Anna connects some general-purpose I/O pins on the CPU to
161 the RTS/CTS lines of UART 1's serial connection. I/O pins P07
162 and P37 are RTS and CTS respectively. */
163 if (chan == 1) {
164 ANNA_PORT_PM(0) &= ~0x80; /* P07 in output mode */
165 ANNA_PORT_PM(3) |= 0x80; /* P37 in input mode */
166 }
167}
168
169/* Minimum and maximum bounds for the moving upper LED boundary in the
170 clock tick display. We can't use the last bit because it's used for
171 UART0's CTS output. */
172#define MIN_MAX_POS 0
173#define MAX_MAX_POS 6
174
175/* There are MAX_MAX_POS^2 - MIN_MAX_POS^2 cycles in the animation, so if
176 we pick 6 and 0 as above, we get 49 cycles, which is when divided into
177 the standard 100 value for HZ, gives us an almost 1s total time. */
178#define TICKS_PER_FRAME \
179 (HZ / (MAX_MAX_POS * MAX_MAX_POS - MIN_MAX_POS * MIN_MAX_POS))
180
181static void anna_led_tick ()
182{
183 static unsigned counter = 0;
184
185 if (++counter == TICKS_PER_FRAME) {
186 static int pos = 0, max_pos = MAX_MAX_POS, dir = 1;
187
188 if (dir > 0 && pos == max_pos) {
189 dir = -1;
190 if (max_pos == MIN_MAX_POS)
191 max_pos = MAX_MAX_POS;
192 else
193 max_pos--;
194 } else {
195 if (dir < 0 && pos == 0)
196 dir = 1;
197
198 if (pos + dir <= max_pos) {
199 /* Each bit of port 0 has a LED. */
200 clear_bit (pos, &ANNA_PORT_IO(LEDS_PORT));
201 pos += dir;
202 set_bit (pos, &ANNA_PORT_IO(LEDS_PORT));
203 }
204 }
205
206 counter = 0;
207 }
208}
diff --git a/arch/v850/kernel/anna.ld b/arch/v850/kernel/anna.ld
new file mode 100644
index 000000000000..df7f80f2833d
--- /dev/null
+++ b/arch/v850/kernel/anna.ld
@@ -0,0 +1,20 @@
1/* Linker script for the Midas labs Anna V850E2 evaluation board
2 (CONFIG_V850E2_ANNA). */
3
4MEMORY {
5 /* 256KB of internal memory (followed by one mirror). */
6 iMEM0 : ORIGIN = 0, LENGTH = 0x00040000
7 /* 256KB of internal memory (followed by one mirror). */
8 iMEM1 : ORIGIN = 0x00040000, LENGTH = 0x00040000
9
10 /* 1MB of static RAM. This memory is mirrored 64 times. */
11 SRAM : ORIGIN = SRAM_ADDR, LENGTH = SRAM_SIZE
12 /* 64MB of DRAM. */
13 SDRAM : ORIGIN = SDRAM_ADDR, LENGTH = SDRAM_SIZE
14}
15
16SECTIONS {
17 .intv : { INTV_CONTENTS } > iMEM0
18 .sram : { RAMK_KRAM_CONTENTS } > SRAM
19 .root : { ROOT_FS_CONTENTS } > SDRAM
20}
diff --git a/arch/v850/kernel/as85ep1-rom.ld b/arch/v850/kernel/as85ep1-rom.ld
new file mode 100644
index 000000000000..fe2a9a3ab525
--- /dev/null
+++ b/arch/v850/kernel/as85ep1-rom.ld
@@ -0,0 +1,21 @@
1/* Linker script for the NEC AS85EP1 V850E evaluation board
2 (CONFIG_V850E_AS85EP1), with kernel in ROM (CONFIG_ROM_KERNEL). */
3
4MEMORY {
5 /* 4MB of flash ROM. */
6 ROM : ORIGIN = 0, LENGTH = 0x00400000
7
8 /* 1MB of static RAM. */
9 SRAM : ORIGIN = SRAM_ADDR, LENGTH = SRAM_SIZE
10
11 /* About 58MB of DRAM. This can actually be at one of two
12 positions, determined by jumper JP3; we have to use the first
13 position because the second is partially out of processor
14 instruction addressing range (though in the second position
15 there's actually 64MB available). */
16 SDRAM : ORIGIN = SDRAM_ADDR, LENGTH = SDRAM_SIZE
17}
18
19SECTIONS {
20 ROMK_SECTIONS(ROM, SRAM)
21}
diff --git a/arch/v850/kernel/as85ep1.c b/arch/v850/kernel/as85ep1.c
new file mode 100644
index 000000000000..4059b1df11b5
--- /dev/null
+++ b/arch/v850/kernel/as85ep1.c
@@ -0,0 +1,240 @@
1/*
2 * arch/v850/kernel/as85ep1.c -- AS85EP1 V850E evaluation chip/board
3 *
4 * Copyright (C) 2002,03 NEC Electronics Corporation
5 * Copyright (C) 2002,03 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14#include <linux/config.h>
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/init.h>
18#include <linux/bootmem.h>
19#include <linux/major.h>
20#include <linux/irq.h>
21
22#include <asm/machdep.h>
23#include <asm/atomic.h>
24#include <asm/page.h>
25#include <asm/v850e_timer_d.h>
26#include <asm/v850e_uart.h>
27
28#include "mach.h"
29
30
31/* SRAM and SDRAM are vaguely contiguous (with a big hole in between; see
32 mach_reserve_bootmem for details); use both as one big area. */
33#define RAM_START SRAM_ADDR
34#define RAM_END (SDRAM_ADDR + SDRAM_SIZE)
35
36/* The bits of this port are connected to an 8-LED bar-graph. */
37#define LEDS_PORT 4
38
39
40static void as85ep1_led_tick (void);
41
42extern char _intv_copy_src_start, _intv_copy_src_end;
43extern char _intv_copy_dst_start;
44
45
46void __init mach_early_init (void)
47{
48#ifndef CONFIG_ROM_KERNEL
49 const u32 *src;
50 register u32 *dst asm ("ep");
51#endif
52
53 AS85EP1_CSC(0) = 0x0403;
54 AS85EP1_BCT(0) = 0xB8B8;
55 AS85EP1_DWC(0) = 0x0104;
56 AS85EP1_BCC = 0x0012;
57 AS85EP1_ASC = 0;
58 AS85EP1_LBS = 0x00A9;
59
60 AS85EP1_PORT_PMC(6) = 0xFF; /* valid A0,A1,A20-A25 */
61 AS85EP1_PORT_PMC(7) = 0x0E; /* valid CS1-CS3 */
62 AS85EP1_PORT_PMC(9) = 0xFF; /* valid D16-D23 */
63 AS85EP1_PORT_PMC(10) = 0xFF; /* valid D24-D31 */
64
65 AS85EP1_RFS(1) = 0x800c;
66 AS85EP1_RFS(3) = 0x800c;
67 AS85EP1_SCR(1) = 0x20A9;
68 AS85EP1_SCR(3) = 0x20A9;
69
70#ifndef CONFIG_ROM_KERNEL
71 /* The early chip we have is buggy, and writing the interrupt
72 vectors into low RAM may screw up, so for non-ROM kernels, we
73 only rely on the reset vector being downloaded, and copy the
74 rest of the interrupt vectors into place here. The specific bug
75 is that writing address N, where (N & 0x10) == 0x10, will _also_
76 write to address (N - 0x10). We avoid this (effectively) by
77 writing in 16-byte chunks backwards from the end. */
78
79 AS85EP1_IRAMM = 0x3; /* "write-mode" for the internal instruction memory */
80
81 src = (u32 *)(((u32)&_intv_copy_src_end - 1) & ~0xF);
82 dst = (u32 *)&_intv_copy_dst_start
83 + (src - (u32 *)&_intv_copy_src_start);
84 do {
85 u32 t0 = src[0], t1 = src[1], t2 = src[2], t3 = src[3];
86 dst[0] = t0; dst[1] = t1; dst[2] = t2; dst[3] = t3;
87 dst -= 4;
88 src -= 4;
89 } while (src > (u32 *)&_intv_copy_src_start);
90
91 AS85EP1_IRAMM = 0x0; /* "read-mode" for the internal instruction memory */
92#endif /* !CONFIG_ROM_KERNEL */
93
94 v850e_intc_disable_irqs ();
95}
96
97void __init mach_setup (char **cmdline)
98{
99 AS85EP1_PORT_PMC (LEDS_PORT) = 0; /* Make the LEDs port an I/O port. */
100 AS85EP1_PORT_PM (LEDS_PORT) = 0; /* Make all the bits output pins. */
101 mach_tick = as85ep1_led_tick;
102}
103
104void __init mach_get_physical_ram (unsigned long *ram_start,
105 unsigned long *ram_len)
106{
107 *ram_start = RAM_START;
108 *ram_len = RAM_END - RAM_START;
109}
110
111/* Convenience macros. */
112#define SRAM_END (SRAM_ADDR + SRAM_SIZE)
113#define SDRAM_END (SDRAM_ADDR + SDRAM_SIZE)
114
115void __init mach_reserve_bootmem ()
116{
117 if (SDRAM_ADDR < RAM_END && SDRAM_ADDR > RAM_START)
118 /* We can't use the space between SRAM and SDRAM, so
119 prevent the kernel from trying. */
120 reserve_bootmem (SRAM_END, SDRAM_ADDR - SRAM_END);
121}
122
123void mach_gettimeofday (struct timespec *tv)
124{
125 tv->tv_sec = 0;
126 tv->tv_nsec = 0;
127}
128
129void __init mach_sched_init (struct irqaction *timer_action)
130{
131 /* Start hardware timer. */
132 v850e_timer_d_configure (0, HZ);
133 /* Install timer interrupt handler. */
134 setup_irq (IRQ_INTCMD(0), timer_action);
135}
136
137static struct v850e_intc_irq_init irq_inits[] = {
138 { "IRQ", 0, NUM_MACH_IRQS, 1, 7 },
139 { "CCC", IRQ_INTCCC(0), IRQ_INTCCC_NUM, 1, 5 },
140 { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 5 },
141 { "SRE", IRQ_INTSRE(0), IRQ_INTSRE_NUM, 3, 3 },
142 { "SR", IRQ_INTSR(0), IRQ_INTSR_NUM, 3, 4 },
143 { "ST", IRQ_INTST(0), IRQ_INTST_NUM, 3, 5 },
144 { 0 }
145};
146#define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1)
147
148static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
149
150void __init mach_init_irqs (void)
151{
152 v850e_intc_init_irq_types (irq_inits, hw_itypes);
153}
154
155void machine_restart (char *__unused)
156{
157#ifdef CONFIG_RESET_GUARD
158 disable_reset_guard ();
159#endif
160 asm ("jmp r0"); /* Jump to the reset vector. */
161}
162
163EXPORT_SYMBOL(machine_restart);
164
165void machine_halt (void)
166{
167#ifdef CONFIG_RESET_GUARD
168 disable_reset_guard ();
169#endif
170 local_irq_disable (); /* Ignore all interrupts. */
171 AS85EP1_PORT_IO (LEDS_PORT) = 0xAA; /* Note that we halted. */
172 for (;;)
173 asm ("halt; nop; nop; nop; nop; nop");
174}
175
176EXPORT_SYMBOL(machine_halt);
177
178void machine_power_off (void)
179{
180 machine_halt ();
181}
182
183EXPORT_SYMBOL(machine_power_off);
184
185/* Called before configuring an on-chip UART. */
186void as85ep1_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud)
187{
188 /* Make the shared uart/port pins be uart pins. */
189 AS85EP1_PORT_PMC(3) |= (0x5 << chan);
190
191 /* The AS85EP1 connects some general-purpose I/O pins on the CPU to
192 the RTS/CTS lines of UART 1's serial connection. I/O pins P53
193 and P54 are RTS and CTS respectively. */
194 if (chan == 1) {
195 /* Put P53 & P54 in I/O port mode. */
196 AS85EP1_PORT_PMC(5) &= ~0x18;
197 /* Make P53 an output, and P54 an input. */
198 AS85EP1_PORT_PM(5) |= 0x10;
199 }
200}
201
202/* Minimum and maximum bounds for the moving upper LED boundary in the
203 clock tick display. */
204#define MIN_MAX_POS 0
205#define MAX_MAX_POS 7
206
207/* There are MAX_MAX_POS^2 - MIN_MAX_POS^2 cycles in the animation, so if
208 we pick 6 and 0 as above, we get 49 cycles, which is when divided into
209 the standard 100 value for HZ, gives us an almost 1s total time. */
210#define TICKS_PER_FRAME \
211 (HZ / (MAX_MAX_POS * MAX_MAX_POS - MIN_MAX_POS * MIN_MAX_POS))
212
213static void as85ep1_led_tick ()
214{
215 static unsigned counter = 0;
216
217 if (++counter == TICKS_PER_FRAME) {
218 static int pos = 0, max_pos = MAX_MAX_POS, dir = 1;
219
220 if (dir > 0 && pos == max_pos) {
221 dir = -1;
222 if (max_pos == MIN_MAX_POS)
223 max_pos = MAX_MAX_POS;
224 else
225 max_pos--;
226 } else {
227 if (dir < 0 && pos == 0)
228 dir = 1;
229
230 if (pos + dir <= max_pos) {
231 /* Each bit of port 0 has a LED. */
232 set_bit (pos, &AS85EP1_PORT_IO(LEDS_PORT));
233 pos += dir;
234 clear_bit (pos, &AS85EP1_PORT_IO(LEDS_PORT));
235 }
236 }
237
238 counter = 0;
239 }
240}
diff --git a/arch/v850/kernel/as85ep1.ld b/arch/v850/kernel/as85ep1.ld
new file mode 100644
index 000000000000..ef2c4399063e
--- /dev/null
+++ b/arch/v850/kernel/as85ep1.ld
@@ -0,0 +1,49 @@
1/* Linker script for the NEC AS85EP1 V850E evaluation board
2 (CONFIG_V850E_AS85EP1). */
3
4MEMORY {
5 /* 1MB of internal instruction memory. */
6 iMEM0 : ORIGIN = 0, LENGTH = 0x00100000
7
8 /* 1MB of static RAM. */
9 SRAM : ORIGIN = SRAM_ADDR, LENGTH = SRAM_SIZE
10
11 /* About 58MB of DRAM. This can actually be at one of two
12 positions, determined by jump JP3; we have to use the first
13 position because the second is partially out of processor
14 instruction addressing range (though in the second position
15 there's actually 64MB available). */
16 SDRAM : ORIGIN = SDRAM_ADDR, LENGTH = SDRAM_SIZE
17}
18
19SECTIONS {
20 .resetv : {
21 __intv_start = . ;
22 *(.intv.reset) /* Reset vector */
23 } > iMEM0
24
25 .sram : {
26 RAMK_KRAM_CONTENTS
27
28 /* We stick most of the interrupt vectors here; they'll be
29 copied into the proper location by the early init code (we
30 can't put them directly in the right place because of
31 hardware bugs). The vectors shouldn't need to be
32 relocated, so we don't have to use `> ... AT> ...' to
33 split the load/vm addresses (and we can't because of
34 problems with the loader). */
35 . = ALIGN (0x10) ;
36 __intv_copy_src_start = . ;
37 *(.intv.common) /* Vectors common to all v850e proc. */
38 *(.intv.mach) /* Machine-specific int. vectors. */
39 . = ALIGN (0x10) ;
40 __intv_copy_src_end = . ;
41 } > SRAM
42
43 /* Where we end up putting the vectors. */
44 __intv_copy_dst_start = 0x10 ;
45 __intv_copy_dst_end = __intv_copy_dst_start + (__intv_copy_src_end - __intv_copy_src_start) ;
46 __intv_end = __intv_copy_dst_end ;
47
48 .root : { ROOT_FS_CONTENTS } > SDRAM
49}
diff --git a/arch/v850/kernel/asm-consts.c b/arch/v850/kernel/asm-consts.c
new file mode 100644
index 000000000000..24f291369070
--- /dev/null
+++ b/arch/v850/kernel/asm-consts.c
@@ -0,0 +1,61 @@
1/*
2 * This program is used to generate definitions needed by
3 * assembly language modules.
4 *
5 * We use the technique used in the OSF Mach kernel code:
6 * generate asm statements containing #defines,
7 * compile this file to assembler, and then extract the
8 * #defines from the assembly-language output.
9 */
10
11#include <linux/stddef.h>
12#include <linux/sched.h>
13#include <linux/kernel_stat.h>
14#include <linux/ptrace.h>
15#include <linux/hardirq.h>
16#include <asm/irq.h>
17#include <asm/errno.h>
18
19#define DEFINE(sym, val) \
20 asm volatile("\n->" #sym " %0 " #val : : "i" (val))
21
22#define BLANK() asm volatile("\n->" : : )
23
24int main (void)
25{
26 /* offsets into the task struct */
27 DEFINE (TASK_STATE, offsetof (struct task_struct, state));
28 DEFINE (TASK_FLAGS, offsetof (struct task_struct, flags));
29 DEFINE (TASK_PTRACE, offsetof (struct task_struct, ptrace));
30 DEFINE (TASK_BLOCKED, offsetof (struct task_struct, blocked));
31 DEFINE (TASK_THREAD, offsetof (struct task_struct, thread));
32 DEFINE (TASK_THREAD_INFO, offsetof (struct task_struct, thread_info));
33 DEFINE (TASK_MM, offsetof (struct task_struct, mm));
34 DEFINE (TASK_ACTIVE_MM, offsetof (struct task_struct, active_mm));
35 DEFINE (TASK_PID, offsetof (struct task_struct, pid));
36
37 /* offsets into the kernel_stat struct */
38 DEFINE (STAT_IRQ, offsetof (struct kernel_stat, irqs));
39
40
41 /* signal defines */
42 DEFINE (SIGSEGV, SIGSEGV);
43 DEFINE (SEGV_MAPERR, SEGV_MAPERR);
44 DEFINE (SIGTRAP, SIGTRAP);
45 DEFINE (SIGCHLD, SIGCHLD);
46 DEFINE (SIGILL, SIGILL);
47 DEFINE (TRAP_TRACE, TRAP_TRACE);
48
49 /* ptrace flag bits */
50 DEFINE (PT_PTRACED, PT_PTRACED);
51 DEFINE (PT_DTRACE, PT_DTRACE);
52
53 /* error values */
54 DEFINE (ENOSYS, ENOSYS);
55
56 /* clone flag bits */
57 DEFINE (CLONE_VFORK, CLONE_VFORK);
58 DEFINE (CLONE_VM, CLONE_VM);
59
60 return 0;
61}
diff --git a/arch/v850/kernel/bug.c b/arch/v850/kernel/bug.c
new file mode 100644
index 000000000000..c78cf750915a
--- /dev/null
+++ b/arch/v850/kernel/bug.c
@@ -0,0 +1,142 @@
1/*
2 * arch/v850/kernel/bug.c -- Bug reporting functions
3 *
4 * Copyright (C) 2001,02,03 NEC Electronics Corporation
5 * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14#include <linux/kernel.h>
15#include <linux/reboot.h>
16#include <linux/sched.h>
17#include <linux/module.h>
18
19#include <asm/errno.h>
20#include <asm/ptrace.h>
21#include <asm/processor.h>
22#include <asm/current.h>
23
24/* We should use __builtin_return_address, but it doesn't work in gcc-2.90
25 (which is currently our standard compiler on the v850). */
26#define ret_addr() ({ register u32 lp asm ("lp"); lp; })
27#define stack_addr() ({ register u32 sp asm ("sp"); sp; })
28
29void __bug ()
30{
31 printk (KERN_CRIT "kernel BUG at PC 0x%x (SP ~0x%x)!\n",
32 ret_addr() - 4, /* - 4 for `jarl' */
33 stack_addr());
34 machine_halt ();
35}
36
37int bad_trap (int trap_num, struct pt_regs *regs)
38{
39 printk (KERN_CRIT
40 "unimplemented trap %d called at 0x%08lx, pid %d!\n",
41 trap_num, regs->pc, current->pid);
42 return -ENOSYS;
43}
44
45#ifdef CONFIG_RESET_GUARD
46void unexpected_reset (unsigned long ret_addr, unsigned long kmode,
47 struct task_struct *task, unsigned long sp)
48{
49 printk (KERN_CRIT
50 "unexpected reset in %s mode, pid %d"
51 " (ret_addr = 0x%lx, sp = 0x%lx)\n",
52 kmode ? "kernel" : "user",
53 task ? task->pid : -1,
54 ret_addr, sp);
55
56 machine_halt ();
57}
58#endif /* CONFIG_RESET_GUARD */
59
60
61
62struct spec_reg_name {
63 const char *name;
64 int gpr;
65};
66
67struct spec_reg_name spec_reg_names[] = {
68 { "sp", GPR_SP },
69 { "gp", GPR_GP },
70 { "tp", GPR_TP },
71 { "ep", GPR_EP },
72 { "lp", GPR_LP },
73 { 0, 0 }
74};
75
76void show_regs (struct pt_regs *regs)
77{
78 int gpr_base, gpr_offs;
79
80 printk (" pc 0x%08lx psw 0x%08lx kernel_mode %d\n",
81 regs->pc, regs->psw, regs->kernel_mode);
82 printk (" ctpc 0x%08lx ctpsw 0x%08lx ctbp 0x%08lx\n",
83 regs->ctpc, regs->ctpsw, regs->ctbp);
84
85 for (gpr_base = 0; gpr_base < NUM_GPRS; gpr_base += 4) {
86 for (gpr_offs = 0; gpr_offs < 4; gpr_offs++) {
87 int gpr = gpr_base + gpr_offs;
88 long val = regs->gpr[gpr];
89 struct spec_reg_name *srn;
90
91 for (srn = spec_reg_names; srn->name; srn++)
92 if (srn->gpr == gpr)
93 break;
94
95 if (srn->name)
96 printk ("%7s 0x%08lx", srn->name, val);
97 else
98 printk (" r%02d 0x%08lx", gpr, val);
99 }
100
101 printk ("\n");
102 }
103}
104
105/*
106 * TASK is a pointer to the task whose backtrace we want to see (or NULL
107 * for current task), SP is the stack pointer of the first frame that
108 * should be shown in the back trace (or NULL if the entire call-chain of
109 * the task should be shown).
110 */
111void show_stack (struct task_struct *task, unsigned long *sp)
112{
113 unsigned long addr, end;
114
115 if (sp)
116 addr = (unsigned long)sp;
117 else if (task)
118 addr = task_sp (task);
119 else
120 addr = stack_addr ();
121
122 addr = addr & ~3;
123 end = (addr + THREAD_SIZE - 1) & THREAD_MASK;
124
125 while (addr < end) {
126 printk ("%8lX: ", addr);
127 while (addr < end) {
128 printk (" %8lX", *(unsigned long *)addr);
129 addr += sizeof (unsigned long);
130 if (! (addr & 0xF))
131 break;
132 }
133 printk ("\n");
134 }
135}
136
137void dump_stack ()
138{
139 show_stack (0, 0);
140}
141
142EXPORT_SYMBOL(dump_stack);
diff --git a/arch/v850/kernel/entry.S b/arch/v850/kernel/entry.S
new file mode 100644
index 000000000000..895e27b1d839
--- /dev/null
+++ b/arch/v850/kernel/entry.S
@@ -0,0 +1,1121 @@
1/*
2 * arch/v850/kernel/entry.S -- Low-level system-call handling, trap handlers,
3 * and context-switching
4 *
5 * Copyright (C) 2001,02,03 NEC Electronics Corporation
6 * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
7 *
8 * This file is subject to the terms and conditions of the GNU General
9 * Public License. See the file COPYING in the main directory of this
10 * archive for more details.
11 *
12 * Written by Miles Bader <miles@gnu.org>
13 */
14
15#include <linux/sys.h>
16
17#include <asm/entry.h>
18#include <asm/current.h>
19#include <asm/thread_info.h>
20#include <asm/clinkage.h>
21#include <asm/processor.h>
22#include <asm/irq.h>
23#include <asm/errno.h>
24
25#include <asm/asm-consts.h>
26
27
28/* Make a slightly more convenient alias for C_SYMBOL_NAME. */
29#define CSYM C_SYMBOL_NAME
30
31
32/* The offset of the struct pt_regs in a state-save-frame on the stack. */
33#define PTO STATE_SAVE_PT_OFFSET
34
35
36/* Save argument registers to the state-save-frame pointed to by EP. */
37#define SAVE_ARG_REGS \
38 sst.w r6, PTO+PT_GPR(6)[ep]; \
39 sst.w r7, PTO+PT_GPR(7)[ep]; \
40 sst.w r8, PTO+PT_GPR(8)[ep]; \
41 sst.w r9, PTO+PT_GPR(9)[ep]
42/* Restore argument registers from the state-save-frame pointed to by EP. */
43#define RESTORE_ARG_REGS \
44 sld.w PTO+PT_GPR(6)[ep], r6; \
45 sld.w PTO+PT_GPR(7)[ep], r7; \
46 sld.w PTO+PT_GPR(8)[ep], r8; \
47 sld.w PTO+PT_GPR(9)[ep], r9
48
49/* Save value return registers to the state-save-frame pointed to by EP. */
50#define SAVE_RVAL_REGS \
51 sst.w r10, PTO+PT_GPR(10)[ep]; \
52 sst.w r11, PTO+PT_GPR(11)[ep]
53/* Restore value return registers from the state-save-frame pointed to by EP. */
54#define RESTORE_RVAL_REGS \
55 sld.w PTO+PT_GPR(10)[ep], r10; \
56 sld.w PTO+PT_GPR(11)[ep], r11
57
58
59#define SAVE_CALL_CLOBBERED_REGS_BEFORE_ARGS \
60 sst.w r1, PTO+PT_GPR(1)[ep]; \
61 sst.w r5, PTO+PT_GPR(5)[ep]
62#define SAVE_CALL_CLOBBERED_REGS_AFTER_RVAL \
63 sst.w r12, PTO+PT_GPR(12)[ep]; \
64 sst.w r13, PTO+PT_GPR(13)[ep]; \
65 sst.w r14, PTO+PT_GPR(14)[ep]; \
66 sst.w r15, PTO+PT_GPR(15)[ep]; \
67 sst.w r16, PTO+PT_GPR(16)[ep]; \
68 sst.w r17, PTO+PT_GPR(17)[ep]; \
69 sst.w r18, PTO+PT_GPR(18)[ep]; \
70 sst.w r19, PTO+PT_GPR(19)[ep]
71#define RESTORE_CALL_CLOBBERED_REGS_BEFORE_ARGS \
72 sld.w PTO+PT_GPR(1)[ep], r1; \
73 sld.w PTO+PT_GPR(5)[ep], r5
74#define RESTORE_CALL_CLOBBERED_REGS_AFTER_RVAL \
75 sld.w PTO+PT_GPR(12)[ep], r12; \
76 sld.w PTO+PT_GPR(13)[ep], r13; \
77 sld.w PTO+PT_GPR(14)[ep], r14; \
78 sld.w PTO+PT_GPR(15)[ep], r15; \
79 sld.w PTO+PT_GPR(16)[ep], r16; \
80 sld.w PTO+PT_GPR(17)[ep], r17; \
81 sld.w PTO+PT_GPR(18)[ep], r18; \
82 sld.w PTO+PT_GPR(19)[ep], r19
83
84/* Save `call clobbered' registers to the state-save-frame pointed to by EP. */
85#define SAVE_CALL_CLOBBERED_REGS \
86 SAVE_CALL_CLOBBERED_REGS_BEFORE_ARGS; \
87 SAVE_ARG_REGS; \
88 SAVE_RVAL_REGS; \
89 SAVE_CALL_CLOBBERED_REGS_AFTER_RVAL
90/* Restore `call clobbered' registers from the state-save-frame pointed to
91 by EP. */
92#define RESTORE_CALL_CLOBBERED_REGS \
93 RESTORE_CALL_CLOBBERED_REGS_BEFORE_ARGS; \
94 RESTORE_ARG_REGS; \
95 RESTORE_RVAL_REGS; \
96 RESTORE_CALL_CLOBBERED_REGS_AFTER_RVAL
97
98/* Save `call clobbered' registers except for the return-value registers
99 to the state-save-frame pointed to by EP. */
100#define SAVE_CALL_CLOBBERED_REGS_NO_RVAL \
101 SAVE_CALL_CLOBBERED_REGS_BEFORE_ARGS; \
102 SAVE_ARG_REGS; \
103 SAVE_CALL_CLOBBERED_REGS_AFTER_RVAL
104/* Restore `call clobbered' registers except for the return-value registers
105 from the state-save-frame pointed to by EP. */
106#define RESTORE_CALL_CLOBBERED_REGS_NO_RVAL \
107 RESTORE_CALL_CLOBBERED_REGS_BEFORE_ARGS; \
108 RESTORE_ARG_REGS; \
109 RESTORE_CALL_CLOBBERED_REGS_AFTER_RVAL
110
111/* Save `call saved' registers to the state-save-frame pointed to by EP. */
112#define SAVE_CALL_SAVED_REGS \
113 sst.w r2, PTO+PT_GPR(2)[ep]; \
114 sst.w r20, PTO+PT_GPR(20)[ep]; \
115 sst.w r21, PTO+PT_GPR(21)[ep]; \
116 sst.w r22, PTO+PT_GPR(22)[ep]; \
117 sst.w r23, PTO+PT_GPR(23)[ep]; \
118 sst.w r24, PTO+PT_GPR(24)[ep]; \
119 sst.w r25, PTO+PT_GPR(25)[ep]; \
120 sst.w r26, PTO+PT_GPR(26)[ep]; \
121 sst.w r27, PTO+PT_GPR(27)[ep]; \
122 sst.w r28, PTO+PT_GPR(28)[ep]; \
123 sst.w r29, PTO+PT_GPR(29)[ep]
124/* Restore `call saved' registers from the state-save-frame pointed to by EP. */
125#define RESTORE_CALL_SAVED_REGS \
126 sld.w PTO+PT_GPR(2)[ep], r2; \
127 sld.w PTO+PT_GPR(20)[ep], r20; \
128 sld.w PTO+PT_GPR(21)[ep], r21; \
129 sld.w PTO+PT_GPR(22)[ep], r22; \
130 sld.w PTO+PT_GPR(23)[ep], r23; \
131 sld.w PTO+PT_GPR(24)[ep], r24; \
132 sld.w PTO+PT_GPR(25)[ep], r25; \
133 sld.w PTO+PT_GPR(26)[ep], r26; \
134 sld.w PTO+PT_GPR(27)[ep], r27; \
135 sld.w PTO+PT_GPR(28)[ep], r28; \
136 sld.w PTO+PT_GPR(29)[ep], r29
137
138
139/* Save the PC stored in the special register SAVEREG to the state-save-frame
140 pointed to by EP. r19 is clobbered. */
141#define SAVE_PC(savereg) \
142 stsr SR_ ## savereg, r19; \
143 sst.w r19, PTO+PT_PC[ep]
144/* Restore the PC from the state-save-frame pointed to by EP, to the special
145 register SAVEREG. LP is clobbered (it is used as a scratch register
146 because the POP_STATE macro restores it, and this macro is usually used
147 inside POP_STATE). */
148#define RESTORE_PC(savereg) \
149 sld.w PTO+PT_PC[ep], lp; \
150 ldsr lp, SR_ ## savereg
151/* Save the PSW register stored in the special register SAVREG to the
152 state-save-frame pointed to by EP. r19 is clobbered. */
153#define SAVE_PSW(savereg) \
154 stsr SR_ ## savereg, r19; \
155 sst.w r19, PTO+PT_PSW[ep]
156/* Restore the PSW register from the state-save-frame pointed to by EP, to
157 the special register SAVEREG. LP is clobbered (it is used as a scratch
158 register because the POP_STATE macro restores it, and this macro is
159 usually used inside POP_STATE). */
160#define RESTORE_PSW(savereg) \
161 sld.w PTO+PT_PSW[ep], lp; \
162 ldsr lp, SR_ ## savereg
163
164/* Save CTPC/CTPSW/CTBP registers to the state-save-frame pointed to by REG.
165 r19 is clobbered. */
166#define SAVE_CT_REGS \
167 stsr SR_CTPC, r19; \
168 sst.w r19, PTO+PT_CTPC[ep]; \
169 stsr SR_CTPSW, r19; \
170 sst.w r19, PTO+PT_CTPSW[ep]; \
171 stsr SR_CTBP, r19; \
172 sst.w r19, PTO+PT_CTBP[ep]
173/* Restore CTPC/CTPSW/CTBP registers from the state-save-frame pointed to by EP.
174 LP is clobbered (it is used as a scratch register because the POP_STATE
175 macro restores it, and this macro is usually used inside POP_STATE). */
176#define RESTORE_CT_REGS \
177 sld.w PTO+PT_CTPC[ep], lp; \
178 ldsr lp, SR_CTPC; \
179 sld.w PTO+PT_CTPSW[ep], lp; \
180 ldsr lp, SR_CTPSW; \
181 sld.w PTO+PT_CTBP[ep], lp; \
182 ldsr lp, SR_CTBP
183
184
185/* Push register state, except for the stack pointer, on the stack in the
186 form of a state-save-frame (plus some extra padding), in preparation for
187 a system call. This macro makes sure that the EP, GP, and LP
188 registers are saved, and TYPE identifies the set of extra registers to
189 be saved as well. Also copies (the new value of) SP to EP. */
190#define PUSH_STATE(type) \
191 addi -STATE_SAVE_SIZE, sp, sp; /* Make room on the stack. */ \
192 st.w ep, PTO+PT_GPR(GPR_EP)[sp]; \
193 mov sp, ep; \
194 sst.w gp, PTO+PT_GPR(GPR_GP)[ep]; \
195 sst.w lp, PTO+PT_GPR(GPR_LP)[ep]; \
196 type ## _STATE_SAVER
197/* Pop a register state pushed by PUSH_STATE, except for the stack pointer,
198 from the the stack. */
199#define POP_STATE(type) \
200 mov sp, ep; \
201 type ## _STATE_RESTORER; \
202 sld.w PTO+PT_GPR(GPR_GP)[ep], gp; \
203 sld.w PTO+PT_GPR(GPR_LP)[ep], lp; \
204 sld.w PTO+PT_GPR(GPR_EP)[ep], ep; \
205 addi STATE_SAVE_SIZE, sp, sp /* Clean up our stack space. */
206
207
208/* Switch to the kernel stack if necessary, and push register state on the
209 stack in the form of a state-save-frame. Also load the current task
210 pointer if switching from user mode. The stack-pointer (r3) should have
211 already been saved to the memory location SP_SAVE_LOC (the reason for
212 this is that the interrupt vectors may be beyond a 22-bit signed offset
213 jump from the actual interrupt handler, and this allows them to save the
214 stack-pointer and use that register to do an indirect jump). This macro
215 makes sure that `special' registers, system registers, and the stack
216 pointer are saved; TYPE identifies the set of extra registers to be
217 saved as well. SYSCALL_NUM is the register in which the system-call
218 number this state is for is stored (r0 if this isn't a system call).
219 Interrupts should already be disabled when calling this. */
220#define SAVE_STATE(type, syscall_num, sp_save_loc) \
221 tst1 0, KM; /* See if already in kernel mode. */ \
222 bz 1f; \
223 ld.w sp_save_loc, sp; /* ... yes, use saved SP. */ \
224 br 2f; \
2251: ld.w KSP, sp; /* ... no, switch to kernel stack. */ \
2262: PUSH_STATE(type); \
227 ld.b KM, r19; /* Remember old kernel-mode. */ \
228 sst.w r19, PTO+PT_KERNEL_MODE[ep]; \
229 ld.w sp_save_loc, r19; /* Remember old SP. */ \
230 sst.w r19, PTO+PT_GPR(GPR_SP)[ep]; \
231 mov 1, r19; /* Now definitely in kernel-mode. */ \
232 st.b r19, KM; \
233 GET_CURRENT_TASK(CURRENT_TASK); /* Fetch the current task pointer. */ \
234 /* Save away the syscall number. */ \
235 sst.w syscall_num, PTO+PT_CUR_SYSCALL[ep]
236
237
238/* Save register state not normally saved by PUSH_STATE for TYPE, to the
239 state-save-frame on the stack; also copies SP to EP. r19 may be trashed. */
240#define SAVE_EXTRA_STATE(type) \
241 mov sp, ep; \
242 type ## _EXTRA_STATE_SAVER
243/* Restore register state not normally restored by POP_STATE for TYPE,
244 from the state-save-frame on the stack; also copies SP to EP.
245 r19 may be trashed. */
246#define RESTORE_EXTRA_STATE(type) \
247 mov sp, ep; \
248 type ## _EXTRA_STATE_RESTORER
249
250/* Save any call-clobbered registers not normally saved by PUSH_STATE for
251 TYPE, to the state-save-frame on the stack.
252 EP may be trashed, but is not guaranteed to contain a copy of SP
253 (unlike after most SAVE_... macros). r19 may be trashed. */
254#define SAVE_EXTRA_STATE_FOR_SCHEDULE(type) \
255 type ## _SCHEDULE_EXTRA_STATE_SAVER
256/* Restore any call-clobbered registers not normally restored by
257 POP_STATE for TYPE, to the state-save-frame on the stack.
258 EP may be trashed, but is not guaranteed to contain a copy of SP
259 (unlike after most RESTORE_... macros). r19 may be trashed. */
260#define RESTORE_EXTRA_STATE_FOR_SCHEDULE(type) \
261 type ## _SCHEDULE_EXTRA_STATE_RESTORER
262
263
264/* These are extra_state_saver/restorer values for a user trap. Note
265 that we save the argument registers so that restarted syscalls will
266 function properly (otherwise it wouldn't be necessary), and we must
267 _not_ restore the return-value registers (so that traps can return a
268 value!), but call-clobbered registers are not saved at all, as the
269 caller of the syscall function should have saved them. */
270
271#define TRAP_RET reti
272/* Traps don't save call-clobbered registers (but do still save arg regs).
273 We preserve PSw to keep long-term state, namely interrupt status (for traps
274 from kernel-mode), and the single-step flag (for user traps). */
275#define TRAP_STATE_SAVER \
276 SAVE_ARG_REGS; \
277 SAVE_PC(EIPC); \
278 SAVE_PSW(EIPSW)
279/* When traps return, they just leave call-clobbered registers (except for arg
280 regs) with whatever value they have from the kernel. Traps don't preserve
281 the PSW, but we zero EIPSW to ensure it doesn't contain anything dangerous
282 (in particular, the single-step flag). */
283#define TRAP_STATE_RESTORER \
284 RESTORE_ARG_REGS; \
285 RESTORE_PC(EIPC); \
286 RESTORE_PSW(EIPSW)
287/* Save registers not normally saved by traps. We need to save r12, even
288 though it's nominally call-clobbered, because it's used when restarting
289 a system call (the signal-handling path uses SAVE_EXTRA_STATE, and
290 expects r12 to be restored when the trap returns). */
291#define TRAP_EXTRA_STATE_SAVER \
292 SAVE_RVAL_REGS; \
293 sst.w r12, PTO+PT_GPR(12)[ep]; \
294 SAVE_CALL_SAVED_REGS; \
295 SAVE_CT_REGS
296#define TRAP_EXTRA_STATE_RESTORER \
297 RESTORE_RVAL_REGS; \
298 sld.w PTO+PT_GPR(12)[ep], r12; \
299 RESTORE_CALL_SAVED_REGS; \
300 RESTORE_CT_REGS
301/* Save registers prior to calling scheduler (just before trap returns).
302 We have to save the return-value registers to preserve the trap's return
303 value. Note that ..._SCHEDULE_EXTRA_STATE_SAVER, unlike most ..._SAVER
304 macros, is required to setup EP itself if EP is needed (this is because
305 in many cases, the macro is empty). */
306#define TRAP_SCHEDULE_EXTRA_STATE_SAVER \
307 mov sp, ep; \
308 SAVE_RVAL_REGS
309/* Note that ..._SCHEDULE_EXTRA_STATE_RESTORER, unlike most ..._RESTORER
310 macros, is required to setup EP itself if EP is needed (this is because
311 in many cases, the macro is empty). */
312#define TRAP_SCHEDULE_EXTRA_STATE_RESTORER \
313 mov sp, ep; \
314 RESTORE_RVAL_REGS
315
316/* Register saving/restoring for maskable interrupts. */
317#define IRQ_RET reti
318#define IRQ_STATE_SAVER \
319 SAVE_CALL_CLOBBERED_REGS; \
320 SAVE_PC(EIPC); \
321 SAVE_PSW(EIPSW)
322#define IRQ_STATE_RESTORER \
323 RESTORE_CALL_CLOBBERED_REGS; \
324 RESTORE_PC(EIPC); \
325 RESTORE_PSW(EIPSW)
326#define IRQ_EXTRA_STATE_SAVER \
327 SAVE_CALL_SAVED_REGS; \
328 SAVE_CT_REGS
329#define IRQ_EXTRA_STATE_RESTORER \
330 RESTORE_CALL_SAVED_REGS; \
331 RESTORE_CT_REGS
332#define IRQ_SCHEDULE_EXTRA_STATE_SAVER /* nothing */
333#define IRQ_SCHEDULE_EXTRA_STATE_RESTORER /* nothing */
334
335/* Register saving/restoring for non-maskable interrupts. */
336#define NMI_RET reti
337#define NMI_STATE_SAVER \
338 SAVE_CALL_CLOBBERED_REGS; \
339 SAVE_PC(FEPC); \
340 SAVE_PSW(FEPSW);
341#define NMI_STATE_RESTORER \
342 RESTORE_CALL_CLOBBERED_REGS; \
343 RESTORE_PC(FEPC); \
344 RESTORE_PSW(FEPSW);
345#define NMI_EXTRA_STATE_SAVER \
346 SAVE_CALL_SAVED_REGS; \
347 SAVE_CT_REGS
348#define NMI_EXTRA_STATE_RESTORER \
349 RESTORE_CALL_SAVED_REGS; \
350 RESTORE_CT_REGS
351#define NMI_SCHEDULE_EXTRA_STATE_SAVER /* nothing */
352#define NMI_SCHEDULE_EXTRA_STATE_RESTORER /* nothing */
353
354/* Register saving/restoring for debug traps. */
355#define DBTRAP_RET .long 0x014607E0 /* `dbret', but gas doesn't support it. */
356#define DBTRAP_STATE_SAVER \
357 SAVE_CALL_CLOBBERED_REGS; \
358 SAVE_PC(DBPC); \
359 SAVE_PSW(DBPSW)
360#define DBTRAP_STATE_RESTORER \
361 RESTORE_CALL_CLOBBERED_REGS; \
362 RESTORE_PC(DBPC); \
363 RESTORE_PSW(DBPSW)
364#define DBTRAP_EXTRA_STATE_SAVER \
365 SAVE_CALL_SAVED_REGS; \
366 SAVE_CT_REGS
367#define DBTRAP_EXTRA_STATE_RESTORER \
368 RESTORE_CALL_SAVED_REGS; \
369 RESTORE_CT_REGS
370#define DBTRAP_SCHEDULE_EXTRA_STATE_SAVER /* nothing */
371#define DBTRAP_SCHEDULE_EXTRA_STATE_RESTORER /* nothing */
372
373/* Register saving/restoring for a context switch. We don't need to save
374 too many registers, because context-switching looks like a function call
375 (via the function `switch_thread'), so callers will save any
376 call-clobbered registers themselves. We do need to save the CT regs, as
377 they're normally not saved during kernel entry (the kernel doesn't use
378 them). We save PSW so that interrupt-status state will correctly follow
379 each thread (mostly NMI vs. normal-IRQ/trap), though for the most part
380 it doesn't matter since threads are always in almost exactly the same
381 processor state during a context switch. The stack pointer and return
382 value are handled by switch_thread itself. */
383#define SWITCH_STATE_SAVER \
384 SAVE_CALL_SAVED_REGS; \
385 SAVE_PSW(PSW); \
386 SAVE_CT_REGS
387#define SWITCH_STATE_RESTORER \
388 RESTORE_CALL_SAVED_REGS; \
389 RESTORE_PSW(PSW); \
390 RESTORE_CT_REGS
391
392
393/* Restore register state from the state-save-frame on the stack, switch back
394 to the user stack if necessary, and return from the trap/interrupt.
395 EXTRA_STATE_RESTORER is a sequence of assembly language statements to
396 restore anything not restored by this macro. Only registers not saved by
397 the C compiler are restored (that is, R3(sp), R4(gp), R31(lp), and
398 anything restored by EXTRA_STATE_RESTORER). */
399#define RETURN(type) \
400 ld.b PTO+PT_KERNEL_MODE[sp], r19; \
401 di; /* Disable interrupts */ \
402 cmp r19, r0; /* See if returning to kernel mode, */\
403 bne 2f; /* ... if so, skip resched &c. */ \
404 \
405 /* We're returning to user mode, so check for various conditions that \
406 trigger rescheduling. */ \
407 GET_CURRENT_THREAD(r18); \
408 ld.w TI_FLAGS[r18], r19; \
409 andi _TIF_NEED_RESCHED, r19, r0; \
410 bnz 3f; /* Call the scheduler. */ \
4115: andi _TIF_SIGPENDING, r19, r18; \
412 ld.w TASK_PTRACE[CURRENT_TASK], r19; /* ptrace flags */ \
413 or r18, r19; /* see if either is non-zero */ \
414 bnz 4f; /* if so, handle them */ \
415 \
416/* Return to user state. */ \
4171: st.b r0, KM; /* Now officially in user state. */ \
418 \
419/* Final return. The stack-pointer fiddling is not needed when returning \
420 to kernel-mode, but they don't hurt, and this way we can share the \
421 (sometimes rather lengthy) POP_STATE macro. */ \
4222: POP_STATE(type); \
423 st.w sp, KSP; /* Save the kernel stack pointer. */ \
424 ld.w PT_GPR(GPR_SP)-PT_SIZE[sp], sp; /* Restore stack pointer. */ \
425 type ## _RET; /* Return from the trap/interrupt. */ \
426 \
427/* Call the scheduler before returning from a syscall/trap. */ \
4283: SAVE_EXTRA_STATE_FOR_SCHEDULE(type); /* Prepare to call scheduler. */ \
429 jarl call_scheduler, lp; /* Call scheduler */ \
430 di; /* The scheduler enables interrupts */\
431 RESTORE_EXTRA_STATE_FOR_SCHEDULE(type); \
432 GET_CURRENT_THREAD(r18); \
433 ld.w TI_FLAGS[r18], r19; \
434 br 5b; /* Continue with return path. */ \
435 \
436/* Handle a signal or ptraced process return. \
437 r18 should be non-zero if there are pending signals. */ \
4384: /* Not all registers are saved by the normal trap/interrupt entry \
439 points (for instance, call-saved registers (because the normal \
440 C-compiler calling sequence in the kernel makes sure they're \
441 preserved), and call-clobbered registers in the case of \
442 traps), but signal handlers may want to examine or change the \
443 complete register state. Here we save anything not saved by \
444 the normal entry sequence, so that it may be safely restored \
445 (in a possibly modified form) after do_signal returns. */ \
446 SAVE_EXTRA_STATE(type); /* Save state not saved by entry. */ \
447 jarl handle_signal_or_ptrace_return, lp; \
448 RESTORE_EXTRA_STATE(type); /* Restore extra regs. */ \
449 br 1b
450
451
452/* Jump to the appropriate function for the system call number in r12
453 (r12 is not preserved), or return an error if r12 is not valid. The
454 LP register should point to the location where the called function
455 should return. [note that MAKE_SYS_CALL uses label 1] */
456#define MAKE_SYS_CALL \
457 /* Figure out which function to use for this system call. */ \
458 shl 2, r12; \
459 /* See if the system call number is valid. */ \
460 addi lo(CSYM(sys_call_table) - sys_call_table_end), r12, r0; \
461 bnh 1f; \
462 mov hilo(CSYM(sys_call_table)), r19; \
463 add r19, r12; \
464 ld.w 0[r12], r12; \
465 /* Make the system call. */ \
466 jmp [r12]; \
467 /* The syscall number is invalid, return an error. */ \
4681: addi -ENOSYS, r0, r10; \
469 jmp [lp]
470
471
472 .text
473
474/*
475 * User trap.
476 *
477 * Trap 0 system calls are also handled here.
478 *
479 * The stack-pointer (r3) should have already been saved to the memory
480 * location ENTRY_SP (the reason for this is that the interrupt vectors may be
481 * beyond a 22-bit signed offset jump from the actual interrupt handler, and
482 * this allows them to save the stack-pointer and use that register to do an
483 * indirect jump).
484 *
485 * Syscall protocol:
486 * Syscall number in r12, args in r6-r9
487 * Return value in r10
488 */
489G_ENTRY(trap):
490 SAVE_STATE (TRAP, r12, ENTRY_SP) // Save registers.
491 stsr SR_ECR, r19 // Find out which trap it was.
492 ei // Enable interrupts.
493 mov hilo(ret_from_trap), lp // where the trap should return
494
495 // The following two shifts (1) clear out extraneous NMI data in the
496 // upper 16-bits, (2) convert the 0x40 - 0x5f range of trap ECR
497 // numbers into the (0-31) << 2 range we want, (3) set the flags.
498 shl 27, r19 // chop off all high bits
499 shr 25, r19 // scale back down and then << 2
500 bnz 2f // See if not trap 0.
501
502 // Trap 0 is a `short' system call, skip general trap table.
503 MAKE_SYS_CALL // Jump to the syscall function.
504
5052: // For other traps, use a table lookup.
506 mov hilo(CSYM(trap_table)), r18
507 add r19, r18
508 ld.w 0[r18], r18
509 jmp [r18] // Jump to the trap handler.
510END(trap)
511
512/* This is just like ret_from_trap, but first restores extra registers
513 saved by some wrappers. */
514L_ENTRY(restore_extra_regs_and_ret_from_trap):
515 RESTORE_EXTRA_STATE(TRAP)
516 // fall through
517END(restore_extra_regs_and_ret_from_trap)
518
519/* Entry point used to return from a syscall/trap. */
520L_ENTRY(ret_from_trap):
521 RETURN(TRAP)
522END(ret_from_trap)
523
524
525/* This the initial entry point for a new child thread, with an appropriate
526 stack in place that makes it look the the child is in the middle of an
527 syscall. This function is actually `returned to' from switch_thread
528 (copy_thread makes ret_from_fork the return address in each new thread's
529 saved context). */
530C_ENTRY(ret_from_fork):
531 mov r10, r6 // switch_thread returns the prev task.
532 jarl CSYM(schedule_tail), lp // ...which is schedule_tail's arg
533 mov r0, r10 // Child's fork call should return 0.
534 br ret_from_trap // Do normal trap return.
535C_END(ret_from_fork)
536
537
538/*
539 * Trap 1: `long' system calls
540 * `Long' syscall protocol:
541 * Syscall number in r12, args in r6-r9, r13-r14
542 * Return value in r10
543 */
544L_ENTRY(syscall_long):
545 // Push extra arguments on the stack. Note that by default, the trap
546 // handler reserves enough stack space for 6 arguments, so we don't
547 // have to make any additional room.
548 st.w r13, 16[sp] // arg 5
549 st.w r14, 20[sp] // arg 6
550
551 // Make sure r13 and r14 are preserved, in case we have to restart a
552 // system call because of a signal (ep has already been set by caller).
553 st.w r13, PTO+PT_GPR(13)[sp]
554 st.w r14, PTO+PT_GPR(13)[sp]
555 mov hilo(ret_from_long_syscall), lp
556
557 MAKE_SYS_CALL // Jump to the syscall function.
558END(syscall_long)
559
560/* Entry point used to return from a long syscall. Only needed to restore
561 r13/r14 if the general trap mechanism doesnt' do so. */
562L_ENTRY(ret_from_long_syscall):
563 ld.w PTO+PT_GPR(13)[sp], r13 // Restore the extra registers
564 ld.w PTO+PT_GPR(13)[sp], r14
565 br ret_from_trap // The rest is the same as other traps
566END(ret_from_long_syscall)
567
568
569/* These syscalls need access to the struct pt_regs on the stack, so we
570 implement them in assembly (they're basically all wrappers anyway). */
571
572L_ENTRY(sys_fork_wrapper):
573#ifdef CONFIG_MMU
574 addi SIGCHLD, r0, r6 // Arg 0: flags
575 ld.w PTO+PT_GPR(GPR_SP)[sp], r7 // Arg 1: child SP (use parent's)
576 movea PTO, sp, r8 // Arg 2: parent context
577 mov r0, r9 // Arg 3/4/5: 0
578 st.w r0, 16[sp]
579 st.w r0, 20[sp]
580 mov hilo(CSYM(do_fork)), r18 // Where the real work gets done
581 br save_extra_state_tramp // Save state and go there
582#else
583 // fork almost works, enough to trick you into looking elsewhere :-(
584 addi -EINVAL, r0, r10
585 jmp [lp]
586#endif
587END(sys_fork_wrapper)
588
589L_ENTRY(sys_vfork_wrapper):
590 addi CLONE_VFORK | CLONE_VM | SIGCHLD, r0, r6 // Arg 0: flags
591 ld.w PTO+PT_GPR(GPR_SP)[sp], r7 // Arg 1: child SP (use parent's)
592 movea PTO, sp, r8 // Arg 2: parent context
593 mov r0, r9 // Arg 3/4/5: 0
594 st.w r0, 16[sp]
595 st.w r0, 20[sp]
596 mov hilo(CSYM(do_fork)), r18 // Where the real work gets done
597 br save_extra_state_tramp // Save state and go there
598END(sys_vfork_wrapper)
599
600L_ENTRY(sys_clone_wrapper):
601 ld.w PTO+PT_GPR(GPR_SP)[sp], r19// parent's stack pointer
602 cmp r7, r0 // See if child SP arg (arg 1) is 0.
603 cmov z, r19, r7, r7 // ... and use the parent's if so.
604 movea PTO, sp, r8 // Arg 2: parent context
605 mov r0, r9 // Arg 3/4/5: 0
606 st.w r0, 16[sp]
607 st.w r0, 20[sp]
608 mov hilo(CSYM(do_fork)), r18 // Where the real work gets done
609 br save_extra_state_tramp // Save state and go there
610END(sys_clone_wrapper)
611
612
613L_ENTRY(sys_execve_wrapper):
614 movea PTO, sp, r9 // add user context as 4th arg
615 jr CSYM(sys_execve) // Do real work (tail-call).
616END(sys_execve_wrapper)
617
618
619L_ENTRY(sys_sigsuspend_wrapper):
620 movea PTO, sp, r7 // add user context as 2nd arg
621 mov hilo(CSYM(sys_sigsuspend)), r18 // syscall function
622 jarl save_extra_state_tramp, lp // Save state and do it
623 br restore_extra_regs_and_ret_from_trap
624END(sys_sigsuspend_wrapper)
625L_ENTRY(sys_rt_sigsuspend_wrapper):
626 movea PTO, sp, r8 // add user context as 3rd arg
627 mov hilo(CSYM(sys_rt_sigsuspend)), r18 // syscall function
628 jarl save_extra_state_tramp, lp // Save state and do it
629 br restore_extra_regs_and_ret_from_trap
630END(sys_rt_sigsuspend_wrapper)
631
632L_ENTRY(sys_sigreturn_wrapper):
633 movea PTO, sp, r6 // add user context as 1st arg
634 mov hilo(CSYM(sys_sigreturn)), r18 // syscall function
635 jarl save_extra_state_tramp, lp // Save state and do it
636 br restore_extra_regs_and_ret_from_trap
637END(sys_sigreturn_wrapper)
638L_ENTRY(sys_rt_sigreturn_wrapper):
639 movea PTO, sp, r6 // add user context as 1st arg
640 mov hilo(CSYM(sys_rt_sigreturn)), r18// syscall function
641 jarl save_extra_state_tramp, lp // Save state and do it
642 br restore_extra_regs_and_ret_from_trap
643END(sys_rt_sigreturn_wrapper)
644
645
646/* Save any state not saved by SAVE_STATE(TRAP), and jump to r18.
647 It's main purpose is to share the rather lengthy code sequence that
648 SAVE_STATE expands into among the above wrapper functions. */
649L_ENTRY(save_extra_state_tramp):
650 SAVE_EXTRA_STATE(TRAP) // Save state not saved by entry.
651 jmp [r18] // Do the work the caller wants
652END(save_extra_state_tramp)
653
654
655/*
656 * Hardware maskable interrupts.
657 *
658 * The stack-pointer (r3) should have already been saved to the memory
659 * location ENTRY_SP (the reason for this is that the interrupt vectors may be
660 * beyond a 22-bit signed offset jump from the actual interrupt handler, and
661 * this allows them to save the stack-pointer and use that register to do an
662 * indirect jump).
663 */
664G_ENTRY(irq):
665 SAVE_STATE (IRQ, r0, ENTRY_SP) // Save registers.
666
667 stsr SR_ECR, r6 // Find out which interrupt it was.
668 movea PTO, sp, r7 // User regs are arg2
669
670 // All v850 implementations I know about encode their interrupts as
671 // multiples of 0x10, starting at 0x80 (after NMIs and software
672 // interrupts). Convert this number into a simple IRQ index for the
673 // rest of the kernel. We also clear the upper 16 bits, which hold
674 // NMI info, and don't appear to be cleared when a NMI returns.
675 shl 16, r6 // clear upper 16 bits
676 shr 20, r6 // shift back, and remove lower nibble
677 add -8, r6 // remove bias for irqs
678
679 // Call the high-level interrupt handling code.
680 jarl CSYM(handle_irq), lp
681
682 RETURN(IRQ)
683END(irq)
684
685
686/*
687 * Debug trap / illegal-instruction exception
688 *
689 * The stack-pointer (r3) should have already been saved to the memory
690 * location ENTRY_SP (the reason for this is that the interrupt vectors may be
691 * beyond a 22-bit signed offset jump from the actual interrupt handler, and
692 * this allows them to save the stack-pointer and use that register to do an
693 * indirect jump).
694 */
695G_ENTRY(dbtrap):
696 SAVE_STATE (DBTRAP, r0, ENTRY_SP)// Save registers.
697
698 /* First see if we came from kernel mode; if so, the dbtrap
699 instruction has a special meaning, to set the DIR (`debug
700 information register') register. This is because the DIR register
701 can _only_ be manipulated/read while in `debug mode,' and debug
702 mode is only active while we're inside the dbtrap handler. The
703 exact functionality is: { DIR = (DIR | r6) & ~r7; return DIR; }. */
704 ld.b PTO+PT_KERNEL_MODE[sp], r19
705 cmp r19, r0
706 bz 1f
707
708 stsr SR_DIR, r10
709 or r6, r10
710 not r7, r7
711 and r7, r10
712 ldsr r10, SR_DIR
713 stsr SR_DIR, r10 // Confirm the value we set
714 st.w r10, PTO+PT_GPR(10)[sp] // return it
715 br 3f
716
7171: ei // Enable interrupts.
718
719 /* The default signal type we raise. */
720 mov SIGTRAP, r6
721
722 /* See if it's a single-step trap. */
723 stsr SR_DBPSW, r19
724 andi 0x0800, r19, r19
725 bnz 2f
726
727 /* Look to see if the preceding instruction was is a dbtrap or not,
728 to decide which signal we should use. */
729 stsr SR_DBPC, r19 // PC following trapping insn
730 ld.hu -2[r19], r19
731 ori 0xf840, r0, r20 // DBTRAP insn
732 cmp r19, r20 // Was this trap caused by DBTRAP?
733 cmov ne, SIGILL, r6, r6 // Choose signal appropriately
734
735 /* Raise the desired signal. */
7362: mov CURRENT_TASK, r7 // Arg 1: task
737 jarl CSYM(send_sig), lp // tail call
738
7393: RETURN(DBTRAP)
740END(dbtrap)
741
742
743/*
744 * Hardware non-maskable interrupts.
745 *
746 * The stack-pointer (r3) should have already been saved to the memory
747 * location ENTRY_SP (the reason for this is that the interrupt vectors may be
748 * beyond a 22-bit signed offset jump from the actual interrupt handler, and
749 * this allows them to save the stack-pointer and use that register to do an
750 * indirect jump).
751 */
752G_ENTRY(nmi):
753 SAVE_STATE (NMI, r0, NMI_ENTRY_SP); /* Save registers. */
754
755 stsr SR_ECR, r6; /* Find out which nmi it was. */
756 shr 20, r6; /* Extract NMI code in bits 20-24. */
757 movea PTO, sp, r7; /* User regs are arg2. */
758
759 /* Non-maskable interrupts always lie right after maskable interrupts.
760 Call the generic IRQ handler, with two arguments, the IRQ number,
761 and a pointer to the user registers, to handle the specifics.
762 (we subtract one because the first NMI has code 1). */
763 addi FIRST_NMI - 1, r6, r6
764 jarl CSYM(handle_irq), lp
765
766 RETURN(NMI)
767END(nmi)
768
769
770/*
771 * Trap with no handler
772 */
773L_ENTRY(bad_trap_wrapper):
774 mov r19, r6 // Arg 0: trap number
775 movea PTO, sp, r7 // Arg 1: user regs
776 jr CSYM(bad_trap) // tail call handler
777END(bad_trap_wrapper)
778
779
780/*
781 * Invoke the scheduler, called from the trap/irq kernel exit path.
782 *
783 * This basically just calls `schedule', but also arranges for extra
784 * registers to be saved for ptrace'd processes, so ptrace can modify them.
785 */
786L_ENTRY(call_scheduler):
787 ld.w TASK_PTRACE[CURRENT_TASK], r19 // See if task is ptrace'd
788 cmp r19, r0
789 bnz 1f // ... yes, do special stuff
790 jr CSYM(schedule) // ... no, just tail-call scheduler
791
792 // Save extra regs for ptrace'd task. We want to save anything
793 // that would otherwise only be `implicitly' saved by the normal
794 // compiler calling-convention.
7951: mov sp, ep // Setup EP for SAVE_CALL_SAVED_REGS
796 SAVE_CALL_SAVED_REGS // Save call-saved registers to stack
797 mov lp, r20 // Save LP in a callee-saved register
798
799 jarl CSYM(schedule), lp // Call scheduler
800
801 mov r20, lp
802 mov sp, ep // We can't rely on EP after return
803 RESTORE_CALL_SAVED_REGS // Restore (possibly modified) regs
804 jmp [lp] // Return to the return path
805END(call_scheduler)
806
807
808/*
809 * This is an out-of-line handler for two special cases during the kernel
810 * trap/irq exit sequence:
811 *
812 * (1) If r18 is non-zero then a signal needs to be handled, which is
813 * done, and then the caller returned to.
814 *
815 * (2) If r18 is non-zero then we're returning to a ptraced process, which
816 * has several special cases -- single-stepping and trap tracing, both
817 * of which require using the `dbret' instruction to exit the kernel
818 * instead of the normal `reti' (this is because the CPU not correctly
819 * single-step after a reti). In this case, of course, this handler
820 * never returns to the caller.
821 *
822 * In either case, all registers should have been saved to the current
823 * state-save-frame on the stack, except for callee-saved registers.
824 *
825 * [These two different cases are combined merely to avoid bloating the
826 * macro-inlined code, not because they really make much sense together!]
827 */
828L_ENTRY(handle_signal_or_ptrace_return):
829 cmp r18, r0 // See if handling a signal
830 bz 1f // ... nope, go do ptrace return
831
832 // Handle a signal
833 mov lp, r20 // Save link-pointer
834 mov r10, r21 // Save return-values (for trap)
835 mov r11, r22
836
837 movea PTO, sp, r6 // Arg 1: struct pt_regs *regs
838 mov r0, r7 // Arg 2: sigset_t *oldset
839 jarl CSYM(do_signal), lp // Handle the signal
840 di // sig handling enables interrupts
841
842 mov r20, lp // Restore link-pointer
843 mov r21, r10 // Restore return-values (for trap)
844 mov r22, r11
845 ld.w TASK_PTRACE[CURRENT_TASK], r19 // check ptrace flags too
846 cmp r19, r0
847 bnz 1f // ... some set, so look more
8482: jmp [lp] // ... none set, so return normally
849
850 // ptrace return
8511: ld.w PTO+PT_PSW[sp], r19 // Look at user-processes's flags
852 andi 0x0800, r19, r19 // See if single-step flag is set
853 bz 2b // ... nope, return normally
854
855 // Return as if from a dbtrap insn
856 st.b r0, KM // Now officially in user state.
857 POP_STATE(DBTRAP) // Restore regs
858 st.w sp, KSP // Save the kernel stack pointer.
859 ld.w PT_GPR(GPR_SP)-PT_SIZE[sp], sp // Restore user stack pointer.
860 DBTRAP_RET // Return from the trap/interrupt.
861END(handle_signal_or_ptrace_return)
862
863
864/*
865 * This is where we switch between two threads. The arguments are:
866 * r6 -- pointer to the struct thread for the `current' process
867 * r7 -- pointer to the struct thread for the `new' process.
868 * when this function returns, it will return to the new thread.
869 */
870C_ENTRY(switch_thread):
871 // Return the previous task (r10 is not clobbered by restore below)
872 mov CURRENT_TASK, r10
873 // First, push the current processor state on the stack
874 PUSH_STATE(SWITCH)
875 // Now save the location of the kernel stack pointer for this thread;
876 // since we've pushed all other state on the stack, this is enough to
877 // restore it all later.
878 st.w sp, THREAD_KSP[r6]
879 // Now restore the stack pointer from the new process
880 ld.w THREAD_KSP[r7], sp
881 // ... and restore all state from that
882 POP_STATE(SWITCH)
883 // Update the current task pointer
884 GET_CURRENT_TASK(CURRENT_TASK)
885 // Now return into the new thread
886 jmp [lp]
887C_END(switch_thread)
888
889
890 .data
891
892 .align 4
893C_DATA(trap_table):
894 .long bad_trap_wrapper // trap 0, doesn't use trap table.
895 .long syscall_long // trap 1, `long' syscall.
896 .long bad_trap_wrapper
897 .long bad_trap_wrapper
898 .long bad_trap_wrapper
899 .long bad_trap_wrapper
900 .long bad_trap_wrapper
901 .long bad_trap_wrapper
902 .long bad_trap_wrapper
903 .long bad_trap_wrapper
904 .long bad_trap_wrapper
905 .long bad_trap_wrapper
906 .long bad_trap_wrapper
907 .long bad_trap_wrapper
908 .long bad_trap_wrapper
909 .long bad_trap_wrapper
910C_END(trap_table)
911
912
913 .section .rodata
914
915 .align 4
916C_DATA(sys_call_table):
917 .long CSYM(sys_restart_syscall) // 0
918 .long CSYM(sys_exit)
919 .long sys_fork_wrapper
920 .long CSYM(sys_read)
921 .long CSYM(sys_write)
922 .long CSYM(sys_open) // 5
923 .long CSYM(sys_close)
924 .long CSYM(sys_waitpid)
925 .long CSYM(sys_creat)
926 .long CSYM(sys_link)
927 .long CSYM(sys_unlink) // 10
928 .long sys_execve_wrapper
929 .long CSYM(sys_chdir)
930 .long CSYM(sys_time)
931 .long CSYM(sys_mknod)
932 .long CSYM(sys_chmod) // 15
933 .long CSYM(sys_chown)
934 .long CSYM(sys_ni_syscall) // was: break
935 .long CSYM(sys_ni_syscall) // was: oldstat (aka stat)
936 .long CSYM(sys_lseek)
937 .long CSYM(sys_getpid) // 20
938 .long CSYM(sys_mount)
939 .long CSYM(sys_oldumount)
940 .long CSYM(sys_setuid)
941 .long CSYM(sys_getuid)
942 .long CSYM(sys_stime) // 25
943 .long CSYM(sys_ptrace)
944 .long CSYM(sys_alarm)
945 .long CSYM(sys_ni_syscall) // was: oldfstat (aka fstat)
946 .long CSYM(sys_pause)
947 .long CSYM(sys_utime) // 30
948 .long CSYM(sys_ni_syscall) // was: stty
949 .long CSYM(sys_ni_syscall) // was: gtty
950 .long CSYM(sys_access)
951 .long CSYM(sys_nice)
952 .long CSYM(sys_ni_syscall) // 35, was: ftime
953 .long CSYM(sys_sync)
954 .long CSYM(sys_kill)
955 .long CSYM(sys_rename)
956 .long CSYM(sys_mkdir)
957 .long CSYM(sys_rmdir) // 40
958 .long CSYM(sys_dup)
959 .long CSYM(sys_pipe)
960 .long CSYM(sys_times)
961 .long CSYM(sys_ni_syscall) // was: prof
962 .long CSYM(sys_brk) // 45
963 .long CSYM(sys_setgid)
964 .long CSYM(sys_getgid)
965 .long CSYM(sys_signal)
966 .long CSYM(sys_geteuid)
967 .long CSYM(sys_getegid) // 50
968 .long CSYM(sys_acct)
969 .long CSYM(sys_umount) // recycled never used phys()
970 .long CSYM(sys_ni_syscall) // was: lock
971 .long CSYM(sys_ioctl)
972 .long CSYM(sys_fcntl) // 55
973 .long CSYM(sys_ni_syscall) // was: mpx
974 .long CSYM(sys_setpgid)
975 .long CSYM(sys_ni_syscall) // was: ulimit
976 .long CSYM(sys_ni_syscall)
977 .long CSYM(sys_umask) // 60
978 .long CSYM(sys_chroot)
979 .long CSYM(sys_ustat)
980 .long CSYM(sys_dup2)
981 .long CSYM(sys_getppid)
982 .long CSYM(sys_getpgrp) // 65
983 .long CSYM(sys_setsid)
984 .long CSYM(sys_sigaction)
985 .long CSYM(sys_sgetmask)
986 .long CSYM(sys_ssetmask)
987 .long CSYM(sys_setreuid) // 70
988 .long CSYM(sys_setregid)
989 .long sys_sigsuspend_wrapper
990 .long CSYM(sys_sigpending)
991 .long CSYM(sys_sethostname)
992 .long CSYM(sys_setrlimit) // 75
993 .long CSYM(sys_getrlimit)
994 .long CSYM(sys_getrusage)
995 .long CSYM(sys_gettimeofday)
996 .long CSYM(sys_settimeofday)
997 .long CSYM(sys_getgroups) // 80
998 .long CSYM(sys_setgroups)
999 .long CSYM(sys_select)
1000 .long CSYM(sys_symlink)
1001 .long CSYM(sys_ni_syscall) // was: oldlstat (aka lstat)
1002 .long CSYM(sys_readlink) // 85
1003 .long CSYM(sys_uselib)
1004 .long CSYM(sys_swapon)
1005 .long CSYM(sys_reboot)
1006 .long CSYM(old_readdir)
1007 .long CSYM(sys_mmap) // 90
1008 .long CSYM(sys_munmap)
1009 .long CSYM(sys_truncate)
1010 .long CSYM(sys_ftruncate)
1011 .long CSYM(sys_fchmod)
1012 .long CSYM(sys_fchown) // 95
1013 .long CSYM(sys_getpriority)
1014 .long CSYM(sys_setpriority)
1015 .long CSYM(sys_ni_syscall) // was: profil
1016 .long CSYM(sys_statfs)
1017 .long CSYM(sys_fstatfs) // 100
1018 .long CSYM(sys_ni_syscall) // i386: ioperm
1019 .long CSYM(sys_socketcall)
1020 .long CSYM(sys_syslog)
1021 .long CSYM(sys_setitimer)
1022 .long CSYM(sys_getitimer) // 105
1023 .long CSYM(sys_newstat)
1024 .long CSYM(sys_newlstat)
1025 .long CSYM(sys_newfstat)
1026 .long CSYM(sys_ni_syscall) // was: olduname (aka uname)
1027 .long CSYM(sys_ni_syscall) // 110, i386: iopl
1028 .long CSYM(sys_vhangup)
1029 .long CSYM(sys_ni_syscall) // was: idle
1030 .long CSYM(sys_ni_syscall) // i386: vm86old
1031 .long CSYM(sys_wait4)
1032 .long CSYM(sys_swapoff) // 115
1033 .long CSYM(sys_sysinfo)
1034 .long CSYM(sys_ipc)
1035 .long CSYM(sys_fsync)
1036 .long sys_sigreturn_wrapper
1037 .long sys_clone_wrapper // 120
1038 .long CSYM(sys_setdomainname)
1039 .long CSYM(sys_newuname)
1040 .long CSYM(sys_ni_syscall) // i386: modify_ldt, m68k: cacheflush
1041 .long CSYM(sys_adjtimex)
1042 .long CSYM(sys_ni_syscall) // 125 - sys_mprotect
1043 .long CSYM(sys_sigprocmask)
1044 .long CSYM(sys_ni_syscall) // sys_create_module
1045 .long CSYM(sys_init_module)
1046 .long CSYM(sys_delete_module)
1047 .long CSYM(sys_ni_syscall) // 130 - sys_get_kernel_syms
1048 .long CSYM(sys_quotactl)
1049 .long CSYM(sys_getpgid)
1050 .long CSYM(sys_fchdir)
1051 .long CSYM(sys_bdflush)
1052 .long CSYM(sys_sysfs) // 135
1053 .long CSYM(sys_personality)
1054 .long CSYM(sys_ni_syscall) // for afs_syscall
1055 .long CSYM(sys_setfsuid)
1056 .long CSYM(sys_setfsgid)
1057 .long CSYM(sys_llseek) // 140
1058 .long CSYM(sys_getdents)
1059 .long CSYM(sys_select) // for backward compat; remove someday
1060 .long CSYM(sys_flock)
1061 .long CSYM(sys_ni_syscall) // sys_msync
1062 .long CSYM(sys_readv) // 145
1063 .long CSYM(sys_writev)
1064 .long CSYM(sys_getsid)
1065 .long CSYM(sys_fdatasync)
1066 .long CSYM(sys_sysctl)
1067 .long CSYM(sys_ni_syscall) // 150 - sys_mlock
1068 .long CSYM(sys_ni_syscall) // sys_munlock
1069 .long CSYM(sys_ni_syscall) // sys_mlockall
1070 .long CSYM(sys_ni_syscall) // sys_munlockall
1071 .long CSYM(sys_sched_setparam)
1072 .long CSYM(sys_sched_getparam) // 155
1073 .long CSYM(sys_sched_setscheduler)
1074 .long CSYM(sys_sched_getscheduler)
1075 .long CSYM(sys_sched_yield)
1076 .long CSYM(sys_sched_get_priority_max)
1077 .long CSYM(sys_sched_get_priority_min) // 160
1078 .long CSYM(sys_sched_rr_get_interval)
1079 .long CSYM(sys_nanosleep)
1080 .long CSYM(sys_ni_syscall) // sys_mremap
1081 .long CSYM(sys_setresuid)
1082 .long CSYM(sys_getresuid) // 165
1083 .long CSYM(sys_ni_syscall) // for vm86
1084 .long CSYM(sys_ni_syscall) // sys_query_module
1085 .long CSYM(sys_poll)
1086 .long CSYM(sys_nfsservctl)
1087 .long CSYM(sys_setresgid) // 170
1088 .long CSYM(sys_getresgid)
1089 .long CSYM(sys_prctl)
1090 .long sys_rt_sigreturn_wrapper
1091 .long CSYM(sys_rt_sigaction)
1092 .long CSYM(sys_rt_sigprocmask) // 175
1093 .long CSYM(sys_rt_sigpending)
1094 .long CSYM(sys_rt_sigtimedwait)
1095 .long CSYM(sys_rt_sigqueueinfo)
1096 .long sys_rt_sigsuspend_wrapper
1097 .long CSYM(sys_pread64) // 180
1098 .long CSYM(sys_pwrite64)
1099 .long CSYM(sys_lchown)
1100 .long CSYM(sys_getcwd)
1101 .long CSYM(sys_capget)
1102 .long CSYM(sys_capset) // 185
1103 .long CSYM(sys_sigaltstack)
1104 .long CSYM(sys_sendfile)
1105 .long CSYM(sys_ni_syscall) // streams1
1106 .long CSYM(sys_ni_syscall) // streams2
1107 .long sys_vfork_wrapper // 190
1108 .long CSYM(sys_ni_syscall)
1109 .long CSYM(sys_mmap2)
1110 .long CSYM(sys_truncate64)
1111 .long CSYM(sys_ftruncate64)
1112 .long CSYM(sys_stat64) // 195
1113 .long CSYM(sys_lstat64)
1114 .long CSYM(sys_fstat64)
1115 .long CSYM(sys_fcntl64)
1116 .long CSYM(sys_getdents64)
1117 .long CSYM(sys_pivot_root) // 200
1118 .long CSYM(sys_gettid)
1119 .long CSYM(sys_tkill)
1120sys_call_table_end:
1121C_END(sys_call_table)
diff --git a/arch/v850/kernel/fpga85e2c.c b/arch/v850/kernel/fpga85e2c.c
new file mode 100644
index 000000000000..4bac5149b3c2
--- /dev/null
+++ b/arch/v850/kernel/fpga85e2c.c
@@ -0,0 +1,171 @@
1/*
2 * arch/v850/kernel/fpga85e2c.h -- Machine-dependent defs for
3 * FPGA implementation of V850E2/NA85E2C
4 *
5 * Copyright (C) 2002,03 NEC Electronics Corporation
6 * Copyright (C) 2002,03 Miles Bader <miles@gnu.org>
7 *
8 * This file is subject to the terms and conditions of the GNU General
9 * Public License. See the file COPYING in the main directory of this
10 * archive for more details.
11 *
12 * Written by Miles Bader <miles@gnu.org>
13 */
14
15#include <linux/config.h>
16#include <linux/kernel.h>
17#include <linux/module.h>
18#include <linux/init.h>
19#include <linux/mm.h>
20#include <linux/swap.h>
21#include <linux/bootmem.h>
22#include <linux/irq.h>
23#include <linux/bitops.h>
24
25#include <asm/atomic.h>
26#include <asm/page.h>
27#include <asm/machdep.h>
28
29#include "mach.h"
30
31extern void memcons_setup (void);
32
33
34#define REG_DUMP_ADDR 0x220000
35
36
37extern struct irqaction reg_snap_action; /* fwd decl */
38
39
40void __init mach_early_init (void)
41{
42 int i;
43 const u32 *src;
44 register u32 *dst asm ("ep");
45 extern u32 _intv_end, _intv_load_start;
46
47 /* Set bus sizes: CS0 32-bit, CS1 16-bit, CS7 8-bit,
48 everything else 32-bit. */
49 V850E2_BSC = 0x2AA6;
50 for (i = 2; i <= 6; i++)
51 CSDEV(i) = 0; /* 32 bit */
52
53 /* Ensure that the simulator halts on a panic, instead of going
54 into an infinite loop inside the panic function. */
55 panic_timeout = -1;
56
57 /* Move the interrupt vectors into their real location. Note that
58 any relocations there are relative to the real location, so we
59 don't have to fix anything up. We use a loop instead of calling
60 memcpy to keep this a leaf function (to avoid a function
61 prologue being generated). */
62 dst = 0x10; /* &_intv_start + 0x10. */
63 src = &_intv_load_start;
64 do {
65 u32 t0 = src[0], t1 = src[1], t2 = src[2], t3 = src[3];
66 u32 t4 = src[4], t5 = src[5], t6 = src[6], t7 = src[7];
67 dst[0] = t0; dst[1] = t1; dst[2] = t2; dst[3] = t3;
68 dst[4] = t4; dst[5] = t5; dst[6] = t6; dst[7] = t7;
69 dst += 8;
70 src += 8;
71 } while (dst < &_intv_end);
72}
73
74void __init mach_setup (char **cmdline)
75{
76 memcons_setup ();
77
78 /* Setup up NMI0 to copy the registers to a known memory location.
79 The FGPA board has a button that produces NMI0 when pressed, so
80 this allows us to push the button, and then look at memory to see
81 what's in the registers (there's no other way to easily do so).
82 We have to use `setup_irq' instead of `request_irq' because it's
83 still too early to do memory allocation. */
84 setup_irq (IRQ_NMI (0), &reg_snap_action);
85}
86
87void mach_get_physical_ram (unsigned long *ram_start, unsigned long *ram_len)
88{
89 *ram_start = ERAM_ADDR;
90 *ram_len = ERAM_SIZE;
91}
92
93void __init mach_sched_init (struct irqaction *timer_action)
94{
95 /* Setup up the timer interrupt. The FPGA peripheral control
96 registers _only_ work with single-bit writes (set1/clr1)! */
97 __clear_bit (RPU_GTMC_CE_BIT, &RPU_GTMC);
98 __clear_bit (RPU_GTMC_CLK_BIT, &RPU_GTMC);
99 __set_bit (RPU_GTMC_CE_BIT, &RPU_GTMC);
100
101 /* We use the first RPU interrupt, which occurs every 8.192ms. */
102 setup_irq (IRQ_RPU (0), timer_action);
103}
104
105
106void mach_gettimeofday (struct timespec *tv)
107{
108 tv->tv_sec = 0;
109 tv->tv_nsec = 0;
110}
111
112void machine_halt (void) __attribute__ ((noreturn));
113void machine_halt (void)
114{
115 for (;;) {
116 DWC(0) = 0x7777;
117 DWC(1) = 0x7777;
118 ASC = 0xffff;
119 FLGREG(0) = 1; /* Halt immediately. */
120 asm ("di; halt; nop; nop; nop; nop; nop");
121 }
122}
123
124EXPORT_SYMBOL(machine_halt);
125
126void machine_restart (char *__unused)
127{
128 machine_halt ();
129}
130
131EXPORT_SYMBOL(machine_restart);
132
133void machine_power_off (void)
134{
135 machine_halt ();
136}
137
138EXPORT_SYMBOL(machine_power_off);
139
140
141/* Interrupts */
142
143struct v850e_intc_irq_init irq_inits[] = {
144 { "IRQ", 0, NUM_MACH_IRQS, 1, 7 },
145 { "RPU", IRQ_RPU(0), IRQ_RPU_NUM, 1, 6 },
146 { 0 }
147};
148#define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1)
149
150struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
151
152/* Initialize interrupts. */
153void __init mach_init_irqs (void)
154{
155 v850e_intc_init_irq_types (irq_inits, hw_itypes);
156}
157
158
159/* An interrupt handler that copies the registers to a known memory location,
160 for debugging purposes. */
161
162static void make_reg_snap (int irq, void *dummy, struct pt_regs *regs)
163{
164 (*(unsigned *)REG_DUMP_ADDR)++;
165 (*(struct pt_regs *)(REG_DUMP_ADDR + sizeof (unsigned))) = *regs;
166}
167
168static int reg_snap_dev_id;
169static struct irqaction reg_snap_action = {
170 make_reg_snap, 0, CPU_MASK_NONE, "reg_snap", &reg_snap_dev_id, 0
171};
diff --git a/arch/v850/kernel/fpga85e2c.ld b/arch/v850/kernel/fpga85e2c.ld
new file mode 100644
index 000000000000..b5d4578ae411
--- /dev/null
+++ b/arch/v850/kernel/fpga85e2c.ld
@@ -0,0 +1,62 @@
1/* Linker script for the FPGA implementation of the V850E2 NA85E2C cpu core
2 (CONFIG_V850E2_FPGA85E2C). */
3
4MEMORY {
5 /* Reset vector. */
6 RESET : ORIGIN = 0, LENGTH = 0x10
7 /* Interrupt vectors. */
8 INTV : ORIGIN = 0x10, LENGTH = 0x470
9 /* The `window' in RAM were we're allowed to load stuff. */
10 RAM_LOW : ORIGIN = 0x480, LENGTH = 0x0005FB80
11 /* Some more ram above the window were we can put bss &c. */
12 RAM_HIGH : ORIGIN = 0x00060000, LENGTH = 0x000A0000
13 /* This is the area visible from the outside world (we can use
14 this only for uninitialized data). */
15 VISIBLE : ORIGIN = 0x00200000, LENGTH = 0x00060000
16}
17
18SECTIONS {
19 .reset : {
20 __kram_start = . ;
21 __intv_start = . ;
22 *(.intv.reset) /* Reset vector */
23 } > RESET
24
25 .ram_low : {
26 __r0_ram = . ; /* Must be near address 0. */
27 . = . + 32 ;
28
29 TEXT_CONTENTS
30 DATA_CONTENTS
31 ROOT_FS_CONTENTS
32 RAMK_INIT_CONTENTS_NO_END
33 INITRAMFS_CONTENTS
34 } > RAM_LOW
35
36 /* Where the interrupt vectors are initially loaded. */
37 __intv_load_start = . ;
38
39 .intv : {
40 *(.intv.common) /* Vectors common to all v850e proc. */
41 *(.intv.mach) /* Machine-specific int. vectors. */
42 __intv_end = . ;
43 } > INTV AT> RAM_LOW
44
45 .ram_high : {
46 /* This is here so that when we free init memory the
47 load-time copy of the interrupt vectors and any empty
48 space at the end of the `RAM_LOW' area is freed too. */
49 . = ALIGN (4096);
50 __init_end = . ;
51
52 BSS_CONTENTS
53 __kram_end = . ;
54 BOOTMAP_CONTENTS
55 } > RAM_HIGH
56
57 .visible : {
58 _memcons_output = . ;
59 . = . + 0x8000 ;
60 _memcons_output_end = . ;
61 } > VISIBLE
62}
diff --git a/arch/v850/kernel/gbus_int.c b/arch/v850/kernel/gbus_int.c
new file mode 100644
index 000000000000..92918b8d89ef
--- /dev/null
+++ b/arch/v850/kernel/gbus_int.c
@@ -0,0 +1,271 @@
1/*
2 * arch/v850/kernel/gbus_int.c -- Midas labs GBUS interrupt support
3 *
4 * Copyright (C) 2001,02,03 NEC Electronics Corporation
5 * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14#include <linux/types.h>
15#include <linux/init.h>
16#include <linux/irq.h>
17#include <linux/interrupt.h>
18#include <linux/signal.h>
19
20#include <asm/machdep.h>
21
22
23/* The number of shared GINT interrupts. */
24#define NUM_GINTS 4
25
26/* For each GINT interrupt, how many GBUS interrupts are using it. */
27static unsigned gint_num_active_irqs[NUM_GINTS] = { 0 };
28
29/* A table of GINTn interrupts we actually use.
30 Note that we don't use GINT0 because all the boards we support treat it
31 specially. */
32struct used_gint {
33 unsigned gint;
34 unsigned priority;
35} used_gint[] = {
36 { 1, GBUS_INT_PRIORITY_HIGH },
37 { 3, GBUS_INT_PRIORITY_LOW }
38};
39#define NUM_USED_GINTS (sizeof used_gint / sizeof used_gint[0])
40
41/* A table of which GINT is used by each GBUS interrupts (they are
42 assigned based on priority). */
43static unsigned char gbus_int_gint[IRQ_GBUS_INT_NUM];
44
45
46/* Interrupt enabling/disabling. */
47
48/* Enable interrupt handling for interrupt IRQ. */
49void gbus_int_enable_irq (unsigned irq)
50{
51 unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ];
52 GBUS_INT_ENABLE (GBUS_INT_IRQ_WORD(irq), gint)
53 |= GBUS_INT_IRQ_MASK (irq);
54}
55
56/* Disable interrupt handling for interrupt IRQ. Note that any
57 interrupts received while disabled will be delivered once the
58 interrupt is enabled again, unless they are explicitly cleared using
59 `gbus_int_clear_pending_irq'. */
60void gbus_int_disable_irq (unsigned irq)
61{
62 unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ];
63 GBUS_INT_ENABLE (GBUS_INT_IRQ_WORD(irq), gint)
64 &= ~GBUS_INT_IRQ_MASK (irq);
65}
66
67/* Return true if interrupt handling for interrupt IRQ is enabled. */
68int gbus_int_irq_enabled (unsigned irq)
69{
70 unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ];
71 return (GBUS_INT_ENABLE (GBUS_INT_IRQ_WORD(irq), gint)
72 & GBUS_INT_IRQ_MASK(irq));
73}
74
75/* Disable all GBUS irqs. */
76void gbus_int_disable_irqs ()
77{
78 unsigned w, n;
79 for (w = 0; w < GBUS_INT_NUM_WORDS; w++)
80 for (n = 0; n < IRQ_GINT_NUM; n++)
81 GBUS_INT_ENABLE (w, n) = 0;
82}
83
84/* Clear any pending interrupts for IRQ. */
85void gbus_int_clear_pending_irq (unsigned irq)
86{
87 GBUS_INT_CLEAR (GBUS_INT_IRQ_WORD(irq)) = GBUS_INT_IRQ_MASK (irq);
88}
89
90/* Return true if interrupt IRQ is pending (but disabled). */
91int gbus_int_irq_pending (unsigned irq)
92{
93 return (GBUS_INT_STATUS (GBUS_INT_IRQ_WORD(irq))
94 & GBUS_INT_IRQ_MASK(irq));
95}
96
97
98/* Delegating interrupts. */
99
100/* Handle a shared GINT interrupt by passing to the appropriate GBUS
101 interrupt handler. */
102static irqreturn_t gbus_int_handle_irq (int irq, void *dev_id,
103 struct pt_regs *regs)
104{
105 unsigned w;
106 irqreturn_t rval = IRQ_NONE;
107 unsigned gint = irq - IRQ_GINT (0);
108
109 for (w = 0; w < GBUS_INT_NUM_WORDS; w++) {
110 unsigned status = GBUS_INT_STATUS (w);
111 unsigned enable = GBUS_INT_ENABLE (w, gint);
112
113 /* Only pay attention to enabled interrupts. */
114 status &= enable;
115 if (status) {
116 irq = IRQ_GBUS_INT (w * GBUS_INT_BITS_PER_WORD);
117 do {
118 /* There's an active interrupt in word
119 W, find out which one, and call its
120 handler. */
121
122 while (! (status & 0x1)) {
123 irq++;
124 status >>= 1;
125 }
126 status &= ~0x1;
127
128 /* Recursively call handle_irq to handle it. */
129 handle_irq (irq, regs);
130 rval = IRQ_HANDLED;
131 } while (status);
132 }
133 }
134
135 /* Toggle the `all enable' bit back and forth, which should cause
136 another edge transition if there are any other interrupts
137 still pending, and so result in another CPU interrupt. */
138 GBUS_INT_ENABLE (0, gint) &= ~0x1;
139 GBUS_INT_ENABLE (0, gint) |= 0x1;
140
141 return rval;
142}
143
144
145/* Initialize GBUS interrupt sources. */
146
147static void irq_nop (unsigned irq) { }
148
149static unsigned gbus_int_startup_irq (unsigned irq)
150{
151 unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ];
152
153 if (gint_num_active_irqs[gint] == 0) {
154 /* First enable the CPU interrupt. */
155 int rval =
156 request_irq (IRQ_GINT(gint), gbus_int_handle_irq,
157 SA_INTERRUPT,
158 "gbus_int_handler",
159 &gint_num_active_irqs[gint]);
160 if (rval != 0)
161 return rval;
162 }
163
164 gint_num_active_irqs[gint]++;
165
166 gbus_int_clear_pending_irq (irq);
167 gbus_int_enable_irq (irq);
168
169 return 0;
170}
171
172static void gbus_int_shutdown_irq (unsigned irq)
173{
174 unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ];
175
176 gbus_int_disable_irq (irq);
177
178 if (--gint_num_active_irqs[gint] == 0)
179 /* Disable the CPU interrupt. */
180 free_irq (IRQ_GINT(gint), &gint_num_active_irqs[gint]);
181}
182
183/* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array
184 INITS (which is terminated by an entry with the name field == 0). */
185void __init gbus_int_init_irq_types (struct gbus_int_irq_init *inits,
186 struct hw_interrupt_type *hw_irq_types)
187{
188 struct gbus_int_irq_init *init;
189 for (init = inits; init->name; init++) {
190 unsigned i;
191 struct hw_interrupt_type *hwit = hw_irq_types++;
192
193 hwit->typename = init->name;
194
195 hwit->startup = gbus_int_startup_irq;
196 hwit->shutdown = gbus_int_shutdown_irq;
197 hwit->enable = gbus_int_enable_irq;
198 hwit->disable = gbus_int_disable_irq;
199 hwit->ack = irq_nop;
200 hwit->end = irq_nop;
201
202 /* Initialize kernel IRQ infrastructure for this interrupt. */
203 init_irq_handlers(init->base, init->num, init->interval, hwit);
204
205 /* Set the interrupt priorities. */
206 for (i = 0; i < init->num; i++) {
207 unsigned j;
208 for (j = 0; j < NUM_USED_GINTS; j++)
209 if (used_gint[j].priority > init->priority)
210 break;
211 /* Wherever we stopped looking is one past the
212 GINT we want. */
213 gbus_int_gint[init->base + i * init->interval
214 - GBUS_INT_BASE_IRQ]
215 = used_gint[j > 0 ? j - 1 : 0].gint;
216 }
217 }
218}
219
220
221/* Initialize IRQS. */
222
223/* Chip interrupts (GINTn) shared among GBUS interrupts. */
224static struct hw_interrupt_type gint_hw_itypes[NUM_USED_GINTS];
225
226
227/* GBUS interrupts themselves. */
228
229struct gbus_int_irq_init gbus_irq_inits[] __initdata = {
230 /* First set defaults. */
231 { "GBUS_INT", IRQ_GBUS_INT(0), IRQ_GBUS_INT_NUM, 1, 6},
232 { 0 }
233};
234#define NUM_GBUS_IRQ_INITS \
235 ((sizeof gbus_irq_inits / sizeof gbus_irq_inits[0]) - 1)
236
237static struct hw_interrupt_type gbus_hw_itypes[NUM_GBUS_IRQ_INITS];
238
239
240/* Initialize GBUS interrupts. */
241void __init gbus_int_init_irqs (void)
242{
243 unsigned i;
244
245 /* First initialize the shared gint interrupts. */
246 for (i = 0; i < NUM_USED_GINTS; i++) {
247 unsigned gint = used_gint[i].gint;
248 struct v850e_intc_irq_init gint_irq_init[2];
249
250 /* We initialize one GINT interrupt at a time. */
251 gint_irq_init[0].name = "GINT";
252 gint_irq_init[0].base = IRQ_GINT (gint);
253 gint_irq_init[0].num = 1;
254 gint_irq_init[0].interval = 1;
255 gint_irq_init[0].priority = used_gint[i].priority;
256
257 gint_irq_init[1].name = 0; /* Terminate the vector. */
258
259 v850e_intc_init_irq_types (gint_irq_init, gint_hw_itypes);
260 }
261
262 /* Then the GBUS interrupts. */
263 gbus_int_disable_irqs ();
264 gbus_int_init_irq_types (gbus_irq_inits, gbus_hw_itypes);
265 /* Turn on the `all enable' bits, which are ANDed with
266 individual interrupt enable bits; we only want to bother with
267 the latter. They are the first bit in the first word of each
268 interrupt-enable area. */
269 for (i = 0; i < NUM_USED_GINTS; i++)
270 GBUS_INT_ENABLE (0, used_gint[i].gint) = 0x1;
271}
diff --git a/arch/v850/kernel/head.S b/arch/v850/kernel/head.S
new file mode 100644
index 000000000000..c490b937ef14
--- /dev/null
+++ b/arch/v850/kernel/head.S
@@ -0,0 +1,128 @@
1/*
2 * arch/v850/kernel/head.S -- Lowest-level startup code
3 *
4 * Copyright (C) 2001,02,03 NEC Electronics Corporation
5 * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14#include <asm/clinkage.h>
15#include <asm/current.h>
16#include <asm/entry.h>
17#include <asm/thread_info.h>
18#include <asm/irq.h>
19
20
21/* Make a slightly more convenient alias for C_SYMBOL_NAME. */
22#define CSYM C_SYMBOL_NAME
23
24
25 .text
26
27 // Define `mach_early_init' as a weak symbol
28 .global CSYM(mach_early_init)
29 .weak CSYM(mach_early_init)
30
31C_ENTRY(start):
32 // Make sure interrupts are turned off, just in case
33 di
34
35#ifdef CONFIG_RESET_GUARD
36 // See if we got here via an unexpected reset
37 ld.w RESET_GUARD, r19 // Check current value of reset guard
38 mov RESET_GUARD_ACTIVE, r20
39 cmp r19, r20
40 bne 1f // Guard was not active
41
42 // If we get here, the reset guard was active. Load up some
43 // interesting values as arguments, and jump to the handler.
44 st.w r0, RESET_GUARD // Allow further resets to succeed
45 mov lp, r6 // Arg 0: return address
46 ld.b KM, r7 // Arg 1: kernel mode
47 mov sp, r9 // Arg 3: stack pointer
48 ld.w KSP, r19 // maybe switch to kernel stack
49 cmp r7, r0 // see if already in kernel mode
50 cmov z, r19, sp, sp // and switch to kernel stack if not
51 GET_CURRENT_TASK(r8) // Arg 2: task pointer
52 jr CSYM(unexpected_reset)
53
541: st.w r20, RESET_GUARD // Turn on reset guard
55#endif /* CONFIG_RESET_GUARD */
56
57 // Setup a temporary stack for doing pre-initialization function calls.
58 //
59 // We can't use the initial kernel stack, because (1) it may be
60 // located in memory we're not allowed to touch, and (2) since
61 // it's in the data segment, calling memcpy to initialize that
62 // area from ROM will overwrite memcpy's return address.
63 mov hilo(CSYM(_init_stack_end) - 4), sp
64
65 // See if there's a platform-specific early-initialization routine
66 // defined; it's a weak symbol, so it will have an address of zero if
67 // there's not.
68 mov hilo(CSYM(mach_early_init)), r6
69 cmp r6, r0
70 bz 3f
71
72 // There is one, so call it. If this function is written in C, it
73 // should be very careful -- the stack pointer is valid, but very
74 // little else is (e.g., bss is not zeroed yet, and initialized data
75 // hasn't been).
76 jarl 2f, lp // first figure out return address
772: add 3f - ., lp
78 jmp [r6] // do call
793:
80
81#ifdef CONFIG_ROM_KERNEL
82 // Copy the data area from ROM to RAM
83 mov hilo(CSYM(_rom_copy_dst_start)), r6
84 mov hilo(CSYM(_rom_copy_src_start)), r7
85 mov hilo(CSYM(_rom_copy_dst_end)), r8
86 sub r6, r8
87 jarl CSYM(memcpy), lp
88#endif
89
90 // Load the initial thread's stack, and current task pointer (in r16)
91 mov hilo(CSYM(init_thread_union)), r19
92 movea THREAD_SIZE, r19, sp
93 ld.w TI_TASK[r19], CURRENT_TASK
94
95#ifdef CONFIG_TIME_BOOTUP
96 /* This stuff must come after mach_early_init, because interrupts may
97 not work until after its been called. */
98 jarl CSYM(highres_timer_reset), lp
99 jarl CSYM(highres_timer_start), lp
100#endif
101
102 // Kernel stack pointer save location
103 st.w sp, KSP
104
105 // Assert that we're in `kernel mode'
106 mov 1, r19
107 st.w r19, KM
108
109#ifdef CONFIG_ZERO_BSS
110 // Zero bss area, since we can't rely upon any loader to do so
111 mov hilo(CSYM(_sbss)), r6
112 mov r0, r7
113 mov hilo(CSYM(_ebss)), r8
114 sub r6, r8
115 jarl CSYM(memset), lp
116#endif
117
118 // What happens if the main kernel function returns (it shouldn't)
119 mov hilo(CSYM(machine_halt)), lp
120
121 // Start the linux kernel. We use an indirect jump to get extra
122 // range, because on some platforms this initial startup code
123 // (and the associated platform-specific code in mach_early_init)
124 // are located far away from the main kernel, e.g. so that they
125 // can initialize RAM first and copy the kernel or something.
126 mov hilo(CSYM(start_kernel)), r12
127 jmp [r12]
128C_END(start)
diff --git a/arch/v850/kernel/highres_timer.c b/arch/v850/kernel/highres_timer.c
new file mode 100644
index 000000000000..b16ad1eaf966
--- /dev/null
+++ b/arch/v850/kernel/highres_timer.c
@@ -0,0 +1,132 @@
1/*
2 * arch/v850/kernel/highres_timer.c -- High resolution timing routines
3 *
4 * Copyright (C) 2001,02,03 NEC Electronics Corporation
5 * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14#include <asm/system.h>
15#include <asm/v850e_timer_d.h>
16#include <asm/highres_timer.h>
17
18#define HIGHRES_TIMER_USEC_SHIFT 12
19
20/* Pre-calculated constant used for converting ticks to real time
21 units. We initialize it to prevent it being put into BSS. */
22static u32 highres_timer_usec_prescale = 1;
23
24void highres_timer_slow_tick_irq (void) __attribute__ ((noreturn));
25void highres_timer_slow_tick_irq (void)
26{
27 /* This is an interrupt handler, so it must be very careful to
28 not to trash any registers. At this point, the stack-pointer
29 (r3) has been saved in the chip ram location ENTRY_SP by the
30 interrupt vector, so we can use it as a scratch register; we
31 must also restore it before returning. */
32 asm ("ld.w %0[r0], sp;"
33 "add 1, sp;"
34 "st.w sp, %0[r0];"
35 "ld.w %1[r0], sp;" /* restore pre-irq stack-pointer */
36 "reti"
37 ::
38 "i" (HIGHRES_TIMER_SLOW_TICKS_ADDR),
39 "i" (ENTRY_SP_ADDR)
40 : "memory");
41}
42
43void highres_timer_reset (void)
44{
45 V850E_TIMER_D_TMD (HIGHRES_TIMER_TIMER_D_UNIT) = 0;
46 HIGHRES_TIMER_SLOW_TICKS = 0;
47}
48
49void highres_timer_start (void)
50{
51 u32 fast_tick_rate;
52
53 /* Start hardware timer. */
54 v850e_timer_d_configure (HIGHRES_TIMER_TIMER_D_UNIT,
55 HIGHRES_TIMER_SLOW_TICK_RATE);
56
57 fast_tick_rate =
58 (V850E_TIMER_D_BASE_FREQ
59 >> V850E_TIMER_D_DIVLOG2 (HIGHRES_TIMER_TIMER_D_UNIT));
60
61 /* The obvious way of calculating microseconds from fast ticks
62 is to do:
63
64 usec = fast_ticks * 10^6 / fast_tick_rate
65
66 However, divisions are much slower than multiplications, and
67 the above calculation can overflow, so we do this instead:
68
69 usec = fast_ticks * (10^6 * 2^12 / fast_tick_rate) / 2^12
70
71 since we can pre-calculate (10^6 * (2^12 / fast_tick_rate))
72 and use a shift for dividing by 2^12, this avoids division,
73 and is almost as accurate (it differs by about 2 microseconds
74 at the extreme value of the fast-tick counter's ranger). */
75 highres_timer_usec_prescale = ((1000000 << HIGHRES_TIMER_USEC_SHIFT)
76 / fast_tick_rate);
77
78 /* Enable the interrupt (which is hardwired to this use), and
79 give it the highest priority. */
80 V850E_INTC_IC (IRQ_INTCMD (HIGHRES_TIMER_TIMER_D_UNIT)) = 0;
81}
82
83void highres_timer_stop (void)
84{
85 /* Stop the timer. */
86 V850E_TIMER_D_TMCD (HIGHRES_TIMER_TIMER_D_UNIT) =
87 V850E_TIMER_D_TMCD_CAE;
88 /* Disable its interrupt, just in case. */
89 v850e_intc_disable_irq (IRQ_INTCMD (HIGHRES_TIMER_TIMER_D_UNIT));
90}
91
92inline void highres_timer_read_ticks (u32 *slow_ticks, u32 *fast_ticks)
93{
94 int flags;
95 u32 fast_ticks_1, fast_ticks_2, _slow_ticks;
96
97 local_irq_save (flags);
98 fast_ticks_1 = V850E_TIMER_D_TMD (HIGHRES_TIMER_TIMER_D_UNIT);
99 _slow_ticks = HIGHRES_TIMER_SLOW_TICKS;
100 fast_ticks_2 = V850E_TIMER_D_TMD (HIGHRES_TIMER_TIMER_D_UNIT);
101 local_irq_restore (flags);
102
103 if (fast_ticks_2 < fast_ticks_1)
104 _slow_ticks++;
105
106 *slow_ticks = _slow_ticks;
107 *fast_ticks = fast_ticks_2;
108}
109
110inline void highres_timer_ticks_to_timeval (u32 slow_ticks, u32 fast_ticks,
111 struct timeval *tv)
112{
113 unsigned long sec, sec_rem, usec;
114
115 usec = ((fast_ticks * highres_timer_usec_prescale)
116 >> HIGHRES_TIMER_USEC_SHIFT);
117
118 sec = slow_ticks / HIGHRES_TIMER_SLOW_TICK_RATE;
119 sec_rem = slow_ticks % HIGHRES_TIMER_SLOW_TICK_RATE;
120
121 usec += sec_rem * (1000000 / HIGHRES_TIMER_SLOW_TICK_RATE);
122
123 tv->tv_sec = sec;
124 tv->tv_usec = usec;
125}
126
127void highres_timer_read (struct timeval *tv)
128{
129 u32 fast_ticks, slow_ticks;
130 highres_timer_read_ticks (&slow_ticks, &fast_ticks);
131 highres_timer_ticks_to_timeval (slow_ticks, fast_ticks, tv);
132}
diff --git a/arch/v850/kernel/init_task.c b/arch/v850/kernel/init_task.c
new file mode 100644
index 000000000000..ed2f93cf7c66
--- /dev/null
+++ b/arch/v850/kernel/init_task.c
@@ -0,0 +1,49 @@
1/*
2 * arch/v850/kernel/init_task.c -- Initial task/thread structures
3 *
4 * Copyright (C) 2002,03 NEC Electronics Corporation
5 * Copyright (C) 2002,03 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 */
11
12#include <linux/mm.h>
13#include <linux/module.h>
14#include <linux/sched.h>
15#include <linux/init.h>
16#include <linux/init_task.h>
17#include <linux/fs.h>
18#include <linux/mqueue.h>
19
20#include <asm/uaccess.h>
21#include <asm/pgtable.h>
22
23static struct fs_struct init_fs = INIT_FS;
24static struct files_struct init_files = INIT_FILES;
25static struct signal_struct init_signals = INIT_SIGNALS (init_signals);
26static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
27struct mm_struct init_mm = INIT_MM (init_mm);
28
29EXPORT_SYMBOL(init_mm);
30
31/*
32 * Initial task structure.
33 *
34 * All other task structs will be allocated on slabs in fork.c
35 */
36struct task_struct init_task = INIT_TASK (init_task);
37
38EXPORT_SYMBOL(init_task);
39
40/*
41 * Initial thread structure.
42 *
43 * We need to make sure that this is 8192-byte aligned due to the
44 * way process stacks are handled. This is done by having a special
45 * "init_task" linker map entry.
46 */
47union thread_union init_thread_union
48 __attribute__((__section__(".data.init_task"))) =
49 { INIT_THREAD_INFO(init_task) };
diff --git a/arch/v850/kernel/intv.S b/arch/v850/kernel/intv.S
new file mode 100644
index 000000000000..671e4c6150dd
--- /dev/null
+++ b/arch/v850/kernel/intv.S
@@ -0,0 +1,87 @@
1/*
2 * arch/v850/kernel/intv.S -- Interrupt vectors
3 *
4 * Copyright (C) 2001,02,03 NEC Electronics Corporation
5 * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14#include <asm/clinkage.h>
15#include <asm/irq.h>
16#include <asm/machdep.h>
17#include <asm/entry.h>
18
19#ifdef CONFIG_V850E_HIGHRES_TIMER
20#include <asm/highres_timer.h>
21#endif
22
23/* Jump to an interrupt/trap handler. These handlers (defined in entry.S)
24 expect the stack-pointer to be saved in ENTRY_SP, so we use sp to do an
25 indirect jump (which avoids problems when the handler is more than a signed
26 22-bit offset away). */
27#define JUMP_TO_HANDLER(name, sp_save_loc) \
28 st.w sp, sp_save_loc; \
29 mov hilo(name), sp; \
30 jmp [sp]
31
32
33 /* Reset vector. */
34 .section .intv.reset, "ax"
35 .org 0x0
36 mov hilo(C_SYMBOL_NAME(start)), r1;
37 jmp [r1]
38
39
40 /* Generic interrupt vectors. */
41 .section .intv.common, "ax"
42 .balign 0x10
43 JUMP_TO_HANDLER (nmi, NMI_ENTRY_SP) // 0x10 - NMI0
44 .balign 0x10
45 JUMP_TO_HANDLER (nmi, NMI_ENTRY_SP) // 0x20 - NMI1
46 .balign 0x10
47 JUMP_TO_HANDLER (nmi, NMI_ENTRY_SP) // 0x30 - NMI2
48
49 .balign 0x10
50 JUMP_TO_HANDLER (trap, ENTRY_SP) // 0x40 - TRAP0n
51 .balign 0x10
52 JUMP_TO_HANDLER (trap, ENTRY_SP) // 0x50 - TRAP1n
53
54 .balign 0x10
55 JUMP_TO_HANDLER (dbtrap, ENTRY_SP) // 0x60 - Illegal op / DBTRAP insn
56
57
58 /* Hardware interrupt vectors. */
59 .section .intv.mach, "ax"
60 .org 0x0
61
62#if defined (CONFIG_V850E_HIGHRES_TIMER) && defined (IRQ_INTCMD)
63
64 /* Interrupts before the highres timer interrupt. */
65 .rept IRQ_INTCMD (HIGHRES_TIMER_TIMER_D_UNIT)
66 .balign 0x10
67 JUMP_TO_HANDLER (irq, ENTRY_SP)
68 .endr
69
70 /* The highres timer interrupt. */
71 .balign 0x10
72 JUMP_TO_HANDLER (C_SYMBOL_NAME (highres_timer_slow_tick_irq), ENTRY_SP)
73
74 /* Interrupts after the highres timer interrupt. */
75 .rept NUM_CPU_IRQS - IRQ_INTCMD (HIGHRES_TIMER_TIMER_D_UNIT) - 1
76 .balign 0x10
77 JUMP_TO_HANDLER (irq, ENTRY_SP)
78 .endr
79
80#else /* No highres timer */
81
82 .rept NUM_CPU_IRQS
83 .balign 0x10
84 JUMP_TO_HANDLER (irq, ENTRY_SP)
85 .endr
86
87#endif /* Highres timer */
diff --git a/arch/v850/kernel/irq.c b/arch/v850/kernel/irq.c
new file mode 100644
index 000000000000..336cbf21dc8f
--- /dev/null
+++ b/arch/v850/kernel/irq.c
@@ -0,0 +1,744 @@
1/*
2 * arch/v850/kernel/irq.c -- High-level interrupt handling
3 *
4 * Copyright (C) 2001,02,03,04 NEC Electronics Corporation
5 * Copyright (C) 2001,02,03,04 Miles Bader <miles@gnu.org>
6 * Copyright (C) 1994-2000 Ralf Baechle
7 * Copyright (C) 1992 Linus Torvalds
8 *
9 * This file is subject to the terms and conditions of the GNU General
10 * Public License. See the file COPYING in the main directory of this
11 * archive for more details.
12 *
13 * This file was was derived from the mips version, arch/mips/kernel/irq.c
14 */
15
16#include <linux/kernel.h>
17#include <linux/module.h>
18#include <linux/irq.h>
19#include <linux/init.h>
20#include <linux/interrupt.h>
21#include <linux/kernel_stat.h>
22#include <linux/slab.h>
23#include <linux/mm.h>
24#include <linux/random.h>
25#include <linux/seq_file.h>
26
27#include <asm/system.h>
28
29/*
30 * Controller mappings for all interrupt sources:
31 */
32irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = {
33 [0 ... NR_IRQS-1] = {
34 .handler = &no_irq_type,
35 .lock = SPIN_LOCK_UNLOCKED
36 }
37};
38
39/*
40 * Special irq handlers.
41 */
42
43irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs)
44{
45 return IRQ_NONE;
46}
47
48/*
49 * Generic no controller code
50 */
51
52static void enable_none(unsigned int irq) { }
53static unsigned int startup_none(unsigned int irq) { return 0; }
54static void disable_none(unsigned int irq) { }
55static void ack_none(unsigned int irq)
56{
57 /*
58 * 'what should we do if we get a hw irq event on an illegal vector'.
59 * each architecture has to answer this themselves, it doesn't deserve
60 * a generic callback i think.
61 */
62 printk("received IRQ %d with unknown interrupt type\n", irq);
63}
64
65/* startup is the same as "enable", shutdown is same as "disable" */
66#define shutdown_none disable_none
67#define end_none enable_none
68
69struct hw_interrupt_type no_irq_type = {
70 "none",
71 startup_none,
72 shutdown_none,
73 enable_none,
74 disable_none,
75 ack_none,
76 end_none
77};
78
79volatile unsigned long irq_err_count, spurious_count;
80
81/*
82 * Generic, controller-independent functions:
83 */
84
85int show_interrupts(struct seq_file *p, void *v)
86{
87 int i = *(loff_t *) v;
88 struct irqaction * action;
89 unsigned long flags;
90
91 if (i == 0) {
92 seq_puts(p, " ");
93 for (i=0; i < 1 /*smp_num_cpus*/; i++)
94 seq_printf(p, "CPU%d ", i);
95 seq_putc(p, '\n');
96 }
97
98 if (i < NR_IRQS) {
99 int j, count, num;
100 const char *type_name = irq_desc[i].handler->typename;
101 spin_lock_irqsave(&irq_desc[j].lock, flags);
102 action = irq_desc[i].action;
103 if (!action)
104 goto skip;
105
106 count = 0;
107 num = -1;
108 for (j = 0; j < NR_IRQS; j++)
109 if (irq_desc[j].handler->typename == type_name) {
110 if (i == j)
111 num = count;
112 count++;
113 }
114
115 seq_printf(p, "%3d: ",i);
116 seq_printf(p, "%10u ", kstat_irqs(i));
117 if (count > 1) {
118 int prec = (num >= 100 ? 3 : num >= 10 ? 2 : 1);
119 seq_printf(p, " %*s%d", 14 - prec, type_name, num);
120 } else
121 seq_printf(p, " %14s", type_name);
122
123 seq_printf(p, " %s", action->name);
124 for (action=action->next; action; action = action->next)
125 seq_printf(p, ", %s", action->name);
126 seq_putc(p, '\n');
127skip:
128 spin_unlock_irqrestore(&irq_desc[j].lock, flags);
129 } else if (i == NR_IRQS)
130 seq_printf(p, "ERR: %10lu\n", irq_err_count);
131 return 0;
132}
133
134/*
135 * This should really return information about whether
136 * we should do bottom half handling etc. Right now we
137 * end up _always_ checking the bottom half, which is a
138 * waste of time and is not what some drivers would
139 * prefer.
140 */
141int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
142{
143 int status = 1; /* Force the "do bottom halves" bit */
144 int ret;
145
146 if (!(action->flags & SA_INTERRUPT))
147 local_irq_enable();
148
149 do {
150 ret = action->handler(irq, action->dev_id, regs);
151 if (ret == IRQ_HANDLED)
152 status |= action->flags;
153 action = action->next;
154 } while (action);
155 if (status & SA_SAMPLE_RANDOM)
156 add_interrupt_randomness(irq);
157 local_irq_disable();
158
159 return status;
160}
161
162/*
163 * Generic enable/disable code: this just calls
164 * down into the PIC-specific version for the actual
165 * hardware disable after having gotten the irq
166 * controller lock.
167 */
168
169/**
170 * disable_irq_nosync - disable an irq without waiting
171 * @irq: Interrupt to disable
172 *
173 * Disable the selected interrupt line. Disables of an interrupt
174 * stack. Unlike disable_irq(), this function does not ensure existing
175 * instances of the IRQ handler have completed before returning.
176 *
177 * This function may be called from IRQ context.
178 */
179
180void inline disable_irq_nosync(unsigned int irq)
181{
182 irq_desc_t *desc = irq_desc + irq;
183 unsigned long flags;
184
185 spin_lock_irqsave(&desc->lock, flags);
186 if (!desc->depth++) {
187 desc->status |= IRQ_DISABLED;
188 desc->handler->disable(irq);
189 }
190 spin_unlock_irqrestore(&desc->lock, flags);
191}
192
193/**
194 * disable_irq - disable an irq and wait for completion
195 * @irq: Interrupt to disable
196 *
197 * Disable the selected interrupt line. Disables of an interrupt
198 * stack. That is for two disables you need two enables. This
199 * function waits for any pending IRQ handlers for this interrupt
200 * to complete before returning. If you use this function while
201 * holding a resource the IRQ handler may need you will deadlock.
202 *
203 * This function may be called - with care - from IRQ context.
204 */
205
206void disable_irq(unsigned int irq)
207{
208 disable_irq_nosync(irq);
209 synchronize_irq(irq);
210}
211
212/**
213 * enable_irq - enable interrupt handling on an irq
214 * @irq: Interrupt to enable
215 *
216 * Re-enables the processing of interrupts on this IRQ line
217 * providing no disable_irq calls are now in effect.
218 *
219 * This function may be called from IRQ context.
220 */
221
222void enable_irq(unsigned int irq)
223{
224 irq_desc_t *desc = irq_desc + irq;
225 unsigned long flags;
226
227 spin_lock_irqsave(&desc->lock, flags);
228 switch (desc->depth) {
229 case 1: {
230 unsigned int status = desc->status & ~IRQ_DISABLED;
231 desc->status = status;
232 if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
233 desc->status = status | IRQ_REPLAY;
234 hw_resend_irq(desc->handler,irq);
235 }
236 desc->handler->enable(irq);
237 /* fall-through */
238 }
239 default:
240 desc->depth--;
241 break;
242 case 0:
243 printk("enable_irq(%u) unbalanced from %p\n", irq,
244 __builtin_return_address(0));
245 }
246 spin_unlock_irqrestore(&desc->lock, flags);
247}
248
249/* Handle interrupt IRQ. REGS are the registers at the time of ther
250 interrupt. */
251unsigned int handle_irq (int irq, struct pt_regs *regs)
252{
253 /*
254 * We ack quickly, we don't want the irq controller
255 * thinking we're snobs just because some other CPU has
256 * disabled global interrupts (we have already done the
257 * INT_ACK cycles, it's too late to try to pretend to the
258 * controller that we aren't taking the interrupt).
259 *
260 * 0 return value means that this irq is already being
261 * handled by some other CPU. (or is disabled)
262 */
263 int cpu = smp_processor_id();
264 irq_desc_t *desc = irq_desc + irq;
265 struct irqaction * action;
266 unsigned int status;
267
268 irq_enter();
269 kstat_cpu(cpu).irqs[irq]++;
270 spin_lock(&desc->lock);
271 desc->handler->ack(irq);
272 /*
273 REPLAY is when Linux resends an IRQ that was dropped earlier
274 WAITING is used by probe to mark irqs that are being tested
275 */
276 status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
277 status |= IRQ_PENDING; /* we _want_ to handle it */
278
279 /*
280 * If the IRQ is disabled for whatever reason, we cannot
281 * use the action we have.
282 */
283 action = NULL;
284 if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) {
285 action = desc->action;
286 status &= ~IRQ_PENDING; /* we commit to handling */
287 status |= IRQ_INPROGRESS; /* we are handling it */
288 }
289 desc->status = status;
290
291 /*
292 * If there is no IRQ handler or it was disabled, exit early.
293 Since we set PENDING, if another processor is handling
294 a different instance of this same irq, the other processor
295 will take care of it.
296 */
297 if (unlikely(!action))
298 goto out;
299
300 /*
301 * Edge triggered interrupts need to remember
302 * pending events.
303 * This applies to any hw interrupts that allow a second
304 * instance of the same irq to arrive while we are in handle_irq
305 * or in the handler. But the code here only handles the _second_
306 * instance of the irq, not the third or fourth. So it is mostly
307 * useful for irq hardware that does not mask cleanly in an
308 * SMP environment.
309 */
310 for (;;) {
311 spin_unlock(&desc->lock);
312 handle_IRQ_event(irq, regs, action);
313 spin_lock(&desc->lock);
314
315 if (likely(!(desc->status & IRQ_PENDING)))
316 break;
317 desc->status &= ~IRQ_PENDING;
318 }
319 desc->status &= ~IRQ_INPROGRESS;
320
321out:
322 /*
323 * The ->end() handler has to deal with interrupts which got
324 * disabled while the handler was running.
325 */
326 desc->handler->end(irq);
327 spin_unlock(&desc->lock);
328
329 irq_exit();
330
331 return 1;
332}
333
334/**
335 * request_irq - allocate an interrupt line
336 * @irq: Interrupt line to allocate
337 * @handler: Function to be called when the IRQ occurs
338 * @irqflags: Interrupt type flags
339 * @devname: An ascii name for the claiming device
340 * @dev_id: A cookie passed back to the handler function
341 *
342 * This call allocates interrupt resources and enables the
343 * interrupt line and IRQ handling. From the point this
344 * call is made your handler function may be invoked. Since
345 * your handler function must clear any interrupt the board
346 * raises, you must take care both to initialise your hardware
347 * and to set up the interrupt handler in the right order.
348 *
349 * Dev_id must be globally unique. Normally the address of the
350 * device data structure is used as the cookie. Since the handler
351 * receives this value it makes sense to use it.
352 *
353 * If your interrupt is shared you must pass a non NULL dev_id
354 * as this is required when freeing the interrupt.
355 *
356 * Flags:
357 *
358 * SA_SHIRQ Interrupt is shared
359 *
360 * SA_INTERRUPT Disable local interrupts while processing
361 *
362 * SA_SAMPLE_RANDOM The interrupt can be used for entropy
363 *
364 */
365
366int request_irq(unsigned int irq,
367 irqreturn_t (*handler)(int, void *, struct pt_regs *),
368 unsigned long irqflags,
369 const char * devname,
370 void *dev_id)
371{
372 int retval;
373 struct irqaction * action;
374
375#if 1
376 /*
377 * Sanity-check: shared interrupts should REALLY pass in
378 * a real dev-ID, otherwise we'll have trouble later trying
379 * to figure out which interrupt is which (messes up the
380 * interrupt freeing logic etc).
381 */
382 if (irqflags & SA_SHIRQ) {
383 if (!dev_id)
384 printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n", devname, (&irq)[-1]);
385 }
386#endif
387
388 if (irq >= NR_IRQS)
389 return -EINVAL;
390 if (!handler)
391 return -EINVAL;
392
393 action = (struct irqaction *)
394 kmalloc(sizeof(struct irqaction), GFP_KERNEL);
395 if (!action)
396 return -ENOMEM;
397
398 action->handler = handler;
399 action->flags = irqflags;
400 cpus_clear(action->mask);
401 action->name = devname;
402 action->next = NULL;
403 action->dev_id = dev_id;
404
405 retval = setup_irq(irq, action);
406 if (retval)
407 kfree(action);
408 return retval;
409}
410
411EXPORT_SYMBOL(request_irq);
412
413/**
414 * free_irq - free an interrupt
415 * @irq: Interrupt line to free
416 * @dev_id: Device identity to free
417 *
418 * Remove an interrupt handler. The handler is removed and if the
419 * interrupt line is no longer in use by any driver it is disabled.
420 * On a shared IRQ the caller must ensure the interrupt is disabled
421 * on the card it drives before calling this function. The function
422 * does not return until any executing interrupts for this IRQ
423 * have completed.
424 *
425 * This function may be called from interrupt context.
426 *
427 * Bugs: Attempting to free an irq in a handler for the same irq hangs
428 * the machine.
429 */
430
431void free_irq(unsigned int irq, void *dev_id)
432{
433 irq_desc_t *desc;
434 struct irqaction **p;
435 unsigned long flags;
436
437 if (irq >= NR_IRQS)
438 return;
439
440 desc = irq_desc + irq;
441 spin_lock_irqsave(&desc->lock,flags);
442 p = &desc->action;
443 for (;;) {
444 struct irqaction * action = *p;
445 if (action) {
446 struct irqaction **pp = p;
447 p = &action->next;
448 if (action->dev_id != dev_id)
449 continue;
450
451 /* Found it - now remove it from the list of entries */
452 *pp = action->next;
453 if (!desc->action) {
454 desc->status |= IRQ_DISABLED;
455 desc->handler->shutdown(irq);
456 }
457 spin_unlock_irqrestore(&desc->lock,flags);
458
459 synchronize_irq(irq);
460 kfree(action);
461 return;
462 }
463 printk("Trying to free free IRQ%d\n",irq);
464 spin_unlock_irqrestore(&desc->lock,flags);
465 return;
466 }
467}
468
469EXPORT_SYMBOL(free_irq);
470
471/*
472 * IRQ autodetection code..
473 *
474 * This depends on the fact that any interrupt that
475 * comes in on to an unassigned handler will get stuck
476 * with "IRQ_WAITING" cleared and the interrupt
477 * disabled.
478 */
479
480static DECLARE_MUTEX(probe_sem);
481
482/**
483 * probe_irq_on - begin an interrupt autodetect
484 *
485 * Commence probing for an interrupt. The interrupts are scanned
486 * and a mask of potential interrupt lines is returned.
487 *
488 */
489
490unsigned long probe_irq_on(void)
491{
492 unsigned int i;
493 irq_desc_t *desc;
494 unsigned long val;
495 unsigned long delay;
496
497 down(&probe_sem);
498 /*
499 * something may have generated an irq long ago and we want to
500 * flush such a longstanding irq before considering it as spurious.
501 */
502 for (i = NR_IRQS-1; i > 0; i--) {
503 desc = irq_desc + i;
504
505 spin_lock_irq(&desc->lock);
506 if (!irq_desc[i].action)
507 irq_desc[i].handler->startup(i);
508 spin_unlock_irq(&desc->lock);
509 }
510
511 /* Wait for longstanding interrupts to trigger. */
512 for (delay = jiffies + HZ/50; time_after(delay, jiffies); )
513 /* about 20ms delay */ barrier();
514
515 /*
516 * enable any unassigned irqs
517 * (we must startup again here because if a longstanding irq
518 * happened in the previous stage, it may have masked itself)
519 */
520 for (i = NR_IRQS-1; i > 0; i--) {
521 desc = irq_desc + i;
522
523 spin_lock_irq(&desc->lock);
524 if (!desc->action) {
525 desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
526 if (desc->handler->startup(i))
527 desc->status |= IRQ_PENDING;
528 }
529 spin_unlock_irq(&desc->lock);
530 }
531
532 /*
533 * Wait for spurious interrupts to trigger
534 */
535 for (delay = jiffies + HZ/10; time_after(delay, jiffies); )
536 /* about 100ms delay */ barrier();
537
538 /*
539 * Now filter out any obviously spurious interrupts
540 */
541 val = 0;
542 for (i = 0; i < NR_IRQS; i++) {
543 irq_desc_t *desc = irq_desc + i;
544 unsigned int status;
545
546 spin_lock_irq(&desc->lock);
547 status = desc->status;
548
549 if (status & IRQ_AUTODETECT) {
550 /* It triggered already - consider it spurious. */
551 if (!(status & IRQ_WAITING)) {
552 desc->status = status & ~IRQ_AUTODETECT;
553 desc->handler->shutdown(i);
554 } else
555 if (i < 32)
556 val |= 1 << i;
557 }
558 spin_unlock_irq(&desc->lock);
559 }
560
561 return val;
562}
563
564EXPORT_SYMBOL(probe_irq_on);
565
566/*
567 * Return a mask of triggered interrupts (this
568 * can handle only legacy ISA interrupts).
569 */
570
571/**
572 * probe_irq_mask - scan a bitmap of interrupt lines
573 * @val: mask of interrupts to consider
574 *
575 * Scan the ISA bus interrupt lines and return a bitmap of
576 * active interrupts. The interrupt probe logic state is then
577 * returned to its previous value.
578 *
579 * Note: we need to scan all the irq's even though we will
580 * only return ISA irq numbers - just so that we reset them
581 * all to a known state.
582 */
583unsigned int probe_irq_mask(unsigned long val)
584{
585 int i;
586 unsigned int mask;
587
588 mask = 0;
589 for (i = 0; i < NR_IRQS; i++) {
590 irq_desc_t *desc = irq_desc + i;
591 unsigned int status;
592
593 spin_lock_irq(&desc->lock);
594 status = desc->status;
595
596 if (status & IRQ_AUTODETECT) {
597 if (i < 16 && !(status & IRQ_WAITING))
598 mask |= 1 << i;
599
600 desc->status = status & ~IRQ_AUTODETECT;
601 desc->handler->shutdown(i);
602 }
603 spin_unlock_irq(&desc->lock);
604 }
605 up(&probe_sem);
606
607 return mask & val;
608}
609
610/*
611 * Return the one interrupt that triggered (this can
612 * handle any interrupt source).
613 */
614
615/**
616 * probe_irq_off - end an interrupt autodetect
617 * @val: mask of potential interrupts (unused)
618 *
619 * Scans the unused interrupt lines and returns the line which
620 * appears to have triggered the interrupt. If no interrupt was
621 * found then zero is returned. If more than one interrupt is
622 * found then minus the first candidate is returned to indicate
623 * their is doubt.
624 *
625 * The interrupt probe logic state is returned to its previous
626 * value.
627 *
628 * BUGS: When used in a module (which arguably shouldnt happen)
629 * nothing prevents two IRQ probe callers from overlapping. The
630 * results of this are non-optimal.
631 */
632
633int probe_irq_off(unsigned long val)
634{
635 int i, irq_found, nr_irqs;
636
637 nr_irqs = 0;
638 irq_found = 0;
639 for (i = 0; i < NR_IRQS; i++) {
640 irq_desc_t *desc = irq_desc + i;
641 unsigned int status;
642
643 spin_lock_irq(&desc->lock);
644 status = desc->status;
645
646 if (status & IRQ_AUTODETECT) {
647 if (!(status & IRQ_WAITING)) {
648 if (!nr_irqs)
649 irq_found = i;
650 nr_irqs++;
651 }
652 desc->status = status & ~IRQ_AUTODETECT;
653 desc->handler->shutdown(i);
654 }
655 spin_unlock_irq(&desc->lock);
656 }
657 up(&probe_sem);
658
659 if (nr_irqs > 1)
660 irq_found = -irq_found;
661 return irq_found;
662}
663
664EXPORT_SYMBOL(probe_irq_off);
665
666/* this was setup_x86_irq but it seems pretty generic */
667int setup_irq(unsigned int irq, struct irqaction * new)
668{
669 int shared = 0;
670 unsigned long flags;
671 struct irqaction *old, **p;
672 irq_desc_t *desc = irq_desc + irq;
673
674 /*
675 * Some drivers like serial.c use request_irq() heavily,
676 * so we have to be careful not to interfere with a
677 * running system.
678 */
679 if (new->flags & SA_SAMPLE_RANDOM) {
680 /*
681 * This function might sleep, we want to call it first,
682 * outside of the atomic block.
683 * Yes, this might clear the entropy pool if the wrong
684 * driver is attempted to be loaded, without actually
685 * installing a new handler, but is this really a problem,
686 * only the sysadmin is able to do this.
687 */
688 rand_initialize_irq(irq);
689 }
690
691 /*
692 * The following block of code has to be executed atomically
693 */
694 spin_lock_irqsave(&desc->lock,flags);
695 p = &desc->action;
696 if ((old = *p) != NULL) {
697 /* Can't share interrupts unless both agree to */
698 if (!(old->flags & new->flags & SA_SHIRQ)) {
699 spin_unlock_irqrestore(&desc->lock,flags);
700 return -EBUSY;
701 }
702
703 /* add new interrupt at end of irq queue */
704 do {
705 p = &old->next;
706 old = *p;
707 } while (old);
708 shared = 1;
709 }
710
711 *p = new;
712
713 if (!shared) {
714 desc->depth = 0;
715 desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS);
716 desc->handler->startup(irq);
717 }
718 spin_unlock_irqrestore(&desc->lock,flags);
719
720 /* register_irq_proc(irq); */
721 return 0;
722}
723
724/* Initialize irq handling for IRQs.
725 BASE_IRQ, BASE_IRQ+INTERVAL, ..., BASE_IRQ+NUM*INTERVAL
726 to IRQ_TYPE. An IRQ_TYPE of 0 means to use a generic interrupt type. */
727void __init
728init_irq_handlers (int base_irq, int num, int interval,
729 struct hw_interrupt_type *irq_type)
730{
731 while (num-- > 0) {
732 irq_desc[base_irq].status = IRQ_DISABLED;
733 irq_desc[base_irq].action = NULL;
734 irq_desc[base_irq].depth = 1;
735 irq_desc[base_irq].handler = irq_type;
736 base_irq += interval;
737 }
738}
739
740#if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL)
741void init_irq_proc(void)
742{
743}
744#endif /* CONFIG_PROC_FS && CONFIG_SYSCTL */
diff --git a/arch/v850/kernel/ma.c b/arch/v850/kernel/ma.c
new file mode 100644
index 000000000000..b3dfbc5d2f40
--- /dev/null
+++ b/arch/v850/kernel/ma.c
@@ -0,0 +1,70 @@
1/*
2 * arch/v850/kernel/ma.c -- V850E/MA series of cpu chips
3 *
4 * Copyright (C) 2001,02,03 NEC Electronics Corporation
5 * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14#include <linux/config.h>
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <linux/mm.h>
18#include <linux/swap.h>
19#include <linux/bootmem.h>
20#include <linux/irq.h>
21
22#include <asm/atomic.h>
23#include <asm/page.h>
24#include <asm/machdep.h>
25#include <asm/v850e_timer_d.h>
26
27#include "mach.h"
28
29void __init mach_sched_init (struct irqaction *timer_action)
30{
31 /* Start hardware timer. */
32 v850e_timer_d_configure (0, HZ);
33 /* Install timer interrupt handler. */
34 setup_irq (IRQ_INTCMD(0), timer_action);
35}
36
37static struct v850e_intc_irq_init irq_inits[] = {
38 { "IRQ", 0, NUM_MACH_IRQS, 1, 7 },
39 { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 5 },
40 { "DMA", IRQ_INTDMA(0), IRQ_INTDMA_NUM, 1, 2 },
41 { "CSI", IRQ_INTCSI(0), IRQ_INTCSI_NUM, 4, 4 },
42 { "SER", IRQ_INTSER(0), IRQ_INTSER_NUM, 4, 3 },
43 { "SR", IRQ_INTSR(0), IRQ_INTSR_NUM, 4, 4 },
44 { "ST", IRQ_INTST(0), IRQ_INTST_NUM, 4, 5 },
45 { 0 }
46};
47#define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1)
48
49static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
50
51/* Initialize MA chip interrupts. */
52void __init ma_init_irqs (void)
53{
54 v850e_intc_init_irq_types (irq_inits, hw_itypes);
55}
56
57/* Called before configuring an on-chip UART. */
58void ma_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud)
59{
60 /* We only know about the first two UART channels (though
61 specific chips may have more). */
62 if (chan < 2) {
63 unsigned bits = 0x3 << (chan * 3);
64 /* Specify that the relevant pins on the chip should do
65 serial I/O, not direct I/O. */
66 MA_PORT4_PMC |= bits;
67 /* Specify that we're using the UART, not the CSI device. */
68 MA_PORT4_PFC |= bits;
69 }
70}
diff --git a/arch/v850/kernel/mach.c b/arch/v850/kernel/mach.c
new file mode 100644
index 000000000000..b9db278d2b71
--- /dev/null
+++ b/arch/v850/kernel/mach.c
@@ -0,0 +1,17 @@
1/*
2 * arch/v850/kernel/mach.c -- Defaults for some things defined by "mach.h"
3 *
4 * Copyright (C) 2001 NEC Corporation
5 * Copyright (C) 2001 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14#include "mach.h"
15
16/* Called with each timer tick, if non-zero. */
17void (*mach_tick)(void) = 0;
diff --git a/arch/v850/kernel/mach.h b/arch/v850/kernel/mach.h
new file mode 100644
index 000000000000..9e0e4816ec56
--- /dev/null
+++ b/arch/v850/kernel/mach.h
@@ -0,0 +1,56 @@
1/*
2 * arch/v850/kernel/mach.h -- Machine-dependent functions used by v850 port
3 *
4 * Copyright (C) 2001,02,03 NEC Electronics Corporation
5 * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14#ifndef __V850_MACH_H__
15#define __V850_MACH_H__
16
17#include <linux/kernel.h>
18#include <linux/time.h>
19#include <linux/spinlock.h>
20#include <linux/interrupt.h>
21#include <linux/fs.h>
22#include <linux/seq_file.h>
23
24#include <asm/ptrace.h>
25#include <asm/entry.h>
26#include <asm/clinkage.h>
27
28void mach_setup (char **cmdline);
29void mach_gettimeofday (struct timespec *tv);
30void mach_sched_init (struct irqaction *timer_action);
31void mach_get_physical_ram (unsigned long *ram_start, unsigned long *ram_len);
32void mach_init_irqs (void);
33
34/* If defined, is called very early in the kernel initialization. The
35 stack pointer is valid, but very little has been initialized (e.g.,
36 bss is not zeroed yet) when this is called, so care must taken. */
37void mach_early_init (void);
38
39/* If defined, called after the bootmem allocator has been initialized,
40 to allow the platform-dependent code to reserve any areas of RAM that
41 the kernel shouldn't touch. */
42void mach_reserve_bootmem (void) __attribute__ ((__weak__));
43
44/* Called with each timer tick, if non-zero. */
45extern void (*mach_tick) (void);
46
47/* The following establishes aliases for various mach_ functions to the
48 name by which the rest of the kernel calls them. These statements
49 should only have an effect in the file that defines the actual functions. */
50#define MACH_ALIAS(to, from) \
51 asm (".global " macrology_stringify (C_SYMBOL_NAME (to)) ";" \
52 macrology_stringify (C_SYMBOL_NAME (to)) \
53 " = " macrology_stringify (C_SYMBOL_NAME (from)))
54/* e.g.: MACH_ALIAS (kernel_name, arch_spec_name); */
55
56#endif /* __V850_MACH_H__ */
diff --git a/arch/v850/kernel/me2.c b/arch/v850/kernel/me2.c
new file mode 100644
index 000000000000..6527c218f91d
--- /dev/null
+++ b/arch/v850/kernel/me2.c
@@ -0,0 +1,74 @@
1/*
2 * arch/v850/kernel/me2.c -- V850E/ME2 chip-specific support
3 *
4 * Copyright (C) 2003 NEC Corporation
5 * Copyright (C) 2003 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14#include <linux/config.h>
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <linux/mm.h>
18#include <linux/swap.h>
19#include <linux/bootmem.h>
20#include <linux/irq.h>
21
22#include <asm/atomic.h>
23#include <asm/page.h>
24#include <asm/machdep.h>
25#include <asm/v850e_timer_d.h>
26
27#include "mach.h"
28
29void __init mach_sched_init (struct irqaction *timer_action)
30{
31 /* Start hardware timer. */
32 v850e_timer_d_configure (0, HZ);
33 /* Install timer interrupt handler. */
34 setup_irq (IRQ_INTCMD(0), timer_action);
35}
36
37static struct v850e_intc_irq_init irq_inits[] = {
38 { "IRQ", 0, NUM_CPU_IRQS, 1, 7 },
39 { "INTP", IRQ_INTP(0), IRQ_INTP_NUM, 1, 5 },
40 { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 3 },
41 { "UBTIRE", IRQ_INTUBTIRE(0), IRQ_INTUBTIRE_NUM, 5, 4 },
42 { "UBTIR", IRQ_INTUBTIR(0), IRQ_INTUBTIR_NUM, 5, 4 },
43 { "UBTIT", IRQ_INTUBTIT(0), IRQ_INTUBTIT_NUM, 5, 4 },
44 { "UBTIF", IRQ_INTUBTIF(0), IRQ_INTUBTIF_NUM, 5, 4 },
45 { "UBTITO", IRQ_INTUBTITO(0), IRQ_INTUBTITO_NUM, 5, 4 },
46 { 0 }
47};
48#define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1)
49
50static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
51
52/* Initialize V850E/ME2 chip interrupts. */
53void __init me2_init_irqs (void)
54{
55 v850e_intc_init_irq_types (irq_inits, hw_itypes);
56}
57
58/* Called before configuring an on-chip UART. */
59void me2_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud)
60{
61 if (chan == 0) {
62 /* Specify that the relevent pins on the chip should do
63 serial I/O, not direct I/O. */
64 ME2_PORT1_PMC |= 0xC;
65 /* Specify that we're using the UART, not the CSI device. */
66 ME2_PORT1_PFC |= 0xC;
67 } else if (chan == 1) {
68 /* Specify that the relevent pins on the chip should do
69 serial I/O, not direct I/O. */
70 ME2_PORT2_PMC |= 0x6;
71 /* Specify that we're using the UART, not the CSI device. */
72 ME2_PORT2_PFC |= 0x6;
73 }
74}
diff --git a/arch/v850/kernel/memcons.c b/arch/v850/kernel/memcons.c
new file mode 100644
index 000000000000..491614c435cd
--- /dev/null
+++ b/arch/v850/kernel/memcons.c
@@ -0,0 +1,135 @@
1/*
2 * arch/v850/kernel/memcons.c -- Console I/O to a memory buffer
3 *
4 * Copyright (C) 2001,02 NEC Corporation
5 * Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14#include <linux/kernel.h>
15#include <linux/console.h>
16#include <linux/tty.h>
17#include <linux/tty_driver.h>
18#include <linux/init.h>
19
20/* If this device is enabled, the linker map should define start and
21 end points for its buffer. */
22extern char memcons_output[], memcons_output_end;
23
24/* Current offset into the buffer. */
25static unsigned long memcons_offs = 0;
26
27/* Spinlock protecting memcons_offs. */
28static DEFINE_SPINLOCK(memcons_lock);
29
30
31static size_t write (const char *buf, size_t len)
32{
33 int flags;
34 char *point;
35
36 spin_lock_irqsave (memcons_lock, flags);
37
38 point = memcons_output + memcons_offs;
39 if (point + len >= &memcons_output_end) {
40 len = &memcons_output_end - point;
41 memcons_offs = 0;
42 } else
43 memcons_offs += len;
44
45 spin_unlock_irqrestore (memcons_lock, flags);
46
47 memcpy (point, buf, len);
48
49 return len;
50}
51
52
53/* Low-level console. */
54
55static void memcons_write (struct console *co, const char *buf, unsigned len)
56{
57 while (len > 0)
58 len -= write (buf, len);
59}
60
61static struct tty_driver *tty_driver;
62
63static struct tty_driver *memcons_device (struct console *co, int *index)
64{
65 *index = co->index;
66 return tty_driver;
67}
68
69static struct console memcons =
70{
71 .name = "memcons",
72 .write = memcons_write,
73 .device = memcons_device,
74 .flags = CON_PRINTBUFFER,
75 .index = -1,
76};
77
78void memcons_setup (void)
79{
80 register_console (&memcons);
81 printk (KERN_INFO "Console: static memory buffer (memcons)\n");
82}
83
84/* Higher level TTY interface. */
85
86int memcons_tty_open (struct tty_struct *tty, struct file *filp)
87{
88 return 0;
89}
90
91int memcons_tty_write (struct tty_struct *tty, const unsigned char *buf, int len)
92{
93 return write (buf, len);
94}
95
96int memcons_tty_write_room (struct tty_struct *tty)
97{
98 return &memcons_output_end - (memcons_output + memcons_offs);
99}
100
101int memcons_tty_chars_in_buffer (struct tty_struct *tty)
102{
103 /* We have no buffer. */
104 return 0;
105}
106
107static struct tty_operations ops = {
108 .open = memcons_tty_open,
109 .write = memcons_tty_write,
110 .write_room = memcons_tty_write_room,
111 .chars_in_buffer = memcons_tty_chars_in_buffer,
112};
113
114int __init memcons_tty_init (void)
115{
116 int err;
117 struct tty_driver *driver = alloc_tty_driver(1);
118 if (!driver)
119 return -ENOMEM;
120
121 driver->name = "memcons";
122 driver->major = TTY_MAJOR;
123 driver->minor_start = 64;
124 driver->type = TTY_DRIVER_TYPE_SYSCONS;
125 driver->init_termios = tty_std_termios;
126 tty_set_operations(driver, &ops);
127 err = tty_register_driver(driver);
128 if (err) {
129 put_tty_driver(driver);
130 return err;
131 }
132 tty_driver = driver;
133 return 0;
134}
135__initcall (memcons_tty_init);
diff --git a/arch/v850/kernel/module.c b/arch/v850/kernel/module.c
new file mode 100644
index 000000000000..64aeb3e37c52
--- /dev/null
+++ b/arch/v850/kernel/module.c
@@ -0,0 +1,237 @@
1/*
2 * arch/v850/kernel/module.c -- Architecture-specific module functions
3 *
4 * Copyright (C) 2002,03 NEC Electronics Corporation
5 * Copyright (C) 2002,03 Miles Bader <miles@gnu.org>
6 * Copyright (C) 2001,03 Rusty Russell
7 *
8 * This file is subject to the terms and conditions of the GNU General
9 * Public License. See the file COPYING in the main directory of this
10 * archive for more details.
11 *
12 * Written by Miles Bader <miles@gnu.org>
13 *
14 * Derived in part from arch/ppc/kernel/module.c
15 */
16
17#include <linux/kernel.h>
18#include <linux/vmalloc.h>
19#include <linux/moduleloader.h>
20#include <linux/elf.h>
21
22#if 0
23#define DEBUGP printk
24#else
25#define DEBUGP(fmt , ...)
26#endif
27
28void *module_alloc (unsigned long size)
29{
30 return size == 0 ? 0 : vmalloc (size);
31}
32
33void module_free (struct module *mod, void *module_region)
34{
35 vfree (module_region);
36 /* FIXME: If module_region == mod->init_region, trim exception
37 table entries. */
38}
39
40int module_finalize (const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
41 struct module *mod)
42{
43 return 0;
44}
45
46/* Count how many different relocations (different symbol, different
47 addend) */
48static unsigned int count_relocs(const Elf32_Rela *rela, unsigned int num)
49{
50 unsigned int i, j, ret = 0;
51
52 /* Sure, this is order(n^2), but it's usually short, and not
53 time critical */
54 for (i = 0; i < num; i++) {
55 for (j = 0; j < i; j++) {
56 /* If this addend appeared before, it's
57 already been counted */
58 if (ELF32_R_SYM(rela[i].r_info)
59 == ELF32_R_SYM(rela[j].r_info)
60 && rela[i].r_addend == rela[j].r_addend)
61 break;
62 }
63 if (j == i) ret++;
64 }
65 return ret;
66}
67
68/* Get the potential trampolines size required of the init and
69 non-init sections */
70static unsigned long get_plt_size(const Elf32_Ehdr *hdr,
71 const Elf32_Shdr *sechdrs,
72 const char *secstrings,
73 int is_init)
74{
75 unsigned long ret = 0;
76 unsigned i;
77
78 /* Everything marked ALLOC (this includes the exported
79 symbols) */
80 for (i = 1; i < hdr->e_shnum; i++) {
81 /* If it's called *.init*, and we're not init, we're
82 not interested */
83 if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0)
84 != is_init)
85 continue;
86
87 if (sechdrs[i].sh_type == SHT_RELA) {
88 DEBUGP("Found relocations in section %u\n", i);
89 DEBUGP("Ptr: %p. Number: %u\n",
90 (void *)hdr + sechdrs[i].sh_offset,
91 sechdrs[i].sh_size / sizeof(Elf32_Rela));
92 ret += count_relocs((void *)hdr
93 + sechdrs[i].sh_offset,
94 sechdrs[i].sh_size
95 / sizeof(Elf32_Rela))
96 * sizeof(struct v850_plt_entry);
97 }
98 }
99
100 return ret;
101}
102
103int module_frob_arch_sections(Elf32_Ehdr *hdr,
104 Elf32_Shdr *sechdrs,
105 char *secstrings,
106 struct module *me)
107{
108 unsigned int i;
109
110 /* Find .plt and .pltinit sections */
111 for (i = 0; i < hdr->e_shnum; i++) {
112 if (strcmp(secstrings + sechdrs[i].sh_name, ".init.plt") == 0)
113 me->arch.init_plt_section = i;
114 else if (strcmp(secstrings + sechdrs[i].sh_name, ".plt") == 0)
115 me->arch.core_plt_section = i;
116 }
117 if (!me->arch.core_plt_section || !me->arch.init_plt_section) {
118 printk("Module doesn't contain .plt or .plt.init sections.\n");
119 return -ENOEXEC;
120 }
121
122 /* Override their sizes */
123 sechdrs[me->arch.core_plt_section].sh_size
124 = get_plt_size(hdr, sechdrs, secstrings, 0);
125 sechdrs[me->arch.init_plt_section].sh_size
126 = get_plt_size(hdr, sechdrs, secstrings, 1);
127 return 0;
128}
129
130int apply_relocate (Elf32_Shdr *sechdrs, const char *strtab,
131 unsigned int symindex, unsigned int relsec,
132 struct module *mod)
133{
134 printk ("Barf\n");
135 return -ENOEXEC;
136}
137
138/* Set up a trampoline in the PLT to bounce us to the distant function */
139static uint32_t do_plt_call (void *location, Elf32_Addr val,
140 Elf32_Shdr *sechdrs, struct module *mod)
141{
142 struct v850_plt_entry *entry;
143 /* Instructions used to do the indirect jump. */
144 uint32_t tramp[2];
145
146 /* We have to trash a register, so we assume that any control
147 transfer more than 21-bits away must be a function call
148 (so we can use a call-clobbered register). */
149 tramp[0] = 0x0621 + ((val & 0xffff) << 16); /* mov sym, r1 ... */
150 tramp[1] = ((val >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
151
152 /* Init, or core PLT? */
153 if (location >= mod->module_core
154 && location < mod->module_core + mod->core_size)
155 entry = (void *)sechdrs[mod->arch.core_plt_section].sh_addr;
156 else
157 entry = (void *)sechdrs[mod->arch.init_plt_section].sh_addr;
158
159 /* Find this entry, or if that fails, the next avail. entry */
160 while (entry->tramp[0])
161 if (entry->tramp[0] == tramp[0] && entry->tramp[1] == tramp[1])
162 return (uint32_t)entry;
163 else
164 entry++;
165
166 entry->tramp[0] = tramp[0];
167 entry->tramp[1] = tramp[1];
168
169 return (uint32_t)entry;
170}
171
172int apply_relocate_add (Elf32_Shdr *sechdrs, const char *strtab,
173 unsigned int symindex, unsigned int relsec,
174 struct module *mod)
175{
176 unsigned int i;
177 Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
178
179 DEBUGP ("Applying relocate section %u to %u\n", relsec,
180 sechdrs[relsec].sh_info);
181
182 for (i = 0; i < sechdrs[relsec].sh_size / sizeof (*rela); i++) {
183 /* This is where to make the change */
184 uint32_t *loc
185 = ((void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
186 + rela[i].r_offset);
187 /* This is the symbol it is referring to. Note that all
188 undefined symbols have been resolved. */
189 Elf32_Sym *sym
190 = ((Elf32_Sym *)sechdrs[symindex].sh_addr
191 + ELF32_R_SYM (rela[i].r_info));
192 uint32_t val = sym->st_value + rela[i].r_addend;
193
194 switch (ELF32_R_TYPE (rela[i].r_info)) {
195 case R_V850_32:
196 /* We write two shorts instead of a long because even
197 32-bit insns only need half-word alignment, but
198 32-bit data writes need to be long-word aligned. */
199 val += ((uint16_t *)loc)[0];
200 val += ((uint16_t *)loc)[1] << 16;
201 ((uint16_t *)loc)[0] = val & 0xffff;
202 ((uint16_t *)loc)[1] = (val >> 16) & 0xffff;
203 break;
204
205 case R_V850_22_PCREL:
206 /* Maybe jump indirectly via a PLT table entry. */
207 if ((int32_t)(val - (uint32_t)loc) > 0x1fffff
208 || (int32_t)(val - (uint32_t)loc) < -0x200000)
209 val = do_plt_call (loc, val, sechdrs, mod);
210
211 val -= (uint32_t)loc;
212
213 /* We write two shorts instead of a long because
214 even 32-bit insns only need half-word alignment,
215 but 32-bit data writes need to be long-word
216 aligned. */
217 ((uint16_t *)loc)[0] =
218 (*(uint16_t *)loc & 0xffc0) /* opcode + reg */
219 | ((val >> 16) & 0xffc03f); /* offs high */
220 ((uint16_t *)loc)[1] =
221 (val & 0xffff); /* offs low */
222 break;
223
224 default:
225 printk (KERN_ERR "module %s: Unknown reloc: %u\n",
226 mod->name, ELF32_R_TYPE (rela[i].r_info));
227 return -ENOEXEC;
228 }
229 }
230
231 return 0;
232}
233
234void
235module_arch_cleanup(struct module *mod)
236{
237}
diff --git a/arch/v850/kernel/process.c b/arch/v850/kernel/process.c
new file mode 100644
index 000000000000..9c708c32c1f0
--- /dev/null
+++ b/arch/v850/kernel/process.c
@@ -0,0 +1,236 @@
1/*
2 * arch/v850/kernel/process.c -- Arch-dependent process handling
3 *
4 * Copyright (C) 2001,02,03 NEC Electronics Corporation
5 * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14#include <linux/config.h>
15#include <linux/errno.h>
16#include <linux/sched.h>
17#include <linux/kernel.h>
18#include <linux/mm.h>
19#include <linux/smp.h>
20#include <linux/smp_lock.h>
21#include <linux/stddef.h>
22#include <linux/unistd.h>
23#include <linux/ptrace.h>
24#include <linux/slab.h>
25#include <linux/user.h>
26#include <linux/a.out.h>
27#include <linux/reboot.h>
28
29#include <asm/uaccess.h>
30#include <asm/system.h>
31#include <asm/pgtable.h>
32
33extern void ret_from_fork (void);
34
35
36/* The idle loop. */
37void default_idle (void)
38{
39 while (1) {
40 while (! need_resched ())
41 asm ("halt; nop; nop; nop; nop; nop" ::: "cc");
42 schedule ();
43 }
44}
45
46void (*idle)(void) = default_idle;
47
48/*
49 * The idle thread. There's no useful work to be
50 * done, so just try to conserve power and have a
51 * low exit latency (ie sit in a loop waiting for
52 * somebody to say that they'd like to reschedule)
53 */
54void cpu_idle (void)
55{
56 /* endless idle loop with no priority at all */
57 (*idle) ();
58}
59
60/*
61 * This is the mechanism for creating a new kernel thread.
62 *
63 * NOTE! Only a kernel-only process (ie the swapper or direct descendants who
64 * haven't done an "execve()") should use this: it will work within a system
65 * call from a "real" process, but the process memory space will not be free'd
66 * until both the parent and the child have exited.
67 */
68int kernel_thread (int (*fn)(void *), void *arg, unsigned long flags)
69{
70 register mm_segment_t fs = get_fs ();
71 register unsigned long syscall asm (SYSCALL_NUM);
72 register unsigned long arg0 asm (SYSCALL_ARG0);
73 register unsigned long ret asm (SYSCALL_RET);
74
75 set_fs (KERNEL_DS);
76
77 /* Clone this thread. Note that we don't pass the clone syscall's
78 second argument -- it's ignored for calls from kernel mode (the
79 child's SP is always set to the top of the kernel stack). */
80 arg0 = flags | CLONE_VM;
81 syscall = __NR_clone;
82 asm volatile ("trap " SYSCALL_SHORT_TRAP
83 : "=r" (ret), "=r" (syscall)
84 : "1" (syscall), "r" (arg0)
85 : SYSCALL_SHORT_CLOBBERS);
86
87 if (ret == 0) {
88 /* In child thread, call FN and exit. */
89 arg0 = (*fn) (arg);
90 syscall = __NR_exit;
91 asm volatile ("trap " SYSCALL_SHORT_TRAP
92 : "=r" (ret), "=r" (syscall)
93 : "1" (syscall), "r" (arg0)
94 : SYSCALL_SHORT_CLOBBERS);
95 }
96
97 /* In parent. */
98 set_fs (fs);
99
100 return ret;
101}
102
103void flush_thread (void)
104{
105 set_fs (USER_DS);
106}
107
108int copy_thread (int nr, unsigned long clone_flags,
109 unsigned long stack_start, unsigned long stack_size,
110 struct task_struct *p, struct pt_regs *regs)
111{
112 /* Start pushing stuff from the top of the child's kernel stack. */
113 unsigned long orig_ksp = (unsigned long)p->thread_info + THREAD_SIZE;
114 unsigned long ksp = orig_ksp;
115 /* We push two `state save' stack fames (see entry.S) on the new
116 kernel stack:
117 1) The innermost one is what switch_thread would have
118 pushed, and is used when we context switch to the child
119 thread for the first time. It's set up to return to
120 ret_from_fork in entry.S.
121 2) The outermost one (nearest the top) is what a syscall
122 trap would have pushed, and is set up to return to the
123 same location as the parent thread, but with a return
124 value of 0. */
125 struct pt_regs *child_switch_regs, *child_trap_regs;
126
127 /* Trap frame. */
128 ksp -= STATE_SAVE_SIZE;
129 child_trap_regs = (struct pt_regs *)(ksp + STATE_SAVE_PT_OFFSET);
130 /* Switch frame. */
131 ksp -= STATE_SAVE_SIZE;
132 child_switch_regs = (struct pt_regs *)(ksp + STATE_SAVE_PT_OFFSET);
133
134 /* First copy parent's register state to child. */
135 *child_switch_regs = *regs;
136 *child_trap_regs = *regs;
137
138 /* switch_thread returns to the restored value of the lp
139 register (r31), so we make that the place where we want to
140 jump when the child thread begins running. */
141 child_switch_regs->gpr[GPR_LP] = (v850_reg_t)ret_from_fork;
142
143 if (regs->kernel_mode)
144 /* Since we're returning to kernel-mode, make sure the child's
145 stored kernel stack pointer agrees with what the actual
146 stack pointer will be at that point (the trap return code
147 always restores the SP, even when returning to
148 kernel-mode). */
149 child_trap_regs->gpr[GPR_SP] = orig_ksp;
150 else
151 /* Set the child's user-mode stack-pointer (the name
152 `stack_start' is a misnomer, it's just the initial SP
153 value). */
154 child_trap_regs->gpr[GPR_SP] = stack_start;
155
156 /* Thread state for the child (everything else is on the stack). */
157 p->thread.ksp = ksp;
158
159 return 0;
160}
161
162/*
163 * fill in the user structure for a core dump..
164 */
165void dump_thread (struct pt_regs *regs, struct user *dump)
166{
167#if 0 /* Later. XXX */
168 dump->magic = CMAGIC;
169 dump->start_code = 0;
170 dump->start_stack = regs->gpr[GPR_SP];
171 dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
172 dump->u_dsize = ((unsigned long) (current->mm->brk +
173 (PAGE_SIZE-1))) >> PAGE_SHIFT;
174 dump->u_dsize -= dump->u_tsize;
175 dump->u_ssize = 0;
176
177 if (dump->start_stack < TASK_SIZE)
178 dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
179
180 dump->u_ar0 = (struct user_regs_struct *)((int)&dump->regs - (int)dump);
181 dump->regs = *regs;
182 dump->u_fpvalid = 0;
183#endif
184}
185
186/*
187 * sys_execve() executes a new program.
188 */
189int sys_execve (char *name, char **argv, char **envp, struct pt_regs *regs)
190{
191 char *filename = getname (name);
192 int error = PTR_ERR (filename);
193
194 if (! IS_ERR (filename)) {
195 error = do_execve (filename, argv, envp, regs);
196 putname (filename);
197 }
198
199 return error;
200}
201
202
203/*
204 * These bracket the sleeping functions..
205 */
206#define first_sched ((unsigned long)__sched_text_start)
207#define last_sched ((unsigned long)__sched_text_end)
208
209unsigned long get_wchan (struct task_struct *p)
210{
211#if 0 /* Barf. Figure out the stack-layout later. XXX */
212 unsigned long fp, pc;
213 int count = 0;
214
215 if (!p || p == current || p->state == TASK_RUNNING)
216 return 0;
217
218 pc = thread_saved_pc (p);
219
220 /* This quite disgusting function walks up the stack, following
221 saved return address, until it something that's out of bounds
222 (as defined by `first_sched' and `last_sched'). It then
223 returns the last PC that was in-bounds. */
224 do {
225 if (fp < stack_page + sizeof (struct task_struct) ||
226 fp >= 8184+stack_page)
227 return 0;
228 pc = ((unsigned long *)fp)[1];
229 if (pc < first_sched || pc >= last_sched)
230 return pc;
231 fp = *(unsigned long *) fp;
232 } while (count++ < 16);
233#endif
234
235 return 0;
236}
diff --git a/arch/v850/kernel/procfs.c b/arch/v850/kernel/procfs.c
new file mode 100644
index 000000000000..e6f9d060ad5b
--- /dev/null
+++ b/arch/v850/kernel/procfs.c
@@ -0,0 +1,67 @@
1/*
2 * arch/v850/kernel/procfs.c -- Introspection functions for /proc filesystem
3 *
4 * Copyright (C) 2001,02 NEC Corporation
5 * Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14#include "mach.h"
15
16static int cpuinfo_print (struct seq_file *m, void *v)
17{
18 extern unsigned long loops_per_jiffy;
19
20 seq_printf (m, "CPU-Family: v850\nCPU-Arch: %s\n", CPU_ARCH);
21
22#ifdef CPU_MODEL_LONG
23 seq_printf (m, "CPU-Model: %s (%s)\n", CPU_MODEL, CPU_MODEL_LONG);
24#else
25 seq_printf (m, "CPU-Model: %s\n", CPU_MODEL);
26#endif
27
28#ifdef CPU_CLOCK_FREQ
29 seq_printf (m, "CPU-Clock: %ld (%ld MHz)\n",
30 (long)CPU_CLOCK_FREQ,
31 (long)CPU_CLOCK_FREQ / 1000000);
32#endif
33
34 seq_printf (m, "BogoMips: %lu.%02lu\n",
35 loops_per_jiffy/(500000/HZ),
36 (loops_per_jiffy/(5000/HZ)) % 100);
37
38#ifdef PLATFORM_LONG
39 seq_printf (m, "Platform: %s (%s)\n", PLATFORM, PLATFORM_LONG);
40#elif defined (PLATFORM)
41 seq_printf (m, "Platform: %s\n", PLATFORM);
42#endif
43
44 return 0;
45}
46
47static void *cpuinfo_start (struct seq_file *m, loff_t *pos)
48{
49 return *pos < NR_CPUS ? ((void *) 0x12345678) : NULL;
50}
51
52static void *cpuinfo_next (struct seq_file *m, void *v, loff_t *pos)
53{
54 ++*pos;
55 return cpuinfo_start (m, pos);
56}
57
58static void cpuinfo_stop (struct seq_file *m, void *v)
59{
60}
61
62struct seq_operations cpuinfo_op = {
63 .start = cpuinfo_start,
64 .next = cpuinfo_next,
65 .stop = cpuinfo_stop,
66 .show = cpuinfo_print
67};
diff --git a/arch/v850/kernel/ptrace.c b/arch/v850/kernel/ptrace.c
new file mode 100644
index 000000000000..8fa780757dcd
--- /dev/null
+++ b/arch/v850/kernel/ptrace.c
@@ -0,0 +1,282 @@
1/*
2 * arch/v850/kernel/ptrace.c -- `ptrace' system call
3 *
4 * Copyright (C) 2002,03,04 NEC Electronics Corporation
5 * Copyright (C) 2002,03,04 Miles Bader <miles@gnu.org>
6 *
7 * Derived from arch/mips/kernel/ptrace.c:
8 *
9 * Copyright (C) 1992 Ross Biro
10 * Copyright (C) Linus Torvalds
11 * Copyright (C) 1994, 95, 96, 97, 98, 2000 Ralf Baechle
12 * Copyright (C) 1996 David S. Miller
13 * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
14 * Copyright (C) 1999 MIPS Technologies, Inc.
15 *
16 * This file is subject to the terms and conditions of the GNU General
17 * Public License. See the file COPYING in the main directory of this
18 * archive for more details.
19 */
20
21#include <linux/kernel.h>
22#include <linux/mm.h>
23#include <linux/sched.h>
24#include <linux/smp_lock.h>
25#include <linux/ptrace.h>
26
27#include <asm/errno.h>
28#include <asm/ptrace.h>
29#include <asm/processor.h>
30#include <asm/uaccess.h>
31
32/* Returns the address where the register at REG_OFFS in P is stashed away. */
33static v850_reg_t *reg_save_addr (unsigned reg_offs, struct task_struct *t)
34{
35 struct pt_regs *regs;
36
37 /* Three basic cases:
38
39 (1) A register normally saved before calling the scheduler, is
40 available in the kernel entry pt_regs structure at the top
41 of the kernel stack. The kernel trap/irq exit path takes
42 care to save/restore almost all registers for ptrace'd
43 processes.
44
45 (2) A call-clobbered register, where the process P entered the
46 kernel via [syscall] trap, is not stored anywhere; that's
47 OK, because such registers are not expected to be preserved
48 when the trap returns anyway (so we don't actually bother to
49 test for this case).
50
51 (3) A few registers not used at all by the kernel, and so
52 normally never saved except by context-switches, are in the
53 context switch state. */
54
55 if (reg_offs == PT_CTPC || reg_offs == PT_CTPSW || reg_offs == PT_CTBP)
56 /* Register saved during context switch. */
57 regs = thread_saved_regs (t);
58 else
59 /* Register saved during kernel entry (or not available). */
60 regs = task_regs (t);
61
62 return (v850_reg_t *)((char *)regs + reg_offs);
63}
64
65/* Set the bits SET and clear the bits CLEAR in the v850e DIR
66 (`debug information register'). Returns the new value of DIR. */
67static inline v850_reg_t set_dir (v850_reg_t set, v850_reg_t clear)
68{
69 register v850_reg_t rval asm ("r10");
70 register v850_reg_t arg0 asm ("r6") = set;
71 register v850_reg_t arg1 asm ("r7") = clear;
72
73 /* The dbtrap handler has exactly this functionality when called
74 from kernel mode. 0xf840 is a `dbtrap' insn. */
75 asm (".short 0xf840" : "=r" (rval) : "r" (arg0), "r" (arg1));
76
77 return rval;
78}
79
80/* Makes sure hardware single-stepping is (globally) enabled.
81 Returns true if successful. */
82static inline int enable_single_stepping (void)
83{
84 static int enabled = 0; /* Remember whether we already did it. */
85 if (! enabled) {
86 /* Turn on the SE (`single-step enable') bit, 0x100, in the
87 DIR (`debug information register'). This may fail if a
88 processor doesn't support it or something. We also try
89 to clear bit 0x40 (`INI'), which is necessary to use the
90 debug stuff on the v850e2; on the v850e, clearing 0x40
91 shouldn't cause any problem. */
92 v850_reg_t dir = set_dir (0x100, 0x40);
93 /* Make sure it really got set. */
94 if (dir & 0x100)
95 enabled = 1;
96 }
97 return enabled;
98}
99
100/* Try to set CHILD's single-step flag to VAL. Returns true if successful. */
101static int set_single_step (struct task_struct *t, int val)
102{
103 v850_reg_t *psw_addr = reg_save_addr(PT_PSW, t);
104 if (val) {
105 /* Make sure single-stepping is enabled. */
106 if (! enable_single_stepping ())
107 return 0;
108 /* Set T's single-step flag. */
109 *psw_addr |= 0x800;
110 } else
111 *psw_addr &= ~0x800;
112 return 1;
113}
114
115int sys_ptrace(long request, long pid, long addr, long data)
116{
117 struct task_struct *child;
118 int rval;
119
120 lock_kernel();
121
122 if (request == PTRACE_TRACEME) {
123 /* are we already being traced? */
124 if (current->ptrace & PT_PTRACED) {
125 rval = -EPERM;
126 goto out;
127 }
128 /* set the ptrace bit in the process flags. */
129 current->ptrace |= PT_PTRACED;
130 rval = 0;
131 goto out;
132 }
133 rval = -ESRCH;
134 read_lock(&tasklist_lock);
135 child = find_task_by_pid(pid);
136 if (child)
137 get_task_struct(child);
138 read_unlock(&tasklist_lock);
139 if (!child)
140 goto out;
141
142 rval = -EPERM;
143 if (pid == 1) /* you may not mess with init */
144 goto out_tsk;
145
146 if (request == PTRACE_ATTACH) {
147 rval = ptrace_attach(child);
148 goto out_tsk;
149 }
150 rval = ptrace_check_attach(child, request == PTRACE_KILL);
151 if (rval < 0)
152 goto out_tsk;
153
154 switch (request) {
155 unsigned long val, copied;
156
157 case PTRACE_PEEKTEXT: /* read word at location addr. */
158 case PTRACE_PEEKDATA:
159 copied = access_process_vm(child, addr, &val, sizeof(val), 0);
160 rval = -EIO;
161 if (copied != sizeof(val))
162 break;
163 rval = put_user(val, (unsigned long *)data);
164 goto out;
165
166 case PTRACE_POKETEXT: /* write the word at location addr. */
167 case PTRACE_POKEDATA:
168 rval = 0;
169 if (access_process_vm(child, addr, &data, sizeof(data), 1)
170 == sizeof(data))
171 break;
172 rval = -EIO;
173 goto out;
174
175 /* Read/write the word at location ADDR in the registers. */
176 case PTRACE_PEEKUSR:
177 case PTRACE_POKEUSR:
178 rval = 0;
179 if (addr >= PT_SIZE && request == PTRACE_PEEKUSR) {
180 /* Special requests that don't actually correspond
181 to offsets in struct pt_regs. */
182 if (addr == PT_TEXT_ADDR)
183 val = child->mm->start_code;
184 else if (addr == PT_DATA_ADDR)
185 val = child->mm->start_data;
186 else if (addr == PT_TEXT_LEN)
187 val = child->mm->end_code
188 - child->mm->start_code;
189 else
190 rval = -EIO;
191 } else if (addr >= 0 && addr < PT_SIZE && (addr & 0x3) == 0) {
192 v850_reg_t *reg_addr = reg_save_addr(addr, child);
193 if (request == PTRACE_PEEKUSR)
194 val = *reg_addr;
195 else
196 *reg_addr = data;
197 } else
198 rval = -EIO;
199
200 if (rval == 0 && request == PTRACE_PEEKUSR)
201 rval = put_user (val, (unsigned long *)data);
202 goto out;
203
204 /* Continue and stop at next (return from) syscall */
205 case PTRACE_SYSCALL:
206 /* Restart after a signal. */
207 case PTRACE_CONT:
208 /* Execute a single instruction. */
209 case PTRACE_SINGLESTEP:
210 rval = -EIO;
211 if ((unsigned long) data > _NSIG)
212 break;
213
214 /* Turn CHILD's single-step flag on or off. */
215 if (! set_single_step (child, request == PTRACE_SINGLESTEP))
216 break;
217
218 if (request == PTRACE_SYSCALL)
219 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
220 else
221 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
222
223 child->exit_code = data;
224 wake_up_process(child);
225 rval = 0;
226 break;
227
228 /*
229 * make the child exit. Best I can do is send it a sigkill.
230 * perhaps it should be put in the status that it wants to
231 * exit.
232 */
233 case PTRACE_KILL:
234 rval = 0;
235 if (child->exit_state == EXIT_ZOMBIE) /* already dead */
236 break;
237 child->exit_code = SIGKILL;
238 wake_up_process(child);
239 break;
240
241 case PTRACE_DETACH: /* detach a process that was attached. */
242 set_single_step (child, 0); /* Clear single-step flag */
243 rval = ptrace_detach(child, data);
244 break;
245
246 default:
247 rval = -EIO;
248 goto out;
249 }
250
251out_tsk:
252 put_task_struct(child);
253out:
254 unlock_kernel();
255 return rval;
256}
257
258asmlinkage void syscall_trace(void)
259{
260 if (!test_thread_flag(TIF_SYSCALL_TRACE))
261 return;
262 if (!(current->ptrace & PT_PTRACED))
263 return;
264 /* The 0x80 provides a way for the tracing parent to distinguish
265 between a syscall stop and SIGTRAP delivery */
266 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
267 ? 0x80 : 0));
268 /*
269 * this isn't the same as continuing with a signal, but it will do
270 * for normal use. strace only continues with a signal if the
271 * stopping signal is not SIGTRAP. -brl
272 */
273 if (current->exit_code) {
274 send_sig(current->exit_code, current, 1);
275 current->exit_code = 0;
276 }
277}
278
279void ptrace_disable (struct task_struct *child)
280{
281 /* nothing to do */
282}
diff --git a/arch/v850/kernel/rte_cb.c b/arch/v850/kernel/rte_cb.c
new file mode 100644
index 000000000000..7ba397f77aca
--- /dev/null
+++ b/arch/v850/kernel/rte_cb.c
@@ -0,0 +1,200 @@
1/*
2 * include/asm-v850/rte_cb.c -- Midas lab RTE-CB series of evaluation boards
3 *
4 * Copyright (C) 2001,02,03 NEC Electronics Corporation
5 * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14#include <linux/config.h>
15#include <linux/init.h>
16#include <linux/irq.h>
17#include <linux/fs.h>
18#include <linux/module.h>
19
20#include <asm/machdep.h>
21#include <asm/v850e_uart.h>
22
23#include "mach.h"
24
25static void led_tick (void);
26
27/* LED access routines. */
28extern unsigned read_leds (int pos, char *buf, int len);
29extern unsigned write_leds (int pos, const char *buf, int len);
30
31#ifdef CONFIG_RTE_CB_MULTI
32extern void multi_init (void);
33#endif
34
35
36void __init rte_cb_early_init (void)
37{
38 v850e_intc_disable_irqs ();
39
40#ifdef CONFIG_RTE_CB_MULTI
41 multi_init ();
42#endif
43}
44
45void __init mach_setup (char **cmdline)
46{
47#ifdef CONFIG_RTE_MB_A_PCI
48 /* Probe for Mother-A, and print a message if we find it. */
49 *(volatile unsigned long *)MB_A_SRAM_ADDR = 0xDEADBEEF;
50 if (*(volatile unsigned long *)MB_A_SRAM_ADDR == 0xDEADBEEF) {
51 *(volatile unsigned long *)MB_A_SRAM_ADDR = 0x12345678;
52 if (*(volatile unsigned long *)MB_A_SRAM_ADDR == 0x12345678)
53 printk (KERN_INFO
54 " NEC SolutionGear/Midas lab"
55 " RTE-MOTHER-A motherboard\n");
56 }
57#endif /* CONFIG_RTE_MB_A_PCI */
58
59 mach_tick = led_tick;
60}
61
62void machine_restart (char *__unused)
63{
64#ifdef CONFIG_RESET_GUARD
65 disable_reset_guard ();
66#endif
67 asm ("jmp r0"); /* Jump to the reset vector. */
68}
69
70EXPORT_SYMBOL(machine_restart);
71
72/* This says `HALt.' in LEDese. */
73static unsigned char halt_leds_msg[] = { 0x76, 0x77, 0x38, 0xF8 };
74
75void machine_halt (void)
76{
77#ifdef CONFIG_RESET_GUARD
78 disable_reset_guard ();
79#endif
80
81 /* Ignore all interrupts. */
82 local_irq_disable ();
83
84 /* Write a little message. */
85 write_leds (0, halt_leds_msg, sizeof halt_leds_msg);
86
87 /* Really halt. */
88 for (;;)
89 asm ("halt; nop; nop; nop; nop; nop");
90}
91
92EXPORT_SYMBOL(machine_halt);
93
94void machine_power_off (void)
95{
96 machine_halt ();
97}
98
99EXPORT_SYMBOL(machine_power_off);
100
101
102/* Animated LED display for timer tick. */
103
104#define TICK_UPD_FREQ 6
105static int tick_frames[][10] = {
106 { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, -1 },
107 { 0x63, 0x5c, -1 },
108 { 0x5c, 0x00, -1 },
109 { 0x63, 0x00, -1 },
110 { -1 }
111};
112
113static void led_tick ()
114{
115 static unsigned counter = 0;
116
117 if (++counter == (HZ / TICK_UPD_FREQ)) {
118 /* Which frame we're currently displaying for each digit. */
119 static unsigned frame_nums[LED_NUM_DIGITS] = { 0 };
120 /* Display image. */
121 static unsigned char image[LED_NUM_DIGITS] = { 0 };
122 unsigned char prev_image[LED_NUM_DIGITS];
123 int write_to_leds = 1; /* true if we should actually display */
124 int digit;
125
126 /* We check to see if the physical LEDs contains what we last
127 wrote to them; if not, we suppress display (this is so that
128 users can write to the LEDs, and not have their output
129 overwritten). As a special case, we start writing again if
130 all the LEDs are blank, or our display image is all zeros
131 (indicating that this is the initial update, when the actual
132 LEDs might contain random data). */
133 read_leds (0, prev_image, LED_NUM_DIGITS);
134 for (digit = 0; digit < LED_NUM_DIGITS; digit++)
135 if (image[digit] != prev_image[digit]
136 && image[digit] && prev_image[digit])
137 {
138 write_to_leds = 0;
139 break;
140 }
141
142 /* Update display image. */
143 for (digit = 0;
144 digit < LED_NUM_DIGITS && tick_frames[digit][0] >= 0;
145 digit++)
146 {
147 int frame = tick_frames[digit][frame_nums[digit]];
148 if (frame < 0) {
149 image[digit] = tick_frames[digit][0];
150 frame_nums[digit] = 1;
151 } else {
152 image[digit] = frame;
153 frame_nums[digit]++;
154 break;
155 }
156 }
157
158 if (write_to_leds)
159 /* Write the display image to the physical LEDs. */
160 write_leds (0, image, LED_NUM_DIGITS);
161
162 counter = 0;
163 }
164}
165
166
167/* Mother-A interrupts. */
168
169#ifdef CONFIG_RTE_GBUS_INT
170
171#define L GBUS_INT_PRIORITY_LOW
172#define M GBUS_INT_PRIORITY_MEDIUM
173#define H GBUS_INT_PRIORITY_HIGH
174
175static struct gbus_int_irq_init gbus_irq_inits[] = {
176#ifdef CONFIG_RTE_MB_A_PCI
177 { "MB_A_LAN", IRQ_MB_A_LAN, 1, 1, L },
178 { "MB_A_PCI1", IRQ_MB_A_PCI1(0), IRQ_MB_A_PCI1_NUM, 1, L },
179 { "MB_A_PCI2", IRQ_MB_A_PCI2(0), IRQ_MB_A_PCI2_NUM, 1, L },
180 { "MB_A_EXT", IRQ_MB_A_EXT(0), IRQ_MB_A_EXT_NUM, 1, L },
181 { "MB_A_USB_OC",IRQ_MB_A_USB_OC(0), IRQ_MB_A_USB_OC_NUM, 1, L },
182 { "MB_A_PCMCIA_OC",IRQ_MB_A_PCMCIA_OC, 1, 1, L },
183#endif
184 { 0 }
185};
186#define NUM_GBUS_IRQ_INITS \
187 ((sizeof gbus_irq_inits / sizeof gbus_irq_inits[0]) - 1)
188
189static struct hw_interrupt_type gbus_hw_itypes[NUM_GBUS_IRQ_INITS];
190
191#endif /* CONFIG_RTE_GBUS_INT */
192
193
194void __init rte_cb_init_irqs (void)
195{
196#ifdef CONFIG_RTE_GBUS_INT
197 gbus_int_init_irqs ();
198 gbus_int_init_irq_types (gbus_irq_inits, gbus_hw_itypes);
199#endif /* CONFIG_RTE_GBUS_INT */
200}
diff --git a/arch/v850/kernel/rte_cb_leds.c b/arch/v850/kernel/rte_cb_leds.c
new file mode 100644
index 000000000000..b662ad838940
--- /dev/null
+++ b/arch/v850/kernel/rte_cb_leds.c
@@ -0,0 +1,138 @@
1/*
2 * include/asm-v850/rte_cb_leds.c -- Midas lab RTE-CB board LED device support
3 *
4 * Copyright (C) 2002,03 NEC Electronics Corporation
5 * Copyright (C) 2002,03 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14#include <linux/config.h>
15#include <linux/init.h>
16#include <linux/spinlock.h>
17#include <linux/fs.h>
18#include <linux/miscdevice.h>
19
20#include <asm/uaccess.h>
21
22#define LEDS_MINOR 169 /* Minor device number, using misc major. */
23
24/* The actual LED hardware is write-only, so we hold the contents here too. */
25static unsigned char leds_image[LED_NUM_DIGITS] = { 0 };
26
27/* Spinlock protecting the above leds. */
28static DEFINE_SPINLOCK(leds_lock);
29
30/* Common body of LED read/write functions, checks POS and LEN for
31 correctness, declares a variable using IMG_DECL, initialized pointing at
32 the POS position in the LED image buffer, and and iterates COPY_EXPR
33 until BUF is equal to the last buffer position; finally, sets LEN to be
34 the amount actually copied. IMG should be a variable declaration
35 (without an initializer or a terminating semicolon); POS, BUF, and LEN
36 should all be simple variables. */
37#define DO_LED_COPY(img_decl, pos, buf, len, copy_expr) \
38do { \
39 if (pos > LED_NUM_DIGITS) \
40 len = 0; \
41 else { \
42 if (pos + len > LED_NUM_DIGITS) \
43 len = LED_NUM_DIGITS - pos; \
44 \
45 if (len > 0) { \
46 int _flags; \
47 const char *_end = buf + len; \
48 img_decl = &leds_image[pos]; \
49 \
50 spin_lock_irqsave (leds_lock, _flags); \
51 do \
52 (copy_expr); \
53 while (buf != _end); \
54 spin_unlock_irqrestore (leds_lock, _flags); \
55 } \
56 } \
57} while (0)
58
59/* Read LEN bytes from LEDs at position POS, into BUF.
60 Returns actual amount read. */
61unsigned read_leds (unsigned pos, char *buf, unsigned len)
62{
63 DO_LED_COPY (const char *img, pos, buf, len, *buf++ = *img++);
64 return len;
65}
66
67/* Write LEN bytes to LEDs at position POS, from BUF.
68 Returns actual amount written. */
69unsigned write_leds (unsigned pos, const char *buf, unsigned len)
70{
71 /* We write the actual LED values backwards, because
72 increasing memory addresses reflect LEDs right-to-left. */
73 volatile char *led = &LED (LED_NUM_DIGITS - pos - 1);
74 /* We invert the value written to the hardware, because 1 = off,
75 and 0 = on. */
76 DO_LED_COPY (char *img, pos, buf, len,
77 *led-- = 0xFF ^ (*img++ = *buf++));
78 return len;
79}
80
81
82/* Device functions. */
83
84static ssize_t leds_dev_read (struct file *file, char *buf, size_t len,
85 loff_t *pos)
86{
87 char temp_buf[LED_NUM_DIGITS];
88 len = read_leds (*pos, temp_buf, len);
89 if (copy_to_user (buf, temp_buf, len))
90 return -EFAULT;
91 *pos += len;
92 return len;
93}
94
95static ssize_t leds_dev_write (struct file *file, const char *buf, size_t len,
96 loff_t *pos)
97{
98 char temp_buf[LED_NUM_DIGITS];
99 if (copy_from_user (temp_buf, buf, min_t(size_t, len, LED_NUM_DIGITS)))
100 return -EFAULT;
101 len = write_leds (*pos, temp_buf, len);
102 *pos += len;
103 return len;
104}
105
106static loff_t leds_dev_lseek (struct file *file, loff_t offs, int whence)
107{
108 if (whence == 1)
109 offs += file->f_pos; /* relative */
110 else if (whence == 2)
111 offs += LED_NUM_DIGITS; /* end-relative */
112
113 if (offs < 0 || offs > LED_NUM_DIGITS)
114 return -EINVAL;
115
116 file->f_pos = offs;
117
118 return 0;
119}
120
121static struct file_operations leds_fops = {
122 .read = leds_dev_read,
123 .write = leds_dev_write,
124 .llseek = leds_dev_lseek
125};
126
127static struct miscdevice leds_miscdev = {
128 .name = "leds",
129 .minor = LEDS_MINOR,
130 .fops = &leds_fops
131};
132
133int __init leds_dev_init (void)
134{
135 return misc_register (&leds_miscdev);
136}
137
138__initcall (leds_dev_init);
diff --git a/arch/v850/kernel/rte_cb_multi.c b/arch/v850/kernel/rte_cb_multi.c
new file mode 100644
index 000000000000..963d55ab34cc
--- /dev/null
+++ b/arch/v850/kernel/rte_cb_multi.c
@@ -0,0 +1,121 @@
1/*
2 * include/asm-v850/rte_multi.c -- Support for Multi debugger monitor ROM
3 * on Midas lab RTE-CB series of evaluation boards
4 *
5 * Copyright (C) 2001,02,03 NEC Electronics Corporation
6 * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
7 *
8 * This file is subject to the terms and conditions of the GNU General
9 * Public License. See the file COPYING in the main directory of this
10 * archive for more details.
11 *
12 * Written by Miles Bader <miles@gnu.org>
13 */
14
15#include <linux/init.h>
16
17#include <asm/machdep.h>
18
19#define IRQ_ADDR(irq) (0x80 + (irq) * 0x10)
20
21/* A table of which interrupt vectors to install, since blindly
22 installing all of them makes the debugger stop working. This is a
23 list of offsets in the interrupt vector area; each entry means to
24 copy that particular 16-byte vector. An entry less than zero ends
25 the table. */
26static long multi_intv_install_table[] = {
27 /* Trap vectors */
28 0x40, 0x50,
29
30#ifdef CONFIG_RTE_CB_MULTI_DBTRAP
31 /* Illegal insn / dbtrap. These are used by multi, so only handle
32 them if configured to do so. */
33 0x60,
34#endif
35
36 /* GINT1 - GINT3 (note, not GINT0!) */
37 IRQ_ADDR (IRQ_GINT(1)),
38 IRQ_ADDR (IRQ_GINT(2)),
39 IRQ_ADDR (IRQ_GINT(3)),
40
41 /* Timer D interrupts (up to 4 timers) */
42 IRQ_ADDR (IRQ_INTCMD(0)),
43#if IRQ_INTCMD_NUM > 1
44 IRQ_ADDR (IRQ_INTCMD(1)),
45#if IRQ_INTCMD_NUM > 2
46 IRQ_ADDR (IRQ_INTCMD(2)),
47#if IRQ_INTCMD_NUM > 3
48 IRQ_ADDR (IRQ_INTCMD(3)),
49#endif
50#endif
51#endif
52
53 /* UART interrupts (up to 3 channels) */
54 IRQ_ADDR (IRQ_INTSER (0)), /* err */
55 IRQ_ADDR (IRQ_INTSR (0)), /* rx */
56 IRQ_ADDR (IRQ_INTST (0)), /* tx */
57#if IRQ_INTSR_NUM > 1
58 IRQ_ADDR (IRQ_INTSER (1)), /* err */
59 IRQ_ADDR (IRQ_INTSR (1)), /* rx */
60 IRQ_ADDR (IRQ_INTST (1)), /* tx */
61#if IRQ_INTSR_NUM > 2
62 IRQ_ADDR (IRQ_INTSER (2)), /* err */
63 IRQ_ADDR (IRQ_INTSR (2)), /* rx */
64 IRQ_ADDR (IRQ_INTST (2)), /* tx */
65#endif
66#endif
67
68 -1
69};
70
71/* Early initialization for kernel using Multi debugger ROM monitor. */
72void __init multi_init (void)
73{
74 /* We're using the Multi debugger monitor, so we have to install
75 the interrupt vectors. The monitor doesn't allow them to be
76 initially downloaded into their final destination because
77 it's in the monitor's scratch-RAM area. Unfortunately, Multi
78 also doesn't deal correctly with ELF sections where the LMA
79 and VMA differ -- it just ignores the LMA -- so we can't use
80 that feature to work around the problem. What we do instead
81 is just put the interrupt vectors into a normal section, and
82 do the necessary copying and relocation here. Since the
83 interrupt vector basically only contains `jr' instructions
84 and no-ops, it's not that hard. */
85 extern unsigned long _intv_load_start, _intv_start;
86 register unsigned long *src = &_intv_load_start;
87 register unsigned long *dst = (unsigned long *)INTV_BASE;
88 register unsigned long jr_fixup = (char *)&_intv_start - (char *)dst;
89 register long *ii;
90
91 /* Copy interrupt vectors as instructed by multi_intv_install_table. */
92 for (ii = multi_intv_install_table; *ii >= 0; ii++) {
93 /* Copy 16-byte interrupt vector at offset *ii. */
94 int boffs;
95 for (boffs = 0; boffs < 0x10; boffs += sizeof *src) {
96 /* Copy a single word, fixing up the jump offs
97 if it's a `jr' instruction. */
98 int woffs = (*ii + boffs) / sizeof *src;
99 unsigned long word = src[woffs];
100
101 if ((word & 0xFC0) == 0x780) {
102 /* A `jr' insn, fix up its offset (and yes, the
103 weird half-word swapping is intentional). */
104 unsigned short hi = word & 0xFFFF;
105 unsigned short lo = word >> 16;
106 unsigned long udisp22
107 = lo + ((hi & 0x3F) << 16);
108 long disp22 = (long)(udisp22 << 10) >> 10;
109
110 disp22 += jr_fixup;
111
112 hi = ((disp22 >> 16) & 0x3F) | 0x780;
113 lo = disp22 & 0xFFFF;
114
115 word = hi + (lo << 16);
116 }
117
118 dst[woffs] = word;
119 }
120 }
121}
diff --git a/arch/v850/kernel/rte_ma1_cb-rom.ld b/arch/v850/kernel/rte_ma1_cb-rom.ld
new file mode 100644
index 000000000000..87b618f8253b
--- /dev/null
+++ b/arch/v850/kernel/rte_ma1_cb-rom.ld
@@ -0,0 +1,14 @@
1/* Linker script for the Midas labs RTE-V850E/MA1-CB evaluation board
2 (CONFIG_RTE_CB_MA1), with kernel in ROM. */
3
4MEMORY {
5 ROM : ORIGIN = 0x00000000, LENGTH = 0x00100000
6 /* 1MB of SRAM. This memory is mirrored 4 times. */
7 SRAM : ORIGIN = SRAM_ADDR, LENGTH = SRAM_SIZE
8 /* 32MB of SDRAM. */
9 SDRAM : ORIGIN = SDRAM_ADDR, LENGTH = SDRAM_SIZE
10}
11
12SECTIONS {
13 ROMK_SECTIONS(ROM, SRAM)
14}
diff --git a/arch/v850/kernel/rte_ma1_cb.c b/arch/v850/kernel/rte_ma1_cb.c
new file mode 100644
index 000000000000..3873e276392f
--- /dev/null
+++ b/arch/v850/kernel/rte_ma1_cb.c
@@ -0,0 +1,106 @@
1/*
2 * arch/v850/kernel/rte_ma1_cb.c -- Midas labs RTE-V850E/MA1-CB board
3 *
4 * Copyright (C) 2001,02,03 NEC Electronics Corporation
5 * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14#include <linux/config.h>
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <linux/bootmem.h>
18
19#include <asm/atomic.h>
20#include <asm/page.h>
21#include <asm/ma1.h>
22#include <asm/rte_ma1_cb.h>
23#include <asm/v850e_timer_c.h>
24
25#include "mach.h"
26
27
28/* SRAM and SDRAM are almost contiguous (with a small hole in between;
29 see mach_reserve_bootmem for details), so just use both as one big area. */
30#define RAM_START SRAM_ADDR
31#define RAM_END (SDRAM_ADDR + SDRAM_SIZE)
32
33
34void __init mach_early_init (void)
35{
36 rte_cb_early_init ();
37}
38
39void __init mach_get_physical_ram (unsigned long *ram_start,
40 unsigned long *ram_len)
41{
42 *ram_start = RAM_START;
43 *ram_len = RAM_END - RAM_START;
44}
45
46void __init mach_reserve_bootmem ()
47{
48#ifdef CONFIG_RTE_CB_MULTI
49 /* Prevent the kernel from touching the monitor's scratch RAM. */
50 reserve_bootmem (MON_SCRATCH_ADDR, MON_SCRATCH_SIZE);
51#endif
52
53 /* The space between SRAM and SDRAM is filled with duplicate
54 images of SRAM. Prevent the kernel from using them. */
55 reserve_bootmem (SRAM_ADDR + SRAM_SIZE,
56 SDRAM_ADDR - (SRAM_ADDR + SRAM_SIZE));
57}
58
59void mach_gettimeofday (struct timespec *tv)
60{
61 tv->tv_sec = 0;
62 tv->tv_nsec = 0;
63}
64
65/* Called before configuring an on-chip UART. */
66void rte_ma1_cb_uart_pre_configure (unsigned chan,
67 unsigned cflags, unsigned baud)
68{
69 /* The RTE-MA1-CB connects some general-purpose I/O pins on the
70 CPU to the RTS/CTS lines of UART 0's serial connection.
71 I/O pins P42 and P43 are RTS and CTS respectively. */
72 if (chan == 0) {
73 /* Put P42 & P43 in I/O port mode. */
74 MA_PORT4_PMC &= ~0xC;
75 /* Make P42 an output, and P43 an input. */
76 MA_PORT4_PM = (MA_PORT4_PM & ~0xC) | 0x8;
77 }
78
79 /* Do pre-configuration for the actual UART. */
80 ma_uart_pre_configure (chan, cflags, baud);
81}
82
83void __init mach_init_irqs (void)
84{
85 unsigned tc;
86
87 /* Initialize interrupts. */
88 ma_init_irqs ();
89 rte_cb_init_irqs ();
90
91 /* Use falling-edge-sensitivity for interrupts . */
92 V850E_TIMER_C_SESC (0) &= ~0xC;
93 V850E_TIMER_C_SESC (1) &= ~0xF;
94
95 /* INTP000-INTP011 are shared with `Timer C', so we have to set
96 up Timer C to pass them through as raw interrupts. */
97 for (tc = 0; tc < 2; tc++)
98 /* Turn on the timer. */
99 V850E_TIMER_C_TMCC0 (tc) |= V850E_TIMER_C_TMCC0_CAE;
100
101 /* Make sure the relevant port0/port1 pins are assigned
102 interrupt duty. We used INTP001-INTP011 (don't screw with
103 INTP000 because the monitor uses it). */
104 MA_PORT0_PMC |= 0x4; /* P02 (INTP001) in IRQ mode. */
105 MA_PORT1_PMC |= 0x6; /* P11 (INTP010) & P12 (INTP011) in IRQ mode.*/
106}
diff --git a/arch/v850/kernel/rte_ma1_cb.ld b/arch/v850/kernel/rte_ma1_cb.ld
new file mode 100644
index 000000000000..c8e16d16be41
--- /dev/null
+++ b/arch/v850/kernel/rte_ma1_cb.ld
@@ -0,0 +1,57 @@
1/* Linker script for the Midas labs RTE-V850E/MA1-CB evaluation board
2 (CONFIG_RTE_CB_MA1), with kernel in SDRAM, under Multi debugger. */
3
4MEMORY {
5 /* 1MB of SRAM; we can't use the last 32KB, because it's used by
6 the monitor scratch-RAM. This memory is mirrored 4 times. */
7 SRAM : ORIGIN = SRAM_ADDR, LENGTH = (SRAM_SIZE - MON_SCRATCH_SIZE)
8 /* Monitor scratch RAM; only the interrupt vectors should go here. */
9 MRAM : ORIGIN = MON_SCRATCH_ADDR, LENGTH = MON_SCRATCH_SIZE
10 /* 32MB of SDRAM. */
11 SDRAM : ORIGIN = SDRAM_ADDR, LENGTH = SDRAM_SIZE
12}
13
14#ifdef CONFIG_RTE_CB_MA1_KSRAM
15# define KRAM SRAM
16#else
17# define KRAM SDRAM
18#endif
19
20SECTIONS {
21 /* We can't use RAMK_KRAM_CONTENTS because that puts the whole
22 kernel in a single ELF segment, and the Multi debugger (which
23 we use to load the kernel) appears to have bizarre problems
24 dealing with it. */
25
26 .text : {
27 __kram_start = . ;
28 TEXT_CONTENTS
29 } > KRAM
30
31 .data : {
32 DATA_CONTENTS
33 BSS_CONTENTS
34 RAMK_INIT_CONTENTS
35 __kram_end = . ;
36 BOOTMAP_CONTENTS
37
38 /* The address at which the interrupt vectors are initially
39 loaded by the loader. We can't load the interrupt vectors
40 directly into their target location, because the monitor
41 ROM for the GHS Multi debugger barfs if we try.
42 Unfortunately, Multi also doesn't deal correctly with ELF
43 sections where the LMA and VMA differ (it just ignores the
44 LMA), so we can't use that feature to work around the
45 problem! What we do instead is just put the interrupt
46 vectors into a normal section, and have the
47 `mach_early_init' function for Midas boards do the
48 necessary copying and relocation at runtime (this section
49 basically only contains `jr' instructions, so it's not
50 that hard). */
51 . = ALIGN (0x10) ;
52 __intv_load_start = . ;
53 INTV_CONTENTS
54 } > KRAM
55
56 .root ALIGN (4096) : { ROOT_FS_CONTENTS } > SDRAM
57}
diff --git a/arch/v850/kernel/rte_mb_a_pci.c b/arch/v850/kernel/rte_mb_a_pci.c
new file mode 100644
index 000000000000..074b50abc89d
--- /dev/null
+++ b/arch/v850/kernel/rte_mb_a_pci.c
@@ -0,0 +1,796 @@
1/*
2 * arch/v850/kernel/mb_a_pci.c -- PCI support for Midas lab RTE-MOTHER-A board
3 *
4 * Copyright (C) 2001,02,03 NEC Electronics Corporation
5 * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14#include <linux/config.h>
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/init.h>
18#include <linux/slab.h>
19#include <linux/spinlock.h>
20#include <linux/pci.h>
21
22#include <asm/machdep.h>
23
24/* __nomods_init is like __devinit, but is a no-op when modules are enabled.
25 This is used by some routines that can be called either during boot
26 or by a module. */
27#ifdef CONFIG_MODULES
28#define __nomods_init /*nothing*/
29#else
30#define __nomods_init __devinit
31#endif
32
33/* PCI devices on the Mother-A board can only do DMA to/from the MB SRAM
34 (the RTE-V850E/MA1-CB cpu board doesn't support PCI access to
35 CPU-board memory), and since linux DMA buffers are allocated in
36 normal kernel memory, we basically have to copy DMA blocks around
37 (this is like a `bounce buffer'). When a DMA block is `mapped', we
38 allocate an identically sized block in MB SRAM, and if we're doing
39 output to the device, copy the CPU-memory block to the MB-SRAM block.
40 When an active block is `unmapped', we will copy the block back to
41 CPU memory if necessary, and then deallocate the MB SRAM block.
42 Ack. */
43
44/* Where the motherboard SRAM is in the PCI-bus address space (the
45 first 512K of it is also mapped at PCI address 0). */
46#define PCI_MB_SRAM_ADDR 0x800000
47
48/* Convert CPU-view MB SRAM address to/from PCI-view addresses of the
49 same memory. */
50#define MB_SRAM_TO_PCI(mb_sram_addr) \
51 ((dma_addr_t)mb_sram_addr - MB_A_SRAM_ADDR + PCI_MB_SRAM_ADDR)
52#define PCI_TO_MB_SRAM(pci_addr) \
53 (void *)(pci_addr - PCI_MB_SRAM_ADDR + MB_A_SRAM_ADDR)
54
55static void pcibios_assign_resources (void);
56
57struct mb_pci_dev_irq {
58 unsigned dev; /* PCI device number */
59 unsigned irq_base; /* First IRQ */
60 unsigned query_pin; /* True if we should read the device's
61 Interrupt Pin info, and allocate
62 interrupt IRQ_BASE + PIN. */
63};
64
65/* PCI interrupts are mapped statically to GBUS interrupts. */
66static struct mb_pci_dev_irq mb_pci_dev_irqs[] = {
67 /* Motherboard SB82558 ethernet controller */
68 { 10, IRQ_MB_A_LAN, 0 },
69 /* PCI slot 1 */
70 { 8, IRQ_MB_A_PCI1(0), 1 },
71 /* PCI slot 2 */
72 { 9, IRQ_MB_A_PCI2(0), 1 }
73};
74#define NUM_MB_PCI_DEV_IRQS \
75 (sizeof mb_pci_dev_irqs / sizeof mb_pci_dev_irqs[0])
76
77
78/* PCI configuration primitives. */
79
80#define CONFIG_DMCFGA(bus, devfn, offs) \
81 (0x80000000 \
82 | ((offs) & ~0x3) \
83 | ((devfn) << 8) \
84 | ((bus)->number << 16))
85
86static int
87mb_pci_read (struct pci_bus *bus, unsigned devfn, int offs, int size, u32 *rval)
88{
89 u32 addr;
90 int flags;
91
92 local_irq_save (flags);
93
94 MB_A_PCI_PCICR = 0x7;
95 MB_A_PCI_DMCFGA = CONFIG_DMCFGA (bus, devfn, offs);
96
97 addr = MB_A_PCI_IO_ADDR + (offs & 0x3);
98
99 switch (size) {
100 case 1: *rval = *(volatile u8 *)addr; break;
101 case 2: *rval = *(volatile u16 *)addr; break;
102 case 4: *rval = *(volatile u32 *)addr; break;
103 }
104
105 if (MB_A_PCI_PCISR & 0x2000) {
106 MB_A_PCI_PCISR = 0x2000;
107 *rval = ~0;
108 }
109
110 MB_A_PCI_DMCFGA = 0;
111
112 local_irq_restore (flags);
113
114 return PCIBIOS_SUCCESSFUL;
115}
116
117static int
118mb_pci_write (struct pci_bus *bus, unsigned devfn, int offs, int size, u32 val)
119{
120 u32 addr;
121 int flags;
122
123 local_irq_save (flags);
124
125 MB_A_PCI_PCICR = 0x7;
126 MB_A_PCI_DMCFGA = CONFIG_DMCFGA (bus, devfn, offs);
127
128 addr = MB_A_PCI_IO_ADDR + (offs & 0x3);
129
130 switch (size) {
131 case 1: *(volatile u8 *)addr = val; break;
132 case 2: *(volatile u16 *)addr = val; break;
133 case 4: *(volatile u32 *)addr = val; break;
134 }
135
136 if (MB_A_PCI_PCISR & 0x2000)
137 MB_A_PCI_PCISR = 0x2000;
138
139 MB_A_PCI_DMCFGA = 0;
140
141 local_irq_restore (flags);
142
143 return PCIBIOS_SUCCESSFUL;
144}
145
146static struct pci_ops mb_pci_config_ops = {
147 .read = mb_pci_read,
148 .write = mb_pci_write,
149};
150
151
152/* PCI Initialization. */
153
154static struct pci_bus *mb_pci_bus = 0;
155
156/* Do initial PCI setup. */
157static int __devinit pcibios_init (void)
158{
159 u32 id = MB_A_PCI_PCIHIDR;
160 u16 vendor = id & 0xFFFF;
161 u16 device = (id >> 16) & 0xFFFF;
162
163 if (vendor == PCI_VENDOR_ID_PLX && device == PCI_DEVICE_ID_PLX_9080) {
164 printk (KERN_INFO
165 "PCI: PLX Technology PCI9080 HOST/PCI bridge\n");
166
167 MB_A_PCI_PCICR = 0x147;
168
169 MB_A_PCI_PCIBAR0 = 0x007FFF00;
170 MB_A_PCI_PCIBAR1 = 0x0000FF00;
171 MB_A_PCI_PCIBAR2 = 0x00800000;
172
173 MB_A_PCI_PCILTR = 0x20;
174
175 MB_A_PCI_PCIPBAM |= 0x3;
176
177 MB_A_PCI_PCISR = ~0; /* Clear errors. */
178
179 /* Reprogram the motherboard's IO/config address space,
180 as we don't support the GCS7 address space that the
181 default uses. */
182
183 /* Significant address bits used for decoding PCI GCS5 space
184 accessess. */
185 MB_A_PCI_DMRR = ~(MB_A_PCI_MEM_SIZE - 1);
186
187 /* I don't understand this, but the SolutionGear example code
188 uses such an offset, and it doesn't work without it. XXX */
189#if GCS5_SIZE == 0x00800000
190#define GCS5_CFG_OFFS 0x00800000
191#else
192#define GCS5_CFG_OFFS 0
193#endif
194
195 /* Address bit values for matching. Note that we have to give
196 the address from the motherboard's point of view, which is
197 different than the CPU's. */
198 /* PCI memory space. */
199 MB_A_PCI_DMLBAM = GCS5_CFG_OFFS + 0x0;
200 /* PCI I/O space. */
201 MB_A_PCI_DMLBAI =
202 GCS5_CFG_OFFS + (MB_A_PCI_IO_ADDR - GCS5_ADDR);
203
204 mb_pci_bus = pci_scan_bus (0, &mb_pci_config_ops, 0);
205
206 pcibios_assign_resources ();
207 } else
208 printk (KERN_ERR "PCI: HOST/PCI bridge not found\n");
209
210 return 0;
211}
212
213subsys_initcall (pcibios_init);
214
215char __devinit *pcibios_setup (char *option)
216{
217 /* Don't handle any options. */
218 return option;
219}
220
221
222int __nomods_init pcibios_enable_device (struct pci_dev *dev, int mask)
223{
224 u16 cmd, old_cmd;
225 int idx;
226 struct resource *r;
227
228 pci_read_config_word(dev, PCI_COMMAND, &cmd);
229 old_cmd = cmd;
230 for (idx = 0; idx < 6; idx++) {
231 r = &dev->resource[idx];
232 if (!r->start && r->end) {
233 printk(KERN_ERR "PCI: Device %s not available because "
234 "of resource collisions\n", pci_name(dev));
235 return -EINVAL;
236 }
237 if (r->flags & IORESOURCE_IO)
238 cmd |= PCI_COMMAND_IO;
239 if (r->flags & IORESOURCE_MEM)
240 cmd |= PCI_COMMAND_MEMORY;
241 }
242 if (cmd != old_cmd) {
243 printk("PCI: Enabling device %s (%04x -> %04x)\n",
244 pci_name(dev), old_cmd, cmd);
245 pci_write_config_word(dev, PCI_COMMAND, cmd);
246 }
247 return 0;
248}
249
250
251/* Resource allocation. */
252static void __devinit pcibios_assign_resources (void)
253{
254 struct pci_dev *dev = NULL;
255 struct resource *r;
256
257 for_each_pci_dev(dev) {
258 unsigned di_num;
259 unsigned class = dev->class >> 8;
260
261 if (class && class != PCI_CLASS_BRIDGE_HOST) {
262 unsigned r_num;
263 for(r_num = 0; r_num < 6; r_num++) {
264 r = &dev->resource[r_num];
265 if (!r->start && r->end)
266 pci_assign_resource (dev, r_num);
267 }
268 }
269
270 /* Assign interrupts. */
271 for (di_num = 0; di_num < NUM_MB_PCI_DEV_IRQS; di_num++) {
272 struct mb_pci_dev_irq *di = &mb_pci_dev_irqs[di_num];
273
274 if (di->dev == PCI_SLOT (dev->devfn)) {
275 unsigned irq = di->irq_base;
276
277 if (di->query_pin) {
278 /* Find out which interrupt pin
279 this device uses (each PCI
280 slot has 4). */
281 u8 irq_pin;
282
283 pci_read_config_byte (dev,
284 PCI_INTERRUPT_PIN,
285 &irq_pin);
286
287 if (irq_pin == 0)
288 /* Doesn't use interrupts. */
289 continue;
290 else
291 irq += irq_pin - 1;
292 }
293
294 pcibios_update_irq (dev, irq);
295 }
296 }
297 }
298}
299
300void __devinit pcibios_update_irq (struct pci_dev *dev, int irq)
301{
302 dev->irq = irq;
303 pci_write_config_byte (dev, PCI_INTERRUPT_LINE, irq);
304}
305
306void __devinit
307pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
308 struct resource *res)
309{
310 unsigned long offset = 0;
311
312 if (res->flags & IORESOURCE_IO) {
313 offset = MB_A_PCI_IO_ADDR;
314 } else if (res->flags & IORESOURCE_MEM) {
315 offset = MB_A_PCI_MEM_ADDR;
316 }
317
318 region->start = res->start - offset;
319 region->end = res->end - offset;
320}
321
322
323/* Stubs for things we don't use. */
324
325/* Called after each bus is probed, but before its children are examined. */
326void pcibios_fixup_bus(struct pci_bus *b)
327{
328}
329
330void
331pcibios_align_resource (void *data, struct resource *res,
332 unsigned long size, unsigned long align)
333{
334}
335
336void pcibios_set_master (struct pci_dev *dev)
337{
338}
339
340
341/* Mother-A SRAM memory allocation. This is a simple first-fit allocator. */
342
343/* A memory free-list node. */
344struct mb_sram_free_area {
345 void *mem;
346 unsigned long size;
347 struct mb_sram_free_area *next;
348};
349
350/* The tail of the free-list, which starts out containing all the SRAM. */
351static struct mb_sram_free_area mb_sram_free_tail = {
352 (void *)MB_A_SRAM_ADDR, MB_A_SRAM_SIZE, 0
353};
354
355/* The free-list. */
356static struct mb_sram_free_area *mb_sram_free_areas = &mb_sram_free_tail;
357
358/* The free-list of free free-list nodes. (:-) */
359static struct mb_sram_free_area *mb_sram_free_free_areas = 0;
360
361/* Spinlock protecting the above globals. */
362static DEFINE_SPINLOCK(mb_sram_lock);
363
364/* Allocate a memory block at least SIZE bytes long in the Mother-A SRAM
365 space. */
366static void *alloc_mb_sram (size_t size)
367{
368 struct mb_sram_free_area *prev, *fa;
369 int flags;
370 void *mem = 0;
371
372 spin_lock_irqsave (mb_sram_lock, flags);
373
374 /* Look for a free area that can contain SIZE bytes. */
375 for (prev = 0, fa = mb_sram_free_areas; fa; prev = fa, fa = fa->next)
376 if (fa->size >= size) {
377 /* Found one! */
378 mem = fa->mem;
379
380 if (fa->size == size) {
381 /* In fact, it fits exactly, so remove
382 this node from the free-list. */
383 if (prev)
384 prev->next = fa->next;
385 else
386 mb_sram_free_areas = fa->next;
387 /* Put it on the free-list-entry-free-list. */
388 fa->next = mb_sram_free_free_areas;
389 mb_sram_free_free_areas = fa;
390 } else {
391 /* FA is bigger than SIZE, so just
392 reduce its size to account for this
393 allocation. */
394 fa->mem += size;
395 fa->size -= size;
396 }
397
398 break;
399 }
400
401 spin_unlock_irqrestore (mb_sram_lock, flags);
402
403 return mem;
404}
405
406/* Return the memory area MEM of size SIZE to the MB SRAM free pool. */
407static void free_mb_sram (void *mem, size_t size)
408{
409 struct mb_sram_free_area *prev, *fa, *new_fa;
410 int flags;
411 void *end = mem + size;
412
413 spin_lock_irqsave (mb_sram_lock, flags);
414
415 retry:
416 /* Find an adjacent free-list entry. */
417 for (prev = 0, fa = mb_sram_free_areas; fa; prev = fa, fa = fa->next)
418 if (fa->mem == end) {
419 /* FA is just after MEM, grow down to encompass it. */
420 fa->mem = mem;
421 fa->size += size;
422 goto done;
423 } else if (fa->mem + fa->size == mem) {
424 struct mb_sram_free_area *next_fa = fa->next;
425
426 /* FA is just before MEM, expand to encompass it. */
427 fa->size += size;
428
429 /* See if FA can now be merged with its successor. */
430 if (next_fa && fa->mem + fa->size == next_fa->mem) {
431 /* Yup; merge NEXT_FA's info into FA. */
432 fa->size += next_fa->size;
433 fa->next = next_fa->next;
434 /* Free NEXT_FA. */
435 next_fa->next = mb_sram_free_free_areas;
436 mb_sram_free_free_areas = next_fa;
437 }
438 goto done;
439 } else if (fa->mem > mem)
440 /* We've reached the right spot in the free-list
441 without finding an adjacent free-area, so add
442 a new free area to hold mem. */
443 break;
444
445 /* Make a new free-list entry. */
446
447 /* First, get a free-list entry. */
448 if (! mb_sram_free_free_areas) {
449 /* There are none, so make some. */
450 void *block;
451 size_t block_size = sizeof (struct mb_sram_free_area) * 8;
452
453 /* Don't hold the lock while calling kmalloc (I'm not
454 sure whether it would be a problem, since we use
455 GFP_ATOMIC, but it makes me nervous). */
456 spin_unlock_irqrestore (mb_sram_lock, flags);
457
458 block = kmalloc (block_size, GFP_ATOMIC);
459 if (! block)
460 panic ("free_mb_sram: can't allocate free-list entry");
461
462 /* Now get the lock back. */
463 spin_lock_irqsave (mb_sram_lock, flags);
464
465 /* Add the new free free-list entries. */
466 while (block_size > 0) {
467 struct mb_sram_free_area *nfa = block;
468 nfa->next = mb_sram_free_free_areas;
469 mb_sram_free_free_areas = nfa;
470 block += sizeof *nfa;
471 block_size -= sizeof *nfa;
472 }
473
474 /* Since we dropped the lock to call kmalloc, the
475 free-list could have changed, so retry from the
476 beginning. */
477 goto retry;
478 }
479
480 /* Remove NEW_FA from the free-list of free-list entries. */
481 new_fa = mb_sram_free_free_areas;
482 mb_sram_free_free_areas = new_fa->next;
483
484 /* NEW_FA initially holds only MEM. */
485 new_fa->mem = mem;
486 new_fa->size = size;
487
488 /* Insert NEW_FA in the free-list between PREV and FA. */
489 new_fa->next = fa;
490 if (prev)
491 prev->next = new_fa;
492 else
493 mb_sram_free_areas = new_fa;
494
495 done:
496 spin_unlock_irqrestore (mb_sram_lock, flags);
497}
498
499
500/* Maintainence of CPU -> Mother-A DMA mappings. */
501
502struct dma_mapping {
503 void *cpu_addr;
504 void *mb_sram_addr;
505 size_t size;
506 struct dma_mapping *next;
507};
508
509/* A list of mappings from CPU addresses to MB SRAM addresses for active
510 DMA blocks (that have been `granted' to the PCI device). */
511static struct dma_mapping *active_dma_mappings = 0;
512
513/* A list of free mapping objects. */
514static struct dma_mapping *free_dma_mappings = 0;
515
516/* Spinlock protecting the above globals. */
517static DEFINE_SPINLOCK(dma_mappings_lock);
518
519static struct dma_mapping *new_dma_mapping (size_t size)
520{
521 int flags;
522 struct dma_mapping *mapping;
523 void *mb_sram_block = alloc_mb_sram (size);
524
525 if (! mb_sram_block)
526 return 0;
527
528 spin_lock_irqsave (dma_mappings_lock, flags);
529
530 if (! free_dma_mappings) {
531 /* We're out of mapping structures, make more. */
532 void *mblock;
533 size_t mblock_size = sizeof (struct dma_mapping) * 8;
534
535 /* Don't hold the lock while calling kmalloc (I'm not
536 sure whether it would be a problem, since we use
537 GFP_ATOMIC, but it makes me nervous). */
538 spin_unlock_irqrestore (dma_mappings_lock, flags);
539
540 mblock = kmalloc (mblock_size, GFP_ATOMIC);
541 if (! mblock) {
542 free_mb_sram (mb_sram_block, size);
543 return 0;
544 }
545
546 /* Get the lock back. */
547 spin_lock_irqsave (dma_mappings_lock, flags);
548
549 /* Add the new mapping structures to the free-list. */
550 while (mblock_size > 0) {
551 struct dma_mapping *fm = mblock;
552 fm->next = free_dma_mappings;
553 free_dma_mappings = fm;
554 mblock += sizeof *fm;
555 mblock_size -= sizeof *fm;
556 }
557 }
558
559 /* Get a mapping struct from the freelist. */
560 mapping = free_dma_mappings;
561 free_dma_mappings = mapping->next;
562
563 /* Initialize the mapping. Other fields should be filled in by
564 caller. */
565 mapping->mb_sram_addr = mb_sram_block;
566 mapping->size = size;
567
568 /* Add it to the list of active mappings. */
569 mapping->next = active_dma_mappings;
570 active_dma_mappings = mapping;
571
572 spin_unlock_irqrestore (dma_mappings_lock, flags);
573
574 return mapping;
575}
576
577static struct dma_mapping *find_dma_mapping (void *mb_sram_addr)
578{
579 int flags;
580 struct dma_mapping *mapping;
581
582 spin_lock_irqsave (dma_mappings_lock, flags);
583
584 for (mapping = active_dma_mappings; mapping; mapping = mapping->next)
585 if (mapping->mb_sram_addr == mb_sram_addr) {
586 spin_unlock_irqrestore (dma_mappings_lock, flags);
587 return mapping;
588 }
589
590 panic ("find_dma_mapping: unmapped PCI DMA addr 0x%x",
591 MB_SRAM_TO_PCI (mb_sram_addr));
592}
593
594static struct dma_mapping *deactivate_dma_mapping (void *mb_sram_addr)
595{
596 int flags;
597 struct dma_mapping *mapping, *prev;
598
599 spin_lock_irqsave (dma_mappings_lock, flags);
600
601 for (prev = 0, mapping = active_dma_mappings;
602 mapping;
603 prev = mapping, mapping = mapping->next)
604 {
605 if (mapping->mb_sram_addr == mb_sram_addr) {
606 /* This is the MAPPING; deactivate it. */
607 if (prev)
608 prev->next = mapping->next;
609 else
610 active_dma_mappings = mapping->next;
611
612 spin_unlock_irqrestore (dma_mappings_lock, flags);
613
614 return mapping;
615 }
616 }
617
618 panic ("deactivate_dma_mapping: unmapped PCI DMA addr 0x%x",
619 MB_SRAM_TO_PCI (mb_sram_addr));
620}
621
622/* Return MAPPING to the freelist. */
623static inline void
624free_dma_mapping (struct dma_mapping *mapping)
625{
626 int flags;
627
628 free_mb_sram (mapping->mb_sram_addr, mapping->size);
629
630 spin_lock_irqsave (dma_mappings_lock, flags);
631
632 mapping->next = free_dma_mappings;
633 free_dma_mappings = mapping;
634
635 spin_unlock_irqrestore (dma_mappings_lock, flags);
636}
637
638
639/* Single PCI DMA mappings. */
640
641/* `Grant' to PDEV the memory block at CPU_ADDR, for doing DMA. The
642 32-bit PCI bus mastering address to use is returned. the device owns
643 this memory until either pci_unmap_single or pci_dma_sync_single is
644 performed. */
645dma_addr_t
646pci_map_single (struct pci_dev *pdev, void *cpu_addr, size_t size, int dir)
647{
648 struct dma_mapping *mapping = new_dma_mapping (size);
649
650 if (! mapping)
651 return 0;
652
653 mapping->cpu_addr = cpu_addr;
654
655 if (dir == PCI_DMA_BIDIRECTIONAL || dir == PCI_DMA_TODEVICE)
656 memcpy (mapping->mb_sram_addr, cpu_addr, size);
657
658 return MB_SRAM_TO_PCI (mapping->mb_sram_addr);
659}
660
661/* Return to the CPU the PCI DMA memory block previously `granted' to
662 PDEV, at DMA_ADDR. */
663void pci_unmap_single (struct pci_dev *pdev, dma_addr_t dma_addr, size_t size,
664 int dir)
665{
666 void *mb_sram_addr = PCI_TO_MB_SRAM (dma_addr);
667 struct dma_mapping *mapping = deactivate_dma_mapping (mb_sram_addr);
668
669 if (size != mapping->size)
670 panic ("pci_unmap_single: size (%d) doesn't match"
671 " size of mapping at PCI DMA addr 0x%x (%d)\n",
672 size, dma_addr, mapping->size);
673
674 /* Copy back the DMA'd contents if necessary. */
675 if (dir == PCI_DMA_BIDIRECTIONAL || dir == PCI_DMA_FROMDEVICE)
676 memcpy (mapping->cpu_addr, mb_sram_addr, size);
677
678 /* Return mapping to the freelist. */
679 free_dma_mapping (mapping);
680}
681
682/* Make physical memory consistent for a single streaming mode DMA
683 translation after a transfer.
684
685 If you perform a pci_map_single() but wish to interrogate the
686 buffer using the cpu, yet do not wish to teardown the PCI dma
687 mapping, you must call this function before doing so. At the next
688 point you give the PCI dma address back to the card, you must first
689 perform a pci_dma_sync_for_device, and then the device again owns
690 the buffer. */
691void
692pci_dma_sync_single_for_cpu (struct pci_dev *pdev, dma_addr_t dma_addr, size_t size,
693 int dir)
694{
695 void *mb_sram_addr = PCI_TO_MB_SRAM (dma_addr);
696 struct dma_mapping *mapping = find_dma_mapping (mb_sram_addr);
697
698 /* Synchronize the DMA buffer with the CPU buffer if necessary. */
699 if (dir == PCI_DMA_FROMDEVICE)
700 memcpy (mapping->cpu_addr, mb_sram_addr, size);
701 else if (dir == PCI_DMA_TODEVICE)
702 ; /* nothing to do */
703 else
704 panic("pci_dma_sync_single: unsupported sync dir: %d", dir);
705}
706
707void
708pci_dma_sync_single_for_device (struct pci_dev *pdev, dma_addr_t dma_addr, size_t size,
709 int dir)
710{
711 void *mb_sram_addr = PCI_TO_MB_SRAM (dma_addr);
712 struct dma_mapping *mapping = find_dma_mapping (mb_sram_addr);
713
714 /* Synchronize the DMA buffer with the CPU buffer if necessary. */
715 if (dir == PCI_DMA_FROMDEVICE)
716 ; /* nothing to do */
717 else if (dir == PCI_DMA_TODEVICE)
718 memcpy (mb_sram_addr, mapping->cpu_addr, size);
719 else
720 panic("pci_dma_sync_single: unsupported sync dir: %d", dir);
721}
722
723
724/* Scatter-gather PCI DMA mappings. */
725
726/* Do multiple DMA mappings at once. */
727int
728pci_map_sg (struct pci_dev *pdev, struct scatterlist *sg, int sg_len, int dir)
729{
730 BUG ();
731 return 0;
732}
733
734/* Unmap multiple DMA mappings at once. */
735void
736pci_unmap_sg (struct pci_dev *pdev, struct scatterlist *sg, int sg_len,int dir)
737{
738 BUG ();
739}
740
741/* Make physical memory consistent for a set of streaming mode DMA
742 translations after a transfer. The same as pci_dma_sync_single_* but
743 for a scatter-gather list, same rules and usage. */
744
745void
746pci_dma_sync_sg_for_cpu (struct pci_dev *dev, struct scatterlist *sg, int sg_len,
747 int dir)
748{
749 BUG ();
750}
751
752void
753pci_dma_sync_sg_for_device (struct pci_dev *dev, struct scatterlist *sg, int sg_len,
754 int dir)
755{
756 BUG ();
757}
758
759
760/* PCI mem mapping. */
761
762/* Allocate and map kernel buffer using consistent mode DMA for PCI
763 device. Returns non-NULL cpu-view pointer to the buffer if
764 successful and sets *DMA_ADDR to the pci side dma address as well,
765 else DMA_ADDR is undefined. */
766void *
767pci_alloc_consistent (struct pci_dev *pdev, size_t size, dma_addr_t *dma_addr)
768{
769 void *mb_sram_mem = alloc_mb_sram (size);
770 if (mb_sram_mem)
771 *dma_addr = MB_SRAM_TO_PCI (mb_sram_mem);
772 return mb_sram_mem;
773}
774
775/* Free and unmap a consistent DMA buffer. CPU_ADDR and DMA_ADDR must
776 be values that were returned from pci_alloc_consistent. SIZE must be
777 the same as what as passed into pci_alloc_consistent. References to
778 the memory and mappings assosciated with CPU_ADDR or DMA_ADDR past
779 this call are illegal. */
780void
781pci_free_consistent (struct pci_dev *pdev, size_t size, void *cpu_addr,
782 dma_addr_t dma_addr)
783{
784 void *mb_sram_mem = PCI_TO_MB_SRAM (dma_addr);
785 free_mb_sram (mb_sram_mem, size);
786}
787
788
789/* symbol exports (for modules) */
790
791EXPORT_SYMBOL (pci_map_single);
792EXPORT_SYMBOL (pci_unmap_single);
793EXPORT_SYMBOL (pci_alloc_consistent);
794EXPORT_SYMBOL (pci_free_consistent);
795EXPORT_SYMBOL (pci_dma_sync_single_for_cpu);
796EXPORT_SYMBOL (pci_dma_sync_single_for_device);
diff --git a/arch/v850/kernel/rte_me2_cb.c b/arch/v850/kernel/rte_me2_cb.c
new file mode 100644
index 000000000000..faaf3d95e6cf
--- /dev/null
+++ b/arch/v850/kernel/rte_me2_cb.c
@@ -0,0 +1,300 @@
1/*
2 * arch/v850/kernel/rte_me2_cb.c -- Midas labs RTE-V850E/ME2-CB board
3 *
4 * Copyright (C) 2001,02,03 NEC Electronics Corporation
5 * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14#include <linux/config.h>
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <linux/bootmem.h>
18#include <linux/irq.h>
19#include <linux/fs.h>
20#include <linux/major.h>
21#include <linux/sched.h>
22#include <linux/delay.h>
23
24#include <asm/atomic.h>
25#include <asm/page.h>
26#include <asm/me2.h>
27#include <asm/rte_me2_cb.h>
28#include <asm/machdep.h>
29#include <asm/v850e_intc.h>
30#include <asm/v850e_cache.h>
31#include <asm/irq.h>
32
33#include "mach.h"
34
35extern unsigned long *_intv_start;
36extern unsigned long *_intv_end;
37
38/* LED access routines. */
39extern unsigned read_leds (int pos, char *buf, int len);
40extern unsigned write_leds (int pos, const char *buf, int len);
41
42
43/* SDRAM are almost contiguous (with a small hole in between;
44 see mach_reserve_bootmem for details), so just use both as one big area. */
45#define RAM_START SDRAM_ADDR
46#define RAM_END (SDRAM_ADDR + SDRAM_SIZE)
47
48
49void __init mach_get_physical_ram (unsigned long *ram_start,
50 unsigned long *ram_len)
51{
52 *ram_start = RAM_START;
53 *ram_len = RAM_END - RAM_START;
54}
55
56void mach_gettimeofday (struct timespec *tv)
57{
58 tv->tv_sec = 0;
59 tv->tv_nsec = 0;
60}
61
62/* Called before configuring an on-chip UART. */
63void rte_me2_cb_uart_pre_configure (unsigned chan,
64 unsigned cflags, unsigned baud)
65{
66 /* The RTE-V850E/ME2-CB connects some general-purpose I/O
67 pins on the CPU to the RTS/CTS lines of UARTB channel 0's
68 serial connection.
69 I/O pins P21 and P22 are RTS and CTS respectively. */
70 if (chan == 0) {
71 /* Put P21 & P22 in I/O port mode. */
72 ME2_PORT2_PMC &= ~0x6;
73 /* Make P21 and output, and P22 an input. */
74 ME2_PORT2_PM = (ME2_PORT2_PM & ~0xC) | 0x4;
75 }
76
77 me2_uart_pre_configure (chan, cflags, baud);
78}
79
80void __init mach_init_irqs (void)
81{
82 /* Initialize interrupts. */
83 me2_init_irqs ();
84 rte_me2_cb_init_irqs ();
85}
86
87#ifdef CONFIG_ROM_KERNEL
88/* Initialization for kernel in ROM. */
89static inline rom_kernel_init (void)
90{
91 /* If the kernel is in ROM, we have to copy any initialized data
92 from ROM into RAM. */
93 extern unsigned long _data_load_start, _sdata, _edata;
94 register unsigned long *src = &_data_load_start;
95 register unsigned long *dst = &_sdata, *end = &_edata;
96
97 while (dst != end)
98 *dst++ = *src++;
99}
100#endif /* CONFIG_ROM_KERNEL */
101
102static void install_interrupt_vectors (void)
103{
104 unsigned long *p1, *p2;
105
106 ME2_IRAMM = 0x03; /* V850E/ME2 iRAM write mode */
107
108 /* vector copy to iRAM */
109 p1 = (unsigned long *)0; /* v85x vector start */
110 p2 = (unsigned long *)&_intv_start;
111 while (p2 < (unsigned long *)&_intv_end)
112 *p1++ = *p2++;
113
114 ME2_IRAMM = 0x00; /* V850E/ME2 iRAM read mode */
115}
116
117/* CompactFlash */
118
119static void cf_power_on (void)
120{
121 /* CF card detected? */
122 if (CB_CF_STS0 & 0x0030)
123 return;
124
125 CB_CF_REG0 = 0x0002; /* reest on */
126 mdelay (10);
127 CB_CF_REG0 = 0x0003; /* power on */
128 mdelay (10);
129 CB_CF_REG0 = 0x0001; /* reset off */
130 mdelay (10);
131}
132
133static void cf_power_off (void)
134{
135 CB_CF_REG0 = 0x0003; /* power on */
136 mdelay (10);
137 CB_CF_REG0 = 0x0002; /* reest on */
138 mdelay (10);
139}
140
141void __init mach_early_init (void)
142{
143 install_interrupt_vectors ();
144
145 /* CS1 SDRAM instruction cache enable */
146 v850e_cache_enable (0x04, 0x03, 0);
147
148 rte_cb_early_init ();
149
150 /* CompactFlash power on */
151 cf_power_on ();
152
153#if defined (CONFIG_ROM_KERNEL)
154 rom_kernel_init ();
155#endif
156}
157
158
159/* RTE-V850E/ME2-CB Programmable Interrupt Controller. */
160
161static struct cb_pic_irq_init cb_pic_irq_inits[] = {
162 { "CB_EXTTM0", IRQ_CB_EXTTM0, 1, 1, 6 },
163 { "CB_EXTSIO", IRQ_CB_EXTSIO, 1, 1, 6 },
164 { "CB_TOVER", IRQ_CB_TOVER, 1, 1, 6 },
165 { "CB_GINT0", IRQ_CB_GINT0, 1, 1, 6 },
166 { "CB_USB", IRQ_CB_USB, 1, 1, 6 },
167 { "CB_LANC", IRQ_CB_LANC, 1, 1, 6 },
168 { "CB_USB_VBUS_ON", IRQ_CB_USB_VBUS_ON, 1, 1, 6 },
169 { "CB_USB_VBUS_OFF", IRQ_CB_USB_VBUS_OFF, 1, 1, 6 },
170 { "CB_EXTTM1", IRQ_CB_EXTTM1, 1, 1, 6 },
171 { "CB_EXTTM2", IRQ_CB_EXTTM2, 1, 1, 6 },
172 { 0 }
173};
174#define NUM_CB_PIC_IRQ_INITS \
175 ((sizeof cb_pic_irq_inits / sizeof cb_pic_irq_inits[0]) - 1)
176
177static struct hw_interrupt_type cb_pic_hw_itypes[NUM_CB_PIC_IRQ_INITS];
178static unsigned char cb_pic_active_irqs = 0;
179
180void __init rte_me2_cb_init_irqs (void)
181{
182 cb_pic_init_irq_types (cb_pic_irq_inits, cb_pic_hw_itypes);
183
184 /* Initalize on board PIC1 (not PIC0) enable */
185 CB_PIC_INT0M = 0x0000;
186 CB_PIC_INT1M = 0x0000;
187 CB_PIC_INTR = 0x0000;
188 CB_PIC_INTEN |= CB_PIC_INT1EN;
189
190 ME2_PORT2_PMC |= 0x08; /* INTP23/SCK1 mode */
191 ME2_PORT2_PFC &= ~0x08; /* INTP23 mode */
192 ME2_INTR(2) &= ~0x08; /* INTP23 falling-edge detect */
193 ME2_INTF(2) &= ~0x08; /* " */
194
195 rte_cb_init_irqs (); /* gbus &c */
196}
197
198
199/* Enable interrupt handling for interrupt IRQ. */
200void cb_pic_enable_irq (unsigned irq)
201{
202 CB_PIC_INT1M |= 1 << (irq - CB_PIC_BASE_IRQ);
203}
204
205void cb_pic_disable_irq (unsigned irq)
206{
207 CB_PIC_INT1M &= ~(1 << (irq - CB_PIC_BASE_IRQ));
208}
209
210void cb_pic_shutdown_irq (unsigned irq)
211{
212 cb_pic_disable_irq (irq);
213
214 if (--cb_pic_active_irqs == 0)
215 free_irq (IRQ_CB_PIC, 0);
216
217 CB_PIC_INT1M &= ~(1 << (irq - CB_PIC_BASE_IRQ));
218}
219
220static irqreturn_t cb_pic_handle_irq (int irq, void *dev_id,
221 struct pt_regs *regs)
222{
223 irqreturn_t rval = IRQ_NONE;
224 unsigned status = CB_PIC_INTR;
225 unsigned enable = CB_PIC_INT1M;
226
227 /* Only pay attention to enabled interrupts. */
228 status &= enable;
229
230 CB_PIC_INTEN &= ~CB_PIC_INT1EN;
231
232 if (status) {
233 unsigned mask = 1;
234
235 irq = CB_PIC_BASE_IRQ;
236 do {
237 /* There's an active interrupt, find out which one,
238 and call its handler. */
239 while (! (status & mask)) {
240 irq++;
241 mask <<= 1;
242 }
243 status &= ~mask;
244
245 CB_PIC_INTR = mask;
246
247 /* Recursively call handle_irq to handle it. */
248 handle_irq (irq, regs);
249 rval = IRQ_HANDLED;
250 } while (status);
251 }
252
253 CB_PIC_INTEN |= CB_PIC_INT1EN;
254
255 return rval;
256}
257
258
259static void irq_nop (unsigned irq) { }
260
261static unsigned cb_pic_startup_irq (unsigned irq)
262{
263 int rval;
264
265 if (cb_pic_active_irqs == 0) {
266 rval = request_irq (IRQ_CB_PIC, cb_pic_handle_irq,
267 SA_INTERRUPT, "cb_pic_handler", 0);
268 if (rval != 0)
269 return rval;
270 }
271
272 cb_pic_active_irqs++;
273
274 cb_pic_enable_irq (irq);
275
276 return 0;
277}
278
279/* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array
280 INITS (which is terminated by an entry with the name field == 0). */
281void __init cb_pic_init_irq_types (struct cb_pic_irq_init *inits,
282 struct hw_interrupt_type *hw_irq_types)
283{
284 struct cb_pic_irq_init *init;
285 for (init = inits; init->name; init++) {
286 struct hw_interrupt_type *hwit = hw_irq_types++;
287
288 hwit->typename = init->name;
289
290 hwit->startup = cb_pic_startup_irq;
291 hwit->shutdown = cb_pic_shutdown_irq;
292 hwit->enable = cb_pic_enable_irq;
293 hwit->disable = cb_pic_disable_irq;
294 hwit->ack = irq_nop;
295 hwit->end = irq_nop;
296
297 /* Initialize kernel IRQ infrastructure for this interrupt. */
298 init_irq_handlers(init->base, init->num, init->interval, hwit);
299 }
300}
diff --git a/arch/v850/kernel/rte_me2_cb.ld b/arch/v850/kernel/rte_me2_cb.ld
new file mode 100644
index 000000000000..cf0766065ec6
--- /dev/null
+++ b/arch/v850/kernel/rte_me2_cb.ld
@@ -0,0 +1,30 @@
1/* Linker script for the Midas labs RTE-V850E/ME2-CB evaluation board
2 (CONFIG_RTE_CB_ME2), with kernel in SDRAM. */
3
4MEMORY {
5 /* 128Kbyte of IRAM */
6 IRAM : ORIGIN = 0x00000000, LENGTH = 0x00020000
7
8 /* 32MB of SDRAM. */
9 SDRAM : ORIGIN = SDRAM_ADDR, LENGTH = SDRAM_SIZE
10}
11
12#define KRAM SDRAM
13
14SECTIONS {
15 .text : {
16 __kram_start = . ;
17 TEXT_CONTENTS
18 INTV_CONTENTS /* copy to iRAM (0x0-0x620) */
19 } > KRAM
20
21 .data : {
22 DATA_CONTENTS
23 BSS_CONTENTS
24 RAMK_INIT_CONTENTS
25 __kram_end = . ;
26 BOOTMAP_CONTENTS
27 } > KRAM
28
29 .root ALIGN (4096) : { ROOT_FS_CONTENTS } > SDRAM
30}
diff --git a/arch/v850/kernel/rte_nb85e_cb-multi.ld b/arch/v850/kernel/rte_nb85e_cb-multi.ld
new file mode 100644
index 000000000000..de347b4fffac
--- /dev/null
+++ b/arch/v850/kernel/rte_nb85e_cb-multi.ld
@@ -0,0 +1,57 @@
1/* Linker script for the Midas labs RTE-NB85E-CB evaluation board
2 (CONFIG_RTE_CB_NB85E), with the Multi debugger ROM monitor . */
3
4MEMORY {
5 /* 1MB of SRAM; we can't use the last 96KB, because it's used by
6 the monitor scratch-RAM. This memory is mirrored 4 times. */
7 SRAM : ORIGIN = SRAM_ADDR, LENGTH = (SRAM_SIZE - MON_SCRATCH_SIZE)
8 /* Monitor scratch RAM; only the interrupt vectors should go here. */
9 MRAM : ORIGIN = MON_SCRATCH_ADDR, LENGTH = MON_SCRATCH_SIZE
10 /* 16MB of SDRAM. */
11 SDRAM : ORIGIN = SDRAM_ADDR, LENGTH = SDRAM_SIZE
12}
13
14#ifdef CONFIG_RTE_CB_NB85E_KSRAM
15# define KRAM SRAM
16#else
17# define KRAM SDRAM
18#endif
19
20SECTIONS {
21 /* We can't use RAMK_KRAM_CONTENTS because that puts the whole
22 kernel in a single ELF segment, and the Multi debugger (which
23 we use to load the kernel) appears to have bizarre problems
24 dealing with it. */
25
26 .text : {
27 __kram_start = . ;
28 TEXT_CONTENTS
29 } > KRAM
30
31 .data : {
32 DATA_CONTENTS
33 BSS_CONTENTS
34 RAMK_INIT_CONTENTS
35 __kram_end = . ;
36 BOOTMAP_CONTENTS
37
38 /* The address at which the interrupt vectors are initially
39 loaded by the loader. We can't load the interrupt vectors
40 directly into their target location, because the monitor
41 ROM for the GHS Multi debugger barfs if we try.
42 Unfortunately, Multi also doesn't deal correctly with ELF
43 sections where the LMA and VMA differ (it just ignores the
44 LMA), so we can't use that feature to work around the
45 problem! What we do instead is just put the interrupt
46 vectors into a normal section, and have the
47 `mach_early_init' function for Midas boards do the
48 necessary copying and relocation at runtime (this section
49 basically only contains `jr' instructions, so it's not
50 that hard). */
51 . = ALIGN (0x10) ;
52 __intv_load_start = . ;
53 INTV_CONTENTS
54 } > KRAM
55
56 .root ALIGN (4096) : { ROOT_FS_CONTENTS } > SDRAM
57}
diff --git a/arch/v850/kernel/rte_nb85e_cb.c b/arch/v850/kernel/rte_nb85e_cb.c
new file mode 100644
index 000000000000..990b20bffe47
--- /dev/null
+++ b/arch/v850/kernel/rte_nb85e_cb.c
@@ -0,0 +1,82 @@
1/*
2 * arch/v850/kernel/rte_nb85e_cb.c -- Midas labs RTE-V850E/NB85E-CB board
3 *
4 * Copyright (C) 2001,02,03 NEC Electronics Corporation
5 * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14#include <linux/config.h>
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <linux/mm.h>
18#include <linux/swap.h>
19#include <linux/bootmem.h>
20#include <linux/irq.h>
21
22#include <asm/atomic.h>
23#include <asm/page.h>
24#include <asm/v850e.h>
25#include <asm/rte_nb85e_cb.h>
26
27#include "mach.h"
28
29void __init mach_early_init (void)
30{
31 /* Configure caching; some possible settings:
32
33 BHC = 0x0000, DCC = 0x0000 -- all caching disabled
34 BHC = 0x0040, DCC = 0x0000 -- SDRAM: icache only
35 BHC = 0x0080, DCC = 0x0C00 -- SDRAM: write-back dcache only
36 BHC = 0x00C0, DCC = 0x0C00 -- SDRAM: icache + write-back dcache
37 BHC = 0x00C0, DCC = 0x0800 -- SDRAM: icache + write-thru dcache
38
39 We can only cache SDRAM (we can't use cache SRAM because it's in
40 the same memory region as the on-chip RAM and I/O space).
41
42 Unfortunately, the dcache seems to be buggy, so we only use the
43 icache for now. */
44 v850e_cache_enable (0x0040 /*BHC*/, 0x0003 /*ICC*/, 0x0000 /*DCC*/);
45
46 rte_cb_early_init ();
47}
48
49void __init mach_get_physical_ram (unsigned long *ram_start,
50 unsigned long *ram_len)
51{
52 /* We just use SDRAM here. */
53 *ram_start = SDRAM_ADDR;
54 *ram_len = SDRAM_SIZE;
55}
56
57void mach_gettimeofday (struct timespec *tv)
58{
59 tv->tv_sec = 0;
60 tv->tv_nsec = 0;
61}
62
63/* Called before configuring an on-chip UART. */
64void rte_nb85e_cb_uart_pre_configure (unsigned chan,
65 unsigned cflags, unsigned baud)
66{
67 /* The RTE-NB85E-CB connects some general-purpose I/O pins on the
68 CPU to the RTS/CTS lines the UART's serial connection, as follows:
69 P00 = CTS (in), P01 = DSR (in), P02 = RTS (out), P03 = DTR (out). */
70
71 TEG_PORT0_PM = 0x03; /* P00 and P01 inputs, P02 and P03 outputs */
72 TEG_PORT0_IO = 0x03; /* Accept input */
73
74 /* Do pre-configuration for the actual UART. */
75 teg_uart_pre_configure (chan, cflags, baud);
76}
77
78void __init mach_init_irqs (void)
79{
80 teg_init_irqs ();
81 rte_cb_init_irqs ();
82}
diff --git a/arch/v850/kernel/rte_nb85e_cb.ld b/arch/v850/kernel/rte_nb85e_cb.ld
new file mode 100644
index 000000000000..b672f484f085
--- /dev/null
+++ b/arch/v850/kernel/rte_nb85e_cb.ld
@@ -0,0 +1,22 @@
1/* Linker script for the Midas labs RTE-NB85E-CB evaluation board
2 (CONFIG_RTE_CB_NB85E). */
3
4MEMORY {
5 LOW : ORIGIN = 0x0, LENGTH = 0x00100000
6 /* 1MB of SRAM This memory is mirrored 4 times. */
7 SRAM : ORIGIN = SRAM_ADDR, LENGTH = SRAM_SIZE
8 /* 16MB of SDRAM. */
9 SDRAM : ORIGIN = SDRAM_ADDR, LENGTH = SDRAM_SIZE
10}
11
12#ifdef CONFIG_RTE_CB_NB85E_KSRAM
13# define KRAM SRAM
14#else
15# define KRAM SDRAM
16#endif
17
18SECTIONS {
19 .intv : { INTV_CONTENTS } > LOW
20 .sram : { RAMK_KRAM_CONTENTS } > KRAM
21 .root : { ROOT_FS_CONTENTS } > SDRAM
22}
diff --git a/arch/v850/kernel/semaphore.c b/arch/v850/kernel/semaphore.c
new file mode 100644
index 000000000000..fc89fd661c99
--- /dev/null
+++ b/arch/v850/kernel/semaphore.c
@@ -0,0 +1,166 @@
1/*
2 * arch/v850/kernel/semaphore.c -- Semaphore support
3 *
4 * Copyright (C) 1998-2000 IBM Corporation
5 * Copyright (C) 1999 Linus Torvalds
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * This file is a copy of the s390 version, arch/s390/kernel/semaphore.c
12 * Author(s): Martin Schwidefsky
13 * which was derived from the i386 version, linux/arch/i386/kernel/semaphore.c
14 */
15
16#include <linux/errno.h>
17#include <linux/sched.h>
18#include <linux/init.h>
19
20#include <asm/semaphore.h>
21
22/*
23 * Semaphores are implemented using a two-way counter:
24 * The "count" variable is decremented for each process
25 * that tries to acquire the semaphore, while the "sleeping"
26 * variable is a count of such acquires.
27 *
28 * Notably, the inline "up()" and "down()" functions can
29 * efficiently test if they need to do any extra work (up
30 * needs to do something only if count was negative before
31 * the increment operation.
32 *
33 * "sleeping" and the contention routine ordering is
34 * protected by the semaphore spinlock.
35 *
36 * Note that these functions are only called when there is
37 * contention on the lock, and as such all this is the
38 * "non-critical" part of the whole semaphore business. The
39 * critical part is the inline stuff in <asm/semaphore.h>
40 * where we want to avoid any extra jumps and calls.
41 */
42
43/*
44 * Logic:
45 * - only on a boundary condition do we need to care. When we go
46 * from a negative count to a non-negative, we wake people up.
47 * - when we go from a non-negative count to a negative do we
48 * (a) synchronize with the "sleeper" count and (b) make sure
49 * that we're on the wakeup list before we synchronize so that
50 * we cannot lose wakeup events.
51 */
52
53void __up(struct semaphore *sem)
54{
55 wake_up(&sem->wait);
56}
57
58static DEFINE_SPINLOCK(semaphore_lock);
59
60void __sched __down(struct semaphore * sem)
61{
62 struct task_struct *tsk = current;
63 DECLARE_WAITQUEUE(wait, tsk);
64 tsk->state = TASK_UNINTERRUPTIBLE;
65 add_wait_queue_exclusive(&sem->wait, &wait);
66
67 spin_lock_irq(&semaphore_lock);
68 sem->sleepers++;
69 for (;;) {
70 int sleepers = sem->sleepers;
71
72 /*
73 * Add "everybody else" into it. They aren't
74 * playing, because we own the spinlock.
75 */
76 if (!atomic_add_negative(sleepers - 1, &sem->count)) {
77 sem->sleepers = 0;
78 break;
79 }
80 sem->sleepers = 1; /* us - see -1 above */
81 spin_unlock_irq(&semaphore_lock);
82
83 schedule();
84 tsk->state = TASK_UNINTERRUPTIBLE;
85 spin_lock_irq(&semaphore_lock);
86 }
87 spin_unlock_irq(&semaphore_lock);
88 remove_wait_queue(&sem->wait, &wait);
89 tsk->state = TASK_RUNNING;
90 wake_up(&sem->wait);
91}
92
93int __sched __down_interruptible(struct semaphore * sem)
94{
95 int retval = 0;
96 struct task_struct *tsk = current;
97 DECLARE_WAITQUEUE(wait, tsk);
98 tsk->state = TASK_INTERRUPTIBLE;
99 add_wait_queue_exclusive(&sem->wait, &wait);
100
101 spin_lock_irq(&semaphore_lock);
102 sem->sleepers ++;
103 for (;;) {
104 int sleepers = sem->sleepers;
105
106 /*
107 * With signals pending, this turns into
108 * the trylock failure case - we won't be
109 * sleeping, and we* can't get the lock as
110 * it has contention. Just correct the count
111 * and exit.
112 */
113 if (signal_pending(current)) {
114 retval = -EINTR;
115 sem->sleepers = 0;
116 atomic_add(sleepers, &sem->count);
117 break;
118 }
119
120 /*
121 * Add "everybody else" into it. They aren't
122 * playing, because we own the spinlock. The
123 * "-1" is because we're still hoping to get
124 * the lock.
125 */
126 if (!atomic_add_negative(sleepers - 1, &sem->count)) {
127 sem->sleepers = 0;
128 break;
129 }
130 sem->sleepers = 1; /* us - see -1 above */
131 spin_unlock_irq(&semaphore_lock);
132
133 schedule();
134 tsk->state = TASK_INTERRUPTIBLE;
135 spin_lock_irq(&semaphore_lock);
136 }
137 spin_unlock_irq(&semaphore_lock);
138 tsk->state = TASK_RUNNING;
139 remove_wait_queue(&sem->wait, &wait);
140 wake_up(&sem->wait);
141 return retval;
142}
143
144/*
145 * Trylock failed - make sure we correct for
146 * having decremented the count.
147 */
148int __down_trylock(struct semaphore * sem)
149{
150 unsigned long flags;
151 int sleepers;
152
153 spin_lock_irqsave(&semaphore_lock, flags);
154 sleepers = sem->sleepers + 1;
155 sem->sleepers = 0;
156
157 /*
158 * Add "everybody else" and us into it. They aren't
159 * playing, because we own the spinlock.
160 */
161 if (!atomic_add_negative(sleepers, &sem->count))
162 wake_up(&sem->wait);
163
164 spin_unlock_irqrestore(&semaphore_lock, flags);
165 return 1;
166}
diff --git a/arch/v850/kernel/setup.c b/arch/v850/kernel/setup.c
new file mode 100644
index 000000000000..c41d72b01b88
--- /dev/null
+++ b/arch/v850/kernel/setup.c
@@ -0,0 +1,286 @@
1/*
2 * arch/v850/kernel/setup.c -- Arch-dependent initialization functions
3 *
4 * Copyright (C) 2001,02,03 NEC Electronics Corporation
5 * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14#include <linux/mm.h>
15#include <linux/bootmem.h>
16#include <linux/swap.h> /* we don't have swap, but for nr_free_pages */
17#include <linux/irq.h>
18#include <linux/reboot.h>
19#include <linux/personality.h>
20#include <linux/major.h>
21#include <linux/root_dev.h>
22#include <linux/mtd/mtd.h>
23#include <linux/init.h>
24
25#include <asm/irq.h>
26#include <asm/setup.h>
27
28#include "mach.h"
29
30/* These symbols are all defined in the linker map to delineate various
31 statically allocated regions of memory. */
32
33extern char _intv_start, _intv_end;
34/* `kram' is only used if the kernel uses part of normal user RAM. */
35extern char _kram_start __attribute__ ((__weak__));
36extern char _kram_end __attribute__ ((__weak__));
37extern char _init_start, _init_end;
38extern char _bootmap;
39extern char _stext, _etext, _sdata, _edata, _sbss, _ebss;
40/* Many platforms use an embedded root image. */
41extern char _root_fs_image_start __attribute__ ((__weak__));
42extern char _root_fs_image_end __attribute__ ((__weak__));
43
44
45char command_line[COMMAND_LINE_SIZE];
46
47/* Memory not used by the kernel. */
48static unsigned long total_ram_pages;
49
50/* System RAM. */
51static unsigned long ram_start = 0, ram_len = 0;
52
53
54#define ADDR_TO_PAGE_UP(x) ((((unsigned long)x) + PAGE_SIZE-1) >> PAGE_SHIFT)
55#define ADDR_TO_PAGE(x) (((unsigned long)x) >> PAGE_SHIFT)
56#define PAGE_TO_ADDR(x) (((unsigned long)x) << PAGE_SHIFT)
57
58static void init_mem_alloc (unsigned long ram_start, unsigned long ram_len);
59
60void set_mem_root (void *addr, size_t len, char *cmd_line);
61
62
63void __init setup_arch (char **cmdline)
64{
65 /* Keep a copy of command line */
66 *cmdline = command_line;
67 memcpy (saved_command_line, command_line, COMMAND_LINE_SIZE);
68 saved_command_line[COMMAND_LINE_SIZE - 1] = '\0';
69
70 console_verbose ();
71
72 init_mm.start_code = (unsigned long) &_stext;
73 init_mm.end_code = (unsigned long) &_etext;
74 init_mm.end_data = (unsigned long) &_edata;
75 init_mm.brk = (unsigned long) &_kram_end;
76
77 /* Find out what mem this machine has. */
78 mach_get_physical_ram (&ram_start, &ram_len);
79 /* ... and tell the kernel about it. */
80 init_mem_alloc (ram_start, ram_len);
81
82 printk (KERN_INFO "CPU: %s\nPlatform: %s\n",
83 CPU_MODEL_LONG, PLATFORM_LONG);
84
85 /* do machine-specific setups. */
86 mach_setup (cmdline);
87
88#ifdef CONFIG_MTD
89 if (!ROOT_DEV && &_root_fs_image_end > &_root_fs_image_start)
90 set_mem_root (&_root_fs_image_start,
91 &_root_fs_image_end - &_root_fs_image_start,
92 *cmdline);
93#endif
94}
95
96void __init trap_init (void)
97{
98}
99
100#ifdef CONFIG_MTD
101/* Set the root filesystem to be the given memory region.
102 Some parameter may be appended to CMD_LINE. */
103void set_mem_root (void *addr, size_t len, char *cmd_line)
104{
105 /* The only way to pass info to the MTD slram driver is via
106 the command line. */
107 if (*cmd_line) {
108 cmd_line += strlen (cmd_line);
109 *cmd_line++ = ' ';
110 }
111 sprintf (cmd_line, "slram=root,0x%x,+0x%x", (u32)addr, (u32)len);
112
113 ROOT_DEV = MKDEV (MTD_BLOCK_MAJOR, 0);
114}
115#endif
116
117
118static void irq_nop (unsigned irq) { }
119static unsigned irq_zero (unsigned irq) { return 0; }
120
121static void nmi_end (unsigned irq)
122{
123 if (irq != IRQ_NMI (0)) {
124 printk (KERN_CRIT "NMI %d is unrecoverable; restarting...",
125 irq - IRQ_NMI (0));
126 machine_restart (0);
127 }
128}
129
130static struct hw_interrupt_type nmi_irq_type = {
131 "NMI",
132 irq_zero, /* startup */
133 irq_nop, /* shutdown */
134 irq_nop, /* enable */
135 irq_nop, /* disable */
136 irq_nop, /* ack */
137 nmi_end, /* end */
138};
139
140void __init init_IRQ (void)
141{
142 init_irq_handlers (0, NUM_MACH_IRQS, 1, 0);
143 init_irq_handlers (IRQ_NMI (0), NUM_NMIS, 1, &nmi_irq_type);
144 mach_init_irqs ();
145}
146
147
148void __init mem_init (void)
149{
150 max_mapnr = MAP_NR (ram_start + ram_len);
151
152 num_physpages = ADDR_TO_PAGE (ram_len);
153
154 total_ram_pages = free_all_bootmem ();
155
156 printk (KERN_INFO
157 "Memory: %luK/%luK available"
158 " (%luK kernel code, %luK data)\n",
159 PAGE_TO_ADDR (nr_free_pages()) / 1024,
160 ram_len / 1024,
161 ((unsigned long)&_etext - (unsigned long)&_stext) / 1024,
162 ((unsigned long)&_ebss - (unsigned long)&_sdata) / 1024);
163}
164
165void free_initmem (void)
166{
167 unsigned long ram_end = ram_start + ram_len;
168 unsigned long start = PAGE_ALIGN ((unsigned long)(&_init_start));
169
170 if (start >= ram_start && start < ram_end) {
171 unsigned long addr;
172 unsigned long end = PAGE_ALIGN ((unsigned long)(&_init_end));
173
174 if (end > ram_end)
175 end = ram_end;
176
177 printk("Freeing unused kernel memory: %ldK freed\n",
178 (end - start) / 1024);
179
180 for (addr = start; addr < end; addr += PAGE_SIZE) {
181 struct page *page = virt_to_page (addr);
182 ClearPageReserved (page);
183 set_page_count (page, 1);
184 __free_page (page);
185 total_ram_pages++;
186 }
187 }
188}
189
190
191/* Initialize the `bootmem allocator'. RAM_START and RAM_LEN identify
192 what RAM may be used. */
193static void __init
194init_bootmem_alloc (unsigned long ram_start, unsigned long ram_len)
195{
196 /* The part of the kernel that's in the same managed RAM space
197 used for general allocation. */
198 unsigned long kram_start = (unsigned long)&_kram_start;
199 unsigned long kram_end = (unsigned long)&_kram_end;
200 /* End of the managed RAM space. */
201 unsigned long ram_end = ram_start + ram_len;
202 /* Address range of the interrupt vector table. */
203 unsigned long intv_start = (unsigned long)&_intv_start;
204 unsigned long intv_end = (unsigned long)&_intv_end;
205 /* True if the interrupt vectors are in the managed RAM area. */
206 int intv_in_ram = (intv_end > ram_start && intv_start < ram_end);
207 /* True if the interrupt vectors are inside the kernel's RAM. */
208 int intv_in_kram = (intv_end > kram_start && intv_start < kram_end);
209 /* A pointer to an optional function that reserves platform-specific
210 memory regions. We declare the pointer `volatile' to avoid gcc
211 turning the call into a static call (the problem is that since
212 it's a weak symbol, a static call may end up trying to reference
213 the location 0x0, which is not always reachable). */
214 void (*volatile mrb) (void) = mach_reserve_bootmem;
215 /* The bootmem allocator's allocation bitmap. */
216 unsigned long bootmap = (unsigned long)&_bootmap;
217 unsigned long bootmap_len;
218
219 /* Round bootmap location up to next page. */
220 bootmap = PAGE_TO_ADDR (ADDR_TO_PAGE_UP (bootmap));
221
222 /* Initialize bootmem allocator. */
223 bootmap_len = init_bootmem_node (NODE_DATA (0),
224 ADDR_TO_PAGE (bootmap),
225 ADDR_TO_PAGE (PAGE_OFFSET),
226 ADDR_TO_PAGE (ram_end));
227
228 /* Now make the RAM actually allocatable (it starts out `reserved'). */
229 free_bootmem (ram_start, ram_len);
230
231 if (kram_end > kram_start)
232 /* Reserve the RAM part of the kernel's address space, so it
233 doesn't get allocated. */
234 reserve_bootmem (kram_start, kram_end - kram_start);
235
236 if (intv_in_ram && !intv_in_kram)
237 /* Reserve the interrupt vector space. */
238 reserve_bootmem (intv_start, intv_end - intv_start);
239
240 if (bootmap >= ram_start && bootmap < ram_end)
241 /* Reserve the bootmap space. */
242 reserve_bootmem (bootmap, bootmap_len);
243
244 /* Reserve the memory used by the root filesystem image if it's
245 in RAM. */
246 if (&_root_fs_image_end > &_root_fs_image_start
247 && (unsigned long)&_root_fs_image_start >= ram_start
248 && (unsigned long)&_root_fs_image_start < ram_end)
249 reserve_bootmem ((unsigned long)&_root_fs_image_start,
250 &_root_fs_image_end - &_root_fs_image_start);
251
252 /* Let the platform-dependent code reserve some too. */
253 if (mrb)
254 (*mrb) ();
255}
256
257/* Tell the kernel about what RAM it may use for memory allocation. */
258static void __init
259init_mem_alloc (unsigned long ram_start, unsigned long ram_len)
260{
261 unsigned i;
262 unsigned long zones_size[MAX_NR_ZONES];
263
264 init_bootmem_alloc (ram_start, ram_len);
265
266 for (i = 0; i < MAX_NR_ZONES; i++)
267 zones_size[i] = 0;
268
269 /* We stuff all the memory into one area, which includes the
270 initial gap from PAGE_OFFSET to ram_start. */
271 zones_size[ZONE_DMA]
272 = ADDR_TO_PAGE (ram_len + (ram_start - PAGE_OFFSET));
273
274 /* The allocator is very picky about the address of the first
275 allocatable page -- it must be at least as aligned as the
276 maximum allocation -- so try to detect cases where it will get
277 confused and signal them at compile time (this is a common
278 problem when porting to a new platform with ). There is a
279 similar runtime check in free_area_init_core. */
280#if ((PAGE_OFFSET >> PAGE_SHIFT) & ((1UL << (MAX_ORDER - 1)) - 1))
281#error MAX_ORDER is too large for given PAGE_OFFSET (use CONFIG_FORCE_MAX_ZONEORDER to change it)
282#endif
283 NODE_DATA(0)->node_mem_map = NULL;
284 free_area_init_node (0, NODE_DATA(0), zones_size,
285 ADDR_TO_PAGE (PAGE_OFFSET), 0);
286}
diff --git a/arch/v850/kernel/signal.c b/arch/v850/kernel/signal.c
new file mode 100644
index 000000000000..37061e32e1a4
--- /dev/null
+++ b/arch/v850/kernel/signal.c
@@ -0,0 +1,525 @@
1/*
2 * arch/v850/kernel/signal.c -- Signal handling
3 *
4 * Copyright (C) 2001,02,03 NEC Electronics Corporation
5 * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
6 * Copyright (C) 1999,2000,2002 Niibe Yutaka & Kaz Kojima
7 * Copyright (C) 1991,1992 Linus Torvalds
8 *
9 * This file is subject to the terms and conditions of the GNU General
10 * Public License. See the file COPYING in the main directory of this
11 * archive for more details.
12 *
13 * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
14 *
15 * This file was derived from the sh version, arch/sh/kernel/signal.c
16 */
17
18#include <linux/mm.h>
19#include <linux/smp.h>
20#include <linux/smp_lock.h>
21#include <linux/kernel.h>
22#include <linux/signal.h>
23#include <linux/errno.h>
24#include <linux/wait.h>
25#include <linux/ptrace.h>
26#include <linux/unistd.h>
27#include <linux/stddef.h>
28#include <linux/personality.h>
29#include <linux/tty.h>
30
31#include <asm/ucontext.h>
32#include <asm/uaccess.h>
33#include <asm/pgtable.h>
34#include <asm/pgalloc.h>
35#include <asm/thread_info.h>
36#include <asm/cacheflush.h>
37
38#define DEBUG_SIG 0
39
40#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
41
42asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
43
44/*
45 * Atomically swap in the new signal mask, and wait for a signal.
46 */
47asmlinkage int
48sys_sigsuspend(old_sigset_t mask, struct pt_regs *regs)
49{
50 sigset_t saveset;
51
52 mask &= _BLOCKABLE;
53 spin_lock_irq(&current->sighand->siglock);
54 saveset = current->blocked;
55 siginitset(&current->blocked, mask);
56 recalc_sigpending();
57 spin_unlock_irq(&current->sighand->siglock);
58
59 regs->gpr[GPR_RVAL] = -EINTR;
60 while (1) {
61 current->state = TASK_INTERRUPTIBLE;
62 schedule();
63 if (do_signal(regs, &saveset))
64 return -EINTR;
65 }
66}
67
68asmlinkage int
69sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize,
70 struct pt_regs *regs)
71{
72 sigset_t saveset, newset;
73
74 /* XXX: Don't preclude handling different sized sigset_t's. */
75 if (sigsetsize != sizeof(sigset_t))
76 return -EINVAL;
77
78 if (copy_from_user(&newset, unewset, sizeof(newset)))
79 return -EFAULT;
80 sigdelsetmask(&newset, ~_BLOCKABLE);
81 spin_lock_irq(&current->sighand->siglock);
82 saveset = current->blocked;
83 current->blocked = newset;
84 recalc_sigpending();
85 spin_unlock_irq(&current->sighand->siglock);
86
87 regs->gpr[GPR_RVAL] = -EINTR;
88 while (1) {
89 current->state = TASK_INTERRUPTIBLE;
90 schedule();
91 if (do_signal(regs, &saveset))
92 return -EINTR;
93 }
94}
95
96asmlinkage int
97sys_sigaction(int sig, const struct old_sigaction *act,
98 struct old_sigaction *oact)
99{
100 struct k_sigaction new_ka, old_ka;
101 int ret;
102
103 if (act) {
104 old_sigset_t mask;
105 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
106 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
107 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
108 return -EFAULT;
109 __get_user(new_ka.sa.sa_flags, &act->sa_flags);
110 __get_user(mask, &act->sa_mask);
111 siginitset(&new_ka.sa.sa_mask, mask);
112 }
113
114 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
115
116 if (!ret && oact) {
117 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
118 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
119 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
120 return -EFAULT;
121 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
122 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
123 }
124
125 return ret;
126}
127
128asmlinkage int
129sys_sigaltstack(const stack_t *uss, stack_t *uoss,
130 struct pt_regs *regs)
131{
132 return do_sigaltstack(uss, uoss, regs->gpr[GPR_SP]);
133}
134
135
136/*
137 * Do a signal return; undo the signal stack.
138 */
139
140struct sigframe
141{
142 struct sigcontext sc;
143 unsigned long extramask[_NSIG_WORDS-1];
144 unsigned long tramp[2]; /* signal trampoline */
145};
146
147struct rt_sigframe
148{
149 struct siginfo info;
150 struct ucontext uc;
151 unsigned long tramp[2]; /* signal trampoline */
152};
153
154static int
155restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *rval_p)
156{
157 unsigned int err = 0;
158
159#define COPY(x) err |= __get_user(regs->x, &sc->regs.x)
160 COPY(gpr[0]); COPY(gpr[1]); COPY(gpr[2]); COPY(gpr[3]);
161 COPY(gpr[4]); COPY(gpr[5]); COPY(gpr[6]); COPY(gpr[7]);
162 COPY(gpr[8]); COPY(gpr[9]); COPY(gpr[10]); COPY(gpr[11]);
163 COPY(gpr[12]); COPY(gpr[13]); COPY(gpr[14]); COPY(gpr[15]);
164 COPY(gpr[16]); COPY(gpr[17]); COPY(gpr[18]); COPY(gpr[19]);
165 COPY(gpr[20]); COPY(gpr[21]); COPY(gpr[22]); COPY(gpr[23]);
166 COPY(gpr[24]); COPY(gpr[25]); COPY(gpr[26]); COPY(gpr[27]);
167 COPY(gpr[28]); COPY(gpr[29]); COPY(gpr[30]); COPY(gpr[31]);
168 COPY(pc); COPY(psw);
169 COPY(ctpc); COPY(ctpsw); COPY(ctbp);
170#undef COPY
171
172 return err;
173}
174
175asmlinkage int sys_sigreturn(struct pt_regs *regs)
176{
177 struct sigframe *frame = (struct sigframe *)regs->gpr[GPR_SP];
178 sigset_t set;
179 int rval;
180
181 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
182 goto badframe;
183
184 if (__get_user(set.sig[0], &frame->sc.oldmask)
185 || (_NSIG_WORDS > 1
186 && __copy_from_user(&set.sig[1], &frame->extramask,
187 sizeof(frame->extramask))))
188 goto badframe;
189
190 sigdelsetmask(&set, ~_BLOCKABLE);
191 spin_lock_irq(&current->sighand->siglock);
192 current->blocked = set;
193 recalc_sigpending();
194 spin_unlock_irq(&current->sighand->siglock);
195
196 if (restore_sigcontext(regs, &frame->sc, &rval))
197 goto badframe;
198 return rval;
199
200badframe:
201 force_sig(SIGSEGV, current);
202 return 0;
203}
204
205asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
206{
207 struct rt_sigframe *frame = (struct rt_sigframe *)regs->gpr[GPR_SP];
208 sigset_t set;
209 stack_t st;
210 int rval;
211
212 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
213 goto badframe;
214
215 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
216 goto badframe;
217
218 sigdelsetmask(&set, ~_BLOCKABLE);
219 spin_lock_irq(&current->sighand->siglock);
220 current->blocked = set;
221 recalc_sigpending();
222 spin_unlock_irq(&current->sighand->siglock);
223
224 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval))
225 goto badframe;
226
227 if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
228 goto badframe;
229 /* It is more difficult to avoid calling this function than to
230 call it and ignore errors. */
231 do_sigaltstack(&st, NULL, regs->gpr[GPR_SP]);
232
233 return rval;
234
235badframe:
236 force_sig(SIGSEGV, current);
237 return 0;
238}
239
240/*
241 * Set up a signal frame.
242 */
243
244static int
245setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
246 unsigned long mask)
247{
248 int err = 0;
249
250#define COPY(x) err |= __put_user(regs->x, &sc->regs.x)
251 COPY(gpr[0]); COPY(gpr[1]); COPY(gpr[2]); COPY(gpr[3]);
252 COPY(gpr[4]); COPY(gpr[5]); COPY(gpr[6]); COPY(gpr[7]);
253 COPY(gpr[8]); COPY(gpr[9]); COPY(gpr[10]); COPY(gpr[11]);
254 COPY(gpr[12]); COPY(gpr[13]); COPY(gpr[14]); COPY(gpr[15]);
255 COPY(gpr[16]); COPY(gpr[17]); COPY(gpr[18]); COPY(gpr[19]);
256 COPY(gpr[20]); COPY(gpr[21]); COPY(gpr[22]); COPY(gpr[23]);
257 COPY(gpr[24]); COPY(gpr[25]); COPY(gpr[26]); COPY(gpr[27]);
258 COPY(gpr[28]); COPY(gpr[29]); COPY(gpr[30]); COPY(gpr[31]);
259 COPY(pc); COPY(psw);
260 COPY(ctpc); COPY(ctpsw); COPY(ctbp);
261#undef COPY
262
263 err |= __put_user(mask, &sc->oldmask);
264
265 return err;
266}
267
268/*
269 * Determine which stack to use..
270 */
271static inline void *
272get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
273{
274 /* Default to using normal stack */
275 unsigned long sp = regs->gpr[GPR_SP];
276
277 if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
278 sp = current->sas_ss_sp + current->sas_ss_size;
279
280 return (void *)((sp - frame_size) & -8UL);
281}
282
283static void setup_frame(int sig, struct k_sigaction *ka,
284 sigset_t *set, struct pt_regs *regs)
285{
286 struct sigframe *frame;
287 int err = 0;
288 int signal;
289
290 frame = get_sigframe(ka, regs, sizeof(*frame));
291
292 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
293 goto give_sigsegv;
294
295 signal = current_thread_info()->exec_domain
296 && current_thread_info()->exec_domain->signal_invmap
297 && sig < 32
298 ? current_thread_info()->exec_domain->signal_invmap[sig]
299 : sig;
300
301 err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
302
303 if (_NSIG_WORDS > 1) {
304 err |= __copy_to_user(frame->extramask, &set->sig[1],
305 sizeof(frame->extramask));
306 }
307
308 /* Set up to return from userspace. If provided, use a stub
309 already in userspace. */
310 if (ka->sa.sa_flags & SA_RESTORER) {
311 regs->gpr[GPR_LP] = (unsigned long) ka->sa.sa_restorer;
312 } else {
313 /* Note, these encodings are _little endian_! */
314
315 /* addi __NR_sigreturn, r0, r12 */
316 err |= __put_user(0x6600 | (__NR_sigreturn << 16),
317 frame->tramp + 0);
318 /* trap 0 */
319 err |= __put_user(0x010007e0,
320 frame->tramp + 1);
321
322 regs->gpr[GPR_LP] = (unsigned long)frame->tramp;
323
324 flush_cache_sigtramp (regs->gpr[GPR_LP]);
325 }
326
327 if (err)
328 goto give_sigsegv;
329
330 /* Set up registers for signal handler. */
331 regs->pc = (v850_reg_t) ka->sa.sa_handler;
332 regs->gpr[GPR_SP] = (v850_reg_t)frame;
333 /* Signal handler args: */
334 regs->gpr[GPR_ARG0] = signal; /* arg 0: signum */
335 regs->gpr[GPR_ARG1] = (v850_reg_t)&frame->sc;/* arg 1: sigcontext */
336
337 set_fs(USER_DS);
338
339#if DEBUG_SIG
340 printk("SIG deliver (%s:%d): sp=%p pc=%08lx ra=%08lx\n",
341 current->comm, current->pid, frame, regs->pc, );
342#endif
343
344 return;
345
346give_sigsegv:
347 force_sigsegv(sig, current);
348}
349
350static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
351 sigset_t *set, struct pt_regs *regs)
352{
353 struct rt_sigframe *frame;
354 int err = 0;
355 int signal;
356
357 frame = get_sigframe(ka, regs, sizeof(*frame));
358
359 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
360 goto give_sigsegv;
361
362 signal = current_thread_info()->exec_domain
363 && current_thread_info()->exec_domain->signal_invmap
364 && sig < 32
365 ? current_thread_info()->exec_domain->signal_invmap[sig]
366 : sig;
367
368 err |= copy_siginfo_to_user(&frame->info, info);
369
370 /* Create the ucontext. */
371 err |= __put_user(0, &frame->uc.uc_flags);
372 err |= __put_user(0, &frame->uc.uc_link);
373 err |= __put_user((void *)current->sas_ss_sp,
374 &frame->uc.uc_stack.ss_sp);
375 err |= __put_user(sas_ss_flags(regs->gpr[GPR_SP]),
376 &frame->uc.uc_stack.ss_flags);
377 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
378 err |= setup_sigcontext(&frame->uc.uc_mcontext,
379 regs, set->sig[0]);
380 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
381
382 /* Set up to return from userspace. If provided, use a stub
383 already in userspace. */
384 if (ka->sa.sa_flags & SA_RESTORER) {
385 regs->gpr[GPR_LP] = (unsigned long) ka->sa.sa_restorer;
386 } else {
387 /* Note, these encodings are _little endian_! */
388
389 /* addi __NR_sigreturn, r0, r12 */
390 err |= __put_user(0x6600 | (__NR_sigreturn << 16),
391 frame->tramp + 0);
392 /* trap 0 */
393 err |= __put_user(0x010007e0,
394 frame->tramp + 1);
395
396 regs->gpr[GPR_LP] = (unsigned long)frame->tramp;
397
398 flush_cache_sigtramp (regs->gpr[GPR_LP]);
399 }
400
401 if (err)
402 goto give_sigsegv;
403
404 /* Set up registers for signal handler. */
405 regs->pc = (v850_reg_t) ka->sa.sa_handler;
406 regs->gpr[GPR_SP] = (v850_reg_t)frame;
407 /* Signal handler args: */
408 regs->gpr[GPR_ARG0] = signal; /* arg 0: signum */
409 regs->gpr[GPR_ARG1] = (v850_reg_t)&frame->info; /* arg 1: siginfo */
410 regs->gpr[GPR_ARG2] = (v850_reg_t)&frame->uc; /* arg 2: ucontext */
411
412 set_fs(USER_DS);
413
414#if DEBUG_SIG
415 printk("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
416 current->comm, current->pid, frame, regs->pc, regs->pr);
417#endif
418
419 return;
420
421give_sigsegv:
422 force_sigsegv(sig, current);
423}
424
425/*
426 * OK, we're invoking a handler
427 */
428
429static void
430handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
431 sigset_t *oldset, struct pt_regs * regs)
432{
433 /* Are we from a system call? */
434 if (PT_REGS_SYSCALL (regs)) {
435 /* If so, check system call restarting.. */
436 switch (regs->gpr[GPR_RVAL]) {
437 case -ERESTART_RESTARTBLOCK:
438 current_thread_info()->restart_block.fn =
439 do_no_restart_syscall;
440 /* fall through */
441 case -ERESTARTNOHAND:
442 regs->gpr[GPR_RVAL] = -EINTR;
443 break;
444
445 case -ERESTARTSYS:
446 if (!(ka->sa.sa_flags & SA_RESTART)) {
447 regs->gpr[GPR_RVAL] = -EINTR;
448 break;
449 }
450 /* fallthrough */
451 case -ERESTARTNOINTR:
452 regs->gpr[12] = PT_REGS_SYSCALL (regs);
453 regs->pc -= 4; /* Size of `trap 0' insn. */
454 }
455
456 PT_REGS_SET_SYSCALL (regs, 0);
457 }
458
459 /* Set up the stack frame */
460 if (ka->sa.sa_flags & SA_SIGINFO)
461 setup_rt_frame(sig, ka, info, oldset, regs);
462 else
463 setup_frame(sig, ka, oldset, regs);
464
465 if (!(ka->sa.sa_flags & SA_NODEFER)) {
466 spin_lock_irq(&current->sighand->siglock);
467 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
468 sigaddset(&current->blocked,sig);
469 recalc_sigpending();
470 spin_unlock_irq(&current->sighand->siglock);
471 }
472}
473
474/*
475 * Note that 'init' is a special process: it doesn't get signals it doesn't
476 * want to handle. Thus you cannot kill init even with a SIGKILL even by
477 * mistake.
478 *
479 * Note that we go through the signals twice: once to check the signals that
480 * the kernel can handle, and then we build all the user-level signal handling
481 * stack-frames in one go after that.
482 */
483int do_signal(struct pt_regs *regs, sigset_t *oldset)
484{
485 siginfo_t info;
486 int signr;
487 struct k_sigaction ka;
488
489 /*
490 * We want the common case to go fast, which
491 * is why we may in certain cases get here from
492 * kernel mode. Just return without doing anything
493 * if so.
494 */
495 if (!user_mode(regs))
496 return 1;
497
498 if (!oldset)
499 oldset = &current->blocked;
500
501 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
502 if (signr > 0) {
503 /* Whee! Actually deliver the signal. */
504 handle_signal(signr, &info, &ka, oldset, regs);
505 return 1;
506 }
507
508 /* Did we come from a system call? */
509 if (PT_REGS_SYSCALL (regs)) {
510 int rval = (int)regs->gpr[GPR_RVAL];
511 /* Restart the system call - no handlers present */
512 if (rval == -ERESTARTNOHAND
513 || rval == -ERESTARTSYS
514 || rval == -ERESTARTNOINTR)
515 {
516 regs->gpr[12] = PT_REGS_SYSCALL (regs);
517 regs->pc -= 4; /* Size of `trap 0' insn. */
518 }
519 else if (rval == -ERESTART_RESTARTBLOCK) {
520 regs->gpr[12] = __NR_restart_syscall;
521 regs->pc -= 4; /* Size of `trap 0' insn. */
522 }
523 }
524 return 0;
525}
diff --git a/arch/v850/kernel/sim.c b/arch/v850/kernel/sim.c
new file mode 100644
index 000000000000..4f31da962632
--- /dev/null
+++ b/arch/v850/kernel/sim.c
@@ -0,0 +1,179 @@
1/*
2 * arch/v850/kernel/sim.c -- Machine-specific stuff for GDB v850e simulator
3 *
4 * Copyright (C) 2001,02 NEC Corporation
5 * Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14#include <linux/config.h>
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/init.h>
18#include <linux/mm.h>
19#include <linux/swap.h>
20#include <linux/bootmem.h>
21#include <linux/irq.h>
22
23#include <asm/atomic.h>
24#include <asm/page.h>
25#include <asm/machdep.h>
26#include <asm/simsyscall.h>
27
28#include "mach.h"
29
30/* The name of a file containing the root filesystem. */
31#define ROOT_FS "rootfs.image"
32
33extern void simcons_setup (void);
34extern void simcons_poll_ttys (void);
35extern void set_mem_root (void *addr, size_t len, char *cmd_line);
36
37static int read_file (const char *name,
38 unsigned long *addr, unsigned long *len,
39 const char **err);
40
41void __init mach_setup (char **cmdline)
42{
43 const char *err;
44 unsigned long root_dev_addr, root_dev_len;
45
46 simcons_setup ();
47
48 printk (KERN_INFO "Reading root filesystem: %s", ROOT_FS);
49
50 if (read_file (ROOT_FS, &root_dev_addr, &root_dev_len, &err)) {
51 printk (" (size %luK)\n", root_dev_len / 1024);
52 set_mem_root ((void *)root_dev_addr, (size_t)root_dev_len,
53 *cmdline);
54 } else
55 printk ("...%s failed!\n", err);
56}
57
58void mach_get_physical_ram (unsigned long *ram_start, unsigned long *ram_len)
59{
60 *ram_start = RAM_ADDR;
61 *ram_len = RAM_SIZE;
62}
63
64void __init mach_sched_init (struct irqaction *timer_action)
65{
66 /* ...do magic timer initialization?... */
67 mach_tick = simcons_poll_ttys;
68 setup_irq (0, timer_action);
69}
70
71
72static void irq_nop (unsigned irq) { }
73static unsigned irq_zero (unsigned irq) { return 0; }
74
75static struct hw_interrupt_type sim_irq_type = {
76 "IRQ",
77 irq_zero, /* startup */
78 irq_nop, /* shutdown */
79 irq_nop, /* enable */
80 irq_nop, /* disable */
81 irq_nop, /* ack */
82 irq_nop, /* end */
83};
84
85void __init mach_init_irqs (void)
86{
87 init_irq_handlers (0, NUM_MACH_IRQS, 1, &sim_irq_type);
88}
89
90
91void mach_gettimeofday (struct timespec *tv)
92{
93 long timeval[2], timezone[2];
94 int rval = V850_SIM_SYSCALL (gettimeofday, timeval, timezone);
95 if (rval == 0) {
96 tv->tv_sec = timeval[0];
97 tv->tv_nsec = timeval[1] * 1000;
98 }
99}
100
101void machine_restart (char *__unused)
102{
103 V850_SIM_SYSCALL (write, 1, "RESTART\n", 8);
104 V850_SIM_SYSCALL (exit, 0);
105}
106
107EXPORT_SYMBOL(machine_restart);
108
109void machine_halt (void)
110{
111 V850_SIM_SYSCALL (write, 1, "HALT\n", 5);
112 V850_SIM_SYSCALL (exit, 0);
113}
114
115EXPORT_SYMBOL(machine_halt);
116
117void machine_power_off (void)
118{
119 V850_SIM_SYSCALL (write, 1, "POWER OFF\n", 10);
120 V850_SIM_SYSCALL (exit, 0);
121}
122
123EXPORT_SYMBOL(machine_power_off);
124
125
126/* Load data from a file called NAME into ram. The address and length
127 of the data image are returned in ADDR and LEN. */
128static int __init
129read_file (const char *name,
130 unsigned long *addr, unsigned long *len,
131 const char **err)
132{
133 int rval, fd;
134 unsigned long cur, left;
135 /* Note this is not a normal stat buffer, it's an ad-hoc
136 structure defined by the simulator. */
137 unsigned long stat_buf[10];
138
139 /* Stat the file to find out the length. */
140 rval = V850_SIM_SYSCALL (stat, name, stat_buf);
141 if (rval < 0) {
142 if (err) *err = "stat";
143 return 0;
144 }
145 *len = stat_buf[4];
146
147 /* Open the file; `0' is O_RDONLY. */
148 fd = V850_SIM_SYSCALL (open, name, 0);
149 if (fd < 0) {
150 if (err) *err = "open";
151 return 0;
152 }
153
154 *addr = (unsigned long)alloc_bootmem(*len);
155 if (! *addr) {
156 V850_SIM_SYSCALL (close, fd);
157 if (err) *err = "alloc_bootmem";
158 return 0;
159 }
160
161 cur = *addr;
162 left = *len;
163 while (left > 0) {
164 int chunk = V850_SIM_SYSCALL (read, fd, cur, left);
165 if (chunk <= 0)
166 break;
167 cur += chunk;
168 left -= chunk;
169 }
170 V850_SIM_SYSCALL (close, fd);
171 if (left > 0) {
172 /* Some read failed. */
173 free_bootmem (*addr, *len);
174 if (err) *err = "read";
175 return 0;
176 }
177
178 return 1;
179}
diff --git a/arch/v850/kernel/sim.ld b/arch/v850/kernel/sim.ld
new file mode 100644
index 000000000000..101885f3c9f0
--- /dev/null
+++ b/arch/v850/kernel/sim.ld
@@ -0,0 +1,13 @@
1/* Linker script for the gdb v850e simulator (CONFIG_V850E_SIM). */
2
3MEMORY {
4 /* Interrupt vectors. */
5 INTV : ORIGIN = 0x0, LENGTH = 0xe0
6 /* Main RAM. */
7 RAM : ORIGIN = RAM_ADDR, LENGTH = RAM_SIZE
8}
9
10SECTIONS {
11 .intv : { INTV_CONTENTS } > INTV
12 .ram : { RAMK_KRAM_CONTENTS } > RAM
13}
diff --git a/arch/v850/kernel/sim85e2.c b/arch/v850/kernel/sim85e2.c
new file mode 100644
index 000000000000..93a722b516bb
--- /dev/null
+++ b/arch/v850/kernel/sim85e2.c
@@ -0,0 +1,201 @@
1/*
2 * arch/v850/kernel/sim85e2.c -- Machine-specific stuff for
3 * V850E2 RTL simulator
4 *
5 * Copyright (C) 2002,03 NEC Electronics Corporation
6 * Copyright (C) 2002,03 Miles Bader <miles@gnu.org>
7 *
8 * This file is subject to the terms and conditions of the GNU General
9 * Public License. See the file COPYING in the main directory of this
10 * archive for more details.
11 *
12 * Written by Miles Bader <miles@gnu.org>
13 */
14
15#include <linux/config.h>
16#include <linux/kernel.h>
17#include <linux/module.h>
18#include <linux/init.h>
19#include <linux/mm.h>
20#include <linux/swap.h>
21#include <linux/bootmem.h>
22#include <linux/irq.h>
23
24#include <asm/atomic.h>
25#include <asm/page.h>
26#include <asm/machdep.h>
27
28#include "mach.h"
29
30
31/* There are 4 possible areas we can use:
32
33 IRAM (1MB) is fast for instruction fetches, but slow for data
34 DRAM (1020KB) is fast for data, but slow for instructions
35 ERAM is cached, so should be fast for both insns and data
36 SDRAM is external DRAM, similar to ERAM
37*/
38
39#define INIT_MEMC_FOR_SDRAM
40#define USE_SDRAM_AREA
41#define KERNEL_IN_SDRAM_AREA
42
43#define DCACHE_MODE V850E2_CACHE_BTSC_DCM_WT
44/*#define DCACHE_MODE V850E2_CACHE_BTSC_DCM_WB_ALLOC*/
45
46#ifdef USE_SDRAM_AREA
47#define RAM_START SDRAM_ADDR
48#define RAM_END (SDRAM_ADDR + SDRAM_SIZE)
49#else
50/* When we use DRAM, we need to account for the fact that the end of it is
51 used for R0_RAM. */
52#define RAM_START DRAM_ADDR
53#define RAM_END R0_RAM_ADDR
54#endif
55
56
57extern void memcons_setup (void);
58
59
60#ifdef KERNEL_IN_SDRAM_AREA
61#define EARLY_INIT_SECTION_ATTR __attribute__ ((section (".early.text")))
62#else
63#define EARLY_INIT_SECTION_ATTR __init
64#endif
65
66void EARLY_INIT_SECTION_ATTR mach_early_init (void)
67{
68 /* The sim85e2 simulator tracks `undefined' values, so to make
69 debugging easier, we begin by zeroing out all otherwise
70 undefined registers. This is not strictly necessary.
71
72 The registers we zero are:
73 Every GPR except:
74 stack-pointer (r3)
75 task-pointer (r16)
76 our return addr (r31)
77 Every system register (SPR) that we know about except for
78 the PSW (SPR 5), which we zero except for the
79 disable-interrupts bit.
80 */
81
82 /* GPRs */
83 asm volatile (" mov r0, r1 ; mov r0, r2 ");
84 asm volatile ("mov r0, r4 ; mov r0, r5 ; mov r0, r6 ; mov r0, r7 ");
85 asm volatile ("mov r0, r8 ; mov r0, r9 ; mov r0, r10; mov r0, r11");
86 asm volatile ("mov r0, r12; mov r0, r13; mov r0, r14; mov r0, r15");
87 asm volatile (" mov r0, r17; mov r0, r18; mov r0, r19");
88 asm volatile ("mov r0, r20; mov r0, r21; mov r0, r22; mov r0, r23");
89 asm volatile ("mov r0, r24; mov r0, r25; mov r0, r26; mov r0, r27");
90 asm volatile ("mov r0, r28; mov r0, r29; mov r0, r30");
91
92 /* SPRs */
93 asm volatile ("ldsr r0, 0; ldsr r0, 1; ldsr r0, 2; ldsr r0, 3");
94 asm volatile ("ldsr r0, 4");
95 asm volatile ("addi 0x20, r0, r1; ldsr r1, 5"); /* PSW */
96 asm volatile ("ldsr r0, 16; ldsr r0, 17; ldsr r0, 18; ldsr r0, 19");
97 asm volatile ("ldsr r0, 20");
98
99
100#ifdef INIT_MEMC_FOR_SDRAM
101 /* Settings for SDRAM controller. */
102 V850E2_VSWC = 0x0042;
103 V850E2_BSC = 0x9286;
104 V850E2_BCT(0) = 0xb000; /* was: 0 */
105 V850E2_BCT(1) = 0x000b;
106 V850E2_ASC = 0;
107 V850E2_LBS = 0xa9aa; /* was: 0xaaaa */
108 V850E2_LBC(0) = 0;
109 V850E2_LBC(1) = 0; /* was: 0x3 */
110 V850E2_BCC = 0;
111 V850E2_RFS(4) = 0x800a; /* was: 0xf109 */
112 V850E2_SCR(4) = 0x2091; /* was: 0x20a1 */
113 V850E2_RFS(3) = 0x800c;
114 V850E2_SCR(3) = 0x20a1;
115 V850E2_DWC(0) = 0;
116 V850E2_DWC(1) = 0;
117#endif
118
119#if 0
120#ifdef CONFIG_V850E2_SIM85E2S
121 /* Turn on the caches. */
122 V850E2_CACHE_BTSC = V850E2_CACHE_BTSC_ICM | DCACHE_MODE;
123 V850E2_BHC = 0x1010;
124#elif CONFIG_V850E2_SIM85E2C
125 V850E2_CACHE_BTSC |= (V850E2_CACHE_BTSC_ICM | V850E2_CACHE_BTSC_DCM0);
126 V850E2_BUSM_BHC = 0xFFFF;
127#endif
128#else
129 V850E2_BHC = 0;
130#endif
131
132 /* Don't stop the simulator at `halt' instructions. */
133 SIM85E2_NOTHAL = 1;
134
135 /* Ensure that the simulator halts on a panic, instead of going
136 into an infinite loop inside the panic function. */
137 panic_timeout = -1;
138}
139
140void __init mach_setup (char **cmdline)
141{
142 memcons_setup ();
143}
144
145void mach_get_physical_ram (unsigned long *ram_start, unsigned long *ram_len)
146{
147 *ram_start = RAM_START;
148 *ram_len = RAM_END - RAM_START;
149}
150
151void __init mach_sched_init (struct irqaction *timer_action)
152{
153 /* The simulator actually cycles through all interrupts
154 periodically. We just pay attention to IRQ0, which gives us
155 1/64 the rate of the periodic interrupts. */
156 setup_irq (0, timer_action);
157}
158
159void mach_gettimeofday (struct timespec *tv)
160{
161 tv->tv_sec = 0;
162 tv->tv_nsec = 0;
163}
164
165/* Interrupts */
166
167struct v850e_intc_irq_init irq_inits[] = {
168 { "IRQ", 0, NUM_MACH_IRQS, 1, 7 },
169 { 0 }
170};
171struct hw_interrupt_type hw_itypes[1];
172
173/* Initialize interrupts. */
174void __init mach_init_irqs (void)
175{
176 v850e_intc_init_irq_types (irq_inits, hw_itypes);
177}
178
179
180void machine_halt (void) __attribute__ ((noreturn));
181void machine_halt (void)
182{
183 SIM85E2_SIMFIN = 0; /* Halt immediately. */
184 for (;;) {}
185}
186
187EXPORT_SYMBOL(machine_halt);
188
189void machine_restart (char *__unused)
190{
191 machine_halt ();
192}
193
194EXPORT_SYMBOL(machine_restart);
195
196void machine_power_off (void)
197{
198 machine_halt ();
199}
200
201EXPORT_SYMBOL(machine_power_off);
diff --git a/arch/v850/kernel/sim85e2.ld b/arch/v850/kernel/sim85e2.ld
new file mode 100644
index 000000000000..7470fd2ffb5b
--- /dev/null
+++ b/arch/v850/kernel/sim85e2.ld
@@ -0,0 +1,36 @@
1/* Linker script for the sim85e2c simulator, which is a verilog simulation of
2 the V850E2 NA85E2C cpu core (CONFIG_V850E2_SIM85E2C). */
3
4MEMORY {
5 /* 1MB of `instruction RAM', starting at 0.
6 Instruction fetches are much faster from IRAM than from DRAM. */
7 IRAM : ORIGIN = IRAM_ADDR, LENGTH = IRAM_SIZE
8
9 /* 1MB of `data RAM', below and contiguous with the I/O space.
10 Data fetches are much faster from DRAM than from IRAM. */
11 DRAM : ORIGIN = DRAM_ADDR, LENGTH = DRAM_SIZE
12
13 /* `external ram' (CS1 area), comes after IRAM. */
14 ERAM : ORIGIN = ERAM_ADDR, LENGTH = ERAM_SIZE
15
16 /* Dynamic RAM; uses memory controller. */
17 SDRAM : ORIGIN = SDRAM_ADDR, LENGTH = SDRAM_SIZE
18}
19
20SECTIONS {
21 .iram : {
22 INTV_CONTENTS
23 *arch/v850/kernel/head.o
24 *(.early.text)
25 } > IRAM
26 .dram : {
27 _memcons_output = . ;
28 . = . + 0x8000 ;
29 _memcons_output_end = . ;
30 } > DRAM
31 .sdram : {
32 /* We stick console output into a buffer here. */
33 RAMK_KRAM_CONTENTS
34 ROOT_FS_CONTENTS
35 } > SDRAM
36}
diff --git a/arch/v850/kernel/simcons.c b/arch/v850/kernel/simcons.c
new file mode 100644
index 000000000000..7f0efaa025c9
--- /dev/null
+++ b/arch/v850/kernel/simcons.c
@@ -0,0 +1,166 @@
1/*
2 * arch/v850/kernel/simcons.c -- Console I/O for GDB v850e simulator
3 *
4 * Copyright (C) 2001,02,03 NEC Electronics Corporation
5 * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14#include <linux/kernel.h>
15#include <linux/console.h>
16#include <linux/tty.h>
17#include <linux/tty_flip.h>
18#include <linux/tty_driver.h>
19#include <linux/init.h>
20
21#include <asm/poll.h>
22#include <asm/string.h>
23#include <asm/simsyscall.h>
24
25
26/* Low-level console. */
27
28static void simcons_write (struct console *co, const char *buf, unsigned len)
29{
30 V850_SIM_SYSCALL (write, 1, buf, len);
31}
32
33static int simcons_read (struct console *co, char *buf, unsigned len)
34{
35 return V850_SIM_SYSCALL (read, 0, buf, len);
36}
37
38static struct tty_driver *tty_driver;
39static struct tty_driver *simcons_device (struct console *c, int *index)
40{
41 *index = c->index;
42 return tty_driver;
43}
44
45static struct console simcons =
46{
47 .name = "simcons",
48 .write = simcons_write,
49 .read = simcons_read,
50 .device = simcons_device,
51 .flags = CON_PRINTBUFFER,
52 .index = -1,
53};
54
55/* Higher level TTY interface. */
56
57int simcons_tty_open (struct tty_struct *tty, struct file *filp)
58{
59 return 0;
60}
61
62int simcons_tty_write (struct tty_struct *tty,
63 const unsigned char *buf, int count)
64{
65 return V850_SIM_SYSCALL (write, 1, buf, count);
66}
67
68int simcons_tty_write_room (struct tty_struct *tty)
69{
70 /* Completely arbitrary. */
71 return 0x100000;
72}
73
74int simcons_tty_chars_in_buffer (struct tty_struct *tty)
75{
76 /* We have no buffer. */
77 return 0;
78}
79
80static struct tty_operations ops = {
81 .open = simcons_tty_open,
82 .write = simcons_tty_write,
83 .write_room = simcons_tty_write_room,
84 .chars_in_buffer = simcons_tty_chars_in_buffer,
85};
86
87int __init simcons_tty_init (void)
88{
89 struct tty_driver *driver = alloc_tty_driver(1);
90 int err;
91 if (!driver)
92 return -ENOMEM;
93 driver->name = "simcons";
94 driver->major = TTY_MAJOR;
95 driver->minor_start = 64;
96 driver->type = TTY_DRIVER_TYPE_SYSCONS;
97 driver->init_termios = tty_std_termios;
98 tty_set_operations(driver, &ops);
99 err = tty_register_driver(driver);
100 if (err) {
101 put_tty_driver(driver);
102 return err;
103 }
104 tty_driver = driver;
105 return 0;
106}
107/* We use `late_initcall' instead of just `__initcall' as a workaround for
108 the fact that (1) simcons_tty_init can't be called before tty_init,
109 (2) tty_init is called via `module_init', (3) if statically linked,
110 module_init == device_init, and (4) there's no ordering of init lists.
111 We can do this easily because simcons is always statically linked, but
112 other tty drivers that depend on tty_init and which must use
113 `module_init' to declare their init routines are likely to be broken. */
114late_initcall(simcons_tty_init);
115
116/* Poll for input on the console, and if there's any, deliver it to the
117 tty driver. */
118void simcons_poll_tty (struct tty_struct *tty)
119{
120 int flip = 0, send_break = 0;
121 struct pollfd pfd;
122 pfd.fd = 0;
123 pfd.events = POLLIN;
124
125 if (V850_SIM_SYSCALL (poll, &pfd, 1, 0) > 0) {
126 if (pfd.revents & POLLIN) {
127 int left = TTY_FLIPBUF_SIZE - tty->flip.count;
128
129 if (left > 0) {
130 unsigned char *buf = tty->flip.char_buf_ptr;
131 int rd = V850_SIM_SYSCALL (read, 0, buf, left);
132
133 if (rd > 0) {
134 tty->flip.count += rd;
135 tty->flip.char_buf_ptr += rd;
136 memset (tty->flip.flag_buf_ptr, 0, rd);
137 tty->flip.flag_buf_ptr += rd;
138 flip = 1;
139 } else
140 send_break = 1;
141 }
142 } else if (pfd.revents & POLLERR)
143 send_break = 1;
144 }
145
146 if (send_break) {
147 tty_insert_flip_char (tty, 0, TTY_BREAK);
148 flip = 1;
149 }
150
151 if (flip)
152 tty_schedule_flip (tty);
153}
154
155void simcons_poll_ttys (void)
156{
157 if (tty_driver && tty_driver->ttys[0])
158 simcons_poll_tty (tty_driver->ttys[0]);
159}
160
161void simcons_setup (void)
162{
163 V850_SIM_SYSCALL (make_raw, 0);
164 register_console (&simcons);
165 printk (KERN_INFO "Console: GDB V850E simulator stdio\n");
166}
diff --git a/arch/v850/kernel/syscalls.c b/arch/v850/kernel/syscalls.c
new file mode 100644
index 000000000000..9224cb65f6ec
--- /dev/null
+++ b/arch/v850/kernel/syscalls.c
@@ -0,0 +1,197 @@
1/*
2 * arch/v850/kernel/syscalls.c -- Various system-call definitions not
3 * defined in machine-independent code
4 *
5 * Copyright (C) 2001,02 NEC Corporation
6 * Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
7 *
8 * This file is subject to the terms and conditions of the GNU General
9 * Public License. See the file COPYING in the main directory of this
10 * archive for more details.
11 *
12 * This file was derived the ppc version, arch/ppc/kernel/syscalls.c
13 * ... which was derived from "arch/i386/kernel/sys_i386.c" by Gary Thomas;
14 * modified by Cort Dougan (cort@cs.nmt.edu)
15 * and Paul Mackerras (paulus@cs.anu.edu.au).
16 */
17
18#include <linux/config.h>
19#include <linux/errno.h>
20#include <linux/mm.h>
21#include <linux/smp.h>
22#include <linux/smp_lock.h>
23#include <linux/syscalls.h>
24#include <linux/sem.h>
25#include <linux/msg.h>
26#include <linux/shm.h>
27#include <linux/stat.h>
28#include <linux/mman.h>
29#include <linux/sys.h>
30#include <linux/ipc.h>
31#include <linux/utsname.h>
32#include <linux/file.h>
33
34#include <asm/uaccess.h>
35#include <asm/ipc.h>
36#include <asm/semaphore.h>
37
38/*
39 * sys_ipc() is the de-multiplexer for the SysV IPC calls..
40 *
41 * This is really horribly ugly.
42 */
43int
44sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
45{
46 int version, ret;
47
48 version = call >> 16; /* hack for backward compatibility */
49 call &= 0xffff;
50
51 ret = -EINVAL;
52 switch (call) {
53 case SEMOP:
54 ret = sys_semop (first, (struct sembuf *)ptr, second);
55 break;
56 case SEMGET:
57 ret = sys_semget (first, second, third);
58 break;
59 case SEMCTL:
60 {
61 union semun fourth;
62
63 if (!ptr)
64 break;
65 if ((ret = access_ok(VERIFY_READ, ptr, sizeof(long)) ? 0 : -EFAULT)
66 || (ret = get_user(fourth.__pad, (void **)ptr)))
67 break;
68 ret = sys_semctl (first, second, third, fourth);
69 break;
70 }
71 case MSGSND:
72 ret = sys_msgsnd (first, (struct msgbuf *) ptr, second, third);
73 break;
74 case MSGRCV:
75 switch (version) {
76 case 0: {
77 struct ipc_kludge tmp;
78
79 if (!ptr)
80 break;
81 if ((ret = access_ok(VERIFY_READ, ptr, sizeof(tmp)) ? 0 : -EFAULT)
82 || (ret = copy_from_user(&tmp,
83 (struct ipc_kludge *) ptr,
84 sizeof (tmp))))
85 break;
86 ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp,
87 third);
88 break;
89 }
90 default:
91 ret = sys_msgrcv (first, (struct msgbuf *) ptr,
92 second, fifth, third);
93 break;
94 }
95 break;
96 case MSGGET:
97 ret = sys_msgget ((key_t) first, second);
98 break;
99 case MSGCTL:
100 ret = sys_msgctl (first, second, (struct msqid_ds *) ptr);
101 break;
102 case SHMAT:
103 switch (version) {
104 default: {
105 ulong raddr;
106
107 if ((ret = access_ok(VERIFY_WRITE, (ulong*) third,
108 sizeof(ulong)) ? 0 : -EFAULT))
109 break;
110 ret = do_shmat (first, (char *) ptr, second, &raddr);
111 if (ret)
112 break;
113 ret = put_user (raddr, (ulong *) third);
114 break;
115 }
116 case 1: /* iBCS2 emulator entry point */
117 if (!segment_eq(get_fs(), get_ds()))
118 break;
119 ret = do_shmat (first, (char *) ptr, second,
120 (ulong *) third);
121 break;
122 }
123 break;
124 case SHMDT:
125 ret = sys_shmdt ((char *)ptr);
126 break;
127 case SHMGET:
128 ret = sys_shmget (first, second, third);
129 break;
130 case SHMCTL:
131 ret = sys_shmctl (first, second, (struct shmid_ds *) ptr);
132 break;
133 }
134
135 return ret;
136}
137
138/*
139 * sys_pipe() is the normal C calling standard for creating
140 * a pipe. It's not the way unix traditionally does this, though.
141 */
142int sys_pipe (int *fildes)
143{
144 int fd[2];
145 int error;
146
147 error = do_pipe (fd);
148 if (!error) {
149 if (copy_to_user (fildes, fd, 2*sizeof (int)))
150 error = -EFAULT;
151 }
152 return error;
153}
154
155static inline unsigned long
156do_mmap2 (unsigned long addr, size_t len,
157 unsigned long prot, unsigned long flags,
158 unsigned long fd, unsigned long pgoff)
159{
160 struct file * file = NULL;
161 int ret = -EBADF;
162
163 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
164 if (! (flags & MAP_ANONYMOUS)) {
165 if (!(file = fget (fd)))
166 goto out;
167 }
168
169 down_write (&current->mm->mmap_sem);
170 ret = do_mmap_pgoff (file, addr, len, prot, flags, pgoff);
171 up_write (&current->mm->mmap_sem);
172 if (file)
173 fput (file);
174out:
175 return ret;
176}
177
178unsigned long sys_mmap2 (unsigned long addr, size_t len,
179 unsigned long prot, unsigned long flags,
180 unsigned long fd, unsigned long pgoff)
181{
182 return do_mmap2 (addr, len, prot, flags, fd, pgoff);
183}
184
185unsigned long sys_mmap (unsigned long addr, size_t len,
186 unsigned long prot, unsigned long flags,
187 unsigned long fd, off_t offset)
188{
189 int err = -EINVAL;
190
191 if (offset & ~PAGE_MASK)
192 goto out;
193
194 err = do_mmap2 (addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
195out:
196 return err;
197}
diff --git a/arch/v850/kernel/teg.c b/arch/v850/kernel/teg.c
new file mode 100644
index 000000000000..495cf8f37bcb
--- /dev/null
+++ b/arch/v850/kernel/teg.c
@@ -0,0 +1,63 @@
1/*
2 * arch/v850/kernel/teg.c -- NB85E-TEG cpu chip
3 *
4 * Copyright (C) 2001,02,03 NEC Electronics Corporation
5 * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14#include <linux/config.h>
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <linux/mm.h>
18#include <linux/swap.h>
19#include <linux/bootmem.h>
20#include <linux/irq.h>
21
22#include <asm/atomic.h>
23#include <asm/page.h>
24#include <asm/machdep.h>
25#include <asm/v850e_timer_d.h>
26
27#include "mach.h"
28
29void __init mach_sched_init (struct irqaction *timer_action)
30{
31 /* Select timer interrupt instead of external pin. */
32 TEG_ISS |= 0x1;
33 /* Start hardware timer. */
34 v850e_timer_d_configure (0, HZ);
35 /* Install timer interrupt handler. */
36 setup_irq (IRQ_INTCMD(0), timer_action);
37}
38
39static struct v850e_intc_irq_init irq_inits[] = {
40 { "IRQ", 0, NUM_CPU_IRQS, 1, 7 },
41 { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 5 },
42 { "SER", IRQ_INTSER(0), IRQ_INTSER_NUM, 1, 3 },
43 { "SR", IRQ_INTSR(0), IRQ_INTSR_NUM, 1, 4 },
44 { "ST", IRQ_INTST(0), IRQ_INTST_NUM, 1, 5 },
45 { 0 }
46};
47#define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1)
48
49static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
50
51/* Initialize MA chip interrupts. */
52void __init teg_init_irqs (void)
53{
54 v850e_intc_init_irq_types (irq_inits, hw_itypes);
55}
56
57/* Called before configuring an on-chip UART. */
58void teg_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud)
59{
60 /* Enable UART I/O pins instead of external interrupt pins, and
61 UART interrupts instead of external pin interrupts. */
62 TEG_ISS |= 0x4E;
63}
diff --git a/arch/v850/kernel/time.c b/arch/v850/kernel/time.c
new file mode 100644
index 000000000000..f722a268238a
--- /dev/null
+++ b/arch/v850/kernel/time.c
@@ -0,0 +1,198 @@
1/*
2 * linux/arch/v850/kernel/time.c -- Arch-dependent timer functions
3 *
4 * Copyright (C) 1991, 1992, 1995, 2001, 2002 Linus Torvalds
5 *
6 * This file contains the v850-specific time handling details.
7 * Most of the stuff is located in the machine specific files.
8 *
9 * 1997-09-10 Updated NTP code according to technical memorandum Jan '96
10 * "A Kernel Model for Precision Timekeeping" by Dave Mills
11 */
12
13#include <linux/config.h> /* CONFIG_HEARTBEAT */
14#include <linux/errno.h>
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/param.h>
18#include <linux/string.h>
19#include <linux/mm.h>
20#include <linux/interrupt.h>
21#include <linux/time.h>
22#include <linux/timex.h>
23#include <linux/profile.h>
24
25#include <asm/io.h>
26
27#include "mach.h"
28
29u64 jiffies_64 = INITIAL_JIFFIES;
30
31EXPORT_SYMBOL(jiffies_64);
32
33#define TICK_SIZE (tick_nsec / 1000)
34
35/*
36 * Scheduler clock - returns current time in nanosec units.
37 */
38unsigned long long sched_clock(void)
39{
40 return (unsigned long long)jiffies * (1000000000 / HZ);
41}
42
43/*
44 * timer_interrupt() needs to keep up the real-time clock,
45 * as well as call the "do_timer()" routine every clocktick
46 */
47static irqreturn_t timer_interrupt (int irq, void *dummy, struct pt_regs *regs)
48{
49#if 0
50 /* last time the cmos clock got updated */
51 static long last_rtc_update=0;
52#endif
53
54 /* may need to kick the hardware timer */
55 if (mach_tick)
56 mach_tick ();
57
58 do_timer (regs);
59#ifndef CONFIG_SMP
60 update_process_times(user_mode(regs));
61#endif
62 profile_tick(CPU_PROFILING, regs);
63#if 0
64 /*
65 * If we have an externally synchronized Linux clock, then update
66 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
67 * called as close as possible to 500 ms before the new second starts.
68 */
69 if ((time_status & STA_UNSYNC) == 0 &&
70 xtime.tv_sec > last_rtc_update + 660 &&
71 (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
72 (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
73 if (set_rtc_mmss (xtime.tv_sec) == 0)
74 last_rtc_update = xtime.tv_sec;
75 else
76 last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
77 }
78#ifdef CONFIG_HEARTBEAT
79 /* use power LED as a heartbeat instead -- much more useful
80 for debugging -- based on the version for PReP by Cort */
81 /* acts like an actual heart beat -- ie thump-thump-pause... */
82 if (mach_heartbeat) {
83 static unsigned cnt = 0, period = 0, dist = 0;
84
85 if (cnt == 0 || cnt == dist)
86 mach_heartbeat ( 1 );
87 else if (cnt == 7 || cnt == dist+7)
88 mach_heartbeat ( 0 );
89
90 if (++cnt > period) {
91 cnt = 0;
92 /* The hyperbolic function below modifies the heartbeat period
93 * length in dependency of the current (5min) load. It goes
94 * through the points f(0)=126, f(1)=86, f(5)=51,
95 * f(inf)->30. */
96 period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
97 dist = period / 4;
98 }
99 }
100#endif /* CONFIG_HEARTBEAT */
101#endif /* 0 */
102
103 return IRQ_HANDLED;
104}
105
106/*
107 * This version of gettimeofday has near microsecond resolution.
108 */
109void do_gettimeofday (struct timeval *tv)
110{
111#if 0 /* DAVIDM later if possible */
112 extern volatile unsigned long lost_ticks;
113 unsigned long lost;
114#endif
115 unsigned long flags;
116 unsigned long usec, sec;
117 unsigned long seq;
118
119 do {
120 seq = read_seqbegin_irqsave(&xtime_lock, flags);
121
122#if 0
123 usec = mach_gettimeoffset ? mach_gettimeoffset () : 0;
124#else
125 usec = 0;
126#endif
127#if 0 /* DAVIDM later if possible */
128 lost = lost_ticks;
129 if (lost)
130 usec += lost * (1000000/HZ);
131#endif
132 sec = xtime.tv_sec;
133 usec += xtime.tv_nsec / 1000;
134 } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
135
136 while (usec >= 1000000) {
137 usec -= 1000000;
138 sec++;
139 }
140
141 tv->tv_sec = sec;
142 tv->tv_usec = usec;
143}
144
145EXPORT_SYMBOL(do_gettimeofday);
146
147int do_settimeofday(struct timespec *tv)
148{
149 if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
150 return -EINVAL;
151
152 write_seqlock_irq (&xtime_lock);
153
154 /* This is revolting. We need to set the xtime.tv_nsec
155 * correctly. However, the value in this location is
156 * is value at the last tick.
157 * Discover what correction gettimeofday
158 * would have done, and then undo it!
159 */
160#if 0
161 tv->tv_nsec -= mach_gettimeoffset() * 1000;
162#endif
163
164 while (tv->tv_nsec < 0) {
165 tv->tv_nsec += NSEC_PER_SEC;
166 tv->tv_sec--;
167 }
168
169 xtime.tv_sec = tv->tv_sec;
170 xtime.tv_nsec = tv->tv_nsec;
171
172 time_adjust = 0; /* stop active adjtime () */
173 time_status |= STA_UNSYNC;
174 time_maxerror = NTP_PHASE_LIMIT;
175 time_esterror = NTP_PHASE_LIMIT;
176
177 write_sequnlock_irq (&xtime_lock);
178 clock_was_set();
179 return 0;
180}
181
182EXPORT_SYMBOL(do_settimeofday);
183
184static int timer_dev_id;
185static struct irqaction timer_irqaction = {
186 timer_interrupt,
187 SA_INTERRUPT,
188 CPU_MASK_NONE,
189 "timer",
190 &timer_dev_id,
191 NULL
192};
193
194void time_init (void)
195{
196 mach_gettimeofday (&xtime);
197 mach_sched_init (&timer_irqaction);
198}
diff --git a/arch/v850/kernel/v850_ksyms.c b/arch/v850/kernel/v850_ksyms.c
new file mode 100644
index 000000000000..0ca64900dd91
--- /dev/null
+++ b/arch/v850/kernel/v850_ksyms.c
@@ -0,0 +1,78 @@
1#include <linux/module.h>
2#include <linux/linkage.h>
3#include <linux/sched.h>
4#include <linux/string.h>
5#include <linux/mm.h>
6#include <linux/user.h>
7#include <linux/elfcore.h>
8#include <linux/in6.h>
9#include <linux/interrupt.h>
10#include <linux/config.h>
11
12#include <asm/pgalloc.h>
13#include <asm/irq.h>
14#include <asm/io.h>
15#include <asm/semaphore.h>
16#include <asm/checksum.h>
17#include <asm/current.h>
18
19
20extern void *trap_table;
21EXPORT_SYMBOL (trap_table);
22
23/* platform dependent support */
24extern void dump_thread (struct pt_regs *, struct user *);
25EXPORT_SYMBOL (dump_thread);
26EXPORT_SYMBOL (kernel_thread);
27EXPORT_SYMBOL (enable_irq);
28EXPORT_SYMBOL (disable_irq);
29EXPORT_SYMBOL (disable_irq_nosync);
30EXPORT_SYMBOL (__bug);
31
32/* Networking helper routines. */
33EXPORT_SYMBOL (csum_partial_copy);
34EXPORT_SYMBOL (csum_partial_copy_from_user);
35EXPORT_SYMBOL (ip_compute_csum);
36EXPORT_SYMBOL (ip_fast_csum);
37
38/* string / mem functions */
39EXPORT_SYMBOL (strcpy);
40EXPORT_SYMBOL (strncpy);
41EXPORT_SYMBOL (strcat);
42EXPORT_SYMBOL (strncat);
43EXPORT_SYMBOL (strcmp);
44EXPORT_SYMBOL (strncmp);
45EXPORT_SYMBOL (strchr);
46EXPORT_SYMBOL (strlen);
47EXPORT_SYMBOL (strnlen);
48EXPORT_SYMBOL (strpbrk);
49EXPORT_SYMBOL (strrchr);
50EXPORT_SYMBOL (strstr);
51EXPORT_SYMBOL (memset);
52EXPORT_SYMBOL (memcpy);
53EXPORT_SYMBOL (memmove);
54EXPORT_SYMBOL (memcmp);
55EXPORT_SYMBOL (memscan);
56
57/* semaphores */
58EXPORT_SYMBOL (__down);
59EXPORT_SYMBOL (__down_interruptible);
60EXPORT_SYMBOL (__down_trylock);
61EXPORT_SYMBOL (__up);
62
63/*
64 * libgcc functions - functions that are used internally by the
65 * compiler... (prototypes are not correct though, but that
66 * doesn't really matter since they're not versioned).
67 */
68extern void __ashldi3 (void);
69extern void __ashrdi3 (void);
70extern void __lshrdi3 (void);
71extern void __muldi3 (void);
72extern void __negdi2 (void);
73
74EXPORT_SYMBOL (__ashldi3);
75EXPORT_SYMBOL (__ashrdi3);
76EXPORT_SYMBOL (__lshrdi3);
77EXPORT_SYMBOL (__muldi3);
78EXPORT_SYMBOL (__negdi2);
diff --git a/arch/v850/kernel/v850e2_cache.c b/arch/v850/kernel/v850e2_cache.c
new file mode 100644
index 000000000000..4570312c689c
--- /dev/null
+++ b/arch/v850/kernel/v850e2_cache.c
@@ -0,0 +1,127 @@
1/*
2 * arch/v850/kernel/v850e2_cache.c -- Cache control for V850E2 cache
3 * memories
4 *
5 * Copyright (C) 2003 NEC Electronics Corporation
6 * Copyright (C) 2003 Miles Bader <miles@gnu.org>
7 *
8 * This file is subject to the terms and conditions of the GNU General
9 * Public License. See the file COPYING in the main directory of this
10 * archive for more details.
11 *
12 * Written by Miles Bader <miles@gnu.org>
13 */
14
15#include <linux/mm.h>
16
17#include <asm/v850e2_cache.h>
18
19/* Cache operations we can do. The encoding corresponds directly to the
20 value we need to write into the COPR register. */
21enum cache_op {
22 OP_SYNC_IF_DIRTY = V850E2_CACHE_COPR_CFC(0), /* 000 */
23 OP_SYNC_IF_VALID = V850E2_CACHE_COPR_CFC(1), /* 001 */
24 OP_SYNC_IF_VALID_AND_CLEAR = V850E2_CACHE_COPR_CFC(3), /* 011 */
25 OP_WAY_CLEAR = V850E2_CACHE_COPR_CFC(4), /* 100 */
26 OP_FILL = V850E2_CACHE_COPR_CFC(5), /* 101 */
27 OP_CLEAR = V850E2_CACHE_COPR_CFC(6), /* 110 */
28 OP_CREATE_DIRTY = V850E2_CACHE_COPR_CFC(7) /* 111 */
29};
30
31/* Which cache to use. This encoding also corresponds directly to the
32 value we need to write into the COPR register. */
33enum cache {
34 ICACHE = 0,
35 DCACHE = V850E2_CACHE_COPR_LBSL
36};
37
38/* Returns ADDR rounded down to the beginning of its cache-line. */
39#define CACHE_LINE_ADDR(addr) \
40 ((addr) & ~(V850E2_CACHE_LINE_SIZE - 1))
41/* Returns END_ADDR rounded up to the `limit' of its cache-line. */
42#define CACHE_LINE_END_ADDR(end_addr) \
43 CACHE_LINE_ADDR(end_addr + (V850E2_CACHE_LINE_SIZE - 1))
44
45
46/* Low-level cache ops. */
47
48/* Apply cache-op OP to all entries in CACHE. */
49static inline void cache_op_all (enum cache_op op, enum cache cache)
50{
51 int cmd = op | cache | V850E2_CACHE_COPR_WSLE | V850E2_CACHE_COPR_STRT;
52
53 if (op != OP_WAY_CLEAR) {
54 /* The WAY_CLEAR operation does the whole way, but other
55 ops take begin-index and count params; we just indicate
56 the entire cache. */
57 V850E2_CACHE_CADL = 0;
58 V850E2_CACHE_CADH = 0;
59 V850E2_CACHE_CCNT = V850E2_CACHE_WAY_SIZE - 1;
60 }
61
62 V850E2_CACHE_COPR = cmd | V850E2_CACHE_COPR_WSL(0); /* way 0 */
63 V850E2_CACHE_COPR = cmd | V850E2_CACHE_COPR_WSL(1); /* way 1 */
64 V850E2_CACHE_COPR = cmd | V850E2_CACHE_COPR_WSL(2); /* way 2 */
65 V850E2_CACHE_COPR = cmd | V850E2_CACHE_COPR_WSL(3); /* way 3 */
66}
67
68/* Apply cache-op OP to all entries in CACHE covering addresses ADDR
69 through ADDR+LEN. */
70static inline void cache_op_range (enum cache_op op, u32 addr, u32 len,
71 enum cache cache)
72{
73 u32 start = CACHE_LINE_ADDR (addr);
74 u32 end = CACHE_LINE_END_ADDR (addr + len);
75 u32 num_lines = (end - start) >> V850E2_CACHE_LINE_SIZE_BITS;
76
77 V850E2_CACHE_CADL = start & 0xFFFF;
78 V850E2_CACHE_CADH = start >> 16;
79 V850E2_CACHE_CCNT = num_lines - 1;
80
81 V850E2_CACHE_COPR = op | cache | V850E2_CACHE_COPR_STRT;
82}
83
84
85/* High-level ops. */
86
87static void cache_exec_after_store_all (void)
88{
89 cache_op_all (OP_SYNC_IF_DIRTY, DCACHE);
90 cache_op_all (OP_WAY_CLEAR, ICACHE);
91}
92
93static void cache_exec_after_store_range (u32 start, u32 len)
94{
95 cache_op_range (OP_SYNC_IF_DIRTY, start, len, DCACHE);
96 cache_op_range (OP_CLEAR, start, len, ICACHE);
97}
98
99
100/* Exported functions. */
101
102void flush_icache (void)
103{
104 cache_exec_after_store_all ();
105}
106
107void flush_icache_range (unsigned long start, unsigned long end)
108{
109 cache_exec_after_store_range (start, end - start);
110}
111
112void flush_icache_page (struct vm_area_struct *vma, struct page *page)
113{
114 cache_exec_after_store_range (page_to_virt (page), PAGE_SIZE);
115}
116
117void flush_icache_user_range (struct vm_area_struct *vma, struct page *page,
118 unsigned long addr, int len)
119{
120 cache_exec_after_store_range (addr, len);
121}
122
123void flush_cache_sigtramp (unsigned long addr)
124{
125 /* For the exact size, see signal.c, but 16 bytes should be enough. */
126 cache_exec_after_store_range (addr, 16);
127}
diff --git a/arch/v850/kernel/v850e_cache.c b/arch/v850/kernel/v850e_cache.c
new file mode 100644
index 000000000000..ea3e51cfb259
--- /dev/null
+++ b/arch/v850/kernel/v850e_cache.c
@@ -0,0 +1,174 @@
1/*
2 * arch/v850/kernel/v850e_cache.c -- Cache control for V850E cache memories
3 *
4 * Copyright (C) 2003 NEC Electronics Corporation
5 * Copyright (C) 2003 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14/* This file implements cache control for the rather simple cache used on
15 some V850E CPUs, specifically the NB85E/TEG CPU-core and the V850E/ME2
16 CPU. V850E2 processors have their own (better) cache
17 implementation. */
18
19#include <asm/entry.h>
20#include <asm/cacheflush.h>
21#include <asm/v850e_cache.h>
22
23#define WAIT_UNTIL_CLEAR(value) while (value) {}
24
25/* Set caching params via the BHC and DCC registers. */
26void v850e_cache_enable (u16 bhc, u16 icc, u16 dcc)
27{
28 unsigned long *r0_ram = (unsigned long *)R0_RAM_ADDR;
29 register u16 bhc_val asm ("r6") = bhc;
30
31 /* Read the instruction cache control register (ICC) and confirm
32 that bits 0 and 1 (TCLR0, TCLR1) are all cleared. */
33 WAIT_UNTIL_CLEAR (V850E_CACHE_ICC & 0x3);
34 V850E_CACHE_ICC = icc;
35
36#ifdef V850E_CACHE_DCC
37 /* Configure data-cache. */
38 V850E_CACHE_DCC = dcc;
39#endif /* V850E_CACHE_DCC */
40
41 /* Configure caching for various memory regions by writing the BHC
42 register. The documentation says that an instruction _cannot_
43 enable/disable caching for the memory region in which the
44 instruction itself exists; to work around this, we store
45 appropriate instructions into the on-chip RAM area (which is never
46 cached), and briefly jump there to do the work. */
47#ifdef V850E_CACHE_WRITE_IBS
48 *r0_ram++ = 0xf0720760; /* st.h r0, 0xfffff072[r0] */
49#endif
50 *r0_ram++ = 0xf06a3760; /* st.h r6, 0xfffff06a[r0] */
51 *r0_ram = 0x5640006b; /* jmp [r11] */
52
53 asm ("mov hilo(1f), r11; jmp [%1]; 1:;"
54 :: "r" (bhc_val), "r" (R0_RAM_ADDR) : "r11");
55}
56
57static void clear_icache (void)
58{
59 /* 1. Read the instruction cache control register (ICC) and confirm
60 that bits 0 and 1 (TCLR0, TCLR1) are all cleared. */
61 WAIT_UNTIL_CLEAR (V850E_CACHE_ICC & 0x3);
62
63 /* 2. Read the ICC register and confirm that bit 12 (LOCK0) is
64 cleared. Bit 13 of the ICC register is always cleared. */
65 WAIT_UNTIL_CLEAR (V850E_CACHE_ICC & 0x1000);
66
67 /* 3. Set the TCLR0 and TCLR1 bits of the ICC register as follows,
68 when clearing way 0 and way 1 at the same time:
69 (a) Set the TCLR0 and TCLR1 bits.
70 (b) Read the TCLR0 and TCLR1 bits to confirm that these bits
71 are cleared.
72 (c) Perform (a) and (b) above again. */
73 V850E_CACHE_ICC |= 0x3;
74 WAIT_UNTIL_CLEAR (V850E_CACHE_ICC & 0x3);
75
76#ifdef V850E_CACHE_REPEAT_ICC_WRITE
77 /* Do it again. */
78 V850E_CACHE_ICC |= 0x3;
79 WAIT_UNTIL_CLEAR (V850E_CACHE_ICC & 0x3);
80#endif
81}
82
83#ifdef V850E_CACHE_DCC
84/* Flush or clear (or both) the data cache, depending on the value of FLAGS;
85 the procedure is the same for both, just the control bits used differ (and
86 both may be performed simultaneously). */
87static void dcache_op (unsigned short flags)
88{
89 /* 1. Read the data cache control register (DCC) and confirm that bits
90 0, 1, 4, and 5 (DC00, DC01, DC04, DC05) are all cleared. */
91 WAIT_UNTIL_CLEAR (V850E_CACHE_DCC & 0x33);
92
93 /* 2. Clear DCC register bit 12 (DC12), bit 13 (DC13), or both
94 depending on the way for which tags are to be cleared. */
95 V850E_CACHE_DCC &= ~0xC000;
96
97 /* 3. Set DCC register bit 0 (DC00), bit 1 (DC01) or both depending on
98 the way for which tags are to be cleared.
99 ...
100 Set DCC register bit 4 (DC04), bit 5 (DC05), or both depending
101 on the way to be data flushed. */
102 V850E_CACHE_DCC |= flags;
103
104 /* 4. Read DCC register bit DC00, DC01 [DC04, DC05], or both depending
105 on the way for which tags were cleared [flushed] and confirm
106 that that bit is cleared. */
107 WAIT_UNTIL_CLEAR (V850E_CACHE_DCC & flags);
108}
109#endif /* V850E_CACHE_DCC */
110
111/* Flushes the contents of the dcache to memory. */
112static inline void flush_dcache (void)
113{
114#ifdef V850E_CACHE_DCC
115 /* We only need to do something if in write-back mode. */
116 if (V850E_CACHE_DCC & 0x0400)
117 dcache_op (0x30);
118#endif /* V850E_CACHE_DCC */
119}
120
121/* Flushes the contents of the dcache to memory, and then clears it. */
122static inline void clear_dcache (void)
123{
124#ifdef V850E_CACHE_DCC
125 /* We only need to do something if the dcache is enabled. */
126 if (V850E_CACHE_DCC & 0x0C00)
127 dcache_op (0x33);
128#endif /* V850E_CACHE_DCC */
129}
130
131/* Clears the dcache without flushing to memory first. */
132static inline void clear_dcache_no_flush (void)
133{
134#ifdef V850E_CACHE_DCC
135 /* We only need to do something if the dcache is enabled. */
136 if (V850E_CACHE_DCC & 0x0C00)
137 dcache_op (0x3);
138#endif /* V850E_CACHE_DCC */
139}
140
141static inline void cache_exec_after_store (void)
142{
143 flush_dcache ();
144 clear_icache ();
145}
146
147
148/* Exported functions. */
149
150void flush_icache (void)
151{
152 cache_exec_after_store ();
153}
154
155void flush_icache_range (unsigned long start, unsigned long end)
156{
157 cache_exec_after_store ();
158}
159
160void flush_icache_page (struct vm_area_struct *vma, struct page *page)
161{
162 cache_exec_after_store ();
163}
164
165void flush_icache_user_range (struct vm_area_struct *vma, struct page *page,
166 unsigned long adr, int len)
167{
168 cache_exec_after_store ();
169}
170
171void flush_cache_sigtramp (unsigned long addr)
172{
173 cache_exec_after_store ();
174}
diff --git a/arch/v850/kernel/v850e_intc.c b/arch/v850/kernel/v850e_intc.c
new file mode 100644
index 000000000000..8d39a52ee6d1
--- /dev/null
+++ b/arch/v850/kernel/v850e_intc.c
@@ -0,0 +1,104 @@
1/*
2 * arch/v850/kernel/v850e_intc.c -- V850E interrupt controller (INTC)
3 *
4 * Copyright (C) 2001,02,03 NEC Electronics Corporation
5 * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14#include <linux/kernel.h>
15#include <linux/init.h>
16#include <linux/irq.h>
17
18#include <asm/v850e_intc.h>
19
20static void irq_nop (unsigned irq) { }
21
22static unsigned v850e_intc_irq_startup (unsigned irq)
23{
24 v850e_intc_clear_pending_irq (irq);
25 v850e_intc_enable_irq (irq);
26 return 0;
27}
28
29static void v850e_intc_end_irq (unsigned irq)
30{
31 unsigned long psw, temp;
32
33 /* Clear the highest-level bit in the In-service priority register
34 (ISPR), to allow this interrupt (or another of the same or
35 lesser priority) to happen again.
36
37 The `reti' instruction normally does this automatically when the
38 PSW bits EP and NP are zero, but we can't always rely on reti
39 being used consistently to return after an interrupt (another
40 process can be scheduled, for instance, which can delay the
41 associated reti for a long time, or this process may be being
42 single-stepped, which uses the `dbret' instruction to return
43 from the kernel).
44
45 We also set the PSW EP bit, which prevents reti from also
46 trying to modify the ISPR itself. */
47
48 /* Get PSW and disable interrupts. */
49 asm volatile ("stsr psw, %0; di" : "=r" (psw));
50 /* We don't want to do anything for NMIs (they don't use the ISPR). */
51 if (! (psw & 0xC0)) {
52 /* Transition to `trap' state, so that an eventual real
53 reti instruction won't modify the ISPR. */
54 psw |= 0x40;
55 /* Fake an interrupt return, which automatically clears the
56 appropriate bit in the ISPR. */
57 asm volatile ("mov hilo(1f), %0;"
58 "ldsr %0, eipc; ldsr %1, eipsw;"
59 "reti;"
60 "1:"
61 : "=&r" (temp) : "r" (psw));
62 }
63}
64
65/* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array
66 INITS (which is terminated by an entry with the name field == 0). */
67void __init v850e_intc_init_irq_types (struct v850e_intc_irq_init *inits,
68 struct hw_interrupt_type *hw_irq_types)
69{
70 struct v850e_intc_irq_init *init;
71 for (init = inits; init->name; init++) {
72 unsigned i;
73 struct hw_interrupt_type *hwit = hw_irq_types++;
74
75 hwit->typename = init->name;
76
77 hwit->startup = v850e_intc_irq_startup;
78 hwit->shutdown = v850e_intc_disable_irq;
79 hwit->enable = v850e_intc_enable_irq;
80 hwit->disable = v850e_intc_disable_irq;
81 hwit->ack = irq_nop;
82 hwit->end = v850e_intc_end_irq;
83
84 /* Initialize kernel IRQ infrastructure for this interrupt. */
85 init_irq_handlers(init->base, init->num, init->interval, hwit);
86
87 /* Set the interrupt priorities. */
88 for (i = 0; i < init->num; i++) {
89 unsigned irq = init->base + i * init->interval;
90
91 /* If the interrupt is currently enabled (all
92 interrupts are initially disabled), then
93 assume whoever enabled it has set things up
94 properly, and avoid messing with it. */
95 if (! v850e_intc_irq_enabled (irq))
96 /* This write also (1) disables the
97 interrupt, and (2) clears any pending
98 interrupts. */
99 V850E_INTC_IC (irq)
100 = (V850E_INTC_IC_PR (init->priority)
101 | V850E_INTC_IC_MK);
102 }
103 }
104}
diff --git a/arch/v850/kernel/v850e_timer_d.c b/arch/v850/kernel/v850e_timer_d.c
new file mode 100644
index 000000000000..d2a4ece2574c
--- /dev/null
+++ b/arch/v850/kernel/v850e_timer_d.c
@@ -0,0 +1,54 @@
1/*
2 * include/asm-v850/v850e_timer_d.c -- `Timer D' component often used
3 * with V850E CPUs
4 *
5 * Copyright (C) 2001,02,03 NEC Electronics Corporation
6 * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
7 *
8 * This file is subject to the terms and conditions of the GNU General
9 * Public License. See the file COPYING in the main directory of this
10 * archive for more details.
11 *
12 * Written by Miles Bader <miles@gnu.org>
13 */
14
15#include <linux/kernel.h>
16
17#include <asm/v850e_utils.h>
18#include <asm/v850e_timer_d.h>
19
20/* Start interval timer TIMER (0-3). The timer will issue the
21 corresponding INTCMD interrupt RATE times per second.
22 This function does not enable the interrupt. */
23void v850e_timer_d_configure (unsigned timer, unsigned rate)
24{
25 unsigned divlog2, count;
26
27 /* Calculate params for timer. */
28 if (! calc_counter_params (
29 V850E_TIMER_D_BASE_FREQ, rate,
30 V850E_TIMER_D_TMCD_CS_MIN, V850E_TIMER_D_TMCD_CS_MAX, 16,
31 &divlog2, &count))
32 printk (KERN_WARNING
33 "Cannot find interval timer %d setting suitable"
34 " for rate of %dHz.\n"
35 "Using rate of %dHz instead.\n",
36 timer, rate,
37 (V850E_TIMER_D_BASE_FREQ >> divlog2) >> 16);
38
39 /* Do the actual hardware timer initialization: */
40
41 /* Enable timer. */
42 V850E_TIMER_D_TMCD(timer) = V850E_TIMER_D_TMCD_CAE;
43 /* Set clock divider. */
44 V850E_TIMER_D_TMCD(timer)
45 = V850E_TIMER_D_TMCD_CAE
46 | V850E_TIMER_D_TMCD_CS(divlog2);
47 /* Set timer compare register. */
48 V850E_TIMER_D_CMD(timer) = count;
49 /* Start counting. */
50 V850E_TIMER_D_TMCD(timer)
51 = V850E_TIMER_D_TMCD_CAE
52 | V850E_TIMER_D_TMCD_CS(divlog2)
53 | V850E_TIMER_D_TMCD_CE;
54}
diff --git a/arch/v850/kernel/v850e_utils.c b/arch/v850/kernel/v850e_utils.c
new file mode 100644
index 000000000000..e6807ef8dee6
--- /dev/null
+++ b/arch/v850/kernel/v850e_utils.c
@@ -0,0 +1,62 @@
1/*
2 * include/asm-v850/v850e_utils.h -- Utility functions associated with
3 * V850E CPUs
4 *
5 * Copyright (C) 2001,02,03 NEC Electronics Corporation
6 * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
7 *
8 * This file is subject to the terms and conditions of the GNU General
9 * Public License. See the file COPYING in the main directory of this
10 * archive for more details.
11 *
12 * Written by Miles Bader <miles@gnu.org>
13 */
14
15#include <asm/v850e_utils.h>
16
17/* Calculate counter clock-divider and count values to attain the
18 desired frequency RATE from the base frequency BASE_FREQ. The
19 counter is expected to have a clock-divider, which can divide the
20 system cpu clock by a power of two value from MIN_DIVLOG2 to
21 MAX_DIV_LOG2, and a word-size of COUNTER_SIZE bits (the counter
22 counts up and resets whenever it's equal to the compare register,
23 generating an interrupt or whatever when it does so). The returned
24 values are: *DIVLOG2 -- log2 of the desired clock divider and *COUNT
25 -- the counter compare value to use. Returns true if it was possible
26 to find a reasonable value, otherwise false (and the other return
27 values will be set to be as good as possible). */
28int calc_counter_params (unsigned long base_freq,
29 unsigned long rate,
30 unsigned min_divlog2, unsigned max_divlog2,
31 unsigned counter_size,
32 unsigned *divlog2, unsigned *count)
33{
34 unsigned _divlog2;
35 int ok = 0;
36
37 /* Find the lowest clock divider setting that can represent RATE. */
38 for (_divlog2 = min_divlog2; _divlog2 <= max_divlog2; _divlog2++) {
39 /* Minimum interrupt rate possible using this divider. */
40 unsigned min_int_rate
41 = (base_freq >> _divlog2) >> counter_size;
42
43 if (min_int_rate <= rate) {
44 /* This setting is the highest resolution
45 setting that's slow enough enough to attain
46 RATE interrupts per second, so use it. */
47 ok = 1;
48 break;
49 }
50 }
51
52 if (_divlog2 > max_divlog2)
53 /* Can't find correct setting. */
54 _divlog2 = max_divlog2;
55
56 if (divlog2)
57 *divlog2 = _divlog2;
58 if (count)
59 *count = ((base_freq >> _divlog2) + rate/2) / rate;
60
61 return ok;
62}
diff --git a/arch/v850/kernel/vmlinux.lds.S b/arch/v850/kernel/vmlinux.lds.S
new file mode 100644
index 000000000000..bbd3429bcffc
--- /dev/null
+++ b/arch/v850/kernel/vmlinux.lds.S
@@ -0,0 +1,285 @@
1/*
2 * arch/v850/vmlinux.lds.S -- kernel linker script for v850 platforms
3 *
4 * Copyright (C) 2002,03,04 NEC Electronics Corporation
5 * Copyright (C) 2002,03,04 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14#include <linux/config.h>
15#define VMLINUX_SYMBOL(_sym_) _##_sym_
16#include <asm-generic/vmlinux.lds.h>
17
18/* For most platforms, this will define useful things like RAM addr/size. */
19#include <asm/machdep.h>
20
21
22/* The following macros contain the usual definitions for various data areas.
23 The prefix `RAMK_' is used to indicate macros suitable for kernels loaded
24 into RAM, and similarly `ROMK_' for ROM-resident kernels. Note that all
25 symbols are prefixed with an extra `_' for compatibility with the v850
26 toolchain. */
27
28
29/* Interrupt vectors. */
30#define INTV_CONTENTS \
31 . = ALIGN (0x10) ; \
32 __intv_start = . ; \
33 *(.intv.reset) /* Reset vector */ \
34 . = __intv_start + 0x10 ; \
35 *(.intv.common) /* Vectors common to all v850e proc */\
36 . = __intv_start + 0x80 ; \
37 *(.intv.mach) /* Machine-specific int. vectors. */ \
38 __intv_end = . ;
39
40#define RODATA_CONTENTS \
41 . = ALIGN (16) ; \
42 *(.rodata) *(.rodata.*) \
43 *(__vermagic) /* Kernel version magic */ \
44 *(.rodata1) \
45 /* Kernel symbol table: Normal symbols */ \
46 ___start___ksymtab = .; \
47 *(__ksymtab) \
48 ___stop___ksymtab = .; \
49 /* Kernel symbol table: GPL-only symbols */ \
50 ___start___ksymtab_gpl = .; \
51 *(__ksymtab_gpl) \
52 ___stop___ksymtab_gpl = .; \
53 /* Kernel symbol table: strings */ \
54 *(__ksymtab_strings) \
55 /* Kernel symbol table: Normal symbols */ \
56 ___start___kcrctab = .; \
57 *(__kcrctab) \
58 ___stop___kcrctab = .; \
59 /* Kernel symbol table: GPL-only symbols */ \
60 ___start___kcrctab_gpl = .; \
61 *(__kcrctab_gpl) \
62 ___stop___kcrctab_gpl = .; \
63 /* Built-in module parameters */ \
64 ___start___param = .; \
65 *(__param) \
66 ___stop___param = .;
67
68
69/* Kernel text segment, and some constant data areas. */
70#define TEXT_CONTENTS \
71 __stext = . ; \
72 *(.text) \
73 SCHED_TEXT \
74 *(.exit.text) /* 2.5 convention */ \
75 *(.text.exit) /* 2.4 convention */ \
76 *(.text.lock) \
77 *(.exitcall.exit) \
78 __real_etext = . ; /* There may be data after here. */ \
79 RODATA_CONTENTS \
80 . = ALIGN (4) ; \
81 *(.call_table_data) \
82 *(.call_table_text) \
83 . = ALIGN (16) ; /* Exception table. */ \
84 ___start___ex_table = . ; \
85 *(__ex_table) \
86 ___stop___ex_table = . ; \
87 . = ALIGN (4) ; \
88 __etext = . ;
89
90/* Kernel data segment. */
91#define DATA_CONTENTS \
92 __sdata = . ; \
93 *(.data) \
94 *(.exit.data) /* 2.5 convention */ \
95 *(.data.exit) /* 2.4 convention */ \
96 . = ALIGN (16) ; \
97 *(.data.cacheline_aligned) \
98 . = ALIGN (0x2000) ; \
99 *(.data.init_task) \
100 . = ALIGN (0x2000) ; \
101 __edata = . ;
102
103/* Kernel BSS segment. */
104#define BSS_CONTENTS \
105 __sbss = . ; \
106 *(.bss) \
107 *(COMMON) \
108 . = ALIGN (4) ; \
109 __init_stack_end = . ; \
110 __ebss = . ;
111
112/* `initcall' tables. */
113#define INITCALL_CONTENTS \
114 . = ALIGN (16) ; \
115 ___setup_start = . ; \
116 *(.init.setup) /* 2.5 convention */ \
117 *(.setup.init) /* 2.4 convention */ \
118 ___setup_end = . ; \
119 ___initcall_start = . ; \
120 *(.initcall.init) \
121 *(.initcall1.init) \
122 *(.initcall2.init) \
123 *(.initcall3.init) \
124 *(.initcall4.init) \
125 *(.initcall5.init) \
126 *(.initcall6.init) \
127 *(.initcall7.init) \
128 . = ALIGN (4) ; \
129 ___initcall_end = . ; \
130 ___con_initcall_start = .; \
131 *(.con_initcall.init) \
132 ___con_initcall_end = .;
133
134/* Contents of `init' section for a kernel that's loaded into RAM. */
135#define RAMK_INIT_CONTENTS \
136 RAMK_INIT_CONTENTS_NO_END \
137 __init_end = . ;
138/* Same as RAMK_INIT_CONTENTS, but doesn't define the `__init_end' symbol. */
139#define RAMK_INIT_CONTENTS_NO_END \
140 . = ALIGN (4096) ; \
141 __init_start = . ; \
142 __sinittext = .; \
143 *(.init.text) /* 2.5 convention */ \
144 __einittext = .; \
145 *(.init.data) \
146 *(.text.init) /* 2.4 convention */ \
147 *(.data.init) \
148 INITCALL_CONTENTS \
149 INITRAMFS_CONTENTS
150
151/* The contents of `init' section for a ROM-resident kernel which
152 should go into RAM. */
153#define ROMK_INIT_RAM_CONTENTS \
154 . = ALIGN (4096) ; \
155 __init_start = . ; \
156 *(.init.data) /* 2.5 convention */ \
157 *(.data.init) /* 2.4 convention */ \
158 __init_end = . ; \
159 . = ALIGN (4096) ;
160
161/* The contents of `init' section for a ROM-resident kernel which
162 should go into ROM. */
163#define ROMK_INIT_ROM_CONTENTS \
164 _sinittext = .; \
165 *(.init.text) /* 2.5 convention */ \
166 _einittext = .; \
167 *(.text.init) /* 2.4 convention */ \
168 INITCALL_CONTENTS \
169 INITRAMFS_CONTENTS
170
171/* A root filesystem image, for kernels with an embedded root filesystem. */
172#define ROOT_FS_CONTENTS \
173 __root_fs_image_start = . ; \
174 *(.root) \
175 __root_fs_image_end = . ;
176/* The initramfs archive. */
177#define INITRAMFS_CONTENTS \
178 . = ALIGN (4) ; \
179 ___initramfs_start = . ; \
180 *(.init.ramfs) \
181 ___initramfs_end = . ;
182/* Where the initial bootmap (bitmap for the boot-time memory allocator)
183 should be place. */
184#define BOOTMAP_CONTENTS \
185 . = ALIGN (4096) ; \
186 __bootmap = . ; \
187 . = . + 4096 ; /* enough for 128MB. */
188
189/* The contents of a `typical' kram area for a kernel in RAM. */
190#define RAMK_KRAM_CONTENTS \
191 __kram_start = . ; \
192 TEXT_CONTENTS \
193 DATA_CONTENTS \
194 BSS_CONTENTS \
195 RAMK_INIT_CONTENTS \
196 __kram_end = . ; \
197 BOOTMAP_CONTENTS
198
199
200/* Define output sections normally used for a ROM-resident kernel.
201 ROM and RAM should be appropriate memory areas to use for kernel
202 ROM and RAM data. This assumes that ROM starts at 0 (and thus can
203 hold the interrupt vectors). */
204#define ROMK_SECTIONS(ROM, RAM) \
205 .rom : { \
206 INTV_CONTENTS \
207 TEXT_CONTENTS \
208 ROMK_INIT_ROM_CONTENTS \
209 ROOT_FS_CONTENTS \
210 } > ROM \
211 \
212 __rom_copy_src_start = . ; \
213 \
214 .data : { \
215 __kram_start = . ; \
216 __rom_copy_dst_start = . ; \
217 DATA_CONTENTS \
218 ROMK_INIT_RAM_CONTENTS \
219 __rom_copy_dst_end = . ; \
220 } > RAM AT> ROM \
221 \
222 .bss ALIGN (4) : { \
223 BSS_CONTENTS \
224 __kram_end = . ; \
225 BOOTMAP_CONTENTS \
226 } > RAM
227
228
229/* The 32-bit variable `jiffies' is just the lower 32-bits of `jiffies_64'. */
230_jiffies = _jiffies_64 ;
231
232
233/* Include an appropriate platform-dependent linker-script (which
234 usually should use the above macros to do most of the work). */
235
236#ifdef CONFIG_V850E_SIM
237# include "sim.ld"
238#endif
239
240#ifdef CONFIG_V850E2_SIM85E2
241# include "sim85e2.ld"
242#endif
243
244#ifdef CONFIG_V850E2_FPGA85E2C
245# include "fpga85e2c.ld"
246#endif
247
248#ifdef CONFIG_V850E2_ANNA
249# ifdef CONFIG_ROM_KERNEL
250# include "anna-rom.ld"
251# else
252# include "anna.ld"
253# endif
254#endif
255
256#ifdef CONFIG_V850E_AS85EP1
257# ifdef CONFIG_ROM_KERNEL
258# include "as85ep1-rom.ld"
259# else
260# include "as85ep1.ld"
261# endif
262#endif
263
264#ifdef CONFIG_RTE_CB_MA1
265# ifdef CONFIG_ROM_KERNEL
266# include "rte_ma1_cb-rom.ld"
267# else
268# include "rte_ma1_cb.ld"
269# endif
270#endif
271
272#ifdef CONFIG_RTE_CB_NB85E
273# ifdef CONFIG_ROM_KERNEL
274# include "rte_nb85e_cb-rom.ld"
275# elif defined(CONFIG_RTE_CB_MULTI)
276# include "rte_nb85e_cb-multi.ld"
277# else
278# include "rte_nb85e_cb.ld"
279# endif
280#endif
281
282#ifdef CONFIG_RTE_CB_ME2
283# include "rte_me2_cb.ld"
284#endif
285
diff --git a/arch/v850/lib/Makefile b/arch/v850/lib/Makefile
new file mode 100644
index 000000000000..1c78b728a117
--- /dev/null
+++ b/arch/v850/lib/Makefile
@@ -0,0 +1,6 @@
1#
2# arch/v850/lib/Makefile
3#
4
5lib-y = ashrdi3.o ashldi3.o lshrdi3.o muldi3.o negdi2.o \
6 checksum.o memcpy.o memset.o
diff --git a/arch/v850/lib/ashldi3.c b/arch/v850/lib/ashldi3.c
new file mode 100644
index 000000000000..9e792d53f0e4
--- /dev/null
+++ b/arch/v850/lib/ashldi3.c
@@ -0,0 +1,62 @@
1/* ashldi3.c extracted from gcc-2.95.2/libgcc2.c which is: */
2/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING. If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
20
21#define BITS_PER_UNIT 8
22
23typedef int SItype __attribute__ ((mode (SI)));
24typedef unsigned int USItype __attribute__ ((mode (SI)));
25typedef int DItype __attribute__ ((mode (DI)));
26typedef int word_type __attribute__ ((mode (__word__)));
27
28struct DIstruct {SItype high, low;};
29
30typedef union
31{
32 struct DIstruct s;
33 DItype ll;
34} DIunion;
35
36DItype
37__ashldi3 (DItype u, word_type b)
38{
39 DIunion w;
40 word_type bm;
41 DIunion uu;
42
43 if (b == 0)
44 return u;
45
46 uu.ll = u;
47
48 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
49 if (bm <= 0)
50 {
51 w.s.low = 0;
52 w.s.high = (USItype)uu.s.low << -bm;
53 }
54 else
55 {
56 USItype carries = (USItype)uu.s.low >> bm;
57 w.s.low = (USItype)uu.s.low << b;
58 w.s.high = ((USItype)uu.s.high << b) | carries;
59 }
60
61 return w.ll;
62}
diff --git a/arch/v850/lib/ashrdi3.c b/arch/v850/lib/ashrdi3.c
new file mode 100644
index 000000000000..78efb65e315a
--- /dev/null
+++ b/arch/v850/lib/ashrdi3.c
@@ -0,0 +1,63 @@
1/* ashrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
2/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING. If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
20
21#define BITS_PER_UNIT 8
22
23typedef int SItype __attribute__ ((mode (SI)));
24typedef unsigned int USItype __attribute__ ((mode (SI)));
25typedef int DItype __attribute__ ((mode (DI)));
26typedef int word_type __attribute__ ((mode (__word__)));
27
28struct DIstruct {SItype high, low;};
29
30typedef union
31{
32 struct DIstruct s;
33 DItype ll;
34} DIunion;
35
36DItype
37__ashrdi3 (DItype u, word_type b)
38{
39 DIunion w;
40 word_type bm;
41 DIunion uu;
42
43 if (b == 0)
44 return u;
45
46 uu.ll = u;
47
48 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
49 if (bm <= 0)
50 {
51 /* w.s.high = 1..1 or 0..0 */
52 w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
53 w.s.low = uu.s.high >> -bm;
54 }
55 else
56 {
57 USItype carries = (USItype)uu.s.high << bm;
58 w.s.high = uu.s.high >> b;
59 w.s.low = ((USItype)uu.s.low >> b) | carries;
60 }
61
62 return w.ll;
63}
diff --git a/arch/v850/lib/checksum.c b/arch/v850/lib/checksum.c
new file mode 100644
index 000000000000..d308b724c023
--- /dev/null
+++ b/arch/v850/lib/checksum.c
@@ -0,0 +1,154 @@
1/*
2 * INET An implementation of the TCP/IP protocol suite for the LINUX
3 * operating system. INET is implemented using the BSD Socket
4 * interface as the means of communication with the user level.
5 *
6 * MIPS specific IP/TCP/UDP checksumming routines
7 *
8 * Authors: Ralf Baechle, <ralf@waldorf-gmbh.de>
9 * Lots of code moved from tcp.c and ip.c; see those files
10 * for more names.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 *
17 * $Id: checksum.c,v 1.1 2002/09/28 14:58:40 gerg Exp $
18 */
19#include <net/checksum.h>
20#include <linux/module.h>
21#include <linux/types.h>
22#include <asm/byteorder.h>
23#include <asm/string.h>
24#include <asm/uaccess.h>
25
26static inline unsigned short from32to16 (unsigned long sum)
27{
28 unsigned int result;
29 /*
30 %0 %1
31 hsw %1, %0 H L L H
32 add %1, %0 H L H+L+C H+L
33 */
34 asm ("hsw %1, %0; add %1, %0" : "=&r" (result) : "r" (sum));
35 return result >> 16;
36}
37
38static inline unsigned int do_csum(const unsigned char * buff, int len)
39{
40 int odd, count;
41 unsigned int result = 0;
42
43 if (len <= 0)
44 goto out;
45 odd = 1 & (unsigned long) buff;
46 if (odd) {
47 result = be16_to_cpu(*buff);
48 len--;
49 buff++;
50 }
51 count = len >> 1; /* nr of 16-bit words.. */
52 if (count) {
53 if (2 & (unsigned long) buff) {
54 result += *(unsigned short *) buff;
55 count--;
56 len -= 2;
57 buff += 2;
58 }
59 count >>= 1; /* nr of 32-bit words.. */
60 if (count) {
61 unsigned int carry = 0;
62 do {
63 unsigned int w = *(unsigned int *) buff;
64 count--;
65 buff += 4;
66 result += carry;
67 result += w;
68 carry = (w > result);
69 } while (count);
70 result += carry;
71 result = (result & 0xffff) + (result >> 16);
72 }
73 if (len & 2) {
74 result += *(unsigned short *) buff;
75 buff += 2;
76 }
77 }
78 if (len & 1)
79 result += le16_to_cpu(*buff);
80 result = from32to16(result);
81 if (odd)
82 result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
83out:
84 return result;
85}
86
87/*
88 * This is a version of ip_compute_csum() optimized for IP headers,
89 * which always checksum on 4 octet boundaries.
90 */
91unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl)
92{
93 return ~do_csum(iph,ihl*4);
94}
95
96/*
97 * this routine is used for miscellaneous IP-like checksums, mainly
98 * in icmp.c
99 */
100unsigned short ip_compute_csum(const unsigned char * buff, int len)
101{
102 return ~do_csum(buff,len);
103}
104
105/*
106 * computes a partial checksum, e.g. for TCP/UDP fragments
107 */
108unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum)
109{
110 unsigned int result = do_csum(buff, len);
111
112 /* add in old sum, and carry.. */
113 result += sum;
114 if(sum > result)
115 result += 1;
116 return result;
117}
118
119EXPORT_SYMBOL(csum_partial);
120
121/*
122 * copy while checksumming, otherwise like csum_partial
123 */
124unsigned int csum_partial_copy(const unsigned char *src, unsigned char *dst,
125 int len, unsigned int sum)
126{
127 /*
128 * It's 2:30 am and I don't feel like doing it real ...
129 * This is lots slower than the real thing (tm)
130 */
131 sum = csum_partial(src, len, sum);
132 memcpy(dst, src, len);
133
134 return sum;
135}
136
137/*
138 * Copy from userspace and compute checksum. If we catch an exception
139 * then zero the rest of the buffer.
140 */
141unsigned int csum_partial_copy_from_user (const unsigned char *src, unsigned char *dst,
142 int len, unsigned int sum,
143 int *err_ptr)
144{
145 int missing;
146
147 missing = copy_from_user(dst, src, len);
148 if (missing) {
149 memset(dst + len - missing, 0, missing);
150 *err_ptr = -EFAULT;
151 }
152
153 return csum_partial(dst, len, sum);
154}
diff --git a/arch/v850/lib/lshrdi3.c b/arch/v850/lib/lshrdi3.c
new file mode 100644
index 000000000000..93b1cb6fdee8
--- /dev/null
+++ b/arch/v850/lib/lshrdi3.c
@@ -0,0 +1,62 @@
1/* lshrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
2/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING. If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
20
21#define BITS_PER_UNIT 8
22
23typedef int SItype __attribute__ ((mode (SI)));
24typedef unsigned int USItype __attribute__ ((mode (SI)));
25typedef int DItype __attribute__ ((mode (DI)));
26typedef int word_type __attribute__ ((mode (__word__)));
27
28struct DIstruct {SItype high, low;};
29
30typedef union
31{
32 struct DIstruct s;
33 DItype ll;
34} DIunion;
35
36DItype
37__lshrdi3 (DItype u, word_type b)
38{
39 DIunion w;
40 word_type bm;
41 DIunion uu;
42
43 if (b == 0)
44 return u;
45
46 uu.ll = u;
47
48 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
49 if (bm <= 0)
50 {
51 w.s.high = 0;
52 w.s.low = (USItype)uu.s.high >> -bm;
53 }
54 else
55 {
56 USItype carries = (USItype)uu.s.high << bm;
57 w.s.high = (USItype)uu.s.high >> b;
58 w.s.low = ((USItype)uu.s.low >> b) | carries;
59 }
60
61 return w.ll;
62}
diff --git a/arch/v850/lib/memcpy.c b/arch/v850/lib/memcpy.c
new file mode 100644
index 000000000000..492847b3e612
--- /dev/null
+++ b/arch/v850/lib/memcpy.c
@@ -0,0 +1,92 @@
1/*
2 * arch/v850/lib/memcpy.c -- Memory copying
3 *
4 * Copyright (C) 2001,02 NEC Corporation
5 * Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14#include <linux/types.h>
15#include <asm/string.h>
16
17#define CHUNK_SIZE 32 /* bytes */
18#define CHUNK_ALIGNED(addr) (((unsigned long)addr & 0x3) == 0)
19
20/* Note that this macro uses 8 call-clobbered registers (not including
21 R1), which are few enough so that the following functions don't need
22 to spill anything to memory. It also uses R1, which is nominally
23 reserved for the assembler, but here it should be OK. */
24#define COPY_CHUNK(src, dst) \
25 asm ("mov %0, ep;" \
26 "sld.w 0[ep], r1; sld.w 4[ep], r12;" \
27 "sld.w 8[ep], r13; sld.w 12[ep], r14;" \
28 "sld.w 16[ep], r15; sld.w 20[ep], r17;" \
29 "sld.w 24[ep], r18; sld.w 28[ep], r19;" \
30 "mov %1, ep;" \
31 "sst.w r1, 0[ep]; sst.w r12, 4[ep];" \
32 "sst.w r13, 8[ep]; sst.w r14, 12[ep];" \
33 "sst.w r15, 16[ep]; sst.w r17, 20[ep];" \
34 "sst.w r18, 24[ep]; sst.w r19, 28[ep]" \
35 :: "r" (src), "r" (dst) \
36 : "r1", "r12", "r13", "r14", "r15", \
37 "r17", "r18", "r19", "ep", "memory");
38
39void *memcpy (void *dst, const void *src, __kernel_size_t size)
40{
41 char *_dst = dst;
42 const char *_src = src;
43
44 if (size >= CHUNK_SIZE && CHUNK_ALIGNED(_src) && CHUNK_ALIGNED(_dst)) {
45 /* Copy large blocks efficiently. */
46 unsigned count;
47 for (count = size / CHUNK_SIZE; count; count--) {
48 COPY_CHUNK (_src, _dst);
49 _src += CHUNK_SIZE;
50 _dst += CHUNK_SIZE;
51 }
52 size %= CHUNK_SIZE;
53 }
54
55 if (size > 0)
56 do
57 *_dst++ = *_src++;
58 while (--size);
59
60 return dst;
61}
62
63void *memmove (void *dst, const void *src, __kernel_size_t size)
64{
65 if ((unsigned long)dst < (unsigned long)src
66 || (unsigned long)src + size < (unsigned long)dst)
67 return memcpy (dst, src, size);
68 else {
69 char *_dst = dst + size;
70 const char *_src = src + size;
71
72 if (size >= CHUNK_SIZE
73 && CHUNK_ALIGNED (_src) && CHUNK_ALIGNED (_dst))
74 {
75 /* Copy large blocks efficiently. */
76 unsigned count;
77 for (count = size / CHUNK_SIZE; count; count--) {
78 _src -= CHUNK_SIZE;
79 _dst -= CHUNK_SIZE;
80 COPY_CHUNK (_src, _dst);
81 }
82 size %= CHUNK_SIZE;
83 }
84
85 if (size > 0)
86 do
87 *--_dst = *--_src;
88 while (--size);
89
90 return _dst;
91 }
92}
diff --git a/arch/v850/lib/memset.c b/arch/v850/lib/memset.c
new file mode 100644
index 000000000000..d1b2ad821b15
--- /dev/null
+++ b/arch/v850/lib/memset.c
@@ -0,0 +1,68 @@
1/*
2 * arch/v850/lib/memset.c -- Memory initialization
3 *
4 * Copyright (C) 2001,02,04 NEC Corporation
5 * Copyright (C) 2001,02,04 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14#include <linux/types.h>
15
16void *memset (void *dst, int val, __kernel_size_t count)
17{
18 if (count) {
19 register unsigned loop;
20 register void *ptr asm ("ep") = dst;
21
22 /* replicate VAL into a long. */
23 val &= 0xff;
24 val |= val << 8;
25 val |= val << 16;
26
27 /* copy initial unaligned bytes. */
28 if ((long)ptr & 1) {
29 *(char *)ptr = val;
30 ptr = (void *)((char *)ptr + 1);
31 count--;
32 }
33 if (count > 2 && ((long)ptr & 2)) {
34 *(short *)ptr = val;
35 ptr = (void *)((short *)ptr + 1);
36 count -= 2;
37 }
38
39 /* 32-byte copying loop. */
40 for (loop = count / 32; loop; loop--) {
41 asm ("sst.w %0, 0[ep]; sst.w %0, 4[ep];"
42 "sst.w %0, 8[ep]; sst.w %0, 12[ep];"
43 "sst.w %0, 16[ep]; sst.w %0, 20[ep];"
44 "sst.w %0, 24[ep]; sst.w %0, 28[ep]"
45 :: "r" (val) : "memory");
46 ptr += 32;
47 }
48 count %= 32;
49
50 /* long copying loop. */
51 for (loop = count / 4; loop; loop--) {
52 *(long *)ptr = val;
53 ptr = (void *)((long *)ptr + 1);
54 }
55 count %= 4;
56
57 /* finish up with any trailing bytes. */
58 if (count & 2) {
59 *(short *)ptr = val;
60 ptr = (void *)((short *)ptr + 1);
61 }
62 if (count & 1) {
63 *(char *)ptr = val;
64 }
65 }
66
67 return dst;
68}
diff --git a/arch/v850/lib/muldi3.c b/arch/v850/lib/muldi3.c
new file mode 100644
index 000000000000..277ca25c82c8
--- /dev/null
+++ b/arch/v850/lib/muldi3.c
@@ -0,0 +1,61 @@
1/* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and
2 gcc-2.7.2.3/longlong.h which is: */
3/* Copyright (C) 1989, 1992, 1993, 1994, 1995, 2001 Free Software Foundation, Inc.
4
5This file is part of GNU CC.
6
7GNU CC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU CC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU CC; see the file COPYING. If not, write to
19the Free Software Foundation, 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
21
22#define umul_ppmm(w1, w0, u, v) \
23 __asm__ ("mulu %3, %0, %1" \
24 : "=r" ((USItype)(w0)), \
25 "=r" ((USItype)(w1)) \
26 : "%0" ((USItype)(u)), \
27 "r" ((USItype)(v)))
28
29#define __umulsidi3(u, v) \
30 ({DIunion __w; \
31 umul_ppmm (__w.s.high, __w.s.low, u, v); \
32 __w.ll; })
33
34typedef int SItype __attribute__ ((mode (SI)));
35typedef unsigned int USItype __attribute__ ((mode (SI)));
36typedef int DItype __attribute__ ((mode (DI)));
37typedef int word_type __attribute__ ((mode (__word__)));
38
39struct DIstruct {SItype high, low;};
40
41typedef union
42{
43 struct DIstruct s;
44 DItype ll;
45} DIunion;
46
47DItype
48__muldi3 (DItype u, DItype v)
49{
50 DIunion w;
51 DIunion uu, vv;
52
53 uu.ll = u,
54 vv.ll = v;
55
56 w.ll = __umulsidi3 (uu.s.low, vv.s.low);
57 w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
58 + (USItype) uu.s.high * (USItype) vv.s.low);
59
60 return w.ll;
61}
diff --git a/arch/v850/lib/negdi2.c b/arch/v850/lib/negdi2.c
new file mode 100644
index 000000000000..571e04fc619a
--- /dev/null
+++ b/arch/v850/lib/negdi2.c
@@ -0,0 +1,25 @@
1/*
2 * arch/v850/lib/negdi2.c -- 64-bit negation
3 *
4 * Copyright (C) 2001 NEC Corporation
5 * Copyright (C) 2001 Miles Bader <miles@gnu.org>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this
9 * archive for more details.
10 *
11 * Written by Miles Bader <miles@gnu.org>
12 */
13
14typedef int DItype __attribute__ ((mode (DI)));
15
16DItype __negdi2 (DItype x)
17{
18 __asm__ __volatile__
19 ("not r6, r10;"
20 "add 1, r10;"
21 "setf c, r6;"
22 "not r7, r11;"
23 "add r6, r11"
24 ::: "r6", "r7", "r10", "r11");
25}