diff mbox series

[v2,2/3] mmc: meson-gx: change clock phase value on SM1 SoCs

Message ID 20201110232211.3717-3-jh80.chung@samsung.com
State Accepted, archived
Commit 0dbb54eb3257c243c7968f967a6b183b1edb56c8
Delegated to: Neil Armstrong
Headers show
Series mmc: meson-gx: fix mmc & sdcard failur on SM1 SoCs | expand

Commit Message

Jaehoon Chung Nov. 10, 2020, 11:22 p.m. UTC
From: Neil Armstrong <narmstrong@baylibre.com>

Amlogic SM1 SoCs doesn't work over 50MHz. When phase sets to 270', it's
working fine over 50MHz on Amlogic SM1 SoCs.
Since Other Amlogic SoCs doens't report an issue, phase value is using
to 180' by default.

To distinguish which value is used adds an u-boot only sm1 compatible.

In future, it needs to find what value is a proper about each SoCs.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
---
 drivers/mmc/meson_gx_mmc.c | 27 +++++++++++++++++++++++----
 drivers/mmc/meson_gx_mmc.h |  5 +++++
 2 files changed, 28 insertions(+), 4 deletions(-)

Comments

Anand Moon Nov. 12, 2020, 8:40 a.m. UTC | #1
Hi Jaehoon,

On Wed, 11 Nov 2020 at 04:52, Jaehoon Chung <jh80.chung@samsung.com> wrote:
>
> From: Neil Armstrong <narmstrong@baylibre.com>
>
> Amlogic SM1 SoCs doesn't work over 50MHz. When phase sets to 270', it's
> working fine over 50MHz on Amlogic SM1 SoCs.
> Since Other Amlogic SoCs doens't report an issue, phase value is using
> to 180' by default.
>
> To distinguish which value is used adds an u-boot only sm1 compatible.
>
> In future, it needs to find what value is a proper about each SoCs.
>
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
> ---

Thanks for this patch series.
I have tested this on Odroid N2 and c4 eMMC module
so Please add my for this series,

Tested-by: Anand Moon <linux.amoon@gmail.com>

>  drivers/mmc/meson_gx_mmc.c | 27 +++++++++++++++++++++++----
>  drivers/mmc/meson_gx_mmc.h |  5 +++++
>  2 files changed, 28 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/mmc/meson_gx_mmc.c b/drivers/mmc/meson_gx_mmc.c
> index eedebb317b5f..a5e9ac5637b9 100644
> --- a/drivers/mmc/meson_gx_mmc.c
> +++ b/drivers/mmc/meson_gx_mmc.c
> @@ -17,6 +17,14 @@
>  #include <linux/log2.h>
>  #include "meson_gx_mmc.h"
>
> +bool meson_gx_mmc_is_compatible(struct udevice *dev,
> +                               enum meson_gx_mmc_compatible family)
> +{
> +       enum meson_gx_mmc_compatible compat = dev_get_driver_data(dev);
> +
> +       return compat == family;
> +}
> +
>  static inline void *get_regbase(const struct mmc *mmc)
>  {
>         struct meson_mmc_platdata *pdata = mmc->priv;
> @@ -42,6 +50,8 @@ static void meson_mmc_config_clock(struct mmc *mmc)
>         if (!mmc->clock)
>                 return;
>
> +       /* TOFIX This should use the proper clock taken from DT */
> +
>         /* 1GHz / CLK_MAX_DIV = 15,9 MHz */
>         if (mmc->clock > 16000000) {
>                 clk = SD_EMMC_CLKSRC_DIV2;
> @@ -52,8 +62,16 @@ static void meson_mmc_config_clock(struct mmc *mmc)
>         }
>         clk_div = DIV_ROUND_UP(clk, mmc->clock);
>
> -       /* 180 phase core clock */
> -       meson_mmc_clk |= CLK_CO_PHASE_180;
> +       /*
> +        * SM1 SoCs doesn't work fine over 50MHz with CLK_CO_PHASE_180
> +        * If CLK_CO_PHASE_270 is used, it's more stable than other.
> +        * Other SoCs use CLK_CO_PHASE_180 by default.
> +        * It needs to find what is a proper value about each SoCs.
> +        */
> +       if (meson_gx_mmc_is_compatible(mmc->dev, MMC_COMPATIBLE_SM1))
> +               meson_mmc_clk |= CLK_CO_PHASE_270;
> +       else
> +               meson_mmc_clk |= CLK_CO_PHASE_180;
>
>         /* 180 phase tx clock */
>         meson_mmc_clk |= CLK_TX_PHASE_000;
> @@ -308,8 +326,9 @@ int meson_mmc_bind(struct udevice *dev)
>  }
>
>  static const struct udevice_id meson_mmc_match[] = {
> -       { .compatible = "amlogic,meson-gx-mmc" },
> -       { .compatible = "amlogic,meson-axg-mmc" },
> +       { .compatible = "amlogic,meson-gx-mmc", .data = MMC_COMPATIBLE_GX },
> +       { .compatible = "amlogic,meson-axg-mmc", .data = MMC_COMPATIBLE_GX },
> +       { .compatible = "amlogic,meson-sm1-mmc", .data = MMC_COMPATIBLE_SM1 },
>         { /* sentinel */ }
>  };
>
> diff --git a/drivers/mmc/meson_gx_mmc.h b/drivers/mmc/meson_gx_mmc.h
> index b4544b55628f..92aec5329f6e 100644
> --- a/drivers/mmc/meson_gx_mmc.h
> +++ b/drivers/mmc/meson_gx_mmc.h
> @@ -9,6 +9,11 @@
>  #include <mmc.h>
>  #include <linux/bitops.h>
>
> +enum meson_gx_mmc_compatible {
> +       MMC_COMPATIBLE_GX,
> +       MMC_COMPATIBLE_SM1,
> +};
> +
>  #define SDIO_PORT_A                    0
>  #define SDIO_PORT_B                    1
>  #define SDIO_PORT_C                    2
> --
> 2.29.0
>
diff mbox series

Patch

diff --git a/drivers/mmc/meson_gx_mmc.c b/drivers/mmc/meson_gx_mmc.c
index eedebb317b5f..a5e9ac5637b9 100644
--- a/drivers/mmc/meson_gx_mmc.c
+++ b/drivers/mmc/meson_gx_mmc.c
@@ -17,6 +17,14 @@ 
 #include <linux/log2.h>
 #include "meson_gx_mmc.h"
 
+bool meson_gx_mmc_is_compatible(struct udevice *dev,
+				enum meson_gx_mmc_compatible family)
+{
+	enum meson_gx_mmc_compatible compat = dev_get_driver_data(dev);
+
+	return compat == family;
+}
+
 static inline void *get_regbase(const struct mmc *mmc)
 {
 	struct meson_mmc_platdata *pdata = mmc->priv;
@@ -42,6 +50,8 @@  static void meson_mmc_config_clock(struct mmc *mmc)
 	if (!mmc->clock)
 		return;
 
+	/* TOFIX This should use the proper clock taken from DT */
+
 	/* 1GHz / CLK_MAX_DIV = 15,9 MHz */
 	if (mmc->clock > 16000000) {
 		clk = SD_EMMC_CLKSRC_DIV2;
@@ -52,8 +62,16 @@  static void meson_mmc_config_clock(struct mmc *mmc)
 	}
 	clk_div = DIV_ROUND_UP(clk, mmc->clock);
 
-	/* 180 phase core clock */
-	meson_mmc_clk |= CLK_CO_PHASE_180;
+	/*
+	 * SM1 SoCs doesn't work fine over 50MHz with CLK_CO_PHASE_180
+	 * If CLK_CO_PHASE_270 is used, it's more stable than other.
+	 * Other SoCs use CLK_CO_PHASE_180 by default.
+	 * It needs to find what is a proper value about each SoCs.
+	 */
+	if (meson_gx_mmc_is_compatible(mmc->dev, MMC_COMPATIBLE_SM1))
+		meson_mmc_clk |= CLK_CO_PHASE_270;
+	else
+		meson_mmc_clk |= CLK_CO_PHASE_180;
 
 	/* 180 phase tx clock */
 	meson_mmc_clk |= CLK_TX_PHASE_000;
@@ -308,8 +326,9 @@  int meson_mmc_bind(struct udevice *dev)
 }
 
 static const struct udevice_id meson_mmc_match[] = {
-	{ .compatible = "amlogic,meson-gx-mmc" },
-	{ .compatible = "amlogic,meson-axg-mmc" },
+	{ .compatible = "amlogic,meson-gx-mmc", .data = MMC_COMPATIBLE_GX },
+	{ .compatible = "amlogic,meson-axg-mmc", .data = MMC_COMPATIBLE_GX },
+	{ .compatible = "amlogic,meson-sm1-mmc", .data = MMC_COMPATIBLE_SM1 },
 	{ /* sentinel */ }
 };
 
diff --git a/drivers/mmc/meson_gx_mmc.h b/drivers/mmc/meson_gx_mmc.h
index b4544b55628f..92aec5329f6e 100644
--- a/drivers/mmc/meson_gx_mmc.h
+++ b/drivers/mmc/meson_gx_mmc.h
@@ -9,6 +9,11 @@ 
 #include <mmc.h>
 #include <linux/bitops.h>
 
+enum meson_gx_mmc_compatible {
+	MMC_COMPATIBLE_GX,
+	MMC_COMPATIBLE_SM1,
+};
+
 #define SDIO_PORT_A			0
 #define SDIO_PORT_B			1
 #define SDIO_PORT_C			2