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

Last change on this file since 449 was 437, checked in by alain, 10 years ago

Introducing dynamic allocation of peripheral channel(TTY, NIC, TIM, CMA)
Removint the ICU driver : ICU component not supported anymore.
Removing the FBF driver.

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>
[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// 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.