Skip to content

Commit 5a48625

Browse files
dgarskedanielinux
authored andcommitted
Fixes for mmc_write.
1 parent 0462e0a commit 5a48625

File tree

2 files changed

+71
-77
lines changed

2 files changed

+71
-77
lines changed

hal/mpfs250.c

Lines changed: 69 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,14 @@ void mmc_irq_handler(void)
310310

311311
/* Check for DMA interrupt */
312312
if (status & EMMC_SD_SRS12_DMAINT) {
313+
/* Read updated DMA address - engine will increment block */
314+
uint32_t* addr = (uint32_t*)(uintptr_t)((((uint64_t)EMMC_SD_SRS23) << 32) |
315+
EMMC_SD_SRS22);
316+
/* Set new DMA address for next boundary */
317+
EMMC_SD_SRS22 = (uint32_t)(uintptr_t)addr;
318+
EMMC_SD_SRS23 = (uint32_t)(((uint64_t)(uintptr_t)addr) >> 32);
319+
/* triggers next DMA block on write of top bit */
320+
313321
g_mmc_irq_status |= MMC_IRQ_FLAG_DMAINT;
314322
EMMC_SD_SRS12 = EMMC_SD_SRS12_DMAINT; /* Clear interrupt */
315323
}
@@ -390,7 +398,6 @@ static int mmc_wait_irq(uint32_t expected_flags, uint32_t timeout)
390398
return 0;
391399
}
392400
}
393-
/* Brief delay while waiting */
394401
asm volatile("nop");
395402
}
396403
return -1; /* Timeout */
@@ -591,6 +598,7 @@ static uint32_t mmc_get_response_type(uint8_t resp_type)
591598
return cmd_reg;
592599
}
593600

601+
#define DEVICE_BUSY 1
594602
static int mmc_send_cmd_internal(uint32_t cmd_type,
595603
uint32_t cmd_index, uint32_t cmd_arg, uint8_t resp_type)
596604
{
@@ -619,24 +627,18 @@ static int mmc_send_cmd_internal(uint32_t cmd_type,
619627
while ((EMMC_SD_SRS12 & (EMMC_SD_SRS12_CC | EMMC_SD_SRS12_TC |
620628
EMMC_SD_SRS12_EINT)) == 0 && --timeout > 0);
621629

622-
if (timeout == 0 || (EMMC_SD_SRS12 & EMMC_SD_SRS12_EINT)) {
623-
wolfBoot_printf("mmc_send_cmd:%s error SRS12: 0x%08X\n",
624-
(timeout == 0) ? " timeout" : "", EMMC_SD_SRS12);
630+
if (timeout == 0) {
631+
wolfBoot_printf("mmc_send_cmd: timeout waiting for command complete\n");
632+
status = -1; /* error */
633+
}
634+
else if (EMMC_SD_SRS12 & EMMC_SD_SRS12_EINT) {
635+
wolfBoot_printf("mmc_send_cmd: error SRS12: 0x%08X\n", EMMC_SD_SRS12);
625636
status = -1; /* error */
626637
}
627638

628639
EMMC_SD_SRS12 = EMMC_SD_SRS12_CC; /* clear command complete */
629640
while ((EMMC_SD_SRS09 & EMMC_SD_SRS09_CICMD) != 0);
630641

631-
return status;
632-
}
633-
634-
#define DEVICE_BUSY 1
635-
int mmc_send_cmd(uint32_t cmd_index, uint32_t cmd_arg, uint8_t resp_type)
636-
{
637-
/* send command */
638-
int status = mmc_send_cmd_internal(EMMC_SD_SRS03_CMD_NORMAL, cmd_index,
639-
cmd_arg, resp_type);
640642
if (status == 0) {
641643
/* check for device busy */
642644
if (resp_type == EMMC_SD_RESP_R1 || resp_type == EMMC_SD_RESP_R1B) {
@@ -648,8 +650,17 @@ int mmc_send_cmd(uint32_t cmd_index, uint32_t cmd_arg, uint8_t resp_type)
648650
}
649651
}
650652

653+
return status;
654+
}
655+
656+
int mmc_send_cmd(uint32_t cmd_index, uint32_t cmd_arg, uint8_t resp_type)
657+
{
658+
/* send command */
659+
int status = mmc_send_cmd_internal(EMMC_SD_SRS03_CMD_NORMAL, cmd_index,
660+
cmd_arg, resp_type);
661+
651662
/* clear all status interrupts
652-
* (except current limit, card interrupt/removal/insert) */
663+
* (except current limit, card interrupt/removal/insert) */
653664
EMMC_SD_SRS12 = ~(EMMC_SD_SRS12_ECL |
654665
EMMC_SD_SRS12_CINT |
655666
EMMC_SD_SRS12_CR |
@@ -737,7 +748,7 @@ int mmc_read(uint32_t cmd_index, uint32_t block_addr, uint32_t* dst,
737748
/* wait for command and data line busy to clear */
738749
while ((EMMC_SD_SRS09 & (EMMC_SD_SRS09_CICMD | EMMC_SD_SRS09_CIDAT)) != 0);
739750

740-
/* set transfer block count */
751+
/* set transfer block count and block size */
741752
EMMC_SD_SRS01 = (block_count << EMMC_SD_SRS01_BCCT_SHIFT) | sz;
742753

743754
cmd_reg = ((cmd_index << EMMC_SD_SRS03_CIDX_SHIFT) |
@@ -762,27 +773,28 @@ int mmc_read(uint32_t cmd_index, uint32_t block_addr, uint32_t* dst,
762773
EMMC_SD_SRS01 = (block_count << EMMC_SD_SRS01_BCCT_SHIFT) |
763774
EMMC_SD_SRS01_DMA_BUFF_512KB | EMMC_SD_BLOCK_SIZE;
764775

765-
/* SDMA mode (for 32-bit transfers) */
776+
/* SDMA mode */
766777
EMMC_SD_SRS10 |= EMMC_SD_SRS10_DMA_SDMA;
767-
EMMC_SD_SRS15 |= EMMC_SD_SRS15_HV4E;
768-
EMMC_SD_SRS16 &= ~EMMC_SD_SRS16_A64S;
769778
/* set SDMA destination address */
770779
EMMC_SD_SRS22 = (uint32_t)(uintptr_t)dst;
771780
EMMC_SD_SRS23 = (uint32_t)(((uint64_t)(uintptr_t)dst) >> 32);
772781

773782
/* Enable SDMA interrupts */
774783
mmc_enable_sdma_interrupts();
775784
}
785+
else {
786+
EMMC_SD_SRS01 = (block_count << EMMC_SD_SRS01_BCCT_SHIFT) |
787+
EMMC_SD_BLOCK_SIZE;
788+
}
776789
}
777790

778791
EMMC_SD_SRS02 = block_addr; /* cmd argument */
779792
EMMC_SD_SRS03 = cmd_reg; /* execute command */
780793

781794
if (cmd_reg & EMMC_SD_SRS03_DMAE) {
782795
while (1) { /* DMA mode with interrupt support */
783-
/* Wait for DMA interrupt, transfer complete, or error */
784-
status = mmc_wait_irq(MMC_IRQ_FLAG_DMAINT | MMC_IRQ_FLAG_TC,
785-
0x00FFFFFF);
796+
/* Wait for transfer complete or error */
797+
status = mmc_wait_irq(MMC_IRQ_FLAG_TC, 0x00FFFFFF);
786798
if (status != 0) {
787799
/* Timeout or error */
788800
wolfBoot_printf("mmc_read: SDMA interrupt timeout/error\n");
@@ -795,17 +807,6 @@ int mmc_read(uint32_t cmd_index, uint32_t block_addr, uint32_t* dst,
795807
g_mmc_irq_status &= ~MMC_IRQ_FLAG_TC;
796808
break; /* Transfer complete */
797809
}
798-
799-
/* Check for DMA boundary interrupt - need to update address */
800-
if (g_mmc_irq_status & MMC_IRQ_FLAG_DMAINT) {
801-
g_mmc_irq_status &= ~MMC_IRQ_FLAG_DMAINT;
802-
/* Read updated DMA address - engine will have incremented */
803-
dst = (uint32_t*)(uintptr_t)((((uint64_t)EMMC_SD_SRS23) << 32) |
804-
EMMC_SD_SRS22);
805-
/* Set new DMA address for next boundary */
806-
EMMC_SD_SRS22 = (uint32_t)(uintptr_t)dst;
807-
EMMC_SD_SRS23 = (uint32_t)(((uint64_t)(uintptr_t)dst) >> 32);
808-
}
809810
}
810811

811812
/* Disable SDMA interrupts after transfer */
@@ -829,6 +830,10 @@ int mmc_read(uint32_t cmd_index, uint32_t block_addr, uint32_t* dst,
829830
}
830831
sz -= read_sz;
831832
}
833+
834+
if (reg & EMMC_SD_SRS12_EINT) {
835+
break; /* error */
836+
}
832837
}
833838
}
834839

@@ -839,7 +844,7 @@ int mmc_read(uint32_t cmd_index, uint32_t block_addr, uint32_t* dst,
839844
if (cmd_index == MMC_CMD18_READ_MULTIPLE) {
840845
(void)mmc_send_cmd_internal(EMMC_SD_SRS03_CMD_ABORT,
841846
MMC_CMD12_STOP_TRANS, (g_rca << SD_RCA_SHIFT),
842-
EMMC_SD_RESP_R1); /* use R1B for write */
847+
EMMC_SD_RESP_R1);
843848
}
844849

845850
/* wait for idle */
@@ -895,20 +900,15 @@ int mmc_write(uint32_t cmd_index, uint32_t block_addr, const uint32_t* src,
895900
/* wait for command and data line busy to clear */
896901
while ((EMMC_SD_SRS09 & (EMMC_SD_SRS09_CICMD | EMMC_SD_SRS09_CIDAT)) != 0);
897902

898-
/* set transfer block count */
903+
/* set transfer block count and block size */
899904
EMMC_SD_SRS01 = (block_count << EMMC_SD_SRS01_BCCT_SHIFT) | sz;
900905

901-
/* Build command register for write:
902-
* - DTDS=0 for write direction (DTDS=1 is read)
903-
* - DPS=1 data present
904-
* - BCE=1 block count enable
905-
* - RECE=1 response error check enable
906-
* - RID=1 response interrupt disable
907-
*/
906+
/* Build command register for write */
908907
cmd_reg = ((cmd_index << EMMC_SD_SRS03_CIDX_SHIFT) |
909908
EMMC_SD_SRS03_DPS | /* Data present, no DTDS = write direction */
910909
EMMC_SD_SRS03_BCE | EMMC_SD_SRS03_RECE | EMMC_SD_SRS03_RID |
911-
EMMC_SD_SRS03_RESP_48 | EMMC_SD_SRS03_CRCCE | EMMC_SD_SRS03_CICE);
910+
EMMC_SD_SRS03_RESP_48 | EMMC_SD_SRS03_CRCCE | EMMC_SD_SRS03_CICE
911+
);
912912

913913
if (cmd_index == MMC_CMD25_WRITE_MULTIPLE) {
914914
cmd_reg |= EMMC_SD_SRS03_MSBS; /* enable multi-block select */
@@ -930,20 +930,20 @@ int mmc_write(uint32_t cmd_index, uint32_t block_addr, const uint32_t* src,
930930
/* Enable SDMA interrupts */
931931
mmc_enable_sdma_interrupts();
932932
}
933+
else {
934+
/* set transfer block count and block size */
935+
EMMC_SD_SRS01 = (block_count << EMMC_SD_SRS01_BCCT_SHIFT) |
936+
EMMC_SD_BLOCK_SIZE;
937+
}
933938
}
934939

935-
/* wait for cmd/data line not busy */
936-
while ((EMMC_SD_SRS09 &
937-
(EMMC_SD_SRS09_CICMD | EMMC_SD_SRS09_CIDAT)) != 0);
938-
939940
EMMC_SD_SRS02 = block_addr; /* cmd argument */
940941
EMMC_SD_SRS03 = cmd_reg; /* execute command */
941942

942943
if (cmd_reg & EMMC_SD_SRS03_DMAE) {
943944
while (1) { /* DMA mode with interrupt support */
944-
/* Wait for DMA interrupt, transfer complete, or error */
945-
status = mmc_wait_irq(MMC_IRQ_FLAG_DMAINT | MMC_IRQ_FLAG_TC,
946-
0x00FFFFFF);
945+
/* Wait for transfer complete or error */
946+
status = mmc_wait_irq(MMC_IRQ_FLAG_TC, 0x00FFFFFF);
947947
if (status != 0) {
948948
/* Timeout or error */
949949
wolfBoot_printf("mmc_write: SDMA interrupt timeout/error\n");
@@ -956,17 +956,6 @@ int mmc_write(uint32_t cmd_index, uint32_t block_addr, const uint32_t* src,
956956
g_mmc_irq_status &= ~MMC_IRQ_FLAG_TC;
957957
break; /* Transfer complete */
958958
}
959-
960-
/* Check for DMA boundary interrupt - need to update address */
961-
if (g_mmc_irq_status & MMC_IRQ_FLAG_DMAINT) {
962-
g_mmc_irq_status &= ~MMC_IRQ_FLAG_DMAINT;
963-
/* Read updated DMA address - engine will have incremented */
964-
src = (const uint32_t*)(uintptr_t)((((uint64_t)EMMC_SD_SRS23) << 32) |
965-
EMMC_SD_SRS22);
966-
/* Set new DMA address for next boundary */
967-
EMMC_SD_SRS22 = (uint32_t)(uintptr_t)src;
968-
EMMC_SD_SRS23 = (uint32_t)(((uint64_t)(uintptr_t)src) >> 32);
969-
}
970959
}
971960

972961
/* Disable SDMA interrupts after transfer */
@@ -990,30 +979,32 @@ int mmc_write(uint32_t cmd_index, uint32_t block_addr, const uint32_t* src,
990979
}
991980
sz -= write_sz;
992981
}
993-
994-
/* wait for trasnfer complete (or error) */
995-
while (((reg = EMMC_SD_SRS12) &
996-
(EMMC_SD_SRS12_TC | EMMC_SD_SRS12_EINT)) == 0);
982+
if (reg & EMMC_SD_SRS12_EINT) {
983+
break; /* error */
984+
}
997985
}
986+
987+
/* wait for transfer complete (or error) BEFORE checking status */
988+
while (((reg = EMMC_SD_SRS12) &
989+
(EMMC_SD_SRS12_TC | EMMC_SD_SRS12_EINT)) == 0);
998990
}
999991

1000992
/* check for any errors */
1001993
reg = EMMC_SD_SRS12;
1002994
if ((reg & EMMC_SD_SRS12_ERR_STAT) == 0) { /* no errors */
1003995
/* if multi-block write, send CMD12 to stop transfer */
1004996
if (cmd_index == MMC_CMD25_WRITE_MULTIPLE) {
997+
/* CMD12 requires CMD_ABORT type per SD spec */
1005998
status = mmc_send_cmd_internal(EMMC_SD_SRS03_CMD_ABORT,
1006999
MMC_CMD12_STOP_TRANS, (g_rca << SD_RCA_SHIFT),
1007-
EMMC_SD_RESP_R1B); /* R1B for write with busy */
1000+
EMMC_SD_RESP_R1B);
10081001
if (status != 0) {
10091002
wolfBoot_printf("mmc_write: CMD12 stop transfer error\n");
10101003
}
10111004
}
10121005

1013-
/* wait for card to finish programming (DAT0 goes high when ready) */
1014-
if (status == 0) {
1015-
status = mmc_wait_busy(1);
1016-
}
1006+
/* wait for idle */
1007+
status = mmc_wait_busy(0);
10171008
}
10181009
else {
10191010
wolfBoot_printf("mmc_write: error SRS12: 0x%08X\n", reg);
@@ -1393,7 +1384,7 @@ int mmc_init(void)
13931384
plic_init_mmc();
13941385

13951386
/* Set initial timeout to 500ms */
1396-
status = mmc_set_timeout(EMMC_SD_DATA_TIMEOUT_US);
1387+
status = mmc_set_timeout(EMMC_SD_INIT_TIMEOUT_US);
13971388
if (status != 0) {
13981389
return status;
13991390
}
@@ -1548,9 +1539,9 @@ int mmc_init(void)
15481539
status = mmc_wait_busy(1);
15491540
}
15501541
}
1542+
irq_restore = EMMC_SD_SRS13;
15511543
if (status == 0) {
15521544
/* disable card insert interrupt while changing bus width to avoid false triggers */
1553-
irq_restore = EMMC_SD_SRS13;
15541545
EMMC_SD_SRS13 = (irq_restore & ~EMMC_SD_SRS13_CINT_SE);
15551546

15561547
status = mmc_set_bus_width(4);
@@ -1595,8 +1586,11 @@ int mmc_init(void)
15951586
status = 0; /* Don't fail init on tuning failure */
15961587
}
15971588
#endif
1598-
1599-
EMMC_SD_SRS13 = irq_restore; /* re-enable interrupt */
1589+
}
1590+
EMMC_SD_SRS13 = irq_restore; /* re-enable interrupt */
1591+
if (status == 0) {
1592+
/* Set data timeout to 3000ms */
1593+
status = mmc_set_timeout(EMMC_SD_DATA_TIMEOUT_US);
16001594
}
16011595
return status;
16021596
}
@@ -1675,8 +1669,8 @@ int disk_write(int drv, uint64_t start, uint32_t count, const uint8_t *buf)
16751669
write_sz = EMMC_SD_BLOCK_SIZE;
16761670
}
16771671
if (write_sz < EMMC_SD_BLOCK_SIZE || /* partial block */
1678-
start_offset != 0 || /* start not block aligned */
1679-
((uintptr_t)buf % 4) != 0) /* buf not 4-byte aligned */
1672+
start_offset != 0 || /* start not block aligned */
1673+
((uintptr_t)buf % 4) != 0) /* buf not 4-byte aligned */
16801674
{
16811675
/* read-modify-write for partial block */
16821676
status = mmc_read(MMC_CMD17_READ_SINGLE, block_addr,

hal/mpfs250.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -817,8 +817,8 @@
817817
#define EMMC_SD_DEBOUNCE_TIME 0x300000U
818818

819819
/* Timeout values */
820-
#define EMMC_SD_DATA_TIMEOUT_US 750000U /* 750ms data timeout */
821-
#define EMMC_SD_CMD_TIMEOUT_MS 3000U /* 3s command timeout */
820+
#define EMMC_SD_INIT_TIMEOUT_US (500U * 1000U) /* 500ms init timeout */
821+
#define EMMC_SD_DATA_TIMEOUT_US (3000U * 1000U) /* 3000ms data timeout */
822822

823823
#define WOLFBOOT_CARDTYPE_SD 1
824824
#define WOLFBOOT_CARDTYPE_EMMC 2

0 commit comments

Comments
 (0)