source: trunk/softs/tsar_boot/drivers/reset_ioc_sdc.c @ 1045

Last change on this file since 1045 was 992, checked in by alain, 10 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: 8.8 KB
Line 
1/**
2 * \File     : reset_ioc_sdc.c
3 * \Date     : 31/04/2015
4 * \Author   : Alain Greiner
5 * \Copyright (c) UPMC-LIP6
6 */
7
8#include <reset_ioc_sdc.h>
9#include <reset_tty.h>
10#include <reset_inval.h>
11#include <reset_utils.h>
12#include <io.h>
13#include <defs.h>
14
15#define  SDC_POLLING_TIMEOUT  1000000     // Number of retries when polling PXCI
16
17#define  SDC_RSP_TIMEOUT      100         // Number of retries for a config RSP
18
19///////////////////////////////////////////////////////////////////////////////////
20//          AHCI related global variables
21///////////////////////////////////////////////////////////////////////////////////
22
23// command descriptor (one single command)
24static ahci_cmd_desc_t  ahci_cmd_desc  __attribute__((aligned(64)));
25
26// command table (one single command)
27static ahci_cmd_table_t  ahci_cmd_table __attribute__((aligned(64)));
28
29// IOC/AHCI device base address
30static int* const ioc_address = (int* const)SEG_IOC_BASE;
31
32///////////////////////////////////////////////////////////////////////////////////
33//          SD Card related global variables
34///////////////////////////////////////////////////////////////////////////////////
35
36// SD card relative address
37unsigned int     sdc_rca;
38
39// SD Card Hih Capacity Support when non zero
40unsigned int     sdc_sdhc;
41
42///////////////////////////////////////////////////////////////////////////////
43// This function sends a command to the SD card and returns the response.
44// - index      : CMD index
45// - arg        : CMD argument
46// - return Card response
47///////////////////////////////////////////////////////////////////////////////
48static unsigned int reset_sdc_send_cmd ( unsigned int   index,
49                                         unsigned int   arg )
50{
51    unsigned int  sdc_rsp;
52    register int  iter = 0;
53
54    // load argument
55    iowrite32( &ioc_address[SDC_CMD_ARG] , arg );
56
57    // lauch command
58    iowrite32( &ioc_address[SDC_CMD_ID] , index );
59
60    // get response
61    do
62    {
63        sdc_rsp = ioread32( &ioc_address[SDC_RSP_STS] );
64        iter++;
65    }
66    while ( (sdc_rsp == 0xFFFFFFFF) && (iter < SDC_RSP_TIMEOUT) ); 
67
68    return sdc_rsp;
69}
70
71/////////////////////////////////////////////////////////////////////////////////
72//           Extern functions
73/////////////////////////////////////////////////////////////////////////////////
74
75///////////////////////////////////////////////////////////////////////////////
76// This function initialises both the SD Card and the AHCI registers and
77// memory structures used by the AHCI_SDC peripheral (one single command).
78///////////////////////////////////////////////////////////////////////////////
79unsigned int reset_sdc_init()
80{
81    //////////// SD Card initialisation //////////
82 
83    unsigned int rsp;
84
85    // define the SD card clock period
86    iowrite32( &ioc_address[SDC_PERIOD] , 2 );
87
88    // send CMD0 command (soft reset / no argument)
89    rsp = reset_sdc_send_cmd( SDC_CMD0 , 0 );
90    if ( rsp == 0xFFFFFFFF )
91    {
92        reset_puts("\n[RESET ERROR] in reset_sdc_init() : no aknowledge to CMD0\n");
93        return 1;
94    }
95
96#if RESET_DEBUG
97reset_puts("\n[DEBUG SDC] reset_sdc_init() : SDC_CMD0 done\n");
98#endif
99
100    // send CMD8 command
101    rsp = reset_sdc_send_cmd( SDC_CMD8 , SDC_CMD8_ARGUMENT );
102    if ( rsp == 0xFFFFFFFF )
103    {
104        reset_puts("\n[RESET ERROR] in reset_sdc_init() : no response to CMD8\n");
105        return 1;
106    }
107    else if ( rsp != SDC_CMD8_ARGUMENT )
108    {
109        reset_puts("\n[RESET ERROR] in reset_sdc_init() : bad response to CMD8\n");
110        return 1;
111    }
112
113#if RESET_DEBUG
114reset_puts("\n[DEBUG SDC] reset_sdc_init() : SDC_CMD8 done\n");
115#endif
116
117    // send CMD41 command to get SDHC
118    rsp = reset_sdc_send_cmd( SDC_CMD41 , SDC_CMD41_ARGUMENT );
119    if ( rsp == 0xFFFFFFFF )
120    {
121        reset_puts("\n[RESET ERROR] in reset_sdc_init() : no response to CMD41\n");
122        return 1;
123    }
124    sdc_sdhc = ( (rsp & SDC_CMD41_RSP_CCS) != 0 );
125
126#if RESET_DEBUG
127reset_puts("\n[DEBUG SDC] reset_sdc_init() : SDC_CMD41 done / sdhc = ");
128reset_putd( sdc_sdhc );
129reset_puts("\n");
130#endif
131
132    // send CMD3 to get RCA
133    rsp = reset_sdc_send_cmd( SDC_CMD3 , 0 );
134    if ( rsp == 0xFFFFFFFF )
135    {
136        reset_puts("\n[RESET ERROR] in reset_sdc_init() : no response to CMD3\n");
137        return 1;
138    }
139    sdc_rca = rsp;
140
141#if RESET_DEBUG
142reset_puts("\n[DEBUG SDC] reset_sdc_init() : SDC_CMD3 done / rca = ");
143reset_putd( sdc_rca );
144reset_puts("\n");
145#endif
146
147    // send CMD7
148    rsp = reset_sdc_send_cmd( SDC_CMD7 , sdc_rca );
149    if ( rsp == 0xFFFFFFFF )
150    {
151        reset_puts("\n[RESET ERROR] in reset_sdc_init() : no response to CMD7\n");
152        return 1;
153    }
154
155#if RESET_DEBUG
156reset_puts("\n[DEBUG SDC] reset_sdc_init() : SDC_CMD7 done\n");
157#endif
158
159    //////////// AHCI interface initialisation  ///////
160
161    // initialise the command descriptor
162    ahci_cmd_desc.ctba  = (unsigned int)&ahci_cmd_table;
163    ahci_cmd_desc.ctbau = 0;
164
165#if USE_IOB
166    // update external memory for the commande descriptor
167    reset_L2_sync( &ahci_cmd_desc , sizeof( ahci_cmd_desc_t ) );
168#endif
169
170    // initialise AHCI registers
171    iowrite32( &ioc_address[AHCI_PXCLB]  , (unsigned int)&ahci_cmd_desc );
172    iowrite32( &ioc_address[AHCI_PXCLBU] , 0 );
173    iowrite32( &ioc_address[AHCI_PXIE]   , 0 );
174    iowrite32( &ioc_address[AHCI_PXIS]   , 0 );
175    iowrite32( &ioc_address[AHCI_PXCI]   , 0 );
176    iowrite32( &ioc_address[AHCI_PXCMD]  , 1 );
177
178#if RESET_DEBUG
179reset_puts("\n[DEBUG SDC] reset_sdc_init() : AHCI init done\n");
180#endif
181
182    return 0;
183
184} // end reset_sdc_init()
185
186
187///////////////////////////////////////////////////////////////////////////////
188// This function register one command in both the command descriptor
189// and the command data, and updates the HBA_PXCI register.
190// The addresses are supposed to be identity mapping (vaddr == paddr).
191// return 0 if success, -1 if error
192///////////////////////////////////////////////////////////////////////////////
193unsigned int reset_sdc_read( unsigned int  lba,
194                             void*         buffer,
195                             unsigned int  count )
196{
197    unsigned int       pxci;              // AHCI_PXCI register value
198    unsigned int       pxis;              // AHCI_PXIS register value
199
200#if RESET_DEBUG
201reset_puts("\n[DEBUG SDC] reset_sdc_read() : buffer = ");
202reset_putx( (unsigned int)buffer );
203reset_puts(" / nblocks = ");
204reset_putd( count );
205reset_puts(" / lba = ");
206reset_putd( lba );
207reset_puts("\n");
208#endif
209
210    // check buffer alignment
211    if( (unsigned int)buffer & 0x3F )
212    {
213        reset_puts("\n[SDC ERROR] in reset_sdc_read() : buffer not 64 bytes aligned\n");
214        return 1;
215    }
216
217    // set command header: lba value
218    ahci_cmd_table.header.lba0 = (char)lba;
219    ahci_cmd_table.header.lba1 = (char)(lba>>8);
220    ahci_cmd_table.header.lba2 = (char)(lba>>16);
221    ahci_cmd_table.header.lba3 = (char)(lba>>24);
222    ahci_cmd_table.header.lba4 = 0;
223    ahci_cmd_table.header.lba5 = 0;
224
225    // set command buffer: address and size)
226    ahci_cmd_table.buffer.dba  = (unsigned int)(buffer);
227    ahci_cmd_table.buffer.dbau = 0;
228    ahci_cmd_table.buffer.dbc  = count*512;
229
230    // set command descriptor: one single buffer / read access
231    ahci_cmd_desc.prdtl[0] = 1;
232    ahci_cmd_desc.prdtl[1] = 0;
233    ahci_cmd_desc.flag[0]  = 0;  // read
234   
235#if RESET_DEBUG
236reset_puts("\n[DEBUG SDC] reset_sdc_read() : command registered\n");
237#endif
238
239#if USE_IOB
240    // update external memory for command table
241    reset_L2_sync( &ahci_cmd_table , 32 );
242
243    // update external memory for command descriptor
244    reset_L2_sync( &ahci_cmd_desc , 16 );
245#endif
246
247    // start transfer
248    iowrite32( &ioc_address[AHCI_PXCI] , 1 );
249
250#if RESET_DEBUG
251reset_puts("\n[DEBUG SDC] reset_sdc_read() : AHCI_SDC activated at cycle ");
252reset_putd( proctime() );
253reset_puts("\n");
254#endif
255
256#if (RESET_HARD_CC == 0) || USE_IOB
257    // inval buffer in L1 cache
258    reset_L1_inval( buffer , count * 512 );
259#endif
260
261#if USE_IOB
262    // inval buffer in  L2 cache
263    reset_L2_inval( buffer , count * 512 );
264#endif
265
266    // poll PXCI until command completed by AHCI
267    unsigned int iter = SDC_POLLING_TIMEOUT;
268    do
269    {
270        pxci = ioread32( &ioc_address[AHCI_PXCI] );
271        iter--;
272        if (iter == 0 )
273        {
274            reset_puts("\n[SDC ERROR] in reset_sdc_read() : polling PXCI timeout\n");
275            return 1;
276        }
277    }
278    while( pxci ); 
279             
280    // get PXIS register
281    pxis = ioread32( &ioc_address[AHCI_PXIS] );
282
283    // reset PXIS register
284    iowrite32( &ioc_address[AHCI_PXIS] , 0 );
285
286    // check error status
287    if ( pxis & 0x40000000 ) 
288    {
289        reset_puts("\n[RESET ERROR] in reset_sdc_read() : status error\n");
290        return 1;
291    }
292
293    return 0;
294
295} // end reset_sdc_read()
296
297// Local Variables:
298// tab-width: 4
299// c-basic-offset: 4
300// c-file-offsets:((innamespace . 0)(inline-open . 0))
301// indent-tabs-mode: nil
302// End:
303// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
Note: See TracBrowser for help on using the repository browser.