mmc: meson-gx: change clock phase value on SM1 SoCs
authorNeil Armstrong <narmstrong@baylibre.com>
Tue, 10 Nov 2020 23:22:10 +0000 (08:22 +0900)
committerNeil Armstrong <narmstrong@baylibre.com>
Thu, 12 Nov 2020 13:31:29 +0000 (14:31 +0100)
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>
Tested-by: Anand Moon <linux.amoon@gmail.com>
drivers/mmc/meson_gx_mmc.c
drivers/mmc/meson_gx_mmc.h

index eedebb3..a5e9ac5 100644 (file)
 #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 */ }
 };
 
index b4544b5..92aec53 100644 (file)
@@ -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