stm32h7: sdmmc: write DCTRL after DTIMER/DLENR for non-data commands

rockbox-gerrit-noreply--- via rockbox-cvs <[email protected]>
Newsgroups gmane.comp.systems.archos.rockbox.cvs
Message-ID <[email protected]>
commit 55183c0b2a82423835aaa0eee276357d9beae3e8
Author: Aidan MacDonald <[email protected]>
Date:   Tue Feb 24 20:33:27 2026 +0000

    stm32h7: sdmmc: write DCTRL after DTIMER/DLENR for non-data commands
    
    According to RM0433 the DCTRL register needs to be written
    after DLENR and DTIMER. This is respected for data transfer
    commands but not for non-data commands. Nothing bad seems
    to be happening because of this, but it seems wise to rectify
    the issue.
    
    Change-Id: I55d8f2c1994bff747e5978847fda57445f001b02

diff --git a/firmware/target/arm/stm32/sdmmc-stm32h7.c b/firmware/target/arm/stm32/sdmmc-stm32h7.c
index 014e5f6340..2fd9ff1cb4 100644
--- a/firmware/target/arm/stm32/sdmmc-stm32h7.c
+++ b/firmware/target/arm/stm32/sdmmc-stm32h7.c
@@ -260,6 +260,7 @@ int stm32h7_sdmmc_submit_command(void *controller,
     uint32_t maskr = CMD_ERROR_BITS;
     uint32_t cmdr = __reg_orf(SDMMC_CMDR, CPSMEN(1), CMDINDEX(cmd->command));
     uint32_t cmd_wait = WAIT_CMD;
+    uint32_t dctrl = 0, dtimer = 0, dlenr = 0;
 
     void *buff_addr = cmd->buffer;
     size_t buff_size = cmd->nr_blocks * cmd->block_len;
@@ -317,7 +318,6 @@ int stm32h7_sdmmc_submit_command(void *controller,
             panicf("%s: buffer too big", __func__);
 
         /* Set block size */
-        uint32_t dctrl = 0;
         uint32_t dblocksize = find_first_set_bit(cmd->block_len);
         if (dblocksize > 14 || (cmd->block_len & (cmd->block_len - 1)))
             panicf("%s: incorrect block size", __func__);
@@ -341,11 +341,8 @@ int stm32h7_sdmmc_submit_command(void *controller,
         reg_assignlf(ctl->regs, SDMMC_IDMACTRLR, IDMAEN(1));
 
         /* Use a 10 second timeout (DTIMER is in units of bus clocks) */
-        reg_varl(ctl->regs, SDMMC_DTIMER) = 10 * ctl->bus_freq;
-        reg_varl(ctl->regs, SDMMC_DLENR) = buff_size;
-
-        /* DCTRL must be written last */
-        reg_varl(ctl->regs, SDMMC_DCTRL) = dctrl;
+        dtimer = 10 * ctl->bus_freq;
+        dlenr = buff_size;
 
         /* Enable data phase */
         reg_vwritef(cmdr, SDMMC_CMDR, CMDTRANS(1));
@@ -356,16 +353,17 @@ int stm32h7_sdmmc_submit_command(void *controller,
     {
         /* Disable data transfer */
         reg_assignlf(ctl->regs, SDMMC_IDMACTRLR, IDMAEN(0));
-        reg_varl(ctl->regs, SDMMC_DLENR) = 0;
-        reg_varl(ctl->regs, SDMMC_DCTRL) = 0;
 
         /* DTIMER is the wait time for the busy signal */
         if (cmd->flags & SDMMC_RESP_BUSY)
-            reg_varl(ctl->regs, SDMMC_DTIMER) = 1 * ctl->bus_freq;
-        else
-            reg_varl(ctl->regs, SDMMC_DTIMER) = 0;
+            dtimer = 1 * ctl->bus_freq;
     }
 
+    /* Set data transfer registers */
+    reg_varl(ctl->regs, SDMMC_DLENR)  = dlenr;
+    reg_varl(ctl->regs, SDMMC_DTIMER) = dtimer;
+    reg_varl(ctl->regs, SDMMC_DCTRL)  = dctrl;
+
     /*
      * Set CMDSTOP bit for CMD12 (stop transmission) command;
      * this is needed to stop the DPSM in case of an error in
-- 
rockbox-cvs mailing list
[email protected]
https://lists.haxx.se/mailman/listinfo/rockbox-cvs
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.