#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: interrupts.c,v 1.12 2026/03/24 07:30:19 macallan Exp $");
#include "opt_multiprocessor.h"
#include <sys/param.h>
#include <sys/kernel.h>
#include <prop/proplib.h>
#include <machine/intr.h>
#include <machine/autoconf.h>
#include <powerpc/pic/picvar.h>
#include <powerpc/pic/ipivar.h>
#include <dev/ofw/openfirm.h>
#include <powerpc/oea/cpufeat.h>
#include "opt_interrupt.h"
#include "pic_openpic.h"
#include "pic_ohare.h"
#include "pic_heathrow.h"
#include "pic_u3_ht.h"
#include "opt_ipi.h"
#include "ipi_openpic.h"
#include "ipi_hammerhead.h"
#if NPIC_OPENPIC > 0
static int init_openpic(int);
const char *compat[] = {
"chrp,open-pic",
"open-pic",
"openpic",
NULL
};
static int
init_openpic(int pass_through)
{
struct pic_ops *opic;
uint32_t reg[5];
uint32_t obio_base, pic_base;
int pic, macio;
macio = OF_finddevice("/pci/mac-io");
if (macio == -1)
macio = OF_finddevice("mac-io");
if (macio == -1)
macio = OF_finddevice("/ht/pci/mac-io");
if (macio == -1)
return FALSE;
aprint_debug("macio: %08x\n", macio);
pic = OF_child(macio);
while ((pic != 0) && !of_compatible(pic, compat))
pic = OF_peer(pic);
aprint_debug("pic: %08x\n", pic);
if ((pic == -1) || (pic == 0))
return FALSE;
if (OF_getprop(macio, "assigned-addresses", reg, sizeof(reg)) != 20)
return FALSE;
obio_base = reg[2];
aprint_debug("obio-base: %08x\n", obio_base);
if (OF_getprop(pic, "reg", reg, 8) < 8)
return FALSE;
pic_base = obio_base + reg[0];
aprint_debug("pic-base: %08x\n", pic_base);
aprint_normal("found openpic PIC at %08x\n", pic_base);
opic = setup_openpic(oea_mapiodev(pic_base, 0x40000), pass_through);
if (opic != NULL)
opic->pic_cookie = (void *)pic_base;
return TRUE;
}
#endif
void
init_interrupt(void)
{
int ok = 0;
pic_init();
#if NPIC_OHARE > 0
if (init_ohare())
goto done;
#endif
#if NPIC_HEATHROW > 0
if (init_heathrow())
goto done;
#endif
#if NPIC_OPENPIC > 0
if (init_openpic(0)) {
#ifdef MULTIPROCESSOR
setup_openpic_ipi();
#endif
ok = 1;
}
#endif
#if NPIC_U3_HT > 0
if (init_u3_ht())
ok = 1;
#endif
if (ok == 0)
panic("%s: no supported interrupt controller found", __func__);
#if NPIC_OHARE + NPIC_HEATHROW > 0
done:
#endif
oea_install_extint(pic_ext_intr);
#ifdef MULTIPROCESSOR
#if (NPIC_OHARE + NPIC_HEATHROW) > 0
if (OF_finddevice("/hammerhead") != -1)
setup_hammerhead_ipi();
#endif
#endif
}
int
OF_get_intr(int node, char *buf, int buflen, int *type)
{
int intr[2], irq, intrparent;
uint32_t picbase;
if(OF_getprop(node, "interrupts", intr, 8) != 8) {
aprint_error(": can't find interrupt\n");
return -1;
}
irq = intr[0];
if (type != NULL) {
*type = (intr[1] & 1) ? IST_LEVEL : IST_EDGE;
}
if (OF_getprop(node, "interrupt-parent", &intrparent, 4) == 4) {
uint32_t preg[8];
struct pic_ops *pic;
if(OF_getprop(intrparent, "reg", preg, 8) > 4) {
picbase = preg[0];
if ((picbase & 0x80000000) == 0) {
int mio = OF_parent(intrparent);
if (OF_getprop(mio, "ranges", preg, 20) == 20)
picbase += preg[3];
}
pic = find_pic_by_cookie((void *)picbase);
if (pic != NULL) {
irq = intr[0];
if (buf != NULL) {
snprintf(buf, buflen, "%s irq %d",
pic->pic_name, irq);
}
irq += pic->pic_intrbase;
return irq;
}
}
aprint_error("failed to find a PIC for node %08x\n",
intrparent);
return -1;
}
if (buf != NULL) {
snprintf(buf, buflen, "irq %d", irq);
}
return irq;
}