SAMV71 Xplained Ultra Software Package 1.5

hsmci.c

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------- */
00002 /*                  Atmel Microcontroller Software Support                      */
00003 /*                       SAM Software Package License                           */
00004 /* ---------------------------------------------------------------------------- */
00005 /* Copyright (c) 2015, Atmel Corporation                                        */
00006 /*                                                                              */
00007 /* All rights reserved.                                                         */
00008 /*                                                                              */
00009 /* Redistribution and use in source and binary forms, with or without           */
00010 /* modification, are permitted provided that the following condition is met:    */
00011 /*                                                                              */
00012 /* - Redistributions of source code must retain the above copyright notice,     */
00013 /* this list of conditions and the disclaimer below.                            */
00014 /*                                                                              */
00015 /* Atmel's name may not be used to endorse or promote products derived from     */
00016 /* this software without specific prior written permission.                     */
00017 /*                                                                              */
00018 /* DISCLAIMER:  THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR   */
00019 /* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
00020 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE   */
00021 /* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,      */
00022 /* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
00023 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,  */
00024 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    */
00025 /* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING         */
00026 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */
00027 /* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                           */
00028 /* ---------------------------------------------------------------------------- */
00029 
00030 /** \file
00031  *
00032  * Implementation of High Speed MultiMedia Card Interface (HSMCI) controller.
00033  */
00034 
00035 /*---------------------------------------------------------------------------
00036  *         Headers
00037  *---------------------------------------------------------------------------*/
00038 
00039 #include "chip.h"
00040 #include <assert.h>
00041 
00042 /*---------------------------------------------------------------------------
00043  *         Exported functions
00044  *---------------------------------------------------------------------------*/
00045 
00046 /** \addtogroup hsmci_functions
00047  *@{
00048  */
00049 
00050 /**
00051  * \brief Enable Multi-Media Interface
00052  *
00053  * \param pRMci Pointer to a Hsmci instance
00054  */
00055 extern void HSMCI_Enable(Hsmci *pRMci)
00056 {
00057     pRMci->HSMCI_CR = HSMCI_CR_MCIEN;
00058 }
00059 
00060 /**
00061  * \brief Disable Multi-Media Interface
00062  *
00063  * \param pRMci Pointer to a Hsmci instance
00064  */
00065 extern void HSMCI_Disable(Hsmci *pRMci)
00066 {
00067     pRMci->HSMCI_CR = HSMCI_CR_MCIDIS;
00068 
00069 }
00070 
00071 /**
00072  * \brief Reset (& Disable) Multi-Media Interface
00073  *
00074  * \param mci Pointer to a Hsmci instance
00075  * \param bBackup Backup registers values to keep previous settings, including
00076  *                _MR, _SDCR, _DTOR, _CSTOR, _DMA and _CFG.
00077  */
00078 extern void HSMCI_Reset(Hsmci *pRMci, uint8_t bBackup)
00079 {
00080     if (bBackup) {
00081         uint32_t mr    = pRMci->HSMCI_MR;
00082         uint32_t dtor  = pRMci->HSMCI_DTOR;
00083         uint32_t sdcr  = pRMci->HSMCI_SDCR;
00084         uint32_t cstor = pRMci->HSMCI_CSTOR;
00085         uint32_t dma   = pRMci->HSMCI_DMA;
00086         uint32_t cfg   = pRMci->HSMCI_CFG;
00087 
00088         pRMci->HSMCI_CR = HSMCI_CR_SWRST;
00089 
00090         pRMci->HSMCI_MR    = mr;
00091         pRMci->HSMCI_DTOR  = dtor;
00092         pRMci->HSMCI_SDCR  = sdcr;
00093         pRMci->HSMCI_CSTOR = cstor;
00094         pRMci->HSMCI_DMA   = dma;
00095         pRMci->HSMCI_CFG   = cfg;
00096     } else
00097         pRMci->HSMCI_CR = HSMCI_CR_SWRST;
00098 }
00099 
00100 /**
00101  * \brief Select slot
00102  * \param pRMci Pointer to a Hsmci instance
00103  * \param bSlot Slot ID (0~3 for A~D).
00104  */
00105 extern void HSMCI_Select(Hsmci *pRMci, uint8_t bSlot, uint8_t bBusWidth)
00106 {
00107     uint32_t dwSdcr;
00108     dwSdcr = (HSMCI_SDCR_SDCSEL_Msk & bSlot);
00109 
00110     switch (bBusWidth) {
00111     case 1:
00112         pRMci->HSMCI_SDCR = dwSdcr | HSMCI_SDCR_SDCBUS_1;
00113         break;
00114 
00115     case 4:
00116         pRMci->HSMCI_SDCR = dwSdcr | HSMCI_SDCR_SDCBUS_4;
00117         break;
00118 
00119     case 8:
00120         pRMci->HSMCI_SDCR = dwSdcr | HSMCI_SDCR_SDCBUS_8;
00121         break;
00122     }
00123 }
00124 
00125 /**
00126  * \brief Set slot
00127  * \param pRMci Pointer to a Hsmci instance
00128  * \param bSlot Slot ID (0~3 for A~D).
00129  */
00130 extern void HSMCI_SetSlot(Hsmci *pRMci, uint8_t bSlot)
00131 {
00132     uint32_t dwSdcr = pRMci->HSMCI_SDCR & ~HSMCI_SDCR_SDCSEL_Msk;
00133     pRMci->HSMCI_SDCR = dwSdcr | (HSMCI_SDCR_SDCSEL_Msk & bSlot);
00134 }
00135 
00136 /**
00137  * \brief Set bus width of MCI
00138  * \param pRMci Pointer to a Hsmci instance
00139  * \param bBusWidth 1,4 or 8 (bits).
00140  */
00141 extern void HSMCI_SetBusWidth(Hsmci *pRMci, uint8_t bBusWidth)
00142 {
00143     uint32_t dwSdcr = pRMci->HSMCI_SDCR & ~HSMCI_SDCR_SDCBUS_Msk;
00144 
00145     switch (bBusWidth) {
00146     case 1:
00147         pRMci->HSMCI_SDCR = dwSdcr | HSMCI_SDCR_SDCBUS_1;
00148         break;
00149 
00150     case 4:
00151         pRMci->HSMCI_SDCR = dwSdcr | HSMCI_SDCR_SDCBUS_4;
00152         break;
00153 
00154     case 8:
00155         pRMci->HSMCI_SDCR = dwSdcr | HSMCI_SDCR_SDCBUS_8;
00156         break;
00157     }
00158 }
00159 
00160 /**
00161  * \brief Return bus width setting.
00162  *
00163  * \param pRMci  Pointer to an MCI instance.
00164  * \return 1, 4 or 8.
00165  */
00166 extern uint8_t HSMCI_GetBusWidth(Hsmci *pRMci)
00167 {
00168     switch (pRMci->HSMCI_SDCR & HSMCI_SDCR_SDCBUS_Msk) {
00169     case HSMCI_SDCR_SDCBUS_1: return 1;
00170 
00171     case HSMCI_SDCR_SDCBUS_4: return 4;
00172 
00173     case HSMCI_SDCR_SDCBUS_8: return 8;
00174     }
00175 
00176     return 0;
00177 }
00178 
00179 /**
00180  * \brief Configures a MCI peripheral as specified.
00181  *
00182  * \param pRMci  Pointer to an MCI instance.
00183  * \param dwMode Value of the MCI Mode register.
00184  */
00185 extern void HSMCI_ConfigureMode(Hsmci *pRMci, uint32_t dwMode)
00186 {
00187     pRMci->HSMCI_MR = dwMode;
00188 
00189 }
00190 
00191 /**
00192  * \brief Return mode register
00193  * \param pRMci  Pointer to an MCI instance.
00194  */
00195 extern uint32_t HSMCI_GetMode(Hsmci *pRMci)
00196 {
00197     return pRMci->HSMCI_MR;
00198 }
00199 
00200 /**
00201  * \brief Enable/Disable R/W proof
00202  *
00203  * \param pRMci    Pointer to an MCI instance.
00204  * \param bRdProof Read proof enable/disable.
00205  * \param bWrProof Write proof enable/disable.
00206  */
00207 extern void HSMCI_ProofEnable(Hsmci *pRMci, uint8_t bRdProof, uint8_t bWrProof)
00208 {
00209     uint32_t mr = pRMci->HSMCI_MR;
00210     pRMci->HSMCI_MR = (mr & (~(HSMCI_MR_WRPROOF | HSMCI_MR_RDPROOF)))
00211                       | (bRdProof ? HSMCI_MR_RDPROOF : 0)
00212                       | (bWrProof ? HSMCI_MR_WRPROOF : 0)
00213                      ;
00214 }
00215 
00216 /**
00217  * \brief Padding value setting.
00218  *
00219  * \param pRMci    Pointer to an MCI instance.
00220  * \param bPadvEn  Padding value 0xFF/0x00.
00221  */
00222 extern void HSMCI_PadvCtl(Hsmci *pRMci, uint8_t bPadv)
00223 {
00224     if (bPadv)
00225         pRMci->HSMCI_MR |= HSMCI_MR_PADV;
00226     else
00227         pRMci->HSMCI_MR &= ~HSMCI_MR_PADV;
00228 }
00229 
00230 /**
00231  * \brief Force byte transfer enable/disable.
00232  *
00233  * \param pRMci    Pointer to an MCI instance.
00234  * \param bFByteEn FBYTE enable/disable.
00235  */
00236 extern void HSMCI_FByteEnable(Hsmci *pRMci, uint8_t bFByteEn)
00237 {
00238     if (bFByteEn)
00239         pRMci->HSMCI_MR |= HSMCI_MR_FBYTE;
00240     else
00241         pRMci->HSMCI_MR &= ~HSMCI_MR_FBYTE;
00242 }
00243 
00244 /**
00245  * \brief Check if Force Byte mode enabled.
00246  *
00247  * \param pRMci    Pointer to an MCI instance.
00248  * \return 1 if _FBYTE is enabled.
00249  */
00250 extern uint8_t HSMCI_IsFByteEnabled(Hsmci *pRMci)
00251 {
00252     return ((pRMci->HSMCI_MR & HSMCI_MR_FBYTE) > 0);
00253 }
00254 
00255 /**
00256  * \brief Set Clock Divider & Power save divider for MCI.
00257  *
00258  * \param pRMci    Pointer to an MCI instance.
00259  * \param bClkDiv  Clock Divider value (0 ~ 255).
00260  * \param bPwsDiv  Power Saving Divider (1 ~ 7).
00261  */
00262 extern void HSMCI_DivCtrl(Hsmci *pRMci, uint32_t bClkDiv, uint8_t bPwsDiv)
00263 {
00264     uint32_t mr = pRMci->HSMCI_MR;
00265     uint32_t clkdiv , clkodd;
00266     clkdiv = bClkDiv - 2;
00267     clkodd = (bClkDiv & 1) ? HSMCI_MR_CLKODD : 0;
00268     clkdiv = clkdiv >> 1;
00269 
00270     pRMci->HSMCI_MR = (mr & ~(HSMCI_MR_CLKDIV_Msk | HSMCI_MR_PWSDIV_Msk))
00271                       | HSMCI_MR_CLKDIV(clkdiv)
00272                       | HSMCI_MR_PWSDIV(bPwsDiv)
00273                       | clkodd
00274                      ;
00275 }
00276 
00277 /**
00278  * \brief Enables one or more interrupt sources of MCI peripheral.
00279  *
00280  * \param pRMci   Pointer to an Hsmci instance.
00281  * \param sources Bitwise OR of selected interrupt sources.
00282  */
00283 extern void HSMCI_EnableIt(Hsmci *pRMci, uint32_t dwSources)
00284 {
00285     pRMci->HSMCI_IER = dwSources;
00286 }
00287 
00288 /**
00289  * \brief Disable one or more interrupt sources of MCI peripheral.
00290  *
00291  * \param pRMci   Pointer to an Hsmci instance.
00292  * \param sources Bitwise OR of selected interrupt sources.
00293  */
00294 extern void HSMCI_DisableIt(Hsmci *pRMci, uint32_t dwSources)
00295 {
00296     pRMci->HSMCI_IDR = dwSources;
00297 }
00298 
00299 /**
00300  * \brief Return the interrupt mask register.
00301  *
00302  * \param pRMci   Pointer to an Hsmci instance.
00303  * \return MCI interrupt mask register.
00304  */
00305 extern uint32_t HSMCI_GetItMask(Hsmci *pRMci)
00306 {
00307     return (pRMci->HSMCI_IMR);
00308 }
00309 
00310 /**
00311  * \brief Set block len & count for transfer
00312  *
00313  * \param pRMci     Pointer to an Hsmci instance.
00314  * \param wBlkLen   Block size.
00315  * \param wCnt      Block(byte) count.
00316  */
00317 extern void HSMCI_ConfigureTransfer(Hsmci *pRMci,
00318                                     uint16_t wBlkLen,
00319                                     uint16_t wCnt)
00320 {
00321     pRMci->HSMCI_BLKR = (wBlkLen << 16) | wCnt;
00322 }
00323 
00324 /**
00325  * \brief Set block length
00326  *
00327  *  Count is reset to 0.
00328  *
00329  * \param pRMci     Pointer to an Hsmci instance.
00330  * \param wBlkSize  Block size.
00331  */
00332 extern void HSMCI_SetBlockLen(Hsmci *pRMci, uint16_t wBlkSize)
00333 {
00334     pRMci->HSMCI_BLKR = wBlkSize << 16;
00335 }
00336 
00337 /**
00338  * \brief Set block (byte) count
00339  *
00340  * \param pRMci     Pointer to an Hsmci instance.
00341  * \param wBlkCnt   Block(byte) count.
00342  */
00343 extern void HSMCI_SetBlockCount(Hsmci *pRMci, uint16_t wBlkCnt)
00344 {
00345     pRMci->HSMCI_BLKR |= wBlkCnt;
00346 }
00347 
00348 /**
00349  * \brief Configure the Completion Signal Timeout
00350  *
00351  * \param pRMci Pointer to an Hsmci instance.
00352  * \param dwConfigure Completion Signal Timeout configure.
00353  */
00354 extern void HSMCI_ConfigureCompletionTO(Hsmci *pRMci, uint32_t dwConfigure)
00355 {
00356     pRMci->HSMCI_CSTOR = dwConfigure;
00357 }
00358 
00359 /**
00360  * \brief Configure the Data Timeout
00361  *
00362  * \param pRMci Pointer to an Hsmci instance.
00363  * \param dwConfigure Data Timeout configure.
00364  */
00365 extern void HSMCI_ConfigureDataTO(Hsmci *pRMci, uint32_t dwConfigure)
00366 {
00367     pRMci->HSMCI_DTOR = dwConfigure;
00368 }
00369 
00370 /**
00371  * \brief Send command
00372  *
00373  * \param pRMci Pointer to an Hsmci instance.
00374  * \param dwCmd Command register value.
00375  * \param dwArg Argument register value.
00376  */
00377 extern void HSMCI_SendCmd(Hsmci *pRMci, uint32_t dwCmd, uint32_t dwArg)
00378 {
00379     pRMci->HSMCI_ARGR = dwArg;
00380     pRMci->HSMCI_CMDR = dwCmd;
00381 }
00382 
00383 
00384 /**
00385  * \brief Return the response register.
00386  *
00387  * \param pRMci   Pointer to an Hsmci instance.
00388  * \return MCI response register.
00389  */
00390 extern uint32_t HSMCI_GetResponse(Hsmci *pRMci)
00391 {
00392     return pRMci->HSMCI_RSPR[0];
00393 }
00394 
00395 /**
00396  * \brief Return the receive data register.
00397  *
00398  * \param pRMci   Pointer to an Hsmci instance.
00399  * \return MCI receive data register.
00400  */
00401 extern uint32_t HSMCI_Read(Hsmci *pRMci)
00402 {
00403     return pRMci->HSMCI_RDR;
00404 }
00405 
00406 /**
00407  * \brief Read from FIFO
00408  *
00409  * \param pRMci   Pointer to an Hsmci instance.
00410  * \param pdwData Pointer to data buffer.
00411  * \param dwSize  Size of data buffer (in DWord).
00412  */
00413 extern void HSMCI_ReadFifo(Hsmci *pRMci, uint8_t *pdwData, uint32_t dwSize)
00414 {
00415     volatile uint32_t *pFIFO = (volatile uint32_t *)(pRMci->HSMCI_FIFO);
00416     register uint32_t c4, c1;
00417 
00418     if (dwSize == 0)
00419         return;
00420 
00421     c4 = dwSize >> 2;
00422     c1 = dwSize & 0x3;
00423 
00424     for (; c4; c4 --) {
00425         *pdwData ++ = *pFIFO ++;
00426         *pdwData ++ = *pFIFO ++;
00427         *pdwData ++ = *pFIFO ++;
00428         *pdwData ++ = *pFIFO ++;
00429     }
00430 
00431     for (; c1; c1 --)
00432         *pdwData ++ = *pFIFO ++;
00433 }
00434 
00435 /**
00436  * \brief Sends data through MCI peripheral.
00437  *
00438  * \param pRMci   Pointer to an Hsmci instance.
00439  * \param
00440  */
00441 extern void HSMCI_Write(Hsmci *pRMci, uint32_t dwData)
00442 {
00443     pRMci->HSMCI_TDR = dwData;
00444 }
00445 
00446 /**
00447  * \brief Write to FIFO
00448  *
00449  * \param pRMci   Pointer to an Hsmci instance.
00450  * \param pdwData Pointer to data buffer.
00451  * \param dwSize  Size of data buffer (In DWord).
00452  */
00453 extern void HSMCI_WriteFifo(Hsmci *pRMci, uint8_t *pdwData, uint32_t dwSize)
00454 {
00455     volatile uint32_t *pFIFO = (volatile uint32_t *)(pRMci->HSMCI_FIFO);
00456     register uint32_t c4, c1;
00457 
00458     if (dwSize == 0)
00459         return;
00460 
00461     c4 = dwSize >> 2;
00462     c1 = dwSize & 0x3;
00463 
00464     for (; c4; c4 --) {
00465         *pFIFO ++ = *pdwData ++;
00466         *pFIFO ++ = *pdwData ++;
00467         *pFIFO ++ = *pdwData ++;
00468         *pFIFO ++ = *pdwData ++;
00469     }
00470 
00471     for (; c1; c1 --)
00472         *pFIFO ++ = *pdwData ++;
00473 }
00474 
00475 /**
00476  * \brief Return the status register.
00477  *
00478  * \param pRMci   Pointer to an Hsmci instance.
00479  * \return MCI status register.
00480  */
00481 extern uint32_t HSMCI_GetStatus(Hsmci *pRMci)
00482 {
00483     return pRMci->HSMCI_SR;
00484 }
00485 
00486 /**
00487  * \brief Configure the HSMCI DMA
00488  *
00489  * \param pRMci Pointer to an Hsmci instance.
00490  * \param dwConfigure Configure value.
00491  */
00492 extern void HSMCI_ConfigureDma(Hsmci *pRMci, uint32_t dwConfigure)
00493 {
00494     pRMci->HSMCI_DMA = dwConfigure;
00495 }
00496 
00497 /**
00498  * \brief Enable the HSMCI DMA
00499  *
00500  * \param pRMci Pointer to an Hsmci instance.
00501  * \param bEnable 1 to enable, 0 to disable.
00502  */
00503 extern void HSMCI_EnableDma(Hsmci *pRMci, uint8_t bEnable)
00504 {
00505     if (bEnable) {
00506         pRMci->HSMCI_DMA |= HSMCI_DMA_DMAEN;//| HSMCI_DMA_CHKSIZE_32;
00507     } else
00508         pRMci->HSMCI_DMA &= ~HSMCI_DMA_DMAEN;
00509 }
00510 
00511 /**
00512  * \brief Configure the HSMCI
00513  *
00514  * \param pRMci   Pointer to an Hsmci instance.
00515  * \param dwConfigure Configure value.
00516  */
00517 extern void HSMCI_Configure(Hsmci *pRMci, uint32_t dwConfigure)
00518 {
00519     pRMci->HSMCI_CFG = dwConfigure;
00520 }
00521 
00522 /**
00523  * \brief Enable/Disable High-Speed mode for MCI
00524  *
00525  * \param pRMci Pointer to an Hsmci instance.
00526  * \param bHsEnable Enable/Disable high-speed.
00527  */
00528 extern void HSMCI_HsEnable(Hsmci *pRMci, uint8_t bHsEnable)
00529 {
00530     if (bHsEnable)
00531         pRMci->HSMCI_CFG |= HSMCI_CFG_HSMODE;
00532     else
00533         pRMci->HSMCI_CFG &= ~HSMCI_CFG_HSMODE;
00534 }
00535 
00536 /**
00537  * \brief Check if High-speed mode is enabled on MCI
00538  * \param pRMci Pointer to an Hsmci instance.
00539  * \return 1
00540  */
00541 extern uint8_t HSMCI_IsHsEnabled(Hsmci *pRMci)
00542 {
00543     return ((pRMci->HSMCI_CFG & HSMCI_CFG_HSMODE) > 0);
00544 }
00545 
00546 /**
00547  * \brief Configure the Write Protection Mode
00548  *
00549  * \param pRMci   Pointer to an Hsmci instance.
00550  * \param dwConfigure WP mode configure value.
00551  */
00552 extern void HSMCI_ConfigureWP(Hsmci *pRMci, uint32_t dwConfigure)
00553 {
00554     pRMci->HSMCI_WPMR = dwConfigure;
00555 }
00556 
00557 /**
00558  * \brief Return the write protect status register.
00559  *
00560  * \param pRMci   Pointer to an Hsmci instance.
00561  * \return MCI write protect status register.
00562  */
00563 extern uint32_t HSMCI_GetWPStatus(Hsmci *pRMci)
00564 {
00565     return pRMci->HSMCI_WPSR;
00566 }
00567 
00568 /**@}*/
00569 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines