1 /* ----------------------------------------------------------------------------
\r
2 * SAM Software Package License
\r
3 * ----------------------------------------------------------------------------
\r
4 * Copyright (c) 2011, Atmel Corporation
\r
6 * All rights reserved.
\r
8 * Redistribution and use in source and binary forms, with or without
\r
9 * modification, are permitted provided that the following conditions are met:
\r
11 * - Redistributions of source code must retain the above copyright notice,
\r
12 * this list of conditions and the disclaimer below.
\r
14 * Atmel's name may not be used to endorse or promote products derived from
\r
15 * this software without specific prior written permission.
\r
17 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
\r
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
\r
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
\r
20 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
\r
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
\r
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
\r
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
\r
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
\r
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
\r
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
27 * ----------------------------------------------------------------------------
\r
32 * Implementation of High Speed MultiMedia Card Interface (HSMCI) controller.
\r
35 /*---------------------------------------------------------------------------
\r
37 *---------------------------------------------------------------------------*/
\r
42 /*---------------------------------------------------------------------------
\r
43 * Exported functions
\r
44 *---------------------------------------------------------------------------*/
\r
46 /** \addtogroup hsmci_functions
\r
51 * \brief Enable Multi-Media Interface
\r
53 * \param pRMci Pointer to a Hsmci instance
\r
55 extern void HSMCI_Enable(Hsmci* pRMci)
\r
57 pRMci->HSMCI_CR = HSMCI_CR_MCIEN;
\r
61 * \brief Disable Multi-Media Interface
\r
63 * \param pRMci Pointer to a Hsmci instance
\r
65 extern void HSMCI_Disable(Hsmci* pRMci)
\r
67 pRMci->HSMCI_CR = HSMCI_CR_MCIDIS;
\r
71 * \brief Reset (& Disable) Multi-Media Interface
\r
73 * \param mci Pointer to a Hsmci instance
\r
74 * \param bBackup Backup registers values to keep previous settings, including
\r
75 * _MR, _SDCR, _DTOR, _CSTOR, _DMA and _CFG.
\r
77 extern void HSMCI_Reset(Hsmci* pRMci, uint8_t bBackup)
\r
81 uint32_t mr = pRMci->HSMCI_MR;
\r
82 uint32_t dtor = pRMci->HSMCI_DTOR;
\r
83 uint32_t sdcr = pRMci->HSMCI_SDCR;
\r
84 uint32_t cstor = pRMci->HSMCI_CSTOR;
\r
85 uint32_t dma = pRMci->HSMCI_DMA;
\r
86 uint32_t cfg = pRMci->HSMCI_CFG;
\r
88 pRMci->HSMCI_CR = HSMCI_CR_SWRST;
\r
90 pRMci->HSMCI_MR = mr;
\r
91 pRMci->HSMCI_DTOR = dtor;
\r
92 pRMci->HSMCI_SDCR = sdcr;
\r
93 pRMci->HSMCI_CSTOR = cstor;
\r
94 pRMci->HSMCI_DMA = dma;
\r
95 pRMci->HSMCI_CFG = cfg;
\r
99 pRMci->HSMCI_CR = HSMCI_CR_SWRST;
\r
104 * \brief Select slot
\r
105 * \param pRMci Pointer to a Hsmci instance
\r
106 * \param bSlot Slot ID (0~3 for A~D).
\r
108 extern void HSMCI_Select(Hsmci *pRMci, uint8_t bSlot, uint8_t bBusWidth)
\r
111 dwSdcr = (HSMCI_SDCR_SDCSEL_Msk & bSlot);
\r
115 pRMci->HSMCI_SDCR = dwSdcr | HSMCI_SDCR_SDCBUS_1;
\r
118 pRMci->HSMCI_SDCR = dwSdcr | HSMCI_SDCR_SDCBUS_4;
\r
121 pRMci->HSMCI_SDCR = dwSdcr | HSMCI_SDCR_SDCBUS_8;
\r
128 * \param pRMci Pointer to a Hsmci instance
\r
129 * \param bSlot Slot ID (0~3 for A~D).
\r
131 extern void HSMCI_SetSlot(Hsmci *pRMci, uint8_t bSlot)
\r
133 uint32_t dwSdcr = pRMci->HSMCI_SDCR & ~HSMCI_SDCR_SDCSEL_Msk;
\r
134 pRMci->HSMCI_SDCR = dwSdcr | (HSMCI_SDCR_SDCSEL_Msk & bSlot);
\r
138 * \brief Set bus width of MCI
\r
139 * \param pRMci Pointer to a Hsmci instance
\r
140 * \param bBusWidth 1,4 or 8 (bits).
\r
142 extern void HSMCI_SetBusWidth(Hsmci * pRMci,uint8_t bBusWidth)
\r
144 uint32_t dwSdcr = pRMci->HSMCI_SDCR & ~HSMCI_SDCR_SDCBUS_Msk;
\r
148 pRMci->HSMCI_SDCR = dwSdcr | HSMCI_SDCR_SDCBUS_1;
\r
151 pRMci->HSMCI_SDCR = dwSdcr | HSMCI_SDCR_SDCBUS_4;
\r
154 pRMci->HSMCI_SDCR = dwSdcr | HSMCI_SDCR_SDCBUS_8;
\r
160 * \brief Return bus width setting.
\r
162 * \param pRMci Pointer to an MCI instance.
\r
163 * \return 1, 4 or 8.
\r
165 extern uint8_t HSMCI_GetBusWidth(Hsmci * pRMci)
\r
167 switch(pRMci->HSMCI_SDCR & HSMCI_SDCR_SDCBUS_Msk)
\r
169 case HSMCI_SDCR_SDCBUS_1: return 1;
\r
170 case HSMCI_SDCR_SDCBUS_4: return 4;
\r
171 case HSMCI_SDCR_SDCBUS_8: return 8;
\r
177 * \brief Configures a MCI peripheral as specified.
\r
179 * \param pRMci Pointer to an MCI instance.
\r
180 * \param dwMode Value of the MCI Mode register.
\r
182 extern void HSMCI_ConfigureMode(Hsmci *pRMci, uint32_t dwMode)
\r
184 pRMci->HSMCI_MR = dwMode;
\r
188 * \brief Return mode register
\r
189 * \param pRMci Pointer to an MCI instance.
\r
191 extern uint32_t HSMCI_GetMode(Hsmci * pRMci)
\r
193 return pRMci->HSMCI_MR;
\r
197 * \brief Enable/Disable R/W proof
\r
199 * \param pRMci Pointer to an MCI instance.
\r
200 * \param bRdProof Read proof enable/disable.
\r
201 * \param bWrProof Write proof enable/disable.
\r
203 extern void HSMCI_ProofEnable(Hsmci *pRMci, uint8_t bRdProof, uint8_t bWrProof)
\r
205 uint32_t mr = pRMci->HSMCI_MR;
\r
206 pRMci->HSMCI_MR = (mr & (~(HSMCI_MR_WRPROOF | HSMCI_MR_RDPROOF)))
\r
207 | (bRdProof ? HSMCI_MR_RDPROOF : 0)
\r
208 | (bWrProof ? HSMCI_MR_WRPROOF : 0)
\r
213 * \brief Padding value setting.
\r
215 * \param pRMci Pointer to an MCI instance.
\r
216 * \param bPadvEn Padding value 0xFF/0x00.
\r
218 extern void HSMCI_PadvCtl(Hsmci *pRMci, uint8_t bPadv)
\r
222 pRMci->HSMCI_MR |= HSMCI_MR_PADV;
\r
226 pRMci->HSMCI_MR &= ~HSMCI_MR_PADV;
\r
231 * \brief Force byte transfer enable/disable.
\r
233 * \param pRMci Pointer to an MCI instance.
\r
234 * \param bFByteEn FBYTE enable/disable.
\r
236 extern void HSMCI_FByteEnable(Hsmci *pRMci, uint8_t bFByteEn)
\r
240 pRMci->HSMCI_MR |= HSMCI_MR_FBYTE;
\r
244 pRMci->HSMCI_MR &= ~HSMCI_MR_FBYTE;
\r
249 * \brief Check if Force Byte mode enabled.
\r
251 * \param pRMci Pointer to an MCI instance.
\r
252 * \return 1 if _FBYTE is enabled.
\r
254 extern uint8_t HSMCI_IsFByteEnabled(Hsmci *pRMci)
\r
256 return ((pRMci->HSMCI_MR & HSMCI_MR_FBYTE) > 0);
\r
260 * \brief Set Clock Divider & Power save divider for MCI.
\r
262 * \param pRMci Pointer to an MCI instance.
\r
263 * \param bClkDiv Clock Divider value (0 ~ 255).
\r
264 * \param bPwsDiv Power Saving Divider (1 ~ 7).
\r
266 extern void HSMCI_DivCtrl(Hsmci *pRMci, uint32_t bClkDiv, uint8_t bPwsDiv)
\r
268 uint32_t mr = pRMci->HSMCI_MR;
\r
269 uint32_t clkdiv ,clkodd;
\r
270 clkdiv = bClkDiv - 2 ;
\r
271 clkodd = (bClkDiv & 1)? HSMCI_MR_CLKODD: 0;
\r
272 clkdiv = clkdiv >> 1;
\r
274 pRMci->HSMCI_MR = (mr & ~(HSMCI_MR_CLKDIV_Msk | HSMCI_MR_PWSDIV_Msk))
\r
275 | HSMCI_MR_CLKDIV(clkdiv)
\r
276 | HSMCI_MR_PWSDIV(bPwsDiv)
\r
282 * \brief Enables one or more interrupt sources of MCI peripheral.
\r
284 * \param pRMci Pointer to an Hsmci instance.
\r
285 * \param sources Bitwise OR of selected interrupt sources.
\r
287 extern void HSMCI_EnableIt(Hsmci *pRMci, uint32_t dwSources)
\r
289 pRMci->HSMCI_IER = dwSources;
\r
293 * \brief Disable one or more interrupt sources of MCI peripheral.
\r
295 * \param pRMci Pointer to an Hsmci instance.
\r
296 * \param sources Bitwise OR of selected interrupt sources.
\r
298 extern void HSMCI_DisableIt(Hsmci *pRMci, uint32_t dwSources)
\r
300 pRMci->HSMCI_IDR = dwSources;
\r
304 * \brief Return the interrupt mask register.
\r
306 * \param pRMci Pointer to an Hsmci instance.
\r
307 * \return MCI interrupt mask register.
\r
309 extern uint32_t HSMCI_GetItMask(Hsmci *pRMci)
\r
311 return (pRMci->HSMCI_IMR) ;
\r
315 * \brief Set block len & count for transfer
\r
317 * \param pRMci Pointer to an Hsmci instance.
\r
318 * \param wBlkLen Block size.
\r
319 * \param wCnt Block(byte) count.
\r
321 extern void HSMCI_ConfigureTransfer(Hsmci *pRMci,
\r
325 pRMci->HSMCI_BLKR = (wBlkLen << 16) | wCnt;
\r
329 * \brief Set block length
\r
331 * Count is reset to 0.
\r
333 * \param pRMci Pointer to an Hsmci instance.
\r
334 * \param wBlkSize Block size.
\r
336 extern void HSMCI_SetBlockLen(Hsmci *pRMci, uint16_t wBlkSize)
\r
338 pRMci->HSMCI_BLKR = wBlkSize << 16;
\r
342 * \brief Set block (byte) count
\r
344 * \param pRMci Pointer to an Hsmci instance.
\r
345 * \param wBlkCnt Block(byte) count.
\r
347 extern void HSMCI_SetBlockCount(Hsmci *pRMci, uint16_t wBlkCnt)
\r
349 pRMci->HSMCI_BLKR |= wBlkCnt;
\r
353 * \brief Configure the Completion Signal Timeout
\r
355 * \param pRMci Pointer to an Hsmci instance.
\r
356 * \param dwConfigure Completion Signal Timeout configure.
\r
358 extern void HSMCI_ConfigureCompletionTO(Hsmci *pRMci, uint32_t dwConfigure)
\r
360 pRMci->HSMCI_CSTOR = dwConfigure;
\r
364 * \brief Configure the Data Timeout
\r
366 * \param pRMci Pointer to an Hsmci instance.
\r
367 * \param dwConfigure Data Timeout configure.
\r
369 extern void HSMCI_ConfigureDataTO(Hsmci *pRMci, uint32_t dwConfigure)
\r
371 pRMci->HSMCI_DTOR = dwConfigure;
\r
375 * \brief Send command
\r
377 * \param pRMci Pointer to an Hsmci instance.
\r
378 * \param dwCmd Command register value.
\r
379 * \param dwArg Argument register value.
\r
381 extern void HSMCI_SendCmd(Hsmci *pRMci, uint32_t dwCmd, uint32_t dwArg)
\r
383 pRMci->HSMCI_ARGR = dwArg;
\r
384 pRMci->HSMCI_CMDR = dwCmd;
\r
389 * \brief Return the response register.
\r
391 * \param pRMci Pointer to an Hsmci instance.
\r
392 * \return MCI response register.
\r
394 extern uint32_t HSMCI_GetResponse(Hsmci *pRMci)
\r
396 return pRMci->HSMCI_RSPR[0];
\r
400 * \brief Return the receive data register.
\r
402 * \param pRMci Pointer to an Hsmci instance.
\r
403 * \return MCI receive data register.
\r
405 extern uint32_t HSMCI_Read(Hsmci *pRMci)
\r
407 return pRMci->HSMCI_RDR;
\r
411 * \brief Read from FIFO
\r
413 * \param pRMci Pointer to an Hsmci instance.
\r
414 * \param pdwData Pointer to data buffer.
\r
415 * \param dwSize Size of data buffer (in DWord).
\r
417 extern void HSMCI_ReadFifo(Hsmci *pRMci, uint8_t *pdwData, uint32_t dwSize)
\r
419 volatile uint32_t *pFIFO = (volatile uint32_t*)(pRMci->HSMCI_FIFO);
\r
420 register uint32_t c4, c1;
\r
430 *pdwData ++ = *pFIFO ++;
\r
431 *pdwData ++ = *pFIFO ++;
\r
432 *pdwData ++ = *pFIFO ++;
\r
433 *pdwData ++ = *pFIFO ++;
\r
437 *pdwData ++ = *pFIFO ++;
\r
442 * \brief Sends data through MCI peripheral.
\r
444 * \param pRMci Pointer to an Hsmci instance.
\r
447 extern void HSMCI_Write(Hsmci *pRMci, uint32_t dwData)
\r
449 pRMci->HSMCI_TDR = dwData;
\r
453 * \brief Write to FIFO
\r
455 * \param pRMci Pointer to an Hsmci instance.
\r
456 * \param pdwData Pointer to data buffer.
\r
457 * \param dwSize Size of data buffer (In DWord).
\r
459 extern void HSMCI_WriteFifo(Hsmci *pRMci, uint8_t *pdwData, uint32_t dwSize)
\r
461 volatile uint32_t *pFIFO = (volatile uint32_t*)(pRMci->HSMCI_FIFO);
\r
462 register uint32_t c4, c1;
\r
472 *pFIFO ++ = *pdwData ++;
\r
473 *pFIFO ++ = *pdwData ++;
\r
474 *pFIFO ++ = *pdwData ++;
\r
475 *pFIFO ++ = *pdwData ++;
\r
479 *pFIFO ++ = *pdwData ++;
\r
484 * \brief Return the status register.
\r
486 * \param pRMci Pointer to an Hsmci instance.
\r
487 * \return MCI status register.
\r
489 extern uint32_t HSMCI_GetStatus(Hsmci *pRMci)
\r
491 return pRMci->HSMCI_SR;
\r
495 * \brief Configure the HSMCI DMA
\r
497 * \param pRMci Pointer to an Hsmci instance.
\r
498 * \param dwConfigure Configure value.
\r
500 extern void HSMCI_ConfigureDma(Hsmci *pRMci, uint32_t dwConfigure)
\r
502 pRMci->HSMCI_DMA = dwConfigure;
\r
506 * \brief Enable the HSMCI DMA
\r
508 * \param pRMci Pointer to an Hsmci instance.
\r
509 * \param bEnable 1 to enable, 0 to disable.
\r
511 extern void HSMCI_EnableDma(Hsmci *pRMci, uint8_t bEnable)
\r
515 pRMci->HSMCI_DMA |= HSMCI_DMA_DMAEN ;//| HSMCI_DMA_CHKSIZE_32;
\r
519 pRMci->HSMCI_DMA &= ~HSMCI_DMA_DMAEN;
\r
524 * \brief Configure the HSMCI
\r
526 * \param pRMci Pointer to an Hsmci instance.
\r
527 * \param dwConfigure Configure value.
\r
529 extern void HSMCI_Configure(Hsmci *pRMci, uint32_t dwConfigure)
\r
531 pRMci->HSMCI_CFG = dwConfigure;
\r
535 * \brief Enable/Disable High-Speed mode for MCI
\r
537 * \param pRMci Pointer to an Hsmci instance.
\r
538 * \param bHsEnable Enable/Disable high-speed.
\r
540 extern void HSMCI_HsEnable(Hsmci *pRMci, uint8_t bHsEnable)
\r
544 pRMci->HSMCI_CFG |= HSMCI_CFG_HSMODE;
\r
548 pRMci->HSMCI_CFG &= ~HSMCI_CFG_HSMODE;
\r
553 * \brief Check if High-speed mode is enabled on MCI
\r
554 * \param pRMci Pointer to an Hsmci instance.
\r
557 extern uint8_t HSMCI_IsHsEnabled(Hsmci * pRMci)
\r
559 return ((pRMci->HSMCI_CFG & HSMCI_CFG_HSMODE) > 0);
\r
563 * \brief Configure the Write Protection Mode
\r
565 * \param pRMci Pointer to an Hsmci instance.
\r
566 * \param dwConfigure WP mode configure value.
\r
568 extern void HSMCI_ConfigureWP(Hsmci *pRMci, uint32_t dwConfigure)
\r
570 pRMci->HSMCI_WPMR = dwConfigure;
\r
574 * \brief Return the write protect status register.
\r
576 * \param pRMci Pointer to an Hsmci instance.
\r
577 * \return MCI write protect status register.
\r
579 extern uint32_t HSMCI_GetWPStatus(Hsmci *pRMci)
\r
581 return pRMci->HSMCI_WPSR;
\r