sdhci.c 20.8 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
 * Copyright 2011, Marvell Semiconductor Inc.
 * Lei Wen <leiwen@marvell.com>
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * Back ported to the 8xx platform (from the 8260 platform) by
 * Murray.Jensen@cmst.csiro.au, 27-Jan-01.
 */

22
#include <libpayload.h>
23

24
#include "drivers/storage/blockdev.h"
25
#include "drivers/storage/mmc.h"
26
#include "drivers/storage/sdhci.h"
27

28
static void sdhci_reset(SdhciHost *host, u8 mask)
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
{
	unsigned long timeout;

	/* Wait max 100 ms */
	timeout = 100;
	sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET);
	while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) {
		if (timeout == 0) {
			printf("Reset 0x%x never completed.\n", (int)mask);
			return;
		}
		timeout--;
		udelay(1000);
	}
}

45
static void sdhci_cmd_done(SdhciHost *host, MmcCommand *cmd)
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
{
	int i;
	if (cmd->resp_type & MMC_RSP_136) {
		/* CRC is stripped so we need to do some shifting. */
		for (i = 0; i < 4; i++) {
			cmd->response[i] = sdhci_readl(host,
					SDHCI_RESPONSE + (3-i)*4) << 8;
			if (i != 3)
				cmd->response[i] |= sdhci_readb(host,
						SDHCI_RESPONSE + (3-i)*4-1);
		}
	} else {
		cmd->response[0] = sdhci_readl(host, SDHCI_RESPONSE);
	}
}

62
static void sdhci_transfer_pio(SdhciHost *host, MmcData *data)
63
64
65
66
67
68
69
70
71
72
73
74
{
	int i;
	char *offs;
	for (i = 0; i < data->blocksize; i += 4) {
		offs = data->dest + i;
		if (data->flags == MMC_DATA_READ)
			*(u32 *)offs = sdhci_readl(host, SDHCI_BUFFER);
		else
			sdhci_writel(host, *(u32 *)offs, SDHCI_BUFFER);
	}
}

75
static int sdhci_transfer_data(SdhciHost *host, MmcData *data,
Vadim Bendebury's avatar
Vadim Bendebury committed
76
			       unsigned int start_addr)
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
{
	unsigned int stat, rdy, mask, timeout, block = 0;

	timeout = 1000000;
	rdy = SDHCI_INT_SPACE_AVAIL | SDHCI_INT_DATA_AVAIL;
	mask = SDHCI_DATA_AVAILABLE | SDHCI_SPACE_AVAILABLE;
	do {
		stat = sdhci_readl(host, SDHCI_INT_STATUS);
		if (stat & SDHCI_INT_ERROR) {
			printf("Error detected in status(0x%X)!\n", stat);
			return -1;
		}
		if (stat & rdy) {
			if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & mask))
				continue;
			sdhci_writel(host, rdy, SDHCI_INT_STATUS);
			sdhci_transfer_pio(host, data);
			data->dest += data->blocksize;
			if (++block >= data->blocks)
				break;
		}
		if (timeout-- > 0)
			udelay(10);
		else {
			printf("Transfer data timeout\n");
			return -1;
		}
	} while (!(stat & SDHCI_INT_DATA_END));
	return 0;
}

108
static void sdhci_alloc_adma_descs(SdhciHost *host, u32 need_descriptors)
Vadim Bendebury's avatar
Vadim Bendebury committed
109
110
111
112
113
114
115
116
117
118
{
	if (host->adma_descs) {
		if (host->adma_desc_count < need_descriptors) {
			/* Previously allocated array is too small */
			free(host->adma_descs);
			host->adma_desc_count = 0;
			host->adma_descs = NULL;
		}
	}

119
	/* use dma_malloc() to make sure we get the coherent/uncached memory */
Vadim Bendebury's avatar
Vadim Bendebury committed
120
	if (!host->adma_descs) {
121
122
123
124
		host->adma_descs = dma_malloc(need_descriptors *
					      sizeof(*host->adma_descs));
		if (host->adma_descs == NULL)
			die("fail to malloc adma_descs\n");
Vadim Bendebury's avatar
Vadim Bendebury committed
125
126
127
128
129
		host->adma_desc_count = need_descriptors;
	}

	memset(host->adma_descs, 0, sizeof(*host->adma_descs) *
	       need_descriptors);
130
131
132
133
134
135
136
137
138
139
140
141
142
}

static void sdhci_alloc_adma64_descs(SdhciHost *host, u32 need_descriptors)
{
	if (host->adma64_descs) {
		if (host->adma_desc_count < need_descriptors) {
			/* Previously allocated array is too small */
			free(host->adma64_descs);
			host->adma_desc_count = 0;
			host->adma64_descs = NULL;
		}
	}

143
	/* use dma_malloc() to make sure we get the coherent/uncached memory */
144
	if (!host->adma64_descs) {
145
		host->adma64_descs = dma_malloc(need_descriptors *
146
					   sizeof(*host->adma64_descs));
147
148
149
		if (host->adma64_descs == NULL)
			die("fail to malloc adma64_descs\n");

150
151
152
153
154
155
156
		host->adma_desc_count = need_descriptors;
	}

	memset(host->adma64_descs, 0, sizeof(*host->adma64_descs) *
	       need_descriptors);
}

157
158
static int sdhci_setup_adma(SdhciHost *host, MmcData *data,
			    struct bounce_buffer *bbstate)
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
{
	int i, togo, need_descriptors;
	char *buffer_data;
	u16 attributes;

	togo = data->blocks * data->blocksize;
	if (!togo) {
		printf("%s: MmcData corrupted: %d blocks of %d bytes\n",
		       __func__, data->blocks, data->blocksize);
		return -1;
	}

	need_descriptors = 1 +  togo / SDHCI_MAX_PER_DESCRIPTOR;

	if (host->dma64)
		sdhci_alloc_adma64_descs(host, need_descriptors);
	else
		sdhci_alloc_adma_descs(host, need_descriptors);

178
179
180
181
	if (bbstate)
		buffer_data = (char *)bbstate->bounce_buffer;
	else
		buffer_data = data->dest;
Vadim Bendebury's avatar
Vadim Bendebury committed
182
183
184
185
186
187
188
189
190

	/* Now set up the descriptor chain. */
	for (i = 0; togo; i++) {
		unsigned desc_length;

		if (togo < SDHCI_MAX_PER_DESCRIPTOR)
			desc_length = togo;
		else
			desc_length = SDHCI_MAX_PER_DESCRIPTOR;
191
		togo -= desc_length;
Vadim Bendebury's avatar
Vadim Bendebury committed
192

193
194
195
196
197
		attributes = SDHCI_ADMA_VALID | SDHCI_ACT_TRAN;
		if (togo == 0)
			attributes |= SDHCI_ADMA_END;

		if (host->dma64) {
198
			host->adma64_descs[i].addr = (uintptr_t) buffer_data;
199
200
201
202
203
			host->adma64_descs[i].addr_hi = 0;
			host->adma64_descs[i].length = desc_length;
			host->adma64_descs[i].attributes = attributes;

		} else {
204
			host->adma_descs[i].addr = (uintptr_t) buffer_data;
205
206
207
			host->adma_descs[i].length = desc_length;
			host->adma_descs[i].attributes = attributes;
		}
Vadim Bendebury's avatar
Vadim Bendebury committed
208
209
210
211

		buffer_data += desc_length;
	}

212
	if (host->dma64)
213
		sdhci_writel(host, (uintptr_t) host->adma64_descs,
214
215
			     SDHCI_ADMA_ADDRESS);
	else
216
		sdhci_writel(host, (uintptr_t) host->adma_descs,
217
			     SDHCI_ADMA_ADDRESS);
Vadim Bendebury's avatar
Vadim Bendebury committed
218
219
220
221

	return 0;
}

222
static int sdhci_complete_adma(SdhciHost *host, MmcCommand *cmd)
Vadim Bendebury's avatar
Vadim Bendebury committed
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
{
	int retry;
	u32 stat = 0, mask;

	mask = SDHCI_INT_RESPONSE | SDHCI_INT_ERROR;

	retry = 10000; /* Command should be done in way less than 10 ms. */
	while (--retry) {
		stat = sdhci_readl(host, SDHCI_INT_STATUS);
		if (stat & mask)
			break;
		udelay(1);
	}

	sdhci_writel(host, SDHCI_INT_RESPONSE, SDHCI_INT_STATUS);

	if (retry && !(stat & SDHCI_INT_ERROR)) {
		/* Command OK, let's wait for data transfer completion. */
		mask = SDHCI_INT_DATA_END |
			SDHCI_INT_ERROR | SDHCI_INT_ADMA_ERROR;

		/* Transfer should take 10 seconds tops. */
		retry = 10 * 1000 * 1000;
		while (--retry) {
			stat = sdhci_readl(host, SDHCI_INT_STATUS);
			if (stat & mask)
				break;
			udelay(1);
		}

253
254
255
		sdhci_writel(host, stat, SDHCI_INT_STATUS);
		if (retry && !(stat & SDHCI_INT_ERROR)) {
			sdhci_cmd_done(host, cmd);
Vadim Bendebury's avatar
Vadim Bendebury committed
256
			return 0;
257
		}
Vadim Bendebury's avatar
Vadim Bendebury committed
258
259
	}

260
261
	printf("%s: transfer error, stat %#x, adma error %#x, retry %d\n",
	       __func__, stat, sdhci_readl(host, SDHCI_ADMA_ERROR), retry);
Vadim Bendebury's avatar
Vadim Bendebury committed
262
263
264
265
266
267
268
269
270
271

	sdhci_reset(host, SDHCI_RESET_CMD);
	sdhci_reset(host, SDHCI_RESET_DATA);

	if (stat & SDHCI_INT_TIMEOUT)
		return MMC_TIMEOUT;
	else
		return MMC_COMM_ERR;
}

272
273
274
static int sdhci_send_command_bounced(MmcCtrlr *mmc_ctrl, MmcCommand *cmd,
				      MmcData *data,
				      struct bounce_buffer *bbstate)
275
276
277
{
	unsigned int stat = 0;
	int ret = 0;
278
	u32 mask, flags;
279
	unsigned int timeout, start_addr = 0;
280
	uint64_t start;
281
	SdhciHost *host = container_of(mmc_ctrl, SdhciHost, mmc_ctrlr);
282

283
284
	/* Wait max 1 s */
	timeout = 1000;
285
286
287
288
289
290
291
292
293
294
295

	sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_INT_STATUS);
	mask = SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT;

	/* We shouldn't wait for data inihibit for stop commands, even
	   though they might use busy signaling */
	if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
		mask &= ~SDHCI_DATA_INHIBIT;

	while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) {
		if (timeout == 0) {
296
297
298
			printf("Controller never released inhibit bit(s), "
			       "present state %#8.8x.\n",
			       sdhci_readl(host, SDHCI_PRESENT_STATE));
299
			return MMC_COMM_ERR;
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
		}
		timeout--;
		udelay(1000);
	}

	mask = SDHCI_INT_RESPONSE;
	if (!(cmd->resp_type & MMC_RSP_PRESENT))
		flags = SDHCI_CMD_RESP_NONE;
	else if (cmd->resp_type & MMC_RSP_136)
		flags = SDHCI_CMD_RESP_LONG;
	else if (cmd->resp_type & MMC_RSP_BUSY) {
		flags = SDHCI_CMD_RESP_SHORT_BUSY;
		mask |= SDHCI_INT_DATA_END;
	} else
		flags = SDHCI_CMD_RESP_SHORT;

	if (cmd->resp_type & MMC_RSP_CRC)
		flags |= SDHCI_CMD_CRC;
	if (cmd->resp_type & MMC_RSP_OPCODE)
		flags |= SDHCI_CMD_INDEX;
	if (data)
		flags |= SDHCI_CMD_DATA;

323
	/* Set Transfer mode regarding to data flag */
Vadim Bendebury's avatar
Vadim Bendebury committed
324
	if (data) {
325
		u16 mode = 0;
Vadim Bendebury's avatar
Vadim Bendebury committed
326

327
		sdhci_writew(host, SDHCI_MAKE_BLKSZ(SDHCI_DEFAULT_BOUNDARY_ARG,
Vadim Bendebury's avatar
Vadim Bendebury committed
328
329
						    data->blocksize),
			     SDHCI_BLOCK_SIZE);
330
331
332
333
334
335
336
337

		if (data->flags == MMC_DATA_READ)
			mode |= SDHCI_TRNS_READ;

		if (data->blocks > 1)
			mode |= SDHCI_TRNS_BLK_CNT_EN |
				SDHCI_TRNS_MULTI | SDHCI_TRNS_ACMD12;

338
		sdhci_writew(host, data->blocks, SDHCI_BLOCK_COUNT);
339
340

		if (host->host_caps & MMC_AUTO_CMD12) {
341
			if (sdhci_setup_adma(host, data, bbstate))
342
343
344
345
346
				return -1;

			mode |= SDHCI_TRNS_DMA;
		}
		sdhci_writew(host, mode, SDHCI_TRANSFER_MODE);
347
348
349
350
351
	} else {
		/* Quirk: Some AMD chipsets require the cleraring the
		 * transfer mode 0 before sending a command without data.
		 * Commands with data always set the transfer mode */
		sdhci_writew(host, 0, SDHCI_TRANSFER_MODE);
352
353
354
355
	}

	sdhci_writel(host, cmd->cmdarg, SDHCI_ARGUMENT);
	sdhci_writew(host, SDHCI_MAKE_CMD(cmd->cmdidx, flags), SDHCI_COMMAND);
Vadim Bendebury's avatar
Vadim Bendebury committed
356
357

	if (data && (host->host_caps & MMC_AUTO_CMD12))
358
		return sdhci_complete_adma(host, cmd);
Vadim Bendebury's avatar
Vadim Bendebury committed
359

360
	start = timer_us(0);
361
362
363
364
365
	do {
		stat = sdhci_readl(host, SDHCI_INT_STATUS);
		if (stat & SDHCI_INT_ERROR)
			break;

366
367
368
369
370
371
372
373
374
		/* Apply max timeout for R1b-type CMD defined in eMMC ext_csd
		   except for erase ones */
		if (timer_us(start) > 2550000) {
			if (host->quirks & SDHCI_QUIRK_BROKEN_R1B)
				return 0;
			else {
				printf("Timeout for status update!\n");
				return MMC_TIMEOUT;
			}
375
		}
376
	} while ((stat & mask) != mask);
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391

	if ((stat & (SDHCI_INT_ERROR | mask)) == mask) {
		sdhci_cmd_done(host, cmd);
		sdhci_writel(host, mask, SDHCI_INT_STATUS);
	} else
		ret = -1;

	if (!ret && data)
		ret = sdhci_transfer_data(host, data, start_addr);

	if (host->quirks & SDHCI_QUIRK_WAIT_SEND_CMD)
		udelay(1000);

	stat = sdhci_readl(host, SDHCI_INT_STATUS);
	sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_INT_STATUS);
392
393

	if (!ret)
394
395
396
397
398
		return 0;

	sdhci_reset(host, SDHCI_RESET_CMD);
	sdhci_reset(host, SDHCI_RESET_DATA);
	if (stat & SDHCI_INT_TIMEOUT)
399
		return MMC_TIMEOUT;
400
	else
401
		return MMC_COMM_ERR;
402
403
}

404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
static int sdhci_send_command(MmcCtrlr *mmc_ctrl, MmcCommand *cmd,
			      MmcData *data)
{
	void *buf;
	unsigned int bbflags;
	size_t len;
	struct bounce_buffer *bbstate = NULL;
	struct bounce_buffer bbstate_val;
	int ret;

	if (data) {
		if (data->flags & MMC_DATA_READ) {
			buf = data->dest;
			bbflags = GEN_BB_WRITE;
		} else {
			buf = (void *)data->src;
			bbflags = GEN_BB_READ;
		}
		len = data->blocks * data->blocksize;

		/*
		 * on some platform(like rk3399 etc) need to worry about
		 * cache coherency, so check the buffer, if not dma
		 * coherent, use bounce_buffer to do DMA management.
		 */
		if (!dma_coherent(buf)) {
			bbstate = &bbstate_val;
431
432
433
434
			if (bounce_buffer_start(bbstate, buf, len, bbflags)) {
				printf("ERROR: Failed to get bounce buffer.\n");
				return -1;
			}
435
436
437
438
439
		}
	}

	ret = sdhci_send_command_bounced(mmc_ctrl, cmd, data, bbstate);

440
	if (bbstate)
441
442
443
444
445
		bounce_buffer_stop(bbstate);

	return ret;
}

446
static int sdhci_set_clock(SdhciHost *host, unsigned int clock)
447
448
449
450
451
452
453
454
455
456
{
	unsigned int div, clk, timeout;

	sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);

	if (clock == 0)
		return 0;

	if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300) {
		/* Version 3.00 divisors must be a multiple of 2. */
457
		if (host->clock_base <= clock)
458
459
460
			div = 1;
		else {
			for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; div += 2) {
461
				if ((host->clock_base / div) <= clock)
462
463
464
465
466
467
					break;
			}
		}
	} else {
		/* Version 2.00 divisors must be a power of 2. */
		for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) {
468
			if ((host->clock_base / div) <= clock)
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
				break;
		}
	}
	div >>= 1;

	clk = (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
	clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
		<< SDHCI_DIVIDER_HI_SHIFT;
	clk |= SDHCI_CLOCK_INT_EN;
	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);

	/* Wait max 20 ms */
	timeout = 20;
	while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
		& SDHCI_CLOCK_INT_STABLE)) {
		if (timeout == 0) {
			printf("Internal clock never stabilised.\n");
			return -1;
		}
		timeout--;
		udelay(1000);
	}

	clk |= SDHCI_CLOCK_CARD_EN;
	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
494
495
496

	host->clock = host->mmc_ctrlr.bus_hz;

497
498
499
	return 0;
}

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
530
/* Find leftmost set bit in a 32 bit integer */
static int fls(u32 x)
{
	int r = 32;

	if (!x)
		return 0;
	if (!(x & 0xffff0000u)) {
		x <<= 16;
		r -= 16;
	}
	if (!(x & 0xff000000u)) {
		x <<= 8;
		r -= 8;
	}
	if (!(x & 0xf0000000u)) {
		x <<= 4;
		r -= 4;
	}
	if (!(x & 0xc0000000u)) {
		x <<= 2;
		r -= 2;
	}
	if (!(x & 0x80000000u)) {
		x <<= 1;
		r -= 1;
	}
	return r;
}

static void sdhci_set_power(SdhciHost *host, unsigned short power)
531
532
533
534
535
536
537
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
{
	u8 pwr = 0;

	if (power != (unsigned short)-1) {
		switch (1 << power) {
		case MMC_VDD_165_195:
			pwr = SDHCI_POWER_180;
			break;
		case MMC_VDD_29_30:
		case MMC_VDD_30_31:
			pwr = SDHCI_POWER_300;
			break;
		case MMC_VDD_32_33:
		case MMC_VDD_33_34:
			pwr = SDHCI_POWER_330;
			break;
		}
	}

	if (pwr == 0) {
		sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
		return;
	}

	if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER)
		sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);

	pwr |= SDHCI_POWER_ON;

	sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
}

563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
void sdhci_set_uhs_signaling(SdhciHost *host, uint32_t timing)
{
	u16 ctrl_2;

	ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
	/* Select Bus Speed Mode for host */
	ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;

	if ((timing != MMC_TIMING_LEGACY) &&
	    (timing != MMC_TIMING_MMC_HS) &&
	    (timing != MMC_TIMING_SD_HS))
		ctrl_2 |= SDHCI_CTRL_VDD_180;

	if ((timing == MMC_TIMING_MMC_HS200) ||
	    (timing == MMC_TIMING_UHS_SDR104))
		ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_DRV_TYPE_A;
	else if (timing == MMC_TIMING_UHS_SDR12)
		ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
	else if (timing == MMC_TIMING_UHS_SDR25)
		ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
	else if (timing == MMC_TIMING_UHS_SDR50)
		ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
	else if ((timing == MMC_TIMING_UHS_DDR50) ||
		 (timing == MMC_TIMING_MMC_DDR52))
		ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
	else if (timing == MMC_TIMING_MMC_HS400 ||
		 timing == MMC_TIMING_MMC_HS400ES)
		ctrl_2 |= SDHCI_CTRL_HS400 | SDHCI_CTRL_DRV_TYPE_A;

	sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
}

595
void sdhci_set_ios(MmcCtrlr *mmc_ctrlr)
596
597
{
	u32 ctrl;
598
	SdhciHost *host = container_of(mmc_ctrlr,
599
				       SdhciHost, mmc_ctrlr);
600
601
602
603

	if (host->set_control_reg)
		host->set_control_reg(host);

604
605
	if (mmc_ctrlr->bus_hz != host->clock)
		sdhci_set_clock(host, mmc_ctrlr->bus_hz);
606

607
	/* Switch to 1.8 volt for HS200 */
608
609
610
	if (mmc_ctrlr->caps & MMC_MODE_1V8_VDD)
		if (mmc_ctrlr->bus_hz == MMC_CLOCK_200MHZ)
			sdhci_set_power(host, MMC_VDD_165_195_SHIFT);
611

612
613
	/* Set bus width */
	ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
614
	if (mmc_ctrlr->bus_width == 8) {
615
616
617
618
619
620
		ctrl &= ~SDHCI_CTRL_4BITBUS;
		if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300)
			ctrl |= SDHCI_CTRL_8BITBUS;
	} else {
		if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300)
			ctrl &= ~SDHCI_CTRL_8BITBUS;
621
		if (mmc_ctrlr->bus_width == 4)
622
623
624
625
626
			ctrl |= SDHCI_CTRL_4BITBUS;
		else
			ctrl &= ~SDHCI_CTRL_4BITBUS;
	}

Ziyuan Xu's avatar
Ziyuan Xu committed
627
628
	if (!(mmc_ctrlr->timing == MMC_TIMING_LEGACY) &&
	    !(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT))
629
630
631
632
		ctrl |= SDHCI_CTRL_HISPD;
	else
		ctrl &= ~SDHCI_CTRL_HISPD;

633
634
	sdhci_set_uhs_signaling(host, mmc_ctrlr->timing);

Vadim Bendebury's avatar
Vadim Bendebury committed
635
636
	if (host->host_caps & MMC_AUTO_CMD12) {
		ctrl &= ~SDHCI_CTRL_DMA_MASK;
637
638
639
640
		if (host->dma64)
			ctrl |= SDHCI_CTRL_ADMA64;
		else
			ctrl |= SDHCI_CTRL_ADMA32;
Vadim Bendebury's avatar
Vadim Bendebury committed
641
642
	}

643
644
645
	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
}

646
647
648
/* Prepare SDHCI controller to be initialized */
static int sdhci_pre_init(SdhciHost *host)
{
649
	unsigned int caps, caps_1;
650
651
652
653
654
655
656

	if (host->attach) {
		int rv = host->attach(host);
		if (rv)
			return rv;
	}

657
658
	host->version = sdhci_readw(host, SDHCI_HOST_VERSION) & 0xff;

659
	caps = sdhci_readl(host, SDHCI_CAPABILITIES);
660
661
662
663
664
	caps_1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);

	if ((caps_1 & SDHCI_SUPPORT_HS400) &&
	   (host->quirks & SDHCI_QUIRK_SUPPORTS_HS400ES))
		host->host_caps |= MMC_MODE_HS400ES;
665

Vadim Bendebury's avatar
Vadim Bendebury committed
666
667
668
	if (caps & SDHCI_CAN_DO_ADMA2)
		host->host_caps |= MMC_AUTO_CMD12;

669
	/* get base clock frequency from CAP register */
670
671
672
673
674
675
676
677
	if (!(host->quirks & SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN)) {
		if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300)
			host->clock_base = (caps & SDHCI_CLOCK_V3_BASE_MASK)
				>> SDHCI_CLOCK_BASE_SHIFT;
		else
			host->clock_base = (caps & SDHCI_CLOCK_BASE_MASK)
				>> SDHCI_CLOCK_BASE_SHIFT;
	}
678

679
680
681
	if (host->clock_base == 0) {
		printf("Hardware doesn't specify base clock frequency\n");
		return -1;
682
	}
683

684
685
686
687
688
689
	host->clock_base *= 1000000;

	if (host->clock_f_max)
		host->mmc_ctrlr.f_max = host->clock_f_max;
	else
		host->mmc_ctrlr.f_max = host->clock_base;
690
691
692
693
694
695

	if (host->clock_f_min) {
		host->mmc_ctrlr.f_min = host->clock_f_min;
	} else {
		if ((host->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300)
			host->mmc_ctrlr.f_min =
696
				host->clock_base / SDHCI_MAX_DIV_SPEC_300;
697
698
		else
			host->mmc_ctrlr.f_min =
699
				host->clock_base / SDHCI_MAX_DIV_SPEC_200;
700
701
702
703
704
705
706
707
708
709
710
711
	}

	if (caps & SDHCI_CAN_VDD_330)
		host->mmc_ctrlr.voltages |= MMC_VDD_32_33 | MMC_VDD_33_34;
	if (caps & SDHCI_CAN_VDD_300)
		host->mmc_ctrlr.voltages |= MMC_VDD_29_30 | MMC_VDD_30_31;
	if (caps & SDHCI_CAN_VDD_180)
		host->mmc_ctrlr.voltages |= MMC_VDD_165_195;

	if (host->quirks & SDHCI_QUIRK_BROKEN_VOLTAGE)
		host->mmc_ctrlr.voltages |= host->voltages;

712
713
714
715
716
717
718
719
720
721
	if (host->quirks & SDHCI_QUIRK_NO_EMMC_HS200)
		host->mmc_ctrlr.caps = MMC_MODE_HS | MMC_MODE_HS_52MHz |
			MMC_MODE_4BIT | MMC_MODE_HC;
	else
		host->mmc_ctrlr.caps = MMC_MODE_HS | MMC_MODE_HS_52MHz |
			MMC_MODE_4BIT | MMC_MODE_HC | MMC_MODE_HS_200MHz;

	if (host->quirks & SDHCI_QUIRK_EMMC_1V8_POWER)
		host->mmc_ctrlr.caps |= MMC_MODE_1V8_VDD;

722
723
	if (caps & SDHCI_CAN_DO_8BIT)
		host->mmc_ctrlr.caps |= MMC_MODE_8BIT;
724
	if (host->host_caps)
725
		host->mmc_ctrlr.caps |= host->host_caps;
726
727
	if (caps & SDHCI_CAN_64BIT)
		host->dma64 = 1;
728
729
730
731
732
733

	sdhci_reset(host, SDHCI_RESET_ALL);

	return 0;
}

734
static int sdhci_init(SdhciHost *host)
735
{
736
737
738
739
740
	int rv = sdhci_pre_init(host);

	if (rv)
		return rv; /* The error has been already reported */

741
	sdhci_set_power(host, fls(host->mmc_ctrlr.voltages) - 1);
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756

	if (host->quirks & SDHCI_QUIRK_NO_CD) {
		unsigned int status;

		sdhci_writel(host, SDHCI_CTRL_CD_TEST_INS | SDHCI_CTRL_CD_TEST,
			SDHCI_HOST_CONTROL);

		status = sdhci_readl(host, SDHCI_PRESENT_STATE);
		while ((!(status & SDHCI_CARD_PRESENT)) ||
		    (!(status & SDHCI_CARD_STATE_STABLE)) ||
		    (!(status & SDHCI_CARD_DETECT_PIN_LEVEL)))
			status = sdhci_readl(host, SDHCI_PRESENT_STATE);
	}

	/* Enable only interrupts served by the SD controller */
757
758
	sdhci_writel(host, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK,
		     SDHCI_INT_ENABLE);
759
760
761
	/* Mask all sdhci interrupt sources */
	sdhci_writel(host, 0x0, SDHCI_SIGNAL_ENABLE);

762
763
764
	/* Set timeout to maximum, shouldn't happen if everything's right. */
	sdhci_writeb(host, 0xe, SDHCI_TIMEOUT_CONTROL);

765
	udelay(10000);
766
767
768
	return 0;
}

769
static int sdhci_update(BlockDevCtrlrOps *me)
770
{
771
772
	SdhciHost *host = container_of
		(me, SdhciHost, mmc_ctrlr.ctrlr.ops);
773

774
	if (host->removable) {
775
776
		int present = (sdhci_readl(host, SDHCI_PRESENT_STATE) &
			       SDHCI_CARD_PRESENT) != 0;
777

778
779
780
781
782
783
784
785
786
787
788
		if (!present) {
			if (host->mmc_ctrlr.media) {
				/*
				 * A card was present but isn't any more. Get
				 * rid of it.
				 */
				list_remove
					(&host->mmc_ctrlr.media->dev.list_node);
				free(host->mmc_ctrlr.media);
				host->mmc_ctrlr.media = NULL;
			}
789
			return 0;
790
791
792
793
794
795
		}

		if (!host->mmc_ctrlr.media) {
			/*
			 * A card is present and not set up yet. Get it ready.
			 */
796
797
798
			if (sdhci_init(host))
				return -1;

799
800
			if (mmc_setup_media(&host->mmc_ctrlr))
				return -1;
801
			host->mmc_ctrlr.media->dev.name = "SDHCI card";
802
803
804
			list_insert_after
				(&host-> mmc_ctrlr.media->dev.list_node,
				 &removable_block_devices);
805
806
		}
	} else {
807
808
809
810
811
		if (!host->initialized && sdhci_init(host))
			return -1;

		host->initialized = 1;

812
813
		if (mmc_setup_media(&host->mmc_ctrlr))
			return -1;
814
		host->mmc_ctrlr.media->dev.name = "SDHCI fixed";
815
816
817
		list_insert_after(&host->mmc_ctrlr.media->dev.list_node,
				  &fixed_block_devices);
		host->mmc_ctrlr.ctrlr.need_update = 0;
818
	}
819

820
	host->mmc_ctrlr.media->dev.removable = host->removable;
821
822
	host->mmc_ctrlr.media->dev.ops.read = block_mmc_read;
	host->mmc_ctrlr.media->dev.ops.write = block_mmc_write;
Jeffy Chen's avatar
Jeffy Chen committed
823
	host->mmc_ctrlr.media->dev.ops.fill_write = block_mmc_fill_write;
824
	host->mmc_ctrlr.media->dev.ops.new_stream = new_simple_stream;
825

826
827
828
	return 0;
}

829
void add_sdhci(SdhciHost *host)
830
{
831
832
	host->mmc_ctrlr.send_cmd = &sdhci_send_command;
	host->mmc_ctrlr.set_ios = &sdhci_set_ios;
833

834
	host->mmc_ctrlr.ctrlr.ops.update = &sdhci_update;
835
	host->mmc_ctrlr.ctrlr.need_update = 1;
836

837
838
	/* TODO(vbendeb): check if SDHCI spec allows to retrieve this value. */
	host->mmc_ctrlr.b_max = 65535;
839
}