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

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

DECLARE_GLOBAL_DATA_PTR;

struct fsl_esdhc {
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
	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 */
Y
Yangbo Lu 已提交
47
	char    reserved1[8];	/* reserved */
48 49 50
	uint    fevt;		/* Force event register */
	uint    admaes;		/* ADMA error status register */
	uint    adsaddr;	/* ADMA system address register */
Y
Yangbo Lu 已提交
51
	char    reserved2[160];
52
	uint    hostver;	/* Host controller version register */
Y
Yangbo Lu 已提交
53
	char    reserved3[4];	/* reserved */
54
	uint    dmaerraddr;	/* DMA error address register */
Y
Yangbo Lu 已提交
55
	char    reserved4[4];	/* reserved */
56
	uint    dmaerrattr;	/* DMA error attribute register */
Y
Yangbo Lu 已提交
57
	char    reserved5[4];	/* reserved */
58
	uint    hostcapblt2;	/* Host controller capabilities register 2 */
Y
Yangbo Lu 已提交
59 60
	char    reserved6[756];	/* reserved */
	uint    esdhcctl;	/* eSDHC control register */
61 62
};

63 64 65 66 67
struct fsl_esdhc_plat {
	struct mmc_config cfg;
	struct mmc mmc;
};

P
Peng Fan 已提交
68 69 70 71 72 73 74 75 76 77 78
/**
 * 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 已提交
79
 * @wp_enable: 1: enable checking wp; 0: no check
P
Peng Fan 已提交
80
 * @cd_gpio: gpio for card detection
P
Peng Fan 已提交
81
 * @wp_gpio: gpio for write protection
P
Peng Fan 已提交
82 83 84 85
 */
struct fsl_esdhc_priv {
	struct fsl_esdhc *esdhc_regs;
	unsigned int sdhc_clk;
P
Peng Fan 已提交
86
	struct clk per_clk;
87
	unsigned int clock;
P
Peng Fan 已提交
88
	unsigned int bus_width;
89
#if !CONFIG_IS_ENABLED(DM_MMC)
P
Peng Fan 已提交
90
	struct mmc *mmc;
91
#endif
P
Peng Fan 已提交
92 93
	struct udevice *dev;
	int non_removable;
P
Peng Fan 已提交
94
	int wp_enable;
P
Peng Fan 已提交
95 96
};

97
/* Return the XFERTYP flags for a given command and data packet */
98
static uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data)
99 100 101 102
{
	uint xfertyp = 0;

	if (data) {
103 104 105 106
		xfertyp |= XFERTYP_DPSEL;
#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
		xfertyp |= XFERTYP_DMAEN;
#endif
107 108 109
		if (data->blocks > 1) {
			xfertyp |= XFERTYP_MSBSEL;
			xfertyp |= XFERTYP_BCEN;
110 111 112
#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111
			xfertyp |= XFERTYP_AC12EN;
#endif
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
		}

		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;

130 131
	if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
		xfertyp |= XFERTYP_CMDTYP_ABORT;
132

133 134 135
	return XFERTYP_CMD(cmd->cmdidx) | xfertyp;
}

136 137 138 139
#ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO
/*
 * PIO Read/Write Mode reduce the performace as DMA is not used in this mode.
 */
140 141
static void esdhc_pio_read_write(struct fsl_esdhc_priv *priv,
				 struct mmc_data *data)
142
{
P
Peng Fan 已提交
143
	struct fsl_esdhc *regs = priv->esdhc_regs;
144 145 146 147 148
	uint blocks;
	char *buffer;
	uint databuf;
	uint size;
	uint irqstat;
149
	ulong start;
150 151 152 153 154

	if (data->flags & MMC_DATA_READ) {
		blocks = data->blocks;
		buffer = data->dest;
		while (blocks) {
155
			start = get_timer(0);
156 157
			size = data->blocksize;
			irqstat = esdhc_read32(&regs->irqstat);
158 159 160 161 162
			while (!(esdhc_read32(&regs->prsstat) & PRSSTAT_BREN)) {
				if (get_timer(start) > PIO_TIMEOUT) {
					printf("\nData Read Failed in PIO Mode.");
					return;
				}
163 164 165 166 167 168 169 170 171 172 173 174 175
			}
			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;
176
		buffer = (char *)data->src;
177
		while (blocks) {
178
			start = get_timer(0);
179 180
			size = data->blocksize;
			irqstat = esdhc_read32(&regs->irqstat);
181 182 183 184 185
			while (!(esdhc_read32(&regs->prsstat) & PRSSTAT_BWEN)) {
				if (get_timer(start) > PIO_TIMEOUT) {
					printf("\nData Write Failed in PIO Mode.");
					return;
				}
186 187 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 */
				databuf = *((uint *)buffer);
				buffer += 4;
				size -= 4;
				irqstat = esdhc_read32(&regs->irqstat);
				out_le32(&regs->datport, databuf);
			}
			blocks--;
		}
	}
}
#endif

201 202
static int esdhc_setup_data(struct fsl_esdhc_priv *priv, struct mmc *mmc,
			    struct mmc_data *data)
203 204
{
	int timeout;
P
Peng Fan 已提交
205
	struct fsl_esdhc *regs = priv->esdhc_regs;
Y
Yangbo Lu 已提交
206
#if defined(CONFIG_FSL_LAYERSCAPE)
207 208
	dma_addr_t addr;
#endif
209
	uint wml_value;
210 211 212 213

	wml_value = data->blocksize/4;

	if (data->flags & MMC_DATA_READ) {
214 215
		if (wml_value > WML_RD_WML_MAX)
			wml_value = WML_RD_WML_MAX_VAL;
216

217
		esdhc_clrsetbits32(&regs->wml, WML_RD_WML_MASK, wml_value);
218
#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
Y
Yangbo Lu 已提交
219
#if defined(CONFIG_FSL_LAYERSCAPE)
220 221 222 223 224 225
		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
226
		esdhc_write32(&regs->dsaddr, (u32)data->dest);
227
#endif
228
#endif
229
	} else {
230
#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
231 232 233
		flush_dcache_range((ulong)data->src,
				   (ulong)data->src+data->blocks
					 *data->blocksize);
234
#endif
235 236
		if (wml_value > WML_WR_WML_MAX)
			wml_value = WML_WR_WML_MAX_VAL;
P
Peng Fan 已提交
237 238 239 240
		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");
241
				return -ETIMEDOUT;
P
Peng Fan 已提交
242
			}
243
		}
244 245 246

		esdhc_clrsetbits32(&regs->wml, WML_WR_WML_MASK,
					wml_value << 16);
247
#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
Y
Yangbo Lu 已提交
248
#if defined(CONFIG_FSL_LAYERSCAPE)
249 250 251 252 253 254
		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
255
		esdhc_write32(&regs->dsaddr, (u32)data->src);
256
#endif
257
#endif
258 259
	}

260
	esdhc_write32(&regs->blkattr, data->blocks << 16 | data->blocksize);
261 262

	/* Calculate the timeout period for data transactions */
263 264 265 266 267
	/*
	 * 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
268
	 *		= (mmc->clock * 1/4) SD Clock cycles
269
	 * As 1) >=  2)
270
	 * => (2^(timeout+13)) >= mmc->clock * 1/4
271
	 * Taking log2 both the sides
272
	 * => timeout + 13 >= log2(mmc->clock/4)
273
	 * Rounding up to next power of 2
274 275
	 * => timeout + 13 = log2(mmc->clock/4) + 1
	 * => timeout + 13 = fls(mmc->clock/4)
276 277 278 279 280 281 282
	 *
	 * 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)
283
	 */
284
	timeout = fls(mmc->clock/2);
285 286 287 288 289 290 291 292
	timeout -= 13;

	if (timeout > 14)
		timeout = 14;

	if (timeout < 0)
		timeout = 0;

293 294 295 296 297
#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC_A001
	if ((timeout == 4) || (timeout == 8) || (timeout == 12))
		timeout++;
#endif

298 299 300
#ifdef ESDHCI_QUIRK_BROKEN_TIMEOUT_VALUE
	timeout = 0xE;
#endif
301
	esdhc_clrsetbits32(&regs->sysctl, SYSCTL_TIMEOUT_MASK, timeout << 16);
302 303 304 305

	return 0;
}

306 307 308
static void check_and_invalidate_dcache_range
	(struct mmc_cmd *cmd,
	 struct mmc_data *data) {
309
	unsigned start = 0;
310
	unsigned end = 0;
311 312
	unsigned size = roundup(ARCH_DMA_MINALIGN,
				data->blocks*data->blocksize);
Y
Yangbo Lu 已提交
313
#if defined(CONFIG_FSL_LAYERSCAPE)
314 315 316 317 318 319 320
	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);
321 322
#else
	start = (unsigned)data->dest;
323
#endif
324
	end = start + size;
325 326
	invalidate_dcache_range(start, end);
}
327

328 329 330 331
/*
 * Sends a command out on the bus.  Takes the mmc pointer,
 * a command pointer, and an optional data pointer.
 */
332 333
static int esdhc_send_cmd_common(struct fsl_esdhc_priv *priv, struct mmc *mmc,
				 struct mmc_cmd *cmd, struct mmc_data *data)
334
{
335
	int	err = 0;
336 337
	uint	xfertyp;
	uint	irqstat;
338
	u32	flags = IRQSTAT_CC | IRQSTAT_CTOE;
P
Peng Fan 已提交
339
	struct fsl_esdhc *regs = priv->esdhc_regs;
340
	unsigned long start;
341

342 343 344 345 346
#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111
	if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
		return 0;
#endif

347
	esdhc_write32(&regs->irqstat, -1);
348 349 350 351

	sync();

	/* Wait for the bus to be idle */
352 353 354
	while ((esdhc_read32(&regs->prsstat) & PRSSTAT_CICHB) ||
			(esdhc_read32(&regs->prsstat) & PRSSTAT_CIDHB))
		;
355

356 357
	while (esdhc_read32(&regs->prsstat) & PRSSTAT_DLA)
		;
358 359 360 361 362 363 364 365 366 367

	/* 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) {
368
		err = esdhc_setup_data(priv, mmc, data);
369 370
		if(err)
			return err;
371 372 373

		if (data->flags & MMC_DATA_READ)
			check_and_invalidate_dcache_range(cmd, data);
374 375 376 377 378
	}

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

379 380 381
	/* Mask all irqs */
	esdhc_write32(&regs->irqsigen, 0);

382
	/* Send the command */
383 384
	esdhc_write32(&regs->cmdarg, cmd->cmdarg);
	esdhc_write32(&regs->xfertyp, xfertyp);
385

386
	/* Wait for the command to complete */
387 388 389 390 391 392 393
	start = get_timer(0);
	while (!(esdhc_read32(&regs->irqstat) & flags)) {
		if (get_timer(start) > 1000) {
			err = -ETIMEDOUT;
			goto out;
		}
	}
394

395
	irqstat = esdhc_read32(&regs->irqstat);
396

397
	if (irqstat & CMD_ERR) {
398
		err = -ECOMM;
399
		goto out;
400 401
	}

402
	if (irqstat & IRQSTAT_CTOE) {
403
		err = -ETIMEDOUT;
404 405
		goto out;
	}
406

407 408
	/* Workaround for ESDHC errata ENGcm03648 */
	if (!data && (cmd->resp_type & MMC_RSP_BUSY)) {
409
		int timeout = 6000;
410

411
		/* Poll on DATA0 line for cmd with busy signal for 600 ms */
412 413 414 415 416 417 418 419
		while (timeout > 0 && !(esdhc_read32(&regs->prsstat) &
					PRSSTAT_DAT0)) {
			udelay(100);
			timeout--;
		}

		if (timeout <= 0) {
			printf("Timeout waiting for DAT0 to go high!\n");
420
			err = -ETIMEDOUT;
421
			goto out;
422 423 424
		}
	}

425 426 427 428
	/* Copy the response to the response buffer */
	if (cmd->resp_type & MMC_RSP_136) {
		u32 cmdrsp3, cmdrsp2, cmdrsp1, cmdrsp0;

429 430 431 432
		cmdrsp3 = esdhc_read32(&regs->cmdrsp3);
		cmdrsp2 = esdhc_read32(&regs->cmdrsp2);
		cmdrsp1 = esdhc_read32(&regs->cmdrsp1);
		cmdrsp0 = esdhc_read32(&regs->cmdrsp0);
R
Rabin Vincent 已提交
433 434 435 436
		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);
437
	} else
438
		cmd->response[0] = esdhc_read32(&regs->cmdrsp0);
439 440 441

	/* Wait until all of the blocks are transferred */
	if (data) {
442
#ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO
443
		esdhc_pio_read_write(priv, data);
444
#else
445
		do {
446
			irqstat = esdhc_read32(&regs->irqstat);
447

448
			if (irqstat & IRQSTAT_DTOE) {
449
				err = -ETIMEDOUT;
450 451
				goto out;
			}
452

453
			if (irqstat & DATA_ERR) {
454
				err = -ECOMM;
455 456
				goto out;
			}
457
		} while ((irqstat & DATA_COMPLETE) != DATA_COMPLETE);
458

459 460 461 462 463
		/*
		 * Need invalidate the dcache here again to avoid any
		 * cache-fill during the DMA operations such as the
		 * speculative pre-fetching etc.
		 */
464
		if (data->flags & MMC_DATA_READ) {
465
			check_and_invalidate_dcache_range(cmd, data);
466
		}
467
#endif
468 469
	}

470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486
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))
				;
		}
	}

487
	esdhc_write32(&regs->irqstat, -1);
488

489
	return err;
490 491
}

492
static void set_sysctl(struct fsl_esdhc_priv *priv, struct mmc *mmc, uint clock)
493
{
494
	struct fsl_esdhc *regs = priv->esdhc_regs;
495 496
	int div = 1;
	int pre_div = 2;
497 498 499
	unsigned int sdhc_clk = priv->sdhc_clk;
	u32 time_out;
	u32 value;
500 501
	uint clk;

502 503
	if (clock < mmc->cfg->f_min)
		clock = mmc->cfg->f_min;
504

505
	while (sdhc_clk / (16 * pre_div) > clock && pre_div < 256)
506
		pre_div *= 2;
507

508
	while (sdhc_clk / (div * pre_div) > clock && div < 16)
509
		div++;
510

511
	pre_div >>= 1;
512 513 514 515
	div -= 1;

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

516
	esdhc_clrbits32(&regs->sysctl, SYSCTL_CKEN);
517 518

	esdhc_clrsetbits32(&regs->sysctl, SYSCTL_CLOCK_MASK, clk);
519

520 521 522 523 524 525 526 527 528 529
	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);
	}
530

531
	esdhc_setbits32(&regs->sysctl, SYSCTL_PEREN | SYSCTL_CKEN);
532 533
}

534
#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
535
static void esdhc_clock_control(struct fsl_esdhc_priv *priv, bool enable)
536
{
P
Peng Fan 已提交
537
	struct fsl_esdhc *regs = priv->esdhc_regs;
538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562
	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

563
static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
564
{
P
Peng Fan 已提交
565
	struct fsl_esdhc *regs = priv->esdhc_regs;
566

567 568
#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
	/* Select to use peripheral clock */
569
	esdhc_clock_control(priv, false);
Y
Yangbo Lu 已提交
570
	esdhc_setbits32(&regs->esdhcctl, ESDHCCTL_PCS);
571
	esdhc_clock_control(priv, true);
572
#endif
573
	/* Set the clock speed */
574 575 576
	if (priv->clock != mmc->clock)
		set_sysctl(priv, mmc, mmc->clock);

577
	/* Set the bus width */
578
	esdhc_clrbits32(&regs->proctl, PROCTL_DTW_4 | PROCTL_DTW_8);
579 580

	if (mmc->bus_width == 4)
581
		esdhc_setbits32(&regs->proctl, PROCTL_DTW_4);
582
	else if (mmc->bus_width == 8)
583 584
		esdhc_setbits32(&regs->proctl, PROCTL_DTW_8);

585
	return 0;
586 587
}

588
static int esdhc_init_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
589
{
P
Peng Fan 已提交
590
	struct fsl_esdhc *regs = priv->esdhc_regs;
591
	ulong start;
592

593
	/* Reset the entire host controller */
594
	esdhc_setbits32(&regs->sysctl, SYSCTL_RSTA);
595 596

	/* Wait until the controller is available */
597 598 599 600 601
	start = get_timer(0);
	while ((esdhc_read32(&regs->sysctl) & SYSCTL_RSTA)) {
		if (get_timer(start) > 1000)
			return -ETIMEDOUT;
	}
602

603
	/* Enable cache snooping */
Y
Yangbo Lu 已提交
604
	esdhc_write32(&regs->esdhcctl, 0x00000040);
605

606
	esdhc_setbits32(&regs->sysctl, SYSCTL_HCKEN | SYSCTL_IPGEN);
607 608

	/* Set the initial clock speed */
609
	mmc_set_clock(mmc, 400000, MMC_CLK_ENABLE);
610 611

	/* Disable the BRR and BWR bits in IRQSTAT */
612
	esdhc_clrbits32(&regs->irqstaten, IRQSTATEN_BRR | IRQSTATEN_BWR);
613 614

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

617 618
	/* Set timout to the maximum value */
	esdhc_clrsetbits32(&regs->sysctl, SYSCTL_TIMEOUT_MASK, 14 << 16);
619

620 621
	return 0;
}
622

623
static int esdhc_getcd_common(struct fsl_esdhc_priv *priv)
624
{
P
Peng Fan 已提交
625
	struct fsl_esdhc *regs = priv->esdhc_regs;
626 627
	int timeout = 1000;

628 629 630 631
#ifdef CONFIG_ESDHC_DETECT_QUIRK
	if (CONFIG_ESDHC_DETECT_QUIRK)
		return 1;
#endif
P
Peng Fan 已提交
632

633
#if CONFIG_IS_ENABLED(DM_MMC)
P
Peng Fan 已提交
634 635 636 637
	if (priv->non_removable)
		return 1;
#endif

638 639
	while (!(esdhc_read32(&regs->prsstat) & PRSSTAT_CINS) && --timeout)
		udelay(1000);
640

641
	return timeout > 0;
642 643
}

S
Simon Glass 已提交
644
#if !CONFIG_IS_ENABLED(DM_MMC)
645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673
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);
}

674
static const struct mmc_ops esdhc_ops = {
675 676
	.getcd		= esdhc_getcd,
	.init		= esdhc_init,
677 678 679
	.send_cmd	= esdhc_send_cmd,
	.set_ios	= esdhc_set_ios,
};
680
#endif
681

682 683
static int fsl_esdhc_init(struct fsl_esdhc_priv *priv,
			  struct fsl_esdhc_plat *plat)
684
{
685
	struct mmc_config *cfg;
686
	struct fsl_esdhc *regs;
Y
Yangbo Lu 已提交
687
	u32 caps;
688

P
Peng Fan 已提交
689 690
	if (!priv)
		return -EINVAL;
691

P
Peng Fan 已提交
692
	regs = priv->esdhc_regs;
693

694
	cfg = &plat->cfg;
695
#ifndef CONFIG_DM_MMC
696
	memset(cfg, '\0', sizeof(*cfg));
697
#endif
698

699
	caps = esdhc_read32(&regs->hostcapblt);
700
#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC135
Y
Yangbo Lu 已提交
701
	caps &= ~(HOSTCAPBLT_SRS | HOSTCAPBLT_VS18 | HOSTCAPBLT_VS30);
702
#endif
703
#ifdef CONFIG_SYS_FSL_MMC_HAS_CAPBLT_VS33
Y
Yangbo Lu 已提交
704
	caps |= HOSTCAPBLT_VS33;
705
#endif
Y
Yangbo Lu 已提交
706 707 708 709 710 711
	if (caps & HOSTCAPBLT_VS18)
		cfg->voltages |= MMC_VDD_165_195;
	if (caps & HOSTCAPBLT_VS30)
		cfg->voltages |= MMC_VDD_29_30 | MMC_VDD_30_31;
	if (caps & HOSTCAPBLT_VS33)
		cfg->voltages |= MMC_VDD_32_33 | MMC_VDD_33_34;
712

713
	cfg->name = "FSL_SDHC";
S
Simon Glass 已提交
714
#if !CONFIG_IS_ENABLED(DM_MMC)
715
	cfg->ops = &esdhc_ops;
716
#endif
P
Peng Fan 已提交
717
	if (priv->bus_width == 8)
718
		cfg->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT;
P
Peng Fan 已提交
719
	else if (priv->bus_width == 4)
720
		cfg->host_caps = MMC_MODE_4BIT;
P
Peng Fan 已提交
721

722
	cfg->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT;
723

P
Peng Fan 已提交
724 725
	if (priv->bus_width > 0) {
		if (priv->bus_width < 8)
726
			cfg->host_caps &= ~MMC_MODE_8BIT;
P
Peng Fan 已提交
727
		if (priv->bus_width < 4)
728
			cfg->host_caps &= ~MMC_MODE_4BIT;
729 730
	}

Y
Yangbo Lu 已提交
731
	if (caps & HOSTCAPBLT_HSS)
732
		cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
733

734 735
#ifdef CONFIG_ESDHC_DETECT_8_BIT_QUIRK
	if (CONFIG_ESDHC_DETECT_8_BIT_QUIRK)
736
		cfg->host_caps &= ~MMC_MODE_8BIT;
737 738
#endif

739
	cfg->f_min = 400000;
740
	cfg->f_max = min(priv->sdhc_clk, (u32)200000000);
741

742
	cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
743

P
Peng Fan 已提交
744 745 746
	return 0;
}

747
#if !CONFIG_IS_ENABLED(DM_MMC)
748 749 750 751 752 753 754 755 756 757 758 759 760 761
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;

	return 0;
};

P
Peng Fan 已提交
762 763
int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
{
764
	struct fsl_esdhc_plat *plat;
P
Peng Fan 已提交
765
	struct fsl_esdhc_priv *priv;
766
	struct mmc *mmc;
P
Peng Fan 已提交
767 768 769 770 771 772 773 774
	int ret;

	if (!cfg)
		return -EINVAL;

	priv = calloc(sizeof(struct fsl_esdhc_priv), 1);
	if (!priv)
		return -ENOMEM;
775 776 777 778 779
	plat = calloc(sizeof(struct fsl_esdhc_plat), 1);
	if (!plat) {
		free(priv);
		return -ENOMEM;
	}
P
Peng Fan 已提交
780 781 782 783

	ret = fsl_esdhc_cfg_to_priv(cfg, priv);
	if (ret) {
		debug("%s xlate failure\n", __func__);
784
		free(plat);
P
Peng Fan 已提交
785 786 787 788
		free(priv);
		return ret;
	}

789
	ret = fsl_esdhc_init(priv, plat);
P
Peng Fan 已提交
790 791
	if (ret) {
		debug("%s init failure\n", __func__);
792
		free(plat);
P
Peng Fan 已提交
793 794 795 796
		free(priv);
		return ret;
	}

797 798 799 800 801 802
	mmc = mmc_create(&plat->cfg, priv);
	if (!mmc)
		return -EIO;

	priv->mmc = mmc;

803 804 805 806 807
	return 0;
}

int fsl_esdhc_mmc_init(bd_t *bis)
{
808 809
	struct fsl_esdhc_cfg *cfg;

F
Fabio Estevam 已提交
810
	cfg = calloc(sizeof(struct fsl_esdhc_cfg), 1);
811
	cfg->esdhc_base = CONFIG_SYS_FSL_ESDHC_ADDR;
812
	cfg->sdhc_clk = gd->arch.sdhc_clk;
813
	return fsl_esdhc_initialize(bis, cfg);
814
}
815
#endif
816

817 818 819 820 821 822 823 824 825 826 827
#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:
828 829 830
		value = QIXIS_READ(brdcfg[5]);
		value |= (QIXIS_DAT4 | QIXIS_DAT5_6_7);
		QIXIS_WRITE(brdcfg[5], value);
831 832
		break;
	case QIXIS_ESDHC_ADAPTER_TYPE_SDMMC_LEGACY:
833 834 835
		value = QIXIS_READ(pwr_ctl[1]);
		value |= QIXIS_EVDD_BY_SDHC_VS;
		QIXIS_WRITE(pwr_ctl[1], value);
836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855
		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

856
#ifdef CONFIG_OF_LIBFDT
857
__weak int esdhc_status_fixup(void *blob, const char *compat)
858
{
859
#ifdef CONFIG_FSL_ESDHC_PIN_MUX
860
	if (!hwconfig("esdhc")) {
861
		do_fixup_by_compat(blob, compat, "status", "disabled",
862 863
				sizeof("disabled"), 1);
		return 1;
864
	}
865
#endif
866 867 868 869 870 871 872 873 874
	return 0;
}

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

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

876 877 878 879
#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
	do_fixup_by_compat_u32(blob, compat, "peripheral-frequency",
			       gd->arch.sdhc_clk, 1);
#else
880
	do_fixup_by_compat_u32(blob, compat, "clock-frequency",
881
			       gd->arch.sdhc_clk, 1);
882
#endif
883 884 885 886
#ifdef CONFIG_FSL_ESDHC_ADAPTER_IDENT
	do_fixup_by_compat_u32(blob, compat, "adapter-type",
			       (u32)(gd->arch.sdhc_adapter), 1);
#endif
887
}
888
#endif
P
Peng Fan 已提交
889

890
#if CONFIG_IS_ENABLED(DM_MMC)
891
#ifndef CONFIG_PPC
P
Peng Fan 已提交
892
#include <asm/arch/clock.h>
893
#endif
P
Peng Fan 已提交
894 895 896
static int fsl_esdhc_probe(struct udevice *dev)
{
	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
897
	struct fsl_esdhc_plat *plat = dev_get_platdata(dev);
P
Peng Fan 已提交
898 899 900
	struct fsl_esdhc_priv *priv = dev_get_priv(dev);
	fdt_addr_t addr;
	unsigned int val;
901
	struct mmc *mmc;
P
Peng Fan 已提交
902 903
	int ret;

904
	addr = dev_read_addr(dev);
P
Peng Fan 已提交
905 906
	if (addr == FDT_ADDR_T_NONE)
		return -EINVAL;
907 908 909
#ifdef CONFIG_PPC
	priv->esdhc_regs = (struct fsl_esdhc *)lower_32_bits(addr);
#else
P
Peng Fan 已提交
910
	priv->esdhc_regs = (struct fsl_esdhc *)addr;
911
#endif
P
Peng Fan 已提交
912 913
	priv->dev = dev;

914
	val = dev_read_u32_default(dev, "bus-width", -1);
P
Peng Fan 已提交
915 916 917 918 919 920 921
	if (val == 8)
		priv->bus_width = 8;
	else if (val == 4)
		priv->bus_width = 4;
	else
		priv->bus_width = 1;

922
	if (dev_read_bool(dev, "non-removable")) {
P
Peng Fan 已提交
923 924 925 926 927
		priv->non_removable = 1;
	 } else {
		priv->non_removable = 0;
	}

Y
Yangbo Lu 已提交
928
	priv->wp_enable = 1;
P
Peng Fan 已提交
929

P
Peng Fan 已提交
930 931 932 933 934 935 936 937 938 939 940 941 942 943 944
	if (IS_ENABLED(CONFIG_CLK)) {
		/* Assigned clock already set clock */
		ret = clk_get_by_name(dev, "per", &priv->per_clk);
		if (ret) {
			printf("Failed to get per_clk\n");
			return ret;
		}
		ret = clk_enable(&priv->per_clk);
		if (ret) {
			printf("Failed to enable per_clk\n");
			return ret;
		}

		priv->sdhc_clk = clk_get_rate(&priv->per_clk);
	} else {
945
#ifndef CONFIG_PPC
P
Peng Fan 已提交
946
		priv->sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK + dev->seq);
947 948 949
#else
		priv->sdhc_clk = gd->arch.sdhc_clk;
#endif
P
Peng Fan 已提交
950 951 952 953
		if (priv->sdhc_clk <= 0) {
			dev_err(dev, "Unable to get clk for %s\n", dev->name);
			return -EINVAL;
		}
P
Peng Fan 已提交
954 955
	}

956
	ret = fsl_esdhc_init(priv, plat);
P
Peng Fan 已提交
957 958 959 960 961
	if (ret) {
		dev_err(dev, "fsl_esdhc_init failure\n");
		return ret;
	}

962 963
	mmc_of_parse(dev, &plat->cfg);

964 965 966
	mmc = &plat->mmc;
	mmc->cfg = &plat->cfg;
	mmc->dev = dev;
967

968
	upriv->mmc = mmc;
P
Peng Fan 已提交
969

970
	return esdhc_init_common(priv, mmc);
P
Peng Fan 已提交
971 972
}

973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000
static int fsl_esdhc_get_cd(struct udevice *dev)
{
	struct fsl_esdhc_priv *priv = dev_get_priv(dev);

	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,
1001 1002 1003
#ifdef MMC_SUPPORTS_TUNING
	.execute_tuning = fsl_esdhc_execute_tuning,
#endif
1004 1005
};

P
Peng Fan 已提交
1006
static const struct udevice_id fsl_esdhc_ids[] = {
1007
	{ .compatible = "fsl,esdhc", },
P
Peng Fan 已提交
1008 1009 1010
	{ /* sentinel */ }
};

1011 1012 1013 1014 1015 1016 1017
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);
}

P
Peng Fan 已提交
1018 1019 1020 1021
U_BOOT_DRIVER(fsl_esdhc) = {
	.name	= "fsl-esdhc-mmc",
	.id	= UCLASS_MMC,
	.of_match = fsl_esdhc_ids,
1022 1023
	.ops	= &fsl_esdhc_ops,
	.bind	= fsl_esdhc_bind,
P
Peng Fan 已提交
1024
	.probe	= fsl_esdhc_probe,
1025
	.platdata_auto_alloc_size = sizeof(struct fsl_esdhc_plat),
P
Peng Fan 已提交
1026 1027 1028
	.priv_auto_alloc_size = sizeof(struct fsl_esdhc_priv),
};
#endif