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

Last change on this file since 607 was 603, checked in by alain, 9 years ago

cosmetic

File size: 17.2 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
136if (_get_proctime() > GIET_DEBUG_IOC)
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
155if (_get_proctime() > GIET_DEBUG_IOC)
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
168if (_get_proctime() > GIET_DEBUG_IOC)
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
182if (_get_proctime() > GIET_DEBUG_IOC)
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
195if (_get_proctime() > GIET_DEBUG_IOC)
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
244if (_get_proctime() > GIET_DEBUG_IOC)
245_printf("\n[DEBUG SDC] _sdc_init() : AHCI init done at cycle %d\n", _get_proctime() );
246#endif
247
248    return 0;
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 )
258{
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;
264
265#if GIET_DEBUG_IOC
266if (_get_proctime() > GIET_DEBUG_IOC)
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
271
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
277
278    // check buffer alignment
279    if( buf_paddr & 0x3F )
280    {
281        _printf("\n[SDC ERROR] in _sdc_access() : buffer not 64 bytes aligned\n");
282        return 1;
283    }
284
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;
289
290    // blocked until allocated entry in Command List is empty
291    iter = SDC_POLLING_TIMEOUT;
292    do
293    {
294        // get PXCI register
295        pxci = _sdc_get_register( AHCI_PXCI );
296
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) );
306
307    // compute pointers on command descriptor and command table   
308    cmd_desc  = &_ahci_cmd_list[ptw];
309    cmd_table = &_ahci_cmd_table[ptw];
310
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;
315
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;
323
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;     
329
330#if USE_IOB    // software L2/L3 cache coherence
331
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
336
337    if ( _get_mmu_mode() & 0x4 )
338    {
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    }
347
348    // update external memory for command table
349    _mmc_sync( cmd_table_paddr & (~0x3F) , sizeof(ahci_cmd_table_t) );
350
351    // update external memory for command descriptor
352    _mmc_sync( cmd_desc_paddr & (~0x3F) , sizeof(ahci_cmd_desc_t) );
353
354    // inval or synchronize memory buffer
355    if ( to_mem )  _mmc_inval( buf_paddr, count<<9 );
356    else           _mmc_sync( buf_paddr, count<<9 );
357
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
369if (_get_proctime() > GIET_DEBUG_IOC)
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
380        {
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            }
390        }
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 );
398    }
399
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
408    {
409
410#if GIET_DEBUG_IOC
411if (_get_proctime() > GIET_DEBUG_IOC)
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();
418
419        // activates interrupt
420        _sdc_set_register( AHCI_PXIE , 0x00000001 ); 
421
422        // set _ahci_gtid[ptw]
423        _ahci_gtid[ptw] = (procid<<16) + ltid;
424
425        // enters critical section
426        _it_disable( &save_sr ); 
427
428        // reset runnable
429        _set_task_slot( x, y, p, ltid, CTX_RUN_ID, 0 ); 
430
431        // start transfer
432        _sdc_set_register( AHCI_PXCI, (1<<ptw) );
433
434        // deschedule task
435        _ctx_switch();                     
436
437#if GIET_DEBUG_IOC
438if (_get_proctime() > GIET_DEBUG_IOC)
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
442
443        // restore SR
444        _it_restore( &save_sr );
445
446        // get command status
447        pxis = _ahci_status[ptw];
448    }   
449
450#if GIET_DEBUG_IOC
451if (_get_proctime() > GIET_DEBUG_IOC)
452_printf("\n[DEBUG SDC] _sdc_access() : P[%d,%d,%d] exit at cycle %d\n",
453        x , y , p , _get_proctime() );
454#endif
455
456    if ( pxis & 0x40000000 ) return pxis;
457    else                     return 0;
458
459} // end _sdc_access()
460
461
462///////////////////////////////////////////////////////////////////////////////
463// This ISR handles the IRQ generated by the AHCI_SDC controler
464///////////////////////////////////////////////////////////////////////////////
465void _sdc_isr( unsigned int irq_type,
466               unsigned int irq_id,
467               unsigned int channel )
468{
469    // get AHCI_PXCI containing commands status
470    unsigned int pxci = _sdc_get_register( AHCI_PXCI );
471
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 
512if (_get_proctime() > GIET_DEBUG_IOC)
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
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.