blob: b2f234b28336e202c0d119b49c444273b5abd49a [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
Kyösti Mälkki4566d2e2014-04-23 10:28:59 +030021#include <rules.h>
Eric Biederman8ca8d762003-04-22 19:02:15 +000022#include <arch/io.h>
Kyösti Mälkki1d7541f2014-02-17 21:34:42 +020023#include <console/uart.h>
Rudolf Marek7f0e9302011-09-02 23:23:41 +020024#include <trace.h>
Kyösti Mälkkibea6bf02014-01-30 15:45:16 +020025#include "uart8250reg.h"
Rudolf Marek7f0e9302011-09-02 23:23:41 +020026
Kyösti Mälkkibbf6f3d2014-03-15 01:32:55 +020027#ifndef __ROMCC__
28#include <boot/coreboot_tables.h>
29#endif
30
Stefan Reinauer85b0fa12010-12-17 00:08:21 +000031/* Should support 8250, 16450, 16550, 16550A type UARTs */
Eric Biederman8ca8d762003-04-22 19:02:15 +000032
Kyösti Mälkki3ee16682014-02-17 19:37:52 +020033/* Nominal values only, good for the range of choices Kconfig offers for
34 * set of standard baudrates.
35 */
36#define BAUDRATE_REFCLK (115200)
37#define BAUDRATE_OVERSAMPLE (1)
38
Kyösti Mälkki9dd3ef12012-02-07 20:50:22 +020039/* Expected character delay at 1200bps is 9ms for a working UART
40 * and no flow-control. Assume UART as stuck if shift register
41 * or FIFO takes more than 50ms per character to appear empty.
42 *
43 * Estimated that inb() from UART takes 1 microsecond.
44 */
45#define SINGLE_CHAR_TIMEOUT (50 * 1000)
46#define FIFO_TIMEOUT (16 * SINGLE_CHAR_TIMEOUT)
47
Kyösti Mälkki47707492014-02-15 07:53:18 +020048static int uart8250_can_tx_byte(unsigned base_port)
Eric Biederman8ca8d762003-04-22 19:02:15 +000049{
Kyösti Mälkki9dd3ef12012-02-07 20:50:22 +020050 return inb(base_port + UART_LSR) & UART_LSR_THRE;
Eric Biederman8ca8d762003-04-22 19:02:15 +000051}
52
Kyösti Mälkki47707492014-02-15 07:53:18 +020053static void uart8250_tx_byte(unsigned base_port, unsigned char data)
Eric Biederman8ca8d762003-04-22 19:02:15 +000054{
Kyösti Mälkki9dd3ef12012-02-07 20:50:22 +020055 unsigned long int i = SINGLE_CHAR_TIMEOUT;
56 while (i-- && !uart8250_can_tx_byte(base_port));
Kyösti Mälkki47707492014-02-15 07:53:18 +020057 outb(data, base_port + UART_TBR);
Eric Biederman8ca8d762003-04-22 19:02:15 +000058}
59
Kyösti Mälkki47707492014-02-15 07:53:18 +020060static void uart8250_tx_flush(unsigned base_port)
Eric Biederman8ca8d762003-04-22 19:02:15 +000061{
Kyösti Mälkki9dd3ef12012-02-07 20:50:22 +020062 unsigned long int i = FIFO_TIMEOUT;
63 while (i-- && !(inb(base_port + UART_LSR) & UART_LSR_TEMT));
Eric Biederman8ca8d762003-04-22 19:02:15 +000064}
65
Kyösti Mälkki47707492014-02-15 07:53:18 +020066static int uart8250_can_rx_byte(unsigned base_port)
Greg Watsone54d55b2004-03-13 03:40:51 +000067{
Stefan Reinauer85b0fa12010-12-17 00:08:21 +000068 return inb(base_port + UART_LSR) & UART_LSR_DR;
Greg Watsone54d55b2004-03-13 03:40:51 +000069}
70
Kyösti Mälkki47707492014-02-15 07:53:18 +020071static unsigned char uart8250_rx_byte(unsigned base_port)
Greg Watsone54d55b2004-03-13 03:40:51 +000072{
Kyösti Mälkki9dd3ef12012-02-07 20:50:22 +020073 unsigned long int i = SINGLE_CHAR_TIMEOUT;
74 while (i-- && !uart8250_can_rx_byte(base_port));
Patrick Georgi472efa62012-02-16 20:44:20 +010075
Kyösti Mälkki9dd3ef12012-02-07 20:50:22 +020076 if (i)
77 return inb(base_port + UART_RBR);
78 else
79 return 0x0;
Greg Watsone54d55b2004-03-13 03:40:51 +000080}
81
Kyösti Mälkki47707492014-02-15 07:53:18 +020082static void uart8250_init(unsigned base_port, unsigned divisor)
Eric Biederman8ca8d762003-04-22 19:02:15 +000083{
Rudolf Marek7f0e9302011-09-02 23:23:41 +020084 DISABLE_TRACE;
Stefan Reinauer85b0fa12010-12-17 00:08:21 +000085 /* Disable interrupts */
Eric Biederman8ca8d762003-04-22 19:02:15 +000086 outb(0x0, base_port + UART_IER);
Stefan Reinauer85b0fa12010-12-17 00:08:21 +000087 /* Enable FIFOs */
88 outb(UART_FCR_FIFO_EN, base_port + UART_FCR);
89
Stefan Reinauerebafa4d2006-10-07 00:13:24 +000090 /* assert DTR and RTS so the other end is happy */
Stefan Reinauer85b0fa12010-12-17 00:08:21 +000091 outb(UART_MCR_DTR | UART_MCR_RTS, base_port + UART_MCR);
92
93 /* DLAB on */
94 outb(UART_LCR_DLAB | CONFIG_TTYS0_LCS, base_port + UART_LCR);
95
Kyösti Mälkki9dd3ef12012-02-07 20:50:22 +020096 /* Set Baud Rate Divisor. 12 ==> 9600 Baud */
Eric Biederman8ca8d762003-04-22 19:02:15 +000097 outb(divisor & 0xFF, base_port + UART_DLL);
98 outb((divisor >> 8) & 0xFF, base_port + UART_DLM);
Stefan Reinauer85b0fa12010-12-17 00:08:21 +000099
100 /* Set to 3 for 8N1 */
101 outb(CONFIG_TTYS0_LCS, base_port + UART_LCR);
Rudolf Marek7f0e9302011-09-02 23:23:41 +0200102 ENABLE_TRACE;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000103}
Eric Biederman5cd81732004-03-11 15:01:31 +0000104
Kyösti Mälkki47707492014-02-15 07:53:18 +0200105/* FIXME: Needs uart index from Kconfig.
106 * Already use array as a work-around for ROMCC.
107 */
108static const unsigned bases[1] = { CONFIG_TTYS0_BASE };
109
Kyösti Mälkkibbf6f3d2014-03-15 01:32:55 +0200110unsigned int uart_platform_base(int idx)
111{
112 return bases[idx];
113}
114
Stefan Reinauer85b0fa12010-12-17 00:08:21 +0000115void uart_init(void)
116{
Kyösti Mälkki3ee16682014-02-17 19:37:52 +0200117 unsigned int div;
118 div = uart_baudrate_divisor(default_baudrate(), BAUDRATE_REFCLK,
119 BAUDRATE_OVERSAMPLE);
Kyösti Mälkki47707492014-02-15 07:53:18 +0200120 uart8250_init(bases[0], div);
121}
122
123void uart_tx_byte(unsigned char data)
124{
125 uart8250_tx_byte(bases[0], data);
126}
127
128unsigned char uart_rx_byte(void)
129{
130 return uart8250_rx_byte(bases[0]);
131}
132
Kyösti Mälkki47707492014-02-15 07:53:18 +0200133void uart_tx_flush(void)
134{
135 uart8250_tx_flush(bases[0]);
Stefan Reinauer85b0fa12010-12-17 00:08:21 +0000136}
Kyösti Mälkkibbf6f3d2014-03-15 01:32:55 +0200137
Kyösti Mälkki4566d2e2014-04-23 10:28:59 +0300138#if ENV_RAMSTAGE
Kyösti Mälkkibbf6f3d2014-03-15 01:32:55 +0200139void uart_fill_lb(void *data)
140{
141 struct lb_serial serial;
142 serial.type = LB_SERIAL_TYPE_IO_MAPPED;
143 serial.baseaddr = uart_platform_base(0);
144 serial.baud = default_baudrate();
145 lb_add_serial(&serial, data);
146
147 lb_add_console(LB_TAG_CONSOLE_SERIAL8250, data);
148}
149#endif