[linux-sunxi] Re: [PATCH] mmc: sunxi: Fix clk-delay settings

Hans de Goede hdegoede at redhat.com
Thu Sep 24 02:52:36 PDT 2015


Hi,

On 23-09-15 23:50, Ulf Hansson wrote:
> On 23 September 2015 at 22:06, Hans de Goede <hdegoede at redhat.com> wrote:
>> In recent allwinner kernel sources the mmc clk-delay settings have been
>> slightly tweaked, and for sun9i they are completely different then what
>> we are using.
>>
>> This commit brings us in sync with what allwinner does, fixing problems
>> accessing sdcards on some A33 devices (and likely others).
>>
>> For pre sun9i hardware this makes the following changes:
>> -At 400Khz change the sample delay from 7 to 0 (introduced in A31 sdk)
>> -At 50 Mhz change the sample delay from 5 to 4 (introduced in A23 sdk)
>>
>> This also drops the clk-delay calculation for clocks > 50 MHz, we do
>> not need this as we've: mmc->f_max = 50000000, and the delays in the
>> old code were not correct (at 100 MHz the delay must be a multiple of 60,
>> at 200 MHz a multiple of 120).
>>
>> Signed-off-by: Hans de Goede <hdegoede at redhat.com>
>
> I assume you want me to take this as a fix?

With that you mean take it into 4.3-rcX ? Yes please.

> If so, can we point to what commit it fixes?

Erm, the clk-sample settings this adjusts have been there more or less
unchanged since the driver was introduced, and were taken directly from
the allwinner A10 kernel source / SDK.

This just syncs them with improvements done to the settings in later
allwinner SDK-s, improvements which I found when I could not get multiple
cards to work on certain A33 based tablets.

Regards,

Hans

>> ---
>>   drivers/mmc/host/sunxi-mmc.c | 53 ++++++++++++++++++++++++++++++++------------
>>   1 file changed, 39 insertions(+), 14 deletions(-)
>>
>> diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
>> index e6226cd..83de82b 100644
>> --- a/drivers/mmc/host/sunxi-mmc.c
>> +++ b/drivers/mmc/host/sunxi-mmc.c
>> @@ -210,6 +210,16 @@
>>   #define SDXC_IDMAC_DES0_CES    BIT(30) /* card error summary */
>>   #define SDXC_IDMAC_DES0_OWN    BIT(31) /* 1-idma owns it, 0-host owns it */
>>
>> +#define SDXC_CLK_400K          0
>> +#define SDXC_CLK_25M           1
>> +#define SDXC_CLK_50M           2
>> +#define SDXC_CLK_50M_DDR       3
>> +
>> +struct sunxi_mmc_clk_delay {
>> +       u32 output;
>> +       u32 sample;
>> +};
>> +
>>   struct sunxi_idma_des {
>>          u32     config;
>>          u32     buf_size;
>> @@ -229,6 +239,7 @@ struct sunxi_mmc_host {
>>          struct clk      *clk_mmc;
>>          struct clk      *clk_sample;
>>          struct clk      *clk_output;
>> +       const struct sunxi_mmc_clk_delay *clk_delays;
>>
>>          /* irq */
>>          spinlock_t      lock;
>> @@ -654,25 +665,19 @@ static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host,
>>
>>          /* determine delays */
>>          if (rate <= 400000) {
>> -               oclk_dly = 180;
>> -               sclk_dly = 42;
>> +               oclk_dly = host->clk_delays[SDXC_CLK_400K].output;
>> +               sclk_dly = host->clk_delays[SDXC_CLK_400K].sample;
>>          } else if (rate <= 25000000) {
>> -               oclk_dly = 180;
>> -               sclk_dly = 75;
>> +               oclk_dly = host->clk_delays[SDXC_CLK_25M].output;
>> +               sclk_dly = host->clk_delays[SDXC_CLK_25M].sample;
>>          } else if (rate <= 50000000) {
>>                  if (ios->timing == MMC_TIMING_UHS_DDR50) {
>> -                       oclk_dly = 60;
>> -                       sclk_dly = 120;
>> +                       oclk_dly = host->clk_delays[SDXC_CLK_50M_DDR].output;
>> +                       sclk_dly = host->clk_delays[SDXC_CLK_50M_DDR].sample;
>>                  } else {
>> -                       oclk_dly = 90;
>> -                       sclk_dly = 150;
>> +                       oclk_dly = host->clk_delays[SDXC_CLK_50M].output;
>> +                       sclk_dly = host->clk_delays[SDXC_CLK_50M].sample;
>>                  }
>> -       } else if (rate <= 100000000) {
>> -               oclk_dly = 6;
>> -               sclk_dly = 24;
>> -       } else if (rate <= 200000000) {
>> -               oclk_dly = 3;
>> -               sclk_dly = 12;
>>          } else {
>>                  return -EINVAL;
>>          }
>> @@ -878,6 +883,7 @@ static int sunxi_mmc_card_busy(struct mmc_host *mmc)
>>   static const struct of_device_id sunxi_mmc_of_match[] = {
>>          { .compatible = "allwinner,sun4i-a10-mmc", },
>>          { .compatible = "allwinner,sun5i-a13-mmc", },
>> +       { .compatible = "allwinner,sun9i-a80-mmc", },
>>          { /* sentinel */ }
>>   };
>>   MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match);
>> @@ -892,6 +898,20 @@ static struct mmc_host_ops sunxi_mmc_ops = {
>>          .card_busy       = sunxi_mmc_card_busy,
>>   };
>>
>> +static const struct sunxi_mmc_clk_delay sunxi_mmc_clk_delays[] = {
>> +       [SDXC_CLK_400K]         = { .output = 180, .sample = 180 },
>> +       [SDXC_CLK_25M]          = { .output = 180, .sample =  75 },
>> +       [SDXC_CLK_50M]          = { .output =  90, .sample = 120 },
>> +       [SDXC_CLK_50M_DDR]      = { .output =  60, .sample = 120 },
>> +};
>> +
>> +static const struct sunxi_mmc_clk_delay sun9i_mmc_clk_delays[] = {
>> +       [SDXC_CLK_400K]         = { .output = 180, .sample = 180 },
>> +       [SDXC_CLK_25M]          = { .output = 180, .sample =  75 },
>> +       [SDXC_CLK_50M]          = { .output = 150, .sample = 120 },
>> +       [SDXC_CLK_50M_DDR]      = { .output =  90, .sample = 120 },
>> +};
>> +
>>   static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
>>                                        struct platform_device *pdev)
>>   {
>> @@ -903,6 +923,11 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
>>          else
>>                  host->idma_des_size_bits = 16;
>>
>> +       if (of_device_is_compatible(np, "allwinner,sun9i-a80-mmc"))
>> +               host->clk_delays = sun9i_mmc_clk_delays;
>> +       else
>> +               host->clk_delays = sunxi_mmc_clk_delays;
>> +
>>          ret = mmc_regulator_get_supply(host->mmc);
>>          if (ret) {
>>                  if (ret != -EPROBE_DEFER)
>> --
>> 2.5.0
>>



More information about the linux-arm-kernel mailing list