diff mbox

[v4] mmc: sdhci-of-esdhc: modify the sd clock in soc_device_match way

Message ID 20180612045026.20039-1-yinbo.zhu@nxp.com (mailing list archive)
State New, archived
Headers show

Commit Message

Yinbo Zhu June 12, 2018, 4:50 a.m. UTC
From: yinbo.zhu <yinbo.zhu@nxp.com>

Convert to use soc_device_match 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>
---
Change in v4:
		Add a special case in code logic for MMC_TIMING_LEGACY. 

 drivers/mmc/host/sdhci-of-esdhc.c |   73 +++++++++++++++++++++++++++----------
 1 files changed, 53 insertions(+), 20 deletions(-)

Comments

Adrian Hunter June 19, 2018, 11:01 a.m. UTC | #1
On 12/06/18 07:50, Yinbo Zhu wrote:
> From: yinbo.zhu <yinbo.zhu@nxp.com>
> 
> Convert to use soc_device_match 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

maxmum -> maximum

> high speed mode is 46.5MHz.
> 
> Signed-off-by: Yinbo Zhu <yinbo.zhu@nxp.com>

Looks good.  A couple of minor points below.

> ---
> Change in v4:
> 		Add a special case in code logic for MMC_TIMING_LEGACY. 
> 
>  drivers/mmc/host/sdhci-of-esdhc.c |   73 +++++++++++++++++++++++++++----------
>  1 files changed, 53 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
> index 4ffa6b1..a64ba6b 100644
> --- a/drivers/mmc/host/sdhci-of-esdhc.c
> +++ b/drivers/mmc/host/sdhci-of-esdhc.c
> @@ -29,11 +29,52 @@
>  #define VENDOR_V_22	0x12
>  #define VENDOR_V_23	0x13
>  
> +#define MMC_TIMING_NUM (MMC_TIMING_MMC_HS400 + 1)
> +
> +struct esdhc_clk_fixup {
> +	const long sd_dflt_max_clk;
> +	const long max_clk[MMC_TIMING_NUM];

Why 'long' instead of 'unsigned int'?

> +};
> +
> +static const struct esdhc_clk_fixup ls1021a_esdhc_clk = {
> +	.sd_dflt_max_clk = 25000000,
> +	.max_clk[MMC_TIMING_MMC_HS] = 46500000,
> +	.max_clk[MMC_TIMING_SD_HS] = 46500000,
> +};
> +
> +static const struct esdhc_clk_fixup ls1046a_esdhc_clk = {
> +	.sd_dflt_max_clk = 25000000,
> +	.max_clk[MMC_TIMING_UHS_SDR104] = 167000000,
> +	.max_clk[MMC_TIMING_MMC_HS200] = 167000000,
> +};
> +
> +static const struct esdhc_clk_fixup ls1012a_esdhc_clk = {
> +	.sd_dflt_max_clk = 25000000,
> +	.max_clk[MMC_TIMING_UHS_SDR104] = 125000000,
> +	.max_clk[MMC_TIMING_MMC_HS200] = 125000000,
> +};
> +
> +static const struct esdhc_clk_fixup p1010_esdhc_clk = {
> +	.sd_dflt_max_clk = 20000000,
> +	.max_clk[MMC_TIMING_LEGACY] = 20000000,
> +	.max_clk[MMC_TIMING_MMC_HS] = 42000000,
> +	.max_clk[MMC_TIMING_SD_HS] = 40000000,
> +};
> +
> +static const struct soc_device_attribute soc_esdhc_clk_fixup[] = {
> +	{ .family = "QorIQ LS1021A", .data = &ls1021a_esdhc_clk},
> +	{ .family = "QorIQ LS1046A", .data = &ls1046a_esdhc_clk},
> +	{ .family = "QorIQ LS1012A", .data = &ls1012a_esdhc_clk},
> +	{ .family = "QorIQ P1010",   .data = &p1010_esdhc_clk},
> +	{},
> +};
> +
>  struct sdhci_esdhc {
>  	u8 vendor_ver;
>  	u8 spec_ver;
>  	bool quirk_incorrect_hostver;
>  	unsigned int peripheral_clock;
> +	const struct esdhc_clk_fixup *clk_fixup;
>  };
>  
>  /**
> @@ -492,6 +533,7 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
>  	int pre_div = 1;
>  	int div = 1;
>  	ktime_t timeout;
> +	long fixup;
>  	u32 temp;
>  
>  	host->mmc->actual_clock = 0;
> @@ -505,27 +547,14 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
>  	if (esdhc->vendor_ver < VENDOR_V_23)
>  		pre_div = 2;
>  
> -	/*
> -	 * Limit SD clock to 167MHz for ls1046a according to its datasheet
> -	 */
> -	if (clock > 167000000 &&
> -	    of_find_compatible_node(NULL, NULL, "fsl,ls1046a-esdhc"))
> -		clock = 167000000;
> +	if (host->mmc->card && mmc_card_sd(host->mmc->card) &&
> +		host->mmc->ios.timing == MMC_TIMING_LEGACY)
> +		fixup = esdhc->clk_fixup->sd_dflt_max_clk;
> +	else
> +		fixup = esdhc->clk_fixup->max_clk[host->mmc->ios.timing];

What if esdhc->clk_fixup is NULL?

Also need to check if host->mmc->ios.timing >= MMC_TIMING_NUM

>  
> -	/*
> -	 * Limit SD clock to 125MHz for ls1012a according to its datasheet
> -	 */
> -	if (clock > 125000000 &&
> -	    of_find_compatible_node(NULL, NULL, "fsl,ls1012a-esdhc"))
> -		clock = 125000000;
> -
> -	/* Workaround to reduce the clock frequency for p1010 esdhc */
> -	if (of_find_compatible_node(NULL, NULL, "fsl,p1010-esdhc")) {
> -		if (clock > 20000000)
> -			clock -= 5000000;
> -		if (clock > 40000000)
> -			clock -= 5000000;
> -	}
> +	if (fixup && clock > fixup)
> +		clock = fixup;
>  
>  	temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
>  	temp &= ~(ESDHC_CLOCK_SDCLKEN | ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN |
> @@ -783,6 +812,7 @@ static SIMPLE_DEV_PM_OPS(esdhc_of_dev_pm_ops,
>  
>  static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
>  {
> +	const struct soc_device_attribute *matches;
>  	struct sdhci_pltfm_host *pltfm_host;
>  	struct sdhci_esdhc *esdhc;
>  	struct device_node *np;
> @@ -802,6 +832,9 @@ static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
>  	else
>  		esdhc->quirk_incorrect_hostver = false;
>  
> +	matches = soc_device_match(soc_esdhc_clk_fixup);
> +	if (matches)
> +		esdhc->clk_fixup = matches->data;

You could provide an all-zero esdhc_clk_fixup to avoid esdhc->clk_fixup
being NULL, otherwise you should probably check whether it is NULL before
using it.

>  	np = pdev->dev.of_node;
>  	clk = of_clk_get(np, 0);
>  	if (!IS_ERR(clk)) {
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index 4ffa6b1..a64ba6b 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -29,11 +29,52 @@ 
 #define VENDOR_V_22	0x12
 #define VENDOR_V_23	0x13
 
+#define MMC_TIMING_NUM (MMC_TIMING_MMC_HS400 + 1)
+
+struct esdhc_clk_fixup {
+	const long sd_dflt_max_clk;
+	const long max_clk[MMC_TIMING_NUM];
+};
+
+static const struct esdhc_clk_fixup ls1021a_esdhc_clk = {
+	.sd_dflt_max_clk = 25000000,
+	.max_clk[MMC_TIMING_MMC_HS] = 46500000,
+	.max_clk[MMC_TIMING_SD_HS] = 46500000,
+};
+
+static const struct esdhc_clk_fixup ls1046a_esdhc_clk = {
+	.sd_dflt_max_clk = 25000000,
+	.max_clk[MMC_TIMING_UHS_SDR104] = 167000000,
+	.max_clk[MMC_TIMING_MMC_HS200] = 167000000,
+};
+
+static const struct esdhc_clk_fixup ls1012a_esdhc_clk = {
+	.sd_dflt_max_clk = 25000000,
+	.max_clk[MMC_TIMING_UHS_SDR104] = 125000000,
+	.max_clk[MMC_TIMING_MMC_HS200] = 125000000,
+};
+
+static const struct esdhc_clk_fixup p1010_esdhc_clk = {
+	.sd_dflt_max_clk = 20000000,
+	.max_clk[MMC_TIMING_LEGACY] = 20000000,
+	.max_clk[MMC_TIMING_MMC_HS] = 42000000,
+	.max_clk[MMC_TIMING_SD_HS] = 40000000,
+};
+
+static const struct soc_device_attribute soc_esdhc_clk_fixup[] = {
+	{ .family = "QorIQ LS1021A", .data = &ls1021a_esdhc_clk},
+	{ .family = "QorIQ LS1046A", .data = &ls1046a_esdhc_clk},
+	{ .family = "QorIQ LS1012A", .data = &ls1012a_esdhc_clk},
+	{ .family = "QorIQ P1010",   .data = &p1010_esdhc_clk},
+	{},
+};
+
 struct sdhci_esdhc {
 	u8 vendor_ver;
 	u8 spec_ver;
 	bool quirk_incorrect_hostver;
 	unsigned int peripheral_clock;
+	const struct esdhc_clk_fixup *clk_fixup;
 };
 
 /**
@@ -492,6 +533,7 @@  static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
 	int pre_div = 1;
 	int div = 1;
 	ktime_t timeout;
+	long fixup;
 	u32 temp;
 
 	host->mmc->actual_clock = 0;
@@ -505,27 +547,14 @@  static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
 	if (esdhc->vendor_ver < VENDOR_V_23)
 		pre_div = 2;
 
-	/*
-	 * Limit SD clock to 167MHz for ls1046a according to its datasheet
-	 */
-	if (clock > 167000000 &&
-	    of_find_compatible_node(NULL, NULL, "fsl,ls1046a-esdhc"))
-		clock = 167000000;
+	if (host->mmc->card && mmc_card_sd(host->mmc->card) &&
+		host->mmc->ios.timing == MMC_TIMING_LEGACY)
+		fixup = esdhc->clk_fixup->sd_dflt_max_clk;
+	else
+		fixup = esdhc->clk_fixup->max_clk[host->mmc->ios.timing];
 
-	/*
-	 * Limit SD clock to 125MHz for ls1012a according to its datasheet
-	 */
-	if (clock > 125000000 &&
-	    of_find_compatible_node(NULL, NULL, "fsl,ls1012a-esdhc"))
-		clock = 125000000;
-
-	/* Workaround to reduce the clock frequency for p1010 esdhc */
-	if (of_find_compatible_node(NULL, NULL, "fsl,p1010-esdhc")) {
-		if (clock > 20000000)
-			clock -= 5000000;
-		if (clock > 40000000)
-			clock -= 5000000;
-	}
+	if (fixup && clock > fixup)
+		clock = fixup;
 
 	temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
 	temp &= ~(ESDHC_CLOCK_SDCLKEN | ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN |
@@ -783,6 +812,7 @@  static SIMPLE_DEV_PM_OPS(esdhc_of_dev_pm_ops,
 
 static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
 {
+	const struct soc_device_attribute *matches;
 	struct sdhci_pltfm_host *pltfm_host;
 	struct sdhci_esdhc *esdhc;
 	struct device_node *np;
@@ -802,6 +832,9 @@  static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
 	else
 		esdhc->quirk_incorrect_hostver = false;
 
+	matches = soc_device_match(soc_esdhc_clk_fixup);
+	if (matches)
+		esdhc->clk_fixup = matches->data;
 	np = pdev->dev.of_node;
 	clk = of_clk_get(np, 0);
 	if (!IS_ERR(clk)) {