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