/* * Copyright (c) 2016, Freescale Semiconductor, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * o Redistributions of source code must retain the above copyright notice, this list * of conditions and the following disclaimer. * * o Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * o Neither the name of Freescale Semiconductor, Inc. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _FSL_SDIF_H_ #define _FSL_SDIF_H_ #include "fsl_common.h" /*! * @addtogroup sdif * @{ */ /****************************************************************************** * Definitions. *****************************************************************************/ /*! @name Driver version */ /*@{*/ /*! @brief Driver version 2.0.0. */ #define FSL_SDIF_DRIVER_VERSION (MAKE_VERSION(2U, 0U, 0U)) /*@}*/ #define SDIF_DriverIRQHandler SDIO_DriverIRQHandler /*!< convert the name here, due to RM use SDIO */ #define SDIF_SUPPORT_SD_VERSION (0x20) /*!< define the controller support sd/sdio card version 2.0 */ #define SDIF_SUPPORT_MMC_VERSION (0x44) /*!< define the controller support mmc card version 4.4 */ #define SDIF_TIMEOUT_VALUE (65535U) /*!< define the timeout counter */ #define SDIF_POLL_DEMAND_VALUE (0xFFU) /*!< this value can be any value */ #define SDIF_DMA_DESCRIPTOR_BUFFER1_SIZE(x) (x & 0x1FFFU) /*!< DMA descriptor buffer1 size */ #define SDIF_DMA_DESCRIPTOR_BUFFER2_SIZE(x) ((x & 0x1FFFU) << 13U) /*!STATUS & SDIF_STATUS_DATA_3_STATUS_MASK; } else { return base->CDETECT & SDIF_CDETECT_CARD_DETECT_MASK; } } /*! * @brief SDIF module enable/disable card clock. * @param base SDIF peripheral base address. * @param enable/disable flag */ static inline void SDIF_EnableCardClock(SDIF_Type *base, bool enable) { if (enable) { base->CLKENA |= SDIF_CLKENA_CCLK_ENABLE_MASK; } else { base->CLKENA &= ~SDIF_CLKENA_CCLK_ENABLE_MASK; } } /*! * @brief SDIF module enable/disable module disable the card clock * to enter low power mode when card is idle,for SDIF cards, if * interrupts must be detected, clock should not be stopped * @param base SDIF peripheral base address. * @param enable/disable flag */ static inline void SDIF_EnableLowPowerMode(SDIF_Type *base, bool enable) { if (enable) { base->CLKENA |= SDIF_CLKENA_CCLK_LOW_POWER_MASK; } else { base->CLKENA &= ~SDIF_CLKENA_CCLK_LOW_POWER_MASK; } } /*! * @brief Sets the card bus clock frequency. * * @param base SDIF peripheral base address. * @param srcClock_Hz SDIF source clock frequency united in Hz. * @param target_HZ card bus clock frequency united in Hz. * @return The nearest frequency of busClock_Hz configured to SD bus. */ uint32_t SDIF_SetCardClock(SDIF_Type *base, uint32_t srcClock_Hz, uint32_t target_HZ); /*! * @brief reset the different block of the interface. * @param base SDIF peripheral base address. * @param mask indicate which block to reset. * @param timeout value,set to wait the bit self clear * @return reset result. */ bool SDIF_Reset(SDIF_Type *base, uint32_t mask, uint32_t timeout); /*! * @brief enable/disable the card power. * once turn power on, software should wait for regulator/switch * ramp-up time before trying to initialize card. * @param base SDIF peripheral base address. * @param enable/disable flag. */ static inline void SDIF_EnableCardPower(SDIF_Type *base, bool enable) { if (enable) { base->PWREN |= SDIF_PWREN_POWER_ENABLE_MASK; } else { base->PWREN &= ~SDIF_PWREN_POWER_ENABLE_MASK; } } /*! * @brief get the card write protect status * @param base SDIF peripheral base address. */ static inline uint32_t SDIF_GetCardWriteProtect(SDIF_Type *base) { return base->WRTPRT & SDIF_WRTPRT_WRITE_PROTECT_MASK; } /*! * @brief set card data bus width * @param base SDIF peripheral base address. * @param data bus width type */ static inline void SDIF_SetCardBusWidth(SDIF_Type *base, sdif_bus_width_t type) { base->CTYPE = type; } /*! * @brief toggle state on hardware reset PIN * This is used which card has a reset PIN typically. * @param base SDIF peripheral base address. */ static inline void SDIF_AssertHardwareReset(SDIF_Type *base) { base->RST_N &= ~SDIF_RST_N_CARD_RESET_MASK; } /*! * @brief send command to the card * @param base SDIF peripheral base address. * @param command configuration collection * @param timeout value * @return command excute status */ status_t SDIF_SendCommand(SDIF_Type *base, sdif_command_t *cmd, uint32_t timeout); /*! * @brief SDIF enable/disable global interrupt * @param base SDIF peripheral base address. * @param enable/disable flag */ static inline void SDIF_EnableGlobalInterrupt(SDIF_Type *base, bool enable) { if (enable) { base->CTRL |= SDIF_CTRL_INT_ENABLE_MASK; } else { base->CTRL &= ~SDIF_CTRL_INT_ENABLE_MASK; } } /*! * @brief SDIF enable interrupt * @param base SDIF peripheral base address. * @param interrupt mask */ static inline void SDIF_EnableInterrupt(SDIF_Type *base, uint32_t mask) { base->INTMASK |= mask; } /*! * @brief SDIF disable interrupt * @param base SDIF peripheral base address. * @param interrupt mask */ static inline void SDIF_DisableInterrupt(SDIF_Type *base, uint32_t mask) { base->INTMASK &= ~mask; } /*! * @brief SDIF get interrupt status * @param base SDIF peripheral base address. */ static inline uint32_t SDIF_GetInterruptStatus(SDIF_Type *base) { return base->MINTSTS; } /*! * @brief SDIF clear interrupt status * @param base SDIF peripheral base address. * @param status mask to clear */ static inline void SDIF_ClearInterruptStatus(SDIF_Type *base, uint32_t mask) { base->RINTSTS &= mask; } /*! * @brief Creates the SDIF handle. * register call back function for interrupt and enable the interrupt * @param base SDIF peripheral base address. * @param handle SDIF handle pointer. * @param callback Structure pointer to contain all callback functions. * @param userData Callback function parameter. */ void SDIF_TransferCreateHandle(SDIF_Type *base, sdif_handle_t *handle, sdif_transfer_callback_t *callback, void *userData); /*! * @brief SDIF enable DMA interrupt * @param base SDIF peripheral base address. * @param interrupt mask to set */ static inline void SDIF_EnableDmaInterrupt(SDIF_Type *base, uint32_t mask) { base->IDINTEN |= mask; } /*! * @brief SDIF disable DMA interrupt * @param base SDIF peripheral base address. * @param interrupt mask to clear */ static inline void SDIF_DisableDmaInterrupt(SDIF_Type *base, uint32_t mask) { base->IDINTEN &= ~mask; } /*! * @brief SDIF get internal DMA status * @param base SDIF peripheral base address. * @return the internal DMA status register */ static inline uint32_t SDIF_GetInternalDMAStatus(SDIF_Type *base) { return base->IDSTS; } /*! * @brief SDIF clear internal DMA status * @param base SDIF peripheral base address. * @param status mask to clear */ static inline void SDIF_ClearInternalDMAStatus(SDIF_Type *base, uint32_t mask) { base->IDSTS &= mask; } /*! * @brief SDIF internal DMA config function * @param base SDIF peripheral base address. * @param internal DMA configuration collection * @param data buffer pointer * @param data buffer size */ status_t SDIF_InternalDMAConfig(SDIF_Type *base, sdif_dma_config_t *config, const uint32_t *data, uint32_t dataSize); /*! * @brief SDIF send read wait to SDIF card function * @param base SDIF peripheral base address. */ static inline void SDIF_SendReadWait(SDIF_Type *base) { base->CTRL |= SDIF_CTRL_READ_WAIT_MASK; } /*! * @brief SDIF abort the read data when SDIF card is in suspend state * Once assert this bit,data state machine will be reset which is waiting for the * next blocking data,used in SDIO card suspend sequence,should call after suspend * cmd send * @param base SDIF peripheral base address. * @param timeout value to wait this bit self clear which indicate the data machine * reset to idle */ bool SDIF_AbortReadData(SDIF_Type *base, uint32_t timeout); /*! * @brief SDIF enable/disable CE-ATA card interrupt * this bit should set together with the card register * @param base SDIF peripheral base address. * @param enable/disable flag */ static inline void SDIF_EnableCEATAInterrupt(SDIF_Type *base, bool enable) { if (enable) { base->CTRL |= SDIF_CTRL_CEATA_DEVICE_INTERRUPT_STATUS_MASK; } else { base->CTRL &= ~SDIF_CTRL_CEATA_DEVICE_INTERRUPT_STATUS_MASK; } } /*! * @brief SDIF transfer function data/cmd in a non-blocking way * this API should be use in interrupt mode, when use this API user * must call SDIF_TransferCreateHandle first, all status check through * interrupt * @param base SDIF peripheral base address. * @param sdif handle * @param DMA config structure * This parameter can be config as: * 1. NULL In this condition, polling transfer mode is selected 2. avaliable DMA config In this condition, DMA transfer mode is selected * @param sdif transfer configuration collection */ status_t SDIF_TransferNonBlocking(SDIF_Type *base, sdif_handle_t *handle, sdif_dma_config_t *dmaConfig, sdif_transfer_t *transfer); /*! * @brief SDIF transfer function data/cmd in a blocking way * @param base SDIF peripheral base address. * @param DMA config structure * 1. NULL * In this condition, polling transfer mode is selected * 2. avaliable DMA config * In this condition, DMA transfer mode is selected * @param sdif transfer configuration collection */ status_t SDIF_TransferBlocking(SDIF_Type *base, sdif_dma_config_t *dmaConfig, sdif_transfer_t *transfer); /*! * @brief SDIF release the DMA descriptor to DMA engine * this function should be called when DMA descriptor unavailable status occurs * @param base SDIF peripheral base address. * @param sdif DMA config pointer */ status_t SDIF_ReleaseDMADescriptor(SDIF_Type *base, sdif_dma_config_t *dmaConfig); /*! * @brief SDIF return the controller capability * @param base SDIF peripheral base address. * @param sdif capability pointer */ void SDIF_GetCapability(SDIF_Type *base, sdif_capability_t *capability); /*! * @brief SDIF return the controller status * @param base SDIF peripheral base address. */ static inline uint32_t SDIF_GetControllerStatus(SDIF_Type *base) { return base->STATUS; } /*! * @brief SDIF send command complete signal disable to CE-ATA card * @param base SDIF peripheral base address. * @param send auto stop flag */ static inline void SDIF_SendCCSD(SDIF_Type *base, bool withAutoStop) { if (withAutoStop) { base->CTRL |= SDIF_CTRL_SEND_CCSD_MASK | SDIF_CTRL_SEND_AUTO_STOP_CCSD_MASK; } else { base->CTRL |= SDIF_CTRL_SEND_CCSD_MASK; } } /*! * @brief SDIF config the clock delay * This function is used to config the cclk_in delay to * sample and drvive the data ,should meet the min setup * time and hold time, and user need to config this paramter * according to your board setting * @param target freq work mode * @param clock divider which is used to decide if use pharse shift for delay */ void SDIF_ConfigClockDelay(uint32_t target_HZ, uint32_t divider); /* @} */ #if defined(__cplusplus) } #endif /*! @} */ #endif /* _FSL_sdif_H_*/