initial commit
[freebsd-arm:freebsd-arm.git] / boot / arm / at91 / libat91 / sd-card.c
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
55 AT91S_MciDevice                 MCI_Device;
56 char                            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 //*----------------------------------------------------------------------------
68 static void
69 MCIDeviceWaitReady(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
97 inline static unsigned int
98 swap(unsigned int a)
99 {
100     return (((a & 0xff) << 24) | ((a & 0xff00) << 8) | ((a & 0xff0000) >> 8)
101       | ((a & 0xff000000) >> 24));
102 }
103
104 inline static void
105 wait_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 //*----------------------------------------------------------------------------
120 static int
121 MCI_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 //*----------------------------------------------------------------------------
145 static unsigned int
146 MCI_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 //*----------------------------------------------------------------------------
157 static int
158 MCI_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
196 int
197 MCI_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 //*----------------------------------------------------------------------------
240 static int
241 MCI_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 //*----------------------------------------------------------------------------
260 static int
261 MCI_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 //*----------------------------------------------------------------------------
279 static int
280 MCI_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 //*----------------------------------------------------------------------------
300 static int
301 MCI_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 //*----------------------------------------------------------------------------
318 static int
319 MCI_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 //*----------------------------------------------------------------------------
349 int
350 sdcard_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 }