sd-card.c revision 225736
1191783Srmacklem/*-
2191783Srmacklem * Copyright (c) 2006 M. Warner Losh.  All rights reserved.
3191783Srmacklem *
4191783Srmacklem * Redistribution and use in source and binary forms, with or without
5191783Srmacklem * modification, are permitted provided that the following conditions
6191783Srmacklem * are met:
7191783Srmacklem * 1. Redistributions of source code must retain the above copyright
8191783Srmacklem *    notice, this list of conditions and the following disclaimer.
9191783Srmacklem * 2. Redistributions in binary form must reproduce the above copyright
10191783Srmacklem *    notice, this list of conditions and the following disclaimer in the
11191783Srmacklem *    documentation and/or other materials provided with the distribution.
12191783Srmacklem *
13191783Srmacklem * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14191783Srmacklem * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15191783Srmacklem * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16191783Srmacklem * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17191783Srmacklem * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18191783Srmacklem * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19191783Srmacklem * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20191783Srmacklem * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21191783Srmacklem * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22191783Srmacklem * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23191783Srmacklem *
24191783Srmacklem * This software is derived from software provide by Kwikbyte who specifically
25191783Srmacklem * disclaimed copyright on the code.
26191783Srmacklem *
27191783Srmacklem * $FreeBSD: stable/9/sys/boot/arm/at91/libat91/sd-card.c 168011 2007-03-28 22:31:32Z imp $
28191783Srmacklem */
29191783Srmacklem
30191783Srmacklem//*----------------------------------------------------------------------------
31191783Srmacklem//*         ATMEL Microcontroller Software Support  -  ROUSSET  -
32191783Srmacklem//*----------------------------------------------------------------------------
33191783Srmacklem//* The software is delivered "AS IS" without warranty or condition of any
34191783Srmacklem//* kind, either express, implied or statutory. This includes without
35191783Srmacklem//* limitation any warranty or condition with respect to merchantability or
36191783Srmacklem//* fitness for any particular purpose, or against the infringements of
37191783Srmacklem//* intellectual property rights of others.
38191783Srmacklem//*----------------------------------------------------------------------------
39191783Srmacklem//* File Name           : main.c
40191783Srmacklem//* Object              : main application written in C
41191783Srmacklem//* Creation            : FB   21/11/2002
42191783Srmacklem//*
43191783Srmacklem//*----------------------------------------------------------------------------
44191783Srmacklem#include "at91rm9200.h"
45191783Srmacklem#include "lib_AT91RM9200.h"
46191783Srmacklem#include "mci_device.h"
47191783Srmacklem#include "lib.h"
48191783Srmacklem#include "sd-card.h"
49191783Srmacklem
50191783Srmacklem#define AT91C_MCI_TIMEOUT	1000000   /* For AT91F_MCIDeviceWaitReady */
51191783Srmacklem#define BUFFER_SIZE_MCI_DEVICE	512
52191783Srmacklem#define MASTER_CLOCK		60000000
53191783Srmacklem
54191783Srmacklem//* Global Variables
55191783SrmacklemAT91S_MciDevice			MCI_Device;
56191783Srmacklemchar				Buffer[BUFFER_SIZE_MCI_DEVICE];
57191783Srmacklem
58191783Srmacklem/******************************************************************************
59191783Srmacklem**Error return codes
60191783Srmacklem******************************************************************************/
61191783Srmacklem#define MCI_UNSUPP_SIZE_ERROR		5
62191783Srmacklem#define MCI_UNSUPP_OFFSET_ERROR 6
63191783Srmacklem
64191783Srmacklem//*----------------------------------------------------------------------------
65191783Srmacklem//* \fn    MCIDeviceWaitReady
66191783Srmacklem//* \brief Wait for MCI Device ready
67191783Srmacklem//*----------------------------------------------------------------------------
68191783Srmacklemstatic void
69191783SrmacklemMCIDeviceWaitReady(unsigned int timeout)
70191783Srmacklem{
71191783Srmacklem	volatile int status;
72191783Srmacklem
73191783Srmacklem	do
74191783Srmacklem	{
75191783Srmacklem		status = AT91C_BASE_MCI->MCI_SR;
76191783Srmacklem		timeout--;
77191783Srmacklem	}
78191783Srmacklem	while( !(status & AT91C_MCI_NOTBUSY)  && (timeout>0) );
79191783Srmacklem
80191783Srmacklem	status = AT91C_BASE_MCI->MCI_SR;
81191783Srmacklem
82191783Srmacklem	// If End of Tx Buffer Empty interrupt occurred
83191783Srmacklem	if (MCI_Device.state == AT91C_MCI_TX_SINGLE_BLOCK && status & AT91C_MCI_TXBUFE) {
84191783Srmacklem		AT91C_BASE_MCI->MCI_IDR = AT91C_MCI_TXBUFE;
85191783Srmacklem 		AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_TXTDIS;
86191783Srmacklem		MCI_Device.state = AT91C_MCI_IDLE;
87191783Srmacklem	}	// End of if AT91C_MCI_TXBUFF
88191783Srmacklem
89191783Srmacklem	// If End of Rx Buffer Full interrupt occurred
90191783Srmacklem	if (MCI_Device.state == AT91C_MCI_RX_SINGLE_BLOCK && status & AT91C_MCI_RXBUFF) {
91191783Srmacklem		AT91C_BASE_MCI->MCI_IDR = AT91C_MCI_RXBUFF;
92191783Srmacklem 		AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_RXTDIS;
93191783Srmacklem		MCI_Device.state = AT91C_MCI_IDLE;
94191783Srmacklem	}	// End of if AT91C_MCI_RXBUFF
95191783Srmacklem}
96191783Srmacklem
97191783Srmackleminline static unsigned int
98191783Srmacklemswap(unsigned int a)
99191783Srmacklem{
100191783Srmacklem    return (((a & 0xff) << 24) | ((a & 0xff00) << 8) | ((a & 0xff0000) >> 8)
101191783Srmacklem      | ((a & 0xff000000) >> 24));
102191783Srmacklem}
103191783Srmacklem
104191783Srmackleminline static void
105191783Srmacklemwait_ready()
106191783Srmacklem{
107191783Srmacklem	int status;
108191783Srmacklem
109191783Srmacklem	// wait for CMDRDY Status flag to read the response
110191783Srmacklem	do
111191783Srmacklem	{
112191783Srmacklem		status = AT91C_BASE_MCI->MCI_SR;
113191783Srmacklem	} while( !(status & AT91C_MCI_CMDRDY) );
114191783Srmacklem}
115191783Srmacklem
116191783Srmacklem//*----------------------------------------------------------------------------
117191783Srmacklem//* \fn    MCI_SendCommand
118191783Srmacklem//* \brief Generic function to send a command to the MMC or SDCard
119191783Srmacklem//*----------------------------------------------------------------------------
120191783Srmacklemstatic int
121191783SrmacklemMCI_SendCommand(
122191783Srmacklem	unsigned int Cmd,
123191783Srmacklem	unsigned int Arg)
124191783Srmacklem{
125191783Srmacklem	unsigned int	error;
126191783Srmacklem
127191783Srmacklem	AT91C_BASE_MCI->MCI_ARGR = Arg;
128191783Srmacklem	AT91C_BASE_MCI->MCI_CMDR = Cmd;
129191783Srmacklem
130191783Srmacklem//	printf("CMDR %x ARG %x\n", Cmd, Arg);
131191783Srmacklem	wait_ready();
132191783Srmacklem	// Test error  ==> if crc error and response R3 ==> don't check error
133191783Srmacklem	error = (AT91C_BASE_MCI->MCI_SR) & AT91C_MCI_SR_ERROR;
134191783Srmacklem	if (error != 0) {
135191783Srmacklem		if (error != AT91C_MCI_RCRCE)
136191783Srmacklem			return (1);
137191783Srmacklem	}
138191783Srmacklem	return 0;
139191783Srmacklem}
140191783Srmacklem
141191783Srmacklem//*----------------------------------------------------------------------------
142191783Srmacklem//* \fn    MCI_GetStatus
143191783Srmacklem//* \brief Addressed card sends its status register
144191783Srmacklem//*----------------------------------------------------------------------------
145191783Srmacklemstatic unsigned int
146191783SrmacklemMCI_GetStatus()
147191783Srmacklem{
148191783Srmacklem	if (MCI_SendCommand(SEND_STATUS_CMD, MCI_Device.RCA << 16))
149191783Srmacklem		return AT91C_CMD_SEND_ERROR;
150191783Srmacklem	return (AT91C_BASE_MCI->MCI_RSPR[0]);
151191783Srmacklem}
152191783Srmacklem
153191783Srmacklem//*----------------------------------------------------------------------------
154191783Srmacklem//* \fn    MCI_ReadBlock
155191783Srmacklem//* \brief Read an ENTIRE block or PARTIAL block
156191783Srmacklem//*----------------------------------------------------------------------------
157191783Srmacklemstatic int
158191783SrmacklemMCI_ReadBlock(int src, unsigned int *dataBuffer, int sizeToRead)
159191783Srmacklem{
160191783Srmacklem//	unsigned log2sl = MCI_Device.READ_BL_LEN;
161191783Srmacklem//	unsigned sectorLength = 1 << log2sl;
162191783Srmacklem	unsigned sectorLength = 512;
163191783Srmacklem
164191783Srmacklem	///////////////////////////////////////////////////////////////////////
165191783Srmacklem	if (MCI_Device.state != AT91C_MCI_IDLE)
166191783Srmacklem		return 1;
167191783Srmacklem
168191783Srmacklem	if ((MCI_GetStatus() & AT91C_SR_READY_FOR_DATA) == 0)
169191783Srmacklem		return 1;
170191783Srmacklem
171191783Srmacklem	///////////////////////////////////////////////////////////////////////
172191783Srmacklem
173191783Srmacklem        // Init Mode Register
174191783Srmacklem	AT91C_BASE_MCI->MCI_MR |= ((sectorLength << 16) | AT91C_MCI_PDCMODE);
175191783Srmacklem
176191783Srmacklem	sizeToRead = sizeToRead / 4;
177191783Srmacklem
178191783Srmacklem	AT91C_BASE_PDC_MCI->PDC_PTCR = (AT91C_PDC_TXTDIS | AT91C_PDC_RXTDIS);
179191783Srmacklem	AT91C_BASE_PDC_MCI->PDC_RPR  = (unsigned int)dataBuffer;
180191783Srmacklem	AT91C_BASE_PDC_MCI->PDC_RCR  = sizeToRead;
181191783Srmacklem
182191783Srmacklem	// Send the Read single block command
183191783Srmacklem	if (MCI_SendCommand(READ_SINGLE_BLOCK_CMD, src))
184191783Srmacklem		return AT91C_READ_ERROR;
185191783Srmacklem	MCI_Device.state = AT91C_MCI_RX_SINGLE_BLOCK;
186191783Srmacklem
187191783Srmacklem	// Enable AT91C_MCI_RXBUFF Interrupt
188191783Srmacklem	AT91C_BASE_MCI->MCI_IER = AT91C_MCI_RXBUFF;
189191783Srmacklem
190191783Srmacklem	// (PDC) Receiver Transfer Enable
191191783Srmacklem	AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_RXTEN;
192191783Srmacklem
193191783Srmacklem	return 0;
194191783Srmacklem}
195191783Srmacklem
196191783Srmacklemint
197191783SrmacklemMCI_read(char* dest, unsigned source, unsigned length)
198191783Srmacklem{
199191783Srmacklem//	unsigned log2sl = MCI_Device.READ_BL_LEN;
200191783Srmacklem//	unsigned sectorLength = 1 << log2sl;
201191783Srmacklem	unsigned sectorLength = 512;
202191783Srmacklem	int sizeToRead;
203191783Srmacklem	unsigned int *walker;
204191783Srmacklem
205191783Srmacklem	//As long as there is data to read
206191783Srmacklem	while (length)
207191783Srmacklem	{
208191783Srmacklem		if (length > sectorLength)
209191783Srmacklem			sizeToRead = sectorLength;
210191783Srmacklem		else
211191783Srmacklem			sizeToRead = length;
212191783Srmacklem
213191783Srmacklem		MCIDeviceWaitReady(AT91C_MCI_TIMEOUT);
214191783Srmacklem		//Do the reading
215191783Srmacklem		if (MCI_ReadBlock(source,
216191783Srmacklem			(unsigned int*)dest, sizeToRead))
217191783Srmacklem			return -1;
218191783Srmacklem
219191783Srmacklem		//* Wait MCI Device Ready
220191783Srmacklem		MCIDeviceWaitReady(AT91C_MCI_TIMEOUT);
221191783Srmacklem
222191783Srmacklem		// Fix erratum in MCI part
223191783Srmacklem		for (walker = (unsigned int *)dest;
224191783Srmacklem		     walker < (unsigned int *)(dest + sizeToRead); walker++)
225191783Srmacklem		    *walker = swap(*walker);
226191783Srmacklem
227191783Srmacklem		//Update counters & pointers
228191783Srmacklem		length -= sizeToRead;
229191783Srmacklem		dest += sizeToRead;
230191783Srmacklem		source += sizeToRead;
231191783Srmacklem	}
232191783Srmacklem
233191783Srmacklem	return 0;
234191783Srmacklem}
235191783Srmacklem
236191783Srmacklem//*----------------------------------------------------------------------------
237191783Srmacklem//* \fn    MCI_SDCard_SendAppCommand
238191783Srmacklem//* \brief Specific function to send a specific command to the SDCard
239191783Srmacklem//*----------------------------------------------------------------------------
240191783Srmacklemstatic int
241191783SrmacklemMCI_SDCard_SendAppCommand(
242191783Srmacklem	unsigned int Cmd_App,
243191783Srmacklem	unsigned int Arg)
244191783Srmacklem{
245191783Srmacklem	// Send the CMD55 for application specific command
246191783Srmacklem	AT91C_BASE_MCI->MCI_ARGR = (MCI_Device.RCA << 16 );
247191783Srmacklem	AT91C_BASE_MCI->MCI_CMDR = APP_CMD;
248191783Srmacklem
249191783Srmacklem	wait_ready();
250191783Srmacklem	// if an error occurs
251191783Srmacklem	if (AT91C_BASE_MCI->MCI_SR & AT91C_MCI_SR_ERROR)
252191783Srmacklem		return (1);
253191783Srmacklem	return (MCI_SendCommand(Cmd_App,Arg));
254191783Srmacklem}
255191783Srmacklem
256191783Srmacklem//*----------------------------------------------------------------------------
257191783Srmacklem//* \fn    MCI_GetCSD
258191783Srmacklem//* \brief Asks to the specified card to send its CSD
259191783Srmacklem//*----------------------------------------------------------------------------
260191783Srmacklemstatic int
261191783SrmacklemMCI_GetCSD(unsigned int rca, unsigned int *response)
262191783Srmacklem{
263191783Srmacklem
264191783Srmacklem 	if (MCI_SendCommand(SEND_CSD_CMD, (rca << 16)))
265191783Srmacklem		return 1;
266191783Srmacklem
267191783Srmacklem	response[0] = AT91C_BASE_MCI->MCI_RSPR[0];
268191783Srmacklem   	response[1] = AT91C_BASE_MCI->MCI_RSPR[1];
269191783Srmacklem	response[2] = AT91C_BASE_MCI->MCI_RSPR[2];
270191783Srmacklem	response[3] = AT91C_BASE_MCI->MCI_RSPR[3];
271191783Srmacklem
272191783Srmacklem	return 0;
273191783Srmacklem}
274191783Srmacklem
275191783Srmacklem//*----------------------------------------------------------------------------
276191783Srmacklem//* \fn    MCI_SDCard_GetOCR
277191783Srmacklem//* \brief Asks to all cards to send their operations conditions
278191783Srmacklem//*----------------------------------------------------------------------------
279191783Srmacklemstatic int
280191783SrmacklemMCI_SDCard_GetOCR()
281191783Srmacklem{
282191783Srmacklem	unsigned int	response=0x0;
283191783Srmacklem
284191783Srmacklem	// The RCA to be used for CMD55 in Idle state shall be the card's default RCA=0x0000.
285191783Srmacklem	MCI_Device.RCA = 0x0;
286191783Srmacklem
287191783Srmacklem 	while( (response & AT91C_CARD_POWER_UP_BUSY) != AT91C_CARD_POWER_UP_BUSY ) {
288191783Srmacklem		if (MCI_SDCard_SendAppCommand(SDCARD_APP_OP_COND_CMD,
289191783Srmacklem			AT91C_MMC_HOST_VOLTAGE_RANGE))
290191783Srmacklem			return 1;
291191783Srmacklem		response = AT91C_BASE_MCI->MCI_RSPR[0];
292191783Srmacklem	}
293191783Srmacklem	return (0);
294191783Srmacklem}
295191783Srmacklem
296191783Srmacklem//*----------------------------------------------------------------------------
297191783Srmacklem//* \fn    MCI_SDCard_GetCID
298191783Srmacklem//* \brief Asks to the SDCard on the chosen slot to send its CID
299191783Srmacklem//*----------------------------------------------------------------------------
300191783Srmacklemstatic int
301191783SrmacklemMCI_SDCard_GetCID(unsigned int *response)
302191783Srmacklem{
303191783Srmacklem	if (MCI_SendCommand(ALL_SEND_CID_CMD, AT91C_NO_ARGUMENT))
304191783Srmacklem		return 1;
305191783Srmacklem
306191783Srmacklem	response[0] = AT91C_BASE_MCI->MCI_RSPR[0];
307191783Srmacklem   	response[1] = AT91C_BASE_MCI->MCI_RSPR[1];
308191783Srmacklem	response[2] = AT91C_BASE_MCI->MCI_RSPR[2];
309191783Srmacklem	response[3] = AT91C_BASE_MCI->MCI_RSPR[3];
310191783Srmacklem
311191783Srmacklem	return 0;
312191783Srmacklem}
313191783Srmacklem
314191783Srmacklem//*----------------------------------------------------------------------------
315191783Srmacklem//* \fn    MCI_SDCard_SetBusWidth
316191783Srmacklem//* \brief  Set bus width for SDCard
317191783Srmacklem//*----------------------------------------------------------------------------
318191783Srmacklemstatic int
319191783SrmacklemMCI_SDCard_SetBusWidth()
320191783Srmacklem{
321191783Srmacklem	volatile int	ret_value;
322191783Srmacklem	char			bus_width;
323191783Srmacklem
324191783Srmacklem	do {
325191783Srmacklem		ret_value=MCI_GetStatus();
326191783Srmacklem	}
327191783Srmacklem	while((ret_value > 0) && ((ret_value & AT91C_SR_READY_FOR_DATA) == 0));
328191783Srmacklem
329191783Srmacklem	// Select Card
330191783Srmacklem	MCI_SendCommand(SEL_DESEL_CARD_CMD, (MCI_Device.RCA)<<16);
331191783Srmacklem
332191783Srmacklem	// Set bus width for Sdcard
333191783Srmacklem	if (MCI_Device.SDCard_bus_width == AT91C_MCI_SCDBUS)
334191783Srmacklem		bus_width = AT91C_BUS_WIDTH_4BITS;
335191783Srmacklem	else
336191783Srmacklem		bus_width = AT91C_BUS_WIDTH_1BIT;
337191783Srmacklem
338191783Srmacklem	if (MCI_SDCard_SendAppCommand(
339191783Srmacklem	      SDCARD_SET_BUS_WIDTH_CMD,bus_width) != AT91C_CMD_SEND_OK)
340191783Srmacklem		return 1;
341191783Srmacklem
342191783Srmacklem	return 0;
343191783Srmacklem}
344191783Srmacklem
345191783Srmacklem//*----------------------------------------------------------------------------
346191783Srmacklem//* \fn    main
347191783Srmacklem//* \brief main function
348191783Srmacklem//*----------------------------------------------------------------------------
349191783Srmacklemint
350191783Srmacklemsdcard_init(void)
351191783Srmacklem{
352191783Srmacklem	unsigned int	tab_response[4];
353191783Srmacklem#ifdef REPORT_SIZE
354191783Srmacklem	unsigned int	mult,blocknr;
355191783Srmacklem#endif
356191783Srmacklem	int i;
357191783Srmacklem
358191783Srmacklem	// Init MCI for MMC and SDCard interface
359191783Srmacklem	AT91F_MCI_CfgPIO();
360191783Srmacklem	AT91F_MCI_CfgPMC();
361191783Srmacklem	AT91F_PDC_Open(AT91C_BASE_PDC_MCI);
362191783Srmacklem
363191783Srmacklem	// Init Device Structure
364191783Srmacklem	MCI_Device.state		= AT91C_MCI_IDLE;
365191783Srmacklem	MCI_Device.SDCard_bus_width	= AT91C_MCI_SCDBUS;
366191783Srmacklem
367191783Srmacklem	//* Reset the MCI
368191783Srmacklem	AT91C_BASE_MCI->MCI_CR = AT91C_MCI_MCIEN | AT91C_MCI_PWSEN;
369191783Srmacklem	AT91C_BASE_MCI->MCI_IDR = 0xFFFFFFFF;
370191783Srmacklem	AT91C_BASE_MCI->MCI_DTOR = AT91C_MCI_DTOR_1MEGA_CYCLES;
371191783Srmacklem	AT91C_BASE_MCI->MCI_MR = AT91C_MCI_PDCMODE;
372191783Srmacklem	AT91C_BASE_MCI->MCI_SDCR = AT91C_MCI_SDCARD_4BITS_SLOTA;
373191783Srmacklem	MCI_SendCommand(GO_IDLE_STATE_CMD, AT91C_NO_ARGUMENT);
374191783Srmacklem
375191783Srmacklem	for (i = 0; i < 100; i++) {
376191783Srmacklem		if (!MCI_SDCard_GetOCR(&MCI_Device))
377191783Srmacklem			break;
378191783Srmacklem		printf(".");
379191783Srmacklem	}
380191783Srmacklem	if (i >= 100)
381191783Srmacklem		return 0;
382191783Srmacklem	if (MCI_SDCard_GetCID(tab_response))
383191783Srmacklem		return 0;
384191783Srmacklem	if (MCI_SendCommand(SET_RELATIVE_ADDR_CMD, 0))
385191783Srmacklem		return 0;
386191783Srmacklem
387191783Srmacklem	MCI_Device.RCA = (AT91C_BASE_MCI->MCI_RSPR[0] >> 16);
388191783Srmacklem	if (MCI_GetCSD(MCI_Device.RCA,tab_response))
389191783Srmacklem		return 0;
390191783Srmacklem	MCI_Device.READ_BL_LEN = (tab_response[1] >> CSD_1_RD_B_LEN_S) &
391191783Srmacklem	    CSD_1_RD_B_LEN_M;
392191783Srmacklem#ifdef REPORT_SIZE
393191783Srmacklem	// compute MULT
394191783Srmacklem	mult = 1 << ( ((tab_response[2] >> CSD_2_C_SIZE_M_S) &
395191783Srmacklem	    CSD_2_C_SIZE_M_M) + 2 );
396191783Srmacklem	// compute MSB of C_SIZE
397191783Srmacklem	blocknr = ((tab_response[1] >> CSD_1_CSIZE_H_S) &
398191783Srmacklem	    CSD_1_CSIZE_H_M) << 2;
399191783Srmacklem	// compute MULT * (LSB of C-SIZE + MSB already computed + 1) = BLOCKNR
400191783Srmacklem	blocknr = mult * ((blocknr + ((tab_response[2] >> CSD_2_CSIZE_L_S) &
401191783Srmacklem	    CSD_2_CSIZE_L_M)) + 1);
402191783Srmacklem	MCI_Device.Memory_Capacity = (1 << MCI_Device.READ_BL_LEN) * blocknr;
403191783Srmacklem#endif
404191783Srmacklem	if (MCI_SDCard_SetBusWidth())
405191783Srmacklem		return 0;
406191783Srmacklem	if (MCI_SendCommand(SET_BLOCKLEN_CMD, 1 << MCI_Device.READ_BL_LEN))
407191783Srmacklem		return 0;
408191783Srmacklem#ifdef REPORT_SIZE
409191783Srmacklem	printf("Found SD card %u bytes\n", MCI_Device.Memory_Capacity);
410191783Srmacklem#endif
411191783Srmacklem	return 1;
412191783Srmacklem}
413191783Srmacklem