mb/google/brya/var/orisa: Update Type C DisplayPort HPD Configuration
[coreboot2.git] / src / commonlib / storage / sd_mmc.c
blob17dd55d8967c79408e199efb8edb721969d14354
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3 * MultiMediaCard (MMC), eMMC and Secure Digital (SD) common initialization
4 * code which brings the card into the standby state. This code is controller
5 * independent.
6 */
8 #include <commonlib/storage.h>
9 #include <delay.h>
10 #include <endian.h>
11 #include <string.h>
13 #include "mmc.h"
14 #include "sd_mmc.h"
15 #include "storage.h"
17 uint64_t sd_mmc_extract_uint32_bits(const uint32_t *array, int start, int count)
19 int i;
20 uint64_t value = 0;
22 for (i = 0; i < count; i++, start++) {
23 value <<= 1;
24 value |= (array[start / 32] >> (31 - (start % 32))) & 0x1;
26 return value;
29 static uint32_t sd_mmc_calculate_transfer_speed(uint32_t csd0)
31 uint32_t mult, freq;
33 /* frequency bases, divided by 10 to be nice to platforms without
34 * floating point */
35 static const int fbase[] = {
36 10000,
37 100000,
38 1000000,
39 10000000,
41 /* Multiplier values for TRAN_SPEED. Multiplied by 10 to be nice
42 * to platforms without floating point. */
43 static const int multipliers[] = {
44 0, // reserved
45 10,
46 12,
47 13,
48 15,
49 20,
50 25,
51 30,
52 35,
53 40,
54 45,
55 50,
56 55,
57 60,
58 70,
59 80,
62 /* divide frequency by 10, since the mults are 10x bigger */
63 freq = fbase[csd0 & 0x7];
64 mult = multipliers[(csd0 >> 3) & 0xf];
65 return freq * mult;
68 int sd_mmc_go_idle(struct storage_media *media)
70 struct sd_mmc_ctrlr *ctrlr = media->ctrlr;
72 // Some cards can't accept idle commands without delay.
73 if (ctrlr->mdelay_before_cmd0)
74 mdelay(ctrlr->mdelay_before_cmd0);
76 struct mmc_command cmd;
77 cmd.cmdidx = MMC_CMD_GO_IDLE_STATE;
78 cmd.cmdarg = 0;
79 cmd.resp_type = CARD_RSP_NONE;
80 cmd.flags = 0;
82 int err = ctrlr->send_cmd(ctrlr, &cmd, NULL);
83 if (err)
84 return err;
86 // Some cards need more than half second to respond to next command (ex,
87 // SEND_OP_COND).
88 if (ctrlr->mdelay_after_cmd0)
89 mdelay(ctrlr->mdelay_after_cmd0);
91 return 0;
94 int sd_mmc_send_status(struct storage_media *media, ssize_t tries)
96 struct mmc_command cmd;
97 struct sd_mmc_ctrlr *ctrlr = media->ctrlr;
99 cmd.cmdidx = MMC_CMD_SEND_STATUS;
100 cmd.resp_type = CARD_RSP_R1;
101 cmd.cmdarg = media->rca << 16;
102 cmd.flags = 0;
104 while (tries--) {
105 int err = ctrlr->send_cmd(ctrlr, &cmd, NULL);
106 if (err)
107 return err;
108 else if (cmd.response[0] & MMC_STATUS_RDY_FOR_DATA)
109 break;
110 else if (cmd.response[0] & MMC_STATUS_MASK) {
111 sd_mmc_error("Status Error: %#8.8x\n", cmd.response[0]);
112 return CARD_COMM_ERR;
115 udelay(100);
118 sd_mmc_trace("CURR STATE:%d\n",
119 (cmd.response[0] & MMC_STATUS_CURR_STATE) >> 9);
121 if (tries < 0) {
122 sd_mmc_error("Timeout waiting card ready\n");
123 return CARD_TIMEOUT;
125 return 0;
128 int sd_mmc_set_blocklen(struct sd_mmc_ctrlr *ctrlr, int len)
130 struct mmc_command cmd;
131 cmd.cmdidx = MMC_CMD_SET_BLOCKLEN;
132 cmd.resp_type = CARD_RSP_R1;
133 cmd.cmdarg = len;
134 cmd.flags = 0;
136 return ctrlr->send_cmd(ctrlr, &cmd, NULL);
139 int sd_mmc_enter_standby(struct storage_media *media)
141 struct mmc_command cmd;
142 struct sd_mmc_ctrlr *ctrlr = media->ctrlr;
143 int err;
145 SET_BUS_WIDTH(ctrlr, 1);
146 SET_CLOCK(ctrlr, 1);
148 /* Reset the Card */
149 err = sd_mmc_go_idle(media);
150 if (err)
151 return err;
153 /* Test for SD version 2 */
154 err = CARD_TIMEOUT;
155 if (CONFIG(COMMONLIB_STORAGE_SD)) {
156 err = sd_send_if_cond(media);
158 /* Get SD card operating condition */
159 if (!err)
160 err = sd_send_op_cond(media);
163 /* If the command timed out, we check for an MMC card */
164 if (CONFIG(COMMONLIB_STORAGE_MMC) && (err == CARD_TIMEOUT)) {
165 /* Some cards seem to need this */
166 sd_mmc_go_idle(media);
168 err = mmc_send_op_cond(media);
169 if (err == CARD_IN_PROGRESS)
170 err = mmc_complete_op_cond(media);
173 if (err) {
174 sd_mmc_error(
175 "Card did not respond to voltage select!\n");
176 return CARD_UNUSABLE_ERR;
179 /* Put the Card in Identify Mode */
180 cmd.cmdidx = MMC_CMD_ALL_SEND_CID;
181 cmd.resp_type = CARD_RSP_R2;
182 cmd.cmdarg = 0;
183 cmd.flags = 0;
184 err = ctrlr->send_cmd(ctrlr, &cmd, NULL);
185 if (err)
186 return err;
187 memcpy(media->cid, cmd.response, sizeof(media->cid));
190 * For MMC cards, set the Relative Address.
191 * For SD cards, get the Relative Address.
192 * This also puts the cards into Standby State
194 cmd.cmdidx = SD_CMD_SEND_RELATIVE_ADDR;
195 cmd.cmdarg = media->rca << 16;
196 cmd.resp_type = CARD_RSP_R6;
197 cmd.flags = 0;
198 err = ctrlr->send_cmd(ctrlr, &cmd, NULL);
199 if (err)
200 return err;
201 if (IS_SD(media))
202 media->rca = (cmd.response[0] >> 16) & 0xffff;
204 /* Get the Card-Specific Data */
205 cmd.cmdidx = MMC_CMD_SEND_CSD;
206 cmd.resp_type = CARD_RSP_R2;
207 cmd.cmdarg = media->rca << 16;
208 cmd.flags = 0;
209 err = ctrlr->send_cmd(ctrlr, &cmd, NULL);
211 /* Waiting for the ready status */
212 sd_mmc_send_status(media, SD_MMC_IO_RETRIES);
213 if (err)
214 return err;
216 memcpy(media->csd, cmd.response, sizeof(media->csd));
217 if (media->version == MMC_VERSION_UNKNOWN) {
218 int version = sd_mmc_extract_uint32_bits(media->csd, 2, 4);
219 switch (version) {
220 case 0:
221 media->version = MMC_VERSION_1_2;
222 break;
223 case 1:
224 media->version = MMC_VERSION_1_4;
225 break;
226 case 2:
227 media->version = MMC_VERSION_2_2;
228 break;
229 case 3:
230 media->version = MMC_VERSION_3;
231 break;
232 case 4:
233 media->version = MMC_VERSION_4;
234 break;
235 default:
236 media->version = MMC_VERSION_1_2;
237 break;
240 media->tran_speed = sd_mmc_calculate_transfer_speed(media->csd[0]);
242 /* Determine the read and write block lengths */
243 media->read_bl_len = 1 << sd_mmc_extract_uint32_bits(media->csd, 44, 4);
244 if (IS_SD(media))
245 media->write_bl_len = media->read_bl_len;
246 else
247 media->write_bl_len =
248 1 << sd_mmc_extract_uint32_bits(media->csd, 102, 4);
250 sd_mmc_debug("mmc media info: version=%#x, tran_speed=%d\n",
251 media->version, (int)media->tran_speed);
253 return 0;