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

Last change on this file since 289 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
Line 
1///////////////////////////////////////////////////////////////////////////////////
2// File     : sdc_driver.c
3// Date     : 31/08/2012
4// Author   : cesar fuguet
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
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
16///////////////////////////////////////////////////////////////////////////////
17//      _sdc_enable()
18// This function enables SD Card select signal
19///////////////////////////////////////////////////////////////////////////////
20static void _sdc_enable()
21{
22    spi_ss_assert(sdcard.spi, sdcard.slave_id);
23}
24
25///////////////////////////////////////////////////////////////////////////////
26//      _sdc_enable()
27// This function disables SD Card select signal
28///////////////////////////////////////////////////////////////////////////////
29static void _sdc_disable()
30{
31    spi_ss_deassert(sdcard.spi, sdcard.slave_id);
32}
33
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///////////////////////////////////////////////////////////////////////////////
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//      _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///////////////////////////////////////////////////////////////////////////////
51void _sdc_lseek(unsigned int lba)
52{
53    sdcard.access_pointer = sdcard.block_length * lba;
54}
55
56///////////////////////////////////////////////////////////////////////////////
57//      _sdc_receive_char()
58// This function gets a byte from the SD card
59///////////////////////////////////////////////////////////////////////////////
60static unsigned char _sdc_receive_char()
61{
62    _sdc_gen_tick(1);
63
64    return spi_get_rx(sdcard.spi, 0);
65}
66
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///////////////////////////////////////////////////////////////////////////////
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
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///////////////////////////////////////////////////////////////////////////////
98static void _sdc_wait_data_block()
99{
100        while (_sdc_receive_char() != 0xFE);
101}
102
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///////////////////////////////////////////////////////////////////////////////
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    {
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
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
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///////////////////////////////////////////////////////////////////////////////
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
166        // supply SD card ramp up time (min 74 cycles)
167        _sdc_gen_tick(10);
168
169        // Assert slave select signal
170        // Send CMD0 (Reset Command)
171        // Deassert slave select signal
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();
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("card CMD8 failed ");
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                        // voltage mismatch
210                        _puts("card CMD8 mismatch: ");
211                        _putx(ersp);
212                        return sdcard_rsp;
213                }
214                _puts("v2 or later ");
215                sdcard.sdhc = 1;
216        }
217    else if ((sdcard_rsp & SDCARD_R1_ILLEGAL_CMD) == 0)
218    {
219                // other error
220                _puts("card CMD8 error ");
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("SD ACMD41 failed ");
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("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();
272                if (ersp & 0x40000000)
273        {
274                        _puts("SDHC ");
275                } else
276        {
277                        sdcard.sdhc = 0;
278                }
279                _sdc_disable();
280        }
281        _puts("card detected ");
282        return 0;
283}
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///////////////////////////////////////////////////////////////////////////////
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//      _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///////////////////////////////////////////////////////////////////////////////
336unsigned int _sdc_init( unsigned int channel )
337{
338    spi = (struct spi_dev*) &seg_ioc_base;
339
340    // initializing the SPI controller
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
350    // initializing the SD Card
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
380    // set the block length of the SD Card
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
388    // incrementing SDCARD clock frequency for normal function
389    _spi_init (
390        spi         ,
391        10000000    , // SPI_clk 10 Mhz
392        SYSCLK_FREQ , // Sys_clk
393        -1          , // Charlen: 8
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
450        // Get the CRC16 (comes at the end of the data block)
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
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///////////////////////////////////////////////////////////////////////////////
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
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///////////////////////////////////////////////////////////////////////////////
486unsigned int _sdc_get_status( unsigned int channel ,
487                              unsigned int* status )
488{
489    *status = BLOCK_DEVICE_IDLE;
490
491    return 0;
492}
493
494///////////////////////////////////////////////////////////////////////////////
495//     _sdc_get_block_size()
496// Returns the block size in bytes of the SD card
497///////////////////////////////////////////////////////////////////////////////
498unsigned int _sdc_get_block_size()
499{
500    if (sdcard.sdhc) return sdcard.block_length*512;
501    else             return sdcard.block_length;
502}
503
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.