diff options
Diffstat (limited to 'arch/v850/kernel/fpga85e2c.c')
-rw-r--r-- | arch/v850/kernel/fpga85e2c.c | 171 |
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 | |||
31 | extern void memcons_setup (void); | ||
32 | |||
33 | |||
34 | #define REG_DUMP_ADDR 0x220000 | ||
35 | |||
36 | |||
37 | extern struct irqaction reg_snap_action; /* fwd decl */ | ||
38 | |||
39 | |||
40 | void __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 | |||
74 | void __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), ®_snap_action); | ||
85 | } | ||
86 | |||
87 | void 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 | |||
93 | void __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 | |||
106 | void mach_gettimeofday (struct timespec *tv) | ||
107 | { | ||
108 | tv->tv_sec = 0; | ||
109 | tv->tv_nsec = 0; | ||
110 | } | ||
111 | |||
112 | void machine_halt (void) __attribute__ ((noreturn)); | ||
113 | void 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 | |||
124 | EXPORT_SYMBOL(machine_halt); | ||
125 | |||
126 | void machine_restart (char *__unused) | ||
127 | { | ||
128 | machine_halt (); | ||
129 | } | ||
130 | |||
131 | EXPORT_SYMBOL(machine_restart); | ||
132 | |||
133 | void machine_power_off (void) | ||
134 | { | ||
135 | machine_halt (); | ||
136 | } | ||
137 | |||
138 | EXPORT_SYMBOL(machine_power_off); | ||
139 | |||
140 | |||
141 | /* Interrupts */ | ||
142 | |||
143 | struct 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 | |||
150 | struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS]; | ||
151 | |||
152 | /* Initialize interrupts. */ | ||
153 | void __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 | |||
162 | static 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 | |||
168 | static int reg_snap_dev_id; | ||
169 | static struct irqaction reg_snap_action = { | ||
170 | make_reg_snap, 0, CPU_MASK_NONE, "reg_snap", ®_snap_dev_id, 0 | ||
171 | }; | ||