blob: 3171e00d138c6e23cd925d008e2fca5aef682a67 [file] [log] [blame]
Stefan Reinauer85b0fa12010-12-17 00:08:21 +00001/*
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 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
Eric Biederman8ca8d762003-04-22 19:02:15 +000021#include <arch/io.h>
Kyösti Mälkki1d7541f2014-02-17 21:34:42 +020022#include <console/uart.h>
Eric Biederman8ca8d762003-04-22 19:02:15 +000023#include <uart8250.h>
Rudolf Marek7f0e9302011-09-02 23:23:41 +020024#include <trace.h>
25
Stefan Reinauer85b0fa12010-12-17 00:08:21 +000026/* Should support 8250, 16450, 16550, 16550A type UARTs */
Eric Biederman8ca8d762003-04-22 19:02:15 +000027
Kyösti Mälkki3ee16682014-02-17 19:37:52 +020028/* Nominal values only, good for the range of choices Kconfig offers for
29 * set of standard baudrates.
30 */
31#define BAUDRATE_REFCLK (115200)
32#define BAUDRATE_OVERSAMPLE (1)
33
Kyösti Mälkki9dd3ef12012-02-07 20:50:22 +020034/* Expected character delay at 1200bps is 9ms for a working UART
35 * and no flow-control. Assume UART as stuck if shift register
36 * or FIFO takes more than 50ms per character to appear empty.
37 *
38 * Estimated that inb() from UART takes 1 microsecond.
39 */
40#define SINGLE_CHAR_TIMEOUT (50 * 1000)
41#define FIFO_TIMEOUT (16 * SINGLE_CHAR_TIMEOUT)
42
Eric Biederman69afe282004-11-11 06:53:24 +000043static inline int uart8250_can_tx_byte(unsigned base_port)
Eric Biederman8ca8d762003-04-22 19:02:15 +000044{
Kyösti Mälkki9dd3ef12012-02-07 20:50:22 +020045 return inb(base_port + UART_LSR) & UART_LSR_THRE;
Eric Biederman8ca8d762003-04-22 19:02:15 +000046}
47
48static inline void uart8250_wait_to_tx_byte(unsigned base_port)
49{
Kyösti Mälkki9dd3ef12012-02-07 20:50:22 +020050 unsigned long int i = SINGLE_CHAR_TIMEOUT;
51 while (i-- && !uart8250_can_tx_byte(base_port));
Eric Biederman8ca8d762003-04-22 19:02:15 +000052}
53
54static inline void uart8250_wait_until_sent(unsigned base_port)
55{
Kyösti Mälkki9dd3ef12012-02-07 20:50:22 +020056 unsigned long int i = FIFO_TIMEOUT;
57 while (i-- && !(inb(base_port + UART_LSR) & UART_LSR_TEMT));
Eric Biederman8ca8d762003-04-22 19:02:15 +000058}
59
60void uart8250_tx_byte(unsigned base_port, unsigned char data)
61{
62 uart8250_wait_to_tx_byte(base_port);
63 outb(data, base_port + UART_TBR);
Kevin O'Connora68555f2011-07-09 20:22:21 -040064}
65
66void uart8250_tx_flush(unsigned base_port)
67{
Eric Biederman8ca8d762003-04-22 19:02:15 +000068 uart8250_wait_until_sent(base_port);
69}
70
Greg Watsone54d55b2004-03-13 03:40:51 +000071int uart8250_can_rx_byte(unsigned base_port)
72{
Stefan Reinauer85b0fa12010-12-17 00:08:21 +000073 return inb(base_port + UART_LSR) & UART_LSR_DR;
Greg Watsone54d55b2004-03-13 03:40:51 +000074}
75
76unsigned char uart8250_rx_byte(unsigned base_port)
77{
Kyösti Mälkki9dd3ef12012-02-07 20:50:22 +020078 unsigned long int i = SINGLE_CHAR_TIMEOUT;
79 while (i-- && !uart8250_can_rx_byte(base_port));
Patrick Georgi472efa62012-02-16 20:44:20 +010080
Kyösti Mälkki9dd3ef12012-02-07 20:50:22 +020081 if (i)
82 return inb(base_port + UART_RBR);
83 else
84 return 0x0;
Greg Watsone54d55b2004-03-13 03:40:51 +000085}
86
Stefan Reinauer85b0fa12010-12-17 00:08:21 +000087void uart8250_init(unsigned base_port, unsigned divisor)
Eric Biederman8ca8d762003-04-22 19:02:15 +000088{
Rudolf Marek7f0e9302011-09-02 23:23:41 +020089 DISABLE_TRACE;
Stefan Reinauer85b0fa12010-12-17 00:08:21 +000090 /* Disable interrupts */
Eric Biederman8ca8d762003-04-22 19:02:15 +000091 outb(0x0, base_port + UART_IER);
Stefan Reinauer85b0fa12010-12-17 00:08:21 +000092 /* Enable FIFOs */
93 outb(UART_FCR_FIFO_EN, base_port + UART_FCR);
94
Stefan Reinauerebafa4d2006-10-07 00:13:24 +000095 /* assert DTR and RTS so the other end is happy */
Stefan Reinauer85b0fa12010-12-17 00:08:21 +000096 outb(UART_MCR_DTR | UART_MCR_RTS, base_port + UART_MCR);
97
98 /* DLAB on */
99 outb(UART_LCR_DLAB | CONFIG_TTYS0_LCS, base_port + UART_LCR);
100
Kyösti Mälkki9dd3ef12012-02-07 20:50:22 +0200101 /* Set Baud Rate Divisor. 12 ==> 9600 Baud */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000102 outb(divisor & 0xFF, base_port + UART_DLL);
103 outb((divisor >> 8) & 0xFF, base_port + UART_DLM);
Stefan Reinauer85b0fa12010-12-17 00:08:21 +0000104
105 /* Set to 3 for 8N1 */
106 outb(CONFIG_TTYS0_LCS, base_port + UART_LCR);
Rudolf Marek7f0e9302011-09-02 23:23:41 +0200107 ENABLE_TRACE;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000108}
Eric Biederman5cd81732004-03-11 15:01:31 +0000109
Stefan Reinauer85b0fa12010-12-17 00:08:21 +0000110void uart_init(void)
111{
Kyösti Mälkki3ee16682014-02-17 19:37:52 +0200112 unsigned int div;
113 div = uart_baudrate_divisor(default_baudrate(), BAUDRATE_REFCLK,
114 BAUDRATE_OVERSAMPLE);
Stefan Reinauerf349d552011-04-22 02:17:26 +0000115 uart8250_init(CONFIG_TTYS0_BASE, div);
Stefan Reinauer85b0fa12010-12-17 00:08:21 +0000116}