blob: df040cae215358b81dac311b326c5414fdf5262d [file] [log] [blame]
Lee Leahyeef40eb2017-03-23 10:54:57 -07001/*
Martin Roth0443ac22019-08-30 21:29:41 -06002 * This file is part of the coreboot project.
Lee Leahyeef40eb2017-03-23 10:54:57 -07003 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of
7 * the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
Martin Roth0443ac22019-08-30 21:29:41 -060013 *
14 * MultiMediaCard (MMC), eMMC and Secure Digital (SD) common code which
15 * transitions the card from the standby state to the transfer state. The
16 * common code supports read operations, erase and write operations are in
17 * a separate modules. This code is controller independent.
Lee Leahyeef40eb2017-03-23 10:54:57 -070018 */
19
Lee Leahy48dbc662017-05-08 16:56:03 -070020#include <commonlib/storage.h>
Lee Leahyeef40eb2017-03-23 10:54:57 -070021#include "sd_mmc.h"
22#include "storage.h"
23#include <string.h>
24
25#define DECIMAL_CAPACITY_MULTIPLIER 1000ULL
26#define HEX_CAPACITY_MULTIPLIER 1024ULL
27
Lee Leahybf5d5092017-05-09 16:37:58 -070028struct capacity {
Elyes HAOUAS6c9737b2018-07-08 12:30:02 +020029 const char *const units;
Lee Leahybf5d5092017-05-09 16:37:58 -070030 uint64_t bytes;
Lee Leahyeef40eb2017-03-23 10:54:57 -070031};
32
33static void display_capacity(struct storage_media *media, int partition_number)
34{
35 uint64_t capacity;
36 uint64_t decimal_divisor;
37 const char *decimal_units;
38 uint64_t hex_divisor;
39 const char *hex_units;
40 int index;
41 const char *name;
42 const char *separator;
Lee Leahybf5d5092017-05-09 16:37:58 -070043 const struct capacity decimal_list[] = {
44 {"TB", DECIMAL_CAPACITY_MULTIPLIER * DECIMAL_CAPACITY_MULTIPLIER
45 * DECIMAL_CAPACITY_MULTIPLIER
46 * DECIMAL_CAPACITY_MULTIPLIER},
47 {"GB", DECIMAL_CAPACITY_MULTIPLIER * DECIMAL_CAPACITY_MULTIPLIER
48 * DECIMAL_CAPACITY_MULTIPLIER},
49 {"MB", DECIMAL_CAPACITY_MULTIPLIER
50 * DECIMAL_CAPACITY_MULTIPLIER},
51 {"KB", DECIMAL_CAPACITY_MULTIPLIER},
52 {"B", 1}
53 };
54 const struct capacity hex_list[] = {
55 {"TiB", HEX_CAPACITY_MULTIPLIER * HEX_CAPACITY_MULTIPLIER
56 * HEX_CAPACITY_MULTIPLIER * HEX_CAPACITY_MULTIPLIER},
57 {"GiB", HEX_CAPACITY_MULTIPLIER * HEX_CAPACITY_MULTIPLIER
58 * HEX_CAPACITY_MULTIPLIER},
59 {"MiB", HEX_CAPACITY_MULTIPLIER * HEX_CAPACITY_MULTIPLIER},
60 {"KiB", HEX_CAPACITY_MULTIPLIER},
61 {"B", 1}
62 };
Lee Leahyeef40eb2017-03-23 10:54:57 -070063
64 /* Get the partition name */
65 capacity = media->capacity[partition_number];
66 name = storage_partition_name(media, partition_number);
67 separator = "";
Julius Wernercd49cce2019-03-05 16:53:33 -080068 if (CONFIG(COMMONLIB_STORAGE_MMC) && !IS_SD(media))
Lee Leahyeef40eb2017-03-23 10:54:57 -070069 separator = ": ";
70
71 /* Determine the decimal divisor for the capacity */
Lee Leahybf5d5092017-05-09 16:37:58 -070072 for (index = 0; index < ARRAY_SIZE(decimal_list) - 1; index++) {
73 if (capacity >= decimal_list[index].bytes)
Lee Leahyeef40eb2017-03-23 10:54:57 -070074 break;
75 }
Lee Leahybf5d5092017-05-09 16:37:58 -070076 decimal_divisor = decimal_list[index].bytes;
77 decimal_units = decimal_list[index].units;
Lee Leahyeef40eb2017-03-23 10:54:57 -070078
79 /* Determine the hex divisor for the capacity */
Lee Leahybf5d5092017-05-09 16:37:58 -070080 for (index = 0; index < ARRAY_SIZE(hex_list) - 1; index++) {
81 if (capacity >= hex_list[index].bytes)
Lee Leahyeef40eb2017-03-23 10:54:57 -070082 break;
83 }
Lee Leahybf5d5092017-05-09 16:37:58 -070084 hex_divisor = hex_list[index].bytes;
85 hex_units = hex_list[index].units;
Lee Leahyeef40eb2017-03-23 10:54:57 -070086
87 /* Display the capacity */
88 sdhc_debug("%3lld.%03lld %sytes (%3lld.%03lld %sytes)%s%s\n",
89 capacity / decimal_divisor,
90 (capacity / (decimal_divisor / 1000)) % 1000,
91 decimal_units,
92 capacity / hex_divisor,
93 ((capacity / (hex_divisor / 1024)) * 1000 / 1024) % 1000,
94 hex_units,
95 separator,
96 name);
97}
98
99void storage_display_setup(struct storage_media *media)
100{
101 int partition_number;
102
103 /* Display the device info */
104 sd_mmc_debug("Man %06x Snr %u ",
105 media->cid[0] >> 24,
106 (((media->cid[2] & 0xffff) << 16) |
107 ((media->cid[3] >> 16) & 0xffff)));
108 sd_mmc_debug("Product %c%c%c%c", media->cid[0] & 0xff,
109 (media->cid[1] >> 24), (media->cid[1] >> 16) & 0xff,
110 (media->cid[1] >> 8) & 0xff);
111 if (!IS_SD(media)) /* eMMC product string is longer */
112 sd_mmc_debug("%c%c", media->cid[1] & 0xff,
113 (media->cid[2] >> 24) & 0xff);
114 sd_mmc_debug(" Revision %d.%d\n", (media->cid[2] >> 20) & 0xf,
115 (media->cid[2] >> 16) & 0xf);
116
117 /* Display the erase block size */
118 sdhc_debug("Erase block size: 0x%08x\n", media->erase_blocks
119 * media->write_bl_len);
120
121 /* Display the partition capacities */
Julius Wernercd49cce2019-03-05 16:53:33 -0800122 if (CONFIG(SDHC_DEBUG)) {
Lee Leahyeef40eb2017-03-23 10:54:57 -0700123 for (partition_number = 0; partition_number
124 < ARRAY_SIZE(media->capacity); partition_number++) {
125 if (!media->capacity[partition_number])
126 continue;
127 display_capacity(media, partition_number);
128 }
129 }
130}
131
132int storage_startup(struct storage_media *media)
133{
134 int err;
135 uint64_t capacity;
136 uint64_t cmult, csize;
137 struct mmc_command cmd;
138 struct sd_mmc_ctrlr *ctrlr = media->ctrlr;
139
140 /* Determine the storage capacity */
141 if (media->high_capacity) {
142 cmult = 8;
143 csize = sd_mmc_extract_uint32_bits(media->csd, 58, 22);
144 } else {
145 csize = sd_mmc_extract_uint32_bits(media->csd, 54, 12);
146 cmult = sd_mmc_extract_uint32_bits(media->csd, 78, 3);
147 }
148 capacity = (csize + 1) << (cmult + 2);
149 capacity *= media->read_bl_len;
150 media->capacity[0] = capacity;
151
152 /* Limit the block size to 512 bytes */
153 if (media->read_bl_len > 512)
154 media->read_bl_len = 512;
155 if (media->write_bl_len > 512)
156 media->write_bl_len = 512;
157
158 /* Get the erase size in blocks */
159 media->erase_blocks =
160 (sd_mmc_extract_uint32_bits(media->csd, 47, 3) + 1)
161 * (sd_mmc_extract_uint32_bits(media->csd, 42, 5) + 1);
162
163 /* Select the card, and put it into Transfer Mode */
164 cmd.cmdidx = MMC_CMD_SELECT_CARD;
165 cmd.resp_type = CARD_RSP_R1;
166 cmd.cmdarg = media->rca << 16;
167 cmd.flags = 0;
168 err = ctrlr->send_cmd(ctrlr, &cmd, NULL);
169 if (err)
170 return err;
171
172 /* Increase the bus frequency */
Julius Wernercd49cce2019-03-05 16:53:33 -0800173 if (CONFIG(COMMONLIB_STORAGE_SD) && IS_SD(media))
Lee Leahyeef40eb2017-03-23 10:54:57 -0700174 err = sd_change_freq(media);
Julius Wernercd49cce2019-03-05 16:53:33 -0800175 else if (CONFIG(COMMONLIB_STORAGE_MMC)) {
Lee Leahyeef40eb2017-03-23 10:54:57 -0700176 err = mmc_change_freq(media);
177 if (!err)
178 mmc_update_capacity(media);
179 }
180 if (err)
181 return err;
182
183 /* Restrict card's capabilities by what the controller can do */
184 media->caps &= ctrlr->caps;
185
186 /* Increase the bus width if possible */
Julius Wernercd49cce2019-03-05 16:53:33 -0800187 if (CONFIG(COMMONLIB_STORAGE_SD) && IS_SD(media))
Lee Leahyeef40eb2017-03-23 10:54:57 -0700188 err = sd_set_bus_width(media);
Julius Wernercd49cce2019-03-05 16:53:33 -0800189 else if (CONFIG(COMMONLIB_STORAGE_MMC))
Lee Leahyeef40eb2017-03-23 10:54:57 -0700190 err = mmc_set_bus_width(media);
191 if (err)
192 return err;
193
194 /* Display the card setup */
195 storage_display_setup(media);
196 return 0;
197}
198
199int storage_setup_media(struct storage_media *media, struct sd_mmc_ctrlr *ctrlr)
200{
201 int err;
202
203 memset(media, 0, sizeof(*media));
204 media->ctrlr = ctrlr;
205
206 err = sd_mmc_enter_standby(media);
207 if (err)
208 return err;
209 return storage_startup(media);
210}
211
212static int storage_read(struct storage_media *media, void *dest, uint32_t start,
213 uint32_t block_count)
214{
215 struct mmc_command cmd;
216 struct sd_mmc_ctrlr *ctrlr = media->ctrlr;
217
218 cmd.resp_type = CARD_RSP_R1;
219 cmd.flags = 0;
220
221 if (block_count > 1)
222 cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
223 else
224 cmd.cmdidx = MMC_CMD_READ_SINGLE_BLOCK;
225
226 if (media->high_capacity)
227 cmd.cmdarg = start;
228 else
229 cmd.cmdarg = start * media->read_bl_len;
230
231 struct mmc_data data;
232 data.dest = dest;
233 data.blocks = block_count;
234 data.blocksize = media->read_bl_len;
235 data.flags = DATA_FLAG_READ;
236
237 if (ctrlr->send_cmd(ctrlr, &cmd, &data))
238 return 0;
239
240 if ((block_count > 1) && !(ctrlr->caps
241 & DRVR_CAP_AUTO_CMD12)) {
242 cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
243 cmd.cmdarg = 0;
244 cmd.resp_type = CARD_RSP_R1b;
245 cmd.flags = CMD_FLAG_IGNORE_INHIBIT;
246 if (ctrlr->send_cmd(ctrlr, &cmd, NULL)) {
247 sd_mmc_error("Failed to send stop cmd\n");
248 return 0;
249 }
250
251 /* Waiting for the ready status */
252 sd_mmc_send_status(media, SD_MMC_IO_RETRIES);
253 }
254
255 return block_count;
256}
257
258/////////////////////////////////////////////////////////////////////////////
259// BlockDevice utilities and callbacks
260
261int storage_block_setup(struct storage_media *media, uint64_t start,
262 uint64_t count, int is_read)
263{
264 struct sd_mmc_ctrlr *ctrlr = media->ctrlr;
265 int partition_number;
266
267 if (count == 0)
268 return 0;
269
270 uint32_t bl_len = is_read ? media->read_bl_len :
271 media->write_bl_len;
272
273 /* Validate the block range */
274 partition_number = media->partition_config & EXT_CSD_PART_ACCESS_MASK;
275 if (((start * bl_len) > media->capacity[partition_number])
276 || (((start + count) * bl_len) >
277 media->capacity[partition_number])) {
278 sd_mmc_error("Block range exceeds device capacity\n");
279 return 0;
280 }
281
282 /*
283 * CMD16 only applies to single data rate mode, and block
284 * length for double data rate is always 512 bytes.
285 */
286 if ((ctrlr->timing == BUS_TIMING_UHS_DDR50) ||
287 (ctrlr->timing == BUS_TIMING_MMC_DDR52) ||
288 (ctrlr->timing == BUS_TIMING_MMC_HS400) ||
289 (ctrlr->timing == BUS_TIMING_MMC_HS400ES))
290 return 1;
291 if (sd_mmc_set_blocklen(ctrlr, bl_len))
292 return 0;
293
294 return 1;
295}
296
297uint64_t storage_block_read(struct storage_media *media, uint64_t start,
298 uint64_t count, void *buffer)
299{
300 uint8_t *dest = (uint8_t *)buffer;
301
302 if (storage_block_setup(media, start, count, 1) == 0)
303 return 0;
304
305 uint64_t todo = count;
306 struct sd_mmc_ctrlr *ctrlr = media->ctrlr;
307 do {
308 uint32_t cur = (uint32_t)MIN(todo, ctrlr->b_max);
309 if (storage_read(media, dest, start, cur) != cur)
310 return 0;
311 todo -= cur;
312 sd_mmc_trace("%s: Got %d blocks, more %d (total %d) to go.\n",
313 __func__, (int)cur, (int)todo, (int)count);
314 start += cur;
315 dest += cur * media->read_bl_len;
316 } while (todo > 0);
317 return count;
318}
319
320int storage_set_partition(struct storage_media *media,
321 unsigned int partition_number)
322{
323 int err;
324
325 /* Select the partition */
326 err = -1;
Julius Wernercd49cce2019-03-05 16:53:33 -0800327 if (CONFIG(COMMONLIB_STORAGE_SD) && IS_SD(media))
Lee Leahyeef40eb2017-03-23 10:54:57 -0700328 err = sd_set_partition(media, partition_number);
Julius Wernercd49cce2019-03-05 16:53:33 -0800329 else if (CONFIG(COMMONLIB_STORAGE_MMC))
Lee Leahyeef40eb2017-03-23 10:54:57 -0700330 err = mmc_set_partition(media, partition_number);
331 if (err)
332 sd_mmc_error("Invalid partition number!\n");
333 return err;
334}
335
336const char *storage_partition_name(struct storage_media *media,
337 unsigned int partition_number)
338{
339 const char *name;
340
341 /* Get the partition name */
342 name = NULL;
Julius Wernercd49cce2019-03-05 16:53:33 -0800343 if (CONFIG(COMMONLIB_STORAGE_SD) && IS_SD(media))
Lee Leahyeef40eb2017-03-23 10:54:57 -0700344 name = sd_partition_name(media, partition_number);
Julius Wernercd49cce2019-03-05 16:53:33 -0800345 else if (CONFIG(COMMONLIB_STORAGE_MMC))
Lee Leahyeef40eb2017-03-23 10:54:57 -0700346 name = mmc_partition_name(media, partition_number);
347 return name;
348}
349
350unsigned int storage_get_current_partition(struct storage_media *media)
351{
352 return media->partition_config & EXT_CSD_PART_ACCESS_MASK;
353}