in lib/cmsis/CMSIS/Pack/Example/CMSIS_Driver/MCI_LPC18xx.c [694:827]
static int32_t Control (uint32_t control, uint32_t arg) {
uint32_t div, bps, pclk;
if (!(MCI.flags & MCI_POWER)) { return ARM_DRIVER_ERROR; }
switch (control) {
case ARM_MCI_BUS_SPEED:
/* Get peripheral clock and calculate clock divider */
pclk = GetClockFreq (SDIO_CLK_SEL_PLL1);
bps = arg;
LPC_SDMMC->CLKENA &= ~SDMMC_CLKENA_CCLK_ENABLE;
if (bps) {
/* bps = pclk / (2 * div) */
div = (pclk + bps - 1) / bps;
if (div & 1) { div += 1; }
bps = pclk / div;
LPC_SDMMC->CLKSRC = SDMMC_CLKSRC_CLK_SOURCE (0);
LPC_SDMMC->CLKDIV = SDMMC_CLKDIV_CLK_DIVIDER0 (div >> 1);
LPC_SDMMC->CLKENA |= SDMMC_CLKENA_CCLK_ENABLE |
SDMMC_CLKENA_CCLK_LOW_POWER;
}
/* Send "update clock registers" command and wait until finished */
LPC_SDMMC->CMD = SDMMC_CMD_UPDATE_CLOCK_REGISTERS_ONLY |
SDMMC_CMD_WAIT_PRVDATA_COMPLETE |
SDMMC_CMD_START_CMD ;
while (LPC_SDMMC->CMD & SDMMC_CMD_START_CMD);
/* Bus speed configured */
MCI.flags |= MCI_SETUP;
return (bps);
case ARM_MCI_BUS_SPEED_MODE:
if (arg == ARM_MCI_BUS_DEFAULT_SPEED) {
/* Speed mode up to 25/26MHz */
return ARM_DRIVER_OK;
}
return ARM_DRIVER_ERROR_UNSUPPORTED;
case ARM_MCI_BUS_CMD_MODE:
/* Implement external pull-up control to support MMC cards in open-drain mode */
/* Default mode is push-pull and is configured in Driver_MCI0.Initialize() */
if (arg == ARM_MCI_BUS_CMD_PUSH_PULL) {
/* Configure external circuit to work in push-pull mode */
}
else if (arg == ARM_MCI_BUS_CMD_OPEN_DRAIN) {
/* Configure external circuit to work in open-drain mode */
}
else {
return ARM_DRIVER_ERROR_UNSUPPORTED;
}
break;
case ARM_MCI_BUS_DATA_WIDTH:
LPC_SDMMC->CTYPE &= ~(SDMMC_CTYPE_CARD_WIDTH0 | SDMMC_CTYPE_CARD_WIDTH1);
switch (arg) {
case ARM_MCI_BUS_DATA_WIDTH_1:
break;
case ARM_MCI_BUS_DATA_WIDTH_4:
LPC_SDMMC->CTYPE |= SDMMC_CTYPE_CARD_WIDTH0;
break;
case ARM_MCI_BUS_DATA_WIDTH_8:
LPC_SDMMC->CTYPE |= SDMMC_CTYPE_CARD_WIDTH1;
break;
default:
return ARM_DRIVER_ERROR_UNSUPPORTED;
}
break;
#if (RTE_SD_RST_PIN_EN)
case ARM_MCI_CONTROL_RESET:
if (arg) {
/* Assert RST_n pin */
LPC_SDMMC->RST_N = 0;
}
else {
/* Deassert RST_n pin */
LPC_SDMMC->RST_N = 1;
}
break;
#endif
case ARM_MCI_CONTROL_CLOCK_IDLE:
if (arg) {
/* Clock generation enabled when idle */
LPC_SDMMC->CLKENA &= ~SDMMC_CLKENA_CCLK_LOW_POWER;
}
else {
/* Clock generation disabled when idle */
LPC_SDMMC->CLKENA |= SDMMC_CLKENA_CCLK_LOW_POWER;
}
/* Send "update clock registers" command and wait until finished */
LPC_SDMMC->CMD = SDMMC_CMD_UPDATE_CLOCK_REGISTERS_ONLY |
SDMMC_CMD_WAIT_PRVDATA_COMPLETE |
SDMMC_CMD_START_CMD ;
while (LPC_SDMMC->CMD & SDMMC_CMD_START_CMD);
break;
case ARM_MCI_DATA_TIMEOUT:
arg <<= 8;
arg |= LPC_SDMMC->TMOUT & 0xFF;
LPC_SDMMC->TMOUT = arg;
break;
case ARM_MCI_MONITOR_SDIO_INTERRUPT:
MCI.status.sdio_interrupt = 0;
LPC_SDMMC->INTMASK |= SDMMC_INTMASK_SDIO_INT_MASK;
break;
case ARM_MCI_CONTROL_READ_WAIT:
if (arg) {
/* Assert read wait */
LPC_SDMMC->CTRL |= SDMMC_CTRL_READ_WAIT;
}
else {
/* Clear read wait */
LPC_SDMMC->CTRL &= ~SDMMC_CTRL_READ_WAIT;
}
break;
case ARM_MCI_DRIVER_STRENGTH:
default: return ARM_DRIVER_ERROR_UNSUPPORTED;
}
return ARM_DRIVER_OK;
}