aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68k/hp300
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/m68k/hp300
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/m68k/hp300')
-rw-r--r--arch/m68k/hp300/Makefile5
-rw-r--r--arch/m68k/hp300/README.hp30014
-rw-r--r--arch/m68k/hp300/config.c279
-rw-r--r--arch/m68k/hp300/hp300map.map252
-rw-r--r--arch/m68k/hp300/ints.c175
-rw-r--r--arch/m68k/hp300/ints.h9
-rw-r--r--arch/m68k/hp300/ksyms.c9
-rw-r--r--arch/m68k/hp300/reboot.S16
-rw-r--r--arch/m68k/hp300/time.c78
-rw-r--r--arch/m68k/hp300/time.h4
10 files changed, 841 insertions, 0 deletions
diff --git a/arch/m68k/hp300/Makefile b/arch/m68k/hp300/Makefile
new file mode 100644
index 000000000000..89b6317899e3
--- /dev/null
+++ b/arch/m68k/hp300/Makefile
@@ -0,0 +1,5 @@
1#
2# Makefile for Linux arch/m68k/hp300 source directory
3#
4
5obj-y := ksyms.o config.o ints.o time.o reboot.o
diff --git a/arch/m68k/hp300/README.hp300 b/arch/m68k/hp300/README.hp300
new file mode 100644
index 000000000000..47073fbd400d
--- /dev/null
+++ b/arch/m68k/hp300/README.hp300
@@ -0,0 +1,14 @@
1HP300 notes
2-----------
3
4The Linux/HP web page is at <http://www.tazenda.demon.co.uk/phil/linux-hp/>
5
6Currently only 9000/340 machines have been tested. Any amount of RAM should
7work now but I've only tried 16MB and 12MB.
8
9The serial console is probably broken at the moment but the Topcat/HIL keyboard
10combination seems to work for me. Your mileage may vary.
11
12The LANCE driver works after a fashion but only if you reset the chip before
13every packet. This doesn't make for very speedy operation.
14
diff --git a/arch/m68k/hp300/config.c b/arch/m68k/hp300/config.c
new file mode 100644
index 000000000000..a0b854f3f94a
--- /dev/null
+++ b/arch/m68k/hp300/config.c
@@ -0,0 +1,279 @@
1/*
2 * linux/arch/m68k/hp300/config.c
3 *
4 * Copyright (C) 1998 Philip Blundell <philb@gnu.org>
5 *
6 * This file contains the HP300-specific initialisation code. It gets
7 * called by setup.c.
8 */
9
10#include <linux/config.h>
11#include <linux/module.h>
12#include <linux/init.h>
13#include <linux/string.h>
14#include <linux/kernel.h>
15#include <linux/console.h>
16
17#include <asm/bootinfo.h>
18#include <asm/machdep.h>
19#include <asm/blinken.h>
20#include <asm/io.h> /* readb() and writeb() */
21#include <asm/hp300hw.h>
22#include <asm/rtc.h>
23
24#include "ints.h"
25#include "time.h"
26
27unsigned long hp300_model;
28unsigned long hp300_uart_scode = -1;
29unsigned char ledstate;
30
31static char s_hp330[] __initdata = "330";
32static char s_hp340[] __initdata = "340";
33static char s_hp345[] __initdata = "345";
34static char s_hp360[] __initdata = "360";
35static char s_hp370[] __initdata = "370";
36static char s_hp375[] __initdata = "375";
37static char s_hp380[] __initdata = "380";
38static char s_hp385[] __initdata = "385";
39static char s_hp400[] __initdata = "400";
40static char s_hp425t[] __initdata = "425t";
41static char s_hp425s[] __initdata = "425s";
42static char s_hp425e[] __initdata = "425e";
43static char s_hp433t[] __initdata = "433t";
44static char s_hp433s[] __initdata = "433s";
45static char *hp300_models[] __initdata = {
46 [HP_320] = NULL,
47 [HP_330] = s_hp330,
48 [HP_340] = s_hp340,
49 [HP_345] = s_hp345,
50 [HP_350] = NULL,
51 [HP_360] = s_hp360,
52 [HP_370] = s_hp370,
53 [HP_375] = s_hp375,
54 [HP_380] = s_hp380,
55 [HP_385] = s_hp385,
56 [HP_400] = s_hp400,
57 [HP_425T] = s_hp425t,
58 [HP_425S] = s_hp425s,
59 [HP_425E] = s_hp425e,
60 [HP_433T] = s_hp433t,
61 [HP_433S] = s_hp433s,
62};
63
64static char hp300_model_name[13] = "HP9000/";
65
66extern void hp300_reset(void);
67extern irqreturn_t (*hp300_default_handler[])(int, void *, struct pt_regs *);
68extern int show_hp300_interrupts(struct seq_file *, void *);
69#ifdef CONFIG_SERIAL_8250_CONSOLE
70extern int hp300_setup_serial_console(void) __init;
71#endif
72
73int __init hp300_parse_bootinfo(const struct bi_record *record)
74{
75 int unknown = 0;
76 const unsigned long *data = record->data;
77
78 switch (record->tag) {
79 case BI_HP300_MODEL:
80 hp300_model = *data;
81 break;
82
83 case BI_HP300_UART_SCODE:
84 hp300_uart_scode = *data;
85 break;
86
87 case BI_HP300_UART_ADDR:
88 /* serial port address: ignored here */
89 break;
90
91 default:
92 unknown = 1;
93 }
94
95 return unknown;
96}
97
98#ifdef CONFIG_HEARTBEAT
99static void hp300_pulse(int x)
100{
101 if (x)
102 blinken_leds(0x10, 0);
103 else
104 blinken_leds(0, 0x10);
105}
106#endif
107
108static void hp300_get_model(char *model)
109{
110 strcpy(model, hp300_model_name);
111}
112
113#define RTCBASE 0xf0420000
114#define RTC_DATA 0x1
115#define RTC_CMD 0x3
116
117#define RTC_BUSY 0x02
118#define RTC_DATA_RDY 0x01
119
120#define rtc_busy() (in_8(RTCBASE + RTC_CMD) & RTC_BUSY)
121#define rtc_data_available() (in_8(RTCBASE + RTC_CMD) & RTC_DATA_RDY)
122#define rtc_status() (in_8(RTCBASE + RTC_CMD))
123#define rtc_command(x) out_8(RTCBASE + RTC_CMD, (x))
124#define rtc_read_data() (in_8(RTCBASE + RTC_DATA))
125#define rtc_write_data(x) out_8(RTCBASE + RTC_DATA, (x))
126
127#define RTC_SETREG 0xe0
128#define RTC_WRITEREG 0xc2
129#define RTC_READREG 0xc3
130
131#define RTC_REG_SEC2 0
132#define RTC_REG_SEC1 1
133#define RTC_REG_MIN2 2
134#define RTC_REG_MIN1 3
135#define RTC_REG_HOUR2 4
136#define RTC_REG_HOUR1 5
137#define RTC_REG_WDAY 6
138#define RTC_REG_DAY2 7
139#define RTC_REG_DAY1 8
140#define RTC_REG_MON2 9
141#define RTC_REG_MON1 10
142#define RTC_REG_YEAR2 11
143#define RTC_REG_YEAR1 12
144
145#define RTC_HOUR1_24HMODE 0x8
146
147#define RTC_STAT_MASK 0xf0
148#define RTC_STAT_RDY 0x40
149
150static inline unsigned char hp300_rtc_read(unsigned char reg)
151{
152 unsigned char s, ret;
153 unsigned long flags;
154
155 local_irq_save(flags);
156
157 while (rtc_busy());
158 rtc_command(RTC_SETREG);
159 while (rtc_busy());
160 rtc_write_data(reg);
161 while (rtc_busy());
162 rtc_command(RTC_READREG);
163
164 do {
165 while (!rtc_data_available());
166 s = rtc_status();
167 ret = rtc_read_data();
168 } while ((s & RTC_STAT_MASK) != RTC_STAT_RDY);
169
170 local_irq_restore(flags);
171
172 return ret;
173}
174
175static inline unsigned char hp300_rtc_write(unsigned char reg,
176 unsigned char val)
177{
178 unsigned char s, ret;
179 unsigned long flags;
180
181 local_irq_save(flags);
182
183 while (rtc_busy());
184 rtc_command(RTC_SETREG);
185 while (rtc_busy());
186 rtc_write_data((val << 4) | reg);
187 while (rtc_busy());
188 rtc_command(RTC_WRITEREG);
189 while (rtc_busy());
190 rtc_command(RTC_READREG);
191
192 do {
193 while (!rtc_data_available());
194 s = rtc_status();
195 ret = rtc_read_data();
196 } while ((s & RTC_STAT_MASK) != RTC_STAT_RDY);
197
198 local_irq_restore(flags);
199
200 return ret;
201}
202
203static int hp300_hwclk(int op, struct rtc_time *t)
204{
205 if (!op) { /* read */
206 t->tm_sec = hp300_rtc_read(RTC_REG_SEC1) * 10 +
207 hp300_rtc_read(RTC_REG_SEC2);
208 t->tm_min = hp300_rtc_read(RTC_REG_MIN1) * 10 +
209 hp300_rtc_read(RTC_REG_MIN2);
210 t->tm_hour = (hp300_rtc_read(RTC_REG_HOUR1) & 3) * 10 +
211 hp300_rtc_read(RTC_REG_HOUR2);
212 t->tm_wday = -1;
213 t->tm_mday = hp300_rtc_read(RTC_REG_DAY1) * 10 +
214 hp300_rtc_read(RTC_REG_DAY2);
215 t->tm_mon = hp300_rtc_read(RTC_REG_MON1) * 10 +
216 hp300_rtc_read(RTC_REG_MON2) - 1;
217 t->tm_year = hp300_rtc_read(RTC_REG_YEAR1) * 10 +
218 hp300_rtc_read(RTC_REG_YEAR2);
219 if (t->tm_year <= 69)
220 t->tm_year += 100;
221 } else {
222 hp300_rtc_write(RTC_REG_SEC1, t->tm_sec / 10);
223 hp300_rtc_write(RTC_REG_SEC2, t->tm_sec % 10);
224 hp300_rtc_write(RTC_REG_MIN1, t->tm_min / 10);
225 hp300_rtc_write(RTC_REG_MIN2, t->tm_min % 10);
226 hp300_rtc_write(RTC_REG_HOUR1,
227 ((t->tm_hour / 10) & 3) | RTC_HOUR1_24HMODE);
228 hp300_rtc_write(RTC_REG_HOUR2, t->tm_hour % 10);
229 hp300_rtc_write(RTC_REG_DAY1, t->tm_mday / 10);
230 hp300_rtc_write(RTC_REG_DAY2, t->tm_mday % 10);
231 hp300_rtc_write(RTC_REG_MON1, (t->tm_mon + 1) / 10);
232 hp300_rtc_write(RTC_REG_MON2, (t->tm_mon + 1) % 10);
233 if (t->tm_year >= 100)
234 t->tm_year -= 100;
235 hp300_rtc_write(RTC_REG_YEAR1, t->tm_year / 10);
236 hp300_rtc_write(RTC_REG_YEAR2, t->tm_year % 10);
237 }
238
239 return 0;
240}
241
242static unsigned int hp300_get_ss(void)
243{
244 return hp300_rtc_read(RTC_REG_SEC1) * 10 +
245 hp300_rtc_read(RTC_REG_SEC2);
246}
247
248void __init config_hp300(void)
249{
250 mach_sched_init = hp300_sched_init;
251 mach_init_IRQ = hp300_init_IRQ;
252 mach_request_irq = hp300_request_irq;
253 mach_free_irq = hp300_free_irq;
254 mach_get_model = hp300_get_model;
255 mach_get_irq_list = show_hp300_interrupts;
256 mach_gettimeoffset = hp300_gettimeoffset;
257 mach_default_handler = &hp300_default_handler;
258 mach_hwclk = hp300_hwclk;
259 mach_get_ss = hp300_get_ss;
260 mach_reset = hp300_reset;
261#ifdef CONFIG_HEARTBEAT
262 mach_heartbeat = hp300_pulse;
263#endif
264#ifdef CONFIG_DUMMY_CONSOLE
265 conswitchp = &dummy_con;
266#endif
267 mach_max_dma_address = 0xffffffff;
268
269 if (hp300_model >= HP_330 && hp300_model <= HP_433S && hp300_model != HP_350) {
270 printk(KERN_INFO "Detected HP9000 model %s\n", hp300_models[hp300_model-HP_320]);
271 strcat(hp300_model_name, hp300_models[hp300_model-HP_320]);
272 }
273 else {
274 panic("Unknown HP9000 Model");
275 }
276#ifdef CONFIG_SERIAL_8250_CONSOLE
277 hp300_setup_serial_console();
278#endif
279}
diff --git a/arch/m68k/hp300/hp300map.map b/arch/m68k/hp300/hp300map.map
new file mode 100644
index 000000000000..6b45f0abc957
--- /dev/null
+++ b/arch/m68k/hp300/hp300map.map
@@ -0,0 +1,252 @@
1# HP300 kernel keymap. This uses 7 modifier combinations.
2keymaps 0-2,4-5,8,12
3# Change the above line into
4# keymaps 0-2,4-6,8,12
5# in case you want the entries
6# altgr control keycode 83 = Boot
7# altgr control keycode 111 = Boot
8# below.
9#
10# In fact AltGr is used very little, and one more keymap can
11# be saved by mapping AltGr to Alt (and adapting a few entries):
12# keycode 100 = Alt
13#
14keycode 1 =
15keycode 2 = Alt
16keycode 3 = Alt
17keycode 4 = Shift
18keycode 5 = Shift
19keycode 6 = Control
20keycode 7 =
21keycode 8 =
22keycode 9 =
23keycode 10 =
24keycode 11 =
25keycode 12 =
26keycode 13 =
27keycode 14 =
28keycode 15 =
29keycode 16 =
30keycode 17 =
31keycode 18 =
32keycode 19 =
33keycode 20 =
34keycode 21 =
35keycode 22 =
36keycode 23 =
37keycode 24 = b
38keycode 25 = v
39keycode 26 = c
40keycode 27 = x
41keycode 28 = z
42keycode 29 =
43keycode 30 =
44keycode 31 = Escape Delete
45keycode 32 =
46keycode 33 =
47keycode 34 =
48keycode 35 =
49keycode 36 =
50keycode 37 =
51keycode 38 =
52keycode 39 =
53keycode 40 = h
54keycode 41 = g
55keycode 42 = f
56keycode 43 = d
57keycode 44 = s
58keycode 45 = a
59keycode 46 =
60keycode 47 = Caps_Lock
61keycode 48 = u
62keycode 49 = y
63keycode 50 = t
64keycode 51 = r
65keycode 52 = e
66keycode 53 = w
67keycode 54 = q
68keycode 55 = Tab Tab
69 alt keycode 55 = Meta_Tab
70keycode 56 = seven ampersand
71keycode 57 = six asciicircum
72keycode 58 = five percent
73keycode 59 = four dollar
74keycode 60 = three numbersign
75keycode 61 = two at at
76keycode 62 = one exclam exclam
77keycode 63 = grave asciitilde
78 control keycode 63 = nul
79 alt keycode 63 = Meta_grave
80keycode 64 =
81keycode 65 =
82keycode 66 =
83keycode 67 =
84keycode 68 =
85keycode 69 =
86keycode 70 =
87keycode 71 =
88keycode 72 =
89keycode 73 = F4
90 control keycode 73 = Console_4
91keycode 74 = F3
92 control keycode 74 = Console_3
93keycode 75 = F2
94 control keycode 75 = Console_2
95keycode 76 = F1
96 control keycode 76 = Console_1
97keycode 77 =
98keycode 78 =
99keycode 79 =
100keycode 80 =
101keycode 81 = F5
102 control keycode 81 = Console_5
103keycode 82 = F6
104 control keycode 82 = Console_6
105keycode 83 = F7
106 control keycode 83 = Console_7
107keycode 84 = F8
108 control keycode 84 = Console_8
109keycode 85 =
110keycode 86 =
111keycode 87 =
112keycode 88 = eight asterisk asterisk
113keycode 89 = nine parenleft bracketleft
114keycode 90 = zero parenright bracketright
115keycode 91 = minus underscore
116keycode 92 = equal plus
117keycode 93 = BackSpace
118keycode 94 =
119keycode 95 =
120keycode 96 = i
121keycode 97 = o
122keycode 98 = p
123keycode 99 = bracketleft braceleft
124keycode 100 = bracketright braceright
125keycode 101 = backslash bar
126 control keycode 101 = Control_backslash
127 alt keycode 101 = Meta_backslash
128keycode 102 =
129keycode 103 =
130keycode 104 = j
131keycode 105 = k
132keycode 106 = l
133keycode 107 = semicolon colon
134 alt keycode 107 = Meta_semicolon
135keycode 108 = apostrophe quotedbl
136 control keycode 108 = Control_g
137 alt keycode 108 = Meta_apostrophe
138keycode 109 = Return
139keycode 110 =
140keycode 111 =
141keycode 112 = m
142keycode 113 = comma less
143keycode 114 = period greater
144keycode 115 = slash question
145keycode 116 =
146keycode 117 =
147keycode 118 =
148keycode 119 =
149keycode 120 = n
150keycode 121 = space space
151keycode 122 =
152keycode 123 =
153keycode 124 = Left
154keycode 125 = Down
155keycode 126 = Up
156keycode 127 = Right
157string F1 = "\033[[A"
158string F2 = "\033[[B"
159string F3 = "\033[[C"
160string F4 = "\033[[D"
161string F5 = "\033[[E"
162string F6 = "\033[17~"
163string F7 = "\033[18~"
164string F8 = "\033[19~"
165string F9 = "\033[20~"
166string F10 = "\033[21~"
167string F11 = "\033[23~"
168string F12 = "\033[24~"
169string F13 = "\033[25~"
170string F14 = "\033[26~"
171string F15 = "\033[28~"
172string F16 = "\033[29~"
173string F17 = "\033[31~"
174string F18 = "\033[32~"
175string F19 = "\033[33~"
176string F20 = "\033[34~"
177string Find = "\033[1~"
178string Insert = "\033[2~"
179string Remove = "\033[3~"
180string Select = "\033[4~"
181string Prior = "\033[5~"
182string Next = "\033[6~"
183string Macro = "\033[M"
184string Pause = "\033[P"
185compose '`' 'A' to 'À'
186compose '`' 'a' to 'à'
187compose '\'' 'A' to 'Á'
188compose '\'' 'a' to 'á'
189compose '^' 'A' to 'Â'
190compose '^' 'a' to 'â'
191compose '~' 'A' to 'Ã'
192compose '~' 'a' to 'ã'
193compose '"' 'A' to 'Ä'
194compose '"' 'a' to 'ä'
195compose 'O' 'A' to 'Å'
196compose 'o' 'a' to 'å'
197compose '0' 'A' to 'Å'
198compose '0' 'a' to 'å'
199compose 'A' 'A' to 'Å'
200compose 'a' 'a' to 'å'
201compose 'A' 'E' to 'Æ'
202compose 'a' 'e' to 'æ'
203compose ',' 'C' to 'Ç'
204compose ',' 'c' to 'ç'
205compose '`' 'E' to 'È'
206compose '`' 'e' to 'è'
207compose '\'' 'E' to 'É'
208compose '\'' 'e' to 'é'
209compose '^' 'E' to 'Ê'
210compose '^' 'e' to 'ê'
211compose '"' 'E' to 'Ë'
212compose '"' 'e' to 'ë'
213compose '`' 'I' to 'Ì'
214compose '`' 'i' to 'ì'
215compose '\'' 'I' to 'Í'
216compose '\'' 'i' to 'í'
217compose '^' 'I' to 'Î'
218compose '^' 'i' to 'î'
219compose '"' 'I' to 'Ï'
220compose '"' 'i' to 'ï'
221compose '-' 'D' to 'Ð'
222compose '-' 'd' to 'ð'
223compose '~' 'N' to 'Ñ'
224compose '~' 'n' to 'ñ'
225compose '`' 'O' to 'Ò'
226compose '`' 'o' to 'ò'
227compose '\'' 'O' to 'Ó'
228compose '\'' 'o' to 'ó'
229compose '^' 'O' to 'Ô'
230compose '^' 'o' to 'ô'
231compose '~' 'O' to 'Õ'
232compose '~' 'o' to 'õ'
233compose '"' 'O' to 'Ö'
234compose '"' 'o' to 'ö'
235compose '/' 'O' to 'Ø'
236compose '/' 'o' to 'ø'
237compose '`' 'U' to 'Ù'
238compose '`' 'u' to 'ù'
239compose '\'' 'U' to 'Ú'
240compose '\'' 'u' to 'ú'
241compose '^' 'U' to 'Û'
242compose '^' 'u' to 'û'
243compose '"' 'U' to 'Ü'
244compose '"' 'u' to 'ü'
245compose '\'' 'Y' to 'Ý'
246compose '\'' 'y' to 'ý'
247compose 'T' 'H' to 'Þ'
248compose 't' 'h' to 'þ'
249compose 's' 's' to 'ß'
250compose '"' 'y' to 'ÿ'
251compose 's' 'z' to 'ß'
252compose 'i' 'j' to 'ÿ'
diff --git a/arch/m68k/hp300/ints.c b/arch/m68k/hp300/ints.c
new file mode 100644
index 000000000000..0c5bb403e893
--- /dev/null
+++ b/arch/m68k/hp300/ints.c
@@ -0,0 +1,175 @@
1/*
2 * linux/arch/m68k/hp300/ints.c
3 *
4 * Copyright (C) 1998 Philip Blundell <philb@gnu.org>
5 *
6 * This file contains the HP300-specific interrupt handling.
7 * We only use the autovector interrupts, and therefore we need to
8 * maintain lists of devices sharing each ipl.
9 * [ipl list code added by Peter Maydell <pmaydell@chiark.greenend.org.uk> 06/1998]
10 */
11
12#include <linux/kernel.h>
13#include <linux/types.h>
14#include <linux/init.h>
15#include <linux/sched.h>
16#include <linux/kernel_stat.h>
17#include <linux/interrupt.h>
18#include <linux/spinlock.h>
19#include <asm/machdep.h>
20#include <asm/irq.h>
21#include <asm/io.h>
22#include <asm/system.h>
23#include <asm/traps.h>
24#include <asm/ptrace.h>
25#include <asm/errno.h>
26#include "ints.h"
27
28/* Each ipl has a linked list of interrupt service routines.
29 * Service routines are added via hp300_request_irq() and removed
30 * via hp300_free_irq(). The device driver should set IRQ_FLG_FAST
31 * if it needs to be serviced early (eg FIFOless UARTs); this will
32 * cause it to be added at the front of the queue rather than
33 * the back.
34 * Currently IRQ_FLG_SLOW and flags=0 are treated identically; if
35 * we needed three levels of priority we could distinguish them
36 * but this strikes me as mildly ugly...
37 */
38
39/* we start with no entries in any list */
40static irq_node_t *hp300_irq_list[HP300_NUM_IRQS];
41
42static spinlock_t irqlist_lock;
43
44/* This handler receives all interrupts, dispatching them to the registered handlers */
45static irqreturn_t hp300_int_handler(int irq, void *dev_id, struct pt_regs *fp)
46{
47 irq_node_t *t;
48 /* We just give every handler on the chain an opportunity to handle
49 * the interrupt, in priority order.
50 */
51 for(t = hp300_irq_list[irq]; t; t=t->next)
52 t->handler(irq, t->dev_id, fp);
53 /* We could put in some accounting routines, checks for stray interrupts,
54 * etc, in here. Note that currently we can't tell whether or not
55 * a handler handles the interrupt, though.
56 */
57 return IRQ_HANDLED;
58}
59
60static irqreturn_t hp300_badint(int irq, void *dev_id, struct pt_regs *fp)
61{
62 num_spurious += 1;
63 return IRQ_NONE;
64}
65
66irqreturn_t (*hp300_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
67 [0] = hp300_badint,
68 [1] = hp300_int_handler,
69 [2] = hp300_int_handler,
70 [3] = hp300_int_handler,
71 [4] = hp300_int_handler,
72 [5] = hp300_int_handler,
73 [6] = hp300_int_handler,
74 [7] = hp300_int_handler
75};
76
77/* dev_id had better be unique to each handler because it's the only way we have
78 * to distinguish handlers when removing them...
79 *
80 * It would be pretty easy to support IRQ_FLG_LOCK (handler is not replacable)
81 * and IRQ_FLG_REPLACE (handler replaces existing one with this dev_id)
82 * if we wanted to. IRQ_FLG_FAST is needed for devices where interrupt latency
83 * matters (eg the dreaded FIFOless UART...)
84 */
85int hp300_request_irq(unsigned int irq,
86 irqreturn_t (*handler) (int, void *, struct pt_regs *),
87 unsigned long flags, const char *devname, void *dev_id)
88{
89 irq_node_t *t, *n = new_irq_node();
90
91 if (!n) /* oops, no free nodes */
92 return -ENOMEM;
93
94 spin_lock_irqsave(&irqlist_lock, flags);
95
96 if (!hp300_irq_list[irq]) {
97 /* no list yet */
98 hp300_irq_list[irq] = n;
99 n->next = NULL;
100 } else if (flags & IRQ_FLG_FAST) {
101 /* insert at head of list */
102 n->next = hp300_irq_list[irq];
103 hp300_irq_list[irq] = n;
104 } else {
105 /* insert at end of list */
106 for(t = hp300_irq_list[irq]; t->next; t = t->next)
107 /* do nothing */;
108 n->next = NULL;
109 t->next = n;
110 }
111
112 /* Fill in n appropriately */
113 n->handler = handler;
114 n->flags = flags;
115 n->dev_id = dev_id;
116 n->devname = devname;
117 spin_unlock_irqrestore(&irqlist_lock, flags);
118 return 0;
119}
120
121void hp300_free_irq(unsigned int irq, void *dev_id)
122{
123 irq_node_t *t;
124 unsigned long flags;
125
126 spin_lock_irqsave(&irqlist_lock, flags);
127
128 t = hp300_irq_list[irq];
129 if (!t) /* no handlers at all for that IRQ */
130 {
131 printk(KERN_ERR "hp300_free_irq: attempt to remove nonexistent handler for IRQ %d\n", irq);
132 spin_unlock_irqrestore(&irqlist_lock, flags);
133 return;
134 }
135
136 if (t->dev_id == dev_id)
137 { /* removing first handler on chain */
138 t->flags = IRQ_FLG_STD; /* we probably don't really need these */
139 t->dev_id = NULL;
140 t->devname = NULL;
141 t->handler = NULL; /* frees this irq_node_t */
142 hp300_irq_list[irq] = t->next;
143 spin_unlock_irqrestore(&irqlist_lock, flags);
144 return;
145 }
146
147 /* OK, must be removing from middle of the chain */
148
149 for (t = hp300_irq_list[irq]; t->next && t->next->dev_id != dev_id; t = t->next)
150 /* do nothing */;
151 if (!t->next)
152 {
153 printk(KERN_ERR "hp300_free_irq: attempt to remove nonexistent handler for IRQ %d\n", irq);
154 spin_unlock_irqrestore(&irqlist_lock, flags);
155 return;
156 }
157 /* remove the entry after t: */
158 t->next->flags = IRQ_FLG_STD;
159 t->next->dev_id = NULL;
160 t->next->devname = NULL;
161 t->next->handler = NULL;
162 t->next = t->next->next;
163
164 spin_unlock_irqrestore(&irqlist_lock, flags);
165}
166
167int show_hp300_interrupts(struct seq_file *p, void *v)
168{
169 return 0;
170}
171
172void __init hp300_init_IRQ(void)
173{
174 spin_lock_init(&irqlist_lock);
175}
diff --git a/arch/m68k/hp300/ints.h b/arch/m68k/hp300/ints.h
new file mode 100644
index 000000000000..8cfabe2f3840
--- /dev/null
+++ b/arch/m68k/hp300/ints.h
@@ -0,0 +1,9 @@
1extern void hp300_init_IRQ(void);
2extern void (*hp300_handlers[8])(int, void *, struct pt_regs *);
3extern void hp300_free_irq(unsigned int irq, void *dev_id);
4extern int hp300_request_irq(unsigned int irq,
5 irqreturn_t (*handler) (int, void *, struct pt_regs *),
6 unsigned long flags, const char *devname, void *dev_id);
7
8/* number of interrupts, includes 0 (what's that?) */
9#define HP300_NUM_IRQS 8
diff --git a/arch/m68k/hp300/ksyms.c b/arch/m68k/hp300/ksyms.c
new file mode 100644
index 000000000000..8202830763d1
--- /dev/null
+++ b/arch/m68k/hp300/ksyms.c
@@ -0,0 +1,9 @@
1/*
2 * linux/arch/m68k/hp300/ksyms.c
3 *
4 * Copyright (C) 1998 Philip Blundell <philb@gnu.org>
5 *
6 * This file contains the HP300-specific kernel symbols. None yet. :-)
7 */
8
9#include <linux/module.h>
diff --git a/arch/m68k/hp300/reboot.S b/arch/m68k/hp300/reboot.S
new file mode 100644
index 000000000000..52eb852e6b04
--- /dev/null
+++ b/arch/m68k/hp300/reboot.S
@@ -0,0 +1,16 @@
1/*
2 * linux/arch/m68k/hp300/reboot.S
3 *
4 * Copyright (C) 1998 Philip Blundell <philb@gnu.org>
5 *
6 * Do the dirty work of rebooting the machine. Basically we need to undo all the
7 * good stuff that head.S did when we started up. The caches and MMU must be
8 * disabled and then we jump back to the PROM. This is a bit gruesome but we put
9 * a brave face on it.
10 */
11
12/* XXX Doesn't work yet. Not sure why and can't be bothered to fix it at the moment. */
13
14 .globl hp300_reset
15hp300_reset:
16 jmp hp300_reset
diff --git a/arch/m68k/hp300/time.c b/arch/m68k/hp300/time.c
new file mode 100644
index 000000000000..8da5b1b31e61
--- /dev/null
+++ b/arch/m68k/hp300/time.c
@@ -0,0 +1,78 @@
1/*
2 * linux/arch/m68k/hp300/time.c
3 *
4 * Copyright (C) 1998 Philip Blundell <philb@gnu.org>
5 *
6 * This file contains the HP300-specific time handling code.
7 */
8
9#include <asm/ptrace.h>
10#include <linux/types.h>
11#include <linux/init.h>
12#include <linux/sched.h>
13#include <linux/kernel_stat.h>
14#include <linux/interrupt.h>
15#include <asm/machdep.h>
16#include <asm/irq.h>
17#include <asm/io.h>
18#include <asm/system.h>
19#include <asm/traps.h>
20#include <asm/blinken.h>
21#include "ints.h"
22
23/* Clock hardware definitions */
24
25#define CLOCKBASE 0xf05f8000
26
27#define CLKCR1 0x1
28#define CLKCR2 0x3
29#define CLKCR3 CLKCR1
30#define CLKSR CLKCR2
31#define CLKMSB1 0x5
32#define CLKMSB2 0x9
33#define CLKMSB3 0xD
34
35/* This is for machines which generate the exact clock. */
36#define USECS_PER_JIFFY (1000000/HZ)
37
38#define INTVAL ((10000 / 4) - 1)
39
40static irqreturn_t hp300_tick(int irq, void *dev_id, struct pt_regs *regs)
41{
42 unsigned long tmp;
43 irqreturn_t (*vector)(int, void *, struct pt_regs *) = dev_id;
44 in_8(CLOCKBASE + CLKSR);
45 asm volatile ("movpw %1@(5),%0" : "=d" (tmp) : "a" (CLOCKBASE));
46 /* Turn off the network and SCSI leds */
47 blinken_leds(0, 0xe0);
48 return vector(irq, NULL, regs);
49}
50
51unsigned long hp300_gettimeoffset(void)
52{
53 /* Read current timer 1 value */
54 unsigned char lsb, msb1, msb2;
55 unsigned short ticks;
56
57 msb1 = in_8(CLOCKBASE + 5);
58 lsb = in_8(CLOCKBASE + 7);
59 msb2 = in_8(CLOCKBASE + 5);
60 if (msb1 != msb2)
61 /* A carry happened while we were reading. Read it again */
62 lsb = in_8(CLOCKBASE + 7);
63 ticks = INTVAL - ((msb2 << 8) | lsb);
64 return (USECS_PER_JIFFY * ticks) / INTVAL;
65}
66
67void __init hp300_sched_init(irqreturn_t (*vector)(int, void *, struct pt_regs *))
68{
69 out_8(CLOCKBASE + CLKCR2, 0x1); /* select CR1 */
70 out_8(CLOCKBASE + CLKCR1, 0x1); /* reset */
71
72 asm volatile(" movpw %0,%1@(5)" : : "d" (INTVAL), "a" (CLOCKBASE));
73
74 cpu_request_irq(6, hp300_tick, IRQ_FLG_STD, "timer tick", vector);
75
76 out_8(CLOCKBASE + CLKCR2, 0x1); /* select CR1 */
77 out_8(CLOCKBASE + CLKCR1, 0x40); /* enable irq */
78}
diff --git a/arch/m68k/hp300/time.h b/arch/m68k/hp300/time.h
new file mode 100644
index 000000000000..8ef9987b49ab
--- /dev/null
+++ b/arch/m68k/hp300/time.h
@@ -0,0 +1,4 @@
1extern void hp300_sched_init(irqreturn_t (*vector)(int, void *, struct pt_regs *));
2extern unsigned long hp300_gettimeoffset (void);
3
4