blob: ef03c04f232301d972fa42b06b12e6d91e15cb85 [file] [log] [blame]
Angel Pons1ddb8942020-04-04 18:51:26 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -08002
Kyösti Mälkki13f66502019-03-03 08:01:05 +02003#include <device/mmio.h>
Kyösti Mälkkibbf6f3d2014-03-15 01:32:55 +02004#include <boot/coreboot_tables.h>
Julius Werner1ed0c8c2014-10-20 13:16:29 -07005#include <console/uart.h>
6#include <soc/clk.h>
7#include <soc/cpu.h>
8#include <soc/periph.h>
9#include <soc/uart.h>
10#include <types.h>
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080011
12#define RX_FIFO_COUNT_MASK 0xff
13#define RX_FIFO_FULL_MASK (1 << 8)
14#define TX_FIFO_FULL_MASK (1 << 24)
15
Kyösti Mälkkic2610a42014-02-24 20:51:30 +020016static void serial_setbrg_dev(struct s5p_uart *uart)
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080017{
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080018 u32 uclk;
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080019 u32 val;
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080020
Stefan Reinauer08dc3572013-05-14 16:57:50 -070021 // All UARTs share the same clock.
22 uclk = clock_get_periph_rate(PERIPH_ID_UART3);
Julien Viard de Galbert235daa42018-02-20 11:45:48 +010023 val = uclk / get_uart_baudrate();
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080024
Julius Werner2f37bd62015-02-19 14:51:15 -080025 write32(&uart->ubrdiv, val / 16 - 1);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080026}
27
28/*
29 * Initialise the serial port with the given baudrate. The settings
30 * are always 8 data bits, no parity, 1 stop bit, no start bits.
31 */
Kyösti Mälkkic2610a42014-02-24 20:51:30 +020032static void exynos5_init_dev(struct s5p_uart *uart)
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080033{
Hung-Te Lin31bb2df2013-02-07 19:30:40 +080034 // TODO initialize with correct peripheral id by base_port.
Gabe Blackfe640602013-06-15 20:33:05 -070035 exynos_pinmux_uart3();
Hung-Te Lin31bb2df2013-02-07 19:30:40 +080036
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080037 /* enable FIFOs */
Julius Werner2f37bd62015-02-19 14:51:15 -080038 write32(&uart->ufcon, 0x1);
39 write32(&uart->umcon, 0);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080040 /* 8N1 */
Julius Werner2f37bd62015-02-19 14:51:15 -080041 write32(&uart->ulcon, 0x3);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080042 /* No interrupts, no DMA, pure polling */
Julius Werner2f37bd62015-02-19 14:51:15 -080043 write32(&uart->ucon, 0x245);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080044
Kyösti Mälkkic2610a42014-02-24 20:51:30 +020045 serial_setbrg_dev(uart);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080046}
47
Kyösti Mälkkic2610a42014-02-24 20:51:30 +020048static int exynos5_uart_err_check(struct s5p_uart *uart, int op)
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080049{
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080050 unsigned int mask;
51
52 /*
53 * UERSTAT
54 * Break Detect [3]
55 * Frame Err [2] : receive operation
56 * Parity Err [1] : receive operation
57 * Overrun Err [0] : receive operation
58 */
59 if (op)
60 mask = 0x8;
61 else
62 mask = 0xf;
63
Julius Werner2f37bd62015-02-19 14:51:15 -080064 return read32(&uart->uerstat) & mask;
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080065}
66
67/*
68 * Read a single byte from the serial port. Returns 1 on success, 0
Martin Roth4c3ab732013-07-08 16:23:54 -060069 * otherwise. When the function is successful, the character read is
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080070 * written into its argument c.
71 */
Kyösti Mälkkic2610a42014-02-24 20:51:30 +020072static unsigned char exynos5_uart_rx_byte(struct s5p_uart *uart)
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080073{
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080074 /* wait for character to arrive */
Julius Werner2f37bd62015-02-19 14:51:15 -080075 while (!(read32(&uart->ufstat) & (RX_FIFO_COUNT_MASK |
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080076 RX_FIFO_FULL_MASK))) {
Kyösti Mälkkic2610a42014-02-24 20:51:30 +020077 if (exynos5_uart_err_check(uart, 0))
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080078 return 0;
79 }
80
Julius Werner2f37bd62015-02-19 14:51:15 -080081 return read8(&uart->urxh) & 0xff;
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080082}
83
84/*
85 * Output a single byte to the serial port.
86 */
Kyösti Mälkkic2610a42014-02-24 20:51:30 +020087static void exynos5_uart_tx_byte(struct s5p_uart *uart, unsigned char data)
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080088{
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080089 /* wait for room in the tx FIFO */
Julius Werner2f37bd62015-02-19 14:51:15 -080090 while ((read32(&uart->ufstat) & TX_FIFO_FULL_MASK)) {
Kyösti Mälkkic2610a42014-02-24 20:51:30 +020091 if (exynos5_uart_err_check(uart, 1))
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080092 return;
93 }
94
Julius Werner2f37bd62015-02-19 14:51:15 -080095 write8(&uart->utxh, data);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -080096}
97
Kyösti Mälkkic2610a42014-02-24 20:51:30 +020098static void exynos5_uart_tx_flush(struct s5p_uart *uart)
Hung-Te Lin7dd58142013-06-05 14:06:55 -070099{
Julius Werner2f37bd62015-02-19 14:51:15 -0800100 while (read32(&uart->ufstat) & 0x1ff0000);
Hung-Te Lin7dd58142013-06-05 14:06:55 -0700101}
102
Felix Helde3a12472020-09-11 15:47:09 +0200103uintptr_t uart_platform_base(unsigned int idx)
Kyösti Mälkkic2610a42014-02-24 20:51:30 +0200104{
Kyösti Mälkki70342a72014-03-14 22:28:29 +0200105 if (idx < 4)
106 return 0x12c00000 + idx * 0x10000;
107 else
108 return 0;
Kyösti Mälkkic2610a42014-02-24 20:51:30 +0200109}
110
Felix Helde3a12472020-09-11 15:47:09 +0200111void uart_init(unsigned int idx)
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800112{
Kyösti Mälkki70342a72014-03-14 22:28:29 +0200113 struct s5p_uart *uart = uart_platform_baseptr(idx);
Kyösti Mälkkic2610a42014-02-24 20:51:30 +0200114 exynos5_init_dev(uart);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800115}
116
Felix Helde3a12472020-09-11 15:47:09 +0200117unsigned char uart_rx_byte(unsigned int idx)
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800118{
Kyösti Mälkki70342a72014-03-14 22:28:29 +0200119 struct s5p_uart *uart = uart_platform_baseptr(idx);
Kyösti Mälkkic2610a42014-02-24 20:51:30 +0200120 return exynos5_uart_rx_byte(uart);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800121}
122
Felix Helde3a12472020-09-11 15:47:09 +0200123void uart_tx_byte(unsigned int idx, unsigned char data)
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800124{
Kyösti Mälkki70342a72014-03-14 22:28:29 +0200125 struct s5p_uart *uart = uart_platform_baseptr(idx);
Kyösti Mälkkic2610a42014-02-24 20:51:30 +0200126 exynos5_uart_tx_byte(uart, data);
Stefan Reinauer9fe20cb2012-12-07 17:18:43 -0800127}
Hung-Te Lin5f83f6c2013-02-04 14:38:03 +0800128
Felix Helde3a12472020-09-11 15:47:09 +0200129void uart_tx_flush(unsigned int idx)
Stefan Reinauer08dc3572013-05-14 16:57:50 -0700130{
Kyösti Mälkki70342a72014-03-14 22:28:29 +0200131 struct s5p_uart *uart = uart_platform_baseptr(idx);
Kyösti Mälkkic2610a42014-02-24 20:51:30 +0200132 exynos5_uart_tx_flush(uart);
Hung-Te Lin5f83f6c2013-02-04 14:38:03 +0800133}
Kyösti Mälkkibbf6f3d2014-03-15 01:32:55 +0200134
Kyösti Mälkkibbf6f3d2014-03-15 01:32:55 +0200135void uart_fill_lb(void *data)
136{
137 struct lb_serial serial;
138 serial.type = LB_SERIAL_TYPE_MEMORY_MAPPED;
Kyösti Mälkki70342a72014-03-14 22:28:29 +0200139 serial.baseaddr = uart_platform_base(CONFIG_UART_FOR_CONSOLE);
Julien Viard de Galbert235daa42018-02-20 11:45:48 +0100140 serial.baud = get_uart_baudrate();
Patrick Georgia7cac0c2016-02-19 17:33:26 +0100141 serial.regwidth = 4;
Jacob Garber78398272019-07-24 11:12:09 -0600142 serial.input_hertz = uart_platform_refclk();
143 serial.uart_pci_addr = CONFIG_UART_PCI_ADDR;
Kyösti Mälkkibbf6f3d2014-03-15 01:32:55 +0200144 lb_add_serial(&serial, data);
145
146 lb_add_console(LB_TAG_CONSOLE_SERIAL8250MEM, data);
147}