I'm trying to establish communication with the WiFi module on an stm32mp157f-dk2 board.
I must be doing something wrong because I always get a timeout from SDMMC2.
I attempt to send 2 commands, the first is an SDIO reset and the second is taken from what linux does in an initialization sequence (I am not sure that part is right at all, but there should be some kind of error back, not timeout):
Here is the main function from my kernel, which is booted using U-Boot (hence the GPIO AFRs seem to already be set correctly):
void main() {
trace("in main\n");
RCC_MP_AHB4ENSETR |= RCC_MP_AHB4ENSETR_GPIOHEN_Msk;
mdelay(1);
trace("GPIOA:\n");
printi(GPIOA->AFR[0]); // 0xb0000bb0
printi(GPIOA->AFR[1]); // 0x00000000
printi(GPIOA->MODER); // 0xc7dfbfeb = 32b'11000111110111111011111111101011
trace("GPIOB:\n");
printi(GPIOB->AFR[0]); // 0x000998bb
printi(GPIOB->AFR[1]); // 0x9900b0b0
printi(GPIOB->MODER); // 0xafbb3eaa = 32b'10101111101110110011111010101010
trace("GPIOG:\n");
printi(GPIOG->AFR[0]); // 180027392 = 0x0abb0000
printi(GPIOG->AFR[1]); // 196108288 = 0x0bb06000
printi(GPIOG->MODER); // 3954699007 = 0xebb7eaff = 32b'11101011101101111110101011111111
trace("GPIOE:\n");
printi(GPIOE->AFR[0]); // 39680 = 0x00009b00
printi(GPIOE->AFR[1]); // 0 = 0x00000000
printi(GPIOE->MODER); // 4294967215 = 0xffffffaf = 32b'11111111111111111111111110101111
trace("GPIOH:\n");
printi(GPIOH->AFR[0]); // 0 =
printi(GPIOH->AFR[1]); // 0 =
printi(GPIOH->MODER); // 4294967295 = 0xffffffff = 32b'11111111111111111111111111111111
// = 0xfffffdff = 32b'11111111111111111111110111111111 (new, set below)
// PB4 -> SDMMC2_D3 (was)
// PB3 -> SDMMC2_D2 (was)
// PB15 -> SDMMC2_D1 (was)
// PB14 -> SDMMC2_D0 (was)
// PG6 -> SDMMC2_CMD (was)
// PE3 -> SDMMC2_CK (was)
// PH4 -> WL_REG_ON (GPIO, should be driven lo first, then hi to power up wireless)
// PD0 -> WL_HOST_WAKE (input from wireless, can be ignored for now)
GPIOH->ODR = 0;
GPIOH->MODER = 0xfffffdff;
RCC_MP_AHB6ENSETR |= RCC_MP_AHB6ENSETR_SDMMC2EN_Msk;
mdelay(1);
DLYB_SDMMC2->CR = 0;
mdelay(1);
{
uintptr_t clk = MCI_STM32_CLK_CLKDIV_MSK;
clk |= MCI_STM32_CLK_WIDEBUS_4;
clk |= MCI_STM32_CLK_HWFCEN;
SDMMC2->CLKCR = clk;
}
mdelay(1);
trace("mmci:\n");
printi(MMCIPOWER); // reads as 0
printi(MMCISTATUS); // reads as 0
printi(MMCIMASK0); // reads as 0
mdelay(1);
MMCIPOWER = 2; //MCI_PWR_CYC;
mdelay(1);
MMCIPOWER = 0;
mdelay(1);
MMCIPOWER = MCI_PWR_ON;
mdelay(1);
MMCIPOWER = 2; //MCI_PWR_CYC;
mdelay(1);
MMCIPOWER = MCI_PWR_ON;
mdelay(1);
{
uintptr_t clk = MCI_STM32_CLK_CLKDIV_MSK;
clk |= MCI_STM32_CLK_WIDEBUS_4;
clk |= MCI_STM32_CLK_HWFCEN;
MODIFY_REG(SDMMC2->CLKCR, CLKCR_CLEAR_MASK, clk);
}
mdelay(1);
printi(MMCIPOWER); // reads as 3
printi(MMCISTATUS); // reads as 0
printi(MMCIMASK0); // reads as 0
trace("action:\n");
GPIOH->ODR |= (1 << 4);
mdelay(1000);
trace("continue:\n");
{
SDMMC2->ARG = (SDIO_CCCR_ABORT << 9);
MODIFY_REG(SDMMC2->CMD, CMD_CLEAR_MASK, SDMMC_CMD_SDMMC_RW_DIRECT|SDMMC_RESPONSE_SHORT|SDMMC_CPSM_ENABLE);
printi(MMCISTATUS); // 8192
printi(SDMMC_GetCmdResp1(SDMMC2, SDMMC_CMD_SDMMC_RW_DIRECT, 1)); // 4
}
mdelay(1000);
{
/*
* [31] R/W flag
* [30:28] Function number
* [27] RAW flag
* [25:9] Register address
* [7:0] Data
*/
SDMMC2->ARG = 0x80022040; // readwrite=W + function=0 + rawflag=0 + address=0x110 + data=0x40
MODIFY_REG(SDMMC2->CMD, CMD_CLEAR_MASK, SDMMC_CMD_SDMMC_RW_DIRECT|SDMMC_RESPONSE_SHORT|SDMMC_CPSM_ENABLE);
printi(MMCISTATUS); // 8192
printi(SDMMC_GetCmdResp1(SDMMC2, SDMMC_CMD_SDMMC_RW_DIRECT, 1)); // 4
}
trace("done!\n");
while (1);
}