blob: ce45de9c10b13099381c0232f1039051eceffe0a [file] [log] [blame]
Stefan Reinauer4885daa2011-04-26 23:47:04 +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
21#include <arch/io.h>
Kyösti Mälkki1d7541f2014-02-17 21:34:42 +020022#include <console/uart.h>
Stefan Reinauer4885daa2011-04-26 23:47:04 +000023#include <uart8250.h>
Stefan Reinauer4885daa2011-04-26 23:47:04 +000024#include <device/device.h>
Stefan Reinauer47818002012-03-30 16:19:31 -070025#include <delay.h>
Stefan Reinauer4885daa2011-04-26 23:47:04 +000026
27/* Should support 8250, 16450, 16550, 16550A type UARTs */
28
Stefan Reinauer47818002012-03-30 16:19:31 -070029/* Expected character delay at 1200bps is 9ms for a working UART
30 * and no flow-control. Assume UART as stuck if shift register
31 * or FIFO takes more than 50ms per character to appear empty.
32 */
33#define SINGLE_CHAR_TIMEOUT (50 * 1000)
34#define FIFO_TIMEOUT (16 * SINGLE_CHAR_TIMEOUT)
35
Kyösti Mälkki2b95da02014-02-15 10:19:23 +020036static int uart8250_mem_can_tx_byte(unsigned base_port)
Stefan Reinauer4885daa2011-04-26 23:47:04 +000037{
Stefan Reinauer47818002012-03-30 16:19:31 -070038 return read8(base_port + UART_LSR) & UART_LSR_THRE;
Stefan Reinauer4885daa2011-04-26 23:47:04 +000039}
40
Kyösti Mälkki2b95da02014-02-15 10:19:23 +020041static void uart8250_mem_tx_byte(unsigned base_port, unsigned char data)
Stefan Reinauer4885daa2011-04-26 23:47:04 +000042{
Stefan Reinauer47818002012-03-30 16:19:31 -070043 unsigned long int i = SINGLE_CHAR_TIMEOUT;
44 while(i-- && !uart8250_mem_can_tx_byte(base_port))
45 udelay(1);
Kyösti Mälkki2b95da02014-02-15 10:19:23 +020046 write8(base_port + UART_TBR, data);
Stefan Reinauer4885daa2011-04-26 23:47:04 +000047}
48
Kyösti Mälkki2b95da02014-02-15 10:19:23 +020049static void uart8250_mem_tx_flush(unsigned base_port)
Stefan Reinauer4885daa2011-04-26 23:47:04 +000050{
Stefan Reinauer47818002012-03-30 16:19:31 -070051 unsigned long int i = FIFO_TIMEOUT;
52 while(i-- && !(read8(base_port + UART_LSR) & UART_LSR_TEMT))
53 udelay(1);
Stefan Reinauer4885daa2011-04-26 23:47:04 +000054}
55
Kyösti Mälkki2b95da02014-02-15 10:19:23 +020056static int uart8250_mem_can_rx_byte(unsigned base_port)
Stefan Reinauer4885daa2011-04-26 23:47:04 +000057{
58 return read8(base_port + UART_LSR) & UART_LSR_DR;
59}
60
Kyösti Mälkki2b95da02014-02-15 10:19:23 +020061static unsigned char uart8250_mem_rx_byte(unsigned base_port)
Stefan Reinauer4885daa2011-04-26 23:47:04 +000062{
Stefan Reinauer47818002012-03-30 16:19:31 -070063 unsigned long int i = SINGLE_CHAR_TIMEOUT;
64 while(i-- && !uart8250_mem_can_rx_byte(base_port))
65 udelay(1);
66 if (i)
67 return read8(base_port + UART_RBR);
68 else
69 return 0x0;
Stefan Reinauer4885daa2011-04-26 23:47:04 +000070}
71
Kyösti Mälkki2b95da02014-02-15 10:19:23 +020072static void uart8250_mem_init(unsigned base_port, unsigned divisor)
Stefan Reinauer4885daa2011-04-26 23:47:04 +000073{
74 /* Disable interrupts */
75 write8(base_port + UART_IER, 0x0);
76 /* Enable FIFOs */
77 write8(base_port + UART_FCR, UART_FCR_FIFO_EN);
78
79 /* Assert DTR and RTS so the other end is happy */
80 write8(base_port + UART_MCR, UART_MCR_DTR | UART_MCR_RTS);
81
82 /* DLAB on */
83 write8(base_port + UART_LCR, UART_LCR_DLAB | CONFIG_TTYS0_LCS);
84
Stefan Reinauer4885daa2011-04-26 23:47:04 +000085 write8(base_port + UART_DLL, divisor & 0xFF);
86 write8(base_port + UART_DLM, (divisor >> 8) & 0xFF);
87
88 /* Set to 3 for 8N1 */
89 write8(base_port + UART_LCR, CONFIG_TTYS0_LCS);
90}
91
Kyösti Mälkki2b95da02014-02-15 10:19:23 +020092void uart_init(void)
Stefan Reinauer4885daa2011-04-26 23:47:04 +000093{
Kyösti Mälkki2b95da02014-02-15 10:19:23 +020094 u32 base = uart_platform_base(0);
95 if (!base)
96 return;
Stefan Reinauer4885daa2011-04-26 23:47:04 +000097
Kyösti Mälkki2b95da02014-02-15 10:19:23 +020098 unsigned int div;
Kyösti Mälkki3ee16682014-02-17 19:37:52 +020099 div = uart_baudrate_divisor(default_baudrate(), uart_platform_refclk(), 16);
Kyösti Mälkki2b95da02014-02-15 10:19:23 +0200100 uart8250_mem_init(base, div);
101}
Stefan Reinauer4885daa2011-04-26 23:47:04 +0000102
Kyösti Mälkki2b95da02014-02-15 10:19:23 +0200103void uart_tx_byte(unsigned char data)
104{
105 u32 base = uart_platform_base(0);
106 if (!base)
107 return;
108 uart8250_mem_tx_byte(base, data);
109}
110
111unsigned char uart_rx_byte(void)
112{
113 u32 base = uart_platform_base(0);
114 if (!base)
115 return 0xff;
116 return uart8250_mem_rx_byte(base);
117}
118
119int uart_can_rx_byte(void)
120{
121 u32 base = uart_platform_base(0);
122 if (!base)
123 return 0;
124 return uart8250_mem_can_rx_byte(base);
125}
126
127void uart_tx_flush(void)
128{
129 u32 base = uart_platform_base(0);
130 if (!base)
131 return;
132 uart8250_mem_tx_flush(base);
Stefan Reinauer4885daa2011-04-26 23:47:04 +0000133}