diff options
Diffstat (limited to 'drivers/mmc/host/sdhci-pxav3.c')
-rw-r--r-- | drivers/mmc/host/sdhci-pxav3.c | 62 |
1 files changed, 40 insertions, 22 deletions
diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index 5036d7d39529..45238871192d 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c | |||
@@ -58,6 +58,12 @@ | |||
58 | #define SDCE_MISC_INT (1<<2) | 58 | #define SDCE_MISC_INT (1<<2) |
59 | #define SDCE_MISC_INT_EN (1<<1) | 59 | #define SDCE_MISC_INT_EN (1<<1) |
60 | 60 | ||
61 | struct sdhci_pxa { | ||
62 | struct clk *clk_core; | ||
63 | struct clk *clk_io; | ||
64 | u8 power_mode; | ||
65 | }; | ||
66 | |||
61 | /* | 67 | /* |
62 | * These registers are relative to the second register region, for the | 68 | * These registers are relative to the second register region, for the |
63 | * MBus bridge. | 69 | * MBus bridge. |
@@ -211,6 +217,7 @@ static void pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs) | |||
211 | case MMC_TIMING_UHS_SDR104: | 217 | case MMC_TIMING_UHS_SDR104: |
212 | ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180; | 218 | ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180; |
213 | break; | 219 | break; |
220 | case MMC_TIMING_MMC_DDR52: | ||
214 | case MMC_TIMING_UHS_DDR50: | 221 | case MMC_TIMING_UHS_DDR50: |
215 | ctrl_2 |= SDHCI_CTRL_UHS_DDR50 | SDHCI_CTRL_VDD_180; | 222 | ctrl_2 |= SDHCI_CTRL_UHS_DDR50 | SDHCI_CTRL_VDD_180; |
216 | break; | 223 | break; |
@@ -283,9 +290,7 @@ static int sdhci_pxav3_probe(struct platform_device *pdev) | |||
283 | struct sdhci_host *host = NULL; | 290 | struct sdhci_host *host = NULL; |
284 | struct sdhci_pxa *pxa = NULL; | 291 | struct sdhci_pxa *pxa = NULL; |
285 | const struct of_device_id *match; | 292 | const struct of_device_id *match; |
286 | |||
287 | int ret; | 293 | int ret; |
288 | struct clk *clk; | ||
289 | 294 | ||
290 | pxa = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_pxa), GFP_KERNEL); | 295 | pxa = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_pxa), GFP_KERNEL); |
291 | if (!pxa) | 296 | if (!pxa) |
@@ -305,14 +310,20 @@ static int sdhci_pxav3_probe(struct platform_device *pdev) | |||
305 | pltfm_host = sdhci_priv(host); | 310 | pltfm_host = sdhci_priv(host); |
306 | pltfm_host->priv = pxa; | 311 | pltfm_host->priv = pxa; |
307 | 312 | ||
308 | clk = devm_clk_get(dev, NULL); | 313 | pxa->clk_io = devm_clk_get(dev, "io"); |
309 | if (IS_ERR(clk)) { | 314 | if (IS_ERR(pxa->clk_io)) |
315 | pxa->clk_io = devm_clk_get(dev, NULL); | ||
316 | if (IS_ERR(pxa->clk_io)) { | ||
310 | dev_err(dev, "failed to get io clock\n"); | 317 | dev_err(dev, "failed to get io clock\n"); |
311 | ret = PTR_ERR(clk); | 318 | ret = PTR_ERR(pxa->clk_io); |
312 | goto err_clk_get; | 319 | goto err_clk_get; |
313 | } | 320 | } |
314 | pltfm_host->clk = clk; | 321 | pltfm_host->clk = pxa->clk_io; |
315 | clk_prepare_enable(clk); | 322 | clk_prepare_enable(pxa->clk_io); |
323 | |||
324 | pxa->clk_core = devm_clk_get(dev, "core"); | ||
325 | if (!IS_ERR(pxa->clk_core)) | ||
326 | clk_prepare_enable(pxa->clk_core); | ||
316 | 327 | ||
317 | /* enable 1/8V DDR capable */ | 328 | /* enable 1/8V DDR capable */ |
318 | host->mmc->caps |= MMC_CAP_1_8V_DDR; | 329 | host->mmc->caps |= MMC_CAP_1_8V_DDR; |
@@ -385,7 +396,9 @@ err_add_host: | |||
385 | pm_runtime_disable(&pdev->dev); | 396 | pm_runtime_disable(&pdev->dev); |
386 | err_of_parse: | 397 | err_of_parse: |
387 | err_cd_req: | 398 | err_cd_req: |
388 | clk_disable_unprepare(clk); | 399 | clk_disable_unprepare(pxa->clk_io); |
400 | if (!IS_ERR(pxa->clk_core)) | ||
401 | clk_disable_unprepare(pxa->clk_core); | ||
389 | err_clk_get: | 402 | err_clk_get: |
390 | err_mbus_win: | 403 | err_mbus_win: |
391 | sdhci_pltfm_free(pdev); | 404 | sdhci_pltfm_free(pdev); |
@@ -396,12 +409,15 @@ static int sdhci_pxav3_remove(struct platform_device *pdev) | |||
396 | { | 409 | { |
397 | struct sdhci_host *host = platform_get_drvdata(pdev); | 410 | struct sdhci_host *host = platform_get_drvdata(pdev); |
398 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 411 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
412 | struct sdhci_pxa *pxa = pltfm_host->priv; | ||
399 | 413 | ||
400 | pm_runtime_get_sync(&pdev->dev); | 414 | pm_runtime_get_sync(&pdev->dev); |
401 | sdhci_remove_host(host, 1); | 415 | sdhci_remove_host(host, 1); |
402 | pm_runtime_disable(&pdev->dev); | 416 | pm_runtime_disable(&pdev->dev); |
403 | 417 | ||
404 | clk_disable_unprepare(pltfm_host->clk); | 418 | clk_disable_unprepare(pxa->clk_io); |
419 | if (!IS_ERR(pxa->clk_core)) | ||
420 | clk_disable_unprepare(pxa->clk_core); | ||
405 | 421 | ||
406 | sdhci_pltfm_free(pdev); | 422 | sdhci_pltfm_free(pdev); |
407 | 423 | ||
@@ -436,20 +452,21 @@ static int sdhci_pxav3_resume(struct device *dev) | |||
436 | } | 452 | } |
437 | #endif | 453 | #endif |
438 | 454 | ||
439 | #ifdef CONFIG_PM_RUNTIME | 455 | #ifdef CONFIG_PM |
440 | static int sdhci_pxav3_runtime_suspend(struct device *dev) | 456 | static int sdhci_pxav3_runtime_suspend(struct device *dev) |
441 | { | 457 | { |
442 | struct sdhci_host *host = dev_get_drvdata(dev); | 458 | struct sdhci_host *host = dev_get_drvdata(dev); |
443 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 459 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
460 | struct sdhci_pxa *pxa = pltfm_host->priv; | ||
444 | unsigned long flags; | 461 | unsigned long flags; |
445 | 462 | ||
446 | if (pltfm_host->clk) { | 463 | spin_lock_irqsave(&host->lock, flags); |
447 | spin_lock_irqsave(&host->lock, flags); | 464 | host->runtime_suspended = true; |
448 | host->runtime_suspended = true; | 465 | spin_unlock_irqrestore(&host->lock, flags); |
449 | spin_unlock_irqrestore(&host->lock, flags); | ||
450 | 466 | ||
451 | clk_disable_unprepare(pltfm_host->clk); | 467 | clk_disable_unprepare(pxa->clk_io); |
452 | } | 468 | if (!IS_ERR(pxa->clk_core)) |
469 | clk_disable_unprepare(pxa->clk_core); | ||
453 | 470 | ||
454 | return 0; | 471 | return 0; |
455 | } | 472 | } |
@@ -458,15 +475,16 @@ static int sdhci_pxav3_runtime_resume(struct device *dev) | |||
458 | { | 475 | { |
459 | struct sdhci_host *host = dev_get_drvdata(dev); | 476 | struct sdhci_host *host = dev_get_drvdata(dev); |
460 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 477 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
478 | struct sdhci_pxa *pxa = pltfm_host->priv; | ||
461 | unsigned long flags; | 479 | unsigned long flags; |
462 | 480 | ||
463 | if (pltfm_host->clk) { | 481 | clk_prepare_enable(pxa->clk_io); |
464 | clk_prepare_enable(pltfm_host->clk); | 482 | if (!IS_ERR(pxa->clk_core)) |
483 | clk_prepare_enable(pxa->clk_core); | ||
465 | 484 | ||
466 | spin_lock_irqsave(&host->lock, flags); | 485 | spin_lock_irqsave(&host->lock, flags); |
467 | host->runtime_suspended = false; | 486 | host->runtime_suspended = false; |
468 | spin_unlock_irqrestore(&host->lock, flags); | 487 | spin_unlock_irqrestore(&host->lock, flags); |
469 | } | ||
470 | 488 | ||
471 | return 0; | 489 | return 0; |
472 | } | 490 | } |