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

Ulf Hansson ulf.hansson at linaro.org
Wed Sep 23 14:50:24 PDT 2015


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? If so, can we point to
what commit it fixes?

Kind regards
Uffe

> ---
>  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