• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Sunxi SD/MMC host driver
3 *
4 * Copyright (C) 2015 AllWinnertech Ltd.
5 * Author: lixiang <lixiang@allwinnertech>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
12 * kind, whether express or implied; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 */
16 
17 
18 #ifdef CONFIG_ARCH_SUN50IW1P1
19 
20 #include <linux/clk.h>
21 #include <sunxi-clk.h>
22 
23 #include <linux/gpio.h>
24 #include <linux/platform_device.h>
25 #include <linux/spinlock.h>
26 #include <linux/scatterlist.h>
27 #include <linux/dma-mapping.h>
28 #include <linux/slab.h>
29 #include <linux/reset.h>
30 
31 #include <linux/of_address.h>
32 #include <linux/of_gpio.h>
33 #include <linux/of_platform.h>
34 
35 #include <linux/mmc/host.h>
36 #include <linux/mmc/sd.h>
37 #include <linux/mmc/sdio.h>
38 #include <linux/mmc/mmc.h>
39 #include <linux/mmc/core.h>
40 #include <linux/mmc/card.h>
41 #include <linux/mmc/slot-gpio.h>
42 
43 #include "sunxi-mmc.h"
44 #include "sunxi-mmc-sun50iw1p1-1.h"
45 
46 /*reg*/
47 /*SMHC eMMC4.5 DDR Start Bit Detection Control Register */
48 /*SMHC CRC Status Detect Control Register */
49 /*SMHC Card Threshold Control Register */
50 /*SMHC Drive Delay Control Register */
51 /*SMHC Sample Delay Control Register */
52 /*SMHC Data Strobe Delay Control Register */
53 /*SMHC NewTiming Set Register */
54 #define SDXC_REG_EDSD		(0x010C)
55 #define SDXC_REG_CSDC		(0x0054)
56 #define SDXC_REG_THLD		(0x0100)
57 #define SDXC_REG_DRV_DL		(0x0140)
58 #define SDXC_REG_SAMP_DL	(0x0144)
59 #define SDXC_REG_DS_DL		(0x0148)
60 #define SDXC_REG_SD_NTSR	(0x005C)
61 
62 /*bit*/
63 #define SDXC_HS400_MD_EN				(1U<<31)
64 #define SDXC_CARD_WR_THLD_ENB		(1U<<2)
65 #define SDXC_CARD_RD_THLD_ENB		(1U)
66 
67 #define SDXC_DAT_DRV_PH_SEL			(1U<<17)
68 #define SDXC_CMD_DRV_PH_SEL			(1U<<16)
69 #define SDXC_SAMP_DL_SW_EN			(1u<<7)
70 #define SDXC_DS_DL_SW_EN			(1u<<7)
71 
72 #define	SDXC_2X_TIMING_MODE			(1U<<31)
73 
74 /*mask*/
75 #define SDXC_CRC_DET_PARA_MASK		(0xf)
76 #define SDXC_CARD_RD_THLD_MASK		(0x0FFF0000)
77 #define SDXC_TX_TL_MASK				(0xff)
78 #define SDXC_RX_TL_MASK				(0x00FF0000)
79 
80 #define SDXC_SAMP_DL_SW_MASK		(0x0000003F)
81 #define SDXC_DS_DL_SW_MASK			(0x0000003F)
82 
83 #define SDXC_SAM_TIMING_PH_MASK		(0x00000030)
84 
85 /*value*/
86 #define SDXC_CRC_DET_PARA_HS400		(6)
87 #define SDXC_CRC_DET_PARA_OTHER		(3)
88 #define SDXC_FIFO_DETH					(1024>>2)
89 
90 /*size*/
91 #define SDXC_CARD_RD_THLD_SIZE		(0x00000FFF)
92 
93 /*shit*/
94 #define SDXC_CARD_RD_THLD_SIZE_SHIFT		(16)
95 
96 #define SDXC_SAM_TIMING_PH_SHIFT			(4)
97 
98 enum sunxi_mmc_clk_mode {
99 	mmc_clk_400k = 0,
100 	mmc_clk_26M,
101 	mmc_clk_52M,
102 	mmc_clk_52M_DDR4,
103 	mmc_clk_52M_DDR8,
104 	mmc_clk_104M,
105 	mmc_clk_208M,
106 	mmc_clk_104M_DDR,
107 	mmc_clk_208M_DDR,
108 	mmc_clk_mod_num,
109 };
110 
111 struct sunxi_mmc_clk_dly {
112 	enum sunxi_mmc_clk_mode cmod;
113 	char *mod_str;
114 	u32 cmd_drv_ph;
115 	u32 dat_drv_ph;
116 	u32 sam_dly;
117 	u32 ds_dly;
118 	u32 sam_ph;
119 };
120 
121 	/*sample delay and output deley setting */
122 static struct sunxi_mmc_clk_dly mmc_clk_dly[mmc_clk_mod_num] = {
123 	[mmc_clk_400k] = {
124 			  .cmod = mmc_clk_400k,
125 			  .mod_str = "sunxi-dly-400k",
126 			  .cmd_drv_ph = 1,
127 			  .dat_drv_ph = 0,
128 			  .sam_dly = 0,
129 			  .ds_dly = 0,
130 			  .sam_ph = 0,
131 			  },
132 	[mmc_clk_26M] = {
133 			 .cmod = mmc_clk_26M,
134 			 .mod_str = "sunxi-dly-26M",
135 			 .cmd_drv_ph = 1,
136 			 .dat_drv_ph = 0,
137 			 .sam_dly = 0,
138 			 .ds_dly = 0,
139 			 .sam_ph = 0,
140 			 },
141 	[mmc_clk_52M] = {
142 			 .cmod = mmc_clk_52M,
143 			 .mod_str = "sunxi-dly-52M",
144 			 .cmd_drv_ph = 1,
145 			 .dat_drv_ph = 0,
146 			 .sam_dly = 0,
147 			 .ds_dly = 0,
148 			 .sam_ph = 0,
149 			 },
150 	[mmc_clk_52M_DDR4] = {
151 			      .cmod = mmc_clk_52M_DDR4,
152 			      .mod_str = "sunxi-dly-52M-ddr4",
153 			      .cmd_drv_ph = 1,
154 			      .dat_drv_ph = 0,
155 			      .sam_dly = 0,
156 			      .ds_dly = 0,
157 			      .sam_ph = 0,
158 			      },
159 	[mmc_clk_52M_DDR8] = {
160 			      .cmod = mmc_clk_52M_DDR8,
161 			      .mod_str = "sunxi-dly-52M-ddr8",
162 			      .cmd_drv_ph = 1,
163 			      .dat_drv_ph = 0,
164 			      .sam_dly = 0,
165 			      .ds_dly = 0,
166 			      .sam_ph = 0,
167 			      },
168 	[mmc_clk_104M] = {
169 			  .cmod = mmc_clk_104M,
170 			  .mod_str = "sunxi-dly-104M",
171 			  .cmd_drv_ph = 1,
172 			  .dat_drv_ph = 0,
173 			  .sam_dly = 0,
174 			  .ds_dly = 0,
175 			  .sam_ph = 0,
176 
177 			  },
178 	[mmc_clk_208M] = {
179 			  .cmod = mmc_clk_208M,
180 			  .mod_str = "sunxi-dly-208M",
181 			  .cmd_drv_ph = 1,
182 			  .dat_drv_ph = 0,
183 			  .sam_dly = 0,
184 			  .ds_dly = 0,
185 			  .sam_ph = 0,
186 			  },
187 	[mmc_clk_104M_DDR] = {
188 			      .cmod = mmc_clk_104M_DDR,
189 			      .mod_str = "sunxi-dly-104M-ddr",
190 			      .cmd_drv_ph = 1,
191 			      .dat_drv_ph = 0,
192 			      .sam_dly = 0,
193 			      .ds_dly = 0,
194 			      .sam_ph = 0,
195 			      },
196 	[mmc_clk_208M_DDR] = {
197 			      .cmod = mmc_clk_208M_DDR,
198 			      .mod_str = "sunxi-dly-208M-ddr",
199 			      .cmd_drv_ph = 1,
200 			      .dat_drv_ph = 0,
201 			      .sam_dly = 0,
202 			      .ds_dly = 0,
203 			      .sam_ph = 0,
204 			      },
205 };
206 
207 struct sunxi_mmc_spec_regs {
208 	u32 drv_dl;		/*REG_DRV_DL */
209 	u32 samp_dl;		/*REG_SAMP_DL */
210 	u32 ds_dl;		/*REG_DS_DL */
211 	u32 sd_ntsr;		/*REG_SD_NTSR */
212 };
213 
214 static struct sunxi_mmc_spec_regs bak_spec_regs;
215 
sunxi_mmc_set_clk_dly(struct sunxi_mmc_host * host,int clk,int bus_width,int timing)216 static void sunxi_mmc_set_clk_dly(struct sunxi_mmc_host *host, int clk,
217 				  int bus_width, int timing)
218 {
219 	struct mmc_host *mhost = host->mmc;
220 	u32 rval = 0;
221 	enum sunxi_mmc_clk_mode cmod = mmc_clk_400k;
222 	u32 in_clk_dly[5] = { 0 };
223 	int ret = 0;
224 	struct device_node *np = NULL;
225 
226 	if (!mhost->parent || !mhost->parent->of_node) {
227 		SM_ERR(mmc_dev(host->mmc),
228 			"no dts to parse clk dly,use default\n");
229 		return;
230 	}
231 
232 	np = mhost->parent->of_node;
233 
234 	if (clk <= 400 * 1000) {
235 		cmod = mmc_clk_400k;
236 	} else if (clk <= 26 * 1000 * 1000) {
237 		cmod = mmc_clk_26M;
238 	} else if (clk <= 52 * 1000 * 1000) {
239 		if ((bus_width == MMC_BUS_WIDTH_4)
240 		    && sunxi_mmc_ddr_timing(timing)) {
241 			cmod = mmc_clk_52M_DDR4;
242 		} else if ((bus_width == MMC_BUS_WIDTH_8)
243 			   && (timing == MMC_TIMING_MMC_DDR52)) {
244 			cmod = mmc_clk_52M_DDR8;
245 		} else {
246 			cmod = mmc_clk_52M;
247 		}
248 	} else if (clk <= 104 * 1000 * 1000) {
249 		if ((bus_width == MMC_BUS_WIDTH_8)
250 		    && (timing == MMC_TIMING_MMC_HS400)) {
251 			cmod = mmc_clk_104M_DDR;
252 		} else {
253 			cmod = mmc_clk_104M;
254 		}
255 	} else if (clk <= 208 * 1000 * 1000) {
256 		if ((bus_width == MMC_BUS_WIDTH_8)
257 		    && (timing == MMC_TIMING_MMC_HS400)) {
258 			cmod = mmc_clk_208M_DDR;
259 		} else {
260 			cmod = mmc_clk_208M;
261 		}
262 	} else {
263 		SM_ERR(mmc_dev(mhost), "clk %d is out of range\n", clk);
264 		return;
265 	}
266 
267 	ret = of_property_read_u32_array(np, mmc_clk_dly[cmod].mod_str,
268 					 in_clk_dly, ARRAY_SIZE(in_clk_dly));
269 	if (ret) {
270 		SM_DBG(mmc_dev(host->mmc), "failded to get %s used default\n",
271 			mmc_clk_dly[cmod].mod_str);
272 	} else {
273 		mmc_clk_dly[cmod].cmd_drv_ph = in_clk_dly[0];
274 		mmc_clk_dly[cmod].dat_drv_ph = in_clk_dly[1];
275 		/*mmc_clk_dly[cmod].sam_dly             = in_clk_dly[2]; */
276 		/*mmc_clk_dly[cmod].ds_dly              = in_clk_dly[3]; */
277 		mmc_clk_dly[cmod].sam_ph = in_clk_dly[4];
278 		SM_DBG(mmc_dev(host->mmc), "Get %s clk dly ok\n",
279 			mmc_clk_dly[cmod].mod_str);
280 
281 	}
282 
283 	SM_DBG(mmc_dev(host->mmc), "Try set %s clk dly       ok\n",
284 		mmc_clk_dly[cmod].mod_str);
285 	SM_DBG(mmc_dev(host->mmc), "cmd_drv_ph	%d\n",
286 		mmc_clk_dly[cmod].cmd_drv_ph);
287 	SM_DBG(mmc_dev(host->mmc), "dat_drv_ph	%d\n",
288 		mmc_clk_dly[cmod].dat_drv_ph);
289 	SM_DBG(mmc_dev(host->mmc), "sam_ph	%d\n",
290 		mmc_clk_dly[cmod].sam_ph);
291 
292 	rval = mmc_readl(host, REG_DRV_DL);
293 	if (mmc_clk_dly[cmod].cmd_drv_ph)
294 		rval |= SDXC_CMD_DRV_PH_SEL;	/*180 phase */
295 	else
296 		rval &= ~SDXC_CMD_DRV_PH_SEL;	/*90 phase */
297 
298 
299 	if (mmc_clk_dly[cmod].dat_drv_ph)
300 		rval |= SDXC_DAT_DRV_PH_SEL;	/*180 phase */
301 	 else
302 		rval &= ~SDXC_DAT_DRV_PH_SEL;	/*90 phase */
303 
304 	sunxi_r_op(host, mmc_writel(host, REG_DRV_DL, rval));
305 
306 /*
307 *	rval = mmc_readl(host,REG_SAMP_DL);
308 *	rval &= ~SDXC_SAMP_DL_SW_MASK;
309 *	rval |= mmc_clk_dly[cmod].sam_dly & SDXC_SAMP_DL_SW_MASK;
310 *	rval |= SDXC_SAMP_DL_SW_EN;
311 *	mmc_writel(host,REG_SAMP_DL,rval);
312 *
313 *	rval = mmc_readl(host,REG_DS_DL);
314 *	rval &= ~SDXC_DS_DL_SW_MASK;
315 *	rval |= mmc_clk_dly[cmod].ds_dly & SDXC_DS_DL_SW_MASK;
316 *	rval |= SDXC_DS_DL_SW_EN;
317 *	mmc_writel(host,REG_DS_DL,rval);
318 */
319 	rval = mmc_readl(host, REG_SD_NTSR);
320 	rval &= ~SDXC_SAM_TIMING_PH_MASK;
321 	rval |=
322 	    (mmc_clk_dly[cmod].
323 	     sam_ph << SDXC_SAM_TIMING_PH_SHIFT) & SDXC_SAM_TIMING_PH_MASK;
324 	mmc_writel(host, REG_SD_NTSR, rval);
325 
326 	SM_DBG(mmc_dev(host->mmc), " REG_DRV_DL    %08x\n",
327 		mmc_readl(host, REG_DRV_DL));
328 	SM_DBG(mmc_dev(host->mmc), " REG_SAMP_DL  %08x\n",
329 		mmc_readl(host, REG_SAMP_DL));
330 	SM_DBG(mmc_dev(host->mmc), " REG_DS_DL      %08x\n",
331 		mmc_readl(host, REG_DS_DL));
332 
333 }
334 
__sunxi_mmc_do_oclk_onoff(struct sunxi_mmc_host * host,u32 oclk_en,u32 pwr_save,u32 ignore_dat0)335 static int __sunxi_mmc_do_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en,
336 				     u32 pwr_save, u32 ignore_dat0)
337 {
338 	unsigned long expire = jiffies + msecs_to_jiffies(250);
339 	u32 rval;
340 
341 	rval = mmc_readl(host, REG_CLKCR);
342 	rval &= ~(SDXC_CARD_CLOCK_ON | SDXC_LOW_POWER_ON | SDXC_MASK_DATA0);
343 
344 	if (oclk_en)
345 		rval |= SDXC_CARD_CLOCK_ON;
346 	if (pwr_save)
347 		rval |= SDXC_LOW_POWER_ON;
348 	if (ignore_dat0)
349 		rval |= SDXC_MASK_DATA0;
350 
351 	mmc_writel(host, REG_CLKCR, rval);
352 
353 	SM_DBG(mmc_dev(host->mmc), "%s REG_CLKCR:%x\n", __func__,
354 		mmc_readl(host, REG_CLKCR));
355 
356 	rval = SDXC_START | SDXC_UPCLK_ONLY | SDXC_WAIT_PRE_OVER;
357 	mmc_writel(host, REG_CMDR, rval);
358 
359 	do {
360 		rval = mmc_readl(host, REG_CMDR);
361 	} while (time_before(jiffies, expire) && (rval & SDXC_START));
362 
363 	/* clear irq status bits set by the command */
364 	/*? */
365 	mmc_writel(host, REG_RINTR,
366 			mmc_readl(host, REG_RINTR) & ~SDXC_SDIO_INTERRUPT);
367 
368 	if (rval & SDXC_START) {
369 		SM_ERR(mmc_dev(host->mmc), "fatal err update clk timeout\n");
370 		return -EIO;
371 	}
372 
373 	/*only use mask data0 when update clk,clear it when not update clk */
374 	if (ignore_dat0)
375 		mmc_writel(host, REG_CLKCR,
376 			   mmc_readl(host, REG_CLKCR) & ~SDXC_MASK_DATA0);
377 
378 	return 0;
379 }
380 
sunxi_mmc_oclk_onoff(struct sunxi_mmc_host * host,u32 oclk_en)381 static int sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en)
382 {
383 	struct device_node *np = NULL;
384 	struct mmc_host *mmc = host->mmc;
385 	int pwr_save = 0;
386 	int len = 0;
387 
388 	if (!mmc->parent || !mmc->parent->of_node) {
389 		SM_ERR(mmc_dev(host->mmc),
390 			"no dts to parse power save mode\n");
391 		return -EIO;
392 	}
393 
394 	np = mmc->parent->of_node;
395 	if (of_find_property(np, "sunxi-power-save-mode", &len))
396 		pwr_save = 1;
397 	return __sunxi_mmc_do_oclk_onoff(host, oclk_en, pwr_save, 1);
398 }
399 
sunxi_mmc_oclk_onoff_sdmmc1(struct sunxi_mmc_host * host,u32 oclk_en)400 int sunxi_mmc_oclk_onoff_sdmmc1(struct sunxi_mmc_host *host, u32 oclk_en)
401 {
402 	return sunxi_mmc_oclk_onoff(host, oclk_en);
403 }
404 
sunxi_mmc_2xmod_onoff(struct sunxi_mmc_host * host,u32 newmode_en)405 static void sunxi_mmc_2xmod_onoff(struct sunxi_mmc_host *host, u32 newmode_en)
406 {
407 	u32 rval = mmc_readl(host, REG_SD_NTSR);
408 
409 	if (newmode_en)
410 		rval |= SDXC_2X_TIMING_MODE;
411 	else
412 		rval &= ~SDXC_2X_TIMING_MODE;
413 
414 	mmc_writel(host, REG_SD_NTSR, rval);
415 
416 	SM_DBG(mmc_dev(host->mmc), "REG_SD_NTSR: 0x%08x ,val %x\n",
417 		mmc_readl(host, REG_SD_NTSR), rval);
418 }
419 
sunxi_mmc_clk_set_rate_for_sdmmc1(struct sunxi_mmc_host * host,struct mmc_ios * ios)420 int sunxi_mmc_clk_set_rate_for_sdmmc1(struct sunxi_mmc_host *host,
421 				      struct mmc_ios *ios)
422 {
423 	u32 mod_clk = 0;
424 	u32 src_clk = 0;
425 	u32 rval = 0;
426 	s32 err = 0;
427 	u32 rate = 0;
428 	char *sclk_name = NULL;
429 	struct clk *mclk = host->clk_mmc;
430 	struct clk *sclk = NULL;
431 	struct device *dev = mmc_dev(host->mmc);
432 	int div = 0;
433 
434 	if (ios->clock == 0) {
435 		__sunxi_mmc_do_oclk_onoff(host, 0, 0, 1);
436 		return 0;
437 	}
438 
439 	if (sunxi_mmc_ddr_timing(ios->timing)) {
440 		mod_clk = ios->clock << 2;
441 		div = 1;
442 	} else {
443 		mod_clk = ios->clock << 1;
444 		div = 0;
445 	}
446 
447 	if (ios->clock <= 400000) {
448 		sclk = clk_get(dev, "osc24m");
449 		sclk_name = "osc24m";
450 	} else {
451 		sclk = clk_get(dev, "pll_periph");
452 		sclk_name = "pll_periph";
453 	}
454 
455 	if (IS_ERR(sclk)) {
456 		SM_ERR(mmc_dev(host->mmc), "Error to get source clock %s\n",
457 			sclk_name);
458 		return -1;
459 	}
460 
461 	sunxi_mmc_oclk_onoff(host, 0);
462 
463 	err = clk_set_parent(mclk, sclk);
464 	if (err) {
465 		SM_ERR(mmc_dev(host->mmc), "set parent failed\n");
466 		clk_put(sclk);
467 		return -1;
468 	}
469 
470 	rate = clk_round_rate(mclk, mod_clk);
471 
472 	SM_DBG(mmc_dev(host->mmc), "get round rate %d\n", rate);
473 
474 	clk_disable_unprepare(host->clk_mmc);
475 
476 	err = clk_set_rate(mclk, rate);
477 	if (err) {
478 		SM_ERR(mmc_dev(host->mmc), "set mclk rate error, rate %dHz\n",
479 			rate);
480 		clk_put(sclk);
481 		return -1;
482 	}
483 
484 	rval = clk_prepare_enable(host->clk_mmc);
485 	if (rval) {
486 		SM_ERR(mmc_dev(host->mmc), "Enable mmc clk err %d\n", rval);
487 		return -1;
488 	}
489 
490 	src_clk = clk_get_rate(sclk);
491 	clk_put(sclk);
492 
493 	SM_DBG(mmc_dev(host->mmc), "set round clock %d, soure clk is %d\n",
494 		rate, src_clk);
495 
496 #ifdef MMC_FPGA
497 	if (sunxi_mmc_ddr_timing(ios->timing)) {
498 		/* clear internal divider */
499 		rval = mmc_readl(host, REG_CLKCR);
500 		rval &= ~0xff;
501 		rval |= 1;
502 	} else {
503 		/* support internal divide clock under fpga environment  */
504 		rval = mmc_readl(host, REG_CLKCR);
505 		rval &= ~0xff;
506 		rval |= 24000000 / mod_clk / 2;	/* =24M/400K/2=0x1E*/
507 	}
508 	mmc_writel(host, REG_CLKCR, rval);
509 	SM_INFO(mmc_dev(host->mmc), "FPGA REG_CLKCR: 0x%08x\n",
510 		mmc_readl(host, REG_CLKCR));
511 #else
512 	/* clear internal divider */
513 	rval = mmc_readl(host, REG_CLKCR);
514 	rval &= ~0xff;
515 	rval |= div;
516 	mmc_writel(host, REG_CLKCR, rval);
517 #endif
518 
519 	/*sunxi_of_parse_clk_dly(host);*/
520 	sunxi_mmc_2xmod_onoff(host, 1);
521 
522 	if (sunxi_mmc_ddr_timing(ios->timing))
523 		ios->clock = rate >> 2;
524 	else
525 		ios->clock = rate >> 1;
526 
527 
528 	sunxi_mmc_set_clk_dly(host, ios->clock, ios->bus_width, ios->timing);
529 
530 	return sunxi_mmc_oclk_onoff(host, 1);
531 }
532 
sunxi_mmc_thld_ctl_for_sdmmc1(struct sunxi_mmc_host * host,struct mmc_ios * ios,struct mmc_data * data)533 void sunxi_mmc_thld_ctl_for_sdmmc1(struct sunxi_mmc_host *host,
534 				   struct mmc_ios *ios, struct mmc_data *data)
535 {
536 	u32 bsz = data->blksz;
537 	/*unit:byte */
538 	u32 rdtl = ((host->dma_tl & SDXC_RX_TL_MASK) >> 16) << 2;
539 	u32 rval = 0;
540 
541 	if ((data->flags & MMC_DATA_READ)
542 	    && (bsz <= SDXC_CARD_RD_THLD_SIZE)
543 	    /*((SDXC_FIFO_DETH<<2)-bsz) >= (rdtl)*/
544 	    && ((SDXC_FIFO_DETH << 2) >= (rdtl + bsz))
545 	    && ((ios->timing == MMC_TIMING_MMC_HS200)
546 		|| (ios->timing == MMC_TIMING_UHS_SDR50)
547 		|| (ios->timing == MMC_TIMING_UHS_SDR104))) {
548 		rval = mmc_readl(host, REG_THLD);
549 		rval &= ~SDXC_CARD_RD_THLD_MASK;
550 		rval |= data->blksz << SDXC_CARD_RD_THLD_SIZE_SHIFT;
551 		rval |= SDXC_CARD_RD_THLD_ENB;
552 		mmc_writel(host, REG_THLD, rval);
553 	} else {
554 		rval = mmc_readl(host, REG_THLD);
555 		rval &= ~SDXC_CARD_RD_THLD_ENB;
556 		mmc_writel(host, REG_THLD, rval);
557 	}
558 
559 	SM_DBG(mmc_dev(host->mmc), "SDXC_REG_THLD: 0x%08x\n",
560 		mmc_readl(host, REG_THLD));
561 
562 }
563 
sunxi_mmc_save_spec_reg1(struct sunxi_mmc_host * host)564 void sunxi_mmc_save_spec_reg1(struct sunxi_mmc_host *host)
565 {
566 	bak_spec_regs.drv_dl = mmc_readl(host, REG_DRV_DL);
567 	bak_spec_regs.samp_dl = mmc_readl(host, REG_SAMP_DL);
568 	bak_spec_regs.ds_dl = mmc_readl(host, REG_DS_DL);
569 	bak_spec_regs.sd_ntsr = mmc_readl(host, REG_SD_NTSR);
570 }
571 
sunxi_mmc_restore_spec_reg1(struct sunxi_mmc_host * host)572 void sunxi_mmc_restore_spec_reg1(struct sunxi_mmc_host *host)
573 {
574 	sunxi_r_op(host, mmc_writel(host, REG_DRV_DL, bak_spec_regs.drv_dl));
575 	mmc_writel(host, REG_SAMP_DL, bak_spec_regs.samp_dl);
576 	mmc_writel(host, REG_DS_DL, bak_spec_regs.ds_dl);
577 	mmc_writel(host, REG_SD_NTSR, bak_spec_regs.sd_ntsr);
578 }
579 
580 #endif
581