diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-28 14:16:11 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-28 14:16:11 -0700 |
commit | 46b51ea2099fa2082342e52b8284aa828429b80b (patch) | |
tree | 0a0d7bfe1aff036c86a2e7beacbd91398008bfb6 /drivers/mmc/host/sh_mobile_sdhi.c | |
parent | 1fdb24e969110fafea36d3b393bea438f702c87f (diff) | |
parent | a6029e1f75bb484c1f5bc68b6a8572e4024795bc (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc: (83 commits)
mmc: fix compile error when CONFIG_BLOCK is not enabled
mmc: core: Cleanup eMMC4.5 conditionals
mmc: omap_hsmmc: if multiblock reads are broken, disable them
mmc: core: add workaround for controllers with broken multiblock reads
mmc: core: Prevent too long response times for suspend
mmc: recognise SDIO cards with SDIO_CCCR_REV 3.00
mmc: sd: Handle SD3.0 cards not supporting UHS-I bus speed mode
mmc: core: support HPI send command
mmc: core: Add cache control for eMMC4.5 device
mmc: core: Modify the timeout value for writing power class
mmc: core: new discard feature support at eMMC v4.5
mmc: core: mmc sanitize feature support for v4.5
mmc: dw_mmc: modify DATA register offset
mmc: sdhci-pci: add flag for devices that can support runtime PM
mmc: omap_hsmmc: ensure pbias configuration is always done
mmc: core: Add Power Off Notify Feature eMMC 4.5
mmc: sdhci-s3c: fix potential NULL dereference
mmc: replace printk with appropriate display macro
mmc: core: Add default timeout value for CMD6
mmc: sdhci-pci: add runtime pm support
...
Diffstat (limited to 'drivers/mmc/host/sh_mobile_sdhi.c')
-rw-r--r-- | drivers/mmc/host/sh_mobile_sdhi.c | 99 |
1 files changed, 74 insertions, 25 deletions
diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c index 0c4a672f5db..41ae6466bd8 100644 --- a/drivers/mmc/host/sh_mobile_sdhi.c +++ b/drivers/mmc/host/sh_mobile_sdhi.c @@ -21,6 +21,7 @@ #include <linux/kernel.h> #include <linux/clk.h> #include <linux/slab.h> +#include <linux/module.h> #include <linux/platform_device.h> #include <linux/mmc/host.h> #include <linux/mmc/sh_mobile_sdhi.h> @@ -96,7 +97,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 +155,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 +216,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 +245,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); |