• 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_SUN8IW10P1
19 
20 #include <linux/clk.h>
21 #include <linux/clk-private.h>
22 #include <linux/reset/sunxi.h>
23 
24 #include <linux/gpio.h>
25 #include <linux/platform_device.h>
26 #include <linux/spinlock.h>
27 #include <linux/scatterlist.h>
28 #include <linux/dma-mapping.h>
29 #include <linux/slab.h>
30 #include <linux/reset.h>
31 
32 #include <linux/of_address.h>
33 #include <linux/of_gpio.h>
34 #include <linux/of_platform.h>
35 
36 #include <linux/mmc/host.h>
37 #include <linux/mmc/sd.h>
38 #include <linux/mmc/sdio.h>
39 #include <linux/mmc/mmc.h>
40 #include <linux/mmc/core.h>
41 #include <linux/mmc/card.h>
42 #include <linux/mmc/slot-gpio.h>
43 
44 #include "sunxi-smhc.h"
45 #include "sunxi-mmc-v5px.h"
46 
47 #define SMHC_DS_DLY	(0x230)
48 #define SMHC_THLD		(0x20c)
49 
50 #define SMHC_SAMP_DL_SW_MASK		(0x0000003F)
51 #define SMHC_DS_DL_SW_MASK			(0x0000003F)
52 #define SMHC_DS_DL_SW_EN			(1u<<7)
53 
54 #define SMHC_CARD_RD_TH_SZ		0x000007FF
55 #define SMHC_CARD_RD_TH_MASK	0x000007FF
56 #define SMHC_CARD_RD_TH_SHIFT	0x0
57 
58 #define SMHC_CARD_WR_TH_SZ		0x000007FF
59 #define SMHC_CARD_WR_TH_MASK	(0x000007FF<<16)
60 #define SMHC_CARD_WR_TH_SHIFT	16
61 
62 #define SMHC_DES_NUM_SHIFT_V5PX	(15)
63 #define SMHC_DES_BUFFER_MAX_LEN_V5PX	(1U << SMHC_DES_NUM_SHIFT)
64 
65 enum sunxi_mmc_speed_mode {
66 	SM0_DS26_SDR12 = 0,
67 	SM1_HSSDR52_SDR25,
68 	SM2_HSDDR52_DDR50,
69 	SM3_HS200_SDR104,
70 	SM4_HS400,
71 	SM_NUM,
72 };
73 
74 struct sunxi_mmc_clk_dly {
75 	enum sunxi_mmc_speed_mode spm;
76 	char *mod_str;
77 	char *raw_tm_sm_str[2];
78 	u32 raw_tm_sm[2];
79 	u32 raw_tm_sm_def[2];
80 };
81 
82 struct sunxi_mmc_ver_priv {
83 	/*struct sunxi_mmc_spec_regs bak_spec_regs; */
84 	struct sunxi_mmc_clk_dly mmc_clk_dly[SM_NUM];
85 };
86 
sunxi_mmc_set_clk_dly(struct sunxi_mmc_host * host,int clk,int bus_width,int timing)87 static void sunxi_mmc_set_clk_dly(struct sunxi_mmc_host *host, int clk,
88 				  int bus_width, int timing)
89 {
90 	struct mmc_host *mmc = host->mmc;
91 	enum sunxi_mmc_speed_mode speed_mod = SM0_DS26_SDR12;
92 	char *raw_sm_str = NULL;
93 	char *m_str = NULL;
94 	struct device_node *np = NULL;
95 	u32 *raw_sm = 0;
96 	u32 *raw_sm_def = 0;
97 	u32 rval = 0;
98 	int frq_index = 0;
99 	u32 cmd_drv_ph = 1;
100 	u32 dat_drv_ph = 0;
101 	u32 sam_dly = 0;
102 	u32 ds_dly = 0;
103 	struct sunxi_mmc_clk_dly *mmc_clk_dly =
104 	    ((struct sunxi_mmc_ver_priv *)host->version_priv_dat)->mmc_clk_dly;
105 
106 	if (!mmc->parent || !mmc->parent->of_node) {
107 		SM_ERR(mmc_dev(host->mmc),
108 			"no dts to parse clk dly,use default\n");
109 		return;
110 	}
111 
112 	np = mmc->parent->of_node;
113 
114 	switch (timing) {
115 	case MMC_TIMING_LEGACY:
116 	case MMC_TIMING_UHS_SDR12:
117 		speed_mod = SM0_DS26_SDR12;
118 		break;
119 	case MMC_TIMING_MMC_HS:
120 	case MMC_TIMING_SD_HS:
121 	case MMC_TIMING_UHS_SDR25:
122 		speed_mod = SM1_HSSDR52_SDR25;
123 		break;
124 	case MMC_TIMING_UHS_DDR50:
125 	case MMC_TIMING_MMC_DDR52:
126 		speed_mod = SM2_HSDDR52_DDR50;
127 		break;
128 	case MMC_TIMING_UHS_SDR50:
129 	case MMC_TIMING_UHS_SDR104:
130 	case MMC_TIMING_MMC_HS200:
131 		speed_mod = SM3_HS200_SDR104;
132 		break;
133 	case MMC_TIMING_MMC_HS400:
134 		speed_mod = SM4_HS400;
135 		break;
136 	default:
137 		SM_ERR(mmc_dev(mmc), "Wrong timing input\n");
138 		return;
139 	}
140 
141 	if (clk <= 400 * 1000) {
142 		frq_index = 0;
143 	} else if (clk <= 25 * 1000 * 1000) {
144 		frq_index = 1;
145 	} else if (clk <= 50 * 1000 * 1000) {
146 		frq_index = 2;
147 	} else if (clk <= 100 * 1000 * 1000) {
148 		frq_index = 3;
149 	} else if (clk <= 150 * 1000 * 1000) {
150 		frq_index = 4;
151 	} else if (clk <= 200 * 1000 * 1000) {
152 		frq_index = 5;
153 	} else if (clk <= 250 * 1000 * 1000) {
154 		frq_index = 6;
155 	} else if (clk <= 300 * 1000 * 1000) {
156 		frq_index = 7;
157 	} else {
158 		SM_ERR(mmc_dev(mmc), "clk is over 300mhz\n");
159 		return;
160 	}
161 
162 	if (frq_index / 4 > 2) {
163 		SM_ERR(mmc_dev(host->mmc), "err frq_index\n");
164 		return;
165 	}
166 
167 	SM_DBG(mmc_dev(host->mmc), "freq %d frq index %d,frq/4 %x\n", clk,
168 		frq_index, frq_index / 4);
169 	raw_sm_str = mmc_clk_dly[speed_mod].raw_tm_sm_str[frq_index / 4];
170 	raw_sm = &mmc_clk_dly[speed_mod].raw_tm_sm[frq_index / 4];
171 	raw_sm_def = &mmc_clk_dly[speed_mod].raw_tm_sm_def[frq_index / 4];
172 	m_str = mmc_clk_dly[speed_mod].mod_str;
173 
174 	rval = of_property_read_u32(np, raw_sm_str, raw_sm);
175 	if (rval) {
176 		SM_INFO(mmc_dev(host->mmc), "failed to get %s used default\n",
177 			 m_str);
178 	} else {
179 		u32 sm_shift = (frq_index % 4) * 8;
180 
181 		rval = ((*raw_sm) >> sm_shift) & 0xff;
182 		if (rval != 0xff) {
183 			if (timing == MMC_TIMING_MMC_HS400) {
184 				u32 raw_sm_hs200 = 0;
185 
186 				ds_dly = rval;
187 				raw_sm_hs200 =
188 				    mmc_clk_dly[SM3_HS200_SDR104].
189 				    raw_tm_sm[frq_index / 4];
190 				sam_dly = ((raw_sm_hs200) >> sm_shift) & 0xff;
191 			} else {
192 				sam_dly = rval;
193 			}
194 			SM_DBG(mmc_dev(host->mmc),
195 				"Get speed mode %s clk dly %s ok\n", m_str,
196 				raw_sm_str);
197 		} else {
198 			u32 sm_shift = (frq_index % 4) * 8;
199 
200 			SM_DBG(mmc_dev(host->mmc), "%s use default value\n",
201 				m_str);
202 			rval = ((*raw_sm_def) >> sm_shift) & 0xff;
203 			if (timing == MMC_TIMING_MMC_HS400) {
204 				u32 raw_sm_hs200 = 0;
205 
206 				ds_dly = rval;
207 				raw_sm_hs200 =
208 				    mmc_clk_dly[SM3_HS200_SDR104].
209 				    raw_tm_sm_def[frq_index / 4];
210 				sam_dly = ((raw_sm_hs200) >> sm_shift) & 0xff;
211 			} else {
212 				sam_dly = rval;
213 			}
214 		}
215 
216 	}
217 
218 	SM_DBG(mmc_dev(host->mmc), "Try set %s clk dly	ok\n", m_str);
219 	SM_DBG(mmc_dev(host->mmc), "cmd_drv_ph	%d\n", cmd_drv_ph);
220 	SM_DBG(mmc_dev(host->mmc), "dat_drv_ph	%d\n", dat_drv_ph);
221 	SM_DBG(mmc_dev(host->mmc), "sam_dly	%d\n", sam_dly);
222 	SM_DBG(mmc_dev(host->mmc), "ds_dly		%d\n", ds_dly);
223 
224 	rval = smhc_readl(host, SMHC_DS_DLY);
225 	rval &= ~SMHC_DS_DL_SW_MASK;
226 	rval |= ds_dly & SMHC_DS_DL_SW_MASK;
227 	rval |= SMHC_DS_DL_SW_EN;
228 	smhc_writel(host, SMHC_DS_DLY, rval);
229 	SM_DBG(mmc_dev(host->mmc), " SMHC_DS_DLY      %08x\n",
230 		smhc_readl(host, SMHC_DS_DLY));
231 }
232 
sunxi_mmc_dump_dly2(struct sunxi_mmc_host * host)233 void sunxi_mmc_dump_dly2(struct sunxi_mmc_host *host)
234 {
235 	SM_DBG(mmc_dev(host->mmc), "no imple %s %d\n", __func__, __LINE__);
236 }
237 
__sunxi_mmc_do_oclk_onoff(struct sunxi_mmc_host * host,u32 oclk_en,u32 pwr_save,u32 ignore_dat0)238 static int __sunxi_mmc_do_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en,
239 				     u32 pwr_save, u32 ignore_dat0)
240 {
241 	u32 tmp = 0;
242 
243 	tmp = smhc_readl(host, SMHC_RST_CLK_CTRL);
244 	if (oclk_en)
245 		tmp |= SdclkEn;
246 	else
247 		tmp &= ~SdclkEn;
248 
249 	smhc_writel(host, SMHC_RST_CLK_CTRL, tmp);
250 
251 	tmp = smhc_readl(host, SMHC_CTRL3);
252 	if (pwr_save)
253 		tmp |= SdclkIdleCtrl;
254 	else
255 		tmp &= ~SdclkIdleCtrl;
256 
257 	smhc_writel(host, SMHC_CTRL3, tmp);
258 
259 	return 0;
260 
261 }
262 
sunxi_mmc_oclk_onoff(struct sunxi_mmc_host * host,u32 oclk_en)263 int sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en)
264 {
265 	struct device_node *np = NULL;
266 	struct mmc_host *mmc = host->mmc;
267 	int pwr_save = 0;
268 	int len = 0;
269 
270 	if (!mmc->parent || !mmc->parent->of_node) {
271 		SM_ERR(mmc_dev(host->mmc),
272 			"no dts to parse power save mode\n");
273 		return -EIO;
274 	}
275 
276 	np = mmc->parent->of_node;
277 	if (of_find_property(np, "sunxi-power-save-mode", &len))
278 		pwr_save = 1;
279 	return __sunxi_mmc_do_oclk_onoff(host, oclk_en, pwr_save, 1);
280 }
sunxi_mmc_clk_set_rate_v5px(struct sunxi_mmc_host * host,struct mmc_ios * ios)281 int sunxi_mmc_clk_set_rate_v5px(struct sunxi_mmc_host *host,
282 				struct mmc_ios *ios)
283 {
284 	u32 mod_clk = 0;
285 	u32 src_clk = 0;
286 	u32 rval = 0;
287 	s32 err = 0;
288 	u32 rate = 0;
289 	char *sclk_name = NULL;
290 	struct clk *mclk = host->clk_mmc;
291 	struct clk *sclk = NULL;
292 	struct device *dev = mmc_dev(host->mmc);
293 
294 	if (ios->clock == 0) {
295 		__sunxi_mmc_do_oclk_onoff(host, 0, 0, 1);
296 		return 0;
297 	}
298 
299 	if (sunxi_mmc_ddr_timing(ios->timing))
300 		mod_clk = ios->clock << 3;
301 	else
302 		mod_clk = ios->clock << 2;
303 
304 	if (ios->clock <= 400000) {
305 		sclk = clk_get(dev, "osc24m");
306 		sclk_name = "osc24m";
307 	} else {
308 		sclk = clk_get(dev, "pll_periph");
309 		sclk_name = "pll_periph";
310 	}
311 	if (IS_ERR(sclk)) {
312 		SM_ERR(mmc_dev(host->mmc), "Error to get source clock %s\n",
313 			sclk_name);
314 		return -1;
315 	}
316 
317 	sunxi_mmc_oclk_onoff(host, 0);
318 
319 	err = clk_set_parent(mclk, sclk);
320 	if (err) {
321 		SM_ERR(mmc_dev(host->mmc), "set parent failed\n");
322 		clk_put(sclk);
323 		return -1;
324 	}
325 
326 	rate = clk_round_rate(mclk, mod_clk);
327 
328 	SM_DBG(mmc_dev(host->mmc), "get round rate %d\n", rate);
329 
330 	clk_disable_unprepare(host->clk_mmc);
331 
332 	err = clk_set_rate(mclk, rate);
333 	if (err) {
334 		SM_ERR(mmc_dev(host->mmc), "set mclk rate error, rate %dHz\n",
335 			rate);
336 		clk_put(sclk);
337 		return -1;
338 	}
339 
340 	rval = clk_prepare_enable(host->clk_mmc);
341 	if (rval) {
342 		SM_ERR(mmc_dev(host->mmc), "Enable mmc clk err %d\n", rval);
343 		return -1;
344 	}
345 
346 	src_clk = clk_get_rate(sclk);
347 	clk_put(sclk);
348 
349 	SM_DBG(mmc_dev(host->mmc), "set round clock %d, soure clk is %d\n",
350 		rate, src_clk);
351 
352 	/*sunxi_of_parse_clk_dly(host); */
353 	if (sunxi_mmc_ddr_timing(ios->timing))
354 		ios->clock = rate >> 3;
355 	else
356 		ios->clock = rate >> 2;
357 
358 
359 	sunxi_mmc_set_clk_dly(host, ios->clock, ios->bus_width, ios->timing);
360 
361 	return sunxi_mmc_oclk_onoff(host, 1);
362 }
363 
sunxi_mmc_thld_ctl_v5px(struct sunxi_mmc_host * host,struct mmc_ios * ios,struct mmc_data * data)364 void sunxi_mmc_thld_ctl_v5px(struct sunxi_mmc_host *host,
365 			     struct mmc_ios *ios, struct mmc_data *data)
366 {
367 	u32 bsz = data->blksz;
368 	u32 rval = 0;
369 
370 	if ((data->flags & MMC_DATA_WRITE)
371 	    && (bsz <= SMHC_CARD_WR_TH_SZ)) {
372 		rval = smhc_readl(host, SMHC_THLD);
373 		rval &= ~SMHC_CARD_WR_TH_MASK;
374 		rval |= data->blksz << SMHC_CARD_WR_TH_SHIFT;
375 		/*rval |= SDXC_CARD_WR_THLD_ENB; */
376 		smhc_writel(host, SMHC_THLD, rval);
377 	} else {
378 		/*
379 		*   rval = mmc_readl(host, REG_THLD);
380 		*   rval &= ~SDXC_CARD_WR_THLD_ENB;
381 		 *  mmc_writel(host, REG_THLD, rval);
382 		 */
383 	}
384 
385 	if ((data->flags & MMC_DATA_READ)
386 	    && (bsz <= SMHC_CARD_RD_TH_SZ)
387 	    && ((ios->timing == MMC_TIMING_MMC_HS200)
388 		|| (ios->timing == MMC_TIMING_MMC_HS400)
389 		|| (ios->timing == MMC_TIMING_UHS_SDR50)
390 		|| (ios->timing == MMC_TIMING_UHS_SDR104))) {
391 		rval = smhc_readl(host, SMHC_THLD);
392 		rval &= ~SMHC_CARD_RD_TH_MASK;
393 		rval |= data->blksz << SMHC_CARD_RD_TH_SHIFT;
394 		/*rval |= SDXC_CARD_RD_THLD_ENB; */
395 		smhc_writel(host, SMHC_THLD, rval);
396 	} else {
397 		/*
398 		*   rval = mmc_readl(host, REG_THLD);
399 		*  rval &= ~SDXC_CARD_RD_THLD_ENB;
400 		*  mmc_writel(host, REG_THLD, rval);
401 		 */
402 	}
403 
404 	SM_DBG(mmc_dev(host->mmc), "SDXC_REG_THLD: 0x%08x\n",
405 		smhc_readl(host, SMHC_THLD));
406 }
407 
sunxi_mmc_save_spec_reg_v5px(struct sunxi_mmc_host * host)408 void sunxi_mmc_save_spec_reg_v5px(struct sunxi_mmc_host *host)
409 {
410 	SM_DBG(mmc_dev(host->mmc), "no imple %s %d\n", __func__, __LINE__);
411 
412 }
413 
sunxi_mmc_restore_spec_reg_v5px(struct sunxi_mmc_host * host)414 void sunxi_mmc_restore_spec_reg_v5px(struct sunxi_mmc_host *host)
415 {
416 	SM_DBG(mmc_dev(host->mmc), "no imple %s %d\n", __func__, __LINE__);
417 
418 }
419 
420 
421 
sunxi_mmc_can_poweroff_notify(const struct mmc_card * card)422 static int sunxi_mmc_can_poweroff_notify(const struct mmc_card *card)
423 {
424 	return card &&
425 	    mmc_card_mmc(card) &&
426 	    (card->ext_csd.power_off_notification == EXT_CSD_POWER_ON);
427 }
428 
sunxi_mmc_poweroff_notify(struct mmc_card * card,unsigned int notify_type)429 static int sunxi_mmc_poweroff_notify(struct mmc_card *card,
430 				     unsigned int notify_type)
431 {
432 	unsigned int timeout = card->ext_csd.generic_cmd6_time;
433 	int err;
434 
435 	/* Use EXT_CSD_POWER_OFF_SHORT as default notification type. */
436 	if (notify_type == EXT_CSD_POWER_OFF_LONG)
437 		timeout = card->ext_csd.power_off_longtime;
438 
439 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
440 			   EXT_CSD_POWER_OFF_NOTIFICATION,
441 			   notify_type, timeout, true, false, false);
442 	if (err)
443 		pr_err("%s: Power Off Notification timed out, %u\n",
444 		       mmc_hostname(card->host), timeout);
445 
446 	/* Disable the power off notification after the switch operation. */
447 	card->ext_csd.power_off_notification = EXT_CSD_NO_POWER_NOTIFICATION;
448 
449 	return err;
450 }
451 
sunxi_mmc_sleep(struct mmc_host * host)452 static int sunxi_mmc_sleep(struct mmc_host *host)
453 {
454 	struct mmc_card *card = host->card;
455 	int err = -1;
456 
457 	if (card && card->ext_csd.rev >= 3) {
458 		err = mmc_card_sleepawake(host, 1);
459 		if (err < 0)
460 			pr_debug("%s: Error %d while putting card into sleep",
461 				 mmc_hostname(host), err);
462 	}
463 
464 	return err;
465 }
466 
sunxi_mmc_suspend(struct mmc_host * host,bool is_suspend)467 static int sunxi_mmc_suspend(struct mmc_host *host, bool is_suspend)
468 {
469 	int err = 0;
470 	unsigned int notify_type = is_suspend ? EXT_CSD_POWER_OFF_SHORT :
471 	    EXT_CSD_POWER_OFF_LONG;
472 
473 	if (!host) {
474 		pr_err("Host should be null\n");
475 		return -1;
476 	}
477 	if (!host->card) {
478 		pr_err("Card should be null\n");
479 		return -1;
480 	}
481 
482 	mmc_claim_host(host);
483 
484 	/*
485 	 *  if (mmc_card_suspended(host->card))
486 	 *  goto out;
487 	 */
488 
489 	if (mmc_card_doing_bkops(host->card)) {
490 		err = mmc_stop_bkops(host->card);
491 		if (err)
492 			goto out;
493 	}
494 
495 	err = mmc_flush_cache(host->card);
496 
497 	if (err)
498 		goto out;
499 
500 	if (sunxi_mmc_can_poweroff_notify(host->card) &&
501 	    ((host->caps2 & MMC_CAP2_POWEROFF_NOTIFY) || !is_suspend)) {
502 		err = sunxi_mmc_poweroff_notify(host->card, notify_type);
503 	} else if (mmc_card_can_sleep(host)) {
504 		err = sunxi_mmc_sleep(host);
505 	} else if (!mmc_host_is_spi(host)) {
506 		err = mmc_deselect_cards(host);
507 	}
508 
509 	if (!err) {
510 		pr_info("%s: %s %d\n",
511 			mmc_hostname(host), __func__, __LINE__);
512 		mmc_power_off(host);
513 /*		mmc_card_set_suspended(host->card);*/
514 	}
515 
516 out:
517 	mmc_release_host(host);
518 	return err;
519 }
520 
sunxi_mmc_do_shutdown_v5px(struct platform_device * pdev)521 void sunxi_mmc_do_shutdown_v5px(struct platform_device *pdev)
522 {
523 	struct mmc_host *mmc = platform_get_drvdata(pdev);
524 	u32 shutdown_notify_type = 0;
525 	u32 rval =
526 	    of_property_read_u32(mmc->parent->of_node, "shutdown_notify_type",
527 				 &shutdown_notify_type);
528 	if (!rval)
529 		sunxi_mmc_suspend(mmc, shutdown_notify_type);
530 	else
531 		sunxi_mmc_suspend(mmc, false);
532 }
533 
sunxi_mmc_init_priv_v5px(struct sunxi_mmc_host * host,struct platform_device * pdev,int phy_index)534 void sunxi_mmc_init_priv_v5px(struct sunxi_mmc_host *host,
535 			      struct platform_device *pdev, int phy_index)
536 {
537 	struct sunxi_mmc_ver_priv *ver_priv =
538 	    devm_kzalloc(&pdev->dev, sizeof(struct sunxi_mmc_ver_priv),
539 			 GFP_KERNEL);
540 	host->version_priv_dat = ver_priv;
541 
542 	ver_priv->mmc_clk_dly[SM0_DS26_SDR12].spm = SM0_DS26_SDR12;
543 	ver_priv->mmc_clk_dly[SM0_DS26_SDR12].mod_str = "DS26_SDR12";
544 	ver_priv->mmc_clk_dly[SM0_DS26_SDR12].raw_tm_sm_str[0] =
545 	    "sdc_tm4_sm0_freq0";
546 	ver_priv->mmc_clk_dly[SM0_DS26_SDR12].raw_tm_sm_str[1] =
547 	    "sdc_tm4_sm0_freq1";
548 	ver_priv->mmc_clk_dly[SM0_DS26_SDR12].raw_tm_sm[0] = 0;
549 	ver_priv->mmc_clk_dly[SM0_DS26_SDR12].raw_tm_sm[1] = 0;
550 	ver_priv->mmc_clk_dly[SM0_DS26_SDR12].raw_tm_sm_def[0] = 0;
551 	ver_priv->mmc_clk_dly[SM0_DS26_SDR12].raw_tm_sm_def[1] = 0;
552 
553 	ver_priv->mmc_clk_dly[SM1_HSSDR52_SDR25].spm = SM1_HSSDR52_SDR25;
554 	ver_priv->mmc_clk_dly[SM1_HSSDR52_SDR25].mod_str = "HSSDR52_SDR25";
555 	ver_priv->mmc_clk_dly[SM1_HSSDR52_SDR25].raw_tm_sm_str[0] =
556 	    "sdc_tm4_sm1_freq0";
557 	ver_priv->mmc_clk_dly[SM1_HSSDR52_SDR25].raw_tm_sm_str[1] =
558 	    "sdc_tm4_sm1_freq1";
559 	ver_priv->mmc_clk_dly[SM1_HSSDR52_SDR25].raw_tm_sm[0] = 0;
560 	ver_priv->mmc_clk_dly[SM1_HSSDR52_SDR25].raw_tm_sm[1] = 0;
561 	ver_priv->mmc_clk_dly[SM1_HSSDR52_SDR25].raw_tm_sm_def[0] = 0;
562 	ver_priv->mmc_clk_dly[SM1_HSSDR52_SDR25].raw_tm_sm_def[1] = 0;
563 
564 	ver_priv->mmc_clk_dly[SM2_HSDDR52_DDR50].spm = SM2_HSDDR52_DDR50;
565 	ver_priv->mmc_clk_dly[SM2_HSDDR52_DDR50].mod_str = "HSDDR52_DDR50";
566 	ver_priv->mmc_clk_dly[SM2_HSDDR52_DDR50].raw_tm_sm_str[0] =
567 	    "sdc_tm4_sm2_freq0";
568 	ver_priv->mmc_clk_dly[SM2_HSDDR52_DDR50].raw_tm_sm_str[1] =
569 	    "sdc_tm4_sm2_freq1";
570 	ver_priv->mmc_clk_dly[SM2_HSDDR52_DDR50].raw_tm_sm[0] = 0;
571 	ver_priv->mmc_clk_dly[SM2_HSDDR52_DDR50].raw_tm_sm[1] = 0;
572 	ver_priv->mmc_clk_dly[SM2_HSDDR52_DDR50].raw_tm_sm_def[0] = 0;
573 	ver_priv->mmc_clk_dly[SM2_HSDDR52_DDR50].raw_tm_sm_def[1] = 0;
574 
575 	ver_priv->mmc_clk_dly[SM3_HS200_SDR104].spm = SM3_HS200_SDR104;
576 	ver_priv->mmc_clk_dly[SM3_HS200_SDR104].mod_str = "HS200_SDR104";
577 	ver_priv->mmc_clk_dly[SM3_HS200_SDR104].raw_tm_sm_str[0] =
578 	    "sdc_tm4_sm3_freq0";
579 	ver_priv->mmc_clk_dly[SM3_HS200_SDR104].raw_tm_sm_str[1] =
580 	    "sdc_tm4_sm3_freq1";
581 	ver_priv->mmc_clk_dly[SM3_HS200_SDR104].raw_tm_sm[0] = 0;
582 	ver_priv->mmc_clk_dly[SM3_HS200_SDR104].raw_tm_sm[1] = 0;
583 	ver_priv->mmc_clk_dly[SM3_HS200_SDR104].raw_tm_sm_def[0] = 0;
584 	ver_priv->mmc_clk_dly[SM3_HS200_SDR104].raw_tm_sm_def[1] = 0x00000405;
585 
586 	ver_priv->mmc_clk_dly[SM4_HS400].spm = SM4_HS400;
587 	ver_priv->mmc_clk_dly[SM4_HS400].mod_str = "HS400";
588 	ver_priv->mmc_clk_dly[SM4_HS400].raw_tm_sm_str[0] = "sdc_tm4_sm4_freq0";
589 	ver_priv->mmc_clk_dly[SM4_HS400].raw_tm_sm_str[1] = "sdc_tm4_sm4_freq1";
590 	ver_priv->mmc_clk_dly[SM4_HS400].raw_tm_sm[0] = 0;
591 	ver_priv->mmc_clk_dly[SM4_HS400].raw_tm_sm[1] = 0x00000608;
592 	ver_priv->mmc_clk_dly[SM4_HS400].raw_tm_sm_def[0] = 0;
593 	ver_priv->mmc_clk_dly[SM4_HS400].raw_tm_sm_def[1] = 0x00000408;
594 
595 	host->sunxi_mmc_clk_set_rate = sunxi_mmc_clk_set_rate_v5px;
596 	/*host->idma_des_size_bits = 15; */
597 	host->idma_des_size_bits = SMHC_DES_NUM_SHIFT_V5PX;
598 	host->sunxi_mmc_thld_ctl = sunxi_mmc_thld_ctl_v5px;
599 	host->sunxi_mmc_save_spec_reg = sunxi_mmc_save_spec_reg_v5px;
600 	host->sunxi_mmc_restore_spec_reg = sunxi_mmc_restore_spec_reg_v5px;
601 	/*sunxi_mmc_reg_ex_res_inter(host, phy_index);
602 	*  host->sunxi_mmc_set_acmda = sunxi_mmc_set_a12a;
603 	 */
604 	host->sunxi_mmc_dump_dly_table = sunxi_mmc_dump_dly2;
605 	host->phy_index = phy_index;
606 }
607 
608 #endif
609