msm_serial_debugger.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. /*
  2. * drivers/serial/msm_serial_debuger.c
  3. *
  4. * Serial Debugger Interface for MSM7K
  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. #include <stdarg.h>
  18. #include <linux/module.h>
  19. #include <linux/io.h>
  20. #include <linux/console.h>
  21. #include <linux/interrupt.h>
  22. #include <linux/clk.h>
  23. #include <linux/platform_device.h>
  24. #include <linux/kernel_debugger.h>
  25. #include <linux/kernel_stat.h>
  26. #include <linux/irq.h>
  27. #include <linux/delay.h>
  28. #include <mach/system.h>
  29. #include <mach/fiq.h>
  30. #include "msm_serial.h"
  31. static unsigned int debug_port_base;
  32. static int debug_signal_irq;
  33. static struct clk *debug_clk;
  34. static int debug_enable;
  35. static int debugger_enable;
  36. static struct {
  37. unsigned int base;
  38. int irq;
  39. struct device *clk_device;
  40. int signal_irq;
  41. } init_data;
  42. static inline void msm_write(unsigned int val, unsigned int off)
  43. {
  44. __raw_writel(val, debug_port_base + off);
  45. }
  46. static inline unsigned int msm_read(unsigned int off)
  47. {
  48. return __raw_readl(debug_port_base + off);
  49. }
  50. static void debug_port_init(void)
  51. {
  52. /* reset everything */
  53. msm_write(UART_CR_CMD_RESET_RX, UART_CR);
  54. msm_write(UART_CR_CMD_RESET_TX, UART_CR);
  55. msm_write(UART_CR_CMD_RESET_ERR, UART_CR);
  56. msm_write(UART_CR_CMD_RESET_BREAK_INT, UART_CR);
  57. msm_write(UART_CR_CMD_RESET_CTS, UART_CR);
  58. msm_write(UART_CR_CMD_SET_RFR, UART_CR);
  59. /* setup clock dividers */
  60. if (clk_get_rate(debug_clk) == 19200000) {
  61. /* clock is TCXO (19.2MHz) */
  62. msm_write(0x06, UART_MREG);
  63. msm_write(0xF1, UART_NREG);
  64. msm_write(0x0F, UART_DREG);
  65. msm_write(0x1A, UART_MNDREG);
  66. } else {
  67. /* clock must be TCXO/4 */
  68. msm_write(0x18, UART_MREG);
  69. msm_write(0xF6, UART_NREG);
  70. msm_write(0x0F, UART_DREG);
  71. msm_write(0x0A, UART_MNDREG);
  72. }
  73. msm_write(UART_CSR_115200, UART_CSR);
  74. /* rx interrupt on every character -- keep it simple */
  75. msm_write(0, UART_RFWR);
  76. /* enable TX and RX */
  77. msm_write(0x05, UART_CR);
  78. /* enable RX interrupt */
  79. msm_write(UART_IMR_RXLEV, UART_IMR);
  80. }
  81. static inline int debug_getc(void)
  82. {
  83. if (msm_read(UART_SR) & UART_SR_RX_READY) {
  84. return msm_read(UART_RF);
  85. } else {
  86. return -1;
  87. }
  88. }
  89. static inline void debug_putc(unsigned int c)
  90. {
  91. while (!(msm_read(UART_SR) & UART_SR_TX_READY)) ;
  92. msm_write(c, UART_TF);
  93. }
  94. static inline void debug_flush(void)
  95. {
  96. while (!(msm_read(UART_SR) & UART_SR_TX_EMPTY)) ;
  97. }
  98. static void debug_puts(char *s)
  99. {
  100. unsigned c;
  101. while ((c = *s++)) {
  102. if (c == '\n')
  103. debug_putc('\r');
  104. debug_putc(c);
  105. }
  106. }
  107. static void debug_prompt(void)
  108. {
  109. debug_puts("debug> ");
  110. }
  111. int log_buf_copy(char *dest, int idx, int len);
  112. static void dump_kernel_log(void)
  113. {
  114. char buf[1024];
  115. int idx = 0;
  116. int ret;
  117. int saved_oip;
  118. /* setting oops_in_progress prevents log_buf_copy()
  119. * from trying to take a spinlock which will make it
  120. * very unhappy in some cases...
  121. */
  122. saved_oip = oops_in_progress;
  123. oops_in_progress = 1;
  124. for (;;) {
  125. ret = log_buf_copy(buf, idx, 1023);
  126. if (ret <= 0)
  127. break;
  128. buf[ret] = 0;
  129. debug_puts(buf);
  130. idx += ret;
  131. }
  132. oops_in_progress = saved_oip;
  133. }
  134. static char *mode_name(unsigned cpsr)
  135. {
  136. switch (cpsr & MODE_MASK) {
  137. case USR_MODE: return "USR";
  138. case FIQ_MODE: return "FIQ";
  139. case IRQ_MODE: return "IRQ";
  140. case SVC_MODE: return "SVC";
  141. case ABT_MODE: return "ABT";
  142. case UND_MODE: return "UND";
  143. case SYSTEM_MODE: return "SYS";
  144. default: return "???";
  145. }
  146. }
  147. #define DEBUG_MAX 64
  148. static char debug_cmd[DEBUG_MAX];
  149. static int debug_busy;
  150. static int debug_abort;
  151. static int debug_printf(void *cookie, const char *fmt, ...)
  152. {
  153. char buf[256];
  154. va_list ap;
  155. va_start(ap, fmt);
  156. vsnprintf(buf, 128, fmt, ap);
  157. va_end(ap);
  158. debug_puts(buf);
  159. return debug_abort;
  160. }
  161. /* Safe outside fiq context */
  162. static int debug_printf_nfiq(void *cookie, const char *fmt, ...)
  163. {
  164. char buf[256];
  165. va_list ap;
  166. unsigned long irq_flags;
  167. va_start(ap, fmt);
  168. vsnprintf(buf, 128, fmt, ap);
  169. va_end(ap);
  170. local_irq_save(irq_flags);
  171. debug_puts(buf);
  172. debug_flush();
  173. local_irq_restore(irq_flags);
  174. return debug_abort;
  175. }
  176. #define dprintf(fmt...) debug_printf(0, fmt)
  177. unsigned int last_irqs[NR_IRQS];
  178. static void dump_irqs(void)
  179. {
  180. int n;
  181. dprintf("irqnr total since-last status name\n");
  182. for (n = 1; n < NR_IRQS; n++) {
  183. struct irqaction *act = irq_desc[n].action;
  184. if (!act && !kstat_cpu(0).irqs[n])
  185. continue;
  186. dprintf("%5d: %10u %11u %8x %s\n", n,
  187. kstat_cpu(0).irqs[n],
  188. kstat_cpu(0).irqs[n] - last_irqs[n],
  189. irq_desc[n].status,
  190. (act && act->name) ? act->name : "???");
  191. last_irqs[n] = kstat_cpu(0).irqs[n];
  192. }
  193. }
  194. static void debug_exec(const char *cmd, unsigned *regs)
  195. {
  196. if (!strcmp(cmd, "pc")) {
  197. dprintf(" pc %08x cpsr %08x mode %s\n",
  198. regs[15], regs[16], mode_name(regs[16]));
  199. } else if (!strcmp(cmd, "regs")) {
  200. dprintf(" r0 %08x r1 %08x r2 %08x r3 %08x\n",
  201. regs[0], regs[1], regs[2], regs[3]);
  202. dprintf(" r4 %08x r5 %08x r6 %08x r7 %08x\n",
  203. regs[4], regs[5], regs[6], regs[7]);
  204. dprintf(" r8 %08x r9 %08x r10 %08x r11 %08x mode %s\n",
  205. regs[8], regs[9], regs[10], regs[11],
  206. mode_name(regs[16]));
  207. dprintf(" ip %08x sp %08x lr %08x pc %08x cpsr %08x\n",
  208. regs[10], regs[13], regs[14], regs[15], regs[16]);
  209. } else if (!strcmp(cmd, "reboot")) {
  210. if (msm_hw_reset_hook)
  211. msm_hw_reset_hook();
  212. } else if (!strcmp(cmd, "irqs")) {
  213. dump_irqs();
  214. } else if (!strcmp(cmd, "kmsg")) {
  215. dump_kernel_log();
  216. } else if (!strcmp(cmd, "version")) {
  217. dprintf("%s\n", linux_banner);
  218. } else {
  219. if (debug_busy) {
  220. dprintf("command processor busy. trying to abort.\n");
  221. debug_abort = -1;
  222. } else {
  223. strcpy(debug_cmd, cmd);
  224. debug_busy = 1;
  225. }
  226. msm_trigger_irq(debug_signal_irq);
  227. return;
  228. }
  229. debug_prompt();
  230. }
  231. static irqreturn_t debug_irq(int irq, void *dev)
  232. {
  233. if (debug_busy) {
  234. struct kdbg_ctxt ctxt;
  235. ctxt.printf = debug_printf_nfiq;
  236. kernel_debugger(&ctxt, debug_cmd);
  237. debug_prompt();
  238. debug_busy = 0;
  239. }
  240. return IRQ_HANDLED;
  241. }
  242. static char debug_buf[DEBUG_MAX];
  243. static int debug_count;
  244. static void debug_fiq(void *data, void *regs)
  245. {
  246. int c;
  247. static int last_c;
  248. while ((c = debug_getc()) != -1) {
  249. if (!debug_enable) {
  250. if ((c == 13) || (c == 10)) {
  251. debug_enable = true;
  252. debug_count = 0;
  253. debug_prompt();
  254. }
  255. } else if ((c >= ' ') && (c < 127)) {
  256. if (debug_count < (DEBUG_MAX - 1)) {
  257. debug_buf[debug_count++] = c;
  258. debug_putc(c);
  259. }
  260. } else if ((c == 8) || (c == 127)) {
  261. if (debug_count > 0) {
  262. debug_count--;
  263. debug_putc(8);
  264. debug_putc(' ');
  265. debug_putc(8);
  266. }
  267. } else if ((c == 13) || (c == 10)) {
  268. if (c == '\r' || (c == '\n' && last_c != '\r')) {
  269. debug_putc('\r');
  270. debug_putc('\n');
  271. }
  272. if (debug_count) {
  273. debug_buf[debug_count] = 0;
  274. debug_count = 0;
  275. debug_exec(debug_buf, regs);
  276. } else {
  277. debug_prompt();
  278. }
  279. }
  280. last_c = c;
  281. }
  282. debug_flush();
  283. }
  284. #if defined(CONFIG_MSM_SERIAL_DEBUGGER_CONSOLE)
  285. static void debug_console_write(struct console *co,
  286. const char *s, unsigned int count)
  287. {
  288. unsigned long irq_flags;
  289. /* disable irq's while TXing outside of FIQ context */
  290. local_irq_save(irq_flags);
  291. while (count--) {
  292. if (*s == '\n')
  293. debug_putc('\r');
  294. debug_putc(*s++);
  295. }
  296. debug_flush();
  297. local_irq_restore(irq_flags);
  298. }
  299. static struct console msm_serial_debug_console = {
  300. .name = "debug_console",
  301. .write = debug_console_write,
  302. .flags = CON_PRINTBUFFER | CON_ANYTIME | CON_ENABLED,
  303. };
  304. #endif
  305. void msm_serial_debug_enable(int enable) {
  306. debug_enable = enable;
  307. }
  308. void msm_serial_debug_init(unsigned int base, int irq,
  309. struct device *clk_device, int signal_irq)
  310. {
  311. int ret;
  312. void *port;
  313. debug_clk = clk_get(clk_device, "uart_clk");
  314. if (debug_clk)
  315. clk_enable(debug_clk);
  316. port = ioremap(base, 4096);
  317. if (!port)
  318. return;
  319. init_data.base = base;
  320. init_data.irq = irq;
  321. init_data.clk_device = clk_device;
  322. init_data.signal_irq = signal_irq;
  323. debug_port_base = (unsigned int) port;
  324. debug_signal_irq = signal_irq;
  325. debug_port_init();
  326. debug_prompt();
  327. msm_fiq_select(irq);
  328. msm_fiq_set_handler(debug_fiq, 0);
  329. msm_fiq_enable(irq);
  330. ret = request_irq(signal_irq, debug_irq,
  331. IRQF_TRIGGER_RISING, "debug", 0);
  332. if (ret)
  333. printk(KERN_ERR
  334. "serial_debugger: could not install signal_irq");
  335. #if defined(CONFIG_MSM_SERIAL_DEBUGGER_CONSOLE)
  336. register_console(&msm_serial_debug_console);
  337. #endif
  338. debugger_enable = 1;
  339. }
  340. static int msm_serial_debug_remove(const char *val, struct kernel_param *kp)
  341. {
  342. int ret;
  343. static int pre_stat = 1;
  344. ret = param_set_bool(val, kp);
  345. if (ret)
  346. return ret;
  347. if (pre_stat == *(int *)kp->arg)
  348. return 0;
  349. pre_stat = *(int *)kp->arg;
  350. if (*(int *)kp->arg) {
  351. msm_serial_debug_init(init_data.base, init_data.irq,
  352. init_data.clk_device, init_data.signal_irq);
  353. printk(KERN_INFO "enable FIQ serial debugger\n");
  354. return 0;
  355. }
  356. #if defined(CONFIG_MSM_SERIAL_DEBUGGER_CONSOLE)
  357. unregister_console(&msm_serial_debug_console);
  358. #endif
  359. free_irq(init_data.signal_irq, 0);
  360. msm_fiq_set_handler(NULL, 0);
  361. msm_fiq_disable(init_data.irq);
  362. msm_fiq_unselect(init_data.irq);
  363. clk_disable(debug_clk);
  364. printk(KERN_INFO "disable FIQ serial debugger\n");
  365. return 0;
  366. }
  367. module_param_call(enable, msm_serial_debug_remove, param_get_bool,
  368. &debugger_enable, S_IWUSR | S_IRUGO);