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

Last change on this file since 479 was 456, checked in by alain, 10 years ago

Defining the NIC and CMA drivers (validated by the classif application).
Updating other drivers to comply with the new tty0 common file.

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