diff options
author | yinbo.zhu <yinbo.zhu@nxp.com> | 2018-06-25 04:46:24 -0400 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@linaro.org> | 2018-07-16 05:21:45 -0400 |
commit | 67fdfbdf0115b39b4e9b9d96d240202fa3049b12 (patch) | |
tree | b7e43ba46ef9089757cd61d80f18eb9e2230748c /drivers/mmc | |
parent | 3f2c7d5d158d7df430b5763674be9e0b834dfd6f (diff) |
mmc: sdhci-of-esdhc: modify the sd clock in of_match_node way
Convert to use of_match_node method to fix up eSDHC clock for
ls1046a/ls1012a/p1010. Also add eSDHC clock fixup for ls1021a
according to its datasheet. The maxmum speed for ls1021a eSDHC
high speed mode is 46.5MHz.
Signed-off-by: Yinbo Zhu <yinbo.zhu@nxp.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/host/sdhci-of-esdhc.c | 85 |
1 files changed, 57 insertions, 28 deletions
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index 4ffa6b173a21..c9685c6e4395 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c | |||
@@ -29,11 +29,56 @@ | |||
29 | #define VENDOR_V_22 0x12 | 29 | #define VENDOR_V_22 0x12 |
30 | #define VENDOR_V_23 0x13 | 30 | #define VENDOR_V_23 0x13 |
31 | 31 | ||
32 | #define MMC_TIMING_NUM (MMC_TIMING_MMC_HS400 + 1) | ||
33 | |||
34 | struct esdhc_clk_fixup { | ||
35 | const unsigned int sd_dflt_max_clk; | ||
36 | const unsigned int max_clk[MMC_TIMING_NUM]; | ||
37 | }; | ||
38 | |||
39 | static const struct esdhc_clk_fixup ls1021a_esdhc_clk = { | ||
40 | .sd_dflt_max_clk = 25000000, | ||
41 | .max_clk[MMC_TIMING_MMC_HS] = 46500000, | ||
42 | .max_clk[MMC_TIMING_SD_HS] = 46500000, | ||
43 | }; | ||
44 | |||
45 | static const struct esdhc_clk_fixup ls1046a_esdhc_clk = { | ||
46 | .sd_dflt_max_clk = 25000000, | ||
47 | .max_clk[MMC_TIMING_UHS_SDR104] = 167000000, | ||
48 | .max_clk[MMC_TIMING_MMC_HS200] = 167000000, | ||
49 | }; | ||
50 | |||
51 | static const struct esdhc_clk_fixup ls1012a_esdhc_clk = { | ||
52 | .sd_dflt_max_clk = 25000000, | ||
53 | .max_clk[MMC_TIMING_UHS_SDR104] = 125000000, | ||
54 | .max_clk[MMC_TIMING_MMC_HS200] = 125000000, | ||
55 | }; | ||
56 | |||
57 | static const struct esdhc_clk_fixup p1010_esdhc_clk = { | ||
58 | .sd_dflt_max_clk = 20000000, | ||
59 | .max_clk[MMC_TIMING_LEGACY] = 20000000, | ||
60 | .max_clk[MMC_TIMING_MMC_HS] = 42000000, | ||
61 | .max_clk[MMC_TIMING_SD_HS] = 40000000, | ||
62 | }; | ||
63 | |||
64 | static const struct of_device_id sdhci_esdhc_of_match[] = { | ||
65 | { .compatible = "fsl,ls1021a-esdhc", .data = &ls1021a_esdhc_clk}, | ||
66 | { .compatible = "fsl,ls1046a-esdhc", .data = &ls1046a_esdhc_clk}, | ||
67 | { .compatible = "fsl,ls1012a-esdhc", .data = &ls1012a_esdhc_clk}, | ||
68 | { .compatible = "fsl,p1010-esdhc", .data = &p1010_esdhc_clk}, | ||
69 | { .compatible = "fsl,mpc8379-esdhc" }, | ||
70 | { .compatible = "fsl,mpc8536-esdhc" }, | ||
71 | { .compatible = "fsl,esdhc" }, | ||
72 | { } | ||
73 | }; | ||
74 | MODULE_DEVICE_TABLE(of, sdhci_esdhc_of_match); | ||
75 | |||
32 | struct sdhci_esdhc { | 76 | struct sdhci_esdhc { |
33 | u8 vendor_ver; | 77 | u8 vendor_ver; |
34 | u8 spec_ver; | 78 | u8 spec_ver; |
35 | bool quirk_incorrect_hostver; | 79 | bool quirk_incorrect_hostver; |
36 | unsigned int peripheral_clock; | 80 | unsigned int peripheral_clock; |
81 | const struct esdhc_clk_fixup *clk_fixup; | ||
37 | }; | 82 | }; |
38 | 83 | ||
39 | /** | 84 | /** |
@@ -492,6 +537,7 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock) | |||
492 | int pre_div = 1; | 537 | int pre_div = 1; |
493 | int div = 1; | 538 | int div = 1; |
494 | ktime_t timeout; | 539 | ktime_t timeout; |
540 | long fixup = 0; | ||
495 | u32 temp; | 541 | u32 temp; |
496 | 542 | ||
497 | host->mmc->actual_clock = 0; | 543 | host->mmc->actual_clock = 0; |
@@ -505,27 +551,14 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock) | |||
505 | if (esdhc->vendor_ver < VENDOR_V_23) | 551 | if (esdhc->vendor_ver < VENDOR_V_23) |
506 | pre_div = 2; | 552 | pre_div = 2; |
507 | 553 | ||
508 | /* | 554 | if (host->mmc->card && mmc_card_sd(host->mmc->card) && |
509 | * Limit SD clock to 167MHz for ls1046a according to its datasheet | 555 | esdhc->clk_fixup && host->mmc->ios.timing == MMC_TIMING_LEGACY) |
510 | */ | 556 | fixup = esdhc->clk_fixup->sd_dflt_max_clk; |
511 | if (clock > 167000000 && | 557 | else if (esdhc->clk_fixup) |
512 | of_find_compatible_node(NULL, NULL, "fsl,ls1046a-esdhc")) | 558 | fixup = esdhc->clk_fixup->max_clk[host->mmc->ios.timing]; |
513 | clock = 167000000; | ||
514 | 559 | ||
515 | /* | 560 | if (fixup && clock > fixup) |
516 | * Limit SD clock to 125MHz for ls1012a according to its datasheet | 561 | clock = fixup; |
517 | */ | ||
518 | if (clock > 125000000 && | ||
519 | of_find_compatible_node(NULL, NULL, "fsl,ls1012a-esdhc")) | ||
520 | clock = 125000000; | ||
521 | |||
522 | /* Workaround to reduce the clock frequency for p1010 esdhc */ | ||
523 | if (of_find_compatible_node(NULL, NULL, "fsl,p1010-esdhc")) { | ||
524 | if (clock > 20000000) | ||
525 | clock -= 5000000; | ||
526 | if (clock > 40000000) | ||
527 | clock -= 5000000; | ||
528 | } | ||
529 | 562 | ||
530 | temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); | 563 | temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); |
531 | temp &= ~(ESDHC_CLOCK_SDCLKEN | ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | | 564 | temp &= ~(ESDHC_CLOCK_SDCLKEN | ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | |
@@ -783,6 +816,7 @@ static struct soc_device_attribute soc_incorrect_hostver[] = { | |||
783 | 816 | ||
784 | static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host) | 817 | static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host) |
785 | { | 818 | { |
819 | const struct of_device_id *match; | ||
786 | struct sdhci_pltfm_host *pltfm_host; | 820 | struct sdhci_pltfm_host *pltfm_host; |
787 | struct sdhci_esdhc *esdhc; | 821 | struct sdhci_esdhc *esdhc; |
788 | struct device_node *np; | 822 | struct device_node *np; |
@@ -802,6 +836,9 @@ static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host) | |||
802 | else | 836 | else |
803 | esdhc->quirk_incorrect_hostver = false; | 837 | esdhc->quirk_incorrect_hostver = false; |
804 | 838 | ||
839 | match = of_match_node(sdhci_esdhc_of_match, pdev->dev.of_node); | ||
840 | if (match) | ||
841 | esdhc->clk_fixup = match->data; | ||
805 | np = pdev->dev.of_node; | 842 | np = pdev->dev.of_node; |
806 | clk = of_clk_get(np, 0); | 843 | clk = of_clk_get(np, 0); |
807 | if (!IS_ERR(clk)) { | 844 | if (!IS_ERR(clk)) { |
@@ -901,14 +938,6 @@ static int sdhci_esdhc_probe(struct platform_device *pdev) | |||
901 | return ret; | 938 | return ret; |
902 | } | 939 | } |
903 | 940 | ||
904 | static const struct of_device_id sdhci_esdhc_of_match[] = { | ||
905 | { .compatible = "fsl,mpc8379-esdhc" }, | ||
906 | { .compatible = "fsl,mpc8536-esdhc" }, | ||
907 | { .compatible = "fsl,esdhc" }, | ||
908 | { } | ||
909 | }; | ||
910 | MODULE_DEVICE_TABLE(of, sdhci_esdhc_of_match); | ||
911 | |||
912 | static struct platform_driver sdhci_esdhc_driver = { | 941 | static struct platform_driver sdhci_esdhc_driver = { |
913 | .driver = { | 942 | .driver = { |
914 | .name = "sdhci-esdhc", | 943 | .name = "sdhci-esdhc", |