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

Last change on this file since 542 was 529, checked in by alain, 10 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.