diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/cris/arch-v32/kernel/debugport.c | 342 |
1 files changed, 43 insertions, 299 deletions
diff --git a/arch/cris/arch-v32/kernel/debugport.c b/arch/cris/arch-v32/kernel/debugport.c index d1272ad92153..15af4c293157 100644 --- a/arch/cris/arch-v32/kernel/debugport.c +++ b/arch/cris/arch-v32/kernel/debugport.c | |||
@@ -4,17 +4,12 @@ | |||
4 | 4 | ||
5 | #include <linux/console.h> | 5 | #include <linux/console.h> |
6 | #include <linux/init.h> | 6 | #include <linux/init.h> |
7 | #include <linux/major.h> | ||
8 | #include <linux/delay.h> | ||
9 | #include <linux/tty.h> | ||
10 | #include <asm/system.h> | 7 | #include <asm/system.h> |
11 | #include <asm/io.h> | 8 | #include <hwregs/reg_rdwr.h> |
12 | #include <asm/arch/hwregs/ser_defs.h> | 9 | #include <hwregs/reg_map.h> |
13 | #include <asm/arch/hwregs/dma_defs.h> | 10 | #include <hwregs/ser_defs.h> |
14 | #include <asm/arch/pinmux.h> | 11 | #include <hwregs/dma_defs.h> |
15 | 12 | #include <asm/arch/mach/pinmux.h> | |
16 | #include <asm/irq.h> | ||
17 | #include <asm/arch/hwregs/intr_vect_defs.h> | ||
18 | 13 | ||
19 | struct dbg_port | 14 | struct dbg_port |
20 | { | 15 | { |
@@ -59,45 +54,50 @@ struct dbg_port ports[] = | |||
59 | 115200, | 54 | 115200, |
60 | 'N', | 55 | 'N', |
61 | 8 | 56 | 8 |
62 | } | 57 | }, |
58 | #if CONFIG_ETRAX_SERIAL_PORTS == 5 | ||
59 | { | ||
60 | 4, | ||
61 | regi_ser4, | ||
62 | 0, | ||
63 | 115200, | ||
64 | 'N', | ||
65 | 8 | ||
66 | }, | ||
67 | #endif | ||
63 | }; | 68 | }; |
64 | static struct dbg_port *port = | 69 | static struct dbg_port *port = |
65 | #if defined(CONFIG_ETRAX_DEBUG_PORT0) | 70 | #if defined(CONFIG_ETRAX_DEBUG_PORT0) |
66 | &ports[0]; | 71 | &ports[0]; |
67 | #elif defined(CONFIG_ETRAX_DEBUG_PORT1) | 72 | #elif defined(CONFIG_ETRAX_DEBUG_PORT1) |
68 | &ports[1]; | 73 | &ports[1]; |
69 | #elif defined(CONFIG_ETRAX_DEBUG_PORT2) | 74 | #elif defined(CONFIG_ETRAX_DEBUG_PORT2) |
70 | &ports[2]; | 75 | &ports[2]; |
71 | #elif defined(CONFIG_ETRAX_DEBUG_PORT3) | 76 | #elif defined(CONFIG_ETRAX_DEBUG_PORT3) |
72 | &ports[3]; | 77 | &ports[3]; |
78 | #elif defined(CONFIG_ETRAX_DEBUG_PORT4) | ||
79 | &ports[4]; | ||
73 | #else | 80 | #else |
74 | NULL; | 81 | NULL; |
75 | #endif | 82 | #endif |
76 | 83 | ||
77 | #ifdef CONFIG_ETRAX_KGDB | 84 | #ifdef CONFIG_ETRAX_KGDB |
78 | static struct dbg_port *kgdb_port = | 85 | static struct dbg_port *kgdb_port = |
79 | #if defined(CONFIG_ETRAX_KGDB_PORT0) | 86 | #if defined(CONFIG_ETRAX_KGDB_PORT0) |
80 | &ports[0]; | 87 | &ports[0]; |
81 | #elif defined(CONFIG_ETRAX_KGDB_PORT1) | 88 | #elif defined(CONFIG_ETRAX_KGDB_PORT1) |
82 | &ports[1]; | 89 | &ports[1]; |
83 | #elif defined(CONFIG_ETRAX_KGDB_PORT2) | 90 | #elif defined(CONFIG_ETRAX_KGDB_PORT2) |
84 | &ports[2]; | 91 | &ports[2]; |
85 | #elif defined(CONFIG_ETRAX_KGDB_PORT3) | 92 | #elif defined(CONFIG_ETRAX_KGDB_PORT3) |
86 | &ports[3]; | 93 | &ports[3]; |
94 | #elif defined(CONFIG_ETRAX_KGDB_PORT4) | ||
95 | &ports[4]; | ||
87 | #else | 96 | #else |
88 | NULL; | 97 | NULL; |
89 | #endif | 98 | #endif |
90 | #endif | 99 | #endif |
91 | 100 | ||
92 | #ifdef CONFIG_ETRAXFS_SIM | ||
93 | extern void print_str( const char *str ); | ||
94 | static char buffer[1024]; | ||
95 | static char msg[] = "Debug: "; | ||
96 | static int buffer_pos = sizeof(msg) - 1; | ||
97 | #endif | ||
98 | |||
99 | extern struct tty_driver *serial_driver; | ||
100 | |||
101 | static void | 101 | static void |
102 | start_port(struct dbg_port* p) | 102 | start_port(struct dbg_port* p) |
103 | { | 103 | { |
@@ -114,6 +114,10 @@ start_port(struct dbg_port* p) | |||
114 | crisv32_pinmux_alloc_fixed(pinmux_ser2); | 114 | crisv32_pinmux_alloc_fixed(pinmux_ser2); |
115 | else if (p->nbr == 3) | 115 | else if (p->nbr == 3) |
116 | crisv32_pinmux_alloc_fixed(pinmux_ser3); | 116 | crisv32_pinmux_alloc_fixed(pinmux_ser3); |
117 | #if CONFIG_ETRAX_SERIAL_PORTS == 5 | ||
118 | else if (p->nbr == 4) | ||
119 | crisv32_pinmux_alloc_fixed(pinmux_ser4); | ||
120 | #endif | ||
117 | 121 | ||
118 | /* Set up serial port registers */ | 122 | /* Set up serial port registers */ |
119 | reg_ser_rw_tr_ctrl tr_ctrl = {0}; | 123 | reg_ser_rw_tr_ctrl tr_ctrl = {0}; |
@@ -156,124 +160,21 @@ start_port(struct dbg_port* p) | |||
156 | REG_WR (ser, p->instance, rw_rec_ctrl, rec_ctrl); | 160 | REG_WR (ser, p->instance, rw_rec_ctrl, rec_ctrl); |
157 | } | 161 | } |
158 | 162 | ||
159 | /* No debug */ | ||
160 | #ifdef CONFIG_ETRAX_DEBUG_PORT_NULL | ||
161 | |||
162 | static void | ||
163 | console_write(struct console *co, const char *buf, unsigned int len) | ||
164 | { | ||
165 | return; | ||
166 | } | ||
167 | |||
168 | /* Target debug */ | ||
169 | #elif !defined(CONFIG_ETRAXFS_SIM) | ||
170 | |||
171 | static void | ||
172 | console_write_direct(struct console *co, const char *buf, unsigned int len) | ||
173 | { | ||
174 | int i; | ||
175 | reg_ser_r_stat_din stat; | ||
176 | reg_ser_rw_tr_dma_en tr_dma_en, old; | ||
177 | |||
178 | /* Switch to manual mode */ | ||
179 | tr_dma_en = old = REG_RD (ser, port->instance, rw_tr_dma_en); | ||
180 | if (tr_dma_en.en == regk_ser_yes) { | ||
181 | tr_dma_en.en = regk_ser_no; | ||
182 | REG_WR(ser, port->instance, rw_tr_dma_en, tr_dma_en); | ||
183 | } | ||
184 | |||
185 | /* Send data */ | ||
186 | for (i = 0; i < len; i++) { | ||
187 | /* LF -> CRLF */ | ||
188 | if (buf[i] == '\n') { | ||
189 | do { | ||
190 | stat = REG_RD (ser, port->instance, r_stat_din); | ||
191 | } while (!stat.tr_rdy); | ||
192 | REG_WR_INT (ser, port->instance, rw_dout, '\r'); | ||
193 | } | ||
194 | /* Wait until transmitter is ready and send.*/ | ||
195 | do { | ||
196 | stat = REG_RD (ser, port->instance, r_stat_din); | ||
197 | } while (!stat.tr_rdy); | ||
198 | REG_WR_INT (ser, port->instance, rw_dout, buf[i]); | ||
199 | } | ||
200 | |||
201 | /* Restore mode */ | ||
202 | if (tr_dma_en.en != old.en) | ||
203 | REG_WR(ser, port->instance, rw_tr_dma_en, old); | ||
204 | } | ||
205 | |||
206 | static void | ||
207 | console_write(struct console *co, const char *buf, unsigned int len) | ||
208 | { | ||
209 | if (!port) | ||
210 | return; | ||
211 | console_write_direct(co, buf, len); | ||
212 | } | ||
213 | |||
214 | |||
215 | |||
216 | #else | ||
217 | |||
218 | /* VCS debug */ | ||
219 | |||
220 | static void | ||
221 | console_write(struct console *co, const char *buf, unsigned int len) | ||
222 | { | ||
223 | char* pos; | ||
224 | pos = memchr(buf, '\n', len); | ||
225 | if (pos) { | ||
226 | int l = ++pos - buf; | ||
227 | memcpy(buffer + buffer_pos, buf, l); | ||
228 | memcpy(buffer, msg, sizeof(msg) - 1); | ||
229 | buffer[buffer_pos + l] = '\0'; | ||
230 | print_str(buffer); | ||
231 | buffer_pos = sizeof(msg) - 1; | ||
232 | if (pos - buf != len) { | ||
233 | memcpy(buffer + buffer_pos, pos, len - l); | ||
234 | buffer_pos += len - l; | ||
235 | } | ||
236 | } else { | ||
237 | memcpy(buffer + buffer_pos, buf, len); | ||
238 | buffer_pos += len; | ||
239 | } | ||
240 | } | ||
241 | |||
242 | #endif | ||
243 | |||
244 | int raw_printk(const char *fmt, ...) | ||
245 | { | ||
246 | static char buf[1024]; | ||
247 | int printed_len; | ||
248 | va_list args; | ||
249 | va_start(args, fmt); | ||
250 | printed_len = vsnprintf(buf, sizeof(buf), fmt, args); | ||
251 | va_end(args); | ||
252 | console_write(NULL, buf, strlen(buf)); | ||
253 | return printed_len; | ||
254 | } | ||
255 | |||
256 | void | ||
257 | stupid_debug(char* buf) | ||
258 | { | ||
259 | console_write(NULL, buf, strlen(buf)); | ||
260 | } | ||
261 | |||
262 | #ifdef CONFIG_ETRAX_KGDB | 163 | #ifdef CONFIG_ETRAX_KGDB |
263 | /* Use polling to get a single character from the kernel debug port */ | 164 | /* Use polling to get a single character from the kernel debug port */ |
264 | int | 165 | int |
265 | getDebugChar(void) | 166 | getDebugChar(void) |
266 | { | 167 | { |
267 | reg_ser_rs_status_data stat; | 168 | reg_ser_rs_stat_din stat; |
268 | reg_ser_rw_ack_intr ack_intr = { 0 }; | 169 | reg_ser_rw_ack_intr ack_intr = { 0 }; |
269 | 170 | ||
270 | do { | 171 | do { |
271 | stat = REG_RD(ser, kgdb_instance, rs_status_data); | 172 | stat = REG_RD(ser, kgdb_port->instance, rs_stat_din); |
272 | } while (!stat.data_avail); | 173 | } while (!stat.dav); |
273 | 174 | ||
274 | /* Ack the data_avail interrupt. */ | 175 | /* Ack the data_avail interrupt. */ |
275 | ack_intr.data_avail = 1; | 176 | ack_intr.dav = 1; |
276 | REG_WR(ser, kgdb_instance, rw_ack_intr, ack_intr); | 177 | REG_WR(ser, kgdb_port->instance, rw_ack_intr, ack_intr); |
277 | 178 | ||
278 | return stat.data; | 179 | return stat.data; |
279 | } | 180 | } |
@@ -282,173 +183,18 @@ getDebugChar(void) | |||
282 | void | 183 | void |
283 | putDebugChar(int val) | 184 | putDebugChar(int val) |
284 | { | 185 | { |
285 | reg_ser_r_status_data stat; | 186 | reg_ser_r_stat_din stat; |
286 | do { | 187 | do { |
287 | stat = REG_RD (ser, kgdb_instance, r_status_data); | 188 | stat = REG_RD(ser, kgdb_port->instance, r_stat_din); |
288 | } while (!stat.tr_ready); | 189 | } while (!stat.tr_rdy); |
289 | REG_WR (ser, kgdb_instance, rw_data_out, REG_TYPE_CONV(reg_ser_rw_data_out, int, val)); | 190 | REG_WR_INT(ser, kgdb_port->instance, rw_dout, val); |
290 | } | 191 | } |
291 | #endif /* CONFIG_ETRAX_KGDB */ | 192 | #endif /* CONFIG_ETRAX_KGDB */ |
292 | 193 | ||
293 | static int __init | ||
294 | console_setup(struct console *co, char *options) | ||
295 | { | ||
296 | char* s; | ||
297 | |||
298 | if (options) { | ||
299 | port = &ports[co->index]; | ||
300 | port->baudrate = 115200; | ||
301 | port->parity = 'N'; | ||
302 | port->bits = 8; | ||
303 | port->baudrate = simple_strtoul(options, NULL, 10); | ||
304 | s = options; | ||
305 | while(*s >= '0' && *s <= '9') | ||
306 | s++; | ||
307 | if (*s) port->parity = *s++; | ||
308 | if (*s) port->bits = *s++ - '0'; | ||
309 | port->started = 0; | ||
310 | start_port(port); | ||
311 | } | ||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | /* This is a dummy serial device that throws away anything written to it. | ||
316 | * This is used when no debug output is wanted. | ||
317 | */ | ||
318 | static struct tty_driver dummy_driver; | ||
319 | |||
320 | static int dummy_open(struct tty_struct *tty, struct file * filp) | ||
321 | { | ||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | static void dummy_close(struct tty_struct *tty, struct file * filp) | ||
326 | { | ||
327 | } | ||
328 | |||
329 | static int dummy_write(struct tty_struct * tty, | ||
330 | const unsigned char *buf, int count) | ||
331 | { | ||
332 | return count; | ||
333 | } | ||
334 | |||
335 | static int | ||
336 | dummy_write_room(struct tty_struct *tty) | ||
337 | { | ||
338 | return 8192; | ||
339 | } | ||
340 | |||
341 | void __init | ||
342 | init_dummy_console(void) | ||
343 | { | ||
344 | memset(&dummy_driver, 0, sizeof(struct tty_driver)); | ||
345 | dummy_driver.driver_name = "serial"; | ||
346 | dummy_driver.name = "ttyS"; | ||
347 | dummy_driver.major = TTY_MAJOR; | ||
348 | dummy_driver.minor_start = 68; | ||
349 | dummy_driver.num = 1; /* etrax100 has 4 serial ports */ | ||
350 | dummy_driver.type = TTY_DRIVER_TYPE_SERIAL; | ||
351 | dummy_driver.subtype = SERIAL_TYPE_NORMAL; | ||
352 | dummy_driver.init_termios = tty_std_termios; | ||
353 | dummy_driver.init_termios.c_cflag = | ||
354 | B115200 | CS8 | CREAD | HUPCL | CLOCAL; /* is normally B9600 default... */ | ||
355 | dummy_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; | ||
356 | |||
357 | dummy_driver.open = dummy_open; | ||
358 | dummy_driver.close = dummy_close; | ||
359 | dummy_driver.write = dummy_write; | ||
360 | dummy_driver.write_room = dummy_write_room; | ||
361 | if (tty_register_driver(&dummy_driver)) | ||
362 | panic("Couldn't register dummy serial driver\n"); | ||
363 | } | ||
364 | |||
365 | static struct tty_driver* | ||
366 | crisv32_console_device(struct console* co, int *index) | ||
367 | { | ||
368 | if (port) | ||
369 | *index = port->nbr; | ||
370 | return port ? serial_driver : &dummy_driver; | ||
371 | } | ||
372 | |||
373 | static struct console sercons = { | ||
374 | name : "ttyS", | ||
375 | write: console_write, | ||
376 | read : NULL, | ||
377 | device : crisv32_console_device, | ||
378 | unblank : NULL, | ||
379 | setup : console_setup, | ||
380 | flags : CON_PRINTBUFFER, | ||
381 | index : -1, | ||
382 | cflag : 0, | ||
383 | next : NULL | ||
384 | }; | ||
385 | static struct console sercons0 = { | ||
386 | name : "ttyS", | ||
387 | write: console_write, | ||
388 | read : NULL, | ||
389 | device : crisv32_console_device, | ||
390 | unblank : NULL, | ||
391 | setup : console_setup, | ||
392 | flags : CON_PRINTBUFFER, | ||
393 | index : 0, | ||
394 | cflag : 0, | ||
395 | next : NULL | ||
396 | }; | ||
397 | |||
398 | static struct console sercons1 = { | ||
399 | name : "ttyS", | ||
400 | write: console_write, | ||
401 | read : NULL, | ||
402 | device : crisv32_console_device, | ||
403 | unblank : NULL, | ||
404 | setup : console_setup, | ||
405 | flags : CON_PRINTBUFFER, | ||
406 | index : 1, | ||
407 | cflag : 0, | ||
408 | next : NULL | ||
409 | }; | ||
410 | static struct console sercons2 = { | ||
411 | name : "ttyS", | ||
412 | write: console_write, | ||
413 | read : NULL, | ||
414 | device : crisv32_console_device, | ||
415 | unblank : NULL, | ||
416 | setup : console_setup, | ||
417 | flags : CON_PRINTBUFFER, | ||
418 | index : 2, | ||
419 | cflag : 0, | ||
420 | next : NULL | ||
421 | }; | ||
422 | static struct console sercons3 = { | ||
423 | name : "ttyS", | ||
424 | write: console_write, | ||
425 | read : NULL, | ||
426 | device : crisv32_console_device, | ||
427 | unblank : NULL, | ||
428 | setup : console_setup, | ||
429 | flags : CON_PRINTBUFFER, | ||
430 | index : 3, | ||
431 | cflag : 0, | ||
432 | next : NULL | ||
433 | }; | ||
434 | |||
435 | /* Register console for printk's, etc. */ | 194 | /* Register console for printk's, etc. */ |
436 | int __init | 195 | int __init |
437 | init_etrax_debug(void) | 196 | init_etrax_debug(void) |
438 | { | 197 | { |
439 | static int first = 1; | ||
440 | |||
441 | if (!first) { | ||
442 | unregister_console(&sercons); | ||
443 | register_console(&sercons0); | ||
444 | register_console(&sercons1); | ||
445 | register_console(&sercons2); | ||
446 | register_console(&sercons3); | ||
447 | init_dummy_console(); | ||
448 | return 0; | ||
449 | } | ||
450 | first = 0; | ||
451 | register_console(&sercons); | ||
452 | start_port(port); | 198 | start_port(port); |
453 | 199 | ||
454 | #ifdef CONFIG_ETRAX_KGDB | 200 | #ifdef CONFIG_ETRAX_KGDB |
@@ -456,5 +202,3 @@ init_etrax_debug(void) | |||
456 | #endif /* CONFIG_ETRAX_KGDB */ | 202 | #endif /* CONFIG_ETRAX_KGDB */ |
457 | return 0; | 203 | return 0; |
458 | } | 204 | } |
459 | |||
460 | __initcall(init_etrax_debug); | ||