sd-card.c revision 164137
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: head/sys/boot/arm/at91/libat91/sd-card.c 164137 2006-11-09 20:32:36Z imp $ 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 97inline static unsigned int 98swap(unsigned int a) 99{ 100 return (((a & 0xff) << 24) | ((a & 0xff00) << 8) | ((a & 0xff0000) >> 8) 101 | ((a & 0xff000000) >> 24)); 102} 103 104inline static 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 163 /////////////////////////////////////////////////////////////////////// 164 if (MCI_Device.state != AT91C_MCI_IDLE) 165 return 1; 166 167 if ((MCI_GetStatus() & AT91C_SR_READY_FOR_DATA) == 0) 168 return 1; 169 170 /////////////////////////////////////////////////////////////////////// 171 172 // Init Mode Register 173 AT91C_BASE_MCI->MCI_MR |= ((sectorLength << 16) | AT91C_MCI_PDCMODE); 174 175 sizeToRead = sizeToRead / 4; 176 177 AT91C_BASE_PDC_MCI->PDC_PTCR = (AT91C_PDC_TXTDIS | AT91C_PDC_RXTDIS); 178 AT91C_BASE_PDC_MCI->PDC_RPR = (unsigned int)dataBuffer; 179 AT91C_BASE_PDC_MCI->PDC_RCR = sizeToRead; 180 181 // Send the Read single block command 182 if (MCI_SendCommand(READ_SINGLE_BLOCK_CMD, src)) 183 return AT91C_READ_ERROR; 184 MCI_Device.state = AT91C_MCI_RX_SINGLE_BLOCK; 185 186 // Enable AT91C_MCI_RXBUFF Interrupt 187 AT91C_BASE_MCI->MCI_IER = AT91C_MCI_RXBUFF; 188 189 // (PDC) Receiver Transfer Enable 190 AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_RXTEN; 191 192 return 0; 193} 194 195int 196MCI_read(char* dest, unsigned source, unsigned length) 197{ 198 unsigned log2sl = MCI_Device.READ_BL_LEN; 199 unsigned sectorLength = 1 << log2sl; 200 int sizeToRead; 201 unsigned int *walker; 202 203 //As long as there is data to read 204 while (length) 205 { 206 if (length > sectorLength) 207 sizeToRead = sectorLength; 208 else 209 sizeToRead = length; 210 211 MCIDeviceWaitReady(AT91C_MCI_TIMEOUT); 212 //Do the reading 213 if (MCI_ReadBlock(source, 214 (unsigned int*)dest, sizeToRead)) 215 return -1; 216 217 //* Wait MCI Device Ready 218 MCIDeviceWaitReady(AT91C_MCI_TIMEOUT); 219 220 // Fix erratum in MCI part 221 for (walker = (unsigned int *)dest; 222 walker < (unsigned int *)(dest + sizeToRead); walker++) 223 *walker = swap(*walker); 224 225 //Update counters & pointers 226 length -= sizeToRead; 227 dest += sizeToRead; 228 source += sizeToRead; 229 } 230 231 return 0; 232} 233 234//*---------------------------------------------------------------------------- 235//* \fn MCI_SDCard_SendAppCommand 236//* \brief Specific function to send a specific command to the SDCard 237//*---------------------------------------------------------------------------- 238static int 239MCI_SDCard_SendAppCommand( 240 unsigned int Cmd_App, 241 unsigned int Arg) 242{ 243 // Send the CMD55 for application specific command 244 AT91C_BASE_MCI->MCI_ARGR = (MCI_Device.RCA << 16 ); 245 AT91C_BASE_MCI->MCI_CMDR = APP_CMD; 246 247 wait_ready(); 248 // if an error occurs 249 if (AT91C_BASE_MCI->MCI_SR & AT91C_MCI_SR_ERROR) 250 return (1); 251 return (MCI_SendCommand(Cmd_App,Arg)); 252} 253 254//*---------------------------------------------------------------------------- 255//* \fn MCI_GetCSD 256//* \brief Asks to the specified card to send its CSD 257//*---------------------------------------------------------------------------- 258static int 259MCI_GetCSD(unsigned int rca, unsigned int *response) 260{ 261 262 if (MCI_SendCommand(SEND_CSD_CMD, (rca << 16))) 263 return 1; 264 265 response[0] = AT91C_BASE_MCI->MCI_RSPR[0]; 266 response[1] = AT91C_BASE_MCI->MCI_RSPR[1]; 267 response[2] = AT91C_BASE_MCI->MCI_RSPR[2]; 268 response[3] = AT91C_BASE_MCI->MCI_RSPR[3]; 269 270 return 0; 271} 272 273//*---------------------------------------------------------------------------- 274//* \fn MCI_SDCard_GetOCR 275//* \brief Asks to all cards to send their operations conditions 276//*---------------------------------------------------------------------------- 277static int 278MCI_SDCard_GetOCR() 279{ 280 unsigned int response=0x0; 281 282 // The RCA to be used for CMD55 in Idle state shall be the card's default RCA=0x0000. 283 MCI_Device.RCA = 0x0; 284 285 while( (response & AT91C_CARD_POWER_UP_BUSY) != AT91C_CARD_POWER_UP_BUSY ) { 286 if (MCI_SDCard_SendAppCommand(SDCARD_APP_OP_COND_CMD, 287 AT91C_MMC_HOST_VOLTAGE_RANGE)) 288 return 1; 289 response = AT91C_BASE_MCI->MCI_RSPR[0]; 290 } 291 return (0); 292} 293 294//*---------------------------------------------------------------------------- 295//* \fn MCI_SDCard_GetCID 296//* \brief Asks to the SDCard on the chosen slot to send its CID 297//*---------------------------------------------------------------------------- 298static int 299MCI_SDCard_GetCID(unsigned int *response) 300{ 301 if (MCI_SendCommand(ALL_SEND_CID_CMD, AT91C_NO_ARGUMENT)) 302 return 1; 303 304 response[0] = AT91C_BASE_MCI->MCI_RSPR[0]; 305 response[1] = AT91C_BASE_MCI->MCI_RSPR[1]; 306 response[2] = AT91C_BASE_MCI->MCI_RSPR[2]; 307 response[3] = AT91C_BASE_MCI->MCI_RSPR[3]; 308 309 return 0; 310} 311 312//*---------------------------------------------------------------------------- 313//* \fn MCI_SDCard_SetBusWidth 314//* \brief Set bus width for SDCard 315//*---------------------------------------------------------------------------- 316static int 317MCI_SDCard_SetBusWidth() 318{ 319 volatile int ret_value; 320 char bus_width; 321 322 do { 323 ret_value=MCI_GetStatus(); 324 } 325 while((ret_value > 0) && ((ret_value & AT91C_SR_READY_FOR_DATA) == 0)); 326 327 // Select Card 328 MCI_SendCommand(SEL_DESEL_CARD_CMD, (MCI_Device.RCA)<<16); 329 330 // Set bus width for Sdcard 331 if (MCI_Device.SDCard_bus_width == AT91C_MCI_SCDBUS) 332 bus_width = AT91C_BUS_WIDTH_4BITS; 333 else 334 bus_width = AT91C_BUS_WIDTH_1BIT; 335 336 if (MCI_SDCard_SendAppCommand( 337 SDCARD_SET_BUS_WIDTH_CMD,bus_width) != AT91C_CMD_SEND_OK) 338 return 1; 339 340 return 0; 341} 342 343//*---------------------------------------------------------------------------- 344//* \fn main 345//* \brief main function 346//*---------------------------------------------------------------------------- 347int 348sdcard_init(void) 349{ 350 unsigned int tab_response[4]; 351#ifdef REPORT_SIZE 352 unsigned int mult,blocknr; 353#endif 354 int i; 355 356 // Init MCI for MMC and SDCard interface 357 AT91F_MCI_CfgPIO(); 358 AT91F_MCI_CfgPMC(); 359 AT91F_PDC_Open(AT91C_BASE_PDC_MCI); 360 361 // Init Device Structure 362 MCI_Device.state = AT91C_MCI_IDLE; 363 MCI_Device.SDCard_bus_width = AT91C_MCI_SCDBUS; 364 365 //* Reset the MCI 366 AT91C_BASE_MCI->MCI_CR = AT91C_MCI_MCIEN | AT91C_MCI_PWSEN; 367 AT91C_BASE_MCI->MCI_IDR = 0xFFFFFFFF; 368 AT91C_BASE_MCI->MCI_DTOR = AT91C_MCI_DTOR_1MEGA_CYCLES; 369 AT91C_BASE_MCI->MCI_MR = AT91C_MCI_PDCMODE; 370 AT91C_BASE_MCI->MCI_SDCR = AT91C_MCI_SDCARD_4BITS_SLOTA; 371 MCI_SendCommand(GO_IDLE_STATE_CMD, AT91C_NO_ARGUMENT); 372 373 for (i = 0; i < 100; i++) { 374 if (!MCI_SDCard_GetOCR(&MCI_Device)) 375 break; 376 printf("."); 377 } 378 if (i >= 100) 379 return 0; 380 if (MCI_SDCard_GetCID(tab_response)) 381 return 0; 382 if (MCI_SendCommand(SET_RELATIVE_ADDR_CMD, 0)) 383 return 0; 384 385 MCI_Device.RCA = (AT91C_BASE_MCI->MCI_RSPR[0] >> 16); 386 if (MCI_GetCSD(MCI_Device.RCA,tab_response)) 387 return 0; 388 MCI_Device.READ_BL_LEN = (tab_response[1] >> CSD_1_RD_B_LEN_S) & 389 CSD_1_RD_B_LEN_M; 390#ifdef REPORT_SIZE 391 // compute MULT 392 mult = 1 << ( ((tab_response[2] >> CSD_2_C_SIZE_M_S) & 393 CSD_2_C_SIZE_M_M) + 2 ); 394 // compute MSB of C_SIZE 395 blocknr = ((tab_response[1] >> CSD_1_CSIZE_H_S) & 396 CSD_1_CSIZE_H_M) << 2; 397 // compute MULT * (LSB of C-SIZE + MSB already computed + 1) = BLOCKNR 398 blocknr = mult * ((blocknr + ((tab_response[2] >> CSD_2_CSIZE_L_S) & 399 CSD_2_CSIZE_L_M)) + 1); 400 MCI_Device.Memory_Capacity = (1 << MCI_Device.READ_BL_LEN) * blocknr; 401#endif 402 if (MCI_SDCard_SetBusWidth()) 403 return 0; 404 if (MCI_SendCommand(SET_BLOCKLEN_CMD, 1 << MCI_Device.READ_BL_LEN)) 405 return 0; 406#ifdef REPORT_SIZE 407 printf("Found SD card %u bytes\n", MCI_Device.Memory_Capacity); 408#endif 409 return 1; 410} 411