132 lines
2.7 KiB
C++
132 lines
2.7 KiB
C++
/*
|
|
* \brief Freescale's TrustZone aware interrupt controller
|
|
* \author Stefan Kalkowski
|
|
* \date 2012-10-24
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2012-2017 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.
|
|
*/
|
|
|
|
#ifndef _SRC__LIB__HW__SPEC__ARM__IMX_TZIC_H_
|
|
#define _SRC__LIB__HW__SPEC__ARM__IMX_TZIC_H_
|
|
|
|
#include <util/mmio.h>
|
|
|
|
namespace Hw { class Pic; }
|
|
|
|
|
|
class Hw::Pic : public Genode::Mmio
|
|
{
|
|
public:
|
|
|
|
enum { NR_OF_IRQ = 109, };
|
|
|
|
protected:
|
|
|
|
/**
|
|
* Software Interrupt Trigger Register
|
|
*/
|
|
struct Swint : Register<0xf00, 32> {
|
|
struct Intid : Bitfield<0,10> { }; };
|
|
|
|
/**
|
|
* Interrupt control register
|
|
*/
|
|
struct Intctrl : Register<0, 32>
|
|
{
|
|
struct Enable : Bitfield<0,1> { };
|
|
struct Nsen : Bitfield<16,1> { };
|
|
struct Nsen_mask : Bitfield<31,1> { };
|
|
};
|
|
|
|
/**
|
|
* Priority mask register
|
|
*/
|
|
struct Priomask : Register<0xc, 32> {
|
|
struct Mask : Bitfield<0,8> { }; };
|
|
|
|
/**
|
|
* Interrupt security registers
|
|
*/
|
|
struct Intsec : Register_array<0x80, 32, NR_OF_IRQ, 1> {
|
|
struct Nonsecure : Bitfield<0, 1> { }; };
|
|
|
|
/**
|
|
* Interrupt set enable registers
|
|
*/
|
|
struct Enset : Register_array<0x100, 32, NR_OF_IRQ, 1, true> {
|
|
struct Set_enable : Bitfield<0, 1> { }; };
|
|
|
|
/**
|
|
* Interrupt clear enable registers
|
|
*/
|
|
struct Enclear : Register_array<0x180, 32, NR_OF_IRQ, 1, true> {
|
|
struct Clear_enable : Bitfield<0, 1> { }; };
|
|
|
|
/**
|
|
* Interrupt priority level registers
|
|
*/
|
|
struct Priority : Register_array<0x400, 32, NR_OF_IRQ, 8> { };
|
|
|
|
/**
|
|
* Highest interrupt pending registers
|
|
*/
|
|
struct Hipndr : Register_array<0xd80, 32, NR_OF_IRQ, 1, true> {
|
|
struct Pending : Bitfield<0, 1> { }; };
|
|
|
|
/**
|
|
* Validate request number 'i'
|
|
*/
|
|
bool _valid(unsigned const i) const { return i < NR_OF_IRQ; }
|
|
|
|
public:
|
|
|
|
enum { IPI = 0xffff };
|
|
|
|
Pic();
|
|
|
|
/**
|
|
* Receive a pending request number 'i'
|
|
*/
|
|
bool take_request(unsigned & i)
|
|
{
|
|
for (unsigned j = 0; j < NR_OF_IRQ; j++) {
|
|
if (!read<Hipndr::Pending>(j)) { continue; }
|
|
i = j;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void finish_request() { }
|
|
|
|
/**
|
|
* Unmask interrupt 'i'
|
|
*/
|
|
void unmask(unsigned const i, unsigned) {
|
|
if (_valid(i)) { write<Enset::Set_enable>(1, i); } }
|
|
|
|
/**
|
|
* Mask interrupt 'i'
|
|
*/
|
|
void mask(unsigned const i) {
|
|
if (_valid(i)) { write<Enclear::Clear_enable>(1, i); } }
|
|
|
|
/*
|
|
* Trigger interrupt 'i' from software if possible
|
|
*/
|
|
void trigger(unsigned const i) {
|
|
write<Swint>(Swint::Intid::bits(i)); }
|
|
|
|
bool secure(unsigned i) {
|
|
return !read<Intsec::Nonsecure>(i); }
|
|
|
|
static constexpr bool fast_interrupts() { return true; }
|
|
};
|
|
|
|
#endif /* _SRC__LIB__HW__SPEC__ARM__IMX_TZIC_H_ */
|