gen550_dbg.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /*
  2. * arch/ppc/syslib/gen550_dbg.c
  3. *
  4. * A library of polled 16550 serial routines. These are intended to
  5. * be used to support progress messages, xmon, kgdb, etc. on a
  6. * variety of platforms.
  7. *
  8. * Adapted from lots of code ripped from the arch/ppc/boot/ polled
  9. * 16550 support.
  10. *
  11. * Author: Matt Porter <mporter@mvista.com>
  12. *
  13. * 2002-2003 (c) MontaVista Software, Inc. This file is licensed under
  14. * the terms of the GNU General Public License version 2. This program
  15. * is licensed "as is" without any warranty of any kind, whether express
  16. * or implied.
  17. */
  18. #include <linux/config.h>
  19. #include <linux/types.h>
  20. #include <linux/serial.h>
  21. #include <linux/tty.h> /* For linux/serial_core.h */
  22. #include <linux/serial_core.h>
  23. #include <linux/serialP.h>
  24. #include <linux/serial_reg.h>
  25. #include <asm/machdep.h>
  26. #include <asm/serial.h>
  27. #include <asm/io.h>
  28. #define SERIAL_BAUD 9600
  29. /* SERIAL_PORT_DFNS is defined in <asm/serial.h> */
  30. #ifndef SERIAL_PORT_DFNS
  31. #define SERIAL_PORT_DFNS
  32. #endif
  33. static struct serial_state rs_table[RS_TABLE_SIZE] = {
  34. SERIAL_PORT_DFNS /* defined in <asm/serial.h> */
  35. };
  36. static void (*serial_outb)(unsigned long, unsigned char);
  37. static unsigned long (*serial_inb)(unsigned long);
  38. static int shift;
  39. unsigned long direct_inb(unsigned long addr)
  40. {
  41. return readb((void __iomem *)addr);
  42. }
  43. void direct_outb(unsigned long addr, unsigned char val)
  44. {
  45. writeb(val, (void __iomem *)addr);
  46. }
  47. unsigned long io_inb(unsigned long port)
  48. {
  49. return inb(port);
  50. }
  51. void io_outb(unsigned long port, unsigned char val)
  52. {
  53. outb(val, port);
  54. }
  55. unsigned long serial_init(int chan, void *ignored)
  56. {
  57. unsigned long com_port;
  58. unsigned char lcr, dlm;
  59. /* We need to find out which type io we're expecting. If it's
  60. * 'SERIAL_IO_PORT', we get an offset from the isa_io_base.
  61. * If it's 'SERIAL_IO_MEM', we can the exact location. -- Tom */
  62. switch (rs_table[chan].io_type) {
  63. case SERIAL_IO_PORT:
  64. com_port = rs_table[chan].port;
  65. serial_outb = io_outb;
  66. serial_inb = io_inb;
  67. break;
  68. case SERIAL_IO_MEM:
  69. com_port = (unsigned long)rs_table[chan].iomem_base;
  70. serial_outb = direct_outb;
  71. serial_inb = direct_inb;
  72. break;
  73. default:
  74. /* We can't deal with it. */
  75. return -1;
  76. }
  77. /* How far apart the registers are. */
  78. shift = rs_table[chan].iomem_reg_shift;
  79. /* save the LCR */
  80. lcr = serial_inb(com_port + (UART_LCR << shift));
  81. /* Access baud rate */
  82. serial_outb(com_port + (UART_LCR << shift), UART_LCR_DLAB);
  83. dlm = serial_inb(com_port + (UART_DLM << shift));
  84. /*
  85. * Test if serial port is unconfigured
  86. * We assume that no-one uses less than 110 baud or
  87. * less than 7 bits per character these days.
  88. * -- paulus.
  89. */
  90. if ((dlm <= 4) && (lcr & 2)) {
  91. /* port is configured, put the old LCR back */
  92. serial_outb(com_port + (UART_LCR << shift), lcr);
  93. }
  94. else {
  95. /* Input clock. */
  96. serial_outb(com_port + (UART_DLL << shift),
  97. (rs_table[chan].baud_base / SERIAL_BAUD) & 0xFF);
  98. serial_outb(com_port + (UART_DLM << shift),
  99. (rs_table[chan].baud_base / SERIAL_BAUD) >> 8);
  100. /* 8 data, 1 stop, no parity */
  101. serial_outb(com_port + (UART_LCR << shift), 0x03);
  102. /* RTS/DTR */
  103. serial_outb(com_port + (UART_MCR << shift), 0x03);
  104. /* Clear & enable FIFOs */
  105. serial_outb(com_port + (UART_FCR << shift), 0x07);
  106. }
  107. return (com_port);
  108. }
  109. void
  110. serial_putc(unsigned long com_port, unsigned char c)
  111. {
  112. while ((serial_inb(com_port + (UART_LSR << shift)) & UART_LSR_THRE) == 0)
  113. ;
  114. serial_outb(com_port, c);
  115. }
  116. unsigned char
  117. serial_getc(unsigned long com_port)
  118. {
  119. while ((serial_inb(com_port + (UART_LSR << shift)) & UART_LSR_DR) == 0)
  120. ;
  121. return serial_inb(com_port);
  122. }
  123. int
  124. serial_tstc(unsigned long com_port)
  125. {
  126. return ((serial_inb(com_port + (UART_LSR << shift)) & UART_LSR_DR) != 0);
  127. }
  128. void
  129. serial_close(unsigned long com_port)
  130. {
  131. }
  132. void
  133. gen550_init(int i, struct uart_port *serial_req)
  134. {
  135. rs_table[i].io_type = serial_req->iotype;
  136. rs_table[i].port = serial_req->iobase;
  137. rs_table[i].iomem_base = serial_req->membase;
  138. rs_table[i].iomem_reg_shift = serial_req->regshift;
  139. rs_table[i].baud_base = serial_req->uartclk ? serial_req->uartclk / 16 : BASE_BAUD;
  140. }
  141. #ifdef CONFIG_SERIAL_TEXT_DEBUG
  142. void
  143. gen550_progress(char *s, unsigned short hex)
  144. {
  145. volatile unsigned int progress_debugport;
  146. volatile char c;
  147. progress_debugport = serial_init(0, NULL);
  148. serial_putc(progress_debugport, '\r');
  149. while ((c = *s++) != 0)
  150. serial_putc(progress_debugport, c);
  151. serial_putc(progress_debugport, '\n');
  152. serial_putc(progress_debugport, '\r');
  153. }
  154. #endif /* CONFIG_SERIAL_TEXT_DEBUG */