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
Line 
1///////////////////////////////////////////////////////////////////////////////////
2// File     : sdc_driver.c
3// Date     : 31/08/2012
4// Author   : cesar fuguet
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7
8#include <hard_config.h>
9#include <sdc_driver.h>
10#include <tty0.h>
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
19///////////////////////////////////////////////////////////////////////////////
20// This function enables SD Card select signal
21///////////////////////////////////////////////////////////////////////////////
22static void _sdc_enable()
23{
24    spi_ss_assert(sdcard.spi, sdcard.slave_id);
25}
26
27///////////////////////////////////////////////////////////////////////////////
28// This function disables SD Card select signal
29///////////////////////////////////////////////////////////////////////////////
30static void _sdc_disable()
31{
32    spi_ss_deassert(sdcard.spi, sdcard.slave_id);
33}
34
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///////////////////////////////////////////////////////////////////////////////
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
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///////////////////////////////////////////////////////////////////////////////
50void _sdc_lseek(unsigned int lba)
51{
52    sdcard.access_pointer = sdcard.block_length * lba;
53}
54
55///////////////////////////////////////////////////////////////////////////////
56// This function gets a byte from the SD card
57///////////////////////////////////////////////////////////////////////////////
58static unsigned char _sdc_receive_char()
59{
60    _sdc_gen_tick(1);
61
62    return spi_get_rx(sdcard.spi, 0);
63}
64
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///////////////////////////////////////////////////////////////////////////////
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
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///////////////////////////////////////////////////////////////////////////////
94static void _sdc_wait_data_block()
95{
96        while (_sdc_receive_char() != 0xFE);
97}
98
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///////////////////////////////////////////////////////////////////////////////
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    {
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
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
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///////////////////////////////////////////////////////////////////////////////
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
160        // supply SD card ramp up time (min 74 cycles)
161        _sdc_gen_tick(10);
162
163        // Assert slave select signal
164        // Send CMD0 (Reset Command)
165        // Deassert slave select signal
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        {
175                _puts("[SDC ERROR] card CMD0 failed\n");
176                return sdcard_rsp;
177        }
178
179        _sdc_disable();
180
181        // send CMD8. If card is pre-v2, It will reply with illegal command.
182        // Otherwise we announce sdhc support.
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);
189        if (!SDCARD_CHECK_R1_VALID(sdcard_rsp))
190    {
191                _puts("[SDC ERROR] card CMD8 failed\n");
192                return sdcard_rsp;
193        }
194        if (!SDCARD_CHECK_R1_ERROR(sdcard_rsp))
195    {
196                // no error, command accepted. get whole reply
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();
201                if ((ersp & 0xffff) != 0x0101) 
202        {
203                        // voltage mismatch
204                        _puts("[SDC ERROR] card CMD8 mismatch : ersp = %x\n");
205                        return sdcard_rsp;
206                }
207                _puts("[SDC WARNING] v2 or later ");
208                sdcard.sdhc = 1;
209        }
210    else if ((sdcard_rsp & SDCARD_R1_ILLEGAL_CMD) == 0)
211    {
212                // other error
213                _puts("[SDC ERROR] card CMD8 error\n");
214                return sdcard_rsp;
215        }
216    else
217    {
218                sdcard.sdhc = 0;
219        }
220        _sdc_disable();
221
222        // send CMD41, enabling the card
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();
242        if (sdcard_rsp)
243    {
244                _puts("[SDC ERROR] ACMD41 failed\n");
245                return sdcard_rsp;
246        }
247        if (sdcard.sdhc != 0)
248    {
249                // get the card capacity to see if it's really HC
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);
256                if (sdcard_rsp)
257        {
258                        _puts("[SDC ERROR] CMD58 failed\n");
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();
265                if (ersp & 0x40000000)
266        {
267                        _puts(" SDHC ");
268                } 
269        else
270        {
271                        sdcard.sdhc = 0;
272                }
273                _sdc_disable();
274        }
275        _puts("card detected\n");
276        return 0;
277}
278
279///////////////////////////////////////////////////////////////////////////////
280// This function sets the block size in the SD card.
281// - len: block size in bytes (only 512 bytes supported)
282// Returns 0 if success, other value if failure
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
290    // For now, supported block size is 512 bytes
291    if (len != 512) return 1;
292
293    // When using high capacity SDCARD, the block_length is not a number of bytes
294    // but a number of blocks (transfer unit)
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
322/////////////////////////////////////////////////////////////////////////////////
323//           Extern functions
324/////////////////////////////////////////////////////////////////////////////////
325
326////////////////////////
327unsigned int _sdc_init()
328{
329    spi = (struct spi_dev*)SEG_IOC_BASE;
330
331    // initializing the SPI controller
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
341    // initializing the SD Card
342    unsigned int iter = 0;
343    unsigned char sdcard_rsp;
344    unsigned int i;
345
346    while(1)
347    {
348        _puts("[SDC WARNING] Trying to initialize SD card...\n");
349
350        sdcard_rsp = _sdc_open( 0 );  // only channel 0
351        if (sdcard_rsp == 0)
352        {
353            _puts("OK\n");
354            break;
355        }
356
357        _puts("KO\n");
358
359        for (i = 0; i < 1000; i++);
360
361        if (++iter >= SDCARD_RESET_ITER_MAX)
362        {
363            _puts("\n[SDC ERROR] During SD card reset / card response = ");
364            _putx( sdcard_rsp );
365            _puts("\n");
366            _exit();
367        }
368    }
369
370    // set the block length of the SD Card
371    sdcard_rsp = _sdc_set_block_size(512);
372    if (sdcard_rsp)
373    {
374        _puts("[SDC ERROR] During SD card block size initialization\n");
375        _exit();
376    }
377
378    // incrementing SDCARD clock frequency for normal function
379    _spi_init (
380        spi         ,
381        10000000    , // SPI_clk 10 Mhz
382        SYSCLK_FREQ , // Sys_clk
383        -1          , // Charlen: 8
384        -1          ,
385        -1
386    );
387
388    _puts("[SDC WARNING] Finish SD card initialization\n\r");
389
390    return 0;
391} // end _sdc_init()
392
393
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 )
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
407    if ( to_mem )  // read access
408    {
409        for ( ; curr < last ; curr++ )
410        {
411            _sdc_lseek(curr);
412
413            for (i = 0; i < 4; i++)
414            {
415                args[i] = (sdcard.access_pointer >> (32 - (i+1)*8)) & 0xFF;
416            }
417
418            _sdc_enable();
419
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            }
426
427            _sdc_wait_data_block();
428
429            if (spi_get_data(sdcard.spi, buf_paddr, 512 ))
430            {
431                _sdc_disable();
432                return 1;
433            }
434
435            // Get the CRC16 (comes at the end of the data block)
436            _sdc_receive_char(); // first byte
437            _sdc_receive_char(); // second byte
438
439            _sdc_disable();
440
441            buf_paddr += 512;
442        }
443    }
444    else            // write access
445    {
446        _printf("[SDC ERROR] function _sdc_write() not iplemented yet\n");
447        _exit();
448    }
449
450    return 0;
451}  // _end sdc_access()
452
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.