*****************************************************************************/
/*
- * This is the code behind /dev/xilinx_icap -- it allows a user-space
+ * This is the code behind /dev/icap* -- it allows a user-space
* application to use the Xilinx ICAP subsystem.
*
* The following operations are possible:
* user-space application code that uses this device. The simplest
* way to use this interface is simply:
*
- * cp foo.bit /dev/xilinx_icap
+ * cp foo.bit /dev/icap0
*
* Note that unless foo.bit is an appropriately constructed partial
* bitstream, this has a high likelyhood of overwriting the design
#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <linux/mutex.h>
+#include <linux/smp_lock.h>
#include <linux/sysctl.h>
#include <linux/version.h>
#include <linux/fs.h>
#include "buffer_icap.h"
#include "fifo_icap.h"
-#define DRIVER_NAME "xilinx_icap"
+#define DRIVER_NAME "icap"
#define HWICAP_REGS (0x10000)
-/* dynamically allocate device number */
-static int xhwicap_major;
-static int xhwicap_minor;
+#define XHWICAP_MAJOR 259
+#define XHWICAP_MINOR 0
#define HWICAP_DEVICES 1
-module_param(xhwicap_major, int, S_IRUGO);
-module_param(xhwicap_minor, int, S_IRUGO);
-
/* An array, which is set to true when the device is registered. */
static bool probed_devices[HWICAP_DEVICES];
static struct mutex icap_sem;
* Create the data to be written to the ICAP.
*/
buffer[index++] = XHI_DUMMY_PACKET;
+ buffer[index++] = XHI_NOOP_PACKET;
buffer[index++] = XHI_SYNC_PACKET;
buffer[index++] = XHI_NOOP_PACKET;
+ buffer[index++] = XHI_NOOP_PACKET;
+
+ /*
+ * Write the data to the FIFO and initiate the transfer of data present
+ * in the FIFO to the ICAP device.
+ */
+ status = drvdata->config->set_configuration(drvdata,
+ &buffer[0], index);
+ if (status)
+ return status;
+
+ /* If the syncword was not found, then we need to start over. */
+ status = drvdata->config->get_status(drvdata);
+ if ((status & XHI_SR_DALIGN_MASK) != XHI_SR_DALIGN_MASK)
+ return -EIO;
+
+ index = 0;
buffer[index++] = hwicap_type_1_read(reg) | 1;
buffer[index++] = XHI_NOOP_PACKET;
buffer[index++] = XHI_NOOP_PACKET;
struct hwicap_drvdata *drvdata;
int status;
+ lock_kernel();
drvdata = container_of(inode->i_cdev, struct hwicap_drvdata, cdev);
status = mutex_lock_interruptible(&drvdata->sem);
if (status)
- return status;
+ goto out;
if (drvdata->is_open) {
status = -EBUSY;
error:
mutex_unlock(&drvdata->sem);
+ out:
+ unlock_kernel();
return status;
}
probed_devices[id] = 1;
mutex_unlock(&icap_sem);
- devt = MKDEV(xhwicap_major, xhwicap_minor + id);
+ devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR + id);
drvdata = kzalloc(sizeof(struct hwicap_drvdata), GFP_KERNEL);
if (!drvdata) {
if (!request_mem_region(drvdata->mem_start,
drvdata->mem_size, DRIVER_NAME)) {
- dev_err(dev, "Couldn't lock memory region at %p\n",
- (void *)regs_res->start);
+ dev_err(dev, "Couldn't lock memory region at %Lx\n",
+ regs_res->start);
retval = -EBUSY;
goto failed1;
}
mutex_init(&drvdata->sem);
drvdata->is_open = 0;
- dev_info(dev, "ioremap %lx to %p with size %x\n",
+ dev_info(dev, "ioremap %lx to %p with size %Lx\n",
(unsigned long int)drvdata->mem_start,
drvdata->base_address, drvdata->mem_size);
static struct hwicap_driver_config buffer_icap_config = {
.get_configuration = buffer_icap_get_configuration,
.set_configuration = buffer_icap_set_configuration,
+ .get_status = buffer_icap_get_status,
.reset = buffer_icap_reset,
};
static struct hwicap_driver_config fifo_icap_config = {
.get_configuration = fifo_icap_get_configuration,
.set_configuration = fifo_icap_set_configuration,
+ .get_status = fifo_icap_get_status,
.reset = fifo_icap_reset,
};
dev_set_drvdata(dev, NULL);
mutex_lock(&icap_sem);
- probed_devices[MINOR(dev->devt)-xhwicap_minor] = 0;
+ probed_devices[MINOR(dev->devt)-XHWICAP_MINOR] = 0;
mutex_unlock(&icap_sem);
return 0; /* success */
}
}
/* Match table for of_platform binding */
-static const struct of_device_id __devinit hwicap_of_match[] = {
+static const struct of_device_id __devinitconst hwicap_of_match[] = {
{ .compatible = "xlnx,opb-hwicap-1.00.b", .data = &buffer_icap_config},
{ .compatible = "xlnx,xps-hwicap-1.00.a", .data = &fifo_icap_config},
{},
icap_class = class_create(THIS_MODULE, "xilinx_config");
mutex_init(&icap_sem);
- if (xhwicap_major) {
- devt = MKDEV(xhwicap_major, xhwicap_minor);
- retval = register_chrdev_region(
- devt,
- HWICAP_DEVICES,
- DRIVER_NAME);
- if (retval < 0)
- return retval;
- } else {
- retval = alloc_chrdev_region(&devt,
- xhwicap_minor,
- HWICAP_DEVICES,
- DRIVER_NAME);
- if (retval < 0)
- return retval;
- xhwicap_major = MAJOR(devt);
- }
+ devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR);
+ retval = register_chrdev_region(devt,
+ HWICAP_DEVICES,
+ DRIVER_NAME);
+ if (retval < 0)
+ return retval;
retval = platform_driver_register(&hwicap_platform_driver);
static void __exit hwicap_module_cleanup(void)
{
- dev_t devt = MKDEV(xhwicap_major, xhwicap_minor);
+ dev_t devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR);
class_destroy(icap_class);