aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/sh_mobile_sdhi.c
diff options
context:
space:
mode:
authorSimon Horman <horms@verge.net.au>2011-08-26 04:42:39 -0400
committerChris Ball <cjb@laptop.org>2011-10-26 15:43:36 -0400
commitd5098cb63b3f13da2a2b230b3566ac7b5dfa4f28 (patch)
treeb1317ea1339a678b283a0213f5c6647a58099b33 /drivers/mmc/host/sh_mobile_sdhi.c
parent7729c7a232a95360fa17ffe8beb1adb621bc0ba0 (diff)
mmc: sdhi: Allow named IRQs to use specific handlers
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>
Diffstat (limited to 'drivers/mmc/host/sh_mobile_sdhi.c')
-rw-r--r--drivers/mmc/host/sh_mobile_sdhi.c98
1 files changed, 73 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);