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

Last change on this file since 318 was 295, checked in by alain, 11 years ago

Introducing a major release, to suppoort the tsar_generic_leti platform
and the various (external or internal) peripherals configurations.
The map.xml format has been modified, in order to support the new
vci_iopic componentand a new policy for peripherals initialisation.
The IRQs are nom described in the XICU and IOPIC components
(and not anymore in the processors).
To enforce this major change, the map.xml file signature changed:
The signature value must be: 0xDACE2014

This new release has been tested on the tsar_generic_leti platform
for the following mappings:

  • 4c_4p_sort_leti
  • 4c_4p_sort_leti_ext
  • 4c_4p_transpose_leti
  • 4c_4p_transpose_leti_ext
  • 4c_1p_four_leti_ext
File size: 14.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
[283]8#include <sdc_driver.h>
[295]9#include <tty_driver.h>
[283]10#include <utils.h>
11
12#define SYSCLK_FREQ           50000000
13#define SDCARD_RESET_ITER_MAX 4
14
15static struct sdcard_dev sdcard;
16static struct spi_dev*   spi;
17
[284]18///////////////////////////////////////////////////////////////////////////////
19//      _sdc_enable()
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//      _sdc_enable()
29// This function disables SD Card select signal
30///////////////////////////////////////////////////////////////////////////////
[283]31static void _sdc_disable()
32{
33    spi_ss_deassert(sdcard.spi, sdcard.slave_id);
34}
35
[284]36///////////////////////////////////////////////////////////////////////////////
37//      _sdc_gen_tick()
38// This function writes on the SPI tx register to generate SD card clock ticks
39// - tick_count: number of ticks to generate (1 tick -> 8 clocks)
40///////////////////////////////////////////////////////////////////////////////
[283]41static void _sdc_gen_tick(unsigned int tick_count)
42{
43    register int i = 0;
44    while(i++ < tick_count) spi_put_tx(sdcard.spi, 0xFF, 0);
45}
46
[284]47///////////////////////////////////////////////////////////////////////////////
48//      _sdc_lseek()
49// This function changes the SD card access pointer position in terms of
50// blocks
51// - lba: number of logical block to move the pointer
52///////////////////////////////////////////////////////////////////////////////
[283]53void _sdc_lseek(unsigned int lba)
54{
55    sdcard.access_pointer = sdcard.block_length * lba;
56}
57
[284]58///////////////////////////////////////////////////////////////////////////////
59//      _sdc_receive_char()
60// This function gets a byte from the SD card
61///////////////////////////////////////////////////////////////////////////////
[283]62static unsigned char _sdc_receive_char()
63{
64    _sdc_gen_tick(1);
65
66    return spi_get_rx(sdcard.spi, 0);
67}
68
[284]69///////////////////////////////////////////////////////////////////////////////
70//      _sdc_wait_response()
71// This function returns when a valid response from the SD card is received or
72// a timeout has been triggered
73// Returns the SD card response value
74///////////////////////////////////////////////////////////////////////////////
[283]75static unsigned char _sdc_wait_response()
76{
77    unsigned char sdcard_rsp;
78    register int  iter;
79
80    iter       = 0;
81    sdcard_rsp = _sdc_receive_char();
82    while (
83            (iter < SDCARD_COMMAND_TIMEOUT) &&
84            !SDCARD_CHECK_R1_VALID(sdcard_rsp)
85          )
86    {
87        sdcard_rsp = _sdc_receive_char();
88        iter++;
89    }
90
91    return sdcard_rsp;
92}
93
[284]94///////////////////////////////////////////////////////////////////////////////
95//      _sdc_wait_data_block()
96// This function returns when a data block from the SD card is received (data
97// block start marker received).
98// It must be called after a read command
99///////////////////////////////////////////////////////////////////////////////
[283]100static void _sdc_wait_data_block()
101{
102        while (_sdc_receive_char() != 0xFE);
103}
104
[284]105///////////////////////////////////////////////////////////////////////////////
106//      _sdc_send_command()
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///////////////////////////////////////////////////////////////////////////////
[283]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    {
[284]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
[283]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
[284]153///////////////////////////////////////////////////////////////////////////////
154//      _sdc_open()
155// This function initializes the SD card (reset procedure)
156// - channel: channel index (only channel 0 is supported)
157// Returns 0 if success, other value if failure
158///////////////////////////////////////////////////////////////////////////////
[283]159static int _sdc_open( unsigned int channel )
160{
161        unsigned char args[4];
162        unsigned char sdcard_rsp;
163        unsigned int  iter, ersp;
164
165        sdcard.spi      = spi;
166        sdcard.slave_id = channel;
167
[284]168        // supply SD card ramp up time (min 74 cycles)
[283]169        _sdc_gen_tick(10);
170
[284]171        // Assert slave select signal
172        // Send CMD0 (Reset Command)
173        // Deassert slave select signal
[283]174        _sdc_enable();
175
176        args[0] = 0;
177        args[1] = 0;
178        args[2] = 0;
179        args[3] = 0;
180        sdcard_rsp = _sdc_send_command(0, SDCARD_CMD, args, 0x4A);
181        if ( sdcard_rsp != 0x01 )
182        {
[295]183                _printf("[SDC ERROR] card CMD0 failed\n");
[283]184                return sdcard_rsp;
185        }
186
187        _sdc_disable();
[284]188
189        // send CMD8. If card is pre-v2, It will reply with illegal command.
190        // Otherwise we announce sdhc support.
[283]191        _sdc_enable();
192        args[0] = 0;
193        args[1] = 0;
194        args[2] = 0x01;
195        args[3] = 0x01;
196        sdcard_rsp = _sdc_send_command(8, SDCARD_CMD, args, 0x63);
[284]197        if (!SDCARD_CHECK_R1_VALID(sdcard_rsp))
198    {
[295]199                _printf("[SDC ERROR] card CMD8 failed\n");
[283]200                return sdcard_rsp;
201        }
[284]202        if (!SDCARD_CHECK_R1_ERROR(sdcard_rsp))
203    {
204                // no error, command accepted. get whole reply
[283]205                ersp = _sdc_receive_char();
206                ersp = (ersp << 8) | _sdc_receive_char();
207                ersp = (ersp << 8) | _sdc_receive_char();
208                ersp = (ersp << 8) | _sdc_receive_char();
[295]209                if ((ersp & 0xffff) != 0x0101) 
210        {
[284]211                        // voltage mismatch
[295]212                        _printf("[SDC ERROR] card CMD8 mismatch : ersp = %x\n");
[283]213                        return sdcard_rsp;
214                }
[295]215                _printf("[SDC WARNING] v2 or later ");
[283]216                sdcard.sdhc = 1;
[284]217        }
218    else if ((sdcard_rsp & SDCARD_R1_ILLEGAL_CMD) == 0)
219    {
220                // other error
[295]221                _printf("[SDC ERROR] card CMD8 error\n");
[283]222                return sdcard_rsp;
[284]223        }
224    else
225    {
[283]226                sdcard.sdhc = 0;
227        }
228        _sdc_disable();
[284]229
230        // send CMD41, enabling the card
[283]231        _sdc_enable();
232        args[0] = sdcard.sdhc ? 0x40: 0;
233        args[1] = 0;
234        args[2] = 0;
235        args[3] = 0;
236
237        iter = 0;
238        while( iter++ < SDCARD_COMMAND_TIMEOUT )
239        {
240                sdcard_rsp = _sdc_send_command(41, SDCARD_ACMD, args, 0x00);
241                if( sdcard_rsp == 0x01 )
242                {
243                        continue;
244                }
245
246                break;
247        }
248
249        _sdc_disable();
[284]250        if (sdcard_rsp)
251    {
[295]252                _printf("[SDC ERROR] ACMD41 failed\n");
[283]253                return sdcard_rsp;
254        }
[284]255        if (sdcard.sdhc != 0)
256    {
257                // get the card capacity to see if it's really HC
[283]258                _sdc_enable();
259                args[0] = sdcard.sdhc ? 0x40: 0;
260                args[1] = 0;
261                args[2] = 0;
262                args[3] = 0;
263        sdcard_rsp = _sdc_send_command(58, SDCARD_CMD, args, 0x00);
[284]264                if (sdcard_rsp)
265        {
[295]266                        _printf("[SDC ERROR] CMD58 failed\n");
[283]267                        return sdcard_rsp;
268                }
269                ersp = _sdc_receive_char();
270                ersp = (ersp << 8) | _sdc_receive_char();
271                ersp = (ersp << 8) | _sdc_receive_char();
272                ersp = (ersp << 8) | _sdc_receive_char();
[284]273                if (ersp & 0x40000000)
274        {
[295]275                        _printf(" SDHC ");
276                } 
277        else
[284]278        {
[283]279                        sdcard.sdhc = 0;
280                }
281                _sdc_disable();
282        }
[295]283        _printf("card detected\n");
[283]284        return 0;
285}
286
[284]287///////////////////////////////////////////////////////////////////////////////
288//      _sdc_set_block_size()
289// This function sets the block size in bytes of the SD card
290// - len: block size in bytes (only 512 bytes supported)
291// Returns 0 if success, other value if failure
292///////////////////////////////////////////////////////////////////////////////
[283]293static unsigned int _sdc_set_block_size(unsigned int len)
294{
295    unsigned char args[4];
296    unsigned char sdcard_rsp;
297    register int i;
298
[284]299    // For now, supported block size is 512 bytes
[283]300    if (len != 512) return 1;
301
[284]302    // When using high capacity SDCARD, the block_length is not a number of bytes
303    // but a number of blocks (transfer unit)
[283]304    if (sdcard.sdhc)
305    {
306        sdcard.block_length = len / 512;
307        return 0;
308    }
309
310    for (i = 0; i < 4; i++)
311    {
312        args[i] = (len >> (32 - (i+1)*8)) & 0xFF;
313    }
314
315    _sdc_enable();
316
317    sdcard_rsp = _sdc_send_command(16, SDCARD_CMD, args, 0x00);
318    if ( SDCARD_CHECK_R1_ERROR(sdcard_rsp) )
319    {
320        _sdc_disable();
321        return sdcard_rsp;
322    }
323
324    _sdc_disable();
325
326    sdcard.block_length = len;
327
328        return 0;
329}
330
[284]331///////////////////////////////////////////////////////////////////////////////
332//      _sdc_init()
333// This function initializes the SPI controller and call sdc_open to
334// initializes SD card
335// - channel: channel to initialize (only channel 0 supported)
336// Returns 0 if success, other value if failure
337///////////////////////////////////////////////////////////////////////////////
[295]338unsigned int _sdc_init()
[283]339{
340    spi = (struct spi_dev*) &seg_ioc_base;
341
[284]342    // initializing the SPI controller
[283]343    _spi_init (
344        spi           ,
345        200000        , /**< SPI_clk: 200 Khz */
346        SYSCLK_FREQ   , /**< Sys_clk          */
347        8             , /**< Charlen: 8       */
348        SPI_TX_NEGEDGE,
349        SPI_RX_POSEDGE
350    );
351
[284]352    // initializing the SD Card
[283]353    unsigned int iter = 0;
354    unsigned char sdcard_rsp;
355    unsigned int i;
356
357    while(1)
358    {
[295]359        _printf("[SDC WARNING] Trying to initialize SD card...\n");
[283]360
[295]361        sdcard_rsp = _sdc_open( 0 );  // only channel 0
[283]362        if (sdcard_rsp == 0)
363        {
[295]364            _printf("OK\n");
[283]365            break;
366        }
367
[295]368        _printf("KO\n");
[283]369
370        for (i = 0; i < 1000; i++);
371
372        if (++iter >= SDCARD_RESET_ITER_MAX)
373        {
[295]374            _printf("\n[SDC ERROR] During SD card reset to IDLE state "
375                    "/ card response = %x\n", sdcard_rsp );
[283]376            _exit();
377        }
378    }
379
[284]380    // set the block length of the SD Card
[283]381    sdcard_rsp = _sdc_set_block_size(512);
382    if (sdcard_rsp)
383    {
[295]384        _printf("[SDC ERROR] During SD card blocklen initialization\n");
[283]385        _exit();
386    }
387
[284]388    // incrementing SDCARD clock frequency for normal function
[283]389    _spi_init (
390        spi         ,
[284]391        10000000    , // SPI_clk 10 Mhz
392        SYSCLK_FREQ , // Sys_clk
393        -1          , // Charlen: 8
[283]394        -1          ,
395        -1
396    );
397
[295]398    _printf("[SDC WARNING] Finish SD card initialization\n\r");
[283]399
400    return 0;
401}
402
403
404///////////////////////////////////////////////////////////////////////////////
405//     _sdc_read()
406// Transfer data from the block device to a memory buffer.
407// - mode     : BOOT / KERNEL / USER
408// - lba      : first block index on the block device
409// - buffer   : base address of the memory buffer (must be word aligned)
410// - count    : number of blocks to be transfered.
411// Returns 0 if success, > 0 if error.
412///////////////////////////////////////////////////////////////////////////////
413unsigned int _sdc_read( unsigned int mode,
414                        unsigned int lba,
415                        paddr_t      buffer,
416                        unsigned int count )
417{
418    unsigned char args[4];
419    unsigned char sdcard_rsp;
420    unsigned int i;
421    unsigned int curr = lba;
422    unsigned int last = lba + count;
423
424    for ( ; curr < last ; curr++ )
425    {
426        _sdc_lseek(curr);
427
428        for (i = 0; i < 4; i++)
429        {
430            args[i] = (sdcard.access_pointer >> (32 - (i+1)*8)) & 0xFF;
431        }
432
433        _sdc_enable();
434
435        sdcard_rsp = _sdc_send_command(17, SDCARD_CMD, args, 0x00);
436        if ( SDCARD_CHECK_R1_ERROR(sdcard_rsp) )
437        {
438            _sdc_disable();
439            return sdcard_rsp;
440        }
441
442        _sdc_wait_data_block();
443
444        if (spi_get_data(sdcard.spi, buffer, 512 ))
445        {
446            _sdc_disable();
447            return 1;
448        }
449
[284]450        // Get the CRC16 (comes at the end of the data block)
[283]451        _sdc_receive_char(); // first byte
452        _sdc_receive_char(); // second byte
453
454        _sdc_disable();
455
456        buffer += 512;
457    }
458
459    return 0;
460}
461
[284]462///////////////////////////////////////////////////////////////////////////////
463//     _sdc_write() (not supported for now)
464// Transfer data from memory buffer to SD card device.
465// - mode     : BOOT / KERNEL / USER
466// - lba      : destination first block index on the SD card
467// - buffer   : base address of the memory buffer (must be word aligned)
468// - count    : number of blocks to be transfered.
469// Returns 0 if success, > 0 if error.
470///////////////////////////////////////////////////////////////////////////////
[283]471unsigned int _sdc_write( unsigned int mode,
472                         unsigned int lba,
473                         paddr_t      buffer,
474                         unsigned int count )
475{
476        return 0;
477}
478
[284]479///////////////////////////////////////////////////////////////////////////////
480// Transfer data from memory buffer to SD card device.
481// - channel: channel index
482// - status: this pointer is used to transmit the status value to caller.
483// Returns 0 if success, > 0 if error.
484///////////////////////////////////////////////////////////////////////////////
[295]485unsigned int _sdc_get_status()
[283]486{
[295]487    _printf("[SDC ERROR] function _sdc_get_status() should not be called\n");
488    _exit();
[284]489
[295]490    return 0;  // to avoid a warning
[283]491}
492
[284]493///////////////////////////////////////////////////////////////////////////////
494// Returns the block size in bytes of the SD card
495///////////////////////////////////////////////////////////////////////////////
[283]496unsigned int _sdc_get_block_size()
497{
498    if (sdcard.sdhc) return sdcard.block_length*512;
499    else             return sdcard.block_length;
500}
501
[284]502// Local Variables:
503// tab-width: 4
504// c-basic-offset: 4
505// c-file-offsets:((innamespace . 0)(inline-open . 0))
506// indent-tabs-mode: nil
507// End:
508// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
Note: See TracBrowser for help on using the repository browser.