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

Last change on this file since 595 was 593, checked in by alain, 9 years ago

Bloup

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
[593]248    return 0;
[563]249} // end _sdc_init()
250
251
252/////////////////////////////////////////////////////
253unsigned int _sdc_access( unsigned int       use_irq, 
254                          unsigned int       to_mem,
255                          unsigned int       lba,
256                          unsigned long long buf_paddr,
257                          unsigned int       count )
[283]258{
[563]259    unsigned int procid  = _get_procid();
260    unsigned int x       = procid >> (Y_WIDTH + P_WIDTH);
261    unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH) - 1);
262    unsigned int p       = procid & ((1<<P_WIDTH)-1);
263    unsigned int iter;
[283]264
[563]265#if GIET_DEBUG_IOC_DRIVER
266if (_get_proctime() > GIET_DEBUG_IOC_DRIVER)
267_printf("\n[DEBUG SDC] _sdc_access() : P[%d,%d,%d] enters at cycle %d\n"
268        "  use_irq = %d / to_mem = %d / lba = %x / paddr = %l / count = %d\n",
269        x , y , p , _get_proctime() , use_irq , to_mem , lba , buf_paddr, count );
270#endif
[283]271
[563]272    unsigned int       pxci;              // AHCI_PXCI register value
273    unsigned int       ptw;               // command list write pointer
274    unsigned int       pxis;              // AHCI_PXIS register value
275    ahci_cmd_desc_t*   cmd_desc;          // command descriptor pointer   
276    ahci_cmd_table_t*  cmd_table;         // command table pointer
[283]277
[563]278    // check buffer alignment
279    if( buf_paddr & 0x3F )
[283]280    {
[563]281        _printf("\n[SDC ERROR] in _sdc_access() : buffer not 64 bytes aligned\n");
282        return 1;
[283]283    }
284
[563]285    // get one entry in Command List, using an
286    // atomic increment on the _ahci_cmd_ptw allocator
287    // only the 5 LSB bits are used to index the Command List
288    ptw = _atomic_increment( &_ahci_cmd_ptw , 1 ) & 0x1F;
[283]289
[563]290    // blocked until allocated entry in Command List is empty
291    iter = SDC_POLLING_TIMEOUT;
292    do
[283]293    {
[563]294        // get PXCI register
295        pxci = _sdc_get_register( AHCI_PXCI );
[283]296
[563]297        // check livelock
298        iter--;
299        if ( iter == 0 )
300        {
301            _printf("\n[SDC ERROR] in _sdc_access() : cannot get PXCI slot\n");
302            return 1;
303        }
304    } 
305    while ( pxci & (1<<ptw) );
[283]306
[563]307    // compute pointers on command descriptor and command table   
308    cmd_desc  = &_ahci_cmd_list[ptw];
309    cmd_table = &_ahci_cmd_table[ptw];
[283]310
[563]311    // set  buffer descriptor in command table
312    cmd_table->buffer.dba  = (unsigned int)(buf_paddr);
313    cmd_table->buffer.dbau = (unsigned int)(buf_paddr >> 32);
314    cmd_table->buffer.dbc  = count * 512;
[283]315
[563]316    // initialize command table header
317    cmd_table->header.lba0 = (char)lba;
318    cmd_table->header.lba1 = (char)(lba>>8);
319    cmd_table->header.lba2 = (char)(lba>>16);
320    cmd_table->header.lba3 = (char)(lba>>24);
321    cmd_table->header.lba4 = 0;
322    cmd_table->header.lba5 = 0;
[437]323
[563]324    // initialise command descriptor
325    cmd_desc->prdtl[0] = 1;
326    cmd_desc->prdtl[1] = 0;
327    if( to_mem ) cmd_desc->flag[0] = 0x00;
328    else         cmd_desc->flag[0] = 0x40;     
[283]329
[563]330#if USE_IOB    // software L2/L3 cache coherence
[283]331
[563]332    // compute physical addresses
333    unsigned long long cmd_desc_paddr;    // command descriptor physical address
334    unsigned long long cmd_table_paddr;   // command table header physical address
335    unsigned int       flags;             // unused
[283]336
[563]337    if ( _get_mmu_mode() & 0x4 )
[283]338    {
[563]339        cmd_desc_paddr  = _v2p_translate( (unsigned int)cmd_desc  , &flags );
340        cmd_table_paddr = _v2p_translate( (unsigned int)cmd_table , &flags );
341    }
342    else
343    {
344        cmd_desc_paddr  = (unsigned int)cmd_desc;
345        cmd_table_paddr = (unsigned int)cmd_table;
346    }
[283]347
[563]348    // update external memory for command table
349    _mmc_sync( cmd_table_paddr & (~0x3F) , sizeof(ahci_cmd_table_t) );
[283]350
[563]351    // update external memory for command descriptor
352    _mmc_sync( cmd_desc_paddr & (~0x3F) , sizeof(ahci_cmd_desc_t) );
[283]353
[563]354    // inval or synchronize memory buffer
355    if ( to_mem )  _mmc_inval( buf_paddr, count<<9 );
356    else           _mmc_sync( buf_paddr, count<<9 );
[283]357
[563]358#endif     // end software L2/L3 cache coherence
359
360    /////////////////////////////////////////////////////////////////////
361    // In synchronous mode, we poll the PXCI register until completion
362    /////////////////////////////////////////////////////////////////////
363    if ( use_irq == 0 ) 
364    {
365        // start transfer
366        _sdc_set_register( AHCI_PXCI, (1<<ptw) );
367
368#if GIET_DEBUG_IOC_DRIVER
369if (_get_proctime() > GIET_DEBUG_IOC_DRIVER)
370_printf("\n[DEBUG SDC] _sdc_access() : command %d for P[%d,%d,%d]"
371        " at cycle %d / polling\n",
372        ptw , x , y , p , _get_proctime() );
373#endif
374        // disable IRQs in PXIE register
375        _sdc_set_register( AHCI_PXIE , 0 );
376
377        // poll PXCI[ptw] until command completed
378        iter = SDC_POLLING_TIMEOUT;
379        do
[283]380        {
[563]381            pxci = _sdc_get_register( AHCI_PXCI );
382
383            // check livelock
384            iter--;
385            if ( iter == 0 )
386            {
387                _printf("\n[SDC ERROR] in _sdc_access() : polling PXCI timeout\n");
388                return 1;
389            }
[283]390        }
[563]391        while( pxci & (1<<ptw) ); 
392             
393        // get PXIS register
394        pxis = _sdc_get_register( AHCI_PXIS );
395
396        // reset PXIS register
397        _sdc_set_register( AHCI_PXIS , 0 );
[283]398    }
399
[563]400    /////////////////////////////////////////////////////////////////
401    // in descheduling mode, we deschedule the task
402    // and use an interrupt to reschedule the task.
403    // We need a critical section, because we must reset the RUN bit
404        // before to launch the transfer, and we don't want to be
405    // descheduled between these two operations.
406    /////////////////////////////////////////////////////////////////
407    else
[283]408    {
409
[563]410#if GIET_DEBUG_IOC_DRIVER
411if (_get_proctime() > GIET_DEBUG_IOC_DRIVER)
412_printf("\n[DEBUG SDC] _sdc_access() : command %d for P[%d,%d,%d] "
413        "at cycle %d / descheduling\n",
414        ptw , x , y , p , _get_proctime() );
415#endif
416        unsigned int save_sr;
417        unsigned int ltid = _get_current_task_id();
[283]418
[563]419        // activates interrupt
420        _sdc_set_register( AHCI_PXIE , 0x00000001 ); 
[283]421
[563]422        // set _ahci_gtid[ptw]
423        _ahci_gtid[ptw] = (procid<<16) + ltid;
[283]424
[563]425        // enters critical section
426        _it_disable( &save_sr ); 
[283]427
[563]428        // reset runnable
429        _set_task_slot( x, y, p, ltid, CTX_RUN_ID, 0 ); 
[283]430
[563]431        // start transfer
432        _sdc_set_register( AHCI_PXCI, (1<<ptw) );
[283]433
[563]434        // deschedule task
435        _ctx_switch();                     
[283]436
[563]437#if GIET_DEBUG_IOC_DRIVER
438if (_get_proctime() > GIET_DEBUG_IOC_DRIVER)
439_printf("\n[DEBUG SDC] _sdc_access() : task %d on P[%d,%d,%d] resume at cycle %d\n",
440        ltid , x , y , p , _get_proctime() );
441#endif
[283]442
[563]443        // restore SR
444        _it_restore( &save_sr );
[283]445
[563]446        // get command status
447        pxis = _ahci_status[ptw];
448    }   
[283]449
[563]450#if GIET_DEBUG_IOC_DRIVER
451if (_get_proctime() > GIET_DEBUG_IOC_DRIVER)
452_printf("\n[DEBUG SDC] _sdc_access() : P[%d,%d,%d] exit at cycle %d\n",
453        x , y , p , _get_proctime() );
454#endif
[283]455
[563]456    if ( pxis & 0x40000000 ) return pxis;
457    else                     return 0;
[283]458
[563]459} // end _sdc_access()
[529]460
[283]461
[545]462///////////////////////////////////////////////////////////////////////////////
[563]463// This ISR handles the IRQ generated by the AHCI_SDC controler
[545]464///////////////////////////////////////////////////////////////////////////////
465void _sdc_isr( unsigned int irq_type,
466               unsigned int irq_id,
467               unsigned int channel )
468{
[563]469    // get AHCI_PXCI containing commands status
470    unsigned int pxci = _sdc_get_register( AHCI_PXCI );
[545]471
[563]472    // we must handle all completed commands
473    // active commands are between  (_ahci_cmd_ptr) and (_ahci_cmd_ptw-1)
474    unsigned int current;
475    for ( current = _ahci_cmd_ptr ; current != _ahci_cmd_ptw ; current++ )
476    {
477        unsigned int ptr = current & 0x1F;
478       
479        if ( (pxci & (1<<ptr)) == 0 )    // command completed
480        {
481            // increment the 32 bits variable _ahci_cmd_ptr
482            _ahci_cmd_ptr++;
483
484            // save AHCI_PXIS register
485            _ahci_status[ptr] = _sdc_get_register( AHCI_PXIS );
486
487            // reset AHCI_PXIS register
488            _sdc_set_register( AHCI_PXIS , 0 );
489 
490            // identify waiting task
491            unsigned int remote_procid  = _ahci_gtid[ptr]>>16;
492            unsigned int ltid           = _ahci_gtid[ptr] & 0xFFFF;
493            unsigned int remote_cluster = remote_procid >> P_WIDTH;
494            unsigned int remote_x       = remote_cluster >> Y_WIDTH;
495            unsigned int remote_y       = remote_cluster & ((1<<Y_WIDTH)-1);
496            unsigned int remote_p       = remote_procid & ((1<<P_WIDTH)-1);
497 
498            // re-activates waiting task
499            _set_task_slot( remote_x,
500                            remote_y,
501                            remote_p,
502                            ltid,
503                            CTX_RUN_ID,
504                            1 );
505
506            // send a WAKUP WTI to processor running the waiting task
507            _xcu_send_wti( remote_cluster , 
508                           remote_p , 
509                           0 );          // don't force context switch
510
511#if GIET_DEBUG_IOC_DRIVER 
512if (_get_proctime() > GIET_DEBUG_IOC_DRIVER)
513_printf("\n[DEBUG SDC] _sdc_isr() : command %d completed at cycle %d\n"
514        "  resume task %d running on P[%d,%d,%d] / status = %x\n",
515        ptr , _get_proctime() ,
516        ltid , remote_x , remote_y , remote_p , _ahci_status[ptr] );
517#endif
518        }
519        else                         // command non completed
520        {
521            break;
522        }
523    }
524}  // end _sdc_isr()
525
[284]526// Local Variables:
527// tab-width: 4
528// c-basic-offset: 4
529// c-file-offsets:((innamespace . 0)(inline-open . 0))
530// indent-tabs-mode: nil
531// End:
532// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
Note: See TracBrowser for help on using the repository browser.