#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <dev/ofw/openfirm.h>
#include <machine/autoconf.h>
#include <machine/intr.h>
struct intr_handle {
struct intr_controller *ih_ic;
void *ih_ih;
};
struct intr_controller *octeon_ic;
LIST_HEAD(, intr_controller) octeon_ic_list =
LIST_HEAD_INITIALIZER(octeon_ic_list);
void
octeon_intr_register(struct intr_controller *ic)
{
struct intr_controller *tmp;
if (octeon_ic == NULL)
octeon_ic = ic;
ic->ic_phandle = OF_getpropint(ic->ic_node, "phandle", 0);
if (ic->ic_phandle == 0)
return;
LIST_FOREACH(tmp, &octeon_ic_list, ic_list) {
if (tmp->ic_phandle == ic->ic_phandle) {
printf("%s: node %d: duplicate phandle %d\n",
__func__, ic->ic_node, ic->ic_phandle);
return;
}
}
LIST_INSERT_HEAD(&octeon_ic_list, ic, ic_list);
}
void
octeon_intr_init(void)
{
octeon_ic->ic_init();
}
void *
octeon_intr_establish(int irq, int level,
int (*ih_fun)(void *), void *ih_arg, const char *ih_what)
{
struct intr_controller *ic = octeon_ic;
struct intr_handle *ih;
void *handler;
ih = malloc(sizeof(*ih), M_DEVBUF, M_NOWAIT);
if (ih == NULL)
return NULL;
handler = ic->ic_establish(irq, level, ih_fun, ih_arg, ih_what);
if (handler == NULL) {
free(ih, M_DEVBUF, sizeof(*ih));
return NULL;
}
ih->ih_ic = ic;
ih->ih_ih = handler;
return ih;
}
void *
octeon_intr_establish_fdt(int node, int level,
int (*ih_fun)(void *), void *ih_arg, const char *ih_what)
{
return octeon_intr_establish_fdt_idx(node, 0, level, ih_fun,
ih_arg, ih_what);
}
void *
octeon_intr_establish_fdt_idx(int node, int idx, int level,
int (*ih_fun)(void *), void *ih_arg, const char *ih_what)
{
struct intr_controller *ic = NULL;
struct intr_handle *ih;
void *handler;
int phandle;
phandle = OF_getpropint(node, "interrupt-parent", 1);
if (phandle < 1)
return NULL;
LIST_FOREACH(ic, &octeon_ic_list, ic_list) {
if (ic->ic_phandle == phandle)
break;
}
if (ic == NULL)
return NULL;
ih = malloc(sizeof(*ih), M_DEVBUF, M_NOWAIT);
if (ih == NULL)
return NULL;
handler = ic->ic_establish_fdt_idx(ic->ic_cookie, node, idx, level,
ih_fun, ih_arg, ih_what);
if (handler == NULL) {
free(ih, M_DEVBUF, sizeof(*ih));
return NULL;
}
ih->ih_ic = ic;
ih->ih_ih = handler;
return ih;
}
void
octeon_intr_disestablish(void *cookie)
{
struct intr_handle *ih = cookie;
struct intr_controller *ic = ih->ih_ic;
ic->ic_disestablish(ih->ih_ih);
free(ih, M_DEVBUF, sizeof(*ih));
}
void
octeon_intr_disestablish_fdt(void *cookie)
{
octeon_intr_disestablish(cookie);
}
void
intr_barrier(void *cookie)
{
struct intr_handle *ih = cookie;
struct intr_controller *ic = ih->ih_ic;
ic->ic_intr_barrier(ih->ih_ih);
}
#ifdef MULTIPROCESSOR
int
hw_ipi_intr_establish(int (*func)(void *), u_long cpuid)
{
return octeon_ic->ic_ipi_establish(func, cpuid);
}
void
hw_ipi_intr_set(u_long cpuid)
{
octeon_ic->ic_ipi_set(cpuid);
}
void
hw_ipi_intr_clear(u_long cpuid)
{
octeon_ic->ic_ipi_clear(cpuid);
}
#endif