SD card emulation and initialization in qemu when used by U-boot and QNX.

Olof Astrand
14 min readOct 6, 2024

--

AI hallucination of SDHC cards

As I investigated in a previous article, I discovered that the SD emulation in qemu was not good enough for the raspberry Pi4. Here I talk a how to improve that emulation as well as how the interface works. On the actual hardware, the device handling the communication with the host, sits on the SD-card itself. In qemu this is handled by hw/sd/sd.c

When I have the time I will update the qemu emulation to handle U-boot and QNX correctly.

  • SD cards use the SD protocol or SPI (Serial Peripheral Interface) to communicate with the host.
  • The data bus width for SD cards can vary, typically supporting 1-bit or 4-bit modes, which offer slower data transfer speeds compared to eMMC’s parallel bus.

FTL (Flash Translation Layer) is software that emulates block device behavior on flash hardware. Initially, FTL ran on host computers, as seen in early PCMCIA flash devices, where the host had to manage the FTL driver. Today, FTL is usually built into the device’s controller, such as in USB flash drives, SD cards, SSDs, and other FTL-based storage, which run FTL firmware on an internal controller.

These FTL devices present block-based access interfaces, such as MMC or SD, making them compatible with traditional Linux block devices and file systems (like FAT or ext4). This allows FTL devices to work similarly to hard drives. However, raw flash devices, often used in embedded systems, lack FTL and present more complexity. Raw flash operates with eraseblocks and requires specialized handling for wear-leveling, garbage collection, and error management, which is handled by software like UBIFS.

http://www.linux-mtd.infradead.org/doc/ubi.html

The command likely to fail when used by QNX and U-boot

CMD8: SEND_IF_COND

  • Command Index: CMD8
  • Purpose: Checks if the SD card supports the supplied voltage range and determines if it’s an SD Version 2.0 or later card.

Usage:

  • Voltage Range Verification: Ensures the card can operate at the voltage supplied by the host.
  • SD Version Detection: Differentiates between SD Version 2.0+ cards and older cards.

Arguments:

  • Bits [31:12]: Reserved (set to zero).
  • Bits [11:8] (Voltage Supplied): 0x1 if the host's supply voltage is 2.7–3.6V.
  • Bits [7:0] (Check Pattern): Any pattern; typically 0xAA.

Response:

  • Type: R7 (Response with the echo-back of the check pattern).
  • Expected Value: The card echoes back the voltage and check pattern if it supports the voltage range and is SD Version 2.0+.
  • Interpretation:
  • Valid Response: Card supports SD Version 2.0+ and the voltage range.
  • No Response or Illegal Command Error: Card is SD Version 1.x or MMC, or does not support the voltage range.
R7 Response

Other commands used at initialization.

SD Commands

There are some command response formats, R1, R2, R3 and R7, the answer depends on the command index. A byte of response, R1, is returned for most commands. The bit field of the R1 response is shown in image below, the value 0x00 means successful. When any error occured, corresponding status bit in the response will be set. The R3/R7 response (R1 + trailing 32-bit data) is for only CMD58 and CMD8.

R1 response
SPI initializarion
R3 response

Correct initialization by QNX on actual hardware. We will later go through the log step by step.

sdio_clock:  clk 400000
sdio_bus_width: width 1
sdio_timing: timing LS
sdio_bus_mode: mode open drain
sdio_signal_voltage: 3.3V
sdio_issue_cmd: CMD 0, flgs 0x1, arg 0x0, blks 0, blksz 0, timeout 1000ms
sdio_cmd_cmplt: CMD 0, flgs 0x1, arg 0x0, blks 0, blksz 0, status SUCCESS (1)
sdio_issue_cmd: CMD 8, flgs 0x152, arg 0x1aa, blks 0, blksz 0, timeout 1000ms
sdio_cmd_cmplt: CMD 8, flgs 0x152, arg 0x1aa, blks 0, blksz 0, status SUCCESS (1)
sdio_issue_cmd: CMD 55, flgs 0x151, arg 0x0, blks 0, blksz 0, timeout 1000ms
sdio_cmd_cmplt: CMD 55, flgs 0x151, arg 0x0, blks 0, blksz 0, status SUCCESS (1)
sdio_issue_cmd: CMD 41, flgs 0x812, arg 0x0, blks 0, blksz 0, timeout 1000ms
sdio_cmd_cmplt: CMD 41, flgs 0x812, arg 0x0, blks 0, blksz 0, status SUCCESS (1)
sd_app_send_op_cond: retries 0, rsp0 0x40ff8000
sdio_pwr: vdd 3.2 (0x100000)
sdio_issue_cmd: CMD 8, flgs 0x152, arg 0x1aa, blks 0, blksz 0, timeout 1000ms
sdio_cmd_cmplt: CMD 8, flgs 0x152, arg 0x1aa, blks 0, blksz 0, status SUCCESS (1)
sdio_issue_cmd: CMD 0, flgs 0x1, arg 0x0, blks 0, blksz 0, timeout 1000ms
sdio_cmd_cmplt: CMD 0, flgs 0x1, arg 0x0, blks 0, blksz 0, status SUCCESS (1)
sdio_issue_cmd: CMD 8, flgs 0x152, arg 0x1aa, blks 0, blksz 0, timeout 1000ms
sdio_cmd_cmplt: CMD 8, flgs 0x152, arg 0x1aa, blks 0, blksz 0, status SUCCESS (1)
sdio_issue_cmd: CMD 55, flgs 0x151, arg 0x0, blks 0, blksz 0, timeout 1000ms
sdio_cmd_cmplt: CMD 55, flgs 0x151, arg 0x0, blks 0, blksz 0, status SUCCESS (1)
sdio_issue_cmd: CMD 41, flgs 0x812, arg 0x40100000, blks 0, blksz 0, timeout 1000ms
sdio_cmd_cmplt: CMD 41, flgs 0x812, arg 0x40100000, blks 0, blksz 0, status SUCCESS (1)
sdio_issue_cmd: CMD 55, flgs 0x151, arg 0x0, blks 0, blksz 0, timeout 1000ms
sdio_cmd_cmplt: CMD 55, flgs 0x151, arg 0x0, blks 0, blksz 0, status SUCCESS (1)
sdio_issue_cmd: CMD 41, flgs 0x812, arg 0x40100000, blks 0, blksz 0, timeout 1000ms
sdio_cmd_cmplt: CMD 41, flgs 0x812, arg 0x40100000, blks 0, blksz 0, status SUCCESS (1)
sd_app_send_op_cond: retries 1, rsp0 0xc0ff8000
sdio_issue_cmd: CMD 2, flgs 0x72, arg 0x0, blks 0, blksz 0, timeout 1000ms
sdio_cmd_cmplt: CMD 2, flgs 0x72, arg 0x0, blks 0, blksz 0, status SUCCESS (1)
sdio_issue_cmd: CMD 3, flgs 0x152, arg 0x0, blks 0, blksz 0, timeout 1000ms
sdio_cmd_cmplt: CMD 3, flgs 0x152, arg 0x0, blks 0, blksz 0, status SUCCESS (1)
sdio_bus_mode: mode push pull
sdio_issue_cmd: CMD 9, flgs 0x74, arg 0xaaaa0000, blks 0, blksz 0, timeout 1000ms
sdio_cmd_cmplt: CMD 9, flgs 0x74, arg 0xaaaa0000, blks 0, blksz 0, status SUCCESS (1)
sdio_issue_cmd: CMD 7, flgs 0x154, arg 0xaaaa0000, blks 0, blksz 0, timeout 1000ms
sdio_cmd_cmplt: CMD 7, flgs 0x154, arg 0xaaaa0000, blks 0, blksz 0, status SUCCESS (1)
sdio_issue_cmd: CMD 55, flgs 0x152, arg 0xaaaa0000, blks 0, blksz 0, timeout 1000ms
sdio_cmd_cmplt: CMD 55, flgs 0x152, arg 0xaaaa0000, blks 0, blksz 0, status SUCCESS (1)
sdio_issue_cmd: CMD 51, flgs 0xb58, arg 0x0, blks 1, blksz 8, timeout 1000ms
sdio_cmd_cmplt: CMD 51, flgs 0xb58, arg 0x0, blks 1, blksz 8, status SUCCESS (1)
sdio_issue_cmd: CMD 55, flgs 0x152, arg 0xaaaa0000, blks 0, blksz 0, timeout 1000ms
sdio_cmd_cmplt: CMD 55, flgs 0x152, arg 0xaaaa0000, blks 0, blksz 0, status SUCCESS (1)
sdio_issue_cmd: CMD 13, flgs 0xb58, arg 0x0, blks 1, blksz 64, timeout 1000ms
sdio_cmd_cmplt: CMD 13, flgs 0xb58, arg 0x0, blks 1, blksz 64, status SUCCESS (1)
sdio_issue_cmd: CMD 6, flgs 0x358, arg 0xffffff, blks 1, blksz 64, timeout 1000ms
sdio_cmd_cmplt: CMD 6, flgs 0x358, arg 0xffffff, blks 1, blksz 64, status SUCCESS (1)
sdio_issue_cmd: CMD 6, flgs 0x358, arg 0x80fffff1, blks 1, blksz 64, timeout 1000ms
sdio_cmd_cmplt: CMD 6, flgs 0x358, arg 0x80fffff1, blks 1, blksz 64, status SUCCESS (1)
sdio_issue_cmd: CMD 55, flgs 0x152, arg 0xaaaa0000, blks 0, blksz 0, timeout 1000ms
sdio_cmd_cmplt: CMD 55, flgs 0x152, arg 0xaaaa0000, blks 0, blksz 0, status SUCCESS (1)
sdio_issue_cmd: CMD 6, flgs 0x954, arg 0x2, blks 0, blksz 0, timeout 1000ms
sdio_cmd_cmplt: CMD 6, flgs 0x954, arg 0x2, blks 0, blksz 0, status SUCCESS (1)
sdio_bus_width: width 4
sdio_timing: timing HS
sdio_clock: clk 50000000
sdio_issue_cmd: CMD 16, flgs 0x154, arg 0x200, blks 0, blksz 0, timeout 1000ms
sdio_cmd_cmplt: CMD 16, flgs 0x154, arg 0x200, blks 0, blksz 0, status SUCCESS (1)
SD CID:
MID 0x3, OID 0x5344, PNM SD64G
PRV 0x96, PSN 0x1996ba36, MDT 6-2021
SD CSD:
CSD_STRUCTURE 1, SPEC_VERS 0, CCC 0x5b5
TAAC 14, NSAC 0, TRAN_SPEED 50
C_SIZE 121811, C_SIZE_MULT 0
READ_BL_LEN 9, WRITE_BL_LEN 9
ERASE GRP_SIZE 0, GRP_MULT 0, SIZE 127
blksz 512, sectors 124735488, dtr 25000000
SD SW CAPS:
bus mode 0x3, cmd sys 0x1
drv type 0x1, curr limit 0x1
dtr 50000000
CFG: Timing HS, DTR 50000000, Bus Width 4 bit

sdio_issue_cmd: CMD 17, flgs 0x358, arg 0x0, blks 1, blksz 512, timeout 60000ms
sdio_cmd_cmplt: CMD 17, flgs 0x358, arg 0x0, blks 1, blksz 512, status SUCCESS (1)
sdio_issue_cmd: CMD 18, flgs 0x2000358, arg 0x0, blks 8, blksz 512, timeout 10000ms
sdio_cmd_cmplt: CMD 18, flgs 0x2000358, arg 0x0, blks 8, blksz 512, status SUCCESS (1)
Path=0 - bcm2711
target=0 lun=0 Direct-Access(0) - SDMMC: SD64G Rev: 9.6

Explanation of the QNX SD Initialization Log

The log shows how initiation is done on QNX by configuring the SDIO (Secure Digital Input Output) interface, sending specific commands to the SD card, interpreting responses, and adjusting settings based on the card’s capabilities. Below, we’ll walk through each step, explaining the logic and purpose behind the commands, configurations, and transitions observed in the log.

Initial SDIO Configuration

  1. Resetting the Card (CMD0)
sdio_issue_cmd: CMD 0, flgs 0x1, arg 0x0, blks 0, blksz 0, timeout 1000ms
sdio_cmd_cmplt: CMD 0, flgs 0x1, arg 0x0, blks 0, blksz 0, status SUCCESS

CMD0 (GO_IDLE_STATE):
Purpose: Resets the card and puts it into idle state.
Flags (flgs 0x1): Indicates a broadcast command without a response (broadcast to all cards).
Argument (arg 0x0): Not used; set to zero.
Response: No response expected for CMD0; the card resets itself.

2. Checking Voltage Range and Version (CMD8)

sdio_issue_cmd: CMD 8, flgs 0x152, arg 0x1aa, blks 0, blksz 0, timeout 1000ms
sdio_cmd_cmplt: CMD 8, flgs 0x152, arg 0x1aa, blks 0, blksz 0, status SUCCESS (1)

CMD8 (SEND_IF_COND):
Purpose: Checks if the card supports the supplied voltage range and is SD Version 2.0 or later.
Flags (flgs 0x152):
0x152 in binary is 0001 0101 0010. The flags likely indicate:
Command expects a response (R7).
No data transfer.
Argument (arg 0x1aa):
Voltage supplied (2.7–3.6V) indicated by 0x1 in bits [11:8].
Check pattern 0xAA in bits [7:0].
Response: The card echoes back the argument if it supports the voltage and is SD Version 2.0+.

3. Preparing for Application-Specific Command (CMD55)

sdio_issue_cmd: CMD 55, flgs 0x151, arg 0x0, blks 0, blksz 0, timeout 1000ms
sdio_cmd_cmplt: CMD 55, flgs 0x151, arg 0x0, blks 0, blksz 0, status SUCCESS (1)

CMD55 (APP_CMD):

  • Purpose: Indicates that the next command is an application-specific command (ACMD).
  • Flags (flgs 0x151): Similar to CMD8 but adjusted for CMD55.
  • Argument (arg 0x0): Typically set to zero during initialization.

4. Initiating Card Initialization (ACMD41)

sdio_issue_cmd: CMD 41, flgs 0x812, arg 0x0, blks 0, blksz 0, timeout 1000ms
sdio_cmd_cmplt: CMD 41, flgs 0x812, arg 0x0, blks 0, blksz 0, status SUCCESS (1)
sd_app_send_op_cond: retries 0, rsp0 0x40ff8000

ACMD41 (SD_SEND_OP_COND):

  • Purpose: Requests the card to initialize and reports its operating conditions.
  • Flags (flgs 0x812): Indicate that this is an application-specific command with a particular response type (R3).
  • Argument (arg 0x0): Initially zero to query the card's capabilities.
  • Response (rsp0 0x40ff8000):
  • Busy Bit (bit 31): 0, indicating the card is still initializing.
  • Voltage Window: Indicates supported voltages.
  • Card Capacity Status (CCS, bit 30): Not set yet.
qemu-system-aarch64     -M raspi4b       
-kernel uboot_rpi_4.bin
-append "startup-bcm2711-rpi4 -v -D pl011-3"
-dtb bcm2711-rpi-4-b.dtb
-serial stdio -serial null
-drive id=sd-card,if=none,format=raw,file=sd.img,bus=0
-trace "sd*" -trace file=trace_output.log
-usb -device usb-mouse -device usb-kbd
-device usb-net,netdev=net0
-monitor telnet::45454,server,nowait
-netdev user,id=net0,hostfwd=tcp::5555-:22 -display gtk

From qemu hw/sd.c

typedef enum {
sd_spi,
sd_bc, /* broadcast -- no response */
sd_bcr, /* broadcast with response */
sd_ac, /* addressed -- no data transfer */
sd_adtc, /* addressed with data transfer */
} sd_cmd_type_t;

typedef struct {
uint8_t cmd;
uint32_t arg;
uint8_t crc;
} SDRequest;


#define TYPE_SD_CARD "sd-card"
static const SDProto sd_proto_sd = {
.name = "SD",
.cmd = {
[0] = {0, sd_bc, "GO_IDLE_STATE", sd_cmd_GO_IDLE_STATE},
[1] = {0, sd_bc, "SEND_OP_COND", sd_cmd_SEND_OP_COND_MMC},
[2] = {0, sd_bcr, "ALL_SEND_CID", sd_cmd_ALL_SEND_CID},
[3] = {0, sd_bcr, "SEND_RELATIVE_ADDR", sd_cmd_SEND_RELATIVE_ADDR},
[4] = {0, sd_bc, "SEND_DSR", sd_cmd_unimplemented},
[5] = {9, sd_bc, "IO_SEND_OP_COND", sd_cmd_optional},
[6] = {10, sd_adtc, "SWITCH_FUNCTION", sd_cmd_SWITCH_FUNCTION},
[7] = {0, sd_ac, "(DE)SELECT_CARD", sd_cmd_DE_SELECT_CARD},
[8] = {0, sd_bcr, "SEND_IF_COND", sd_cmd_SEND_IF_COND},
[9] = {0, sd_ac, "SEND_CSD", sd_cmd_SEND_CSD},
[10] = {0, sd_ac, "SEND_CID", sd_cmd_SEND_CID},
[11] = {0, sd_ac, "VOLTAGE_SWITCH", sd_cmd_optional},
[12] = {0, sd_ac, "STOP_TRANSMISSION", sd_cmd_STOP_TRANSMISSION},
[13] = {0, sd_ac, "SEND_STATUS", sd_cmd_SEND_STATUS},
[15] = {0, sd_ac, "GO_INACTIVE_STATE", sd_cmd_GO_INACTIVE_STATE},
[16] = {2, sd_ac, "SET_BLOCKLEN", sd_cmd_SET_BLOCKLEN},
[17] = {2, sd_adtc, "READ_SINGLE_BLOCK", sd_cmd_READ_SINGLE_BLOCK},
[19] = {2, sd_adtc, "SEND_TUNING_BLOCK", sd_cmd_SEND_TUNING_BLOCK},
[20] = {2, sd_ac, "SPEED_CLASS_CONTROL", sd_cmd_optional},
[23] = {2, sd_ac, "SET_BLOCK_COUNT", sd_cmd_SET_BLOCK_COUNT},
[24] = {4, sd_adtc, "WRITE_SINGLE_BLOCK", sd_cmd_WRITE_SINGLE_BLOCK},
[27] = {4, sd_adtc, "PROGRAM_CSD", sd_cmd_PROGRAM_CSD},
[28] = {6, sd_ac, "SET_WRITE_PROT", sd_cmd_SET_WRITE_PROT},
[29] = {6, sd_ac, "CLR_WRITE_PROT", sd_cmd_CLR_WRITE_PROT},
[30] = {6, sd_adtc, "SEND_WRITE_PROT", sd_cmd_SEND_WRITE_PROT},
[32] = {5, sd_ac, "ERASE_WR_BLK_START", sd_cmd_ERASE_WR_BLK_START},
[33] = {5, sd_ac, "ERASE_WR_BLK_END", sd_cmd_ERASE_WR_BLK_END},
[34] = {10, sd_adtc, "READ_SEC_CMD", sd_cmd_optional},
[35] = {10, sd_adtc, "WRITE_SEC_CMD", sd_cmd_optional},
[36] = {10, sd_adtc, "SEND_PSI", sd_cmd_optional},
[37] = {10, sd_ac, "CONTROL_ASSD_SYSTEM", sd_cmd_optional},
[38] = {5, sd_ac, "ERASE", sd_cmd_ERASE},
[42] = {7, sd_adtc, "LOCK_UNLOCK", sd_cmd_LOCK_UNLOCK},
[43] = {1, sd_ac, "Q_MANAGEMENT", sd_cmd_optional},
[44] = {1, sd_ac, "Q_TASK_INFO_A", sd_cmd_optional},
[45] = {1, sd_ac, "Q_TASK_INFO_B", sd_cmd_optional},
[46] = {1, sd_adtc, "Q_RD_TASK", sd_cmd_optional},
[47] = {1, sd_adtc, "Q_WR_TASK", sd_cmd_optional},
[48] = {1, sd_adtc, "READ_EXTR_SINGLE", sd_cmd_optional},
[49] = {1, sd_adtc, "WRITE_EXTR_SINGLE", sd_cmd_optional},
[50] = {10, sd_adtc, "DIRECT_SECURE_READ", sd_cmd_optional},
[52] = {9, sd_bc, "IO_RW_DIRECT", sd_cmd_optional},
[53] = {9, sd_bc, "IO_RW_EXTENDED", sd_cmd_optional},
[55] = {8, sd_ac, "APP_CMD", sd_cmd_APP_CMD},
[56] = {8, sd_adtc, "GEN_CMD", sd_cmd_GEN_CMD},
[57] = {10, sd_adtc, "DIRECT_SECURE_WRITE", sd_cmd_optional},
[58] = {11, sd_adtc, "READ_EXTR_MULTI", sd_cmd_optional},
[59] = {11, sd_adtc, "WRITE_EXTR_MULTI", sd_cmd_optional},
},
.acmd = {
[1] = {8, sd_bc, "SEND_OP_COND", sd_cmd_SEND_OP_COND_MMC},
[6] = {8, sd_ac, "SET_BUS_WIDTH", sd_acmd_SET_BUS_WIDTH},
[13] = {8, sd_adtc, "SD_STATUS", sd_acmd_SD_STATUS},
[22] = {8, sd_adtc, "SEND_NUM_WR_BLOCKS", sd_acmd_SEND_NUM_WR_BLOCKS},
[23] = {8, sd_ac, "SET_WR_BLK_ERASE_COUNT", sd_acmd_SET_WR_BLK_ERASE_COUNT},
[41] = {8, sd_bcr, "SEND_OP_COND", sd_cmd_SEND_OP_COND},
[42] = {8, sd_ac, "SET_CLR_CARD_DETECT", sd_acmd_SET_CLR_CARD_DETECT},
[51] = {8, sd_adtc, "SEND_SCR", sd_acmd_SEND_SCR},
},
};

After some “hack around and find out” wirh QEMU I managed to get this far. It seems like the main problem was that the “sd-card” was not attatched to the correct sd-bus

qemu-system-aarch64      -M raspi4b        -kernel ifs-rpi4.bin      
-append "startup-bcm2711-rpi4 -v -D pl011-3" -cpu cortex-a72
-dtb bcm2711-rpi-4-b.dtb -serial null -serial stdio
-monitor telnet::45454,server,nowait
-drive id=sd-card,if=none,format=raw,file=sd.img
-m 2G -smp 4 -trace "sd*" -trace file=trace_output.log
-netdev user,id=genet0,hostfwd=tcp::5555-:22 -display gtk

Note that in the previous article we used, -sd sd.img

This is equivalent to,

 -drive id=sd-card,if=none,format=raw,file=sd.img
-device sd-card,drive=sd-card,bus=sd-bus

Running QNX in qemu,

devb-sdmmc-bcm2711 dos exe=all mem name=below1G sdio addr=0xfe340000,irq=158,bs=bmstr_base=0xc0000000,verbose=7 disk name=sd
# sdio_cd: insertion path 0, cd state 0x1
sdio_pwr: vdd 0.0 (0x0)
sdio_pwr: vdd 3.3 (0x200000)
sdio_clock: clk 400000
sdio_bus_width: width 1
sdio_timing: timing LS
sdio_bus_mode: mode open drain
sdio_signal_voltage: 3.3V
sdio_issue_cmd: CMD 0, flgs 0x1, arg 0x0, blks 0, blksz 0, timeout 1000ms
sdio_cmd_cmplt: CMD 0, flgs 0x1, arg 0x0, blks 0, blksz 0, status SUCCESS (1)
sdio_issue_cmd: CMD 8, flgs 0x152, arg 0x1aa, blks 0, blksz 0, timeout 1000ms
sdio_cmd_cmplt: CMD 8, flgs 0x152, arg 0x1aa, blks 0, blksz 0, status CMD TO ERR (5)
sdio_issue_cmd: CMD 55, flgs 0x151, arg 0x0, blks 0, blksz 0, timeout 1000ms
sdio_cmd_cmplt: CMD 55, flgs 0x151, arg 0x0, blks 0, blksz 0, status CMD TO ERR (5)
sd_app_send_op_cond: retries 0, rsp0 0x0
sdio_issue_cmd: CMD 0, flgs 0x1, arg 0x0, blks 0, blksz 0, timeout 1000ms
sdio_cmd_cmplt: CMD 0, flgs 0x1, arg 0x0, blks 0, blksz 0, status SUCCESS (1)
sdio_issue_cmd: CMD 1, flgs 0x12, arg 0x0, blks 0, blksz 0, timeout 1000ms
sdio_cmd_cmplt: CMD 1, flgs 0x12, arg 0x0, blks 0, blksz 0, status CMD TO ERR (5)
sdio_pwr: vdd 0.0 (0x0)
sdio_pwr: vdd 3.3 (0x200000)
sdio_clock: clk 300000
..
It will try lower clock sppeds, 300000, 200000 until we get
sdio_cd: Unsupported card inserted
xpt_configure: No sdmmc interfaces found

Useful u-boot info

U-Boot> printenv bootcmd
bootcmd=
U-Boot> saveenv

On actual hardware

U-Boot>  mmc info
Device: mmc@7e340000
Manufacturer ID: 3
OEM: 5344
Name: SD64G
Bus Speed: 50000000
Mode: SD High Speed (50MHz)
Rd Block Len: 512
SD version 3.0
High Capacity: Yes
Capacity: 59.4GiB
Bus Width: 4-bit
Erase Group Size: 512 Bytes

When running u-boot in qemu

qemu-system-aarch64      -M  raspi4b        
-kernel u-boot.bin
-append "startup-bcm2711-rpi4 -v -D pl011-3" -cpu cortex-a72
-dtb bcm2711-rpi-4-b.dtb
-serial stdio -serial null
-monitor telnet::45454,server,nowait
-drive id=sdcard,if=none,format=raw,file=sd.img
-m 2G -smp 4
-trace "sd*" -trace file=trace_output.log
-netdev user,id=bcm2838-genet,hostfwd=tcp::5555-:22 -display gtk

U-Boot> mmc info
Card did not respond to voltage select! : -110
U-Boot>

SD log
sdhci_send_command CMD00 ARG[0x00000000]
sdbus_command @sd-bus CMD00 arg 0x00000000
sdhci_access wr32: addr[0x000c] <- 0x00000000 (0)
sdhci_access rd32: addr[0x0030] -> 0x00000001 (1)
sdhci_access rd32: addr[0x0010] -> 0x00000000 (0)
sdhci_access wr32: addr[0x0030] <- 0x00000001 (1)
sdhci_access rd32: addr[0x0030] -> 0x00000000 (0)
sdhci_access wr32: addr[0x0030] <- 0xffffffff (4294967295)
sdbus_get_dat_lines @sd-bus dat_lines: 15
sdbus_get_cmd_line @sd-bus cmd_line: 1
sdhci_access rd32: addr[0x0024] -> 0x01ff0000 (33488896)
sdhci_access wr32: addr[0x0030] <- 0xffffffff (4294967295)
sdhci_access wr32: addr[0x0008] <- 0x00000000 (0)
sdhci_send_command CMD01 ARG[0x00000000]
sdbus_command @sd-bus CMD01 arg 0x00000000
sdhci_error timeout waiting for command response
sdhci_access wr32: addr[0x000c] <- 0x01020000 (16908288)
sdhci_access rd32: addr[0x0030] -> 0x00018001 (98305)
sdhci_access rd32: addr[0x0030] -> 0x00018001 (98305)
sdhci_access wr32: addr[0x0030] <- 0xffffffff (4294967295)
sdhci_access rd32: addr[0x002c] -> 0x00006bc7 (27591)
sdhci_access wr32: addr[0x002c] <- 0x02006bc7 (33582023)
sdhci_access rd32: addr[0x002c] -> 0x00006bc7 (27591)
sdhci_access rd32: addr[0x002c] -> 0x00006bc7 (27591)
sdhci_access wr32: addr[0x002c] <- 0x04006bc7 (67136455)
sdhci_access rd32: addr[0x002c] -> 0x00006bc7 (27591)

Extended Log from QNX,

slog2info

devb-sdmmc-bcm2711 dos exe=all mem name=below1G sdio addr=0xfe340000,irq=158,bs=bmstr_base=0xc0000000 disk name=sd

an 01 00:00:00.060          devb_sdmmc_bcm2711.12                 slog*  1800  devb-sdmmc-bcm2711 1.00A (Nov 30 2020 14:40:48)
Jan 01 00:00:00.061 devb_sdmmc_bcm2711.12 slog 0 libcam.so (Aug 2 2019 15:41:15) bver 606010d
Jan 01 00:00:00.063 devb_sdmmc_bcm2711.12 slog 1800 sdio_cd: insertion path 0, cd state 0x1
Jan 01 00:00:00.112 devb_sdmmc_bcm2711.12 slog 1800 SD CID:
Jan 01 00:00:00.112 devb_sdmmc_bcm2711.12 slog 1800 MID 0x3, OID 0x5344, PNM SD64G
Jan 01 00:00:00.112 devb_sdmmc_bcm2711.12 slog 1800 PRV 0x96, PSN 0x1996ba36, MDT 6-2021
Jan 01 00:00:00.112 devb_sdmmc_bcm2711.12 slog 1800 SD CSD:
Jan 01 00:00:00.112 devb_sdmmc_bcm2711.12 slog 1800 CSD_STRUCTURE 1, SPEC_VERS 0, CCC 0x5b5
Jan 01 00:00:00.112 devb_sdmmc_bcm2711.12 slog 1800 TAAC 14, NSAC 0, TRAN_SPEED 50
Jan 01 00:00:00.112 devb_sdmmc_bcm2711.12 slog 1800 C_SIZE 121811, C_SIZE_MULT 0
Jan 01 00:00:00.112 devb_sdmmc_bcm2711.12 slog 1800 READ_BL_LEN 9, WRITE_BL_LEN 9
Jan 01 00:00:00.112 devb_sdmmc_bcm2711.12 slog 1800 ERASE GRP_SIZE 0, GRP_MULT 0, SIZE 127
Jan 01 00:00:00.112 devb_sdmmc_bcm2711.12 slog 1800 blksz 512, sectors 124735488, dtr 25000000
Jan 01 00:00:00.112 devb_sdmmc_bcm2711.12 slog 1800 SD SW CAPS:
Jan 01 00:00:00.112 devb_sdmmc_bcm2711.12 slog 1800 bus mode 0x3, cmd sys 0x1
Jan 01 00:00:00.112 devb_sdmmc_bcm2711.12 slog 1800 drv type 0x1, curr limit 0x1
Jan 01 00:00:00.112 devb_sdmmc_bcm2711.12 slog 1800 dtr 50000000
Jan 01 00:00:00.112 devb_sdmmc_bcm2711.12 slog 1800 CFG: Timing HS, DTR 50000000, Bus Width 4 bit
Jan 01 00:00:00.112 devb_sdmmc_bcm2711.12 slog 100 cam-disk.so (Aug 2 2019 15:41:25)
Jan 01 00:00:00.396 devb_sdmmc_bcm2711.12 slog 1000 fs-qnx6: Allocation strategy 0
Jan 01 00:00:00.396 devb_sdmmc_bcm2711.12 slog 1000 fs-qnx6: Use btree directory 0
Jan 01 00:00:00.397 devb_sdmmc_bcm2711.12 slog 1000 fs-qnx6: trim (0,1048576,2) was requested, but is NOT usable

At some point while waiting in the debugger, U-boot initialised the SD card correctly. This indicate that it might be a timing issue, we got.

U-Boot>  mmc info
Device: mmc@7e340000
Manufacturer ID: aa
OEM: 5859
Name: QEMU!
Bus Speed: 50000000
Mode: SD High Speed (50MHz)
Rd Block Len: 512
SD version 3.0
High Capacity: No
Capacity: 2 GiB
Bus Width: 4-bit
Erase Group Size: 512 Bytes
U-Boot> ls mmc 0:1
52325 bcm2711-rpi-4-b.dtb
24971216 ifs-rpi4.bin
3746856 start4db.elf
5400 fixup4.dat
3170 fixup4cd.dat
2250656 start4.elf
16384 uboot.env
8386 fixup4x.dat
573 net-config.sh
569920 u-boot.bin
805084 start4cd.elf
8382 fixup4db.dat
172 config.txt
2998120 start4x.elf

13 file(s), 0 dir(s)

Hopefully I will get the time to fix this in my fork of qemu, but even better if it could be fixed in qemu itself.

--

--