summaryrefslogtreecommitdiffstats
path: root/packages/u-boot/u-boot-1.1.4/at32stk1000/fix-mmc-data-timeout.patch
blob: d78cbcaaaac304593ce50dfd71f358ceb10f4798 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
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
---
 cpu/at32ap7xxx/mmc.c |   58 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)

Index: u-boot-1.1.4-avr32/cpu/at32ap7xxx/mmc.c
===================================================================
--- u-boot-1.1.4-avr32.orig/cpu/at32ap7xxx/mmc.c	2007-01-30 14:53:33.000000000 +0100
+++ u-boot-1.1.4-avr32/cpu/at32ap7xxx/mmc.c	2007-01-30 15:45:37.000000000 +0100
@@ -67,6 +67,7 @@ struct mmci {
 	unsigned int rca;
 	block_dev_desc_t blkdev;
 	const struct device *dev;
+	int card_is_sd;
 };
 
 struct mmci mmci = {
@@ -391,6 +392,8 @@ static int sd_init_card(struct mmci *mmc
 	mmc->rca = resp[0] >> 16;
 	if (verbose)
 		printf("SD Card detected (RCA %u)\n", mmc->rca);
+	mmc->card_is_sd = 1;
+
 	return 0;
 }
 
@@ -425,6 +428,57 @@ static int mmc_init_card(struct mmci *mm
 	return ret;
 }
 
+static void mci_set_data_timeout(struct mmci *mmc, struct mmc_csd *csd)
+{
+	static const unsigned int dtomul_to_shift[] = {
+		0, 4, 7, 8, 10, 12, 16, 20,
+	};
+	static const unsigned int taac_exp[] = {
+		1, 10, 100, 1000, 10000, 100000, 1000000, 10000000,
+	};
+	static const unsigned int taac_mant[] = {
+		0,  10, 12, 13, 15, 60, 25, 30,
+		35, 40, 45, 50, 55, 60, 70, 80,
+	};
+	unsigned int timeout_ns, timeout_clks;
+	unsigned int e, m;
+	unsigned int dtocyc, dtomul;
+	u32 dtor;
+
+	e = csd->taac & 0x07;
+	m = (csd->taac >> 3) & 0x0f;
+
+	timeout_ns = (taac_exp[e] * taac_mant[m] + 9) / 10;
+	timeout_clks = csd->nsac * 100;
+
+	timeout_clks += (((timeout_ns + 9) / 10)
+			 * ((CFG_MMC_CLK_PP + 99999) / 100000) + 9999) / 10000;
+	if (!mmc->card_is_sd)
+		timeout_clks *= 10;
+	else
+		timeout_clks *= 100;
+
+	dtocyc = timeout_clks;
+	dtomul = 0;
+	while (dtocyc > 15 && dtomul < 8) {
+		dtomul++;
+		dtocyc = timeout_clks >> dtomul_to_shift[dtomul];
+	}
+
+	if (dtomul >= 8) {
+		dtomul = 7;
+		dtocyc = 15;
+		puts("Warning: Using maximum data timeout\n");
+	}
+
+	dtor = (MMCI_MKBF(MCI_DTOR_DTOMUL, dtomul)
+		| MMCI_MKBF(MCI_DTOR_DTOCYC, dtocyc));
+	mmci_writel(&mmci, MCI_DTOR, dtor);
+
+	printf("mmc: Using %u cycles data timeout (DTOR=0x%x)\n",
+	       dtocyc << dtomul_to_shift[dtomul], dtor);
+}
+
 int mmc_init(int verbose)
 {
 	struct mmc_cid cid;
@@ -443,6 +497,8 @@ int mmc_init(int verbose)
 	mmci_writel(&mmci, MCI_IDR, ~0UL);
 	mci_set_mode(CFG_MMC_CLK_OD, CFG_MMC_BLKLEN);
 
+	mmci.card_is_sd = 0;
+
 	ret = sd_init_card(&mmci, &cid, verbose);
 	if (ret) {
 		mmci.rca = MMC_DEFAULT_RCA;
@@ -458,6 +514,8 @@ int mmc_init(int verbose)
 	if (verbose)
 		mmc_dump_csd(&csd);
 
+	mci_set_data_timeout(&mmci, &csd);
+
 	/* Initialize the blockdev structure */
 	sprintf(mmci.blkdev.vendor,
 		 "Man %02x%04x Snr %08x",