diff options
Diffstat (limited to 'drivers/char/xilinx_hwicap/xilinx_hwicap.c')
| -rw-r--r-- | drivers/char/xilinx_hwicap/xilinx_hwicap.c | 188 |
1 files changed, 42 insertions, 146 deletions
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c index 067396bedf22..34a345dc5e72 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c @@ -84,18 +84,13 @@ #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 <linux/io.h> #include <linux/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 "xilinx_hwicap.h" #include "buffer_icap.h" #include "fifo_icap.h" @@ -113,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 @@ -241,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, @@ -297,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, @@ -384,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; @@ -599,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"); @@ -634,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) { 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"); - retval = -ENOMEM; - 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); @@ -721,53 +685,22 @@ static struct hwicap_driver_config fifo_icap_config = { .reset = fifo_icap_reset, }; -static int hwicap_remove(struct device *dev) -{ - struct hwicap_drvdata *drvdata; - - 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); - - 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 */ regs = &v4_config_registers; - family = of_get_property(op->dev.of_node, "xlnx,family", NULL); - - if (family) { + 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")) @@ -777,60 +710,24 @@ static int hwicap_of_probe(struct platform_device *op, 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}, @@ -838,9 +735,6 @@ 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, @@ -856,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); @@ -882,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); |
