aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mmc/host/sh_mobile_sdhi.c98
-rw-r--r--include/linux/mmc/sh_mobile_sdhi.h4
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
184eirq: 218eirq_multiplexed:
219 while (i--) {
220 irq = platform_get_irq(pdev, i);
221 free_irq(irq, host);
222 }
223eirq_sdcard:
224 irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_SDIO);
225 if (irq >= 0)
226 free_irq(irq, host);
227eirq_sdio:
228 irq = platform_get_irq_byname(pdev, SH_MOBILE_SDHI_IRQ_CARD_DETECT);
229 if (irq >= 0)
230 free_irq(irq, host);
231eirq_card_detect:
185 tmio_mmc_host_remove(host); 232 tmio_mmc_host_remove(host);
186eprobe: 233eprobe:
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 @@
6struct platform_device; 6struct platform_device;
7struct tmio_mmc_data; 7struct 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
9struct sh_mobile_sdhi_info { 13struct sh_mobile_sdhi_info {
10 int dma_slave_tx; 14 int dma_slave_tx;
11 int dma_slave_rx; 15 int dma_slave_rx;