1 --- a/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt
2 +++ b/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt
3 @@ -13,6 +13,7 @@ Required properties:
4 * "allwinner,sun5i-a13-mmc"
5 * "allwinner,sun7i-a20-mmc"
6 * "allwinner,sun9i-a80-mmc"
7 + * "allwinner,sun50i-a64-emmc"
8 * "allwinner,sun50i-a64-mmc"
9 - reg : mmc controller base registers
10 - clocks : a list with 4 phandle + clock specifier pairs
11 --- a/drivers/mmc/host/sunxi-mmc.c
12 +++ b/drivers/mmc/host/sunxi-mmc.c
14 * (C) Copyright 2013-2014 O2S GmbH <www.o2s.ch>
15 * (C) Copyright 2013-2014 David Lanzend�rfer <david.lanzendoerfer@o2s.ch>
16 * (C) Copyright 2013-2014 Hans de Goede <hdegoede@redhat.com>
17 + * (C) Copyright 2017 Sootech SA
19 * This program is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU General Public License as
22 (SDXC_SOFT_RESET | SDXC_FIFO_RESET | SDXC_DMA_RESET)
24 /* clock control bits */
25 +#define SDXC_MASK_DATA0 BIT(31)
26 #define SDXC_CARD_CLOCK_ON BIT(16)
27 #define SDXC_LOW_POWER_ON BIT(17)
29 @@ -253,6 +255,11 @@ struct sunxi_mmc_cfg {
31 /* does the IP block support autocalibration? */
34 + /* Does DATA0 needs to be masked while the clock is updated */
37 + bool needs_new_timings;
40 struct sunxi_mmc_host {
41 @@ -482,7 +489,7 @@ static void sunxi_mmc_dump_errinfo(struc
42 cmd->opcode == SD_IO_RW_DIRECT))
45 - dev_err(mmc_dev(host->mmc),
46 + dev_dbg(mmc_dev(host->mmc),
47 "smc %d err, cmd %d,%s%s%s%s%s%s%s%s%s%s !!\n",
48 host->mmc->index, cmd->opcode,
49 data ? (data->flags & MMC_DATA_WRITE ? " WR" : " RD") : "",
50 @@ -654,11 +661,16 @@ static int sunxi_mmc_oclk_onoff(struct s
51 unsigned long expire = jiffies + msecs_to_jiffies(750);
54 + dev_dbg(mmc_dev(host->mmc), "%sabling the clock\n",
55 + oclk_en ? "en" : "dis");
57 rval = mmc_readl(host, REG_CLKCR);
58 - rval &= ~(SDXC_CARD_CLOCK_ON | SDXC_LOW_POWER_ON);
59 + rval &= ~(SDXC_CARD_CLOCK_ON | SDXC_LOW_POWER_ON | SDXC_MASK_DATA0);
62 rval |= SDXC_CARD_CLOCK_ON;
63 + if (host->cfg->mask_data0)
64 + rval |= SDXC_MASK_DATA0;
66 mmc_writel(host, REG_CLKCR, rval);
68 @@ -678,46 +690,29 @@ static int sunxi_mmc_oclk_onoff(struct s
72 + if (host->cfg->mask_data0) {
73 + rval = mmc_readl(host, REG_CLKCR);
74 + mmc_writel(host, REG_CLKCR, rval & ~SDXC_MASK_DATA0);
80 static int sunxi_mmc_calibrate(struct sunxi_mmc_host *host, int reg_off)
82 - u32 reg = readl(host->reg_base + reg_off);
84 - unsigned long timeout;
86 if (!host->cfg->can_calibrate)
89 - reg &= ~(SDXC_CAL_DL_MASK << SDXC_CAL_DL_SW_SHIFT);
90 - reg &= ~SDXC_CAL_DL_SW_EN;
92 - writel(reg | SDXC_CAL_START, host->reg_base + reg_off);
94 - dev_dbg(mmc_dev(host->mmc), "calibration started\n");
96 - timeout = jiffies + HZ * SDXC_CAL_TIMEOUT;
98 - while (!((reg = readl(host->reg_base + reg_off)) & SDXC_CAL_DONE)) {
99 - if (time_before(jiffies, timeout))
102 - reg &= ~SDXC_CAL_START;
103 - writel(reg, host->reg_base + reg_off);
109 - delay = (reg >> SDXC_CAL_DL_SHIFT) & SDXC_CAL_DL_MASK;
111 - reg &= ~SDXC_CAL_START;
112 - reg |= (delay << SDXC_CAL_DL_SW_SHIFT) | SDXC_CAL_DL_SW_EN;
114 - writel(reg, host->reg_base + reg_off);
116 - dev_dbg(mmc_dev(host->mmc), "calibration ended, reg is 0x%x\n", reg);
119 + * This is not clear how the calibration is supposed to work
120 + * yet. The best rate have been obtained by simply setting the
121 + * delay to 0, as Allwinner does in its BSP.
123 + * The only mode that doesn't have such a delay is HS400, that
124 + * is in itself a TODO.
126 + writel(SDXC_CAL_DL_SW_EN, host->reg_base + reg_off);
130 @@ -745,6 +740,7 @@ static int sunxi_mmc_clk_set_phase(struc
131 index = SDXC_CLK_50M_DDR;
134 + dev_dbg(mmc_dev(host->mmc), "Invalid clock... returning\n");
138 @@ -757,10 +753,21 @@ static int sunxi_mmc_clk_set_phase(struc
139 static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host,
142 + struct mmc_host *mmc = host->mmc;
144 u32 rval, clock = ios->clock;
147 + ret = sunxi_mmc_oclk_onoff(host, 0);
151 + /* Our clock is gated now */
152 + mmc->actual_clock = 0;
157 /* 8 bit DDR requires a higher module clock */
158 if (ios->timing == MMC_TIMING_MMC_DDR52 &&
159 ios->bus_width == MMC_BUS_WIDTH_8)
160 @@ -768,25 +775,21 @@ static int sunxi_mmc_clk_set_rate(struct
162 rate = clk_round_rate(host->clk_mmc, clock);
164 - dev_err(mmc_dev(host->mmc), "error rounding clk to %d: %ld\n",
165 + dev_err(mmc_dev(mmc), "error rounding clk to %d: %ld\n",
169 - dev_dbg(mmc_dev(host->mmc), "setting clk to %d, rounded %ld\n",
170 + dev_dbg(mmc_dev(mmc), "setting clk to %d, rounded %ld\n",
173 /* setting clock rate */
174 ret = clk_set_rate(host->clk_mmc, rate);
176 - dev_err(mmc_dev(host->mmc), "error setting clk to %ld: %d\n",
177 + dev_err(mmc_dev(mmc), "error setting clk to %ld: %d\n",
182 - ret = sunxi_mmc_oclk_onoff(host, 0);
186 /* clear internal divider */
187 rval = mmc_readl(host, REG_CLKCR);
189 @@ -798,6 +801,13 @@ static int sunxi_mmc_clk_set_rate(struct
191 mmc_writel(host, REG_CLKCR, rval);
193 + if (host->cfg->needs_new_timings) {
194 + /* Don't touch the delay bits */
195 + rval = mmc_readl(host, REG_SD_NTSR);
196 + rval |= SDXC_2X_TIMING_MODE;
197 + mmc_writel(host, REG_SD_NTSR, rval);
200 ret = sunxi_mmc_clk_set_phase(host, ios, rate);
203 @@ -806,9 +816,22 @@ static int sunxi_mmc_clk_set_rate(struct
207 - /* TODO: enable calibrate on sdc2 SDXC_REG_DS_DL_REG of A64 */
211 + * In HS400 we'll also need to calibrate the data strobe
212 + * signal. This should only happen on the MMC2 controller (at
213 + * least on the A64).
216 + ret = sunxi_mmc_oclk_onoff(host, 1);
220 - return sunxi_mmc_oclk_onoff(host, 1);
221 + /* And we just enabled our clock back */
222 + mmc->actual_clock = rate;
227 static void sunxi_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
228 @@ -822,10 +845,13 @@ static void sunxi_mmc_set_ios(struct mmc
232 - host->ferror = mmc_regulator_set_ocr(mmc, mmc->supply.vmmc,
236 + if (!IS_ERR(mmc->supply.vmmc)) {
237 + host->ferror = mmc_regulator_set_ocr(mmc,
244 if (!IS_ERR(mmc->supply.vqmmc)) {
245 host->ferror = regulator_enable(mmc->supply.vqmmc);
246 @@ -847,7 +873,9 @@ static void sunxi_mmc_set_ios(struct mmc
248 dev_dbg(mmc_dev(mmc), "power off!\n");
249 sunxi_mmc_reset_host(host);
250 - mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
251 + if (!IS_ERR(mmc->supply.vmmc))
252 + mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
254 if (!IS_ERR(mmc->supply.vqmmc) && host->vqmmc_enabled)
255 regulator_disable(mmc->supply.vqmmc);
256 host->vqmmc_enabled = false;
257 @@ -877,7 +905,7 @@ static void sunxi_mmc_set_ios(struct mmc
258 mmc_writel(host, REG_GCTRL, rval);
261 - if (ios->clock && ios->power_mode) {
262 + if (ios->power_mode) {
263 host->ferror = sunxi_mmc_clk_set_rate(host, ios);
264 /* Android code had a usleep_range(50000, 55000); here */
266 @@ -1084,6 +1112,14 @@ static const struct sunxi_mmc_cfg sun50i
267 .idma_des_size_bits = 16,
269 .can_calibrate = true,
270 + .mask_data0 = true,
271 + .needs_new_timings = true,
274 +static const struct sunxi_mmc_cfg sun50i_a64_emmc_cfg = {
275 + .idma_des_size_bits = 13,
276 + .clk_delays = NULL,
277 + .can_calibrate = true,
280 static const struct of_device_id sunxi_mmc_of_match[] = {
281 @@ -1092,6 +1128,7 @@ static const struct of_device_id sunxi_m
282 { .compatible = "allwinner,sun7i-a20-mmc", .data = &sun7i_a20_cfg },
283 { .compatible = "allwinner,sun9i-a80-mmc", .data = &sun9i_a80_cfg },
284 { .compatible = "allwinner,sun50i-a64-mmc", .data = &sun50i_a64_cfg },
285 + { .compatible = "allwinner,sun50i-a64-emmc", .data = &sun50i_a64_emmc_cfg },
288 MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match);