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

Last change on this file since 553 was 545, checked in by alain, 10 years ago

Cosmetic

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