#include <linux/types.h>
#include <linux/uaccess.h>
#include <linux/jiffies.h>
+#include <linux/miscdevice.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
* globals
* ----------------------------
*/
-
-static struct class *axis_fifo_driver_class; /* char device class */
-
static int read_timeout = 1000; /* ms to wait before read() times out */
static int write_timeout = 1000; /* ms to wait before write() times out */
unsigned int read_flags; /* read file flags */
struct device *dt_device; /* device created from the device tree */
- struct device *device; /* device associated with char_device */
- dev_t devt; /* our char device number */
- struct cdev char_device; /* our char device */
+ struct miscdevice miscdev;
};
/* ----------------------------
.attrs = axis_fifo_attrs,
};
+static const struct attribute_group *axis_fifo_attrs_groups[] = {
+ &axis_fifo_attrs_group,
+ NULL,
+};
+
/* ----------------------------
* implementation
* ----------------------------
static int axis_fifo_open(struct inode *inod, struct file *f)
{
- struct axis_fifo *fifo = (struct axis_fifo *)container_of(inod->i_cdev,
- struct axis_fifo, char_device);
+ struct axis_fifo *fifo = container_of(f->private_data,
+ struct axis_fifo, miscdev);
f->private_data = fifo;
if (((f->f_flags & O_ACCMODE) == O_WRONLY) ||
struct resource *r_mem; /* IO mem resources */
struct device *dev = &pdev->dev; /* OS device (from device tree) */
struct axis_fifo *fifo = NULL;
-
- char device_name[32];
-
+ char *device_name;
int rc = 0; /* error return value */
/* ----------------------------
* ----------------------------
*/
+ device_name = devm_kzalloc(dev, 32, GFP_KERNEL);
+ if (!device_name)
+ return -ENOMEM;
+
/* allocate device wrapper memory */
- fifo = devm_kmalloc(dev, sizeof(*fifo), GFP_KERNEL);
+ fifo = devm_kzalloc(dev, sizeof(*fifo), GFP_KERNEL);
if (!fifo)
return -ENOMEM;
dev_dbg(fifo->dt_device, "remapped memory to 0x%p\n", fifo->base_addr);
/* create unique device name */
- snprintf(device_name, sizeof(device_name), "%s_%pa",
- DRIVER_NAME, &r_mem->start);
-
+ snprintf(device_name, 32, "%s_%pa", DRIVER_NAME, &r_mem->start);
dev_dbg(fifo->dt_device, "device name [%s]\n", device_name);
/* ----------------------------
* ----------------------------
*/
- /* allocate device number */
- rc = alloc_chrdev_region(&fifo->devt, 0, 1, DRIVER_NAME);
+ /* create character device */
+ fifo->miscdev.fops = &fops;
+ fifo->miscdev.minor = MISC_DYNAMIC_MINOR;
+ fifo->miscdev.name = device_name;
+ fifo->miscdev.groups = axis_fifo_attrs_groups;
+ fifo->miscdev.parent = dev;
+ rc = misc_register(&fifo->miscdev);
if (rc < 0)
goto err_initial;
- dev_dbg(fifo->dt_device, "allocated device number major %i minor %i\n",
- MAJOR(fifo->devt), MINOR(fifo->devt));
-
- /* create driver file */
- fifo->device = device_create(axis_fifo_driver_class, NULL, fifo->devt,
- NULL, device_name);
- if (IS_ERR(fifo->device)) {
- dev_err(fifo->dt_device,
- "couldn't create driver file\n");
- rc = PTR_ERR(fifo->device);
- goto err_chrdev_region;
- }
- dev_set_drvdata(fifo->device, fifo);
-
- /* create character device */
- cdev_init(&fifo->char_device, &fops);
- rc = cdev_add(&fifo->char_device, fifo->devt, 1);
- if (rc < 0) {
- dev_err(fifo->dt_device, "couldn't create character device\n");
- goto err_dev;
- }
-
- /* create sysfs entries */
- rc = devm_device_add_group(fifo->device, &axis_fifo_attrs_group);
- if (rc < 0) {
- dev_err(fifo->dt_device, "couldn't register sysfs group\n");
- goto err_cdev;
- }
- dev_info(fifo->dt_device, "axis-fifo created at %pa mapped to 0x%pa, irq=%i, major=%i, minor=%i\n",
- &r_mem->start, &fifo->base_addr, fifo->irq,
- MAJOR(fifo->devt), MINOR(fifo->devt));
+ dev_info(fifo->dt_device, "axis-fifo created at %pa mapped to 0x%pa, irq=%i\n",
+ &r_mem->start, &fifo->base_addr, fifo->irq);
return 0;
-err_cdev:
- cdev_del(&fifo->char_device);
-err_dev:
- device_destroy(axis_fifo_driver_class, fifo->devt);
-err_chrdev_region:
- unregister_chrdev_region(fifo->devt, 1);
err_initial:
dev_set_drvdata(dev, NULL);
return rc;
struct device *dev = &pdev->dev;
struct axis_fifo *fifo = dev_get_drvdata(dev);
- cdev_del(&fifo->char_device);
- dev_set_drvdata(fifo->device, NULL);
- device_destroy(axis_fifo_driver_class, fifo->devt);
- unregister_chrdev_region(fifo->devt, 1);
+ misc_deregister(&fifo->miscdev);
dev_set_drvdata(dev, NULL);
return 0;
{
pr_info("axis-fifo driver loaded with parameters read_timeout = %i, write_timeout = %i\n",
read_timeout, write_timeout);
- axis_fifo_driver_class = class_create(THIS_MODULE, DRIVER_NAME);
- if (IS_ERR(axis_fifo_driver_class))
- return PTR_ERR(axis_fifo_driver_class);
return platform_driver_register(&axis_fifo_driver);
}
static void __exit axis_fifo_exit(void)
{
platform_driver_unregister(&axis_fifo_driver);
- class_destroy(axis_fifo_driver_class);
}
module_exit(axis_fifo_exit);