3 * @author Lunaixsky (lunaxisky@qq.com)
4 * @brief 16550 UART with port mapped IO
8 * @copyright Copyright (c) 2023
11 #include <lunaix/device.h>
12 #include <lunaix/generic/isrm.h>
14 #include <sys/port_io.h>
20 static DEFINE_LLIST(com_ports);
23 com_regread(struct uart16550* uart, ptr_t regoff)
25 u8_t val = port_rdbyte(uart->base_addr + regoff);
32 com_regwrite(struct uart16550* uart, ptr_t regoff, u32_t val)
34 port_wrbyte(uart->base_addr + regoff, (u8_t)val);
39 com_irq_handler(const struct hart_state* hstate)
41 int vector = hart_vector_stamp(hstate);
42 uart_general_irq_handler(vector, &com_ports);
46 upiom_init(struct device_def* def)
48 int irq3 = 3, irq4 = 4;
49 u16_t ioports[] = { 0x3F8, 0x2F8, 0x3E8, 0x2E8 };
50 int* irqs[] = { &irq4, &irq3, &irq4, &irq3 };
52 struct uart16550* uart = NULL;
55 for (size_t i = 0; i < 4; i++) {
57 uart = uart_alloc(ioports[i]);
58 uart->read_reg = com_regread;
59 uart->write_reg = com_regwrite;
61 uart->base_addr = ioports[i];
64 if (!uart_testport(uart, 0xe3)) {
71 * Since these irqs are overlapped, this particular setup is needed
72 * to avoid double-bind
74 uart->iv = isrm_bindirq(irq, com_irq_handler);
75 *((volatile int*)irqs[i]) = 0;
78 uart_enable_fifo(uart, UART_FIFO8);
79 llist_append(&com_ports, &uart->local_ports);
81 struct serial_dev* sdev = serial_create(&def->class, "S");
83 sdev->write = uart_general_tx;
84 sdev->exec_cmd = uart_general_exec_cmd;
100 static struct device_def uart_pmio_def = {
101 .class = DEVCLASS(DEVIF_SOC, DEVFN_CHAR, DEV_UART16550),
102 .name = "16550 Generic UART (I/O)",
105 EXPORT_DEVICE(uart16550_pmio, &uart_pmio_def, load_onboot);