[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