blob: b9abc9e2198e0e28549845f162ffad2d4b7bfa8c [file] [log] [blame]
Eric Biederman8ca8d762003-04-22 19:02:15 +00001/* Should support 8250, 16450, 16550, 16550A type uarts */
2#include <arch/io.h>
3#include <uart8250.h>
4
5/* Data */
6#define UART_RBR 0x00
7#define UART_TBR 0x00
8
9/* Control */
10#define UART_IER 0x01
11#define UART_IIR 0x02
12#define UART_FCR 0x02
13#define UART_LCR 0x03
14#define UART_MCR 0x04
15#define UART_DLL 0x00
16#define UART_DLM 0x01
17
18/* Status */
19#define UART_LSR 0x05
20#define UART_MSR 0x06
21#define UART_SCR 0x07
22
Eric Biederman69afe282004-11-11 06:53:24 +000023static inline int uart8250_can_tx_byte(unsigned base_port)
Eric Biederman8ca8d762003-04-22 19:02:15 +000024{
25 return inb(base_port + UART_LSR) & 0x20;
26}
27
28static inline void uart8250_wait_to_tx_byte(unsigned base_port)
29{
30 while(!uart8250_can_tx_byte(base_port))
31 ;
32}
33
34static inline void uart8250_wait_until_sent(unsigned base_port)
35{
36 while(!(inb(base_port + UART_LSR) & 0x40))
37 ;
38}
39
40void uart8250_tx_byte(unsigned base_port, unsigned char data)
41{
42 uart8250_wait_to_tx_byte(base_port);
43 outb(data, base_port + UART_TBR);
44 /* Make certain the data clears the fifos */
45 uart8250_wait_until_sent(base_port);
46}
47
Greg Watsone54d55b2004-03-13 03:40:51 +000048int uart8250_can_rx_byte(unsigned base_port)
49{
50 return inb(base_port + UART_LSR) & 0x01;
51}
52
53unsigned char uart8250_rx_byte(unsigned base_port)
54{
55 while(!uart8250_can_rx_byte(base_port))
56 ;
57 return inb(base_port + UART_RBR);
58}
59
Eric Biederman8ca8d762003-04-22 19:02:15 +000060void uart8250_init(unsigned base_port, unsigned divisor, unsigned lcs)
61{
62 lcs &= 0x7f;
63 /* disable interrupts */
64 outb(0x0, base_port + UART_IER);
65 /* enable fifo's */
66 outb(0x01, base_port + UART_FCR);
Stefan Reinauerebafa4d2006-10-07 00:13:24 +000067 /* assert DTR and RTS so the other end is happy */
68 outb(0x03, base_port + UART_MCR);
Eric Biederman8ca8d762003-04-22 19:02:15 +000069 /* Set Baud Rate Divisor to 12 ==> 115200 Baud */
70 outb(0x80 | lcs, base_port + UART_LCR);
71 outb(divisor & 0xFF, base_port + UART_DLL);
72 outb((divisor >> 8) & 0xFF, base_port + UART_DLM);
73 outb(lcs, base_port + UART_LCR);
74}
Eric Biederman5cd81732004-03-11 15:01:31 +000075
76/* Initialize a generic uart */
77void init_uart8250(unsigned base_port, struct uart8250 *uart)
78{
79 int divisor;
80 int lcs;
81 divisor = 115200/(uart->baud ? uart->baud: 1);
82 lcs = 3;
83 if (base_port == TTYS0_BASE) {
84 /* Don't reinitialize the console serial port,
85 * This is espeically nasty in SMP.
86 */
87 return;
88 }
89 uart8250_init(base_port, divisor, lcs);
90}