uart8250mem.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. /*
  2. * This file is part of the coreboot project.
  3. *
  4. * Copyright (C) 2003 Eric Biederman
  5. * Copyright (C) 2006-2010 coresystems GmbH
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; version 2 of the License.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. */
  16. #include "u.h"
  17. #include "../port/lib.h"
  18. #include "mem.h"
  19. #include "dat.h"
  20. #include "fns.h"
  21. extern void *uart;
  22. void udelay(int d)
  23. {
  24. volatile int i;
  25. for(i = 0; i < 1*d; i++)
  26. ;
  27. }
  28. // Note: this was a separate file in coreboot. The Plan 9 convention
  29. // is to keep constants in the files that need them. This avoids the
  30. // proliferation of files and their use seen in other projects.
  31. /* Data */
  32. #define UART8250_RBR 0x00
  33. #define UART8250_TBR 0x00
  34. /* Control */
  35. #define UART8250_IER 0x01
  36. #define UART8250_IER_MSI 0x08 /* Enable Modem status interrupt */
  37. #define UART8250_IER_RLSI 0x04 /* Enable receiver line status interrupt */
  38. #define UART8250_IER_THRI 0x02 /* Enable Transmitter holding register int. */
  39. #define UART8250_IER_RDI 0x01 /* Enable receiver data interrupt */
  40. #define UART8250_IIR 0x02
  41. #define UART8250_IIR_NO_INT 0x01 /* No interrupts pending */
  42. #define UART8250_IIR_ID 0x06 /* Mask for the interrupt ID */
  43. #define UART8250_IIR_MSI 0x00 /* Modem status interrupt */
  44. #define UART8250_IIR_THRI 0x02 /* Transmitter holding register empty */
  45. #define UART8250_IIR_RDI 0x04 /* Receiver data interrupt */
  46. #define UART8250_IIR_RLSI 0x06 /* Receiver line status interrupt */
  47. #define UART8250_FCR 0x02
  48. #define UART8250_FCR_FIFO_EN 0x01 /* Fifo enable */
  49. #define UART8250_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */
  50. #define UART8250_FCR_CLEAR_XMIT 0x04 /* Clear the XMIT FIFO */
  51. #define UART8250_FCR_DMA_SELECT 0x08 /* For DMA applications */
  52. #define UART8250_FCR_TRIGGER_MASK 0xC0 /* Mask for the FIFO trigger range */
  53. #define UART8250_FCR_TRIGGER_1 0x00 /* Mask for trigger set at 1 */
  54. #define UART8250_FCR_TRIGGER_4 0x40 /* Mask for trigger set at 4 */
  55. #define UART8250_FCR_TRIGGER_8 0x80 /* Mask for trigger set at 8 */
  56. #define UART8250_FCR_TRIGGER_14 0xC0 /* Mask for trigger set at 14 */
  57. #define UART8250_FCR_RXSR 0x02 /* Receiver soft reset */
  58. #define UART8250_FCR_TXSR 0x04 /* Transmitter soft reset */
  59. #define UART8250_LCR 0x03
  60. #define UART8250_LCR_WLS_MSK 0x03 /* character length select mask */
  61. #define UART8250_LCR_WLS_5 0x00 /* 5 bit character length */
  62. #define UART8250_LCR_WLS_6 0x01 /* 6 bit character length */
  63. #define UART8250_LCR_WLS_7 0x02 /* 7 bit character length */
  64. #define UART8250_LCR_WLS_8 0x03 /* 8 bit character length */
  65. #define UART8250_LCR_STB 0x04 /* Number of stop Bits, off = 1, on = 1.5 or 2) */
  66. #define UART8250_LCR_PEN 0x08 /* Parity enable */
  67. #define UART8250_LCR_EPS 0x10 /* Even Parity Select */
  68. #define UART8250_LCR_STKP 0x20 /* Stick Parity */
  69. #define UART8250_LCR_SBRK 0x40 /* Set Break */
  70. #define UART8250_LCR_BKSE 0x80 /* Bank select enable */
  71. #define UART8250_LCR_DLAB 0x80 /* Divisor latch access bit */
  72. #define UART8250_MCR 0x04
  73. #define UART8250_MCR_DTR 0x01 /* DTR */
  74. #define UART8250_MCR_RTS 0x02 /* RTS */
  75. #define UART8250_MCR_OUT1 0x04 /* Out 1 */
  76. #define UART8250_MCR_OUT2 0x08 /* Out 2 */
  77. #define UART8250_MCR_LOOP 0x10 /* Enable loopback test mode */
  78. #define UART8250_MCR_DMA_EN 0x04
  79. #define UART8250_MCR_TX_DFR 0x08
  80. #define UART8250_DLL 0x00
  81. #define UART8250_DLM 0x01
  82. /* Status */
  83. #define UART8250_LSR 0x05
  84. #define UART8250_LSR_DR 0x01 /* Data ready */
  85. #define UART8250_LSR_OE 0x02 /* Overrun */
  86. #define UART8250_LSR_PE 0x04 /* Parity error */
  87. #define UART8250_LSR_FE 0x08 /* Framing error */
  88. #define UART8250_LSR_BI 0x10 /* Break */
  89. #define UART8250_LSR_THRE 0x20 /* Xmit holding register empty */
  90. #define UART8250_LSR_TEMT 0x40 /* Xmitter empty */
  91. #define UART8250_LSR_ERR 0x80 /* Error */
  92. #define UART8250_MSR 0x06
  93. #define UART8250_MSR_DCD 0x80 /* Data Carrier Detect */
  94. #define UART8250_MSR_RI 0x40 /* Ring Indicator */
  95. #define UART8250_MSR_DSR 0x20 /* Data Set Ready */
  96. #define UART8250_MSR_CTS 0x10 /* Clear to Send */
  97. #define UART8250_MSR_DDCD 0x08 /* Delta DCD */
  98. #define UART8250_MSR_TERI 0x04 /* Trailing edge ring indicator */
  99. #define UART8250_MSR_DDSR 0x02 /* Delta DSR */
  100. #define UART8250_MSR_DCTS 0x01 /* Delta CTS */
  101. #define UART8250_SCR 0x07
  102. #define UART8250_SPR 0x07
  103. /* Should support 8250, 16450, 16550, 16550A type UARTs */
  104. /* Expected character delay at 1200bps is 9ms for a working UART
  105. * and no flow-control. Assume UART as stuck if shift register
  106. * or FIFO takes more than 50ms per character to appear empty.
  107. */
  108. #define SINGLE_CHAR_TIMEOUT (50 * 1000)
  109. #define FIFO_TIMEOUT (16 * SINGLE_CHAR_TIMEOUT)
  110. /* Other essential constants. TODO: make these all plan 9 style */
  111. #define CONFIG_TTYS0_LCS 0x3
  112. // These functions are here as we may need to get tricky
  113. // for riscv with memory barriers and such.
  114. uint8_t read8(uint32_t *p)
  115. {
  116. return *p;
  117. }
  118. void write8(uint32_t *p, uint8_t val)
  119. {
  120. *p = val;
  121. }
  122. static uint8_t uart8250_read(uint32_t *base, uint8_t reg)
  123. {
  124. return read8(base + reg);
  125. }
  126. static void uart8250_write(uint32_t *base, uint8_t reg, uint8_t data)
  127. {
  128. write8(base + reg, data);
  129. }
  130. static int uart8250_mem_can_tx_byte(void *base)
  131. {
  132. return uart8250_read(base, UART8250_LSR) & UART8250_LSR_THRE;
  133. }
  134. static void uart8250_mem_tx_byte(void *base, unsigned char data)
  135. {
  136. unsigned long int i = SINGLE_CHAR_TIMEOUT;
  137. while (i-- && !uart8250_mem_can_tx_byte(base))
  138. udelay(1);
  139. uart8250_write(base, UART8250_TBR, data);
  140. }
  141. static void uart8250_mem_tx_flush(void *base)
  142. {
  143. unsigned long int i = FIFO_TIMEOUT;
  144. while (i-- && !(uart8250_read(base, UART8250_LSR) & UART8250_LSR_TEMT))
  145. udelay(1);
  146. }
  147. static int uart8250_mem_can_rx_byte(void *base)
  148. {
  149. return uart8250_read(base, UART8250_LSR) & UART8250_LSR_DR;
  150. }
  151. static int uart8250_mem_rx_byte(void *base)
  152. {
  153. unsigned long int i = SINGLE_CHAR_TIMEOUT;
  154. uint8_t c;
  155. while (i-- && !uart8250_mem_can_rx_byte(base))
  156. udelay(1);
  157. if (0) print("rx_byte, register is 0x%x LSR 0x%x\n", uart8250_read(base, UART8250_LSR) , UART8250_LSR_DR);
  158. if (i) {
  159. c = uart8250_read(base, UART8250_RBR);
  160. if (0) print("c is 0x%x\n", c);
  161. return c;
  162. }
  163. else
  164. return -1;
  165. }
  166. static void uart8250_mem_init(void *base, unsigned divisor)
  167. {
  168. /* Disable interrupts */
  169. uart8250_write(base, UART8250_IER, 0x0);
  170. /* Enable FIFOs */
  171. uart8250_write(base, UART8250_FCR, UART8250_FCR_FIFO_EN);
  172. /* Assert DTR and RTS so the other end is happy */
  173. uart8250_write(base, UART8250_MCR, UART8250_MCR_DTR | UART8250_MCR_RTS);
  174. /* Divisor Latch Access Bit -- DLAB -- on */
  175. uart8250_write(base, UART8250_LCR, UART8250_LCR_DLAB | CONFIG_TTYS0_LCS);
  176. uart8250_write(base, UART8250_DLL, divisor & 0xFF);
  177. uart8250_write(base, UART8250_DLM, (divisor >> 8) & 0xFF);
  178. /* Set to 3 for 8N1 */
  179. uart8250_write(base, UART8250_LCR, CONFIG_TTYS0_LCS);
  180. }
  181. // We don't use idx at present but it's a reasonable API to preserve
  182. // should someone ever add more than one uart.
  183. static void *uart_platform_baseptr(int idx)
  184. {
  185. return uart;
  186. }
  187. /* Calculate divisor. Do not floor but round to nearest integer. */
  188. static unsigned int uart_baudrate_divisor(unsigned int baudrate,
  189. unsigned int refclk, unsigned int oversample)
  190. {
  191. return (1 + (2 * refclk) / (baudrate * oversample)) / 2;
  192. }
  193. static unsigned int uart_platform_refclk(void)
  194. {
  195. return 25 * 1000 * 1000;
  196. }
  197. static unsigned int uart_input_clock_divider(void)
  198. {
  199. /* Specify the default oversample rate for the UART.
  200. *
  201. * UARTs oversample the receive data. The UART's input clock first
  202. * enters the baud-rate divider to generate the oversample clock. Then
  203. * the UART typically divides the result by 16. The asynchronous
  204. * receive data is synchronized with the oversample clock and when a
  205. * start bit is detected the UART delays half a bit time using the
  206. * oversample clock. Samples are then taken to verify the start bit and
  207. * if present, samples are taken for the rest of the frame.
  208. */
  209. return 16;
  210. }
  211. void lowrisc_uart_init(int idx)
  212. {
  213. void *base = uart_platform_baseptr(idx);
  214. if (!base)
  215. return;
  216. unsigned int div;
  217. div = uart_baudrate_divisor(115200,
  218. uart_platform_refclk(), uart_input_clock_divider());
  219. uart8250_mem_init(base, div);
  220. }
  221. void lowrisc_putchar(int data)
  222. {
  223. void *base = uart_platform_baseptr(0);
  224. if (!base)
  225. return;
  226. uart8250_mem_tx_byte(base, data);
  227. }
  228. int lowrisc_getchar(int idx)
  229. {
  230. void *base = uart_platform_baseptr(idx);
  231. if (!base)
  232. return -1;
  233. return uart8250_mem_rx_byte(base);
  234. }
  235. void lowrisc_flush(int idx)
  236. {
  237. void *base = uart_platform_baseptr(idx);
  238. if (!base)
  239. return;
  240. uart8250_mem_tx_flush(base);
  241. }