source: soft/giet_vm/giet_drivers/sdc_driver.c @ 337

Last change on this file since 337 was 320, checked in by alain, 11 years ago

All drivers have been modified to use only the information
contained in the hard_config.h file

File size: 14.3 KB
RevLine 
[284]1///////////////////////////////////////////////////////////////////////////////////
2// File     : sdc_driver.c
3// Date     : 31/08/2012
4// Author   : cesar fuguet
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
[295]7
[320]8#include <hard_config.h>
[283]9#include <sdc_driver.h>
[295]10#include <tty_driver.h>
[283]11#include <utils.h>
12
13#define SYSCLK_FREQ           50000000
14#define SDCARD_RESET_ITER_MAX 4
15
16static struct sdcard_dev sdcard;
17static struct spi_dev*   spi;
18
[284]19///////////////////////////////////////////////////////////////////////////////
20//      _sdc_enable()
21// This function enables SD Card select signal
22///////////////////////////////////////////////////////////////////////////////
[283]23static void _sdc_enable()
24{
25    spi_ss_assert(sdcard.spi, sdcard.slave_id);
26}
27
[284]28///////////////////////////////////////////////////////////////////////////////
29//      _sdc_enable()
30// This function disables SD Card select signal
31///////////////////////////////////////////////////////////////////////////////
[283]32static void _sdc_disable()
33{
34    spi_ss_deassert(sdcard.spi, sdcard.slave_id);
35}
36
[284]37///////////////////////////////////////////////////////////////////////////////
38//      _sdc_gen_tick()
39// This function writes on the SPI tx register to generate SD card clock ticks
40// - tick_count: number of ticks to generate (1 tick -> 8 clocks)
41///////////////////////////////////////////////////////////////////////////////
[283]42static void _sdc_gen_tick(unsigned int tick_count)
43{
44    register int i = 0;
45    while(i++ < tick_count) spi_put_tx(sdcard.spi, 0xFF, 0);
46}
47
[284]48///////////////////////////////////////////////////////////////////////////////
49//      _sdc_lseek()
50// This function changes the SD card access pointer position in terms of
51// blocks
52// - lba: number of logical block to move the pointer
53///////////////////////////////////////////////////////////////////////////////
[283]54void _sdc_lseek(unsigned int lba)
55{
56    sdcard.access_pointer = sdcard.block_length * lba;
57}
58
[284]59///////////////////////////////////////////////////////////////////////////////
60//      _sdc_receive_char()
61// This function gets a byte from the SD card
62///////////////////////////////////////////////////////////////////////////////
[283]63static unsigned char _sdc_receive_char()
64{
65    _sdc_gen_tick(1);
66
67    return spi_get_rx(sdcard.spi, 0);
68}
69
[284]70///////////////////////////////////////////////////////////////////////////////
71//      _sdc_wait_response()
72// This function returns when a valid response from the SD card is received or
73// a timeout has been triggered
74// Returns the SD card response value
75///////////////////////////////////////////////////////////////////////////////
[283]76static unsigned char _sdc_wait_response()
77{
78    unsigned char sdcard_rsp;
79    register int  iter;
80
81    iter       = 0;
82    sdcard_rsp = _sdc_receive_char();
83    while (
84            (iter < SDCARD_COMMAND_TIMEOUT) &&
85            !SDCARD_CHECK_R1_VALID(sdcard_rsp)
86          )
87    {
88        sdcard_rsp = _sdc_receive_char();
89        iter++;
90    }
91
92    return sdcard_rsp;
93}
94
[284]95///////////////////////////////////////////////////////////////////////////////
96//      _sdc_wait_data_block()
97// This function returns when a data block from the SD card is received (data
98// block start marker received).
99// It must be called after a read command
100///////////////////////////////////////////////////////////////////////////////
[283]101static void _sdc_wait_data_block()
102{
103        while (_sdc_receive_char() != 0xFE);
104}
105
[284]106///////////////////////////////////////////////////////////////////////////////
107//      _sdc_send_command()
108// This function sends a command to the SD card
109// - index: CMD index
110// - app: type of command
111// - args: CMD arguments vector
112// - crc7: CRC (7 bits) to send
113///////////////////////////////////////////////////////////////////////////////
[283]114static int _sdc_send_command ( int      index,
115                               int      app  ,
116                               void *   args ,
117                               unsigned crc7 )
118{
119    unsigned char sdcard_rsp;
120    unsigned char * _args;
121
122    _sdc_gen_tick(5); 
123
124    if (app == SDCARD_ACMD)
125    {
[284]126        spi_put_tx(sdcard.spi, 0x40 | 55         , 0 );// CMD and START bit
127        spi_put_tx(sdcard.spi, 0x00              , 0 );// Argument[0]
128        spi_put_tx(sdcard.spi, 0x00              , 0 );// Argument[1]
129        spi_put_tx(sdcard.spi, 0x00              , 0 );// Argument[2]
130        spi_put_tx(sdcard.spi, 0x00              , 0 );// Argument[3]
131        spi_put_tx(sdcard.spi, 0x01 | (crc7 << 1), 0 );// END bit
[283]132
133        sdcard_rsp = _sdc_wait_response();
134        if (SDCARD_CHECK_R1_ERROR(sdcard_rsp))
135        {
136            return sdcard_rsp;       
137        }
138    }
139
140    _args = (unsigned char *) args;
141
142    _sdc_gen_tick(1); 
143
144    spi_put_tx(sdcard.spi, 0x40 | index      , 0 );
145    spi_put_tx(sdcard.spi, _args[0]          , 0 );
146    spi_put_tx(sdcard.spi, _args[1]          , 0 );
147    spi_put_tx(sdcard.spi, _args[2]          , 0 );
148    spi_put_tx(sdcard.spi, _args[3]          , 0 );
149    spi_put_tx(sdcard.spi, 0x01 | (crc7 << 1), 0 );
150
151    return _sdc_wait_response();
152}
153
[284]154///////////////////////////////////////////////////////////////////////////////
155//      _sdc_open()
156// This function initializes the SD card (reset procedure)
157// - channel: channel index (only channel 0 is supported)
158// Returns 0 if success, other value if failure
159///////////////////////////////////////////////////////////////////////////////
[283]160static int _sdc_open( unsigned int channel )
161{
162        unsigned char args[4];
163        unsigned char sdcard_rsp;
164        unsigned int  iter, ersp;
165
166        sdcard.spi      = spi;
167        sdcard.slave_id = channel;
168
[284]169        // supply SD card ramp up time (min 74 cycles)
[283]170        _sdc_gen_tick(10);
171
[284]172        // Assert slave select signal
173        // Send CMD0 (Reset Command)
174        // Deassert slave select signal
[283]175        _sdc_enable();
176
177        args[0] = 0;
178        args[1] = 0;
179        args[2] = 0;
180        args[3] = 0;
181        sdcard_rsp = _sdc_send_command(0, SDCARD_CMD, args, 0x4A);
182        if ( sdcard_rsp != 0x01 )
183        {
[295]184                _printf("[SDC ERROR] card CMD0 failed\n");
[283]185                return sdcard_rsp;
186        }
187
188        _sdc_disable();
[284]189
190        // send CMD8. If card is pre-v2, It will reply with illegal command.
191        // Otherwise we announce sdhc support.
[283]192        _sdc_enable();
193        args[0] = 0;
194        args[1] = 0;
195        args[2] = 0x01;
196        args[3] = 0x01;
197        sdcard_rsp = _sdc_send_command(8, SDCARD_CMD, args, 0x63);
[284]198        if (!SDCARD_CHECK_R1_VALID(sdcard_rsp))
199    {
[295]200                _printf("[SDC ERROR] card CMD8 failed\n");
[283]201                return sdcard_rsp;
202        }
[284]203        if (!SDCARD_CHECK_R1_ERROR(sdcard_rsp))
204    {
205                // no error, command accepted. get whole reply
[283]206                ersp = _sdc_receive_char();
207                ersp = (ersp << 8) | _sdc_receive_char();
208                ersp = (ersp << 8) | _sdc_receive_char();
209                ersp = (ersp << 8) | _sdc_receive_char();
[295]210                if ((ersp & 0xffff) != 0x0101) 
211        {
[284]212                        // voltage mismatch
[295]213                        _printf("[SDC ERROR] card CMD8 mismatch : ersp = %x\n");
[283]214                        return sdcard_rsp;
215                }
[295]216                _printf("[SDC WARNING] v2 or later ");
[283]217                sdcard.sdhc = 1;
[284]218        }
219    else if ((sdcard_rsp & SDCARD_R1_ILLEGAL_CMD) == 0)
220    {
221                // other error
[295]222                _printf("[SDC ERROR] card CMD8 error\n");
[283]223                return sdcard_rsp;
[284]224        }
225    else
226    {
[283]227                sdcard.sdhc = 0;
228        }
229        _sdc_disable();
[284]230
231        // send CMD41, enabling the card
[283]232        _sdc_enable();
233        args[0] = sdcard.sdhc ? 0x40: 0;
234        args[1] = 0;
235        args[2] = 0;
236        args[3] = 0;
237
238        iter = 0;
239        while( iter++ < SDCARD_COMMAND_TIMEOUT )
240        {
241                sdcard_rsp = _sdc_send_command(41, SDCARD_ACMD, args, 0x00);
242                if( sdcard_rsp == 0x01 )
243                {
244                        continue;
245                }
246
247                break;
248        }
249
250        _sdc_disable();
[284]251        if (sdcard_rsp)
252    {
[295]253                _printf("[SDC ERROR] ACMD41 failed\n");
[283]254                return sdcard_rsp;
255        }
[284]256        if (sdcard.sdhc != 0)
257    {
258                // get the card capacity to see if it's really HC
[283]259                _sdc_enable();
260                args[0] = sdcard.sdhc ? 0x40: 0;
261                args[1] = 0;
262                args[2] = 0;
263                args[3] = 0;
264        sdcard_rsp = _sdc_send_command(58, SDCARD_CMD, args, 0x00);
[284]265                if (sdcard_rsp)
266        {
[295]267                        _printf("[SDC ERROR] CMD58 failed\n");
[283]268                        return sdcard_rsp;
269                }
270                ersp = _sdc_receive_char();
271                ersp = (ersp << 8) | _sdc_receive_char();
272                ersp = (ersp << 8) | _sdc_receive_char();
273                ersp = (ersp << 8) | _sdc_receive_char();
[284]274                if (ersp & 0x40000000)
275        {
[295]276                        _printf(" SDHC ");
277                } 
278        else
[284]279        {
[283]280                        sdcard.sdhc = 0;
281                }
282                _sdc_disable();
283        }
[295]284        _printf("card detected\n");
[283]285        return 0;
286}
287
[284]288///////////////////////////////////////////////////////////////////////////////
289//      _sdc_set_block_size()
290// This function sets the block size in bytes of the SD card
291// - len: block size in bytes (only 512 bytes supported)
292// Returns 0 if success, other value if failure
293///////////////////////////////////////////////////////////////////////////////
[283]294static unsigned int _sdc_set_block_size(unsigned int len)
295{
296    unsigned char args[4];
297    unsigned char sdcard_rsp;
298    register int i;
299
[284]300    // For now, supported block size is 512 bytes
[283]301    if (len != 512) return 1;
302
[284]303    // When using high capacity SDCARD, the block_length is not a number of bytes
304    // but a number of blocks (transfer unit)
[283]305    if (sdcard.sdhc)
306    {
307        sdcard.block_length = len / 512;
308        return 0;
309    }
310
311    for (i = 0; i < 4; i++)
312    {
313        args[i] = (len >> (32 - (i+1)*8)) & 0xFF;
314    }
315
316    _sdc_enable();
317
318    sdcard_rsp = _sdc_send_command(16, SDCARD_CMD, args, 0x00);
319    if ( SDCARD_CHECK_R1_ERROR(sdcard_rsp) )
320    {
321        _sdc_disable();
322        return sdcard_rsp;
323    }
324
325    _sdc_disable();
326
327    sdcard.block_length = len;
328
329        return 0;
330}
331
[284]332///////////////////////////////////////////////////////////////////////////////
333//      _sdc_init()
334// This function initializes the SPI controller and call sdc_open to
335// initializes SD card
336// - channel: channel to initialize (only channel 0 supported)
337// Returns 0 if success, other value if failure
338///////////////////////////////////////////////////////////////////////////////
[295]339unsigned int _sdc_init()
[283]340{
[320]341    spi = (struct spi_dev*)SEG_IOC_BASE;
[283]342
[284]343    // initializing the SPI controller
[283]344    _spi_init (
345        spi           ,
346        200000        , /**< SPI_clk: 200 Khz */
347        SYSCLK_FREQ   , /**< Sys_clk          */
348        8             , /**< Charlen: 8       */
349        SPI_TX_NEGEDGE,
350        SPI_RX_POSEDGE
351    );
352
[284]353    // initializing the SD Card
[283]354    unsigned int iter = 0;
355    unsigned char sdcard_rsp;
356    unsigned int i;
357
358    while(1)
359    {
[295]360        _printf("[SDC WARNING] Trying to initialize SD card...\n");
[283]361
[295]362        sdcard_rsp = _sdc_open( 0 );  // only channel 0
[283]363        if (sdcard_rsp == 0)
364        {
[295]365            _printf("OK\n");
[283]366            break;
367        }
368
[295]369        _printf("KO\n");
[283]370
371        for (i = 0; i < 1000; i++);
372
373        if (++iter >= SDCARD_RESET_ITER_MAX)
374        {
[295]375            _printf("\n[SDC ERROR] During SD card reset to IDLE state "
376                    "/ card response = %x\n", sdcard_rsp );
[283]377            _exit();
378        }
379    }
380
[284]381    // set the block length of the SD Card
[283]382    sdcard_rsp = _sdc_set_block_size(512);
383    if (sdcard_rsp)
384    {
[295]385        _printf("[SDC ERROR] During SD card blocklen initialization\n");
[283]386        _exit();
387    }
388
[284]389    // incrementing SDCARD clock frequency for normal function
[283]390    _spi_init (
391        spi         ,
[284]392        10000000    , // SPI_clk 10 Mhz
393        SYSCLK_FREQ , // Sys_clk
394        -1          , // Charlen: 8
[283]395        -1          ,
396        -1
397    );
398
[295]399    _printf("[SDC WARNING] Finish SD card initialization\n\r");
[283]400
401    return 0;
402}
403
404
405///////////////////////////////////////////////////////////////////////////////
406//     _sdc_read()
407// Transfer data from the block device to a memory buffer.
408// - mode     : BOOT / KERNEL / USER
409// - lba      : first block index on the block device
410// - buffer   : base address of the memory buffer (must be word aligned)
411// - count    : number of blocks to be transfered.
412// Returns 0 if success, > 0 if error.
413///////////////////////////////////////////////////////////////////////////////
414unsigned int _sdc_read( unsigned int mode,
415                        unsigned int lba,
416                        paddr_t      buffer,
417                        unsigned int count )
418{
419    unsigned char args[4];
420    unsigned char sdcard_rsp;
421    unsigned int i;
422    unsigned int curr = lba;
423    unsigned int last = lba + count;
424
425    for ( ; curr < last ; curr++ )
426    {
427        _sdc_lseek(curr);
428
429        for (i = 0; i < 4; i++)
430        {
431            args[i] = (sdcard.access_pointer >> (32 - (i+1)*8)) & 0xFF;
432        }
433
434        _sdc_enable();
435
436        sdcard_rsp = _sdc_send_command(17, SDCARD_CMD, args, 0x00);
437        if ( SDCARD_CHECK_R1_ERROR(sdcard_rsp) )
438        {
439            _sdc_disable();
440            return sdcard_rsp;
441        }
442
443        _sdc_wait_data_block();
444
445        if (spi_get_data(sdcard.spi, buffer, 512 ))
446        {
447            _sdc_disable();
448            return 1;
449        }
450
[284]451        // Get the CRC16 (comes at the end of the data block)
[283]452        _sdc_receive_char(); // first byte
453        _sdc_receive_char(); // second byte
454
455        _sdc_disable();
456
457        buffer += 512;
458    }
459
460    return 0;
461}
462
[284]463///////////////////////////////////////////////////////////////////////////////
464//     _sdc_write() (not supported for now)
465// Transfer data from memory buffer to SD card device.
466// - mode     : BOOT / KERNEL / USER
467// - lba      : destination first block index on the SD card
468// - buffer   : base address of the memory buffer (must be word aligned)
469// - count    : number of blocks to be transfered.
470// Returns 0 if success, > 0 if error.
471///////////////////////////////////////////////////////////////////////////////
[283]472unsigned int _sdc_write( unsigned int mode,
473                         unsigned int lba,
474                         paddr_t      buffer,
475                         unsigned int count )
476{
477        return 0;
478}
479
[284]480///////////////////////////////////////////////////////////////////////////////
481// Transfer data from memory buffer to SD card device.
482// - channel: channel index
483// - status: this pointer is used to transmit the status value to caller.
484// Returns 0 if success, > 0 if error.
485///////////////////////////////////////////////////////////////////////////////
[295]486unsigned int _sdc_get_status()
[283]487{
[295]488    _printf("[SDC ERROR] function _sdc_get_status() should not be called\n");
489    _exit();
[284]490
[295]491    return 0;  // to avoid a warning
[283]492}
493
[284]494///////////////////////////////////////////////////////////////////////////////
495// Returns the block size in bytes of the SD card
496///////////////////////////////////////////////////////////////////////////////
[283]497unsigned int _sdc_get_block_size()
498{
499    if (sdcard.sdhc) return sdcard.block_length*512;
500    else             return sdcard.block_length;
501}
502
[284]503// Local Variables:
504// tab-width: 4
505// c-basic-offset: 4
506// c-file-offsets:((innamespace . 0)(inline-open . 0))
507// indent-tabs-mode: nil
508// End:
509// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
Note: See TracBrowser for help on using the repository browser.