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