genode/base-hw/src/core/pic/imx31.h

211 lines
4.2 KiB
C++

/*
* \brief Programmable interrupt controller for core
* \author Norman Feske
* \author Martin Stein
* \date 2012-08-30
*/
/*
* Copyright (C) 2012-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _PIC__IMX31_H_
#define _PIC__IMX31_H_
/* Genode includes */
#include <util/mmio.h>
/* core includes */
#include <board.h>
namespace Imx31
{
using namespace Genode;
/**
* Programmable interrupt controller for core
*/
class Pic : public Mmio
{
/**
* Interrupt control register
*/
struct Intcntl : Register<0x0, 32>
{
struct Nm : Bitfield<18,1> /* IRQ mode */
{
enum { SW_CONTROL = 0 };
};
struct Fiad : Bitfield<19,1> { }; /* FIQ rises prio in arbiter */
struct Niad : Bitfield<20,1> { }; /* IRQ rises prio in arbiter */
struct Fidis : Bitfield<21,1> { }; /* FIQ disable */
struct Nidis : Bitfield<22,1> { }; /* IRQ disable */
struct Abfen : Bitfield<24,1> { }; /* if ABFLAG is sticky */
struct Abflag : Bitfield<25,1> { }; /* rise prio in bus arbiter */
static access_t init_value()
{
return Nm::bits(Nm::SW_CONTROL) |
Fiad::bits(0) |
Niad::bits(0) |
Fidis::bits(0) |
Nidis::bits(0) |
Abfen::bits(0) |
Abflag::bits(0);
}
};
/**
* Normal interrupt mask register
*/
struct Nimask : Register<0x4, 32>
{
enum { NONE_MASKED = ~0 };
};
/**
* Interrupt enable number register
*/
struct Intennum : Register<0x8, 32>
{
struct Enable : Bitfield<0,6> { };
};
/**
* Interrupt disable number register
*/
struct Intdisnum : Register<0xc, 32>
{
struct Disable : Bitfield<0,6> { };
};
/**
* Interrupt enable register
*/
struct Intenableh : Register<0x10, 32> { };
struct Intenablel : Register<0x14, 32> { };
/**
* Interrupt type register
*/
struct Inttype { enum { ALL_IRQS = 0 }; };
struct Inttypeh : Register<0x18, 32> { };
struct Inttypel : Register<0x1c, 32> { };
/**
* Normal interrupt priority registers
*/
struct Nipriority : Register_array<0x20, 32, 8, 32>
{
enum { ALL_LOWEST = 0 };
};
/**
* Interrupt source registers
*/
struct Intsrch : Register<0x48, 32> { };
struct Intsrcl : Register<0x4c, 32> { };
/**
* Normal interrupt pending registers
*/
struct Nipndh : Register<0x58, 32> { };
struct Nipndl : Register<0x5c, 32> { };
/**
* Normal interrupt vector and status register
*/
struct Nivecsr : Register<0x40, 32>
{
struct Nvector : Bitfield<16, 16> { };
};
public:
enum { MAX_INTERRUPT_ID = 63 };
/**
* Constructor, enables all interrupts
*/
Pic() : Mmio(Board::AVIC_MMIO_BASE)
{
mask();
write<Nimask>(Nimask::NONE_MASKED);
write<Intcntl>(Intcntl::init_value());
write<Inttypeh>(Inttype::ALL_IRQS);
write<Inttypel>(Inttype::ALL_IRQS);
for (unsigned i = 0; i < Nipriority::ITEMS; i++)
write<Nipriority>(Nipriority::ALL_LOWEST, i);
}
/**
* Initialize processor local interface of the controller
*/
void init_processor_local() { }
/**
* Receive a pending request number 'i'
*/
bool take_request(unsigned & i)
{
i = read<Nivecsr::Nvector>();
return valid(i) ? true : false;
}
/**
* Finish the last taken request
*/
void finish_request() {
/* requests disappear by source retraction or masking */ }
/**
* Validate request number 'i'
*/
bool valid(unsigned const i) const {
return i <= MAX_INTERRUPT_ID; }
/**
* Unmask all interrupts
*/
void unmask()
{
write<Intenablel>(~0);
write<Intenableh>(~0);
}
/**
* Mask all interrupts
*/
void mask()
{
write<Intenablel>(0);
write<Intenableh>(0);
}
/**
* Unmask interrupt
*
* \param interrupt_id kernel name of targeted interrupt
*/
void unmask(unsigned const interrupt_id, unsigned)
{
if (interrupt_id <= MAX_INTERRUPT_ID) {
write<Intennum>(interrupt_id);
}
}
/**
* Mask interrupt 'i'
*/
void mask(unsigned const i) {
if (i <= MAX_INTERRUPT_ID) write<Intdisnum>(i); }
};
}
#endif /* _PIC__IMX31_H_ */