treewide: replace GPLv2 long form headers with SPDX header
[coreboot.git] / src / commonlib / storage / storage.c
blobf5d1517cbf2e7e50eba8d7fd57469a2b8879cd5b
1 /* This file is part of the coreboot project. */
2 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 /*
4 * MultiMediaCard (MMC), eMMC and Secure Digital (SD) common code which
5 * transitions the card from the standby state to the transfer state. The
6 * common code supports read operations, erase and write operations are in
7 * a separate modules. This code is controller independent.
8 */
10 #include <commonlib/storage.h>
11 #include "sd_mmc.h"
12 #include "storage.h"
13 #include <string.h>
15 #define DECIMAL_CAPACITY_MULTIPLIER 1000ULL
16 #define HEX_CAPACITY_MULTIPLIER 1024ULL
18 struct capacity {
19 const char *const units;
20 uint64_t bytes;
23 static void display_capacity(struct storage_media *media, int partition_number)
25 uint64_t capacity;
26 uint64_t decimal_divisor;
27 const char *decimal_units;
28 uint64_t hex_divisor;
29 const char *hex_units;
30 int index;
31 const char *name;
32 const char *separator;
33 const struct capacity decimal_list[] = {
34 {"TB", DECIMAL_CAPACITY_MULTIPLIER * DECIMAL_CAPACITY_MULTIPLIER
35 * DECIMAL_CAPACITY_MULTIPLIER
36 * DECIMAL_CAPACITY_MULTIPLIER},
37 {"GB", DECIMAL_CAPACITY_MULTIPLIER * DECIMAL_CAPACITY_MULTIPLIER
38 * DECIMAL_CAPACITY_MULTIPLIER},
39 {"MB", DECIMAL_CAPACITY_MULTIPLIER
40 * DECIMAL_CAPACITY_MULTIPLIER},
41 {"KB", DECIMAL_CAPACITY_MULTIPLIER},
42 {"B", 1}
44 const struct capacity hex_list[] = {
45 {"TiB", HEX_CAPACITY_MULTIPLIER * HEX_CAPACITY_MULTIPLIER
46 * HEX_CAPACITY_MULTIPLIER * HEX_CAPACITY_MULTIPLIER},
47 {"GiB", HEX_CAPACITY_MULTIPLIER * HEX_CAPACITY_MULTIPLIER
48 * HEX_CAPACITY_MULTIPLIER},
49 {"MiB", HEX_CAPACITY_MULTIPLIER * HEX_CAPACITY_MULTIPLIER},
50 {"KiB", HEX_CAPACITY_MULTIPLIER},
51 {"B", 1}
54 /* Get the partition name */
55 capacity = media->capacity[partition_number];
56 name = storage_partition_name(media, partition_number);
57 separator = "";
58 if (CONFIG(COMMONLIB_STORAGE_MMC) && !IS_SD(media))
59 separator = ": ";
61 /* Determine the decimal divisor for the capacity */
62 for (index = 0; index < ARRAY_SIZE(decimal_list) - 1; index++) {
63 if (capacity >= decimal_list[index].bytes)
64 break;
66 decimal_divisor = decimal_list[index].bytes;
67 decimal_units = decimal_list[index].units;
69 /* Determine the hex divisor for the capacity */
70 for (index = 0; index < ARRAY_SIZE(hex_list) - 1; index++) {
71 if (capacity >= hex_list[index].bytes)
72 break;
74 hex_divisor = hex_list[index].bytes;
75 hex_units = hex_list[index].units;
77 /* Display the capacity */
78 sdhc_debug("%3lld.%03lld %sytes (%3lld.%03lld %sytes)%s%s\n",
79 capacity / decimal_divisor,
80 (capacity / (decimal_divisor / 1000)) % 1000,
81 decimal_units,
82 capacity / hex_divisor,
83 ((capacity / (hex_divisor / 1024)) * 1000 / 1024) % 1000,
84 hex_units,
85 separator,
86 name);
89 void storage_display_setup(struct storage_media *media)
91 int partition_number;
93 /* Display the device info */
94 sd_mmc_debug("Man %06x Snr %u ",
95 media->cid[0] >> 24,
96 (((media->cid[2] & 0xffff) << 16) |
97 ((media->cid[3] >> 16) & 0xffff)));
98 sd_mmc_debug("Product %c%c%c%c", media->cid[0] & 0xff,
99 (media->cid[1] >> 24), (media->cid[1] >> 16) & 0xff,
100 (media->cid[1] >> 8) & 0xff);
101 if (!IS_SD(media)) /* eMMC product string is longer */
102 sd_mmc_debug("%c%c", media->cid[1] & 0xff,
103 (media->cid[2] >> 24) & 0xff);
104 sd_mmc_debug(" Revision %d.%d\n", (media->cid[2] >> 20) & 0xf,
105 (media->cid[2] >> 16) & 0xf);
107 /* Display the erase block size */
108 sdhc_debug("Erase block size: 0x%08x\n", media->erase_blocks
109 * media->write_bl_len);
111 /* Display the partition capacities */
112 if (CONFIG(SDHC_DEBUG)) {
113 for (partition_number = 0; partition_number
114 < ARRAY_SIZE(media->capacity); partition_number++) {
115 if (!media->capacity[partition_number])
116 continue;
117 display_capacity(media, partition_number);
122 int storage_startup(struct storage_media *media)
124 int err;
125 uint64_t capacity;
126 uint64_t cmult, csize;
127 struct mmc_command cmd;
128 struct sd_mmc_ctrlr *ctrlr = media->ctrlr;
130 /* Determine the storage capacity */
131 if (media->high_capacity) {
132 cmult = 8;
133 csize = sd_mmc_extract_uint32_bits(media->csd, 58, 22);
134 } else {
135 csize = sd_mmc_extract_uint32_bits(media->csd, 54, 12);
136 cmult = sd_mmc_extract_uint32_bits(media->csd, 78, 3);
138 capacity = (csize + 1) << (cmult + 2);
139 capacity *= media->read_bl_len;
140 media->capacity[0] = capacity;
142 /* Limit the block size to 512 bytes */
143 if (media->read_bl_len > 512)
144 media->read_bl_len = 512;
145 if (media->write_bl_len > 512)
146 media->write_bl_len = 512;
148 /* Get the erase size in blocks */
149 media->erase_blocks =
150 (sd_mmc_extract_uint32_bits(media->csd, 47, 3) + 1)
151 * (sd_mmc_extract_uint32_bits(media->csd, 42, 5) + 1);
153 /* Select the card, and put it into Transfer Mode */
154 cmd.cmdidx = MMC_CMD_SELECT_CARD;
155 cmd.resp_type = CARD_RSP_R1;
156 cmd.cmdarg = media->rca << 16;
157 cmd.flags = 0;
158 err = ctrlr->send_cmd(ctrlr, &cmd, NULL);
159 if (err)
160 return err;
162 /* Increase the bus frequency */
163 if (CONFIG(COMMONLIB_STORAGE_SD) && IS_SD(media))
164 err = sd_change_freq(media);
165 else if (CONFIG(COMMONLIB_STORAGE_MMC)) {
166 err = mmc_change_freq(media);
167 if (!err)
168 mmc_update_capacity(media);
170 if (err)
171 return err;
173 /* Restrict card's capabilities by what the controller can do */
174 media->caps &= ctrlr->caps;
176 /* Increase the bus width if possible */
177 if (CONFIG(COMMONLIB_STORAGE_SD) && IS_SD(media))
178 err = sd_set_bus_width(media);
179 else if (CONFIG(COMMONLIB_STORAGE_MMC))
180 err = mmc_set_bus_width(media);
181 if (err)
182 return err;
184 /* Display the card setup */
185 storage_display_setup(media);
186 return 0;
189 int storage_setup_media(struct storage_media *media, struct sd_mmc_ctrlr *ctrlr)
191 int err;
193 memset(media, 0, sizeof(*media));
194 media->ctrlr = ctrlr;
196 err = sd_mmc_enter_standby(media);
197 if (err)
198 return err;
199 return storage_startup(media);
202 static int storage_read(struct storage_media *media, void *dest, uint32_t start,
203 uint32_t block_count)
205 struct mmc_command cmd;
206 struct sd_mmc_ctrlr *ctrlr = media->ctrlr;
208 cmd.resp_type = CARD_RSP_R1;
209 cmd.flags = 0;
211 if (block_count > 1)
212 cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
213 else
214 cmd.cmdidx = MMC_CMD_READ_SINGLE_BLOCK;
216 if (media->high_capacity)
217 cmd.cmdarg = start;
218 else
219 cmd.cmdarg = start * media->read_bl_len;
221 struct mmc_data data;
222 data.dest = dest;
223 data.blocks = block_count;
224 data.blocksize = media->read_bl_len;
225 data.flags = DATA_FLAG_READ;
227 if (ctrlr->send_cmd(ctrlr, &cmd, &data))
228 return 0;
230 if ((block_count > 1) && !(ctrlr->caps
231 & DRVR_CAP_AUTO_CMD12)) {
232 cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
233 cmd.cmdarg = 0;
234 cmd.resp_type = CARD_RSP_R1b;
235 cmd.flags = CMD_FLAG_IGNORE_INHIBIT;
236 if (ctrlr->send_cmd(ctrlr, &cmd, NULL)) {
237 sd_mmc_error("Failed to send stop cmd\n");
238 return 0;
241 /* Waiting for the ready status */
242 sd_mmc_send_status(media, SD_MMC_IO_RETRIES);
245 return block_count;
248 /////////////////////////////////////////////////////////////////////////////
249 // BlockDevice utilities and callbacks
251 int storage_block_setup(struct storage_media *media, uint64_t start,
252 uint64_t count, int is_read)
254 struct sd_mmc_ctrlr *ctrlr = media->ctrlr;
255 int partition_number;
257 if (count == 0)
258 return 0;
260 uint32_t bl_len = is_read ? media->read_bl_len :
261 media->write_bl_len;
263 /* Validate the block range */
264 partition_number = media->partition_config & EXT_CSD_PART_ACCESS_MASK;
265 if (((start * bl_len) > media->capacity[partition_number])
266 || (((start + count) * bl_len) >
267 media->capacity[partition_number])) {
268 sd_mmc_error("Block range exceeds device capacity\n");
269 return 0;
273 * CMD16 only applies to single data rate mode, and block
274 * length for double data rate is always 512 bytes.
276 if ((ctrlr->timing == BUS_TIMING_UHS_DDR50) ||
277 (ctrlr->timing == BUS_TIMING_MMC_DDR52) ||
278 (ctrlr->timing == BUS_TIMING_MMC_HS400) ||
279 (ctrlr->timing == BUS_TIMING_MMC_HS400ES))
280 return 1;
281 if (sd_mmc_set_blocklen(ctrlr, bl_len))
282 return 0;
284 return 1;
287 uint64_t storage_block_read(struct storage_media *media, uint64_t start,
288 uint64_t count, void *buffer)
290 uint8_t *dest = (uint8_t *)buffer;
292 if (storage_block_setup(media, start, count, 1) == 0)
293 return 0;
295 uint64_t todo = count;
296 struct sd_mmc_ctrlr *ctrlr = media->ctrlr;
297 do {
298 uint32_t cur = (uint32_t)MIN(todo, ctrlr->b_max);
299 if (storage_read(media, dest, start, cur) != cur)
300 return 0;
301 todo -= cur;
302 sd_mmc_trace("%s: Got %d blocks, more %d (total %d) to go.\n",
303 __func__, (int)cur, (int)todo, (int)count);
304 start += cur;
305 dest += cur * media->read_bl_len;
306 } while (todo > 0);
307 return count;
310 int storage_set_partition(struct storage_media *media,
311 unsigned int partition_number)
313 int err;
315 /* Select the partition */
316 err = -1;
317 if (CONFIG(COMMONLIB_STORAGE_SD) && IS_SD(media))
318 err = sd_set_partition(media, partition_number);
319 else if (CONFIG(COMMONLIB_STORAGE_MMC))
320 err = mmc_set_partition(media, partition_number);
321 if (err)
322 sd_mmc_error("Invalid partition number!\n");
323 return err;
326 const char *storage_partition_name(struct storage_media *media,
327 unsigned int partition_number)
329 const char *name;
331 /* Get the partition name */
332 name = NULL;
333 if (CONFIG(COMMONLIB_STORAGE_SD) && IS_SD(media))
334 name = sd_partition_name(media, partition_number);
335 else if (CONFIG(COMMONLIB_STORAGE_MMC))
336 name = mmc_partition_name(media, partition_number);
337 return name;
340 unsigned int storage_get_current_partition(struct storage_media *media)
342 return media->partition_config & EXT_CSD_PART_ACCESS_MASK;