diff options
Diffstat (limited to 'arch/cris/arch-v10/kernel')
-rw-r--r-- | arch/cris/arch-v10/kernel/Makefile | 5 | ||||
-rw-r--r-- | arch/cris/arch-v10/kernel/debugport.c | 273 | ||||
-rw-r--r-- | arch/cris/arch-v10/kernel/dma.c | 287 | ||||
-rw-r--r-- | arch/cris/arch-v10/kernel/entry.S | 54 | ||||
-rw-r--r-- | arch/cris/arch-v10/kernel/fasttimer.c | 55 | ||||
-rw-r--r-- | arch/cris/arch-v10/kernel/head.S | 126 | ||||
-rw-r--r-- | arch/cris/arch-v10/kernel/io_interface_mux.c | 879 | ||||
-rw-r--r-- | arch/cris/arch-v10/kernel/irq.c | 76 | ||||
-rw-r--r-- | arch/cris/arch-v10/kernel/kgdb.c | 17 | ||||
-rw-r--r-- | arch/cris/arch-v10/kernel/process.c | 3 | ||||
-rw-r--r-- | arch/cris/arch-v10/kernel/ptrace.c | 9 | ||||
-rw-r--r-- | arch/cris/arch-v10/kernel/shadows.c | 3 | ||||
-rw-r--r-- | arch/cris/arch-v10/kernel/traps.c | 37 |
13 files changed, 1574 insertions, 250 deletions
diff --git a/arch/cris/arch-v10/kernel/Makefile b/arch/cris/arch-v10/kernel/Makefile index 52761603b6a5..dcfec41d3533 100644 --- a/arch/cris/arch-v10/kernel/Makefile +++ b/arch/cris/arch-v10/kernel/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | # $Id: Makefile,v 1.5 2004/06/02 08:24:38 starvik Exp $ | 1 | # $Id: Makefile,v 1.6 2004/12/13 12:21:51 starvik Exp $ |
2 | # | 2 | # |
3 | # Makefile for the linux kernel. | 3 | # Makefile for the linux kernel. |
4 | # | 4 | # |
@@ -7,7 +7,8 @@ extra-y := head.o | |||
7 | 7 | ||
8 | 8 | ||
9 | obj-y := entry.o traps.o shadows.o debugport.o irq.o \ | 9 | obj-y := entry.o traps.o shadows.o debugport.o irq.o \ |
10 | process.o setup.o signal.o traps.o time.o ptrace.o | 10 | process.o setup.o signal.o traps.o time.o ptrace.o \ |
11 | dma.o io_interface_mux.o | ||
11 | 12 | ||
12 | obj-$(CONFIG_ETRAX_KGDB) += kgdb.o | 13 | obj-$(CONFIG_ETRAX_KGDB) += kgdb.o |
13 | obj-$(CONFIG_ETRAX_FAST_TIMER) += fasttimer.o | 14 | obj-$(CONFIG_ETRAX_FAST_TIMER) += fasttimer.o |
diff --git a/arch/cris/arch-v10/kernel/debugport.c b/arch/cris/arch-v10/kernel/debugport.c index 6cf069e5e7b6..f3a85b77c17e 100644 --- a/arch/cris/arch-v10/kernel/debugport.c +++ b/arch/cris/arch-v10/kernel/debugport.c | |||
@@ -12,6 +12,31 @@ | |||
12 | * init_etrax_debug() | 12 | * init_etrax_debug() |
13 | * | 13 | * |
14 | * $Log: debugport.c,v $ | 14 | * $Log: debugport.c,v $ |
15 | * Revision 1.27 2005/06/10 10:34:14 starvik | ||
16 | * Real console support | ||
17 | * | ||
18 | * Revision 1.26 2005/06/07 07:06:07 starvik | ||
19 | * Added LF->CR translation to make ETRAX customers happy. | ||
20 | * | ||
21 | * Revision 1.25 2005/03/08 08:56:47 mikaelam | ||
22 | * Do only set index as port->index if port is defined, otherwise use the index from the command line | ||
23 | * | ||
24 | * Revision 1.24 2005/01/19 10:26:33 mikaelam | ||
25 | * Return the cris serial driver in console device driver callback function | ||
26 | * | ||
27 | * Revision 1.23 2005/01/14 10:12:17 starvik | ||
28 | * KGDB on separate port. | ||
29 | * Console fixes from 2.4. | ||
30 | * | ||
31 | * Revision 1.22 2005/01/11 16:06:13 starvik | ||
32 | * typo | ||
33 | * | ||
34 | * Revision 1.21 2005/01/11 13:49:14 starvik | ||
35 | * Added raw_printk to be used where we don't trust the console. | ||
36 | * | ||
37 | * Revision 1.20 2004/12/27 11:18:32 starvik | ||
38 | * Merge of Linux 2.6.10 (not functional yet). | ||
39 | * | ||
15 | * Revision 1.19 2004/10/21 07:26:16 starvik | 40 | * Revision 1.19 2004/10/21 07:26:16 starvik |
16 | * Made it possible to specify console settings on kernel command line. | 41 | * Made it possible to specify console settings on kernel command line. |
17 | * | 42 | * |
@@ -114,7 +139,11 @@ struct dbg_port ports[]= | |||
114 | R_SERIAL0_BAUD, | 139 | R_SERIAL0_BAUD, |
115 | R_SERIAL0_TR_CTRL, | 140 | R_SERIAL0_TR_CTRL, |
116 | R_SERIAL0_REC_CTRL, | 141 | R_SERIAL0_REC_CTRL, |
117 | IO_STATE(R_IRQ_MASK1_SET, ser0_data, set) | 142 | IO_STATE(R_IRQ_MASK1_SET, ser0_data, set), |
143 | 0, | ||
144 | 115200, | ||
145 | 'N', | ||
146 | 8 | ||
118 | }, | 147 | }, |
119 | { | 148 | { |
120 | 1, | 149 | 1, |
@@ -124,7 +153,11 @@ struct dbg_port ports[]= | |||
124 | R_SERIAL1_BAUD, | 153 | R_SERIAL1_BAUD, |
125 | R_SERIAL1_TR_CTRL, | 154 | R_SERIAL1_TR_CTRL, |
126 | R_SERIAL1_REC_CTRL, | 155 | R_SERIAL1_REC_CTRL, |
127 | IO_STATE(R_IRQ_MASK1_SET, ser1_data, set) | 156 | IO_STATE(R_IRQ_MASK1_SET, ser1_data, set), |
157 | 0, | ||
158 | 115200, | ||
159 | 'N', | ||
160 | 8 | ||
128 | }, | 161 | }, |
129 | { | 162 | { |
130 | 2, | 163 | 2, |
@@ -134,7 +167,11 @@ struct dbg_port ports[]= | |||
134 | R_SERIAL2_BAUD, | 167 | R_SERIAL2_BAUD, |
135 | R_SERIAL2_TR_CTRL, | 168 | R_SERIAL2_TR_CTRL, |
136 | R_SERIAL2_REC_CTRL, | 169 | R_SERIAL2_REC_CTRL, |
137 | IO_STATE(R_IRQ_MASK1_SET, ser2_data, set) | 170 | IO_STATE(R_IRQ_MASK1_SET, ser2_data, set), |
171 | 0, | ||
172 | 115200, | ||
173 | 'N', | ||
174 | 8 | ||
138 | }, | 175 | }, |
139 | { | 176 | { |
140 | 3, | 177 | 3, |
@@ -144,11 +181,15 @@ struct dbg_port ports[]= | |||
144 | R_SERIAL3_BAUD, | 181 | R_SERIAL3_BAUD, |
145 | R_SERIAL3_TR_CTRL, | 182 | R_SERIAL3_TR_CTRL, |
146 | R_SERIAL3_REC_CTRL, | 183 | R_SERIAL3_REC_CTRL, |
147 | IO_STATE(R_IRQ_MASK1_SET, ser3_data, set) | 184 | IO_STATE(R_IRQ_MASK1_SET, ser3_data, set), |
185 | 0, | ||
186 | 115200, | ||
187 | 'N', | ||
188 | 8 | ||
148 | } | 189 | } |
149 | }; | 190 | }; |
150 | 191 | ||
151 | static struct tty_driver *serial_driver; | 192 | extern struct tty_driver *serial_driver; |
152 | 193 | ||
153 | struct dbg_port* port = | 194 | struct dbg_port* port = |
154 | #if defined(CONFIG_ETRAX_DEBUG_PORT0) | 195 | #if defined(CONFIG_ETRAX_DEBUG_PORT0) |
@@ -162,37 +203,44 @@ struct dbg_port* port = | |||
162 | #else | 203 | #else |
163 | NULL; | 204 | NULL; |
164 | #endif | 205 | #endif |
165 | /* Used by serial.c to register a debug_write_function so that the normal | ||
166 | * serial driver is used for kernel debug output | ||
167 | */ | ||
168 | typedef int (*debugport_write_function)(int i, const char *buf, unsigned int len); | ||
169 | 206 | ||
170 | debugport_write_function debug_write_function = NULL; | 207 | static struct dbg_port* kgdb_port = |
208 | #if defined(CONFIG_ETRAX_KGDB_PORT0) | ||
209 | &ports[0]; | ||
210 | #elif defined(CONFIG_ETRAX_KGDB_PORT1) | ||
211 | &ports[1]; | ||
212 | #elif defined(CONFIG_ETRAX_KGDB_PORT2) | ||
213 | &ports[2]; | ||
214 | #elif defined(CONFIG_ETRAX_KGDB_PORT3) | ||
215 | &ports[3]; | ||
216 | #else | ||
217 | NULL; | ||
218 | #endif | ||
171 | 219 | ||
172 | static void | 220 | static void |
173 | start_port(void) | 221 | start_port(struct dbg_port* p) |
174 | { | 222 | { |
175 | unsigned long rec_ctrl = 0; | 223 | unsigned long rec_ctrl = 0; |
176 | unsigned long tr_ctrl = 0; | 224 | unsigned long tr_ctrl = 0; |
177 | 225 | ||
178 | if (!port) | 226 | if (!p) |
179 | return; | 227 | return; |
180 | 228 | ||
181 | if (port->started) | 229 | if (p->started) |
182 | return; | 230 | return; |
183 | port->started = 1; | 231 | p->started = 1; |
184 | 232 | ||
185 | if (port->index == 0) | 233 | if (p->index == 0) |
186 | { | 234 | { |
187 | genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma6); | 235 | genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma6); |
188 | genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma6, unused); | 236 | genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma6, unused); |
189 | } | 237 | } |
190 | else if (port->index == 1) | 238 | else if (p->index == 1) |
191 | { | 239 | { |
192 | genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma8); | 240 | genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma8); |
193 | genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma8, usb); | 241 | genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma8, usb); |
194 | } | 242 | } |
195 | else if (port->index == 2) | 243 | else if (p->index == 2) |
196 | { | 244 | { |
197 | genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma2); | 245 | genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma2); |
198 | genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma2, par0); | 246 | genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma2, par0); |
@@ -211,69 +259,69 @@ start_port(void) | |||
211 | 259 | ||
212 | *R_GEN_CONFIG = genconfig_shadow; | 260 | *R_GEN_CONFIG = genconfig_shadow; |
213 | 261 | ||
214 | *port->xoff = | 262 | *p->xoff = |
215 | IO_STATE(R_SERIAL0_XOFF, tx_stop, enable) | | 263 | IO_STATE(R_SERIAL0_XOFF, tx_stop, enable) | |
216 | IO_STATE(R_SERIAL0_XOFF, auto_xoff, disable) | | 264 | IO_STATE(R_SERIAL0_XOFF, auto_xoff, disable) | |
217 | IO_FIELD(R_SERIAL0_XOFF, xoff_char, 0); | 265 | IO_FIELD(R_SERIAL0_XOFF, xoff_char, 0); |
218 | 266 | ||
219 | switch (port->baudrate) | 267 | switch (p->baudrate) |
220 | { | 268 | { |
221 | case 0: | 269 | case 0: |
222 | case 115200: | 270 | case 115200: |
223 | *port->baud = | 271 | *p->baud = |
224 | IO_STATE(R_SERIAL0_BAUD, tr_baud, c115k2Hz) | | 272 | IO_STATE(R_SERIAL0_BAUD, tr_baud, c115k2Hz) | |
225 | IO_STATE(R_SERIAL0_BAUD, rec_baud, c115k2Hz); | 273 | IO_STATE(R_SERIAL0_BAUD, rec_baud, c115k2Hz); |
226 | break; | 274 | break; |
227 | case 1200: | 275 | case 1200: |
228 | *port->baud = | 276 | *p->baud = |
229 | IO_STATE(R_SERIAL0_BAUD, tr_baud, c1200Hz) | | 277 | IO_STATE(R_SERIAL0_BAUD, tr_baud, c1200Hz) | |
230 | IO_STATE(R_SERIAL0_BAUD, rec_baud, c1200Hz); | 278 | IO_STATE(R_SERIAL0_BAUD, rec_baud, c1200Hz); |
231 | break; | 279 | break; |
232 | case 2400: | 280 | case 2400: |
233 | *port->baud = | 281 | *p->baud = |
234 | IO_STATE(R_SERIAL0_BAUD, tr_baud, c2400Hz) | | 282 | IO_STATE(R_SERIAL0_BAUD, tr_baud, c2400Hz) | |
235 | IO_STATE(R_SERIAL0_BAUD, rec_baud, c2400Hz); | 283 | IO_STATE(R_SERIAL0_BAUD, rec_baud, c2400Hz); |
236 | break; | 284 | break; |
237 | case 4800: | 285 | case 4800: |
238 | *port->baud = | 286 | *p->baud = |
239 | IO_STATE(R_SERIAL0_BAUD, tr_baud, c4800Hz) | | 287 | IO_STATE(R_SERIAL0_BAUD, tr_baud, c4800Hz) | |
240 | IO_STATE(R_SERIAL0_BAUD, rec_baud, c4800Hz); | 288 | IO_STATE(R_SERIAL0_BAUD, rec_baud, c4800Hz); |
241 | break; | 289 | break; |
242 | case 9600: | 290 | case 9600: |
243 | *port->baud = | 291 | *p->baud = |
244 | IO_STATE(R_SERIAL0_BAUD, tr_baud, c9600Hz) | | 292 | IO_STATE(R_SERIAL0_BAUD, tr_baud, c9600Hz) | |
245 | IO_STATE(R_SERIAL0_BAUD, rec_baud, c9600Hz); | 293 | IO_STATE(R_SERIAL0_BAUD, rec_baud, c9600Hz); |
246 | break; | 294 | break; |
247 | case 19200: | 295 | case 19200: |
248 | *port->baud = | 296 | *p->baud = |
249 | IO_STATE(R_SERIAL0_BAUD, tr_baud, c19k2Hz) | | 297 | IO_STATE(R_SERIAL0_BAUD, tr_baud, c19k2Hz) | |
250 | IO_STATE(R_SERIAL0_BAUD, rec_baud, c19k2Hz); | 298 | IO_STATE(R_SERIAL0_BAUD, rec_baud, c19k2Hz); |
251 | break; | 299 | break; |
252 | case 38400: | 300 | case 38400: |
253 | *port->baud = | 301 | *p->baud = |
254 | IO_STATE(R_SERIAL0_BAUD, tr_baud, c38k4Hz) | | 302 | IO_STATE(R_SERIAL0_BAUD, tr_baud, c38k4Hz) | |
255 | IO_STATE(R_SERIAL0_BAUD, rec_baud, c38k4Hz); | 303 | IO_STATE(R_SERIAL0_BAUD, rec_baud, c38k4Hz); |
256 | break; | 304 | break; |
257 | case 57600: | 305 | case 57600: |
258 | *port->baud = | 306 | *p->baud = |
259 | IO_STATE(R_SERIAL0_BAUD, tr_baud, c57k6Hz) | | 307 | IO_STATE(R_SERIAL0_BAUD, tr_baud, c57k6Hz) | |
260 | IO_STATE(R_SERIAL0_BAUD, rec_baud, c57k6Hz); | 308 | IO_STATE(R_SERIAL0_BAUD, rec_baud, c57k6Hz); |
261 | break; | 309 | break; |
262 | default: | 310 | default: |
263 | *port->baud = | 311 | *p->baud = |
264 | IO_STATE(R_SERIAL0_BAUD, tr_baud, c115k2Hz) | | 312 | IO_STATE(R_SERIAL0_BAUD, tr_baud, c115k2Hz) | |
265 | IO_STATE(R_SERIAL0_BAUD, rec_baud, c115k2Hz); | 313 | IO_STATE(R_SERIAL0_BAUD, rec_baud, c115k2Hz); |
266 | break; | 314 | break; |
267 | } | 315 | } |
268 | 316 | ||
269 | if (port->parity == 'E') { | 317 | if (p->parity == 'E') { |
270 | rec_ctrl = | 318 | rec_ctrl = |
271 | IO_STATE(R_SERIAL0_REC_CTRL, rec_par, even) | | 319 | IO_STATE(R_SERIAL0_REC_CTRL, rec_par, even) | |
272 | IO_STATE(R_SERIAL0_REC_CTRL, rec_par_en, enable); | 320 | IO_STATE(R_SERIAL0_REC_CTRL, rec_par_en, enable); |
273 | tr_ctrl = | 321 | tr_ctrl = |
274 | IO_STATE(R_SERIAL0_TR_CTRL, tr_par, even) | | 322 | IO_STATE(R_SERIAL0_TR_CTRL, tr_par, even) | |
275 | IO_STATE(R_SERIAL0_TR_CTRL, tr_par_en, enable); | 323 | IO_STATE(R_SERIAL0_TR_CTRL, tr_par_en, enable); |
276 | } else if (port->parity == 'O') { | 324 | } else if (p->parity == 'O') { |
277 | rec_ctrl = | 325 | rec_ctrl = |
278 | IO_STATE(R_SERIAL0_REC_CTRL, rec_par, odd) | | 326 | IO_STATE(R_SERIAL0_REC_CTRL, rec_par, odd) | |
279 | IO_STATE(R_SERIAL0_REC_CTRL, rec_par_en, enable); | 327 | IO_STATE(R_SERIAL0_REC_CTRL, rec_par_en, enable); |
@@ -288,8 +336,7 @@ start_port(void) | |||
288 | IO_STATE(R_SERIAL0_TR_CTRL, tr_par, even) | | 336 | IO_STATE(R_SERIAL0_TR_CTRL, tr_par, even) | |
289 | IO_STATE(R_SERIAL0_TR_CTRL, tr_par_en, disable); | 337 | IO_STATE(R_SERIAL0_TR_CTRL, tr_par_en, disable); |
290 | } | 338 | } |
291 | 339 | if (p->bits == 7) | |
292 | if (port->bits == 7) | ||
293 | { | 340 | { |
294 | rec_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_bitnr, rec_7bit); | 341 | rec_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_bitnr, rec_7bit); |
295 | tr_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_bitnr, tr_7bit); | 342 | tr_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_bitnr, tr_7bit); |
@@ -300,7 +347,7 @@ start_port(void) | |||
300 | tr_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_bitnr, tr_8bit); | 347 | tr_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_bitnr, tr_8bit); |
301 | } | 348 | } |
302 | 349 | ||
303 | *port->rec_ctrl = | 350 | *p->rec_ctrl = |
304 | IO_STATE(R_SERIAL0_REC_CTRL, dma_err, stop) | | 351 | IO_STATE(R_SERIAL0_REC_CTRL, dma_err, stop) | |
305 | IO_STATE(R_SERIAL0_REC_CTRL, rec_enable, enable) | | 352 | IO_STATE(R_SERIAL0_REC_CTRL, rec_enable, enable) | |
306 | IO_STATE(R_SERIAL0_REC_CTRL, rts_, active) | | 353 | IO_STATE(R_SERIAL0_REC_CTRL, rts_, active) | |
@@ -308,7 +355,7 @@ start_port(void) | |||
308 | IO_STATE(R_SERIAL0_REC_CTRL, rec_stick_par, normal) | | 355 | IO_STATE(R_SERIAL0_REC_CTRL, rec_stick_par, normal) | |
309 | rec_ctrl; | 356 | rec_ctrl; |
310 | 357 | ||
311 | *port->tr_ctrl = | 358 | *p->tr_ctrl = |
312 | IO_FIELD(R_SERIAL0_TR_CTRL, txd, 0) | | 359 | IO_FIELD(R_SERIAL0_TR_CTRL, txd, 0) | |
313 | IO_STATE(R_SERIAL0_TR_CTRL, tr_enable, enable) | | 360 | IO_STATE(R_SERIAL0_TR_CTRL, tr_enable, enable) | |
314 | IO_STATE(R_SERIAL0_TR_CTRL, auto_cts, disabled) | | 361 | IO_STATE(R_SERIAL0_TR_CTRL, auto_cts, disabled) | |
@@ -323,8 +370,18 @@ console_write_direct(struct console *co, const char *buf, unsigned int len) | |||
323 | int i; | 370 | int i; |
324 | unsigned long flags; | 371 | unsigned long flags; |
325 | local_irq_save(flags); | 372 | local_irq_save(flags); |
373 | |||
374 | if (!port) | ||
375 | return; | ||
376 | |||
326 | /* Send data */ | 377 | /* Send data */ |
327 | for (i = 0; i < len; i++) { | 378 | for (i = 0; i < len; i++) { |
379 | /* LF -> CRLF */ | ||
380 | if (buf[i] == '\n') { | ||
381 | while (!(*port->read & IO_MASK(R_SERIAL0_READ, tr_ready))) | ||
382 | ; | ||
383 | *port->write = '\r'; | ||
384 | } | ||
328 | /* Wait until transmitter is ready and send.*/ | 385 | /* Wait until transmitter is ready and send.*/ |
329 | while (!(*port->read & IO_MASK(R_SERIAL0_READ, tr_ready))) | 386 | while (!(*port->read & IO_MASK(R_SERIAL0_READ, tr_ready))) |
330 | ; | 387 | ; |
@@ -333,6 +390,25 @@ console_write_direct(struct console *co, const char *buf, unsigned int len) | |||
333 | local_irq_restore(flags); | 390 | local_irq_restore(flags); |
334 | } | 391 | } |
335 | 392 | ||
393 | int raw_printk(const char *fmt, ...) | ||
394 | { | ||
395 | static char buf[1024]; | ||
396 | int printed_len; | ||
397 | static int first = 1; | ||
398 | if (first) { | ||
399 | /* Force reinitialization of the port to get manual mode. */ | ||
400 | port->started = 0; | ||
401 | start_port(port); | ||
402 | first = 0; | ||
403 | } | ||
404 | va_list args; | ||
405 | va_start(args, fmt); | ||
406 | printed_len = vsnprintf(buf, sizeof(buf), fmt, args); | ||
407 | va_end(args); | ||
408 | console_write_direct(NULL, buf, strlen(buf)); | ||
409 | return printed_len; | ||
410 | } | ||
411 | |||
336 | static void | 412 | static void |
337 | console_write(struct console *co, const char *buf, unsigned int len) | 413 | console_write(struct console *co, const char *buf, unsigned int len) |
338 | { | 414 | { |
@@ -345,18 +421,7 @@ console_write(struct console *co, const char *buf, unsigned int len) | |||
345 | return; | 421 | return; |
346 | #endif | 422 | #endif |
347 | 423 | ||
348 | start_port(); | 424 | console_write_direct(co, buf, len); |
349 | |||
350 | #ifdef CONFIG_ETRAX_KGDB | ||
351 | /* kgdb needs to output debug info using the gdb protocol */ | ||
352 | putDebugString(buf, len); | ||
353 | return; | ||
354 | #endif | ||
355 | |||
356 | if (debug_write_function) | ||
357 | debug_write_function(co->index, buf, len); | ||
358 | else | ||
359 | console_write_direct(co, buf, len); | ||
360 | } | 425 | } |
361 | 426 | ||
362 | /* legacy function */ | 427 | /* legacy function */ |
@@ -374,8 +439,11 @@ getDebugChar(void) | |||
374 | { | 439 | { |
375 | unsigned long readval; | 440 | unsigned long readval; |
376 | 441 | ||
442 | if (!kgdb_port) | ||
443 | return 0; | ||
444 | |||
377 | do { | 445 | do { |
378 | readval = *port->read; | 446 | readval = *kgdb_port->read; |
379 | } while (!(readval & IO_MASK(R_SERIAL0_READ, data_avail))); | 447 | } while (!(readval & IO_MASK(R_SERIAL0_READ, data_avail))); |
380 | 448 | ||
381 | return (readval & IO_MASK(R_SERIAL0_READ, data_in)); | 449 | return (readval & IO_MASK(R_SERIAL0_READ, data_in)); |
@@ -386,9 +454,12 @@ getDebugChar(void) | |||
386 | void | 454 | void |
387 | putDebugChar(int val) | 455 | putDebugChar(int val) |
388 | { | 456 | { |
389 | while (!(*port->read & IO_MASK(R_SERIAL0_READ, tr_ready))) | 457 | if (!kgdb_port) |
458 | return; | ||
459 | |||
460 | while (!(*kgdb_port->read & IO_MASK(R_SERIAL0_READ, tr_ready))) | ||
390 | ; | 461 | ; |
391 | *port->write = val; | 462 | *kgdb_port->write = val; |
392 | } | 463 | } |
393 | 464 | ||
394 | /* Enable irq for receiving chars on the debug port, used by kgdb */ | 465 | /* Enable irq for receiving chars on the debug port, used by kgdb */ |
@@ -396,19 +467,16 @@ putDebugChar(int val) | |||
396 | void | 467 | void |
397 | enableDebugIRQ(void) | 468 | enableDebugIRQ(void) |
398 | { | 469 | { |
399 | *R_IRQ_MASK1_SET = port->irq; | 470 | if (!kgdb_port) |
471 | return; | ||
472 | |||
473 | *R_IRQ_MASK1_SET = kgdb_port->irq; | ||
400 | /* use R_VECT_MASK directly, since we really bypass Linux normal | 474 | /* use R_VECT_MASK directly, since we really bypass Linux normal |
401 | * IRQ handling in kgdb anyway, we don't need to use enable_irq | 475 | * IRQ handling in kgdb anyway, we don't need to use enable_irq |
402 | */ | 476 | */ |
403 | *R_VECT_MASK_SET = IO_STATE(R_VECT_MASK_SET, serial, set); | 477 | *R_VECT_MASK_SET = IO_STATE(R_VECT_MASK_SET, serial, set); |
404 | 478 | ||
405 | *port->rec_ctrl = IO_STATE(R_SERIAL0_REC_CTRL, rec_enable, enable); | 479 | *kgdb_port->rec_ctrl = IO_STATE(R_SERIAL0_REC_CTRL, rec_enable, enable); |
406 | } | ||
407 | |||
408 | static struct tty_driver* | ||
409 | etrax_console_device(struct console* co, int *index) | ||
410 | { | ||
411 | return serial_driver; | ||
412 | } | 480 | } |
413 | 481 | ||
414 | static int __init | 482 | static int __init |
@@ -428,11 +496,69 @@ console_setup(struct console *co, char *options) | |||
428 | if (*s) port->parity = *s++; | 496 | if (*s) port->parity = *s++; |
429 | if (*s) port->bits = *s++ - '0'; | 497 | if (*s) port->bits = *s++ - '0'; |
430 | port->started = 0; | 498 | port->started = 0; |
431 | start_port(); | 499 | start_port(0); |
432 | } | 500 | } |
433 | return 0; | 501 | return 0; |
434 | } | 502 | } |
435 | 503 | ||
504 | /* This is a dummy serial device that throws away anything written to it. | ||
505 | * This is used when no debug output is wanted. | ||
506 | */ | ||
507 | static struct tty_driver dummy_driver; | ||
508 | |||
509 | static int dummy_open(struct tty_struct *tty, struct file * filp) | ||
510 | { | ||
511 | return 0; | ||
512 | } | ||
513 | |||
514 | static void dummy_close(struct tty_struct *tty, struct file * filp) | ||
515 | { | ||
516 | } | ||
517 | |||
518 | static int dummy_write(struct tty_struct * tty, | ||
519 | const unsigned char *buf, int count) | ||
520 | { | ||
521 | return count; | ||
522 | } | ||
523 | |||
524 | static int | ||
525 | dummy_write_room(struct tty_struct *tty) | ||
526 | { | ||
527 | return 8192; | ||
528 | } | ||
529 | |||
530 | void __init | ||
531 | init_dummy_console(void) | ||
532 | { | ||
533 | memset(&dummy_driver, 0, sizeof(struct tty_driver)); | ||
534 | dummy_driver.driver_name = "serial"; | ||
535 | dummy_driver.name = "ttyS"; | ||
536 | dummy_driver.major = TTY_MAJOR; | ||
537 | dummy_driver.minor_start = 68; | ||
538 | dummy_driver.num = 1; /* etrax100 has 4 serial ports */ | ||
539 | dummy_driver.type = TTY_DRIVER_TYPE_SERIAL; | ||
540 | dummy_driver.subtype = SERIAL_TYPE_NORMAL; | ||
541 | dummy_driver.init_termios = tty_std_termios; | ||
542 | dummy_driver.init_termios.c_cflag = | ||
543 | B115200 | CS8 | CREAD | HUPCL | CLOCAL; /* is normally B9600 default... */ | ||
544 | dummy_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS; | ||
545 | |||
546 | dummy_driver.open = dummy_open; | ||
547 | dummy_driver.close = dummy_close; | ||
548 | dummy_driver.write = dummy_write; | ||
549 | dummy_driver.write_room = dummy_write_room; | ||
550 | if (tty_register_driver(&dummy_driver)) | ||
551 | panic("Couldn't register dummy serial driver\n"); | ||
552 | } | ||
553 | |||
554 | static struct tty_driver* | ||
555 | etrax_console_device(struct console* co, int *index) | ||
556 | { | ||
557 | if (port) | ||
558 | *index = port->index; | ||
559 | return port ? serial_driver : &dummy_driver; | ||
560 | } | ||
561 | |||
436 | static struct console sercons = { | 562 | static struct console sercons = { |
437 | name : "ttyS", | 563 | name : "ttyS", |
438 | write: console_write, | 564 | write: console_write, |
@@ -504,28 +630,21 @@ init_etrax_debug(void) | |||
504 | static int first = 1; | 630 | static int first = 1; |
505 | 631 | ||
506 | if (!first) { | 632 | if (!first) { |
507 | if (!port) { | 633 | unregister_console(&sercons); |
508 | register_console(&sercons0); | 634 | register_console(&sercons0); |
509 | register_console(&sercons1); | 635 | register_console(&sercons1); |
510 | register_console(&sercons2); | 636 | register_console(&sercons2); |
511 | register_console(&sercons3); | 637 | register_console(&sercons3); |
512 | unregister_console(&sercons); | 638 | init_dummy_console(); |
513 | } | ||
514 | return 0; | 639 | return 0; |
515 | } | 640 | } |
516 | first = 0; | ||
517 | if (port) | ||
518 | register_console(&sercons); | ||
519 | return 0; | ||
520 | } | ||
521 | 641 | ||
522 | int __init | 642 | first = 0; |
523 | init_console(void) | 643 | register_console(&sercons); |
524 | { | 644 | start_port(port); |
525 | serial_driver = alloc_tty_driver(1); | 645 | #ifdef CONFIG_ETRAX_KGDB |
526 | if (!serial_driver) | 646 | start_port(kgdb_port); |
527 | return -ENOMEM; | 647 | #endif |
528 | return 0; | 648 | return 0; |
529 | } | 649 | } |
530 | |||
531 | __initcall(init_etrax_debug); | 650 | __initcall(init_etrax_debug); |
diff --git a/arch/cris/arch-v10/kernel/dma.c b/arch/cris/arch-v10/kernel/dma.c new file mode 100644 index 000000000000..e9a0311b141d --- /dev/null +++ b/arch/cris/arch-v10/kernel/dma.c | |||
@@ -0,0 +1,287 @@ | |||
1 | /* Wrapper for DMA channel allocator that updates DMA client muxing. | ||
2 | * Copyright 2004, Axis Communications AB | ||
3 | * $Id: dma.c,v 1.1 2004/12/13 12:21:51 starvik Exp $ | ||
4 | */ | ||
5 | |||
6 | #include <linux/kernel.h> | ||
7 | #include <linux/module.h> | ||
8 | #include <linux/errno.h> | ||
9 | |||
10 | #include <asm/dma.h> | ||
11 | #include <asm/arch/svinto.h> | ||
12 | |||
13 | /* Macro to access ETRAX 100 registers */ | ||
14 | #define SETS(var, reg, field, val) var = (var & ~IO_MASK_(reg##_, field##_)) | \ | ||
15 | IO_STATE_(reg##_, field##_, _##val) | ||
16 | |||
17 | |||
18 | static char used_dma_channels[MAX_DMA_CHANNELS]; | ||
19 | static const char * used_dma_channels_users[MAX_DMA_CHANNELS]; | ||
20 | |||
21 | int cris_request_dma(unsigned int dmanr, const char * device_id, | ||
22 | unsigned options, enum dma_owner owner) | ||
23 | { | ||
24 | unsigned long flags; | ||
25 | unsigned long int gens; | ||
26 | int fail = -EINVAL; | ||
27 | |||
28 | if ((dmanr < 0) || (dmanr >= MAX_DMA_CHANNELS)) { | ||
29 | printk(KERN_CRIT "cris_request_dma: invalid DMA channel %u\n", dmanr); | ||
30 | return -EINVAL; | ||
31 | } | ||
32 | |||
33 | local_irq_save(flags); | ||
34 | if (used_dma_channels[dmanr]) { | ||
35 | local_irq_restore(flags); | ||
36 | if (options & DMA_VERBOSE_ON_ERROR) { | ||
37 | printk(KERN_CRIT "Failed to request DMA %i for %s, already allocated by %s\n", dmanr, device_id, used_dma_channels_users[dmanr]); | ||
38 | } | ||
39 | if (options & DMA_PANIC_ON_ERROR) { | ||
40 | panic("request_dma error!"); | ||
41 | } | ||
42 | return -EBUSY; | ||
43 | } | ||
44 | |||
45 | gens = genconfig_shadow; | ||
46 | |||
47 | switch(owner) | ||
48 | { | ||
49 | case dma_eth: | ||
50 | if ((dmanr != NETWORK_TX_DMA_NBR) && | ||
51 | (dmanr != NETWORK_RX_DMA_NBR)) { | ||
52 | printk(KERN_CRIT "Invalid DMA channel for eth\n"); | ||
53 | goto bail; | ||
54 | } | ||
55 | break; | ||
56 | case dma_ser0: | ||
57 | if (dmanr == SER0_TX_DMA_NBR) { | ||
58 | SETS(gens, R_GEN_CONFIG, dma6, serial0); | ||
59 | } else if (dmanr == SER0_RX_DMA_NBR) { | ||
60 | SETS(gens, R_GEN_CONFIG, dma7, serial0); | ||
61 | } else { | ||
62 | printk(KERN_CRIT "Invalid DMA channel for ser0\n"); | ||
63 | goto bail; | ||
64 | } | ||
65 | break; | ||
66 | case dma_ser1: | ||
67 | if (dmanr == SER1_TX_DMA_NBR) { | ||
68 | SETS(gens, R_GEN_CONFIG, dma8, serial1); | ||
69 | } else if (dmanr == SER1_RX_DMA_NBR) { | ||
70 | SETS(gens, R_GEN_CONFIG, dma9, serial1); | ||
71 | } else { | ||
72 | printk(KERN_CRIT "Invalid DMA channel for ser1\n"); | ||
73 | goto bail; | ||
74 | } | ||
75 | break; | ||
76 | case dma_ser2: | ||
77 | if (dmanr == SER2_TX_DMA_NBR) { | ||
78 | SETS(gens, R_GEN_CONFIG, dma2, serial2); | ||
79 | } else if (dmanr == SER2_RX_DMA_NBR) { | ||
80 | SETS(gens, R_GEN_CONFIG, dma3, serial2); | ||
81 | } else { | ||
82 | printk(KERN_CRIT "Invalid DMA channel for ser2\n"); | ||
83 | goto bail; | ||
84 | } | ||
85 | break; | ||
86 | case dma_ser3: | ||
87 | if (dmanr == SER3_TX_DMA_NBR) { | ||
88 | SETS(gens, R_GEN_CONFIG, dma4, serial3); | ||
89 | } else if (dmanr == SER3_RX_DMA_NBR) { | ||
90 | SETS(gens, R_GEN_CONFIG, dma5, serial3); | ||
91 | } else { | ||
92 | printk(KERN_CRIT "Invalid DMA channel for ser3\n"); | ||
93 | goto bail; | ||
94 | } | ||
95 | break; | ||
96 | case dma_ata: | ||
97 | if (dmanr == ATA_TX_DMA_NBR) { | ||
98 | SETS(gens, R_GEN_CONFIG, dma2, ata); | ||
99 | } else if (dmanr == ATA_RX_DMA_NBR) { | ||
100 | SETS(gens, R_GEN_CONFIG, dma3, ata); | ||
101 | } else { | ||
102 | printk(KERN_CRIT "Invalid DMA channel for ata\n"); | ||
103 | goto bail; | ||
104 | } | ||
105 | break; | ||
106 | case dma_ext0: | ||
107 | if (dmanr == EXTDMA0_TX_DMA_NBR) { | ||
108 | SETS(gens, R_GEN_CONFIG, dma4, extdma0); | ||
109 | } else if (dmanr == EXTDMA0_RX_DMA_NBR) { | ||
110 | SETS(gens, R_GEN_CONFIG, dma5, extdma0); | ||
111 | } else { | ||
112 | printk(KERN_CRIT "Invalid DMA channel for ext0\n"); | ||
113 | goto bail; | ||
114 | } | ||
115 | break; | ||
116 | case dma_ext1: | ||
117 | if (dmanr == EXTDMA1_TX_DMA_NBR) { | ||
118 | SETS(gens, R_GEN_CONFIG, dma6, extdma1); | ||
119 | } else if (dmanr == EXTDMA1_RX_DMA_NBR) { | ||
120 | SETS(gens, R_GEN_CONFIG, dma7, extdma1); | ||
121 | } else { | ||
122 | printk(KERN_CRIT "Invalid DMA channel for ext1\n"); | ||
123 | goto bail; | ||
124 | } | ||
125 | break; | ||
126 | case dma_int6: | ||
127 | if (dmanr == MEM2MEM_RX_DMA_NBR) { | ||
128 | SETS(gens, R_GEN_CONFIG, dma7, intdma6); | ||
129 | } else { | ||
130 | printk(KERN_CRIT "Invalid DMA channel for int6\n"); | ||
131 | goto bail; | ||
132 | } | ||
133 | break; | ||
134 | case dma_int7: | ||
135 | if (dmanr == MEM2MEM_TX_DMA_NBR) { | ||
136 | SETS(gens, R_GEN_CONFIG, dma6, intdma7); | ||
137 | } else { | ||
138 | printk(KERN_CRIT "Invalid DMA channel for int7\n"); | ||
139 | goto bail; | ||
140 | } | ||
141 | break; | ||
142 | case dma_usb: | ||
143 | if (dmanr == USB_TX_DMA_NBR) { | ||
144 | SETS(gens, R_GEN_CONFIG, dma8, usb); | ||
145 | } else if (dmanr == USB_RX_DMA_NBR) { | ||
146 | SETS(gens, R_GEN_CONFIG, dma9, usb); | ||
147 | } else { | ||
148 | printk(KERN_CRIT "Invalid DMA channel for usb\n"); | ||
149 | goto bail; | ||
150 | } | ||
151 | break; | ||
152 | case dma_scsi0: | ||
153 | if (dmanr == SCSI0_TX_DMA_NBR) { | ||
154 | SETS(gens, R_GEN_CONFIG, dma2, scsi0); | ||
155 | } else if (dmanr == SCSI0_RX_DMA_NBR) { | ||
156 | SETS(gens, R_GEN_CONFIG, dma3, scsi0); | ||
157 | } else { | ||
158 | printk(KERN_CRIT "Invalid DMA channel for scsi0\n"); | ||
159 | goto bail; | ||
160 | } | ||
161 | break; | ||
162 | case dma_scsi1: | ||
163 | if (dmanr == SCSI1_TX_DMA_NBR) { | ||
164 | SETS(gens, R_GEN_CONFIG, dma4, scsi1); | ||
165 | } else if (dmanr == SCSI1_RX_DMA_NBR) { | ||
166 | SETS(gens, R_GEN_CONFIG, dma5, scsi1); | ||
167 | } else { | ||
168 | printk(KERN_CRIT "Invalid DMA channel for scsi1\n"); | ||
169 | goto bail; | ||
170 | } | ||
171 | break; | ||
172 | case dma_par0: | ||
173 | if (dmanr == PAR0_TX_DMA_NBR) { | ||
174 | SETS(gens, R_GEN_CONFIG, dma2, par0); | ||
175 | } else if (dmanr == PAR0_RX_DMA_NBR) { | ||
176 | SETS(gens, R_GEN_CONFIG, dma3, par0); | ||
177 | } else { | ||
178 | printk(KERN_CRIT "Invalid DMA channel for par0\n"); | ||
179 | goto bail; | ||
180 | } | ||
181 | break; | ||
182 | case dma_par1: | ||
183 | if (dmanr == PAR1_TX_DMA_NBR) { | ||
184 | SETS(gens, R_GEN_CONFIG, dma4, par1); | ||
185 | } else if (dmanr == PAR1_RX_DMA_NBR) { | ||
186 | SETS(gens, R_GEN_CONFIG, dma5, par1); | ||
187 | } else { | ||
188 | printk(KERN_CRIT "Invalid DMA channel for par1\n"); | ||
189 | goto bail; | ||
190 | } | ||
191 | break; | ||
192 | default: | ||
193 | printk(KERN_CRIT "Invalid DMA owner.\n"); | ||
194 | goto bail; | ||
195 | } | ||
196 | |||
197 | used_dma_channels[dmanr] = 1; | ||
198 | used_dma_channels_users[dmanr] = device_id; | ||
199 | |||
200 | { | ||
201 | volatile int i; | ||
202 | genconfig_shadow = gens; | ||
203 | *R_GEN_CONFIG = genconfig_shadow; | ||
204 | /* Wait 12 cycles before doing any DMA command */ | ||
205 | for(i = 6; i > 0; i--) | ||
206 | nop(); | ||
207 | } | ||
208 | fail = 0; | ||
209 | bail: | ||
210 | local_irq_restore(flags); | ||
211 | return fail; | ||
212 | } | ||
213 | |||
214 | void cris_free_dma(unsigned int dmanr, const char * device_id) | ||
215 | { | ||
216 | unsigned long flags; | ||
217 | if ((dmanr < 0) || (dmanr >= MAX_DMA_CHANNELS)) { | ||
218 | printk(KERN_CRIT "cris_free_dma: invalid DMA channel %u\n", dmanr); | ||
219 | return; | ||
220 | } | ||
221 | |||
222 | local_irq_save(flags); | ||
223 | if (!used_dma_channels[dmanr]) { | ||
224 | printk(KERN_CRIT "cris_free_dma: DMA channel %u not allocated\n", dmanr); | ||
225 | } else if (device_id != used_dma_channels_users[dmanr]) { | ||
226 | printk(KERN_CRIT "cris_free_dma: DMA channel %u not allocated by device\n", dmanr); | ||
227 | } else { | ||
228 | switch(dmanr) | ||
229 | { | ||
230 | case 0: | ||
231 | *R_DMA_CH0_CMD = IO_STATE(R_DMA_CH0_CMD, cmd, reset); | ||
232 | while (IO_EXTRACT(R_DMA_CH0_CMD, cmd, *R_DMA_CH0_CMD) == | ||
233 | IO_STATE_VALUE(R_DMA_CH0_CMD, cmd, reset)); | ||
234 | break; | ||
235 | case 1: | ||
236 | *R_DMA_CH1_CMD = IO_STATE(R_DMA_CH1_CMD, cmd, reset); | ||
237 | while (IO_EXTRACT(R_DMA_CH1_CMD, cmd, *R_DMA_CH1_CMD) == | ||
238 | IO_STATE_VALUE(R_DMA_CH1_CMD, cmd, reset)); | ||
239 | break; | ||
240 | case 2: | ||
241 | *R_DMA_CH2_CMD = IO_STATE(R_DMA_CH2_CMD, cmd, reset); | ||
242 | while (IO_EXTRACT(R_DMA_CH2_CMD, cmd, *R_DMA_CH2_CMD) == | ||
243 | IO_STATE_VALUE(R_DMA_CH2_CMD, cmd, reset)); | ||
244 | break; | ||
245 | case 3: | ||
246 | *R_DMA_CH3_CMD = IO_STATE(R_DMA_CH3_CMD, cmd, reset); | ||
247 | while (IO_EXTRACT(R_DMA_CH3_CMD, cmd, *R_DMA_CH3_CMD) == | ||
248 | IO_STATE_VALUE(R_DMA_CH3_CMD, cmd, reset)); | ||
249 | break; | ||
250 | case 4: | ||
251 | *R_DMA_CH4_CMD = IO_STATE(R_DMA_CH4_CMD, cmd, reset); | ||
252 | while (IO_EXTRACT(R_DMA_CH4_CMD, cmd, *R_DMA_CH4_CMD) == | ||
253 | IO_STATE_VALUE(R_DMA_CH4_CMD, cmd, reset)); | ||
254 | break; | ||
255 | case 5: | ||
256 | *R_DMA_CH5_CMD = IO_STATE(R_DMA_CH5_CMD, cmd, reset); | ||
257 | while (IO_EXTRACT(R_DMA_CH5_CMD, cmd, *R_DMA_CH5_CMD) == | ||
258 | IO_STATE_VALUE(R_DMA_CH5_CMD, cmd, reset)); | ||
259 | break; | ||
260 | case 6: | ||
261 | *R_DMA_CH6_CMD = IO_STATE(R_DMA_CH6_CMD, cmd, reset); | ||
262 | while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *R_DMA_CH6_CMD) == | ||
263 | IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset)); | ||
264 | break; | ||
265 | case 7: | ||
266 | *R_DMA_CH7_CMD = IO_STATE(R_DMA_CH7_CMD, cmd, reset); | ||
267 | while (IO_EXTRACT(R_DMA_CH7_CMD, cmd, *R_DMA_CH7_CMD) == | ||
268 | IO_STATE_VALUE(R_DMA_CH7_CMD, cmd, reset)); | ||
269 | break; | ||
270 | case 8: | ||
271 | *R_DMA_CH8_CMD = IO_STATE(R_DMA_CH8_CMD, cmd, reset); | ||
272 | while (IO_EXTRACT(R_DMA_CH8_CMD, cmd, *R_DMA_CH8_CMD) == | ||
273 | IO_STATE_VALUE(R_DMA_CH8_CMD, cmd, reset)); | ||
274 | break; | ||
275 | case 9: | ||
276 | *R_DMA_CH9_CMD = IO_STATE(R_DMA_CH9_CMD, cmd, reset); | ||
277 | while (IO_EXTRACT(R_DMA_CH9_CMD, cmd, *R_DMA_CH9_CMD) == | ||
278 | IO_STATE_VALUE(R_DMA_CH9_CMD, cmd, reset)); | ||
279 | break; | ||
280 | } | ||
281 | used_dma_channels[dmanr] = 0; | ||
282 | } | ||
283 | local_irq_restore(flags); | ||
284 | } | ||
285 | |||
286 | EXPORT_SYMBOL(cris_request_dma); | ||
287 | EXPORT_SYMBOL(cris_free_dma); | ||
diff --git a/arch/cris/arch-v10/kernel/entry.S b/arch/cris/arch-v10/kernel/entry.S index 1bc44f481c34..c0163bf94a50 100644 --- a/arch/cris/arch-v10/kernel/entry.S +++ b/arch/cris/arch-v10/kernel/entry.S | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $Id: entry.S,v 1.23 2004/10/19 13:07:37 starvik Exp $ | 1 | /* $Id: entry.S,v 1.28 2005/06/20 05:06:30 starvik Exp $ |
2 | * | 2 | * |
3 | * linux/arch/cris/entry.S | 3 | * linux/arch/cris/entry.S |
4 | * | 4 | * |
@@ -7,6 +7,22 @@ | |||
7 | * Authors: Bjorn Wesen (bjornw@axis.com) | 7 | * Authors: Bjorn Wesen (bjornw@axis.com) |
8 | * | 8 | * |
9 | * $Log: entry.S,v $ | 9 | * $Log: entry.S,v $ |
10 | * Revision 1.28 2005/06/20 05:06:30 starvik | ||
11 | * Remove unnecessary diff to kernel.org tree | ||
12 | * | ||
13 | * Revision 1.27 2005/03/04 08:16:16 starvik | ||
14 | * Merge of Linux 2.6.11. | ||
15 | * | ||
16 | * Revision 1.26 2005/01/11 13:49:47 starvik | ||
17 | * Added NMI handler. | ||
18 | * | ||
19 | * Revision 1.25 2004/12/27 11:18:32 starvik | ||
20 | * Merge of Linux 2.6.10 (not functional yet). | ||
21 | * | ||
22 | * Revision 1.24 2004/12/22 10:41:23 starvik | ||
23 | * Updates to make v10 compile with the latest SMP aware generic code (even | ||
24 | * though v10 will never have SMP). | ||
25 | * | ||
10 | * Revision 1.23 2004/10/19 13:07:37 starvik | 26 | * Revision 1.23 2004/10/19 13:07:37 starvik |
11 | * Merge of Linux 2.6.9 | 27 | * Merge of Linux 2.6.9 |
12 | * | 28 | * |
@@ -279,6 +295,7 @@ | |||
279 | #ifdef CONFIG_PREEMPT | 295 | #ifdef CONFIG_PREEMPT |
280 | ; Check if preemptive kernel scheduling should be done | 296 | ; Check if preemptive kernel scheduling should be done |
281 | _resume_kernel: | 297 | _resume_kernel: |
298 | di | ||
282 | ; Load current task struct | 299 | ; Load current task struct |
283 | movs.w -8192, $r0 ; THREAD_SIZE = 8192 | 300 | movs.w -8192, $r0 ; THREAD_SIZE = 8192 |
284 | and.d $sp, $r0 | 301 | and.d $sp, $r0 |
@@ -291,12 +308,7 @@ _need_resched: | |||
291 | bpl _Rexit | 308 | bpl _Rexit |
292 | nop | 309 | nop |
293 | ; Ok, lets's do some preemptive kernel scheduling | 310 | ; Ok, lets's do some preemptive kernel scheduling |
294 | move.d PREEMPT_ACTIVE, $r10 | 311 | jsr preempt_schedule_irq |
295 | move.d $r10, [$r0+TI_preempt_count] ; Mark as active | ||
296 | ei | ||
297 | jsr schedule | ||
298 | clear.d [$r0+TI_preempt_count] ; Mark as inactive | ||
299 | di | ||
300 | ; Load new task struct | 312 | ; Load new task struct |
301 | movs.w -8192, $r0 ; THREAD_SIZE = 8192 | 313 | movs.w -8192, $r0 ; THREAD_SIZE = 8192 |
302 | and.d $sp, $r0 | 314 | and.d $sp, $r0 |
@@ -590,15 +602,15 @@ mmu_bus_fault: | |||
590 | move.d $r0, [$sp+16] | 602 | move.d $r0, [$sp+16] |
591 | 1: btstq 12, $r1 ; Refill? | 603 | 1: btstq 12, $r1 ; Refill? |
592 | bpl 2f | 604 | bpl 2f |
593 | lsrq PMD_SHIFT, $r1 ; Get PMD index into PGD (bit 24-31) | 605 | lsrq 24, $r1 ; Get PGD index (bit 24-31) |
594 | move.d [current_pgd], $r0 ; PGD for the current process | 606 | move.d [per_cpu__current_pgd], $r0 ; PGD for the current process |
595 | move.d [$r0+$r1.d], $r0 ; Get PMD | 607 | move.d [$r0+$r1.d], $r0 ; Get PMD |
596 | beq 2f | 608 | beq 2f |
597 | nop | 609 | nop |
598 | and.w PAGE_MASK, $r0 ; Remove PMD flags | 610 | and.w PAGE_MASK, $r0 ; Remove PMD flags |
599 | move.d [R_MMU_CAUSE], $r1 | 611 | move.d [R_MMU_CAUSE], $r1 |
600 | lsrq PAGE_SHIFT, $r1 | 612 | lsrq PAGE_SHIFT, $r1 |
601 | and.d 0x7ff, $r1 ; Get PTE index into PMD (bit 13-24) | 613 | and.d 0x7ff, $r1 ; Get PTE index into PGD (bit 13-23) |
602 | move.d [$r0+$r1.d], $r1 ; Get PTE | 614 | move.d [$r0+$r1.d], $r1 ; Get PTE |
603 | beq 2f | 615 | beq 2f |
604 | nop | 616 | nop |
@@ -656,11 +668,6 @@ hwbreakpoint: | |||
656 | nop | 668 | nop |
657 | 669 | ||
658 | IRQ1_interrupt: | 670 | IRQ1_interrupt: |
659 | |||
660 | #if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM) | ||
661 | ;; If we receive a watchdog interrupt while it is not expected, then set | ||
662 | ;; up a canonical frame and dump register contents before dying. | ||
663 | |||
664 | ;; this prologue MUST match the one in irq.h and the struct in ptregs.h!!! | 671 | ;; this prologue MUST match the one in irq.h and the struct in ptregs.h!!! |
665 | move $brp,[$sp=$sp-16]; instruction pointer and room for a fake SBFS frame | 672 | move $brp,[$sp=$sp-16]; instruction pointer and room for a fake SBFS frame |
666 | push $srp | 673 | push $srp |
@@ -672,9 +679,16 @@ IRQ1_interrupt: | |||
672 | push $r10 ; push orig_r10 | 679 | push $r10 ; push orig_r10 |
673 | clear.d [$sp=$sp-4] ; frametype == 0, normal frame | 680 | clear.d [$sp=$sp-4] ; frametype == 0, normal frame |
674 | 681 | ||
675 | ;; We don't check that we actually were bit by the watchdog as opposed to | 682 | move.d [R_IRQ_MASK0_RD], $r1 ; External NMI or watchdog? |
676 | ;; an external NMI, since there is currently no handler for external NMI. | 683 | and.d 0x80000000, $r1 |
677 | 684 | beq wdog | |
685 | move.d $sp, $r10 | ||
686 | jsr handle_nmi | ||
687 | setf m ; Enable NMI again | ||
688 | retb ; Return from NMI | ||
689 | nop | ||
690 | wdog: | ||
691 | #if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM) | ||
678 | ;; Check if we're waiting for reset to happen, as signalled by | 692 | ;; Check if we're waiting for reset to happen, as signalled by |
679 | ;; hard_reset_now setting cause_of_death to a magic value. If so, just | 693 | ;; hard_reset_now setting cause_of_death to a magic value. If so, just |
680 | ;; get stuck until reset happens. | 694 | ;; get stuck until reset happens. |
@@ -1118,6 +1132,10 @@ sys_call_table: | |||
1118 | .long sys_mq_getsetattr | 1132 | .long sys_mq_getsetattr |
1119 | .long sys_ni_syscall /* reserved for kexec */ | 1133 | .long sys_ni_syscall /* reserved for kexec */ |
1120 | .long sys_waitid | 1134 | .long sys_waitid |
1135 | .long sys_ni_syscall /* 285 */ /* available */ | ||
1136 | .long sys_add_key | ||
1137 | .long sys_request_key | ||
1138 | .long sys_keyctl | ||
1121 | 1139 | ||
1122 | /* | 1140 | /* |
1123 | * NOTE!! This doesn't have to be exact - we just have | 1141 | * NOTE!! This doesn't have to be exact - we just have |
diff --git a/arch/cris/arch-v10/kernel/fasttimer.c b/arch/cris/arch-v10/kernel/fasttimer.c index 4717f7ae8e51..094ff45ae85b 100644 --- a/arch/cris/arch-v10/kernel/fasttimer.c +++ b/arch/cris/arch-v10/kernel/fasttimer.c | |||
@@ -1,10 +1,20 @@ | |||
1 | /* $Id: fasttimer.c,v 1.6 2004/05/14 10:18:39 starvik Exp $ | 1 | /* $Id: fasttimer.c,v 1.9 2005/03/04 08:16:16 starvik Exp $ |
2 | * linux/arch/cris/kernel/fasttimer.c | 2 | * linux/arch/cris/kernel/fasttimer.c |
3 | * | 3 | * |
4 | * Fast timers for ETRAX100/ETRAX100LX | 4 | * Fast timers for ETRAX100/ETRAX100LX |
5 | * This may be useful in other OS than Linux so use 2 space indentation... | 5 | * This may be useful in other OS than Linux so use 2 space indentation... |
6 | * | 6 | * |
7 | * $Log: fasttimer.c,v $ | 7 | * $Log: fasttimer.c,v $ |
8 | * Revision 1.9 2005/03/04 08:16:16 starvik | ||
9 | * Merge of Linux 2.6.11. | ||
10 | * | ||
11 | * Revision 1.8 2005/01/05 06:09:29 starvik | ||
12 | * cli()/sti() will be obsolete in 2.6.11. | ||
13 | * | ||
14 | * Revision 1.7 2005/01/03 13:35:46 starvik | ||
15 | * Removed obsolete stuff. | ||
16 | * Mark fast timer IRQ as not shared. | ||
17 | * | ||
8 | * Revision 1.6 2004/05/14 10:18:39 starvik | 18 | * Revision 1.6 2004/05/14 10:18:39 starvik |
9 | * Export fast_timer_list | 19 | * Export fast_timer_list |
10 | * | 20 | * |
@@ -148,8 +158,7 @@ static int debug_log_cnt_wrapped = 0; | |||
148 | #define DEBUG_LOG(string, value) \ | 158 | #define DEBUG_LOG(string, value) \ |
149 | { \ | 159 | { \ |
150 | unsigned long log_flags; \ | 160 | unsigned long log_flags; \ |
151 | save_flags(log_flags); \ | 161 | local_irq_save(log_flags); \ |
152 | cli(); \ | ||
153 | debug_log_string[debug_log_cnt] = (string); \ | 162 | debug_log_string[debug_log_cnt] = (string); \ |
154 | debug_log_value[debug_log_cnt] = (unsigned long)(value); \ | 163 | debug_log_value[debug_log_cnt] = (unsigned long)(value); \ |
155 | if (++debug_log_cnt >= DEBUG_LOG_MAX) \ | 164 | if (++debug_log_cnt >= DEBUG_LOG_MAX) \ |
@@ -157,7 +166,7 @@ static int debug_log_cnt_wrapped = 0; | |||
157 | debug_log_cnt = debug_log_cnt % DEBUG_LOG_MAX; \ | 166 | debug_log_cnt = debug_log_cnt % DEBUG_LOG_MAX; \ |
158 | debug_log_cnt_wrapped = 1; \ | 167 | debug_log_cnt_wrapped = 1; \ |
159 | } \ | 168 | } \ |
160 | restore_flags(log_flags); \ | 169 | local_irq_restore(log_flags); \ |
161 | } | 170 | } |
162 | #else | 171 | #else |
163 | #define DEBUG_LOG(string, value) | 172 | #define DEBUG_LOG(string, value) |
@@ -320,8 +329,7 @@ void start_one_shot_timer(struct fast_timer *t, | |||
320 | 329 | ||
321 | D1(printk("sft %s %d us\n", name, delay_us)); | 330 | D1(printk("sft %s %d us\n", name, delay_us)); |
322 | 331 | ||
323 | save_flags(flags); | 332 | local_irq_save(flags); |
324 | cli(); | ||
325 | 333 | ||
326 | do_gettimeofday_fast(&t->tv_set); | 334 | do_gettimeofday_fast(&t->tv_set); |
327 | tmp = fast_timer_list; | 335 | tmp = fast_timer_list; |
@@ -395,7 +403,7 @@ void start_one_shot_timer(struct fast_timer *t, | |||
395 | 403 | ||
396 | D2(printk("start_one_shot_timer: %d us done\n", delay_us)); | 404 | D2(printk("start_one_shot_timer: %d us done\n", delay_us)); |
397 | 405 | ||
398 | restore_flags(flags); | 406 | local_irq_restore(flags); |
399 | } /* start_one_shot_timer */ | 407 | } /* start_one_shot_timer */ |
400 | 408 | ||
401 | static inline int fast_timer_pending (const struct fast_timer * t) | 409 | static inline int fast_timer_pending (const struct fast_timer * t) |
@@ -425,11 +433,10 @@ int del_fast_timer(struct fast_timer * t) | |||
425 | unsigned long flags; | 433 | unsigned long flags; |
426 | int ret; | 434 | int ret; |
427 | 435 | ||
428 | save_flags(flags); | 436 | local_irq_save(flags); |
429 | cli(); | ||
430 | ret = detach_fast_timer(t); | 437 | ret = detach_fast_timer(t); |
431 | t->next = t->prev = NULL; | 438 | t->next = t->prev = NULL; |
432 | restore_flags(flags); | 439 | local_irq_restore(flags); |
433 | return ret; | 440 | return ret; |
434 | } /* del_fast_timer */ | 441 | } /* del_fast_timer */ |
435 | 442 | ||
@@ -444,8 +451,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs) | |||
444 | struct fast_timer *t; | 451 | struct fast_timer *t; |
445 | unsigned long flags; | 452 | unsigned long flags; |
446 | 453 | ||
447 | save_flags(flags); | 454 | local_irq_save(flags); |
448 | cli(); | ||
449 | 455 | ||
450 | /* Clear timer1 irq */ | 456 | /* Clear timer1 irq */ |
451 | *R_IRQ_MASK0_CLR = IO_STATE(R_IRQ_MASK0_CLR, timer1, clr); | 457 | *R_IRQ_MASK0_CLR = IO_STATE(R_IRQ_MASK0_CLR, timer1, clr); |
@@ -462,7 +468,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs) | |||
462 | fast_timer_running = 0; | 468 | fast_timer_running = 0; |
463 | fast_timer_ints++; | 469 | fast_timer_ints++; |
464 | 470 | ||
465 | restore_flags(flags); | 471 | local_irq_restore(flags); |
466 | 472 | ||
467 | t = fast_timer_list; | 473 | t = fast_timer_list; |
468 | while (t) | 474 | while (t) |
@@ -482,8 +488,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs) | |||
482 | fast_timers_expired++; | 488 | fast_timers_expired++; |
483 | 489 | ||
484 | /* Remove this timer before call, since it may reuse the timer */ | 490 | /* Remove this timer before call, since it may reuse the timer */ |
485 | save_flags(flags); | 491 | local_irq_save(flags); |
486 | cli(); | ||
487 | if (t->prev) | 492 | if (t->prev) |
488 | { | 493 | { |
489 | t->prev->next = t->next; | 494 | t->prev->next = t->next; |
@@ -498,7 +503,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs) | |||
498 | } | 503 | } |
499 | t->prev = NULL; | 504 | t->prev = NULL; |
500 | t->next = NULL; | 505 | t->next = NULL; |
501 | restore_flags(flags); | 506 | local_irq_restore(flags); |
502 | 507 | ||
503 | if (t->function != NULL) | 508 | if (t->function != NULL) |
504 | { | 509 | { |
@@ -515,8 +520,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs) | |||
515 | D1(printk(".\n")); | 520 | D1(printk(".\n")); |
516 | } | 521 | } |
517 | 522 | ||
518 | save_flags(flags); | 523 | local_irq_save(flags); |
519 | cli(); | ||
520 | if ((t = fast_timer_list) != NULL) | 524 | if ((t = fast_timer_list) != NULL) |
521 | { | 525 | { |
522 | /* Start next timer.. */ | 526 | /* Start next timer.. */ |
@@ -535,7 +539,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs) | |||
535 | #endif | 539 | #endif |
536 | start_timer1(us); | 540 | start_timer1(us); |
537 | } | 541 | } |
538 | restore_flags(flags); | 542 | local_irq_restore(flags); |
539 | break; | 543 | break; |
540 | } | 544 | } |
541 | else | 545 | else |
@@ -546,7 +550,7 @@ timer1_handler(int irq, void *dev_id, struct pt_regs *regs) | |||
546 | D1(printk("e! %d\n", us)); | 550 | D1(printk("e! %d\n", us)); |
547 | } | 551 | } |
548 | } | 552 | } |
549 | restore_flags(flags); | 553 | local_irq_restore(flags); |
550 | } | 554 | } |
551 | 555 | ||
552 | if (!t) | 556 | if (!t) |
@@ -748,13 +752,12 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len | |||
748 | #endif | 752 | #endif |
749 | 753 | ||
750 | used += sprintf(bigbuf + used, "Active timers:\n"); | 754 | used += sprintf(bigbuf + used, "Active timers:\n"); |
751 | save_flags(flags); | 755 | local_irq_save(flags); |
752 | cli(); | ||
753 | t = fast_timer_list; | 756 | t = fast_timer_list; |
754 | while (t != NULL && (used+100 < BIG_BUF_SIZE)) | 757 | while (t != NULL && (used+100 < BIG_BUF_SIZE)) |
755 | { | 758 | { |
756 | nextt = t->next; | 759 | nextt = t->next; |
757 | restore_flags(flags); | 760 | local_irq_restore(flags); |
758 | used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu " | 761 | used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu " |
759 | "d: %6li us data: 0x%08lX" | 762 | "d: %6li us data: 0x%08lX" |
760 | /* " func: 0x%08lX" */ | 763 | /* " func: 0x%08lX" */ |
@@ -768,14 +771,14 @@ static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len | |||
768 | t->data | 771 | t->data |
769 | /* , t->function */ | 772 | /* , t->function */ |
770 | ); | 773 | ); |
771 | cli(); | 774 | local_irq_disable(); |
772 | if (t->next != nextt) | 775 | if (t->next != nextt) |
773 | { | 776 | { |
774 | printk(KERN_WARNING "timer removed!\n"); | 777 | printk(KERN_WARNING "timer removed!\n"); |
775 | } | 778 | } |
776 | t = nextt; | 779 | t = nextt; |
777 | } | 780 | } |
778 | restore_flags(flags); | 781 | local_irq_restore(flags); |
779 | } | 782 | } |
780 | 783 | ||
781 | if (used - offset < len) | 784 | if (used - offset < len) |
@@ -963,7 +966,7 @@ void fast_timer_init(void) | |||
963 | if ((fasttimer_proc_entry = create_proc_entry( "fasttimer", 0, 0 ))) | 966 | if ((fasttimer_proc_entry = create_proc_entry( "fasttimer", 0, 0 ))) |
964 | fasttimer_proc_entry->read_proc = proc_fasttimer_read; | 967 | fasttimer_proc_entry->read_proc = proc_fasttimer_read; |
965 | #endif /* PROC_FS */ | 968 | #endif /* PROC_FS */ |
966 | if(request_irq(TIMER1_IRQ_NBR, timer1_handler, SA_SHIRQ, | 969 | if(request_irq(TIMER1_IRQ_NBR, timer1_handler, 0, |
967 | "fast timer int", NULL)) | 970 | "fast timer int", NULL)) |
968 | { | 971 | { |
969 | printk("err: timer1 irq\n"); | 972 | printk("err: timer1 irq\n"); |
diff --git a/arch/cris/arch-v10/kernel/head.S b/arch/cris/arch-v10/kernel/head.S index 2c1dd1184a8f..f00c145b43f1 100644 --- a/arch/cris/arch-v10/kernel/head.S +++ b/arch/cris/arch-v10/kernel/head.S | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $Id: head.S,v 1.7 2004/05/14 07:58:01 starvik Exp $ | 1 | /* $Id: head.S,v 1.10 2005/06/20 05:12:54 starvik Exp $ |
2 | * | 2 | * |
3 | * Head of the kernel - alter with care | 3 | * Head of the kernel - alter with care |
4 | * | 4 | * |
@@ -7,6 +7,16 @@ | |||
7 | * Authors: Bjorn Wesen (bjornw@axis.com) | 7 | * Authors: Bjorn Wesen (bjornw@axis.com) |
8 | * | 8 | * |
9 | * $Log: head.S,v $ | 9 | * $Log: head.S,v $ |
10 | * Revision 1.10 2005/06/20 05:12:54 starvik | ||
11 | * Remove unnecessary diff to kernel.org tree | ||
12 | * | ||
13 | * Revision 1.9 2004/12/13 12:21:51 starvik | ||
14 | * Added I/O and DMA allocators from Linux 2.4 | ||
15 | * | ||
16 | * Revision 1.8 2004/11/22 11:41:14 starvik | ||
17 | * Kernel command line may be supplied to kernel. Not used by Axis but may | ||
18 | * be used by customers. | ||
19 | * | ||
10 | * Revision 1.7 2004/05/14 07:58:01 starvik | 20 | * Revision 1.7 2004/05/14 07:58:01 starvik |
11 | * Merge of changes from 2.4 | 21 | * Merge of changes from 2.4 |
12 | * | 22 | * |
@@ -181,6 +191,7 @@ | |||
181 | 191 | ||
182 | #define CRAMFS_MAGIC 0x28cd3d45 | 192 | #define CRAMFS_MAGIC 0x28cd3d45 |
183 | #define RAM_INIT_MAGIC 0x56902387 | 193 | #define RAM_INIT_MAGIC 0x56902387 |
194 | #define COMMAND_LINE_MAGIC 0x87109563 | ||
184 | 195 | ||
185 | #define START_ETHERNET_CLOCK IO_STATE(R_NETWORK_GEN_CONFIG, enable, on) |\ | 196 | #define START_ETHERNET_CLOCK IO_STATE(R_NETWORK_GEN_CONFIG, enable, on) |\ |
186 | IO_STATE(R_NETWORK_GEN_CONFIG, phy, mii_clk) | 197 | IO_STATE(R_NETWORK_GEN_CONFIG, phy, mii_clk) |
@@ -490,6 +501,23 @@ _no_romfs_in_flash: | |||
490 | 501 | ||
491 | _start_it: | 502 | _start_it: |
492 | 503 | ||
504 | ;; Check if kernel command line is supplied | ||
505 | cmp.d COMMAND_LINE_MAGIC, $r10 | ||
506 | bne no_command_line | ||
507 | nop | ||
508 | |||
509 | move.d 256, $r13 | ||
510 | move.d cris_command_line, $r10 | ||
511 | or.d 0x80000000, $r11 ; Make it virtual | ||
512 | 1: | ||
513 | move.b [$r11+], $r12 | ||
514 | move.b $r12, [$r10+] | ||
515 | subq 1, $r13 | ||
516 | bne 1b | ||
517 | nop | ||
518 | |||
519 | no_command_line: | ||
520 | |||
493 | ;; the kernel stack is overlayed with the task structure for each | 521 | ;; the kernel stack is overlayed with the task structure for each |
494 | ;; task. thus the initial kernel stack is in the same page as the | 522 | ;; task. thus the initial kernel stack is in the same page as the |
495 | ;; init_task (but starts in the top of the page, size 8192) | 523 | ;; init_task (but starts in the top of the page, size 8192) |
@@ -567,76 +595,32 @@ _start_it: | |||
567 | ;; Etrax product HW genconfig setup | 595 | ;; Etrax product HW genconfig setup |
568 | 596 | ||
569 | moveq 0,$r0 | 597 | moveq 0,$r0 |
570 | #if (!defined(CONFIG_ETRAX_KGDB) || !defined(CONFIG_ETRAX_DEBUG_PORT0)) \ | 598 | |
571 | && !defined(CONFIG_DMA_MEMCPY) | 599 | ;; Init interfaces (disable them). |
572 | ; DMA channels 6 and 7 to ser0, kgdb doesnt want DMA | 600 | or.d IO_STATE (R_GEN_CONFIG, scsi0, disable) \ |
573 | or.d IO_STATE (R_GEN_CONFIG, dma7, serial0) \ | 601 | | IO_STATE (R_GEN_CONFIG, ata, disable) \ |
574 | | IO_STATE (R_GEN_CONFIG, dma6, serial0),$r0 | 602 | | IO_STATE (R_GEN_CONFIG, par0, disable) \ |
575 | #endif | 603 | | IO_STATE (R_GEN_CONFIG, ser2, disable) \ |
576 | #if !defined(CONFIG_ETRAX_KGDB) || !defined(CONFIG_ETRAX_DEBUG_PORT1) | 604 | | IO_STATE (R_GEN_CONFIG, mio, disable) \ |
577 | ; DMA channels 8 and 9 to ser1, kgdb doesnt want DMA | 605 | | IO_STATE (R_GEN_CONFIG, scsi1, disable) \ |
578 | or.d IO_STATE (R_GEN_CONFIG, dma9, serial1) \ | 606 | | IO_STATE (R_GEN_CONFIG, scsi0w, disable) \ |
579 | | IO_STATE (R_GEN_CONFIG, dma8, serial1),$r0 | 607 | | IO_STATE (R_GEN_CONFIG, par1, disable) \ |
580 | #endif | 608 | | IO_STATE (R_GEN_CONFIG, ser3, disable) \ |
581 | #ifdef CONFIG_DMA_MEMCPY | 609 | | IO_STATE (R_GEN_CONFIG, mio_w, disable) \ |
582 | ; 6/7 memory-memory DMA | 610 | | IO_STATE (R_GEN_CONFIG, usb1, disable) \ |
583 | or.d IO_STATE (R_GEN_CONFIG, dma7, intdma6) \ | 611 | | IO_STATE (R_GEN_CONFIG, usb2, disable) \ |
584 | | IO_STATE (R_GEN_CONFIG, dma6, intdma7),$r0 | 612 | | IO_STATE (R_GEN_CONFIG, par_w, disable),$r0 |
585 | #endif | 613 | |
586 | #ifdef CONFIG_ETRAX_SERIAL_PORT2 | 614 | ;; Init DMA channel muxing (set to unused clients). |
587 | ; Enable serial port 2 | 615 | or.d IO_STATE (R_GEN_CONFIG, dma2, ata) \ |
588 | or.w IO_STATE (R_GEN_CONFIG, ser2, select),$r0 | 616 | | IO_STATE (R_GEN_CONFIG, dma3, ata) \ |
589 | #if !defined(CONFIG_ETRAX_KGDB) || !defined(CONFIG_ETRAX_DEBUG_PORT2) | 617 | | IO_STATE (R_GEN_CONFIG, dma4, scsi1) \ |
590 | ; DMA channels 2 and 3 to ser2, kgdb doesnt want DMA | 618 | | IO_STATE (R_GEN_CONFIG, dma5, scsi1) \ |
591 | or.d IO_STATE (R_GEN_CONFIG, dma3, serial2) \ | 619 | | IO_STATE (R_GEN_CONFIG, dma6, unused) \ |
592 | | IO_STATE (R_GEN_CONFIG, dma2, serial2),$r0 | 620 | | IO_STATE (R_GEN_CONFIG, dma7, unused) \ |
593 | #endif | 621 | | IO_STATE (R_GEN_CONFIG, dma8, usb) \ |
594 | #endif | 622 | | IO_STATE (R_GEN_CONFIG, dma9, usb),$r0 |
595 | #if defined(CONFIG_ETRAX_SERIAL_PORT3) || defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1) | 623 | |
596 | ; Enable serial port 3 | ||
597 | or.w IO_STATE (R_GEN_CONFIG, ser3, select),$r0 | ||
598 | #if !defined(CONFIG_ETRAX_KGDB) || !defined(CONFIG_ETRAX_DEBUG_PORT3) | ||
599 | ; DMA channels 4 and 5 to ser3, kgdb doesnt want DMA | ||
600 | or.d IO_STATE (R_GEN_CONFIG, dma5, serial3) \ | ||
601 | | IO_STATE (R_GEN_CONFIG, dma4, serial3),$r0 | ||
602 | #endif | ||
603 | #endif | ||
604 | #if defined(CONFIG_ETRAX_PARALLEL_PORT0) || defined(CONFIG_ETRAX_ETHERNET_LPSLAVE) | ||
605 | ; parport 0 enabled using DMA 2/3 | ||
606 | or.w IO_STATE (R_GEN_CONFIG, par0, select),$r0 | ||
607 | #endif | ||
608 | #if defined(CONFIG_ETRAX_PARALLEL_PORT1) || defined(CONFIG_ETRAX_ETHERNET_LPSLAVE) | ||
609 | ; parport 1 enabled using DMA 4/5 | ||
610 | or.w IO_STATE (R_GEN_CONFIG, par1, select),$r0 | ||
611 | #endif | ||
612 | #ifdef CONFIG_ETRAX_IDE | ||
613 | ; DMA channels 2 and 3 to ATA, ATA enabled | ||
614 | or.d IO_STATE (R_GEN_CONFIG, dma3, ata) \ | ||
615 | | IO_STATE (R_GEN_CONFIG, dma2, ata) \ | ||
616 | | IO_STATE (R_GEN_CONFIG, ata, select),$r0 | ||
617 | #endif | ||
618 | |||
619 | #ifdef CONFIG_ETRAX_USB_HOST_PORT1 | ||
620 | ; Set the USB port 1 enable bit | ||
621 | or.d IO_STATE (R_GEN_CONFIG, usb1, select),$r0 | ||
622 | #endif | ||
623 | #ifdef CONFIG_ETRAX_USB_HOST_PORT2 | ||
624 | ; Set the USB port 2 enable bit | ||
625 | or.d IO_STATE (R_GEN_CONFIG, usb2, select),$r0 | ||
626 | #endif | ||
627 | #ifdef CONFIG_ETRAX_USB_HOST | ||
628 | ; Connect DMA channels 8 and 9 to USB | ||
629 | and.d (~(IO_MASK (R_GEN_CONFIG, dma9) \ | ||
630 | | IO_MASK (R_GEN_CONFIG, dma8))) \ | ||
631 | | IO_STATE (R_GEN_CONFIG, dma9, usb) \ | ||
632 | | IO_STATE (R_GEN_CONFIG, dma8, usb),$r0 | ||
633 | #endif | ||
634 | |||
635 | #ifdef CONFIG_JULIETTE | ||
636 | ; DMA channels 4 and 5 to EXTDMA0, for Juliette | ||
637 | or.d IO_STATE (R_GEN_CONFIG, dma5, extdma0) \ | ||
638 | | IO_STATE (R_GEN_CONFIG, dma4, extdma0),$r0 | ||
639 | #endif | ||
640 | 624 | ||
641 | #if defined(CONFIG_ETRAX_DEF_R_PORT_G0_DIR_OUT) | 625 | #if defined(CONFIG_ETRAX_DEF_R_PORT_G0_DIR_OUT) |
642 | or.d IO_STATE (R_GEN_CONFIG, g0dir, out),$r0 | 626 | or.d IO_STATE (R_GEN_CONFIG, g0dir, out),$r0 |
diff --git a/arch/cris/arch-v10/kernel/io_interface_mux.c b/arch/cris/arch-v10/kernel/io_interface_mux.c new file mode 100644 index 000000000000..29d48ad00df9 --- /dev/null +++ b/arch/cris/arch-v10/kernel/io_interface_mux.c | |||
@@ -0,0 +1,879 @@ | |||
1 | /* IO interface mux allocator for ETRAX100LX. | ||
2 | * Copyright 2004, Axis Communications AB | ||
3 | * $Id: io_interface_mux.c,v 1.2 2004/12/21 12:08:38 starvik Exp $ | ||
4 | */ | ||
5 | |||
6 | |||
7 | /* C.f. ETRAX100LX Designer's Reference 20.9 */ | ||
8 | |||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/slab.h> | ||
11 | #include <linux/errno.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/init.h> | ||
14 | |||
15 | #include <asm/arch/svinto.h> | ||
16 | #include <asm/io.h> | ||
17 | #include <asm/arch/io_interface_mux.h> | ||
18 | |||
19 | |||
20 | #define DBG(s) | ||
21 | |||
22 | /* Macro to access ETRAX 100 registers */ | ||
23 | #define SETS(var, reg, field, val) var = (var & ~IO_MASK_(reg##_, field##_)) | \ | ||
24 | IO_STATE_(reg##_, field##_, _##val) | ||
25 | |||
26 | enum io_if_group { | ||
27 | group_a = (1<<0), | ||
28 | group_b = (1<<1), | ||
29 | group_c = (1<<2), | ||
30 | group_d = (1<<3), | ||
31 | group_e = (1<<4), | ||
32 | group_f = (1<<5) | ||
33 | }; | ||
34 | |||
35 | struct watcher | ||
36 | { | ||
37 | void (*notify)(const unsigned int gpio_in_available, | ||
38 | const unsigned int gpio_out_available, | ||
39 | const unsigned char pa_available, | ||
40 | const unsigned char pb_available); | ||
41 | struct watcher *next; | ||
42 | }; | ||
43 | |||
44 | |||
45 | struct if_group | ||
46 | { | ||
47 | enum io_if_group group; | ||
48 | unsigned char used; | ||
49 | enum cris_io_interface owner; | ||
50 | }; | ||
51 | |||
52 | |||
53 | struct interface | ||
54 | { | ||
55 | enum cris_io_interface ioif; | ||
56 | unsigned char groups; | ||
57 | unsigned char used; | ||
58 | char *owner; | ||
59 | unsigned int gpio_g_in; | ||
60 | unsigned int gpio_g_out; | ||
61 | unsigned char gpio_b; | ||
62 | }; | ||
63 | |||
64 | static struct if_group if_groups[6] = { | ||
65 | { | ||
66 | .group = group_a, | ||
67 | .used = 0, | ||
68 | }, | ||
69 | { | ||
70 | .group = group_b, | ||
71 | .used = 0, | ||
72 | }, | ||
73 | { | ||
74 | .group = group_c, | ||
75 | .used = 0, | ||
76 | }, | ||
77 | { | ||
78 | .group = group_d, | ||
79 | .used = 0, | ||
80 | }, | ||
81 | { | ||
82 | .group = group_e, | ||
83 | .used = 0, | ||
84 | }, | ||
85 | { | ||
86 | .group = group_f, | ||
87 | .used = 0, | ||
88 | } | ||
89 | }; | ||
90 | |||
91 | /* The order in the array must match the order of enum | ||
92 | * cris_io_interface in io_interface_mux.h */ | ||
93 | static struct interface interfaces[] = { | ||
94 | /* Begin Non-multiplexed interfaces */ | ||
95 | { | ||
96 | .ioif = if_eth, | ||
97 | .groups = 0, | ||
98 | .gpio_g_in = 0, | ||
99 | .gpio_g_out = 0, | ||
100 | .gpio_b = 0 | ||
101 | }, | ||
102 | { | ||
103 | .ioif = if_serial_0, | ||
104 | .groups = 0, | ||
105 | .gpio_g_in = 0, | ||
106 | .gpio_g_out = 0, | ||
107 | .gpio_b = 0 | ||
108 | }, | ||
109 | /* End Non-multiplexed interfaces */ | ||
110 | { | ||
111 | .ioif = if_serial_1, | ||
112 | .groups = group_e, | ||
113 | .gpio_g_in = 0x00000000, | ||
114 | .gpio_g_out = 0x00000000, | ||
115 | .gpio_b = 0x00 | ||
116 | }, | ||
117 | { | ||
118 | .ioif = if_serial_2, | ||
119 | .groups = group_b, | ||
120 | .gpio_g_in = 0x000000c0, | ||
121 | .gpio_g_out = 0x000000c0, | ||
122 | .gpio_b = 0x00 | ||
123 | }, | ||
124 | { | ||
125 | .ioif = if_serial_3, | ||
126 | .groups = group_c, | ||
127 | .gpio_g_in = 0xc0000000, | ||
128 | .gpio_g_out = 0xc0000000, | ||
129 | .gpio_b = 0x00 | ||
130 | }, | ||
131 | { | ||
132 | .ioif = if_sync_serial_1, | ||
133 | .groups = group_e | group_f, /* if_sync_serial_1 and if_sync_serial_3 | ||
134 | can be used simultaneously */ | ||
135 | .gpio_g_in = 0x00000000, | ||
136 | .gpio_g_out = 0x00000000, | ||
137 | .gpio_b = 0x10 | ||
138 | }, | ||
139 | { | ||
140 | .ioif = if_sync_serial_3, | ||
141 | .groups = group_c | group_f, | ||
142 | .gpio_g_in = 0xc0000000, | ||
143 | .gpio_g_out = 0xc0000000, | ||
144 | .gpio_b = 0x80 | ||
145 | }, | ||
146 | { | ||
147 | .ioif = if_shared_ram, | ||
148 | .groups = group_a, | ||
149 | .gpio_g_in = 0x0000ff3e, | ||
150 | .gpio_g_out = 0x0000ff38, | ||
151 | .gpio_b = 0x00 | ||
152 | }, | ||
153 | { | ||
154 | .ioif = if_shared_ram_w, | ||
155 | .groups = group_a | group_d, | ||
156 | .gpio_g_in = 0x00ffff3e, | ||
157 | .gpio_g_out = 0x00ffff38, | ||
158 | .gpio_b = 0x00 | ||
159 | }, | ||
160 | { | ||
161 | .ioif = if_par_0, | ||
162 | .groups = group_a, | ||
163 | .gpio_g_in = 0x0000ff3e, | ||
164 | .gpio_g_out = 0x0000ff3e, | ||
165 | .gpio_b = 0x00 | ||
166 | }, | ||
167 | { | ||
168 | .ioif = if_par_1, | ||
169 | .groups = group_d, | ||
170 | .gpio_g_in = 0x3eff0000, | ||
171 | .gpio_g_out = 0x3eff0000, | ||
172 | .gpio_b = 0x00 | ||
173 | }, | ||
174 | { | ||
175 | .ioif = if_par_w, | ||
176 | .groups = group_a | group_d, | ||
177 | .gpio_g_in = 0x00ffff3e, | ||
178 | .gpio_g_out = 0x00ffff3e, | ||
179 | .gpio_b = 0x00 | ||
180 | }, | ||
181 | { | ||
182 | .ioif = if_scsi8_0, | ||
183 | .groups = group_a | group_b | group_f, /* if_scsi8_0 and if_scsi8_1 | ||
184 | can be used simultaneously */ | ||
185 | .gpio_g_in = 0x0000ffff, | ||
186 | .gpio_g_out = 0x0000ffff, | ||
187 | .gpio_b = 0x10 | ||
188 | }, | ||
189 | { | ||
190 | .ioif = if_scsi8_1, | ||
191 | .groups = group_c | group_d | group_f, /* if_scsi8_0 and if_scsi8_1 | ||
192 | can be used simultaneously */ | ||
193 | .gpio_g_in = 0xffff0000, | ||
194 | .gpio_g_out = 0xffff0000, | ||
195 | .gpio_b = 0x80 | ||
196 | }, | ||
197 | { | ||
198 | .ioif = if_scsi_w, | ||
199 | .groups = group_a | group_b | group_d | group_f, | ||
200 | .gpio_g_in = 0x01ffffff, | ||
201 | .gpio_g_out = 0x07ffffff, | ||
202 | .gpio_b = 0x80 | ||
203 | }, | ||
204 | { | ||
205 | .ioif = if_ata, | ||
206 | .groups = group_a | group_b | group_c | group_d, | ||
207 | .gpio_g_in = 0xf9ffffff, | ||
208 | .gpio_g_out = 0xffffffff, | ||
209 | .gpio_b = 0x80 | ||
210 | }, | ||
211 | { | ||
212 | .ioif = if_csp, | ||
213 | .groups = group_f, /* if_csp and if_i2c can be used simultaneously */ | ||
214 | .gpio_g_in = 0x00000000, | ||
215 | .gpio_g_out = 0x00000000, | ||
216 | .gpio_b = 0xfc | ||
217 | }, | ||
218 | { | ||
219 | .ioif = if_i2c, | ||
220 | .groups = group_f, /* if_csp and if_i2c can be used simultaneously */ | ||
221 | .gpio_g_in = 0x00000000, | ||
222 | .gpio_g_out = 0x00000000, | ||
223 | .gpio_b = 0x03 | ||
224 | }, | ||
225 | { | ||
226 | .ioif = if_usb_1, | ||
227 | .groups = group_e | group_f, | ||
228 | .gpio_g_in = 0x00000000, | ||
229 | .gpio_g_out = 0x00000000, | ||
230 | .gpio_b = 0x2c | ||
231 | }, | ||
232 | { | ||
233 | .ioif = if_usb_2, | ||
234 | .groups = group_d, | ||
235 | .gpio_g_in = 0x0e000000, | ||
236 | .gpio_g_out = 0x3c000000, | ||
237 | .gpio_b = 0x00 | ||
238 | }, | ||
239 | /* GPIO pins */ | ||
240 | { | ||
241 | .ioif = if_gpio_grp_a, | ||
242 | .groups = group_a, | ||
243 | .gpio_g_in = 0x0000ff3f, | ||
244 | .gpio_g_out = 0x0000ff3f, | ||
245 | .gpio_b = 0x00 | ||
246 | }, | ||
247 | { | ||
248 | .ioif = if_gpio_grp_b, | ||
249 | .groups = group_b, | ||
250 | .gpio_g_in = 0x000000c0, | ||
251 | .gpio_g_out = 0x000000c0, | ||
252 | .gpio_b = 0x00 | ||
253 | }, | ||
254 | { | ||
255 | .ioif = if_gpio_grp_c, | ||
256 | .groups = group_c, | ||
257 | .gpio_g_in = 0xc0000000, | ||
258 | .gpio_g_out = 0xc0000000, | ||
259 | .gpio_b = 0x00 | ||
260 | }, | ||
261 | { | ||
262 | .ioif = if_gpio_grp_d, | ||
263 | .groups = group_d, | ||
264 | .gpio_g_in = 0x3fff0000, | ||
265 | .gpio_g_out = 0x3fff0000, | ||
266 | .gpio_b = 0x00 | ||
267 | }, | ||
268 | { | ||
269 | .ioif = if_gpio_grp_e, | ||
270 | .groups = group_e, | ||
271 | .gpio_g_in = 0x00000000, | ||
272 | .gpio_g_out = 0x00000000, | ||
273 | .gpio_b = 0x00 | ||
274 | }, | ||
275 | { | ||
276 | .ioif = if_gpio_grp_f, | ||
277 | .groups = group_f, | ||
278 | .gpio_g_in = 0x00000000, | ||
279 | .gpio_g_out = 0x00000000, | ||
280 | .gpio_b = 0xff | ||
281 | } | ||
282 | /* Array end */ | ||
283 | }; | ||
284 | |||
285 | static struct watcher *watchers = NULL; | ||
286 | |||
287 | static unsigned int gpio_in_pins = 0xffffffff; | ||
288 | static unsigned int gpio_out_pins = 0xffffffff; | ||
289 | static unsigned char gpio_pb_pins = 0xff; | ||
290 | static unsigned char gpio_pa_pins = 0xff; | ||
291 | |||
292 | static enum cris_io_interface gpio_pa_owners[8]; | ||
293 | static enum cris_io_interface gpio_pb_owners[8]; | ||
294 | static enum cris_io_interface gpio_pg_owners[32]; | ||
295 | |||
296 | static int cris_io_interface_init(void); | ||
297 | |||
298 | static unsigned char clear_group_from_set(const unsigned char groups, struct if_group *group) | ||
299 | { | ||
300 | return (groups & ~group->group); | ||
301 | } | ||
302 | |||
303 | |||
304 | static struct if_group *get_group(const unsigned char groups) | ||
305 | { | ||
306 | int i; | ||
307 | for (i = 0; i < sizeof(if_groups)/sizeof(struct if_group); i++) { | ||
308 | if (groups & if_groups[i].group) { | ||
309 | return &if_groups[i]; | ||
310 | } | ||
311 | } | ||
312 | return NULL; | ||
313 | } | ||
314 | |||
315 | |||
316 | static void notify_watchers(void) | ||
317 | { | ||
318 | struct watcher *w = watchers; | ||
319 | |||
320 | DBG(printk("io_interface_mux: notifying watchers\n")); | ||
321 | |||
322 | while (NULL != w) { | ||
323 | w->notify((const unsigned int)gpio_in_pins, | ||
324 | (const unsigned int)gpio_out_pins, | ||
325 | (const unsigned char)gpio_pa_pins, | ||
326 | (const unsigned char)gpio_pb_pins); | ||
327 | w = w->next; | ||
328 | } | ||
329 | } | ||
330 | |||
331 | |||
332 | int cris_request_io_interface(enum cris_io_interface ioif, const char *device_id) | ||
333 | { | ||
334 | int set_gen_config = 0; | ||
335 | int set_gen_config_ii = 0; | ||
336 | unsigned long int gens; | ||
337 | unsigned long int gens_ii; | ||
338 | struct if_group *grp; | ||
339 | unsigned char group_set; | ||
340 | unsigned long flags; | ||
341 | |||
342 | (void)cris_io_interface_init(); | ||
343 | |||
344 | DBG(printk("cris_request_io_interface(%d, \"%s\")\n", ioif, device_id)); | ||
345 | |||
346 | if ((ioif >= if_max_interfaces) || (ioif < 0)) { | ||
347 | printk(KERN_CRIT "cris_request_io_interface: Bad interface %u submitted for %s\n", | ||
348 | ioif, | ||
349 | device_id); | ||
350 | return -EINVAL; | ||
351 | } | ||
352 | |||
353 | local_irq_save(flags); | ||
354 | |||
355 | if (interfaces[ioif].used) { | ||
356 | local_irq_restore(flags); | ||
357 | printk(KERN_CRIT "cris_io_interface: Cannot allocate interface for %s, in use by %s\n", | ||
358 | device_id, | ||
359 | interfaces[ioif].owner); | ||
360 | return -EBUSY; | ||
361 | } | ||
362 | |||
363 | /* Check that all required groups are free before allocating, */ | ||
364 | group_set = interfaces[ioif].groups; | ||
365 | while (NULL != (grp = get_group(group_set))) { | ||
366 | if (grp->used) { | ||
367 | if (grp->group == group_f) { | ||
368 | if ((if_sync_serial_1 == ioif) || | ||
369 | (if_sync_serial_3 == ioif)) { | ||
370 | if ((grp->owner != if_sync_serial_1) && | ||
371 | (grp->owner != if_sync_serial_3)) { | ||
372 | local_irq_restore(flags); | ||
373 | return -EBUSY; | ||
374 | } | ||
375 | } else if ((if_scsi8_0 == ioif) || | ||
376 | (if_scsi8_1 == ioif)) { | ||
377 | if ((grp->owner != if_scsi8_0) && | ||
378 | (grp->owner != if_scsi8_1)) { | ||
379 | local_irq_restore(flags); | ||
380 | return -EBUSY; | ||
381 | } | ||
382 | } | ||
383 | } else { | ||
384 | local_irq_restore(flags); | ||
385 | return -EBUSY; | ||
386 | } | ||
387 | } | ||
388 | group_set = clear_group_from_set(group_set, grp); | ||
389 | } | ||
390 | |||
391 | /* Are the required GPIO pins available too? */ | ||
392 | if (((interfaces[ioif].gpio_g_in & gpio_in_pins) != interfaces[ioif].gpio_g_in) || | ||
393 | ((interfaces[ioif].gpio_g_out & gpio_out_pins) != interfaces[ioif].gpio_g_out) || | ||
394 | ((interfaces[ioif].gpio_b & gpio_pb_pins) != interfaces[ioif].gpio_b)) { | ||
395 | printk(KERN_CRIT "cris_request_io_interface: Could not get required pins for interface %u\n", | ||
396 | ioif); | ||
397 | return -EBUSY; | ||
398 | } | ||
399 | |||
400 | /* All needed I/O pins and pin groups are free, allocate. */ | ||
401 | group_set = interfaces[ioif].groups; | ||
402 | while (NULL != (grp = get_group(group_set))) { | ||
403 | grp->used = 1; | ||
404 | grp->owner = ioif; | ||
405 | group_set = clear_group_from_set(group_set, grp); | ||
406 | } | ||
407 | |||
408 | gens = genconfig_shadow; | ||
409 | gens_ii = gen_config_ii_shadow; | ||
410 | |||
411 | set_gen_config = 1; | ||
412 | switch (ioif) | ||
413 | { | ||
414 | /* Begin Non-multiplexed interfaces */ | ||
415 | case if_eth: | ||
416 | /* fall through */ | ||
417 | case if_serial_0: | ||
418 | set_gen_config = 0; | ||
419 | break; | ||
420 | /* End Non-multiplexed interfaces */ | ||
421 | case if_serial_1: | ||
422 | set_gen_config_ii = 1; | ||
423 | SETS(gens_ii, R_GEN_CONFIG_II, sermode1, async); | ||
424 | break; | ||
425 | case if_serial_2: | ||
426 | SETS(gens, R_GEN_CONFIG, ser2, select); | ||
427 | break; | ||
428 | case if_serial_3: | ||
429 | SETS(gens, R_GEN_CONFIG, ser3, select); | ||
430 | set_gen_config_ii = 1; | ||
431 | SETS(gens_ii, R_GEN_CONFIG_II, sermode3, async); | ||
432 | break; | ||
433 | case if_sync_serial_1: | ||
434 | set_gen_config_ii = 1; | ||
435 | SETS(gens_ii, R_GEN_CONFIG_II, sermode1, sync); | ||
436 | break; | ||
437 | case if_sync_serial_3: | ||
438 | SETS(gens, R_GEN_CONFIG, ser3, select); | ||
439 | set_gen_config_ii = 1; | ||
440 | SETS(gens_ii, R_GEN_CONFIG_II, sermode3, sync); | ||
441 | break; | ||
442 | case if_shared_ram: | ||
443 | SETS(gens, R_GEN_CONFIG, mio, select); | ||
444 | break; | ||
445 | case if_shared_ram_w: | ||
446 | SETS(gens, R_GEN_CONFIG, mio_w, select); | ||
447 | break; | ||
448 | case if_par_0: | ||
449 | SETS(gens, R_GEN_CONFIG, par0, select); | ||
450 | break; | ||
451 | case if_par_1: | ||
452 | SETS(gens, R_GEN_CONFIG, par1, select); | ||
453 | break; | ||
454 | case if_par_w: | ||
455 | SETS(gens, R_GEN_CONFIG, par0, select); | ||
456 | SETS(gens, R_GEN_CONFIG, par_w, select); | ||
457 | break; | ||
458 | case if_scsi8_0: | ||
459 | SETS(gens, R_GEN_CONFIG, scsi0, select); | ||
460 | break; | ||
461 | case if_scsi8_1: | ||
462 | SETS(gens, R_GEN_CONFIG, scsi1, select); | ||
463 | break; | ||
464 | case if_scsi_w: | ||
465 | SETS(gens, R_GEN_CONFIG, scsi0, select); | ||
466 | SETS(gens, R_GEN_CONFIG, scsi0w, select); | ||
467 | break; | ||
468 | case if_ata: | ||
469 | SETS(gens, R_GEN_CONFIG, ata, select); | ||
470 | break; | ||
471 | case if_csp: | ||
472 | /* fall through */ | ||
473 | case if_i2c: | ||
474 | set_gen_config = 0; | ||
475 | break; | ||
476 | case if_usb_1: | ||
477 | SETS(gens, R_GEN_CONFIG, usb1, select); | ||
478 | break; | ||
479 | case if_usb_2: | ||
480 | SETS(gens, R_GEN_CONFIG, usb2, select); | ||
481 | break; | ||
482 | case if_gpio_grp_a: | ||
483 | /* GPIO groups are only accounted, don't do configuration changes. */ | ||
484 | /* fall through */ | ||
485 | case if_gpio_grp_b: | ||
486 | /* fall through */ | ||
487 | case if_gpio_grp_c: | ||
488 | /* fall through */ | ||
489 | case if_gpio_grp_d: | ||
490 | /* fall through */ | ||
491 | case if_gpio_grp_e: | ||
492 | /* fall through */ | ||
493 | case if_gpio_grp_f: | ||
494 | set_gen_config = 0; | ||
495 | break; | ||
496 | default: | ||
497 | panic("cris_request_io_interface: Bad interface %u submitted for %s\n", | ||
498 | ioif, | ||
499 | device_id); | ||
500 | } | ||
501 | |||
502 | interfaces[ioif].used = 1; | ||
503 | interfaces[ioif].owner = (char*)device_id; | ||
504 | |||
505 | if (set_gen_config) { | ||
506 | volatile int i; | ||
507 | genconfig_shadow = gens; | ||
508 | *R_GEN_CONFIG = genconfig_shadow; | ||
509 | /* Wait 12 cycles before doing any DMA command */ | ||
510 | for(i = 6; i > 0; i--) | ||
511 | nop(); | ||
512 | } | ||
513 | if (set_gen_config_ii) { | ||
514 | gen_config_ii_shadow = gens_ii; | ||
515 | *R_GEN_CONFIG_II = gen_config_ii_shadow; | ||
516 | } | ||
517 | |||
518 | DBG(printk("GPIO pins: available before: g_in=0x%08x g_out=0x%08x pb=0x%02x\n", | ||
519 | gpio_in_pins, gpio_out_pins, gpio_pb_pins)); | ||
520 | DBG(printk("grabbing pins: g_in=0x%08x g_out=0x%08x pb=0x%02x\n", | ||
521 | interfaces[ioif].gpio_g_in, | ||
522 | interfaces[ioif].gpio_g_out, | ||
523 | interfaces[ioif].gpio_b)); | ||
524 | |||
525 | gpio_in_pins &= ~interfaces[ioif].gpio_g_in; | ||
526 | gpio_out_pins &= ~interfaces[ioif].gpio_g_out; | ||
527 | gpio_pb_pins &= ~interfaces[ioif].gpio_b; | ||
528 | |||
529 | DBG(printk("GPIO pins: available after: g_in=0x%08x g_out=0x%08x pb=0x%02x\n", | ||
530 | gpio_in_pins, gpio_out_pins, gpio_pb_pins)); | ||
531 | |||
532 | local_irq_restore(flags); | ||
533 | |||
534 | notify_watchers(); | ||
535 | |||
536 | return 0; | ||
537 | } | ||
538 | |||
539 | |||
540 | void cris_free_io_interface(enum cris_io_interface ioif) | ||
541 | { | ||
542 | struct if_group *grp; | ||
543 | unsigned char group_set; | ||
544 | unsigned long flags; | ||
545 | |||
546 | (void)cris_io_interface_init(); | ||
547 | |||
548 | if ((ioif >= if_max_interfaces) || (ioif < 0)) { | ||
549 | printk(KERN_CRIT "cris_free_io_interface: Bad interface %u\n", | ||
550 | ioif); | ||
551 | return; | ||
552 | } | ||
553 | local_irq_save(flags); | ||
554 | if (!interfaces[ioif].used) { | ||
555 | printk(KERN_CRIT "cris_free_io_interface: Freeing free interface %u\n", | ||
556 | ioif); | ||
557 | local_irq_restore(flags); | ||
558 | return; | ||
559 | } | ||
560 | group_set = interfaces[ioif].groups; | ||
561 | while (NULL != (grp = get_group(group_set))) { | ||
562 | if (grp->group == group_f) { | ||
563 | switch (ioif) | ||
564 | { | ||
565 | case if_sync_serial_1: | ||
566 | if ((grp->owner == if_sync_serial_1) && | ||
567 | interfaces[if_sync_serial_3].used) { | ||
568 | grp->owner = if_sync_serial_3; | ||
569 | } else | ||
570 | grp->used = 0; | ||
571 | break; | ||
572 | case if_sync_serial_3: | ||
573 | if ((grp->owner == if_sync_serial_3) && | ||
574 | interfaces[if_sync_serial_1].used) { | ||
575 | grp->owner = if_sync_serial_1; | ||
576 | } else | ||
577 | grp->used = 0; | ||
578 | break; | ||
579 | case if_scsi8_0: | ||
580 | if ((grp->owner == if_scsi8_0) && | ||
581 | interfaces[if_scsi8_1].used) { | ||
582 | grp->owner = if_scsi8_1; | ||
583 | } else | ||
584 | grp->used = 0; | ||
585 | break; | ||
586 | case if_scsi8_1: | ||
587 | if ((grp->owner == if_scsi8_1) && | ||
588 | interfaces[if_scsi8_0].used) { | ||
589 | grp->owner = if_scsi8_0; | ||
590 | } else | ||
591 | grp->used = 0; | ||
592 | break; | ||
593 | default: | ||
594 | grp->used = 0; | ||
595 | } | ||
596 | } else { | ||
597 | grp->used = 0; | ||
598 | } | ||
599 | group_set = clear_group_from_set(group_set, grp); | ||
600 | } | ||
601 | interfaces[ioif].used = 0; | ||
602 | interfaces[ioif].owner = NULL; | ||
603 | |||
604 | DBG(printk("GPIO pins: available before: g_in=0x%08x g_out=0x%08x pb=0x%02x\n", | ||
605 | gpio_in_pins, gpio_out_pins, gpio_pb_pins)); | ||
606 | DBG(printk("freeing pins: g_in=0x%08x g_out=0x%08x pb=0x%02x\n", | ||
607 | interfaces[ioif].gpio_g_in, | ||
608 | interfaces[ioif].gpio_g_out, | ||
609 | interfaces[ioif].gpio_b)); | ||
610 | |||
611 | gpio_in_pins |= interfaces[ioif].gpio_g_in; | ||
612 | gpio_out_pins |= interfaces[ioif].gpio_g_out; | ||
613 | gpio_pb_pins |= interfaces[ioif].gpio_b; | ||
614 | |||
615 | DBG(printk("GPIO pins: available after: g_in=0x%08x g_out=0x%08x pb=0x%02x\n", | ||
616 | gpio_in_pins, gpio_out_pins, gpio_pb_pins)); | ||
617 | |||
618 | local_irq_restore(flags); | ||
619 | |||
620 | notify_watchers(); | ||
621 | } | ||
622 | |||
623 | /* Create a bitmask from bit 0 (inclusive) to bit stop_bit | ||
624 | (non-inclusive). stop_bit == 0 returns 0x0 */ | ||
625 | static inline unsigned int create_mask(const unsigned stop_bit) | ||
626 | { | ||
627 | /* Avoid overflow */ | ||
628 | if (stop_bit >= 32) { | ||
629 | return 0xffffffff; | ||
630 | } | ||
631 | return (1<<stop_bit)-1; | ||
632 | } | ||
633 | |||
634 | |||
635 | /* port can be 'a', 'b' or 'g' */ | ||
636 | int cris_io_interface_allocate_pins(const enum cris_io_interface ioif, | ||
637 | const char port, | ||
638 | const unsigned start_bit, | ||
639 | const unsigned stop_bit) | ||
640 | { | ||
641 | unsigned int i; | ||
642 | unsigned int mask = 0; | ||
643 | unsigned int tmp_mask; | ||
644 | unsigned long int flags; | ||
645 | enum cris_io_interface *owners; | ||
646 | |||
647 | (void)cris_io_interface_init(); | ||
648 | |||
649 | DBG(printk("cris_io_interface_allocate_pins: if=%d port=%c start=%u stop=%u\n", | ||
650 | ioif, port, start_bit, stop_bit)); | ||
651 | |||
652 | if (!((start_bit <= stop_bit) && | ||
653 | ((((port == 'a') || (port == 'b')) && (stop_bit < 8)) || | ||
654 | ((port == 'g') && (stop_bit < 32))))) { | ||
655 | return -EINVAL; | ||
656 | } | ||
657 | |||
658 | mask = create_mask(stop_bit + 1); | ||
659 | tmp_mask = create_mask(start_bit); | ||
660 | mask &= ~tmp_mask; | ||
661 | |||
662 | DBG(printk("cris_io_interface_allocate_pins: port=%c start=%u stop=%u mask=0x%08x\n", | ||
663 | port, start_bit, stop_bit, mask)); | ||
664 | |||
665 | local_irq_save(flags); | ||
666 | |||
667 | switch (port) { | ||
668 | case 'a': | ||
669 | if ((gpio_pa_pins & mask) != mask) { | ||
670 | local_irq_restore(flags); | ||
671 | return -EBUSY; | ||
672 | } | ||
673 | owners = gpio_pa_owners; | ||
674 | gpio_pa_pins &= ~mask; | ||
675 | break; | ||
676 | case 'b': | ||
677 | if ((gpio_pb_pins & mask) != mask) { | ||
678 | local_irq_restore(flags); | ||
679 | return -EBUSY; | ||
680 | } | ||
681 | owners = gpio_pb_owners; | ||
682 | gpio_pb_pins &= ~mask; | ||
683 | break; | ||
684 | case 'g': | ||
685 | if (((gpio_in_pins & mask) != mask) || | ||
686 | ((gpio_out_pins & mask) != mask)) { | ||
687 | local_irq_restore(flags); | ||
688 | return -EBUSY; | ||
689 | } | ||
690 | owners = gpio_pg_owners; | ||
691 | gpio_in_pins &= ~mask; | ||
692 | gpio_out_pins &= ~mask; | ||
693 | break; | ||
694 | default: | ||
695 | local_irq_restore(flags); | ||
696 | return -EINVAL; | ||
697 | } | ||
698 | |||
699 | for (i = start_bit; i <= stop_bit; i++) { | ||
700 | owners[i] = ioif; | ||
701 | } | ||
702 | local_irq_restore(flags); | ||
703 | |||
704 | notify_watchers(); | ||
705 | return 0; | ||
706 | } | ||
707 | |||
708 | |||
709 | /* port can be 'a', 'b' or 'g' */ | ||
710 | int cris_io_interface_free_pins(const enum cris_io_interface ioif, | ||
711 | const char port, | ||
712 | const unsigned start_bit, | ||
713 | const unsigned stop_bit) | ||
714 | { | ||
715 | unsigned int i; | ||
716 | unsigned int mask = 0; | ||
717 | unsigned int tmp_mask; | ||
718 | unsigned long int flags; | ||
719 | enum cris_io_interface *owners; | ||
720 | |||
721 | (void)cris_io_interface_init(); | ||
722 | |||
723 | if (!((start_bit <= stop_bit) && | ||
724 | ((((port == 'a') || (port == 'b')) && (stop_bit < 8)) || | ||
725 | ((port == 'g') && (stop_bit < 32))))) { | ||
726 | return -EINVAL; | ||
727 | } | ||
728 | |||
729 | mask = create_mask(stop_bit + 1); | ||
730 | tmp_mask = create_mask(start_bit); | ||
731 | mask &= ~tmp_mask; | ||
732 | |||
733 | DBG(printk("cris_io_interface_free_pins: port=%c start=%u stop=%u mask=0x%08x\n", | ||
734 | port, start_bit, stop_bit, mask)); | ||
735 | |||
736 | local_irq_save(flags); | ||
737 | |||
738 | switch (port) { | ||
739 | case 'a': | ||
740 | if ((~gpio_pa_pins & mask) != mask) { | ||
741 | local_irq_restore(flags); | ||
742 | printk(KERN_CRIT "cris_io_interface_free_pins: Freeing free pins"); | ||
743 | } | ||
744 | owners = gpio_pa_owners; | ||
745 | break; | ||
746 | case 'b': | ||
747 | if ((~gpio_pb_pins & mask) != mask) { | ||
748 | local_irq_restore(flags); | ||
749 | printk(KERN_CRIT "cris_io_interface_free_pins: Freeing free pins"); | ||
750 | } | ||
751 | owners = gpio_pb_owners; | ||
752 | break; | ||
753 | case 'g': | ||
754 | if (((~gpio_in_pins & mask) != mask) || | ||
755 | ((~gpio_out_pins & mask) != mask)) { | ||
756 | local_irq_restore(flags); | ||
757 | printk(KERN_CRIT "cris_io_interface_free_pins: Freeing free pins"); | ||
758 | } | ||
759 | owners = gpio_pg_owners; | ||
760 | break; | ||
761 | default: | ||
762 | owners = NULL; /* Cannot happen. Shut up, gcc! */ | ||
763 | } | ||
764 | |||
765 | for (i = start_bit; i <= stop_bit; i++) { | ||
766 | if (owners[i] != ioif) { | ||
767 | printk(KERN_CRIT "cris_io_interface_free_pins: Freeing unowned pins"); | ||
768 | } | ||
769 | } | ||
770 | |||
771 | /* All was ok, change data. */ | ||
772 | switch (port) { | ||
773 | case 'a': | ||
774 | gpio_pa_pins |= mask; | ||
775 | break; | ||
776 | case 'b': | ||
777 | gpio_pb_pins |= mask; | ||
778 | break; | ||
779 | case 'g': | ||
780 | gpio_in_pins |= mask; | ||
781 | gpio_out_pins |= mask; | ||
782 | break; | ||
783 | } | ||
784 | |||
785 | for (i = start_bit; i <= stop_bit; i++) { | ||
786 | owners[i] = if_unclaimed; | ||
787 | } | ||
788 | local_irq_restore(flags); | ||
789 | notify_watchers(); | ||
790 | |||
791 | return 0; | ||
792 | } | ||
793 | |||
794 | |||
795 | int cris_io_interface_register_watcher(void (*notify)(const unsigned int gpio_in_available, | ||
796 | const unsigned int gpio_out_available, | ||
797 | const unsigned char pa_available, | ||
798 | const unsigned char pb_available)) | ||
799 | { | ||
800 | struct watcher *w; | ||
801 | |||
802 | (void)cris_io_interface_init(); | ||
803 | |||
804 | if (NULL == notify) { | ||
805 | return -EINVAL; | ||
806 | } | ||
807 | w = kmalloc(sizeof(*w), GFP_KERNEL); | ||
808 | if (!w) { | ||
809 | return -ENOMEM; | ||
810 | } | ||
811 | w->notify = notify; | ||
812 | w->next = watchers; | ||
813 | watchers = w; | ||
814 | |||
815 | w->notify((const unsigned int)gpio_in_pins, | ||
816 | (const unsigned int)gpio_out_pins, | ||
817 | (const unsigned char)gpio_pa_pins, | ||
818 | (const unsigned char)gpio_pb_pins); | ||
819 | |||
820 | return 0; | ||
821 | } | ||
822 | |||
823 | void cris_io_interface_delete_watcher(void (*notify)(const unsigned int gpio_in_available, | ||
824 | const unsigned int gpio_out_available, | ||
825 | const unsigned char pa_available, | ||
826 | const unsigned char pb_available)) | ||
827 | { | ||
828 | struct watcher *w = watchers, *prev = NULL; | ||
829 | |||
830 | (void)cris_io_interface_init(); | ||
831 | |||
832 | while ((NULL != w) && (w->notify != notify)){ | ||
833 | prev = w; | ||
834 | w = w->next; | ||
835 | } | ||
836 | if (NULL != w) { | ||
837 | if (NULL != prev) { | ||
838 | prev->next = w->next; | ||
839 | } else { | ||
840 | watchers = w->next; | ||
841 | } | ||
842 | kfree(w); | ||
843 | return; | ||
844 | } | ||
845 | printk(KERN_WARNING "cris_io_interface_delete_watcher: Deleting unknown watcher 0x%p\n", notify); | ||
846 | } | ||
847 | |||
848 | |||
849 | static int cris_io_interface_init(void) | ||
850 | { | ||
851 | static int first = 1; | ||
852 | int i; | ||
853 | |||
854 | if (!first) { | ||
855 | return 0; | ||
856 | } | ||
857 | first = 0; | ||
858 | |||
859 | for (i = 0; i<8; i++) { | ||
860 | gpio_pa_owners[i] = if_unclaimed; | ||
861 | gpio_pb_owners[i] = if_unclaimed; | ||
862 | gpio_pg_owners[i] = if_unclaimed; | ||
863 | } | ||
864 | for (; i<32; i++) { | ||
865 | gpio_pg_owners[i] = if_unclaimed; | ||
866 | } | ||
867 | return 0; | ||
868 | } | ||
869 | |||
870 | |||
871 | module_init(cris_io_interface_init); | ||
872 | |||
873 | |||
874 | EXPORT_SYMBOL(cris_request_io_interface); | ||
875 | EXPORT_SYMBOL(cris_free_io_interface); | ||
876 | EXPORT_SYMBOL(cris_io_interface_allocate_pins); | ||
877 | EXPORT_SYMBOL(cris_io_interface_free_pins); | ||
878 | EXPORT_SYMBOL(cris_io_interface_register_watcher); | ||
879 | EXPORT_SYMBOL(cris_io_interface_delete_watcher); | ||
diff --git a/arch/cris/arch-v10/kernel/irq.c b/arch/cris/arch-v10/kernel/irq.c index b2f16d6fc871..4b368a122015 100644 --- a/arch/cris/arch-v10/kernel/irq.c +++ b/arch/cris/arch-v10/kernel/irq.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $Id: irq.c,v 1.2 2004/06/09 05:30:27 starvik Exp $ | 1 | /* $Id: irq.c,v 1.4 2005/01/04 12:22:28 starvik Exp $ |
2 | * | 2 | * |
3 | * linux/arch/cris/kernel/irq.c | 3 | * linux/arch/cris/kernel/irq.c |
4 | * | 4 | * |
@@ -12,11 +12,13 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <asm/irq.h> | 14 | #include <asm/irq.h> |
15 | #include <linux/irq.h> | ||
15 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
16 | #include <linux/init.h> | 17 | #include <linux/init.h> |
17 | #include <linux/config.h> | 18 | #include <linux/config.h> |
18 | 19 | ||
19 | irqvectptr irq_shortcuts[NR_IRQS]; /* vector of shortcut jumps after the irq prologue */ | 20 | #define mask_irq(irq_nr) (*R_VECT_MASK_CLR = 1 << (irq_nr)); |
21 | #define unmask_irq(irq_nr) (*R_VECT_MASK_SET = 1 << (irq_nr)); | ||
20 | 22 | ||
21 | /* don't use set_int_vector, it bypasses the linux interrupt handlers. it is | 23 | /* don't use set_int_vector, it bypasses the linux interrupt handlers. it is |
22 | * global just so that the kernel gdb can use it. | 24 | * global just so that the kernel gdb can use it. |
@@ -102,41 +104,52 @@ static void (*interrupt[NR_IRQS])(void) = { | |||
102 | IRQ31_interrupt | 104 | IRQ31_interrupt |
103 | }; | 105 | }; |
104 | 106 | ||
105 | static void (*bad_interrupt[NR_IRQS])(void) = { | 107 | static void enable_crisv10_irq(unsigned int irq); |
106 | NULL, NULL, | 108 | |
107 | NULL, bad_IRQ3_interrupt, | 109 | static unsigned int startup_crisv10_irq(unsigned int irq) |
108 | bad_IRQ4_interrupt, bad_IRQ5_interrupt, | 110 | { |
109 | bad_IRQ6_interrupt, bad_IRQ7_interrupt, | 111 | enable_crisv10_irq(irq); |
110 | bad_IRQ8_interrupt, bad_IRQ9_interrupt, | 112 | return 0; |
111 | bad_IRQ10_interrupt, bad_IRQ11_interrupt, | 113 | } |
112 | bad_IRQ12_interrupt, bad_IRQ13_interrupt, | 114 | |
113 | NULL, NULL, | 115 | #define shutdown_crisv10_irq disable_crisv10_irq |
114 | bad_IRQ16_interrupt, bad_IRQ17_interrupt, | ||
115 | bad_IRQ18_interrupt, bad_IRQ19_interrupt, | ||
116 | bad_IRQ20_interrupt, bad_IRQ21_interrupt, | ||
117 | bad_IRQ22_interrupt, bad_IRQ23_interrupt, | ||
118 | bad_IRQ24_interrupt, bad_IRQ25_interrupt, | ||
119 | NULL, NULL, NULL, NULL, NULL, | ||
120 | bad_IRQ31_interrupt | ||
121 | }; | ||
122 | 116 | ||
123 | void arch_setup_irq(int irq) | 117 | static void enable_crisv10_irq(unsigned int irq) |
124 | { | 118 | { |
125 | set_int_vector(irq, interrupt[irq]); | 119 | unmask_irq(irq); |
126 | } | 120 | } |
127 | 121 | ||
128 | void arch_free_irq(int irq) | 122 | static void disable_crisv10_irq(unsigned int irq) |
129 | { | 123 | { |
130 | set_int_vector(irq, bad_interrupt[irq]); | 124 | mask_irq(irq); |
131 | } | 125 | } |
132 | 126 | ||
127 | static void ack_crisv10_irq(unsigned int irq) | ||
128 | { | ||
129 | } | ||
130 | |||
131 | static void end_crisv10_irq(unsigned int irq) | ||
132 | { | ||
133 | } | ||
134 | |||
135 | static struct hw_interrupt_type crisv10_irq_type = { | ||
136 | .typename = "CRISv10", | ||
137 | .startup = startup_crisv10_irq, | ||
138 | .shutdown = shutdown_crisv10_irq, | ||
139 | .enable = enable_crisv10_irq, | ||
140 | .disable = disable_crisv10_irq, | ||
141 | .ack = ack_crisv10_irq, | ||
142 | .end = end_crisv10_irq, | ||
143 | .set_affinity = NULL | ||
144 | }; | ||
145 | |||
133 | void weird_irq(void); | 146 | void weird_irq(void); |
134 | void system_call(void); /* from entry.S */ | 147 | void system_call(void); /* from entry.S */ |
135 | void do_sigtrap(void); /* from entry.S */ | 148 | void do_sigtrap(void); /* from entry.S */ |
136 | void gdb_handle_breakpoint(void); /* from entry.S */ | 149 | void gdb_handle_breakpoint(void); /* from entry.S */ |
137 | 150 | ||
138 | /* init_IRQ() is called by start_kernel and is responsible for fixing IRQ masks and | 151 | /* init_IRQ() is called by start_kernel and is responsible for fixing IRQ masks and |
139 | setting the irq vector table to point to bad_interrupt ptrs. | 152 | setting the irq vector table. |
140 | */ | 153 | */ |
141 | 154 | ||
142 | void __init | 155 | void __init |
@@ -154,14 +167,15 @@ init_IRQ(void) | |||
154 | 167 | ||
155 | *R_VECT_MASK_CLR = 0xffffffff; | 168 | *R_VECT_MASK_CLR = 0xffffffff; |
156 | 169 | ||
157 | /* clear the shortcut entry points */ | ||
158 | |||
159 | for(i = 0; i < NR_IRQS; i++) | ||
160 | irq_shortcuts[i] = NULL; | ||
161 | |||
162 | for (i = 0; i < 256; i++) | 170 | for (i = 0; i < 256; i++) |
163 | etrax_irv->v[i] = weird_irq; | 171 | etrax_irv->v[i] = weird_irq; |
164 | 172 | ||
173 | /* Initialize IRQ handler descriptiors. */ | ||
174 | for(i = 2; i < NR_IRQS; i++) { | ||
175 | irq_desc[i].handler = &crisv10_irq_type; | ||
176 | set_int_vector(i, interrupt[i]); | ||
177 | } | ||
178 | |||
165 | /* the entries in the break vector contain actual code to be | 179 | /* the entries in the break vector contain actual code to be |
166 | executed by the associated break handler, rather than just a jump | 180 | executed by the associated break handler, rather than just a jump |
167 | address. therefore we need to setup a default breakpoint handler | 181 | address. therefore we need to setup a default breakpoint handler |
@@ -170,10 +184,6 @@ init_IRQ(void) | |||
170 | for (i = 0; i < 16; i++) | 184 | for (i = 0; i < 16; i++) |
171 | set_break_vector(i, do_sigtrap); | 185 | set_break_vector(i, do_sigtrap); |
172 | 186 | ||
173 | /* set all etrax irq's to the bad handlers */ | ||
174 | for (i = 2; i < NR_IRQS; i++) | ||
175 | set_int_vector(i, bad_interrupt[i]); | ||
176 | |||
177 | /* except IRQ 15 which is the multiple-IRQ handler on Etrax100 */ | 187 | /* except IRQ 15 which is the multiple-IRQ handler on Etrax100 */ |
178 | 188 | ||
179 | set_int_vector(15, multiple_interrupt); | 189 | set_int_vector(15, multiple_interrupt); |
diff --git a/arch/cris/arch-v10/kernel/kgdb.c b/arch/cris/arch-v10/kernel/kgdb.c index 7d368c877ee9..b72e6a91a639 100644 --- a/arch/cris/arch-v10/kernel/kgdb.c +++ b/arch/cris/arch-v10/kernel/kgdb.c | |||
@@ -18,6 +18,10 @@ | |||
18 | *! Jul 21 1999 Bjorn Wesen eLinux port | 18 | *! Jul 21 1999 Bjorn Wesen eLinux port |
19 | *! | 19 | *! |
20 | *! $Log: kgdb.c,v $ | 20 | *! $Log: kgdb.c,v $ |
21 | *! Revision 1.6 2005/01/14 10:12:17 starvik | ||
22 | *! KGDB on separate port. | ||
23 | *! Console fixes from 2.4. | ||
24 | *! | ||
21 | *! Revision 1.5 2004/10/07 13:59:08 starvik | 25 | *! Revision 1.5 2004/10/07 13:59:08 starvik |
22 | *! Corrected call to set_int_vector | 26 | *! Corrected call to set_int_vector |
23 | *! | 27 | *! |
@@ -71,7 +75,7 @@ | |||
71 | *! | 75 | *! |
72 | *!--------------------------------------------------------------------------- | 76 | *!--------------------------------------------------------------------------- |
73 | *! | 77 | *! |
74 | *! $Id: kgdb.c,v 1.5 2004/10/07 13:59:08 starvik Exp $ | 78 | *! $Id: kgdb.c,v 1.6 2005/01/14 10:12:17 starvik Exp $ |
75 | *! | 79 | *! |
76 | *! (C) Copyright 1999, Axis Communications AB, LUND, SWEDEN | 80 | *! (C) Copyright 1999, Axis Communications AB, LUND, SWEDEN |
77 | *! | 81 | *! |
@@ -225,6 +229,7 @@ | |||
225 | #include <linux/kernel.h> | 229 | #include <linux/kernel.h> |
226 | #include <linux/delay.h> | 230 | #include <linux/delay.h> |
227 | #include <linux/linkage.h> | 231 | #include <linux/linkage.h> |
232 | #include <linux/reboot.h> | ||
228 | 233 | ||
229 | #include <asm/setup.h> | 234 | #include <asm/setup.h> |
230 | #include <asm/ptrace.h> | 235 | #include <asm/ptrace.h> |
@@ -1344,12 +1349,11 @@ handle_exception (int sigval) | |||
1344 | } | 1349 | } |
1345 | } | 1350 | } |
1346 | 1351 | ||
1347 | /* The jump is to the address 0x00000002. Performs a complete re-start | 1352 | /* Performs a complete re-start from scratch. */ |
1348 | from scratch. */ | ||
1349 | static void | 1353 | static void |
1350 | kill_restart () | 1354 | kill_restart () |
1351 | { | 1355 | { |
1352 | __asm__ volatile ("jump 2"); | 1356 | machine_restart(""); |
1353 | } | 1357 | } |
1354 | 1358 | ||
1355 | /********************************** Breakpoint *******************************/ | 1359 | /********************************** Breakpoint *******************************/ |
@@ -1506,6 +1510,11 @@ kgdb_handle_serial: | |||
1506 | bne goback | 1510 | bne goback |
1507 | nop | 1511 | nop |
1508 | 1512 | ||
1513 | move.d [reg+0x5E], $r10 ; Get DCCR | ||
1514 | btstq 8, $r10 ; Test the U-flag. | ||
1515 | bmi goback | ||
1516 | nop | ||
1517 | |||
1509 | ;; | 1518 | ;; |
1510 | ;; Handle the communication | 1519 | ;; Handle the communication |
1511 | ;; | 1520 | ;; |
diff --git a/arch/cris/arch-v10/kernel/process.c b/arch/cris/arch-v10/kernel/process.c index 87ff37790827..69e28b4057e8 100644 --- a/arch/cris/arch-v10/kernel/process.c +++ b/arch/cris/arch-v10/kernel/process.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $Id: process.c,v 1.9 2004/10/19 13:07:37 starvik Exp $ | 1 | /* $Id: process.c,v 1.12 2004/12/27 11:18:32 starvik Exp $ |
2 | * | 2 | * |
3 | * linux/arch/cris/kernel/process.c | 3 | * linux/arch/cris/kernel/process.c |
4 | * | 4 | * |
@@ -101,6 +101,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | |||
101 | regs.r11 = (unsigned long)fn; | 101 | regs.r11 = (unsigned long)fn; |
102 | regs.r12 = (unsigned long)arg; | 102 | regs.r12 = (unsigned long)arg; |
103 | regs.irp = (unsigned long)kernel_thread_helper; | 103 | regs.irp = (unsigned long)kernel_thread_helper; |
104 | regs.dccr = 1 << I_DCCR_BITNR; | ||
104 | 105 | ||
105 | /* Ok, create the new process.. */ | 106 | /* Ok, create the new process.. */ |
106 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); | 107 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); |
diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c index 581ecabaae53..130dd214e41d 100644 --- a/arch/cris/arch-v10/kernel/ptrace.c +++ b/arch/cris/arch-v10/kernel/ptrace.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/ptrace.h> | 11 | #include <linux/ptrace.h> |
12 | #include <linux/user.h> | 12 | #include <linux/user.h> |
13 | #include <linux/signal.h> | 13 | #include <linux/signal.h> |
14 | #include <linux/security.h> | ||
14 | 15 | ||
15 | #include <asm/uaccess.h> | 16 | #include <asm/uaccess.h> |
16 | #include <asm/page.h> | 17 | #include <asm/page.h> |
@@ -86,9 +87,13 @@ sys_ptrace(long request, long pid, long addr, long data) | |||
86 | ret = -EPERM; | 87 | ret = -EPERM; |
87 | 88 | ||
88 | if (request == PTRACE_TRACEME) { | 89 | if (request == PTRACE_TRACEME) { |
90 | /* are we already being traced? */ | ||
89 | if (current->ptrace & PT_PTRACED) | 91 | if (current->ptrace & PT_PTRACED) |
90 | goto out; | 92 | goto out; |
91 | 93 | ret = security_ptrace(current->parent, current); | |
94 | if (ret) | ||
95 | goto out; | ||
96 | /* set the ptrace bit in the process flags. */ | ||
92 | current->ptrace |= PT_PTRACED; | 97 | current->ptrace |= PT_PTRACED; |
93 | ret = 0; | 98 | ret = 0; |
94 | goto out; | 99 | goto out; |
@@ -207,7 +212,7 @@ sys_ptrace(long request, long pid, long addr, long data) | |||
207 | case PTRACE_KILL: | 212 | case PTRACE_KILL: |
208 | ret = 0; | 213 | ret = 0; |
209 | 214 | ||
210 | if (child->state == TASK_ZOMBIE) | 215 | if (child->exit_state == EXIT_ZOMBIE) |
211 | break; | 216 | break; |
212 | 217 | ||
213 | child->exit_code = SIGKILL; | 218 | child->exit_code = SIGKILL; |
diff --git a/arch/cris/arch-v10/kernel/shadows.c b/arch/cris/arch-v10/kernel/shadows.c index 561a890a8e4c..38fd44dfbc5b 100644 --- a/arch/cris/arch-v10/kernel/shadows.c +++ b/arch/cris/arch-v10/kernel/shadows.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $Id: shadows.c,v 1.1 2001/12/17 13:59:27 bjornw Exp $ | 1 | /* $Id: shadows.c,v 1.2 2004/12/13 12:21:51 starvik Exp $ |
2 | * | 2 | * |
3 | * Various shadow registers. Defines for these are in include/asm-etrax100/io.h | 3 | * Various shadow registers. Defines for these are in include/asm-etrax100/io.h |
4 | */ | 4 | */ |
@@ -6,6 +6,7 @@ | |||
6 | /* Shadows for internal Etrax-registers */ | 6 | /* Shadows for internal Etrax-registers */ |
7 | 7 | ||
8 | unsigned long genconfig_shadow; | 8 | unsigned long genconfig_shadow; |
9 | unsigned long gen_config_ii_shadow; | ||
9 | unsigned long port_g_data_shadow; | 10 | unsigned long port_g_data_shadow; |
10 | unsigned char port_pa_dir_shadow; | 11 | unsigned char port_pa_dir_shadow; |
11 | unsigned char port_pa_data_shadow; | 12 | unsigned char port_pa_data_shadow; |
diff --git a/arch/cris/arch-v10/kernel/traps.c b/arch/cris/arch-v10/kernel/traps.c index da491f438a6e..34a27ea2052d 100644 --- a/arch/cris/arch-v10/kernel/traps.c +++ b/arch/cris/arch-v10/kernel/traps.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $Id: traps.c,v 1.2 2003/07/04 08:27:41 starvik Exp $ | 1 | /* $Id: traps.c,v 1.4 2005/04/24 18:47:55 starvik Exp $ |
2 | * | 2 | * |
3 | * linux/arch/cris/arch-v10/traps.c | 3 | * linux/arch/cris/arch-v10/traps.c |
4 | * | 4 | * |
@@ -16,6 +16,8 @@ | |||
16 | #include <asm/uaccess.h> | 16 | #include <asm/uaccess.h> |
17 | #include <asm/arch/sv_addr_ag.h> | 17 | #include <asm/arch/sv_addr_ag.h> |
18 | 18 | ||
19 | extern int raw_printk(const char *fmt, ...); | ||
20 | |||
19 | void | 21 | void |
20 | show_registers(struct pt_regs * regs) | 22 | show_registers(struct pt_regs * regs) |
21 | { | 23 | { |
@@ -26,18 +28,18 @@ show_registers(struct pt_regs * regs) | |||
26 | register. */ | 28 | register. */ |
27 | unsigned long usp = rdusp(); | 29 | unsigned long usp = rdusp(); |
28 | 30 | ||
29 | printk("IRP: %08lx SRP: %08lx DCCR: %08lx USP: %08lx MOF: %08lx\n", | 31 | raw_printk("IRP: %08lx SRP: %08lx DCCR: %08lx USP: %08lx MOF: %08lx\n", |
30 | regs->irp, regs->srp, regs->dccr, usp, regs->mof ); | 32 | regs->irp, regs->srp, regs->dccr, usp, regs->mof ); |
31 | printk(" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n", | 33 | raw_printk(" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n", |
32 | regs->r0, regs->r1, regs->r2, regs->r3); | 34 | regs->r0, regs->r1, regs->r2, regs->r3); |
33 | printk(" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n", | 35 | raw_printk(" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n", |
34 | regs->r4, regs->r5, regs->r6, regs->r7); | 36 | regs->r4, regs->r5, regs->r6, regs->r7); |
35 | printk(" r8: %08lx r9: %08lx r10: %08lx r11: %08lx\n", | 37 | raw_printk(" r8: %08lx r9: %08lx r10: %08lx r11: %08lx\n", |
36 | regs->r8, regs->r9, regs->r10, regs->r11); | 38 | regs->r8, regs->r9, regs->r10, regs->r11); |
37 | printk("r12: %08lx r13: %08lx oR10: %08lx\n", | 39 | raw_printk("r12: %08lx r13: %08lx oR10: %08lx sp: %08lx\n", |
38 | regs->r12, regs->r13, regs->orig_r10); | 40 | regs->r12, regs->r13, regs->orig_r10, regs); |
39 | printk("R_MMU_CAUSE: %08lx\n", (unsigned long)*R_MMU_CAUSE); | 41 | raw_printk("R_MMU_CAUSE: %08lx\n", (unsigned long)*R_MMU_CAUSE); |
40 | printk("Process %s (pid: %d, stackpage=%08lx)\n", | 42 | raw_printk("Process %s (pid: %d, stackpage=%08lx)\n", |
41 | current->comm, current->pid, (unsigned long)current); | 43 | current->comm, current->pid, (unsigned long)current); |
42 | 44 | ||
43 | /* | 45 | /* |
@@ -53,7 +55,7 @@ show_registers(struct pt_regs * regs) | |||
53 | if (usp != 0) | 55 | if (usp != 0) |
54 | show_stack (NULL, NULL); | 56 | show_stack (NULL, NULL); |
55 | 57 | ||
56 | printk("\nCode: "); | 58 | raw_printk("\nCode: "); |
57 | if(regs->irp < PAGE_OFFSET) | 59 | if(regs->irp < PAGE_OFFSET) |
58 | goto bad; | 60 | goto bad; |
59 | 61 | ||
@@ -70,16 +72,16 @@ show_registers(struct pt_regs * regs) | |||
70 | unsigned char c; | 72 | unsigned char c; |
71 | if(__get_user(c, &((unsigned char*)regs->irp)[i])) { | 73 | if(__get_user(c, &((unsigned char*)regs->irp)[i])) { |
72 | bad: | 74 | bad: |
73 | printk(" Bad IP value."); | 75 | raw_printk(" Bad IP value."); |
74 | break; | 76 | break; |
75 | } | 77 | } |
76 | 78 | ||
77 | if (i == 0) | 79 | if (i == 0) |
78 | printk("(%02x) ", c); | 80 | raw_printk("(%02x) ", c); |
79 | else | 81 | else |
80 | printk("%02x ", c); | 82 | raw_printk("%02x ", c); |
81 | } | 83 | } |
82 | printk("\n"); | 84 | raw_printk("\n"); |
83 | } | 85 | } |
84 | } | 86 | } |
85 | 87 | ||
@@ -121,7 +123,7 @@ die_if_kernel(const char * str, struct pt_regs * regs, long err) | |||
121 | stop_watchdog(); | 123 | stop_watchdog(); |
122 | #endif | 124 | #endif |
123 | 125 | ||
124 | printk("%s: %04lx\n", str, err & 0xffff); | 126 | raw_printk("%s: %04lx\n", str, err & 0xffff); |
125 | 127 | ||
126 | show_registers(regs); | 128 | show_registers(regs); |
127 | 129 | ||
@@ -130,3 +132,8 @@ die_if_kernel(const char * str, struct pt_regs * regs, long err) | |||
130 | #endif | 132 | #endif |
131 | do_exit(SIGSEGV); | 133 | do_exit(SIGSEGV); |
132 | } | 134 | } |
135 | |||
136 | void arch_enable_nmi(void) | ||
137 | { | ||
138 | asm volatile("setf m"); | ||
139 | } | ||