blob: 8eaa2ee6111e977be33788730001ac877fc9ebe5 [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) and eMMC specific support code
15 * This code is controller independent
Lee Leahyeef40eb2017-03-23 10:54:57 -070016 */
17
Lee Leahy48dbc662017-05-08 16:56:03 -070018#include <commonlib/storage.h>
Lee Leahy927f06a2017-06-19 10:53:18 -070019#include <delay.h>
Lee Leahyeef40eb2017-03-23 10:54:57 -070020#include "mmc.h"
21#include "sd_mmc.h"
22#include "storage.h"
23#include <string.h>
Lee Leahy927f06a2017-06-19 10:53:18 -070024#include <timer.h>
Lee Leahyeef40eb2017-03-23 10:54:57 -070025
26/* We pass in the cmd since otherwise the init seems to fail */
27static int mmc_send_op_cond_iter(struct storage_media *media,
28 struct mmc_command *cmd, int use_arg)
29{
30 struct sd_mmc_ctrlr *ctrlr = media->ctrlr;
31
32 cmd->cmdidx = MMC_CMD_SEND_OP_COND;
33 cmd->resp_type = CARD_RSP_R3;
34
35 /* Set the controller's operating conditions */
36 if (use_arg) {
37 uint32_t mask = media->op_cond_response &
38 (OCR_VOLTAGE_MASK | OCR_ACCESS_MODE);
39 cmd->cmdarg = ctrlr->voltages & mask;
40
41 /* Always request high capacity if supported by the
42 * controller
43 */
44 if (ctrlr->caps & DRVR_CAP_HC)
45 cmd->cmdarg |= OCR_HCS;
46 }
47 cmd->flags = 0;
48 int err = ctrlr->send_cmd(ctrlr, cmd, NULL);
49 if (err)
50 return err;
51
52 media->op_cond_response = cmd->response[0];
53 return 0;
54}
55
56int mmc_send_op_cond(struct storage_media *media)
57{
58 struct mmc_command cmd;
59 int max_iters = 2;
60
61 /* Ask the card for its operating conditions */
62 cmd.cmdarg = 0;
63 for (int i = 0; i < max_iters; i++) {
64 int err = mmc_send_op_cond_iter(media, &cmd, i != 0);
65 if (err)
66 return err;
67
68 // OCR_BUSY is active low, this bit set means
69 // "initialization complete".
70 if (media->op_cond_response & OCR_BUSY)
71 return 0;
72 }
73 return CARD_IN_PROGRESS;
74}
75
76int mmc_complete_op_cond(struct storage_media *media)
77{
78 struct mmc_command cmd;
79 struct stopwatch sw;
80
81 stopwatch_init_msecs_expire(&sw, MMC_INIT_TIMEOUT_US_MS);
82 while (1) {
83 // CMD1 queries whether initialization is done.
84 int err = mmc_send_op_cond_iter(media, &cmd, 1);
85 if (err)
86 return err;
87
88 // OCR_BUSY means "initialization complete".
89 if (media->op_cond_response & OCR_BUSY)
90 break;
91
92 // Check if init timeout has expired.
93 if (stopwatch_expired(&sw))
94 return CARD_UNUSABLE_ERR;
95
96 udelay(100);
97 }
98
99 media->version = MMC_VERSION_UNKNOWN;
100 media->ocr = cmd.response[0];
101
102 media->high_capacity = ((media->ocr & OCR_HCS) == OCR_HCS);
103 media->rca = 0;
104 return 0;
105}
106
107int mmc_send_ext_csd(struct sd_mmc_ctrlr *ctrlr, unsigned char *ext_csd)
108{
109 struct mmc_command cmd;
110 struct mmc_data data;
111 int rv;
112
113 /* Get the Card Status Register */
114 cmd.cmdidx = MMC_CMD_SEND_EXT_CSD;
115 cmd.resp_type = CARD_RSP_R1;
116 cmd.cmdarg = 0;
117 cmd.flags = 0;
118
119 data.dest = (char *)ext_csd;
120 data.blocks = 1;
121 data.blocksize = 512;
122 data.flags = DATA_FLAG_READ;
123
124 rv = ctrlr->send_cmd(ctrlr, &cmd, &data);
125
Julius Wernercd49cce2019-03-05 16:53:33 -0800126 if (!rv && CONFIG(SD_MMC_TRACE)) {
Lee Leahyeef40eb2017-03-23 10:54:57 -0700127 int i, size;
128
129 size = data.blocks * data.blocksize;
130 sd_mmc_trace("\t%p ext_csd:", ctrlr);
131 for (i = 0; i < size; i++) {
132 if (!(i % 32))
133 sd_mmc_trace("\n");
134 sd_mmc_trace(" %2.2x", ext_csd[i]);
135 }
136 sd_mmc_trace("\n");
137 }
138 return rv;
139}
140
141static int mmc_switch(struct storage_media *media, uint8_t index, uint8_t value)
142{
143 struct mmc_command cmd;
144 struct sd_mmc_ctrlr *ctrlr = media->ctrlr;
145
146 cmd.cmdidx = MMC_CMD_SWITCH;
147 cmd.resp_type = CARD_RSP_R1b;
148 cmd.cmdarg = ((MMC_SWITCH_MODE_WRITE_BYTE << 24) |
149 (index << 16) | (value << 8));
150 cmd.flags = 0;
151
152 int ret = ctrlr->send_cmd(ctrlr, &cmd, NULL);
153
154 /* Waiting for the ready status */
155 sd_mmc_send_status(media, SD_MMC_IO_RETRIES);
156 return ret;
157
158}
159
160static void mmc_recalculate_clock(struct storage_media *media)
161{
162 uint32_t clock;
163
164 clock = CLOCK_26MHZ;
165 if (media->caps & DRVR_CAP_HS) {
166 if ((media->caps & DRVR_CAP_HS200) ||
167 (media->caps & DRVR_CAP_HS400))
168 clock = CLOCK_200MHZ;
169 else if (media->caps & DRVR_CAP_HS52)
170 clock = CLOCK_52MHZ;
171 }
172 SET_CLOCK(media->ctrlr, clock);
173}
174
175static int mmc_select_hs(struct storage_media *media)
176{
177 int ret;
178
179 /* Switch the MMC device into high speed mode */
180 ret = mmc_switch(media, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS);
181 if (ret) {
182 sd_mmc_error("Timing switch to high speed failed\n");
183 return ret;
184 }
185 sdhc_debug("SDHCI switched MMC to high speed\n");
186
187 /* Increase the controller clock speed */
188 SET_TIMING(media->ctrlr, BUS_TIMING_MMC_HS);
Bora Guvendik3280b762019-12-16 16:51:38 -0800189 media->caps &= ~(DRVR_CAP_HS200 | DRVR_CAP_HS400);
Lee Leahyeef40eb2017-03-23 10:54:57 -0700190 media->caps |= DRVR_CAP_HS52 | DRVR_CAP_HS;
191 mmc_recalculate_clock(media);
192 ret = sd_mmc_send_status(media, SD_MMC_IO_RETRIES);
193 return ret;
194}
195
Elyes HAOUAS0b133972018-08-15 11:17:39 +0200196static int mmc_send_tuning_seq(struct sd_mmc_ctrlr *ctrlr, char *buffer)
Lee Leahyeef40eb2017-03-23 10:54:57 -0700197{
198 struct mmc_command cmd;
199 struct mmc_data data;
200
201 /* Request the device send the tuning sequence to the host */
202 cmd.cmdidx = MMC_CMD_AUTO_TUNING_SEQUENCE;
203 cmd.resp_type = CARD_RSP_R1;
204 cmd.cmdarg = 0;
205 cmd.flags = CMD_FLAG_IGNORE_INHIBIT;
206
207 data.dest = buffer;
208 data.blocks = 1;
209 data.blocksize = (ctrlr->bus_width == 8) ? 128 : 64;
210 data.flags = DATA_FLAG_READ;
211 return ctrlr->send_cmd(ctrlr, &cmd, &data);
212}
213
214static int mmc_bus_tuning(struct storage_media *media)
215{
216 ALLOC_CACHE_ALIGN_BUFFER(char, buffer, 128);
217 struct sd_mmc_ctrlr *ctrlr = media->ctrlr;
218 int index;
219 int successful;
220
221 /* Request the device send the tuning sequence up to 40 times */
222 ctrlr->tuning_start(ctrlr, 0);
223 for (index = 0; index < 40; index++) {
Elyes HAOUAS0b133972018-08-15 11:17:39 +0200224 mmc_send_tuning_seq(ctrlr, buffer);
Lee Leahyeef40eb2017-03-23 10:54:57 -0700225 if (ctrlr->is_tuning_complete(ctrlr, &successful)) {
226 if (successful)
227 return 0;
228 break;
229 }
230 }
231 sd_mmc_error("Bus tuning failed!\n");
232 return -1;
233}
234
235static int mmc_select_hs400(struct storage_media *media)
236{
237 uint8_t bus_width;
238 uint32_t caps;
239 struct sd_mmc_ctrlr *ctrlr = media->ctrlr;
240 int ret;
241 uint32_t timing;
242
243 /* Switch the MMC device into high speed mode */
244 ret = mmc_select_hs(media);
245 if (ret)
246 return ret;
247
248 /* Switch MMC device to 8-bit DDR with strobe */
249 bus_width = EXT_CSD_DDR_BUS_WIDTH_8;
250 caps = DRVR_CAP_HS400 | DRVR_CAP_HS52 | DRVR_CAP_HS;
251 timing = BUS_TIMING_MMC_HS400;
252 if ((ctrlr->caps & DRVR_CAP_ENHANCED_STROBE)
253 && (media->caps & DRVR_CAP_ENHANCED_STROBE)) {
254 bus_width |= EXT_CSD_BUS_WIDTH_STROBE;
255 caps |= DRVR_CAP_ENHANCED_STROBE;
256 timing = BUS_TIMING_MMC_HS400ES;
257 }
258 ret = mmc_switch(media, EXT_CSD_BUS_WIDTH, bus_width);
259 if (ret) {
260 sd_mmc_error("Switching bus width for HS400 failed\n");
261 return ret;
262 }
263 sdhc_debug("SDHCI switched MMC to 8-bit DDR\n");
264
265 /* Set controller to 8-bit mode */
266 SET_BUS_WIDTH(ctrlr, 8);
267 media->caps |= EXT_CSD_BUS_WIDTH_8;
268
269 /* Switch MMC device to HS400 */
270 ret = mmc_switch(media, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS400);
271 if (ret) {
272 sd_mmc_error("Switch to HS400 timing failed\n");
273 return ret;
274 }
275
276 /* Set controller to 200 MHz and use receive strobe */
277 SET_TIMING(ctrlr, timing);
278 media->caps |= caps;
279 mmc_recalculate_clock(media);
280 ret = sd_mmc_send_status(media, SD_MMC_IO_RETRIES);
281 return ret;
282}
283
284static int mmc_select_hs200(struct storage_media *media)
285{
286 struct sd_mmc_ctrlr *ctrlr = media->ctrlr;
287 int ret;
288
289 /* Switch the MMC device to 8-bit SDR */
290 ret = mmc_switch(media, EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_8);
291 if (ret) {
292 sd_mmc_error("Switching bus width for HS200 failed\n");
293 return ret;
294 }
295
296 /* Set controller to 8-bit mode */
297 SET_BUS_WIDTH(ctrlr, 8);
298 media->caps |= EXT_CSD_BUS_WIDTH_8;
299
300 /* Switch to HS200 */
301 ret = mmc_switch(media, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS200);
302
303 if (ret) {
304 sd_mmc_error("Switch to HS200 failed\n");
305 return ret;
306 }
307 sdhc_debug("SDHCI switched MMC to 8-bit SDR\n");
308
309 /* Set controller to 200 MHz */
310 SET_TIMING(ctrlr, BUS_TIMING_MMC_HS200);
311 media->caps |= DRVR_CAP_HS200 | DRVR_CAP_HS52 | DRVR_CAP_HS;
312 mmc_recalculate_clock(media);
313
314 /* Tune the receive sampling point for the bus */
315 if ((!ret) && (ctrlr->caps & DRVR_CAP_HS200_TUNING))
316 ret = mmc_bus_tuning(media);
317 return ret;
318}
319
320int mmc_change_freq(struct storage_media *media)
321{
322 struct sd_mmc_ctrlr *ctrlr = media->ctrlr;
323 int err;
324 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, ext_csd, 512);
325
326 media->caps = 0;
327
328 /* Only version 4 supports high-speed */
329 if (media->version < MMC_VERSION_4)
330 return 0;
331
332 err = mmc_send_ext_csd(ctrlr, ext_csd);
333 if (err)
334 return err;
335
Barnali Sarkare9628402017-12-27 13:51:18 +0530336 /* Determine if the device supports enhanced strobe */
337 media->caps |= ext_csd[EXT_CSD_STROBE_SUPPORT]
338 ? DRVR_CAP_ENHANCED_STROBE : 0;
339
Lee Leahyeef40eb2017-03-23 10:54:57 -0700340 if ((ctrlr->caps & DRVR_CAP_HS400) &&
341 (ext_csd[EXT_CSD_CARD_TYPE] & MMC_HS400))
342 err = mmc_select_hs400(media);
343 else if ((ctrlr->caps & DRVR_CAP_HS200) &&
344 (ext_csd[EXT_CSD_CARD_TYPE] & MMC_HS_200MHZ))
345 err = mmc_select_hs200(media);
346 else
347 err = mmc_select_hs(media);
348
349 return err;
350}
351
352int mmc_set_bus_width(struct storage_media *media)
353{
354 struct sd_mmc_ctrlr *ctrlr = media->ctrlr;
355 int err;
356 int width;
357
358 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, ext_csd, EXT_CSD_SIZE);
359 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, test_csd, EXT_CSD_SIZE);
360
361 /* Set the bus width */
362 err = 0;
363 for (width = EXT_CSD_BUS_WIDTH_8; width >= 0; width--) {
364 /* If HS200 is switched, Bus Width has been 8-bit */
365 if ((media->caps & DRVR_CAP_HS200) ||
366 (media->caps & DRVR_CAP_HS400))
367 break;
368
369 /* Set the card to use 4 bit*/
370 err = mmc_switch(media, EXT_CSD_BUS_WIDTH, width);
371 if (err)
372 continue;
373
374 if (!width) {
375 SET_BUS_WIDTH(ctrlr, 1);
376 break;
377 }
378 SET_BUS_WIDTH(ctrlr, 4 * width);
379
380 err = mmc_send_ext_csd(ctrlr, test_csd);
381 if (!err &&
382 (ext_csd[EXT_CSD_PARTITIONING_SUPPORT] ==
383 test_csd[EXT_CSD_PARTITIONING_SUPPORT]) &&
384 (ext_csd[EXT_CSD_ERASE_GROUP_DEF] ==
385 test_csd[EXT_CSD_ERASE_GROUP_DEF]) &&
386 (ext_csd[EXT_CSD_REV] ==
387 test_csd[EXT_CSD_REV]) &&
388 (ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] ==
389 test_csd[EXT_CSD_HC_ERASE_GRP_SIZE]) &&
390 memcmp(&ext_csd[EXT_CSD_SEC_CNT],
391 &test_csd[EXT_CSD_SEC_CNT], 4) == 0) {
392 media->caps |= width;
393 break;
394 }
395 }
396 return err;
397}
398
399int mmc_update_capacity(struct storage_media *media)
400{
401 uint64_t capacity;
402 struct sd_mmc_ctrlr *ctrlr = media->ctrlr;
403 int err;
404 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, ext_csd, EXT_CSD_SIZE);
405 uint32_t erase_size;
406 uint32_t hc_erase_size;
407 uint64_t hc_wp_size;
408 int index;
409
410 if (media->version < MMC_VERSION_4)
411 return 0;
412
413 /* check ext_csd version and capacity */
414 err = mmc_send_ext_csd(ctrlr, ext_csd);
415 if (err)
416 return err;
417
418 if (ext_csd[EXT_CSD_REV] < 2)
419 return 0;
420
Lee Leahyeef40eb2017-03-23 10:54:57 -0700421 /* Determine the eMMC device information */
422 media->partition_config = ext_csd[EXT_CSD_PART_CONF]
423 & EXT_CSD_PART_ACCESS_MASK;
424
425 /* Determine the user partition size
426 *
427 * According to the JEDEC Standard, the value of
428 * ext_csd's capacity is valid if the value is
429 * more than 2GB
430 */
Lee Leahyf968a4c2017-06-27 09:28:35 -0700431 capacity = (uint32_t)(ext_csd[EXT_CSD_SEC_CNT + 0] << 0 |
Lee Leahyeef40eb2017-03-23 10:54:57 -0700432 ext_csd[EXT_CSD_SEC_CNT + 1] << 8 |
433 ext_csd[EXT_CSD_SEC_CNT + 2] << 16 |
434 ext_csd[EXT_CSD_SEC_CNT + 3] << 24);
435 capacity *= 512;
436 if ((capacity >> 20) > 2 * 1024)
437 media->capacity[MMC_PARTITION_USER] = capacity;
438
Elyes HAOUASb8473d02020-01-08 15:39:34 +0100439 /* Determine the boot partition sizes */
Lee Leahyeef40eb2017-03-23 10:54:57 -0700440 hc_erase_size = ext_csd[224] * 512 * KiB;
441 capacity = ext_csd[EXT_CSD_BOOT_SIZE_MULT] * 128 * KiB;
442 media->capacity[MMC_PARTITION_BOOT_1] = capacity;
443 media->capacity[MMC_PARTITION_BOOT_2] = capacity;
444
445 /* Determine the RPMB size */
446 hc_wp_size = ext_csd[EXT_CSD_HC_WP_GRP_SIZE] * hc_erase_size;
447 capacity = 128 * KiB * ext_csd[EXT_CSD_RPMB_SIZE_MULT];
448 media->capacity[MMC_PARTITION_RPMB] = capacity;
449
450 /* Determine the general partition sizes */
451 capacity = (ext_csd[EXT_CSD_GP_SIZE_MULT_GP0 + 2] << 16)
452 | (ext_csd[EXT_CSD_GP_SIZE_MULT_GP0 + 1] << 8)
453 | ext_csd[EXT_CSD_GP_SIZE_MULT_GP0];
454 capacity *= hc_wp_size;
455 media->capacity[MMC_PARTITION_GP1] = capacity;
456
457 capacity = (ext_csd[EXT_CSD_GP_SIZE_MULT_GP1 + 2] << 16)
458 | (ext_csd[EXT_CSD_GP_SIZE_MULT_GP1 + 1] << 8)
459 | ext_csd[EXT_CSD_GP_SIZE_MULT_GP1];
460 capacity *= hc_wp_size;
461 media->capacity[MMC_PARTITION_GP2] = capacity;
462
463 capacity = (ext_csd[EXT_CSD_GP_SIZE_MULT_GP2 + 2] << 16)
464 | (ext_csd[EXT_CSD_GP_SIZE_MULT_GP2 + 1] << 8)
465 | ext_csd[EXT_CSD_GP_SIZE_MULT_GP2];
466 capacity *= hc_wp_size;
467 media->capacity[MMC_PARTITION_GP3] = capacity;
468
469 capacity = (ext_csd[EXT_CSD_GP_SIZE_MULT_GP3 + 2] << 16)
470 | (ext_csd[EXT_CSD_GP_SIZE_MULT_GP3 + 1] << 8)
471 | ext_csd[EXT_CSD_GP_SIZE_MULT_GP3];
472 capacity *= hc_wp_size;
473 media->capacity[MMC_PARTITION_GP4] = capacity;
474
475 /* Determine the erase size */
476 erase_size = (sd_mmc_extract_uint32_bits(media->csd,
477 81, 5) + 1) *
478 (sd_mmc_extract_uint32_bits(media->csd, 86, 5)
479 + 1);
480 for (index = MMC_PARTITION_BOOT_1; index <= MMC_PARTITION_GP4;
481 index++) {
482 if (media->capacity[index] != 0) {
483 /* Enable the partitions */
484 err = mmc_switch(media, EXT_CSD_ERASE_GROUP_DEF,
485 EXT_CSD_PARTITION_ENABLE);
486 if (err) {
487 sdhc_error("Failed to enable partition access\n");
488 return err;
489 }
490
491 /* Use HC erase group size */
492 erase_size = hc_erase_size / media->write_bl_len;
493 break;
494 }
495 }
496 media->erase_blocks = erase_size;
497 media->trim_mult = ext_csd[EXT_CSD_TRIM_MULT];
498
499 return 0;
500}
501
502int mmc_set_partition(struct storage_media *media,
503 unsigned int partition_number)
504{
505 uint8_t partition_config;
506
507 /* Validate the partition number */
508 if ((partition_number > MMC_PARTITION_GP4)
509 || (!media->capacity[partition_number]))
510 return -1;
511
512 /* Update the partition register */
513 partition_config = media->partition_config;
514 partition_config &= ~EXT_CSD_PART_ACCESS_MASK;
515 partition_config |= partition_number;
516
517 /* Select the new partition */
518 int ret = mmc_switch(media, EXT_CSD_PART_CONF, partition_config);
519 if (!ret)
520 media->partition_config = partition_config;
521
522 return ret;
523}
524
525const char *mmc_partition_name(struct storage_media *media,
526 unsigned int partition_number)
527{
Elyes HAOUAS6c9737b2018-07-08 12:30:02 +0200528 static const char *const partition_name[8] = {
Lee Leahyeef40eb2017-03-23 10:54:57 -0700529 "User", /* 0 */
530 "Boot 1", /* 1 */
531 "Boot 2", /* 2 */
532 "RPMB", /* 3 */
533 "GP 1", /* 4 */
534 "GP 2", /* 5 */
535 "GP 3", /* 6 */
536 "GP 4" /* 7 */
537 };
538
539 if (partition_number >= ARRAY_SIZE(partition_name))
540 return "";
541 return partition_name[partition_number];
542}