예제 #1
0
static void
openpic_send_ipi(cpuid_t target, uint32_t mesg)
{
	struct cpu_info * const ci = curcpu();
	uint32_t cpumask = 0;

	switch (target) {
		case IPI_DST_ALL:
		case IPI_DST_NOTME:
			for (u_int i = 0; i < ncpu; i++) {
				struct cpu_info * const dst_ci = cpu_lookup(i);
				if (target == IPI_DST_ALL || dst_ci != ci) {
					cpumask |= 1 << cpu_index(dst_ci);
					atomic_or_32(&dst_ci->ci_pending_ipis,
					    mesg);
				}
			}
			break;
		default: {
			struct cpu_info * const dst_ci = cpu_lookup(target);
			cpumask = 1 << cpu_index(dst_ci);
			atomic_or_32(&dst_ci->ci_pending_ipis, mesg);
			break;
		}
	}
	openpic_write(OPENPIC_IPI(cpu_index(ci), 1), cpumask);
}
예제 #2
0
파일: openpic.cpp 프로젝트: mmanley/Antares
static void
openpic_eoi(openpic_info *info, int cpu)
{
	openpic_write(info, OPENPIC_EOI(cpu), 0);
// the Linux driver does this:
//openpic_read(info, OPENPIC_EOI(cpu));
}
예제 #3
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);
	}
}
예제 #4
0
파일: cpu.c 프로젝트: lacombar/netbsd-alc
void
md_setup_interrupts(void)
{
    if (!openpic_base)
        return;
    /* clear the reset on all CPU's */
    openpic_write(OPENPIC_PROC_INIT, 0);
    openpic_set_priority(cpu_number(), 0);
}
예제 #5
0
파일: openpic.cpp 프로젝트: mmanley/Antares
static void
openpic_disable_irq(openpic_info *info, int irq)
{
	uint32 x;

	x = openpic_read(info, OPENPIC_SRC_VECTOR(irq));
	x |= OPENPIC_IMASK;
	openpic_write(info, OPENPIC_SRC_VECTOR(irq), x);
}
예제 #6
0
파일: openpic.cpp 프로젝트: mmanley/Antares
static void
openpic_set_priority(openpic_info *info, int cpu, int pri)
{
	uint32 x;

	x = openpic_read(info, OPENPIC_CPU_PRIORITY(cpu));
	x &= ~OPENPIC_CPU_PRIORITY_MASK;
	x |= pri;
	openpic_write(info, OPENPIC_CPU_PRIORITY(cpu), x);
}
예제 #7
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);
	}
}
예제 #8
0
void
openpic_set_priority(int cpu, int pri)
{
	u_int x;

	x = openpic_read(OPENPIC_CPU_PRIORITY(cpu));
	x &= ~OPENPIC_CPU_PRIORITY_MASK;
	x |= pri;
	openpic_write(OPENPIC_CPU_PRIORITY(cpu), x);
}
예제 #9
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);
}
예제 #10
0
void
openpic_eoi(device_t dev, u_int irq __unused)
{
	struct openpic_softc *sc;
	u_int cpuid;

	cpuid = (dev == root_pic) ? PCPU_GET(cpuid) : 0;

	sc = device_get_softc(dev);
	openpic_write(sc, OPENPIC_PCPU_EOI(cpuid), 0);
}
예제 #11
0
void
openpic_bind(device_t dev, u_int irq, cpumask_t cpumask)
{
	struct openpic_softc *sc;

	/* If we aren't directly connected to the CPU, this won't work */
	if (dev != root_pic)
		return;

	sc = device_get_softc(dev);
	openpic_write(sc, OPENPIC_IDEST(irq), cpumask);
}
예제 #12
0
void
openpic_ipi(device_t dev, u_int cpu)
{
	struct openpic_softc *sc;

	KASSERT(dev == root_pic, ("Cannot send IPIs from non-root OpenPIC"));

	sc = device_get_softc(dev);
	sched_pin();
	openpic_write(sc, OPENPIC_PCPU_IPI_DISPATCH(PCPU_GET(cpuid), 0),
	    1u << cpu);
	sched_unpin();
}
예제 #13
0
static __inline void
openpic_set_priority(struct openpic_softc *sc, int pri)
{
	u_int tpr;
	uint32_t x;

	sched_pin();
	tpr = OPENPIC_PCPU_TPR((sc->sc_dev == root_pic) ? PCPU_GET(cpuid) : 0);
	x = openpic_read(sc, tpr);
	x &= ~OPENPIC_TPR_MASK;
	x |= pri;
	openpic_write(sc, tpr, x);
	sched_unpin();
}
예제 #14
0
파일: openpic.cpp 프로젝트: mmanley/Antares
static void
openpic_enable_irq(openpic_info *info, int irq, int type)
{
// TODO: Align this code with the sequence recommended in the Open PIC
// Specification (v 1.2 section 5.2.2).
	uint32 x;

	x = openpic_read(info, OPENPIC_SRC_VECTOR(irq));
	x &= ~(OPENPIC_IMASK | OPENPIC_SENSE_LEVEL | OPENPIC_SENSE_EDGE);
	if (type == IRQ_TYPE_LEVEL)
		x |= OPENPIC_SENSE_LEVEL;
	else
		x |= OPENPIC_SENSE_EDGE;
	openpic_write(info, OPENPIC_SRC_VECTOR(irq), x);
}
예제 #15
0
파일: cpu.c 프로젝트: lacombar/netbsd-alc
int
md_setup_trampoline(volatile struct cpu_hatch_data *h, struct cpu_info *ci)
{
    if (!openpic_base)
        return -1;

    /* construct an absolute branch instruction */
    /* ba cpu_spinup_trampoline */
    *(u_int *)EXC_RST = 0x48000002 | (u_int)cpu_spinup_trampoline;
    __syncicache((void *)EXC_RST, 0x100);
    h->running = -1;

    /* Start secondary CPU. */
    openpic_write(OPENPIC_PROC_INIT, (1 << 1));
    return 1;
}
예제 #16
0
void
opic_finish_setup(struct pic_ops *pic)
{
	uint32_t cpumask = 0;
	int i;

#ifdef OPENPIC_DISTRIBUTE
	for (i = 0; i < ncpu; i++)
		cpumask |= (1 << cpu_info[i].ci_index);
#else
	cpumask = 1;
#endif
	for (i = 0; i < pic->pic_numintrs; i++) {
		/* send all interrupts to all active CPUs */
		openpic_write(OPENPIC_IDEST(i), cpumask);
	}
}
예제 #17
0
void
openpic_config(device_t dev, u_int irq, enum intr_trigger trig,
    enum intr_polarity pol)
{
	struct openpic_softc *sc;
	uint32_t x;

	sc = device_get_softc(dev);
	x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
	if (pol == INTR_POLARITY_LOW)
		x &= ~OPENPIC_POLARITY_POSITIVE;
	else
		x |= OPENPIC_POLARITY_POSITIVE;
	if (trig == INTR_TRIGGER_EDGE)
		x &= ~OPENPIC_SENSE_LEVEL;
	else
		x |= OPENPIC_SENSE_LEVEL;
	openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
}
예제 #18
0
파일: openpic.cpp 프로젝트: mmanley/Antares
static status_t
openpic_init(openpic_info *info)
{
	uint32 x = openpic_read(info, OPENPIC_FEATURE);
	const char *featureVersion;
	char versionBuffer[64];
	switch (x & OPENPIC_FEATURE_VERSION_MASK) {
		case 1:
			featureVersion = "1.0";
			break;
		case 2:
			featureVersion = "1.2";
			break;
		case 3:
			featureVersion = "1.3";
			break;
		default:
			snprintf(versionBuffer, sizeof(versionBuffer),
				"unknown (feature reg: 0x%lx)", x);
			featureVersion = versionBuffer;
			break;
	}

	info->cpu_count = ((x & OPENPIC_FEATURE_LAST_CPU_MASK) >>
	    OPENPIC_FEATURE_LAST_CPU_SHIFT) + 1;
	info->irq_count = ((x & OPENPIC_FEATURE_LAST_IRQ_MASK) >>
	    OPENPIC_FEATURE_LAST_IRQ_SHIFT) + 1;

	/*
	 * PSIM seems to report 1 too many IRQs
	 */
// 	if (sc->sc_psim)
// 		sc->sc_nirq--;

	dprintf("openpic: Version %s, supports %d CPUs and %d irqs\n",
		    featureVersion, info->cpu_count, info->irq_count);

	/* disable all interrupts */
	for (int irq = 0; irq < info->irq_count; irq++)
		openpic_write(info, OPENPIC_SRC_VECTOR(irq), OPENPIC_IMASK);

	openpic_set_priority(info, 0, 15);

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

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

	for (int irq = 0; irq < info->irq_count; irq++) {
		x = irq;
		x |= OPENPIC_IMASK;
		x |= OPENPIC_POLARITY_POSITIVE;
		x |= OPENPIC_SENSE_LEVEL;
		x |= 8 << OPENPIC_PRIORITY_SHIFT;
		openpic_write(info, OPENPIC_SRC_VECTOR(irq), x);
	}

	/* XXX IPI */
	/* XXX set spurious intr vector */

	openpic_set_priority(info, 0, 0);

	/* clear all pending interrupts */
	for (int irq = 0; irq < info->irq_count; irq++) {
		openpic_read_irq(info, 0);
		openpic_eoi(info, 0);
	}

	return B_OK;
}
예제 #19
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);
}