import of ftp.dlink.com/GPL/DSMG-600_reB/ppclinux.tar.gz
[linux-2.4.21-pre4.git] / drivers / block / xilinx_sysace / xsysace_l.c
1 /* $Id: xsysace_l.c,v 1.1.1.1 2005/04/11 02:50:17 jack Exp $ */
2 /******************************************************************************
3 *
4 *     Author: Xilinx, Inc.
5 *     
6 *     
7 *     This program is free software; you can redistribute it and/or modify it
8 *     under the terms of the GNU General Public License as published by the
9 *     Free Software Foundation; either version 2 of the License, or (at your
10 *     option) any later version.
11 *     
12 *     
13 *     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
14 *     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
15 *     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
16 *     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
17 *     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR
18 *     OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
19 *     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
20 *     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
21 *     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
22 *     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
23 *     FITNESS FOR A PARTICULAR PURPOSE.
24 *     
25 *     
26 *     Xilinx products are not intended for use in life support appliances,
27 *     devices, or systems. Use in such applications is expressly prohibited.
28 *     
29 *     
30 *     (c) Copyright 2002 Xilinx Inc.
31 *     All rights reserved.
32 *     
33 *     
34 *     You should have received a copy of the GNU General Public License along
35 *     with this program; if not, write to the Free Software Foundation, Inc.,
36 *     675 Mass Ave, Cambridge, MA 02139, USA.
37 *
38 ******************************************************************************/
39 /*****************************************************************************/
40 /**
41 *
42 * @file xsysace_l.c
43 *
44 * This file contains low-level functions to read and write CompactFlash
45 * sectors and ACE controller registers. These functions can be used when only
46 * the low-level functionality of the driver is desired. The user would
47 * typically use the high-level driver functions defined in xsysace.h.
48 *
49 * <pre>
50 * MODIFICATION HISTORY:
51 *
52 * Ver   Who  Date     Changes
53 * ----- ---- -------- -----------------------------------------------
54 * 1.00a rpm  06/14/02 work in progress
55 * </pre>
56 *
57 ******************************************************************************/
58
59 /***************************** Include Files *********************************/
60
61 #include "xsysace_l.h"
62
63 /************************** Constant Definitions *****************************/
64
65 /*
66  * Set up the access width of the MPU registers based on compile-time constants.
67  * If hardware requires 32-bit aligned addresses (XSA_ADDR_ALIGN=4) to access
68  * the MPU registers, then access all of them as 32 bits. If hardware allows
69  * 8-bit aligned addresses (XSA_ADDR_ALIGN=1, or not 4) to access the MPU
70  * registers, access them as 8 or 16 bits depending on the bus mode of the ACE
71  * controller.
72  */
73 #if (XSA_ADDR_ALIGN == 4)
74
75 #define XIo_In   XIo_In32
76 #define XIo_Out  XIo_Out32
77
78 #else
79
80 #ifdef XPAR_XSYSACE_16BIT_MODE
81 #define XIo_In   XIo_In16
82 #define XIo_Out  XIo_Out16
83 #else                           /* XPAR_XSYSACE_16BIT_MODE */
84 #define XIo_In   XIo_In8
85 #define XIo_Out  XIo_Out8
86 #endif                          /* XPAR_XSYSACE_16BIT_MODE */
87
88 #endif                          /* (XSA_ADDR_ALIGN == 4) */
89
90 /**************************** Type Definitions *******************************/
91
92 /***************** Macros (Inline Functions) Definitions *********************/
93
94 /************************** Function Prototypes ******************************/
95
96 /************************** Variable Definitions *****************************/
97
98 /*****************************************************************************/
99 /**
100 *
101 * Read a 32-bit value from the given address. Based on a compile-time
102 * constant, do the read in two 16-bit reads or four 8-bit reads.
103 *
104 * @param    Address is the address to read from.
105 *
106 * @return   The 32-bit value of the address.
107 *
108 * @note     No need for endian conversion in 8-bit mode since this function
109 *           gets the bytes into their proper lanes in the 32-bit word.
110 *
111 ******************************************************************************/
112 #ifdef XPAR_XSYSACE_16BIT_MODE
113 u32
114 XSysAce_RegRead32(u32 Address)
115 {
116         u16 Data;
117         u16 ConvertedData;
118         u32 Value = 0;
119
120         /*
121          * Need to endian convert each 32-bit value. The ACE registers are little-
122          * endian, so we read the two LSBs first, endian convert, then put them
123          * in the LSB lanes of the 32-bit word. etc...
124          */
125         Data = (u16) XIo_In(Address);
126         XIo_FromLittleEndian16(Data, &ConvertedData);
127         Value = (u32) ConvertedData;
128
129         Data = (u16) XIo_In(Address + (2 * XSA_ADDR_ALIGN));
130         XIo_FromLittleEndian16(Data, &ConvertedData);
131         Value |= ((u32) ConvertedData << 16);
132
133         return Value;
134 }
135 #else
136 u32
137 XSysAce_RegRead32(u32 Address)
138 {
139         u32 Value = 0;
140
141         /*
142          * The ACE registers are little-endian always. This code reads each 8-bit
143          * register value, in order from LSB to MSB, and shifts it to the correct
144          * byte lane of the 32-bit word. This code should work on both
145          * little-endian and big-endian processors.
146          */
147         Value = (u32) XIo_In(Address);
148         Value |= ((u32) XIo_In(Address + (1 * XSA_ADDR_ALIGN)) << 8);
149         Value |= ((u32) XIo_In(Address + (2 * XSA_ADDR_ALIGN)) << 16);
150         Value |= ((u32) XIo_In(Address + (3 * XSA_ADDR_ALIGN)) << 24);
151
152         return Value;
153 }
154 #endif
155
156 /*****************************************************************************/
157 /**
158 *
159 * Read a 16-bit value from the given address. Based on a compile-time
160 * constant, do the read in one 16-bit read or two 8-bit reads.
161 *
162 * @param    Address is the address to read from.
163 *
164 * @return   The 16-bit value of the address.
165 *
166 * @note     No need for endian conversion in 8-bit mode since this function
167 *           gets the bytes into their proper lanes in the 16-bit word.
168 *
169 ******************************************************************************/
170 #ifdef XPAR_XSYSACE_16BIT_MODE
171 u16
172 XSysAce_RegRead16(u32 Address)
173 {
174         u16 Data;
175         u16 ConvertedData;
176
177         /*
178          * Need to endian convert the 16-bit value. The ACE registers are little-
179          * endian.
180          */
181         Data = (u16) XIo_In(Address);
182         XIo_FromLittleEndian16(Data, &ConvertedData);
183         return ConvertedData;
184 }
185 #else
186 u16
187 XSysAce_RegRead16(u32 Address)
188 {
189         u16 Value = 0;
190
191         /*
192          * The ACE registers are little-endian always. This code reads each 8-bit
193          * register value, in order from LSB to MSB, and shifts it to the correct
194          * byte lane of the 32-bit word. This code should work on both
195          * little-endian and big-endian processors.
196          */
197         Value = (u16) XIo_In(Address);
198         Value |= ((u16) XIo_In(Address + (1 * XSA_ADDR_ALIGN)) << 8);
199
200         return Value;
201 }
202 #endif
203
204 /*****************************************************************************/
205 /**
206 *
207 * Write a 32-bit value to the given address. Based on a compile-time
208 * constant, do the write in two 16-bit writes or four 8-bit writes.
209 *
210 * @param    Address is the address to write to.
211 * @param    Data is the value to write
212 *
213 * @return   None.
214 *
215 * @note     No need for endian conversion in 8-bit mode since this function
216 *           writes the bytes into their proper lanes based on address.
217 *
218 ******************************************************************************/
219 #ifdef XPAR_XSYSACE_16BIT_MODE
220 void
221 XSysAce_RegWrite32(u32 Address, u32 Data)
222 {
223         u16 Hword;
224         u16 ConvertedData;
225
226         /*
227          * The ACE registers are little-endian always. This code takes each 16-bit
228          * value of the incoming 32-bit word and endian converts it, then writes it
229          * to the ACE register.
230          */
231         Hword = (u16) Data;
232         XIo_ToLittleEndian16(Hword, &ConvertedData);
233         XIo_Out(Address, ConvertedData);
234
235         Hword = (u16) (Data >> 16);
236         XIo_ToLittleEndian16(Hword, &ConvertedData);
237         XIo_Out(Address + (2 * XSA_ADDR_ALIGN), ConvertedData);
238 }
239 #else
240 void
241 XSysAce_RegWrite32(u32 Address, u32 Data)
242 {
243         /*
244          * The ACE registers are little-endian always. This code reads each 8-bit
245          * register value, in order from LSB to MSB, and shifts it to the correct
246          * byte lane of the 32-bit word. This code should work on both
247          * little-endian and big-endian processors.
248          */
249         XIo_Out(Address, (u8) Data);
250         XIo_Out(Address + (1 * XSA_ADDR_ALIGN), (u8) (Data >> 8));
251         XIo_Out(Address + (2 * XSA_ADDR_ALIGN), (u8) (Data >> 16));
252         XIo_Out(Address + (3 * XSA_ADDR_ALIGN), (u8) (Data >> 24));
253 }
254 #endif
255
256 /*****************************************************************************/
257 /**
258 *
259 * Write a 16-bit value to the given address. Based on a compile-time
260 * constant, do the write in one 16-bit write or two 8-bit writes.
261 *
262 * @param    Address is the address to write to.
263 * @param    Data is the value to write
264 *
265 * @return   None.
266 *
267 * @note     No need for endian conversion in 8-bit mode since this function
268 *           writes the bytes into their proper lanes based on address.
269 *
270 ******************************************************************************/
271 #ifdef XPAR_XSYSACE_16BIT_MODE
272 void
273 XSysAce_RegWrite16(u32 Address, u16 Data)
274 {
275         u16 ConvertedData;
276
277         /*
278          * The ACE registers are little-endian always. This code takes the incoming
279          * 16-bit and endian converts it, then writes it to the ACE register.
280          */
281         XIo_ToLittleEndian16(Data, &ConvertedData);
282         XIo_Out(Address, ConvertedData);
283 }
284 #else
285 void
286 XSysAce_RegWrite16(u32 Address, u16 Data)
287 {
288         /*
289          * The ACE registers are little-endian always. This code reads each 8-bit
290          * register value, in order from LSB to MSB, and shifts it to the correct
291          * byte lane of the 32-bit word. This code should work on both
292          * little-endian and big-endian processors.
293          */
294         XIo_Out(Address, (u8) Data);
295         XIo_Out(Address + (1 * XSA_ADDR_ALIGN), (u8) (Data >> 8));
296 }
297 #endif
298
299 /*****************************************************************************/
300 /**
301 *
302 * Read a CompactFlash sector. This is a blocking, low-level function which
303 * does not return until the specified sector is read.
304 *
305 * @param BaseAddress is the base address of the device
306 * @param SectorId is the id of the sector to read
307 * @param BufferPtr is a pointer to a buffer where the data will be stored.
308 *
309 * @return
310 *
311 * The number of bytes read. If this number is not equal to the sector size,
312 * 512 bytes, then an error occurred.
313 *
314 * @note
315 *
316 * None.
317 *
318 ******************************************************************************/
319 int
320 XSysAce_ReadSector(u32 BaseAddress, u32 SectorId, u8 * BufferPtr)
321 {
322         int NumRead;
323
324         /* Request and wait for the lock */
325         XSysAce_mWaitForLock(BaseAddress);
326
327         /* See if the CF is ready for a command */
328         if (!XSysAce_mIsReadyForCmd(BaseAddress)) {
329                 return 0;
330         }
331
332         /* Write the sector ID (LBA) */
333         XSysAce_RegWrite32(BaseAddress + XSA_MLR_OFFSET, SectorId);
334
335         /* Send a read command of one sector to the controller */
336         XSysAce_RegWrite16(BaseAddress + XSA_SCCR_OFFSET,
337                            XSA_SCCR_READDATA_MASK | 1);
338
339         /* Reset configuration controller (be sure to keep the lock) */
340         XSysAce_mOrControlReg(BaseAddress, XSA_CR_CFGRESET_MASK);
341
342         /* Read a sector of data from the data buffer */
343         NumRead = XSysAce_ReadDataBuffer(BaseAddress, BufferPtr,
344                                          XSA_CF_SECTOR_SIZE);
345
346         /* Clear reset of configuration controller and locks */
347         XSysAce_mAndControlReg(BaseAddress, ~(XSA_CR_CFGRESET_MASK |
348                                               XSA_CR_LOCKREQ_MASK));
349
350         return NumRead;
351 }
352
353 /*****************************************************************************/
354 /**
355 *
356 * Write a CompactFlash sector. This is a blocking, low-level function which
357 * does not return until the specified sector is written in its entirety.
358 *
359 * @param BaseAddress is the base address of the device
360 * @param SectorId is the id of the sector to write
361 * @param BufferPtr is a pointer to a buffer used to write the sector.
362 *
363 * @return
364 *
365 * The number of bytes written. If this number is not equal to the sector size,
366 * 512 bytes, then an error occurred.
367 *
368 * @note
369 *
370 * None.
371 *
372 ******************************************************************************/
373 int
374 XSysAce_WriteSector(u32 BaseAddress, u32 SectorId, u8 * BufferPtr)
375 {
376         int NumSent;
377
378         /* Get the lock */
379         XSysAce_mWaitForLock(BaseAddress);
380
381         /* See if the CF is ready for a command */
382         if (!XSysAce_mIsReadyForCmd(BaseAddress)) {
383                 return 0;
384         }
385
386         /* Write the sector ID (LBA) */
387         XSysAce_RegWrite32(BaseAddress + XSA_MLR_OFFSET, SectorId);
388
389         /* Send a write command of one sector to the controller */
390         XSysAce_RegWrite16(BaseAddress + XSA_SCCR_OFFSET,
391                            XSA_SCCR_READDATA_MASK | 1);
392
393         /* Reset configuration controller (be sure to keep the lock) */
394         XSysAce_mOrControlReg(BaseAddress, XSA_CR_CFGRESET_MASK);
395
396         /* Write a sector of data to the data buffer */
397         NumSent = XSysAce_WriteDataBuffer(BaseAddress, BufferPtr,
398                                           XSA_CF_SECTOR_SIZE);
399
400         /* Clear reset of configuration controller and locks */
401         XSysAce_mAndControlReg(BaseAddress, ~(XSA_CR_CFGRESET_MASK |
402                                               XSA_CR_LOCKREQ_MASK));
403
404         return NumSent;
405 }
406
407 /*****************************************************************************/
408 /**
409 *
410 * Read the specified number of bytes from the data buffer of the ACE
411 * controller. The data buffer, which is 32 bytes, can only be read two bytes
412 * at a time.  Once the data buffer is read, we wait for it to be filled again
413 * before reading the next buffer's worth of data.
414 *
415 * @param BaseAddress is the base address of the device
416 * @param BufferPtr is a pointer to a buffer in which to store data.
417 * @param Size is the number of bytes to read
418 *
419 * @return
420 *
421 * The total number of bytes read, or 0 if an error occurred.
422 *
423 * @note
424 *
425 * If Size is not aligned with the size of the data buffer (32 bytes), this
426 * function will read the entire data buffer, dropping the extra bytes on the
427 * floor since the user did not request them. This is necessary to get the
428 * data buffer to be ready again.
429 *
430 ******************************************************************************/
431 int
432 XSysAce_ReadDataBuffer(u32 BaseAddress, u8 * BufferPtr, int Size)
433 {
434         int DataBytes;          /* number of data bytes written */
435         int BufferBytes;
436         u16 Data;
437
438         /*
439          * Read data two bytes at a time. We need to wait for the data
440          * buffer to be ready before reading the buffer.
441          */
442         BufferBytes = 0;
443         for (DataBytes = 0; DataBytes < Size;) {
444                 /*
445                  * If at any point during this read an error occurs, exit early
446                  */
447                 if (XSysAce_mGetErrorReg(BaseAddress) != 0) {
448                         return 0;
449                 }
450
451                 if (BufferBytes == 0) {
452                         /*
453                          * Wait for CF data buffer to ready, then reset buffer byte count
454                          */
455                         while ((XSysAce_mGetStatusReg(BaseAddress)
456                                 & XSA_SR_DATABUFRDY_MASK) == 0) ;
457
458                         BufferBytes = XSA_DATA_BUFFER_SIZE;
459                 }
460
461                 /*
462                  * Need to read two bytes. Put the first one in the output buffer
463                  * because if we're here we know one more is needed. Put the second one
464                  * in the output buffer if there is still room, or just drop it on the
465                  * floor if the requested number of bytes have already been read.
466                  */
467                 Data = XSysAce_RegRead16(BaseAddress + XSA_DBR_OFFSET);
468                 *BufferPtr++ = (u8) Data;
469                 DataBytes++;
470
471                 if (DataBytes < Size) {
472                         /* Still more room in the output buffer */
473                         *BufferPtr++ = (u8) (Data >> 8);
474                         DataBytes++;
475                 }
476
477                 BufferBytes -= 2;
478         }
479
480         /*
481          * If a complete data buffer was not read, read and ignore the remaining
482          * bytes
483          */
484         while (BufferBytes != 0) {
485                 /*
486                  * If at any point during this read an error occurs, exit early
487                  */
488                 if (XSysAce_mGetErrorReg(BaseAddress) != 0) {
489                         return 0;
490                 }
491
492                 (void) XSysAce_RegRead16(BaseAddress + XSA_DBR_OFFSET);
493                 BufferBytes -= 2;
494         }
495
496         return DataBytes;
497 }
498
499 /*****************************************************************************/
500 /**
501 *
502 * Write the specified number of bytes to the data buffer of the ACE controller.
503 * The data buffer, which is 32 bytes, can only be written two bytes at a time.
504 * Once the data buffer is written, we wait for it to be empty again before
505 * writing the next buffer's worth of data. If the size of the incoming buffer
506 * is not aligned with the System ACE data buffer size (32 bytes), then this
507 * routine pads out the data buffer with zeros so the entire data buffer is
508 * written. This is necessary for the ACE controller to process the data buffer.
509 *
510 * @param BaseAddress is the base address of the device
511 * @param BufferPtr is a pointer to a buffer used to write to the controller.
512 * @param Size is the number of bytes to write
513 *
514 * @return
515 *
516 * The total number of bytes written (not including pad bytes), or 0 if an
517 * error occurs.
518 *
519 * @note
520 *
521 * None.
522 *
523 ******************************************************************************/
524 int
525 XSysAce_WriteDataBuffer(u32 BaseAddress, u8 * BufferPtr, int Size)
526 {
527         int DataBytes;          /* number of data bytes written */
528         int BufferBytes;
529         u16 Data;
530
531         /*
532          * Write a sector two bytes at a time. We need to wait for the data
533          * buffer to be ready before writing the buffer.
534          */
535         BufferBytes = 0;
536         for (DataBytes = 0; DataBytes < Size;) {
537                 /*
538                  * If at any point during this write an error occurs, exit early
539                  */
540                 if (XSysAce_mGetErrorReg(BaseAddress) != 0) {
541                         return 0;
542                 }
543
544                 if (BufferBytes == 0) {
545                         /*
546                          * Wait for CF read data buffer to ready, then reset buffer byte
547                          * count
548                          */
549                         while ((XSysAce_mGetStatusReg(BaseAddress)
550                                 & XSA_SR_DATABUFRDY_MASK) == 0) ;
551
552                         BufferBytes = XSA_DATA_BUFFER_SIZE;
553                 }
554
555                 /*
556                  * Need to send two bytes. Grab the first one from the incoming buffer
557                  * because if we're here we know one more exists. Grab the second one
558                  * from the incoming buffer if there are still any bytes remaining, or
559                  * send a pad byte if the incoming buffer has been expired.
560                  */
561                 Data = *BufferPtr++;
562                 DataBytes++;
563
564                 if (DataBytes < Size) {
565                         /* Still more data in the incoming buffer */
566                         Data |= ((u16) * BufferPtr++ << 8);
567                         DataBytes++;
568                 } else {
569                         /* No more data in the incoming buffer, send a pad byte of 0 */
570                         Data |= ((u16) 0 << 8);
571                 }
572
573                 XSysAce_RegWrite16(BaseAddress + XSA_DBR_OFFSET, Data);
574
575                 BufferBytes -= 2;
576         }
577
578         /*
579          * If a complete data buffer was not filled, fill it with pad bytes (zeros)
580          */
581         while (BufferBytes != 0) {
582                 /*
583                  * If at any point during this write an error occurs, exit early
584                  */
585                 if (XSysAce_mGetErrorReg(BaseAddress) != 0) {
586                         return 0;
587                 }
588
589                 XSysAce_RegWrite16(BaseAddress + XSA_DBR_OFFSET, 0);
590                 BufferBytes -= 2;
591         }
592
593         return DataBytes;
594 }