SDIO
The gamepad includes a SDIO host controller to access the BCM4319 wifi card.
Registers
The SDIO host controller registers are at 0xE0010000. They occupy a 256-byte block which is mirrored across the entire 0xE0010000-0xE001FFFF range.
Address | Desc. |
---|---|
0xE0010000 | SD_SysAddr |
0xE0010004 | SD_BlockSize |
0xE0010006 | SD_BlockCount |
0xE0010008 | SD_Arg0 |
0xE001000A | SD_Arg1 |
0xE001000C | SD_TransferMode |
0xE001000E | SD_Command |
0xE0010010 | SD_Response0 |
0xE0010012 | SD_Response1 |
0xE0010014 | SD_Response2 |
0xE0010016 | SD_Response3 |
0xE0010018 | SD_Response4 |
0xE001001A | SD_Response5 |
0xE001001C | SD_Response6 |
0xE001001E | SD_Response7 |
0xE0010020 | SD_BufferDataPort0 |
0xE0010022 | SD_BufferDataPort1 |
0xE0010024 | SD_PresentState |
0xE0010028 | SD_HostCntrl |
0xE0010029 | SD_PwrCntrl |
0xE001002A | SD_BlockGapCntrl |
0xE001002B | SD_WakeupCntrl |
0xE001002C | SD_ClockCntrl |
0xE001002E | SD_TimeoutCntrl |
0xE001002F | SD_SoftwareReset |
0xE0010030 | SD_IntrStatus |
0xE0010032 | SD_ErrorIntrStatus |
0xE0010034 | SD_IntrStatusEnable |
0xE0010036 | SD_ErrorIntrStatusEnable |
0xE0010038 | SD_IntrSignalEnable |
0xE001003A | SD_ErrorIntrSignalEnable |
0xE001003C | SD_CMD12ErrorStatus |
0xE0010040 | SD_Capabilities |
0xE0010044 | SD_Capabilities3 |
0xE0010048 | SD_MaxCurCap |
0xE001004C | SD_MaxCurCap_Reserved |
0xE0010054 | SD_ADMA_ErrStatus |
0xE0010058 | SD_ADMA_SysAddr |
0xE00100FC | SD_SlotInterruptStatus |
0xE00100FE | SD_HostControllerVersion |
There is also a register at 0xF0004800 that seems to control something related to the SDIO controller. The reset value for that register is 3, any other value breaks SDIO functionality. Not known yet how this works in detail.
This SDIO host controller seems to be mostly standards compliant. Documentation: https://kuribo64.net/get.php?id=XwfZ1HYFrc4T2uAv
When setting the block size for a CMD53 transfer, the stock firmware sets bit 12-14 in SD_BlockSize to 7. The open-source BCM43xx drivers do not do this. These bits are the SDMA buffer boundary: a DMA transfer stops when crossing the specified boundary (here configured to 512K). Writing a new address to SD_SysAddr will resume the DMA transfer. If not using fancy memory tricks, one can just write the current SD_SysAddr value back to continue the transfer where it stopped.
Register SD_Capabilities reads as 0x69EF30B0. (TODO: document some of the other fixed registers)