2 * This file is part of the coreboot project.
4 * Copyright (C) 2003 Eric Biederman
5 * Copyright (C) 2006-2010 coresystems GmbH
6 * Copyright (C) 2014 Imagination Technologies
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; version 2 of
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
20 #include <boot/coreboot_tables.h>
21 #include <console/console.h>
22 #include <console/uart.h>
23 #include <device/device.h>
25 #include <drivers/uart/uart8250reg.h>
27 /* Should support 8250, 16450, 16550, 16550A type UARTs */
29 /* 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.
33 #define SINGLE_CHAR_TIMEOUT (50 * 1000)
34 #define FIFO_TIMEOUT (16 * SINGLE_CHAR_TIMEOUT)
37 #define GEN_ACCESSOR(name, idx) \
38 static inline uint8_t read_##name(unsigned base_port) \
40 return read8(base_port + (idx << UART_SHIFT)); \
43 static inline void write_##name(unsigned base_port, uint8_t val) \
45 write8(base_port + (idx << UART_SHIFT), val); \
48 GEN_ACCESSOR(rbr
, UART8250_RBR
)
49 GEN_ACCESSOR(tbr
, UART8250_TBR
)
50 GEN_ACCESSOR(ier
, UART8250_IER
)
51 GEN_ACCESSOR(fcr
, UART8250_FCR
)
52 GEN_ACCESSOR(lcr
, UART8250_LCR
)
53 GEN_ACCESSOR(mcr
, UART8250_MCR
)
54 GEN_ACCESSOR(lsr
, UART8250_LSR
)
55 GEN_ACCESSOR(dll
, UART8250_DLL
)
56 GEN_ACCESSOR(dlm
, UART8250_DLM
)
58 static int uart8250_mem_can_tx_byte(unsigned base_port
)
60 return read_lsr(base_port
) & UART8250_LSR_THRE
;
63 static void uart8250_mem_tx_byte(unsigned base_port
, unsigned char data
)
65 unsigned long int i
= SINGLE_CHAR_TIMEOUT
;
66 while (i
-- && !uart8250_mem_can_tx_byte(base_port
))
68 write_tbr(base_port
, data
);
71 static void uart8250_mem_tx_flush(unsigned base_port
)
73 unsigned long int i
= FIFO_TIMEOUT
;
74 while (i
-- && !(read_lsr(base_port
) & UART8250_LSR_TEMT
))
78 static int uart8250_mem_can_rx_byte(unsigned base_port
)
80 return read_lsr(base_port
) & UART8250_LSR_DR
;
83 static unsigned char uart8250_mem_rx_byte(unsigned base_port
)
85 unsigned long int i
= SINGLE_CHAR_TIMEOUT
;
86 while (i
-- && !uart8250_mem_can_rx_byte(base_port
))
89 return read_rbr(base_port
);
94 static void uart8250_mem_init(unsigned base_port
, unsigned divisor
)
96 /* Disable interrupts */
97 write_ier(base_port
, 0x0);
99 write_fcr(base_port
, UART8250_FCR_FIFO_EN
);
101 /* Assert DTR and RTS so the other end is happy */
102 write_mcr(base_port
, UART8250_MCR_DTR
| UART8250_MCR_RTS
);
105 write_lcr(base_port
, UART8250_LCR_DLAB
| CONFIG_TTYS0_LCS
);
107 write_dll(base_port
, divisor
& 0xFF);
108 write_dlm(base_port
, (divisor
>> 8) & 0xFF);
110 /* Set to 3 for 8N1 */
111 write_lcr(base_port
, CONFIG_TTYS0_LCS
);
114 unsigned int uart_platform_refclk(void)
120 void uart_init(int idx
)
122 u32 base
= CONFIG_CONSOLE_SERIAL_UART_ADDRESS
;
127 div
= uart_baudrate_divisor(get_uart_baudrate(),
128 uart_platform_refclk(), 16);
129 uart8250_mem_init(base
, div
);
132 void uart_tx_byte(int idx
, unsigned char data
)
134 uart8250_mem_tx_byte(CONFIG_CONSOLE_SERIAL_UART_ADDRESS
, data
);
137 unsigned char uart_rx_byte(int idx
)
139 return uart8250_mem_rx_byte(CONFIG_CONSOLE_SERIAL_UART_ADDRESS
);
142 void uart_tx_flush(int idx
)
144 uart8250_mem_tx_flush(CONFIG_CONSOLE_SERIAL_UART_ADDRESS
);
148 void uart_fill_lb(void *data
)
150 struct lb_serial serial
;
151 serial
.type
= LB_SERIAL_TYPE_MEMORY_MAPPED
;
152 serial
.baseaddr
= CONFIG_CONSOLE_SERIAL_UART_ADDRESS
;
153 serial
.baud
= get_uart_baudrate();
154 serial
.regwidth
= 1 << UART_SHIFT
;
155 lb_add_serial(&serial
, data
);
157 lb_add_console(LB_TAG_CONSOLE_SERIAL8250MEM
, data
);