示例#1
0
void
openpic_unmask(device_t dev, u_int irq)
{
	struct openpic_softc *sc;
	uint32_t x;

	sc = device_get_softc(dev);
	if (irq < sc->sc_nirq) {
		x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
		x &= ~OPENPIC_IMASK;
		openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
	} else {
		x = openpic_read(sc, OPENPIC_IPI_VECTOR(0));
		x &= ~OPENPIC_IMASK;
		openpic_write(sc, OPENPIC_IPI_VECTOR(0), x);
	}
}
示例#2
0
void
openpic_enable(device_t dev, u_int irq, u_int vector)
{
	struct openpic_softc *sc;
	uint32_t x;

	sc = device_get_softc(dev);
	if (irq < sc->sc_nirq) {
		x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
		x &= ~(OPENPIC_IMASK | OPENPIC_VECTOR_MASK);
		x |= vector;
		openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
	} else {
		x = openpic_read(sc, OPENPIC_IPI_VECTOR(0));
		x &= ~(OPENPIC_IMASK | OPENPIC_VECTOR_MASK);
		x |= vector;
		openpic_write(sc, OPENPIC_IPI_VECTOR(0), x);
	}
}
示例#3
0
void
setup_openpic_ipi(void)
{
	uint32_t x;

	ipiops.ppc_send_ipi = openpic_send_ipi;
	ipiops.ppc_establish_ipi = openpic_establish_ipi;
	ipiops.ppc_ipi_vector = IPI_VECTOR;

	/* Some (broken) openpic's byteswap on read, but not write. */
	openpic_write(OPENPIC_IPI_VECTOR(0), OPENPIC_IMASK);
	x = openpic_read(OPENPIC_IPI_VECTOR(0));
	if (x != OPENPIC_IMASK)
		x = bswap32(openpic_read(OPENPIC_IPI_VECTOR(1)));
	else
		x = openpic_read(OPENPIC_IPI_VECTOR(1));
	x &= ~(OPENPIC_IMASK | OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK);
	x |= (15 << OPENPIC_PRIORITY_SHIFT) | ipiops.ppc_ipi_vector;
	openpic_write(OPENPIC_IPI_VECTOR(1), x);
}
示例#4
0
int
openpic_attach(device_t dev)
{
	struct openpic_softc *sc;
	u_int     cpu, ipi, irq;
	u_int32_t x;

	sc = device_get_softc(dev);
	sc->sc_dev = dev;

	sc->sc_rid = 0;
	sc->sc_memr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid,
	    RF_ACTIVE);

	if (sc->sc_memr == NULL) {
		device_printf(dev, "Could not alloc mem resource!\n");
		return (ENXIO);
	}

	sc->sc_bt = rman_get_bustag(sc->sc_memr);
	sc->sc_bh = rman_get_bushandle(sc->sc_memr);

	/* Reset the PIC */
	x = openpic_read(sc, OPENPIC_CONFIG);
	x |= OPENPIC_CONFIG_RESET;
	openpic_write(sc, OPENPIC_CONFIG, x);

	while (openpic_read(sc, OPENPIC_CONFIG) & OPENPIC_CONFIG_RESET) {
		powerpc_sync();
		DELAY(100);
	}

	/* Check if this is a cascaded PIC */
	sc->sc_irq = 0;
	sc->sc_intr = NULL;
	do {
		struct resource_list *rl;

		rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev);
		if (rl == NULL)
			break;
		if (resource_list_find(rl, SYS_RES_IRQ, 0) == NULL)
			break;

		sc->sc_intr = bus_alloc_resource_any(dev, SYS_RES_IRQ,
		    &sc->sc_irq, RF_ACTIVE);

		/* XXX Cascaded PICs pass NULL trapframes! */
		bus_setup_intr(dev, sc->sc_intr, INTR_TYPE_MISC | INTR_MPSAFE,
		    openpic_intr, NULL, dev, &sc->sc_icookie);
	} while (0);

	/* Reset the PIC */
	x = openpic_read(sc, OPENPIC_CONFIG);
	x |= OPENPIC_CONFIG_RESET;
	openpic_write(sc, OPENPIC_CONFIG, x);

	while (openpic_read(sc, OPENPIC_CONFIG) & OPENPIC_CONFIG_RESET) {
		powerpc_sync();
		DELAY(100);
	}

	x = openpic_read(sc, OPENPIC_FEATURE);
	switch (x & OPENPIC_FEATURE_VERSION_MASK) {
	case 1:
		sc->sc_version = "1.0";
		break;
	case 2:
		sc->sc_version = "1.2";
		break;
	case 3:
		sc->sc_version = "1.3";
		break;
	default:
		sc->sc_version = "unknown";
		break;
	}

	sc->sc_ncpu = ((x & OPENPIC_FEATURE_LAST_CPU_MASK) >>
	    OPENPIC_FEATURE_LAST_CPU_SHIFT) + 1;
	sc->sc_nirq = ((x & OPENPIC_FEATURE_LAST_IRQ_MASK) >>
	    OPENPIC_FEATURE_LAST_IRQ_SHIFT) + 1;

	/*
	 * PSIM seems to report 1 too many IRQs and CPUs
	 */
	if (sc->sc_psim) {
		sc->sc_nirq--;
		sc->sc_ncpu--;
	}

	if (bootverbose)
		device_printf(dev,
		    "Version %s, supports %d CPUs and %d irqs\n",
		    sc->sc_version, sc->sc_ncpu, sc->sc_nirq);

	for (cpu = 0; cpu < sc->sc_ncpu; cpu++)
		openpic_write(sc, OPENPIC_PCPU_TPR(cpu), 15);

	/* Reset and disable all interrupts. */
	for (irq = 0; irq < sc->sc_nirq; irq++) {
		x = irq;                /* irq == vector. */
		x |= OPENPIC_IMASK;
		x |= OPENPIC_POLARITY_NEGATIVE;
		x |= OPENPIC_SENSE_LEVEL;
		x |= 8 << OPENPIC_PRIORITY_SHIFT;
		openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
	}

	/* Reset and disable all IPIs. */
	for (ipi = 0; ipi < 4; ipi++) {
		x = sc->sc_nirq + ipi;
		x |= OPENPIC_IMASK;
		x |= 15 << OPENPIC_PRIORITY_SHIFT;
		openpic_write(sc, OPENPIC_IPI_VECTOR(ipi), x);
	}

	/* we don't need 8259 passthrough mode */
	x = openpic_read(sc, OPENPIC_CONFIG);
	x |= OPENPIC_CONFIG_8259_PASSTHRU_DISABLE;
	openpic_write(sc, OPENPIC_CONFIG, x);

	/* send all interrupts to cpu 0 */
	for (irq = 0; irq < sc->sc_nirq; irq++)
		openpic_write(sc, OPENPIC_IDEST(irq), 1 << 0);

	/* clear all pending interrupts from cpu 0 */
	for (irq = 0; irq < sc->sc_nirq; irq++) {
		(void)openpic_read(sc, OPENPIC_PCPU_IACK(0));
		openpic_write(sc, OPENPIC_PCPU_EOI(0), 0);
	}

	for (cpu = 0; cpu < sc->sc_ncpu; cpu++)
		openpic_write(sc, OPENPIC_PCPU_TPR(cpu), 0);

	powerpc_register_pic(dev, sc->sc_nirq);

	/* If this is not a cascaded PIC, it must be the root PIC */
	if (sc->sc_intr == NULL)
		root_pic = dev;

	return (0);
}