xref: /aosp_15_r20/external/coreboot/src/commonlib/storage/sdhci_adma.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * Secure Digital (SD) Host Controller interface DMA support code
4  */
5 
6 #include <commonlib/sdhci.h>
7 #include <commonlib/storage.h>
8 #include <console/console.h>
9 #include <delay.h>
10 #include <endian.h>
11 #include <stdlib.h>
12 #include <string.h>
13 
14 #include "sdhci.h"
15 #include "sd_mmc.h"
16 #include "storage.h"
17 
sdhci_alloc_adma_descs(struct sdhci_ctrlr * sdhci_ctrlr,u32 need_descriptors)18 static void sdhci_alloc_adma_descs(struct sdhci_ctrlr *sdhci_ctrlr,
19 	u32 need_descriptors)
20 {
21 	if (sdhci_ctrlr->adma_descs) {
22 		if (sdhci_ctrlr->adma_desc_count < need_descriptors) {
23 			/* Previously allocated array is too small */
24 			free(sdhci_ctrlr->adma_descs);
25 			sdhci_ctrlr->adma_desc_count = 0;
26 			sdhci_ctrlr->adma_descs = NULL;
27 		}
28 	}
29 
30 	/* use dma_malloc() to make sure we get the coherent/uncached memory */
31 	if (!sdhci_ctrlr->adma_descs) {
32 		sdhci_ctrlr->adma_descs = malloc(need_descriptors
33 			* sizeof(*sdhci_ctrlr->adma_descs));
34 		if (sdhci_ctrlr->adma_descs == NULL)
35 			die("fail to malloc adma_descs\n");
36 		sdhci_ctrlr->adma_desc_count = need_descriptors;
37 	}
38 
39 	memset(sdhci_ctrlr->adma_descs, 0, sizeof(*sdhci_ctrlr->adma_descs)
40 		* need_descriptors);
41 }
42 
sdhci_alloc_adma64_descs(struct sdhci_ctrlr * sdhci_ctrlr,u32 need_descriptors)43 static void sdhci_alloc_adma64_descs(struct sdhci_ctrlr *sdhci_ctrlr,
44 	u32 need_descriptors)
45 {
46 	if (sdhci_ctrlr->adma64_descs) {
47 		if (sdhci_ctrlr->adma_desc_count < need_descriptors) {
48 			/* Previously allocated array is too small */
49 			free(sdhci_ctrlr->adma64_descs);
50 			sdhci_ctrlr->adma_desc_count = 0;
51 			sdhci_ctrlr->adma64_descs = NULL;
52 		}
53 	}
54 
55 	/* use dma_malloc() to make sure we get the coherent/uncached memory */
56 	if (!sdhci_ctrlr->adma64_descs) {
57 		sdhci_ctrlr->adma64_descs = malloc(need_descriptors
58 			* sizeof(*sdhci_ctrlr->adma64_descs));
59 		if (sdhci_ctrlr->adma64_descs == NULL)
60 			die("fail to malloc adma64_descs\n");
61 
62 		sdhci_ctrlr->adma_desc_count = need_descriptors;
63 	}
64 
65 	memset(sdhci_ctrlr->adma64_descs, 0, sizeof(*sdhci_ctrlr->adma64_descs)
66 		* need_descriptors);
67 }
68 
sdhci_setup_adma(struct sdhci_ctrlr * sdhci_ctrlr,struct mmc_data * data)69 int sdhci_setup_adma(struct sdhci_ctrlr *sdhci_ctrlr, struct mmc_data *data)
70 {
71 	int i, togo, need_descriptors;
72 	int dma64;
73 	char *buffer_data;
74 	u16 attributes;
75 
76 	togo = data->blocks * data->blocksize;
77 	if (!togo) {
78 		sdhc_error("%s: MmcData corrupted: %d blocks of %d bytes\n",
79 		       __func__, data->blocks, data->blocksize);
80 		return -1;
81 	}
82 
83 	need_descriptors = 1 +  togo / SDHCI_MAX_PER_DESCRIPTOR;
84 	dma64 = sdhci_ctrlr->sd_mmc_ctrlr.caps & DRVR_CAP_DMA_64BIT;
85 	if (dma64)
86 		sdhci_alloc_adma64_descs(sdhci_ctrlr, need_descriptors);
87 	else
88 		sdhci_alloc_adma_descs(sdhci_ctrlr, need_descriptors);
89 	buffer_data = data->dest;
90 
91 	/* Now set up the descriptor chain. */
92 	for (i = 0; togo; i++) {
93 		unsigned int desc_length;
94 
95 		if (togo < SDHCI_MAX_PER_DESCRIPTOR)
96 			desc_length = togo;
97 		else
98 			desc_length = SDHCI_MAX_PER_DESCRIPTOR;
99 		togo -= desc_length;
100 
101 		attributes = SDHCI_ADMA_VALID | SDHCI_ACT_TRAN;
102 		if (togo == 0)
103 			attributes |= SDHCI_ADMA_END;
104 
105 		if (dma64) {
106 			sdhci_ctrlr->adma64_descs[i].addr =
107 				(uintptr_t)buffer_data;
108 			sdhci_ctrlr->adma64_descs[i].addr_hi = 0;
109 			sdhci_ctrlr->adma64_descs[i].length = desc_length;
110 			sdhci_ctrlr->adma64_descs[i].attributes = attributes;
111 
112 		} else {
113 			sdhci_ctrlr->adma_descs[i].addr =
114 				(uintptr_t)buffer_data;
115 			sdhci_ctrlr->adma_descs[i].length = desc_length;
116 			sdhci_ctrlr->adma_descs[i].attributes = attributes;
117 		}
118 
119 		buffer_data += desc_length;
120 	}
121 
122 	if (dma64)
123 		sdhci_writel(sdhci_ctrlr, (uintptr_t)sdhci_ctrlr->adma64_descs,
124 			     SDHCI_ADMA_ADDRESS);
125 	else
126 		sdhci_writel(sdhci_ctrlr, (uintptr_t)sdhci_ctrlr->adma_descs,
127 			     SDHCI_ADMA_ADDRESS);
128 
129 	return 0;
130 }
131 
sdhci_complete_adma(struct sdhci_ctrlr * sdhci_ctrlr,struct mmc_command * cmd)132 int sdhci_complete_adma(struct sdhci_ctrlr *sdhci_ctrlr,
133 	struct mmc_command *cmd)
134 {
135 	int retry;
136 	u32 stat = 0, mask;
137 
138 	mask = SDHCI_INT_RESPONSE | SDHCI_INT_ERROR;
139 
140 	retry = 10000; /* Command should be done in way less than 10 ms. */
141 	while (--retry) {
142 		stat = sdhci_readl(sdhci_ctrlr, SDHCI_INT_STATUS);
143 		if (stat & mask)
144 			break;
145 		udelay(1);
146 	}
147 
148 	sdhci_writel(sdhci_ctrlr, SDHCI_INT_RESPONSE, SDHCI_INT_STATUS);
149 
150 	if (retry && !(stat & SDHCI_INT_ERROR)) {
151 		/* Command OK, let's wait for data transfer completion. */
152 		mask = SDHCI_INT_DATA_END |
153 			SDHCI_INT_ERROR | SDHCI_INT_ADMA_ERROR;
154 
155 		/* Transfer should take 10 seconds tops. */
156 		retry = 10 * 1000 * 1000;
157 		while (--retry) {
158 			stat = sdhci_readl(sdhci_ctrlr, SDHCI_INT_STATUS);
159 			if (stat & mask)
160 				break;
161 			udelay(1);
162 		}
163 
164 		sdhci_writel(sdhci_ctrlr, stat, SDHCI_INT_STATUS);
165 		if (retry && !(stat & SDHCI_INT_ERROR)) {
166 			sdhci_cmd_done(sdhci_ctrlr, cmd);
167 			return 0;
168 		}
169 	}
170 
171 	sdhc_error("%s: transfer error, stat %#x, adma error %#x, retry %d\n",
172 	       __func__, stat, sdhci_readl(sdhci_ctrlr, SDHCI_ADMA_ERROR),
173 		retry);
174 
175 	sdhci_reset(sdhci_ctrlr, SDHCI_RESET_CMD);
176 	sdhci_reset(sdhci_ctrlr, SDHCI_RESET_DATA);
177 
178 	if (stat & SDHCI_INT_TIMEOUT)
179 		return CARD_TIMEOUT;
180 	return CARD_COMM_ERR;
181 }
182