blob: fcd499f16b572abd9a880abdc2e4f0f77fd4d3c0 [file] [log] [blame]
Sheetal Tigadolib0156702020-01-05 14:59:04 +05301/*
2 * Copyright (c) 2016 - 2020, Broadcom
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <string.h>
8
9#include <emmc_api.h>
10#include <cmn_plat_util.h>
11
12#define MAX_CMD_RETRY 10
13
14#if EMMC_USE_DMA
15#define USE_DMA 1
16#else
17#define USE_DMA 0
18#endif
19
20struct emmc_global_buffer emmc_global_buf;
21struct emmc_global_buffer *emmc_global_buf_ptr = &emmc_global_buf;
22
23struct emmc_global_vars emmc_global_vars;
24struct emmc_global_vars *emmc_global_vars_ptr = &emmc_global_vars;
25
26static struct sd_handle *sdio_gethandle(void);
27static uint32_t sdio_idle(struct sd_handle *p_sdhandle);
28
29static uint32_t sdio_read(struct sd_handle *p_sdhandle,
30 uintptr_t mem_addr,
31 uintptr_t storage_addr,
32 size_t storage_size,
33 size_t bytes_to_read);
34
35#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
36static uint32_t sdio_write(struct sd_handle *p_sdhandle,
37 uintptr_t mem_addr,
38 uintptr_t data_addr,
39 size_t bytes_to_write);
40#endif
41
42static struct sd_handle *sdio_init(void);
43static int32_t bcm_emmc_card_ready_state(struct sd_handle *p_sdhandle);
44
45static void init_globals(void)
46{
47 memset((void *)emmc_global_buf_ptr, 0, sizeof(*emmc_global_buf_ptr));
48 memset((void *)emmc_global_vars_ptr, 0, sizeof(*emmc_global_vars_ptr));
49}
50
51/*
52 * This function is used to change partition
53 */
54uint32_t emmc_partition_select(uint32_t partition)
55{
56 int rc;
57 struct sd_handle *sd_handle = sdio_gethandle();
58
59 if (sd_handle->device == 0) {
60 EMMC_TRACE("eMMC init is not done");
61 return 0;
62 }
63
64 switch (partition) {
65 case EMMC_BOOT_PARTITION1:
66 rc = set_boot_config(sd_handle,
67 SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_BOOT1);
68 EMMC_TRACE(
69 "Change to Boot Partition 1 result:%d (0 means SD_OK)\n",
70 rc);
71 break;
72
73 case EMMC_BOOT_PARTITION2:
74 rc = set_boot_config(sd_handle,
75 SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_BOOT2);
76 EMMC_TRACE(
77 "Change to Boot Partition 2 result:%d (0 means SD_OK)\n",
78 rc);
79 break;
80
81 case EMMC_USE_CURRENT_PARTITION:
82 rc = SD_OK;
83 EMMC_TRACE("Stay on current partition");
84 break;
85
86 case EMMC_USER_AREA:
87 default:
88 rc = set_boot_config(sd_handle,
89 SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_USER);
90 EMMC_TRACE("Change to User area result:%d (0 means SD_OK)\n",
91 rc);
92 break;
93
94 }
95 return (rc == SD_OK);
96}
97
98/*
99 * Initialize emmc controller for eMMC
100 * Returns 0 on fail condition
101 */
102uint32_t bcm_emmc_init(bool card_rdy_only)
103{
104 struct sd_handle *p_sdhandle;
105 uint32_t result = 0;
106
107 EMMC_TRACE("Enter emmc_controller_init()\n");
108
109 /* If eMMC is already initialized, skip init */
110 if (emmc_global_vars_ptr->init_done)
111 return 1;
112
113 init_globals();
114
115 p_sdhandle = sdio_init();
116
117 if (p_sdhandle == NULL) {
118 ERROR("eMMC init failed");
119 return result;
120 }
121
122 if (card_rdy_only) {
123 /* Put the card in Ready state, Not complete init */
124 result = bcm_emmc_card_ready_state(p_sdhandle);
125 return !result;
126 }
127
128 if (sdio_idle(p_sdhandle) == EMMC_BOOT_OK) {
129 set_config(p_sdhandle, SD_NORMAL_SPEED, MAX_CMD_RETRY, USE_DMA,
130 SD_DMA_BOUNDARY_256K, EMMC_BLOCK_SIZE,
131 EMMC_WFE_RETRY);
132
133 if (!select_blk_sz(p_sdhandle,
134 p_sdhandle->device->cfg.blockSize)) {
135 emmc_global_vars_ptr->init_done = 1;
136 result = 1;
137 } else {
138 ERROR("Select Block Size failed\n");
139 }
140 } else {
141 ERROR("eMMC init failed");
142 }
143
144 /* Initialization is failed, so deinit HW setting */
145 if (result == 0)
146 emmc_deinit();
147
148 return result;
149}
150
151/*
152 * Function to de-init SDIO controller for eMMC
153 */
154void emmc_deinit(void)
155{
156 emmc_global_vars_ptr->init_done = 0;
157 emmc_global_vars_ptr->sdHandle.card = 0;
158 emmc_global_vars_ptr->sdHandle.device = 0;
159}
160
161/*
162 * Read eMMC memory
163 * Returns read_size
164 */
165uint32_t emmc_read(uintptr_t mem_addr, uintptr_t storage_addr,
166 size_t storage_size, size_t bytes_to_read)
167{
168 struct sd_handle *sd_handle = sdio_gethandle();
169
170 if (sd_handle->device == 0) {
171 EMMC_TRACE("eMMC init is not done");
172 return 0;
173 }
174
175 return sdio_read(sdio_gethandle(), mem_addr, storage_addr,
176 storage_size, bytes_to_read);
177}
178
179#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE
180#define EXT_CSD_ERASE_GRP_SIZE 224
181
182static int emmc_block_erase(uintptr_t mem_addr, size_t blocks)
183{
184 struct sd_handle *sd_handle = sdio_gethandle();
185
186 if (sd_handle->device == 0) {
187 ERROR("eMMC init is not done");
188 return -1;
189 }
190
191 return erase_card(sdio_gethandle(), mem_addr, blocks);
192}
193
194int emmc_erase(uintptr_t mem_addr, size_t num_of_blocks, uint32_t partition)
195{
196 int err = 0;
197 size_t block_count = 0, blocks = 0;
198 size_t erase_group = 0;
199
200 erase_group =
201 emmc_global_buf_ptr->u.Ext_CSD_storage[EXT_CSD_ERASE_GRP_SIZE]*1024;
202
203 INFO("eMMC Erase Group Size=0x%lx\n", erase_group);
204
205 emmc_partition_select(partition);
206
207 while (block_count < num_of_blocks) {
208 blocks = ((num_of_blocks - block_count) > erase_group) ?
209 erase_group : (num_of_blocks - block_count);
210 err = emmc_block_erase(mem_addr + block_count, blocks);
211 if (err)
212 break;
213
214 block_count += blocks;
215 }
216
217 if (err == 0)
218 INFO("eMMC Erase of partition %d successful\n", partition);
219 else
220 ERROR("eMMC Erase of partition %d Failed(%i)\n", partition, err);
221
222 return err;
223}
224#endif
225
226#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
227/*
228 * Write to eMMC memory
229 * Returns written_size
230 */
231uint32_t emmc_write(uintptr_t mem_addr, uintptr_t data_addr,
232 size_t bytes_to_write)
233{
234 struct sd_handle *sd_handle = sdio_gethandle();
235
236 if (sd_handle->device == 0) {
237 EMMC_TRACE("eMMC init is not done");
238 return 0;
239 }
240
241 return sdio_write(sd_handle, mem_addr, data_addr, bytes_to_write);
242}
243#endif
244
245/*
246 * Send SDIO Cmd
247 * Return 0 for pass condition
248 */
249uint32_t send_sdio_cmd(uint32_t cmdIndex, uint32_t argument,
250 uint32_t options, struct sd_resp *resp)
251{
252 struct sd_handle *sd_handle = sdio_gethandle();
253
254 if (sd_handle->device == 0) {
255 EMMC_TRACE("eMMC init is not done");
256 return 1;
257 }
258
259 return send_cmd(sd_handle, cmdIndex, argument, options, resp);
260}
261
262
263/*
264 * This function return SDIO handle
265 */
266struct sd_handle *sdio_gethandle(void)
267{
268 return &emmc_global_vars_ptr->sdHandle;
269}
270
271/*
272 * Initialize SDIO controller
273 */
274struct sd_handle *sdio_init(void)
275{
276 uint32_t SDIO_base;
277 struct sd_handle *p_sdhandle = &emmc_global_vars_ptr->sdHandle;
278
279 SDIO_base = EMMC_CTRL_REGS_BASE_ADDR;
280
Boyan Karatotevd8705c42022-11-22 14:05:18 +0000281 if (SDIO_base == SDIO0_EMMCSDXC_SYSADDR) {
Sheetal Tigadolib0156702020-01-05 14:59:04 +0530282 EMMC_TRACE(" ---> for SDIO 0 Controller\n\n");
Boyan Karatotevd8705c42022-11-22 14:05:18 +0000283 }
Sheetal Tigadolib0156702020-01-05 14:59:04 +0530284
285 memset(p_sdhandle, 0, sizeof(struct sd_handle));
286
287 p_sdhandle->device = &emmc_global_vars_ptr->sdDevice;
288 p_sdhandle->card = &emmc_global_vars_ptr->sdCard;
289
290 memset(p_sdhandle->device, 0, sizeof(struct sd_dev));
291 memset(p_sdhandle->card, 0, sizeof(struct sd_card_info));
292
293 if (chal_sd_start((CHAL_HANDLE *) p_sdhandle->device,
Boyan Karatotevd8705c42022-11-22 14:05:18 +0000294 SD_PIO_MODE, SDIO_base, SDIO_base) != SD_OK) {
Sheetal Tigadolib0156702020-01-05 14:59:04 +0530295 return NULL;
Boyan Karatotevd8705c42022-11-22 14:05:18 +0000296 }
Sheetal Tigadolib0156702020-01-05 14:59:04 +0530297
298 set_config(p_sdhandle, SD_NORMAL_SPEED, MAX_CMD_RETRY, SD_DMA_OFF,
299 SD_DMA_BOUNDARY_4K, EMMC_BLOCK_SIZE, EMMC_WFE_RETRY);
300
301 return &emmc_global_vars_ptr->sdHandle;
302}
303
304uint32_t sdio_idle(struct sd_handle *p_sdhandle)
305{
306 reset_card(p_sdhandle);
307
308 SD_US_DELAY(1000);
309
310 if (init_card(p_sdhandle, SD_CARD_DETECT_MMC) != SD_OK) {
311 reset_card(p_sdhandle);
312 reset_host_ctrl(p_sdhandle);
313 return EMMC_BOOT_NO_CARD;
314 }
315
316 return EMMC_BOOT_OK;
317}
318
319/*
320 * This function read eMMC
321 */
322uint32_t sdio_read(struct sd_handle *p_sdhandle,
323 uintptr_t mem_addr,
324 uintptr_t storage_addr,
325 size_t storage_size, size_t bytes_to_read)
326{
327 uint32_t offset = 0, blockAddr, readLen = 0, rdCount;
328 uint32_t remSize, manual_copy_size;
329 uint8_t *outputBuf = (uint8_t *) storage_addr;
330 const size_t blockSize = p_sdhandle->device->cfg.blockSize;
331
332 VERBOSE("EMMC READ: dst=0x%lx, src=0x%lx, size=0x%lx\n",
333 storage_addr, mem_addr, bytes_to_read);
334
Boyan Karatotevd8705c42022-11-22 14:05:18 +0000335 if (storage_size < bytes_to_read) {
Sheetal Tigadolib0156702020-01-05 14:59:04 +0530336 /* Don't have sufficient storage to complete the operation */
337 return 0;
Boyan Karatotevd8705c42022-11-22 14:05:18 +0000338 }
Sheetal Tigadolib0156702020-01-05 14:59:04 +0530339
340 /* Range check non high capacity memory */
341 if ((p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) == 0) {
Boyan Karatotevd8705c42022-11-22 14:05:18 +0000342 if (mem_addr > 0x80000000) {
Sheetal Tigadolib0156702020-01-05 14:59:04 +0530343 return 0;
Boyan Karatotevd8705c42022-11-22 14:05:18 +0000344 }
Sheetal Tigadolib0156702020-01-05 14:59:04 +0530345 }
346
347 /* High capacity card use block address mode */
348 if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) {
349 blockAddr = (uint32_t) (mem_addr / blockSize);
350 offset = (uint32_t) (mem_addr - (blockAddr * blockSize));
351 } else {
352 blockAddr = (uint32_t) (mem_addr / blockSize) * blockSize;
353 offset = (uint32_t) (mem_addr - blockAddr);
354 }
355
356 remSize = bytes_to_read;
357
358 rdCount = 0;
359
360 /* Process first unaligned block of MAX_READ_LENGTH */
361 if (offset > 0) {
362 if (!read_block(p_sdhandle, emmc_global_buf_ptr->u.tempbuf,
363 blockAddr, SD_MAX_READ_LENGTH)) {
364
365 if (remSize < (blockSize - offset)) {
366 rdCount += remSize;
367 manual_copy_size = remSize;
368 remSize = 0; /* read is done */
369 } else {
370 remSize -= (blockSize - offset);
371 rdCount += (blockSize - offset);
372 manual_copy_size = blockSize - offset;
373 }
374
375 /* Check for overflow */
376 if (manual_copy_size > storage_size ||
377 (((uintptr_t)outputBuf + manual_copy_size) >
378 (storage_addr + storage_size))) {
379 ERROR("EMMC READ: Overflow 1\n");
380 return 0;
381 }
382
383 memcpy(outputBuf,
384 (void *)((uintptr_t)
385 (emmc_global_buf_ptr->u.tempbuf + offset)),
386 manual_copy_size);
387
388 /* Update Physical address */
389 outputBuf += manual_copy_size;
390
Boyan Karatotevd8705c42022-11-22 14:05:18 +0000391 if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) {
Sheetal Tigadolib0156702020-01-05 14:59:04 +0530392 blockAddr++;
Boyan Karatotevd8705c42022-11-22 14:05:18 +0000393 } else {
Sheetal Tigadolib0156702020-01-05 14:59:04 +0530394 blockAddr += blockSize;
Boyan Karatotevd8705c42022-11-22 14:05:18 +0000395 }
Sheetal Tigadolib0156702020-01-05 14:59:04 +0530396 } else {
397 return 0;
398 }
399 }
400
401 while (remSize >= blockSize) {
402
Boyan Karatotevd8705c42022-11-22 14:05:18 +0000403 if (remSize >= SD_MAX_BLK_TRANSFER_LENGTH) {
Sheetal Tigadolib0156702020-01-05 14:59:04 +0530404 readLen = SD_MAX_BLK_TRANSFER_LENGTH;
Boyan Karatotevd8705c42022-11-22 14:05:18 +0000405 } else {
Sheetal Tigadolib0156702020-01-05 14:59:04 +0530406 readLen = (remSize / blockSize) * blockSize;
Boyan Karatotevd8705c42022-11-22 14:05:18 +0000407 }
Sheetal Tigadolib0156702020-01-05 14:59:04 +0530408
409 /* Check for overflow */
410 if ((rdCount + readLen) > storage_size ||
411 (((uintptr_t) outputBuf + readLen) >
412 (storage_addr + storage_size))) {
413 ERROR("EMMC READ: Overflow\n");
414 return 0;
415 }
416
417 if (!read_block(p_sdhandle, outputBuf, blockAddr, readLen)) {
Boyan Karatotevd8705c42022-11-22 14:05:18 +0000418 if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) {
Sheetal Tigadolib0156702020-01-05 14:59:04 +0530419 blockAddr += (readLen / blockSize);
Boyan Karatotevd8705c42022-11-22 14:05:18 +0000420 } else {
Sheetal Tigadolib0156702020-01-05 14:59:04 +0530421 blockAddr += readLen;
Boyan Karatotevd8705c42022-11-22 14:05:18 +0000422 }
Sheetal Tigadolib0156702020-01-05 14:59:04 +0530423
424 remSize -= readLen;
425 rdCount += readLen;
426
427 /* Update Physical address */
428 outputBuf += readLen;
429 } else {
430 return 0;
431 }
432 }
433
434 /* process the last unaligned block reading */
435 if (remSize > 0) {
436 if (!read_block(p_sdhandle, emmc_global_buf_ptr->u.tempbuf,
437 blockAddr, SD_MAX_READ_LENGTH)) {
438
439 rdCount += remSize;
440 /* Check for overflow */
441 if (rdCount > storage_size ||
442 (((uintptr_t) outputBuf + remSize) >
443 (storage_addr + storage_size))) {
444 ERROR("EMMC READ: Overflow\n");
445 return 0;
446 }
447
448 memcpy(outputBuf,
449 emmc_global_buf_ptr->u.tempbuf, remSize);
450
451 /* Update Physical address */
452 outputBuf += remSize;
453 } else {
454 rdCount = 0;
455 }
456 }
457
458 return rdCount;
459}
460
461#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE
462static uint32_t sdio_write(struct sd_handle *p_sdhandle, uintptr_t mem_addr,
463 uintptr_t data_addr, size_t bytes_to_write)
464{
465
466 uint32_t offset, blockAddr, writeLen, wtCount = 0;
467 uint32_t remSize, manual_copy_size = 0;
468
469 uint8_t *inputBuf = (uint8_t *)data_addr;
470
471 /* range check non high capacity memory */
472 if ((p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) == 0) {
Boyan Karatotevd8705c42022-11-22 14:05:18 +0000473 if (mem_addr > 0x80000000) {
Sheetal Tigadolib0156702020-01-05 14:59:04 +0530474 return 0;
Boyan Karatotevd8705c42022-11-22 14:05:18 +0000475 }
Sheetal Tigadolib0156702020-01-05 14:59:04 +0530476 }
477
478 /* the high capacity card use block address mode */
479 if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) {
480 blockAddr =
481 (uint32_t)(mem_addr / p_sdhandle->device->cfg.blockSize);
482 offset =
483 (uint32_t)(mem_addr -
484 blockAddr * p_sdhandle->device->cfg.blockSize);
485 } else {
486 blockAddr =
487 ((uint32_t)mem_addr / p_sdhandle->device->cfg.blockSize) *
488 p_sdhandle->device->cfg.blockSize;
489 offset = (uint32_t) mem_addr - blockAddr;
490 }
491
492 remSize = bytes_to_write;
493
494 wtCount = 0;
495
496 /* process first unaligned block */
497 if (offset > 0) {
498 if (!read_block(p_sdhandle, emmc_global_buf_ptr->u.tempbuf,
499 blockAddr, p_sdhandle->device->cfg.blockSize)) {
500
501 if (remSize <
Boyan Karatotevd8705c42022-11-22 14:05:18 +0000502 (p_sdhandle->device->cfg.blockSize - offset)) {
Sheetal Tigadolib0156702020-01-05 14:59:04 +0530503 manual_copy_size = remSize;
Boyan Karatotevd8705c42022-11-22 14:05:18 +0000504 } else {
Sheetal Tigadolib0156702020-01-05 14:59:04 +0530505 manual_copy_size =
506 p_sdhandle->device->cfg.blockSize - offset;
Boyan Karatotevd8705c42022-11-22 14:05:18 +0000507 }
Sheetal Tigadolib0156702020-01-05 14:59:04 +0530508
509 memcpy((void *)((uintptr_t)
510 (emmc_global_buf_ptr->u.tempbuf + offset)),
511 inputBuf,
512 manual_copy_size);
513
514 /* Update Physical address */
515
516 if (!write_block(p_sdhandle,
517 emmc_global_buf_ptr->u.tempbuf,
518 blockAddr,
519 p_sdhandle->device->cfg.blockSize)) {
520
521 if (remSize <
522 (p_sdhandle->device->cfg.blockSize -
523 offset)) {
524 wtCount += remSize;
525 manual_copy_size = remSize;
526 remSize = 0; /* read is done */
527 } else {
528 remSize -=
529 (p_sdhandle->device->cfg.blockSize -
530 offset);
531 wtCount +=
532 (p_sdhandle->device->cfg.blockSize -
533 offset);
534 manual_copy_size =
535 p_sdhandle->device->cfg.blockSize -
536 offset;
537 }
538
539 inputBuf += manual_copy_size;
540
541 if (p_sdhandle->device->ctrl.ocr &
Boyan Karatotevd8705c42022-11-22 14:05:18 +0000542 SD_CARD_HIGH_CAPACITY) {
Sheetal Tigadolib0156702020-01-05 14:59:04 +0530543 blockAddr++;
Boyan Karatotevd8705c42022-11-22 14:05:18 +0000544 } else {
Sheetal Tigadolib0156702020-01-05 14:59:04 +0530545 blockAddr +=
546 p_sdhandle->device->cfg.blockSize;
Boyan Karatotevd8705c42022-11-22 14:05:18 +0000547 }
Sheetal Tigadolib0156702020-01-05 14:59:04 +0530548 } else
549 return 0;
550 } else {
551 return 0;
552 }
553 }
554
555 /* process block writing */
556 while (remSize >= p_sdhandle->device->cfg.blockSize) {
557 if (remSize >= SD_MAX_READ_LENGTH) {
558 writeLen = SD_MAX_READ_LENGTH;
559 } else {
560 writeLen =
561 (remSize / p_sdhandle->device->cfg.blockSize) *
562 p_sdhandle->device->cfg.blockSize;
563 }
564
565 if (!write_block(p_sdhandle, inputBuf, blockAddr, writeLen)) {
566 if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY)
567 blockAddr +=
568 (writeLen /
569 p_sdhandle->device->cfg.blockSize);
570 else
571 blockAddr += writeLen;
572
573 remSize -= writeLen;
574 wtCount += writeLen;
575 inputBuf += writeLen;
576 } else {
577 return 0;
578 }
579 }
580
581 /* process the last unaligned block reading */
582 if (remSize > 0) {
583 if (!read_block(p_sdhandle,
584 emmc_global_buf_ptr->u.tempbuf,
585 blockAddr, p_sdhandle->device->cfg.blockSize)) {
586
587 memcpy(emmc_global_buf_ptr->u.tempbuf,
588 inputBuf, remSize);
589
590 /* Update Physical address */
591
592 if (!write_block(p_sdhandle,
593 emmc_global_buf_ptr->u.tempbuf,
594 blockAddr,
595 p_sdhandle->device->cfg.blockSize)) {
596 wtCount += remSize;
597 inputBuf += remSize;
598 } else {
599 return 0;
600 }
601 } else {
602 wtCount = 0;
603 }
604 }
605
606 return wtCount;
607}
608#endif
609
610/*
611 * Function to put the card in Ready state by sending CMD0 and CMD1
612 */
613static int32_t bcm_emmc_card_ready_state(struct sd_handle *p_sdhandle)
614{
615 int32_t result = 0;
616 uint32_t argument = MMC_CMD_IDLE_RESET_ARG; /* Exit from Boot mode */
617
618 if (p_sdhandle) {
619 send_sdio_cmd(SD_CMD_GO_IDLE_STATE, argument, 0, NULL);
620
621 result = reset_card(p_sdhandle);
622 if (result != SD_OK) {
623 EMMC_TRACE("eMMC Reset error\n");
624 return SD_RESET_ERROR;
625 }
626 SD_US_DELAY(2000);
627 result = mmc_cmd1(p_sdhandle);
628 }
629
630 return result;
631}