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