source: trunk/softs/tsar_boot/drivers/reset_ioc_hba.c @ 992

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

Introduce a new driver for SD Card using the 4bits wide SD bus.
THere is now 5 supported block device peripherals, and the driver names
have been re-organised: reset_ioc_xxx with xxx in (bdv, hba, rdk, spi, sdc)

File size: 5.5 KB
Line 
1/**
2 * \File     : reset_ioc_hba.c
3 * \Date     : 23/11/2013
4 * \Author   : alain greiner
5 * \Copyright (c) UPMC-LIP6
6 */
7
8#include <reset_ioc_hba.h>
9#include <reset_tty.h>
10#include <reset_inval.h>
11#include <io.h>
12#include <defs.h>
13
14#define   HBA_POLLING_TIMEOUT    1000000
15
16///////////////////////////////////////////////////////////////////////////////
17//               Global variables
18///////////////////////////////////////////////////////////////////////////////
19
20// command descriptor (one single command)
21static hba_cmd_desc_t  hba_cmd_desc  __attribute__((aligned(64)));
22
23// command table (one single command)
24static hba_cmd_table_t  hba_cmd_table __attribute__((aligned(64)));
25
26// IOC/HBA device base address
27static int* const ioc_address = (int* const)SEG_IOC_BASE;
28
29///////////////////////////////////////////////////////////////////////////////
30//      Extern functions
31///////////////////////////////////////////////////////////////////////////////
32
33///////////////////////////////////////////////////////////////////////////////
34// This function register one command in both the command descriptor
35// and the command data, and updates the HBA_PXCI register.
36// The addresses are supposed to be identity mapping (vaddr == paddr).
37// return 0 if success, -1 if error
38///////////////////////////////////////////////////////////////////////////////
39int reset_hba_read( unsigned int lba, 
40                    void*        buffer,
41                    unsigned int count )   
42{
43    unsigned int       pxci;           // HBA_PXCI register value
44    unsigned int       pxis;           // HBA_PXIS register value
45
46#if RESET_DEBUG
47reset_puts("\n[DEBUG HBA] reset_hba_read() : buffer = ");
48reset_putx( (unsigned int)buffer );
49reset_puts(" / nblocks = ");
50reset_putd( count );
51reset_puts(" / lba = ");
52reset_putd( lba );
53reset_puts("\n");
54#endif
55
56    // check buffer alignment
57    if( (unsigned int)buffer & 0x3F )
58    {
59        reset_puts("\n[RESET ERROR] in reset_hba_read() ");
60        reset_puts("buffer not aligned on 64 bytes: base = "); 
61        reset_putx( (unsigned int)buffer );
62        reset_puts("\n"); 
63        return -1;
64    }
65
66    // set command data header: lba value
67    hba_cmd_table.header.lba0 = (char)lba;
68    hba_cmd_table.header.lba1 = (char)(lba>>8);
69    hba_cmd_table.header.lba2 = (char)(lba>>16);
70    hba_cmd_table.header.lba3 = (char)(lba>>24);
71    hba_cmd_table.header.lba4 = 0;
72    hba_cmd_table.header.lba5 = 0;
73
74    // set command data buffer: address and size)
75    hba_cmd_table.buffer.dba  = (unsigned int)(buffer);
76    hba_cmd_table.buffer.dbau = 0;
77    hba_cmd_table.buffer.dbc  = count*512;
78
79    // set command descriptor: one single buffer / read access
80    hba_cmd_desc.prdtl[0] = 1;
81    hba_cmd_desc.prdtl[1] = 0;
82    hba_cmd_desc.flag[0]  = 0;  // read
83   
84#if RESET_DEBUG
85reset_puts("\n[DEBUG HBA] reset_hba_read() : command registered\n");
86#endif
87
88#if USE_IOB
89    // update external memory for command table
90    reset_L2_sync( &hba_cmd_table , 32 );
91
92    // update external memory for command descriptor
93    reset_L2_sync( &hba_cmd_desc , 16 );
94#endif
95
96    // start transfer
97    iowrite32( &ioc_address[HBA_PXCI] , 1 );
98
99#if RESET_DEBUG
100reset_puts("\n[DEBUG HBA] reset_hba_read() : MULTI_AHCI controler activated\n");
101#endif
102
103#if (RESET_HARD_CC == 0) || USE_IOB
104    // inval buffer in L1 cache
105    reset_L1_inval( buffer , count * 512 );
106#endif
107
108#if USE_IOB
109    // inval buffer in  L2 cache
110    reset_L2_inval( buffer , count * 512 );
111#endif
112
113    // poll PXCI until command completed by HBA
114    unsigned int iter = HBA_POLLING_TIMEOUT;
115    do
116    {
117        pxci = ioread32( &ioc_address[HBA_PXCI] );
118        iter--;
119        if (iter == 0 )
120        {
121            reset_puts("\n[SDC ERROR] in reset_sdc_read() : polling timeout\n");
122            return 1;
123        }
124    }
125    while( pxci ); 
126             
127    // get PXIS register
128    pxis = ioread32( &ioc_address[HBA_PXIS] );
129
130    // reset PXIS register
131    iowrite32( &ioc_address[HBA_PXIS] , 0 );
132
133    // reset PXCI register : we use only command slot[0] in PXCI
134    iowrite32( &ioc_address[HBA_PXCI] , 0 );
135
136    // check error status
137    if ( pxis & 0x40000000 ) 
138    {
139        reset_puts("[RESET ERROR] in reset_hba_read() : "
140                   " status error returned by HBA\n");
141        return 1;
142    }
143
144    return 0;
145} // end reset_hba_read()
146
147
148///////////////////////////////////////////////////////////////////////////////
149// This function initialises both the HBA registers and the
150// memory structures used by the AHCI peripheral (one single command).
151///////////////////////////////////////////////////////////////////////////////
152int reset_hba_init()
153{
154    // initialise the command descriptor
155    hba_cmd_desc.ctba  = (unsigned int)&hba_cmd_table;
156    hba_cmd_desc.ctbau = 0;
157
158#if USE_IOB
159    // update external memory for the commande descriptor
160    reset_L2_sync( &hba_cmd_desc , sizeof( hba_cmd_desc_t ) );
161#endif
162    // initialise HBA registers
163    iowrite32( &ioc_address[HBA_PXCLB]  , (unsigned int)&hba_cmd_desc );
164    iowrite32( &ioc_address[HBA_PXCLBU] , 0 );
165    iowrite32( &ioc_address[HBA_PXIE]   , 0 );
166    iowrite32( &ioc_address[HBA_PXIS]   , 0 );
167    iowrite32( &ioc_address[HBA_PXCI]   , 0 );
168    iowrite32( &ioc_address[HBA_PXCMD]  , 1 );
169
170#if RESET_DEBUG
171reset_puts("\n[DEBUG HBA] reset_hba_init() : AHCI init done\n");
172#endif
173
174    return 0;
175}
176
177
178// Local Variables:
179// tab-width: 4
180// c-basic-offset: 4
181// c-file-offsets:((innamespace . 0)(inline-open . 0))
182// indent-tabs-mode: nil
183// End:
184// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
185
Note: See TracBrowser for help on using the repository browser.