udbg_16550.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  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 = clock / 16;
  75. if (speed == 0)
  76. speed = 9600;
  77. dll = base_bauds / speed;
  78. if (comport) {
  79. udbg_comport = (struct NS16550 __iomem *)comport;
  80. out_8(&udbg_comport->lcr, 0x00);
  81. out_8(&udbg_comport->ier, 0xff);
  82. out_8(&udbg_comport->ier, 0x00);
  83. out_8(&udbg_comport->lcr, LCR_DLAB);
  84. out_8(&udbg_comport->dll, dll & 0xff);
  85. out_8(&udbg_comport->dlm, dll >> 8);
  86. /* 8 data, 1 stop, no parity */
  87. out_8(&udbg_comport->lcr, 0x03);
  88. /* RTS/DTR */
  89. out_8(&udbg_comport->mcr, 0x03);
  90. /* Clear & enable FIFOs */
  91. out_8(&udbg_comport->fcr ,0x07);
  92. udbg_putc = udbg_550_putc;
  93. udbg_getc = udbg_550_getc;
  94. udbg_getc_poll = udbg_550_getc_poll;
  95. }
  96. }
  97. unsigned int udbg_probe_uart_speed(void __iomem *comport, unsigned int clock)
  98. {
  99. unsigned int dll, dlm, divisor, prescaler, speed;
  100. u8 old_lcr;
  101. volatile struct NS16550 __iomem *port = comport;
  102. old_lcr = in_8(&port->lcr);
  103. /* select divisor latch registers. */
  104. out_8(&port->lcr, LCR_DLAB);
  105. /* now, read the divisor */
  106. dll = in_8(&port->dll);
  107. dlm = in_8(&port->dlm);
  108. divisor = dlm << 8 | dll;
  109. /* check prescaling */
  110. if (in_8(&port->mcr) & 0x80)
  111. prescaler = 4;
  112. else
  113. prescaler = 1;
  114. /* restore the LCR */
  115. out_8(&port->lcr, old_lcr);
  116. /* calculate speed */
  117. speed = (clock / prescaler) / (divisor * 16);
  118. /* sanity check */
  119. if (speed < 0 || speed > (clock / 16))
  120. speed = 9600;
  121. return speed;
  122. }
  123. #ifdef CONFIG_PPC_MAPLE
  124. void udbg_maple_real_putc(char c)
  125. {
  126. if (udbg_comport) {
  127. while ((real_readb(&udbg_comport->lsr) & LSR_THRE) == 0)
  128. /* wait for idle */;
  129. real_writeb(c, &udbg_comport->thr); eieio();
  130. if (c == '\n')
  131. udbg_maple_real_putc('\r');
  132. }
  133. }
  134. void __init udbg_init_maple_realmode(void)
  135. {
  136. udbg_comport = (volatile struct NS16550 __iomem *)0xf40003f8;
  137. udbg_putc = udbg_maple_real_putc;
  138. udbg_getc = NULL;
  139. udbg_getc_poll = NULL;
  140. }
  141. #endif /* CONFIG_PPC_MAPLE */