i-RISCV Input/Output Support
The i-RISCV SoC provides the following input/output mechanisms.
IOMMU
The SoC implements the RISC-V IOMMU (v1.0) for DMA-capable devices. Supported mechanisms:
- Device Directory Table (DDT) walk in
Off,Bare,1LVL,2LVL, and3LVLmodes - Second-stage-only DMA address translation (
Sv39x4/Sv48x4/Sv57x4) with hardware A/D update on page-table entries - MSI address translation, redirecting a device’s writes to a guest’s virtual IMSIC interrupt file onto the real physical guest file (AIA/IMSIC tie-in)
- IOATC: a device-context cache and an I/O TLB, invalidated via
IODIR.INVAL_DDTandIOTINVAL.VMA/.GVMAcommands - Command queue (
IOTINVAL,IOFENCE.C,IODIR) and fault queue for translation errors - WSI (wire-signal) interrupt delivery to the PLIC/APLIC on faults or fence completion
- IOPMP enforcement of the final physical address after every successful translation
AIA and IMSIC
The core implements the RISC-V Advanced Interrupt Architecture (AIA, v1.0). Supported mechanisms:
Smaia/Ssaia: M-level and S-level AIA CSRs (miselect/mireg,siselect/sireg,mtopi/stopi,mvien/mvip)- IMSIC (Incoming MSI Controller) with per-hart M-file and S-file, memory-mapped MSI delivery (
seteipnum_le), and claim-and-clear viamtopei/stopei - Two VS-level guest interrupt files per hart for the H extension, selected by
hstatus.VGEIN, each with its own physical MSI region to support migrating a guest between files - VS-level hypervisor AIA CSRs (
hvien,hvictl,vsiselect/vsireg,vstopei/vstopi) - A minimal, MSI-mode-only, machine-level APLIC domain (
aplic0, 8 sources,msi-parent = imsic_s) that forwards this platform’s wired sources into the IMSIC S-file as MSIs – under Linux, the IOMMU’s and IOPMP’s interrupts are advertised against it (sources 2/3) instead of throughplic0’s own S-mode context, which keeps a position-preserving placeholder entry; the PLIC retains its M-mode context for firmware and bare-metal use
IOPMP
The SoC implements RISC-V I/O Physical Memory Protection (IOPMP), which regulates physical-address accesses issued by non-hart bus requesters (the IOMMU’s translation path). Supported mechanisms:
- 16 requester IDs, 8 memory domains, and 16 protection entries
- TOR/NA4/NAPOT address matching with lowest-index-wins priority and per-entry r/w/x permissions
- Memory-domain / source association gating (
MDCFG/SRCMD_EN) - Locking of MD associations, MDCFG, and entries (W1SS/incremental-only)
- First-violation error capture (requester ID, address, access type, denial reason) with interrupt reporting
Console UART
A genuine ns16550a-register-compatible serial console (rtl/uncore/uart.sv), build-time optional (UART_ENABLE; at 0 it is removed from the design entirely – registers read 0, interrupt tied low, TX held idle-high). Supported mechanisms:
- Standard byte-addressed 8-register map with DLAB-banked offsets 0/1 (RBR/THR/DLL, IER/DLM, IIR/FCR, LCR, MCR, LSR, MSR, SCR) – the exact layout a stock Linux
8250driver expects, noreg-shift/reg-io-widthoverrides - Real baud-rate divisor: one bit period = 16 x DLL/DLM core cycles; reset to 115200 at a 50 MHz clock so bare-metal firmware gets a known rate without programming it; reprogrammed via the standard DLAB sequence
- Full 16550A hardware FIFOs: 16-byte TX and RX, enabled by sticky
FCR.FE(any toggle clears both), four RX trigger levels (1/4/8/14 bytes) plus a real 4-character-time RX timeout interrupt so low-throughput links never stall below the trigger level; withoutFCR.FE, one physical shift register feeds single holding/latch registers instead (THR writes while busy are silently ignored, THRE and TEMT collapse to one condition) - Receiver error detection – framing error, BREAK, overrun – with per-byte error tags in the RX FIFO feeding LSR’s errors-in-FIFO bit; RBR reads clear DR/pop the FIFO while LSR reads clear OE/PE/FE/BI (two distinct read-to-clear conditions, matching real 16550 semantics)
- Real interrupt priority chain: line status > data available / character timeout > THR-empty (one-shot – fires exactly once per emptying, acknowledged by an IIR read or a new THR write) > modem status, with standard IIR identification codes
MCR.LOOPinternal loopback feeding the transmitter back into the receiver while the external TX pin is held idle-high; in loopback mode MSR’s CTS/DSR/RI/DCD mirror MCR’s DTR/RTS/OUT1/OUT2 one-to-one with delta bits latched and cleared on read- Modem status defaults to “always ready” (CTS=DSR=DCD=1, RI=0) since no real modem lines exist
The UART’s irq is wired to both controllers’ source 1 (source 2 = the IOMMU WSI, source 3 = the IOPMP); sources 2 and 3 are advertised in the device tree against aplic0, while the UART itself carries no interrupts property – a single honest compatible = "ns16550a" – so under Linux the stock driver falls back to polling (see Linux).
Disclosed simplifications. Not silent scope cuts:
- Fixed 8N1 wire framing – LCR’s word-length/parity/stop-bit fields are stored and read back faithfully but not enforced on the wire
- No 16750/16950 extensions (no 64-byte FIFO, no auto-flow-control beyond the plain MCR/MSR pins)