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
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	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