Changeset View
Changeset View
Standalone View
Standalone View
head/sys/arm/ralink/rt1310_intc.c
Show First 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | |||||
#include <dev/ofw/ofw_bus.h> | #include <dev/ofw/ofw_bus.h> | ||||
#include <dev/ofw/ofw_bus_subr.h> | #include <dev/ofw/ofw_bus_subr.h> | ||||
#include <arm/ralink/rt1310reg.h> | #include <arm/ralink/rt1310reg.h> | ||||
#define INTC_NIRQS 32 | #define INTC_NIRQS 32 | ||||
#ifdef INTRNG | |||||
#include "pic_if.h" | #include "pic_if.h" | ||||
struct rt1310_irqsrc { | struct rt1310_irqsrc { | ||||
struct intr_irqsrc ri_isrc; | struct intr_irqsrc ri_isrc; | ||||
u_int ri_irq; | u_int ri_irq; | ||||
}; | }; | ||||
#endif | |||||
struct rt1310_intc_softc { | struct rt1310_intc_softc { | ||||
device_t dev; | device_t dev; | ||||
struct resource * ri_res; | struct resource * ri_res; | ||||
bus_space_tag_t ri_bst; | bus_space_tag_t ri_bst; | ||||
bus_space_handle_t ri_bsh; | bus_space_handle_t ri_bsh; | ||||
#ifdef INTRNG | |||||
struct rt1310_irqsrc ri_isrcs[INTC_NIRQS]; | struct rt1310_irqsrc ri_isrcs[INTC_NIRQS]; | ||||
#endif | |||||
}; | }; | ||||
static int rt1310_intc_probe(device_t); | static int rt1310_intc_probe(device_t); | ||||
static int rt1310_intc_attach(device_t); | static int rt1310_intc_attach(device_t); | ||||
#ifndef INTRNG | |||||
static void rt1310_intc_eoi(void *); | |||||
#else | |||||
static int rt1310_pic_attach(struct rt1310_intc_softc *sc); | static int rt1310_pic_attach(struct rt1310_intc_softc *sc); | ||||
#endif | |||||
static struct rt1310_intc_softc *intc_softc = NULL; | static struct rt1310_intc_softc *intc_softc = NULL; | ||||
#define intc_read_4(_sc, _reg) \ | #define intc_read_4(_sc, _reg) \ | ||||
bus_space_read_4((_sc)->ri_bst, (_sc)->ri_bsh, (_reg)) | bus_space_read_4((_sc)->ri_bst, (_sc)->ri_bsh, (_reg)) | ||||
#define intc_write_4(_sc, _reg, _val) \ | #define intc_write_4(_sc, _reg, _val) \ | ||||
bus_space_write_4((_sc)->ri_bst, (_sc)->ri_bsh, (_reg), (_val)) | bus_space_write_4((_sc)->ri_bst, (_sc)->ri_bsh, (_reg), (_val)) | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | |||||
rt1310_intc_probe(device_t dev) | rt1310_intc_probe(device_t dev) | ||||
{ | { | ||||
if (!ofw_bus_status_okay(dev)) | if (!ofw_bus_status_okay(dev)) | ||||
return (ENXIO); | return (ENXIO); | ||||
if (!ofw_bus_is_compatible_strict(dev, "rt,pic")) | if (!ofw_bus_is_compatible_strict(dev, "rt,pic")) | ||||
return (ENXIO); | return (ENXIO); | ||||
#ifdef INTRNG | |||||
device_set_desc(dev, "RT1310 INTRNG Interrupt Controller"); | |||||
#else | |||||
device_set_desc(dev, "RT1310 Interrupt Controller"); | device_set_desc(dev, "RT1310 Interrupt Controller"); | ||||
#endif | |||||
return (BUS_PROBE_DEFAULT); | return (BUS_PROBE_DEFAULT); | ||||
} | } | ||||
static int | static int | ||||
rt1310_intc_attach(device_t dev) | rt1310_intc_attach(device_t dev) | ||||
{ | { | ||||
struct rt1310_intc_softc *sc = device_get_softc(dev); | struct rt1310_intc_softc *sc = device_get_softc(dev); | ||||
int rid = 0; | int rid = 0; | ||||
Show All 9 Lines | rt1310_intc_attach(device_t dev) | ||||
if (!sc->ri_res) { | if (!sc->ri_res) { | ||||
device_printf(dev, "could not alloc resources\n"); | device_printf(dev, "could not alloc resources\n"); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
sc->ri_bst = rman_get_bustag(sc->ri_res); | sc->ri_bst = rman_get_bustag(sc->ri_res); | ||||
sc->ri_bsh = rman_get_bushandle(sc->ri_res); | sc->ri_bsh = rman_get_bushandle(sc->ri_res); | ||||
intc_softc = sc; | intc_softc = sc; | ||||
#ifndef INTRNG | |||||
arm_post_filter = rt1310_intc_eoi; | |||||
#else | |||||
rt1310_pic_attach(sc); | rt1310_pic_attach(sc); | ||||
#endif | |||||
intc_write_4(sc, RT_INTC_IECR, 0); | intc_write_4(sc, RT_INTC_IECR, 0); | ||||
intc_write_4(sc, RT_INTC_ICCR, ~0); | intc_write_4(sc, RT_INTC_ICCR, ~0); | ||||
for (i = 0; i <= INTC_NIRQS; ++i) { | for (i = 0; i <= INTC_NIRQS; ++i) { | ||||
intc_write_4(sc, RT_INTC_SCR0+i*4, | intc_write_4(sc, RT_INTC_SCR0+i*4, | ||||
(irqdef[i].ri_trig << RT_INTC_TRIG_SHIF) | | (irqdef[i].ri_trig << RT_INTC_TRIG_SHIF) | | ||||
irqdef[i].ri_prio); | irqdef[i].ri_prio); | ||||
intc_write_4(sc, RT_INTC_SVR0+i*4, i); | intc_write_4(sc, RT_INTC_SVR0+i*4, i); | ||||
} | } | ||||
/* Clear interrupt status registers and disable all interrupts */ | /* Clear interrupt status registers and disable all interrupts */ | ||||
intc_write_4(sc, RT_INTC_ICCR, ~0); | intc_write_4(sc, RT_INTC_ICCR, ~0); | ||||
intc_write_4(sc, RT_INTC_IMR, 0); | intc_write_4(sc, RT_INTC_IMR, 0); | ||||
return (0); | return (0); | ||||
} | } | ||||
#ifndef INTRNG | |||||
int | |||||
arm_get_next_irq(int last) | |||||
{ | |||||
struct rt1310_intc_softc *sc = intc_softc; | |||||
uint32_t value; | |||||
int i; | |||||
value = intc_read_4(sc, RT_INTC_IPR); | |||||
for (i = 0; i < 32; i++) { | |||||
if (value & (1 << i)) | |||||
return (i); | |||||
} | |||||
return (-1); | |||||
} | |||||
void | |||||
arm_mask_irq(uintptr_t nb) | |||||
{ | |||||
struct rt1310_intc_softc *sc = intc_softc; | |||||
uint32_t value; | |||||
/* Make sure that interrupt isn't active already */ | |||||
rt1310_intc_eoi((void *)nb); | |||||
/* Clear bit in ER register */ | |||||
value = intc_read_4(sc, RT_INTC_IECR); | |||||
value &= ~(1 << nb); | |||||
intc_write_4(sc, RT_INTC_IECR, value); | |||||
intc_write_4(sc, RT_INTC_IMR, value); | |||||
intc_write_4(sc, RT_INTC_ICCR, 1 << nb); | |||||
} | |||||
void | |||||
arm_unmask_irq(uintptr_t nb) | |||||
{ | |||||
struct rt1310_intc_softc *sc = intc_softc; | |||||
uint32_t value; | |||||
value = intc_read_4(sc, RT_INTC_IECR); | |||||
value |= (1 << nb); | |||||
intc_write_4(sc, RT_INTC_IMR, value); | |||||
intc_write_4(sc, RT_INTC_IECR, value); | |||||
} | |||||
static void | static void | ||||
rt1310_intc_eoi(void *data) | |||||
{ | |||||
struct rt1310_intc_softc *sc = intc_softc; | |||||
int nb = (int)data; | |||||
intc_write_4(sc, RT_INTC_ICCR, 1 << nb); | |||||
if (nb == 0) { | |||||
uint32_t value; | |||||
value = intc_read_4(sc, RT_INTC_IECR); | |||||
value &= ~(1 << nb); | |||||
intc_write_4(sc, RT_INTC_IECR, value); | |||||
intc_write_4(sc, RT_INTC_IMR, value); | |||||
} | |||||
} | |||||
#else | |||||
static void | |||||
rt1310_enable_intr(device_t dev, struct intr_irqsrc *isrc) | rt1310_enable_intr(device_t dev, struct intr_irqsrc *isrc) | ||||
{ | { | ||||
u_int irq; | u_int irq; | ||||
unsigned int value; | unsigned int value; | ||||
struct rt1310_intc_softc *sc; | struct rt1310_intc_softc *sc; | ||||
sc = intc_softc; | sc = intc_softc; | ||||
irq = ((struct rt1310_irqsrc *)isrc)->ri_irq; | irq = ((struct rt1310_irqsrc *)isrc)->ri_irq; | ||||
▲ Show 20 Lines • Show All 112 Lines • ▼ Show 20 Lines | rt1310_pic_attach(struct rt1310_intc_softc *sc) | ||||
xref = OF_xref_from_node(ofw_bus_get_node(sc->dev)); | xref = OF_xref_from_node(ofw_bus_get_node(sc->dev)); | ||||
pic = intr_pic_register(sc->dev, xref); | pic = intr_pic_register(sc->dev, xref); | ||||
if (pic == NULL) | if (pic == NULL) | ||||
return (ENXIO); | return (ENXIO); | ||||
return (intr_pic_claim_root(sc->dev, xref, rt1310_intr, sc, 0)); | return (intr_pic_claim_root(sc->dev, xref, rt1310_intr, sc, 0)); | ||||
} | } | ||||
#endif | |||||
struct fdt_fixup_entry fdt_fixup_table[] = { | struct fdt_fixup_entry fdt_fixup_table[] = { | ||||
{ NULL, NULL } | { NULL, NULL } | ||||
}; | }; | ||||
#ifndef INTRNG | |||||
static int | |||||
fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig, | |||||
int *pol) | |||||
{ | |||||
if (!fdt_is_compatible(node, "lpc,pic")) | |||||
return (ENXIO); | |||||
*interrupt = fdt32_to_cpu(intr[0]); | |||||
*trig = INTR_TRIGGER_CONFORM; | |||||
*pol = INTR_POLARITY_CONFORM; | |||||
return (0); | |||||
} | |||||
fdt_pic_decode_t fdt_pic_table[] = { | |||||
&fdt_pic_decode_ic, | |||||
NULL | |||||
}; | |||||
#endif | |||||
static device_method_t rt1310_intc_methods[] = { | static device_method_t rt1310_intc_methods[] = { | ||||
DEVMETHOD(device_probe, rt1310_intc_probe), | DEVMETHOD(device_probe, rt1310_intc_probe), | ||||
DEVMETHOD(device_attach, rt1310_intc_attach), | DEVMETHOD(device_attach, rt1310_intc_attach), | ||||
#ifdef INTRNG | |||||
DEVMETHOD(pic_disable_intr, rt1310_disable_intr), | DEVMETHOD(pic_disable_intr, rt1310_disable_intr), | ||||
DEVMETHOD(pic_enable_intr, rt1310_enable_intr), | DEVMETHOD(pic_enable_intr, rt1310_enable_intr), | ||||
DEVMETHOD(pic_map_intr, rt1310_map_intr), | DEVMETHOD(pic_map_intr, rt1310_map_intr), | ||||
DEVMETHOD(pic_post_filter, rt1310_post_filter), | DEVMETHOD(pic_post_filter, rt1310_post_filter), | ||||
DEVMETHOD(pic_post_ithread, rt1310_post_ithread), | DEVMETHOD(pic_post_ithread, rt1310_post_ithread), | ||||
DEVMETHOD(pic_pre_ithread, rt1310_pre_ithread), | DEVMETHOD(pic_pre_ithread, rt1310_pre_ithread), | ||||
#endif | |||||
{ 0, 0 } | { 0, 0 } | ||||
}; | }; | ||||
static driver_t rt1310_intc_driver = { | static driver_t rt1310_intc_driver = { | ||||
"pic", | "pic", | ||||
rt1310_intc_methods, | rt1310_intc_methods, | ||||
sizeof(struct rt1310_intc_softc), | sizeof(struct rt1310_intc_softc), | ||||
}; | }; | ||||
static devclass_t rt1310_intc_devclass; | static devclass_t rt1310_intc_devclass; | ||||
EARLY_DRIVER_MODULE(pic, simplebus, rt1310_intc_driver, rt1310_intc_devclass, 0, 0, BUS_PASS_INTERRUPT); | EARLY_DRIVER_MODULE(pic, simplebus, rt1310_intc_driver, rt1310_intc_devclass, 0, 0, BUS_PASS_INTERRUPT); |