blob: 3c0286785ad55104fff82002a413364e3ac0f8a1 [file] [log] [blame]
Alexandru Gagniucf64111b2013-12-13 20:44:48 -06001/*
2 * Uart setup helpers for Allwinner SoCs
3 *
4 * Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
5 * Subject to the GNU GPL v2, or (at your option) any later version.
6 */
7
8#include "uart.h"
9#include <arch/io.h>
Kyösti Mälkki1d7541f2014-02-17 21:34:42 +020010#include <console/uart.h>
Kyösti Mälkkibea6bf02014-01-30 15:45:16 +020011#include <drivers/uart/uart8250reg.h>
Alexandru Gagniucf64111b2013-12-13 20:44:48 -060012
13/**
14 * \brief Configure line control settings for UART
15 */
Kyösti Mälkki28837c62014-04-04 20:32:59 +030016static void a10_uart_configure(struct a10_uart *uart, u32 baud_rate, u8 data_bits,
Alexandru Gagniucf64111b2013-12-13 20:44:48 -060017 enum uart_parity parity, u8 stop_bits)
18{
19 u32 reg32;
20 u16 div;
Alexandru Gagniucf64111b2013-12-13 20:44:48 -060021
Kyösti Mälkki65ba20e2014-02-19 08:58:12 +020022 div = (u16) uart_baudrate_divisor(baud_rate,
23 uart_platform_refclk(), 16);
Alexandru Gagniucf64111b2013-12-13 20:44:48 -060024 /* Enable access to Divisor Latch register */
Julius Werner2f37bd62015-02-19 14:51:15 -080025 write32(&uart->lcr, UART8250_LCR_DLAB);
Alexandru Gagniucf64111b2013-12-13 20:44:48 -060026 /* Set baudrate */
Julius Werner2f37bd62015-02-19 14:51:15 -080027 write32(&uart->dlh, (div >> 8) & 0xff);
28 write32(&uart->dll, div & 0xff);
Alexandru Gagniucf64111b2013-12-13 20:44:48 -060029 /* Set line control */
Gabe Black77ffa0d2013-09-30 21:25:49 -070030 reg32 = (data_bits - 5) & UART8250_LCR_WLS_MSK;
Alexandru Gagniucf64111b2013-12-13 20:44:48 -060031 switch (parity) {
32 case UART_PARITY_ODD:
Gabe Black77ffa0d2013-09-30 21:25:49 -070033 reg32 |= UART8250_LCR_PEN;
Alexandru Gagniucf64111b2013-12-13 20:44:48 -060034 break;
35 case UART_PARITY_EVEN:
Gabe Black77ffa0d2013-09-30 21:25:49 -070036 reg32 |= UART8250_LCR_PEN;
37 reg32 |= UART8250_LCR_EPS;
Alexandru Gagniucf64111b2013-12-13 20:44:48 -060038 break;
39 case UART_PARITY_NONE: /* Fall through */
40 default:
41 break;
42 }
Julius Werner2f37bd62015-02-19 14:51:15 -080043 write32(&uart->lcr, reg32);
Alexandru Gagniucf64111b2013-12-13 20:44:48 -060044}
45
Kyösti Mälkki28837c62014-04-04 20:32:59 +030046static void a10_uart_enable_fifos(struct a10_uart *uart)
Alexandru Gagniucf64111b2013-12-13 20:44:48 -060047{
Julius Werner2f37bd62015-02-19 14:51:15 -080048 write32(&uart->fcr, UART8250_FCR_FIFO_EN);
Alexandru Gagniucf64111b2013-12-13 20:44:48 -060049}
50
51static int tx_fifo_full(struct a10_uart *uart)
52{
53 /* This may be a misnomer, or a typo in the datasheet. THRE indicates
54 * that the TX register is empty, not that the FIFO is not full, but
55 * this may be due to a datasheet typo. Keep the current name to signal
56 * intent. */
Gabe Black77ffa0d2013-09-30 21:25:49 -070057 return !(read32(&uart->lsr) & UART8250_LSR_THRE);
Alexandru Gagniucf64111b2013-12-13 20:44:48 -060058}
59
60static int rx_fifo_empty(struct a10_uart *uart)
61{
Gabe Black77ffa0d2013-09-30 21:25:49 -070062 return !(read32(&uart->lsr) & UART8250_LSR_DR);
Alexandru Gagniucf64111b2013-12-13 20:44:48 -060063}
64
65/**
66 * \brief Read a single byte from the UART.
67 *
68 * Blocks until at least a byte is available.
69 */
Kyösti Mälkki28837c62014-04-04 20:32:59 +030070static u8 a10_uart_rx_blocking(struct a10_uart *uart)
Alexandru Gagniucf64111b2013-12-13 20:44:48 -060071{
Alexandru Gagniucf64111b2013-12-13 20:44:48 -060072 while (rx_fifo_empty(uart)) ;
73
74 return read32(&uart->rbr);
75}
76
77/**
78 * \brief Write a single byte to the UART.
79 *
80 * Blocks until there is space in the FIFO.
81 */
Kyösti Mälkki28837c62014-04-04 20:32:59 +030082static void a10_uart_tx_blocking(struct a10_uart *uart, u8 data)
Alexandru Gagniucf64111b2013-12-13 20:44:48 -060083{
Alexandru Gagniucf64111b2013-12-13 20:44:48 -060084 while (tx_fifo_full(uart)) ;
85
Julius Werner2f37bd62015-02-19 14:51:15 -080086 return write32(&uart->thr, data);
Alexandru Gagniucf64111b2013-12-13 20:44:48 -060087}
Kyösti Mälkki28837c62014-04-04 20:32:59 +030088
89
90void uart_init(int idx)
91{
92 struct a10_uart *uart_base = uart_platform_baseptr(idx);
93
94 /* Use default 8N1 encoding */
95 a10_uart_configure(uart_base, default_baudrate(),
96 8, UART_PARITY_NONE, 1);
97 a10_uart_enable_fifos(uart_base);
98}
99
100unsigned char uart_rx_byte(int idx)
101{
102 return a10_uart_rx_blocking(uart_platform_baseptr(idx));
103}
104
105void uart_tx_byte(int idx, unsigned char data)
106{
107 a10_uart_tx_blocking(uart_platform_baseptr(idx), data);
108}
109
110void uart_tx_flush(int idx)
111{
112}