I'm afraid my question could be board- or SoC-specific. Anyway, I hope someone has experience in it.
SoC: RK3308 (board: ROCK Pi S). I read from SD card in bare-metal environment: AArch64 EL3, DDR initialized, MMU/GIC disabled.
Reading a block from SD card. I assumed, that BootROM will do all initialization for me and SD card will be ready for use when my code gains control. It is. I can successfully read from the card - FIFO gets filled. My question is the following:
RK3308 Technical Reference Manual Part 2, Chapter 3 describes the Mobile Storage Host Controller.
SDMMC_PWREN Power-enable register
Bit [0]: power_enable. Power on/off switch for the card. Once power is turned on, firmware should wait for regulator/switch ramp-up time before trying to initialize card.
1'b0: power off 1'b1: power on
Bit values output to card_power_en port
Also,
SDMMC_CMD Command register
Bit [15] send_initialization
1'b0: do not send initialization sequence (80 clocks of 1) before sending this command
1'b1: send initialization sequence before sending this command After power on, 80 clocks must be sent to card for initialization before sending any commands to card. Bit should be set while sending first command to card so that controller will initialize clocks before sending command to card. This bit should not be set for either of the boot modes (alternate or mandatory)
The problem is when my code gains control from the BootROM code, SDMMC_PWREN[0] = 0
(power off). But reads from the card are successful. I tried setting SDMMC_PWREN[0] = 1
, I also tried setting SDMMC_CMD[15] = 1
for the 80-clocks initialization sequence before the first command after power up. This all doesn't seem to have any effect. In all cases read from the card (CMD17) is successful. However, CMD0/CMD8 sequence fails with response timed out
error if I try to issue these commands after setting power_enable=1
.
Register values when my code gains control:
SDMMC_CTRL 0x00000000
SDMMC_PWREN 0x00000000
SDMMC_CLKDIV 0x00000000
SDMMC_CLKSRC 0x00000000
SDMMC_CLKENA 0x00000001
SDMMC_TMOUT 0xFFFFFF40
SDMMC_CTYPE 0x00000001
SDMMC_BLKSIZ 0x00000200
SDMMC_BYTCNT 0x00000200
SDMMC_INTMASK 0x00000000
SDMMC_CMDARG 0x00001040
SDMMC_CMD 0x20002351
SDMMC_RESP0 0x00000000
SDMMC_RESP1 0x2023BC16
SDMMC_RESP2 0x53443030
SDMMC_RESP3 0x9C534F55
SDMMC_MINTSTS 0x00000000
SDMMC_RINTSTS 0x0000000C
SDMMC_STATUS 0x03000101
SDMMC_FIFOTH 0x307F0080
SDMMC_CDETECT 0x00000000
SDMMC_WRTPRT 0x00000000
SDMMC_TCBCNT 0x00000000
SDMMC_TBBCNT 0x00000000
SDMMC_DEBNCE 0x00FFFFFF
SDMMC_HCON 0x04C434C1
SDMMC_UHS_REG 0x00000000
SDMMC_RSTN 0x00000001
I do not understand the actual purpose of SDMMC_PWREN
register and how/when to use it. Any details will be highly appreciated.
My test code is very simple:
. . .
.probe_device:
str x30, [sp, -16]!
bl .serial__send_string
ldr w11, [x2, SDMMC_CDETECT]
tbnz w11, 0, .device_absent
adr x0, .msg__present
bl .serial__send_string
ldr w10, [x2, SDMMC_CMD] ; BootROM leaves SDMMC_CMD register
orr w10, w10, 1 shl 31 ; pre-filled for CMD17, so I just
str wzr, [x2, SDMMC_CMDARG] ; change block address to 0
str w10, [x2, SDMMC_CMD] ; to read from the first block
ldr w11, [x2, SDMMC_RINTSTS]
tbz w11, 2, $ - 4 ; wait until command completed
. . .
User contributions licensed under CC BY-SA 3.0