udbg_16550.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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. struct NS16550 {
  17. /* this struct must be packed */
  18. unsigned char rbr; /* 0 */
  19. unsigned char ier; /* 1 */
  20. unsigned char fcr; /* 2 */
  21. unsigned char lcr; /* 3 */
  22. unsigned char mcr; /* 4 */
  23. unsigned char lsr; /* 5 */
  24. unsigned char msr; /* 6 */
  25. unsigned char scr; /* 7 */
  26. };
  27. #define thr rbr
  28. #define iir fcr
  29. #define dll rbr
  30. #define dlm ier
  31. #define dlab lcr
  32. #define LSR_DR 0x01 /* Data ready */
  33. #define LSR_OE 0x02 /* Overrun */
  34. #define LSR_PE 0x04 /* Parity error */
  35. #define LSR_FE 0x08 /* Framing error */
  36. #define LSR_BI 0x10 /* Break */
  37. #define LSR_THRE 0x20 /* Xmit holding register empty */
  38. #define LSR_TEMT 0x40 /* Xmitter empty */
  39. #define LSR_ERR 0x80 /* Error */
  40. #define LCR_DLAB 0x80
  41. static volatile struct NS16550 __iomem *udbg_comport;
  42. static void udbg_550_putc(char c)
  43. {
  44. if (udbg_comport) {
  45. while ((in_8(&udbg_comport->lsr) & LSR_THRE) == 0)
  46. /* wait for idle */;
  47. out_8(&udbg_comport->thr, c);
  48. if (c == '\n')
  49. udbg_550_putc('\r');
  50. }
  51. }
  52. static int udbg_550_getc_poll(void)
  53. {
  54. if (udbg_comport) {
  55. if ((in_8(&udbg_comport->lsr) & LSR_DR) != 0)
  56. return in_8(&udbg_comport->rbr);
  57. else
  58. return -1;
  59. }
  60. return -1;
  61. }
  62. static int udbg_550_getc(void)
  63. {
  64. if (udbg_comport) {
  65. while ((in_8(&udbg_comport->lsr) & LSR_DR) == 0)
  66. /* wait for char */;
  67. return in_8(&udbg_comport->rbr);
  68. }
  69. return -1;
  70. }
  71. void udbg_init_uart(void __iomem *comport, unsigned int speed,
  72. unsigned int clock)
  73. {
  74. unsigned int dll, base_bauds;
  75. if (clock == 0)
  76. clock = 1843200;
  77. if (speed == 0)
  78. speed = 9600;
  79. base_bauds = clock / 16;
  80. dll = base_bauds / speed;
  81. if (comport) {
  82. udbg_comport = (struct NS16550 __iomem *)comport;
  83. out_8(&udbg_comport->lcr, 0x00);
  84. out_8(&udbg_comport->ier, 0xff);
  85. out_8(&udbg_comport->ier, 0x00);
  86. out_8(&udbg_comport->lcr, LCR_DLAB);
  87. out_8(&udbg_comport->dll, dll & 0xff);
  88. out_8(&udbg_comport->dlm, dll >> 8);
  89. /* 8 data, 1 stop, no parity */
  90. out_8(&udbg_comport->lcr, 0x03);
  91. /* RTS/DTR */
  92. out_8(&udbg_comport->mcr, 0x03);
  93. /* Clear & enable FIFOs */
  94. out_8(&udbg_comport->fcr ,0x07);
  95. udbg_putc = udbg_550_putc;
  96. udbg_getc = udbg_550_getc;
  97. udbg_getc_poll = udbg_550_getc_poll;
  98. }
  99. }
  100. unsigned int udbg_probe_uart_speed(void __iomem *comport, unsigned int clock)
  101. {
  102. unsigned int dll, dlm, divisor, prescaler, speed;
  103. u8 old_lcr;
  104. volatile struct NS16550 __iomem *port = comport;
  105. old_lcr = in_8(&port->lcr);
  106. /* select divisor latch registers. */
  107. out_8(&port->lcr, LCR_DLAB);
  108. /* now, read the divisor */
  109. dll = in_8(&port->dll);
  110. dlm = in_8(&port->dlm);
  111. divisor = dlm << 8 | dll;
  112. /* check prescaling */
  113. if (in_8(&port->mcr) & 0x80)
  114. prescaler = 4;
  115. else
  116. prescaler = 1;
  117. /* restore the LCR */
  118. out_8(&port->lcr, old_lcr);
  119. /* calculate speed */
  120. speed = (clock / prescaler) / (divisor * 16);
  121. /* sanity check */
  122. if (speed < 0 || speed > (clock / 16))
  123. speed = 9600;
  124. return speed;
  125. }
  126. #ifdef CONFIG_PPC_MAPLE
  127. void udbg_maple_real_putc(char c)
  128. {
  129. if (udbg_comport) {
  130. while ((real_readb(&udbg_comport->lsr) & LSR_THRE) == 0)
  131. /* wait for idle */;
  132. real_writeb(c, &udbg_comport->thr); eieio();
  133. if (c == '\n')
  134. udbg_maple_real_putc('\r');
  135. }
  136. }
  137. void __init udbg_init_maple_realmode(void)
  138. {
  139. udbg_comport = (volatile struct NS16550 __iomem *)0xf40003f8;
  140. udbg_putc = udbg_maple_real_putc;
  141. udbg_getc = NULL;
  142. udbg_getc_poll = NULL;
  143. }
  144. #endif /* CONFIG_PPC_MAPLE */