blob: 278ddb8ebb5616f0c4d0d54a6786edb2a782c8fe [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;
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +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;
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +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;
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +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;
Kyösti Mälkki3ee16682014-02-17 19:37:52 +0200120 div = uart_baudrate_divisor(default_baudrate(), uart_platform_refclk(), 16);
Kyösti Mälkki2b95da02014-02-15 10:19:23 +0200121 uart8250_mem_init(base, div);
122}
Stefan Reinauer4885daa2011-04-26 23:47:04 +0000123
Kyösti Mälkki70342a72014-03-14 22:28:29 +0200124void uart_tx_byte(int idx, unsigned char data)
Kyösti Mälkki2b95da02014-02-15 10:19:23 +0200125{
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +0200126 void *base = uart_platform_baseptr(idx);
Kyösti Mälkki2b95da02014-02-15 10:19:23 +0200127 if (!base)
128 return;
129 uart8250_mem_tx_byte(base, data);
130}
131
Kyösti Mälkki70342a72014-03-14 22:28:29 +0200132unsigned char uart_rx_byte(int idx)
Kyösti Mälkki2b95da02014-02-15 10:19:23 +0200133{
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +0200134 void *base = uart_platform_baseptr(idx);
Kyösti Mälkki2b95da02014-02-15 10:19:23 +0200135 if (!base)
136 return 0xff;
137 return uart8250_mem_rx_byte(base);
138}
139
Kyösti Mälkki70342a72014-03-14 22:28:29 +0200140void uart_tx_flush(int idx)
Kyösti Mälkki2b95da02014-02-15 10:19:23 +0200141{
Kyösti Mälkki164ac0a2014-12-13 16:39:40 +0200142 void *base = uart_platform_baseptr(idx);
Kyösti Mälkki2b95da02014-02-15 10:19:23 +0200143 if (!base)
144 return;
145 uart8250_mem_tx_flush(base);
Stefan Reinauer4885daa2011-04-26 23:47:04 +0000146}
Aaron Durbin4f7cf3a2015-07-30 16:47:18 -0500147
148#if ENV_RAMSTAGE
149void uart_fill_lb(void *data)
150{
151 struct lb_serial serial;
152 serial.type = LB_SERIAL_TYPE_MEMORY_MAPPED;
153 serial.baseaddr = uart_platform_base(CONFIG_UART_FOR_CONSOLE);
154 serial.baud = default_baudrate();
155 if (IS_ENABLED(CONFIG_DRIVERS_UART_8250MEM_32))
156 serial.regwidth = sizeof(uint32_t);
157 else
158 serial.regwidth = sizeof(uint8_t);
159 lb_add_serial(&serial, data);
160
161 lb_add_console(LB_TAG_CONSOLE_SERIAL8250MEM, data);
162}
163#endif