Example #1
0
static int octeon_irq_ciu1_set_affinity(unsigned int irq, const struct cpumask *dest)
{
	int cpu;
	unsigned long flags;
	int bit = irq - OCTEON_IRQ_WDOG0;	/* Bit 0-63 of EN1 */

	write_lock_irqsave(&octeon_irq_ciu1_rwlock, flags);
	for_each_online_cpu(cpu) {
		int coreid = cpu_logical_map(cpu);
		uint64_t en1 =
			cvmx_read_csr(CVMX_CIU_INTX_EN1
				(coreid * 2 + 1));
		if (cpumask_test_cpu(cpu, dest))
			en1 |= 1ull << bit;
		else
			en1 &= ~(1ull << bit);
		cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1);
	}
	/*
	 * We need to do a read after the last update to make sure all
	 * of them are done.
	 */
	cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1));
	write_unlock_irqrestore(&octeon_irq_ciu1_rwlock, flags);

	return 0;
}
Example #2
0
/*
 * octeon_ciu_reset
 *
 * Shutdown all CIU to IP2, IP3 mappings
 */
void
octeon_ciu_reset(void)
{
	uint64_t cvmctl;

	/* Disable all CIU interrupts by default */
	cvmx_write_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num()*2), 0);
	cvmx_write_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num()*2+1), 0);
	cvmx_write_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num()*2), 0);
	cvmx_write_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num()*2+1), 0);

#ifdef SMP
	/* Enable the MBOX interrupts.  */
	cvmx_write_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num()*2+1),
		       (1ull << (OCTEON_IRQ_MBOX0 - 8)) |
		       (1ull << (OCTEON_IRQ_MBOX1 - 8)));
#endif

	/* 
	 * Move the Performance Counter interrupt to OCTEON_PMC_IRQ
	 */
	cvmctl = mips_rd_cvmctl();
	cvmctl &= ~(7 << 7);
	cvmctl |= (OCTEON_PMC_IRQ + 2) << 7;
	mips_wr_cvmctl(cvmctl);
}
Example #3
0
File: ciu.c Project: coyizumi/cs111
static void
ciu_en1_intr_unmask(void *arg)
{
	uint64_t mask;
	int irq;

	irq = (uintptr_t)arg;
	mask = cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num()*2));
	mask |= 1ull << (irq - CIU_IRQ_EN1_BEGIN);
	cvmx_write_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num()*2), mask);
}
static void octeon_irq_ciu1_enable(unsigned int irq)
{
	int coreid = cvmx_get_core_num();
	unsigned long flags;
	uint64_t en1;
	int bit = irq - OCTEON_IRQ_WDOG0;	/* Bit 0-63 of EN1 */

	raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
	en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
	en1 |= 1ull << bit;
	cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1);
	cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
	raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
}
Example #5
0
File: ciu.c Project: coyizumi/cs111
static int
ciu_en1_intr_bind(void *arg, u_char target)
{
	uint64_t mask;
	int core;
	int irq;

	irq = (uintptr_t)arg;
	CPU_FOREACH(core) {
		mask = cvmx_read_csr(CVMX_CIU_INTX_EN1(core*2));
		if (core == target)
			mask |= 1ull << (irq - CIU_IRQ_EN1_BEGIN);
		else
			mask &= ~(1ull << (irq - CIU_IRQ_EN1_BEGIN));
		cvmx_write_csr(CVMX_CIU_INTX_EN1(core*2), mask);
	}

	return (0);
}
static void octeon_irq_ciu1_disable(unsigned int irq)
{
	int bit = irq - OCTEON_IRQ_WDOG0;	/* Bit 0-63 of EN1 */
	unsigned long flags;
	uint64_t en1;
	int cpu;
	raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
	for_each_online_cpu(cpu) {
		int coreid = octeon_coreid_for_cpu(cpu);
		en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
		en1 &= ~(1ull << bit);
		cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1);
	}
	/*
	 * We need to do a read after the last update to make sure all
	 * of them are done.
	 */
	cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1));
	raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
}
Example #7
0
static void octeon_irq_ciu1_enable(unsigned int irq)
{
	int coreid = cvmx_get_core_num();
	unsigned long flags;
	uint64_t en1;
	int bit = irq - OCTEON_IRQ_WDOG0;	/* Bit 0-63 of EN1 */

	/*
	 * A read lock is used here to make sure only one core is ever
	 * updating the CIU enable bits at a time.  During an enable
	 * the cores don't interfere with each other.  During a disable
	 * the write lock stops any enables that might cause a
	 * problem.
	 */
	read_lock_irqsave(&octeon_irq_ciu1_rwlock, flags);
	en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
	en1 |= 1ull << bit;
	cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1);
	cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
	read_unlock_irqrestore(&octeon_irq_ciu1_rwlock, flags);
}
Example #8
0
static void octeon_irq_ciu1_disable(unsigned int irq)
{
	int bit = irq - OCTEON_IRQ_WDOG0;	/* Bit 0-63 of EN1 */
	unsigned long flags;
	uint64_t en1;
#ifdef CONFIG_SMP
	int cpu;
	write_lock_irqsave(&octeon_irq_ciu1_rwlock, flags);
	for_each_online_cpu(cpu) {
		int coreid = cpu_logical_map(cpu);
		en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
		en1 &= ~(1ull << bit);
		cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1);
	}
	/*
	 * We need to do a read after the last update to make sure all
	 * of them are done.
	 */
	cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1));
	write_unlock_irqrestore(&octeon_irq_ciu1_rwlock, flags);
#else
	int coreid = cvmx_get_core_num();
	local_irq_save(flags);
	en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
	en1 &= ~(1ull << bit);
	cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1);
	cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
	local_irq_restore(flags);
#endif
}
Example #9
0
File: ciu.c Project: coyizumi/cs111
static int
ciu_intr(void *arg)
{
	struct ciu_softc *sc;
	uint64_t en0_sum, en1_sum;
	uint64_t en0_mask, en1_mask;
	int irq_index;
	int error;

	sc = arg;
	(void)sc;

	en0_sum = cvmx_read_csr(CVMX_CIU_INTX_SUM0(cvmx_get_core_num()*2));
	en1_sum = cvmx_read_csr(CVMX_CIU_INT_SUM1);

	en0_mask = cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num()*2));
	en1_mask = cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num()*2));

	en0_sum &= en0_mask;
	en1_sum &= en1_mask;

	if (en0_sum == 0 && en1_sum == 0)
		return (FILTER_STRAY);

	irq_index = 0;
	for (irq_index = 0; en0_sum != 0; irq_index++, en0_sum >>= 1) {
		if ((en0_sum & 1) == 0)
			continue;

		mips_intrcnt_inc(ciu_en0_intrcnt[irq_index]);

		error = intr_event_handle(ciu_en0_intr_events[irq_index], NULL);
		if (error != 0)
			printf("%s: stray en0 irq%d\n", __func__, irq_index);
	}

	irq_index = 0;
	for (irq_index = 0; en1_sum != 0; irq_index++, en1_sum >>= 1) {
		if ((en1_sum & 1) == 0)
			continue;

		mips_intrcnt_inc(ciu_en1_intrcnt[irq_index]);

		error = intr_event_handle(ciu_en1_intr_events[irq_index], NULL);
		if (error != 0)
			printf("%s: stray en1 irq%d\n", __func__, irq_index);
	}

	return (FILTER_HANDLED);
}
Example #10
0
asmlinkage void plat_irq_dispatch(void)
{
	const unsigned long core_id = cvmx_get_core_num();
	const uint64_t ciu_sum0_address = CVMX_CIU_INTX_SUM0(core_id * 2);
	const uint64_t ciu_en0_address = CVMX_CIU_INTX_EN0(core_id * 2);
	const uint64_t ciu_sum1_address = CVMX_CIU_INT_SUM1;
	const uint64_t ciu_en1_address = CVMX_CIU_INTX_EN1(core_id * 2 + 1);
	unsigned long cop0_cause;
	unsigned long cop0_status;
	uint64_t ciu_en;
	uint64_t ciu_sum;

	while (1) {
		cop0_cause = read_c0_cause();
		cop0_status = read_c0_status();
		cop0_cause &= cop0_status;
		cop0_cause &= ST0_IM;

		if (unlikely(cop0_cause & STATUSF_IP2)) {
			ciu_sum = cvmx_read_csr(ciu_sum0_address);
			ciu_en = cvmx_read_csr(ciu_en0_address);
			ciu_sum &= ciu_en;
			if (likely(ciu_sum))
				do_IRQ(fls64(ciu_sum) + OCTEON_IRQ_WORKQ0 - 1);
			else
				spurious_interrupt();
		} else if (unlikely(cop0_cause & STATUSF_IP3)) {
			ciu_sum = cvmx_read_csr(ciu_sum1_address);
			ciu_en = cvmx_read_csr(ciu_en1_address);
			ciu_sum &= ciu_en;
			if (likely(ciu_sum))
				do_IRQ(fls64(ciu_sum) + OCTEON_IRQ_WDOG0 - 1);
			else
				spurious_interrupt();
		} else if (likely(cop0_cause)) {
			do_IRQ(fls(cop0_cause) - 9 + MIPS_CPU_IRQ_BASE);
		} else {
			break;
		}
	}
}
Example #11
0
static void octeon_irq_ciu_disable_local(struct irq_data *data)
{
	unsigned long *pen;
	unsigned long flags;
	union octeon_ciu_chip_data cd;

	cd.p = irq_data_get_irq_chip_data(data);

	if (cd.s.line == 0) {
		raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags);
		pen = &__get_cpu_var(octeon_irq_ciu0_en_mirror);
		clear_bit(cd.s.bit, pen);
		cvmx_write_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2), *pen);
		raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags);
	} else {
		raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
		pen = &__get_cpu_var(octeon_irq_ciu1_en_mirror);
		clear_bit(cd.s.bit, pen);
		cvmx_write_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1), *pen);
		raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
	}
}
Example #12
0
static void octeon_irq_ciu_enable(struct irq_data *data)
{
	int cpu = next_cpu_for_irq(data);
	int coreid = octeon_coreid_for_cpu(cpu);
	unsigned long *pen;
	unsigned long flags;
	union octeon_ciu_chip_data cd;

	cd.p = irq_data_get_irq_chip_data(data);

	if (cd.s.line == 0) {
		raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags);
		pen = &per_cpu(octeon_irq_ciu0_en_mirror, cpu);
		set_bit(cd.s.bit, pen);
		cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), *pen);
		raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags);
	} else {
		raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
		pen = &per_cpu(octeon_irq_ciu1_en_mirror, cpu);
		set_bit(cd.s.bit, pen);
		cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), *pen);
		raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
	}
}