1 /* $Id: xsysace_l.c,v 1.1.1.1 2005/04/11 02:50:17 jack Exp $ */
2 /******************************************************************************
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.
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.
26 * Xilinx products are not intended for use in life support appliances,
27 * devices, or systems. Use in such applications is expressly prohibited.
30 * (c) Copyright 2002 Xilinx Inc.
31 * All rights reserved.
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.
38 ******************************************************************************/
39 /*****************************************************************************/
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.
50 * MODIFICATION HISTORY:
52 * Ver Who Date Changes
53 * ----- ---- -------- -----------------------------------------------
54 * 1.00a rpm 06/14/02 work in progress
57 ******************************************************************************/
59 /***************************** Include Files *********************************/
61 #include "xsysace_l.h"
63 /************************** Constant Definitions *****************************/
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
73 #if (XSA_ADDR_ALIGN == 4)
75 #define XIo_In XIo_In32
76 #define XIo_Out XIo_Out32
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 */
88 #endif /* (XSA_ADDR_ALIGN == 4) */
90 /**************************** Type Definitions *******************************/
92 /***************** Macros (Inline Functions) Definitions *********************/
94 /************************** Function Prototypes ******************************/
96 /************************** Variable Definitions *****************************/
98 /*****************************************************************************/
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.
104 * @param Address is the address to read from.
106 * @return The 32-bit value of the address.
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.
111 ******************************************************************************/
112 #ifdef XPAR_XSYSACE_16BIT_MODE
114 XSysAce_RegRead32(u32 Address)
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...
125 Data = (u16) XIo_In(Address);
126 XIo_FromLittleEndian16(Data, &ConvertedData);
127 Value = (u32) ConvertedData;
129 Data = (u16) XIo_In(Address + (2 * XSA_ADDR_ALIGN));
130 XIo_FromLittleEndian16(Data, &ConvertedData);
131 Value |= ((u32) ConvertedData << 16);
137 XSysAce_RegRead32(u32 Address)
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.
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);
156 /*****************************************************************************/
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.
162 * @param Address is the address to read from.
164 * @return The 16-bit value of the address.
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.
169 ******************************************************************************/
170 #ifdef XPAR_XSYSACE_16BIT_MODE
172 XSysAce_RegRead16(u32 Address)
178 * Need to endian convert the 16-bit value. The ACE registers are little-
181 Data = (u16) XIo_In(Address);
182 XIo_FromLittleEndian16(Data, &ConvertedData);
183 return ConvertedData;
187 XSysAce_RegRead16(u32 Address)
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.
197 Value = (u16) XIo_In(Address);
198 Value |= ((u16) XIo_In(Address + (1 * XSA_ADDR_ALIGN)) << 8);
204 /*****************************************************************************/
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.
210 * @param Address is the address to write to.
211 * @param Data is the value to write
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.
218 ******************************************************************************/
219 #ifdef XPAR_XSYSACE_16BIT_MODE
221 XSysAce_RegWrite32(u32 Address, u32 Data)
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.
232 XIo_ToLittleEndian16(Hword, &ConvertedData);
233 XIo_Out(Address, ConvertedData);
235 Hword = (u16) (Data >> 16);
236 XIo_ToLittleEndian16(Hword, &ConvertedData);
237 XIo_Out(Address + (2 * XSA_ADDR_ALIGN), ConvertedData);
241 XSysAce_RegWrite32(u32 Address, u32 Data)
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.
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));
256 /*****************************************************************************/
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.
262 * @param Address is the address to write to.
263 * @param Data is the value to write
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.
270 ******************************************************************************/
271 #ifdef XPAR_XSYSACE_16BIT_MODE
273 XSysAce_RegWrite16(u32 Address, u16 Data)
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.
281 XIo_ToLittleEndian16(Data, &ConvertedData);
282 XIo_Out(Address, ConvertedData);
286 XSysAce_RegWrite16(u32 Address, u16 Data)
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.
294 XIo_Out(Address, (u8) Data);
295 XIo_Out(Address + (1 * XSA_ADDR_ALIGN), (u8) (Data >> 8));
299 /*****************************************************************************/
302 * Read a CompactFlash sector. This is a blocking, low-level function which
303 * does not return until the specified sector is read.
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.
311 * The number of bytes read. If this number is not equal to the sector size,
312 * 512 bytes, then an error occurred.
318 ******************************************************************************/
320 XSysAce_ReadSector(u32 BaseAddress, u32 SectorId, u8 * BufferPtr)
324 /* Request and wait for the lock */
325 XSysAce_mWaitForLock(BaseAddress);
327 /* See if the CF is ready for a command */
328 if (!XSysAce_mIsReadyForCmd(BaseAddress)) {
332 /* Write the sector ID (LBA) */
333 XSysAce_RegWrite32(BaseAddress + XSA_MLR_OFFSET, SectorId);
335 /* Send a read command of one sector to the controller */
336 XSysAce_RegWrite16(BaseAddress + XSA_SCCR_OFFSET,
337 XSA_SCCR_READDATA_MASK | 1);
339 /* Reset configuration controller (be sure to keep the lock) */
340 XSysAce_mOrControlReg(BaseAddress, XSA_CR_CFGRESET_MASK);
342 /* Read a sector of data from the data buffer */
343 NumRead = XSysAce_ReadDataBuffer(BaseAddress, BufferPtr,
346 /* Clear reset of configuration controller and locks */
347 XSysAce_mAndControlReg(BaseAddress, ~(XSA_CR_CFGRESET_MASK |
348 XSA_CR_LOCKREQ_MASK));
353 /*****************************************************************************/
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.
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.
365 * The number of bytes written. If this number is not equal to the sector size,
366 * 512 bytes, then an error occurred.
372 ******************************************************************************/
374 XSysAce_WriteSector(u32 BaseAddress, u32 SectorId, u8 * BufferPtr)
379 XSysAce_mWaitForLock(BaseAddress);
381 /* See if the CF is ready for a command */
382 if (!XSysAce_mIsReadyForCmd(BaseAddress)) {
386 /* Write the sector ID (LBA) */
387 XSysAce_RegWrite32(BaseAddress + XSA_MLR_OFFSET, SectorId);
389 /* Send a write command of one sector to the controller */
390 XSysAce_RegWrite16(BaseAddress + XSA_SCCR_OFFSET,
391 XSA_SCCR_READDATA_MASK | 1);
393 /* Reset configuration controller (be sure to keep the lock) */
394 XSysAce_mOrControlReg(BaseAddress, XSA_CR_CFGRESET_MASK);
396 /* Write a sector of data to the data buffer */
397 NumSent = XSysAce_WriteDataBuffer(BaseAddress, BufferPtr,
400 /* Clear reset of configuration controller and locks */
401 XSysAce_mAndControlReg(BaseAddress, ~(XSA_CR_CFGRESET_MASK |
402 XSA_CR_LOCKREQ_MASK));
407 /*****************************************************************************/
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.
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
421 * The total number of bytes read, or 0 if an error occurred.
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.
430 ******************************************************************************/
432 XSysAce_ReadDataBuffer(u32 BaseAddress, u8 * BufferPtr, int Size)
434 int DataBytes; /* number of data bytes written */
439 * Read data two bytes at a time. We need to wait for the data
440 * buffer to be ready before reading the buffer.
443 for (DataBytes = 0; DataBytes < Size;) {
445 * If at any point during this read an error occurs, exit early
447 if (XSysAce_mGetErrorReg(BaseAddress) != 0) {
451 if (BufferBytes == 0) {
453 * Wait for CF data buffer to ready, then reset buffer byte count
455 while ((XSysAce_mGetStatusReg(BaseAddress)
456 & XSA_SR_DATABUFRDY_MASK) == 0) ;
458 BufferBytes = XSA_DATA_BUFFER_SIZE;
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.
467 Data = XSysAce_RegRead16(BaseAddress + XSA_DBR_OFFSET);
468 *BufferPtr++ = (u8) Data;
471 if (DataBytes < Size) {
472 /* Still more room in the output buffer */
473 *BufferPtr++ = (u8) (Data >> 8);
481 * If a complete data buffer was not read, read and ignore the remaining
484 while (BufferBytes != 0) {
486 * If at any point during this read an error occurs, exit early
488 if (XSysAce_mGetErrorReg(BaseAddress) != 0) {
492 (void) XSysAce_RegRead16(BaseAddress + XSA_DBR_OFFSET);
499 /*****************************************************************************/
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.
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
516 * The total number of bytes written (not including pad bytes), or 0 if an
523 ******************************************************************************/
525 XSysAce_WriteDataBuffer(u32 BaseAddress, u8 * BufferPtr, int Size)
527 int DataBytes; /* number of data bytes written */
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.
536 for (DataBytes = 0; DataBytes < Size;) {
538 * If at any point during this write an error occurs, exit early
540 if (XSysAce_mGetErrorReg(BaseAddress) != 0) {
544 if (BufferBytes == 0) {
546 * Wait for CF read data buffer to ready, then reset buffer byte
549 while ((XSysAce_mGetStatusReg(BaseAddress)
550 & XSA_SR_DATABUFRDY_MASK) == 0) ;
552 BufferBytes = XSA_DATA_BUFFER_SIZE;
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.
564 if (DataBytes < Size) {
565 /* Still more data in the incoming buffer */
566 Data |= ((u16) * BufferPtr++ << 8);
569 /* No more data in the incoming buffer, send a pad byte of 0 */
570 Data |= ((u16) 0 << 8);
573 XSysAce_RegWrite16(BaseAddress + XSA_DBR_OFFSET, Data);
579 * If a complete data buffer was not filled, fill it with pad bytes (zeros)
581 while (BufferBytes != 0) {
583 * If at any point during this write an error occurs, exit early
585 if (XSysAce_mGetErrorReg(BaseAddress) != 0) {
589 XSysAce_RegWrite16(BaseAddress + XSA_DBR_OFFSET, 0);