1 /* ----------------------------------------------------------------------------
\r
2 * ATMEL Microcontroller Software Support - ROUSSET -
\r
3 * ----------------------------------------------------------------------------
\r
4 * Copyright (c) 2006, 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 * - Redistributions in binary form must reproduce the above copyright notice,
\r
15 * this list of conditions and the disclaimer below in the documentation and/or
\r
16 * other materials provided with the distribution.
\r
18 * Atmel's name may not be used to endorse or promote products derived from
\r
19 * this software without specific prior written permission.
\r
21 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
\r
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
\r
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
\r
24 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
\r
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
\r
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
\r
27 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
\r
28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
\r
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
\r
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
31 * ----------------------------------------------------------------------------
\r
34 //------------------------------------------------------------------------------
\r
36 //------------------------------------------------------------------------------
\r
39 #include <utility/assert.h>
\r
40 #include <utility/trace.h>
\r
42 //------------------------------------------------------------------------------
\r
44 //------------------------------------------------------------------------------
\r
46 /// Bit mask for status register errors.
\r
47 #define STATUS_ERRORS (AT91C_MCI_UNRE \
\r
57 /// MCI data timeout configuration with 1048576 MCK cycles between 2 data transfers.
\r
58 #define DTOR_1MEGA_CYCLES (AT91C_MCI_DTOCYC | AT91C_MCI_DTOMUL)
\r
60 #define SDCARD_APP_OP_COND_CMD (41 | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_TRCMD_NO )
\r
61 #define MMC_SEND_OP_COND_CMD (1 | AT91C_MCI_TRCMD_NO | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_OPDCMD)
\r
64 #define DISABLE 0 // Disable MCI interface
\r
65 #define ENABLE 1 // Enable MCI interface
\r
68 //------------------------------------------------------------------------------
\r
70 //------------------------------------------------------------------------------
\r
72 /// Used to write in PMC registers.
\r
73 #define WRITE_PMC(pPmc, regName, value) pPmc->regName = (value)
\r
75 /// Used to write in MCI registers.
\r
76 #define WRITE_MCI(pMci, regName, value) pMci->regName = (value)
\r
78 /// Used to read from MCI registers.
\r
79 #define READ_MCI(pMci, regName) (pMci->regName)
\r
81 //------------------------------------------------------------------------------
\r
83 //------------------------------------------------------------------------------
\r
85 //------------------------------------------------------------------------------
\r
86 /// Enable/disable a MCI driver instance.
\r
87 /// \param pMci Pointer to a MCI driver instance.
\r
88 /// \param enb 0 for disable MCI and 1 for enable MCI.
\r
89 //------------------------------------------------------------------------------
\r
90 void MCI_Enable(Mci *pMci, unsigned char enb)
\r
92 AT91S_MCI *pMciHw = pMci->pMciHw;
\r
95 SANITY_CHECK(pMci->pMciHw);
\r
97 // Set the Control Register: Enable/Disable MCI interface clock
\r
98 if(enb == DISABLE) {
\r
99 WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIDIS);
\r
102 WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIEN);
\r
106 //------------------------------------------------------------------------------
\r
107 /// Initializes a MCI driver instance and the underlying peripheral.
\r
108 /// \param pMci Pointer to a MCI driver instance.
\r
109 /// \param pMciHw Pointer to a MCI peripheral.
\r
110 /// \param mciId MCI peripheral identifier.
\r
111 /// \param mode Slot and type of connected card.
\r
112 //------------------------------------------------------------------------------
\r
116 unsigned char mciId,
\r
119 unsigned short clkDiv;
\r
121 SANITY_CHECK(pMci);
\r
122 SANITY_CHECK(pMciHw);
\r
123 SANITY_CHECK((mode == MCI_MMC_SLOTA) || (mode == MCI_MMC_SLOTB)
\r
124 || (mode == MCI_SD_SLOTA) || (mode == MCI_SD_SLOTB));
\r
126 // Initialize the MCI driver structure
\r
127 pMci->pMciHw = pMciHw;
\r
128 pMci->mciId = mciId;
\r
129 pMci->semaphore = 1;
\r
130 pMci->pCommand = 0;
\r
132 // Enable the MCI clock
\r
133 WRITE_PMC(AT91C_BASE_PMC, PMC_PCER, (1 << mciId));
\r
136 WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_SWRST);
\r
139 WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIDIS | AT91C_MCI_PWSDIS);
\r
141 // Disable all the interrupts
\r
142 WRITE_MCI(pMciHw, MCI_IDR, 0xFFFFFFFF);
\r
144 // Set the Data Timeout Register
\r
145 WRITE_MCI(pMciHw, MCI_DTOR, DTOR_1MEGA_CYCLES);
\r
147 // Set the Mode Register: 400KHz for MCK = 48MHz (CLKDIV = 58)
\r
148 clkDiv = (BOARD_MCK / (400000 * 2)) - 1;
\r
149 WRITE_MCI(pMciHw, MCI_MR, (clkDiv | (AT91C_MCI_PWSDIV & (0x7 << 8))));
\r
151 // Set the SDCard Register
\r
152 WRITE_MCI(pMciHw, MCI_SDCR, mode);
\r
154 // Enable the MCI and the Power Saving
\r
155 WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIEN);
\r
157 // Disable the MCI peripheral clock.
\r
158 WRITE_PMC(AT91C_BASE_PMC, PMC_PCDR, (1 << mciId));
\r
161 //------------------------------------------------------------------------------
\r
162 /// Close a MCI driver instance and the underlying peripheral.
\r
163 /// \param pMci Pointer to a MCI driver instance.
\r
164 /// \param pMciHw Pointer to a MCI peripheral.
\r
165 /// \param mciId MCI peripheral identifier.
\r
166 //------------------------------------------------------------------------------
\r
167 void MCI_Close(Mci *pMci)
\r
169 AT91S_MCI *pMciHw = pMci->pMciHw;
\r
171 SANITY_CHECK(pMci);
\r
172 SANITY_CHECK(pMciHw);
\r
174 // Initialize the MCI driver structure
\r
175 pMci->semaphore = 1;
\r
176 pMci->pCommand = 0;
\r
178 // Disable the MCI peripheral clock.
\r
179 WRITE_PMC(AT91C_BASE_PMC, PMC_PCDR, (1 << pMci->mciId));
\r
182 WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIDIS);
\r
184 // Disable all the interrupts
\r
185 WRITE_MCI(pMciHw, MCI_IDR, 0xFFFFFFFF);
\r
188 //------------------------------------------------------------------------------
\r
189 /// Configure the MCI CLKDIV in the MCI_MR register. The max. for MCI clock is
\r
190 /// MCK/2 and corresponds to CLKDIV = 0
\r
191 /// \param pMci Pointer to the low level MCI driver.
\r
192 /// \param mciSpeed MCI clock speed in Hz.
\r
193 //------------------------------------------------------------------------------
\r
194 void MCI_SetSpeed(Mci *pMci, unsigned int mciSpeed)
\r
196 AT91S_MCI *pMciHw = pMci->pMciHw;
\r
197 unsigned int mciMr;
\r
198 unsigned short clkdiv;
\r
200 SANITY_CHECK(pMci);
\r
201 SANITY_CHECK(pMci->pMciHw);
\r
203 // Set the Mode Register: 400KHz for MCK = 48MHz (CLKDIV = 58)
\r
204 mciMr = READ_MCI(pMciHw, MCI_MR) & (~AT91C_MCI_CLKDIV);
\r
206 // Multimedia Card Interface clock (MCCK or MCI_CK) is Master Clock (MCK)
\r
207 // divided by (2*(CLKDIV+1))
\r
208 if (mciSpeed > 0) {
\r
210 clkdiv = (BOARD_MCK / (mciSpeed * 2));
\r
221 WRITE_MCI(pMciHw, MCI_MR, mciMr | clkdiv);
\r
224 //------------------------------------------------------------------------------
\r
225 /// Configure the MCI SDCBUS in the MCI_SDCR register. Only two modes available
\r
227 /// \param pMci Pointer to the low level MCI driver.
\r
228 /// \param busWidth MCI bus width mode.
\r
229 //------------------------------------------------------------------------------
\r
230 void MCI_SetBusWidth(Mci *pMci, unsigned char busWidth)
\r
232 AT91S_MCI *pMciHw = pMci->pMciHw;
\r
233 unsigned int mciSdcr;
\r
235 SANITY_CHECK(pMci);
\r
236 SANITY_CHECK(pMci->pMciHw);
\r
238 mciSdcr = (READ_MCI(pMciHw, MCI_SDCR) & ~(AT91C_MCI_SCDBUS));
\r
240 WRITE_MCI(pMciHw, MCI_SDCR, mciSdcr | busWidth);
\r
243 //------------------------------------------------------------------------------
\r
244 /// Starts a MCI transfer. This is a non blocking function. It will return
\r
245 /// as soon as the transfer is started.
\r
246 /// Return 0 if successful; otherwise returns MCI_ERROR_LOCK if the driver is
\r
247 /// already in use.
\r
248 /// \param pMci Pointer to an MCI driver instance.
\r
249 /// \param pCommand Pointer to the command to execute.
\r
250 //------------------------------------------------------------------------------
\r
251 unsigned char MCI_SendCommand(Mci *pMci, MciCmd *pCommand)
\r
253 AT91PS_MCI pMciHw = pMci->pMciHw;
\r
254 unsigned int mciIer, mciMr;
\r
256 SANITY_CHECK(pMci);
\r
257 SANITY_CHECK(pMciHw);
\r
258 SANITY_CHECK(pCommand);
\r
260 // Try to acquire the MCI semaphore
\r
261 if (pMci->semaphore == 0) {
\r
263 return MCI_ERROR_LOCK;
\r
266 // trace_LOG(trace_DEBUG, "MCI_SendCommand %x %d\n\r", READ_MCI(pMciHw, MCI_SR), pCommand->cmd & 0x3f);
\r
268 // Command is now being executed
\r
269 pMci->pCommand = pCommand;
\r
270 pCommand->status = MCI_STATUS_PENDING;
\r
272 // Enable the MCI clock
\r
273 WRITE_PMC(AT91C_BASE_PMC, PMC_PCER, (1 << pMci->mciId));
\r
275 //Disable MCI clock, for multi-block data transfer
\r
276 MCI_Enable(pMci, DISABLE);
\r
278 // Set PDC data transfer direction
\r
279 if(pCommand->blockSize > 0) {
\r
280 if(pCommand->isRead) {
\r
281 WRITE_MCI(pMciHw, MCI_PTCR, AT91C_PDC_RXTEN);
\r
284 WRITE_MCI(pMciHw, MCI_PTCR, AT91C_PDC_TXTEN);
\r
287 // Disable transmitter and receiver
\r
288 WRITE_MCI(pMciHw, MCI_PTCR, AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS);
\r
290 mciMr = READ_MCI(pMciHw, MCI_MR) & (~(AT91C_MCI_BLKLEN | AT91C_MCI_PDCMODE));
\r
292 // Command with DATA stage
\r
293 if (pCommand->blockSize > 0) {
\r
294 // Enable PDC mode and set block size
\r
295 if(pCommand->conTrans != MCI_CONTINUE_TRANSFER) {
\r
297 WRITE_MCI(pMciHw, MCI_MR, mciMr | AT91C_MCI_PDCMODE | (pCommand->blockSize << 16));
\r
300 // DATA transfer from card to host
\r
301 if (pCommand->isRead) {
\r
302 WRITE_MCI(pMciHw, MCI_RPR, (int) pCommand->pData);
\r
304 // If Multiblock command set the BLKR register
\r
305 /* if (pCommand->nbBlock > 1) {
\r
306 WRITE_MCI(pMciHw, MCI_BLKR, pCommand->nbBlock | (pCommand->blockSize << 16));
\r
309 WRITE_MCI(pMciHw, MCI_BLKR, (pCommand->blockSize << 16));
\r
313 if (pCommand->nbBlock == 0)
\r
314 pCommand->nbBlock = 1;
\r
316 if ((pCommand->blockSize & 0x3) != 0) {
\r
317 WRITE_MCI(pMciHw, MCI_RCR, (pCommand->nbBlock * pCommand->blockSize) / 4 + 1);
\r
320 WRITE_MCI(pMciHw, MCI_RCR, (pCommand->nbBlock * pCommand->blockSize) / 4);
\r
323 WRITE_MCI(pMciHw, MCI_PTCR, AT91C_PDC_RXTEN);
\r
324 mciIer = AT91C_MCI_ENDRX | STATUS_ERRORS;
\r
325 // mciIer = AT91C_MCI_RXBUFF | STATUS_ERRORS;
\r
328 // DATA transfer from host to card
\r
331 if (pCommand->nbBlock == 0)
\r
332 pCommand->nbBlock = 1;
\r
333 WRITE_MCI(pMciHw, MCI_TPR, (int) pCommand->pData);
\r
334 // Update the PDC counter
\r
335 if ((pCommand->blockSize & 0x3) != 0) {
\r
336 WRITE_MCI(pMciHw, MCI_TCR, (pCommand->nbBlock * pCommand->blockSize) / 4 + 1);
\r
339 WRITE_MCI(pMciHw, MCI_TCR, (pCommand->nbBlock * pCommand->blockSize) / 4);
\r
341 // MCI_BLKE notifies the end of Multiblock command
\r
342 mciIer = AT91C_MCI_BLKE | STATUS_ERRORS;
\r
345 // No data transfer: stop at the end of the command
\r
347 WRITE_MCI(pMciHw, MCI_MR, mciMr);
\r
348 mciIer = AT91C_MCI_CMDRDY | STATUS_ERRORS;
\r
350 // Enable MCI clock
\r
351 MCI_Enable(pMci, ENABLE);
\r
353 // Send the command
\r
354 if((pCommand->conTrans != MCI_CONTINUE_TRANSFER)
\r
355 || (pCommand->blockSize == 0)) {
\r
357 WRITE_MCI(pMciHw, MCI_ARGR, pCommand->arg);
\r
358 WRITE_MCI(pMciHw, MCI_CMDR, pCommand->cmd);
\r
361 // In case of transmit, the PDC shall be enabled after sending the command
\r
362 if ((pCommand->blockSize > 0) && !(pCommand->isRead)) {
\r
363 WRITE_MCI(pMciHw, MCI_PTCR, AT91C_PDC_TXTEN);
\r
366 // Ignore data error
\r
367 // if (pCommand->blockSize == 0) {
\r
369 mciIer &= ~(AT91C_MCI_UNRE | AT91C_MCI_OVRE \
\r
370 | AT91C_MCI_DTOE | AT91C_MCI_DCRCE);
\r
373 // Interrupt enable shall be done after PDC TXTEN and RXTEN
\r
374 WRITE_MCI(pMciHw, MCI_IER, mciIer);
\r
379 //------------------------------------------------------------------------------
\r
380 /// Check NOTBUSY and DTIP bits of status register on the given MCI driver.
\r
381 /// Return value, 0 for bus ready, 1 for bus busy
\r
382 /// \param pMci Pointer to a MCI driver instance.
\r
383 //------------------------------------------------------------------------------
\r
384 unsigned char MCI_CheckBusy(Mci *pMci)
\r
386 AT91S_MCI *pMciHw = pMci->pMciHw;
\r
387 unsigned int status;
\r
389 // Enable MCI clock
\r
390 MCI_Enable(pMci, ENABLE);
\r
392 status = READ_MCI(pMciHw, MCI_SR);
\r
393 // trace_LOG(trace_DEBUG, "status %x\n\r",status);
\r
396 if(((status & AT91C_MCI_NOTBUSY)!=0)
\r
397 && ((status & AT91C_MCI_DTIP)==0)) {
\r
399 // Disable MCI clock
\r
400 MCI_Enable(pMci, DISABLE);
\r
409 //------------------------------------------------------------------------------
\r
410 /// Check BLKE bit of status register on the given MCI driver.
\r
411 /// \param pMci Pointer to a MCI driver instance.
\r
412 //------------------------------------------------------------------------------
\r
413 unsigned char MCI_CheckBlke(Mci *pMci)
\r
415 AT91S_MCI *pMciHw = pMci->pMciHw;
\r
416 unsigned int status;
\r
418 status = READ_MCI(pMciHw, MCI_SR);
\r
419 // trace_LOG(trace_DEBUG, "status %x\n\r",status);
\r
421 if((status & AT91C_MCI_BLKE)!=0) {
\r
429 //------------------------------------------------------------------------------
\r
430 /// Processes pending events on the given MCI driver.
\r
431 /// \param pMci Pointer to a MCI driver instance.
\r
432 //------------------------------------------------------------------------------
\r
433 void MCI_Handler(Mci *pMci)
\r
435 AT91S_MCI *pMciHw = pMci->pMciHw;
\r
436 MciCmd *pCommand = pMci->pCommand;
\r
437 unsigned int status;
\r
439 #if defined(at91rm9200)
\r
440 unsigned int mciCr, mciSdcr, mciMr, mciDtor;
\r
443 SANITY_CHECK(pMci);
\r
444 SANITY_CHECK(pMciHw);
\r
445 SANITY_CHECK(pCommand);
\r
447 // Read the status register
\r
448 status = READ_MCI(pMciHw, MCI_SR) & READ_MCI(pMciHw, MCI_IMR);
\r
449 // trace_LOG(trace_DEBUG, "status %x\n\r", status);
\r
451 // Check if an error has occured
\r
452 if ((status & STATUS_ERRORS) != 0) {
\r
454 // Check error code
\r
455 if ((status & STATUS_ERRORS) == AT91C_MCI_RTOE) {
\r
457 pCommand->status = MCI_STATUS_NORESPONSE;
\r
459 // if the command is SEND_OP_COND the CRC error flag is always present
\r
460 // (cf : R3 response)
\r
461 else if (((status & STATUS_ERRORS) != AT91C_MCI_RCRCE)
\r
462 || ((pCommand->cmd != SDCARD_APP_OP_COND_CMD)
\r
463 && (pCommand->cmd != MMC_SEND_OP_COND_CMD))) {
\r
465 pCommand->status = MCI_STATUS_ERROR;
\r
469 // Check if a transfer has been completed
\r
470 if (((status & AT91C_MCI_CMDRDY) != 0)
\r
471 || ((status & AT91C_MCI_ENDRX) != 0)
\r
472 || ((status & AT91C_MCI_RXBUFF) != 0)
\r
473 || ((status & AT91C_MCI_ENDTX) != 0)
\r
474 || ((status & AT91C_MCI_BLKE) != 0)
\r
475 || ((status & AT91C_MCI_RTOE) != 0)) {
\r
477 if (((status & AT91C_MCI_ENDRX) != 0)
\r
478 || ((status & AT91C_MCI_RXBUFF) != 0)
\r
479 || ((status & AT91C_MCI_ENDTX) != 0)) {
\r
481 MCI_Enable(pMci, DISABLE);
\r
484 /// On AT91RM9200-EK, if stop transmission, software reset MCI.
\r
485 #if defined(at91rm9200)
\r
486 if ((pCommand->cmd & AT91C_MCI_TRCMD_STOP) != 0) {
\r
487 mciMr = READ_MCI(pMciHw, MCI_MR);
\r
488 mciSdcr = READ_MCI(pMciHw, MCI_SDCR);
\r
489 mciDtor = READ_MCI(pMciHw, MCI_DTOR);
\r
490 WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_SWRST);
\r
491 // trace_LOG(trace_DEBUG, "reset MCI\n\r");
\r
493 WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIDIS | AT91C_MCI_PWSDIS);
\r
494 WRITE_MCI(pMciHw, MCI_MR, mciMr);
\r
495 WRITE_MCI(pMciHw, MCI_SDCR, mciSdcr);
\r
496 WRITE_MCI(pMciHw, MCI_DTOR, mciDtor);
\r
500 // If no error occured, the transfer is successful
\r
501 if (pCommand->status == MCI_STATUS_PENDING) {
\r
502 pCommand->status = 0;
\r
505 if ((status & AT91C_MCI_CMDRDY) != 0)
\r
506 trace_LOG(trace_DEBUG, ".");
\r
507 if ((status & AT91C_MCI_ENDRX) != 0)
\r
508 trace_LOG(trace_DEBUG, "<");
\r
509 if ((status & AT91C_MCI_ENDTX) != 0)
\r
510 trace_LOG(trace_DEBUG, "-");
\r
511 if ((status & AT91C_MCI_BLKE) != 0)
\r
512 trace_LOG(trace_DEBUG, ">");
\r
513 trace_LOG(trace_DEBUG, "\n\r");
\r
515 // Store the card response in the provided buffer
\r
516 if (pCommand->pResp) {
\r
518 for (i=0; i < pCommand->resSize; i++) {
\r
520 pCommand->pResp[i] = READ_MCI(pMciHw, MCI_RSPR[0]);
\r
524 // Disable interrupts
\r
525 WRITE_MCI(pMciHw, MCI_IDR, READ_MCI(pMciHw, MCI_IMR));
\r
527 // Release the semaphore
\r
530 // Invoke the callback associated with the current command (if any)
\r
531 if (pCommand->callback) {
\r
532 (pCommand->callback)(pCommand->status, pCommand);
\r
537 //------------------------------------------------------------------------------
\r
538 /// Returns 1 if the given MCI transfer is complete; otherwise returns 0.
\r
539 /// \param pCommand Pointer to a MciCmd instance.
\r
540 //------------------------------------------------------------------------------
\r
541 unsigned char MCI_IsTxComplete(MciCmd *pCommand)
\r
543 if (pCommand->status != MCI_STATUS_PENDING) {
\r
544 if (pCommand->status != 0)
\r
545 printf("MCI_IsTxComplete %d\n\r", pCommand->status);
\r