Commit 4d80d59437247075029534adec8d69fce2cfb87a

Authored by Uwe Kleine-König
Committed by Greg Kroah-Hartman
1 parent 328a14e70e

UIO: add generic UIO platform driver

This patch adds a generic UIO platform driver. It eliminates the need for a
dedicated kernel module for simple platform devices. Users only need to
implement their irq handler in platform code and fill a struct uio_info
there. This helps avoiding code duplication as UIO platform drivers often
share a lot of common code.

Signed-off-by: Uwe Kleine-König <Uwe.Kleine-Koenig@digi.com>
Signed-off-by: Hans J. Koch <hjk@linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

Showing 3 changed files with 126 additions and 0 deletions Side-by-side Diff

... ... @@ -26,6 +26,13 @@
26 26 To compile this driver as a module, choose M here: the module
27 27 will be called uio_cif.
28 28  
  29 +config UIO_PDRV
  30 + tristate "Userspace I/O platform driver"
  31 + help
  32 + Generic platform driver for Userspace I/O devices.
  33 +
  34 + If you don't know what to do here, say N.
  35 +
29 36 config UIO_SMX
30 37 tristate "SMX cryptengine UIO interface"
31 38 default n
drivers/uio/Makefile
1 1 obj-$(CONFIG_UIO) += uio.o
2 2 obj-$(CONFIG_UIO_CIF) += uio_cif.o
  3 +obj-$(CONFIG_UIO_PDRV) += uio_pdrv.o
3 4 obj-$(CONFIG_UIO_SMX) += uio_smx.o
drivers/uio/uio_pdrv.c
  1 +/*
  2 + * drivers/uio/uio_pdrv.c
  3 + *
  4 + * Copyright (C) 2008 by Digi International Inc.
  5 + * All rights reserved.
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify it
  8 + * under the terms of the GNU General Public License version 2 as published by
  9 + * the Free Software Foundation.
  10 + */
  11 +#include <linux/platform_device.h>
  12 +#include <linux/uio_driver.h>
  13 +#include <linux/stringify.h>
  14 +
  15 +#define DRIVER_NAME "uio"
  16 +
  17 +struct uio_platdata {
  18 + struct uio_info *uioinfo;
  19 +};
  20 +
  21 +static int uio_pdrv_probe(struct platform_device *pdev)
  22 +{
  23 + struct uio_info *uioinfo = pdev->dev.platform_data;
  24 + struct uio_platdata *pdata;
  25 + struct uio_mem *uiomem;
  26 + int ret = -ENODEV;
  27 + int i;
  28 +
  29 + if (!uioinfo || !uioinfo->name || !uioinfo->version) {
  30 + dev_dbg(&pdev->dev, "%s: err_uioinfo\n", __func__);
  31 + goto err_uioinfo;
  32 + }
  33 +
  34 + pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
  35 + if (!pdata) {
  36 + ret = -ENOMEM;
  37 + dev_dbg(&pdev->dev, "%s: err_alloc_pdata\n", __func__);
  38 + goto err_alloc_pdata;
  39 + }
  40 +
  41 + pdata->uioinfo = uioinfo;
  42 +
  43 + uiomem = &uioinfo->mem[0];
  44 +
  45 + for (i = 0; i < pdev->num_resources; ++i) {
  46 + struct resource *r = &pdev->resource[i];
  47 +
  48 + if (r->flags != IORESOURCE_MEM)
  49 + continue;
  50 +
  51 + if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) {
  52 + dev_warn(&pdev->dev, "device has more than "
  53 + __stringify(MAX_UIO_MAPS)
  54 + " I/O memory resources.\n");
  55 + break;
  56 + }
  57 +
  58 + uiomem->memtype = UIO_MEM_PHYS;
  59 + uiomem->addr = r->start;
  60 + uiomem->size = r->end - r->start + 1;
  61 + ++uiomem;
  62 + }
  63 +
  64 + while (uiomem < &uioinfo->mem[MAX_UIO_MAPS]) {
  65 + uiomem->size = 0;
  66 + ++uiomem;
  67 + }
  68 +
  69 + pdata->uioinfo->priv = pdata;
  70 +
  71 + ret = uio_register_device(&pdev->dev, pdata->uioinfo);
  72 +
  73 + if (ret) {
  74 + kfree(pdata);
  75 +err_alloc_pdata:
  76 +err_uioinfo:
  77 + return ret;
  78 + }
  79 +
  80 + platform_set_drvdata(pdev, pdata);
  81 +
  82 + return 0;
  83 +}
  84 +
  85 +static int uio_pdrv_remove(struct platform_device *pdev)
  86 +{
  87 + struct uio_platdata *pdata = platform_get_drvdata(pdev);
  88 +
  89 + uio_unregister_device(pdata->uioinfo);
  90 +
  91 + return 0;
  92 +}
  93 +
  94 +static struct platform_driver uio_pdrv = {
  95 + .probe = uio_pdrv_probe,
  96 + .remove = uio_pdrv_remove,
  97 + .driver = {
  98 + .name = DRIVER_NAME,
  99 + .owner = THIS_MODULE,
  100 + },
  101 +};
  102 +
  103 +static int __init uio_pdrv_init(void)
  104 +{
  105 + return platform_driver_register(&uio_pdrv);
  106 +}
  107 +
  108 +static void __exit uio_pdrv_exit(void)
  109 +{
  110 + platform_driver_unregister(&uio_pdrv);
  111 +}
  112 +module_init(uio_pdrv_init);
  113 +module_exit(uio_pdrv_exit);
  114 +
  115 +MODULE_AUTHOR("Uwe Kleine-Koenig");
  116 +MODULE_DESCRIPTION("Userspace I/O platform driver");
  117 +MODULE_LICENSE("GPL");
  118 +MODULE_ALIAS("platform:" DRIVER_NAME);