fsl_esdhc.c 29.3 KB
Newer Older
1
/*
2
 * Copyright 2007, 2010-2011 Freescale Semiconductor, Inc
3 4 5 6 7 8
 * Andy Fleming
 *
 * Based vaguely on the pxa mmc code:
 * (C) Copyright 2003
 * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net
 *
9
 * SPDX-License-Identifier:	GPL-2.0+
10 11 12 13 14
 */

#include <config.h>
#include <common.h>
#include <command.h>
15
#include <errno.h>
16
#include <hwconfig.h>
17 18
#include <mmc.h>
#include <part.h>
19
#include <power/regulator.h>
20 21
#include <malloc.h>
#include <fsl_esdhc.h>
22
#include <fdt_support.h>
23
#include <asm/io.h>
P
Peng Fan 已提交
24 25
#include <dm.h>
#include <asm-generic/gpio.h>
26 27 28

DECLARE_GLOBAL_DATA_PTR;

29 30 31 32 33 34 35
#define SDHCI_IRQ_EN_BITS		(IRQSTATEN_CC | IRQSTATEN_TC | \
				IRQSTATEN_CINT | \
				IRQSTATEN_CTOE | IRQSTATEN_CCE | IRQSTATEN_CEBE | \
				IRQSTATEN_CIE | IRQSTATEN_DTOE | IRQSTATEN_DCE | \
				IRQSTATEN_DEBE | IRQSTATEN_BRR | IRQSTATEN_BWR | \
				IRQSTATEN_DINT)

36
struct fsl_esdhc {
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
	uint    dsaddr;		/* SDMA system address register */
	uint    blkattr;	/* Block attributes register */
	uint    cmdarg;		/* Command argument register */
	uint    xfertyp;	/* Transfer type register */
	uint    cmdrsp0;	/* Command response 0 register */
	uint    cmdrsp1;	/* Command response 1 register */
	uint    cmdrsp2;	/* Command response 2 register */
	uint    cmdrsp3;	/* Command response 3 register */
	uint    datport;	/* Buffer data port register */
	uint    prsstat;	/* Present state register */
	uint    proctl;		/* Protocol control register */
	uint    sysctl;		/* System Control Register */
	uint    irqstat;	/* Interrupt status register */
	uint    irqstaten;	/* Interrupt status enable register */
	uint    irqsigen;	/* Interrupt signal enable register */
	uint    autoc12err;	/* Auto CMD error status register */
	uint    hostcapblt;	/* Host controller capabilities register */
	uint    wml;		/* Watermark level register */
	uint    mixctrl;	/* For USDHC */
	char    reserved1[4];	/* reserved */
	uint    fevt;		/* Force event register */
	uint    admaes;		/* ADMA error status register */
	uint    adsaddr;	/* ADMA system address register */
60 61 62 63 64 65 66 67 68
	char    reserved2[4];
	uint    dllctrl;
	uint    dllstat;
	uint    clktunectrlstatus;
	char    reserved3[84];
	uint    vendorspec;
	uint    mmcboot;
	uint    vendorspec2;
	char	reserved4[48];
69 70
	uint    hostver;	/* Host controller version register */
	char    reserved5[4];	/* reserved */
71
	uint    dmaerraddr;	/* DMA error address register */
72
	char    reserved6[4];	/* reserved */
73 74
	uint    dmaerrattr;	/* DMA error attribute register */
	char    reserved7[4];	/* reserved */
75
	uint    hostcapblt2;	/* Host controller capabilities register 2 */
76
	char    reserved8[8];	/* reserved */
77
	uint    tcr;		/* Tuning control register */
78
	char    reserved9[28];	/* reserved */
79
	uint    sddirctl;	/* SD direction control register */
80
	char    reserved10[712];/* reserved */
81
	uint    scr;		/* eSDHC control register */
82 83
};

84 85 86 87 88
struct fsl_esdhc_plat {
	struct mmc_config cfg;
	struct mmc mmc;
};

P
Peng Fan 已提交
89 90 91 92 93 94 95 96 97 98 99
/**
 * struct fsl_esdhc_priv
 *
 * @esdhc_regs: registers of the sdhc controller
 * @sdhc_clk: Current clk of the sdhc controller
 * @bus_width: bus width, 1bit, 4bit or 8bit
 * @cfg: mmc config
 * @mmc: mmc
 * Following is used when Driver Model is enabled for MMC
 * @dev: pointer for the device
 * @non_removable: 0: removable; 1: non-removable
P
Peng Fan 已提交
100
 * @wp_enable: 1: enable checking wp; 0: no check
101
 * @vs18_enable: 1: use 1.8V voltage; 0: use 3.3V
P
Peng Fan 已提交
102
 * @cd_gpio: gpio for card detection
P
Peng Fan 已提交
103
 * @wp_gpio: gpio for write protection
P
Peng Fan 已提交
104 105 106 107 108
 */
struct fsl_esdhc_priv {
	struct fsl_esdhc *esdhc_regs;
	unsigned int sdhc_clk;
	unsigned int bus_width;
109
#if !CONFIG_IS_ENABLED(BLK)
P
Peng Fan 已提交
110
	struct mmc *mmc;
111
#endif
P
Peng Fan 已提交
112 113
	struct udevice *dev;
	int non_removable;
P
Peng Fan 已提交
114
	int wp_enable;
115
	int vs18_enable;
116
#ifdef CONFIG_DM_GPIO
P
Peng Fan 已提交
117
	struct gpio_desc cd_gpio;
P
Peng Fan 已提交
118
	struct gpio_desc wp_gpio;
119
#endif
P
Peng Fan 已提交
120 121
};

122
/* Return the XFERTYP flags for a given command and data packet */
123
static uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data)
124 125 126 127
{
	uint xfertyp = 0;

	if (data) {
128 129 130 131
		xfertyp |= XFERTYP_DPSEL;
#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
		xfertyp |= XFERTYP_DMAEN;
#endif
132 133 134
		if (data->blocks > 1) {
			xfertyp |= XFERTYP_MSBSEL;
			xfertyp |= XFERTYP_BCEN;
135 136 137
#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111
			xfertyp |= XFERTYP_AC12EN;
#endif
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
		}

		if (data->flags & MMC_DATA_READ)
			xfertyp |= XFERTYP_DTDSEL;
	}

	if (cmd->resp_type & MMC_RSP_CRC)
		xfertyp |= XFERTYP_CCCEN;
	if (cmd->resp_type & MMC_RSP_OPCODE)
		xfertyp |= XFERTYP_CICEN;
	if (cmd->resp_type & MMC_RSP_136)
		xfertyp |= XFERTYP_RSPTYP_136;
	else if (cmd->resp_type & MMC_RSP_BUSY)
		xfertyp |= XFERTYP_RSPTYP_48_BUSY;
	else if (cmd->resp_type & MMC_RSP_PRESENT)
		xfertyp |= XFERTYP_RSPTYP_48;

155 156
	if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
		xfertyp |= XFERTYP_CMDTYP_ABORT;
157

158 159 160
	return XFERTYP_CMD(cmd->cmdidx) | xfertyp;
}

161 162 163 164
#ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO
/*
 * PIO Read/Write Mode reduce the performace as DMA is not used in this mode.
 */
165 166
static void esdhc_pio_read_write(struct fsl_esdhc_priv *priv,
				 struct mmc_data *data)
167
{
P
Peng Fan 已提交
168
	struct fsl_esdhc *regs = priv->esdhc_regs;
169 170 171 172 173
	uint blocks;
	char *buffer;
	uint databuf;
	uint size;
	uint irqstat;
174
	ulong start;
175 176 177 178 179

	if (data->flags & MMC_DATA_READ) {
		blocks = data->blocks;
		buffer = data->dest;
		while (blocks) {
180
			start = get_timer(0);
181 182
			size = data->blocksize;
			irqstat = esdhc_read32(&regs->irqstat);
183 184 185 186 187
			while (!(esdhc_read32(&regs->prsstat) & PRSSTAT_BREN)) {
				if (get_timer(start) > PIO_TIMEOUT) {
					printf("\nData Read Failed in PIO Mode.");
					return;
				}
188 189 190 191 192 193 194 195 196 197 198 199 200
			}
			while (size && (!(irqstat & IRQSTAT_TC))) {
				udelay(100); /* Wait before last byte transfer complete */
				irqstat = esdhc_read32(&regs->irqstat);
				databuf = in_le32(&regs->datport);
				*((uint *)buffer) = databuf;
				buffer += 4;
				size -= 4;
			}
			blocks--;
		}
	} else {
		blocks = data->blocks;
201
		buffer = (char *)data->src;
202
		while (blocks) {
203
			start = get_timer(0);
204 205
			size = data->blocksize;
			irqstat = esdhc_read32(&regs->irqstat);
206 207 208 209 210
			while (!(esdhc_read32(&regs->prsstat) & PRSSTAT_BWEN)) {
				if (get_timer(start) > PIO_TIMEOUT) {
					printf("\nData Write Failed in PIO Mode.");
					return;
				}
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
			}
			while (size && (!(irqstat & IRQSTAT_TC))) {
				udelay(100); /* Wait before last byte transfer complete */
				databuf = *((uint *)buffer);
				buffer += 4;
				size -= 4;
				irqstat = esdhc_read32(&regs->irqstat);
				out_le32(&regs->datport, databuf);
			}
			blocks--;
		}
	}
}
#endif

226 227
static int esdhc_setup_data(struct fsl_esdhc_priv *priv, struct mmc *mmc,
			    struct mmc_data *data)
228 229
{
	int timeout;
P
Peng Fan 已提交
230
	struct fsl_esdhc *regs = priv->esdhc_regs;
P
Peng Fan 已提交
231 232
#if defined(CONFIG_FSL_LAYERSCAPE) || defined(CONFIG_S32V234) || \
	defined(CONFIG_MX8M)
233 234
	dma_addr_t addr;
#endif
235
	uint wml_value;
236 237 238 239

	wml_value = data->blocksize/4;

	if (data->flags & MMC_DATA_READ) {
240 241
		if (wml_value > WML_RD_WML_MAX)
			wml_value = WML_RD_WML_MAX_VAL;
242

243
		esdhc_clrsetbits32(&regs->wml, WML_RD_WML_MASK, wml_value);
244
#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
P
Peng Fan 已提交
245 246
#if defined(CONFIG_FSL_LAYERSCAPE) || defined(CONFIG_S32V234) || \
	defined(CONFIG_MX8M)
247 248 249 250 251 252
		addr = virt_to_phys((void *)(data->dest));
		if (upper_32_bits(addr))
			printf("Error found for upper 32 bits\n");
		else
			esdhc_write32(&regs->dsaddr, lower_32_bits(addr));
#else
253
		esdhc_write32(&regs->dsaddr, (u32)data->dest);
254
#endif
255
#endif
256
	} else {
257
#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
258 259 260
		flush_dcache_range((ulong)data->src,
				   (ulong)data->src+data->blocks
					 *data->blocksize);
261
#endif
262 263
		if (wml_value > WML_WR_WML_MAX)
			wml_value = WML_WR_WML_MAX_VAL;
P
Peng Fan 已提交
264 265 266 267
		if (priv->wp_enable) {
			if ((esdhc_read32(&regs->prsstat) &
			    PRSSTAT_WPSPL) == 0) {
				printf("\nThe SD card is locked. Can not write to a locked card.\n\n");
268
				return -ETIMEDOUT;
P
Peng Fan 已提交
269
			}
270
		}
271 272 273

		esdhc_clrsetbits32(&regs->wml, WML_WR_WML_MASK,
					wml_value << 16);
274
#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
P
Peng Fan 已提交
275 276
#if defined(CONFIG_FSL_LAYERSCAPE) || defined(CONFIG_S32V234) || \
	defined(CONFIG_MX8M)
277 278 279 280 281 282
		addr = virt_to_phys((void *)(data->src));
		if (upper_32_bits(addr))
			printf("Error found for upper 32 bits\n");
		else
			esdhc_write32(&regs->dsaddr, lower_32_bits(addr));
#else
283
		esdhc_write32(&regs->dsaddr, (u32)data->src);
284
#endif
285
#endif
286 287
	}

288
	esdhc_write32(&regs->blkattr, data->blocks << 16 | data->blocksize);
289 290

	/* Calculate the timeout period for data transactions */
291 292 293 294 295
	/*
	 * 1)Timeout period = (2^(timeout+13)) SD Clock cycles
	 * 2)Timeout period should be minimum 0.250sec as per SD Card spec
	 *  So, Number of SD Clock cycles for 0.25sec should be minimum
	 *		(SD Clock/sec * 0.25 sec) SD Clock cycles
296
	 *		= (mmc->clock * 1/4) SD Clock cycles
297
	 * As 1) >=  2)
298
	 * => (2^(timeout+13)) >= mmc->clock * 1/4
299
	 * Taking log2 both the sides
300
	 * => timeout + 13 >= log2(mmc->clock/4)
301
	 * Rounding up to next power of 2
302 303
	 * => timeout + 13 = log2(mmc->clock/4) + 1
	 * => timeout + 13 = fls(mmc->clock/4)
304 305 306 307 308 309 310
	 *
	 * However, the MMC spec "It is strongly recommended for hosts to
	 * implement more than 500ms timeout value even if the card
	 * indicates the 250ms maximum busy length."  Even the previous
	 * value of 300ms is known to be insufficient for some cards.
	 * So, we use
	 * => timeout + 13 = fls(mmc->clock/2)
311
	 */
312
	timeout = fls(mmc->clock/2);
313 314 315 316 317 318 319 320
	timeout -= 13;

	if (timeout > 14)
		timeout = 14;

	if (timeout < 0)
		timeout = 0;

321 322 323 324 325
#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC_A001
	if ((timeout == 4) || (timeout == 8) || (timeout == 12))
		timeout++;
#endif

326 327 328
#ifdef ESDHCI_QUIRK_BROKEN_TIMEOUT_VALUE
	timeout = 0xE;
#endif
329
	esdhc_clrsetbits32(&regs->sysctl, SYSCTL_TIMEOUT_MASK, timeout << 16);
330 331 332 333

	return 0;
}

334 335 336
static void check_and_invalidate_dcache_range
	(struct mmc_cmd *cmd,
	 struct mmc_data *data) {
337
	unsigned start = 0;
338
	unsigned end = 0;
339 340
	unsigned size = roundup(ARCH_DMA_MINALIGN,
				data->blocks*data->blocksize);
P
Peng Fan 已提交
341 342
#if defined(CONFIG_FSL_LAYERSCAPE) || defined(CONFIG_S32V234) || \
	defined(CONFIG_MX8M)
343 344 345 346 347 348 349
	dma_addr_t addr;

	addr = virt_to_phys((void *)(data->dest));
	if (upper_32_bits(addr))
		printf("Error found for upper 32 bits\n");
	else
		start = lower_32_bits(addr);
350 351
#else
	start = (unsigned)data->dest;
352
#endif
353
	end = start + size;
354 355
	invalidate_dcache_range(start, end);
}
356

357 358 359 360
/*
 * Sends a command out on the bus.  Takes the mmc pointer,
 * a command pointer, and an optional data pointer.
 */
361 362
static int esdhc_send_cmd_common(struct fsl_esdhc_priv *priv, struct mmc *mmc,
				 struct mmc_cmd *cmd, struct mmc_data *data)
363
{
364
	int	err = 0;
365 366
	uint	xfertyp;
	uint	irqstat;
P
Peng Fan 已提交
367
	struct fsl_esdhc *regs = priv->esdhc_regs;
368

369 370 371 372 373
#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111
	if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
		return 0;
#endif

374
	esdhc_write32(&regs->irqstat, -1);
375 376 377 378

	sync();

	/* Wait for the bus to be idle */
379 380 381
	while ((esdhc_read32(&regs->prsstat) & PRSSTAT_CICHB) ||
			(esdhc_read32(&regs->prsstat) & PRSSTAT_CIDHB))
		;
382

383 384
	while (esdhc_read32(&regs->prsstat) & PRSSTAT_DLA)
		;
385 386 387 388 389 390 391 392 393 394

	/* Wait at least 8 SD clock cycles before the next command */
	/*
	 * Note: This is way more than 8 cycles, but 1ms seems to
	 * resolve timing issues with some cards
	 */
	udelay(1000);

	/* Set up for a data transfer if we have one */
	if (data) {
395
		err = esdhc_setup_data(priv, mmc, data);
396 397
		if(err)
			return err;
398 399 400

		if (data->flags & MMC_DATA_READ)
			check_and_invalidate_dcache_range(cmd, data);
401 402 403 404 405
	}

	/* Figure out the transfer arguments */
	xfertyp = esdhc_xfertyp(cmd, data);

406 407 408
	/* Mask all irqs */
	esdhc_write32(&regs->irqsigen, 0);

409
	/* Send the command */
410
	esdhc_write32(&regs->cmdarg, cmd->cmdarg);
411 412
#if defined(CONFIG_FSL_USDHC)
	esdhc_write32(&regs->mixctrl,
413 414
	(esdhc_read32(&regs->mixctrl) & 0xFFFFFF80) | (xfertyp & 0x7F)
			| (mmc->ddr_mode ? XFERTYP_DDREN : 0));
415 416
	esdhc_write32(&regs->xfertyp, xfertyp & 0xFFFF0000);
#else
417
	esdhc_write32(&regs->xfertyp, xfertyp);
418
#endif
419

420
	/* Wait for the command to complete */
421
	while (!(esdhc_read32(&regs->irqstat) & (IRQSTAT_CC | IRQSTAT_CTOE)))
422
		;
423

424
	irqstat = esdhc_read32(&regs->irqstat);
425

426
	if (irqstat & CMD_ERR) {
427
		err = -ECOMM;
428
		goto out;
429 430
	}

431
	if (irqstat & IRQSTAT_CTOE) {
432
		err = -ETIMEDOUT;
433 434
		goto out;
	}
435

436 437 438 439 440 441 442 443 444
	/* Switch voltage to 1.8V if CMD11 succeeded */
	if (cmd->cmdidx == SD_CMD_SWITCH_UHS18V) {
		esdhc_setbits32(&regs->vendorspec, ESDHC_VENDORSPEC_VSELECT);

		printf("Run CMD11 1.8V switch\n");
		/* Sleep for 5 ms - max time for card to switch to 1.8V */
		udelay(5000);
	}

445 446
	/* Workaround for ESDHC errata ENGcm03648 */
	if (!data && (cmd->resp_type & MMC_RSP_BUSY)) {
447
		int timeout = 6000;
448

449
		/* Poll on DATA0 line for cmd with busy signal for 600 ms */
450 451 452 453 454 455 456 457
		while (timeout > 0 && !(esdhc_read32(&regs->prsstat) &
					PRSSTAT_DAT0)) {
			udelay(100);
			timeout--;
		}

		if (timeout <= 0) {
			printf("Timeout waiting for DAT0 to go high!\n");
458
			err = -ETIMEDOUT;
459
			goto out;
460 461 462
		}
	}

463 464 465 466
	/* Copy the response to the response buffer */
	if (cmd->resp_type & MMC_RSP_136) {
		u32 cmdrsp3, cmdrsp2, cmdrsp1, cmdrsp0;

467 468 469 470
		cmdrsp3 = esdhc_read32(&regs->cmdrsp3);
		cmdrsp2 = esdhc_read32(&regs->cmdrsp2);
		cmdrsp1 = esdhc_read32(&regs->cmdrsp1);
		cmdrsp0 = esdhc_read32(&regs->cmdrsp0);
R
Rabin Vincent 已提交
471 472 473 474
		cmd->response[0] = (cmdrsp3 << 8) | (cmdrsp2 >> 24);
		cmd->response[1] = (cmdrsp2 << 8) | (cmdrsp1 >> 24);
		cmd->response[2] = (cmdrsp1 << 8) | (cmdrsp0 >> 24);
		cmd->response[3] = (cmdrsp0 << 8);
475
	} else
476
		cmd->response[0] = esdhc_read32(&regs->cmdrsp0);
477 478 479

	/* Wait until all of the blocks are transferred */
	if (data) {
480
#ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO
481
		esdhc_pio_read_write(priv, data);
482
#else
483
		do {
484
			irqstat = esdhc_read32(&regs->irqstat);
485

486
			if (irqstat & IRQSTAT_DTOE) {
487
				err = -ETIMEDOUT;
488 489
				goto out;
			}
490

491
			if (irqstat & DATA_ERR) {
492
				err = -ECOMM;
493 494
				goto out;
			}
495
		} while ((irqstat & DATA_COMPLETE) != DATA_COMPLETE);
496

497 498 499 500 501
		/*
		 * Need invalidate the dcache here again to avoid any
		 * cache-fill during the DMA operations such as the
		 * speculative pre-fetching etc.
		 */
502 503
		if (data->flags & MMC_DATA_READ)
			check_and_invalidate_dcache_range(cmd, data);
504
#endif
505 506
	}

507 508 509 510 511 512 513 514 515 516 517 518 519 520 521
out:
	/* Reset CMD and DATA portions on error */
	if (err) {
		esdhc_write32(&regs->sysctl, esdhc_read32(&regs->sysctl) |
			      SYSCTL_RSTC);
		while (esdhc_read32(&regs->sysctl) & SYSCTL_RSTC)
			;

		if (data) {
			esdhc_write32(&regs->sysctl,
				      esdhc_read32(&regs->sysctl) |
				      SYSCTL_RSTD);
			while ((esdhc_read32(&regs->sysctl) & SYSCTL_RSTD))
				;
		}
522 523 524 525

		/* If this was CMD11, then notify that power cycle is needed */
		if (cmd->cmdidx == SD_CMD_SWITCH_UHS18V)
			printf("CMD11 to switch to 1.8V mode failed, card requires power cycle.\n");
526 527
	}

528
	esdhc_write32(&regs->irqstat, -1);
529

530
	return err;
531 532
}

533
static void set_sysctl(struct fsl_esdhc_priv *priv, struct mmc *mmc, uint clock)
534
{
535
	struct fsl_esdhc *regs = priv->esdhc_regs;
536 537
	int div = 1;
#ifdef ARCH_MXC
538 539 540 541
#ifdef CONFIG_MX53
	/* For i.MX53 eSDHCv3, SYSCTL.SDCLKFS may not be set to 0. */
	int pre_div = (regs == (struct fsl_esdhc *)MMC_SDHC3_BASE_ADDR) ? 2 : 1;
#else
542
	int pre_div = 1;
543
#endif
544 545 546 547
#else
	int pre_div = 2;
#endif
	int ddr_pre_div = mmc->ddr_mode ? 2 : 1;
P
Peng Fan 已提交
548
	int sdhc_clk = priv->sdhc_clk;
549 550
	uint clk;

551 552
	if (clock < mmc->cfg->f_min)
		clock = mmc->cfg->f_min;
553

554 555
	while (sdhc_clk / (16 * pre_div * ddr_pre_div) > clock && pre_div < 256)
		pre_div *= 2;
556

557 558
	while (sdhc_clk / (div * pre_div * ddr_pre_div) > clock && div < 16)
		div++;
559

560
	pre_div >>= 1;
561 562 563 564
	div -= 1;

	clk = (pre_div << 8) | (div << 4);

565
#ifdef CONFIG_FSL_USDHC
566
	esdhc_clrbits32(&regs->vendorspec, VENDORSPEC_CKEN);
567
#else
568
	esdhc_clrbits32(&regs->sysctl, SYSCTL_CKEN);
569
#endif
570 571

	esdhc_clrsetbits32(&regs->sysctl, SYSCTL_CLOCK_MASK, clk);
572 573 574

	udelay(10000);

575
#ifdef CONFIG_FSL_USDHC
576
	esdhc_setbits32(&regs->vendorspec, VENDORSPEC_PEREN | VENDORSPEC_CKEN);
577 578 579
#else
	esdhc_setbits32(&regs->sysctl, SYSCTL_PEREN | SYSCTL_CKEN);
#endif
580

581 582
}

583
#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
584
static void esdhc_clock_control(struct fsl_esdhc_priv *priv, bool enable)
585
{
P
Peng Fan 已提交
586
	struct fsl_esdhc *regs = priv->esdhc_regs;
587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611
	u32 value;
	u32 time_out;

	value = esdhc_read32(&regs->sysctl);

	if (enable)
		value |= SYSCTL_CKEN;
	else
		value &= ~SYSCTL_CKEN;

	esdhc_write32(&regs->sysctl, value);

	time_out = 20;
	value = PRSSTAT_SDSTB;
	while (!(esdhc_read32(&regs->prsstat) & value)) {
		if (time_out == 0) {
			printf("fsl_esdhc: Internal clock never stabilised.\n");
			break;
		}
		time_out--;
		mdelay(1);
	}
}
#endif

612
static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
613
{
P
Peng Fan 已提交
614
	struct fsl_esdhc *regs = priv->esdhc_regs;
615

616 617
#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
	/* Select to use peripheral clock */
618
	esdhc_clock_control(priv, false);
619
	esdhc_setbits32(&regs->scr, ESDHCCTL_PCS);
620
	esdhc_clock_control(priv, true);
621
#endif
622
	/* Set the clock speed */
623
	set_sysctl(priv, mmc, mmc->clock);
624 625

	/* Set the bus width */
626
	esdhc_clrbits32(&regs->proctl, PROCTL_DTW_4 | PROCTL_DTW_8);
627 628

	if (mmc->bus_width == 4)
629
		esdhc_setbits32(&regs->proctl, PROCTL_DTW_4);
630
	else if (mmc->bus_width == 8)
631 632
		esdhc_setbits32(&regs->proctl, PROCTL_DTW_8);

633
	return 0;
634 635
}

636
static int esdhc_init_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
637
{
P
Peng Fan 已提交
638
	struct fsl_esdhc *regs = priv->esdhc_regs;
639
	ulong start;
640

641
	/* Reset the entire host controller */
642
	esdhc_setbits32(&regs->sysctl, SYSCTL_RSTA);
643 644

	/* Wait until the controller is available */
645 646 647 648 649
	start = get_timer(0);
	while ((esdhc_read32(&regs->sysctl) & SYSCTL_RSTA)) {
		if (get_timer(start) > 1000)
			return -ETIMEDOUT;
	}
650

651 652 653 654 655 656 657 658
#if defined(CONFIG_FSL_USDHC)
	/* RSTA doesn't reset MMC_BOOT register, so manually reset it */
	esdhc_write32(&regs->mmcboot, 0x0);
	/* Reset MIX_CTRL and CLK_TUNE_CTRL_STATUS regs to 0 */
	esdhc_write32(&regs->mixctrl, 0x0);
	esdhc_write32(&regs->clktunectrlstatus, 0x0);

	/* Put VEND_SPEC to default value */
659 660 661 662 663
	if (priv->vs18_enable)
		esdhc_write32(&regs->vendorspec, (VENDORSPEC_INIT |
			      ESDHC_VENDORSPEC_VSELECT));
	else
		esdhc_write32(&regs->vendorspec, VENDORSPEC_INIT);
664 665 666 667 668

	/* Disable DLL_CTRL delay line */
	esdhc_write32(&regs->dllctrl, 0x0);
#endif

669
#ifndef ARCH_MXC
670
	/* Enable cache snooping */
671 672
	esdhc_write32(&regs->scr, 0x00000040);
#endif
673

674
#ifndef CONFIG_FSL_USDHC
675
	esdhc_setbits32(&regs->sysctl, SYSCTL_HCKEN | SYSCTL_IPGEN);
676 677
#else
	esdhc_setbits32(&regs->vendorspec, VENDORSPEC_HCKEN | VENDORSPEC_IPGEN);
678
#endif
679 680

	/* Set the initial clock speed */
681
	mmc_set_clock(mmc, 400000, false);
682 683

	/* Disable the BRR and BWR bits in IRQSTAT */
684
	esdhc_clrbits32(&regs->irqstaten, IRQSTATEN_BRR | IRQSTATEN_BWR);
685 686

	/* Put the PROCTL reg back to the default */
687
	esdhc_write32(&regs->proctl, PROCTL_INIT);
688

689 690
	/* Set timout to the maximum value */
	esdhc_clrsetbits32(&regs->sysctl, SYSCTL_TIMEOUT_MASK, 14 << 16);
691

692 693
	return 0;
}
694

695
static int esdhc_getcd_common(struct fsl_esdhc_priv *priv)
696
{
P
Peng Fan 已提交
697
	struct fsl_esdhc *regs = priv->esdhc_regs;
698 699
	int timeout = 1000;

700 701 702 703
#ifdef CONFIG_ESDHC_DETECT_QUIRK
	if (CONFIG_ESDHC_DETECT_QUIRK)
		return 1;
#endif
P
Peng Fan 已提交
704

705
#if CONFIG_IS_ENABLED(DM_MMC)
P
Peng Fan 已提交
706 707
	if (priv->non_removable)
		return 1;
708
#ifdef CONFIG_DM_GPIO
P
Peng Fan 已提交
709 710
	if (dm_gpio_is_valid(&priv->cd_gpio))
		return dm_gpio_get_value(&priv->cd_gpio);
711
#endif
P
Peng Fan 已提交
712 713
#endif

714 715
	while (!(esdhc_read32(&regs->prsstat) & PRSSTAT_CINS) && --timeout)
		udelay(1000);
716

717
	return timeout > 0;
718 719
}

720
static int esdhc_reset(struct fsl_esdhc *regs)
721
{
722
	ulong start;
723 724

	/* reset the controller */
725
	esdhc_setbits32(&regs->sysctl, SYSCTL_RSTA);
726 727

	/* hardware clears the bit when it is done */
728 729 730 731 732 733 734 735 736
	start = get_timer(0);
	while ((esdhc_read32(&regs->sysctl) & SYSCTL_RSTA)) {
		if (get_timer(start) > 100) {
			printf("MMC/SD: Reset never completed.\n");
			return -ETIMEDOUT;
		}
	}

	return 0;
737 738
}

S
Simon Glass 已提交
739
#if !CONFIG_IS_ENABLED(DM_MMC)
740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768
static int esdhc_getcd(struct mmc *mmc)
{
	struct fsl_esdhc_priv *priv = mmc->priv;

	return esdhc_getcd_common(priv);
}

static int esdhc_init(struct mmc *mmc)
{
	struct fsl_esdhc_priv *priv = mmc->priv;

	return esdhc_init_common(priv, mmc);
}

static int esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
			  struct mmc_data *data)
{
	struct fsl_esdhc_priv *priv = mmc->priv;

	return esdhc_send_cmd_common(priv, mmc, cmd, data);
}

static int esdhc_set_ios(struct mmc *mmc)
{
	struct fsl_esdhc_priv *priv = mmc->priv;

	return esdhc_set_ios_common(priv, mmc);
}

769
static const struct mmc_ops esdhc_ops = {
770 771
	.getcd		= esdhc_getcd,
	.init		= esdhc_init,
772 773 774
	.send_cmd	= esdhc_send_cmd,
	.set_ios	= esdhc_set_ios,
};
775
#endif
776

777 778
static int fsl_esdhc_init(struct fsl_esdhc_priv *priv,
			  struct fsl_esdhc_plat *plat)
779
{
780
	struct mmc_config *cfg;
781
	struct fsl_esdhc *regs;
782
	u32 caps, voltage_caps;
783
	int ret;
784

P
Peng Fan 已提交
785 786
	if (!priv)
		return -EINVAL;
787

P
Peng Fan 已提交
788
	regs = priv->esdhc_regs;
789

790
	/* First reset the eSDHC controller */
791 792 793
	ret = esdhc_reset(regs);
	if (ret)
		return ret;
794

795
#ifndef CONFIG_FSL_USDHC
796 797
	esdhc_setbits32(&regs->sysctl, SYSCTL_PEREN | SYSCTL_HCKEN
				| SYSCTL_IPGEN | SYSCTL_CKEN);
798 799 800
#else
	esdhc_setbits32(&regs->vendorspec, VENDORSPEC_PEREN |
			VENDORSPEC_HCKEN | VENDORSPEC_IPGEN | VENDORSPEC_CKEN);
801
#endif
802

803 804 805
	if (priv->vs18_enable)
		esdhc_setbits32(&regs->vendorspec, ESDHC_VENDORSPEC_VSELECT);

806
	writel(SDHCI_IRQ_EN_BITS, &regs->irqstaten);
807
	cfg = &plat->cfg;
808
#ifndef CONFIG_DM_MMC
809
	memset(cfg, '\0', sizeof(*cfg));
810
#endif
811

812
	voltage_caps = 0;
813
	caps = esdhc_read32(&regs->hostcapblt);
814 815 816 817 818

#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC135
	caps = caps & ~(ESDHC_HOSTCAPBLT_SRS |
			ESDHC_HOSTCAPBLT_VS18 | ESDHC_HOSTCAPBLT_VS30);
#endif
819 820 821 822 823 824

/* T4240 host controller capabilities register should have VS33 bit */
#ifdef CONFIG_SYS_FSL_MMC_HAS_CAPBLT_VS33
	caps = caps | ESDHC_HOSTCAPBLT_VS33;
#endif

825
	if (caps & ESDHC_HOSTCAPBLT_VS18)
826
		voltage_caps |= MMC_VDD_165_195;
827
	if (caps & ESDHC_HOSTCAPBLT_VS30)
828
		voltage_caps |= MMC_VDD_29_30 | MMC_VDD_30_31;
829
	if (caps & ESDHC_HOSTCAPBLT_VS33)
830 831
		voltage_caps |= MMC_VDD_32_33 | MMC_VDD_33_34;

832
	cfg->name = "FSL_SDHC";
S
Simon Glass 已提交
833
#if !CONFIG_IS_ENABLED(DM_MMC)
834
	cfg->ops = &esdhc_ops;
835
#endif
836
#ifdef CONFIG_SYS_SD_VOLTAGE
837
	cfg->voltages = CONFIG_SYS_SD_VOLTAGE;
838
#else
839
	cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
840
#endif
841
	if ((cfg->voltages & voltage_caps) == 0) {
842 843 844
		printf("voltage not supported by controller\n");
		return -1;
	}
845

P
Peng Fan 已提交
846
	if (priv->bus_width == 8)
847
		cfg->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT;
P
Peng Fan 已提交
848
	else if (priv->bus_width == 4)
849
		cfg->host_caps = MMC_MODE_4BIT;
P
Peng Fan 已提交
850

851
	cfg->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT;
852
#ifdef CONFIG_SYS_FSL_ESDHC_HAS_DDR_MODE
853
	cfg->host_caps |= MMC_MODE_DDR_52MHz;
854
#endif
855

P
Peng Fan 已提交
856 857
	if (priv->bus_width > 0) {
		if (priv->bus_width < 8)
858
			cfg->host_caps &= ~MMC_MODE_8BIT;
P
Peng Fan 已提交
859
		if (priv->bus_width < 4)
860
			cfg->host_caps &= ~MMC_MODE_4BIT;
861 862
	}

863
	if (caps & ESDHC_HOSTCAPBLT_HSS)
864
		cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
865

866 867
#ifdef CONFIG_ESDHC_DETECT_8_BIT_QUIRK
	if (CONFIG_ESDHC_DETECT_8_BIT_QUIRK)
868
		cfg->host_caps &= ~MMC_MODE_8BIT;
869 870
#endif

871 872
	cfg->f_min = 400000;
	cfg->f_max = min(priv->sdhc_clk, (u32)52000000);
873

874
	cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
875

P
Peng Fan 已提交
876 877 878
	return 0;
}

879
#if !CONFIG_IS_ENABLED(DM_MMC)
880 881 882 883 884 885 886 887 888 889
static int fsl_esdhc_cfg_to_priv(struct fsl_esdhc_cfg *cfg,
				 struct fsl_esdhc_priv *priv)
{
	if (!cfg || !priv)
		return -EINVAL;

	priv->esdhc_regs = (struct fsl_esdhc *)(unsigned long)(cfg->esdhc_base);
	priv->bus_width = cfg->max_bus_width;
	priv->sdhc_clk = cfg->sdhc_clk;
	priv->wp_enable  = cfg->wp_enable;
890
	priv->vs18_enable  = cfg->vs18_enable;
891 892 893 894

	return 0;
};

P
Peng Fan 已提交
895 896
int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
{
897
	struct fsl_esdhc_plat *plat;
P
Peng Fan 已提交
898
	struct fsl_esdhc_priv *priv;
899
	struct mmc *mmc;
P
Peng Fan 已提交
900 901 902 903 904 905 906 907
	int ret;

	if (!cfg)
		return -EINVAL;

	priv = calloc(sizeof(struct fsl_esdhc_priv), 1);
	if (!priv)
		return -ENOMEM;
908 909 910 911 912
	plat = calloc(sizeof(struct fsl_esdhc_plat), 1);
	if (!plat) {
		free(priv);
		return -ENOMEM;
	}
P
Peng Fan 已提交
913 914 915 916

	ret = fsl_esdhc_cfg_to_priv(cfg, priv);
	if (ret) {
		debug("%s xlate failure\n", __func__);
917
		free(plat);
P
Peng Fan 已提交
918 919 920 921
		free(priv);
		return ret;
	}

922
	ret = fsl_esdhc_init(priv, plat);
P
Peng Fan 已提交
923 924
	if (ret) {
		debug("%s init failure\n", __func__);
925
		free(plat);
P
Peng Fan 已提交
926 927 928 929
		free(priv);
		return ret;
	}

930 931 932 933 934 935
	mmc = mmc_create(&plat->cfg, priv);
	if (!mmc)
		return -EIO;

	priv->mmc = mmc;

936 937 938 939 940
	return 0;
}

int fsl_esdhc_mmc_init(bd_t *bis)
{
941 942
	struct fsl_esdhc_cfg *cfg;

F
Fabio Estevam 已提交
943
	cfg = calloc(sizeof(struct fsl_esdhc_cfg), 1);
944
	cfg->esdhc_base = CONFIG_SYS_FSL_ESDHC_ADDR;
945
	cfg->sdhc_clk = gd->arch.sdhc_clk;
946
	return fsl_esdhc_initialize(bis, cfg);
947
}
948
#endif
949

950 951 952 953 954 955 956 957 958 959 960
#ifdef CONFIG_FSL_ESDHC_ADAPTER_IDENT
void mmc_adapter_card_type_ident(void)
{
	u8 card_id;
	u8 value;

	card_id = QIXIS_READ(present) & QIXIS_SDID_MASK;
	gd->arch.sdhc_adapter = card_id;

	switch (card_id) {
	case QIXIS_ESDHC_ADAPTER_TYPE_EMMC45:
961 962 963
		value = QIXIS_READ(brdcfg[5]);
		value |= (QIXIS_DAT4 | QIXIS_DAT5_6_7);
		QIXIS_WRITE(brdcfg[5], value);
964 965
		break;
	case QIXIS_ESDHC_ADAPTER_TYPE_SDMMC_LEGACY:
966 967 968
		value = QIXIS_READ(pwr_ctl[1]);
		value |= QIXIS_EVDD_BY_SDHC_VS;
		QIXIS_WRITE(pwr_ctl[1], value);
969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988
		break;
	case QIXIS_ESDHC_ADAPTER_TYPE_EMMC44:
		value = QIXIS_READ(brdcfg[5]);
		value |= (QIXIS_SDCLKIN | QIXIS_SDCLKOUT);
		QIXIS_WRITE(brdcfg[5], value);
		break;
	case QIXIS_ESDHC_ADAPTER_TYPE_RSV:
		break;
	case QIXIS_ESDHC_ADAPTER_TYPE_MMC:
		break;
	case QIXIS_ESDHC_ADAPTER_TYPE_SD:
		break;
	case QIXIS_ESDHC_NO_ADAPTER:
		break;
	default:
		break;
	}
}
#endif

989
#ifdef CONFIG_OF_LIBFDT
990
__weak int esdhc_status_fixup(void *blob, const char *compat)
991
{
992
#ifdef CONFIG_FSL_ESDHC_PIN_MUX
993
	if (!hwconfig("esdhc")) {
994
		do_fixup_by_compat(blob, compat, "status", "disabled",
995 996
				sizeof("disabled"), 1);
		return 1;
997
	}
998
#endif
999 1000 1001 1002 1003 1004 1005 1006 1007
	return 0;
}

void fdt_fixup_esdhc(void *blob, bd_t *bd)
{
	const char *compat = "fsl,esdhc";

	if (esdhc_status_fixup(blob, compat))
		return;
1008

1009 1010 1011 1012
#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
	do_fixup_by_compat_u32(blob, compat, "peripheral-frequency",
			       gd->arch.sdhc_clk, 1);
#else
1013
	do_fixup_by_compat_u32(blob, compat, "clock-frequency",
1014
			       gd->arch.sdhc_clk, 1);
1015
#endif
1016 1017 1018 1019
#ifdef CONFIG_FSL_ESDHC_ADAPTER_IDENT
	do_fixup_by_compat_u32(blob, compat, "adapter-type",
			       (u32)(gd->arch.sdhc_adapter), 1);
#endif
1020
}
1021
#endif
P
Peng Fan 已提交
1022

1023
#if CONFIG_IS_ENABLED(DM_MMC)
P
Peng Fan 已提交
1024
#include <asm/arch/clock.h>
P
Peng Fan 已提交
1025 1026 1027 1028
__weak void init_clk_usdhc(u32 index)
{
}

P
Peng Fan 已提交
1029 1030 1031
static int fsl_esdhc_probe(struct udevice *dev)
{
	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
1032
	struct fsl_esdhc_plat *plat = dev_get_platdata(dev);
P
Peng Fan 已提交
1033
	struct fsl_esdhc_priv *priv = dev_get_priv(dev);
1034
#ifdef CONFIG_DM_REGULATOR
1035
	struct udevice *vqmmc_dev;
1036
#endif
P
Peng Fan 已提交
1037 1038
	fdt_addr_t addr;
	unsigned int val;
1039
	struct mmc *mmc;
P
Peng Fan 已提交
1040 1041
	int ret;

1042
	addr = dev_read_addr(dev);
P
Peng Fan 已提交
1043 1044 1045 1046 1047 1048
	if (addr == FDT_ADDR_T_NONE)
		return -EINVAL;

	priv->esdhc_regs = (struct fsl_esdhc *)addr;
	priv->dev = dev;

1049
	val = dev_read_u32_default(dev, "bus-width", -1);
P
Peng Fan 已提交
1050 1051 1052 1053 1054 1055 1056
	if (val == 8)
		priv->bus_width = 8;
	else if (val == 4)
		priv->bus_width = 4;
	else
		priv->bus_width = 1;

1057
	if (dev_read_bool(dev, "non-removable")) {
P
Peng Fan 已提交
1058 1059 1060
		priv->non_removable = 1;
	 } else {
		priv->non_removable = 0;
1061
#ifdef CONFIG_DM_GPIO
1062 1063
		gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio,
				     GPIOD_IS_IN);
1064
#endif
P
Peng Fan 已提交
1065 1066
	}

P
Peng Fan 已提交
1067 1068
	priv->wp_enable = 1;

1069
#ifdef CONFIG_DM_GPIO
1070 1071
	ret = gpio_request_by_name(dev, "wp-gpios", 0, &priv->wp_gpio,
				   GPIOD_IS_IN);
P
Peng Fan 已提交
1072 1073
	if (ret)
		priv->wp_enable = 0;
1074
#endif
1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097

	priv->vs18_enable = 0;

#ifdef CONFIG_DM_REGULATOR
	/*
	 * If emmc I/O has a fixed voltage at 1.8V, this must be provided,
	 * otherwise, emmc will work abnormally.
	 */
	ret = device_get_supply_regulator(dev, "vqmmc-supply", &vqmmc_dev);
	if (ret) {
		dev_dbg(dev, "no vqmmc-supply\n");
	} else {
		ret = regulator_set_enable(vqmmc_dev, true);
		if (ret) {
			dev_err(dev, "fail to enable vqmmc-supply\n");
			return ret;
		}

		if (regulator_get_value(vqmmc_dev) == 1800000)
			priv->vs18_enable = 1;
	}
#endif

P
Peng Fan 已提交
1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116
	/*
	 * TODO:
	 * Because lack of clk driver, if SDHC clk is not enabled,
	 * need to enable it first before this driver is invoked.
	 *
	 * we use MXC_ESDHC_CLK to get clk freq.
	 * If one would like to make this function work,
	 * the aliases should be provided in dts as this:
	 *
	 *  aliases {
	 *	mmc0 = &usdhc1;
	 *	mmc1 = &usdhc2;
	 *	mmc2 = &usdhc3;
	 *	mmc3 = &usdhc4;
	 *	};
	 * Then if your board only supports mmc2 and mmc3, but we can
	 * correctly get the seq as 2 and 3, then let mxc_get_clock
	 * work as expected.
	 */
P
Peng Fan 已提交
1117 1118 1119

	init_clk_usdhc(dev->seq);

P
Peng Fan 已提交
1120 1121 1122 1123 1124 1125
	priv->sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK + dev->seq);
	if (priv->sdhc_clk <= 0) {
		dev_err(dev, "Unable to get clk for %s\n", dev->name);
		return -EINVAL;
	}

1126
	ret = fsl_esdhc_init(priv, plat);
P
Peng Fan 已提交
1127 1128 1129 1130 1131
	if (ret) {
		dev_err(dev, "fsl_esdhc_init failure\n");
		return ret;
	}

1132 1133 1134 1135
	mmc = &plat->mmc;
	mmc->cfg = &plat->cfg;
	mmc->dev = dev;
	upriv->mmc = mmc;
P
Peng Fan 已提交
1136

1137
	return esdhc_init_common(priv, mmc);
P
Peng Fan 已提交
1138 1139
}

S
Simon Glass 已提交
1140
#if CONFIG_IS_ENABLED(DM_MMC)
1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172
static int fsl_esdhc_get_cd(struct udevice *dev)
{
	struct fsl_esdhc_priv *priv = dev_get_priv(dev);

	return true;
	return esdhc_getcd_common(priv);
}

static int fsl_esdhc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
			      struct mmc_data *data)
{
	struct fsl_esdhc_plat *plat = dev_get_platdata(dev);
	struct fsl_esdhc_priv *priv = dev_get_priv(dev);

	return esdhc_send_cmd_common(priv, &plat->mmc, cmd, data);
}

static int fsl_esdhc_set_ios(struct udevice *dev)
{
	struct fsl_esdhc_plat *plat = dev_get_platdata(dev);
	struct fsl_esdhc_priv *priv = dev_get_priv(dev);

	return esdhc_set_ios_common(priv, &plat->mmc);
}

static const struct dm_mmc_ops fsl_esdhc_ops = {
	.get_cd		= fsl_esdhc_get_cd,
	.send_cmd	= fsl_esdhc_send_cmd,
	.set_ios	= fsl_esdhc_set_ios,
};
#endif

P
Peng Fan 已提交
1173 1174 1175 1176 1177 1178
static const struct udevice_id fsl_esdhc_ids[] = {
	{ .compatible = "fsl,imx6ul-usdhc", },
	{ .compatible = "fsl,imx6sx-usdhc", },
	{ .compatible = "fsl,imx6sl-usdhc", },
	{ .compatible = "fsl,imx6q-usdhc", },
	{ .compatible = "fsl,imx7d-usdhc", },
P
Peng Fan 已提交
1179
	{ .compatible = "fsl,imx7ulp-usdhc", },
1180
	{ .compatible = "fsl,esdhc", },
P
Peng Fan 已提交
1181 1182 1183
	{ /* sentinel */ }
};

1184 1185 1186 1187 1188 1189 1190 1191 1192
#if CONFIG_IS_ENABLED(BLK)
static int fsl_esdhc_bind(struct udevice *dev)
{
	struct fsl_esdhc_plat *plat = dev_get_platdata(dev);

	return mmc_bind(dev, &plat->mmc, &plat->cfg);
}
#endif

P
Peng Fan 已提交
1193 1194 1195 1196
U_BOOT_DRIVER(fsl_esdhc) = {
	.name	= "fsl-esdhc-mmc",
	.id	= UCLASS_MMC,
	.of_match = fsl_esdhc_ids,
1197 1198 1199 1200
	.ops	= &fsl_esdhc_ops,
#if CONFIG_IS_ENABLED(BLK)
	.bind	= fsl_esdhc_bind,
#endif
P
Peng Fan 已提交
1201
	.probe	= fsl_esdhc_probe,
1202
	.platdata_auto_alloc_size = sizeof(struct fsl_esdhc_plat),
P
Peng Fan 已提交
1203 1204 1205
	.priv_auto_alloc_size = sizeof(struct fsl_esdhc_priv),
};
#endif