aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m32r/kernel
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/m32r/kernel
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/m32r/kernel')
-rw-r--r--arch/m32r/kernel/Makefile20
-rw-r--r--arch/m32r/kernel/align.c585
-rw-r--r--arch/m32r/kernel/entry.S1000
-rw-r--r--arch/m32r/kernel/head.S287
-rw-r--r--arch/m32r/kernel/init_task.c41
-rw-r--r--arch/m32r/kernel/io_m32700ut.c472
-rw-r--r--arch/m32r/kernel/io_mappi.c384
-rw-r--r--arch/m32r/kernel/io_mappi2.c461
-rw-r--r--arch/m32r/kernel/io_oaks32r.c251
-rw-r--r--arch/m32r/kernel/io_opsput.c390
-rw-r--r--arch/m32r/kernel/io_usrv.c249
-rw-r--r--arch/m32r/kernel/irq.c91
-rw-r--r--arch/m32r/kernel/m32r_ksyms.c140
-rw-r--r--arch/m32r/kernel/module.c259
-rw-r--r--arch/m32r/kernel/process.c359
-rw-r--r--arch/m32r/kernel/ptrace.c829
-rw-r--r--arch/m32r/kernel/semaphore.c186
-rw-r--r--arch/m32r/kernel/setup.c420
-rw-r--r--arch/m32r/kernel/setup_m32700ut.c478
-rw-r--r--arch/m32r/kernel/setup_mappi.c160
-rw-r--r--arch/m32r/kernel/setup_mappi2.c212
-rw-r--r--arch/m32r/kernel/setup_oaks32r.c143
-rw-r--r--arch/m32r/kernel/setup_opsput.c482
-rw-r--r--arch/m32r/kernel/setup_usrv.c256
-rw-r--r--arch/m32r/kernel/signal.c438
-rw-r--r--arch/m32r/kernel/smp.c965
-rw-r--r--arch/m32r/kernel/smpboot.c630
-rw-r--r--arch/m32r/kernel/sys_m32r.c217
-rw-r--r--arch/m32r/kernel/time.c318
-rw-r--r--arch/m32r/kernel/traps.c332
-rw-r--r--arch/m32r/kernel/vmlinux.lds.S143
31 files changed, 11198 insertions, 0 deletions
diff --git a/arch/m32r/kernel/Makefile b/arch/m32r/kernel/Makefile
new file mode 100644
index 000000000000..cfd690bf6d8a
--- /dev/null
+++ b/arch/m32r/kernel/Makefile
@@ -0,0 +1,20 @@
1#
2# Makefile for the Linux/M32R kernel.
3#
4
5extra-y := head.o init_task.o vmlinux.lds
6
7obj-y := process.o entry.o traps.o align.o irq.o setup.o time.o \
8 m32r_ksyms.o sys_m32r.o semaphore.o signal.o ptrace.o
9
10obj-$(CONFIG_SMP) += smp.o smpboot.o
11obj-$(CONFIG_PLAT_MAPPI) += setup_mappi.o io_mappi.o
12obj-$(CONFIG_PLAT_MAPPI2) += setup_mappi2.o io_mappi2.o
13obj-$(CONFIG_PLAT_USRV) += setup_usrv.o io_usrv.o
14obj-$(CONFIG_PLAT_M32700UT) += setup_m32700ut.o io_m32700ut.o
15obj-$(CONFIG_PLAT_OPSPUT) += setup_opsput.o io_opsput.o
16obj-$(CONFIG_MODULES) += module.o
17obj-$(CONFIG_PLAT_OAKS32R) += setup_oaks32r.o io_oaks32r.o
18
19EXTRA_AFLAGS := -traditional
20
diff --git a/arch/m32r/kernel/align.c b/arch/m32r/kernel/align.c
new file mode 100644
index 000000000000..48ec29714238
--- /dev/null
+++ b/arch/m32r/kernel/align.c
@@ -0,0 +1,585 @@
1/*
2 * align.c - address exception handler for M32R
3 *
4 * Copyright (c) 2003 Hitoshi Yamamoto
5 */
6
7#include <linux/config.h>
8#include <asm/ptrace.h>
9#include <asm/uaccess.h>
10
11static int get_reg(struct pt_regs *regs, int nr)
12{
13 int val;
14
15 if (nr < 4)
16 val = *(unsigned long *)(&regs->r0 + nr);
17 else if (nr < 7)
18 val = *(unsigned long *)(&regs->r4 + (nr - 4));
19 else if (nr < 13)
20 val = *(unsigned long *)(&regs->r7 + (nr - 7));
21 else
22 val = *(unsigned long *)(&regs->fp + (nr - 13));
23
24 return val;
25}
26
27static void set_reg(struct pt_regs *regs, int nr, int val)
28{
29 if (nr < 4)
30 *(unsigned long *)(&regs->r0 + nr) = val;
31 else if (nr < 7)
32 *(unsigned long *)(&regs->r4 + (nr - 4)) = val;
33 else if (nr < 13)
34 *(unsigned long *)(&regs->r7 + (nr - 7)) = val;
35 else
36 *(unsigned long *)(&regs->fp + (nr - 13)) = val;
37}
38
39#define REG1(insn) (((insn) & 0x0f00) >> 8)
40#define REG2(insn) ((insn) & 0x000f)
41#define PSW_BC 0x100
42
43/* O- instruction */
44#define ISA_LD1 0x20c0 /* ld Rdest, @Rsrc */
45#define ISA_LD2 0x20e0 /* ld Rdest, @Rsrc+ */
46#define ISA_LDH 0x20a0 /* ldh Rdest, @Rsrc */
47#define ISA_LDUH 0x20b0 /* lduh Rdest, @Rsrc */
48#define ISA_ST1 0x2040 /* st Rsrc1, @Rsrc2 */
49#define ISA_ST2 0x2060 /* st Rsrc1, @+Rsrc2 */
50#define ISA_ST3 0x2070 /* st Rsrc1, @-Rsrc2 */
51#define ISA_STH1 0x2020 /* sth Rsrc1, @Rsrc2 */
52#define ISA_STH2 0x2030 /* sth Rsrc1, @Rsrc2+ */
53
54#ifdef CONFIG_ISA_DUAL_ISSUE
55
56/* OS instruction */
57#define ISA_ADD 0x00a0 /* add Rdest, Rsrc */
58#define ISA_ADDI 0x4000 /* addi Rdest, #imm8 */
59#define ISA_ADDX 0x0090 /* addx Rdest, Rsrc */
60#define ISA_AND 0x00c0 /* and Rdest, Rsrc */
61#define ISA_CMP 0x0040 /* cmp Rsrc1, Rsrc2 */
62#define ISA_CMPEQ 0x0060 /* cmpeq Rsrc1, Rsrc2 */
63#define ISA_CMPU 0x0050 /* cmpu Rsrc1, Rsrc2 */
64#define ISA_CMPZ 0x0070 /* cmpz Rsrc */
65#define ISA_LDI 0x6000 /* ldi Rdest, #imm8 */
66#define ISA_MV 0x1080 /* mv Rdest, Rsrc */
67#define ISA_NEG 0x0030 /* neg Rdest, Rsrc */
68#define ISA_NOP 0x7000 /* nop */
69#define ISA_NOT 0x00b0 /* not Rdest, Rsrc */
70#define ISA_OR 0x00e0 /* or Rdest, Rsrc */
71#define ISA_SUB 0x0020 /* sub Rdest, Rsrc */
72#define ISA_SUBX 0x0010 /* subx Rdest, Rsrc */
73#define ISA_XOR 0x00d0 /* xor Rdest, Rsrc */
74
75/* -S instruction */
76#define ISA_MUL 0x1060 /* mul Rdest, Rsrc */
77#define ISA_MULLO_A0 0x3010 /* mullo Rsrc1, Rsrc2, A0 */
78#define ISA_MULLO_A1 0x3090 /* mullo Rsrc1, Rsrc2, A1 */
79#define ISA_MVFACMI_A0 0x50f2 /* mvfacmi Rdest, A0 */
80#define ISA_MVFACMI_A1 0x50f6 /* mvfacmi Rdest, A1 */
81
82static int emu_addi(unsigned short insn, struct pt_regs *regs)
83{
84 char imm = (char)(insn & 0xff);
85 int dest = REG1(insn);
86 int val;
87
88 val = get_reg(regs, dest);
89 val += imm;
90 set_reg(regs, dest, val);
91
92 return 0;
93}
94
95static int emu_ldi(unsigned short insn, struct pt_regs *regs)
96{
97 char imm = (char)(insn & 0xff);
98
99 set_reg(regs, REG1(insn), (int)imm);
100
101 return 0;
102}
103
104static int emu_add(unsigned short insn, struct pt_regs *regs)
105{
106 int dest = REG1(insn);
107 int src = REG2(insn);
108 int val;
109
110 val = get_reg(regs, dest);
111 val += get_reg(regs, src);
112 set_reg(regs, dest, val);
113
114 return 0;
115}
116
117static int emu_addx(unsigned short insn, struct pt_regs *regs)
118{
119 int dest = REG1(insn);
120 unsigned int val, tmp;
121
122 val = regs->psw & PSW_BC ? 1 : 0;
123 tmp = get_reg(regs, dest);
124 val += tmp;
125 val += (unsigned int)get_reg(regs, REG2(insn));
126 set_reg(regs, dest, val);
127
128 /* C bit set */
129 if (val < tmp)
130 regs->psw |= PSW_BC;
131 else
132 regs->psw &= ~(PSW_BC);
133
134 return 0;
135}
136
137static int emu_and(unsigned short insn, struct pt_regs *regs)
138{
139 int dest = REG1(insn);
140 int val;
141
142 val = get_reg(regs, dest);
143 val &= get_reg(regs, REG2(insn));
144 set_reg(regs, dest, val);
145
146 return 0;
147}
148
149static int emu_cmp(unsigned short insn, struct pt_regs *regs)
150{
151 if (get_reg(regs, REG1(insn)) < get_reg(regs, REG2(insn)))
152 regs->psw |= PSW_BC;
153 else
154 regs->psw &= ~(PSW_BC);
155
156 return 0;
157}
158
159static int emu_cmpeq(unsigned short insn, struct pt_regs *regs)
160{
161 if (get_reg(regs, REG1(insn)) == get_reg(regs, REG2(insn)))
162 regs->psw |= PSW_BC;
163 else
164 regs->psw &= ~(PSW_BC);
165
166 return 0;
167}
168
169static int emu_cmpu(unsigned short insn, struct pt_regs *regs)
170{
171 if ((unsigned int)get_reg(regs, REG1(insn))
172 < (unsigned int)get_reg(regs, REG2(insn)))
173 regs->psw |= PSW_BC;
174 else
175 regs->psw &= ~(PSW_BC);
176
177 return 0;
178}
179
180static int emu_cmpz(unsigned short insn, struct pt_regs *regs)
181{
182 if (!get_reg(regs, REG2(insn)))
183 regs->psw |= PSW_BC;
184 else
185 regs->psw &= ~(PSW_BC);
186
187 return 0;
188}
189
190static int emu_mv(unsigned short insn, struct pt_regs *regs)
191{
192 int val;
193
194 val = get_reg(regs, REG2(insn));
195 set_reg(regs, REG1(insn), val);
196
197 return 0;
198}
199
200static int emu_neg(unsigned short insn, struct pt_regs *regs)
201{
202 int val;
203
204 val = get_reg(regs, REG2(insn));
205 set_reg(regs, REG1(insn), 0 - val);
206
207 return 0;
208}
209
210static int emu_not(unsigned short insn, struct pt_regs *regs)
211{
212 int val;
213
214 val = get_reg(regs, REG2(insn));
215 set_reg(regs, REG1(insn), ~val);
216
217 return 0;
218}
219
220static int emu_or(unsigned short insn, struct pt_regs *regs)
221{
222 int dest = REG1(insn);
223 int val;
224
225 val = get_reg(regs, dest);
226 val |= get_reg(regs, REG2(insn));
227 set_reg(regs, dest, val);
228
229 return 0;
230}
231
232static int emu_sub(unsigned short insn, struct pt_regs *regs)
233{
234 int dest = REG1(insn);
235 int val;
236
237 val = get_reg(regs, dest);
238 val -= get_reg(regs, REG2(insn));
239 set_reg(regs, dest, val);
240
241 return 0;
242}
243
244static int emu_subx(unsigned short insn, struct pt_regs *regs)
245{
246 int dest = REG1(insn);
247 unsigned int val, tmp;
248
249 val = tmp = get_reg(regs, dest);
250 val -= (unsigned int)get_reg(regs, REG2(insn));
251 val -= regs->psw & PSW_BC ? 1 : 0;
252 set_reg(regs, dest, val);
253
254 /* C bit set */
255 if (val > tmp)
256 regs->psw |= PSW_BC;
257 else
258 regs->psw &= ~(PSW_BC);
259
260 return 0;
261}
262
263static int emu_xor(unsigned short insn, struct pt_regs *regs)
264{
265 int dest = REG1(insn);
266 unsigned int val;
267
268 val = (unsigned int)get_reg(regs, dest);
269 val ^= (unsigned int)get_reg(regs, REG2(insn));
270 set_reg(regs, dest, val);
271
272 return 0;
273}
274
275static int emu_mul(unsigned short insn, struct pt_regs *regs)
276{
277 int dest = REG1(insn);
278 int reg1, reg2;
279
280 reg1 = get_reg(regs, dest);
281 reg2 = get_reg(regs, REG2(insn));
282
283 __asm__ __volatile__ (
284 "mul %0, %1; \n\t"
285 : "+r" (reg1) : "r" (reg2)
286 );
287
288 set_reg(regs, dest, reg1);
289
290 return 0;
291}
292
293static int emu_mullo_a0(unsigned short insn, struct pt_regs *regs)
294{
295 int reg1, reg2;
296
297 reg1 = get_reg(regs, REG1(insn));
298 reg2 = get_reg(regs, REG2(insn));
299
300 __asm__ __volatile__ (
301 "mullo %0, %1, a0; \n\t"
302 "mvfachi %0, a0; \n\t"
303 "mvfaclo %1, a0; \n\t"
304 : "+r" (reg1), "+r" (reg2)
305 );
306
307 regs->acc0h = reg1;
308 regs->acc0l = reg2;
309
310 return 0;
311}
312
313static int emu_mullo_a1(unsigned short insn, struct pt_regs *regs)
314{
315 int reg1, reg2;
316
317 reg1 = get_reg(regs, REG1(insn));
318 reg2 = get_reg(regs, REG2(insn));
319
320 __asm__ __volatile__ (
321 "mullo %0, %1, a0; \n\t"
322 "mvfachi %0, a0; \n\t"
323 "mvfaclo %1, a0; \n\t"
324 : "+r" (reg1), "+r" (reg2)
325 );
326
327 regs->acc1h = reg1;
328 regs->acc1l = reg2;
329
330 return 0;
331}
332
333static int emu_mvfacmi_a0(unsigned short insn, struct pt_regs *regs)
334{
335 unsigned long val;
336
337 val = (regs->acc0h << 16) | (regs->acc0l >> 16);
338 set_reg(regs, REG1(insn), (int)val);
339
340 return 0;
341}
342
343static int emu_mvfacmi_a1(unsigned short insn, struct pt_regs *regs)
344{
345 unsigned long val;
346
347 val = (regs->acc1h << 16) | (regs->acc1l >> 16);
348 set_reg(regs, REG1(insn), (int)val);
349
350 return 0;
351}
352
353static int emu_m32r2(unsigned short insn, struct pt_regs *regs)
354{
355 int res = -1;
356
357 if ((insn & 0x7fff) == ISA_NOP) /* nop */
358 return 0;
359
360 switch(insn & 0x7000) {
361 case ISA_ADDI: /* addi Rdest, #imm8 */
362 res = emu_addi(insn, regs);
363 break;
364 case ISA_LDI: /* ldi Rdest, #imm8 */
365 res = emu_ldi(insn, regs);
366 break;
367 default:
368 break;
369 }
370
371 if (!res)
372 return 0;
373
374 switch(insn & 0x70f0) {
375 case ISA_ADD: /* add Rdest, Rsrc */
376 res = emu_add(insn, regs);
377 break;
378 case ISA_ADDX: /* addx Rdest, Rsrc */
379 res = emu_addx(insn, regs);
380 break;
381 case ISA_AND: /* and Rdest, Rsrc */
382 res = emu_and(insn, regs);
383 break;
384 case ISA_CMP: /* cmp Rsrc1, Rsrc2 */
385 res = emu_cmp(insn, regs);
386 break;
387 case ISA_CMPEQ: /* cmpeq Rsrc1, Rsrc2 */
388 res = emu_cmpeq(insn, regs);
389 break;
390 case ISA_CMPU: /* cmpu Rsrc1, Rsrc2 */
391 res = emu_cmpu(insn, regs);
392 break;
393 case ISA_CMPZ: /* cmpz Rsrc */
394 res = emu_cmpz(insn, regs);
395 break;
396 case ISA_MV: /* mv Rdest, Rsrc */
397 res = emu_mv(insn, regs);
398 break;
399 case ISA_NEG: /* neg Rdest, Rsrc */
400 res = emu_neg(insn, regs);
401 break;
402 case ISA_NOT: /* not Rdest, Rsrc */
403 res = emu_not(insn, regs);
404 break;
405 case ISA_OR: /* or Rdest, Rsrc */
406 res = emu_or(insn, regs);
407 break;
408 case ISA_SUB: /* sub Rdest, Rsrc */
409 res = emu_sub(insn, regs);
410 break;
411 case ISA_SUBX: /* subx Rdest, Rsrc */
412 res = emu_subx(insn, regs);
413 break;
414 case ISA_XOR: /* xor Rdest, Rsrc */
415 res = emu_xor(insn, regs);
416 break;
417 case ISA_MUL: /* mul Rdest, Rsrc */
418 res = emu_mul(insn, regs);
419 break;
420 case ISA_MULLO_A0: /* mullo Rsrc1, Rsrc2 */
421 res = emu_mullo_a0(insn, regs);
422 break;
423 case ISA_MULLO_A1: /* mullo Rsrc1, Rsrc2 */
424 res = emu_mullo_a1(insn, regs);
425 break;
426 default:
427 break;
428 }
429
430 if (!res)
431 return 0;
432
433 switch(insn & 0x70ff) {
434 case ISA_MVFACMI_A0: /* mvfacmi Rdest */
435 res = emu_mvfacmi_a0(insn, regs);
436 break;
437 case ISA_MVFACMI_A1: /* mvfacmi Rdest */
438 res = emu_mvfacmi_a1(insn, regs);
439 break;
440 default:
441 break;
442 }
443
444 return res;
445}
446
447#endif /* CONFIG_ISA_DUAL_ISSUE */
448
449/*
450 * ld : ?010 dest 1100 src
451 * 0010 dest 1110 src : ld Rdest, @Rsrc+
452 * ldh : ?010 dest 1010 src
453 * lduh : ?010 dest 1011 src
454 * st : ?010 src1 0100 src2
455 * 0010 src1 0110 src2 : st Rsrc1, @+Rsrc2
456 * 0010 src1 0111 src2 : st Rsrc1, @-Rsrc2
457 * sth : ?010 src1 0010 src2
458 */
459
460static int insn_check(unsigned long insn, struct pt_regs *regs,
461 unsigned char **ucp)
462{
463 int res = 0;
464
465 /*
466 * 32bit insn
467 * ld Rdest, @(disp16, Rsrc)
468 * st Rdest, @(disp16, Rsrc)
469 */
470 if (insn & 0x80000000) { /* 32bit insn */
471 *ucp += (short)(insn & 0x0000ffff);
472 regs->bpc += 4;
473 } else { /* 16bit insn */
474#ifdef CONFIG_ISA_DUAL_ISSUE
475 /* parallel exec check */
476 if (!(regs->bpc & 0x2) && insn & 0x8000) {
477 res = emu_m32r2((unsigned short)insn, regs);
478 regs->bpc += 4;
479 } else
480#endif /* CONFIG_ISA_DUAL_ISSUE */
481 regs->bpc += 2;
482 }
483
484 return res;
485}
486
487static int emu_ld(unsigned long insn32, struct pt_regs *regs)
488{
489 unsigned char *ucp;
490 unsigned long val;
491 unsigned short insn16;
492 int size, src;
493
494 insn16 = insn32 >> 16;
495 src = REG2(insn16);
496 ucp = (unsigned char *)get_reg(regs, src);
497
498 if (insn_check(insn32, regs, &ucp))
499 return -1;
500
501 size = insn16 & 0x0040 ? 4 : 2;
502 if (copy_from_user(&val, ucp, size))
503 return -1;
504
505 if (size == 2)
506 val >>= 16;
507
508 /* ldh sign check */
509 if ((insn16 & 0x00f0) == 0x00a0 && (val & 0x8000))
510 val |= 0xffff0000;
511
512 set_reg(regs, REG1(insn16), val);
513
514 /* ld increment check */
515 if ((insn16 & 0xf0f0) == ISA_LD2) /* ld Rdest, @Rsrc+ */
516 set_reg(regs, src, (unsigned long)(ucp + 4));
517
518 return 0;
519}
520
521static int emu_st(unsigned long insn32, struct pt_regs *regs)
522{
523 unsigned char *ucp;
524 unsigned long val;
525 unsigned short insn16;
526 int size, src2;
527
528 insn16 = insn32 >> 16;
529 src2 = REG2(insn16);
530
531 ucp = (unsigned char *)get_reg(regs, src2);
532
533 if (insn_check(insn32, regs, &ucp))
534 return -1;
535
536 size = insn16 & 0x0040 ? 4 : 2;
537 val = get_reg(regs, REG1(insn16));
538 if (size == 2)
539 val <<= 16;
540
541 /* st inc/dec check */
542 if ((insn16 & 0xf0e0) == 0x2060) {
543 if (insn16 & 0x0010)
544 ucp -= 4;
545 else
546 ucp += 4;
547
548 set_reg(regs, src2, (unsigned long)ucp);
549 }
550
551 if (copy_to_user(ucp, &val, size))
552 return -1;
553
554 /* sth inc check */
555 if ((insn16 & 0xf0f0) == ISA_STH2) {
556 ucp += 2;
557 set_reg(regs, src2, (unsigned long)ucp);
558 }
559
560 return 0;
561}
562
563int handle_unaligned_access(unsigned long insn32, struct pt_regs *regs)
564{
565 unsigned short insn16;
566 int res;
567
568 insn16 = insn32 >> 16;
569
570 /* ld or st check */
571 if ((insn16 & 0x7000) != 0x2000)
572 return -1;
573
574 /* insn alignment check */
575 if ((insn16 & 0x8000) && (regs->bpc & 3))
576 return -1;
577
578 if (insn16 & 0x0080) /* ld */
579 res = emu_ld(insn32, regs);
580 else /* st */
581 res = emu_st(insn32, regs);
582
583 return res;
584}
585
diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S
new file mode 100644
index 000000000000..dddbf6b5ed2c
--- /dev/null
+++ b/arch/m32r/kernel/entry.S
@@ -0,0 +1,1000 @@
1/*
2 * linux/arch/m32r/kernel/entry.S
3 *
4 * Copyright (c) 2001, 2002 Hirokazu Takata, Hitoshi Yamamoto, H. Kondo
5 * Copyright (c) 2003 Hitoshi Yamamoto
6 * Copyright (c) 2004 Hirokazu Takata <takata at linux-m32r.org>
7 *
8 * Taken from i386 version.
9 * Copyright (C) 1991, 1992 Linus Torvalds
10 */
11
12/*
13 * entry.S contains the system-call and fault low-level handling routines.
14 * This also contains the timer-interrupt handler, as well as all interrupts
15 * and faults that can result in a task-switch.
16 *
17 * NOTE: This code handles signal-recognition, which happens every time
18 * after a timer-interrupt and after each system call.
19 *
20 * Stack layout in 'ret_from_system_call':
21 * ptrace needs to have all regs on the stack.
22 * if the order here is changed, it needs to be
23 * updated in fork.c:copy_process, signal.c:do_signal,
24 * ptrace.c and ptrace.h
25 *
26 * M32Rx/M32R2 M32R
27 * @(sp) - r4 ditto
28 * @(0x04,sp) - r5 ditto
29 * @(0x08,sp) - r6 ditto
30 * @(0x0c,sp) - *pt_regs ditto
31 * @(0x10,sp) - r0 ditto
32 * @(0x14,sp) - r1 ditto
33 * @(0x18,sp) - r2 ditto
34 * @(0x1c,sp) - r3 ditto
35 * @(0x20,sp) - r7 ditto
36 * @(0x24,sp) - r8 ditto
37 * @(0x28,sp) - r9 ditto
38 * @(0x2c,sp) - r10 ditto
39 * @(0x30,sp) - r11 ditto
40 * @(0x34,sp) - r12 ditto
41 * @(0x38,sp) - syscall_nr ditto
42 * @(0x3c,sp) - acc0h @(0x3c,sp) - acch
43 * @(0x40,sp) - acc0l @(0x40,sp) - accl
44 * @(0x44,sp) - acc1h @(0x44,sp) - psw
45 * @(0x48,sp) - acc1l @(0x48,sp) - bpc
46 * @(0x4c,sp) - psw @(0x4c,sp) - bbpsw
47 * @(0x50,sp) - bpc @(0x50,sp) - bbpc
48 * @(0x54,sp) - bbpsw @(0x54,sp) - spu (cr3)
49 * @(0x58,sp) - bbpc @(0x58,sp) - fp (r13)
50 * @(0x5c,sp) - spu (cr3) @(0x5c,sp) - lr (r14)
51 * @(0x60,sp) - fp (r13) @(0x60,sp) - spi (cr12)
52 * @(0x64,sp) - lr (r14) @(0x64,sp) - orig_r0
53 * @(0x68,sp) - spi (cr2)
54 * @(0x6c,sp) - orig_r0
55 *
56 */
57
58#include <linux/config.h>
59#include <linux/linkage.h>
60#include <asm/irq.h>
61#include <asm/unistd.h>
62#include <asm/assembler.h>
63#include <asm/thread_info.h>
64#include <asm/errno.h>
65#include <asm/segment.h>
66#include <asm/smp.h>
67#include <asm/page.h>
68#include <asm/m32r.h>
69#include <asm/mmu_context.h>
70
71#if !defined(CONFIG_MMU)
72#define sys_madvise sys_ni_syscall
73#define sys_readahead sys_ni_syscall
74#define sys_mprotect sys_ni_syscall
75#define sys_msync sys_ni_syscall
76#define sys_mlock sys_ni_syscall
77#define sys_munlock sys_ni_syscall
78#define sys_mlockall sys_ni_syscall
79#define sys_munlockall sys_ni_syscall
80#define sys_mremap sys_ni_syscall
81#define sys_mincore sys_ni_syscall
82#define sys_remap_file_pages sys_ni_syscall
83#endif /* CONFIG_MMU */
84
85#define R4(reg) @reg
86#define R5(reg) @(0x04,reg)
87#define R6(reg) @(0x08,reg)
88#define PTREGS(reg) @(0x0C,reg)
89#define R0(reg) @(0x10,reg)
90#define R1(reg) @(0x14,reg)
91#define R2(reg) @(0x18,reg)
92#define R3(reg) @(0x1C,reg)
93#define R7(reg) @(0x20,reg)
94#define R8(reg) @(0x24,reg)
95#define R9(reg) @(0x28,reg)
96#define R10(reg) @(0x2C,reg)
97#define R11(reg) @(0x30,reg)
98#define R12(reg) @(0x34,reg)
99#define SYSCALL_NR(reg) @(0x38,reg)
100#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
101#define ACC0H(reg) @(0x3C,reg)
102#define ACC0L(reg) @(0x40,reg)
103#define ACC1H(reg) @(0x44,reg)
104#define ACC1L(reg) @(0x48,reg)
105#define PSW(reg) @(0x4C,reg)
106#define BPC(reg) @(0x50,reg)
107#define BBPSW(reg) @(0x54,reg)
108#define BBPC(reg) @(0x58,reg)
109#define SPU(reg) @(0x5C,reg)
110#define FP(reg) @(0x60,reg) /* FP = R13 */
111#define LR(reg) @(0x64,reg)
112#define SP(reg) @(0x68,reg)
113#define ORIG_R0(reg) @(0x6C,reg)
114#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
115#define ACCH(reg) @(0x3C,reg)
116#define ACCL(reg) @(0x40,reg)
117#define PSW(reg) @(0x44,reg)
118#define BPC(reg) @(0x48,reg)
119#define BBPSW(reg) @(0x4C,reg)
120#define BBPC(reg) @(0x50,reg)
121#define SPU(reg) @(0x54,reg)
122#define FP(reg) @(0x58,reg) /* FP = R13 */
123#define LR(reg) @(0x5C,reg)
124#define SP(reg) @(0x60,reg)
125#define ORIG_R0(reg) @(0x64,reg)
126#else
127#error unknown isa configuration
128#endif
129
130CF_MASK = 0x00000001
131TF_MASK = 0x00000100
132IF_MASK = 0x00000200
133DF_MASK = 0x00000400
134NT_MASK = 0x00004000
135VM_MASK = 0x00020000
136
137#ifdef CONFIG_PREEMPT
138#define preempt_stop(x) CLI(x)
139#else
140#define preempt_stop(x)
141#define resume_kernel restore_all
142#endif
143
144ENTRY(ret_from_fork)
145 ld r0, @sp+
146 bl schedule_tail
147 GET_THREAD_INFO(r8)
148 bra syscall_exit
149
150/*
151 * Return to user mode is not as complex as all this looks,
152 * but we want the default path for a system call return to
153 * go as quickly as possible which is why some of this is
154 * less clear than it otherwise should be.
155 */
156
157 ; userspace resumption stub bypassing syscall exit tracing
158 ALIGN
159ret_from_exception:
160 preempt_stop(r4)
161ret_from_intr:
162 ld r4, PSW(sp)
163#ifdef CONFIG_ISA_M32R2
164 and3 r4, r4, #0x8800 ; check BSM and BPM bits
165#else
166 and3 r4, r4, #0x8000 ; check BSM bit
167#endif
168 beqz r4, resume_kernel
169ENTRY(resume_userspace)
170 CLI(r4) ; make sure we don't miss an interrupt
171 ; setting need_resched or sigpending
172 ; between sampling and the iret
173 GET_THREAD_INFO(r8)
174 ld r9, @(TI_FLAGS, r8)
175 and3 r4, r9, #_TIF_WORK_MASK ; is there any work to be done on
176 ; int/exception return?
177 bnez r4, work_pending
178 bra restore_all
179
180#ifdef CONFIG_PREEMPT
181ENTRY(resume_kernel)
182 GET_THREAD_INFO(r8)
183 ld r9, @(TI_PRE_COUNT, r8) ; non-zero preempt_count ?
184 bnez r9, restore_all
185need_resched:
186 ld r9, @(TI_FLAGS, r8) ; need_resched set ?
187 and3 r4, r9, #_TIF_NEED_RESCHED
188 beqz r4, restore_all
189 ld r4, PSW(sp) ; interrupts off (exception path) ?
190 and3 r4, r4, #0x4000
191 beqz r4, restore_all
192 LDIMM (r4, PREEMPT_ACTIVE)
193 st r4, @(TI_PRE_COUNT, r8)
194 STI(r4)
195 bl schedule
196 ldi r4, #0
197 st r4, @(TI_PRE_COUNT, r8)
198 CLI(r4)
199 bra need_resched
200#endif
201
202 ; system call handler stub
203ENTRY(system_call)
204 SWITCH_TO_KERNEL_STACK
205 SAVE_ALL
206 STI(r4) ; Enable interrupt
207 st sp, PTREGS(sp) ; implicit pt_regs parameter
208 cmpui r7, #NR_syscalls
209 bnc syscall_badsys
210 st r7, SYSCALL_NR(sp) ; syscall_nr
211 ; system call tracing in operation
212 GET_THREAD_INFO(r8)
213 ld r9, @(TI_FLAGS, r8)
214 and3 r4, r9, #_TIF_SYSCALL_TRACE
215 bnez r4, syscall_trace_entry
216syscall_call:
217 slli r7, #2 ; table jump for the system call
218 LDIMM (r4, sys_call_table)
219 add r7, r4
220 ld r7, @r7
221 jl r7 ; execute system call
222 st r0, R0(sp) ; save the return value
223syscall_exit:
224 CLI(r4) ; make sure we don't miss an interrupt
225 ; setting need_resched or sigpending
226 ; between sampling and the iret
227 ld r9, @(TI_FLAGS, r8)
228 and3 r4, r9, #_TIF_ALLWORK_MASK ; current->work
229 bnez r4, syscall_exit_work
230restore_all:
231 RESTORE_ALL
232
233 # perform work that needs to be done immediately before resumption
234 # r9 : frags
235 ALIGN
236work_pending:
237 and3 r4, r9, #_TIF_NEED_RESCHED
238 beqz r4, work_notifysig
239work_resched:
240 bl schedule
241 CLI(r4) ; make sure we don't miss an interrupt
242 ; setting need_resched or sigpending
243 ; between sampling and the iret
244 ld r9, @(TI_FLAGS, r8)
245 and3 r4, r9, #_TIF_WORK_MASK ; is there any work to be done other
246 ; than syscall tracing?
247 beqz r4, restore_all
248 and3 r4, r4, #_TIF_NEED_RESCHED
249 bnez r4, work_resched
250
251work_notifysig: ; deal with pending signals and
252 ; notify-resume requests
253 mv r0, sp ; arg1 : struct pt_regs *regs
254 ldi r1, #0 ; arg2 : sigset_t *oldset
255 mv r2, r9 ; arg3 : __u32 thread_info_flags
256 bl do_notify_resume
257 bra restore_all
258
259 ; perform syscall exit tracing
260 ALIGN
261syscall_trace_entry:
262 ldi r4, #-ENOSYS
263 st r4, R0(sp)
264 bl do_syscall_trace
265 ld r0, ORIG_R0(sp)
266 ld r1, R1(sp)
267 ld r2, R2(sp)
268 ld r3, R3(sp)
269 ld r4, R4(sp)
270 ld r5, R5(sp)
271 ld r6, R6(sp)
272 ld r7, SYSCALL_NR(sp)
273 cmpui r7, #NR_syscalls
274 bc syscall_call
275 bra syscall_exit
276
277 ; perform syscall exit tracing
278 ALIGN
279syscall_exit_work:
280 ld r9, @(TI_FLAGS, r8)
281 and3 r4, r9, #_TIF_SYSCALL_TRACE
282 beqz r4, work_pending
283 STI(r4) ; could let do_syscall_trace() call
284 ; schedule() instead
285 bl do_syscall_trace
286 bra resume_userspace
287
288 ALIGN
289syscall_fault:
290 SAVE_ALL
291 GET_THREAD_INFO(r8)
292 ldi r4, #-EFAULT
293 st r4, R0(sp)
294 bra resume_userspace
295
296 ALIGN
297syscall_badsys:
298 ldi r4, #-ENOSYS
299 st r4, R0(sp)
300 bra resume_userspace
301
302 .global eit_vector
303
304 .equ ei_vec_table, eit_vector + 0x0200
305
306/*
307 * EI handler routine
308 */
309ENTRY(ei_handler)
310#if defined(CONFIG_CHIP_M32700)
311 SWITCH_TO_KERNEL_STACK
312 ; WORKAROUND: force to clear SM bit and use the kernel stack (SPI).
313#endif
314 SAVE_ALL
315 mv r1, sp ; arg1(regs)
316#if defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_XNUX2) \
317 || defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_M32102) \
318 || defined(CONFIG_CHIP_OPSP)
319
320; GET_ICU_STATUS;
321 seth r0, #shigh(M32R_ICU_ISTS_ADDR)
322 ld r0, @(low(M32R_ICU_ISTS_ADDR),r0)
323 st r0, @-sp
324#if defined(CONFIG_SMP)
325 /*
326 * If IRQ == 0 --> Nothing to do, Not write IMASK
327 * If IRQ == IPI --> Do IPI handler, Not write IMASK
328 * If IRQ != 0, IPI --> Do do_IRQ(), Write IMASK
329 */
330 slli r0, #4
331 srli r0, #24 ; r0(irq_num<<2)
332 ;; IRQ exist check
333#if defined(CONFIG_CHIP_M32700)
334 /* WORKAROUND: IMASK bug M32700-TS1, TS2 chip. */
335 beqz r0, 3f ; if (!irq_num) goto exit
336#else
337 beqz r0, 1f ; if (!irq_num) goto exit
338#endif /* WORKAROUND */
339 ;; IPI check
340 cmpi r0, #(M32R_IRQ_IPI0<<2) ; ISN < IPI0 check
341 bc 2f
342 cmpi r0, #((M32R_IRQ_IPI7+1)<<2) ; ISN > IPI7 check
343 bnc 2f
344 LDIMM (r2, ei_vec_table)
345 add r2, r0
346 ld r2, @r2
347 beqz r2, 1f ; if (no IPI handler) goto exit
348 mv r0, r1 ; arg0(regs)
349 jl r2
350 .fillinsn
3511:
352 addi sp, #4
353 bra ret_to_intr
354#if defined(CONFIG_CHIP_M32700)
355 /* WORKAROUND: IMASK bug M32700-TS1, TS2 chip. */
356 .fillinsn
3573:
358 ld24 r14, #0x00070000
359 seth r0, #shigh(M32R_ICU_IMASK_ADDR)
360 st r14, @(low(M32R_ICU_IMASK_ADDR), r0)
361 addi sp, #4
362 bra ret_to_intr
363#endif /* WORKAROUND */
364 ;; do_IRQ
365 .fillinsn
3662:
367 srli r0, #2
368#if defined(CONFIG_PLAT_USRV)
369 add3 r2, r0, #-(M32R_IRQ_INT1) ; INT1# interrupt
370 bnez r2, 9f
371 ; read ICU status register of PLD
372 seth r0, #high(PLD_ICUISTS)
373 or3 r0, r0, #low(PLD_ICUISTS)
374 lduh r0, @r0
375 slli r0, #21
376 srli r0, #27 ; ISN
377 addi r0, #(M32700UT_PLD_IRQ_BASE)
378 .fillinsn
3799:
380#elif defined(CONFIG_PLAT_M32700UT)
381 add3 r2, r0, #-(M32R_IRQ_INT1) ; INT1# interrupt
382 bnez r2, check_int0
383 ; read ICU status register of PLD
384 seth r0, #high(PLD_ICUISTS)
385 or3 r0, r0, #low(PLD_ICUISTS)
386 lduh r0, @r0
387 slli r0, #21
388 srli r0, #27 ; ISN
389 addi r0, #(M32700UT_PLD_IRQ_BASE)
390 bra check_end
391 .fillinsn
392check_int0:
393 add3 r2, r0, #-(M32R_IRQ_INT0) ; INT0# interrupt
394 bnez r2, check_int2
395 ; read ICU status of LAN-board
396 seth r0, #high(M32700UT_LAN_ICUISTS)
397 or3 r0, r0, #low(M32700UT_LAN_ICUISTS)
398 lduh r0, @r0
399 slli r0, #21
400 srli r0, #27 ; ISN
401 add3 r0, r0, #(M32700UT_LAN_PLD_IRQ_BASE)
402 bra check_end
403 .fillinsn
404check_int2:
405 add3 r2, r0, #-(M32R_IRQ_INT2) ; INT2# interrupt
406 bnez r2, check_end
407 ; read ICU status of LCD-board
408 seth r0, #high(M32700UT_LCD_ICUISTS)
409 or3 r0, r0, #low(M32700UT_LCD_ICUISTS)
410 lduh r0, @r0
411 slli r0, #21
412 srli r0, #27 ; ISN
413 add3 r0, r0, #(M32700UT_LCD_PLD_IRQ_BASE)
414 bra check_end
415 .fillinsn
416check_end:
417#elif defined(CONFIG_PLAT_OPSPUT)
418 add3 r2, r0, #-(M32R_IRQ_INT1) ; INT1# interrupt
419 bnez r2, check_int0
420 ; read ICU status register of PLD
421 seth r0, #high(PLD_ICUISTS)
422 or3 r0, r0, #low(PLD_ICUISTS)
423 lduh r0, @r0
424 slli r0, #21
425 srli r0, #27 ; ISN
426 addi r0, #(OPSPUT_PLD_IRQ_BASE)
427 bra check_end
428 .fillinsn
429check_int0:
430 add3 r2, r0, #-(M32R_IRQ_INT0) ; INT0# interrupt
431 bnez r2, check_int2
432 ; read ICU status of LAN-board
433 seth r0, #high(OPSPUT_LAN_ICUISTS)
434 or3 r0, r0, #low(OPSPUT_LAN_ICUISTS)
435 lduh r0, @r0
436 slli r0, #21
437 srli r0, #27 ; ISN
438 add3 r0, r0, #(OPSPUT_LAN_PLD_IRQ_BASE)
439 bra check_end
440 .fillinsn
441check_int2:
442 add3 r2, r0, #-(M32R_IRQ_INT2) ; INT2# interrupt
443 bnez r2, check_end
444 ; read ICU status of LCD-board
445 seth r0, #high(OPSPUT_LCD_ICUISTS)
446 or3 r0, r0, #low(OPSPUT_LCD_ICUISTS)
447 lduh r0, @r0
448 slli r0, #21
449 srli r0, #27 ; ISN
450 add3 r0, r0, #(OPSPUT_LCD_PLD_IRQ_BASE)
451 bra check_end
452 .fillinsn
453check_end:
454#endif /* CONFIG_PLAT_OPSPUT */
455 bl do_IRQ ; r0(irq), r1(regs)
456#else /* not CONFIG_SMP */
457 srli r0, #22 ; r0(irq)
458#if defined(CONFIG_PLAT_USRV)
459 add3 r2, r0, #-(M32R_IRQ_INT1) ; INT1# interrupt
460 bnez r2, 1f
461 ; read ICU status register of PLD
462 seth r0, #high(PLD_ICUISTS)
463 or3 r0, r0, #low(PLD_ICUISTS)
464 lduh r0, @r0
465 slli r0, #21
466 srli r0, #27 ; ISN
467 addi r0, #(M32700UT_PLD_IRQ_BASE)
468 .fillinsn
4691:
470#elif defined(CONFIG_PLAT_M32700UT)
471 add3 r2, r0, #-(M32R_IRQ_INT1) ; INT1# interrupt
472 bnez r2, check_int0
473 ; read ICU status register of PLD
474 seth r0, #high(PLD_ICUISTS)
475 or3 r0, r0, #low(PLD_ICUISTS)
476 lduh r0, @r0
477 slli r0, #21
478 srli r0, #27 ; ISN
479 addi r0, #(M32700UT_PLD_IRQ_BASE)
480 bra check_end
481 .fillinsn
482check_int0:
483 add3 r2, r0, #-(M32R_IRQ_INT0) ; INT0# interrupt
484 bnez r2, check_int2
485 ; read ICU status of LAN-board
486 seth r0, #high(M32700UT_LAN_ICUISTS)
487 or3 r0, r0, #low(M32700UT_LAN_ICUISTS)
488 lduh r0, @r0
489 slli r0, #21
490 srli r0, #27 ; ISN
491 add3 r0, r0, #(M32700UT_LAN_PLD_IRQ_BASE)
492 bra check_end
493 .fillinsn
494check_int2:
495 add3 r2, r0, #-(M32R_IRQ_INT2) ; INT2# interrupt
496 bnez r2, check_end
497 ; read ICU status of LCD-board
498 seth r0, #high(M32700UT_LCD_ICUISTS)
499 or3 r0, r0, #low(M32700UT_LCD_ICUISTS)
500 lduh r0, @r0
501 slli r0, #21
502 srli r0, #27 ; ISN
503 add3 r0, r0, #(M32700UT_LCD_PLD_IRQ_BASE)
504 bra check_end
505 .fillinsn
506check_end:
507#elif defined(CONFIG_PLAT_OPSPUT)
508 add3 r2, r0, #-(M32R_IRQ_INT1) ; INT1# interrupt
509 bnez r2, check_int0
510 ; read ICU status register of PLD
511 seth r0, #high(PLD_ICUISTS)
512 or3 r0, r0, #low(PLD_ICUISTS)
513 lduh r0, @r0
514 slli r0, #21
515 srli r0, #27 ; ISN
516 addi r0, #(OPSPUT_PLD_IRQ_BASE)
517 bra check_end
518 .fillinsn
519check_int0:
520 add3 r2, r0, #-(M32R_IRQ_INT0) ; INT0# interrupt
521 bnez r2, check_int2
522 ; read ICU status of LAN-board
523 seth r0, #high(OPSPUT_LAN_ICUISTS)
524 or3 r0, r0, #low(OPSPUT_LAN_ICUISTS)
525 lduh r0, @r0
526 slli r0, #21
527 srli r0, #27 ; ISN
528 add3 r0, r0, #(OPSPUT_LAN_PLD_IRQ_BASE)
529 bra check_end
530 .fillinsn
531check_int2:
532 add3 r2, r0, #-(M32R_IRQ_INT2) ; INT2# interrupt
533 bnez r2, check_end
534 ; read ICU status of LCD-board
535 seth r0, #high(OPSPUT_LCD_ICUISTS)
536 or3 r0, r0, #low(OPSPUT_LCD_ICUISTS)
537 lduh r0, @r0
538 slli r0, #21
539 srli r0, #27 ; ISN
540 add3 r0, r0, #(OPSPUT_LCD_PLD_IRQ_BASE)
541 bra check_end
542 .fillinsn
543check_end:
544#endif /* CONFIG_PLAT_OPSPUT */
545 bl do_IRQ
546#endif /* CONFIG_SMP */
547 ld r14, @sp+
548 seth r0, #shigh(M32R_ICU_IMASK_ADDR)
549 st r14, @(low(M32R_ICU_IMASK_ADDR),r0)
550#else
551#error no chip configuration
552#endif
553ret_to_intr:
554 bra ret_from_intr
555
556/*
557 * Default EIT handler
558 */
559 ALIGN
560int_msg:
561 .asciz "Unknown interrupt\n"
562 .byte 0
563
564ENTRY(default_eit_handler)
565 push r0
566 mvfc r0, psw
567 push r1
568 push r2
569 push r3
570 push r0
571 LDIMM (r0, __KERNEL_DS)
572 mv r0, r1
573 mv r0, r2
574 LDIMM (r0, int_msg)
575 bl printk
576 pop r0
577 pop r3
578 pop r2
579 pop r1
580 mvtc r0, psw
581 pop r0
582infinit:
583 bra infinit
584
585#ifdef CONFIG_MMU
586/*
587 * Access Exception handler
588 */
589ENTRY(ace_handler)
590 SWITCH_TO_KERNEL_STACK
591 SAVE_ALL
592
593 seth r2, #shigh(MMU_REG_BASE) /* Check status register */
594 ld r4, @(low(MESTS_offset),r2)
595 st r4, @(low(MESTS_offset),r2)
596 srl3 r1, r4, #4
597#ifdef CONFIG_CHIP_M32700
598 and3 r1, r1, #0x0000ffff
599 ; WORKAROUND: ignore TME bit for the M32700(TS1).
600#endif /* CONFIG_CHIP_M32700 */
601 beqz r1, inst
602oprand:
603 ld r2, @(low(MDEVA_offset),r2) ; set address
604 srli r2, #12
605 slli r2, #12
606 srli r1, #1
607 bra 1f
608inst:
609 and3 r1, r4, #2
610 srli r1, #1
611 or3 r1, r1, #8
612 mvfc r2, bpc ; set address
613 .fillinsn
6141:
615 mvfc r3, psw
616 mv r0, sp
617 and3 r3, r3, 0x800
618 srli r3, #9
619 or r1, r3
620 /*
621 * do_page_fault():
622 * r0 : struct pt_regs *regs
623 * r1 : unsigned long error-code
624 * r2 : unsigned long address
625 * error-code:
626 * +------+------+------+------+
627 * | bit3 | bit2 | bit1 | bit0 |
628 * +------+------+------+------+
629 * bit 3 == 0:means data, 1:means instruction
630 * bit 2 == 0:means kernel, 1:means user-mode
631 * bit 1 == 0:means read, 1:means write
632 * bit 0 == 0:means no page found 1:means protection fault
633 *
634 */
635 bl do_page_fault
636 bra ret_from_intr
637#endif /* CONFIG_MMU */
638
639
640ENTRY(alignment_check)
641/* void alignment_check(int error_code) */
642 SWITCH_TO_KERNEL_STACK
643 SAVE_ALL
644 ldi r1, #0x30 ; error_code
645 mv r0, sp ; pt_regs
646 bl do_alignment_check
647error_code:
648 bra ret_from_exception
649
650ENTRY(rie_handler)
651/* void rie_handler(int error_code) */
652 SWITCH_TO_KERNEL_STACK
653 SAVE_ALL
654 mvfc r0, bpc
655 ld r1, @r0
656 seth r0, #0xa0f0
657 st r1, @r0
658 ldi r1, #0x20 ; error_code
659 mv r0, sp ; pt_regs
660 bl do_rie_handler
661 bra error_code
662
663ENTRY(pie_handler)
664/* void pie_handler(int error_code) */
665 SWITCH_TO_KERNEL_STACK
666 SAVE_ALL
667 ldi r1, #0 ; error_code ; FIXME
668 mv r0, sp ; pt_regs
669 bl do_pie_handler
670 bra error_code
671
672ENTRY(debug_trap)
673 .global withdraw_debug_trap
674 /* void debug_trap(void) */
675 SWITCH_TO_KERNEL_STACK
676 SAVE_ALL
677 mv r0, sp ; pt_regs
678 bl withdraw_debug_trap
679 ldi r1, #0 ; error_code
680 mv r0, sp ; pt_regs
681 bl do_debug_trap
682 bra error_code
683
684
685/* Cache flushing handler */
686ENTRY(cache_flushing_handler)
687 .global _flush_cache_all
688 /* void _flush_cache_all(void); */
689 SWITCH_TO_KERNEL_STACK
690 push r0
691 push r1
692 push r2
693 push r3
694 push r4
695 push r5
696 push r6
697 push r7
698 push lr
699 bl _flush_cache_all
700 pop lr
701 pop r7
702 pop r6
703 pop r5
704 pop r4
705 pop r3
706 pop r2
707 pop r1
708 pop r0
709 rte
710
711.data
712ENTRY(sys_call_table)
713 .long sys_restart_syscall /* 0 - old "setup()" system call*/
714 .long sys_exit
715 .long sys_fork
716 .long sys_read
717 .long sys_write
718 .long sys_open /* 5 */
719 .long sys_close
720 .long sys_waitpid
721 .long sys_creat
722 .long sys_link
723 .long sys_unlink /* 10 */
724 .long sys_execve
725 .long sys_chdir
726 .long sys_time
727 .long sys_mknod
728 .long sys_chmod /* 15 */
729 .long sys_ni_syscall /* lchown16 syscall holder */
730 .long sys_ni_syscall /* old break syscall holder */
731 .long sys_ni_syscall /* old stat syscall holder */
732 .long sys_lseek
733 .long sys_getpid /* 20 */
734 .long sys_mount
735 .long sys_oldumount
736 .long sys_ni_syscall /* setuid16 syscall holder */
737 .long sys_ni_syscall /* getuid16 syscall holder */
738 .long sys_stime /* 25 */
739 .long sys_ptrace
740 .long sys_alarm
741 .long sys_ni_syscall /* old fstat syscall holder */
742 .long sys_pause
743 .long sys_utime /* 30 */
744 .long sys_ni_syscall /* old stty syscall holder */
745 .long sys_cachectl /* for M32R */ /* old gtty syscall holder */
746 .long sys_access
747 .long sys_ni_syscall /* nice syscall holder */
748 .long sys_ni_syscall /* 35 - old ftime syscall holder */
749 .long sys_sync
750 .long sys_kill
751 .long sys_rename
752 .long sys_mkdir
753 .long sys_rmdir /* 40 */
754 .long sys_dup
755 .long sys_pipe
756 .long sys_times
757 .long sys_ni_syscall /* old prof syscall holder */
758 .long sys_brk /* 45 */
759 .long sys_ni_syscall /* setgid16 syscall holder */
760 .long sys_getgid /* will be unused */
761 .long sys_ni_syscall /* signal syscall holder */
762 .long sys_ni_syscall /* geteuid16 syscall holder */
763 .long sys_ni_syscall /* 50 - getegid16 syscall holder */
764 .long sys_acct
765 .long sys_umount /* recycled never used phys() */
766 .long sys_ni_syscall /* old lock syscall holder */
767 .long sys_ioctl
768 .long sys_fcntl /* 55 - will be unused */
769 .long sys_ni_syscall /* mpx syscall holder */
770 .long sys_setpgid
771 .long sys_ni_syscall /* old ulimit syscall holder */
772 .long sys_ni_syscall /* sys_olduname */
773 .long sys_umask /* 60 */
774 .long sys_chroot
775 .long sys_ustat
776 .long sys_dup2
777 .long sys_getppid
778 .long sys_getpgrp /* 65 */
779 .long sys_setsid
780 .long sys_ni_syscall /* sigaction syscall holder */
781 .long sys_ni_syscall /* sgetmask syscall holder */
782 .long sys_ni_syscall /* ssetmask syscall holder */
783 .long sys_ni_syscall /* 70 - setreuid16 syscall holder */
784 .long sys_ni_syscall /* setregid16 syscall holder */
785 .long sys_ni_syscall /* sigsuspend syscall holder */
786 .long sys_ni_syscall /* sigpending syscall holder */
787 .long sys_sethostname
788 .long sys_setrlimit /* 75 */
789 .long sys_getrlimit/*will be unused*/
790 .long sys_getrusage
791 .long sys_gettimeofday
792 .long sys_settimeofday
793 .long sys_ni_syscall /* 80 - getgroups16 syscall holder */
794 .long sys_ni_syscall /* setgroups16 syscall holder */
795 .long sys_ni_syscall /* sys_oldselect */
796 .long sys_symlink
797 .long sys_ni_syscall /* old lstat syscall holder */
798 .long sys_readlink /* 85 */
799 .long sys_uselib
800 .long sys_swapon
801 .long sys_reboot
802 .long sys_ni_syscall /* readdir syscall holder */
803 .long sys_ni_syscall /* 90 - old_mmap syscall holder */
804 .long sys_munmap
805 .long sys_truncate
806 .long sys_ftruncate
807 .long sys_fchmod
808 .long sys_ni_syscall /* 95 - fchwon16 syscall holder */
809 .long sys_getpriority
810 .long sys_setpriority
811 .long sys_ni_syscall /* old profil syscall holder */
812 .long sys_statfs
813 .long sys_fstatfs /* 100 */
814 .long sys_ni_syscall /* ioperm syscall holder */
815 .long sys_socketcall
816 .long sys_syslog
817 .long sys_setitimer
818 .long sys_getitimer /* 105 */
819 .long sys_newstat
820 .long sys_newlstat
821 .long sys_newfstat
822 .long sys_ni_syscall /* old uname syscall holder */
823 .long sys_ni_syscall /* 110 - iopl syscall holder */
824 .long sys_vhangup
825 .long sys_ni_syscall /* idle syscall holder */
826 .long sys_ni_syscall /* vm86old syscall holder */
827 .long sys_wait4
828 .long sys_swapoff /* 115 */
829 .long sys_sysinfo
830 .long sys_ipc
831 .long sys_fsync
832 .long sys_ni_syscall /* sigreturn syscall holder */
833 .long sys_clone /* 120 */
834 .long sys_setdomainname
835 .long sys_newuname
836 .long sys_ni_syscall /* modify_ldt syscall holder */
837 .long sys_adjtimex
838 .long sys_mprotect /* 125 */
839 .long sys_ni_syscall /* sigprocmask syscall holder */
840 .long sys_ni_syscall /* create_module syscall holder */
841 .long sys_init_module
842 .long sys_delete_module
843 .long sys_ni_syscall /* 130 - get_kernel_syms */
844 .long sys_quotactl
845 .long sys_getpgid
846 .long sys_fchdir
847 .long sys_bdflush
848 .long sys_sysfs /* 135 */
849 .long sys_personality
850 .long sys_ni_syscall /* afs_syscall syscall holder */
851 .long sys_ni_syscall /* setfsuid16 syscall holder */
852 .long sys_ni_syscall /* setfsgid16 syscall holder */
853 .long sys_llseek /* 140 */
854 .long sys_getdents
855 .long sys_select
856 .long sys_flock
857 .long sys_msync
858 .long sys_readv /* 145 */
859 .long sys_writev
860 .long sys_getsid
861 .long sys_fdatasync
862 .long sys_sysctl
863 .long sys_mlock /* 150 */
864 .long sys_munlock
865 .long sys_mlockall
866 .long sys_munlockall
867 .long sys_sched_setparam
868 .long sys_sched_getparam /* 155 */
869 .long sys_sched_setscheduler
870 .long sys_sched_getscheduler
871 .long sys_sched_yield
872 .long sys_sched_get_priority_max
873 .long sys_sched_get_priority_min /* 160 */
874 .long sys_sched_rr_get_interval
875 .long sys_nanosleep
876 .long sys_mremap
877 .long sys_ni_syscall /* setresuid16 syscall holder */
878 .long sys_ni_syscall /* 165 - getresuid16 syscall holder */
879 .long sys_tas /* vm86 syscall holder */
880 .long sys_ni_syscall /* query_module syscall holder */
881 .long sys_poll
882 .long sys_nfsservctl
883 .long sys_setresgid /* 170 */
884 .long sys_getresgid
885 .long sys_prctl
886 .long sys_rt_sigreturn
887 .long sys_rt_sigaction
888 .long sys_rt_sigprocmask /* 175 */
889 .long sys_rt_sigpending
890 .long sys_rt_sigtimedwait
891 .long sys_rt_sigqueueinfo
892 .long sys_rt_sigsuspend
893 .long sys_pread64 /* 180 */
894 .long sys_pwrite64
895 .long sys_ni_syscall /* chown16 syscall holder */
896 .long sys_getcwd
897 .long sys_capget
898 .long sys_capset /* 185 */
899 .long sys_sigaltstack
900 .long sys_sendfile
901 .long sys_ni_syscall /* streams1 */
902 .long sys_ni_syscall /* streams2 */
903 .long sys_vfork /* 190 */
904 .long sys_getrlimit
905 .long sys_mmap2
906 .long sys_truncate64
907 .long sys_ftruncate64
908 .long sys_stat64 /* 195 */
909 .long sys_lstat64
910 .long sys_fstat64
911 .long sys_lchown
912 .long sys_getuid
913 .long sys_getgid /* 200 */
914 .long sys_geteuid
915 .long sys_getegid
916 .long sys_setreuid
917 .long sys_setregid
918 .long sys_getgroups /* 205 */
919 .long sys_setgroups
920 .long sys_fchown
921 .long sys_setresuid
922 .long sys_getresuid
923 .long sys_setresgid /* 210 */
924 .long sys_getresgid
925 .long sys_chown
926 .long sys_setuid
927 .long sys_setgid
928 .long sys_setfsuid /* 215 */
929 .long sys_setfsgid
930 .long sys_pivot_root
931 .long sys_mincore
932 .long sys_madvise
933 .long sys_getdents64 /* 220 */
934 .long sys_fcntl64
935 .long sys_ni_syscall /* reserved for TUX */
936 .long sys_ni_syscall /* Reserved for Security */
937 .long sys_gettid
938 .long sys_readahead /* 225 */
939 .long sys_setxattr
940 .long sys_lsetxattr
941 .long sys_fsetxattr
942 .long sys_getxattr
943 .long sys_lgetxattr /* 230 */
944 .long sys_fgetxattr
945 .long sys_listxattr
946 .long sys_llistxattr
947 .long sys_flistxattr
948 .long sys_removexattr /* 235 */
949 .long sys_lremovexattr
950 .long sys_fremovexattr
951 .long sys_tkill
952 .long sys_sendfile64
953 .long sys_futex /* 240 */
954 .long sys_sched_setaffinity
955 .long sys_sched_getaffinity
956 .long sys_ni_syscall /* reserved for "set_thread_area" system call */
957 .long sys_ni_syscall /* reserved for "get_thread_area" system call */
958 .long sys_io_setup /* 245 */
959 .long sys_io_destroy
960 .long sys_io_getevents
961 .long sys_io_submit
962 .long sys_io_cancel
963 .long sys_fadvise64 /* 250 */
964 .long sys_ni_syscall
965 .long sys_exit_group
966 .long sys_lookup_dcookie
967 .long sys_epoll_create
968 .long sys_epoll_ctl /* 255 */
969 .long sys_epoll_wait
970 .long sys_remap_file_pages
971 .long sys_set_tid_address
972 .long sys_timer_create
973 .long sys_timer_settime /* 260 */
974 .long sys_timer_gettime
975 .long sys_timer_getoverrun
976 .long sys_timer_delete
977 .long sys_clock_settime
978 .long sys_clock_gettime /* 265 */
979 .long sys_clock_getres
980 .long sys_clock_nanosleep
981 .long sys_statfs64
982 .long sys_fstatfs64
983 .long sys_tgkill /* 270 */
984 .long sys_utimes
985 .long sys_fadvise64_64
986 .long sys_ni_syscall /* Reserved for sys_vserver */
987 .long sys_ni_syscall /* Reserved for sys_mbind */
988 .long sys_ni_syscall /* Reserved for sys_get_mempolicy */
989 .long sys_ni_syscall /* Reserved for sys_set_mempolicy */
990 .long sys_mq_open
991 .long sys_mq_unlink
992 .long sys_mq_timedsend
993 .long sys_mq_timedreceive /* 280 */
994 .long sys_mq_notify
995 .long sys_mq_getsetattr
996 .long sys_ni_syscall /* reserved for kexec */
997 .long sys_waitid
998
999syscall_table_size=(.-sys_call_table)
1000
diff --git a/arch/m32r/kernel/head.S b/arch/m32r/kernel/head.S
new file mode 100644
index 000000000000..3e83173995cd
--- /dev/null
+++ b/arch/m32r/kernel/head.S
@@ -0,0 +1,287 @@
1/*
2 * linux/arch/m32r/kernel/head.S
3 *
4 * M32R startup code.
5 *
6 * Copyright (c) 2001, 2002 Hiroyuki Kondo, Hirokazu Takata,
7 * Hitoshi Yamamoto
8 */
9
10/* $Id$ */
11
12#include <linux/init.h>
13__INIT
14__INITDATA
15
16 .text
17#include <linux/config.h>
18#include <linux/linkage.h>
19#include <asm/segment.h>
20#include <asm/page.h>
21#include <asm/pgtable.h>
22#include <asm/assembler.h>
23#include <asm/m32r.h>
24#include <asm/mmu_context.h>
25
26/*
27 * References to members of the boot_cpu_data structure.
28 */
29 .text
30 .global start_kernel
31 .global __bss_start
32 .global _end
33ENTRY(stext)
34ENTRY(_stext)
35ENTRY(startup_32)
36 /* Setup up the stack pointer */
37 LDIMM (r0, spi_stack_top)
38 LDIMM (r1, spu_stack_top)
39 mvtc r0, spi
40 mvtc r1, spu
41
42 /* Initilalize PSW */
43 ldi r0, #0x0000 /* use SPI, disable EI */
44 mvtc r0, psw
45
46 /* Set up the stack pointer */
47 LDIMM (r0, stack_start)
48 ld r0, @r0
49 mvtc r0, spi
50
51/*
52 * Clear BSS first so that there are no surprises...
53 */
54#ifdef CONFIG_ISA_DUAL_ISSUE
55
56 LDIMM (r2, __bss_start)
57 LDIMM (r3, _end)
58 sub r3, r2 ; BSS size in bytes
59 ; R4 = BSS size in longwords (rounded down)
60 mv r4, r3 || ldi r1, #0
61 srli r4, #4 || addi r2, #-4
62 beqz r4, .Lendloop1
63.Lloop1:
64#ifndef CONFIG_CHIP_M32310
65 ; Touch memory for the no-write-allocating cache.
66 ld r0, @(4,r2)
67#endif
68 st r1, @+r2 || addi r4, #-1
69 st r1, @+r2
70 st r1, @+r2
71 st r1, @+r2 || cmpeq r1, r4 ; R4 = 0?
72 bnc .Lloop1
73.Lendloop1:
74 and3 r4, r3, #15
75 addi r2, #4
76 beqz r4, .Lendloop2
77.Lloop2:
78 stb r1, @r2 || addi r4, #-1
79 addi r2, #1
80 bnez r4, .Lloop2
81.Lendloop2:
82
83#else /* not CONFIG_ISA_DUAL_ISSUE */
84
85 LDIMM (r2, __bss_start)
86 LDIMM (r3, _end)
87 sub r3, r2 ; BSS size in bytes
88 mv r4, r3
89 srli r4, #2 ; R4 = BSS size in longwords (rounded down)
90 ldi r1, #0 ; clear R1 for longwords store
91 addi r2, #-4 ; account for pre-inc store
92 beqz r4, .Lendloop1 ; any more to go?
93.Lloop1:
94 st r1, @+r2 ; yep, zero out another longword
95 addi r4, #-1 ; decrement count
96 bnez r4, .Lloop1 ; go do some more
97.Lendloop1:
98 and3 r4, r3, #3 ; get no. of remaining BSS bytes to clear
99 addi r2, #4 ; account for pre-inc store
100 beqz r4, .Lendloop2 ; any more to go?
101.Lloop2:
102 stb r1, @r2 ; yep, zero out another byte
103 addi r2, #1 ; bump address
104 addi r4, #-1 ; decrement count
105 bnez r4, .Lloop2 ; go do some more
106.Lendloop2:
107
108#endif /* not CONFIG_ISA_DUAL_ISSUE */
109
110#if 0 /* M32R_FIXME */
111/*
112 * Copy data segment from ROM to RAM.
113 */
114 .global ROM_D, TOP_DATA, END_DATA
115
116 LDIMM (r1, ROM_D)
117 LDIMM (r2, TOP_DATA)
118 LDIMM (r3, END_DATA)
119 addi r2, #-4
120 addi r3, #-4
121loop1:
122 ld r0, @r1+
123 st r0, @+r2
124 cmp r2, r3
125 bc loop1
126#endif /* 0 */
127
128/* Jump to kernel */
129 LDIMM (r2, start_kernel)
130 jl r2
131 .fillinsn
1321:
133 bra 1b ; main should never return here, but
134 ; just in case, we know what happens.
135
136#ifdef CONFIG_SMP
137/*
138 * AP startup routine
139 */
140 .text
141 .global eit_vector
142ENTRY(startup_AP)
143;; setup EVB
144 LDIMM (r4, eit_vector)
145 mvtc r4, cr5
146
147;; enable MMU
148 LDIMM (r2, init_tlb)
149 jl r2
150 seth r4, #high(MATM)
151 or3 r4, r4, #low(MATM)
152 ldi r5, #0x01
153 st r5, @r4 ; Set MATM Reg(T bit ON)
154 ld r6, @r4 ; MATM Check
155 LDIMM (r5, 1f)
156 jmp r5 ; enable MMU
157 nop
158 .fillinsn
1591:
160;; ISN check
161 ld r6, @r4 ; MATM Check
162 seth r4, #high(M32R_ICU_ISTS_ADDR)
163 or3 r4, r4, #low(M32R_ICU_ISTS_ADDR)
164 ld r5, @r4 ; Read ISTSi reg.
165 mv r6, r5
166 slli r5, #13 ; PIML check
167 srli r5, #13 ;
168 seth r4, #high(M32R_ICU_IMASK_ADDR)
169 or3 r4, r4, #low(M32R_ICU_IMASK_ADDR)
170 st r5, @r4 ; Write IMASKi reg.
171 slli r6, #4 ; ISN check
172 srli r6, #26 ;
173 seth r4, #high(M32R_IRQ_IPI5)
174 or3 r4, r4, #low(M32R_IRQ_IPI5)
175 bne r4, r6, 2f ; if (ISN != CPU_BOOT_IPI) goto sleep;
176
177;; check cpu_bootout_map and set cpu_bootin_map
178 LDIMM (r4, cpu_bootout_map)
179 ld r4, @r4
180 seth r5, #high(M32R_CPUID_PORTL)
181 or3 r5, r5, #low(M32R_CPUID_PORTL)
182 ld r5, @r5
183 ldi r6, #1
184 sll r6, r5
185 and r4, r6
186 beqz r4, 2f
187 LDIMM (r4, cpu_bootin_map)
188 ld r5, @r4
189 or r5, r6
190 st r6, @r4
191
192;; clear PSW
193 ldi r4, #0
194 mvtc r4, psw
195
196;; setup SPI
197 LDIMM (r4, stack_start)
198 ld r4, @r4
199 mvtc r4, spi
200
201;; setup BPC (start_secondary)
202 LDIMM (r4, start_secondary)
203 mvtc r4, bpc
204
205 rte ; goto startup_secondary
206 nop
207 nop
208
209 .fillinsn
2102:
211 ;; disable MMU
212 seth r4, #high(MATM)
213 or3 r4, r4, #low(MATM)
214 ldi r5, #0
215 st r5, @r4 ; Set MATM Reg(T bit OFF)
216 ld r6, @r4 ; MATM Check
217 LDIMM (r4, 3f)
218 seth r5, #high(__PAGE_OFFSET)
219 or3 r5, r5, #low(__PAGE_OFFSET)
220 not r5, r5
221 and r4, r5
222 jmp r4 ; disable MMU
223 nop
224 .fillinsn
2253:
226 ;; SLEEP and wait IPI
227 LDIMM (r4, AP_loop)
228 seth r5, #high(__PAGE_OFFSET)
229 or3 r5, r5, #low(__PAGE_OFFSET)
230 not r5, r5
231 and r4, r5
232 jmp r4
233 nop
234 nop
235#endif /* CONFIG_SMP */
236
237ENTRY(stack_start)
238 .long init_thread_union+8192
239 .long __KERNEL_DS
240
241/*
242 * This is initialized to create a identity-mapping at 0-4M (for bootup
243 * purposes) and another mapping of the 0-4M area at virtual address
244 * PAGE_OFFSET.
245 */
246 .text
247
248#define MOUNT_ROOT_RDONLY 1
249#define RAMDISK_FLAGS 0 ; 1024KB
250#define ORIG_ROOT_DEV 0x0100 ; /dev/ram0 (major:01, minor:00)
251#define LOADER_TYPE 1 ; (??? - non-zero value seems
252 ; to be needed to boot from initrd)
253
254#define COMMAND_LINE ""
255
256 .section .empty_zero_page, "aw"
257ENTRY(empty_zero_page)
258 .long MOUNT_ROOT_RDONLY /* offset: +0x00 */
259 .long RAMDISK_FLAGS
260 .long ORIG_ROOT_DEV
261 .long LOADER_TYPE
262 .long 0 /* INITRD_START */ /* +0x10 */
263 .long 0 /* INITRD_SIZE */
264 .long 0 /* CPU_CLOCK */
265 .long 0 /* BUS_CLOCK */
266 .long 0 /* TIMER_DIVIDE */ /* +0x20 */
267 .balign 256,0
268 .asciz COMMAND_LINE
269 .byte 0
270 .balign 4096,0,4096
271
272/*------------------------------------------------------------------------
273 * Stack area
274 */
275 .section .spi
276 ALIGN
277 .global spi_stack_top
278 .zero 1024
279spi_stack_top:
280
281 .section .spu
282 ALIGN
283 .global spu_stack_top
284 .zero 1024
285spu_stack_top:
286
287 .end
diff --git a/arch/m32r/kernel/init_task.c b/arch/m32r/kernel/init_task.c
new file mode 100644
index 000000000000..9e508fd9d970
--- /dev/null
+++ b/arch/m32r/kernel/init_task.c
@@ -0,0 +1,41 @@
1/* orig : i386 init_task.c */
2
3#include <linux/mm.h>
4#include <linux/module.h>
5#include <linux/sched.h>
6#include <linux/init.h>
7#include <linux/init_task.h>
8#include <linux/fs.h>
9#include <linux/mqueue.h>
10
11#include <asm/uaccess.h>
12#include <asm/pgtable.h>
13
14static struct fs_struct init_fs = INIT_FS;
15static struct files_struct init_files = INIT_FILES;
16static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
17static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
18struct mm_struct init_mm = INIT_MM(init_mm);
19
20EXPORT_SYMBOL(init_mm);
21
22/*
23 * Initial thread structure.
24 *
25 * We need to make sure that this is 8192-byte aligned due to the
26 * way process stacks are handled. This is done by having a special
27 * "init_task" linker map entry..
28 */
29union thread_union init_thread_union
30 __attribute__((__section__(".data.init_task"))) =
31 { INIT_THREAD_INFO(init_task) };
32
33/*
34 * Initial task structure.
35 *
36 * All other task structs will be allocated on slabs in fork.c
37 */
38struct task_struct init_task = INIT_TASK(init_task);
39
40EXPORT_SYMBOL(init_task);
41
diff --git a/arch/m32r/kernel/io_m32700ut.c b/arch/m32r/kernel/io_m32700ut.c
new file mode 100644
index 000000000000..371ba904e968
--- /dev/null
+++ b/arch/m32r/kernel/io_m32700ut.c
@@ -0,0 +1,472 @@
1/*
2 * linux/arch/m32r/kernel/io_m32700ut.c
3 *
4 * Typical I/O routines for M32700UT board.
5 *
6 * Copyright (c) 2001, 2002 Hiroyuki Kondo, Hirokazu Takata,
7 * Hitoshi Yamamoto, Takeo Takahashi
8 *
9 * This file is subject to the terms and conditions of the GNU General
10 * Public License. See the file "COPYING" in the main directory of this
11 * archive for more details.
12 */
13
14#include <linux/config.h>
15#include <asm/m32r.h>
16#include <asm/page.h>
17#include <asm/io.h>
18#include <asm/byteorder.h>
19
20#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
21#include <linux/types.h>
22
23#define M32R_PCC_IOMAP_SIZE 0x1000
24
25#define M32R_PCC_IOSTART0 0x1000
26#define M32R_PCC_IOEND0 (M32R_PCC_IOSTART0 + M32R_PCC_IOMAP_SIZE - 1)
27
28extern void pcc_ioread_byte(int, unsigned long, void *, size_t, size_t, int);
29extern void pcc_ioread_word(int, unsigned long, void *, size_t, size_t, int);
30extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int);
31extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
32#endif /* CONFIG_PCMCIA && CONFIG_M32R_CFC */
33
34#define PORT2ADDR(port) _port2addr(port)
35#define PORT2ADDR_USB(port) _port2addr_usb(port)
36
37static inline void *_port2addr(unsigned long port)
38{
39 return (void *)(port + NONCACHE_OFFSET);
40}
41
42#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
43static inline void *__port2addr_ata(unsigned long port)
44{
45 static int dummy_reg;
46
47 switch (port) {
48 case 0x1f0: return (void *)0xac002000;
49 case 0x1f1: return (void *)0xac012800;
50 case 0x1f2: return (void *)0xac012002;
51 case 0x1f3: return (void *)0xac012802;
52 case 0x1f4: return (void *)0xac012004;
53 case 0x1f5: return (void *)0xac012804;
54 case 0x1f6: return (void *)0xac012006;
55 case 0x1f7: return (void *)0xac012806;
56 case 0x3f6: return (void *)0xac01200e;
57 default: return (void *)&dummy_reg;
58 }
59}
60#endif
61
62/*
63 * M32700UT-LAN is located in the extended bus space
64 * from 0x10000000 to 0x13ffffff on physical address.
65 * The base address of LAN controller(LAN91C111) is 0x300.
66 */
67#define LAN_IOSTART 0x300
68#define LAN_IOEND 0x320
69static inline void *_port2addr_ne(unsigned long port)
70{
71 return (void *)(port + NONCACHE_OFFSET + 0x10000000);
72}
73static inline void *_port2addr_usb(unsigned long port)
74{
75 return (void *)((port & 0x0f) + NONCACHE_OFFSET + 0x10303000);
76}
77
78static inline void delay(void)
79{
80 __asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");
81}
82
83/*
84 * NIC I/O function
85 */
86
87#define PORT2ADDR_NE(port) _port2addr_ne(port)
88
89static inline unsigned char _ne_inb(void *portp)
90{
91 return *(volatile unsigned char *)portp;
92}
93
94static inline unsigned short _ne_inw(void *portp)
95{
96 return (unsigned short)le16_to_cpu(*(volatile unsigned short *)portp);
97}
98
99static inline void _ne_insb(void *portp, void *addr, unsigned long count)
100{
101 unsigned char *buf = (unsigned char *)addr;
102
103 while (count--)
104 *buf++ = _ne_inb(portp);
105}
106
107static inline void _ne_outb(unsigned char b, void *portp)
108{
109 *(volatile unsigned char *)portp = b;
110}
111
112static inline void _ne_outw(unsigned short w, void *portp)
113{
114 *(volatile unsigned short *)portp = cpu_to_le16(w);
115}
116
117unsigned char _inb(unsigned long port)
118{
119 if (port >= LAN_IOSTART && port < LAN_IOEND)
120 return _ne_inb(PORT2ADDR_NE(port));
121
122#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
123 else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
124 return *(volatile unsigned char *)__port2addr_ata(port);
125 }
126#endif
127#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
128 else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
129 unsigned char b;
130 pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
131 return b;
132 } else
133#endif
134
135 return *(volatile unsigned char *)PORT2ADDR(port);
136}
137
138unsigned short _inw(unsigned long port)
139{
140 if (port >= LAN_IOSTART && port < LAN_IOEND)
141 return _ne_inw(PORT2ADDR_NE(port));
142#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
143 else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
144 return *(volatile unsigned short *)__port2addr_ata(port);
145 }
146#endif
147#if defined(CONFIG_USB)
148 else if(port >= 0x340 && port < 0x3a0)
149 return *(volatile unsigned short *)PORT2ADDR_USB(port);
150#endif
151#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
152 else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
153 unsigned short w;
154 pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
155 return w;
156 } else
157#endif
158 return *(volatile unsigned short *)PORT2ADDR(port);
159}
160
161unsigned long _inl(unsigned long port)
162{
163#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
164 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
165 unsigned long l;
166 pcc_ioread_word(0, port, &l, sizeof(l), 1, 0);
167 return l;
168 } else
169#endif
170 return *(volatile unsigned long *)PORT2ADDR(port);
171}
172
173unsigned char _inb_p(unsigned long port)
174{
175 unsigned char v;
176
177 if (port >= LAN_IOSTART && port < LAN_IOEND)
178 v = _ne_inb(PORT2ADDR_NE(port));
179 else
180#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
181 if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
182 return *(volatile unsigned char *)__port2addr_ata(port);
183 } else
184#endif
185#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
186 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
187 unsigned char b;
188 pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
189 return b;
190 } else
191#endif
192 v = *(volatile unsigned char *)PORT2ADDR(port);
193
194 delay();
195 return (v);
196}
197
198unsigned short _inw_p(unsigned long port)
199{
200 unsigned short v;
201
202 if (port >= LAN_IOSTART && port < LAN_IOEND)
203 v = _ne_inw(PORT2ADDR_NE(port));
204 else
205#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
206 if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
207 return *(volatile unsigned short *)__port2addr_ata(port);
208 } else
209#endif
210#if defined(CONFIG_USB)
211 if(port >= 0x340 && port < 0x3a0)
212 return *(volatile unsigned short *)PORT2ADDR_USB(port);
213 else
214#endif
215#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
216 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
217 unsigned short w;
218 pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
219 return w;
220 } else
221#endif
222 v = *(volatile unsigned short *)PORT2ADDR(port);
223
224 delay();
225 return (v);
226}
227
228unsigned long _inl_p(unsigned long port)
229{
230 unsigned long v;
231
232 v = *(volatile unsigned long *)PORT2ADDR(port);
233 delay();
234 return (v);
235}
236
237void _outb(unsigned char b, unsigned long port)
238{
239 if (port >= LAN_IOSTART && port < LAN_IOEND)
240 _ne_outb(b, PORT2ADDR_NE(port));
241 else
242#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
243 if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
244 *(volatile unsigned char *)__port2addr_ata(port) = b;
245 } else
246#endif
247#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
248 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
249 pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
250 } else
251#endif
252 *(volatile unsigned char *)PORT2ADDR(port) = b;
253}
254
255void _outw(unsigned short w, unsigned long port)
256{
257 if (port >= LAN_IOSTART && port < LAN_IOEND)
258 _ne_outw(w, PORT2ADDR_NE(port));
259 else
260#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
261 if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
262 *(volatile unsigned short *)__port2addr_ata(port) = w;
263 } else
264#endif
265#if defined(CONFIG_USB)
266 if(port >= 0x340 && port < 0x3a0)
267 *(volatile unsigned short *)PORT2ADDR_USB(port) = w;
268 else
269#endif
270#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
271 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
272 pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
273 } else
274#endif
275 *(volatile unsigned short *)PORT2ADDR(port) = w;
276}
277
278void _outl(unsigned long l, unsigned long port)
279{
280#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
281 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
282 pcc_iowrite_word(0, port, &l, sizeof(l), 1, 0);
283 } else
284#endif
285 *(volatile unsigned long *)PORT2ADDR(port) = l;
286}
287
288void _outb_p(unsigned char b, unsigned long port)
289{
290 if (port >= LAN_IOSTART && port < LAN_IOEND)
291 _ne_outb(b, PORT2ADDR_NE(port));
292 else
293#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
294 if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
295 *(volatile unsigned char *)__port2addr_ata(port) = b;
296 } else
297#endif
298#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
299 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
300 pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
301 } else
302#endif
303 *(volatile unsigned char *)PORT2ADDR(port) = b;
304
305 delay();
306}
307
308void _outw_p(unsigned short w, unsigned long port)
309{
310 if (port >= LAN_IOSTART && port < LAN_IOEND)
311 _ne_outw(w, PORT2ADDR_NE(port));
312 else
313#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
314 if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
315 *(volatile unsigned short *)__port2addr_ata(port) = w;
316 } else
317#endif
318#if defined(CONFIG_USB)
319 if(port >= 0x340 && port < 0x3a0)
320 *(volatile unsigned short *)PORT2ADDR_USB(port) = w;
321 else
322#endif
323#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
324 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
325 pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
326 } else
327#endif
328 *(volatile unsigned short *)PORT2ADDR(port) = w;
329
330 delay();
331}
332
333void _outl_p(unsigned long l, unsigned long port)
334{
335 *(volatile unsigned long *)PORT2ADDR(port) = l;
336 delay();
337}
338
339void _insb(unsigned int port, void *addr, unsigned long count)
340{
341 if (port >= LAN_IOSTART && port < LAN_IOEND)
342 _ne_insb(PORT2ADDR_NE(port), addr, count);
343#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
344 else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
345 unsigned char *buf = addr;
346 unsigned char *portp = __port2addr_ata(port);
347 while (count--)
348 *buf++ = *(volatile unsigned char *)portp;
349 }
350#endif
351#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
352 else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
353 pcc_ioread_byte(0, port, (void *)addr, sizeof(unsigned char),
354 count, 1);
355 }
356#endif
357 else {
358 unsigned char *buf = addr;
359 unsigned char *portp = PORT2ADDR(port);
360 while (count--)
361 *buf++ = *(volatile unsigned char *)portp;
362 }
363}
364
365void _insw(unsigned int port, void *addr, unsigned long count)
366{
367 unsigned short *buf = addr;
368 unsigned short *portp;
369
370 if (port >= LAN_IOSTART && port < LAN_IOEND) {
371 /*
372 * This portion is only used by smc91111.c to read data
373 * from the DATA_REG. Do not swap the data.
374 */
375 portp = PORT2ADDR_NE(port);
376 while (count--)
377 *buf++ = *(volatile unsigned short *)portp;
378#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
379 } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
380 pcc_ioread_word(9, port, (void *)addr, sizeof(unsigned short),
381 count, 1);
382#endif
383#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
384 } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
385 portp = __port2addr_ata(port);
386 while (count--)
387 *buf++ = *(volatile unsigned short *)portp;
388#endif
389 } else {
390 portp = PORT2ADDR(port);
391 while (count--)
392 *buf++ = *(volatile unsigned short *)portp;
393 }
394}
395
396void _insl(unsigned int port, void *addr, unsigned long count)
397{
398 unsigned long *buf = addr;
399 unsigned long *portp;
400
401 portp = PORT2ADDR(port);
402 while (count--)
403 *buf++ = *(volatile unsigned long *)portp;
404}
405
406void _outsb(unsigned int port, const void *addr, unsigned long count)
407{
408 const unsigned char *buf = addr;
409 unsigned char *portp;
410
411 if (port >= LAN_IOSTART && port < LAN_IOEND) {
412 portp = PORT2ADDR_NE(port);
413 while (count--)
414 _ne_outb(*buf++, portp);
415#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
416 } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
417 portp = __port2addr_ata(port);
418 while (count--)
419 *(volatile unsigned char *)portp = *buf++;
420#endif
421#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
422 } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
423 pcc_iowrite_byte(0, port, (void *)addr, sizeof(unsigned char),
424 count, 1);
425#endif
426 } else {
427 portp = PORT2ADDR(port);
428 while (count--)
429 *(volatile unsigned char *)portp = *buf++;
430 }
431}
432
433void _outsw(unsigned int port, const void *addr, unsigned long count)
434{
435 const unsigned short *buf = addr;
436 unsigned short *portp;
437
438 if (port >= LAN_IOSTART && port < LAN_IOEND) {
439 /*
440 * This portion is only used by smc91111.c to write data
441 * into the DATA_REG. Do not swap the data.
442 */
443 portp = PORT2ADDR_NE(port);
444 while (count--)
445 *(volatile unsigned short *)portp = *buf++;
446#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
447 } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
448 portp = __port2addr_ata(port);
449 while (count--)
450 *(volatile unsigned short *)portp = *buf++;
451#endif
452#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
453 } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
454 pcc_iowrite_word(9, port, (void *)addr, sizeof(unsigned short),
455 count, 1);
456#endif
457 } else {
458 portp = PORT2ADDR(port);
459 while (count--)
460 *(volatile unsigned short *)portp = *buf++;
461 }
462}
463
464void _outsl(unsigned int port, const void *addr, unsigned long count)
465{
466 const unsigned long *buf = addr;
467 unsigned char *portp;
468
469 portp = PORT2ADDR(port);
470 while (count--)
471 *(volatile unsigned long *)portp = *buf++;
472}
diff --git a/arch/m32r/kernel/io_mappi.c b/arch/m32r/kernel/io_mappi.c
new file mode 100644
index 000000000000..85688ffb52f9
--- /dev/null
+++ b/arch/m32r/kernel/io_mappi.c
@@ -0,0 +1,384 @@
1/*
2 * linux/arch/m32r/kernel/io_mappi.c
3 *
4 * Typical I/O routines for Mappi board.
5 *
6 * Copyright (c) 2001, 2002 Hiroyuki Kondo, Hirokazu Takata,
7 * Hitoshi Yamamoto
8 */
9
10#include <linux/config.h>
11#include <asm/m32r.h>
12#include <asm/page.h>
13#include <asm/io.h>
14#include <asm/byteorder.h>
15
16#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
17#include <linux/types.h>
18
19#define M32R_PCC_IOMAP_SIZE 0x1000
20
21#define M32R_PCC_IOSTART0 0x1000
22#define M32R_PCC_IOEND0 (M32R_PCC_IOSTART0 + M32R_PCC_IOMAP_SIZE - 1)
23#define M32R_PCC_IOSTART1 0x2000
24#define M32R_PCC_IOEND1 (M32R_PCC_IOSTART1 + M32R_PCC_IOMAP_SIZE - 1)
25
26extern void pcc_ioread(int, unsigned long, void *, size_t, size_t, int);
27extern void pcc_iowrite(int, unsigned long, void *, size_t, size_t, int);
28#endif /* CONFIG_PCMCIA && CONFIG_M32R_PCC */
29
30#define PORT2ADDR(port) _port2addr(port)
31
32static inline void *_port2addr(unsigned long port)
33{
34 return (void *)(port + NONCACHE_OFFSET);
35}
36
37static inline void *_port2addr_ne(unsigned long port)
38{
39 return (void *)((port<<1) + NONCACHE_OFFSET + 0x0C000000);
40}
41
42static inline void delay(void)
43{
44 __asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");
45}
46
47/*
48 * NIC I/O function
49 */
50
51#define PORT2ADDR_NE(port) _port2addr_ne(port)
52
53static inline unsigned char _ne_inb(void *portp)
54{
55 return (unsigned char) *(volatile unsigned short *)portp;
56}
57
58static inline unsigned short _ne_inw(void *portp)
59{
60 unsigned short tmp;
61
62 tmp = *(volatile unsigned short *)portp;
63 return le16_to_cpu(tmp);
64}
65
66static inline void _ne_outb(unsigned char b, void *portp)
67{
68 *(volatile unsigned short *)portp = (unsigned short)b;
69}
70
71static inline void _ne_outw(unsigned short w, void *portp)
72{
73 *(volatile unsigned short *)portp = cpu_to_le16(w);
74}
75
76unsigned char _inb(unsigned long port)
77{
78 if (port >= 0x300 && port < 0x320)
79 return _ne_inb(PORT2ADDR_NE(port));
80 else
81#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
82 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
83 unsigned char b;
84 pcc_ioread(0, port, &b, sizeof(b), 1, 0);
85 return b;
86 } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
87 unsigned char b;
88 pcc_ioread(1, port, &b, sizeof(b), 1, 0);
89 return b;
90 } else
91#endif
92
93 return *(volatile unsigned char *)PORT2ADDR(port);
94}
95
96unsigned short _inw(unsigned long port)
97{
98 if (port >= 0x300 && port < 0x320)
99 return _ne_inw(PORT2ADDR_NE(port));
100 else
101#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
102 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
103 unsigned short w;
104 pcc_ioread(0, port, &w, sizeof(w), 1, 0);
105 return w;
106 } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
107 unsigned short w;
108 pcc_ioread(1, port, &w, sizeof(w), 1, 0);
109 return w;
110 } else
111#endif
112 return *(volatile unsigned short *)PORT2ADDR(port);
113}
114
115unsigned long _inl(unsigned long port)
116{
117#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
118 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
119 unsigned long l;
120 pcc_ioread(0, port, &l, sizeof(l), 1, 0);
121 return l;
122 } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
123 unsigned short l;
124 pcc_ioread(1, port, &l, sizeof(l), 1, 0);
125 return l;
126 } else
127#endif
128 return *(volatile unsigned long *)PORT2ADDR(port);
129}
130
131unsigned char _inb_p(unsigned long port)
132{
133 unsigned char v;
134
135 if (port >= 0x300 && port < 0x320)
136 v = _ne_inb(PORT2ADDR_NE(port));
137 else
138#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
139 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
140 unsigned char b;
141 pcc_ioread(0, port, &b, sizeof(b), 1, 0);
142 return b;
143 } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
144 unsigned char b;
145 pcc_ioread(1, port, &b, sizeof(b), 1, 0);
146 return b;
147 } else
148#endif
149 v = *(volatile unsigned char *)PORT2ADDR(port);
150
151 delay();
152 return (v);
153}
154
155unsigned short _inw_p(unsigned long port)
156{
157 unsigned short v;
158
159 if (port >= 0x300 && port < 0x320)
160 v = _ne_inw(PORT2ADDR_NE(port));
161 else
162#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
163 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
164 unsigned short w;
165 pcc_ioread(0, port, &w, sizeof(w), 1, 0);
166 return w;
167 } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
168 unsigned short w;
169 pcc_ioread(1, port, &w, sizeof(w), 1, 0);
170 return w;
171 } else
172#endif
173 v = *(volatile unsigned short *)PORT2ADDR(port);
174
175 delay();
176 return (v);
177}
178
179unsigned long _inl_p(unsigned long port)
180{
181 unsigned long v;
182
183 v = *(volatile unsigned long *)PORT2ADDR(port);
184 delay();
185 return (v);
186}
187
188void _outb(unsigned char b, unsigned long port)
189{
190 if (port >= 0x300 && port < 0x320)
191 _ne_outb(b, PORT2ADDR_NE(port));
192 else
193#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
194 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
195 pcc_iowrite(0, port, &b, sizeof(b), 1, 0);
196 } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
197 pcc_iowrite(1, port, &b, sizeof(b), 1, 0);
198 } else
199#endif
200 *(volatile unsigned char *)PORT2ADDR(port) = b;
201}
202
203void _outw(unsigned short w, unsigned long port)
204{
205 if (port >= 0x300 && port < 0x320)
206 _ne_outw(w, PORT2ADDR_NE(port));
207 else
208#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
209 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
210 pcc_iowrite(0, port, &w, sizeof(w), 1, 0);
211 } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
212 pcc_iowrite(1, port, &w, sizeof(w), 1, 0);
213 } else
214#endif
215 *(volatile unsigned short *)PORT2ADDR(port) = w;
216}
217
218void _outl(unsigned long l, unsigned long port)
219{
220#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
221 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
222 pcc_iowrite(0, port, &l, sizeof(l), 1, 0);
223 } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
224 pcc_iowrite(1, port, &l, sizeof(l), 1, 0);
225 } else
226#endif
227 *(volatile unsigned long *)PORT2ADDR(port) = l;
228}
229
230void _outb_p(unsigned char b, unsigned long port)
231{
232 if (port >= 0x300 && port < 0x320)
233 _ne_outb(b, PORT2ADDR_NE(port));
234 else
235#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
236 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
237 pcc_iowrite(0, port, &b, sizeof(b), 1, 0);
238 } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
239 pcc_iowrite(1, port, &b, sizeof(b), 1, 0);
240 } else
241#endif
242 *(volatile unsigned char *)PORT2ADDR(port) = b;
243
244 delay();
245}
246
247void _outw_p(unsigned short w, unsigned long port)
248{
249 if (port >= 0x300 && port < 0x320)
250 _ne_outw(w, PORT2ADDR_NE(port));
251 else
252#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
253 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
254 pcc_iowrite(0, port, &w, sizeof(w), 1, 0);
255 } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
256 pcc_iowrite(1, port, &w, sizeof(w), 1, 0);
257 } else
258#endif
259 *(volatile unsigned short *)PORT2ADDR(port) = w;
260
261 delay();
262}
263
264void _outl_p(unsigned long l, unsigned long port)
265{
266 *(volatile unsigned long *)PORT2ADDR(port) = l;
267 delay();
268}
269
270void _insb(unsigned int port, void *addr, unsigned long count)
271{
272 unsigned short *buf = addr;
273 unsigned short *portp;
274
275 if (port >= 0x300 && port < 0x320){
276 portp = PORT2ADDR_NE(port);
277 while (count--)
278 *buf++ = *(volatile unsigned char *)portp;
279#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
280 } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
281 pcc_ioread(0, port, (void *)addr, sizeof(unsigned char),
282 count, 1);
283 } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
284 pcc_ioread(1, port, (void *)addr, sizeof(unsigned char),
285 count, 1);
286#endif
287 } else {
288 portp = PORT2ADDR(port);
289 while (count--)
290 *buf++ = *(volatile unsigned char *)portp;
291 }
292}
293
294void _insw(unsigned int port, void *addr, unsigned long count)
295{
296 unsigned short *buf = addr;
297 unsigned short *portp;
298
299 if (port >= 0x300 && port < 0x320) {
300 portp = PORT2ADDR_NE(port);
301 while (count--)
302 *buf++ = _ne_inw(portp);
303#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
304 } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
305 pcc_ioread(0, port, (void *)addr, sizeof(unsigned short),
306 count, 1);
307 } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
308 pcc_ioread(1, port, (void *)addr, sizeof(unsigned short),
309 count, 1);
310#endif
311 } else {
312 portp = PORT2ADDR(port);
313 while (count--)
314 *buf++ = *(volatile unsigned short *)portp;
315 }
316}
317
318void _insl(unsigned int port, void *addr, unsigned long count)
319{
320 unsigned long *buf = addr;
321 unsigned long *portp;
322
323 portp = PORT2ADDR(port);
324 while (count--)
325 *buf++ = *(volatile unsigned long *)portp;
326}
327
328void _outsb(unsigned int port, const void *addr, unsigned long count)
329{
330 const unsigned char *buf = addr;
331 unsigned char *portp;
332
333 if (port >= 0x300 && port < 0x320) {
334 portp = PORT2ADDR_NE(port);
335 while (count--)
336 _ne_outb(*buf++, portp);
337#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
338 } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
339 pcc_iowrite(0, port, (void *)addr, sizeof(unsigned char),
340 count, 1);
341 } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
342 pcc_iowrite(1, port, (void *)addr, sizeof(unsigned char),
343 count, 1);
344#endif
345 } else {
346 portp = PORT2ADDR(port);
347 while (count--)
348 *(volatile unsigned char *)portp = *buf++;
349 }
350}
351
352void _outsw(unsigned int port, const void *addr, unsigned long count)
353{
354 const unsigned short *buf = addr;
355 unsigned short *portp;
356
357 if (port >= 0x300 && port < 0x320) {
358 portp = PORT2ADDR_NE(port);
359 while (count--)
360 _ne_outw(*buf++, portp);
361#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
362 } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
363 pcc_iowrite(0, port, (void *)addr, sizeof(unsigned short),
364 count, 1);
365 } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
366 pcc_iowrite(1, port, (void *)addr, sizeof(unsigned short),
367 count, 1);
368#endif
369 } else {
370 portp = PORT2ADDR(port);
371 while (count--)
372 *(volatile unsigned short *)portp = *buf++;
373 }
374}
375
376void _outsl(unsigned int port, const void *addr, unsigned long count)
377{
378 const unsigned long *buf = addr;
379 unsigned char *portp;
380
381 portp = PORT2ADDR(port);
382 while (count--)
383 *(volatile unsigned long *)portp = *buf++;
384}
diff --git a/arch/m32r/kernel/io_mappi2.c b/arch/m32r/kernel/io_mappi2.c
new file mode 100644
index 000000000000..4182cd4f97c8
--- /dev/null
+++ b/arch/m32r/kernel/io_mappi2.c
@@ -0,0 +1,461 @@
1/*
2 * linux/arch/m32r/kernel/io_mappi2.c
3 *
4 * Typical I/O routines for Mappi2 board.
5 *
6 * Copyright (c) 2001-2003 Hiroyuki Kondo, Hirokazu Takata,
7 * Hitoshi Yamamoto, Mamoru Sakugawa
8 */
9
10#include <linux/config.h>
11#include <asm/m32r.h>
12#include <asm/page.h>
13#include <asm/io.h>
14#include <asm/byteorder.h>
15
16#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
17#include <linux/types.h>
18
19#define M32R_PCC_IOMAP_SIZE 0x1000
20
21#define M32R_PCC_IOSTART0 0x1000
22#define M32R_PCC_IOEND0 (M32R_PCC_IOSTART0 + M32R_PCC_IOMAP_SIZE - 1)
23
24extern void pcc_ioread_byte(int, unsigned long, void *, size_t, size_t, int);
25extern void pcc_ioread_word(int, unsigned long, void *, size_t, size_t, int);
26extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int);
27extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
28#endif /* CONFIG_PCMCIA && CONFIG_MAPPI2_CFC */
29
30#define PORT2ADDR(port) _port2addr(port)
31#define PORT2ADDR_NE(port) _port2addr_ne(port)
32#define PORT2ADDR_USB(port) _port2addr_usb(port)
33
34static inline void *_port2addr(unsigned long port)
35{
36 return (void *)(port + NONCACHE_OFFSET);
37}
38
39#define LAN_IOSTART 0x300
40#define LAN_IOEND 0x320
41
42#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
43static inline void *__port2addr_ata(unsigned long port)
44{
45 static int dummy_reg;
46
47 switch (port) {
48 case 0x1f0: return (void *)0xac002000;
49 case 0x1f1: return (void *)0xac012800;
50 case 0x1f2: return (void *)0xac012002;
51 case 0x1f3: return (void *)0xac012802;
52 case 0x1f4: return (void *)0xac012004;
53 case 0x1f5: return (void *)0xac012804;
54 case 0x1f6: return (void *)0xac012006;
55 case 0x1f7: return (void *)0xac012806;
56 case 0x3f6: return (void *)0xac01200e;
57 default: return (void *)&dummy_reg;
58 }
59}
60#endif
61
62#ifdef CONFIG_CHIP_OPSP
63static inline void *_port2addr_ne(unsigned long port)
64{
65 return (void *)(port + NONCACHE_OFFSET + 0x10000000);
66}
67#else
68static inline void *_port2addr_ne(unsigned long port)
69{
70 return (void *)(port + NONCACHE_OFFSET + 0x04000000);
71}
72#endif
73static inline void *_port2addr_usb(unsigned long port)
74{
75 return (void *)(port + NONCACHE_OFFSET + 0x14000000);
76}
77static inline void delay(void)
78{
79 __asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");
80}
81
82/*
83 * NIC I/O function
84 */
85
86static inline unsigned char _ne_inb(void *portp)
87{
88 return (unsigned char) *(volatile unsigned char *)portp;
89}
90
91static inline unsigned short _ne_inw(void *portp)
92{
93 return (unsigned short)le16_to_cpu(*(volatile unsigned short *)portp);
94}
95
96static inline void _ne_insb(void *portp, void * addr, unsigned long count)
97{
98 unsigned char *buf = addr;
99
100 while (count--)
101 *buf++ = *(volatile unsigned char *)portp;
102}
103
104static inline void _ne_outb(unsigned char b, void *portp)
105{
106 *(volatile unsigned char *)portp = (unsigned char)b;
107}
108
109static inline void _ne_outw(unsigned short w, void *portp)
110{
111 *(volatile unsigned short *)portp = cpu_to_le16(w);
112}
113
114unsigned char _inb(unsigned long port)
115{
116 if (port >= LAN_IOSTART && port < LAN_IOEND)
117 return _ne_inb(PORT2ADDR_NE(port));
118#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
119 else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
120 return *(volatile unsigned char *)__port2addr_ata(port);
121 }
122#endif
123#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
124 else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
125 unsigned char b;
126 pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
127 return b;
128 } else
129#endif
130
131 return *(volatile unsigned char *)PORT2ADDR(port);
132}
133
134unsigned short _inw(unsigned long port)
135{
136 if (port >= LAN_IOSTART && port < LAN_IOEND)
137 return _ne_inw(PORT2ADDR_NE(port));
138#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
139 else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
140 return *(volatile unsigned short *)__port2addr_ata(port);
141 }
142#endif
143#if defined(CONFIG_USB)
144 else if (port >= 0x340 && port < 0x3a0)
145 return *(volatile unsigned short *)PORT2ADDR_USB(port);
146#endif
147
148#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
149 else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
150 unsigned short w;
151 pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
152 return w;
153 } else
154#endif
155 return *(volatile unsigned short *)PORT2ADDR(port);
156}
157
158unsigned long _inl(unsigned long port)
159{
160#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
161 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
162 unsigned long l;
163 pcc_ioread_word(0, port, &l, sizeof(l), 1, 0);
164 return l;
165 } else
166#endif
167 return *(volatile unsigned long *)PORT2ADDR(port);
168}
169
170unsigned char _inb_p(unsigned long port)
171{
172 unsigned char v;
173
174 if (port >= LAN_IOSTART && port < LAN_IOEND)
175 v = _ne_inb(PORT2ADDR_NE(port));
176 else
177#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
178 if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
179 return *(volatile unsigned char *)__port2addr_ata(port);
180 } else
181#endif
182#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
183 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
184 unsigned char b;
185 pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
186 return b;
187 } else
188#endif
189 v = *(volatile unsigned char *)PORT2ADDR(port);
190
191 delay();
192 return (v);
193}
194
195unsigned short _inw_p(unsigned long port)
196{
197 unsigned short v;
198
199 if (port >= LAN_IOSTART && port < LAN_IOEND)
200 v = _ne_inw(PORT2ADDR_NE(port));
201 else
202#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
203 if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
204 return *(volatile unsigned short *)__port2addr_ata(port);
205 } else
206#endif
207#if defined(CONFIG_USB)
208 if (port >= 0x340 && port < 0x3a0)
209 v = *(volatile unsigned short *)PORT2ADDR_USB(port);
210 else
211#endif
212#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
213 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
214 unsigned short w;
215 pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
216 return w;
217 } else
218#endif
219 v = *(volatile unsigned short *)PORT2ADDR(port);
220
221 delay();
222 return (v);
223}
224
225unsigned long _inl_p(unsigned long port)
226{
227 unsigned long v;
228
229 v = *(volatile unsigned long *)PORT2ADDR(port);
230 delay();
231 return (v);
232}
233
234void _outb(unsigned char b, unsigned long port)
235{
236 if (port >= LAN_IOSTART && port < LAN_IOEND)
237 _ne_outb(b, PORT2ADDR_NE(port));
238 else
239#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
240 if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
241 *(volatile unsigned char *)__port2addr_ata(port) = b;
242 } else
243#endif
244#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
245 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
246 pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
247 } else
248#endif
249 *(volatile unsigned char *)PORT2ADDR(port) = b;
250}
251
252void _outw(unsigned short w, unsigned long port)
253{
254 if (port >= LAN_IOSTART && port < LAN_IOEND)
255 _ne_outw(w, PORT2ADDR_NE(port));
256 else
257#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
258 if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
259 *(volatile unsigned short *)__port2addr_ata(port) = w;
260 } else
261#endif
262#if defined(CONFIG_USB)
263 if (port >= 0x340 && port < 0x3a0)
264 *(volatile unsigned short *)PORT2ADDR_USB(port) = w;
265 else
266#endif
267#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
268 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
269 pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
270 } else
271#endif
272 *(volatile unsigned short *)PORT2ADDR(port) = w;
273}
274
275void _outl(unsigned long l, unsigned long port)
276{
277#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
278 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
279 pcc_iowrite_word(0, port, &l, sizeof(l), 1, 0);
280 } else
281#endif
282 *(volatile unsigned long *)PORT2ADDR(port) = l;
283}
284
285void _outb_p(unsigned char b, unsigned long port)
286{
287 if (port >= LAN_IOSTART && port < LAN_IOEND)
288 _ne_outb(b, PORT2ADDR_NE(port));
289 else
290#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
291 if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
292 *(volatile unsigned char *)__port2addr_ata(port) = b;
293 } else
294#endif
295#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
296 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
297 pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
298 } else
299#endif
300 *(volatile unsigned char *)PORT2ADDR(port) = b;
301
302 delay();
303}
304
305void _outw_p(unsigned short w, unsigned long port)
306{
307 if (port >= LAN_IOSTART && port < LAN_IOEND)
308 _ne_outw(w, PORT2ADDR_NE(port));
309 else
310#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
311 if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
312 *(volatile unsigned short *)__port2addr_ata(port) = w;
313 } else
314#endif
315#if defined(CONFIG_USB)
316 if (port >= 0x340 && port < 0x3a0)
317 *(volatile unsigned short *)PORT2ADDR_USB(port) = w;
318 else
319#endif
320#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
321 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
322 pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
323 } else
324#endif
325 *(volatile unsigned short *)PORT2ADDR(port) = w;
326
327 delay();
328}
329
330void _outl_p(unsigned long l, unsigned long port)
331{
332 *(volatile unsigned long *)PORT2ADDR(port) = l;
333 delay();
334}
335
336void _insb(unsigned int port, void * addr, unsigned long count)
337{
338 if (port >= LAN_IOSTART && port < LAN_IOEND)
339 _ne_insb(PORT2ADDR_NE(port), addr, count);
340#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
341 else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
342 unsigned char *buf = addr;
343 unsigned char *portp = __port2addr_ata(port);
344 while (count--)
345 *buf++ = *(volatile unsigned char *)portp;
346 }
347#endif
348#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
349 else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
350 pcc_ioread_byte(0, port, (void *)addr, sizeof(unsigned char),
351 count, 1);
352 }
353#endif
354 else {
355 unsigned char *buf = addr;
356 unsigned char *portp = PORT2ADDR(port);
357 while (count--)
358 *buf++ = *(volatile unsigned char *)portp;
359 }
360}
361
362void _insw(unsigned int port, void * addr, unsigned long count)
363{
364 unsigned short *buf = addr;
365 unsigned short *portp;
366
367 if (port >= LAN_IOSTART && port < LAN_IOEND) {
368 portp = PORT2ADDR_NE(port);
369 while (count--)
370 *buf++ = *(volatile unsigned short *)portp;
371#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
372 } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
373 pcc_ioread_word(9, port, (void *)addr, sizeof(unsigned short),
374 count, 1);
375#endif
376#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
377 } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
378 portp = __port2addr_ata(port);
379 while (count--)
380 *buf++ = *(volatile unsigned short *)portp;
381#endif
382 } else {
383 portp = PORT2ADDR(port);
384 while (count--)
385 *buf++ = *(volatile unsigned short *)portp;
386 }
387}
388
389void _insl(unsigned int port, void * addr, unsigned long count)
390{
391 unsigned long *buf = addr;
392 unsigned long *portp;
393
394 portp = PORT2ADDR(port);
395 while (count--)
396 *buf++ = *(volatile unsigned long *)portp;
397}
398
399void _outsb(unsigned int port, const void * addr, unsigned long count)
400{
401 const unsigned char *buf = addr;
402 unsigned char *portp;
403
404 if (port >= LAN_IOSTART && port < LAN_IOEND) {
405 portp = PORT2ADDR_NE(port);
406 while (count--)
407 _ne_outb(*buf++, portp);
408#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
409 } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
410 portp = __port2addr_ata(port);
411 while (count--)
412 *(volatile unsigned char *)portp = *buf++;
413#endif
414#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
415 } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
416 pcc_iowrite_byte(0, port, (void *)addr, sizeof(unsigned char),
417 count, 1);
418#endif
419 } else {
420 portp = PORT2ADDR(port);
421 while (count--)
422 *(volatile unsigned char *)portp = *buf++;
423 }
424}
425
426void _outsw(unsigned int port, const void * addr, unsigned long count)
427{
428 const unsigned short *buf = addr;
429 unsigned short *portp;
430
431 if (port >= LAN_IOSTART && port < LAN_IOEND) {
432 portp = PORT2ADDR_NE(port);
433 while (count--)
434 *(volatile unsigned short *)portp = *buf++;
435#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
436 } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
437 portp = __port2addr_ata(port);
438 while (count--)
439 *(volatile unsigned short *)portp = *buf++;
440#endif
441#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
442 } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
443 pcc_iowrite_word(9, port, (void *)addr, sizeof(unsigned short),
444 count, 1);
445#endif
446 } else {
447 portp = PORT2ADDR(port);
448 while (count--)
449 *(volatile unsigned short *)portp = *buf++;
450 }
451}
452
453void _outsl(unsigned int port, const void * addr, unsigned long count)
454{
455 const unsigned long *buf = addr;
456 unsigned char *portp;
457
458 portp = PORT2ADDR(port);
459 while (count--)
460 *(volatile unsigned long *)portp = *buf++;
461}
diff --git a/arch/m32r/kernel/io_oaks32r.c b/arch/m32r/kernel/io_oaks32r.c
new file mode 100644
index 000000000000..286964794d51
--- /dev/null
+++ b/arch/m32r/kernel/io_oaks32r.c
@@ -0,0 +1,251 @@
1/*
2 * linux/arch/m32r/kernel/io_oaks32r.c
3 *
4 * Typical I/O routines for OAKS32R board.
5 *
6 * Copyright (c) 2001-2004 Hiroyuki Kondo, Hirokazu Takata,
7 * Hitoshi Yamamoto, Mamoru Sakugawa
8 */
9
10#include <linux/config.h>
11#include <asm/m32r.h>
12#include <asm/page.h>
13#include <asm/io.h>
14
15#define PORT2ADDR(port) _port2addr(port)
16
17static inline void *_port2addr(unsigned long port)
18{
19 return (void *)(port + NONCACHE_OFFSET);
20}
21
22static inline void *_port2addr_ne(unsigned long port)
23{
24 return (void *)((port<<1) + NONCACHE_OFFSET + 0x02000000);
25}
26
27static inline void delay(void)
28{
29 __asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");
30}
31
32/*
33 * NIC I/O function
34 */
35
36#define PORT2ADDR_NE(port) _port2addr_ne(port)
37
38static inline unsigned char _ne_inb(void *portp)
39{
40 return *(volatile unsigned char *)(portp+1);
41}
42
43static inline unsigned short _ne_inw(void *portp)
44{
45 unsigned short tmp;
46
47 tmp = *(unsigned short *)(portp) & 0xff;
48 tmp |= *(unsigned short *)(portp+2) << 8;
49 return tmp;
50}
51
52static inline void _ne_insb(void *portp, void *addr, unsigned long count)
53{
54 unsigned char *buf = addr;
55 while (count--)
56 *buf++ = *(volatile unsigned char *)(portp+1);
57}
58
59static inline void _ne_outb(unsigned char b, void *portp)
60{
61 *(volatile unsigned char *)(portp+1) = b;
62}
63
64static inline void _ne_outw(unsigned short w, void *portp)
65{
66 *(volatile unsigned short *)portp = (w >> 8);
67 *(volatile unsigned short *)(portp+2) = (w & 0xff);
68}
69
70unsigned char _inb(unsigned long port)
71{
72 if (port >= 0x300 && port < 0x320)
73 return _ne_inb(PORT2ADDR_NE(port));
74
75 return *(volatile unsigned char *)PORT2ADDR(port);
76}
77
78unsigned short _inw(unsigned long port)
79{
80 if (port >= 0x300 && port < 0x320)
81 return _ne_inw(PORT2ADDR_NE(port));
82
83 return *(volatile unsigned short *)PORT2ADDR(port);
84}
85
86unsigned long _inl(unsigned long port)
87{
88 return *(volatile unsigned long *)PORT2ADDR(port);
89}
90
91unsigned char _inb_p(unsigned long port)
92{
93 unsigned char v;
94
95 if (port >= 0x300 && port < 0x320)
96 v = _ne_inb(PORT2ADDR_NE(port));
97 else
98 v = *(volatile unsigned char *)PORT2ADDR(port);
99
100 delay();
101 return (v);
102}
103
104unsigned short _inw_p(unsigned long port)
105{
106 unsigned short v;
107
108 if (port >= 0x300 && port < 0x320)
109 v = _ne_inw(PORT2ADDR_NE(port));
110 else
111 v = *(volatile unsigned short *)PORT2ADDR(port);
112
113 delay();
114 return (v);
115}
116
117unsigned long _inl_p(unsigned long port)
118{
119 unsigned long v;
120
121 v = *(volatile unsigned long *)PORT2ADDR(port);
122 delay();
123 return (v);
124}
125
126void _outb(unsigned char b, unsigned long port)
127{
128 if (port >= 0x300 && port < 0x320)
129 _ne_outb(b, PORT2ADDR_NE(port));
130 else
131 *(volatile unsigned char *)PORT2ADDR(port) = b;
132}
133
134void _outw(unsigned short w, unsigned long port)
135{
136 if (port >= 0x300 && port < 0x320)
137 _ne_outw(w, PORT2ADDR_NE(port));
138 else
139 *(volatile unsigned short *)PORT2ADDR(port) = w;
140}
141
142void _outl(unsigned long l, unsigned long port)
143{
144 *(volatile unsigned long *)PORT2ADDR(port) = l;
145}
146
147void _outb_p(unsigned char b, unsigned long port)
148{
149 if (port >= 0x300 && port < 0x320)
150 _ne_outb(b, PORT2ADDR_NE(port));
151 else
152 *(volatile unsigned char *)PORT2ADDR(port) = b;
153
154 delay();
155}
156
157void _outw_p(unsigned short w, unsigned long port)
158{
159 if (port >= 0x300 && port < 0x320)
160 _ne_outw(w, PORT2ADDR_NE(port));
161 else
162 *(volatile unsigned short *)PORT2ADDR(port) = w;
163
164 delay();
165}
166
167void _outl_p(unsigned long l, unsigned long port)
168{
169 *(volatile unsigned long *)PORT2ADDR(port) = l;
170 delay();
171}
172
173void _insb(unsigned int port, void *addr, unsigned long count)
174{
175 if (port >= 0x300 && port < 0x320)
176 _ne_insb(PORT2ADDR_NE(port), addr, count);
177 else {
178 unsigned char *buf = addr;
179 unsigned char *portp = PORT2ADDR(port);
180 while (count--)
181 *buf++ = *(volatile unsigned char *)portp;
182 }
183}
184
185void _insw(unsigned int port, void *addr, unsigned long count)
186{
187 unsigned short *buf = addr;
188 unsigned short *portp;
189
190 if (port >= 0x300 && port < 0x320) {
191 portp = PORT2ADDR_NE(port);
192 while (count--)
193 *buf++ = _ne_inw(portp);
194 } else {
195 portp = PORT2ADDR(port);
196 while (count--)
197 *buf++ = *(volatile unsigned short *)portp;
198 }
199}
200
201void _insl(unsigned int port, void *addr, unsigned long count)
202{
203 unsigned long *buf = addr;
204 unsigned long *portp;
205
206 portp = PORT2ADDR(port);
207 while (count--)
208 *buf++ = *(volatile unsigned long *)portp;
209}
210
211void _outsb(unsigned int port, const void *addr, unsigned long count)
212{
213 const unsigned char *buf = addr;
214 unsigned char *portp;
215
216 if (port >= 0x300 && port < 0x320) {
217 portp = PORT2ADDR_NE(port);
218 while (count--)
219 _ne_outb(*buf++, portp);
220 } else {
221 portp = PORT2ADDR(port);
222 while (count--)
223 *(volatile unsigned char *)portp = *buf++;
224 }
225}
226
227void _outsw(unsigned int port, const void *addr, unsigned long count)
228{
229 const unsigned short *buf = addr;
230 unsigned short *portp;
231
232 if (port >= 0x300 && port < 0x320) {
233 portp = PORT2ADDR_NE(port);
234 while (count--)
235 _ne_outw(*buf++, portp);
236 } else {
237 portp = PORT2ADDR(port);
238 while (count--)
239 *(volatile unsigned short *)portp = *buf++;
240 }
241}
242
243void _outsl(unsigned int port, const void *addr, unsigned long count)
244{
245 const unsigned long *buf = addr;
246 unsigned char *portp;
247
248 portp = PORT2ADDR(port);
249 while (count--)
250 *(volatile unsigned long *)portp = *buf++;
251}
diff --git a/arch/m32r/kernel/io_opsput.c b/arch/m32r/kernel/io_opsput.c
new file mode 100644
index 000000000000..aaf42f9f76da
--- /dev/null
+++ b/arch/m32r/kernel/io_opsput.c
@@ -0,0 +1,390 @@
1/*
2 * linux/arch/m32r/kernel/io_mappi.c
3 *
4 * Typical I/O routines for OPSPUT board.
5 *
6 * Copyright (c) 2001, 2002 Hiroyuki Kondo, Hirokazu Takata,
7 * Hitoshi Yamamoto, Takeo Takahashi
8 *
9 * This file is subject to the terms and conditions of the GNU General
10 * Public License. See the file "COPYING" in the main directory of this
11 * archive for more details.
12 */
13
14#include <linux/config.h>
15#include <asm/m32r.h>
16#include <asm/page.h>
17#include <asm/io.h>
18#include <asm/byteorder.h>
19
20#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
21#include <linux/types.h>
22
23#define M32R_PCC_IOMAP_SIZE 0x1000
24
25#define M32R_PCC_IOSTART0 0x1000
26#define M32R_PCC_IOEND0 (M32R_PCC_IOSTART0 + M32R_PCC_IOMAP_SIZE - 1)
27
28extern void pcc_ioread_byte(int, unsigned long, void *, size_t, size_t, int);
29extern void pcc_ioread_word(int, unsigned long, void *, size_t, size_t, int);
30extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int);
31extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
32#endif /* CONFIG_PCMCIA && CONFIG_M32R_CFC */
33
34#define PORT2ADDR(port) _port2addr(port)
35#define PORT2ADDR_USB(port) _port2addr_usb(port)
36
37static inline void *_port2addr(unsigned long port)
38{
39 return (void *)(port + NONCACHE_OFFSET);
40}
41
42/*
43 * OPSPUT-LAN is located in the extended bus space
44 * from 0x10000000 to 0x13ffffff on physical address.
45 * The base address of LAN controller(LAN91C111) is 0x300.
46 */
47#define LAN_IOSTART 0x300
48#define LAN_IOEND 0x320
49static inline void *_port2addr_ne(unsigned long port)
50{
51 return (void *)(port + NONCACHE_OFFSET + 0x10000000);
52}
53static inline void *_port2addr_usb(unsigned long port)
54{
55 return (void *)((port & 0x0f) + NONCACHE_OFFSET + 0x10303000);
56}
57
58static inline void delay(void)
59{
60 __asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");
61}
62
63/*
64 * NIC I/O function
65 */
66
67#define PORT2ADDR_NE(port) _port2addr_ne(port)
68
69static inline unsigned char _ne_inb(void *portp)
70{
71 return *(volatile unsigned char *)portp;
72}
73
74static inline unsigned short _ne_inw(void *portp)
75{
76 return (unsigned short)le16_to_cpu(*(volatile unsigned short *)portp);
77}
78
79static inline void _ne_insb(void *portp, void *addr, unsigned long count)
80{
81 unsigned char *buf = (unsigned char *)addr;
82
83 while (count--)
84 *buf++ = _ne_inb(portp);
85}
86
87static inline void _ne_outb(unsigned char b, void *portp)
88{
89 *(volatile unsigned char *)portp = b;
90}
91
92static inline void _ne_outw(unsigned short w, void *portp)
93{
94 *(volatile unsigned short *)portp = cpu_to_le16(w);
95}
96
97unsigned char _inb(unsigned long port)
98{
99 if (port >= LAN_IOSTART && port < LAN_IOEND)
100 return _ne_inb(PORT2ADDR_NE(port));
101
102#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
103 else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
104 unsigned char b;
105 pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
106 return b;
107 } else
108#endif
109
110 return *(volatile unsigned char *)PORT2ADDR(port);
111}
112
113unsigned short _inw(unsigned long port)
114{
115 if (port >= LAN_IOSTART && port < LAN_IOEND)
116 return _ne_inw(PORT2ADDR_NE(port));
117#if defined(CONFIG_USB)
118 else if(port >= 0x340 && port < 0x3a0)
119 return *(volatile unsigned short *)PORT2ADDR_USB(port);
120#endif
121
122#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
123 else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
124 unsigned short w;
125 pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
126 return w;
127 } else
128#endif
129 return *(volatile unsigned short *)PORT2ADDR(port);
130}
131
132unsigned long _inl(unsigned long port)
133{
134#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
135 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
136 unsigned long l;
137 pcc_ioread_word(0, port, &l, sizeof(l), 1, 0);
138 return l;
139 } else
140#endif
141 return *(volatile unsigned long *)PORT2ADDR(port);
142}
143
144unsigned char _inb_p(unsigned long port)
145{
146 unsigned char v;
147
148 if (port >= LAN_IOSTART && port < LAN_IOEND)
149 v = _ne_inb(PORT2ADDR_NE(port));
150 else
151#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
152 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
153 unsigned char b;
154 pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
155 return b;
156 } else
157#endif
158 v = *(volatile unsigned char *)PORT2ADDR(port);
159
160 delay();
161 return (v);
162}
163
164unsigned short _inw_p(unsigned long port)
165{
166 unsigned short v;
167
168 if (port >= LAN_IOSTART && port < LAN_IOEND)
169 v = _ne_inw(PORT2ADDR_NE(port));
170 else
171#if defined(CONFIG_USB)
172 if(port >= 0x340 && port < 0x3a0)
173 return *(volatile unsigned short *)PORT2ADDR_USB(port);
174 else
175#endif
176
177#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
178 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
179 unsigned short w;
180 pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
181 return w;
182 } else
183#endif
184 v = *(volatile unsigned short *)PORT2ADDR(port);
185
186 delay();
187 return (v);
188}
189
190unsigned long _inl_p(unsigned long port)
191{
192 unsigned long v;
193
194 v = *(volatile unsigned long *)PORT2ADDR(port);
195 delay();
196 return (v);
197}
198
199void _outb(unsigned char b, unsigned long port)
200{
201 if (port >= LAN_IOSTART && port < LAN_IOEND)
202 _ne_outb(b, PORT2ADDR_NE(port));
203 else
204#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
205 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
206 pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
207 } else
208#endif
209 *(volatile unsigned char *)PORT2ADDR(port) = b;
210}
211
212void _outw(unsigned short w, unsigned long port)
213{
214 if (port >= LAN_IOSTART && port < LAN_IOEND)
215 _ne_outw(w, PORT2ADDR_NE(port));
216 else
217#if defined(CONFIG_USB)
218 if(port >= 0x340 && port < 0x3a0)
219 *(volatile unsigned short *)PORT2ADDR_USB(port) = w;
220 else
221#endif
222
223#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
224 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
225 pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
226 } else
227#endif
228 *(volatile unsigned short *)PORT2ADDR(port) = w;
229}
230
231void _outl(unsigned long l, unsigned long port)
232{
233#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
234 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
235 pcc_iowrite_word(0, port, &l, sizeof(l), 1, 0);
236 } else
237#endif
238 *(volatile unsigned long *)PORT2ADDR(port) = l;
239}
240
241void _outb_p(unsigned char b, unsigned long port)
242{
243 if (port >= LAN_IOSTART && port < LAN_IOEND)
244 _ne_outb(b, PORT2ADDR_NE(port));
245 else
246#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
247 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
248 pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
249 } else
250#endif
251 *(volatile unsigned char *)PORT2ADDR(port) = b;
252
253 delay();
254}
255
256void _outw_p(unsigned short w, unsigned long port)
257{
258 if (port >= LAN_IOSTART && port < LAN_IOEND)
259 _ne_outw(w, PORT2ADDR_NE(port));
260 else
261#if defined(CONFIG_USB)
262 if(port >= 0x340 && port < 0x3a0)
263 *(volatile unsigned short *)PORT2ADDR_USB(port) = w;
264 else
265#endif
266
267#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
268 if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
269 pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
270 } else
271#endif
272 *(volatile unsigned short *)PORT2ADDR(port) = w;
273
274 delay();
275}
276
277void _outl_p(unsigned long l, unsigned long port)
278{
279 *(volatile unsigned long *)PORT2ADDR(port) = l;
280 delay();
281}
282
283void _insb(unsigned int port, void *addr, unsigned long count)
284{
285 if (port >= LAN_IOSTART && port < LAN_IOEND)
286 _ne_insb(PORT2ADDR_NE(port), addr, count);
287#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
288 else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
289 pcc_ioread_byte(0, port, (void *)addr, sizeof(unsigned char),
290 count, 1);
291 }
292#endif
293 else {
294 unsigned char *buf = addr;
295 unsigned char *portp = PORT2ADDR(port);
296 while (count--)
297 *buf++ = *(volatile unsigned char *)portp;
298 }
299}
300
301void _insw(unsigned int port, void *addr, unsigned long count)
302{
303 unsigned short *buf = addr;
304 unsigned short *portp;
305
306 if (port >= LAN_IOSTART && port < LAN_IOEND) {
307 /*
308 * This portion is only used by smc91111.c to read data
309 * from the DATA_REG. Do not swap the data.
310 */
311 portp = PORT2ADDR_NE(port);
312 while (count--)
313 *buf++ = *(volatile unsigned short *)portp;
314#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
315 } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
316 pcc_ioread_word(9, port, (void *)addr, sizeof(unsigned short),
317 count, 1);
318#endif
319 } else {
320 portp = PORT2ADDR(port);
321 while (count--)
322 *buf++ = *(volatile unsigned short *)portp;
323 }
324}
325
326void _insl(unsigned int port, void *addr, unsigned long count)
327{
328 unsigned long *buf = addr;
329 unsigned long *portp;
330
331 portp = PORT2ADDR(port);
332 while (count--)
333 *buf++ = *(volatile unsigned long *)portp;
334}
335
336void _outsb(unsigned int port, const void *addr, unsigned long count)
337{
338 const unsigned char *buf = addr;
339 unsigned char *portp;
340
341 if (port >= LAN_IOSTART && port < LAN_IOEND) {
342 portp = PORT2ADDR_NE(port);
343 while (count--)
344 _ne_outb(*buf++, portp);
345#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
346 } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
347 pcc_iowrite_byte(0, port, (void *)addr, sizeof(unsigned char),
348 count, 1);
349#endif
350 } else {
351 portp = PORT2ADDR(port);
352 while (count--)
353 *(volatile unsigned char *)portp = *buf++;
354 }
355}
356
357void _outsw(unsigned int port, const void *addr, unsigned long count)
358{
359 const unsigned short *buf = addr;
360 unsigned short *portp;
361
362 if (port >= LAN_IOSTART && port < LAN_IOEND) {
363 /*
364 * This portion is only used by smc91111.c to write data
365 * into the DATA_REG. Do not swap the data.
366 */
367 portp = PORT2ADDR_NE(port);
368 while (count--)
369 *(volatile unsigned short *)portp = *buf++;
370#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
371 } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
372 pcc_iowrite_word(9, port, (void *)addr, sizeof(unsigned short),
373 count, 1);
374#endif
375 } else {
376 portp = PORT2ADDR(port);
377 while (count--)
378 *(volatile unsigned short *)portp = *buf++;
379 }
380}
381
382void _outsl(unsigned int port, const void *addr, unsigned long count)
383{
384 const unsigned long *buf = addr;
385 unsigned char *portp;
386
387 portp = PORT2ADDR(port);
388 while (count--)
389 *(volatile unsigned long *)portp = *buf++;
390}
diff --git a/arch/m32r/kernel/io_usrv.c b/arch/m32r/kernel/io_usrv.c
new file mode 100644
index 000000000000..27928a0b99ed
--- /dev/null
+++ b/arch/m32r/kernel/io_usrv.c
@@ -0,0 +1,249 @@
1/*
2 * linux/arch/m32r/kernel/io_usrv.c
3 *
4 * Typical I/O routines for uServer board.
5 *
6 * Copyright (c) 2001 - 2003 Hiroyuki Kondo, Hirokazu Takata,
7 * Hitoshi Yamamoto, Takeo Takahashi
8 *
9 * This file is subject to the terms and conditions of the GNU General
10 * Public License. See the file "COPYING" in the main directory of this
11 * archive for more details.
12 *
13 */
14
15#include <linux/config.h>
16#include <asm/m32r.h>
17#include <asm/page.h>
18#include <asm/io.h>
19
20#include <linux/types.h>
21#include "../drivers/m32r_cfc.h"
22
23extern void pcc_ioread_byte(int, unsigned long, void *, size_t, size_t, int);
24extern void pcc_ioread_word(int, unsigned long, void *, size_t, size_t, int);
25extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int);
26extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
27#define CFC_IOSTART CFC_IOPORT_BASE
28#define CFC_IOEND (CFC_IOSTART + (M32R_PCC_MAPSIZE * M32R_MAX_PCC) - 1)
29
30#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
31#define UART0_REGSTART 0x04c20000
32#define UART1_REGSTART 0x04c20100
33#define UART_IOMAP_SIZE 8
34#define UART0_IOSTART 0x3f8
35#define UART0_IOEND (UART0_IOSTART + UART_IOMAP_SIZE - 1)
36#define UART1_IOSTART 0x2f8
37#define UART1_IOEND (UART1_IOSTART + UART_IOMAP_SIZE - 1)
38#endif /* CONFIG_SERIAL_8250 || CONFIG_SERIAL_8250_MODULE */
39
40#define PORT2ADDR(port) _port2addr(port)
41
42static __inline__ void *_port2addr(unsigned long port)
43{
44#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
45 if (port >= UART0_IOSTART && port <= UART0_IOEND)
46 port = ((port - UART0_IOSTART) << 1) + UART0_REGSTART;
47 else if (port >= UART1_IOSTART && port <= UART1_IOEND)
48 port = ((port - UART1_IOSTART) << 1) + UART1_REGSTART;
49#endif /* CONFIG_SERIAL_8250 || CONFIG_SERIAL_8250_MODULE */
50 return (void *)(port + NONCACHE_OFFSET);
51}
52
53static __inline__ void delay(void)
54{
55 __asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");
56}
57
58unsigned char _inb(unsigned long port)
59{
60 if (port >= CFC_IOSTART && port <= CFC_IOEND) {
61 unsigned char b;
62 pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
63 return b;
64 } else
65 return *(volatile unsigned char *)PORT2ADDR(port);
66}
67
68unsigned short _inw(unsigned long port)
69{
70 if (port >= CFC_IOSTART && port <= CFC_IOEND) {
71 unsigned short w;
72 pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
73 return w;
74 } else
75 return *(volatile unsigned short *)PORT2ADDR(port);
76}
77
78unsigned long _inl(unsigned long port)
79{
80 if (port >= CFC_IOSTART && port <= CFC_IOEND) {
81 unsigned long l;
82 pcc_ioread_word(0, port, &l, sizeof(l), 1, 0);
83 return l;
84 } else
85 return *(volatile unsigned long *)PORT2ADDR(port);
86}
87
88unsigned char _inb_p(unsigned long port)
89{
90 unsigned char b;
91
92 if (port >= CFC_IOSTART && port <= CFC_IOEND) {
93 pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
94 return b;
95 } else {
96 b = *(volatile unsigned char *)PORT2ADDR(port);
97 delay();
98 return b;
99 }
100}
101
102unsigned short _inw_p(unsigned long port)
103{
104 unsigned short w;
105
106 if (port >= CFC_IOSTART && port <= CFC_IOEND) {
107 pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
108 return w;
109 } else {
110 w = *(volatile unsigned short *)PORT2ADDR(port);
111 delay();
112 return w;
113 }
114}
115
116unsigned long _inl_p(unsigned long port)
117{
118 unsigned long v;
119
120 v = *(volatile unsigned long *)PORT2ADDR(port);
121 delay();
122
123 return v;
124}
125
126void _outb(unsigned char b, unsigned long port)
127{
128 if (port >= CFC_IOSTART && port <= CFC_IOEND)
129 pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
130 else
131 *(volatile unsigned char *)PORT2ADDR(port) = b;
132}
133
134void _outw(unsigned short w, unsigned long port)
135{
136 if (port >= CFC_IOSTART && port <= CFC_IOEND)
137 pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
138 else
139 *(volatile unsigned short *)PORT2ADDR(port) = w;
140}
141
142void _outl(unsigned long l, unsigned long port)
143{
144 if (port >= CFC_IOSTART && port <= CFC_IOEND)
145 pcc_iowrite_word(0, port, &l, sizeof(l), 1, 0);
146 else
147 *(volatile unsigned long *)PORT2ADDR(port) = l;
148}
149
150void _outb_p(unsigned char b, unsigned long port)
151{
152 if (port >= CFC_IOSTART && port <= CFC_IOEND)
153 pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
154 else
155 *(volatile unsigned char *)PORT2ADDR(port) = b;
156 delay();
157}
158
159void _outw_p(unsigned short w, unsigned long port)
160{
161 if (port >= CFC_IOSTART && port <= CFC_IOEND)
162 pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
163 else
164 *(volatile unsigned short *)PORT2ADDR(port) = w;
165 delay();
166}
167
168void _outl_p(unsigned long l, unsigned long port)
169{
170 *(volatile unsigned long *)PORT2ADDR(port) = l;
171 delay();
172}
173
174void _insb(unsigned int port, void * addr, unsigned long count)
175{
176 if (port >= CFC_IOSTART && port <= CFC_IOEND)
177 pcc_ioread_byte(0, port, addr, sizeof(unsigned char), count, 1);
178 else {
179 unsigned char *buf = addr;
180 unsigned char *portp = PORT2ADDR(port);
181 while (count--)
182 *buf++ = *(volatile unsigned char *)portp;
183 }
184}
185
186void _insw(unsigned int port, void * addr, unsigned long count)
187{
188 unsigned short *buf = addr;
189 unsigned short *portp;
190
191 if (port >= CFC_IOSTART && port <= CFC_IOEND)
192 pcc_ioread_word(0, port, addr, sizeof(unsigned short), count,
193 1);
194 else {
195 portp = PORT2ADDR(port);
196 while (count--)
197 *buf++ = *(volatile unsigned short *)portp;
198 }
199}
200
201void _insl(unsigned int port, void * addr, unsigned long count)
202{
203 unsigned long *buf = addr;
204 unsigned long *portp;
205
206 portp = PORT2ADDR(port);
207 while (count--)
208 *buf++ = *(volatile unsigned long *)portp;
209}
210
211void _outsb(unsigned int port, const void * addr, unsigned long count)
212{
213 const unsigned char *buf = addr;
214 unsigned char *portp;
215
216 if (port >= CFC_IOSTART && port <= CFC_IOEND)
217 pcc_iowrite_byte(0, port, (void *)addr, sizeof(unsigned char),
218 count, 1);
219 else {
220 portp = PORT2ADDR(port);
221 while (count--)
222 *(volatile unsigned char *)portp = *buf++;
223 }
224}
225
226void _outsw(unsigned int port, const void * addr, unsigned long count)
227{
228 const unsigned short *buf = addr;
229 unsigned short *portp;
230
231 if (port >= CFC_IOSTART && port <= CFC_IOEND)
232 pcc_iowrite_word(0, port, (void *)addr, sizeof(unsigned short),
233 count, 1);
234 else {
235 portp = PORT2ADDR(port);
236 while (count--)
237 *(volatile unsigned short *)portp = *buf++;
238 }
239}
240
241void _outsl(unsigned int port, const void * addr, unsigned long count)
242{
243 const unsigned long *buf = addr;
244 unsigned char *portp;
245
246 portp = PORT2ADDR(port);
247 while (count--)
248 *(volatile unsigned long *)portp = *buf++;
249}
diff --git a/arch/m32r/kernel/irq.c b/arch/m32r/kernel/irq.c
new file mode 100644
index 000000000000..1ce63926a3c0
--- /dev/null
+++ b/arch/m32r/kernel/irq.c
@@ -0,0 +1,91 @@
1/*
2 * linux/arch/m32r/kernel/irq.c
3 *
4 * Copyright (c) 2003, 2004 Hitoshi Yamamoto
5 * Copyright (c) 2004 Hirokazu Takata <takata at linux-m32r.org>
6 */
7
8/*
9 * linux/arch/i386/kernel/irq.c
10 *
11 * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
12 *
13 * This file contains the lowest level m32r-specific interrupt
14 * entry and irq statistics code. All the remaining irq logic is
15 * done by the generic kernel/irq/ code and in the
16 * m32r-specific irq controller code.
17 */
18
19#include <linux/kernel_stat.h>
20#include <linux/interrupt.h>
21#include <linux/seq_file.h>
22#include <linux/module.h>
23#include <asm/uaccess.h>
24
25atomic_t irq_err_count;
26atomic_t irq_mis_count;
27
28/*
29 * Generic, controller-independent functions:
30 */
31
32int show_interrupts(struct seq_file *p, void *v)
33{
34 int i = *(loff_t *) v, j;
35 struct irqaction * action;
36 unsigned long flags;
37
38 if (i == 0) {
39 seq_printf(p, " ");
40 for (j=0; j<NR_CPUS; j++)
41 if (cpu_online(j))
42 seq_printf(p, "CPU%d ",j);
43 seq_putc(p, '\n');
44 }
45
46 if (i < NR_IRQS) {
47 spin_lock_irqsave(&irq_desc[i].lock, flags);
48 action = irq_desc[i].action;
49 if (!action)
50 goto skip;
51 seq_printf(p, "%3d: ",i);
52#ifndef CONFIG_SMP
53 seq_printf(p, "%10u ", kstat_irqs(i));
54#else
55 for (j = 0; j < NR_CPUS; j++)
56 if (cpu_online(j))
57 seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
58#endif
59 seq_printf(p, " %14s", irq_desc[i].handler->typename);
60 seq_printf(p, " %s", action->name);
61
62 for (action=action->next; action; action = action->next)
63 seq_printf(p, ", %s", action->name);
64
65 seq_putc(p, '\n');
66skip:
67 spin_unlock_irqrestore(&irq_desc[i].lock, flags);
68 } else if (i == NR_IRQS) {
69 seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
70 seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
71 }
72 return 0;
73}
74
75/*
76 * do_IRQ handles all normal device IRQ's (the special
77 * SMP cross-CPU interrupts have their own specific
78 * handlers).
79 */
80asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs)
81{
82 irq_enter();
83
84#ifdef CONFIG_DEBUG_STACKOVERFLOW
85 /* FIXME M32R */
86#endif
87 __do_IRQ(irq, regs);
88 irq_exit();
89
90 return 1;
91}
diff --git a/arch/m32r/kernel/m32r_ksyms.c b/arch/m32r/kernel/m32r_ksyms.c
new file mode 100644
index 000000000000..e5ec134d81d9
--- /dev/null
+++ b/arch/m32r/kernel/m32r_ksyms.c
@@ -0,0 +1,140 @@
1#include <linux/config.h>
2#include <linux/module.h>
3#include <linux/smp.h>
4#include <linux/user.h>
5#include <linux/elfcore.h>
6#include <linux/sched.h>
7#include <linux/in6.h>
8#include <linux/interrupt.h>
9#include <linux/smp_lock.h>
10#include <linux/string.h>
11
12#include <asm/semaphore.h>
13#include <asm/processor.h>
14#include <asm/uaccess.h>
15#include <asm/checksum.h>
16#include <asm/io.h>
17#include <asm/delay.h>
18#include <asm/irq.h>
19#include <asm/tlbflush.h>
20
21extern void dump_thread(struct pt_regs *, struct user *);
22
23#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE)
24extern struct drive_info_struct drive_info;
25EXPORT_SYMBOL(drive_info);
26#endif
27
28/* platform dependent support */
29EXPORT_SYMBOL(boot_cpu_data);
30EXPORT_SYMBOL(dump_thread);
31EXPORT_SYMBOL(dump_fpu);
32EXPORT_SYMBOL(__ioremap);
33EXPORT_SYMBOL(iounmap);
34EXPORT_SYMBOL(enable_irq);
35EXPORT_SYMBOL(disable_irq);
36EXPORT_SYMBOL(disable_irq_nosync);
37EXPORT_SYMBOL(kernel_thread);
38EXPORT_SYMBOL(__down);
39EXPORT_SYMBOL(__down_interruptible);
40EXPORT_SYMBOL(__up);
41EXPORT_SYMBOL(__down_trylock);
42
43/* Networking helper routines. */
44/* Delay loops */
45EXPORT_SYMBOL(__udelay);
46EXPORT_SYMBOL(__delay);
47EXPORT_SYMBOL(__const_udelay);
48
49EXPORT_SYMBOL(__get_user_1);
50EXPORT_SYMBOL(__get_user_2);
51EXPORT_SYMBOL(__get_user_4);
52
53EXPORT_SYMBOL(strpbrk);
54EXPORT_SYMBOL(strstr);
55
56EXPORT_SYMBOL(strncpy_from_user);
57EXPORT_SYMBOL(__strncpy_from_user);
58EXPORT_SYMBOL(clear_user);
59EXPORT_SYMBOL(__clear_user);
60EXPORT_SYMBOL(__generic_copy_from_user);
61EXPORT_SYMBOL(__generic_copy_to_user);
62EXPORT_SYMBOL(strnlen_user);
63
64#ifdef CONFIG_SMP
65#ifdef CONFIG_CHIP_M32700_TS1
66extern void *dcache_dummy;
67EXPORT_SYMBOL(dcache_dummy);
68#endif
69EXPORT_SYMBOL(cpu_data);
70EXPORT_SYMBOL(cpu_online_map);
71EXPORT_SYMBOL(cpu_callout_map);
72
73/* Global SMP stuff */
74EXPORT_SYMBOL(synchronize_irq);
75EXPORT_SYMBOL(smp_call_function);
76
77/* TLB flushing */
78EXPORT_SYMBOL(smp_flush_tlb_page);
79#endif
80
81/* compiler generated symbol */
82extern void __ashldi3(void);
83extern void __ashrdi3(void);
84extern void __lshldi3(void);
85extern void __lshrdi3(void);
86extern void __muldi3(void);
87EXPORT_SYMBOL(__ashldi3);
88EXPORT_SYMBOL(__ashrdi3);
89EXPORT_SYMBOL(__lshldi3);
90EXPORT_SYMBOL(__lshrdi3);
91EXPORT_SYMBOL(__muldi3);
92
93/* memory and string operations */
94EXPORT_SYMBOL(memchr);
95EXPORT_SYMBOL(memcpy);
96/* EXPORT_SYMBOL(memcpy_fromio); // not implement yet */
97/* EXPORT_SYMBOL(memcpy_toio); // not implement yet */
98EXPORT_SYMBOL(memset);
99/* EXPORT_SYMBOL(memset_io); // not implement yet */
100EXPORT_SYMBOL(memmove);
101EXPORT_SYMBOL(memcmp);
102EXPORT_SYMBOL(memscan);
103EXPORT_SYMBOL(copy_page);
104EXPORT_SYMBOL(clear_page);
105
106EXPORT_SYMBOL(strcat);
107EXPORT_SYMBOL(strchr);
108EXPORT_SYMBOL(strcmp);
109EXPORT_SYMBOL(strcpy);
110EXPORT_SYMBOL(strlen);
111EXPORT_SYMBOL(strncat);
112EXPORT_SYMBOL(strncmp);
113EXPORT_SYMBOL(strnlen);
114EXPORT_SYMBOL(strncpy);
115
116EXPORT_SYMBOL(_inb);
117EXPORT_SYMBOL(_inw);
118EXPORT_SYMBOL(_inl);
119EXPORT_SYMBOL(_outb);
120EXPORT_SYMBOL(_outw);
121EXPORT_SYMBOL(_outl);
122EXPORT_SYMBOL(_inb_p);
123EXPORT_SYMBOL(_inw_p);
124EXPORT_SYMBOL(_inl_p);
125EXPORT_SYMBOL(_outb_p);
126EXPORT_SYMBOL(_outw_p);
127EXPORT_SYMBOL(_outl_p);
128EXPORT_SYMBOL(_insb);
129EXPORT_SYMBOL(_insw);
130EXPORT_SYMBOL(_insl);
131EXPORT_SYMBOL(_outsb);
132EXPORT_SYMBOL(_outsw);
133EXPORT_SYMBOL(_outsl);
134EXPORT_SYMBOL(_readb);
135EXPORT_SYMBOL(_readw);
136EXPORT_SYMBOL(_readl);
137EXPORT_SYMBOL(_writeb);
138EXPORT_SYMBOL(_writew);
139EXPORT_SYMBOL(_writel);
140
diff --git a/arch/m32r/kernel/module.c b/arch/m32r/kernel/module.c
new file mode 100644
index 000000000000..f6a79a016ce0
--- /dev/null
+++ b/arch/m32r/kernel/module.c
@@ -0,0 +1,259 @@
1/* Kernel module help for M32R.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16*/
17
18#include <linux/config.h>
19#include <linux/moduleloader.h>
20#include <linux/elf.h>
21#include <linux/vmalloc.h>
22#include <linux/fs.h>
23#include <linux/string.h>
24#include <linux/kernel.h>
25
26#if 0
27#define DEBUGP printk
28#else
29#define DEBUGP(fmt...)
30#endif
31
32void *module_alloc(unsigned long size)
33{
34 if (size == 0)
35 return NULL;
36#ifdef CONFIG_MMU
37 return vmalloc_exec(size);
38#else
39 return vmalloc(size);
40#endif
41}
42
43
44/* Free memory returned from module_alloc */
45void module_free(struct module *mod, void *module_region)
46{
47 vfree(module_region);
48 /* FIXME: If module_region == mod->init_region, trim exception
49 table entries. */
50}
51
52/* We don't need anything special. */
53int module_frob_arch_sections(Elf_Ehdr *hdr,
54 Elf_Shdr *sechdrs,
55 char *secstrings,
56 struct module *mod)
57{
58 return 0;
59}
60
61#define COPY_UNALIGNED_WORD(sw, tw, align) \
62{ \
63 void *__s = &(sw), *__t = &(tw); \
64 unsigned short *__s2 = __s, *__t2 =__t; \
65 unsigned char *__s1 = __s, *__t1 =__t; \
66 switch ((align)) \
67 { \
68 case 0: \
69 *(unsigned long *) __t = *(unsigned long *) __s; \
70 break; \
71 case 2: \
72 *__t2++ = *__s2++; \
73 *__t2 = *__s2; \
74 break; \
75 default: \
76 *__t1++ = *__s1++; \
77 *__t1++ = *__s1++; \
78 *__t1++ = *__s1++; \
79 *__t1 = *__s1; \
80 break; \
81 } \
82}
83
84#define COPY_UNALIGNED_HWORD(sw, tw, align) \
85 { \
86 void *__s = &(sw), *__t = &(tw); \
87 unsigned short *__s2 = __s, *__t2 =__t; \
88 unsigned char *__s1 = __s, *__t1 =__t; \
89 switch ((align)) \
90 { \
91 case 0: \
92 *__t2 = *__s2; \
93 break; \
94 default: \
95 *__t1++ = *__s1++; \
96 *__t1 = *__s1; \
97 break; \
98 } \
99 }
100
101int apply_relocate_add(Elf32_Shdr *sechdrs,
102 const char *strtab,
103 unsigned int symindex,
104 unsigned int relsec,
105 struct module *me)
106{
107 unsigned int i;
108 Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
109 Elf32_Sym *sym;
110 Elf32_Addr relocation;
111 uint32_t *location;
112 uint32_t value;
113 unsigned short *hlocation;
114 unsigned short hvalue;
115 int svalue;
116 int align;
117
118 DEBUGP("Applying relocate section %u to %u\n", relsec,
119 sechdrs[relsec].sh_info);
120 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
121 /* This is where to make the change */
122 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
123 + rel[i].r_offset;
124 /* This is the symbol it is referring to. Note that all
125 undefined symbols have been resolved. */
126 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
127 + ELF32_R_SYM(rel[i].r_info);
128 relocation = sym->st_value + rel[i].r_addend;
129 align = (int)location & 3;
130
131 switch (ELF32_R_TYPE(rel[i].r_info)) {
132 case R_M32R_32_RELA:
133 COPY_UNALIGNED_WORD (*location, value, align);
134 value += relocation;
135 COPY_UNALIGNED_WORD (value, *location, align);
136 break;
137 case R_M32R_HI16_ULO_RELA:
138 COPY_UNALIGNED_WORD (*location, value, align);
139 relocation = (relocation >>16) & 0xffff;
140 /* RELA must has 0 at relocation field. */
141 value += relocation;
142 COPY_UNALIGNED_WORD (value, *location, align);
143 break;
144 case R_M32R_HI16_SLO_RELA:
145 COPY_UNALIGNED_WORD (*location, value, align);
146 if (relocation & 0x8000) relocation += 0x10000;
147 relocation = (relocation >>16) & 0xffff;
148 /* RELA must has 0 at relocation field. */
149 value += relocation;
150 COPY_UNALIGNED_WORD (value, *location, align);
151 break;
152 case R_M32R_16_RELA:
153 hlocation = (unsigned short *)location;
154 relocation = relocation & 0xffff;
155 /* RELA must has 0 at relocation field. */
156 hvalue = relocation;
157 COPY_UNALIGNED_WORD (hvalue, *hlocation, align);
158 break;
159 case R_M32R_SDA16_RELA:
160 case R_M32R_LO16_RELA:
161 COPY_UNALIGNED_WORD (*location, value, align);
162 relocation = relocation & 0xffff;
163 /* RELA must has 0 at relocation field. */
164 value += relocation;
165 COPY_UNALIGNED_WORD (value, *location, align);
166 break;
167 case R_M32R_24_RELA:
168 COPY_UNALIGNED_WORD (*location, value, align);
169 relocation = relocation & 0xffffff;
170 /* RELA must has 0 at relocation field. */
171 value += relocation;
172 COPY_UNALIGNED_WORD (value, *location, align);
173 break;
174 case R_M32R_18_PCREL_RELA:
175 relocation = (relocation - (Elf32_Addr) location);
176 if (relocation < -0x20000 || 0x1fffc < relocation)
177 {
178 printk(KERN_ERR "module %s: relocation overflow: %u\n",
179 me->name, relocation);
180 return -ENOEXEC;
181 }
182 COPY_UNALIGNED_WORD (*location, value, align);
183 if (value & 0xffff)
184 {
185 /* RELA must has 0 at relocation field. */
186 printk(KERN_ERR "module %s: illegal relocation field: %u\n",
187 me->name, value);
188 return -ENOEXEC;
189 }
190 relocation = (relocation >> 2) & 0xffff;
191 value += relocation;
192 COPY_UNALIGNED_WORD (value, *location, align);
193 break;
194 case R_M32R_10_PCREL_RELA:
195 hlocation = (unsigned short *)location;
196 relocation = (relocation - (Elf32_Addr) location);
197 COPY_UNALIGNED_HWORD (*hlocation, hvalue, align);
198 svalue = (int)hvalue;
199 svalue = (signed char)svalue << 2;
200 relocation += svalue;
201 relocation = (relocation >> 2) & 0xff;
202 hvalue = hvalue & 0xff00;
203 hvalue += relocation;
204 COPY_UNALIGNED_HWORD (hvalue, *hlocation, align);
205 break;
206 case R_M32R_26_PCREL_RELA:
207 relocation = (relocation - (Elf32_Addr) location);
208 if (relocation < -0x2000000 || 0x1fffffc < relocation)
209 {
210 printk(KERN_ERR "module %s: relocation overflow: %u\n",
211 me->name, relocation);
212 return -ENOEXEC;
213 }
214 COPY_UNALIGNED_WORD (*location, value, align);
215 if (value & 0xffffff)
216 {
217 /* RELA must has 0 at relocation field. */
218 printk(KERN_ERR "module %s: illegal relocation field: %u\n",
219 me->name, value);
220 return -ENOEXEC;
221 }
222 relocation = (relocation >> 2) & 0xffffff;
223 value += relocation;
224 COPY_UNALIGNED_WORD (value, *location, align);
225 break;
226 default:
227 printk(KERN_ERR "module %s: Unknown relocation: %u\n",
228 me->name, ELF32_R_TYPE(rel[i].r_info));
229 return -ENOEXEC;
230 }
231 }
232 return 0;
233}
234
235int apply_relocate(Elf32_Shdr *sechdrs,
236 const char *strtab,
237 unsigned int symindex,
238 unsigned int relsec,
239 struct module *me)
240{
241#if 0
242 printk(KERN_ERR "module %s: REL RELOCATION unsupported\n",
243 me->name);
244 return -ENOEXEC;
245#endif
246 return 0;
247
248}
249
250int module_finalize(const Elf_Ehdr *hdr,
251 const Elf_Shdr *sechdrs,
252 struct module *me)
253{
254 return 0;
255}
256
257void module_arch_cleanup(struct module *mod)
258{
259}
diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c
new file mode 100644
index 000000000000..b556c3cf6495
--- /dev/null
+++ b/arch/m32r/kernel/process.c
@@ -0,0 +1,359 @@
1/*
2 * linux/arch/m32r/kernel/process.c
3 *
4 * Copyright (c) 2001, 2002 Hiroyuki Kondo, Hirokazu Takata,
5 * Hitoshi Yamamoto
6 * Taken from sh version.
7 * Copyright (C) 1995 Linus Torvalds
8 * SuperH version: Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima
9 */
10
11#undef DEBUG_PROCESS
12#ifdef DEBUG_PROCESS
13#define DPRINTK(fmt, args...) printk("%s:%d:%s: " fmt, __FILE__, __LINE__, \
14 __FUNCTION__, ##args)
15#else
16#define DPRINTK(fmt, args...)
17#endif
18
19/*
20 * This file handles the architecture-dependent parts of process handling..
21 */
22
23#include <linux/fs.h>
24#include <linux/config.h>
25#include <linux/module.h>
26#include <linux/ptrace.h>
27#include <linux/unistd.h>
28#include <linux/slab.h>
29#include <linux/hardirq.h>
30
31#include <asm/io.h>
32#include <asm/uaccess.h>
33#include <asm/mmu_context.h>
34#include <asm/elf.h>
35#include <asm/m32r.h>
36
37#include <linux/err.h>
38
39static int hlt_counter=0;
40
41/*
42 * Return saved PC of a blocked thread.
43 */
44unsigned long thread_saved_pc(struct task_struct *tsk)
45{
46 return tsk->thread.lr;
47}
48
49/*
50 * Powermanagement idle function, if any..
51 */
52void (*pm_idle)(void) = NULL;
53
54void disable_hlt(void)
55{
56 hlt_counter++;
57}
58
59EXPORT_SYMBOL(disable_hlt);
60
61void enable_hlt(void)
62{
63 hlt_counter--;
64}
65
66EXPORT_SYMBOL(enable_hlt);
67
68/*
69 * We use this is we don't have any better
70 * idle routine..
71 */
72void default_idle(void)
73{
74 /* M32R_FIXME: Please use "cpu_sleep" mode. */
75 cpu_relax();
76}
77
78/*
79 * On SMP it's slightly faster (but much more power-consuming!)
80 * to poll the ->work.need_resched flag instead of waiting for the
81 * cross-CPU IPI to arrive. Use this option with caution.
82 */
83static void poll_idle (void)
84{
85 /* M32R_FIXME */
86 cpu_relax();
87}
88
89/*
90 * The idle thread. There's no useful work to be
91 * done, so just try to conserve power and have a
92 * low exit latency (ie sit in a loop waiting for
93 * somebody to say that they'd like to reschedule)
94 */
95void cpu_idle (void)
96{
97 /* endless idle loop with no priority at all */
98 while (1) {
99 while (!need_resched()) {
100 void (*idle)(void) = pm_idle;
101
102 if (!idle)
103 idle = default_idle;
104
105 idle();
106 }
107 schedule();
108 }
109}
110
111void machine_restart(char *__unused)
112{
113 printk("Please push reset button!\n");
114 while (1)
115 cpu_relax();
116}
117
118EXPORT_SYMBOL(machine_restart);
119
120void machine_halt(void)
121{
122 printk("Please push reset button!\n");
123 while (1)
124 cpu_relax();
125}
126
127EXPORT_SYMBOL(machine_halt);
128
129void machine_power_off(void)
130{
131 /* M32R_FIXME */
132}
133
134EXPORT_SYMBOL(machine_power_off);
135
136static int __init idle_setup (char *str)
137{
138 if (!strncmp(str, "poll", 4)) {
139 printk("using poll in idle threads.\n");
140 pm_idle = poll_idle;
141 } else if (!strncmp(str, "sleep", 4)) {
142 printk("using sleep in idle threads.\n");
143 pm_idle = default_idle;
144 }
145
146 return 1;
147}
148
149__setup("idle=", idle_setup);
150
151void show_regs(struct pt_regs * regs)
152{
153 printk("\n");
154 printk("BPC[%08lx]:PSW[%08lx]:LR [%08lx]:FP [%08lx]\n", \
155 regs->bpc, regs->psw, regs->lr, regs->fp);
156 printk("BBPC[%08lx]:BBPSW[%08lx]:SPU[%08lx]:SPI[%08lx]\n", \
157 regs->bbpc, regs->bbpsw, regs->spu, regs->spi);
158 printk("R0 [%08lx]:R1 [%08lx]:R2 [%08lx]:R3 [%08lx]\n", \
159 regs->r0, regs->r1, regs->r2, regs->r3);
160 printk("R4 [%08lx]:R5 [%08lx]:R6 [%08lx]:R7 [%08lx]\n", \
161 regs->r4, regs->r5, regs->r6, regs->r7);
162 printk("R8 [%08lx]:R9 [%08lx]:R10[%08lx]:R11[%08lx]\n", \
163 regs->r8, regs->r9, regs->r10, regs->r11);
164 printk("R12[%08lx]\n", \
165 regs->r12);
166
167#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
168 printk("ACC0H[%08lx]:ACC0L[%08lx]\n", \
169 regs->acc0h, regs->acc0l);
170 printk("ACC1H[%08lx]:ACC1L[%08lx]\n", \
171 regs->acc1h, regs->acc1l);
172#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
173 printk("ACCH[%08lx]:ACCL[%08lx]\n", \
174 regs->acch, regs->accl);
175#else
176#error unknown isa configuration
177#endif
178}
179
180/*
181 * Create a kernel thread
182 */
183
184/*
185 * This is the mechanism for creating a new kernel thread.
186 *
187 * NOTE! Only a kernel-only process(ie the swapper or direct descendants
188 * who haven't done an "execve()") should use this: it will work within
189 * a system call from a "real" process, but the process memory space will
190 * not be free'd until both the parent and the child have exited.
191 */
192static void kernel_thread_helper(void *nouse, int (*fn)(void *), void *arg)
193{
194 fn(arg);
195 do_exit(-1);
196}
197
198int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
199{
200 struct pt_regs regs;
201
202 memset(&regs, 0, sizeof (regs));
203 regs.r1 = (unsigned long)fn;
204 regs.r2 = (unsigned long)arg;
205
206 regs.bpc = (unsigned long)kernel_thread_helper;
207
208 regs.psw = M32R_PSW_BIE;
209
210 /* Ok, create the new process. */
211 return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL,
212 NULL);
213}
214
215/*
216 * Free current thread data structures etc..
217 */
218void exit_thread(void)
219{
220 /* Nothing to do. */
221 DPRINTK("pid = %d\n", current->pid);
222}
223
224void flush_thread(void)
225{
226 DPRINTK("pid = %d\n", current->pid);
227 memset(&current->thread.debug_trap, 0, sizeof(struct debug_trap));
228}
229
230void release_thread(struct task_struct *dead_task)
231{
232 /* do nothing */
233 DPRINTK("pid = %d\n", dead_task->pid);
234}
235
236/* Fill in the fpu structure for a core dump.. */
237int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
238{
239 return 0; /* Task didn't use the fpu at all. */
240}
241
242int copy_thread(int nr, unsigned long clone_flags, unsigned long spu,
243 unsigned long unused, struct task_struct *tsk, struct pt_regs *regs)
244{
245 struct pt_regs *childregs;
246 unsigned long sp = (unsigned long)tsk->thread_info + THREAD_SIZE;
247 extern void ret_from_fork(void);
248
249 /* Copy registers */
250 sp -= sizeof (struct pt_regs);
251 childregs = (struct pt_regs *)sp;
252 *childregs = *regs;
253
254 childregs->spu = spu;
255 childregs->r0 = 0; /* Child gets zero as return value */
256 regs->r0 = tsk->pid;
257 tsk->thread.sp = (unsigned long)childregs;
258 tsk->thread.lr = (unsigned long)ret_from_fork;
259
260 return 0;
261}
262
263/*
264 * fill in the user structure for a core dump..
265 */
266void dump_thread(struct pt_regs * regs, struct user * dump)
267{
268 /* M32R_FIXME */
269}
270
271/*
272 * Capture the user space registers if the task is not running (in user space)
273 */
274int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
275{
276 /* M32R_FIXME */
277 return 1;
278}
279
280asmlinkage int sys_fork(unsigned long r0, unsigned long r1, unsigned long r2,
281 unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6,
282 struct pt_regs regs)
283{
284#ifdef CONFIG_MMU
285 return do_fork(SIGCHLD, regs.spu, &regs, 0, NULL, NULL);
286#else
287 return -EINVAL;
288#endif /* CONFIG_MMU */
289}
290
291asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
292 unsigned long parent_tidptr,
293 unsigned long child_tidptr,
294 unsigned long r4, unsigned long r5, unsigned long r6,
295 struct pt_regs regs)
296{
297 if (!newsp)
298 newsp = regs.spu;
299
300 return do_fork(clone_flags, newsp, &regs, 0,
301 (int __user *)parent_tidptr, (int __user *)child_tidptr);
302}
303
304/*
305 * This is trivial, and on the face of it looks like it
306 * could equally well be done in user mode.
307 *
308 * Not so, for quite unobvious reasons - register pressure.
309 * In user mode vfork() cannot have a stack frame, and if
310 * done by calling the "clone()" system call directly, you
311 * do not have enough call-clobbered registers to hold all
312 * the information you need.
313 */
314asmlinkage int sys_vfork(unsigned long r0, unsigned long r1, unsigned long r2,
315 unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6,
316 struct pt_regs regs)
317{
318 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.spu, &regs, 0,
319 NULL, NULL);
320}
321
322/*
323 * sys_execve() executes a new program.
324 */
325asmlinkage int sys_execve(char __user *ufilename, char __user * __user *uargv,
326 char __user * __user *uenvp,
327 unsigned long r3, unsigned long r4, unsigned long r5,
328 unsigned long r6, struct pt_regs regs)
329{
330 int error;
331 char *filename;
332
333 filename = getname(ufilename);
334 error = PTR_ERR(filename);
335 if (IS_ERR(filename))
336 goto out;
337
338 error = do_execve(filename, uargv, uenvp, &regs);
339 if (error == 0) {
340 task_lock(current);
341 current->ptrace &= ~PT_DTRACE;
342 task_unlock(current);
343 }
344 putname(filename);
345out:
346 return error;
347}
348
349/*
350 * These bracket the sleeping functions..
351 */
352#define first_sched ((unsigned long) scheduling_functions_start_here)
353#define last_sched ((unsigned long) scheduling_functions_end_here)
354
355unsigned long get_wchan(struct task_struct *p)
356{
357 /* M32R_FIXME */
358 return (0);
359}
diff --git a/arch/m32r/kernel/ptrace.c b/arch/m32r/kernel/ptrace.c
new file mode 100644
index 000000000000..8b40f362dd6f
--- /dev/null
+++ b/arch/m32r/kernel/ptrace.c
@@ -0,0 +1,829 @@
1/*
2 * linux/arch/m32r/kernel/ptrace.c
3 *
4 * Copyright (C) 2002 Hirokazu Takata, Takeo Takahashi
5 * Copyright (C) 2004 Hirokazu Takata, Kei Sakamoto
6 *
7 * Original x86 implementation:
8 * By Ross Biro 1/23/92
9 * edited by Linus Torvalds
10 *
11 * Some code taken from sh version:
12 * Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka
13 * Some code taken from arm version:
14 * Copyright (C) 2000 Russell King
15 */
16
17#include <linux/config.h>
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/string.h>
27
28#include <asm/cacheflush.h>
29#include <asm/io.h>
30#include <asm/uaccess.h>
31#include <asm/pgtable.h>
32#include <asm/system.h>
33#include <asm/processor.h>
34#include <asm/mmu_context.h>
35
36/*
37 * Get the address of the live pt_regs for the specified task.
38 * These are saved onto the top kernel stack when the process
39 * is not running.
40 *
41 * Note: if a user thread is execve'd from kernel space, the
42 * kernel stack will not be empty on entry to the kernel, so
43 * ptracing these tasks will fail.
44 */
45static inline struct pt_regs *
46get_user_regs(struct task_struct *task)
47{
48 return (struct pt_regs *)
49 ((unsigned long)task->thread_info + THREAD_SIZE
50 - sizeof(struct pt_regs));
51}
52
53/*
54 * This routine will get a word off of the process kernel stack.
55 */
56static inline unsigned long int
57get_stack_long(struct task_struct *task, int offset)
58{
59 unsigned long *stack;
60
61 stack = (unsigned long *)get_user_regs(task);
62
63 return stack[offset];
64}
65
66/*
67 * This routine will put a word on the process kernel stack.
68 */
69static inline int
70put_stack_long(struct task_struct *task, int offset, unsigned long data)
71{
72 unsigned long *stack;
73
74 stack = (unsigned long *)get_user_regs(task);
75 stack[offset] = data;
76
77 return 0;
78}
79
80static int reg_offset[] = {
81 PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5, PT_R6, PT_R7,
82 PT_R8, PT_R9, PT_R10, PT_R11, PT_R12, PT_FP, PT_LR, PT_SPU,
83};
84
85/*
86 * Read the word at offset "off" into the "struct user". We
87 * actually access the pt_regs stored on the kernel stack.
88 */
89static int ptrace_read_user(struct task_struct *tsk, unsigned long off,
90 unsigned long __user *data)
91{
92 unsigned long tmp;
93#ifndef NO_FPU
94 struct user * dummy = NULL;
95#endif
96
97 if ((off & 3) || (off < 0) || (off > sizeof(struct user) - 3))
98 return -EIO;
99
100 off >>= 2;
101 switch (off) {
102 case PT_EVB:
103 __asm__ __volatile__ (
104 "mvfc %0, cr5 \n\t"
105 : "=r" (tmp)
106 );
107 break;
108 case PT_CBR: {
109 unsigned long psw;
110 psw = get_stack_long(tsk, PT_PSW);
111 tmp = ((psw >> 8) & 1);
112 }
113 break;
114 case PT_PSW: {
115 unsigned long psw, bbpsw;
116 psw = get_stack_long(tsk, PT_PSW);
117 bbpsw = get_stack_long(tsk, PT_BBPSW);
118 tmp = ((psw >> 8) & 0xff) | ((bbpsw & 0xff) << 8);
119 }
120 break;
121 case PT_PC:
122 tmp = get_stack_long(tsk, PT_BPC);
123 break;
124 case PT_BPC:
125 off = PT_BBPC;
126 /* fall through */
127 default:
128 if (off < (sizeof(struct pt_regs) >> 2))
129 tmp = get_stack_long(tsk, off);
130#ifndef NO_FPU
131 else if (off >= (long)(&dummy->fpu >> 2) &&
132 off < (long)(&dummy->u_fpvalid >> 2)) {
133 if (!tsk_used_math(tsk)) {
134 if (off == (long)(&dummy->fpu.fpscr >> 2))
135 tmp = FPSCR_INIT;
136 else
137 tmp = 0;
138 } else
139 tmp = ((long *)(&tsk->thread.fpu >> 2))
140 [off - (long)&dummy->fpu];
141 } else if (off == (long)(&dummy->u_fpvalid >> 2))
142 tmp = !!tsk_used_math(tsk);
143#endif /* not NO_FPU */
144 else
145 tmp = 0;
146 }
147
148 return put_user(tmp, data);
149}
150
151static int ptrace_write_user(struct task_struct *tsk, unsigned long off,
152 unsigned long data)
153{
154 int ret = -EIO;
155#ifndef NO_FPU
156 struct user * dummy = NULL;
157#endif
158
159 if ((off & 3) || off < 0 ||
160 off > sizeof(struct user) - 3)
161 return -EIO;
162
163 off >>= 2;
164 switch (off) {
165 case PT_EVB:
166 case PT_BPC:
167 case PT_SPI:
168 /* We don't allow to modify evb. */
169 ret = 0;
170 break;
171 case PT_PSW:
172 case PT_CBR: {
173 /* We allow to modify only cbr in psw */
174 unsigned long psw;
175 psw = get_stack_long(tsk, PT_PSW);
176 psw = (psw & ~0x100) | ((data & 1) << 8);
177 ret = put_stack_long(tsk, PT_PSW, psw);
178 }
179 break;
180 case PT_PC:
181 off = PT_BPC;
182 data &= ~1;
183 /* fall through */
184 default:
185 if (off < (sizeof(struct pt_regs) >> 2))
186 ret = put_stack_long(tsk, off, data);
187#ifndef NO_FPU
188 else if (off >= (long)(&dummy->fpu >> 2) &&
189 off < (long)(&dummy->u_fpvalid >> 2)) {
190 set_stopped_child_used_math(tsk);
191 ((long *)&tsk->thread.fpu)
192 [off - (long)&dummy->fpu] = data;
193 ret = 0;
194 } else if (off == (long)(&dummy->u_fpvalid >> 2)) {
195 conditional_stopped_child_used_math(data, tsk);
196 ret = 0;
197 }
198#endif /* not NO_FPU */
199 break;
200 }
201
202 return ret;
203}
204
205/*
206 * Get all user integer registers.
207 */
208static int ptrace_getregs(struct task_struct *tsk, void __user *uregs)
209{
210 struct pt_regs *regs = get_user_regs(tsk);
211
212 return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0;
213}
214
215/*
216 * Set all user integer registers.
217 */
218static int ptrace_setregs(struct task_struct *tsk, void __user *uregs)
219{
220 struct pt_regs newregs;
221 int ret;
222
223 ret = -EFAULT;
224 if (copy_from_user(&newregs, uregs, sizeof(struct pt_regs)) == 0) {
225 struct pt_regs *regs = get_user_regs(tsk);
226 *regs = newregs;
227 ret = 0;
228 }
229
230 return ret;
231}
232
233
234static inline int
235check_condition_bit(struct task_struct *child)
236{
237 return (int)((get_stack_long(child, PT_PSW) >> 8) & 1);
238}
239
240static int
241check_condition_src(unsigned long op, unsigned long regno1,
242 unsigned long regno2, struct task_struct *child)
243{
244 unsigned long reg1, reg2;
245
246 reg2 = get_stack_long(child, reg_offset[regno2]);
247
248 switch (op) {
249 case 0x0: /* BEQ */
250 reg1 = get_stack_long(child, reg_offset[regno1]);
251 return reg1 == reg2;
252 case 0x1: /* BNE */
253 reg1 = get_stack_long(child, reg_offset[regno1]);
254 return reg1 != reg2;
255 case 0x8: /* BEQZ */
256 return reg2 == 0;
257 case 0x9: /* BNEZ */
258 return reg2 != 0;
259 case 0xa: /* BLTZ */
260 return (int)reg2 < 0;
261 case 0xb: /* BGEZ */
262 return (int)reg2 >= 0;
263 case 0xc: /* BLEZ */
264 return (int)reg2 <= 0;
265 case 0xd: /* BGTZ */
266 return (int)reg2 > 0;
267 default:
268 /* never reached */
269 return 0;
270 }
271}
272
273static void
274compute_next_pc_for_16bit_insn(unsigned long insn, unsigned long pc,
275 unsigned long *next_pc,
276 struct task_struct *child)
277{
278 unsigned long op, op2, op3;
279 unsigned long disp;
280 unsigned long regno;
281 int parallel = 0;
282
283 if (insn & 0x00008000)
284 parallel = 1;
285 if (pc & 3)
286 insn &= 0x7fff; /* right slot */
287 else
288 insn >>= 16; /* left slot */
289
290 op = (insn >> 12) & 0xf;
291 op2 = (insn >> 8) & 0xf;
292 op3 = (insn >> 4) & 0xf;
293
294 if (op == 0x7) {
295 switch (op2) {
296 case 0xd: /* BNC */
297 case 0x9: /* BNCL */
298 if (!check_condition_bit(child)) {
299 disp = (long)(insn << 24) >> 22;
300 *next_pc = (pc & ~0x3) + disp;
301 return;
302 }
303 break;
304 case 0x8: /* BCL */
305 case 0xc: /* BC */
306 if (check_condition_bit(child)) {
307 disp = (long)(insn << 24) >> 22;
308 *next_pc = (pc & ~0x3) + disp;
309 return;
310 }
311 break;
312 case 0xe: /* BL */
313 case 0xf: /* BRA */
314 disp = (long)(insn << 24) >> 22;
315 *next_pc = (pc & ~0x3) + disp;
316 return;
317 break;
318 }
319 } else if (op == 0x1) {
320 switch (op2) {
321 case 0x0:
322 if (op3 == 0xf) { /* TRAP */
323#if 1
324 /* pass through */
325#else
326 /* kernel space is not allowed as next_pc */
327 unsigned long evb;
328 unsigned long trapno;
329 trapno = insn & 0xf;
330 __asm__ __volatile__ (
331 "mvfc %0, cr5\n"
332 :"=r"(evb)
333 :
334 );
335 *next_pc = evb + (trapno << 2);
336 return;
337#endif
338 } else if (op3 == 0xd) { /* RTE */
339 *next_pc = get_stack_long(child, PT_BPC);
340 return;
341 }
342 break;
343 case 0xc: /* JC */
344 if (op3 == 0xc && check_condition_bit(child)) {
345 regno = insn & 0xf;
346 *next_pc = get_stack_long(child,
347 reg_offset[regno]);
348 return;
349 }
350 break;
351 case 0xd: /* JNC */
352 if (op3 == 0xc && !check_condition_bit(child)) {
353 regno = insn & 0xf;
354 *next_pc = get_stack_long(child,
355 reg_offset[regno]);
356 return;
357 }
358 break;
359 case 0xe: /* JL */
360 case 0xf: /* JMP */
361 if (op3 == 0xc) { /* JMP */
362 regno = insn & 0xf;
363 *next_pc = get_stack_long(child,
364 reg_offset[regno]);
365 return;
366 }
367 break;
368 }
369 }
370 if (parallel)
371 *next_pc = pc + 4;
372 else
373 *next_pc = pc + 2;
374}
375
376static void
377compute_next_pc_for_32bit_insn(unsigned long insn, unsigned long pc,
378 unsigned long *next_pc,
379 struct task_struct *child)
380{
381 unsigned long op;
382 unsigned long op2;
383 unsigned long disp;
384 unsigned long regno1, regno2;
385
386 op = (insn >> 28) & 0xf;
387 if (op == 0xf) { /* branch 24-bit relative */
388 op2 = (insn >> 24) & 0xf;
389 switch (op2) {
390 case 0xd: /* BNC */
391 case 0x9: /* BNCL */
392 if (!check_condition_bit(child)) {
393 disp = (long)(insn << 8) >> 6;
394 *next_pc = (pc & ~0x3) + disp;
395 return;
396 }
397 break;
398 case 0x8: /* BCL */
399 case 0xc: /* BC */
400 if (check_condition_bit(child)) {
401 disp = (long)(insn << 8) >> 6;
402 *next_pc = (pc & ~0x3) + disp;
403 return;
404 }
405 break;
406 case 0xe: /* BL */
407 case 0xf: /* BRA */
408 disp = (long)(insn << 8) >> 6;
409 *next_pc = (pc & ~0x3) + disp;
410 return;
411 }
412 } else if (op == 0xb) { /* branch 16-bit relative */
413 op2 = (insn >> 20) & 0xf;
414 switch (op2) {
415 case 0x0: /* BEQ */
416 case 0x1: /* BNE */
417 case 0x8: /* BEQZ */
418 case 0x9: /* BNEZ */
419 case 0xa: /* BLTZ */
420 case 0xb: /* BGEZ */
421 case 0xc: /* BLEZ */
422 case 0xd: /* BGTZ */
423 regno1 = ((insn >> 24) & 0xf);
424 regno2 = ((insn >> 16) & 0xf);
425 if (check_condition_src(op2, regno1, regno2, child)) {
426 disp = (long)(insn << 16) >> 14;
427 *next_pc = (pc & ~0x3) + disp;
428 return;
429 }
430 break;
431 }
432 }
433 *next_pc = pc + 4;
434}
435
436static inline void
437compute_next_pc(unsigned long insn, unsigned long pc,
438 unsigned long *next_pc, struct task_struct *child)
439{
440 if (insn & 0x80000000)
441 compute_next_pc_for_32bit_insn(insn, pc, next_pc, child);
442 else
443 compute_next_pc_for_16bit_insn(insn, pc, next_pc, child);
444}
445
446static int
447register_debug_trap(struct task_struct *child, unsigned long next_pc,
448 unsigned long next_insn, unsigned long *code)
449{
450 struct debug_trap *p = &child->thread.debug_trap;
451 unsigned long addr = next_pc & ~3;
452
453 if (p->nr_trap == MAX_TRAPS) {
454 printk("kernel BUG at %s %d: p->nr_trap = %d\n",
455 __FILE__, __LINE__, p->nr_trap);
456 return -1;
457 }
458 p->addr[p->nr_trap] = addr;
459 p->insn[p->nr_trap] = next_insn;
460 p->nr_trap++;
461 if (next_pc & 3) {
462 *code = (next_insn & 0xffff0000) | 0x10f1;
463 /* xxx --> TRAP1 */
464 } else {
465 if ((next_insn & 0x80000000) || (next_insn & 0x8000)) {
466 *code = 0x10f17000;
467 /* TRAP1 --> NOP */
468 } else {
469 *code = (next_insn & 0xffff) | 0x10f10000;
470 /* TRAP1 --> xxx */
471 }
472 }
473 return 0;
474}
475
476static int
477unregister_debug_trap(struct task_struct *child, unsigned long addr,
478 unsigned long *code)
479{
480 struct debug_trap *p = &child->thread.debug_trap;
481 int i;
482
483 /* Search debug trap entry. */
484 for (i = 0; i < p->nr_trap; i++) {
485 if (p->addr[i] == addr)
486 break;
487 }
488 if (i >= p->nr_trap) {
489 /* The trap may be requested from debugger.
490 * ptrace should do nothing in this case.
491 */
492 return 0;
493 }
494
495 /* Recover orignal instruction code. */
496 *code = p->insn[i];
497
498 /* Shift debug trap entries. */
499 while (i < p->nr_trap - 1) {
500 p->insn[i] = p->insn[i + 1];
501 p->addr[i] = p->addr[i + 1];
502 i++;
503 }
504 p->nr_trap--;
505 return 1;
506}
507
508static void
509unregister_all_debug_traps(struct task_struct *child)
510{
511 struct debug_trap *p = &child->thread.debug_trap;
512 int i;
513
514 for (i = 0; i < p->nr_trap; i++)
515 access_process_vm(child, p->addr[i], &p->insn[i], sizeof(p->insn[i]), 1);
516 p->nr_trap = 0;
517}
518
519static inline void
520invalidate_cache(void)
521{
522#if defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_OPSP)
523
524 _flush_cache_copyback_all();
525
526#else /* ! CONFIG_CHIP_M32700 */
527
528 /* Invalidate cache */
529 __asm__ __volatile__ (
530 "ldi r0, #-1 \n\t"
531 "ldi r1, #0 \n\t"
532 "stb r1, @r0 ; cache off \n\t"
533 "; \n\t"
534 "ldi r0, #-2 \n\t"
535 "ldi r1, #1 \n\t"
536 "stb r1, @r0 ; cache invalidate \n\t"
537 ".fillinsn \n"
538 "0: \n\t"
539 "ldb r1, @r0 ; invalidate check \n\t"
540 "bnez r1, 0b \n\t"
541 "; \n\t"
542 "ldi r0, #-1 \n\t"
543 "ldi r1, #1 \n\t"
544 "stb r1, @r0 ; cache on \n\t"
545 : : : "r0", "r1", "memory"
546 );
547 /* FIXME: copying-back d-cache and invalidating i-cache are needed.
548 */
549#endif /* CONFIG_CHIP_M32700 */
550}
551
552/* Embed a debug trap (TRAP1) code */
553static int
554embed_debug_trap(struct task_struct *child, unsigned long next_pc)
555{
556 unsigned long next_insn, code;
557 unsigned long addr = next_pc & ~3;
558
559 if (access_process_vm(child, addr, &next_insn, sizeof(next_insn), 0)
560 != sizeof(next_insn)) {
561 return -1; /* error */
562 }
563
564 /* Set a trap code. */
565 if (register_debug_trap(child, next_pc, next_insn, &code)) {
566 return -1; /* error */
567 }
568 if (access_process_vm(child, addr, &code, sizeof(code), 1)
569 != sizeof(code)) {
570 return -1; /* error */
571 }
572 return 0; /* success */
573}
574
575void
576withdraw_debug_trap(struct pt_regs *regs)
577{
578 unsigned long addr;
579 unsigned long code;
580
581 addr = (regs->bpc - 2) & ~3;
582 regs->bpc -= 2;
583 if (unregister_debug_trap(current, addr, &code)) {
584 access_process_vm(current, addr, &code, sizeof(code), 1);
585 invalidate_cache();
586 }
587}
588
589static void
590init_debug_traps(struct task_struct *child)
591{
592 struct debug_trap *p = &child->thread.debug_trap;
593 int i;
594 p->nr_trap = 0;
595 for (i = 0; i < MAX_TRAPS; i++) {
596 p->addr[i] = 0;
597 p->insn[i] = 0;
598 }
599}
600
601
602/*
603 * Called by kernel/ptrace.c when detaching..
604 *
605 * Make sure single step bits etc are not set.
606 */
607void ptrace_disable(struct task_struct *child)
608{
609 /* nothing to do.. */
610}
611
612static int
613do_ptrace(long request, struct task_struct *child, long addr, long data)
614{
615 unsigned long tmp;
616 int ret;
617
618 switch (request) {
619 /*
620 * read word at location "addr" in the child process.
621 */
622 case PTRACE_PEEKTEXT:
623 case PTRACE_PEEKDATA:
624 ret = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
625 if (ret == sizeof(tmp))
626 ret = put_user(tmp,(unsigned long __user *) data);
627 else
628 ret = -EIO;
629 break;
630
631 /*
632 * read the word at location addr in the USER area.
633 */
634 case PTRACE_PEEKUSR:
635 ret = ptrace_read_user(child, addr,
636 (unsigned long __user *)data);
637 break;
638
639 /*
640 * write the word at location addr.
641 */
642 case PTRACE_POKETEXT:
643 case PTRACE_POKEDATA:
644 ret = access_process_vm(child, addr, &data, sizeof(data), 1);
645 if (ret == sizeof(data)) {
646 ret = 0;
647 if (request == PTRACE_POKETEXT) {
648 invalidate_cache();
649 }
650 } else {
651 ret = -EIO;
652 }
653 break;
654
655 /*
656 * write the word at location addr in the USER area.
657 */
658 case PTRACE_POKEUSR:
659 ret = ptrace_write_user(child, addr, data);
660 break;
661
662 /*
663 * continue/restart and stop at next (return from) syscall
664 */
665 case PTRACE_SYSCALL:
666 case PTRACE_CONT:
667 ret = -EIO;
668 if ((unsigned long) data > _NSIG)
669 break;
670 if (request == PTRACE_SYSCALL)
671 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
672 else
673 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
674 child->exit_code = data;
675 wake_up_process(child);
676 ret = 0;
677 break;
678
679 /*
680 * make the child exit. Best I can do is send it a sigkill.
681 * perhaps it should be put in the status that it wants to
682 * exit.
683 */
684 case PTRACE_KILL: {
685 ret = 0;
686 unregister_all_debug_traps(child);
687 invalidate_cache();
688 if (child->exit_state == EXIT_ZOMBIE) /* already dead */
689 break;
690 child->exit_code = SIGKILL;
691 wake_up_process(child);
692 break;
693 }
694
695 /*
696 * execute single instruction.
697 */
698 case PTRACE_SINGLESTEP: {
699 unsigned long next_pc;
700 unsigned long pc, insn;
701
702 ret = -EIO;
703 if ((unsigned long) data > _NSIG)
704 break;
705 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
706 if ((child->ptrace & PT_DTRACE) == 0) {
707 /* Spurious delayed TF traps may occur */
708 child->ptrace |= PT_DTRACE;
709 }
710
711 /* Compute next pc. */
712 pc = get_stack_long(child, PT_BPC);
713
714 if (access_process_vm(child, pc&~3, &insn, sizeof(insn), 0)
715 != sizeof(insn))
716 break;
717
718 compute_next_pc(insn, pc, &next_pc, child);
719 if (next_pc & 0x80000000)
720 break;
721
722 if (embed_debug_trap(child, next_pc))
723 break;
724
725 invalidate_cache();
726 child->exit_code = data;
727
728 /* give it a chance to run. */
729 wake_up_process(child);
730 ret = 0;
731 break;
732 }
733
734 /*
735 * detach a process that was attached.
736 */
737 case PTRACE_DETACH:
738 ret = 0;
739 ret = ptrace_detach(child, data);
740 break;
741
742 case PTRACE_GETREGS:
743 ret = ptrace_getregs(child, (void __user *)data);
744 break;
745
746 case PTRACE_SETREGS:
747 ret = ptrace_setregs(child, (void __user *)data);
748 break;
749
750 default:
751 ret = ptrace_request(child, request, addr, data);
752 break;
753 }
754
755 return ret;
756}
757
758asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
759{
760 struct task_struct *child;
761 int ret;
762
763 lock_kernel();
764 ret = -EPERM;
765 if (request == PTRACE_TRACEME) {
766 /* are we already being traced? */
767 if (current->ptrace & PT_PTRACED)
768 goto out;
769 /* set the ptrace bit in the process flags. */
770 current->ptrace |= PT_PTRACED;
771 ret = 0;
772 goto out;
773 }
774 ret = -ESRCH;
775 read_lock(&tasklist_lock);
776 child = find_task_by_pid(pid);
777 if (child)
778 get_task_struct(child);
779 read_unlock(&tasklist_lock);
780 if (!child)
781 goto out;
782
783 ret = -EPERM;
784 if (pid == 1) /* you may not mess with init */
785 goto out;
786
787 if (request == PTRACE_ATTACH) {
788 ret = ptrace_attach(child);
789 if (ret == 0)
790 init_debug_traps(child);
791 goto out_tsk;
792 }
793
794 ret = ptrace_check_attach(child, request == PTRACE_KILL);
795 if (ret == 0)
796 ret = do_ptrace(request, child, addr, data);
797
798out_tsk:
799 put_task_struct(child);
800out:
801 unlock_kernel();
802
803 return ret;
804}
805
806/* notification of system call entry/exit
807 * - triggered by current->work.syscall_trace
808 */
809void do_syscall_trace(void)
810{
811 if (!test_thread_flag(TIF_SYSCALL_TRACE))
812 return;
813 if (!(current->ptrace & PT_PTRACED))
814 return;
815 /* the 0x80 provides a way for the tracing parent to distinguish
816 between a syscall stop and SIGTRAP delivery */
817 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
818 ? 0x80 : 0));
819
820 /*
821 * this isn't the same as continuing with a signal, but it will do
822 * for normal use. strace only continues with a signal if the
823 * stopping signal is not SIGTRAP. -brl
824 */
825 if (current->exit_code) {
826 send_sig(current->exit_code, current, 1);
827 current->exit_code = 0;
828 }
829}
diff --git a/arch/m32r/kernel/semaphore.c b/arch/m32r/kernel/semaphore.c
new file mode 100644
index 000000000000..9a6e6d754ddc
--- /dev/null
+++ b/arch/m32r/kernel/semaphore.c
@@ -0,0 +1,186 @@
1/*
2 * linux/arch/m32r/semaphore.c
3 * orig : i386 2.6.4
4 *
5 * M32R semaphore implementation.
6 *
7 * Copyright (c) 2002 - 2004 Hitoshi Yamamoto
8 */
9
10/*
11 * i386 semaphore implementation.
12 *
13 * (C) Copyright 1999 Linus Torvalds
14 *
15 * Portions Copyright 1999 Red Hat, Inc.
16 *
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation; either version
20 * 2 of the License, or (at your option) any later version.
21 *
22 * rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl@kvack.org>
23 */
24#include <linux/config.h>
25#include <linux/sched.h>
26#include <linux/err.h>
27#include <linux/init.h>
28#include <asm/semaphore.h>
29
30/*
31 * Semaphores are implemented using a two-way counter:
32 * The "count" variable is decremented for each process
33 * that tries to acquire the semaphore, while the "sleeping"
34 * variable is a count of such acquires.
35 *
36 * Notably, the inline "up()" and "down()" functions can
37 * efficiently test if they need to do any extra work (up
38 * needs to do something only if count was negative before
39 * the increment operation.
40 *
41 * "sleeping" and the contention routine ordering is protected
42 * by the spinlock in the semaphore's waitqueue head.
43 *
44 * Note that these functions are only called when there is
45 * contention on the lock, and as such all this is the
46 * "non-critical" part of the whole semaphore business. The
47 * critical part is the inline stuff in <asm/semaphore.h>
48 * where we want to avoid any extra jumps and calls.
49 */
50
51/*
52 * Logic:
53 * - only on a boundary condition do we need to care. When we go
54 * from a negative count to a non-negative, we wake people up.
55 * - when we go from a non-negative count to a negative do we
56 * (a) synchronize with the "sleeper" count and (b) make sure
57 * that we're on the wakeup list before we synchronize so that
58 * we cannot lose wakeup events.
59 */
60
61asmlinkage void __up(struct semaphore *sem)
62{
63 wake_up(&sem->wait);
64}
65
66asmlinkage void __sched __down(struct semaphore * sem)
67{
68 struct task_struct *tsk = current;
69 DECLARE_WAITQUEUE(wait, tsk);
70 unsigned long flags;
71
72 tsk->state = TASK_UNINTERRUPTIBLE;
73 spin_lock_irqsave(&sem->wait.lock, flags);
74 add_wait_queue_exclusive_locked(&sem->wait, &wait);
75
76 sem->sleepers++;
77 for (;;) {
78 int sleepers = sem->sleepers;
79
80 /*
81 * Add "everybody else" into it. They aren't
82 * playing, because we own the spinlock in
83 * the wait_queue_head.
84 */
85 if (!atomic_add_negative(sleepers - 1, &sem->count)) {
86 sem->sleepers = 0;
87 break;
88 }
89 sem->sleepers = 1; /* us - see -1 above */
90 spin_unlock_irqrestore(&sem->wait.lock, flags);
91
92 schedule();
93
94 spin_lock_irqsave(&sem->wait.lock, flags);
95 tsk->state = TASK_UNINTERRUPTIBLE;
96 }
97 remove_wait_queue_locked(&sem->wait, &wait);
98 wake_up_locked(&sem->wait);
99 spin_unlock_irqrestore(&sem->wait.lock, flags);
100 tsk->state = TASK_RUNNING;
101}
102
103asmlinkage int __sched __down_interruptible(struct semaphore * sem)
104{
105 int retval = 0;
106 struct task_struct *tsk = current;
107 DECLARE_WAITQUEUE(wait, tsk);
108 unsigned long flags;
109
110 tsk->state = TASK_INTERRUPTIBLE;
111 spin_lock_irqsave(&sem->wait.lock, flags);
112 add_wait_queue_exclusive_locked(&sem->wait, &wait);
113
114 sem->sleepers++;
115 for (;;) {
116 int sleepers = sem->sleepers;
117
118 /*
119 * With signals pending, this turns into
120 * the trylock failure case - we won't be
121 * sleeping, and we* can't get the lock as
122 * it has contention. Just correct the count
123 * and exit.
124 */
125 if (signal_pending(current)) {
126 retval = -EINTR;
127 sem->sleepers = 0;
128 atomic_add(sleepers, &sem->count);
129 break;
130 }
131
132 /*
133 * Add "everybody else" into it. They aren't
134 * playing, because we own the spinlock in
135 * wait_queue_head. The "-1" is because we're
136 * still hoping to get the semaphore.
137 */
138 if (!atomic_add_negative(sleepers - 1, &sem->count)) {
139 sem->sleepers = 0;
140 break;
141 }
142 sem->sleepers = 1; /* us - see -1 above */
143 spin_unlock_irqrestore(&sem->wait.lock, flags);
144
145 schedule();
146
147 spin_lock_irqsave(&sem->wait.lock, flags);
148 tsk->state = TASK_INTERRUPTIBLE;
149 }
150 remove_wait_queue_locked(&sem->wait, &wait);
151 wake_up_locked(&sem->wait);
152 spin_unlock_irqrestore(&sem->wait.lock, flags);
153
154 tsk->state = TASK_RUNNING;
155 return retval;
156}
157
158/*
159 * Trylock failed - make sure we correct for
160 * having decremented the count.
161 *
162 * We could have done the trylock with a
163 * single "cmpxchg" without failure cases,
164 * but then it wouldn't work on a 386.
165 */
166asmlinkage int __down_trylock(struct semaphore * sem)
167{
168 int sleepers;
169 unsigned long flags;
170
171 spin_lock_irqsave(&sem->wait.lock, flags);
172 sleepers = sem->sleepers + 1;
173 sem->sleepers = 0;
174
175 /*
176 * Add "everybody else" and us into it. They aren't
177 * playing, because we own the spinlock in the
178 * wait_queue_head.
179 */
180 if (!atomic_add_negative(sleepers, &sem->count)) {
181 wake_up_locked(&sem->wait);
182 }
183
184 spin_unlock_irqrestore(&sem->wait.lock, flags);
185 return 1;
186}
diff --git a/arch/m32r/kernel/setup.c b/arch/m32r/kernel/setup.c
new file mode 100644
index 000000000000..4826cd6e40e8
--- /dev/null
+++ b/arch/m32r/kernel/setup.c
@@ -0,0 +1,420 @@
1/*
2 * linux/arch/m32r/kernel/setup.c
3 *
4 * Setup routines for Renesas M32R
5 *
6 * Copyright (c) 2001, 2002 Hiroyuki Kondo, Hirokazu Takata,
7 * Hitoshi Yamamoto
8 */
9
10#include <linux/config.h>
11#include <linux/init.h>
12#include <linux/stddef.h>
13#include <linux/fs.h>
14#include <linux/sched.h>
15#include <linux/ioport.h>
16#include <linux/mm.h>
17#include <linux/bootmem.h>
18#include <linux/console.h>
19#include <linux/initrd.h>
20#include <linux/major.h>
21#include <linux/root_dev.h>
22#include <linux/seq_file.h>
23#include <linux/timex.h>
24#include <linux/tty.h>
25#include <linux/cpu.h>
26#include <linux/nodemask.h>
27
28#include <asm/processor.h>
29#include <asm/pgtable.h>
30#include <asm/io.h>
31#include <asm/mmu_context.h>
32#include <asm/m32r.h>
33#include <asm/setup.h>
34#include <asm/sections.h>
35
36#ifdef CONFIG_MMU
37extern void init_mmu(void);
38#endif
39
40#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) \
41 || defined(CONFIG_BLK_DEV_IDE_MODULE) \
42 || defined(CONFIG_BLK_DEV_HD_MODULE)
43struct drive_info_struct { char dummy[32]; } drive_info;
44#endif
45
46extern char _end[];
47
48/*
49 * Machine setup..
50 */
51struct cpuinfo_m32r boot_cpu_data;
52
53#ifdef CONFIG_BLK_DEV_RAM
54extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */
55extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */
56extern int rd_image_start; /* starting block # of image */
57#endif
58
59#if defined(CONFIG_VGA_CONSOLE)
60struct screen_info screen_info = {
61 .orig_video_lines = 25,
62 .orig_video_cols = 80,
63 .orig_video_mode = 0,
64 .orig_video_ega_bx = 0,
65 .orig_video_isVGA = 1,
66 .orig_video_points = 8
67};
68#endif
69
70extern int root_mountflags;
71
72static char command_line[COMMAND_LINE_SIZE];
73
74static struct resource data_resource = {
75 .name = "Kernel data",
76 .start = 0,
77 .end = 0,
78 .flags = IORESOURCE_BUSY | IORESOURCE_MEM
79};
80
81static struct resource code_resource = {
82 .name = "Kernel code",
83 .start = 0,
84 .end = 0,
85 .flags = IORESOURCE_BUSY | IORESOURCE_MEM
86};
87
88unsigned long memory_start;
89unsigned long memory_end;
90
91void __init setup_arch(char **);
92int get_cpuinfo(char *);
93
94static __inline__ void parse_mem_cmdline(char ** cmdline_p)
95{
96 char c = ' ';
97 char *to = command_line;
98 char *from = COMMAND_LINE;
99 int len = 0;
100 int usermem = 0;
101
102 /* Save unparsed command line copy for /proc/cmdline */
103 memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
104 saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
105
106 memory_start = (unsigned long)CONFIG_MEMORY_START+PAGE_OFFSET;
107 memory_end = memory_start+(unsigned long)CONFIG_MEMORY_SIZE;
108
109 for ( ; ; ) {
110 if (c == ' ' && !memcmp(from, "mem=", 4)) {
111 if (to != command_line)
112 to--;
113
114 {
115 unsigned long mem_size;
116
117 usermem = 1;
118 mem_size = memparse(from+4, &from);
119 memory_end = memory_start + mem_size;
120 }
121 }
122 c = *(from++);
123 if (!c)
124 break;
125
126 if (COMMAND_LINE_SIZE <= ++len)
127 break;
128
129 *(to++) = c;
130 }
131 *to = '\0';
132 *cmdline_p = command_line;
133 if (usermem)
134 printk(KERN_INFO "user-defined physical RAM map:\n");
135}
136
137#ifndef CONFIG_DISCONTIGMEM
138static unsigned long __init setup_memory(void)
139{
140 unsigned long start_pfn, max_low_pfn, bootmap_size;
141
142 start_pfn = PFN_UP( __pa(_end) );
143 max_low_pfn = PFN_DOWN( __pa(memory_end) );
144
145 /*
146 * Initialize the boot-time allocator (with low memory only):
147 */
148 bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn,
149 CONFIG_MEMORY_START>>PAGE_SHIFT, max_low_pfn);
150
151 /*
152 * Register fully available low RAM pages with the bootmem allocator.
153 */
154 {
155 unsigned long curr_pfn;
156 unsigned long last_pfn;
157 unsigned long pages;
158
159 /*
160 * We are rounding up the start address of usable memory:
161 */
162 curr_pfn = PFN_UP(__pa(memory_start));
163
164 /*
165 * ... and at the end of the usable range downwards:
166 */
167 last_pfn = PFN_DOWN(__pa(memory_end));
168
169 if (last_pfn > max_low_pfn)
170 last_pfn = max_low_pfn;
171
172 pages = last_pfn - curr_pfn;
173 free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(pages));
174 }
175
176 /*
177 * Reserve the kernel text and
178 * Reserve the bootmem bitmap. We do this in two steps (first step
179 * was init_bootmem()), because this catches the (definitely buggy)
180 * case of us accidentally initializing the bootmem allocator with
181 * an invalid RAM area.
182 */
183 reserve_bootmem(CONFIG_MEMORY_START + PAGE_SIZE,
184 (PFN_PHYS(start_pfn) + bootmap_size + PAGE_SIZE - 1)
185 - CONFIG_MEMORY_START);
186
187 /*
188 * reserve physical page 0 - it's a special BIOS page on many boxes,
189 * enabling clean reboots, SMP operation, laptop functions.
190 */
191 reserve_bootmem(CONFIG_MEMORY_START, PAGE_SIZE);
192
193 /*
194 * reserve memory hole
195 */
196#ifdef CONFIG_MEMHOLE
197 reserve_bootmem(CONFIG_MEMHOLE_START, CONFIG_MEMHOLE_SIZE);
198#endif
199
200#ifdef CONFIG_BLK_DEV_INITRD
201 if (LOADER_TYPE && INITRD_START) {
202 if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
203 reserve_bootmem(INITRD_START, INITRD_SIZE);
204 initrd_start = INITRD_START ?
205 INITRD_START + PAGE_OFFSET : 0;
206
207 initrd_end = initrd_start + INITRD_SIZE;
208 printk("initrd:start[%08lx],size[%08lx]\n",
209 initrd_start, INITRD_SIZE);
210 } else {
211 printk("initrd extends beyond end of memory "
212 "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
213 INITRD_START + INITRD_SIZE,
214 max_low_pfn << PAGE_SHIFT);
215
216 initrd_start = 0;
217 }
218 }
219#endif
220
221 return max_low_pfn;
222}
223#else /* CONFIG_DISCONTIGMEM */
224extern unsigned long setup_memory(void);
225#endif /* CONFIG_DISCONTIGMEM */
226
227#define M32R_PCC_PCATCR 0x00ef7014 /* will move to m32r.h */
228
229void __init setup_arch(char **cmdline_p)
230{
231 ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
232
233 boot_cpu_data.cpu_clock = M32R_CPUCLK;
234 boot_cpu_data.bus_clock = M32R_BUSCLK;
235 boot_cpu_data.timer_divide = M32R_TIMER_DIVIDE;
236
237#ifdef CONFIG_BLK_DEV_RAM
238 rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
239 rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
240 rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
241#endif
242
243 if (!MOUNT_ROOT_RDONLY)
244 root_mountflags &= ~MS_RDONLY;
245
246#ifdef CONFIG_VT
247#if defined(CONFIG_VGA_CONSOLE)
248 conswitchp = &vga_con;
249#elif defined(CONFIG_DUMMY_CONSOLE)
250 conswitchp = &dummy_con;
251#endif
252#endif
253
254#ifdef CONFIG_DISCONTIGMEM
255 nodes_clear(node_online_map);
256 node_set_online(0);
257 node_set_online(1);
258#endif /* CONFIG_DISCONTIGMEM */
259
260 init_mm.start_code = (unsigned long) _text;
261 init_mm.end_code = (unsigned long) _etext;
262 init_mm.end_data = (unsigned long) _edata;
263 init_mm.brk = (unsigned long) _end;
264
265 code_resource.start = virt_to_phys(_text);
266 code_resource.end = virt_to_phys(_etext)-1;
267 data_resource.start = virt_to_phys(_etext);
268 data_resource.end = virt_to_phys(_edata)-1;
269
270 parse_mem_cmdline(cmdline_p);
271
272 setup_memory();
273
274 paging_init();
275}
276
277static struct cpu cpu[NR_CPUS];
278
279static int __init topology_init(void)
280{
281 int cpu_id;
282
283 for (cpu_id = 0; cpu_id < NR_CPUS; cpu_id++)
284 if (cpu_possible(cpu_id))
285 register_cpu(&cpu[cpu_id], cpu_id, NULL);
286
287 return 0;
288}
289
290subsys_initcall(topology_init);
291
292#ifdef CONFIG_PROC_FS
293/*
294 * Get CPU information for use by the procfs.
295 */
296static int show_cpuinfo(struct seq_file *m, void *v)
297{
298 struct cpuinfo_m32r *c = v;
299 unsigned long cpu = c - cpu_data;
300
301#ifdef CONFIG_SMP
302 if (!cpu_online(cpu))
303 return 0;
304#endif /* CONFIG_SMP */
305
306 seq_printf(m, "processor\t: %ld\n", cpu);
307
308#ifdef CONFIG_CHIP_VDEC2
309 seq_printf(m, "cpu family\t: VDEC2\n"
310 "cache size\t: Unknown\n");
311#elif CONFIG_CHIP_M32700
312 seq_printf(m,"cpu family\t: M32700\n"
313 "cache size\t: I-8KB/D-8KB\n");
314#elif CONFIG_CHIP_M32102
315 seq_printf(m,"cpu family\t: M32102\n"
316 "cache size\t: I-8KB\n");
317#elif CONFIG_CHIP_OPSP
318 seq_printf(m,"cpu family\t: OPSP\n"
319 "cache size\t: I-8KB/D-8KB\n");
320#elif CONFIG_CHIP_MP
321 seq_printf(m, "cpu family\t: M32R-MP\n"
322 "cache size\t: I-xxKB/D-xxKB\n");
323#else
324 seq_printf(m, "cpu family\t: Unknown\n");
325#endif
326 seq_printf(m, "bogomips\t: %lu.%02lu\n",
327 c->loops_per_jiffy/(500000/HZ),
328 (c->loops_per_jiffy/(5000/HZ)) % 100);
329#ifdef CONFIG_PLAT_MAPPI
330 seq_printf(m, "Machine\t\t: Mappi Evaluation board\n");
331#elif CONFIG_PLAT_MAPPI2
332 seq_printf(m, "Machine\t\t: Mappi-II Evaluation board\n");
333#elif CONFIG_PLAT_M32700UT
334 seq_printf(m, "Machine\t\t: M32700UT Evaluation board\n");
335#elif CONFIG_PLAT_OPSPUT
336 seq_printf(m, "Machine\t\t: OPSPUT Evaluation board\n");
337#elif CONFIG_PLAT_USRV
338 seq_printf(m, "Machine\t\t: uServer\n");
339#elif CONFIG_PLAT_OAKS32R
340 seq_printf(m, "Machine\t\t: OAKS32R\n");
341#else
342 seq_printf(m, "Machine\t\t: Unknown\n");
343#endif
344
345#define PRINT_CLOCK(name, value) \
346 seq_printf(m, name " clock\t: %d.%02dMHz\n", \
347 ((value) / 1000000), ((value) % 1000000)/10000)
348
349 PRINT_CLOCK("CPU", (int)c->cpu_clock);
350 PRINT_CLOCK("Bus", (int)c->bus_clock);
351
352 seq_printf(m, "\n");
353
354 return 0;
355}
356
357static void *c_start(struct seq_file *m, loff_t *pos)
358{
359 return *pos < NR_CPUS ? cpu_data + *pos : NULL;
360}
361
362static void *c_next(struct seq_file *m, void *v, loff_t *pos)
363{
364 ++*pos;
365 return c_start(m, pos);
366}
367
368static void c_stop(struct seq_file *m, void *v)
369{
370}
371
372struct seq_operations cpuinfo_op = {
373 start: c_start,
374 next: c_next,
375 stop: c_stop,
376 show: show_cpuinfo,
377};
378#endif /* CONFIG_PROC_FS */
379
380unsigned long cpu_initialized __initdata = 0;
381
382/*
383 * cpu_init() initializes state that is per-CPU. Some data is already
384 * initialized (naturally) in the bootstrap process.
385 * We reload them nevertheless, this function acts as a
386 * 'CPU state barrier', nothing should get across.
387 */
388#if defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_XNUX2) \
389 || defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_M32102) \
390 || defined(CONFIG_CHIP_OPSP)
391void __init cpu_init (void)
392{
393 int cpu_id = smp_processor_id();
394
395 if (test_and_set_bit(cpu_id, &cpu_initialized)) {
396 printk(KERN_WARNING "CPU#%d already initialized!\n", cpu_id);
397 for ( ; ; )
398 local_irq_enable();
399 }
400 printk(KERN_INFO "Initializing CPU#%d\n", cpu_id);
401
402 /* Set up and load the per-CPU TSS and LDT */
403 atomic_inc(&init_mm.mm_count);
404 current->active_mm = &init_mm;
405 if (current->mm)
406 BUG();
407
408 /* Force FPU initialization */
409 current_thread_info()->status = 0;
410 clear_used_math();
411
412#ifdef CONFIG_MMU
413 /* Set up MMU */
414 init_mmu();
415#endif
416
417 /* Set up ICUIMASK */
418 outl(0x00070000, M32R_ICU_IMASK_PORTL); /* imask=111 */
419}
420#endif /* defined(CONFIG_CHIP_VDEC2) ... */
diff --git a/arch/m32r/kernel/setup_m32700ut.c b/arch/m32r/kernel/setup_m32700ut.c
new file mode 100644
index 000000000000..488aa87bab76
--- /dev/null
+++ b/arch/m32r/kernel/setup_m32700ut.c
@@ -0,0 +1,478 @@
1/*
2 * linux/arch/m32r/kernel/setup_m32700ut.c
3 *
4 * Setup routines for Renesas M32700UT Board
5 *
6 * Copyright (c) 2002 Hiroyuki Kondo, Hirokazu Takata,
7 * Hitoshi Yamamoto, Takeo Takahashi
8 *
9 * This file is subject to the terms and conditions of the GNU General
10 * Public License. See the file "COPYING" in the main directory of this
11 * archive for more details.
12 */
13
14#include <linux/config.h>
15#include <linux/irq.h>
16#include <linux/kernel.h>
17#include <linux/init.h>
18#include <linux/device.h>
19
20#include <asm/system.h>
21#include <asm/m32r.h>
22#include <asm/io.h>
23
24/*
25 * M32700 Interrupt Control Unit (Level 1)
26 */
27#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
28
29#ifndef CONFIG_SMP
30typedef struct {
31 unsigned long icucr; /* ICU Control Register */
32} icu_data_t;
33#endif /* CONFIG_SMP */
34
35static icu_data_t icu_data[M32700UT_NUM_CPU_IRQ];
36
37static void disable_m32700ut_irq(unsigned int irq)
38{
39 unsigned long port, data;
40
41 port = irq2port(irq);
42 data = icu_data[irq].icucr|M32R_ICUCR_ILEVEL7;
43 outl(data, port);
44}
45
46static void enable_m32700ut_irq(unsigned int irq)
47{
48 unsigned long port, data;
49
50 port = irq2port(irq);
51 data = icu_data[irq].icucr|M32R_ICUCR_IEN|M32R_ICUCR_ILEVEL6;
52 outl(data, port);
53}
54
55static void mask_and_ack_m32700ut(unsigned int irq)
56{
57 disable_m32700ut_irq(irq);
58}
59
60static void end_m32700ut_irq(unsigned int irq)
61{
62 enable_m32700ut_irq(irq);
63}
64
65static unsigned int startup_m32700ut_irq(unsigned int irq)
66{
67 enable_m32700ut_irq(irq);
68 return (0);
69}
70
71static void shutdown_m32700ut_irq(unsigned int irq)
72{
73 unsigned long port;
74
75 port = irq2port(irq);
76 outl(M32R_ICUCR_ILEVEL7, port);
77}
78
79static struct hw_interrupt_type m32700ut_irq_type =
80{
81 "M32700UT-IRQ",
82 startup_m32700ut_irq,
83 shutdown_m32700ut_irq,
84 enable_m32700ut_irq,
85 disable_m32700ut_irq,
86 mask_and_ack_m32700ut,
87 end_m32700ut_irq
88};
89
90/*
91 * Interrupt Control Unit of PLD on M32700UT (Level 2)
92 */
93#define irq2pldirq(x) ((x) - M32700UT_PLD_IRQ_BASE)
94#define pldirq2port(x) (unsigned long)((int)PLD_ICUCR1 + \
95 (((x) - 1) * sizeof(unsigned short)))
96
97typedef struct {
98 unsigned short icucr; /* ICU Control Register */
99} pld_icu_data_t;
100
101static pld_icu_data_t pld_icu_data[M32700UT_NUM_PLD_IRQ];
102
103static void disable_m32700ut_pld_irq(unsigned int irq)
104{
105 unsigned long port, data;
106 unsigned int pldirq;
107
108 pldirq = irq2pldirq(irq);
109// disable_m32700ut_irq(M32R_IRQ_INT1);
110 port = pldirq2port(pldirq);
111 data = pld_icu_data[pldirq].icucr|PLD_ICUCR_ILEVEL7;
112 outw(data, port);
113}
114
115static void enable_m32700ut_pld_irq(unsigned int irq)
116{
117 unsigned long port, data;
118 unsigned int pldirq;
119
120 pldirq = irq2pldirq(irq);
121// enable_m32700ut_irq(M32R_IRQ_INT1);
122 port = pldirq2port(pldirq);
123 data = pld_icu_data[pldirq].icucr|PLD_ICUCR_IEN|PLD_ICUCR_ILEVEL6;
124 outw(data, port);
125}
126
127static void mask_and_ack_m32700ut_pld(unsigned int irq)
128{
129 disable_m32700ut_pld_irq(irq);
130// mask_and_ack_m32700ut(M32R_IRQ_INT1);
131}
132
133static void end_m32700ut_pld_irq(unsigned int irq)
134{
135 enable_m32700ut_pld_irq(irq);
136 end_m32700ut_irq(M32R_IRQ_INT1);
137}
138
139static unsigned int startup_m32700ut_pld_irq(unsigned int irq)
140{
141 enable_m32700ut_pld_irq(irq);
142 return (0);
143}
144
145static void shutdown_m32700ut_pld_irq(unsigned int irq)
146{
147 unsigned long port;
148 unsigned int pldirq;
149
150 pldirq = irq2pldirq(irq);
151// shutdown_m32700ut_irq(M32R_IRQ_INT1);
152 port = pldirq2port(pldirq);
153 outw(PLD_ICUCR_ILEVEL7, port);
154}
155
156static struct hw_interrupt_type m32700ut_pld_irq_type =
157{
158 "M32700UT-PLD-IRQ",
159 startup_m32700ut_pld_irq,
160 shutdown_m32700ut_pld_irq,
161 enable_m32700ut_pld_irq,
162 disable_m32700ut_pld_irq,
163 mask_and_ack_m32700ut_pld,
164 end_m32700ut_pld_irq
165};
166
167/*
168 * Interrupt Control Unit of PLD on M32700UT-LAN (Level 2)
169 */
170#define irq2lanpldirq(x) ((x) - M32700UT_LAN_PLD_IRQ_BASE)
171#define lanpldirq2port(x) (unsigned long)((int)M32700UT_LAN_ICUCR1 + \
172 (((x) - 1) * sizeof(unsigned short)))
173
174static pld_icu_data_t lanpld_icu_data[M32700UT_NUM_LAN_PLD_IRQ];
175
176static void disable_m32700ut_lanpld_irq(unsigned int irq)
177{
178 unsigned long port, data;
179 unsigned int pldirq;
180
181 pldirq = irq2lanpldirq(irq);
182 port = lanpldirq2port(pldirq);
183 data = lanpld_icu_data[pldirq].icucr|PLD_ICUCR_ILEVEL7;
184 outw(data, port);
185}
186
187static void enable_m32700ut_lanpld_irq(unsigned int irq)
188{
189 unsigned long port, data;
190 unsigned int pldirq;
191
192 pldirq = irq2lanpldirq(irq);
193 port = lanpldirq2port(pldirq);
194 data = lanpld_icu_data[pldirq].icucr|PLD_ICUCR_IEN|PLD_ICUCR_ILEVEL6;
195 outw(data, port);
196}
197
198static void mask_and_ack_m32700ut_lanpld(unsigned int irq)
199{
200 disable_m32700ut_lanpld_irq(irq);
201}
202
203static void end_m32700ut_lanpld_irq(unsigned int irq)
204{
205 enable_m32700ut_lanpld_irq(irq);
206 end_m32700ut_irq(M32R_IRQ_INT0);
207}
208
209static unsigned int startup_m32700ut_lanpld_irq(unsigned int irq)
210{
211 enable_m32700ut_lanpld_irq(irq);
212 return (0);
213}
214
215static void shutdown_m32700ut_lanpld_irq(unsigned int irq)
216{
217 unsigned long port;
218 unsigned int pldirq;
219
220 pldirq = irq2lanpldirq(irq);
221 port = lanpldirq2port(pldirq);
222 outw(PLD_ICUCR_ILEVEL7, port);
223}
224
225static struct hw_interrupt_type m32700ut_lanpld_irq_type =
226{
227 "M32700UT-PLD-LAN-IRQ",
228 startup_m32700ut_lanpld_irq,
229 shutdown_m32700ut_lanpld_irq,
230 enable_m32700ut_lanpld_irq,
231 disable_m32700ut_lanpld_irq,
232 mask_and_ack_m32700ut_lanpld,
233 end_m32700ut_lanpld_irq
234};
235
236/*
237 * Interrupt Control Unit of PLD on M32700UT-LCD (Level 2)
238 */
239#define irq2lcdpldirq(x) ((x) - M32700UT_LCD_PLD_IRQ_BASE)
240#define lcdpldirq2port(x) (unsigned long)((int)M32700UT_LCD_ICUCR1 + \
241 (((x) - 1) * sizeof(unsigned short)))
242
243static pld_icu_data_t lcdpld_icu_data[M32700UT_NUM_LCD_PLD_IRQ];
244
245static void disable_m32700ut_lcdpld_irq(unsigned int irq)
246{
247 unsigned long port, data;
248 unsigned int pldirq;
249
250 pldirq = irq2lcdpldirq(irq);
251 port = lcdpldirq2port(pldirq);
252 data = lcdpld_icu_data[pldirq].icucr|PLD_ICUCR_ILEVEL7;
253 outw(data, port);
254}
255
256static void enable_m32700ut_lcdpld_irq(unsigned int irq)
257{
258 unsigned long port, data;
259 unsigned int pldirq;
260
261 pldirq = irq2lcdpldirq(irq);
262 port = lcdpldirq2port(pldirq);
263 data = lcdpld_icu_data[pldirq].icucr|PLD_ICUCR_IEN|PLD_ICUCR_ILEVEL6;
264 outw(data, port);
265}
266
267static void mask_and_ack_m32700ut_lcdpld(unsigned int irq)
268{
269 disable_m32700ut_lcdpld_irq(irq);
270}
271
272static void end_m32700ut_lcdpld_irq(unsigned int irq)
273{
274 enable_m32700ut_lcdpld_irq(irq);
275 end_m32700ut_irq(M32R_IRQ_INT2);
276}
277
278static unsigned int startup_m32700ut_lcdpld_irq(unsigned int irq)
279{
280 enable_m32700ut_lcdpld_irq(irq);
281 return (0);
282}
283
284static void shutdown_m32700ut_lcdpld_irq(unsigned int irq)
285{
286 unsigned long port;
287 unsigned int pldirq;
288
289 pldirq = irq2lcdpldirq(irq);
290 port = lcdpldirq2port(pldirq);
291 outw(PLD_ICUCR_ILEVEL7, port);
292}
293
294static struct hw_interrupt_type m32700ut_lcdpld_irq_type =
295{
296 "M32700UT-PLD-LCD-IRQ",
297 startup_m32700ut_lcdpld_irq,
298 shutdown_m32700ut_lcdpld_irq,
299 enable_m32700ut_lcdpld_irq,
300 disable_m32700ut_lcdpld_irq,
301 mask_and_ack_m32700ut_lcdpld,
302 end_m32700ut_lcdpld_irq
303};
304
305void __init init_IRQ(void)
306{
307#if defined(CONFIG_SMC91X)
308 /* INT#0: LAN controller on M32700UT-LAN (SMC91C111)*/
309 irq_desc[M32700UT_LAN_IRQ_LAN].status = IRQ_DISABLED;
310 irq_desc[M32700UT_LAN_IRQ_LAN].handler = &m32700ut_lanpld_irq_type;
311 irq_desc[M32700UT_LAN_IRQ_LAN].action = 0;
312 irq_desc[M32700UT_LAN_IRQ_LAN].depth = 1; /* disable nested irq */
313 lanpld_icu_data[irq2lanpldirq(M32700UT_LAN_IRQ_LAN)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD02; /* "H" edge sense */
314 disable_m32700ut_lanpld_irq(M32700UT_LAN_IRQ_LAN);
315#endif /* CONFIG_SMC91X */
316
317 /* MFT2 : system timer */
318 irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
319 irq_desc[M32R_IRQ_MFT2].handler = &m32700ut_irq_type;
320 irq_desc[M32R_IRQ_MFT2].action = 0;
321 irq_desc[M32R_IRQ_MFT2].depth = 1;
322 icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
323 disable_m32700ut_irq(M32R_IRQ_MFT2);
324
325 /* SIO0 : receive */
326 irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
327 irq_desc[M32R_IRQ_SIO0_R].handler = &m32700ut_irq_type;
328 irq_desc[M32R_IRQ_SIO0_R].action = 0;
329 irq_desc[M32R_IRQ_SIO0_R].depth = 1;
330 icu_data[M32R_IRQ_SIO0_R].icucr = 0;
331 disable_m32700ut_irq(M32R_IRQ_SIO0_R);
332
333 /* SIO0 : send */
334 irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
335 irq_desc[M32R_IRQ_SIO0_S].handler = &m32700ut_irq_type;
336 irq_desc[M32R_IRQ_SIO0_S].action = 0;
337 irq_desc[M32R_IRQ_SIO0_S].depth = 1;
338 icu_data[M32R_IRQ_SIO0_S].icucr = 0;
339 disable_m32700ut_irq(M32R_IRQ_SIO0_S);
340
341 /* SIO1 : receive */
342 irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
343 irq_desc[M32R_IRQ_SIO1_R].handler = &m32700ut_irq_type;
344 irq_desc[M32R_IRQ_SIO1_R].action = 0;
345 irq_desc[M32R_IRQ_SIO1_R].depth = 1;
346 icu_data[M32R_IRQ_SIO1_R].icucr = 0;
347 disable_m32700ut_irq(M32R_IRQ_SIO1_R);
348
349 /* SIO1 : send */
350 irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
351 irq_desc[M32R_IRQ_SIO1_S].handler = &m32700ut_irq_type;
352 irq_desc[M32R_IRQ_SIO1_S].action = 0;
353 irq_desc[M32R_IRQ_SIO1_S].depth = 1;
354 icu_data[M32R_IRQ_SIO1_S].icucr = 0;
355 disable_m32700ut_irq(M32R_IRQ_SIO1_S);
356
357 /* DMA1 : */
358 irq_desc[M32R_IRQ_DMA1].status = IRQ_DISABLED;
359 irq_desc[M32R_IRQ_DMA1].handler = &m32700ut_irq_type;
360 irq_desc[M32R_IRQ_DMA1].action = 0;
361 irq_desc[M32R_IRQ_DMA1].depth = 1;
362 icu_data[M32R_IRQ_DMA1].icucr = 0;
363 disable_m32700ut_irq(M32R_IRQ_DMA1);
364
365#ifdef CONFIG_SERIAL_M32R_PLDSIO
366 /* INT#1: SIO0 Receive on PLD */
367 irq_desc[PLD_IRQ_SIO0_RCV].status = IRQ_DISABLED;
368 irq_desc[PLD_IRQ_SIO0_RCV].handler = &m32700ut_pld_irq_type;
369 irq_desc[PLD_IRQ_SIO0_RCV].action = 0;
370 irq_desc[PLD_IRQ_SIO0_RCV].depth = 1; /* disable nested irq */
371 pld_icu_data[irq2pldirq(PLD_IRQ_SIO0_RCV)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD03;
372 disable_m32700ut_pld_irq(PLD_IRQ_SIO0_RCV);
373
374 /* INT#1: SIO0 Send on PLD */
375 irq_desc[PLD_IRQ_SIO0_SND].status = IRQ_DISABLED;
376 irq_desc[PLD_IRQ_SIO0_SND].handler = &m32700ut_pld_irq_type;
377 irq_desc[PLD_IRQ_SIO0_SND].action = 0;
378 irq_desc[PLD_IRQ_SIO0_SND].depth = 1; /* disable nested irq */
379 pld_icu_data[irq2pldirq(PLD_IRQ_SIO0_SND)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD03;
380 disable_m32700ut_pld_irq(PLD_IRQ_SIO0_SND);
381#endif /* CONFIG_SERIAL_M32R_PLDSIO */
382
383 /* INT#1: CFC IREQ on PLD */
384 irq_desc[PLD_IRQ_CFIREQ].status = IRQ_DISABLED;
385 irq_desc[PLD_IRQ_CFIREQ].handler = &m32700ut_pld_irq_type;
386 irq_desc[PLD_IRQ_CFIREQ].action = 0;
387 irq_desc[PLD_IRQ_CFIREQ].depth = 1; /* disable nested irq */
388 pld_icu_data[irq2pldirq(PLD_IRQ_CFIREQ)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD01; /* 'L' level sense */
389 disable_m32700ut_pld_irq(PLD_IRQ_CFIREQ);
390
391 /* INT#1: CFC Insert on PLD */
392 irq_desc[PLD_IRQ_CFC_INSERT].status = IRQ_DISABLED;
393 irq_desc[PLD_IRQ_CFC_INSERT].handler = &m32700ut_pld_irq_type;
394 irq_desc[PLD_IRQ_CFC_INSERT].action = 0;
395 irq_desc[PLD_IRQ_CFC_INSERT].depth = 1; /* disable nested irq */
396 pld_icu_data[irq2pldirq(PLD_IRQ_CFC_INSERT)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD00; /* 'L' edge sense */
397 disable_m32700ut_pld_irq(PLD_IRQ_CFC_INSERT);
398
399 /* INT#1: CFC Eject on PLD */
400 irq_desc[PLD_IRQ_CFC_EJECT].status = IRQ_DISABLED;
401 irq_desc[PLD_IRQ_CFC_EJECT].handler = &m32700ut_pld_irq_type;
402 irq_desc[PLD_IRQ_CFC_EJECT].action = 0;
403 irq_desc[PLD_IRQ_CFC_EJECT].depth = 1; /* disable nested irq */
404 pld_icu_data[irq2pldirq(PLD_IRQ_CFC_EJECT)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD02; /* 'H' edge sense */
405 disable_m32700ut_pld_irq(PLD_IRQ_CFC_EJECT);
406
407 /*
408 * INT0# is used for LAN, DIO
409 * We enable it here.
410 */
411 icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD11;
412 enable_m32700ut_irq(M32R_IRQ_INT0);
413
414 /*
415 * INT1# is used for UART, MMC, CF Controller in FPGA.
416 * We enable it here.
417 */
418 icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD11;
419 enable_m32700ut_irq(M32R_IRQ_INT1);
420
421#if defined(CONFIG_USB)
422 outw(USBCR_OTGS, USBCR); /* USBCR: non-OTG */
423
424 irq_desc[M32700UT_LCD_IRQ_USB_INT1].status = IRQ_DISABLED;
425 irq_desc[M32700UT_LCD_IRQ_USB_INT1].handler = &m32700ut_lcdpld_irq_type;
426 irq_desc[M32700UT_LCD_IRQ_USB_INT1].action = 0;
427 irq_desc[M32700UT_LCD_IRQ_USB_INT1].depth = 1;
428 lcdpld_icu_data[irq2lcdpldirq(M32700UT_LCD_IRQ_USB_INT1)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD01; /* "L" level sense */
429 disable_m32700ut_lcdpld_irq(M32700UT_LCD_IRQ_USB_INT1);
430#endif
431 /*
432 * INT2# is used for BAT, USB, AUDIO
433 * We enable it here.
434 */
435 icu_data[M32R_IRQ_INT2].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD01;
436 enable_m32700ut_irq(M32R_IRQ_INT2);
437
438//#if defined(CONFIG_VIDEO_M32R_AR)
439 /*
440 * INT3# is used for AR
441 */
442 irq_desc[M32R_IRQ_INT3].status = IRQ_DISABLED;
443 irq_desc[M32R_IRQ_INT3].handler = &m32700ut_irq_type;
444 irq_desc[M32R_IRQ_INT3].action = 0;
445 irq_desc[M32R_IRQ_INT3].depth = 1;
446 icu_data[M32R_IRQ_INT3].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
447 disable_m32700ut_irq(M32R_IRQ_INT3);
448//#endif /* CONFIG_VIDEO_M32R_AR */
449}
450
451#define LAN_IOSTART 0x300
452#define LAN_IOEND 0x320
453static struct resource smc91x_resources[] = {
454 [0] = {
455 .start = (LAN_IOSTART),
456 .end = (LAN_IOEND),
457 .flags = IORESOURCE_MEM,
458 },
459 [1] = {
460 .start = M32700UT_LAN_IRQ_LAN,
461 .end = M32700UT_LAN_IRQ_LAN,
462 .flags = IORESOURCE_IRQ,
463 }
464};
465
466static struct platform_device smc91x_device = {
467 .name = "smc91x",
468 .id = 0,
469 .num_resources = ARRAY_SIZE(smc91x_resources),
470 .resource = smc91x_resources,
471};
472
473static int __init platform_init(void)
474{
475 platform_device_register(&smc91x_device);
476 return 0;
477}
478arch_initcall(platform_init);
diff --git a/arch/m32r/kernel/setup_mappi.c b/arch/m32r/kernel/setup_mappi.c
new file mode 100644
index 000000000000..1e74110f0670
--- /dev/null
+++ b/arch/m32r/kernel/setup_mappi.c
@@ -0,0 +1,160 @@
1/*
2 * linux/arch/m32r/kernel/setup_mappi.c
3 *
4 * Setup routines for Renesas MAPPI Board
5 *
6 * Copyright (c) 2001, 2002 Hiroyuki Kondo, Hirokazu Takata,
7 * Hitoshi Yamamoto
8 */
9
10#include <linux/config.h>
11#include <linux/irq.h>
12#include <linux/kernel.h>
13#include <linux/init.h>
14
15#include <asm/system.h>
16#include <asm/m32r.h>
17#include <asm/io.h>
18
19#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
20
21#ifndef CONFIG_SMP
22typedef struct {
23 unsigned long icucr; /* ICU Control Register */
24} icu_data_t;
25#endif /* CONFIG_SMP */
26
27icu_data_t icu_data[NR_IRQS];
28
29static void disable_mappi_irq(unsigned int irq)
30{
31 unsigned long port, data;
32
33 port = irq2port(irq);
34 data = icu_data[irq].icucr|M32R_ICUCR_ILEVEL7;
35 outl(data, port);
36}
37
38static void enable_mappi_irq(unsigned int irq)
39{
40 unsigned long port, data;
41
42 port = irq2port(irq);
43 data = icu_data[irq].icucr|M32R_ICUCR_IEN|M32R_ICUCR_ILEVEL6;
44 outl(data, port);
45}
46
47static void mask_and_ack_mappi(unsigned int irq)
48{
49 disable_mappi_irq(irq);
50}
51
52static void end_mappi_irq(unsigned int irq)
53{
54 enable_mappi_irq(irq);
55}
56
57static unsigned int startup_mappi_irq(unsigned int irq)
58{
59 enable_mappi_irq(irq);
60 return (0);
61}
62
63static void shutdown_mappi_irq(unsigned int irq)
64{
65 unsigned long port;
66
67 port = irq2port(irq);
68 outl(M32R_ICUCR_ILEVEL7, port);
69}
70
71static struct hw_interrupt_type mappi_irq_type =
72{
73 "MAPPI-IRQ",
74 startup_mappi_irq,
75 shutdown_mappi_irq,
76 enable_mappi_irq,
77 disable_mappi_irq,
78 mask_and_ack_mappi,
79 end_mappi_irq
80};
81
82void __init init_IRQ(void)
83{
84 static int once = 0;
85
86 if (once)
87 return;
88 else
89 once++;
90
91#ifdef CONFIG_NE2000
92 /* INT0 : LAN controller (RTL8019AS) */
93 irq_desc[M32R_IRQ_INT0].status = IRQ_DISABLED;
94 irq_desc[M32R_IRQ_INT0].handler = &mappi_irq_type;
95 irq_desc[M32R_IRQ_INT0].action = 0;
96 irq_desc[M32R_IRQ_INT0].depth = 1;
97 icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
98 disable_mappi_irq(M32R_IRQ_INT0);
99#endif /* CONFIG_M32R_NE2000 */
100
101 /* MFT2 : system timer */
102 irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
103 irq_desc[M32R_IRQ_MFT2].handler = &mappi_irq_type;
104 irq_desc[M32R_IRQ_MFT2].action = 0;
105 irq_desc[M32R_IRQ_MFT2].depth = 1;
106 icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
107 disable_mappi_irq(M32R_IRQ_MFT2);
108
109#ifdef CONFIG_SERIAL_M32R_SIO
110 /* SIO0_R : uart receive data */
111 irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
112 irq_desc[M32R_IRQ_SIO0_R].handler = &mappi_irq_type;
113 irq_desc[M32R_IRQ_SIO0_R].action = 0;
114 irq_desc[M32R_IRQ_SIO0_R].depth = 1;
115 icu_data[M32R_IRQ_SIO0_R].icucr = 0;
116 disable_mappi_irq(M32R_IRQ_SIO0_R);
117
118 /* SIO0_S : uart send data */
119 irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
120 irq_desc[M32R_IRQ_SIO0_S].handler = &mappi_irq_type;
121 irq_desc[M32R_IRQ_SIO0_S].action = 0;
122 irq_desc[M32R_IRQ_SIO0_S].depth = 1;
123 icu_data[M32R_IRQ_SIO0_S].icucr = 0;
124 disable_mappi_irq(M32R_IRQ_SIO0_S);
125
126 /* SIO1_R : uart receive data */
127 irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
128 irq_desc[M32R_IRQ_SIO1_R].handler = &mappi_irq_type;
129 irq_desc[M32R_IRQ_SIO1_R].action = 0;
130 irq_desc[M32R_IRQ_SIO1_R].depth = 1;
131 icu_data[M32R_IRQ_SIO1_R].icucr = 0;
132 disable_mappi_irq(M32R_IRQ_SIO1_R);
133
134 /* SIO1_S : uart send data */
135 irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
136 irq_desc[M32R_IRQ_SIO1_S].handler = &mappi_irq_type;
137 irq_desc[M32R_IRQ_SIO1_S].action = 0;
138 irq_desc[M32R_IRQ_SIO1_S].depth = 1;
139 icu_data[M32R_IRQ_SIO1_S].icucr = 0;
140 disable_mappi_irq(M32R_IRQ_SIO1_S);
141#endif /* CONFIG_SERIAL_M32R_SIO */
142
143#if defined(CONFIG_M32R_PCC)
144 /* INT1 : pccard0 interrupt */
145 irq_desc[M32R_IRQ_INT1].status = IRQ_DISABLED;
146 irq_desc[M32R_IRQ_INT1].handler = &mappi_irq_type;
147 irq_desc[M32R_IRQ_INT1].action = 0;
148 irq_desc[M32R_IRQ_INT1].depth = 1;
149 icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_IEN | M32R_ICUCR_ISMOD00;
150 disable_mappi_irq(M32R_IRQ_INT1);
151
152 /* INT2 : pccard1 interrupt */
153 irq_desc[M32R_IRQ_INT2].status = IRQ_DISABLED;
154 irq_desc[M32R_IRQ_INT2].handler = &mappi_irq_type;
155 irq_desc[M32R_IRQ_INT2].action = 0;
156 irq_desc[M32R_IRQ_INT2].depth = 1;
157 icu_data[M32R_IRQ_INT2].icucr = M32R_ICUCR_IEN | M32R_ICUCR_ISMOD00;
158 disable_mappi_irq(M32R_IRQ_INT2);
159#endif /* CONFIG_M32RPCC */
160}
diff --git a/arch/m32r/kernel/setup_mappi2.c b/arch/m32r/kernel/setup_mappi2.c
new file mode 100644
index 000000000000..1904d465a507
--- /dev/null
+++ b/arch/m32r/kernel/setup_mappi2.c
@@ -0,0 +1,212 @@
1/*
2 * linux/arch/m32r/kernel/setup_mappi.c
3 *
4 * Setup routines for Renesas MAPPI-II(M3A-ZA36) Board
5 *
6 * Copyright (c) 2001, 2002 Hiroyuki Kondo, Hirokazu Takata,
7 * Hitoshi Yamamoto, Mamoru Sakugawa
8 */
9
10#include <linux/config.h>
11#include <linux/irq.h>
12#include <linux/kernel.h>
13#include <linux/init.h>
14#include <linux/device.h>
15
16#include <asm/system.h>
17#include <asm/m32r.h>
18#include <asm/io.h>
19
20#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
21
22#ifndef CONFIG_SMP
23typedef struct {
24 unsigned long icucr; /* ICU Control Register */
25} icu_data_t;
26#endif /* CONFIG_SMP */
27
28icu_data_t icu_data[NR_IRQS];
29
30static void disable_mappi2_irq(unsigned int irq)
31{
32 unsigned long port, data;
33
34 if ((irq == 0) ||(irq >= NR_IRQS)) {
35 printk("bad irq 0x%08x\n", irq);
36 return;
37 }
38 port = irq2port(irq);
39 data = icu_data[irq].icucr|M32R_ICUCR_ILEVEL7;
40 outl(data, port);
41}
42
43static void enable_mappi2_irq(unsigned int irq)
44{
45 unsigned long port, data;
46
47 if ((irq == 0) ||(irq >= NR_IRQS)) {
48 printk("bad irq 0x%08x\n", irq);
49 return;
50 }
51 port = irq2port(irq);
52 data = icu_data[irq].icucr|M32R_ICUCR_IEN|M32R_ICUCR_ILEVEL6;
53 outl(data, port);
54}
55
56static void mask_and_ack_mappi2(unsigned int irq)
57{
58 disable_mappi2_irq(irq);
59}
60
61static void end_mappi2_irq(unsigned int irq)
62{
63 enable_mappi2_irq(irq);
64}
65
66static unsigned int startup_mappi2_irq(unsigned int irq)
67{
68 enable_mappi2_irq(irq);
69 return (0);
70}
71
72static void shutdown_mappi2_irq(unsigned int irq)
73{
74 unsigned long port;
75
76 port = irq2port(irq);
77 outl(M32R_ICUCR_ILEVEL7, port);
78}
79
80static struct hw_interrupt_type mappi2_irq_type =
81{
82 "MAPPI2-IRQ",
83 startup_mappi2_irq,
84 shutdown_mappi2_irq,
85 enable_mappi2_irq,
86 disable_mappi2_irq,
87 mask_and_ack_mappi2,
88 end_mappi2_irq
89};
90
91void __init init_IRQ(void)
92{
93#if defined(CONFIG_SMC91X)
94 /* INT0 : LAN controller (SMC91111) */
95 irq_desc[M32R_IRQ_INT0].status = IRQ_DISABLED;
96 irq_desc[M32R_IRQ_INT0].handler = &mappi2_irq_type;
97 irq_desc[M32R_IRQ_INT0].action = 0;
98 irq_desc[M32R_IRQ_INT0].depth = 1;
99 icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
100 disable_mappi2_irq(M32R_IRQ_INT0);
101#endif /* CONFIG_SMC91X */
102
103 /* MFT2 : system timer */
104 irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
105 irq_desc[M32R_IRQ_MFT2].handler = &mappi2_irq_type;
106 irq_desc[M32R_IRQ_MFT2].action = 0;
107 irq_desc[M32R_IRQ_MFT2].depth = 1;
108 icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
109 disable_mappi2_irq(M32R_IRQ_MFT2);
110
111#ifdef CONFIG_SERIAL_M32R_SIO
112 /* SIO0_R : uart receive data */
113 irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
114 irq_desc[M32R_IRQ_SIO0_R].handler = &mappi2_irq_type;
115 irq_desc[M32R_IRQ_SIO0_R].action = 0;
116 irq_desc[M32R_IRQ_SIO0_R].depth = 1;
117 icu_data[M32R_IRQ_SIO0_R].icucr = 0;
118 disable_mappi2_irq(M32R_IRQ_SIO0_R);
119
120 /* SIO0_S : uart send data */
121 irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
122 irq_desc[M32R_IRQ_SIO0_S].handler = &mappi2_irq_type;
123 irq_desc[M32R_IRQ_SIO0_S].action = 0;
124 irq_desc[M32R_IRQ_SIO0_S].depth = 1;
125 icu_data[M32R_IRQ_SIO0_S].icucr = 0;
126 disable_mappi2_irq(M32R_IRQ_SIO0_S);
127 /* SIO1_R : uart receive data */
128 irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
129 irq_desc[M32R_IRQ_SIO1_R].handler = &mappi2_irq_type;
130 irq_desc[M32R_IRQ_SIO1_R].action = 0;
131 irq_desc[M32R_IRQ_SIO1_R].depth = 1;
132 icu_data[M32R_IRQ_SIO1_R].icucr = 0;
133 disable_mappi2_irq(M32R_IRQ_SIO1_R);
134
135 /* SIO1_S : uart send data */
136 irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
137 irq_desc[M32R_IRQ_SIO1_S].handler = &mappi2_irq_type;
138 irq_desc[M32R_IRQ_SIO1_S].action = 0;
139 irq_desc[M32R_IRQ_SIO1_S].depth = 1;
140 icu_data[M32R_IRQ_SIO1_S].icucr = 0;
141 disable_mappi2_irq(M32R_IRQ_SIO1_S);
142#endif /* CONFIG_M32R_USE_DBG_CONSOLE */
143
144#if defined(CONFIG_USB)
145 /* INT1 : USB Host controller interrupt */
146 irq_desc[M32R_IRQ_INT1].status = IRQ_DISABLED;
147 irq_desc[M32R_IRQ_INT1].handler = &mappi2_irq_type;
148 irq_desc[M32R_IRQ_INT1].action = 0;
149 irq_desc[M32R_IRQ_INT1].depth = 1;
150 icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_ISMOD01;
151 disable_mappi2_irq(M32R_IRQ_INT1);
152#endif /* CONFIG_USB */
153
154 /* ICUCR40: CFC IREQ */
155 irq_desc[PLD_IRQ_CFIREQ].status = IRQ_DISABLED;
156 irq_desc[PLD_IRQ_CFIREQ].handler = &mappi2_irq_type;
157 irq_desc[PLD_IRQ_CFIREQ].action = 0;
158 irq_desc[PLD_IRQ_CFIREQ].depth = 1; /* disable nested irq */
159// icu_data[PLD_IRQ_CFIREQ].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD00;
160 icu_data[PLD_IRQ_CFIREQ].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD01;
161 disable_mappi2_irq(PLD_IRQ_CFIREQ);
162
163#if defined(CONFIG_M32R_CFC)
164 /* ICUCR41: CFC Insert */
165 irq_desc[PLD_IRQ_CFC_INSERT].status = IRQ_DISABLED;
166 irq_desc[PLD_IRQ_CFC_INSERT].handler = &mappi2_irq_type;
167 irq_desc[PLD_IRQ_CFC_INSERT].action = 0;
168 irq_desc[PLD_IRQ_CFC_INSERT].depth = 1; /* disable nested irq */
169 icu_data[PLD_IRQ_CFC_INSERT].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD00;
170// icu_data[PLD_IRQ_CFC_INSERT].icucr = 0;
171 disable_mappi2_irq(PLD_IRQ_CFC_INSERT);
172
173 /* ICUCR42: CFC Eject */
174 irq_desc[PLD_IRQ_CFC_EJECT].status = IRQ_DISABLED;
175 irq_desc[PLD_IRQ_CFC_EJECT].handler = &mappi2_irq_type;
176 irq_desc[PLD_IRQ_CFC_EJECT].action = 0;
177 irq_desc[PLD_IRQ_CFC_EJECT].depth = 1; /* disable nested irq */
178 icu_data[PLD_IRQ_CFC_EJECT].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
179// icu_data[PLD_IRQ_CFC_EJECT].icucr = 0;
180 disable_mappi2_irq(PLD_IRQ_CFC_EJECT);
181
182#endif /* CONFIG_MAPPI2_CFC */
183}
184
185#define LAN_IOSTART 0x300
186#define LAN_IOEND 0x320
187static struct resource smc91x_resources[] = {
188 [0] = {
189 .start = (LAN_IOSTART),
190 .end = (LAN_IOEND),
191 .flags = IORESOURCE_MEM,
192 },
193 [1] = {
194 .start = M32R_IRQ_INT0,
195 .end = M32R_IRQ_INT0,
196 .flags = IORESOURCE_IRQ,
197 }
198};
199
200static struct platform_device smc91x_device = {
201 .name = "smc91x",
202 .id = 0,
203 .num_resources = ARRAY_SIZE(smc91x_resources),
204 .resource = smc91x_resources,
205};
206
207static int __init platform_init(void)
208{
209 platform_device_register(&smc91x_device);
210 return 0;
211}
212arch_initcall(platform_init);
diff --git a/arch/m32r/kernel/setup_oaks32r.c b/arch/m32r/kernel/setup_oaks32r.c
new file mode 100644
index 000000000000..b04834526c9a
--- /dev/null
+++ b/arch/m32r/kernel/setup_oaks32r.c
@@ -0,0 +1,143 @@
1/*
2 * linux/arch/m32r/kernel/setup_oaks32r.c
3 *
4 * Setup routines for OAKS32R Board
5 *
6 * Copyright (c) 2002-2004 Hiroyuki Kondo, Hirokazu Takata,
7 * Hitoshi Yamamoto, Mamoru Sakugawa
8 */
9
10#include <linux/config.h>
11#include <linux/irq.h>
12#include <linux/kernel.h>
13#include <linux/init.h>
14
15#include <asm/system.h>
16#include <asm/m32r.h>
17#include <asm/io.h>
18
19#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
20
21#ifndef CONFIG_SMP
22typedef struct {
23 unsigned long icucr; /* ICU Control Register */
24} icu_data_t;
25#endif /* CONFIG_SMP */
26
27icu_data_t icu_data[NR_IRQS];
28
29static void disable_oaks32r_irq(unsigned int irq)
30{
31 unsigned long port, data;
32
33 port = irq2port(irq);
34 data = icu_data[irq].icucr|M32R_ICUCR_ILEVEL7;
35 outl(data, port);
36}
37
38static void enable_oaks32r_irq(unsigned int irq)
39{
40 unsigned long port, data;
41
42 port = irq2port(irq);
43 data = icu_data[irq].icucr|M32R_ICUCR_IEN|M32R_ICUCR_ILEVEL6;
44 outl(data, port);
45}
46
47static void mask_and_ack_mappi(unsigned int irq)
48{
49 disable_oaks32r_irq(irq);
50}
51
52static void end_oaks32r_irq(unsigned int irq)
53{
54 enable_oaks32r_irq(irq);
55}
56
57static unsigned int startup_oaks32r_irq(unsigned int irq)
58{
59 enable_oaks32r_irq(irq);
60 return (0);
61}
62
63static void shutdown_oaks32r_irq(unsigned int irq)
64{
65 unsigned long port;
66
67 port = irq2port(irq);
68 outl(M32R_ICUCR_ILEVEL7, port);
69}
70
71static struct hw_interrupt_type oaks32r_irq_type =
72{
73 "OAKS32R-IRQ",
74 startup_oaks32r_irq,
75 shutdown_oaks32r_irq,
76 enable_oaks32r_irq,
77 disable_oaks32r_irq,
78 mask_and_ack_mappi,
79 end_oaks32r_irq
80};
81
82void __init init_IRQ(void)
83{
84 static int once = 0;
85
86 if (once)
87 return;
88 else
89 once++;
90
91#ifdef CONFIG_NE2000
92 /* INT3 : LAN controller (RTL8019AS) */
93 irq_desc[M32R_IRQ_INT3].status = IRQ_DISABLED;
94 irq_desc[M32R_IRQ_INT3].handler = &oaks32r_irq_type;
95 irq_desc[M32R_IRQ_INT3].action = 0;
96 irq_desc[M32R_IRQ_INT3].depth = 1;
97 icu_data[M32R_IRQ_INT3].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
98 disable_oaks32r_irq(M32R_IRQ_INT3);
99#endif /* CONFIG_M32R_NE2000 */
100
101 /* MFT2 : system timer */
102 irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
103 irq_desc[M32R_IRQ_MFT2].handler = &oaks32r_irq_type;
104 irq_desc[M32R_IRQ_MFT2].action = 0;
105 irq_desc[M32R_IRQ_MFT2].depth = 1;
106 icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
107 disable_oaks32r_irq(M32R_IRQ_MFT2);
108
109#ifdef CONFIG_SERIAL_M32R_SIO
110 /* SIO0_R : uart receive data */
111 irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
112 irq_desc[M32R_IRQ_SIO0_R].handler = &oaks32r_irq_type;
113 irq_desc[M32R_IRQ_SIO0_R].action = 0;
114 irq_desc[M32R_IRQ_SIO0_R].depth = 1;
115 icu_data[M32R_IRQ_SIO0_R].icucr = 0;
116 disable_oaks32r_irq(M32R_IRQ_SIO0_R);
117
118 /* SIO0_S : uart send data */
119 irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
120 irq_desc[M32R_IRQ_SIO0_S].handler = &oaks32r_irq_type;
121 irq_desc[M32R_IRQ_SIO0_S].action = 0;
122 irq_desc[M32R_IRQ_SIO0_S].depth = 1;
123 icu_data[M32R_IRQ_SIO0_S].icucr = 0;
124 disable_oaks32r_irq(M32R_IRQ_SIO0_S);
125
126 /* SIO1_R : uart receive data */
127 irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
128 irq_desc[M32R_IRQ_SIO1_R].handler = &oaks32r_irq_type;
129 irq_desc[M32R_IRQ_SIO1_R].action = 0;
130 irq_desc[M32R_IRQ_SIO1_R].depth = 1;
131 icu_data[M32R_IRQ_SIO1_R].icucr = 0;
132 disable_oaks32r_irq(M32R_IRQ_SIO1_R);
133
134 /* SIO1_S : uart send data */
135 irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
136 irq_desc[M32R_IRQ_SIO1_S].handler = &oaks32r_irq_type;
137 irq_desc[M32R_IRQ_SIO1_S].action = 0;
138 irq_desc[M32R_IRQ_SIO1_S].depth = 1;
139 icu_data[M32R_IRQ_SIO1_S].icucr = 0;
140 disable_oaks32r_irq(M32R_IRQ_SIO1_S);
141#endif /* CONFIG_SERIAL_M32R_SIO */
142
143}
diff --git a/arch/m32r/kernel/setup_opsput.c b/arch/m32r/kernel/setup_opsput.c
new file mode 100644
index 000000000000..84315e344c58
--- /dev/null
+++ b/arch/m32r/kernel/setup_opsput.c
@@ -0,0 +1,482 @@
1/*
2 * linux/arch/m32r/kernel/setup_opsput.c
3 *
4 * Setup routines for Renesas OPSPUT Board
5 *
6 * Copyright (c) 2002-2004
7 * Hiroyuki Kondo, Hirokazu Takata,
8 * Hitoshi Yamamoto, Takeo Takahashi, Mamoru Sakugawa
9 *
10 * This file is subject to the terms and conditions of the GNU General
11 * Public License. See the file "COPYING" in the main directory of this
12 * archive for more details.
13 */
14
15#include <linux/config.h>
16#include <linux/irq.h>
17#include <linux/kernel.h>
18#include <linux/init.h>
19#include <linux/device.h>
20
21#include <asm/system.h>
22#include <asm/m32r.h>
23#include <asm/io.h>
24
25/*
26 * OPSP Interrupt Control Unit (Level 1)
27 */
28#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
29
30#ifndef CONFIG_SMP
31typedef struct {
32 unsigned long icucr; /* ICU Control Register */
33} icu_data_t;
34#endif /* CONFIG_SMP */
35
36static icu_data_t icu_data[OPSPUT_NUM_CPU_IRQ];
37
38static void disable_opsput_irq(unsigned int irq)
39{
40 unsigned long port, data;
41
42 port = irq2port(irq);
43 data = icu_data[irq].icucr|M32R_ICUCR_ILEVEL7;
44 outl(data, port);
45}
46
47static void enable_opsput_irq(unsigned int irq)
48{
49 unsigned long port, data;
50
51 port = irq2port(irq);
52 data = icu_data[irq].icucr|M32R_ICUCR_IEN|M32R_ICUCR_ILEVEL6;
53 outl(data, port);
54}
55
56static void mask_and_ack_opsput(unsigned int irq)
57{
58 disable_opsput_irq(irq);
59}
60
61static void end_opsput_irq(unsigned int irq)
62{
63 enable_opsput_irq(irq);
64}
65
66static unsigned int startup_opsput_irq(unsigned int irq)
67{
68 enable_opsput_irq(irq);
69 return (0);
70}
71
72static void shutdown_opsput_irq(unsigned int irq)
73{
74 unsigned long port;
75
76 port = irq2port(irq);
77 outl(M32R_ICUCR_ILEVEL7, port);
78}
79
80static struct hw_interrupt_type opsput_irq_type =
81{
82 "OPSPUT-IRQ",
83 startup_opsput_irq,
84 shutdown_opsput_irq,
85 enable_opsput_irq,
86 disable_opsput_irq,
87 mask_and_ack_opsput,
88 end_opsput_irq
89};
90
91/*
92 * Interrupt Control Unit of PLD on OPSPUT (Level 2)
93 */
94#define irq2pldirq(x) ((x) - OPSPUT_PLD_IRQ_BASE)
95#define pldirq2port(x) (unsigned long)((int)PLD_ICUCR1 + \
96 (((x) - 1) * sizeof(unsigned short)))
97
98typedef struct {
99 unsigned short icucr; /* ICU Control Register */
100} pld_icu_data_t;
101
102static pld_icu_data_t pld_icu_data[OPSPUT_NUM_PLD_IRQ];
103
104static void disable_opsput_pld_irq(unsigned int irq)
105{
106 unsigned long port, data;
107 unsigned int pldirq;
108
109 pldirq = irq2pldirq(irq);
110// disable_opsput_irq(M32R_IRQ_INT1);
111 port = pldirq2port(pldirq);
112 data = pld_icu_data[pldirq].icucr|PLD_ICUCR_ILEVEL7;
113 outw(data, port);
114}
115
116static void enable_opsput_pld_irq(unsigned int irq)
117{
118 unsigned long port, data;
119 unsigned int pldirq;
120
121 pldirq = irq2pldirq(irq);
122// enable_opsput_irq(M32R_IRQ_INT1);
123 port = pldirq2port(pldirq);
124 data = pld_icu_data[pldirq].icucr|PLD_ICUCR_IEN|PLD_ICUCR_ILEVEL6;
125 outw(data, port);
126}
127
128static void mask_and_ack_opsput_pld(unsigned int irq)
129{
130 disable_opsput_pld_irq(irq);
131// mask_and_ack_opsput(M32R_IRQ_INT1);
132}
133
134static void end_opsput_pld_irq(unsigned int irq)
135{
136 enable_opsput_pld_irq(irq);
137 end_opsput_irq(M32R_IRQ_INT1);
138}
139
140static unsigned int startup_opsput_pld_irq(unsigned int irq)
141{
142 enable_opsput_pld_irq(irq);
143 return (0);
144}
145
146static void shutdown_opsput_pld_irq(unsigned int irq)
147{
148 unsigned long port;
149 unsigned int pldirq;
150
151 pldirq = irq2pldirq(irq);
152// shutdown_opsput_irq(M32R_IRQ_INT1);
153 port = pldirq2port(pldirq);
154 outw(PLD_ICUCR_ILEVEL7, port);
155}
156
157static struct hw_interrupt_type opsput_pld_irq_type =
158{
159 "OPSPUT-PLD-IRQ",
160 startup_opsput_pld_irq,
161 shutdown_opsput_pld_irq,
162 enable_opsput_pld_irq,
163 disable_opsput_pld_irq,
164 mask_and_ack_opsput_pld,
165 end_opsput_pld_irq
166};
167
168/*
169 * Interrupt Control Unit of PLD on OPSPUT-LAN (Level 2)
170 */
171#define irq2lanpldirq(x) ((x) - OPSPUT_LAN_PLD_IRQ_BASE)
172#define lanpldirq2port(x) (unsigned long)((int)OPSPUT_LAN_ICUCR1 + \
173 (((x) - 1) * sizeof(unsigned short)))
174
175static pld_icu_data_t lanpld_icu_data[OPSPUT_NUM_LAN_PLD_IRQ];
176
177static void disable_opsput_lanpld_irq(unsigned int irq)
178{
179 unsigned long port, data;
180 unsigned int pldirq;
181
182 pldirq = irq2lanpldirq(irq);
183 port = lanpldirq2port(pldirq);
184 data = lanpld_icu_data[pldirq].icucr|PLD_ICUCR_ILEVEL7;
185 outw(data, port);
186}
187
188static void enable_opsput_lanpld_irq(unsigned int irq)
189{
190 unsigned long port, data;
191 unsigned int pldirq;
192
193 pldirq = irq2lanpldirq(irq);
194 port = lanpldirq2port(pldirq);
195 data = lanpld_icu_data[pldirq].icucr|PLD_ICUCR_IEN|PLD_ICUCR_ILEVEL6;
196 outw(data, port);
197}
198
199static void mask_and_ack_opsput_lanpld(unsigned int irq)
200{
201 disable_opsput_lanpld_irq(irq);
202}
203
204static void end_opsput_lanpld_irq(unsigned int irq)
205{
206 enable_opsput_lanpld_irq(irq);
207 end_opsput_irq(M32R_IRQ_INT0);
208}
209
210static unsigned int startup_opsput_lanpld_irq(unsigned int irq)
211{
212 enable_opsput_lanpld_irq(irq);
213 return (0);
214}
215
216static void shutdown_opsput_lanpld_irq(unsigned int irq)
217{
218 unsigned long port;
219 unsigned int pldirq;
220
221 pldirq = irq2lanpldirq(irq);
222 port = lanpldirq2port(pldirq);
223 outw(PLD_ICUCR_ILEVEL7, port);
224}
225
226static struct hw_interrupt_type opsput_lanpld_irq_type =
227{
228 "OPSPUT-PLD-LAN-IRQ",
229 startup_opsput_lanpld_irq,
230 shutdown_opsput_lanpld_irq,
231 enable_opsput_lanpld_irq,
232 disable_opsput_lanpld_irq,
233 mask_and_ack_opsput_lanpld,
234 end_opsput_lanpld_irq
235};
236
237/*
238 * Interrupt Control Unit of PLD on OPSPUT-LCD (Level 2)
239 */
240#define irq2lcdpldirq(x) ((x) - OPSPUT_LCD_PLD_IRQ_BASE)
241#define lcdpldirq2port(x) (unsigned long)((int)OPSPUT_LCD_ICUCR1 + \
242 (((x) - 1) * sizeof(unsigned short)))
243
244static pld_icu_data_t lcdpld_icu_data[OPSPUT_NUM_LCD_PLD_IRQ];
245
246static void disable_opsput_lcdpld_irq(unsigned int irq)
247{
248 unsigned long port, data;
249 unsigned int pldirq;
250
251 pldirq = irq2lcdpldirq(irq);
252 port = lcdpldirq2port(pldirq);
253 data = lcdpld_icu_data[pldirq].icucr|PLD_ICUCR_ILEVEL7;
254 outw(data, port);
255}
256
257static void enable_opsput_lcdpld_irq(unsigned int irq)
258{
259 unsigned long port, data;
260 unsigned int pldirq;
261
262 pldirq = irq2lcdpldirq(irq);
263 port = lcdpldirq2port(pldirq);
264 data = lcdpld_icu_data[pldirq].icucr|PLD_ICUCR_IEN|PLD_ICUCR_ILEVEL6;
265 outw(data, port);
266}
267
268static void mask_and_ack_opsput_lcdpld(unsigned int irq)
269{
270 disable_opsput_lcdpld_irq(irq);
271}
272
273static void end_opsput_lcdpld_irq(unsigned int irq)
274{
275 enable_opsput_lcdpld_irq(irq);
276 end_opsput_irq(M32R_IRQ_INT2);
277}
278
279static unsigned int startup_opsput_lcdpld_irq(unsigned int irq)
280{
281 enable_opsput_lcdpld_irq(irq);
282 return (0);
283}
284
285static void shutdown_opsput_lcdpld_irq(unsigned int irq)
286{
287 unsigned long port;
288 unsigned int pldirq;
289
290 pldirq = irq2lcdpldirq(irq);
291 port = lcdpldirq2port(pldirq);
292 outw(PLD_ICUCR_ILEVEL7, port);
293}
294
295static struct hw_interrupt_type opsput_lcdpld_irq_type =
296{
297 "OPSPUT-PLD-LCD-IRQ",
298 startup_opsput_lcdpld_irq,
299 shutdown_opsput_lcdpld_irq,
300 enable_opsput_lcdpld_irq,
301 disable_opsput_lcdpld_irq,
302 mask_and_ack_opsput_lcdpld,
303 end_opsput_lcdpld_irq
304};
305
306void __init init_IRQ(void)
307{
308#if defined(CONFIG_SMC91X)
309 /* INT#0: LAN controller on OPSPUT-LAN (SMC91C111)*/
310 irq_desc[OPSPUT_LAN_IRQ_LAN].status = IRQ_DISABLED;
311 irq_desc[OPSPUT_LAN_IRQ_LAN].handler = &opsput_lanpld_irq_type;
312 irq_desc[OPSPUT_LAN_IRQ_LAN].action = 0;
313 irq_desc[OPSPUT_LAN_IRQ_LAN].depth = 1; /* disable nested irq */
314 lanpld_icu_data[irq2lanpldirq(OPSPUT_LAN_IRQ_LAN)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD02; /* "H" edge sense */
315 disable_opsput_lanpld_irq(OPSPUT_LAN_IRQ_LAN);
316#endif /* CONFIG_SMC91X */
317
318 /* MFT2 : system timer */
319 irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
320 irq_desc[M32R_IRQ_MFT2].handler = &opsput_irq_type;
321 irq_desc[M32R_IRQ_MFT2].action = 0;
322 irq_desc[M32R_IRQ_MFT2].depth = 1;
323 icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
324 disable_opsput_irq(M32R_IRQ_MFT2);
325
326 /* SIO0 : receive */
327 irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
328 irq_desc[M32R_IRQ_SIO0_R].handler = &opsput_irq_type;
329 irq_desc[M32R_IRQ_SIO0_R].action = 0;
330 irq_desc[M32R_IRQ_SIO0_R].depth = 1;
331 icu_data[M32R_IRQ_SIO0_R].icucr = 0;
332 disable_opsput_irq(M32R_IRQ_SIO0_R);
333
334 /* SIO0 : send */
335 irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
336 irq_desc[M32R_IRQ_SIO0_S].handler = &opsput_irq_type;
337 irq_desc[M32R_IRQ_SIO0_S].action = 0;
338 irq_desc[M32R_IRQ_SIO0_S].depth = 1;
339 icu_data[M32R_IRQ_SIO0_S].icucr = 0;
340 disable_opsput_irq(M32R_IRQ_SIO0_S);
341
342 /* SIO1 : receive */
343 irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
344 irq_desc[M32R_IRQ_SIO1_R].handler = &opsput_irq_type;
345 irq_desc[M32R_IRQ_SIO1_R].action = 0;
346 irq_desc[M32R_IRQ_SIO1_R].depth = 1;
347 icu_data[M32R_IRQ_SIO1_R].icucr = 0;
348 disable_opsput_irq(M32R_IRQ_SIO1_R);
349
350 /* SIO1 : send */
351 irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
352 irq_desc[M32R_IRQ_SIO1_S].handler = &opsput_irq_type;
353 irq_desc[M32R_IRQ_SIO1_S].action = 0;
354 irq_desc[M32R_IRQ_SIO1_S].depth = 1;
355 icu_data[M32R_IRQ_SIO1_S].icucr = 0;
356 disable_opsput_irq(M32R_IRQ_SIO1_S);
357
358 /* DMA1 : */
359 irq_desc[M32R_IRQ_DMA1].status = IRQ_DISABLED;
360 irq_desc[M32R_IRQ_DMA1].handler = &opsput_irq_type;
361 irq_desc[M32R_IRQ_DMA1].action = 0;
362 irq_desc[M32R_IRQ_DMA1].depth = 1;
363 icu_data[M32R_IRQ_DMA1].icucr = 0;
364 disable_opsput_irq(M32R_IRQ_DMA1);
365
366#ifdef CONFIG_SERIAL_M32R_PLDSIO
367 /* INT#1: SIO0 Receive on PLD */
368 irq_desc[PLD_IRQ_SIO0_RCV].status = IRQ_DISABLED;
369 irq_desc[PLD_IRQ_SIO0_RCV].handler = &opsput_pld_irq_type;
370 irq_desc[PLD_IRQ_SIO0_RCV].action = 0;
371 irq_desc[PLD_IRQ_SIO0_RCV].depth = 1; /* disable nested irq */
372 pld_icu_data[irq2pldirq(PLD_IRQ_SIO0_RCV)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD03;
373 disable_opsput_pld_irq(PLD_IRQ_SIO0_RCV);
374
375 /* INT#1: SIO0 Send on PLD */
376 irq_desc[PLD_IRQ_SIO0_SND].status = IRQ_DISABLED;
377 irq_desc[PLD_IRQ_SIO0_SND].handler = &opsput_pld_irq_type;
378 irq_desc[PLD_IRQ_SIO0_SND].action = 0;
379 irq_desc[PLD_IRQ_SIO0_SND].depth = 1; /* disable nested irq */
380 pld_icu_data[irq2pldirq(PLD_IRQ_SIO0_SND)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD03;
381 disable_opsput_pld_irq(PLD_IRQ_SIO0_SND);
382#endif /* CONFIG_SERIAL_M32R_PLDSIO */
383
384#if defined(CONFIG_M32R_CFC)
385 /* INT#1: CFC IREQ on PLD */
386 irq_desc[PLD_IRQ_CFIREQ].status = IRQ_DISABLED;
387 irq_desc[PLD_IRQ_CFIREQ].handler = &opsput_pld_irq_type;
388 irq_desc[PLD_IRQ_CFIREQ].action = 0;
389 irq_desc[PLD_IRQ_CFIREQ].depth = 1; /* disable nested irq */
390 pld_icu_data[irq2pldirq(PLD_IRQ_CFIREQ)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD01; /* 'L' level sense */
391 disable_opsput_pld_irq(PLD_IRQ_CFIREQ);
392
393 /* INT#1: CFC Insert on PLD */
394 irq_desc[PLD_IRQ_CFC_INSERT].status = IRQ_DISABLED;
395 irq_desc[PLD_IRQ_CFC_INSERT].handler = &opsput_pld_irq_type;
396 irq_desc[PLD_IRQ_CFC_INSERT].action = 0;
397 irq_desc[PLD_IRQ_CFC_INSERT].depth = 1; /* disable nested irq */
398 pld_icu_data[irq2pldirq(PLD_IRQ_CFC_INSERT)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD00; /* 'L' edge sense */
399 disable_opsput_pld_irq(PLD_IRQ_CFC_INSERT);
400
401 /* INT#1: CFC Eject on PLD */
402 irq_desc[PLD_IRQ_CFC_EJECT].status = IRQ_DISABLED;
403 irq_desc[PLD_IRQ_CFC_EJECT].handler = &opsput_pld_irq_type;
404 irq_desc[PLD_IRQ_CFC_EJECT].action = 0;
405 irq_desc[PLD_IRQ_CFC_EJECT].depth = 1; /* disable nested irq */
406 pld_icu_data[irq2pldirq(PLD_IRQ_CFC_EJECT)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD02; /* 'H' edge sense */
407 disable_opsput_pld_irq(PLD_IRQ_CFC_EJECT);
408#endif /* CONFIG_M32R_CFC */
409
410
411 /*
412 * INT0# is used for LAN, DIO
413 * We enable it here.
414 */
415 icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD11;
416 enable_opsput_irq(M32R_IRQ_INT0);
417
418 /*
419 * INT1# is used for UART, MMC, CF Controller in FPGA.
420 * We enable it here.
421 */
422 icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD11;
423 enable_opsput_irq(M32R_IRQ_INT1);
424
425#if defined(CONFIG_USB)
426 outw(USBCR_OTGS, USBCR); /* USBCR: non-OTG */
427
428 irq_desc[OPSPUT_LCD_IRQ_USB_INT1].status = IRQ_DISABLED;
429 irq_desc[OPSPUT_LCD_IRQ_USB_INT1].handler = &opsput_lcdpld_irq_type;
430 irq_desc[OPSPUT_LCD_IRQ_USB_INT1].action = 0;
431 irq_desc[OPSPUT_LCD_IRQ_USB_INT1].depth = 1;
432 lcdpld_icu_data[irq2lcdpldirq(OPSPUT_LCD_IRQ_USB_INT1)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD01; /* "L" level sense */
433 disable_opsput_lcdpld_irq(OPSPUT_LCD_IRQ_USB_INT1);
434#endif
435 /*
436 * INT2# is used for BAT, USB, AUDIO
437 * We enable it here.
438 */
439 icu_data[M32R_IRQ_INT2].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD01;
440 enable_opsput_irq(M32R_IRQ_INT2);
441
442//#if defined(CONFIG_VIDEO_M32R_AR)
443 /*
444 * INT3# is used for AR
445 */
446 irq_desc[M32R_IRQ_INT3].status = IRQ_DISABLED;
447 irq_desc[M32R_IRQ_INT3].handler = &opsput_irq_type;
448 irq_desc[M32R_IRQ_INT3].action = 0;
449 irq_desc[M32R_IRQ_INT3].depth = 1;
450 icu_data[M32R_IRQ_INT3].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
451 disable_opsput_irq(M32R_IRQ_INT3);
452//#endif /* CONFIG_VIDEO_M32R_AR */
453}
454
455#define LAN_IOSTART 0x300
456#define LAN_IOEND 0x320
457static struct resource smc91x_resources[] = {
458 [0] = {
459 .start = (LAN_IOSTART),
460 .end = (LAN_IOEND),
461 .flags = IORESOURCE_MEM,
462 },
463 [1] = {
464 .start = OPSPUT_LAN_IRQ_LAN,
465 .end = OPSPUT_LAN_IRQ_LAN,
466 .flags = IORESOURCE_IRQ,
467 }
468};
469
470static struct platform_device smc91x_device = {
471 .name = "smc91x",
472 .id = 0,
473 .num_resources = ARRAY_SIZE(smc91x_resources),
474 .resource = smc91x_resources,
475};
476
477static int __init platform_init(void)
478{
479 platform_device_register(&smc91x_device);
480 return 0;
481}
482arch_initcall(platform_init);
diff --git a/arch/m32r/kernel/setup_usrv.c b/arch/m32r/kernel/setup_usrv.c
new file mode 100644
index 000000000000..fe417be5e3e9
--- /dev/null
+++ b/arch/m32r/kernel/setup_usrv.c
@@ -0,0 +1,256 @@
1/*
2 * linux/arch/m32r/kernel/setup_usrv.c
3 *
4 * Setup routines for MITSUBISHI uServer
5 *
6 * Copyright (c) 2001, 2002, 2003 Hiroyuki Kondo, Hirokazu Takata,
7 * Hitoshi Yamamoto
8 */
9
10#include <linux/config.h>
11#include <linux/irq.h>
12#include <linux/kernel.h>
13#include <linux/init.h>
14
15#include <asm/system.h>
16#include <asm/m32r.h>
17#include <asm/io.h>
18
19#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
20
21#if !defined(CONFIG_SMP)
22typedef struct {
23 unsigned long icucr; /* ICU Control Register */
24} icu_data_t;
25#endif /* CONFIG_SMP */
26
27icu_data_t icu_data[M32700UT_NUM_CPU_IRQ];
28
29static void disable_mappi_irq(unsigned int irq)
30{
31 unsigned long port, data;
32
33 port = irq2port(irq);
34 data = icu_data[irq].icucr|M32R_ICUCR_ILEVEL7;
35 outl(data, port);
36}
37
38static void enable_mappi_irq(unsigned int irq)
39{
40 unsigned long port, data;
41
42 port = irq2port(irq);
43 data = icu_data[irq].icucr|M32R_ICUCR_IEN|M32R_ICUCR_ILEVEL6;
44 outl(data, port);
45}
46
47static void mask_and_ack_mappi(unsigned int irq)
48{
49 disable_mappi_irq(irq);
50}
51
52static void end_mappi_irq(unsigned int irq)
53{
54 enable_mappi_irq(irq);
55}
56
57static unsigned int startup_mappi_irq(unsigned int irq)
58{
59 enable_mappi_irq(irq);
60 return 0;
61}
62
63static void shutdown_mappi_irq(unsigned int irq)
64{
65 unsigned long port;
66
67 port = irq2port(irq);
68 outl(M32R_ICUCR_ILEVEL7, port);
69}
70
71static struct hw_interrupt_type mappi_irq_type =
72{
73 "M32700-IRQ",
74 startup_mappi_irq,
75 shutdown_mappi_irq,
76 enable_mappi_irq,
77 disable_mappi_irq,
78 mask_and_ack_mappi,
79 end_mappi_irq
80};
81
82/*
83 * Interrupt Control Unit of PLD on M32700UT (Level 2)
84 */
85#define irq2pldirq(x) ((x) - M32700UT_PLD_IRQ_BASE)
86#define pldirq2port(x) (unsigned long)((int)PLD_ICUCR1 + \
87 (((x) - 1) * sizeof(unsigned short)))
88
89typedef struct {
90 unsigned short icucr; /* ICU Control Register */
91} pld_icu_data_t;
92
93static pld_icu_data_t pld_icu_data[M32700UT_NUM_PLD_IRQ];
94
95static void disable_m32700ut_pld_irq(unsigned int irq)
96{
97 unsigned long port, data;
98 unsigned int pldirq;
99
100 pldirq = irq2pldirq(irq);
101 port = pldirq2port(pldirq);
102 data = pld_icu_data[pldirq].icucr|PLD_ICUCR_ILEVEL7;
103 outw(data, port);
104}
105
106static void enable_m32700ut_pld_irq(unsigned int irq)
107{
108 unsigned long port, data;
109 unsigned int pldirq;
110
111 pldirq = irq2pldirq(irq);
112 port = pldirq2port(pldirq);
113 data = pld_icu_data[pldirq].icucr|PLD_ICUCR_IEN|PLD_ICUCR_ILEVEL6;
114 outw(data, port);
115}
116
117static void mask_and_ack_m32700ut_pld(unsigned int irq)
118{
119 disable_m32700ut_pld_irq(irq);
120}
121
122static void end_m32700ut_pld_irq(unsigned int irq)
123{
124 enable_m32700ut_pld_irq(irq);
125 end_mappi_irq(M32R_IRQ_INT1);
126}
127
128static unsigned int startup_m32700ut_pld_irq(unsigned int irq)
129{
130 enable_m32700ut_pld_irq(irq);
131 return 0;
132}
133
134static void shutdown_m32700ut_pld_irq(unsigned int irq)
135{
136 unsigned long port;
137 unsigned int pldirq;
138
139 pldirq = irq2pldirq(irq);
140 port = pldirq2port(pldirq);
141 outw(PLD_ICUCR_ILEVEL7, port);
142}
143
144static struct hw_interrupt_type m32700ut_pld_irq_type =
145{
146 "USRV-PLD-IRQ",
147 startup_m32700ut_pld_irq,
148 shutdown_m32700ut_pld_irq,
149 enable_m32700ut_pld_irq,
150 disable_m32700ut_pld_irq,
151 mask_and_ack_m32700ut_pld,
152 end_m32700ut_pld_irq
153};
154
155void __init init_IRQ(void)
156{
157 static int once = 0;
158 int i;
159
160 if (once)
161 return;
162 else
163 once++;
164
165 /* MFT2 : system timer */
166 irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
167 irq_desc[M32R_IRQ_MFT2].handler = &mappi_irq_type;
168 irq_desc[M32R_IRQ_MFT2].action = 0;
169 irq_desc[M32R_IRQ_MFT2].depth = 1;
170 icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
171 disable_mappi_irq(M32R_IRQ_MFT2);
172
173#if defined(CONFIG_SERIAL_M32R_SIO)
174 /* SIO0_R : uart receive data */
175 irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
176 irq_desc[M32R_IRQ_SIO0_R].handler = &mappi_irq_type;
177 irq_desc[M32R_IRQ_SIO0_R].action = 0;
178 irq_desc[M32R_IRQ_SIO0_R].depth = 1;
179 icu_data[M32R_IRQ_SIO0_R].icucr = 0;
180 disable_mappi_irq(M32R_IRQ_SIO0_R);
181
182 /* SIO0_S : uart send data */
183 irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
184 irq_desc[M32R_IRQ_SIO0_S].handler = &mappi_irq_type;
185 irq_desc[M32R_IRQ_SIO0_S].action = 0;
186 irq_desc[M32R_IRQ_SIO0_S].depth = 1;
187 icu_data[M32R_IRQ_SIO0_S].icucr = 0;
188 disable_mappi_irq(M32R_IRQ_SIO0_S);
189
190 /* SIO1_R : uart receive data */
191 irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
192 irq_desc[M32R_IRQ_SIO1_R].handler = &mappi_irq_type;
193 irq_desc[M32R_IRQ_SIO1_R].action = 0;
194 irq_desc[M32R_IRQ_SIO1_R].depth = 1;
195 icu_data[M32R_IRQ_SIO1_R].icucr = 0;
196 disable_mappi_irq(M32R_IRQ_SIO1_R);
197
198 /* SIO1_S : uart send data */
199 irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
200 irq_desc[M32R_IRQ_SIO1_S].handler = &mappi_irq_type;
201 irq_desc[M32R_IRQ_SIO1_S].action = 0;
202 irq_desc[M32R_IRQ_SIO1_S].depth = 1;
203 icu_data[M32R_IRQ_SIO1_S].icucr = 0;
204 disable_mappi_irq(M32R_IRQ_SIO1_S);
205#endif /* CONFIG_SERIAL_M32R_SIO */
206
207 /* INT#67-#71: CFC#0 IREQ on PLD */
208 for (i = 0 ; i < CONFIG_CFC_NUM ; i++ ) {
209 irq_desc[PLD_IRQ_CF0 + i].status = IRQ_DISABLED;
210 irq_desc[PLD_IRQ_CF0 + i].handler = &m32700ut_pld_irq_type;
211 irq_desc[PLD_IRQ_CF0 + i].action = 0;
212 irq_desc[PLD_IRQ_CF0 + i].depth = 1; /* disable nested irq */
213 pld_icu_data[irq2pldirq(PLD_IRQ_CF0 + i)].icucr
214 = PLD_ICUCR_ISMOD01; /* 'L' level sense */
215 disable_m32700ut_pld_irq(PLD_IRQ_CF0 + i);
216 }
217
218#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
219 /* INT#76: 16552D#0 IREQ on PLD */
220 irq_desc[PLD_IRQ_UART0].status = IRQ_DISABLED;
221 irq_desc[PLD_IRQ_UART0].handler = &m32700ut_pld_irq_type;
222 irq_desc[PLD_IRQ_UART0].action = 0;
223 irq_desc[PLD_IRQ_UART0].depth = 1; /* disable nested irq */
224 pld_icu_data[irq2pldirq(PLD_IRQ_UART0)].icucr
225 = PLD_ICUCR_ISMOD03; /* 'H' level sense */
226 disable_m32700ut_pld_irq(PLD_IRQ_UART0);
227
228 /* INT#77: 16552D#1 IREQ on PLD */
229 irq_desc[PLD_IRQ_UART1].status = IRQ_DISABLED;
230 irq_desc[PLD_IRQ_UART1].handler = &m32700ut_pld_irq_type;
231 irq_desc[PLD_IRQ_UART1].action = 0;
232 irq_desc[PLD_IRQ_UART1].depth = 1; /* disable nested irq */
233 pld_icu_data[irq2pldirq(PLD_IRQ_UART1)].icucr
234 = PLD_ICUCR_ISMOD03; /* 'H' level sense */
235 disable_m32700ut_pld_irq(PLD_IRQ_UART1);
236#endif /* CONFIG_SERIAL_8250 || CONFIG_SERIAL_8250_MODULE */
237
238#if defined(CONFIG_IDC_AK4524) || defined(CONFIG_IDC_AK4524_MODULE)
239 /* INT#80: AK4524 IREQ on PLD */
240 irq_desc[PLD_IRQ_SNDINT].status = IRQ_DISABLED;
241 irq_desc[PLD_IRQ_SNDINT].handler = &m32700ut_pld_irq_type;
242 irq_desc[PLD_IRQ_SNDINT].action = 0;
243 irq_desc[PLD_IRQ_SNDINT].depth = 1; /* disable nested irq */
244 pld_icu_data[irq2pldirq(PLD_IRQ_SNDINT)].icucr
245 = PLD_ICUCR_ISMOD01; /* 'L' level sense */
246 disable_m32700ut_pld_irq(PLD_IRQ_SNDINT);
247#endif /* CONFIG_IDC_AK4524 || CONFIG_IDC_AK4524_MODULE */
248
249 /*
250 * INT1# is used for UART, MMC, CF Controller in FPGA.
251 * We enable it here.
252 */
253 icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_ISMOD11;
254 enable_mappi_irq(M32R_IRQ_INT1);
255}
256
diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c
new file mode 100644
index 000000000000..50311eb07a24
--- /dev/null
+++ b/arch/m32r/kernel/signal.c
@@ -0,0 +1,438 @@
1/*
2 * linux/arch/m32r/kernel/signal.c
3 *
4 * Copyright (c) 2003 Hitoshi Yamamoto
5 *
6 * Taken from i386 version.
7 * Copyright (C) 1991, 1992 Linus Torvalds
8 *
9 * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
10 * 2000-06-20 Pentium III FXSR, SSE support by Gareth Hughes
11 */
12
13#include <linux/config.h>
14#include <linux/sched.h>
15#include <linux/mm.h>
16#include <linux/smp.h>
17#include <linux/smp_lock.h>
18#include <linux/kernel.h>
19#include <linux/signal.h>
20#include <linux/errno.h>
21#include <linux/wait.h>
22#include <linux/unistd.h>
23#include <linux/stddef.h>
24#include <linux/personality.h>
25#include <linux/suspend.h>
26#include <asm/cacheflush.h>
27#include <asm/ucontext.h>
28#include <asm/uaccess.h>
29
30#define DEBUG_SIG 0
31
32#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
33
34int do_signal(struct pt_regs *, sigset_t *);
35
36asmlinkage int
37sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize,
38 unsigned long r2, unsigned long r3, unsigned long r4,
39 unsigned long r5, unsigned long r6, struct pt_regs regs)
40{
41 sigset_t saveset, newset;
42
43 /* XXX: Don't preclude handling different sized sigset_t's. */
44 if (sigsetsize != sizeof(sigset_t))
45 return -EINVAL;
46
47 if (copy_from_user(&newset, unewset, sizeof(newset)))
48 return -EFAULT;
49 sigdelsetmask(&newset, ~_BLOCKABLE);
50
51 spin_lock_irq(&current->sighand->siglock);
52 saveset = current->blocked;
53 current->blocked = newset;
54 recalc_sigpending();
55 spin_unlock_irq(&current->sighand->siglock);
56
57 regs.r0 = -EINTR;
58 while (1) {
59 current->state = TASK_INTERRUPTIBLE;
60 schedule();
61 if (do_signal(&regs, &saveset))
62 return regs.r0;
63 }
64}
65
66asmlinkage int
67sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
68 unsigned long r2, unsigned long r3, unsigned long r4,
69 unsigned long r5, unsigned long r6, struct pt_regs regs)
70{
71 return do_sigaltstack(uss, uoss, regs.spu);
72}
73
74
75/*
76 * Do a signal return; undo the signal stack.
77 */
78
79struct rt_sigframe
80{
81 int sig;
82 struct siginfo *pinfo;
83 void *puc;
84 struct siginfo info;
85 struct ucontext uc;
86// struct _fpstate fpstate;
87};
88
89static int
90restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
91 int *r0_p)
92{
93 unsigned int err = 0;
94
95 /* Always make any pending restarted system calls return -EINTR */
96 current_thread_info()->restart_block.fn = do_no_restart_syscall;
97
98#define COPY(x) err |= __get_user(regs->x, &sc->sc_##x)
99 COPY(r4);
100 COPY(r5);
101 COPY(r6);
102 COPY(pt_regs);
103 /* COPY(r0); Skip r0 */
104 COPY(r1);
105 COPY(r2);
106 COPY(r3);
107 COPY(r7);
108 COPY(r8);
109 COPY(r9);
110 COPY(r10);
111 COPY(r11);
112 COPY(r12);
113#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
114 COPY(acc0h);
115 COPY(acc0l);
116 COPY(acc1h);
117 COPY(acc1l);
118#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
119 COPY(acch);
120 COPY(accl);
121#else
122#error unknown isa configuration
123#endif
124 COPY(psw);
125 COPY(bpc);
126 COPY(bbpsw);
127 COPY(bbpc);
128 COPY(spu);
129 COPY(fp);
130 COPY(lr);
131 COPY(spi);
132#undef COPY
133
134 regs->syscall_nr = -1; /* disable syscall checks */
135 err |= __get_user(*r0_p, &sc->sc_r0);
136
137 return err;
138}
139
140asmlinkage int
141sys_rt_sigreturn(unsigned long r0, unsigned long r1,
142 unsigned long r2, unsigned long r3, unsigned long r4,
143 unsigned long r5, unsigned long r6, struct pt_regs regs)
144{
145 struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs.spu;
146 sigset_t set;
147 stack_t st;
148 int result;
149
150 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
151 goto badframe;
152 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
153 goto badframe;
154
155 sigdelsetmask(&set, ~_BLOCKABLE);
156 spin_lock_irq(&current->sighand->siglock);
157 current->blocked = set;
158 recalc_sigpending();
159 spin_unlock_irq(&current->sighand->siglock);
160
161 if (restore_sigcontext(&regs, &frame->uc.uc_mcontext, &result))
162 goto badframe;
163
164 if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
165 goto badframe;
166 /* It is more difficult to avoid calling this function than to
167 call it and ignore errors. */
168 do_sigaltstack(&st, NULL, regs.spu);
169
170 return result;
171
172badframe:
173 force_sig(SIGSEGV, current);
174 return 0;
175}
176
177/*
178 * Set up a signal frame.
179 */
180
181static int
182setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
183 unsigned long mask)
184{
185 int err = 0;
186
187#define COPY(x) err |= __put_user(regs->x, &sc->sc_##x)
188 COPY(r4);
189 COPY(r5);
190 COPY(r6);
191 COPY(pt_regs);
192 COPY(r0);
193 COPY(r1);
194 COPY(r2);
195 COPY(r3);
196 COPY(r7);
197 COPY(r8);
198 COPY(r9);
199 COPY(r10);
200 COPY(r11);
201 COPY(r12);
202#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
203 COPY(acc0h);
204 COPY(acc0l);
205 COPY(acc1h);
206 COPY(acc1l);
207#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
208 COPY(acch);
209 COPY(accl);
210#else
211#error unknown isa configuration
212#endif
213 COPY(psw);
214 COPY(bpc);
215 COPY(bbpsw);
216 COPY(bbpc);
217 COPY(spu);
218 COPY(fp);
219 COPY(lr);
220 COPY(spi);
221#undef COPY
222
223 err |= __put_user(mask, &sc->oldmask);
224
225 return err;
226}
227
228/*
229 * Determine which stack to use..
230 */
231static inline void __user *
232get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
233{
234 /* This is the X/Open sanctioned signal stack switching. */
235 if (ka->sa.sa_flags & SA_ONSTACK) {
236 if (sas_ss_flags(sp) == 0)
237 sp = current->sas_ss_sp + current->sas_ss_size;
238 }
239
240 return (void __user *)((sp - frame_size) & -8ul);
241}
242
243static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
244 sigset_t *set, struct pt_regs *regs)
245{
246 struct rt_sigframe __user *frame;
247 int err = 0;
248 int signal;
249
250 frame = get_sigframe(ka, regs->spu, sizeof(*frame));
251
252 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
253 goto give_sigsegv;
254
255 signal = current_thread_info()->exec_domain
256 && current_thread_info()->exec_domain->signal_invmap
257 && sig < 32
258 ? current_thread_info()->exec_domain->signal_invmap[sig]
259 : sig;
260
261 err |= __put_user(signal, &frame->sig);
262 if (err)
263 goto give_sigsegv;
264
265 err |= __put_user(&frame->info, &frame->pinfo);
266 err |= __put_user(&frame->uc, &frame->puc);
267 err |= copy_siginfo_to_user(&frame->info, info);
268 if (err)
269 goto give_sigsegv;
270
271 /* Create the ucontext. */
272 err |= __put_user(0, &frame->uc.uc_flags);
273 err |= __put_user(0, &frame->uc.uc_link);
274 err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
275 err |= __put_user(sas_ss_flags(regs->spu),
276 &frame->uc.uc_stack.ss_flags);
277 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
278 err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]);
279 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
280 if (err)
281 goto give_sigsegv;
282
283 /* Set up to return from userspace. */
284 regs->lr = (unsigned long)ka->sa.sa_restorer;
285
286 /* Set up registers for signal handler */
287 regs->spu = (unsigned long)frame;
288 regs->r0 = signal; /* Arg for signal handler */
289 regs->r1 = (unsigned long)&frame->info;
290 regs->r2 = (unsigned long)&frame->uc;
291 regs->bpc = (unsigned long)ka->sa.sa_handler;
292
293 set_fs(USER_DS);
294
295#if DEBUG_SIG
296 printk("SIG deliver (%s:%d): sp=%p pc=%p\n",
297 current->comm, current->pid, frame, regs->pc);
298#endif
299
300 return;
301
302give_sigsegv:
303 force_sigsegv(sig, current);
304}
305
306/*
307 * OK, we're invoking a handler
308 */
309
310static void
311handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
312 sigset_t *oldset, struct pt_regs *regs)
313{
314 unsigned short inst;
315
316 /* Are we from a system call? */
317 if (regs->syscall_nr >= 0) {
318 /* If so, check system call restarting.. */
319 switch (regs->r0) {
320 case -ERESTART_RESTARTBLOCK:
321 case -ERESTARTNOHAND:
322 regs->r0 = -EINTR;
323 break;
324
325 case -ERESTARTSYS:
326 if (!(ka->sa.sa_flags & SA_RESTART)) {
327 regs->r0 = -EINTR;
328 break;
329 }
330 /* fallthrough */
331 case -ERESTARTNOINTR:
332 regs->r0 = regs->orig_r0;
333 inst = *(unsigned short *)(regs->bpc - 2);
334 if ((inst & 0xfff0) == 0x10f0) /* trap ? */
335 regs->bpc -= 2;
336 else
337 regs->bpc -= 4;
338 }
339 }
340
341 /* Set up the stack frame */
342 setup_rt_frame(sig, ka, info, oldset, regs);
343
344 if (!(ka->sa.sa_flags & SA_NODEFER)) {
345 spin_lock_irq(&current->sighand->siglock);
346 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
347 sigaddset(&current->blocked,sig);
348 recalc_sigpending();
349 spin_unlock_irq(&current->sighand->siglock);
350 }
351}
352
353/*
354 * Note that 'init' is a special process: it doesn't get signals it doesn't
355 * want to handle. Thus you cannot kill init even with a SIGKILL even by
356 * mistake.
357 */
358int do_signal(struct pt_regs *regs, sigset_t *oldset)
359{
360 siginfo_t info;
361 int signr;
362 struct k_sigaction ka;
363 unsigned short inst;
364
365 /*
366 * We want the common case to go fast, which
367 * is why we may in certain cases get here from
368 * kernel mode. Just return without doing anything
369 * if so.
370 */
371 if (!user_mode(regs))
372 return 1;
373
374 if (current->flags & PF_FREEZE) {
375 refrigerator(0);
376 goto no_signal;
377 }
378
379 if (!oldset)
380 oldset = &current->blocked;
381
382 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
383 if (signr > 0) {
384 /* Reenable any watchpoints before delivering the
385 * signal to user space. The processor register will
386 * have been cleared if the watchpoint triggered
387 * inside the kernel.
388 */
389
390 /* Whee! Actually deliver the signal. */
391 handle_signal(signr, &ka, &info, oldset, regs);
392 return 1;
393 }
394
395 no_signal:
396 /* Did we come from a system call? */
397 if (regs->syscall_nr >= 0) {
398 /* Restart the system call - no handlers present */
399 if (regs->r0 == -ERESTARTNOHAND ||
400 regs->r0 == -ERESTARTSYS ||
401 regs->r0 == -ERESTARTNOINTR) {
402 regs->r0 = regs->orig_r0;
403 inst = *(unsigned short *)(regs->bpc - 2);
404 if ((inst & 0xfff0) == 0x10f0) /* trap ? */
405 regs->bpc -= 2;
406 else
407 regs->bpc -= 4;
408 }
409 if (regs->r0 == -ERESTART_RESTARTBLOCK){
410 regs->r0 = regs->orig_r0;
411 regs->r7 = __NR_restart_syscall;
412 inst = *(unsigned short *)(regs->bpc - 2);
413 if ((inst & 0xfff0) == 0x10f0) /* trap ? */
414 regs->bpc -= 2;
415 else
416 regs->bpc -= 4;
417 }
418 }
419 return 0;
420}
421
422/*
423 * notification of userspace execution resumption
424 * - triggered by current->work.notify_resume
425 */
426void do_notify_resume(struct pt_regs *regs, sigset_t *oldset,
427 __u32 thread_info_flags)
428{
429 /* Pending single-step? */
430 if (thread_info_flags & _TIF_SINGLESTEP)
431 clear_thread_flag(TIF_SINGLESTEP);
432
433 /* deal with pending signal delivery */
434 if (thread_info_flags & _TIF_SIGPENDING)
435 do_signal(regs,oldset);
436
437 clear_thread_flag(TIF_IRET);
438}
diff --git a/arch/m32r/kernel/smp.c b/arch/m32r/kernel/smp.c
new file mode 100644
index 000000000000..48b187f2d2b3
--- /dev/null
+++ b/arch/m32r/kernel/smp.c
@@ -0,0 +1,965 @@
1/*
2 * linux/arch/m32r/kernel/smp.c
3 *
4 * M32R SMP support routines.
5 *
6 * Copyright (c) 2001, 2002 Hitoshi Yamamoto
7 *
8 * Taken from i386 version.
9 * (c) 1995 Alan Cox, Building #3 <alan@redhat.com>
10 * (c) 1998-99, 2000 Ingo Molnar <mingo@redhat.com>
11 *
12 * This code is released under the GNU General Public License version 2 or
13 * later.
14 */
15
16#undef DEBUG_SMP
17
18#include <linux/irq.h>
19#include <linux/interrupt.h>
20#include <linux/spinlock.h>
21#include <linux/mm.h>
22#include <linux/smp.h>
23#include <linux/profile.h>
24#include <linux/cpu.h>
25
26#include <asm/cacheflush.h>
27#include <asm/pgalloc.h>
28#include <asm/atomic.h>
29#include <asm/io.h>
30#include <asm/mmu_context.h>
31#include <asm/m32r.h>
32
33/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
34/* Data structures and variables */
35/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
36
37/*
38 * Structure and data for smp_call_function(). This is designed to minimise
39 * static memory requirements. It also looks cleaner.
40 */
41static DEFINE_SPINLOCK(call_lock);
42
43struct call_data_struct {
44 void (*func) (void *info);
45 void *info;
46 atomic_t started;
47 atomic_t finished;
48 int wait;
49} __attribute__ ((__aligned__(SMP_CACHE_BYTES)));
50
51static struct call_data_struct *call_data;
52
53/*
54 * For flush_cache_all()
55 */
56static DEFINE_SPINLOCK(flushcache_lock);
57static volatile unsigned long flushcache_cpumask = 0;
58
59/*
60 * For flush_tlb_others()
61 */
62static volatile cpumask_t flush_cpumask;
63static struct mm_struct *flush_mm;
64static struct vm_area_struct *flush_vma;
65static volatile unsigned long flush_va;
66static DEFINE_SPINLOCK(tlbstate_lock);
67#define FLUSH_ALL 0xffffffff
68
69DECLARE_PER_CPU(int, prof_multiplier);
70DECLARE_PER_CPU(int, prof_old_multiplier);
71DECLARE_PER_CPU(int, prof_counter);
72
73extern spinlock_t ipi_lock[];
74
75/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
76/* Function Prototypes */
77/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
78
79void smp_send_reschedule(int);
80void smp_reschedule_interrupt(void);
81
82void smp_flush_cache_all(void);
83void smp_flush_cache_all_interrupt(void);
84
85void smp_flush_tlb_all(void);
86static void flush_tlb_all_ipi(void *);
87
88void smp_flush_tlb_mm(struct mm_struct *);
89void smp_flush_tlb_range(struct vm_area_struct *, unsigned long, \
90 unsigned long);
91void smp_flush_tlb_page(struct vm_area_struct *, unsigned long);
92static void flush_tlb_others(cpumask_t, struct mm_struct *,
93 struct vm_area_struct *, unsigned long);
94void smp_invalidate_interrupt(void);
95
96void smp_send_stop(void);
97static void stop_this_cpu(void *);
98
99int smp_call_function(void (*) (void *), void *, int, int);
100void smp_call_function_interrupt(void);
101
102void smp_send_timer(void);
103void smp_ipi_timer_interrupt(struct pt_regs *);
104void smp_local_timer_interrupt(struct pt_regs *);
105
106void send_IPI_allbutself(int, int);
107static void send_IPI_mask(cpumask_t, int, int);
108unsigned long send_IPI_mask_phys(cpumask_t, int, int);
109
110/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
111/* Rescheduling request Routines */
112/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
113
114/*==========================================================================*
115 * Name: smp_send_reschedule
116 *
117 * Description: This routine requests other CPU to execute rescheduling.
118 * 1.Send 'RESCHEDULE_IPI' to other CPU.
119 * Request other CPU to execute 'smp_reschedule_interrupt()'.
120 *
121 * Born on Date: 2002.02.05
122 *
123 * Arguments: cpu_id - Target CPU ID
124 *
125 * Returns: void (cannot fail)
126 *
127 * Modification log:
128 * Date Who Description
129 * ---------- --- --------------------------------------------------------
130 *
131 *==========================================================================*/
132void smp_send_reschedule(int cpu_id)
133{
134 WARN_ON(cpu_is_offline(cpu_id));
135 send_IPI_mask(cpumask_of_cpu(cpu_id), RESCHEDULE_IPI, 1);
136}
137
138/*==========================================================================*
139 * Name: smp_reschedule_interrupt
140 *
141 * Description: This routine executes on CPU which received
142 * 'RESCHEDULE_IPI'.
143 * Rescheduling is processed at the exit of interrupt
144 * operation.
145 *
146 * Born on Date: 2002.02.05
147 *
148 * Arguments: NONE
149 *
150 * Returns: void (cannot fail)
151 *
152 * Modification log:
153 * Date Who Description
154 * ---------- --- --------------------------------------------------------
155 *
156 *==========================================================================*/
157void smp_reschedule_interrupt(void)
158{
159 /* nothing to do */
160}
161
162/*==========================================================================*
163 * Name: smp_flush_cache_all
164 *
165 * Description: This routine sends a 'INVALIDATE_CACHE_IPI' to all other
166 * CPUs in the system.
167 *
168 * Born on Date: 2003-05-28
169 *
170 * Arguments: NONE
171 *
172 * Returns: void (cannot fail)
173 *
174 * Modification log:
175 * Date Who Description
176 * ---------- --- --------------------------------------------------------
177 *
178 *==========================================================================*/
179void smp_flush_cache_all(void)
180{
181 cpumask_t cpumask;
182 unsigned long *mask;
183
184 preempt_disable();
185 cpumask = cpu_online_map;
186 cpu_clear(smp_processor_id(), cpumask);
187 spin_lock(&flushcache_lock);
188 mask=cpus_addr(cpumask);
189 atomic_set_mask(*mask, (atomic_t *)&flushcache_cpumask);
190 send_IPI_mask(cpumask, INVALIDATE_CACHE_IPI, 0);
191 _flush_cache_copyback_all();
192 while (flushcache_cpumask)
193 mb();
194 spin_unlock(&flushcache_lock);
195 preempt_enable();
196}
197
198void smp_flush_cache_all_interrupt(void)
199{
200 _flush_cache_copyback_all();
201 clear_bit(smp_processor_id(), &flushcache_cpumask);
202}
203
204/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
205/* TLB flush request Routins */
206/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
207
208/*==========================================================================*
209 * Name: smp_flush_tlb_all
210 *
211 * Description: This routine flushes all processes TLBs.
212 * 1.Request other CPU to execute 'flush_tlb_all_ipi()'.
213 * 2.Execute 'do_flush_tlb_all_local()'.
214 *
215 * Born on Date: 2002.02.05
216 *
217 * Arguments: NONE
218 *
219 * Returns: void (cannot fail)
220 *
221 * Modification log:
222 * Date Who Description
223 * ---------- --- --------------------------------------------------------
224 *
225 *==========================================================================*/
226void smp_flush_tlb_all(void)
227{
228 unsigned long flags;
229
230 preempt_disable();
231 local_irq_save(flags);
232 __flush_tlb_all();
233 local_irq_restore(flags);
234 smp_call_function(flush_tlb_all_ipi, 0, 1, 1);
235 preempt_enable();
236}
237
238/*==========================================================================*
239 * Name: flush_tlb_all_ipi
240 *
241 * Description: This routine flushes all local TLBs.
242 * 1.Execute 'do_flush_tlb_all_local()'.
243 *
244 * Born on Date: 2002.02.05
245 *
246 * Arguments: *info - not used
247 *
248 * Returns: void (cannot fail)
249 *
250 * Modification log:
251 * Date Who Description
252 * ---------- --- --------------------------------------------------------
253 *
254 *==========================================================================*/
255static void flush_tlb_all_ipi(void *info)
256{
257 __flush_tlb_all();
258}
259
260/*==========================================================================*
261 * Name: smp_flush_tlb_mm
262 *
263 * Description: This routine flushes the specified mm context TLB's.
264 *
265 * Born on Date: 2002.02.05
266 *
267 * Arguments: *mm - a pointer to the mm struct for flush TLB
268 *
269 * Returns: void (cannot fail)
270 *
271 * Modification log:
272 * Date Who Description
273 * ---------- --- --------------------------------------------------------
274 *
275 *==========================================================================*/
276void smp_flush_tlb_mm(struct mm_struct *mm)
277{
278 int cpu_id = smp_processor_id();
279 cpumask_t cpu_mask;
280 unsigned long *mmc = &mm->context[cpu_id];
281 unsigned long flags;
282
283 preempt_disable();
284 cpu_mask = mm->cpu_vm_mask;
285 cpu_clear(cpu_id, cpu_mask);
286
287 if (*mmc != NO_CONTEXT) {
288 local_irq_save(flags);
289 *mmc = NO_CONTEXT;
290 if (mm == current->mm)
291 activate_context(mm);
292 else
293 cpu_clear(cpu_id, mm->cpu_vm_mask);
294 local_irq_restore(flags);
295 }
296 if (!cpus_empty(cpu_mask))
297 flush_tlb_others(cpu_mask, mm, NULL, FLUSH_ALL);
298
299 preempt_enable();
300}
301
302/*==========================================================================*
303 * Name: smp_flush_tlb_range
304 *
305 * Description: This routine flushes a range of pages.
306 *
307 * Born on Date: 2002.02.05
308 *
309 * Arguments: *mm - a pointer to the mm struct for flush TLB
310 * start - not used
311 * end - not used
312 *
313 * Returns: void (cannot fail)
314 *
315 * Modification log:
316 * Date Who Description
317 * ---------- --- --------------------------------------------------------
318 *
319 *==========================================================================*/
320void smp_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
321 unsigned long end)
322{
323 smp_flush_tlb_mm(vma->vm_mm);
324}
325
326/*==========================================================================*
327 * Name: smp_flush_tlb_page
328 *
329 * Description: This routine flushes one page.
330 *
331 * Born on Date: 2002.02.05
332 *
333 * Arguments: *vma - a pointer to the vma struct include va
334 * va - virtual address for flush TLB
335 *
336 * Returns: void (cannot fail)
337 *
338 * Modification log:
339 * Date Who Description
340 * ---------- --- --------------------------------------------------------
341 *
342 *==========================================================================*/
343void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long va)
344{
345 struct mm_struct *mm = vma->vm_mm;
346 int cpu_id = smp_processor_id();
347 cpumask_t cpu_mask;
348 unsigned long *mmc = &mm->context[cpu_id];
349 unsigned long flags;
350
351 preempt_disable();
352 cpu_mask = mm->cpu_vm_mask;
353 cpu_clear(cpu_id, cpu_mask);
354
355#ifdef DEBUG_SMP
356 if (!mm)
357 BUG();
358#endif
359
360 if (*mmc != NO_CONTEXT) {
361 local_irq_save(flags);
362 va &= PAGE_MASK;
363 va |= (*mmc & MMU_CONTEXT_ASID_MASK);
364 __flush_tlb_page(va);
365 local_irq_restore(flags);
366 }
367 if (!cpus_empty(cpu_mask))
368 flush_tlb_others(cpu_mask, mm, vma, va);
369
370 preempt_enable();
371}
372
373/*==========================================================================*
374 * Name: flush_tlb_others
375 *
376 * Description: This routine requests other CPU to execute flush TLB.
377 * 1.Setup parmeters.
378 * 2.Send 'INVALIDATE_TLB_IPI' to other CPU.
379 * Request other CPU to execute 'smp_invalidate_interrupt()'.
380 * 3.Wait for other CPUs operation finished.
381 *
382 * Born on Date: 2002.02.05
383 *
384 * Arguments: cpumask - bitmap of target CPUs
385 * *mm - a pointer to the mm struct for flush TLB
386 * *vma - a pointer to the vma struct include va
387 * va - virtual address for flush TLB
388 *
389 * Returns: void (cannot fail)
390 *
391 * Modification log:
392 * Date Who Description
393 * ---------- --- --------------------------------------------------------
394 *
395 *==========================================================================*/
396static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
397 struct vm_area_struct *vma, unsigned long va)
398{
399 unsigned long *mask;
400#ifdef DEBUG_SMP
401 unsigned long flags;
402 __save_flags(flags);
403 if (!(flags & 0x0040)) /* Interrupt Disable NONONO */
404 BUG();
405#endif /* DEBUG_SMP */
406
407 /*
408 * A couple of (to be removed) sanity checks:
409 *
410 * - we do not send IPIs to not-yet booted CPUs.
411 * - current CPU must not be in mask
412 * - mask must exist :)
413 */
414 BUG_ON(cpus_empty(cpumask));
415
416 BUG_ON(cpu_isset(smp_processor_id(), cpumask));
417 BUG_ON(!mm);
418
419 /* If a CPU which we ran on has gone down, OK. */
420 cpus_and(cpumask, cpumask, cpu_online_map);
421 if (cpus_empty(cpumask))
422 return;
423
424 /*
425 * i'm not happy about this global shared spinlock in the
426 * MM hot path, but we'll see how contended it is.
427 * Temporarily this turns IRQs off, so that lockups are
428 * detected by the NMI watchdog.
429 */
430 spin_lock(&tlbstate_lock);
431
432 flush_mm = mm;
433 flush_vma = vma;
434 flush_va = va;
435 mask=cpus_addr(cpumask);
436 atomic_set_mask(*mask, (atomic_t *)&flush_cpumask);
437
438 /*
439 * We have to send the IPI only to
440 * CPUs affected.
441 */
442 send_IPI_mask(cpumask, INVALIDATE_TLB_IPI, 0);
443
444 while (!cpus_empty(flush_cpumask)) {
445 /* nothing. lockup detection does not belong here */
446 mb();
447 }
448
449 flush_mm = NULL;
450 flush_vma = NULL;
451 flush_va = 0;
452 spin_unlock(&tlbstate_lock);
453}
454
455/*==========================================================================*
456 * Name: smp_invalidate_interrupt
457 *
458 * Description: This routine executes on CPU which received
459 * 'INVALIDATE_TLB_IPI'.
460 * 1.Flush local TLB.
461 * 2.Report flush TLB process was finished.
462 *
463 * Born on Date: 2002.02.05
464 *
465 * Arguments: NONE
466 *
467 * Returns: void (cannot fail)
468 *
469 * Modification log:
470 * Date Who Description
471 * ---------- --- --------------------------------------------------------
472 *
473 *==========================================================================*/
474void smp_invalidate_interrupt(void)
475{
476 int cpu_id = smp_processor_id();
477 unsigned long *mmc = &flush_mm->context[cpu_id];
478
479 if (!cpu_isset(cpu_id, flush_cpumask))
480 return;
481
482 if (flush_va == FLUSH_ALL) {
483 *mmc = NO_CONTEXT;
484 if (flush_mm == current->active_mm)
485 activate_context(flush_mm);
486 else
487 cpu_clear(cpu_id, flush_mm->cpu_vm_mask);
488 } else {
489 unsigned long va = flush_va;
490
491 if (*mmc != NO_CONTEXT) {
492 va &= PAGE_MASK;
493 va |= (*mmc & MMU_CONTEXT_ASID_MASK);
494 __flush_tlb_page(va);
495 }
496 }
497 cpu_clear(cpu_id, flush_cpumask);
498}
499
500/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
501/* Stop CPU request Routins */
502/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
503
504/*==========================================================================*
505 * Name: smp_send_stop
506 *
507 * Description: This routine requests stop all CPUs.
508 * 1.Request other CPU to execute 'stop_this_cpu()'.
509 *
510 * Born on Date: 2002.02.05
511 *
512 * Arguments: NONE
513 *
514 * Returns: void (cannot fail)
515 *
516 * Modification log:
517 * Date Who Description
518 * ---------- --- --------------------------------------------------------
519 *
520 *==========================================================================*/
521void smp_send_stop(void)
522{
523 smp_call_function(stop_this_cpu, NULL, 1, 0);
524}
525
526/*==========================================================================*
527 * Name: stop_this_cpu
528 *
529 * Description: This routine halt CPU.
530 *
531 * Born on Date: 2002.02.05
532 *
533 * Arguments: NONE
534 *
535 * Returns: void (cannot fail)
536 *
537 * Modification log:
538 * Date Who Description
539 * ---------- --- --------------------------------------------------------
540 *
541 *==========================================================================*/
542static void stop_this_cpu(void *dummy)
543{
544 int cpu_id = smp_processor_id();
545
546 /*
547 * Remove this CPU:
548 */
549 cpu_clear(cpu_id, cpu_online_map);
550
551 /*
552 * PSW IE = 1;
553 * IMASK = 0;
554 * goto SLEEP
555 */
556 local_irq_disable();
557 outl(0, M32R_ICU_IMASK_PORTL);
558 inl(M32R_ICU_IMASK_PORTL); /* dummy read */
559 local_irq_enable();
560
561 for ( ; ; );
562}
563
564/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
565/* Call function Routins */
566/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
567
568/*==========================================================================*
569 * Name: smp_call_function
570 *
571 * Description: This routine sends a 'CALL_FUNCTION_IPI' to all other CPUs
572 * in the system.
573 *
574 * Born on Date: 2002.02.05
575 *
576 * Arguments: *func - The function to run. This must be fast and
577 * non-blocking.
578 * *info - An arbitrary pointer to pass to the function.
579 * nonatomic - currently unused.
580 * wait - If true, wait (atomically) until function has
581 * completed on other CPUs.
582 *
583 * Returns: 0 on success, else a negative status code. Does not return
584 * until remote CPUs are nearly ready to execute <<func>> or
585 * are or have executed.
586 *
587 * Cautions: You must not call this function with disabled interrupts or
588 * from a hardware interrupt handler, you may call it from a
589 * bottom half handler.
590 *
591 * Modification log:
592 * Date Who Description
593 * ---------- --- --------------------------------------------------------
594 *
595 *==========================================================================*/
596int smp_call_function(void (*func) (void *info), void *info, int nonatomic,
597 int wait)
598{
599 struct call_data_struct data;
600 int cpus;
601
602#ifdef DEBUG_SMP
603 unsigned long flags;
604 __save_flags(flags);
605 if (!(flags & 0x0040)) /* Interrupt Disable NONONO */
606 BUG();
607#endif /* DEBUG_SMP */
608
609 /* Holding any lock stops cpus from going down. */
610 spin_lock(&call_lock);
611 cpus = num_online_cpus() - 1;
612
613 if (!cpus) {
614 spin_unlock(&call_lock);
615 return 0;
616 }
617
618 /* Can deadlock when called with interrupts disabled */
619 WARN_ON(irqs_disabled());
620
621 data.func = func;
622 data.info = info;
623 atomic_set(&data.started, 0);
624 data.wait = wait;
625 if (wait)
626 atomic_set(&data.finished, 0);
627
628 call_data = &data;
629 mb();
630
631 /* Send a message to all other CPUs and wait for them to respond */
632 send_IPI_allbutself(CALL_FUNCTION_IPI, 0);
633
634 /* Wait for response */
635 while (atomic_read(&data.started) != cpus)
636 barrier();
637
638 if (wait)
639 while (atomic_read(&data.finished) != cpus)
640 barrier();
641 spin_unlock(&call_lock);
642
643 return 0;
644}
645
646/*==========================================================================*
647 * Name: smp_call_function_interrupt
648 *
649 * Description: This routine executes on CPU which received
650 * 'CALL_FUNCTION_IPI'.
651 *
652 * Born on Date: 2002.02.05
653 *
654 * Arguments: NONE
655 *
656 * Returns: void (cannot fail)
657 *
658 * Modification log:
659 * Date Who Description
660 * ---------- --- --------------------------------------------------------
661 *
662 *==========================================================================*/
663void smp_call_function_interrupt(void)
664{
665 void (*func) (void *info) = call_data->func;
666 void *info = call_data->info;
667 int wait = call_data->wait;
668
669 /*
670 * Notify initiating CPU that I've grabbed the data and am
671 * about to execute the function
672 */
673 mb();
674 atomic_inc(&call_data->started);
675 /*
676 * At this point the info structure may be out of scope unless wait==1
677 */
678 irq_enter();
679 (*func)(info);
680 irq_exit();
681
682 if (wait) {
683 mb();
684 atomic_inc(&call_data->finished);
685 }
686}
687
688/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
689/* Timer Routins */
690/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
691
692/*==========================================================================*
693 * Name: smp_send_timer
694 *
695 * Description: This routine sends a 'LOCAL_TIMER_IPI' to all other CPUs
696 * in the system.
697 *
698 * Born on Date: 2002.02.05
699 *
700 * Arguments: NONE
701 *
702 * Returns: void (cannot fail)
703 *
704 * Modification log:
705 * Date Who Description
706 * ---------- --- --------------------------------------------------------
707 *
708 *==========================================================================*/
709void smp_send_timer(void)
710{
711 send_IPI_allbutself(LOCAL_TIMER_IPI, 1);
712}
713
714/*==========================================================================*
715 * Name: smp_send_timer
716 *
717 * Description: This routine executes on CPU which received
718 * 'LOCAL_TIMER_IPI'.
719 *
720 * Born on Date: 2002.02.05
721 *
722 * Arguments: *regs - a pointer to the saved regster info
723 *
724 * Returns: void (cannot fail)
725 *
726 * Modification log:
727 * Date Who Description
728 * ---------- --- --------------------------------------------------------
729 *
730 *==========================================================================*/
731void smp_ipi_timer_interrupt(struct pt_regs *regs)
732{
733 irq_enter();
734 smp_local_timer_interrupt(regs);
735 irq_exit();
736}
737
738/*==========================================================================*
739 * Name: smp_local_timer_interrupt
740 *
741 * Description: Local timer interrupt handler. It does both profiling and
742 * process statistics/rescheduling.
743 * We do profiling in every local tick, statistics/rescheduling
744 * happen only every 'profiling multiplier' ticks. The default
745 * multiplier is 1 and it can be changed by writing the new
746 * multiplier value into /proc/profile.
747 *
748 * Born on Date: 2002.02.05
749 *
750 * Arguments: *regs - a pointer to the saved regster info
751 *
752 * Returns: void (cannot fail)
753 *
754 * Original: arch/i386/kernel/apic.c
755 *
756 * Modification log:
757 * Date Who Description
758 * ---------- --- --------------------------------------------------------
759 * 2003-06-24 hy use per_cpu structure.
760 *==========================================================================*/
761void smp_local_timer_interrupt(struct pt_regs *regs)
762{
763 int user = user_mode(regs);
764 int cpu_id = smp_processor_id();
765
766 /*
767 * The profiling function is SMP safe. (nothing can mess
768 * around with "current", and the profiling counters are
769 * updated with atomic operations). This is especially
770 * useful with a profiling multiplier != 1
771 */
772
773 profile_tick(CPU_PROFILING, regs);
774
775 if (--per_cpu(prof_counter, cpu_id) <= 0) {
776 /*
777 * The multiplier may have changed since the last time we got
778 * to this point as a result of the user writing to
779 * /proc/profile. In this case we need to adjust the APIC
780 * timer accordingly.
781 *
782 * Interrupts are already masked off at this point.
783 */
784 per_cpu(prof_counter, cpu_id)
785 = per_cpu(prof_multiplier, cpu_id);
786 if (per_cpu(prof_counter, cpu_id)
787 != per_cpu(prof_old_multiplier, cpu_id))
788 {
789 per_cpu(prof_old_multiplier, cpu_id)
790 = per_cpu(prof_counter, cpu_id);
791 }
792
793 update_process_times(user);
794 }
795}
796
797/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
798/* Send IPI Routins */
799/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
800
801/*==========================================================================*
802 * Name: send_IPI_allbutself
803 *
804 * Description: This routine sends a IPI to all other CPUs in the system.
805 *
806 * Born on Date: 2002.02.05
807 *
808 * Arguments: ipi_num - Number of IPI
809 * try - 0 : Send IPI certainly.
810 * !0 : The following IPI is not sended when Target CPU
811 * has not received the before IPI.
812 *
813 * Returns: void (cannot fail)
814 *
815 * Modification log:
816 * Date Who Description
817 * ---------- --- --------------------------------------------------------
818 *
819 *==========================================================================*/
820void send_IPI_allbutself(int ipi_num, int try)
821{
822 cpumask_t cpumask;
823
824 cpumask = cpu_online_map;
825 cpu_clear(smp_processor_id(), cpumask);
826
827 send_IPI_mask(cpumask, ipi_num, try);
828}
829
830/*==========================================================================*
831 * Name: send_IPI_mask
832 *
833 * Description: This routine sends a IPI to CPUs in the system.
834 *
835 * Born on Date: 2002.02.05
836 *
837 * Arguments: cpu_mask - Bitmap of target CPUs logical ID
838 * ipi_num - Number of IPI
839 * try - 0 : Send IPI certainly.
840 * !0 : The following IPI is not sended when Target CPU
841 * has not received the before IPI.
842 *
843 * Returns: void (cannot fail)
844 *
845 * Modification log:
846 * Date Who Description
847 * ---------- --- --------------------------------------------------------
848 *
849 *==========================================================================*/
850static void send_IPI_mask(cpumask_t cpumask, int ipi_num, int try)
851{
852 cpumask_t physid_mask, tmp;
853 int cpu_id, phys_id;
854 int num_cpus = num_online_cpus();
855
856 if (num_cpus <= 1) /* NO MP */
857 return;
858
859 cpus_and(tmp, cpumask, cpu_online_map);
860 BUG_ON(!cpus_equal(cpumask, tmp));
861
862 physid_mask = CPU_MASK_NONE;
863 for_each_cpu_mask(cpu_id, cpumask){
864 if ((phys_id = cpu_to_physid(cpu_id)) != -1)
865 cpu_set(phys_id, physid_mask);
866 }
867
868 send_IPI_mask_phys(physid_mask, ipi_num, try);
869}
870
871/*==========================================================================*
872 * Name: send_IPI_mask_phys
873 *
874 * Description: This routine sends a IPI to other CPUs in the system.
875 *
876 * Born on Date: 2002.02.05
877 *
878 * Arguments: cpu_mask - Bitmap of target CPUs physical ID
879 * ipi_num - Number of IPI
880 * try - 0 : Send IPI certainly.
881 * !0 : The following IPI is not sended when Target CPU
882 * has not received the before IPI.
883 *
884 * Returns: IPICRi regster value.
885 *
886 * Modification log:
887 * Date Who Description
888 * ---------- --- --------------------------------------------------------
889 *
890 *==========================================================================*/
891unsigned long send_IPI_mask_phys(cpumask_t physid_mask, int ipi_num,
892 int try)
893{
894 spinlock_t *ipilock;
895 unsigned long flags = 0;
896 volatile unsigned long *ipicr_addr;
897 unsigned long ipicr_val;
898 unsigned long my_physid_mask;
899 unsigned long mask = cpus_addr(physid_mask)[0];
900
901
902 if (mask & ~physids_coerce(phys_cpu_present_map))
903 BUG();
904 if (ipi_num >= NR_IPIS)
905 BUG();
906
907 mask <<= IPI_SHIFT;
908 ipilock = &ipi_lock[ipi_num];
909 ipicr_addr = (volatile unsigned long *)(M32R_ICU_IPICR_ADDR
910 + (ipi_num << 2));
911 my_physid_mask = ~(1 << smp_processor_id());
912
913 /*
914 * lock ipi_lock[i]
915 * check IPICRi == 0
916 * write IPICRi (send IPIi)
917 * unlock ipi_lock[i]
918 */
919 __asm__ __volatile__ (
920 ";; LOCK ipi_lock[i] \n\t"
921 ".fillinsn \n"
922 "1: \n\t"
923 "mvfc %1, psw \n\t"
924 "clrpsw #0x40 -> nop \n\t"
925 DCACHE_CLEAR("r4", "r5", "%2")
926 "lock r4, @%2 \n\t"
927 "addi r4, #-1 \n\t"
928 "unlock r4, @%2 \n\t"
929 "mvtc %1, psw \n\t"
930 "bnez r4, 2f \n\t"
931 LOCK_SECTION_START(".balign 4 \n\t")
932 ".fillinsn \n"
933 "2: \n\t"
934 "ld r4, @%2 \n\t"
935 "blez r4, 2b \n\t"
936 "bra 1b \n\t"
937 LOCK_SECTION_END
938 ";; CHECK IPICRi == 0 \n\t"
939 ".fillinsn \n"
940 "3: \n\t"
941 "ld %0, @%3 \n\t"
942 "and %0, %6 \n\t"
943 "beqz %0, 4f \n\t"
944 "bnez %5, 5f \n\t"
945 "bra 3b \n\t"
946 ";; WRITE IPICRi (send IPIi) \n\t"
947 ".fillinsn \n"
948 "4: \n\t"
949 "st %4, @%3 \n\t"
950 ";; UNLOCK ipi_lock[i] \n\t"
951 ".fillinsn \n"
952 "5: \n\t"
953 "ldi r4, #1 \n\t"
954 "st r4, @%2 \n\t"
955 : "=&r"(ipicr_val)
956 : "r"(flags), "r"(&ipilock->slock), "r"(ipicr_addr),
957 "r"(mask), "r"(try), "r"(my_physid_mask)
958 : "memory", "r4"
959#ifdef CONFIG_CHIP_M32700_TS1
960 , "r5"
961#endif /* CONFIG_CHIP_M32700_TS1 */
962 );
963
964 return ipicr_val;
965}
diff --git a/arch/m32r/kernel/smpboot.c b/arch/m32r/kernel/smpboot.c
new file mode 100644
index 000000000000..f9a0e723478d
--- /dev/null
+++ b/arch/m32r/kernel/smpboot.c
@@ -0,0 +1,630 @@
1/*
2 * linux/arch/m32r/kernel/smpboot.c
3 * orig : i386 2.4.10
4 *
5 * M32R SMP booting functions
6 *
7 * Copyright (c) 2001, 2002, 2003 Hitoshi Yamamoto
8 *
9 * Taken from i386 version.
10 * (c) 1995 Alan Cox, Building #3 <alan@redhat.com>
11 * (c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com>
12 *
13 * Much of the core SMP work is based on previous work by Thomas Radke, to
14 * whom a great many thanks are extended.
15 *
16 * Thanks to Intel for making available several different Pentium,
17 * Pentium Pro and Pentium-II/Xeon MP machines.
18 * Original development of Linux SMP code supported by Caldera.
19 *
20 * This code is released under the GNU General Public License version 2 or
21 * later.
22 *
23 * Fixes
24 * Felix Koop : NR_CPUS used properly
25 * Jose Renau : Handle single CPU case.
26 * Alan Cox : By repeated request
27 * 8) - Total BogoMIP report.
28 * Greg Wright : Fix for kernel stacks panic.
29 * Erich Boleyn : MP v1.4 and additional changes.
30 * Matthias Sattler : Changes for 2.1 kernel map.
31 * Michel Lespinasse : Changes for 2.1 kernel map.
32 * Michael Chastain : Change trampoline.S to gnu as.
33 * Alan Cox : Dumb bug: 'B' step PPro's are fine
34 * Ingo Molnar : Added APIC timers, based on code
35 * from Jose Renau
36 * Ingo Molnar : various cleanups and rewrites
37 * Tigran Aivazian : fixed "0.00 in /proc/uptime on SMP" bug.
38 * Maciej W. Rozycki : Bits for genuine 82489DX APICs
39 * Martin J. Bligh : Added support for multi-quad systems
40 */
41
42#include <linux/config.h>
43#include <linux/init.h>
44#include <linux/mm.h>
45#include <linux/smp_lock.h>
46#include <linux/irq.h>
47#include <linux/bootmem.h>
48#include <linux/delay.h>
49
50#include <asm/io.h>
51#include <asm/pgalloc.h>
52#include <asm/tlbflush.h>
53
54#define DEBUG_SMP
55#ifdef DEBUG_SMP
56#define Dprintk(x...) printk(x)
57#else
58#define Dprintk(x...)
59#endif
60
61extern cpumask_t cpu_initialized;
62
63/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
64/* Data structures and variables */
65/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
66
67/* Processor that is doing the boot up */
68static unsigned int bsp_phys_id = -1;
69
70/* Bitmask of physically existing CPUs */
71physid_mask_t phys_cpu_present_map;
72
73/* Bitmask of currently online CPUs */
74cpumask_t cpu_online_map;
75
76cpumask_t cpu_bootout_map;
77cpumask_t cpu_bootin_map;
78cpumask_t cpu_callout_map;
79static cpumask_t cpu_callin_map;
80
81/* Per CPU bogomips and other parameters */
82struct cpuinfo_m32r cpu_data[NR_CPUS] __cacheline_aligned;
83
84static int cpucount;
85static cpumask_t smp_commenced_mask;
86
87extern struct {
88 void * spi;
89 unsigned short ss;
90} stack_start;
91
92/* which physical physical ID maps to which logical CPU number */
93static volatile int physid_2_cpu[NR_CPUS];
94
95/* which logical CPU number maps to which physical ID */
96volatile int cpu_2_physid[NR_CPUS];
97
98DEFINE_PER_CPU(int, prof_multiplier) = 1;
99DEFINE_PER_CPU(int, prof_old_multiplier) = 1;
100DEFINE_PER_CPU(int, prof_counter) = 1;
101
102spinlock_t ipi_lock[NR_IPIS];
103
104static unsigned int calibration_result;
105
106/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
107/* Function Prototypes */
108/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
109
110void smp_prepare_boot_cpu(void);
111void smp_prepare_cpus(unsigned int);
112static void smp_tune_scheduling(void);
113static void init_ipi_lock(void);
114static void do_boot_cpu(int);
115int __cpu_up(unsigned int);
116void smp_cpus_done(unsigned int);
117
118int start_secondary(void *);
119static void smp_callin(void);
120static void smp_online(void);
121
122static void show_mp_info(int);
123static void smp_store_cpu_info(int);
124static void show_cpu_info(int);
125int setup_profiling_timer(unsigned int);
126static void init_cpu_to_physid(void);
127static void map_cpu_to_physid(int, int);
128static void unmap_cpu_to_physid(int, int);
129
130/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
131/* Boot up APs Routins : BSP */
132/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
133void __devinit smp_prepare_boot_cpu(void)
134{
135 bsp_phys_id = hard_smp_processor_id();
136 physid_set(bsp_phys_id, phys_cpu_present_map);
137 cpu_set(0, cpu_online_map); /* BSP's cpu_id == 0 */
138 cpu_set(0, cpu_callout_map);
139 cpu_set(0, cpu_callin_map);
140
141 /*
142 * Initialize the logical to physical CPU number mapping
143 */
144 init_cpu_to_physid();
145 map_cpu_to_physid(0, bsp_phys_id);
146 current_thread_info()->cpu = 0;
147}
148
149/*==========================================================================*
150 * Name: smp_prepare_cpus (old smp_boot_cpus)
151 *
152 * Description: This routine boot up APs.
153 *
154 * Born on Date: 2002.02.05
155 *
156 * Arguments: NONE
157 *
158 * Returns: void (cannot fail)
159 *
160 * Modification log:
161 * Date Who Description
162 * ---------- --- --------------------------------------------------------
163 * 2003-06-24 hy modify for linux-2.5.69
164 *
165 *==========================================================================*/
166void __init smp_prepare_cpus(unsigned int max_cpus)
167{
168 int phys_id;
169 unsigned long nr_cpu;
170
171 nr_cpu = inl(M32R_FPGA_NUM_OF_CPUS_PORTL);
172 if (nr_cpu > NR_CPUS) {
173 printk(KERN_INFO "NUM_OF_CPUS reg. value [%ld] > NR_CPU [%d]",
174 nr_cpu, NR_CPUS);
175 goto smp_done;
176 }
177 for (phys_id = 0 ; phys_id < nr_cpu ; phys_id++)
178 physid_set(phys_id, phys_cpu_present_map);
179
180 show_mp_info(nr_cpu);
181
182 init_ipi_lock();
183
184 /*
185 * Setup boot CPU information
186 */
187 smp_store_cpu_info(0); /* Final full version of the data */
188 smp_tune_scheduling();
189
190 /*
191 * If SMP should be disabled, then really disable it!
192 */
193 if (!max_cpus) {
194 printk(KERN_INFO "SMP mode deactivated by commandline.\n");
195 goto smp_done;
196 }
197
198 /*
199 * Now scan the CPU present map and fire up the other CPUs.
200 */
201 Dprintk("CPU present map : %lx\n", physids_coerce(phys_cpu_present_map));
202
203 for (phys_id = 0 ; phys_id < NR_CPUS ; phys_id++) {
204 /*
205 * Don't even attempt to start the boot CPU!
206 */
207 if (phys_id == bsp_phys_id)
208 continue;
209
210 if (!physid_isset(phys_id, phys_cpu_present_map))
211 continue;
212
213 if ((max_cpus >= 0) && (max_cpus <= cpucount + 1))
214 continue;
215
216 do_boot_cpu(phys_id);
217
218 /*
219 * Make sure we unmap all failed CPUs
220 */
221 if (physid_to_cpu(phys_id) == -1) {
222 physid_clear(phys_id, phys_cpu_present_map);
223 printk("phys CPU#%d not responding - " \
224 "cannot use it.\n", phys_id);
225 }
226 }
227
228smp_done:
229 Dprintk("Boot done.\n");
230}
231
232static void __init smp_tune_scheduling(void)
233{
234 /* Nothing to do. */
235}
236
237/*
238 * init_ipi_lock : Initialize IPI locks.
239 */
240static void __init init_ipi_lock(void)
241{
242 int ipi;
243
244 for (ipi = 0 ; ipi < NR_IPIS ; ipi++)
245 spin_lock_init(&ipi_lock[ipi]);
246}
247
248/*==========================================================================*
249 * Name: do_boot_cpu
250 *
251 * Description: This routine boot up one AP.
252 *
253 * Born on Date: 2002.02.05
254 *
255 * Arguments: phys_id - Target CPU physical ID
256 *
257 * Returns: void (cannot fail)
258 *
259 * Modification log:
260 * Date Who Description
261 * ---------- --- --------------------------------------------------------
262 * 2003-06-24 hy modify for linux-2.5.69
263 *
264 *==========================================================================*/
265static void __init do_boot_cpu(int phys_id)
266{
267 struct task_struct *idle;
268 unsigned long send_status, boot_status;
269 int timeout, cpu_id;
270
271 cpu_id = ++cpucount;
272
273 /*
274 * We can't use kernel_thread since we must avoid to
275 * reschedule the child.
276 */
277 idle = fork_idle(cpu_id);
278 if (IS_ERR(idle))
279 panic("failed fork for CPU#%d.", cpu_id);
280
281 idle->thread.lr = (unsigned long)start_secondary;
282
283 map_cpu_to_physid(cpu_id, phys_id);
284
285 /* So we see what's up */
286 printk("Booting processor %d/%d\n", phys_id, cpu_id);
287 stack_start.spi = (void *)idle->thread.sp;
288 idle->thread_info->cpu = cpu_id;
289
290 /*
291 * Send Startup IPI
292 * 1.IPI received by CPU#(phys_id).
293 * 2.CPU#(phys_id) enter startup_AP (arch/m32r/kernel/head.S)
294 * 3.CPU#(phys_id) enter start_secondary()
295 */
296 send_status = 0;
297 boot_status = 0;
298
299 cpu_set(phys_id, cpu_bootout_map);
300
301 /* Send Startup IPI */
302 send_IPI_mask_phys(cpumask_of_cpu(phys_id), CPU_BOOT_IPI, 0);
303
304 Dprintk("Waiting for send to finish...\n");
305 timeout = 0;
306
307 /* Wait 100[ms] */
308 do {
309 Dprintk("+");
310 udelay(1000);
311 send_status = !cpu_isset(phys_id, cpu_bootin_map);
312 } while (send_status && (timeout++ < 100));
313
314 Dprintk("After Startup.\n");
315
316 if (!send_status) {
317 /*
318 * allow APs to start initializing.
319 */
320 Dprintk("Before Callout %d.\n", cpu_id);
321 cpu_set(cpu_id, cpu_callout_map);
322 Dprintk("After Callout %d.\n", cpu_id);
323
324 /*
325 * Wait 5s total for a response
326 */
327 for (timeout = 0; timeout < 5000; timeout++) {
328 if (cpu_isset(cpu_id, cpu_callin_map))
329 break; /* It has booted */
330 udelay(1000);
331 }
332
333 if (cpu_isset(cpu_id, cpu_callin_map)) {
334 /* number CPUs logically, starting from 1 (BSP is 0) */
335 Dprintk("OK.\n");
336 } else {
337 boot_status = 1;
338 printk("Not responding.\n");
339 }
340 } else
341 printk("IPI never delivered???\n");
342
343 if (send_status || boot_status) {
344 unmap_cpu_to_physid(cpu_id, phys_id);
345 cpu_clear(cpu_id, cpu_callout_map);
346 cpu_clear(cpu_id, cpu_callin_map);
347 cpu_clear(cpu_id, cpu_initialized);
348 cpucount--;
349 }
350}
351
352int __devinit __cpu_up(unsigned int cpu_id)
353{
354 int timeout;
355
356 cpu_set(cpu_id, smp_commenced_mask);
357
358 /*
359 * Wait 5s total for a response
360 */
361 for (timeout = 0; timeout < 5000; timeout++) {
362 if (cpu_isset(cpu_id, cpu_online_map))
363 break;
364 udelay(1000);
365 }
366 if (!cpu_isset(cpu_id, cpu_online_map))
367 BUG();
368
369 return 0;
370}
371
372void __init smp_cpus_done(unsigned int max_cpus)
373{
374 int cpu_id, timeout;
375 unsigned long bogosum = 0;
376
377 for (timeout = 0; timeout < 5000; timeout++) {
378 if (cpus_equal(cpu_callin_map, cpu_online_map))
379 break;
380 udelay(1000);
381 }
382 if (!cpus_equal(cpu_callin_map, cpu_online_map))
383 BUG();
384
385 for (cpu_id = 0 ; cpu_id < num_online_cpus() ; cpu_id++)
386 show_cpu_info(cpu_id);
387
388 /*
389 * Allow the user to impress friends.
390 */
391 Dprintk("Before bogomips.\n");
392 if (cpucount) {
393 for_each_cpu_mask(cpu_id, cpu_online_map)
394 bogosum += cpu_data[cpu_id].loops_per_jiffy;
395
396 printk(KERN_INFO "Total of %d processors activated " \
397 "(%lu.%02lu BogoMIPS).\n", cpucount + 1,
398 bogosum / (500000 / HZ),
399 (bogosum / (5000 / HZ)) % 100);
400 Dprintk("Before bogocount - setting activated=1.\n");
401 }
402}
403
404/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
405/* Activate a secondary processor Routins */
406/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
407
408/*==========================================================================*
409 * Name: start_secondary
410 *
411 * Description: This routine activate a secondary processor.
412 *
413 * Born on Date: 2002.02.05
414 *
415 * Arguments: *unused - currently unused.
416 *
417 * Returns: void (cannot fail)
418 *
419 * Modification log:
420 * Date Who Description
421 * ---------- --- --------------------------------------------------------
422 * 2003-06-24 hy modify for linux-2.5.69
423 *
424 *==========================================================================*/
425int __init start_secondary(void *unused)
426{
427 cpu_init();
428 smp_callin();
429 while (!cpu_isset(smp_processor_id(), smp_commenced_mask))
430 cpu_relax();
431
432 smp_online();
433
434 /*
435 * low-memory mappings have been cleared, flush them from
436 * the local TLBs too.
437 */
438 local_flush_tlb_all();
439
440 cpu_idle();
441 return 0;
442}
443
444/*==========================================================================*
445 * Name: smp_callin
446 *
447 * Description: This routine activate a secondary processor.
448 *
449 * Born on Date: 2002.02.05
450 *
451 * Arguments: NONE
452 *
453 * Returns: void (cannot fail)
454 *
455 * Modification log:
456 * Date Who Description
457 * ---------- --- --------------------------------------------------------
458 * 2003-06-24 hy modify for linux-2.5.69
459 *
460 *==========================================================================*/
461static void __init smp_callin(void)
462{
463 int phys_id = hard_smp_processor_id();
464 int cpu_id = smp_processor_id();
465 unsigned long timeout;
466
467 if (cpu_isset(cpu_id, cpu_callin_map)) {
468 printk("huh, phys CPU#%d, CPU#%d already present??\n",
469 phys_id, cpu_id);
470 BUG();
471 }
472 Dprintk("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpu_id, phys_id);
473
474 /* Waiting 2s total for startup (udelay is not yet working) */
475 timeout = jiffies + (2 * HZ);
476 while (time_before(jiffies, timeout)) {
477 /* Has the boot CPU finished it's STARTUP sequence ? */
478 if (cpu_isset(cpu_id, cpu_callout_map))
479 break;
480 cpu_relax();
481 }
482
483 if (!time_before(jiffies, timeout)) {
484 printk("BUG: CPU#%d started up but did not get a callout!\n",
485 cpu_id);
486 BUG();
487 }
488
489 /* Allow the master to continue. */
490 cpu_set(cpu_id, cpu_callin_map);
491}
492
493static void __init smp_online(void)
494{
495 int cpu_id = smp_processor_id();
496
497 local_irq_enable();
498
499 /* Get our bogomips. */
500 calibrate_delay();
501
502 /* Save our processor parameters */
503 smp_store_cpu_info(cpu_id);
504
505 cpu_set(cpu_id, cpu_online_map);
506}
507
508/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
509/* Boot up CPUs common Routins */
510/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
511static void __init show_mp_info(int nr_cpu)
512{
513 int i;
514 char cpu_model0[17], cpu_model1[17], cpu_ver[9];
515
516 strncpy(cpu_model0, (char *)M32R_FPGA_CPU_NAME_ADDR, 16);
517 strncpy(cpu_model1, (char *)M32R_FPGA_MODEL_ID_ADDR, 16);
518 strncpy(cpu_ver, (char *)M32R_FPGA_VERSION_ADDR, 8);
519
520 cpu_model0[16] = '\0';
521 for (i = 15 ; i >= 0 ; i--) {
522 if (cpu_model0[i] != ' ')
523 break;
524 cpu_model0[i] = '\0';
525 }
526 cpu_model1[16] = '\0';
527 for (i = 15 ; i >= 0 ; i--) {
528 if (cpu_model1[i] != ' ')
529 break;
530 cpu_model1[i] = '\0';
531 }
532 cpu_ver[8] = '\0';
533 for (i = 7 ; i >= 0 ; i--) {
534 if (cpu_ver[i] != ' ')
535 break;
536 cpu_ver[i] = '\0';
537 }
538
539 printk(KERN_INFO "M32R-mp information\n");
540 printk(KERN_INFO " On-chip CPUs : %d\n", nr_cpu);
541 printk(KERN_INFO " CPU model : %s/%s(%s)\n", cpu_model0,
542 cpu_model1, cpu_ver);
543}
544
545/*
546 * The bootstrap kernel entry code has set these up. Save them for
547 * a given CPU
548 */
549static void __init smp_store_cpu_info(int cpu_id)
550{
551 struct cpuinfo_m32r *ci = cpu_data + cpu_id;
552
553 *ci = boot_cpu_data;
554 ci->loops_per_jiffy = loops_per_jiffy;
555}
556
557static void __init show_cpu_info(int cpu_id)
558{
559 struct cpuinfo_m32r *ci = &cpu_data[cpu_id];
560
561 printk("CPU#%d : ", cpu_id);
562
563#define PRINT_CLOCK(name, value) \
564 printk(name " clock %d.%02dMHz", \
565 ((value) / 1000000), ((value) % 1000000) / 10000)
566
567 PRINT_CLOCK("CPU", (int)ci->cpu_clock);
568 PRINT_CLOCK(", Bus", (int)ci->bus_clock);
569 printk(", loops_per_jiffy[%ld]\n", ci->loops_per_jiffy);
570}
571
572/*
573 * the frequency of the profiling timer can be changed
574 * by writing a multiplier value into /proc/profile.
575 */
576int setup_profiling_timer(unsigned int multiplier)
577{
578 int i;
579
580 /*
581 * Sanity check. [at least 500 APIC cycles should be
582 * between APIC interrupts as a rule of thumb, to avoid
583 * irqs flooding us]
584 */
585 if ( (!multiplier) || (calibration_result / multiplier < 500))
586 return -EINVAL;
587
588 /*
589 * Set the new multiplier for each CPU. CPUs don't start using the
590 * new values until the next timer interrupt in which they do process
591 * accounting. At that time they also adjust their APIC timers
592 * accordingly.
593 */
594 for (i = 0; i < NR_CPUS; ++i)
595 per_cpu(prof_multiplier, i) = multiplier;
596
597 return 0;
598}
599
600/* Initialize all maps between cpu number and apicids */
601static void __init init_cpu_to_physid(void)
602{
603 int i;
604
605 for (i = 0 ; i < NR_CPUS ; i++) {
606 cpu_2_physid[i] = -1;
607 physid_2_cpu[i] = -1;
608 }
609}
610
611/*
612 * set up a mapping between cpu and apicid. Uses logical apicids for multiquad,
613 * else physical apic ids
614 */
615static void __init map_cpu_to_physid(int cpu_id, int phys_id)
616{
617 physid_2_cpu[phys_id] = cpu_id;
618 cpu_2_physid[cpu_id] = phys_id;
619}
620
621/*
622 * undo a mapping between cpu and apicid. Uses logical apicids for multiquad,
623 * else physical apic ids
624 */
625static void __init unmap_cpu_to_physid(int cpu_id, int phys_id)
626{
627 physid_2_cpu[phys_id] = -1;
628 cpu_2_physid[cpu_id] = -1;
629}
630
diff --git a/arch/m32r/kernel/sys_m32r.c b/arch/m32r/kernel/sys_m32r.c
new file mode 100644
index 000000000000..e0500e12c5fb
--- /dev/null
+++ b/arch/m32r/kernel/sys_m32r.c
@@ -0,0 +1,217 @@
1/*
2 * linux/arch/m32r/kernel/sys_m32r.c
3 *
4 * This file contains various random system calls that
5 * have a non-standard calling sequence on the Linux/M32R platform.
6 *
7 * Taken from i386 version.
8 */
9
10#include <linux/config.h>
11#include <linux/errno.h>
12#include <linux/sched.h>
13#include <linux/mm.h>
14#include <linux/smp.h>
15#include <linux/smp_lock.h>
16#include <linux/sem.h>
17#include <linux/msg.h>
18#include <linux/shm.h>
19#include <linux/stat.h>
20#include <linux/syscalls.h>
21#include <linux/mman.h>
22#include <linux/file.h>
23#include <linux/utsname.h>
24
25#include <asm/uaccess.h>
26#include <asm/cachectl.h>
27#include <asm/cacheflush.h>
28#include <asm/ipc.h>
29
30/*
31 * sys_tas() - test-and-set
32 * linuxthreads testing version
33 */
34#ifndef CONFIG_SMP
35asmlinkage int sys_tas(int *addr)
36{
37 int oldval;
38 unsigned long flags;
39
40 if (!access_ok(VERIFY_WRITE, addr, sizeof (int)))
41 return -EFAULT;
42 local_irq_save(flags);
43 oldval = *addr;
44 *addr = 1;
45 local_irq_restore(flags);
46 return oldval;
47}
48#else /* CONFIG_SMP */
49#include <linux/spinlock.h>
50
51static DEFINE_SPINLOCK(tas_lock);
52
53asmlinkage int sys_tas(int *addr)
54{
55 int oldval;
56
57 if (!access_ok(VERIFY_WRITE, addr, sizeof (int)))
58 return -EFAULT;
59
60 _raw_spin_lock(&tas_lock);
61 oldval = *addr;
62 *addr = 1;
63 _raw_spin_unlock(&tas_lock);
64
65 return oldval;
66}
67#endif /* CONFIG_SMP */
68
69/*
70 * sys_pipe() is the normal C calling standard for creating
71 * a pipe. It's not the way Unix traditionally does this, though.
72 */
73asmlinkage int
74sys_pipe(unsigned long r0, unsigned long r1, unsigned long r2,
75 unsigned long r3, unsigned long r4, unsigned long r5,
76 unsigned long r6, struct pt_regs regs)
77{
78 int fd[2];
79 int error;
80
81 error = do_pipe(fd);
82 if (!error) {
83 if (copy_to_user((void *)r0, (void *)fd, 2*sizeof(int)))
84 error = -EFAULT;
85 }
86 return error;
87}
88
89asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
90 unsigned long prot, unsigned long flags,
91 unsigned long fd, unsigned long pgoff)
92{
93 int error = -EBADF;
94 struct file *file = NULL;
95
96 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
97 if (!(flags & MAP_ANONYMOUS)) {
98 file = fget(fd);
99 if (!file)
100 goto out;
101 }
102
103 down_write(&current->mm->mmap_sem);
104 error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
105 up_write(&current->mm->mmap_sem);
106
107 if (file)
108 fput(file);
109out:
110 return error;
111}
112
113/*
114 * sys_ipc() is the de-multiplexer for the SysV IPC calls..
115 *
116 * This is really horribly ugly.
117 */
118asmlinkage int sys_ipc(uint call, int first, int second,
119 int third, void __user *ptr, long fifth)
120{
121 int version, ret;
122
123 version = call >> 16; /* hack for backward compatibility */
124 call &= 0xffff;
125
126 switch (call) {
127 case SEMOP:
128 return sys_semtimedop(first, (struct sembuf __user *)ptr,
129 second, NULL);
130 case SEMTIMEDOP:
131 return sys_semtimedop(first, (struct sembuf __user *)ptr,
132 second, (const struct timespec __user *)fifth);
133 case SEMGET:
134 return sys_semget (first, second, third);
135 case SEMCTL: {
136 union semun fourth;
137 if (!ptr)
138 return -EINVAL;
139 if (get_user(fourth.__pad, (void __user * __user *) ptr))
140 return -EFAULT;
141 return sys_semctl (first, second, third, fourth);
142 }
143
144 case MSGSND:
145 return sys_msgsnd (first, (struct msgbuf __user *) ptr,
146 second, third);
147 case MSGRCV:
148 switch (version) {
149 case 0: {
150 struct ipc_kludge tmp;
151 if (!ptr)
152 return -EINVAL;
153
154 if (copy_from_user(&tmp,
155 (struct ipc_kludge __user *) ptr,
156 sizeof (tmp)))
157 return -EFAULT;
158 return sys_msgrcv (first, tmp.msgp, second,
159 tmp.msgtyp, third);
160 }
161 default:
162 return sys_msgrcv (first,
163 (struct msgbuf __user *) ptr,
164 second, fifth, third);
165 }
166 case MSGGET:
167 return sys_msgget ((key_t) first, second);
168 case MSGCTL:
169 return sys_msgctl (first, second,
170 (struct msqid_ds __user *) ptr);
171 case SHMAT: {
172 ulong raddr;
173
174 if (!access_ok(VERIFY_WRITE, (ulong __user *) third,
175 sizeof(ulong)))
176 return -EFAULT;
177 ret = do_shmat (first, (char __user *) ptr, second, &raddr);
178 if (ret)
179 return ret;
180 return put_user (raddr, (ulong __user *) third);
181 }
182 case SHMDT:
183 return sys_shmdt ((char __user *)ptr);
184 case SHMGET:
185 return sys_shmget (first, second, third);
186 case SHMCTL:
187 return sys_shmctl (first, second,
188 (struct shmid_ds __user *) ptr);
189 default:
190 return -ENOSYS;
191 }
192}
193
194asmlinkage int sys_uname(struct old_utsname * name)
195{
196 int err;
197 if (!name)
198 return -EFAULT;
199 down_read(&uts_sem);
200 err=copy_to_user(name, &system_utsname, sizeof (*name));
201 up_read(&uts_sem);
202 return err?-EFAULT:0;
203}
204
205asmlinkage int sys_cacheflush(void *addr, int bytes, int cache)
206{
207 /* This should flush more selectivly ... */
208 _flush_cache_all();
209 return 0;
210}
211
212asmlinkage int sys_cachectl(char *addr, int nbytes, int op)
213{
214 /* Not implemented yet. */
215 return -ENOSYS;
216}
217
diff --git a/arch/m32r/kernel/time.c b/arch/m32r/kernel/time.c
new file mode 100644
index 000000000000..3c4707280a52
--- /dev/null
+++ b/arch/m32r/kernel/time.c
@@ -0,0 +1,318 @@
1/*
2 * linux/arch/m32r/kernel/time.c
3 *
4 * Copyright (c) 2001, 2002 Hiroyuki Kondo, Hirokazu Takata,
5 * Hitoshi Yamamoto
6 * Taken from i386 version.
7 * Copyright (C) 1991, 1992, 1995 Linus Torvalds
8 * Copyright (C) 1996, 1997, 1998 Ralf Baechle
9 *
10 * This file contains the time handling details for PC-style clocks as
11 * found in some MIPS systems.
12 *
13 * Some code taken from sh version.
14 * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
15 * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
16 */
17
18#undef DEBUG_TIMER
19
20#include <linux/config.h>
21#include <linux/errno.h>
22#include <linux/init.h>
23#include <linux/module.h>
24#include <linux/sched.h>
25#include <linux/kernel.h>
26#include <linux/param.h>
27#include <linux/string.h>
28#include <linux/mm.h>
29#include <linux/interrupt.h>
30#include <linux/profile.h>
31
32#include <asm/io.h>
33#include <asm/m32r.h>
34
35#include <asm/hw_irq.h>
36
37#ifdef CONFIG_SMP
38extern void send_IPI_allbutself(int, int);
39extern void smp_local_timer_interrupt(struct pt_regs *);
40#endif
41
42u64 jiffies_64 = INITIAL_JIFFIES;
43
44EXPORT_SYMBOL(jiffies_64);
45
46extern unsigned long wall_jiffies;
47#define TICK_SIZE (tick_nsec / 1000)
48
49/*
50 * Change this if you have some constant time drift
51 */
52
53/* This is for machines which generate the exact clock. */
54#define USECS_PER_JIFFY (1000000/HZ)
55
56static unsigned long latch;
57
58static unsigned long do_gettimeoffset(void)
59{
60 unsigned long elapsed_time = 0; /* [us] */
61
62#if defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_XNUX2) \
63 || defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_M32700) \
64 || defined(CONFIG_CHIP_OPSP)
65#ifndef CONFIG_SMP
66
67 unsigned long count;
68
69 /* timer count may underflow right here */
70 count = inl(M32R_MFT2CUT_PORTL);
71
72 if (inl(M32R_ICU_CR18_PORTL) & 0x00000100) /* underflow check */
73 count = 0;
74
75 count = (latch - count) * TICK_SIZE;
76 elapsed_time = (count + latch / 2) / latch;
77 /* NOTE: LATCH is equal to the "interval" value (= reload count). */
78
79#else /* CONFIG_SMP */
80 unsigned long count;
81 static unsigned long p_jiffies = -1;
82 static unsigned long p_count = 0;
83
84 /* timer count may underflow right here */
85 count = inl(M32R_MFT2CUT_PORTL);
86
87 if (jiffies == p_jiffies && count > p_count)
88 count = 0;
89
90 p_jiffies = jiffies;
91 p_count = count;
92
93 count = (latch - count) * TICK_SIZE;
94 elapsed_time = (count + latch / 2) / latch;
95 /* NOTE: LATCH is equal to the "interval" value (= reload count). */
96#endif /* CONFIG_SMP */
97#elif defined(CONFIG_CHIP_M32310)
98#warning do_gettimeoffse not implemented
99#else
100#error no chip configuration
101#endif
102
103 return elapsed_time;
104}
105
106/*
107 * This version of gettimeofday has near microsecond resolution.
108 */
109void do_gettimeofday(struct timeval *tv)
110{
111 unsigned long seq;
112 unsigned long usec, sec;
113 unsigned long max_ntp_tick = tick_usec - tickadj;
114
115 do {
116 unsigned long lost;
117
118 seq = read_seqbegin(&xtime_lock);
119
120 usec = do_gettimeoffset();
121 lost = jiffies - wall_jiffies;
122
123 /*
124 * If time_adjust is negative then NTP is slowing the clock
125 * so make sure not to go into next possible interval.
126 * Better to lose some accuracy than have time go backwards..
127 */
128 if (unlikely(time_adjust < 0)) {
129 usec = min(usec, max_ntp_tick);
130 if (lost)
131 usec += lost * max_ntp_tick;
132 } else if (unlikely(lost))
133 usec += lost * tick_usec;
134
135 sec = xtime.tv_sec;
136 usec += (xtime.tv_nsec / 1000);
137 } while (read_seqretry(&xtime_lock, seq));
138
139 while (usec >= 1000000) {
140 usec -= 1000000;
141 sec++;
142 }
143
144 tv->tv_sec = sec;
145 tv->tv_usec = usec;
146}
147
148EXPORT_SYMBOL(do_gettimeofday);
149
150int do_settimeofday(struct timespec *tv)
151{
152 time_t wtm_sec, sec = tv->tv_sec;
153 long wtm_nsec, nsec = tv->tv_nsec;
154
155 if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
156 return -EINVAL;
157
158 write_seqlock_irq(&xtime_lock);
159 /*
160 * This is revolting. We need to set "xtime" correctly. However, the
161 * value in this location is the value at the most recent update of
162 * wall time. Discover what correction gettimeofday() would have
163 * made, and then undo it!
164 */
165 nsec -= do_gettimeoffset() * NSEC_PER_USEC;
166 nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
167
168 wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
169 wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
170
171 set_normalized_timespec(&xtime, sec, nsec);
172 set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
173
174 time_adjust = 0; /* stop active adjtime() */
175 time_status |= STA_UNSYNC;
176 time_maxerror = NTP_PHASE_LIMIT;
177 time_esterror = NTP_PHASE_LIMIT;
178 write_sequnlock_irq(&xtime_lock);
179 clock_was_set();
180
181 return 0;
182}
183
184EXPORT_SYMBOL(do_settimeofday);
185
186/*
187 * In order to set the CMOS clock precisely, set_rtc_mmss has to be
188 * called 500 ms after the second nowtime has started, because when
189 * nowtime is written into the registers of the CMOS clock, it will
190 * jump to the next second precisely 500 ms later. Check the Motorola
191 * MC146818A or Dallas DS12887 data sheet for details.
192 *
193 * BUG: This routine does not handle hour overflow properly; it just
194 * sets the minutes. Usually you won't notice until after reboot!
195 */
196static inline int set_rtc_mmss(unsigned long nowtime)
197{
198 return 0;
199}
200
201/* last time the cmos clock got updated */
202static long last_rtc_update = 0;
203
204/*
205 * timer_interrupt() needs to keep up the real-time clock,
206 * as well as call the "do_timer()" routine every clocktick
207 */
208static inline void
209do_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
210{
211#ifndef CONFIG_SMP
212 profile_tick(CPU_PROFILING, regs);
213#endif
214 do_timer(regs);
215
216#ifndef CONFIG_SMP
217 update_process_times(user_mode(regs));
218#endif
219 /*
220 * If we have an externally synchronized Linux clock, then update
221 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
222 * called as close as possible to 500 ms before the new second starts.
223 */
224 if ((time_status & STA_UNSYNC) == 0
225 && xtime.tv_sec > last_rtc_update + 660
226 && (xtime.tv_nsec / 1000) >= 500000 - ((unsigned)TICK_SIZE) / 2
227 && (xtime.tv_nsec / 1000) <= 500000 + ((unsigned)TICK_SIZE) / 2)
228 {
229 if (set_rtc_mmss(xtime.tv_sec) == 0)
230 last_rtc_update = xtime.tv_sec;
231 else /* do it again in 60 s */
232 last_rtc_update = xtime.tv_sec - 600;
233 }
234 /* As we return to user mode fire off the other CPU schedulers..
235 this is basically because we don't yet share IRQ's around.
236 This message is rigged to be safe on the 386 - basically it's
237 a hack, so don't look closely for now.. */
238
239#ifdef CONFIG_SMP
240 smp_local_timer_interrupt(regs);
241#endif
242}
243
244irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
245{
246 write_seqlock(&xtime_lock);
247 do_timer_interrupt(irq, NULL, regs);
248 write_sequnlock(&xtime_lock);
249
250 return IRQ_HANDLED;
251}
252
253struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE,
254 "MFT2", NULL, NULL };
255
256void __init time_init(void)
257{
258 unsigned int epoch, year, mon, day, hour, min, sec;
259
260 sec = min = hour = day = mon = year = 0;
261 epoch = 0;
262
263 year = 23;
264 mon = 4;
265 day = 17;
266
267 /* Attempt to guess the epoch. This is the same heuristic as in rtc.c
268 so no stupid things will happen to timekeeping. Who knows, maybe
269 Ultrix also uses 1952 as epoch ... */
270 if (year > 10 && year < 44)
271 epoch = 1980;
272 else if (year < 96)
273 epoch = 1952;
274 year += epoch;
275
276 xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
277 xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
278 set_normalized_timespec(&wall_to_monotonic,
279 -xtime.tv_sec, -xtime.tv_nsec);
280
281#if defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_XNUX2) \
282 || defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_M32700) \
283 || defined(CONFIG_CHIP_OPSP)
284
285 /* M32102 MFT setup */
286 setup_irq(M32R_IRQ_MFT2, &irq0);
287 {
288 unsigned long bus_clock;
289 unsigned short divide;
290
291 bus_clock = boot_cpu_data.bus_clock;
292 divide = boot_cpu_data.timer_divide;
293 latch = (bus_clock/divide + HZ / 2) / HZ;
294
295 printk("Timer start : latch = %ld\n", latch);
296
297 outl((M32R_MFTMOD_CC_MASK | M32R_MFTMOD_TCCR \
298 |M32R_MFTMOD_CSSEL011), M32R_MFT2MOD_PORTL);
299 outl(latch, M32R_MFT2RLD_PORTL);
300 outl(latch, M32R_MFT2CUT_PORTL);
301 outl(0, M32R_MFT2CMPRLD_PORTL);
302 outl((M32R_MFTCR_MFT2MSK|M32R_MFTCR_MFT2EN), M32R_MFTCR_PORTL);
303 }
304
305#elif defined(CONFIG_CHIP_M32310)
306#warning time_init not implemented
307#else
308#error no chip configuration
309#endif
310}
311
312/*
313 * Scheduler clock - returns current time in nanosec units.
314 */
315unsigned long long sched_clock(void)
316{
317 return (unsigned long long)jiffies * (1000000000 / HZ);
318}
diff --git a/arch/m32r/kernel/traps.c b/arch/m32r/kernel/traps.c
new file mode 100644
index 000000000000..01922271d17e
--- /dev/null
+++ b/arch/m32r/kernel/traps.c
@@ -0,0 +1,332 @@
1/*
2 * linux/arch/m32r/kernel/traps.c
3 *
4 * Copyright (C) 2001, 2002 Hirokazu Takata, Hiroyuki Kondo,
5 * Hitoshi Yamamoto
6 */
7
8/* $Id$ */
9
10/*
11 * 'traps.c' handles hardware traps and faults after we have saved some
12 * state in 'entry.S'.
13 */
14#include <linux/config.h>
15#include <linux/init.h>
16#include <linux/kernel.h>
17#include <linux/kallsyms.h>
18#include <linux/stddef.h>
19#include <linux/ptrace.h>
20#include <linux/mm.h>
21#include <asm/page.h>
22#include <asm/processor.h>
23
24#include <asm/system.h>
25#include <asm/uaccess.h>
26#include <asm/io.h>
27#include <asm/atomic.h>
28
29#include <asm/smp.h>
30
31#include <linux/module.h>
32
33asmlinkage void alignment_check(void);
34asmlinkage void ei_handler(void);
35asmlinkage void rie_handler(void);
36asmlinkage void debug_trap(void);
37asmlinkage void cache_flushing_handler(void);
38
39#ifdef CONFIG_SMP
40extern void smp_reschedule_interrupt(void);
41extern void smp_invalidate_interrupt(void);
42extern void smp_call_function_interrupt(void);
43extern void smp_ipi_timer_interrupt(void);
44extern void smp_flush_cache_all_interrupt(void);
45
46/*
47 * for Boot AP function
48 */
49asm (
50 " .section .eit_vector4,\"ax\" \n"
51 " .global _AP_RE \n"
52 " .global startup_AP \n"
53 "_AP_RE: \n"
54 " .fill 32, 4, 0 \n"
55 "_AP_EI: bra startup_AP \n"
56 " .previous \n"
57);
58#endif /* CONFIG_SMP */
59
60extern unsigned long eit_vector[];
61#define BRA_INSN(func, entry) \
62 ((unsigned long)func - (unsigned long)eit_vector - entry*4)/4 \
63 + 0xff000000UL
64
65void set_eit_vector_entries(void)
66{
67 extern void default_eit_handler(void);
68 extern void system_call(void);
69 extern void pie_handler(void);
70 extern void ace_handler(void);
71 extern void tme_handler(void);
72 extern void _flush_cache_copyback_all(void);
73
74 eit_vector[0] = 0xd0c00001; /* seth r0, 0x01 */
75 eit_vector[1] = BRA_INSN(default_eit_handler, 1);
76 eit_vector[4] = 0xd0c00010; /* seth r0, 0x10 */
77 eit_vector[5] = BRA_INSN(default_eit_handler, 5);
78 eit_vector[8] = BRA_INSN(rie_handler, 8);
79 eit_vector[12] = BRA_INSN(alignment_check, 12);
80 eit_vector[16] = 0xff000000UL;
81 eit_vector[17] = BRA_INSN(debug_trap, 17);
82 eit_vector[18] = BRA_INSN(system_call, 18);
83 eit_vector[19] = 0xff000000UL;
84 eit_vector[20] = 0xff000000UL;
85 eit_vector[21] = 0xff000000UL;
86 eit_vector[22] = 0xff000000UL;
87 eit_vector[23] = 0xff000000UL;
88 eit_vector[24] = 0xff000000UL;
89 eit_vector[25] = 0xff000000UL;
90 eit_vector[26] = 0xff000000UL;
91 eit_vector[27] = 0xff000000UL;
92 eit_vector[28] = BRA_INSN(cache_flushing_handler, 28);
93 eit_vector[29] = 0xff000000UL;
94 eit_vector[30] = 0xff000000UL;
95 eit_vector[31] = 0xff000000UL;
96 eit_vector[32] = BRA_INSN(ei_handler, 32);
97 eit_vector[64] = BRA_INSN(pie_handler, 64);
98#ifdef CONFIG_MMU
99 eit_vector[68] = BRA_INSN(ace_handler, 68);
100 eit_vector[72] = BRA_INSN(tme_handler, 72);
101#endif /* CONFIG_MMU */
102#ifdef CONFIG_SMP
103 eit_vector[184] = (unsigned long)smp_reschedule_interrupt;
104 eit_vector[185] = (unsigned long)smp_invalidate_interrupt;
105 eit_vector[186] = (unsigned long)smp_call_function_interrupt;
106 eit_vector[187] = (unsigned long)smp_ipi_timer_interrupt;
107 eit_vector[188] = (unsigned long)smp_flush_cache_all_interrupt;
108 eit_vector[189] = 0;
109 eit_vector[190] = 0;
110 eit_vector[191] = 0;
111#endif
112 _flush_cache_copyback_all();
113}
114
115void __init trap_init(void)
116{
117 set_eit_vector_entries();
118
119 /*
120 * Should be a barrier for any external CPU state.
121 */
122 cpu_init();
123}
124
125int kstack_depth_to_print = 24;
126
127void show_trace(struct task_struct *task, unsigned long *stack)
128{
129 unsigned long addr;
130
131 if (!stack)
132 stack = (unsigned long*)&stack;
133
134 printk("Call Trace: ");
135 while (!kstack_end(stack)) {
136 addr = *stack++;
137 if (__kernel_text_address(addr)) {
138 printk("[<%08lx>] ", addr);
139 print_symbol("%s\n", addr);
140 }
141 }
142 printk("\n");
143}
144
145void show_stack(struct task_struct *task, unsigned long *sp)
146{
147 unsigned long *stack;
148 int i;
149
150 /*
151 * debugging aid: "show_stack(NULL);" prints the
152 * back trace for this cpu.
153 */
154
155 if(sp==NULL) {
156 if (task)
157 sp = (unsigned long *)task->thread.sp;
158 else
159 sp=(unsigned long*)&sp;
160 }
161
162 stack = sp;
163 for(i=0; i < kstack_depth_to_print; i++) {
164 if (kstack_end(stack))
165 break;
166 if (i && ((i % 4) == 0))
167 printk("\n ");
168 printk("%08lx ", *stack++);
169 }
170 printk("\n");
171 show_trace(task, sp);
172}
173
174void dump_stack(void)
175{
176 unsigned long stack;
177
178 show_trace(current, &stack);
179}
180
181EXPORT_SYMBOL(dump_stack);
182
183static void show_registers(struct pt_regs *regs)
184{
185 int i = 0;
186 int in_kernel = 1;
187 unsigned long sp;
188
189 printk("CPU: %d\n", smp_processor_id());
190 show_regs(regs);
191
192 sp = (unsigned long) (1+regs);
193 if (user_mode(regs)) {
194 in_kernel = 0;
195 sp = regs->spu;
196 printk("SPU: %08lx\n", sp);
197 } else {
198 printk("SPI: %08lx\n", sp);
199 }
200 printk("Process %s (pid: %d, process nr: %d, stackpage=%08lx)",
201 current->comm, current->pid, 0xffff & i, 4096+(unsigned long)current);
202
203 /*
204 * When in-kernel, we also print out the stack and code at the
205 * time of the fault..
206 */
207 if (in_kernel) {
208 printk("\nStack: ");
209 show_stack(current, (unsigned long*) sp);
210
211 printk("\nCode: ");
212 if (regs->bpc < PAGE_OFFSET)
213 goto bad;
214
215 for(i=0;i<20;i++) {
216 unsigned char c;
217 if (__get_user(c, &((unsigned char*)regs->bpc)[i])) {
218bad:
219 printk(" Bad PC value.");
220 break;
221 }
222 printk("%02x ", c);
223 }
224 }
225 printk("\n");
226}
227
228DEFINE_SPINLOCK(die_lock);
229
230void die(const char * str, struct pt_regs * regs, long err)
231{
232 console_verbose();
233 spin_lock_irq(&die_lock);
234 bust_spinlocks(1);
235 printk("%s: %04lx\n", str, err & 0xffff);
236 show_registers(regs);
237 bust_spinlocks(0);
238 spin_unlock_irq(&die_lock);
239 do_exit(SIGSEGV);
240}
241
242static __inline__ void die_if_kernel(const char * str,
243 struct pt_regs * regs, long err)
244{
245 if (!user_mode(regs))
246 die(str, regs, err);
247}
248
249static __inline__ void do_trap(int trapnr, int signr, const char * str,
250 struct pt_regs * regs, long error_code, siginfo_t *info)
251{
252 if (user_mode(regs)) {
253 /* trap_signal */
254 struct task_struct *tsk = current;
255 tsk->thread.error_code = error_code;
256 tsk->thread.trap_no = trapnr;
257 if (info)
258 force_sig_info(signr, info, tsk);
259 else
260 force_sig(signr, tsk);
261 return;
262 } else {
263 /* kernel_trap */
264 if (!fixup_exception(regs))
265 die(str, regs, error_code);
266 return;
267 }
268}
269
270#define DO_ERROR(trapnr, signr, str, name) \
271asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
272{ \
273 do_trap(trapnr, signr, 0, regs, error_code, NULL); \
274}
275
276#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
277asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
278{ \
279 siginfo_t info; \
280 info.si_signo = signr; \
281 info.si_errno = 0; \
282 info.si_code = sicode; \
283 info.si_addr = (void __user *)siaddr; \
284 do_trap(trapnr, signr, str, regs, error_code, &info); \
285}
286
287DO_ERROR( 1, SIGTRAP, "debug trap", debug_trap)
288DO_ERROR_INFO(0x20, SIGILL, "reserved instruction ", rie_handler, ILL_ILLOPC, regs->bpc)
289DO_ERROR_INFO(0x100, SIGILL, "privilege instruction", pie_handler, ILL_PRVOPC, regs->bpc)
290
291extern int handle_unaligned_access(unsigned long, struct pt_regs *);
292
293/* This code taken from arch/sh/kernel/traps.c */
294asmlinkage void do_alignment_check(struct pt_regs *regs, long error_code)
295{
296 mm_segment_t oldfs;
297 unsigned long insn;
298 int tmp;
299
300 oldfs = get_fs();
301
302 if (user_mode(regs)) {
303 local_irq_enable();
304 current->thread.error_code = error_code;
305 current->thread.trap_no = 0x17;
306
307 set_fs(USER_DS);
308 if (copy_from_user(&insn, (void *)regs->bpc, 4)) {
309 set_fs(oldfs);
310 goto uspace_segv;
311 }
312 tmp = handle_unaligned_access(insn, regs);
313 set_fs(oldfs);
314
315 if (!tmp)
316 return;
317
318 uspace_segv:
319 printk(KERN_NOTICE "Killing process \"%s\" due to unaligned "
320 "access\n", current->comm);
321 force_sig(SIGSEGV, current);
322 } else {
323 set_fs(KERNEL_DS);
324 if (copy_from_user(&insn, (void *)regs->bpc, 4)) {
325 set_fs(oldfs);
326 die("insn faulting in do_address_error", regs, 0);
327 }
328 handle_unaligned_access(insn, regs);
329 set_fs(oldfs);
330 }
331}
332
diff --git a/arch/m32r/kernel/vmlinux.lds.S b/arch/m32r/kernel/vmlinux.lds.S
new file mode 100644
index 000000000000..729a2645a03f
--- /dev/null
+++ b/arch/m32r/kernel/vmlinux.lds.S
@@ -0,0 +1,143 @@
1/* ld script to make M32R Linux kernel
2 */
3
4#include <linux/config.h>
5#include <asm-generic/vmlinux.lds.h>
6#include <asm/addrspace.h>
7#include <asm/page.h>
8
9OUTPUT_ARCH(m32r)
10ENTRY(startup_32)
11#if defined(__LITTLE_ENDIAN__)
12 jiffies = jiffies_64;
13#else
14 jiffies = jiffies_64 + 4;
15#endif
16SECTIONS
17{
18 . = CONFIG_MEMORY_START + __PAGE_OFFSET;
19 eit_vector = .;
20
21 . = . + 0x1000;
22 .empty_zero_page : { *(.empty_zero_page) } = 0
23
24 /* read-only */
25 _text = .; /* Text and read-only data */
26 .boot : { *(.boot) } = 0
27 .text : {
28 *(.text)
29 SCHED_TEXT
30 LOCK_TEXT
31 *(.fixup)
32 *(.gnu.warning)
33 } = 0x9090
34#ifdef CONFIG_SMP
35 . = ALIGN(65536);
36 .eit_vector4 : { *(.eit_vector4) }
37#endif
38 _etext = .; /* End of text section */
39
40 . = ALIGN(16); /* Exception table */
41 __start___ex_table = .;
42 __ex_table : { *(__ex_table) }
43 __stop___ex_table = .;
44
45 RODATA
46
47 /* writeable */
48 .data : { /* Data */
49 *(.spu)
50 *(.spi)
51 *(.data)
52 CONSTRUCTORS
53 }
54
55 . = ALIGN(4096);
56 __nosave_begin = .;
57 .data_nosave : { *(.data.nosave) }
58 . = ALIGN(4096);
59 __nosave_end = .;
60
61 . = ALIGN(4096);
62 .data.page_aligned : { *(.data.idt) }
63
64 . = ALIGN(32);
65 .data.cacheline_aligned : { *(.data.cacheline_aligned) }
66
67 _edata = .; /* End of data section */
68
69 . = ALIGN(8192); /* init_task */
70 .data.init_task : { *(.data.init_task) }
71
72 /* will be freed after init */
73 . = ALIGN(4096); /* Init code and data */
74 __init_begin = .;
75 .init.text : {
76 _sinittext = .;
77 *(.init.text)
78 _einittext = .;
79 }
80 .init.data : { *(.init.data) }
81 . = ALIGN(16);
82 __setup_start = .;
83 .init.setup : { *(.init.setup) }
84 __setup_end = .;
85 __initcall_start = .;
86 .initcall.init : {
87 *(.initcall1.init)
88 *(.initcall2.init)
89 *(.initcall3.init)
90 *(.initcall4.init)
91 *(.initcall5.init)
92 *(.initcall6.init)
93 *(.initcall7.init)
94 }
95 __initcall_end = .;
96 __con_initcall_start = .;
97 .con_initcall.init : { *(.con_initcall.init) }
98 __con_initcall_end = .;
99 SECURITY_INIT
100 . = ALIGN(4);
101 __alt_instructions = .;
102 .altinstructions : { *(.altinstructions) }
103 __alt_instructions_end = .;
104 .altinstr_replacement : { *(.altinstr_replacement) }
105 /* .exit.text is discard at runtime, not link time, to deal with references
106 from .altinstructions and .eh_frame */
107 .exit.text : { *(.exit.text) }
108 .exit.data : { *(.exit.data) }
109 . = ALIGN(4096);
110 __initramfs_start = .;
111 .init.ramfs : { *(.init.ramfs) }
112 __initramfs_end = .;
113 . = ALIGN(32);
114 __per_cpu_start = .;
115 .data.percpu : { *(.data.percpu) }
116 __per_cpu_end = .;
117 . = ALIGN(4096);
118 __init_end = .;
119 /* freed after init ends here */
120
121 __bss_start = .; /* BSS */
122 .bss : { *(.bss) }
123 . = ALIGN(4);
124 __bss_stop = .;
125
126 _end = . ;
127
128 /* Sections to be discarded */
129 /DISCARD/ : {
130 *(.exit.text)
131 *(.exit.data)
132 *(.exitcall.exit)
133 }
134
135 /* Stabs debugging sections. */
136 .stab 0 : { *(.stab) }
137 .stabstr 0 : { *(.stabstr) }
138 .stab.excl 0 : { *(.stab.excl) }
139 .stab.exclstr 0 : { *(.stab.exclstr) }
140 .stab.index 0 : { *(.stab.index) }
141 .stab.indexstr 0 : { *(.stab.indexstr) }
142 .comment 0 : { *(.comment) }
143}