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_GICV2 "gicv2"
|
||||||
#define INTC_KIND_OMAP3 "omap3"
|
#define INTC_KIND_OMAP3 "omap3"
|
||||||
#define INTC_KIND_PXA "pxa"
|
#define INTC_KIND_PXA "pxa"
|
||||||
|
#define INTC_KIND_SUN4I "sun4i"
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ const struct supported_interrupt_controllers {
|
|||||||
{ "arm,gic-400", INTC_KIND_GICV2 },
|
{ "arm,gic-400", INTC_KIND_GICV2 },
|
||||||
{ "ti,omap3-intc", INTC_KIND_OMAP3 },
|
{ "ti,omap3-intc", INTC_KIND_OMAP3 },
|
||||||
{ "marvell,pxa-intc", INTC_KIND_PXA },
|
{ "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.cpp
|
||||||
soc_pxa.cpp
|
soc_pxa.cpp
|
||||||
soc_omap3.cpp
|
soc_omap3.cpp
|
||||||
|
soc_sun4i.cpp
|
||||||
|
|
||||||
# paging
|
# paging
|
||||||
arm_physical_page_mapper_large_memory.cpp
|
arm_physical_page_mapper_large_memory.cpp
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
|
|
||||||
#include "soc_pxa.h"
|
#include "soc_pxa.h"
|
||||||
#include "soc_omap3.h"
|
#include "soc_omap3.h"
|
||||||
|
#include "soc_sun4i.h"
|
||||||
|
|
||||||
#define TRACE_ARCH_INT
|
#define TRACE_ARCH_INT
|
||||||
#ifdef 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);
|
args->arch_args.interrupt_controller.regs1.start);
|
||||||
if (ic == NULL)
|
if (ic == NULL)
|
||||||
return B_NO_MEMORY;
|
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 {
|
} else {
|
||||||
panic("No interrupt controllers found!\n");
|
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