Beispiel #1
0
static void uv_domain_free(struct irq_domain *domain, unsigned int virq,
			   unsigned int nr_irqs)
{
	struct irq_data *irq_data = irq_domain_get_irq_data(domain, virq);

	BUG_ON(nr_irqs != 1);
	kfree(irq_data->chip_data);
	irq_clear_status_flags(virq, IRQ_MOVE_PCNTXT);
	irq_clear_status_flags(virq, IRQ_NO_BALANCING);
	irq_domain_free_irqs_top(domain, virq, nr_irqs);
}
Beispiel #2
0
static void ep93xx_gpio_init_irq(void)
{
	int gpio_irq;

	for (gpio_irq = gpio_to_irq(0);
	     gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) {
		irq_set_chip_and_handler(gpio_irq, &ep93xx_gpio_irq_chip,
					 handle_level_irq);
		irq_clear_status_flags(gpio_irq, IRQ_NOREQUEST);
	}

	irq_set_chained_handler(IRQ_EP93XX_GPIO_AB,
				ep93xx_gpio_ab_irq_handler);
	irq_set_chained_handler(IRQ_EP93XX_GPIO0MUX,
				ep93xx_gpio_f_irq_handler);
	irq_set_chained_handler(IRQ_EP93XX_GPIO1MUX,
				ep93xx_gpio_f_irq_handler);
	irq_set_chained_handler(IRQ_EP93XX_GPIO2MUX,
				ep93xx_gpio_f_irq_handler);
	irq_set_chained_handler(IRQ_EP93XX_GPIO3MUX,
				ep93xx_gpio_f_irq_handler);
	irq_set_chained_handler(IRQ_EP93XX_GPIO4MUX,
				ep93xx_gpio_f_irq_handler);
	irq_set_chained_handler(IRQ_EP93XX_GPIO5MUX,
				ep93xx_gpio_f_irq_handler);
	irq_set_chained_handler(IRQ_EP93XX_GPIO6MUX,
				ep93xx_gpio_f_irq_handler);
	irq_set_chained_handler(IRQ_EP93XX_GPIO7MUX,
				ep93xx_gpio_f_irq_handler);
}
static int __init scalewayc1gpio_init(void) {
  unsigned int gpio;
  int ret;

  printk(KERN_DEBUG "Scaleway C1 SoC IRQ: initializing\n");

  /* create reboot thread */
  task = kthread_create(scalewayc1_reboot_thread, NULL, "scaleway-c1-soc-irq");
  if (IS_ERR(task)) {
    printk(KERN_ALERT "Scaleway C1 SoC IRQ: kthread_create error\n");
    return -1;
  }
  wake_up_process(task);

  /* setup an irq that watch the reset gpio state */
  gpio = SCALEWAYC1_GPIO_SWRESET;
  gpio_request(gpio, "softreset");
  gpio_direction_input(gpio);
  g_irq = gpio_to_irq(gpio);
  irq_clear_status_flags(g_irq, IRQ_LEVEL);
  ret = request_any_context_irq(g_irq, scalewayc1_irq_resethandler,
				IRQF_TRIGGER_FALLING, "scaleway-c1", NULL);

  /* enable console, switch the booted gpio */
  gpio = SCALEWAYC1_GPIO_BOOTED;
  gpio_request(gpio, "booted");
  gpio_direction_output(gpio, 0);

  printk(KERN_INFO "Scaleway C1 SoC IRQ: initialized\n");
  return 0;
}
Beispiel #4
0
static __init int bast_irq_init(void)
{
	unsigned int i;

	if (machine_is_bast()) {
		printk(KERN_INFO "BAST PC104 IRQ routing, Copyright 2005 Simtec Electronics\n");

		/* zap all the IRQs */

		__raw_writeb(0x0, BAST_VA_PC104_IRQMASK);

		irq_set_chained_handler(BAST_IRQ_ISA, bast_irq_pc104_demux);

		/* register our IRQs */

		for (i = 0; i < 4; i++) {
			unsigned int irqno = bast_pc104_irqs[i];

			irq_set_chip_and_handler(irqno, &bast_pc104_chip,
						 handle_level_irq);
			irq_clear_status_flags(irqno, IRQ_NOREQUEST);
		}
	}

	return 0;
}
Beispiel #5
0
static void __init zeus_init_irq(void)
{
	int level;
	int isa_irq;

	pxa27x_init_irq();

	/* Peripheral IRQs. It would be nice to move those inside driver
	   configuration, but it is not supported at the moment. */
	irq_set_irq_type(gpio_to_irq(ZEUS_AC97_GPIO), IRQ_TYPE_EDGE_RISING);
	irq_set_irq_type(gpio_to_irq(ZEUS_WAKEUP_GPIO), IRQ_TYPE_EDGE_RISING);
	irq_set_irq_type(gpio_to_irq(ZEUS_PTT_GPIO), IRQ_TYPE_EDGE_RISING);
	irq_set_irq_type(gpio_to_irq(ZEUS_EXTGPIO_GPIO),
			 IRQ_TYPE_EDGE_FALLING);
	irq_set_irq_type(gpio_to_irq(ZEUS_CAN_GPIO), IRQ_TYPE_EDGE_FALLING);

	/* Setup ISA IRQs */
	for (level = 0; level < ARRAY_SIZE(zeus_isa_irqs); level++) {
		isa_irq = zeus_bit_to_irq(level);
		irq_set_chip_and_handler(isa_irq, &zeus_irq_chip,
					 handle_edge_irq);
		irq_clear_status_flags(isa_irq, IRQ_NOREQUEST | IRQ_NOPROBE);
	}

	irq_set_irq_type(gpio_to_irq(ZEUS_ISA_GPIO), IRQ_TYPE_EDGE_RISING);
	irq_set_chained_handler(gpio_to_irq(ZEUS_ISA_GPIO), zeus_irq_handler);
}
static irqreturn_t scalewayc1_irq_resethandler(int irq, void *dev_id) {
  /* handled when reset gpio state changed */
  if (irq == g_irq) {
    need_reboot = 1;
    atomic_inc(&probe_count);
    wake_up(&probe_waitqueue);
    irq_clear_status_flags(irq, IRQ_LEVEL);
  }
  return IRQ_HANDLED;
}
Beispiel #7
0
int xintc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
{
	u32 intr_mask = (u32)d->host_data;

	if (intr_mask & (1 << hw)) {
		irq_set_chip_and_handler_name(irq, &intc_dev,
						handle_edge_irq, "edge");
		irq_clear_status_flags(irq, IRQ_LEVEL);
	} else {
		irq_set_chip_and_handler_name(irq, &intc_dev,
						handle_level_irq, "level");
		irq_set_status_flags(irq, IRQ_LEVEL);
	}
	return 0;
}
Beispiel #8
0
/*
 * All of the FPGA interrupt request inputs except for the touchscreen are
 * edge-sensitive; the touchscreen is level-sensitive.  The edge-sensitive
 * interrupts are acknowledged as a side-effect of reading the interrupt
 * status register from the FPGA.  The edge-sensitive interrupt inputs
 * cause a problem with level interrupt requests, such as Ethernet.  The
 * problem occurs when a level interrupt request is asserted while its
 * interrupt input is masked in the FPGA, which results in a missed
 * interrupt.
 *
 * In an attempt to workaround the problem with missed interrupts, the
 * mask_ack routine for all of the FPGA interrupts has been changed from
 * fpga_mask_ack_irq() to fpga_ack_irq() so that the specific FPGA interrupt
 * being serviced is left unmasked.  We can do this because the FPGA cascade
 * interrupt is run with all interrupts masked.
 *
 * Limited testing indicates that this workaround appears to be effective
 * for the smc9194 Ethernet driver used on the Innovator.  It should work
 * on other FPGA interrupts as well, but any drivers that explicitly mask
 * interrupts at the interrupt controller via disable_irq/enable_irq
 * could pose a problem.
 */
void omap1510_fpga_init_irq(void)
{
	int i, res;

	__raw_writeb(0, OMAP1510_FPGA_IMR_LO);
	__raw_writeb(0, OMAP1510_FPGA_IMR_HI);
	__raw_writeb(0, INNOVATOR_FPGA_IMR2);

	for (i = OMAP_FPGA_IRQ_BASE; i < OMAP_FPGA_IRQ_END; i++) {

		if (i == OMAP1510_INT_FPGA_TS) {
			/*
			 * The touchscreen interrupt is level-sensitive, so
			 * we'll use the regular mask_ack routine for it.
			 */
			irq_set_chip(i, &omap_fpga_irq_ack);
		}
		else {
			/*
			 * All FPGA interrupts except the touchscreen are
			 * edge-sensitive, so we won't mask them.
			 */
			irq_set_chip(i, &omap_fpga_irq);
		}

		irq_set_handler(i, handle_edge_irq);
		irq_clear_status_flags(i, IRQ_NOREQUEST);
	}

	/*
	 * The FPGA interrupt line is connected to GPIO13. Claim this pin for
	 * the ARM.
	 *
	 * NOTE: For general GPIO/MPUIO access and interrupts, please see
	 * gpio.[ch]
	 */
	res = gpio_request(13, "FPGA irq");
	if (res) {
		pr_err("%s failed to get gpio\n", __func__);
		return;
	}
	gpio_direction_input(13);
	irq_set_irq_type(gpio_to_irq(13), IRQ_TYPE_EDGE_RISING);
	irq_set_chained_handler(OMAP1510_INT_FPGA, innovator_fpga_IRQ_demux);
}
static void __init balloon3_init_irq(void)
{
	int irq;

	pxa27x_init_irq();
	/* setup extra Balloon3 irqs */
	for (irq = BALLOON3_IRQ(0); irq <= BALLOON3_IRQ(7); irq++) {
		irq_set_chip_and_handler(irq, &balloon3_irq_chip,
					 handle_level_irq);
		irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
	}

	irq_set_chained_handler(BALLOON3_AUX_NIRQ, balloon3_irq_handler);
	irq_set_irq_type(BALLOON3_AUX_NIRQ, IRQ_TYPE_EDGE_FALLING);

	pr_debug("%s: chained handler installed - irq %d automatically "
		"enabled\n", __func__, BALLOON3_AUX_NIRQ);
}
Beispiel #10
0
static void __init pcm990_init_irq(void)
{
	int irq;

	/* setup extra PCM990 irqs */
	for (irq = PCM027_IRQ(0); irq <= PCM027_IRQ(3); irq++) {
		irq_set_chip_and_handler(irq, &pcm990_irq_chip,
					 handle_level_irq);
		irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
	}

	/* disable all Interrupts */
	pcm990_cpld_writeb(0x0, PCM990_CTRL_INTMSKENA);
	pcm990_cpld_writeb(0xff, PCM990_CTRL_INTSETCLR);

	irq_set_chained_handler(PCM990_CTRL_INT_IRQ, pcm990_irq_handler);
	irq_set_irq_type(PCM990_CTRL_INT_IRQ, PCM990_CTRL_INT_IRQ_EDGE);
}
Beispiel #11
0
/**
 * irq_alloc_hwirqs - Allocate an irq descriptor and initialize the hardware
 * @cnt:	number of interrupts to allocate
 * @node:	node on which to allocate
 *
 * Returns an interrupt number > 0 or 0, if the allocation fails.
 */
unsigned int irq_alloc_hwirqs(int cnt, int node)
{
	int i, irq = __irq_alloc_descs(-1, 0, cnt, node, NULL, NULL);

	if (irq < 0)
		return 0;

	for (i = irq; cnt > 0; i++, cnt--) {
		if (arch_setup_hwirq(i, node))
			goto err;
		irq_clear_status_flags(i, _IRQ_NOREQUEST);
	}
	return irq;

err:
	for (i--; i >= irq; i--) {
		irq_set_status_flags(i, _IRQ_NOREQUEST | _IRQ_NOPROBE);
		arch_teardown_hwirq(i);
	}
	irq_free_descs(irq, cnt);
	return 0;
}
Beispiel #12
0
static void hpet_msi_free(struct irq_domain *domain,
			  struct msi_domain_info *info, unsigned int virq)
{
	irq_clear_status_flags(virq, IRQ_MOVE_PCNTXT);
}
Beispiel #13
0
int its_unmap_vlpi(int irq)
{
	irq_clear_status_flags(irq, IRQ_DISABLE_UNLAZY);
	return irq_set_vcpu_affinity(irq, NULL);
}
Beispiel #14
0
/**
 * 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;
}
Beispiel #15
0
static int __init CoreServicesInit(void)
{
    int         ret_val         = 0;
    int         result          = 0;
    uint32_t    currentSettings = 0;


    struct resource* r = request_mem_region(ALLOY_RAM_BASE, ALLOY_DEDICATED_RAM_SIZE, "AlloyRAM");
    if(r == NULL)
    {
        printk("request_mem_region failed.\n");
    }
    else
    {
        printk("request_mem_region ok.\n");
    }

    r = request_mem_region(0x40000000, 4096, "AlloyPeripherals");
    if(r == NULL)
    {
        printk("request_mem_region failed.\n");
    }
    else
    {
        printk("request_mem_region ok.\n");
    }

    /*
     * Register the character device (atleast try)
     */
    ret_val = register_chrdev(MAJOR_NUM, DEVICE_NAME, &Fops);

    /*
     * Negative values signify an error
     */
    if (ret_val < 0)
    {
        printk(KERN_ALERT "%s failed with %d\n", "Sorry, registering the character device ", ret_val);
        return ret_val;
    }

    set_irq_flags(IRQ_ARM_LOCAL_MAILBOX2, IRQF_VALID);
    irq_clear_status_flags(IRQ_ARM_LOCAL_MAILBOX2, IRQ_PER_CPU);
    irq_clear_status_flags(IRQ_ARM_LOCAL_MAILBOX2, IRQ_LEVEL);


    irq_modify_status(IRQ_ARM_LOCAL_MAILBOX0,0xffffffff,0x00000000);
    irq_modify_status(IRQ_ARM_LOCAL_MAILBOX1,0xffffffff,0x00000000);
    irq_modify_status(IRQ_ARM_LOCAL_MAILBOX2,0xffffffff,0x00000000);
    irq_modify_status(IRQ_ARM_LOCAL_MAILBOX3,0xffffffff,0x00000000);

    //
    // Register the interrupt handler for mailbox IRQs.
    // 
    set_irq_flags(IRQ_ARM_LOCAL_MAILBOX2, IRQF_VALID);
    result = request_threaded_irq(   IRQ_ARM_LOCAL_MAILBOX0,                 // The interrupt number requested 
                            (irq_handler_t) MailboxIRQHandler0,      // The pointer to the handler function (above)
                            NULL,
                            IRQF_SHARED,           // Interrupt is on rising edge (button press in Fig.1)
                            "MailboxIRQHandler",                    // Used in /proc/interrupts to identify the owner
                            DEVICE_NAME);                                  // The *dev_id for shared interrupt lines, NULL here

    result = request_threaded_irq(   IRQ_ARM_LOCAL_MAILBOX1,                 // The interrupt number requested 
                            (irq_handler_t) MailboxIRQHandler1,      // The pointer to the handler function (above)
                            NULL,
                            IRQF_SHARED,           // Interrupt is on rising edge (button press in Fig.1)
                            "MailboxIRQHandler",                    // Used in /proc/interrupts to identify the owner
                            DEVICE_NAME);                                  // The *dev_id for shared interrupt lines, NULL here

    result = request_threaded_irq(   IRQ_ARM_LOCAL_MAILBOX2,                 // The interrupt number requested 
                            (irq_handler_t) MailboxIRQHandler2,      // The pointer to the handler function (above)
                            NULL,
                            IRQF_SHARED,           // Interrupt is on rising edge (button press in Fig.1)
                            "MailboxIRQHandler",                    // Used in /proc/interrupts to identify the owner
                            DEVICE_NAME);                                  // The *dev_id for shared interrupt lines, NULL here

    result = request_threaded_irq(   IRQ_ARM_LOCAL_MAILBOX3,                 // The interrupt number requested 
                            (irq_handler_t) MailboxIRQHandler3,      // The pointer to the handler function (above)
                            NULL,
                            IRQF_SHARED,           // Interrupt is on rising edge (button press in Fig.1)
                            "MailboxIRQHandler",                    // Used in /proc/interrupts to identify the owner
                            DEVICE_NAME);                                  // The *dev_id for shared interrupt lines, NULL here
    if(result == 0)
    {
        printk(KERN_INFO "Mailbox ISR registered ok.\n");
    }
    else
    {
        printk(KERN_INFO "Mailbox ISR registration failed (%d).\n", result);        
    }

    //
    // Enable the interupt.
    // We're on Core0 and we want to enable the Mailbox 1 interrupt.
    //
    currentSettings     = readl( __io_address(ARM_LOCAL_MAILBOX_INT_CONTROL0) );
    currentSettings |= 0x0000000f;
    writel( currentSettings, __io_address(ARM_LOCAL_MAILBOX_INT_CONTROL0) );


    //
    //
    //
    alloyRam    = ioremap_nocache( ALLOY_RAM_BASE, ALLOY_DEDICATED_RAM_SIZE );

    printk(KERN_INFO "%s The major device number is %d.\n", "Registeration is a success", MAJOR_NUM);
    printk(KERN_INFO "If you want to talk to the device driver,\n");
    printk(KERN_INFO "you'll have to create a device file. \n");
    printk(KERN_INFO "We suggest you use:\n");
    printk(KERN_INFO "mknod %s c %d 0\n", DEVICE_FILE_NAME, MAJOR_NUM);
    printk(KERN_INFO "The device file name is important, because\n");
    printk(KERN_INFO "the ioctl program assumes that's the\n");
    printk(KERN_INFO "file you'll use.\n");

    return 0;
}
Beispiel #16
0
void __init init_IRQ(void)
{
	u32 i, j, intr_type;
	struct device_node *intc = NULL;
#ifdef CONFIG_SELFMOD_INTC
	unsigned int intc_baseaddr = 0;
	static int arr_func[] = {
				(int)&get_irq,
				(int)&intc_enable_or_unmask,
				(int)&intc_disable_or_mask,
				(int)&intc_mask_ack,
				(int)&intc_ack,
				(int)&intc_end,
				0
			};
#endif
	const char * const intc_list[] = {
				"xlnx,xps-intc-1.00.a",
				NULL
			};

	for (j = 0; intc_list[j] != NULL; j++) {
		intc = of_find_compatible_node(NULL, NULL, intc_list[j]);
		if (intc)
			break;
	}
	BUG_ON(!intc);

	intc_baseaddr = be32_to_cpup(of_get_property(intc,
								"reg", NULL));
	intc_baseaddr = (unsigned long) ioremap(intc_baseaddr, PAGE_SIZE);
	nr_irq = be32_to_cpup(of_get_property(intc,
						"xlnx,num-intr-inputs", NULL));

	intr_type =
		be32_to_cpup(of_get_property(intc,
						"xlnx,kind-of-intr", NULL));
	if (intr_type > (u32)((1ULL << nr_irq) - 1))
		printk(KERN_INFO " ERROR: Mismatch in kind-of-intr param\n");

#ifdef CONFIG_SELFMOD_INTC
	selfmod_function((int *) arr_func, intc_baseaddr);
#endif
	printk(KERN_INFO "%s #0 at 0x%08x, num_irq=%d, edge=0x%x\n",
		intc_list[j], intc_baseaddr, nr_irq, intr_type);

	/*
	 * Disable all external interrupts until they are
	 * explicity requested.
	 */
	out_be32(intc_baseaddr + IER, 0);

	/* Acknowledge any pending interrupts just in case. */
	out_be32(intc_baseaddr + IAR, 0xffffffff);

	/* Turn on the Master Enable. */
	out_be32(intc_baseaddr + MER, MER_HIE | MER_ME);

	for (i = 0; i < nr_irq; ++i) {
		if (intr_type & (0x00000001 << i)) {
			irq_set_chip_and_handler_name(i, &intc_dev,
				handle_edge_irq, "edge");
			irq_clear_status_flags(i, IRQ_LEVEL);
		} else {
			irq_set_chip_and_handler_name(i, &intc_dev,
				handle_level_irq, "level");
			irq_set_status_flags(i, IRQ_LEVEL);
		}
	}
}
Beispiel #17
0
static int ezx_pcap_probe(struct spi_device *spi)
{
	struct pcap_platform_data *pdata = dev_get_platdata(&spi->dev);
	struct pcap_chip *pcap;
	int i, adc_irq;
	int ret = -ENODEV;

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

	pcap = devm_kzalloc(&spi->dev, 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);
	spi_set_drvdata(spi, 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 ret;

	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 ret;
	}

	/* 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);
		irq_clear_status_flags(i, IRQ_NOREQUEST | IRQ_NOPROBE);
	}

	/* 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_chained_handler_and_data(spi->irq, pcap_irq_handler, pcap);
	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 = devm_request_irq(&spi->dev, 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_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);
ret:
	return ret;
}