]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/CORTEX_M7_SAMV71_Xplained_IAR_Keil/libchip_samv7/source/hsmci.c
Final V8.2.1 release ready for tagging:
[freertos] / FreeRTOS / Demo / CORTEX_M7_SAMV71_Xplained_IAR_Keil / libchip_samv7 / source / hsmci.c
diff --git a/FreeRTOS/Demo/CORTEX_M7_SAMV71_Xplained_IAR_Keil/libchip_samv7/source/hsmci.c b/FreeRTOS/Demo/CORTEX_M7_SAMV71_Xplained_IAR_Keil/libchip_samv7/source/hsmci.c
new file mode 100644 (file)
index 0000000..d5e0644
--- /dev/null
@@ -0,0 +1,585 @@
+/* ----------------------------------------------------------------------------\r
+ *         SAM Software Package License \r
+ * ----------------------------------------------------------------------------\r
+ * Copyright (c) 2011, Atmel Corporation\r
+ *\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above copyright notice,\r
+ * this list of conditions and the disclaimer below.\r
+ *\r
+ * Atmel's name may not be used to endorse or promote products derived from\r
+ * this software without specific prior written permission.\r
+ *\r
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR\r
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ * ----------------------------------------------------------------------------\r
+ */\r
+\r
+/** \file\r
+ *\r
+ * Implementation of High Speed MultiMedia Card Interface (HSMCI) controller.\r
+ */\r
+\r
+/*---------------------------------------------------------------------------\r
+ *         Headers\r
+ *---------------------------------------------------------------------------*/\r
+\r
+#include "chip.h"\r
+#include <assert.h>\r
+\r
+/*---------------------------------------------------------------------------\r
+ *         Exported functions\r
+ *---------------------------------------------------------------------------*/\r
+\r
+/** \addtogroup hsmci_functions\r
+ *@{\r
+ */\r
+\r
+/**\r
+ * \brief Enable Multi-Media Interface\r
+ *\r
+ * \param pRMci Pointer to a Hsmci instance\r
+ */\r
+extern void HSMCI_Enable(Hsmci* pRMci)\r
+{\r
+    pRMci->HSMCI_CR = HSMCI_CR_MCIEN;\r
+}\r
+\r
+/**\r
+ * \brief Disable Multi-Media Interface\r
+ *\r
+ * \param pRMci Pointer to a Hsmci instance\r
+ */\r
+extern void HSMCI_Disable(Hsmci* pRMci)\r
+{\r
+    pRMci->HSMCI_CR = HSMCI_CR_MCIDIS;\r
+}\r
+\r
+/**\r
+ * \brief Reset (& Disable) Multi-Media Interface\r
+ *\r
+ * \param mci Pointer to a Hsmci instance\r
+ * \param bBackup Backup registers values to keep previous settings, including\r
+ *                _MR, _SDCR, _DTOR, _CSTOR, _DMA and _CFG.\r
+ */\r
+extern void HSMCI_Reset(Hsmci* pRMci, uint8_t bBackup)\r
+{\r
+    if (bBackup)\r
+    {\r
+        uint32_t mr    = pRMci->HSMCI_MR;\r
+        uint32_t dtor  = pRMci->HSMCI_DTOR;\r
+        uint32_t sdcr  = pRMci->HSMCI_SDCR;\r
+        uint32_t cstor = pRMci->HSMCI_CSTOR;\r
+        uint32_t dma   = pRMci->HSMCI_DMA;\r
+        uint32_t cfg   = pRMci->HSMCI_CFG;\r
+\r
+        pRMci->HSMCI_CR = HSMCI_CR_SWRST;\r
+\r
+        pRMci->HSMCI_MR    = mr;\r
+        pRMci->HSMCI_DTOR  = dtor;\r
+        pRMci->HSMCI_SDCR  = sdcr;\r
+        pRMci->HSMCI_CSTOR = cstor;\r
+        pRMci->HSMCI_DMA   = dma;\r
+        pRMci->HSMCI_CFG   = cfg;\r
+    }\r
+    else\r
+    {\r
+        pRMci->HSMCI_CR = HSMCI_CR_SWRST;\r
+    }\r
+}\r
+\r
+/**\r
+ * \brief Select slot\r
+ * \param pRMci Pointer to a Hsmci instance\r
+ * \param bSlot Slot ID (0~3 for A~D).\r
+ */\r
+extern void HSMCI_Select(Hsmci *pRMci, uint8_t bSlot, uint8_t bBusWidth)\r
+{\r
+    uint32_t dwSdcr;\r
+    dwSdcr = (HSMCI_SDCR_SDCSEL_Msk & bSlot);\r
+    switch(bBusWidth)\r
+    {\r
+        case 1:\r
+            pRMci->HSMCI_SDCR = dwSdcr | HSMCI_SDCR_SDCBUS_1;\r
+            break;\r
+        case 4:\r
+            pRMci->HSMCI_SDCR = dwSdcr | HSMCI_SDCR_SDCBUS_4;\r
+            break;\r
+        case 8:\r
+            pRMci->HSMCI_SDCR = dwSdcr | HSMCI_SDCR_SDCBUS_8;\r
+            break;\r
+    }\r
+}\r
+\r
+/**\r
+ * \brief Set slot\r
+ * \param pRMci Pointer to a Hsmci instance\r
+ * \param bSlot Slot ID (0~3 for A~D).\r
+ */\r
+extern void HSMCI_SetSlot(Hsmci *pRMci, uint8_t bSlot)\r
+{\r
+    uint32_t dwSdcr = pRMci->HSMCI_SDCR & ~HSMCI_SDCR_SDCSEL_Msk;\r
+    pRMci->HSMCI_SDCR = dwSdcr | (HSMCI_SDCR_SDCSEL_Msk & bSlot);\r
+}\r
+\r
+/**\r
+ * \brief Set bus width of MCI\r
+ * \param pRMci Pointer to a Hsmci instance\r
+ * \param bBusWidth 1,4 or 8 (bits).\r
+ */\r
+extern void HSMCI_SetBusWidth(Hsmci * pRMci,uint8_t bBusWidth)\r
+{\r
+    uint32_t dwSdcr = pRMci->HSMCI_SDCR & ~HSMCI_SDCR_SDCBUS_Msk;\r
+    switch(bBusWidth)\r
+    {\r
+        case 1:\r
+            pRMci->HSMCI_SDCR = dwSdcr | HSMCI_SDCR_SDCBUS_1;\r
+            break;\r
+        case 4:\r
+            pRMci->HSMCI_SDCR = dwSdcr | HSMCI_SDCR_SDCBUS_4;\r
+            break;\r
+        case 8:\r
+            pRMci->HSMCI_SDCR = dwSdcr | HSMCI_SDCR_SDCBUS_8;\r
+            break;\r
+    }\r
+}\r
+\r
+/**\r
+ * \brief Return bus width setting.\r
+ *\r
+ * \param pRMci  Pointer to an MCI instance.\r
+ * \return 1, 4 or 8.\r
+ */\r
+extern uint8_t HSMCI_GetBusWidth(Hsmci * pRMci)\r
+{\r
+    switch(pRMci->HSMCI_SDCR & HSMCI_SDCR_SDCBUS_Msk)\r
+    {\r
+        case HSMCI_SDCR_SDCBUS_1: return 1;\r
+        case HSMCI_SDCR_SDCBUS_4: return 4;\r
+        case HSMCI_SDCR_SDCBUS_8: return 8;\r
+    }\r
+    return 0;\r
+}\r
+\r
+/**\r
+ * \brief Configures a MCI peripheral as specified.\r
+ *\r
+ * \param pRMci  Pointer to an MCI instance.\r
+ * \param dwMode Value of the MCI Mode register.\r
+ */\r
+extern void HSMCI_ConfigureMode(Hsmci *pRMci, uint32_t dwMode)\r
+{\r
+    pRMci->HSMCI_MR = dwMode;\r
+}\r
+\r
+/**\r
+ * \brief Return mode register\r
+ * \param pRMci  Pointer to an MCI instance.\r
+ */\r
+extern uint32_t HSMCI_GetMode(Hsmci * pRMci)\r
+{\r
+    return pRMci->HSMCI_MR;\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable R/W proof\r
+ *\r
+ * \param pRMci    Pointer to an MCI instance.\r
+ * \param bRdProof Read proof enable/disable.\r
+ * \param bWrProof Write proof enable/disable.\r
+ */\r
+extern void HSMCI_ProofEnable(Hsmci *pRMci, uint8_t bRdProof, uint8_t bWrProof)\r
+{\r
+    uint32_t mr = pRMci->HSMCI_MR;\r
+    pRMci->HSMCI_MR = (mr & (~(HSMCI_MR_WRPROOF | HSMCI_MR_RDPROOF)))\r
+                    | (bRdProof ? HSMCI_MR_RDPROOF : 0)\r
+                    | (bWrProof ? HSMCI_MR_WRPROOF : 0)\r
+                    ;\r
+}\r
+\r
+/**\r
+ * \brief Padding value setting.\r
+ *\r
+ * \param pRMci    Pointer to an MCI instance.\r
+ * \param bPadvEn  Padding value 0xFF/0x00.\r
+ */\r
+extern void HSMCI_PadvCtl(Hsmci *pRMci, uint8_t bPadv)\r
+{\r
+    if (bPadv)\r
+    {\r
+        pRMci->HSMCI_MR |= HSMCI_MR_PADV;\r
+    }\r
+    else\r
+    {\r
+        pRMci->HSMCI_MR &= ~HSMCI_MR_PADV;\r
+    }\r
+}\r
+\r
+/**\r
+ * \brief Force byte transfer enable/disable.\r
+ *\r
+ * \param pRMci    Pointer to an MCI instance.\r
+ * \param bFByteEn FBYTE enable/disable.\r
+ */\r
+extern void HSMCI_FByteEnable(Hsmci *pRMci, uint8_t bFByteEn)\r
+{\r
+    if (bFByteEn)\r
+    {\r
+        pRMci->HSMCI_MR |= HSMCI_MR_FBYTE;\r
+    }\r
+    else\r
+    {\r
+        pRMci->HSMCI_MR &= ~HSMCI_MR_FBYTE;\r
+    }\r
+}\r
+\r
+/**\r
+ * \brief Check if Force Byte mode enabled.\r
+ *\r
+ * \param pRMci    Pointer to an MCI instance.\r
+ * \return 1 if _FBYTE is enabled.\r
+ */\r
+extern uint8_t HSMCI_IsFByteEnabled(Hsmci *pRMci)\r
+{\r
+    return ((pRMci->HSMCI_MR & HSMCI_MR_FBYTE) > 0);\r
+}\r
+\r
+/**\r
+ * \brief Set Clock Divider & Power save divider for MCI.\r
+ *\r
+ * \param pRMci    Pointer to an MCI instance.\r
+ * \param bClkDiv  Clock Divider value (0 ~ 255).\r
+ * \param bPwsDiv  Power Saving Divider (1 ~ 7).\r
+ */\r
+extern void HSMCI_DivCtrl(Hsmci *pRMci, uint32_t bClkDiv, uint8_t bPwsDiv)\r
+{\r
+    uint32_t mr = pRMci->HSMCI_MR;\r
+    uint32_t clkdiv ,clkodd;\r
+    clkdiv = bClkDiv - 2 ;\r
+    clkodd = (bClkDiv & 1)? HSMCI_MR_CLKODD: 0;\r
+    clkdiv = clkdiv >> 1;\r
+\r
+    pRMci->HSMCI_MR = (mr & ~(HSMCI_MR_CLKDIV_Msk | HSMCI_MR_PWSDIV_Msk))\r
+                    | HSMCI_MR_CLKDIV(clkdiv)\r
+                    | HSMCI_MR_PWSDIV(bPwsDiv)\r
+                    | clkodd\r
+                    ;\r
+}\r
+\r
+/**\r
+ * \brief Enables one or more interrupt sources of MCI peripheral.\r
+ *\r
+ * \param pRMci   Pointer to an Hsmci instance.\r
+ * \param sources Bitwise OR of selected interrupt sources.\r
+ */\r
+extern void HSMCI_EnableIt(Hsmci *pRMci, uint32_t dwSources)\r
+{\r
+    pRMci->HSMCI_IER = dwSources;\r
+}\r
+\r
+/**\r
+ * \brief Disable one or more interrupt sources of MCI peripheral.\r
+ *\r
+ * \param pRMci   Pointer to an Hsmci instance.\r
+ * \param sources Bitwise OR of selected interrupt sources.\r
+ */\r
+extern void HSMCI_DisableIt(Hsmci *pRMci, uint32_t dwSources)\r
+{\r
+    pRMci->HSMCI_IDR = dwSources;\r
+}\r
+\r
+/**\r
+ * \brief Return the interrupt mask register.\r
+ *\r
+ * \param pRMci   Pointer to an Hsmci instance.\r
+ * \return MCI interrupt mask register.\r
+ */\r
+extern uint32_t HSMCI_GetItMask(Hsmci *pRMci)\r
+{\r
+    return (pRMci->HSMCI_IMR) ;\r
+}\r
+\r
+/**\r
+ * \brief Set block len & count for transfer\r
+ * \r
+ * \param pRMci     Pointer to an Hsmci instance.\r
+ * \param wBlkLen   Block size.\r
+ * \param wCnt      Block(byte) count.\r
+ */\r
+extern void HSMCI_ConfigureTransfer(Hsmci *pRMci,\r
+                                    uint16_t wBlkLen,\r
+                                    uint16_t wCnt)\r
+{\r
+    pRMci->HSMCI_BLKR = (wBlkLen << 16) | wCnt;\r
+}\r
+\r
+/**\r
+ * \brief Set block length\r
+ *\r
+ *  Count is reset to 0.\r
+ *\r
+ * \param pRMci     Pointer to an Hsmci instance.\r
+ * \param wBlkSize  Block size.\r
+ */\r
+extern void HSMCI_SetBlockLen(Hsmci *pRMci, uint16_t wBlkSize)\r
+{\r
+    pRMci->HSMCI_BLKR = wBlkSize << 16;\r
+}\r
+\r
+/**\r
+ * \brief Set block (byte) count\r
+ *\r
+ * \param pRMci     Pointer to an Hsmci instance.\r
+ * \param wBlkCnt   Block(byte) count.\r
+ */\r
+extern void HSMCI_SetBlockCount(Hsmci *pRMci, uint16_t wBlkCnt)\r
+{\r
+    pRMci->HSMCI_BLKR |= wBlkCnt;\r
+}\r
+\r
+/**\r
+ * \brief Configure the Completion Signal Timeout\r
+ *\r
+ * \param pRMci Pointer to an Hsmci instance.\r
+ * \param dwConfigure Completion Signal Timeout configure.\r
+ */\r
+extern void HSMCI_ConfigureCompletionTO(Hsmci *pRMci, uint32_t dwConfigure)\r
+{\r
+    pRMci->HSMCI_CSTOR = dwConfigure;\r
+}\r
+\r
+/**\r
+ * \brief Configure the Data Timeout\r
+ *\r
+ * \param pRMci Pointer to an Hsmci instance.\r
+ * \param dwConfigure Data Timeout configure.\r
+ */\r
+extern void HSMCI_ConfigureDataTO(Hsmci *pRMci, uint32_t dwConfigure)\r
+{\r
+    pRMci->HSMCI_DTOR = dwConfigure;\r
+}\r
+\r
+/**\r
+ * \brief Send command\r
+ *\r
+ * \param pRMci Pointer to an Hsmci instance.\r
+ * \param dwCmd Command register value.\r
+ * \param dwArg Argument register value.\r
+ */\r
+extern void HSMCI_SendCmd(Hsmci *pRMci, uint32_t dwCmd, uint32_t dwArg)\r
+{\r
+    pRMci->HSMCI_ARGR = dwArg;\r
+    pRMci->HSMCI_CMDR = dwCmd;\r
+}\r
+\r
+\r
+/**\r
+ * \brief Return the response register.\r
+ *\r
+ * \param pRMci   Pointer to an Hsmci instance.\r
+ * \return MCI response register.\r
+ */\r
+extern uint32_t HSMCI_GetResponse(Hsmci *pRMci)\r
+{\r
+    return pRMci->HSMCI_RSPR[0];\r
+}\r
+\r
+/**\r
+ * \brief Return the receive data register.\r
+ *\r
+ * \param pRMci   Pointer to an Hsmci instance.\r
+ * \return MCI receive data register.\r
+ */\r
+extern uint32_t HSMCI_Read(Hsmci *pRMci)\r
+{\r
+    return pRMci->HSMCI_RDR;\r
+}\r
+\r
+/**\r
+ * \brief Read from FIFO\r
+ *\r
+ * \param pRMci   Pointer to an Hsmci instance.\r
+ * \param pdwData Pointer to data buffer.\r
+ * \param dwSize  Size of data buffer (in DWord).\r
+ */\r
+extern void HSMCI_ReadFifo(Hsmci *pRMci, uint8_t *pdwData, uint32_t dwSize)\r
+{\r
+    volatile uint32_t *pFIFO = (volatile uint32_t*)(pRMci->HSMCI_FIFO);\r
+    register uint32_t c4, c1;\r
+\r
+    if (dwSize == 0)\r
+        return;\r
+\r
+    c4 = dwSize >> 2;\r
+    c1 = dwSize & 0x3;\r
+\r
+    for(;c4;c4 --)\r
+    {\r
+        *pdwData ++ = *pFIFO ++;\r
+        *pdwData ++ = *pFIFO ++;\r
+        *pdwData ++ = *pFIFO ++;\r
+        *pdwData ++ = *pFIFO ++;\r
+    }\r
+    for(;c1;c1 --)\r
+    {\r
+        *pdwData ++ = *pFIFO ++;\r
+    }\r
+}\r
+\r
+/**\r
+ * \brief Sends data through MCI peripheral.\r
+ *\r
+ * \param pRMci   Pointer to an Hsmci instance.\r
+ * \param\r
+ */\r
+extern void HSMCI_Write(Hsmci *pRMci, uint32_t dwData)\r
+{\r
+    pRMci->HSMCI_TDR = dwData;\r
+}\r
+\r
+/**\r
+ * \brief Write to FIFO\r
+ *\r
+ * \param pRMci   Pointer to an Hsmci instance.\r
+ * \param pdwData Pointer to data buffer.\r
+ * \param dwSize  Size of data buffer (In DWord).\r
+ */\r
+extern void HSMCI_WriteFifo(Hsmci *pRMci, uint8_t *pdwData, uint32_t dwSize)\r
+{\r
+    volatile uint32_t *pFIFO = (volatile uint32_t*)(pRMci->HSMCI_FIFO);\r
+    register uint32_t c4, c1;\r
+\r
+    if (dwSize == 0)\r
+        return;\r
+\r
+    c4 = dwSize >> 2;\r
+    c1 = dwSize & 0x3;\r
+\r
+    for(;c4;c4 --)\r
+    {\r
+        *pFIFO ++ = *pdwData ++;\r
+        *pFIFO ++ = *pdwData ++;\r
+        *pFIFO ++ = *pdwData ++;\r
+        *pFIFO ++ = *pdwData ++;\r
+    }\r
+    for(;c1;c1 --)\r
+    {\r
+        *pFIFO ++ = *pdwData ++;\r
+    }\r
+}\r
+\r
+/**\r
+ * \brief Return the status register.\r
+ *\r
+ * \param pRMci   Pointer to an Hsmci instance.\r
+ * \return MCI status register.\r
+ */\r
+extern uint32_t HSMCI_GetStatus(Hsmci *pRMci)\r
+{\r
+    return pRMci->HSMCI_SR;\r
+}\r
+\r
+/**\r
+ * \brief Configure the HSMCI DMA\r
+ *  \r
+ * \param pRMci Pointer to an Hsmci instance.\r
+ * \param dwConfigure Configure value. \r
+ */\r
+extern void HSMCI_ConfigureDma(Hsmci *pRMci, uint32_t dwConfigure)\r
+{\r
+    pRMci->HSMCI_DMA = dwConfigure;\r
+}\r
+\r
+/**\r
+ * \brief Enable the HSMCI DMA\r
+ *  \r
+ * \param pRMci Pointer to an Hsmci instance.\r
+ * \param bEnable 1 to enable, 0 to disable.\r
+ */\r
+extern void HSMCI_EnableDma(Hsmci *pRMci, uint8_t bEnable)\r
+{\r
+    if (bEnable)\r
+    {\r
+        pRMci->HSMCI_DMA |= HSMCI_DMA_DMAEN ;//| HSMCI_DMA_CHKSIZE_32;\r
+    }\r
+    else\r
+    {\r
+        pRMci->HSMCI_DMA &= ~HSMCI_DMA_DMAEN;\r
+    }\r
+}\r
+\r
+/**\r
+ * \brief Configure the HSMCI\r
+ *  \r
+ * \param pRMci   Pointer to an Hsmci instance.\r
+ * \param dwConfigure Configure value. \r
+ */\r
+extern void HSMCI_Configure(Hsmci *pRMci, uint32_t dwConfigure)\r
+{\r
+    pRMci->HSMCI_CFG = dwConfigure;\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable High-Speed mode for MCI\r
+ * \r
+ * \param pRMci Pointer to an Hsmci instance.\r
+ * \param bHsEnable Enable/Disable high-speed.\r
+ */\r
+extern void HSMCI_HsEnable(Hsmci *pRMci, uint8_t bHsEnable)\r
+{\r
+    if (bHsEnable)\r
+    {\r
+        pRMci->HSMCI_CFG |= HSMCI_CFG_HSMODE;\r
+    }\r
+    else\r
+    {\r
+        pRMci->HSMCI_CFG &= ~HSMCI_CFG_HSMODE;\r
+    }\r
+}\r
+\r
+/**\r
+ * \brief Check if High-speed mode is enabled on MCI\r
+ * \param pRMci Pointer to an Hsmci instance.\r
+ * \return 1 \r
+ */\r
+extern uint8_t HSMCI_IsHsEnabled(Hsmci * pRMci)\r
+{\r
+    return ((pRMci->HSMCI_CFG & HSMCI_CFG_HSMODE) > 0);\r
+}\r
+\r
+/**\r
+ * \brief Configure the Write Protection Mode\r
+ *  \r
+ * \param pRMci   Pointer to an Hsmci instance.\r
+ * \param dwConfigure WP mode configure value. \r
+ */\r
+extern void HSMCI_ConfigureWP(Hsmci *pRMci, uint32_t dwConfigure)\r
+{\r
+    pRMci->HSMCI_WPMR = dwConfigure;\r
+}\r
+\r
+/**\r
+ * \brief Return the write protect status register.\r
+ *\r
+ * \param pRMci   Pointer to an Hsmci instance.\r
+ * \return MCI write protect status register.\r
+ */\r
+extern uint32_t HSMCI_GetWPStatus(Hsmci *pRMci)\r
+{\r
+    return pRMci->HSMCI_WPSR;\r
+}\r
+\r
+/**@}*/\r
+\r