diff options
-rw-r--r-- | riscv/clint.cc | 31 | ||||
-rw-r--r-- | riscv/ns16550.cc | 37 | ||||
-rw-r--r-- | riscv/plic.cc | 37 |
3 files changed, 105 insertions, 0 deletions
diff --git a/riscv/clint.cc b/riscv/clint.cc index 25e45fb..908ccb6 100644 --- a/riscv/clint.cc +++ b/riscv/clint.cc @@ -1,7 +1,10 @@ #include <sys/time.h> +#include <sstream> #include "devices.h" #include "processor.h" #include "simif.h" +#include "sim.h" +#include "dts.h" clint_t::clint_t(const simif_t* sim, uint64_t freq_hz, bool real_time) : sim(sim), freq_hz(freq_hz), real_time(real_time), mtime(0) @@ -112,3 +115,31 @@ void clint_t::tick(reg_t rtc_ticks) hart->state.mip->backdoor_write_with_mask(MIP_MTIP, mtime >= mtimecmp[hart_id] ? MIP_MTIP : 0); } } + +clint_t* clint_parse_from_fdt(const void* fdt, const sim_t* sim, reg_t* base) { + if (fdt_parse_clint(fdt, base, "riscv,clint0") == 0) + return new clint_t(sim, + sim->CPU_HZ / sim->INSNS_PER_RTC_TICK, + sim->get_cfg().real_time_clint()); + else + return nullptr; +} + +std::string clint_generate_dts(const sim_t* sim) { + std::stringstream s; + s << std::hex + << " clint@" << CLINT_BASE << " {\n" + " compatible = \"riscv,clint0\";\n" + " interrupts-extended = <" << std::dec; + for (size_t i = 0; i < sim->get_cfg().nprocs(); i++) + s << "&CPU" << i << "_intc 3 &CPU" << i << "_intc 7 "; + reg_t clintbs = CLINT_BASE; + reg_t clintsz = CLINT_SIZE; + s << std::hex << ">;\n" + " reg = <0x" << (clintbs >> 32) << " 0x" << (clintbs & (uint32_t)-1) << + " 0x" << (clintsz >> 32) << " 0x" << (clintsz & (uint32_t)-1) << ">;\n" + " };\n"; + return s.str(); +} + +REGISTER_DEVICE(clint, clint_parse_from_fdt, clint_generate_dts) diff --git a/riscv/ns16550.cc b/riscv/ns16550.cc index 475d5ec..a4bd204 100644 --- a/riscv/ns16550.cc +++ b/riscv/ns16550.cc @@ -1,7 +1,10 @@ #include <sys/time.h> +#include <sstream> #include "devices.h" #include "processor.h" #include "term.h" +#include "sim.h" +#include "dts.h" #define UART_QUEUE_SIZE 64 @@ -317,3 +320,37 @@ void ns16550_t::tick(reg_t UNUSED rtc_ticks) lsr |= UART_LSR_DR; update_interrupt(); } + +std::string ns16550_generate_dts(const sim_t* sim) +{ + std::stringstream s; + s << std::hex + << " SERIAL0: ns16550@" << NS16550_BASE << " {\n" + " compatible = \"ns16550a\";\n" + " clock-frequency = <" << std::dec << (sim->CPU_HZ/sim->INSNS_PER_RTC_TICK) << ">;\n" + " interrupt-parent = <&PLIC>;\n" + " interrupts = <" << std::dec << NS16550_INTERRUPT_ID; + reg_t ns16550bs = NS16550_BASE; + reg_t ns16550sz = NS16550_SIZE; + s << std::hex << ">;\n" + " reg = <0x" << (ns16550bs >> 32) << " 0x" << (ns16550bs & (uint32_t)-1) << + " 0x" << (ns16550sz >> 32) << " 0x" << (ns16550sz & (uint32_t)-1) << ">;\n" + " reg-shift = <0x" << NS16550_REG_SHIFT << ">;\n" + " reg-io-width = <0x" << NS16550_REG_IO_WIDTH << ">;\n" + " };\n"; + return s.str(); +} + +ns16550_t* ns16550_parse_from_fdt(const void* fdt, const sim_t* sim, reg_t* base) +{ + uint32_t ns16550_shift, ns16550_io_width; + if (fdt_parse_ns16550(fdt, base, + &ns16550_shift, &ns16550_io_width, "ns16550a") == 0) { + abstract_interrupt_controller_t* intctrl = sim->get_intctrl(); + return new ns16550_t(intctrl, NS16550_INTERRUPT_ID, ns16550_shift, ns16550_io_width); + } else { + return nullptr; + } +} + +REGISTER_DEVICE(ns16550, ns16550_parse_from_fdt, ns16550_generate_dts) diff --git a/riscv/plic.cc b/riscv/plic.cc index e2685a9..1aa5852 100644 --- a/riscv/plic.cc +++ b/riscv/plic.cc @@ -1,7 +1,10 @@ #include <sys/time.h> +#include <sstream> #include "devices.h" #include "processor.h" #include "simif.h" +#include "sim.h" +#include "dts.h" #define PLIC_MAX_CONTEXTS 15872 @@ -388,3 +391,37 @@ bool plic_t::store(reg_t addr, size_t len, const uint8_t* bytes) return ret; } + +std::string plic_generate_dts(const sim_t* sim) +{ + std::stringstream s; + s << std::hex + << " PLIC: plic@" << PLIC_BASE << " {\n" + " compatible = \"riscv,plic0\";\n" + " #address-cells = <2>;\n" + " interrupts-extended = <" << std::dec; + for (size_t i = 0; i < sim->get_cfg().nprocs(); i++) + s << "&CPU" << i << "_intc 11 &CPU" << i << "_intc 9 "; + reg_t plicbs = PLIC_BASE; + reg_t plicsz = PLIC_SIZE; + s << std::hex << ">;\n" + " reg = <0x" << (plicbs >> 32) << " 0x" << (plicbs & (uint32_t)-1) << + " 0x" << (plicsz >> 32) << " 0x" << (plicsz & (uint32_t)-1) << ">;\n" + " riscv,ndev = <0x" << PLIC_NDEV << ">;\n" + " riscv,max-priority = <0x" << ((1U << PLIC_PRIO_BITS) - 1) << ">;\n" + " #interrupt-cells = <1>;\n" + " interrupt-controller;\n" + " };\n"; + return s.str(); +} + +plic_t* plic_parse_from_fdt(const void* fdt, const sim_t* sim, reg_t* base) +{ + uint32_t plic_ndev; + if (fdt_parse_plic(fdt, base, &plic_ndev, "riscv,plic0") == 0) + return new plic_t(sim, plic_ndev); + else + return nullptr; +} + +REGISTER_DEVICE(plic, plic_parse_from_fdt, plic_generate_dts) |