aboutsummaryrefslogtreecommitdiffstats
path: root/arch/v850/kernel/fpga85e2c.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/v850/kernel/fpga85e2c.c')
-rw-r--r--arch/v850/kernel/fpga85e2c.c171
1 files changed, 171 insertions, 0 deletions
diff --git a/arch/v850/kernel/fpga85e2c.c b/arch/v850/kernel/fpga85e2c.c
new file mode 100644
index 000000000000..4bac5149b3c2
--- /dev/null
+++ b/arch/v850/kernel/fpga85e2c.c
@@ -0,0 +1,171 @@
1/*
2 * arch/v850/kernel/fpga85e2c.h -- Machine-dependent defs for
3 * FPGA implementation of V850E2/NA85E2C
4 *
5 * Copyright (C) 2002,03 NEC Electronics Corporation
6 * Copyright (C) 2002,03 Miles Bader <miles@gnu.org>
7 *
8 * This file is subject to the terms and conditions of the GNU General
9 * Public License. See the file COPYING in the main directory of this
10 * archive for more details.
11 *
12 * Written by Miles Bader <miles@gnu.org>
13 */
14
15#include <linux/config.h>
16#include <linux/kernel.h>
17#include <linux/module.h>
18#include <linux/init.h>
19#include <linux/mm.h>
20#include <linux/swap.h>
21#include <linux/bootmem.h>
22#include <linux/irq.h>
23#include <linux/bitops.h>
24
25#include <asm/atomic.h>
26#include <asm/page.h>
27#include <asm/machdep.h>
28
29#include "mach.h"
30
31extern void memcons_setup (void);
32
33
34#define REG_DUMP_ADDR 0x220000
35
36
37extern struct irqaction reg_snap_action; /* fwd decl */
38
39
40void __init mach_early_init (void)
41{
42 int i;
43 const u32 *src;
44 register u32 *dst asm ("ep");
45 extern u32 _intv_end, _intv_load_start;
46
47 /* Set bus sizes: CS0 32-bit, CS1 16-bit, CS7 8-bit,
48 everything else 32-bit. */
49 V850E2_BSC = 0x2AA6;
50 for (i = 2; i <= 6; i++)
51 CSDEV(i) = 0; /* 32 bit */
52
53 /* Ensure that the simulator halts on a panic, instead of going
54 into an infinite loop inside the panic function. */
55 panic_timeout = -1;
56
57 /* Move the interrupt vectors into their real location. Note that
58 any relocations there are relative to the real location, so we
59 don't have to fix anything up. We use a loop instead of calling
60 memcpy to keep this a leaf function (to avoid a function
61 prologue being generated). */
62 dst = 0x10; /* &_intv_start + 0x10. */
63 src = &_intv_load_start;
64 do {
65 u32 t0 = src[0], t1 = src[1], t2 = src[2], t3 = src[3];
66 u32 t4 = src[4], t5 = src[5], t6 = src[6], t7 = src[7];
67 dst[0] = t0; dst[1] = t1; dst[2] = t2; dst[3] = t3;
68 dst[4] = t4; dst[5] = t5; dst[6] = t6; dst[7] = t7;
69 dst += 8;
70 src += 8;
71 } while (dst < &_intv_end);
72}
73
74void __init mach_setup (char **cmdline)
75{
76 memcons_setup ();
77
78 /* Setup up NMI0 to copy the registers to a known memory location.
79 The FGPA board has a button that produces NMI0 when pressed, so
80 this allows us to push the button, and then look at memory to see
81 what's in the registers (there's no other way to easily do so).
82 We have to use `setup_irq' instead of `request_irq' because it's
83 still too early to do memory allocation. */
84 setup_irq (IRQ_NMI (0), &reg_snap_action);
85}
86
87void mach_get_physical_ram (unsigned long *ram_start, unsigned long *ram_len)
88{
89 *ram_start = ERAM_ADDR;
90 *ram_len = ERAM_SIZE;
91}
92
93void __init mach_sched_init (struct irqaction *timer_action)
94{
95 /* Setup up the timer interrupt. The FPGA peripheral control
96 registers _only_ work with single-bit writes (set1/clr1)! */
97 __clear_bit (RPU_GTMC_CE_BIT, &RPU_GTMC);
98 __clear_bit (RPU_GTMC_CLK_BIT, &RPU_GTMC);
99 __set_bit (RPU_GTMC_CE_BIT, &RPU_GTMC);
100
101 /* We use the first RPU interrupt, which occurs every 8.192ms. */
102 setup_irq (IRQ_RPU (0), timer_action);
103}
104
105
106void mach_gettimeofday (struct timespec *tv)
107{
108 tv->tv_sec = 0;
109 tv->tv_nsec = 0;
110}
111
112void machine_halt (void) __attribute__ ((noreturn));
113void machine_halt (void)
114{
115 for (;;) {
116 DWC(0) = 0x7777;
117 DWC(1) = 0x7777;
118 ASC = 0xffff;
119 FLGREG(0) = 1; /* Halt immediately. */
120 asm ("di; halt; nop; nop; nop; nop; nop");
121 }
122}
123
124EXPORT_SYMBOL(machine_halt);
125
126void machine_restart (char *__unused)
127{
128 machine_halt ();
129}
130
131EXPORT_SYMBOL(machine_restart);
132
133void machine_power_off (void)
134{
135 machine_halt ();
136}
137
138EXPORT_SYMBOL(machine_power_off);
139
140
141/* Interrupts */
142
143struct v850e_intc_irq_init irq_inits[] = {
144 { "IRQ", 0, NUM_MACH_IRQS, 1, 7 },
145 { "RPU", IRQ_RPU(0), IRQ_RPU_NUM, 1, 6 },
146 { 0 }
147};
148#define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1)
149
150struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
151
152/* Initialize interrupts. */
153void __init mach_init_irqs (void)
154{
155 v850e_intc_init_irq_types (irq_inits, hw_itypes);
156}
157
158
159/* An interrupt handler that copies the registers to a known memory location,
160 for debugging purposes. */
161
162static void make_reg_snap (int irq, void *dummy, struct pt_regs *regs)
163{
164 (*(unsigned *)REG_DUMP_ADDR)++;
165 (*(struct pt_regs *)(REG_DUMP_ADDR + sizeof (unsigned))) = *regs;
166}
167
168static int reg_snap_dev_id;
169static struct irqaction reg_snap_action = {
170 make_reg_snap, 0, CPU_MASK_NONE, "reg_snap", &reg_snap_dev_id, 0
171};