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

Last change on this file since 542 was 529, checked in by alain, 9 years ago

1) Removing the IOC driver (integrated in the FAT library).
2) Simplifying the BDV, HBA, SDC, RDK drivers: they support
only two modes (synchronous => polling / descheduling => IRQ),
and only one access function (for both read/write).

File size: 12.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>
[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    {
[529]374        _puts("[SDC ERROR] During SD card block size 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;
[529]391} // end _sdc_init()
[283]392
393
[529]394/////////////////////////////////////////////////////
395unsigned int _sdc_access( unsigned int       use_irq,  // unused
396                          unsigned int       to_mem,
397                          unsigned int       lba,
398                          unsigned long long buf_paddr,
399                          unsigned int       count )
[283]400{
401    unsigned char args[4];
402    unsigned char sdcard_rsp;
403    unsigned int i;
404    unsigned int curr = lba;
405    unsigned int last = lba + count;
406
[529]407    if ( to_mem )  // read access
[283]408    {
[529]409        for ( ; curr < last ; curr++ )
[283]410        {
[529]411            _sdc_lseek(curr);
[283]412
[529]413            for (i = 0; i < 4; i++)
414            {
415                args[i] = (sdcard.access_pointer >> (32 - (i+1)*8)) & 0xFF;
416            }
[283]417
[529]418            _sdc_enable();
[283]419
[529]420            sdcard_rsp = _sdc_send_command(17, SDCARD_CMD, args, 0x00);
421            if ( SDCARD_CHECK_R1_ERROR(sdcard_rsp) )
422            {
423                _sdc_disable();
424                return sdcard_rsp;
425            }
[283]426
[529]427            _sdc_wait_data_block();
[283]428
[529]429            if (spi_get_data(sdcard.spi, buf_paddr, 512 ))
430            {
431                _sdc_disable();
432                return 1;
433            }
[283]434
[529]435            // Get the CRC16 (comes at the end of the data block)
436            _sdc_receive_char(); // first byte
437            _sdc_receive_char(); // second byte
[283]438
[529]439            _sdc_disable();
440
441            buf_paddr += 512;
442        }
[283]443    }
[529]444    else            // write access
445    {
446        _printf("[SDC ERROR] function _sdc_write() not iplemented yet\n");
447        _exit();
448    }
[283]449
450    return 0;
[529]451}  // _end sdc_access()
[283]452
[284]453// Local Variables:
454// tab-width: 4
455// c-basic-offset: 4
456// c-file-offsets:((innamespace . 0)(inline-open . 0))
457// indent-tabs-mode: nil
458// End:
459// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
Note: See TracBrowser for help on using the repository browser.