udbg_16550.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /*
  2. * udbg for for NS16550 compatable serial ports
  3. *
  4. * Copyright (C) 2001-2005 PPC 64 Team, IBM Corp
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the License, or (at your option) any later version.
  10. */
  11. #include <linux/types.h>
  12. #include <asm/udbg.h>
  13. #include <asm/io.h>
  14. extern u8 real_readb(volatile u8 __iomem *addr);
  15. extern void real_writeb(u8 data, volatile u8 __iomem *addr);
  16. extern u8 real_205_readb(volatile u8 __iomem *addr);
  17. extern void real_205_writeb(u8 data, volatile u8 __iomem *addr);
  18. struct NS16550 {
  19. /* this struct must be packed */
  20. unsigned char rbr; /* 0 */
  21. unsigned char ier; /* 1 */
  22. unsigned char fcr; /* 2 */
  23. unsigned char lcr; /* 3 */
  24. unsigned char mcr; /* 4 */
  25. unsigned char lsr; /* 5 */
  26. unsigned char msr; /* 6 */
  27. unsigned char scr; /* 7 */
  28. };
  29. #define thr rbr
  30. #define iir fcr
  31. #define dll rbr
  32. #define dlm ier
  33. #define dlab lcr
  34. #define LSR_DR 0x01 /* Data ready */
  35. #define LSR_OE 0x02 /* Overrun */
  36. #define LSR_PE 0x04 /* Parity error */
  37. #define LSR_FE 0x08 /* Framing error */
  38. #define LSR_BI 0x10 /* Break */
  39. #define LSR_THRE 0x20 /* Xmit holding register empty */
  40. #define LSR_TEMT 0x40 /* Xmitter empty */
  41. #define LSR_ERR 0x80 /* Error */
  42. #define LCR_DLAB 0x80
  43. static volatile struct NS16550 __iomem *udbg_comport;
  44. static void udbg_550_putc(char c)
  45. {
  46. if (udbg_comport) {
  47. while ((in_8(&udbg_comport->lsr) & LSR_THRE) == 0)
  48. /* wait for idle */;
  49. out_8(&udbg_comport->thr, c);
  50. if (c == '\n')
  51. udbg_550_putc('\r');
  52. }
  53. }
  54. static int udbg_550_getc_poll(void)
  55. {
  56. if (udbg_comport) {
  57. if ((in_8(&udbg_comport->lsr) & LSR_DR) != 0)
  58. return in_8(&udbg_comport->rbr);
  59. else
  60. return -1;
  61. }
  62. return -1;
  63. }
  64. static int udbg_550_getc(void)
  65. {
  66. if (udbg_comport) {
  67. while ((in_8(&udbg_comport->lsr) & LSR_DR) == 0)
  68. /* wait for char */;
  69. return in_8(&udbg_comport->rbr);
  70. }
  71. return -1;
  72. }
  73. void udbg_init_uart(void __iomem *comport, unsigned int speed,
  74. unsigned int clock)
  75. {
  76. unsigned int dll, base_bauds;
  77. if (clock == 0)
  78. clock = 1843200;
  79. if (speed == 0)
  80. speed = 9600;
  81. base_bauds = clock / 16;
  82. dll = base_bauds / speed;
  83. if (comport) {
  84. udbg_comport = (struct NS16550 __iomem *)comport;
  85. out_8(&udbg_comport->lcr, 0x00);
  86. out_8(&udbg_comport->ier, 0xff);
  87. out_8(&udbg_comport->ier, 0x00);
  88. out_8(&udbg_comport->lcr, LCR_DLAB);
  89. out_8(&udbg_comport->dll, dll & 0xff);
  90. out_8(&udbg_comport->dlm, dll >> 8);
  91. /* 8 data, 1 stop, no parity */
  92. out_8(&udbg_comport->lcr, 0x03);
  93. /* RTS/DTR */
  94. out_8(&udbg_comport->mcr, 0x03);
  95. /* Clear & enable FIFOs */
  96. out_8(&udbg_comport->fcr ,0x07);
  97. udbg_putc = udbg_550_putc;
  98. udbg_getc = udbg_550_getc;
  99. udbg_getc_poll = udbg_550_getc_poll;
  100. }
  101. }
  102. unsigned int udbg_probe_uart_speed(void __iomem *comport, unsigned int clock)
  103. {
  104. unsigned int dll, dlm, divisor, prescaler, speed;
  105. u8 old_lcr;
  106. volatile struct NS16550 __iomem *port = comport;
  107. old_lcr = in_8(&port->lcr);
  108. /* select divisor latch registers. */
  109. out_8(&port->lcr, LCR_DLAB);
  110. /* now, read the divisor */
  111. dll = in_8(&port->dll);
  112. dlm = in_8(&port->dlm);
  113. divisor = dlm << 8 | dll;
  114. /* check prescaling */
  115. if (in_8(&port->mcr) & 0x80)
  116. prescaler = 4;
  117. else
  118. prescaler = 1;
  119. /* restore the LCR */
  120. out_8(&port->lcr, old_lcr);
  121. /* calculate speed */
  122. speed = (clock / prescaler) / (divisor * 16);
  123. /* sanity check */
  124. if (speed < 0 || speed > (clock / 16))
  125. speed = 9600;
  126. return speed;
  127. }
  128. #ifdef CONFIG_PPC_MAPLE
  129. void udbg_maple_real_putc(char c)
  130. {
  131. if (udbg_comport) {
  132. while ((real_readb(&udbg_comport->lsr) & LSR_THRE) == 0)
  133. /* wait for idle */;
  134. real_writeb(c, &udbg_comport->thr); eieio();
  135. if (c == '\n')
  136. udbg_maple_real_putc('\r');
  137. }
  138. }
  139. void __init udbg_init_maple_realmode(void)
  140. {
  141. udbg_comport = (volatile struct NS16550 __iomem *)0xf40003f8;
  142. udbg_putc = udbg_maple_real_putc;
  143. udbg_getc = NULL;
  144. udbg_getc_poll = NULL;
  145. }
  146. #endif /* CONFIG_PPC_MAPLE */
  147. #ifdef CONFIG_PPC_PASEMI
  148. void udbg_pas_real_putc(char c)
  149. {
  150. if (udbg_comport) {
  151. while ((real_205_readb(&udbg_comport->lsr) & LSR_THRE) == 0)
  152. /* wait for idle */;
  153. real_205_writeb(c, &udbg_comport->thr); eieio();
  154. if (c == '\n')
  155. udbg_pas_real_putc('\r');
  156. }
  157. }
  158. void udbg_init_pas_realmode(void)
  159. {
  160. udbg_comport = (volatile struct NS16550 __iomem *)0xfcff03f8UL;
  161. udbg_putc = udbg_pas_real_putc;
  162. udbg_getc = NULL;
  163. udbg_getc_poll = NULL;
  164. }
  165. #endif /* CONFIG_PPC_MAPLE */
  166. #ifdef CONFIG_PPC_EARLY_DEBUG_44x
  167. #include <platforms/44x/44x.h>
  168. static void udbg_44x_as1_putc(char c)
  169. {
  170. if (udbg_comport) {
  171. while ((as1_readb(&udbg_comport->lsr) & LSR_THRE) == 0)
  172. /* wait for idle */;
  173. as1_writeb(c, &udbg_comport->thr); eieio();
  174. if (c == '\n')
  175. udbg_44x_as1_putc('\r');
  176. }
  177. }
  178. static int udbg_44x_as1_getc(void)
  179. {
  180. if (udbg_comport) {
  181. while ((as1_readb(&udbg_comport->lsr) & LSR_DR) == 0)
  182. ; /* wait for char */
  183. return as1_readb(&udbg_comport->rbr);
  184. }
  185. return -1;
  186. }
  187. void __init udbg_init_44x_as1(void)
  188. {
  189. udbg_comport =
  190. (volatile struct NS16550 __iomem *)PPC44x_EARLY_DEBUG_VIRTADDR;
  191. udbg_putc = udbg_44x_as1_putc;
  192. udbg_getc = udbg_44x_as1_getc;
  193. }
  194. #endif /* CONFIG_PPC_EARLY_DEBUG_44x */