From ec1f97d3bec6e7ea7209580bbfa84c748b72b544 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 23 Apr 2023 12:27:46 +0200 Subject: [PATCH] WIP pinephone port --- arch/dev/+aarch64/ns16550.ha | 121 +++++++++++++++++++++++++++++++++++ arch/main/+aarch64/main.ha | 7 ++ efi/mmap.ha | 2 - 3 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 arch/dev/+aarch64/ns16550.ha diff --git a/arch/dev/+aarch64/ns16550.ha b/arch/dev/+aarch64/ns16550.ha new file mode 100644 index 0000000..1e3e12a --- /dev/null +++ b/arch/dev/+aarch64/ns16550.ha @@ -0,0 +1,121 @@ +use arch::mem; +use cons; +use fdt; + +export type ns16550_console = struct { + cons: cons::console, + base: uintptr, + reg_shift: u32, +}; + +def NS16550_RBR: u32 = 0x00; +def NS16550_IER: u32 = 0x01; +def NS16550_FCR: u32 = 0x02; +def NS16550_LCR: u32 = 0x03; +def NS16550_MCR: u32 = 0x04; +def NS16550_LSR: u32 = 0x05; +def NS16550_MSR: u32 = 0x06; +def NS16550_SPR: u32 = 0x07; + +def NS16550_LSR_DR: u8 = 0x01; +def NS16550_LSR_OE: u8 = 0x02; +def NS16550_LSR_PE: u8 = 0x04; +def NS16550_LSR_FE: u8 = 0x08; +def NS16550_LSR_BI: u8 = 0x10; +def NS16550_LSR_THRE: u8 = 0x20; +def NS16550_LSR_TEMT: u8 = 0x40; +def NS16550_LSR_ERR: u8 = 0x80; + +fn ns16550_mmio_read( + cons: *ns16550_console, + reg: u32, +) u8 = { + let reg = (cons.base + (reg << cons.reg_shift): uintptr): *u32; + return *reg: u8; +}; + +fn ns16550_mmio_write( + cons: *ns16550_console, + reg: u32, + val: u8, +) void = { + let reg = (cons.base + (reg << cons.reg_shift): uintptr): *u32; + *reg = val: u32; +}; + +// Initializes a NS16550 UART console with the given MMIO base address. +export fn ns16550_init( + cons: *ns16550_console, + base: uintptr, + reg_shift: u32, +) void = { + cons.cons.write = &ns16550_write; + cons.base = mem::dev_tokernel(base): uintptr; + cons.reg_shift = reg_shift; + + // Mask interrupts + ns16550_mmio_write(cons, NS16550_IER, 0); + ns16550_mmio_write(cons, NS16550_FCR, + 0x1 | // Enable FIFO + 0x2 | // Reset rx + 0x4); // Reset tx +}; + +fn ns16550_putc(cons: *ns16550_console, c: u8) void = { + for (true) { + const lsr = ns16550_mmio_read(cons, NS16550_LSR); + if (lsr & NS16550_LSR_THRE == NS16550_LSR_THRE) { + break; + }; + }; + ns16550_mmio_write(cons, NS16550_RBR, c); +}; + +fn ns16550_write(cons: *cons::console, buf: []u8) size = { + let cons = cons: *ns16550_console; + assert(cons.cons.write == &ns16550_write); + for (let i = 0z; i < len(buf); i += 1) { + if (buf[i] == '\n') { + ns16550_putc(cons, '\r'); + }; + ns16550_putc(cons, buf[i]); + }; + return len(buf); +}; + +// XXX: Could add more but the first one is fine for now +def NS16550_MAX_CONS: size = 1; +let ns16550_consbuf: [NS16550_MAX_CONS]ns16550_console = [ + ns16550_console { ... }... +]; +let ns16550_consoles: []ns16550_console = []; + +fn ns16550_probe(node: *fdt::prober_state) void = { + if (len(ns16550_consoles) >= NS16550_MAX_CONS) { + return; + }; + const (base, _) = fdt::reg(node); + static append(ns16550_consoles, ns16550_console { ... }); + let cons = &ns16550_consoles[len(ns16550_consoles) - 1]; + // TODO: + // - Don't hard-code reg-shift of 2 + // - Support reg-io-width != 4 + ns16550_init(cons, base, 2); + cons::register(cons); +}; + +const ns16550_prober: fdt::probe_compat = fdt::probe_compat { + compat = [ + "ns16550", + "ns16550a", + "nvidia,tegra20-uart", + "snps,dw-apb-uart", + ], + probe = &ns16550_probe, + next = null, +}; + +@init fn ns16550_init() void = { + ns16550_consoles = ns16550_consbuf[..0]; + fdt::register_compat(&ns16550_prober); +}; diff --git a/arch/main/+aarch64/main.ha b/arch/main/+aarch64/main.ha index 4964ad4..36757a9 100644 --- a/arch/main/+aarch64/main.ha +++ b/arch/main/+aarch64/main.ha @@ -68,3 +68,10 @@ fn rpi4_earlycons() void = { log::setcons(&pl011cons); rt::set_abortcons(&log::write); }; + +fn pinephone_earlycons() void = { + static let ns16550cons = dev::ns16550_console { ... }; + dev::ns16550_init(&ns16550cons, 0x1c28000, 2); + log::setcons(&ns16550cons); + rt::set_abortcons(&log::write); +}; diff --git a/efi/mmap.ha b/efi/mmap.ha index e75fd21..587b88a 100644 --- a/efi/mmap.ha +++ b/efi/mmap.ha @@ -1,5 +1,3 @@ -use log; - // Type of a memory region. export type MEMORY_TYPE = enum u32 { RESERVED, -- 2.45.2