blob: fb7327e2387a8fdc26f35a379b4de0d69dfde445 [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
Patrick Georgib890a122015-03-26 15:17:45 +010018 * Foundation, Inc.
Stefan Reinauer4885daa2011-04-26 23:47:04 +000019 */
20
21#include <arch/io.h>
Aaron Durbin4f7cf3a2015-07-30 16:47:18 -050022#include <boot/coreboot_tables.h>
Kyösti Mälkki1d7541f2014-02-17 21:34:42 +020023#include <console/uart.h>
Stefan Reinauer4885daa2011-04-26 23:47:04 +000024#include <device/device.h>
Stefan Reinauer47818002012-03-30 16:19:31 -070025#include <delay.h>
Aaron Durbin4f7cf3a2015-07-30 16:47:18 -050026#include <rules.h>
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +020027#include <stdint.h>
Kyösti Mälkkibea6bf02014-01-30 15:45:16 +020028#include "uart8250reg.h"
Stefan Reinauer4885daa2011-04-26 23:47:04 +000029
30/* Should support 8250, 16450, 16550, 16550A type UARTs */
31
Stefan Reinauer47818002012-03-30 16:19:31 -070032/* Expected character delay at 1200bps is 9ms for a working UART
33 * and no flow-control. Assume UART as stuck if shift register
34 * or FIFO takes more than 50ms per character to appear empty.
35 */
36#define SINGLE_CHAR_TIMEOUT (50 * 1000)
37#define FIFO_TIMEOUT (16 * SINGLE_CHAR_TIMEOUT)
38
Naveen Krishna Chatradhia73408d2015-07-08 14:23:06 +053039#if IS_ENABLED(CONFIG_DRIVERS_UART_8250MEM_32)
40static uint8_t uart8250_read(void *base, uint8_t reg)
41{
42 return read32(base + 4 * reg) & 0xff;
43}
44
45static void uart8250_write(void *base, uint8_t reg, uint8_t data)
46{
47 write32(base + 4 * reg, data);
48}
49#else
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +020050static uint8_t uart8250_read(void *base, uint8_t reg)
Stefan Reinauer4885daa2011-04-26 23:47:04 +000051{
Kyösti Mälkki8517f942015-03-12 11:33:14 +020052 return read8(base + reg);
Stefan Reinauer4885daa2011-04-26 23:47:04 +000053}
54
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +020055static void uart8250_write(void *base, uint8_t reg, uint8_t data)
56{
Kyösti Mälkki8517f942015-03-12 11:33:14 +020057 write8(base + reg, data);
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +020058}
Naveen Krishna Chatradhia73408d2015-07-08 14:23:06 +053059#endif
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +020060
61static int uart8250_mem_can_tx_byte(void *base)
62{
63 return uart8250_read(base, UART8250_LSR) & UART8250_LSR_THRE;
64}
65
66static void uart8250_mem_tx_byte(void *base, unsigned char data)
Stefan Reinauer4885daa2011-04-26 23:47:04 +000067{
Stefan Reinauer47818002012-03-30 16:19:31 -070068 unsigned long int i = SINGLE_CHAR_TIMEOUT;
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +020069 while(i-- && !uart8250_mem_can_tx_byte(base))
Stefan Reinauer47818002012-03-30 16:19:31 -070070 udelay(1);
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +020071 uart8250_write(base, UART8250_TBR, data);
Stefan Reinauer4885daa2011-04-26 23:47:04 +000072}
73
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +020074static void uart8250_mem_tx_flush(void *base)
Stefan Reinauer4885daa2011-04-26 23:47:04 +000075{
Stefan Reinauer47818002012-03-30 16:19:31 -070076 unsigned long int i = FIFO_TIMEOUT;
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +020077 while(i-- && !(uart8250_read(base, UART8250_LSR) & UART8250_LSR_TEMT))
Stefan Reinauer47818002012-03-30 16:19:31 -070078 udelay(1);
Stefan Reinauer4885daa2011-04-26 23:47:04 +000079}
80
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +020081static int uart8250_mem_can_rx_byte(void *base)
Stefan Reinauer4885daa2011-04-26 23:47:04 +000082{
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +020083 return uart8250_read(base, UART8250_LSR) & UART8250_LSR_DR;
Stefan Reinauer4885daa2011-04-26 23:47:04 +000084}
85
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +020086static unsigned char uart8250_mem_rx_byte(void *base)
Stefan Reinauer4885daa2011-04-26 23:47:04 +000087{
Stefan Reinauer47818002012-03-30 16:19:31 -070088 unsigned long int i = SINGLE_CHAR_TIMEOUT;
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +020089 while(i-- && !uart8250_mem_can_rx_byte(base))
Stefan Reinauer47818002012-03-30 16:19:31 -070090 udelay(1);
91 if (i)
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +020092 return uart8250_read(base, UART8250_RBR);
Stefan Reinauer47818002012-03-30 16:19:31 -070093 else
94 return 0x0;
Stefan Reinauer4885daa2011-04-26 23:47:04 +000095}
96
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +020097static void uart8250_mem_init(void *base, unsigned divisor)
Stefan Reinauer4885daa2011-04-26 23:47:04 +000098{
99 /* Disable interrupts */
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +0200100 uart8250_write(base, UART8250_IER, 0x0);
Stefan Reinauer4885daa2011-04-26 23:47:04 +0000101 /* Enable FIFOs */
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +0200102 uart8250_write(base, UART8250_FCR, UART8250_FCR_FIFO_EN);
Stefan Reinauer4885daa2011-04-26 23:47:04 +0000103
104 /* Assert DTR and RTS so the other end is happy */
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +0200105 uart8250_write(base, UART8250_MCR, UART8250_MCR_DTR | UART8250_MCR_RTS);
Stefan Reinauer4885daa2011-04-26 23:47:04 +0000106
107 /* DLAB on */
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +0200108 uart8250_write(base, UART8250_LCR, UART8250_LCR_DLAB | CONFIG_TTYS0_LCS);
Stefan Reinauer4885daa2011-04-26 23:47:04 +0000109
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +0200110 uart8250_write(base, UART8250_DLL, divisor & 0xFF);
111 uart8250_write(base, UART8250_DLM, (divisor >> 8) & 0xFF);
Stefan Reinauer4885daa2011-04-26 23:47:04 +0000112
113 /* Set to 3 for 8N1 */
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +0200114 uart8250_write(base, UART8250_LCR, CONFIG_TTYS0_LCS);
Stefan Reinauer4885daa2011-04-26 23:47:04 +0000115}
116
Kyösti Mälkki70342a72014-03-14 22:28:29 +0200117void uart_init(int idx)
Stefan Reinauer4885daa2011-04-26 23:47:04 +0000118{
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +0200119 void *base = uart_platform_baseptr(idx);
Kyösti Mälkki2b95da02014-02-15 10:19:23 +0200120 if (!base)
121 return;
Stefan Reinauer4885daa2011-04-26 23:47:04 +0000122
Kyösti Mälkki2b95da02014-02-15 10:19:23 +0200123 unsigned int div;
Kyösti Mälkki3ee16682014-02-17 19:37:52 +0200124 div = uart_baudrate_divisor(default_baudrate(), uart_platform_refclk(), 16);
Kyösti Mälkki2b95da02014-02-15 10:19:23 +0200125 uart8250_mem_init(base, div);
126}
Stefan Reinauer4885daa2011-04-26 23:47:04 +0000127
Kyösti Mälkki70342a72014-03-14 22:28:29 +0200128void uart_tx_byte(int idx, unsigned char data)
Kyösti Mälkki2b95da02014-02-15 10:19:23 +0200129{
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +0200130 void *base = uart_platform_baseptr(idx);
Kyösti Mälkki2b95da02014-02-15 10:19:23 +0200131 if (!base)
132 return;
133 uart8250_mem_tx_byte(base, data);
134}
135
Kyösti Mälkki70342a72014-03-14 22:28:29 +0200136unsigned char uart_rx_byte(int idx)
Kyösti Mälkki2b95da02014-02-15 10:19:23 +0200137{
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +0200138 void *base = uart_platform_baseptr(idx);
Kyösti Mälkki2b95da02014-02-15 10:19:23 +0200139 if (!base)
140 return 0xff;
141 return uart8250_mem_rx_byte(base);
142}
143
Kyösti Mälkki70342a72014-03-14 22:28:29 +0200144void uart_tx_flush(int idx)
Kyösti Mälkki2b95da02014-02-15 10:19:23 +0200145{
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +0200146 void *base = uart_platform_baseptr(idx);
Kyösti Mälkki2b95da02014-02-15 10:19:23 +0200147 if (!base)
148 return;
149 uart8250_mem_tx_flush(base);
Stefan Reinauer4885daa2011-04-26 23:47:04 +0000150}
Aaron Durbin4f7cf3a2015-07-30 16:47:18 -0500151
152#if ENV_RAMSTAGE
153void uart_fill_lb(void *data)
154{
155 struct lb_serial serial;
156 serial.type = LB_SERIAL_TYPE_MEMORY_MAPPED;
157 serial.baseaddr = uart_platform_base(CONFIG_UART_FOR_CONSOLE);
158 serial.baud = default_baudrate();
159 if (IS_ENABLED(CONFIG_DRIVERS_UART_8250MEM_32))
160 serial.regwidth = sizeof(uint32_t);
161 else
162 serial.regwidth = sizeof(uint8_t);
163 lb_add_serial(&serial, data);
164
165 lb_add_console(LB_TAG_CONSOLE_SERIAL8250MEM, data);
166}
167#endif