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

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

24
25
#define DEFAULT_CMD6_TIMEOUT_MS  500

26
static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage);
27

Simon Glass's avatar
Simon Glass committed
28
#if !CONFIG_IS_ENABLED(DM_MMC)
29

30
static int mmc_wait_dat0(struct mmc *mmc, int state, int timeout_us)
31
32
33
34
{
	return -ENOSYS;
}

35
__weak int board_mmc_getwp(struct mmc *mmc)
36
37
38
39
40
41
42
43
44
45
{
	return -1;
}

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

	wp = board_mmc_getwp(mmc);

46
	if (wp < 0) {
47
48
		if (mmc->cfg->ops->getwp)
			wp = mmc->cfg->ops->getwp(mmc);
49
50
51
		else
			wp = 0;
	}
52
53
54
55

	return wp;
}

Jeroen Hofstee's avatar
Jeroen Hofstee committed
56
57
__weak int board_mmc_getcd(struct mmc *mmc)
{
58
59
	return -1;
}
60
#endif
61

62
63
#ifdef CONFIG_MMC_TRACE
void mmmc_trace_before_send(struct mmc *mmc, struct mmc_cmd *cmd)
Andy Fleming's avatar
Andy Fleming committed
64
{
65
	printf("CMD_SEND:%d\n", cmd->cmdidx);
66
	printf("\t\tARG\t\t\t 0x%08x\n", cmd->cmdarg);
67
}
68

69
70
void mmmc_trace_after_send(struct mmc *mmc, struct mmc_cmd *cmd, int ret)
{
Raffaele Recalcati's avatar
Raffaele Recalcati committed
71
72
73
	int i;
	u8 *ptr;

74
75
76
77
78
79
80
81
	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:
82
			printf("\t\tMMC_RSP_R1,5,6,7 \t 0x%08x \n",
83
84
85
				cmd->response[0]);
			break;
		case MMC_RSP_R1b:
86
			printf("\t\tMMC_RSP_R1b\t\t 0x%08x \n",
87
88
89
				cmd->response[0]);
			break;
		case MMC_RSP_R2:
90
			printf("\t\tMMC_RSP_R2\t\t 0x%08x \n",
91
				cmd->response[0]);
92
			printf("\t\t          \t\t 0x%08x \n",
93
				cmd->response[1]);
94
			printf("\t\t          \t\t 0x%08x \n",
95
				cmd->response[2]);
96
			printf("\t\t          \t\t 0x%08x \n",
97
				cmd->response[3]);
Raffaele Recalcati's avatar
Raffaele Recalcati committed
98
			printf("\n");
99
100
101
102
103
104
105
			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++)
106
					printf("%02x ", *ptr--);
107
108
109
110
				printf("\n");
			}
			break;
		case MMC_RSP_R3:
111
			printf("\t\tMMC_RSP_R3,4\t\t 0x%08x \n",
112
113
114
115
116
				cmd->response[0]);
			break;
		default:
			printf("\t\tERROR MMC rsp not supported\n");
			break;
Bin Meng's avatar
Bin Meng committed
117
		}
Raffaele Recalcati's avatar
Raffaele Recalcati committed
118
	}
119
120
121
122
123
124
125
126
127
}

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
128
#endif
129

Jean-Jacques Hiblot's avatar
Jean-Jacques Hiblot committed
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#if CONFIG_IS_ENABLED(MMC_VERBOSE) || defined(DEBUG)
const char *mmc_mode_name(enum bus_mode mode)
{
	static const char *const names[] = {
	      [MMC_LEGACY]	= "MMC legacy",
	      [SD_LEGACY]	= "SD Legacy",
	      [MMC_HS]		= "MMC High Speed (26MHz)",
	      [SD_HS]		= "SD High Speed (50MHz)",
	      [UHS_SDR12]	= "UHS SDR12 (25MHz)",
	      [UHS_SDR25]	= "UHS SDR25 (50MHz)",
	      [UHS_SDR50]	= "UHS SDR50 (100MHz)",
	      [UHS_SDR104]	= "UHS SDR104 (208MHz)",
	      [UHS_DDR50]	= "UHS DDR50 (50MHz)",
	      [MMC_HS_52]	= "MMC High Speed (52MHz)",
	      [MMC_DDR_52]	= "MMC DDR52 (52MHz)",
	      [MMC_HS_200]	= "HS200 (200MHz)",
Peng Fan's avatar
Peng Fan committed
146
	      [MMC_HS_400]	= "HS400 (200MHz)",
147
	      [MMC_HS_400_ES]	= "HS400ES (200MHz)",
Jean-Jacques Hiblot's avatar
Jean-Jacques Hiblot committed
148
149
150
151
152
153
154
155
156
	};

	if (mode >= MMC_MODES_END)
		return "Unknown mode";
	else
		return names[mode];
}
#endif

157
158
159
static uint mmc_mode2freq(struct mmc *mmc, enum bus_mode mode)
{
	static const int freqs[] = {
160
	      [MMC_LEGACY]	= 25000000,
161
162
163
	      [SD_LEGACY]	= 25000000,
	      [MMC_HS]		= 26000000,
	      [SD_HS]		= 50000000,
164
165
	      [MMC_HS_52]	= 52000000,
	      [MMC_DDR_52]	= 52000000,
166
167
168
169
	      [UHS_SDR12]	= 25000000,
	      [UHS_SDR25]	= 50000000,
	      [UHS_SDR50]	= 100000000,
	      [UHS_DDR50]	= 50000000,
170
	      [UHS_SDR104]	= 208000000,
171
	      [MMC_HS_200]	= 200000000,
Peng Fan's avatar
Peng Fan committed
172
	      [MMC_HS_400]	= 200000000,
173
	      [MMC_HS_400_ES]	= 200000000,
174
175
176
177
178
179
180
181
182
183
	};

	if (mode == MMC_LEGACY)
		return mmc->legacy_speed;
	else if (mode >= MMC_MODES_END)
		return 0;
	else
		return freqs[mode];
}

Jean-Jacques Hiblot's avatar
Jean-Jacques Hiblot committed
184
185
186
static int mmc_select_mode(struct mmc *mmc, enum bus_mode mode)
{
	mmc->selected_mode = mode;
187
	mmc->tran_speed = mmc_mode2freq(mmc, mode);
188
	mmc->ddr_mode = mmc_is_mode_ddr(mode);
Masahiro Yamada's avatar
Masahiro Yamada committed
189
190
	pr_debug("selecting mode %s (freq : %d MHz)\n", mmc_mode_name(mode),
		 mmc->tran_speed / 1000000);
Jean-Jacques Hiblot's avatar
Jean-Jacques Hiblot committed
191
192
193
	return 0;
}

Simon Glass's avatar
Simon Glass committed
194
#if !CONFIG_IS_ENABLED(DM_MMC)
195
196
197
198
199
200
201
202
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);

203
	return ret;
Andy Fleming's avatar
Andy Fleming committed
204
}
205
#endif
Andy Fleming's avatar
Andy Fleming committed
206

207
int mmc_send_status(struct mmc *mmc, unsigned int *status)
208
209
{
	struct mmc_cmd cmd;
210
	int err, retries = 5;
211
212
213

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

217
	while (retries--) {
218
		err = mmc_send_cmd(mmc, &cmd, NULL);
219
		if (!err) {
220
221
222
223
224
225
226
227
228
			mmc_trace_state(mmc, &cmd);
			*status = cmd.response[0];
			return 0;
		}
	}
	mmc_trace_state(mmc, &cmd);
	return -ECOMM;
}

229
int mmc_poll_for_busy(struct mmc *mmc, int timeout_ms)
230
231
232
{
	unsigned int status;
	int err;
233

234
	err = mmc_wait_dat0(mmc, 1, timeout_ms * 1000);
235
236
237
	if (err != -ENOSYS)
		return err;

238
239
240
241
242
243
244
245
246
247
248
	while (1) {
		err = mmc_send_status(mmc, &status);
		if (err)
			return err;

		if ((status & MMC_STATUS_RDY_FOR_DATA) &&
		    (status & MMC_STATUS_CURR_STATE) !=
		     MMC_STATE_PRG)
			break;

		if (status & MMC_STATUS_MASK) {
249
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
250
			pr_err("Status Error: 0x%08x\n", status);
251
#endif
252
253
			return -ECOMM;
		}
254

255
		if (timeout_ms-- <= 0)
256
			break;
257

258
259
		udelay(1000);
	}
260

261
	if (timeout_ms <= 0) {
262
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
263
		pr_err("Timeout waiting card ready\n");
264
#endif
265
		return -ETIMEDOUT;
266
267
268
269
270
	}

	return 0;
}

271
int mmc_set_blocklen(struct mmc *mmc, int len)
Andy Fleming's avatar
Andy Fleming committed
272
273
{
	struct mmc_cmd cmd;
274
	int err;
Andy Fleming's avatar
Andy Fleming committed
275

276
	if (mmc->ddr_mode)
277
278
		return 0;

Andy Fleming's avatar
Andy Fleming committed
279
280
281
282
	cmd.cmdidx = MMC_CMD_SET_BLOCKLEN;
	cmd.resp_type = MMC_RSP_R1;
	cmd.cmdarg = len;

283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
	err = mmc_send_cmd(mmc, &cmd, NULL);

#ifdef CONFIG_MMC_QUIRKS
	if (err && (mmc->quirks & MMC_QUIRK_RETRY_SET_BLOCKLEN)) {
		int retries = 4;
		/*
		 * It has been seen that SET_BLOCKLEN may fail on the first
		 * attempt, let's try a few more time
		 */
		do {
			err = mmc_send_cmd(mmc, &cmd, NULL);
			if (!err)
				break;
		} while (retries--);
	}
#endif

	return err;
Andy Fleming's avatar
Andy Fleming committed
301
302
}

303
#ifdef MMC_SUPPORTS_TUNING
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
static const u8 tuning_blk_pattern_4bit[] = {
	0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
	0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef,
	0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb,
	0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef,
	0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c,
	0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee,
	0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff,
	0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde,
};

static const u8 tuning_blk_pattern_8bit[] = {
	0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00,
	0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc,
	0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff,
	0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff,
	0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd,
	0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb,
	0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff,
	0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff,
	0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00,
	0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc,
	0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff,
	0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee,
	0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd,
	0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff,
	0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff,
	0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
};

int mmc_send_tuning(struct mmc *mmc, u32 opcode, int *cmd_error)
{
	struct mmc_cmd cmd;
	struct mmc_data data;
	const u8 *tuning_block_pattern;
	int size, err;

	if (mmc->bus_width == 8) {
		tuning_block_pattern = tuning_blk_pattern_8bit;
		size = sizeof(tuning_blk_pattern_8bit);
	} else if (mmc->bus_width == 4) {
		tuning_block_pattern = tuning_blk_pattern_4bit;
		size = sizeof(tuning_blk_pattern_4bit);
	} else {
		return -EINVAL;
	}

	ALLOC_CACHE_ALIGN_BUFFER(u8, data_buf, size);

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

	data.dest = (void *)data_buf;
	data.blocks = 1;
	data.blocksize = size;
	data.flags = MMC_DATA_READ;

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

	if (memcmp(data_buf, tuning_block_pattern, size))
		return -EIO;

	return 0;
}
371
#endif
372

373
static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
Kim Phillips's avatar
Kim Phillips committed
374
			   lbaint_t blkcnt)
Andy Fleming's avatar
Andy Fleming committed
375
376
377
378
{
	struct mmc_cmd cmd;
	struct mmc_data data;

379
380
381
382
	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
383
384

	if (mmc->high_capacity)
385
		cmd.cmdarg = start;
Andy Fleming's avatar
Andy Fleming committed
386
	else
387
		cmd.cmdarg = start * mmc->read_bl_len;
Andy Fleming's avatar
Andy Fleming committed
388
389
390
391

	cmd.resp_type = MMC_RSP_R1;

	data.dest = dst;
392
	data.blocks = blkcnt;
Andy Fleming's avatar
Andy Fleming committed
393
394
395
	data.blocksize = mmc->read_bl_len;
	data.flags = MMC_DATA_READ;

396
397
	if (mmc_send_cmd(mmc, &cmd, &data))
		return 0;
Andy Fleming's avatar
Andy Fleming committed
398

399
400
401
402
403
	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)) {
404
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
405
			pr_err("mmc fail to send stop cmd\n");
406
#endif
407
408
			return 0;
		}
Andy Fleming's avatar
Andy Fleming committed
409
410
	}

411
	return blkcnt;
Andy Fleming's avatar
Andy Fleming committed
412
413
}

414
#if CONFIG_IS_ENABLED(BLK)
415
ulong mmc_bread(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, void *dst)
416
#else
417
418
ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt,
		void *dst)
419
#endif
Andy Fleming's avatar
Andy Fleming committed
420
{
421
#if CONFIG_IS_ENABLED(BLK)
422
423
	struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
#endif
424
	int dev_num = block_dev->devnum;
425
	int err;
426
427
428
429
	lbaint_t cur, blocks_todo = blkcnt;

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

431
	struct mmc *mmc = find_mmc_device(dev_num);
Andy Fleming's avatar
Andy Fleming committed
432
433
434
	if (!mmc)
		return 0;

435
436
437
438
439
	if (CONFIG_IS_ENABLED(MMC_TINY))
		err = mmc_switch_part(mmc, block_dev->hwpart);
	else
		err = blk_dselect_hwpart(block_dev, block_dev->hwpart);

440
441
442
	if (err < 0)
		return 0;

443
	if ((start + blkcnt) > block_dev->lba) {
444
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
445
446
		pr_err("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
		       start + blkcnt, block_dev->lba);
447
#endif
448
449
		return 0;
	}
Andy Fleming's avatar
Andy Fleming committed
450

451
	if (mmc_set_blocklen(mmc, mmc->read_bl_len)) {
Masahiro Yamada's avatar
Masahiro Yamada committed
452
		pr_debug("%s: Failed to set blocklen\n", __func__);
Andy Fleming's avatar
Andy Fleming committed
453
		return 0;
454
	}
Andy Fleming's avatar
Andy Fleming committed
455

456
	do {
457
458
		cur = (blocks_todo > mmc->cfg->b_max) ?
			mmc->cfg->b_max : blocks_todo;
459
		if (mmc_read_blocks(mmc, dst, start, cur) != cur) {
Masahiro Yamada's avatar
Masahiro Yamada committed
460
			pr_debug("%s: Failed to read blocks\n", __func__);
461
			return 0;
462
		}
463
464
465
466
		blocks_todo -= cur;
		start += cur;
		dst += cur * mmc->read_bl_len;
	} while (blocks_todo > 0);
Andy Fleming's avatar
Andy Fleming committed
467
468
469
470

	return blkcnt;
}

Kim Phillips's avatar
Kim Phillips committed
471
static int mmc_go_idle(struct mmc *mmc)
Andy Fleming's avatar
Andy Fleming committed
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
{
	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;
}

492
#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
static int mmc_switch_voltage(struct mmc *mmc, int signal_voltage)
{
	struct mmc_cmd cmd;
	int err = 0;

	/*
	 * Send CMD11 only if the request is to switch the card to
	 * 1.8V signalling.
	 */
	if (signal_voltage == MMC_SIGNAL_VOLTAGE_330)
		return mmc_set_signal_voltage(mmc, signal_voltage);

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

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

	if (!mmc_host_is_spi(mmc) && (cmd.response[0] & MMC_STATUS_ERROR))
		return -EIO;

	/*
	 * The card should drive cmd and dat[0:3] low immediately
	 * after the response of cmd11, but wait 100 us to be sure
	 */
	err = mmc_wait_dat0(mmc, 0, 100);
	if (err == -ENOSYS)
		udelay(100);
	else if (err)
		return -ETIMEDOUT;

	/*
	 * During a signal voltage level switch, the clock must be gated
	 * for 5 ms according to the SD spec
	 */
530
	mmc_set_clock(mmc, mmc->clock, MMC_CLK_DISABLE);
531
532
533
534
535
536
537

	err = mmc_set_signal_voltage(mmc, signal_voltage);
	if (err)
		return err;

	/* Keep clock gated for at least 10 ms, though spec only says 5 ms */
	mdelay(10);
538
	mmc_set_clock(mmc, mmc->clock, MMC_CLK_ENABLE);
539
540
541
542
543
544
545
546
547
548
549
550
551

	/*
	 * Failure to switch is indicated by the card holding
	 * dat[0:3] low. Wait for at least 1 ms according to spec
	 */
	err = mmc_wait_dat0(mmc, 1, 1000);
	if (err == -ENOSYS)
		udelay(1000);
	else if (err)
		return -ETIMEDOUT;

	return 0;
}
552
#endif
553
554

static int sd_send_op_cond(struct mmc *mmc, bool uhs_en)
Andy Fleming's avatar
Andy Fleming committed
555
556
557
558
559
{
	int timeout = 1000;
	int err;
	struct mmc_cmd cmd;

560
	while (1) {
Andy Fleming's avatar
Andy Fleming committed
561
562
563
564
565
566
567
568
569
570
571
		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;
572
573
574
575
576
577
578
579

		/*
		 * 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
580
		cmd.cmdarg = mmc_host_is_spi(mmc) ? 0 :
581
			(mmc->cfg->voltages & 0xff8000);
Andy Fleming's avatar
Andy Fleming committed
582
583
584
585

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

586
587
588
		if (uhs_en)
			cmd.cmdarg |= OCR_S18R;

Andy Fleming's avatar
Andy Fleming committed
589
590
591
592
593
		err = mmc_send_cmd(mmc, &cmd, NULL);

		if (err)
			return err;

594
595
596
597
		if (cmd.response[0] & OCR_BUSY)
			break;

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

600
601
		udelay(1000);
	}
Andy Fleming's avatar
Andy Fleming committed
602
603
604
605

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

Thomas Chou's avatar
Thomas Chou committed
606
607
608
609
610
611
612
613
614
615
616
	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
617
	mmc->ocr = cmd.response[0];
Andy Fleming's avatar
Andy Fleming committed
618

619
#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
620
621
622
623
624
625
	if (uhs_en && !(mmc_host_is_spi(mmc)) && (cmd.response[0] & 0x41000000)
	    == 0x41000000) {
		err = mmc_switch_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
		if (err)
			return err;
	}
626
#endif
627

Andy Fleming's avatar
Andy Fleming committed
628
629
630
631
632
633
	mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
	mmc->rca = 0;

	return 0;
}

634
static int mmc_send_op_cond_iter(struct mmc *mmc, int use_arg)
Andy Fleming's avatar
Andy Fleming committed
635
{
636
	struct mmc_cmd cmd;
Andy Fleming's avatar
Andy Fleming committed
637
638
	int err;

639
640
641
	cmd.cmdidx = MMC_CMD_SEND_OP_COND;
	cmd.resp_type = MMC_RSP_R3;
	cmd.cmdarg = 0;
Rob Herring's avatar
Rob Herring committed
642
643
	if (use_arg && !mmc_host_is_spi(mmc))
		cmd.cmdarg = OCR_HCS |
644
			(mmc->cfg->voltages &
645
646
			(mmc->ocr & OCR_VOLTAGE_MASK)) |
			(mmc->ocr & OCR_ACCESS_MODE);
647

648
	err = mmc_send_cmd(mmc, &cmd, NULL);
649
650
	if (err)
		return err;
651
	mmc->ocr = cmd.response[0];
652
653
654
	return 0;
}

655
static int mmc_send_op_cond(struct mmc *mmc)
656
657
658
{
	int err, i;

Andy Fleming's avatar
Andy Fleming committed
659
660
661
	/* Some cards seem to need this */
	mmc_go_idle(mmc);

662
 	/* Asking to the card its capabilities */
663
	for (i = 0; i < 2; i++) {
664
		err = mmc_send_op_cond_iter(mmc, i != 0);
665
666
		if (err)
			return err;
Wolfgang Denk's avatar
Wolfgang Denk committed
667

668
		/* exit if not busy (flag seems to be inverted) */
669
		if (mmc->ocr & OCR_BUSY)
670
			break;
671
	}
672
673
	mmc->op_cond_pending = 1;
	return 0;
674
}
Wolfgang Denk's avatar
Wolfgang Denk committed
675

676
static int mmc_complete_op_cond(struct mmc *mmc)
677
678
679
{
	struct mmc_cmd cmd;
	int timeout = 1000;
680
	ulong start;
681
	int err;
Wolfgang Denk's avatar
Wolfgang Denk committed
682

683
	mmc->op_cond_pending = 0;
684
	if (!(mmc->ocr & OCR_BUSY)) {
685
686
687
		/* Some cards seem to need this */
		mmc_go_idle(mmc);

688
		start = get_timer(0);
689
		while (1) {
690
691
692
			err = mmc_send_op_cond_iter(mmc, 1);
			if (err)
				return err;
693
694
			if (mmc->ocr & OCR_BUSY)
				break;
695
			if (get_timer(start) > timeout)
696
				return -EOPNOTSUPP;
697
			udelay(100);
698
		}
699
	}
Andy Fleming's avatar
Andy Fleming committed
700

Thomas Chou's avatar
Thomas Chou committed
701
702
703
704
705
706
707
708
709
	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;
710
711

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

Andy Fleming's avatar
Andy Fleming committed
714
715
716
	mmc->version = MMC_VERSION_UNKNOWN;

	mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
717
	mmc->rca = 1;
Andy Fleming's avatar
Andy Fleming committed
718
719
720
721
722

	return 0;
}


Kim Phillips's avatar
Kim Phillips committed
723
static int mmc_send_ext_csd(struct mmc *mmc, u8 *ext_csd)
Andy Fleming's avatar
Andy Fleming committed
724
725
726
727
728
729
730
731
732
733
{
	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;

734
	data.dest = (char *)ext_csd;
Andy Fleming's avatar
Andy Fleming committed
735
	data.blocks = 1;
736
	data.blocksize = MMC_MAX_BLOCK_LEN;
Andy Fleming's avatar
Andy Fleming committed
737
738
739
740
741
742
743
	data.flags = MMC_DATA_READ;

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

	return err;
}

744
745
static int __mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value,
			bool send_status)
Andy Fleming's avatar
Andy Fleming committed
746
{
747
	unsigned int status, start;
Andy Fleming's avatar
Andy Fleming committed
748
	struct mmc_cmd cmd;
749
	int timeout_ms = DEFAULT_CMD6_TIMEOUT_MS;
750
751
	bool is_part_switch = (set == EXT_CSD_CMD_SET_NORMAL) &&
			      (index == EXT_CSD_PART_CONF);
Maxime Ripard's avatar
Maxime Ripard committed
752
	int retries = 3;
753
	int ret;
Andy Fleming's avatar
Andy Fleming committed
754

755
	if (mmc->gen_cmd6_time)
756
		timeout_ms = mmc->gen_cmd6_time * 10;
757

758
	if (is_part_switch  && mmc->part_switch_time)
759
		timeout_ms = mmc->part_switch_time * 10;
760

Andy Fleming's avatar
Andy Fleming committed
761
762
763
	cmd.cmdidx = MMC_CMD_SWITCH;
	cmd.resp_type = MMC_RSP_R1b;
	cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
764
765
				 (index << 16) |
				 (value << 8);
Andy Fleming's avatar
Andy Fleming committed
766

767
	do {
Maxime Ripard's avatar
Maxime Ripard committed
768
		ret = mmc_send_cmd(mmc, &cmd, NULL);
769
	} while (ret && retries-- > 0);
770

771
772
	if (ret)
		return ret;
773

774
	start = get_timer(0);
Maxime Ripard's avatar
Maxime Ripard committed
775

776
	/* poll dat0 for rdy/buys status */
777
	ret = mmc_wait_dat0(mmc, 1, timeout_ms * 1000);
778
779
	if (ret && ret != -ENOSYS)
		return ret;
780

781
782
783
784
785
786
	/*
	 * In cases when not allowed to poll by using CMD13 or because we aren't
	 * capable of polling by using mmc_wait_dat0, then rely on waiting the
	 * stated timeout to be sufficient.
	 */
	if (ret == -ENOSYS && !send_status)
787
		mdelay(timeout_ms);
788
789
790

	/* Finally wait until the card is ready or indicates a failure
	 * to switch. It doesn't hurt to use CMD13 here even if send_status
791
	 * is false, because by now (after 'timeout_ms' ms) the bus should be
792
793
794
795
796
797
798
799
800
801
802
803
804
	 * reliable.
	 */
	do {
		ret = mmc_send_status(mmc, &status);

		if (!ret && (status & MMC_STATUS_SWITCH_ERROR)) {
			pr_debug("switch failed %d/%d/0x%x !\n", set, index,
				 value);
			return -EIO;
		}
		if (!ret && (status & MMC_STATUS_RDY_FOR_DATA))
			return 0;
		udelay(100);
805
	} while (get_timer(start) < timeout_ms);
806

807
	return -ETIMEDOUT;
Andy Fleming's avatar
Andy Fleming committed
808
809
}

810
811
812
813
814
int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
{
	return __mmc_switch(mmc, set, index, value, true);
}

Marek Vasut's avatar
Marek Vasut committed
815
#if !CONFIG_IS_ENABLED(MMC_TINY)
816
817
static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode,
			      bool hsdowngrade)
Andy Fleming's avatar
Andy Fleming committed
818
819
{
	int err;
820
821
822
823
824
825
826
827
828
	int speed_bits;

	ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, MMC_MAX_BLOCK_LEN);

	switch (mode) {
	case MMC_HS:
	case MMC_HS_52:
	case MMC_DDR_52:
		speed_bits = EXT_CSD_TIMING_HS;
829
		break;
830
#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
831
832
833
	case MMC_HS_200:
		speed_bits = EXT_CSD_TIMING_HS200;
		break;
Peng Fan's avatar
Peng Fan committed
834
835
836
837
838
#endif
#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
	case MMC_HS_400:
		speed_bits = EXT_CSD_TIMING_HS400;
		break;
839
840
841
842
843
#endif
#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
	case MMC_HS_400_ES:
		speed_bits = EXT_CSD_TIMING_HS400;
		break;
844
#endif
845
846
847
848
849
850
	case MMC_LEGACY:
		speed_bits = EXT_CSD_TIMING_LEGACY;
		break;
	default:
		return -EINVAL;
	}
851
852
853

	err = __mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
			   speed_bits, !hsdowngrade);
854
855
856
	if (err)
		return err;

857
858
859
860
861
862
863
864
865
866
867
868
869
870
#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
    CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
	/*
	 * In case the eMMC is in HS200/HS400 mode and we are downgrading
	 * to HS mode, the card clock are still running much faster than
	 * the supported HS mode clock, so we can not reliably read out
	 * Extended CSD. Reconfigure the controller to run at HS mode.
	 */
	if (hsdowngrade) {
		mmc_select_mode(mmc, MMC_HS);
		mmc_set_clock(mmc, mmc_mode2freq(mmc, MMC_HS), false);
	}
#endif

871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
	if ((mode == MMC_HS) || (mode == MMC_HS_52)) {
		/* Now check to see that it worked */
		err = mmc_send_ext_csd(mmc, test_csd);
		if (err)
			return err;

		/* No high-speed support */
		if (!test_csd[EXT_CSD_HS_TIMING])
			return -ENOTSUPP;
	}

	return 0;
}

static int mmc_get_capabilities(struct mmc *mmc)
{
	u8 *ext_csd = mmc->ext_csd;
	char cardtype;
Andy Fleming's avatar
Andy Fleming committed
889

890
	mmc->card_caps = MMC_MODE_1BIT | MMC_CAP(MMC_LEGACY);
Andy Fleming's avatar
Andy Fleming committed
891

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
	/* Only version 4 supports high-speed */
	if (mmc->version < MMC_VERSION_4)
		return 0;

899
	if (!ext_csd) {
900
		pr_err("No ext_csd found!\n"); /* this should enver happen */
901
902
		return -ENOTSUPP;
	}
Andy Fleming's avatar
Andy Fleming committed
903

904
	mmc->card_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT;
Andy Fleming's avatar
Andy Fleming committed
905

Peng Fan's avatar
Peng Fan committed
906
	cardtype = ext_csd[EXT_CSD_CARD_TYPE];
907
	mmc->cardtype = cardtype;
Andy Fleming's avatar
Andy Fleming committed
908

909
#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
910
911
912
913
	if (cardtype & (EXT_CSD_CARD_TYPE_HS200_1_2V |
			EXT_CSD_CARD_TYPE_HS200_1_8V)) {
		mmc->card_caps |= MMC_MODE_HS200;
	}
Peng Fan's avatar
Peng Fan committed
914
#endif
915
916
#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) || \
	CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
Peng Fan's avatar
Peng Fan committed
917
918
919
920
	if (cardtype & (EXT_CSD_CARD_TYPE_HS400_1_2V |
			EXT_CSD_CARD_TYPE_HS400_1_8V)) {
		mmc->card_caps |= MMC_MODE_HS400;
	}
921
#endif
922
	if (cardtype & EXT_CSD_CARD_TYPE_52) {
923
		if (cardtype & EXT_CSD_CARD_TYPE_DDR_52)
924
			mmc->card_caps |= MMC_MODE_DDR_52MHz;
925
		mmc->card_caps |= MMC_MODE_HS_52MHz;
926
	}
927
928
	if (cardtype & EXT_CSD_CARD_TYPE_26)
		mmc->card_caps |= MMC_MODE_HS;
Andy Fleming's avatar
Andy Fleming committed
929

930
931
932
933
934
935
936
#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
	if (ext_csd[EXT_CSD_STROBE_SUPPORT] &&
	    (mmc->card_caps & MMC_MODE_HS400)) {
		mmc->card_caps |= MMC_MODE_HS400_ES;
	}
#endif

Andy Fleming's avatar
Andy Fleming committed
937
938
	return 0;
}
Marek Vasut's avatar
Marek Vasut committed
939
#endif
Andy Fleming's avatar
Andy Fleming committed
940

941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
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;
	}

964
	mmc_get_blk_desc(mmc)->lba = lldiv(mmc->capacity, mmc->read_bl_len);
965
966
967
968

	return 0;
}

969
int mmc_switch_part(struct mmc *mmc, unsigned int part_num)
970
{
971
	int ret;
972
	int retry = 3;
973

974
975
976
977
978
979
	do {
		ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
				 EXT_CSD_PART_CONF,
				 (mmc->part_config & ~PART_ACCESS_MASK)
				 | (part_num & PART_ACCESS_MASK));
	} while (ret && retry--);
980

981
982
983
984
	/*
	 * Set the capacity if the switch succeeded or was intended
	 * to return to representing the raw device.
	 */
985
	if ((ret == 0) || ((ret == -ENODEV) && (part_num == 0))) {
986
		ret = mmc_set_capacity(mmc, part_num);
987
		mmc_get_blk_desc(mmc)->hwpart = part_num;
988
	}
989
990

	return ret;
991
992
}

993
#if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING)
994
995
996
997
998
999
1000
1001
1002
1003
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;
1004
	u8 wr_rel_set;
1005
1006
1007
1008
1009
1010
1011
	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)) {
1012
		pr_err("eMMC >= 4.4 required for enhanced user data area\n");
1013
1014
1015
1016
		return -EMEDIUMTYPE;
	}

	if (!(mmc->part_support & PART_SUPPORT)) {
1017
		pr_err("Card does not support partitioning\n");
1018
1019
1020
1021
		return -EMEDIUMTYPE;
	}

	if (!mmc->hc_wp_grp_size) {
1022
		pr_err("Card does not define HC WP group size\n");
1023
1024
1025
1026
1027
1028
1029
		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) {
1030
			pr_err("User data enhanced area not HC WP group "
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
			       "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) {
1049
			pr_err("GP%i partition not HC WP group size "
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
			       "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)) {
1061
		pr_err("Card does not support enhanced attribute\n");
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
		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) {
1074
		pr_err("Total enhanced size exceeds maximum (%u > %u)\n",
1075
1076
1077
1078
		       tot_enh_size_mult, max_enh_size_mult);
		return -EMEDIUMTYPE;
	}

1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
	/* 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;
	}

1106
1107
	if (ext_csd[EXT_CSD_PARTITION_SETTING] &
	    EXT_CSD_PARTITION_SETTING_COMPLETED) {
1108
		pr_err("Card already partitioned\n");
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
		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;

1125
#if CONFIG_IS_ENABLED(MMC_WRITE)
1126
1127
1128
		/* update erase group size to be high-capacity */
		mmc->erase_grp_size =
			ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] * 1024;
1129
#endif
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164

	}

	/* 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;