mmc: sunxi: Fix clock frequency change sequence
authorMaxime Ripard <maxime.ripard@free-electrons.com>
Fri, 27 Jan 2017 21:38:33 +0000 (22:38 +0100)
committerUlf Hansson <ulf.hansson@linaro.org>
Mon, 13 Feb 2017 12:20:48 +0000 (13:20 +0100)
The SD specification documents that the clock frequency should only be
changed once gated (Section 3.2.3 - SD Clock Frequency Change Sequence).

The current code first modifies the parent clock, gates it and then
modifies the internal divider. This means that since the parent clock rate
might be changed, the bus clock might be changed as well before it is
gated, which breaks the specification.

Move the gating before the parent rate modification.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Tested-by: Florian Vaussard <florian.vaussard@heig-vd.ch>
Acked-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
drivers/mmc/host/sunxi-mmc.c

index b1d1303389a71eb17f6def0e9941b1687061f589..ab4324e6eb7409e45acec6b91b437ab58bdf9439 100644 (file)
@@ -761,6 +761,10 @@ static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host,
        u32 rval, clock = ios->clock;
        int ret;
 
+       ret = sunxi_mmc_oclk_onoff(host, 0);
+       if (ret)
+               return ret;
+
        /* 8 bit DDR requires a higher module clock */
        if (ios->timing == MMC_TIMING_MMC_DDR52 &&
            ios->bus_width == MMC_BUS_WIDTH_8)
@@ -783,10 +787,6 @@ static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host,
                return ret;
        }
 
-       ret = sunxi_mmc_oclk_onoff(host, 0);
-       if (ret)
-               return ret;
-
        /* clear internal divider */
        rval = mmc_readl(host, REG_CLKCR);
        rval &= ~0xff;