]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/xilinx/common/xpacket_fifo_v1_00_b.c
ae2d6d43c54cb8f2778722a8abbb8bf2a76559c5
[karo-tx-uboot.git] / board / xilinx / common / xpacket_fifo_v1_00_b.c
1 /******************************************************************************
2 *
3 *     Author: Xilinx, Inc.
4 *
5 *
6 *     This program is free software; you can redistribute it and/or modify it
7 *     under the terms of the GNU General Public License as published by the
8 *     Free Software Foundation; either version 2 of the License, or (at your
9 *     option) any later version.
10 *
11 *
12 *     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
13 *     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
14 *     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
15 *     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
16 *     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING
17 *     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
18 *     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
19 *     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
20 *     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
21 *     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
22 *     FITNESS FOR A PARTICULAR PURPOSE.
23 *
24 *
25 *     Xilinx hardware products are not intended for use in life support
26 *     appliances, devices, or systems. Use in such applications is
27 *     expressly prohibited.
28 *
29 *
30 *     (c) Copyright 2002-2004 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 xpacket_fifo_v1_00_b.c
43 *
44 * Contains functions for the XPacketFifoV100b component. See xpacket_fifo_v1_00_b.h
45 * for more information about the component.
46 *
47 * <pre>
48 * MODIFICATION HISTORY:
49 *
50 * Ver   Who  Date     Changes
51 * ----- ---- -------- -----------------------------------------------
52 * 1.00b rpm 03/26/02  First release
53 * </pre>
54 *
55 *****************************************************************************/
56
57 /***************************** Include Files *********************************/
58
59 #include "xbasic_types.h"
60 #include "xio.h"
61 #include "xstatus.h"
62 #include "xpacket_fifo_v1_00_b.h"
63
64 /************************** Constant Definitions *****************************/
65
66 /* width of a FIFO word */
67
68 #define XPF_FIFO_WIDTH_BYTE_COUNT       4UL
69
70 /**************************** Type Definitions *******************************/
71
72 /***************** Macros (Inline Functions) Definitions *********************/
73
74 /************************* Variable Definitions ******************************/
75
76 /************************** Function Prototypes ******************************/
77
78 /*****************************************************************************/
79 /*
80 *
81 * This function initializes a packet FIFO.  Initialization resets the
82 * FIFO such that it's empty and ready to use.
83 *
84 * @param InstancePtr contains a pointer to the FIFO to operate on.
85 * @param RegBaseAddress contains the base address of the registers for
86 *        the packet FIFO.
87 * @param DataBaseAddress contains the base address of the data for
88 *        the packet FIFO.
89 *
90 * @return
91 *
92 * Always returns XST_SUCCESS.
93 *
94 * @note
95 *
96 * None.
97 *
98 ******************************************************************************/
99 XStatus
100 XPacketFifoV100b_Initialize(XPacketFifoV100b * InstancePtr,
101                             u32 RegBaseAddress, u32 DataBaseAddress)
102 {
103         /* assert to verify input argument are valid */
104
105         XASSERT_NONVOID(InstancePtr != NULL);
106
107         /* initialize the component variables to the specified state */
108
109         InstancePtr->RegBaseAddress = RegBaseAddress;
110         InstancePtr->DataBaseAddress = DataBaseAddress;
111         InstancePtr->IsReady = XCOMPONENT_IS_READY;
112
113         /* reset the FIFO such that it's empty and ready to use and indicate the
114          * initialization was successful, note that the is ready variable must be
115          * set prior to calling the reset function to prevent an assert
116          */
117         XPF_V100B_RESET(InstancePtr);
118
119         return XST_SUCCESS;
120 }
121
122 /*****************************************************************************/
123 /*
124 *
125 * This function performs a self-test on the specified packet FIFO.  The self
126 * test resets the FIFO and reads a register to determine if it is the correct
127 * reset value.  This test is destructive in that any data in the FIFO will
128 * be lost.
129 *
130 * @param InstancePtr is a pointer to the packet FIFO to be operated on.
131 *
132 * @param FifoType specifies the type of FIFO, read or write, for the self test.
133 *        The FIFO type is specified by the values XPF_READ_FIFO_TYPE or
134 *        XPF_WRITE_FIFO_TYPE.
135 *
136 * @return
137 *
138 * XST_SUCCESS is returned if the selftest is successful, or
139 * XST_PFIFO_BAD_REG_VALUE indicating that the value readback from the
140 * occupancy/vacancy count register after a reset does not match the
141 * specified reset value.
142 *
143 * @note
144 *
145 * None.
146 *
147 ******************************************************************************/
148 XStatus
149 XPacketFifoV100b_SelfTest(XPacketFifoV100b * InstancePtr, u32 FifoType)
150 {
151         u32 Register;
152
153         /* assert to verify valid input arguments */
154
155         XASSERT_NONVOID(InstancePtr != NULL);
156         XASSERT_NONVOID((FifoType == XPF_READ_FIFO_TYPE) ||
157                         (FifoType == XPF_WRITE_FIFO_TYPE));
158         XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
159
160         /* reset the fifo and then check to make sure the occupancy/vacancy
161          * register contents are correct for a reset condition
162          */
163         XPF_V100B_RESET(InstancePtr);
164
165         Register = XIo_In32(InstancePtr->RegBaseAddress +
166                             XPF_COUNT_STATUS_REG_OFFSET);
167
168         /* check the value of the register to ensure that it's correct for the
169          * specified FIFO type since both FIFO types reset to empty, but a bit
170          * in the register changes definition based upon FIFO type
171          */
172
173         if (FifoType == XPF_READ_FIFO_TYPE) {
174                 /* check the regiser value for a read FIFO which should be empty */
175
176                 if (Register != XPF_EMPTY_FULL_MASK) {
177                         return XST_PFIFO_BAD_REG_VALUE;
178                 }
179         } else {
180                 /* check the register value for a write FIFO which should not be full
181                  * on reset
182                  */
183                 if ((Register & XPF_EMPTY_FULL_MASK) != 0) {
184                         return XST_PFIFO_BAD_REG_VALUE;
185                 }
186         }
187
188         /* the test was successful */
189
190         return XST_SUCCESS;
191 }
192
193 /*****************************************************************************/
194 /*
195 *
196 * Read data from a FIFO and puts it into a specified buffer. The packet FIFO is
197 * currently 32 bits wide such that an input buffer which is a series of bytes
198 * is filled from the FIFO a word at a time. If the requested byte count is not
199 * a multiple of 32 bit words, it is necessary for this function to format the
200 * remaining 32 bit word from the FIFO into a series of bytes in the buffer.
201 * There may be up to 3 extra bytes which must be extracted from the last word
202 * of the FIFO and put into the buffer.
203 *
204 * @param InstancePtr contains a pointer to the FIFO to operate on.
205 * @param BufferPtr points to the memory buffer to write the data into. This
206 *        buffer must be 32 bit aligned or an alignment exception could be
207 *        generated. Since this buffer is a byte buffer, the data is assumed to
208 *        be endian independent.
209 * @param ByteCount contains the number of bytes to read from the FIFO. This
210 *        number of bytes must be present in the FIFO or an error will be
211 *        returned.
212 *
213 * @return
214 *
215 * XST_SUCCESS indicates the operation was successful.  If the number of
216 * bytes specified by the byte count is not present in the FIFO
217 * XST_PFIFO_LACK_OF_DATA is returned.
218 *
219 * If the function was successful, the specified buffer is modified to contain
220 * the bytes which were removed from the FIFO.
221 *
222 * @note
223 *
224 * Note that the exact number of bytes which are present in the FIFO is
225 * not known by this function.  It can only check for a number of 32 bit
226 * words such that if the byte count specified is incorrect, but is still
227 * possible based on the number of words in the FIFO, up to 3 garbage bytes
228 * may be present at the end of the buffer.
229 * <br><br>
230 * This function assumes that if the device consuming data from the FIFO is
231 * a byte device, the order of the bytes to be consumed is from the most
232 * significant byte to the least significant byte of a 32 bit word removed
233 * from the FIFO.
234 *
235 ******************************************************************************/
236 XStatus
237 XPacketFifoV100b_Read(XPacketFifoV100b * InstancePtr,
238                       u8 * BufferPtr, u32 ByteCount)
239 {
240         u32 FifoCount;
241         u32 WordCount;
242         u32 ExtraByteCount;
243         u32 *WordBuffer = (u32 *) BufferPtr;
244
245         /* assert to verify valid input arguments including 32 bit alignment of
246          * the buffer pointer
247          */
248         XASSERT_NONVOID(InstancePtr != NULL);
249         XASSERT_NONVOID(BufferPtr != NULL);
250         XASSERT_NONVOID(((u32) BufferPtr &
251                          (XPF_FIFO_WIDTH_BYTE_COUNT - 1)) == 0);
252         XASSERT_NONVOID(ByteCount != 0);
253         XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
254
255         /* get the count of how many 32 bit words are in the FIFO, if there aren't
256          * enought words to satisfy the request, return an error
257          */
258
259         FifoCount = XIo_In32(InstancePtr->RegBaseAddress +
260                              XPF_COUNT_STATUS_REG_OFFSET) & XPF_COUNT_MASK;
261
262         if ((FifoCount * XPF_FIFO_WIDTH_BYTE_COUNT) < ByteCount) {
263                 return XST_PFIFO_LACK_OF_DATA;
264         }
265
266         /* calculate the number of words to read from the FIFO before the word
267          * containing the extra bytes, and calculate the number of extra bytes
268          * the extra bytes are defined as those at the end of the buffer when
269          * the buffer does not end on a 32 bit boundary
270          */
271         WordCount = ByteCount / XPF_FIFO_WIDTH_BYTE_COUNT;
272         ExtraByteCount = ByteCount % XPF_FIFO_WIDTH_BYTE_COUNT;
273
274         /* Read the 32 bit words from the FIFO for all the buffer except the
275          * last word which contains the extra bytes, the following code assumes
276          * that the buffer is 32 bit aligned, otherwise an alignment exception could
277          * be generated
278          */
279         for (FifoCount = 0; FifoCount < WordCount; FifoCount++) {
280                 WordBuffer[FifoCount] = XIo_In32(InstancePtr->DataBaseAddress);
281         }
282
283         /* if there are extra bytes to handle, read the last word from the FIFO
284          * and insert the extra bytes into the buffer
285          */
286         if (ExtraByteCount > 0) {
287                 u32 LastWord;
288                 u8 *ExtraBytesBuffer = (u8 *) (WordBuffer + WordCount);
289
290                 /* get the last word from the FIFO for the extra bytes */
291
292                 LastWord = XIo_In32(InstancePtr->DataBaseAddress);
293
294                 /* one extra byte in the last word, put the byte into the next location
295                  * of the buffer, bytes in a word of the FIFO are ordered from most
296                  * significant byte to least
297                  */
298                 if (ExtraByteCount == 1) {
299                         ExtraBytesBuffer[0] = (u8) (LastWord >> 24);
300                 }
301
302                 /* two extra bytes in the last word, put each byte into the next two
303                  * locations of the buffer
304                  */
305                 else if (ExtraByteCount == 2) {
306                         ExtraBytesBuffer[0] = (u8) (LastWord >> 24);
307                         ExtraBytesBuffer[1] = (u8) (LastWord >> 16);
308                 }
309                 /* three extra bytes in the last word, put each byte into the next three
310                  * locations of the buffer
311                  */
312                 else if (ExtraByteCount == 3) {
313                         ExtraBytesBuffer[0] = (u8) (LastWord >> 24);
314                         ExtraBytesBuffer[1] = (u8) (LastWord >> 16);
315                         ExtraBytesBuffer[2] = (u8) (LastWord >> 8);
316                 }
317         }
318         return XST_SUCCESS;
319 }
320
321 /*****************************************************************************/
322 /*
323 *
324 * Write data into a packet FIFO. The packet FIFO is currently 32 bits wide
325 * such that an input buffer which is a series of bytes must be written into the
326 * FIFO a word at a time. If the buffer is not a multiple of 32 bit words, it is
327 * necessary for this function to format the remaining bytes into a single 32
328 * bit word to be inserted into the FIFO. This is necessary to avoid any
329 * accesses past the end of the buffer.
330 *
331 * @param InstancePtr contains a pointer to the FIFO to operate on.
332 * @param BufferPtr points to the memory buffer that data is to be read from
333 *        and written into the FIFO. Since this buffer is a byte buffer, the data
334 *        is assumed to be endian independent. This buffer must be 32 bit aligned
335 *        or an alignment exception could be generated.
336 * @param ByteCount contains the number of bytes to read from the buffer and to
337 *        write to the FIFO.
338 *
339 * @return
340 *
341 * XST_SUCCESS is returned if the operation succeeded.  If there is not enough
342 * room in the FIFO to hold the specified bytes, XST_PFIFO_NO_ROOM is
343 * returned.
344 *
345 * @note
346 *
347 * This function assumes that if the device inserting data into the FIFO is
348 * a byte device, the order of the bytes in each 32 bit word is from the most
349 * significant byte to the least significant byte.
350 *
351 ******************************************************************************/
352 XStatus
353 XPacketFifoV100b_Write(XPacketFifoV100b * InstancePtr,
354                        u8 * BufferPtr, u32 ByteCount)
355 {
356         u32 FifoCount;
357         u32 WordCount;
358         u32 ExtraByteCount;
359         u32 *WordBuffer = (u32 *) BufferPtr;
360
361         /* assert to verify valid input arguments including 32 bit alignment of
362          * the buffer pointer
363          */
364         XASSERT_NONVOID(InstancePtr != NULL);
365         XASSERT_NONVOID(BufferPtr != NULL);
366         XASSERT_NONVOID(((u32) BufferPtr &
367                          (XPF_FIFO_WIDTH_BYTE_COUNT - 1)) == 0);
368         XASSERT_NONVOID(ByteCount != 0);
369         XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
370
371         /* get the count of how many words may be inserted into the FIFO */
372
373         FifoCount = XIo_In32(InstancePtr->RegBaseAddress +
374                              XPF_COUNT_STATUS_REG_OFFSET) & XPF_COUNT_MASK;
375
376         /* Calculate the number of 32 bit words required to insert the specified
377          * number of bytes in the FIFO and determine the number of extra bytes
378          * if the buffer length is not a multiple of 32 bit words
379          */
380
381         WordCount = ByteCount / XPF_FIFO_WIDTH_BYTE_COUNT;
382         ExtraByteCount = ByteCount % XPF_FIFO_WIDTH_BYTE_COUNT;
383
384         /* take into account the extra bytes in the total word count */
385
386         if (ExtraByteCount > 0) {
387                 WordCount++;
388         }
389
390         /* if there's not enough room in the FIFO to hold the specified
391          * number of bytes, then indicate an error,
392          */
393         if (FifoCount < WordCount) {
394                 return XST_PFIFO_NO_ROOM;
395         }
396
397         /* readjust the word count to not take into account the extra bytes */
398
399         if (ExtraByteCount > 0) {
400                 WordCount--;
401         }
402
403         /* Write all the bytes of the buffer which can be written as 32 bit
404          * words into the FIFO, waiting to handle the extra bytes seperately
405          */
406         for (FifoCount = 0; FifoCount < WordCount; FifoCount++) {
407                 XIo_Out32(InstancePtr->DataBaseAddress, WordBuffer[FifoCount]);
408         }
409
410         /* if there are extra bytes to handle, extract them from the buffer
411          * and create a 32 bit word and write it to the FIFO
412          */
413         if (ExtraByteCount > 0) {
414                 u32 LastWord = 0;
415                 u8 *ExtraBytesBuffer = (u8 *) (WordBuffer + WordCount);
416
417                 /* one extra byte in the buffer, put the byte into the last word
418                  * to be inserted into the FIFO, perform this processing inline rather
419                  * than in a loop to help performance
420                  */
421                 if (ExtraByteCount == 1) {
422                         LastWord = ExtraBytesBuffer[0] << 24;
423                 }
424
425                 /* two extra bytes in the buffer, put each byte into the last word
426                  * to be inserted into the FIFO
427                  */
428                 else if (ExtraByteCount == 2) {
429                         LastWord = ExtraBytesBuffer[0] << 24 |
430                             ExtraBytesBuffer[1] << 16;
431                 }
432
433                 /* three extra bytes in the buffer, put each byte into the last word
434                  * to be inserted into the FIFO
435                  */
436                 else if (ExtraByteCount == 3) {
437                         LastWord = ExtraBytesBuffer[0] << 24 |
438                             ExtraBytesBuffer[1] << 16 |
439                             ExtraBytesBuffer[2] << 8;
440                 }
441
442                 /* write the last 32 bit word to the FIFO and return with no errors */
443
444                 XIo_Out32(InstancePtr->DataBaseAddress, LastWord);
445         }
446
447         return XST_SUCCESS;
448 }