void __init omap3_init_irq(void)
{
	omap_nr_irqs = 96;
	omap_nr_pending = 3;
	omap_init_irq(OMAP34XX_IC_BASE, NULL);
	set_handle_irq(omap_intc_handle_irq);
}
示例#2
0
文件: irq-mxs.c 项目: 020gzh/linux
static int __init asm9260_of_init(struct device_node *np,
			  struct device_node *interrupt_parent)
{
	void __iomem *icoll_base;
	int i;

	icoll_priv.type = ASM9260_ICOLL;

	icoll_base = icoll_init_iobase(np);
	icoll_priv.vector	= icoll_base + ASM9260_HW_ICOLL_VECTOR;
	icoll_priv.levelack	= icoll_base + ASM9260_HW_ICOLL_LEVELACK;
	icoll_priv.ctrl		= icoll_base + ASM9260_HW_ICOLL_CTRL;
	icoll_priv.stat		= icoll_base + ASM9260_HW_ICOLL_STAT_OFFSET;
	icoll_priv.intr		= icoll_base + ASM9260_HW_ICOLL_INTERRUPT0;
	icoll_priv.clear	= icoll_base + ASM9260_HW_ICOLL_CLEAR0;

	writel_relaxed(ASM9260_BM_CTRL_IRQ_ENABLE,
			icoll_priv.ctrl);
	/*
	 * ASM9260 don't provide reset bit. So, we need to set level 0
	 * manually.
	 */
	for (i = 0; i < 16 * 0x10; i += 0x10)
		writel(0, icoll_priv.intr + i);

	icoll_add_domain(np, ASM9260_NUM_IRQS);
	set_handle_irq(icoll_handle_irq);

	return 0;
}
static int __init intc_of_init(struct device_node *node,
			     struct device_node *parent)
{
	int ret;

	omap_nr_pending = 3;
	omap_nr_irqs = 96;

	if (WARN_ON(!node))
		return -ENODEV;

	if (of_device_is_compatible(node, "ti,dm814-intc") ||
	    of_device_is_compatible(node, "ti,dm816-intc") ||
	    of_device_is_compatible(node, "ti,am33xx-intc")) {
		omap_nr_irqs = 128;
		omap_nr_pending = 4;
	}

	ret = omap_init_irq(-1, of_node_get(node));
	if (ret < 0)
		return ret;

	set_handle_irq(omap_intc_handle_irq);

	return 0;
}
示例#4
0
static int __init armctrl_of_init(struct device_node *node,
	struct device_node *parent)
{
	void __iomem *base;
	int irq, b, i;

	base = of_iomap(node, 0);
	if (!base)
		panic("%s: unable to map IC registers\n",
			node->full_name);

	intc.domain = irq_domain_add_linear(node, MAKE_HWIRQ(NR_BANKS, 0),
			&armctrl_ops, NULL);
	if (!intc.domain)
		panic("%s: unable to create IRQ domain\n", node->full_name);

	for (b = 0; b < NR_BANKS; b++) {
		intc.pending[b] = base + reg_pending[b];
		intc.enable[b] = base + reg_enable[b];
		intc.disable[b] = base + reg_disable[b];

		for (i = 0; i < bank_irqs[b]; i++) {
			irq = irq_create_mapping(intc.domain, MAKE_HWIRQ(b, i));
			BUG_ON(irq <= 0);
			irq_set_chip_and_handler(irq, &armctrl_chip,
				handle_level_irq);
			set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
		}
	}

	set_handle_irq(bcm2835_handle_irq);
	return 0;
}
示例#5
0
static int __init aic_of_init(struct device_node *node,
			      struct device_node *parent)
{
	struct irq_chip_generic *gc;
	struct irq_domain *domain;

	if (aic_domain)
		return -EEXIST;

	domain = aic_common_of_init(node, &aic_irq_ops, "atmel-aic",
				    NR_AIC_IRQS);
	if (IS_ERR(domain))
		return PTR_ERR(domain);

	aic_common_irq_fixup(aic_irq_fixups);

	aic_domain = domain;
	gc = irq_get_domain_generic_chip(domain, 0);

	gc->chip_types[0].regs.eoi = AT91_AIC_EOICR;
	gc->chip_types[0].regs.enable = AT91_AIC_IECR;
	gc->chip_types[0].regs.disable = AT91_AIC_IDCR;
	gc->chip_types[0].chip.irq_mask = irq_gc_mask_disable_reg;
	gc->chip_types[0].chip.irq_unmask = irq_gc_unmask_enable_reg;
	gc->chip_types[0].chip.irq_retrigger = aic_retrigger;
	gc->chip_types[0].chip.irq_set_type = aic_set_type;
	gc->chip_types[0].chip.irq_suspend = aic_suspend;
	gc->chip_types[0].chip.irq_resume = aic_resume;
	gc->chip_types[0].chip.irq_pm_shutdown = aic_pm_shutdown;

	aic_hw_init(domain);
	set_handle_irq(aic_handle);

	return 0;
}
示例#6
0
文件: irq-moxart.c 项目: 168519/linux
static int __init moxart_of_intc_init(struct device_node *node,
				      struct device_node *parent)
{
	unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
	int ret;
	struct irq_chip_generic *gc;

	intc.base = of_iomap(node, 0);
	if (!intc.base) {
		pr_err("%s: unable to map IC registers\n",
		       node->full_name);
		return -EINVAL;
	}

	intc.domain = irq_domain_add_linear(node, 32, &irq_generic_chip_ops,
					    intc.base);
	if (!intc.domain) {
		pr_err("%s: unable to create IRQ domain\n", node->full_name);
		return -EINVAL;
	}

	ret = irq_alloc_domain_generic_chips(intc.domain, 32, 1,
					     "MOXARTINTC", handle_edge_irq,
					     clr, 0, IRQ_GC_INIT_MASK_CACHE);
	if (ret) {
		pr_err("%s: could not allocate generic chip\n",
		       node->full_name);
		irq_domain_remove(intc.domain);
		return -EINVAL;
	}

	ret = of_property_read_u32(node, "interrupt-mask",
				   &intc.interrupt_mask);
	if (ret)
		pr_err("%s: could not read interrupt-mask DT property\n",
		       node->full_name);

	gc = irq_get_domain_generic_chip(intc.domain, 0);

	gc->reg_base = intc.base;
	gc->chip_types[0].regs.mask = IRQ_MASK_REG;
	gc->chip_types[0].regs.ack = IRQ_CLEAR_REG;
	gc->chip_types[0].chip.irq_ack = irq_gc_ack_set_bit;
	gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit;
	gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;

	writel(0, intc.base + IRQ_MASK_REG);
	writel(0xffffffff, intc.base + IRQ_CLEAR_REG);

	writel(intc.interrupt_mask, intc.base + IRQ_MODE_REG);
	writel(intc.interrupt_mask, intc.base + IRQ_LEVEL_REG);

	set_handle_irq(handle_irq);

	return 0;
}
示例#7
0
static int __init vt8500_irq_init(struct device_node *node,
				  struct device_node *parent)
{
	int irq, i;
	struct device_node *np = node;

	if (active_cnt == VT8500_INTC_MAX) {
		pr_err("%s: Interrupt controllers > VT8500_INTC_MAX\n",
								__func__);
		goto out;
	}

	intc[active_cnt].base = of_iomap(np, 0);
	intc[active_cnt].domain = irq_domain_add_linear(node, 64,
			&vt8500_irq_domain_ops,	&intc[active_cnt]);

	if (!intc[active_cnt].base) {
		pr_err("%s: Unable to map IO memory\n", __func__);
		goto out;
	}

	if (!intc[active_cnt].domain) {
		pr_err("%s: Unable to add irq domain!\n", __func__);
		goto out;
	}

	set_handle_irq(vt8500_handle_irq);

	vt8500_init_irq_hw(intc[active_cnt].base);

	pr_info("vt8500-irq: Added interrupt controller\n");

	active_cnt++;

	/* check if this is a slaved controller */
	if (of_irq_count(np) != 0) {
		/* check that we have the correct number of interrupts */
		if (of_irq_count(np) != 8) {
			pr_err("%s: Incorrect IRQ map for slaved controller\n",
					__func__);
			return -EINVAL;
		}

		for (i = 0; i < 8; i++) {
			irq = irq_of_parse_and_map(np, i);
			enable_irq(irq);
		}

		pr_info("vt8500-irq: Enabled slave->parent interrupts\n");
	}
out:
	return 0;
}
示例#8
0
/*
 * This sets up the IRQ domain for the PIC built in to the OpenRISC
 * 1000 CPU.  This is the "root" domain as these are the interrupts
 * that directly trigger an exception in the CPU.
 */
static int __init or1k_pic_init(struct device_node *node,
				 struct or1k_pic_dev *pic)
{
	/* Disable all interrupts until explicitly requested */
	mtspr(SPR_PICMR, (0UL));

	root_domain = irq_domain_add_linear(node, 32, &or1k_irq_domain_ops,
					    pic);

	set_handle_irq(or1k_pic_handle_irq);

	return 0;
}
示例#9
0
文件: irq.c 项目: 0-T-0/ps4-linux
void __init orion5x_init_irq(void)
{
	orion_irq_init(1, MAIN_IRQ_MASK);

#ifdef CONFIG_MULTI_IRQ_HANDLER
	set_handle_irq(orion5x_legacy_handle_irq);
#endif

	/*
	 * Initialize gpiolib for GPIOs 0-31.
	 */
	orion_gpio_init(NULL, 0, 32, GPIO_VIRT_BASE, 0,
			IRQ_ORION5X_GPIO_START, gpio0_irqs);
}
示例#10
0
文件: irq-orion.c 项目: 7799/linux
static int __init orion_irq_init(struct device_node *np,
				 struct device_node *parent)
{
	unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
	int n, ret, base, num_chips = 0;
	struct resource r;

	/* count number of irq chips by valid reg addresses */
	while (of_address_to_resource(np, num_chips, &r) == 0)
		num_chips++;

	orion_irq_domain = irq_domain_add_linear(np,
				num_chips * ORION_IRQS_PER_CHIP,
				&irq_generic_chip_ops, NULL);
	if (!orion_irq_domain)
		panic("%s: unable to add irq domain\n", np->name);

	ret = irq_alloc_domain_generic_chips(orion_irq_domain,
				ORION_IRQS_PER_CHIP, 1, np->name,
				handle_level_irq, clr, 0,
				IRQ_GC_INIT_MASK_CACHE);
	if (ret)
		panic("%s: unable to alloc irq domain gc\n", np->name);

	for (n = 0, base = 0; n < num_chips; n++, base += ORION_IRQS_PER_CHIP) {
		struct irq_chip_generic *gc =
			irq_get_domain_generic_chip(orion_irq_domain, base);

		of_address_to_resource(np, n, &r);

		if (!request_mem_region(r.start, resource_size(&r), np->name))
			panic("%s: unable to request mem region %d",
			      np->name, n);

		gc->reg_base = ioremap(r.start, resource_size(&r));
		if (!gc->reg_base)
			panic("%s: unable to map resource %d", np->name, n);

		gc->chip_types[0].regs.mask = ORION_IRQ_MASK;
		gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit;
		gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;

		/* mask all interrupts */
		writel(0, gc->reg_base + ORION_IRQ_MASK);
	}

	set_handle_irq(orion_handle_irq);
	return 0;
}
示例#11
0
static int __init digicolor_of_init(struct device_node *node,
				struct device_node *parent)
{
	static void __iomem *reg_base;
	unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
	struct regmap *ucregs;
	int ret;

	reg_base = of_iomap(node, 0);
	if (!reg_base) {
		pr_err("%s: unable to map IC registers\n", node->full_name);
		return -ENXIO;
	}

	/* disable all interrupts */
	writel(0, reg_base + IC_INT0ENABLE_LO);
	writel(0, reg_base + IC_INT0ENABLE_XLO);

	ucregs = syscon_regmap_lookup_by_phandle(node, "syscon");
	if (IS_ERR(ucregs)) {
		pr_err("%s: unable to map UC registers\n", node->full_name);
		return PTR_ERR(ucregs);
	}
	/* channel 1, regular IRQs */
	regmap_write(ucregs, UC_IRQ_CONTROL, 1);

	digicolor_irq_domain =
		irq_domain_add_linear(node, 64, &irq_generic_chip_ops, NULL);
	if (!digicolor_irq_domain) {
		pr_err("%s: unable to create IRQ domain\n", node->full_name);
		return -ENOMEM;
	}

	ret = irq_alloc_domain_generic_chips(digicolor_irq_domain, 32, 1,
					     "digicolor_irq", handle_level_irq,
					     clr, 0, 0);
	if (ret) {
		pr_err("%s: unable to allocate IRQ gc\n", node->full_name);
		return ret;
	}

	digicolor_set_gc(reg_base, 0, IC_INT0ENABLE_LO, IC_FLAG_CLEAR_LO);
	digicolor_set_gc(reg_base, 32, IC_INT0ENABLE_XLO, IC_FLAG_CLEAR_XLO);

	set_handle_irq(digicolor_handle_irq);

	return 0;
}
示例#12
0
static int __init armctrl_of_init(struct device_node *node,
				  struct device_node *parent,
				  bool is_2836)
{
	void __iomem *base;
	int irq, b, i;

	base = of_iomap(node, 0);
	if (!base)
		panic("%s: unable to map IC registers\n",
			node->full_name);

	intc.domain = irq_domain_add_linear(node, MAKE_HWIRQ(NR_BANKS, 0),
			&armctrl_ops, NULL);
	if (!intc.domain)
		panic("%s: unable to create IRQ domain\n", node->full_name);

	for (b = 0; b < NR_BANKS; b++) {
		intc.pending[b] = base + reg_pending[b];
		intc.enable[b] = base + reg_enable[b];
		intc.disable[b] = base + reg_disable[b];

		for (i = 0; i < bank_irqs[b]; i++) {
			irq = irq_create_mapping(intc.domain, MAKE_HWIRQ(b, i));
			BUG_ON(irq <= 0);
			irq_set_chip_and_handler(irq, &armctrl_chip,
				handle_level_irq);
			irq_set_probe(irq);
		}
	}

	if (is_2836) {
		int parent_irq = irq_of_parse_and_map(node, 0);

		if (!parent_irq) {
			panic("%s: unable to get parent interrupt.\n",
			      node->full_name);
		}
		irq_set_chained_handler(parent_irq, bcm2836_chained_handle_irq);
	} else {
		set_handle_irq(bcm2835_handle_irq);
	}

	return 0;
}
void __init dove_init_irq(void)
{
	orion_irq_init(1, IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF);
	orion_irq_init(33, IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF);

	set_handle_irq(dove_legacy_handle_irq);

	/*
	 * Initialize gpiolib for GPIOs 0-71.
	 */
	orion_gpio_init(NULL, 0, 32, DOVE_GPIO_LO_VIRT_BASE, 0,
			IRQ_DOVE_GPIO_START, gpio0_irqs);

	orion_gpio_init(NULL, 32, 32, DOVE_GPIO_HI_VIRT_BASE, 0,
			IRQ_DOVE_GPIO_START + 32, gpio1_irqs);

	orion_gpio_init(NULL, 64, 8, DOVE_GPIO2_VIRT_BASE, 0,
			IRQ_DOVE_GPIO_START + 64, gpio2_irqs);
}
示例#14
0
static int __init aic5_of_init(struct device_node *node,
			       struct device_node *parent,
			       int nirqs)
{
	struct irq_chip_generic *gc;
	struct irq_domain *domain;
	int nchips;
	int i;

	if (nirqs > NR_AIC5_IRQS)
		return -EINVAL;

	if (aic5_domain)
		return -EEXIST;

	domain = aic_common_of_init(node, &aic5_irq_ops, "atmel-aic5",
				    nirqs);
	if (IS_ERR(domain))
		return PTR_ERR(domain);

	aic_common_irq_fixup(aic5_irq_fixups);

	aic5_domain = domain;
	nchips = aic5_domain->revmap_size / 32;
	for (i = 0; i < nchips; i++) {
		gc = irq_get_domain_generic_chip(domain, i * 32);

		gc->chip_types[0].regs.eoi = AT91_AIC5_EOICR;
		gc->chip_types[0].chip.irq_mask = aic5_mask;
		gc->chip_types[0].chip.irq_unmask = aic5_unmask;
		gc->chip_types[0].chip.irq_retrigger = aic5_retrigger;
		gc->chip_types[0].chip.irq_set_type = aic5_set_type;
		gc->chip_types[0].chip.irq_suspend = aic5_suspend;
		gc->chip_types[0].chip.irq_resume = aic5_resume;
		gc->chip_types[0].chip.irq_pm_shutdown = aic5_pm_shutdown;
	}

	aic5_hw_init(domain);
	set_handle_irq(aic5_handle);

	return 0;
}
int __init fpga_irq_of_init(struct device_node *node,
			    struct device_node *parent)
{
	void __iomem *base;
	u32 clear_mask;
	u32 valid_mask;
	int parent_irq;

	if (WARN_ON(!node))
		return -ENODEV;

	base = of_iomap(node, 0);
	WARN(!base, "unable to map fpga irq registers\n");

	if (of_property_read_u32(node, "clear-mask", &clear_mask))
		clear_mask = 0;

	if (of_property_read_u32(node, "valid-mask", &valid_mask))
		valid_mask = 0;

	/* Some chips are cascaded from a parent IRQ */
	parent_irq = irq_of_parse_and_map(node, 0);
	if (!parent_irq) {
		set_handle_irq(fpga_handle_irq);
		parent_irq = -1;
	}

	fpga_irq_init(base, node->name, 0, parent_irq, valid_mask, node);

	writel(clear_mask, base + IRQ_ENABLE_CLEAR);
	writel(clear_mask, base + FIQ_ENABLE_CLEAR);

	/*
	 * On Versatile AB/PB, some secondary interrupts have a direct
	 * pass-thru to the primary controller for IRQs 20 and 22-31 which need
	 * to be enabled. See section 3.10 of the Versatile AB user guide.
	 */
	if (of_device_is_compatible(node, "arm,versatile-sic"))
		writel(0xffd00000, base + PIC_ENABLES);

	return 0;
}
示例#16
0
文件: irq.c 项目: 383530895/linux
void __init sa1100_init_irq(void)
{
	request_resource(&iomem_resource, &irq_resource);

	/* disable all IRQs */
	ICMR = 0;

	/* all IRQs are IRQ, not FIQ */
	ICLR = 0;

	/* clear all GPIO edge detects */
	GFER = 0;
	GRER = 0;
	GEDR = -1;

	/*
	 * Whatever the doc says, this has to be set for the wait-on-irq
	 * instruction to work... on a SA1100 rev 9 at least.
	 */
	ICCR = 1;

	sa1100_low_gpio_irqdomain = irq_domain_add_legacy(NULL,
			11, IRQ_GPIO0, 0,
			&sa1100_low_gpio_irqdomain_ops, NULL);

	sa1100_normal_irqdomain = irq_domain_add_legacy(NULL,
			21, IRQ_GPIO11_27, 11,
			&sa1100_normal_irqdomain_ops, NULL);

	sa1100_high_gpio_irqdomain = irq_domain_add_legacy(NULL,
			17, IRQ_GPIO11, 11,
			&sa1100_high_gpio_irqdomain_ops, NULL);

	/*
	 * Install handler for GPIO 11-27 edge detect interrupts
	 */
	irq_set_chained_handler(IRQ_GPIO11_27, sa1100_high_gpio_handler);

	set_handle_irq(sa1100_handle_irq);

	sa1100_init_gpio();
}
示例#17
0
static int __init sirfsoc_irq_init(struct device_node *np, struct device_node *parent)
{
	void __iomem *base = of_iomap(np, 0);
	if (!base)
		panic("unable to map intc cpu registers\n");

	sirfsoc_irqdomain = irq_domain_add_linear(np, SIRFSOC_NUM_IRQS,
		&irq_generic_chip_ops, base);

	sirfsoc_alloc_gc(base, 0, 32);
	sirfsoc_alloc_gc(base + 4, 32, SIRFSOC_NUM_IRQS - 32);

	writel_relaxed(0, base + SIRFSOC_INT_RISC_LEVEL0);
	writel_relaxed(0, base + SIRFSOC_INT_RISC_LEVEL1);

	writel_relaxed(0, base + SIRFSOC_INT_RISC_MASK0);
	writel_relaxed(0, base + SIRFSOC_INT_RISC_MASK1);

	set_handle_irq(sirfsoc_handle_irq);

	return 0;
}
示例#18
0
int __init ft010_of_init_irq(struct device_node *node,
			      struct device_node *parent)
{
	struct ft010_irq_data *f = &firq;

	/*
	 * Disable the idle handler by default since it is buggy
	 * For more info see arch/arm/mach-gemini/idle.c
	 */
	cpu_idle_poll_ctrl(true);

	f->base = of_iomap(node, 0);
	WARN(!f->base, "unable to map gemini irq registers\n");

	/* Disable all interrupts */
	writel(0, FT010_IRQ_MASK(f->base));
	writel(0, FT010_FIQ_MASK(f->base));

	f->domain = irq_domain_add_simple(node, FT010_NUM_IRQS, 0,
					  &ft010_irqdomain_ops, f);
	set_handle_irq(ft010_irqchip_handle_irq);

	return 0;
}
示例#19
0
文件: irq.c 项目: 01org/prd
void __init dove_init_irq(void)
{
	int i;

	orion_irq_init(1, IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF);
	orion_irq_init(33, IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF);

#ifdef CONFIG_MULTI_IRQ_HANDLER
	set_handle_irq(dove_legacy_handle_irq);
#endif

	/*
	 * Initialize gpiolib for GPIOs 0-71.
	 */
	orion_gpio_init(NULL, 0, 32, DOVE_GPIO_LO_VIRT_BASE, 0,
			IRQ_DOVE_GPIO_START, gpio0_irqs);

	orion_gpio_init(NULL, 32, 32, DOVE_GPIO_HI_VIRT_BASE, 0,
			IRQ_DOVE_GPIO_START + 32, gpio1_irqs);

	orion_gpio_init(NULL, 64, 8, DOVE_GPIO2_VIRT_BASE, 0,
			IRQ_DOVE_GPIO_START + 64, gpio2_irqs);

	/*
	 * Mask and clear PMU interrupts
	 */
	writel(0, PMU_INTERRUPT_MASK);
	writel(0, PMU_INTERRUPT_CAUSE);

	for (i = IRQ_DOVE_PMU_START; i < NR_IRQS; i++) {
		irq_set_chip_and_handler(i, &pmu_irq_chip, handle_level_irq);
		irq_set_status_flags(i, IRQ_LEVEL);
		set_irq_flags(i, IRQF_VALID);
	}
	irq_set_chained_handler(IRQ_DOVE_PMU, pmu_irq_handler);
}
示例#20
0
static struct s3c_irq_intc * __init s3c24xx_init_intc(struct device_node *np,
				       struct s3c_irq_data *irq_data,
				       struct s3c_irq_intc *parent,
				       unsigned long address)
{
	struct s3c_irq_intc *intc;
	void __iomem *base = (void *)0xf6000000; /* static mapping */
	int irq_num;
	int irq_start;
	int ret;

	intc = kzalloc(sizeof(struct s3c_irq_intc), GFP_KERNEL);
	if (!intc)
		return ERR_PTR(-ENOMEM);

	intc->irqs = irq_data;

	if (parent)
		intc->parent = parent;

	/* select the correct data for the controller.
	 * Need to hard code the irq num start and offset
	 * to preserve the static mapping for now
	 */
	switch (address) {
	case 0x4a000000:
		pr_debug("irq: found main intc\n");
		intc->reg_pending = base;
		intc->reg_mask = base + 0x08;
		intc->reg_intpnd = base + 0x10;
		irq_num = 32;
		irq_start = S3C2410_IRQ(0);
		break;
	case 0x4a000018:
		pr_debug("irq: found subintc\n");
		intc->reg_pending = base + 0x18;
		intc->reg_mask = base + 0x1c;
		irq_num = 29;
		irq_start = S3C2410_IRQSUB(0);
		break;
	case 0x4a000040:
		pr_debug("irq: found intc2\n");
		intc->reg_pending = base + 0x40;
		intc->reg_mask = base + 0x48;
		intc->reg_intpnd = base + 0x50;
		irq_num = 8;
		irq_start = S3C2416_IRQ(0);
		break;
	case 0x560000a4:
		pr_debug("irq: found eintc\n");
		base = (void *)0xfd000000;

		intc->reg_mask = base + 0xa4;
		intc->reg_pending = base + 0xa8;
		irq_num = 24;
		irq_start = S3C2410_IRQ(32);
		break;
	default:
		pr_err("irq: unsupported controller address\n");
		ret = -EINVAL;
		goto err;
	}

	/* now that all the data is complete, init the irq-domain */
	s3c24xx_clear_intc(intc);
	intc->domain = irq_domain_add_legacy(np, irq_num, irq_start,
					     0, &s3c24xx_irq_ops,
					     intc);
	if (!intc->domain) {
		pr_err("irq: could not create irq-domain\n");
		ret = -EINVAL;
		goto err;
	}

	set_handle_irq(s3c24xx_handle_irq);

	return intc;

err:
	kfree(intc);
	return ERR_PTR(ret);
}
示例#21
0
static int __init s3c_init_intc_of(struct device_node *np,
			struct device_node *interrupt_parent,
			struct s3c24xx_irq_of_ctrl *s3c_ctrl, int num_ctrl)
{
	struct s3c_irq_intc *intc;
	struct s3c24xx_irq_of_ctrl *ctrl;
	struct irq_domain *domain;
	void __iomem *reg_base;
	int i;

	reg_base = of_iomap(np, 0);
	if (!reg_base) {
		pr_err("irq-s3c24xx: could not map irq registers\n");
		return -EINVAL;
	}

	domain = irq_domain_add_linear(np, num_ctrl * 32,
						     &s3c24xx_irq_ops_of, NULL);
	if (!domain) {
		pr_err("irq: could not create irq-domain\n");
		return -EINVAL;
	}

	for (i = 0; i < num_ctrl; i++) {
		ctrl = &s3c_ctrl[i];

		pr_debug("irq: found controller %s\n", ctrl->name);

		intc = kzalloc(sizeof(struct s3c_irq_intc), GFP_KERNEL);
		if (!intc)
			return -ENOMEM;

		intc->domain = domain;
		intc->irqs = kzalloc(sizeof(struct s3c_irq_data) * 32,
				     GFP_KERNEL);
		if (!intc->irqs) {
			kfree(intc);
			return -ENOMEM;
		}

		if (ctrl->parent) {
			intc->reg_pending = reg_base + ctrl->offset;
			intc->reg_mask = reg_base + ctrl->offset + 0x4;

			if (*(ctrl->parent)) {
				intc->parent = *(ctrl->parent);
			} else {
				pr_warn("irq: parent of %s missing\n",
					ctrl->name);
				kfree(intc->irqs);
				kfree(intc);
				continue;
			}
		} else {
			intc->reg_pending = reg_base + ctrl->offset;
			intc->reg_mask = reg_base + ctrl->offset + 0x08;
			intc->reg_intpnd = reg_base + ctrl->offset + 0x10;
		}

		s3c24xx_clear_intc(intc);
		s3c_intc[i] = intc;
	}

	set_handle_irq(s3c24xx_handle_irq);

	return 0;
}