svn commit: r191872 - projects/mips/sys/mips/atheros
Oleksandr Tymoshenko
gonzo at FreeBSD.org
Thu May 7 03:39:25 UTC 2009
Author: gonzo
Date: Thu May 7 03:39:23 2009
New Revision: 191872
URL: http://svn.freebsd.org/changeset/base/191872
Log:
- Add interrupt handling for AR71XX PCI bridge
Modified:
projects/mips/sys/mips/atheros/ar71xx_pci.c
projects/mips/sys/mips/atheros/ar71xxreg.h
Modified: projects/mips/sys/mips/atheros/ar71xx_pci.c
==============================================================================
--- projects/mips/sys/mips/atheros/ar71xx_pci.c Thu May 7 03:23:22 2009 (r191871)
+++ projects/mips/sys/mips/atheros/ar71xx_pci.c Thu May 7 03:39:23 2009 (r191872)
@@ -68,10 +68,34 @@ struct ar71xx_pci_softc {
struct rman sc_mem_rman;
struct rman sc_irq_rman;
+ struct intr_event *sc_eventstab[AR71XX_PCI_NIRQS];
struct resource *sc_irq;
void *sc_ih;
};
+static int ar71xx_pci_setup_intr(device_t, device_t, struct resource *, int,
+ driver_filter_t *, driver_intr_t *, void *, void **);
+static int ar71xx_pci_teardown_intr(device_t, device_t, struct resource *,
+ void *);
+static int ar71xx_pci_intr(void *);
+
+static void ar71xx_pci_mask_irq(unsigned int irq)
+{
+ uint32_t reg;
+
+ reg = ATH_READ_REG(AR71XX_PCI_INTR_MASK);
+ ATH_WRITE_REG(AR71XX_PCI_INTR_MASK, reg & ~(1 << irq));
+
+}
+
+static void ar71xx_pci_unmask_irq(unsigned int irq)
+{
+ uint32_t reg;
+
+ reg = ATH_READ_REG(AR71XX_PCI_INTR_MASK);
+ ATH_WRITE_REG(AR71XX_PCI_INTR_MASK, reg | (1 << irq));
+}
+
/*
* get bitmask for bytes of interest:
* 0 - we want this byte, 1 - ignore it. e.g: we read 1 byte
@@ -213,13 +237,6 @@ ar71xx_pci_write_config(device_t dev, in
}
static int
-at71xx_pci_intr(void *v)
-{
- panic("Implement me: %s\n", __func__);
- return FILTER_HANDLED;
-}
-
-static int
ar71xx_pci_probe(device_t dev)
{
@@ -261,7 +278,7 @@ ar71xx_pci_attach(device_t dev)
}
if ((bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_MISC,
- at71xx_pci_intr, NULL, sc, &sc->sc_ih))) {
+ ar71xx_pci_intr, NULL, sc, &sc->sc_ih))) {
device_printf(dev,
"WARNING: unable to register interrupt handler\n");
return ENXIO;
@@ -369,11 +386,85 @@ ar71xx_pci_alloc_resource(device_t bus,
}
static int
-ar71xx_pci_teardown_intr(device_t dev, device_t child, struct resource *res,
+ar71xx_pci_setup_intr(device_t bus, device_t child, struct resource *ires,
+ int flags, driver_filter_t *filt, driver_intr_t *handler,
+ void *arg, void **cookiep)
+{
+ struct ar71xx_pci_softc *sc = device_get_softc(bus);
+ struct intr_event *event;
+ int irq, error;
+
+ irq = rman_get_start(ires);
+
+ if (irq > AR71XX_PCI_IRQ_END)
+ panic("%s: bad irq %d", __func__, irq);
+
+ event = sc->sc_eventstab[irq];
+ if (event == NULL) {
+ error = intr_event_create(&event, (void *)irq, 0, irq,
+ (mask_fn)ar71xx_pci_mask_irq,
+ (mask_fn)ar71xx_pci_unmask_irq,
+ NULL, NULL,
+ "ar71xx_pci intr%d:", irq);
+
+ sc->sc_eventstab[irq] = event;
+ }
+
+ intr_event_add_handler(event, device_get_nameunit(child), filt,
+ handler, arg, intr_priority(flags), flags, cookiep);
+
+ ar71xx_pci_unmask_irq(irq);
+
+ return (0);
+}
+
+static int
+ar71xx_pci_teardown_intr(device_t dev, device_t child, struct resource *ires,
void *cookie)
{
+ struct ar71xx_pci_softc *sc = device_get_softc(dev);
+ int irq, result;
+
+ irq = rman_get_start(ires);
+ if (irq > AR71XX_PCI_IRQ_END)
+ panic("%s: bad irq %d", __func__, irq);
+
+ if (sc->sc_eventstab[irq] == NULL)
+ panic("Trying to teardown unoccupied IRQ");
+
+ ar71xx_pci_mask_irq(irq);
+
+ result = intr_event_remove_handler(cookie);
+ if (!result)
+ sc->sc_eventstab[irq] = NULL;
+
+ return (result);
+}
+
+static int
+ar71xx_pci_intr(void *arg)
+{
+ struct ar71xx_pci_softc *sc = arg;
+ struct intr_event *event;
+ uint32_t reg, irq;
+
+ reg = ATH_READ_REG(AR71XX_PCI_INTR_STATUS);
+ for (irq = AR71XX_PCI_IRQ_START; irq <= AR71XX_PCI_IRQ_END; irq++) {
+ if (reg & (1 << irq)) {
+ event = sc->sc_eventstab[irq];
+ if (!event || TAILQ_EMPTY(&event->ie_handlers)) {
+ /* Ignore timer interrupts */
+ if (irq != 0)
+ printf("Stray IRQ %d\n", irq);
+ continue;
+ }
+
+ /* TODO: frame instead of NULL? */
+ intr_event_handle(event, NULL);
+ }
+ }
- return (intr_event_remove_handler(cookie));
+ return (FILTER_HANDLED);
}
static int
@@ -406,7 +497,7 @@ static device_method_t ar71xx_pci_method
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
- DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_setup_intr, ar71xx_pci_setup_intr),
DEVMETHOD(bus_teardown_intr, ar71xx_pci_teardown_intr),
/* pcib interface */
Modified: projects/mips/sys/mips/atheros/ar71xxreg.h
==============================================================================
--- projects/mips/sys/mips/atheros/ar71xxreg.h Thu May 7 03:23:22 2009 (r191871)
+++ projects/mips/sys/mips/atheros/ar71xxreg.h Thu May 7 03:39:23 2009 (r191872)
@@ -41,6 +41,7 @@
#define AR71XX_PCI_MEM_SIZE 0x07000000
#define AR71XX_PCI_IRQ_START 0
#define AR71XX_PCI_IRQ_END 2
+#define AR71XX_PCI_NIRQS 3
/* PCI config registers */
#define AR71XX_PCI_LCONF_CMD 0x17010000
More information about the svn-src-projects
mailing list