Пример #1
0
static void intc_mask_ack(struct irq_data *data)
{
	unsigned int irq = data->irq;
	struct intc_desc_int *d = get_intc_desc(irq);
	unsigned long handle = intc_get_ack_handle(irq);
	unsigned long addr;

	intc_disable(data);

	/* read register and write zero only to the associated bit */
	if (handle) {
		unsigned int value;

		addr = INTC_REG(d, _INTC_ADDR_D(handle), 0);
		value = intc_set_field_from_handle(0, 1, handle);

		switch (_INTC_FN(handle)) {
		case REG_FN_MODIFY_BASE + 0:	/* 8bit */
			__raw_readb(addr);
			__raw_writeb(0xff ^ value, addr);
			break;
		case REG_FN_MODIFY_BASE + 1:	/* 16bit */
			__raw_readw(addr);
			__raw_writew(0xffff ^ value, addr);
			break;
		case REG_FN_MODIFY_BASE + 3:	/* 32bit */
			__raw_readl(addr);
			__raw_writel(0xffffffff ^ value, addr);
			break;
		default:
			BUG();
			break;
		}
	}
}
Пример #2
0
int intc_set_priority(unsigned int irq, unsigned int prio)
{
	struct intc_desc_int *d = get_intc_desc(irq);
	struct irq_data *data = irq_get_irq_data(irq);
	struct intc_handle_int *ihp;

	if (!intc_get_prio_level(irq) || prio <= 1)
		return -EINVAL;

	ihp = intc_find_irq(d->prio, d->nr_prio, irq);
	if (ihp) {
		if (prio >= (1 << _INTC_WIDTH(ihp->handle)))
			return -EINVAL;

		intc_set_prio_level(irq, prio);

		/*
		 * only set secondary masking method directly
		 * primary masking method is using intc_prio_level[irq]
		 * priority level will be set during next enable()
		 */
		if (_INTC_FN(ihp->handle) != REG_FN_ERR)
			_intc_enable(data, ihp->handle);
	}
	return 0;
}
Пример #3
0
static int intc_set_type(struct irq_data *data, unsigned int type)
{
	unsigned int irq = data->irq;
	struct intc_desc_int *d = get_intc_desc(irq);
	unsigned char value = intc_irq_sense_table[type & IRQ_TYPE_SENSE_MASK];
	struct intc_handle_int *ihp;
	unsigned long addr;

	if (!value)
		return -EINVAL;

	value &= ~SENSE_VALID_FLAG;

	ihp = intc_find_irq(d->sense, d->nr_sense, irq);
	if (ihp) {
		/* PINT has 2-bit sense registers, should fail on EDGE_BOTH */
		if (value >= (1 << _INTC_WIDTH(ihp->handle)))
			return -EINVAL;

		addr = INTC_REG(d, _INTC_ADDR_E(ihp->handle), 0);
		intc_reg_fns[_INTC_FN(ihp->handle)](addr, ihp->handle, value);
	}

	return 0;
}
Пример #4
0
void intc_balancing_disable(unsigned int irq)
{
	struct intc_desc_int *d = get_intc_desc(irq);
	unsigned long handle = dist_handle[irq];
	unsigned long addr;

	if (irq_balancing_disabled(irq) || !handle)
		return;

	addr = INTC_REG(d, _INTC_ADDR_D(handle), 0);
	intc_reg_fns[_INTC_FN(handle)](addr, handle, 0);
}
Пример #5
0
static void intc_enable_disable(struct intc_desc_int *d,
				unsigned long handle, int do_enable)
{
	unsigned long addr;
	unsigned int cpu;
	unsigned long (*fn)(unsigned long, unsigned long,
		   unsigned long (*)(unsigned long, unsigned long,
				     unsigned long),
		   unsigned int);

	if (do_enable) {
		for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_E(handle)); cpu++) {
			addr = INTC_REG(d, _INTC_ADDR_E(handle), cpu);
			fn = intc_enable_noprio_fns[_INTC_MODE(handle)];
			fn(addr, handle, intc_reg_fns[_INTC_FN(handle)], 0);
		}
	} else {
		for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) {
			addr = INTC_REG(d, _INTC_ADDR_D(handle), cpu);
			fn = intc_disable_fns[_INTC_MODE(handle)];
			fn(addr, handle, intc_reg_fns[_INTC_FN(handle)], 0);
		}
	}
}
Пример #6
0
void _intc_enable(struct irq_data *data, unsigned long handle)
{
	unsigned int irq = data->irq;
	struct intc_desc_int *d = get_intc_desc(irq);
	unsigned long addr;
	unsigned int cpu;

	for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_E(handle)); cpu++) {
#ifdef CONFIG_SMP
		if (!cpumask_test_cpu(cpu, data->affinity))
			continue;
#endif
		addr = INTC_REG(d, _INTC_ADDR_E(handle), cpu);
		intc_enable_fns[_INTC_MODE(handle)](addr, handle, intc_reg_fns\
						    [_INTC_FN(handle)], irq);
	}

	intc_balancing_enable(irq);
}
Пример #7
0
static int intc_set_type(struct irq_data *data, unsigned int type)
{
	unsigned int irq = data->irq;
	struct intc_desc_int *d = get_intc_desc(irq);
	unsigned char value = intc_irq_sense_table[type & IRQ_TYPE_SENSE_MASK];
	struct intc_handle_int *ihp;
	unsigned long addr;

	if (!value)
		return -EINVAL;

	ihp = intc_find_irq(d->sense, d->nr_sense, irq);
	if (ihp) {
		addr = INTC_REG(d, _INTC_ADDR_E(ihp->handle), 0);
		intc_reg_fns[_INTC_FN(ihp->handle)](addr, ihp->handle, value);
	}

	return 0;
}
Пример #8
0
int intc_set_priority(unsigned int irq, unsigned int prio)
{
	struct intc_desc_int *d = get_intc_desc(irq);
	struct irq_data *data = irq_get_irq_data(irq);
	struct intc_handle_int *ihp;

	if (!intc_get_prio_level(irq) || prio <= 1)
		return -EINVAL;

	ihp = intc_find_irq(d->prio, d->nr_prio, irq);
	if (ihp) {
		if (prio >= (1 << _INTC_WIDTH(ihp->handle)))
			return -EINVAL;

		intc_set_prio_level(irq, prio);

		if (_INTC_FN(ihp->handle) != REG_FN_ERR)
			_intc_enable(data, ihp->handle);
	}
	return 0;
}