diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/h8300 |
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/h8300')
64 files changed, 8135 insertions, 0 deletions
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig new file mode 100644 index 000000000000..62a89e812e3e --- /dev/null +++ b/arch/h8300/Kconfig | |||
@@ -0,0 +1,194 @@ | |||
1 | # | ||
2 | # For a description of the syntax of this configuration file, | ||
3 | # see Documentation/kbuild/config-language.txt. | ||
4 | # | ||
5 | |||
6 | mainmenu "uClinux/h8300 (w/o MMU) Kernel Configuration" | ||
7 | |||
8 | config H8300 | ||
9 | bool | ||
10 | default y | ||
11 | |||
12 | config MMU | ||
13 | bool | ||
14 | default n | ||
15 | |||
16 | config SWAP | ||
17 | bool | ||
18 | default n | ||
19 | |||
20 | config FPU | ||
21 | bool | ||
22 | default n | ||
23 | |||
24 | config UID16 | ||
25 | bool | ||
26 | default y | ||
27 | |||
28 | config RWSEM_GENERIC_SPINLOCK | ||
29 | bool | ||
30 | default y | ||
31 | |||
32 | config RWSEM_XCHGADD_ALGORITHM | ||
33 | bool | ||
34 | default n | ||
35 | |||
36 | config GENERIC_CALIBRATE_DELAY | ||
37 | bool | ||
38 | default y | ||
39 | |||
40 | config ISA | ||
41 | bool | ||
42 | default y | ||
43 | |||
44 | config PCI | ||
45 | bool | ||
46 | default n | ||
47 | |||
48 | source "init/Kconfig" | ||
49 | |||
50 | source "arch/h8300/Kconfig.cpu" | ||
51 | |||
52 | menu "Executable file formats" | ||
53 | |||
54 | source "fs/Kconfig.binfmt" | ||
55 | |||
56 | endmenu | ||
57 | |||
58 | source "drivers/base/Kconfig" | ||
59 | |||
60 | source "drivers/mtd/Kconfig" | ||
61 | |||
62 | source "drivers/block/Kconfig" | ||
63 | |||
64 | source "drivers/ide/Kconfig" | ||
65 | |||
66 | source "arch/h8300/Kconfig.ide" | ||
67 | |||
68 | source "net/Kconfig" | ||
69 | |||
70 | # | ||
71 | # input - input/joystick depends on it. As does USB. | ||
72 | # | ||
73 | source "drivers/input/Kconfig" | ||
74 | |||
75 | menu "Character devices" | ||
76 | |||
77 | config VT | ||
78 | bool "Virtual terminal" | ||
79 | ---help--- | ||
80 | If you say Y here, you will get support for terminal devices with | ||
81 | display and keyboard devices. These are called "virtual" because you | ||
82 | can run several virtual terminals (also called virtual consoles) on | ||
83 | one physical terminal. This is rather useful, for example one | ||
84 | virtual terminal can collect system messages and warnings, another | ||
85 | one can be used for a text-mode user session, and a third could run | ||
86 | an X session, all in parallel. Switching between virtual terminals | ||
87 | is done with certain key combinations, usually Alt-<function key>. | ||
88 | |||
89 | The setterm command ("man setterm") can be used to change the | ||
90 | properties (such as colors or beeping) of a virtual terminal. The | ||
91 | man page console_codes(4) ("man console_codes") contains the special | ||
92 | character sequences that can be used to change those properties | ||
93 | directly. The fonts used on virtual terminals can be changed with | ||
94 | the setfont ("man setfont") command and the key bindings are defined | ||
95 | with the loadkeys ("man loadkeys") command. | ||
96 | |||
97 | You need at least one virtual terminal device in order to make use | ||
98 | of your keyboard and monitor. Therefore, only people configuring an | ||
99 | embedded system would want to say N here in order to save some | ||
100 | memory; the only way to log into such a system is then via a serial | ||
101 | or network connection. | ||
102 | |||
103 | If unsure, say Y, or else you won't be able to do much with your new | ||
104 | shiny Linux system :-) | ||
105 | |||
106 | config VT_CONSOLE | ||
107 | bool "Support for console on virtual terminal" | ||
108 | depends on VT | ||
109 | ---help--- | ||
110 | The system console is the device which receives all kernel messages | ||
111 | and warnings and which allows logins in single user mode. If you | ||
112 | answer Y here, a virtual terminal (the device used to interact with | ||
113 | a physical terminal) can be used as system console. This is the most | ||
114 | common mode of operations, so you should say Y here unless you want | ||
115 | the kernel messages be output only to a serial port (in which case | ||
116 | you should say Y to "Console on serial port", below). | ||
117 | |||
118 | If you do say Y here, by default the currently visible virtual | ||
119 | terminal (/dev/tty0) will be used as system console. You can change | ||
120 | that with a kernel command line option such as "console=tty3" which | ||
121 | would use the third virtual terminal as system console. (Try "man | ||
122 | bootparam" or see the documentation of your boot loader (lilo or | ||
123 | loadlin) about how to pass options to the kernel at boot time.) | ||
124 | |||
125 | If unsure, say Y. | ||
126 | |||
127 | config HW_CONSOLE | ||
128 | bool | ||
129 | depends on VT && !S390 && !UM | ||
130 | default y | ||
131 | |||
132 | comment "Unix98 PTY support" | ||
133 | |||
134 | config UNIX98_PTYS | ||
135 | bool "Unix98 PTY support" | ||
136 | ---help--- | ||
137 | A pseudo terminal (PTY) is a software device consisting of two | ||
138 | halves: a master and a slave. The slave device behaves identical to | ||
139 | a physical terminal; the master device is used by a process to | ||
140 | read data from and write data to the slave, thereby emulating a | ||
141 | terminal. Typical programs for the master side are telnet servers | ||
142 | and xterms. | ||
143 | |||
144 | Linux has traditionally used the BSD-like names /dev/ptyxx for | ||
145 | masters and /dev/ttyxx for slaves of pseudo terminals. This scheme | ||
146 | has a number of problems. The GNU C library glibc 2.1 and later, | ||
147 | however, supports the Unix98 naming standard: in order to acquire a | ||
148 | pseudo terminal, a process opens /dev/ptmx; the number of the pseudo | ||
149 | terminal is then made available to the process and the pseudo | ||
150 | terminal slave can be accessed as /dev/pts/<number>. What was | ||
151 | traditionally /dev/ttyp2 will then be /dev/pts/2, for example. | ||
152 | |||
153 | The entries in /dev/pts/ are created on the fly by a virtual | ||
154 | file system; therefore, if you say Y here you should say Y to | ||
155 | "/dev/pts file system for Unix98 PTYs" as well. | ||
156 | |||
157 | If you want to say Y here, you need to have the C library glibc 2.1 | ||
158 | or later (equal to libc-6.1, check with "ls -l /lib/libc.so.*"). | ||
159 | Read the instructions in <file:Documentation/Changes> pertaining to | ||
160 | pseudo terminals. It's safe to say N. | ||
161 | |||
162 | config UNIX98_PTY_COUNT | ||
163 | int "Maximum number of Unix98 PTYs in use (0-2048)" | ||
164 | depends on UNIX98_PTYS | ||
165 | default "256" | ||
166 | help | ||
167 | The maximum number of Unix98 PTYs that can be used at any one time. | ||
168 | The default is 256, and should be enough for desktop systems. Server | ||
169 | machines which support incoming telnet/rlogin/ssh connections and/or | ||
170 | serve several X terminals may want to increase this: every incoming | ||
171 | connection and every xterm uses up one PTY. | ||
172 | |||
173 | When not in use, each additional set of 256 PTYs occupy | ||
174 | approximately 8 KB of kernel memory on 32-bit architectures. | ||
175 | |||
176 | source "drivers/char/pcmcia/Kconfig" | ||
177 | |||
178 | source "drivers/serial/Kconfig" | ||
179 | |||
180 | source "drivers/i2c/Kconfig" | ||
181 | |||
182 | source "drivers/usb/Kconfig" | ||
183 | |||
184 | endmenu | ||
185 | |||
186 | source "fs/Kconfig" | ||
187 | |||
188 | source "arch/h8300/Kconfig.debug" | ||
189 | |||
190 | source "security/Kconfig" | ||
191 | |||
192 | source "crypto/Kconfig" | ||
193 | |||
194 | source "lib/Kconfig" | ||
diff --git a/arch/h8300/Kconfig.cpu b/arch/h8300/Kconfig.cpu new file mode 100644 index 000000000000..d9dd62a565a9 --- /dev/null +++ b/arch/h8300/Kconfig.cpu | |||
@@ -0,0 +1,183 @@ | |||
1 | menu "Processor type and features" | ||
2 | |||
3 | choice | ||
4 | prompt "H8/300 platform" | ||
5 | default H8300H_GENERIC | ||
6 | |||
7 | config H8300H_GENERIC | ||
8 | bool "H8/300H Generic" | ||
9 | help | ||
10 | H8/300H CPU Generic Hardware Support | ||
11 | |||
12 | config H8300H_AKI3068NET | ||
13 | bool "AE-3068/69" | ||
14 | help | ||
15 | AKI-H8/3068F / AKI-H8/3069F Flashmicom LAN Board Support | ||
16 | More Information. (Japanese Only) | ||
17 | <http://akizukidensi.com/catalog/h8.html> | ||
18 | AE-3068/69 Evaluation Board Support | ||
19 | More Information. | ||
20 | <http://www.microtronique.com/ae3069lan.htm> | ||
21 | |||
22 | config H8300H_H8MAX | ||
23 | bool "H8MAX" | ||
24 | help | ||
25 | H8MAX Evaluation Board Support | ||
26 | More Information. (Japanese Only) | ||
27 | <http://strawberry-linux.com/h8/index.html> | ||
28 | |||
29 | config H8300H_SIM | ||
30 | bool "H8/300H Simulator" | ||
31 | help | ||
32 | GDB Simulator Support | ||
33 | More Information. | ||
34 | arch/h8300/Doc/simulator.txt | ||
35 | |||
36 | config H8S_GENERIC | ||
37 | bool "H8S Generic" | ||
38 | help | ||
39 | H8S CPU Generic Hardware Support | ||
40 | |||
41 | config H8S_EDOSK2674 | ||
42 | bool "EDOSK-2674" | ||
43 | help | ||
44 | Renesas EDOSK-2674 Evaluation Board Support | ||
45 | More Information. | ||
46 | <http://www.azpower.com/H8-uClinux/index.html> | ||
47 | <http://www.eu.renesas.com/tools/edk/support/edosk2674.html> | ||
48 | |||
49 | config H8S_SIM | ||
50 | bool "H8S Simulator" | ||
51 | help | ||
52 | GDB Simulator Support | ||
53 | More Information. | ||
54 | arch/h8300/Doc/simulator.txt | ||
55 | |||
56 | endchoice | ||
57 | |||
58 | if (H8300H_GENERIC || H8S_GENERIC) | ||
59 | menu "Detail Selection" | ||
60 | if (H8300H_GENERIC) | ||
61 | choice | ||
62 | prompt "CPU Selection" | ||
63 | |||
64 | config H83002 | ||
65 | bool "H8/3001,3002,3003" | ||
66 | |||
67 | config H83007 | ||
68 | bool "H8/3006,3007" | ||
69 | |||
70 | config H83048 | ||
71 | bool "H8/3044,3045,3046,3047,3048,3052" | ||
72 | |||
73 | config H83068 | ||
74 | bool "H8/3065,3066,3067,3068,3069" | ||
75 | endchoice | ||
76 | endif | ||
77 | |||
78 | if (H8S_GENERIC) | ||
79 | choice | ||
80 | prompt "CPU Selection" | ||
81 | |||
82 | config H8S2678 | ||
83 | bool "H8S/2670,2673,2674R,2675,2676" | ||
84 | endchoice | ||
85 | endif | ||
86 | |||
87 | config CPU_CLOCK | ||
88 | int "CPU Clock Frequency (/1KHz)" | ||
89 | default "20000" | ||
90 | help | ||
91 | CPU Clock Frequency divide to 1000 | ||
92 | endmenu | ||
93 | endif | ||
94 | |||
95 | if (H8300H_GENERIC || H8S_GENERIC || H8300H_SIM || H8S_SIM || H8S_EDOSK2674) | ||
96 | choice | ||
97 | prompt "Kernel executes from" | ||
98 | ---help--- | ||
99 | Choose the memory type that the kernel will be running in. | ||
100 | |||
101 | config RAMKERNEL | ||
102 | bool "RAM" | ||
103 | help | ||
104 | The kernel will be resident in RAM when running. | ||
105 | |||
106 | config ROMKERNEL | ||
107 | bool "ROM" | ||
108 | help | ||
109 | The kernel will be resident in FLASH/ROM when running. | ||
110 | |||
111 | endchoice | ||
112 | endif | ||
113 | |||
114 | if (H8300H_AKI3068NET) | ||
115 | config H83068 | ||
116 | bool | ||
117 | default y | ||
118 | |||
119 | config CPU_CLOCK | ||
120 | int | ||
121 | default "20000" | ||
122 | |||
123 | config RAMKERNEL | ||
124 | bool | ||
125 | default y | ||
126 | endif | ||
127 | |||
128 | if (H8300H_H8MAX) | ||
129 | config H83068 | ||
130 | bool | ||
131 | default y | ||
132 | |||
133 | config CPU_CLOCK | ||
134 | int | ||
135 | default 25000 | ||
136 | |||
137 | config RAMKERNEL | ||
138 | bool | ||
139 | default y | ||
140 | endif | ||
141 | |||
142 | if (H8300H_SIM) | ||
143 | config H83007 | ||
144 | bool | ||
145 | default y | ||
146 | |||
147 | config CPU_CLOCK | ||
148 | int | ||
149 | default "16000" | ||
150 | endif | ||
151 | |||
152 | if (H8S_EDOSK2674) | ||
153 | config H8S2678 | ||
154 | bool | ||
155 | default y | ||
156 | config CPU_CLOCK | ||
157 | int | ||
158 | default 33000 | ||
159 | endif | ||
160 | |||
161 | if (H8S_SIM) | ||
162 | config H8S2678 | ||
163 | bool | ||
164 | default y | ||
165 | config CPU_CLOCK | ||
166 | int | ||
167 | default 33000 | ||
168 | endif | ||
169 | |||
170 | config CPU_H8300H | ||
171 | bool | ||
172 | depends on (H8002 || H83007 || H83048 || H83068) | ||
173 | default y | ||
174 | |||
175 | config CPU_H8S | ||
176 | bool | ||
177 | depends on H8S2678 | ||
178 | default y | ||
179 | |||
180 | config PREEMPT | ||
181 | bool "Preemptible Kernel" | ||
182 | default n | ||
183 | endmenu | ||
diff --git a/arch/h8300/Kconfig.debug b/arch/h8300/Kconfig.debug new file mode 100644 index 000000000000..55034d08abff --- /dev/null +++ b/arch/h8300/Kconfig.debug | |||
@@ -0,0 +1,68 @@ | |||
1 | menu "Kernel hacking" | ||
2 | |||
3 | source "lib/Kconfig.debug" | ||
4 | |||
5 | config FULLDEBUG | ||
6 | bool "Full Symbolic/Source Debugging support" | ||
7 | help | ||
8 | Enable debugging symbols on kernel build. | ||
9 | |||
10 | config HIGHPROFILE | ||
11 | bool "Use fast second timer for profiling" | ||
12 | help | ||
13 | Use a fast secondary clock to produce profiling information. | ||
14 | |||
15 | config NO_KERNEL_MSG | ||
16 | bool "Suppress Kernel BUG Messages" | ||
17 | help | ||
18 | Do not output any debug BUG messages within the kernel. | ||
19 | |||
20 | config GDB_MAGICPRINT | ||
21 | bool "Message Output for GDB MagicPrint service" | ||
22 | depends on (H8300H_SIM || H8S_SIM) | ||
23 | help | ||
24 | kernel messages output useing MagicPrint service from GDB | ||
25 | |||
26 | config SYSCALL_PRINT | ||
27 | bool "SystemCall trace print" | ||
28 | help | ||
29 | outout history of systemcall | ||
30 | |||
31 | config GDB_DEBUG | ||
32 | bool "Use gdb stub" | ||
33 | depends on (!H8300H_SIM && !H8S_SIM) | ||
34 | help | ||
35 | gdb stub exception support | ||
36 | |||
37 | config CONFIG_SH_STANDARD_BIOS | ||
38 | bool "Use gdb protocol serial console" | ||
39 | depends on (!H8300H_SIM && !H8S_SIM) | ||
40 | help | ||
41 | serial console output using GDB protocol. | ||
42 | Require eCos/RedBoot | ||
43 | |||
44 | config DEFAULT_CMDLINE | ||
45 | bool "Use buildin commandline" | ||
46 | default n | ||
47 | help | ||
48 | buildin kernel commandline enabled. | ||
49 | |||
50 | config KERNEL_COMMAND | ||
51 | string "Buildin commmand string" | ||
52 | depends on DEFAULT_CMDLINE | ||
53 | help | ||
54 | buildin kernel commandline strings. | ||
55 | |||
56 | config BLKDEV_RESERVE | ||
57 | bool "BLKDEV Reserved Memory" | ||
58 | default n | ||
59 | help | ||
60 | Reserved BLKDEV area. | ||
61 | |||
62 | config CONFIG_BLKDEV_RESERVE_ADDRESS | ||
63 | hex 'start address' | ||
64 | depends on BLKDEV_RESERVE | ||
65 | help | ||
66 | BLKDEV start address. | ||
67 | |||
68 | endmenu | ||
diff --git a/arch/h8300/Kconfig.ide b/arch/h8300/Kconfig.ide new file mode 100644 index 000000000000..a38a63054ac2 --- /dev/null +++ b/arch/h8300/Kconfig.ide | |||
@@ -0,0 +1,44 @@ | |||
1 | # uClinux H8/300 Target Board Selection Menu (IDE) | ||
2 | |||
3 | if (H8300H_AKI3068NET) | ||
4 | menu "IDE Extra configuration" | ||
5 | |||
6 | config H8300_IDE_BASE | ||
7 | hex "IDE register base address" | ||
8 | depends on IDE | ||
9 | default 0 | ||
10 | help | ||
11 | IDE registers base address | ||
12 | |||
13 | config H8300_IDE_ALT | ||
14 | hex "IDE register alternate address" | ||
15 | depends on IDE | ||
16 | default 0 | ||
17 | help | ||
18 | IDE alternate registers address | ||
19 | |||
20 | config H8300_IDE_IRQ | ||
21 | int "IDE IRQ no" | ||
22 | depends on IDE | ||
23 | default 0 | ||
24 | help | ||
25 | IDE use IRQ no | ||
26 | endmenu | ||
27 | endif | ||
28 | |||
29 | if (H8300H_H8MAX) | ||
30 | config H8300_IDE_BASE | ||
31 | hex | ||
32 | depends on IDE | ||
33 | default 0x200000 | ||
34 | |||
35 | config H8300_IDE_ALT | ||
36 | hex | ||
37 | depends on IDE | ||
38 | default 0x60000c | ||
39 | |||
40 | config H8300_IDE_IRQ | ||
41 | int | ||
42 | depends on IDE | ||
43 | default 5 | ||
44 | endif | ||
diff --git a/arch/h8300/Makefile b/arch/h8300/Makefile new file mode 100644 index 000000000000..c9b80cffd71d --- /dev/null +++ b/arch/h8300/Makefile | |||
@@ -0,0 +1,78 @@ | |||
1 | # | ||
2 | # arch/h8300/Makefile | ||
3 | # | ||
4 | # This file is subject to the terms and conditions of the GNU General Public | ||
5 | # License. See the file "COPYING" in the main directory of this archive | ||
6 | # for more details. | ||
7 | # | ||
8 | # (C) Copyright 2002,2003 Yoshinori Sato <ysato@users.sourceforge.jp> | ||
9 | # | ||
10 | |||
11 | platform-$(CONFIG_CPU_H8300H) := h8300h | ||
12 | platform-$(CONFIG_CPU_H8S) := h8s | ||
13 | PLATFORM := $(platform-y) | ||
14 | |||
15 | board-$(CONFIG_H8300H_GENERIC) := generic | ||
16 | board-$(CONFIG_H8300H_AKI3068NET) := aki3068net | ||
17 | board-$(CONFIG_H8300H_H8MAX) := h8max | ||
18 | board-$(CONFIG_H8300H_SIM) := generic | ||
19 | board-$(CONFIG_H8S_GENERIC) := generic | ||
20 | board-$(CONFIG_H8S_EDOSK2674) := edosk2674 | ||
21 | board-$(CONFIG_H8S_SIM) := generic | ||
22 | BOARD := $(board-y) | ||
23 | |||
24 | model-$(CONFIG_RAMKERNEL) := ram | ||
25 | model-$(CONFIG_ROMKERNEL) := rom | ||
26 | MODEL := $(model-y) | ||
27 | |||
28 | cflags-$(CONFIG_CPU_H8300H) := -mh | ||
29 | ldflags-$(CONFIG_CPU_H8300H) := -mh8300helf | ||
30 | cflags-$(CONFIG_CPU_H8S) := -ms | ||
31 | ldflags-$(CONFIG_CPU_H8S) := -mh8300self | ||
32 | |||
33 | CFLAGS += $(cflags-y) | ||
34 | CFLAGS += -mint32 -fno-builtin | ||
35 | CFLAGS += -g | ||
36 | CFLAGS += -D__linux__ | ||
37 | CFLAGS += -DUTS_SYSNAME=\"uClinux\" | ||
38 | AFLAGS += -DPLATFORM=$(PLATFORM) -DMODEL=$(MODEL) $(cflags-y) | ||
39 | LDFLAGS += $(ldflags-y) | ||
40 | |||
41 | CROSS_COMPILE = h8300-elf- | ||
42 | LIBGCC := $(shell $(CROSS-COMPILE)$(CC) $(CFLAGS) -print-libgcc-file-name) | ||
43 | |||
44 | head-y := arch/$(ARCH)/platform/$(platform-y)/$(board-y)/crt0_$(model-y).o | ||
45 | |||
46 | core-y += arch/$(ARCH)/kernel/ \ | ||
47 | arch/$(ARCH)/mm/ | ||
48 | ifdef PLATFORM | ||
49 | core-y += arch/$(ARCH)/platform/$(PLATFORM)/ \ | ||
50 | arch/$(ARCH)/platform/$(PLATFORM)/$(BOARD)/ | ||
51 | endif | ||
52 | |||
53 | libs-y += arch/$(ARCH)/lib/ $(LIBGCC) | ||
54 | |||
55 | boot := arch/h8300/boot | ||
56 | |||
57 | export MODEL PLATFORM BOARD | ||
58 | |||
59 | archmrproper: | ||
60 | |||
61 | archclean: | ||
62 | $(Q)$(MAKE) $(clean)=$(boot) | ||
63 | |||
64 | prepare: include/asm-$(ARCH)/asm-offsets.h | ||
65 | |||
66 | include/asm-$(ARCH)/asm-offsets.h: arch/$(ARCH)/kernel/asm-offsets.s \ | ||
67 | include/asm include/linux/version.h | ||
68 | $(call filechk,gen-asm-offsets) | ||
69 | |||
70 | vmlinux.srec vmlinux.bin: vmlinux | ||
71 | $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ | ||
72 | |||
73 | define archhelp | ||
74 | echo 'vmlinux.bin - Create raw binary' | ||
75 | echo 'vmlinux.srec - Create srec binary' | ||
76 | endef | ||
77 | |||
78 | CLEAN_FILES += include/asm-$(ARCH)/asm-offsets.h | ||
diff --git a/arch/h8300/README b/arch/h8300/README new file mode 100644 index 000000000000..2fd6f6d7a019 --- /dev/null +++ b/arch/h8300/README | |||
@@ -0,0 +1,37 @@ | |||
1 | linux-2.6 for H8/300 README | ||
2 | Yoshinori Sato <ysato@users.sourceforge.jp> | ||
3 | |||
4 | * Supported CPU | ||
5 | H8/300H and H8S | ||
6 | |||
7 | * Supported Target | ||
8 | 1.simulator of GDB | ||
9 | require patches. | ||
10 | |||
11 | 2.AE 3068/AE 3069 | ||
12 | more information | ||
13 | MICROTRONIQUE <http://www.microtronique.com/> | ||
14 | Akizuki Denshi Tsusho Ltd. <http://www.akizuki.ne.jp> (Japanese Only) | ||
15 | |||
16 | 3.H8MAX | ||
17 | see http://ip-sol.jp/h8max/ (Japanese Only) | ||
18 | |||
19 | 4.EDOSK2674 | ||
20 | see http://www.eu.renesas.com/products/mpumcu/tool/edk/support/edosk2674.html | ||
21 | http://www.azpower.com/H8-uClinux/ | ||
22 | |||
23 | * Toolchain Version | ||
24 | gcc-3.1 or higher and patch | ||
25 | see arch/h8300/tools_patch/README | ||
26 | binutils-2.12 or higher | ||
27 | gdb-5.2 or higher | ||
28 | The environment that can compile a h8300-elf binary is necessary. | ||
29 | |||
30 | * Userland Develop environment | ||
31 | used h8300-elf toolchains. | ||
32 | see http://www.uclinux.org/pub/uClinux/ports/h8/ | ||
33 | |||
34 | * A few words of thanks | ||
35 | Porting to H8/300 serieses is support of Information-technology Promotion Agency, Japan. | ||
36 | I thank support. | ||
37 | and All developer/user. | ||
diff --git a/arch/h8300/boot/Makefile b/arch/h8300/boot/Makefile new file mode 100644 index 000000000000..65086d925ca7 --- /dev/null +++ b/arch/h8300/boot/Makefile | |||
@@ -0,0 +1,12 @@ | |||
1 | # arch/h8300/boot/Makefile | ||
2 | |||
3 | targets := vmlinux.srec vmlinux.bin | ||
4 | |||
5 | OBJCOPYFLAGS_vmlinux.srec := -Osrec | ||
6 | OBJCOPYFLAGS_vmlinux.bin := -Obinary | ||
7 | |||
8 | $(obj)/vmlinux.srec $(obj)/vmlinux.bin: vmlinux FORCE | ||
9 | $(call if_changed,objcopy) | ||
10 | @echo ' Kernel: $@ is ready' | ||
11 | |||
12 | CLEAN_FILES += arch/$(ARCH)/vmlinux.bin arch/$(ARCH)/vmlinux.srec | ||
diff --git a/arch/h8300/defconfig b/arch/h8300/defconfig new file mode 100644 index 000000000000..9d9b491cfc2c --- /dev/null +++ b/arch/h8300/defconfig | |||
@@ -0,0 +1,356 @@ | |||
1 | # | ||
2 | # Automatically generated make config: don't edit | ||
3 | # Linux kernel version: 2.6.11-rc1 | ||
4 | # Sun Jan 16 17:24:38 2005 | ||
5 | # | ||
6 | CONFIG_H8300=y | ||
7 | # CONFIG_MMU is not set | ||
8 | # CONFIG_SWAP is not set | ||
9 | # CONFIG_FPU is not set | ||
10 | CONFIG_UID16=y | ||
11 | CONFIG_RWSEM_GENERIC_SPINLOCK=y | ||
12 | # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set | ||
13 | CONFIG_GENERIC_CALIBRATE_DELAY=y | ||
14 | CONFIG_ISA=y | ||
15 | # CONFIG_PCI is not set | ||
16 | |||
17 | # | ||
18 | # Code maturity level options | ||
19 | # | ||
20 | CONFIG_EXPERIMENTAL=y | ||
21 | CONFIG_CLEAN_COMPILE=y | ||
22 | CONFIG_BROKEN_ON_SMP=y | ||
23 | |||
24 | # | ||
25 | # General setup | ||
26 | # | ||
27 | CONFIG_LOCALVERSION="" | ||
28 | # CONFIG_BSD_PROCESS_ACCT is not set | ||
29 | # CONFIG_SYSCTL is not set | ||
30 | # CONFIG_AUDIT is not set | ||
31 | CONFIG_LOG_BUF_SHIFT=14 | ||
32 | # CONFIG_HOTPLUG is not set | ||
33 | # CONFIG_IKCONFIG is not set | ||
34 | CONFIG_EMBEDDED=y | ||
35 | # CONFIG_KALLSYMS is not set | ||
36 | # CONFIG_FUTEX is not set | ||
37 | # CONFIG_EPOLL is not set | ||
38 | CONFIG_CC_OPTIMIZE_FOR_SIZE=y | ||
39 | CONFIG_CC_ALIGN_FUNCTIONS=0 | ||
40 | CONFIG_CC_ALIGN_LABELS=0 | ||
41 | CONFIG_CC_ALIGN_LOOPS=0 | ||
42 | CONFIG_CC_ALIGN_JUMPS=0 | ||
43 | CONFIG_TINY_SHMEM=y | ||
44 | |||
45 | # | ||
46 | # Loadable module support | ||
47 | # | ||
48 | # CONFIG_MODULES is not set | ||
49 | |||
50 | # | ||
51 | # Processor type and features | ||
52 | # | ||
53 | CONFIG_H8300H_GENERIC=y | ||
54 | # CONFIG_H8300H_AKI3068NET is not set | ||
55 | # CONFIG_H8300H_H8MAX is not set | ||
56 | # CONFIG_H8300H_SIM is not set | ||
57 | # CONFIG_H8S_GENERIC is not set | ||
58 | # CONFIG_H8S_EDOSK2674 is not set | ||
59 | # CONFIG_H8S_SIM is not set | ||
60 | |||
61 | # | ||
62 | # Detail Selection | ||
63 | # | ||
64 | # CONFIG_H83002 is not set | ||
65 | # CONFIG_H83007 is not set | ||
66 | # CONFIG_H83048 is not set | ||
67 | CONFIG_H83068=y | ||
68 | CONFIG_CPU_CLOCK=20000 | ||
69 | # CONFIG_RAMKERNEL is not set | ||
70 | CONFIG_ROMKERNEL=y | ||
71 | CONFIG_CPU_H8300H=y | ||
72 | # CONFIG_PREEMPT is not set | ||
73 | |||
74 | # | ||
75 | # Executable file formats | ||
76 | # | ||
77 | CONFIG_BINFMT_FLAT=y | ||
78 | CONFIG_BINFMT_ZFLAT=y | ||
79 | # CONFIG_BINFMT_SHARED_FLAT is not set | ||
80 | # CONFIG_BINFMT_MISC is not set | ||
81 | |||
82 | # | ||
83 | # Generic Driver Options | ||
84 | # | ||
85 | # CONFIG_STANDALONE is not set | ||
86 | # CONFIG_PREVENT_FIRMWARE_BUILD is not set | ||
87 | # CONFIG_FW_LOADER is not set | ||
88 | # CONFIG_DEBUG_DRIVER is not set | ||
89 | |||
90 | # | ||
91 | # Memory Technology Devices (MTD) | ||
92 | # | ||
93 | CONFIG_MTD=y | ||
94 | # CONFIG_MTD_DEBUG is not set | ||
95 | CONFIG_MTD_PARTITIONS=y | ||
96 | CONFIG_MTD_CONCAT=y | ||
97 | # CONFIG_MTD_REDBOOT_PARTS is not set | ||
98 | # CONFIG_MTD_CMDLINE_PARTS is not set | ||
99 | |||
100 | # | ||
101 | # User Modules And Translation Layers | ||
102 | # | ||
103 | CONFIG_MTD_CHAR=y | ||
104 | CONFIG_MTD_BLOCK=y | ||
105 | # CONFIG_FTL is not set | ||
106 | # CONFIG_NFTL is not set | ||
107 | # CONFIG_INFTL is not set | ||
108 | |||
109 | # | ||
110 | # RAM/ROM/Flash chip drivers | ||
111 | # | ||
112 | # CONFIG_MTD_CFI is not set | ||
113 | # CONFIG_MTD_JEDECPROBE is not set | ||
114 | CONFIG_MTD_MAP_BANK_WIDTH_1=y | ||
115 | CONFIG_MTD_MAP_BANK_WIDTH_2=y | ||
116 | CONFIG_MTD_MAP_BANK_WIDTH_4=y | ||
117 | # CONFIG_MTD_MAP_BANK_WIDTH_8 is not set | ||
118 | # CONFIG_MTD_MAP_BANK_WIDTH_16 is not set | ||
119 | # CONFIG_MTD_MAP_BANK_WIDTH_32 is not set | ||
120 | CONFIG_MTD_CFI_I1=y | ||
121 | CONFIG_MTD_CFI_I2=y | ||
122 | # CONFIG_MTD_CFI_I4 is not set | ||
123 | # CONFIG_MTD_CFI_I8 is not set | ||
124 | CONFIG_MTD_RAM=y | ||
125 | CONFIG_MTD_ROM=y | ||
126 | # CONFIG_MTD_ABSENT is not set | ||
127 | |||
128 | # | ||
129 | # Mapping drivers for chip access | ||
130 | # | ||
131 | # CONFIG_MTD_COMPLEX_MAPPINGS is not set | ||
132 | CONFIG_MTD_UCLINUX=y | ||
133 | |||
134 | # | ||
135 | # Self-contained MTD device drivers | ||
136 | # | ||
137 | # CONFIG_MTD_SLRAM is not set | ||
138 | # CONFIG_MTD_PHRAM is not set | ||
139 | # CONFIG_MTD_MTDRAM is not set | ||
140 | # CONFIG_MTD_BLKMTD is not set | ||
141 | # CONFIG_MTD_BLOCK2MTD is not set | ||
142 | |||
143 | # | ||
144 | # Disk-On-Chip Device Drivers | ||
145 | # | ||
146 | # CONFIG_MTD_DOC2000 is not set | ||
147 | # CONFIG_MTD_DOC2001 is not set | ||
148 | # CONFIG_MTD_DOC2001PLUS is not set | ||
149 | |||
150 | # | ||
151 | # NAND Flash Device Drivers | ||
152 | # | ||
153 | # CONFIG_MTD_NAND is not set | ||
154 | |||
155 | # | ||
156 | # Block devices | ||
157 | # | ||
158 | # CONFIG_BLK_DEV_FD is not set | ||
159 | # CONFIG_BLK_DEV_XD is not set | ||
160 | # CONFIG_BLK_DEV_LOOP is not set | ||
161 | # CONFIG_BLK_DEV_RAM is not set | ||
162 | CONFIG_BLK_DEV_RAM_COUNT=16 | ||
163 | CONFIG_INITRAMFS_SOURCE="" | ||
164 | # CONFIG_CDROM_PKTCDVD is not set | ||
165 | |||
166 | # | ||
167 | # IO Schedulers | ||
168 | # | ||
169 | CONFIG_IOSCHED_NOOP=y | ||
170 | # CONFIG_IOSCHED_AS is not set | ||
171 | # CONFIG_IOSCHED_DEADLINE is not set | ||
172 | # CONFIG_IOSCHED_CFQ is not set | ||
173 | |||
174 | # | ||
175 | # ATA/ATAPI/MFM/RLL support | ||
176 | # | ||
177 | # CONFIG_IDE is not set | ||
178 | |||
179 | # | ||
180 | # Networking support | ||
181 | # | ||
182 | # CONFIG_NET is not set | ||
183 | # CONFIG_NETPOLL is not set | ||
184 | # CONFIG_NET_POLL_CONTROLLER is not set | ||
185 | |||
186 | # | ||
187 | # Input device support | ||
188 | # | ||
189 | # CONFIG_INPUT is not set | ||
190 | |||
191 | # | ||
192 | # Userland interfaces | ||
193 | # | ||
194 | |||
195 | # | ||
196 | # Input I/O drivers | ||
197 | # | ||
198 | # CONFIG_GAMEPORT is not set | ||
199 | CONFIG_SOUND_GAMEPORT=y | ||
200 | # CONFIG_SERIO is not set | ||
201 | # CONFIG_SERIO_I8042 is not set | ||
202 | |||
203 | # | ||
204 | # Input Device Drivers | ||
205 | # | ||
206 | |||
207 | # | ||
208 | # Character devices | ||
209 | # | ||
210 | # CONFIG_VT is not set | ||
211 | |||
212 | # | ||
213 | # Unix98 PTY support | ||
214 | # | ||
215 | # CONFIG_UNIX98_PTYS is not set | ||
216 | |||
217 | # | ||
218 | # Serial drivers | ||
219 | # | ||
220 | # CONFIG_SERIAL_8250 is not set | ||
221 | |||
222 | # | ||
223 | # Non-8250 serial port support | ||
224 | # | ||
225 | CONFIG_SERIAL_SH_SCI=y | ||
226 | CONFIG_SERIAL_SH_SCI_CONSOLE=y | ||
227 | CONFIG_SERIAL_CORE=y | ||
228 | CONFIG_SERIAL_CORE_CONSOLE=y | ||
229 | |||
230 | # | ||
231 | # I2C support | ||
232 | # | ||
233 | # CONFIG_I2C is not set | ||
234 | |||
235 | # | ||
236 | # USB support | ||
237 | # | ||
238 | # CONFIG_USB_ARCH_HAS_HCD is not set | ||
239 | # CONFIG_USB_ARCH_HAS_OHCI is not set | ||
240 | |||
241 | # | ||
242 | # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information | ||
243 | # | ||
244 | |||
245 | # | ||
246 | # USB Gadget Support | ||
247 | # | ||
248 | # CONFIG_USB_GADGET is not set | ||
249 | |||
250 | # | ||
251 | # File systems | ||
252 | # | ||
253 | # CONFIG_EXT2_FS is not set | ||
254 | # CONFIG_EXT3_FS is not set | ||
255 | # CONFIG_JBD is not set | ||
256 | # CONFIG_REISERFS_FS is not set | ||
257 | # CONFIG_JFS_FS is not set | ||
258 | # CONFIG_XFS_FS is not set | ||
259 | # CONFIG_MINIX_FS is not set | ||
260 | CONFIG_ROMFS_FS=y | ||
261 | # CONFIG_QUOTA is not set | ||
262 | # CONFIG_DNOTIFY is not set | ||
263 | # CONFIG_AUTOFS_FS is not set | ||
264 | # CONFIG_AUTOFS4_FS is not set | ||
265 | |||
266 | # | ||
267 | # CD-ROM/DVD Filesystems | ||
268 | # | ||
269 | # CONFIG_ISO9660_FS is not set | ||
270 | # CONFIG_UDF_FS is not set | ||
271 | |||
272 | # | ||
273 | # DOS/FAT/NT Filesystems | ||
274 | # | ||
275 | # CONFIG_MSDOS_FS is not set | ||
276 | # CONFIG_VFAT_FS is not set | ||
277 | # CONFIG_NTFS_FS is not set | ||
278 | |||
279 | # | ||
280 | # Pseudo filesystems | ||
281 | # | ||
282 | CONFIG_PROC_FS=y | ||
283 | # CONFIG_SYSFS is not set | ||
284 | # CONFIG_DEVFS_FS is not set | ||
285 | # CONFIG_TMPFS is not set | ||
286 | # CONFIG_HUGETLB_PAGE is not set | ||
287 | CONFIG_RAMFS=y | ||
288 | |||
289 | # | ||
290 | # Miscellaneous filesystems | ||
291 | # | ||
292 | # CONFIG_ADFS_FS is not set | ||
293 | # CONFIG_AFFS_FS is not set | ||
294 | # CONFIG_HFS_FS is not set | ||
295 | # CONFIG_HFSPLUS_FS is not set | ||
296 | # CONFIG_BEFS_FS is not set | ||
297 | # CONFIG_BFS_FS is not set | ||
298 | # CONFIG_EFS_FS is not set | ||
299 | # CONFIG_JFFS_FS is not set | ||
300 | # CONFIG_JFFS2_FS is not set | ||
301 | # CONFIG_CRAMFS is not set | ||
302 | # CONFIG_VXFS_FS is not set | ||
303 | # CONFIG_HPFS_FS is not set | ||
304 | # CONFIG_QNX4FS_FS is not set | ||
305 | # CONFIG_SYSV_FS is not set | ||
306 | # CONFIG_UFS_FS is not set | ||
307 | |||
308 | # | ||
309 | # Partition Types | ||
310 | # | ||
311 | # CONFIG_PARTITION_ADVANCED is not set | ||
312 | CONFIG_MSDOS_PARTITION=y | ||
313 | |||
314 | # | ||
315 | # Native Language Support | ||
316 | # | ||
317 | # CONFIG_NLS is not set | ||
318 | |||
319 | # | ||
320 | # Kernel hacking | ||
321 | # | ||
322 | CONFIG_DEBUG_KERNEL=y | ||
323 | # CONFIG_SCHEDSTATS is not set | ||
324 | # CONFIG_DEBUG_KOBJECT is not set | ||
325 | # CONFIG_DEBUG_FS is not set | ||
326 | CONFIG_FULLDEBUG=y | ||
327 | # CONFIG_HIGHPROFILE is not set | ||
328 | CONFIG_NO_KERNEL_MSG=y | ||
329 | # CONFIG_SYSCALL_PRINT is not set | ||
330 | # CONFIG_GDB_DEBUG is not set | ||
331 | # CONFIG_CONFIG_SH_STANDARD_BIOS is not set | ||
332 | # CONFIG_DEFAULT_CMDLINE is not set | ||
333 | # CONFIG_BLKDEV_RESERVE is not set | ||
334 | |||
335 | # | ||
336 | # Security options | ||
337 | # | ||
338 | # CONFIG_KEYS is not set | ||
339 | # CONFIG_SECURITY is not set | ||
340 | |||
341 | # | ||
342 | # Cryptographic options | ||
343 | # | ||
344 | # CONFIG_CRYPTO is not set | ||
345 | |||
346 | # | ||
347 | # Hardware crypto devices | ||
348 | # | ||
349 | |||
350 | # | ||
351 | # Library routines | ||
352 | # | ||
353 | # CONFIG_CRC_CCITT is not set | ||
354 | CONFIG_CRC32=y | ||
355 | # CONFIG_LIBCRC32C is not set | ||
356 | CONFIG_ZLIB_INFLATE=y | ||
diff --git a/arch/h8300/kernel/Makefile b/arch/h8300/kernel/Makefile new file mode 100644 index 000000000000..71b6131e98b8 --- /dev/null +++ b/arch/h8300/kernel/Makefile | |||
@@ -0,0 +1,11 @@ | |||
1 | # | ||
2 | # Makefile for the linux kernel. | ||
3 | # | ||
4 | |||
5 | extra-y := vmlinux.lds | ||
6 | |||
7 | obj-y := process.o traps.o ptrace.o ints.o \ | ||
8 | sys_h8300.o time.o semaphore.o signal.o \ | ||
9 | setup.o gpio.o init_task.o syscalls.o | ||
10 | |||
11 | obj-$(CONFIG_MODULES) += module.o h8300_ksyms.o | ||
diff --git a/arch/h8300/kernel/asm-offsets.c b/arch/h8300/kernel/asm-offsets.c new file mode 100644 index 000000000000..b78b82ad28a3 --- /dev/null +++ b/arch/h8300/kernel/asm-offsets.c | |||
@@ -0,0 +1,65 @@ | |||
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/bootinfo.h> | ||
17 | #include <asm/irq.h> | ||
18 | #include <asm/ptrace.h> | ||
19 | |||
20 | #define DEFINE(sym, val) \ | ||
21 | asm volatile("\n->" #sym " %0 " #val : : "i" (val)) | ||
22 | |||
23 | #define BLANK() asm volatile("\n->" : : ) | ||
24 | |||
25 | int main(void) | ||
26 | { | ||
27 | /* offsets into the task struct */ | ||
28 | DEFINE(TASK_STATE, offsetof(struct task_struct, state)); | ||
29 | DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags)); | ||
30 | DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace)); | ||
31 | DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked)); | ||
32 | DEFINE(TASK_THREAD, offsetof(struct task_struct, thread)); | ||
33 | DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, thread_info)); | ||
34 | DEFINE(TASK_MM, offsetof(struct task_struct, mm)); | ||
35 | DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); | ||
36 | |||
37 | /* offsets into the irq_cpustat_t struct */ | ||
38 | DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending)); | ||
39 | |||
40 | /* offsets into the thread struct */ | ||
41 | DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp)); | ||
42 | DEFINE(THREAD_USP, offsetof(struct thread_struct, usp)); | ||
43 | DEFINE(THREAD_CCR, offsetof(struct thread_struct, ccr)); | ||
44 | |||
45 | /* offsets into the pt_regs struct */ | ||
46 | DEFINE(LER0, offsetof(struct pt_regs, er0) - sizeof(long)); | ||
47 | DEFINE(LER1, offsetof(struct pt_regs, er1) - sizeof(long)); | ||
48 | DEFINE(LER2, offsetof(struct pt_regs, er2) - sizeof(long)); | ||
49 | DEFINE(LER3, offsetof(struct pt_regs, er3) - sizeof(long)); | ||
50 | DEFINE(LER4, offsetof(struct pt_regs, er4) - sizeof(long)); | ||
51 | DEFINE(LER5, offsetof(struct pt_regs, er5) - sizeof(long)); | ||
52 | DEFINE(LER6, offsetof(struct pt_regs, er6) - sizeof(long)); | ||
53 | DEFINE(LORIG, offsetof(struct pt_regs, orig_er0) - sizeof(long)); | ||
54 | DEFINE(LCCR, offsetof(struct pt_regs, ccr) - sizeof(long)); | ||
55 | DEFINE(LVEC, offsetof(struct pt_regs, vector) - sizeof(long)); | ||
56 | #if defined(__H8300S__) | ||
57 | DEFINE(LEXR, offsetof(struct pt_regs, exr) - sizeof(long)); | ||
58 | #endif | ||
59 | DEFINE(LRET, offsetof(struct pt_regs, pc) - sizeof(long)); | ||
60 | |||
61 | DEFINE(PT_PTRACED, PT_PTRACED); | ||
62 | DEFINE(PT_DTRACE, PT_DTRACE); | ||
63 | |||
64 | return 0; | ||
65 | } | ||
diff --git a/arch/h8300/kernel/gpio.c b/arch/h8300/kernel/gpio.c new file mode 100644 index 000000000000..795682b873e2 --- /dev/null +++ b/arch/h8300/kernel/gpio.c | |||
@@ -0,0 +1,174 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/kernel/gpio.c | ||
3 | * | ||
4 | * Yoshinori Sato <ysato@users.sourceforge.jp> | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | /* | ||
9 | * Internal I/O Port Management | ||
10 | */ | ||
11 | |||
12 | #include <linux/config.h> | ||
13 | #include <linux/stddef.h> | ||
14 | #include <linux/proc_fs.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/string.h> | ||
17 | #include <linux/fs.h> | ||
18 | #include <linux/init.h> | ||
19 | |||
20 | #define _(addr) (volatile unsigned char *)(addr) | ||
21 | #if defined(CONFIG_H83007) || defined(CONFIG_H83068) | ||
22 | #include <asm/regs306x.h> | ||
23 | static volatile unsigned char *ddrs[] = { | ||
24 | _(P1DDR),_(P2DDR),_(P3DDR),_(P4DDR),_(P5DDR),_(P6DDR), | ||
25 | NULL, _(P8DDR),_(P9DDR),_(PADDR),_(PBDDR), | ||
26 | }; | ||
27 | #define MAX_PORT 11 | ||
28 | #endif | ||
29 | |||
30 | #if defined(CONFIG_H83002) || defined(CONFIG_H8048) | ||
31 | /* Fix me!! */ | ||
32 | #include <asm/regs306x.h> | ||
33 | static volatile unsigned char *ddrs[] = { | ||
34 | _(P1DDR),_(P2DDR),_(P3DDR),_(P4DDR),_(P5DDR),_(P6DDR), | ||
35 | NULL, _(P8DDR),_(P9DDR),_(PADDR),_(PBDDR), | ||
36 | }; | ||
37 | #define MAX_PORT 11 | ||
38 | #endif | ||
39 | |||
40 | #if defined(CONFIG_H8S2678) | ||
41 | #include <asm/regs267x.h> | ||
42 | static volatile unsigned char *ddrs[] = { | ||
43 | _(P1DDR),_(P2DDR),_(P3DDR),NULL ,_(P5DDR),_(P6DDR), | ||
44 | _(P7DDR),_(P8DDR),NULL, _(PADDR),_(PBDDR),_(PCDDR), | ||
45 | _(PDDDR),_(PEDDR),_(PFDDR),_(PGDDR),_(PHDDR), | ||
46 | _(PADDR),_(PBDDR),_(PCDDR),_(PDDDR),_(PEDDR),_(PFDDR), | ||
47 | _(PGDDR),_(PHDDR) | ||
48 | }; | ||
49 | #define MAX_PORT 17 | ||
50 | #endif | ||
51 | #undef _ | ||
52 | |||
53 | #if !defined(P1DDR) | ||
54 | #error Unsuppoted CPU Selection | ||
55 | #endif | ||
56 | |||
57 | static struct { | ||
58 | unsigned char used; | ||
59 | unsigned char ddr; | ||
60 | } gpio_regs[MAX_PORT]; | ||
61 | |||
62 | extern char *_platform_gpio_table(int length); | ||
63 | |||
64 | int h8300_reserved_gpio(int port, unsigned int bits) | ||
65 | { | ||
66 | unsigned char *used; | ||
67 | |||
68 | if (port < 0 || port >= MAX_PORT) | ||
69 | return -1; | ||
70 | used = &(gpio_regs[port].used); | ||
71 | if ((*used & bits) != 0) | ||
72 | return 0; | ||
73 | *used |= bits; | ||
74 | return 1; | ||
75 | } | ||
76 | |||
77 | int h8300_free_gpio(int port, unsigned int bits) | ||
78 | { | ||
79 | unsigned char *used; | ||
80 | |||
81 | if (port < 0 || port >= MAX_PORT) | ||
82 | return -1; | ||
83 | used = &(gpio_regs[port].used); | ||
84 | if ((*used & bits) != bits) | ||
85 | return 0; | ||
86 | *used &= (~bits); | ||
87 | return 1; | ||
88 | } | ||
89 | |||
90 | int h8300_set_gpio_dir(int port_bit,int dir) | ||
91 | { | ||
92 | int port = (port_bit >> 8) & 0xff; | ||
93 | int bit = port_bit & 0xff; | ||
94 | |||
95 | if (ddrs[port] == NULL) | ||
96 | return 0; | ||
97 | if (gpio_regs[port].used & bit) { | ||
98 | if (dir) | ||
99 | gpio_regs[port].ddr |= bit; | ||
100 | else | ||
101 | gpio_regs[port].ddr &= ~bit; | ||
102 | *ddrs[port] = gpio_regs[port].ddr; | ||
103 | return 1; | ||
104 | } else | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | int h8300_get_gpio_dir(int port_bit) | ||
109 | { | ||
110 | int port = (port_bit >> 8) & 0xff; | ||
111 | int bit = port_bit & 0xff; | ||
112 | |||
113 | if (ddrs[port] == NULL) | ||
114 | return 0; | ||
115 | if (gpio_regs[port].used & bit) { | ||
116 | return (gpio_regs[port].ddr & bit) != 0; | ||
117 | } else | ||
118 | return -1; | ||
119 | } | ||
120 | |||
121 | #if defined(CONFIG_PROC_FS) | ||
122 | static char *port_status(int portno) | ||
123 | { | ||
124 | static char result[10]; | ||
125 | const static char io[2]={'I','O'}; | ||
126 | char *rp; | ||
127 | int c; | ||
128 | unsigned char used,ddr; | ||
129 | |||
130 | used = gpio_regs[portno].used; | ||
131 | ddr = gpio_regs[portno].ddr; | ||
132 | result[8]='\0'; | ||
133 | rp = result + 7; | ||
134 | for (c = 8; c > 0; c--,rp--,used >>= 1, ddr >>= 1) | ||
135 | if (used & 0x01) | ||
136 | *rp = io[ ddr & 0x01]; | ||
137 | else | ||
138 | *rp = '-'; | ||
139 | return result; | ||
140 | } | ||
141 | |||
142 | static int gpio_proc_read(char *buf, char **start, off_t offset, | ||
143 | int len, int *unused_i, void *unused_v) | ||
144 | { | ||
145 | int c,outlen; | ||
146 | const static char port_name[]="123456789ABCDEFGH"; | ||
147 | outlen = 0; | ||
148 | for (c = 0; c < MAX_PORT; c++) { | ||
149 | if (ddrs[c] == NULL) | ||
150 | continue ; | ||
151 | len = sprintf(buf,"P%c: %s\n",port_name[c],port_status(c)); | ||
152 | buf += len; | ||
153 | outlen += len; | ||
154 | } | ||
155 | return outlen; | ||
156 | } | ||
157 | |||
158 | static __init int register_proc(void) | ||
159 | { | ||
160 | struct proc_dir_entry *proc_gpio; | ||
161 | |||
162 | proc_gpio = create_proc_entry("gpio", S_IRUGO, NULL); | ||
163 | if (proc_gpio) | ||
164 | proc_gpio->read_proc = gpio_proc_read; | ||
165 | return proc_gpio != NULL; | ||
166 | } | ||
167 | |||
168 | __initcall(register_proc); | ||
169 | #endif | ||
170 | |||
171 | void __init h8300_gpio_init(void) | ||
172 | { | ||
173 | memcpy(gpio_regs,_platform_gpio_table(sizeof(gpio_regs)),sizeof(gpio_regs)); | ||
174 | } | ||
diff --git a/arch/h8300/kernel/h8300_ksyms.c b/arch/h8300/kernel/h8300_ksyms.c new file mode 100644 index 000000000000..5a630233112f --- /dev/null +++ b/arch/h8300/kernel/h8300_ksyms.c | |||
@@ -0,0 +1,112 @@ | |||
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/setup.h> | ||
13 | #include <asm/pgalloc.h> | ||
14 | #include <asm/irq.h> | ||
15 | #include <asm/io.h> | ||
16 | #include <asm/semaphore.h> | ||
17 | #include <asm/checksum.h> | ||
18 | #include <asm/current.h> | ||
19 | #include <asm/gpio.h> | ||
20 | |||
21 | //asmlinkage long long __ashrdi3 (long long, int); | ||
22 | //asmlinkage long long __lshrdi3 (long long, int); | ||
23 | extern char h8300_debug_device[]; | ||
24 | |||
25 | extern void dump_thread(struct pt_regs *, struct user *); | ||
26 | |||
27 | /* platform dependent support */ | ||
28 | |||
29 | EXPORT_SYMBOL(dump_thread); | ||
30 | EXPORT_SYMBOL(strnlen); | ||
31 | EXPORT_SYMBOL(strrchr); | ||
32 | EXPORT_SYMBOL(strstr); | ||
33 | EXPORT_SYMBOL(strchr); | ||
34 | EXPORT_SYMBOL(strcat); | ||
35 | EXPORT_SYMBOL(strlen); | ||
36 | EXPORT_SYMBOL(strcmp); | ||
37 | EXPORT_SYMBOL(strncmp); | ||
38 | |||
39 | EXPORT_SYMBOL(ip_fast_csum); | ||
40 | |||
41 | EXPORT_SYMBOL(kernel_thread); | ||
42 | EXPORT_SYMBOL(enable_irq); | ||
43 | EXPORT_SYMBOL(disable_irq); | ||
44 | |||
45 | /* Networking helper routines. */ | ||
46 | EXPORT_SYMBOL(csum_partial_copy); | ||
47 | |||
48 | /* The following are special because they're not called | ||
49 | explicitly (the C compiler generates them). Fortunately, | ||
50 | their interface isn't gonna change any time soon now, so | ||
51 | it's OK to leave it out of version control. */ | ||
52 | //EXPORT_SYMBOL(__ashrdi3); | ||
53 | //EXPORT_SYMBOL(__lshrdi3); | ||
54 | EXPORT_SYMBOL(memcpy); | ||
55 | EXPORT_SYMBOL(memset); | ||
56 | EXPORT_SYMBOL(memcmp); | ||
57 | EXPORT_SYMBOL(memscan); | ||
58 | EXPORT_SYMBOL(memmove); | ||
59 | |||
60 | EXPORT_SYMBOL(get_wchan); | ||
61 | |||
62 | /* | ||
63 | * libgcc functions - functions that are used internally by the | ||
64 | * compiler... (prototypes are not correct though, but that | ||
65 | * doesn't really matter since they're not versioned). | ||
66 | */ | ||
67 | extern void __gcc_bcmp(void); | ||
68 | extern void __ashldi3(void); | ||
69 | extern void __ashrdi3(void); | ||
70 | extern void __cmpdi2(void); | ||
71 | extern void __divdi3(void); | ||
72 | extern void __divsi3(void); | ||
73 | extern void __lshrdi3(void); | ||
74 | extern void __moddi3(void); | ||
75 | extern void __modsi3(void); | ||
76 | extern void __muldi3(void); | ||
77 | extern void __mulsi3(void); | ||
78 | extern void __negdi2(void); | ||
79 | extern void __ucmpdi2(void); | ||
80 | extern void __udivdi3(void); | ||
81 | extern void __udivmoddi4(void); | ||
82 | extern void __udivsi3(void); | ||
83 | extern void __umoddi3(void); | ||
84 | extern void __umodsi3(void); | ||
85 | |||
86 | /* gcc lib functions */ | ||
87 | EXPORT_SYMBOL(__gcc_bcmp); | ||
88 | EXPORT_SYMBOL(__ashldi3); | ||
89 | EXPORT_SYMBOL(__ashrdi3); | ||
90 | EXPORT_SYMBOL(__cmpdi2); | ||
91 | EXPORT_SYMBOL(__divdi3); | ||
92 | EXPORT_SYMBOL(__divsi3); | ||
93 | EXPORT_SYMBOL(__lshrdi3); | ||
94 | EXPORT_SYMBOL(__moddi3); | ||
95 | EXPORT_SYMBOL(__modsi3); | ||
96 | EXPORT_SYMBOL(__muldi3); | ||
97 | EXPORT_SYMBOL(__mulsi3); | ||
98 | EXPORT_SYMBOL(__negdi2); | ||
99 | EXPORT_SYMBOL(__ucmpdi2); | ||
100 | EXPORT_SYMBOL(__udivdi3); | ||
101 | EXPORT_SYMBOL(__udivmoddi4); | ||
102 | EXPORT_SYMBOL(__udivsi3); | ||
103 | EXPORT_SYMBOL(__umoddi3); | ||
104 | EXPORT_SYMBOL(__umodsi3); | ||
105 | |||
106 | #ifdef MAGIC_ROM_PTR | ||
107 | EXPORT_SYMBOL(is_in_rom); | ||
108 | #endif | ||
109 | |||
110 | EXPORT_SYMBOL(h8300_reserved_gpio); | ||
111 | EXPORT_SYMBOL(h8300_free_gpio); | ||
112 | EXPORT_SYMBOL(h8300_set_gpio_dir); | ||
diff --git a/arch/h8300/kernel/init_task.c b/arch/h8300/kernel/init_task.c new file mode 100644 index 000000000000..19272c2ac56a --- /dev/null +++ b/arch/h8300/kernel/init_task.c | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/kernel/init_task.c | ||
3 | */ | ||
4 | #include <linux/mm.h> | ||
5 | #include <linux/module.h> | ||
6 | #include <linux/sched.h> | ||
7 | #include <linux/init.h> | ||
8 | #include <linux/init_task.h> | ||
9 | #include <linux/fs.h> | ||
10 | #include <linux/mqueue.h> | ||
11 | |||
12 | #include <asm/uaccess.h> | ||
13 | #include <asm/pgtable.h> | ||
14 | |||
15 | static struct fs_struct init_fs = INIT_FS; | ||
16 | static struct files_struct init_files = INIT_FILES; | ||
17 | static struct signal_struct init_signals = INIT_SIGNALS(init_signals); | ||
18 | static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); | ||
19 | struct mm_struct init_mm = INIT_MM(init_mm); | ||
20 | |||
21 | EXPORT_SYMBOL(init_mm); | ||
22 | |||
23 | /* | ||
24 | * Initial task structure. | ||
25 | * | ||
26 | * All other task structs will be allocated on slabs in fork.c | ||
27 | */ | ||
28 | __asm__(".align 4"); | ||
29 | struct task_struct init_task = INIT_TASK(init_task); | ||
30 | |||
31 | EXPORT_SYMBOL(init_task); | ||
32 | |||
33 | /* | ||
34 | * Initial thread structure. | ||
35 | * | ||
36 | * We need to make sure that this is 8192-byte aligned due to the | ||
37 | * way process stacks are handled. This is done by having a special | ||
38 | * "init_task" linker map entry.. | ||
39 | */ | ||
40 | union thread_union init_thread_union | ||
41 | __attribute__((__section__(".data.init_task"))) = | ||
42 | { INIT_THREAD_INFO(init_task) }; | ||
43 | |||
diff --git a/arch/h8300/kernel/ints.c b/arch/h8300/kernel/ints.c new file mode 100644 index 000000000000..edb3c4170013 --- /dev/null +++ b/arch/h8300/kernel/ints.c | |||
@@ -0,0 +1,255 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/platform/h8300h/ints.c | ||
3 | * | ||
4 | * Yoshinori Sato <ysato@users.sourceforge.jp> | ||
5 | * | ||
6 | * Based on linux/arch/$(ARCH)/platform/$(PLATFORM)/ints.c | ||
7 | * | ||
8 | * This file is subject to the terms and conditions of the GNU General Public | ||
9 | * License. See the file COPYING in the main directory of this archive | ||
10 | * for more details. | ||
11 | * | ||
12 | * Copyright 1996 Roman Zippel | ||
13 | * Copyright 1999 D. Jeff Dionne <jeff@rt-control.com> | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/types.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/kernel_stat.h> | ||
21 | #include <linux/seq_file.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/random.h> | ||
24 | #include <linux/bootmem.h> | ||
25 | #include <linux/hardirq.h> | ||
26 | |||
27 | #include <asm/system.h> | ||
28 | #include <asm/irq.h> | ||
29 | #include <asm/traps.h> | ||
30 | #include <asm/io.h> | ||
31 | #include <asm/setup.h> | ||
32 | #include <asm/errno.h> | ||
33 | |||
34 | /* | ||
35 | * This structure has only 4 elements for speed reasons | ||
36 | */ | ||
37 | typedef struct irq_handler { | ||
38 | irqreturn_t (*handler)(int, void *, struct pt_regs *); | ||
39 | int flags; | ||
40 | int count; | ||
41 | void *dev_id; | ||
42 | const char *devname; | ||
43 | } irq_handler_t; | ||
44 | |||
45 | static irq_handler_t *irq_list[NR_IRQS]; | ||
46 | static int use_kmalloc; | ||
47 | |||
48 | extern unsigned long *interrupt_redirect_table; | ||
49 | extern const int h8300_saved_vectors[]; | ||
50 | extern const unsigned long h8300_trap_table[]; | ||
51 | int h8300_enable_irq_pin(unsigned int irq); | ||
52 | void h8300_disable_irq_pin(unsigned int irq); | ||
53 | |||
54 | #define CPU_VECTOR ((unsigned long *)0x000000) | ||
55 | #define ADDR_MASK (0xffffff) | ||
56 | |||
57 | #if defined(CONFIG_RAMKERNEL) | ||
58 | static unsigned long __init *get_vector_address(void) | ||
59 | { | ||
60 | unsigned long *rom_vector = CPU_VECTOR; | ||
61 | unsigned long base,tmp; | ||
62 | int vec_no; | ||
63 | |||
64 | base = rom_vector[EXT_IRQ0] & ADDR_MASK; | ||
65 | |||
66 | /* check romvector format */ | ||
67 | for (vec_no = EXT_IRQ1; vec_no <= EXT_IRQ0+EXT_IRQS; vec_no++) { | ||
68 | if ((base+(vec_no - EXT_IRQ0)*4) != (rom_vector[vec_no] & ADDR_MASK)) | ||
69 | return NULL; | ||
70 | } | ||
71 | |||
72 | /* ramvector base address */ | ||
73 | base -= EXT_IRQ0*4; | ||
74 | |||
75 | /* writerble check */ | ||
76 | tmp = ~(*(volatile unsigned long *)base); | ||
77 | (*(volatile unsigned long *)base) = tmp; | ||
78 | if ((*(volatile unsigned long *)base) != tmp) | ||
79 | return NULL; | ||
80 | return (unsigned long *)base; | ||
81 | } | ||
82 | #endif | ||
83 | |||
84 | void __init init_IRQ(void) | ||
85 | { | ||
86 | #if defined(CONFIG_RAMKERNEL) | ||
87 | int i; | ||
88 | unsigned long *ramvec,*ramvec_p; | ||
89 | const unsigned long *trap_entry; | ||
90 | const int *saved_vector; | ||
91 | |||
92 | ramvec = get_vector_address(); | ||
93 | if (ramvec == NULL) | ||
94 | panic("interrupt vector serup failed."); | ||
95 | else | ||
96 | printk(KERN_INFO "virtual vector at 0x%08lx\n",(unsigned long)ramvec); | ||
97 | |||
98 | /* create redirect table */ | ||
99 | ramvec_p = ramvec; | ||
100 | trap_entry = h8300_trap_table; | ||
101 | saved_vector = h8300_saved_vectors; | ||
102 | for ( i = 0; i < NR_IRQS; i++) { | ||
103 | if (i == *saved_vector) { | ||
104 | ramvec_p++; | ||
105 | saved_vector++; | ||
106 | } else { | ||
107 | if ( i < NR_TRAPS ) { | ||
108 | if (*trap_entry) | ||
109 | *ramvec_p = VECTOR(*trap_entry); | ||
110 | ramvec_p++; | ||
111 | trap_entry++; | ||
112 | } else | ||
113 | *ramvec_p++ = REDIRECT(interrupt_entry); | ||
114 | } | ||
115 | } | ||
116 | interrupt_redirect_table = ramvec; | ||
117 | #ifdef DUMP_VECTOR | ||
118 | ramvec_p = ramvec; | ||
119 | for (i = 0; i < NR_IRQS; i++) { | ||
120 | if ((i % 8) == 0) | ||
121 | printk(KERN_DEBUG "\n%p: ",ramvec_p); | ||
122 | printk(KERN_DEBUG "%p ",*ramvec_p); | ||
123 | ramvec_p++; | ||
124 | } | ||
125 | printk(KERN_DEBUG "\n"); | ||
126 | #endif | ||
127 | #endif | ||
128 | } | ||
129 | |||
130 | int request_irq(unsigned int irq, | ||
131 | irqreturn_t (*handler)(int, void *, struct pt_regs *), | ||
132 | unsigned long flags, const char *devname, void *dev_id) | ||
133 | { | ||
134 | irq_handler_t *irq_handle; | ||
135 | if (irq < 0 || irq >= NR_IRQS) { | ||
136 | printk(KERN_ERR "Incorrect IRQ %d from %s\n", irq, devname); | ||
137 | return -EINVAL; | ||
138 | } | ||
139 | |||
140 | if (irq_list[irq] || (h8300_enable_irq_pin(irq) == -EBUSY)) | ||
141 | return -EBUSY; | ||
142 | |||
143 | if (use_kmalloc) | ||
144 | irq_handle = (irq_handler_t *)kmalloc(sizeof(irq_handler_t), GFP_ATOMIC); | ||
145 | else { | ||
146 | /* use bootmem allocater */ | ||
147 | irq_handle = (irq_handler_t *)alloc_bootmem(sizeof(irq_handler_t)); | ||
148 | irq_handle = (irq_handler_t *)((unsigned long)irq_handle | 0x80000000); | ||
149 | } | ||
150 | |||
151 | if (irq_handle == NULL) | ||
152 | return -ENOMEM; | ||
153 | |||
154 | irq_handle->handler = handler; | ||
155 | irq_handle->flags = flags; | ||
156 | irq_handle->count = 0; | ||
157 | irq_handle->dev_id = dev_id; | ||
158 | irq_handle->devname = devname; | ||
159 | irq_list[irq] = irq_handle; | ||
160 | |||
161 | if (irq_handle->flags & SA_SAMPLE_RANDOM) | ||
162 | rand_initialize_irq(irq); | ||
163 | |||
164 | enable_irq(irq); | ||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | EXPORT_SYMBOL(request_irq); | ||
169 | |||
170 | void free_irq(unsigned int irq, void *dev_id) | ||
171 | { | ||
172 | if (irq >= NR_IRQS) | ||
173 | return; | ||
174 | |||
175 | if (!irq_list[irq] || irq_list[irq]->dev_id != dev_id) | ||
176 | printk(KERN_WARNING "Removing probably wrong IRQ %d from %s\n", | ||
177 | irq, irq_list[irq]->devname); | ||
178 | disable_irq(irq); | ||
179 | h8300_disable_irq_pin(irq); | ||
180 | if (((unsigned long)irq_list[irq] & 0x80000000) == 0) { | ||
181 | kfree(irq_list[irq]); | ||
182 | irq_list[irq] = NULL; | ||
183 | } | ||
184 | } | ||
185 | |||
186 | EXPORT_SYMBOL(free_irq); | ||
187 | |||
188 | /* | ||
189 | * Do we need these probe functions on the m68k? | ||
190 | */ | ||
191 | unsigned long probe_irq_on (void) | ||
192 | { | ||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | EXPORT_SYMBOL(probe_irq_on); | ||
197 | |||
198 | int probe_irq_off (unsigned long irqs) | ||
199 | { | ||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | EXPORT_SYMBOL(probe_irq_off); | ||
204 | |||
205 | void enable_irq(unsigned int irq) | ||
206 | { | ||
207 | if (irq >= EXT_IRQ0 && irq <= (EXT_IRQ0 + EXT_IRQS)) | ||
208 | IER_REGS |= 1 << (irq - EXT_IRQ0); | ||
209 | } | ||
210 | |||
211 | void disable_irq(unsigned int irq) | ||
212 | { | ||
213 | if (irq >= EXT_IRQ0 && irq <= (EXT_IRQ0 + EXT_IRQS)) | ||
214 | IER_REGS &= ~(1 << (irq - EXT_IRQ0)); | ||
215 | } | ||
216 | |||
217 | asmlinkage void process_int(int irq, struct pt_regs *fp) | ||
218 | { | ||
219 | irq_enter(); | ||
220 | h8300_clear_isr(irq); | ||
221 | if (irq >= NR_TRAPS && irq < NR_IRQS) { | ||
222 | if (irq_list[irq]) { | ||
223 | irq_list[irq]->handler(irq, irq_list[irq]->dev_id, fp); | ||
224 | irq_list[irq]->count++; | ||
225 | if (irq_list[irq]->flags & SA_SAMPLE_RANDOM) | ||
226 | add_interrupt_randomness(irq); | ||
227 | } | ||
228 | } else { | ||
229 | BUG(); | ||
230 | } | ||
231 | irq_exit(); | ||
232 | } | ||
233 | |||
234 | int show_interrupts(struct seq_file *p, void *v) | ||
235 | { | ||
236 | int i = *(loff_t *) v; | ||
237 | |||
238 | if ((i < NR_IRQS) && (irq_list[i]!=NULL)) { | ||
239 | seq_printf(p, "%3d: %10u ",i,irq_list[i]->count); | ||
240 | seq_printf(p, "%s\n", irq_list[i]->devname); | ||
241 | } | ||
242 | |||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | void init_irq_proc(void) | ||
247 | { | ||
248 | } | ||
249 | |||
250 | static int __init enable_kmalloc(void) | ||
251 | { | ||
252 | use_kmalloc = 1; | ||
253 | return 0; | ||
254 | } | ||
255 | core_initcall(enable_kmalloc); | ||
diff --git a/arch/h8300/kernel/module.c b/arch/h8300/kernel/module.c new file mode 100644 index 000000000000..4fd7138a6e03 --- /dev/null +++ b/arch/h8300/kernel/module.c | |||
@@ -0,0 +1,122 @@ | |||
1 | #include <linux/moduleloader.h> | ||
2 | #include <linux/elf.h> | ||
3 | #include <linux/vmalloc.h> | ||
4 | #include <linux/fs.h> | ||
5 | #include <linux/string.h> | ||
6 | #include <linux/kernel.h> | ||
7 | |||
8 | #if 0 | ||
9 | #define DEBUGP printk | ||
10 | #else | ||
11 | #define DEBUGP(fmt...) | ||
12 | #endif | ||
13 | |||
14 | void *module_alloc(unsigned long size) | ||
15 | { | ||
16 | if (size == 0) | ||
17 | return NULL; | ||
18 | return vmalloc(size); | ||
19 | } | ||
20 | |||
21 | |||
22 | /* Free memory returned from module_alloc */ | ||
23 | void module_free(struct module *mod, void *module_region) | ||
24 | { | ||
25 | vfree(module_region); | ||
26 | /* FIXME: If module_region == mod->init_region, trim exception | ||
27 | table entries. */ | ||
28 | } | ||
29 | |||
30 | /* We don't need anything special. */ | ||
31 | int module_frob_arch_sections(Elf_Ehdr *hdr, | ||
32 | Elf_Shdr *sechdrs, | ||
33 | char *secstrings, | ||
34 | struct module *mod) | ||
35 | { | ||
36 | return 0; | ||
37 | } | ||
38 | |||
39 | int apply_relocate(Elf32_Shdr *sechdrs, | ||
40 | const char *strtab, | ||
41 | unsigned int symindex, | ||
42 | unsigned int relsec, | ||
43 | struct module *me) | ||
44 | { | ||
45 | printk(KERN_ERR "module %s: RELOCATION unsupported\n", | ||
46 | me->name); | ||
47 | return -ENOEXEC; | ||
48 | } | ||
49 | |||
50 | int apply_relocate_add(Elf32_Shdr *sechdrs, | ||
51 | const char *strtab, | ||
52 | unsigned int symindex, | ||
53 | unsigned int relsec, | ||
54 | struct module *me) | ||
55 | { | ||
56 | unsigned int i; | ||
57 | Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr; | ||
58 | |||
59 | DEBUGP("Applying relocate section %u to %u\n", relsec, | ||
60 | sechdrs[relsec].sh_info); | ||
61 | for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) { | ||
62 | /* This is where to make the change */ | ||
63 | uint32_t *loc = (uint32_t *)(sechdrs[sechdrs[relsec].sh_info].sh_addr | ||
64 | + rela[i].r_offset); | ||
65 | /* This is the symbol it is referring to. Note that all | ||
66 | undefined symbols have been resolved. */ | ||
67 | Elf32_Sym *sym = (Elf32_Sym *)sechdrs[symindex].sh_addr | ||
68 | + ELF32_R_SYM(rela[i].r_info); | ||
69 | uint32_t v = sym->st_value + rela[i].r_addend; | ||
70 | |||
71 | switch (ELF32_R_TYPE(rela[i].r_info)) { | ||
72 | case R_H8_DIR24R8: | ||
73 | loc = (uint32_t *)((uint32_t)loc - 1); | ||
74 | *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v); | ||
75 | break; | ||
76 | case R_H8_DIR24A8: | ||
77 | if (ELF32_R_SYM(rela[i].r_info)) | ||
78 | *loc += v; | ||
79 | break; | ||
80 | case R_H8_DIR32: | ||
81 | case R_H8_DIR32A16: | ||
82 | *loc += v; | ||
83 | break; | ||
84 | case R_H8_PCREL16: | ||
85 | v -= (unsigned long)loc + 2; | ||
86 | if ((Elf32_Sword)v > 0x7fff || | ||
87 | (Elf32_Sword)v < -(Elf32_Sword)0x8000) | ||
88 | goto overflow; | ||
89 | else | ||
90 | *(unsigned short *)loc = v; | ||
91 | break; | ||
92 | case R_H8_PCREL8: | ||
93 | v -= (unsigned long)loc + 1; | ||
94 | if ((Elf32_Sword)v > 0x7f || | ||
95 | (Elf32_Sword)v < -(Elf32_Sword)0x80) | ||
96 | goto overflow; | ||
97 | else | ||
98 | *(unsigned char *)loc = v; | ||
99 | break; | ||
100 | default: | ||
101 | printk(KERN_ERR "module %s: Unknown relocation: %u\n", | ||
102 | me->name, ELF32_R_TYPE(rela[i].r_info)); | ||
103 | return -ENOEXEC; | ||
104 | } | ||
105 | } | ||
106 | return 0; | ||
107 | overflow: | ||
108 | printk(KERN_ERR "module %s: relocation offset overflow: %08x\n", | ||
109 | me->name, rela[i].r_offset); | ||
110 | return -ENOEXEC; | ||
111 | } | ||
112 | |||
113 | int module_finalize(const Elf_Ehdr *hdr, | ||
114 | const Elf_Shdr *sechdrs, | ||
115 | struct module *me) | ||
116 | { | ||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | void module_arch_cleanup(struct module *mod) | ||
121 | { | ||
122 | } | ||
diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c new file mode 100644 index 000000000000..134aec1c6d19 --- /dev/null +++ b/arch/h8300/kernel/process.c | |||
@@ -0,0 +1,288 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/kernel/process.c | ||
3 | * | ||
4 | * Yoshinori Sato <ysato@users.sourceforge.jp> | ||
5 | * | ||
6 | * Based on: | ||
7 | * | ||
8 | * linux/arch/m68knommu/kernel/process.c | ||
9 | * | ||
10 | * Copyright (C) 1998 D. Jeff Dionne <jeff@ryeham.ee.ryerson.ca>, | ||
11 | * Kenneth Albanowski <kjahds@kjahds.com>, | ||
12 | * The Silver Hammer Group, Ltd. | ||
13 | * | ||
14 | * linux/arch/m68k/kernel/process.c | ||
15 | * | ||
16 | * Copyright (C) 1995 Hamish Macdonald | ||
17 | * | ||
18 | * 68060 fixes by Jesper Skov | ||
19 | */ | ||
20 | |||
21 | /* | ||
22 | * This file handles the architecture-dependent parts of process handling.. | ||
23 | */ | ||
24 | |||
25 | #include <linux/config.h> | ||
26 | #include <linux/errno.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/sched.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/mm.h> | ||
31 | #include <linux/smp.h> | ||
32 | #include <linux/smp_lock.h> | ||
33 | #include <linux/stddef.h> | ||
34 | #include <linux/unistd.h> | ||
35 | #include <linux/ptrace.h> | ||
36 | #include <linux/slab.h> | ||
37 | #include <linux/user.h> | ||
38 | #include <linux/a.out.h> | ||
39 | #include <linux/interrupt.h> | ||
40 | #include <linux/reboot.h> | ||
41 | |||
42 | #include <asm/uaccess.h> | ||
43 | #include <asm/system.h> | ||
44 | #include <asm/traps.h> | ||
45 | #include <asm/setup.h> | ||
46 | #include <asm/pgtable.h> | ||
47 | |||
48 | asmlinkage void ret_from_fork(void); | ||
49 | |||
50 | /* | ||
51 | * The idle loop on an H8/300.. | ||
52 | */ | ||
53 | #if !defined(CONFIG_H8300H_SIM) && !defined(CONFIG_H8S_SIM) | ||
54 | void default_idle(void) | ||
55 | { | ||
56 | while(1) { | ||
57 | if (need_resched()) { | ||
58 | local_irq_enable(); | ||
59 | __asm__("sleep"); | ||
60 | local_irq_disable(); | ||
61 | } | ||
62 | schedule(); | ||
63 | } | ||
64 | } | ||
65 | #else | ||
66 | void default_idle(void) | ||
67 | { | ||
68 | while(1) { | ||
69 | if (need_resched()) | ||
70 | schedule(); | ||
71 | } | ||
72 | } | ||
73 | #endif | ||
74 | void (*idle)(void) = default_idle; | ||
75 | |||
76 | /* | ||
77 | * The idle thread. There's no useful work to be | ||
78 | * done, so just try to conserve power and have a | ||
79 | * low exit latency (ie sit in a loop waiting for | ||
80 | * somebody to say that they'd like to reschedule) | ||
81 | */ | ||
82 | void cpu_idle(void) | ||
83 | { | ||
84 | idle(); | ||
85 | } | ||
86 | |||
87 | void machine_restart(char * __unused) | ||
88 | { | ||
89 | local_irq_disable(); | ||
90 | __asm__("jmp @@0"); | ||
91 | } | ||
92 | |||
93 | EXPORT_SYMBOL(machine_restart); | ||
94 | |||
95 | void machine_halt(void) | ||
96 | { | ||
97 | local_irq_disable(); | ||
98 | __asm__("sleep"); | ||
99 | for (;;); | ||
100 | } | ||
101 | |||
102 | EXPORT_SYMBOL(machine_halt); | ||
103 | |||
104 | void machine_power_off(void) | ||
105 | { | ||
106 | local_irq_disable(); | ||
107 | __asm__("sleep"); | ||
108 | for (;;); | ||
109 | } | ||
110 | |||
111 | EXPORT_SYMBOL(machine_power_off); | ||
112 | |||
113 | void show_regs(struct pt_regs * regs) | ||
114 | { | ||
115 | printk("\nPC: %08lx Status: %02x", | ||
116 | regs->pc, regs->ccr); | ||
117 | printk("\nORIG_ER0: %08lx ER0: %08lx ER1: %08lx", | ||
118 | regs->orig_er0, regs->er0, regs->er1); | ||
119 | printk("\nER2: %08lx ER3: %08lx ER4: %08lx ER5: %08lx", | ||
120 | regs->er2, regs->er3, regs->er4, regs->er5); | ||
121 | printk("\nER6' %08lx ",regs->er6); | ||
122 | if (user_mode(regs)) | ||
123 | printk("USP: %08lx\n", rdusp()); | ||
124 | else | ||
125 | printk("\n"); | ||
126 | } | ||
127 | |||
128 | /* | ||
129 | * Create a kernel thread | ||
130 | */ | ||
131 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | ||
132 | { | ||
133 | long retval; | ||
134 | long clone_arg; | ||
135 | mm_segment_t fs; | ||
136 | |||
137 | fs = get_fs(); | ||
138 | set_fs (KERNEL_DS); | ||
139 | clone_arg = flags | CLONE_VM; | ||
140 | __asm__("mov.l sp,er3\n\t" | ||
141 | "sub.l er2,er2\n\t" | ||
142 | "mov.l %2,er1\n\t" | ||
143 | "mov.l %1,er0\n\t" | ||
144 | "trapa #0\n\t" | ||
145 | "cmp.l sp,er3\n\t" | ||
146 | "beq 1f\n\t" | ||
147 | "mov.l %4,er0\n\t" | ||
148 | "mov.l %3,er1\n\t" | ||
149 | "jsr @er1\n\t" | ||
150 | "mov.l %5,er0\n\t" | ||
151 | "trapa #0\n" | ||
152 | "1:\n\t" | ||
153 | "mov.l er0,%0" | ||
154 | :"=r"(retval) | ||
155 | :"i"(__NR_clone),"g"(clone_arg),"g"(fn),"g"(arg),"i"(__NR_exit) | ||
156 | :"er0","er1","er2","er3"); | ||
157 | set_fs (fs); | ||
158 | return retval; | ||
159 | } | ||
160 | |||
161 | void flush_thread(void) | ||
162 | { | ||
163 | } | ||
164 | |||
165 | /* | ||
166 | * "h8300_fork()".. By the time we get here, the | ||
167 | * non-volatile registers have also been saved on the | ||
168 | * stack. We do some ugly pointer stuff here.. (see | ||
169 | * also copy_thread) | ||
170 | */ | ||
171 | |||
172 | asmlinkage int h8300_fork(struct pt_regs *regs) | ||
173 | { | ||
174 | return -EINVAL; | ||
175 | } | ||
176 | |||
177 | asmlinkage int h8300_vfork(struct pt_regs *regs) | ||
178 | { | ||
179 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL); | ||
180 | } | ||
181 | |||
182 | asmlinkage int h8300_clone(struct pt_regs *regs) | ||
183 | { | ||
184 | unsigned long clone_flags; | ||
185 | unsigned long newsp; | ||
186 | |||
187 | /* syscall2 puts clone_flags in er1 and usp in er2 */ | ||
188 | clone_flags = regs->er1; | ||
189 | newsp = regs->er2; | ||
190 | if (!newsp) | ||
191 | newsp = rdusp(); | ||
192 | return do_fork(clone_flags, newsp, regs, 0, NULL, NULL); | ||
193 | |||
194 | } | ||
195 | |||
196 | int copy_thread(int nr, unsigned long clone_flags, | ||
197 | unsigned long usp, unsigned long topstk, | ||
198 | struct task_struct * p, struct pt_regs * regs) | ||
199 | { | ||
200 | struct pt_regs * childregs; | ||
201 | |||
202 | childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1; | ||
203 | |||
204 | *childregs = *regs; | ||
205 | childregs->retpc = (unsigned long) ret_from_fork; | ||
206 | childregs->er0 = 0; | ||
207 | |||
208 | p->thread.usp = usp; | ||
209 | p->thread.ksp = (unsigned long)childregs; | ||
210 | |||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | /* | ||
215 | * fill in the user structure for a core dump.. | ||
216 | */ | ||
217 | void dump_thread(struct pt_regs * regs, struct user * dump) | ||
218 | { | ||
219 | /* changed the size calculations - should hopefully work better. lbt */ | ||
220 | dump->magic = CMAGIC; | ||
221 | dump->start_code = 0; | ||
222 | dump->start_stack = rdusp() & ~(PAGE_SIZE - 1); | ||
223 | dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT; | ||
224 | dump->u_dsize = ((unsigned long) (current->mm->brk + | ||
225 | (PAGE_SIZE-1))) >> PAGE_SHIFT; | ||
226 | dump->u_dsize -= dump->u_tsize; | ||
227 | dump->u_ssize = 0; | ||
228 | |||
229 | dump->u_ar0 = (struct user_regs_struct *)(((int)(&dump->regs)) -((int)(dump))); | ||
230 | dump->regs.er0 = regs->er0; | ||
231 | dump->regs.er1 = regs->er1; | ||
232 | dump->regs.er2 = regs->er2; | ||
233 | dump->regs.er3 = regs->er3; | ||
234 | dump->regs.er4 = regs->er4; | ||
235 | dump->regs.er5 = regs->er5; | ||
236 | dump->regs.er6 = regs->er6; | ||
237 | dump->regs.orig_er0 = regs->orig_er0; | ||
238 | dump->regs.ccr = regs->ccr; | ||
239 | dump->regs.pc = regs->pc; | ||
240 | } | ||
241 | |||
242 | /* | ||
243 | * sys_execve() executes a new program. | ||
244 | */ | ||
245 | asmlinkage int sys_execve(char *name, char **argv, char **envp,int dummy,...) | ||
246 | { | ||
247 | int error; | ||
248 | char * filename; | ||
249 | struct pt_regs *regs = (struct pt_regs *) ((unsigned char *)&dummy-4); | ||
250 | |||
251 | lock_kernel(); | ||
252 | filename = getname(name); | ||
253 | error = PTR_ERR(filename); | ||
254 | if (IS_ERR(filename)) | ||
255 | goto out; | ||
256 | error = do_execve(filename, argv, envp, regs); | ||
257 | putname(filename); | ||
258 | out: | ||
259 | unlock_kernel(); | ||
260 | return error; | ||
261 | } | ||
262 | |||
263 | unsigned long thread_saved_pc(struct task_struct *tsk) | ||
264 | { | ||
265 | return ((struct pt_regs *)tsk->thread.esp0)->pc; | ||
266 | } | ||
267 | |||
268 | unsigned long get_wchan(struct task_struct *p) | ||
269 | { | ||
270 | unsigned long fp, pc; | ||
271 | unsigned long stack_page; | ||
272 | int count = 0; | ||
273 | if (!p || p == current || p->state == TASK_RUNNING) | ||
274 | return 0; | ||
275 | |||
276 | stack_page = (unsigned long)p; | ||
277 | fp = ((struct pt_regs *)p->thread.ksp)->er6; | ||
278 | do { | ||
279 | if (fp < stack_page+sizeof(struct thread_info) || | ||
280 | fp >= 8184+stack_page) | ||
281 | return 0; | ||
282 | pc = ((unsigned long *)fp)[1]; | ||
283 | if (!in_sched_functions(pc)) | ||
284 | return pc; | ||
285 | fp = *(unsigned long *) fp; | ||
286 | } while (count++ < 16); | ||
287 | return 0; | ||
288 | } | ||
diff --git a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c new file mode 100644 index 000000000000..5f19d774a288 --- /dev/null +++ b/arch/h8300/kernel/ptrace.c | |||
@@ -0,0 +1,277 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/kernel/ptrace.c | ||
3 | * | ||
4 | * Yoshinori Sato <ysato@users.sourceforge.jp> | ||
5 | * | ||
6 | * Based on: | ||
7 | * linux/arch/m68k/kernel/ptrace.c | ||
8 | * | ||
9 | * Copyright (C) 1994 by Hamish Macdonald | ||
10 | * Taken from linux/kernel/ptrace.c and modified for M680x0. | ||
11 | * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds | ||
12 | * | ||
13 | * This file is subject to the terms and conditions of the GNU General | ||
14 | * Public License. See the file COPYING in the main directory of | ||
15 | * this archive for more details. | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/mm.h> | ||
21 | #include <linux/smp.h> | ||
22 | #include <linux/smp_lock.h> | ||
23 | #include <linux/errno.h> | ||
24 | #include <linux/ptrace.h> | ||
25 | #include <linux/user.h> | ||
26 | #include <linux/config.h> | ||
27 | |||
28 | #include <asm/uaccess.h> | ||
29 | #include <asm/page.h> | ||
30 | #include <asm/pgtable.h> | ||
31 | #include <asm/system.h> | ||
32 | #include <asm/processor.h> | ||
33 | #include <asm/signal.h> | ||
34 | |||
35 | /* cpu depend functions */ | ||
36 | extern long h8300_get_reg(struct task_struct *task, int regno); | ||
37 | extern int h8300_put_reg(struct task_struct *task, int regno, unsigned long data); | ||
38 | extern void h8300_disable_trace(struct task_struct *child); | ||
39 | extern void h8300_enable_trace(struct task_struct *child); | ||
40 | |||
41 | /* | ||
42 | * does not yet catch signals sent when the child dies. | ||
43 | * in exit.c or in signal.c. | ||
44 | */ | ||
45 | |||
46 | inline | ||
47 | static int read_long(struct task_struct * tsk, unsigned long addr, | ||
48 | unsigned long * result) | ||
49 | { | ||
50 | *result = *(unsigned long *)addr; | ||
51 | return 0; | ||
52 | } | ||
53 | |||
54 | void ptrace_disable(struct task_struct *child) | ||
55 | { | ||
56 | h8300_disable_trace(child); | ||
57 | } | ||
58 | |||
59 | asmlinkage int sys_ptrace(long request, long pid, long addr, long data) | ||
60 | { | ||
61 | struct task_struct *child; | ||
62 | int ret; | ||
63 | |||
64 | lock_kernel(); | ||
65 | ret = -EPERM; | ||
66 | if (request == PTRACE_TRACEME) { | ||
67 | /* are we already being traced? */ | ||
68 | if (current->ptrace & PT_PTRACED) | ||
69 | goto out; | ||
70 | /* set the ptrace bit in the process flags. */ | ||
71 | current->ptrace |= PT_PTRACED; | ||
72 | ret = 0; | ||
73 | goto out; | ||
74 | } | ||
75 | ret = -ESRCH; | ||
76 | read_lock(&tasklist_lock); | ||
77 | child = find_task_by_pid(pid); | ||
78 | if (child) | ||
79 | get_task_struct(child); | ||
80 | read_unlock(&tasklist_lock); | ||
81 | if (!child) | ||
82 | goto out; | ||
83 | |||
84 | ret = -EPERM; | ||
85 | if (pid == 1) /* you may not mess with init */ | ||
86 | goto out_tsk; | ||
87 | |||
88 | if (request == PTRACE_ATTACH) { | ||
89 | ret = ptrace_attach(child); | ||
90 | goto out_tsk; | ||
91 | } | ||
92 | ret = ptrace_check_attach(child, request == PTRACE_KILL); | ||
93 | if (ret < 0) | ||
94 | goto out_tsk; | ||
95 | |||
96 | switch (request) { | ||
97 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | ||
98 | case PTRACE_PEEKDATA: { | ||
99 | unsigned long tmp; | ||
100 | |||
101 | ret = read_long(child, addr, &tmp); | ||
102 | if (ret < 0) | ||
103 | break ; | ||
104 | ret = put_user(tmp, (unsigned long *) data); | ||
105 | break ; | ||
106 | } | ||
107 | |||
108 | /* read the word at location addr in the USER area. */ | ||
109 | case PTRACE_PEEKUSR: { | ||
110 | unsigned long tmp = 0; | ||
111 | |||
112 | if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) { | ||
113 | ret = -EIO; | ||
114 | break ; | ||
115 | } | ||
116 | |||
117 | ret = 0; /* Default return condition */ | ||
118 | addr = addr >> 2; /* temporary hack. */ | ||
119 | |||
120 | if (addr < H8300_REGS_NO) | ||
121 | tmp = h8300_get_reg(child, addr); | ||
122 | else { | ||
123 | switch(addr) { | ||
124 | case 49: | ||
125 | tmp = child->mm->start_code; | ||
126 | break ; | ||
127 | case 50: | ||
128 | tmp = child->mm->start_data; | ||
129 | break ; | ||
130 | case 51: | ||
131 | tmp = child->mm->end_code; | ||
132 | break ; | ||
133 | case 52: | ||
134 | tmp = child->mm->end_data; | ||
135 | break ; | ||
136 | default: | ||
137 | ret = -EIO; | ||
138 | } | ||
139 | } | ||
140 | if (!ret) | ||
141 | ret = put_user(tmp,(unsigned long *) data); | ||
142 | break ; | ||
143 | } | ||
144 | |||
145 | /* when I and D space are separate, this will have to be fixed. */ | ||
146 | case PTRACE_POKETEXT: /* write the word at location addr. */ | ||
147 | case PTRACE_POKEDATA: | ||
148 | ret = 0; | ||
149 | if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) | ||
150 | break; | ||
151 | ret = -EIO; | ||
152 | break; | ||
153 | |||
154 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ | ||
155 | if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) { | ||
156 | ret = -EIO; | ||
157 | break ; | ||
158 | } | ||
159 | addr = addr >> 2; /* temporary hack. */ | ||
160 | |||
161 | if (addr == PT_ORIG_ER0) { | ||
162 | ret = -EIO; | ||
163 | break ; | ||
164 | } | ||
165 | if (addr < H8300_REGS_NO) { | ||
166 | ret = h8300_put_reg(child, addr, data); | ||
167 | break ; | ||
168 | } | ||
169 | ret = -EIO; | ||
170 | break ; | ||
171 | case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ | ||
172 | case PTRACE_CONT: { /* restart after signal. */ | ||
173 | ret = -EIO; | ||
174 | if ((unsigned long) data >= _NSIG) | ||
175 | break ; | ||
176 | if (request == PTRACE_SYSCALL) | ||
177 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
178 | else | ||
179 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
180 | child->exit_code = data; | ||
181 | wake_up_process(child); | ||
182 | /* make sure the single step bit is not set. */ | ||
183 | h8300_disable_trace(child); | ||
184 | ret = 0; | ||
185 | } | ||
186 | |||
187 | /* | ||
188 | * make the child exit. Best I can do is send it a sigkill. | ||
189 | * perhaps it should be put in the status that it wants to | ||
190 | * exit. | ||
191 | */ | ||
192 | case PTRACE_KILL: { | ||
193 | |||
194 | ret = 0; | ||
195 | if (child->exit_state == EXIT_ZOMBIE) /* already dead */ | ||
196 | break; | ||
197 | child->exit_code = SIGKILL; | ||
198 | h8300_disable_trace(child); | ||
199 | wake_up_process(child); | ||
200 | break; | ||
201 | } | ||
202 | |||
203 | case PTRACE_SINGLESTEP: { /* set the trap flag. */ | ||
204 | ret = -EIO; | ||
205 | if ((unsigned long) data > _NSIG) | ||
206 | break; | ||
207 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
208 | child->exit_code = data; | ||
209 | h8300_enable_trace(child); | ||
210 | wake_up_process(child); | ||
211 | ret = 0; | ||
212 | break; | ||
213 | } | ||
214 | |||
215 | case PTRACE_DETACH: /* detach a process that was attached. */ | ||
216 | ret = ptrace_detach(child, data); | ||
217 | break; | ||
218 | |||
219 | case PTRACE_GETREGS: { /* Get all gp regs from the child. */ | ||
220 | int i; | ||
221 | unsigned long tmp; | ||
222 | for (i = 0; i < H8300_REGS_NO; i++) { | ||
223 | tmp = h8300_get_reg(child, i); | ||
224 | if (put_user(tmp, (unsigned long *) data)) { | ||
225 | ret = -EFAULT; | ||
226 | break; | ||
227 | } | ||
228 | data += sizeof(long); | ||
229 | } | ||
230 | ret = 0; | ||
231 | break; | ||
232 | } | ||
233 | |||
234 | case PTRACE_SETREGS: { /* Set all gp regs in the child. */ | ||
235 | int i; | ||
236 | unsigned long tmp; | ||
237 | for (i = 0; i < H8300_REGS_NO; i++) { | ||
238 | if (get_user(tmp, (unsigned long *) data)) { | ||
239 | ret = -EFAULT; | ||
240 | break; | ||
241 | } | ||
242 | h8300_put_reg(child, i, tmp); | ||
243 | data += sizeof(long); | ||
244 | } | ||
245 | ret = 0; | ||
246 | break; | ||
247 | } | ||
248 | |||
249 | default: | ||
250 | ret = -EIO; | ||
251 | break; | ||
252 | } | ||
253 | out_tsk: | ||
254 | put_task_struct(child); | ||
255 | out: | ||
256 | unlock_kernel(); | ||
257 | return ret; | ||
258 | } | ||
259 | |||
260 | asmlinkage void syscall_trace(void) | ||
261 | { | ||
262 | if (!test_thread_flag(TIF_SYSCALL_TRACE)) | ||
263 | return; | ||
264 | if (!(current->ptrace & PT_PTRACED)) | ||
265 | return; | ||
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 | } | ||
diff --git a/arch/h8300/kernel/semaphore.c b/arch/h8300/kernel/semaphore.c new file mode 100644 index 000000000000..1ebb79baaa8c --- /dev/null +++ b/arch/h8300/kernel/semaphore.c | |||
@@ -0,0 +1,133 @@ | |||
1 | /* | ||
2 | * Generic semaphore code. Buyer beware. Do your own | ||
3 | * specific changes in <asm/semaphore-helper.h> | ||
4 | */ | ||
5 | |||
6 | #include <linux/config.h> | ||
7 | #include <linux/sched.h> | ||
8 | #include <linux/init.h> | ||
9 | #include <asm/semaphore-helper.h> | ||
10 | |||
11 | #ifndef CONFIG_RMW_INSNS | ||
12 | spinlock_t semaphore_wake_lock; | ||
13 | #endif | ||
14 | |||
15 | /* | ||
16 | * Semaphores are implemented using a two-way counter: | ||
17 | * The "count" variable is decremented for each process | ||
18 | * that tries to sleep, while the "waking" variable is | ||
19 | * incremented when the "up()" code goes to wake up waiting | ||
20 | * processes. | ||
21 | * | ||
22 | * Notably, the inline "up()" and "down()" functions can | ||
23 | * efficiently test if they need to do any extra work (up | ||
24 | * needs to do something only if count was negative before | ||
25 | * the increment operation. | ||
26 | * | ||
27 | * waking_non_zero() (from asm/semaphore.h) must execute | ||
28 | * atomically. | ||
29 | * | ||
30 | * When __up() is called, the count was negative before | ||
31 | * incrementing it, and we need to wake up somebody. | ||
32 | * | ||
33 | * This routine adds one to the count of processes that need to | ||
34 | * wake up and exit. ALL waiting processes actually wake up but | ||
35 | * only the one that gets to the "waking" field first will gate | ||
36 | * through and acquire the semaphore. The others will go back | ||
37 | * to sleep. | ||
38 | * | ||
39 | * Note that these functions are only called when there is | ||
40 | * contention on the lock, and as such all this is the | ||
41 | * "non-critical" part of the whole semaphore business. The | ||
42 | * critical part is the inline stuff in <asm/semaphore.h> | ||
43 | * where we want to avoid any extra jumps and calls. | ||
44 | */ | ||
45 | void __up(struct semaphore *sem) | ||
46 | { | ||
47 | wake_one_more(sem); | ||
48 | wake_up(&sem->wait); | ||
49 | } | ||
50 | |||
51 | /* | ||
52 | * Perform the "down" function. Return zero for semaphore acquired, | ||
53 | * return negative for signalled out of the function. | ||
54 | * | ||
55 | * If called from __down, the return is ignored and the wait loop is | ||
56 | * not interruptible. This means that a task waiting on a semaphore | ||
57 | * using "down()" cannot be killed until someone does an "up()" on | ||
58 | * the semaphore. | ||
59 | * | ||
60 | * If called from __down_interruptible, the return value gets checked | ||
61 | * upon return. If the return value is negative then the task continues | ||
62 | * with the negative value in the return register (it can be tested by | ||
63 | * the caller). | ||
64 | * | ||
65 | * Either form may be used in conjunction with "up()". | ||
66 | * | ||
67 | */ | ||
68 | |||
69 | |||
70 | #define DOWN_HEAD(task_state) \ | ||
71 | \ | ||
72 | \ | ||
73 | current->state = (task_state); \ | ||
74 | add_wait_queue(&sem->wait, &wait); \ | ||
75 | \ | ||
76 | /* \ | ||
77 | * Ok, we're set up. sem->count is known to be less than zero \ | ||
78 | * so we must wait. \ | ||
79 | * \ | ||
80 | * We can let go the lock for purposes of waiting. \ | ||
81 | * We re-acquire it after awaking so as to protect \ | ||
82 | * all semaphore operations. \ | ||
83 | * \ | ||
84 | * If "up()" is called before we call waking_non_zero() then \ | ||
85 | * we will catch it right away. If it is called later then \ | ||
86 | * we will have to go through a wakeup cycle to catch it. \ | ||
87 | * \ | ||
88 | * Multiple waiters contend for the semaphore lock to see \ | ||
89 | * who gets to gate through and who has to wait some more. \ | ||
90 | */ \ | ||
91 | for (;;) { | ||
92 | |||
93 | #define DOWN_TAIL(task_state) \ | ||
94 | current->state = (task_state); \ | ||
95 | } \ | ||
96 | current->state = TASK_RUNNING; \ | ||
97 | remove_wait_queue(&sem->wait, &wait); | ||
98 | |||
99 | void __sched __down(struct semaphore * sem) | ||
100 | { | ||
101 | DECLARE_WAITQUEUE(wait, current); | ||
102 | |||
103 | DOWN_HEAD(TASK_UNINTERRUPTIBLE) | ||
104 | if (waking_non_zero(sem)) | ||
105 | break; | ||
106 | schedule(); | ||
107 | DOWN_TAIL(TASK_UNINTERRUPTIBLE) | ||
108 | } | ||
109 | |||
110 | int __sched __down_interruptible(struct semaphore * sem) | ||
111 | { | ||
112 | DECLARE_WAITQUEUE(wait, current); | ||
113 | int ret = 0; | ||
114 | |||
115 | DOWN_HEAD(TASK_INTERRUPTIBLE) | ||
116 | |||
117 | ret = waking_non_zero_interruptible(sem, current); | ||
118 | if (ret) | ||
119 | { | ||
120 | if (ret == 1) | ||
121 | /* ret != 0 only if we get interrupted -arca */ | ||
122 | ret = 0; | ||
123 | break; | ||
124 | } | ||
125 | schedule(); | ||
126 | DOWN_TAIL(TASK_INTERRUPTIBLE) | ||
127 | return ret; | ||
128 | } | ||
129 | |||
130 | int __down_trylock(struct semaphore * sem) | ||
131 | { | ||
132 | return waking_non_zero_trylock(sem); | ||
133 | } | ||
diff --git a/arch/h8300/kernel/setup.c b/arch/h8300/kernel/setup.c new file mode 100644 index 000000000000..f469d9160730 --- /dev/null +++ b/arch/h8300/kernel/setup.c | |||
@@ -0,0 +1,248 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/kernel/setup.c | ||
3 | * | ||
4 | * Copyleft ()) 2000 James D. Schettine {james@telos-systems.com} | ||
5 | * Copyright (C) 1999,2000 Greg Ungerer (gerg@snapgear.com) | ||
6 | * Copyright (C) 1998,1999 D. Jeff Dionne <jeff@lineo.ca> | ||
7 | * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com> | ||
8 | * Copyright (C) 1995 Hamish Macdonald | ||
9 | * Copyright (C) 2000 Lineo Inc. (www.lineo.com) | ||
10 | * Copyright (C) 2001 Lineo, Inc. <www.lineo.com> | ||
11 | * | ||
12 | * H8/300 porting Yoshinori Sato <ysato@users.sourceforge.jp> | ||
13 | */ | ||
14 | |||
15 | /* | ||
16 | * This file handles the architecture-dependent parts of system setup | ||
17 | */ | ||
18 | |||
19 | #include <linux/config.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/sched.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/fs.h> | ||
25 | #include <linux/fb.h> | ||
26 | #include <linux/console.h> | ||
27 | #include <linux/genhd.h> | ||
28 | #include <linux/errno.h> | ||
29 | #include <linux/string.h> | ||
30 | #include <linux/major.h> | ||
31 | #include <linux/bootmem.h> | ||
32 | #include <linux/seq_file.h> | ||
33 | #include <linux/init.h> | ||
34 | |||
35 | #include <asm/setup.h> | ||
36 | #include <asm/irq.h> | ||
37 | |||
38 | #ifdef CONFIG_BLK_DEV_INITRD | ||
39 | #include <asm/pgtable.h> | ||
40 | #endif | ||
41 | |||
42 | #if defined(__H8300H__) | ||
43 | #define CPU "H8/300H" | ||
44 | #include <asm/regs306x.h> | ||
45 | #endif | ||
46 | |||
47 | #if defined(__H8300S__) | ||
48 | #define CPU "H8S" | ||
49 | #include <asm/regs267x.h> | ||
50 | #endif | ||
51 | |||
52 | #define STUBSIZE 0xc000; | ||
53 | |||
54 | unsigned long rom_length; | ||
55 | unsigned long memory_start; | ||
56 | unsigned long memory_end; | ||
57 | |||
58 | char command_line[COMMAND_LINE_SIZE]; | ||
59 | |||
60 | extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end; | ||
61 | extern int _ramstart, _ramend; | ||
62 | extern char _target_name[]; | ||
63 | extern void h8300_gpio_init(void); | ||
64 | |||
65 | #if (defined(CONFIG_H8300H_SIM) || defined(CONFIG_H8S_SIM)) \ | ||
66 | && defined(CONFIG_GDB_MAGICPRINT) | ||
67 | /* printk with gdb service */ | ||
68 | static void gdb_console_output(struct console *c, const char *msg, unsigned len) | ||
69 | { | ||
70 | for (; len > 0; len--) { | ||
71 | asm("mov.w %0,r2\n\t" | ||
72 | "jsr @0xc4"::"r"(*msg++):"er2"); | ||
73 | } | ||
74 | } | ||
75 | |||
76 | /* | ||
77 | * Setup initial baud/bits/parity. We do two things here: | ||
78 | * - construct a cflag setting for the first rs_open() | ||
79 | * - initialize the serial port | ||
80 | * Return non-zero if we didn't find a serial port. | ||
81 | */ | ||
82 | static int __init gdb_console_setup(struct console *co, char *options) | ||
83 | { | ||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static const struct console gdb_console = { | ||
88 | .name = "gdb_con", | ||
89 | .write = gdb_console_output, | ||
90 | .device = NULL, | ||
91 | .setup = gdb_console_setup, | ||
92 | .flags = CON_PRINTBUFFER, | ||
93 | .index = -1, | ||
94 | }; | ||
95 | #endif | ||
96 | |||
97 | void __init setup_arch(char **cmdline_p) | ||
98 | { | ||
99 | int bootmap_size; | ||
100 | |||
101 | memory_start = (unsigned long) &_ramstart; | ||
102 | |||
103 | /* allow for ROMFS on the end of the kernel */ | ||
104 | if (memcmp((void *)memory_start, "-rom1fs-", 8) == 0) { | ||
105 | #if defined(CONFIG_BLK_DEV_INITRD) | ||
106 | initrd_start = memory_start; | ||
107 | initrd_end = memory_start += be32_to_cpu(((unsigned long *) (memory_start))[2]); | ||
108 | #else | ||
109 | memory_start += be32_to_cpu(((unsigned long *) memory_start)[2]); | ||
110 | #endif | ||
111 | } | ||
112 | memory_start = PAGE_ALIGN(memory_start); | ||
113 | #if !defined(CONFIG_BLKDEV_RESERVE) | ||
114 | memory_end = (unsigned long) &_ramend; /* by now the stack is part of the init task */ | ||
115 | #if defined(CONFIG_GDB_DEBUG) | ||
116 | memory_end -= STUBSIZE; | ||
117 | #endif | ||
118 | #else | ||
119 | if ((memory_end < CONFIG_BLKDEV_RESERVE_ADDRESS) && | ||
120 | (memory_end > CONFIG_BLKDEV_RESERVE_ADDRESS) | ||
121 | /* overlap userarea */ | ||
122 | memory_end = CONFIG_BLKDEV_RESERVE_ADDRESS; | ||
123 | #endif | ||
124 | |||
125 | init_mm.start_code = (unsigned long) &_stext; | ||
126 | init_mm.end_code = (unsigned long) &_etext; | ||
127 | init_mm.end_data = (unsigned long) &_edata; | ||
128 | init_mm.brk = (unsigned long) 0; | ||
129 | |||
130 | #if (defined(CONFIG_H8300H_SIM) || defined(CONFIG_H8S_SIM)) && defined(CONFIG_GDB_MAGICPRINT) | ||
131 | register_console((struct console *)&gdb_console); | ||
132 | #endif | ||
133 | |||
134 | printk(KERN_INFO "\r\n\nuClinux " CPU "\n"); | ||
135 | printk(KERN_INFO "Target Hardware: %s\n",_target_name); | ||
136 | printk(KERN_INFO "Flat model support (C) 1998,1999 Kenneth Albanowski, D. Jeff Dionne\n"); | ||
137 | printk(KERN_INFO "H8/300 series support by Yoshinori Sato <ysato@users.sourceforge.jp>\n"); | ||
138 | |||
139 | #ifdef DEBUG | ||
140 | printk(KERN_DEBUG "KERNEL -> TEXT=0x%06x-0x%06x DATA=0x%06x-0x%06x " | ||
141 | "BSS=0x%06x-0x%06x\n", (int) &_stext, (int) &_etext, | ||
142 | (int) &_sdata, (int) &_edata, | ||
143 | (int) &_sbss, (int) &_ebss); | ||
144 | printk(KERN_DEBUG "KERNEL -> ROMFS=0x%06x-0x%06x MEM=0x%06x-0x%06x " | ||
145 | "STACK=0x%06x-0x%06x\n", | ||
146 | (int) &_ebss, (int) memory_start, | ||
147 | (int) memory_start, (int) memory_end, | ||
148 | (int) memory_end, (int) &_ramend); | ||
149 | #endif | ||
150 | |||
151 | #ifdef CONFIG_DEFAULT_CMDLINE | ||
152 | /* set from default command line */ | ||
153 | if (*command_line == '\0') | ||
154 | strcpy(command_line,CONFIG_KERNEL_COMMAND); | ||
155 | #endif | ||
156 | /* Keep a copy of command line */ | ||
157 | *cmdline_p = &command_line[0]; | ||
158 | memcpy(saved_command_line, command_line, COMMAND_LINE_SIZE); | ||
159 | saved_command_line[COMMAND_LINE_SIZE-1] = 0; | ||
160 | |||
161 | #ifdef DEBUG | ||
162 | if (strlen(*cmdline_p)) | ||
163 | printk(KERN_DEBUG "Command line: '%s'\n", *cmdline_p); | ||
164 | #endif | ||
165 | |||
166 | /* | ||
167 | * give all the memory to the bootmap allocator, tell it to put the | ||
168 | * boot mem_map at the start of memory | ||
169 | */ | ||
170 | bootmap_size = init_bootmem_node( | ||
171 | NODE_DATA(0), | ||
172 | memory_start >> PAGE_SHIFT, /* map goes here */ | ||
173 | PAGE_OFFSET >> PAGE_SHIFT, /* 0 on coldfire */ | ||
174 | memory_end >> PAGE_SHIFT); | ||
175 | /* | ||
176 | * free the usable memory, we have to make sure we do not free | ||
177 | * the bootmem bitmap so we then reserve it after freeing it :-) | ||
178 | */ | ||
179 | free_bootmem(memory_start, memory_end - memory_start); | ||
180 | reserve_bootmem(memory_start, bootmap_size); | ||
181 | /* | ||
182 | * get kmalloc into gear | ||
183 | */ | ||
184 | paging_init(); | ||
185 | h8300_gpio_init(); | ||
186 | #if defined(CONFIG_H8300_AKI3068NET) && defined(CONFIG_IDE) | ||
187 | { | ||
188 | #define AREABIT(addr) (1 << (((addr) >> 21) & 7)) | ||
189 | /* setup BSC */ | ||
190 | volatile unsigned char *abwcr = (volatile unsigned char *)ABWCR; | ||
191 | volatile unsigned char *cscr = (volatile unsigned char *)CSCR; | ||
192 | *abwcr &= ~(AREABIT(CONFIG_H8300_IDE_BASE) | AREABIT(CONFIG_H8300_IDE_ALT)); | ||
193 | *cscr |= (AREABIT(CONFIG_H8300_IDE_BASE) | AREABIT(CONFIG_H8300_IDE_ALT)) | 0x0f; | ||
194 | } | ||
195 | #endif | ||
196 | #ifdef DEBUG | ||
197 | printk(KERN_DEBUG "Done setup_arch\n"); | ||
198 | #endif | ||
199 | } | ||
200 | |||
201 | /* | ||
202 | * Get CPU information for use by the procfs. | ||
203 | */ | ||
204 | |||
205 | static int show_cpuinfo(struct seq_file *m, void *v) | ||
206 | { | ||
207 | char *cpu; | ||
208 | int mode; | ||
209 | u_long clockfreq; | ||
210 | |||
211 | cpu = CPU; | ||
212 | mode = *(volatile unsigned char *)MDCR & 0x07; | ||
213 | |||
214 | clockfreq = CONFIG_CPU_CLOCK; | ||
215 | |||
216 | seq_printf(m, "CPU:\t\t%s (mode:%d)\n" | ||
217 | "Clock:\t\t%lu.%1luMHz\n" | ||
218 | "BogoMips:\t%lu.%02lu\n" | ||
219 | "Calibration:\t%lu loops\n", | ||
220 | cpu,mode, | ||
221 | clockfreq/1000,clockfreq%1000, | ||
222 | (loops_per_jiffy*HZ)/500000,((loops_per_jiffy*HZ)/5000)%100, | ||
223 | (loops_per_jiffy*HZ)); | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | static void *c_start(struct seq_file *m, loff_t *pos) | ||
229 | { | ||
230 | return *pos < NR_CPUS ? ((void *) 0x12345678) : NULL; | ||
231 | } | ||
232 | |||
233 | static void *c_next(struct seq_file *m, void *v, loff_t *pos) | ||
234 | { | ||
235 | ++*pos; | ||
236 | return c_start(m, pos); | ||
237 | } | ||
238 | |||
239 | static void c_stop(struct seq_file *m, void *v) | ||
240 | { | ||
241 | } | ||
242 | |||
243 | struct seq_operations cpuinfo_op = { | ||
244 | .start = c_start, | ||
245 | .next = c_next, | ||
246 | .stop = c_stop, | ||
247 | .show = show_cpuinfo, | ||
248 | }; | ||
diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c new file mode 100644 index 000000000000..a4799d633ef4 --- /dev/null +++ b/arch/h8300/kernel/signal.c | |||
@@ -0,0 +1,552 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/kernel/signal.c | ||
3 | * | ||
4 | * Copyright (C) 1991, 1992 Linus Torvalds | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of the GNU General Public | ||
7 | * License. See the file COPYING in the main directory of this archive | ||
8 | * for more details. | ||
9 | */ | ||
10 | |||
11 | /* | ||
12 | * uClinux H8/300 support by Yoshinori Sato <ysato@users.sourceforge.jp> | ||
13 | * and David McCullough <davidm@snapgear.com> | ||
14 | * | ||
15 | * Based on | ||
16 | * Linux/m68k by Hamish Macdonald | ||
17 | */ | ||
18 | |||
19 | /* | ||
20 | * ++roman (07/09/96): implemented signal stacks (specially for tosemu on | ||
21 | * Atari :-) Current limitation: Only one sigstack can be active at one time. | ||
22 | * If a second signal with SA_ONSTACK set arrives while working on a sigstack, | ||
23 | * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested | ||
24 | * signal handlers! | ||
25 | */ | ||
26 | |||
27 | #include <linux/sched.h> | ||
28 | #include <linux/mm.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/signal.h> | ||
31 | #include <linux/syscalls.h> | ||
32 | #include <linux/errno.h> | ||
33 | #include <linux/wait.h> | ||
34 | #include <linux/ptrace.h> | ||
35 | #include <linux/unistd.h> | ||
36 | #include <linux/stddef.h> | ||
37 | #include <linux/highuid.h> | ||
38 | #include <linux/personality.h> | ||
39 | #include <linux/tty.h> | ||
40 | #include <linux/binfmts.h> | ||
41 | #include <linux/suspend.h> | ||
42 | |||
43 | #include <asm/setup.h> | ||
44 | #include <asm/uaccess.h> | ||
45 | #include <asm/pgtable.h> | ||
46 | #include <asm/traps.h> | ||
47 | #include <asm/ucontext.h> | ||
48 | |||
49 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | ||
50 | |||
51 | asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset); | ||
52 | |||
53 | /* | ||
54 | * Atomically swap in the new signal mask, and wait for a signal. | ||
55 | */ | ||
56 | asmlinkage int do_sigsuspend(struct pt_regs *regs) | ||
57 | { | ||
58 | old_sigset_t mask = regs->er3; | ||
59 | sigset_t saveset; | ||
60 | |||
61 | mask &= _BLOCKABLE; | ||
62 | spin_lock_irq(¤t->sighand->siglock); | ||
63 | saveset = current->blocked; | ||
64 | siginitset(¤t->blocked, mask); | ||
65 | recalc_sigpending(); | ||
66 | spin_unlock_irq(¤t->sighand->siglock); | ||
67 | |||
68 | regs->er0 = -EINTR; | ||
69 | while (1) { | ||
70 | current->state = TASK_INTERRUPTIBLE; | ||
71 | schedule(); | ||
72 | if (do_signal(regs, &saveset)) | ||
73 | return -EINTR; | ||
74 | } | ||
75 | } | ||
76 | |||
77 | asmlinkage int | ||
78 | do_rt_sigsuspend(struct pt_regs *regs) | ||
79 | { | ||
80 | sigset_t *unewset = (sigset_t *)regs->er1; | ||
81 | size_t sigsetsize = (size_t)regs->er2; | ||
82 | sigset_t saveset, newset; | ||
83 | |||
84 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
85 | if (sigsetsize != sizeof(sigset_t)) | ||
86 | return -EINVAL; | ||
87 | |||
88 | if (copy_from_user(&newset, unewset, sizeof(newset))) | ||
89 | return -EFAULT; | ||
90 | sigdelsetmask(&newset, ~_BLOCKABLE); | ||
91 | |||
92 | spin_lock_irq(¤t->sighand->siglock); | ||
93 | saveset = current->blocked; | ||
94 | current->blocked = newset; | ||
95 | recalc_sigpending(); | ||
96 | spin_unlock_irq(¤t->sighand->siglock); | ||
97 | |||
98 | regs->er0 = -EINTR; | ||
99 | while (1) { | ||
100 | current->state = TASK_INTERRUPTIBLE; | ||
101 | schedule(); | ||
102 | if (do_signal(regs, &saveset)) | ||
103 | return -EINTR; | ||
104 | } | ||
105 | } | ||
106 | |||
107 | asmlinkage int | ||
108 | sys_sigaction(int sig, const struct old_sigaction *act, | ||
109 | struct old_sigaction *oact) | ||
110 | { | ||
111 | struct k_sigaction new_ka, old_ka; | ||
112 | int ret; | ||
113 | |||
114 | if (act) { | ||
115 | old_sigset_t mask; | ||
116 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || | ||
117 | __get_user(new_ka.sa.sa_handler, &act->sa_handler) || | ||
118 | __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) | ||
119 | return -EFAULT; | ||
120 | __get_user(new_ka.sa.sa_flags, &act->sa_flags); | ||
121 | __get_user(mask, &act->sa_mask); | ||
122 | siginitset(&new_ka.sa.sa_mask, mask); | ||
123 | } | ||
124 | |||
125 | ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); | ||
126 | |||
127 | if (!ret && oact) { | ||
128 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || | ||
129 | __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || | ||
130 | __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) | ||
131 | return -EFAULT; | ||
132 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags); | ||
133 | __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); | ||
134 | } | ||
135 | |||
136 | return ret; | ||
137 | } | ||
138 | |||
139 | asmlinkage int | ||
140 | sys_sigaltstack(const stack_t *uss, stack_t *uoss) | ||
141 | { | ||
142 | return do_sigaltstack(uss, uoss, rdusp()); | ||
143 | } | ||
144 | |||
145 | |||
146 | /* | ||
147 | * Do a signal return; undo the signal stack. | ||
148 | * | ||
149 | * Keep the return code on the stack quadword aligned! | ||
150 | * That makes the cache flush below easier. | ||
151 | */ | ||
152 | |||
153 | struct sigframe | ||
154 | { | ||
155 | long dummy_er0; | ||
156 | long dummy_vector; | ||
157 | #if defined(CONFIG_CPU_H8S) | ||
158 | short dummy_exr; | ||
159 | #endif | ||
160 | long dummy_pc; | ||
161 | char *pretcode; | ||
162 | unsigned char retcode[8]; | ||
163 | unsigned long extramask[_NSIG_WORDS-1]; | ||
164 | struct sigcontext sc; | ||
165 | int sig; | ||
166 | } __attribute__((aligned(2),packed)); | ||
167 | |||
168 | struct rt_sigframe | ||
169 | { | ||
170 | long dummy_er0; | ||
171 | long dummy_vector; | ||
172 | #if defined(CONFIG_CPU_H8S) | ||
173 | short dummy_exr; | ||
174 | #endif | ||
175 | long dummy_pc; | ||
176 | char *pretcode; | ||
177 | struct siginfo *pinfo; | ||
178 | void *puc; | ||
179 | unsigned char retcode[8]; | ||
180 | struct siginfo info; | ||
181 | struct ucontext uc; | ||
182 | int sig; | ||
183 | } __attribute__((aligned(2),packed)); | ||
184 | |||
185 | static inline int | ||
186 | restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, | ||
187 | int *pd0) | ||
188 | { | ||
189 | int err = 0; | ||
190 | unsigned int ccr; | ||
191 | unsigned int usp; | ||
192 | unsigned int er0; | ||
193 | |||
194 | /* Always make any pending restarted system calls return -EINTR */ | ||
195 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | ||
196 | |||
197 | #define COPY(r) err |= __get_user(regs->r, &usc->sc_##r) /* restore passed registers */ | ||
198 | COPY(er1); | ||
199 | COPY(er2); | ||
200 | COPY(er3); | ||
201 | COPY(er5); | ||
202 | COPY(pc); | ||
203 | ccr = regs->ccr & 0x10; | ||
204 | COPY(ccr); | ||
205 | #undef COPY | ||
206 | regs->ccr &= 0xef; | ||
207 | regs->ccr |= ccr; | ||
208 | regs->orig_er0 = -1; /* disable syscall checks */ | ||
209 | err |= __get_user(usp, &usc->sc_usp); | ||
210 | wrusp(usp); | ||
211 | |||
212 | err |= __get_user(er0, &usc->sc_er0); | ||
213 | *pd0 = er0; | ||
214 | return err; | ||
215 | } | ||
216 | |||
217 | asmlinkage int do_sigreturn(unsigned long __unused,...) | ||
218 | { | ||
219 | struct pt_regs *regs = (struct pt_regs *) (&__unused - 1); | ||
220 | unsigned long usp = rdusp(); | ||
221 | struct sigframe *frame = (struct sigframe *)(usp - 4); | ||
222 | sigset_t set; | ||
223 | int er0; | ||
224 | |||
225 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | ||
226 | goto badframe; | ||
227 | if (__get_user(set.sig[0], &frame->sc.sc_mask) || | ||
228 | (_NSIG_WORDS > 1 && | ||
229 | __copy_from_user(&set.sig[1], &frame->extramask, | ||
230 | sizeof(frame->extramask)))) | ||
231 | goto badframe; | ||
232 | |||
233 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
234 | spin_lock_irq(¤t->sighand->siglock); | ||
235 | current->blocked = set; | ||
236 | recalc_sigpending(); | ||
237 | spin_unlock_irq(¤t->sighand->siglock); | ||
238 | |||
239 | if (restore_sigcontext(regs, &frame->sc, &er0)) | ||
240 | goto badframe; | ||
241 | return er0; | ||
242 | |||
243 | badframe: | ||
244 | force_sig(SIGSEGV, current); | ||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | asmlinkage int do_rt_sigreturn(unsigned long __unused,...) | ||
249 | { | ||
250 | struct pt_regs *regs = (struct pt_regs *) &__unused; | ||
251 | unsigned long usp = rdusp(); | ||
252 | struct rt_sigframe *frame = (struct rt_sigframe *)(usp - 4); | ||
253 | sigset_t set; | ||
254 | int er0; | ||
255 | |||
256 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | ||
257 | goto badframe; | ||
258 | if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) | ||
259 | goto badframe; | ||
260 | |||
261 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
262 | spin_unlock_irq(¤t->sighand->siglock); | ||
263 | current->blocked = set; | ||
264 | recalc_sigpending(); | ||
265 | spin_lock_irq(¤t->sighand->siglock); | ||
266 | |||
267 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &er0)) | ||
268 | goto badframe; | ||
269 | |||
270 | if (do_sigaltstack(&frame->uc.uc_stack, NULL, usp) == -EFAULT) | ||
271 | goto badframe; | ||
272 | |||
273 | return er0; | ||
274 | |||
275 | badframe: | ||
276 | force_sig(SIGSEGV, current); | ||
277 | return 0; | ||
278 | } | ||
279 | |||
280 | static int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, | ||
281 | unsigned long mask) | ||
282 | { | ||
283 | int err = 0; | ||
284 | |||
285 | err |= __put_user(regs->er0, &sc->sc_er0); | ||
286 | err |= __put_user(regs->er1, &sc->sc_er1); | ||
287 | err |= __put_user(regs->er2, &sc->sc_er2); | ||
288 | err |= __put_user(regs->er3, &sc->sc_er3); | ||
289 | err |= __put_user(regs->er4, &sc->sc_er4); | ||
290 | err |= __put_user(regs->er5, &sc->sc_er5); | ||
291 | err |= __put_user(regs->er6, &sc->sc_er6); | ||
292 | err |= __put_user(rdusp(), &sc->sc_usp); | ||
293 | err |= __put_user(regs->pc, &sc->sc_pc); | ||
294 | err |= __put_user(regs->ccr, &sc->sc_ccr); | ||
295 | err |= __put_user(mask, &sc->sc_mask); | ||
296 | |||
297 | return err; | ||
298 | } | ||
299 | |||
300 | static inline void * | ||
301 | get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) | ||
302 | { | ||
303 | unsigned long usp; | ||
304 | |||
305 | /* Default to using normal stack. */ | ||
306 | usp = rdusp(); | ||
307 | |||
308 | /* This is the X/Open sanctioned signal stack switching. */ | ||
309 | if (ka->sa.sa_flags & SA_ONSTACK) { | ||
310 | if (!on_sig_stack(usp)) | ||
311 | usp = current->sas_ss_sp + current->sas_ss_size; | ||
312 | } | ||
313 | return (void *)((usp - frame_size) & -8UL); | ||
314 | } | ||
315 | |||
316 | static void setup_frame (int sig, struct k_sigaction *ka, | ||
317 | sigset_t *set, struct pt_regs *regs) | ||
318 | { | ||
319 | struct sigframe *frame; | ||
320 | int err = 0; | ||
321 | int usig; | ||
322 | unsigned char *ret; | ||
323 | |||
324 | frame = get_sigframe(ka, regs, sizeof(*frame)); | ||
325 | |||
326 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | ||
327 | goto give_sigsegv; | ||
328 | |||
329 | usig = current_thread_info()->exec_domain | ||
330 | && current_thread_info()->exec_domain->signal_invmap | ||
331 | && sig < 32 | ||
332 | ? current_thread_info()->exec_domain->signal_invmap[sig] | ||
333 | : sig; | ||
334 | |||
335 | err |= __put_user(usig, &frame->sig); | ||
336 | if (err) | ||
337 | goto give_sigsegv; | ||
338 | |||
339 | err |= setup_sigcontext(&frame->sc, regs, set->sig[0]); | ||
340 | if (err) | ||
341 | goto give_sigsegv; | ||
342 | |||
343 | if (_NSIG_WORDS > 1) { | ||
344 | err |= copy_to_user(frame->extramask, &set->sig[1], | ||
345 | sizeof(frame->extramask)); | ||
346 | if (err) | ||
347 | goto give_sigsegv; | ||
348 | } | ||
349 | |||
350 | ret = frame->retcode; | ||
351 | if (ka->sa.sa_flags & SA_RESTORER) | ||
352 | ret = (unsigned char *)(ka->sa.sa_restorer); | ||
353 | else { | ||
354 | /* sub.l er0,er0; mov.b #__NR_sigreturn,r0l; trapa #0 */ | ||
355 | err != __put_user(0x1a80f800 + (__NR_sigreturn & 0xff), | ||
356 | (unsigned long *)(frame->retcode + 0)); | ||
357 | err |= __put_user(0x5700, (unsigned short *)(frame->retcode + 4)); | ||
358 | } | ||
359 | |||
360 | /* Set up to return from userspace. */ | ||
361 | err |= __put_user(ret, &frame->pretcode); | ||
362 | |||
363 | if (err) | ||
364 | goto give_sigsegv; | ||
365 | |||
366 | /* Set up registers for signal handler */ | ||
367 | wrusp ((unsigned long) frame); | ||
368 | regs->pc = (unsigned long) ka->sa.sa_handler; | ||
369 | regs->er0 = (current_thread_info()->exec_domain | ||
370 | && current_thread_info()->exec_domain->signal_invmap | ||
371 | && sig < 32 | ||
372 | ? current_thread_info()->exec_domain->signal_invmap[sig] | ||
373 | : sig); | ||
374 | regs->er1 = (unsigned long)&(frame->sc); | ||
375 | regs->er5 = current->mm->start_data; /* GOT base */ | ||
376 | |||
377 | return; | ||
378 | |||
379 | give_sigsegv: | ||
380 | force_sigsegv(sig, current); | ||
381 | } | ||
382 | |||
383 | static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, | ||
384 | sigset_t *set, struct pt_regs *regs) | ||
385 | { | ||
386 | struct rt_sigframe *frame; | ||
387 | int err = 0; | ||
388 | int usig; | ||
389 | unsigned char *ret; | ||
390 | |||
391 | frame = get_sigframe(ka, regs, sizeof(*frame)); | ||
392 | |||
393 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | ||
394 | goto give_sigsegv; | ||
395 | |||
396 | usig = current_thread_info()->exec_domain | ||
397 | && current_thread_info()->exec_domain->signal_invmap | ||
398 | && sig < 32 | ||
399 | ? current_thread_info()->exec_domain->signal_invmap[sig] | ||
400 | : sig; | ||
401 | |||
402 | err |= __put_user(usig, &frame->sig); | ||
403 | if (err) | ||
404 | goto give_sigsegv; | ||
405 | |||
406 | err |= __put_user(&frame->info, &frame->pinfo); | ||
407 | err |= __put_user(&frame->uc, &frame->puc); | ||
408 | err |= copy_siginfo_to_user(&frame->info, info); | ||
409 | if (err) | ||
410 | goto give_sigsegv; | ||
411 | |||
412 | /* Create the ucontext. */ | ||
413 | err |= __put_user(0, &frame->uc.uc_flags); | ||
414 | err |= __put_user(0, &frame->uc.uc_link); | ||
415 | err |= __put_user((void *)current->sas_ss_sp, | ||
416 | &frame->uc.uc_stack.ss_sp); | ||
417 | err |= __put_user(sas_ss_flags(rdusp()), | ||
418 | &frame->uc.uc_stack.ss_flags); | ||
419 | err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); | ||
420 | err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]); | ||
421 | err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set)); | ||
422 | if (err) | ||
423 | goto give_sigsegv; | ||
424 | |||
425 | /* Set up to return from userspace. */ | ||
426 | ret = frame->retcode; | ||
427 | if (ka->sa.sa_flags & SA_RESTORER) | ||
428 | ret = (unsigned char *)(ka->sa.sa_restorer); | ||
429 | else { | ||
430 | /* sub.l er0,er0; mov.b #__NR_sigreturn,r0l; trapa #0 */ | ||
431 | err != __put_user(0x1a80f800 + (__NR_sigreturn & 0xff), | ||
432 | (unsigned long *)(frame->retcode + 0)); | ||
433 | err |= __put_user(0x5700, (unsigned short *)(frame->retcode + 4)); | ||
434 | } | ||
435 | err |= __put_user(ret, &frame->pretcode); | ||
436 | |||
437 | if (err) | ||
438 | goto give_sigsegv; | ||
439 | |||
440 | /* Set up registers for signal handler */ | ||
441 | wrusp ((unsigned long) frame); | ||
442 | regs->pc = (unsigned long) ka->sa.sa_handler; | ||
443 | regs->er0 = (current_thread_info()->exec_domain | ||
444 | && current_thread_info()->exec_domain->signal_invmap | ||
445 | && sig < 32 | ||
446 | ? current_thread_info()->exec_domain->signal_invmap[sig] | ||
447 | : sig); | ||
448 | regs->er1 = (unsigned long)&(frame->info); | ||
449 | regs->er2 = (unsigned long)&frame->uc; | ||
450 | regs->er5 = current->mm->start_data; /* GOT base */ | ||
451 | |||
452 | return; | ||
453 | |||
454 | give_sigsegv: | ||
455 | force_sigsegv(sig, current); | ||
456 | } | ||
457 | |||
458 | /* | ||
459 | * OK, we're invoking a handler | ||
460 | */ | ||
461 | static void | ||
462 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | ||
463 | sigset_t *oldset, struct pt_regs * regs) | ||
464 | { | ||
465 | /* are we from a system call? */ | ||
466 | if (regs->orig_er0 >= 0) { | ||
467 | switch (regs->er0) { | ||
468 | case -ERESTART_RESTARTBLOCK: | ||
469 | case -ERESTARTNOHAND: | ||
470 | regs->er0 = -EINTR; | ||
471 | break; | ||
472 | |||
473 | case -ERESTARTSYS: | ||
474 | if (!(ka->sa.sa_flags & SA_RESTART)) { | ||
475 | regs->er0 = -EINTR; | ||
476 | break; | ||
477 | } | ||
478 | /* fallthrough */ | ||
479 | case -ERESTARTNOINTR: | ||
480 | regs->er0 = regs->orig_er0; | ||
481 | regs->pc -= 2; | ||
482 | } | ||
483 | } | ||
484 | |||
485 | /* set up the stack frame */ | ||
486 | if (ka->sa.sa_flags & SA_SIGINFO) | ||
487 | setup_rt_frame(sig, ka, info, oldset, regs); | ||
488 | else | ||
489 | setup_frame(sig, ka, oldset, regs); | ||
490 | |||
491 | if (!(ka->sa.sa_flags & SA_NODEFER)) { | ||
492 | spin_lock_irq(¤t->sighand->siglock); | ||
493 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); | ||
494 | sigaddset(¤t->blocked,sig); | ||
495 | recalc_sigpending(); | ||
496 | spin_unlock_irq(¤t->sighand->siglock); | ||
497 | } | ||
498 | } | ||
499 | |||
500 | /* | ||
501 | * Note that 'init' is a special process: it doesn't get signals it doesn't | ||
502 | * want to handle. Thus you cannot kill init even with a SIGKILL even by | ||
503 | * mistake. | ||
504 | */ | ||
505 | asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset) | ||
506 | { | ||
507 | siginfo_t info; | ||
508 | int signr; | ||
509 | struct k_sigaction ka; | ||
510 | |||
511 | /* | ||
512 | * We want the common case to go fast, which | ||
513 | * is why we may in certain cases get here from | ||
514 | * kernel mode. Just return without doing anything | ||
515 | * if so. | ||
516 | */ | ||
517 | if ((regs->ccr & 0x10)) | ||
518 | return 1; | ||
519 | |||
520 | if (current->flags & PF_FREEZE) { | ||
521 | refrigerator(0); | ||
522 | goto no_signal; | ||
523 | } | ||
524 | |||
525 | current->thread.esp0 = (unsigned long) regs; | ||
526 | |||
527 | if (!oldset) | ||
528 | oldset = ¤t->blocked; | ||
529 | |||
530 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | ||
531 | if (signr > 0) { | ||
532 | /* Whee! Actually deliver the signal. */ | ||
533 | handle_signal(signr, &info, &ka, oldset, regs); | ||
534 | return 1; | ||
535 | } | ||
536 | no_signal: | ||
537 | /* Did we come from a system call? */ | ||
538 | if (regs->orig_er0 >= 0) { | ||
539 | /* Restart the system call - no handlers present */ | ||
540 | if (regs->er0 == -ERESTARTNOHAND || | ||
541 | regs->er0 == -ERESTARTSYS || | ||
542 | regs->er0 == -ERESTARTNOINTR) { | ||
543 | regs->er0 = regs->orig_er0; | ||
544 | regs->pc -= 2; | ||
545 | } | ||
546 | if (regs->er0 == -ERESTART_RESTARTBLOCK){ | ||
547 | regs->er0 = __NR_restart_syscall; | ||
548 | regs->pc -= 2; | ||
549 | } | ||
550 | } | ||
551 | return 0; | ||
552 | } | ||
diff --git a/arch/h8300/kernel/sys_h8300.c b/arch/h8300/kernel/sys_h8300.c new file mode 100644 index 000000000000..0f61b7ad69ab --- /dev/null +++ b/arch/h8300/kernel/sys_h8300.c | |||
@@ -0,0 +1,282 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/kernel/sys_h8300.c | ||
3 | * | ||
4 | * This file contains various random system calls that | ||
5 | * have a non-standard calling sequence on the H8/300 | ||
6 | * platform. | ||
7 | */ | ||
8 | |||
9 | #include <linux/errno.h> | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/mm.h> | ||
12 | #include <linux/smp.h> | ||
13 | #include <linux/smp_lock.h> | ||
14 | #include <linux/sem.h> | ||
15 | #include <linux/msg.h> | ||
16 | #include <linux/shm.h> | ||
17 | #include <linux/stat.h> | ||
18 | #include <linux/syscalls.h> | ||
19 | #include <linux/mman.h> | ||
20 | #include <linux/file.h> | ||
21 | #include <linux/utsname.h> | ||
22 | |||
23 | #include <asm/setup.h> | ||
24 | #include <asm/uaccess.h> | ||
25 | #include <asm/cachectl.h> | ||
26 | #include <asm/traps.h> | ||
27 | #include <asm/ipc.h> | ||
28 | |||
29 | /* | ||
30 | * sys_pipe() is the normal C calling standard for creating | ||
31 | * a pipe. It's not the way unix traditionally does this, though. | ||
32 | */ | ||
33 | asmlinkage int sys_pipe(unsigned long * fildes) | ||
34 | { | ||
35 | int fd[2]; | ||
36 | int error; | ||
37 | |||
38 | error = do_pipe(fd); | ||
39 | if (!error) { | ||
40 | if (copy_to_user(fildes, fd, 2*sizeof(int))) | ||
41 | error = -EFAULT; | ||
42 | } | ||
43 | return error; | ||
44 | } | ||
45 | |||
46 | /* common code for old and new mmaps */ | ||
47 | static inline long do_mmap2( | ||
48 | unsigned long addr, unsigned long len, | ||
49 | unsigned long prot, unsigned long flags, | ||
50 | unsigned long fd, unsigned long pgoff) | ||
51 | { | ||
52 | int error = -EBADF; | ||
53 | struct file * file = NULL; | ||
54 | |||
55 | flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); | ||
56 | if (!(flags & MAP_ANONYMOUS)) { | ||
57 | file = fget(fd); | ||
58 | if (!file) | ||
59 | goto out; | ||
60 | } | ||
61 | |||
62 | down_write(¤t->mm->mmap_sem); | ||
63 | error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); | ||
64 | up_write(¤t->mm->mmap_sem); | ||
65 | |||
66 | if (file) | ||
67 | fput(file); | ||
68 | out: | ||
69 | return error; | ||
70 | } | ||
71 | |||
72 | asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, | ||
73 | unsigned long prot, unsigned long flags, | ||
74 | unsigned long fd, unsigned long pgoff) | ||
75 | { | ||
76 | return do_mmap2(addr, len, prot, flags, fd, pgoff); | ||
77 | } | ||
78 | |||
79 | /* | ||
80 | * Perform the select(nd, in, out, ex, tv) and mmap() system | ||
81 | * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to | ||
82 | * handle more than 4 system call parameters, so these system calls | ||
83 | * used a memory block for parameter passing.. | ||
84 | */ | ||
85 | |||
86 | struct mmap_arg_struct { | ||
87 | unsigned long addr; | ||
88 | unsigned long len; | ||
89 | unsigned long prot; | ||
90 | unsigned long flags; | ||
91 | unsigned long fd; | ||
92 | unsigned long offset; | ||
93 | }; | ||
94 | |||
95 | asmlinkage int old_mmap(struct mmap_arg_struct *arg) | ||
96 | { | ||
97 | struct mmap_arg_struct a; | ||
98 | int error = -EFAULT; | ||
99 | |||
100 | if (copy_from_user(&a, arg, sizeof(a))) | ||
101 | goto out; | ||
102 | |||
103 | error = -EINVAL; | ||
104 | if (a.offset & ~PAGE_MASK) | ||
105 | goto out; | ||
106 | |||
107 | a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); | ||
108 | |||
109 | error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); | ||
110 | out: | ||
111 | return error; | ||
112 | } | ||
113 | |||
114 | #if 0 /* DAVIDM - do we want this */ | ||
115 | struct mmap_arg_struct64 { | ||
116 | __u32 addr; | ||
117 | __u32 len; | ||
118 | __u32 prot; | ||
119 | __u32 flags; | ||
120 | __u64 offset; /* 64 bits */ | ||
121 | __u32 fd; | ||
122 | }; | ||
123 | |||
124 | asmlinkage long sys_mmap64(struct mmap_arg_struct64 *arg) | ||
125 | { | ||
126 | int error = -EFAULT; | ||
127 | struct file * file = NULL; | ||
128 | struct mmap_arg_struct64 a; | ||
129 | unsigned long pgoff; | ||
130 | |||
131 | if (copy_from_user(&a, arg, sizeof(a))) | ||
132 | return -EFAULT; | ||
133 | |||
134 | if ((long)a.offset & ~PAGE_MASK) | ||
135 | return -EINVAL; | ||
136 | |||
137 | pgoff = a.offset >> PAGE_SHIFT; | ||
138 | if ((a.offset >> PAGE_SHIFT) != pgoff) | ||
139 | return -EINVAL; | ||
140 | |||
141 | if (!(a.flags & MAP_ANONYMOUS)) { | ||
142 | error = -EBADF; | ||
143 | file = fget(a.fd); | ||
144 | if (!file) | ||
145 | goto out; | ||
146 | } | ||
147 | a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); | ||
148 | |||
149 | down_write(¤t->mm->mmap_sem); | ||
150 | error = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, pgoff); | ||
151 | up_write(¤t->mm->mmap_sem); | ||
152 | if (file) | ||
153 | fput(file); | ||
154 | out: | ||
155 | return error; | ||
156 | } | ||
157 | #endif | ||
158 | |||
159 | struct sel_arg_struct { | ||
160 | unsigned long n; | ||
161 | fd_set *inp, *outp, *exp; | ||
162 | struct timeval *tvp; | ||
163 | }; | ||
164 | |||
165 | asmlinkage int old_select(struct sel_arg_struct *arg) | ||
166 | { | ||
167 | struct sel_arg_struct a; | ||
168 | |||
169 | if (copy_from_user(&a, arg, sizeof(a))) | ||
170 | return -EFAULT; | ||
171 | /* sys_select() does the appropriate kernel locking */ | ||
172 | return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); | ||
173 | } | ||
174 | |||
175 | /* | ||
176 | * sys_ipc() is the de-multiplexer for the SysV IPC calls.. | ||
177 | * | ||
178 | * This is really horribly ugly. | ||
179 | */ | ||
180 | asmlinkage int sys_ipc (uint call, int first, int second, | ||
181 | int third, void *ptr, long fifth) | ||
182 | { | ||
183 | int version, ret; | ||
184 | |||
185 | version = call >> 16; /* hack for backward compatibility */ | ||
186 | call &= 0xffff; | ||
187 | |||
188 | if (call <= SEMCTL) | ||
189 | switch (call) { | ||
190 | case SEMOP: | ||
191 | return sys_semop (first, (struct sembuf *)ptr, second); | ||
192 | case SEMGET: | ||
193 | return sys_semget (first, second, third); | ||
194 | case SEMCTL: { | ||
195 | union semun fourth; | ||
196 | if (!ptr) | ||
197 | return -EINVAL; | ||
198 | if (get_user(fourth.__pad, (void **) ptr)) | ||
199 | return -EFAULT; | ||
200 | return sys_semctl (first, second, third, fourth); | ||
201 | } | ||
202 | default: | ||
203 | return -EINVAL; | ||
204 | } | ||
205 | if (call <= MSGCTL) | ||
206 | switch (call) { | ||
207 | case MSGSND: | ||
208 | return sys_msgsnd (first, (struct msgbuf *) ptr, | ||
209 | second, third); | ||
210 | case MSGRCV: | ||
211 | switch (version) { | ||
212 | case 0: { | ||
213 | struct ipc_kludge tmp; | ||
214 | if (!ptr) | ||
215 | return -EINVAL; | ||
216 | if (copy_from_user (&tmp, | ||
217 | (struct ipc_kludge *)ptr, | ||
218 | sizeof (tmp))) | ||
219 | return -EFAULT; | ||
220 | return sys_msgrcv (first, tmp.msgp, second, | ||
221 | tmp.msgtyp, third); | ||
222 | } | ||
223 | default: | ||
224 | return sys_msgrcv (first, | ||
225 | (struct msgbuf *) ptr, | ||
226 | second, fifth, third); | ||
227 | } | ||
228 | case MSGGET: | ||
229 | return sys_msgget ((key_t) first, second); | ||
230 | case MSGCTL: | ||
231 | return sys_msgctl (first, second, | ||
232 | (struct msqid_ds *) ptr); | ||
233 | default: | ||
234 | return -EINVAL; | ||
235 | } | ||
236 | if (call <= SHMCTL) | ||
237 | switch (call) { | ||
238 | case SHMAT: | ||
239 | switch (version) { | ||
240 | default: { | ||
241 | ulong raddr; | ||
242 | ret = do_shmat (first, (char *) ptr, | ||
243 | second, &raddr); | ||
244 | if (ret) | ||
245 | return ret; | ||
246 | return put_user (raddr, (ulong *) third); | ||
247 | } | ||
248 | } | ||
249 | case SHMDT: | ||
250 | return sys_shmdt ((char *)ptr); | ||
251 | case SHMGET: | ||
252 | return sys_shmget (first, second, third); | ||
253 | case SHMCTL: | ||
254 | return sys_shmctl (first, second, | ||
255 | (struct shmid_ds *) ptr); | ||
256 | default: | ||
257 | return -EINVAL; | ||
258 | } | ||
259 | |||
260 | return -EINVAL; | ||
261 | } | ||
262 | |||
263 | /* sys_cacheflush -- no support. */ | ||
264 | asmlinkage int | ||
265 | sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) | ||
266 | { | ||
267 | return -EINVAL; | ||
268 | } | ||
269 | |||
270 | asmlinkage int sys_getpagesize(void) | ||
271 | { | ||
272 | return PAGE_SIZE; | ||
273 | } | ||
274 | |||
275 | #if defined(CONFIG_SYSCALL_PRINT) | ||
276 | asmlinkage void syscall_print(void *dummy,...) | ||
277 | { | ||
278 | struct pt_regs *regs = (struct pt_regs *) ((unsigned char *)&dummy-4); | ||
279 | printk("call %06lx:%ld 1:%08lx,2:%08lx,3:%08lx,ret:%08lx\n", | ||
280 | ((regs->pc)&0xffffff)-2,regs->orig_er0,regs->er1,regs->er2,regs->er3,regs->er0); | ||
281 | } | ||
282 | #endif | ||
diff --git a/arch/h8300/kernel/syscalls.S b/arch/h8300/kernel/syscalls.S new file mode 100644 index 000000000000..79b3bda5c6e3 --- /dev/null +++ b/arch/h8300/kernel/syscalls.S | |||
@@ -0,0 +1,340 @@ | |||
1 | /* Systemcall Entry Table */ | ||
2 | #include <linux/config.h> | ||
3 | #include <linux/sys.h> | ||
4 | #include <asm/linkage.h> | ||
5 | #include <asm/unistd.h> | ||
6 | |||
7 | .globl SYMBOL_NAME(sys_call_table) | ||
8 | |||
9 | #if defined(CONFIG_CPU_H8300H) | ||
10 | .h8300h | ||
11 | #endif | ||
12 | #if defined(CONFIG_CPU_H8S) | ||
13 | .h8300s | ||
14 | #endif | ||
15 | .section .text | ||
16 | .align 2 | ||
17 | SYMBOL_NAME_LABEL(sys_call_table) | ||
18 | .long SYMBOL_NAME(sys_ni_syscall) /* 0 - old "setup()" system call*/ | ||
19 | .long SYMBOL_NAME(sys_exit) | ||
20 | .long SYMBOL_NAME(sys_fork) | ||
21 | .long SYMBOL_NAME(sys_read) | ||
22 | .long SYMBOL_NAME(sys_write) | ||
23 | .long SYMBOL_NAME(sys_open) /* 5 */ | ||
24 | .long SYMBOL_NAME(sys_close) | ||
25 | .long SYMBOL_NAME(sys_waitpid) | ||
26 | .long SYMBOL_NAME(sys_creat) | ||
27 | .long SYMBOL_NAME(sys_link) | ||
28 | .long SYMBOL_NAME(sys_unlink) /* 10 */ | ||
29 | .long SYMBOL_NAME(sys_execve) | ||
30 | .long SYMBOL_NAME(sys_chdir) | ||
31 | .long SYMBOL_NAME(sys_time) | ||
32 | .long SYMBOL_NAME(sys_mknod) | ||
33 | .long SYMBOL_NAME(sys_chmod) /* 15 */ | ||
34 | .long SYMBOL_NAME(sys_chown16) | ||
35 | .long SYMBOL_NAME(sys_ni_syscall) /* old break syscall holder */ | ||
36 | .long SYMBOL_NAME(sys_stat) | ||
37 | .long SYMBOL_NAME(sys_lseek) | ||
38 | .long SYMBOL_NAME(sys_getpid) /* 20 */ | ||
39 | .long SYMBOL_NAME(sys_mount) | ||
40 | .long SYMBOL_NAME(sys_oldumount) | ||
41 | .long SYMBOL_NAME(sys_setuid16) | ||
42 | .long SYMBOL_NAME(sys_getuid16) | ||
43 | .long SYMBOL_NAME(sys_stime) /* 25 */ | ||
44 | .long SYMBOL_NAME(sys_ptrace) | ||
45 | .long SYMBOL_NAME(sys_alarm) | ||
46 | .long SYMBOL_NAME(sys_fstat) | ||
47 | .long SYMBOL_NAME(sys_pause) | ||
48 | .long SYMBOL_NAME(sys_utime) /* 30 */ | ||
49 | .long SYMBOL_NAME(sys_ni_syscall) /* old stty syscall holder */ | ||
50 | .long SYMBOL_NAME(sys_ni_syscall) /* old gtty syscall holder */ | ||
51 | .long SYMBOL_NAME(sys_access) | ||
52 | .long SYMBOL_NAME(sys_nice) | ||
53 | .long SYMBOL_NAME(sys_ni_syscall) /* 35 */ /* old ftime syscall holder */ | ||
54 | .long SYMBOL_NAME(sys_sync) | ||
55 | .long SYMBOL_NAME(sys_kill) | ||
56 | .long SYMBOL_NAME(sys_rename) | ||
57 | .long SYMBOL_NAME(sys_mkdir) | ||
58 | .long SYMBOL_NAME(sys_rmdir) /* 40 */ | ||
59 | .long SYMBOL_NAME(sys_dup) | ||
60 | .long SYMBOL_NAME(sys_pipe) | ||
61 | .long SYMBOL_NAME(sys_times) | ||
62 | .long SYMBOL_NAME(sys_ni_syscall) /* old prof syscall holder */ | ||
63 | .long SYMBOL_NAME(sys_brk) /* 45 */ | ||
64 | .long SYMBOL_NAME(sys_setgid16) | ||
65 | .long SYMBOL_NAME(sys_getgid16) | ||
66 | .long SYMBOL_NAME(sys_signal) | ||
67 | .long SYMBOL_NAME(sys_geteuid16) | ||
68 | .long SYMBOL_NAME(sys_getegid16) /* 50 */ | ||
69 | .long SYMBOL_NAME(sys_acct) | ||
70 | .long SYMBOL_NAME(sys_umount) /* recycled never used phys() */ | ||
71 | .long SYMBOL_NAME(sys_ni_syscall) /* old lock syscall holder */ | ||
72 | .long SYMBOL_NAME(sys_ioctl) | ||
73 | .long SYMBOL_NAME(sys_fcntl) /* 55 */ | ||
74 | .long SYMBOL_NAME(sys_ni_syscall) /* old mpx syscall holder */ | ||
75 | .long SYMBOL_NAME(sys_setpgid) | ||
76 | .long SYMBOL_NAME(sys_ni_syscall) /* old ulimit syscall holder */ | ||
77 | .long SYMBOL_NAME(sys_ni_syscall) | ||
78 | .long SYMBOL_NAME(sys_umask) /* 60 */ | ||
79 | .long SYMBOL_NAME(sys_chroot) | ||
80 | .long SYMBOL_NAME(sys_ustat) | ||
81 | .long SYMBOL_NAME(sys_dup2) | ||
82 | .long SYMBOL_NAME(sys_getppid) | ||
83 | .long SYMBOL_NAME(sys_getpgrp) /* 65 */ | ||
84 | .long SYMBOL_NAME(sys_setsid) | ||
85 | .long SYMBOL_NAME(sys_sigaction) | ||
86 | .long SYMBOL_NAME(sys_sgetmask) | ||
87 | .long SYMBOL_NAME(sys_ssetmask) | ||
88 | .long SYMBOL_NAME(sys_setreuid16) /* 70 */ | ||
89 | .long SYMBOL_NAME(sys_setregid16) | ||
90 | .long SYMBOL_NAME(sys_sigsuspend) | ||
91 | .long SYMBOL_NAME(sys_sigpending) | ||
92 | .long SYMBOL_NAME(sys_sethostname) | ||
93 | .long SYMBOL_NAME(sys_setrlimit) /* 75 */ | ||
94 | .long SYMBOL_NAME(sys_old_getrlimit) | ||
95 | .long SYMBOL_NAME(sys_getrusage) | ||
96 | .long SYMBOL_NAME(sys_gettimeofday) | ||
97 | .long SYMBOL_NAME(sys_settimeofday) | ||
98 | .long SYMBOL_NAME(sys_getgroups16) /* 80 */ | ||
99 | .long SYMBOL_NAME(sys_setgroups16) | ||
100 | .long SYMBOL_NAME(old_select) | ||
101 | .long SYMBOL_NAME(sys_symlink) | ||
102 | .long SYMBOL_NAME(sys_lstat) | ||
103 | .long SYMBOL_NAME(sys_readlink) /* 85 */ | ||
104 | .long SYMBOL_NAME(sys_uselib) | ||
105 | .long SYMBOL_NAME(sys_swapon) | ||
106 | .long SYMBOL_NAME(sys_reboot) | ||
107 | .long SYMBOL_NAME(old_readdir) | ||
108 | .long SYMBOL_NAME(old_mmap) /* 90 */ | ||
109 | .long SYMBOL_NAME(sys_munmap) | ||
110 | .long SYMBOL_NAME(sys_truncate) | ||
111 | .long SYMBOL_NAME(sys_ftruncate) | ||
112 | .long SYMBOL_NAME(sys_fchmod) | ||
113 | .long SYMBOL_NAME(sys_fchown16) /* 95 */ | ||
114 | .long SYMBOL_NAME(sys_getpriority) | ||
115 | .long SYMBOL_NAME(sys_setpriority) | ||
116 | .long SYMBOL_NAME(sys_ni_syscall) /* old profil syscall holder */ | ||
117 | .long SYMBOL_NAME(sys_statfs) | ||
118 | .long SYMBOL_NAME(sys_fstatfs) /* 100 */ | ||
119 | .long SYMBOL_NAME(sys_ni_syscall) /* ioperm for i386 */ | ||
120 | .long SYMBOL_NAME(sys_socketcall) | ||
121 | .long SYMBOL_NAME(sys_syslog) | ||
122 | .long SYMBOL_NAME(sys_setitimer) | ||
123 | .long SYMBOL_NAME(sys_getitimer) /* 105 */ | ||
124 | .long SYMBOL_NAME(sys_newstat) | ||
125 | .long SYMBOL_NAME(sys_newlstat) | ||
126 | .long SYMBOL_NAME(sys_newfstat) | ||
127 | .long SYMBOL_NAME(sys_ni_syscall) | ||
128 | .long SYMBOL_NAME(sys_ni_syscall) /* iopl for i386 */ /* 110 */ | ||
129 | .long SYMBOL_NAME(sys_vhangup) | ||
130 | .long SYMBOL_NAME(sys_ni_syscall) /* obsolete idle() syscall */ | ||
131 | .long SYMBOL_NAME(sys_ni_syscall) /* vm86old for i386 */ | ||
132 | .long SYMBOL_NAME(sys_wait4) | ||
133 | .long SYMBOL_NAME(sys_swapoff) /* 115 */ | ||
134 | .long SYMBOL_NAME(sys_sysinfo) | ||
135 | .long SYMBOL_NAME(sys_ipc) | ||
136 | .long SYMBOL_NAME(sys_fsync) | ||
137 | .long SYMBOL_NAME(sys_sigreturn) | ||
138 | .long SYMBOL_NAME(sys_clone) /* 120 */ | ||
139 | .long SYMBOL_NAME(sys_setdomainname) | ||
140 | .long SYMBOL_NAME(sys_newuname) | ||
141 | .long SYMBOL_NAME(sys_cacheflush) /* modify_ldt for i386 */ | ||
142 | .long SYMBOL_NAME(sys_adjtimex) | ||
143 | .long SYMBOL_NAME(sys_ni_syscall) /* 125 sys_mprotect */ | ||
144 | .long SYMBOL_NAME(sys_sigprocmask) | ||
145 | .long SYMBOL_NAME(sys_ni_syscall) /* sys_create_module */ | ||
146 | .long SYMBOL_NAME(sys_init_module) | ||
147 | .long SYMBOL_NAME(sys_delete_module) | ||
148 | .long SYMBOL_NAME(sys_ni_syscall) /* 130 sys_get_kernel_syms */ | ||
149 | .long SYMBOL_NAME(sys_quotactl) | ||
150 | .long SYMBOL_NAME(sys_getpgid) | ||
151 | .long SYMBOL_NAME(sys_fchdir) | ||
152 | .long SYMBOL_NAME(sys_bdflush) | ||
153 | .long SYMBOL_NAME(sys_sysfs) /* 135 */ | ||
154 | .long SYMBOL_NAME(sys_personality) | ||
155 | .long SYMBOL_NAME(sys_ni_syscall) /* for afs_syscall */ | ||
156 | .long SYMBOL_NAME(sys_setfsuid16) | ||
157 | .long SYMBOL_NAME(sys_setfsgid16) | ||
158 | .long SYMBOL_NAME(sys_llseek) /* 140 */ | ||
159 | .long SYMBOL_NAME(sys_getdents) | ||
160 | .long SYMBOL_NAME(sys_select) | ||
161 | .long SYMBOL_NAME(sys_flock) | ||
162 | .long SYMBOL_NAME(sys_ni_syscall) /* sys_msync */ | ||
163 | .long SYMBOL_NAME(sys_readv) /* 145 */ | ||
164 | .long SYMBOL_NAME(sys_writev) | ||
165 | .long SYMBOL_NAME(sys_getsid) | ||
166 | .long SYMBOL_NAME(sys_fdatasync) | ||
167 | .long SYMBOL_NAME(sys_sysctl) | ||
168 | .long SYMBOL_NAME(sys_ni_syscall) /* 150 sys_mlock */ | ||
169 | .long SYMBOL_NAME(sys_ni_syscall) /* sys_munlock */ | ||
170 | .long SYMBOL_NAME(sys_ni_syscall) /* sys_mlockall */ | ||
171 | .long SYMBOL_NAME(sys_ni_syscall) /* sys_munlockall */ | ||
172 | .long SYMBOL_NAME(sys_sched_setparam) | ||
173 | .long SYMBOL_NAME(sys_sched_getparam) /* 155 */ | ||
174 | .long SYMBOL_NAME(sys_sched_setscheduler) | ||
175 | .long SYMBOL_NAME(sys_sched_getscheduler) | ||
176 | .long SYMBOL_NAME(sys_sched_yield) | ||
177 | .long SYMBOL_NAME(sys_sched_get_priority_max) | ||
178 | .long SYMBOL_NAME(sys_sched_get_priority_min) /* 160 */ | ||
179 | .long SYMBOL_NAME(sys_sched_rr_get_interval) | ||
180 | .long SYMBOL_NAME(sys_nanosleep) | ||
181 | .long SYMBOL_NAME(sys_ni_syscall) /* sys_mremap */ | ||
182 | .long SYMBOL_NAME(sys_setresuid16) | ||
183 | .long SYMBOL_NAME(sys_getresuid16) /* 165 */ | ||
184 | .long SYMBOL_NAME(sys_ni_syscall) /* for vm86 */ | ||
185 | .long SYMBOL_NAME(sys_ni_syscall) /* sys_query_module */ | ||
186 | .long SYMBOL_NAME(sys_poll) | ||
187 | .long SYMBOL_NAME(sys_nfsservctl) | ||
188 | .long SYMBOL_NAME(sys_setresgid16) /* 170 */ | ||
189 | .long SYMBOL_NAME(sys_getresgid16) | ||
190 | .long SYMBOL_NAME(sys_prctl) | ||
191 | .long SYMBOL_NAME(sys_rt_sigreturn) | ||
192 | .long SYMBOL_NAME(sys_rt_sigaction) | ||
193 | .long SYMBOL_NAME(sys_rt_sigprocmask) /* 175 */ | ||
194 | .long SYMBOL_NAME(sys_rt_sigpending) | ||
195 | .long SYMBOL_NAME(sys_rt_sigtimedwait) | ||
196 | .long SYMBOL_NAME(sys_rt_sigqueueinfo) | ||
197 | .long SYMBOL_NAME(sys_rt_sigsuspend) | ||
198 | .long SYMBOL_NAME(sys_pread64) /* 180 */ | ||
199 | .long SYMBOL_NAME(sys_pwrite64) | ||
200 | .long SYMBOL_NAME(sys_lchown16); | ||
201 | .long SYMBOL_NAME(sys_getcwd) | ||
202 | .long SYMBOL_NAME(sys_capget) | ||
203 | .long SYMBOL_NAME(sys_capset) /* 185 */ | ||
204 | .long SYMBOL_NAME(sys_sigaltstack) | ||
205 | .long SYMBOL_NAME(sys_sendfile) | ||
206 | .long SYMBOL_NAME(sys_ni_syscall) /* streams1 */ | ||
207 | .long SYMBOL_NAME(sys_ni_syscall) /* streams2 */ | ||
208 | .long SYMBOL_NAME(sys_vfork) /* 190 */ | ||
209 | .long SYMBOL_NAME(sys_getrlimit) | ||
210 | .long SYMBOL_NAME(sys_mmap2) | ||
211 | .long SYMBOL_NAME(sys_truncate64) | ||
212 | .long SYMBOL_NAME(sys_ftruncate64) | ||
213 | .long SYMBOL_NAME(sys_stat64) /* 195 */ | ||
214 | .long SYMBOL_NAME(sys_lstat64) | ||
215 | .long SYMBOL_NAME(sys_fstat64) | ||
216 | .long SYMBOL_NAME(sys_chown) | ||
217 | .long SYMBOL_NAME(sys_getuid) | ||
218 | .long SYMBOL_NAME(sys_getgid) /* 200 */ | ||
219 | .long SYMBOL_NAME(sys_geteuid) | ||
220 | .long SYMBOL_NAME(sys_getegid) | ||
221 | .long SYMBOL_NAME(sys_setreuid) | ||
222 | .long SYMBOL_NAME(sys_setregid) | ||
223 | .long SYMBOL_NAME(sys_getgroups) /* 205 */ | ||
224 | .long SYMBOL_NAME(sys_setgroups) | ||
225 | .long SYMBOL_NAME(sys_fchown) | ||
226 | .long SYMBOL_NAME(sys_setresuid) | ||
227 | .long SYMBOL_NAME(sys_getresuid) | ||
228 | .long SYMBOL_NAME(sys_setresgid) /* 210 */ | ||
229 | .long SYMBOL_NAME(sys_getresgid) | ||
230 | .long SYMBOL_NAME(sys_lchown) | ||
231 | .long SYMBOL_NAME(sys_setuid) | ||
232 | .long SYMBOL_NAME(sys_setgid) | ||
233 | .long SYMBOL_NAME(sys_setfsuid) /* 215 */ | ||
234 | .long SYMBOL_NAME(sys_setfsgid) | ||
235 | .long SYMBOL_NAME(sys_pivot_root) | ||
236 | .long SYMBOL_NAME(sys_ni_syscall) | ||
237 | .long SYMBOL_NAME(sys_ni_syscall) | ||
238 | .long SYMBOL_NAME(sys_getdents64) /* 220 */ | ||
239 | .long SYMBOL_NAME(sys_fcntl64) | ||
240 | .long SYMBOL_NAME(sys_ni_syscall) /* reserved for TUX */ | ||
241 | .long SYMBOL_NAME(sys_ni_syscall) | ||
242 | .long SYMBOL_NAME(sys_gettid) | ||
243 | .long SYMBOL_NAME(sys_ni_syscall) /* 225 */ /* sys_readahead */ | ||
244 | .long SYMBOL_NAME(sys_setxattr) | ||
245 | .long SYMBOL_NAME(sys_lsetxattr) | ||
246 | .long SYMBOL_NAME(sys_fsetxattr) | ||
247 | .long SYMBOL_NAME(sys_getxattr) | ||
248 | .long SYMBOL_NAME(sys_lgetxattr) /* 230 */ | ||
249 | .long SYMBOL_NAME(sys_fgetxattr) | ||
250 | .long SYMBOL_NAME(sys_listxattr) | ||
251 | .long SYMBOL_NAME(sys_llistxattr) | ||
252 | .long SYMBOL_NAME(sys_flistxattr) | ||
253 | .long SYMBOL_NAME(sys_removexattr) /* 235 */ | ||
254 | .long SYMBOL_NAME(sys_lremovexattr) | ||
255 | .long SYMBOL_NAME(sys_fremovexattr) | ||
256 | .long SYMBOL_NAME(sys_tkill) | ||
257 | .long SYMBOL_NAME(sys_sendfile64) | ||
258 | .long SYMBOL_NAME(sys_futex) /* 240 */ | ||
259 | .long SYMBOL_NAME(sys_sched_setaffinity) | ||
260 | .long SYMBOL_NAME(sys_sched_getaffinity) | ||
261 | .long SYMBOL_NAME(sys_ni_syscall) /* sys_set_thread_area */ | ||
262 | .long SYMBOL_NAME(sys_ni_syscall) /* sys_get_thread_area */ | ||
263 | .long SYMBOL_NAME(sys_io_setup) /* 245 */ | ||
264 | .long SYMBOL_NAME(sys_io_destroy) | ||
265 | .long SYMBOL_NAME(sys_io_getevents) | ||
266 | .long SYMBOL_NAME(sys_io_submit) | ||
267 | .long SYMBOL_NAME(sys_io_cancel) | ||
268 | .long SYMBOL_NAME(sys_fadvise64) /* 250 */ | ||
269 | .long SYMBOL_NAME(sys_ni_syscall) | ||
270 | .long SYMBOL_NAME(sys_exit_group) | ||
271 | .long SYMBOL_NAME(sys_lookup_dcookie) | ||
272 | .long SYMBOL_NAME(sys_epoll_create) | ||
273 | .long SYMBOL_NAME(sys_epoll_ctl) /* 255 */ | ||
274 | .long SYMBOL_NAME(sys_epoll_wait) | ||
275 | .long SYMBOL_NAME(sys_ni_syscall) /* sys_remap_file_pages */ | ||
276 | .long SYMBOL_NAME(sys_set_tid_address) | ||
277 | .long SYMBOL_NAME(sys_timer_create) | ||
278 | .long SYMBOL_NAME(sys_timer_settime) /* 260 */ | ||
279 | .long SYMBOL_NAME(sys_timer_gettime) | ||
280 | .long SYMBOL_NAME(sys_timer_getoverrun) | ||
281 | .long SYMBOL_NAME(sys_timer_delete) | ||
282 | .long SYMBOL_NAME(sys_clock_settime) | ||
283 | .long SYMBOL_NAME(sys_clock_gettime) /* 265 */ | ||
284 | .long SYMBOL_NAME(sys_clock_getres) | ||
285 | .long SYMBOL_NAME(sys_clock_nanosleep) | ||
286 | .long SYMBOL_NAME(sys_statfs64) | ||
287 | .long SYMBOL_NAME(sys_fstatfs64) | ||
288 | .long SYMBOL_NAME(sys_tgkill) /* 270 */ | ||
289 | .long SYMBOL_NAME(sys_utimes) | ||
290 | .long SYMBOL_NAME(sys_fadvise64_64) | ||
291 | .long SYMBOL_NAME(sys_ni_syscall) /* sys_vserver */ | ||
292 | .long SYMBOL_NAME(sys_mbind) | ||
293 | .long SYMBOL_NAME(sys_get_mempolicy) | ||
294 | .long SYMBOL_NAME(sys_set_mempolicy) | ||
295 | .long SYMBOL_NAME(sys_mq_open) | ||
296 | .long SYMBOL_NAME(sys_mq_unlink) | ||
297 | .long SYMBOL_NAME(sys_mq_timedsend) | ||
298 | .long SYMBOL_NAME(sys_mq_timedreceive) /* 280 */ | ||
299 | .long SYMBOL_NAME(sys_mq_notify) | ||
300 | .long SYMBOL_NAME(sys_mq_getsetattr) | ||
301 | .long SYMBOL_NAME(sys_ni_syscall) /* reserved for kexec */ | ||
302 | .long SYMBOL_NAME(sys_waitid) | ||
303 | .long SYMBOL_NAME(sys_ni_syscall) /* 285 */ /* available */ | ||
304 | .long SYMBOL_NAME(sys_add_key) | ||
305 | .long SYMBOL_NAME(sys_request_key) | ||
306 | .long SYMBOL_NAME(sys_keyctl) | ||
307 | |||
308 | .rept NR_syscalls-(.-SYMBOL_NAME(sys_call_table))/4 | ||
309 | .long SYMBOL_NAME(sys_ni_syscall) | ||
310 | .endr | ||
311 | |||
312 | .macro call_sp addr | ||
313 | mov.l #SYMBOL_NAME(\addr),er6 | ||
314 | bra SYMBOL_NAME(syscall_trampoline):8 | ||
315 | .endm | ||
316 | |||
317 | SYMBOL_NAME_LABEL(sys_clone) | ||
318 | call_sp h8300_clone | ||
319 | |||
320 | SYMBOL_NAME_LABEL(sys_sigsuspend) | ||
321 | call_sp do_sigsuspend | ||
322 | |||
323 | SYMBOL_NAME_LABEL(sys_rt_sigsuspend) | ||
324 | call_sp do_rt_sigsuspend | ||
325 | |||
326 | SYMBOL_NAME_LABEL(sys_sigreturn) | ||
327 | call_sp do_sigreturn | ||
328 | |||
329 | SYMBOL_NAME_LABEL(sys_rt_sigreturn) | ||
330 | call_sp do_rt_sigreturn | ||
331 | |||
332 | SYMBOL_NAME_LABEL(sys_fork) | ||
333 | call_sp h8300_fork | ||
334 | |||
335 | SYMBOL_NAME_LABEL(sys_vfork) | ||
336 | call_sp h8300_vfork | ||
337 | |||
338 | SYMBOL_NAME_LABEL(syscall_trampoline) | ||
339 | mov.l sp,er0 | ||
340 | jmp @er6 | ||
diff --git a/arch/h8300/kernel/time.c b/arch/h8300/kernel/time.c new file mode 100644 index 000000000000..8a600218334d --- /dev/null +++ b/arch/h8300/kernel/time.c | |||
@@ -0,0 +1,134 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/kernel/time.c | ||
3 | * | ||
4 | * Yoshinori Sato <ysato@users.sourceforge.jp> | ||
5 | * | ||
6 | * Copied/hacked from: | ||
7 | * | ||
8 | * linux/arch/m68k/kernel/time.c | ||
9 | * | ||
10 | * Copyright (C) 1991, 1992, 1995 Linus Torvalds | ||
11 | * | ||
12 | * This file contains the m68k-specific time handling details. | ||
13 | * Most of the stuff is located in the machine specific files. | ||
14 | * | ||
15 | * 1997-09-10 Updated NTP code according to technical memorandum Jan '96 | ||
16 | * "A Kernel Model for Precision Timekeeping" by Dave Mills | ||
17 | */ | ||
18 | |||
19 | #include <linux/config.h> /* CONFIG_HEARTBEAT */ | ||
20 | #include <linux/errno.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/param.h> | ||
25 | #include <linux/string.h> | ||
26 | #include <linux/mm.h> | ||
27 | #include <linux/timex.h> | ||
28 | #include <linux/profile.h> | ||
29 | |||
30 | #include <asm/io.h> | ||
31 | #include <asm/target_time.h> | ||
32 | |||
33 | #define TICK_SIZE (tick_nsec / 1000) | ||
34 | |||
35 | u64 jiffies_64; | ||
36 | |||
37 | EXPORT_SYMBOL(jiffies_64); | ||
38 | |||
39 | /* | ||
40 | * timer_interrupt() needs to keep up the real-time clock, | ||
41 | * as well as call the "do_timer()" routine every clocktick | ||
42 | */ | ||
43 | static void timer_interrupt(int irq, void *dummy, struct pt_regs * regs) | ||
44 | { | ||
45 | /* may need to kick the hardware timer */ | ||
46 | platform_timer_eoi(); | ||
47 | |||
48 | do_timer(regs); | ||
49 | #ifndef CONFIG_SMP | ||
50 | update_process_times(user_mode(regs)); | ||
51 | #endif | ||
52 | profile_tick(CPU_PROFILING, regs); | ||
53 | } | ||
54 | |||
55 | void time_init(void) | ||
56 | { | ||
57 | unsigned int year, mon, day, hour, min, sec; | ||
58 | |||
59 | /* FIX by dqg : Set to zero for platforms that don't have tod */ | ||
60 | /* without this time is undefined and can overflow time_t, causing */ | ||
61 | /* very stange errors */ | ||
62 | year = 1980; | ||
63 | mon = day = 1; | ||
64 | hour = min = sec = 0; | ||
65 | platform_gettod (&year, &mon, &day, &hour, &min, &sec); | ||
66 | |||
67 | if ((year += 1900) < 1970) | ||
68 | year += 100; | ||
69 | xtime.tv_sec = mktime(year, mon, day, hour, min, sec); | ||
70 | xtime.tv_nsec = 0; | ||
71 | |||
72 | platform_timer_setup(timer_interrupt); | ||
73 | } | ||
74 | |||
75 | /* | ||
76 | * This version of gettimeofday has near microsecond resolution. | ||
77 | */ | ||
78 | void do_gettimeofday(struct timeval *tv) | ||
79 | { | ||
80 | unsigned long flags; | ||
81 | unsigned long usec, sec; | ||
82 | |||
83 | read_lock_irqsave(&xtime_lock, flags); | ||
84 | usec = 0; | ||
85 | sec = xtime.tv_sec; | ||
86 | usec += (xtime.tv_nsec / 1000); | ||
87 | read_unlock_irqrestore(&xtime_lock, flags); | ||
88 | |||
89 | while (usec >= 1000000) { | ||
90 | usec -= 1000000; | ||
91 | sec++; | ||
92 | } | ||
93 | |||
94 | tv->tv_sec = sec; | ||
95 | tv->tv_usec = usec; | ||
96 | } | ||
97 | |||
98 | EXPORT_SYMBOL(do_gettimeofday); | ||
99 | |||
100 | int do_settimeofday(struct timespec *tv) | ||
101 | { | ||
102 | if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) | ||
103 | return -EINVAL; | ||
104 | |||
105 | write_lock_irq(&xtime_lock); | ||
106 | /* This is revolting. We need to set the xtime.tv_usec | ||
107 | * correctly. However, the value in this location is | ||
108 | * is value at the last tick. | ||
109 | * Discover what correction gettimeofday | ||
110 | * would have done, and then undo it! | ||
111 | */ | ||
112 | while (tv->tv_nsec < 0) { | ||
113 | tv->tv_nsec += NSEC_PER_SEC; | ||
114 | tv->tv_sec--; | ||
115 | } | ||
116 | |||
117 | xtime.tv_sec = tv->tv_sec; | ||
118 | xtime.tv_nsec = tv->tv_nsec; | ||
119 | time_adjust = 0; /* stop active adjtime() */ | ||
120 | time_status |= STA_UNSYNC; | ||
121 | time_maxerror = NTP_PHASE_LIMIT; | ||
122 | time_esterror = NTP_PHASE_LIMIT; | ||
123 | write_sequnlock_irq(&xtime_lock); | ||
124 | clock_was_set(); | ||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | EXPORT_SYMBOL(do_settimeofday); | ||
129 | |||
130 | unsigned long long sched_clock(void) | ||
131 | { | ||
132 | return (unsigned long long)jiffies * (1000000000 / HZ); | ||
133 | |||
134 | } | ||
diff --git a/arch/h8300/kernel/traps.c b/arch/h8300/kernel/traps.c new file mode 100644 index 000000000000..300e3279ca5a --- /dev/null +++ b/arch/h8300/kernel/traps.c | |||
@@ -0,0 +1,169 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/boot/traps.c -- general exception handling code | ||
3 | * H8/300 support Yoshinori Sato <ysato@users.sourceforge.jp> | ||
4 | * | ||
5 | * Cloned from Linux/m68k. | ||
6 | * | ||
7 | * No original Copyright holder listed, | ||
8 | * Probabily original (C) Roman Zippel (assigned DJD, 1999) | ||
9 | * | ||
10 | * Copyright 1999-2000 D. Jeff Dionne, <jeff@rt-control.com> | ||
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 | |||
17 | #include <linux/types.h> | ||
18 | #include <linux/sched.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/errno.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/module.h> | ||
23 | |||
24 | #include <asm/system.h> | ||
25 | #include <asm/irq.h> | ||
26 | #include <asm/traps.h> | ||
27 | #include <asm/page.h> | ||
28 | #include <asm/gpio.h> | ||
29 | |||
30 | /* | ||
31 | * this must be called very early as the kernel might | ||
32 | * use some instruction that are emulated on the 060 | ||
33 | */ | ||
34 | |||
35 | void __init base_trap_init(void) | ||
36 | { | ||
37 | } | ||
38 | |||
39 | void __init trap_init (void) | ||
40 | { | ||
41 | } | ||
42 | |||
43 | asmlinkage void set_esp0 (unsigned long ssp) | ||
44 | { | ||
45 | current->thread.esp0 = ssp; | ||
46 | } | ||
47 | |||
48 | /* | ||
49 | * Generic dumping code. Used for panic and debug. | ||
50 | */ | ||
51 | |||
52 | static void dump(struct pt_regs *fp) | ||
53 | { | ||
54 | unsigned long *sp; | ||
55 | unsigned char *tp; | ||
56 | int i; | ||
57 | |||
58 | printk("\nCURRENT PROCESS:\n\n"); | ||
59 | printk("COMM=%s PID=%d\n", current->comm, current->pid); | ||
60 | if (current->mm) { | ||
61 | printk("TEXT=%08x-%08x DATA=%08x-%08x BSS=%08x-%08x\n", | ||
62 | (int) current->mm->start_code, | ||
63 | (int) current->mm->end_code, | ||
64 | (int) current->mm->start_data, | ||
65 | (int) current->mm->end_data, | ||
66 | (int) current->mm->end_data, | ||
67 | (int) current->mm->brk); | ||
68 | printk("USER-STACK=%08x KERNEL-STACK=%08lx\n\n", | ||
69 | (int) current->mm->start_stack, | ||
70 | (int) PAGE_SIZE+(unsigned long)current); | ||
71 | } | ||
72 | |||
73 | show_regs(fp); | ||
74 | printk("\nCODE:"); | ||
75 | tp = ((unsigned char *) fp->pc) - 0x20; | ||
76 | for (sp = (unsigned long *) tp, i = 0; (i < 0x40); i += 4) { | ||
77 | if ((i % 0x10) == 0) | ||
78 | printk("\n%08x: ", (int) (tp + i)); | ||
79 | printk("%08x ", (int) *sp++); | ||
80 | } | ||
81 | printk("\n"); | ||
82 | |||
83 | printk("\nKERNEL STACK:"); | ||
84 | tp = ((unsigned char *) fp) - 0x40; | ||
85 | for (sp = (unsigned long *) tp, i = 0; (i < 0xc0); i += 4) { | ||
86 | if ((i % 0x10) == 0) | ||
87 | printk("\n%08x: ", (int) (tp + i)); | ||
88 | printk("%08x ", (int) *sp++); | ||
89 | } | ||
90 | printk("\n"); | ||
91 | if (STACK_MAGIC != *(unsigned long *)((unsigned long)current+PAGE_SIZE)) | ||
92 | printk("(Possibly corrupted stack page??)\n"); | ||
93 | |||
94 | printk("\n\n"); | ||
95 | } | ||
96 | |||
97 | void die_if_kernel (char *str, struct pt_regs *fp, int nr) | ||
98 | { | ||
99 | extern int console_loglevel; | ||
100 | |||
101 | if (!(fp->ccr & PS_S)) | ||
102 | return; | ||
103 | |||
104 | console_loglevel = 15; | ||
105 | dump(fp); | ||
106 | |||
107 | do_exit(SIGSEGV); | ||
108 | } | ||
109 | |||
110 | extern char _start, _etext; | ||
111 | #define check_kernel_text(addr) \ | ||
112 | ((addr >= (unsigned long)(&_start)) && \ | ||
113 | (addr < (unsigned long)(&_etext))) | ||
114 | |||
115 | static int kstack_depth_to_print = 24; | ||
116 | |||
117 | void show_stack(struct task_struct *task, unsigned long *esp) | ||
118 | { | ||
119 | unsigned long *stack, addr; | ||
120 | int i; | ||
121 | |||
122 | if (esp == NULL) | ||
123 | esp = (unsigned long *) &esp; | ||
124 | |||
125 | stack = esp; | ||
126 | |||
127 | printk("Stack from %08lx:", (unsigned long)stack); | ||
128 | for (i = 0; i < kstack_depth_to_print; i++) { | ||
129 | if (((unsigned long)stack & (THREAD_SIZE - 1)) == 0) | ||
130 | break; | ||
131 | if (i % 8 == 0) | ||
132 | printk("\n "); | ||
133 | printk(" %08lx", *stack++); | ||
134 | } | ||
135 | |||
136 | printk("\nCall Trace:"); | ||
137 | i = 0; | ||
138 | stack = esp; | ||
139 | while (((unsigned long)stack & (THREAD_SIZE - 1)) == 0) { | ||
140 | addr = *stack++; | ||
141 | /* | ||
142 | * If the address is either in the text segment of the | ||
143 | * kernel, or in the region which contains vmalloc'ed | ||
144 | * memory, it *may* be the address of a calling | ||
145 | * routine; if so, print it so that someone tracing | ||
146 | * down the cause of the crash will be able to figure | ||
147 | * out the call path that was taken. | ||
148 | */ | ||
149 | if (check_kernel_text(addr)) { | ||
150 | if (i % 4 == 0) | ||
151 | printk("\n "); | ||
152 | printk(" [<%08lx>]", addr); | ||
153 | i++; | ||
154 | } | ||
155 | } | ||
156 | printk("\n"); | ||
157 | } | ||
158 | |||
159 | void show_trace_task(struct task_struct *tsk) | ||
160 | { | ||
161 | show_stack(tsk,(unsigned long *)tsk->thread.esp0); | ||
162 | } | ||
163 | |||
164 | void dump_stack(void) | ||
165 | { | ||
166 | show_stack(NULL,NULL); | ||
167 | } | ||
168 | |||
169 | EXPORT_SYMBOL(dump_stack); | ||
diff --git a/arch/h8300/kernel/vmlinux.lds.S b/arch/h8300/kernel/vmlinux.lds.S new file mode 100644 index 000000000000..17fa11da1e4a --- /dev/null +++ b/arch/h8300/kernel/vmlinux.lds.S | |||
@@ -0,0 +1,172 @@ | |||
1 | #define VMLINUX_SYMBOL(_sym_) _##_sym_ | ||
2 | #include <asm-generic/vmlinux.lds.h> | ||
3 | #include <linux/config.h> | ||
4 | |||
5 | /* target memory map */ | ||
6 | #ifdef CONFIG_H8300H_GENERIC | ||
7 | #define ROMTOP 0x000000 | ||
8 | #define ROMSIZE 0x400000 | ||
9 | #define RAMTOP 0x400000 | ||
10 | #define RAMSIZE 0x400000 | ||
11 | #endif | ||
12 | |||
13 | #ifdef CONFIG_H8300H_AKI3068NET | ||
14 | #define ROMTOP 0x000000 | ||
15 | #define ROMSIZE 0x080000 | ||
16 | #define RAMTOP 0x400000 | ||
17 | #define RAMSIZE 0x200000 | ||
18 | #endif | ||
19 | |||
20 | #ifdef CONFIG_H8300H_H8MAX | ||
21 | #define ROMTOP 0x000000 | ||
22 | #define ROMSIZE 0x080000 | ||
23 | #define RAMTOP 0x400000 | ||
24 | #define RAMSIZE 0x200000 | ||
25 | #endif | ||
26 | |||
27 | #ifdef CONFIG_H8300H_SIM | ||
28 | #define ROMTOP 0x000000 | ||
29 | #define ROMSIZE 0x400000 | ||
30 | #define RAMTOP 0x400000 | ||
31 | #define RAMSIZE 0x400000 | ||
32 | #endif | ||
33 | |||
34 | #ifdef CONFIG_H8S_SIM | ||
35 | #define ROMTOP 0x000000 | ||
36 | #define ROMSIZE 0x400000 | ||
37 | #define RAMTOP 0x400000 | ||
38 | #define RAMSIZE 0x800000 | ||
39 | #endif | ||
40 | |||
41 | #ifdef CONFIG_H8S_EDOSK2674 | ||
42 | #define ROMTOP 0x000000 | ||
43 | #define ROMSIZE 0x400000 | ||
44 | #define RAMTOP 0x400000 | ||
45 | #define RAMSIZE 0x800000 | ||
46 | #endif | ||
47 | |||
48 | #if defined(CONFIG_H8300H_SIM) || defined(CONFIG_H8S_SIM) | ||
49 | INPUT(romfs.o) | ||
50 | #endif | ||
51 | |||
52 | _jiffies = _jiffies_64 + 4; | ||
53 | |||
54 | ENTRY(__start) | ||
55 | |||
56 | SECTIONS | ||
57 | { | ||
58 | #if defined(CONFIG_ROMKERNEL) | ||
59 | . = ROMTOP; | ||
60 | .vectors : | ||
61 | { | ||
62 | __vector = . ; | ||
63 | *(.vectors*) | ||
64 | } | ||
65 | #else | ||
66 | . = RAMTOP; | ||
67 | .bootvec : | ||
68 | { | ||
69 | *(.bootvec) | ||
70 | } | ||
71 | #endif | ||
72 | .text : | ||
73 | { | ||
74 | #if defined(CONFIG_ROMKERNEL) | ||
75 | *(.int_redirect) | ||
76 | #endif | ||
77 | __stext = . ; | ||
78 | *(.text) | ||
79 | SCHED_TEXT | ||
80 | LOCK_TEXT | ||
81 | __etext = . ; | ||
82 | . = ALIGN(16); /* Exception table */ | ||
83 | ___start___ex_table = .; | ||
84 | *(__ex_table) | ||
85 | ___stop___ex_table = .; | ||
86 | } | ||
87 | |||
88 | RODATA | ||
89 | #if defined(CONFIG_ROMKERNEL) | ||
90 | SECURITY_INIT | ||
91 | #endif | ||
92 | ROEND = .; | ||
93 | #if defined(CONFIG_ROMKERNEL) | ||
94 | . = RAMTOP; | ||
95 | .data : AT(ROEND) | ||
96 | #else | ||
97 | .data : | ||
98 | #endif | ||
99 | { | ||
100 | __sdata = . ; | ||
101 | ___data_start = . ; | ||
102 | |||
103 | . = ALIGN(0x2000) ; | ||
104 | *(.data.init_task) | ||
105 | . = ALIGN(0x4) ; | ||
106 | *(.data) | ||
107 | . = ALIGN(0x4) ; | ||
108 | *(.data.*) | ||
109 | |||
110 | . = ALIGN(0x4) ; | ||
111 | ___init_begin = .; | ||
112 | __sinittext = .; | ||
113 | *(.init.text) | ||
114 | __einittext = .; | ||
115 | *(.init.data) | ||
116 | . = ALIGN(0x4) ; | ||
117 | ___setup_start = .; | ||
118 | *(.init.setup) | ||
119 | . = ALIGN(0x4) ; | ||
120 | ___setup_end = .; | ||
121 | ___initcall_start = .; | ||
122 | *(.initcall1.init) | ||
123 | *(.initcall2.init) | ||
124 | *(.initcall3.init) | ||
125 | *(.initcall4.init) | ||
126 | *(.initcall5.init) | ||
127 | *(.initcall6.init) | ||
128 | *(.initcall7.init) | ||
129 | ___initcall_end = .; | ||
130 | ___con_initcall_start = .; | ||
131 | *(.con_initcall.init) | ||
132 | ___con_initcall_end = .; | ||
133 | *(.exit.text) | ||
134 | *(.exit.data) | ||
135 | . = ALIGN(4); | ||
136 | ___initramfs_start = .; | ||
137 | *(.init.ramfs) | ||
138 | ___initramfs_end = .; | ||
139 | . = ALIGN(0x4) ; | ||
140 | ___init_end = .; | ||
141 | __edata = . ; | ||
142 | } | ||
143 | #if defined(CONFIG_RAMKERNEL) | ||
144 | SECURITY_INIT | ||
145 | #endif | ||
146 | __begin_data = LOADADDR(.data); | ||
147 | .bss : | ||
148 | { | ||
149 | . = ALIGN(0x4) ; | ||
150 | __sbss = . ; | ||
151 | *(.bss*) | ||
152 | . = ALIGN(0x4) ; | ||
153 | *(COMMON) | ||
154 | . = ALIGN(0x4) ; | ||
155 | __ebss = . ; | ||
156 | __end = . ; | ||
157 | __ramstart = .; | ||
158 | } | ||
159 | /DISCARD/ : { | ||
160 | *(.exitcall.exit) | ||
161 | } | ||
162 | .romfs : | ||
163 | { | ||
164 | *(.romfs*) | ||
165 | } | ||
166 | . = RAMTOP+RAMSIZE; | ||
167 | .dummy : | ||
168 | { | ||
169 | COMMAND_START = . - 0x200 ; | ||
170 | __ramend = . ; | ||
171 | } | ||
172 | } | ||
diff --git a/arch/h8300/lib/Makefile b/arch/h8300/lib/Makefile new file mode 100644 index 000000000000..98272b66f4e5 --- /dev/null +++ b/arch/h8300/lib/Makefile | |||
@@ -0,0 +1,8 @@ | |||
1 | # | ||
2 | # Makefile for H8/300-specific library files.. | ||
3 | # | ||
4 | |||
5 | .S.o: | ||
6 | $(CC) $(AFLAGS) -D__ASSEMBLY__ -c $< -o $@ | ||
7 | |||
8 | lib-y = ashrdi3.o checksum.o memcpy.o memset.o abs.o romfs.o | ||
diff --git a/arch/h8300/lib/abs.S b/arch/h8300/lib/abs.S new file mode 100644 index 000000000000..cabdd46b41db --- /dev/null +++ b/arch/h8300/lib/abs.S | |||
@@ -0,0 +1,21 @@ | |||
1 | ;;; abs.S | ||
2 | |||
3 | #include <asm/linkage.h> | ||
4 | |||
5 | #if defined(__H8300H__) | ||
6 | .h8300h | ||
7 | #endif | ||
8 | #if defined(__H8300S__) | ||
9 | .h8300s | ||
10 | #endif | ||
11 | .text | ||
12 | .global SYMBOL_NAME(abs) | ||
13 | |||
14 | ;;; int abs(int n) | ||
15 | SYMBOL_NAME_LABEL(abs) | ||
16 | mov.l er0,er0 | ||
17 | bpl 1f | ||
18 | neg.l er0 | ||
19 | 1: | ||
20 | rts | ||
21 | |||
diff --git a/arch/h8300/lib/ashrdi3.c b/arch/h8300/lib/ashrdi3.c new file mode 100644 index 000000000000..78efb65e315a --- /dev/null +++ b/arch/h8300/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 | |||
4 | This file is part of GNU CC. | ||
5 | |||
6 | GNU CC is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2, or (at your option) | ||
9 | any later version. | ||
10 | |||
11 | GNU CC is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with GNU CC; see the file COPYING. If not, write to | ||
18 | the Free Software Foundation, 59 Temple Place - Suite 330, | ||
19 | Boston, MA 02111-1307, USA. */ | ||
20 | |||
21 | #define BITS_PER_UNIT 8 | ||
22 | |||
23 | typedef int SItype __attribute__ ((mode (SI))); | ||
24 | typedef unsigned int USItype __attribute__ ((mode (SI))); | ||
25 | typedef int DItype __attribute__ ((mode (DI))); | ||
26 | typedef int word_type __attribute__ ((mode (__word__))); | ||
27 | |||
28 | struct DIstruct {SItype high, low;}; | ||
29 | |||
30 | typedef union | ||
31 | { | ||
32 | struct DIstruct s; | ||
33 | DItype ll; | ||
34 | } DIunion; | ||
35 | |||
36 | DItype | ||
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/h8300/lib/checksum.c b/arch/h8300/lib/checksum.c new file mode 100644 index 000000000000..5aa688d9242d --- /dev/null +++ b/arch/h8300/lib/checksum.c | |||
@@ -0,0 +1,159 @@ | |||
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 | * IP/TCP/UDP checksumming routines | ||
7 | * | ||
8 | * Authors: Jorge Cwik, <jorge@laser.satlink.net> | ||
9 | * Arnt Gulbrandsen, <agulbra@nvg.unit.no> | ||
10 | * Tom May, <ftom@netcom.com> | ||
11 | * Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de> | ||
12 | * Lots of code moved from tcp.c and ip.c; see those files | ||
13 | * for more names. | ||
14 | * | ||
15 | * 03/02/96 Jes Sorensen, Andreas Schwab, Roman Hodek: | ||
16 | * Fixed some nasty bugs, causing some horrible crashes. | ||
17 | * A: At some points, the sum (%0) was used as | ||
18 | * length-counter instead of the length counter | ||
19 | * (%1). Thanks to Roman Hodek for pointing this out. | ||
20 | * B: GCC seems to mess up if one uses too many | ||
21 | * data-registers to hold input values and one tries to | ||
22 | * specify d0 and d1 as scratch registers. Letting gcc choose these | ||
23 | * registers itself solves the problem. | ||
24 | * | ||
25 | * This program is free software; you can redistribute it and/or | ||
26 | * modify it under the terms of the GNU General Public License | ||
27 | * as published by the Free Software Foundation; either version | ||
28 | * 2 of the License, or (at your option) any later version. | ||
29 | */ | ||
30 | |||
31 | /* Revised by Kenneth Albanowski for m68knommu. Basic problem: unaligned access kills, so most | ||
32 | of the assembly has to go. */ | ||
33 | |||
34 | #include <net/checksum.h> | ||
35 | #include <linux/module.h> | ||
36 | |||
37 | static inline unsigned short from32to16(unsigned long x) | ||
38 | { | ||
39 | /* add up 16-bit and 16-bit for 16+c bit */ | ||
40 | x = (x & 0xffff) + (x >> 16); | ||
41 | /* add up carry.. */ | ||
42 | x = (x & 0xffff) + (x >> 16); | ||
43 | return x; | ||
44 | } | ||
45 | |||
46 | static unsigned long do_csum(const unsigned char * buff, int len) | ||
47 | { | ||
48 | int odd, count; | ||
49 | unsigned long result = 0; | ||
50 | |||
51 | if (len <= 0) | ||
52 | goto out; | ||
53 | odd = 1 & (unsigned long) buff; | ||
54 | if (odd) { | ||
55 | result = *buff; | ||
56 | len--; | ||
57 | buff++; | ||
58 | } | ||
59 | count = len >> 1; /* nr of 16-bit words.. */ | ||
60 | if (count) { | ||
61 | if (2 & (unsigned long) buff) { | ||
62 | result += *(unsigned short *) buff; | ||
63 | count--; | ||
64 | len -= 2; | ||
65 | buff += 2; | ||
66 | } | ||
67 | count >>= 1; /* nr of 32-bit words.. */ | ||
68 | if (count) { | ||
69 | unsigned long carry = 0; | ||
70 | do { | ||
71 | unsigned long w = *(unsigned long *) buff; | ||
72 | count--; | ||
73 | buff += 4; | ||
74 | result += carry; | ||
75 | result += w; | ||
76 | carry = (w > result); | ||
77 | } while (count); | ||
78 | result += carry; | ||
79 | result = (result & 0xffff) + (result >> 16); | ||
80 | } | ||
81 | if (len & 2) { | ||
82 | result += *(unsigned short *) buff; | ||
83 | buff += 2; | ||
84 | } | ||
85 | } | ||
86 | if (len & 1) | ||
87 | result += (*buff << 8); | ||
88 | result = from32to16(result); | ||
89 | if (odd) | ||
90 | result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); | ||
91 | out: | ||
92 | return result; | ||
93 | } | ||
94 | |||
95 | /* | ||
96 | * This is a version of ip_compute_csum() optimized for IP headers, | ||
97 | * which always checksum on 4 octet boundaries. | ||
98 | */ | ||
99 | unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl) | ||
100 | { | ||
101 | return ~do_csum(iph,ihl*4); | ||
102 | } | ||
103 | |||
104 | /* | ||
105 | * computes the checksum of a memory block at buff, length len, | ||
106 | * and adds in "sum" (32-bit) | ||
107 | * | ||
108 | * returns a 32-bit number suitable for feeding into itself | ||
109 | * or csum_tcpudp_magic | ||
110 | * | ||
111 | * this function must be called with even lengths, except | ||
112 | * for the last fragment, which may be odd | ||
113 | * | ||
114 | * it's best to have buff aligned on a 32-bit boundary | ||
115 | */ | ||
116 | unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum) | ||
117 | { | ||
118 | unsigned int result = do_csum(buff, len); | ||
119 | |||
120 | /* add in old sum, and carry.. */ | ||
121 | result += sum; | ||
122 | /* 16+c bits -> 16 bits */ | ||
123 | result = (result & 0xffff) + (result >> 16); | ||
124 | return result; | ||
125 | } | ||
126 | |||
127 | EXPORT_SYMBOL(csum_partial); | ||
128 | |||
129 | /* | ||
130 | * this routine is used for miscellaneous IP-like checksums, mainly | ||
131 | * in icmp.c | ||
132 | */ | ||
133 | unsigned short ip_compute_csum(const unsigned char * buff, int len) | ||
134 | { | ||
135 | return ~do_csum(buff,len); | ||
136 | } | ||
137 | |||
138 | /* | ||
139 | * copy from fs while checksumming, otherwise like csum_partial | ||
140 | */ | ||
141 | |||
142 | unsigned int | ||
143 | csum_partial_copy_from_user(const char *src, char *dst, int len, int sum, int *csum_err) | ||
144 | { | ||
145 | if (csum_err) *csum_err = 0; | ||
146 | memcpy(dst, src, len); | ||
147 | return csum_partial(dst, len, sum); | ||
148 | } | ||
149 | |||
150 | /* | ||
151 | * copy from ds while checksumming, otherwise like csum_partial | ||
152 | */ | ||
153 | |||
154 | unsigned int | ||
155 | csum_partial_copy(const char *src, char *dst, int len, int sum) | ||
156 | { | ||
157 | memcpy(dst, src, len); | ||
158 | return csum_partial(dst, len, sum); | ||
159 | } | ||
diff --git a/arch/h8300/lib/memcpy.S b/arch/h8300/lib/memcpy.S new file mode 100644 index 000000000000..fdcbc1ee673c --- /dev/null +++ b/arch/h8300/lib/memcpy.S | |||
@@ -0,0 +1,84 @@ | |||
1 | ;;; memcpy.S | ||
2 | |||
3 | #include <asm/linkage.h> | ||
4 | |||
5 | #if defined(__H8300H__) | ||
6 | .h8300h | ||
7 | #endif | ||
8 | #if defined(__H8300S__) | ||
9 | .h8300s | ||
10 | #endif | ||
11 | |||
12 | .text | ||
13 | .global SYMBOL_NAME(memcpy) | ||
14 | |||
15 | ;;; void *memcpy(void *to, void *from, size_t n) | ||
16 | SYMBOL_NAME_LABEL(memcpy) | ||
17 | mov.l er2,er2 | ||
18 | bne 1f | ||
19 | rts | ||
20 | 1: | ||
21 | ;; address check | ||
22 | bld #0,r0l | ||
23 | bxor #0,r1l | ||
24 | bcs 4f | ||
25 | mov.l er4,@-sp | ||
26 | mov.l er0,@-sp | ||
27 | btst #0,r0l | ||
28 | beq 1f | ||
29 | ;; (aligned even) odd address | ||
30 | mov.b @er1,r3l | ||
31 | mov.b r3l,@er0 | ||
32 | adds #1,er1 | ||
33 | adds #1,er0 | ||
34 | dec.l #1,er2 | ||
35 | beq 3f | ||
36 | 1: | ||
37 | ;; n < sizeof(unsigned long) check | ||
38 | sub.l er4,er4 | ||
39 | adds #4,er4 ; loop count check value | ||
40 | cmp.l er4,er2 | ||
41 | blo 2f | ||
42 | ;; unsigned long copy | ||
43 | 1: | ||
44 | mov.l @er1,er3 | ||
45 | mov.l er3,@er0 | ||
46 | adds #4,er0 | ||
47 | adds #4,er1 | ||
48 | subs #4,er2 | ||
49 | cmp.l er4,er2 | ||
50 | bcc 1b | ||
51 | ;; rest | ||
52 | 2: | ||
53 | mov.l er2,er2 | ||
54 | beq 3f | ||
55 | 1: | ||
56 | mov.b @er1,r3l | ||
57 | mov.b r3l,@er0 | ||
58 | adds #1,er1 | ||
59 | adds #1,er0 | ||
60 | dec.l #1,er2 | ||
61 | bne 1b | ||
62 | 3: | ||
63 | mov.l @sp+,er0 | ||
64 | mov.l @sp+,er4 | ||
65 | rts | ||
66 | |||
67 | ;; odd <- even / even <- odd | ||
68 | 4: | ||
69 | mov.l er4,er3 | ||
70 | mov.l er2,er4 | ||
71 | mov.l er5,er2 | ||
72 | mov.l er1,er5 | ||
73 | mov.l er6,er1 | ||
74 | mov.l er0,er6 | ||
75 | 1: | ||
76 | eepmov.w | ||
77 | mov.w r4,r4 | ||
78 | bne 1b | ||
79 | dec.w #1,e4 | ||
80 | bpl 1b | ||
81 | mov.l er1,er6 | ||
82 | mov.l er2,er5 | ||
83 | mov.l er3,er4 | ||
84 | rts | ||
diff --git a/arch/h8300/lib/memset.S b/arch/h8300/lib/memset.S new file mode 100644 index 000000000000..59abdf9485a5 --- /dev/null +++ b/arch/h8300/lib/memset.S | |||
@@ -0,0 +1,61 @@ | |||
1 | /* memset.S */ | ||
2 | |||
3 | #include <asm/linkage.h> | ||
4 | |||
5 | #if defined(__H8300H__) | ||
6 | .h8300h | ||
7 | #endif | ||
8 | #if defined(__H8300S__) | ||
9 | .h8300s | ||
10 | #endif | ||
11 | .text | ||
12 | |||
13 | .global SYMBOL_NAME(memset) | ||
14 | |||
15 | ;;void *memset(*ptr, int c, size_t count) | ||
16 | ;; ptr = er0 | ||
17 | ;; c = er1(r1l) | ||
18 | ;; count = er2 | ||
19 | SYMBOL_NAME_LABEL(memset) | ||
20 | btst #0,r0l | ||
21 | beq 2f | ||
22 | |||
23 | ;; odd address | ||
24 | 1: | ||
25 | mov.b r1l,@er0 | ||
26 | adds #1,er0 | ||
27 | dec.l #1,er2 | ||
28 | beq 6f | ||
29 | |||
30 | ;; even address | ||
31 | 2: | ||
32 | mov.l er2,er3 | ||
33 | cmp.l #4,er2 | ||
34 | blo 4f | ||
35 | ;; count>=4 -> count/4 | ||
36 | #if defined(__H8300H__) | ||
37 | shlr.l er2 | ||
38 | shlr.l er2 | ||
39 | #endif | ||
40 | #if defined(__H8300S__) | ||
41 | shlr.l #2,er2 | ||
42 | #endif | ||
43 | ;; byte -> long | ||
44 | mov.b r1l,r1h | ||
45 | mov.w r1,e1 | ||
46 | 3: | ||
47 | mov.l er1,@er0 | ||
48 | adds #4,er0 | ||
49 | dec.l #1,er2 | ||
50 | bne 3b | ||
51 | 4: | ||
52 | ;; count % 4 | ||
53 | and.b #3,r3l | ||
54 | beq 6f | ||
55 | 5: | ||
56 | mov.b r1l,@er0 | ||
57 | adds #1,er0 | ||
58 | dec.b r3l | ||
59 | bne 5b | ||
60 | 6: | ||
61 | rts | ||
diff --git a/arch/h8300/lib/romfs.S b/arch/h8300/lib/romfs.S new file mode 100644 index 000000000000..b72f93a47e31 --- /dev/null +++ b/arch/h8300/lib/romfs.S | |||
@@ -0,0 +1,58 @@ | |||
1 | /* romfs move to __ebss */ | ||
2 | |||
3 | #include <asm/linkage.h> | ||
4 | #include <linux/config.h> | ||
5 | |||
6 | #if defined(__H8300H__) | ||
7 | .h8300h | ||
8 | #endif | ||
9 | #if defined(__H8300S__) | ||
10 | .h8300s | ||
11 | #endif | ||
12 | |||
13 | #define BLKOFFSET 512 | ||
14 | |||
15 | .text | ||
16 | .globl __move_romfs | ||
17 | _romfs_sig_len = 8 | ||
18 | |||
19 | __move_romfs: | ||
20 | mov.l #__sbss,er0 | ||
21 | mov.l #_romfs_sig,er1 | ||
22 | mov.b #_romfs_sig_len,r3l | ||
23 | 1: /* check romfs image */ | ||
24 | mov.b @er0+,r2l | ||
25 | mov.b @er1+,r2h | ||
26 | cmp.b r2l,r2h | ||
27 | bne 2f | ||
28 | dec.b r3l | ||
29 | bne 1b | ||
30 | |||
31 | /* find romfs image */ | ||
32 | mov.l @__sbss+8,er0 /* romfs length(be) */ | ||
33 | mov.l #__sbss,er1 | ||
34 | add.l er0,er1 /* romfs image end */ | ||
35 | mov.l #__ebss,er2 | ||
36 | add.l er0,er2 /* distination address */ | ||
37 | #if defined(CONFIG_INTELFLASH) | ||
38 | add.l #BLKOFFSET,er2 | ||
39 | #endif | ||
40 | adds #2,er0 | ||
41 | adds #1,er0 | ||
42 | shlr er0 | ||
43 | shlr er0 /* transfer length */ | ||
44 | 1: | ||
45 | mov.l @er1,er3 /* copy image */ | ||
46 | mov.l er3,@er2 | ||
47 | subs #4,er1 | ||
48 | subs #4,er2 | ||
49 | dec.l #1,er0 | ||
50 | bpl 1b | ||
51 | 2: | ||
52 | rts | ||
53 | |||
54 | .section .rodata | ||
55 | _romfs_sig: | ||
56 | .ascii "-rom1fs-" | ||
57 | |||
58 | .end | ||
diff --git a/arch/h8300/mm/Makefile b/arch/h8300/mm/Makefile new file mode 100644 index 000000000000..5f4bc42b6453 --- /dev/null +++ b/arch/h8300/mm/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | # | ||
2 | # Makefile for the linux m68k-specific parts of the memory manager. | ||
3 | # | ||
4 | |||
5 | obj-y := init.o fault.o memory.o kmap.o | ||
diff --git a/arch/h8300/mm/fault.c b/arch/h8300/mm/fault.c new file mode 100644 index 000000000000..29e9af9f0e6a --- /dev/null +++ b/arch/h8300/mm/fault.c | |||
@@ -0,0 +1,58 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/mm/fault.c | ||
3 | * | ||
4 | * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>, | ||
5 | * Copyright (C) 2000 Lineo, Inc. (www.lineo.com) | ||
6 | * | ||
7 | * Based on: | ||
8 | * | ||
9 | * linux/arch/m68knommu/mm/fault.c | ||
10 | * linux/arch/m68k/mm/fault.c | ||
11 | * | ||
12 | * Copyright (C) 1995 Hamish Macdonald | ||
13 | */ | ||
14 | |||
15 | #include <linux/mman.h> | ||
16 | #include <linux/mm.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/ptrace.h> | ||
19 | |||
20 | #include <asm/system.h> | ||
21 | #include <asm/pgtable.h> | ||
22 | |||
23 | extern void die_if_kernel(char *, struct pt_regs *, long); | ||
24 | |||
25 | /* | ||
26 | * This routine handles page faults. It determines the problem, and | ||
27 | * then passes it off to one of the appropriate routines. | ||
28 | * | ||
29 | * error_code: | ||
30 | * bit 0 == 0 means no page found, 1 means protection fault | ||
31 | * bit 1 == 0 means read, 1 means write | ||
32 | * | ||
33 | * If this routine detects a bad access, it returns 1, otherwise it | ||
34 | * returns 0. | ||
35 | */ | ||
36 | asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address, | ||
37 | unsigned long error_code) | ||
38 | { | ||
39 | #ifdef DEBUG | ||
40 | printk ("regs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld\n", | ||
41 | regs->sr, regs->pc, address, error_code); | ||
42 | #endif | ||
43 | |||
44 | /* | ||
45 | * Oops. The kernel tried to access some bad page. We'll have to | ||
46 | * terminate things with extreme prejudice. | ||
47 | */ | ||
48 | if ((unsigned long) address < PAGE_SIZE) { | ||
49 | printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference"); | ||
50 | } else | ||
51 | printk(KERN_ALERT "Unable to handle kernel access"); | ||
52 | printk(" at virtual address %08lx\n",address); | ||
53 | die_if_kernel("Oops", regs, error_code); | ||
54 | do_exit(SIGKILL); | ||
55 | |||
56 | return 1; | ||
57 | } | ||
58 | |||
diff --git a/arch/h8300/mm/init.c b/arch/h8300/mm/init.c new file mode 100644 index 000000000000..1e0929ddc8c4 --- /dev/null +++ b/arch/h8300/mm/init.c | |||
@@ -0,0 +1,232 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/mm/init.c | ||
3 | * | ||
4 | * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>, | ||
5 | * Kenneth Albanowski <kjahds@kjahds.com>, | ||
6 | * Copyright (C) 2000 Lineo, Inc. (www.lineo.com) | ||
7 | * | ||
8 | * Based on: | ||
9 | * | ||
10 | * linux/arch/m68knommu/mm/init.c | ||
11 | * linux/arch/m68k/mm/init.c | ||
12 | * | ||
13 | * Copyright (C) 1995 Hamish Macdonald | ||
14 | * | ||
15 | * JAN/1999 -- hacked to support ColdFire (gerg@snapgear.com) | ||
16 | * DEC/2000 -- linux 2.4 support <davidm@snapgear.com> | ||
17 | */ | ||
18 | |||
19 | #include <linux/config.h> | ||
20 | #include <linux/signal.h> | ||
21 | #include <linux/sched.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/errno.h> | ||
24 | #include <linux/string.h> | ||
25 | #include <linux/types.h> | ||
26 | #include <linux/ptrace.h> | ||
27 | #include <linux/mman.h> | ||
28 | #include <linux/mm.h> | ||
29 | #include <linux/swap.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/highmem.h> | ||
32 | #include <linux/pagemap.h> | ||
33 | #include <linux/bootmem.h> | ||
34 | #include <linux/slab.h> | ||
35 | |||
36 | #include <asm/setup.h> | ||
37 | #include <asm/segment.h> | ||
38 | #include <asm/page.h> | ||
39 | #include <asm/pgtable.h> | ||
40 | #include <asm/system.h> | ||
41 | |||
42 | #undef DEBUG | ||
43 | |||
44 | extern void die_if_kernel(char *,struct pt_regs *,long); | ||
45 | extern void free_initmem(void); | ||
46 | |||
47 | /* | ||
48 | * BAD_PAGE is the page that is used for page faults when linux | ||
49 | * is out-of-memory. Older versions of linux just did a | ||
50 | * do_exit(), but using this instead means there is less risk | ||
51 | * for a process dying in kernel mode, possibly leaving a inode | ||
52 | * unused etc.. | ||
53 | * | ||
54 | * BAD_PAGETABLE is the accompanying page-table: it is initialized | ||
55 | * to point to BAD_PAGE entries. | ||
56 | * | ||
57 | * ZERO_PAGE is a special page that is used for zero-initialized | ||
58 | * data and COW. | ||
59 | */ | ||
60 | static unsigned long empty_bad_page_table; | ||
61 | |||
62 | static unsigned long empty_bad_page; | ||
63 | |||
64 | unsigned long empty_zero_page; | ||
65 | |||
66 | extern unsigned long rom_length; | ||
67 | |||
68 | void show_mem(void) | ||
69 | { | ||
70 | unsigned long i; | ||
71 | int free = 0, total = 0, reserved = 0, shared = 0; | ||
72 | int cached = 0; | ||
73 | |||
74 | printk("\nMem-info:\n"); | ||
75 | show_free_areas(); | ||
76 | i = max_mapnr; | ||
77 | while (i-- > 0) { | ||
78 | total++; | ||
79 | if (PageReserved(mem_map+i)) | ||
80 | reserved++; | ||
81 | else if (PageSwapCache(mem_map+i)) | ||
82 | cached++; | ||
83 | else if (!page_count(mem_map+i)) | ||
84 | free++; | ||
85 | else | ||
86 | shared += page_count(mem_map+i) - 1; | ||
87 | } | ||
88 | printk("%d pages of RAM\n",total); | ||
89 | printk("%d free pages\n",free); | ||
90 | printk("%d reserved pages\n",reserved); | ||
91 | printk("%d pages shared\n",shared); | ||
92 | printk("%d pages swap cached\n",cached); | ||
93 | } | ||
94 | |||
95 | extern unsigned long memory_start; | ||
96 | extern unsigned long memory_end; | ||
97 | |||
98 | /* | ||
99 | * paging_init() continues the virtual memory environment setup which | ||
100 | * was begun by the code in arch/head.S. | ||
101 | * The parameters are pointers to where to stick the starting and ending | ||
102 | * addresses of available kernel virtual memory. | ||
103 | */ | ||
104 | void paging_init(void) | ||
105 | { | ||
106 | /* | ||
107 | * Make sure start_mem is page aligned, otherwise bootmem and | ||
108 | * page_alloc get different views og the world. | ||
109 | */ | ||
110 | #ifdef DEBUG | ||
111 | unsigned long start_mem = PAGE_ALIGN(memory_start); | ||
112 | #endif | ||
113 | unsigned long end_mem = memory_end & PAGE_MASK; | ||
114 | |||
115 | #ifdef DEBUG | ||
116 | printk ("start_mem is %#lx\nvirtual_end is %#lx\n", | ||
117 | start_mem, end_mem); | ||
118 | #endif | ||
119 | |||
120 | /* | ||
121 | * Initialize the bad page table and bad page to point | ||
122 | * to a couple of allocated pages. | ||
123 | */ | ||
124 | empty_bad_page_table = (unsigned long)alloc_bootmem_pages(PAGE_SIZE); | ||
125 | empty_bad_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE); | ||
126 | empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE); | ||
127 | memset((void *)empty_zero_page, 0, PAGE_SIZE); | ||
128 | |||
129 | /* | ||
130 | * Set up SFC/DFC registers (user data space). | ||
131 | */ | ||
132 | set_fs (USER_DS); | ||
133 | |||
134 | #ifdef DEBUG | ||
135 | printk ("before free_area_init\n"); | ||
136 | |||
137 | printk ("free_area_init -> start_mem is %#lx\nvirtual_end is %#lx\n", | ||
138 | start_mem, end_mem); | ||
139 | #endif | ||
140 | |||
141 | { | ||
142 | unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; | ||
143 | |||
144 | zones_size[ZONE_DMA] = 0 >> PAGE_SHIFT; | ||
145 | zones_size[ZONE_NORMAL] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT; | ||
146 | #ifdef CONFIG_HIGHMEM | ||
147 | zones_size[ZONE_HIGHMEM] = 0; | ||
148 | #endif | ||
149 | free_area_init(zones_size); | ||
150 | } | ||
151 | } | ||
152 | |||
153 | void mem_init(void) | ||
154 | { | ||
155 | int codek = 0, datak = 0, initk = 0; | ||
156 | /* DAVIDM look at setup memory map generically with reserved area */ | ||
157 | unsigned long tmp; | ||
158 | extern char _etext, _stext, _sdata, _ebss, __init_begin, __init_end; | ||
159 | extern unsigned long _ramend, _ramstart; | ||
160 | unsigned long len = &_ramend - &_ramstart; | ||
161 | unsigned long start_mem = memory_start; /* DAVIDM - these must start at end of kernel */ | ||
162 | unsigned long end_mem = memory_end; /* DAVIDM - this must not include kernel stack at top */ | ||
163 | |||
164 | #ifdef DEBUG | ||
165 | printk(KERN_DEBUG "Mem_init: start=%lx, end=%lx\n", start_mem, end_mem); | ||
166 | #endif | ||
167 | |||
168 | end_mem &= PAGE_MASK; | ||
169 | high_memory = (void *) end_mem; | ||
170 | |||
171 | start_mem = PAGE_ALIGN(start_mem); | ||
172 | max_mapnr = num_physpages = MAP_NR(high_memory); | ||
173 | |||
174 | /* this will put all memory onto the freelists */ | ||
175 | totalram_pages = free_all_bootmem(); | ||
176 | |||
177 | codek = (&_etext - &_stext) >> 10; | ||
178 | datak = (&_ebss - &_sdata) >> 10; | ||
179 | initk = (&__init_begin - &__init_end) >> 10; | ||
180 | |||
181 | tmp = nr_free_pages() << PAGE_SHIFT; | ||
182 | printk(KERN_INFO "Memory available: %luk/%luk RAM, %luk/%luk ROM (%dk kernel code, %dk data)\n", | ||
183 | tmp >> 10, | ||
184 | len >> 10, | ||
185 | (rom_length > 0) ? ((rom_length >> 10) - codek) : 0, | ||
186 | rom_length >> 10, | ||
187 | codek, | ||
188 | datak | ||
189 | ); | ||
190 | } | ||
191 | |||
192 | |||
193 | #ifdef CONFIG_BLK_DEV_INITRD | ||
194 | void free_initrd_mem(unsigned long start, unsigned long end) | ||
195 | { | ||
196 | int pages = 0; | ||
197 | for (; start < end; start += PAGE_SIZE) { | ||
198 | ClearPageReserved(virt_to_page(start)); | ||
199 | set_page_count(virt_to_page(start), 1); | ||
200 | free_page(start); | ||
201 | totalram_pages++; | ||
202 | pages++; | ||
203 | } | ||
204 | printk ("Freeing initrd memory: %dk freed\n", pages); | ||
205 | } | ||
206 | #endif | ||
207 | |||
208 | void | ||
209 | free_initmem() | ||
210 | { | ||
211 | #ifdef CONFIG_RAMKERNEL | ||
212 | unsigned long addr; | ||
213 | extern char __init_begin, __init_end; | ||
214 | /* | ||
215 | * the following code should be cool even if these sections | ||
216 | * are not page aligned. | ||
217 | */ | ||
218 | addr = PAGE_ALIGN((unsigned long)(&__init_begin)); | ||
219 | /* next to check that the page we free is not a partial page */ | ||
220 | for (; addr + PAGE_SIZE < (unsigned long)(&__init_end); addr +=PAGE_SIZE) { | ||
221 | ClearPageReserved(virt_to_page(addr)); | ||
222 | set_page_count(virt_to_page(addr), 1); | ||
223 | free_page(addr); | ||
224 | totalram_pages++; | ||
225 | } | ||
226 | printk(KERN_INFO "Freeing unused kernel memory: %ldk freed (0x%x - 0x%x)\n", | ||
227 | (addr - PAGE_ALIGN((long) &__init_begin)) >> 10, | ||
228 | (int)(PAGE_ALIGN((unsigned long)(&__init_begin))), | ||
229 | (int)(addr - PAGE_SIZE)); | ||
230 | #endif | ||
231 | } | ||
232 | |||
diff --git a/arch/h8300/mm/kmap.c b/arch/h8300/mm/kmap.c new file mode 100644 index 000000000000..4101ab54fc17 --- /dev/null +++ b/arch/h8300/mm/kmap.c | |||
@@ -0,0 +1,59 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/mm/kmap.c | ||
3 | * | ||
4 | * Based on | ||
5 | * linux/arch/m68knommu/mm/kmap.c | ||
6 | * | ||
7 | * Copyright (C) 2000 Lineo, <davidm@snapgear.com> | ||
8 | * Copyright (C) 2000-2002 David McCullough <davidm@snapgear.com> | ||
9 | */ | ||
10 | |||
11 | #include <linux/config.h> | ||
12 | #include <linux/mm.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/string.h> | ||
15 | #include <linux/types.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/vmalloc.h> | ||
18 | |||
19 | #include <asm/setup.h> | ||
20 | #include <asm/segment.h> | ||
21 | #include <asm/page.h> | ||
22 | #include <asm/pgalloc.h> | ||
23 | #include <asm/io.h> | ||
24 | #include <asm/system.h> | ||
25 | |||
26 | #undef DEBUG | ||
27 | |||
28 | /* | ||
29 | * Map some physical address range into the kernel address space. | ||
30 | */ | ||
31 | void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag) | ||
32 | { | ||
33 | return (void *)physaddr; | ||
34 | } | ||
35 | |||
36 | /* | ||
37 | * Unmap a ioremap()ed region again. | ||
38 | */ | ||
39 | void iounmap(void *addr) | ||
40 | { | ||
41 | } | ||
42 | |||
43 | /* | ||
44 | * __iounmap unmaps nearly everything, so be careful | ||
45 | * it doesn't free currently pointer/page tables anymore but it | ||
46 | * wans't used anyway and might be added later. | ||
47 | */ | ||
48 | void __iounmap(void *addr, unsigned long size) | ||
49 | { | ||
50 | } | ||
51 | |||
52 | /* | ||
53 | * Set new cache mode for some kernel address space. | ||
54 | * The caller must push data for that range itself, if such data may already | ||
55 | * be in the cache. | ||
56 | */ | ||
57 | void kernel_set_cachemode(void *addr, unsigned long size, int cmode) | ||
58 | { | ||
59 | } | ||
diff --git a/arch/h8300/mm/memory.c b/arch/h8300/mm/memory.c new file mode 100644 index 000000000000..f4ddece3216f --- /dev/null +++ b/arch/h8300/mm/memory.c | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/mm/memory.c | ||
3 | * | ||
4 | * Copyright (C) 2002 Yoshinori Sato <ysato@users.sourceforge.jp>, | ||
5 | * | ||
6 | * Based on: | ||
7 | * | ||
8 | * linux/arch/m68knommu/mm/memory.c | ||
9 | * | ||
10 | * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>, | ||
11 | * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com) | ||
12 | * | ||
13 | * Based on: | ||
14 | * | ||
15 | * linux/arch/m68k/mm/memory.c | ||
16 | * | ||
17 | * Copyright (C) 1995 Hamish Macdonald | ||
18 | */ | ||
19 | |||
20 | #include <linux/config.h> | ||
21 | #include <linux/mm.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/string.h> | ||
24 | #include <linux/types.h> | ||
25 | #include <linux/slab.h> | ||
26 | |||
27 | #include <asm/setup.h> | ||
28 | #include <asm/segment.h> | ||
29 | #include <asm/page.h> | ||
30 | #include <asm/pgtable.h> | ||
31 | #include <asm/system.h> | ||
32 | #include <asm/traps.h> | ||
33 | #include <asm/io.h> | ||
34 | |||
35 | void cache_clear (unsigned long paddr, int len) | ||
36 | { | ||
37 | } | ||
38 | |||
39 | |||
40 | void cache_push (unsigned long paddr, int len) | ||
41 | { | ||
42 | } | ||
43 | |||
44 | void cache_push_v (unsigned long vaddr, int len) | ||
45 | { | ||
46 | } | ||
47 | |||
48 | /* Map some physical address range into the kernel address space. The | ||
49 | * code is copied and adapted from map_chunk(). | ||
50 | */ | ||
51 | |||
52 | unsigned long kernel_map(unsigned long paddr, unsigned long size, | ||
53 | int nocacheflag, unsigned long *memavailp ) | ||
54 | { | ||
55 | return paddr; | ||
56 | } | ||
57 | |||
58 | #ifdef MAGIC_ROM_PTR | ||
59 | |||
60 | int is_in_rom(unsigned long addr) | ||
61 | { | ||
62 | /* Anything not in operational RAM is returned as in rom! */ | ||
63 | if (addr < _ramstart || addr >= _ramend) | ||
64 | return 1; | ||
65 | else | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | #endif | ||
70 | |||
diff --git a/arch/h8300/platform/h8300h/Makefile b/arch/h8300/platform/h8300h/Makefile new file mode 100644 index 000000000000..5d42c772f75a --- /dev/null +++ b/arch/h8300/platform/h8300h/Makefile | |||
@@ -0,0 +1,7 @@ | |||
1 | # | ||
2 | # Makefile for the linux kernel. | ||
3 | # | ||
4 | # Reuse any files we can from the H8/300H | ||
5 | # | ||
6 | |||
7 | obj-y := entry.o ints_h8300h.o ptrace_h8300h.o | ||
diff --git a/arch/h8300/platform/h8300h/aki3068net/Makefile b/arch/h8300/platform/h8300h/aki3068net/Makefile new file mode 100644 index 000000000000..b03c328f8c70 --- /dev/null +++ b/arch/h8300/platform/h8300h/aki3068net/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | # | ||
2 | # Makefile for the linux kernel. | ||
3 | # | ||
4 | |||
5 | extra-y := crt0_ram.o | ||
6 | obj-y := timer.o | ||
diff --git a/arch/h8300/platform/h8300h/aki3068net/crt0_ram.S b/arch/h8300/platform/h8300h/aki3068net/crt0_ram.S new file mode 100644 index 000000000000..31c3703d8d60 --- /dev/null +++ b/arch/h8300/platform/h8300h/aki3068net/crt0_ram.S | |||
@@ -0,0 +1,111 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/platform/h8300h/aki3068net/crt0_ram.S | ||
3 | * | ||
4 | * Yoshinori Sato <ysato@users.sourceforge.jp> | ||
5 | * | ||
6 | * Platform depend startup | ||
7 | * Target Archtecture: AE-3068 (aka. aki3068net) | ||
8 | * Memory Layout : RAM | ||
9 | */ | ||
10 | |||
11 | #define ASSEMBLY | ||
12 | |||
13 | #include <linux/config.h> | ||
14 | #include <asm/linkage.h> | ||
15 | |||
16 | #if !defined(CONFIG_BLKDEV_RESERVE) | ||
17 | #if defined(CONFIG_GDB_DEBUG) | ||
18 | #define RAMEND (__ramend - 0xc000) | ||
19 | #else | ||
20 | #define RAMEND __ramend | ||
21 | #endif | ||
22 | #else | ||
23 | #define RAMEND CONFIG_BLKDEV_RESERVE_ADDRESS | ||
24 | #endif | ||
25 | |||
26 | .global SYMBOL_NAME(_start) | ||
27 | .global SYMBOL_NAME(command_line) | ||
28 | .global SYMBOL_NAME(_platform_gpio_table) | ||
29 | .global SYMBOL_NAME(_target_name) | ||
30 | |||
31 | .h8300h | ||
32 | |||
33 | .section .text | ||
34 | .file "crt0_ram.S" | ||
35 | |||
36 | /* CPU Reset entry */ | ||
37 | SYMBOL_NAME_LABEL(_start) | ||
38 | mov.l #RAMEND,sp | ||
39 | ldc #0x80,ccr | ||
40 | |||
41 | /* Peripheral Setup */ | ||
42 | |||
43 | #if defined(CONFIG_MTD_UCLINUX) | ||
44 | /* move romfs image */ | ||
45 | jsr @__move_romfs | ||
46 | #endif | ||
47 | |||
48 | /* .bss clear */ | ||
49 | mov.l #__sbss,er5 | ||
50 | mov.l #__ebss,er4 | ||
51 | sub.l er5,er4 | ||
52 | shlr er4 | ||
53 | shlr er4 | ||
54 | sub.l er0,er0 | ||
55 | 1: | ||
56 | mov.l er0,@er5 | ||
57 | adds #4,er5 | ||
58 | dec.l #1,er4 | ||
59 | bne 1b | ||
60 | |||
61 | /* copy kernel commandline */ | ||
62 | mov.l #COMMAND_START,er5 | ||
63 | mov.l #SYMBOL_NAME(command_line),er6 | ||
64 | mov.w #512,r4 | ||
65 | eepmov.w | ||
66 | |||
67 | /* uClinux kernel start */ | ||
68 | ldc #0x90,ccr /* running kernel */ | ||
69 | mov.l #SYMBOL_NAME(init_thread_union),sp | ||
70 | add.l #0x2000,sp | ||
71 | jsr @_start_kernel | ||
72 | _exit: | ||
73 | |||
74 | jmp _exit | ||
75 | |||
76 | rts | ||
77 | |||
78 | /* I/O port assign information */ | ||
79 | __platform_gpio_table: | ||
80 | mov.l #gpio_table,er0 | ||
81 | rts | ||
82 | |||
83 | gpio_table: | ||
84 | ;; P1DDR | ||
85 | .byte 0xff,0xff | ||
86 | ;; P2DDR | ||
87 | .byte 0xff,0xff | ||
88 | ;; P3DDR | ||
89 | .byte 0xff,0x00 | ||
90 | ;; P4DDR | ||
91 | .byte 0x00,0x00 | ||
92 | ;; P5DDR | ||
93 | .byte 0x01,0x01 | ||
94 | ;; P6DDR | ||
95 | .byte 0x00,0x00 | ||
96 | ;; dummy | ||
97 | .byte 0x00,0x00 | ||
98 | ;; P8DDR | ||
99 | .byte 0x0c,0x0c | ||
100 | ;; P9DDR | ||
101 | .byte 0x00,0x00 | ||
102 | ;; PADDR | ||
103 | .byte 0x00,0x00 | ||
104 | ;; PBDDR | ||
105 | .byte 0x30,0x30 | ||
106 | |||
107 | __target_name: | ||
108 | .asciz "AE-3068" | ||
109 | |||
110 | .section .bootvec,"ax" | ||
111 | jmp @SYMBOL_NAME(_start) | ||
diff --git a/arch/h8300/platform/h8300h/aki3068net/timer.c b/arch/h8300/platform/h8300h/aki3068net/timer.c new file mode 100644 index 000000000000..086efb1fd283 --- /dev/null +++ b/arch/h8300/platform/h8300h/aki3068net/timer.c | |||
@@ -0,0 +1,52 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/platform/h8300h/aki3068net/timer.c | ||
3 | * | ||
4 | * Yoshinori Sato <ysato@users.sourcefoge.jp> | ||
5 | * | ||
6 | * Platform depend Timer Handler | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #include <linux/config.h> | ||
11 | #include <linux/errno.h> | ||
12 | #include <linux/sched.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/param.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <linux/mm.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/timex.h> | ||
20 | |||
21 | #include <asm/segment.h> | ||
22 | #include <asm/io.h> | ||
23 | #include <asm/irq.h> | ||
24 | #include <asm/regs306x.h> | ||
25 | |||
26 | #define CMFA 6 | ||
27 | |||
28 | #define CMIEA 0x40 | ||
29 | #define CCLR_CMA 0x08 | ||
30 | #define CLK_DIV8192 0x03 | ||
31 | |||
32 | #define H8300_TIMER_FREQ CONFIG_CPU_CLOCK*1000/8192 /* Timer input freq. */ | ||
33 | |||
34 | void __init platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *)) | ||
35 | { | ||
36 | /* setup 8bit timer ch2 */ | ||
37 | ctrl_outb(H8300_TIMER_FREQ / HZ, TCORA2); /* set interval */ | ||
38 | ctrl_outb(0x00, _8TCSR2); /* no output */ | ||
39 | request_irq(40, timer_int, 0, "timer", 0); | ||
40 | ctrl_outb(CMIEA|CCLR_CMA|CLK_DIV8192, _8TCR2); /* start count */ | ||
41 | } | ||
42 | |||
43 | void platform_timer_eoi(void) | ||
44 | { | ||
45 | *(volatile unsigned char *)_8TCSR2 &= ~(1 << CMFA); | ||
46 | } | ||
47 | |||
48 | void platform_gettod(int *year, int *mon, int *day, int *hour, | ||
49 | int *min, int *sec) | ||
50 | { | ||
51 | *year = *mon = *day = *hour = *min = *sec = 0; | ||
52 | } | ||
diff --git a/arch/h8300/platform/h8300h/entry.S b/arch/h8300/platform/h8300h/entry.S new file mode 100644 index 000000000000..2052dbb9483f --- /dev/null +++ b/arch/h8300/platform/h8300h/entry.S | |||
@@ -0,0 +1,333 @@ | |||
1 | /* -*- mode: asm -*- | ||
2 | * | ||
3 | * linux/arch/h8300/platform/h8300h/entry.S | ||
4 | * | ||
5 | * Yoshinori Sato <ysato@users.sourceforge.jp> | ||
6 | * David McCullough <davidm@snapgear.com> | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * entry.S | ||
12 | * include exception/interrupt gateway | ||
13 | * system call entry | ||
14 | */ | ||
15 | |||
16 | #include <linux/sys.h> | ||
17 | #include <linux/config.h> | ||
18 | #include <asm/unistd.h> | ||
19 | #include <asm/setup.h> | ||
20 | #include <asm/segment.h> | ||
21 | #include <asm/linkage.h> | ||
22 | #include <asm/asm-offsets.h> | ||
23 | #include <asm/thread_info.h> | ||
24 | #include <asm/errno.h> | ||
25 | |||
26 | .h8300h | ||
27 | |||
28 | /* CPU context save/restore macros. */ | ||
29 | |||
30 | .macro SAVE_ALL | ||
31 | mov.l er0,@-sp | ||
32 | |||
33 | stc ccr,r0l /* check kernel mode */ | ||
34 | orc #0x10,ccr | ||
35 | btst #4,r0l | ||
36 | bne 5f | ||
37 | |||
38 | mov.l sp,@SYMBOL_NAME(sw_usp) /* user mode */ | ||
39 | mov.l @sp,er0 | ||
40 | mov.l @SYMBOL_NAME(sw_ksp),sp | ||
41 | sub.l #(LRET-LORIG),sp /* allocate LORIG - LRET */ | ||
42 | mov.l er0,@-sp | ||
43 | mov.l er1,@-sp | ||
44 | mov.l @SYMBOL_NAME(sw_usp),er0 | ||
45 | mov.l @(8:16,er0),er1 /* copy the RET addr */ | ||
46 | mov.l er1,@(LRET-LER1:16,sp) | ||
47 | |||
48 | mov.w e1,r1 /* e1 highbyte = ccr */ | ||
49 | and #0xef,r1h /* mask mode? flag */ | ||
50 | sub.w r0,r0 | ||
51 | mov.b r1h,r0l | ||
52 | mov.w r0,@(LCCR-LER1:16,sp) /* copy ccr */ | ||
53 | mov.l @(LORIG-LER1:16,sp),er0 | ||
54 | mov.l er0,@(LER0-LER1:16,sp) /* copy ER0 */ | ||
55 | bra 6f | ||
56 | 5: | ||
57 | mov.l @sp,er0 /* kernel mode */ | ||
58 | subs #2,sp /* dummy ccr */ | ||
59 | mov.l er0,@-sp | ||
60 | mov.l er1,@-sp | ||
61 | mov.w @(LRET-LER1:16,sp),r1 /* copy old ccr */ | ||
62 | mov.b r1h,r1l | ||
63 | mov.b #0,r1h | ||
64 | mov.w r1,@(LCCR-LER1:16,sp) /* set ccr */ | ||
65 | 6: | ||
66 | mov.l er2,@-sp | ||
67 | mov.l er3,@-sp | ||
68 | mov.l er6,@-sp /* syscall arg #6 */ | ||
69 | mov.l er5,@-sp /* syscall arg #5 */ | ||
70 | mov.l er4,@-sp /* syscall arg #4 */ | ||
71 | .endm | ||
72 | |||
73 | .macro RESTORE_ALL | ||
74 | mov.l @sp+,er4 | ||
75 | mov.l @sp+,er5 | ||
76 | mov.l @sp+,er6 | ||
77 | mov.l @sp+,er3 | ||
78 | mov.l @sp+,er2 | ||
79 | mov.w @(LCCR-LER1:16,sp),r0 /* check kernel mode */ | ||
80 | btst #4,r0l | ||
81 | bne 7f | ||
82 | |||
83 | orc #0x80,ccr | ||
84 | mov.l @SYMBOL_NAME(sw_usp),er0 | ||
85 | mov.l @(LER0-LER1:16,sp),er1 /* restore ER0 */ | ||
86 | mov.l er1,@er0 | ||
87 | mov.w @(LCCR-LER1:16,sp),r1 /* restore the RET addr */ | ||
88 | mov.b r1l,r1h | ||
89 | mov.b @(LRET+1-LER1:16,sp),r1l | ||
90 | mov.w r1,e1 | ||
91 | mov.w @(LRET+2-LER1:16,sp),r1 | ||
92 | mov.l er1,@(8:16,er0) | ||
93 | |||
94 | mov.l @sp+,er1 | ||
95 | add.l #(LRET-LER1),sp /* remove LORIG - LRET */ | ||
96 | mov.l sp,@SYMBOL_NAME(sw_ksp) | ||
97 | mov.l er0,sp | ||
98 | bra 8f | ||
99 | 7: | ||
100 | mov.l @sp+,er1 | ||
101 | adds #4,sp | ||
102 | adds #2,sp | ||
103 | 8: | ||
104 | mov.l @sp+,er0 | ||
105 | adds #4,sp /* remove the sw created LVEC */ | ||
106 | rte | ||
107 | .endm | ||
108 | |||
109 | .globl SYMBOL_NAME(system_call) | ||
110 | .globl SYMBOL_NAME(ret_from_exception) | ||
111 | .globl SYMBOL_NAME(ret_from_fork) | ||
112 | .globl SYMBOL_NAME(ret_from_interrupt) | ||
113 | .globl SYMBOL_NAME(interrupt_redirect_table) | ||
114 | .globl SYMBOL_NAME(sw_ksp),SYMBOL_NAME(sw_usp) | ||
115 | .globl SYMBOL_NAME(resume) | ||
116 | .globl SYMBOL_NAME(interrupt_redirect_table) | ||
117 | .globl SYMBOL_NAME(interrupt_entry) | ||
118 | .globl SYMBOL_NAME(system_call) | ||
119 | .globl SYMBOL_NAME(trace_break) | ||
120 | |||
121 | #if defined(CONFIG_ROMKERNEL) | ||
122 | INTERRUPTS = 64 | ||
123 | .section .int_redirect,"ax" | ||
124 | SYMBOL_NAME_LABEL(interrupt_redirect_table) | ||
125 | .rept 7 | ||
126 | .long 0 | ||
127 | .endr | ||
128 | jsr @SYMBOL_NAME(interrupt_entry) /* NMI */ | ||
129 | jmp @SYMBOL_NAME(system_call) /* TRAPA #0 (System call) */ | ||
130 | .long 0 | ||
131 | .long 0 | ||
132 | jmp @SYMBOL_NAME(trace_break) /* TRAPA #3 (breakpoint) */ | ||
133 | .rept INTERRUPTS-12 | ||
134 | jsr @SYMBOL_NAME(interrupt_entry) | ||
135 | .endr | ||
136 | #endif | ||
137 | #if defined(CONFIG_RAMKERNEL) | ||
138 | .globl SYMBOL_NAME(interrupt_redirect_table) | ||
139 | .section .bss | ||
140 | SYMBOL_NAME_LABEL(interrupt_redirect_table) | ||
141 | .space 4 | ||
142 | #endif | ||
143 | |||
144 | .section .text | ||
145 | .align 2 | ||
146 | SYMBOL_NAME_LABEL(interrupt_entry) | ||
147 | SAVE_ALL | ||
148 | mov.w @(LCCR,sp),r0 | ||
149 | btst #4,r0l | ||
150 | bne 1f | ||
151 | mov.l @SYMBOL_NAME(sw_usp),er0 | ||
152 | mov.l @(4:16,er0),er0 | ||
153 | bra 2f | ||
154 | 1: | ||
155 | mov.l @(LVEC,sp),er0 | ||
156 | 2: | ||
157 | #if defined(CONFIG_ROMKERNEL) | ||
158 | sub.l #SYMBOL_NAME(interrupt_redirect_table),er0 | ||
159 | #endif | ||
160 | #if defined(CONFIG_RAMKERNEL) | ||
161 | mov.l @SYMBOL_NAME(interrupt_redirect_table),er1 | ||
162 | sub.l er1,er0 | ||
163 | #endif | ||
164 | shlr.l er0 | ||
165 | shlr.l er0 | ||
166 | dec.l #1,er0 | ||
167 | mov.l sp,er1 | ||
168 | subs #4,er1 /* adjust ret_pc */ | ||
169 | jsr @SYMBOL_NAME(process_int) | ||
170 | mov.l @SYMBOL_NAME(irq_stat)+CPUSTAT_SOFTIRQ_PENDING,er0 | ||
171 | beq 1f | ||
172 | jsr @SYMBOL_NAME(do_softirq) | ||
173 | 1: | ||
174 | jmp @SYMBOL_NAME(ret_from_interrupt) | ||
175 | |||
176 | SYMBOL_NAME_LABEL(system_call) | ||
177 | subs #4,sp /* dummy LVEC */ | ||
178 | SAVE_ALL | ||
179 | mov.w @(LCCR:16,sp),r1 | ||
180 | bset #4,r1l | ||
181 | ldc r1l,ccr | ||
182 | mov.l er0,er4 | ||
183 | mov.l #-ENOSYS,er0 | ||
184 | mov.l er0,@(LER0:16,sp) | ||
185 | |||
186 | /* save top of frame */ | ||
187 | mov.l sp,er0 | ||
188 | jsr @SYMBOL_NAME(set_esp0) | ||
189 | cmp.l #NR_syscalls,er4 | ||
190 | bcc SYMBOL_NAME(ret_from_exception):16 | ||
191 | shll.l er4 | ||
192 | shll.l er4 | ||
193 | mov.l #SYMBOL_NAME(sys_call_table),er0 | ||
194 | add.l er4,er0 | ||
195 | mov.l @er0,er4 | ||
196 | beq SYMBOL_NAME(ret_from_exception):16 | ||
197 | mov.l sp,er2 | ||
198 | and.w #0xe000,r2 | ||
199 | mov.b @((TASK_FLAGS+3-(TIF_SYSCALL_TRACE >> 3)):16,er2),r2l | ||
200 | btst #(TIF_SYSCALL_TRACE & 7),r2l | ||
201 | bne 1f | ||
202 | mov.l @(LER1:16,sp),er0 | ||
203 | mov.l @(LER2:16,sp),er1 | ||
204 | mov.l @(LER3:16,sp),er2 | ||
205 | jsr @er4 | ||
206 | mov.l er0,@(LER0:16,sp) /* save the return value */ | ||
207 | #if defined(CONFIG_SYSCALL_PRINT) | ||
208 | jsr @SYMBOL_NAME(syscall_print) | ||
209 | #endif | ||
210 | bra SYMBOL_NAME(ret_from_exception):8 | ||
211 | 1: | ||
212 | jsr SYMBOL_NAME(syscall_trace) | ||
213 | mov.l @(LER1:16,sp),er0 | ||
214 | mov.l @(LER2:16,sp),er1 | ||
215 | mov.l @(LER3:16,sp),er2 | ||
216 | jsr @er4 | ||
217 | mov.l er0,@(LER0:16,sp) /* save the return value */ | ||
218 | jsr @SYMBOL_NAME(syscall_trace) | ||
219 | bra SYMBOL_NAME(ret_from_exception):8 | ||
220 | |||
221 | SYMBOL_NAME_LABEL(ret_from_fork) | ||
222 | mov.l er2,er0 | ||
223 | jsr @SYMBOL_NAME(schedule_tail) | ||
224 | bra SYMBOL_NAME(ret_from_exception):8 | ||
225 | |||
226 | SYMBOL_NAME_LABEL(reschedule) | ||
227 | /* save top of frame */ | ||
228 | mov.l sp,er0 | ||
229 | jsr @SYMBOL_NAME(set_esp0) | ||
230 | jsr @SYMBOL_NAME(schedule) | ||
231 | |||
232 | SYMBOL_NAME_LABEL(ret_from_exception) | ||
233 | #if defined(CONFIG_PREEMPT) | ||
234 | orc #0x80,ccr | ||
235 | #endif | ||
236 | SYMBOL_NAME_LABEL(ret_from_interrupt) | ||
237 | mov.b @(LCCR+1:16,sp),r0l | ||
238 | btst #4,r0l /* check if returning to kernel */ | ||
239 | bne done:8 /* if so, skip resched, signals */ | ||
240 | andc #0x7f,ccr | ||
241 | mov.l sp,er4 | ||
242 | and.w #0xe000,r4 | ||
243 | mov.l @(TI_FLAGS:16,er4),er1 | ||
244 | and.l #_TIF_WORK_MASK,er1 | ||
245 | beq done:8 | ||
246 | 1: | ||
247 | mov.l @(TI_FLAGS:16,er4),er1 | ||
248 | btst #TIF_NEED_RESCHED,r1l | ||
249 | bne SYMBOL_NAME(reschedule):16 | ||
250 | mov.l sp,er0 | ||
251 | subs #4,er0 /* adjust retpc */ | ||
252 | mov.l er2,er1 | ||
253 | jsr @SYMBOL_NAME(do_signal) | ||
254 | #if defined(CONFIG_PREEMPT) | ||
255 | bra done:8 /* userspace thoru */ | ||
256 | 3: | ||
257 | btst #4,r0l | ||
258 | beq done:8 /* userspace thoru */ | ||
259 | 4: | ||
260 | mov.l @(TI_PRE_COUNT:16,er4),er1 | ||
261 | bne done:8 | ||
262 | mov.l @(TI_FLAGS:16,er4),er1 | ||
263 | btst #TIF_NEED_RESCHED,r1l | ||
264 | beq done:8 | ||
265 | mov.b r0l,r0l | ||
266 | bpl done:8 /* interrupt off (exception path?) */ | ||
267 | mov.l #PREEMPT_ACTIVE,er1 | ||
268 | mov.l er1,@(TI_PRE_COUNT:16,er4) | ||
269 | andc #0x7f,ccr | ||
270 | jsr @SYMBOL_NAME(schedule) | ||
271 | sub.l er1,er1 | ||
272 | mov.l er1,@(TI_PRE_COUNT:16,er4) | ||
273 | orc #0x80,ccr | ||
274 | bra 4b:8 | ||
275 | #endif | ||
276 | done: | ||
277 | RESTORE_ALL /* Does RTE */ | ||
278 | |||
279 | SYMBOL_NAME_LABEL(resume) | ||
280 | /* | ||
281 | * Beware - when entering resume, offset of tss is in d1, | ||
282 | * prev (the current task) is in a0, next (the new task) | ||
283 | * is in a1 and d2.b is non-zero if the mm structure is | ||
284 | * shared between the tasks, so don't change these | ||
285 | * registers until their contents are no longer needed. | ||
286 | */ | ||
287 | |||
288 | /* save sr */ | ||
289 | sub.w r3,r3 | ||
290 | stc ccr,r3l | ||
291 | mov.w r3,@(THREAD_CCR+2:16,er0) | ||
292 | |||
293 | /* disable interrupts */ | ||
294 | orc #0x80,ccr | ||
295 | mov.l @SYMBOL_NAME(sw_usp),er3 | ||
296 | mov.l er3,@(THREAD_USP:16,er0) | ||
297 | mov.l sp,@(THREAD_KSP:16,er0) | ||
298 | |||
299 | /* Skip address space switching if they are the same. */ | ||
300 | /* FIXME: what did we hack out of here, this does nothing! */ | ||
301 | |||
302 | mov.l @(THREAD_USP:16,er1),er0 | ||
303 | mov.l er0,@SYMBOL_NAME(sw_usp) | ||
304 | mov.l @(THREAD_KSP:16,er1),sp | ||
305 | |||
306 | /* restore status register */ | ||
307 | mov.w @(THREAD_CCR+2:16,er1),r3 | ||
308 | |||
309 | ldc r3l,ccr | ||
310 | rts | ||
311 | |||
312 | SYMBOL_NAME_LABEL(trace_break) | ||
313 | subs #4,sp | ||
314 | SAVE_ALL | ||
315 | sub.l er1,er1 | ||
316 | dec.l #1,er1 | ||
317 | mov.l er1,@(LORIG,sp) | ||
318 | mov.l sp,er0 | ||
319 | jsr @SYMBOL_NAME(set_esp0) | ||
320 | mov.l @SYMBOL_NAME(sw_usp),er0 | ||
321 | mov.l @er0,er1 | ||
322 | subs #2,er1 | ||
323 | mov.l er1,@er0 | ||
324 | and.w #0xff,e1 | ||
325 | mov.l er1,er0 | ||
326 | jsr @SYMBOL_NAME(trace_trap) | ||
327 | jmp @SYMBOL_NAME(ret_from_exception) | ||
328 | |||
329 | .section .bss | ||
330 | SYMBOL_NAME_LABEL(sw_ksp) | ||
331 | .space 4 | ||
332 | SYMBOL_NAME_LABEL(sw_usp) | ||
333 | .space 4 | ||
diff --git a/arch/h8300/platform/h8300h/generic/Makefile b/arch/h8300/platform/h8300h/generic/Makefile new file mode 100644 index 000000000000..b6ea7688a616 --- /dev/null +++ b/arch/h8300/platform/h8300h/generic/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | # | ||
2 | # Makefile for the linux kernel. | ||
3 | # | ||
4 | |||
5 | obj-y := timer.o | ||
6 | extra-y = crt0_$(MODEL).o | ||
diff --git a/arch/h8300/platform/h8300h/generic/crt0_ram.S b/arch/h8300/platform/h8300h/generic/crt0_ram.S new file mode 100644 index 000000000000..b735042a7c3f --- /dev/null +++ b/arch/h8300/platform/h8300h/generic/crt0_ram.S | |||
@@ -0,0 +1,108 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/platform/h8300h/generic/crt0_ram.S | ||
3 | * | ||
4 | * Yoshinori Sato <ysato@users.sourceforge.jp> | ||
5 | * | ||
6 | * Platform depend startup | ||
7 | * Target Archtecture: AE-3068 (aka. aki3068net) | ||
8 | * Memory Layout : RAM | ||
9 | */ | ||
10 | |||
11 | #define ASSEMBLY | ||
12 | |||
13 | #include <linux/config.h> | ||
14 | #include <asm/linkage.h> | ||
15 | |||
16 | #if !defined(CONFIG_BLKDEV_RESERVE) | ||
17 | #if defined(CONFIG_GDB_DEBUG) | ||
18 | #define RAMEND (__ramend - 0xc000) | ||
19 | #else | ||
20 | #define RAMEND __ramend | ||
21 | #endif | ||
22 | #else | ||
23 | #define RAMEND CONFIG_BLKDEV_RESERVE_ADDRESS | ||
24 | #endif | ||
25 | |||
26 | .global SYMBOL_NAME(_start) | ||
27 | .global SYMBOL_NAME(command_line) | ||
28 | .global SYMBOL_NAME(_platform_gpio_table) | ||
29 | .global SYMBOL_NAME(_target_name) | ||
30 | |||
31 | .h8300h | ||
32 | |||
33 | .section .text | ||
34 | .file "crt0_ram.S" | ||
35 | |||
36 | /* CPU Reset entry */ | ||
37 | SYMBOL_NAME_LABEL(_start) | ||
38 | mov.l #RAMEND,sp | ||
39 | ldc #0x80,ccr | ||
40 | |||
41 | /* Peripheral Setup */ | ||
42 | |||
43 | #if defined(CONFIG_BLK_DEV_BLKMEM) | ||
44 | /* move romfs image */ | ||
45 | jsr @__move_romfs | ||
46 | #endif | ||
47 | |||
48 | /* .bss clear */ | ||
49 | mov.l #__sbss,er5 | ||
50 | mov.l #__ebss,er4 | ||
51 | sub.l er5,er4 | ||
52 | shlr er4 | ||
53 | shlr er4 | ||
54 | sub.l er0,er0 | ||
55 | 1: | ||
56 | mov.l er0,@er5 | ||
57 | adds #4,er5 | ||
58 | dec.l #1,er4 | ||
59 | bne 1b | ||
60 | |||
61 | /* copy kernel commandline */ | ||
62 | mov.l #COMMAND_START,er5 | ||
63 | mov.l #SYMBOL_NAME(command_line),er6 | ||
64 | mov.w #512,r4 | ||
65 | eepmov.w | ||
66 | |||
67 | /* uClinux kernel start */ | ||
68 | ldc #0x90,ccr /* running kernel */ | ||
69 | mov.l #SYMBOL_NAME(init_thread_union),sp | ||
70 | add.l #0x2000,sp | ||
71 | jsr @_start_kernel | ||
72 | _exit: | ||
73 | |||
74 | jmp _exit | ||
75 | |||
76 | rts | ||
77 | |||
78 | /* I/O port assign information */ | ||
79 | __platform_gpio_table: | ||
80 | mov.l #gpio_table,er0 | ||
81 | rts | ||
82 | |||
83 | gpio_table: | ||
84 | ;; P1DDR | ||
85 | .byte 0x00,0x00 | ||
86 | ;; P2DDR | ||
87 | .byte 0x00,0x00 | ||
88 | ;; P3DDR | ||
89 | .byte 0x00,0x00 | ||
90 | ;; P4DDR | ||
91 | .byte 0x00,0x00 | ||
92 | ;; P5DDR | ||
93 | .byte 0x00,0x00 | ||
94 | ;; P6DDR | ||
95 | .byte 0x00,0x00 | ||
96 | ;; dummy | ||
97 | .byte 0x00,0x00 | ||
98 | ;; P8DDR | ||
99 | .byte 0x00,0x00 | ||
100 | ;; P9DDR | ||
101 | .byte 0x00,0x00 | ||
102 | ;; PADDR | ||
103 | .byte 0x00,0x00 | ||
104 | ;; PBDDR | ||
105 | .byte 0x00,0x00 | ||
106 | |||
107 | __target_name: | ||
108 | .asciz "generic" | ||
diff --git a/arch/h8300/platform/h8300h/generic/crt0_rom.S b/arch/h8300/platform/h8300h/generic/crt0_rom.S new file mode 100644 index 000000000000..2e32d8179db3 --- /dev/null +++ b/arch/h8300/platform/h8300h/generic/crt0_rom.S | |||
@@ -0,0 +1,123 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/platform/h8300h/generic/crt0_rom.S | ||
3 | * | ||
4 | * Yoshinori Sato <ysato@users.sourceforge.jp> | ||
5 | * | ||
6 | * Platform depend startup | ||
7 | * Target Archtecture: generic | ||
8 | * Memory Layout : ROM | ||
9 | */ | ||
10 | |||
11 | #define ASSEMBLY | ||
12 | |||
13 | #include <linux/config.h> | ||
14 | #include <asm/linkage.h> | ||
15 | |||
16 | .global SYMBOL_NAME(_start) | ||
17 | .global SYMBOL_NAME(_command_line) | ||
18 | .global SYMBOL_NAME(_platform_gpio_table) | ||
19 | .global SYMBOL_NAME(_target_name) | ||
20 | |||
21 | .h8300h | ||
22 | .section .text | ||
23 | .file "crt0_rom.S" | ||
24 | |||
25 | /* CPU Reset entry */ | ||
26 | SYMBOL_NAME_LABEL(_start) | ||
27 | mov.l #__ramend,sp | ||
28 | ldc #0x80,ccr | ||
29 | |||
30 | /* Peripheral Setup */ | ||
31 | |||
32 | /* .bss clear */ | ||
33 | mov.l #__sbss,er5 | ||
34 | mov.l #__ebss,er4 | ||
35 | sub.l er5,er4 | ||
36 | shlr er4 | ||
37 | shlr er4 | ||
38 | sub.l er0,er0 | ||
39 | 1: | ||
40 | mov.l er0,@er5 | ||
41 | adds #4,er5 | ||
42 | dec.l #1,er4 | ||
43 | bne 1b | ||
44 | |||
45 | /* copy .data */ | ||
46 | #if !defined(CONFIG_H8300H_SIM) | ||
47 | /* copy .data */ | ||
48 | mov.l #__begin_data,er5 | ||
49 | mov.l #__sdata,er6 | ||
50 | mov.l #__edata,er4 | ||
51 | sub.l er6,er4 | ||
52 | shlr.l er4 | ||
53 | shlr.l er4 | ||
54 | 1: | ||
55 | mov.l @er5+,er0 | ||
56 | mov.l er0,@er6 | ||
57 | adds #4,er6 | ||
58 | dec.l #1,er4 | ||
59 | bne 1b | ||
60 | #endif | ||
61 | |||
62 | /* copy kernel commandline */ | ||
63 | mov.l #COMMAND_START,er5 | ||
64 | mov.l #SYMBOL_NAME(_command_line),er6 | ||
65 | mov.w #512,r4 | ||
66 | eepmov.w | ||
67 | |||
68 | /* linux kernel start */ | ||
69 | ldc #0x90,ccr /* running kernel */ | ||
70 | mov.l #SYMBOL_NAME(init_thread_union),sp | ||
71 | add.l #0x2000,sp | ||
72 | jsr @_start_kernel | ||
73 | _exit: | ||
74 | |||
75 | jmp _exit | ||
76 | |||
77 | rts | ||
78 | |||
79 | /* I/O port assign information */ | ||
80 | __platform_gpio_table: | ||
81 | mov.l #gpio_table,er0 | ||
82 | rts | ||
83 | |||
84 | gpio_table: | ||
85 | ;; P1DDR | ||
86 | .byte 0x00,0x00 | ||
87 | ;; P2DDR | ||
88 | .byte 0x00,0x00 | ||
89 | ;; P3DDR | ||
90 | .byte 0x00,0x00 | ||
91 | ;; P4DDR | ||
92 | .byte 0x00,0x00 | ||
93 | ;; P5DDR | ||
94 | .byte 0x00,0x00 | ||
95 | ;; P6DDR | ||
96 | .byte 0x00,0x00 | ||
97 | ;; dummy | ||
98 | .byte 0x00,0x00 | ||
99 | ;; P8DDR | ||
100 | .byte 0x00,0x00 | ||
101 | ;; P9DDR | ||
102 | .byte 0x00,0x00 | ||
103 | ;; PADDR | ||
104 | .byte 0x00,0x00 | ||
105 | ;; PBDDR | ||
106 | .byte 0x00,0x00 | ||
107 | |||
108 | .section .rodata | ||
109 | __target_name: | ||
110 | .asciz "generic" | ||
111 | |||
112 | .section .bss | ||
113 | __command_line: | ||
114 | .space 512 | ||
115 | |||
116 | /* interrupt vector */ | ||
117 | .section .vectors,"ax" | ||
118 | .long __start | ||
119 | vector = 1 | ||
120 | .rept 64-1 | ||
121 | .long _interrupt_redirect_table+vector*4 | ||
122 | vector = vector + 1 | ||
123 | .endr | ||
diff --git a/arch/h8300/platform/h8300h/generic/timer.c b/arch/h8300/platform/h8300h/generic/timer.c new file mode 100644 index 000000000000..6590f89e521a --- /dev/null +++ b/arch/h8300/platform/h8300h/generic/timer.c | |||
@@ -0,0 +1,96 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/platform/h8300h/generic/timer.c | ||
3 | * | ||
4 | * Yoshinori Sato <ysato@users.sourceforge.jp> | ||
5 | * | ||
6 | * Platform depend Timer Handler | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #include <linux/config.h> | ||
11 | #include <linux/errno.h> | ||
12 | #include <linux/sched.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/param.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <linux/mm.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | |||
19 | #include <asm/segment.h> | ||
20 | #include <asm/io.h> | ||
21 | #include <asm/irq.h> | ||
22 | |||
23 | #include <linux/timex.h> | ||
24 | |||
25 | #if defined(CONFIG_H83007) || defined(CONFIG_H83068) | ||
26 | #include <asm/regs306x.h> | ||
27 | #define CMFA 6 | ||
28 | |||
29 | #define CMIEA 0x40 | ||
30 | #define CCLR_CMA 0x08 | ||
31 | #define CLK_DIV8192 0x03 | ||
32 | |||
33 | #define H8300_TIMER_FREQ CONFIG_CPU_CLOCK*1000/8192 /* Timer input freq. */ | ||
34 | |||
35 | void __init platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *)) | ||
36 | { | ||
37 | /* setup 8bit timer ch2 */ | ||
38 | ctrl_outb(H8300_TIMER_FREQ / HZ, TCORA2); /* set interval */ | ||
39 | ctrl_outb(0x00, _8TCSR2); /* no output */ | ||
40 | request_irq(40, timer_int, 0, "timer", 0); | ||
41 | ctrl_outb(CMIEA|CCLR_CMA|CLK_DIV8192, _8TCR2); /* start count */ | ||
42 | } | ||
43 | |||
44 | void platform_timer_eoi(void) | ||
45 | { | ||
46 | *(volatile unsigned char *)_8TCSR2 &= ~(1 << CMFA); | ||
47 | } | ||
48 | #endif | ||
49 | |||
50 | #if defined(CONFIG_H83002) || defined(CONFIG_H83048) | ||
51 | /* FIXME! */ | ||
52 | #define TSTR 0x00ffff60 | ||
53 | #define TSNC 0x00ffff61 | ||
54 | #define TMDR 0x00ffff62 | ||
55 | #define TFCR 0x00ffff63 | ||
56 | #define TOER 0x00ffff90 | ||
57 | #define TOCR 0x00ffff91 | ||
58 | /* ITU0 */ | ||
59 | #define TCR 0x00ffff64 | ||
60 | #define TIOR 0x00ffff65 | ||
61 | #define TIER 0x00ffff66 | ||
62 | #define TSR 0x00ffff67 | ||
63 | #define TCNT 0x00ffff68 | ||
64 | #define GRA 0x00ffff6a | ||
65 | #define GRB 0x00ffff6c | ||
66 | |||
67 | #define CCLR_CMGRA 0x20 | ||
68 | #define CLK_DIV8 0x03 | ||
69 | |||
70 | #define H8300_TIMER_FREQ CONFIG_CPU_CLOCK*1000/8 /* Timer input freq. */ | ||
71 | |||
72 | void __init platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *)) | ||
73 | { | ||
74 | *(unsigned short *)GRA= H8300_TIMER_FREQ / HZ; /* set interval */ | ||
75 | *(unsigned short *)TCNT=0; /* clear counter */ | ||
76 | ctrl_outb(0x80|CCLR_CMGRA|CLK_DIV8, TCR); /* set ITU0 clock */ | ||
77 | ctrl_outb(0x88, TIOR); /* no output */ | ||
78 | request_irq(26, timer_int, 0, "timer", 0); | ||
79 | ctrl_outb(0xf9, TIER); /* compare match GRA interrupt */ | ||
80 | ctrl_outb(ctrl_inb(TSNC) & ~0x01, TSNC); /* ITU0 async */ | ||
81 | ctrl_outb(ctrl_inb(TMDR) & ~0x01, TMDR); /* ITU0 normal mode */ | ||
82 | ctrl_outb(ctrl_inb(TSTR) | 0x01, TSTR); /* ITU0 Start */ | ||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | void platform_timer_eoi(void) | ||
87 | { | ||
88 | ctrl_outb(ctrl_inb(TSR) & ~0x01,TSR); | ||
89 | } | ||
90 | #endif | ||
91 | |||
92 | void platform_gettod(int *year, int *mon, int *day, int *hour, | ||
93 | int *min, int *sec) | ||
94 | { | ||
95 | *year = *mon = *day = *hour = *min = *sec = 0; | ||
96 | } | ||
diff --git a/arch/h8300/platform/h8300h/h8max/Makefile b/arch/h8300/platform/h8300h/h8max/Makefile new file mode 100644 index 000000000000..b03c328f8c70 --- /dev/null +++ b/arch/h8300/platform/h8300h/h8max/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | # | ||
2 | # Makefile for the linux kernel. | ||
3 | # | ||
4 | |||
5 | extra-y := crt0_ram.o | ||
6 | obj-y := timer.o | ||
diff --git a/arch/h8300/platform/h8300h/h8max/crt0_ram.S b/arch/h8300/platform/h8300h/h8max/crt0_ram.S new file mode 100644 index 000000000000..a5c5a9156e04 --- /dev/null +++ b/arch/h8300/platform/h8300h/h8max/crt0_ram.S | |||
@@ -0,0 +1,111 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/platform/h8300h/h8max/crt0_ram.S | ||
3 | * | ||
4 | * Yoshinori Sato <ysato@users.sourceforge.jp> | ||
5 | * | ||
6 | * Platform depend startup | ||
7 | * Target Archtecture: H8MAX | ||
8 | * Memory Layout : RAM | ||
9 | */ | ||
10 | |||
11 | #define ASSEMBLY | ||
12 | |||
13 | #include <linux/config.h> | ||
14 | #include <asm/linkage.h> | ||
15 | |||
16 | #if !defined(CONFIG_BLKDEV_RESERVE) | ||
17 | #if defined(CONFIG_GDB_DEBUG) | ||
18 | #define RAMEND (__ramend - 0xc000) | ||
19 | #else | ||
20 | #define RAMEND __ramend | ||
21 | #endif | ||
22 | #else | ||
23 | #define RAMEND CONFIG_BLKDEV_RESERVE_ADDRESS | ||
24 | #endif | ||
25 | |||
26 | .global SYMBOL_NAME(_start) | ||
27 | .global SYMBOL_NAME(command_line) | ||
28 | .global SYMBOL_NAME(_platform_gpio_table) | ||
29 | .global SYMBOL_NAME(_target_name) | ||
30 | |||
31 | .h8300h | ||
32 | |||
33 | .section .text | ||
34 | .file "crt0_ram.S" | ||
35 | |||
36 | /* CPU Reset entry */ | ||
37 | SYMBOL_NAME_LABEL(_start) | ||
38 | mov.l #RAMEND,sp | ||
39 | ldc #0x80,ccr | ||
40 | |||
41 | /* Peripheral Setup */ | ||
42 | |||
43 | #if defined(CONFIG_MTD_UCLINUX) | ||
44 | /* move romfs image */ | ||
45 | jsr @__move_romfs | ||
46 | #endif | ||
47 | |||
48 | /* .bss clear */ | ||
49 | mov.l #__sbss,er5 | ||
50 | mov.l #__ebss,er4 | ||
51 | sub.l er5,er4 | ||
52 | shlr er4 | ||
53 | shlr er4 | ||
54 | sub.l er0,er0 | ||
55 | 1: | ||
56 | mov.l er0,@er5 | ||
57 | adds #4,er5 | ||
58 | dec.l #1,er4 | ||
59 | bne 1b | ||
60 | |||
61 | /* copy kernel commandline */ | ||
62 | mov.l #COMMAND_START,er5 | ||
63 | mov.l #SYMBOL_NAME(command_line),er6 | ||
64 | mov.w #512,r4 | ||
65 | eepmov.w | ||
66 | |||
67 | /* uClinux kernel start */ | ||
68 | ldc #0x90,ccr /* running kernel */ | ||
69 | mov.l #SYMBOL_NAME(init_thread_union),sp | ||
70 | add.l #0x2000,sp | ||
71 | jsr @_start_kernel | ||
72 | _exit: | ||
73 | |||
74 | jmp _exit | ||
75 | |||
76 | rts | ||
77 | |||
78 | /* I/O port assign information */ | ||
79 | __platform_gpio_table: | ||
80 | mov.l #gpio_table,er0 | ||
81 | rts | ||
82 | |||
83 | gpio_table: | ||
84 | ;; P1DDR | ||
85 | .byte 0xff,0xff | ||
86 | ;; P2DDR | ||
87 | .byte 0xff,0xff | ||
88 | ;; P3DDR | ||
89 | .byte 0x00,0x00 | ||
90 | ;; P4DDR | ||
91 | .byte 0x00,0x00 | ||
92 | ;; P5DDR | ||
93 | .byte 0x01,0x01 | ||
94 | ;; P6DDR | ||
95 | .byte 0xf6,0xf6 | ||
96 | ;; dummy | ||
97 | .byte 0x00,0x00 | ||
98 | ;; P8DDR | ||
99 | .byte 0xee,0xee | ||
100 | ;; P9DDR | ||
101 | .byte 0x00,0x00 | ||
102 | ;; PADDR | ||
103 | .byte 0x00,0x00 | ||
104 | ;; PBDDR | ||
105 | .byte 0x30,0x30 | ||
106 | |||
107 | __target_name: | ||
108 | .asciz "H8MAX" | ||
109 | |||
110 | .section .bootvec,"ax" | ||
111 | jmp @SYMBOL_NAME(_start) | ||
diff --git a/arch/h8300/platform/h8300h/h8max/timer.c b/arch/h8300/platform/h8300h/h8max/timer.c new file mode 100644 index 000000000000..9ac9fa6691c0 --- /dev/null +++ b/arch/h8300/platform/h8300h/h8max/timer.c | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/platform/h8300h/h8max/timer.c | ||
3 | * | ||
4 | * Yoshinori Sato <ysato@users.sourcefoge.jp> | ||
5 | * | ||
6 | * Platform depend Timer Handler | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #include <linux/config.h> | ||
11 | #include <linux/errno.h> | ||
12 | #include <linux/sched.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/param.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <linux/mm.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/timex.h> | ||
20 | |||
21 | #include <asm/segment.h> | ||
22 | #include <asm/io.h> | ||
23 | #include <asm/irq.h> | ||
24 | #include <asm/regs306x.h> | ||
25 | |||
26 | #define CMFA 6 | ||
27 | |||
28 | #define CMIEA 0x40 | ||
29 | #define CCLR_CMA 0x08 | ||
30 | #define CLK_DIV8192 0x03 | ||
31 | |||
32 | #define H8300_TIMER_FREQ CONFIG_CPU_CLOCK*1000/8192 /* Timer input freq. */ | ||
33 | |||
34 | void __init platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *)) | ||
35 | { | ||
36 | /* setup 8bit timer ch2 */ | ||
37 | ctrl_outb(H8300_TIMER_FREQ / HZ, TCORA2); /* set interval */ | ||
38 | ctrl_outb(0x00, _8TCSR2); /* no output */ | ||
39 | request_irq(40, timer_int, 0, "timer", 0); | ||
40 | ctrl_outb(CMIEA|CCLR_CMA|CLK_DIV8192, _8TCR2); /* start count */ | ||
41 | } | ||
42 | |||
43 | void platform_timer_eoi(void) | ||
44 | { | ||
45 | *(volatile unsigned char *)_8TCSR2 &= ~(1 << CMFA); | ||
46 | } | ||
47 | |||
48 | void platform_gettod(int *year, int *mon, int *day, int *hour, | ||
49 | int *min, int *sec) | ||
50 | { | ||
51 | *year = *mon = *day = *hour = *min = *sec = 0; | ||
52 | } | ||
53 | |||
diff --git a/arch/h8300/platform/h8300h/ints_h8300h.c b/arch/h8300/platform/h8300h/ints_h8300h.c new file mode 100644 index 000000000000..86a155479167 --- /dev/null +++ b/arch/h8300/platform/h8300h/ints_h8300h.c | |||
@@ -0,0 +1,86 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/platform/h8300h/ints_h8300h.c | ||
3 | * Interrupt handling CPU variants | ||
4 | * | ||
5 | * Yoshinori Sato <ysato@users.sourceforge.jp> | ||
6 | * | ||
7 | */ | ||
8 | |||
9 | #include <linux/config.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/errno.h> | ||
12 | |||
13 | #include <asm/ptrace.h> | ||
14 | #include <asm/traps.h> | ||
15 | #include <asm/irq.h> | ||
16 | #include <asm/io.h> | ||
17 | #include <asm/gpio.h> | ||
18 | #include <asm/regs306x.h> | ||
19 | |||
20 | /* saved vector list */ | ||
21 | const int __initdata h8300_saved_vectors[]={ | ||
22 | #if defined(CONFIG_GDB_DEBUG) | ||
23 | TRAP3_VEC, | ||
24 | #endif | ||
25 | -1 | ||
26 | }; | ||
27 | |||
28 | /* trap entry table */ | ||
29 | const unsigned long __initdata h8300_trap_table[NR_TRAPS]={ | ||
30 | 0,0,0,0,0,0,0,0, | ||
31 | (unsigned long)system_call, /* TRAPA #0 */ | ||
32 | 0,0, | ||
33 | (unsigned long)trace_break, /* TRAPA #3 */ | ||
34 | }; | ||
35 | |||
36 | int h8300_enable_irq_pin(unsigned int irq) | ||
37 | { | ||
38 | int bitmask; | ||
39 | if (irq < EXT_IRQ0 || irq > EXT_IRQ5) | ||
40 | return 0; | ||
41 | |||
42 | /* initialize IRQ pin */ | ||
43 | bitmask = 1 << (irq - EXT_IRQ0); | ||
44 | switch(irq) { | ||
45 | case EXT_IRQ0: | ||
46 | case EXT_IRQ1: | ||
47 | case EXT_IRQ2: | ||
48 | case EXT_IRQ3: | ||
49 | if (H8300_GPIO_RESERVE(H8300_GPIO_P8, bitmask) == 0) | ||
50 | return -EBUSY; | ||
51 | H8300_GPIO_DDR(H8300_GPIO_P8, bitmask, H8300_GPIO_INPUT); | ||
52 | break; | ||
53 | case EXT_IRQ4: | ||
54 | case EXT_IRQ5: | ||
55 | if (H8300_GPIO_RESERVE(H8300_GPIO_P9, bitmask) == 0) | ||
56 | return -EBUSY; | ||
57 | H8300_GPIO_DDR(H8300_GPIO_P9, bitmask, H8300_GPIO_INPUT); | ||
58 | break; | ||
59 | } | ||
60 | |||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | void h8300_disable_irq_pin(unsigned int irq) | ||
65 | { | ||
66 | int bitmask; | ||
67 | if (irq < EXT_IRQ0 || irq > EXT_IRQ5) | ||
68 | return; | ||
69 | |||
70 | /* disable interrupt & release IRQ pin */ | ||
71 | bitmask = 1 << (irq - EXT_IRQ0); | ||
72 | switch(irq) { | ||
73 | case EXT_IRQ0: | ||
74 | case EXT_IRQ1: | ||
75 | case EXT_IRQ2: | ||
76 | case EXT_IRQ3: | ||
77 | *(volatile unsigned char *)IER &= ~bitmask; | ||
78 | H8300_GPIO_FREE(H8300_GPIO_P8, bitmask); | ||
79 | break ; | ||
80 | case EXT_IRQ4: | ||
81 | case EXT_IRQ5: | ||
82 | *(volatile unsigned char *)IER &= ~bitmask; | ||
83 | H8300_GPIO_FREE(H8300_GPIO_P9, bitmask); | ||
84 | break; | ||
85 | } | ||
86 | } | ||
diff --git a/arch/h8300/platform/h8300h/ptrace_h8300h.c b/arch/h8300/platform/h8300h/ptrace_h8300h.c new file mode 100644 index 000000000000..18e51a7167d3 --- /dev/null +++ b/arch/h8300/platform/h8300h/ptrace_h8300h.c | |||
@@ -0,0 +1,284 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/platform/h8300h/ptrace_h8300h.c | ||
3 | * ptrace cpu depend helper functions | ||
4 | * | ||
5 | * Yoshinori Sato <ysato@users.sourceforge.jp> | ||
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 | ||
9 | * this archive for more details. | ||
10 | */ | ||
11 | |||
12 | #include <linux/linkage.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <asm/ptrace.h> | ||
15 | |||
16 | #define CCR_MASK 0x6f /* mode/imask not set */ | ||
17 | #define BREAKINST 0x5730 /* trapa #3 */ | ||
18 | |||
19 | /* Mapping from PT_xxx to the stack offset at which the register is | ||
20 | saved. Notice that usp has no stack-slot and needs to be treated | ||
21 | specially (see get_reg/put_reg below). */ | ||
22 | static const int h8300_register_offset[] = { | ||
23 | PT_REG(er1), PT_REG(er2), PT_REG(er3), PT_REG(er4), | ||
24 | PT_REG(er5), PT_REG(er6), PT_REG(er0), PT_REG(orig_er0), | ||
25 | PT_REG(ccr), PT_REG(pc) | ||
26 | }; | ||
27 | |||
28 | /* read register */ | ||
29 | long h8300_get_reg(struct task_struct *task, int regno) | ||
30 | { | ||
31 | switch (regno) { | ||
32 | case PT_USP: | ||
33 | return task->thread.usp + sizeof(long)*2; | ||
34 | case PT_CCR: | ||
35 | return *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]); | ||
36 | default: | ||
37 | return *(unsigned long *)(task->thread.esp0 + h8300_register_offset[regno]); | ||
38 | } | ||
39 | } | ||
40 | |||
41 | /* write register */ | ||
42 | int h8300_put_reg(struct task_struct *task, int regno, unsigned long data) | ||
43 | { | ||
44 | unsigned short oldccr; | ||
45 | switch (regno) { | ||
46 | case PT_USP: | ||
47 | task->thread.usp = data - sizeof(long)*2; | ||
48 | case PT_CCR: | ||
49 | oldccr = *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]); | ||
50 | oldccr &= ~CCR_MASK; | ||
51 | data &= CCR_MASK; | ||
52 | data |= oldccr; | ||
53 | *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]) = data; | ||
54 | break; | ||
55 | default: | ||
56 | *(unsigned long *)(task->thread.esp0 + h8300_register_offset[regno]) = data; | ||
57 | break; | ||
58 | } | ||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | /* disable singlestep */ | ||
63 | void h8300_disable_trace(struct task_struct *child) | ||
64 | { | ||
65 | if((long)child->thread.breakinfo.addr != -1L) { | ||
66 | *child->thread.breakinfo.addr = child->thread.breakinfo.inst; | ||
67 | child->thread.breakinfo.addr = (unsigned short *)-1L; | ||
68 | } | ||
69 | } | ||
70 | |||
71 | /* calculate next pc */ | ||
72 | enum jump_type {none, /* normal instruction */ | ||
73 | jabs, /* absolute address jump */ | ||
74 | ind, /* indirect address jump */ | ||
75 | ret, /* return to subrutine */ | ||
76 | reg, /* register indexed jump */ | ||
77 | relb, /* pc relative jump (byte offset) */ | ||
78 | relw, /* pc relative jump (word offset) */ | ||
79 | }; | ||
80 | |||
81 | /* opcode decode table define | ||
82 | ptn: opcode pattern | ||
83 | msk: opcode bitmask | ||
84 | len: instruction length (<0 next table index) | ||
85 | jmp: jump operation mode */ | ||
86 | struct optable { | ||
87 | unsigned char bitpattern; | ||
88 | unsigned char bitmask; | ||
89 | signed char length; | ||
90 | signed char type; | ||
91 | } __attribute__((aligned(1),packed)); | ||
92 | |||
93 | #define OPTABLE(ptn,msk,len,jmp) \ | ||
94 | { \ | ||
95 | .bitpattern = ptn, \ | ||
96 | .bitmask = msk, \ | ||
97 | .length = len, \ | ||
98 | .type = jmp, \ | ||
99 | } | ||
100 | |||
101 | const static struct optable optable_0[] = { | ||
102 | OPTABLE(0x00,0xff, 1,none), /* 0x00 */ | ||
103 | OPTABLE(0x01,0xff,-1,none), /* 0x01 */ | ||
104 | OPTABLE(0x02,0xfe, 1,none), /* 0x02-0x03 */ | ||
105 | OPTABLE(0x04,0xee, 1,none), /* 0x04-0x05/0x14-0x15 */ | ||
106 | OPTABLE(0x06,0xfe, 1,none), /* 0x06-0x07 */ | ||
107 | OPTABLE(0x08,0xea, 1,none), /* 0x08-0x09/0x0c-0x0d/0x18-0x19/0x1c-0x1d */ | ||
108 | OPTABLE(0x0a,0xee, 1,none), /* 0x0a-0x0b/0x1a-0x1b */ | ||
109 | OPTABLE(0x0e,0xee, 1,none), /* 0x0e-0x0f/0x1e-0x1f */ | ||
110 | OPTABLE(0x10,0xfc, 1,none), /* 0x10-0x13 */ | ||
111 | OPTABLE(0x16,0xfe, 1,none), /* 0x16-0x17 */ | ||
112 | OPTABLE(0x20,0xe0, 1,none), /* 0x20-0x3f */ | ||
113 | OPTABLE(0x40,0xf0, 1,relb), /* 0x40-0x4f */ | ||
114 | OPTABLE(0x50,0xfc, 1,none), /* 0x50-0x53 */ | ||
115 | OPTABLE(0x54,0xfd, 1,ret ), /* 0x54/0x56 */ | ||
116 | OPTABLE(0x55,0xff, 1,relb), /* 0x55 */ | ||
117 | OPTABLE(0x57,0xff, 1,none), /* 0x57 */ | ||
118 | OPTABLE(0x58,0xfb, 2,relw), /* 0x58/0x5c */ | ||
119 | OPTABLE(0x59,0xfb, 1,reg ), /* 0x59/0x5b */ | ||
120 | OPTABLE(0x5a,0xfb, 2,jabs), /* 0x5a/0x5e */ | ||
121 | OPTABLE(0x5b,0xfb, 2,ind ), /* 0x5b/0x5f */ | ||
122 | OPTABLE(0x60,0xe8, 1,none), /* 0x60-0x67/0x70-0x77 */ | ||
123 | OPTABLE(0x68,0xfa, 1,none), /* 0x68-0x69/0x6c-0x6d */ | ||
124 | OPTABLE(0x6a,0xfe,-2,none), /* 0x6a-0x6b */ | ||
125 | OPTABLE(0x6e,0xfe, 2,none), /* 0x6e-0x6f */ | ||
126 | OPTABLE(0x78,0xff, 4,none), /* 0x78 */ | ||
127 | OPTABLE(0x79,0xff, 2,none), /* 0x79 */ | ||
128 | OPTABLE(0x7a,0xff, 3,none), /* 0x7a */ | ||
129 | OPTABLE(0x7b,0xff, 2,none), /* 0x7b */ | ||
130 | OPTABLE(0x7c,0xfc, 2,none), /* 0x7c-0x7f */ | ||
131 | OPTABLE(0x80,0x80, 1,none), /* 0x80-0xff */ | ||
132 | }; | ||
133 | |||
134 | const static struct optable optable_1[] = { | ||
135 | OPTABLE(0x00,0xff,-3,none), /* 0x0100 */ | ||
136 | OPTABLE(0x40,0xf0,-3,none), /* 0x0140-0x14f */ | ||
137 | OPTABLE(0x80,0xf0, 1,none), /* 0x0180-0x018f */ | ||
138 | OPTABLE(0xc0,0xc0, 2,none), /* 0x01c0-0x01ff */ | ||
139 | }; | ||
140 | |||
141 | const static struct optable optable_2[] = { | ||
142 | OPTABLE(0x00,0x20, 2,none), /* 0x6a0?/0x6a8?/0x6b0?/0x6b8? */ | ||
143 | OPTABLE(0x20,0x20, 3,none), /* 0x6a2?/0x6aa?/0x6b2?/0x6ba? */ | ||
144 | }; | ||
145 | |||
146 | const static struct optable optable_3[] = { | ||
147 | OPTABLE(0x69,0xfb, 2,none), /* 0x010069/0x01006d/014069/0x01406d */ | ||
148 | OPTABLE(0x6b,0xff,-4,none), /* 0x01006b/0x01406b */ | ||
149 | OPTABLE(0x6f,0xff, 3,none), /* 0x01006f/0x01406f */ | ||
150 | OPTABLE(0x78,0xff, 5,none), /* 0x010078/0x014078 */ | ||
151 | }; | ||
152 | |||
153 | const static struct optable optable_4[] = { | ||
154 | OPTABLE(0x00,0x78, 3,none), /* 0x0100690?/0x01006d0?/0140690/0x01406d0?/0x0100698?/0x01006d8?/0140698?/0x01406d8? */ | ||
155 | OPTABLE(0x20,0x78, 4,none), /* 0x0100692?/0x01006d2?/0140692/0x01406d2?/0x010069a?/0x01006da?/014069a?/0x01406da? */ | ||
156 | }; | ||
157 | |||
158 | const static struct optables_list { | ||
159 | const struct optable *ptr; | ||
160 | int size; | ||
161 | } optables[] = { | ||
162 | #define OPTABLES(no) \ | ||
163 | { \ | ||
164 | .ptr = optable_##no, \ | ||
165 | .size = sizeof(optable_##no) / sizeof(struct optable), \ | ||
166 | } | ||
167 | OPTABLES(0), | ||
168 | OPTABLES(1), | ||
169 | OPTABLES(2), | ||
170 | OPTABLES(3), | ||
171 | OPTABLES(4), | ||
172 | |||
173 | }; | ||
174 | |||
175 | const unsigned char condmask[] = { | ||
176 | 0x00,0x40,0x01,0x04,0x02,0x08,0x10,0x20 | ||
177 | }; | ||
178 | |||
179 | static int isbranch(struct task_struct *task,int reson) | ||
180 | { | ||
181 | unsigned char cond = h8300_get_reg(task, PT_CCR); | ||
182 | /* encode complex conditions */ | ||
183 | /* B4: N^V | ||
184 | B5: Z|(N^V) | ||
185 | B6: C|Z */ | ||
186 | __asm__("bld #3,%w0\n\t" | ||
187 | "bxor #1,%w0\n\t" | ||
188 | "bst #4,%w0\n\t" | ||
189 | "bor #2,%w0\n\t" | ||
190 | "bst #5,%w0\n\t" | ||
191 | "bld #2,%w0\n\t" | ||
192 | "bor #0,%w0\n\t" | ||
193 | "bst #6,%w0\n\t" | ||
194 | :"=&r"(cond)::"cc"); | ||
195 | cond &= condmask[reson >> 1]; | ||
196 | if (!(reson & 1)) | ||
197 | return cond == 0; | ||
198 | else | ||
199 | return cond != 0; | ||
200 | } | ||
201 | |||
202 | static unsigned short *getnextpc(struct task_struct *child, unsigned short *pc) | ||
203 | { | ||
204 | const struct optable *op; | ||
205 | unsigned char *fetch_p; | ||
206 | unsigned char inst; | ||
207 | unsigned long addr; | ||
208 | unsigned long *sp; | ||
209 | int op_len,regno; | ||
210 | op = optables[0].ptr; | ||
211 | op_len = optables[0].size; | ||
212 | fetch_p = (unsigned char *)pc; | ||
213 | inst = *fetch_p++; | ||
214 | do { | ||
215 | if ((inst & op->bitmask) == op->bitpattern) { | ||
216 | if (op->length < 0) { | ||
217 | op = optables[-op->length].ptr; | ||
218 | op_len = optables[-op->length].size + 1; | ||
219 | inst = *fetch_p++; | ||
220 | } else { | ||
221 | switch (op->type) { | ||
222 | case none: | ||
223 | return pc + op->length; | ||
224 | case jabs: | ||
225 | addr = *(unsigned long *)pc; | ||
226 | return (unsigned short *)(addr & 0x00ffffff); | ||
227 | case ind: | ||
228 | addr = *pc & 0xff; | ||
229 | return (unsigned short *)(*(unsigned long *)addr); | ||
230 | case ret: | ||
231 | sp = (unsigned long *)h8300_get_reg(child, PT_USP); | ||
232 | /* user stack frames | ||
233 | | er0 | temporary saved | ||
234 | +--------+ | ||
235 | | exp | exception stack frames | ||
236 | +--------+ | ||
237 | | ret pc | userspace return address | ||
238 | */ | ||
239 | return (unsigned short *)(*(sp+2) & 0x00ffffff); | ||
240 | case reg: | ||
241 | regno = (*pc >> 4) & 0x07; | ||
242 | if (regno == 0) | ||
243 | addr = h8300_get_reg(child, PT_ER0); | ||
244 | else | ||
245 | addr = h8300_get_reg(child, regno-1+PT_ER1); | ||
246 | return (unsigned short *)addr; | ||
247 | case relb: | ||
248 | if ((inst = 0x55) || isbranch(child,inst & 0x0f)) | ||
249 | pc = (unsigned short *)((unsigned long)pc + | ||
250 | ((signed char)(*fetch_p))); | ||
251 | return pc+1; /* skip myself */ | ||
252 | case relw: | ||
253 | if ((inst = 0x5c) || isbranch(child,(*fetch_p & 0xf0) >> 4)) | ||
254 | pc = (unsigned short *)((unsigned long)pc + | ||
255 | ((signed short)(*(pc+1)))); | ||
256 | return pc+2; /* skip myself */ | ||
257 | } | ||
258 | } | ||
259 | } else | ||
260 | op++; | ||
261 | } while(--op_len > 0); | ||
262 | return NULL; | ||
263 | } | ||
264 | |||
265 | /* Set breakpoint(s) to simulate a single step from the current PC. */ | ||
266 | |||
267 | void h8300_enable_trace(struct task_struct *child) | ||
268 | { | ||
269 | unsigned short *nextpc; | ||
270 | nextpc = getnextpc(child,(unsigned short *)h8300_get_reg(child, PT_PC)); | ||
271 | child->thread.breakinfo.addr = nextpc; | ||
272 | child->thread.breakinfo.inst = *nextpc; | ||
273 | *nextpc = BREAKINST; | ||
274 | } | ||
275 | |||
276 | asmlinkage void trace_trap(unsigned long bp) | ||
277 | { | ||
278 | if ((unsigned long)current->thread.breakinfo.addr == bp) { | ||
279 | h8300_disable_trace(current); | ||
280 | force_sig(SIGTRAP,current); | ||
281 | } else | ||
282 | force_sig(SIGILL,current); | ||
283 | } | ||
284 | |||
diff --git a/arch/h8300/platform/h8s/Makefile b/arch/h8300/platform/h8s/Makefile new file mode 100644 index 000000000000..0847b15d4256 --- /dev/null +++ b/arch/h8300/platform/h8s/Makefile | |||
@@ -0,0 +1,7 @@ | |||
1 | # | ||
2 | # Makefile for the linux kernel. | ||
3 | # | ||
4 | # Reuse any files we can from the H8S | ||
5 | # | ||
6 | |||
7 | obj-y := entry.o ints_h8s.o ptrace_h8s.o | ||
diff --git a/arch/h8300/platform/h8s/edosk2674/Makefile b/arch/h8300/platform/h8s/edosk2674/Makefile new file mode 100644 index 000000000000..f763654ac6fe --- /dev/null +++ b/arch/h8300/platform/h8s/edosk2674/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | # | ||
2 | # Makefile for the linux kernel. | ||
3 | # | ||
4 | |||
5 | extra-y := crt0_$(MODEL).o | ||
6 | obj-y := timer.o | ||
diff --git a/arch/h8300/platform/h8s/edosk2674/crt0_ram.S b/arch/h8300/platform/h8s/edosk2674/crt0_ram.S new file mode 100644 index 000000000000..8105dc17d735 --- /dev/null +++ b/arch/h8300/platform/h8s/edosk2674/crt0_ram.S | |||
@@ -0,0 +1,131 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/platform/h8s/edosk2674/crt0_ram.S | ||
3 | * | ||
4 | * Yoshinori Sato <ysato@users.sourceforge.jp> | ||
5 | * | ||
6 | * Platform depend startup | ||
7 | * Target Archtecture: EDOSK-2674 | ||
8 | * Memory Layout : RAM | ||
9 | */ | ||
10 | |||
11 | #define ASSEMBLY | ||
12 | |||
13 | #include <linux/config.h> | ||
14 | #include <asm/linkage.h> | ||
15 | #include <asm/regs267x.h> | ||
16 | |||
17 | #if !defined(CONFIG_BLKDEV_RESERVE) | ||
18 | #if defined(CONFIG_GDB_DEBUG) | ||
19 | #define RAMEND (__ramend - 0xc000) | ||
20 | #else | ||
21 | #define RAMEND __ramend | ||
22 | #endif | ||
23 | #else | ||
24 | #define RAMEND CONFIG_BLKDEV_RESERVE_ADDRESS | ||
25 | #endif | ||
26 | |||
27 | .global SYMBOL_NAME(_start) | ||
28 | .global SYMBOL_NAME(_command_line) | ||
29 | .global SYMBOL_NAME(_platform_gpio_table) | ||
30 | .global SYMBOL_NAME(_target_name) | ||
31 | |||
32 | .h8300s | ||
33 | |||
34 | .section .text | ||
35 | .file "crt0_ram.S" | ||
36 | |||
37 | /* CPU Reset entry */ | ||
38 | SYMBOL_NAME_LABEL(_start) | ||
39 | mov.l #RAMEND,sp | ||
40 | ldc #0x80,ccr | ||
41 | ldc #0x00,exr | ||
42 | |||
43 | /* Peripheral Setup */ | ||
44 | bclr #4,@INTCR:8 /* interrupt mode 2 */ | ||
45 | bset #5,@INTCR:8 | ||
46 | bclr #0,@IER+1:16 | ||
47 | bset #1,@ISCRL+1:16 /* IRQ0 Positive Edge */ | ||
48 | bclr #0,@ISCRL+1:16 | ||
49 | |||
50 | #if defined(CONFIG_MTD_UCLINUX) | ||
51 | /* move romfs image */ | ||
52 | jsr @__move_romfs | ||
53 | #endif | ||
54 | |||
55 | /* .bss clear */ | ||
56 | mov.l #__sbss,er5 | ||
57 | mov.l er5,er6 | ||
58 | mov.l #__ebss,er4 | ||
59 | sub.l er5,er4 | ||
60 | shlr #2,er4 | ||
61 | sub.l er0,er0 | ||
62 | 1: | ||
63 | mov.l er0,@er5 | ||
64 | adds #4,er5 | ||
65 | dec.l #1,er4 | ||
66 | bne 1b | ||
67 | |||
68 | /* copy kernel commandline */ | ||
69 | mov.l #COMMAND_START,er5 | ||
70 | mov.l #SYMBOL_NAME(command_line),er6 | ||
71 | mov.w #512,r4 | ||
72 | eepmov.w | ||
73 | |||
74 | /* uClinux kernel start */ | ||
75 | ldc #0x90,ccr /* running kernel */ | ||
76 | mov.l #SYMBOL_NAME(init_thread_union),sp | ||
77 | add.l #0x2000,sp | ||
78 | jsr @_start_kernel | ||
79 | _exit: | ||
80 | |||
81 | jmp _exit | ||
82 | |||
83 | rts | ||
84 | |||
85 | /* I/O port assign information */ | ||
86 | __platform_gpio_table: | ||
87 | mov.l #gpio_table,er0 | ||
88 | rts | ||
89 | |||
90 | gpio_table: | ||
91 | ;; P1DDR | ||
92 | ;; used,ddr | ||
93 | .byte 0x00,0x00 | ||
94 | ;; P2DDR | ||
95 | .byte 0x00,0x00 | ||
96 | ;; P3DDR | ||
97 | .byte 0x3f,0x3a | ||
98 | ;; dummy | ||
99 | .byte 0x00,0x00 | ||
100 | ;; P5DDR | ||
101 | .byte 0x00,0x00 | ||
102 | ;; P6DDR | ||
103 | .byte 0x00,0x00 | ||
104 | ;; P7DDR | ||
105 | .byte 0x00,0x00 | ||
106 | ;; P8DDR | ||
107 | .byte 0x00,0x00 | ||
108 | ;; dummy | ||
109 | .byte 0x00,0x00 | ||
110 | ;; PADDR | ||
111 | .byte 0xff,0xff | ||
112 | ;; PBDDR | ||
113 | .byte 0xff,0x00 | ||
114 | ;; PCDDR | ||
115 | .byte 0xff,0x00 | ||
116 | ;; PDDDR | ||
117 | .byte 0xff,0x00 | ||
118 | ;; PEDDR | ||
119 | .byte 0xff,0x00 | ||
120 | ;; PFDDR | ||
121 | .byte 0xff,0xff | ||
122 | ;; PGDDR | ||
123 | .byte 0x0f,0x0f | ||
124 | ;; PHDDR | ||
125 | .byte 0x0f,0x0f | ||
126 | |||
127 | __target_name: | ||
128 | .asciz "EDOSK-2674" | ||
129 | |||
130 | .section .bootvec,"ax" | ||
131 | jmp @SYMBOL_NAME(_start) | ||
diff --git a/arch/h8300/platform/h8s/edosk2674/crt0_rom.S b/arch/h8300/platform/h8s/edosk2674/crt0_rom.S new file mode 100644 index 000000000000..65748bf18556 --- /dev/null +++ b/arch/h8300/platform/h8s/edosk2674/crt0_rom.S | |||
@@ -0,0 +1,187 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/platform/h8s/edosk2674/crt0_rom.S | ||
3 | * | ||
4 | * Yoshinori Sato <ysato@users.sourceforge.jp> | ||
5 | * | ||
6 | * Platform depend startup | ||
7 | * Target Archtecture: EDOSK-2674 | ||
8 | * Memory Layout : ROM | ||
9 | */ | ||
10 | |||
11 | #define ASSEMBLY | ||
12 | |||
13 | #include <linux/config.h> | ||
14 | #include <asm/linkage.h> | ||
15 | #include <asm/regs267x.h> | ||
16 | |||
17 | .global SYMBOL_NAME(_start) | ||
18 | .global SYMBOL_NAME(_command_line) | ||
19 | .global SYMBOL_NAME(_platform_gpio_table) | ||
20 | .global SYMBOL_NAME(_target_name) | ||
21 | |||
22 | .h8300s | ||
23 | .section .text | ||
24 | .file "crt0_rom.S" | ||
25 | |||
26 | /* CPU Reset entry */ | ||
27 | SYMBOL_NAME_LABEL(_start) | ||
28 | mov.l #__ramend,sp | ||
29 | ldc #0x80,ccr | ||
30 | ldc #0,exr | ||
31 | |||
32 | /* Peripheral Setup */ | ||
33 | ;BSC/GPIO setup | ||
34 | mov.l #init_regs,er0 | ||
35 | mov.w #0xffff,e2 | ||
36 | 1: | ||
37 | mov.w @er0+,r2 | ||
38 | beq 2f | ||
39 | mov.w @er0+,r1 | ||
40 | mov.b r1l,@er2 | ||
41 | bra 1b | ||
42 | |||
43 | 2: | ||
44 | ;SDRAM setup | ||
45 | #define SDRAM_SMR 0x400040 | ||
46 | |||
47 | mov.b #0,r0l | ||
48 | mov.b r0l,@DRACCR:16 | ||
49 | mov.w #0x188,r0 | ||
50 | mov.w r0,@REFCR:16 | ||
51 | mov.w #0x85b4,r0 | ||
52 | mov.w r0,@DRAMCR:16 | ||
53 | mov.b #0,r1l | ||
54 | mov.b r1l,@SDRAM_SMR | ||
55 | mov.w #0x84b4,r0 | ||
56 | mov.w r0,@DRAMCR:16 | ||
57 | ;special thanks to Arizona Cooperative Power | ||
58 | |||
59 | /* copy .data */ | ||
60 | mov.l #__begin_data,er5 | ||
61 | mov.l #__sdata,er6 | ||
62 | mov.l #__edata,er4 | ||
63 | sub.l er6,er4 | ||
64 | shlr.l #2,er4 | ||
65 | 1: | ||
66 | mov.l @er5+,er0 | ||
67 | mov.l er0,@er6 | ||
68 | adds #4,er6 | ||
69 | dec.l #1,er4 | ||
70 | bne 1b | ||
71 | |||
72 | /* .bss clear */ | ||
73 | mov.l #__sbss,er5 | ||
74 | mov.l #__ebss,er4 | ||
75 | sub.l er5,er4 | ||
76 | shlr.l #2,er4 | ||
77 | sub.l er0,er0 | ||
78 | 1: | ||
79 | mov.l er0,@er5 | ||
80 | adds #4,er5 | ||
81 | dec.l #1,er4 | ||
82 | bne 1b | ||
83 | |||
84 | /* copy kernel commandline */ | ||
85 | mov.l #COMMAND_START,er5 | ||
86 | mov.l #SYMBOL_NAME(_command_line),er6 | ||
87 | mov.w #512,r4 | ||
88 | eepmov.w | ||
89 | |||
90 | /* linux kernel start */ | ||
91 | ldc #0x90,ccr /* running kernel */ | ||
92 | mov.l #SYMBOL_NAME(init_thread_union),sp | ||
93 | add.l #0x2000,sp | ||
94 | jsr @_start_kernel | ||
95 | _exit: | ||
96 | |||
97 | jmp _exit | ||
98 | |||
99 | rts | ||
100 | |||
101 | /* I/O port assign information */ | ||
102 | __platform_gpio_table: | ||
103 | mov.l #gpio_table,er0 | ||
104 | rts | ||
105 | |||
106 | #define INIT_REGS_DATA(REGS,DATA) \ | ||
107 | .word ((REGS) & 0xffff),DATA | ||
108 | |||
109 | init_regs: | ||
110 | INIT_REGS_DATA(ASTCR,0xff) | ||
111 | INIT_REGS_DATA(RDNCR,0x00) | ||
112 | INIT_REGS_DATA(ABWCR,0x80) | ||
113 | INIT_REGS_DATA(WTCRAH,0x27) | ||
114 | INIT_REGS_DATA(WTCRAL,0x77) | ||
115 | INIT_REGS_DATA(WTCRBH,0x71) | ||
116 | INIT_REGS_DATA(WTCRBL,0x22) | ||
117 | INIT_REGS_DATA(CSACRH,0x80) | ||
118 | INIT_REGS_DATA(CSACRL,0x80) | ||
119 | INIT_REGS_DATA(BROMCRH,0xa0) | ||
120 | INIT_REGS_DATA(BROMCRL,0xa0) | ||
121 | INIT_REGS_DATA(P3DDR,0x3a) | ||
122 | INIT_REGS_DATA(P3ODR,0x06) | ||
123 | INIT_REGS_DATA(PADDR,0xff) | ||
124 | INIT_REGS_DATA(PFDDR,0xfe) | ||
125 | INIT_REGS_DATA(PGDDR,0x0f) | ||
126 | INIT_REGS_DATA(PHDDR,0x0f) | ||
127 | INIT_REGS_DATA(PFCR0,0xff) | ||
128 | INIT_REGS_DATA(PFCR2,0x0d) | ||
129 | INIT_REGS_DATA(ITSR, 0x00) | ||
130 | INIT_REGS_DATA(ITSR+1,0x3f) | ||
131 | INIT_REGS_DATA(INTCR,0x20) | ||
132 | |||
133 | .word 0 | ||
134 | |||
135 | gpio_table: | ||
136 | ;; P1DDR | ||
137 | .byte 0x00,0x00 | ||
138 | ;; P2DDR | ||
139 | .byte 0x00,0x00 | ||
140 | ;; P3DDR | ||
141 | .byte 0x00,0x00 | ||
142 | ;; dummy | ||
143 | .byte 0x00,0x00 | ||
144 | ;; P5DDR | ||
145 | .byte 0x00,0x00 | ||
146 | ;; P6DDR | ||
147 | .byte 0x00,0x00 | ||
148 | ;; P7DDR | ||
149 | .byte 0x00,0x00 | ||
150 | ;; P8DDR | ||
151 | .byte 0x00,0x00 | ||
152 | ;; dummy | ||
153 | .byte 0x00,0x00 | ||
154 | ;; PADDR | ||
155 | .byte 0x00,0x00 | ||
156 | ;; PBDDR | ||
157 | .byte 0x00,0x00 | ||
158 | ;; PCDDR | ||
159 | .byte 0x00,0x00 | ||
160 | ;; PDDDR | ||
161 | .byte 0x00,0x00 | ||
162 | ;; PEDDR | ||
163 | .byte 0x00,0x00 | ||
164 | ;; PFDDR | ||
165 | .byte 0x00,0x00 | ||
166 | ;; PGDDR | ||
167 | .byte 0x00,0x00 | ||
168 | ;; PHDDR | ||
169 | .byte 0x00,0x00 | ||
170 | |||
171 | .section .rodata | ||
172 | __target_name: | ||
173 | .asciz "EDOSK-2674" | ||
174 | |||
175 | .section .bss | ||
176 | __command_line: | ||
177 | .space 512 | ||
178 | |||
179 | /* interrupt vector */ | ||
180 | .section .vectors,"ax" | ||
181 | .long __start | ||
182 | .long __start | ||
183 | vector = 2 | ||
184 | .rept 126 | ||
185 | .long _interrupt_redirect_table+vector*4 | ||
186 | vector = vector + 1 | ||
187 | .endr | ||
diff --git a/arch/h8300/platform/h8s/edosk2674/timer.c b/arch/h8300/platform/h8s/edosk2674/timer.c new file mode 100644 index 000000000000..9441a4f1631f --- /dev/null +++ b/arch/h8300/platform/h8s/edosk2674/timer.c | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/platform/h8s/edosk2674/timer.c | ||
3 | * | ||
4 | * Yoshinori Sato <ysato@users.sourceforge.jp> | ||
5 | * | ||
6 | * Platform depend Timer Handler | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #include <linux/config.h> | ||
11 | #include <linux/errno.h> | ||
12 | #include <linux/sched.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/param.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <linux/mm.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/timex.h> | ||
20 | |||
21 | #include <asm/segment.h> | ||
22 | #include <asm/io.h> | ||
23 | #include <asm/irq.h> | ||
24 | #include <asm/regs267x.h> | ||
25 | |||
26 | #define CMFA 6 | ||
27 | |||
28 | #define CMIEA 0x40 | ||
29 | #define CCLR_CMA 0x08 | ||
30 | #define CLK_DIV8192 0x03 | ||
31 | |||
32 | #define H8300_TIMER_FREQ CONFIG_CPU_CLOCK*1000/8192 /* Timer input freq. */ | ||
33 | |||
34 | void __init platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *)) | ||
35 | { | ||
36 | /* 8bit timer module enabled */ | ||
37 | ctrl_outb(ctrl_inb(MSTPCRL) & ~0x01, MSTPCRL); | ||
38 | /* setup 8bit timer ch1 */ | ||
39 | ctrl_outb(H8300_TIMER_FREQ / HZ, _8TCORA1); /* set interval */ | ||
40 | ctrl_outb(0x00, _8TCSR1); /* no output */ | ||
41 | request_irq(76, timer_int, 0, "timer" ,0); | ||
42 | ctrl_outb(CMIEA|CCLR_CMA|CLK_DIV8192, _8TCR1); /* start count */ | ||
43 | } | ||
44 | |||
45 | void platform_timer_eoi(void) | ||
46 | { | ||
47 | *(volatile unsigned char *)_8TCSR1 &= ~(1 << CMFA); | ||
48 | } | ||
49 | |||
50 | void platform_gettod(int *year, int *mon, int *day, int *hour, | ||
51 | int *min, int *sec) | ||
52 | { | ||
53 | /* FIXME! not RTC support */ | ||
54 | *year = *mon = *day = *hour = *min = *sec = 0; | ||
55 | } | ||
diff --git a/arch/h8300/platform/h8s/entry.S b/arch/h8300/platform/h8s/entry.S new file mode 100644 index 000000000000..a7a53c84c801 --- /dev/null +++ b/arch/h8300/platform/h8s/entry.S | |||
@@ -0,0 +1,331 @@ | |||
1 | /* -*- mode: asm -*- | ||
2 | * | ||
3 | * linux/arch/h8300/platform/h8s/entry.S | ||
4 | * | ||
5 | * Yoshinori Sato <ysato@users.sourceforge.jp> | ||
6 | * | ||
7 | * fairly heavy changes to fix syscall args and signal processing | ||
8 | * by David McCullough <davidm@snapgear.com> | ||
9 | */ | ||
10 | |||
11 | /* | ||
12 | * entry.S | ||
13 | * include exception/interrupt gateway | ||
14 | * system call entry | ||
15 | */ | ||
16 | |||
17 | #include <linux/sys.h> | ||
18 | #include <linux/config.h> | ||
19 | #include <asm/unistd.h> | ||
20 | #include <asm/setup.h> | ||
21 | #include <asm/segment.h> | ||
22 | #include <asm/linkage.h> | ||
23 | #include <asm/asm-offsets.h> | ||
24 | #include <asm/thread_info.h> | ||
25 | #include <asm/errno.h> | ||
26 | |||
27 | .h8300s | ||
28 | |||
29 | /* CPU context save/restore macros. */ | ||
30 | |||
31 | .macro SAVE_ALL | ||
32 | mov.l er0,@-sp | ||
33 | |||
34 | stc ccr,r0l /* check kernel mode */ | ||
35 | orc #0x10,ccr | ||
36 | btst #4,r0l | ||
37 | bne 5f | ||
38 | |||
39 | mov.l sp,@SYMBOL_NAME(sw_usp) /* user mode */ | ||
40 | mov.l @sp,er0 | ||
41 | mov.l @SYMBOL_NAME(sw_ksp),sp | ||
42 | sub.l #(LRET-LORIG),sp /* allocate LORIG - LRET */ | ||
43 | stm.l er0-er3,@-sp | ||
44 | mov.l @SYMBOL_NAME(sw_usp),er0 | ||
45 | mov.l @(10:16,er0),er1 /* copy the RET addr */ | ||
46 | mov.l er1,@(LRET-LER3:16,sp) | ||
47 | mov.w @(8:16,er0),r1 | ||
48 | mov.w r1,@(LEXR-LER3:16,sp) /* copy EXR */ | ||
49 | |||
50 | mov.w e1,r1 /* e1 highbyte = ccr */ | ||
51 | and #0xef,r1h /* mask mode? flag */ | ||
52 | sub.w r0,r0 | ||
53 | mov.b r1h,r0l | ||
54 | mov.w r0,@(LCCR-LER3:16,sp) /* copy ccr */ | ||
55 | mov.l @(LORIG-LER3:16,sp),er0 | ||
56 | mov.l er0,@(LER0-LER3:16,sp) /* copy ER0 */ | ||
57 | bra 6f | ||
58 | 5: | ||
59 | mov.l @sp,er0 /* kernel mode */ | ||
60 | subs #2,sp /* dummy ccr */ | ||
61 | stm.l er0-er3,@-sp | ||
62 | mov.w @(LRET-LER3:16,sp),r1 /* copy old ccr */ | ||
63 | mov.b r1h,r1l | ||
64 | mov.b #0,r1h | ||
65 | mov.w r1,@(LCCR-LER3:16,sp) | ||
66 | 6: | ||
67 | mov.l er6,@-sp /* syscall arg #6 */ | ||
68 | mov.l er5,@-sp /* syscall arg #5 */ | ||
69 | mov.l er4,@-sp /* syscall arg #4 */ | ||
70 | .endm | ||
71 | |||
72 | .macro RESTORE_ALL | ||
73 | mov.l @sp+,er4 | ||
74 | mov.l @sp+,er5 | ||
75 | mov.l @sp+,er6 | ||
76 | ldm.l @sp+,er2-er3 | ||
77 | mov.w @(LCCR-LER1:16,sp),r0 /* check kernel mode */ | ||
78 | btst #4,r0l | ||
79 | bne 7f | ||
80 | |||
81 | orc #0x80,ccr | ||
82 | mov.l @SYMBOL_NAME(sw_usp),er0 | ||
83 | mov.l @(LER0-LER1:16,sp),er1 /* restore ER0 */ | ||
84 | mov.l er1,@er0 | ||
85 | mov.w @(LEXR-LER1:16,sp),r1 /* restore EXR */ | ||
86 | mov.b r1l,r1h | ||
87 | mov.w r1,@(8:16,er0) | ||
88 | mov.w @(LCCR-LER1:16,sp),r1 /* restore the RET addr */ | ||
89 | mov.b r1l,r1h | ||
90 | mov.b @(LRET+1-LER1:16,sp),r1l | ||
91 | mov.w r1,e1 | ||
92 | mov.w @(LRET+2-LER1:16,sp),r1 | ||
93 | mov.l er1,@(10:16,er0) | ||
94 | |||
95 | mov.l @sp+,er1 | ||
96 | add.l #(LRET-LER1),sp /* remove LORIG - LRET */ | ||
97 | mov.l sp,@SYMBOL_NAME(sw_ksp) | ||
98 | mov.l er0,sp | ||
99 | bra 8f | ||
100 | 7: | ||
101 | mov.l @sp+,er1 | ||
102 | adds #4,sp | ||
103 | adds #2,sp | ||
104 | 8: | ||
105 | mov.l @sp+,er0 | ||
106 | adds #4,sp /* remove the sw created LVEC */ | ||
107 | rte | ||
108 | .endm | ||
109 | |||
110 | .globl SYMBOL_NAME(system_call) | ||
111 | .globl SYMBOL_NAME(ret_from_exception) | ||
112 | .globl SYMBOL_NAME(ret_from_fork) | ||
113 | .globl SYMBOL_NAME(ret_from_interrupt) | ||
114 | .globl SYMBOL_NAME(interrupt_redirect_table) | ||
115 | .globl SYMBOL_NAME(sw_ksp),SYMBOL_NAME(sw_usp) | ||
116 | .globl SYMBOL_NAME(resume) | ||
117 | .globl SYMBOL_NAME(trace_break) | ||
118 | .globl SYMBOL_NAME(interrupt_entry) | ||
119 | |||
120 | INTERRUPTS = 128 | ||
121 | #if defined(CONFIG_ROMKERNEL) | ||
122 | .section .int_redirect,"ax" | ||
123 | SYMBOL_NAME_LABEL(interrupt_redirect_table) | ||
124 | .rept 7 | ||
125 | .long 0 | ||
126 | .endr | ||
127 | jsr @SYMBOL_NAME(interrupt_entry) /* NMI */ | ||
128 | jmp @SYMBOL_NAME(system_call) /* TRAPA #0 (System call) */ | ||
129 | .long 0 | ||
130 | .long 0 | ||
131 | jmp @SYMBOL_NAME(trace_break) /* TRAPA #3 (breakpoint) */ | ||
132 | .rept INTERRUPTS-12 | ||
133 | jsr @SYMBOL_NAME(interrupt_entry) | ||
134 | .endr | ||
135 | #endif | ||
136 | #if defined(CONFIG_RAMKERNEL) | ||
137 | .globl SYMBOL_NAME(interrupt_redirect_table) | ||
138 | .section .bss | ||
139 | SYMBOL_NAME_LABEL(interrupt_redirect_table) | ||
140 | .space 4 | ||
141 | #endif | ||
142 | |||
143 | .section .text | ||
144 | .align 2 | ||
145 | SYMBOL_NAME_LABEL(interrupt_entry) | ||
146 | SAVE_ALL | ||
147 | mov.w @(LCCR,sp),r0 | ||
148 | btst #4,r0l | ||
149 | bne 1f | ||
150 | mov.l @SYMBOL_NAME(sw_usp),er0 | ||
151 | mov.l @(4:16,er0),er0 | ||
152 | bra 2f | ||
153 | 1: | ||
154 | mov.l @(LVEC:16,sp),er0 | ||
155 | 2: | ||
156 | #if defined(CONFIG_ROMKERNEL) | ||
157 | sub.l #SYMBOL_NAME(interrupt_redirect_table),er0 | ||
158 | #endif | ||
159 | #if defined(CONFIG_RAMKERNEL) | ||
160 | mov.l @SYMBOL_NAME(interrupt_redirect_table),er1 | ||
161 | sub.l er1,er0 | ||
162 | #endif | ||
163 | shlr.l #2,er0 | ||
164 | dec.l #1,er0 | ||
165 | mov.l sp,er1 | ||
166 | subs #4,er1 /* adjust ret_pc */ | ||
167 | jsr @SYMBOL_NAME(process_int) | ||
168 | mov.l @SYMBOL_NAME(irq_stat)+CPUSTAT_SOFTIRQ_PENDING,er0 | ||
169 | beq 1f | ||
170 | jsr @SYMBOL_NAME(do_softirq) | ||
171 | 1: | ||
172 | jmp @SYMBOL_NAME(ret_from_exception) | ||
173 | |||
174 | SYMBOL_NAME_LABEL(system_call) | ||
175 | subs #4,sp /* dummy LVEC */ | ||
176 | SAVE_ALL | ||
177 | mov.w @(LCCR:16,sp),r1 | ||
178 | bset #4,r1l | ||
179 | ldc r1l,ccr /* restore ccr */ | ||
180 | mov.l er0,er4 | ||
181 | mov.l #-ENOSYS,er0 | ||
182 | mov.l er0,@(LER0:16,sp) | ||
183 | |||
184 | /* save top of frame */ | ||
185 | mov.l sp,er0 | ||
186 | jsr @SYMBOL_NAME(set_esp0) | ||
187 | cmp.l #NR_syscalls,er4 | ||
188 | bcc SYMBOL_NAME(ret_from_exception):16 | ||
189 | shll.l #2,er4 | ||
190 | mov.l #SYMBOL_NAME(sys_call_table),er0 | ||
191 | add.l er4,er0 | ||
192 | mov.l @er0,er0 | ||
193 | mov.l er0,er4 | ||
194 | beq SYMBOL_NAME(ret_from_exception):16 | ||
195 | mov.l sp,er2 | ||
196 | and.w #0xe000,r2 | ||
197 | mov.b @((TASK_FLAGS+3-(TIF_SYSCALL_TRACE >> 3)):16,er2),r2l | ||
198 | btst #(TIF_SYSCALL_TRACE & 7),r2l | ||
199 | mov.l @(LER1:16,sp),er0 | ||
200 | mov.l @(LER2:16,sp),er1 | ||
201 | mov.l @(LER3:16,sp),er2 | ||
202 | jsr @er4 | ||
203 | mov.l er0,@(LER0:16,sp) /* save the return value */ | ||
204 | #if defined(CONFIG_SYSCALL_PRINT) | ||
205 | jsr @SYMBOL_NAME(syscall_print) | ||
206 | #endif | ||
207 | bra SYMBOL_NAME(ret_from_exception):8 | ||
208 | 1: | ||
209 | jsr SYMBOL_NAME(syscall_trace) | ||
210 | mov.l @(LER1:16,sp),er0 | ||
211 | mov.l @(LER2:16,sp),er1 | ||
212 | mov.l @(LER3:16,sp),er2 | ||
213 | jsr @er4 | ||
214 | mov.l er0,@(LER0:16,sp) /* save the return value */ | ||
215 | jsr @SYMBOL_NAME(syscall_trace) | ||
216 | bra SYMBOL_NAME(ret_from_exception):8 | ||
217 | |||
218 | SYMBOL_NAME_LABEL(ret_from_fork) | ||
219 | mov.l er2,er0 | ||
220 | jsr @SYMBOL_NAME(schedule_tail) | ||
221 | bra SYMBOL_NAME(ret_from_exception):8 | ||
222 | |||
223 | SYMBOL_NAME_LABEL(reschedule) | ||
224 | /* save top of frame */ | ||
225 | mov.l sp,er0 | ||
226 | jsr @SYMBOL_NAME(set_esp0) | ||
227 | jsr @SYMBOL_NAME(schedule) | ||
228 | |||
229 | SYMBOL_NAME_LABEL(ret_from_exception) | ||
230 | #if defined(CONFIG_PREEMPT) | ||
231 | orc #0x80,ccr | ||
232 | #endif | ||
233 | SYMBOL_NAME_LABEL(ret_from_interrupt) | ||
234 | mov.b @(LCCR+1:16,sp),r0l | ||
235 | btst #4,r0l /* check if returning to kernel */ | ||
236 | bne done:8 /* if so, skip resched, signals */ | ||
237 | andc #0x7f,ccr | ||
238 | mov.l sp,er4 | ||
239 | and.w #0xe000,r4 | ||
240 | mov.l @(TI_FLAGS:16,er4),er1 | ||
241 | and.l #_TIF_WORK_MASK,er1 | ||
242 | beq done:8 | ||
243 | 1: | ||
244 | mov.l @(TI_FLAGS:16,er4),er1 | ||
245 | btst #TIF_NEED_RESCHED,r1l | ||
246 | bne SYMBOL_NAME(reschedule):16 | ||
247 | mov.l sp,er0 | ||
248 | subs #4,er0 /* adjust retpc */ | ||
249 | mov.l er2,er1 | ||
250 | jsr @SYMBOL_NAME(do_signal) | ||
251 | #if defined(CONFIG_PREEMPT) | ||
252 | bra done:8 /* userspace thoru */ | ||
253 | 3: | ||
254 | btst #4,r0l | ||
255 | beq done:8 /* userspace thoru */ | ||
256 | 4: | ||
257 | mov.l @(TI_PRE_COUNT:16,er4),er1 | ||
258 | bne done:8 | ||
259 | mov.l @(TI_FLAGS:16,er4),er1 | ||
260 | btst #TIF_NEED_RESCHED,r1l | ||
261 | beq done:8 | ||
262 | mov.b r0l,r0l | ||
263 | bpl done:8 /* interrupt off (exception path?) */ | ||
264 | mov.l #PREEMPT_ACTIVE,er1 | ||
265 | mov.l er1,@(TI_PRE_COUNT:16,er4) | ||
266 | andc #0x7f,ccr | ||
267 | jsr @SYMBOL_NAME(schedule) | ||
268 | sub.l er1,er1 | ||
269 | mov.l er1,@(TI_PRE_COUNT:16,er4) | ||
270 | orc #0x80,ccr | ||
271 | bra 4b:8 | ||
272 | #endif | ||
273 | done: | ||
274 | RESTORE_ALL /* Does RTE */ | ||
275 | |||
276 | SYMBOL_NAME_LABEL(resume) | ||
277 | /* | ||
278 | * er0 = prev | ||
279 | * er1 = next | ||
280 | * return last in er2 | ||
281 | */ | ||
282 | |||
283 | /* save sr */ | ||
284 | sub.w r3,r3 | ||
285 | stc ccr,r3l | ||
286 | stc exr,r3h | ||
287 | mov.w r3,@(THREAD_CCR+2:16,er0) | ||
288 | |||
289 | /* disable interrupts */ | ||
290 | orc #0x80,ccr | ||
291 | mov.l @SYMBOL_NAME(sw_usp),er3 | ||
292 | mov.l er3,@(THREAD_USP:16,er0) | ||
293 | mov.l sp,@(THREAD_KSP:16,er0) | ||
294 | |||
295 | /* Skip address space switching if they are the same. */ | ||
296 | /* FIXME: what did we hack out of here, this does nothing! */ | ||
297 | |||
298 | mov.l @(THREAD_USP:16,er1),er0 | ||
299 | mov.l er0,@SYMBOL_NAME(sw_usp) | ||
300 | mov.l @(THREAD_KSP:16,er1),sp | ||
301 | |||
302 | /* restore status register */ | ||
303 | mov.w @(THREAD_CCR+2:16,er1),r3 | ||
304 | |||
305 | ldc r3l,ccr | ||
306 | ldc r3h,exr | ||
307 | |||
308 | rts | ||
309 | |||
310 | SYMBOL_NAME_LABEL(trace_break) | ||
311 | subs #4,sp /* dummy LVEC */ | ||
312 | SAVE_ALL | ||
313 | sub.l er1,er1 | ||
314 | dec.l #1,er1 | ||
315 | mov.l er1,@(LORIG,sp) | ||
316 | mov.l sp,er0 | ||
317 | jsr @SYMBOL_NAME(set_esp0) | ||
318 | mov.l @SYMBOL_NAME(sw_usp),er0 | ||
319 | mov.l @er0,er1 | ||
320 | subs #2,er1 | ||
321 | mov.l er1,@er0 | ||
322 | and.w #0xff,e1 | ||
323 | mov.l er1,er0 | ||
324 | jsr @SYMBOL_NAME(trace_trap) | ||
325 | jmp @SYMBOL_NAME(ret_from_exception) | ||
326 | |||
327 | .section .bss | ||
328 | SYMBOL_NAME_LABEL(sw_ksp) | ||
329 | .space 4 | ||
330 | SYMBOL_NAME_LABEL(sw_usp) | ||
331 | .space 4 | ||
diff --git a/arch/h8300/platform/h8s/generic/Makefile b/arch/h8300/platform/h8s/generic/Makefile new file mode 100644 index 000000000000..055d53a9811b --- /dev/null +++ b/arch/h8300/platform/h8s/generic/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | # | ||
2 | # Makefile for the linux kernel. | ||
3 | # | ||
4 | |||
5 | extra-y = crt0_$(MODEL).o | ||
6 | obj-y := timer.o | ||
diff --git a/arch/h8300/platform/h8s/generic/crt0_ram.S b/arch/h8300/platform/h8s/generic/crt0_ram.S new file mode 100644 index 000000000000..86f450178466 --- /dev/null +++ b/arch/h8300/platform/h8s/generic/crt0_ram.S | |||
@@ -0,0 +1,128 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/platform/h8s/edosk2674/crt0_ram.S | ||
3 | * | ||
4 | * Yoshinori Sato <ysato@users.sourceforge.jp> | ||
5 | * | ||
6 | * Platform depend startup | ||
7 | * Target Archtecture: generic | ||
8 | * Memory Layout : RAM | ||
9 | */ | ||
10 | |||
11 | #define ASSEMBLY | ||
12 | |||
13 | #include <linux/config.h> | ||
14 | #include <asm/linkage.h> | ||
15 | #include <asm/regs267x.h> | ||
16 | |||
17 | #if !defined(CONFIG_BLKDEV_RESERVE) | ||
18 | #if defined(CONFIG_GDB_DEBUG) | ||
19 | #define RAMEND (__ramend - 0xc000) | ||
20 | #else | ||
21 | #define RAMEND __ramend | ||
22 | #endif | ||
23 | #else | ||
24 | #define RAMEND CONFIG_BLKDEV_RESERVE_ADDRESS | ||
25 | #endif | ||
26 | |||
27 | .global SYMBOL_NAME(_start) | ||
28 | .global SYMBOL_NAME(_command_line) | ||
29 | .global SYMBOL_NAME(_platform_gpio_table) | ||
30 | .global SYMBOL_NAME(_target_name) | ||
31 | |||
32 | .h8300s | ||
33 | |||
34 | .section .text | ||
35 | .file "crt0_ram.S" | ||
36 | |||
37 | /* CPU Reset entry */ | ||
38 | SYMBOL_NAME_LABEL(_start) | ||
39 | mov.l #RAMEND,sp | ||
40 | ldc #0x80,ccr | ||
41 | ldc #0x00,exr | ||
42 | |||
43 | /* Peripheral Setup */ | ||
44 | bclr #4,@INTCR:8 /* interrupt mode 2 */ | ||
45 | bset #5,@INTCR:8 | ||
46 | |||
47 | #if defined(CONFIG_MTD_UCLINUX) | ||
48 | /* move romfs image */ | ||
49 | jsr @__move_romfs | ||
50 | #endif | ||
51 | |||
52 | /* .bss clear */ | ||
53 | mov.l #__sbss,er5 | ||
54 | mov.l er5,er6 | ||
55 | mov.l #__ebss,er4 | ||
56 | sub.l er5,er4 | ||
57 | shlr #2,er4 | ||
58 | sub.l er0,er0 | ||
59 | 1: | ||
60 | mov.l er0,@er5 | ||
61 | adds #4,er5 | ||
62 | dec.l #1,er4 | ||
63 | bne 1b | ||
64 | |||
65 | /* copy kernel commandline */ | ||
66 | mov.l #COMMAND_START,er5 | ||
67 | mov.l #SYMBOL_NAME(command_line),er6 | ||
68 | mov.w #512,r4 | ||
69 | eepmov.w | ||
70 | |||
71 | /* uClinux kernel start */ | ||
72 | ldc #0x90,ccr /* running kernel */ | ||
73 | mov.l #SYMBOL_NAME(init_thread_union),sp | ||
74 | add.l #0x2000,sp | ||
75 | jsr @_start_kernel | ||
76 | _exit: | ||
77 | |||
78 | jmp _exit | ||
79 | |||
80 | rts | ||
81 | |||
82 | /* I/O port assign information */ | ||
83 | __platform_gpio_table: | ||
84 | mov.l #gpio_table,er0 | ||
85 | rts | ||
86 | |||
87 | gpio_table: | ||
88 | ;; P1DDR | ||
89 | ;; used,ddr | ||
90 | .byte 0x00,0x00 | ||
91 | ;; P2DDR | ||
92 | .byte 0x00,0x00 | ||
93 | ;; P3DDR | ||
94 | .byte 0x00,0x00 | ||
95 | ;; dummy | ||
96 | .byte 0x00,0x00 | ||
97 | ;; P5DDR | ||
98 | .byte 0x00,0x00 | ||
99 | ;; P6DDR | ||
100 | .byte 0x00,0x00 | ||
101 | ;; P7DDR | ||
102 | .byte 0x00,0x00 | ||
103 | ;; P8DDR | ||
104 | .byte 0x00,0x00 | ||
105 | ;; dummy | ||
106 | .byte 0x00,0x00 | ||
107 | ;; PADDR | ||
108 | .byte 0x00,0x00 | ||
109 | ;; PBDDR | ||
110 | .byte 0x00,0x00 | ||
111 | ;; PCDDR | ||
112 | .byte 0x00,0x00 | ||
113 | ;; PDDDR | ||
114 | .byte 0x00,0x00 | ||
115 | ;; PEDDR | ||
116 | .byte 0x00,0x00 | ||
117 | ;; PFDDR | ||
118 | .byte 0x00,0x00 | ||
119 | ;; PGDDR | ||
120 | .byte 0x00,0x00 | ||
121 | ;; PHDDR | ||
122 | .byte 0x00,0x00 | ||
123 | |||
124 | __target_name: | ||
125 | .asciz "generic" | ||
126 | |||
127 | .section .bootvec,"ax" | ||
128 | jmp @SYMBOL_NAME(_start) | ||
diff --git a/arch/h8300/platform/h8s/generic/crt0_rom.S b/arch/h8300/platform/h8s/generic/crt0_rom.S new file mode 100644 index 000000000000..e18e41202282 --- /dev/null +++ b/arch/h8300/platform/h8s/generic/crt0_rom.S | |||
@@ -0,0 +1,129 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/platform/h8s/generic/crt0_rom.S | ||
3 | * | ||
4 | * Yoshinori Sato <ysato@users.sourceforge.jp> | ||
5 | * | ||
6 | * Platform depend startup | ||
7 | * Target Archtecture: generic | ||
8 | * Memory Layout : ROM | ||
9 | */ | ||
10 | |||
11 | #define ASSEMBLY | ||
12 | |||
13 | #include <linux/config.h> | ||
14 | #include <asm/linkage.h> | ||
15 | #include <asm/regs267x.h> | ||
16 | |||
17 | .global SYMBOL_NAME(_start) | ||
18 | .global SYMBOL_NAME(_command_line) | ||
19 | .global SYMBOL_NAME(_platform_gpio_table) | ||
20 | .global SYMBOL_NAME(_target_name) | ||
21 | |||
22 | .h8300s | ||
23 | .section .text | ||
24 | .file "crt0_rom.S" | ||
25 | |||
26 | /* CPU Reset entry */ | ||
27 | SYMBOL_NAME_LABEL(_start) | ||
28 | mov.l #__ramend,sp | ||
29 | ldc #0x80,ccr | ||
30 | ldc #0,exr | ||
31 | bclr #4,@INTCR:8 | ||
32 | bset #5,@INTCR:8 /* Interrupt mode 2 */ | ||
33 | |||
34 | /* Peripheral Setup */ | ||
35 | |||
36 | /* copy .data */ | ||
37 | #if !defined(CONFIG_H8S_SIM) | ||
38 | mov.l #__begin_data,er5 | ||
39 | mov.l #__sdata,er6 | ||
40 | mov.l #__edata,er4 | ||
41 | sub.l er6,er4 | ||
42 | shlr.l #2,er4 | ||
43 | 1: | ||
44 | mov.l @er5+,er0 | ||
45 | mov.l er0,@er6 | ||
46 | adds #4,er6 | ||
47 | dec.l #1,er4 | ||
48 | bne 1b | ||
49 | #endif | ||
50 | |||
51 | /* .bss clear */ | ||
52 | mov.l #__sbss,er5 | ||
53 | mov.l #__ebss,er4 | ||
54 | sub.l er5,er4 | ||
55 | shlr.l #2,er4 | ||
56 | sub.l er0,er0 | ||
57 | 1: | ||
58 | mov.l er0,@er5 | ||
59 | adds #4,er5 | ||
60 | dec.l #1,er4 | ||
61 | bne 1b | ||
62 | |||
63 | /* linux kernel start */ | ||
64 | ldc #0x90,ccr /* running kernel */ | ||
65 | mov.l #SYMBOL_NAME(init_thread_union),sp | ||
66 | add.l #0x2000,sp | ||
67 | jsr @_start_kernel | ||
68 | _exit: | ||
69 | |||
70 | jmp _exit | ||
71 | |||
72 | rts | ||
73 | |||
74 | /* I/O port assign information */ | ||
75 | __platform_gpio_table: | ||
76 | mov.l #gpio_table,er0 | ||
77 | rts | ||
78 | |||
79 | gpio_table: | ||
80 | ;; P1DDR | ||
81 | .byte 0x00,0x00 | ||
82 | ;; P2DDR | ||
83 | .byte 0x00,0x00 | ||
84 | ;; P3DDR | ||
85 | .byte 0x00,0x00 | ||
86 | ;; P4DDR | ||
87 | .byte 0x00,0x00 | ||
88 | ;; P5DDR | ||
89 | .byte 0x00,0x00 | ||
90 | ;; P6DDR | ||
91 | .byte 0x00,0x00 | ||
92 | ;; dummy | ||
93 | .byte 0x00,0x00 | ||
94 | ;; P8DDR | ||
95 | .byte 0x00,0x00 | ||
96 | ;; PADDR | ||
97 | .byte 0x00,0x00 | ||
98 | ;; PBDDR | ||
99 | .byte 0x00,0x00 | ||
100 | ;; PCDDR | ||
101 | .byte 0x00,0x00 | ||
102 | ;; PDDDR | ||
103 | .byte 0x00,0x00 | ||
104 | ;; PEDDR | ||
105 | .byte 0x00,0x00 | ||
106 | ;; PFDDR | ||
107 | .byte 0x00,0x00 | ||
108 | ;; PGDDR | ||
109 | .byte 0x00,0x00 | ||
110 | ;; PHDDR | ||
111 | .byte 0x00,0x00 | ||
112 | |||
113 | .section .rodata | ||
114 | __target_name: | ||
115 | .asciz "generic" | ||
116 | |||
117 | .section .bss | ||
118 | __command_line: | ||
119 | .space 512 | ||
120 | |||
121 | /* interrupt vector */ | ||
122 | .section .vectors,"ax" | ||
123 | .long __start | ||
124 | .long __start | ||
125 | vector = 2 | ||
126 | .rept 126-1 | ||
127 | .long _interrupt_redirect_table+vector*4 | ||
128 | vector = vector + 1 | ||
129 | .endr | ||
diff --git a/arch/h8300/platform/h8s/generic/timer.c b/arch/h8300/platform/h8s/generic/timer.c new file mode 100644 index 000000000000..633cd8e1c21d --- /dev/null +++ b/arch/h8300/platform/h8s/generic/timer.c | |||
@@ -0,0 +1,54 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/platform/h8s/generic/timer.c | ||
3 | * | ||
4 | * Yoshinori Sato <ysato@users.sourceforge.jp> | ||
5 | * | ||
6 | * Platform depend Timer Handler | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #include <linux/config.h> | ||
11 | #include <linux/errno.h> | ||
12 | #include <linux/sched.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/param.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <linux/mm.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/timex.h> | ||
20 | |||
21 | #include <asm/segment.h> | ||
22 | #include <asm/io.h> | ||
23 | #include <asm/irq.h> | ||
24 | #include <asm/regs267x.h> | ||
25 | |||
26 | #define CMFA 6 | ||
27 | |||
28 | #define CMIEA 0x40 | ||
29 | #define CCLR_CMA 0x08 | ||
30 | #define CLK_DIV8192 0x03 | ||
31 | |||
32 | #define H8300_TIMER_FREQ CONFIG_CPU_CLOCK*1000/8192 /* Timer input freq. */ | ||
33 | |||
34 | void __init platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *)) | ||
35 | { | ||
36 | /* 8bit timer module enabled */ | ||
37 | ctrl_outb(ctrl_inb(MSTPCRL) & ~0x01, MSTPCRL); | ||
38 | /* setup 8bit timer ch1 */ | ||
39 | ctrl_outb(H8300_TIMER_FREQ / HZ, _8TCORA1); /* set interval */ | ||
40 | ctrl_outb(0x00, _8TCSR1); /* no output */ | ||
41 | request_irq(76, timer_int, 0, "timer" ,0); | ||
42 | ctrl_outb(CMIEA|CCLR_CMA|CLK_DIV8192, _8TCR1); /* start count */ | ||
43 | } | ||
44 | |||
45 | void platform_timer_eoi(void) | ||
46 | { | ||
47 | *(volatile unsigned char *)_8TCSR1 &= ~(1 << CMFA); | ||
48 | } | ||
49 | |||
50 | void platform_gettod(int *year, int *mon, int *day, int *hour, | ||
51 | int *min, int *sec) | ||
52 | { | ||
53 | *year = *mon = *day = *hour = *min = *sec = 0; | ||
54 | } | ||
diff --git a/arch/h8300/platform/h8s/ints.c b/arch/h8300/platform/h8s/ints.c new file mode 100644 index 000000000000..5441cdd12a39 --- /dev/null +++ b/arch/h8300/platform/h8s/ints.c | |||
@@ -0,0 +1,303 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/platform/h8s/ints.c | ||
3 | * | ||
4 | * Yoshinori Sato <ysato@users.sourceforge.jp> | ||
5 | * | ||
6 | * Based on linux/arch/$(ARCH)/platform/$(PLATFORM)/ints.c | ||
7 | * | ||
8 | * This file is subject to the terms and conditions of the GNU General Public | ||
9 | * License. See the file COPYING in the main directory of this archive | ||
10 | * for more details. | ||
11 | * | ||
12 | * Copyright 1996 Roman Zippel | ||
13 | * Copyright 1999 D. Jeff Dionne <jeff@rt-control.com> | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/types.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/kernel_stat.h> | ||
21 | #include <linux/seq_file.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/bootmem.h> | ||
24 | #include <linux/random.h> | ||
25 | #include <linux/hardirq.h> | ||
26 | |||
27 | #include <asm/system.h> | ||
28 | #include <asm/irq.h> | ||
29 | #include <asm/traps.h> | ||
30 | #include <asm/io.h> | ||
31 | #include <asm/setup.h> | ||
32 | #include <asm/gpio.h> | ||
33 | #include <asm/regs267x.h> | ||
34 | #include <asm/errno.h> | ||
35 | |||
36 | /* | ||
37 | * This structure has only 4 elements for speed reasons | ||
38 | */ | ||
39 | typedef struct irq_handler { | ||
40 | irqreturn_t (*handler)(int, void *, struct pt_regs *); | ||
41 | int flags; | ||
42 | int count; | ||
43 | void *dev_id; | ||
44 | const char *devname; | ||
45 | } irq_handler_t; | ||
46 | |||
47 | static irq_handler_t *irq_list[NR_IRQS]; | ||
48 | |||
49 | /* IRQ pin assignment */ | ||
50 | struct irq_pins { | ||
51 | unsigned char port_no; | ||
52 | unsigned char bit_no; | ||
53 | }; | ||
54 | /* ISTR = 0 */ | ||
55 | const static struct irq_pins irq_assign_table0[16]={ | ||
56 | {H8300_GPIO_P5,H8300_GPIO_B0},{H8300_GPIO_P5,H8300_GPIO_B1}, | ||
57 | {H8300_GPIO_P5,H8300_GPIO_B2},{H8300_GPIO_P5,H8300_GPIO_B3}, | ||
58 | {H8300_GPIO_P5,H8300_GPIO_B4},{H8300_GPIO_P5,H8300_GPIO_B5}, | ||
59 | {H8300_GPIO_P5,H8300_GPIO_B6},{H8300_GPIO_P5,H8300_GPIO_B7}, | ||
60 | {H8300_GPIO_P6,H8300_GPIO_B0},{H8300_GPIO_P6,H8300_GPIO_B1}, | ||
61 | {H8300_GPIO_P6,H8300_GPIO_B2},{H8300_GPIO_P6,H8300_GPIO_B3}, | ||
62 | {H8300_GPIO_P6,H8300_GPIO_B4},{H8300_GPIO_P6,H8300_GPIO_B5}, | ||
63 | {H8300_GPIO_PF,H8300_GPIO_B1},{H8300_GPIO_PF,H8300_GPIO_B2}, | ||
64 | }; | ||
65 | /* ISTR = 1 */ | ||
66 | const static struct irq_pins irq_assign_table1[16]={ | ||
67 | {H8300_GPIO_P8,H8300_GPIO_B0},{H8300_GPIO_P8,H8300_GPIO_B1}, | ||
68 | {H8300_GPIO_P8,H8300_GPIO_B2},{H8300_GPIO_P8,H8300_GPIO_B3}, | ||
69 | {H8300_GPIO_P8,H8300_GPIO_B4},{H8300_GPIO_P8,H8300_GPIO_B5}, | ||
70 | {H8300_GPIO_PH,H8300_GPIO_B2},{H8300_GPIO_PH,H8300_GPIO_B3}, | ||
71 | {H8300_GPIO_P2,H8300_GPIO_B0},{H8300_GPIO_P2,H8300_GPIO_B1}, | ||
72 | {H8300_GPIO_P2,H8300_GPIO_B2},{H8300_GPIO_P2,H8300_GPIO_B3}, | ||
73 | {H8300_GPIO_P2,H8300_GPIO_B4},{H8300_GPIO_P2,H8300_GPIO_B5}, | ||
74 | {H8300_GPIO_P2,H8300_GPIO_B6},{H8300_GPIO_P2,H8300_GPIO_B7}, | ||
75 | }; | ||
76 | |||
77 | static short use_kmalloc = 0; | ||
78 | |||
79 | extern unsigned long *interrupt_redirect_table; | ||
80 | |||
81 | #define CPU_VECTOR ((unsigned long *)0x000000) | ||
82 | #define ADDR_MASK (0xffffff) | ||
83 | |||
84 | static inline unsigned long *get_vector_address(void) | ||
85 | { | ||
86 | volatile unsigned long *rom_vector = CPU_VECTOR; | ||
87 | unsigned long base,tmp; | ||
88 | int vec_no; | ||
89 | |||
90 | base = rom_vector[EXT_IRQ0] & ADDR_MASK; | ||
91 | |||
92 | /* check romvector format */ | ||
93 | for (vec_no = EXT_IRQ1; vec_no <= EXT_IRQ15; vec_no++) { | ||
94 | if ((base+(vec_no - EXT_IRQ0)*4) != (rom_vector[vec_no] & ADDR_MASK)) | ||
95 | return NULL; | ||
96 | } | ||
97 | |||
98 | /* ramvector base address */ | ||
99 | base -= EXT_IRQ0*4; | ||
100 | |||
101 | /* writerble check */ | ||
102 | tmp = ~(*(unsigned long *)base); | ||
103 | (*(unsigned long *)base) = tmp; | ||
104 | if ((*(unsigned long *)base) != tmp) | ||
105 | return NULL; | ||
106 | return (unsigned long *)base; | ||
107 | } | ||
108 | |||
109 | void __init init_IRQ(void) | ||
110 | { | ||
111 | #if defined(CONFIG_RAMKERNEL) | ||
112 | int i; | ||
113 | unsigned long *ramvec,*ramvec_p; | ||
114 | unsigned long break_vec; | ||
115 | |||
116 | ramvec = get_vector_address(); | ||
117 | if (ramvec == NULL) | ||
118 | panic("interrupt vector serup failed."); | ||
119 | else | ||
120 | printk("virtual vector at 0x%08lx\n",(unsigned long)ramvec); | ||
121 | |||
122 | #if defined(CONFIG_GDB_DEBUG) | ||
123 | /* save orignal break vector */ | ||
124 | break_vec = ramvec[TRAP3_VEC]; | ||
125 | #else | ||
126 | break_vec = VECTOR(trace_break); | ||
127 | #endif | ||
128 | |||
129 | /* create redirect table */ | ||
130 | for (ramvec_p = ramvec, i = 0; i < NR_IRQS; i++) | ||
131 | *ramvec_p++ = REDIRECT(interrupt_entry); | ||
132 | |||
133 | /* set special vector */ | ||
134 | ramvec[TRAP0_VEC] = VECTOR(system_call); | ||
135 | ramvec[TRAP3_VEC] = break_vec; | ||
136 | interrupt_redirect_table = ramvec; | ||
137 | #ifdef DUMP_VECTOR | ||
138 | ramvec_p = ramvec; | ||
139 | for (i = 0; i < NR_IRQS; i++) { | ||
140 | if ((i % 8) == 0) | ||
141 | printk("\n%p: ",ramvec_p); | ||
142 | printk("%p ",*ramvec_p); | ||
143 | ramvec_p++; | ||
144 | } | ||
145 | printk("\n"); | ||
146 | #endif | ||
147 | #endif | ||
148 | } | ||
149 | |||
150 | int request_irq(unsigned int irq, | ||
151 | irqreturn_t (*handler)(int, void *, struct pt_regs *), | ||
152 | unsigned long flags, const char *devname, void *dev_id) | ||
153 | { | ||
154 | unsigned short ptn = 1 << (irq - EXT_IRQ0); | ||
155 | irq_handler_t *irq_handle; | ||
156 | if (irq < 0 || irq >= NR_IRQS) { | ||
157 | printk("Incorrect IRQ %d from %s\n", irq, devname); | ||
158 | return -EINVAL; | ||
159 | } | ||
160 | if (irq_list[irq]) | ||
161 | return -EBUSY; /* already used */ | ||
162 | if (irq >= EXT_IRQ0 && irq <= EXT_IRQ15) { | ||
163 | /* initialize IRQ pin */ | ||
164 | unsigned int port_no,bit_no; | ||
165 | if (*(volatile unsigned short *)ITSR & ptn) { | ||
166 | port_no = irq_assign_table1[irq - EXT_IRQ0].port_no; | ||
167 | bit_no = irq_assign_table1[irq - EXT_IRQ0].bit_no; | ||
168 | } else { | ||
169 | port_no = irq_assign_table0[irq - EXT_IRQ0].port_no; | ||
170 | bit_no = irq_assign_table0[irq - EXT_IRQ0].bit_no; | ||
171 | } | ||
172 | if (H8300_GPIO_RESERVE(port_no, bit_no) == 0) | ||
173 | return -EBUSY; /* pin already use */ | ||
174 | H8300_GPIO_DDR(port_no, bit_no, H8300_GPIO_INPUT); | ||
175 | *(volatile unsigned short *)ISR &= ~ptn; /* ISR clear */ | ||
176 | } | ||
177 | |||
178 | if (use_kmalloc) | ||
179 | irq_handle = (irq_handler_t *)kmalloc(sizeof(irq_handler_t), GFP_ATOMIC); | ||
180 | else { | ||
181 | /* use bootmem allocater */ | ||
182 | irq_handle = (irq_handler_t *)alloc_bootmem(sizeof(irq_handler_t)); | ||
183 | irq_handle = (irq_handler_t *)((unsigned long)irq_handle | 0x80000000); | ||
184 | } | ||
185 | |||
186 | if (irq_handle == NULL) | ||
187 | return -ENOMEM; | ||
188 | |||
189 | irq_handle->handler = handler; | ||
190 | irq_handle->flags = flags; | ||
191 | irq_handle->count = 0; | ||
192 | irq_handle->dev_id = dev_id; | ||
193 | irq_handle->devname = devname; | ||
194 | irq_list[irq] = irq_handle; | ||
195 | if (irq_handle->flags & SA_SAMPLE_RANDOM) | ||
196 | rand_initialize_irq(irq); | ||
197 | |||
198 | /* enable interrupt */ | ||
199 | /* compatible i386 */ | ||
200 | if (irq >= EXT_IRQ0 && irq <= EXT_IRQ15) | ||
201 | *(volatile unsigned short *)IER |= ptn; | ||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | EXPORT_SYMBOL(request_irq); | ||
206 | |||
207 | void free_irq(unsigned int irq, void *dev_id) | ||
208 | { | ||
209 | if (irq >= NR_IRQS) | ||
210 | return; | ||
211 | if (irq_list[irq]->dev_id != dev_id) | ||
212 | printk("%s: Removing probably wrong IRQ %d from %s\n", | ||
213 | __FUNCTION__, irq, irq_list[irq]->devname); | ||
214 | if (irq >= EXT_IRQ0 && irq <= EXT_IRQ15) { | ||
215 | /* disable interrupt & release IRQ pin */ | ||
216 | unsigned short port_no,bit_no; | ||
217 | *(volatile unsigned short *)ISR &= ~(1 << (irq - EXT_IRQ0)); | ||
218 | *(volatile unsigned short *)IER |= 1 << (irq - EXT_IRQ0); | ||
219 | if (*(volatile unsigned short *)ITSR & (1 << (irq - EXT_IRQ0))) { | ||
220 | port_no = irq_assign_table1[irq - EXT_IRQ0].port_no; | ||
221 | bit_no = irq_assign_table1[irq - EXT_IRQ0].bit_no; | ||
222 | } else { | ||
223 | port_no = irq_assign_table0[irq - EXT_IRQ0].port_no; | ||
224 | bit_no = irq_assign_table0[irq - EXT_IRQ0].bit_no; | ||
225 | } | ||
226 | H8300_GPIO_FREE(port_no, bit_no); | ||
227 | } | ||
228 | if (((unsigned long)irq_list[irq] & 0x80000000) == 0) { | ||
229 | kfree(irq_list[irq]); | ||
230 | irq_list[irq] = NULL; | ||
231 | } | ||
232 | } | ||
233 | |||
234 | EXPORT_SYMBOL(free_irq); | ||
235 | |||
236 | unsigned long probe_irq_on (void) | ||
237 | { | ||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | EXPORT_SYMBOL(probe_irq_on); | ||
242 | |||
243 | int probe_irq_off (unsigned long irqs) | ||
244 | { | ||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | EXPORT_SYMBOL(probe_irq_off); | ||
249 | |||
250 | void enable_irq(unsigned int irq) | ||
251 | { | ||
252 | if (irq >= EXT_IRQ0 && irq <= EXT_IRQ15) | ||
253 | *(volatile unsigned short *)IER |= 1 << (irq - EXT_IRQ0); | ||
254 | } | ||
255 | |||
256 | void disable_irq(unsigned int irq) | ||
257 | { | ||
258 | if (irq >= EXT_IRQ0 && irq <= EXT_IRQ15) | ||
259 | *(volatile unsigned short *)IER &= ~(1 << (irq - EXT_IRQ0)); | ||
260 | } | ||
261 | |||
262 | asmlinkage void process_int(unsigned long vec, struct pt_regs *fp) | ||
263 | { | ||
264 | irq_enter(); | ||
265 | /* ISR clear */ | ||
266 | /* compatible i386 */ | ||
267 | if (vec >= EXT_IRQ0 && vec <= EXT_IRQ15) | ||
268 | *(volatile unsigned short *)ISR &= ~(1 << (vec - EXT_IRQ0)); | ||
269 | if (vec < NR_IRQS) { | ||
270 | if (irq_list[vec]) { | ||
271 | irq_list[vec]->handler(vec, irq_list[vec]->dev_id, fp); | ||
272 | irq_list[vec]->count++; | ||
273 | if (irq_list[vec]->flags & SA_SAMPLE_RANDOM) | ||
274 | add_interrupt_randomness(vec); | ||
275 | } | ||
276 | } else { | ||
277 | BUG(); | ||
278 | } | ||
279 | irq_exit(); | ||
280 | } | ||
281 | |||
282 | int show_interrupts(struct seq_file *p, void *v) | ||
283 | { | ||
284 | int i = *(loff_t *) v; | ||
285 | |||
286 | if ((i < NR_IRQS) && (irq_list[i] !=NULL)) { | ||
287 | seq_printf(p, "%3d: %10u ",i,irq_list[i]->count); | ||
288 | seq_printf(p, "%s\n", irq_list[i]->devname); | ||
289 | } | ||
290 | |||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | void init_irq_proc(void) | ||
295 | { | ||
296 | } | ||
297 | |||
298 | static int __init enable_kmalloc(void) | ||
299 | { | ||
300 | use_kmalloc = 1; | ||
301 | return 0; | ||
302 | } | ||
303 | core_initcall(enable_kmalloc); | ||
diff --git a/arch/h8300/platform/h8s/ints_h8s.c b/arch/h8300/platform/h8s/ints_h8s.c new file mode 100644 index 000000000000..f53de493e3e8 --- /dev/null +++ b/arch/h8300/platform/h8s/ints_h8s.c | |||
@@ -0,0 +1,105 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/platform/h8s/ints_h8s.c | ||
3 | * Interrupt handling CPU variants | ||
4 | * | ||
5 | * Yoshinori Sato <ysato@users.sourceforge.jp> | ||
6 | * | ||
7 | */ | ||
8 | |||
9 | #include <linux/config.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/errno.h> | ||
12 | #include <linux/kernel.h> | ||
13 | |||
14 | #include <asm/ptrace.h> | ||
15 | #include <asm/traps.h> | ||
16 | #include <asm/irq.h> | ||
17 | #include <asm/io.h> | ||
18 | #include <asm/gpio.h> | ||
19 | #include <asm/regs267x.h> | ||
20 | |||
21 | /* saved vector list */ | ||
22 | const int __initdata h8300_saved_vectors[]={ | ||
23 | #if defined(CONFIG_GDB_DEBUG) | ||
24 | TRACE_VEC, | ||
25 | TRAP3_VEC, | ||
26 | #endif | ||
27 | -1 | ||
28 | }; | ||
29 | |||
30 | /* trap entry table */ | ||
31 | const unsigned long __initdata h8300_trap_table[NR_TRAPS]={ | ||
32 | 0,0,0,0,0, | ||
33 | (unsigned long)trace_break, /* TRACE */ | ||
34 | 0,0, | ||
35 | (unsigned long)system_call, /* TRAPA #0 */ | ||
36 | 0,0,0,0,0,0,0 | ||
37 | }; | ||
38 | |||
39 | /* IRQ pin assignment */ | ||
40 | struct irq_pins { | ||
41 | unsigned char port_no; | ||
42 | unsigned char bit_no; | ||
43 | } __attribute__((aligned(1),packed)); | ||
44 | /* ISTR = 0 */ | ||
45 | const static struct irq_pins irq_assign_table0[16]={ | ||
46 | {H8300_GPIO_P5,H8300_GPIO_B0},{H8300_GPIO_P5,H8300_GPIO_B1}, | ||
47 | {H8300_GPIO_P5,H8300_GPIO_B2},{H8300_GPIO_P5,H8300_GPIO_B3}, | ||
48 | {H8300_GPIO_P5,H8300_GPIO_B4},{H8300_GPIO_P5,H8300_GPIO_B5}, | ||
49 | {H8300_GPIO_P5,H8300_GPIO_B6},{H8300_GPIO_P5,H8300_GPIO_B7}, | ||
50 | {H8300_GPIO_P6,H8300_GPIO_B0},{H8300_GPIO_P6,H8300_GPIO_B1}, | ||
51 | {H8300_GPIO_P6,H8300_GPIO_B2},{H8300_GPIO_P6,H8300_GPIO_B3}, | ||
52 | {H8300_GPIO_P6,H8300_GPIO_B4},{H8300_GPIO_P6,H8300_GPIO_B5}, | ||
53 | {H8300_GPIO_PF,H8300_GPIO_B1},{H8300_GPIO_PF,H8300_GPIO_B2}, | ||
54 | }; | ||
55 | /* ISTR = 1 */ | ||
56 | const static struct irq_pins irq_assign_table1[16]={ | ||
57 | {H8300_GPIO_P8,H8300_GPIO_B0},{H8300_GPIO_P8,H8300_GPIO_B1}, | ||
58 | {H8300_GPIO_P8,H8300_GPIO_B2},{H8300_GPIO_P8,H8300_GPIO_B3}, | ||
59 | {H8300_GPIO_P8,H8300_GPIO_B4},{H8300_GPIO_P8,H8300_GPIO_B5}, | ||
60 | {H8300_GPIO_PH,H8300_GPIO_B2},{H8300_GPIO_PH,H8300_GPIO_B3}, | ||
61 | {H8300_GPIO_P2,H8300_GPIO_B0},{H8300_GPIO_P2,H8300_GPIO_B1}, | ||
62 | {H8300_GPIO_P2,H8300_GPIO_B2},{H8300_GPIO_P2,H8300_GPIO_B3}, | ||
63 | {H8300_GPIO_P2,H8300_GPIO_B4},{H8300_GPIO_P2,H8300_GPIO_B5}, | ||
64 | {H8300_GPIO_P2,H8300_GPIO_B6},{H8300_GPIO_P2,H8300_GPIO_B7}, | ||
65 | }; | ||
66 | |||
67 | /* IRQ to GPIO pinno transrate */ | ||
68 | #define IRQ_GPIO_MAP(irqbit,irq,port,bit) \ | ||
69 | do { \ | ||
70 | if (*(volatile unsigned short *)ITSR & irqbit) { \ | ||
71 | port = irq_assign_table1[irq - EXT_IRQ0].port_no; \ | ||
72 | bit = irq_assign_table1[irq - EXT_IRQ0].bit_no; \ | ||
73 | } else { \ | ||
74 | port = irq_assign_table0[irq - EXT_IRQ0].port_no; \ | ||
75 | bit = irq_assign_table0[irq - EXT_IRQ0].bit_no; \ | ||
76 | } \ | ||
77 | } while(0) | ||
78 | |||
79 | int h8300_enable_irq_pin(unsigned int irq) | ||
80 | { | ||
81 | if (irq >= EXT_IRQ0 && irq <= EXT_IRQ15) { | ||
82 | unsigned short ptn = 1 << (irq - EXT_IRQ0); | ||
83 | unsigned int port_no,bit_no; | ||
84 | IRQ_GPIO_MAP(ptn, irq, port_no, bit_no); | ||
85 | if (H8300_GPIO_RESERVE(port_no, bit_no) == 0) | ||
86 | return -EBUSY; /* pin already use */ | ||
87 | H8300_GPIO_DDR(port_no, bit_no, H8300_GPIO_INPUT); | ||
88 | *(volatile unsigned short *)ISR &= ~ptn; /* ISR clear */ | ||
89 | } | ||
90 | |||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | void h8300_disable_irq_pin(unsigned int irq) | ||
95 | { | ||
96 | if (irq >= EXT_IRQ0 && irq <= EXT_IRQ15) { | ||
97 | /* disable interrupt & release IRQ pin */ | ||
98 | unsigned short ptn = 1 << (irq - EXT_IRQ0); | ||
99 | unsigned short port_no,bit_no; | ||
100 | *(volatile unsigned short *)ISR &= ~ptn; | ||
101 | *(volatile unsigned short *)IER &= ~ptn; | ||
102 | IRQ_GPIO_MAP(ptn, irq, port_no, bit_no); | ||
103 | H8300_GPIO_FREE(port_no, bit_no); | ||
104 | } | ||
105 | } | ||
diff --git a/arch/h8300/platform/h8s/ptrace_h8s.c b/arch/h8300/platform/h8s/ptrace_h8s.c new file mode 100644 index 000000000000..e8cd46f9255c --- /dev/null +++ b/arch/h8300/platform/h8s/ptrace_h8s.c | |||
@@ -0,0 +1,84 @@ | |||
1 | /* | ||
2 | * linux/arch/h8300/platform/h8s/ptrace_h8s.c | ||
3 | * ptrace cpu depend helper functions | ||
4 | * | ||
5 | * Yoshinori Sato <ysato@users.sourceforge.jp> | ||
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 | ||
9 | * this archive for more details. | ||
10 | */ | ||
11 | |||
12 | #include <linux/linkage.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <linux/errno.h> | ||
15 | #include <asm/ptrace.h> | ||
16 | |||
17 | #define CCR_MASK 0x6f | ||
18 | #define EXR_TRACE 0x80 | ||
19 | |||
20 | /* Mapping from PT_xxx to the stack offset at which the register is | ||
21 | saved. Notice that usp has no stack-slot and needs to be treated | ||
22 | specially (see get_reg/put_reg below). */ | ||
23 | static const int h8300_register_offset[] = { | ||
24 | PT_REG(er1), PT_REG(er2), PT_REG(er3), PT_REG(er4), | ||
25 | PT_REG(er5), PT_REG(er6), PT_REG(er0), PT_REG(orig_er0), | ||
26 | PT_REG(ccr), PT_REG(pc), 0, PT_REG(exr) | ||
27 | }; | ||
28 | |||
29 | /* read register */ | ||
30 | long h8300_get_reg(struct task_struct *task, int regno) | ||
31 | { | ||
32 | switch (regno) { | ||
33 | case PT_USP: | ||
34 | return task->thread.usp + sizeof(long)*2 + 2; | ||
35 | case PT_CCR: | ||
36 | case PT_EXR: | ||
37 | return *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]); | ||
38 | default: | ||
39 | return *(unsigned long *)(task->thread.esp0 + h8300_register_offset[regno]); | ||
40 | } | ||
41 | } | ||
42 | |||
43 | /* write register */ | ||
44 | int h8300_put_reg(struct task_struct *task, int regno, unsigned long data) | ||
45 | { | ||
46 | unsigned short oldccr; | ||
47 | switch (regno) { | ||
48 | case PT_USP: | ||
49 | task->thread.usp = data - sizeof(long)*2 - 2; | ||
50 | case PT_CCR: | ||
51 | oldccr = *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]); | ||
52 | oldccr &= ~CCR_MASK; | ||
53 | data &= CCR_MASK; | ||
54 | data |= oldccr; | ||
55 | *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]) = data; | ||
56 | break; | ||
57 | case PT_EXR: | ||
58 | /* exr modify not support */ | ||
59 | return -EIO; | ||
60 | default: | ||
61 | *(unsigned long *)(task->thread.esp0 + h8300_register_offset[regno]) = data; | ||
62 | break; | ||
63 | } | ||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | /* disable singlestep */ | ||
68 | void h8300_disable_trace(struct task_struct *child) | ||
69 | { | ||
70 | *(unsigned short *)(child->thread.esp0 + h8300_register_offset[PT_EXR]) &= ~EXR_TRACE; | ||
71 | } | ||
72 | |||
73 | /* enable singlestep */ | ||
74 | void h8300_enable_trace(struct task_struct *child) | ||
75 | { | ||
76 | *(unsigned short *)(child->thread.esp0 + h8300_register_offset[PT_EXR]) |= EXR_TRACE; | ||
77 | } | ||
78 | |||
79 | asmlinkage void trace_trap(unsigned long bp) | ||
80 | { | ||
81 | (void)bp; | ||
82 | force_sig(SIGTRAP,current); | ||
83 | } | ||
84 | |||