source: trunk/hal/tsar_mips32/drivers/soclib_sdc.c @ 546

Last change on this file since 546 was 543, checked in by nicolas.van.phan@…, 6 years ago

Add untested bare SDC driver (from giet)

Changes some hard-coded definitions in SD card driver

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