aboutsummaryrefslogtreecommitdiff
path: root/sys/powerpc/powermac/hrowpic.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/powerpc/powermac/hrowpic.c')
-rw-r--r--sys/powerpc/powermac/hrowpic.c278
1 files changed, 278 insertions, 0 deletions
diff --git a/sys/powerpc/powermac/hrowpic.c b/sys/powerpc/powermac/hrowpic.c
new file mode 100644
index 000000000000..cd1a1f17694f
--- /dev/null
+++ b/sys/powerpc/powermac/hrowpic.c
@@ -0,0 +1,278 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright 2003 by Peter Grehan. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * A driver for the PIC found in the Heathrow/Paddington MacIO chips.
+ * This was superseded by an OpenPIC in the Keylargo and beyond
+ * MacIO versions.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/rman.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/openfirm.h>
+
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+#include <machine/md_var.h>
+#include <machine/pio.h>
+#include <machine/resource.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <powerpc/powermac/hrowpicvar.h>
+
+#include "pic_if.h"
+
+/*
+ * MacIO interface
+ */
+static int hrowpic_probe(device_t);
+static int hrowpic_attach(device_t);
+
+static void hrowpic_dispatch(device_t, struct trapframe *);
+static void hrowpic_enable(device_t, u_int, u_int, void **);
+static void hrowpic_eoi(device_t, u_int, void *);
+static void hrowpic_ipi(device_t, u_int);
+static void hrowpic_mask(device_t, u_int, void *);
+static void hrowpic_unmask(device_t, u_int, void *);
+
+static device_method_t hrowpic_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, hrowpic_probe),
+ DEVMETHOD(device_attach, hrowpic_attach),
+
+ /* PIC interface */
+ DEVMETHOD(pic_dispatch, hrowpic_dispatch),
+ DEVMETHOD(pic_enable, hrowpic_enable),
+ DEVMETHOD(pic_eoi, hrowpic_eoi),
+ DEVMETHOD(pic_ipi, hrowpic_ipi),
+ DEVMETHOD(pic_mask, hrowpic_mask),
+ DEVMETHOD(pic_unmask, hrowpic_unmask),
+
+ { 0, 0 },
+};
+
+static driver_t hrowpic_driver = {
+ "hrowpic",
+ hrowpic_methods,
+ sizeof(struct hrowpic_softc)
+};
+
+DRIVER_MODULE(hrowpic, macio, hrowpic_driver, 0, 0);
+
+static uint32_t
+hrowpic_read_reg(struct hrowpic_softc *sc, u_int reg, u_int bank)
+{
+ if (bank == HPIC_PRIMARY)
+ reg += HPIC_1ST_OFFSET;
+
+ return (bus_space_read_4(sc->sc_bt, sc->sc_bh, reg));
+}
+
+static void
+hrowpic_write_reg(struct hrowpic_softc *sc, u_int reg, u_int bank,
+ uint32_t val)
+{
+
+ if (bank == HPIC_PRIMARY)
+ reg += HPIC_1ST_OFFSET;
+
+ bus_space_write_4(sc->sc_bt, sc->sc_bh, reg, val);
+
+ /* XXX Issue a read to force the write to complete. */
+ bus_space_read_4(sc->sc_bt, sc->sc_bh, reg);
+}
+
+static int
+hrowpic_probe(device_t dev)
+{
+ const char *type = ofw_bus_get_type(dev);
+
+ /*
+ * OpenPIC cells have a type of "open-pic", so this
+ * is sufficient to identify a Heathrow cell
+ */
+ if (strcmp(type, "interrupt-controller") != 0)
+ return (ENXIO);
+
+ /*
+ * The description was already printed out in the nexus
+ * probe, so don't do it again here
+ */
+ device_set_desc(dev, "Heathrow MacIO interrupt controller");
+ return (0);
+}
+
+static int
+hrowpic_attach(device_t dev)
+{
+ struct hrowpic_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+
+ sc->sc_rrid = 0;
+ sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rrid,
+ RF_ACTIVE);
+
+ if (sc->sc_rres == NULL) {
+ device_printf(dev, "Could not alloc mem resource!\n");
+ return (ENXIO);
+ }
+
+ sc->sc_bt = rman_get_bustag(sc->sc_rres);
+ sc->sc_bh = rman_get_bushandle(sc->sc_rres);
+
+ /*
+ * Disable all interrupt sources and clear outstanding interrupts
+ */
+ hrowpic_write_reg(sc, HPIC_ENABLE, HPIC_PRIMARY, 0);
+ hrowpic_write_reg(sc, HPIC_CLEAR, HPIC_PRIMARY, 0xffffffff);
+ hrowpic_write_reg(sc, HPIC_ENABLE, HPIC_SECONDARY, 0);
+ hrowpic_write_reg(sc, HPIC_CLEAR, HPIC_SECONDARY, 0xffffffff);
+
+ powerpc_register_pic(dev, ofw_bus_get_node(dev), 64, 0, FALSE);
+ return (0);
+}
+
+/*
+ * Local routines
+ */
+
+static void
+hrowpic_toggle_irq(struct hrowpic_softc *sc, int irq, int enable)
+{
+ u_int roffset;
+ u_int rbit;
+
+ KASSERT((irq > 0) && (irq <= HROWPIC_IRQMAX), ("en irq out of range"));
+
+ /*
+ * Humor the SMP layer if it wants to set up an IPI handler.
+ */
+ if (irq == HROWPIC_IRQMAX)
+ return;
+
+ /*
+ * Calculate prim/sec register bank for the IRQ, update soft copy,
+ * and enable the IRQ as an interrupt source
+ */
+ roffset = HPIC_INT_TO_BANK(irq);
+ rbit = HPIC_INT_TO_REGBIT(irq);
+
+ if (enable)
+ sc->sc_softreg[roffset] |= (1 << rbit);
+ else
+ sc->sc_softreg[roffset] &= ~(1 << rbit);
+
+ hrowpic_write_reg(sc, HPIC_ENABLE, roffset, sc->sc_softreg[roffset]);
+}
+
+/*
+ * PIC I/F methods.
+ */
+
+static void
+hrowpic_dispatch(device_t dev, struct trapframe *tf)
+{
+ struct hrowpic_softc *sc;
+ uint64_t mask;
+ uint32_t reg;
+ u_int irq;
+
+ sc = device_get_softc(dev);
+ while (1) {
+ mask = hrowpic_read_reg(sc, HPIC_STATUS, HPIC_SECONDARY);
+ reg = hrowpic_read_reg(sc, HPIC_STATUS, HPIC_PRIMARY);
+ mask = (mask << 32) | reg;
+ if (mask == 0)
+ break;
+
+ irq = 0;
+ while (irq < HROWPIC_IRQMAX) {
+ if (mask & 1)
+ powerpc_dispatch_intr(sc->sc_vector[irq], tf);
+ mask >>= 1;
+ irq++;
+ }
+ }
+}
+
+static void
+hrowpic_enable(device_t dev, u_int irq, u_int vector, void **priv __unused)
+{
+ struct hrowpic_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->sc_vector[irq] = vector;
+ hrowpic_toggle_irq(sc, irq, 1);
+}
+
+static void
+hrowpic_eoi(device_t dev, u_int irq, void *priv __unused)
+{
+ struct hrowpic_softc *sc;
+ int bank;
+
+ sc = device_get_softc(dev);
+ bank = (irq >= 32) ? HPIC_SECONDARY : HPIC_PRIMARY ;
+ hrowpic_write_reg(sc, HPIC_CLEAR, bank, 1U << (irq & 0x1f));
+}
+
+static void
+hrowpic_ipi(device_t dev, u_int irq)
+{
+ /* No SMP support. */
+}
+
+static void
+hrowpic_mask(device_t dev, u_int irq, void *priv __unused)
+{
+ struct hrowpic_softc *sc;
+
+ sc = device_get_softc(dev);
+ hrowpic_toggle_irq(sc, irq, 0);
+}
+
+static void
+hrowpic_unmask(device_t dev, u_int irq, void *priv __unused)
+{
+ struct hrowpic_softc *sc;
+
+ sc = device_get_softc(dev);
+ hrowpic_toggle_irq(sc, irq, 1);
+}