e3f82b09d7
Ref #3520
76 lines
2.1 KiB
C++
76 lines
2.1 KiB
C++
/*
|
|
* \brief Programmable interrupt controller for core
|
|
* \author Stefan Kalkowski
|
|
* \date 2012-10-24
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2012-2019 Genode Labs GmbH
|
|
*
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
* under the terms of the GNU Affero General Public License version 3.
|
|
*/
|
|
|
|
#include <board.h>
|
|
|
|
Hw::Gicv2::Gicv2()
|
|
: _distr(Board::Cpu_mmio::IRQ_CONTROLLER_DISTR_BASE),
|
|
_cpui (Board::Cpu_mmio::IRQ_CONTROLLER_CPU_BASE),
|
|
_last_iar(Cpu_interface::Iar::Irq_id::bits(spurious_id)),
|
|
_max_irq(_distr.max_irq())
|
|
{
|
|
static bool distributor_initialized = false;
|
|
|
|
if (!distributor_initialized) {
|
|
distributor_initialized = true;
|
|
|
|
/* disable device */
|
|
_distr.write<Distributor::Ctlr>(0);
|
|
|
|
/* configure every shared peripheral interrupt */
|
|
for (unsigned i = min_spi; i <= _max_irq; i++) {
|
|
if (Board::NON_SECURE) {
|
|
_distr.write<Distributor::Igroupr::Group_status>(1, i);
|
|
}
|
|
_distr.write<Distributor::Icfgr::Edge_triggered>(0, i);
|
|
_distr.write<Distributor::Ipriorityr::Priority>(0, i);
|
|
_distr.write<Distributor::Icenabler::Clear_enable>(1, i);
|
|
}
|
|
|
|
/* enable device */
|
|
Distributor::Ctlr::access_t v = 0;
|
|
if (Board::NON_SECURE) {
|
|
Distributor::Ctlr::Enable_grp0::set(v, 1);
|
|
Distributor::Ctlr::Enable_grp1::set(v, 1);
|
|
} else {
|
|
Distributor::Ctlr::Enable::set(v, 1);
|
|
}
|
|
_distr.write<Distributor::Ctlr>(v);
|
|
}
|
|
|
|
if (Board::NON_SECURE) {
|
|
_cpui.write<Cpu_interface::Ctlr>(0);
|
|
|
|
/* mark software-generated IRQs as being non-secure */
|
|
for (unsigned i = 0; i < min_spi; i++)
|
|
_distr.write<Distributor::Igroupr::Group_status>(1, i);
|
|
}
|
|
|
|
/* disable the priority filter */
|
|
_cpui.write<Cpu_interface::Pmr::Priority>(_distr.min_priority());
|
|
|
|
/* disable preemption of IRQ handling by other IRQs */
|
|
_cpui.write<Cpu_interface::Bpr::Binary_point>(~0);
|
|
|
|
/* enable device */
|
|
Cpu_interface::Ctlr::access_t v = 0;
|
|
if (Board::NON_SECURE) {
|
|
Cpu_interface::Ctlr::Enable_grp0::set(v, 1);
|
|
Cpu_interface::Ctlr::Enable_grp1::set(v, 1);
|
|
Cpu_interface::Ctlr::Fiq_en::set(v, 1);
|
|
} else {
|
|
Cpu_interface::Ctlr::Enable::set(v, 1);
|
|
}
|
|
_cpui.write<Cpu_interface::Ctlr>(v);
|
|
}
|