1161370Simp/*- 2161370Simp * Copyright (c) 2006 M. Warner Losh. All rights reserved. 3161370Simp * 4161370Simp * Redistribution and use in source and binary forms, with or without 5161370Simp * modification, are permitted provided that the following conditions 6161370Simp * are met: 7161370Simp * 1. Redistributions of source code must retain the above copyright 8161370Simp * notice, this list of conditions and the following disclaimer. 9161370Simp * 2. Redistributions in binary form must reproduce the above copyright 10161370Simp * notice, this list of conditions and the following disclaimer in the 11161370Simp * documentation and/or other materials provided with the distribution. 12161370Simp * 13161370Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14161370Simp * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15161370Simp * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16161370Simp * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17161370Simp * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18161370Simp * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19161370Simp * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20161370Simp * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21161370Simp * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22161370Simp * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23161370Simp * 24161370Simp * This software is derived from software provide by Kwikbyte who specifically 25161370Simp * disclaimed copyright on the code. 26161370Simp * 27161370Simp * $FreeBSD$ 28161370Simp */ 29161370Simp 30161370Simp//*---------------------------------------------------------------------------- 31161370Simp//* ATMEL Microcontroller Software Support - ROUSSET - 32161370Simp//*---------------------------------------------------------------------------- 33161370Simp//* The software is delivered "AS IS" without warranty or condition of any 34161370Simp//* kind, either express, implied or statutory. This includes without 35161370Simp//* limitation any warranty or condition with respect to merchantability or 36161370Simp//* fitness for any particular purpose, or against the infringements of 37161370Simp//* intellectual property rights of others. 38161370Simp//*---------------------------------------------------------------------------- 39161370Simp//* File Name : main.c 40161370Simp//* Object : main application written in C 41161370Simp//* Creation : FB 21/11/2002 42161370Simp//* 43161370Simp//*---------------------------------------------------------------------------- 44161370Simp#include "at91rm9200.h" 45161370Simp#include "lib_AT91RM9200.h" 46161370Simp#include "mci_device.h" 47161370Simp#include "lib.h" 48161370Simp#include "sd-card.h" 49161370Simp 50161370Simp#define AT91C_MCI_TIMEOUT 1000000 /* For AT91F_MCIDeviceWaitReady */ 51161370Simp#define BUFFER_SIZE_MCI_DEVICE 512 52161370Simp#define MASTER_CLOCK 60000000 53161370Simp 54161370Simp//* Global Variables 55161370SimpAT91S_MciDevice MCI_Device; 56161370Simpchar Buffer[BUFFER_SIZE_MCI_DEVICE]; 57161370Simp 58161370Simp/****************************************************************************** 59161370Simp**Error return codes 60161370Simp******************************************************************************/ 61161370Simp#define MCI_UNSUPP_SIZE_ERROR 5 62161370Simp#define MCI_UNSUPP_OFFSET_ERROR 6 63161370Simp 64161370Simp//*---------------------------------------------------------------------------- 65164137Simp//* \fn MCIDeviceWaitReady 66161370Simp//* \brief Wait for MCI Device ready 67161370Simp//*---------------------------------------------------------------------------- 68161370Simpstatic void 69164137SimpMCIDeviceWaitReady(unsigned int timeout) 70161370Simp{ 71161370Simp volatile int status; 72161370Simp 73161370Simp do 74161370Simp { 75161370Simp status = AT91C_BASE_MCI->MCI_SR; 76161370Simp timeout--; 77161370Simp } 78161370Simp while( !(status & AT91C_MCI_NOTBUSY) && (timeout>0) ); 79161370Simp 80164137Simp status = AT91C_BASE_MCI->MCI_SR; 81164137Simp 82164137Simp // If End of Tx Buffer Empty interrupt occurred 83164137Simp if (MCI_Device.state == AT91C_MCI_TX_SINGLE_BLOCK && status & AT91C_MCI_TXBUFE) { 84164137Simp AT91C_BASE_MCI->MCI_IDR = AT91C_MCI_TXBUFE; 85164137Simp AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_TXTDIS; 86164137Simp MCI_Device.state = AT91C_MCI_IDLE; 87164137Simp } // End of if AT91C_MCI_TXBUFF 88164137Simp 89164137Simp // If End of Rx Buffer Full interrupt occurred 90164137Simp if (MCI_Device.state == AT91C_MCI_RX_SINGLE_BLOCK && status & AT91C_MCI_RXBUFF) { 91164137Simp AT91C_BASE_MCI->MCI_IDR = AT91C_MCI_RXBUFF; 92164137Simp AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_RXTDIS; 93164137Simp MCI_Device.state = AT91C_MCI_IDLE; 94164137Simp } // End of if AT91C_MCI_RXBUFF 95161370Simp} 96161370Simp 97164137Simpinline static unsigned int 98164137Simpswap(unsigned int a) 99161370Simp{ 100164137Simp return (((a & 0xff) << 24) | ((a & 0xff00) << 8) | ((a & 0xff0000) >> 8) 101164137Simp | ((a & 0xff000000) >> 24)); 102164137Simp} 103161370Simp 104164137Simpinline static void 105164137Simpwait_ready() 106164137Simp{ 107164137Simp int status; 108164137Simp 109164137Simp // wait for CMDRDY Status flag to read the response 110164137Simp do 111161370Simp { 112164137Simp status = AT91C_BASE_MCI->MCI_SR; 113164137Simp } while( !(status & AT91C_MCI_CMDRDY) ); 114164137Simp} 115161370Simp 116164137Simp//*---------------------------------------------------------------------------- 117164137Simp//* \fn MCI_SendCommand 118164137Simp//* \brief Generic function to send a command to the MMC or SDCard 119164137Simp//*---------------------------------------------------------------------------- 120164137Simpstatic int 121164137SimpMCI_SendCommand( 122164137Simp unsigned int Cmd, 123164137Simp unsigned int Arg) 124164137Simp{ 125164137Simp unsigned int error; 126161370Simp 127164137Simp AT91C_BASE_MCI->MCI_ARGR = Arg; 128164137Simp AT91C_BASE_MCI->MCI_CMDR = Cmd; 129164137Simp 130164137Simp// printf("CMDR %x ARG %x\n", Cmd, Arg); 131164137Simp wait_ready(); 132164137Simp // Test error ==> if crc error and response R3 ==> don't check error 133164137Simp error = (AT91C_BASE_MCI->MCI_SR) & AT91C_MCI_SR_ERROR; 134164137Simp if (error != 0) { 135164137Simp if (error != AT91C_MCI_RCRCE) 136164137Simp return (1); 137161370Simp } 138161370Simp return 0; 139161370Simp} 140161370Simp 141164137Simp//*---------------------------------------------------------------------------- 142164137Simp//* \fn MCI_GetStatus 143164137Simp//* \brief Addressed card sends its status register 144164137Simp//*---------------------------------------------------------------------------- 145164137Simpstatic unsigned int 146164137SimpMCI_GetStatus() 147161370Simp{ 148164137Simp if (MCI_SendCommand(SEND_STATUS_CMD, MCI_Device.RCA << 16)) 149164137Simp return AT91C_CMD_SEND_ERROR; 150164137Simp return (AT91C_BASE_MCI->MCI_RSPR[0]); 151161370Simp} 152161370Simp 153164137Simp//*---------------------------------------------------------------------------- 154164137Simp//* \fn MCI_ReadBlock 155164137Simp//* \brief Read an ENTIRE block or PARTIAL block 156164137Simp//*---------------------------------------------------------------------------- 157164137Simpstatic int 158164137SimpMCI_ReadBlock(int src, unsigned int *dataBuffer, int sizeToRead) 159164137Simp{ 160168011Simp// unsigned log2sl = MCI_Device.READ_BL_LEN; 161168011Simp// unsigned sectorLength = 1 << log2sl; 162168011Simp unsigned sectorLength = 512; 163164137Simp 164164137Simp /////////////////////////////////////////////////////////////////////// 165164137Simp if (MCI_Device.state != AT91C_MCI_IDLE) 166164137Simp return 1; 167164137Simp 168164137Simp if ((MCI_GetStatus() & AT91C_SR_READY_FOR_DATA) == 0) 169164137Simp return 1; 170164137Simp 171164137Simp /////////////////////////////////////////////////////////////////////// 172164137Simp 173164137Simp // Init Mode Register 174164137Simp AT91C_BASE_MCI->MCI_MR |= ((sectorLength << 16) | AT91C_MCI_PDCMODE); 175164137Simp 176164137Simp sizeToRead = sizeToRead / 4; 177164137Simp 178164137Simp AT91C_BASE_PDC_MCI->PDC_PTCR = (AT91C_PDC_TXTDIS | AT91C_PDC_RXTDIS); 179164137Simp AT91C_BASE_PDC_MCI->PDC_RPR = (unsigned int)dataBuffer; 180164137Simp AT91C_BASE_PDC_MCI->PDC_RCR = sizeToRead; 181164137Simp 182164137Simp // Send the Read single block command 183164137Simp if (MCI_SendCommand(READ_SINGLE_BLOCK_CMD, src)) 184164137Simp return AT91C_READ_ERROR; 185164137Simp MCI_Device.state = AT91C_MCI_RX_SINGLE_BLOCK; 186164137Simp 187164137Simp // Enable AT91C_MCI_RXBUFF Interrupt 188164137Simp AT91C_BASE_MCI->MCI_IER = AT91C_MCI_RXBUFF; 189164137Simp 190164137Simp // (PDC) Receiver Transfer Enable 191164137Simp AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_RXTEN; 192164137Simp 193164137Simp return 0; 194164137Simp} 195164137Simp 196161370Simpint 197161370SimpMCI_read(char* dest, unsigned source, unsigned length) 198161370Simp{ 199168011Simp// unsigned log2sl = MCI_Device.READ_BL_LEN; 200168011Simp// unsigned sectorLength = 1 << log2sl; 201168011Simp unsigned sectorLength = 512; 202161370Simp int sizeToRead; 203161370Simp unsigned int *walker; 204161370Simp 205161370Simp //As long as there is data to read 206161370Simp while (length) 207161370Simp { 208161370Simp if (length > sectorLength) 209161370Simp sizeToRead = sectorLength; 210161370Simp else 211161370Simp sizeToRead = length; 212161370Simp 213164137Simp MCIDeviceWaitReady(AT91C_MCI_TIMEOUT); 214163533Simp //Do the reading 215164137Simp if (MCI_ReadBlock(source, 216164137Simp (unsigned int*)dest, sizeToRead)) 217161370Simp return -1; 218161370Simp 219161370Simp //* Wait MCI Device Ready 220164137Simp MCIDeviceWaitReady(AT91C_MCI_TIMEOUT); 221161370Simp 222161370Simp // Fix erratum in MCI part 223161370Simp for (walker = (unsigned int *)dest; 224161370Simp walker < (unsigned int *)(dest + sizeToRead); walker++) 225161370Simp *walker = swap(*walker); 226161370Simp 227161370Simp //Update counters & pointers 228161370Simp length -= sizeToRead; 229161370Simp dest += sizeToRead; 230161370Simp source += sizeToRead; 231161370Simp } 232161370Simp 233161370Simp return 0; 234161370Simp} 235161370Simp 236164137Simp//*---------------------------------------------------------------------------- 237164137Simp//* \fn MCI_SDCard_SendAppCommand 238164137Simp//* \brief Specific function to send a specific command to the SDCard 239164137Simp//*---------------------------------------------------------------------------- 240164137Simpstatic int 241164137SimpMCI_SDCard_SendAppCommand( 242164137Simp unsigned int Cmd_App, 243164137Simp unsigned int Arg) 244164137Simp{ 245164137Simp // Send the CMD55 for application specific command 246164137Simp AT91C_BASE_MCI->MCI_ARGR = (MCI_Device.RCA << 16 ); 247164137Simp AT91C_BASE_MCI->MCI_CMDR = APP_CMD; 248161370Simp 249164137Simp wait_ready(); 250164137Simp // if an error occurs 251164137Simp if (AT91C_BASE_MCI->MCI_SR & AT91C_MCI_SR_ERROR) 252164137Simp return (1); 253164137Simp return (MCI_SendCommand(Cmd_App,Arg)); 254164137Simp} 255164137Simp 256161370Simp//*---------------------------------------------------------------------------- 257164137Simp//* \fn MCI_GetCSD 258164137Simp//* \brief Asks to the specified card to send its CSD 259161370Simp//*---------------------------------------------------------------------------- 260164137Simpstatic int 261164137SimpMCI_GetCSD(unsigned int rca, unsigned int *response) 262161370Simp{ 263164137Simp 264164137Simp if (MCI_SendCommand(SEND_CSD_CMD, (rca << 16))) 265164137Simp return 1; 266164137Simp 267164137Simp response[0] = AT91C_BASE_MCI->MCI_RSPR[0]; 268164137Simp response[1] = AT91C_BASE_MCI->MCI_RSPR[1]; 269164137Simp response[2] = AT91C_BASE_MCI->MCI_RSPR[2]; 270164137Simp response[3] = AT91C_BASE_MCI->MCI_RSPR[3]; 271164137Simp 272164137Simp return 0; 273164137Simp} 274161370Simp 275164137Simp//*---------------------------------------------------------------------------- 276164137Simp//* \fn MCI_SDCard_GetOCR 277164137Simp//* \brief Asks to all cards to send their operations conditions 278164137Simp//*---------------------------------------------------------------------------- 279164137Simpstatic int 280164137SimpMCI_SDCard_GetOCR() 281164137Simp{ 282164137Simp unsigned int response=0x0; 283164137Simp 284164137Simp // The RCA to be used for CMD55 in Idle state shall be the card's default RCA=0x0000. 285164137Simp MCI_Device.RCA = 0x0; 286164137Simp 287164137Simp while( (response & AT91C_CARD_POWER_UP_BUSY) != AT91C_CARD_POWER_UP_BUSY ) { 288164137Simp if (MCI_SDCard_SendAppCommand(SDCARD_APP_OP_COND_CMD, 289164137Simp AT91C_MMC_HOST_VOLTAGE_RANGE)) 290164137Simp return 1; 291164137Simp response = AT91C_BASE_MCI->MCI_RSPR[0]; 292164137Simp } 293164137Simp return (0); 294161370Simp} 295161370Simp 296164137Simp//*---------------------------------------------------------------------------- 297164137Simp//* \fn MCI_SDCard_GetCID 298164137Simp//* \brief Asks to the SDCard on the chosen slot to send its CID 299164137Simp//*---------------------------------------------------------------------------- 300164137Simpstatic int 301164137SimpMCI_SDCard_GetCID(unsigned int *response) 302161370Simp{ 303164137Simp if (MCI_SendCommand(ALL_SEND_CID_CMD, AT91C_NO_ARGUMENT)) 304164137Simp return 1; 305164137Simp 306164137Simp response[0] = AT91C_BASE_MCI->MCI_RSPR[0]; 307164137Simp response[1] = AT91C_BASE_MCI->MCI_RSPR[1]; 308164137Simp response[2] = AT91C_BASE_MCI->MCI_RSPR[2]; 309164137Simp response[3] = AT91C_BASE_MCI->MCI_RSPR[3]; 310164137Simp 311164137Simp return 0; 312164137Simp} 313161370Simp 314164137Simp//*---------------------------------------------------------------------------- 315164137Simp//* \fn MCI_SDCard_SetBusWidth 316164137Simp//* \brief Set bus width for SDCard 317164137Simp//*---------------------------------------------------------------------------- 318164137Simpstatic int 319164137SimpMCI_SDCard_SetBusWidth() 320164137Simp{ 321164137Simp volatile int ret_value; 322164137Simp char bus_width; 323161370Simp 324164137Simp do { 325164137Simp ret_value=MCI_GetStatus(); 326164137Simp } 327164137Simp while((ret_value > 0) && ((ret_value & AT91C_SR_READY_FOR_DATA) == 0)); 328164137Simp 329164137Simp // Select Card 330164137Simp MCI_SendCommand(SEL_DESEL_CARD_CMD, (MCI_Device.RCA)<<16); 331164137Simp 332164137Simp // Set bus width for Sdcard 333164137Simp if (MCI_Device.SDCard_bus_width == AT91C_MCI_SCDBUS) 334164137Simp bus_width = AT91C_BUS_WIDTH_4BITS; 335164137Simp else 336164137Simp bus_width = AT91C_BUS_WIDTH_1BIT; 337164137Simp 338164137Simp if (MCI_SDCard_SendAppCommand( 339164137Simp SDCARD_SET_BUS_WIDTH_CMD,bus_width) != AT91C_CMD_SEND_OK) 340164137Simp return 1; 341164137Simp 342164137Simp return 0; 343161370Simp} 344161370Simp 345161370Simp//*---------------------------------------------------------------------------- 346161370Simp//* \fn main 347161370Simp//* \brief main function 348161370Simp//*---------------------------------------------------------------------------- 349161370Simpint 350161370Simpsdcard_init(void) 351161370Simp{ 352164137Simp unsigned int tab_response[4]; 353164137Simp#ifdef REPORT_SIZE 354164137Simp unsigned int mult,blocknr; 355164137Simp#endif 356164137Simp int i; 357161370Simp 358161370Simp // Init MCI for MMC and SDCard interface 359161370Simp AT91F_MCI_CfgPIO(); 360161370Simp AT91F_MCI_CfgPMC(); 361161370Simp AT91F_PDC_Open(AT91C_BASE_PDC_MCI); 362161370Simp 363164137Simp // Init Device Structure 364164137Simp MCI_Device.state = AT91C_MCI_IDLE; 365164137Simp MCI_Device.SDCard_bus_width = AT91C_MCI_SCDBUS; 366161370Simp 367164137Simp //* Reset the MCI 368164137Simp AT91C_BASE_MCI->MCI_CR = AT91C_MCI_MCIEN | AT91C_MCI_PWSEN; 369164137Simp AT91C_BASE_MCI->MCI_IDR = 0xFFFFFFFF; 370164137Simp AT91C_BASE_MCI->MCI_DTOR = AT91C_MCI_DTOR_1MEGA_CYCLES; 371164137Simp AT91C_BASE_MCI->MCI_MR = AT91C_MCI_PDCMODE; 372164137Simp AT91C_BASE_MCI->MCI_SDCR = AT91C_MCI_SDCARD_4BITS_SLOTA; 373164137Simp MCI_SendCommand(GO_IDLE_STATE_CMD, AT91C_NO_ARGUMENT); 374164137Simp 375164137Simp for (i = 0; i < 100; i++) { 376164137Simp if (!MCI_SDCard_GetOCR(&MCI_Device)) 377164137Simp break; 378164137Simp printf("."); 379164137Simp } 380164137Simp if (i >= 100) 381161370Simp return 0; 382164137Simp if (MCI_SDCard_GetCID(tab_response)) 383164137Simp return 0; 384164137Simp if (MCI_SendCommand(SET_RELATIVE_ADDR_CMD, 0)) 385164137Simp return 0; 386164137Simp 387164137Simp MCI_Device.RCA = (AT91C_BASE_MCI->MCI_RSPR[0] >> 16); 388164137Simp if (MCI_GetCSD(MCI_Device.RCA,tab_response)) 389164137Simp return 0; 390164137Simp MCI_Device.READ_BL_LEN = (tab_response[1] >> CSD_1_RD_B_LEN_S) & 391164137Simp CSD_1_RD_B_LEN_M; 392164137Simp#ifdef REPORT_SIZE 393164137Simp // compute MULT 394164137Simp mult = 1 << ( ((tab_response[2] >> CSD_2_C_SIZE_M_S) & 395164137Simp CSD_2_C_SIZE_M_M) + 2 ); 396164137Simp // compute MSB of C_SIZE 397164137Simp blocknr = ((tab_response[1] >> CSD_1_CSIZE_H_S) & 398164137Simp CSD_1_CSIZE_H_M) << 2; 399164137Simp // compute MULT * (LSB of C-SIZE + MSB already computed + 1) = BLOCKNR 400164137Simp blocknr = mult * ((blocknr + ((tab_response[2] >> CSD_2_CSIZE_L_S) & 401164137Simp CSD_2_CSIZE_L_M)) + 1); 402164137Simp MCI_Device.Memory_Capacity = (1 << MCI_Device.READ_BL_LEN) * blocknr; 403164137Simp#endif 404164137Simp if (MCI_SDCard_SetBusWidth()) 405164137Simp return 0; 406164137Simp if (MCI_SendCommand(SET_BLOCKLEN_CMD, 1 << MCI_Device.READ_BL_LEN)) 407164137Simp return 0; 408164137Simp#ifdef REPORT_SIZE 409164137Simp printf("Found SD card %u bytes\n", MCI_Device.Memory_Capacity); 410164137Simp#endif 411161370Simp return 1; 412161370Simp} 413