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

Last change on this file since 589 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
RevLine 
[284]1///////////////////////////////////////////////////////////////////////////////////
2// File     : sdc_driver.c
[563]3// Date     : 31/04/2015
4// Author   : Alain Greiner
[284]5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
[295]7
[563]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"
[283]18
[563]19#define  SDC_RSP_TIMEOUT      100       // number of retries for a config RSP
[283]20
[563]21#define  SDC_POLLING_TIMEOUT  1000000   // number of retries for polling PXCI
[545]22
[563]23///////////////////////////////////////////////////////////////////////////////////
24//          AHCI related global variables
25///////////////////////////////////////////////////////////////////////////////////
26
27// global index ot the task, for each entry in the command list
[545]28__attribute__((section(".kdata")))
[563]29unsigned int     _ahci_gtid[32];
[545]30
[563]31// status of the command, for each entry in the command list
[545]32__attribute__((section(".kdata")))
[563]33unsigned int     _ahci_status[32];
[283]34
[563]35// command list : up to 32 commands
36__attribute__((section(".kdata")))
37ahci_cmd_desc_t  _ahci_cmd_list[32] __attribute__((aligned(0x40)));   
[283]38
[563]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))); 
[283]42
[563]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
[284]65///////////////////////////////////////////////////////////////////////////////
[563]66// This low_level function returns the value contained in register (index).
[284]67///////////////////////////////////////////////////////////////////////////////
[563]68static unsigned int _sdc_get_register( unsigned int index )
[283]69{
[563]70    unsigned int* vaddr = (unsigned int*)SEG_IOC_BASE + index;
71    return _io_extended_read( vaddr );
[283]72}
73
[284]74///////////////////////////////////////////////////////////////////////////////
[563]75// This low-level function set a new value in register (index).
[284]76///////////////////////////////////////////////////////////////////////////////
[563]77static void _sdc_set_register( unsigned int index,
78                               unsigned int value ) 
[283]79{
[563]80    unsigned int* vaddr = (unsigned int*)SEG_IOC_BASE + index;
81    _io_extended_write( vaddr, value );
[283]82}
83
[284]84///////////////////////////////////////////////////////////////////////////////
[563]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
[284]89///////////////////////////////////////////////////////////////////////////////
[563]90static unsigned int _sdc_send_cmd ( unsigned int   index,
91                                    unsigned int   arg )
[283]92{
[563]93    unsigned int  sdc_rsp;
94    register int  iter = 0;
[283]95
[563]96    // load argument
97    _sdc_set_register( SDC_CMD_ARG, arg );
[283]98
[563]99    // lauch command
100    _sdc_set_register( SDC_CMD_ID , index );
[283]101
[563]102    // get response
103    do
[283]104    {
[563]105        sdc_rsp = _sdc_get_register( SDC_RSP_STS );
[283]106        iter++;
107    }
[563]108    while ( (sdc_rsp == 0xFFFFFFFF) && (iter < SDC_RSP_TIMEOUT) ); 
[283]109
[563]110    return sdc_rsp;
[283]111}
112
[563]113/////////////////////////////////////////////////////////////////////////////////
114//           Extern functions
115/////////////////////////////////////////////////////////////////////////////////
[283]116
[563]117////////////////////////
118unsigned int _sdc_init()
[283]119{
[563]120    //////////// SD Card initialisation //////////
121 
122    unsigned int rsp;
[283]123
[563]124    // define the SD card clock period
125    _sdc_set_register( SDC_PERIOD , GIET_SDC_PERIOD );
[283]126
[563]127    // send CMD0 (soft reset / no argument)
128    rsp = _sdc_send_cmd( SDC_CMD0 , 0 );
129    if ( rsp == 0xFFFFFFFF )
[283]130    {
[563]131        _printf("\n[SDC ERROR] in _sdc_init() : no acknowledge to CMD0\n");
132        return 1;
133    }
[283]134
[563]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;
[283]146    }
[563]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    }
[283]153
[563]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
[283]158
[563]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 );
[283]166
[563]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
[283]171
[563]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;
[283]180
[563]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
[283]185
[563]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    }
[283]193
[563]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
[283]198
[563]199    //////////// AHCI interface initialisation  ///////
[283]200
[563]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
[283]206
[563]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 )
[284]211    {
[563]212        cmd_list_paddr  = _v2p_translate( cmd_list_vaddr  , &flags );
213        cmd_table_paddr = _v2p_translate( cmd_table_vaddr , &flags );
214    }
[284]215    else
216    {
[563]217        cmd_list_paddr  = (unsigned long long)cmd_list_vaddr;
218        cmd_table_paddr = (unsigned long long)cmd_table_vaddr;
219    }
[284]220
[563]221    // initialise Command List pointers
222    _ahci_cmd_ptw = 0;
223    _ahci_cmd_ptr = 0;
[283]224
[563]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    }
[283]234
[563]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 );
[283]242
[563]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
[283]247
[563]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 )
[283]257{
[563]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;
[283]263
[563]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
[283]270
[563]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
[283]276
[563]277    // check buffer alignment
278    if( buf_paddr & 0x3F )
[283]279    {
[563]280        _printf("\n[SDC ERROR] in _sdc_access() : buffer not 64 bytes aligned\n");
281        return 1;
[283]282    }
283
[563]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;
[283]288
[563]289    // blocked until allocated entry in Command List is empty
290    iter = SDC_POLLING_TIMEOUT;
291    do
[283]292    {
[563]293        // get PXCI register
294        pxci = _sdc_get_register( AHCI_PXCI );
[283]295
[563]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) );
[283]305
[563]306    // compute pointers on command descriptor and command table   
307    cmd_desc  = &_ahci_cmd_list[ptw];
308    cmd_table = &_ahci_cmd_table[ptw];
[283]309
[563]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;
[283]314
[563]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;
[437]322
[563]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;     
[283]328
[563]329#if USE_IOB    // software L2/L3 cache coherence
[283]330
[563]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
[283]335
[563]336    if ( _get_mmu_mode() & 0x4 )
[283]337    {
[563]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    }
[283]346
[563]347    // update external memory for command table
348    _mmc_sync( cmd_table_paddr & (~0x3F) , sizeof(ahci_cmd_table_t) );
[283]349
[563]350    // update external memory for command descriptor
351    _mmc_sync( cmd_desc_paddr & (~0x3F) , sizeof(ahci_cmd_desc_t) );
[283]352
[563]353    // inval or synchronize memory buffer
354    if ( to_mem )  _mmc_inval( buf_paddr, count<<9 );
355    else           _mmc_sync( buf_paddr, count<<9 );
[283]356
[563]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
[283]379        {
[563]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            }
[283]389        }
[563]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 );
[283]397    }
398
[563]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
[283]407    {
408
[563]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();
[283]417
[563]418        // activates interrupt
419        _sdc_set_register( AHCI_PXIE , 0x00000001 ); 
[283]420
[563]421        // set _ahci_gtid[ptw]
422        _ahci_gtid[ptw] = (procid<<16) + ltid;
[283]423
[563]424        // enters critical section
425        _it_disable( &save_sr ); 
[283]426
[563]427        // reset runnable
428        _set_task_slot( x, y, p, ltid, CTX_RUN_ID, 0 ); 
[283]429
[563]430        // start transfer
431        _sdc_set_register( AHCI_PXCI, (1<<ptw) );
[283]432
[563]433        // deschedule task
434        _ctx_switch();                     
[283]435
[563]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
[283]441
[563]442        // restore SR
443        _it_restore( &save_sr );
[283]444
[563]445        // get command status
446        pxis = _ahci_status[ptw];
447    }   
[283]448
[563]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
[283]454
[563]455    if ( pxis & 0x40000000 ) return pxis;
456    else                     return 0;
[283]457
[563]458} // end _sdc_access()
[529]459
[283]460
[545]461///////////////////////////////////////////////////////////////////////////////
[563]462// This ISR handles the IRQ generated by the AHCI_SDC controler
[545]463///////////////////////////////////////////////////////////////////////////////
464void _sdc_isr( unsigned int irq_type,
465               unsigned int irq_id,
466               unsigned int channel )
467{
[563]468    // get AHCI_PXCI containing commands status
469    unsigned int pxci = _sdc_get_register( AHCI_PXCI );
[545]470
[563]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
[284]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.