ARM: add support for Allwinner A10 interrupt controller
Untested so far. Change-Id: I3453115599cf2112858a194173212401ae4ac1b7 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5104 Reviewed-by: Fredrik Holmqvist <[email protected]> Reviewed-by: David Karoly <[email protected]> Reviewed-by: Alex von Gluck IV <[email protected]> Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
41ed7a1ed6
commit
cda13c638d
@@ -14,6 +14,7 @@
|
||||
#define INTC_KIND_GICV2 "gicv2"
|
||||
#define INTC_KIND_OMAP3 "omap3"
|
||||
#define INTC_KIND_PXA "pxa"
|
||||
#define INTC_KIND_SUN4I "sun4i"
|
||||
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -28,6 +28,7 @@ const struct supported_interrupt_controllers {
|
||||
{ "arm,gic-400", INTC_KIND_GICV2 },
|
||||
{ "ti,omap3-intc", INTC_KIND_OMAP3 },
|
||||
{ "marvell,pxa-intc", INTC_KIND_PXA },
|
||||
{ "allwinner,sun4i-a10-ic", INTC_KIND_SUN4I },
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ KernelMergeObject kernel_arch_arm.o :
|
||||
soc.cpp
|
||||
soc_pxa.cpp
|
||||
soc_omap3.cpp
|
||||
soc_sun4i.cpp
|
||||
|
||||
# paging
|
||||
arm_physical_page_mapper_large_memory.cpp
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
|
||||
#include "soc_pxa.h"
|
||||
#include "soc_omap3.h"
|
||||
#include "soc_sun4i.h"
|
||||
|
||||
#define TRACE_ARCH_INT
|
||||
#ifdef TRACE_ARCH_INT
|
||||
@@ -180,6 +181,12 @@ arch_int_init_post_vm(kernel_args *args)
|
||||
args->arch_args.interrupt_controller.regs1.start);
|
||||
if (ic == NULL)
|
||||
return B_NO_MEMORY;
|
||||
} else if (strncmp(args->arch_args.interrupt_controller.kind, INTC_KIND_SUN4I,
|
||||
sizeof(args->arch_args.interrupt_controller.kind)) == 0) {
|
||||
InterruptController *ic = new(std::nothrow) Sun4iInterruptController(
|
||||
args->arch_args.interrupt_controller.regs1.start);
|
||||
if (ic == NULL)
|
||||
return B_NO_MEMORY;
|
||||
} else {
|
||||
panic("No interrupt controllers found!\n");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2022, Adrien Destugues, [email protected]
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include <vm/vm.h>
|
||||
|
||||
#include "soc_sun4i.h"
|
||||
|
||||
|
||||
#define SUN4I_INTC_PEND_REG0 0x10
|
||||
#define SUN4I_INTC_PEND_REG1 0x14
|
||||
#define SUN4I_INTC_PEND_REG2 0x18
|
||||
#define SUN4I_INTC_MASK_REG0 0x50
|
||||
#define SUN4I_INTC_MASK_REG1 0x54
|
||||
#define SUN4I_INTC_MASK_REG2 0x58
|
||||
|
||||
|
||||
void
|
||||
Sun4iInterruptController::EnableInterrupt(int irq)
|
||||
{
|
||||
if (irq <= 31) {
|
||||
fRegBase[SUN4I_INTC_MASK_REG0] |= 1 << irq;
|
||||
return;
|
||||
}
|
||||
|
||||
if (irq <= 63) {
|
||||
fRegBase[SUN4I_INTC_MASK_REG1] |= 1 << (irq - 32);
|
||||
return;
|
||||
}
|
||||
|
||||
fRegBase[SUN4I_INTC_MASK_REG2] |= 1 << (irq - 64);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Sun4iInterruptController::DisableInterrupt(int irq)
|
||||
{
|
||||
if (irq <= 31) {
|
||||
fRegBase[SUN4I_INTC_MASK_REG0] &= ~(1 << irq);
|
||||
return;
|
||||
}
|
||||
|
||||
if (irq <= 63) {
|
||||
fRegBase[SUN4I_INTC_MASK_REG1] &= ~(1 << (irq - 32));
|
||||
return;
|
||||
}
|
||||
|
||||
fRegBase[SUN4I_INTC_MASK_REG1] &= ~(1 << (irq - 64));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Sun4iInterruptController::HandleInterrupt()
|
||||
{
|
||||
// FIXME can we use the hardware managed interrupt vector instead?
|
||||
for (int i=0; i < 32; i++) {
|
||||
if (fRegBase[SUN4I_INTC_PEND_REG0] & (1 << i))
|
||||
int_io_interrupt_handler(i, true);
|
||||
}
|
||||
|
||||
for (int i=0; i < 32; i++) {
|
||||
if (fRegBase[SUN4I_INTC_PEND_REG1] & (1 << i))
|
||||
int_io_interrupt_handler(i + 32, true);
|
||||
}
|
||||
|
||||
for (int i=0; i < 32; i++) {
|
||||
if (fRegBase[SUN4I_INTC_PEND_REG2] & (1 << i))
|
||||
int_io_interrupt_handler(i + 64, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Sun4iInterruptController::Sun4iInterruptController(uint32_t reg_base)
|
||||
{
|
||||
fRegArea = vm_map_physical_memory(B_SYSTEM_TEAM, "intc-sun4i", (void**)&fRegBase,
|
||||
B_ANY_KERNEL_ADDRESS, B_PAGE_SIZE, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA,
|
||||
reg_base, false);
|
||||
if (fRegArea < 0)
|
||||
panic("Sun4iInterruptController: cannot map registers!");
|
||||
|
||||
fRegBase[SUN4I_INTC_MASK_REG0] = 0;
|
||||
fRegBase[SUN4I_INTC_MASK_REG1] = 0;
|
||||
fRegBase[SUN4I_INTC_MASK_REG2] = 0;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2022, Adrien Destugues, [email protected]
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef ARCH_ARM_SOC_SUN4I_H
|
||||
#define ARCH_ARM_SOC_SUN4I_H
|
||||
|
||||
|
||||
#include "soc.h"
|
||||
|
||||
|
||||
class Sun4iInterruptController : public InterruptController {
|
||||
public:
|
||||
Sun4iInterruptController(uint32_t reg_base);
|
||||
void EnableInterrupt(int irq);
|
||||
void DisableInterrupt(int irq);
|
||||
void HandleInterrupt();
|
||||
|
||||
protected:
|
||||
area_id fRegArea;
|
||||
uint32 *fRegBase;
|
||||
};
|
||||
|
||||
|
||||
#endif /* !SOC_SUN4I_H */
|
||||
Reference in New Issue
Block a user