diff options
author | Himbeer <himbeer@disroot.org> | 2024-05-18 10:58:01 +0200 |
---|---|---|
committer | Himbeer <himbeer@disroot.org> | 2024-05-18 10:58:01 +0200 |
commit | 573f58487f899563e1ae08fd829eb4053a1f10ac (patch) | |
tree | e051c2169533aea52885c1cd12e0636afe468399 /src/uart.zig | |
parent | 71a8c414d0ffcb6426f440542ea97e54133034f6 (diff) |
logging: Use UART directly if available
Some SBIs don't implement the Debug Console extension. Using the UART is one solution, supporting the SBI Legacy extension might work too if it exists.
Diffstat (limited to 'src/uart.zig')
-rw-r--r-- | src/uart.zig | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/src/uart.zig b/src/uart.zig new file mode 100644 index 0000000..3a15a6c --- /dev/null +++ b/src/uart.zig @@ -0,0 +1,58 @@ +// SPDX-FileCopyrightText: 2024 Himbeer <himbeer@disroot.org> +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +const std = @import("std"); + +const fdt = @import("fdt.zig"); +const paging = @import("paging.zig"); + +pub var default: ?Port = null; + +pub const Error = error{ + NoSocNode, +}; + +pub const Port = struct { + reg: []volatile u8, + reg_shift: u6, + + const lsr_temt = 1 << 5; + + pub const Writer = std.io.Writer(Port, error{}, write); + + fn isWriteReady(self: Port) bool { + return self.reg[@as(usize, 5) << self.reg_shift] & lsr_temt != 0; + } + + pub fn write(self: Port, bytes: []const u8) !usize { + for (bytes) |byte| { + while (!self.isWriteReady()) {} + self.reg[0] = byte; + } + + return bytes.len; + } + + pub fn writer(port: Port) Writer { + return .{ .context = port }; + } +}; + +pub fn init(kmem: *paging.Table, dt: *const fdt.Tree, allocator: std.mem.Allocator) !void { + var soc = fdt.findPathExact(dt, "/soc") orelse return Error.NoSocNode; + + const compatible = fdt.findCompatible(&soc, &[_][]const u8{ "ns16550", "snps,dw-apb-uart" }, 1); + + const node = if (compatible.len > 0) compatible[0] else return; + + const regs = try node.reg(allocator); + defer regs.deinit(); + + try kmem.mapDevice(regs.items[0]); + + const reg_shift_bytes = node.props.get("reg-shift"); + const reg_shift = if (reg_shift_bytes) |bytes| std.mem.readInt(u32, bytes[0..4], .big) else 0; + + default = .{ .reg = regs.items[0].slice(u8), .reg_shift = @intCast(reg_shift) }; +} |