[PATCH] Allow IRQ-less operation of htc-egpio

From: Philipp Zabel <philipp.zabel_at_gmail.com>
Date: Mon, 12 Nov 2007 23:22:44 +0100

Hi,

there are some HTC devices (hx4700, n560, artemis, athena) that have one
or more memory mapped EGPIO registers with output pins only.
The following patch makes the htc-egpio probe just not register the irq
handler instead of failing if there is no base_irq given.

regards
Philipp

Index: kernel26/drivers/mfd/htc-egpio.c
===================================================================
--- kernel26.orig/drivers/mfd/htc-egpio.c 2007-11-12 21:40:22.000000000 +0100
+++ kernel26/drivers/mfd/htc-egpio.c 2007-11-12 21:40:24.000000000 +0100
@@ -226,9 +226,8 @@
         /* Find chained irq */
         ret = -EINVAL;
         res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!res)
- goto fail;
- ei->chainedirq = res->start;
+ if (res)
+ ei->chainedirq = res->start;
 
         /* Map egpio chip into virtual address space. */
         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -255,29 +254,32 @@
         for (i = 0; i < pdata->nr_pins; i++)
                 setup_pin(ei, &pdata->pins[i]);
 
- /* Setup irq handlers */
- ei->ackWrite = 0xFFFF;
- if (pdata->invertAcks)
- ei->ackWrite = 0;
- for (irq = ei->irqStart; irq < ei->irqStart+MAX_EGPIO_IRQS; irq++) {
- set_irq_chip(irq, &egpio_muxed_chip);
- set_irq_chip_data(irq, ei);
- set_irq_handler(irq, handle_simple_irq);
- set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+ if (ei->chainedirq) {
+ /* Setup irq handlers */
+ ei->ackWrite = 0xFFFF;
+ if (pdata->invertAcks)
+ ei->ackWrite = 0;
+ for (irq = ei->irqStart; irq < ei->irqStart+MAX_EGPIO_IRQS; irq++) {
+ set_irq_chip(irq, &egpio_muxed_chip);
+ set_irq_chip_data(irq, ei);
+ set_irq_handler(irq, handle_simple_irq);
+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+ }
+ set_irq_type(ei->chainedirq, IRQT_RISING);
+ set_irq_data(ei->chainedirq, ei);
+ set_irq_chained_handler(ei->chainedirq, egpio_handler);
+ ackirqs(ei);
+
+ device_init_wakeup(&pdev->dev, 1);
         }
- set_irq_type(ei->chainedirq, IRQT_RISING);
- set_irq_data(ei->chainedirq, ei);
- set_irq_chained_handler(ei->chainedirq, egpio_handler);
- ackirqs(ei);
 
         /* Setup initial output pin values. */
         for (i = 0; i<=ei->maxRegs; i++)
                 if (i != ei->ackRegister)
                         writew(ei->cached_values[i], &ei->addrBase[i << ei->bus_shift]);
 
- device_init_wakeup(&pdev->dev, 1);
-
         return 0;
+
 fail:
         printk(KERN_NOTICE "EGPIO failed to setup\n");
         kfree(ei);
@@ -288,18 +290,18 @@
 {
         struct egpio_info *ei = platform_get_drvdata(pdev);
         unsigned int irq;
- for (irq = ei->irqStart; irq < ei->irqStart+MAX_EGPIO_IRQS; irq++) {
- set_irq_chip(irq, NULL);
- set_irq_handler(irq, NULL);
- set_irq_flags(irq, 0);
+ if (ei->chainedirq) {
+ for (irq = ei->irqStart; irq < ei->irqStart+MAX_EGPIO_IRQS; irq++) {
+ set_irq_chip(irq, NULL);
+ set_irq_handler(irq, NULL);
+ set_irq_flags(irq, 0);
+ }
+ set_irq_chained_handler(ei->chainedirq, NULL);
+ device_init_wakeup(&pdev->dev, 0);
         }
- set_irq_chained_handler(ei->chainedirq, NULL);
-
         iounmap(ei->addrBase);
         kfree(ei);
 
- device_init_wakeup(&pdev->dev, 0);
-
         return 0;
 }
 
@@ -308,7 +310,7 @@
 {
         struct egpio_info *ei = platform_get_drvdata(pdev);
 
- if (device_may_wakeup(&pdev->dev))
+ if (ei->chainedirq && device_may_wakeup(&pdev->dev))
                 enable_irq_wake(ei->chainedirq);
         return 0;
 }
@@ -317,7 +319,7 @@
 {
         struct egpio_info *ei = platform_get_drvdata(pdev);
 
- if (device_may_wakeup(&pdev->dev))
+ if (ei->chainedirq && device_may_wakeup(&pdev->dev))
                 disable_irq_wake(ei->chainedirq);
         return 0;
 }
Received on Mon Nov 12 2007 - 17:23:02 EST

This archive was generated by hypermail 2.2.0 : Mon Nov 12 2007 - 17:23:16 EST