diff mbox series

[2/3] mmc: meson-gx: limit max frequency on SM1 SoCs

Message ID 20201106092755.2250773-3-narmstrong@baylibre.com
State Changes Requested, archived
Delegated to: Neil Armstrong
Headers show
Series mmc: meson-gx: fix mmc & scard failure on SM1 SoCs | expand

Commit Message

Neil Armstrong Nov. 6, 2020, 9:27 a.m. UTC
Amlogic SM1 SoCs doesn't handle very well high clocks from the DIV2 input
Thus we limit the max freq to 26MHz on SM1 SoCs until we handle higher
frequencies via the first input from a composite clock.

Here 26MHz corresponds to MMC_HS clock speed.

We also add a u-boot only sm1 compatible to distinguish the controller.

Finally a TOFIX is added to precise the clock management should use
the clock controller instead of local management with fixed clock rates.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
 drivers/mmc/meson_gx_mmc.c | 26 +++++++++++++++++++++++---
 drivers/mmc/meson_gx_mmc.h |  5 +++++
 2 files changed, 28 insertions(+), 3 deletions(-)

Comments

Jaehoon Chung Nov. 6, 2020, 10:32 a.m. UTC | #1
On 11/6/20 6:27 PM, Neil Armstrong wrote:
> Amlogic SM1 SoCs doesn't handle very well high clocks from the DIV2 input
> Thus we limit the max freq to 26MHz on SM1 SoCs until we handle higher
> frequencies via the first input from a composite clock.
> 
> Here 26MHz corresponds to MMC_HS clock speed.
> 
> We also add a u-boot only sm1 compatible to distinguish the controller.

Well, it's workaround for using eMMC.
I didn't check all SM1 SoCs..but odroid-c4 is supported hs200 mode (200MHz) on Kernel side.
It means that bootloader can also support its mode.

I'm checking this problem with odroid-c4 target. If i find how to fix, i will share.

Best Regards,
Jaehoon Chung


> 
> Finally a TOFIX is added to precise the clock management should use
> the clock controller instead of local management with fixed clock rates.
> 
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
>  drivers/mmc/meson_gx_mmc.c | 26 +++++++++++++++++++++++---
>  drivers/mmc/meson_gx_mmc.h |  5 +++++
>  2 files changed, 28 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/mmc/meson_gx_mmc.c b/drivers/mmc/meson_gx_mmc.c
> index 9350edf3fa..2c6b6cd15b 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;
> @@ -265,7 +275,16 @@ static int meson_mmc_probe(struct udevice *dev)
>  	cfg->host_caps = MMC_MODE_8BIT | MMC_MODE_4BIT |
>  			MMC_MODE_HS_52MHz | MMC_MODE_HS;
>  	cfg->f_min = DIV_ROUND_UP(SD_EMMC_CLKSRC_24M, CLK_MAX_DIV);
> -	cfg->f_max = 100000000; /* 100 MHz */;
> +	/*
> +	 * TOFIX SM1 SoCs doesn't handle very well high clocks from the DIV2 input
> +	 * Thus we limit the max freq to 26MHz on SM1 SoCs until we handle higher
> +	 * frequencies via the first input from a composite clock
> +	 * 26MHz corresponds to MMC_HS clock speed
> +	 */
> +	if (meson_gx_mmc_is_compatible(dev, MMC_COMPATIBLE_SM1))
> +		cfg->f_max = 26000000; /* 26 MHz */
> +	else
> +		cfg->f_max = 100000000; /* 100 MHz */
>  	cfg->b_max = 511; /* max 512 - 1 blocks */
>  	cfg->name = dev->name;
>  
> @@ -308,8 +327,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 b4544b5562..92aec5329f 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
>
Neil Armstrong Nov. 6, 2020, 10:35 a.m. UTC | #2
On 06/11/2020 11:32, Jaehoon Chung wrote:
> On 11/6/20 6:27 PM, Neil Armstrong wrote:
>> Amlogic SM1 SoCs doesn't handle very well high clocks from the DIV2 input
>> Thus we limit the max freq to 26MHz on SM1 SoCs until we handle higher
>> frequencies via the first input from a composite clock.
>>
>> Here 26MHz corresponds to MMC_HS clock speed.
>>
>> We also add a u-boot only sm1 compatible to distinguish the controller.
> 
> Well, it's workaround for using eMMC.

It's for the next release, to have a temporary fix.
The goal is to not have such workaround....

> I didn't check all SM1 SoCs..but odroid-c4 is supported hs200 mode (200MHz) on Kernel side.
> It means that bootloader can also support its mode.
> 
> I'm checking this problem with odroid-c4 target. If i find how to fix, i will share.

H200 will need a big work including tuning and proper clock management.

If you manage to got that far, I'll be great !

Neil

> 
> Best Regards,
> Jaehoon Chung
> 
> 
>>
>> Finally a TOFIX is added to precise the clock management should use
>> the clock controller instead of local management with fixed clock rates.
>>
>> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
>> ---
>>  drivers/mmc/meson_gx_mmc.c | 26 +++++++++++++++++++++++---
>>  drivers/mmc/meson_gx_mmc.h |  5 +++++
>>  2 files changed, 28 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/mmc/meson_gx_mmc.c b/drivers/mmc/meson_gx_mmc.c
>> index 9350edf3fa..2c6b6cd15b 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;
>> @@ -265,7 +275,16 @@ static int meson_mmc_probe(struct udevice *dev)
>>  	cfg->host_caps = MMC_MODE_8BIT | MMC_MODE_4BIT |
>>  			MMC_MODE_HS_52MHz | MMC_MODE_HS;
>>  	cfg->f_min = DIV_ROUND_UP(SD_EMMC_CLKSRC_24M, CLK_MAX_DIV);
>> -	cfg->f_max = 100000000; /* 100 MHz */;
>> +	/*
>> +	 * TOFIX SM1 SoCs doesn't handle very well high clocks from the DIV2 input
>> +	 * Thus we limit the max freq to 26MHz on SM1 SoCs until we handle higher
>> +	 * frequencies via the first input from a composite clock
>> +	 * 26MHz corresponds to MMC_HS clock speed
>> +	 */
>> +	if (meson_gx_mmc_is_compatible(dev, MMC_COMPATIBLE_SM1))
>> +		cfg->f_max = 26000000; /* 26 MHz */
>> +	else
>> +		cfg->f_max = 100000000; /* 100 MHz */
>>  	cfg->b_max = 511; /* max 512 - 1 blocks */
>>  	cfg->name = dev->name;
>>  
>> @@ -308,8 +327,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 b4544b5562..92aec5329f 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
>>
>
Mark Kettenis Nov. 6, 2020, 11:53 a.m. UTC | #3
> From: Neil Armstrong <narmstrong@baylibre.com>
> Date: Fri, 6 Nov 2020 11:35:30 +0100
> 
> On 06/11/2020 11:32, Jaehoon Chung wrote:
> > On 11/6/20 6:27 PM, Neil Armstrong wrote:
> >> Amlogic SM1 SoCs doesn't handle very well high clocks from the DIV2 input
> >> Thus we limit the max freq to 26MHz on SM1 SoCs until we handle higher
> >> frequencies via the first input from a composite clock.
> >>
> >> Here 26MHz corresponds to MMC_HS clock speed.
> >>
> >> We also add a u-boot only sm1 compatible to distinguish the controller.
> > 
> > Well, it's workaround for using eMMC.
> 
> It's for the next release, to have a temporary fix.
> The goal is to not have such workaround....
> 
> > I didn't check all SM1 SoCs..but odroid-c4 is supported hs200 mode (200MHz) on Kernel side.
> > It means that bootloader can also support its mode.
> > 
> > I'm checking this problem with odroid-c4 target. If i find how to fix, i will share.
> 
> H200 will need a big work including tuning and proper clock management.

I worry a bit that this would make things more fragile.  I have some
trouble getting HS200 to work properly on the Odroid-N2 in OpenBSD
(might be a clock management issue).  And the fact that on both the
Odroid-N2 and Odroid-C4 the eMMC isn't soldered on means that it has
to work reliably on a wider variety of eMMC modules.

I believe Linux automatically switches back to a lowe-speed mode if
HS200 doesn't work isn't it?  Should U-Boot do something similar?

> If you manage to got that far, I'll be great !
> 
> Neil
> 
> > 
> > Best Regards,
> > Jaehoon Chung
> > 
> > 
> >>
> >> Finally a TOFIX is added to precise the clock management should use
> >> the clock controller instead of local management with fixed clock rates.
> >>
> >> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> >> ---
> >>  drivers/mmc/meson_gx_mmc.c | 26 +++++++++++++++++++++++---
> >>  drivers/mmc/meson_gx_mmc.h |  5 +++++
> >>  2 files changed, 28 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/drivers/mmc/meson_gx_mmc.c b/drivers/mmc/meson_gx_mmc.c
> >> index 9350edf3fa..2c6b6cd15b 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;
> >> @@ -265,7 +275,16 @@ static int meson_mmc_probe(struct udevice *dev)
> >>  	cfg->host_caps = MMC_MODE_8BIT | MMC_MODE_4BIT |
> >>  			MMC_MODE_HS_52MHz | MMC_MODE_HS;
> >>  	cfg->f_min = DIV_ROUND_UP(SD_EMMC_CLKSRC_24M, CLK_MAX_DIV);
> >> -	cfg->f_max = 100000000; /* 100 MHz */;
> >> +	/*
> >> +	 * TOFIX SM1 SoCs doesn't handle very well high clocks from the DIV2 input
> >> +	 * Thus we limit the max freq to 26MHz on SM1 SoCs until we handle higher
> >> +	 * frequencies via the first input from a composite clock
> >> +	 * 26MHz corresponds to MMC_HS clock speed
> >> +	 */
> >> +	if (meson_gx_mmc_is_compatible(dev, MMC_COMPATIBLE_SM1))
> >> +		cfg->f_max = 26000000; /* 26 MHz */
> >> +	else
> >> +		cfg->f_max = 100000000; /* 100 MHz */
> >>  	cfg->b_max = 511; /* max 512 - 1 blocks */
> >>  	cfg->name = dev->name;
> >>  
> >> @@ -308,8 +327,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 b4544b5562..92aec5329f 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
> >>
> > 
> 
>
Jaehoon Chung Nov. 8, 2020, 11:12 p.m. UTC | #4
Hi Mark,

On 11/6/20 8:53 PM, Mark Kettenis wrote:
>> From: Neil Armstrong <narmstrong@baylibre.com>
>> Date: Fri, 6 Nov 2020 11:35:30 +0100
>>
>> On 06/11/2020 11:32, Jaehoon Chung wrote:
>>> On 11/6/20 6:27 PM, Neil Armstrong wrote:
>>>> Amlogic SM1 SoCs doesn't handle very well high clocks from the DIV2 input
>>>> Thus we limit the max freq to 26MHz on SM1 SoCs until we handle higher
>>>> frequencies via the first input from a composite clock.
>>>>
>>>> Here 26MHz corresponds to MMC_HS clock speed.
>>>>
>>>> We also add a u-boot only sm1 compatible to distinguish the controller.
>>>
>>> Well, it's workaround for using eMMC.
>>
>> It's for the next release, to have a temporary fix.
>> The goal is to not have such workaround....
>>
>>> I didn't check all SM1 SoCs..but odroid-c4 is supported hs200 mode (200MHz) on Kernel side.
>>> It means that bootloader can also support its mode.
>>>
>>> I'm checking this problem with odroid-c4 target. If i find how to fix, i will share.
>>
>> H200 will need a big work including tuning and proper clock management.
> 
> I worry a bit that this would make things more fragile.  I have some
> trouble getting HS200 to work properly on the Odroid-N2 in OpenBSD
> (might be a clock management issue).  And the fact that on both the
> Odroid-N2 and Odroid-C4 the eMMC isn't soldered on means that it has
> to work reliably on a wider variety of eMMC modules.
> 
> I believe Linux automatically switches back to a lowe-speed mode if
> HS200 doesn't work isn't it?  Should U-Boot do something similar?

As i know, It's provided on U-boot side, likes Linux.
If HS200 or other modes are failed, then it's trying to set lower mode.
But I don't know why SM1 SoC doesn't set to it. 
It seems that doesn't recovery to previous clock or some configs.

Best Regards,
Jaehoon Chung

> 
>> If you manage to got that far, I'll be great !
>>
>> Neil
>>
>>>
>>> Best Regards,
>>> Jaehoon Chung
>>>
>>>
>>>>
>>>> Finally a TOFIX is added to precise the clock management should use
>>>> the clock controller instead of local management with fixed clock rates.
>>>>
>>>> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
>>>> ---
>>>>  drivers/mmc/meson_gx_mmc.c | 26 +++++++++++++++++++++++---
>>>>  drivers/mmc/meson_gx_mmc.h |  5 +++++
>>>>  2 files changed, 28 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/drivers/mmc/meson_gx_mmc.c b/drivers/mmc/meson_gx_mmc.c
>>>> index 9350edf3fa..2c6b6cd15b 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;
>>>> @@ -265,7 +275,16 @@ static int meson_mmc_probe(struct udevice *dev)
>>>>  	cfg->host_caps = MMC_MODE_8BIT | MMC_MODE_4BIT |
>>>>  			MMC_MODE_HS_52MHz | MMC_MODE_HS;
>>>>  	cfg->f_min = DIV_ROUND_UP(SD_EMMC_CLKSRC_24M, CLK_MAX_DIV);
>>>> -	cfg->f_max = 100000000; /* 100 MHz */;
>>>> +	/*
>>>> +	 * TOFIX SM1 SoCs doesn't handle very well high clocks from the DIV2 input
>>>> +	 * Thus we limit the max freq to 26MHz on SM1 SoCs until we handle higher
>>>> +	 * frequencies via the first input from a composite clock
>>>> +	 * 26MHz corresponds to MMC_HS clock speed
>>>> +	 */
>>>> +	if (meson_gx_mmc_is_compatible(dev, MMC_COMPATIBLE_SM1))
>>>> +		cfg->f_max = 26000000; /* 26 MHz */
>>>> +	else
>>>> +		cfg->f_max = 100000000; /* 100 MHz */
>>>>  	cfg->b_max = 511; /* max 512 - 1 blocks */
>>>>  	cfg->name = dev->name;
>>>>  
>>>> @@ -308,8 +327,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 b4544b5562..92aec5329f 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
>>>>
>>>
>>
>>
>
diff mbox series

Patch

diff --git a/drivers/mmc/meson_gx_mmc.c b/drivers/mmc/meson_gx_mmc.c
index 9350edf3fa..2c6b6cd15b 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;
@@ -265,7 +275,16 @@  static int meson_mmc_probe(struct udevice *dev)
 	cfg->host_caps = MMC_MODE_8BIT | MMC_MODE_4BIT |
 			MMC_MODE_HS_52MHz | MMC_MODE_HS;
 	cfg->f_min = DIV_ROUND_UP(SD_EMMC_CLKSRC_24M, CLK_MAX_DIV);
-	cfg->f_max = 100000000; /* 100 MHz */;
+	/*
+	 * TOFIX SM1 SoCs doesn't handle very well high clocks from the DIV2 input
+	 * Thus we limit the max freq to 26MHz on SM1 SoCs until we handle higher
+	 * frequencies via the first input from a composite clock
+	 * 26MHz corresponds to MMC_HS clock speed
+	 */
+	if (meson_gx_mmc_is_compatible(dev, MMC_COMPATIBLE_SM1))
+		cfg->f_max = 26000000; /* 26 MHz */
+	else
+		cfg->f_max = 100000000; /* 100 MHz */
 	cfg->b_max = 511; /* max 512 - 1 blocks */
 	cfg->name = dev->name;
 
@@ -308,8 +327,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 b4544b5562..92aec5329f 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