diff options
Diffstat (limited to 'drivers/char/xilinx_hwicap/xilinx_hwicap.c')
| -rw-r--r-- | drivers/char/xilinx_hwicap/xilinx_hwicap.c | 218 |
1 files changed, 58 insertions, 160 deletions
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c index 5224da5202d3..34a345dc5e72 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c @@ -84,18 +84,12 @@ #include <linux/sysctl.h> #include <linux/fs.h> #include <linux/cdev.h> +#include <linux/of.h> #include <linux/platform_device.h> +#include <linux/property.h> #include <linux/slab.h> - -#include <asm/io.h> -#include <asm/uaccess.h> - -#ifdef CONFIG_OF -/* For open firmware. */ -#include <linux/of_address.h> -#include <linux/of_device.h> -#include <linux/of_platform.h> -#endif +#include <linux/io.h> +#include <linux/uaccess.h> #include "xilinx_hwicap.h" #include "buffer_icap.h" @@ -114,7 +108,9 @@ static DEFINE_MUTEX(hwicap_mutex); static bool probed_devices[HWICAP_DEVICES]; static struct mutex icap_sem; -static struct class *icap_class; +static const struct class icap_class = { + .name = "xilinx_config", +}; #define UNIMPLEMENTED 0xFFFF @@ -222,6 +218,8 @@ static const struct config_registers v6_config_registers = { * hwicap_command_desync - Send a DESYNC command to the ICAP port. * @drvdata: a pointer to the drvdata. * + * Returns: '0' on success and failure value on error + * * This command desynchronizes the ICAP After this command, a * bitstream containing a NULL packet, followed by a SYNCH packet is * required before the ICAP will recognize commands. @@ -240,7 +238,7 @@ static int hwicap_command_desync(struct hwicap_drvdata *drvdata) buffer[index++] = XHI_NOOP_PACKET; /* - * Write the data to the FIFO and intiate the transfer of data present + * Write the data to the FIFO and initiate the transfer of data present * in the FIFO to the ICAP device. */ return drvdata->config->set_configuration(drvdata, @@ -251,10 +249,12 @@ static int hwicap_command_desync(struct hwicap_drvdata *drvdata) * hwicap_get_configuration_register - Query a configuration register. * @drvdata: a pointer to the drvdata. * @reg: a constant which represents the configuration - * register value to be returned. - * Examples: XHI_IDCODE, XHI_FLR. + * register value to be returned. + * Examples: XHI_IDCODE, XHI_FLR. * @reg_data: returns the value of the register. * + * Returns: '0' on success and failure value on error + * * Sends a query packet to the ICAP and then receives the response. * The icap is left in Synched state. */ @@ -294,7 +294,7 @@ static int hwicap_get_configuration_register(struct hwicap_drvdata *drvdata, buffer[index++] = XHI_NOOP_PACKET; /* - * Write the data to the FIFO and intiate the transfer of data present + * 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, @@ -320,7 +320,8 @@ static int hwicap_initialize_hwicap(struct hwicap_drvdata *drvdata) dev_dbg(drvdata->dev, "initializing\n"); /* Abort any current transaction, to make sure we have the - * ICAP in a good state. */ + * ICAP in a good state. + */ dev_dbg(drvdata->dev, "Reset...\n"); drvdata->config->reset(drvdata); @@ -380,7 +381,7 @@ hwicap_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) drvdata->read_buffer + bytes_to_read, 4 - bytes_to_read); } else { - /* Get new data from the ICAP, and return was was requested. */ + /* Get new data from the ICAP, and return what was requested. */ kbuf = (u32 *) get_zeroed_page(GFP_KERNEL); if (!kbuf) { status = -ENOMEM; @@ -595,14 +596,14 @@ static const struct file_operations hwicap_fops = { .llseek = noop_llseek, }; -static int hwicap_setup(struct device *dev, int id, - const struct resource *regs_res, +static int hwicap_setup(struct platform_device *pdev, int id, const struct hwicap_driver_config *config, const struct config_registers *config_regs) { dev_t devt; struct hwicap_drvdata *drvdata = NULL; - int retval = 0; + struct device *dev = &pdev->dev; + int retval; dev_info(dev, "Xilinx icap port driver\n"); @@ -630,72 +631,39 @@ static int hwicap_setup(struct device *dev, int id, devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR + id); - drvdata = kzalloc(sizeof(struct hwicap_drvdata), GFP_KERNEL); + drvdata = devm_kzalloc(dev, sizeof(struct hwicap_drvdata), GFP_KERNEL); if (!drvdata) { - dev_err(dev, "Couldn't allocate device private record\n"); retval = -ENOMEM; - goto failed0; - } - dev_set_drvdata(dev, (void *)drvdata); - - if (!regs_res) { - dev_err(dev, "Couldn't get registers resource\n"); - retval = -EFAULT; - goto failed1; + goto failed; } + dev_set_drvdata(dev, drvdata); - drvdata->mem_start = regs_res->start; - drvdata->mem_end = regs_res->end; - drvdata->mem_size = resource_size(regs_res); - - if (!request_mem_region(drvdata->mem_start, - drvdata->mem_size, DRIVER_NAME)) { - dev_err(dev, "Couldn't lock memory region at %Lx\n", - (unsigned long long) regs_res->start); - retval = -EBUSY; - goto failed1; + drvdata->base_address = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(drvdata->base_address)) { + retval = PTR_ERR(drvdata->base_address); + goto failed; } drvdata->devt = devt; drvdata->dev = dev; - drvdata->base_address = ioremap(drvdata->mem_start, drvdata->mem_size); - if (!drvdata->base_address) { - dev_err(dev, "ioremap() failed\n"); - goto failed2; - } - drvdata->config = config; drvdata->config_regs = config_regs; mutex_init(&drvdata->sem); drvdata->is_open = 0; - dev_info(dev, "ioremap %llx to %p with size %llx\n", - (unsigned long long) drvdata->mem_start, - drvdata->base_address, - (unsigned long long) drvdata->mem_size); - cdev_init(&drvdata->cdev, &hwicap_fops); drvdata->cdev.owner = THIS_MODULE; retval = cdev_add(&drvdata->cdev, devt, 1); if (retval) { dev_err(dev, "cdev_add() failed\n"); - goto failed3; + goto failed; } - device_create(icap_class, dev, devt, NULL, "%s%d", DRIVER_NAME, id); + device_create(&icap_class, dev, devt, NULL, "%s%d", DRIVER_NAME, id); return 0; /* success */ - failed3: - iounmap(drvdata->base_address); - - failed2: - release_mem_region(regs_res->start, drvdata->mem_size); - - failed1: - kfree(drvdata); - - failed0: + failed: mutex_lock(&icap_sem); probed_devices[id] = 0; mutex_unlock(&icap_sem); @@ -717,117 +685,49 @@ static struct hwicap_driver_config fifo_icap_config = { .reset = fifo_icap_reset, }; -static int hwicap_remove(struct device *dev) -{ - struct hwicap_drvdata *drvdata; - - drvdata = (struct hwicap_drvdata *)dev_get_drvdata(dev); - - if (!drvdata) - return 0; - - device_destroy(icap_class, drvdata->devt); - cdev_del(&drvdata->cdev); - iounmap(drvdata->base_address); - release_mem_region(drvdata->mem_start, drvdata->mem_size); - kfree(drvdata); - dev_set_drvdata(dev, NULL); - - mutex_lock(&icap_sem); - probed_devices[MINOR(dev->devt)-XHWICAP_MINOR] = 0; - mutex_unlock(&icap_sem); - return 0; /* success */ -} - -#ifdef CONFIG_OF -static int hwicap_of_probe(struct platform_device *op, - const struct hwicap_driver_config *config) +static int hwicap_drv_probe(struct platform_device *pdev) { - struct resource res; - const unsigned int *id; - const char *family; - int rc; const struct config_registers *regs; + const struct hwicap_driver_config *config; + const char *family; + int id = -1; + config = device_get_match_data(&pdev->dev); - rc = of_address_to_resource(op->dev.of_node, 0, &res); - if (rc) { - dev_err(&op->dev, "invalid address\n"); - return rc; - } - - id = of_get_property(op->dev.of_node, "port-number", NULL); + of_property_read_u32(pdev->dev.of_node, "port-number", &id); /* It's most likely that we're using V4, if the family is not - specified */ + * specified + */ regs = &v4_config_registers; - family = of_get_property(op->dev.of_node, "xlnx,family", NULL); - - if (family) { - if (!strcmp(family, "virtex2p")) { + if (!of_property_read_string(pdev->dev.of_node, "xlnx,family", &family)) { + if (!strcmp(family, "virtex2p")) regs = &v2_config_registers; - } else if (!strcmp(family, "virtex4")) { + else if (!strcmp(family, "virtex4")) regs = &v4_config_registers; - } else if (!strcmp(family, "virtex5")) { + else if (!strcmp(family, "virtex5")) regs = &v5_config_registers; - } else if (!strcmp(family, "virtex6")) { + else if (!strcmp(family, "virtex6")) regs = &v6_config_registers; - } } - return hwicap_setup(&op->dev, id ? *id : -1, &res, config, - regs); + return hwicap_setup(pdev, id, config, regs); } -#else -static inline int hwicap_of_probe(struct platform_device *op, - const struct hwicap_driver_config *config) -{ - return -EINVAL; -} -#endif /* CONFIG_OF */ -static const struct of_device_id hwicap_of_match[]; -static int hwicap_drv_probe(struct platform_device *pdev) +static void hwicap_drv_remove(struct platform_device *pdev) { - const struct of_device_id *match; - struct resource *res; - const struct config_registers *regs; - const char *family; - - match = of_match_device(hwicap_of_match, &pdev->dev); - if (match) - return hwicap_of_probe(pdev, match->data); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENODEV; - - /* It's most likely that we're using V4, if the family is not - specified */ - regs = &v4_config_registers; - family = pdev->dev.platform_data; + struct device *dev = &pdev->dev; + struct hwicap_drvdata *drvdata; - if (family) { - if (!strcmp(family, "virtex2p")) { - regs = &v2_config_registers; - } else if (!strcmp(family, "virtex4")) { - regs = &v4_config_registers; - } else if (!strcmp(family, "virtex5")) { - regs = &v5_config_registers; - } else if (!strcmp(family, "virtex6")) { - regs = &v6_config_registers; - } - } + drvdata = dev_get_drvdata(dev); - return hwicap_setup(&pdev->dev, pdev->id, res, - &buffer_icap_config, regs); -} + device_destroy(&icap_class, drvdata->devt); + cdev_del(&drvdata->cdev); -static int hwicap_drv_remove(struct platform_device *pdev) -{ - return hwicap_remove(&pdev->dev); + mutex_lock(&icap_sem); + probed_devices[MINOR(dev->devt)-XHWICAP_MINOR] = 0; + mutex_unlock(&icap_sem); } -#ifdef CONFIG_OF /* Match table for device tree binding */ static const struct of_device_id hwicap_of_match[] = { { .compatible = "xlnx,opb-hwicap-1.00.b", .data = &buffer_icap_config}, @@ -835,15 +735,11 @@ static const struct of_device_id hwicap_of_match[] = { {}, }; MODULE_DEVICE_TABLE(of, hwicap_of_match); -#else -#define hwicap_of_match NULL -#endif static struct platform_driver hwicap_platform_driver = { .probe = hwicap_drv_probe, .remove = hwicap_drv_remove, .driver = { - .owner = THIS_MODULE, .name = DRIVER_NAME, .of_match_table = hwicap_of_match, }, @@ -854,7 +750,9 @@ static int __init hwicap_module_init(void) dev_t devt; int retval; - icap_class = class_create(THIS_MODULE, "xilinx_config"); + retval = class_register(&icap_class); + if (retval) + return retval; mutex_init(&icap_sem); devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR); @@ -880,7 +778,7 @@ static void __exit hwicap_module_cleanup(void) { dev_t devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR); - class_destroy(icap_class); + class_unregister(&icap_class); platform_driver_unregister(&hwicap_platform_driver); |
