uio_pdrv.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  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. #include <linux/module.h>
  15. #include <linux/slab.h>
  16. #define DRIVER_NAME "uio_pdrv"
  17. struct uio_platdata {
  18. struct uio_info *uioinfo;
  19. };
  20. static int uio_pdrv_probe(struct platform_device *pdev)
  21. {
  22. struct uio_info *uioinfo = pdev->dev.platform_data;
  23. struct uio_platdata *pdata;
  24. struct uio_mem *uiomem;
  25. int ret = -ENODEV;
  26. int i;
  27. if (!uioinfo || !uioinfo->name || !uioinfo->version) {
  28. dev_dbg(&pdev->dev, "%s: err_uioinfo\n", __func__);
  29. goto err_uioinfo;
  30. }
  31. pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
  32. if (!pdata) {
  33. ret = -ENOMEM;
  34. dev_dbg(&pdev->dev, "%s: err_alloc_pdata\n", __func__);
  35. goto err_alloc_pdata;
  36. }
  37. pdata->uioinfo = uioinfo;
  38. uiomem = &uioinfo->mem[0];
  39. for (i = 0; i < pdev->num_resources; ++i) {
  40. struct resource *r = &pdev->resource[i];
  41. if (r->flags != IORESOURCE_MEM)
  42. continue;
  43. if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) {
  44. dev_warn(&pdev->dev, "device has more than "
  45. __stringify(MAX_UIO_MAPS)
  46. " I/O memory resources.\n");
  47. break;
  48. }
  49. uiomem->memtype = UIO_MEM_PHYS;
  50. uiomem->addr = r->start;
  51. uiomem->size = resource_size(r);
  52. ++uiomem;
  53. }
  54. while (uiomem < &uioinfo->mem[MAX_UIO_MAPS]) {
  55. uiomem->size = 0;
  56. ++uiomem;
  57. }
  58. pdata->uioinfo->priv = pdata;
  59. ret = uio_register_device(&pdev->dev, pdata->uioinfo);
  60. if (ret) {
  61. kfree(pdata);
  62. err_alloc_pdata:
  63. err_uioinfo:
  64. return ret;
  65. }
  66. platform_set_drvdata(pdev, pdata);
  67. return 0;
  68. }
  69. static int uio_pdrv_remove(struct platform_device *pdev)
  70. {
  71. struct uio_platdata *pdata = platform_get_drvdata(pdev);
  72. uio_unregister_device(pdata->uioinfo);
  73. kfree(pdata);
  74. return 0;
  75. }
  76. static struct platform_driver uio_pdrv = {
  77. .probe = uio_pdrv_probe,
  78. .remove = uio_pdrv_remove,
  79. .driver = {
  80. .name = DRIVER_NAME,
  81. .owner = THIS_MODULE,
  82. },
  83. };
  84. module_platform_driver(uio_pdrv);
  85. MODULE_AUTHOR("Uwe Kleine-Koenig");
  86. MODULE_DESCRIPTION("Userspace I/O platform driver");
  87. MODULE_LICENSE("GPL v2");
  88. MODULE_ALIAS("platform:" DRIVER_NAME);