diff options
| -rw-r--r-- | drivers/mmc/host/sh_mobile_sdhi.c | 98 | ||||
| -rw-r--r-- | include/linux/mmc/sh_mobile_sdhi.h | 4 |
2 files changed, 77 insertions, 25 deletions
diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c index 0c4a672f5db6..75bffc4768fe 100644 --- a/drivers/mmc/host/sh_mobile_sdhi.c +++ b/drivers/mmc/host/sh_mobile_sdhi.c | |||
| @@ -96,7 +96,8 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) | |||
| 96 | struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; | 96 | struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; |
| 97 | struct tmio_mmc_host *host; | 97 | struct tmio_mmc_host *host; |
| 98 | char clk_name[8]; | 98 | char clk_name[8]; |
| 99 | int i, irq, ret; | 99 | int irq, ret, i = 0; |
| 100 | bool multiplexed_isr = true; | ||
| 100 | 101 | ||
| 101 | priv = kzalloc(sizeof(struct sh_mobile_sdhi), GFP_KERNEL); | 102 | priv = kzalloc(sizeof(struct sh_mobile_sdhi), GFP_KERNEL); |
| 102 | if (priv == NULL) { | 103 | if (priv == NULL) { |
| @@ -153,27 +154,60 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) | |||
| 153 | if (ret < 0) | 154 | if (ret < 0) |
| 154 | goto eprobe; | 155 | goto eprobe; |
| 155 | 156 | ||
| 156 | for (i = 0; i < 3; i++) { | 157 | /* |
| 157 | irq = platform_get_irq(pdev, i); | 158 | * Allow one or more specific (named) ISRs or |
| 158 | if (irq < 0) { | 159 | * one or more multiplexed (un-named) ISRs. |
| 159 | if (i) { | 160 | */ |
| 160 | continue; | 161 | |
| 161 | } else { | 162 | irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_CARD_DETECT); |
| 162 | ret = irq; | 163 | if (irq >= 0) { |
| 163 | goto eirq; | 164 | multiplexed_isr = false; |
| 164 | } | 165 | ret = request_irq(irq, tmio_mmc_card_detect_irq, 0, |
| 165 | } | 166 | dev_name(&pdev->dev), host); |
| 166 | ret = request_irq(irq, tmio_mmc_irq, 0, | 167 | if (ret) |
| 168 | goto eirq_card_detect; | ||
| 169 | } | ||
| 170 | |||
| 171 | irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_SDIO); | ||
| 172 | if (irq >= 0) { | ||
| 173 | multiplexed_isr = false; | ||
| 174 | ret = request_irq(irq, tmio_mmc_sdio_irq, 0, | ||
| 175 | dev_name(&pdev->dev), host); | ||
| 176 | if (ret) | ||
| 177 | goto eirq_sdio; | ||
| 178 | } | ||
| 179 | |||
| 180 | irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_SDCARD); | ||
| 181 | if (irq >= 0) { | ||
| 182 | multiplexed_isr = false; | ||
| 183 | ret = request_irq(irq, tmio_mmc_sdcard_irq, 0, | ||
| 167 | dev_name(&pdev->dev), host); | 184 | dev_name(&pdev->dev), host); |
| 168 | if (ret) { | 185 | if (ret) |
| 169 | while (i--) { | 186 | goto eirq_sdcard; |
| 170 | irq = platform_get_irq(pdev, i); | 187 | } else if (!multiplexed_isr) { |
| 171 | if (irq >= 0) | 188 | dev_err(&pdev->dev, |
| 172 | free_irq(irq, host); | 189 | "Principal SD-card IRQ is missing among named interrupts\n"); |
| 173 | } | 190 | ret = irq; |
| 174 | goto eirq; | 191 | goto eirq_sdcard; |
| 192 | } | ||
| 193 | |||
| 194 | if (multiplexed_isr) { | ||
| 195 | while (1) { | ||
| 196 | irq = platform_get_irq(pdev, i); | ||
| 197 | if (irq < 0) | ||
| 198 | break; | ||
| 199 | i++; | ||
| 200 | ret = request_irq(irq, tmio_mmc_irq, 0, | ||
| 201 | dev_name(&pdev->dev), host); | ||
| 202 | if (ret) | ||
| 203 | goto eirq_multiplexed; | ||
| 175 | } | 204 | } |
| 205 | |||
| 206 | /* There must be at least one IRQ source */ | ||
| 207 | if (!i) | ||
| 208 | goto eirq_multiplexed; | ||
| 176 | } | 209 | } |
| 210 | |||
| 177 | dev_info(&pdev->dev, "%s base at 0x%08lx clock rate %u MHz\n", | 211 | dev_info(&pdev->dev, "%s base at 0x%08lx clock rate %u MHz\n", |
| 178 | mmc_hostname(host->mmc), (unsigned long) | 212 | mmc_hostname(host->mmc), (unsigned long) |
| 179 | (platform_get_resource(pdev,IORESOURCE_MEM, 0)->start), | 213 | (platform_get_resource(pdev,IORESOURCE_MEM, 0)->start), |
| @@ -181,7 +215,20 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) | |||
| 181 | 215 | ||
| 182 | return ret; | 216 | return ret; |
| 183 | 217 | ||
| 184 | eirq: | 218 | eirq_multiplexed: |
| 219 | while (i--) { | ||
| 220 | irq = platform_get_irq(pdev, i); | ||
| 221 | free_irq(irq, host); | ||
| 222 | } | ||
| 223 | eirq_sdcard: | ||
| 224 | irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_SDIO); | ||
| 225 | if (irq >= 0) | ||
| 226 | free_irq(irq, host); | ||
| 227 | eirq_sdio: | ||
| 228 | irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_CARD_DETECT); | ||
| 229 | if (irq >= 0) | ||
| 230 | free_irq(irq, host); | ||
| 231 | eirq_card_detect: | ||
| 185 | tmio_mmc_host_remove(host); | 232 | tmio_mmc_host_remove(host); |
| 186 | eprobe: | 233 | eprobe: |
| 187 | clk_disable(priv->clk); | 234 | clk_disable(priv->clk); |
| @@ -197,16 +244,17 @@ static int sh_mobile_sdhi_remove(struct platform_device *pdev) | |||
| 197 | struct tmio_mmc_host *host = mmc_priv(mmc); | 244 | struct tmio_mmc_host *host = mmc_priv(mmc); |
| 198 | struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data); | 245 | struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data); |
| 199 | struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; | 246 | struct sh_mobile_sdhi_info *p = pdev->dev.platform_data; |
| 200 | int i, irq; | 247 | int i = 0, irq; |
| 201 | 248 | ||
| 202 | p->pdata = NULL; | 249 | p->pdata = NULL; |
| 203 | 250 | ||
| 204 | tmio_mmc_host_remove(host); | 251 | tmio_mmc_host_remove(host); |
| 205 | 252 | ||
| 206 | for (i = 0; i < 3; i++) { | 253 | while (1) { |
| 207 | irq = platform_get_irq(pdev, i); | 254 | irq = platform_get_irq(pdev, i++); |
| 208 | if (irq >= 0) | 255 | if (irq < 0) |
| 209 | free_irq(irq, host); | 256 | break; |
| 257 | free_irq(irq, host); | ||
| 210 | } | 258 | } |
| 211 | 259 | ||
| 212 | clk_disable(priv->clk); | 260 | clk_disable(priv->clk); |
diff --git a/include/linux/mmc/sh_mobile_sdhi.h b/include/linux/mmc/sh_mobile_sdhi.h index bd50b365167f..71b805451bd8 100644 --- a/include/linux/mmc/sh_mobile_sdhi.h +++ b/include/linux/mmc/sh_mobile_sdhi.h | |||
| @@ -6,6 +6,10 @@ | |||
| 6 | struct platform_device; | 6 | struct platform_device; |
| 7 | struct tmio_mmc_data; | 7 | struct tmio_mmc_data; |
| 8 | 8 | ||
| 9 | #define SH_MOBILE_SDHI_IRQ_CARD_DETECT "card_detect" | ||
| 10 | #define SH_MOBILE_SDHI_IRQ_SDCARD "sdcard" | ||
| 11 | #define SH_MOBILE_SDHI_IRQ_SDIO "sdio" | ||
| 12 | |||
| 9 | struct sh_mobile_sdhi_info { | 13 | struct sh_mobile_sdhi_info { |
| 10 | int dma_slave_tx; | 14 | int dma_slave_tx; |
| 11 | int dma_slave_rx; | 15 | int dma_slave_rx; |
