]> git.sur5r.net Git - freertos/blob - 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
1 /* ----------------------------------------------------------------------------\r
2  *         SAM Software Package License \r
3  * ----------------------------------------------------------------------------\r
4  * Copyright (c) 2011, Atmel Corporation\r
5  *\r
6  * All rights reserved.\r
7  *\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
10  *\r
11  * - Redistributions of source code must retain the above copyright notice,\r
12  * this list of conditions and the disclaimer below.\r
13  *\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
16  *\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
28  */\r
29 \r
30 /** \file\r
31  *\r
32  * Implementation of High Speed MultiMedia Card Interface (HSMCI) controller.\r
33  */\r
34 \r
35 /*---------------------------------------------------------------------------\r
36  *         Headers\r
37  *---------------------------------------------------------------------------*/\r
38 \r
39 #include "chip.h"\r
40 #include <assert.h>\r
41 \r
42 /*---------------------------------------------------------------------------\r
43  *         Exported functions\r
44  *---------------------------------------------------------------------------*/\r
45 \r
46 /** \addtogroup hsmci_functions\r
47  *@{\r
48  */\r
49 \r
50 /**\r
51  * \brief Enable Multi-Media Interface\r
52  *\r
53  * \param pRMci Pointer to a Hsmci instance\r
54  */\r
55 extern void HSMCI_Enable(Hsmci* pRMci)\r
56 {\r
57     pRMci->HSMCI_CR = HSMCI_CR_MCIEN;\r
58 }\r
59 \r
60 /**\r
61  * \brief Disable Multi-Media Interface\r
62  *\r
63  * \param pRMci Pointer to a Hsmci instance\r
64  */\r
65 extern void HSMCI_Disable(Hsmci* pRMci)\r
66 {\r
67     pRMci->HSMCI_CR = HSMCI_CR_MCIDIS;\r
68 }\r
69 \r
70 /**\r
71  * \brief Reset (& Disable) Multi-Media Interface\r
72  *\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
76  */\r
77 extern void HSMCI_Reset(Hsmci* pRMci, uint8_t bBackup)\r
78 {\r
79     if (bBackup)\r
80     {\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
87 \r
88         pRMci->HSMCI_CR = HSMCI_CR_SWRST;\r
89 \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
96     }\r
97     else\r
98     {\r
99         pRMci->HSMCI_CR = HSMCI_CR_SWRST;\r
100     }\r
101 }\r
102 \r
103 /**\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
107  */\r
108 extern void HSMCI_Select(Hsmci *pRMci, uint8_t bSlot, uint8_t bBusWidth)\r
109 {\r
110     uint32_t dwSdcr;\r
111     dwSdcr = (HSMCI_SDCR_SDCSEL_Msk & bSlot);\r
112     switch(bBusWidth)\r
113     {\r
114         case 1:\r
115             pRMci->HSMCI_SDCR = dwSdcr | HSMCI_SDCR_SDCBUS_1;\r
116             break;\r
117         case 4:\r
118             pRMci->HSMCI_SDCR = dwSdcr | HSMCI_SDCR_SDCBUS_4;\r
119             break;\r
120         case 8:\r
121             pRMci->HSMCI_SDCR = dwSdcr | HSMCI_SDCR_SDCBUS_8;\r
122             break;\r
123     }\r
124 }\r
125 \r
126 /**\r
127  * \brief Set slot\r
128  * \param pRMci Pointer to a Hsmci instance\r
129  * \param bSlot Slot ID (0~3 for A~D).\r
130  */\r
131 extern void HSMCI_SetSlot(Hsmci *pRMci, uint8_t bSlot)\r
132 {\r
133     uint32_t dwSdcr = pRMci->HSMCI_SDCR & ~HSMCI_SDCR_SDCSEL_Msk;\r
134     pRMci->HSMCI_SDCR = dwSdcr | (HSMCI_SDCR_SDCSEL_Msk & bSlot);\r
135 }\r
136 \r
137 /**\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
141  */\r
142 extern void HSMCI_SetBusWidth(Hsmci * pRMci,uint8_t bBusWidth)\r
143 {\r
144     uint32_t dwSdcr = pRMci->HSMCI_SDCR & ~HSMCI_SDCR_SDCBUS_Msk;\r
145     switch(bBusWidth)\r
146     {\r
147         case 1:\r
148             pRMci->HSMCI_SDCR = dwSdcr | HSMCI_SDCR_SDCBUS_1;\r
149             break;\r
150         case 4:\r
151             pRMci->HSMCI_SDCR = dwSdcr | HSMCI_SDCR_SDCBUS_4;\r
152             break;\r
153         case 8:\r
154             pRMci->HSMCI_SDCR = dwSdcr | HSMCI_SDCR_SDCBUS_8;\r
155             break;\r
156     }\r
157 }\r
158 \r
159 /**\r
160  * \brief Return bus width setting.\r
161  *\r
162  * \param pRMci  Pointer to an MCI instance.\r
163  * \return 1, 4 or 8.\r
164  */\r
165 extern uint8_t HSMCI_GetBusWidth(Hsmci * pRMci)\r
166 {\r
167     switch(pRMci->HSMCI_SDCR & HSMCI_SDCR_SDCBUS_Msk)\r
168     {\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
172     }\r
173     return 0;\r
174 }\r
175 \r
176 /**\r
177  * \brief Configures a MCI peripheral as specified.\r
178  *\r
179  * \param pRMci  Pointer to an MCI instance.\r
180  * \param dwMode Value of the MCI Mode register.\r
181  */\r
182 extern void HSMCI_ConfigureMode(Hsmci *pRMci, uint32_t dwMode)\r
183 {\r
184     pRMci->HSMCI_MR = dwMode;\r
185 }\r
186 \r
187 /**\r
188  * \brief Return mode register\r
189  * \param pRMci  Pointer to an MCI instance.\r
190  */\r
191 extern uint32_t HSMCI_GetMode(Hsmci * pRMci)\r
192 {\r
193     return pRMci->HSMCI_MR;\r
194 }\r
195 \r
196 /**\r
197  * \brief Enable/Disable R/W proof\r
198  *\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
202  */\r
203 extern void HSMCI_ProofEnable(Hsmci *pRMci, uint8_t bRdProof, uint8_t bWrProof)\r
204 {\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
209                     ;\r
210 }\r
211 \r
212 /**\r
213  * \brief Padding value setting.\r
214  *\r
215  * \param pRMci    Pointer to an MCI instance.\r
216  * \param bPadvEn  Padding value 0xFF/0x00.\r
217  */\r
218 extern void HSMCI_PadvCtl(Hsmci *pRMci, uint8_t bPadv)\r
219 {\r
220     if (bPadv)\r
221     {\r
222         pRMci->HSMCI_MR |= HSMCI_MR_PADV;\r
223     }\r
224     else\r
225     {\r
226         pRMci->HSMCI_MR &= ~HSMCI_MR_PADV;\r
227     }\r
228 }\r
229 \r
230 /**\r
231  * \brief Force byte transfer enable/disable.\r
232  *\r
233  * \param pRMci    Pointer to an MCI instance.\r
234  * \param bFByteEn FBYTE enable/disable.\r
235  */\r
236 extern void HSMCI_FByteEnable(Hsmci *pRMci, uint8_t bFByteEn)\r
237 {\r
238     if (bFByteEn)\r
239     {\r
240         pRMci->HSMCI_MR |= HSMCI_MR_FBYTE;\r
241     }\r
242     else\r
243     {\r
244         pRMci->HSMCI_MR &= ~HSMCI_MR_FBYTE;\r
245     }\r
246 }\r
247 \r
248 /**\r
249  * \brief Check if Force Byte mode enabled.\r
250  *\r
251  * \param pRMci    Pointer to an MCI instance.\r
252  * \return 1 if _FBYTE is enabled.\r
253  */\r
254 extern uint8_t HSMCI_IsFByteEnabled(Hsmci *pRMci)\r
255 {\r
256     return ((pRMci->HSMCI_MR & HSMCI_MR_FBYTE) > 0);\r
257 }\r
258 \r
259 /**\r
260  * \brief Set Clock Divider & Power save divider for MCI.\r
261  *\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
265  */\r
266 extern void HSMCI_DivCtrl(Hsmci *pRMci, uint32_t bClkDiv, uint8_t bPwsDiv)\r
267 {\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
273 \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
277                     | clkodd\r
278                     ;\r
279 }\r
280 \r
281 /**\r
282  * \brief Enables one or more interrupt sources of MCI peripheral.\r
283  *\r
284  * \param pRMci   Pointer to an Hsmci instance.\r
285  * \param sources Bitwise OR of selected interrupt sources.\r
286  */\r
287 extern void HSMCI_EnableIt(Hsmci *pRMci, uint32_t dwSources)\r
288 {\r
289     pRMci->HSMCI_IER = dwSources;\r
290 }\r
291 \r
292 /**\r
293  * \brief Disable one or more interrupt sources of MCI peripheral.\r
294  *\r
295  * \param pRMci   Pointer to an Hsmci instance.\r
296  * \param sources Bitwise OR of selected interrupt sources.\r
297  */\r
298 extern void HSMCI_DisableIt(Hsmci *pRMci, uint32_t dwSources)\r
299 {\r
300     pRMci->HSMCI_IDR = dwSources;\r
301 }\r
302 \r
303 /**\r
304  * \brief Return the interrupt mask register.\r
305  *\r
306  * \param pRMci   Pointer to an Hsmci instance.\r
307  * \return MCI interrupt mask register.\r
308  */\r
309 extern uint32_t HSMCI_GetItMask(Hsmci *pRMci)\r
310 {\r
311     return (pRMci->HSMCI_IMR) ;\r
312 }\r
313 \r
314 /**\r
315  * \brief Set block len & count for transfer\r
316  * \r
317  * \param pRMci     Pointer to an Hsmci instance.\r
318  * \param wBlkLen   Block size.\r
319  * \param wCnt      Block(byte) count.\r
320  */\r
321 extern void HSMCI_ConfigureTransfer(Hsmci *pRMci,\r
322                                     uint16_t wBlkLen,\r
323                                     uint16_t wCnt)\r
324 {\r
325     pRMci->HSMCI_BLKR = (wBlkLen << 16) | wCnt;\r
326 }\r
327 \r
328 /**\r
329  * \brief Set block length\r
330  *\r
331  *  Count is reset to 0.\r
332  *\r
333  * \param pRMci     Pointer to an Hsmci instance.\r
334  * \param wBlkSize  Block size.\r
335  */\r
336 extern void HSMCI_SetBlockLen(Hsmci *pRMci, uint16_t wBlkSize)\r
337 {\r
338     pRMci->HSMCI_BLKR = wBlkSize << 16;\r
339 }\r
340 \r
341 /**\r
342  * \brief Set block (byte) count\r
343  *\r
344  * \param pRMci     Pointer to an Hsmci instance.\r
345  * \param wBlkCnt   Block(byte) count.\r
346  */\r
347 extern void HSMCI_SetBlockCount(Hsmci *pRMci, uint16_t wBlkCnt)\r
348 {\r
349     pRMci->HSMCI_BLKR |= wBlkCnt;\r
350 }\r
351 \r
352 /**\r
353  * \brief Configure the Completion Signal Timeout\r
354  *\r
355  * \param pRMci Pointer to an Hsmci instance.\r
356  * \param dwConfigure Completion Signal Timeout configure.\r
357  */\r
358 extern void HSMCI_ConfigureCompletionTO(Hsmci *pRMci, uint32_t dwConfigure)\r
359 {\r
360     pRMci->HSMCI_CSTOR = dwConfigure;\r
361 }\r
362 \r
363 /**\r
364  * \brief Configure the Data Timeout\r
365  *\r
366  * \param pRMci Pointer to an Hsmci instance.\r
367  * \param dwConfigure Data Timeout configure.\r
368  */\r
369 extern void HSMCI_ConfigureDataTO(Hsmci *pRMci, uint32_t dwConfigure)\r
370 {\r
371     pRMci->HSMCI_DTOR = dwConfigure;\r
372 }\r
373 \r
374 /**\r
375  * \brief Send command\r
376  *\r
377  * \param pRMci Pointer to an Hsmci instance.\r
378  * \param dwCmd Command register value.\r
379  * \param dwArg Argument register value.\r
380  */\r
381 extern void HSMCI_SendCmd(Hsmci *pRMci, uint32_t dwCmd, uint32_t dwArg)\r
382 {\r
383     pRMci->HSMCI_ARGR = dwArg;\r
384     pRMci->HSMCI_CMDR = dwCmd;\r
385 }\r
386 \r
387 \r
388 /**\r
389  * \brief Return the response register.\r
390  *\r
391  * \param pRMci   Pointer to an Hsmci instance.\r
392  * \return MCI response register.\r
393  */\r
394 extern uint32_t HSMCI_GetResponse(Hsmci *pRMci)\r
395 {\r
396     return pRMci->HSMCI_RSPR[0];\r
397 }\r
398 \r
399 /**\r
400  * \brief Return the receive data register.\r
401  *\r
402  * \param pRMci   Pointer to an Hsmci instance.\r
403  * \return MCI receive data register.\r
404  */\r
405 extern uint32_t HSMCI_Read(Hsmci *pRMci)\r
406 {\r
407     return pRMci->HSMCI_RDR;\r
408 }\r
409 \r
410 /**\r
411  * \brief Read from FIFO\r
412  *\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
416  */\r
417 extern void HSMCI_ReadFifo(Hsmci *pRMci, uint8_t *pdwData, uint32_t dwSize)\r
418 {\r
419     volatile uint32_t *pFIFO = (volatile uint32_t*)(pRMci->HSMCI_FIFO);\r
420     register uint32_t c4, c1;\r
421 \r
422     if (dwSize == 0)\r
423         return;\r
424 \r
425     c4 = dwSize >> 2;\r
426     c1 = dwSize & 0x3;\r
427 \r
428     for(;c4;c4 --)\r
429     {\r
430         *pdwData ++ = *pFIFO ++;\r
431         *pdwData ++ = *pFIFO ++;\r
432         *pdwData ++ = *pFIFO ++;\r
433         *pdwData ++ = *pFIFO ++;\r
434     }\r
435     for(;c1;c1 --)\r
436     {\r
437         *pdwData ++ = *pFIFO ++;\r
438     }\r
439 }\r
440 \r
441 /**\r
442  * \brief Sends data through MCI peripheral.\r
443  *\r
444  * \param pRMci   Pointer to an Hsmci instance.\r
445  * \param\r
446  */\r
447 extern void HSMCI_Write(Hsmci *pRMci, uint32_t dwData)\r
448 {\r
449     pRMci->HSMCI_TDR = dwData;\r
450 }\r
451 \r
452 /**\r
453  * \brief Write to FIFO\r
454  *\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
458  */\r
459 extern void HSMCI_WriteFifo(Hsmci *pRMci, uint8_t *pdwData, uint32_t dwSize)\r
460 {\r
461     volatile uint32_t *pFIFO = (volatile uint32_t*)(pRMci->HSMCI_FIFO);\r
462     register uint32_t c4, c1;\r
463 \r
464     if (dwSize == 0)\r
465         return;\r
466 \r
467     c4 = dwSize >> 2;\r
468     c1 = dwSize & 0x3;\r
469 \r
470     for(;c4;c4 --)\r
471     {\r
472         *pFIFO ++ = *pdwData ++;\r
473         *pFIFO ++ = *pdwData ++;\r
474         *pFIFO ++ = *pdwData ++;\r
475         *pFIFO ++ = *pdwData ++;\r
476     }\r
477     for(;c1;c1 --)\r
478     {\r
479         *pFIFO ++ = *pdwData ++;\r
480     }\r
481 }\r
482 \r
483 /**\r
484  * \brief Return the status register.\r
485  *\r
486  * \param pRMci   Pointer to an Hsmci instance.\r
487  * \return MCI status register.\r
488  */\r
489 extern uint32_t HSMCI_GetStatus(Hsmci *pRMci)\r
490 {\r
491     return pRMci->HSMCI_SR;\r
492 }\r
493 \r
494 /**\r
495  * \brief Configure the HSMCI DMA\r
496  *  \r
497  * \param pRMci Pointer to an Hsmci instance.\r
498  * \param dwConfigure Configure value. \r
499  */\r
500 extern void HSMCI_ConfigureDma(Hsmci *pRMci, uint32_t dwConfigure)\r
501 {\r
502     pRMci->HSMCI_DMA = dwConfigure;\r
503 }\r
504 \r
505 /**\r
506  * \brief Enable the HSMCI DMA\r
507  *  \r
508  * \param pRMci Pointer to an Hsmci instance.\r
509  * \param bEnable 1 to enable, 0 to disable.\r
510  */\r
511 extern void HSMCI_EnableDma(Hsmci *pRMci, uint8_t bEnable)\r
512 {\r
513     if (bEnable)\r
514     {\r
515         pRMci->HSMCI_DMA |= HSMCI_DMA_DMAEN ;//| HSMCI_DMA_CHKSIZE_32;\r
516     }\r
517     else\r
518     {\r
519         pRMci->HSMCI_DMA &= ~HSMCI_DMA_DMAEN;\r
520     }\r
521 }\r
522 \r
523 /**\r
524  * \brief Configure the HSMCI\r
525  *  \r
526  * \param pRMci   Pointer to an Hsmci instance.\r
527  * \param dwConfigure Configure value. \r
528  */\r
529 extern void HSMCI_Configure(Hsmci *pRMci, uint32_t dwConfigure)\r
530 {\r
531     pRMci->HSMCI_CFG = dwConfigure;\r
532 }\r
533 \r
534 /**\r
535  * \brief Enable/Disable High-Speed mode for MCI\r
536  * \r
537  * \param pRMci Pointer to an Hsmci instance.\r
538  * \param bHsEnable Enable/Disable high-speed.\r
539  */\r
540 extern void HSMCI_HsEnable(Hsmci *pRMci, uint8_t bHsEnable)\r
541 {\r
542     if (bHsEnable)\r
543     {\r
544         pRMci->HSMCI_CFG |= HSMCI_CFG_HSMODE;\r
545     }\r
546     else\r
547     {\r
548         pRMci->HSMCI_CFG &= ~HSMCI_CFG_HSMODE;\r
549     }\r
550 }\r
551 \r
552 /**\r
553  * \brief Check if High-speed mode is enabled on MCI\r
554  * \param pRMci Pointer to an Hsmci instance.\r
555  * \return 1 \r
556  */\r
557 extern uint8_t HSMCI_IsHsEnabled(Hsmci * pRMci)\r
558 {\r
559     return ((pRMci->HSMCI_CFG & HSMCI_CFG_HSMODE) > 0);\r
560 }\r
561 \r
562 /**\r
563  * \brief Configure the Write Protection Mode\r
564  *  \r
565  * \param pRMci   Pointer to an Hsmci instance.\r
566  * \param dwConfigure WP mode configure value. \r
567  */\r
568 extern void HSMCI_ConfigureWP(Hsmci *pRMci, uint32_t dwConfigure)\r
569 {\r
570     pRMci->HSMCI_WPMR = dwConfigure;\r
571 }\r
572 \r
573 /**\r
574  * \brief Return the write protect status register.\r
575  *\r
576  * \param pRMci   Pointer to an Hsmci instance.\r
577  * \return MCI write protect status register.\r
578  */\r
579 extern uint32_t HSMCI_GetWPStatus(Hsmci *pRMci)\r
580 {\r
581     return pRMci->HSMCI_WPSR;\r
582 }\r
583 \r
584 /**@}*/\r
585 \r