1/*- 2 * Copyright (c) 2006 M. Warner Losh. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * 24 * This software is derived from software provide by Kwikbyte who specifically 25 * disclaimed copyright on the code. 26 * 27 * $FreeBSD$ 28 */ 29 30//*---------------------------------------------------------------------------- 31//* ATMEL Microcontroller Software Support - ROUSSET - 32//*---------------------------------------------------------------------------- 33//* The software is delivered "AS IS" without warranty or condition of any 34//* kind, either express, implied or statutory. This includes without 35//* limitation any warranty or condition with respect to merchantability or 36//* fitness for any particular purpose, or against the infringements of 37//* intellectual property rights of others. 38//*---------------------------------------------------------------------------- 39//* File Name : main.c 40//* Object : main application written in C 41//* Creation : FB 21/11/2002 42//* 43//*---------------------------------------------------------------------------- 44#include "at91rm9200.h" 45#include "lib_AT91RM9200.h" 46#include "mci_device.h" 47#include "lib.h" 48#include "sd-card.h" 49 50#define AT91C_MCI_TIMEOUT 1000000 /* For AT91F_MCIDeviceWaitReady */ 51#define BUFFER_SIZE_MCI_DEVICE 512 52#define MASTER_CLOCK 60000000 53 54//* Global Variables 55AT91S_MciDevice MCI_Device; 56char Buffer[BUFFER_SIZE_MCI_DEVICE]; 57 58/****************************************************************************** 59**Error return codes 60******************************************************************************/ 61#define MCI_UNSUPP_SIZE_ERROR 5 62#define MCI_UNSUPP_OFFSET_ERROR 6 63 64//*---------------------------------------------------------------------------- 65//* \fn MCIDeviceWaitReady 66//* \brief Wait for MCI Device ready 67//*---------------------------------------------------------------------------- 68static void 69MCIDeviceWaitReady(unsigned int timeout) 70{ 71 volatile int status; 72 73 do 74 { 75 status = AT91C_BASE_MCI->MCI_SR; 76 timeout--; 77 } 78 while( !(status & AT91C_MCI_NOTBUSY) && (timeout>0) ); 79 80 status = AT91C_BASE_MCI->MCI_SR; 81 82 // If End of Tx Buffer Empty interrupt occurred 83 if (MCI_Device.state == AT91C_MCI_TX_SINGLE_BLOCK && status & AT91C_MCI_TXBUFE) { 84 AT91C_BASE_MCI->MCI_IDR = AT91C_MCI_TXBUFE; 85 AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_TXTDIS; 86 MCI_Device.state = AT91C_MCI_IDLE; 87 } // End of if AT91C_MCI_TXBUFF 88 89 // If End of Rx Buffer Full interrupt occurred 90 if (MCI_Device.state == AT91C_MCI_RX_SINGLE_BLOCK && status & AT91C_MCI_RXBUFF) { 91 AT91C_BASE_MCI->MCI_IDR = AT91C_MCI_RXBUFF; 92 AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_RXTDIS; 93 MCI_Device.state = AT91C_MCI_IDLE; 94 } // End of if AT91C_MCI_RXBUFF 95} 96 97static inline unsigned int 98swap(unsigned int a) 99{ 100 return (((a & 0xff) << 24) | ((a & 0xff00) << 8) | ((a & 0xff0000) >> 8) 101 | ((a & 0xff000000) >> 24)); 102} 103 104static inline void 105wait_ready() 106{ 107 int status; 108 109 // wait for CMDRDY Status flag to read the response 110 do 111 { 112 status = AT91C_BASE_MCI->MCI_SR; 113 } while( !(status & AT91C_MCI_CMDRDY) ); 114} 115 116//*---------------------------------------------------------------------------- 117//* \fn MCI_SendCommand 118//* \brief Generic function to send a command to the MMC or SDCard 119//*---------------------------------------------------------------------------- 120static int 121MCI_SendCommand( 122 unsigned int Cmd, 123 unsigned int Arg) 124{ 125 unsigned int error; 126 127 AT91C_BASE_MCI->MCI_ARGR = Arg; 128 AT91C_BASE_MCI->MCI_CMDR = Cmd; 129 130// printf("CMDR %x ARG %x\n", Cmd, Arg); 131 wait_ready(); 132 // Test error ==> if crc error and response R3 ==> don't check error 133 error = (AT91C_BASE_MCI->MCI_SR) & AT91C_MCI_SR_ERROR; 134 if (error != 0) { 135 if (error != AT91C_MCI_RCRCE) 136 return (1); 137 } 138 return 0; 139} 140 141//*---------------------------------------------------------------------------- 142//* \fn MCI_GetStatus 143//* \brief Addressed card sends its status register 144//*---------------------------------------------------------------------------- 145static unsigned int 146MCI_GetStatus() 147{ 148 if (MCI_SendCommand(SEND_STATUS_CMD, MCI_Device.RCA << 16)) 149 return AT91C_CMD_SEND_ERROR; 150 return (AT91C_BASE_MCI->MCI_RSPR[0]); 151} 152 153//*---------------------------------------------------------------------------- 154//* \fn MCI_ReadBlock 155//* \brief Read an ENTIRE block or PARTIAL block 156//*---------------------------------------------------------------------------- 157static int 158MCI_ReadBlock(int src, unsigned int *dataBuffer, int sizeToRead) 159{ 160// unsigned log2sl = MCI_Device.READ_BL_LEN; 161// unsigned sectorLength = 1 << log2sl; 162 unsigned sectorLength = 512; 163 164 /////////////////////////////////////////////////////////////////////// 165 if (MCI_Device.state != AT91C_MCI_IDLE) 166 return 1; 167 168 if ((MCI_GetStatus() & AT91C_SR_READY_FOR_DATA) == 0) 169 return 1; 170 171 /////////////////////////////////////////////////////////////////////// 172 173 // Init Mode Register 174 AT91C_BASE_MCI->MCI_MR |= ((sectorLength << 16) | AT91C_MCI_PDCMODE); 175 176 sizeToRead = sizeToRead / 4; 177 178 AT91C_BASE_PDC_MCI->PDC_PTCR = (AT91C_PDC_TXTDIS | AT91C_PDC_RXTDIS); 179 AT91C_BASE_PDC_MCI->PDC_RPR = (unsigned int)dataBuffer; 180 AT91C_BASE_PDC_MCI->PDC_RCR = sizeToRead; 181 182 // Send the Read single block command 183 if (MCI_SendCommand(READ_SINGLE_BLOCK_CMD, src)) 184 return AT91C_READ_ERROR; 185 MCI_Device.state = AT91C_MCI_RX_SINGLE_BLOCK; 186 187 // Enable AT91C_MCI_RXBUFF Interrupt 188 AT91C_BASE_MCI->MCI_IER = AT91C_MCI_RXBUFF; 189 190 // (PDC) Receiver Transfer Enable 191 AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_RXTEN; 192 193 return 0; 194} 195 196int 197MCI_read(char* dest, unsigned source, unsigned length) 198{ 199// unsigned log2sl = MCI_Device.READ_BL_LEN; 200// unsigned sectorLength = 1 << log2sl; 201 unsigned sectorLength = 512; 202 int sizeToRead; 203 unsigned int *walker; 204 205 //As long as there is data to read 206 while (length) 207 { 208 if (length > sectorLength) 209 sizeToRead = sectorLength; 210 else 211 sizeToRead = length; 212 213 MCIDeviceWaitReady(AT91C_MCI_TIMEOUT); 214 //Do the reading 215 if (MCI_ReadBlock(source, 216 (unsigned int*)dest, sizeToRead)) 217 return -1; 218 219 //* Wait MCI Device Ready 220 MCIDeviceWaitReady(AT91C_MCI_TIMEOUT); 221 222 // Fix erratum in MCI part 223 for (walker = (unsigned int *)dest; 224 walker < (unsigned int *)(dest + sizeToRead); walker++) 225 *walker = swap(*walker); 226 227 //Update counters & pointers 228 length -= sizeToRead; 229 dest += sizeToRead; 230 source += sizeToRead; 231 } 232 233 return 0; 234} 235 236//*---------------------------------------------------------------------------- 237//* \fn MCI_SDCard_SendAppCommand 238//* \brief Specific function to send a specific command to the SDCard 239//*---------------------------------------------------------------------------- 240static int 241MCI_SDCard_SendAppCommand( 242 unsigned int Cmd_App, 243 unsigned int Arg) 244{ 245 // Send the CMD55 for application specific command 246 AT91C_BASE_MCI->MCI_ARGR = (MCI_Device.RCA << 16 ); 247 AT91C_BASE_MCI->MCI_CMDR = APP_CMD; 248 249 wait_ready(); 250 // if an error occurs 251 if (AT91C_BASE_MCI->MCI_SR & AT91C_MCI_SR_ERROR) 252 return (1); 253 return (MCI_SendCommand(Cmd_App,Arg)); 254} 255 256//*---------------------------------------------------------------------------- 257//* \fn MCI_GetCSD 258//* \brief Asks to the specified card to send its CSD 259//*---------------------------------------------------------------------------- 260static int 261MCI_GetCSD(unsigned int rca, unsigned int *response) 262{ 263 264 if (MCI_SendCommand(SEND_CSD_CMD, (rca << 16))) 265 return 1; 266 267 response[0] = AT91C_BASE_MCI->MCI_RSPR[0]; 268 response[1] = AT91C_BASE_MCI->MCI_RSPR[1]; 269 response[2] = AT91C_BASE_MCI->MCI_RSPR[2]; 270 response[3] = AT91C_BASE_MCI->MCI_RSPR[3]; 271 272 return 0; 273} 274 275//*---------------------------------------------------------------------------- 276//* \fn MCI_SDCard_GetOCR 277//* \brief Asks to all cards to send their operations conditions 278//*---------------------------------------------------------------------------- 279static int 280MCI_SDCard_GetOCR() 281{ 282 unsigned int response=0x0; 283 284 // The RCA to be used for CMD55 in Idle state shall be the card's default RCA=0x0000. 285 MCI_Device.RCA = 0x0; 286 287 while( (response & AT91C_CARD_POWER_UP_BUSY) != AT91C_CARD_POWER_UP_BUSY ) { 288 if (MCI_SDCard_SendAppCommand(SDCARD_APP_OP_COND_CMD, 289 AT91C_MMC_HOST_VOLTAGE_RANGE)) 290 return 1; 291 response = AT91C_BASE_MCI->MCI_RSPR[0]; 292 } 293 return (0); 294} 295 296//*---------------------------------------------------------------------------- 297//* \fn MCI_SDCard_GetCID 298//* \brief Asks to the SDCard on the chosen slot to send its CID 299//*---------------------------------------------------------------------------- 300static int 301MCI_SDCard_GetCID(unsigned int *response) 302{ 303 if (MCI_SendCommand(ALL_SEND_CID_CMD, AT91C_NO_ARGUMENT)) 304 return 1; 305 306 response[0] = AT91C_BASE_MCI->MCI_RSPR[0]; 307 response[1] = AT91C_BASE_MCI->MCI_RSPR[1]; 308 response[2] = AT91C_BASE_MCI->MCI_RSPR[2]; 309 response[3] = AT91C_BASE_MCI->MCI_RSPR[3]; 310 311 return 0; 312} 313 314//*---------------------------------------------------------------------------- 315//* \fn MCI_SDCard_SetBusWidth 316//* \brief Set bus width for SDCard 317//*---------------------------------------------------------------------------- 318static int 319MCI_SDCard_SetBusWidth() 320{ 321 volatile int ret_value; 322 char bus_width; 323 324 do { 325 ret_value=MCI_GetStatus(); 326 } 327 while((ret_value > 0) && ((ret_value & AT91C_SR_READY_FOR_DATA) == 0)); 328 329 // Select Card 330 MCI_SendCommand(SEL_DESEL_CARD_CMD, (MCI_Device.RCA)<<16); 331 332 // Set bus width for Sdcard 333 if (MCI_Device.SDCard_bus_width == AT91C_MCI_SCDBUS) 334 bus_width = AT91C_BUS_WIDTH_4BITS; 335 else 336 bus_width = AT91C_BUS_WIDTH_1BIT; 337 338 if (MCI_SDCard_SendAppCommand( 339 SDCARD_SET_BUS_WIDTH_CMD,bus_width) != AT91C_CMD_SEND_OK) 340 return 1; 341 342 return 0; 343} 344 345//*---------------------------------------------------------------------------- 346//* \fn main 347//* \brief main function 348//*---------------------------------------------------------------------------- 349int 350sdcard_init(void) 351{ 352 unsigned int tab_response[4]; 353#ifdef REPORT_SIZE 354 unsigned int mult,blocknr; 355#endif 356 int i; 357 358 // Init MCI for MMC and SDCard interface 359 AT91F_MCI_CfgPIO(); 360 AT91F_MCI_CfgPMC(); 361 AT91F_PDC_Open(AT91C_BASE_PDC_MCI); 362 363 // Init Device Structure 364 MCI_Device.state = AT91C_MCI_IDLE; 365 MCI_Device.SDCard_bus_width = AT91C_MCI_SCDBUS; 366 367 //* Reset the MCI 368 AT91C_BASE_MCI->MCI_CR = AT91C_MCI_MCIEN | AT91C_MCI_PWSEN; 369 AT91C_BASE_MCI->MCI_IDR = 0xFFFFFFFF; 370 AT91C_BASE_MCI->MCI_DTOR = AT91C_MCI_DTOR_1MEGA_CYCLES; 371 AT91C_BASE_MCI->MCI_MR = AT91C_MCI_PDCMODE; 372 AT91C_BASE_MCI->MCI_SDCR = AT91C_MCI_SDCARD_4BITS_SLOTA; 373 MCI_SendCommand(GO_IDLE_STATE_CMD, AT91C_NO_ARGUMENT); 374 375 for (i = 0; i < 100; i++) { 376 if (!MCI_SDCard_GetOCR(&MCI_Device)) 377 break; 378 printf("."); 379 } 380 if (i >= 100) 381 return 0; 382 if (MCI_SDCard_GetCID(tab_response)) 383 return 0; 384 if (MCI_SendCommand(SET_RELATIVE_ADDR_CMD, 0)) 385 return 0; 386 387 MCI_Device.RCA = (AT91C_BASE_MCI->MCI_RSPR[0] >> 16); 388 if (MCI_GetCSD(MCI_Device.RCA,tab_response)) 389 return 0; 390 MCI_Device.READ_BL_LEN = (tab_response[1] >> CSD_1_RD_B_LEN_S) & 391 CSD_1_RD_B_LEN_M; 392#ifdef REPORT_SIZE 393 // compute MULT 394 mult = 1 << ( ((tab_response[2] >> CSD_2_C_SIZE_M_S) & 395 CSD_2_C_SIZE_M_M) + 2 ); 396 // compute MSB of C_SIZE 397 blocknr = ((tab_response[1] >> CSD_1_CSIZE_H_S) & 398 CSD_1_CSIZE_H_M) << 2; 399 // compute MULT * (LSB of C-SIZE + MSB already computed + 1) = BLOCKNR 400 blocknr = mult * ((blocknr + ((tab_response[2] >> CSD_2_CSIZE_L_S) & 401 CSD_2_CSIZE_L_M)) + 1); 402 MCI_Device.Memory_Capacity = (1 << MCI_Device.READ_BL_LEN) * blocknr; 403#endif 404 if (MCI_SDCard_SetBusWidth()) 405 return 0; 406 if (MCI_SendCommand(SET_BLOCKLEN_CMD, 1 << MCI_Device.READ_BL_LEN)) 407 return 0; 408#ifdef REPORT_SIZE 409 printf("Found SD card %u bytes\n", MCI_Device.Memory_Capacity); 410#endif 411 return 1; 412} 413