<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Generator" CONTENT="MS Exchange Server version 6.5.7652.24">
<TITLE>RE: [PATCH] [POWERPC] Xilinx: hwicap driver</TITLE>
</HEAD>
<BODY>
<!-- Converted from text/plain format -->
<BR>
<P><FONT SIZE=2>Nevermind... I posted this too fast and screwed up the spinlocks.<BR>
<BR>
-----Original Message-----<BR>
From: Stephen Neuendorffer [<A HREF="mailto:stephen.neuendorffer@xilinx.com">mailto:stephen.neuendorffer@xilinx.com</A>]<BR>
Sent: Thu 1/31/2008 5:02 PM<BR>
To: linuxppc-dev@ozlabs.org; grant.likely@secretlab.ca; jacmet@sunsite.dk<BR>
Cc: Stephen Neuendorffer<BR>
Subject: [PATCH] [POWERPC] Xilinx: hwicap driver<BR>
<BR>
This includes code for new fifo-based xps_hwicap in addition to the<BR>
older opb_hwicap, which has a significantly different interface.  The<BR>
common code between the two drivers is largely shared.<BR>
<BR>
Significant differences exists between this driver and what is<BR>
supported in the EDK drivers.  In particular, most of the<BR>
architecture-specific code for reconfiguring individual FPGA resources<BR>
has been removed.  This functionality is likely better provided in a<BR>
user-space support library.  In addition, read and write access is<BR>
supported.  In addition, although the xps_hwicap cores support<BR>
interrupt-driver mode, this driver only supports polled operation, in<BR>
order to make the code simpler, and since the interrupt processing<BR>
overhead is likely to slow down the throughput under Linux.<BR>
<BR>
Signed-off-by: Stephen Neuendorffer <stephen.neuendorffer@xilinx.com><BR>
<BR>
Fixed to add spinlocks, and a few style issues.<BR>
---<BR>
 drivers/char/Kconfig                       |    7 +<BR>
 drivers/char/Makefile                      |    1 +<BR>
 drivers/char/xilinx_hwicap/Makefile        |    7 +<BR>
 drivers/char/xilinx_hwicap/buffer_icap.c   |  380 ++++++++++++<BR>
 drivers/char/xilinx_hwicap/buffer_icap.h   |   57 ++<BR>
 drivers/char/xilinx_hwicap/fifo_icap.c     |  381 ++++++++++++<BR>
 drivers/char/xilinx_hwicap/fifo_icap.h     |   62 ++<BR>
 drivers/char/xilinx_hwicap/xilinx_hwicap.c |  912 ++++++++++++++++++++++++++++<BR>
 drivers/char/xilinx_hwicap/xilinx_hwicap.h |  193 ++++++<BR>
 9 files changed, 2000 insertions(+), 0 deletions(-)<BR>
 create mode 100644 drivers/char/xilinx_hwicap/Makefile<BR>
 create mode 100644 drivers/char/xilinx_hwicap/buffer_icap.c<BR>
 create mode 100644 drivers/char/xilinx_hwicap/buffer_icap.h<BR>
 create mode 100644 drivers/char/xilinx_hwicap/fifo_icap.c<BR>
 create mode 100644 drivers/char/xilinx_hwicap/fifo_icap.h<BR>
 create mode 100644 drivers/char/xilinx_hwicap/xilinx_hwicap.c<BR>
 create mode 100644 drivers/char/xilinx_hwicap/xilinx_hwicap.h<BR>
<BR>
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig<BR>
index ef1ed5d..157ae2a 100644<BR>
--- a/drivers/char/Kconfig<BR>
+++ b/drivers/char/Kconfig<BR>
@@ -831,6 +831,13 @@ config DTLK<BR>
          To compile this driver as a module, choose M here: the<BR>
          module will be called dtlk.<BR>
<BR>
+config XILINX_HWICAP<BR>
+       tristate "Xilinx HWICAP Support"<BR>
+       depends on XILINX_VIRTEX<BR>
+       help<BR>
+         This option enables support for Xilinx Internal Configuration<BR>
+         Access Port (ICAP) driver.<BR>
+<BR>
 config R3964<BR>
        tristate "Siemens R3964 line discipline"<BR>
        ---help---<BR>
diff --git a/drivers/char/Makefile b/drivers/char/Makefile<BR>
index 07304d5..3a278a0 100644<BR>
--- a/drivers/char/Makefile<BR>
+++ b/drivers/char/Makefile<BR>
@@ -76,6 +76,7 @@ obj-$(CONFIG_EFI_RTC)         += efirtc.o<BR>
 obj-$(CONFIG_SGI_DS1286)       += ds1286.o<BR>
 obj-$(CONFIG_SGI_IP27_RTC)     += ip27-rtc.o<BR>
 obj-$(CONFIG_DS1302)           += ds1302.o<BR>
+obj-$(CONFIG_XILINX_HWICAP)    += xilinx_hwicap/<BR>
 ifeq ($(CONFIG_GENERIC_NVRAM),y)<BR>
   obj-$(CONFIG_NVRAM)  += generic_nvram.o<BR>
 else<BR>
diff --git a/drivers/char/xilinx_hwicap/Makefile b/drivers/char/xilinx_hwicap/Makefile<BR>
new file mode 100644<BR>
index 0000000..5491cbc<BR>
--- /dev/null<BR>
+++ b/drivers/char/xilinx_hwicap/Makefile<BR>
@@ -0,0 +1,7 @@<BR>
+#<BR>
+# Makefile for the Xilinx OPB hwicap driver<BR>
+#<BR>
+<BR>
+obj-$(CONFIG_XILINX_HWICAP) += xilinx_hwicap_m.o<BR>
+<BR>
+xilinx_hwicap_m-y := xilinx_hwicap.o fifo_icap.o buffer_icap.o<BR>
diff --git a/drivers/char/xilinx_hwicap/buffer_icap.c b/drivers/char/xilinx_hwicap/buffer_icap.c<BR>
new file mode 100644<BR>
index 0000000..dfea2bd<BR>
--- /dev/null<BR>
+++ b/drivers/char/xilinx_hwicap/buffer_icap.c<BR>
@@ -0,0 +1,380 @@<BR>
+/*****************************************************************************<BR>
+ *<BR>
+ *     Author: Xilinx, Inc.<BR>
+ *<BR>
+ *     This program is free software; you can redistribute it and/or modify it<BR>
+ *     under the terms of the GNU General Public License as published by the<BR>
+ *     Free Software Foundation; either version 2 of the License, or (at your<BR>
+ *     option) any later version.<BR>
+ *<BR>
+ *     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"<BR>
+ *     AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND<BR>
+ *     SOLUTIONS FOR XILINX DEVICES.  BY PROVIDING THIS DESIGN, CODE,<BR>
+ *     OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,<BR>
+ *     APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION<BR>
+ *     THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,<BR>
+ *     AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE<BR>
+ *     FOR YOUR IMPLEMENTATION.  XILINX EXPRESSLY DISCLAIMS ANY<BR>
+ *     WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE<BR>
+ *     IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR<BR>
+ *     REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF<BR>
+ *     INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS<BR>
+ *     FOR A PARTICULAR PURPOSE.<BR>
+ *<BR>
+ *     Xilinx products are not intended for use in life support appliances,<BR>
+ *     devices, or systems. Use in such applications is expressly prohibited.<BR>
+ *<BR>
+ *     (c) Copyright 2003-2008 Xilinx Inc.<BR>
+ *     All rights reserved.<BR>
+ *<BR>
+ *     You should have received a copy of the GNU General Public License along<BR>
+ *     with this program; if not, write to the Free Software Foundation, Inc.,<BR>
+ *     675 Mass Ave, Cambridge, MA 02139, USA.<BR>
+ *<BR>
+ *****************************************************************************/<BR>
+<BR>
+#include "buffer_icap.h"<BR>
+<BR>
+/* Indicates how many bytes will fit in a buffer. (1 BRAM) */<BR>
+#define XHI_MAX_BUFFER_BYTES        2048<BR>
+#define XHI_MAX_BUFFER_INTS         (XHI_MAX_BUFFER_BYTES >> 2)<BR>
+<BR>
+/* File access and error constants */<BR>
+#define XHI_DEVICE_READ_ERROR       -1<BR>
+#define XHI_DEVICE_WRITE_ERROR      -2<BR>
+#define XHI_BUFFER_OVERFLOW_ERROR   -3<BR>
+<BR>
+#define XHI_DEVICE_READ             0x1<BR>
+#define XHI_DEVICE_WRITE            0x0<BR>
+<BR>
+/* Constants for checking transfer status */<BR>
+#define XHI_CYCLE_DONE              0<BR>
+#define XHI_CYCLE_EXECUTING         1<BR>
+<BR>
+/* buffer_icap register offsets */<BR>
+<BR>
+/* Size of transfer, read & write */<BR>
+#define XHI_SIZE_REG_OFFSET        0x800L<BR>
+/* offset into bram, read & write */<BR>
+#define XHI_BRAM_OFFSET_REG_OFFSET 0x804L<BR>
+/* Read not Configure, direction of transfer.  Write only */<BR>
+#define XHI_RNC_REG_OFFSET         0x808L<BR>
+/* Indicates transfer complete. Read only */<BR>
+#define XHI_STATUS_REG_OFFSET      0x80CL<BR>
+<BR>
+/* Constants for setting the RNC register */<BR>
+#define XHI_CONFIGURE              0x0UL<BR>
+#define XHI_READBACK               0x1UL<BR>
+<BR>
+/* Constants for the Done register */<BR>
+#define XHI_NOT_FINISHED           0x0UL<BR>
+#define XHI_FINISHED               0x1UL<BR>
+<BR>
+#define XHI_BUFFER_START 0<BR>
+<BR>
+/**<BR>
+ * buffer_icap_get_status: Get the contents of the status register.<BR>
+ * @parameter base_address: is the base address of the device<BR>
+ *<BR>
+ * The status register contains the ICAP status and the done bit.<BR>
+ *<BR>
+ * D8 - cfgerr<BR>
+ * D7 - dalign<BR>
+ * D6 - rip<BR>
+ * D5 - in_abort_l<BR>
+ * D4 - Always 1<BR>
+ * D3 - Always 1<BR>
+ * D2 - Always 1<BR>
+ * D1 - Always 1<BR>
+ * D0 - Done bit<BR>
+ **/<BR>
+static inline u32 buffer_icap_get_status(void __iomem *base_address)<BR>
+{<BR>
+       return in_be32(base_address + XHI_STATUS_REG_OFFSET);<BR>
+}<BR>
+<BR>
+/**<BR>
+ * buffer_icap_get_bram: Reads data from the storage buffer bram.<BR>
+ * @parameter base_address: contains the base address of the component.<BR>
+ * @parameter offset: The word offset from which the data should be read.<BR>
+ *<BR>
+ * A bram is used as a configuration memory cache.  One frame of data can<BR>
+ * be stored in this "storage buffer".<BR>
+ **/<BR>
+static inline u32 buffer_icap_get_bram(void __iomem *base_address,<BR>
+               u32 offset)<BR>
+{<BR>
+       return in_be32(base_address + (offset << 2));<BR>
+}<BR>
+<BR>
+/**<BR>
+ * buffer_icap_busy: Return true if the icap device is busy<BR>
+ * @parameter base_address: is the base address of the device<BR>
+ *<BR>
+ * The queries the low order bit of the status register, which<BR>
+ * indicates whether the current configuration or readback operation<BR>
+ * has completed.<BR>
+ **/<BR>
+static inline bool buffer_icap_busy(void __iomem *base_address)<BR>
+{<BR>
+       return (buffer_icap_get_status(base_address) & 1) == XHI_NOT_FINISHED;<BR>
+}<BR>
+<BR>
+/**<BR>
+ * buffer_icap_busy: Return true if the icap device is not busy<BR>
+ * @parameter base_address: is the base address of the device<BR>
+ *<BR>
+ * The queries the low order bit of the status register, which<BR>
+ * indicates whether the current configuration or readback operation<BR>
+ * has completed.<BR>
+ **/<BR>
+static inline bool buffer_icap_done(void __iomem *base_address)<BR>
+{<BR>
+       return (buffer_icap_get_status(base_address) & 1) == XHI_FINISHED;<BR>
+}<BR>
+<BR>
+/**<BR>
+ * buffer_icap_set_size: Set the size register.<BR>
+ * @parameter base_address: is the base address of the device<BR>
+ * @parameter data: The size in bytes.<BR>
+ *<BR>
+ * The size register holds the number of 8 bit bytes to transfer between<BR>
+ * bram and the icap (or icap to bram).<BR>
+ **/<BR>
+static inline void buffer_icap_set_size(void __iomem *base_address,<BR>
+               u32 data)<BR>
+{<BR>
+       out_be32(base_address + XHI_SIZE_REG_OFFSET, data);<BR>
+}<BR>
+<BR>
+/**<BR>
+ * buffer_icap_mSetoffsetReg: Set the bram offset register.<BR>
+ * @parameter base_address: contains the base address of the device.<BR>
+ * @parameter data: is the value to be written to the data register.<BR>
+ *<BR>
+ * The bram offset register holds the starting bram address to transfer<BR>
+ * data from during configuration or write data to during readback.<BR>
+ **/<BR>
+static inline void buffer_icap_set_offset(void __iomem *base_address,<BR>
+               u32 data)<BR>
+{<BR>
+       out_be32(base_address + XHI_BRAM_OFFSET_REG_OFFSET, data);<BR>
+}<BR>
+<BR>
+/**<BR>
+ * buffer_icap_set_rnc: Set the RNC (Readback not Configure) register.<BR>
+ * @parameter base_address: contains the base address of the device.<BR>
+ * @parameter data: is the value to be written to the data register.<BR>
+ *<BR>
+ * The RNC register determines the direction of the data transfer.  It<BR>
+ * controls whether a configuration or readback take place.  Writing to<BR>
+ * this register initiates the transfer.  A value of 1 initiates a<BR>
+ * readback while writing a value of 0 initiates a configuration.<BR>
+ **/<BR>
+static inline void buffer_icap_set_rnc(void __iomem *base_address,<BR>
+               u32 data)<BR>
+{<BR>
+       out_be32(base_address + XHI_RNC_REG_OFFSET, data);<BR>
+}<BR>
+<BR>
+/**<BR>
+ * buffer_icap_set_bram: Write data to the storage buffer bram.<BR>
+ * @parameter base_address: contains the base address of the component.<BR>
+ * @parameter offset: The word offset at which the data should be written.<BR>
+ * @parameter data: The value to be written to the bram offset.<BR>
+ *<BR>
+ * A bram is used as a configuration memory cache.  One frame of data can<BR>
+ * be stored in this "storage buffer".<BR>
+ **/<BR>
+static inline void buffer_icap_set_bram(void __iomem *base_address,<BR>
+               u32 offset, u32 data)<BR>
+{<BR>
+       out_be32(base_address + (offset << 2), data);<BR>
+}<BR>
+<BR>
+/**<BR>
+ * buffer_icap_device_read: Transfer bytes from ICAP to the storage buffer.<BR>
+ * @parameter drvdata: a pointer to the drvdata.<BR>
+ * @parameter offset: The storage buffer start address.<BR>
+ * @parameter count: The number of words (32 bit) to read from the<BR>
+ *           device (ICAP).<BR>
+ **/<BR>
+static int buffer_icap_device_read(struct hwicap_drvdata *drvdata,<BR>
+               u32 offset, u32 count)<BR>
+{<BR>
+<BR>
+       s32 retries = 0;<BR>
+       void __iomem *base_address = drvdata->base_address;<BR>
+<BR>
+       if (buffer_icap_busy(base_address))<BR>
+               return -EBUSY;<BR>
+<BR>
+       if ((offset + count) > XHI_MAX_BUFFER_INTS)<BR>
+               return -EINVAL;<BR>
+<BR>
+       /* setSize count*4 to get bytes. */<BR>
+       buffer_icap_set_size(base_address, (count << 2));<BR>
+       buffer_icap_set_offset(base_address, offset);<BR>
+       buffer_icap_set_rnc(base_address, XHI_READBACK);<BR>
+<BR>
+       while (buffer_icap_busy(base_address)) {<BR>
+               retries++;<BR>
+               if (retries > XHI_MAX_RETRIES)<BR>
+                       return -EBUSY;<BR>
+       }<BR>
+       return 0;<BR>
+<BR>
+};<BR>
+<BR>
+/**<BR>
+ * buffer_icap_device_write: Transfer bytes from ICAP to the storage buffer.<BR>
+ * @parameter drvdata: a pointer to the drvdata.<BR>
+ * @parameter offset: The storage buffer start address.<BR>
+ * @parameter count: The number of words (32 bit) to read from the<BR>
+ *           device (ICAP).<BR>
+ **/<BR>
+static int buffer_icap_device_write(struct hwicap_drvdata *drvdata,<BR>
+               u32 offset, u32 count)<BR>
+{<BR>
+<BR>
+       s32 retries = 0;<BR>
+       void __iomem *base_address = drvdata->base_address;<BR>
+<BR>
+       if (buffer_icap_busy(base_address))<BR>
+               return -EBUSY;<BR>
+<BR>
+       if ((offset + count) > XHI_MAX_BUFFER_INTS)<BR>
+               return -EINVAL;<BR>
+<BR>
+       /* setSize count*4 to get bytes. */<BR>
+       buffer_icap_set_size(base_address, count << 2);<BR>
+       buffer_icap_set_offset(base_address, offset);<BR>
+       buffer_icap_set_rnc(base_address, XHI_CONFIGURE);<BR>
+<BR>
+       while (buffer_icap_busy(base_address)) {<BR>
+               retries++;<BR>
+               if (retries > XHI_MAX_RETRIES)<BR>
+                       return -EBUSY;<BR>
+       }<BR>
+       return 0;<BR>
+<BR>
+};<BR>
+<BR>
+/**<BR>
+ * buffer_icap_reset: Reset the logic of the icap device.<BR>
+ * @parameter drvdata: a pointer to the drvdata.<BR>
+ *<BR>
+ * Writing to the status register resets the ICAP logic in an internal<BR>
+ * version of the core.  For the version of the core published in EDK,<BR>
+ * this is a noop.<BR>
+ **/<BR>
+void buffer_icap_reset(struct hwicap_drvdata *drvdata)<BR>
+{<BR>
+    out_be32(drvdata->base_address + XHI_STATUS_REG_OFFSET, 0xFEFE);<BR>
+}<BR>
+<BR>
+/**<BR>
+ * buffer_icap_set_configuration: Load a partial bitstream from system memory.<BR>
+ * @parameter drvdata: a pointer to the drvdata.<BR>
+ * @parameter data: Kernel address of the partial bitstream.<BR>
+ * @parameter size: the size of the partial bitstream in 32 bit words.<BR>
+ **/<BR>
+int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data,<BR>
+                            u32 size)<BR>
+{<BR>
+       int status;<BR>
+       s32 buffer_count = 0;<BR>
+       s32 num_writes = 0;<BR>
+       bool dirty = 0;<BR>
+       u32 i;<BR>
+       void __iomem *base_address = drvdata->base_address;<BR>
+<BR>
+       /* Loop through all the data */<BR>
+       for (i = 0, buffer_count = 0; i < size; i++) {<BR>
+<BR>
+               /* Copy data to bram */<BR>
+               buffer_icap_set_bram(base_address, buffer_count, data[i]);<BR>
+               dirty = 1;<BR>
+<BR>
+               if (buffer_count < XHI_MAX_BUFFER_INTS - 1) {<BR>
+                       buffer_count++;<BR>
+                       continue;<BR>
+               }<BR>
+<BR>
+               /* Write data to ICAP */<BR>
+               status = buffer_icap_device_write(<BR>
+                               drvdata,<BR>
+                               XHI_BUFFER_START,<BR>
+                               XHI_MAX_BUFFER_INTS);<BR>
+               if (status != 0) {<BR>
+                       /* abort. */<BR>
+                       buffer_icap_reset(drvdata);<BR>
+                       return status;<BR>
+               }<BR>
+<BR>
+               buffer_count = 0;<BR>
+               num_writes++;<BR>
+               dirty = 0;<BR>
+       }<BR>
+<BR>
+       /* Write unwritten data to ICAP */<BR>
+       if (dirty) {<BR>
+               /* Write data to ICAP */<BR>
+               status = buffer_icap_device_write(drvdata, XHI_BUFFER_START,<BR>
+                                            buffer_count);<BR>
+               if (status != 0) {<BR>
+                       /* abort. */<BR>
+                       buffer_icap_reset(drvdata);<BR>
+               }<BR>
+               return status;<BR>
+       }<BR>
+<BR>
+       return 0;<BR>
+};<BR>
+<BR>
+/**<BR>
+ * buffer_icap_get_configuration: Read configuration data from the device.<BR>
+ * @parameter drvdata: a pointer to the drvdata.<BR>
+ * @parameter data: Address of the data representing the partial bitstream<BR>
+ * @parameter size: the size of the partial bitstream in 32 bit words.<BR>
+ **/<BR>
+int buffer_icap_get_configuration(struct hwicap_drvdata *drvdata, u32 *data,<BR>
+                            u32 size)<BR>
+{<BR>
+       int status;<BR>
+       s32 buffer_count = 0;<BR>
+       s32 read_count = 0;<BR>
+       u32 i;<BR>
+       void __iomem *base_address = drvdata->base_address;<BR>
+<BR>
+       /* Loop through all the data */<BR>
+       for (i = 0, buffer_count = XHI_MAX_BUFFER_INTS; i < size; i++) {<BR>
+               if (buffer_count == XHI_MAX_BUFFER_INTS) {<BR>
+                       u32 words_remaining = size - i;<BR>
+                       u32 words_to_read =<BR>
+                               words_remaining <<BR>
+                               XHI_MAX_BUFFER_INTS ? words_remaining :<BR>
+                               XHI_MAX_BUFFER_INTS;<BR>
+<BR>
+                       /* Read data from ICAP */<BR>
+                       status = buffer_icap_device_read(<BR>
+                                       drvdata,<BR>
+                                       XHI_BUFFER_START,<BR>
+                                       words_to_read);<BR>
+                       if (status != 0) {<BR>
+                               /* abort. */<BR>
+                               buffer_icap_reset(drvdata);<BR>
+                               return status;<BR>
+                       }<BR>
+<BR>
+                       buffer_count = 0;<BR>
+                       read_count++;<BR>
+               }<BR>
+<BR>
+               /* Copy data from bram */<BR>
+               data[i] = buffer_icap_get_bram(base_address, buffer_count);<BR>
+               buffer_count++;<BR>
+       }<BR>
+<BR>
+       return 0;<BR>
+};<BR>
diff --git a/drivers/char/xilinx_hwicap/buffer_icap.h b/drivers/char/xilinx_hwicap/buffer_icap.h<BR>
new file mode 100644<BR>
index 0000000..0318495<BR>
--- /dev/null<BR>
+++ b/drivers/char/xilinx_hwicap/buffer_icap.h<BR>
@@ -0,0 +1,57 @@<BR>
+/*****************************************************************************<BR>
+ *<BR>
+ *     Author: Xilinx, Inc.<BR>
+ *<BR>
+ *     This program is free software; you can redistribute it and/or modify it<BR>
+ *     under the terms of the GNU General Public License as published by the<BR>
+ *     Free Software Foundation; either version 2 of the License, or (at your<BR>
+ *     option) any later version.<BR>
+ *<BR>
+ *     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"<BR>
+ *     AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND<BR>
+ *     SOLUTIONS FOR XILINX DEVICES.  BY PROVIDING THIS DESIGN, CODE,<BR>
+ *     OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,<BR>
+ *     APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION<BR>
+ *     THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,<BR>
+ *     AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE<BR>
+ *     FOR YOUR IMPLEMENTATION.  XILINX EXPRESSLY DISCLAIMS ANY<BR>
+ *     WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE<BR>
+ *     IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR<BR>
+ *     REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF<BR>
+ *     INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS<BR>
+ *     FOR A PARTICULAR PURPOSE.<BR>
+ *<BR>
+ *     Xilinx products are not intended for use in life support appliances,<BR>
+ *     devices, or systems. Use in such applications is expressly prohibited.<BR>
+ *<BR>
+ *     (c) Copyright 2003-2008 Xilinx Inc.<BR>
+ *     All rights reserved.<BR>
+ *<BR>
+ *     You should have received a copy of the GNU General Public License along<BR>
+ *     with this program; if not, write to the Free Software Foundation, Inc.,<BR>
+ *     675 Mass Ave, Cambridge, MA 02139, USA.<BR>
+ *<BR>
+ *****************************************************************************/<BR>
+<BR>
+#ifndef XILINX_BUFFER_ICAP_H_  /* prevent circular inclusions */<BR>
+#define XILINX_BUFFER_ICAP_H_  /* by using protection macros */<BR>
+<BR>
+#include <linux/types.h><BR>
+#include <linux/cdev.h><BR>
+#include <linux/version.h><BR>
+#include <linux/platform_device.h><BR>
+<BR>
+#include <asm/io.h><BR>
+#include "xilinx_hwicap.h"<BR>
+<BR>
+void buffer_icap_reset(struct hwicap_drvdata *drvdata);<BR>
+<BR>
+/* Loads a partial bitstream from system memory. */<BR>
+int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data,<BR>
+                            u32 Size);<BR>
+<BR>
+/* Loads a partial bitstream from system memory. */<BR>
+int buffer_icap_get_configuration(struct hwicap_drvdata *drvdata, u32 *data,<BR>
+                            u32 Size);<BR>
+<BR>
+#endif<BR>
diff --git a/drivers/char/xilinx_hwicap/fifo_icap.c b/drivers/char/xilinx_hwicap/fifo_icap.c<BR>
new file mode 100644<BR>
index 0000000..0988314<BR>
--- /dev/null<BR>
+++ b/drivers/char/xilinx_hwicap/fifo_icap.c<BR>
@@ -0,0 +1,381 @@<BR>
+/*****************************************************************************<BR>
+ *<BR>
+ *     Author: Xilinx, Inc.<BR>
+ *<BR>
+ *     This program is free software; you can redistribute it and/or modify it<BR>
+ *     under the terms of the GNU General Public License as published by the<BR>
+ *     Free Software Foundation; either version 2 of the License, or (at your<BR>
+ *     option) any later version.<BR>
+ *<BR>
+ *     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"<BR>
+ *     AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND<BR>
+ *     SOLUTIONS FOR XILINX DEVICES.  BY PROVIDING THIS DESIGN, CODE,<BR>
+ *     OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,<BR>
+ *     APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION<BR>
+ *     THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,<BR>
+ *     AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE<BR>
+ *     FOR YOUR IMPLEMENTATION.  XILINX EXPRESSLY DISCLAIMS ANY<BR>
+ *     WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE<BR>
+ *     IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR<BR>
+ *     REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF<BR>
+ *     INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS<BR>
+ *     FOR A PARTICULAR PURPOSE.<BR>
+ *<BR>
+ *     Xilinx products are not intended for use in life support appliances,<BR>
+ *     devices, or systems. Use in such applications is expressly prohibited.<BR>
+ *<BR>
+ *     (c) Copyright 2007-2008 Xilinx Inc.<BR>
+ *     All rights reserved.<BR>
+ *<BR>
+ *     You should have received a copy of the GNU General Public License along<BR>
+ *     with this program; if not, write to the Free Software Foundation, Inc.,<BR>
+ *     675 Mass Ave, Cambridge, MA 02139, USA.<BR>
+ *<BR>
+ *****************************************************************************/<BR>
+<BR>
+#include "fifo_icap.h"<BR>
+<BR>
+/* Register offsets for the XHwIcap device. */<BR>
+#define XHI_GIER_OFFSET        0x1C  /* Device Global Interrupt Enable Reg */<BR>
+#define XHI_IPISR_OFFSET 0x20  /* Interrupt Status Register */<BR>
+#define XHI_IPIER_OFFSET 0x28  /* Interrupt Enable Register */<BR>
+#define XHI_WF_OFFSET 0x100 /* Write FIFO */<BR>
+#define XHI_RF_OFFSET 0x104 /* Read FIFO */<BR>
+#define XHI_SZ_OFFSET 0x108 /* Size Register */<BR>
+#define XHI_CR_OFFSET 0x10C /* Control Register */<BR>
+#define XHI_SR_OFFSET 0x110 /* Status Register */<BR>
+#define XHI_WFV_OFFSET 0x114 /* Write FIFO Vacancy Register */<BR>
+#define XHI_RFO_OFFSET 0x118 /* Read FIFO Occupancy Register */<BR>
+<BR>
+/* Device Global Interrupt Enable Register (GIER) bit definitions */<BR>
+<BR>
+#define XHI_GIER_GIE_MASK 0x80000000 /* Global Interrupt enable Mask */<BR>
+<BR>
+/**<BR>
+ * HwIcap Device Interrupt Status/Enable Registers<BR>
+ *<BR>
+ * Interrupt Status Register (IPISR) : This register holds the<BR>
+ * interrupt status flags for the device. These bits are toggle on<BR>
+ * write.<BR>
+ *<BR>
+ * Interrupt Enable Register (IPIER) : This register is used to enable<BR>
+ * interrupt sources for the device.<BR>
+ * Writing a '1' to a bit enables the corresponding interrupt.<BR>
+ * Writing a '0' to a bit disables the corresponding interrupt.<BR>
+ *<BR>
+ * IPISR/IPIER registers have the same bit definitions and are only defined<BR>
+ * once.<BR>
+ */<BR>
+#define XHI_IPIXR_RFULL_MASK 0x00000008 /* Read FIFO Full */<BR>
+#define XHI_IPIXR_WEMPTY_MASK 0x00000004 /* Write FIFO Empty */<BR>
+#define XHI_IPIXR_RDP_MASK 0x00000002 /* Read FIFO half full */<BR>
+#define XHI_IPIXR_WRP_MASK 0x00000001 /* Write FIFO half full */<BR>
+#define XHI_IPIXR_ALL_MASK 0x0000000F /* Mask of all interrupts */<BR>
+<BR>
+/* Control Register (CR) */<BR>
+#define XHI_CR_SW_RESET_MASK 0x00000008 /* SW Reset Mask */<BR>
+#define XHI_CR_FIFO_CLR_MASK 0x00000004 /* FIFO Clear Mask */<BR>
+#define XHI_CR_READ_MASK 0x00000002 /* Read from ICAP to FIFO */<BR>
+#define XHI_CR_WRITE_MASK 0x00000001 /* Write from FIFO to ICAP */<BR>
+<BR>
+/* Status Register (SR) */<BR>
+#define XHI_SR_CFGERR_N_MASK 0x00000100 /* Config Error Mask */<BR>
+#define XHI_SR_DALIGN_MASK 0x00000080 /* Data Alignment Mask */<BR>
+#define XHI_SR_RIP_MASK 0x00000040 /* Read back Mask */<BR>
+#define XHI_SR_IN_ABORT_N_MASK 0x00000020 /* Select Map Abort Mask */<BR>
+#define XHI_SR_DONE_MASK 0x00000001 /* Done bit Mask  */<BR>
+<BR>
+<BR>
+#define XHI_WFO_MAX_VACANCY 1024 /* Max Write FIFO Vacancy, in words */<BR>
+#define XHI_RFO_MAX_OCCUPANCY 256 /* Max Read FIFO Occupancy, in words */<BR>
+/* The maximum amount we can request from fifo_icap_get_configuration<BR>
+   at once, in bytes. */<BR>
+#define XHI_MAX_READ_TRANSACTION_WORDS 0xFFF<BR>
+<BR>
+<BR>
+/**<BR>
+ * fifo_icap_fifo_write: Write data to the write FIFO.<BR>
+ * @parameter drvdata: a pointer to the drvdata.<BR>
+ * @parameter data: the 32-bit value to be written to the FIFO.<BR>
+ *<BR>
+ * This function will silently fail if the fifo is full.<BR>
+ **/<BR>
+static inline void fifo_icap_fifo_write(struct hwicap_drvdata *drvdata,<BR>
+               u32 data)<BR>
+{<BR>
+       dev_dbg(drvdata->dev, "fifo_write: %x\n", data);<BR>
+       out_be32(drvdata->base_address + XHI_WF_OFFSET, data);<BR>
+}<BR>
+<BR>
+/**<BR>
+ * fifo_icap_fifo_read: Read data from the Read FIFO.<BR>
+ * @parameter drvdata: a pointer to the drvdata.<BR>
+ *<BR>
+ * This function will silently fail if the fifo is empty.<BR>
+ **/<BR>
+static inline u32 fifo_icap_fifo_read(struct hwicap_drvdata *drvdata)<BR>
+{<BR>
+       u32 data = in_be32(drvdata->base_address + XHI_RF_OFFSET);<BR>
+       dev_dbg(drvdata->dev, "fifo_read: %x\n", data);<BR>
+       return data;<BR>
+}<BR>
+<BR>
+/**<BR>
+ * fifo_icap_set_read_size: Set the the size register.<BR>
+ * @parameter drvdata: a pointer to the drvdata.<BR>
+ * @parameter data: the size of the following read transaction, in words.<BR>
+ **/<BR>
+static inline void fifo_icap_set_read_size(struct hwicap_drvdata *drvdata,<BR>
+               u32 data)<BR>
+{<BR>
+       out_be32(drvdata->base_address + XHI_SZ_OFFSET, data);<BR>
+}<BR>
+<BR>
+/**<BR>
+ * fifo_icap_start_config: Initiate a configuration (write) to the device.<BR>
+ * @parameter drvdata: a pointer to the drvdata.<BR>
+ **/<BR>
+static inline void fifo_icap_start_config(struct hwicap_drvdata *drvdata)<BR>
+{<BR>
+       out_be32(drvdata->base_address + XHI_CR_OFFSET, XHI_CR_WRITE_MASK);<BR>
+       dev_dbg(drvdata->dev, "configuration started\n");<BR>
+}<BR>
+<BR>
+/**<BR>
+ * fifo_icap_start_readback: Initiate a readback from the device.<BR>
+ * @parameter drvdata: a pointer to the drvdata.<BR>
+ **/<BR>
+static inline void fifo_icap_start_readback(struct hwicap_drvdata *drvdata)<BR>
+{<BR>
+       out_be32(drvdata->base_address + XHI_CR_OFFSET, XHI_CR_READ_MASK);<BR>
+       dev_dbg(drvdata->dev, "readback started\n");<BR>
+}<BR>
+<BR>
+/**<BR>
+ * fifo_icap_busy: Return true if the ICAP is still processing a transaction.<BR>
+ * @parameter drvdata: a pointer to the drvdata.<BR>
+ **/<BR>
+static inline u32 fifo_icap_busy(struct hwicap_drvdata *drvdata)<BR>
+{<BR>
+       u32 status = in_be32(drvdata->base_address + XHI_SR_OFFSET);<BR>
+       dev_dbg(drvdata->dev, "Getting status = %x\n", status);<BR>
+       return (status & XHI_SR_DONE_MASK) ? 0 : 1;<BR>
+}<BR>
+<BR>
+/**<BR>
+ * fifo_icap_write_fifo_vacancy: Query the write fifo available space.<BR>
+ * @parameter drvdata: a pointer to the drvdata.<BR>
+ *<BR>
+ * Return the number of words that can be safely pushed into the write fifo.<BR>
+ **/<BR>
+static inline u32 fifo_icap_write_fifo_vacancy(<BR>
+               struct hwicap_drvdata *drvdata)<BR>
+{<BR>
+       return in_be32(drvdata->base_address + XHI_WFV_OFFSET);<BR>
+}<BR>
+<BR>
+/**<BR>
+ * fifo_icap_read_fifo_occupancy: Query the read fifo available data.<BR>
+ * @parameter drvdata: a pointer to the drvdata.<BR>
+ *<BR>
+ * Return the number of words that can be safely read from the read fifo.<BR>
+ **/<BR>
+static inline u32 fifo_icap_read_fifo_occupancy(<BR>
+               struct hwicap_drvdata *drvdata)<BR>
+{<BR>
+       return in_be32(drvdata->base_address + XHI_RFO_OFFSET);<BR>
+}<BR>
+<BR>
+/**<BR>
+ * fifo_icap_set_configuration: Send configuration data to the ICAP.<BR>
+ * @parameter drvdata: a pointer to the drvdata.<BR>
+ * @parameter frame_buffer: a pointer to the data to be written to the<BR>
+ *             ICAP device.<BR>
+ * @parameter num_words: the number of words (32 bit) to write to the ICAP<BR>
+ *             device.<BR>
+<BR>
+ * This function writes the given user data to the Write FIFO in<BR>
+ * polled mode and starts the transfer of the data to<BR>
+ * the ICAP device.<BR>
+ **/<BR>
+int fifo_icap_set_configuration(struct hwicap_drvdata *drvdata,<BR>
+               u32 *frame_buffer, u32 num_words)<BR>
+{<BR>
+<BR>
+       u32 write_fifo_vacancy = 0;<BR>
+       u32 retries = 0;<BR>
+       u32 remaining_words;<BR>
+<BR>
+       dev_dbg(drvdata->dev, "fifo_set_configuration\n");<BR>
+<BR>
+       /*<BR>
+        * Check if the ICAP device is Busy with the last Read/Write<BR>
+        */<BR>
+       if (fifo_icap_busy(drvdata))<BR>
+               return -EBUSY;<BR>
+<BR>
+       /*<BR>
+        * Set up the buffer pointer and the words to be transferred.<BR>
+        */<BR>
+       remaining_words = num_words;<BR>
+<BR>
+       while (remaining_words > 0) {<BR>
+               /*<BR>
+                * Wait until we have some data in the fifo.<BR>
+                */<BR>
+               while (write_fifo_vacancy == 0) {<BR>
+                       write_fifo_vacancy =<BR>
+                               fifo_icap_write_fifo_vacancy(drvdata);<BR>
+                       retries++;<BR>
+                       if (retries > XHI_MAX_RETRIES)<BR>
+                               return -EIO;<BR>
+               }<BR>
+<BR>
+               /*<BR>
+                * Write data into the Write FIFO.<BR>
+                */<BR>
+               while ((write_fifo_vacancy != 0) &&<BR>
+                               (remaining_words > 0)) {<BR>
+                       fifo_icap_fifo_write(drvdata, *frame_buffer);<BR>
+<BR>
+                       remaining_words--;<BR>
+                       write_fifo_vacancy--;<BR>
+                       frame_buffer++;<BR>
+               }<BR>
+               /* Start pushing whatever is in the FIFO into the ICAP. */<BR>
+               fifo_icap_start_config(drvdata);<BR>
+       }<BR>
+<BR>
+       /* Wait until the write has finished. */<BR>
+       while (fifo_icap_busy(drvdata)) {<BR>
+               retries++;<BR>
+               if (retries > XHI_MAX_RETRIES)<BR>
+                       break;<BR>
+       }<BR>
+<BR>
+       dev_dbg(drvdata->dev, "done fifo_set_configuration\n");<BR>
+<BR>
+       /*<BR>
+        * If the requested number of words have not been read from<BR>
+        * the device then indicate failure.<BR>
+        */<BR>
+       if (remaining_words != 0)<BR>
+               return -EIO;<BR>
+<BR>
+       return 0;<BR>
+}<BR>
+<BR>
+/**<BR>
+ * fifo_icap_get_configuration: Read configuration data from the device.<BR>
+ * @parameter drvdata: a pointer to the drvdata.<BR>
+ * @parameter data: Address of the data representing the partial bitstream<BR>
+ * @parameter size: the size of the partial bitstream in 32 bit words.<BR>
+ *<BR>
+ * This function reads the specified number of words from the ICAP device in<BR>
+ * the polled mode.<BR>
+ */<BR>
+int fifo_icap_get_configuration(struct hwicap_drvdata *drvdata,<BR>
+               u32 *frame_buffer, u32 num_words)<BR>
+{<BR>
+<BR>
+       u32 read_fifo_occupancy = 0;<BR>
+       u32 retries = 0;<BR>
+       u32 *data = frame_buffer;<BR>
+       u32 remaining_words;<BR>
+       u32 words_to_read;<BR>
+<BR>
+       dev_dbg(drvdata->dev, "fifo_get_configuration\n");<BR>
+<BR>
+       /*<BR>
+        * Check if the ICAP device is Busy with the last Write/Read<BR>
+        */<BR>
+       if (fifo_icap_busy(drvdata))<BR>
+               return -EBUSY;<BR>
+<BR>
+       remaining_words = num_words;<BR>
+<BR>
+       while (remaining_words > 0) {<BR>
+               words_to_read = remaining_words;<BR>
+               /* The hardware has a limit on the number of words<BR>
+                  that can be read at one time.  */<BR>
+               if (words_to_read > XHI_MAX_READ_TRANSACTION_WORDS)<BR>
+                       words_to_read = XHI_MAX_READ_TRANSACTION_WORDS;<BR>
+<BR>
+               remaining_words -= words_to_read;<BR>
+<BR>
+               fifo_icap_set_read_size(drvdata, words_to_read);<BR>
+               fifo_icap_start_readback(drvdata);<BR>
+<BR>
+               while (words_to_read > 0) {<BR>
+                       /* Wait until we have some data in the fifo. */<BR>
+                       while (read_fifo_occupancy == 0) {<BR>
+                               read_fifo_occupancy =<BR>
+                                       fifo_icap_read_fifo_occupancy(drvdata);<BR>
+                               retries++;<BR>
+                               if (retries > XHI_MAX_RETRIES)<BR>
+                                       return -EIO;<BR>
+                       }<BR>
+<BR>
+                       if (read_fifo_occupancy > words_to_read)<BR>
+                               read_fifo_occupancy = words_to_read;<BR>
+<BR>
+                       words_to_read -= read_fifo_occupancy;<BR>
+<BR>
+                       /* Read the data from the Read FIFO. */<BR>
+                       while (read_fifo_occupancy != 0) {<BR>
+                               *data++ = fifo_icap_fifo_read(drvdata);<BR>
+                               read_fifo_occupancy--;<BR>
+                       }<BR>
+               }<BR>
+       }<BR>
+<BR>
+       dev_dbg(drvdata->dev, "done fifo_get_configuration\n");<BR>
+<BR>
+       return 0;<BR>
+}<BR>
+<BR>
+/**<BR>
+ * buffer_icap_reset: Reset the logic of the icap device.<BR>
+ * @parameter drvdata: a pointer to the drvdata.<BR>
+ *<BR>
+ * This function forces the software reset of the complete HWICAP device.<BR>
+ * All the registers will return to the default value and the FIFO is also<BR>
+ * flushed as a part of this software reset.<BR>
+ */<BR>
+void fifo_icap_reset(struct hwicap_drvdata *drvdata)<BR>
+{<BR>
+       u32 reg_data;<BR>
+       /*<BR>
+        * Reset the device by setting/clearing the RESET bit in the<BR>
+        * Control Register.<BR>
+        */<BR>
+       reg_data = in_be32(drvdata->base_address + XHI_CR_OFFSET);<BR>
+<BR>
+       out_be32(drvdata->base_address + XHI_CR_OFFSET,<BR>
+                               reg_data | XHI_CR_SW_RESET_MASK);<BR>
+<BR>
+       out_be32(drvdata->base_address + XHI_CR_OFFSET,<BR>
+                               reg_data & (~XHI_CR_SW_RESET_MASK));<BR>
+<BR>
+}<BR>
+<BR>
+/**<BR>
+ * fifo_icap_flush_fifo: This function flushes the FIFOs in the device.<BR>
+ * @parameter drvdata: a pointer to the drvdata.<BR>
+ */<BR>
+void fifo_icap_flush_fifo(struct hwicap_drvdata *drvdata)<BR>
+{<BR>
+       u32 reg_data;<BR>
+       /*<BR>
+        * Flush the FIFO by setting/clearing the FIFO Clear bit in the<BR>
+        * Control Register.<BR>
+        */<BR>
+       reg_data = in_be32(drvdata->base_address + XHI_CR_OFFSET);<BR>
+<BR>
+       out_be32(drvdata->base_address + XHI_CR_OFFSET,<BR>
+                               reg_data | XHI_CR_FIFO_CLR_MASK);<BR>
+<BR>
+       out_be32(drvdata->base_address + XHI_CR_OFFSET,<BR>
+                               reg_data & (~XHI_CR_FIFO_CLR_MASK));<BR>
+}<BR>
+<BR>
diff --git a/drivers/char/xilinx_hwicap/fifo_icap.h b/drivers/char/xilinx_hwicap/fifo_icap.h<BR>
new file mode 100644<BR>
index 0000000..4d3068d<BR>
--- /dev/null<BR>
+++ b/drivers/char/xilinx_hwicap/fifo_icap.h<BR>
@@ -0,0 +1,62 @@<BR>
+/*****************************************************************************<BR>
+ *<BR>
+ *     Author: Xilinx, Inc.<BR>
+ *<BR>
+ *     This program is free software; you can redistribute it and/or modify it<BR>
+ *     under the terms of the GNU General Public License as published by the<BR>
+ *     Free Software Foundation; either version 2 of the License, or (at your<BR>
+ *     option) any later version.<BR>
+ *<BR>
+ *     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"<BR>
+ *     AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND<BR>
+ *     SOLUTIONS FOR XILINX DEVICES.  BY PROVIDING THIS DESIGN, CODE,<BR>
+ *     OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,<BR>
+ *     APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION<BR>
+ *     THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,<BR>
+ *     AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE<BR>
+ *     FOR YOUR IMPLEMENTATION.  XILINX EXPRESSLY DISCLAIMS ANY<BR>
+ *     WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE<BR>
+ *     IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR<BR>
+ *     REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF<BR>
+ *     INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS<BR>
+ *     FOR A PARTICULAR PURPOSE.<BR>
+ *<BR>
+ *     Xilinx products are not intended for use in life support appliances,<BR>
+ *     devices, or systems. Use in such applications is expressly prohibited.<BR>
+ *<BR>
+ *     (c) Copyright 2007-2008 Xilinx Inc.<BR>
+ *     All rights reserved.<BR>
+ *<BR>
+ *     You should have received a copy of the GNU General Public License along<BR>
+ *     with this program; if not, write to the Free Software Foundation, Inc.,<BR>
+ *     675 Mass Ave, Cambridge, MA 02139, USA.<BR>
+ *<BR>
+ *****************************************************************************/<BR>
+<BR>
+#ifndef XILINX_FIFO_ICAP_H_    /* prevent circular inclusions */<BR>
+#define XILINX_FIFO_ICAP_H_    /* by using protection macros */<BR>
+<BR>
+#include <linux/types.h><BR>
+#include <linux/cdev.h><BR>
+#include <linux/version.h><BR>
+#include <linux/platform_device.h><BR>
+<BR>
+#include <asm/io.h><BR>
+#include "xilinx_hwicap.h"<BR>
+<BR>
+/* Reads integers from the device into the storage buffer. */<BR>
+int fifo_icap_get_configuration(<BR>
+               struct hwicap_drvdata *drvdata,<BR>
+               u32 *FrameBuffer,<BR>
+               u32 NumWords);<BR>
+<BR>
+/* Writes integers to the device from the storage buffer. */<BR>
+int fifo_icap_set_configuration(<BR>
+               struct hwicap_drvdata *drvdata,<BR>
+               u32 *FrameBuffer,<BR>
+               u32 NumWords);<BR>
+<BR>
+void fifo_icap_reset(struct hwicap_drvdata *drvdata);<BR>
+void fifo_icap_flush_fifo(struct hwicap_drvdata *drvdata);<BR>
+<BR>
+#endif<BR>
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c<BR>
new file mode 100644<BR>
index 0000000..a55e6e1<BR>
--- /dev/null<BR>
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c<BR>
@@ -0,0 +1,912 @@<BR>
+/*****************************************************************************<BR>
+ *<BR>
+ *     Author: Xilinx, Inc.<BR>
+ *<BR>
+ *     This program is free software; you can redistribute it and/or modify it<BR>
+ *     under the terms of the GNU General Public License as published by the<BR>
+ *     Free Software Foundation; either version 2 of the License, or (at your<BR>
+ *     option) any later version.<BR>
+ *<BR>
+ *     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"<BR>
+ *     AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND<BR>
+ *     SOLUTIONS FOR XILINX DEVICES.  BY PROVIDING THIS DESIGN, CODE,<BR>
+ *     OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,<BR>
+ *     APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION<BR>
+ *     THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,<BR>
+ *     AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE<BR>
+ *     FOR YOUR IMPLEMENTATION.  XILINX EXPRESSLY DISCLAIMS ANY<BR>
+ *     WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE<BR>
+ *     IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR<BR>
+ *     REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF<BR>
+ *     INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS<BR>
+ *     FOR A PARTICULAR PURPOSE.<BR>
+ *<BR>
+ *     Xilinx products are not intended for use in life support appliances,<BR>
+ *     devices, or systems. Use in such applications is expressly prohibited.<BR>
+ *<BR>
+ *     (c) Copyright 2002 Xilinx Inc., Systems Engineering Group<BR>
+ *     (c) Copyright 2004 Xilinx Inc., Systems Engineering Group<BR>
+ *     (c) Copyright 2007-2008 Xilinx Inc.<BR>
+ *     All rights reserved.<BR>
+ *<BR>
+ *     You should have received a copy of the GNU General Public License along<BR>
+ *     with this program; if not, write to the Free Software Foundation, Inc.,<BR>
+ *     675 Mass Ave, Cambridge, MA 02139, USA.<BR>
+ *<BR>
+ *****************************************************************************/<BR>
+<BR>
+/*<BR>
+ * This is the code behind /dev/xilinx_icap -- it allows a user-space<BR>
+ * application to use the Xilinx ICAP subsystem.<BR>
+ *<BR>
+ * The following operations are possible:<BR>
+ *<BR>
+ * open                open the port and initialize for access.<BR>
+ * release     release port<BR>
+ * write        Write a bitstream to the configuration processor.<BR>
+ * read         Read a data stream from the configuration processor.<BR>
+ *<BR>
+ * After being opened, the port is initialized and accessed to avoid a<BR>
+ * corrupted first read which may occur with some hardware.  The port<BR>
+ * is left in a desynched state, requiring that a synch sequence be<BR>
+ * transmitted before any valid configuration data.  A user will have<BR>
+ * exclusive access to the device while it remains open, and the state<BR>
+ * of the ICAP cannot be guaranteed after the device is closed.  Note<BR>
+ * that a complete reset of the core and the state of the ICAP cannot<BR>
+ * be performed on many versions of the cores, hence users of this<BR>
+ * device should avoid making inconsistent accesses to the device.  In<BR>
+ * particular, accessing the read interface, without first generating<BR>
+ * a write containing a readback packet can leave the ICAP in an<BR>
+ * inaccessible state.<BR>
+ *<BR>
+ * Note that in order to use the read interface, it is first necessary<BR>
+ * to write a request packet to the write interface.  i.e., it is not<BR>
+ * possible to simply readback the bitstream (or any configuration<BR>
+ * bits) from a device without specifically requesting them first.<BR>
+ * The code to craft such packets is intended to be part of the<BR>
+ * user-space application code that uses this device.  The simplest<BR>
+ * way to use this interface is simply:<BR>
+ *<BR>
+ * cp foo.bit /dev/xilinx_icap<BR>
+ *<BR>
+ * Note that unless foo.bit is an appropriately constructed partial<BR>
+ * bitstream, this has a high likelyhood of overwriting the design<BR>
+ * currently programmed in the FPGA.<BR>
+ */<BR>
+<BR>
+#include <linux/version.h><BR>
+#include <linux/module.h><BR>
+#include <linux/kernel.h><BR>
+#include <linux/types.h><BR>
+#include <linux/ioport.h><BR>
+#include <linux/interrupt.h><BR>
+#include <linux/fcntl.h><BR>
+#include <linux/init.h><BR>
+#include <linux/poll.h><BR>
+#include <linux/proc_fs.h><BR>
+#include <linux/spinlock.h><BR>
+#include <linux/sysctl.h><BR>
+#include <linux/version.h><BR>
+#include <linux/fs.h><BR>
+#include <linux/cdev.h><BR>
+#include <linux/platform_device.h><BR>
+<BR>
+#include <asm/io.h><BR>
+#include <asm/uaccess.h><BR>
+#include <asm/system.h><BR>
+<BR>
+#ifdef CONFIG_OF<BR>
+/* For open firmware. */<BR>
+#include <linux/of_device.h><BR>
+#include <linux/of_platform.h><BR>
+#endif<BR>
+<BR>
+#include "xilinx_hwicap.h"<BR>
+#include "buffer_icap.h"<BR>
+#include "fifo_icap.h"<BR>
+<BR>
+#define DRIVER_NAME "xilinx_icap"<BR>
+<BR>
+#define HWICAP_REGS   (0x10000)<BR>
+<BR>
+/* dynamically allocate device number */<BR>
+static int xhwicap_major;<BR>
+static int xhwicap_minor;<BR>
+#define HWICAP_DEVICES 1<BR>
+<BR>
+module_param(xhwicap_major, int, S_IRUGO);<BR>
+module_param(xhwicap_minor, int, S_IRUGO);<BR>
+<BR>
+/* An array, which is set to true when the device is registered. */<BR>
+static bool probed_devices[HWICAP_DEVICES];<BR>
+<BR>
+static spinlock_t hwicap_spinlock = SPIN_LOCK_UNLOCKED;<BR>
+<BR>
+static struct class *icap_class;<BR>
+<BR>
+#define UNIMPLEMENTED 0xFFFF<BR>
+<BR>
+static const struct config_registers v2_config_registers = {<BR>
+       .CRC = 0,<BR>
+       .FAR = 1,<BR>
+       .FDRI = 2,<BR>
+       .FDRO = 3,<BR>
+       .CMD = 4,<BR>
+       .CTL = 5,<BR>
+       .MASK = 6,<BR>
+       .STAT = 7,<BR>
+       .LOUT = 8,<BR>
+       .COR = 9,<BR>
+       .MFWR = 10,<BR>
+       .FLR = 11,<BR>
+       .KEY = 12,<BR>
+       .CBC = 13,<BR>
+       .IDCODE = 14,<BR>
+       .AXSS = UNIMPLEMENTED,<BR>
+       .C0R_1 = UNIMPLEMENTED,<BR>
+       .CSOB = UNIMPLEMENTED,<BR>
+       .WBSTAR = UNIMPLEMENTED,<BR>
+       .TIMER = UNIMPLEMENTED,<BR>
+       .BOOTSTS = UNIMPLEMENTED,<BR>
+       .CTL_1 = UNIMPLEMENTED,<BR>
+};<BR>
+<BR>
+static const struct config_registers v4_config_registers = {<BR>
+       .CRC = 0,<BR>
+       .FAR = 1,<BR>
+       .FDRI = 2,<BR>
+       .FDRO = 3,<BR>
+       .CMD = 4,<BR>
+       .CTL = 5,<BR>
+       .MASK = 6,<BR>
+       .STAT = 7,<BR>
+       .LOUT = 8,<BR>
+       .COR = 9,<BR>
+       .MFWR = 10,<BR>
+       .FLR = UNIMPLEMENTED,<BR>
+       .KEY = UNIMPLEMENTED,<BR>
+       .CBC = 11,<BR>
+       .IDCODE = 12,<BR>
+       .AXSS = 13,<BR>
+       .C0R_1 = UNIMPLEMENTED,<BR>
+       .CSOB = UNIMPLEMENTED,<BR>
+       .WBSTAR = UNIMPLEMENTED,<BR>
+       .TIMER = UNIMPLEMENTED,<BR>
+       .BOOTSTS = UNIMPLEMENTED,<BR>
+       .CTL_1 = UNIMPLEMENTED,<BR>
+};<BR>
+static const struct config_registers v5_config_registers = {<BR>
+       .CRC = 0,<BR>
+       .FAR = 1,<BR>
+       .FDRI = 2,<BR>
+       .FDRO = 3,<BR>
+       .CMD = 4,<BR>
+       .CTL = 5,<BR>
+       .MASK = 6,<BR>
+       .STAT = 7,<BR>
+       .LOUT = 8,<BR>
+       .COR = 9,<BR>
+       .MFWR = 10,<BR>
+       .FLR = UNIMPLEMENTED,<BR>
+       .KEY = UNIMPLEMENTED,<BR>
+       .CBC = 11,<BR>
+       .IDCODE = 12,<BR>
+       .AXSS = 13,<BR>
+       .C0R_1 = 14,<BR>
+       .CSOB = 15,<BR>
+       .WBSTAR = 16,<BR>
+       .TIMER = 17,<BR>
+       .BOOTSTS = 18,<BR>
+       .CTL_1 = 19,<BR>
+};<BR>
+<BR>
+/**<BR>
+ * hwicap_command_desync: Send a DESYNC command to the ICAP port.<BR>
+ * @parameter drvdata: a pointer to the drvdata.<BR>
+ *<BR>
+ * This command desynchronizes the ICAP After this command, a<BR>
+ * bitstream containing a NULL packet, followed by a SYNCH packet is<BR>
+ * required before the ICAP will recognize commands.<BR>
+ */<BR>
+int hwicap_command_desync(struct hwicap_drvdata *drvdata)<BR>
+{<BR>
+       u32 buffer[4];<BR>
+       u32 index = 0;<BR>
+<BR>
+       /*<BR>
+        * Create the data to be written to the ICAP.<BR>
+        */<BR>
+       buffer[index++] = hwicap_type_1_write(drvdata->config_regs->CMD) | 1;<BR>
+       buffer[index++] = XHI_CMD_DESYNCH;<BR>
+       buffer[index++] = XHI_NOOP_PACKET;<BR>
+       buffer[index++] = XHI_NOOP_PACKET;<BR>
+<BR>
+       /*<BR>
+        * Write the data to the FIFO and intiate the transfer of data present<BR>
+        * in the FIFO to the ICAP device.<BR>
+        */<BR>
+       return drvdata->config->set_configuration(drvdata,<BR>
+                       &buffer[0], index);<BR>
+}<BR>
+<BR>
+/**<BR>
+ * hwicap_command_capture: Send a CAPTURE command to the ICAP port.<BR>
+ * @parameter drvdata: a pointer to the drvdata.<BR>
+ *<BR>
+ * This command captures all of the flip flop states so they will be<BR>
+ * available during readback.  One can use this command instead of<BR>
+ * enabling the CAPTURE block in the design.<BR>
+ */<BR>
+int hwicap_command_capture(struct hwicap_drvdata *drvdata)<BR>
+{<BR>
+       u32 buffer[7];<BR>
+       u32 index = 0;<BR>
+<BR>
+       /*<BR>
+        * Create the data to be written to the ICAP.<BR>
+        */<BR>
+       buffer[index++] = XHI_DUMMY_PACKET;<BR>
+       buffer[index++] = XHI_SYNC_PACKET;<BR>
+       buffer[index++] = XHI_NOOP_PACKET;<BR>
+       buffer[index++] = hwicap_type_1_write(drvdata->config_regs->CMD) | 1;<BR>
+       buffer[index++] = XHI_CMD_GCAPTURE;<BR>
+       buffer[index++] = XHI_DUMMY_PACKET;<BR>
+       buffer[index++] = XHI_DUMMY_PACKET;<BR>
+<BR>
+       /*<BR>
+        * Write the data to the FIFO and intiate the transfer of data<BR>
+        * present in the FIFO to the ICAP device.<BR>
+        */<BR>
+       return drvdata->config->set_configuration(drvdata,<BR>
+                       &buffer[0], index);<BR>
+<BR>
+}<BR>
+<BR>
+/**<BR>
+ * hwicap_get_configuration_register: Query a configuration register.<BR>
+ * @parameter drvdata: a pointer to the drvdata.<BR>
+ * @parameter reg: a constant which represents the configuration<BR>
+ *             register value to be returned.<BR>
+ *             Examples:  XHI_IDCODE, XHI_FLR.<BR>
+ * @parameter RegData: returns the value of the register.<BR>
+ *<BR>
+ * Sends a query packet to the ICAP and then receives the response.<BR>
+ * The icap is left in Synched state.<BR>
+ */<BR>
+int hwicap_get_configuration_register(struct hwicap_drvdata *drvdata,<BR>
+               u32 reg, u32 *RegData)<BR>
+{<BR>
+       int status;<BR>
+       u32 buffer[6];<BR>
+       u32 index = 0;<BR>
+<BR>
+       /*<BR>
+        * Create the data to be written to the ICAP.<BR>
+        */<BR>
+       buffer[index++] = XHI_DUMMY_PACKET;<BR>
+       buffer[index++] = XHI_SYNC_PACKET;<BR>
+       buffer[index++] = XHI_NOOP_PACKET;<BR>
+       buffer[index++] = hwicap_type_1_read(reg) | 1;<BR>
+       buffer[index++] = XHI_NOOP_PACKET;<BR>
+       buffer[index++] = XHI_NOOP_PACKET;<BR>
+<BR>
+       /*<BR>
+        * Write the data to the FIFO and intiate the transfer of data present<BR>
+        * in the FIFO to the ICAP device.<BR>
+        */<BR>
+       status = drvdata->config->set_configuration(drvdata,<BR>
+                       &buffer[0], index);<BR>
+       if (status)<BR>
+               return status;<BR>
+<BR>
+       /*<BR>
+        * Read the configuration register<BR>
+        */<BR>
+       status = drvdata->config->get_configuration(drvdata, RegData, 1);<BR>
+       if (status)<BR>
+               return status;<BR>
+<BR>
+       return 0;<BR>
+}<BR>
+<BR>
+int hwicap_initialize_hwicap(struct hwicap_drvdata *drvdata)<BR>
+{<BR>
+       int status;<BR>
+       u32 idcode;<BR>
+<BR>
+       dev_dbg(drvdata->dev, "initializing\n");<BR>
+<BR>
+       /* Abort any current transaction, to make sure we have the<BR>
+        * ICAP in a good state. */<BR>
+       dev_dbg(drvdata->dev, "Reset...\n");<BR>
+       drvdata->config->reset(drvdata);<BR>
+<BR>
+       dev_dbg(drvdata->dev, "Desync...\n");<BR>
+       status = hwicap_command_desync(drvdata);<BR>
+       if (status)<BR>
+               return status;<BR>
+<BR>
+       /* Attempt to read the IDCODE from ICAP.  This<BR>
+        * may not be returned correctly, due to the design of the<BR>
+        * hardware.<BR>
+        */<BR>
+       dev_dbg(drvdata->dev, "Reading IDCODE...\n");<BR>
+       status = hwicap_get_configuration_register(<BR>
+                       drvdata, drvdata->config_regs->IDCODE, &idcode);<BR>
+       dev_dbg(drvdata->dev, "IDCODE = %x\n", idcode);<BR>
+       if (status)<BR>
+               return status;<BR>
+<BR>
+       dev_dbg(drvdata->dev, "Desync...\n");<BR>
+       status = hwicap_command_desync(drvdata);<BR>
+       if (status)<BR>
+               return status;<BR>
+<BR>
+       return 0;<BR>
+}<BR>
+<BR>
+static ssize_t<BR>
+hwicap_read(struct file *file, char *buf, size_t count, loff_t *ppos)<BR>
+{<BR>
+       struct hwicap_drvdata *drvdata = file->private_data;<BR>
+       ssize_t bytes_to_read = 0;<BR>
+       u32 *kbuf;<BR>
+       u32 words;<BR>
+       u32 bytes_remaining;<BR>
+       int status;<BR>
+<BR>
+        spin_lock(&hwicap_spinlock);<BR>
+       if (drvdata->is_accessing)<BR>
+               return -EBUSY;<BR>
+       drvdata->is_accessing = 1;<BR>
+        spin_unlock(&hwicap_spinlock);<BR>
+<BR>
+       if (drvdata->read_buffer_in_use) {<BR>
+               /* If there are leftover bytes in the buffer, just */<BR>
+               /* return them and don't try to read more from the */<BR>
+               /* ICAP device. */<BR>
+               bytes_to_read =<BR>
+                       (count < drvdata->read_buffer_in_use) ? count :<BR>
+                       drvdata->read_buffer_in_use;<BR>
+<BR>
+               /* Return the data currently in the read buffer. */<BR>
+               if (copy_to_user(buf, drvdata->read_buffer, bytes_to_read)) {<BR>
+                       status = -EFAULT;<BR>
+                       goto error;<BR>
+               }<BR>
+               drvdata->read_buffer_in_use -= bytes_to_read;<BR>
+               memcpy(drvdata->read_buffer + bytes_to_read,<BR>
+                               drvdata->read_buffer, 4 - bytes_to_read);<BR>
+       } else {<BR>
+               /* Get new data from the ICAP, and return was was requested. */<BR>
+               kbuf = (u32 *) get_zeroed_page(GFP_KERNEL);<BR>
+               if (!kbuf) {<BR>
+                       status = -ENOMEM;<BR>
+                       goto error;<BR>
+               }<BR>
+<BR>
+               /* The ICAP device is only able to read complete */<BR>
+               /* words.  If a number of bytes that do not correspond */<BR>
+               /* to complete words is requested, then we read enough */<BR>
+               /* words to get the required number of bytes, and then */<BR>
+               /* save the remaining bytes for the next read. */<BR>
+<BR>
+               /* Determine the number of words to read, rounding up */<BR>
+               /* if necessary. */<BR>
+               words = ((count + 3) >> 2);<BR>
+               bytes_to_read = words << 2;<BR>
+<BR>
+               if (bytes_to_read > PAGE_SIZE)<BR>
+                       bytes_to_read = PAGE_SIZE;<BR>
+<BR>
+               /* Ensure we only read a complete number of words. */<BR>
+               bytes_remaining = bytes_to_read & 3;<BR>
+               bytes_to_read &= ~3;<BR>
+               words = bytes_to_read >> 2;<BR>
+<BR>
+               status = drvdata->config->get_configuration(drvdata,<BR>
+                               kbuf, words);<BR>
+<BR>
+               /* If we didn't read correctly, then bail out. */<BR>
+               if (status) {<BR>
+                       free_page((unsigned long)kbuf);<BR>
+                       goto error;<BR>
+               }<BR>
+<BR>
+               /* If we fail to return the data to the user, then bail out. */<BR>
+               if (copy_to_user(buf, kbuf, bytes_to_read)) {<BR>
+                       free_page((unsigned long)kbuf);<BR>
+                       status = -EFAULT;<BR>
+                       goto error;<BR>
+               }<BR>
+               memcpy(kbuf, drvdata->read_buffer, bytes_remaining);<BR>
+               drvdata->read_buffer_in_use = bytes_remaining;<BR>
+               free_page((unsigned long)kbuf);<BR>
+       }<BR>
+       status = bytes_to_read;<BR>
+ error:<BR>
+        spin_lock(&hwicap_spinlock);<BR>
+       drvdata->is_accessing = 0;<BR>
+        spin_unlock(&hwicap_spinlock);<BR>
+       return status;<BR>
+}<BR>
+<BR>
+static ssize_t<BR>
+hwicap_write(struct file *file, const char *buf,<BR>
+               size_t count, loff_t *ppos)<BR>
+{<BR>
+       struct hwicap_drvdata *drvdata = file->private_data;<BR>
+       ssize_t written = 0;<BR>
+       ssize_t left = count;<BR>
+       u32 *kbuf;<BR>
+       ssize_t len;<BR>
+       ssize_t status;<BR>
+<BR>
+        spin_lock(&hwicap_spinlock);<BR>
+       if (drvdata->is_accessing)<BR>
+               return -EBUSY;<BR>
+       drvdata->is_accessing = 1;<BR>
+        spin_unlock(&hwicap_spinlock);<BR>
+<BR>
+       left += drvdata->write_buffer_in_use;<BR>
+<BR>
+       /* Only write multiples of 4 bytes. */<BR>
+       if (left < 4) {<BR>
+               status = 0;<BR>
+               goto error;<BR>
+       }<BR>
+<BR>
+       kbuf = (u32 *) __get_free_page(GFP_KERNEL);<BR>
+       if (!kbuf) {<BR>
+               status = -ENOMEM;<BR>
+               goto error;<BR>
+       }<BR>
+<BR>
+       while (left > 3) {<BR>
+               /* only write multiples of 4 bytes, so there might */<BR>
+               /* be as many as 3 bytes left (at the end). */<BR>
+               len = left;<BR>
+<BR>
+               if (len > PAGE_SIZE)<BR>
+                       len = PAGE_SIZE;<BR>
+               len &= ~3;<BR>
+<BR>
+               if (drvdata->write_buffer_in_use) {<BR>
+                       memcpy(kbuf, drvdata->write_buffer,<BR>
+                                       drvdata->write_buffer_in_use);<BR>
+                       if (copy_from_user(<BR>
+                           (((char *)kbuf) + (drvdata->write_buffer_in_use)),<BR>
+                           buf + written,<BR>
+                           len - (drvdata->write_buffer_in_use))) {<BR>
+                               free_page((unsigned long)kbuf);<BR>
+                               status = -EFAULT;<BR>
+                               goto error;<BR>
+                       }<BR>
+               } else {<BR>
+                       if (copy_from_user(kbuf, buf + written, len)) {<BR>
+                               free_page((unsigned long)kbuf);<BR>
+                               status = -EFAULT;<BR>
+                               goto error;<BR>
+                       }<BR>
+               }<BR>
+<BR>
+               status = drvdata->config->set_configuration(drvdata,<BR>
+                               kbuf, len >> 2);<BR>
+<BR>
+               if (status) {<BR>
+                       free_page((unsigned long)kbuf);<BR>
+                       status = -EFAULT;<BR>
+                       goto error;<BR>
+               }<BR>
+               if (drvdata->write_buffer_in_use) {<BR>
+                       len -= drvdata->write_buffer_in_use;<BR>
+                       left -= drvdata->write_buffer_in_use;<BR>
+                       drvdata->write_buffer_in_use = 0;<BR>
+               }<BR>
+               written += len;<BR>
+               left -= len;<BR>
+       }<BR>
+       if ((left > 0) && (left < 4)) {<BR>
+               if (!copy_from_user(drvdata->write_buffer,<BR>
+                                               buf + written, left)) {<BR>
+                       drvdata->write_buffer_in_use = left;<BR>
+                       written += left;<BR>
+                       left = 0;<BR>
+               }<BR>
+       }<BR>
+<BR>
+       free_page((unsigned long)kbuf);<BR>
+       status = written;<BR>
+ error:<BR>
+        spin_lock(&hwicap_spinlock);<BR>
+       drvdata->is_accessing = 0;<BR>
+        spin_unlock(&hwicap_spinlock);<BR>
+       return status;<BR>
+}<BR>
+<BR>
+static int hwicap_open(struct inode *inode, struct file *file)<BR>
+{<BR>
+       struct hwicap_drvdata *drvdata;<BR>
+       int status;<BR>
+<BR>
+       drvdata = container_of(inode->i_cdev, struct hwicap_drvdata, cdev);<BR>
+<BR>
+        spin_lock(&hwicap_spinlock);<BR>
+       if (drvdata->is_open)<BR>
+               return -EBUSY;<BR>
+       drvdata->is_open = 1;<BR>
+       drvdata->is_accessing = 0;<BR>
+        spin_unlock(&hwicap_spinlock);<BR>
+<BR>
+       status = hwicap_initialize_hwicap(drvdata);<BR>
+       if (status) {<BR>
+               dev_err(drvdata->dev, "Failed to open file");<BR>
+               return status;<BR>
+       }<BR>
+<BR>
+       file->private_data = drvdata;<BR>
+       drvdata->write_buffer_in_use = 0;<BR>
+       drvdata->read_buffer_in_use = 0;<BR>
+<BR>
+       return 0;<BR>
+}<BR>
+<BR>
+static int hwicap_release(struct inode *inode, struct file *file)<BR>
+{<BR>
+       struct hwicap_drvdata *drvdata = file->private_data;<BR>
+       int i;<BR>
+       int status = 0;<BR>
+<BR>
+       if (drvdata->write_buffer_in_use) {<BR>
+               /* Flush write buffer. */<BR>
+               for (i = drvdata->write_buffer_in_use; i < 4; i++)<BR>
+                       drvdata->write_buffer[i] = 0;<BR>
+<BR>
+               status = drvdata->config->set_configuration(drvdata,<BR>
+                               (u32 *) drvdata->write_buffer, 1);<BR>
+               if (status)<BR>
+                       goto error;<BR>
+       }<BR>
+<BR>
+       status = hwicap_command_desync(drvdata);<BR>
+       if (status)<BR>
+               goto error;<BR>
+<BR>
+ error:<BR>
+        spin_lock(&hwicap_spinlock);<BR>
+       drvdata->is_open = 0;<BR>
+        spin_unlock(&hwicap_spinlock);<BR>
+       return status;<BR>
+}<BR>
+<BR>
+static struct file_operations hwicap_fops = {<BR>
+       .owner = THIS_MODULE,<BR>
+       .write = hwicap_write,<BR>
+       .read = hwicap_read,<BR>
+       .open = hwicap_open,<BR>
+       .release = hwicap_release,<BR>
+};<BR>
+<BR>
+static int __devinit hwicap_setup(struct device *dev, int id,<BR>
+               const struct resource *regs_res,<BR>
+               const struct hwicap_driver_config *config,<BR>
+               const struct config_registers *config_regs)<BR>
+{<BR>
+       dev_t devt;<BR>
+       struct hwicap_drvdata *drvdata = NULL;<BR>
+       int retval = 0;<BR>
+<BR>
+       dev_info(dev, "Xilinx icap port driver\n");<BR>
+<BR>
+       if (id < 0) {<BR>
+               for (id = 0; id < HWICAP_DEVICES; id++)<BR>
+                       if (!probed_devices[id])<BR>
+                               break;<BR>
+       }<BR>
+       if (id < 0 || id >= HWICAP_DEVICES) {<BR>
+               dev_err(dev, "%s%i too large\n", DRIVER_NAME, id);<BR>
+               return -EINVAL;<BR>
+       }<BR>
+       if (probed_devices[id]) {<BR>
+               dev_err(dev, "cannot assign to %s%i; it is already in use\n",<BR>
+                       DRIVER_NAME, id);<BR>
+               return -EBUSY;<BR>
+       }<BR>
+<BR>
+       probed_devices[id] = 1;<BR>
+<BR>
+       devt = MKDEV(xhwicap_major, xhwicap_minor + id);<BR>
+<BR>
+       drvdata = kmalloc(sizeof(struct hwicap_drvdata), GFP_KERNEL);<BR>
+       if (!drvdata) {<BR>
+               dev_err(dev, "Couldn't allocate device private record\n");<BR>
+               return -ENOMEM;<BR>
+       }<BR>
+       memset((void *)drvdata, 0, sizeof(struct hwicap_drvdata));<BR>
+       dev_set_drvdata(dev, (void *)drvdata);<BR>
+<BR>
+       if (!regs_res) {<BR>
+               dev_err(dev, "Couldn't get registers resource\n");<BR>
+               retval = -EFAULT;<BR>
+               goto failed1;<BR>
+       }<BR>
+<BR>
+       drvdata->mem_start = regs_res->start;<BR>
+       drvdata->mem_end = regs_res->end;<BR>
+       drvdata->mem_size = regs_res->end - regs_res->start + 1;<BR>
+<BR>
+       if (!request_mem_region(drvdata->mem_start,<BR>
+                                       drvdata->mem_size, DRIVER_NAME)) {<BR>
+               dev_err(dev, "Couldn't lock memory region at %p\n",<BR>
+                       (void *)regs_res->start);<BR>
+               retval = -EBUSY;<BR>
+               goto failed1;<BR>
+       }<BR>
+<BR>
+       drvdata->devt = devt;<BR>
+       drvdata->dev = dev;<BR>
+       drvdata->base_address = ioremap(drvdata->mem_start, drvdata->mem_size);<BR>
+       if (!drvdata->base_address) {<BR>
+               dev_err(dev, "ioremap() failed\n");<BR>
+               goto failed2;<BR>
+       }<BR>
+<BR>
+       drvdata->config = config;<BR>
+       drvdata->config_regs = config_regs;<BR>
+<BR>
+        spin_lock(&hwicap_spinlock);<BR>
+       drvdata->is_open = 0;<BR>
+       drvdata->is_accessing = 0;<BR>
+        spin_unlock(&hwicap_spinlock);<BR>
+<BR>
+       dev_info(dev, "ioremap %lx to %p with size %x\n",<BR>
+                (unsigned long int)drvdata->mem_start,<BR>
+                       drvdata->base_address, drvdata->mem_size);<BR>
+<BR>
+       cdev_init(&drvdata->cdev, &hwicap_fops);<BR>
+       drvdata->cdev.owner = THIS_MODULE;<BR>
+       retval = cdev_add(&drvdata->cdev, devt, 1);<BR>
+       if (retval) {<BR>
+               dev_err(dev, "cdev_add() failed\n");<BR>
+               goto failed3;<BR>
+       }<BR>
+       /*  devfs_mk_cdev(devt, S_IFCHR|S_IRUGO|S_IWUGO, DRIVER_NAME); */<BR>
+       class_device_create(icap_class, NULL, devt, NULL, DRIVER_NAME);<BR>
+       return 0;               /* success */<BR>
+<BR>
+ failed3:<BR>
+       iounmap(drvdata->base_address);<BR>
+<BR>
+ failed2:<BR>
+       release_mem_region(regs_res->start, drvdata->mem_size);<BR>
+<BR>
+ failed1:<BR>
+       kfree(drvdata);<BR>
+<BR>
+       return retval;<BR>
+}<BR>
+<BR>
+static struct hwicap_driver_config buffer_icap_config = {<BR>
+       .get_configuration = buffer_icap_get_configuration,<BR>
+       .set_configuration = buffer_icap_set_configuration,<BR>
+       .reset = buffer_icap_reset,<BR>
+};<BR>
+<BR>
+static struct hwicap_driver_config fifo_icap_config = {<BR>
+       .get_configuration = fifo_icap_get_configuration,<BR>
+       .set_configuration = fifo_icap_set_configuration,<BR>
+       .reset = fifo_icap_reset,<BR>
+};<BR>
+<BR>
+static int __devexit hwicap_remove(struct device *dev)<BR>
+{<BR>
+       struct hwicap_drvdata *drvdata;<BR>
+<BR>
+       drvdata = (struct hwicap_drvdata *)dev_get_drvdata(dev);<BR>
+<BR>
+       if (!drvdata)<BR>
+            return 0;<BR>
+       <BR>
+        class_device_destroy(icap_class, drvdata->devt);<BR>
+        cdev_del(&drvdata->cdev);<BR>
+        iounmap(drvdata->base_address);<BR>
+        release_mem_region(drvdata->mem_start, drvdata->mem_size);<BR>
+        kfree(drvdata);<BR>
+        dev_set_drvdata(dev, NULL);<BR>
+        probed_devices[MINOR(dev->devt)-xhwicap_minor] = 0;<BR>
+      <BR>
+       return 0;               /* success */<BR>
+}<BR>
+<BR>
+static int __devinit hwicap_drv_probe(struct platform_device *pdev)<BR>
+{<BR>
+       struct resource *res;<BR>
+       const struct config_registers *regs;<BR>
+       const char *family;<BR>
+<BR>
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);<BR>
+       if (!res)<BR>
+               return -ENODEV;<BR>
+<BR>
+       /* It's most likely that we're using V4, if the family is not<BR>
+          specified */<BR>
+       regs = &v4_config_registers;<BR>
+       family = pdev->dev.platform_data;<BR>
+<BR>
+       if (family) {<BR>
+               if (!strcmp(family, "virtex2p")) {<BR>
+                       regs = &v2_config_registers;<BR>
+               } else if (!strcmp(family, "virtex4")) {<BR>
+                       regs = &v4_config_registers;<BR>
+               } else if (!strcmp(family, "virtex5")) {<BR>
+                       regs = &v5_config_registers;<BR>
+               }<BR>
+       }<BR>
+<BR>
+       return hwicap_setup(&pdev->dev, pdev->id, res,<BR>
+                       &buffer_icap_config, regs);<BR>
+}<BR>
+<BR>
+static int __devexit hwicap_drv_remove(struct platform_device *pdev)<BR>
+{<BR>
+       return hwicap_remove(&pdev->dev);<BR>
+}<BR>
+<BR>
+static struct platform_driver hwicap_platform_driver = {<BR>
+       .probe = hwicap_drv_probe,<BR>
+       .remove = hwicap_drv_remove,<BR>
+       .driver = {<BR>
+               .owner = THIS_MODULE,<BR>
+               .name = DRIVER_NAME,<BR>
+       },<BR>
+};<BR>
+<BR>
+/* ---------------------------------------------------------------------<BR>
+ * OF bus binding<BR>
+ */<BR>
+<BR>
+#if defined(CONFIG_OF)<BR>
+static int __devinit<BR>
+hwicap_of_probe(struct of_device *op, const struct of_device_id *match)<BR>
+{<BR>
+       struct resource res;<BR>
+       const unsigned int *id;<BR>
+       const char *family;<BR>
+       int rc;<BR>
+       const struct hwicap_driver_config *config = match->data;<BR>
+       const struct config_registers *regs;<BR>
+<BR>
+       dev_dbg(&op->dev, "hwicap_of_probe(%p, %p)\n", op, match);<BR>
+<BR>
+       rc = of_address_to_resource(op->node, 0, &res);<BR>
+       if (rc) {<BR>
+               dev_err(&op->dev, "invalid address\n");<BR>
+               return rc;<BR>
+       }<BR>
+<BR>
+       id = of_get_property(op->node, "port-number", NULL);<BR>
+<BR>
+       /* It's most likely that we're using V4, if the family is not<BR>
+          specified */<BR>
+       regs = &v4_config_registers;<BR>
+       family = of_get_property(op->node, "xlnx,family", NULL);<BR>
+<BR>
+       if (family) {<BR>
+               if (!strcmp(family, "virtex2p")) {<BR>
+                       regs = &v2_config_registers;<BR>
+               } else if (!strcmp(family, "virtex4")) {<BR>
+                       regs = &v4_config_registers;<BR>
+               } else if (!strcmp(family, "virtex5")) {<BR>
+                       regs = &v5_config_registers;<BR>
+               }<BR>
+       }<BR>
+       return hwicap_setup(&op->dev, id ? *id : -1, &res, config,<BR>
+                       regs);<BR>
+}<BR>
+<BR>
+static int __devexit hwicap_of_remove(struct of_device *op)<BR>
+{<BR>
+       return hwicap_remove(&op->dev);<BR>
+}<BR>
+<BR>
+/* Match table for of_platform binding */<BR>
+static const struct of_device_id __devinit hwicap_of_match[] = {<BR>
+       { .compatible = "xlnx,opb-hwicap-1.00.b", .data = &buffer_icap_config},<BR>
+       { .compatible = "xlnx,xps-hwicap-1.00.a", .data = &fifo_icap_config},<BR>
+       {},<BR>
+};<BR>
+MODULE_DEVICE_TABLE(of, hwicap_of_match);<BR>
+<BR>
+static struct of_platform_driver hwicap_of_driver = {<BR>
+       .owner = THIS_MODULE,<BR>
+       .name = DRIVER_NAME,<BR>
+       .match_table = hwicap_of_match,<BR>
+       .probe = hwicap_of_probe,<BR>
+       .remove = __devexit_p(hwicap_of_remove),<BR>
+       .driver = {<BR>
+               .name = DRIVER_NAME,<BR>
+       },<BR>
+};<BR>
+<BR>
+/* Registration helpers to keep the number of #ifdefs to a minimum */<BR>
+static inline int __devinit hwicap_of_register(void)<BR>
+{<BR>
+       pr_debug("hwicap: calling of_register_platform_driver()\n");<BR>
+       return of_register_platform_driver(&hwicap_of_driver);<BR>
+}<BR>
+<BR>
+static inline void __devexit hwicap_of_unregister(void)<BR>
+{<BR>
+       of_unregister_platform_driver(&hwicap_of_driver);<BR>
+}<BR>
+#else /* CONFIG_OF */<BR>
+/* CONFIG_OF not enabled; do nothing helpers */<BR>
+static inline int __devinit hwicap_of_register(void) { return 0; }<BR>
+static inline void __devexit hwicap_of_unregister(void) { }<BR>
+#endif /* CONFIG_OF */<BR>
+<BR>
+static int __devinit hwicap_module_init(void)<BR>
+{<BR>
+       dev_t devt;<BR>
+       int retval;<BR>
+<BR>
+       icap_class = class_create(THIS_MODULE, "xilinx_config");<BR>
+<BR>
+       if (xhwicap_major) {<BR>
+               devt = MKDEV(xhwicap_major, xhwicap_minor);<BR>
+               retval = register_chrdev_region(<BR>
+                               devt,<BR>
+                               HWICAP_DEVICES,<BR>
+                               DRIVER_NAME);<BR>
+               if (retval < 0)<BR>
+                       return retval;<BR>
+       } else {<BR>
+               retval = alloc_chrdev_region(&devt,<BR>
+                               xhwicap_minor,<BR>
+                               HWICAP_DEVICES,<BR>
+                               DRIVER_NAME);<BR>
+               if (retval < 0)<BR>
+                       return retval;<BR>
+               xhwicap_major = MAJOR(devt);<BR>
+       }<BR>
+<BR>
+       retval = platform_driver_register(&hwicap_platform_driver);<BR>
+<BR>
+       if (retval)<BR>
+               goto failed1;<BR>
+<BR>
+       retval = hwicap_of_register();<BR>
+<BR>
+       if (retval)<BR>
+               goto failed2;<BR>
+<BR>
+       return retval;<BR>
+<BR>
+ failed2:<BR>
+       platform_driver_unregister(&hwicap_platform_driver);<BR>
+<BR>
+ failed1:<BR>
+       unregister_chrdev_region(devt, HWICAP_DEVICES);<BR>
+<BR>
+       return retval;<BR>
+}<BR>
+<BR>
+static void __devexit hwicap_module_cleanup(void)<BR>
+{<BR>
+       dev_t devt = MKDEV(xhwicap_major, xhwicap_minor);<BR>
+<BR>
+       class_destroy(icap_class);<BR>
+<BR>
+       platform_driver_unregister(&hwicap_platform_driver);<BR>
+<BR>
+       hwicap_of_unregister();<BR>
+<BR>
+       unregister_chrdev_region(devt, HWICAP_DEVICES);<BR>
+}<BR>
+<BR>
+module_init(hwicap_module_init);<BR>
+module_exit(hwicap_module_cleanup);<BR>
+<BR>
+MODULE_AUTHOR("Xilinx, Inc; Xilinx Research Labs Group");<BR>
+MODULE_DESCRIPTION("Xilinx ICAP Port Driver");<BR>
+MODULE_LICENSE("GPL");<BR>
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.h b/drivers/char/xilinx_hwicap/xilinx_hwicap.h<BR>
new file mode 100644<BR>
index 0000000..b6b47d0<BR>
--- /dev/null<BR>
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.h<BR>
@@ -0,0 +1,193 @@<BR>
+/*****************************************************************************<BR>
+ *<BR>
+ *     Author: Xilinx, Inc.<BR>
+ *<BR>
+ *     This program is free software; you can redistribute it and/or modify it<BR>
+ *     under the terms of the GNU General Public License as published by the<BR>
+ *     Free Software Foundation; either version 2 of the License, or (at your<BR>
+ *     option) any later version.<BR>
+ *<BR>
+ *     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"<BR>
+ *     AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND<BR>
+ *     SOLUTIONS FOR XILINX DEVICES.  BY PROVIDING THIS DESIGN, CODE,<BR>
+ *     OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,<BR>
+ *     APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION<BR>
+ *     THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,<BR>
+ *     AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE<BR>
+ *     FOR YOUR IMPLEMENTATION.  XILINX EXPRESSLY DISCLAIMS ANY<BR>
+ *     WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE<BR>
+ *     IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR<BR>
+ *     REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF<BR>
+ *     INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS<BR>
+ *     FOR A PARTICULAR PURPOSE.<BR>
+ *<BR>
+ *     Xilinx products are not intended for use in life support appliances,<BR>
+ *     devices, or systems. Use in such applications is expressly prohibited.<BR>
+ *<BR>
+ *     (c) Copyright 2003-2007 Xilinx Inc.<BR>
+ *     All rights reserved.<BR>
+ *<BR>
+ *     You should have received a copy of the GNU General Public License along<BR>
+ *     with this program; if not, write to the Free Software Foundation, Inc.,<BR>
+ *     675 Mass Ave, Cambridge, MA 02139, USA.<BR>
+ *<BR>
+ *****************************************************************************/<BR>
+<BR>
+#ifndef XILINX_HWICAP_H_       /* prevent circular inclusions */<BR>
+#define XILINX_HWICAP_H_       /* by using protection macros */<BR>
+<BR>
+#include <linux/types.h><BR>
+#include <linux/cdev.h><BR>
+#include <linux/version.h><BR>
+#include <linux/platform_device.h><BR>
+<BR>
+#include <asm/io.h><BR>
+<BR>
+struct hwicap_drvdata {<BR>
+       u32 write_buffer_in_use;  /* Always in [0,3] */<BR>
+       u8 write_buffer[4];<BR>
+       u32 read_buffer_in_use;   /* Always in [0,3] */<BR>
+       u8 read_buffer[4];<BR>
+       u32 mem_start;            /* phys. address of the control registers */<BR>
+       u32 mem_end;              /* phys. address of the control registers */<BR>
+       u32 mem_size;<BR>
+       void __iomem *base_address;/* virt. address of the control registers */<BR>
+<BR>
+       struct device *dev;<BR>
+       struct cdev cdev;       /* Char device structure */<BR>
+       dev_t devt;<BR>
+<BR>
+       const struct hwicap_driver_config *config;<BR>
+       const struct config_registers *config_regs;<BR>
+       void *private_data;<BR>
+       bool is_open;<BR>
+       bool is_accessing;<BR>
+};<BR>
+<BR>
+struct hwicap_driver_config {<BR>
+       int (*get_configuration)(struct hwicap_drvdata *drvdata, u32 *data,<BR>
+                       u32 size);<BR>
+       int (*set_configuration)(struct hwicap_drvdata *drvdata, u32 *data,<BR>
+                       u32 size);<BR>
+       void (*reset)(struct hwicap_drvdata *drvdata);<BR>
+};<BR>
+<BR>
+/* Number of times to poll the done regsiter */<BR>
+#define XHI_MAX_RETRIES     10<BR>
+<BR>
+/************ Constant Definitions *************/<BR>
+<BR>
+#define XHI_PAD_FRAMES              0x1<BR>
+<BR>
+/* Mask for calculating configuration packet headers */<BR>
+#define XHI_WORD_COUNT_MASK_TYPE_1  0x7FFUL<BR>
+#define XHI_WORD_COUNT_MASK_TYPE_2  0x1FFFFFUL<BR>
+#define XHI_TYPE_MASK               0x7<BR>
+#define XHI_REGISTER_MASK           0xF<BR>
+#define XHI_OP_MASK                 0x3<BR>
+<BR>
+#define XHI_TYPE_SHIFT              29<BR>
+#define XHI_REGISTER_SHIFT          13<BR>
+#define XHI_OP_SHIFT                27<BR>
+<BR>
+#define XHI_TYPE_1                  1<BR>
+#define XHI_TYPE_2                  2<BR>
+#define XHI_OP_WRITE                2<BR>
+#define XHI_OP_READ                 1<BR>
+<BR>
+/* Address Block Types */<BR>
+#define XHI_FAR_CLB_BLOCK           0<BR>
+#define XHI_FAR_BRAM_BLOCK          1<BR>
+#define XHI_FAR_BRAM_INT_BLOCK      2<BR>
+<BR>
+struct config_registers {<BR>
+       u32 CRC;<BR>
+       u32 FAR;<BR>
+       u32 FDRI;<BR>
+       u32 FDRO;<BR>
+       u32 CMD;<BR>
+       u32 CTL;<BR>
+       u32 MASK;<BR>
+       u32 STAT;<BR>
+       u32 LOUT;<BR>
+       u32 COR;<BR>
+       u32 MFWR;<BR>
+       u32 FLR;<BR>
+       u32 KEY;<BR>
+       u32 CBC;<BR>
+       u32 IDCODE;<BR>
+       u32 AXSS;<BR>
+       u32 C0R_1;<BR>
+       u32 CSOB;<BR>
+       u32 WBSTAR;<BR>
+       u32 TIMER;<BR>
+       u32 BOOTSTS;<BR>
+       u32 CTL_1;<BR>
+};<BR>
+<BR>
+/* Configuration Commands */<BR>
+#define XHI_CMD_NULL                0<BR>
+#define XHI_CMD_WCFG                1<BR>
+#define XHI_CMD_MFW                 2<BR>
+#define XHI_CMD_DGHIGH              3<BR>
+#define XHI_CMD_RCFG                4<BR>
+#define XHI_CMD_START               5<BR>
+#define XHI_CMD_RCAP                6<BR>
+#define XHI_CMD_RCRC                7<BR>
+#define XHI_CMD_AGHIGH              8<BR>
+#define XHI_CMD_SWITCH              9<BR>
+#define XHI_CMD_GRESTORE            10<BR>
+#define XHI_CMD_SHUTDOWN            11<BR>
+#define XHI_CMD_GCAPTURE            12<BR>
+#define XHI_CMD_DESYNCH             13<BR>
+#define XHI_CMD_IPROG               15 /* Only in Virtex5 */<BR>
+#define XHI_CMD_CRCC                16 /* Only in Virtex5 */<BR>
+#define XHI_CMD_LTIMER              17 /* Only in Virtex5 */<BR>
+<BR>
+/* Packet constants */<BR>
+#define XHI_SYNC_PACKET             0xAA995566UL<BR>
+#define XHI_DUMMY_PACKET            0xFFFFFFFFUL<BR>
+#define XHI_NOOP_PACKET             (XHI_TYPE_1 << XHI_TYPE_SHIFT)<BR>
+#define XHI_TYPE_2_READ ((XHI_TYPE_2 << XHI_TYPE_SHIFT) | \<BR>
+                       (XHI_OP_READ << XHI_OP_SHIFT))<BR>
+<BR>
+#define XHI_TYPE_2_WRITE ((XHI_TYPE_2 << XHI_TYPE_SHIFT) | \<BR>
+                       (XHI_OP_WRITE << XHI_OP_SHIFT))<BR>
+<BR>
+#define XHI_TYPE2_CNT_MASK          0x07FFFFFF<BR>
+<BR>
+#define XHI_TYPE_1_PACKET_MAX_WORDS 2047UL<BR>
+#define XHI_TYPE_1_HEADER_BYTES     4<BR>
+#define XHI_TYPE_2_HEADER_BYTES     8<BR>
+<BR>
+/* Constant to use for CRC check when CRC has been disabled */<BR>
+#define XHI_DISABLED_AUTO_CRC       0x0000DEFCUL<BR>
+<BR>
+/**<BR>
+ * hwicap_type_1_read: Generates a Type 1 read packet header.<BR>
+ * @parameter: Register is the address of the register to be read back.<BR>
+ *<BR>
+ * Generates a Type 1 read packet header, which is used to indirectly<BR>
+ * read registers in the configuration logic.  This packet must then<BR>
+ * be sent through the icap device, and a return packet received with<BR>
+ * the information.<BR>
+ **/<BR>
+static inline u32 hwicap_type_1_read(u32 Register)<BR>
+{<BR>
+       return (XHI_TYPE_1 << XHI_TYPE_SHIFT) |<BR>
+               (Register << XHI_REGISTER_SHIFT) |<BR>
+               (XHI_OP_READ << XHI_OP_SHIFT);<BR>
+}<BR>
+<BR>
+/**<BR>
+ * hwicap_type_1_write: Generates a Type 1 write packet header<BR>
+ * @parameter: Register is the address of the register to be read back.<BR>
+ **/<BR>
+static inline u32 hwicap_type_1_write(u32 Register)<BR>
+{<BR>
+       return (XHI_TYPE_1 << XHI_TYPE_SHIFT) |<BR>
+               (Register << XHI_REGISTER_SHIFT) |<BR>
+               (XHI_OP_WRITE << XHI_OP_SHIFT);<BR>
+}<BR>
+<BR>
+#endif<BR>
--<BR>
1.5.3.4-dirty<BR>
<BR>
<BR>
<BR>
</FONT>
</P>
</BODY>
</HTML>