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

Last change on this file since 293 was 289, checked in by cfuguet, 11 years ago

Modifications on GIET-VM IOC driver:

  • Introducing new layer on the IOC driver. Every call to ioc_read, ioc_write, ioc_get_block_size or ioc_init

functions will call the specific driver of the used IOC
controller. Supported IOC controllers are (for now) :

  1. BDV (Soclib Block Device)
  2. HBA
  3. SPI (SDCARD - SPI controller)
  • All functions of IOC controllers drivers respect the same interface.
  • To specify the used IOC controller of the platform, a subtype field has been introduced on the map.xml file. This subtype field must be declared on the IOC periph instantiation. Available subtypes (for now) : BDV, HBA or SPI.
File size: 14.2 KB
RevLine 
[284]1///////////////////////////////////////////////////////////////////////////////////
2// File     : sdc_driver.c
3// Date     : 31/08/2012
4// Author   : cesar fuguet
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
[283]7#include <sdc_driver.h>
8#include <utils.h>
9
10#define SYSCLK_FREQ           50000000
11#define SDCARD_RESET_ITER_MAX 4
12
13static struct sdcard_dev sdcard;
14static struct spi_dev*   spi;
15
[284]16///////////////////////////////////////////////////////////////////////////////
17//      _sdc_enable()
18// This function enables SD Card select signal
19///////////////////////////////////////////////////////////////////////////////
[283]20static void _sdc_enable()
21{
22    spi_ss_assert(sdcard.spi, sdcard.slave_id);
23}
24
[284]25///////////////////////////////////////////////////////////////////////////////
26//      _sdc_enable()
27// This function disables SD Card select signal
28///////////////////////////////////////////////////////////////////////////////
[283]29static void _sdc_disable()
30{
31    spi_ss_deassert(sdcard.spi, sdcard.slave_id);
32}
33
[284]34///////////////////////////////////////////////////////////////////////////////
35//      _sdc_gen_tick()
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//      _sdc_lseek()
47// This function changes the SD card access pointer position in terms of
48// blocks
49// - lba: number of logical block to move the pointer
50///////////////////////////////////////////////////////////////////////////////
[283]51void _sdc_lseek(unsigned int lba)
52{
53    sdcard.access_pointer = sdcard.block_length * lba;
54}
55
[284]56///////////////////////////////////////////////////////////////////////////////
57//      _sdc_receive_char()
58// This function gets a byte from the SD card
59///////////////////////////////////////////////////////////////////////////////
[283]60static unsigned char _sdc_receive_char()
61{
62    _sdc_gen_tick(1);
63
64    return spi_get_rx(sdcard.spi, 0);
65}
66
[284]67///////////////////////////////////////////////////////////////////////////////
68//      _sdc_wait_response()
69// This function returns when a valid response from the SD card is received or
70// a timeout has been triggered
71// Returns the SD card response value
72///////////////////////////////////////////////////////////////////////////////
[283]73static unsigned char _sdc_wait_response()
74{
75    unsigned char sdcard_rsp;
76    register int  iter;
77
78    iter       = 0;
79    sdcard_rsp = _sdc_receive_char();
80    while (
81            (iter < SDCARD_COMMAND_TIMEOUT) &&
82            !SDCARD_CHECK_R1_VALID(sdcard_rsp)
83          )
84    {
85        sdcard_rsp = _sdc_receive_char();
86        iter++;
87    }
88
89    return sdcard_rsp;
90}
91
[284]92///////////////////////////////////////////////////////////////////////////////
93//      _sdc_wait_data_block()
94// This function returns when a data block from the SD card is received (data
95// block start marker received).
96// It must be called after a read command
97///////////////////////////////////////////////////////////////////////////////
[283]98static void _sdc_wait_data_block()
99{
100        while (_sdc_receive_char() != 0xFE);
101}
102
[284]103///////////////////////////////////////////////////////////////////////////////
104//      _sdc_send_command()
105// This function sends a command to the SD card
106// - index: CMD index
107// - app: type of command
108// - args: CMD arguments vector
109// - crc7: CRC (7 bits) to send
110///////////////////////////////////////////////////////////////////////////////
[283]111static int _sdc_send_command ( int      index,
112                               int      app  ,
113                               void *   args ,
114                               unsigned crc7 )
115{
116    unsigned char sdcard_rsp;
117    unsigned char * _args;
118
119    _sdc_gen_tick(5); 
120
121    if (app == SDCARD_ACMD)
122    {
[284]123        spi_put_tx(sdcard.spi, 0x40 | 55         , 0 );// CMD and START bit
124        spi_put_tx(sdcard.spi, 0x00              , 0 );// Argument[0]
125        spi_put_tx(sdcard.spi, 0x00              , 0 );// Argument[1]
126        spi_put_tx(sdcard.spi, 0x00              , 0 );// Argument[2]
127        spi_put_tx(sdcard.spi, 0x00              , 0 );// Argument[3]
128        spi_put_tx(sdcard.spi, 0x01 | (crc7 << 1), 0 );// END bit
[283]129
130        sdcard_rsp = _sdc_wait_response();
131        if (SDCARD_CHECK_R1_ERROR(sdcard_rsp))
132        {
133            return sdcard_rsp;       
134        }
135    }
136
137    _args = (unsigned char *) args;
138
139    _sdc_gen_tick(1); 
140
141    spi_put_tx(sdcard.spi, 0x40 | index      , 0 );
142    spi_put_tx(sdcard.spi, _args[0]          , 0 );
143    spi_put_tx(sdcard.spi, _args[1]          , 0 );
144    spi_put_tx(sdcard.spi, _args[2]          , 0 );
145    spi_put_tx(sdcard.spi, _args[3]          , 0 );
146    spi_put_tx(sdcard.spi, 0x01 | (crc7 << 1), 0 );
147
148    return _sdc_wait_response();
149}
150
[284]151///////////////////////////////////////////////////////////////////////////////
152//      _sdc_open()
153// This function initializes the SD card (reset procedure)
154// - channel: channel index (only channel 0 is supported)
155// Returns 0 if success, other value if failure
156///////////////////////////////////////////////////////////////////////////////
[283]157static int _sdc_open( unsigned int channel )
158{
159        unsigned char args[4];
160        unsigned char sdcard_rsp;
161        unsigned int  iter, ersp;
162
163        sdcard.spi      = spi;
164        sdcard.slave_id = channel;
165
[284]166        // supply SD card ramp up time (min 74 cycles)
[283]167        _sdc_gen_tick(10);
168
[284]169        // Assert slave select signal
170        // Send CMD0 (Reset Command)
171        // Deassert slave select signal
[283]172        _sdc_enable();
173
174        args[0] = 0;
175        args[1] = 0;
176        args[2] = 0;
177        args[3] = 0;
178        sdcard_rsp = _sdc_send_command(0, SDCARD_CMD, args, 0x4A);
179        if ( sdcard_rsp != 0x01 )
180        {
181
182                _puts("card CMD0 failed ");
183                return sdcard_rsp;
184        }
185
186        _sdc_disable();
[284]187
188        // send CMD8. If card is pre-v2, It will reply with illegal command.
189        // Otherwise we announce sdhc support.
[283]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);
[284]196        if (!SDCARD_CHECK_R1_VALID(sdcard_rsp))
197    {
[283]198                _puts("card CMD8 failed ");
199                return sdcard_rsp;
200        }
[284]201        if (!SDCARD_CHECK_R1_ERROR(sdcard_rsp))
202    {
203                // no error, command accepted. get whole reply
[283]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) {
[284]209                        // voltage mismatch
[283]210                        _puts("card CMD8 mismatch: ");
211                        _putx(ersp);
212                        return sdcard_rsp;
213                }
214                _puts("v2 or later ");
215                sdcard.sdhc = 1;
[284]216        }
217    else if ((sdcard_rsp & SDCARD_R1_ILLEGAL_CMD) == 0)
218    {
219                // other error
[283]220                _puts("card CMD8 error ");
221                return sdcard_rsp;
[284]222        }
223    else
224    {
[283]225                sdcard.sdhc = 0;
226        }
227        _sdc_disable();
[284]228
229        // send CMD41, enabling the card
[283]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();
[284]249        if (sdcard_rsp)
250    {
[283]251                _puts("SD ACMD41 failed ");
252                return sdcard_rsp;
253        }
[284]254        if (sdcard.sdhc != 0)
255    {
256                // get the card capacity to see if it's really HC
[283]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);
[284]263                if (sdcard_rsp)
264        {
[283]265                        _puts("SD CMD58 failed ");
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();
[284]272                if (ersp & 0x40000000)
273        {
[283]274                        _puts("SDHC ");
[284]275                } else
276        {
[283]277                        sdcard.sdhc = 0;
278                }
279                _sdc_disable();
280        }
281        _puts("card detected ");
282        return 0;
283}
284
[284]285///////////////////////////////////////////////////////////////////////////////
286//      _sdc_set_block_size()
287// This function sets the block size in bytes of the SD card
288// - len: block size in bytes (only 512 bytes supported)
289// Returns 0 if success, other value if failure
290///////////////////////////////////////////////////////////////////////////////
[283]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
[284]297    // For now, supported block size is 512 bytes
[283]298    if (len != 512) return 1;
299
[284]300    // When using high capacity SDCARD, the block_length is not a number of bytes
301    // but a number of blocks (transfer unit)
[283]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
[284]329///////////////////////////////////////////////////////////////////////////////
330//      _sdc_init()
331// This function initializes the SPI controller and call sdc_open to
332// initializes SD card
333// - channel: channel to initialize (only channel 0 supported)
334// Returns 0 if success, other value if failure
335///////////////////////////////////////////////////////////////////////////////
[283]336unsigned int _sdc_init( unsigned int channel )
337{
338    spi = (struct spi_dev*) &seg_ioc_base;
339
[284]340    // initializing the SPI controller
[283]341    _spi_init (
342        spi           ,
343        200000        , /**< SPI_clk: 200 Khz */
344        SYSCLK_FREQ   , /**< Sys_clk          */
345        8             , /**< Charlen: 8       */
346        SPI_TX_NEGEDGE,
347        SPI_RX_POSEDGE
348    );
349
[284]350    // initializing the SD Card
[283]351    unsigned int iter = 0;
352    unsigned char sdcard_rsp;
353    unsigned int i;
354
355    while(1)
356    {
357        _puts("Trying to initialize SD card... ");
358
359        sdcard_rsp = _sdc_open( channel );
360        if (sdcard_rsp == 0)
361        {
362            _puts("OK\n");
363            break;
364        }
365
366        _puts("KO\n");
367
368        for (i = 0; i < 1000; i++);
369
370        if (++iter >= SDCARD_RESET_ITER_MAX)
371        {
372            _puts("\nERROR: During SD card reset to IDLE state\n"
373                 "/ card response = ");
374            _putx(sdcard_rsp);
375            _puts("\n");
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    {
384        _puts("ERROR: During SD card blocklen initialization\n");
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
398    _puts("Finish block device initialization\n\r");
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//     _sdc_get_status()
481// Transfer data from memory buffer to SD card device.
482// - channel: channel index
483// - status: this pointer is used to transmit the status value to caller.
484// Returns 0 if success, > 0 if error.
485///////////////////////////////////////////////////////////////////////////////
[283]486unsigned int _sdc_get_status( unsigned int channel ,
487                              unsigned int* status )
488{
[284]489    *status = BLOCK_DEVICE_IDLE;
490
491    return 0;
[283]492}
493
[284]494///////////////////////////////////////////////////////////////////////////////
495//     _sdc_get_block_size()
496// Returns the block size in bytes of the SD card
497///////////////////////////////////////////////////////////////////////////////
[283]498unsigned int _sdc_get_block_size()
499{
500    if (sdcard.sdhc) return sdcard.block_length*512;
501    else             return sdcard.block_length;
502}
503
[284]504// Local Variables:
505// tab-width: 4
506// c-basic-offset: 4
507// c-file-offsets:((innamespace . 0)(inline-open . 0))
508// indent-tabs-mode: nil
509// End:
510// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
Note: See TracBrowser for help on using the repository browser.