diff options
author | Simon Horman <horms@verge.net.au> | 2011-08-26 04:42:39 -0400 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2011-10-26 15:43:36 -0400 |
commit | d5098cb63b3f13da2a2b230b3566ac7b5dfa4f28 (patch) | |
tree | b1317ea1339a678b283a0213f5c6647a58099b33 /drivers/mmc/host/sh_mobile_sdhi.c | |
parent | 7729c7a232a95360fa17ffe8beb1adb621bc0ba0 (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.c | 98 |
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 | ||
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); |