ARM: kernel: introduce SoC abstraction

This introduces InterruptController and HardwareTimer classes to
handle the SoC specific implementations of timers and ints for
the ARM platform.

These could be improved and moved to a more 'generic' level once
we're confident they are 'good enough'.

NOTE: The OMAP timer implementation is fully untested and probably
      completely non-functional....
This commit is contained in:
Ithamar R. Adema
2014-10-31 11:37:02 +01:00
parent 47c5303305
commit a52dd58d2d
9 changed files with 618 additions and 120 deletions
+6
View File
@@ -34,6 +34,12 @@ KernelMergeObject kernel_arch_arm.o :
arch_atomic64.cpp
arch_atomic32.cpp
# SoC minimal kernel-required support
# (timers, interrupts, rtc?)
soc.cpp
soc_pxa.cpp
soc_omap3.cpp
# paging
arm_physical_page_mapper_large_memory.cpp
ARMPagingMethod.cpp
+34 -43
View File
@@ -30,6 +30,11 @@
#include <vm/VMAddressSpace.h>
#include <string.h>
#include <drivers/bus/FDT.h>
#include "soc.h"
#include "soc_pxa.h"
#include "soc_omap3.h"
#define TRACE_ARCH_INT
#ifdef TRACE_ARCH_INT
@@ -42,17 +47,6 @@
#define USER_VECTOR_ADDR_LOW 0x00000000
#define USER_VECTOR_ADDR_HIGH 0xffff0000
#define PXA_INTERRUPT_PHYS_BASE 0x40D00000
#define PXA_INTERRUPT_SIZE 0x00000034
#define PXA_ICIP 0x00
#define PXA_ICMR 0x01
#define PXA_ICFP 0x03
#define PXA_ICMR2 0x28
static area_id sPxaInterruptArea;
static uint32 *sPxaInterruptBase;
extern int _vectors_start;
extern int _vectors_end;
@@ -60,6 +54,7 @@ static area_id sVectorPageArea;
static void *sVectorPageAddress;
static area_id sUserVectorPageArea;
static void *sUserVectorPageAddress;
static fdt_module_info *sFdtModule;
// An iframe stack used in the early boot process when we don't have
// threads yet.
@@ -70,13 +65,9 @@ void
arch_int_enable_io_interrupt(int irq)
{
TRACE(("arch_int_enable_io_interrupt(%d)\n", irq));
if (irq <= 31) {
sPxaInterruptBase[PXA_ICMR] |= 1 << irq;
return;
}
sPxaInterruptBase[PXA_ICMR2] |= 1 << (irq - 32);
InterruptController *ic = InterruptController::Get();
if (ic != NULL)
ic->EnableInterrupt(irq);
}
@@ -84,13 +75,9 @@ void
arch_int_disable_io_interrupt(int irq)
{
TRACE(("arch_int_disable_io_interrupt(%d)\n", irq));
if (irq <= 31) {
sPxaInterruptBase[PXA_ICMR] &= ~(1 << irq);
return;
}
sPxaInterruptBase[PXA_ICMR2] &= ~(1 << (irq - 32));
InterruptController *ic = InterruptController::Get();
if (ic != NULL)
ic->DisableInterrupt(irq);
}
@@ -129,6 +116,18 @@ arch_int_init(kernel_args *args)
extern "C" void arm_vector_init(void);
static struct fdt_device_info intc_table[] = {
{
.compatible = "marvell,pxa-intc",
.init = PXAInterruptController::Init,
}, {
.compatible = "ti,omap3-intc",
.init = OMAP3InterruptController::Init,
}
};
static int intc_count = sizeof(intc_table) / sizeof(struct fdt_device_info);
status_t
arch_int_init_post_vm(kernel_args *args)
{
@@ -136,7 +135,6 @@ arch_int_init_post_vm(kernel_args *args)
sVectorPageArea = create_area("vectorpage", (void **)&sVectorPageAddress,
B_ANY_ADDRESS, VECTORPAGE_SIZE, B_FULL_LOCK,
B_KERNEL_WRITE_AREA | B_KERNEL_READ_AREA);
if (sVectorPageArea < 0)
panic("vector page could not be created!");
@@ -166,14 +164,13 @@ arch_int_init_post_vm(kernel_args *args)
dprintf("Enabled high vectors\n");
}
sPxaInterruptArea = map_physical_memory("pxa_intc", PXA_INTERRUPT_PHYS_BASE,
PXA_INTERRUPT_SIZE, 0, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)&sPxaInterruptBase);
status_t rc = get_module(B_FDT_MODULE_NAME, (module_info**)&sFdtModule);
if (rc != B_OK)
panic("Unable to get FDT module: %08lx!\n", rc);
if (sPxaInterruptArea < 0)
return sPxaInterruptArea;
sPxaInterruptBase[PXA_ICMR] = 0;
sPxaInterruptBase[PXA_ICMR2] = 0;
rc = sFdtModule->setup_devices(intc_table, intc_count, NULL);
if (rc != B_OK)
panic("No interrupt controllers found!\n");
return B_OK;
}
@@ -338,10 +335,9 @@ arch_arm_irq(struct iframe *iframe)
{
IFrameScope scope(iframe);
for (int i=0; i < 32; i++) {
if (sPxaInterruptBase[PXA_ICIP] & (1 << i))
int_io_interrupt_handler(i, true);
}
InterruptController *ic = InterruptController::Get();
if (ic != NULL)
ic->HandleInterrupt();
}
@@ -350,10 +346,5 @@ arch_arm_fiq(struct iframe *iframe)
{
IFrameScope scope(iframe);
for (int i=0; i < 32; i++) {
if (sPxaInterruptBase[PXA_ICIP] & (1 << i)) {
dprintf("arch_arm_fiq: help me, FIQ %d was triggered but no "
"FIQ support!\n", i);
}
}
panic("FIQ not implemented yet!");
}
+31 -77
View File
@@ -19,6 +19,11 @@
#include <arch/timer.h>
#include <arch/cpu.h>
#include <drivers/bus/FDT.h>
#include "soc.h"
#include "soc_pxa.h"
#include "soc_omap3.h"
//#define TRACE_ARCH_TIMER
#ifdef TRACE_ARCH_TIMER
@@ -27,99 +32,49 @@
# define TRACE(x) ;
#endif
static fdt_module_info *sFdtModule;
#define PXA_TIMERS_PHYS_BASE 0x40A00000
#define PXA_TIMERS_SIZE B_PAGE_SIZE
#define PXA_TIMERS_INTERRUPT 7 /* OST_4_11 */
#define PXA_OSSR 0x05
#define PXA_OIER 0x07
#define PXA_OSCR4 0x10
#define PXA_OSCR5 0x11
#define PXA_OSMR4 0x20
#define PXA_OSMR5 0x21
#define PXA_OMCR4 0x30
#define PXA_OMCR5 0x31
#define PXA_RES_S (3 << 0)
#define PXA_RES_MS (1 << 1)
#define PXA_RES_US (1 << 2)
#define US2S(bt) ((bt) / 1000000ULL)
#define US2MS(bt) ((bt) / 1000ULL)
static area_id sPxaTimersArea = -1;
static uint32 *sPxaTimersBase = NULL;
static bigtime_t sSystemTime = 0;
static int32
pxa_timer_interrupt(void *data)
{
if (sPxaTimersBase[PXA_OSSR] & (1 << 4)) {
sPxaTimersBase[PXA_OSSR] |= (1 << 4);
return timer_interrupt();
static struct fdt_device_info intc_table[] = {
{
.compatible = "marvell,pxa-timers", // XXX not in FDT (also not in upstream!)
.init = PXATimer::Init,
}, {
.compatible = "ti,omap3430-timer",
.init = OMAP3Timer::Init,
}
};
static int intc_count = sizeof(intc_table) / sizeof(struct fdt_device_info);
if (sPxaTimersBase[PXA_OSSR] & (1 << 5)) {
sPxaTimersBase[PXA_OSSR] |= (1 << 5);
sSystemTime += UINT_MAX + 1ULL;
}
return B_HANDLED_INTERRUPT;
}
void
arch_timer_set_hardware_timer(bigtime_t timeout)
{
uint32 val = timeout & UINT_MAX;
uint32 res = PXA_RES_US;
if (timeout & ~UINT_MAX) {
// Does not fit, so scale resolution down to milliseconds
if (US2MS(timeout) & ~UINT_MAX) {
// Still does not fit, scale down to seconds as last ditch attempt
val = US2S(timeout) & UINT_MAX;
res = PXA_RES_S;
} else {
// Fits in millisecond resolution
val = US2MS(timeout) & UINT_MAX;
res = PXA_RES_MS;
}
}
TRACE(("arch_timer_set_hardware_timer(val=%lu, res=%lu)\n", val, res));
sPxaTimersBase[PXA_OIER] |= (1 << 4);
sPxaTimersBase[PXA_OMCR4] = res;
sPxaTimersBase[PXA_OSMR4] = val;
sPxaTimersBase[PXA_OSCR4] = 0; // start counting from 0 again
HardwareTimer *timer = HardwareTimer::Get();
if (timer != NULL)
timer->SetTimeout(timeout);
}
void
arch_timer_clear_hardware_timer()
{
TRACE(("arch_timer_clear_hardware_timer\n"));
sPxaTimersBase[PXA_OMCR4] = 0; // disable our timer
sPxaTimersBase[PXA_OIER] &= ~(1 << 4);
HardwareTimer *timer = HardwareTimer::Get();
if (timer != NULL)
timer->Clear();
}
int
arch_init_timer(kernel_args *args)
{
TRACE(("%s\n", __func__));
sPxaTimersArea = map_physical_memory("pxa_timers", PXA_TIMERS_PHYS_BASE,
PXA_TIMERS_SIZE, 0, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)&sPxaTimersBase);
if (sPxaTimersArea < 0)
return sPxaTimersArea;
status_t rc = get_module(B_FDT_MODULE_NAME, (module_info**)&sFdtModule);
if (rc != B_OK)
panic("Unable to get FDT module: %08lx!\n", rc);
sPxaTimersBase[PXA_OIER] |= (1 << 5); // enable timekeeping timer
sPxaTimersBase[PXA_OMCR5] = PXA_RES_US | (1 << 7);
sPxaTimersBase[PXA_OSMR5] = UINT_MAX;
sPxaTimersBase[PXA_OSCR5] = 0;
install_io_interrupt_handler(PXA_TIMERS_INTERRUPT, &pxa_timer_interrupt, NULL, 0);
rc = sFdtModule->setup_devices(intc_table, intc_count, NULL);
if (rc != B_OK)
panic("No interrupt controllers found!\n");
return B_OK;
}
@@ -127,10 +82,9 @@ arch_init_timer(kernel_args *args)
bigtime_t
system_time(void)
{
if (sPxaTimersArea < 0)
return 0;
HardwareTimer *timer = HardwareTimer::Get();
if (timer != NULL)
return timer->Time();
return (sPxaTimersBase != NULL) ?
sSystemTime + sPxaTimersBase[PXA_OSCR5] :
0ULL;
return 0;
}
+4
View File
@@ -0,0 +1,4 @@
#include "soc.h"
InterruptController *InterruptController::sInstance = NULL;
HardwareTimer *HardwareTimer::sInstance = NULL;
+68
View File
@@ -0,0 +1,68 @@
#ifndef ARCH_ARM_SOC_H
#define ARCH_ARM_SOC_H
class InterruptController;
#include <drivers/bus/FDT.h>
#include <private/kernel/int.h>
#include <private/kernel/timer.h>
// ------------------------------------------------------ InterruptController
class InterruptController {
public:
virtual void EnableInterrupt(int irq) = 0;
virtual void DisableInterrupt(int irq) = 0;
virtual void HandleInterrupt() = 0;
static InterruptController* Get() {
return sInstance;
}
protected:
InterruptController(fdt_module_info *fdtModule, fdt_device_node node)
: fFDT(fdtModule), fNode(node) {
if (sInstance) {
panic("Multiple InterruptController objects created; that is currently unsupported!");
}
sInstance = this;
}
// Keep our node around as we might want to grab attributes from it
fdt_module_info *fFDT;
fdt_device_node fNode;
static InterruptController *sInstance;
};
// ------------------------------------------------------ HardwareTimer
class HardwareTimer {
public:
virtual void SetTimeout(bigtime_t timeout) = 0;
virtual bigtime_t Time() = 0;
virtual void Clear() = 0;
static HardwareTimer* Get() {
return sInstance;
}
protected:
HardwareTimer(fdt_module_info *fdtModule, fdt_device_node node)
: fFDT(fdtModule), fNode(node) {
if (sInstance) {
panic("Multiple HardwareTimer objects created; that is currently unsupported!");
}
sInstance = this;
}
// Keep our node around as we might want to grab attributes from it
fdt_module_info *fFDT;
fdt_device_node fNode;
static HardwareTimer *sInstance;
};
#endif // ARCH_ARM_SOC_H
+204
View File
@@ -0,0 +1,204 @@
#include "soc_omap3.h"
enum {
INTCPS_REVISION = 0,
INTCPS_SYSCONFIG = 4,
INTCPS_SYSSTATUS,
INTCPS_SIR_IRQ = 16,
INTCPS_SIR_FIQ = 17,
INTCPS_CONTROL = 18,
INTCPS_PROTECTION = 19,
INTCPS_IDLE = 20,
INTCPS_IRQ_PRIORITY = 24,
INTCPS_FIQ_PRIORITY = 25,
INTCPS_THRESHOLD = 26,
INTCPS_ITRn = 32,
INTCPS_MIRn = 33,
INTCPS_MIR_CLEARn = 34,
INTCPS_MIR_SETn = 35,
INTCPS_ISR_SETn = 36,
INTCPS_ISR_CLEARn = 37,
INTCPS_PENDING_IRQn = 38,
INTCPS_PENDING_FIQn = 39,
INTCPS_ILRm = 40,
};
void
OMAP3InterruptController::EnableInterrupt(int irq)
{
uint32 bit = irq % 32, bank = irq / 32;
fRegBase[INTCPS_MIR_CLEARn + (8 * bank)] = 1 << bit;
}
void
OMAP3InterruptController::DisableInterrupt(int irq)
{
uint32 bit = irq % 32, bank = irq / 32;
fRegBase[INTCPS_MIR_SETn + (8 * bank)] = 1 << bit;
}
void
OMAP3InterruptController::HandleInterrupt()
{
bool handledIRQ = false;
int irqnr = 0;
do {
for (uint32 i=0; i < fNumPending; i++) {
irqnr = fRegBase[INTCPS_PENDING_IRQn + (8 * i)];
if (irqnr)
break;
}
if (!irqnr)
break;
irqnr = fRegBase[INTCPS_SIR_IRQ];
irqnr &= 0x7f; /* ACTIVEIRQ */
if (irqnr) {
int_io_interrupt_handler(irqnr, true);
handledIRQ = true;
}
} while(irqnr);
// If IRQ got cleared before we could handle it, simply
// ack it.
if (!handledIRQ)
fRegBase[INTCPS_CONTROL] = 1;
}
void
OMAP3InterruptController::SoftReset()
{
uint32 tmp = fRegBase[INTCPS_REVISION] & 0xff;
dprintf("OMAP: INTC found at 0x%p (rev %ld.%ld)\n",
fRegBase, tmp >> 4, tmp & 0xf);
tmp = fRegBase[INTCPS_SYSCONFIG];
tmp |= 1 << 1; /* soft reset */
fRegBase[INTCPS_SYSCONFIG] = tmp;
while (!(fRegBase[INTCPS_SYSSTATUS] & 0x1))
/* Wait for reset to complete */;
/* Enable autoidle */
fRegBase[INTCPS_SYSCONFIG] = 1;
}
OMAP3InterruptController::OMAP3InterruptController(fdt_module_info *fdt, fdt_device_node node)
: InterruptController(fdt, node),
fNumPending(3)
{
fRegArea = fFDT->map_reg_range(node, 0, (void**)&fRegBase);
if (fRegArea < 0)
panic("OMAP3InterruptController: cannot map registers!");
SoftReset();
// Enable protection (MPU registers only available in privileged mode)
fRegBase[INTCPS_PROTECTION] |= 1;
}
enum {
TIDR = 0,
TIOCP_CFG = 4,
TISTAT,
TISR,
TIER,
TWER,
TCLR,
TCRR,
TLDR,
TTGR,
TWPS,
TMAR,
TCAR1,
TSICR,
TCAR2,
TPIR,
TNIR,
TCVR,
TOCR,
TOWR,
};
int32
OMAP3Timer::_InterruptWrapper(void *data)
{
return ((OMAP3Timer*)data)->HandleInterrupt();
}
int32
OMAP3Timer::HandleInterrupt()
{
uint32 ints = fRegBase[TISR] & 7;
if (ints & 1) { // Match?
dprintf("OMAP3Timer: match!\n");
timer_interrupt();
} else if (ints & 2) { // Overflow?
dprintf("OMAP3Timer: overflow!\n");
fSystemTime += UINT_MAX +1;
} else if (ints & 4) { // Capture?
dprintf("OMAP3Timer: capture!\n");
}
// clear interrupt
fRegBase[TISR] = ints;
return B_HANDLED_INTERRUPT;
}
void
OMAP3Timer::SetTimeout(bigtime_t timeout)
{
fRegBase[TMAR] = fRegBase[TCRR] + timeout / 1000ULL;
fRegBase[TIER] |= 1; // Enable match interrupt
}
bigtime_t
OMAP3Timer::Time()
{
return fSystemTime + fRegBase[TCRR];
}
void
OMAP3Timer::Clear()
{
fRegBase[TIER] &= ~1; // Disable match interrupt
}
OMAP3Timer::OMAP3Timer(fdt_module_info *fdtModule, fdt_device_node node)
: HardwareTimer(fdtModule, node),
fSystemTime(0)
{
fRegArea = fFDT->map_reg_range(node, 0, (void**)&fRegBase);
if (fRegArea < 0)
panic("Cannot map OMAP3Timer registers!");
fInterrupt = fFDT->get_interrupt(node, 0);
if (fInterrupt < 0)
panic("Cannot get OMAP3Timer interrupt!");
uint32 rev = fRegBase[TIDR];
dprintf("OMAP: Found timer @ 0x%p, IRQ %d (rev %ld.%ld)\n", fRegBase, fInterrupt, (rev >> 4) & 0xf, rev & 0xf);
// Let the timer run (so we can use it as clocksource)
fRegBase[TCLR] |= 1;
fRegBase[TIER] = 2; // Enable overflow interrupt
install_io_interrupt_handler(fInterrupt, &OMAP3Timer::_InterruptWrapper, this, 0);
}
+62
View File
@@ -0,0 +1,62 @@
#ifndef ARCH_ARM_SOC_OMAP3_H
#define ARCH_ARM_SOC_OMAP3_H
class OMAP3InterruptController;
#include "soc.h"
#include <new>
class OMAP3InterruptController : public InterruptController {
public:
void EnableInterrupt(int irq);
void DisableInterrupt(int irq);
void HandleInterrupt();
static status_t Init(fdt_module_info *fdt, fdt_device_node node, void *cookie) {
InterruptController *ic = new(std::nothrow) OMAP3InterruptController(fdt, node);
// XXX implement InitCheck() functionality
return ic != NULL ? B_OK : B_NO_MEMORY;
}
protected:
OMAP3InterruptController(fdt_module_info *fdt, fdt_device_node node);
void SoftReset();
area_id fRegArea;
uint32 *fRegBase;
uint32 fNumPending;
};
class OMAP3Timer : public HardwareTimer {
public:
void SetTimeout(bigtime_t timeout);
bigtime_t Time();
void Clear();
static status_t Init(fdt_module_info *fdt, fdt_device_node node, void *cookie) {
if (sInstance == NULL) {
OMAP3Timer *timer = new(std::nothrow) OMAP3Timer(fdt, node);
// XXX implement InitCheck() functionality
return timer != NULL ? B_OK : B_NO_MEMORY;
} else {
// XXX We have multiple timers; just create the first one
// and ignore the rest
return B_OK;
}
}
private:
OMAP3Timer(fdt_module_info *fdtModule, fdt_device_node node);
static int32 _InterruptWrapper(void *data);
int32 HandleInterrupt();
bigtime_t fSystemTime;
area_id fRegArea;
uint32 *fRegBase;
int fInterrupt;
};
#endif /* ARCH_ARM_SOC_OMAP3_H */
+154
View File
@@ -0,0 +1,154 @@
#include "soc_pxa.h"
/* PXA Interrupt Controller Registers */
#define PXA_ICIP 0x00
#define PXA_ICMR 0x01
#define PXA_ICFP 0x03
#define PXA_ICMR2 0x28
void
PXAInterruptController::EnableInterrupt(int irq)
{
if (irq <= 31) {
fRegBase[PXA_ICMR] |= 1 << irq;
return;
}
fRegBase[PXA_ICMR2] |= 1 << (irq - 32);
}
void
PXAInterruptController::DisableInterrupt(int irq)
{
if (irq <= 31) {
fRegBase[PXA_ICMR] &= ~(1 << irq);
return;
}
fRegBase[PXA_ICMR2] &= ~(1 << (irq - 32));
}
void
PXAInterruptController::HandleInterrupt()
{
for (int i=0; i < 32; i++) {
if (fRegBase[PXA_ICIP] & (1 << i))
int_io_interrupt_handler(i, true);
}
}
PXAInterruptController::PXAInterruptController(fdt_module_info *fdt, fdt_device_node node)
: InterruptController(fdt, node) {
fRegArea = fFDT->map_reg_range(node, 0, (void**)&fRegBase);
if (fRegArea < 0)
panic("PXAInterruptController: cannot map registers!");
fRegBase[PXA_ICMR] = 0;
fRegBase[PXA_ICMR2] = 0;
}
#define PXA_TIMERS_INTERRUPT 7 /* OST_4_11 */
#define PXA_OSSR 0x05
#define PXA_OIER 0x07
#define PXA_OSCR4 0x10
#define PXA_OSCR5 0x11
#define PXA_OSMR4 0x20
#define PXA_OSMR5 0x21
#define PXA_OMCR4 0x30
#define PXA_OMCR5 0x31
#define PXA_RES_S (3 << 0)
#define PXA_RES_MS (1 << 1)
#define PXA_RES_US (1 << 2)
#define US2S(bt) ((bt) / 1000000ULL)
#define US2MS(bt) ((bt) / 1000ULL)
void
PXATimer::SetTimeout(bigtime_t timeout)
{
uint32 val = timeout & UINT_MAX;
uint32 res = PXA_RES_US;
if (timeout & ~UINT_MAX) {
// Does not fit, so scale resolution down to milliseconds
if (US2MS(timeout) & ~UINT_MAX) {
// Still does not fit, scale down to seconds as last ditch attempt
val = US2S(timeout) & UINT_MAX;
res = PXA_RES_S;
} else {
// Fits in millisecond resolution
val = US2MS(timeout) & UINT_MAX;
res = PXA_RES_MS;
}
}
dprintf("arch_timer_set_hardware_timer(val=%lu, res=%lu)\n", val, res);
fRegBase[PXA_OIER] |= (1 << 4);
fRegBase[PXA_OMCR4] = res;
fRegBase[PXA_OSMR4] = val;
fRegBase[PXA_OSCR4] = 0; // start counting from 0 again
}
void
PXATimer::Clear()
{
fRegBase[PXA_OMCR4] = 0; // disable our timer
fRegBase[PXA_OIER] &= ~(1 << 4);
}
bigtime_t
PXATimer::Time()
{
if (fRegArea < 0)
return 0;
return (fRegBase != NULL) ?
fSystemTime + fRegBase[PXA_OSCR5] :
0ULL;
}
int32
PXATimer::_InterruptWrapper(void *data)
{
return ((PXATimer*)data)->HandleInterrupt();
}
int32
PXATimer::HandleInterrupt()
{
if (fRegBase[PXA_OSSR] & (1 << 4)) {
fRegBase[PXA_OSSR] |= (1 << 4);
return timer_interrupt();
}
if (fRegBase[PXA_OSSR] & (1 << 5)) {
fRegBase[PXA_OSSR] |= (1 << 5);
fSystemTime += UINT_MAX + 1ULL;
}
return B_HANDLED_INTERRUPT;
}
PXATimer::PXATimer(fdt_module_info *fdt, fdt_device_node node)
: HardwareTimer(fdt, node)
{
fRegArea = fFDT->map_reg_range(node, 0, (void**)&fRegBase);
if (fRegArea < 0)
panic("Cannot map PXATimer registers!");
fRegBase[PXA_OIER] |= (1 << 5); // enable timekeeping timer
fRegBase[PXA_OMCR5] = PXA_RES_US | (1 << 7);
fRegBase[PXA_OSMR5] = UINT_MAX;
fRegBase[PXA_OSCR5] = 0;
install_io_interrupt_handler(PXA_TIMERS_INTERRUPT, &PXATimer::_InterruptWrapper, NULL, 0);
}
+55
View File
@@ -0,0 +1,55 @@
#ifndef ARCH_ARM_SOC_PXA_H
#define ARCH_ARM_SOC_PXA_H
class PXAInterruptController;
#include "soc.h"
#include <new>
class PXAInterruptController : public InterruptController {
public:
void EnableInterrupt(int irq);
void DisableInterrupt(int irq);
void HandleInterrupt();
static status_t Init(fdt_module_info *fdt, fdt_device_node node, void *cookie) {
InterruptController *ic = new(std::nothrow) PXAInterruptController(fdt, node);
// XXX implement InitCheck() functionality
return ic != NULL ? B_OK : B_NO_MEMORY;
}
protected:
PXAInterruptController(fdt_module_info *fdt, fdt_device_node node);
area_id fRegArea;
uint32 *fRegBase;
};
class PXATimer : public HardwareTimer {
public:
void SetTimeout(bigtime_t timeout);
void Clear();
bigtime_t Time();
static status_t Init(fdt_module_info *fdt, fdt_device_node node, void *cookie) {
PXATimer *timer = new(std::nothrow) PXATimer(fdt, node);
// XXX implement InitCheck() functionality
return timer != NULL ? B_OK : B_NO_MEMORY;
}
protected:
PXATimer(fdt_module_info *fdt, fdt_device_node node);
area_id fRegArea;
uint32 *fRegBase;
bigtime_t fSystemTime;
private:
static int32 _InterruptWrapper(void *data);
int32 HandleInterrupt();
};
#endif // ARCH_ARM_SOC_PXA_H