diff options
Diffstat (limited to 'drivers/mmc/host/sdhci-pxav3.c')
-rw-r--r-- | drivers/mmc/host/sdhci-pxav3.c | 35 |
1 files changed, 31 insertions, 4 deletions
diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index 07fe3834fe0b..e918a2bb3af1 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c | |||
@@ -24,12 +24,14 @@ | |||
24 | #include <linux/gpio.h> | 24 | #include <linux/gpio.h> |
25 | #include <linux/mmc/card.h> | 25 | #include <linux/mmc/card.h> |
26 | #include <linux/mmc/host.h> | 26 | #include <linux/mmc/host.h> |
27 | #include <linux/mmc/slot-gpio.h> | ||
27 | #include <linux/platform_data/pxa_sdhci.h> | 28 | #include <linux/platform_data/pxa_sdhci.h> |
28 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
29 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
30 | #include <linux/module.h> | 31 | #include <linux/module.h> |
31 | #include <linux/of.h> | 32 | #include <linux/of.h> |
32 | #include <linux/of_device.h> | 33 | #include <linux/of_device.h> |
34 | #include <linux/of_gpio.h> | ||
33 | 35 | ||
34 | #include "sdhci.h" | 36 | #include "sdhci.h" |
35 | #include "sdhci-pltfm.h" | 37 | #include "sdhci-pltfm.h" |
@@ -182,6 +184,7 @@ static struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev) | |||
182 | struct device_node *np = dev->of_node; | 184 | struct device_node *np = dev->of_node; |
183 | u32 bus_width; | 185 | u32 bus_width; |
184 | u32 clk_delay_cycles; | 186 | u32 clk_delay_cycles; |
187 | enum of_gpio_flags gpio_flags; | ||
185 | 188 | ||
186 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | 189 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); |
187 | if (!pdata) | 190 | if (!pdata) |
@@ -198,6 +201,10 @@ static struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev) | |||
198 | if (clk_delay_cycles > 0) | 201 | if (clk_delay_cycles > 0) |
199 | pdata->clk_delay_cycles = clk_delay_cycles; | 202 | pdata->clk_delay_cycles = clk_delay_cycles; |
200 | 203 | ||
204 | pdata->ext_cd_gpio = of_get_named_gpio_flags(np, "cd-gpios", 0, &gpio_flags); | ||
205 | if (gpio_flags != OF_GPIO_ACTIVE_LOW) | ||
206 | pdata->host_caps2 |= MMC_CAP2_CD_ACTIVE_HIGH; | ||
207 | |||
201 | return pdata; | 208 | return pdata; |
202 | } | 209 | } |
203 | #else | 210 | #else |
@@ -231,14 +238,14 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev) | |||
231 | pltfm_host = sdhci_priv(host); | 238 | pltfm_host = sdhci_priv(host); |
232 | pltfm_host->priv = pxa; | 239 | pltfm_host->priv = pxa; |
233 | 240 | ||
234 | clk = clk_get(dev, "PXA-SDHCLK"); | 241 | clk = clk_get(dev, NULL); |
235 | if (IS_ERR(clk)) { | 242 | if (IS_ERR(clk)) { |
236 | dev_err(dev, "failed to get io clock\n"); | 243 | dev_err(dev, "failed to get io clock\n"); |
237 | ret = PTR_ERR(clk); | 244 | ret = PTR_ERR(clk); |
238 | goto err_clk_get; | 245 | goto err_clk_get; |
239 | } | 246 | } |
240 | pltfm_host->clk = clk; | 247 | pltfm_host->clk = clk; |
241 | clk_enable(clk); | 248 | clk_prepare_enable(clk); |
242 | 249 | ||
243 | host->quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | 250 | host->quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
244 | | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | 251 | | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC |
@@ -266,12 +273,25 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev) | |||
266 | host->quirks |= pdata->quirks; | 273 | host->quirks |= pdata->quirks; |
267 | if (pdata->host_caps) | 274 | if (pdata->host_caps) |
268 | host->mmc->caps |= pdata->host_caps; | 275 | host->mmc->caps |= pdata->host_caps; |
276 | if (pdata->host_caps2) | ||
277 | host->mmc->caps2 |= pdata->host_caps2; | ||
269 | if (pdata->pm_caps) | 278 | if (pdata->pm_caps) |
270 | host->mmc->pm_caps |= pdata->pm_caps; | 279 | host->mmc->pm_caps |= pdata->pm_caps; |
280 | |||
281 | if (gpio_is_valid(pdata->ext_cd_gpio)) { | ||
282 | ret = mmc_gpio_request_cd(host->mmc, pdata->ext_cd_gpio); | ||
283 | if (ret) { | ||
284 | dev_err(mmc_dev(host->mmc), | ||
285 | "failed to allocate card detect gpio\n"); | ||
286 | goto err_cd_req; | ||
287 | } | ||
288 | } | ||
271 | } | 289 | } |
272 | 290 | ||
273 | host->ops = &pxav3_sdhci_ops; | 291 | host->ops = &pxav3_sdhci_ops; |
274 | 292 | ||
293 | sdhci_get_of_property(pdev); | ||
294 | |||
275 | ret = sdhci_add_host(host); | 295 | ret = sdhci_add_host(host); |
276 | if (ret) { | 296 | if (ret) { |
277 | dev_err(&pdev->dev, "failed to add host\n"); | 297 | dev_err(&pdev->dev, "failed to add host\n"); |
@@ -283,8 +303,10 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev) | |||
283 | return 0; | 303 | return 0; |
284 | 304 | ||
285 | err_add_host: | 305 | err_add_host: |
286 | clk_disable(clk); | 306 | clk_disable_unprepare(clk); |
287 | clk_put(clk); | 307 | clk_put(clk); |
308 | mmc_gpio_free_cd(host->mmc); | ||
309 | err_cd_req: | ||
288 | err_clk_get: | 310 | err_clk_get: |
289 | sdhci_pltfm_free(pdev); | 311 | sdhci_pltfm_free(pdev); |
290 | kfree(pxa); | 312 | kfree(pxa); |
@@ -296,11 +318,16 @@ static int __devexit sdhci_pxav3_remove(struct platform_device *pdev) | |||
296 | struct sdhci_host *host = platform_get_drvdata(pdev); | 318 | struct sdhci_host *host = platform_get_drvdata(pdev); |
297 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 319 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
298 | struct sdhci_pxa *pxa = pltfm_host->priv; | 320 | struct sdhci_pxa *pxa = pltfm_host->priv; |
321 | struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data; | ||
299 | 322 | ||
300 | sdhci_remove_host(host, 1); | 323 | sdhci_remove_host(host, 1); |
301 | 324 | ||
302 | clk_disable(pltfm_host->clk); | 325 | clk_disable_unprepare(pltfm_host->clk); |
303 | clk_put(pltfm_host->clk); | 326 | clk_put(pltfm_host->clk); |
327 | |||
328 | if (gpio_is_valid(pdata->ext_cd_gpio)) | ||
329 | mmc_gpio_free_cd(host->mmc); | ||
330 | |||
304 | sdhci_pltfm_free(pdev); | 331 | sdhci_pltfm_free(pdev); |
305 | kfree(pxa); | 332 | kfree(pxa); |
306 | 333 | ||