1 /*
2  * Copyright (C) 2018-2022 Intel Corporation.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <types.h>
8 #include <asm/lib/spinlock.h>
9 #include <pci.h>
10 #include <uart16550.h>
11 #include <asm/io.h>
12 #include <asm/cpu.h>
13 #include <asm/mmu.h>
14 
15 #define MAX_BDF_LEN 8
16 
17 struct console_uart {
18 	bool enabled;
19 
20 	enum serial_dev_type type;
21 	uint16_t port_address;
22 	void *mmio_base_vaddr;
23 	union pci_bdf bdf;
24 
25 	spinlock_t rx_lock;
26 	spinlock_t tx_lock;
27 
28 	uint32_t reg_width;
29 };
30 
31 #if defined(CONFIG_SERIAL_PIO_BASE)
32 static struct console_uart uart = {
33 	.enabled = true,
34 	.type = PIO,
35 	.port_address = CONFIG_SERIAL_PIO_BASE,
36 	.reg_width = 1,
37 };
38 #elif defined(CONFIG_SERIAL_PCI_BDF)
39 static struct console_uart uart = {
40 	.enabled = true,
41 	.type = PCI,
42 	.bdf.value = CONFIG_SERIAL_PCI_BDF,
43 	.reg_width = 4,
44 };
45 #elif defined(CONFIG_SERIAL_MMIO_BASE)
46 static struct console_uart uart = {
47 	.enabled = true,
48 	.type = MMIO,
49 	.mmio_base_vaddr = (void *)CONFIG_SERIAL_MMIO_BASE,
50 	.reg_width = 1,
51 };
52 #endif
53 
54 typedef uint32_t uart_reg_t;
55 
56 /**
57  * @pre uart->enabled == true
58  */
uart16550_read_reg(struct console_uart uart,uint16_t reg_idx)59 static inline uint32_t uart16550_read_reg(struct console_uart uart, uint16_t reg_idx)
60 {
61 	if (uart.type == PIO) {
62 		return pio_read8(uart.port_address + (reg_idx * uart.reg_width));
63 	} else {
64 		if (uart.reg_width == 4U) {
65 			return mmio_read32(uart.mmio_base_vaddr + (reg_idx * uart.reg_width));
66 		} else {
67 			return mmio_read8(uart.mmio_base_vaddr + (reg_idx * uart.reg_width));
68 		}
69 	}
70 }
71 
72 /**
73  * @pre uart->enabled == true
74  */
uart16550_write_reg(struct console_uart uart,uint32_t val,uint16_t reg_idx)75 static inline void uart16550_write_reg(struct console_uart uart, uint32_t val, uint16_t reg_idx)
76 {
77 	if (uart.type == PIO) {
78 		pio_write8(val, uart.port_address + (reg_idx * uart.reg_width));
79 	} else {
80 		if (uart.reg_width == 4U) {
81 			mmio_write32(val, uart.mmio_base_vaddr + (reg_idx * uart.reg_width));
82 		} else {
83 			mmio_write8(val, uart.mmio_base_vaddr + (reg_idx * uart.reg_width));
84 		}
85 	}
86 }
87 
uart16550_calc_baud_div(uint32_t ref_freq,uint32_t * baud_div_ptr,uint32_t baud_rate_arg)88 static void uart16550_calc_baud_div(uint32_t ref_freq, uint32_t *baud_div_ptr, uint32_t baud_rate_arg)
89 {
90 	uint32_t baud_rate = baud_rate_arg;
91 	uint32_t baud_multiplier = baud_rate < BAUD_460800 ? 16U : 13U;
92 
93 	if (baud_rate == 0U) {
94 		baud_rate = BAUD_115200;
95 	}
96 	*baud_div_ptr = ref_freq / (baud_multiplier * baud_rate);
97 }
98 
99 /**
100  * @pre uart->enabled == true
101  */
uart16550_set_baud_rate(uint32_t baud_rate)102 static void uart16550_set_baud_rate(uint32_t baud_rate)
103 {
104 	uint32_t baud_div, duart_clock = UART_CLOCK_RATE;
105 	uart_reg_t temp_reg;
106 
107 	/* Calculate baud divisor */
108 	uart16550_calc_baud_div(duart_clock, &baud_div, baud_rate);
109 
110 	/* Enable DLL and DLM registers for setting the Divisor */
111 	temp_reg = uart16550_read_reg(uart, UART16550_LCR);
112 	temp_reg |= LCR_DLAB;
113 	uart16550_write_reg(uart, temp_reg, UART16550_LCR);
114 
115 	/* Write the appropriate divisor value */
116 	uart16550_write_reg(uart, ((baud_div >> 8U) & 0xFFU), UART16550_DLM);
117 	uart16550_write_reg(uart, (baud_div & 0xFFU), UART16550_DLL);
118 
119 	/* Disable DLL and DLM registers */
120 	temp_reg &= ~LCR_DLAB;
121 	uart16550_write_reg(uart, temp_reg, UART16550_LCR);
122 }
123 
124 static uint8_t uart_pde_page[PAGE_SIZE]__aligned(PAGE_SIZE);
125 static uint8_t uart_pdpte_page[PAGE_SIZE]__aligned(PAGE_SIZE);
126 
early_pgtable_map_uart(uint64_t addr)127 static void early_pgtable_map_uart(uint64_t addr)
128 {
129 	uint64_t *pml4e, *pdpte, *pde;
130 	uint64_t value;
131 
132 	CPU_CR_READ(cr3, &value);
133 	/*assumpiton for map high mmio in early pagetable is that it is only used for
134 	  2MB page since 1G page may not available when memory width is 39bit */
135 	pml4e = pml4e_offset((uint64_t *)value, addr);
136 	/* address is above 512G */
137 	if(!(*pml4e & PAGE_PRESENT)) {
138 		*pml4e = hva2hpa_early(uart_pdpte_page) + (PAGE_PRESENT|PAGE_RW);
139 	}
140 	pdpte = pdpte_offset(pml4e, addr);
141 	if(!(*pdpte & PAGE_PRESENT)) {
142 		*(pdpte) = hva2hpa_early(uart_pde_page) + (PAGE_PRESENT|PAGE_RW);
143 		pde = pde_offset(pdpte, addr);
144 		*pde =  (addr & PDE_MASK) + (PAGE_PRESENT|PAGE_RW|PAGE_PSE);
145 	} else if(!(*pdpte & PAGE_PSE)) {
146 		pde = pde_offset(pdpte, addr);
147 		if(!(*pde & PAGE_PRESENT)) {
148 			*pde = (addr & PDE_MASK) + (PAGE_PRESENT|PAGE_RW|PAGE_PSE);
149 		}
150 	}
151 }
152 
uart16550_init(bool early_boot)153 void uart16550_init(bool early_boot)
154 {
155 	void *mmio_base_va = NULL;
156 
157 	if (!uart.enabled) {
158 		return;
159 	}
160 
161 	if (!early_boot) {
162 		if (uart.type == MMIO) {
163 			mmio_base_va = hpa2hva(hva2hpa_early(uart.mmio_base_vaddr));
164 			if (mmio_base_va != NULL) {
165 				set_paging_supervisor((uint64_t)mmio_base_va, PDE_SIZE);
166 			}
167 		}
168 		return;
169 	}
170 
171 	/* if configure serial PCI BDF, get its base MMIO address */
172 	if (uart.type == PCI) {
173 		uint32_t bar0 = pci_pdev_read_cfg(uart.bdf, pci_bar_offset(0), 4U);
174 
175 		if ((bar0 & ~0xfU) == 0U) {
176 			/* in case the PCI UART BAR is reset to 0 after boot */
177 			uart.enabled = false;
178 			return;
179 		} else {
180 			uint16_t cmd = (uint16_t)pci_pdev_read_cfg(uart.bdf, PCIR_COMMAND, 2U);
181 			if ((bar0 & 0x3U) == PCIM_BAR_IO_SPACE) { /* IO Space */
182 				uart.type = PIO;
183 				uart.port_address = (uint16_t)(bar0 & PCI_BASE_ADDRESS_IO_MASK);
184 				uart.reg_width = 1;
185 				pci_pdev_write_cfg(uart.bdf, PCIR_COMMAND, 2U, cmd | PCIM_CMD_PORTEN);
186 			} else if (((bar0 & 0x7U) == 0U) || ((bar0 & 0x7U) == 4U)) {
187 					uart.type = MMIO;
188 					uint32_t bar_hi = pci_pdev_read_cfg(uart.bdf, pci_bar_offset(1), 4U);
189 					uint64_t addr = (bar0 & PCI_BASE_ADDRESS_MEM_MASK)|(((uint64_t)bar_hi) << 32U);
190 					if (bar_hi != 0U) {
191 						early_pgtable_map_uart(addr);
192 					}
193 					uart.mmio_base_vaddr = hpa2hva_early(addr);
194 					pci_pdev_write_cfg(uart.bdf, PCIR_COMMAND, 2U, cmd | PCIM_CMD_MEMEN);
195 			} else {
196 				uart.enabled = false;
197 				return;
198 			}
199 		}
200 	}
201 
202 	spinlock_init(&uart.rx_lock);
203 	spinlock_init(&uart.tx_lock);
204 
205 	/* Enable TX and RX FIFOs */
206 	uart16550_write_reg(uart, FCR_FIFOE | FCR_RFR | FCR_TFR, UART16550_FCR);
207 
208 	/* Set-up data bits / parity / stop bits. */
209 	uart16550_write_reg(uart, (LCR_WL8 | LCR_NB_STOP_BITS_1 | LCR_PARITY_NONE), UART16550_LCR);
210 
211 	/* Disable interrupts (we use polling) */
212 	uart16550_write_reg(uart, UART_IER_DISABLE_ALL, UART16550_IER);
213 
214 	/* Set baud rate */
215 	uart16550_set_baud_rate(BAUD_115200);
216 
217 	/* Data terminal ready + Request to send */
218 	uart16550_write_reg(uart, MCR_RTS | MCR_DTR, UART16550_MCR);
219 }
220 
uart16550_getc(void)221 char uart16550_getc(void)
222 {
223 	char ret = -1;
224 	uint64_t rflags;
225 
226 	if (!uart.enabled) {
227 		return ret;
228 	}
229 
230 	spinlock_irqsave_obtain(&uart.rx_lock, &rflags);
231 	/* If a character has been received, read it */
232 	if ((uart16550_read_reg(uart, UART16550_LSR) & LSR_DR) == LSR_DR) {
233 		/* Read a character */
234 		ret = uart16550_read_reg(uart, UART16550_RBR);
235 
236 	}
237 	spinlock_irqrestore_release(&uart.rx_lock, rflags);
238 	return ret;
239 }
240 
241 /**
242  * @pre uart->enabled == true
243  */
uart16550_putc(char c)244 static void uart16550_putc(char c)
245 {
246 	uint8_t temp;
247 	uint32_t reg;
248 
249 	/* Ensure there are no further Transmit buffer write requests */
250 	do {
251 		reg = uart16550_read_reg(uart, UART16550_LSR);
252 	} while ((reg & LSR_THRE) == 0U || (reg & LSR_TEMT) == 0U);
253 
254 	temp = (uint8_t)c;
255 	/* Transmit the character. */
256 	uart16550_write_reg(uart, (uint32_t)temp, UART16550_THR);
257 }
258 
uart16550_puts(const char * buf,uint32_t len)259 size_t uart16550_puts(const char *buf, uint32_t len)
260 {
261 	uint32_t i;
262 	uint64_t rflags;
263 
264 	if (!uart.enabled) {
265 		return len;
266 	}
267 
268 	spinlock_irqsave_obtain(&uart.tx_lock, &rflags);
269 	for (i = 0U; i < len; i++) {
270 		/* Transmit character */
271 		uart16550_putc(*buf);
272 		if (*buf == '\n') {
273 			/* Append '\r', no need change the len */
274 			uart16550_putc('\r');
275 		}
276 		buf++;
277 	}
278 	spinlock_irqrestore_release(&uart.tx_lock, rflags);
279 	return len;
280 }
281 
uart16550_set_property(bool enabled,enum serial_dev_type uart_type,uint64_t data)282 void uart16550_set_property(bool enabled, enum serial_dev_type uart_type, uint64_t data)
283 {
284 	uart.enabled = enabled;
285 	uart.type = uart_type;
286 	uart.bdf.value = 0U;
287 
288 	if (uart_type == PIO) {
289 		uart.port_address = data;
290 	} else if (uart_type == PCI) {
291 		uart.bdf.value = data;
292 		uart.reg_width = 4;
293 	} else if (uart_type == MMIO) {
294 		uart.mmio_base_vaddr = (void *)data;
295 		uart.reg_width = 1;
296 	}
297 }
298 
is_pci_dbg_uart(union pci_bdf bdf_value)299 bool is_pci_dbg_uart(union pci_bdf bdf_value)
300 {
301 	bool ret = false;
302 
303 	if (uart.enabled && (uart.bdf.value != 0)) {
304 		if (bdf_value.value == uart.bdf.value) {
305 			ret = true;
306 		}
307 	}
308 
309 	return ret;
310 }
311 
get_pio_dbg_uart_cfg(uint16_t * pio_address,uint32_t * nbytes)312 bool get_pio_dbg_uart_cfg(uint16_t *pio_address, uint32_t *nbytes)
313 {
314 	bool ret = false;
315 
316 	if (uart.enabled && (uart.type == PIO)) {
317 		*pio_address = uart.port_address;
318 		*nbytes = 8U;
319 		ret = true;
320 	}
321 
322 	return ret;
323 }
324