blob: 4e53a92a4675b77944695e425f1d166a6cb9a0ae [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.
Stefan Reinauer4885daa2011-04-26 23:47:04 +000015 */
16
17#include <arch/io.h>
Aaron Durbin4f7cf3a2015-07-30 16:47:18 -050018#include <boot/coreboot_tables.h>
Kyösti Mälkki1d7541f2014-02-17 21:34:42 +020019#include <console/uart.h>
Stefan Reinauer4885daa2011-04-26 23:47:04 +000020#include <device/device.h>
Stefan Reinauer47818002012-03-30 16:19:31 -070021#include <delay.h>
Aaron Durbin4f7cf3a2015-07-30 16:47:18 -050022#include <rules.h>
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +020023#include <stdint.h>
Kyösti Mälkkibea6bf02014-01-30 15:45:16 +020024#include "uart8250reg.h"
Stefan Reinauer4885daa2011-04-26 23:47:04 +000025
26/* Should support 8250, 16450, 16550, 16550A type UARTs */
27
Stefan Reinauer47818002012-03-30 16:19:31 -070028/* Expected character delay at 1200bps is 9ms for a working UART
29 * and no flow-control. Assume UART as stuck if shift register
30 * or FIFO takes more than 50ms per character to appear empty.
31 */
32#define SINGLE_CHAR_TIMEOUT (50 * 1000)
33#define FIFO_TIMEOUT (16 * SINGLE_CHAR_TIMEOUT)
34
Naveen Krishna Chatradhia73408d2015-07-08 14:23:06 +053035#if IS_ENABLED(CONFIG_DRIVERS_UART_8250MEM_32)
36static uint8_t uart8250_read(void *base, uint8_t reg)
37{
38 return read32(base + 4 * reg) & 0xff;
39}
40
41static void uart8250_write(void *base, uint8_t reg, uint8_t data)
42{
43 write32(base + 4 * reg, data);
44}
45#else
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +020046static uint8_t uart8250_read(void *base, uint8_t reg)
Stefan Reinauer4885daa2011-04-26 23:47:04 +000047{
Kyösti Mälkki8517f942015-03-12 11:33:14 +020048 return read8(base + reg);
Stefan Reinauer4885daa2011-04-26 23:47:04 +000049}
50
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +020051static void uart8250_write(void *base, uint8_t reg, uint8_t data)
52{
Kyösti Mälkki8517f942015-03-12 11:33:14 +020053 write8(base + reg, data);
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +020054}
Naveen Krishna Chatradhia73408d2015-07-08 14:23:06 +053055#endif
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +020056
57static int uart8250_mem_can_tx_byte(void *base)
58{
59 return uart8250_read(base, UART8250_LSR) & UART8250_LSR_THRE;
60}
61
62static void uart8250_mem_tx_byte(void *base, unsigned char data)
Stefan Reinauer4885daa2011-04-26 23:47:04 +000063{
Stefan Reinauer47818002012-03-30 16:19:31 -070064 unsigned long int i = SINGLE_CHAR_TIMEOUT;
Elyes HAOUAS2e4d8062016-08-25 20:50:50 +020065 while (i-- && !uart8250_mem_can_tx_byte(base))
Stefan Reinauer47818002012-03-30 16:19:31 -070066 udelay(1);
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +020067 uart8250_write(base, UART8250_TBR, data);
Stefan Reinauer4885daa2011-04-26 23:47:04 +000068}
69
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +020070static void uart8250_mem_tx_flush(void *base)
Stefan Reinauer4885daa2011-04-26 23:47:04 +000071{
Stefan Reinauer47818002012-03-30 16:19:31 -070072 unsigned long int i = FIFO_TIMEOUT;
Elyes HAOUAS2e4d8062016-08-25 20:50:50 +020073 while (i-- && !(uart8250_read(base, UART8250_LSR) & UART8250_LSR_TEMT))
Stefan Reinauer47818002012-03-30 16:19:31 -070074 udelay(1);
Stefan Reinauer4885daa2011-04-26 23:47:04 +000075}
76
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +020077static int uart8250_mem_can_rx_byte(void *base)
Stefan Reinauer4885daa2011-04-26 23:47:04 +000078{
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +020079 return uart8250_read(base, UART8250_LSR) & UART8250_LSR_DR;
Stefan Reinauer4885daa2011-04-26 23:47:04 +000080}
81
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +020082static unsigned char uart8250_mem_rx_byte(void *base)
Stefan Reinauer4885daa2011-04-26 23:47:04 +000083{
Stefan Reinauer47818002012-03-30 16:19:31 -070084 unsigned long int i = SINGLE_CHAR_TIMEOUT;
Elyes HAOUAS2e4d8062016-08-25 20:50:50 +020085 while (i-- && !uart8250_mem_can_rx_byte(base))
Stefan Reinauer47818002012-03-30 16:19:31 -070086 udelay(1);
87 if (i)
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +020088 return uart8250_read(base, UART8250_RBR);
Stefan Reinauer47818002012-03-30 16:19:31 -070089 else
90 return 0x0;
Stefan Reinauer4885daa2011-04-26 23:47:04 +000091}
92
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +020093static void uart8250_mem_init(void *base, unsigned divisor)
Stefan Reinauer4885daa2011-04-26 23:47:04 +000094{
95 /* Disable interrupts */
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +020096 uart8250_write(base, UART8250_IER, 0x0);
Stefan Reinauer4885daa2011-04-26 23:47:04 +000097 /* Enable FIFOs */
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +020098 uart8250_write(base, UART8250_FCR, UART8250_FCR_FIFO_EN);
Stefan Reinauer4885daa2011-04-26 23:47:04 +000099
100 /* Assert DTR and RTS so the other end is happy */
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +0200101 uart8250_write(base, UART8250_MCR, UART8250_MCR_DTR | UART8250_MCR_RTS);
Stefan Reinauer4885daa2011-04-26 23:47:04 +0000102
103 /* DLAB on */
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +0200104 uart8250_write(base, UART8250_LCR, UART8250_LCR_DLAB | CONFIG_TTYS0_LCS);
Stefan Reinauer4885daa2011-04-26 23:47:04 +0000105
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +0200106 uart8250_write(base, UART8250_DLL, divisor & 0xFF);
107 uart8250_write(base, UART8250_DLM, (divisor >> 8) & 0xFF);
Stefan Reinauer4885daa2011-04-26 23:47:04 +0000108
109 /* Set to 3 for 8N1 */
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +0200110 uart8250_write(base, UART8250_LCR, CONFIG_TTYS0_LCS);
Stefan Reinauer4885daa2011-04-26 23:47:04 +0000111}
112
Kyösti Mälkki70342a72014-03-14 22:28:29 +0200113void uart_init(int idx)
Stefan Reinauer4885daa2011-04-26 23:47:04 +0000114{
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +0200115 void *base = uart_platform_baseptr(idx);
Kyösti Mälkki2b95da02014-02-15 10:19:23 +0200116 if (!base)
117 return;
Stefan Reinauer4885daa2011-04-26 23:47:04 +0000118
Kyösti Mälkki2b95da02014-02-15 10:19:23 +0200119 unsigned int div;
Lee Leahy14876212016-05-04 13:13:20 -0700120 div = uart_baudrate_divisor(default_baudrate(),
121 uart_platform_refclk(), uart_input_clock_divider());
Kyösti Mälkki2b95da02014-02-15 10:19:23 +0200122 uart8250_mem_init(base, div);
123}
Stefan Reinauer4885daa2011-04-26 23:47:04 +0000124
Kyösti Mälkki70342a72014-03-14 22:28:29 +0200125void uart_tx_byte(int idx, unsigned char data)
Kyösti Mälkki2b95da02014-02-15 10:19:23 +0200126{
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +0200127 void *base = uart_platform_baseptr(idx);
Kyösti Mälkki2b95da02014-02-15 10:19:23 +0200128 if (!base)
129 return;
130 uart8250_mem_tx_byte(base, data);
131}
132
Kyösti Mälkki70342a72014-03-14 22:28:29 +0200133unsigned char uart_rx_byte(int idx)
Kyösti Mälkki2b95da02014-02-15 10:19:23 +0200134{
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +0200135 void *base = uart_platform_baseptr(idx);
Kyösti Mälkki2b95da02014-02-15 10:19:23 +0200136 if (!base)
137 return 0xff;
138 return uart8250_mem_rx_byte(base);
139}
140
Kyösti Mälkki70342a72014-03-14 22:28:29 +0200141void uart_tx_flush(int idx)
Kyösti Mälkki2b95da02014-02-15 10:19:23 +0200142{
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +0200143 void *base = uart_platform_baseptr(idx);
Kyösti Mälkki2b95da02014-02-15 10:19:23 +0200144 if (!base)
145 return;
146 uart8250_mem_tx_flush(base);
Stefan Reinauer4885daa2011-04-26 23:47:04 +0000147}
Aaron Durbin4f7cf3a2015-07-30 16:47:18 -0500148
149#if ENV_RAMSTAGE
150void uart_fill_lb(void *data)
151{
152 struct lb_serial serial;
153 serial.type = LB_SERIAL_TYPE_MEMORY_MAPPED;
154 serial.baseaddr = uart_platform_base(CONFIG_UART_FOR_CONSOLE);
155 serial.baud = default_baudrate();
156 if (IS_ENABLED(CONFIG_DRIVERS_UART_8250MEM_32))
157 serial.regwidth = sizeof(uint32_t);
158 else
159 serial.regwidth = sizeof(uint8_t);
Lee Leahy6ec72c92016-05-07 09:04:46 -0700160 serial.input_hertz = uart_platform_refclk();
Lee Leahyf92a98c2016-05-04 11:59:19 -0700161 serial.uart_pci_addr = CONFIG_UART_PCI_ADDR;
Aaron Durbin4f7cf3a2015-07-30 16:47:18 -0500162 lb_add_serial(&serial, data);
163
164 lb_add_console(LB_TAG_CONSOLE_SERIAL8250MEM, data);
165}
166#endif