static int32_t Control()

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;
}