#include #include #include #include #include "cortexa8.hh" #include "mmio.hh" #include "util.hh" #include "omap35x_intc.hh" extern "C" void _omap35x_intc_handler(); static OMAP35x_intc_impl* intc = nullptr; class OMAP35x_intc_impl { public: OMAP35x_intc_impl(uintptr_t base) : base_{base} { // Interrupts should (still) be disabled from boot assert(!cortexa8_get_int()); // This is something like a singleton assert(!intc); intc = this; r_sysconfig() = 0x1; // Autoidle = 1 r_idle() = 0x2; // Turbo = 1, Funcidle = 0 // Disable all ints for(int i = 0;i <= 2;++i) r_mir_set(i) = 0xffffffff; } void register_handler(int irq, int_handler_t const& handler, int prio) { assert(irq >= 0 && irq <= 95); assert(prio >= 0 && prio <= 63); handler_tbl_[irq] = handler; r_ilr(irq) = prio<<2; } void enable_int(int irq) { assert(irq >= 0 && irq <= 95); assert(handler_tbl_[irq]); int i = irq/32, j = irq%32; r_mir_clear(i) = (1<= 0 && irq <= 95); int i = irq/32, j = irq%32; r_mir_set(i) = (1<= 0 && irq <= 95); assert(handler_tbl_[irq]); handler_tbl_[irq](); r_control() = 0x1; __asm__ __volatile__ ("dsb"); } uint32_t volatile& r_sysconfig() {return _reg32(base_.get_virt(), 0x10); } uint32_t volatile& r_sysstatus() {return _reg32(base_.get_virt(), 0x14); } uint32_t volatile& r_sir_irq() {return _reg32(base_.get_virt(), 0x40); } uint32_t volatile& r_sir_fiq() {return _reg32(base_.get_virt(), 0x44); } uint32_t volatile& r_control() {return _reg32(base_.get_virt(), 0x48); } uint32_t volatile& r_protection() {return _reg32(base_.get_virt(), 0x4c); } uint32_t volatile& r_idle() {return _reg32(base_.get_virt(), 0x50); } uint32_t volatile& r_irq_priority() {return _reg32(base_.get_virt(), 0x60); } uint32_t volatile& r_fiq_priority() {return _reg32(base_.get_virt(), 0x64); } uint32_t volatile& r_threshold() {return _reg32(base_.get_virt(), 0x68); } uint32_t volatile& r_itr(int n) {assert(n >= 0 && n <= 2); return _reg32(base_.get_virt(), 0x80+0x20*n); } uint32_t volatile& r_mir(int n) {assert(n >= 0 && n <= 2); return _reg32(base_.get_virt(), 0x84+0x20*n); } uint32_t volatile& r_mir_clear(int n) {assert(n >= 0 && n <= 2); return _reg32(base_.get_virt(), 0x88+0x20*n); } uint32_t volatile& r_mir_set(int n) {assert(n >= 0 && n <= 2); return _reg32(base_.get_virt(), 0x8c+0x20*n); } uint32_t volatile& r_isr_set(int n) {assert(n >= 0 && n <= 2); return _reg32(base_.get_virt(), 0x90+0x20*n); } uint32_t volatile& r_isr_clear(int n) {assert(n >= 0 && n <= 2); return _reg32(base_.get_virt(), 0x94+0x20*n); } uint32_t volatile& r_pending_irq(int n) {assert(n >= 0 && n <= 2); return _reg32(base_.get_virt(), 0x98+0x20*n); } uint32_t volatile& r_pending_fiq(int n) {assert(n >= 0 && n <= 2); return _reg32(base_.get_virt(), 0x9c+0x20*n); } uint32_t volatile& r_ilr(int m) {assert(m >= 0 && m <= 95); return _reg32(base_.get_virt(), 0x100+0x4*m); } MMIO_alloc base_; std::array handler_tbl_; }; void _omap35x_intc_handler() { if(intc) intc->handler(); } OMAP35x_intc::OMAP35x_intc(uintptr_t base) : impl_{new OMAP35x_intc_impl{base}} { } OMAP35x_intc::~OMAP35x_intc() { } void OMAP35x_intc::register_handler(int irq, int_handler_t const& handler, int prio) { impl_->register_handler(irq, handler, prio); } void OMAP35x_intc::enable_int(int irq) { impl_->enable_int(irq); } void OMAP35x_intc::disable_int(int irq) { impl_->disable_int(irq); }