mmc: sdhi: Allow named IRQs to use specific handlers
authorSimon Horman <horms@verge.net.au>
Fri, 26 Aug 2011 08:42:39 +0000 (10:42 +0200)
committerChris Ball <cjb@laptop.org>
Wed, 26 Oct 2011 19:43:36 +0000 (15:43 -0400)
Allow named IRQs to use corresponding specific handlers. If named IRQs are
used, at least an "sdcard" IRQ has to be specified by the platform. If
names are not used, an arbitrary number of IRQs can be provided by the
platform, in which case the generic ISR will be used for each of them.

Cc: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Acked-by: Magnus Damm <magnus.damm@gmail.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
[g.liakhovetski@gmx.de: style and typo corrections, platform data check]
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Chris Ball <cjb@laptop.org>
drivers/mmc/host/sh_mobile_sdhi.c
include/linux/mmc/sh_mobile_sdhi.h

index 0c4a672f5db618bd68c96b4bb7a6239bdf7f12aa..75bffc4768fe5f5a6362f3f8a9b5f68ffe8f9c5a 100644 (file)
@@ -96,7 +96,8 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
        struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
        struct tmio_mmc_host *host;
        char clk_name[8];
-       int i, irq, ret;
+       int irq, ret, i = 0;
+       bool multiplexed_isr = true;
 
        priv = kzalloc(sizeof(struct sh_mobile_sdhi), GFP_KERNEL);
        if (priv == NULL) {
@@ -153,27 +154,60 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
        if (ret < 0)
                goto eprobe;
 
-       for (i = 0; i < 3; i++) {
-               irq = platform_get_irq(pdev, i);
-               if (irq < 0) {
-                       if (i) {
-                               continue;
-                       } else {
-                               ret = irq;
-                               goto eirq;
-                       }
-               }
-               ret = request_irq(irq, tmio_mmc_irq, 0,
+       /*
+        * Allow one or more specific (named) ISRs or
+        * one or more multiplexed (un-named) ISRs.
+        */
+
+       irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_CARD_DETECT);
+       if (irq >= 0) {
+               multiplexed_isr = false;
+               ret = request_irq(irq, tmio_mmc_card_detect_irq, 0,
+                                 dev_name(&pdev->dev), host);
+               if (ret)
+                       goto eirq_card_detect;
+       }
+
+       irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_SDIO);
+       if (irq >= 0) {
+               multiplexed_isr = false;
+               ret = request_irq(irq, tmio_mmc_sdio_irq, 0,
+                                 dev_name(&pdev->dev), host);
+               if (ret)
+                       goto eirq_sdio;
+       }
+
+       irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_SDCARD);
+       if (irq >= 0) {
+               multiplexed_isr = false;
+               ret = request_irq(irq, tmio_mmc_sdcard_irq, 0,
                                  dev_name(&pdev->dev), host);
-               if (ret) {
-                       while (i--) {
-                               irq = platform_get_irq(pdev, i);
-                               if (irq >= 0)
-                                       free_irq(irq, host);
-                       }
-                       goto eirq;
+               if (ret)
+                       goto eirq_sdcard;
+       } else if (!multiplexed_isr) {
+               dev_err(&pdev->dev,
+                       "Principal SD-card IRQ is missing among named interrupts\n");
+               ret = irq;
+               goto eirq_sdcard;
+       }
+
+       if (multiplexed_isr) {
+               while (1) {
+                       irq = platform_get_irq(pdev, i);
+                       if (irq < 0)
+                               break;
+                       i++;
+                       ret = request_irq(irq, tmio_mmc_irq, 0,
+                                         dev_name(&pdev->dev), host);
+                       if (ret)
+                               goto eirq_multiplexed;
                }
+
+               /* There must be at least one IRQ source */
+               if (!i)
+                       goto eirq_multiplexed;
        }
+
        dev_info(&pdev->dev, "%s base at 0x%08lx clock rate %u MHz\n",
                 mmc_hostname(host->mmc), (unsigned long)
                 (platform_get_resource(pdev,IORESOURCE_MEM, 0)->start),
@@ -181,7 +215,20 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
 
        return ret;
 
-eirq:
+eirq_multiplexed:
+       while (i--) {
+               irq = platform_get_irq(pdev, i);
+               free_irq(irq, host);
+       }
+eirq_sdcard:
+       irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_SDIO);
+       if (irq >= 0)
+               free_irq(irq, host);
+eirq_sdio:
+       irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_CARD_DETECT);
+       if (irq >= 0)
+               free_irq(irq, host);
+eirq_card_detect:
        tmio_mmc_host_remove(host);
 eprobe:
        clk_disable(priv->clk);
@@ -197,16 +244,17 @@ static int sh_mobile_sdhi_remove(struct platform_device *pdev)
        struct tmio_mmc_host *host = mmc_priv(mmc);
        struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data);
        struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
-       int i, irq;
+       int i = 0, irq;
 
        p->pdata = NULL;
 
        tmio_mmc_host_remove(host);
 
-       for (i = 0; i < 3; i++) {
-               irq = platform_get_irq(pdev, i);
-               if (irq >= 0)
-                       free_irq(irq, host);
+       while (1) {
+               irq = platform_get_irq(pdev, i++);
+               if (irq < 0)
+                       break;
+               free_irq(irq, host);
        }
 
        clk_disable(priv->clk);
index bd50b365167f25586848d18b23d04c3a6f2917e8..71b805451bd82d9175ae2dff99a467edb62a83b2 100644 (file)
@@ -6,6 +6,10 @@
 struct platform_device;
 struct tmio_mmc_data;
 
+#define SH_MOBILE_SDHI_IRQ_CARD_DETECT "card_detect"
+#define SH_MOBILE_SDHI_IRQ_SDCARD      "sdcard"
+#define SH_MOBILE_SDHI_IRQ_SDIO                "sdio"
+
 struct sh_mobile_sdhi_info {
        int dma_slave_tx;
        int dma_slave_rx;