diff options
Diffstat (limited to 'arch/cris/arch-v32/kernel')
-rw-r--r-- | arch/cris/arch-v32/kernel/Makefile | 5 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/arbiter.c | 296 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/crisksyms.c | 7 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/debugport.c | 342 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/dma.c | 224 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/entry.S | 83 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/fasttimer.c | 535 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/head.S | 204 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/io.c | 153 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/irq.c | 274 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/kgdb.c | 12 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/process.c | 14 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/ptrace.c | 10 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/signal.c | 144 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/smp.c | 31 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/time.c | 237 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/traps.c | 192 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/vcs_hook.c | 96 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/vcs_hook.h | 42 |
19 files changed, 974 insertions, 1927 deletions
diff --git a/arch/cris/arch-v32/kernel/Makefile b/arch/cris/arch-v32/kernel/Makefile index 5d5b613cde8c..993d987b0078 100644 --- a/arch/cris/arch-v32/kernel/Makefile +++ b/arch/cris/arch-v32/kernel/Makefile | |||
@@ -1,4 +1,3 @@ | |||
1 | # $Id: Makefile,v 1.11 2004/12/17 10:16:13 starvik Exp $ | ||
2 | # | 1 | # |
3 | # Makefile for the linux kernel. | 2 | # Makefile for the linux kernel. |
4 | # | 3 | # |
@@ -6,9 +5,9 @@ | |||
6 | extra-y := head.o | 5 | extra-y := head.o |
7 | 6 | ||
8 | 7 | ||
9 | obj-y := entry.o traps.o irq.o debugport.o dma.o pinmux.o \ | 8 | obj-y := entry.o traps.o irq.o debugport.o \ |
10 | process.o ptrace.o setup.o signal.o traps.o time.o \ | 9 | process.o ptrace.o setup.o signal.o traps.o time.o \ |
11 | arbiter.o io.o | 10 | cache.o cacheflush.o |
12 | 11 | ||
13 | obj-$(CONFIG_ETRAXFS_SIM) += vcs_hook.o | 12 | obj-$(CONFIG_ETRAXFS_SIM) += vcs_hook.o |
14 | 13 | ||
diff --git a/arch/cris/arch-v32/kernel/arbiter.c b/arch/cris/arch-v32/kernel/arbiter.c deleted file mode 100644 index 420a5312ed03..000000000000 --- a/arch/cris/arch-v32/kernel/arbiter.c +++ /dev/null | |||
@@ -1,296 +0,0 @@ | |||
1 | /* | ||
2 | * Memory arbiter functions. Allocates bandwidth through the | ||
3 | * arbiter and sets up arbiter breakpoints. | ||
4 | * | ||
5 | * The algorithm first assigns slots to the clients that has specified | ||
6 | * bandwidth (e.g. ethernet) and then the remaining slots are divided | ||
7 | * on all the active clients. | ||
8 | * | ||
9 | * Copyright (c) 2004, 2005 Axis Communications AB. | ||
10 | */ | ||
11 | |||
12 | #include <asm/arch/hwregs/reg_map.h> | ||
13 | #include <asm/arch/hwregs/reg_rdwr.h> | ||
14 | #include <asm/arch/hwregs/marb_defs.h> | ||
15 | #include <asm/arch/arbiter.h> | ||
16 | #include <asm/arch/hwregs/intr_vect.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/signal.h> | ||
19 | #include <linux/errno.h> | ||
20 | #include <linux/spinlock.h> | ||
21 | #include <asm/io.h> | ||
22 | |||
23 | struct crisv32_watch_entry | ||
24 | { | ||
25 | unsigned long instance; | ||
26 | watch_callback* cb; | ||
27 | unsigned long start; | ||
28 | unsigned long end; | ||
29 | int used; | ||
30 | }; | ||
31 | |||
32 | #define NUMBER_OF_BP 4 | ||
33 | #define NBR_OF_CLIENTS 14 | ||
34 | #define NBR_OF_SLOTS 64 | ||
35 | #define SDRAM_BANDWIDTH 100000000 /* Some kind of expected value */ | ||
36 | #define INTMEM_BANDWIDTH 400000000 | ||
37 | #define NBR_OF_REGIONS 2 | ||
38 | |||
39 | static struct crisv32_watch_entry watches[NUMBER_OF_BP] = | ||
40 | { | ||
41 | {regi_marb_bp0}, | ||
42 | {regi_marb_bp1}, | ||
43 | {regi_marb_bp2}, | ||
44 | {regi_marb_bp3} | ||
45 | }; | ||
46 | |||
47 | static int requested_slots[NBR_OF_REGIONS][NBR_OF_CLIENTS]; | ||
48 | static int active_clients[NBR_OF_REGIONS][NBR_OF_CLIENTS]; | ||
49 | static int max_bandwidth[NBR_OF_REGIONS] = {SDRAM_BANDWIDTH, INTMEM_BANDWIDTH}; | ||
50 | |||
51 | DEFINE_SPINLOCK(arbiter_lock); | ||
52 | |||
53 | static irqreturn_t | ||
54 | crisv32_arbiter_irq(int irq, void* dev_id, struct pt_regs* regs); | ||
55 | |||
56 | static void crisv32_arbiter_config(int region) | ||
57 | { | ||
58 | int slot; | ||
59 | int client; | ||
60 | int interval = 0; | ||
61 | int val[NBR_OF_SLOTS]; | ||
62 | |||
63 | for (slot = 0; slot < NBR_OF_SLOTS; slot++) | ||
64 | val[slot] = NBR_OF_CLIENTS + 1; | ||
65 | |||
66 | for (client = 0; client < NBR_OF_CLIENTS; client++) | ||
67 | { | ||
68 | int pos; | ||
69 | if (!requested_slots[region][client]) | ||
70 | continue; | ||
71 | interval = NBR_OF_SLOTS / requested_slots[region][client]; | ||
72 | pos = 0; | ||
73 | while (pos < NBR_OF_SLOTS) | ||
74 | { | ||
75 | if (val[pos] != NBR_OF_CLIENTS + 1) | ||
76 | pos++; | ||
77 | else | ||
78 | { | ||
79 | val[pos] = client; | ||
80 | pos += interval; | ||
81 | } | ||
82 | } | ||
83 | } | ||
84 | |||
85 | client = 0; | ||
86 | for (slot = 0; slot < NBR_OF_SLOTS; slot++) | ||
87 | { | ||
88 | if (val[slot] == NBR_OF_CLIENTS + 1) | ||
89 | { | ||
90 | int first = client; | ||
91 | while(!active_clients[region][client]) { | ||
92 | client = (client + 1) % NBR_OF_CLIENTS; | ||
93 | if (client == first) | ||
94 | break; | ||
95 | } | ||
96 | val[slot] = client; | ||
97 | client = (client + 1) % NBR_OF_CLIENTS; | ||
98 | } | ||
99 | if (region == EXT_REGION) | ||
100 | REG_WR_INT_VECT(marb, regi_marb, rw_ext_slots, slot, val[slot]); | ||
101 | else if (region == INT_REGION) | ||
102 | REG_WR_INT_VECT(marb, regi_marb, rw_int_slots, slot, val[slot]); | ||
103 | } | ||
104 | } | ||
105 | |||
106 | extern char _stext, _etext; | ||
107 | |||
108 | static void crisv32_arbiter_init(void) | ||
109 | { | ||
110 | static int initialized = 0; | ||
111 | |||
112 | if (initialized) | ||
113 | return; | ||
114 | |||
115 | initialized = 1; | ||
116 | |||
117 | /* CPU caches are active. */ | ||
118 | active_clients[EXT_REGION][10] = active_clients[EXT_REGION][11] = 1; | ||
119 | crisv32_arbiter_config(EXT_REGION); | ||
120 | crisv32_arbiter_config(INT_REGION); | ||
121 | |||
122 | if (request_irq(MEMARB_INTR_VECT, crisv32_arbiter_irq, IRQF_DISABLED, | ||
123 | "arbiter", NULL)) | ||
124 | printk(KERN_ERR "Couldn't allocate arbiter IRQ\n"); | ||
125 | |||
126 | #ifndef CONFIG_ETRAX_KGDB | ||
127 | /* Global watch for writes to kernel text segment. */ | ||
128 | crisv32_arbiter_watch(virt_to_phys(&_stext), &_etext - &_stext, | ||
129 | arbiter_all_clients, arbiter_all_write, NULL); | ||
130 | #endif | ||
131 | } | ||
132 | |||
133 | |||
134 | |||
135 | int crisv32_arbiter_allocate_bandwidth(int client, int region, | ||
136 | unsigned long bandwidth) | ||
137 | { | ||
138 | int i; | ||
139 | int total_assigned = 0; | ||
140 | int total_clients = 0; | ||
141 | int req; | ||
142 | |||
143 | crisv32_arbiter_init(); | ||
144 | |||
145 | for (i = 0; i < NBR_OF_CLIENTS; i++) | ||
146 | { | ||
147 | total_assigned += requested_slots[region][i]; | ||
148 | total_clients += active_clients[region][i]; | ||
149 | } | ||
150 | req = NBR_OF_SLOTS / (max_bandwidth[region] / bandwidth); | ||
151 | |||
152 | if (total_assigned + total_clients + req + 1 > NBR_OF_SLOTS) | ||
153 | return -ENOMEM; | ||
154 | |||
155 | active_clients[region][client] = 1; | ||
156 | requested_slots[region][client] = req; | ||
157 | crisv32_arbiter_config(region); | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | int crisv32_arbiter_watch(unsigned long start, unsigned long size, | ||
163 | unsigned long clients, unsigned long accesses, | ||
164 | watch_callback* cb) | ||
165 | { | ||
166 | int i; | ||
167 | |||
168 | crisv32_arbiter_init(); | ||
169 | |||
170 | if (start > 0x80000000) { | ||
171 | printk("Arbiter: %lX doesn't look like a physical address", start); | ||
172 | return -EFAULT; | ||
173 | } | ||
174 | |||
175 | spin_lock(&arbiter_lock); | ||
176 | |||
177 | for (i = 0; i < NUMBER_OF_BP; i++) { | ||
178 | if (!watches[i].used) { | ||
179 | reg_marb_rw_intr_mask intr_mask = REG_RD(marb, regi_marb, rw_intr_mask); | ||
180 | |||
181 | watches[i].used = 1; | ||
182 | watches[i].start = start; | ||
183 | watches[i].end = start + size; | ||
184 | watches[i].cb = cb; | ||
185 | |||
186 | REG_WR_INT(marb_bp, watches[i].instance, rw_first_addr, watches[i].start); | ||
187 | REG_WR_INT(marb_bp, watches[i].instance, rw_last_addr, watches[i].end); | ||
188 | REG_WR_INT(marb_bp, watches[i].instance, rw_op, accesses); | ||
189 | REG_WR_INT(marb_bp, watches[i].instance, rw_clients, clients); | ||
190 | |||
191 | if (i == 0) | ||
192 | intr_mask.bp0 = regk_marb_yes; | ||
193 | else if (i == 1) | ||
194 | intr_mask.bp1 = regk_marb_yes; | ||
195 | else if (i == 2) | ||
196 | intr_mask.bp2 = regk_marb_yes; | ||
197 | else if (i == 3) | ||
198 | intr_mask.bp3 = regk_marb_yes; | ||
199 | |||
200 | REG_WR(marb, regi_marb, rw_intr_mask, intr_mask); | ||
201 | spin_unlock(&arbiter_lock); | ||
202 | |||
203 | return i; | ||
204 | } | ||
205 | } | ||
206 | spin_unlock(&arbiter_lock); | ||
207 | return -ENOMEM; | ||
208 | } | ||
209 | |||
210 | int crisv32_arbiter_unwatch(int id) | ||
211 | { | ||
212 | reg_marb_rw_intr_mask intr_mask = REG_RD(marb, regi_marb, rw_intr_mask); | ||
213 | |||
214 | crisv32_arbiter_init(); | ||
215 | |||
216 | spin_lock(&arbiter_lock); | ||
217 | |||
218 | if ((id < 0) || (id >= NUMBER_OF_BP) || (!watches[id].used)) { | ||
219 | spin_unlock(&arbiter_lock); | ||
220 | return -EINVAL; | ||
221 | } | ||
222 | |||
223 | memset(&watches[id], 0, sizeof(struct crisv32_watch_entry)); | ||
224 | |||
225 | if (id == 0) | ||
226 | intr_mask.bp0 = regk_marb_no; | ||
227 | else if (id == 1) | ||
228 | intr_mask.bp2 = regk_marb_no; | ||
229 | else if (id == 2) | ||
230 | intr_mask.bp2 = regk_marb_no; | ||
231 | else if (id == 3) | ||
232 | intr_mask.bp3 = regk_marb_no; | ||
233 | |||
234 | REG_WR(marb, regi_marb, rw_intr_mask, intr_mask); | ||
235 | |||
236 | spin_unlock(&arbiter_lock); | ||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | extern void show_registers(struct pt_regs *regs); | ||
241 | |||
242 | static irqreturn_t | ||
243 | crisv32_arbiter_irq(int irq, void* dev_id, struct pt_regs* regs) | ||
244 | { | ||
245 | reg_marb_r_masked_intr masked_intr = REG_RD(marb, regi_marb, r_masked_intr); | ||
246 | reg_marb_bp_r_brk_clients r_clients; | ||
247 | reg_marb_bp_r_brk_addr r_addr; | ||
248 | reg_marb_bp_r_brk_op r_op; | ||
249 | reg_marb_bp_r_brk_first_client r_first; | ||
250 | reg_marb_bp_r_brk_size r_size; | ||
251 | reg_marb_bp_rw_ack ack = {0}; | ||
252 | reg_marb_rw_ack_intr ack_intr = {.bp0=1,.bp1=1,.bp2=1,.bp3=1}; | ||
253 | struct crisv32_watch_entry* watch; | ||
254 | |||
255 | if (masked_intr.bp0) { | ||
256 | watch = &watches[0]; | ||
257 | ack_intr.bp0 = regk_marb_yes; | ||
258 | } else if (masked_intr.bp1) { | ||
259 | watch = &watches[1]; | ||
260 | ack_intr.bp1 = regk_marb_yes; | ||
261 | } else if (masked_intr.bp2) { | ||
262 | watch = &watches[2]; | ||
263 | ack_intr.bp2 = regk_marb_yes; | ||
264 | } else if (masked_intr.bp3) { | ||
265 | watch = &watches[3]; | ||
266 | ack_intr.bp3 = regk_marb_yes; | ||
267 | } else { | ||
268 | return IRQ_NONE; | ||
269 | } | ||
270 | |||
271 | /* Retrieve all useful information and print it. */ | ||
272 | r_clients = REG_RD(marb_bp, watch->instance, r_brk_clients); | ||
273 | r_addr = REG_RD(marb_bp, watch->instance, r_brk_addr); | ||
274 | r_op = REG_RD(marb_bp, watch->instance, r_brk_op); | ||
275 | r_first = REG_RD(marb_bp, watch->instance, r_brk_first_client); | ||
276 | r_size = REG_RD(marb_bp, watch->instance, r_brk_size); | ||
277 | |||
278 | printk("Arbiter IRQ\n"); | ||
279 | printk("Clients %X addr %X op %X first %X size %X\n", | ||
280 | REG_TYPE_CONV(int, reg_marb_bp_r_brk_clients, r_clients), | ||
281 | REG_TYPE_CONV(int, reg_marb_bp_r_brk_addr, r_addr), | ||
282 | REG_TYPE_CONV(int, reg_marb_bp_r_brk_op, r_op), | ||
283 | REG_TYPE_CONV(int, reg_marb_bp_r_brk_first_client, r_first), | ||
284 | REG_TYPE_CONV(int, reg_marb_bp_r_brk_size, r_size)); | ||
285 | |||
286 | REG_WR(marb_bp, watch->instance, rw_ack, ack); | ||
287 | REG_WR(marb, regi_marb, rw_ack_intr, ack_intr); | ||
288 | |||
289 | printk("IRQ occured at %lX\n", regs->erp); | ||
290 | |||
291 | if (watch->cb) | ||
292 | watch->cb(); | ||
293 | |||
294 | |||
295 | return IRQ_HANDLED; | ||
296 | } | ||
diff --git a/arch/cris/arch-v32/kernel/crisksyms.c b/arch/cris/arch-v32/kernel/crisksyms.c index e513da711245..77d02c15a7fc 100644 --- a/arch/cris/arch-v32/kernel/crisksyms.c +++ b/arch/cris/arch-v32/kernel/crisksyms.c | |||
@@ -2,7 +2,8 @@ | |||
2 | #include <linux/irq.h> | 2 | #include <linux/irq.h> |
3 | #include <asm/arch/dma.h> | 3 | #include <asm/arch/dma.h> |
4 | #include <asm/arch/intmem.h> | 4 | #include <asm/arch/intmem.h> |
5 | #include <asm/arch/pinmux.h> | 5 | #include <asm/arch/mach/pinmux.h> |
6 | #include <asm/arch/io.h> | ||
6 | 7 | ||
7 | /* Functions for allocating DMA channels */ | 8 | /* Functions for allocating DMA channels */ |
8 | EXPORT_SYMBOL(crisv32_request_dma); | 9 | EXPORT_SYMBOL(crisv32_request_dma); |
@@ -16,7 +17,11 @@ EXPORT_SYMBOL(crisv32_intmem_virt_to_phys); | |||
16 | 17 | ||
17 | /* Functions for handling pinmux */ | 18 | /* Functions for handling pinmux */ |
18 | EXPORT_SYMBOL(crisv32_pinmux_alloc); | 19 | EXPORT_SYMBOL(crisv32_pinmux_alloc); |
20 | EXPORT_SYMBOL(crisv32_pinmux_alloc_fixed); | ||
19 | EXPORT_SYMBOL(crisv32_pinmux_dealloc); | 21 | EXPORT_SYMBOL(crisv32_pinmux_dealloc); |
22 | EXPORT_SYMBOL(crisv32_pinmux_dealloc_fixed); | ||
23 | EXPORT_SYMBOL(crisv32_io_get_name); | ||
24 | EXPORT_SYMBOL(crisv32_io_get); | ||
20 | 25 | ||
21 | /* Functions masking/unmasking interrupts */ | 26 | /* Functions masking/unmasking interrupts */ |
22 | EXPORT_SYMBOL(mask_irq); | 27 | EXPORT_SYMBOL(mask_irq); |
diff --git a/arch/cris/arch-v32/kernel/debugport.c b/arch/cris/arch-v32/kernel/debugport.c index d1272ad92153..15af4c293157 100644 --- a/arch/cris/arch-v32/kernel/debugport.c +++ b/arch/cris/arch-v32/kernel/debugport.c | |||
@@ -4,17 +4,12 @@ | |||
4 | 4 | ||
5 | #include <linux/console.h> | 5 | #include <linux/console.h> |
6 | #include <linux/init.h> | 6 | #include <linux/init.h> |
7 | #include <linux/major.h> | ||
8 | #include <linux/delay.h> | ||
9 | #include <linux/tty.h> | ||
10 | #include <asm/system.h> | 7 | #include <asm/system.h> |
11 | #include <asm/io.h> | 8 | #include <hwregs/reg_rdwr.h> |
12 | #include <asm/arch/hwregs/ser_defs.h> | 9 | #include <hwregs/reg_map.h> |
13 | #include <asm/arch/hwregs/dma_defs.h> | 10 | #include <hwregs/ser_defs.h> |
14 | #include <asm/arch/pinmux.h> | 11 | #include <hwregs/dma_defs.h> |
15 | 12 | #include <asm/arch/mach/pinmux.h> | |
16 | #include <asm/irq.h> | ||
17 | #include <asm/arch/hwregs/intr_vect_defs.h> | ||
18 | 13 | ||
19 | struct dbg_port | 14 | struct dbg_port |
20 | { | 15 | { |
@@ -59,45 +54,50 @@ struct dbg_port ports[] = | |||
59 | 115200, | 54 | 115200, |
60 | 'N', | 55 | 'N', |
61 | 8 | 56 | 8 |
62 | } | 57 | }, |
58 | #if CONFIG_ETRAX_SERIAL_PORTS == 5 | ||
59 | { | ||
60 | 4, | ||
61 | regi_ser4, | ||
62 | 0, | ||
63 | 115200, | ||
64 | 'N', | ||
65 | 8 | ||
66 | }, | ||
67 | #endif | ||
63 | }; | 68 | }; |
64 | static struct dbg_port *port = | 69 | static struct dbg_port *port = |
65 | #if defined(CONFIG_ETRAX_DEBUG_PORT0) | 70 | #if defined(CONFIG_ETRAX_DEBUG_PORT0) |
66 | &ports[0]; | 71 | &ports[0]; |
67 | #elif defined(CONFIG_ETRAX_DEBUG_PORT1) | 72 | #elif defined(CONFIG_ETRAX_DEBUG_PORT1) |
68 | &ports[1]; | 73 | &ports[1]; |
69 | #elif defined(CONFIG_ETRAX_DEBUG_PORT2) | 74 | #elif defined(CONFIG_ETRAX_DEBUG_PORT2) |
70 | &ports[2]; | 75 | &ports[2]; |
71 | #elif defined(CONFIG_ETRAX_DEBUG_PORT3) | 76 | #elif defined(CONFIG_ETRAX_DEBUG_PORT3) |
72 | &ports[3]; | 77 | &ports[3]; |
78 | #elif defined(CONFIG_ETRAX_DEBUG_PORT4) | ||
79 | &ports[4]; | ||
73 | #else | 80 | #else |
74 | NULL; | 81 | NULL; |
75 | #endif | 82 | #endif |
76 | 83 | ||
77 | #ifdef CONFIG_ETRAX_KGDB | 84 | #ifdef CONFIG_ETRAX_KGDB |
78 | static struct dbg_port *kgdb_port = | 85 | static struct dbg_port *kgdb_port = |
79 | #if defined(CONFIG_ETRAX_KGDB_PORT0) | 86 | #if defined(CONFIG_ETRAX_KGDB_PORT0) |
80 | &ports[0]; | 87 | &ports[0]; |
81 | #elif defined(CONFIG_ETRAX_KGDB_PORT1) | 88 | #elif defined(CONFIG_ETRAX_KGDB_PORT1) |
82 | &ports[1]; | 89 | &ports[1]; |
83 | #elif defined(CONFIG_ETRAX_KGDB_PORT2) | 90 | #elif defined(CONFIG_ETRAX_KGDB_PORT2) |
84 | &ports[2]; | 91 | &ports[2]; |
85 | #elif defined(CONFIG_ETRAX_KGDB_PORT3) | 92 | #elif defined(CONFIG_ETRAX_KGDB_PORT3) |
86 | &ports[3]; | 93 | &ports[3]; |
94 | #elif defined(CONFIG_ETRAX_KGDB_PORT4) | ||
95 | &ports[4]; | ||
87 | #else | 96 | #else |
88 | NULL; | 97 | NULL; |
89 | #endif | 98 | #endif |
90 | #endif | 99 | #endif |
91 | 100 | ||
92 | #ifdef CONFIG_ETRAXFS_SIM | ||
93 | extern void print_str( const char *str ); | ||
94 | static char buffer[1024]; | ||
95 | static char msg[] = "Debug: "; | ||
96 | static int buffer_pos = sizeof(msg) - 1; | ||
97 | #endif | ||
98 | |||
99 | extern struct tty_driver *serial_driver; | ||
100 | |||
101 | static void | 101 | static void |
102 | start_port(struct dbg_port* p) | 102 | start_port(struct dbg_port* p) |
103 | { | 103 | { |
@@ -114,6 +114,10 @@ start_port(struct dbg_port* p) | |||
114 | crisv32_pinmux_alloc_fixed(pinmux_ser2); | 114 | crisv32_pinmux_alloc_fixed(pinmux_ser2); |
115 | else if (p->nbr == 3) | 115 | else if (p->nbr == 3) |
116 | crisv32_pinmux_alloc_fixed(pinmux_ser3); | 116 | crisv32_pinmux_alloc_fixed(pinmux_ser3); |
117 | #if CONFIG_ETRAX_SERIAL_PORTS == 5 | ||
118 | else if (p->nbr == 4) | ||
119 | crisv32_pinmux_alloc_fixed(pinmux_ser4); | ||
120 | #endif | ||
117 | 121 | ||
118 | /* Set up serial port registers */ | 122 | /* Set up serial port registers */ |
119 | reg_ser_rw_tr_ctrl tr_ctrl = {0}; | 123 | reg_ser_rw_tr_ctrl tr_ctrl = {0}; |
@@ -156,124 +160,21 @@ start_port(struct dbg_port* p) | |||
156 | REG_WR (ser, p->instance, rw_rec_ctrl, rec_ctrl); | 160 | REG_WR (ser, p->instance, rw_rec_ctrl, rec_ctrl); |
157 | } | 161 | } |
158 | 162 | ||
159 | /* No debug */ | ||
160 | #ifdef CONFIG_ETRAX_DEBUG_PORT_NULL | ||
161 | |||
162 | static void | ||
163 | console_write(struct console *co, const char *buf, unsigned int len) | ||
164 | { | ||
165 | return; | ||
166 | } | ||
167 | |||
168 | /* Target debug */ | ||
169 | #elif !defined(CONFIG_ETRAXFS_SIM) | ||
170 | |||
171 | static void | ||
172 | console_write_direct(struct console *co, const char *buf, unsigned int len) | ||
173 | { | ||
174 | int i; | ||
175 | reg_ser_r_stat_din stat; | ||
176 | reg_ser_rw_tr_dma_en tr_dma_en, old; | ||
177 | |||
178 | /* Switch to manual mode */ | ||
179 | tr_dma_en = old = REG_RD (ser, port->instance, rw_tr_dma_en); | ||
180 | if (tr_dma_en.en == regk_ser_yes) { | ||
181 | tr_dma_en.en = regk_ser_no; | ||
182 | REG_WR(ser, port->instance, rw_tr_dma_en, tr_dma_en); | ||
183 | } | ||
184 | |||
185 | /* Send data */ | ||
186 | for (i = 0; i < len; i++) { | ||
187 | /* LF -> CRLF */ | ||
188 | if (buf[i] == '\n') { | ||
189 | do { | ||
190 | stat = REG_RD (ser, port->instance, r_stat_din); | ||
191 | } while (!stat.tr_rdy); | ||
192 | REG_WR_INT (ser, port->instance, rw_dout, '\r'); | ||
193 | } | ||
194 | /* Wait until transmitter is ready and send.*/ | ||
195 | do { | ||
196 | stat = REG_RD (ser, port->instance, r_stat_din); | ||
197 | } while (!stat.tr_rdy); | ||
198 | REG_WR_INT (ser, port->instance, rw_dout, buf[i]); | ||
199 | } | ||
200 | |||
201 | /* Restore mode */ | ||
202 | if (tr_dma_en.en != old.en) | ||
203 | REG_WR(ser, port->instance, rw_tr_dma_en, old); | ||
204 | } | ||
205 | |||
206 | static void | ||
207 | console_write(struct console *co, const char *buf, unsigned int len) | ||
208 | { | ||
209 | if (!port) | ||
210 | return; | ||
211 | console_write_direct(co, buf, len); | ||
212 | } | ||
213 | |||
214 | |||
215 | |||
216 | #else | ||
217 | |||
218 | /* VCS debug */ | ||
219 | |||
220 | static void | ||
221 | console_write(struct console *co, const char *buf, unsigned int len) | ||
222 | { | ||
223 | char* pos; | ||
224 | pos = memchr(buf, '\n', len); | ||
225 | if (pos) { | ||
226 | int l = ++pos - buf; | ||
227 | memcpy(buffer + buffer_pos, buf, l); | ||
228 | memcpy(buffer, msg, sizeof(msg) - 1); | ||
229 | buffer[buffer_pos + l] = '\0'; | ||
230 | print_str(buffer); | ||
231 | buffer_pos = sizeof(msg) - 1; | ||
232 | if (pos - buf != len) { | ||
233 | memcpy(buffer + buffer_pos, pos, len - l); | ||
234 | buffer_pos += len - l; | ||
235 | } | ||
236 | } else { | ||
237 | memcpy(buffer + buffer_pos, buf, len); | ||
238 | buffer_pos += len; | ||
239 | } | ||
240 | } | ||
241 | |||
242 | #endif | ||
243 | |||
244 | int raw_printk(const char *fmt, ...) | ||
245 | { | ||
246 | static char buf[1024]; | ||
247 | int printed_len; | ||
248 | va_list args; | ||
249 | va_start(args, fmt); | ||
250 | printed_len = vsnprintf(buf, sizeof(buf), fmt, args); | ||
251 | va_end(args); | ||
252 | console_write(NULL, buf, strlen(buf)); | ||
253 | return printed_len; | ||
254 | } | ||
255 | |||
256 | void | ||
257 | stupid_debug(char* buf) | ||
258 | { | ||
259 | console_write(NULL, buf, strlen(buf)); | ||
260 | } | ||
261 | |||
262 | #ifdef CONFIG_ETRAX_KGDB | 163 | #ifdef CONFIG_ETRAX_KGDB |
263 | /* Use polling to get a single character from the kernel debug port */ | 164 | /* Use polling to get a single character from the kernel debug port */ |
264 | int | 165 | int |
265 | getDebugChar(void) | 166 | getDebugChar(void) |
266 | { | 167 | { |
267 | reg_ser_rs_status_data stat; | 168 | reg_ser_rs_stat_din stat; |
268 | reg_ser_rw_ack_intr ack_intr = { 0 }; | 169 | reg_ser_rw_ack_intr ack_intr = { 0 }; |
269 | 170 | ||
270 | do { | 171 | do { |
271 | stat = REG_RD(ser, kgdb_instance, rs_status_data); | 172 | stat = REG_RD(ser, kgdb_port->instance, rs_stat_din); |
272 | } while (!stat.data_avail); | 173 | } while (!stat.dav); |
273 | 174 | ||
274 | /* Ack the data_avail interrupt. */ | 175 | /* Ack the data_avail interrupt. */ |
275 | ack_intr.data_avail = 1; | 176 | ack_intr.dav = 1; |
276 | REG_WR(ser, kgdb_instance, rw_ack_intr, ack_intr); | 177 | REG_WR(ser, kgdb_port->instance, rw_ack_intr, ack_intr); |
277 | 178 | ||
278 | return stat.data; | 179 | return stat.data; |
279 | } | 180 | } |
@@ -282,173 +183,18 @@ getDebugChar(void) | |||
282 | void | 183 | void |
283 | putDebugChar(int val) | 184 | putDebugChar(int val) |
284 | { | 185 | { |
285 | reg_ser_r_status_data stat; | 186 | reg_ser_r_stat_din stat; |
286 | do { | 187 | do { |
287 | stat = REG_RD (ser, kgdb_instance, r_status_data); | 188 | stat = REG_RD(ser, kgdb_port->instance, r_stat_din); |
288 | } while (!stat.tr_ready); | 189 | } while (!stat.tr_rdy); |
289 | REG_WR (ser, kgdb_instance, rw_data_out, REG_TYPE_CONV(reg_ser_rw_data_out, int, val)); | 190 | REG_WR_INT(ser, kgdb_port->instance, rw_dout, val); |
290 | } | 191 | } |
291 | #endif /* CONFIG_ETRAX_KGDB */ | 192 | #endif /* CONFIG_ETRAX_KGDB */ |
292 | 193 | ||
293 | static int __init | ||
294 | console_setup(struct console *co, char *options) | ||
295 | { | ||
296 | char* s; | ||
297 | |||
298 | if (options) { | ||
299 | port = &ports[co->index]; | ||
300 | port->baudrate = 115200; | ||
301 | port->parity = 'N'; | ||
302 | port->bits = 8; | ||
303 | port->baudrate = simple_strtoul(options, NULL, 10); | ||
304 | s = options; | ||
305 | while(*s >= '0' && *s <= '9') | ||
306 | s++; | ||
307 | if (*s) port->parity = *s++; | ||
308 | if (*s) port->bits = *s++ - '0'; | ||
309 | port->started = 0; | ||
310 | start_port(port); | ||
311 | } | ||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | /* This is a dummy serial device that throws away anything written to it. | ||
316 | * This is used when no debug output is wanted. | ||
317 | */ | ||
318 | static struct tty_driver dummy_driver; | ||
319 | |||
320 | static int dummy_open(struct tty_struct *tty, struct file * filp) | ||
321 | { | ||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | static void dummy_close(struct tty_struct *tty, struct file * filp) | ||
326 | { | ||
327 | } | ||
328 | |||
329 | static int dummy_write(struct tty_struct * tty, | ||
330 | const unsigned char *buf, int count) | ||
331 | { | ||
332 | return count; | ||
333 | } | ||
334 | |||
335 | static int | ||
336 | dummy_write_room(struct tty_struct *tty) | ||
337 | { | ||
338 | return 8192; | ||
339 | } | ||
340 | |||
341 | void __init | ||
342 | init_dummy_console(void) | ||
343 | { | ||
344 | memset(&dummy_driver, 0, sizeof(struct tty_driver)); | ||
345 | dummy_driver.driver_name = "serial"; | ||
346 | dummy_driver.name = "ttyS"; | ||
347 | dummy_driver.major = TTY_MAJOR; | ||
348 | dummy_driver.minor_start = 68; | ||
349 | dummy_driver.num = 1; /* etrax100 has 4 serial ports */ | ||
350 | dummy_driver.type = TTY_DRIVER_TYPE_SERIAL; | ||
351 | dummy_driver.subtype = SERIAL_TYPE_NORMAL; | ||
352 | dummy_driver.init_termios = tty_std_termios; | ||
353 | dummy_driver.init_termios.c_cflag = | ||
354 | B115200 | CS8 | CREAD | HUPCL | CLOCAL; /* is normally B9600 default... */ | ||
355 | dummy_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; | ||
356 | |||
357 | dummy_driver.open = dummy_open; | ||
358 | dummy_driver.close = dummy_close; | ||
359 | dummy_driver.write = dummy_write; | ||
360 | dummy_driver.write_room = dummy_write_room; | ||
361 | if (tty_register_driver(&dummy_driver)) | ||
362 | panic("Couldn't register dummy serial driver\n"); | ||
363 | } | ||
364 | |||
365 | static struct tty_driver* | ||
366 | crisv32_console_device(struct console* co, int *index) | ||
367 | { | ||
368 | if (port) | ||
369 | *index = port->nbr; | ||
370 | return port ? serial_driver : &dummy_driver; | ||
371 | } | ||
372 | |||
373 | static struct console sercons = { | ||
374 | name : "ttyS", | ||
375 | write: console_write, | ||
376 | read : NULL, | ||
377 | device : crisv32_console_device, | ||
378 | unblank : NULL, | ||
379 | setup : console_setup, | ||
380 | flags : CON_PRINTBUFFER, | ||
381 | index : -1, | ||
382 | cflag : 0, | ||
383 | next : NULL | ||
384 | }; | ||
385 | static struct console sercons0 = { | ||
386 | name : "ttyS", | ||
387 | write: console_write, | ||
388 | read : NULL, | ||
389 | device : crisv32_console_device, | ||
390 | unblank : NULL, | ||
391 | setup : console_setup, | ||
392 | flags : CON_PRINTBUFFER, | ||
393 | index : 0, | ||
394 | cflag : 0, | ||
395 | next : NULL | ||
396 | }; | ||
397 | |||
398 | static struct console sercons1 = { | ||
399 | name : "ttyS", | ||
400 | write: console_write, | ||
401 | read : NULL, | ||
402 | device : crisv32_console_device, | ||
403 | unblank : NULL, | ||
404 | setup : console_setup, | ||
405 | flags : CON_PRINTBUFFER, | ||
406 | index : 1, | ||
407 | cflag : 0, | ||
408 | next : NULL | ||
409 | }; | ||
410 | static struct console sercons2 = { | ||
411 | name : "ttyS", | ||
412 | write: console_write, | ||
413 | read : NULL, | ||
414 | device : crisv32_console_device, | ||
415 | unblank : NULL, | ||
416 | setup : console_setup, | ||
417 | flags : CON_PRINTBUFFER, | ||
418 | index : 2, | ||
419 | cflag : 0, | ||
420 | next : NULL | ||
421 | }; | ||
422 | static struct console sercons3 = { | ||
423 | name : "ttyS", | ||
424 | write: console_write, | ||
425 | read : NULL, | ||
426 | device : crisv32_console_device, | ||
427 | unblank : NULL, | ||
428 | setup : console_setup, | ||
429 | flags : CON_PRINTBUFFER, | ||
430 | index : 3, | ||
431 | cflag : 0, | ||
432 | next : NULL | ||
433 | }; | ||
434 | |||
435 | /* Register console for printk's, etc. */ | 194 | /* Register console for printk's, etc. */ |
436 | int __init | 195 | int __init |
437 | init_etrax_debug(void) | 196 | init_etrax_debug(void) |
438 | { | 197 | { |
439 | static int first = 1; | ||
440 | |||
441 | if (!first) { | ||
442 | unregister_console(&sercons); | ||
443 | register_console(&sercons0); | ||
444 | register_console(&sercons1); | ||
445 | register_console(&sercons2); | ||
446 | register_console(&sercons3); | ||
447 | init_dummy_console(); | ||
448 | return 0; | ||
449 | } | ||
450 | first = 0; | ||
451 | register_console(&sercons); | ||
452 | start_port(port); | 198 | start_port(port); |
453 | 199 | ||
454 | #ifdef CONFIG_ETRAX_KGDB | 200 | #ifdef CONFIG_ETRAX_KGDB |
@@ -456,5 +202,3 @@ init_etrax_debug(void) | |||
456 | #endif /* CONFIG_ETRAX_KGDB */ | 202 | #endif /* CONFIG_ETRAX_KGDB */ |
457 | return 0; | 203 | return 0; |
458 | } | 204 | } |
459 | |||
460 | __initcall(init_etrax_debug); | ||
diff --git a/arch/cris/arch-v32/kernel/dma.c b/arch/cris/arch-v32/kernel/dma.c deleted file mode 100644 index 570e19128ffd..000000000000 --- a/arch/cris/arch-v32/kernel/dma.c +++ /dev/null | |||
@@ -1,224 +0,0 @@ | |||
1 | /* Wrapper for DMA channel allocator that starts clocks etc */ | ||
2 | |||
3 | #include <linux/kernel.h> | ||
4 | #include <linux/spinlock.h> | ||
5 | #include <asm/dma.h> | ||
6 | #include <asm/arch/hwregs/reg_map.h> | ||
7 | #include <asm/arch/hwregs/reg_rdwr.h> | ||
8 | #include <asm/arch/hwregs/marb_defs.h> | ||
9 | #include <asm/arch/hwregs/config_defs.h> | ||
10 | #include <asm/arch/hwregs/strmux_defs.h> | ||
11 | #include <linux/errno.h> | ||
12 | #include <asm/system.h> | ||
13 | #include <asm/arch/arbiter.h> | ||
14 | |||
15 | static char used_dma_channels[MAX_DMA_CHANNELS]; | ||
16 | static const char * used_dma_channels_users[MAX_DMA_CHANNELS]; | ||
17 | |||
18 | static DEFINE_SPINLOCK(dma_lock); | ||
19 | |||
20 | int crisv32_request_dma(unsigned int dmanr, const char * device_id, | ||
21 | unsigned options, unsigned int bandwidth, | ||
22 | enum dma_owner owner) | ||
23 | { | ||
24 | unsigned long flags; | ||
25 | reg_config_rw_clk_ctrl clk_ctrl; | ||
26 | reg_strmux_rw_cfg strmux_cfg; | ||
27 | |||
28 | if (crisv32_arbiter_allocate_bandwidth(dmanr, | ||
29 | options & DMA_INT_MEM ? INT_REGION : EXT_REGION, | ||
30 | bandwidth)) | ||
31 | return -ENOMEM; | ||
32 | |||
33 | spin_lock_irqsave(&dma_lock, flags); | ||
34 | |||
35 | if (used_dma_channels[dmanr]) { | ||
36 | spin_unlock_irqrestore(&dma_lock, flags); | ||
37 | if (options & DMA_VERBOSE_ON_ERROR) { | ||
38 | printk("Failed to request DMA %i for %s, already allocated by %s\n", dmanr, device_id, used_dma_channels_users[dmanr]); | ||
39 | } | ||
40 | if (options & DMA_PANIC_ON_ERROR) | ||
41 | panic("request_dma error!"); | ||
42 | return -EBUSY; | ||
43 | } | ||
44 | clk_ctrl = REG_RD(config, regi_config, rw_clk_ctrl); | ||
45 | strmux_cfg = REG_RD(strmux, regi_strmux, rw_cfg); | ||
46 | |||
47 | switch(dmanr) | ||
48 | { | ||
49 | case 0: | ||
50 | case 1: | ||
51 | clk_ctrl.dma01_eth0 = 1; | ||
52 | break; | ||
53 | case 2: | ||
54 | case 3: | ||
55 | clk_ctrl.dma23 = 1; | ||
56 | break; | ||
57 | case 4: | ||
58 | case 5: | ||
59 | clk_ctrl.dma45 = 1; | ||
60 | break; | ||
61 | case 6: | ||
62 | case 7: | ||
63 | clk_ctrl.dma67 = 1; | ||
64 | break; | ||
65 | case 8: | ||
66 | case 9: | ||
67 | clk_ctrl.dma89_strcop = 1; | ||
68 | break; | ||
69 | #if MAX_DMA_CHANNELS-1 != 9 | ||
70 | #error Check dma.c | ||
71 | #endif | ||
72 | default: | ||
73 | spin_unlock_irqrestore(&dma_lock, flags); | ||
74 | if (options & DMA_VERBOSE_ON_ERROR) { | ||
75 | printk("Failed to request DMA %i for %s, only 0-%i valid)\n", dmanr, device_id, MAX_DMA_CHANNELS-1); | ||
76 | } | ||
77 | |||
78 | if (options & DMA_PANIC_ON_ERROR) | ||
79 | panic("request_dma error!"); | ||
80 | return -EINVAL; | ||
81 | } | ||
82 | |||
83 | switch(owner) | ||
84 | { | ||
85 | case dma_eth0: | ||
86 | if (dmanr == 0) | ||
87 | strmux_cfg.dma0 = regk_strmux_eth0; | ||
88 | else if (dmanr == 1) | ||
89 | strmux_cfg.dma1 = regk_strmux_eth0; | ||
90 | else | ||
91 | panic("Invalid DMA channel for eth0\n"); | ||
92 | break; | ||
93 | case dma_eth1: | ||
94 | if (dmanr == 6) | ||
95 | strmux_cfg.dma6 = regk_strmux_eth1; | ||
96 | else if (dmanr == 7) | ||
97 | strmux_cfg.dma7 = regk_strmux_eth1; | ||
98 | else | ||
99 | panic("Invalid DMA channel for eth1\n"); | ||
100 | break; | ||
101 | case dma_iop0: | ||
102 | if (dmanr == 2) | ||
103 | strmux_cfg.dma2 = regk_strmux_iop0; | ||
104 | else if (dmanr == 3) | ||
105 | strmux_cfg.dma3 = regk_strmux_iop0; | ||
106 | else | ||
107 | panic("Invalid DMA channel for iop0\n"); | ||
108 | break; | ||
109 | case dma_iop1: | ||
110 | if (dmanr == 4) | ||
111 | strmux_cfg.dma4 = regk_strmux_iop1; | ||
112 | else if (dmanr == 5) | ||
113 | strmux_cfg.dma5 = regk_strmux_iop1; | ||
114 | else | ||
115 | panic("Invalid DMA channel for iop1\n"); | ||
116 | break; | ||
117 | case dma_ser0: | ||
118 | if (dmanr == 6) | ||
119 | strmux_cfg.dma6 = regk_strmux_ser0; | ||
120 | else if (dmanr == 7) | ||
121 | strmux_cfg.dma7 = regk_strmux_ser0; | ||
122 | else | ||
123 | panic("Invalid DMA channel for ser0\n"); | ||
124 | break; | ||
125 | case dma_ser1: | ||
126 | if (dmanr == 4) | ||
127 | strmux_cfg.dma4 = regk_strmux_ser1; | ||
128 | else if (dmanr == 5) | ||
129 | strmux_cfg.dma5 = regk_strmux_ser1; | ||
130 | else | ||
131 | panic("Invalid DMA channel for ser1\n"); | ||
132 | break; | ||
133 | case dma_ser2: | ||
134 | if (dmanr == 2) | ||
135 | strmux_cfg.dma2 = regk_strmux_ser2; | ||
136 | else if (dmanr == 3) | ||
137 | strmux_cfg.dma3 = regk_strmux_ser2; | ||
138 | else | ||
139 | panic("Invalid DMA channel for ser2\n"); | ||
140 | break; | ||
141 | case dma_ser3: | ||
142 | if (dmanr == 8) | ||
143 | strmux_cfg.dma8 = regk_strmux_ser3; | ||
144 | else if (dmanr == 9) | ||
145 | strmux_cfg.dma9 = regk_strmux_ser3; | ||
146 | else | ||
147 | panic("Invalid DMA channel for ser3\n"); | ||
148 | break; | ||
149 | case dma_sser0: | ||
150 | if (dmanr == 4) | ||
151 | strmux_cfg.dma4 = regk_strmux_sser0; | ||
152 | else if (dmanr == 5) | ||
153 | strmux_cfg.dma5 = regk_strmux_sser0; | ||
154 | else | ||
155 | panic("Invalid DMA channel for sser0\n"); | ||
156 | break; | ||
157 | case dma_sser1: | ||
158 | if (dmanr == 6) | ||
159 | strmux_cfg.dma6 = regk_strmux_sser1; | ||
160 | else if (dmanr == 7) | ||
161 | strmux_cfg.dma7 = regk_strmux_sser1; | ||
162 | else | ||
163 | panic("Invalid DMA channel for sser1\n"); | ||
164 | break; | ||
165 | case dma_ata: | ||
166 | if (dmanr == 2) | ||
167 | strmux_cfg.dma2 = regk_strmux_ata; | ||
168 | else if (dmanr == 3) | ||
169 | strmux_cfg.dma3 = regk_strmux_ata; | ||
170 | else | ||
171 | panic("Invalid DMA channel for ata\n"); | ||
172 | break; | ||
173 | case dma_strp: | ||
174 | if (dmanr == 8) | ||
175 | strmux_cfg.dma8 = regk_strmux_strcop; | ||
176 | else if (dmanr == 9) | ||
177 | strmux_cfg.dma9 = regk_strmux_strcop; | ||
178 | else | ||
179 | panic("Invalid DMA channel for strp\n"); | ||
180 | break; | ||
181 | case dma_ext0: | ||
182 | if (dmanr == 6) | ||
183 | strmux_cfg.dma6 = regk_strmux_ext0; | ||
184 | else | ||
185 | panic("Invalid DMA channel for ext0\n"); | ||
186 | break; | ||
187 | case dma_ext1: | ||
188 | if (dmanr == 7) | ||
189 | strmux_cfg.dma7 = regk_strmux_ext1; | ||
190 | else | ||
191 | panic("Invalid DMA channel for ext1\n"); | ||
192 | break; | ||
193 | case dma_ext2: | ||
194 | if (dmanr == 2) | ||
195 | strmux_cfg.dma2 = regk_strmux_ext2; | ||
196 | else if (dmanr == 8) | ||
197 | strmux_cfg.dma8 = regk_strmux_ext2; | ||
198 | else | ||
199 | panic("Invalid DMA channel for ext2\n"); | ||
200 | break; | ||
201 | case dma_ext3: | ||
202 | if (dmanr == 3) | ||
203 | strmux_cfg.dma3 = regk_strmux_ext3; | ||
204 | else if (dmanr == 9) | ||
205 | strmux_cfg.dma9 = regk_strmux_ext2; | ||
206 | else | ||
207 | panic("Invalid DMA channel for ext2\n"); | ||
208 | break; | ||
209 | } | ||
210 | |||
211 | used_dma_channels[dmanr] = 1; | ||
212 | used_dma_channels_users[dmanr] = device_id; | ||
213 | REG_WR(config, regi_config, rw_clk_ctrl, clk_ctrl); | ||
214 | REG_WR(strmux, regi_strmux, rw_cfg, strmux_cfg); | ||
215 | spin_unlock_irqrestore(&dma_lock,flags); | ||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | void crisv32_free_dma(unsigned int dmanr) | ||
220 | { | ||
221 | spin_lock(&dma_lock); | ||
222 | used_dma_channels[dmanr] = 0; | ||
223 | spin_unlock(&dma_lock); | ||
224 | } | ||
diff --git a/arch/cris/arch-v32/kernel/entry.S b/arch/cris/arch-v32/kernel/entry.S index f9d27807b914..eebbaba45430 100644 --- a/arch/cris/arch-v32/kernel/entry.S +++ b/arch/cris/arch-v32/kernel/entry.S | |||
@@ -10,7 +10,7 @@ | |||
10 | * after a timer-interrupt and after each system call. | 10 | * after a timer-interrupt and after each system call. |
11 | * | 11 | * |
12 | * Stack layout in 'ret_from_system_call': | 12 | * Stack layout in 'ret_from_system_call': |
13 | * ptrace needs to have all regs on the stack. | 13 | * ptrace needs to have all regs on the stack. |
14 | * if the order here is changed, it needs to be | 14 | * if the order here is changed, it needs to be |
15 | * updated in fork.c:copy_process, signal.c:do_signal, | 15 | * updated in fork.c:copy_process, signal.c:do_signal, |
16 | * ptrace.c and ptrace.h | 16 | * ptrace.c and ptrace.h |
@@ -281,12 +281,10 @@ _work_notifysig: | |||
281 | ;; Deal with pending signals and notify-resume requests. | 281 | ;; Deal with pending signals and notify-resume requests. |
282 | 282 | ||
283 | addoq +TI_flags, $r0, $acr | 283 | addoq +TI_flags, $r0, $acr |
284 | move.d [$acr], $r13 ; The thread_info_flags parameter. | 284 | move.d [$acr], $r12 ; The thread_info_flags parameter. |
285 | move.d $r9, $r10 ; do_notify_resume syscall/irq param. | 285 | move.d $sp, $r11 ; The regs param. |
286 | moveq 0, $r11 ; oldset param - 0 in this case. | ||
287 | move.d $sp, $r12 ; The regs param. | ||
288 | jsr do_notify_resume | 286 | jsr do_notify_resume |
289 | nop | 287 | move.d $r9, $r10 ; do_notify_resume syscall/irq param. |
290 | 288 | ||
291 | ba _Rexit | 289 | ba _Rexit |
292 | nop | 290 | nop |
@@ -396,7 +394,7 @@ nmi_interrupt: | |||
396 | btstq REG_BIT(intr_vect, r_nmi, watchdog), $r0 | 394 | btstq REG_BIT(intr_vect, r_nmi, watchdog), $r0 |
397 | bpl 1f | 395 | bpl 1f |
398 | nop | 396 | nop |
399 | jsr handle_watchdog_bite ; In time.c. | 397 | jsr handle_watchdog_bite ; In time.c. |
400 | move.d $sp, $r10 ; Pointer to registers | 398 | move.d $sp, $r10 ; Pointer to registers |
401 | 1: btstq REG_BIT(intr_vect, r_nmi, ext), $r0 | 399 | 1: btstq REG_BIT(intr_vect, r_nmi, ext), $r0 |
402 | bpl 1f | 400 | bpl 1f |
@@ -515,6 +513,13 @@ _ugdb_handle_exception: | |||
515 | ba do_sigtrap ; SIGTRAP the offending process. | 513 | ba do_sigtrap ; SIGTRAP the offending process. |
516 | move.d [$sp+], $r0 ; Restore R0 in delay slot. | 514 | move.d [$sp+], $r0 ; Restore R0 in delay slot. |
517 | 515 | ||
516 | .global kernel_execve | ||
517 | kernel_execve: | ||
518 | move.d __NR_execve, $r9 | ||
519 | break 13 | ||
520 | ret | ||
521 | nop | ||
522 | |||
518 | .data | 523 | .data |
519 | 524 | ||
520 | .section .rodata,"a" | 525 | .section .rodata,"a" |
@@ -778,21 +783,21 @@ sys_call_table: | |||
778 | .long sys_epoll_ctl /* 255 */ | 783 | .long sys_epoll_ctl /* 255 */ |
779 | .long sys_epoll_wait | 784 | .long sys_epoll_wait |
780 | .long sys_remap_file_pages | 785 | .long sys_remap_file_pages |
781 | .long sys_set_tid_address | 786 | .long sys_set_tid_address |
782 | .long sys_timer_create | 787 | .long sys_timer_create |
783 | .long sys_timer_settime /* 260 */ | 788 | .long sys_timer_settime /* 260 */ |
784 | .long sys_timer_gettime | 789 | .long sys_timer_gettime |
785 | .long sys_timer_getoverrun | 790 | .long sys_timer_getoverrun |
786 | .long sys_timer_delete | 791 | .long sys_timer_delete |
787 | .long sys_clock_settime | 792 | .long sys_clock_settime |
788 | .long sys_clock_gettime /* 265 */ | 793 | .long sys_clock_gettime /* 265 */ |
789 | .long sys_clock_getres | 794 | .long sys_clock_getres |
790 | .long sys_clock_nanosleep | 795 | .long sys_clock_nanosleep |
791 | .long sys_statfs64 | 796 | .long sys_statfs64 |
792 | .long sys_fstatfs64 | 797 | .long sys_fstatfs64 |
793 | .long sys_tgkill /* 270 */ | 798 | .long sys_tgkill /* 270 */ |
794 | .long sys_utimes | 799 | .long sys_utimes |
795 | .long sys_fadvise64_64 | 800 | .long sys_fadvise64_64 |
796 | .long sys_ni_syscall /* sys_vserver */ | 801 | .long sys_ni_syscall /* sys_vserver */ |
797 | .long sys_ni_syscall /* sys_mbind */ | 802 | .long sys_ni_syscall /* sys_mbind */ |
798 | .long sys_ni_syscall /* 275 sys_get_mempolicy */ | 803 | .long sys_ni_syscall /* 275 sys_get_mempolicy */ |
@@ -805,6 +810,48 @@ sys_call_table: | |||
805 | .long sys_mq_getsetattr | 810 | .long sys_mq_getsetattr |
806 | .long sys_ni_syscall /* reserved for kexec */ | 811 | .long sys_ni_syscall /* reserved for kexec */ |
807 | .long sys_waitid | 812 | .long sys_waitid |
813 | .long sys_ni_syscall /* 285 */ /* available */ | ||
814 | .long sys_add_key | ||
815 | .long sys_request_key | ||
816 | .long sys_keyctl | ||
817 | .long sys_ioprio_set | ||
818 | .long sys_ioprio_get /* 290 */ | ||
819 | .long sys_inotify_init | ||
820 | .long sys_inotify_add_watch | ||
821 | .long sys_inotify_rm_watch | ||
822 | .long sys_migrate_pages | ||
823 | .long sys_openat /* 295 */ | ||
824 | .long sys_mkdirat | ||
825 | .long sys_mknodat | ||
826 | .long sys_fchownat | ||
827 | .long sys_futimesat | ||
828 | .long sys_fstatat64 /* 300 */ | ||
829 | .long sys_unlinkat | ||
830 | .long sys_renameat | ||
831 | .long sys_linkat | ||
832 | .long sys_symlinkat | ||
833 | .long sys_readlinkat /* 305 */ | ||
834 | .long sys_fchmodat | ||
835 | .long sys_faccessat | ||
836 | .long sys_pselect6 | ||
837 | .long sys_ppoll | ||
838 | .long sys_unshare /* 310 */ | ||
839 | .long sys_set_robust_list | ||
840 | .long sys_get_robust_list | ||
841 | .long sys_splice | ||
842 | .long sys_sync_file_range | ||
843 | .long sys_tee /* 315 */ | ||
844 | .long sys_vmsplice | ||
845 | .long sys_move_pages | ||
846 | .long sys_getcpu | ||
847 | .long sys_epoll_pwait | ||
848 | .long sys_utimensat /* 320 */ | ||
849 | .long sys_signalfd | ||
850 | .long sys_timerfd_create | ||
851 | .long sys_eventfd | ||
852 | .long sys_fallocate | ||
853 | .long sys_timerfd_settime /* 325 */ | ||
854 | .long sys_timerfd_gettime | ||
808 | 855 | ||
809 | /* | 856 | /* |
810 | * NOTE!! This doesn't have to be exact - we just have | 857 | * NOTE!! This doesn't have to be exact - we just have |
diff --git a/arch/cris/arch-v32/kernel/fasttimer.c b/arch/cris/arch-v32/kernel/fasttimer.c index b40551f9f40d..2de9d5849ef0 100644 --- a/arch/cris/arch-v32/kernel/fasttimer.c +++ b/arch/cris/arch-v32/kernel/fasttimer.c | |||
@@ -1,110 +1,9 @@ | |||
1 | /* $Id: fasttimer.c,v 1.11 2005/01/04 11:15:46 starvik Exp $ | 1 | /* |
2 | * linux/arch/cris/kernel/fasttimer.c | 2 | * linux/arch/cris/kernel/fasttimer.c |
3 | * | 3 | * |
4 | * Fast timers for ETRAX FS | 4 | * Fast timers for ETRAX FS |
5 | * This may be useful in other OS than Linux so use 2 space indentation... | ||
6 | * | ||
7 | * $Log: fasttimer.c,v $ | ||
8 | * Revision 1.11 2005/01/04 11:15:46 starvik | ||
9 | * Don't share timer IRQ. | ||
10 | * | ||
11 | * Revision 1.10 2004/12/07 09:19:38 starvik | ||
12 | * Corrected includes. | ||
13 | * Use correct interrupt macros. | ||
14 | * | ||
15 | * Revision 1.9 2004/05/14 10:18:58 starvik | ||
16 | * Export fast_timer_list | ||
17 | * | ||
18 | * Revision 1.8 2004/05/14 07:58:03 starvik | ||
19 | * Merge of changes from 2.4 | ||
20 | * | ||
21 | * Revision 1.7 2003/07/10 12:06:14 starvik | ||
22 | * Return IRQ_NONE if irq wasn't handled | ||
23 | * | ||
24 | * Revision 1.6 2003/07/04 08:27:49 starvik | ||
25 | * Merge of Linux 2.5.74 | ||
26 | * | ||
27 | * Revision 1.5 2003/06/05 10:16:22 johana | ||
28 | * New INTR_VECT macros. | ||
29 | * | ||
30 | * Revision 1.4 2003/06/03 08:49:45 johana | ||
31 | * Fixed typo. | ||
32 | * | ||
33 | * Revision 1.3 2003/06/02 12:51:27 johana | ||
34 | * Now compiles. | ||
35 | * Commented some include files that probably can be removed. | ||
36 | * | ||
37 | * Revision 1.2 2003/06/02 12:09:41 johana | ||
38 | * Ported to ETRAX FS using the trig interrupt instead of timer1. | ||
39 | * | ||
40 | * Revision 1.3 2002/12/12 08:26:32 starvik | ||
41 | * Don't use C-comments inside CVS comments | ||
42 | * | ||
43 | * Revision 1.2 2002/12/11 15:42:02 starvik | ||
44 | * Extracted v10 (ETRAX 100LX) specific stuff from arch/cris/kernel/ | ||
45 | * | ||
46 | * Revision 1.1 2002/11/18 07:58:06 starvik | ||
47 | * Fast timers (from Linux 2.4) | ||
48 | * | ||
49 | * Revision 1.5 2002/10/15 06:21:39 starvik | ||
50 | * Added call to init_waitqueue_head | ||
51 | * | 5 | * |
52 | * Revision 1.4 2002/05/28 17:47:59 johana | 6 | * Copyright (C) 2000-2006 Axis Communications AB, Lund, Sweden |
53 | * Added del_fast_timer() | ||
54 | * | ||
55 | * Revision 1.3 2002/05/28 16:16:07 johana | ||
56 | * Handle empty fast_timer_list | ||
57 | * | ||
58 | * Revision 1.2 2002/05/27 15:38:42 johana | ||
59 | * Made it compile without warnings on Linux 2.4. | ||
60 | * (includes, wait_queue, PROC_FS and snprintf) | ||
61 | * | ||
62 | * Revision 1.1 2002/05/27 15:32:25 johana | ||
63 | * arch/etrax100/kernel/fasttimer.c v1.8 from the elinux tree. | ||
64 | * | ||
65 | * Revision 1.8 2001/11/27 13:50:40 pkj | ||
66 | * Disable interrupts while stopping the timer and while modifying the | ||
67 | * list of active timers in timer1_handler() as it may be interrupted | ||
68 | * by other interrupts (e.g., the serial interrupt) which may add fast | ||
69 | * timers. | ||
70 | * | ||
71 | * Revision 1.7 2001/11/22 11:50:32 pkj | ||
72 | * * Only store information about the last 16 timers. | ||
73 | * * proc_fasttimer_read() now uses an allocated buffer, since it | ||
74 | * requires more space than just a page even for only writing the | ||
75 | * last 16 timers. The buffer is only allocated on request, so | ||
76 | * unless /proc/fasttimer is read, it is never allocated. | ||
77 | * * Renamed fast_timer_started to fast_timers_started to match | ||
78 | * fast_timers_added and fast_timers_expired. | ||
79 | * * Some clean-up. | ||
80 | * | ||
81 | * Revision 1.6 2000/12/13 14:02:08 johana | ||
82 | * Removed volatile for fast_timer_list | ||
83 | * | ||
84 | * Revision 1.5 2000/12/13 13:55:35 johana | ||
85 | * Added DEBUG_LOG, added som cli() and cleanup | ||
86 | * | ||
87 | * Revision 1.4 2000/12/05 13:48:50 johana | ||
88 | * Added range check when writing proc file, modified timer int handling | ||
89 | * | ||
90 | * Revision 1.3 2000/11/23 10:10:20 johana | ||
91 | * More debug/logging possibilities. | ||
92 | * Moved GET_JIFFIES_USEC() to timex.h and time.c | ||
93 | * | ||
94 | * Revision 1.2 2000/11/01 13:41:04 johana | ||
95 | * Clean up and bugfixes. | ||
96 | * Created new do_gettimeofday_fast() that gets a timeval struct | ||
97 | * with time based on jiffies and *R_TIMER0_DATA, uses a table | ||
98 | * for fast conversion of timer value to microseconds. | ||
99 | * (Much faster the standard do_gettimeofday() and we don't really | ||
100 | * want to use the true time - we want the "uptime" so timers don't screw up | ||
101 | * when we change the time. | ||
102 | * TODO: Add efficient support for continuous timers as well. | ||
103 | * | ||
104 | * Revision 1.1 2000/10/26 15:49:16 johana | ||
105 | * Added fasttimer, highresolution timers. | ||
106 | * | ||
107 | * Copyright (C) 2000,2001 2002, 2003 Axis Communications AB, Lund, Sweden | ||
108 | */ | 7 | */ |
109 | 8 | ||
110 | #include <linux/errno.h> | 9 | #include <linux/errno.h> |
@@ -122,9 +21,9 @@ | |||
122 | 21 | ||
123 | #include <linux/version.h> | 22 | #include <linux/version.h> |
124 | 23 | ||
125 | #include <asm/arch/hwregs/reg_map.h> | 24 | #include <hwregs/reg_map.h> |
126 | #include <asm/arch/hwregs/reg_rdwr.h> | 25 | #include <hwregs/reg_rdwr.h> |
127 | #include <asm/arch/hwregs/timer_defs.h> | 26 | #include <hwregs/timer_defs.h> |
128 | #include <asm/fasttimer.h> | 27 | #include <asm/fasttimer.h> |
129 | #include <linux/proc_fs.h> | 28 | #include <linux/proc_fs.h> |
130 | 29 | ||
@@ -140,30 +39,25 @@ | |||
140 | 39 | ||
141 | #define DEBUG_LOG_INCLUDED | 40 | #define DEBUG_LOG_INCLUDED |
142 | #define FAST_TIMER_LOG | 41 | #define FAST_TIMER_LOG |
143 | //#define FAST_TIMER_TEST | 42 | /* #define FAST_TIMER_TEST */ |
144 | 43 | ||
145 | #define FAST_TIMER_SANITY_CHECKS | 44 | #define FAST_TIMER_SANITY_CHECKS |
146 | 45 | ||
147 | #ifdef FAST_TIMER_SANITY_CHECKS | 46 | #ifdef FAST_TIMER_SANITY_CHECKS |
148 | #define SANITYCHECK(x) x | 47 | static int sanity_failed; |
149 | static int sanity_failed = 0; | ||
150 | #else | ||
151 | #define SANITYCHECK(x) | ||
152 | #endif | 48 | #endif |
153 | 49 | ||
154 | #define D1(x) | 50 | #define D1(x) |
155 | #define D2(x) | 51 | #define D2(x) |
156 | #define DP(x) | 52 | #define DP(x) |
157 | 53 | ||
158 | #define __INLINE__ inline | 54 | static unsigned int fast_timer_running; |
159 | 55 | static unsigned int fast_timers_added; | |
160 | static int fast_timer_running = 0; | 56 | static unsigned int fast_timers_started; |
161 | static int fast_timers_added = 0; | 57 | static unsigned int fast_timers_expired; |
162 | static int fast_timers_started = 0; | 58 | static unsigned int fast_timers_deleted; |
163 | static int fast_timers_expired = 0; | 59 | static unsigned int fast_timer_is_init; |
164 | static int fast_timers_deleted = 0; | 60 | static unsigned int fast_timer_ints; |
165 | static int fast_timer_is_init = 0; | ||
166 | static int fast_timer_ints = 0; | ||
167 | 61 | ||
168 | struct fast_timer *fast_timer_list = NULL; | 62 | struct fast_timer *fast_timer_list = NULL; |
169 | 63 | ||
@@ -171,8 +65,8 @@ struct fast_timer *fast_timer_list = NULL; | |||
171 | #define DEBUG_LOG_MAX 128 | 65 | #define DEBUG_LOG_MAX 128 |
172 | static const char * debug_log_string[DEBUG_LOG_MAX]; | 66 | static const char * debug_log_string[DEBUG_LOG_MAX]; |
173 | static unsigned long debug_log_value[DEBUG_LOG_MAX]; | 67 | static unsigned long debug_log_value[DEBUG_LOG_MAX]; |
174 | static int debug_log_cnt = 0; | 68 | static unsigned int debug_log_cnt; |
175 | static int debug_log_cnt_wrapped = 0; | 69 | static unsigned int debug_log_cnt_wrapped; |
176 | 70 | ||
177 | #define DEBUG_LOG(string, value) \ | 71 | #define DEBUG_LOG(string, value) \ |
178 | { \ | 72 | { \ |
@@ -202,103 +96,92 @@ struct fast_timer timer_expired_log[NUM_TIMER_STATS]; | |||
202 | int timer_div_settings[NUM_TIMER_STATS]; | 96 | int timer_div_settings[NUM_TIMER_STATS]; |
203 | int timer_delay_settings[NUM_TIMER_STATS]; | 97 | int timer_delay_settings[NUM_TIMER_STATS]; |
204 | 98 | ||
99 | struct work_struct fast_work; | ||
205 | 100 | ||
206 | static void | 101 | static void |
207 | timer_trig_handler(void); | 102 | timer_trig_handler(struct work_struct *work); |
208 | 103 | ||
209 | 104 | ||
210 | 105 | ||
211 | /* Not true gettimeofday, only checks the jiffies (uptime) + useconds */ | 106 | /* Not true gettimeofday, only checks the jiffies (uptime) + useconds */ |
212 | void __INLINE__ do_gettimeofday_fast(struct timeval *tv) | 107 | inline void do_gettimeofday_fast(struct fasttime_t *tv) |
213 | { | 108 | { |
214 | unsigned long sec = jiffies; | 109 | tv->tv_jiff = jiffies; |
215 | unsigned long usec = GET_JIFFIES_USEC(); | 110 | tv->tv_usec = GET_JIFFIES_USEC(); |
216 | |||
217 | usec += (sec % HZ) * (1000000 / HZ); | ||
218 | sec = sec / HZ; | ||
219 | |||
220 | if (usec > 1000000) | ||
221 | { | ||
222 | usec -= 1000000; | ||
223 | sec++; | ||
224 | } | ||
225 | tv->tv_sec = sec; | ||
226 | tv->tv_usec = usec; | ||
227 | } | 111 | } |
228 | 112 | ||
229 | int __INLINE__ timeval_cmp(struct timeval *t0, struct timeval *t1) | 113 | inline int fasttime_cmp(struct fasttime_t *t0, struct fasttime_t *t1) |
230 | { | 114 | { |
231 | if (t0->tv_sec < t1->tv_sec) | 115 | /* Compare jiffies. Takes care of wrapping */ |
232 | { | 116 | if (time_before(t0->tv_jiff, t1->tv_jiff)) |
233 | return -1; | 117 | return -1; |
234 | } | 118 | else if (time_after(t0->tv_jiff, t1->tv_jiff)) |
235 | else if (t0->tv_sec > t1->tv_sec) | 119 | return 1; |
236 | { | 120 | |
237 | return 1; | 121 | /* Compare us */ |
238 | } | 122 | if (t0->tv_usec < t1->tv_usec) |
239 | if (t0->tv_usec < t1->tv_usec) | 123 | return -1; |
240 | { | 124 | else if (t0->tv_usec > t1->tv_usec) |
241 | return -1; | 125 | return 1; |
242 | } | 126 | return 0; |
243 | else if (t0->tv_usec > t1->tv_usec) | ||
244 | { | ||
245 | return 1; | ||
246 | } | ||
247 | return 0; | ||
248 | } | 127 | } |
249 | 128 | ||
250 | /* Called with ints off */ | 129 | /* Called with ints off */ |
251 | void __INLINE__ start_timer_trig(unsigned long delay_us) | 130 | inline void start_timer_trig(unsigned long delay_us) |
252 | { | 131 | { |
253 | reg_timer_rw_ack_intr ack_intr = { 0 }; | 132 | reg_timer_rw_ack_intr ack_intr = { 0 }; |
254 | reg_timer_rw_intr_mask intr_mask; | 133 | reg_timer_rw_intr_mask intr_mask; |
255 | reg_timer_rw_trig trig; | 134 | reg_timer_rw_trig trig; |
256 | reg_timer_rw_trig_cfg trig_cfg = { 0 }; | 135 | reg_timer_rw_trig_cfg trig_cfg = { 0 }; |
257 | reg_timer_r_time r_time; | 136 | reg_timer_r_time r_time0; |
137 | reg_timer_r_time r_time1; | ||
138 | unsigned char trig_wrap; | ||
139 | unsigned char time_wrap; | ||
258 | 140 | ||
259 | r_time = REG_RD(timer, regi_timer, r_time); | 141 | r_time0 = REG_RD(timer, regi_timer0, r_time); |
260 | 142 | ||
261 | D1(printk("start_timer_trig : %d us freq: %i div: %i\n", | 143 | D1(printk("start_timer_trig : %d us freq: %i div: %i\n", |
262 | delay_us, freq_index, div)); | 144 | delay_us, freq_index, div)); |
263 | /* Clear trig irq */ | 145 | /* Clear trig irq */ |
264 | intr_mask = REG_RD(timer, regi_timer, rw_intr_mask); | 146 | intr_mask = REG_RD(timer, regi_timer0, rw_intr_mask); |
265 | intr_mask.trig = 0; | 147 | intr_mask.trig = 0; |
266 | REG_WR(timer, regi_timer, rw_intr_mask, intr_mask); | 148 | REG_WR(timer, regi_timer0, rw_intr_mask, intr_mask); |
267 | 149 | ||
268 | /* Set timer values */ | 150 | /* Set timer values and check if trigger wraps. */ |
269 | /* r_time is 100MHz (10 ns resolution) */ | 151 | /* r_time is 100MHz (10 ns resolution) */ |
270 | trig = r_time + delay_us*(1000/10); | 152 | trig_wrap = (trig = r_time0 + delay_us*(1000/10)) < r_time0; |
271 | 153 | ||
272 | timer_div_settings[fast_timers_started % NUM_TIMER_STATS] = trig; | 154 | timer_div_settings[fast_timers_started % NUM_TIMER_STATS] = trig; |
273 | timer_delay_settings[fast_timers_started % NUM_TIMER_STATS] = delay_us; | 155 | timer_delay_settings[fast_timers_started % NUM_TIMER_STATS] = delay_us; |
274 | 156 | ||
275 | /* Ack interrupt */ | 157 | /* Ack interrupt */ |
276 | ack_intr.trig = 1; | 158 | ack_intr.trig = 1; |
277 | REG_WR(timer, regi_timer, rw_ack_intr, ack_intr); | 159 | REG_WR(timer, regi_timer0, rw_ack_intr, ack_intr); |
278 | 160 | ||
279 | /* Start timer */ | 161 | /* Start timer */ |
280 | REG_WR(timer, regi_timer, rw_trig, trig); | 162 | REG_WR(timer, regi_timer0, rw_trig, trig); |
281 | trig_cfg.tmr = regk_timer_time; | 163 | trig_cfg.tmr = regk_timer_time; |
282 | REG_WR(timer, regi_timer, rw_trig_cfg, trig_cfg); | 164 | REG_WR(timer, regi_timer0, rw_trig_cfg, trig_cfg); |
283 | 165 | ||
284 | /* Check if we have already passed the trig time */ | 166 | /* Check if we have already passed the trig time */ |
285 | r_time = REG_RD(timer, regi_timer, r_time); | 167 | r_time1 = REG_RD(timer, regi_timer0, r_time); |
286 | if (r_time < trig) { | 168 | time_wrap = r_time1 < r_time0; |
169 | |||
170 | if ((trig_wrap && !time_wrap) || (r_time1 < trig)) { | ||
287 | /* No, Enable trig irq */ | 171 | /* No, Enable trig irq */ |
288 | intr_mask = REG_RD(timer, regi_timer, rw_intr_mask); | 172 | intr_mask = REG_RD(timer, regi_timer0, rw_intr_mask); |
289 | intr_mask.trig = 1; | 173 | intr_mask.trig = 1; |
290 | REG_WR(timer, regi_timer, rw_intr_mask, intr_mask); | 174 | REG_WR(timer, regi_timer0, rw_intr_mask, intr_mask); |
291 | fast_timers_started++; | 175 | fast_timers_started++; |
292 | fast_timer_running = 1; | 176 | fast_timer_running = 1; |
293 | } | 177 | } else { |
294 | else | ||
295 | { | ||
296 | /* We have passed the time, disable trig point, ack intr */ | 178 | /* We have passed the time, disable trig point, ack intr */ |
297 | trig_cfg.tmr = regk_timer_off; | 179 | trig_cfg.tmr = regk_timer_off; |
298 | REG_WR(timer, regi_timer, rw_trig_cfg, trig_cfg); | 180 | REG_WR(timer, regi_timer0, rw_trig_cfg, trig_cfg); |
299 | REG_WR(timer, regi_timer, rw_ack_intr, ack_intr); | 181 | REG_WR(timer, regi_timer0, rw_ack_intr, ack_intr); |
300 | /* call the int routine directly */ | 182 | /* call the int routine */ |
301 | timer_trig_handler(); | 183 | INIT_WORK(&fast_work, timer_trig_handler); |
184 | schedule_work(&fast_work); | ||
302 | } | 185 | } |
303 | 186 | ||
304 | } | 187 | } |
@@ -320,22 +203,20 @@ void start_one_shot_timer(struct fast_timer *t, | |||
320 | do_gettimeofday_fast(&t->tv_set); | 203 | do_gettimeofday_fast(&t->tv_set); |
321 | tmp = fast_timer_list; | 204 | tmp = fast_timer_list; |
322 | 205 | ||
323 | SANITYCHECK({ /* Check so this is not in the list already... */ | 206 | #ifdef FAST_TIMER_SANITY_CHECKS |
324 | while (tmp != NULL) | 207 | /* Check so this is not in the list already... */ |
325 | { | 208 | while (tmp != NULL) { |
326 | if (tmp == t) | 209 | if (tmp == t) { |
327 | { | 210 | printk(KERN_DEBUG |
328 | printk("timer name: %s data: 0x%08lX already in list!\n", name, data); | 211 | "timer name: %s data: 0x%08lX already " |
329 | sanity_failed++; | 212 | "in list!\n", name, data); |
330 | return; | 213 | sanity_failed++; |
331 | } | 214 | goto done; |
332 | else | 215 | } else |
333 | { | 216 | tmp = tmp->next; |
334 | tmp = tmp->next; | 217 | } |
335 | } | 218 | tmp = fast_timer_list; |
336 | } | 219 | #endif |
337 | tmp = fast_timer_list; | ||
338 | }); | ||
339 | 220 | ||
340 | t->delay_us = delay_us; | 221 | t->delay_us = delay_us; |
341 | t->function = function; | 222 | t->function = function; |
@@ -343,11 +224,10 @@ void start_one_shot_timer(struct fast_timer *t, | |||
343 | t->name = name; | 224 | t->name = name; |
344 | 225 | ||
345 | t->tv_expires.tv_usec = t->tv_set.tv_usec + delay_us % 1000000; | 226 | t->tv_expires.tv_usec = t->tv_set.tv_usec + delay_us % 1000000; |
346 | t->tv_expires.tv_sec = t->tv_set.tv_sec + delay_us / 1000000; | 227 | t->tv_expires.tv_jiff = t->tv_set.tv_jiff + delay_us / 1000000 / HZ; |
347 | if (t->tv_expires.tv_usec > 1000000) | 228 | if (t->tv_expires.tv_usec > 1000000) { |
348 | { | ||
349 | t->tv_expires.tv_usec -= 1000000; | 229 | t->tv_expires.tv_usec -= 1000000; |
350 | t->tv_expires.tv_sec++; | 230 | t->tv_expires.tv_jiff += HZ; |
351 | } | 231 | } |
352 | #ifdef FAST_TIMER_LOG | 232 | #ifdef FAST_TIMER_LOG |
353 | timer_added_log[fast_timers_added % NUM_TIMER_STATS] = *t; | 233 | timer_added_log[fast_timers_added % NUM_TIMER_STATS] = *t; |
@@ -355,15 +235,12 @@ void start_one_shot_timer(struct fast_timer *t, | |||
355 | fast_timers_added++; | 235 | fast_timers_added++; |
356 | 236 | ||
357 | /* Check if this should timeout before anything else */ | 237 | /* Check if this should timeout before anything else */ |
358 | if (tmp == NULL || timeval_cmp(&t->tv_expires, &tmp->tv_expires) < 0) | 238 | if (tmp == NULL || fasttime_cmp(&t->tv_expires, &tmp->tv_expires) < 0) { |
359 | { | ||
360 | /* Put first in list and modify the timer value */ | 239 | /* Put first in list and modify the timer value */ |
361 | t->prev = NULL; | 240 | t->prev = NULL; |
362 | t->next = fast_timer_list; | 241 | t->next = fast_timer_list; |
363 | if (fast_timer_list) | 242 | if (fast_timer_list) |
364 | { | ||
365 | fast_timer_list->prev = t; | 243 | fast_timer_list->prev = t; |
366 | } | ||
367 | fast_timer_list = t; | 244 | fast_timer_list = t; |
368 | #ifdef FAST_TIMER_LOG | 245 | #ifdef FAST_TIMER_LOG |
369 | timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t; | 246 | timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t; |
@@ -372,10 +249,8 @@ void start_one_shot_timer(struct fast_timer *t, | |||
372 | } else { | 249 | } else { |
373 | /* Put in correct place in list */ | 250 | /* Put in correct place in list */ |
374 | while (tmp->next && | 251 | while (tmp->next && |
375 | timeval_cmp(&t->tv_expires, &tmp->next->tv_expires) > 0) | 252 | fasttime_cmp(&t->tv_expires, &tmp->next->tv_expires) > 0) |
376 | { | ||
377 | tmp = tmp->next; | 253 | tmp = tmp->next; |
378 | } | ||
379 | /* Insert t after tmp */ | 254 | /* Insert t after tmp */ |
380 | t->prev = tmp; | 255 | t->prev = tmp; |
381 | t->next = tmp->next; | 256 | t->next = tmp->next; |
@@ -388,6 +263,7 @@ void start_one_shot_timer(struct fast_timer *t, | |||
388 | 263 | ||
389 | D2(printk("start_one_shot_timer: %d us done\n", delay_us)); | 264 | D2(printk("start_one_shot_timer: %d us done\n", delay_us)); |
390 | 265 | ||
266 | done: | ||
391 | local_irq_restore(flags); | 267 | local_irq_restore(flags); |
392 | } /* start_one_shot_timer */ | 268 | } /* start_one_shot_timer */ |
393 | 269 | ||
@@ -431,19 +307,18 @@ int del_fast_timer(struct fast_timer * t) | |||
431 | /* Timer interrupt handler for trig interrupts */ | 307 | /* Timer interrupt handler for trig interrupts */ |
432 | 308 | ||
433 | static irqreturn_t | 309 | static irqreturn_t |
434 | timer_trig_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 310 | timer_trig_interrupt(int irq, void *dev_id) |
435 | { | 311 | { |
436 | reg_timer_r_masked_intr masked_intr; | 312 | reg_timer_r_masked_intr masked_intr; |
437 | |||
438 | /* Check if the timer interrupt is for us (a trig int) */ | 313 | /* Check if the timer interrupt is for us (a trig int) */ |
439 | masked_intr = REG_RD(timer, regi_timer, r_masked_intr); | 314 | masked_intr = REG_RD(timer, regi_timer0, r_masked_intr); |
440 | if (!masked_intr.trig) | 315 | if (!masked_intr.trig) |
441 | return IRQ_NONE; | 316 | return IRQ_NONE; |
442 | timer_trig_handler(); | 317 | timer_trig_handler(NULL); |
443 | return IRQ_HANDLED; | 318 | return IRQ_HANDLED; |
444 | } | 319 | } |
445 | 320 | ||
446 | static void timer_trig_handler(void) | 321 | static void timer_trig_handler(struct work_struct *work) |
447 | { | 322 | { |
448 | reg_timer_rw_ack_intr ack_intr = { 0 }; | 323 | reg_timer_rw_ack_intr ack_intr = { 0 }; |
449 | reg_timer_rw_intr_mask intr_mask; | 324 | reg_timer_rw_intr_mask intr_mask; |
@@ -451,38 +326,45 @@ static void timer_trig_handler(void) | |||
451 | struct fast_timer *t; | 326 | struct fast_timer *t; |
452 | unsigned long flags; | 327 | unsigned long flags; |
453 | 328 | ||
329 | /* We keep interrupts disabled not only when we modify the | ||
330 | * fast timer list, but any time we hold a reference to a | ||
331 | * timer in the list, since del_fast_timer may be called | ||
332 | * from (another) interrupt context. Thus, the only time | ||
333 | * when interrupts are enabled is when calling the timer | ||
334 | * callback function. | ||
335 | */ | ||
454 | local_irq_save(flags); | 336 | local_irq_save(flags); |
455 | 337 | ||
456 | /* Clear timer trig interrupt */ | 338 | /* Clear timer trig interrupt */ |
457 | intr_mask = REG_RD(timer, regi_timer, rw_intr_mask); | 339 | intr_mask = REG_RD(timer, regi_timer0, rw_intr_mask); |
458 | intr_mask.trig = 0; | 340 | intr_mask.trig = 0; |
459 | REG_WR(timer, regi_timer, rw_intr_mask, intr_mask); | 341 | REG_WR(timer, regi_timer0, rw_intr_mask, intr_mask); |
460 | 342 | ||
461 | /* First stop timer, then ack interrupt */ | 343 | /* First stop timer, then ack interrupt */ |
462 | /* Stop timer */ | 344 | /* Stop timer */ |
463 | trig_cfg.tmr = regk_timer_off; | 345 | trig_cfg.tmr = regk_timer_off; |
464 | REG_WR(timer, regi_timer, rw_trig_cfg, trig_cfg); | 346 | REG_WR(timer, regi_timer0, rw_trig_cfg, trig_cfg); |
465 | 347 | ||
466 | /* Ack interrupt */ | 348 | /* Ack interrupt */ |
467 | ack_intr.trig = 1; | 349 | ack_intr.trig = 1; |
468 | REG_WR(timer, regi_timer, rw_ack_intr, ack_intr); | 350 | REG_WR(timer, regi_timer0, rw_ack_intr, ack_intr); |
469 | 351 | ||
470 | fast_timer_running = 0; | 352 | fast_timer_running = 0; |
471 | fast_timer_ints++; | 353 | fast_timer_ints++; |
472 | 354 | ||
473 | local_irq_restore(flags); | 355 | fast_timer_function_type *f; |
356 | unsigned long d; | ||
474 | 357 | ||
475 | t = fast_timer_list; | 358 | t = fast_timer_list; |
476 | while (t) | 359 | while (t) { |
477 | { | 360 | struct fasttime_t tv; |
478 | struct timeval tv; | ||
479 | 361 | ||
480 | /* Has it really expired? */ | 362 | /* Has it really expired? */ |
481 | do_gettimeofday_fast(&tv); | 363 | do_gettimeofday_fast(&tv); |
482 | D1(printk("t: %is %06ius\n", tv.tv_sec, tv.tv_usec)); | 364 | D1(printk(KERN_DEBUG |
365 | "t: %is %06ius\n", tv.tv_jiff, tv.tv_usec)); | ||
483 | 366 | ||
484 | if (timeval_cmp(&t->tv_expires, &tv) <= 0) | 367 | if (fasttime_cmp(&t->tv_expires, &tv) <= 0) { |
485 | { | ||
486 | /* Yes it has expired */ | 368 | /* Yes it has expired */ |
487 | #ifdef FAST_TIMER_LOG | 369 | #ifdef FAST_TIMER_LOG |
488 | timer_expired_log[fast_timers_expired % NUM_TIMER_STATS] = *t; | 370 | timer_expired_log[fast_timers_expired % NUM_TIMER_STATS] = *t; |
@@ -490,84 +372,77 @@ static void timer_trig_handler(void) | |||
490 | fast_timers_expired++; | 372 | fast_timers_expired++; |
491 | 373 | ||
492 | /* Remove this timer before call, since it may reuse the timer */ | 374 | /* Remove this timer before call, since it may reuse the timer */ |
493 | local_irq_save(flags); | ||
494 | if (t->prev) | 375 | if (t->prev) |
495 | { | ||
496 | t->prev->next = t->next; | 376 | t->prev->next = t->next; |
497 | } | ||
498 | else | 377 | else |
499 | { | ||
500 | fast_timer_list = t->next; | 378 | fast_timer_list = t->next; |
501 | } | ||
502 | if (t->next) | 379 | if (t->next) |
503 | { | ||
504 | t->next->prev = t->prev; | 380 | t->next->prev = t->prev; |
505 | } | ||
506 | t->prev = NULL; | 381 | t->prev = NULL; |
507 | t->next = NULL; | 382 | t->next = NULL; |
508 | local_irq_restore(flags); | ||
509 | 383 | ||
510 | if (t->function != NULL) | 384 | /* Save function callback data before enabling |
511 | { | 385 | * interrupts, since the timer may be removed and we |
512 | t->function(t->data); | 386 | * don't know how it was allocated (e.g. ->function |
513 | } | 387 | * and ->data may become overwritten after deletion |
514 | else | 388 | * if the timer was stack-allocated). |
515 | { | 389 | */ |
390 | f = t->function; | ||
391 | d = t->data; | ||
392 | |||
393 | if (f != NULL) { | ||
394 | /* Run the callback function with interrupts | ||
395 | * enabled. */ | ||
396 | local_irq_restore(flags); | ||
397 | f(d); | ||
398 | local_irq_save(flags); | ||
399 | } else | ||
516 | DEBUG_LOG("!trimertrig %i function==NULL!\n", fast_timer_ints); | 400 | DEBUG_LOG("!trimertrig %i function==NULL!\n", fast_timer_ints); |
517 | } | 401 | } else { |
518 | } | ||
519 | else | ||
520 | { | ||
521 | /* Timer is to early, let's set it again using the normal routines */ | 402 | /* Timer is to early, let's set it again using the normal routines */ |
522 | D1(printk(".\n")); | 403 | D1(printk(".\n")); |
523 | } | 404 | } |
524 | 405 | ||
525 | local_irq_save(flags); | 406 | t = fast_timer_list; |
526 | if ((t = fast_timer_list) != NULL) | 407 | if (t != NULL) { |
527 | { | ||
528 | /* Start next timer.. */ | 408 | /* Start next timer.. */ |
529 | long us; | 409 | long us = 0; |
530 | struct timeval tv; | 410 | struct fasttime_t tv; |
531 | 411 | ||
532 | do_gettimeofday_fast(&tv); | 412 | do_gettimeofday_fast(&tv); |
533 | us = ((t->tv_expires.tv_sec - tv.tv_sec) * 1000000 + | 413 | |
534 | t->tv_expires.tv_usec - tv.tv_usec); | 414 | /* time_after_eq takes care of wrapping */ |
535 | if (us > 0) | 415 | if (time_after_eq(t->tv_expires.tv_jiff, tv.tv_jiff)) |
536 | { | 416 | us = ((t->tv_expires.tv_jiff - tv.tv_jiff) * |
537 | if (!fast_timer_running) | 417 | 1000000 / HZ + t->tv_expires.tv_usec - |
538 | { | 418 | tv.tv_usec); |
419 | |||
420 | if (us > 0) { | ||
421 | if (!fast_timer_running) { | ||
539 | #ifdef FAST_TIMER_LOG | 422 | #ifdef FAST_TIMER_LOG |
540 | timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t; | 423 | timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t; |
541 | #endif | 424 | #endif |
542 | start_timer_trig(us); | 425 | start_timer_trig(us); |
543 | } | 426 | } |
544 | local_irq_restore(flags); | ||
545 | break; | 427 | break; |
546 | } | 428 | } else { |
547 | else | ||
548 | { | ||
549 | /* Timer already expired, let's handle it better late than never. | 429 | /* Timer already expired, let's handle it better late than never. |
550 | * The normal loop handles it | 430 | * The normal loop handles it |
551 | */ | 431 | */ |
552 | D1(printk("e! %d\n", us)); | 432 | D1(printk("e! %d\n", us)); |
553 | } | 433 | } |
554 | } | 434 | } |
555 | local_irq_restore(flags); | ||
556 | } | 435 | } |
557 | 436 | ||
558 | if (!t) | 437 | local_irq_restore(flags); |
559 | { | 438 | |
439 | if (!t) | ||
560 | D1(printk("ttrig stop!\n")); | 440 | D1(printk("ttrig stop!\n")); |
561 | } | ||
562 | } | 441 | } |
563 | 442 | ||
564 | static void wake_up_func(unsigned long data) | 443 | static void wake_up_func(unsigned long data) |
565 | { | 444 | { |
566 | #ifdef DECLARE_WAITQUEUE | ||
567 | wait_queue_head_t *sleep_wait_p = (wait_queue_head_t*)data; | 445 | wait_queue_head_t *sleep_wait_p = (wait_queue_head_t*)data; |
568 | #else | ||
569 | struct wait_queue **sleep_wait_p = (struct wait_queue **)data; | ||
570 | #endif | ||
571 | wake_up(sleep_wait_p); | 446 | wake_up(sleep_wait_p); |
572 | } | 447 | } |
573 | 448 | ||
@@ -577,28 +452,17 @@ static void wake_up_func(unsigned long data) | |||
577 | void schedule_usleep(unsigned long us) | 452 | void schedule_usleep(unsigned long us) |
578 | { | 453 | { |
579 | struct fast_timer t; | 454 | struct fast_timer t; |
580 | #ifdef DECLARE_WAITQUEUE | ||
581 | wait_queue_head_t sleep_wait; | 455 | wait_queue_head_t sleep_wait; |
582 | init_waitqueue_head(&sleep_wait); | 456 | init_waitqueue_head(&sleep_wait); |
583 | { | ||
584 | DECLARE_WAITQUEUE(wait, current); | ||
585 | #else | ||
586 | struct wait_queue *sleep_wait = NULL; | ||
587 | struct wait_queue wait = { current, NULL }; | ||
588 | #endif | ||
589 | 457 | ||
590 | D1(printk("schedule_usleep(%d)\n", us)); | 458 | D1(printk("schedule_usleep(%d)\n", us)); |
591 | add_wait_queue(&sleep_wait, &wait); | ||
592 | set_current_state(TASK_INTERRUPTIBLE); | ||
593 | start_one_shot_timer(&t, wake_up_func, (unsigned long)&sleep_wait, us, | 459 | start_one_shot_timer(&t, wake_up_func, (unsigned long)&sleep_wait, us, |
594 | "usleep"); | 460 | "usleep"); |
595 | schedule(); | 461 | /* Uninterruptible sleep on the fast timer. (The condition is |
596 | set_current_state(TASK_RUNNING); | 462 | * somewhat redundant since the timer is what wakes us up.) */ |
597 | remove_wait_queue(&sleep_wait, &wait); | 463 | wait_event(sleep_wait, !fast_timer_pending(&t)); |
464 | |||
598 | D1(printk("done schedule_usleep(%d)\n", us)); | 465 | D1(printk("done schedule_usleep(%d)\n", us)); |
599 | #ifdef DECLARE_WAITQUEUE | ||
600 | } | ||
601 | #endif | ||
602 | } | 466 | } |
603 | 467 | ||
604 | #ifdef CONFIG_PROC_FS | 468 | #ifdef CONFIG_PROC_FS |
@@ -618,20 +482,22 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len | |||
618 | unsigned long flags; | 482 | unsigned long flags; |
619 | int i = 0; | 483 | int i = 0; |
620 | int num_to_show; | 484 | int num_to_show; |
621 | struct timeval tv; | 485 | struct fasttime_t tv; |
622 | struct fast_timer *t, *nextt; | 486 | struct fast_timer *t, *nextt; |
623 | static char *bigbuf = NULL; | 487 | static char *bigbuf = NULL; |
624 | static unsigned long used; | 488 | static unsigned long used; |
625 | 489 | ||
626 | if (!bigbuf && !(bigbuf = vmalloc(BIG_BUF_SIZE))) | 490 | if (!bigbuf) { |
627 | { | 491 | bigbuf = vmalloc(BIG_BUF_SIZE); |
628 | used = 0; | 492 | if (!bigbuf) { |
629 | bigbuf[0] = '\0'; | 493 | used = 0; |
630 | return 0; | 494 | if (buf) |
631 | } | 495 | buf[0] = '\0'; |
632 | 496 | return 0; | |
633 | if (!offset || !used) | 497 | } |
634 | { | 498 | } |
499 | |||
500 | if (!offset || !used) { | ||
635 | do_gettimeofday_fast(&tv); | 501 | do_gettimeofday_fast(&tv); |
636 | 502 | ||
637 | used = 0; | 503 | used = 0; |
@@ -648,7 +514,7 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len | |||
648 | used += sprintf(bigbuf + used, "Fast timer running: %s\n", | 514 | used += sprintf(bigbuf + used, "Fast timer running: %s\n", |
649 | fast_timer_running ? "yes" : "no"); | 515 | fast_timer_running ? "yes" : "no"); |
650 | used += sprintf(bigbuf + used, "Current time: %lu.%06lu\n", | 516 | used += sprintf(bigbuf + used, "Current time: %lu.%06lu\n", |
651 | (unsigned long)tv.tv_sec, | 517 | (unsigned long)tv.tv_jiff, |
652 | (unsigned long)tv.tv_usec); | 518 | (unsigned long)tv.tv_usec); |
653 | #ifdef FAST_TIMER_SANITY_CHECKS | 519 | #ifdef FAST_TIMER_SANITY_CHECKS |
654 | used += sprintf(bigbuf + used, "Sanity failed: %i\n", | 520 | used += sprintf(bigbuf + used, "Sanity failed: %i\n", |
@@ -661,10 +527,8 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len | |||
661 | int end_i = debug_log_cnt; | 527 | int end_i = debug_log_cnt; |
662 | i = 0; | 528 | i = 0; |
663 | 529 | ||
664 | if (debug_log_cnt_wrapped) | 530 | if (debug_log_cnt_wrapped) |
665 | { | ||
666 | i = debug_log_cnt; | 531 | i = debug_log_cnt; |
667 | } | ||
668 | 532 | ||
669 | while ((i != end_i || (debug_log_cnt_wrapped && !used)) && | 533 | while ((i != end_i || (debug_log_cnt_wrapped && !used)) && |
670 | used+100 < BIG_BUF_SIZE) | 534 | used+100 < BIG_BUF_SIZE) |
@@ -697,9 +561,9 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len | |||
697 | "d: %6li us data: 0x%08lX" | 561 | "d: %6li us data: 0x%08lX" |
698 | "\n", | 562 | "\n", |
699 | t->name, | 563 | t->name, |
700 | (unsigned long)t->tv_set.tv_sec, | 564 | (unsigned long)t->tv_set.tv_jiff, |
701 | (unsigned long)t->tv_set.tv_usec, | 565 | (unsigned long)t->tv_set.tv_usec, |
702 | (unsigned long)t->tv_expires.tv_sec, | 566 | (unsigned long)t->tv_expires.tv_jiff, |
703 | (unsigned long)t->tv_expires.tv_usec, | 567 | (unsigned long)t->tv_expires.tv_usec, |
704 | t->delay_us, | 568 | t->delay_us, |
705 | t->data | 569 | t->data |
@@ -719,9 +583,9 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len | |||
719 | "d: %6li us data: 0x%08lX" | 583 | "d: %6li us data: 0x%08lX" |
720 | "\n", | 584 | "\n", |
721 | t->name, | 585 | t->name, |
722 | (unsigned long)t->tv_set.tv_sec, | 586 | (unsigned long)t->tv_set.tv_jiff, |
723 | (unsigned long)t->tv_set.tv_usec, | 587 | (unsigned long)t->tv_set.tv_usec, |
724 | (unsigned long)t->tv_expires.tv_sec, | 588 | (unsigned long)t->tv_expires.tv_jiff, |
725 | (unsigned long)t->tv_expires.tv_usec, | 589 | (unsigned long)t->tv_expires.tv_usec, |
726 | t->delay_us, | 590 | t->delay_us, |
727 | t->data | 591 | t->data |
@@ -739,9 +603,9 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len | |||
739 | "d: %6li us data: 0x%08lX" | 603 | "d: %6li us data: 0x%08lX" |
740 | "\n", | 604 | "\n", |
741 | t->name, | 605 | t->name, |
742 | (unsigned long)t->tv_set.tv_sec, | 606 | (unsigned long)t->tv_set.tv_jiff, |
743 | (unsigned long)t->tv_set.tv_usec, | 607 | (unsigned long)t->tv_set.tv_usec, |
744 | (unsigned long)t->tv_expires.tv_sec, | 608 | (unsigned long)t->tv_expires.tv_jiff, |
745 | (unsigned long)t->tv_expires.tv_usec, | 609 | (unsigned long)t->tv_expires.tv_usec, |
746 | t->delay_us, | 610 | t->delay_us, |
747 | t->data | 611 | t->data |
@@ -752,26 +616,25 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len | |||
752 | 616 | ||
753 | used += sprintf(bigbuf + used, "Active timers:\n"); | 617 | used += sprintf(bigbuf + used, "Active timers:\n"); |
754 | local_irq_save(flags); | 618 | local_irq_save(flags); |
755 | local_irq_save(flags); | ||
756 | t = fast_timer_list; | 619 | t = fast_timer_list; |
757 | while (t != NULL && (used+100 < BIG_BUF_SIZE)) | 620 | while (t != NULL && (used+100 < BIG_BUF_SIZE)) |
758 | { | 621 | { |
759 | nextt = t->next; | 622 | nextt = t->next; |
760 | local_irq_restore(flags); | 623 | local_irq_restore(flags); |
761 | used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu " | 624 | used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu " |
762 | "d: %6li us data: 0x%08lX" | 625 | "d: %6li us data: 0x%08lX" |
763 | /* " func: 0x%08lX" */ | 626 | /* " func: 0x%08lX" */ |
764 | "\n", | 627 | "\n", |
765 | t->name, | 628 | t->name, |
766 | (unsigned long)t->tv_set.tv_sec, | 629 | (unsigned long)t->tv_set.tv_jiff, |
767 | (unsigned long)t->tv_set.tv_usec, | 630 | (unsigned long)t->tv_set.tv_usec, |
768 | (unsigned long)t->tv_expires.tv_sec, | 631 | (unsigned long)t->tv_expires.tv_jiff, |
769 | (unsigned long)t->tv_expires.tv_usec, | 632 | (unsigned long)t->tv_expires.tv_usec, |
770 | t->delay_us, | 633 | t->delay_us, |
771 | t->data | 634 | t->data |
772 | /* , t->function */ | 635 | /* , t->function */ |
773 | ); | 636 | ); |
774 | local_irq_disable(); | 637 | local_irq_save(flags); |
775 | if (t->next != nextt) | 638 | if (t->next != nextt) |
776 | { | 639 | { |
777 | printk("timer removed!\n"); | 640 | printk("timer removed!\n"); |
@@ -800,7 +663,7 @@ static volatile int num_test_timeout = 0; | |||
800 | static struct fast_timer tr[10]; | 663 | static struct fast_timer tr[10]; |
801 | static int exp_num[10]; | 664 | static int exp_num[10]; |
802 | 665 | ||
803 | static struct timeval tv_exp[100]; | 666 | static struct fasttime_t tv_exp[100]; |
804 | 667 | ||
805 | static void test_timeout(unsigned long data) | 668 | static void test_timeout(unsigned long data) |
806 | { | 669 | { |
@@ -838,7 +701,7 @@ static void fast_timer_test(void) | |||
838 | int prev_num; | 701 | int prev_num; |
839 | int j; | 702 | int j; |
840 | 703 | ||
841 | struct timeval tv, tv0, tv1, tv2; | 704 | struct fasttime_t tv, tv0, tv1, tv2; |
842 | 705 | ||
843 | printk("fast_timer_test() start\n"); | 706 | printk("fast_timer_test() start\n"); |
844 | do_gettimeofday_fast(&tv); | 707 | do_gettimeofday_fast(&tv); |
@@ -851,21 +714,22 @@ static void fast_timer_test(void) | |||
851 | { | 714 | { |
852 | do_gettimeofday_fast(&tv_exp[j]); | 715 | do_gettimeofday_fast(&tv_exp[j]); |
853 | } | 716 | } |
854 | printk("fast_timer_test() %is %06i\n", tv.tv_sec, tv.tv_usec); | 717 | printk(KERN_DEBUG "fast_timer_test() %is %06i\n", tv.tv_jiff, tv.tv_usec); |
855 | 718 | ||
856 | for (j = 0; j < 1000; j++) | 719 | for (j = 0; j < 1000; j++) |
857 | { | 720 | { |
858 | printk("%i %i %i %i %i\n",j_u[j], j_u[j+1], j_u[j+2], j_u[j+3], j_u[j+4]); | 721 | printk(KERN_DEBUG "%i %i %i %i %i\n", |
722 | j_u[j], j_u[j+1], j_u[j+2], j_u[j+3], j_u[j+4]); | ||
859 | j += 4; | 723 | j += 4; |
860 | } | 724 | } |
861 | for (j = 0; j < 100; j++) | 725 | for (j = 0; j < 100; j++) |
862 | { | 726 | { |
863 | printk("%i.%i %i.%i %i.%i %i.%i %i.%i\n", | 727 | printk(KERN_DEBUG "%i.%i %i.%i %i.%i %i.%i %i.%i\n", |
864 | tv_exp[j].tv_sec,tv_exp[j].tv_usec, | 728 | tv_exp[j].tv_jiff, tv_exp[j].tv_usec, |
865 | tv_exp[j+1].tv_sec,tv_exp[j+1].tv_usec, | 729 | tv_exp[j+1].tv_jiff, tv_exp[j+1].tv_usec, |
866 | tv_exp[j+2].tv_sec,tv_exp[j+2].tv_usec, | 730 | tv_exp[j+2].tv_jiff, tv_exp[j+2].tv_usec, |
867 | tv_exp[j+3].tv_sec,tv_exp[j+3].tv_usec, | 731 | tv_exp[j+3].tv_jiff, tv_exp[j+3].tv_usec, |
868 | tv_exp[j+4].tv_sec,tv_exp[j+4].tv_usec); | 732 | tv_exp[j+4].tv_jiff, tv_exp[j+4].tv_usec); |
869 | j += 4; | 733 | j += 4; |
870 | } | 734 | } |
871 | do_gettimeofday_fast(&tv0); | 735 | do_gettimeofday_fast(&tv0); |
@@ -892,14 +756,15 @@ static void fast_timer_test(void) | |||
892 | while (num_test_timeout < i) | 756 | while (num_test_timeout < i) |
893 | { | 757 | { |
894 | if (num_test_timeout != prev_num) | 758 | if (num_test_timeout != prev_num) |
895 | { | ||
896 | prev_num = num_test_timeout; | 759 | prev_num = num_test_timeout; |
897 | } | ||
898 | } | 760 | } |
899 | do_gettimeofday_fast(&tv2); | 761 | do_gettimeofday_fast(&tv2); |
900 | printk("Timers started %is %06i\n", tv0.tv_sec, tv0.tv_usec); | 762 | printk(KERN_INFO "Timers started %is %06i\n", |
901 | printk("Timers started at %is %06i\n", tv1.tv_sec, tv1.tv_usec); | 763 | tv0.tv_jiff, tv0.tv_usec); |
902 | printk("Timers done %is %06i\n", tv2.tv_sec, tv2.tv_usec); | 764 | printk(KERN_INFO "Timers started at %is %06i\n", |
765 | tv1.tv_jiff, tv1.tv_usec); | ||
766 | printk(KERN_INFO "Timers done %is %06i\n", | ||
767 | tv2.tv_jiff, tv2.tv_usec); | ||
903 | DP(printk("buf0:\n"); | 768 | DP(printk("buf0:\n"); |
904 | printk(buf0); | 769 | printk(buf0); |
905 | printk("buf1:\n"); | 770 | printk("buf1:\n"); |
@@ -921,9 +786,9 @@ static void fast_timer_test(void) | |||
921 | printk("%-10s set: %6is %06ius exp: %6is %06ius " | 786 | printk("%-10s set: %6is %06ius exp: %6is %06ius " |
922 | "data: 0x%08X func: 0x%08X\n", | 787 | "data: 0x%08X func: 0x%08X\n", |
923 | t->name, | 788 | t->name, |
924 | t->tv_set.tv_sec, | 789 | t->tv_set.tv_jiff, |
925 | t->tv_set.tv_usec, | 790 | t->tv_set.tv_usec, |
926 | t->tv_expires.tv_sec, | 791 | t->tv_expires.tv_jiff, |
927 | t->tv_expires.tv_usec, | 792 | t->tv_expires.tv_usec, |
928 | t->data, | 793 | t->data, |
929 | t->function | 794 | t->function |
@@ -931,10 +796,12 @@ static void fast_timer_test(void) | |||
931 | 796 | ||
932 | printk(" del: %6ius did exp: %6is %06ius as #%i error: %6li\n", | 797 | printk(" del: %6ius did exp: %6is %06ius as #%i error: %6li\n", |
933 | t->delay_us, | 798 | t->delay_us, |
934 | tv_exp[j].tv_sec, | 799 | tv_exp[j].tv_jiff, |
935 | tv_exp[j].tv_usec, | 800 | tv_exp[j].tv_usec, |
936 | exp_num[j], | 801 | exp_num[j], |
937 | (tv_exp[j].tv_sec - t->tv_expires.tv_sec)*1000000 + tv_exp[j].tv_usec - t->tv_expires.tv_usec); | 802 | (tv_exp[j].tv_jiff - t->tv_expires.tv_jiff) * |
803 | 1000000 + tv_exp[j].tv_usec - | ||
804 | t->tv_expires.tv_usec); | ||
938 | } | 805 | } |
939 | proc_fasttimer_read(buf5, NULL, 0, 0, 0); | 806 | proc_fasttimer_read(buf5, NULL, 0, 0, 0); |
940 | printk("buf5 after all done:\n"); | 807 | printk("buf5 after all done:\n"); |
@@ -944,7 +811,7 @@ static void fast_timer_test(void) | |||
944 | #endif | 811 | #endif |
945 | 812 | ||
946 | 813 | ||
947 | void fast_timer_init(void) | 814 | int fast_timer_init(void) |
948 | { | 815 | { |
949 | /* For some reason, request_irq() hangs when called froom time_init() */ | 816 | /* For some reason, request_irq() hangs when called froom time_init() */ |
950 | if (!fast_timer_is_init) | 817 | if (!fast_timer_is_init) |
@@ -952,18 +819,20 @@ void fast_timer_init(void) | |||
952 | printk("fast_timer_init()\n"); | 819 | printk("fast_timer_init()\n"); |
953 | 820 | ||
954 | #ifdef CONFIG_PROC_FS | 821 | #ifdef CONFIG_PROC_FS |
955 | if ((fasttimer_proc_entry = create_proc_entry( "fasttimer", 0, 0 ))) | 822 | fasttimer_proc_entry = create_proc_entry("fasttimer", 0, 0); |
956 | fasttimer_proc_entry->read_proc = proc_fasttimer_read; | 823 | if (fasttimer_proc_entry) |
824 | fasttimer_proc_entry->read_proc = proc_fasttimer_read; | ||
957 | #endif /* PROC_FS */ | 825 | #endif /* PROC_FS */ |
958 | if(request_irq(TIMER_INTR_VECT, timer_trig_interrupt, IRQF_DISABLED, | 826 | if (request_irq(TIMER0_INTR_VECT, timer_trig_interrupt, |
959 | "fast timer int", NULL)) | 827 | IRQF_SHARED | IRQF_DISABLED, |
960 | { | 828 | "fast timer int", &fast_timer_list)) |
961 | printk("err: timer1 irq\n"); | 829 | printk(KERN_ERR "err: fasttimer irq\n"); |
962 | } | ||
963 | fast_timer_is_init = 1; | 830 | fast_timer_is_init = 1; |
964 | #ifdef FAST_TIMER_TEST | 831 | #ifdef FAST_TIMER_TEST |
965 | printk("do test\n"); | 832 | printk("do test\n"); |
966 | fast_timer_test(); | 833 | fast_timer_test(); |
967 | #endif | 834 | #endif |
968 | } | 835 | } |
836 | return 0; | ||
969 | } | 837 | } |
838 | __initcall(fast_timer_init); | ||
diff --git a/arch/cris/arch-v32/kernel/head.S b/arch/cris/arch-v32/kernel/head.S index 20bd80a84e48..2d66a7c320e1 100644 --- a/arch/cris/arch-v32/kernel/head.S +++ b/arch/cris/arch-v32/kernel/head.S | |||
@@ -4,22 +4,25 @@ | |||
4 | * Copyright (C) 2003, Axis Communications AB | 4 | * Copyright (C) 2003, Axis Communications AB |
5 | */ | 5 | */ |
6 | 6 | ||
7 | |||
8 | #define ASSEMBLER_MACROS_ONLY | 7 | #define ASSEMBLER_MACROS_ONLY |
9 | 8 | ||
10 | /* | 9 | /* |
11 | * The macros found in mmu_defs_asm.h uses the ## concatenation operator, so | 10 | * The macros found in mmu_defs_asm.h uses the ## concatenation operator, so |
12 | * -traditional must not be used when assembling this file. | 11 | * -traditional must not be used when assembling this file. |
13 | */ | 12 | */ |
14 | #include <asm/arch/hwregs/reg_rdwr.h> | 13 | #include <hwregs/reg_rdwr.h> |
15 | #include <asm/arch/hwregs/asm/mmu_defs_asm.h> | 14 | #include <asm/arch/memmap.h> |
16 | #include <asm/arch/hwregs/asm/reg_map_asm.h> | 15 | #include <hwregs/intr_vect.h> |
17 | #include <asm/arch/hwregs/asm/config_defs_asm.h> | 16 | #include <hwregs/asm/mmu_defs_asm.h> |
18 | #include <asm/arch/hwregs/asm/bif_core_defs_asm.h> | 17 | #include <hwregs/asm/reg_map_asm.h> |
18 | #include <asm/arch/mach/startup.inc> | ||
19 | 19 | ||
20 | #define CRAMFS_MAGIC 0x28cd3d45 | 20 | #define CRAMFS_MAGIC 0x28cd3d45 |
21 | #define JHEAD_MAGIC 0x1FF528A6 | ||
22 | #define JHEAD_SIZE 8 | ||
21 | #define RAM_INIT_MAGIC 0x56902387 | 23 | #define RAM_INIT_MAGIC 0x56902387 |
22 | #define COMMAND_LINE_MAGIC 0x87109563 | 24 | #define COMMAND_LINE_MAGIC 0x87109563 |
25 | #define NAND_BOOT_MAGIC 0x9a9db001 | ||
23 | 26 | ||
24 | ;; NOTE: R8 and R9 carry information from the decompressor (if the | 27 | ;; NOTE: R8 and R9 carry information from the decompressor (if the |
25 | ;; kernel was compressed). They must not be used in the code below | 28 | ;; kernel was compressed). They must not be used in the code below |
@@ -30,12 +33,11 @@ | |||
30 | .global romfs_start | 33 | .global romfs_start |
31 | .global romfs_length | 34 | .global romfs_length |
32 | .global romfs_in_flash | 35 | .global romfs_in_flash |
36 | .global nand_boot | ||
33 | .global swapper_pg_dir | 37 | .global swapper_pg_dir |
34 | .global crisv32_nand_boot | ||
35 | .global crisv32_nand_cramfs_offset | ||
36 | 38 | ||
37 | ;; Dummy section to make it bootable with current VCS simulator | 39 | ;; Dummy section to make it bootable with current VCS simulator |
38 | #ifdef CONFIG_ETRAXFS_SIM | 40 | #ifdef CONFIG_ETRAX_VCS_SIM |
39 | .section ".boot", "ax" | 41 | .section ".boot", "ax" |
40 | ba tstart | 42 | ba tstart |
41 | nop | 43 | nop |
@@ -51,33 +53,15 @@ tstart: | |||
51 | ;; | 53 | ;; |
52 | di | 54 | di |
53 | 55 | ||
54 | ;; Start clocks for used blocks. | 56 | START_CLOCKS |
55 | move.d REG_ADDR(config, regi_config, rw_clk_ctrl), $r1 | 57 | |
56 | move.d [$r1], $r0 | 58 | SETUP_WAIT_STATES |
57 | or.d REG_STATE(config, rw_clk_ctrl, cpu, yes) | \ | 59 | |
58 | REG_STATE(config, rw_clk_ctrl, bif, yes) | \ | 60 | GIO_INIT |
59 | REG_STATE(config, rw_clk_ctrl, fix_io, yes), $r0 | 61 | |
60 | move.d $r0, [$r1] | 62 | #ifdef CONFIG_SMP |
61 | 63 | secondary_cpu_entry: /* Entry point for secondary CPUs */ | |
62 | ;; Set up waitstates etc | 64 | di |
63 | move.d REG_ADDR(bif_core, regi_bif_core, rw_grp1_cfg), $r0 | ||
64 | move.d CONFIG_ETRAX_MEM_GRP1_CONFIG, $r1 | ||
65 | move.d $r1, [$r0] | ||
66 | move.d REG_ADDR(bif_core, regi_bif_core, rw_grp2_cfg), $r0 | ||
67 | move.d CONFIG_ETRAX_MEM_GRP2_CONFIG, $r1 | ||
68 | move.d $r1, [$r0] | ||
69 | move.d REG_ADDR(bif_core, regi_bif_core, rw_grp3_cfg), $r0 | ||
70 | move.d CONFIG_ETRAX_MEM_GRP3_CONFIG, $r1 | ||
71 | move.d $r1, [$r0] | ||
72 | move.d REG_ADDR(bif_core, regi_bif_core, rw_grp4_cfg), $r0 | ||
73 | move.d CONFIG_ETRAX_MEM_GRP4_CONFIG, $r1 | ||
74 | move.d $r1, [$r0] | ||
75 | |||
76 | #ifdef CONFIG_ETRAXFS_SIM | ||
77 | ;; Set up minimal flash waitstates | ||
78 | move.d 0, $r10 | ||
79 | move.d REG_ADDR(bif_core, regi_bif_core, rw_grp1_cfg), $r11 | ||
80 | move.d $r10, [$r11] | ||
81 | #endif | 65 | #endif |
82 | 66 | ||
83 | ;; Setup and enable the MMU. Use same configuration for both the data | 67 | ;; Setup and enable the MMU. Use same configuration for both the data |
@@ -85,7 +69,7 @@ tstart: | |||
85 | ;; | 69 | ;; |
86 | ;; Note; 3 cycles is needed for a bank-select to take effect. Further; | 70 | ;; Note; 3 cycles is needed for a bank-select to take effect. Further; |
87 | ;; bank 1 is the instruction MMU, bank 2 is the data MMU. | 71 | ;; bank 1 is the instruction MMU, bank 2 is the data MMU. |
88 | #ifndef CONFIG_ETRAXFS_SIM | 72 | #ifndef CONFIG_ETRAX_VCS_SIM |
89 | move.d REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 8) \ | 73 | move.d REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 8) \ |
90 | | REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 4) \ | 74 | | REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 4) \ |
91 | | REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb), $r0 | 75 | | REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb), $r0 |
@@ -93,7 +77,7 @@ tstart: | |||
93 | ;; Map the virtual DRAM to the RW eprom area at address 0. | 77 | ;; Map the virtual DRAM to the RW eprom area at address 0. |
94 | ;; Also map 0xa for the hook calls, | 78 | ;; Also map 0xa for the hook calls, |
95 | move.d REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 8) \ | 79 | move.d REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 8) \ |
96 | | REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 0) \ | 80 | | REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 4) \ |
97 | | REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb) \ | 81 | | REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb) \ |
98 | | REG_FIELD(mmu, rw_mm_kbase_hi, base_a, 0xa), $r0 | 82 | | REG_FIELD(mmu, rw_mm_kbase_hi, base_a, 0xa), $r0 |
99 | #endif | 83 | #endif |
@@ -104,7 +88,7 @@ tstart: | |||
104 | 88 | ||
105 | ;; Enable certain page protections and setup linear mapping | 89 | ;; Enable certain page protections and setup linear mapping |
106 | ;; for f,e,c,b,4,0. | 90 | ;; for f,e,c,b,4,0. |
107 | #ifndef CONFIG_ETRAXFS_SIM | 91 | #ifndef CONFIG_ETRAX_VCS_SIM |
108 | move.d REG_STATE(mmu, rw_mm_cfg, we, on) \ | 92 | move.d REG_STATE(mmu, rw_mm_cfg, we, on) \ |
109 | | REG_STATE(mmu, rw_mm_cfg, acc, on) \ | 93 | | REG_STATE(mmu, rw_mm_cfg, acc, on) \ |
110 | | REG_STATE(mmu, rw_mm_cfg, ex, on) \ | 94 | | REG_STATE(mmu, rw_mm_cfg, ex, on) \ |
@@ -183,17 +167,11 @@ tstart: | |||
183 | nop | 167 | nop |
184 | nop | 168 | nop |
185 | nop | 169 | nop |
186 | move $s10, $r0 | 170 | move $s12, $r0 |
187 | cmpq 0, $r0 | 171 | cmpq 0, $r0 |
188 | beq master_cpu | 172 | beq master_cpu |
189 | nop | 173 | nop |
190 | slave_cpu: | 174 | slave_cpu: |
191 | ; A slave waits for cpu_now_booting to be equal to CPU ID. | ||
192 | move.d cpu_now_booting, $r1 | ||
193 | slave_wait: | ||
194 | cmp.d [$r1], $r0 | ||
195 | bne slave_wait | ||
196 | nop | ||
197 | ; Time to boot-up. Get stack location provided by master CPU. | 175 | ; Time to boot-up. Get stack location provided by master CPU. |
198 | move.d smp_init_current_idle_thread, $r1 | 176 | move.d smp_init_current_idle_thread, $r1 |
199 | move.d [$r1], $sp | 177 | move.d [$r1], $sp |
@@ -203,9 +181,16 @@ slave_wait: | |||
203 | jsr smp_callin | 181 | jsr smp_callin |
204 | nop | 182 | nop |
205 | master_cpu: | 183 | master_cpu: |
184 | /* Set up entry point for secondary CPUs. The boot ROM has set up | ||
185 | * EBP at start of internal memory. The CPU will get there | ||
186 | * later when we issue an IPI to them... */ | ||
187 | move.d MEM_INTMEM_START + IPI_INTR_VECT * 4, $r0 | ||
188 | move.d secondary_cpu_entry, $r1 | ||
189 | move.d $r1, [$r0] | ||
206 | #endif | 190 | #endif |
207 | #ifndef CONFIG_ETRAXFS_SIM | 191 | #ifndef CONFIG_ETRAX_VCS_SIM |
208 | ;; Check if starting from DRAM or flash. | 192 | ; Check if starting from DRAM (network->RAM boot or unpacked |
193 | ; compressed kernel), or directly from flash. | ||
209 | lapcq ., $r0 | 194 | lapcq ., $r0 |
210 | and.d 0x7fffffff, $r0 ; Mask off the non-cache bit. | 195 | and.d 0x7fffffff, $r0 ; Mask off the non-cache bit. |
211 | cmp.d 0x10000, $r0 ; Arbitrary, something above this code. | 196 | cmp.d 0x10000, $r0 ; Arbitrary, something above this code. |
@@ -232,12 +217,13 @@ _inflash: | |||
232 | beq _dram_initialized | 217 | beq _dram_initialized |
233 | nop | 218 | nop |
234 | 219 | ||
235 | #include "../lib/dram_init.S" | 220 | #include "../mach/dram_init.S" |
236 | 221 | ||
237 | _dram_initialized: | 222 | _dram_initialized: |
238 | ;; Copy the text and data section to DRAM. This depends on that the | 223 | ;; Copy the text and data section to DRAM. This depends on that the |
239 | ;; variables used below are correctly set up by the linker script. | 224 | ;; variables used below are correctly set up by the linker script. |
240 | ;; The calculated value stored in R4 is used below. | 225 | ;; The calculated value stored in R4 is used below. |
226 | ;; Leave the cramfs file system (piggybacked after the kernel) in flash. | ||
241 | moveq 0, $r0 ; Source. | 227 | moveq 0, $r0 ; Source. |
242 | move.d text_start, $r1 ; Destination. | 228 | move.d text_start, $r1 ; Destination. |
243 | move.d __vmlinux_end, $r2 | 229 | move.d __vmlinux_end, $r2 |
@@ -249,7 +235,7 @@ _dram_initialized: | |||
249 | blo 1b | 235 | blo 1b |
250 | nop | 236 | nop |
251 | 237 | ||
252 | ;; Keep CRAMFS in flash. | 238 | ;; Check for cramfs. |
253 | moveq 0, $r0 | 239 | moveq 0, $r0 |
254 | move.d romfs_length, $r1 | 240 | move.d romfs_length, $r1 |
255 | move.d $r0, [$r1] | 241 | move.d $r0, [$r1] |
@@ -258,6 +244,7 @@ _dram_initialized: | |||
258 | bne 1f | 244 | bne 1f |
259 | nop | 245 | nop |
260 | 246 | ||
247 | ;; Set length and start of cramfs, set romfs_in_flash flag | ||
261 | addoq +4, $r4, $acr | 248 | addoq +4, $r4, $acr |
262 | move.d [$acr], $r0 | 249 | move.d [$acr], $r0 |
263 | move.d romfs_length, $r1 | 250 | move.d romfs_length, $r1 |
@@ -273,35 +260,32 @@ _dram_initialized: | |||
273 | nop | 260 | nop |
274 | 261 | ||
275 | _inram: | 262 | _inram: |
276 | ;; Check if booting from NAND flash (in that case we just remember the offset | 263 | ;; Check if booting from NAND flash; if so, set appropriate flags |
277 | ;; into the flash where cramfs should be). | 264 | ;; and move on. |
278 | move.d REG_ADDR(config, regi_config, r_bootsel), $r0 | 265 | cmp.d NAND_BOOT_MAGIC, $r12 |
279 | move.d [$r0], $r0 | 266 | bne move_cramfs ; not nand, jump |
280 | and.d REG_MASK(config, r_bootsel, boot_mode), $r0 | ||
281 | cmp.d REG_STATE(config, r_bootsel, boot_mode, nand), $r0 | ||
282 | bne move_cramfs | ||
283 | moveq 1,$r0 | ||
284 | move.d crisv32_nand_boot, $r1 | ||
285 | move.d $r0, [$r1] | ||
286 | move.d crisv32_nand_cramfs_offset, $r1 | ||
287 | move.d $r9, [$r1] | ||
288 | moveq 1, $r0 | 267 | moveq 1, $r0 |
289 | move.d romfs_in_flash, $r1 | 268 | move.d nand_boot, $r1 ; tell axisflashmap we're booting from NAND |
269 | move.d $r0, [$r1] | ||
270 | moveq 0, $r0 ; tell axisflashmap romfs is not in | ||
271 | move.d romfs_in_flash, $r1 ; (directly accessed) flash | ||
290 | move.d $r0, [$r1] | 272 | move.d $r0, [$r1] |
291 | jump _start_it | 273 | jump _start_it ; continue with boot |
292 | nop | 274 | nop |
293 | 275 | ||
294 | move_cramfs: | 276 | move_cramfs: |
295 | ;; Move the cramfs after BSS. | 277 | ;; kernel is in DRAM. |
278 | ;; Must figure out if there is a piggybacked rootfs image or not. | ||
279 | ;; Set romfs_length to 0 => no rootfs image available by default. | ||
296 | moveq 0, $r0 | 280 | moveq 0, $r0 |
297 | move.d romfs_length, $r1 | 281 | move.d romfs_length, $r1 |
298 | move.d $r0, [$r1] | 282 | move.d $r0, [$r1] |
299 | 283 | ||
300 | #ifndef CONFIG_ETRAXFS_SIM | 284 | #ifndef CONFIG_ETRAX_VCS_SIM |
301 | ;; The kernel could have been unpacked to DRAM by the loader, but | 285 | ;; The kernel could have been unpacked to DRAM by the loader, but |
302 | ;; the cramfs image could still be inte the flash immediately | 286 | ;; the cramfs image could still be in the flash immediately |
303 | ;; following the compressed kernel image. The loaded passes the address | 287 | ;; following the compressed kernel image. The loader passes the address |
304 | ;; of the bute succeeding the last compressed byte in the flash in | 288 | ;; of the byte succeeding the last compressed byte in the flash in |
305 | ;; register R9 when starting the kernel. | 289 | ;; register R9 when starting the kernel. |
306 | cmp.d 0x0ffffff8, $r9 | 290 | cmp.d 0x0ffffff8, $r9 |
307 | bhs _no_romfs_in_flash ; R9 points outside the flash area. | 291 | bhs _no_romfs_in_flash ; R9 points outside the flash area. |
@@ -310,11 +294,13 @@ move_cramfs: | |||
310 | ba _no_romfs_in_flash | 294 | ba _no_romfs_in_flash |
311 | nop | 295 | nop |
312 | #endif | 296 | #endif |
297 | ;; cramfs rootfs might to be in flash. Check for it. | ||
313 | move.d [$r9], $r0 ; cramfs_super.magic | 298 | move.d [$r9], $r0 ; cramfs_super.magic |
314 | cmp.d CRAMFS_MAGIC, $r0 | 299 | cmp.d CRAMFS_MAGIC, $r0 |
315 | bne _no_romfs_in_flash | 300 | bne _no_romfs_in_flash |
316 | nop | 301 | nop |
317 | 302 | ||
303 | ;; found cramfs in flash. set address and size, and romfs_in_flash flag. | ||
318 | addoq +4, $r9, $acr | 304 | addoq +4, $r9, $acr |
319 | move.d [$acr], $r0 | 305 | move.d [$acr], $r0 |
320 | move.d romfs_length, $r1 | 306 | move.d romfs_length, $r1 |
@@ -330,27 +316,43 @@ move_cramfs: | |||
330 | nop | 316 | nop |
331 | 317 | ||
332 | _no_romfs_in_flash: | 318 | _no_romfs_in_flash: |
333 | ;; Look for cramfs. | 319 | ;; No romfs in flash, so look for cramfs, or jffs2 with jhead, |
320 | ;; after kernel in RAM, as is the case with network->RAM boot. | ||
321 | ;; For cramfs, partition starts with magic and length. | ||
322 | ;; For jffs2, a jhead is prepended which contains with magic and length. | ||
323 | ;; The jhead is not part of the jffs2 partition however. | ||
334 | #ifndef CONFIG_ETRAXFS_SIM | 324 | #ifndef CONFIG_ETRAXFS_SIM |
335 | move.d __vmlinux_end, $r0 | 325 | move.d __vmlinux_end, $r0 |
336 | #else | 326 | #else |
337 | move.d __end, $r0 | 327 | move.d __end, $r0 |
338 | #endif | 328 | #endif |
339 | move.d [$r0], $r1 | 329 | move.d [$r0], $r1 |
340 | cmp.d CRAMFS_MAGIC, $r1 | 330 | cmp.d CRAMFS_MAGIC, $r1 ; cramfs magic? |
341 | bne 2f | 331 | beq 2f ; yes, jump |
332 | nop | ||
333 | cmp.d JHEAD_MAGIC, $r1 ; jffs2 (jhead) magic? | ||
334 | bne 4f ; no, skip copy | ||
342 | nop | 335 | nop |
336 | addq 4, $r0 ; location of jffs2 size | ||
337 | move.d [$r0+], $r2 ; fetch jffs2 size -> r2 | ||
338 | ; r0 now points to start of jffs2 | ||
339 | ba 3f | ||
340 | nop | ||
341 | 2: | ||
342 | addoq +4, $r0, $acr ; location of cramfs size | ||
343 | move.d [$acr], $r2 ; fetch cramfs size -> r2 | ||
344 | ; r0 still points to start of cramfs | ||
345 | 3: | ||
346 | ;; Now, move the root fs to after kernel's BSS | ||
343 | 347 | ||
344 | addoq +4, $r0, $acr | 348 | move.d _end, $r1 ; start of cramfs -> r1 |
345 | move.d [$acr], $r2 | ||
346 | move.d _end, $r1 | ||
347 | move.d romfs_start, $r3 | 349 | move.d romfs_start, $r3 |
348 | move.d $r1, [$r3] | 350 | move.d $r1, [$r3] ; store at romfs_start (for axisflashmap) |
349 | move.d romfs_length, $r3 | 351 | move.d romfs_length, $r3 |
350 | move.d $r2, [$r3] | 352 | move.d $r2, [$r3] ; store size at romfs_length |
351 | 353 | ||
352 | #ifndef CONFIG_ETRAXFS_SIM | 354 | #ifndef CONFIG_ETRAX_VCS_SIM |
353 | add.d $r2, $r0 | 355 | add.d $r2, $r0 ; copy from end and downwards |
354 | add.d $r2, $r1 | 356 | add.d $r2, $r1 |
355 | 357 | ||
356 | lsrq 1, $r2 ; Size is in bytes, we copy words. | 358 | lsrq 1, $r2 ; Size is in bytes, we copy words. |
@@ -365,10 +367,17 @@ _no_romfs_in_flash: | |||
365 | nop | 367 | nop |
366 | #endif | 368 | #endif |
367 | 369 | ||
368 | 2: | 370 | 4: |
371 | ;; BSS move done. | ||
372 | ;; Clear romfs_in_flash flag, as we now know romfs is in DRAM | ||
373 | ;; Also clear nand_boot flag; if we got here, we know we've not | ||
374 | ;; booted from NAND flash. | ||
369 | moveq 0, $r0 | 375 | moveq 0, $r0 |
370 | move.d romfs_in_flash, $r1 | 376 | move.d romfs_in_flash, $r1 |
371 | move.d $r0, [$r1] | 377 | move.d $r0, [$r1] |
378 | moveq 0, $r0 | ||
379 | move.d nand_boot, $r1 | ||
380 | move.d $r0, [$r1] | ||
372 | 381 | ||
373 | jump _start_it ; Jump to cached code. | 382 | jump _start_it ; Jump to cached code. |
374 | nop | 383 | nop |
@@ -384,8 +393,8 @@ _start_it: | |||
384 | move.d cris_command_line, $r10 | 393 | move.d cris_command_line, $r10 |
385 | or.d 0x80000000, $r11 ; Make it virtual | 394 | or.d 0x80000000, $r11 ; Make it virtual |
386 | 1: | 395 | 1: |
387 | move.b [$r11+], $r12 | 396 | move.b [$r11+], $r1 |
388 | move.b $r12, [$r10+] | 397 | move.b $r1, [$r10+] |
389 | subq 1, $r13 | 398 | subq 1, $r13 |
390 | bne 1b | 399 | bne 1b |
391 | nop | 400 | nop |
@@ -401,7 +410,7 @@ no_command_line: | |||
401 | move.d etrax_irv, $r1 ; Set the exception base register and pointer. | 410 | move.d etrax_irv, $r1 ; Set the exception base register and pointer. |
402 | move.d $r0, [$r1] | 411 | move.d $r0, [$r1] |
403 | 412 | ||
404 | #ifndef CONFIG_ETRAXFS_SIM | 413 | #ifndef CONFIG_ETRAX_VCS_SIM |
405 | ;; Clear the BSS region from _bss_start to _end. | 414 | ;; Clear the BSS region from _bss_start to _end. |
406 | move.d __bss_start, $r0 | 415 | move.d __bss_start, $r0 |
407 | move.d _end, $r1 | 416 | move.d _end, $r1 |
@@ -411,7 +420,7 @@ no_command_line: | |||
411 | nop | 420 | nop |
412 | #endif | 421 | #endif |
413 | 422 | ||
414 | #ifdef CONFIG_ETRAXFS_SIM | 423 | #ifdef CONFIG_ETRAX_VCS_SIM |
415 | /* Set the watchdog timeout to something big. Will be removed when */ | 424 | /* Set the watchdog timeout to something big. Will be removed when */ |
416 | /* watchdog can be disabled with command line option */ | 425 | /* watchdog can be disabled with command line option */ |
417 | move.d 0x7fffffff, $r10 | 426 | move.d 0x7fffffff, $r10 |
@@ -423,25 +432,44 @@ no_command_line: | |||
423 | move.d __bss_start, $r0 | 432 | move.d __bss_start, $r0 |
424 | movem [$r0], $r13 | 433 | movem [$r0], $r13 |
425 | 434 | ||
435 | #ifdef CONFIG_ETRAX_L2CACHE | ||
436 | jsr l2cache_init | ||
437 | nop | ||
438 | #endif | ||
439 | |||
426 | jump start_kernel ; Jump to start_kernel() in init/main.c. | 440 | jump start_kernel ; Jump to start_kernel() in init/main.c. |
427 | nop | 441 | nop |
428 | 442 | ||
429 | .data | 443 | .data |
430 | etrax_irv: | 444 | etrax_irv: |
431 | .dword 0 | 445 | .dword 0 |
446 | |||
447 | ; Variables for communication with the Axis flash map driver (axisflashmap), | ||
448 | ; and for setting up memory in arch/cris/kernel/setup.c . | ||
449 | |||
450 | ; romfs_start is set to the start of the root file system, if it exists | ||
451 | ; in directly accessible memory (i.e. NOR Flash when booting from Flash, | ||
452 | ; or RAM when booting directly from a network-downloaded RAM image) | ||
432 | romfs_start: | 453 | romfs_start: |
433 | .dword 0 | 454 | .dword 0 |
455 | |||
456 | ; romfs_length is set to the size of the root file system image, if it exists | ||
457 | ; in directly accessible memory (see romfs_start). Otherwise it is set to 0. | ||
434 | romfs_length: | 458 | romfs_length: |
435 | .dword 0 | 459 | .dword 0 |
460 | |||
461 | ; romfs_in_flash is set to 1 if the root file system resides in directly | ||
462 | ; accessible flash memory (i.e. NOR flash). It is set to 0 for RAM boot | ||
463 | ; or NAND flash boot. | ||
436 | romfs_in_flash: | 464 | romfs_in_flash: |
437 | .dword 0 | 465 | .dword 0 |
438 | crisv32_nand_boot: | 466 | |
439 | .dword 0 | 467 | ; nand_boot is set to 1 when the kernel has been booted from NAND flash |
440 | crisv32_nand_cramfs_offset: | 468 | nand_boot: |
441 | .dword 0 | 469 | .dword 0 |
442 | 470 | ||
443 | swapper_pg_dir = 0xc0002000 | 471 | swapper_pg_dir = 0xc0002000 |
444 | 472 | ||
445 | .section ".init.data", "aw" | 473 | .section ".init.data", "aw" |
446 | 474 | ||
447 | #include "../lib/hw_settings.S" | 475 | #include "../mach/hw_settings.S" |
diff --git a/arch/cris/arch-v32/kernel/io.c b/arch/cris/arch-v32/kernel/io.c deleted file mode 100644 index a22a9e02e093..000000000000 --- a/arch/cris/arch-v32/kernel/io.c +++ /dev/null | |||
@@ -1,153 +0,0 @@ | |||
1 | /* | ||
2 | * Helper functions for I/O pins. | ||
3 | * | ||
4 | * Copyright (c) 2004 Axis Communications AB. | ||
5 | */ | ||
6 | |||
7 | #include <linux/types.h> | ||
8 | #include <linux/errno.h> | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/string.h> | ||
11 | #include <linux/ctype.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <asm/io.h> | ||
15 | #include <asm/arch/pinmux.h> | ||
16 | #include <asm/arch/hwregs/gio_defs.h> | ||
17 | |||
18 | struct crisv32_ioport crisv32_ioports[] = | ||
19 | { | ||
20 | { | ||
21 | (unsigned long*)REG_ADDR(gio, regi_gio, rw_pa_oe), | ||
22 | (unsigned long*)REG_ADDR(gio, regi_gio, rw_pa_dout), | ||
23 | (unsigned long*)REG_ADDR(gio, regi_gio, r_pa_din), | ||
24 | 8 | ||
25 | }, | ||
26 | { | ||
27 | (unsigned long*)REG_ADDR(gio, regi_gio, rw_pb_oe), | ||
28 | (unsigned long*)REG_ADDR(gio, regi_gio, rw_pb_dout), | ||
29 | (unsigned long*)REG_ADDR(gio, regi_gio, r_pb_din), | ||
30 | 18 | ||
31 | }, | ||
32 | { | ||
33 | (unsigned long*)REG_ADDR(gio, regi_gio, rw_pc_oe), | ||
34 | (unsigned long*)REG_ADDR(gio, regi_gio, rw_pc_dout), | ||
35 | (unsigned long*)REG_ADDR(gio, regi_gio, r_pc_din), | ||
36 | 18 | ||
37 | }, | ||
38 | { | ||
39 | (unsigned long*)REG_ADDR(gio, regi_gio, rw_pd_oe), | ||
40 | (unsigned long*)REG_ADDR(gio, regi_gio, rw_pd_dout), | ||
41 | (unsigned long*)REG_ADDR(gio, regi_gio, r_pd_din), | ||
42 | 18 | ||
43 | }, | ||
44 | { | ||
45 | (unsigned long*)REG_ADDR(gio, regi_gio, rw_pe_oe), | ||
46 | (unsigned long*)REG_ADDR(gio, regi_gio, rw_pe_dout), | ||
47 | (unsigned long*)REG_ADDR(gio, regi_gio, r_pe_din), | ||
48 | 18 | ||
49 | } | ||
50 | }; | ||
51 | |||
52 | #define NBR_OF_PORTS ARRAY_SIZE(crisv32_ioports) | ||
53 | |||
54 | struct crisv32_iopin crisv32_led1_green; | ||
55 | struct crisv32_iopin crisv32_led1_red; | ||
56 | struct crisv32_iopin crisv32_led2_green; | ||
57 | struct crisv32_iopin crisv32_led2_red; | ||
58 | struct crisv32_iopin crisv32_led3_green; | ||
59 | struct crisv32_iopin crisv32_led3_red; | ||
60 | |||
61 | /* Dummy port used when green LED and red LED is on the same bit */ | ||
62 | static unsigned long io_dummy; | ||
63 | static struct crisv32_ioport dummy_port = | ||
64 | { | ||
65 | &io_dummy, | ||
66 | &io_dummy, | ||
67 | &io_dummy, | ||
68 | 18 | ||
69 | }; | ||
70 | static struct crisv32_iopin dummy_led = | ||
71 | { | ||
72 | &dummy_port, | ||
73 | 0 | ||
74 | }; | ||
75 | |||
76 | static int __init crisv32_io_init(void) | ||
77 | { | ||
78 | int ret = 0; | ||
79 | /* Initialize LEDs */ | ||
80 | ret += crisv32_io_get_name(&crisv32_led1_green, CONFIG_ETRAX_LED1G); | ||
81 | ret += crisv32_io_get_name(&crisv32_led1_red, CONFIG_ETRAX_LED1R); | ||
82 | ret += crisv32_io_get_name(&crisv32_led2_green, CONFIG_ETRAX_LED2G); | ||
83 | ret += crisv32_io_get_name(&crisv32_led2_red, CONFIG_ETRAX_LED2R); | ||
84 | ret += crisv32_io_get_name(&crisv32_led3_green, CONFIG_ETRAX_LED3G); | ||
85 | ret += crisv32_io_get_name(&crisv32_led3_red, CONFIG_ETRAX_LED3R); | ||
86 | crisv32_io_set_dir(&crisv32_led1_green, crisv32_io_dir_out); | ||
87 | crisv32_io_set_dir(&crisv32_led1_red, crisv32_io_dir_out); | ||
88 | crisv32_io_set_dir(&crisv32_led2_green, crisv32_io_dir_out); | ||
89 | crisv32_io_set_dir(&crisv32_led2_red, crisv32_io_dir_out); | ||
90 | crisv32_io_set_dir(&crisv32_led3_green, crisv32_io_dir_out); | ||
91 | crisv32_io_set_dir(&crisv32_led3_red, crisv32_io_dir_out); | ||
92 | |||
93 | if (!strcmp(CONFIG_ETRAX_LED1G, CONFIG_ETRAX_LED1R)) | ||
94 | crisv32_led1_red = dummy_led; | ||
95 | if (!strcmp(CONFIG_ETRAX_LED2G, CONFIG_ETRAX_LED2R)) | ||
96 | crisv32_led2_red = dummy_led; | ||
97 | |||
98 | return ret; | ||
99 | } | ||
100 | |||
101 | __initcall(crisv32_io_init); | ||
102 | |||
103 | int crisv32_io_get(struct crisv32_iopin* iopin, | ||
104 | unsigned int port, unsigned int pin) | ||
105 | { | ||
106 | if (port > NBR_OF_PORTS) | ||
107 | return -EINVAL; | ||
108 | if (port > crisv32_ioports[port].pin_count) | ||
109 | return -EINVAL; | ||
110 | |||
111 | iopin->bit = 1 << pin; | ||
112 | iopin->port = &crisv32_ioports[port]; | ||
113 | |||
114 | if (crisv32_pinmux_alloc(port, pin, pin, pinmux_gpio)) | ||
115 | return -EIO; | ||
116 | |||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | int crisv32_io_get_name(struct crisv32_iopin* iopin, | ||
121 | char* name) | ||
122 | { | ||
123 | int port; | ||
124 | int pin; | ||
125 | |||
126 | if (toupper(*name) == 'P') | ||
127 | name++; | ||
128 | |||
129 | if (toupper(*name) < 'A' || toupper(*name) > 'E') | ||
130 | return -EINVAL; | ||
131 | |||
132 | port = toupper(*name) - 'A'; | ||
133 | name++; | ||
134 | pin = simple_strtoul(name, NULL, 10); | ||
135 | |||
136 | if (pin < 0 || pin > crisv32_ioports[port].pin_count) | ||
137 | return -EINVAL; | ||
138 | |||
139 | iopin->bit = 1 << pin; | ||
140 | iopin->port = &crisv32_ioports[port]; | ||
141 | |||
142 | if (crisv32_pinmux_alloc(port, pin, pin, pinmux_gpio)) | ||
143 | return -EIO; | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | #ifdef CONFIG_PCI | ||
149 | /* PCI I/O access stuff */ | ||
150 | struct cris_io_operations* cris_iops = NULL; | ||
151 | EXPORT_SYMBOL(cris_iops); | ||
152 | #endif | ||
153 | |||
diff --git a/arch/cris/arch-v32/kernel/irq.c b/arch/cris/arch-v32/kernel/irq.c index a9acaa270243..173c141ac9ba 100644 --- a/arch/cris/arch-v32/kernel/irq.c +++ b/arch/cris/arch-v32/kernel/irq.c | |||
@@ -15,15 +15,21 @@ | |||
15 | #include <linux/threads.h> | 15 | #include <linux/threads.h> |
16 | #include <linux/spinlock.h> | 16 | #include <linux/spinlock.h> |
17 | #include <linux/kernel_stat.h> | 17 | #include <linux/kernel_stat.h> |
18 | #include <asm/arch/hwregs/reg_map.h> | 18 | #include <hwregs/reg_map.h> |
19 | #include <asm/arch/hwregs/reg_rdwr.h> | 19 | #include <hwregs/reg_rdwr.h> |
20 | #include <asm/arch/hwregs/intr_vect.h> | 20 | #include <hwregs/intr_vect.h> |
21 | #include <asm/arch/hwregs/intr_vect_defs.h> | 21 | #include <hwregs/intr_vect_defs.h> |
22 | 22 | ||
23 | #define CPU_FIXED -1 | 23 | #define CPU_FIXED -1 |
24 | 24 | ||
25 | /* IRQ masks (refer to comment for crisv32_do_multiple) */ | 25 | /* IRQ masks (refer to comment for crisv32_do_multiple) */ |
26 | #define TIMER_MASK (1 << (TIMER_INTR_VECT - FIRST_IRQ)) | 26 | #if TIMER0_INTR_VECT - FIRST_IRQ < 32 |
27 | #define TIMER_MASK (1 << (TIMER0_INTR_VECT - FIRST_IRQ)) | ||
28 | #undef TIMER_VECT1 | ||
29 | #else | ||
30 | #define TIMER_MASK (1 << (TIMER0_INTR_VECT - FIRST_IRQ - 32)) | ||
31 | #define TIMER_VECT1 | ||
32 | #endif | ||
27 | #ifdef CONFIG_ETRAX_KGDB | 33 | #ifdef CONFIG_ETRAX_KGDB |
28 | #if defined(CONFIG_ETRAX_KGDB_PORT0) | 34 | #if defined(CONFIG_ETRAX_KGDB_PORT0) |
29 | #define IGNOREMASK (1 << (SER0_INTR_VECT - FIRST_IRQ)) | 35 | #define IGNOREMASK (1 << (SER0_INTR_VECT - FIRST_IRQ)) |
@@ -44,8 +50,8 @@ struct cris_irq_allocation | |||
44 | cpumask_t mask; /* The CPUs to which the IRQ may be allocated. */ | 50 | cpumask_t mask; /* The CPUs to which the IRQ may be allocated. */ |
45 | }; | 51 | }; |
46 | 52 | ||
47 | struct cris_irq_allocation irq_allocations[NR_IRQS] = | 53 | struct cris_irq_allocation irq_allocations[NR_REAL_IRQS] = |
48 | {[0 ... NR_IRQS - 1] = {0, CPU_MASK_ALL}}; | 54 | { [0 ... NR_REAL_IRQS - 1] = {0, CPU_MASK_ALL} }; |
49 | 55 | ||
50 | static unsigned long irq_regs[NR_CPUS] = | 56 | static unsigned long irq_regs[NR_CPUS] = |
51 | { | 57 | { |
@@ -55,6 +61,12 @@ static unsigned long irq_regs[NR_CPUS] = | |||
55 | #endif | 61 | #endif |
56 | }; | 62 | }; |
57 | 63 | ||
64 | #if NR_REAL_IRQS > 32 | ||
65 | #define NBR_REGS 2 | ||
66 | #else | ||
67 | #define NBR_REGS 1 | ||
68 | #endif | ||
69 | |||
58 | unsigned long cpu_irq_counters[NR_CPUS]; | 70 | unsigned long cpu_irq_counters[NR_CPUS]; |
59 | unsigned long irq_counters[NR_REAL_IRQS]; | 71 | unsigned long irq_counters[NR_REAL_IRQS]; |
60 | 72 | ||
@@ -79,45 +91,81 @@ extern void d_mmu_write(void); | |||
79 | extern void kgdb_init(void); | 91 | extern void kgdb_init(void); |
80 | extern void breakpoint(void); | 92 | extern void breakpoint(void); |
81 | 93 | ||
94 | /* From traps.c. */ | ||
95 | extern void breakh_BUG(void); | ||
96 | |||
82 | /* | 97 | /* |
83 | * Build the IRQ handler stubs using macros from irq.h. First argument is the | 98 | * Build the IRQ handler stubs using macros from irq.h. |
84 | * IRQ number, the second argument is the corresponding bit in | ||
85 | * intr_rw_vect_mask found in asm/arch/hwregs/intr_vect_defs.h. | ||
86 | */ | 99 | */ |
87 | BUILD_IRQ(0x31, (1 << 0)) /* memarb */ | 100 | BUILD_IRQ(0x31) |
88 | BUILD_IRQ(0x32, (1 << 1)) /* gen_io */ | 101 | BUILD_IRQ(0x32) |
89 | BUILD_IRQ(0x33, (1 << 2)) /* iop0 */ | 102 | BUILD_IRQ(0x33) |
90 | BUILD_IRQ(0x34, (1 << 3)) /* iop1 */ | 103 | BUILD_IRQ(0x34) |
91 | BUILD_IRQ(0x35, (1 << 4)) /* iop2 */ | 104 | BUILD_IRQ(0x35) |
92 | BUILD_IRQ(0x36, (1 << 5)) /* iop3 */ | 105 | BUILD_IRQ(0x36) |
93 | BUILD_IRQ(0x37, (1 << 6)) /* dma0 */ | 106 | BUILD_IRQ(0x37) |
94 | BUILD_IRQ(0x38, (1 << 7)) /* dma1 */ | 107 | BUILD_IRQ(0x38) |
95 | BUILD_IRQ(0x39, (1 << 8)) /* dma2 */ | 108 | BUILD_IRQ(0x39) |
96 | BUILD_IRQ(0x3a, (1 << 9)) /* dma3 */ | 109 | BUILD_IRQ(0x3a) |
97 | BUILD_IRQ(0x3b, (1 << 10)) /* dma4 */ | 110 | BUILD_IRQ(0x3b) |
98 | BUILD_IRQ(0x3c, (1 << 11)) /* dma5 */ | 111 | BUILD_IRQ(0x3c) |
99 | BUILD_IRQ(0x3d, (1 << 12)) /* dma6 */ | 112 | BUILD_IRQ(0x3d) |
100 | BUILD_IRQ(0x3e, (1 << 13)) /* dma7 */ | 113 | BUILD_IRQ(0x3e) |
101 | BUILD_IRQ(0x3f, (1 << 14)) /* dma8 */ | 114 | BUILD_IRQ(0x3f) |
102 | BUILD_IRQ(0x40, (1 << 15)) /* dma9 */ | 115 | BUILD_IRQ(0x40) |
103 | BUILD_IRQ(0x41, (1 << 16)) /* ata */ | 116 | BUILD_IRQ(0x41) |
104 | BUILD_IRQ(0x42, (1 << 17)) /* sser0 */ | 117 | BUILD_IRQ(0x42) |
105 | BUILD_IRQ(0x43, (1 << 18)) /* sser1 */ | 118 | BUILD_IRQ(0x43) |
106 | BUILD_IRQ(0x44, (1 << 19)) /* ser0 */ | 119 | BUILD_IRQ(0x44) |
107 | BUILD_IRQ(0x45, (1 << 20)) /* ser1 */ | 120 | BUILD_IRQ(0x45) |
108 | BUILD_IRQ(0x46, (1 << 21)) /* ser2 */ | 121 | BUILD_IRQ(0x46) |
109 | BUILD_IRQ(0x47, (1 << 22)) /* ser3 */ | 122 | BUILD_IRQ(0x47) |
110 | BUILD_IRQ(0x48, (1 << 23)) | 123 | BUILD_IRQ(0x48) |
111 | BUILD_IRQ(0x49, (1 << 24)) /* eth0 */ | 124 | BUILD_IRQ(0x49) |
112 | BUILD_IRQ(0x4a, (1 << 25)) /* eth1 */ | 125 | BUILD_IRQ(0x4a) |
113 | BUILD_TIMER_IRQ(0x4b, (1 << 26))/* timer */ | 126 | BUILD_IRQ(0x4b) |
114 | BUILD_IRQ(0x4c, (1 << 27)) /* bif_arb */ | 127 | BUILD_IRQ(0x4c) |
115 | BUILD_IRQ(0x4d, (1 << 28)) /* bif_dma */ | 128 | BUILD_IRQ(0x4d) |
116 | BUILD_IRQ(0x4e, (1 << 29)) /* ext */ | 129 | BUILD_IRQ(0x4e) |
117 | BUILD_IRQ(0x4f, (1 << 29)) /* ipi */ | 130 | BUILD_IRQ(0x4f) |
131 | BUILD_IRQ(0x50) | ||
132 | #if MACH_IRQS > 32 | ||
133 | BUILD_IRQ(0x51) | ||
134 | BUILD_IRQ(0x52) | ||
135 | BUILD_IRQ(0x53) | ||
136 | BUILD_IRQ(0x54) | ||
137 | BUILD_IRQ(0x55) | ||
138 | BUILD_IRQ(0x56) | ||
139 | BUILD_IRQ(0x57) | ||
140 | BUILD_IRQ(0x58) | ||
141 | BUILD_IRQ(0x59) | ||
142 | BUILD_IRQ(0x5a) | ||
143 | BUILD_IRQ(0x5b) | ||
144 | BUILD_IRQ(0x5c) | ||
145 | BUILD_IRQ(0x5d) | ||
146 | BUILD_IRQ(0x5e) | ||
147 | BUILD_IRQ(0x5f) | ||
148 | BUILD_IRQ(0x60) | ||
149 | BUILD_IRQ(0x61) | ||
150 | BUILD_IRQ(0x62) | ||
151 | BUILD_IRQ(0x63) | ||
152 | BUILD_IRQ(0x64) | ||
153 | BUILD_IRQ(0x65) | ||
154 | BUILD_IRQ(0x66) | ||
155 | BUILD_IRQ(0x67) | ||
156 | BUILD_IRQ(0x68) | ||
157 | BUILD_IRQ(0x69) | ||
158 | BUILD_IRQ(0x6a) | ||
159 | BUILD_IRQ(0x6b) | ||
160 | BUILD_IRQ(0x6c) | ||
161 | BUILD_IRQ(0x6d) | ||
162 | BUILD_IRQ(0x6e) | ||
163 | BUILD_IRQ(0x6f) | ||
164 | BUILD_IRQ(0x70) | ||
165 | #endif | ||
118 | 166 | ||
119 | /* Pointers to the low-level handlers. */ | 167 | /* Pointers to the low-level handlers. */ |
120 | static void (*interrupt[NR_IRQS])(void) = { | 168 | static void (*interrupt[MACH_IRQS])(void) = { |
121 | IRQ0x31_interrupt, IRQ0x32_interrupt, IRQ0x33_interrupt, | 169 | IRQ0x31_interrupt, IRQ0x32_interrupt, IRQ0x33_interrupt, |
122 | IRQ0x34_interrupt, IRQ0x35_interrupt, IRQ0x36_interrupt, | 170 | IRQ0x34_interrupt, IRQ0x35_interrupt, IRQ0x36_interrupt, |
123 | IRQ0x37_interrupt, IRQ0x38_interrupt, IRQ0x39_interrupt, | 171 | IRQ0x37_interrupt, IRQ0x38_interrupt, IRQ0x39_interrupt, |
@@ -128,7 +176,20 @@ static void (*interrupt[NR_IRQS])(void) = { | |||
128 | IRQ0x46_interrupt, IRQ0x47_interrupt, IRQ0x48_interrupt, | 176 | IRQ0x46_interrupt, IRQ0x47_interrupt, IRQ0x48_interrupt, |
129 | IRQ0x49_interrupt, IRQ0x4a_interrupt, IRQ0x4b_interrupt, | 177 | IRQ0x49_interrupt, IRQ0x4a_interrupt, IRQ0x4b_interrupt, |
130 | IRQ0x4c_interrupt, IRQ0x4d_interrupt, IRQ0x4e_interrupt, | 178 | IRQ0x4c_interrupt, IRQ0x4d_interrupt, IRQ0x4e_interrupt, |
131 | IRQ0x4f_interrupt | 179 | IRQ0x4f_interrupt, IRQ0x50_interrupt, |
180 | #if MACH_IRQS > 32 | ||
181 | IRQ0x51_interrupt, IRQ0x52_interrupt, IRQ0x53_interrupt, | ||
182 | IRQ0x54_interrupt, IRQ0x55_interrupt, IRQ0x56_interrupt, | ||
183 | IRQ0x57_interrupt, IRQ0x58_interrupt, IRQ0x59_interrupt, | ||
184 | IRQ0x5a_interrupt, IRQ0x5b_interrupt, IRQ0x5c_interrupt, | ||
185 | IRQ0x5d_interrupt, IRQ0x5e_interrupt, IRQ0x5f_interrupt, | ||
186 | IRQ0x60_interrupt, IRQ0x61_interrupt, IRQ0x62_interrupt, | ||
187 | IRQ0x63_interrupt, IRQ0x64_interrupt, IRQ0x65_interrupt, | ||
188 | IRQ0x66_interrupt, IRQ0x67_interrupt, IRQ0x68_interrupt, | ||
189 | IRQ0x69_interrupt, IRQ0x6a_interrupt, IRQ0x6b_interrupt, | ||
190 | IRQ0x6c_interrupt, IRQ0x6d_interrupt, IRQ0x6e_interrupt, | ||
191 | IRQ0x6f_interrupt, IRQ0x70_interrupt, | ||
192 | #endif | ||
132 | }; | 193 | }; |
133 | 194 | ||
134 | void | 195 | void |
@@ -137,13 +198,26 @@ block_irq(int irq, int cpu) | |||
137 | int intr_mask; | 198 | int intr_mask; |
138 | unsigned long flags; | 199 | unsigned long flags; |
139 | 200 | ||
140 | spin_lock_irqsave(&irq_lock, flags); | 201 | spin_lock_irqsave(&irq_lock, flags); |
141 | intr_mask = REG_RD_INT(intr_vect, irq_regs[cpu], rw_mask); | 202 | if (irq - FIRST_IRQ < 32) |
142 | 203 | intr_mask = REG_RD_INT_VECT(intr_vect, irq_regs[cpu], | |
143 | /* Remember; 1 let through, 0 block. */ | 204 | rw_mask, 0); |
144 | intr_mask &= ~(1 << (irq - FIRST_IRQ)); | 205 | else |
145 | 206 | intr_mask = REG_RD_INT_VECT(intr_vect, irq_regs[cpu], | |
146 | REG_WR_INT(intr_vect, irq_regs[cpu], rw_mask, intr_mask); | 207 | rw_mask, 1); |
208 | |||
209 | /* Remember; 1 let thru, 0 block. */ | ||
210 | if (irq - FIRST_IRQ < 32) | ||
211 | intr_mask &= ~(1 << (irq - FIRST_IRQ)); | ||
212 | else | ||
213 | intr_mask &= ~(1 << (irq - FIRST_IRQ - 32)); | ||
214 | |||
215 | if (irq - FIRST_IRQ < 32) | ||
216 | REG_WR_INT_VECT(intr_vect, irq_regs[cpu], rw_mask, | ||
217 | 0, intr_mask); | ||
218 | else | ||
219 | REG_WR_INT_VECT(intr_vect, irq_regs[cpu], rw_mask, | ||
220 | 1, intr_mask); | ||
147 | spin_unlock_irqrestore(&irq_lock, flags); | 221 | spin_unlock_irqrestore(&irq_lock, flags); |
148 | } | 222 | } |
149 | 223 | ||
@@ -154,12 +228,26 @@ unblock_irq(int irq, int cpu) | |||
154 | unsigned long flags; | 228 | unsigned long flags; |
155 | 229 | ||
156 | spin_lock_irqsave(&irq_lock, flags); | 230 | spin_lock_irqsave(&irq_lock, flags); |
157 | intr_mask = REG_RD_INT(intr_vect, irq_regs[cpu], rw_mask); | 231 | if (irq - FIRST_IRQ < 32) |
158 | 232 | intr_mask = REG_RD_INT_VECT(intr_vect, irq_regs[cpu], | |
159 | /* Remember; 1 let through, 0 block. */ | 233 | rw_mask, 0); |
160 | intr_mask |= (1 << (irq - FIRST_IRQ)); | 234 | else |
235 | intr_mask = REG_RD_INT_VECT(intr_vect, irq_regs[cpu], | ||
236 | rw_mask, 1); | ||
237 | |||
238 | /* Remember; 1 let thru, 0 block. */ | ||
239 | if (irq - FIRST_IRQ < 32) | ||
240 | intr_mask |= (1 << (irq - FIRST_IRQ)); | ||
241 | else | ||
242 | intr_mask |= (1 << (irq - FIRST_IRQ - 32)); | ||
243 | |||
244 | if (irq - FIRST_IRQ < 32) | ||
245 | REG_WR_INT_VECT(intr_vect, irq_regs[cpu], rw_mask, | ||
246 | 0, intr_mask); | ||
247 | else | ||
248 | REG_WR_INT_VECT(intr_vect, irq_regs[cpu], rw_mask, | ||
249 | 1, intr_mask); | ||
161 | 250 | ||
162 | REG_WR_INT(intr_vect, irq_regs[cpu], rw_mask, intr_mask); | ||
163 | spin_unlock_irqrestore(&irq_lock, flags); | 251 | spin_unlock_irqrestore(&irq_lock, flags); |
164 | } | 252 | } |
165 | 253 | ||
@@ -298,8 +386,9 @@ crisv32_do_multiple(struct pt_regs* regs) | |||
298 | { | 386 | { |
299 | int cpu; | 387 | int cpu; |
300 | int mask; | 388 | int mask; |
301 | int masked; | 389 | int masked[NBR_REGS]; |
302 | int bit; | 390 | int bit; |
391 | int i; | ||
303 | 392 | ||
304 | cpu = smp_processor_id(); | 393 | cpu = smp_processor_id(); |
305 | 394 | ||
@@ -308,42 +397,59 @@ crisv32_do_multiple(struct pt_regs* regs) | |||
308 | */ | 397 | */ |
309 | irq_enter(); | 398 | irq_enter(); |
310 | 399 | ||
311 | /* Get which IRQs that happened. */ | 400 | for (i = 0; i < NBR_REGS; i++) { |
312 | masked = REG_RD_INT(intr_vect, irq_regs[cpu], r_masked_vect); | 401 | /* Get which IRQs that happend. */ |
402 | masked[i] = REG_RD_INT_VECT(intr_vect, irq_regs[cpu], | ||
403 | r_masked_vect, i); | ||
313 | 404 | ||
314 | /* Calculate new IRQ mask with these IRQs disabled. */ | 405 | /* Calculate new IRQ mask with these IRQs disabled. */ |
315 | mask = REG_RD_INT(intr_vect, irq_regs[cpu], rw_mask); | 406 | mask = REG_RD_INT_VECT(intr_vect, irq_regs[cpu], rw_mask, i); |
316 | mask &= ~masked; | 407 | mask &= ~masked[i]; |
317 | 408 | ||
318 | /* Timer IRQ is never masked */ | 409 | /* Timer IRQ is never masked */ |
319 | if (masked & TIMER_MASK) | 410 | #ifdef TIMER_VECT1 |
320 | mask |= TIMER_MASK; | 411 | if ((i == 1) && (masked[0] & TIMER_MASK)) |
321 | 412 | mask |= TIMER_MASK; | |
322 | /* Block all the IRQs */ | 413 | #else |
323 | REG_WR_INT(intr_vect, irq_regs[cpu], rw_mask, mask); | 414 | if ((i == 0) && (masked[0] & TIMER_MASK)) |
415 | mask |= TIMER_MASK; | ||
416 | #endif | ||
417 | /* Block all the IRQs */ | ||
418 | REG_WR_INT_VECT(intr_vect, irq_regs[cpu], rw_mask, i, mask); | ||
324 | 419 | ||
325 | /* Check for timer IRQ and handle it special. */ | 420 | /* Check for timer IRQ and handle it special. */ |
326 | if (masked & TIMER_MASK) { | 421 | #ifdef TIMER_VECT1 |
327 | masked &= ~TIMER_MASK; | 422 | if ((i == 1) && (masked[i] & TIMER_MASK)) { |
328 | do_IRQ(TIMER_INTR_VECT, regs); | 423 | masked[i] &= ~TIMER_MASK; |
424 | do_IRQ(TIMER0_INTR_VECT, regs); | ||
425 | } | ||
426 | #else | ||
427 | if ((i == 0) && (masked[i] & TIMER_MASK)) { | ||
428 | masked[i] &= ~TIMER_MASK; | ||
429 | do_IRQ(TIMER0_INTR_VECT, regs); | ||
430 | } | ||
329 | } | 431 | } |
432 | #endif | ||
330 | 433 | ||
331 | #ifdef IGNORE_MASK | 434 | #ifdef IGNORE_MASK |
332 | /* Remove IRQs that can't be handled as multiple. */ | 435 | /* Remove IRQs that can't be handled as multiple. */ |
333 | masked &= ~IGNORE_MASK; | 436 | masked[0] &= ~IGNORE_MASK; |
334 | #endif | 437 | #endif |
335 | 438 | ||
336 | /* Handle the rest of the IRQs. */ | 439 | /* Handle the rest of the IRQs. */ |
337 | for (bit = 0; bit < 32; bit++) | 440 | for (i = 0; i < NBR_REGS; i++) { |
338 | { | 441 | for (bit = 0; bit < 32; bit++) { |
339 | if (masked & (1 << bit)) | 442 | if (masked[i] & (1 << bit)) |
340 | do_IRQ(bit + FIRST_IRQ, regs); | 443 | do_IRQ(bit + FIRST_IRQ + i*32, regs); |
444 | } | ||
341 | } | 445 | } |
342 | 446 | ||
343 | /* Unblock all the IRQs. */ | 447 | /* Unblock all the IRQs. */ |
344 | mask = REG_RD_INT(intr_vect, irq_regs[cpu], rw_mask); | 448 | for (i = 0; i < NBR_REGS; i++) { |
345 | mask |= masked; | 449 | mask = REG_RD_INT_VECT(intr_vect, irq_regs[cpu], rw_mask, i); |
346 | REG_WR_INT(intr_vect, irq_regs[cpu], rw_mask, mask); | 450 | mask |= masked[i]; |
451 | REG_WR_INT_VECT(intr_vect, irq_regs[cpu], rw_mask, i, mask); | ||
452 | } | ||
347 | 453 | ||
348 | /* This irq_exit() will trigger the soft IRQs. */ | 454 | /* This irq_exit() will trigger the soft IRQs. */ |
349 | irq_exit(); | 455 | irq_exit(); |
@@ -361,20 +467,21 @@ init_IRQ(void) | |||
361 | reg_intr_vect_rw_mask vect_mask = {0}; | 467 | reg_intr_vect_rw_mask vect_mask = {0}; |
362 | 468 | ||
363 | /* Clear all interrupts masks. */ | 469 | /* Clear all interrupts masks. */ |
364 | REG_WR(intr_vect, regi_irq, rw_mask, vect_mask); | 470 | for (i = 0; i < NBR_REGS; i++) |
471 | REG_WR_VECT(intr_vect, regi_irq, rw_mask, i, vect_mask); | ||
365 | 472 | ||
366 | for (i = 0; i < 256; i++) | 473 | for (i = 0; i < 256; i++) |
367 | etrax_irv->v[i] = weird_irq; | 474 | etrax_irv->v[i] = weird_irq; |
368 | 475 | ||
369 | /* Point all IRQs to bad handlers. */ | 476 | /* Point all IRQ's to bad handlers. */ |
370 | for (i = FIRST_IRQ, j = 0; j < NR_IRQS; i++, j++) { | 477 | for (i = FIRST_IRQ, j = 0; j < NR_IRQS; i++, j++) { |
371 | irq_desc[j].chip = &crisv32_irq_type; | 478 | irq_desc[j].chip = &crisv32_irq_type; |
372 | set_exception_vector(i, interrupt[j]); | 479 | set_exception_vector(i, interrupt[j]); |
373 | } | 480 | } |
374 | 481 | ||
375 | /* Mark Timer and IPI IRQs as CPU local */ | 482 | /* Mark Timer and IPI IRQs as CPU local */ |
376 | irq_allocations[TIMER_INTR_VECT - FIRST_IRQ].cpu = CPU_FIXED; | 483 | irq_allocations[TIMER0_INTR_VECT - FIRST_IRQ].cpu = CPU_FIXED; |
377 | irq_desc[TIMER_INTR_VECT].status |= IRQ_PER_CPU; | 484 | irq_desc[TIMER0_INTR_VECT].status |= IRQ_PER_CPU; |
378 | irq_allocations[IPI_INTR_VECT - FIRST_IRQ].cpu = CPU_FIXED; | 485 | irq_allocations[IPI_INTR_VECT - FIRST_IRQ].cpu = CPU_FIXED; |
379 | irq_desc[IPI_INTR_VECT].status |= IRQ_PER_CPU; | 486 | irq_desc[IPI_INTR_VECT].status |= IRQ_PER_CPU; |
380 | 487 | ||
@@ -391,6 +498,11 @@ init_IRQ(void) | |||
391 | set_exception_vector(0x0a, d_mmu_access); | 498 | set_exception_vector(0x0a, d_mmu_access); |
392 | set_exception_vector(0x0b, d_mmu_write); | 499 | set_exception_vector(0x0b, d_mmu_write); |
393 | 500 | ||
501 | #ifdef CONFIG_BUG | ||
502 | /* Break 14 handler, used to implement cheap BUG(). */ | ||
503 | set_exception_vector(0x1e, breakh_BUG); | ||
504 | #endif | ||
505 | |||
394 | /* The system-call trap is reached by "break 13". */ | 506 | /* The system-call trap is reached by "break 13". */ |
395 | set_exception_vector(0x1d, system_call); | 507 | set_exception_vector(0x1d, system_call); |
396 | 508 | ||
diff --git a/arch/cris/arch-v32/kernel/kgdb.c b/arch/cris/arch-v32/kernel/kgdb.c index 480e56348be2..4e2e2e271efb 100644 --- a/arch/cris/arch-v32/kernel/kgdb.c +++ b/arch/cris/arch-v32/kernel/kgdb.c | |||
@@ -381,7 +381,7 @@ static int read_register(char regno, unsigned int *valptr); | |||
381 | /* Serial port, reads one character. ETRAX 100 specific. from debugport.c */ | 381 | /* Serial port, reads one character. ETRAX 100 specific. from debugport.c */ |
382 | int getDebugChar(void); | 382 | int getDebugChar(void); |
383 | 383 | ||
384 | #ifdef CONFIG_ETRAXFS_SIM | 384 | #ifdef CONFIG_ETRAX_VCS_SIM |
385 | int getDebugChar(void) | 385 | int getDebugChar(void) |
386 | { | 386 | { |
387 | return socketread(); | 387 | return socketread(); |
@@ -391,7 +391,7 @@ int getDebugChar(void) | |||
391 | /* Serial port, writes one character. ETRAX 100 specific. from debugport.c */ | 391 | /* Serial port, writes one character. ETRAX 100 specific. from debugport.c */ |
392 | void putDebugChar(int val); | 392 | void putDebugChar(int val); |
393 | 393 | ||
394 | #ifdef CONFIG_ETRAXFS_SIM | 394 | #ifdef CONFIG_ETRAX_VCS_SIM |
395 | void putDebugChar(int val) | 395 | void putDebugChar(int val) |
396 | { | 396 | { |
397 | socketwrite((char *)&val, 1); | 397 | socketwrite((char *)&val, 1); |
@@ -1599,7 +1599,7 @@ kgdb_init(void) | |||
1599 | REG_WR(intr_vect, regi_irq, rw_mask, intr_mask); | 1599 | REG_WR(intr_vect, regi_irq, rw_mask, intr_mask); |
1600 | 1600 | ||
1601 | ser_intr_mask = REG_RD(ser, regi_ser0, rw_intr_mask); | 1601 | ser_intr_mask = REG_RD(ser, regi_ser0, rw_intr_mask); |
1602 | ser_intr_mask.data_avail = regk_ser_yes; | 1602 | ser_intr_mask.dav = regk_ser_yes; |
1603 | REG_WR(ser, regi_ser0, rw_intr_mask, ser_intr_mask); | 1603 | REG_WR(ser, regi_ser0, rw_intr_mask, ser_intr_mask); |
1604 | #elif defined(CONFIG_ETRAX_KGDB_PORT1) | 1604 | #elif defined(CONFIG_ETRAX_KGDB_PORT1) |
1605 | /* Note: no shortcut registered (not handled by multiple_interrupt). | 1605 | /* Note: no shortcut registered (not handled by multiple_interrupt). |
@@ -1611,7 +1611,7 @@ kgdb_init(void) | |||
1611 | REG_WR(intr_vect, regi_irq, rw_mask, intr_mask); | 1611 | REG_WR(intr_vect, regi_irq, rw_mask, intr_mask); |
1612 | 1612 | ||
1613 | ser_intr_mask = REG_RD(ser, regi_ser1, rw_intr_mask); | 1613 | ser_intr_mask = REG_RD(ser, regi_ser1, rw_intr_mask); |
1614 | ser_intr_mask.data_avail = regk_ser_yes; | 1614 | ser_intr_mask.dav = regk_ser_yes; |
1615 | REG_WR(ser, regi_ser1, rw_intr_mask, ser_intr_mask); | 1615 | REG_WR(ser, regi_ser1, rw_intr_mask, ser_intr_mask); |
1616 | #elif defined(CONFIG_ETRAX_KGDB_PORT2) | 1616 | #elif defined(CONFIG_ETRAX_KGDB_PORT2) |
1617 | /* Note: no shortcut registered (not handled by multiple_interrupt). | 1617 | /* Note: no shortcut registered (not handled by multiple_interrupt). |
@@ -1623,7 +1623,7 @@ kgdb_init(void) | |||
1623 | REG_WR(intr_vect, regi_irq, rw_mask, intr_mask); | 1623 | REG_WR(intr_vect, regi_irq, rw_mask, intr_mask); |
1624 | 1624 | ||
1625 | ser_intr_mask = REG_RD(ser, regi_ser2, rw_intr_mask); | 1625 | ser_intr_mask = REG_RD(ser, regi_ser2, rw_intr_mask); |
1626 | ser_intr_mask.data_avail = regk_ser_yes; | 1626 | ser_intr_mask.dav = regk_ser_yes; |
1627 | REG_WR(ser, regi_ser2, rw_intr_mask, ser_intr_mask); | 1627 | REG_WR(ser, regi_ser2, rw_intr_mask, ser_intr_mask); |
1628 | #elif defined(CONFIG_ETRAX_KGDB_PORT3) | 1628 | #elif defined(CONFIG_ETRAX_KGDB_PORT3) |
1629 | /* Note: no shortcut registered (not handled by multiple_interrupt). | 1629 | /* Note: no shortcut registered (not handled by multiple_interrupt). |
@@ -1635,7 +1635,7 @@ kgdb_init(void) | |||
1635 | REG_WR(intr_vect, regi_irq, rw_mask, intr_mask); | 1635 | REG_WR(intr_vect, regi_irq, rw_mask, intr_mask); |
1636 | 1636 | ||
1637 | ser_intr_mask = REG_RD(ser, regi_ser3, rw_intr_mask); | 1637 | ser_intr_mask = REG_RD(ser, regi_ser3, rw_intr_mask); |
1638 | ser_intr_mask.data_avail = regk_ser_yes; | 1638 | ser_intr_mask.dav = regk_ser_yes; |
1639 | REG_WR(ser, regi_ser3, rw_intr_mask, ser_intr_mask); | 1639 | REG_WR(ser, regi_ser3, rw_intr_mask, ser_intr_mask); |
1640 | #endif | 1640 | #endif |
1641 | 1641 | ||
diff --git a/arch/cris/arch-v32/kernel/process.c b/arch/cris/arch-v32/kernel/process.c index b72a15580dc7..ced5b725d9bd 100644 --- a/arch/cris/arch-v32/kernel/process.c +++ b/arch/cris/arch-v32/kernel/process.c | |||
@@ -12,17 +12,13 @@ | |||
12 | #include <linux/err.h> | 12 | #include <linux/err.h> |
13 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <asm/arch/hwregs/reg_rdwr.h> | 15 | #include <hwregs/reg_rdwr.h> |
16 | #include <asm/arch/hwregs/reg_map.h> | 16 | #include <hwregs/reg_map.h> |
17 | #include <asm/arch/hwregs/timer_defs.h> | 17 | #include <hwregs/timer_defs.h> |
18 | #include <asm/arch/hwregs/intr_vect_defs.h> | 18 | #include <hwregs/intr_vect_defs.h> |
19 | 19 | ||
20 | extern void stop_watchdog(void); | 20 | extern void stop_watchdog(void); |
21 | 21 | ||
22 | #ifdef CONFIG_ETRAX_GPIO | ||
23 | extern void etrax_gpio_wake_up_check(void); /* Defined in drivers/gpio.c. */ | ||
24 | #endif | ||
25 | |||
26 | extern int cris_hlt_counter; | 22 | extern int cris_hlt_counter; |
27 | 23 | ||
28 | /* We use this if we don't have any better idle routine. */ | 24 | /* We use this if we don't have any better idle routine. */ |
@@ -82,7 +78,7 @@ hard_reset_now(void) | |||
82 | wd_ctrl.cmd = regk_timer_start; | 78 | wd_ctrl.cmd = regk_timer_start; |
83 | 79 | ||
84 | arch_enable_nmi(); | 80 | arch_enable_nmi(); |
85 | REG_WR(timer, regi_timer, rw_wd_ctrl, wd_ctrl); | 81 | REG_WR(timer, regi_timer0, rw_wd_ctrl, wd_ctrl); |
86 | } | 82 | } |
87 | #endif | 83 | #endif |
88 | 84 | ||
diff --git a/arch/cris/arch-v32/kernel/ptrace.c b/arch/cris/arch-v32/kernel/ptrace.c index 2df60529a8af..e27f4670e88e 100644 --- a/arch/cris/arch-v32/kernel/ptrace.c +++ b/arch/cris/arch-v32/kernel/ptrace.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2000-2003, Axis Communications AB. | 2 | * Copyright (C) 2000-2007, Axis Communications AB. |
3 | */ | 3 | */ |
4 | 4 | ||
5 | #include <linux/kernel.h> | 5 | #include <linux/kernel.h> |
@@ -149,7 +149,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
149 | ret = generic_ptrace_pokedata(child, addr, data); | 149 | ret = generic_ptrace_pokedata(child, addr, data); |
150 | break; | 150 | break; |
151 | 151 | ||
152 | /* Write the word at location address in the USER area. */ | 152 | /* Write the word at location address in the USER area. */ |
153 | case PTRACE_POKEUSR: | 153 | case PTRACE_POKEUSR: |
154 | ret = -EIO; | 154 | ret = -EIO; |
155 | if ((addr & 3) || addr < 0 || addr > PT_MAX << 2) | 155 | if ((addr & 3) || addr < 0 || addr > PT_MAX << 2) |
@@ -201,7 +201,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
201 | 201 | ||
202 | break; | 202 | break; |
203 | 203 | ||
204 | /* Make the child exit by sending it a sigkill. */ | 204 | /* Make the child exit by sending it a sigkill. */ |
205 | case PTRACE_KILL: | 205 | case PTRACE_KILL: |
206 | ret = 0; | 206 | ret = 0; |
207 | 207 | ||
@@ -245,9 +245,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
245 | break; | 245 | break; |
246 | 246 | ||
247 | } | 247 | } |
248 | |||
248 | /* Get all GP registers from the child. */ | 249 | /* Get all GP registers from the child. */ |
249 | case PTRACE_GETREGS: { | 250 | case PTRACE_GETREGS: { |
250 | int i; | 251 | int i; |
251 | unsigned long tmp; | 252 | unsigned long tmp; |
252 | 253 | ||
253 | for (i = 0; i <= PT_MAX; i++) { | 254 | for (i = 0; i <= PT_MAX; i++) { |
@@ -294,6 +295,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
294 | break; | 295 | break; |
295 | } | 296 | } |
296 | 297 | ||
298 | out_tsk: | ||
297 | return ret; | 299 | return ret; |
298 | } | 300 | } |
299 | 301 | ||
diff --git a/arch/cris/arch-v32/kernel/signal.c b/arch/cris/arch-v32/kernel/signal.c index 024cc6901974..58c1866804e3 100644 --- a/arch/cris/arch-v32/kernel/signal.c +++ b/arch/cris/arch-v32/kernel/signal.c | |||
@@ -50,7 +50,7 @@ struct rt_signal_frame { | |||
50 | unsigned char retcode[8]; /* Trampoline code. */ | 50 | unsigned char retcode[8]; /* Trampoline code. */ |
51 | }; | 51 | }; |
52 | 52 | ||
53 | int do_signal(int restart, sigset_t *oldset, struct pt_regs *regs); | 53 | void do_signal(int restart, struct pt_regs *regs); |
54 | void keep_debug_flags(unsigned long oldccs, unsigned long oldspc, | 54 | void keep_debug_flags(unsigned long oldccs, unsigned long oldspc, |
55 | struct pt_regs *regs); | 55 | struct pt_regs *regs); |
56 | /* | 56 | /* |
@@ -61,74 +61,16 @@ int | |||
61 | sys_sigsuspend(old_sigset_t mask, long r11, long r12, long r13, long mof, | 61 | sys_sigsuspend(old_sigset_t mask, long r11, long r12, long r13, long mof, |
62 | long srp, struct pt_regs *regs) | 62 | long srp, struct pt_regs *regs) |
63 | { | 63 | { |
64 | sigset_t saveset; | ||
65 | |||
66 | mask &= _BLOCKABLE; | 64 | mask &= _BLOCKABLE; |
67 | |||
68 | spin_lock_irq(¤t->sighand->siglock); | 65 | spin_lock_irq(¤t->sighand->siglock); |
69 | 66 | current->saved_sigmask = current->blocked; | |
70 | saveset = current->blocked; | ||
71 | |||
72 | siginitset(¤t->blocked, mask); | 67 | siginitset(¤t->blocked, mask); |
73 | |||
74 | recalc_sigpending(); | ||
75 | spin_unlock_irq(¤t->sighand->siglock); | ||
76 | |||
77 | regs->r10 = -EINTR; | ||
78 | |||
79 | while (1) { | ||
80 | current->state = TASK_INTERRUPTIBLE; | ||
81 | schedule(); | ||
82 | |||
83 | if (do_signal(0, &saveset, regs)) { | ||
84 | /* | ||
85 | * This point is reached twice: once to call | ||
86 | * the signal handler, then again to return | ||
87 | * from the sigsuspend system call. When | ||
88 | * calling the signal handler, R10 hold the | ||
89 | * signal number as set by do_signal(). The | ||
90 | * sigsuspend call will always return with | ||
91 | * the restored value above; -EINTR. | ||
92 | */ | ||
93 | return regs->r10; | ||
94 | } | ||
95 | } | ||
96 | } | ||
97 | |||
98 | /* Define some dummy arguments to be able to reach the regs argument. */ | ||
99 | int | ||
100 | sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, long r12, long r13, | ||
101 | long mof, long srp, struct pt_regs *regs) | ||
102 | { | ||
103 | sigset_t saveset; | ||
104 | sigset_t newset; | ||
105 | |||
106 | if (sigsetsize != sizeof(sigset_t)) | ||
107 | return -EINVAL; | ||
108 | |||
109 | if (copy_from_user(&newset, unewset, sizeof(newset))) | ||
110 | return -EFAULT; | ||
111 | |||
112 | sigdelsetmask(&newset, ~_BLOCKABLE); | ||
113 | spin_lock_irq(¤t->sighand->siglock); | ||
114 | |||
115 | saveset = current->blocked; | ||
116 | current->blocked = newset; | ||
117 | |||
118 | recalc_sigpending(); | 68 | recalc_sigpending(); |
119 | spin_unlock_irq(¤t->sighand->siglock); | 69 | spin_unlock_irq(¤t->sighand->siglock); |
120 | 70 | current->state = TASK_INTERRUPTIBLE; | |
121 | regs->r10 = -EINTR; | 71 | schedule(); |
122 | 72 | set_thread_flag(TIF_RESTORE_SIGMASK); | |
123 | while (1) { | 73 | return -ERESTARTNOHAND; |
124 | current->state = TASK_INTERRUPTIBLE; | ||
125 | schedule(); | ||
126 | |||
127 | if (do_signal(0, &saveset, regs)) { | ||
128 | /* See comment in function above. */ | ||
129 | return regs->r10; | ||
130 | } | ||
131 | } | ||
132 | } | 74 | } |
133 | 75 | ||
134 | int | 76 | int |
@@ -290,7 +232,7 @@ sys_rt_sigreturn(long r10, long r11, long r12, long r13, long mof, long srp, | |||
290 | goto badframe; | 232 | goto badframe; |
291 | 233 | ||
292 | if (do_sigaltstack(&frame->uc.uc_stack, NULL, rdusp()) == -EFAULT) | 234 | if (do_sigaltstack(&frame->uc.uc_stack, NULL, rdusp()) == -EFAULT) |
293 | goto badframe; | 235 | goto badframe; |
294 | 236 | ||
295 | keep_debug_flags(oldccs, oldspc, regs); | 237 | keep_debug_flags(oldccs, oldspc, regs); |
296 | 238 | ||
@@ -347,11 +289,11 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) | |||
347 | /* Grab and setup a signal frame. | 289 | /* Grab and setup a signal frame. |
348 | * | 290 | * |
349 | * Basically a lot of state-info is stacked, and arranged for the | 291 | * Basically a lot of state-info is stacked, and arranged for the |
350 | * user-mode program to return to the kernel using either a trampoline | 292 | * user-mode program to return to the kernel using either a trampiline |
351 | * which performs the syscall sigreturn(), or a provided user-mode | 293 | * which performs the syscall sigreturn(), or a provided user-mode |
352 | * trampoline. | 294 | * trampoline. |
353 | */ | 295 | */ |
354 | static void | 296 | static int |
355 | setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, | 297 | setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, |
356 | struct pt_regs * regs) | 298 | struct pt_regs * regs) |
357 | { | 299 | { |
@@ -417,16 +359,17 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, | |||
417 | /* Actually move the USP to reflect the stacked frame. */ | 359 | /* Actually move the USP to reflect the stacked frame. */ |
418 | wrusp((unsigned long)frame); | 360 | wrusp((unsigned long)frame); |
419 | 361 | ||
420 | return; | 362 | return 0; |
421 | 363 | ||
422 | give_sigsegv: | 364 | give_sigsegv: |
423 | if (sig == SIGSEGV) | 365 | if (sig == SIGSEGV) |
424 | ka->sa.sa_handler = SIG_DFL; | 366 | ka->sa.sa_handler = SIG_DFL; |
425 | 367 | ||
426 | force_sig(SIGSEGV, current); | 368 | force_sig(SIGSEGV, current); |
369 | return -EFAULT; | ||
427 | } | 370 | } |
428 | 371 | ||
429 | static void | 372 | static int |
430 | setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 373 | setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, |
431 | sigset_t *set, struct pt_regs * regs) | 374 | sigset_t *set, struct pt_regs * regs) |
432 | { | 375 | { |
@@ -503,21 +446,24 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
503 | /* Actually move the usp to reflect the stacked frame. */ | 446 | /* Actually move the usp to reflect the stacked frame. */ |
504 | wrusp((unsigned long)frame); | 447 | wrusp((unsigned long)frame); |
505 | 448 | ||
506 | return; | 449 | return 0; |
507 | 450 | ||
508 | give_sigsegv: | 451 | give_sigsegv: |
509 | if (sig == SIGSEGV) | 452 | if (sig == SIGSEGV) |
510 | ka->sa.sa_handler = SIG_DFL; | 453 | ka->sa.sa_handler = SIG_DFL; |
511 | 454 | ||
512 | force_sig(SIGSEGV, current); | 455 | force_sig(SIGSEGV, current); |
456 | return -EFAULT; | ||
513 | } | 457 | } |
514 | 458 | ||
515 | /* Invoke a singal handler to, well, handle the signal. */ | 459 | /* Invoke a singal handler to, well, handle the signal. */ |
516 | static inline void | 460 | static inline int |
517 | handle_signal(int canrestart, unsigned long sig, | 461 | handle_signal(int canrestart, unsigned long sig, |
518 | siginfo_t *info, struct k_sigaction *ka, | 462 | siginfo_t *info, struct k_sigaction *ka, |
519 | sigset_t *oldset, struct pt_regs * regs) | 463 | sigset_t *oldset, struct pt_regs * regs) |
520 | { | 464 | { |
465 | int ret; | ||
466 | |||
521 | /* Check if this got called from a system call. */ | 467 | /* Check if this got called from a system call. */ |
522 | if (canrestart) { | 468 | if (canrestart) { |
523 | /* If so, check system call restarting. */ | 469 | /* If so, check system call restarting. */ |
@@ -561,19 +507,24 @@ handle_signal(int canrestart, unsigned long sig, | |||
561 | 507 | ||
562 | /* Set up the stack frame. */ | 508 | /* Set up the stack frame. */ |
563 | if (ka->sa.sa_flags & SA_SIGINFO) | 509 | if (ka->sa.sa_flags & SA_SIGINFO) |
564 | setup_rt_frame(sig, ka, info, oldset, regs); | 510 | ret = setup_rt_frame(sig, ka, info, oldset, regs); |
565 | else | 511 | else |
566 | setup_frame(sig, ka, oldset, regs); | 512 | ret = setup_frame(sig, ka, oldset, regs); |
567 | 513 | ||
568 | if (ka->sa.sa_flags & SA_ONESHOT) | 514 | if (ka->sa.sa_flags & SA_ONESHOT) |
569 | ka->sa.sa_handler = SIG_DFL; | 515 | ka->sa.sa_handler = SIG_DFL; |
570 | 516 | ||
571 | spin_lock_irq(¤t->sighand->siglock); | 517 | if (ret == 0) { |
572 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); | 518 | spin_lock_irq(¤t->sighand->siglock); |
573 | if (!(ka->sa.sa_flags & SA_NODEFER)) | 519 | sigorsets(¤t->blocked, ¤t->blocked, |
574 | sigaddset(¤t->blocked,sig); | 520 | &ka->sa.sa_mask); |
575 | recalc_sigpending(); | 521 | if (!(ka->sa.sa_flags & SA_NODEFER)) |
576 | spin_unlock_irq(¤t->sighand->siglock); | 522 | sigaddset(¤t->blocked, sig); |
523 | recalc_sigpending(); | ||
524 | spin_unlock_irq(¤t->sighand->siglock); | ||
525 | } | ||
526 | |||
527 | return ret; | ||
577 | } | 528 | } |
578 | 529 | ||
579 | /* | 530 | /* |
@@ -587,12 +538,13 @@ handle_signal(int canrestart, unsigned long sig, | |||
587 | * we can use user_mode(regs) to see if we came directly from kernel or user | 538 | * we can use user_mode(regs) to see if we came directly from kernel or user |
588 | * mode below. | 539 | * mode below. |
589 | */ | 540 | */ |
590 | int | 541 | void |
591 | do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs) | 542 | do_signal(int canrestart, struct pt_regs *regs) |
592 | { | 543 | { |
593 | int signr; | 544 | int signr; |
594 | siginfo_t info; | 545 | siginfo_t info; |
595 | struct k_sigaction ka; | 546 | struct k_sigaction ka; |
547 | sigset_t *oldset; | ||
596 | 548 | ||
597 | /* | 549 | /* |
598 | * The common case should go fast, which is why this point is | 550 | * The common case should go fast, which is why this point is |
@@ -600,17 +552,28 @@ do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs) | |||
600 | * without doing anything. | 552 | * without doing anything. |
601 | */ | 553 | */ |
602 | if (!user_mode(regs)) | 554 | if (!user_mode(regs)) |
603 | return 1; | 555 | return; |
604 | 556 | ||
605 | if (!oldset) | 557 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
558 | oldset = ¤t->saved_sigmask; | ||
559 | else | ||
606 | oldset = ¤t->blocked; | 560 | oldset = ¤t->blocked; |
607 | 561 | ||
608 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 562 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
609 | 563 | ||
610 | if (signr > 0) { | 564 | if (signr > 0) { |
611 | /* Deliver the signal. */ | 565 | /* Whee! Actually deliver the signal. */ |
612 | handle_signal(canrestart, signr, &info, &ka, oldset, regs); | 566 | if (handle_signal(canrestart, signr, &info, &ka, |
613 | return 1; | 567 | oldset, regs)) { |
568 | /* a signal was successfully delivered; the saved | ||
569 | * sigmask will have been stored in the signal frame, | ||
570 | * and will be restored by sigreturn, so we can simply | ||
571 | * clear the TIF_RESTORE_SIGMASK flag */ | ||
572 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
573 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
574 | } | ||
575 | |||
576 | return; | ||
614 | } | 577 | } |
615 | 578 | ||
616 | /* Got here from a system call? */ | 579 | /* Got here from a system call? */ |
@@ -628,7 +591,12 @@ do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs) | |||
628 | } | 591 | } |
629 | } | 592 | } |
630 | 593 | ||
631 | return 0; | 594 | /* if there's no signal to deliver, we just put the saved sigmask |
595 | * back */ | ||
596 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||
597 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
598 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
599 | } | ||
632 | } | 600 | } |
633 | 601 | ||
634 | asmlinkage void | 602 | asmlinkage void |
@@ -641,7 +609,7 @@ ugdb_trap_user(struct thread_info *ti, int sig) | |||
641 | user_regs(ti)->spc = 0; | 609 | user_regs(ti)->spc = 0; |
642 | } | 610 | } |
643 | /* FIXME: Filter out false h/w breakpoint hits (i.e. EDA | 611 | /* FIXME: Filter out false h/w breakpoint hits (i.e. EDA |
644 | not within any configured h/w breakpoint range). Synchronize with | 612 | not withing any configured h/w breakpoint range). Synchronize with |
645 | what already exists for kernel debugging. */ | 613 | what already exists for kernel debugging. */ |
646 | if (((user_regs(ti)->exs & 0xff00) >> 8) == BREAK_8_INTR_VECT) { | 614 | if (((user_regs(ti)->exs & 0xff00) >> 8) == BREAK_8_INTR_VECT) { |
647 | /* Break 8: subtract 2 from ERP unless in a delay slot. */ | 615 | /* Break 8: subtract 2 from ERP unless in a delay slot. */ |
diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c index 171c96e0a5d3..a9c3334e46c9 100644 --- a/arch/cris/arch-v32/kernel/smp.c +++ b/arch/cris/arch-v32/kernel/smp.c | |||
@@ -1,11 +1,12 @@ | |||
1 | #include <linux/types.h> | ||
1 | #include <asm/delay.h> | 2 | #include <asm/delay.h> |
2 | #include <asm/arch/irq.h> | 3 | #include <irq.h> |
3 | #include <asm/arch/hwregs/intr_vect.h> | 4 | #include <hwregs/intr_vect.h> |
4 | #include <asm/arch/hwregs/intr_vect_defs.h> | 5 | #include <hwregs/intr_vect_defs.h> |
5 | #include <asm/tlbflush.h> | 6 | #include <asm/tlbflush.h> |
6 | #include <asm/mmu_context.h> | 7 | #include <asm/mmu_context.h> |
7 | #include <asm/arch/hwregs/mmu_defs_asm.h> | 8 | #include <hwregs/asm/mmu_defs_asm.h> |
8 | #include <asm/arch/hwregs/supp_reg.h> | 9 | #include <hwregs/supp_reg.h> |
9 | #include <asm/atomic.h> | 10 | #include <asm/atomic.h> |
10 | 11 | ||
11 | #include <linux/err.h> | 12 | #include <linux/err.h> |
@@ -20,6 +21,7 @@ | |||
20 | #define IPI_SCHEDULE 1 | 21 | #define IPI_SCHEDULE 1 |
21 | #define IPI_CALL 2 | 22 | #define IPI_CALL 2 |
22 | #define IPI_FLUSH_TLB 4 | 23 | #define IPI_FLUSH_TLB 4 |
24 | #define IPI_BOOT 8 | ||
23 | 25 | ||
24 | #define FLUSH_ALL (void*)0xffffffff | 26 | #define FLUSH_ALL (void*)0xffffffff |
25 | 27 | ||
@@ -30,6 +32,8 @@ spinlock_t cris_atomic_locks[] = { [0 ... LOCK_COUNT - 1] = SPIN_LOCK_UNLOCKED}; | |||
30 | cpumask_t cpu_online_map = CPU_MASK_NONE; | 32 | cpumask_t cpu_online_map = CPU_MASK_NONE; |
31 | EXPORT_SYMBOL(cpu_online_map); | 33 | EXPORT_SYMBOL(cpu_online_map); |
32 | cpumask_t phys_cpu_present_map = CPU_MASK_NONE; | 34 | cpumask_t phys_cpu_present_map = CPU_MASK_NONE; |
35 | cpumask_t cpu_possible_map; | ||
36 | EXPORT_SYMBOL(cpu_possible_map); | ||
33 | EXPORT_SYMBOL(phys_cpu_present_map); | 37 | EXPORT_SYMBOL(phys_cpu_present_map); |
34 | 38 | ||
35 | /* Variables used during SMP boot */ | 39 | /* Variables used during SMP boot */ |
@@ -55,13 +59,12 @@ static unsigned long flush_addr; | |||
55 | extern int setup_irq(int, struct irqaction *); | 59 | extern int setup_irq(int, struct irqaction *); |
56 | 60 | ||
57 | /* Mode registers */ | 61 | /* Mode registers */ |
58 | static unsigned long irq_regs[NR_CPUS] = | 62 | static unsigned long irq_regs[NR_CPUS] = { |
59 | { | ||
60 | regi_irq, | 63 | regi_irq, |
61 | regi_irq2 | 64 | regi_irq2 |
62 | }; | 65 | }; |
63 | 66 | ||
64 | static irqreturn_t crisv32_ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs); | 67 | static irqreturn_t crisv32_ipi_interrupt(int irq, void *dev_id); |
65 | static int send_ipi(int vector, int wait, cpumask_t cpu_mask); | 68 | static int send_ipi(int vector, int wait, cpumask_t cpu_mask); |
66 | static struct irqaction irq_ipi = { | 69 | static struct irqaction irq_ipi = { |
67 | .handler = crisv32_ipi_interrupt, | 70 | .handler = crisv32_ipi_interrupt, |
@@ -101,6 +104,7 @@ void __devinit smp_prepare_boot_cpu(void) | |||
101 | 104 | ||
102 | cpu_set(0, cpu_online_map); | 105 | cpu_set(0, cpu_online_map); |
103 | cpu_set(0, phys_cpu_present_map); | 106 | cpu_set(0, phys_cpu_present_map); |
107 | cpu_set(0, cpu_possible_map); | ||
104 | } | 108 | } |
105 | 109 | ||
106 | void __init smp_cpus_done(unsigned int max_cpus) | 110 | void __init smp_cpus_done(unsigned int max_cpus) |
@@ -113,6 +117,7 @@ smp_boot_one_cpu(int cpuid) | |||
113 | { | 117 | { |
114 | unsigned timeout; | 118 | unsigned timeout; |
115 | struct task_struct *idle; | 119 | struct task_struct *idle; |
120 | cpumask_t cpu_mask = CPU_MASK_NONE; | ||
116 | 121 | ||
117 | idle = fork_idle(cpuid); | 122 | idle = fork_idle(cpuid); |
118 | if (IS_ERR(idle)) | 123 | if (IS_ERR(idle)) |
@@ -124,6 +129,12 @@ smp_boot_one_cpu(int cpuid) | |||
124 | smp_init_current_idle_thread = task_thread_info(idle); | 129 | smp_init_current_idle_thread = task_thread_info(idle); |
125 | cpu_now_booting = cpuid; | 130 | cpu_now_booting = cpuid; |
126 | 131 | ||
132 | /* Kick it */ | ||
133 | cpu_set(cpuid, cpu_online_map); | ||
134 | cpu_set(cpuid, cpu_mask); | ||
135 | send_ipi(IPI_BOOT, 0, cpu_mask); | ||
136 | cpu_clear(cpuid, cpu_online_map); | ||
137 | |||
127 | /* Wait for CPU to come online */ | 138 | /* Wait for CPU to come online */ |
128 | for (timeout = 0; timeout < 10000; timeout++) { | 139 | for (timeout = 0; timeout < 10000; timeout++) { |
129 | if(cpu_online(cpuid)) { | 140 | if(cpu_online(cpuid)) { |
@@ -165,7 +176,7 @@ void __init smp_callin(void) | |||
165 | /* Enable IRQ and idle */ | 176 | /* Enable IRQ and idle */ |
166 | REG_WR(intr_vect, irq_regs[cpu], rw_mask, vect_mask); | 177 | REG_WR(intr_vect, irq_regs[cpu], rw_mask, vect_mask); |
167 | unmask_irq(IPI_INTR_VECT); | 178 | unmask_irq(IPI_INTR_VECT); |
168 | unmask_irq(TIMER_INTR_VECT); | 179 | unmask_irq(TIMER0_INTR_VECT); |
169 | preempt_disable(); | 180 | preempt_disable(); |
170 | local_irq_enable(); | 181 | local_irq_enable(); |
171 | 182 | ||
@@ -328,7 +339,7 @@ int smp_call_function(void (*func)(void *info), void *info, | |||
328 | return ret; | 339 | return ret; |
329 | } | 340 | } |
330 | 341 | ||
331 | irqreturn_t crisv32_ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 342 | irqreturn_t crisv32_ipi_interrupt(int irq, void *dev_id) |
332 | { | 343 | { |
333 | void (*func) (void *info) = call_data->func; | 344 | void (*func) (void *info) = call_data->func; |
334 | void *info = call_data->info; | 345 | void *info = call_data->info; |
diff --git a/arch/cris/arch-v32/kernel/time.c b/arch/cris/arch-v32/kernel/time.c index 2f7e8e200f2c..3a13dd6e0a9a 100644 --- a/arch/cris/arch-v32/kernel/time.c +++ b/arch/cris/arch-v32/kernel/time.c | |||
@@ -1,8 +1,7 @@ | |||
1 | /* $Id: time.c,v 1.19 2005/04/29 05:40:09 starvik Exp $ | 1 | /* |
2 | * | ||
3 | * linux/arch/cris/arch-v32/kernel/time.c | 2 | * linux/arch/cris/arch-v32/kernel/time.c |
4 | * | 3 | * |
5 | * Copyright (C) 2003 Axis Communications AB | 4 | * Copyright (C) 2003-2007 Axis Communications AB |
6 | * | 5 | * |
7 | */ | 6 | */ |
8 | 7 | ||
@@ -14,28 +13,34 @@ | |||
14 | #include <linux/sched.h> | 13 | #include <linux/sched.h> |
15 | #include <linux/init.h> | 14 | #include <linux/init.h> |
16 | #include <linux/threads.h> | 15 | #include <linux/threads.h> |
16 | #include <linux/cpufreq.h> | ||
17 | #include <asm/types.h> | 17 | #include <asm/types.h> |
18 | #include <asm/signal.h> | 18 | #include <asm/signal.h> |
19 | #include <asm/io.h> | 19 | #include <asm/io.h> |
20 | #include <asm/delay.h> | 20 | #include <asm/delay.h> |
21 | #include <asm/rtc.h> | 21 | #include <asm/rtc.h> |
22 | #include <asm/irq.h> | 22 | #include <asm/irq.h> |
23 | 23 | #include <asm/irq_regs.h> | |
24 | #include <asm/arch/hwregs/reg_map.h> | 24 | |
25 | #include <asm/arch/hwregs/reg_rdwr.h> | 25 | #include <hwregs/reg_map.h> |
26 | #include <asm/arch/hwregs/timer_defs.h> | 26 | #include <hwregs/reg_rdwr.h> |
27 | #include <asm/arch/hwregs/intr_vect_defs.h> | 27 | #include <hwregs/timer_defs.h> |
28 | #include <hwregs/intr_vect_defs.h> | ||
29 | #ifdef CONFIG_CRIS_MACH_ARTPEC3 | ||
30 | #include <hwregs/clkgen_defs.h> | ||
31 | #endif | ||
28 | 32 | ||
29 | /* Watchdog defines */ | 33 | /* Watchdog defines */ |
30 | #define ETRAX_WD_KEY_MASK 0x7F /* key is 7 bit */ | 34 | #define ETRAX_WD_KEY_MASK 0x7F /* key is 7 bit */ |
31 | #define ETRAX_WD_HZ 763 /* watchdog counts at 763 Hz */ | 35 | #define ETRAX_WD_HZ 763 /* watchdog counts at 763 Hz */ |
32 | #define ETRAX_WD_CNT ((2*ETRAX_WD_HZ)/HZ + 1) /* Number of 763 counts before watchdog bites */ | 36 | /* Number of 763 counts before watchdog bites */ |
37 | #define ETRAX_WD_CNT ((2*ETRAX_WD_HZ)/HZ + 1) | ||
33 | 38 | ||
34 | unsigned long timer_regs[NR_CPUS] = | 39 | unsigned long timer_regs[NR_CPUS] = |
35 | { | 40 | { |
36 | regi_timer, | 41 | regi_timer0, |
37 | #ifdef CONFIG_SMP | 42 | #ifdef CONFIG_SMP |
38 | regi_timer2 | 43 | regi_timer2 |
39 | #endif | 44 | #endif |
40 | }; | 45 | }; |
41 | 46 | ||
@@ -44,12 +49,22 @@ extern int set_rtc_mmss(unsigned long nowtime); | |||
44 | extern int setup_irq(int, struct irqaction *); | 49 | extern int setup_irq(int, struct irqaction *); |
45 | extern int have_rtc; | 50 | extern int have_rtc; |
46 | 51 | ||
52 | #ifdef CONFIG_CPU_FREQ | ||
53 | static int | ||
54 | cris_time_freq_notifier(struct notifier_block *nb, unsigned long val, | ||
55 | void *data); | ||
56 | |||
57 | static struct notifier_block cris_time_freq_notifier_block = { | ||
58 | .notifier_call = cris_time_freq_notifier, | ||
59 | }; | ||
60 | #endif | ||
61 | |||
47 | unsigned long get_ns_in_jiffie(void) | 62 | unsigned long get_ns_in_jiffie(void) |
48 | { | 63 | { |
49 | reg_timer_r_tmr0_data data; | 64 | reg_timer_r_tmr0_data data; |
50 | unsigned long ns; | 65 | unsigned long ns; |
51 | 66 | ||
52 | data = REG_RD(timer, regi_timer, r_tmr0_data); | 67 | data = REG_RD(timer, regi_timer0, r_tmr0_data); |
53 | ns = (TIMER0_DIV - data) * 10; | 68 | ns = (TIMER0_DIV - data) * 10; |
54 | return ns; | 69 | return ns; |
55 | } | 70 | } |
@@ -59,31 +74,27 @@ unsigned long do_slow_gettimeoffset(void) | |||
59 | unsigned long count; | 74 | unsigned long count; |
60 | unsigned long usec_count = 0; | 75 | unsigned long usec_count = 0; |
61 | 76 | ||
62 | static unsigned long count_p = TIMER0_DIV;/* for the first call after boot */ | 77 | /* For the first call after boot */ |
78 | static unsigned long count_p = TIMER0_DIV; | ||
63 | static unsigned long jiffies_p = 0; | 79 | static unsigned long jiffies_p = 0; |
64 | 80 | ||
65 | /* | 81 | /* Cache volatile jiffies temporarily; we have IRQs turned off. */ |
66 | * cache volatile jiffies temporarily; we have IRQs turned off. | ||
67 | */ | ||
68 | unsigned long jiffies_t; | 82 | unsigned long jiffies_t; |
69 | 83 | ||
70 | /* The timer interrupt comes from Etrax timer 0. In order to get | 84 | /* The timer interrupt comes from Etrax timer 0. In order to get |
71 | * better precision, we check the current value. It might have | 85 | * better precision, we check the current value. It might have |
72 | * underflowed already though. | 86 | * underflowed already though. */ |
73 | */ | 87 | count = REG_RD(timer, regi_timer0, r_tmr0_data); |
88 | jiffies_t = jiffies; | ||
74 | 89 | ||
75 | count = REG_RD(timer, regi_timer, r_tmr0_data); | 90 | /* Avoiding timer inconsistencies (they are rare, but they happen) |
76 | jiffies_t = jiffies; | 91 | * There is one problem that must be avoided here: |
77 | 92 | * 1. the timer counter underflows | |
78 | /* | ||
79 | * avoiding timer inconsistencies (they are rare, but they happen)... | ||
80 | * there are one problem that must be avoided here: | ||
81 | * 1. the timer counter underflows | ||
82 | */ | 93 | */ |
83 | if( jiffies_t == jiffies_p ) { | 94 | if( jiffies_t == jiffies_p ) { |
84 | if( count > count_p ) { | 95 | if( count > count_p ) { |
85 | /* Timer wrapped, use new count and prescale | 96 | /* Timer wrapped, use new count and prescale. |
86 | * increase the time corresponding to one jiffie | 97 | * Increase the time corresponding to one jiffy. |
87 | */ | 98 | */ |
88 | usec_count = 1000000/HZ; | 99 | usec_count = 1000000/HZ; |
89 | } | 100 | } |
@@ -106,17 +117,15 @@ unsigned long do_slow_gettimeoffset(void) | |||
106 | */ | 117 | */ |
107 | /* This gives us 1.3 ms to do something useful when the NMI comes */ | 118 | /* This gives us 1.3 ms to do something useful when the NMI comes */ |
108 | 119 | ||
109 | /* right now, starting the watchdog is the same as resetting it */ | 120 | /* Right now, starting the watchdog is the same as resetting it */ |
110 | #define start_watchdog reset_watchdog | 121 | #define start_watchdog reset_watchdog |
111 | 122 | ||
112 | #if defined(CONFIG_ETRAX_WATCHDOG) | 123 | #if defined(CONFIG_ETRAX_WATCHDOG) |
113 | static short int watchdog_key = 42; /* arbitrary 7 bit number */ | 124 | static short int watchdog_key = 42; /* arbitrary 7 bit number */ |
114 | #endif | 125 | #endif |
115 | 126 | ||
116 | /* number of pages to consider "out of memory". it is normal that the memory | 127 | /* Number of pages to consider "out of memory". It is normal that the memory |
117 | * is used though, so put this really low. | 128 | * is used though, so set this really low. */ |
118 | */ | ||
119 | |||
120 | #define WATCHDOG_MIN_FREE_PAGES 8 | 129 | #define WATCHDOG_MIN_FREE_PAGES 8 |
121 | 130 | ||
122 | void | 131 | void |
@@ -125,14 +134,15 @@ reset_watchdog(void) | |||
125 | #if defined(CONFIG_ETRAX_WATCHDOG) | 134 | #if defined(CONFIG_ETRAX_WATCHDOG) |
126 | reg_timer_rw_wd_ctrl wd_ctrl = { 0 }; | 135 | reg_timer_rw_wd_ctrl wd_ctrl = { 0 }; |
127 | 136 | ||
128 | /* only keep watchdog happy as long as we have memory left! */ | 137 | /* Only keep watchdog happy as long as we have memory left! */ |
129 | if(nr_free_pages() > WATCHDOG_MIN_FREE_PAGES) { | 138 | if(nr_free_pages() > WATCHDOG_MIN_FREE_PAGES) { |
130 | /* reset the watchdog with the inverse of the old key */ | 139 | /* Reset the watchdog with the inverse of the old key */ |
131 | watchdog_key ^= ETRAX_WD_KEY_MASK; /* invert key, which is 7 bits */ | 140 | /* Invert key, which is 7 bits */ |
141 | watchdog_key ^= ETRAX_WD_KEY_MASK; | ||
132 | wd_ctrl.cnt = ETRAX_WD_CNT; | 142 | wd_ctrl.cnt = ETRAX_WD_CNT; |
133 | wd_ctrl.cmd = regk_timer_start; | 143 | wd_ctrl.cmd = regk_timer_start; |
134 | wd_ctrl.key = watchdog_key; | 144 | wd_ctrl.key = watchdog_key; |
135 | REG_WR(timer, regi_timer, rw_wd_ctrl, wd_ctrl); | 145 | REG_WR(timer, regi_timer0, rw_wd_ctrl, wd_ctrl); |
136 | } | 146 | } |
137 | #endif | 147 | #endif |
138 | } | 148 | } |
@@ -148,7 +158,7 @@ stop_watchdog(void) | |||
148 | wd_ctrl.cnt = ETRAX_WD_CNT; | 158 | wd_ctrl.cnt = ETRAX_WD_CNT; |
149 | wd_ctrl.cmd = regk_timer_stop; | 159 | wd_ctrl.cmd = regk_timer_stop; |
150 | wd_ctrl.key = watchdog_key; | 160 | wd_ctrl.key = watchdog_key; |
151 | REG_WR(timer, regi_timer, rw_wd_ctrl, wd_ctrl); | 161 | REG_WR(timer, regi_timer0, rw_wd_ctrl, wd_ctrl); |
152 | #endif | 162 | #endif |
153 | } | 163 | } |
154 | 164 | ||
@@ -160,17 +170,28 @@ handle_watchdog_bite(struct pt_regs* regs) | |||
160 | #if defined(CONFIG_ETRAX_WATCHDOG) | 170 | #if defined(CONFIG_ETRAX_WATCHDOG) |
161 | extern int cause_of_death; | 171 | extern int cause_of_death; |
162 | 172 | ||
163 | raw_printk("Watchdog bite\n"); | 173 | oops_in_progress = 1; |
174 | printk(KERN_WARNING "Watchdog bite\n"); | ||
164 | 175 | ||
165 | /* Check if forced restart or unexpected watchdog */ | 176 | /* Check if forced restart or unexpected watchdog */ |
166 | if (cause_of_death == 0xbedead) { | 177 | if (cause_of_death == 0xbedead) { |
178 | #ifdef CONFIG_CRIS_MACH_ARTPEC3 | ||
179 | /* There is a bug in Artpec-3 (voodoo TR 78) that requires | ||
180 | * us to go to lower frequency for the reset to be reliable | ||
181 | */ | ||
182 | reg_clkgen_rw_clk_ctrl ctrl = | ||
183 | REG_RD(clkgen, regi_clkgen, rw_clk_ctrl); | ||
184 | ctrl.pll = 0; | ||
185 | REG_WR(clkgen, regi_clkgen, rw_clk_ctrl, ctrl); | ||
186 | #endif | ||
167 | while(1); | 187 | while(1); |
168 | } | 188 | } |
169 | 189 | ||
170 | /* Unexpected watchdog, stop the watchdog and dump registers*/ | 190 | /* Unexpected watchdog, stop the watchdog and dump registers. */ |
171 | stop_watchdog(); | 191 | stop_watchdog(); |
172 | raw_printk("Oops: bitten by watchdog\n"); | 192 | printk(KERN_WARNING "Oops: bitten by watchdog\n"); |
173 | show_registers(regs); | 193 | show_registers(regs); |
194 | oops_in_progress = 0; | ||
174 | #ifndef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY | 195 | #ifndef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY |
175 | reset_watchdog(); | 196 | reset_watchdog(); |
176 | #endif | 197 | #endif |
@@ -178,21 +199,19 @@ handle_watchdog_bite(struct pt_regs* regs) | |||
178 | #endif | 199 | #endif |
179 | } | 200 | } |
180 | 201 | ||
181 | /* last time the cmos clock got updated */ | 202 | /* Last time the cmos clock got updated. */ |
182 | static long last_rtc_update = 0; | 203 | static long last_rtc_update = 0; |
183 | 204 | ||
184 | /* | 205 | /* |
185 | * timer_interrupt() needs to keep up the real-time clock, | 206 | * timer_interrupt() needs to keep up the real-time clock, |
186 | * as well as call the "do_timer()" routine every clocktick | 207 | * as well as call the "do_timer()" routine every clocktick. |
187 | */ | 208 | */ |
188 | |||
189 | //static unsigned short myjiff; /* used by our debug routine print_timestamp */ | ||
190 | |||
191 | extern void cris_do_profile(struct pt_regs *regs); | 209 | extern void cris_do_profile(struct pt_regs *regs); |
192 | 210 | ||
193 | static inline irqreturn_t | 211 | static inline irqreturn_t |
194 | timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 212 | timer_interrupt(int irq, void *dev_id) |
195 | { | 213 | { |
214 | struct pt_regs *regs = get_irq_regs(); | ||
196 | int cpu = smp_processor_id(); | 215 | int cpu = smp_processor_id(); |
197 | reg_timer_r_masked_intr masked_intr; | 216 | reg_timer_r_masked_intr masked_intr; |
198 | reg_timer_rw_ack_intr ack_intr = { 0 }; | 217 | reg_timer_rw_ack_intr ack_intr = { 0 }; |
@@ -202,11 +221,11 @@ timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
202 | if (!masked_intr.tmr0) | 221 | if (!masked_intr.tmr0) |
203 | return IRQ_NONE; | 222 | return IRQ_NONE; |
204 | 223 | ||
205 | /* acknowledge the timer irq */ | 224 | /* Acknowledge the timer irq. */ |
206 | ack_intr.tmr0 = 1; | 225 | ack_intr.tmr0 = 1; |
207 | REG_WR(timer, timer_regs[cpu], rw_ack_intr, ack_intr); | 226 | REG_WR(timer, timer_regs[cpu], rw_ack_intr, ack_intr); |
208 | 227 | ||
209 | /* reset watchdog otherwise it resets us! */ | 228 | /* Reset watchdog otherwise it resets us! */ |
210 | reset_watchdog(); | 229 | reset_watchdog(); |
211 | 230 | ||
212 | /* Update statistics. */ | 231 | /* Update statistics. */ |
@@ -218,7 +237,7 @@ timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
218 | if (cpu != 0) | 237 | if (cpu != 0) |
219 | return IRQ_HANDLED; | 238 | return IRQ_HANDLED; |
220 | 239 | ||
221 | /* call the real timer interrupt handler */ | 240 | /* Call the real timer interrupt handler */ |
222 | do_timer(1); | 241 | do_timer(1); |
223 | 242 | ||
224 | /* | 243 | /* |
@@ -236,17 +255,17 @@ timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
236 | if (set_rtc_mmss(xtime.tv_sec) == 0) | 255 | if (set_rtc_mmss(xtime.tv_sec) == 0) |
237 | last_rtc_update = xtime.tv_sec; | 256 | last_rtc_update = xtime.tv_sec; |
238 | else | 257 | else |
239 | last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ | 258 | /* Do it again in 60 s */ |
259 | last_rtc_update = xtime.tv_sec - 600; | ||
240 | } | 260 | } |
241 | return IRQ_HANDLED; | 261 | return IRQ_HANDLED; |
242 | } | 262 | } |
243 | 263 | ||
244 | /* timer is IRQF_SHARED so drivers can add stuff to the timer irq chain | 264 | /* Timer is IRQF_SHARED so drivers can add stuff to the timer irq chain. |
245 | * it needs to be IRQF_DISABLED to make the jiffies update work properly | 265 | * It needs to be IRQF_DISABLED to make the jiffies update work properly. |
246 | */ | 266 | */ |
247 | 267 | static struct irqaction irq_timer = { | |
248 | static struct irqaction irq_timer = { | 268 | .handler = timer_interrupt, |
249 | .mask = timer_interrupt, | ||
250 | .flags = IRQF_SHARED | IRQF_DISABLED, | 269 | .flags = IRQF_SHARED | IRQF_DISABLED, |
251 | .mask = CPU_MASK_NONE, | 270 | .mask = CPU_MASK_NONE, |
252 | .name = "timer" | 271 | .name = "timer" |
@@ -256,27 +275,27 @@ void __init | |||
256 | cris_timer_init(void) | 275 | cris_timer_init(void) |
257 | { | 276 | { |
258 | int cpu = smp_processor_id(); | 277 | int cpu = smp_processor_id(); |
259 | reg_timer_rw_tmr0_ctrl tmr0_ctrl = { 0 }; | 278 | reg_timer_rw_tmr0_ctrl tmr0_ctrl = { 0 }; |
260 | reg_timer_rw_tmr0_div tmr0_div = TIMER0_DIV; | 279 | reg_timer_rw_tmr0_div tmr0_div = TIMER0_DIV; |
261 | reg_timer_rw_intr_mask timer_intr_mask; | 280 | reg_timer_rw_intr_mask timer_intr_mask; |
262 | 281 | ||
263 | /* Setup the etrax timers | 282 | /* Setup the etrax timers. |
264 | * Base frequency is 100MHz, divider 1000000 -> 100 HZ | 283 | * Base frequency is 100MHz, divider 1000000 -> 100 HZ |
265 | * We use timer0, so timer1 is free. | 284 | * We use timer0, so timer1 is free. |
266 | * The trig timer is used by the fasttimer API if enabled. | 285 | * The trig timer is used by the fasttimer API if enabled. |
267 | */ | 286 | */ |
268 | 287 | ||
269 | tmr0_ctrl.op = regk_timer_ld; | 288 | tmr0_ctrl.op = regk_timer_ld; |
270 | tmr0_ctrl.freq = regk_timer_f100; | 289 | tmr0_ctrl.freq = regk_timer_f100; |
271 | REG_WR(timer, timer_regs[cpu], rw_tmr0_div, tmr0_div); | 290 | REG_WR(timer, timer_regs[cpu], rw_tmr0_div, tmr0_div); |
272 | REG_WR(timer, timer_regs[cpu], rw_tmr0_ctrl, tmr0_ctrl); /* Load */ | 291 | REG_WR(timer, timer_regs[cpu], rw_tmr0_ctrl, tmr0_ctrl); /* Load */ |
273 | tmr0_ctrl.op = regk_timer_run; | 292 | tmr0_ctrl.op = regk_timer_run; |
274 | REG_WR(timer, timer_regs[cpu], rw_tmr0_ctrl, tmr0_ctrl); /* Start */ | 293 | REG_WR(timer, timer_regs[cpu], rw_tmr0_ctrl, tmr0_ctrl); /* Start */ |
275 | 294 | ||
276 | /* enable the timer irq */ | 295 | /* Enable the timer irq. */ |
277 | timer_intr_mask = REG_RD(timer, timer_regs[cpu], rw_intr_mask); | 296 | timer_intr_mask = REG_RD(timer, timer_regs[cpu], rw_intr_mask); |
278 | timer_intr_mask.tmr0 = 1; | 297 | timer_intr_mask.tmr0 = 1; |
279 | REG_WR(timer, timer_regs[cpu], rw_intr_mask, timer_intr_mask); | 298 | REG_WR(timer, timer_regs[cpu], rw_intr_mask, timer_intr_mask); |
280 | } | 299 | } |
281 | 300 | ||
282 | void __init | 301 | void __init |
@@ -284,7 +303,7 @@ time_init(void) | |||
284 | { | 303 | { |
285 | reg_intr_vect_rw_mask intr_mask; | 304 | reg_intr_vect_rw_mask intr_mask; |
286 | 305 | ||
287 | /* probe for the RTC and read it if it exists | 306 | /* Probe for the RTC and read it if it exists. |
288 | * Before the RTC can be probed the loops_per_usec variable needs | 307 | * Before the RTC can be probed the loops_per_usec variable needs |
289 | * to be initialized to make usleep work. A better value for | 308 | * to be initialized to make usleep work. A better value for |
290 | * loops_per_usec is calculated by the kernel later once the | 309 | * loops_per_usec is calculated by the kernel later once the |
@@ -293,52 +312,74 @@ time_init(void) | |||
293 | loops_per_usec = 50; | 312 | loops_per_usec = 50; |
294 | 313 | ||
295 | if(RTC_INIT() < 0) { | 314 | if(RTC_INIT() < 0) { |
296 | /* no RTC, start at 1980 */ | 315 | /* No RTC, start at 1980 */ |
297 | xtime.tv_sec = 0; | 316 | xtime.tv_sec = 0; |
298 | xtime.tv_nsec = 0; | 317 | xtime.tv_nsec = 0; |
299 | have_rtc = 0; | 318 | have_rtc = 0; |
300 | } else { | 319 | } else { |
301 | /* get the current time */ | 320 | /* Get the current time */ |
302 | have_rtc = 1; | 321 | have_rtc = 1; |
303 | update_xtime_from_cmos(); | 322 | update_xtime_from_cmos(); |
304 | } | 323 | } |
305 | 324 | ||
306 | /* | 325 | /* |
307 | * Initialize wall_to_monotonic such that adding it to xtime will yield zero, the | 326 | * Initialize wall_to_monotonic such that adding it to |
308 | * tv_nsec field must be normalized (i.e., 0 <= nsec < NSEC_PER_SEC). | 327 | * xtime will yield zero, the tv_nsec field must be normalized |
328 | * (i.e., 0 <= nsec < NSEC_PER_SEC). | ||
309 | */ | 329 | */ |
310 | set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec); | 330 | set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec); |
311 | 331 | ||
312 | /* Start CPU local timer */ | 332 | /* Start CPU local timer. */ |
313 | cris_timer_init(); | 333 | cris_timer_init(); |
314 | 334 | ||
315 | /* enable the timer irq in global config */ | 335 | /* Enable the timer irq in global config. */ |
316 | intr_mask = REG_RD(intr_vect, regi_irq, rw_mask); | 336 | intr_mask = REG_RD_VECT(intr_vect, regi_irq, rw_mask, 1); |
317 | intr_mask.timer = 1; | 337 | intr_mask.timer0 = 1; |
318 | REG_WR(intr_vect, regi_irq, rw_mask, intr_mask); | 338 | REG_WR_VECT(intr_vect, regi_irq, rw_mask, 1, intr_mask); |
319 | |||
320 | /* now actually register the timer irq handler that calls timer_interrupt() */ | ||
321 | 339 | ||
322 | setup_irq(TIMER_INTR_VECT, &irq_timer); | 340 | /* Now actually register the timer irq handler that calls |
341 | * timer_interrupt(). */ | ||
342 | setup_irq(TIMER0_INTR_VECT, &irq_timer); | ||
323 | 343 | ||
324 | /* enable watchdog if we should use one */ | 344 | /* Enable watchdog if we should use one. */ |
325 | 345 | ||
326 | #if defined(CONFIG_ETRAX_WATCHDOG) | 346 | #if defined(CONFIG_ETRAX_WATCHDOG) |
327 | printk("Enabling watchdog...\n"); | 347 | printk(KERN_INFO "Enabling watchdog...\n"); |
328 | start_watchdog(); | 348 | start_watchdog(); |
329 | 349 | ||
330 | /* If we use the hardware watchdog, we want to trap it as an NMI | 350 | /* If we use the hardware watchdog, we want to trap it as an NMI |
331 | and dump registers before it resets us. For this to happen, we | 351 | * and dump registers before it resets us. For this to happen, we |
332 | must set the "m" NMI enable flag (which once set, is unset only | 352 | * must set the "m" NMI enable flag (which once set, is unset only |
333 | when an NMI is taken). | 353 | * when an NMI is taken). */ |
334 | 354 | { | |
335 | The same goes for the external NMI, but that doesn't have any | 355 | unsigned long flags; |
336 | driver or infrastructure support yet. */ | 356 | local_save_flags(flags); |
337 | { | 357 | flags |= (1<<30); /* NMI M flag is at bit 30 */ |
338 | unsigned long flags; | 358 | local_irq_restore(flags); |
339 | local_save_flags(flags); | 359 | } |
340 | flags |= (1<<30); /* NMI M flag is at bit 30 */ | 360 | #endif |
341 | local_irq_restore(flags); | 361 | |
342 | } | 362 | #ifdef CONFIG_CPU_FREQ |
363 | cpufreq_register_notifier(&cris_time_freq_notifier_block, | ||
364 | CPUFREQ_TRANSITION_NOTIFIER); | ||
343 | #endif | 365 | #endif |
344 | } | 366 | } |
367 | |||
368 | #ifdef CONFIG_CPU_FREQ | ||
369 | static int | ||
370 | cris_time_freq_notifier(struct notifier_block *nb, unsigned long val, | ||
371 | void *data) | ||
372 | { | ||
373 | struct cpufreq_freqs *freqs = data; | ||
374 | if (val == CPUFREQ_POSTCHANGE) { | ||
375 | reg_timer_r_tmr0_data data; | ||
376 | reg_timer_rw_tmr0_div div = (freqs->new * 500) / HZ; | ||
377 | do { | ||
378 | data = REG_RD(timer, timer_regs[freqs->cpu], | ||
379 | r_tmr0_data); | ||
380 | } while (data > 20); | ||
381 | REG_WR(timer, timer_regs[freqs->cpu], rw_tmr0_div, div); | ||
382 | } | ||
383 | return 0; | ||
384 | } | ||
385 | #endif | ||
diff --git a/arch/cris/arch-v32/kernel/traps.c b/arch/cris/arch-v32/kernel/traps.c index 17fd3dbd1c80..9003e382cada 100644 --- a/arch/cris/arch-v32/kernel/traps.c +++ b/arch/cris/arch-v32/kernel/traps.c | |||
@@ -1,50 +1,45 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2003, Axis Communications AB. | 2 | * Copyright (C) 2003-2006, Axis Communications AB. |
3 | */ | 3 | */ |
4 | 4 | ||
5 | #include <linux/ptrace.h> | 5 | #include <linux/ptrace.h> |
6 | #include <linux/module.h> | ||
6 | #include <asm/uaccess.h> | 7 | #include <asm/uaccess.h> |
7 | 8 | #include <hwregs/supp_reg.h> | |
8 | #include <asm/arch/hwregs/supp_reg.h> | 9 | #include <hwregs/intr_vect_defs.h> |
9 | 10 | #include <asm/irq.h> | |
10 | extern void reset_watchdog(void); | ||
11 | extern void stop_watchdog(void); | ||
12 | |||
13 | extern int raw_printk(const char *fmt, ...); | ||
14 | 11 | ||
15 | void | 12 | void |
16 | show_registers(struct pt_regs *regs) | 13 | show_registers(struct pt_regs *regs) |
17 | { | 14 | { |
18 | /* | 15 | /* |
19 | * It's possible to use either the USP register or current->thread.usp. | 16 | * It's possible to use either the USP register or current->thread.usp. |
20 | * USP might not correspond to the current proccess for all cases this | 17 | * USP might not correspond to the current process for all cases this |
21 | * function is called, and current->thread.usp isn't up to date for the | 18 | * function is called, and current->thread.usp isn't up to date for the |
22 | * current proccess. Experience shows that using USP is the way to go. | 19 | * current process. Experience shows that using USP is the way to go. |
23 | */ | 20 | */ |
24 | unsigned long usp; | 21 | unsigned long usp = rdusp(); |
25 | unsigned long d_mmu_cause; | 22 | unsigned long d_mmu_cause; |
26 | unsigned long i_mmu_cause; | 23 | unsigned long i_mmu_cause; |
27 | 24 | ||
28 | usp = rdusp(); | 25 | printk("CPU: %d\n", smp_processor_id()); |
29 | 26 | ||
30 | raw_printk("CPU: %d\n", smp_processor_id()); | 27 | printk("ERP: %08lx SRP: %08lx CCS: %08lx USP: %08lx MOF: %08lx\n", |
28 | regs->erp, regs->srp, regs->ccs, usp, regs->mof); | ||
31 | 29 | ||
32 | raw_printk("ERP: %08lx SRP: %08lx CCS: %08lx USP: %08lx MOF: %08lx\n", | 30 | printk(" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n", |
33 | regs->erp, regs->srp, regs->ccs, usp, regs->mof); | 31 | regs->r0, regs->r1, regs->r2, regs->r3); |
34 | 32 | ||
35 | raw_printk(" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n", | 33 | printk(" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n", |
36 | regs->r0, regs->r1, regs->r2, regs->r3); | 34 | regs->r4, regs->r5, regs->r6, regs->r7); |
37 | 35 | ||
38 | raw_printk(" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n", | 36 | printk(" r8: %08lx r9: %08lx r10: %08lx r11: %08lx\n", |
39 | regs->r4, regs->r5, regs->r6, regs->r7); | 37 | regs->r8, regs->r9, regs->r10, regs->r11); |
40 | 38 | ||
41 | raw_printk(" r8: %08lx r9: %08lx r10: %08lx r11: %08lx\n", | 39 | printk("r12: %08lx r13: %08lx oR10: %08lx acr: %08lx\n", |
42 | regs->r8, regs->r9, regs->r10, regs->r11); | 40 | regs->r12, regs->r13, regs->orig_r10, regs->acr); |
43 | 41 | ||
44 | raw_printk("r12: %08lx r13: %08lx oR10: %08lx acr: %08lx\n", | 42 | printk(" sp: %08lx\n", (unsigned long)regs); |
45 | regs->r12, regs->r13, regs->orig_r10, regs->acr); | ||
46 | |||
47 | raw_printk("sp: %08lx\n", regs); | ||
48 | 43 | ||
49 | SUPP_BANK_SEL(BANK_IM); | 44 | SUPP_BANK_SEL(BANK_IM); |
50 | SUPP_REG_RD(RW_MM_CAUSE, i_mmu_cause); | 45 | SUPP_REG_RD(RW_MM_CAUSE, i_mmu_cause); |
@@ -52,18 +47,20 @@ show_registers(struct pt_regs *regs) | |||
52 | SUPP_BANK_SEL(BANK_DM); | 47 | SUPP_BANK_SEL(BANK_DM); |
53 | SUPP_REG_RD(RW_MM_CAUSE, d_mmu_cause); | 48 | SUPP_REG_RD(RW_MM_CAUSE, d_mmu_cause); |
54 | 49 | ||
55 | raw_printk(" Data MMU Cause: %08lx\n", d_mmu_cause); | 50 | printk(" Data MMU Cause: %08lx\n", d_mmu_cause); |
56 | raw_printk("Instruction MMU Cause: %08lx\n", i_mmu_cause); | 51 | printk("Instruction MMU Cause: %08lx\n", i_mmu_cause); |
57 | 52 | ||
58 | raw_printk("Process %s (pid: %d, stackpage: %08lx)\n", | 53 | printk("Process %s (pid: %d, stackpage=%08lx)\n", |
59 | current->comm, current->pid, (unsigned long) current); | 54 | current->comm, current->pid, (unsigned long)current); |
60 | 55 | ||
61 | /* Show additional info if in kernel-mode. */ | 56 | /* |
57 | * When in-kernel, we also print out the stack and code at the | ||
58 | * time of the fault.. | ||
59 | */ | ||
62 | if (!user_mode(regs)) { | 60 | if (!user_mode(regs)) { |
63 | int i; | 61 | int i; |
64 | unsigned char c; | ||
65 | 62 | ||
66 | show_stack(NULL, (unsigned long *) usp); | 63 | show_stack(NULL, (unsigned long *)usp); |
67 | 64 | ||
68 | /* | 65 | /* |
69 | * If the previous stack-dump wasn't a kernel one, dump the | 66 | * If the previous stack-dump wasn't a kernel one, dump the |
@@ -72,7 +69,7 @@ show_registers(struct pt_regs *regs) | |||
72 | if (usp != 0) | 69 | if (usp != 0) |
73 | show_stack(NULL, NULL); | 70 | show_stack(NULL, NULL); |
74 | 71 | ||
75 | raw_printk("\nCode: "); | 72 | printk("\nCode: "); |
76 | 73 | ||
77 | if (regs->erp < PAGE_OFFSET) | 74 | if (regs->erp < PAGE_OFFSET) |
78 | goto bad_value; | 75 | goto bad_value; |
@@ -84,76 +81,115 @@ show_registers(struct pt_regs *regs) | |||
84 | * instruction decoding should be in sync at the interesting | 81 | * instruction decoding should be in sync at the interesting |
85 | * point, but small enough to fit on a row. The regs->erp | 82 | * point, but small enough to fit on a row. The regs->erp |
86 | * location is pointed out in a ksymoops-friendly way by | 83 | * location is pointed out in a ksymoops-friendly way by |
87 | * wrapping the byte for that address in parenthesis. | 84 | * wrapping the byte for that address in parenthesises. |
88 | */ | 85 | */ |
89 | for (i = -12; i < 12; i++) { | 86 | for (i = -12; i < 12; i++) { |
90 | if (__get_user(c, &((unsigned char *) regs->erp)[i])) { | 87 | unsigned char c; |
88 | |||
89 | if (__get_user(c, &((unsigned char *)regs->erp)[i])) { | ||
91 | bad_value: | 90 | bad_value: |
92 | raw_printk(" Bad IP value."); | 91 | printk(" Bad IP value."); |
93 | break; | 92 | break; |
94 | } | 93 | } |
95 | 94 | ||
96 | if (i == 0) | 95 | if (i == 0) |
97 | raw_printk("(%02x) ", c); | 96 | printk("(%02x) ", c); |
98 | else | 97 | else |
99 | raw_printk("%02x ", c); | 98 | printk("%02x ", c); |
100 | } | 99 | } |
101 | 100 | printk("\n"); | |
102 | raw_printk("\n"); | ||
103 | } | 101 | } |
104 | } | 102 | } |
105 | 103 | ||
106 | /* | ||
107 | * This gets called from entry.S when the watchdog has bitten. Show something | ||
108 | * similar to an Oops dump, and if the kernel is configured to be a nice doggy; | ||
109 | * halt instead of reboot. | ||
110 | */ | ||
111 | void | 104 | void |
112 | watchdog_bite_hook(struct pt_regs *regs) | 105 | arch_enable_nmi(void) |
113 | { | 106 | { |
114 | #ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY | 107 | unsigned long flags; |
115 | local_irq_disable(); | ||
116 | stop_watchdog(); | ||
117 | show_registers(regs); | ||
118 | 108 | ||
119 | while (1) | 109 | local_save_flags(flags); |
120 | ; /* Do nothing. */ | 110 | flags |= (1 << 30); /* NMI M flag is at bit 30 */ |
121 | #else | 111 | local_irq_restore(flags); |
122 | show_registers(regs); | ||
123 | #endif | ||
124 | } | 112 | } |
125 | 113 | ||
126 | /* This is normally the Oops function. */ | 114 | extern void (*nmi_handler)(struct pt_regs *); |
127 | void | 115 | void handle_nmi(struct pt_regs *regs) |
128 | die_if_kernel(const char *str, struct pt_regs *regs, long err) | ||
129 | { | 116 | { |
130 | if (user_mode(regs)) | 117 | #ifdef CONFIG_ETRAXFS |
131 | return; | 118 | reg_intr_vect_r_nmi r; |
119 | #endif | ||
132 | 120 | ||
133 | #ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY | 121 | if (nmi_handler) |
134 | /* | 122 | nmi_handler(regs); |
135 | * This printout might take too long and could trigger | 123 | |
136 | * the watchdog normally. If NICE_DOGGY is set, simply | 124 | #ifdef CONFIG_ETRAXFS |
137 | * stop the watchdog during the printout. | 125 | /* Wait until nmi is no longer active. */ |
138 | */ | 126 | do { |
139 | stop_watchdog(); | 127 | r = REG_RD(intr_vect, regi_irq, r_nmi); |
128 | } while (r.ext == regk_intr_vect_on); | ||
140 | #endif | 129 | #endif |
130 | } | ||
141 | 131 | ||
142 | raw_printk("%s: %04lx\n", str, err & 0xffff); | ||
143 | 132 | ||
144 | show_registers(regs); | 133 | #ifdef CONFIG_BUG |
134 | extern void die_if_kernel(const char *str, struct pt_regs *regs, long err); | ||
145 | 135 | ||
146 | #ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY | 136 | /* Copy of the regs at BUG() time. */ |
147 | reset_watchdog(); | 137 | struct pt_regs BUG_regs; |
148 | #endif | ||
149 | 138 | ||
150 | do_exit(SIGSEGV); | 139 | void do_BUG(char *file, unsigned int line) |
140 | { | ||
141 | printk("kernel BUG at %s:%d!\n", file, line); | ||
142 | die_if_kernel("Oops", &BUG_regs, 0); | ||
151 | } | 143 | } |
144 | EXPORT_SYMBOL(do_BUG); | ||
152 | 145 | ||
153 | void arch_enable_nmi(void) | 146 | void fixup_BUG(struct pt_regs *regs) |
154 | { | 147 | { |
155 | unsigned long flags; | 148 | BUG_regs = *regs; |
156 | local_save_flags(flags); | 149 | |
157 | flags |= (1<<30); /* NMI M flag is at bit 30 */ | 150 | #ifdef CONFIG_DEBUG_BUGVERBOSE |
158 | local_irq_restore(flags); | 151 | /* |
152 | * Fixup the BUG arguments through exception handlers. | ||
153 | */ | ||
154 | { | ||
155 | const struct exception_table_entry *fixup; | ||
156 | |||
157 | /* | ||
158 | * ERP points at the "break 14" + 2, compensate for the 2 | ||
159 | * bytes. | ||
160 | */ | ||
161 | fixup = search_exception_tables(instruction_pointer(regs) - 2); | ||
162 | if (fixup) { | ||
163 | /* Adjust the instruction pointer in the stackframe. */ | ||
164 | instruction_pointer(regs) = fixup->fixup; | ||
165 | arch_fixup(regs); | ||
166 | } | ||
167 | } | ||
168 | #else | ||
169 | /* Dont try to lookup the filename + line, just dump regs. */ | ||
170 | do_BUG("unknown", 0); | ||
171 | #endif | ||
159 | } | 172 | } |
173 | |||
174 | /* | ||
175 | * Break 14 handler. Save regs and jump into the fixup_BUG. | ||
176 | */ | ||
177 | __asm__ ( ".text\n\t" | ||
178 | ".global breakh_BUG\n\t" | ||
179 | "breakh_BUG:\n\t" | ||
180 | SAVE_ALL | ||
181 | KGDB_FIXUP | ||
182 | "move.d $sp, $r10\n\t" | ||
183 | "jsr fixup_BUG\n\t" | ||
184 | "nop\n\t" | ||
185 | "jump ret_from_intr\n\t" | ||
186 | "nop\n\t"); | ||
187 | |||
188 | |||
189 | #ifdef CONFIG_DEBUG_BUGVERBOSE | ||
190 | void | ||
191 | handle_BUG(struct pt_regs *regs) | ||
192 | { | ||
193 | } | ||
194 | #endif | ||
195 | #endif | ||
diff --git a/arch/cris/arch-v32/kernel/vcs_hook.c b/arch/cris/arch-v32/kernel/vcs_hook.c deleted file mode 100644 index 64d71c54c22c..000000000000 --- a/arch/cris/arch-v32/kernel/vcs_hook.c +++ /dev/null | |||
@@ -1,96 +0,0 @@ | |||
1 | // $Id: vcs_hook.c,v 1.2 2003/08/12 12:01:06 starvik Exp $ | ||
2 | // | ||
3 | // Call simulator hook. This is the part running in the | ||
4 | // simulated program. | ||
5 | // | ||
6 | |||
7 | #include "vcs_hook.h" | ||
8 | #include <stdarg.h> | ||
9 | #include <asm/arch-v32/hwregs/reg_map.h> | ||
10 | #include <asm/arch-v32/hwregs/intr_vect_defs.h> | ||
11 | |||
12 | #define HOOK_TRIG_ADDR 0xb7000000 /* hook cvlog model reg address */ | ||
13 | #define HOOK_MEM_BASE_ADDR 0xa0000000 /* csp4 (shared mem) base addr */ | ||
14 | |||
15 | #define HOOK_DATA(offset) ((unsigned*) HOOK_MEM_BASE_ADDR)[offset] | ||
16 | #define VHOOK_DATA(offset) ((volatile unsigned*) HOOK_MEM_BASE_ADDR)[offset] | ||
17 | #define HOOK_TRIG(funcid) do { *((unsigned *) HOOK_TRIG_ADDR) = funcid; } while(0) | ||
18 | #define HOOK_DATA_BYTE(offset) ((unsigned char*) HOOK_MEM_BASE_ADDR)[offset] | ||
19 | |||
20 | |||
21 | // ------------------------------------------------------------------ hook_call | ||
22 | int hook_call( unsigned id, unsigned pcnt, ...) { | ||
23 | va_list ap; | ||
24 | unsigned i; | ||
25 | unsigned ret; | ||
26 | #ifdef USING_SOS | ||
27 | PREEMPT_OFF_SAVE(); | ||
28 | #endif | ||
29 | |||
30 | // pass parameters | ||
31 | HOOK_DATA(0) = id; | ||
32 | |||
33 | /* Have to make hook_print_str a special case since we call with a | ||
34 | parameter of byte type. Should perhaps be a separate | ||
35 | hook_call. */ | ||
36 | |||
37 | if (id == hook_print_str) { | ||
38 | int i; | ||
39 | char *str; | ||
40 | |||
41 | HOOK_DATA(1) = pcnt; | ||
42 | |||
43 | va_start(ap, pcnt); | ||
44 | str = (char*)va_arg(ap,unsigned); | ||
45 | |||
46 | for (i=0; i!=pcnt; i++) { | ||
47 | HOOK_DATA_BYTE(8+i) = str[i]; | ||
48 | } | ||
49 | HOOK_DATA_BYTE(8+i) = 0; /* null byte */ | ||
50 | } | ||
51 | else { | ||
52 | va_start(ap, pcnt); | ||
53 | for( i = 1; i <= pcnt; i++ ) HOOK_DATA(i) = va_arg(ap,unsigned); | ||
54 | va_end(ap); | ||
55 | } | ||
56 | |||
57 | // read from mem to make sure data has propagated to memory before trigging | ||
58 | *((volatile unsigned*) HOOK_MEM_BASE_ADDR); | ||
59 | |||
60 | // trigger hook | ||
61 | HOOK_TRIG(id); | ||
62 | |||
63 | // wait for call to finish | ||
64 | while( VHOOK_DATA(0) > 0 ) {} | ||
65 | |||
66 | // extract return value | ||
67 | |||
68 | ret = VHOOK_DATA(1); | ||
69 | |||
70 | #ifdef USING_SOS | ||
71 | PREEMPT_RESTORE(); | ||
72 | #endif | ||
73 | return ret; | ||
74 | } | ||
75 | |||
76 | unsigned | ||
77 | hook_buf(unsigned i) | ||
78 | { | ||
79 | return (HOOK_DATA(i)); | ||
80 | } | ||
81 | |||
82 | void print_str( const char *str ) { | ||
83 | int i; | ||
84 | for (i=1; str[i]; i++); /* find null at end of string */ | ||
85 | hook_call(hook_print_str, i, str); | ||
86 | } | ||
87 | |||
88 | // --------------------------------------------------------------- CPU_KICK_DOG | ||
89 | void CPU_KICK_DOG(void) { | ||
90 | (void) hook_call( hook_kick_dog, 0 ); | ||
91 | } | ||
92 | |||
93 | // ------------------------------------------------------- CPU_WATCHDOG_TIMEOUT | ||
94 | void CPU_WATCHDOG_TIMEOUT( unsigned t ) { | ||
95 | (void) hook_call( hook_dog_timeout, 1, t ); | ||
96 | } | ||
diff --git a/arch/cris/arch-v32/kernel/vcs_hook.h b/arch/cris/arch-v32/kernel/vcs_hook.h deleted file mode 100644 index 7d73709e3cc6..000000000000 --- a/arch/cris/arch-v32/kernel/vcs_hook.h +++ /dev/null | |||
@@ -1,42 +0,0 @@ | |||
1 | // $Id: vcs_hook.h,v 1.1 2003/08/12 12:01:06 starvik Exp $ | ||
2 | // | ||
3 | // Call simulator hook functions | ||
4 | |||
5 | #ifndef HOOK_H | ||
6 | #define HOOK_H | ||
7 | |||
8 | int hook_call( unsigned id, unsigned pcnt, ...); | ||
9 | |||
10 | enum hook_ids { | ||
11 | hook_debug_on = 1, | ||
12 | hook_debug_off, | ||
13 | hook_stop_sim_ok, | ||
14 | hook_stop_sim_fail, | ||
15 | hook_alloc_shared, | ||
16 | hook_ptr_shared, | ||
17 | hook_free_shared, | ||
18 | hook_file2shared, | ||
19 | hook_cmp_shared, | ||
20 | hook_print_params, | ||
21 | hook_sim_time, | ||
22 | hook_stop_sim, | ||
23 | hook_kick_dog, | ||
24 | hook_dog_timeout, | ||
25 | hook_rand, | ||
26 | hook_srand, | ||
27 | hook_rand_range, | ||
28 | hook_print_str, | ||
29 | hook_print_hex, | ||
30 | hook_cmp_offset_shared, | ||
31 | hook_fill_random_shared, | ||
32 | hook_alloc_random_data, | ||
33 | hook_calloc_random_data, | ||
34 | hook_print_int, | ||
35 | hook_print_uint, | ||
36 | hook_fputc, | ||
37 | hook_init_fd, | ||
38 | hook_sbrk | ||
39 | |||
40 | }; | ||
41 | |||
42 | #endif | ||