static int vlynq_setup_irq()

in vlynq.c [245:301]


static int vlynq_setup_irq(struct vlynq_device *dev)
{
	u32 val;
	int i, virq;

	if (dev->local_irq == dev->remote_irq) {
		printk(KERN_ERR
		       "%s: local vlynq irq should be different from remote\n",
		       dev_name(&dev->dev));
		return -EINVAL;
	}

	/* Clear local and remote error bits */
	writel(readl(&dev->local->status), &dev->local->status);
	writel(readl(&dev->remote->status), &dev->remote->status);

	/* Now setup interrupts */
	val = VLYNQ_CTRL_INT_VECTOR(dev->local_irq);
	val |= VLYNQ_CTRL_INT_ENABLE | VLYNQ_CTRL_INT_LOCAL |
		VLYNQ_CTRL_INT2CFG;
	val |= readl(&dev->local->control);
	writel(VLYNQ_INT_OFFSET, &dev->local->int_ptr);
	writel(val, &dev->local->control);

	val = VLYNQ_CTRL_INT_VECTOR(dev->remote_irq);
	val |= VLYNQ_CTRL_INT_ENABLE;
	val |= readl(&dev->remote->control);
	writel(VLYNQ_INT_OFFSET, &dev->remote->int_ptr);
	writel(val, &dev->remote->int_ptr);
	writel(val, &dev->remote->control);

	for (i = dev->irq_start; i <= dev->irq_end; i++) {
		virq = i - dev->irq_start;
		if (virq == dev->local_irq) {
			irq_set_chip_and_handler(i, &vlynq_local_chip,
						 handle_level_irq);
			irq_set_chip_data(i, dev);
		} else if (virq == dev->remote_irq) {
			irq_set_chip_and_handler(i, &vlynq_remote_chip,
						 handle_level_irq);
			irq_set_chip_data(i, dev);
		} else {
			irq_set_chip_and_handler(i, &vlynq_irq_chip,
						 handle_simple_irq);
			irq_set_chip_data(i, dev);
			writel(0, &dev->remote->int_device[virq >> 2]);
		}
	}

	if (request_irq(dev->irq, vlynq_irq, IRQF_SHARED, "vlynq", dev)) {
		printk(KERN_ERR "%s: request_irq failed\n",
					dev_name(&dev->dev));
		return -EAGAIN;
	}

	return 0;
}