summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLee Jones <lee.jones@linaro.org>2016-09-08 05:11:36 -0400
committerUlf Hansson <ulf.hansson@linaro.org>2016-09-12 04:31:43 -0400
commit3ae50f4512ce831e8b63eb54ad969417ff30ada7 (patch)
tree492f9aeec0c8c91649d949cfee41dd52dc99ab6e
parent981b178964d03f6f8e6cca01568c17d1dbafdf0e (diff)
mmc: sdhci-st: Handle interconnect clock
Some ST platforms contain interconnect (ICN) clocks which must be handed correctly in order to obtain full functionality of a given IP. In this case, if the ICN clocks are not handled properly by the ST SDHCI driver MMC will break and the following output can be observed: [ 13.916949] mmc0: Timeout waiting for hardware interrupt. [ 13.922349] sdhci: =========== REGISTER DUMP (mmc0)=========== [ 13.928175] sdhci: Sys addr: 0x00000000 | Version: 0x00001002 [ 13.933999] sdhci: Blk size: 0x00007040 | Blk cnt: 0x00000001 [ 13.939825] sdhci: Argument: 0x00fffff0 | Trn mode: 0x00000013 [ 13.945650] sdhci: Present: 0x1fff0206 | Host ctl: 0x00000011 [ 13.951475] sdhci: Power: 0x0000000f | Blk gap: 0x00000080 [ 13.957300] sdhci: Wake-up: 0x00000000 | Clock: 0x00003f07 [ 13.963126] sdhci: Timeout: 0x00000004 | Int stat: 0x00000000 [ 13.968952] sdhci: Int enab: 0x02ff008b | Sig enab: 0x02ff008b [ 13.974777] sdhci: AC12 err: 0x00000000 | Slot int: 0x00000000 [ 13.980602] sdhci: Caps: 0x21ed3281 | Caps_1: 0x00000000 [ 13.986428] sdhci: Cmd: 0x0000063a | Max curr: 0x00000000 [ 13.992252] sdhci: Host ctl2: 0x00000000 [ 13.996166] sdhci: ADMA Err: 0x00000000 | ADMA Ptr: 0x7c048200 [ 14.001990] sdhci: =========================================== [ 14.009802] mmc0: Got data interrupt 0x02000000 even though no data operation was in progress. A decent point was raised about minimising the use of a local variable that we 'could' do without. I've chosen consistency over the possibility of reducing the local variable count by 1. Thinking that it's more important for the code to be grouped and authoured in a similar manner/style for greater maintainability/readability. Cc: stable@vger.kernel.org Tested-by: Peter Griffin <peter.griffin@linaro.org> Signed-off-by: Lee Jones <lee.jones@linaro.org> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r--drivers/mmc/host/sdhci-st.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/drivers/mmc/host/sdhci-st.c b/drivers/mmc/host/sdhci-st.c
index c95ba83366a0..ed92ce729dde 100644
--- a/drivers/mmc/host/sdhci-st.c
+++ b/drivers/mmc/host/sdhci-st.c
@@ -28,6 +28,7 @@
28 28
29struct st_mmc_platform_data { 29struct st_mmc_platform_data {
30 struct reset_control *rstc; 30 struct reset_control *rstc;
31 struct clk *icnclk;
31 void __iomem *top_ioaddr; 32 void __iomem *top_ioaddr;
32}; 33};
33 34
@@ -353,7 +354,7 @@ static int sdhci_st_probe(struct platform_device *pdev)
353 struct sdhci_host *host; 354 struct sdhci_host *host;
354 struct st_mmc_platform_data *pdata; 355 struct st_mmc_platform_data *pdata;
355 struct sdhci_pltfm_host *pltfm_host; 356 struct sdhci_pltfm_host *pltfm_host;
356 struct clk *clk; 357 struct clk *clk, *icnclk;
357 int ret = 0; 358 int ret = 0;
358 u16 host_version; 359 u16 host_version;
359 struct resource *res; 360 struct resource *res;
@@ -365,6 +366,11 @@ static int sdhci_st_probe(struct platform_device *pdev)
365 return PTR_ERR(clk); 366 return PTR_ERR(clk);
366 } 367 }
367 368
369 /* ICN clock isn't compulsory, but use it if it's provided. */
370 icnclk = devm_clk_get(&pdev->dev, "icn");
371 if (IS_ERR(icnclk))
372 icnclk = NULL;
373
368 rstc = devm_reset_control_get(&pdev->dev, NULL); 374 rstc = devm_reset_control_get(&pdev->dev, NULL);
369 if (IS_ERR(rstc)) 375 if (IS_ERR(rstc))
370 rstc = NULL; 376 rstc = NULL;
@@ -389,6 +395,7 @@ static int sdhci_st_probe(struct platform_device *pdev)
389 } 395 }
390 396
391 clk_prepare_enable(clk); 397 clk_prepare_enable(clk);
398 clk_prepare_enable(icnclk);
392 399
393 /* Configure the FlashSS Top registers for setting eMMC TX/RX delay */ 400 /* Configure the FlashSS Top registers for setting eMMC TX/RX delay */
394 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, 401 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
@@ -400,6 +407,7 @@ static int sdhci_st_probe(struct platform_device *pdev)
400 } 407 }
401 408
402 pltfm_host->clk = clk; 409 pltfm_host->clk = clk;
410 pdata->icnclk = icnclk;
403 411
404 /* Configure the Arasan HC inside the flashSS */ 412 /* Configure the Arasan HC inside the flashSS */
405 st_mmcss_cconfig(np, host); 413 st_mmcss_cconfig(np, host);
@@ -422,6 +430,7 @@ static int sdhci_st_probe(struct platform_device *pdev)
422 return 0; 430 return 0;
423 431
424err_out: 432err_out:
433 clk_disable_unprepare(icnclk);
425 clk_disable_unprepare(clk); 434 clk_disable_unprepare(clk);
426err_of: 435err_of:
427 sdhci_pltfm_free(pdev); 436 sdhci_pltfm_free(pdev);
@@ -442,6 +451,8 @@ static int sdhci_st_remove(struct platform_device *pdev)
442 451
443 ret = sdhci_pltfm_unregister(pdev); 452 ret = sdhci_pltfm_unregister(pdev);
444 453
454 clk_disable_unprepare(pdata->icnclk);
455
445 if (rstc) 456 if (rstc)
446 reset_control_assert(rstc); 457 reset_control_assert(rstc);
447 458
@@ -462,6 +473,7 @@ static int sdhci_st_suspend(struct device *dev)
462 if (pdata->rstc) 473 if (pdata->rstc)
463 reset_control_assert(pdata->rstc); 474 reset_control_assert(pdata->rstc);
464 475
476 clk_disable_unprepare(pdata->icnclk);
465 clk_disable_unprepare(pltfm_host->clk); 477 clk_disable_unprepare(pltfm_host->clk);
466out: 478out:
467 return ret; 479 return ret;
@@ -475,6 +487,7 @@ static int sdhci_st_resume(struct device *dev)
475 struct device_node *np = dev->of_node; 487 struct device_node *np = dev->of_node;
476 488
477 clk_prepare_enable(pltfm_host->clk); 489 clk_prepare_enable(pltfm_host->clk);
490 clk_prepare_enable(pdata->icnclk);
478 491
479 if (pdata->rstc) 492 if (pdata->rstc)
480 reset_control_deassert(pdata->rstc); 493 reset_control_deassert(pdata->rstc);