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

Last change on this file since 565 was 563, checked in by alain, 10 years ago

1) Introduce a new driver "sdc_driver" for SD Card uding directly the 4 bits SD bus.
2) Improve the debug for all IOC drivers (debug activated only if _get_time() > GIET_DEBUG_IOC_DRIVER).

File size: 17.4 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////
2// File     : sdc_driver.c
3// Date     : 31/04/2015
4// Author   : Alain Greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7
8#include "hard_config.h"
9#include "giet_config.h"
10#include "sdc_driver.h"
11#include "tty0.h"
12#include "utils.h"
13#include "vmem.h"
14#include "kernel_locks.h"
15#include "mmc_driver.h"
16#include "xcu_driver.h"
17#include "ctx_handler.h"
18
19#define  SDC_RSP_TIMEOUT      100       // number of retries for a config RSP
20
21#define  SDC_POLLING_TIMEOUT  1000000   // number of retries for polling PXCI
22
23///////////////////////////////////////////////////////////////////////////////////
24//          AHCI related global variables
25///////////////////////////////////////////////////////////////////////////////////
26
27// global index ot the task, for each entry in the command list
28__attribute__((section(".kdata")))
29unsigned int     _ahci_gtid[32];
30
31// status of the command, for each entry in the command list
32__attribute__((section(".kdata")))
33unsigned int     _ahci_status[32];
34
35// command list : up to 32 commands
36__attribute__((section(".kdata")))
37ahci_cmd_desc_t  _ahci_cmd_list[32] __attribute__((aligned(0x40)));   
38
39// command tables array : one command table per entry in command list
40__attribute__((section(".kdata")))
41ahci_cmd_table_t _ahci_cmd_table[32] __attribute__((aligned(0x40))); 
42
43// command list write index : next slot to register a command
44__attribute__((section(".kdata")))
45unsigned int     _ahci_cmd_ptw;
46
47// command list read index : next slot to poll a completed command
48__attribute__((section(".kdata")))
49unsigned int     _ahci_cmd_ptr;
50
51
52///////////////////////////////////////////////////////////////////////////////////
53//          SD Card related global variables
54///////////////////////////////////////////////////////////////////////////////////
55
56// SD card relative address
57__attribute__((section(".kdata")))
58unsigned int     _sdc_rca;
59
60// SD Card Hih Capacity Support when non zero
61__attribute__((section(".kdata")))
62unsigned int     _sdc_sdhc;
63
64
65///////////////////////////////////////////////////////////////////////////////
66// This low_level function returns the value contained in register (index).
67///////////////////////////////////////////////////////////////////////////////
68static unsigned int _sdc_get_register( unsigned int index )
69{
70    unsigned int* vaddr = (unsigned int*)SEG_IOC_BASE + index;
71    return _io_extended_read( vaddr );
72}
73
74///////////////////////////////////////////////////////////////////////////////
75// This low-level function set a new value in register (index).
76///////////////////////////////////////////////////////////////////////////////
77static void _sdc_set_register( unsigned int index,
78                               unsigned int value ) 
79{
80    unsigned int* vaddr = (unsigned int*)SEG_IOC_BASE + index;
81    _io_extended_write( vaddr, value );
82}
83
84///////////////////////////////////////////////////////////////////////////////
85// This function sends a command to the SD card and returns the response.
86// - index      : CMD index
87// - arg        : CMD argument
88// - return Card response
89///////////////////////////////////////////////////////////////////////////////
90static unsigned int _sdc_send_cmd ( unsigned int   index,
91                                    unsigned int   arg )
92{
93    unsigned int  sdc_rsp;
94    register int  iter = 0;
95
96    // load argument
97    _sdc_set_register( SDC_CMD_ARG, arg );
98
99    // lauch command
100    _sdc_set_register( SDC_CMD_ID , index );
101
102    // get response
103    do
104    {
105        sdc_rsp = _sdc_get_register( SDC_RSP_STS );
106        iter++;
107    }
108    while ( (sdc_rsp == 0xFFFFFFFF) && (iter < SDC_RSP_TIMEOUT) ); 
109
110    return sdc_rsp;
111}
112
113/////////////////////////////////////////////////////////////////////////////////
114//           Extern functions
115/////////////////////////////////////////////////////////////////////////////////
116
117////////////////////////
118unsigned int _sdc_init()
119{
120    //////////// SD Card initialisation //////////
121 
122    unsigned int rsp;
123
124    // define the SD card clock period
125    _sdc_set_register( SDC_PERIOD , GIET_SDC_PERIOD );
126
127    // send CMD0 (soft reset / no argument)
128    rsp = _sdc_send_cmd( SDC_CMD0 , 0 );
129    if ( rsp == 0xFFFFFFFF )
130    {
131        _printf("\n[SDC ERROR] in _sdc_init() : no acknowledge to CMD0\n");
132        return 1;
133    }
134
135#if GIET_DEBUG_IOC_DRIVER
136if (_get_proctime() > GIET_DEBUG_IOC_DRIVER)
137_printf("\n[DEBUG SDC] _sdc_init() : SDC_CMD0 done at cycle %d\n", _get_proctime() );
138#endif
139
140    // send CMD8 command
141    rsp = _sdc_send_cmd( SDC_CMD8 , SDC_CMD8_ARGUMENT );
142    if ( rsp == 0xFFFFFFFF )
143    {
144        _printf("\n[SDC ERROR] in _sdc_init() : no response to CMD8\n");
145        return 1;
146    }
147    else if ( rsp != SDC_CMD8_ARGUMENT )
148    {
149        _printf("\n[SDC ERROR] in _sdc_init() : response to CMD8 = %x / expected = %x\n",
150                rsp , SDC_CMD8_ARGUMENT );
151        return 1;
152    }
153
154#if GIET_DEBUG_IOC_DRIVER
155if (_get_proctime() > GIET_DEBUG_IOC_DRIVER)
156_printf("\n[DEBUG SDC] _sdc_init() : SDC_CMD8 done at cycle %d\n", _get_proctime() );
157#endif
158
159    // send CMD41 to get SDHC
160    if ( rsp == 0xFFFFFFFF )
161    {
162        _printf("\n[SDC ERROR] in _sdc_init() : no response to CMD41\n");
163        return 1;
164    }
165    _sdc_sdhc = ( (rsp & SDC_CMD41_RSP_CCS) != 0 );
166
167#if GIET_DEBUG_IOC_DRIVER
168if (_get_proctime() > GIET_DEBUG_IOC_DRIVER)
169_printf("\n[DEBUG SDC] _sdc_init() : SDC_CMD41 done at cycle %d\n", _get_proctime() );
170#endif
171
172    // send CMD3 to get RCA
173    rsp = _sdc_send_cmd( SDC_CMD3 , 0 );
174    if ( rsp == 0xFFFFFFFF )
175    {
176        _printf("\n[SDC ERROR] in _sdc_init() : no response to CMD3\n");
177        return 1;
178    }
179    _sdc_rca = rsp;
180
181#if GIET_DEBUG_IOC_DRIVER
182if (_get_proctime() > GIET_DEBUG_IOC_DRIVER)
183_printf("\n[DEBUG SDC] _sdc_init() : SDC_CMD3 done at cycle %d\n", _get_proctime() );
184#endif
185
186    // send CMD7
187    rsp = _sdc_send_cmd( SDC_CMD7 , _sdc_rca );
188    if ( rsp == 0xFFFFFFFF )
189    {
190        _printf("\n[SDC ERROR] in _sdc_init() : no response to CMD7\n");
191        return 1;
192    }
193
194#if GIET_DEBUG_IOC_DRIVER
195if (_get_proctime() > GIET_DEBUG_IOC_DRIVER)
196_printf("\n[DEBUG SDC] _sdc_init() : SDC_CMD7 done at cycle %d\n", _get_proctime() );
197#endif
198
199    //////////// AHCI interface initialisation  ///////
200
201    unsigned int       cmd_list_vaddr;
202    unsigned int       cmd_table_vaddr;
203    unsigned long long cmd_list_paddr;
204    unsigned long long cmd_table_paddr;
205    unsigned int       flags;                 // unused
206
207    // compute Command list & command table physical addresses
208    cmd_list_vaddr  = (unsigned int)(&_ahci_cmd_list[0]);
209    cmd_table_vaddr = (unsigned int)(&_ahci_cmd_table[0]);
210    if ( _get_mmu_mode() & 0x4 )
211    {
212        cmd_list_paddr  = _v2p_translate( cmd_list_vaddr  , &flags );
213        cmd_table_paddr = _v2p_translate( cmd_table_vaddr , &flags );
214    }
215    else
216    {
217        cmd_list_paddr  = (unsigned long long)cmd_list_vaddr;
218        cmd_table_paddr = (unsigned long long)cmd_table_vaddr;
219    }
220
221    // initialise Command List pointers
222    _ahci_cmd_ptw = 0;
223    _ahci_cmd_ptr = 0;
224
225    // initialise Command Descriptors in Command List
226    unsigned int         c;     
227    unsigned long long   paddr;
228    for( c=0 ; c<32 ; c++ )
229    {
230        paddr = cmd_table_paddr + c * sizeof(ahci_cmd_table_t);
231        _ahci_cmd_list[c].ctba  = (unsigned int)(paddr);
232        _ahci_cmd_list[c].ctbau = (unsigned int)(paddr>>32);
233    }
234
235    // initialise AHCI registers
236    _sdc_set_register( AHCI_PXCLB  , (unsigned int)(cmd_list_paddr) );
237    _sdc_set_register( AHCI_PXCLBU , (unsigned int)(cmd_list_paddr>>32) );
238    _sdc_set_register( AHCI_PXIE   , 0 );
239    _sdc_set_register( AHCI_PXIS   , 0 );
240    _sdc_set_register( AHCI_PXCI   , 0 );
241    _sdc_set_register( AHCI_PXCMD  , 1 );
242
243#if GIET_DEBUG_IOC_DRIVER
244if (_get_proctime() > GIET_DEBUG_IOC_DRIVER)
245_printf("\n[DEBUG SDC] _sdc_init() : AHCI init done at cycle %d\n", _get_proctime() );
246#endif
247
248} // end _sdc_init()
249
250
251/////////////////////////////////////////////////////
252unsigned int _sdc_access( unsigned int       use_irq, 
253                          unsigned int       to_mem,
254                          unsigned int       lba,
255                          unsigned long long buf_paddr,
256                          unsigned int       count )
257{
258    unsigned int procid  = _get_procid();
259    unsigned int x       = procid >> (Y_WIDTH + P_WIDTH);
260    unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH) - 1);
261    unsigned int p       = procid & ((1<<P_WIDTH)-1);
262    unsigned int iter;
263
264#if GIET_DEBUG_IOC_DRIVER
265if (_get_proctime() > GIET_DEBUG_IOC_DRIVER)
266_printf("\n[DEBUG SDC] _sdc_access() : P[%d,%d,%d] enters at cycle %d\n"
267        "  use_irq = %d / to_mem = %d / lba = %x / paddr = %l / count = %d\n",
268        x , y , p , _get_proctime() , use_irq , to_mem , lba , buf_paddr, count );
269#endif
270
271    unsigned int       pxci;              // AHCI_PXCI register value
272    unsigned int       ptw;               // command list write pointer
273    unsigned int       pxis;              // AHCI_PXIS register value
274    ahci_cmd_desc_t*   cmd_desc;          // command descriptor pointer   
275    ahci_cmd_table_t*  cmd_table;         // command table pointer
276
277    // check buffer alignment
278    if( buf_paddr & 0x3F )
279    {
280        _printf("\n[SDC ERROR] in _sdc_access() : buffer not 64 bytes aligned\n");
281        return 1;
282    }
283
284    // get one entry in Command List, using an
285    // atomic increment on the _ahci_cmd_ptw allocator
286    // only the 5 LSB bits are used to index the Command List
287    ptw = _atomic_increment( &_ahci_cmd_ptw , 1 ) & 0x1F;
288
289    // blocked until allocated entry in Command List is empty
290    iter = SDC_POLLING_TIMEOUT;
291    do
292    {
293        // get PXCI register
294        pxci = _sdc_get_register( AHCI_PXCI );
295
296        // check livelock
297        iter--;
298        if ( iter == 0 )
299        {
300            _printf("\n[SDC ERROR] in _sdc_access() : cannot get PXCI slot\n");
301            return 1;
302        }
303    } 
304    while ( pxci & (1<<ptw) );
305
306    // compute pointers on command descriptor and command table   
307    cmd_desc  = &_ahci_cmd_list[ptw];
308    cmd_table = &_ahci_cmd_table[ptw];
309
310    // set  buffer descriptor in command table
311    cmd_table->buffer.dba  = (unsigned int)(buf_paddr);
312    cmd_table->buffer.dbau = (unsigned int)(buf_paddr >> 32);
313    cmd_table->buffer.dbc  = count * 512;
314
315    // initialize command table header
316    cmd_table->header.lba0 = (char)lba;
317    cmd_table->header.lba1 = (char)(lba>>8);
318    cmd_table->header.lba2 = (char)(lba>>16);
319    cmd_table->header.lba3 = (char)(lba>>24);
320    cmd_table->header.lba4 = 0;
321    cmd_table->header.lba5 = 0;
322
323    // initialise command descriptor
324    cmd_desc->prdtl[0] = 1;
325    cmd_desc->prdtl[1] = 0;
326    if( to_mem ) cmd_desc->flag[0] = 0x00;
327    else         cmd_desc->flag[0] = 0x40;     
328
329#if USE_IOB    // software L2/L3 cache coherence
330
331    // compute physical addresses
332    unsigned long long cmd_desc_paddr;    // command descriptor physical address
333    unsigned long long cmd_table_paddr;   // command table header physical address
334    unsigned int       flags;             // unused
335
336    if ( _get_mmu_mode() & 0x4 )
337    {
338        cmd_desc_paddr  = _v2p_translate( (unsigned int)cmd_desc  , &flags );
339        cmd_table_paddr = _v2p_translate( (unsigned int)cmd_table , &flags );
340    }
341    else
342    {
343        cmd_desc_paddr  = (unsigned int)cmd_desc;
344        cmd_table_paddr = (unsigned int)cmd_table;
345    }
346
347    // update external memory for command table
348    _mmc_sync( cmd_table_paddr & (~0x3F) , sizeof(ahci_cmd_table_t) );
349
350    // update external memory for command descriptor
351    _mmc_sync( cmd_desc_paddr & (~0x3F) , sizeof(ahci_cmd_desc_t) );
352
353    // inval or synchronize memory buffer
354    if ( to_mem )  _mmc_inval( buf_paddr, count<<9 );
355    else           _mmc_sync( buf_paddr, count<<9 );
356
357#endif     // end software L2/L3 cache coherence
358
359    /////////////////////////////////////////////////////////////////////
360    // In synchronous mode, we poll the PXCI register until completion
361    /////////////////////////////////////////////////////////////////////
362    if ( use_irq == 0 ) 
363    {
364        // start transfer
365        _sdc_set_register( AHCI_PXCI, (1<<ptw) );
366
367#if GIET_DEBUG_IOC_DRIVER
368if (_get_proctime() > GIET_DEBUG_IOC_DRIVER)
369_printf("\n[DEBUG SDC] _sdc_access() : command %d for P[%d,%d,%d]"
370        " at cycle %d / polling\n",
371        ptw , x , y , p , _get_proctime() );
372#endif
373        // disable IRQs in PXIE register
374        _sdc_set_register( AHCI_PXIE , 0 );
375
376        // poll PXCI[ptw] until command completed
377        iter = SDC_POLLING_TIMEOUT;
378        do
379        {
380            pxci = _sdc_get_register( AHCI_PXCI );
381
382            // check livelock
383            iter--;
384            if ( iter == 0 )
385            {
386                _printf("\n[SDC ERROR] in _sdc_access() : polling PXCI timeout\n");
387                return 1;
388            }
389        }
390        while( pxci & (1<<ptw) ); 
391             
392        // get PXIS register
393        pxis = _sdc_get_register( AHCI_PXIS );
394
395        // reset PXIS register
396        _sdc_set_register( AHCI_PXIS , 0 );
397    }
398
399    /////////////////////////////////////////////////////////////////
400    // in descheduling mode, we deschedule the task
401    // and use an interrupt to reschedule the task.
402    // We need a critical section, because we must reset the RUN bit
403        // before to launch the transfer, and we don't want to be
404    // descheduled between these two operations.
405    /////////////////////////////////////////////////////////////////
406    else
407    {
408
409#if GIET_DEBUG_IOC_DRIVER
410if (_get_proctime() > GIET_DEBUG_IOC_DRIVER)
411_printf("\n[DEBUG SDC] _sdc_access() : command %d for P[%d,%d,%d] "
412        "at cycle %d / descheduling\n",
413        ptw , x , y , p , _get_proctime() );
414#endif
415        unsigned int save_sr;
416        unsigned int ltid = _get_current_task_id();
417
418        // activates interrupt
419        _sdc_set_register( AHCI_PXIE , 0x00000001 ); 
420
421        // set _ahci_gtid[ptw]
422        _ahci_gtid[ptw] = (procid<<16) + ltid;
423
424        // enters critical section
425        _it_disable( &save_sr ); 
426
427        // reset runnable
428        _set_task_slot( x, y, p, ltid, CTX_RUN_ID, 0 ); 
429
430        // start transfer
431        _sdc_set_register( AHCI_PXCI, (1<<ptw) );
432
433        // deschedule task
434        _ctx_switch();                     
435
436#if GIET_DEBUG_IOC_DRIVER
437if (_get_proctime() > GIET_DEBUG_IOC_DRIVER)
438_printf("\n[DEBUG SDC] _sdc_access() : task %d on P[%d,%d,%d] resume at cycle %d\n",
439        ltid , x , y , p , _get_proctime() );
440#endif
441
442        // restore SR
443        _it_restore( &save_sr );
444
445        // get command status
446        pxis = _ahci_status[ptw];
447    }   
448
449#if GIET_DEBUG_IOC_DRIVER
450if (_get_proctime() > GIET_DEBUG_IOC_DRIVER)
451_printf("\n[DEBUG SDC] _sdc_access() : P[%d,%d,%d] exit at cycle %d\n",
452        x , y , p , _get_proctime() );
453#endif
454
455    if ( pxis & 0x40000000 ) return pxis;
456    else                     return 0;
457
458} // end _sdc_access()
459
460
461///////////////////////////////////////////////////////////////////////////////
462// This ISR handles the IRQ generated by the AHCI_SDC controler
463///////////////////////////////////////////////////////////////////////////////
464void _sdc_isr( unsigned int irq_type,
465               unsigned int irq_id,
466               unsigned int channel )
467{
468    // get AHCI_PXCI containing commands status
469    unsigned int pxci = _sdc_get_register( AHCI_PXCI );
470
471    // we must handle all completed commands
472    // active commands are between  (_ahci_cmd_ptr) and (_ahci_cmd_ptw-1)
473    unsigned int current;
474    for ( current = _ahci_cmd_ptr ; current != _ahci_cmd_ptw ; current++ )
475    {
476        unsigned int ptr = current & 0x1F;
477       
478        if ( (pxci & (1<<ptr)) == 0 )    // command completed
479        {
480            // increment the 32 bits variable _ahci_cmd_ptr
481            _ahci_cmd_ptr++;
482
483            // save AHCI_PXIS register
484            _ahci_status[ptr] = _sdc_get_register( AHCI_PXIS );
485
486            // reset AHCI_PXIS register
487            _sdc_set_register( AHCI_PXIS , 0 );
488 
489            // identify waiting task
490            unsigned int remote_procid  = _ahci_gtid[ptr]>>16;
491            unsigned int ltid           = _ahci_gtid[ptr] & 0xFFFF;
492            unsigned int remote_cluster = remote_procid >> P_WIDTH;
493            unsigned int remote_x       = remote_cluster >> Y_WIDTH;
494            unsigned int remote_y       = remote_cluster & ((1<<Y_WIDTH)-1);
495            unsigned int remote_p       = remote_procid & ((1<<P_WIDTH)-1);
496 
497            // re-activates waiting task
498            _set_task_slot( remote_x,
499                            remote_y,
500                            remote_p,
501                            ltid,
502                            CTX_RUN_ID,
503                            1 );
504
505            // send a WAKUP WTI to processor running the waiting task
506            _xcu_send_wti( remote_cluster , 
507                           remote_p , 
508                           0 );          // don't force context switch
509
510#if GIET_DEBUG_IOC_DRIVER 
511if (_get_proctime() > GIET_DEBUG_IOC_DRIVER)
512_printf("\n[DEBUG SDC] _sdc_isr() : command %d completed at cycle %d\n"
513        "  resume task %d running on P[%d,%d,%d] / status = %x\n",
514        ptr , _get_proctime() ,
515        ltid , remote_x , remote_y , remote_p , _ahci_status[ptr] );
516#endif
517        }
518        else                         // command non completed
519        {
520            break;
521        }
522    }
523}  // end _sdc_isr()
524
525// Local Variables:
526// tab-width: 4
527// c-basic-offset: 4
528// c-file-offsets:((innamespace . 0)(inline-open . 0))
529// indent-tabs-mode: nil
530// End:
531// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
Note: See TracBrowser for help on using the repository browser.