1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2015, Linaro Limited
4 */
5
6 #include <compiler.h>
7 #include <console.h>
8 #include <drivers/serial8250_uart.h>
9 #include <io.h>
10 #include <keep.h>
11 #include <kernel/dt.h>
12 #include <kernel/dt_driver.h>
13 #include <util.h>
14
15 /* uart register defines */
16 #define UART_RHR 0x0
17 #define UART_THR 0x0
18 #define UART_IER 0x4
19 #define UART_ISR 0x8
20 #define UART_FCR 0x8
21 #define UART_LCR 0xc
22 #define UART_MCR 0x10
23 #define UART_LSR 0x14
24 #define UART_MSR 0x18
25 #define UART_SPR 0x1c
26
27 /* uart status register bits */
28 #define LSR_TEMT 0x40 /* Transmitter empty */
29 #define LSR_THRE 0x20 /* Transmit-hold-register empty */
30 #define LSR_EMPTY (LSR_TEMT | LSR_THRE)
31 #define LSR_DR 0x01 /* DATA Ready */
32
chip_to_base(struct serial_chip * chip)33 static vaddr_t chip_to_base(struct serial_chip *chip)
34 {
35 struct serial8250_uart_data *pd =
36 container_of(chip, struct serial8250_uart_data, chip);
37
38 return io_pa_or_va(&pd->base, SERIAL8250_UART_REG_SIZE);
39 }
40
serial8250_uart_flush(struct serial_chip * chip)41 static void serial8250_uart_flush(struct serial_chip *chip)
42 {
43 vaddr_t base = chip_to_base(chip);
44
45 while (1) {
46 uint32_t state = io_read32(base + UART_LSR);
47
48 /* Wait until transmit FIFO is empty */
49 if ((state & LSR_EMPTY) == LSR_EMPTY)
50 break;
51 }
52 }
53
serial8250_uart_have_rx_data(struct serial_chip * chip)54 static bool serial8250_uart_have_rx_data(struct serial_chip *chip)
55 {
56 vaddr_t base = chip_to_base(chip);
57
58 return (io_read32(base + UART_LSR) & LSR_DR);
59 }
60
serial8250_uart_getchar(struct serial_chip * chip)61 static int serial8250_uart_getchar(struct serial_chip *chip)
62 {
63 vaddr_t base = chip_to_base(chip);
64
65 while (!serial8250_uart_have_rx_data(chip)) {
66 /* Transmit FIFO is empty, waiting again */
67 ;
68 }
69 return io_read32(base + UART_RHR) & 0xff;
70 }
71
serial8250_uart_putc(struct serial_chip * chip,int ch)72 static void serial8250_uart_putc(struct serial_chip *chip, int ch)
73 {
74 vaddr_t base = chip_to_base(chip);
75
76 serial8250_uart_flush(chip);
77
78 /* Write out character to transmit FIFO */
79 io_write32(base + UART_THR, ch);
80 }
81
82 static const struct serial_ops serial8250_uart_ops = {
83 .flush = serial8250_uart_flush,
84 .getchar = serial8250_uart_getchar,
85 .have_rx_data = serial8250_uart_have_rx_data,
86 .putc = serial8250_uart_putc,
87 };
88 DECLARE_KEEP_PAGER(serial8250_uart_ops);
89
serial8250_uart_init(struct serial8250_uart_data * pd,paddr_t base,uint32_t __unused uart_clk,uint32_t __unused baud_rate)90 void serial8250_uart_init(struct serial8250_uart_data *pd, paddr_t base,
91 uint32_t __unused uart_clk,
92 uint32_t __unused baud_rate)
93
94 {
95 pd->base.pa = base;
96 pd->chip.ops = &serial8250_uart_ops;
97
98 /*
99 * do nothing, debug uart(uart0) share with normal world,
100 * everything for uart0 is ready now.
101 */
102 }
103
104 #ifdef CFG_DT
105
serial8250_uart_dev_alloc(void)106 static struct serial_chip *serial8250_uart_dev_alloc(void)
107 {
108 struct serial8250_uart_data *pd = calloc(1, sizeof(*pd));
109
110 if (!pd)
111 return NULL;
112 return &pd->chip;
113 }
114
serial8250_uart_dev_init(struct serial_chip * chip,const void * fdt,int offs,const char * parms)115 static int serial8250_uart_dev_init(struct serial_chip *chip,
116 const void *fdt,
117 int offs,
118 const char *parms)
119 {
120 struct serial8250_uart_data *pd =
121 container_of(chip, struct serial8250_uart_data, chip);
122 vaddr_t vbase;
123 paddr_t pbase;
124 size_t size;
125
126 if (parms && parms[0])
127 IMSG("serial8250_uart: device parameters ignored (%s)", parms);
128
129 if (dt_map_dev(fdt, offs, &vbase, &size, DT_MAP_AUTO) < 0)
130 return -1;
131
132 if (size < SERIAL8250_UART_REG_SIZE) {
133 EMSG("serial8250_uart: register size too small: %zx", size);
134 return -1;
135 }
136
137 pbase = virt_to_phys((void *)vbase);
138 serial8250_uart_init(pd, pbase, 0, 0);
139
140 return 0;
141 }
142
serial8250_uart_dev_free(struct serial_chip * chip)143 static void serial8250_uart_dev_free(struct serial_chip *chip)
144 {
145 struct serial8250_uart_data *pd =
146 container_of(chip, struct serial8250_uart_data, chip);
147
148 free(pd);
149 }
150
151 static const struct serial_driver serial8250_driver = {
152 .dev_alloc = serial8250_uart_dev_alloc,
153 .dev_init = serial8250_uart_dev_init,
154 .dev_free = serial8250_uart_dev_free,
155 };
156
157 static const struct dt_device_match serial8250_match_table[] = {
158 { .compatible = "snps,dw-apb-uart" },
159 { 0 }
160 };
161
162 DEFINE_DT_DRIVER(serial8250_dt_driver) = {
163 .name = "serial8250_uart",
164 .type = DT_DRIVER_UART,
165 .match_table = serial8250_match_table,
166 .driver = &serial8250_driver,
167 };
168
169 #endif /* CFG_DT */
170