mmc.c 40.4 KB
Newer Older
Andy Fleming's avatar
Andy Fleming committed
1 2 3 4 5 6
/*
 * Copyright 2008, Freescale Semiconductor, Inc
 * Andy Fleming
 *
 * Based vaguely on the Linux code
 *
7
 * SPDX-License-Identifier:	GPL-2.0+
Andy Fleming's avatar
Andy Fleming committed
8 9 10 11 12
 */

#include <config.h>
#include <common.h>
#include <command.h>
13 14
#include <dm.h>
#include <dm/device-internal.h>
15
#include <errno.h>
Andy Fleming's avatar
Andy Fleming committed
16 17
#include <mmc.h>
#include <part.h>
Peng Fan's avatar
Peng Fan committed
18
#include <power/regulator.h>
Andy Fleming's avatar
Andy Fleming committed
19
#include <malloc.h>
20
#include <memalign.h>
Andy Fleming's avatar
Andy Fleming committed
21
#include <linux/list.h>
22
#include <div64.h>
23
#include "mmc_private.h"
Andy Fleming's avatar
Andy Fleming committed
24

25 26 27 28 29 30 31 32
static const unsigned int sd_au_size[] = {
	0,		SZ_16K / 512,		SZ_32K / 512,
	SZ_64K / 512,	SZ_128K / 512,		SZ_256K / 512,
	SZ_512K / 512,	SZ_1M / 512,		SZ_2M / 512,
	SZ_4M / 512,	SZ_8M / 512,		(SZ_8M + SZ_4M) / 512,
	SZ_16M / 512,	(SZ_16M + SZ_8M) / 512,	SZ_32M / 512,	SZ_64M / 512,
};

33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
#if CONFIG_IS_ENABLED(MMC_TINY)
static struct mmc mmc_static;
struct mmc *find_mmc_device(int dev_num)
{
	return &mmc_static;
}

void mmc_do_preinit(void)
{
	struct mmc *m = &mmc_static;
#ifdef CONFIG_FSL_ESDHC_ADAPTER_IDENT
	mmc_set_preinit(m, 1);
#endif
	if (m->preinit)
		mmc_start_init(m);
}

struct blk_desc *mmc_get_blk_desc(struct mmc *mmc)
{
	return &mmc->block_dev;
}
#endif

56
#ifndef CONFIG_DM_MMC_OPS
57
__weak int board_mmc_getwp(struct mmc *mmc)
58 59 60 61 62 63 64 65 66 67
{
	return -1;
}

int mmc_getwp(struct mmc *mmc)
{
	int wp;

	wp = board_mmc_getwp(mmc);

68
	if (wp < 0) {
69 70
		if (mmc->cfg->ops->getwp)
			wp = mmc->cfg->ops->getwp(mmc);
71 72 73
		else
			wp = 0;
	}
74 75 76 77

	return wp;
}

Jeroen Hofstee's avatar
Jeroen Hofstee committed
78 79
__weak int board_mmc_getcd(struct mmc *mmc)
{
80 81
	return -1;
}
82
#endif
83

84 85
#ifdef CONFIG_MMC_TRACE
void mmmc_trace_before_send(struct mmc *mmc, struct mmc_cmd *cmd)
Andy Fleming's avatar
Andy Fleming committed
86
{
87 88 89
	printf("CMD_SEND:%d\n", cmd->cmdidx);
	printf("\t\tARG\t\t\t 0x%08X\n", cmd->cmdarg);
}
90

91 92
void mmmc_trace_after_send(struct mmc *mmc, struct mmc_cmd *cmd, int ret)
{
Raffaele Recalcati's avatar
Raffaele Recalcati committed
93 94 95
	int i;
	u8 *ptr;

96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
	if (ret) {
		printf("\t\tRET\t\t\t %d\n", ret);
	} else {
		switch (cmd->resp_type) {
		case MMC_RSP_NONE:
			printf("\t\tMMC_RSP_NONE\n");
			break;
		case MMC_RSP_R1:
			printf("\t\tMMC_RSP_R1,5,6,7 \t 0x%08X \n",
				cmd->response[0]);
			break;
		case MMC_RSP_R1b:
			printf("\t\tMMC_RSP_R1b\t\t 0x%08X \n",
				cmd->response[0]);
			break;
		case MMC_RSP_R2:
			printf("\t\tMMC_RSP_R2\t\t 0x%08X \n",
				cmd->response[0]);
			printf("\t\t          \t\t 0x%08X \n",
				cmd->response[1]);
			printf("\t\t          \t\t 0x%08X \n",
				cmd->response[2]);
			printf("\t\t          \t\t 0x%08X \n",
				cmd->response[3]);
Raffaele Recalcati's avatar
Raffaele Recalcati committed
120
			printf("\n");
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
			printf("\t\t\t\t\tDUMPING DATA\n");
			for (i = 0; i < 4; i++) {
				int j;
				printf("\t\t\t\t\t%03d - ", i*4);
				ptr = (u8 *)&cmd->response[i];
				ptr += 3;
				for (j = 0; j < 4; j++)
					printf("%02X ", *ptr--);
				printf("\n");
			}
			break;
		case MMC_RSP_R3:
			printf("\t\tMMC_RSP_R3,4\t\t 0x%08X \n",
				cmd->response[0]);
			break;
		default:
			printf("\t\tERROR MMC rsp not supported\n");
			break;
Bin Meng's avatar
Bin Meng committed
139
		}
Raffaele Recalcati's avatar
Raffaele Recalcati committed
140
	}
141 142 143 144 145 146 147 148 149
}

void mmc_trace_state(struct mmc *mmc, struct mmc_cmd *cmd)
{
	int status;

	status = (cmd->response[0] & MMC_STATUS_CURR_STATE) >> 9;
	printf("CURR STATE:%d\n", status);
}
Raffaele Recalcati's avatar
Raffaele Recalcati committed
150
#endif
151

152
#ifndef CONFIG_DM_MMC_OPS
153 154 155 156 157 158 159 160
int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
{
	int ret;

	mmmc_trace_before_send(mmc, cmd);
	ret = mmc->cfg->ops->send_cmd(mmc, cmd, data);
	mmmc_trace_after_send(mmc, cmd, ret);

161
	return ret;
Andy Fleming's avatar
Andy Fleming committed
162
}
163
#endif
Andy Fleming's avatar
Andy Fleming committed
164

165
int mmc_send_status(struct mmc *mmc, int timeout)
166 167
{
	struct mmc_cmd cmd;
168
	int err, retries = 5;
169 170 171

	cmd.cmdidx = MMC_CMD_SEND_STATUS;
	cmd.resp_type = MMC_RSP_R1;
Marek Vasut's avatar
Marek Vasut committed
172 173
	if (!mmc_host_is_spi(mmc))
		cmd.cmdarg = mmc->rca << 16;
174

175
	while (1) {
176
		err = mmc_send_cmd(mmc, &cmd, NULL);
177 178 179 180 181 182
		if (!err) {
			if ((cmd.response[0] & MMC_STATUS_RDY_FOR_DATA) &&
			    (cmd.response[0] & MMC_STATUS_CURR_STATE) !=
			     MMC_STATE_PRG)
				break;
			else if (cmd.response[0] & MMC_STATUS_MASK) {
183
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
184 185
				printf("Status Error: 0x%08X\n",
					cmd.response[0]);
186
#endif
187
				return -ECOMM;
188 189
			}
		} else if (--retries < 0)
190 191
			return err;

192 193
		if (timeout-- <= 0)
			break;
194

195 196
		udelay(1000);
	}
197

198
	mmc_trace_state(mmc, &cmd);
199
	if (timeout <= 0) {
200
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
201
		printf("Timeout waiting card ready\n");
202
#endif
203
		return -ETIMEDOUT;
204 205 206 207 208
	}

	return 0;
}

209
int mmc_set_blocklen(struct mmc *mmc, int len)
Andy Fleming's avatar
Andy Fleming committed
210 211 212
{
	struct mmc_cmd cmd;

213
	if (mmc->ddr_mode)
214 215
		return 0;

Andy Fleming's avatar
Andy Fleming committed
216 217 218 219 220 221 222
	cmd.cmdidx = MMC_CMD_SET_BLOCKLEN;
	cmd.resp_type = MMC_RSP_R1;
	cmd.cmdarg = len;

	return mmc_send_cmd(mmc, &cmd, NULL);
}

223
static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
Kim Phillips's avatar
Kim Phillips committed
224
			   lbaint_t blkcnt)
Andy Fleming's avatar
Andy Fleming committed
225 226 227 228
{
	struct mmc_cmd cmd;
	struct mmc_data data;

229 230 231 232
	if (blkcnt > 1)
		cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
	else
		cmd.cmdidx = MMC_CMD_READ_SINGLE_BLOCK;
Andy Fleming's avatar
Andy Fleming committed
233 234

	if (mmc->high_capacity)
235
		cmd.cmdarg = start;
Andy Fleming's avatar
Andy Fleming committed
236
	else
237
		cmd.cmdarg = start * mmc->read_bl_len;
Andy Fleming's avatar
Andy Fleming committed
238 239 240 241

	cmd.resp_type = MMC_RSP_R1;

	data.dest = dst;
242
	data.blocks = blkcnt;
Andy Fleming's avatar
Andy Fleming committed
243 244 245
	data.blocksize = mmc->read_bl_len;
	data.flags = MMC_DATA_READ;

246 247
	if (mmc_send_cmd(mmc, &cmd, &data))
		return 0;
Andy Fleming's avatar
Andy Fleming committed
248

249 250 251 252 253
	if (blkcnt > 1) {
		cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
		cmd.cmdarg = 0;
		cmd.resp_type = MMC_RSP_R1b;
		if (mmc_send_cmd(mmc, &cmd, NULL)) {
254
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
255
			printf("mmc fail to send stop cmd\n");
256
#endif
257 258
			return 0;
		}
Andy Fleming's avatar
Andy Fleming committed
259 260
	}

261
	return blkcnt;
Andy Fleming's avatar
Andy Fleming committed
262 263
}

264
#ifdef CONFIG_BLK
265
ulong mmc_bread(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, void *dst)
266
#else
267 268
ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt,
		void *dst)
269
#endif
Andy Fleming's avatar
Andy Fleming committed
270
{
271 272 273
#ifdef CONFIG_BLK
	struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
#endif
274
	int dev_num = block_dev->devnum;
275
	int err;
276 277 278 279
	lbaint_t cur, blocks_todo = blkcnt;

	if (blkcnt == 0)
		return 0;
Andy Fleming's avatar
Andy Fleming committed
280

281
	struct mmc *mmc = find_mmc_device(dev_num);
Andy Fleming's avatar
Andy Fleming committed
282 283 284
	if (!mmc)
		return 0;

285 286 287 288 289
	if (CONFIG_IS_ENABLED(MMC_TINY))
		err = mmc_switch_part(mmc, block_dev->hwpart);
	else
		err = blk_dselect_hwpart(block_dev, block_dev->hwpart);

290 291 292
	if (err < 0)
		return 0;

293
	if ((start + blkcnt) > block_dev->lba) {
294
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
295
		printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
296
			start + blkcnt, block_dev->lba);
297
#endif
298 299
		return 0;
	}
Andy Fleming's avatar
Andy Fleming committed
300

301 302
	if (mmc_set_blocklen(mmc, mmc->read_bl_len)) {
		debug("%s: Failed to set blocklen\n", __func__);
Andy Fleming's avatar
Andy Fleming committed
303
		return 0;
304
	}
Andy Fleming's avatar
Andy Fleming committed
305

306
	do {
307 308
		cur = (blocks_todo > mmc->cfg->b_max) ?
			mmc->cfg->b_max : blocks_todo;
309 310
		if (mmc_read_blocks(mmc, dst, start, cur) != cur) {
			debug("%s: Failed to read blocks\n", __func__);
311
			return 0;
312
		}
313 314 315 316
		blocks_todo -= cur;
		start += cur;
		dst += cur * mmc->read_bl_len;
	} while (blocks_todo > 0);
Andy Fleming's avatar
Andy Fleming committed
317 318 319 320

	return blkcnt;
}

Kim Phillips's avatar
Kim Phillips committed
321
static int mmc_go_idle(struct mmc *mmc)
Andy Fleming's avatar
Andy Fleming committed
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
{
	struct mmc_cmd cmd;
	int err;

	udelay(1000);

	cmd.cmdidx = MMC_CMD_GO_IDLE_STATE;
	cmd.cmdarg = 0;
	cmd.resp_type = MMC_RSP_NONE;

	err = mmc_send_cmd(mmc, &cmd, NULL);

	if (err)
		return err;

	udelay(2000);

	return 0;
}

Kim Phillips's avatar
Kim Phillips committed
342
static int sd_send_op_cond(struct mmc *mmc)
Andy Fleming's avatar
Andy Fleming committed
343 344 345 346 347
{
	int timeout = 1000;
	int err;
	struct mmc_cmd cmd;

348
	while (1) {
Andy Fleming's avatar
Andy Fleming committed
349 350 351 352 353 354 355 356 357 358 359
		cmd.cmdidx = MMC_CMD_APP_CMD;
		cmd.resp_type = MMC_RSP_R1;
		cmd.cmdarg = 0;

		err = mmc_send_cmd(mmc, &cmd, NULL);

		if (err)
			return err;

		cmd.cmdidx = SD_CMD_APP_SEND_OP_COND;
		cmd.resp_type = MMC_RSP_R3;
360 361 362 363 364 365 366 367

		/*
		 * Most cards do not answer if some reserved bits
		 * in the ocr are set. However, Some controller
		 * can set bit 7 (reserved for low voltages), but
		 * how to manage low voltages SD card is not yet
		 * specified.
		 */
Thomas Chou's avatar
Thomas Chou committed
368
		cmd.cmdarg = mmc_host_is_spi(mmc) ? 0 :
369
			(mmc->cfg->voltages & 0xff8000);
Andy Fleming's avatar
Andy Fleming committed
370 371 372 373 374 375 376 377 378

		if (mmc->version == SD_VERSION_2)
			cmd.cmdarg |= OCR_HCS;

		err = mmc_send_cmd(mmc, &cmd, NULL);

		if (err)
			return err;

379 380 381 382
		if (cmd.response[0] & OCR_BUSY)
			break;

		if (timeout-- <= 0)
383
			return -EOPNOTSUPP;
Andy Fleming's avatar
Andy Fleming committed
384

385 386
		udelay(1000);
	}
Andy Fleming's avatar
Andy Fleming committed
387 388 389 390

	if (mmc->version != SD_VERSION_2)
		mmc->version = SD_VERSION_1_0;

Thomas Chou's avatar
Thomas Chou committed
391 392 393 394 395 396 397 398 399 400 401
	if (mmc_host_is_spi(mmc)) { /* read OCR for spi */
		cmd.cmdidx = MMC_CMD_SPI_READ_OCR;
		cmd.resp_type = MMC_RSP_R3;
		cmd.cmdarg = 0;

		err = mmc_send_cmd(mmc, &cmd, NULL);

		if (err)
			return err;
	}

Rabin Vincent's avatar
Rabin Vincent committed
402
	mmc->ocr = cmd.response[0];
Andy Fleming's avatar
Andy Fleming committed
403 404 405 406 407 408 409

	mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
	mmc->rca = 0;

	return 0;
}

410
static int mmc_send_op_cond_iter(struct mmc *mmc, int use_arg)
Andy Fleming's avatar
Andy Fleming committed
411
{
412
	struct mmc_cmd cmd;
Andy Fleming's avatar
Andy Fleming committed
413 414
	int err;

415 416 417
	cmd.cmdidx = MMC_CMD_SEND_OP_COND;
	cmd.resp_type = MMC_RSP_R3;
	cmd.cmdarg = 0;
Rob Herring's avatar
Rob Herring committed
418 419
	if (use_arg && !mmc_host_is_spi(mmc))
		cmd.cmdarg = OCR_HCS |
420
			(mmc->cfg->voltages &
421 422
			(mmc->ocr & OCR_VOLTAGE_MASK)) |
			(mmc->ocr & OCR_ACCESS_MODE);
423

424
	err = mmc_send_cmd(mmc, &cmd, NULL);
425 426
	if (err)
		return err;
427
	mmc->ocr = cmd.response[0];
428 429 430
	return 0;
}

431
static int mmc_send_op_cond(struct mmc *mmc)
432 433 434
{
	int err, i;

Andy Fleming's avatar
Andy Fleming committed
435 436 437
	/* Some cards seem to need this */
	mmc_go_idle(mmc);

438
 	/* Asking to the card its capabilities */
439
	for (i = 0; i < 2; i++) {
440
		err = mmc_send_op_cond_iter(mmc, i != 0);
441 442
		if (err)
			return err;
Wolfgang Denk's avatar
Wolfgang Denk committed
443

444
		/* exit if not busy (flag seems to be inverted) */
445
		if (mmc->ocr & OCR_BUSY)
446
			break;
447
	}
448 449
	mmc->op_cond_pending = 1;
	return 0;
450
}
Wolfgang Denk's avatar
Wolfgang Denk committed
451

452
static int mmc_complete_op_cond(struct mmc *mmc)
453 454 455 456 457
{
	struct mmc_cmd cmd;
	int timeout = 1000;
	uint start;
	int err;
Wolfgang Denk's avatar
Wolfgang Denk committed
458

459
	mmc->op_cond_pending = 0;
460
	if (!(mmc->ocr & OCR_BUSY)) {
461 462 463
		/* Some cards seem to need this */
		mmc_go_idle(mmc);

464
		start = get_timer(0);
465
		while (1) {
466 467 468
			err = mmc_send_op_cond_iter(mmc, 1);
			if (err)
				return err;
469 470
			if (mmc->ocr & OCR_BUSY)
				break;
471
			if (get_timer(start) > timeout)
472
				return -EOPNOTSUPP;
473
			udelay(100);
474
		}
475
	}
Andy Fleming's avatar
Andy Fleming committed
476

Thomas Chou's avatar
Thomas Chou committed
477 478 479 480 481 482 483 484 485
	if (mmc_host_is_spi(mmc)) { /* read OCR for spi */
		cmd.cmdidx = MMC_CMD_SPI_READ_OCR;
		cmd.resp_type = MMC_RSP_R3;
		cmd.cmdarg = 0;

		err = mmc_send_cmd(mmc, &cmd, NULL);

		if (err)
			return err;
486 487

		mmc->ocr = cmd.response[0];
Thomas Chou's avatar
Thomas Chou committed
488 489
	}

Andy Fleming's avatar
Andy Fleming committed
490 491 492
	mmc->version = MMC_VERSION_UNKNOWN;

	mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
493
	mmc->rca = 1;
Andy Fleming's avatar
Andy Fleming committed
494 495 496 497 498

	return 0;
}


Kim Phillips's avatar
Kim Phillips committed
499
static int mmc_send_ext_csd(struct mmc *mmc, u8 *ext_csd)
Andy Fleming's avatar
Andy Fleming committed
500 501 502 503 504 505 506 507 508 509
{
	struct mmc_cmd cmd;
	struct mmc_data data;
	int err;

	/* Get the Card Status Register */
	cmd.cmdidx = MMC_CMD_SEND_EXT_CSD;
	cmd.resp_type = MMC_RSP_R1;
	cmd.cmdarg = 0;

510
	data.dest = (char *)ext_csd;
Andy Fleming's avatar
Andy Fleming committed
511
	data.blocks = 1;
512
	data.blocksize = MMC_MAX_BLOCK_LEN;
Andy Fleming's avatar
Andy Fleming committed
513 514 515 516 517 518 519
	data.flags = MMC_DATA_READ;

	err = mmc_send_cmd(mmc, &cmd, &data);

	return err;
}

520
int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
Andy Fleming's avatar
Andy Fleming committed
521 522
{
	struct mmc_cmd cmd;
523
	int timeout = 1000;
Maxime Ripard's avatar
Maxime Ripard committed
524
	int retries = 3;
525
	int ret;
Andy Fleming's avatar
Andy Fleming committed
526 527 528 529

	cmd.cmdidx = MMC_CMD_SWITCH;
	cmd.resp_type = MMC_RSP_R1b;
	cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
530 531
				 (index << 16) |
				 (value << 8);
Andy Fleming's avatar
Andy Fleming committed
532

Maxime Ripard's avatar
Maxime Ripard committed
533 534
	while (retries > 0) {
		ret = mmc_send_cmd(mmc, &cmd, NULL);
535

Maxime Ripard's avatar
Maxime Ripard committed
536 537 538 539 540 541 542 543
		/* Waiting for the ready status */
		if (!ret) {
			ret = mmc_send_status(mmc, timeout);
			return ret;
		}

		retries--;
	}
544 545 546

	return ret;

Andy Fleming's avatar
Andy Fleming committed
547 548
}

Kim Phillips's avatar
Kim Phillips committed
549
static int mmc_change_freq(struct mmc *mmc)
Andy Fleming's avatar
Andy Fleming committed
550
{
551
	ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
Andy Fleming's avatar
Andy Fleming committed
552 553 554
	char cardtype;
	int err;

555
	mmc->card_caps = 0;
Andy Fleming's avatar
Andy Fleming committed
556

Thomas Chou's avatar
Thomas Chou committed
557 558 559
	if (mmc_host_is_spi(mmc))
		return 0;

Andy Fleming's avatar
Andy Fleming committed
560 561 562 563
	/* Only version 4 supports high-speed */
	if (mmc->version < MMC_VERSION_4)
		return 0;

564 565
	mmc->card_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT;

Andy Fleming's avatar
Andy Fleming committed
566 567 568 569 570
	err = mmc_send_ext_csd(mmc, ext_csd);

	if (err)
		return err;

571
	cardtype = ext_csd[EXT_CSD_CARD_TYPE] & 0xf;
Andy Fleming's avatar
Andy Fleming committed
572 573 574 575

	err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, 1);

	if (err)
576
		return err;
Andy Fleming's avatar
Andy Fleming committed
577 578 579 580 581 582 583 584

	/* Now check to see that it worked */
	err = mmc_send_ext_csd(mmc, ext_csd);

	if (err)
		return err;

	/* No high-speed support */
585
	if (!ext_csd[EXT_CSD_HS_TIMING])
Andy Fleming's avatar
Andy Fleming committed
586 587 588
		return 0;

	/* High Speed is set, there are two types: 52MHz and 26MHz */
589
	if (cardtype & EXT_CSD_CARD_TYPE_52) {
590
		if (cardtype & EXT_CSD_CARD_TYPE_DDR_1_8V)
591
			mmc->card_caps |= MMC_MODE_DDR_52MHz;
Andy Fleming's avatar
Andy Fleming committed
592
		mmc->card_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
593
	} else {
Andy Fleming's avatar
Andy Fleming committed
594
		mmc->card_caps |= MMC_MODE_HS;
595
	}
Andy Fleming's avatar
Andy Fleming committed
596 597 598 599

	return 0;
}

600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622
static int mmc_set_capacity(struct mmc *mmc, int part_num)
{
	switch (part_num) {
	case 0:
		mmc->capacity = mmc->capacity_user;
		break;
	case 1:
	case 2:
		mmc->capacity = mmc->capacity_boot;
		break;
	case 3:
		mmc->capacity = mmc->capacity_rpmb;
		break;
	case 4:
	case 5:
	case 6:
	case 7:
		mmc->capacity = mmc->capacity_gp[part_num - 4];
		break;
	default:
		return -1;
	}

623
	mmc_get_blk_desc(mmc)->lba = lldiv(mmc->capacity, mmc->read_bl_len);
624 625 626 627

	return 0;
}

628
int mmc_switch_part(struct mmc *mmc, unsigned int part_num)
629
{
630
	int ret;
631

632 633 634 635
	ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
			 (mmc->part_config & ~PART_ACCESS_MASK)
			 | (part_num & PART_ACCESS_MASK));

636 637 638 639
	/*
	 * Set the capacity if the switch succeeded or was intended
	 * to return to representing the raw device.
	 */
640
	if ((ret == 0) || ((ret == -ENODEV) && (part_num == 0))) {
641
		ret = mmc_set_capacity(mmc, part_num);
642
		mmc_get_blk_desc(mmc)->hwpart = part_num;
643
	}
644 645

	return ret;
646 647
}

648 649 650 651 652 653 654 655 656 657
int mmc_hwpart_config(struct mmc *mmc,
		      const struct mmc_hwpart_conf *conf,
		      enum mmc_hwpart_conf_mode mode)
{
	u8 part_attrs = 0;
	u32 enh_size_mult;
	u32 enh_start_addr;
	u32 gp_size_mult[4];
	u32 max_enh_size_mult;
	u32 tot_enh_size_mult = 0;
658
	u8 wr_rel_set;
659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732
	int i, pidx, err;
	ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);

	if (mode < MMC_HWPART_CONF_CHECK || mode > MMC_HWPART_CONF_COMPLETE)
		return -EINVAL;

	if (IS_SD(mmc) || (mmc->version < MMC_VERSION_4_41)) {
		printf("eMMC >= 4.4 required for enhanced user data area\n");
		return -EMEDIUMTYPE;
	}

	if (!(mmc->part_support & PART_SUPPORT)) {
		printf("Card does not support partitioning\n");
		return -EMEDIUMTYPE;
	}

	if (!mmc->hc_wp_grp_size) {
		printf("Card does not define HC WP group size\n");
		return -EMEDIUMTYPE;
	}

	/* check partition alignment and total enhanced size */
	if (conf->user.enh_size) {
		if (conf->user.enh_size % mmc->hc_wp_grp_size ||
		    conf->user.enh_start % mmc->hc_wp_grp_size) {
			printf("User data enhanced area not HC WP group "
			       "size aligned\n");
			return -EINVAL;
		}
		part_attrs |= EXT_CSD_ENH_USR;
		enh_size_mult = conf->user.enh_size / mmc->hc_wp_grp_size;
		if (mmc->high_capacity) {
			enh_start_addr = conf->user.enh_start;
		} else {
			enh_start_addr = (conf->user.enh_start << 9);
		}
	} else {
		enh_size_mult = 0;
		enh_start_addr = 0;
	}
	tot_enh_size_mult += enh_size_mult;

	for (pidx = 0; pidx < 4; pidx++) {
		if (conf->gp_part[pidx].size % mmc->hc_wp_grp_size) {
			printf("GP%i partition not HC WP group size "
			       "aligned\n", pidx+1);
			return -EINVAL;
		}
		gp_size_mult[pidx] = conf->gp_part[pidx].size / mmc->hc_wp_grp_size;
		if (conf->gp_part[pidx].size && conf->gp_part[pidx].enhanced) {
			part_attrs |= EXT_CSD_ENH_GP(pidx);
			tot_enh_size_mult += gp_size_mult[pidx];
		}
	}

	if (part_attrs && ! (mmc->part_support & ENHNCD_SUPPORT)) {
		printf("Card does not support enhanced attribute\n");
		return -EMEDIUMTYPE;
	}

	err = mmc_send_ext_csd(mmc, ext_csd);
	if (err)
		return err;

	max_enh_size_mult =
		(ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT+2] << 16) +
		(ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT+1] << 8) +
		ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT];
	if (tot_enh_size_mult > max_enh_size_mult) {
		printf("Total enhanced size exceeds maximum (%u > %u)\n",
		       tot_enh_size_mult, max_enh_size_mult);
		return -EMEDIUMTYPE;
	}

733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759
	/* The default value of EXT_CSD_WR_REL_SET is device
	 * dependent, the values can only be changed if the
	 * EXT_CSD_HS_CTRL_REL bit is set. The values can be
	 * changed only once and before partitioning is completed. */
	wr_rel_set = ext_csd[EXT_CSD_WR_REL_SET];
	if (conf->user.wr_rel_change) {
		if (conf->user.wr_rel_set)
			wr_rel_set |= EXT_CSD_WR_DATA_REL_USR;
		else
			wr_rel_set &= ~EXT_CSD_WR_DATA_REL_USR;
	}
	for (pidx = 0; pidx < 4; pidx++) {
		if (conf->gp_part[pidx].wr_rel_change) {
			if (conf->gp_part[pidx].wr_rel_set)
				wr_rel_set |= EXT_CSD_WR_DATA_REL_GP(pidx);
			else
				wr_rel_set &= ~EXT_CSD_WR_DATA_REL_GP(pidx);
		}
	}

	if (wr_rel_set != ext_csd[EXT_CSD_WR_REL_SET] &&
	    !(ext_csd[EXT_CSD_WR_REL_PARAM] & EXT_CSD_HS_CTRL_REL)) {
		puts("Card does not support host controlled partition write "
		     "reliability settings\n");
		return -EMEDIUMTYPE;
	}

760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816
	if (ext_csd[EXT_CSD_PARTITION_SETTING] &
	    EXT_CSD_PARTITION_SETTING_COMPLETED) {
		printf("Card already partitioned\n");
		return -EPERM;
	}

	if (mode == MMC_HWPART_CONF_CHECK)
		return 0;

	/* Partitioning requires high-capacity size definitions */
	if (!(ext_csd[EXT_CSD_ERASE_GROUP_DEF] & 0x01)) {
		err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
				 EXT_CSD_ERASE_GROUP_DEF, 1);

		if (err)
			return err;

		ext_csd[EXT_CSD_ERASE_GROUP_DEF] = 1;

		/* update erase group size to be high-capacity */
		mmc->erase_grp_size =
			ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] * 1024;

	}

	/* all OK, write the configuration */
	for (i = 0; i < 4; i++) {
		err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
				 EXT_CSD_ENH_START_ADDR+i,
				 (enh_start_addr >> (i*8)) & 0xFF);
		if (err)
			return err;
	}
	for (i = 0; i < 3; i++) {
		err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
				 EXT_CSD_ENH_SIZE_MULT+i,
				 (enh_size_mult >> (i*8)) & 0xFF);
		if (err)
			return err;
	}
	for (pidx = 0; pidx < 4; pidx++) {
		for (i = 0; i < 3; i++) {
			err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
					 EXT_CSD_GP_SIZE_MULT+pidx*3+i,
					 (gp_size_mult[pidx] >> (i*8)) & 0xFF);
			if (err)
				return err;
		}
	}
	err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
			 EXT_CSD_PARTITIONS_ATTRIBUTE, part_attrs);
	if (err)
		return err;

	if (mode == MMC_HWPART_CONF_SET)
		return 0;

817 818 819 820 821 822 823 824 825 826 827
	/* The WR_REL_SET is a write-once register but shall be
	 * written before setting PART_SETTING_COMPLETED. As it is
	 * write-once we can only write it when completing the
	 * partitioning. */
	if (wr_rel_set != ext_csd[EXT_CSD_WR_REL_SET]) {
		err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
				 EXT_CSD_WR_REL_SET, wr_rel_set);
		if (err)
			return err;
	}

828 829 830 831 832 833 834 835 836 837 838 839 840 841
	/* Setting PART_SETTING_COMPLETED confirms the partition
	 * configuration but it only becomes effective after power
	 * cycle, so we do not adjust the partition related settings
	 * in the mmc struct. */

	err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
			 EXT_CSD_PARTITION_SETTING,
			 EXT_CSD_PARTITION_SETTING_COMPLETED);
	if (err)
		return err;

	return 0;
}

842
#ifndef CONFIG_DM_MMC_OPS
843 844 845 846 847 848
int mmc_getcd(struct mmc *mmc)
{
	int cd;

	cd = board_mmc_getcd(mmc);

849
	if (cd < 0) {
850 851
		if (mmc->cfg->ops->getcd)
			cd = mmc->cfg->ops->getcd(mmc);
852 853 854
		else
			cd = 1;
	}
855 856 857

	return cd;
}
858
#endif
859

Kim Phillips's avatar
Kim Phillips committed
860
static int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp)
Andy Fleming's avatar
Andy Fleming committed
861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880
{
	struct mmc_cmd cmd;
	struct mmc_data data;

	/* Switch the frequency */
	cmd.cmdidx = SD_CMD_SWITCH_FUNC;
	cmd.resp_type = MMC_RSP_R1;
	cmd.cmdarg = (mode << 31) | 0xffffff;
	cmd.cmdarg &= ~(0xf << (group * 4));
	cmd.cmdarg |= value << (group * 4);

	data.dest = (char *)resp;
	data.blocksize = 64;
	data.blocks = 1;
	data.flags = MMC_DATA_READ;

	return mmc_send_cmd(mmc, &cmd, &data);
}


Kim Phillips's avatar
Kim Phillips committed
881
static int sd_change_freq(struct mmc *mmc)
Andy Fleming's avatar
Andy Fleming committed
882 883 884
{
	int err;
	struct mmc_cmd cmd;
885 886
	ALLOC_CACHE_ALIGN_BUFFER(uint, scr, 2);
	ALLOC_CACHE_ALIGN_BUFFER(uint, switch_status, 16);
Andy Fleming's avatar
Andy Fleming committed
887 888 889 890 891
	struct mmc_data data;
	int timeout;

	mmc->card_caps = 0;

Thomas Chou's avatar
Thomas Chou committed
892 893 894
	if (mmc_host_is_spi(mmc))
		return 0;

Andy Fleming's avatar
Andy Fleming committed
895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911
	/* Read the SCR to find out if this card supports higher speeds */
	cmd.cmdidx = MMC_CMD_APP_CMD;
	cmd.resp_type = MMC_RSP_R1;
	cmd.cmdarg = mmc->rca << 16;

	err = mmc_send_cmd(mmc, &cmd, NULL);

	if (err)
		return err;

	cmd.cmdidx = SD_CMD_APP_SEND_SCR;
	cmd.resp_type = MMC_RSP_R1;
	cmd.cmdarg = 0;

	timeout = 3;

retry_scr:
912
	data.dest = (char *)scr;
Andy Fleming's avatar
Andy Fleming committed
913 914 915 916 917 918 919 920 921 922 923 924 925
	data.blocksize = 8;
	data.blocks = 1;
	data.flags = MMC_DATA_READ;

	err = mmc_send_cmd(mmc, &cmd, &data);

	if (err) {
		if (timeout--)
			goto retry_scr;

		return err;
	}

926 927
	mmc->scr[0] = __be32_to_cpu(scr[0]);
	mmc->scr[1] = __be32_to_cpu(scr[1]);
Andy Fleming's avatar
Andy Fleming committed
928 929

	switch ((mmc->scr[0] >> 24) & 0xf) {
Bin Meng's avatar
Bin Meng committed
930 931 932 933 934 935 936 937 938 939 940 941 942 943
	case 0:
		mmc->version = SD_VERSION_1_0;
		break;
	case 1:
		mmc->version = SD_VERSION_1_10;
		break;
	case 2:
		mmc->version = SD_VERSION_2;
		if ((mmc->scr[0] >> 15) & 0x1)
			mmc->version = SD_VERSION_3;
		break;
	default:
		mmc->version = SD_VERSION_1_0;
		break;
Andy Fleming's avatar
Andy Fleming committed
944 945
	}

Alagu Sankar's avatar
Alagu Sankar committed
946 947 948
	if (mmc->scr[0] & SD_DATA_4BIT)
		mmc->card_caps |= MMC_MODE_4BIT;

Andy Fleming's avatar
Andy Fleming committed
949 950 951 952 953 954 955
	/* Version 1.0 doesn't support switching */
	if (mmc->version == SD_VERSION_1_0)
		return 0;

	timeout = 4;
	while (timeout--) {
		err = sd_switch(mmc, SD_SWITCH_CHECK, 0, 1,
956
				(u8 *)switch_status);
Andy Fleming's avatar
Andy Fleming committed
957 958 959 960 961

		if (err)
			return err;

		/* The high-speed function is busy.  Try again */
962
		if (!(__be32_to_cpu(switch_status[7]) & SD_HIGHSPEED_BUSY))
Andy Fleming's avatar
Andy Fleming committed
963 964 965 966
			break;
	}

	/* If high-speed isn't supported, we return */
967
	if (!(__be32_to_cpu(switch_status[3]) & SD_HIGHSPEED_SUPPORTED))
Andy Fleming's avatar
Andy Fleming committed
968 969
		return 0;

970 971 972 973 974 975
	/*
	 * If the host doesn't support SD_HIGHSPEED, do not switch card to
	 * HIGHSPEED mode even if the card support SD_HIGHSPPED.
	 * This can avoid furthur problem when the card runs in different
	 * mode between the host.
	 */
976 977
	if (!((mmc->cfg->host_caps & MMC_MODE_HS_52MHz) &&
		(mmc->cfg->host_caps & MMC_MODE_HS)))
978 979
		return 0;

980
	err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, 1, (u8 *)switch_status);
Andy Fleming's avatar
Andy Fleming committed
981 982 983 984

	if (err)
		return err;

985
	if ((__be32_to_cpu(switch_status[4]) & 0x0f000000) == 0x01000000)
Andy Fleming's avatar
Andy Fleming committed
986 987 988 989 990
		mmc->card_caps |= MMC_MODE_HS;

	return 0;
}

991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046
static int sd_read_ssr(struct mmc *mmc)
{
	int err, i;
	struct mmc_cmd cmd;
	ALLOC_CACHE_ALIGN_BUFFER(uint, ssr, 16);
	struct mmc_data data;
	int timeout = 3;
	unsigned int au, eo, et, es;

	cmd.cmdidx = MMC_CMD_APP_CMD;
	cmd.resp_type = MMC_RSP_R1;
	cmd.cmdarg = mmc->rca << 16;

	err = mmc_send_cmd(mmc, &cmd, NULL);
	if (err)
		return err;

	cmd.cmdidx = SD_CMD_APP_SD_STATUS;
	cmd.resp_type = MMC_RSP_R1;
	cmd.cmdarg = 0;

retry_ssr:
	data.dest = (char *)ssr;
	data.blocksize = 64;
	data.blocks = 1;
	data.flags = MMC_DATA_READ;

	err = mmc_send_cmd(mmc, &cmd, &data);
	if (err) {
		if (timeout--)
			goto retry_ssr;

		return err;
	}

	for (i = 0; i < 16; i++)
		ssr[i] = be32_to_cpu(ssr[i]);

	au = (ssr[2] >> 12) & 0xF;
	if ((au <= 9) || (mmc->version == SD_VERSION_3)) {
		mmc->ssr.au = sd_au_size[au];
		es = (ssr[3] >> 24) & 0xFF;
		es |= (ssr[2] & 0xFF) << 8;
		et = (ssr[3] >> 18) & 0x3F;
		if (es && et) {
			eo = (ssr[3] >> 16) & 0x3;
			mmc->ssr.erase_timeout = (et * 1000) / es;
			mmc->ssr.erase_offset = eo * 1000;
		}
	} else {
		debug("Invalid Allocation Unit Size.\n");
	}

	return 0;
}

Andy Fleming's avatar
Andy Fleming committed
1047 1048
/* frequency bases */
/* divided by 10 to be nice to platforms without floating point */
Mike Frysinger's avatar
Mike Frysinger committed
1049
static const int fbase[] = {
Andy Fleming's avatar
Andy Fleming committed
1050 1051 1052 1053 1054 1055 1056 1057 1058
	10000,
	100000,
	1000000,
	10000000,
};

/* Multiplier values for TRAN_SPEED.  Multiplied by 10 to be nice
 * to platforms without floating point.
 */
1059
static const u8 multipliers[] = {
Andy Fleming's avatar
Andy Fleming committed
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077
	0,	/* reserved */
	10,
	12,
	13,
	15,
	20,
	25,
	30,
	35,
	40,
	45,
	50,
	55,
	60,
	70,
	80,
};

1078
#ifndef CONFIG_DM_MMC_OPS
Kim Phillips's avatar
Kim Phillips committed
1079
static void mmc_set_ios(struct mmc *mmc)
Andy Fleming's avatar
Andy Fleming committed
1080
{
1081 1082
	if (mmc->cfg->ops->set_ios)
		mmc->cfg->ops->set_ios(mmc);
Andy Fleming's avatar
Andy Fleming committed
1083
}
1084
#endif
Andy Fleming's avatar
Andy Fleming committed
1085 1086 1087

void mmc_set_clock(struct mmc *mmc, uint clock)
{
1088 1089
	if (clock > mmc->cfg->f_max)
		clock = mmc->cfg->f_max;
Andy Fleming's avatar
Andy Fleming committed
1090

1091 1092
	if (clock < mmc->cfg->f_min)
		clock = mmc->cfg->f_min;
Andy Fleming's avatar
Andy Fleming committed
1093 1094 1095 1096 1097 1098

	mmc->clock = clock;

	mmc_set_ios(mmc);
}

Kim Phillips's avatar
Kim Phillips committed
1099
static void mmc_set_bus_width(struct mmc *mmc, uint width)
Andy Fleming's avatar
Andy Fleming committed
1100 1101 1102 1103 1104 1105
{
	mmc->bus_width = width;

	mmc_set_ios(mmc);
}

Kim Phillips's avatar
Kim Phillips committed
1106
static int mmc_startup(struct mmc *mmc)
Andy Fleming's avatar
Andy Fleming committed
1107
{
1108
	int err, i;