blob: 4c04cec67f9ec99c8e9ad5aba7e89e66c63d956d [file] [log] [blame]
Iliyan Malchevc1db50b2010-06-05 17:36:24 -07001/*
2 * arch/arm/common/fiq_debugger.c
3 *
4 * Serial Debugger Interface accessed through an FIQ interrupt.
5 *
6 * Copyright (C) 2008 Google, Inc.
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <stdarg.h>
19#include <linux/module.h>
20#include <linux/io.h>
Colin Cross4df8d7b2010-08-16 14:51:51 -070021#include <linux/console.h>
Iliyan Malchevc1db50b2010-06-05 17:36:24 -070022#include <linux/interrupt.h>
23#include <linux/clk.h>
24#include <linux/platform_device.h>
25#include <linux/kernel_debugger.h>
26#include <linux/kernel_stat.h>
27#include <linux/irq.h>
28#include <linux/delay.h>
29#include <linux/sched.h>
30#include <linux/slab.h>
Dima Zavin83b72702011-10-02 20:35:47 -070031#include <linux/smp.h>
Iliyan Malchevc1db50b2010-06-05 17:36:24 -070032#include <linux/timer.h>
Colin Cross4df8d7b2010-08-16 14:51:51 -070033#include <linux/tty.h>
34#include <linux/tty_flip.h>
Iliyan Malchevc1db50b2010-06-05 17:36:24 -070035#include <linux/wakelock.h>
36
37#include <asm/fiq_debugger.h>
38#include <asm/fiq_glue.h>
39#include <asm/stacktrace.h>
40
41#include <mach/system.h>
42
43#include <linux/uaccess.h>
44
Colin Cross4df8d7b2010-08-16 14:51:51 -070045#include "fiq_debugger_ringbuf.h"
46
Iliyan Malchevc1db50b2010-06-05 17:36:24 -070047#define DEBUG_MAX 64
Colin Cross24b3bd42010-10-01 23:41:38 -070048#define MAX_UNHANDLED_FIQ_COUNT 1000000
49
50#define THREAD_INFO(sp) ((struct thread_info *) \
51 ((unsigned long)(sp) & ~(THREAD_SIZE - 1)))
Iliyan Malchevc1db50b2010-06-05 17:36:24 -070052
53struct fiq_debugger_state {
54 struct fiq_glue_handler handler;
55
56 int fiq;
Dima Zavin83b72702011-10-02 20:35:47 -070057 int uart_irq;
Iliyan Malchevc1db50b2010-06-05 17:36:24 -070058 int signal_irq;
59 int wakeup_irq;
60 bool wakeup_irq_no_set_wake;
61 struct clk *clk;
62 struct fiq_debugger_pdata *pdata;
63 struct platform_device *pdev;
64
65 char debug_cmd[DEBUG_MAX];
66 int debug_busy;
67 int debug_abort;
68
69 char debug_buf[DEBUG_MAX];
70 int debug_count;
71
72 bool no_sleep;
73 bool debug_enable;
74 bool ignore_next_wakeup_irq;
75 struct timer_list sleep_timer;
76 bool uart_clk_enabled;
77 struct wake_lock debugger_wake_lock;
Colin Cross4df8d7b2010-08-16 14:51:51 -070078 bool console_enable;
Colin Cross24b3bd42010-10-01 23:41:38 -070079 int current_cpu;
80 atomic_t unhandled_fiq_count;
81 bool in_fiq;
Colin Cross4df8d7b2010-08-16 14:51:51 -070082
83#ifdef CONFIG_FIQ_DEBUGGER_CONSOLE
84 struct console console;
85 struct tty_driver *tty_driver;
86 struct tty_struct *tty;
87 int tty_open_count;
88 struct fiq_debugger_ringbuf *tty_rbuf;
89#endif
Iliyan Malchevc1db50b2010-06-05 17:36:24 -070090
91 unsigned int last_irqs[NR_IRQS];
Rebecca Schultz Zavinb824eef2010-10-22 15:55:17 -070092 unsigned int last_local_timer_irqs[NR_CPUS];
Iliyan Malchevc1db50b2010-06-05 17:36:24 -070093};
94
95#ifdef CONFIG_FIQ_DEBUGGER_NO_SLEEP
96static bool initial_no_sleep = true;
97#else
98static bool initial_no_sleep;
99#endif
Dima Zavinc6fba162010-11-10 15:39:07 -0800100
101#ifdef CONFIG_FIQ_DEBUGGER_CONSOLE_DEFAULT_ENABLE
102static bool initial_debug_enable = true;
103static bool initial_console_enable = true;
104#else
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700105static bool initial_debug_enable;
Colin Cross4df8d7b2010-08-16 14:51:51 -0700106static bool initial_console_enable;
Dima Zavinc6fba162010-11-10 15:39:07 -0800107#endif
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700108
109module_param_named(no_sleep, initial_no_sleep, bool, 0644);
110module_param_named(debug_enable, initial_debug_enable, bool, 0644);
Colin Cross4df8d7b2010-08-16 14:51:51 -0700111module_param_named(console_enable, initial_console_enable, bool, 0644);
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700112
113#ifdef CONFIG_FIQ_DEBUGGER_WAKEUP_IRQ_ALWAYS_ON
114static inline void enable_wakeup_irq(struct fiq_debugger_state *state) {}
115static inline void disable_wakeup_irq(struct fiq_debugger_state *state) {}
116#else
117static inline void enable_wakeup_irq(struct fiq_debugger_state *state)
118{
119 if (state->wakeup_irq < 0)
120 return;
121 enable_irq(state->wakeup_irq);
122 if (!state->wakeup_irq_no_set_wake)
123 enable_irq_wake(state->wakeup_irq);
124}
125static inline void disable_wakeup_irq(struct fiq_debugger_state *state)
126{
127 if (state->wakeup_irq < 0)
128 return;
129 disable_irq_nosync(state->wakeup_irq);
130 if (!state->wakeup_irq_no_set_wake)
131 disable_irq_wake(state->wakeup_irq);
132}
133#endif
134
Dima Zavin83b72702011-10-02 20:35:47 -0700135static bool inline debug_have_fiq(struct fiq_debugger_state *state)
136{
137 return (state->fiq >= 0);
138}
139
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700140static void debug_force_irq(struct fiq_debugger_state *state)
141{
142 unsigned int irq = state->signal_irq;
Dima Zavin83b72702011-10-02 20:35:47 -0700143
144 if (WARN_ON(!debug_have_fiq(state)))
145 return;
146 if (state->pdata->force_irq) {
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700147 state->pdata->force_irq(state->pdev, irq);
Dima Zavin83b72702011-10-02 20:35:47 -0700148 } else {
Colin Cross999853b2011-04-08 17:26:06 -0700149 struct irq_chip *chip = irq_get_chip(irq);
150 if (chip && chip->irq_retrigger)
151 chip->irq_retrigger(irq_get_irq_data(irq));
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700152 }
153}
154
155static void debug_uart_flush(struct fiq_debugger_state *state)
156{
157 if (state->pdata->uart_flush)
158 state->pdata->uart_flush(state->pdev);
159}
160
161static void debug_puts(struct fiq_debugger_state *state, char *s)
162{
163 unsigned c;
164 while ((c = *s++)) {
165 if (c == '\n')
166 state->pdata->uart_putc(state->pdev, '\r');
167 state->pdata->uart_putc(state->pdev, c);
168 }
169}
170
171static void debug_prompt(struct fiq_debugger_state *state)
172{
173 debug_puts(state, "debug> ");
174}
175
176int log_buf_copy(char *dest, int idx, int len);
177static void dump_kernel_log(struct fiq_debugger_state *state)
178{
179 char buf[1024];
180 int idx = 0;
181 int ret;
182 int saved_oip;
183
184 /* setting oops_in_progress prevents log_buf_copy()
185 * from trying to take a spinlock which will make it
186 * very unhappy in some cases...
187 */
188 saved_oip = oops_in_progress;
189 oops_in_progress = 1;
190 for (;;) {
191 ret = log_buf_copy(buf, idx, 1023);
192 if (ret <= 0)
193 break;
194 buf[ret] = 0;
195 debug_puts(state, buf);
196 idx += ret;
197 }
198 oops_in_progress = saved_oip;
199}
200
201static char *mode_name(unsigned cpsr)
202{
203 switch (cpsr & MODE_MASK) {
204 case USR_MODE: return "USR";
205 case FIQ_MODE: return "FIQ";
206 case IRQ_MODE: return "IRQ";
207 case SVC_MODE: return "SVC";
208 case ABT_MODE: return "ABT";
209 case UND_MODE: return "UND";
210 case SYSTEM_MODE: return "SYS";
211 default: return "???";
212 }
213}
214
215static int debug_printf(void *cookie, const char *fmt, ...)
216{
217 struct fiq_debugger_state *state = cookie;
218 char buf[256];
219 va_list ap;
220
221 va_start(ap, fmt);
222 vsnprintf(buf, sizeof(buf), fmt, ap);
223 va_end(ap);
224
225 debug_puts(state, buf);
226 return state->debug_abort;
227}
228
229/* Safe outside fiq context */
230static int debug_printf_nfiq(void *cookie, const char *fmt, ...)
231{
232 struct fiq_debugger_state *state = cookie;
233 char buf[256];
234 va_list ap;
235 unsigned long irq_flags;
236
237 va_start(ap, fmt);
238 vsnprintf(buf, 128, fmt, ap);
239 va_end(ap);
240
241 local_irq_save(irq_flags);
242 debug_puts(state, buf);
243 debug_uart_flush(state);
244 local_irq_restore(irq_flags);
245 return state->debug_abort;
246}
247
248static void dump_regs(struct fiq_debugger_state *state, unsigned *regs)
249{
250 debug_printf(state, " r0 %08x r1 %08x r2 %08x r3 %08x\n",
251 regs[0], regs[1], regs[2], regs[3]);
252 debug_printf(state, " r4 %08x r5 %08x r6 %08x r7 %08x\n",
253 regs[4], regs[5], regs[6], regs[7]);
254 debug_printf(state, " r8 %08x r9 %08x r10 %08x r11 %08x mode %s\n",
255 regs[8], regs[9], regs[10], regs[11],
256 mode_name(regs[16]));
257 if ((regs[16] & MODE_MASK) == USR_MODE)
258 debug_printf(state, " ip %08x sp %08x lr %08x pc %08x "
259 "cpsr %08x\n", regs[12], regs[13], regs[14],
260 regs[15], regs[16]);
261 else
262 debug_printf(state, " ip %08x sp %08x lr %08x pc %08x "
263 "cpsr %08x spsr %08x\n", regs[12], regs[13],
264 regs[14], regs[15], regs[16], regs[17]);
265}
266
267struct mode_regs {
268 unsigned long sp_svc;
269 unsigned long lr_svc;
270 unsigned long spsr_svc;
271
272 unsigned long sp_abt;
273 unsigned long lr_abt;
274 unsigned long spsr_abt;
275
276 unsigned long sp_und;
277 unsigned long lr_und;
278 unsigned long spsr_und;
279
280 unsigned long sp_irq;
281 unsigned long lr_irq;
282 unsigned long spsr_irq;
283
284 unsigned long r8_fiq;
285 unsigned long r9_fiq;
286 unsigned long r10_fiq;
287 unsigned long r11_fiq;
288 unsigned long r12_fiq;
289 unsigned long sp_fiq;
290 unsigned long lr_fiq;
291 unsigned long spsr_fiq;
292};
293
294void __naked get_mode_regs(struct mode_regs *regs)
295{
296 asm volatile (
297 "mrs r1, cpsr\n"
298 "msr cpsr_c, #0xd3 @(SVC_MODE | PSR_I_BIT | PSR_F_BIT)\n"
299 "stmia r0!, {r13 - r14}\n"
300 "mrs r2, spsr\n"
301 "msr cpsr_c, #0xd7 @(ABT_MODE | PSR_I_BIT | PSR_F_BIT)\n"
302 "stmia r0!, {r2, r13 - r14}\n"
303 "mrs r2, spsr\n"
304 "msr cpsr_c, #0xdb @(UND_MODE | PSR_I_BIT | PSR_F_BIT)\n"
305 "stmia r0!, {r2, r13 - r14}\n"
306 "mrs r2, spsr\n"
307 "msr cpsr_c, #0xd2 @(IRQ_MODE | PSR_I_BIT | PSR_F_BIT)\n"
308 "stmia r0!, {r2, r13 - r14}\n"
309 "mrs r2, spsr\n"
310 "msr cpsr_c, #0xd1 @(FIQ_MODE | PSR_I_BIT | PSR_F_BIT)\n"
311 "stmia r0!, {r2, r8 - r14}\n"
312 "mrs r2, spsr\n"
313 "stmia r0!, {r2}\n"
314 "msr cpsr_c, r1\n"
315 "bx lr\n");
316}
317
318
319static void dump_allregs(struct fiq_debugger_state *state, unsigned *regs)
320{
321 struct mode_regs mode_regs;
322 dump_regs(state, regs);
323 get_mode_regs(&mode_regs);
324 debug_printf(state, " svc: sp %08x lr %08x spsr %08x\n",
325 mode_regs.sp_svc, mode_regs.lr_svc, mode_regs.spsr_svc);
326 debug_printf(state, " abt: sp %08x lr %08x spsr %08x\n",
327 mode_regs.sp_abt, mode_regs.lr_abt, mode_regs.spsr_abt);
328 debug_printf(state, " und: sp %08x lr %08x spsr %08x\n",
329 mode_regs.sp_und, mode_regs.lr_und, mode_regs.spsr_und);
330 debug_printf(state, " irq: sp %08x lr %08x spsr %08x\n",
331 mode_regs.sp_irq, mode_regs.lr_irq, mode_regs.spsr_irq);
332 debug_printf(state, " fiq: r8 %08x r9 %08x r10 %08x r11 %08x "
333 "r12 %08x\n",
334 mode_regs.r8_fiq, mode_regs.r9_fiq, mode_regs.r10_fiq,
335 mode_regs.r11_fiq, mode_regs.r12_fiq);
336 debug_printf(state, " fiq: sp %08x lr %08x spsr %08x\n",
337 mode_regs.sp_fiq, mode_regs.lr_fiq, mode_regs.spsr_fiq);
338}
339
340static void dump_irqs(struct fiq_debugger_state *state)
341{
342 int n;
Rebecca Schultz Zavinb824eef2010-10-22 15:55:17 -0700343 unsigned int cpu;
344
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700345 debug_printf(state, "irqnr total since-last status name\n");
346 for (n = 0; n < NR_IRQS; n++) {
347 struct irqaction *act = irq_desc[n].action;
348 if (!act && !kstat_irqs(n))
349 continue;
350 debug_printf(state, "%5d: %10u %11u %8x %s\n", n,
351 kstat_irqs(n),
352 kstat_irqs(n) - state->last_irqs[n],
Colin Cross999853b2011-04-08 17:26:06 -0700353 irq_desc[n].status_use_accessors,
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700354 (act && act->name) ? act->name : "???");
355 state->last_irqs[n] = kstat_irqs(n);
356 }
Rebecca Schultz Zavinb824eef2010-10-22 15:55:17 -0700357
358 for (cpu = 0; cpu < NR_CPUS; cpu++) {
359
360 debug_printf(state, "LOC %d: %10u %11u\n", cpu,
361 __IRQ_STAT(cpu, local_timer_irqs),
362 __IRQ_STAT(cpu, local_timer_irqs) -
363 state->last_local_timer_irqs[cpu]);
364 state->last_local_timer_irqs[cpu] =
365 __IRQ_STAT(cpu, local_timer_irqs);
366 }
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700367}
368
369struct stacktrace_state {
370 struct fiq_debugger_state *state;
371 unsigned int depth;
372};
373
374static int report_trace(struct stackframe *frame, void *d)
375{
376 struct stacktrace_state *sts = d;
377
378 if (sts->depth) {
379 debug_printf(sts->state,
380 " pc: %p (%pF), lr %p (%pF), sp %p, fp %p\n",
381 frame->pc, frame->pc, frame->lr, frame->lr,
382 frame->sp, frame->fp);
383 sts->depth--;
384 return 0;
385 }
386 debug_printf(sts->state, " ...\n");
387
388 return sts->depth == 0;
389}
390
391struct frame_tail {
392 struct frame_tail *fp;
393 unsigned long sp;
394 unsigned long lr;
395} __attribute__((packed));
396
397static struct frame_tail *user_backtrace(struct fiq_debugger_state *state,
398 struct frame_tail *tail)
399{
400 struct frame_tail buftail[2];
401
402 /* Also check accessibility of one struct frame_tail beyond */
403 if (!access_ok(VERIFY_READ, tail, sizeof(buftail))) {
404 debug_printf(state, " invalid frame pointer %p\n", tail);
405 return NULL;
406 }
407 if (__copy_from_user_inatomic(buftail, tail, sizeof(buftail))) {
408 debug_printf(state,
409 " failed to copy frame pointer %p\n", tail);
410 return NULL;
411 }
412
413 debug_printf(state, " %p\n", buftail[0].lr);
414
415 /* frame pointers should strictly progress back up the stack
416 * (towards higher addresses) */
417 if (tail >= buftail[0].fp)
418 return NULL;
419
420 return buftail[0].fp-1;
421}
422
423void dump_stacktrace(struct fiq_debugger_state *state,
424 struct pt_regs * const regs, unsigned int depth, void *ssp)
425{
426 struct frame_tail *tail;
Colin Cross24b3bd42010-10-01 23:41:38 -0700427 struct thread_info *real_thread_info = THREAD_INFO(ssp);
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700428 struct stacktrace_state sts;
429
430 sts.depth = depth;
431 sts.state = state;
432 *current_thread_info() = *real_thread_info;
433
434 if (!current)
435 debug_printf(state, "current NULL\n");
436 else
437 debug_printf(state, "pid: %d comm: %s\n",
438 current->pid, current->comm);
439 dump_regs(state, (unsigned *)regs);
440
441 if (!user_mode(regs)) {
442 struct stackframe frame;
443 frame.fp = regs->ARM_fp;
444 frame.sp = regs->ARM_sp;
445 frame.lr = regs->ARM_lr;
446 frame.pc = regs->ARM_pc;
447 debug_printf(state,
448 " pc: %p (%pF), lr %p (%pF), sp %p, fp %p\n",
449 regs->ARM_pc, regs->ARM_pc, regs->ARM_lr, regs->ARM_lr,
450 regs->ARM_sp, regs->ARM_fp);
451 walk_stackframe(&frame, report_trace, &sts);
452 return;
453 }
454
455 tail = ((struct frame_tail *) regs->ARM_fp) - 1;
456 while (depth-- && tail && !((unsigned long) tail & 3))
457 tail = user_backtrace(state, tail);
458}
459
Dima Zavin83b72702011-10-02 20:35:47 -0700460static bool debug_help(struct fiq_debugger_state *state)
Dmitry Shmidt5eed1db2010-11-16 15:40:13 -0800461{
462 debug_printf(state, "FIQ Debugger commands:\n"
463 " pc PC status\n"
464 " regs Register dump\n"
465 " allregs Extended Register dump\n"
466 " bt Stack trace\n"
467 " reboot Reboot\n"
468 " irqs Interupt status\n"
469 " kmsg Kernel log\n"
470 " version Kernel version\n");
471 debug_printf(state, " sleep Allow sleep while in FIQ\n"
472 " nosleep Disable sleep while in FIQ\n"
473 " console Switch terminal to console\n"
474 " cpu Current CPU\n"
475 " cpu <number> Switch to CPU<number>\n");
476 if (!state->debug_busy) {
477 strcpy(state->debug_cmd, "help");
478 state->debug_busy = 1;
Dima Zavin83b72702011-10-02 20:35:47 -0700479 return true;
Dmitry Shmidt5eed1db2010-11-16 15:40:13 -0800480 }
Dima Zavin83b72702011-10-02 20:35:47 -0700481
482 return false;
Dmitry Shmidt5eed1db2010-11-16 15:40:13 -0800483}
484
Dima Zavin83b72702011-10-02 20:35:47 -0700485static void take_affinity(void *info)
486{
487 struct fiq_debugger_state *state = info;
488 struct cpumask cpumask;
489
490 cpumask_clear(&cpumask);
491 cpumask_set_cpu(get_cpu(), &cpumask);
492
493 irq_set_affinity(state->uart_irq, &cpumask);
494}
495
496static void switch_cpu(struct fiq_debugger_state *state, int cpu)
497{
498 if (!debug_have_fiq(state))
499 smp_call_function_single(cpu, take_affinity, state, false);
500 state->current_cpu = cpu;
501}
502
503static bool debug_exec(struct fiq_debugger_state *state,
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700504 const char *cmd, unsigned *regs, void *svc_sp)
505{
Dima Zavin83b72702011-10-02 20:35:47 -0700506 bool signal_helper = false;
507
Dmitry Shmidt5eed1db2010-11-16 15:40:13 -0800508 if (!strcmp(cmd, "help") || !strcmp(cmd, "?")) {
Dima Zavin83b72702011-10-02 20:35:47 -0700509 signal_helper |= debug_help(state);
Dmitry Shmidt5eed1db2010-11-16 15:40:13 -0800510 } else if (!strcmp(cmd, "pc")) {
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700511 debug_printf(state, " pc %08x cpsr %08x mode %s\n",
512 regs[15], regs[16], mode_name(regs[16]));
513 } else if (!strcmp(cmd, "regs")) {
514 dump_regs(state, regs);
515 } else if (!strcmp(cmd, "allregs")) {
516 dump_allregs(state, regs);
517 } else if (!strcmp(cmd, "bt")) {
518 dump_stacktrace(state, (struct pt_regs *)regs, 100, svc_sp);
519 } else if (!strcmp(cmd, "reboot")) {
520 arch_reset(0, 0);
521 } else if (!strcmp(cmd, "irqs")) {
522 dump_irqs(state);
523 } else if (!strcmp(cmd, "kmsg")) {
524 dump_kernel_log(state);
525 } else if (!strcmp(cmd, "version")) {
526 debug_printf(state, "%s\n", linux_banner);
527 } else if (!strcmp(cmd, "sleep")) {
528 state->no_sleep = false;
Dima Zavin83b72702011-10-02 20:35:47 -0700529 debug_printf(state, "enabling sleep\n");
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700530 } else if (!strcmp(cmd, "nosleep")) {
531 state->no_sleep = true;
Dima Zavin83b72702011-10-02 20:35:47 -0700532 debug_printf(state, "disabling sleep\n");
Colin Cross4df8d7b2010-08-16 14:51:51 -0700533 } else if (!strcmp(cmd, "console")) {
534 state->console_enable = true;
535 debug_printf(state, "console mode\n");
Colin Cross24b3bd42010-10-01 23:41:38 -0700536 } else if (!strcmp(cmd, "cpu")) {
537 debug_printf(state, "cpu %d\n", state->current_cpu);
538 } else if (!strncmp(cmd, "cpu ", 4)) {
539 unsigned long cpu = 0;
540 if (strict_strtoul(cmd + 4, 10, &cpu) == 0)
Dima Zavin83b72702011-10-02 20:35:47 -0700541 switch_cpu(state, cpu);
Colin Cross24b3bd42010-10-01 23:41:38 -0700542 else
543 debug_printf(state, "invalid cpu\n");
544 debug_printf(state, "cpu %d\n", state->current_cpu);
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700545 } else {
546 if (state->debug_busy) {
547 debug_printf(state,
548 "command processor busy. trying to abort.\n");
549 state->debug_abort = -1;
550 } else {
551 strcpy(state->debug_cmd, cmd);
552 state->debug_busy = 1;
553 }
554
Dima Zavin83b72702011-10-02 20:35:47 -0700555 return true;
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700556 }
Colin Cross4df8d7b2010-08-16 14:51:51 -0700557 if (!state->console_enable)
558 debug_prompt(state);
Dima Zavin83b72702011-10-02 20:35:47 -0700559
560 return signal_helper;
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700561}
562
563static void sleep_timer_expired(unsigned long data)
564{
565 struct fiq_debugger_state *state = (struct fiq_debugger_state *)data;
566
567 if (state->uart_clk_enabled && !state->no_sleep) {
Dima Zavin48ef31a2011-10-09 11:47:35 -0700568 if (state->debug_enable && !state->console_enable) {
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700569 state->debug_enable = false;
570 debug_printf_nfiq(state, "suspending fiq debugger\n");
571 }
572 state->ignore_next_wakeup_irq = true;
573 if (state->clk)
574 clk_disable(state->clk);
575 state->uart_clk_enabled = false;
576 enable_wakeup_irq(state);
577 }
578 wake_unlock(&state->debugger_wake_lock);
579}
580
Dima Zavin83b72702011-10-02 20:35:47 -0700581static void handle_wakeup(struct fiq_debugger_state *state)
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700582{
Dima Zavin83b72702011-10-02 20:35:47 -0700583 if (state->wakeup_irq >= 0 && state->ignore_next_wakeup_irq) {
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700584 state->ignore_next_wakeup_irq = false;
Dima Zavin83b72702011-10-02 20:35:47 -0700585 } else if (!state->uart_clk_enabled) {
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700586 wake_lock(&state->debugger_wake_lock);
587 if (state->clk)
588 clk_enable(state->clk);
589 state->uart_clk_enabled = true;
590 disable_wakeup_irq(state);
591 mod_timer(&state->sleep_timer, jiffies + HZ / 2);
592 }
Dima Zavin83b72702011-10-02 20:35:47 -0700593}
594
595static irqreturn_t wakeup_irq_handler(int irq, void *dev)
596{
597 struct fiq_debugger_state *state = dev;
598
599 if (!state->no_sleep)
600 debug_puts(state, "WAKEUP\n");
601 handle_wakeup(state);
602
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700603 return IRQ_HANDLED;
604}
605
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700606
Dima Zavin83b72702011-10-02 20:35:47 -0700607static void debug_handle_irq_context(struct fiq_debugger_state *state)
608{
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700609 if (!state->no_sleep) {
610 wake_lock(&state->debugger_wake_lock);
611 mod_timer(&state->sleep_timer, jiffies + HZ * 5);
612 }
Colin Cross4df8d7b2010-08-16 14:51:51 -0700613#if defined(CONFIG_FIQ_DEBUGGER_CONSOLE)
614 if (state->tty) {
615 int i;
616 int count = fiq_debugger_ringbuf_level(state->tty_rbuf);
617 for (i = 0; i < count; i++) {
Dima Zavinb0092752011-10-25 21:24:10 -0700618 int c = fiq_debugger_ringbuf_peek(state->tty_rbuf, 0);
Colin Cross4df8d7b2010-08-16 14:51:51 -0700619 tty_insert_flip_char(state->tty, c, TTY_NORMAL);
620 if (!fiq_debugger_ringbuf_consume(state->tty_rbuf, 1))
621 pr_warn("fiq tty failed to consume byte\n");
622 }
623 tty_flip_buffer_push(state->tty);
624 }
625#endif
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700626 if (state->debug_busy) {
627 struct kdbg_ctxt ctxt;
628
629 ctxt.printf = debug_printf_nfiq;
630 ctxt.cookie = state;
631 kernel_debugger(&ctxt, state->debug_cmd);
632 debug_prompt(state);
633
634 state->debug_busy = 0;
635 }
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700636}
637
638static int debug_getc(struct fiq_debugger_state *state)
639{
640 return state->pdata->uart_getc(state->pdev);
641}
642
Dima Zavin83b72702011-10-02 20:35:47 -0700643static bool debug_handle_uart_interrupt(struct fiq_debugger_state *state,
644 int this_cpu, void *regs, void *svc_sp)
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700645{
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700646 int c;
647 static int last_c;
648 int count = 0;
Dima Zavin83b72702011-10-02 20:35:47 -0700649 bool signal_helper = false;
Colin Cross24b3bd42010-10-01 23:41:38 -0700650
651 if (this_cpu != state->current_cpu) {
652 if (state->in_fiq)
Dima Zavin83b72702011-10-02 20:35:47 -0700653 return false;
Colin Cross24b3bd42010-10-01 23:41:38 -0700654
655 if (atomic_inc_return(&state->unhandled_fiq_count) !=
656 MAX_UNHANDLED_FIQ_COUNT)
Dima Zavin83b72702011-10-02 20:35:47 -0700657 return false;
Colin Cross24b3bd42010-10-01 23:41:38 -0700658
659 debug_printf(state, "fiq_debugger: cpu %d not responding, "
660 "reverting to cpu %d\n", state->current_cpu,
661 this_cpu);
662
663 atomic_set(&state->unhandled_fiq_count, 0);
Dima Zavin83b72702011-10-02 20:35:47 -0700664 switch_cpu(state, this_cpu);
665 return false;
Colin Cross24b3bd42010-10-01 23:41:38 -0700666 }
667
668 state->in_fiq = true;
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700669
670 while ((c = debug_getc(state)) != FIQ_DEBUGGER_NO_CHAR) {
671 count++;
672 if (!state->debug_enable) {
673 if ((c == 13) || (c == 10)) {
674 state->debug_enable = true;
675 state->debug_count = 0;
676 debug_prompt(state);
677 }
Colin Cross4df8d7b2010-08-16 14:51:51 -0700678 } else if (c == FIQ_DEBUGGER_BREAK) {
679 state->console_enable = false;
680 debug_puts(state, "fiq debugger mode\n");
681 state->debug_count = 0;
682 debug_prompt(state);
683#ifdef CONFIG_FIQ_DEBUGGER_CONSOLE
684 } else if (state->console_enable && state->tty_rbuf) {
685 fiq_debugger_ringbuf_push(state->tty_rbuf, c);
Dima Zavin83b72702011-10-02 20:35:47 -0700686 signal_helper = true;
Colin Cross4df8d7b2010-08-16 14:51:51 -0700687#endif
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700688 } else if ((c >= ' ') && (c < 127)) {
689 if (state->debug_count < (DEBUG_MAX - 1)) {
690 state->debug_buf[state->debug_count++] = c;
691 state->pdata->uart_putc(state->pdev, c);
692 }
693 } else if ((c == 8) || (c == 127)) {
694 if (state->debug_count > 0) {
695 state->debug_count--;
696 state->pdata->uart_putc(state->pdev, 8);
697 state->pdata->uart_putc(state->pdev, ' ');
698 state->pdata->uart_putc(state->pdev, 8);
699 }
700 } else if ((c == 13) || (c == 10)) {
701 if (c == '\r' || (c == '\n' && last_c != '\r')) {
702 state->pdata->uart_putc(state->pdev, '\r');
703 state->pdata->uart_putc(state->pdev, '\n');
704 }
705 if (state->debug_count) {
706 state->debug_buf[state->debug_count] = 0;
707 state->debug_count = 0;
Dima Zavin83b72702011-10-02 20:35:47 -0700708 signal_helper |=
709 debug_exec(state, state->debug_buf,
710 regs, svc_sp);
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700711 } else {
712 debug_prompt(state);
713 }
714 }
715 last_c = c;
716 }
717 debug_uart_flush(state);
718 if (state->pdata->fiq_ack)
719 state->pdata->fiq_ack(state->pdev, state->fiq);
720
721 /* poke sleep timer if necessary */
722 if (state->debug_enable && !state->no_sleep)
Dima Zavin83b72702011-10-02 20:35:47 -0700723 signal_helper = true;
Colin Cross24b3bd42010-10-01 23:41:38 -0700724
725 atomic_set(&state->unhandled_fiq_count, 0);
726 state->in_fiq = false;
Dima Zavin83b72702011-10-02 20:35:47 -0700727
728 return signal_helper;
729}
730
731static void debug_fiq(struct fiq_glue_handler *h, void *regs, void *svc_sp)
732{
733 struct fiq_debugger_state *state =
734 container_of(h, struct fiq_debugger_state, handler);
735 unsigned int this_cpu = THREAD_INFO(svc_sp)->cpu;
736 bool need_irq;
737
738 need_irq = debug_handle_uart_interrupt(state, this_cpu, regs, svc_sp);
739 if (need_irq)
740 debug_force_irq(state);
741}
742
743/*
744 * When not using FIQs, we only use this single interrupt as an entry point.
745 * This just effectively takes over the UART interrupt and does all the work
746 * in this context.
747 */
748static irqreturn_t debug_uart_irq(int irq, void *dev)
749{
750 struct fiq_debugger_state *state = dev;
751 bool not_done;
752
753 handle_wakeup(state);
754
755 /* handle the debugger irq in regular context */
756 not_done = debug_handle_uart_interrupt(state, smp_processor_id(),
757 get_irq_regs(),
758 current_thread_info());
759 if (not_done)
760 debug_handle_irq_context(state);
761
762 return IRQ_HANDLED;
763}
764
765/*
766 * If FIQs are used, not everything can happen in fiq context.
767 * FIQ handler does what it can and then signals this interrupt to finish the
768 * job in irq context.
769 */
770static irqreturn_t debug_signal_irq(int irq, void *dev)
771{
772 struct fiq_debugger_state *state = dev;
773
774 if (state->pdata->force_irq_ack)
775 state->pdata->force_irq_ack(state->pdev, state->signal_irq);
776
777 debug_handle_irq_context(state);
778
779 return IRQ_HANDLED;
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700780}
781
782static void debug_resume(struct fiq_glue_handler *h)
783{
784 struct fiq_debugger_state *state =
785 container_of(h, struct fiq_debugger_state, handler);
786 if (state->pdata->uart_resume)
787 state->pdata->uart_resume(state->pdev);
788}
789
Colin Cross4df8d7b2010-08-16 14:51:51 -0700790#if defined(CONFIG_FIQ_DEBUGGER_CONSOLE)
791struct tty_driver *debug_console_device(struct console *co, int *index)
792{
793 struct fiq_debugger_state *state;
794 state = container_of(co, struct fiq_debugger_state, console);
795 *index = 0;
796 return state->tty_driver;
797}
798
799static void debug_console_write(struct console *co,
800 const char *s, unsigned int count)
801{
802 struct fiq_debugger_state *state;
803
804 state = container_of(co, struct fiq_debugger_state, console);
805
806 if (!state->console_enable)
807 return;
808
809 while (count--) {
810 if (*s == '\n')
811 state->pdata->uart_putc(state->pdev, '\r');
812 state->pdata->uart_putc(state->pdev, *s++);
813 }
814 debug_uart_flush(state);
815}
816
817static struct console fiq_debugger_console = {
818 .name = "ttyFIQ",
819 .device = debug_console_device,
820 .write = debug_console_write,
821 .flags = CON_PRINTBUFFER | CON_ANYTIME | CON_ENABLED,
822};
823
824int fiq_tty_open(struct tty_struct *tty, struct file *filp)
825{
826 struct fiq_debugger_state *state = tty->driver->driver_state;
827 if (state->tty_open_count++)
828 return 0;
829
830 tty->driver_data = state;
831 state->tty = tty;
832 return 0;
833}
834
835void fiq_tty_close(struct tty_struct *tty, struct file *filp)
836{
837 struct fiq_debugger_state *state = tty->driver_data;
838 if (--state->tty_open_count)
839 return;
840 state->tty = NULL;
841}
842
843int fiq_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
844{
845 int i;
846 struct fiq_debugger_state *state = tty->driver_data;
847
848 if (!state->console_enable)
849 return count;
850
851 if (state->clk)
852 clk_enable(state->clk);
853 for (i = 0; i < count; i++)
854 state->pdata->uart_putc(state->pdev, *buf++);
855 if (state->clk)
856 clk_disable(state->clk);
857
858 return count;
859}
860
861int fiq_tty_write_room(struct tty_struct *tty)
862{
863 return 1024;
864}
865
866static const struct tty_operations fiq_tty_driver_ops = {
867 .write = fiq_tty_write,
868 .write_room = fiq_tty_write_room,
869 .open = fiq_tty_open,
870 .close = fiq_tty_close,
871};
872
873static int fiq_debugger_tty_init(struct fiq_debugger_state *state)
874{
875 int ret = -EINVAL;
876
877 state->tty_driver = alloc_tty_driver(1);
878 if (!state->tty_driver) {
879 pr_err("Failed to allocate fiq debugger tty\n");
880 return -ENOMEM;
881 }
882
883 state->tty_driver->owner = THIS_MODULE;
884 state->tty_driver->driver_name = "fiq-debugger";
885 state->tty_driver->name = "ttyFIQ";
886 state->tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
887 state->tty_driver->subtype = SERIAL_TYPE_NORMAL;
888 state->tty_driver->init_termios = tty_std_termios;
889 state->tty_driver->init_termios.c_cflag =
890 B115200 | CS8 | CREAD | HUPCL | CLOCAL;
891 state->tty_driver->init_termios.c_ispeed =
892 state->tty_driver->init_termios.c_ospeed = 115200;
893 state->tty_driver->flags = TTY_DRIVER_REAL_RAW;
894 tty_set_operations(state->tty_driver, &fiq_tty_driver_ops);
895 state->tty_driver->driver_state = state;
896
897 ret = tty_register_driver(state->tty_driver);
898 if (ret) {
899 pr_err("Failed to register fiq tty: %d\n", ret);
900 goto err;
901 }
902
903 state->tty_rbuf = fiq_debugger_ringbuf_alloc(1024);
904 if (!state->tty_rbuf) {
905 pr_err("Failed to allocate fiq debugger ringbuf\n");
906 ret = -ENOMEM;
907 goto err;
908 }
909
910 pr_info("Registered FIQ tty driver %p\n", state->tty_driver);
911 return 0;
912
913err:
914 fiq_debugger_ringbuf_free(state->tty_rbuf);
915 state->tty_rbuf = NULL;
916 put_tty_driver(state->tty_driver);
917 return ret;
918}
919#endif
920
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700921static int fiq_debugger_probe(struct platform_device *pdev)
922{
923 int ret;
924 struct fiq_debugger_pdata *pdata = dev_get_platdata(&pdev->dev);
925 struct fiq_debugger_state *state;
Dima Zavin83b72702011-10-02 20:35:47 -0700926 int fiq;
927 int uart_irq;
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700928
Dima Zavin83b72702011-10-02 20:35:47 -0700929 if (!pdata->uart_getc || !pdata->uart_putc)
930 return -EINVAL;
931
932 fiq = platform_get_irq_byname(pdev, "fiq");
933 uart_irq = platform_get_irq_byname(pdev, "uart_irq");
934
935 /* uart_irq mode and fiq mode are mutually exclusive, but one of them
936 * is required */
937 if ((uart_irq < 0 && fiq < 0) || (uart_irq >= 0 && fiq >= 0))
938 return -EINVAL;
939 if (fiq >= 0 && !pdata->fiq_enable)
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700940 return -EINVAL;
941
942 state = kzalloc(sizeof(*state), GFP_KERNEL);
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700943 setup_timer(&state->sleep_timer, sleep_timer_expired,
944 (unsigned long)state);
945 state->pdata = pdata;
946 state->pdev = pdev;
947 state->no_sleep = initial_no_sleep;
948 state->debug_enable = initial_debug_enable;
Colin Cross4df8d7b2010-08-16 14:51:51 -0700949 state->console_enable = initial_console_enable;
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700950
Dima Zavin83b72702011-10-02 20:35:47 -0700951 state->fiq = fiq;
952 state->uart_irq = uart_irq;
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700953 state->signal_irq = platform_get_irq_byname(pdev, "signal");
954 state->wakeup_irq = platform_get_irq_byname(pdev, "wakeup");
955
Dima Zavin83b72702011-10-02 20:35:47 -0700956 if (state->wakeup_irq < 0 && debug_have_fiq(state))
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700957 state->no_sleep = true;
958 state->ignore_next_wakeup_irq = !state->no_sleep;
959
960 wake_lock_init(&state->debugger_wake_lock,
961 WAKE_LOCK_SUSPEND, "serial-debug");
962
963 state->clk = clk_get(&pdev->dev, NULL);
964 if (IS_ERR(state->clk))
965 state->clk = NULL;
966
967 if (state->clk)
968 clk_enable(state->clk);
969
970 if (pdata->uart_init) {
971 ret = pdata->uart_init(pdev);
972 if (ret)
973 goto err_uart_init;
974 }
975
976 debug_printf_nfiq(state, "<hit enter %sto activate fiq debugger>\n",
977 state->no_sleep ? "" : "twice ");
978
Dima Zavin83b72702011-10-02 20:35:47 -0700979 if (debug_have_fiq(state)) {
980 state->handler.fiq = debug_fiq;
981 state->handler.resume = debug_resume;
982 ret = fiq_glue_register_handler(&state->handler);
983 if (ret) {
984 pr_err("%s: could not install fiq handler\n", __func__);
985 goto err_register_fiq;
986 }
Iliyan Malchevc1db50b2010-06-05 17:36:24 -0700987
Dima Zavin83b72702011-10-02 20:35:47 -0700988 pdata->fiq_enable(pdev, state->fiq, 1);
989 } else {
990 ret = request_irq(state->uart_irq, debug_uart_irq,
991 0, "debug", state);
992 if (ret) {
993 pr_err("%s: could not install irq handler\n", __func__);
994 goto err_register_irq;
995 }
996
997 /* for irq-only mode, we want this irq to wake us up, if it
998 * can.
999 */
1000 enable_irq_wake(state->uart_irq);
1001 }
Iliyan Malchevc1db50b2010-06-05 17:36:24 -07001002
1003 if (state->clk)
1004 clk_disable(state->clk);
1005
Dima Zavin83b72702011-10-02 20:35:47 -07001006 if (state->signal_irq >= 0) {
1007 ret = request_irq(state->signal_irq, debug_signal_irq,
1008 IRQF_TRIGGER_RISING, "debug-signal", state);
1009 if (ret)
1010 pr_err("serial_debugger: could not install signal_irq");
1011 }
Iliyan Malchevc1db50b2010-06-05 17:36:24 -07001012
1013 if (state->wakeup_irq >= 0) {
1014 ret = request_irq(state->wakeup_irq, wakeup_irq_handler,
1015 IRQF_TRIGGER_FALLING | IRQF_DISABLED,
1016 "debug-wakeup", state);
1017 if (ret) {
1018 pr_err("serial_debugger: "
1019 "could not install wakeup irq\n");
1020 state->wakeup_irq = -1;
1021 } else {
1022 ret = enable_irq_wake(state->wakeup_irq);
1023 if (ret) {
1024 pr_err("serial_debugger: "
1025 "could not enable wakeup\n");
1026 state->wakeup_irq_no_set_wake = true;
1027 }
1028 }
1029 }
1030 if (state->no_sleep)
Dima Zavin83b72702011-10-02 20:35:47 -07001031 handle_wakeup(state);
Iliyan Malchevc1db50b2010-06-05 17:36:24 -07001032
Colin Cross4df8d7b2010-08-16 14:51:51 -07001033#if defined(CONFIG_FIQ_DEBUGGER_CONSOLE)
1034 state->console = fiq_debugger_console;
1035 register_console(&state->console);
1036 fiq_debugger_tty_init(state);
1037#endif
Iliyan Malchevc1db50b2010-06-05 17:36:24 -07001038 return 0;
1039
Dima Zavin83b72702011-10-02 20:35:47 -07001040err_register_irq:
Iliyan Malchevc1db50b2010-06-05 17:36:24 -07001041err_register_fiq:
1042 if (pdata->uart_free)
1043 pdata->uart_free(pdev);
1044err_uart_init:
Dima Zavin0d5d8ec2011-10-20 14:48:37 -07001045 if (state->clk)
1046 clk_disable(state->clk);
Iliyan Malchevc1db50b2010-06-05 17:36:24 -07001047 if (state->clk)
1048 clk_put(state->clk);
Dima Zavin0d5d8ec2011-10-20 14:48:37 -07001049 wake_lock_destroy(&state->debugger_wake_lock);
1050 kfree(state);
Iliyan Malchevc1db50b2010-06-05 17:36:24 -07001051 return ret;
1052}
1053
1054static struct platform_driver fiq_debugger_driver = {
1055 .probe = fiq_debugger_probe,
1056 .driver.name = "fiq_debugger",
1057};
1058
1059static int __init fiq_debugger_init(void)
1060{
1061 return platform_driver_register(&fiq_debugger_driver);
1062}
1063
1064postcore_initcall(fiq_debugger_init);