aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorStephen Neuendorffer <stephen.neuendorffer@xilinx.com>2008-02-05 12:24:09 -0500
committerGrant Likely <grant.likely@secretlab.ca>2008-02-06 12:23:52 -0500
commitef141a0bb0dc6172bb8fe5408cf8adbd5f76ff45 (patch)
tree41bc7cbfa8e8501c510632f8e98b3603c6b3746c /drivers/char
parent3de66a175d2014246a2e990412e5750922e5c7d8 (diff)
[POWERPC] Xilinx: hwicap driver
This includes code for new fifo-based xps_hwicap in addition to the older opb_hwicap, which has a significantly different interface. The common code between the two drivers is largely shared. Significant differences exists between this driver and what is supported in the EDK drivers. In particular, most of the architecture-specific code for reconfiguring individual FPGA resources has been removed. This functionality is likely better provided in a user-space support library. In addition, read and write access is supported. In addition, although the xps_hwicap cores support interrupt-driver mode, this driver only supports polled operation, in order to make the code simpler, and since the interrupt processing overhead is likely to slow down the throughput under Linux. Signed-off-by: Stephen Neuendorffer <stephen.neuendorffer@xilinx.com> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/Kconfig10
-rw-r--r--drivers/char/Makefile1
-rw-r--r--drivers/char/xilinx_hwicap/Makefile7
-rw-r--r--drivers/char/xilinx_hwicap/buffer_icap.c380
-rw-r--r--drivers/char/xilinx_hwicap/buffer_icap.h57
-rw-r--r--drivers/char/xilinx_hwicap/fifo_icap.c381
-rw-r--r--drivers/char/xilinx_hwicap/fifo_icap.h62
-rw-r--r--drivers/char/xilinx_hwicap/xilinx_hwicap.c904
-rw-r--r--drivers/char/xilinx_hwicap/xilinx_hwicap.h193
9 files changed, 1995 insertions, 0 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 466629594776..be8371ac3086 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -841,6 +841,16 @@ config DTLK
841 To compile this driver as a module, choose M here: the 841 To compile this driver as a module, choose M here: the
842 module will be called dtlk. 842 module will be called dtlk.
843 843
844config XILINX_HWICAP
845 tristate "Xilinx HWICAP Support"
846 depends on XILINX_VIRTEX
847 help
848 This option enables support for Xilinx Internal Configuration
849 Access Port (ICAP) driver. The ICAP is used on Xilinx Virtex
850 FPGA platforms to partially reconfigure the FPGA at runtime.
851
852 If unsure, say N.
853
844config R3964 854config R3964
845 tristate "Siemens R3964 line discipline" 855 tristate "Siemens R3964 line discipline"
846 ---help--- 856 ---help---
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 96fc01eddefe..686fabbd85cd 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -77,6 +77,7 @@ obj-$(CONFIG_EFI_RTC) += efirtc.o
77obj-$(CONFIG_SGI_DS1286) += ds1286.o 77obj-$(CONFIG_SGI_DS1286) += ds1286.o
78obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o 78obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o
79obj-$(CONFIG_DS1302) += ds1302.o 79obj-$(CONFIG_DS1302) += ds1302.o
80obj-$(CONFIG_XILINX_HWICAP) += xilinx_hwicap/
80ifeq ($(CONFIG_GENERIC_NVRAM),y) 81ifeq ($(CONFIG_GENERIC_NVRAM),y)
81 obj-$(CONFIG_NVRAM) += generic_nvram.o 82 obj-$(CONFIG_NVRAM) += generic_nvram.o
82else 83else
diff --git a/drivers/char/xilinx_hwicap/Makefile b/drivers/char/xilinx_hwicap/Makefile
new file mode 100644
index 000000000000..5491cbc42f43
--- /dev/null
+++ b/drivers/char/xilinx_hwicap/Makefile
@@ -0,0 +1,7 @@
1#
2# Makefile for the Xilinx OPB hwicap driver
3#
4
5obj-$(CONFIG_XILINX_HWICAP) += xilinx_hwicap_m.o
6
7xilinx_hwicap_m-y := xilinx_hwicap.o fifo_icap.o buffer_icap.o
diff --git a/drivers/char/xilinx_hwicap/buffer_icap.c b/drivers/char/xilinx_hwicap/buffer_icap.c
new file mode 100644
index 000000000000..dfea2bde162b
--- /dev/null
+++ b/drivers/char/xilinx_hwicap/buffer_icap.c
@@ -0,0 +1,380 @@
1/*****************************************************************************
2 *
3 * Author: Xilinx, Inc.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
11 * AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND
12 * SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,
13 * OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,
14 * APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION
15 * THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
16 * AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
17 * FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
18 * WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
19 * IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
20 * REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
21 * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 * FOR A PARTICULAR PURPOSE.
23 *
24 * Xilinx products are not intended for use in life support appliances,
25 * devices, or systems. Use in such applications is expressly prohibited.
26 *
27 * (c) Copyright 2003-2008 Xilinx Inc.
28 * All rights reserved.
29 *
30 * You should have received a copy of the GNU General Public License along
31 * with this program; if not, write to the Free Software Foundation, Inc.,
32 * 675 Mass Ave, Cambridge, MA 02139, USA.
33 *
34 *****************************************************************************/
35
36#include "buffer_icap.h"
37
38/* Indicates how many bytes will fit in a buffer. (1 BRAM) */
39#define XHI_MAX_BUFFER_BYTES 2048
40#define XHI_MAX_BUFFER_INTS (XHI_MAX_BUFFER_BYTES >> 2)
41
42/* File access and error constants */
43#define XHI_DEVICE_READ_ERROR -1
44#define XHI_DEVICE_WRITE_ERROR -2
45#define XHI_BUFFER_OVERFLOW_ERROR -3
46
47#define XHI_DEVICE_READ 0x1
48#define XHI_DEVICE_WRITE 0x0
49
50/* Constants for checking transfer status */
51#define XHI_CYCLE_DONE 0
52#define XHI_CYCLE_EXECUTING 1
53
54/* buffer_icap register offsets */
55
56/* Size of transfer, read & write */
57#define XHI_SIZE_REG_OFFSET 0x800L
58/* offset into bram, read & write */
59#define XHI_BRAM_OFFSET_REG_OFFSET 0x804L
60/* Read not Configure, direction of transfer. Write only */
61#define XHI_RNC_REG_OFFSET 0x808L
62/* Indicates transfer complete. Read only */
63#define XHI_STATUS_REG_OFFSET 0x80CL
64
65/* Constants for setting the RNC register */
66#define XHI_CONFIGURE 0x0UL
67#define XHI_READBACK 0x1UL
68
69/* Constants for the Done register */
70#define XHI_NOT_FINISHED 0x0UL
71#define XHI_FINISHED 0x1UL
72
73#define XHI_BUFFER_START 0
74
75/**
76 * buffer_icap_get_status: Get the contents of the status register.
77 * @parameter base_address: is the base address of the device
78 *
79 * The status register contains the ICAP status and the done bit.
80 *
81 * D8 - cfgerr
82 * D7 - dalign
83 * D6 - rip
84 * D5 - in_abort_l
85 * D4 - Always 1
86 * D3 - Always 1
87 * D2 - Always 1
88 * D1 - Always 1
89 * D0 - Done bit
90 **/
91static inline u32 buffer_icap_get_status(void __iomem *base_address)
92{
93 return in_be32(base_address + XHI_STATUS_REG_OFFSET);
94}
95
96/**
97 * buffer_icap_get_bram: Reads data from the storage buffer bram.
98 * @parameter base_address: contains the base address of the component.
99 * @parameter offset: The word offset from which the data should be read.
100 *
101 * A bram is used as a configuration memory cache. One frame of data can
102 * be stored in this "storage buffer".
103 **/
104static inline u32 buffer_icap_get_bram(void __iomem *base_address,
105 u32 offset)
106{
107 return in_be32(base_address + (offset << 2));
108}
109
110/**
111 * buffer_icap_busy: Return true if the icap device is busy
112 * @parameter base_address: is the base address of the device
113 *
114 * The queries the low order bit of the status register, which
115 * indicates whether the current configuration or readback operation
116 * has completed.
117 **/
118static inline bool buffer_icap_busy(void __iomem *base_address)
119{
120 return (buffer_icap_get_status(base_address) & 1) == XHI_NOT_FINISHED;
121}
122
123/**
124 * buffer_icap_busy: Return true if the icap device is not busy
125 * @parameter base_address: is the base address of the device
126 *
127 * The queries the low order bit of the status register, which
128 * indicates whether the current configuration or readback operation
129 * has completed.
130 **/
131static inline bool buffer_icap_done(void __iomem *base_address)
132{
133 return (buffer_icap_get_status(base_address) & 1) == XHI_FINISHED;
134}
135
136/**
137 * buffer_icap_set_size: Set the size register.
138 * @parameter base_address: is the base address of the device
139 * @parameter data: The size in bytes.
140 *
141 * The size register holds the number of 8 bit bytes to transfer between
142 * bram and the icap (or icap to bram).
143 **/
144static inline void buffer_icap_set_size(void __iomem *base_address,
145 u32 data)
146{
147 out_be32(base_address + XHI_SIZE_REG_OFFSET, data);
148}
149
150/**
151 * buffer_icap_mSetoffsetReg: Set the bram offset register.
152 * @parameter base_address: contains the base address of the device.
153 * @parameter data: is the value to be written to the data register.
154 *
155 * The bram offset register holds the starting bram address to transfer
156 * data from during configuration or write data to during readback.
157 **/
158static inline void buffer_icap_set_offset(void __iomem *base_address,
159 u32 data)
160{
161 out_be32(base_address + XHI_BRAM_OFFSET_REG_OFFSET, data);
162}
163
164/**
165 * buffer_icap_set_rnc: Set the RNC (Readback not Configure) register.
166 * @parameter base_address: contains the base address of the device.
167 * @parameter data: is the value to be written to the data register.
168 *
169 * The RNC register determines the direction of the data transfer. It
170 * controls whether a configuration or readback take place. Writing to
171 * this register initiates the transfer. A value of 1 initiates a
172 * readback while writing a value of 0 initiates a configuration.
173 **/
174static inline void buffer_icap_set_rnc(void __iomem *base_address,
175 u32 data)
176{
177 out_be32(base_address + XHI_RNC_REG_OFFSET, data);
178}
179
180/**
181 * buffer_icap_set_bram: Write data to the storage buffer bram.
182 * @parameter base_address: contains the base address of the component.
183 * @parameter offset: The word offset at which the data should be written.
184 * @parameter data: The value to be written to the bram offset.
185 *
186 * A bram is used as a configuration memory cache. One frame of data can
187 * be stored in this "storage buffer".
188 **/
189static inline void buffer_icap_set_bram(void __iomem *base_address,
190 u32 offset, u32 data)
191{
192 out_be32(base_address + (offset << 2), data);
193}
194
195/**
196 * buffer_icap_device_read: Transfer bytes from ICAP to the storage buffer.
197 * @parameter drvdata: a pointer to the drvdata.
198 * @parameter offset: The storage buffer start address.
199 * @parameter count: The number of words (32 bit) to read from the
200 * device (ICAP).
201 **/
202static int buffer_icap_device_read(struct hwicap_drvdata *drvdata,
203 u32 offset, u32 count)
204{
205
206 s32 retries = 0;
207 void __iomem *base_address = drvdata->base_address;
208
209 if (buffer_icap_busy(base_address))
210 return -EBUSY;
211
212 if ((offset + count) > XHI_MAX_BUFFER_INTS)
213 return -EINVAL;
214
215 /* setSize count*4 to get bytes. */
216 buffer_icap_set_size(base_address, (count << 2));
217 buffer_icap_set_offset(base_address, offset);
218 buffer_icap_set_rnc(base_address, XHI_READBACK);
219
220 while (buffer_icap_busy(base_address)) {
221 retries++;
222 if (retries > XHI_MAX_RETRIES)
223 return -EBUSY;
224 }
225 return 0;
226
227};
228
229/**
230 * buffer_icap_device_write: Transfer bytes from ICAP to the storage buffer.
231 * @parameter drvdata: a pointer to the drvdata.
232 * @parameter offset: The storage buffer start address.
233 * @parameter count: The number of words (32 bit) to read from the
234 * device (ICAP).
235 **/
236static int buffer_icap_device_write(struct hwicap_drvdata *drvdata,
237 u32 offset, u32 count)
238{
239
240 s32 retries = 0;
241 void __iomem *base_address = drvdata->base_address;
242
243 if (buffer_icap_busy(base_address))
244 return -EBUSY;
245
246 if ((offset + count) > XHI_MAX_BUFFER_INTS)
247 return -EINVAL;
248
249 /* setSize count*4 to get bytes. */
250 buffer_icap_set_size(base_address, count << 2);
251 buffer_icap_set_offset(base_address, offset);
252 buffer_icap_set_rnc(base_address, XHI_CONFIGURE);
253
254 while (buffer_icap_busy(base_address)) {
255 retries++;
256 if (retries > XHI_MAX_RETRIES)
257 return -EBUSY;
258 }
259 return 0;
260
261};
262
263/**
264 * buffer_icap_reset: Reset the logic of the icap device.
265 * @parameter drvdata: a pointer to the drvdata.
266 *
267 * Writing to the status register resets the ICAP logic in an internal
268 * version of the core. For the version of the core published in EDK,
269 * this is a noop.
270 **/
271void buffer_icap_reset(struct hwicap_drvdata *drvdata)
272{
273 out_be32(drvdata->base_address + XHI_STATUS_REG_OFFSET, 0xFEFE);
274}
275
276/**
277 * buffer_icap_set_configuration: Load a partial bitstream from system memory.
278 * @parameter drvdata: a pointer to the drvdata.
279 * @parameter data: Kernel address of the partial bitstream.
280 * @parameter size: the size of the partial bitstream in 32 bit words.
281 **/
282int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data,
283 u32 size)
284{
285 int status;
286 s32 buffer_count = 0;
287 s32 num_writes = 0;
288 bool dirty = 0;
289 u32 i;
290 void __iomem *base_address = drvdata->base_address;
291
292 /* Loop through all the data */
293 for (i = 0, buffer_count = 0; i < size; i++) {
294
295 /* Copy data to bram */
296 buffer_icap_set_bram(base_address, buffer_count, data[i]);
297 dirty = 1;
298
299 if (buffer_count < XHI_MAX_BUFFER_INTS - 1) {
300 buffer_count++;
301 continue;
302 }
303
304 /* Write data to ICAP */
305 status = buffer_icap_device_write(
306 drvdata,
307 XHI_BUFFER_START,
308 XHI_MAX_BUFFER_INTS);
309 if (status != 0) {
310 /* abort. */
311 buffer_icap_reset(drvdata);
312 return status;
313 }
314
315 buffer_count = 0;
316 num_writes++;
317 dirty = 0;
318 }
319
320 /* Write unwritten data to ICAP */
321 if (dirty) {
322 /* Write data to ICAP */
323 status = buffer_icap_device_write(drvdata, XHI_BUFFER_START,
324 buffer_count);
325 if (status != 0) {
326 /* abort. */
327 buffer_icap_reset(drvdata);
328 }
329 return status;
330 }
331
332 return 0;
333};
334
335/**
336 * buffer_icap_get_configuration: Read configuration data from the device.
337 * @parameter drvdata: a pointer to the drvdata.
338 * @parameter data: Address of the data representing the partial bitstream
339 * @parameter size: the size of the partial bitstream in 32 bit words.
340 **/
341int buffer_icap_get_configuration(struct hwicap_drvdata *drvdata, u32 *data,
342 u32 size)
343{
344 int status;
345 s32 buffer_count = 0;
346 s32 read_count = 0;
347 u32 i;
348 void __iomem *base_address = drvdata->base_address;
349
350 /* Loop through all the data */
351 for (i = 0, buffer_count = XHI_MAX_BUFFER_INTS; i < size; i++) {
352 if (buffer_count == XHI_MAX_BUFFER_INTS) {
353 u32 words_remaining = size - i;
354 u32 words_to_read =
355 words_remaining <
356 XHI_MAX_BUFFER_INTS ? words_remaining :
357 XHI_MAX_BUFFER_INTS;
358
359 /* Read data from ICAP */
360 status = buffer_icap_device_read(
361 drvdata,
362 XHI_BUFFER_START,
363 words_to_read);
364 if (status != 0) {
365 /* abort. */
366 buffer_icap_reset(drvdata);
367 return status;
368 }
369
370 buffer_count = 0;
371 read_count++;
372 }
373
374 /* Copy data from bram */
375 data[i] = buffer_icap_get_bram(base_address, buffer_count);
376 buffer_count++;
377 }
378
379 return 0;
380};
diff --git a/drivers/char/xilinx_hwicap/buffer_icap.h b/drivers/char/xilinx_hwicap/buffer_icap.h
new file mode 100644
index 000000000000..03184959fa00
--- /dev/null
+++ b/drivers/char/xilinx_hwicap/buffer_icap.h
@@ -0,0 +1,57 @@
1/*****************************************************************************
2 *
3 * Author: Xilinx, Inc.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
11 * AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND
12 * SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,
13 * OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,
14 * APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION
15 * THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
16 * AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
17 * FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
18 * WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
19 * IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
20 * REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
21 * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 * FOR A PARTICULAR PURPOSE.
23 *
24 * Xilinx products are not intended for use in life support appliances,
25 * devices, or systems. Use in such applications is expressly prohibited.
26 *
27 * (c) Copyright 2003-2008 Xilinx Inc.
28 * All rights reserved.
29 *
30 * You should have received a copy of the GNU General Public License along
31 * with this program; if not, write to the Free Software Foundation, Inc.,
32 * 675 Mass Ave, Cambridge, MA 02139, USA.
33 *
34 *****************************************************************************/
35
36#ifndef XILINX_BUFFER_ICAP_H_ /* prevent circular inclusions */
37#define XILINX_BUFFER_ICAP_H_ /* by using protection macros */
38
39#include <linux/types.h>
40#include <linux/cdev.h>
41#include <linux/version.h>
42#include <linux/platform_device.h>
43
44#include <asm/io.h>
45#include "xilinx_hwicap.h"
46
47void buffer_icap_reset(struct hwicap_drvdata *drvdata);
48
49/* Loads a partial bitstream from system memory. */
50int buffer_icap_set_configuration(struct hwicap_drvdata *drvdata, u32 *data,
51 u32 Size);
52
53/* Loads a partial bitstream from system memory. */
54int buffer_icap_get_configuration(struct hwicap_drvdata *drvdata, u32 *data,
55 u32 Size);
56
57#endif
diff --git a/drivers/char/xilinx_hwicap/fifo_icap.c b/drivers/char/xilinx_hwicap/fifo_icap.c
new file mode 100644
index 000000000000..0988314694a6
--- /dev/null
+++ b/drivers/char/xilinx_hwicap/fifo_icap.c
@@ -0,0 +1,381 @@
1/*****************************************************************************
2 *
3 * Author: Xilinx, Inc.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
11 * AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND
12 * SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,
13 * OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,
14 * APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION
15 * THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
16 * AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
17 * FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
18 * WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
19 * IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
20 * REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
21 * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 * FOR A PARTICULAR PURPOSE.
23 *
24 * Xilinx products are not intended for use in life support appliances,
25 * devices, or systems. Use in such applications is expressly prohibited.
26 *
27 * (c) Copyright 2007-2008 Xilinx Inc.
28 * All rights reserved.
29 *
30 * You should have received a copy of the GNU General Public License along
31 * with this program; if not, write to the Free Software Foundation, Inc.,
32 * 675 Mass Ave, Cambridge, MA 02139, USA.
33 *
34 *****************************************************************************/
35
36#include "fifo_icap.h"
37
38/* Register offsets for the XHwIcap device. */
39#define XHI_GIER_OFFSET 0x1C /* Device Global Interrupt Enable Reg */
40#define XHI_IPISR_OFFSET 0x20 /* Interrupt Status Register */
41#define XHI_IPIER_OFFSET 0x28 /* Interrupt Enable Register */
42#define XHI_WF_OFFSET 0x100 /* Write FIFO */
43#define XHI_RF_OFFSET 0x104 /* Read FIFO */
44#define XHI_SZ_OFFSET 0x108 /* Size Register */
45#define XHI_CR_OFFSET 0x10C /* Control Register */
46#define XHI_SR_OFFSET 0x110 /* Status Register */
47#define XHI_WFV_OFFSET 0x114 /* Write FIFO Vacancy Register */
48#define XHI_RFO_OFFSET 0x118 /* Read FIFO Occupancy Register */
49
50/* Device Global Interrupt Enable Register (GIER) bit definitions */
51
52#define XHI_GIER_GIE_MASK 0x80000000 /* Global Interrupt enable Mask */
53
54/**
55 * HwIcap Device Interrupt Status/Enable Registers
56 *
57 * Interrupt Status Register (IPISR) : This register holds the
58 * interrupt status flags for the device. These bits are toggle on
59 * write.
60 *
61 * Interrupt Enable Register (IPIER) : This register is used to enable
62 * interrupt sources for the device.
63 * Writing a '1' to a bit enables the corresponding interrupt.
64 * Writing a '0' to a bit disables the corresponding interrupt.
65 *
66 * IPISR/IPIER registers have the same bit definitions and are only defined
67 * once.
68 */
69#define XHI_IPIXR_RFULL_MASK 0x00000008 /* Read FIFO Full */
70#define XHI_IPIXR_WEMPTY_MASK 0x00000004 /* Write FIFO Empty */
71#define XHI_IPIXR_RDP_MASK 0x00000002 /* Read FIFO half full */
72#define XHI_IPIXR_WRP_MASK 0x00000001 /* Write FIFO half full */
73#define XHI_IPIXR_ALL_MASK 0x0000000F /* Mask of all interrupts */
74
75/* Control Register (CR) */
76#define XHI_CR_SW_RESET_MASK 0x00000008 /* SW Reset Mask */
77#define XHI_CR_FIFO_CLR_MASK 0x00000004 /* FIFO Clear Mask */
78#define XHI_CR_READ_MASK 0x00000002 /* Read from ICAP to FIFO */
79#define XHI_CR_WRITE_MASK 0x00000001 /* Write from FIFO to ICAP */
80
81/* Status Register (SR) */
82#define XHI_SR_CFGERR_N_MASK 0x00000100 /* Config Error Mask */
83#define XHI_SR_DALIGN_MASK 0x00000080 /* Data Alignment Mask */
84#define XHI_SR_RIP_MASK 0x00000040 /* Read back Mask */
85#define XHI_SR_IN_ABORT_N_MASK 0x00000020 /* Select Map Abort Mask */
86#define XHI_SR_DONE_MASK 0x00000001 /* Done bit Mask */
87
88
89#define XHI_WFO_MAX_VACANCY 1024 /* Max Write FIFO Vacancy, in words */
90#define XHI_RFO_MAX_OCCUPANCY 256 /* Max Read FIFO Occupancy, in words */
91/* The maximum amount we can request from fifo_icap_get_configuration
92 at once, in bytes. */
93#define XHI_MAX_READ_TRANSACTION_WORDS 0xFFF
94
95
96/**
97 * fifo_icap_fifo_write: Write data to the write FIFO.
98 * @parameter drvdata: a pointer to the drvdata.
99 * @parameter data: the 32-bit value to be written to the FIFO.
100 *
101 * This function will silently fail if the fifo is full.
102 **/
103static inline void fifo_icap_fifo_write(struct hwicap_drvdata *drvdata,
104 u32 data)
105{
106 dev_dbg(drvdata->dev, "fifo_write: %x\n", data);
107 out_be32(drvdata->base_address + XHI_WF_OFFSET, data);
108}
109
110/**
111 * fifo_icap_fifo_read: Read data from the Read FIFO.
112 * @parameter drvdata: a pointer to the drvdata.
113 *
114 * This function will silently fail if the fifo is empty.
115 **/
116static inline u32 fifo_icap_fifo_read(struct hwicap_drvdata *drvdata)
117{
118 u32 data = in_be32(drvdata->base_address + XHI_RF_OFFSET);
119 dev_dbg(drvdata->dev, "fifo_read: %x\n", data);
120 return data;
121}
122
123/**
124 * fifo_icap_set_read_size: Set the the size register.
125 * @parameter drvdata: a pointer to the drvdata.
126 * @parameter data: the size of the following read transaction, in words.
127 **/
128static inline void fifo_icap_set_read_size(struct hwicap_drvdata *drvdata,
129 u32 data)
130{
131 out_be32(drvdata->base_address + XHI_SZ_OFFSET, data);
132}
133
134/**
135 * fifo_icap_start_config: Initiate a configuration (write) to the device.
136 * @parameter drvdata: a pointer to the drvdata.
137 **/
138static inline void fifo_icap_start_config(struct hwicap_drvdata *drvdata)
139{
140 out_be32(drvdata->base_address + XHI_CR_OFFSET, XHI_CR_WRITE_MASK);
141 dev_dbg(drvdata->dev, "configuration started\n");
142}
143
144/**
145 * fifo_icap_start_readback: Initiate a readback from the device.
146 * @parameter drvdata: a pointer to the drvdata.
147 **/
148static inline void fifo_icap_start_readback(struct hwicap_drvdata *drvdata)
149{
150 out_be32(drvdata->base_address + XHI_CR_OFFSET, XHI_CR_READ_MASK);
151 dev_dbg(drvdata->dev, "readback started\n");
152}
153
154/**
155 * fifo_icap_busy: Return true if the ICAP is still processing a transaction.
156 * @parameter drvdata: a pointer to the drvdata.
157 **/
158static inline u32 fifo_icap_busy(struct hwicap_drvdata *drvdata)
159{
160 u32 status = in_be32(drvdata->base_address + XHI_SR_OFFSET);
161 dev_dbg(drvdata->dev, "Getting status = %x\n", status);
162 return (status & XHI_SR_DONE_MASK) ? 0 : 1;
163}
164
165/**
166 * fifo_icap_write_fifo_vacancy: Query the write fifo available space.
167 * @parameter drvdata: a pointer to the drvdata.
168 *
169 * Return the number of words that can be safely pushed into the write fifo.
170 **/
171static inline u32 fifo_icap_write_fifo_vacancy(
172 struct hwicap_drvdata *drvdata)
173{
174 return in_be32(drvdata->base_address + XHI_WFV_OFFSET);
175}
176
177/**
178 * fifo_icap_read_fifo_occupancy: Query the read fifo available data.
179 * @parameter drvdata: a pointer to the drvdata.
180 *
181 * Return the number of words that can be safely read from the read fifo.
182 **/
183static inline u32 fifo_icap_read_fifo_occupancy(
184 struct hwicap_drvdata *drvdata)
185{
186 return in_be32(drvdata->base_address + XHI_RFO_OFFSET);
187}
188
189/**
190 * fifo_icap_set_configuration: Send configuration data to the ICAP.
191 * @parameter drvdata: a pointer to the drvdata.
192 * @parameter frame_buffer: a pointer to the data to be written to the
193 * ICAP device.
194 * @parameter num_words: the number of words (32 bit) to write to the ICAP
195 * device.
196
197 * This function writes the given user data to the Write FIFO in
198 * polled mode and starts the transfer of the data to
199 * the ICAP device.
200 **/
201int fifo_icap_set_configuration(struct hwicap_drvdata *drvdata,
202 u32 *frame_buffer, u32 num_words)
203{
204
205 u32 write_fifo_vacancy = 0;
206 u32 retries = 0;
207 u32 remaining_words;
208
209 dev_dbg(drvdata->dev, "fifo_set_configuration\n");
210
211 /*
212 * Check if the ICAP device is Busy with the last Read/Write
213 */
214 if (fifo_icap_busy(drvdata))
215 return -EBUSY;
216
217 /*
218 * Set up the buffer pointer and the words to be transferred.
219 */
220 remaining_words = num_words;
221
222 while (remaining_words > 0) {
223 /*
224 * Wait until we have some data in the fifo.
225 */
226 while (write_fifo_vacancy == 0) {
227 write_fifo_vacancy =
228 fifo_icap_write_fifo_vacancy(drvdata);
229 retries++;
230 if (retries > XHI_MAX_RETRIES)
231 return -EIO;
232 }
233
234 /*
235 * Write data into the Write FIFO.
236 */
237 while ((write_fifo_vacancy != 0) &&
238 (remaining_words > 0)) {
239 fifo_icap_fifo_write(drvdata, *frame_buffer);
240
241 remaining_words--;
242 write_fifo_vacancy--;
243 frame_buffer++;
244 }
245 /* Start pushing whatever is in the FIFO into the ICAP. */
246 fifo_icap_start_config(drvdata);
247 }
248
249 /* Wait until the write has finished. */
250 while (fifo_icap_busy(drvdata)) {
251 retries++;
252 if (retries > XHI_MAX_RETRIES)
253 break;
254 }
255
256 dev_dbg(drvdata->dev, "done fifo_set_configuration\n");
257
258 /*
259 * If the requested number of words have not been read from
260 * the device then indicate failure.
261 */
262 if (remaining_words != 0)
263 return -EIO;
264
265 return 0;
266}
267
268/**
269 * fifo_icap_get_configuration: Read configuration data from the device.
270 * @parameter drvdata: a pointer to the drvdata.
271 * @parameter data: Address of the data representing the partial bitstream
272 * @parameter size: the size of the partial bitstream in 32 bit words.
273 *
274 * This function reads the specified number of words from the ICAP device in
275 * the polled mode.
276 */
277int fifo_icap_get_configuration(struct hwicap_drvdata *drvdata,
278 u32 *frame_buffer, u32 num_words)
279{
280
281 u32 read_fifo_occupancy = 0;
282 u32 retries = 0;
283 u32 *data = frame_buffer;
284 u32 remaining_words;
285 u32 words_to_read;
286
287 dev_dbg(drvdata->dev, "fifo_get_configuration\n");
288
289 /*
290 * Check if the ICAP device is Busy with the last Write/Read
291 */
292 if (fifo_icap_busy(drvdata))
293 return -EBUSY;
294
295 remaining_words = num_words;
296
297 while (remaining_words > 0) {
298 words_to_read = remaining_words;
299 /* The hardware has a limit on the number of words
300 that can be read at one time. */
301 if (words_to_read > XHI_MAX_READ_TRANSACTION_WORDS)
302 words_to_read = XHI_MAX_READ_TRANSACTION_WORDS;
303
304 remaining_words -= words_to_read;
305
306 fifo_icap_set_read_size(drvdata, words_to_read);
307 fifo_icap_start_readback(drvdata);
308
309 while (words_to_read > 0) {
310 /* Wait until we have some data in the fifo. */
311 while (read_fifo_occupancy == 0) {
312 read_fifo_occupancy =
313 fifo_icap_read_fifo_occupancy(drvdata);
314 retries++;
315 if (retries > XHI_MAX_RETRIES)
316 return -EIO;
317 }
318
319 if (read_fifo_occupancy > words_to_read)
320 read_fifo_occupancy = words_to_read;
321
322 words_to_read -= read_fifo_occupancy;
323
324 /* Read the data from the Read FIFO. */
325 while (read_fifo_occupancy != 0) {
326 *data++ = fifo_icap_fifo_read(drvdata);
327 read_fifo_occupancy--;
328 }
329 }
330 }
331
332 dev_dbg(drvdata->dev, "done fifo_get_configuration\n");
333
334 return 0;
335}
336
337/**
338 * buffer_icap_reset: Reset the logic of the icap device.
339 * @parameter drvdata: a pointer to the drvdata.
340 *
341 * This function forces the software reset of the complete HWICAP device.
342 * All the registers will return to the default value and the FIFO is also
343 * flushed as a part of this software reset.
344 */
345void fifo_icap_reset(struct hwicap_drvdata *drvdata)
346{
347 u32 reg_data;
348 /*
349 * Reset the device by setting/clearing the RESET bit in the
350 * Control Register.
351 */
352 reg_data = in_be32(drvdata->base_address + XHI_CR_OFFSET);
353
354 out_be32(drvdata->base_address + XHI_CR_OFFSET,
355 reg_data | XHI_CR_SW_RESET_MASK);
356
357 out_be32(drvdata->base_address + XHI_CR_OFFSET,
358 reg_data & (~XHI_CR_SW_RESET_MASK));
359
360}
361
362/**
363 * fifo_icap_flush_fifo: This function flushes the FIFOs in the device.
364 * @parameter drvdata: a pointer to the drvdata.
365 */
366void fifo_icap_flush_fifo(struct hwicap_drvdata *drvdata)
367{
368 u32 reg_data;
369 /*
370 * Flush the FIFO by setting/clearing the FIFO Clear bit in the
371 * Control Register.
372 */
373 reg_data = in_be32(drvdata->base_address + XHI_CR_OFFSET);
374
375 out_be32(drvdata->base_address + XHI_CR_OFFSET,
376 reg_data | XHI_CR_FIFO_CLR_MASK);
377
378 out_be32(drvdata->base_address + XHI_CR_OFFSET,
379 reg_data & (~XHI_CR_FIFO_CLR_MASK));
380}
381
diff --git a/drivers/char/xilinx_hwicap/fifo_icap.h b/drivers/char/xilinx_hwicap/fifo_icap.h
new file mode 100644
index 000000000000..4d3068dd0405
--- /dev/null
+++ b/drivers/char/xilinx_hwicap/fifo_icap.h
@@ -0,0 +1,62 @@
1/*****************************************************************************
2 *
3 * Author: Xilinx, Inc.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
11 * AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND
12 * SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,
13 * OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,
14 * APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION
15 * THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
16 * AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
17 * FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
18 * WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
19 * IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
20 * REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
21 * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 * FOR A PARTICULAR PURPOSE.
23 *
24 * Xilinx products are not intended for use in life support appliances,
25 * devices, or systems. Use in such applications is expressly prohibited.
26 *
27 * (c) Copyright 2007-2008 Xilinx Inc.
28 * All rights reserved.
29 *
30 * You should have received a copy of the GNU General Public License along
31 * with this program; if not, write to the Free Software Foundation, Inc.,
32 * 675 Mass Ave, Cambridge, MA 02139, USA.
33 *
34 *****************************************************************************/
35
36#ifndef XILINX_FIFO_ICAP_H_ /* prevent circular inclusions */
37#define XILINX_FIFO_ICAP_H_ /* by using protection macros */
38
39#include <linux/types.h>
40#include <linux/cdev.h>
41#include <linux/version.h>
42#include <linux/platform_device.h>
43
44#include <asm/io.h>
45#include "xilinx_hwicap.h"
46
47/* Reads integers from the device into the storage buffer. */
48int fifo_icap_get_configuration(
49 struct hwicap_drvdata *drvdata,
50 u32 *FrameBuffer,
51 u32 NumWords);
52
53/* Writes integers to the device from the storage buffer. */
54int fifo_icap_set_configuration(
55 struct hwicap_drvdata *drvdata,
56 u32 *FrameBuffer,
57 u32 NumWords);
58
59void fifo_icap_reset(struct hwicap_drvdata *drvdata);
60void fifo_icap_flush_fifo(struct hwicap_drvdata *drvdata);
61
62#endif
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
new file mode 100644
index 000000000000..24f6aef0fd3c
--- /dev/null
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
@@ -0,0 +1,904 @@
1/*****************************************************************************
2 *
3 * Author: Xilinx, Inc.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
11 * AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND
12 * SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,
13 * OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,
14 * APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION
15 * THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
16 * AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
17 * FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
18 * WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
19 * IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
20 * REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
21 * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 * FOR A PARTICULAR PURPOSE.
23 *
24 * Xilinx products are not intended for use in life support appliances,
25 * devices, or systems. Use in such applications is expressly prohibited.
26 *
27 * (c) Copyright 2002 Xilinx Inc., Systems Engineering Group
28 * (c) Copyright 2004 Xilinx Inc., Systems Engineering Group
29 * (c) Copyright 2007-2008 Xilinx Inc.
30 * All rights reserved.
31 *
32 * You should have received a copy of the GNU General Public License along
33 * with this program; if not, write to the Free Software Foundation, Inc.,
34 * 675 Mass Ave, Cambridge, MA 02139, USA.
35 *
36 *****************************************************************************/
37
38/*
39 * This is the code behind /dev/xilinx_icap -- it allows a user-space
40 * application to use the Xilinx ICAP subsystem.
41 *
42 * The following operations are possible:
43 *
44 * open open the port and initialize for access.
45 * release release port
46 * write Write a bitstream to the configuration processor.
47 * read Read a data stream from the configuration processor.
48 *
49 * After being opened, the port is initialized and accessed to avoid a
50 * corrupted first read which may occur with some hardware. The port
51 * is left in a desynched state, requiring that a synch sequence be
52 * transmitted before any valid configuration data. A user will have
53 * exclusive access to the device while it remains open, and the state
54 * of the ICAP cannot be guaranteed after the device is closed. Note
55 * that a complete reset of the core and the state of the ICAP cannot
56 * be performed on many versions of the cores, hence users of this
57 * device should avoid making inconsistent accesses to the device. In
58 * particular, accessing the read interface, without first generating
59 * a write containing a readback packet can leave the ICAP in an
60 * inaccessible state.
61 *
62 * Note that in order to use the read interface, it is first necessary
63 * to write a request packet to the write interface. i.e., it is not
64 * possible to simply readback the bitstream (or any configuration
65 * bits) from a device without specifically requesting them first.
66 * The code to craft such packets is intended to be part of the
67 * user-space application code that uses this device. The simplest
68 * way to use this interface is simply:
69 *
70 * cp foo.bit /dev/xilinx_icap
71 *
72 * Note that unless foo.bit is an appropriately constructed partial
73 * bitstream, this has a high likelyhood of overwriting the design
74 * currently programmed in the FPGA.
75 */
76
77#include <linux/version.h>
78#include <linux/module.h>
79#include <linux/kernel.h>
80#include <linux/types.h>
81#include <linux/ioport.h>
82#include <linux/interrupt.h>
83#include <linux/fcntl.h>
84#include <linux/init.h>
85#include <linux/poll.h>
86#include <linux/proc_fs.h>
87#include <asm/semaphore.h>
88#include <linux/sysctl.h>
89#include <linux/version.h>
90#include <linux/fs.h>
91#include <linux/cdev.h>
92#include <linux/platform_device.h>
93
94#include <asm/io.h>
95#include <asm/uaccess.h>
96#include <asm/system.h>
97
98#ifdef CONFIG_OF
99/* For open firmware. */
100#include <linux/of_device.h>
101#include <linux/of_platform.h>
102#endif
103
104#include "xilinx_hwicap.h"
105#include "buffer_icap.h"
106#include "fifo_icap.h"
107
108#define DRIVER_NAME "xilinx_icap"
109
110#define HWICAP_REGS (0x10000)
111
112/* dynamically allocate device number */
113static int xhwicap_major;
114static int xhwicap_minor;
115#define HWICAP_DEVICES 1
116
117module_param(xhwicap_major, int, S_IRUGO);
118module_param(xhwicap_minor, int, S_IRUGO);
119
120/* An array, which is set to true when the device is registered. */
121static bool probed_devices[HWICAP_DEVICES];
122
123static struct class *icap_class;
124
125#define UNIMPLEMENTED 0xFFFF
126
127static const struct config_registers v2_config_registers = {
128 .CRC = 0,
129 .FAR = 1,
130 .FDRI = 2,
131 .FDRO = 3,
132 .CMD = 4,
133 .CTL = 5,
134 .MASK = 6,
135 .STAT = 7,
136 .LOUT = 8,
137 .COR = 9,
138 .MFWR = 10,
139 .FLR = 11,
140 .KEY = 12,
141 .CBC = 13,
142 .IDCODE = 14,
143 .AXSS = UNIMPLEMENTED,
144 .C0R_1 = UNIMPLEMENTED,
145 .CSOB = UNIMPLEMENTED,
146 .WBSTAR = UNIMPLEMENTED,
147 .TIMER = UNIMPLEMENTED,
148 .BOOTSTS = UNIMPLEMENTED,
149 .CTL_1 = UNIMPLEMENTED,
150};
151
152static const struct config_registers v4_config_registers = {
153 .CRC = 0,
154 .FAR = 1,
155 .FDRI = 2,
156 .FDRO = 3,
157 .CMD = 4,
158 .CTL = 5,
159 .MASK = 6,
160 .STAT = 7,
161 .LOUT = 8,
162 .COR = 9,
163 .MFWR = 10,
164 .FLR = UNIMPLEMENTED,
165 .KEY = UNIMPLEMENTED,
166 .CBC = 11,
167 .IDCODE = 12,
168 .AXSS = 13,
169 .C0R_1 = UNIMPLEMENTED,
170 .CSOB = UNIMPLEMENTED,
171 .WBSTAR = UNIMPLEMENTED,
172 .TIMER = UNIMPLEMENTED,
173 .BOOTSTS = UNIMPLEMENTED,
174 .CTL_1 = UNIMPLEMENTED,
175};
176static const struct config_registers v5_config_registers = {
177 .CRC = 0,
178 .FAR = 1,
179 .FDRI = 2,
180 .FDRO = 3,
181 .CMD = 4,
182 .CTL = 5,
183 .MASK = 6,
184 .STAT = 7,
185 .LOUT = 8,
186 .COR = 9,
187 .MFWR = 10,
188 .FLR = UNIMPLEMENTED,
189 .KEY = UNIMPLEMENTED,
190 .CBC = 11,
191 .IDCODE = 12,
192 .AXSS = 13,
193 .C0R_1 = 14,
194 .CSOB = 15,
195 .WBSTAR = 16,
196 .TIMER = 17,
197 .BOOTSTS = 18,
198 .CTL_1 = 19,
199};
200
201/**
202 * hwicap_command_desync: Send a DESYNC command to the ICAP port.
203 * @parameter drvdata: a pointer to the drvdata.
204 *
205 * This command desynchronizes the ICAP After this command, a
206 * bitstream containing a NULL packet, followed by a SYNCH packet is
207 * required before the ICAP will recognize commands.
208 */
209int hwicap_command_desync(struct hwicap_drvdata *drvdata)
210{
211 u32 buffer[4];
212 u32 index = 0;
213
214 /*
215 * Create the data to be written to the ICAP.
216 */
217 buffer[index++] = hwicap_type_1_write(drvdata->config_regs->CMD) | 1;
218 buffer[index++] = XHI_CMD_DESYNCH;
219 buffer[index++] = XHI_NOOP_PACKET;
220 buffer[index++] = XHI_NOOP_PACKET;
221
222 /*
223 * Write the data to the FIFO and intiate the transfer of data present
224 * in the FIFO to the ICAP device.
225 */
226 return drvdata->config->set_configuration(drvdata,
227 &buffer[0], index);
228}
229
230/**
231 * hwicap_command_capture: Send a CAPTURE command to the ICAP port.
232 * @parameter drvdata: a pointer to the drvdata.
233 *
234 * This command captures all of the flip flop states so they will be
235 * available during readback. One can use this command instead of
236 * enabling the CAPTURE block in the design.
237 */
238int hwicap_command_capture(struct hwicap_drvdata *drvdata)
239{
240 u32 buffer[7];
241 u32 index = 0;
242
243 /*
244 * Create the data to be written to the ICAP.
245 */
246 buffer[index++] = XHI_DUMMY_PACKET;
247 buffer[index++] = XHI_SYNC_PACKET;
248 buffer[index++] = XHI_NOOP_PACKET;
249 buffer[index++] = hwicap_type_1_write(drvdata->config_regs->CMD) | 1;
250 buffer[index++] = XHI_CMD_GCAPTURE;
251 buffer[index++] = XHI_DUMMY_PACKET;
252 buffer[index++] = XHI_DUMMY_PACKET;
253
254 /*
255 * Write the data to the FIFO and intiate the transfer of data
256 * present in the FIFO to the ICAP device.
257 */
258 return drvdata->config->set_configuration(drvdata,
259 &buffer[0], index);
260
261}
262
263/**
264 * hwicap_get_configuration_register: Query a configuration register.
265 * @parameter drvdata: a pointer to the drvdata.
266 * @parameter reg: a constant which represents the configuration
267 * register value to be returned.
268 * Examples: XHI_IDCODE, XHI_FLR.
269 * @parameter RegData: returns the value of the register.
270 *
271 * Sends a query packet to the ICAP and then receives the response.
272 * The icap is left in Synched state.
273 */
274int hwicap_get_configuration_register(struct hwicap_drvdata *drvdata,
275 u32 reg, u32 *RegData)
276{
277 int status;
278 u32 buffer[6];
279 u32 index = 0;
280
281 /*
282 * Create the data to be written to the ICAP.
283 */
284 buffer[index++] = XHI_DUMMY_PACKET;
285 buffer[index++] = XHI_SYNC_PACKET;
286 buffer[index++] = XHI_NOOP_PACKET;
287 buffer[index++] = hwicap_type_1_read(reg) | 1;
288 buffer[index++] = XHI_NOOP_PACKET;
289 buffer[index++] = XHI_NOOP_PACKET;
290
291 /*
292 * Write the data to the FIFO and intiate the transfer of data present
293 * in the FIFO to the ICAP device.
294 */
295 status = drvdata->config->set_configuration(drvdata,
296 &buffer[0], index);
297 if (status)
298 return status;
299
300 /*
301 * Read the configuration register
302 */
303 status = drvdata->config->get_configuration(drvdata, RegData, 1);
304 if (status)
305 return status;
306
307 return 0;
308}
309
310int hwicap_initialize_hwicap(struct hwicap_drvdata *drvdata)
311{
312 int status;
313 u32 idcode;
314
315 dev_dbg(drvdata->dev, "initializing\n");
316
317 /* Abort any current transaction, to make sure we have the
318 * ICAP in a good state. */
319 dev_dbg(drvdata->dev, "Reset...\n");
320 drvdata->config->reset(drvdata);
321
322 dev_dbg(drvdata->dev, "Desync...\n");
323 status = hwicap_command_desync(drvdata);
324 if (status)
325 return status;
326
327 /* Attempt to read the IDCODE from ICAP. This
328 * may not be returned correctly, due to the design of the
329 * hardware.
330 */
331 dev_dbg(drvdata->dev, "Reading IDCODE...\n");
332 status = hwicap_get_configuration_register(
333 drvdata, drvdata->config_regs->IDCODE, &idcode);
334 dev_dbg(drvdata->dev, "IDCODE = %x\n", idcode);
335 if (status)
336 return status;
337
338 dev_dbg(drvdata->dev, "Desync...\n");
339 status = hwicap_command_desync(drvdata);
340 if (status)
341 return status;
342
343 return 0;
344}
345
346static ssize_t
347hwicap_read(struct file *file, char *buf, size_t count, loff_t *ppos)
348{
349 struct hwicap_drvdata *drvdata = file->private_data;
350 ssize_t bytes_to_read = 0;
351 u32 *kbuf;
352 u32 words;
353 u32 bytes_remaining;
354 int status;
355
356 if (down_interruptible(&drvdata->sem))
357 return -ERESTARTSYS;
358
359 if (drvdata->read_buffer_in_use) {
360 /* If there are leftover bytes in the buffer, just */
361 /* return them and don't try to read more from the */
362 /* ICAP device. */
363 bytes_to_read =
364 (count < drvdata->read_buffer_in_use) ? count :
365 drvdata->read_buffer_in_use;
366
367 /* Return the data currently in the read buffer. */
368 if (copy_to_user(buf, drvdata->read_buffer, bytes_to_read)) {
369 status = -EFAULT;
370 goto error;
371 }
372 drvdata->read_buffer_in_use -= bytes_to_read;
373 memcpy(drvdata->read_buffer + bytes_to_read,
374 drvdata->read_buffer, 4 - bytes_to_read);
375 } else {
376 /* Get new data from the ICAP, and return was was requested. */
377 kbuf = (u32 *) get_zeroed_page(GFP_KERNEL);
378 if (!kbuf) {
379 status = -ENOMEM;
380 goto error;
381 }
382
383 /* The ICAP device is only able to read complete */
384 /* words. If a number of bytes that do not correspond */
385 /* to complete words is requested, then we read enough */
386 /* words to get the required number of bytes, and then */
387 /* save the remaining bytes for the next read. */
388
389 /* Determine the number of words to read, rounding up */
390 /* if necessary. */
391 words = ((count + 3) >> 2);
392 bytes_to_read = words << 2;
393
394 if (bytes_to_read > PAGE_SIZE)
395 bytes_to_read = PAGE_SIZE;
396
397 /* Ensure we only read a complete number of words. */
398 bytes_remaining = bytes_to_read & 3;
399 bytes_to_read &= ~3;
400 words = bytes_to_read >> 2;
401
402 status = drvdata->config->get_configuration(drvdata,
403 kbuf, words);
404
405 /* If we didn't read correctly, then bail out. */
406 if (status) {
407 free_page((unsigned long)kbuf);
408 goto error;
409 }
410
411 /* If we fail to return the data to the user, then bail out. */
412 if (copy_to_user(buf, kbuf, bytes_to_read)) {
413 free_page((unsigned long)kbuf);
414 status = -EFAULT;
415 goto error;
416 }
417 memcpy(kbuf, drvdata->read_buffer, bytes_remaining);
418 drvdata->read_buffer_in_use = bytes_remaining;
419 free_page((unsigned long)kbuf);
420 }
421 status = bytes_to_read;
422 error:
423 up(&drvdata->sem);
424 return status;
425}
426
427static ssize_t
428hwicap_write(struct file *file, const char *buf,
429 size_t count, loff_t *ppos)
430{
431 struct hwicap_drvdata *drvdata = file->private_data;
432 ssize_t written = 0;
433 ssize_t left = count;
434 u32 *kbuf;
435 ssize_t len;
436 ssize_t status;
437
438 if (down_interruptible(&drvdata->sem))
439 return -ERESTARTSYS;
440
441 left += drvdata->write_buffer_in_use;
442
443 /* Only write multiples of 4 bytes. */
444 if (left < 4) {
445 status = 0;
446 goto error;
447 }
448
449 kbuf = (u32 *) __get_free_page(GFP_KERNEL);
450 if (!kbuf) {
451 status = -ENOMEM;
452 goto error;
453 }
454
455 while (left > 3) {
456 /* only write multiples of 4 bytes, so there might */
457 /* be as many as 3 bytes left (at the end). */
458 len = left;
459
460 if (len > PAGE_SIZE)
461 len = PAGE_SIZE;
462 len &= ~3;
463
464 if (drvdata->write_buffer_in_use) {
465 memcpy(kbuf, drvdata->write_buffer,
466 drvdata->write_buffer_in_use);
467 if (copy_from_user(
468 (((char *)kbuf) + (drvdata->write_buffer_in_use)),
469 buf + written,
470 len - (drvdata->write_buffer_in_use))) {
471 free_page((unsigned long)kbuf);
472 status = -EFAULT;
473 goto error;
474 }
475 } else {
476 if (copy_from_user(kbuf, buf + written, len)) {
477 free_page((unsigned long)kbuf);
478 status = -EFAULT;
479 goto error;
480 }
481 }
482
483 status = drvdata->config->set_configuration(drvdata,
484 kbuf, len >> 2);
485
486 if (status) {
487 free_page((unsigned long)kbuf);
488 status = -EFAULT;
489 goto error;
490 }
491 if (drvdata->write_buffer_in_use) {
492 len -= drvdata->write_buffer_in_use;
493 left -= drvdata->write_buffer_in_use;
494 drvdata->write_buffer_in_use = 0;
495 }
496 written += len;
497 left -= len;
498 }
499 if ((left > 0) && (left < 4)) {
500 if (!copy_from_user(drvdata->write_buffer,
501 buf + written, left)) {
502 drvdata->write_buffer_in_use = left;
503 written += left;
504 left = 0;
505 }
506 }
507
508 free_page((unsigned long)kbuf);
509 status = written;
510 error:
511 up(&drvdata->sem);
512 return status;
513}
514
515static int hwicap_open(struct inode *inode, struct file *file)
516{
517 struct hwicap_drvdata *drvdata;
518 int status;
519
520 drvdata = container_of(inode->i_cdev, struct hwicap_drvdata, cdev);
521
522 if (down_interruptible(&drvdata->sem))
523 return -ERESTARTSYS;
524
525 if (drvdata->is_open) {
526 status = -EBUSY;
527 goto error;
528 }
529
530 status = hwicap_initialize_hwicap(drvdata);
531 if (status) {
532 dev_err(drvdata->dev, "Failed to open file");
533 goto error;
534 }
535
536 file->private_data = drvdata;
537 drvdata->write_buffer_in_use = 0;
538 drvdata->read_buffer_in_use = 0;
539 drvdata->is_open = 1;
540
541 error:
542 up(&drvdata->sem);
543 return status;
544}
545
546static int hwicap_release(struct inode *inode, struct file *file)
547{
548 struct hwicap_drvdata *drvdata = file->private_data;
549 int i;
550 int status = 0;
551
552 if (down_interruptible(&drvdata->sem))
553 return -ERESTARTSYS;
554
555 if (drvdata->write_buffer_in_use) {
556 /* Flush write buffer. */
557 for (i = drvdata->write_buffer_in_use; i < 4; i++)
558 drvdata->write_buffer[i] = 0;
559
560 status = drvdata->config->set_configuration(drvdata,
561 (u32 *) drvdata->write_buffer, 1);
562 if (status)
563 goto error;
564 }
565
566 status = hwicap_command_desync(drvdata);
567 if (status)
568 goto error;
569
570 error:
571 drvdata->is_open = 0;
572 up(&drvdata->sem);
573 return status;
574}
575
576static struct file_operations hwicap_fops = {
577 .owner = THIS_MODULE,
578 .write = hwicap_write,
579 .read = hwicap_read,
580 .open = hwicap_open,
581 .release = hwicap_release,
582};
583
584static int __devinit hwicap_setup(struct device *dev, int id,
585 const struct resource *regs_res,
586 const struct hwicap_driver_config *config,
587 const struct config_registers *config_regs)
588{
589 dev_t devt;
590 struct hwicap_drvdata *drvdata = NULL;
591 int retval = 0;
592
593 dev_info(dev, "Xilinx icap port driver\n");
594
595 if (id < 0) {
596 for (id = 0; id < HWICAP_DEVICES; id++)
597 if (!probed_devices[id])
598 break;
599 }
600 if (id < 0 || id >= HWICAP_DEVICES) {
601 dev_err(dev, "%s%i too large\n", DRIVER_NAME, id);
602 return -EINVAL;
603 }
604 if (probed_devices[id]) {
605 dev_err(dev, "cannot assign to %s%i; it is already in use\n",
606 DRIVER_NAME, id);
607 return -EBUSY;
608 }
609
610 probed_devices[id] = 1;
611
612 devt = MKDEV(xhwicap_major, xhwicap_minor + id);
613
614 drvdata = kmalloc(sizeof(struct hwicap_drvdata), GFP_KERNEL);
615 if (!drvdata) {
616 dev_err(dev, "Couldn't allocate device private record\n");
617 return -ENOMEM;
618 }
619 memset((void *)drvdata, 0, sizeof(struct hwicap_drvdata));
620 dev_set_drvdata(dev, (void *)drvdata);
621
622 if (!regs_res) {
623 dev_err(dev, "Couldn't get registers resource\n");
624 retval = -EFAULT;
625 goto failed1;
626 }
627
628 drvdata->mem_start = regs_res->start;
629 drvdata->mem_end = regs_res->end;
630 drvdata->mem_size = regs_res->end - regs_res->start + 1;
631
632 if (!request_mem_region(drvdata->mem_start,
633 drvdata->mem_size, DRIVER_NAME)) {
634 dev_err(dev, "Couldn't lock memory region at %p\n",
635 (void *)regs_res->start);
636 retval = -EBUSY;
637 goto failed1;
638 }
639
640 drvdata->devt = devt;
641 drvdata->dev = dev;
642 drvdata->base_address = ioremap(drvdata->mem_start, drvdata->mem_size);
643 if (!drvdata->base_address) {
644 dev_err(dev, "ioremap() failed\n");
645 goto failed2;
646 }
647
648 drvdata->config = config;
649 drvdata->config_regs = config_regs;
650
651 init_MUTEX(&drvdata->sem);
652 drvdata->is_open = 0;
653
654 dev_info(dev, "ioremap %lx to %p with size %x\n",
655 (unsigned long int)drvdata->mem_start,
656 drvdata->base_address, drvdata->mem_size);
657
658 cdev_init(&drvdata->cdev, &hwicap_fops);
659 drvdata->cdev.owner = THIS_MODULE;
660 retval = cdev_add(&drvdata->cdev, devt, 1);
661 if (retval) {
662 dev_err(dev, "cdev_add() failed\n");
663 goto failed3;
664 }
665 /* devfs_mk_cdev(devt, S_IFCHR|S_IRUGO|S_IWUGO, DRIVER_NAME); */
666 class_device_create(icap_class, NULL, devt, NULL, DRIVER_NAME);
667 return 0; /* success */
668
669 failed3:
670 iounmap(drvdata->base_address);
671
672 failed2:
673 release_mem_region(regs_res->start, drvdata->mem_size);
674
675 failed1:
676 kfree(drvdata);
677
678 return retval;
679}
680
681static struct hwicap_driver_config buffer_icap_config = {
682 .get_configuration = buffer_icap_get_configuration,
683 .set_configuration = buffer_icap_set_configuration,
684 .reset = buffer_icap_reset,
685};
686
687static struct hwicap_driver_config fifo_icap_config = {
688 .get_configuration = fifo_icap_get_configuration,
689 .set_configuration = fifo_icap_set_configuration,
690 .reset = fifo_icap_reset,
691};
692
693static int __devexit hwicap_remove(struct device *dev)
694{
695 struct hwicap_drvdata *drvdata;
696
697 drvdata = (struct hwicap_drvdata *)dev_get_drvdata(dev);
698
699 if (!drvdata)
700 return 0;
701
702 class_device_destroy(icap_class, drvdata->devt);
703 cdev_del(&drvdata->cdev);
704 iounmap(drvdata->base_address);
705 release_mem_region(drvdata->mem_start, drvdata->mem_size);
706 kfree(drvdata);
707 dev_set_drvdata(dev, NULL);
708 probed_devices[MINOR(dev->devt)-xhwicap_minor] = 0;
709
710 return 0; /* success */
711}
712
713static int __devinit hwicap_drv_probe(struct platform_device *pdev)
714{
715 struct resource *res;
716 const struct config_registers *regs;
717 const char *family;
718
719 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
720 if (!res)
721 return -ENODEV;
722
723 /* It's most likely that we're using V4, if the family is not
724 specified */
725 regs = &v4_config_registers;
726 family = pdev->dev.platform_data;
727
728 if (family) {
729 if (!strcmp(family, "virtex2p")) {
730 regs = &v2_config_registers;
731 } else if (!strcmp(family, "virtex4")) {
732 regs = &v4_config_registers;
733 } else if (!strcmp(family, "virtex5")) {
734 regs = &v5_config_registers;
735 }
736 }
737
738 return hwicap_setup(&pdev->dev, pdev->id, res,
739 &buffer_icap_config, regs);
740}
741
742static int __devexit hwicap_drv_remove(struct platform_device *pdev)
743{
744 return hwicap_remove(&pdev->dev);
745}
746
747static struct platform_driver hwicap_platform_driver = {
748 .probe = hwicap_drv_probe,
749 .remove = hwicap_drv_remove,
750 .driver = {
751 .owner = THIS_MODULE,
752 .name = DRIVER_NAME,
753 },
754};
755
756/* ---------------------------------------------------------------------
757 * OF bus binding
758 */
759
760#if defined(CONFIG_OF)
761static int __devinit
762hwicap_of_probe(struct of_device *op, const struct of_device_id *match)
763{
764 struct resource res;
765 const unsigned int *id;
766 const char *family;
767 int rc;
768 const struct hwicap_driver_config *config = match->data;
769 const struct config_registers *regs;
770
771 dev_dbg(&op->dev, "hwicap_of_probe(%p, %p)\n", op, match);
772
773 rc = of_address_to_resource(op->node, 0, &res);
774 if (rc) {
775 dev_err(&op->dev, "invalid address\n");
776 return rc;
777 }
778
779 id = of_get_property(op->node, "port-number", NULL);
780
781 /* It's most likely that we're using V4, if the family is not
782 specified */
783 regs = &v4_config_registers;
784 family = of_get_property(op->node, "xlnx,family", NULL);
785
786 if (family) {
787 if (!strcmp(family, "virtex2p")) {
788 regs = &v2_config_registers;
789 } else if (!strcmp(family, "virtex4")) {
790 regs = &v4_config_registers;
791 } else if (!strcmp(family, "virtex5")) {
792 regs = &v5_config_registers;
793 }
794 }
795 return hwicap_setup(&op->dev, id ? *id : -1, &res, config,
796 regs);
797}
798
799static int __devexit hwicap_of_remove(struct of_device *op)
800{
801 return hwicap_remove(&op->dev);
802}
803
804/* Match table for of_platform binding */
805static const struct of_device_id __devinit hwicap_of_match[] = {
806 { .compatible = "xlnx,opb-hwicap-1.00.b", .data = &buffer_icap_config},
807 { .compatible = "xlnx,xps-hwicap-1.00.a", .data = &fifo_icap_config},
808 {},
809};
810MODULE_DEVICE_TABLE(of, hwicap_of_match);
811
812static struct of_platform_driver hwicap_of_driver = {
813 .owner = THIS_MODULE,
814 .name = DRIVER_NAME,
815 .match_table = hwicap_of_match,
816 .probe = hwicap_of_probe,
817 .remove = __devexit_p(hwicap_of_remove),
818 .driver = {
819 .name = DRIVER_NAME,
820 },
821};
822
823/* Registration helpers to keep the number of #ifdefs to a minimum */
824static inline int __devinit hwicap_of_register(void)
825{
826 pr_debug("hwicap: calling of_register_platform_driver()\n");
827 return of_register_platform_driver(&hwicap_of_driver);
828}
829
830static inline void __devexit hwicap_of_unregister(void)
831{
832 of_unregister_platform_driver(&hwicap_of_driver);
833}
834#else /* CONFIG_OF */
835/* CONFIG_OF not enabled; do nothing helpers */
836static inline int __devinit hwicap_of_register(void) { return 0; }
837static inline void __devexit hwicap_of_unregister(void) { }
838#endif /* CONFIG_OF */
839
840static int __devinit hwicap_module_init(void)
841{
842 dev_t devt;
843 int retval;
844
845 icap_class = class_create(THIS_MODULE, "xilinx_config");
846
847 if (xhwicap_major) {
848 devt = MKDEV(xhwicap_major, xhwicap_minor);
849 retval = register_chrdev_region(
850 devt,
851 HWICAP_DEVICES,
852 DRIVER_NAME);
853 if (retval < 0)
854 return retval;
855 } else {
856 retval = alloc_chrdev_region(&devt,
857 xhwicap_minor,
858 HWICAP_DEVICES,
859 DRIVER_NAME);
860 if (retval < 0)
861 return retval;
862 xhwicap_major = MAJOR(devt);
863 }
864
865 retval = platform_driver_register(&hwicap_platform_driver);
866
867 if (retval)
868 goto failed1;
869
870 retval = hwicap_of_register();
871
872 if (retval)
873 goto failed2;
874
875 return retval;
876
877 failed2:
878 platform_driver_unregister(&hwicap_platform_driver);
879
880 failed1:
881 unregister_chrdev_region(devt, HWICAP_DEVICES);
882
883 return retval;
884}
885
886static void __devexit hwicap_module_cleanup(void)
887{
888 dev_t devt = MKDEV(xhwicap_major, xhwicap_minor);
889
890 class_destroy(icap_class);
891
892 platform_driver_unregister(&hwicap_platform_driver);
893
894 hwicap_of_unregister();
895
896 unregister_chrdev_region(devt, HWICAP_DEVICES);
897}
898
899module_init(hwicap_module_init);
900module_exit(hwicap_module_cleanup);
901
902MODULE_AUTHOR("Xilinx, Inc; Xilinx Research Labs Group");
903MODULE_DESCRIPTION("Xilinx ICAP Port Driver");
904MODULE_LICENSE("GPL");
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.h b/drivers/char/xilinx_hwicap/xilinx_hwicap.h
new file mode 100644
index 000000000000..ae771cac1629
--- /dev/null
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.h
@@ -0,0 +1,193 @@
1/*****************************************************************************
2 *
3 * Author: Xilinx, Inc.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
11 * AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND
12 * SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,
13 * OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,
14 * APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION
15 * THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
16 * AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
17 * FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
18 * WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
19 * IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
20 * REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
21 * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 * FOR A PARTICULAR PURPOSE.
23 *
24 * Xilinx products are not intended for use in life support appliances,
25 * devices, or systems. Use in such applications is expressly prohibited.
26 *
27 * (c) Copyright 2003-2007 Xilinx Inc.
28 * All rights reserved.
29 *
30 * You should have received a copy of the GNU General Public License along
31 * with this program; if not, write to the Free Software Foundation, Inc.,
32 * 675 Mass Ave, Cambridge, MA 02139, USA.
33 *
34 *****************************************************************************/
35
36#ifndef XILINX_HWICAP_H_ /* prevent circular inclusions */
37#define XILINX_HWICAP_H_ /* by using protection macros */
38
39#include <linux/types.h>
40#include <linux/cdev.h>
41#include <linux/version.h>
42#include <linux/platform_device.h>
43
44#include <asm/io.h>
45
46struct hwicap_drvdata {
47 u32 write_buffer_in_use; /* Always in [0,3] */
48 u8 write_buffer[4];
49 u32 read_buffer_in_use; /* Always in [0,3] */
50 u8 read_buffer[4];
51 u32 mem_start; /* phys. address of the control registers */
52 u32 mem_end; /* phys. address of the control registers */
53 u32 mem_size;
54 void __iomem *base_address;/* virt. address of the control registers */
55
56 struct device *dev;
57 struct cdev cdev; /* Char device structure */
58 dev_t devt;
59
60 const struct hwicap_driver_config *config;
61 const struct config_registers *config_regs;
62 void *private_data;
63 bool is_open;
64 struct semaphore sem;
65};
66
67struct hwicap_driver_config {
68 int (*get_configuration)(struct hwicap_drvdata *drvdata, u32 *data,
69 u32 size);
70 int (*set_configuration)(struct hwicap_drvdata *drvdata, u32 *data,
71 u32 size);
72 void (*reset)(struct hwicap_drvdata *drvdata);
73};
74
75/* Number of times to poll the done regsiter */
76#define XHI_MAX_RETRIES 10
77
78/************ Constant Definitions *************/
79
80#define XHI_PAD_FRAMES 0x1
81
82/* Mask for calculating configuration packet headers */
83#define XHI_WORD_COUNT_MASK_TYPE_1 0x7FFUL
84#define XHI_WORD_COUNT_MASK_TYPE_2 0x1FFFFFUL
85#define XHI_TYPE_MASK 0x7
86#define XHI_REGISTER_MASK 0xF
87#define XHI_OP_MASK 0x3
88
89#define XHI_TYPE_SHIFT 29
90#define XHI_REGISTER_SHIFT 13
91#define XHI_OP_SHIFT 27
92
93#define XHI_TYPE_1 1
94#define XHI_TYPE_2 2
95#define XHI_OP_WRITE 2
96#define XHI_OP_READ 1
97
98/* Address Block Types */
99#define XHI_FAR_CLB_BLOCK 0
100#define XHI_FAR_BRAM_BLOCK 1
101#define XHI_FAR_BRAM_INT_BLOCK 2
102
103struct config_registers {
104 u32 CRC;
105 u32 FAR;
106 u32 FDRI;
107 u32 FDRO;
108 u32 CMD;
109 u32 CTL;
110 u32 MASK;
111 u32 STAT;
112 u32 LOUT;
113 u32 COR;
114 u32 MFWR;
115 u32 FLR;
116 u32 KEY;
117 u32 CBC;
118 u32 IDCODE;
119 u32 AXSS;
120 u32 C0R_1;
121 u32 CSOB;
122 u32 WBSTAR;
123 u32 TIMER;
124 u32 BOOTSTS;
125 u32 CTL_1;
126};
127
128/* Configuration Commands */
129#define XHI_CMD_NULL 0
130#define XHI_CMD_WCFG 1
131#define XHI_CMD_MFW 2
132#define XHI_CMD_DGHIGH 3
133#define XHI_CMD_RCFG 4
134#define XHI_CMD_START 5
135#define XHI_CMD_RCAP 6
136#define XHI_CMD_RCRC 7
137#define XHI_CMD_AGHIGH 8
138#define XHI_CMD_SWITCH 9
139#define XHI_CMD_GRESTORE 10
140#define XHI_CMD_SHUTDOWN 11
141#define XHI_CMD_GCAPTURE 12
142#define XHI_CMD_DESYNCH 13
143#define XHI_CMD_IPROG 15 /* Only in Virtex5 */
144#define XHI_CMD_CRCC 16 /* Only in Virtex5 */
145#define XHI_CMD_LTIMER 17 /* Only in Virtex5 */
146
147/* Packet constants */
148#define XHI_SYNC_PACKET 0xAA995566UL
149#define XHI_DUMMY_PACKET 0xFFFFFFFFUL
150#define XHI_NOOP_PACKET (XHI_TYPE_1 << XHI_TYPE_SHIFT)
151#define XHI_TYPE_2_READ ((XHI_TYPE_2 << XHI_TYPE_SHIFT) | \
152 (XHI_OP_READ << XHI_OP_SHIFT))
153
154#define XHI_TYPE_2_WRITE ((XHI_TYPE_2 << XHI_TYPE_SHIFT) | \
155 (XHI_OP_WRITE << XHI_OP_SHIFT))
156
157#define XHI_TYPE2_CNT_MASK 0x07FFFFFF
158
159#define XHI_TYPE_1_PACKET_MAX_WORDS 2047UL
160#define XHI_TYPE_1_HEADER_BYTES 4
161#define XHI_TYPE_2_HEADER_BYTES 8
162
163/* Constant to use for CRC check when CRC has been disabled */
164#define XHI_DISABLED_AUTO_CRC 0x0000DEFCUL
165
166/**
167 * hwicap_type_1_read: Generates a Type 1 read packet header.
168 * @parameter: Register is the address of the register to be read back.
169 *
170 * Generates a Type 1 read packet header, which is used to indirectly
171 * read registers in the configuration logic. This packet must then
172 * be sent through the icap device, and a return packet received with
173 * the information.
174 **/
175static inline u32 hwicap_type_1_read(u32 Register)
176{
177 return (XHI_TYPE_1 << XHI_TYPE_SHIFT) |
178 (Register << XHI_REGISTER_SHIFT) |
179 (XHI_OP_READ << XHI_OP_SHIFT);
180}
181
182/**
183 * hwicap_type_1_write: Generates a Type 1 write packet header
184 * @parameter: Register is the address of the register to be read back.
185 **/
186static inline u32 hwicap_type_1_write(u32 Register)
187{
188 return (XHI_TYPE_1 << XHI_TYPE_SHIFT) |
189 (Register << XHI_REGISTER_SHIFT) |
190 (XHI_OP_WRITE << XHI_OP_SHIFT);
191}
192
193#endif