1 /* ----------------------------------------------------------------------------
\r
2 * ATMEL Microcontroller Software Support
\r
3 * ----------------------------------------------------------------------------
\r
4 * Copyright (c) 2008, 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
30 //------------------------------------------------------------------------------
\r
32 //------------------------------------------------------------------------------
\r
35 #include <utility/assert.h>
\r
36 #include <utility/trace.h>
\r
38 //------------------------------------------------------------------------------
\r
40 //------------------------------------------------------------------------------
\r
42 /// Bit mask for status register errors.
\r
43 #define STATUS_ERRORS (AT91C_MCI_UNRE \
\r
53 /// MCI data timeout configuration with 1048576 MCK cycles between 2 data transfers.
\r
54 #define DTOR_1MEGA_CYCLES (AT91C_MCI_DTOCYC | AT91C_MCI_DTOMUL)
\r
56 /// MCI MR: disable MCI Clock when FIFO is full
\r
57 #ifndef AT91C_MCI_WRPROOF
\r
58 #define AT91C_MCI_WRPROOF 0
\r
60 #ifndef AT91C_MCI_RDPROOF
\r
61 #define AT91C_MCI_RDPROOF 0
\r
64 #define SDCARD_APP_OP_COND_CMD (41 | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_TRCMD_NO )
\r
65 #define MMC_SEND_OP_COND_CMD (1 | AT91C_MCI_TRCMD_NO | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_OPDCMD)
\r
68 #define DISABLE 0 // Disable MCI interface
\r
69 #define ENABLE 1 // Enable MCI interface
\r
72 //------------------------------------------------------------------------------
\r
74 //------------------------------------------------------------------------------
\r
76 /// Used to write in PMC registers.
\r
77 #define WRITE_PMC(pPmc, regName, value) pPmc->regName = (value)
\r
79 /// Used to write in MCI registers.
\r
80 #define WRITE_MCI(pMci, regName, value) pMci->regName = (value)
\r
82 /// Used to read from MCI registers.
\r
83 #define READ_MCI(pMci, regName) (pMci->regName)
\r
85 //------------------------------------------------------------------------------
\r
87 //------------------------------------------------------------------------------
\r
89 //------------------------------------------------------------------------------
\r
90 /// Enable/disable a MCI driver instance.
\r
91 /// \param pMci Pointer to a MCI driver instance.
\r
92 /// \param enb 0 for disable MCI and 1 for enable MCI.
\r
93 //------------------------------------------------------------------------------
\r
94 void MCI_Enable(Mci *pMci, unsigned char enb)
\r
96 AT91S_MCI *pMciHw = pMci->pMciHw;
\r
99 SANITY_CHECK(pMci->pMciHw);
\r
101 // Set the Control Register: Enable/Disable MCI interface clock
\r
102 if(enb == DISABLE) {
\r
103 WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIDIS);
\r
106 WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIEN);
\r
110 //------------------------------------------------------------------------------
\r
111 /// Initializes a MCI driver instance and the underlying peripheral.
\r
112 /// \param pMci Pointer to a MCI driver instance.
\r
113 /// \param pMciHw Pointer to a MCI peripheral.
\r
114 /// \param mciId MCI peripheral identifier.
\r
115 /// \param mode Slot and type of connected card.
\r
116 //------------------------------------------------------------------------------
\r
120 unsigned char mciId,
\r
123 unsigned short clkDiv;
\r
125 SANITY_CHECK(pMci);
\r
126 SANITY_CHECK(pMciHw);
\r
127 SANITY_CHECK((mode == MCI_MMC_SLOTA) || (mode == MCI_MMC_SLOTB)
\r
128 || (mode == MCI_SD_SLOTA) || (mode == MCI_SD_SLOTB));
\r
130 // Initialize the MCI driver structure
\r
131 pMci->pMciHw = pMciHw;
\r
132 pMci->mciId = mciId;
\r
133 pMci->semaphore = 1;
\r
134 pMci->pCommand = 0;
\r
136 // Enable the MCI clock
\r
137 WRITE_PMC(AT91C_BASE_PMC, PMC_PCER, (1 << mciId));
\r
140 WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_SWRST);
\r
143 WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIDIS | AT91C_MCI_PWSDIS);
\r
145 // Disable all the interrupts
\r
146 WRITE_MCI(pMciHw, MCI_IDR, 0xFFFFFFFF);
\r
148 // Set the Data Timeout Register
\r
149 WRITE_MCI(pMciHw, MCI_DTOR, DTOR_1MEGA_CYCLES);
\r
151 // Set the Mode Register: 400KHz for MCK = 48MHz (CLKDIV = 58)
\r
152 clkDiv = (BOARD_MCK / (400000 * 2)) - 1;
\r
153 WRITE_MCI(pMciHw, MCI_MR, (clkDiv | (AT91C_MCI_PWSDIV & (0x7 << 8))));
\r
155 // Set the SDCard Register
\r
156 WRITE_MCI(pMciHw, MCI_SDCR, mode);
\r
158 // Enable the MCI and the Power Saving
\r
159 WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIEN);
\r
161 // Disable the MCI peripheral clock.
\r
162 WRITE_PMC(AT91C_BASE_PMC, PMC_PCDR, (1 << mciId));
\r
165 //------------------------------------------------------------------------------
\r
166 /// Close a MCI driver instance and the underlying peripheral.
\r
167 /// \param pMci Pointer to a MCI driver instance.
\r
168 /// \param pMciHw Pointer to a MCI peripheral.
\r
169 /// \param mciId MCI peripheral identifier.
\r
170 //------------------------------------------------------------------------------
\r
171 void MCI_Close(Mci *pMci)
\r
173 AT91S_MCI *pMciHw = pMci->pMciHw;
\r
175 SANITY_CHECK(pMci);
\r
176 SANITY_CHECK(pMciHw);
\r
178 // Initialize the MCI driver structure
\r
179 pMci->semaphore = 1;
\r
180 pMci->pCommand = 0;
\r
182 // Disable the MCI peripheral clock.
\r
183 WRITE_PMC(AT91C_BASE_PMC, PMC_PCDR, (1 << pMci->mciId));
\r
186 WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIDIS);
\r
188 // Disable all the interrupts
\r
189 WRITE_MCI(pMciHw, MCI_IDR, 0xFFFFFFFF);
\r
192 //------------------------------------------------------------------------------
\r
193 /// Configure the MCI CLKDIV in the MCI_MR register. The max. for MCI clock is
\r
194 /// MCK/2 and corresponds to CLKDIV = 0
\r
195 /// \param pMci Pointer to the low level MCI driver.
\r
196 /// \param mciSpeed MCI clock speed in Hz.
\r
197 //------------------------------------------------------------------------------
\r
198 void MCI_SetSpeed(Mci *pMci, unsigned int mciSpeed)
\r
200 AT91S_MCI *pMciHw = pMci->pMciHw;
\r
201 unsigned int mciMr;
\r
202 unsigned int clkdiv;
\r
204 SANITY_CHECK(pMci);
\r
205 SANITY_CHECK(pMci->pMciHw);
\r
207 // Set the Mode Register: 400KHz for MCK = 48MHz (CLKDIV = 58)
\r
208 mciMr = READ_MCI(pMciHw, MCI_MR) & (~AT91C_MCI_CLKDIV);
\r
210 // Multimedia Card Interface clock (MCCK or MCI_CK) is Master Clock (MCK)
\r
211 // divided by (2*(CLKDIV+1))
\r
212 if (mciSpeed > 0) {
\r
214 clkdiv = (BOARD_MCK / (mciSpeed * 2));
\r
219 ASSERT( (clkdiv & 0xFFFFFF00) == 0, "mciSpeed too small");
\r
226 WRITE_MCI(pMciHw, MCI_MR, mciMr | clkdiv);
\r
229 //------------------------------------------------------------------------------
\r
230 /// Configure the MCI SDCBUS in the MCI_SDCR register. Only two modes available
\r
232 /// \param pMci Pointer to the low level MCI driver.
\r
233 /// \param busWidth MCI bus width mode.
\r
234 //------------------------------------------------------------------------------
\r
235 void MCI_SetBusWidth(Mci *pMci, unsigned char busWidth)
\r
237 AT91S_MCI *pMciHw = pMci->pMciHw;
\r
238 unsigned int mciSdcr;
\r
240 SANITY_CHECK(pMci);
\r
241 SANITY_CHECK(pMci->pMciHw);
\r
243 mciSdcr = (READ_MCI(pMciHw, MCI_SDCR) & ~(AT91C_MCI_SCDBUS));
\r
245 WRITE_MCI(pMciHw, MCI_SDCR, mciSdcr | busWidth);
\r
248 //------------------------------------------------------------------------------
\r
249 /// Starts a MCI transfer. This is a non blocking function. It will return
\r
250 /// as soon as the transfer is started.
\r
251 /// Return 0 if successful; otherwise returns MCI_ERROR_LOCK if the driver is
\r
252 /// already in use.
\r
253 /// \param pMci Pointer to an MCI driver instance.
\r
254 /// \param pCommand Pointer to the command to execute.
\r
255 //------------------------------------------------------------------------------
\r
256 unsigned char MCI_SendCommand(Mci *pMci, MciCmd *pCommand)
\r
258 AT91PS_MCI pMciHw = pMci->pMciHw;
\r
259 unsigned int mciIer, mciMr;
\r
261 SANITY_CHECK(pMci);
\r
262 SANITY_CHECK(pMciHw);
\r
263 SANITY_CHECK(pCommand);
\r
265 // Try to acquire the MCI semaphore
\r
266 if (pMci->semaphore == 0) {
\r
268 return MCI_ERROR_LOCK;
\r
271 // TRACE_DEBUG("MCI_SendCommand %x %d\n\r", READ_MCI(pMciHw, MCI_SR), pCommand->cmd & 0x3f);
\r
273 // Command is now being executed
\r
274 pMci->pCommand = pCommand;
\r
275 pCommand->status = MCI_STATUS_PENDING;
\r
277 // Enable the MCI clock
\r
278 WRITE_PMC(AT91C_BASE_PMC, PMC_PCER, (1 << pMci->mciId));
\r
280 //Disable MCI clock, for multi-block data transfer
\r
281 MCI_Enable(pMci, DISABLE);
\r
283 // Set PDC data transfer direction
\r
284 if(pCommand->blockSize > 0) {
\r
285 if(pCommand->isRead) {
\r
286 WRITE_MCI(pMciHw, MCI_PTCR, AT91C_PDC_RXTEN);
\r
289 WRITE_MCI(pMciHw, MCI_PTCR, AT91C_PDC_TXTEN);
\r
292 // Disable transmitter and receiver
\r
293 WRITE_MCI(pMciHw, MCI_PTCR, AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS);
\r
295 mciMr = READ_MCI(pMciHw, MCI_MR) & (~(AT91C_MCI_WRPROOF|AT91C_MCI_RDPROOF|AT91C_MCI_BLKLEN | AT91C_MCI_PDCMODE));
\r
297 // Command with DATA stage
\r
298 if (pCommand->blockSize > 0) {
\r
299 // Enable PDC mode and set block size
\r
300 if(pCommand->conTrans != MCI_CONTINUE_TRANSFER) {
\r
302 WRITE_MCI(pMciHw, MCI_MR, mciMr | AT91C_MCI_PDCMODE |AT91C_MCI_RDPROOF|AT91C_MCI_WRPROOF|(pCommand->blockSize << 16));
\r
305 // DATA transfer from card to host
\r
306 if (pCommand->isRead) {
\r
307 WRITE_MCI(pMciHw, MCI_RPR, (int) pCommand->pData);
\r
310 if (pCommand->nbBlock == 0)
\r
311 pCommand->nbBlock = 1;
\r
313 if ((pCommand->blockSize & 0x3) != 0) {
\r
314 WRITE_MCI(pMciHw, MCI_RCR, (pCommand->nbBlock * pCommand->blockSize) / 4 + 1);
\r
317 WRITE_MCI(pMciHw, MCI_RCR, (pCommand->nbBlock * pCommand->blockSize) / 4);
\r
320 WRITE_MCI(pMciHw, MCI_PTCR, AT91C_PDC_RXTEN);
\r
321 mciIer = AT91C_MCI_ENDRX | STATUS_ERRORS;
\r
322 // mciIer = AT91C_MCI_RXBUFF | STATUS_ERRORS;
\r
325 // DATA transfer from host to card
\r
328 if (pCommand->nbBlock == 0)
\r
329 pCommand->nbBlock = 1;
\r
330 WRITE_MCI(pMciHw, MCI_TPR, (int) pCommand->pData);
\r
331 // Update the PDC counter
\r
332 if ((pCommand->blockSize & 0x3) != 0) {
\r
333 WRITE_MCI(pMciHw, MCI_TCR, (pCommand->nbBlock * pCommand->blockSize) / 4 + 1);
\r
336 WRITE_MCI(pMciHw, MCI_TCR, (pCommand->nbBlock * pCommand->blockSize) / 4);
\r
338 // MCI_BLKE notifies the end of Multiblock command
\r
339 mciIer = AT91C_MCI_BLKE | STATUS_ERRORS;
\r
342 // No data transfer: stop at the end of the command
\r
344 WRITE_MCI(pMciHw, MCI_MR, mciMr);
\r
345 mciIer = AT91C_MCI_CMDRDY | STATUS_ERRORS;
\r
347 // Enable MCI clock
\r
348 MCI_Enable(pMci, ENABLE);
\r
350 // Send the command
\r
351 if((pCommand->conTrans != MCI_CONTINUE_TRANSFER)
\r
352 || (pCommand->blockSize == 0)) {
\r
354 WRITE_MCI(pMciHw, MCI_ARGR, pCommand->arg);
\r
355 WRITE_MCI(pMciHw, MCI_CMDR, pCommand->cmd);
\r
358 // In case of transmit, the PDC shall be enabled after sending the command
\r
359 if ((pCommand->blockSize > 0) && !(pCommand->isRead)) {
\r
360 WRITE_MCI(pMciHw, MCI_PTCR, AT91C_PDC_TXTEN);
\r
363 // Ignore data error
\r
364 mciIer &= ~(AT91C_MCI_UNRE | AT91C_MCI_OVRE \
\r
365 | AT91C_MCI_DTOE | AT91C_MCI_DCRCE);
\r
367 // Interrupt enable shall be done after PDC TXTEN and RXTEN
\r
368 WRITE_MCI(pMciHw, MCI_IER, mciIer);
\r
373 //------------------------------------------------------------------------------
\r
374 /// Check NOTBUSY and DTIP bits of status register on the given MCI driver.
\r
375 /// Return value, 0 for bus ready, 1 for bus busy
\r
376 /// \param pMci Pointer to a MCI driver instance.
\r
377 //------------------------------------------------------------------------------
\r
378 unsigned char MCI_CheckBusy(Mci *pMci)
\r
380 AT91S_MCI *pMciHw = pMci->pMciHw;
\r
381 unsigned int status;
\r
383 // Enable MCI clock
\r
384 MCI_Enable(pMci, ENABLE);
\r
386 status = READ_MCI(pMciHw, MCI_SR);
\r
387 // TRACE_DEBUG("status %x\n\r",status);
\r
390 if(((status & AT91C_MCI_NOTBUSY)!=0)
\r
391 && ((status & AT91C_MCI_DTIP)==0)) {
\r
393 // Disable MCI clock
\r
394 MCI_Enable(pMci, DISABLE);
\r
403 //------------------------------------------------------------------------------
\r
404 /// Check BLKE bit of status register on the given MCI driver.
\r
405 /// \param pMci Pointer to a MCI driver instance.
\r
406 //------------------------------------------------------------------------------
\r
407 unsigned char MCI_CheckBlke(Mci *pMci)
\r
409 AT91S_MCI *pMciHw = pMci->pMciHw;
\r
410 unsigned int status;
\r
412 status = READ_MCI(pMciHw, MCI_SR);
\r
413 // TRACE_DEBUG("status %x\n\r",status);
\r
415 if((status & AT91C_MCI_BLKE)!=0) {
\r
423 //------------------------------------------------------------------------------
\r
424 /// Processes pending events on the given MCI driver.
\r
425 /// \param pMci Pointer to a MCI driver instance.
\r
426 //------------------------------------------------------------------------------
\r
427 void MCI_Handler(Mci *pMci)
\r
429 AT91S_MCI *pMciHw = pMci->pMciHw;
\r
430 MciCmd *pCommand = pMci->pCommand;
\r
431 unsigned int status;
\r
433 #if defined(at91rm9200)
\r
434 unsigned int mciCr, mciSdcr, mciMr, mciDtor;
\r
437 SANITY_CHECK(pMci);
\r
438 SANITY_CHECK(pMciHw);
\r
439 SANITY_CHECK(pCommand);
\r
441 // Read the status register
\r
442 status = READ_MCI(pMciHw, MCI_SR) & READ_MCI(pMciHw, MCI_IMR);
\r
443 // TRACE_DEBUG("status %x\n\r", status);
\r
445 // Check if an error has occured
\r
446 if ((status & STATUS_ERRORS) != 0) {
\r
448 // Check error code
\r
449 if ((status & STATUS_ERRORS) == AT91C_MCI_RTOE) {
\r
451 pCommand->status = MCI_STATUS_NORESPONSE;
\r
453 // if the command is SEND_OP_COND the CRC error flag is always present
\r
454 // (cf : R3 response)
\r
455 else if (((status & STATUS_ERRORS) != AT91C_MCI_RCRCE)
\r
456 || ((pCommand->cmd != SDCARD_APP_OP_COND_CMD)
\r
457 && (pCommand->cmd != MMC_SEND_OP_COND_CMD))) {
\r
459 pCommand->status = MCI_STATUS_ERROR;
\r
463 // Check if a transfer has been completed
\r
464 if (((status & AT91C_MCI_CMDRDY) != 0)
\r
465 || ((status & AT91C_MCI_ENDRX) != 0)
\r
466 || ((status & AT91C_MCI_RXBUFF) != 0)
\r
467 || ((status & AT91C_MCI_ENDTX) != 0)
\r
468 || ((status & AT91C_MCI_BLKE) != 0)
\r
469 || ((status & AT91C_MCI_RTOE) != 0)) {
\r
471 if (((status & AT91C_MCI_ENDRX) != 0)
\r
472 || ((status & AT91C_MCI_RXBUFF) != 0)
\r
473 || ((status & AT91C_MCI_ENDTX) != 0)) {
\r
475 MCI_Enable(pMci, DISABLE);
\r
478 /// On AT91RM9200-EK, if stop transmission, software reset MCI.
\r
479 #if defined(at91rm9200)
\r
480 if ((pCommand->cmd & AT91C_MCI_TRCMD_STOP) != 0) {
\r
481 mciMr = READ_MCI(pMciHw, MCI_MR);
\r
482 mciSdcr = READ_MCI(pMciHw, MCI_SDCR);
\r
483 mciDtor = READ_MCI(pMciHw, MCI_DTOR);
\r
484 WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_SWRST);
\r
485 // TRACE_DEBUG("reset MCI\n\r");
\r
487 WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIDIS | AT91C_MCI_PWSDIS);
\r
488 WRITE_MCI(pMciHw, MCI_MR, mciMr);
\r
489 WRITE_MCI(pMciHw, MCI_SDCR, mciSdcr);
\r
490 WRITE_MCI(pMciHw, MCI_DTOR, mciDtor);
\r
494 // If no error occured, the transfer is successful
\r
495 if (pCommand->status == MCI_STATUS_PENDING) {
\r
496 pCommand->status = 0;
\r
499 if ((status & AT91C_MCI_CMDRDY) != 0)
\r
500 TRACE_DEBUG_WP(".");
\r
501 if ((status & AT91C_MCI_ENDRX) != 0)
\r
502 TRACE_DEBUG_WP("<");
\r
503 if ((status & AT91C_MCI_ENDTX) != 0)
\r
504 TRACE_DEBUG_WP("-");
\r
505 if ((status & AT91C_MCI_BLKE) != 0)
\r
506 TRACE_DEBUG_WP(">");
\r
507 TRACE_DEBUG_WP("\n\r");
\r
509 // Store the card response in the provided buffer
\r
510 if (pCommand->pResp) {
\r
511 unsigned char resSize;
\r
513 switch (pCommand->resType) {
\r
546 for (i=0; i < resSize; i++) {
\r
548 pCommand->pResp[i] = READ_MCI(pMciHw, MCI_RSPR[0]);
\r
552 // Disable interrupts
\r
553 WRITE_MCI(pMciHw, MCI_IDR, READ_MCI(pMciHw, MCI_IMR));
\r
555 // Release the semaphore
\r
558 // Invoke the callback associated with the current command (if any)
\r
559 if (pCommand->callback) {
\r
560 (pCommand->callback)(pCommand->status, pCommand);
\r
565 //------------------------------------------------------------------------------
\r
566 /// Returns 1 if the given MCI transfer is complete; otherwise returns 0.
\r
567 /// \param pCommand Pointer to a MciCmd instance.
\r
568 //------------------------------------------------------------------------------
\r
569 unsigned char MCI_IsTxComplete(MciCmd *pCommand)
\r
571 if (pCommand->status != MCI_STATUS_PENDING) {
\r
572 if (pCommand->status != 0) {
\r
573 TRACE_DEBUG("MCI_IsTxComplete %d\n\r", pCommand->status);
\r