Cygwin: pinfo: raise MAX_PID to 4194304
[newlib-cygwin.git] / libgloss / arc / uart-8250.c
blobfd9c55fc4ed47f369f7462c87d5c662eaf060dad
1 /*
2 * uart-8250.c -- polling driver for 32-bit 8250 UART.
3 * Provides _uart_8250_setup(), _read() and _write(). Please note that
4 * _read() and _write() from this file can only be used for console access.
6 * Copyright (c) 2024 Synopsys Inc.
8 * The authors hereby grant permission to use, copy, modify, distribute,
9 * and license this software and its documentation for any purpose, provided
10 * that existing copyright notices are retained in all copies and that this
11 * notice is included verbatim in any distributions. No written agreement,
12 * license, or royalty fee is required for any of the authorized uses.
13 * Modifications to this software may be copyrighted by their authors
14 * and need not follow the licensing terms described here, provided that
15 * the new terms are clearly indicated on the first page of each file where
16 * they apply.
19 #include <unistd.h>
20 #include <stdint.h>
21 #include <stdio.h>
22 #include <errno.h>
23 #include "arc-specific.h"
26 * List of UART 8250 registers with offsets:
28 * 0x00 - Transmit Holding Register, WO, LCR_DLAB == 0
29 * 0x00 - Receive Buffer Register, RO, LCR_DLAB == 0
30 * 0x00 - Divisor Latch Low, RW, LCR_DLAB == 1
31 * 0x04 - Divisor Latch High, RW, LCR_DLAB == 1
32 * 0x04 - Interrupt Enable Register, RW, LCR_DLAB == 0
33 * 0x08 - FIFO Control Register, WO
34 * 0x08 - Interrupt Identification Register, RO
35 * 0x0C - Line Control Register, RW
36 * 0x10 - Modem Control Register, RW
37 * 0x14 - Line Status Register, RO
38 * 0x18 - Modem Status Register, RO
41 #define THR_OFFSET 0x00
42 #define RBR_OFFSET 0x00
43 #define DLL_OFFSET 0x00
44 #define DLH_OFFSET 0x04
45 #define IER_OFFSET 0x04
46 #define FCR_OFFSET 0x08
47 #define IIR_OFFSET 0x08
48 #define LCR_OFFSET 0x0C
49 #define MCR_OFFSET 0x10
50 #define LSR_OFFSET 0x14
51 #define MSR_OFFSET 0x18
54 * LCR (Line Control Register) fields:
56 * [7] - Divisor Latch Access Bit
57 * [6] - Set Break
58 * [5] - Stick Parity
59 * [4] - Even Parity Select
60 * [3] - Parity Enable
61 * [2] - Number of Stop Bits
62 * [1:0] - Data Length Select. Values:
63 * 0b11 - 8 data bits per character (default)
64 * 0b10 - 7 data bits per character
65 * 0b01 - 6 data bits per character
66 * 0b00 - 5 data bits per character
69 #define LCR_DLAB_SHIFT 7
70 #define LCR_SB_SHIFT 6
71 #define LCR_SP_SHIFT 5
72 #define LCR_EPS_SHIFT 4
73 #define LCR_PEN_SHIFT 3
74 #define LCR_STB_SHIFT 2
75 #define LCR_DLS_SHIFT 0
77 * MCR (Modem Control Register) fields:
79 * [4] - LoopBack Bit
80 * [3] - Auxiliary Output 2
81 * [2] - Auxiliary Output 1
82 * [1] - Request To Send (ON by default)
83 * [0] - Data Terminal Ready (ON by default)
86 #define MCR_LB_SHIFT 4
87 #define MCR_OUT2_SHIFT 3
88 #define MCR_OUT1_SHIFT 2
89 #define MCR_RTS_SHIFT 1
90 #define MCR_DTR_SHIFT 0
93 * LSR (Line Status Register) fields:
95 * [7] - Receiver FIFO Error
96 * [6] - Transmitter Empty
97 * [5] - Transmit Holding Register Empty
98 * [4] - Break Interrupt
99 * [3] - Framing Error
100 * [2] - Parity Error
101 * [1] - Overrun Error
102 * [0] - Data Ready
105 #define LSR_RFE_SHIFT 7
106 #define LSR_TEMT_SHIFT 6
107 #define LSR_THRE_SHIFT 5
108 #define LSR_BI_SHIFT 4
109 #define LSR_FE_SHIFT 3
110 #define LSR_PE_SHIFT 2
111 #define LSR_OE_SHIFT 1
112 #define LSR_DR_SHIFT 0
115 * Default initial values for configuration registers.
118 #define FCR_DEFAULT 0x0
119 #define IER_DEFAULT 0x0
120 #define LCR_DLS_DEFAULT 0x3
121 #define LCR_DEFAULT (LCR_DLS_DEFAULT << LCR_DLS_SHIFT)
122 #define MCR_RTS_DEFAULT 0x1
123 #define MCR_DTR_DEFAULT 0x1
124 #define MCR_DEFAULT ((MCR_RTS_DEFAULT << MCR_RTS_SHIFT) | \
125 (MCR_DTR_DEFAULT << MCR_DTR_SHIFT))
127 #define LCR_MODE_SETUP (0x1 << LCR_DLAB_SHIFT)
128 #define LSR_MODE_GETC (0x1 << LSR_DR_SHIFT)
129 #define LSR_MODE_PUTC ((0x1 << LSR_TEMT_SHIFT) | (0x1 << LSR_THRE_SHIFT))
131 /* Main UART control structure. */
132 struct _uart_8250 {
133 volatile char *base; /* Start of UART registers. */
134 uint32_t clk; /* UART clock. */
135 uint32_t baud; /* Baud rate. */
136 int aux_mapped; /* If UART registers are mapped to AUX or memory. */
137 int ready; /* If UART is ready to use or not. */
140 static struct _uart_8250 _uart_8250;
142 /* Write 32-bit value to the UART register. */
143 static inline void
144 _uart_8250_write_reg (const struct _uart_8250 *uart, uint32_t reg,
145 uint32_t value)
147 if (uart->aux_mapped)
148 write_aux_reg (value, (uint32_t) uart->base + reg);
149 else
150 *(volatile uint32_t *)(uart->base + reg) = value;
153 /* Read 32-bit value from the UART register. */
154 static inline uint32_t
155 _uart_8250_read_reg (const struct _uart_8250 *uart, uint32_t reg)
157 if (uart->aux_mapped)
158 return read_aux_reg ((uint32_t) uart->base + reg);
159 else
160 return *(volatile uint32_t *)(uart->base + reg);
163 /* Wait until all flags are set. */
164 static inline void
165 _uart_8250_wait (const struct _uart_8250 *uart, uint32_t reg, uint32_t flags)
167 while (1)
169 if ((_uart_8250_read_reg (uart, reg) & flags) == flags)
170 break;
174 /* Get one character from UART. CR is converted to NL. */
175 static int
176 _uart_8250_getc (const struct _uart_8250 *uart)
178 char c;
180 _uart_8250_wait (uart, LSR_OFFSET, LSR_MODE_GETC);
182 c = _uart_8250_read_reg (uart, RBR_OFFSET);
184 if (c == '\r')
185 c = '\n';
187 return c;
190 /* Put one character to UART. CR is placed before NL. */
191 static void
192 _uart_8250_putc (const struct _uart_8250 *uart, char c)
194 if (c == '\n')
195 _uart_8250_putc (uart, '\r');
197 _uart_8250_wait (uart, LSR_OFFSET, LSR_MODE_PUTC);
199 _uart_8250_write_reg (uart, THR_OFFSET, c);
203 * Setup UART control structure and following parameters:
205 * - baudrate if clock and baudrate are passed to function
206 * - 8n1 (8 data bits, no parity bit, one stop bit)
207 * - disable interrupts
208 * - disable FIFO
209 * - set Request To Send and Data Terminal Ready
211 * Arguments:
213 * - base - start address of UART registers
214 * - aux_mapped - set if UART registers are mapped to ARC AUX
215 * - clk - UART clock frequency
216 * - baud - UART baudrate to setup
218 * The function returns 0 on success.
221 _uart_8250_setup (void *base, int aux_mapped, uint32_t clk, uint32_t baud)
223 struct _uart_8250 *uart = &_uart_8250;
225 uart->base = base;
226 uart->aux_mapped = aux_mapped;
227 uart->clk = clk;
228 uart->baud = baud;
230 if (clk && baud)
232 uint32_t div;
234 div = ((clk + 8 * baud) / baud) / 16;
235 _uart_8250_write_reg (uart, LCR_OFFSET, LCR_MODE_SETUP);
236 _uart_8250_write_reg (uart, DLL_OFFSET, div & 0xFF);
237 _uart_8250_write_reg (uart, DLH_OFFSET, div >> 8);
240 _uart_8250_write_reg (uart, FCR_OFFSET, FCR_DEFAULT);
241 _uart_8250_write_reg (uart, IER_OFFSET, IER_DEFAULT);
242 _uart_8250_write_reg (uart, LCR_OFFSET, LCR_DEFAULT);
243 _uart_8250_write_reg (uart, MCR_OFFSET, MCR_DEFAULT);
245 uart->ready = 1;
247 return 0;
250 /* _read() is implemented only for stdin. Each read character is echoed. */
251 ssize_t
252 _read (int fd, void *buf, size_t count)
254 struct _uart_8250 *uart = &_uart_8250;
255 size_t bytes_read;
256 char *buf_char = buf;
257 int c;
259 if (fd != STDIN_FILENO)
261 errno = ENOSYS;
262 return -1;
265 if (!uart->ready)
267 errno = EIO;
268 return -1;
271 bytes_read = 0;
272 c = EOF;
273 /* Break on '\n' to simulate readline behavior. */
274 while (bytes_read != count && c != '\n')
276 c = _uart_8250_getc (uart);
277 if (c == EOF)
278 break;
280 /* Echo character to the console. */
281 _uart_8250_putc (uart, c);
283 buf_char[bytes_read] = c;
284 bytes_read++;
287 return bytes_read;
290 /* _write() is implemented only for stdout and stderr. */
291 ssize_t
292 _write (int fd, const char *buf, size_t nbyte)
294 struct _uart_8250 *uart = &_uart_8250;
295 uint32_t bytes_written;
297 if (fd != STDOUT_FILENO && fd != STDERR_FILENO)
299 errno = ENOSYS;
300 return -1;
303 if (!uart->ready)
305 errno = EIO;
306 return -1;
309 bytes_written = 0;
310 while (bytes_written != nbyte)
312 _uart_8250_putc (uart, buf[bytes_written]);
313 bytes_written++;
316 return bytes_written;