コード例 #1
0
ファイル: irq-tb10x.c プロジェクト: 03199618/linux
static int __init of_tb10x_init_irq(struct device_node *ictl,
					struct device_node *parent)
{
	int i, ret, nrirqs = of_irq_count(ictl);
	struct resource mem;
	struct irq_chip_generic *gc;
	struct irq_domain *domain;
	void __iomem *reg_base;

	if (of_address_to_resource(ictl, 0, &mem)) {
		pr_err("%s: No registers declared in DeviceTree.\n",
			ictl->name);
		return -EINVAL;
	}

	if (!request_mem_region(mem.start, resource_size(&mem),
		ictl->name)) {
		pr_err("%s: Request mem region failed.\n", ictl->name);
		return -EBUSY;
	}

	reg_base = ioremap(mem.start, resource_size(&mem));
	if (!reg_base) {
		ret = -EBUSY;
		pr_err("%s: ioremap failed.\n", ictl->name);
		goto ioremap_fail;
	}

	domain = irq_domain_add_linear(ictl, AB_IRQCTL_MAXIRQ,
					&irq_generic_chip_ops, NULL);
	if (!domain) {
		ret = -ENOMEM;
		pr_err("%s: Could not register interrupt domain.\n",
			ictl->name);
		goto irq_domain_add_fail;
	}

	ret = irq_alloc_domain_generic_chips(domain, AB_IRQCTL_MAXIRQ,
				2, ictl->name, handle_level_irq,
				IRQ_NOREQUEST, IRQ_NOPROBE,
				IRQ_GC_INIT_MASK_CACHE);
	if (ret) {
		pr_err("%s: Could not allocate generic interrupt chip.\n",
			ictl->name);
		goto gc_alloc_fail;
	}

	gc = domain->gc->gc[0];
	gc->reg_base                         = reg_base;

	gc->chip_types[0].type               = IRQ_TYPE_LEVEL_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;
	gc->chip_types[0].chip.irq_set_type  = tb10x_irq_set_type;
	gc->chip_types[0].regs.mask          = AB_IRQCTL_INT_ENABLE;

	gc->chip_types[1].type               = IRQ_TYPE_EDGE_BOTH;
	gc->chip_types[1].chip.name          = gc->chip_types[0].chip.name;
	gc->chip_types[1].chip.irq_ack       = irq_gc_ack_set_bit;
	gc->chip_types[1].chip.irq_mask      = irq_gc_mask_clr_bit;
	gc->chip_types[1].chip.irq_unmask    = irq_gc_mask_set_bit;
	gc->chip_types[1].chip.irq_set_type  = tb10x_irq_set_type;
	gc->chip_types[1].regs.ack           = AB_IRQCTL_INT_STATUS;
	gc->chip_types[1].regs.mask          = AB_IRQCTL_INT_ENABLE;
	gc->chip_types[1].handler            = handle_edge_irq;

	for (i = 0; i < nrirqs; i++) {
		unsigned int irq = irq_of_parse_and_map(ictl, i);

		irq_set_handler_data(irq, domain);
		irq_set_chained_handler(irq, tb10x_irq_cascade);
	}

	ab_irqctl_writereg(gc, AB_IRQCTL_INT_ENABLE, 0);
	ab_irqctl_writereg(gc, AB_IRQCTL_INT_MODE, 0);
	ab_irqctl_writereg(gc, AB_IRQCTL_INT_POLARITY, 0);
	ab_irqctl_writereg(gc, AB_IRQCTL_INT_STATUS, ~0UL);

	return 0;

gc_alloc_fail:
	irq_domain_remove(domain);
irq_domain_add_fail:
	iounmap(reg_base);
ioremap_fail:
	release_mem_region(mem.start, resource_size(&mem));
	return ret;
}
コード例 #2
0
static int pdc_intc_probe(struct platform_device *pdev)
{
	struct pdc_intc_priv *priv;
	struct device_node *node = pdev->dev.of_node;
	struct resource *res_regs;
	struct irq_chip_generic *gc;
	unsigned int i;
	int irq, ret;
	u32 val;

	if (!node)
		return -ENOENT;

	/* Get registers */
	res_regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (res_regs == NULL) {
		dev_err(&pdev->dev, "cannot find registers resource\n");
		return -ENOENT;
	}

	/* Allocate driver data */
	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
	if (!priv) {
		dev_err(&pdev->dev, "cannot allocate device data\n");
		return -ENOMEM;
	}
	raw_spin_lock_init(&priv->lock);
	platform_set_drvdata(pdev, priv);

	/* Ioremap the registers */
	priv->pdc_base = devm_ioremap(&pdev->dev, res_regs->start,
				      res_regs->end - res_regs->start);
	if (!priv->pdc_base)
		return -EIO;

	/* Get number of peripherals */
	ret = of_property_read_u32(node, "num-perips", &val);
	if (ret) {
		dev_err(&pdev->dev, "No num-perips node property found\n");
		return -EINVAL;
	}
	if (val > SYS0_HWIRQ) {
		dev_err(&pdev->dev, "num-perips (%u) out of range\n", val);
		return -EINVAL;
	}
	priv->nr_perips = val;

	/* Get number of syswakes */
	ret = of_property_read_u32(node, "num-syswakes", &val);
	if (ret) {
		dev_err(&pdev->dev, "No num-syswakes node property found\n");
		return -EINVAL;
	}
	if (val > SYS0_HWIRQ) {
		dev_err(&pdev->dev, "num-syswakes (%u) out of range\n", val);
		return -EINVAL;
	}
	priv->nr_syswakes = val;

	/* Get peripheral IRQ numbers */
	priv->perip_irqs = devm_kzalloc(&pdev->dev, 4 * priv->nr_perips,
					GFP_KERNEL);
	if (!priv->perip_irqs) {
		dev_err(&pdev->dev, "cannot allocate perip IRQ list\n");
		return -ENOMEM;
	}
	for (i = 0; i < priv->nr_perips; ++i) {
		irq = platform_get_irq(pdev, 1 + i);
		if (irq < 0) {
			dev_err(&pdev->dev, "cannot find perip IRQ #%u\n", i);
			return irq;
		}
		priv->perip_irqs[i] = irq;
	}
	/* check if too many were provided */
	if (platform_get_irq(pdev, 1 + i) >= 0) {
		dev_err(&pdev->dev, "surplus perip IRQs detected\n");
		return -EINVAL;
	}

	/* Get syswake IRQ number */
	irq = platform_get_irq(pdev, 0);
	if (irq < 0) {
		dev_err(&pdev->dev, "cannot find syswake IRQ\n");
		return irq;
	}
	priv->syswake_irq = irq;

	/* Set up an IRQ domain */
	priv->domain = irq_domain_add_linear(node, 16, &irq_generic_chip_ops,
					     priv);
	if (unlikely(!priv->domain)) {
		dev_err(&pdev->dev, "cannot add IRQ domain\n");
		return -ENOMEM;
	}

	/*
	 * Set up 2 generic irq chips with 2 chip types.
	 * The first one for peripheral irqs (only 1 chip type used)
	 * The second one for syswake irqs (edge and level chip types)
	 */
	ret = irq_alloc_domain_generic_chips(priv->domain, 8, 2, "pdc",
					     handle_level_irq, 0, 0,
					     IRQ_GC_INIT_NESTED_LOCK);
	if (ret)
		goto err_generic;

	/* peripheral interrupt chip */

	gc = irq_get_domain_generic_chip(priv->domain, 0);
	gc->unused	= ~(BIT(priv->nr_perips) - 1);
	gc->reg_base	= priv->pdc_base;
	/*
	 * IRQ_ROUTE contains wake bits, so we can't use the generic versions as
	 * they cache the mask
	 */
	gc->chip_types[0].regs.mask		= PDC_IRQ_ROUTE;
	gc->chip_types[0].chip.irq_mask		= perip_irq_mask;
	gc->chip_types[0].chip.irq_unmask	= perip_irq_unmask;
	gc->chip_types[0].chip.irq_set_wake	= pdc_irq_set_wake;

	/* syswake interrupt chip */

	gc = irq_get_domain_generic_chip(priv->domain, 8);
	gc->unused	= ~(BIT(priv->nr_syswakes) - 1);
	gc->reg_base	= priv->pdc_base;

	/* edge interrupts */
	gc->chip_types[0].type			= IRQ_TYPE_EDGE_BOTH;
	gc->chip_types[0].handler		= handle_edge_irq;
	gc->chip_types[0].regs.ack		= PDC_IRQ_CLEAR;
	gc->chip_types[0].regs.mask		= PDC_IRQ_ENABLE;
	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;
	gc->chip_types[0].chip.irq_set_type	= syswake_irq_set_type;
	gc->chip_types[0].chip.irq_set_wake	= pdc_irq_set_wake;
	/* for standby we pass on to the shared syswake IRQ */
	gc->chip_types[0].chip.flags		= IRQCHIP_MASK_ON_SUSPEND;

	/* level interrupts */
	gc->chip_types[1].type			= IRQ_TYPE_LEVEL_MASK;
	gc->chip_types[1].handler		= handle_level_irq;
	gc->chip_types[1].regs.ack		= PDC_IRQ_CLEAR;
	gc->chip_types[1].regs.mask		= PDC_IRQ_ENABLE;
	gc->chip_types[1].chip.irq_ack		= irq_gc_ack_set_bit;
	gc->chip_types[1].chip.irq_mask		= irq_gc_mask_clr_bit;
	gc->chip_types[1].chip.irq_unmask	= irq_gc_mask_set_bit;
	gc->chip_types[1].chip.irq_set_type	= syswake_irq_set_type;
	gc->chip_types[1].chip.irq_set_wake	= pdc_irq_set_wake;
	/* for standby we pass on to the shared syswake IRQ */
	gc->chip_types[1].chip.flags		= IRQCHIP_MASK_ON_SUSPEND;

	/* Set up the hardware to enable interrupt routing */
	pdc_intc_setup(priv);

	/* Setup chained handlers for the peripheral IRQs */
	for (i = 0; i < priv->nr_perips; ++i) {
		irq = priv->perip_irqs[i];
		irq_set_handler_data(irq, priv);
		irq_set_chained_handler(irq, pdc_intc_perip_isr);
	}

	/* Setup chained handler for the syswake IRQ */
	irq_set_handler_data(priv->syswake_irq, priv);
	irq_set_chained_handler(priv->syswake_irq, pdc_intc_syswake_isr);

	dev_info(&pdev->dev,
		 "PDC IRQ controller initialised (%u perip IRQs, %u syswake IRQs)\n",
		 priv->nr_perips,
		 priv->nr_syswakes);

	return 0;
err_generic:
	irq_domain_remove(priv->domain);
	return ret;
}
コード例 #3
0
static int s3c24xx_irq_map(struct irq_domain *h, unsigned int virq,
                           irq_hw_number_t hw)
{
    struct s3c_irq_intc *intc = h->host_data;
    struct s3c_irq_data *irq_data = &intc->irqs[hw];
    struct s3c_irq_intc *parent_intc;
    struct s3c_irq_data *parent_irq_data;
    unsigned int irqno;

    /* attach controller pointer to irq_data */
    irq_data->intc = intc;
    irq_data->offset = hw;

    parent_intc = intc->parent;

    /* set handler and flags */
    switch (irq_data->type) {
    case S3C_IRQTYPE_NONE:
        return 0;
    case S3C_IRQTYPE_EINT:
        /* On the S3C2412, the EINT0to3 have a parent irq
         * but need the s3c_irq_eint0t4 chip
         */
        if (parent_intc && (!soc_is_s3c2412() || hw >= 4))
            irq_set_chip_and_handler(virq, &s3c_irqext_chip,
                                     handle_edge_irq);
        else
            irq_set_chip_and_handler(virq, &s3c_irq_eint0t4,
                                     handle_edge_irq);
        break;
    case S3C_IRQTYPE_EDGE:
        if (parent_intc || intc->reg_pending == S3C2416_SRCPND2)
            irq_set_chip_and_handler(virq, &s3c_irq_level_chip,
                                     handle_edge_irq);
        else
            irq_set_chip_and_handler(virq, &s3c_irq_chip,
                                     handle_edge_irq);
        break;
    case S3C_IRQTYPE_LEVEL:
        if (parent_intc)
            irq_set_chip_and_handler(virq, &s3c_irq_level_chip,
                                     handle_level_irq);
        else
            irq_set_chip_and_handler(virq, &s3c_irq_chip,
                                     handle_level_irq);
        break;
    default:
        pr_err("irq-s3c24xx: unsupported irqtype %d\n", irq_data->type);
        return -EINVAL;
    }

    irq_set_chip_data(virq, irq_data);

    set_irq_flags(virq, IRQF_VALID);

    if (parent_intc && irq_data->type != S3C_IRQTYPE_NONE) {
        if (irq_data->parent_irq > 31) {
            pr_err("irq-s3c24xx: parent irq %lu is out of range\n",
                   irq_data->parent_irq);
            goto err;
        }

        parent_irq_data = &parent_intc->irqs[irq_data->parent_irq];
        parent_irq_data->sub_intc = intc;
        parent_irq_data->sub_bits |= (1UL << hw);

        /* attach the demuxer to the parent irq */
        irqno = irq_find_mapping(parent_intc->domain,
                                 irq_data->parent_irq);
        if (!irqno) {
            pr_err("irq-s3c24xx: could not find mapping for parent irq %lu\n",
                   irq_data->parent_irq);
            goto err;
        }
        irq_set_chained_handler(irqno, s3c_irq_demux);
    }

    return 0;

err:
    set_irq_flags(virq, 0);

    /* the only error can result from bad mapping data*/
    return -EINVAL;
}
コード例 #4
0
ファイル: gpio-zynq.c プロジェクト: DenisKuzovin/linux-xlnx
/**
 * zynq_gpio_probe - Initialization method for a zynq_gpio device
 * @pdev:	platform device instance
 *
 * This function allocates memory resources for the gpio device and registers
 * all the banks of the device. It will also set up interrupts for the gpio
 * pins.
 * Note: Interrupts are disabled for all the banks during initialization.
 *
 * Return: 0 on success, negative error otherwise.
 */
static int zynq_gpio_probe(struct platform_device *pdev)
{
	int ret, pin_num, bank_num, gpio_irq;
	unsigned int irq_num;
	struct zynq_gpio *gpio;
	struct gpio_chip *chip;
	struct resource *res;

	gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
	if (!gpio)
		return -ENOMEM;

	platform_set_drvdata(pdev, gpio);

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	gpio->base_addr = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(gpio->base_addr))
		return PTR_ERR(gpio->base_addr);

	irq_num = platform_get_irq(pdev, 0);
	gpio->irq = irq_num;

	/* configure the gpio chip */
	chip = &gpio->chip;
	chip->label = "zynq_gpio";
	chip->owner = THIS_MODULE;
	chip->dev = &pdev->dev;
	chip->get = zynq_gpio_get_value;
	chip->set = zynq_gpio_set_value;
	chip->request = zynq_gpio_request;
	chip->free = zynq_gpio_free;
	chip->direction_input = zynq_gpio_dir_in;
	chip->direction_output = zynq_gpio_dir_out;
	chip->to_irq = zynq_gpio_to_irq;
	chip->dbg_show = NULL;
	chip->base = 0;		/* default pin base */
	chip->ngpio = ZYNQ_GPIO_NR_GPIOS;
	chip->can_sleep = 0;

	gpio->irq_base = irq_alloc_descs(-1, 0, chip->ngpio, 0);
	if (gpio->irq_base < 0) {
		dev_err(&pdev->dev, "Couldn't allocate IRQ numbers\n");
		return -ENODEV;
	}

	irq_domain = irq_domain_add_legacy(pdev->dev.of_node,
					   chip->ngpio, gpio->irq_base, 0,
					   &irq_domain_simple_ops, NULL);

	/* report a bug if gpio chip registration fails */
	ret = gpiochip_add(chip);
	if (ret < 0)
		return ret;

	/* Enable GPIO clock */
	gpio->clk = devm_clk_get(&pdev->dev, NULL);
	if (IS_ERR(gpio->clk)) {
		dev_err(&pdev->dev, "input clock not found.\n");
		if (gpiochip_remove(chip))
			dev_err(&pdev->dev, "Failed to remove gpio chip\n");
		return PTR_ERR(gpio->clk);
	}
	ret = clk_prepare_enable(gpio->clk);
	if (ret) {
		dev_err(&pdev->dev, "Unable to enable clock.\n");
		if (gpiochip_remove(chip))
			dev_err(&pdev->dev, "Failed to remove gpio chip\n");
		return ret;
	}

	/* disable interrupts for all banks */
	for (bank_num = 0; bank_num < ZYNQ_GPIO_MAX_BANK; bank_num++) {
		zynq_gpio_writereg(gpio->base_addr +
				   ZYNQ_GPIO_INTDIS_OFFSET(bank_num),
				   ZYNQ_GPIO_IXR_DISABLE_ALL);
	}

	/*
	 * set the irq chip, handler and irq chip data for callbacks for
	 * each pin
	 */
	for (pin_num = 0; pin_num < min_t(int, ZYNQ_GPIO_NR_GPIOS,
					  (int)chip->ngpio); pin_num++) {
		gpio_irq = irq_find_mapping(irq_domain, pin_num);
		irq_set_chip_and_handler(gpio_irq, &zynq_gpio_irqchip,
					 handle_simple_irq);
		irq_set_chip_data(gpio_irq, (void *)gpio);
		set_irq_flags(gpio_irq, IRQF_VALID);
	}

	irq_set_handler_data(irq_num, (void *)gpio);
	irq_set_chained_handler(irq_num, zynq_gpio_irqhandler);

	pm_runtime_enable(&pdev->dev);

	device_set_wakeup_capable(&pdev->dev, 1);

	return 0;
}
コード例 #5
0
int __init pq2ads_pci_init_irq(void)
{
    struct pq2ads_pci_pic *priv;
    struct irq_host *host;
    struct device_node *np;
    int ret = -ENODEV;
    int irq;

    np = of_find_compatible_node(NULL, NULL, "fsl,pq2ads-pci-pic");
    if (!np) {
        printk(KERN_ERR "No pci pic node in device tree.\n");
        of_node_put(np);
        goto out;
    }

    irq = irq_of_parse_and_map(np, 0);
    if (irq == NO_IRQ) {
        printk(KERN_ERR "No interrupt in pci pic node.\n");
        of_node_put(np);
        goto out;
    }

    priv = kzalloc(sizeof(*priv), GFP_KERNEL);
    if (!priv) {
        of_node_put(np);
        ret = -ENOMEM;
        goto out_unmap_irq;
    }

    /* PCI interrupt controller registers: status and mask */
    priv->regs = of_iomap(np, 0);
    if (!priv->regs) {
        printk(KERN_ERR "Cannot map PCI PIC registers.\n");
        goto out_free_bootmem;
    }

    /* mask all PCI interrupts */
    out_be32(&priv->regs->mask, ~0);
    mb();

    host = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, NUM_IRQS,
                          &pci_pic_host_ops, NUM_IRQS);
    if (!host) {
        ret = -ENOMEM;
        goto out_unmap_regs;
    }

    host->host_data = priv;

    priv->host = host;
    host->host_data = priv;
    irq_set_handler_data(irq, priv);
    irq_set_chained_handler(irq, pq2ads_pci_irq_demux);

    of_node_put(np);
    return 0;

out_unmap_regs:
    iounmap(priv->regs);
out_free_bootmem:
    free_bootmem((unsigned long)priv,
                 sizeof(struct pq2ads_pci_pic));
    of_node_put(np);
out_unmap_irq:
    irq_dispose_mapping(irq);
out:
    return ret;
}
コード例 #6
0
static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
{
	struct device *dev = &adev->dev;
	struct pl061_platform_data *pdata = dev->platform_data;
	struct pl061_gpio *chip;
	int ret, irq, i, irq_base;
	struct device_node *np = dev->of_node;

	chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
	if (chip == NULL)
		return -ENOMEM;

	if (pdata) {
		chip->gc.base = pdata->gpio_base;
		irq_base = pdata->irq_base;
		if (irq_base <= 0)
			return -ENODEV;
	} else {
		chip->gc.base = pl061_parse_gpio_base(dev);
		irq_base = 0;
	}

	if (!devm_request_mem_region(dev, adev->res.start,
				     resource_size(&adev->res), "pl061"))
		return -EBUSY;

	chip->base = devm_ioremap(dev, adev->res.start,
				  resource_size(&adev->res));
	if (!chip->base)
		return -ENOMEM;

	spin_lock_init(&chip->lock);

	if (of_get_property(np, "gpio,hwspinlock", NULL)) {
		gpio_hwlock = hwspin_lock_request_specific(GPIO_HWLOCK_ID);
		if (gpio_hwlock == NULL)
			return -EBUSY;
	}

	/* Hook the request()/free() for pinctrl operation */
	if (of_get_property(dev->of_node, "gpio-ranges", NULL)) {
		chip->gc.request = pl061_gpio_request;
		chip->gc.free = pl061_gpio_free;
	}
	chip->gc.direction_input = pl061_direction_input;
	chip->gc.direction_output = pl061_direction_output;
	chip->gc.get = pl061_get_value;
	chip->gc.set = pl061_set_value;
	chip->gc.to_irq = pl061_to_irq;
	chip->gc.ngpio = PL061_GPIO_NR;
	chip->gc.label = dev_name(dev);
	chip->gc.dev = dev;
	chip->gc.owner = THIS_MODULE;

	ret = gpiochip_add(&chip->gc);
	if (ret)
		return ret;

	/*
	 * irq_chip support
	 */
	writeb(0, chip->base + GPIOIE); /* disable irqs */
	irq = adev->irq[0];
	if (irq < 0)
		return -ENODEV;

	irq_set_chained_handler(irq, pl061_irq_handler);
	irq_set_handler_data(irq, chip);

	chip->domain = irq_domain_add_simple(adev->dev.of_node, PL061_GPIO_NR,
					     irq_base, &pl061_domain_ops, chip);
	if (!chip->domain)
		return -ENODEV;

	for (i = 0; i < PL061_GPIO_NR; i++) {
		if (pdata) {
			if (pdata->directions & (1 << i))
				pl061_direction_output(&chip->gc, i,
						pdata->values & (1 << i));
			else
				pl061_direction_input(&chip->gc, i);
		}
	}

	amba_set_drvdata(adev, chip);

	return 0;
}
コード例 #7
0
/* MMP2 (ARMv7) */
void __init mmp2_init_icu(void)
{
	int irq;

	max_icu_nr = 8;
	mmp_icu_base = ioremap(0xd4282000, 0x1000);
	icu_data[0].conf_enable = mmp2_conf.conf_enable;
	icu_data[0].conf_disable = mmp2_conf.conf_disable;
	icu_data[0].conf_mask = mmp2_conf.conf_mask;
	icu_data[0].nr_irqs = 64;
	icu_data[0].virq_base = 0;
	icu_data[0].domain = irq_domain_add_legacy(NULL, 64, 0, 0,
						   &irq_domain_simple_ops,
						   &icu_data[0]);
	icu_data[1].reg_status = mmp_icu_base + 0x150;
	icu_data[1].reg_mask = mmp_icu_base + 0x168;
	icu_data[1].clr_mfp_irq_base = IRQ_MMP2_PMIC_BASE;
	icu_data[1].clr_mfp_hwirq = IRQ_MMP2_PMIC - IRQ_MMP2_PMIC_BASE;
	icu_data[1].nr_irqs = 2;
	icu_data[1].cascade_irq = 4;
	icu_data[1].virq_base = IRQ_MMP2_PMIC_BASE;
	icu_data[1].domain = irq_domain_add_legacy(NULL, icu_data[1].nr_irqs,
						   icu_data[1].virq_base, 0,
						   &irq_domain_simple_ops,
						   &icu_data[1]);
	icu_data[2].reg_status = mmp_icu_base + 0x154;
	icu_data[2].reg_mask = mmp_icu_base + 0x16c;
	icu_data[2].nr_irqs = 2;
	icu_data[2].cascade_irq = 5;
	icu_data[2].virq_base = IRQ_MMP2_RTC_BASE;
	icu_data[2].domain = irq_domain_add_legacy(NULL, icu_data[2].nr_irqs,
						   icu_data[2].virq_base, 0,
						   &irq_domain_simple_ops,
						   &icu_data[2]);
	icu_data[3].reg_status = mmp_icu_base + 0x180;
	icu_data[3].reg_mask = mmp_icu_base + 0x17c;
	icu_data[3].nr_irqs = 3;
	icu_data[3].cascade_irq = 9;
	icu_data[3].virq_base = IRQ_MMP2_KEYPAD_BASE;
	icu_data[3].domain = irq_domain_add_legacy(NULL, icu_data[3].nr_irqs,
						   icu_data[3].virq_base, 0,
						   &irq_domain_simple_ops,
						   &icu_data[3]);
	icu_data[4].reg_status = mmp_icu_base + 0x158;
	icu_data[4].reg_mask = mmp_icu_base + 0x170;
	icu_data[4].nr_irqs = 5;
	icu_data[4].cascade_irq = 17;
	icu_data[4].virq_base = IRQ_MMP2_TWSI_BASE;
	icu_data[4].domain = irq_domain_add_legacy(NULL, icu_data[4].nr_irqs,
						   icu_data[4].virq_base, 0,
						   &irq_domain_simple_ops,
						   &icu_data[4]);
	icu_data[5].reg_status = mmp_icu_base + 0x15c;
	icu_data[5].reg_mask = mmp_icu_base + 0x174;
	icu_data[5].nr_irqs = 15;
	icu_data[5].cascade_irq = 35;
	icu_data[5].virq_base = IRQ_MMP2_MISC_BASE;
	icu_data[5].domain = irq_domain_add_legacy(NULL, icu_data[5].nr_irqs,
						   icu_data[5].virq_base, 0,
						   &irq_domain_simple_ops,
						   &icu_data[5]);
	icu_data[6].reg_status = mmp_icu_base + 0x160;
	icu_data[6].reg_mask = mmp_icu_base + 0x178;
	icu_data[6].nr_irqs = 2;
	icu_data[6].cascade_irq = 51;
	icu_data[6].virq_base = IRQ_MMP2_MIPI_HSI1_BASE;
	icu_data[6].domain = irq_domain_add_legacy(NULL, icu_data[6].nr_irqs,
						   icu_data[6].virq_base, 0,
						   &irq_domain_simple_ops,
						   &icu_data[6]);
	icu_data[7].reg_status = mmp_icu_base + 0x188;
	icu_data[7].reg_mask = mmp_icu_base + 0x184;
	icu_data[7].nr_irqs = 2;
	icu_data[7].cascade_irq = 55;
	icu_data[7].virq_base = IRQ_MMP2_MIPI_HSI0_BASE;
	icu_data[7].domain = irq_domain_add_legacy(NULL, icu_data[7].nr_irqs,
						   icu_data[7].virq_base, 0,
						   &irq_domain_simple_ops,
						   &icu_data[7]);
	for (irq = 0; irq < IRQ_MMP2_MUX_END; irq++) {
		icu_mask_irq(irq_get_irq_data(irq));
		switch (irq) {
		case IRQ_MMP2_PMIC_MUX:
		case IRQ_MMP2_RTC_MUX:
		case IRQ_MMP2_KEYPAD_MUX:
		case IRQ_MMP2_TWSI_MUX:
		case IRQ_MMP2_MISC_MUX:
		case IRQ_MMP2_MIPI_HSI1_MUX:
		case IRQ_MMP2_MIPI_HSI0_MUX:
			irq_set_chip(irq, &icu_irq_chip);
			irq_set_chained_handler(irq, icu_mux_irq_demux);
			break;
		default:
			irq_set_chip_and_handler(irq, &icu_irq_chip,
						 handle_level_irq);
			break;
		}
		set_irq_flags(irq, IRQF_VALID);
	}
	irq_set_default_host(icu_data[0].domain);
#ifdef CONFIG_CPU_MMP2
	icu_irq_chip.irq_set_wake = mmp2_set_wake;
#endif
}
コード例 #8
0
ファイル: gpio-tz1090.c プロジェクト: 24hours/linux
static int tz1090_gpio_bank_probe(struct tz1090_gpio_bank_info *info)
{
	struct device_node *np = info->node;
	struct device *dev = info->priv->dev;
	struct tz1090_gpio_bank *bank;
	struct irq_chip_generic *gc;
	int err;

	bank = devm_kzalloc(dev, sizeof(*bank), GFP_KERNEL);
	if (!bank) {
		dev_err(dev, "unable to allocate driver data\n");
		return -ENOMEM;
	}

	/* Offset the main registers to the first register in this bank */
	bank->reg = info->priv->reg + info->index * 4;

	/* Set up GPIO chip */
	snprintf(bank->label, sizeof(bank->label), "tz1090-gpio-%u",
		 info->index);
	bank->chip.label		= bank->label;
	bank->chip.dev			= dev;
	bank->chip.direction_input	= tz1090_gpio_direction_input;
	bank->chip.direction_output	= tz1090_gpio_direction_output;
	bank->chip.get			= tz1090_gpio_get;
	bank->chip.set			= tz1090_gpio_set;
	bank->chip.free			= tz1090_gpio_free;
	bank->chip.request		= tz1090_gpio_request;
	bank->chip.to_irq		= tz1090_gpio_to_irq;
	bank->chip.of_node		= np;

	/* GPIO numbering from 0 */
	bank->chip.base			= info->index * 30;
	bank->chip.ngpio		= 30;

	/* Add the GPIO bank */
	gpiochip_add(&bank->chip);

	/* Get the GPIO bank IRQ if provided */
	bank->irq = irq_of_parse_and_map(np, 0);

	/* The interrupt is optional (it may be used by another core on chip) */
	if (bank->irq < 0) {
		dev_info(dev, "IRQ not provided for bank %u, IRQs disabled\n",
			 info->index);
		return 0;
	}

	dev_info(dev, "Setting up IRQs for GPIO bank %u\n",
		 info->index);

	/*
	 * Initialise all interrupts to disabled so we don't get
	 * spurious ones on a dirty boot and hit the BUG_ON in the
	 * handler.
	 */
	tz1090_gpio_write(bank, REG_GPIO_IRQ_EN, 0);

	/* Add a virtual IRQ for each GPIO */
	bank->domain = irq_domain_add_linear(np,
					     bank->chip.ngpio,
					     &irq_generic_chip_ops,
					     bank);

	/* Set up a generic irq chip with 2 chip types (level and edge) */
	err = irq_alloc_domain_generic_chips(bank->domain, bank->chip.ngpio, 2,
					     bank->label, handle_bad_irq, 0, 0,
					     IRQ_GC_INIT_NESTED_LOCK);
	if (err) {
		dev_info(dev,
			 "irq_alloc_domain_generic_chips failed for bank %u, IRQs disabled\n",
			 info->index);
		irq_domain_remove(bank->domain);
		return 0;
	}

	gc = irq_get_domain_generic_chip(bank->domain, 0);
	gc->reg_base	= bank->reg;

	/* level chip type */
	gc->chip_types[0].type			= IRQ_TYPE_LEVEL_MASK;
	gc->chip_types[0].handler		= handle_level_irq;
	gc->chip_types[0].regs.ack		= REG_GPIO_IRQ_STS;
	gc->chip_types[0].regs.mask		= REG_GPIO_IRQ_EN;
	gc->chip_types[0].chip.irq_startup	= gpio_startup_irq;
	gc->chip_types[0].chip.irq_ack		= irq_gc_ack_clr_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;
	gc->chip_types[0].chip.irq_set_type	= gpio_set_irq_type;
	gc->chip_types[0].chip.irq_set_wake	= gpio_set_irq_wake;
	gc->chip_types[0].chip.flags		= IRQCHIP_MASK_ON_SUSPEND;

	/* edge chip type */
	gc->chip_types[1].type			= IRQ_TYPE_EDGE_BOTH;
	gc->chip_types[1].handler		= handle_edge_irq;
	gc->chip_types[1].regs.ack		= REG_GPIO_IRQ_STS;
	gc->chip_types[1].regs.mask		= REG_GPIO_IRQ_EN;
	gc->chip_types[1].chip.irq_startup	= gpio_startup_irq;
	gc->chip_types[1].chip.irq_ack		= irq_gc_ack_clr_bit;
	gc->chip_types[1].chip.irq_mask		= irq_gc_mask_clr_bit;
	gc->chip_types[1].chip.irq_unmask	= irq_gc_mask_set_bit;
	gc->chip_types[1].chip.irq_set_type	= gpio_set_irq_type;
	gc->chip_types[1].chip.irq_set_wake	= gpio_set_irq_wake;
	gc->chip_types[1].chip.flags		= IRQCHIP_MASK_ON_SUSPEND;

	/* Setup chained handler for this GPIO bank */
	irq_set_handler_data(bank->irq, bank);
	irq_set_chained_handler(bank->irq, tz1090_gpio_irq_handler);

	return 0;
}
コード例 #9
0
static int __devinit jz_adc_probe(struct platform_device *pdev)
{
	int ret;
	struct jz_adc *adc;
	struct resource *mem_base;
	int irq;
	int i;
	unsigned char clkdiv, clkdiv_us;
	unsigned short clkdiv_ms;
	struct jz_battery_info *battery_info;
	struct jz_adc_platform_data *adc_platform_data = pdev->dev.platform_data;
	if(!adc_platform_data)
	{
		dev_err(&pdev->dev,"no platform data,can't attach\n");
		return -EINVAL;
	}
	battery_info = &adc_platform_data->battery_info;
	adc = kmalloc(sizeof(*adc), GFP_KERNEL);
	if (!adc) {
		dev_err(&pdev->dev, "Failed to allocate driver structre\n");
		return -ENOMEM;
	}

	adc->irq = platform_get_irq(pdev, 0);
	if (adc->irq < 0) {
		ret = adc->irq;
		dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret);
		goto err_free;
	}

	adc->irq_base = platform_get_irq(pdev, 1);
	if (adc->irq_base < 0) {
		ret = adc->irq_base;
		dev_err(&pdev->dev, "Failed to get irq base: %d\n", ret);
		goto err_free;
	}

	mem_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!mem_base) {
		ret = -ENOENT;
		dev_err(&pdev->dev, "Failed to get platform mmio resource");
		goto err_free;
	}

	adc->mem = request_mem_region(mem_base->start, JZ_REG_ADC_STATUS,
			pdev->name);
	if (!adc->mem) {
		ret = -EBUSY;
		dev_err(&pdev->dev, "Failed to request mmio memory region\n");
		goto err_free;
	}

	adc->base = ioremap_nocache(adc->mem->start, resource_size(adc->mem));
	if (!adc->base) {
		ret = -EBUSY;
		dev_err(&pdev->dev, "Failed to ioremap mmio memory\n");
		goto err_release_mem_region;
	}

	adc->clk = clk_get(&pdev->dev, "sadc");
	if (IS_ERR(adc->clk)) {
		ret = PTR_ERR(adc->clk);
		dev_err(&pdev->dev, "Failed to get clock: %d\n", ret);
		goto err_iounmap;
	}

	spin_lock_init(&adc->lock);
	atomic_set(&adc->clk_ref, 0);

	platform_set_drvdata(pdev, adc);

	for (irq = adc->irq_base; irq < adc->irq_base + SADC_NR_IRQS; ++irq) {
		irq_set_chip_data(irq, adc);
		irq_set_chip_and_handler(irq, &jz_adc_irq_chip,
				handle_level_irq);
	}

	irq_set_handler_data(adc->irq, adc);
	irq_set_chained_handler(adc->irq, jz_adc_irq_demux);

	clk_enable(adc->clk);

	writeb(0x80, adc->base + JZ_REG_ADC_ENABLE);
	writeb(0xff, adc->base + JZ_REG_ADC_CTRL);

	clkdiv = CLKDIV - 1;
	clkdiv_us = CLKDIV_US - 1;
	clkdiv_ms = CLKDIV_MS - 1;

	jz_adc_clk_div(adc, clkdiv, clkdiv_us, clkdiv_ms);

	for(i = 0;i < ARRAY_SIZE(jz_adc_cells);i++)
	{
		switch(jz_adc_cells[i].id)
		{
			case 1:
				jz_adc_cells[i].platform_data = battery_info;
				break;
			default:
				break;
		}
	}
	ret = mfd_add_devices(&pdev->dev, 0, jz_adc_cells,
			ARRAY_SIZE(jz_adc_cells), mem_base, adc->irq_base);
	if (ret < 0) {
		goto err_clk_put;
	}

	printk("jz4775 SADC driver registeres over!\n");

	return 0;

err_clk_put:
	clk_put(adc->clk);
err_iounmap:
	platform_set_drvdata(pdev, NULL);
	iounmap(adc->base);
err_release_mem_region:
	release_mem_region(adc->mem->start, resource_size(adc->mem));
err_free:
	kfree(adc);

	return ret;
}
コード例 #10
0
static int byt_gpio_probe(struct platform_device *pdev)
{
	struct byt_gpio *vg;
	struct gpio_chip *gc;
	struct resource *mem_rc, *irq_rc;
	struct device *dev = &pdev->dev;
	struct acpi_device *acpi_dev;
	struct pinctrl_gpio_range *range;
	acpi_handle handle = ACPI_HANDLE(dev);
	unsigned hwirq;
	int ret;

	if (acpi_bus_get_device(handle, &acpi_dev))
		return -ENODEV;

	vg = devm_kzalloc(dev, sizeof(struct byt_gpio), GFP_KERNEL);
	if (!vg) {
		dev_err(&pdev->dev, "can't allocate byt_gpio chip data\n");
		return -ENOMEM;
	}

	for (range = byt_ranges; range->name; range++) {
		if (!strcmp(acpi_dev->pnp.unique_id, range->name)) {
			vg->chip.ngpio = range->npins;
			vg->range = range;
			break;
		}
	}

	if (!vg->chip.ngpio || !vg->range)
		return -ENODEV;

	vg->pdev = pdev;
	platform_set_drvdata(pdev, vg);

	mem_rc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	vg->reg_base = devm_ioremap_resource(dev, mem_rc);
	if (IS_ERR(vg->reg_base))
		return PTR_ERR(vg->reg_base);

	spin_lock_init(&vg->lock);

	gc = &vg->chip;
	gc->label = dev_name(&pdev->dev);
	gc->owner = THIS_MODULE;
	gc->request = byt_gpio_request;
	gc->free = byt_gpio_free;
	gc->direction_input = byt_gpio_direction_input;
	gc->direction_output = byt_gpio_direction_output;
	gc->get = byt_gpio_get;
	gc->set = byt_gpio_set;
	gc->dbg_show = byt_gpio_dbg_show;
	gc->base = -1;
	gc->can_sleep = false;
	gc->dev = dev;

	ret = gpiochip_add(gc);
	if (ret) {
		dev_err(&pdev->dev, "failed adding byt-gpio chip\n");
		return ret;
	}

	/* set up interrupts  */
	irq_rc = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (irq_rc && irq_rc->start) {
		hwirq = irq_rc->start;
		gc->to_irq = byt_gpio_to_irq;

		vg->domain = irq_domain_add_linear(NULL, gc->ngpio,
						   &byt_gpio_irq_ops, vg);
		if (!vg->domain)
			return -ENXIO;

		byt_gpio_irq_init_hw(vg);

		irq_set_handler_data(hwirq, vg);
		irq_set_chained_handler(hwirq, byt_gpio_irq_handler);
	}

	pm_runtime_enable(dev);

	return 0;
}
コード例 #11
0
ファイル: megamod-pic.c プロジェクト: 33d/linux-2.6.21-hh20
static struct megamod_pic * __init init_megamod_pic(struct device_node *np)
{
	struct megamod_pic *pic;
	int i, irq;
	int mapping[NR_MUX_OUTPUTS];

	pr_info("Initializing C64x+ Megamodule PIC\n");

	pic = kzalloc(sizeof(struct megamod_pic), GFP_KERNEL);
	if (!pic) {
		pr_err("%s: Could not alloc PIC structure.\n", np->full_name);
		return NULL;
	}

	pic->irqhost = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR,
				      NR_COMBINERS * 32, &megamod_host_ops,
				      IRQ_UNMAPPED);
	if (!pic->irqhost) {
		pr_err("%s: Could not alloc host.\n", np->full_name);
		goto error_free;
	}

	pic->irqhost->host_data = pic;

	raw_spin_lock_init(&pic->lock);

	pic->regs = of_iomap(np, 0);
	if (!pic->regs) {
		pr_err("%s: Could not map registers.\n", np->full_name);
		goto error_free;
	}

	/* Initialize MUX map */
	for (i = 0; i < ARRAY_SIZE(mapping); i++)
		mapping[i] = IRQ_UNMAPPED;

	parse_priority_map(pic, mapping, ARRAY_SIZE(mapping));

	/*
	 * We can have up to 12 interrupts cascading to the core controller.
	 * These cascades can be from the combined interrupt sources or for
	 * individual interrupt sources. The "interrupts" property only
	 * deals with the cascaded combined interrupts. The individual
	 * interrupts muxed to the core controller use the core controller
	 * as their interrupt parent.
	 */
	for (i = 0; i < NR_COMBINERS; i++) {

		irq = irq_of_parse_and_map(np, i);
		if (irq == NO_IRQ)
			continue;

		/*
		 * We count on the core priority interrupts (4 - 15) being
		 * direct mapped. Check that device tree provided something
		 * in that range.
		 */
		if (irq < 4 || irq >= NR_PRIORITY_IRQS) {
			pr_err("%s: combiner-%d virq %d out of range!\n",
				 np->full_name, i, irq);
			continue;
		}

		/* record the mapping */
		mapping[irq - 4] = i;

		pr_debug("%s: combiner-%d cascading to virq %d\n",
			 np->full_name, i, irq);

		cascade_data[i].pic = pic;
		cascade_data[i].index = i;

		/* mask and clear all events in combiner */
		soc_writel(~0, &pic->regs->evtmask[i]);
		soc_writel(~0, &pic->regs->evtclr[i]);

		irq_set_handler_data(irq, &cascade_data[i]);
		irq_set_chained_handler(irq, megamod_irq_cascade);
	}

	/* Finally, set up the MUX registers */
	for (i = 0; i < NR_MUX_OUTPUTS; i++) {
		if (mapping[i] != IRQ_UNMAPPED) {
			pr_debug("%s: setting mux %d to priority %d\n",
				 np->full_name, mapping[i], i + 4);
			set_megamod_mux(pic, mapping[i], i);
		}
	}

	return pic;

error_free:
	kfree(pic);

	return NULL;
}
コード例 #12
0
ファイル: common.c プロジェクト: AceKatz/networking_research
static int __init exynos_init_irq_eint(void)
{
	int irq;

#ifdef CONFIG_PINCTRL_SAMSUNG
	/*
	 * The Samsung pinctrl driver provides an integrated gpio/pinmux/pinconf
	 * functionality along with support for external gpio and wakeup
	 * interrupts. If the samsung pinctrl driver is enabled and includes
	 * the wakeup interrupt support, then the setting up external wakeup
	 * interrupts here can be skipped. This check here is temporary to
	 * allow exynos4 platforms that do not use Samsung pinctrl driver to
	 * co-exist with platforms that do. When all of the Samsung Exynos4
	 * platforms switch over to using the pinctrl driver, the wakeup
	 * interrupt support code here can be completely removed.
	 */
	struct device_node *pctrl_np, *wkup_np;
	const char *pctrl_compat = "samsung,pinctrl-exynos4210";
	const char *wkup_compat = "samsung,exynos4210-wakeup-eint";

	for_each_compatible_node(pctrl_np, NULL, pctrl_compat) {
		if (of_device_is_available(pctrl_np)) {
			wkup_np = of_find_compatible_node(pctrl_np, NULL,
							wkup_compat);
			if (wkup_np)
				return -ENODEV;
		}
	}
#endif

	if (soc_is_exynos5250())
		exynos_eint_base = ioremap(EXYNOS5_PA_GPIO1, SZ_4K);
	else
		exynos_eint_base = ioremap(EXYNOS4_PA_GPIO2, SZ_4K);

	if (exynos_eint_base == NULL) {
		pr_err("unable to ioremap for EINT base address\n");
		return -ENOMEM;
	}

	for (irq = 0 ; irq <= 31 ; irq++) {
		irq_set_chip_and_handler(IRQ_EINT(irq), &exynos_irq_eint,
					 handle_level_irq);
		set_irq_flags(IRQ_EINT(irq), IRQF_VALID);
	}

	irq_set_chained_handler(EXYNOS_IRQ_EINT16_31, exynos_irq_demux_eint16_31);

	for (irq = 0 ; irq <= 15 ; irq++) {
		eint0_15_data[irq] = IRQ_EINT(irq);

		if (soc_is_exynos5250()) {
			irq_set_handler_data(exynos5_eint0_15_src_int[irq],
					     &eint0_15_data[irq]);
			irq_set_chained_handler(exynos5_eint0_15_src_int[irq],
						exynos_irq_eint0_15);
		} else {
			irq_set_handler_data(exynos4_eint0_15_src_int[irq],
					     &eint0_15_data[irq]);
			irq_set_chained_handler(exynos4_eint0_15_src_int[irq],
						exynos_irq_eint0_15);
		}
	}

	return 0;
}
コード例 #13
0
static int lnw_gpio_probe(struct pci_dev *pdev,
			const struct pci_device_id *id)
{
	void *base;
	resource_size_t start, len;
	struct lnw_gpio *lnw;
	u32 gpio_base;
	u32 irq_base;
	int retval;
	int ngpio = id->driver_data;

	retval = pci_enable_device(pdev);
	if (retval)
		return retval;

	retval = pci_request_regions(pdev, "langwell_gpio");
	if (retval) {
		dev_err(&pdev->dev, "error requesting resources\n");
		goto err_pci_req_region;
	}
	/* get the gpio_base from bar1 */
	start = pci_resource_start(pdev, 1);
	len = pci_resource_len(pdev, 1);
	base = ioremap_nocache(start, len);
	if (!base) {
		dev_err(&pdev->dev, "error mapping bar1\n");
		retval = -EFAULT;
		goto err_ioremap;
	}
	irq_base = *(u32 *)base;
	gpio_base = *((u32 *)base + 1);
	/* release the IO mapping, since we already get the info from bar1 */
	iounmap(base);
	/* get the register base from bar0 */
	start = pci_resource_start(pdev, 0);
	len = pci_resource_len(pdev, 0);
	base = devm_ioremap_nocache(&pdev->dev, start, len);
	if (!base) {
		dev_err(&pdev->dev, "error mapping bar0\n");
		retval = -EFAULT;
		goto err_ioremap;
	}

	lnw = devm_kzalloc(&pdev->dev, sizeof(*lnw), GFP_KERNEL);
	if (!lnw) {
		dev_err(&pdev->dev, "can't allocate langwell_gpio chip data\n");
		retval = -ENOMEM;
		goto err_ioremap;
	}

	lnw->reg_base = base;
	lnw->chip.label = dev_name(&pdev->dev);
	lnw->chip.request = lnw_gpio_request;
	lnw->chip.direction_input = lnw_gpio_direction_input;
	lnw->chip.direction_output = lnw_gpio_direction_output;
	lnw->chip.get = lnw_gpio_get;
	lnw->chip.set = lnw_gpio_set;
	lnw->chip.to_irq = lnw_gpio_to_irq;
	lnw->chip.base = gpio_base;
	lnw->chip.ngpio = ngpio;
	lnw->chip.can_sleep = 0;
	lnw->pdev = pdev;

	lnw->domain = irq_domain_add_simple(pdev->dev.of_node, ngpio, irq_base,
					    &lnw_gpio_irq_ops, lnw);
	if (!lnw->domain) {
		retval = -ENOMEM;
		goto err_ioremap;
	}

	pci_set_drvdata(pdev, lnw);
	retval = gpiochip_add(&lnw->chip);
	if (retval) {
		dev_err(&pdev->dev, "langwell gpiochip_add error %d\n", retval);
		goto err_ioremap;
	}

	lnw_irq_init_hw(lnw);

	irq_set_handler_data(pdev->irq, lnw);
	irq_set_chained_handler(pdev->irq, lnw_irq_handler);

	spin_lock_init(&lnw->lock);

	pm_runtime_put_noidle(&pdev->dev);
	pm_runtime_allow(&pdev->dev);

	return 0;

err_ioremap:
	pci_release_regions(pdev);
err_pci_req_region:
	pci_disable_device(pdev);
	return retval;
}
コード例 #14
0
ファイル: jz4740-adc.c プロジェクト: 03199618/linux
static int jz4740_adc_probe(struct platform_device *pdev)
{
	struct irq_chip_generic *gc;
	struct irq_chip_type *ct;
	struct jz4740_adc *adc;
	struct resource *mem_base;
	int ret;
	int irq_base;

	adc = devm_kzalloc(&pdev->dev, sizeof(*adc), GFP_KERNEL);
	if (!adc) {
		dev_err(&pdev->dev, "Failed to allocate driver structure\n");
		return -ENOMEM;
	}

	adc->irq = platform_get_irq(pdev, 0);
	if (adc->irq < 0) {
		ret = adc->irq;
		dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret);
		return ret;
	}

	irq_base = platform_get_irq(pdev, 1);
	if (irq_base < 0) {
		dev_err(&pdev->dev, "Failed to get irq base: %d\n", irq_base);
		return irq_base;
	}

	mem_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!mem_base) {
		dev_err(&pdev->dev, "Failed to get platform mmio resource\n");
		return -ENOENT;
	}

	/* Only request the shared registers for the MFD driver */
	adc->mem = request_mem_region(mem_base->start, JZ_REG_ADC_STATUS,
					pdev->name);
	if (!adc->mem) {
		dev_err(&pdev->dev, "Failed to request mmio memory region\n");
		return -EBUSY;
	}

	adc->base = ioremap_nocache(adc->mem->start, resource_size(adc->mem));
	if (!adc->base) {
		ret = -EBUSY;
		dev_err(&pdev->dev, "Failed to ioremap mmio memory\n");
		goto err_release_mem_region;
	}

	adc->clk = clk_get(&pdev->dev, "adc");
	if (IS_ERR(adc->clk)) {
		ret = PTR_ERR(adc->clk);
		dev_err(&pdev->dev, "Failed to get clock: %d\n", ret);
		goto err_iounmap;
	}

	spin_lock_init(&adc->lock);
	atomic_set(&adc->clk_ref, 0);

	platform_set_drvdata(pdev, adc);

	gc = irq_alloc_generic_chip("INTC", 1, irq_base, adc->base,
		handle_level_irq);

	ct = gc->chip_types;
	ct->regs.mask = JZ_REG_ADC_CTRL;
	ct->regs.ack = JZ_REG_ADC_STATUS;
	ct->chip.irq_mask = irq_gc_mask_set_bit;
	ct->chip.irq_unmask = irq_gc_mask_clr_bit;
	ct->chip.irq_ack = irq_gc_ack_set_bit;

	irq_setup_generic_chip(gc, IRQ_MSK(5), 0, 0, IRQ_NOPROBE | IRQ_LEVEL);

	adc->gc = gc;

	irq_set_handler_data(adc->irq, gc);
	irq_set_chained_handler(adc->irq, jz4740_adc_irq_demux);

	writeb(0x00, adc->base + JZ_REG_ADC_ENABLE);
	writeb(0xff, adc->base + JZ_REG_ADC_CTRL);

	ret = mfd_add_devices(&pdev->dev, 0, jz4740_adc_cells,
			      ARRAY_SIZE(jz4740_adc_cells), mem_base,
			      irq_base, NULL);
	if (ret < 0)
		goto err_clk_put;

	return 0;

err_clk_put:
	clk_put(adc->clk);
err_iounmap:
	iounmap(adc->base);
err_release_mem_region:
	release_mem_region(adc->mem->start, resource_size(adc->mem));
	return ret;
}
コード例 #15
0
int __init mmp2_mux_init(struct device_node *parent)
{
	struct device_node *node;
	const struct of_device_id *of_id;
	struct resource res;
	int i, irq_base, ret, irq;
	u32 nr_irqs, mfp_irq;

	node = parent;
	max_icu_nr = 1;
	for (i = 1; i < MAX_ICU_NR; i++) {
		node = of_find_matching_node(node, mmp_mux_irq_match);
		if (!node)
			break;
		of_id = of_match_node(&mmp_mux_irq_match[0], node);
		ret = of_property_read_u32(node, "mrvl,intc-nr-irqs",
					   &nr_irqs);
		if (ret) {
			pr_err("Not found mrvl,intc-nr-irqs property\n");
			ret = -EINVAL;
			goto err;
		}
		ret = of_address_to_resource(node, 0, &res);
		if (ret < 0) {
			pr_err("Not found reg property\n");
			ret = -EINVAL;
			goto err;
		}
		icu_data[i].reg_status = mmp_icu_base + res.start;
		ret = of_address_to_resource(node, 1, &res);
		if (ret < 0) {
			pr_err("Not found reg property\n");
			ret = -EINVAL;
			goto err;
		}
		icu_data[i].reg_mask = mmp_icu_base + res.start;
		icu_data[i].cascade_irq = irq_of_parse_and_map(node, 0);
		if (!icu_data[i].cascade_irq) {
			ret = -EINVAL;
			goto err;
		}

		irq_base = irq_alloc_descs(-1, 0, nr_irqs, 0);
		if (irq_base < 0) {
			pr_err("Failed to allocate IRQ numbers for mux intc\n");
			ret = irq_base;
			goto err;
		}
		if (!of_property_read_u32(node, "mrvl,clr-mfp-irq",
					  &mfp_irq)) {
			icu_data[i].clr_mfp_irq_base = irq_base;
			icu_data[i].clr_mfp_hwirq = mfp_irq;
		}
		irq_set_chained_handler(icu_data[i].cascade_irq,
					icu_mux_irq_demux);
		icu_data[i].nr_irqs = nr_irqs;
		icu_data[i].virq_base = irq_base;
		icu_data[i].domain = irq_domain_add_legacy(node, nr_irqs,
							   irq_base, 0,
							   &mmp_irq_domain_ops,
							   &icu_data[i]);
		for (irq = irq_base; irq < irq_base + nr_irqs; irq++)
			icu_mask_irq(irq_get_irq_data(irq));
	}
	max_icu_nr = i;
	return 0;
err:
	of_node_put(node);
	max_icu_nr = i;
	return ret;
}
コード例 #16
0
static void __init mpc8xxx_add_controller(struct device_node *np)
{
	struct mpc8xxx_gpio_chip *mpc8xxx_gc;
	struct of_mm_gpio_chip *mm_gc;
	struct gpio_chip *gc;
	const struct of_device_id *id;
	unsigned hwirq;
	int ret;

	mpc8xxx_gc = kzalloc(sizeof(*mpc8xxx_gc), GFP_KERNEL);
	if (!mpc8xxx_gc) {
		ret = -ENOMEM;
		goto err;
	}

	spin_lock_init(&mpc8xxx_gc->lock);

	mm_gc = &mpc8xxx_gc->mm_gc;
	gc = &mm_gc->gc;

	mm_gc->save_regs = mpc8xxx_gpio_save_regs;
	gc->ngpio = MPC8XXX_GPIO_PINS;
	gc->direction_input = mpc8xxx_gpio_dir_in;
	gc->direction_output = of_device_is_compatible(np, "fsl,mpc5121-gpio") ?
		mpc5121_gpio_dir_out : mpc8xxx_gpio_dir_out;
	gc->get = of_device_is_compatible(np, "fsl,mpc8572-gpio") ?
		mpc8572_gpio_get : mpc8xxx_gpio_get;
	gc->set = mpc8xxx_gpio_set;
	gc->to_irq = mpc8xxx_gpio_to_irq;

	ret = of_mm_gpiochip_add(np, mm_gc);
	if (ret)
		goto err;

	hwirq = irq_of_parse_and_map(np, 0);
	if (hwirq == NO_IRQ)
		goto skip_irq;

	mpc8xxx_gc->irq = irq_domain_add_linear(np, MPC8XXX_GPIO_PINS,
					&mpc8xxx_gpio_irq_ops, mpc8xxx_gc);
	if (!mpc8xxx_gc->irq)
		goto skip_irq;

	id = of_match_node(mpc8xxx_gpio_ids, np);
	if (id)
		mpc8xxx_gc->of_dev_id_data = id->data;

	/* ack and mask all irqs */
	out_be32(mm_gc->regs + GPIO_IER, 0xffffffff);
	out_be32(mm_gc->regs + GPIO_IMR, 0);

	irq_set_handler_data(hwirq, mpc8xxx_gc);
	irq_set_chained_handler(hwirq, mpc8xxx_gpio_irq_cascade);

skip_irq:
	return;

err:
	pr_err("%s: registration failed with status %d\n",
	       np->full_name, ret);
	kfree(mpc8xxx_gc);

	return;
}
コード例 #17
0
static int intel_gpio_probe(struct pci_dev *pdev,
			  const struct pci_device_id *id)
{
	void __iomem *base;
	struct intel_mid_gpio *priv;
	u32 gpio_base;
	u32 irq_base;
	int retval;
	struct intel_mid_gpio_ddata *ddata =
				(struct intel_mid_gpio_ddata *)id->driver_data;

	retval = pcim_enable_device(pdev);
	if (retval)
		return retval;

	retval = pcim_iomap_regions(pdev, 1 << 0 | 1 << 1, pci_name(pdev));
	if (retval) {
		dev_err(&pdev->dev, "I/O memory mapping error\n");
		return retval;
	}

	base = pcim_iomap_table(pdev)[1];

	irq_base = readl(base);
	gpio_base = readl(sizeof(u32) + base);

	/* release the IO mapping, since we already get the info from bar1 */
	pcim_iounmap_regions(pdev, 1 << 1);

	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
	if (!priv) {
		dev_err(&pdev->dev, "can't allocate chip data\n");
		return -ENOMEM;
	}

	priv->reg_base = pcim_iomap_table(pdev)[0];
	priv->chip.label = dev_name(&pdev->dev);
	priv->chip.dev = &pdev->dev;
	priv->chip.request = intel_gpio_request;
	priv->chip.direction_input = intel_gpio_direction_input;
	priv->chip.direction_output = intel_gpio_direction_output;
	priv->chip.get = intel_gpio_get;
	priv->chip.set = intel_gpio_set;
	priv->chip.to_irq = intel_gpio_to_irq;
	priv->chip.base = gpio_base;
	priv->chip.ngpio = ddata->ngpio;
	priv->chip.can_sleep = false;
	priv->pdev = pdev;

	spin_lock_init(&priv->lock);

	priv->domain = irq_domain_add_simple(pdev->dev.of_node, ddata->ngpio,
					irq_base, &intel_gpio_irq_ops, priv);
	if (!priv->domain)
		return -ENOMEM;

	pci_set_drvdata(pdev, priv);
	retval = gpiochip_add(&priv->chip);
	if (retval) {
		dev_err(&pdev->dev, "gpiochip_add error %d\n", retval);
		return retval;
	}

	intel_mid_irq_init_hw(priv);

	irq_set_handler_data(pdev->irq, priv);
	irq_set_chained_handler(pdev->irq, intel_mid_irq_handler);

	pm_runtime_put_noidle(&pdev->dev);
	pm_runtime_allow(&pdev->dev);

	return 0;
}
コード例 #18
0
ファイル: gpio-xilinxps.c プロジェクト: Analias/SNOWLeo-SDR-1
/**
 * xgpiops_probe - Initialization method for a xgpiops device
 * @pdev:	platform device instance
 *
 * This function allocates memory resources for the gpio device and registers
 * all the banks of the device. It will also set up interrupts for the gpio
 * pins.
 * Note: Interrupts are disabled for all the banks during initialization.
 * Returns 0 on success, negative error otherwise.
 */
static int __devinit xgpiops_probe(struct platform_device *pdev)
{
	int ret;
	unsigned int irq_num;
	struct xgpiops *gpio;
	struct gpio_chip *chip;
	resource_size_t remap_size;
	struct resource *mem_res = NULL;
	int pin_num, bank_num, gpio_irq;

	gpio = kzalloc(sizeof(struct xgpiops), GFP_KERNEL);
	if (!gpio) {
		dev_err(&pdev->dev,
			"couldn't allocate memory for gpio private data\n");
		return -ENOMEM;
	}

	spin_lock_init(&gpio->gpio_lock);

	platform_set_drvdata(pdev, gpio);

	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!mem_res) {
		dev_err(&pdev->dev, "No memory resource\n");
		ret = -ENODEV;
		goto err_free_gpio;
	}

	remap_size = mem_res->end - mem_res->start + 1;
	if (!request_mem_region(mem_res->start, remap_size, pdev->name)) {
		dev_err(&pdev->dev, "Cannot request IO\n");
		ret = -ENXIO;
		goto err_free_gpio;
	}

	gpio->base_addr = ioremap(mem_res->start, remap_size);
	if (gpio->base_addr == NULL) {
		dev_err(&pdev->dev, "Couldn't ioremap memory at 0x%08lx\n",
			(unsigned long)mem_res->start);
		ret = -ENOMEM;
		goto err_release_region;
	}

	irq_num = platform_get_irq(pdev, 0);
	gpio->irq = irq_num;

	/* configure the gpio chip */
	chip = &gpio->chip;
	chip->label = "xgpiops";
	chip->owner = THIS_MODULE;
	chip->dev = &pdev->dev;
	chip->get = xgpiops_get_value;
	chip->set = xgpiops_set_value;
	chip->request = xgpiops_request;
	chip->free = xgpiops_free;
	chip->direction_input = xgpiops_dir_in;
	chip->direction_output = xgpiops_dir_out;
	chip->to_irq = xgpiops_to_irq;
	chip->dbg_show = NULL;
	chip->base = 0;		/* default pin base */
	chip->ngpio = XGPIOPS_NR_GPIOS;
	chip->can_sleep = 0;

	/* report a bug if gpio chip registration fails */
	ret = gpiochip_add(chip);
	if (ret < 0) {
		dev_err(&pdev->dev, "gpio chip registration failed\n");
		goto err_iounmap;
	} else {
		dev_info(&pdev->dev, "gpio at 0x%08lx mapped to 0x%08lx\n",
			 (unsigned long)mem_res->start,
			 (unsigned long)gpio->base_addr);
	}

	/* Enable GPIO clock */
	gpio->clk = clk_get_sys("GPIO_APER", NULL);
	if (IS_ERR(gpio->clk)) {
		dev_err(&pdev->dev, "Clock not found.\n");
		ret = PTR_ERR(gpio->clk);
		goto err_chip_remove;
	}
	ret = clk_prepare_enable(gpio->clk);
	if (ret) {
		dev_err(&pdev->dev, "Unable to enable clock.\n");
		goto err_clk_put;
	}

	/* disable interrupts for all banks */
	for (bank_num = 0; bank_num < 4; bank_num++) {
		xgpiops_writereg(0xffffffff, gpio->base_addr +
				  XGPIOPS_INTDIS_OFFSET(bank_num));
	}

	/*
	 * set the irq chip, handler and irq chip data for callbacks for
	 * each pin
	 */
	gpio_irq = XGPIOPS_IRQBASE;
	for (pin_num = 0; pin_num < XGPIOPS_NR_GPIOS; pin_num++, gpio_irq++) {
		irq_set_chip(gpio_irq, &xgpiops_irqchip);
		irq_set_chip_data(gpio_irq, (void *)gpio);
		irq_set_handler(gpio_irq, handle_simple_irq);
		irq_set_status_flags(gpio_irq, IRQF_VALID);
		irq_clear_status_flags(gpio_irq, IRQ_NOREQUEST);
	}

	irq_set_handler_data(irq_num, (void *)(XGPIOPS_IRQBASE));
	irq_set_chained_handler(irq_num, xgpiops_irqhandler);

	xgpiops_pm_runtime_init(pdev);

	device_set_wakeup_capable(&pdev->dev, 1);

	return 0;

err_clk_put:
	clk_put(gpio->clk);
err_chip_remove:
	gpiochip_remove(chip);
err_iounmap:
	iounmap(gpio->base_addr);
err_release_region:
	release_mem_region(mem_res->start, remap_size);
err_free_gpio:
	platform_set_drvdata(pdev, NULL);
	kfree(gpio);

	return ret;
}
コード例 #19
0
ファイル: irq-orion.c プロジェクト: 7799/linux
static int __init orion_bridge_irq_init(struct device_node *np,
					struct device_node *parent)
{
	unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
	struct resource r;
	struct irq_domain *domain;
	struct irq_chip_generic *gc;
	int ret, irq, nrirqs = 32;

	/* get optional number of interrupts provided */
	of_property_read_u32(np, "marvell,#interrupts", &nrirqs);

	domain = irq_domain_add_linear(np, nrirqs,
				       &irq_generic_chip_ops, NULL);
	if (!domain) {
		pr_err("%s: unable to add irq domain\n", np->name);
		return -ENOMEM;
	}

	ret = irq_alloc_domain_generic_chips(domain, nrirqs, 1, np->name,
			     handle_edge_irq, clr, 0, IRQ_GC_INIT_MASK_CACHE);
	if (ret) {
		pr_err("%s: unable to alloc irq domain gc\n", np->name);
		return ret;
	}

	ret = of_address_to_resource(np, 0, &r);
	if (ret) {
		pr_err("%s: unable to get resource\n", np->name);
		return ret;
	}

	if (!request_mem_region(r.start, resource_size(&r), np->name)) {
		pr_err("%s: unable to request mem region\n", np->name);
		return -ENOMEM;
	}

	/* Map the parent interrupt for the chained handler */
	irq = irq_of_parse_and_map(np, 0);
	if (irq <= 0) {
		pr_err("%s: unable to parse irq\n", np->name);
		return -EINVAL;
	}

	gc = irq_get_domain_generic_chip(domain, 0);
	gc->reg_base = ioremap(r.start, resource_size(&r));
	if (!gc->reg_base) {
		pr_err("%s: unable to map resource\n", np->name);
		return -ENOMEM;
	}

	gc->chip_types[0].regs.ack = ORION_BRIDGE_IRQ_CAUSE;
	gc->chip_types[0].regs.mask = ORION_BRIDGE_IRQ_MASK;
	gc->chip_types[0].chip.irq_startup = orion_bridge_irq_startup;
	gc->chip_types[0].chip.irq_ack = irq_gc_ack_clr_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;

	/* mask and clear all interrupts */
	writel(0, gc->reg_base + ORION_BRIDGE_IRQ_MASK);
	writel(0, gc->reg_base + ORION_BRIDGE_IRQ_CAUSE);

	irq_set_handler_data(irq, domain);
	irq_set_chained_handler(irq, orion_bridge_irq_handler);

	return 0;
}
コード例 #20
0
ファイル: cs75xx-gpio.c プロジェクト: xtra72/s805
static int cs75xx_gpio_probe(struct platform_device *pdev)
{
	int i, j;
	char tmp_str[16];
	struct resource *res_mem;

	gpio_dbgmsg("Function: %s, pdev->name = %s\n", __func__, pdev->name);

	memset(cs75xx_gpio_base, 0, sizeof(cs75xx_gpio_base));

	/* get the module base address and irq number */
	sprintf(tmp_str, "global");
	res_mem = platform_get_resource_byname(pdev, IORESOURCE_IO, tmp_str);
	if (!res_mem) {
		gpio_dbgmsg("Func: %s - can't get resource %s\n", __func__, tmp_str);
		goto fail;
	}
	cs75xx_global_base = ioremap(res_mem->start, res_mem->end - res_mem->start + 1);
	if (!cs75xx_global_base) {
		gpio_dbgmsg("Func: %s - unable to remap %s %d memory \n",
		            __func__, tmp_str, res_mem->end - res_mem->start + 1);
		goto fail;
	}
	gpio_dbgmsg("\tcs75xx_global_base = %p\n", cs75xx_global_base);

	for (i = 0; i < GPIO_BANK_NUM; i++) {
		sprintf(tmp_str, "gpio%d", i);
		res_mem = platform_get_resource_byname(pdev, IORESOURCE_IO, tmp_str);
		if (!res_mem) {
			gpio_dbgmsg("Func: %s - can't get resource %s\n", __func__, tmp_str);
			goto fail;
		}
		cs75xx_gpio_base[i] = ioremap(res_mem->start, res_mem->end - res_mem->start + 1);
		if (!cs75xx_gpio_base[i]) {
			gpio_dbgmsg("Func: %s - unable to remap %s %d memory \n",
			            __func__, tmp_str, res_mem->end - res_mem->start + 1);
			goto fail;
		}
		gpio_dbgmsg("\tcs75xx_gpio_base[%d] = %p\n", i, cs75xx_gpio_base[i]);
	}

	for (i = 0; i < GPIO_BANK_NUM; i++) {
		sprintf(tmp_str, "irq_gpio%d", i);
		cs75xx_irq_gpio[i] = platform_get_irq_byname(pdev, tmp_str);
		if (cs75xx_irq_gpio[i] == -ENXIO) {
			gpio_dbgmsg("Func: %s - can't get resource %s\n", __func__, tmp_str);
			goto fail;
		}
		gpio_dbgmsg("\tcs75xx_irq_gpio[%d] = %08x\n", i, cs75xx_irq_gpio[i]);
	}

	/* disable irq and register to gpiolib */
	for (i = 0; i < GPIO_BANK_NUM; i++) {
		/* disable, unmask and clear all interrupts */
		__raw_writel(0x0, cs75xx_gpio_base[i] + CS75XX_GPIO_IE);

		for (j = GPIO_IRQ_BASE + i * GPIO_BANK_SIZE;
		     j < GPIO_IRQ_BASE + (i + 1) * GPIO_BANK_SIZE; j++) {
			irq_set_chip(j, &cs75xx_gpio_irq_chip);
			irq_set_handler(j, handle_edge_irq);
			set_irq_flags(j, IRQF_VALID);
		}

		irq_set_chained_handler(cs75xx_irq_gpio[i], cs75xx_gpio_irq_handler);
		irq_set_handler_data(cs75xx_irq_gpio[i], (void *)i);
	}

	BUG_ON(gpiochip_add(&cs75xx_gpio_chip));

	return 0;

fail:
	for (i = 0; i < GPIO_BANK_NUM; i++)
		if (cs75xx_gpio_base[i])
			iounmap(cs75xx_gpio_base[i]);

	return -ENODEV;
}
コード例 #21
0
void __init baboon_register_interrupts(void)
{
	irq_set_chained_handler(IRQ_NUBUS_C, baboon_irq);
}
コード例 #22
0
static int __init eic_probe(struct platform_device *pdev)
{
	struct eic *eic;
	struct resource *regs;
	unsigned int i;
	unsigned int nr_of_irqs;
	unsigned int int_irq;
	int ret;
	u32 pattern;

	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	int_irq = platform_get_irq(pdev, 0);
	if (!regs || (int)int_irq <= 0) {
		dev_dbg(&pdev->dev, "missing regs and/or irq resource\n");
		return -ENXIO;
	}

	ret = -ENOMEM;
	eic = kzalloc(sizeof(struct eic), GFP_KERNEL);
	if (!eic) {
		dev_dbg(&pdev->dev, "no memory for eic structure\n");
		goto err_kzalloc;
	}

	eic->first_irq = EIM_IRQ_BASE + 32 * pdev->id;
	eic->regs = ioremap(regs->start, resource_size(regs));
	if (!eic->regs) {
		dev_dbg(&pdev->dev, "failed to map regs\n");
		goto err_ioremap;
	}

	/*
                                                       
                            
  */
	eic_writel(eic, IDR, ~0UL);
	eic_writel(eic, MODE, ~0UL);
	pattern = eic_readl(eic, MODE);
	nr_of_irqs = fls(pattern);

	/*                                                  */
	eic_writel(eic, EDGE, 0UL);
	eic_writel(eic, LEVEL, 0UL);

	eic->chip = &eic_chip;

	for (i = 0; i < nr_of_irqs; i++) {
		irq_set_chip_and_handler(eic->first_irq + i, &eic_chip,
					 handle_level_irq);
		irq_set_chip_data(eic->first_irq + i, eic);
	}

	irq_set_chained_handler(int_irq, demux_eic_irq);
	irq_set_handler_data(int_irq, eic);

	if (pdev->id == 0) {
		nmi_eic = eic;
		if (nmi_enabled)
			/*
                                                
                       
    */
			nmi_enable();
	}

	dev_info(&pdev->dev,
		 "External Interrupt Controller at 0x%p, IRQ %u\n",
		 eic->regs, int_irq);
	dev_info(&pdev->dev,
		 "Handling %u external IRQs, starting with IRQ %u\n",
		 nr_of_irqs, eic->first_irq);

	return 0;

err_ioremap:
	kfree(eic);
err_kzalloc:
	return ret;
}
コード例 #23
0
ファイル: ezx-pcap.c プロジェクト: 119-org/hi3518-osdrv
static int __devinit ezx_pcap_probe(struct spi_device *spi)
{
	struct pcap_platform_data *pdata = spi->dev.platform_data;
	struct pcap_chip *pcap;
	int i, adc_irq;
	int ret = -ENODEV;

	/* platform data is required */
	if (!pdata)
		goto ret;

	pcap = kzalloc(sizeof(*pcap), GFP_KERNEL);
	if (!pcap) {
		ret = -ENOMEM;
		goto ret;
	}

	mutex_init(&pcap->io_mutex);
	mutex_init(&pcap->adc_mutex);
	INIT_WORK(&pcap->isr_work, pcap_isr_work);
	INIT_WORK(&pcap->msr_work, pcap_msr_work);
	dev_set_drvdata(&spi->dev, pcap);

	/* setup spi */
	spi->bits_per_word = 32;
	spi->mode = SPI_MODE_0 | (pdata->config & PCAP_CS_AH ? SPI_CS_HIGH : 0);
	ret = spi_setup(spi);
	if (ret)
		goto free_pcap;

	pcap->spi = spi;

	/* setup irq */
	pcap->irq_base = pdata->irq_base;
	pcap->workqueue = create_singlethread_workqueue("pcapd");
	if (!pcap->workqueue) {
		ret = -ENOMEM;
		dev_err(&spi->dev, "can't create pcap thread\n");
		goto free_pcap;
	}

	/* redirect interrupts to AP, except adcdone2 */
	if (!(pdata->config & PCAP_SECOND_PORT))
		ezx_pcap_write(pcap, PCAP_REG_INT_SEL,
					(1 << PCAP_IRQ_ADCDONE2));

	/* setup irq chip */
	for (i = pcap->irq_base; i < (pcap->irq_base + PCAP_NIRQS); i++) {
		irq_set_chip_and_handler(i, &pcap_irq_chip, handle_simple_irq);
		irq_set_chip_data(i, pcap);
#ifdef CONFIG_ARM
		set_irq_flags(i, IRQF_VALID);
#else
		irq_set_noprobe(i);
#endif
	}

	/* mask/ack all PCAP interrupts */
	ezx_pcap_write(pcap, PCAP_REG_MSR, PCAP_MASK_ALL_INTERRUPT);
	ezx_pcap_write(pcap, PCAP_REG_ISR, PCAP_CLEAR_INTERRUPT_REGISTER);
	pcap->msr = PCAP_MASK_ALL_INTERRUPT;

	irq_set_irq_type(spi->irq, IRQ_TYPE_EDGE_RISING);
	irq_set_handler_data(spi->irq, pcap);
	irq_set_chained_handler(spi->irq, pcap_irq_handler);
	irq_set_irq_wake(spi->irq, 1);

	/* ADC */
	adc_irq = pcap_to_irq(pcap, (pdata->config & PCAP_SECOND_PORT) ?
					PCAP_IRQ_ADCDONE2 : PCAP_IRQ_ADCDONE);

	ret = request_irq(adc_irq, pcap_adc_irq, 0, "ADC", pcap);
	if (ret)
		goto free_irqchip;

	/* setup subdevs */
	for (i = 0; i < pdata->num_subdevs; i++) {
		ret = pcap_add_subdev(pcap, &pdata->subdevs[i]);
		if (ret)
			goto remove_subdevs;
	}

	/* board specific quirks */
	if (pdata->init)
		pdata->init(pcap);

	return 0;

remove_subdevs:
	device_for_each_child(&spi->dev, NULL, pcap_remove_subdev);
/* free_adc: */
	free_irq(adc_irq, pcap);
free_irqchip:
	for (i = pcap->irq_base; i < (pcap->irq_base + PCAP_NIRQS); i++)
		irq_set_chip_and_handler(i, NULL, NULL);
/* destroy_workqueue: */
	destroy_workqueue(pcap->workqueue);
free_pcap:
	kfree(pcap);
ret:
	return ret;
}
コード例 #24
0
ファイル: pm8xxx-irq.c プロジェクト: DarkSense/PyramidION
int __devexit pm8xxx_irq_exit(struct pm_irq_chip *chip)
{
	irq_set_chained_handler(chip->devirq, NULL);
	kfree(chip);
	return 0;
}
コード例 #25
0
ファイル: gpio-altera.c プロジェクト: embest-amp/cycloneV_evm
int __devinit altera_gpio_probe(struct platform_device *pdev)
{
	struct device_node *node = pdev->dev.of_node;
	int id, reg, ret;
	struct altera_gpio_chip *altera_gc = devm_kzalloc(&pdev->dev,
				sizeof(*altera_gc), GFP_KERNEL);
	if (altera_gc == NULL) {
		ret = -ENOMEM;
		pr_err("%s: registration failed with status %d\n",
			node->full_name, ret);
		return ret;
	}
	altera_gc->irq = 0;

	spin_lock_init(&altera_gc->gpio_lock);

	id = pdev->id;

	if (of_property_read_u32(node, "width", &reg))
		/*By default assume full GPIO controller*/
		altera_gc->mmchip.gc.ngpio = 32;
	else
		altera_gc->mmchip.gc.ngpio = reg;

	if (altera_gc->mmchip.gc.ngpio > 32) {
		pr_warn("%s: ngpio is greater than 32, defaulting to 32\n",
			node->full_name);
		altera_gc->mmchip.gc.ngpio = 32;
	}

	altera_gc->mmchip.gc.direction_input	= altera_gpio_direction_input;
	altera_gc->mmchip.gc.direction_output	= altera_gpio_direction_output;
	altera_gc->mmchip.gc.get		= altera_gpio_get;
	altera_gc->mmchip.gc.set		= altera_gpio_set;
	altera_gc->mmchip.gc.to_irq		= altera_gpio_to_irq;
	altera_gc->mmchip.gc.owner		= THIS_MODULE;

	ret = of_mm_gpiochip_add(node, &altera_gc->mmchip);
	if (ret)
		goto err;

	platform_set_drvdata(pdev, altera_gc);

	if (of_get_property(node, "interrupts", &reg) == NULL)
		goto skip_irq;
	altera_gc->hwirq = irq_of_parse_and_map(node, 0);

	if (altera_gc->hwirq == NO_IRQ)
		goto skip_irq;

	altera_gc->irq = irq_domain_add_linear(node, altera_gc->mmchip.gc.ngpio,
				&altera_gpio_irq_ops, altera_gc);

	if (!altera_gc->irq) {
		ret = -ENODEV;
		goto dispose_irq;
	}

	if (of_property_read_u32(node, "level_trigger", &reg)) {
		ret = -EINVAL;
		pr_err("%s: level_trigger value not set in device tree\n",
			node->full_name);
		goto teardown;
	}
	altera_gc->level_trigger = reg;

	irq_set_handler_data(altera_gc->hwirq, altera_gc);
	irq_set_chained_handler(altera_gc->hwirq, altera_gpio_irq_handler);

	return 0;

teardown:
	irq_domain_remove(altera_gc->irq);
dispose_irq:
	irq_dispose_mapping(altera_gc->hwirq);
	WARN_ON(gpiochip_remove(&altera_gc->mmchip.gc) < 0);

err:
	pr_err("%s: registration failed with status %d\n",
		node->full_name, ret);
	devm_kfree(&pdev->dev, altera_gc);

	return ret;
skip_irq:
	return 0;
}