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/slab.h> 15 16#define DRIVER_NAME "uio_pdrv" 17 18struct uio_platdata { 19 struct uio_info *uioinfo; 20}; 21 22static int uio_pdrv_probe(struct platform_device *pdev) 23{ 24 struct uio_info *uioinfo = pdev->dev.platform_data; 25 struct uio_platdata *pdata; 26 struct uio_mem *uiomem; 27 int ret = -ENODEV; 28 int i; 29 30 if (!uioinfo || !uioinfo->name || !uioinfo->version) { 31 dev_dbg(&pdev->dev, "%s: err_uioinfo\n", __func__); 32 goto err_uioinfo; 33 } 34 35 pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); 36 if (!pdata) { 37 ret = -ENOMEM; 38 dev_dbg(&pdev->dev, "%s: err_alloc_pdata\n", __func__); 39 goto err_alloc_pdata; 40 } 41 42 pdata->uioinfo = uioinfo; 43 44 uiomem = &uioinfo->mem[0]; 45 46 for (i = 0; i < pdev->num_resources; ++i) { 47 struct resource *r = &pdev->resource[i]; 48 49 if (r->flags != IORESOURCE_MEM) 50 continue; 51 52 if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) { 53 dev_warn(&pdev->dev, "device has more than " 54 __stringify(MAX_UIO_MAPS) 55 " I/O memory resources.\n"); 56 break; 57 } 58 59 uiomem->memtype = UIO_MEM_PHYS; 60 uiomem->addr = r->start; 61 uiomem->size = r->end - r->start + 1; 62 ++uiomem; 63 } 64 65 while (uiomem < &uioinfo->mem[MAX_UIO_MAPS]) { 66 uiomem->size = 0; 67 ++uiomem; 68 } 69 70 pdata->uioinfo->priv = pdata; 71 72 ret = uio_register_device(&pdev->dev, pdata->uioinfo); 73 74 if (ret) { 75 kfree(pdata); 76err_alloc_pdata: 77err_uioinfo: 78 return ret; 79 } 80 81 platform_set_drvdata(pdev, pdata); 82 83 return 0; 84} 85 86static int uio_pdrv_remove(struct platform_device *pdev) 87{ 88 struct uio_platdata *pdata = platform_get_drvdata(pdev); 89 90 uio_unregister_device(pdata->uioinfo); 91 92 kfree(pdata); 93 94 return 0; 95} 96 97static struct platform_driver uio_pdrv = { 98 .probe = uio_pdrv_probe, 99 .remove = uio_pdrv_remove, 100 .driver = { 101 .name = DRIVER_NAME, 102 .owner = THIS_MODULE, 103 }, 104}; 105 106static int __init uio_pdrv_init(void) 107{ 108 return platform_driver_register(&uio_pdrv); 109} 110 111static void __exit uio_pdrv_exit(void) 112{ 113 platform_driver_unregister(&uio_pdrv); 114} 115module_init(uio_pdrv_init); 116module_exit(uio_pdrv_exit); 117 118MODULE_AUTHOR("Uwe Kleine-Koenig"); 119MODULE_DESCRIPTION("Userspace I/O platform driver"); 120MODULE_LICENSE("GPL v2"); 121MODULE_ALIAS("platform:" DRIVER_NAME); 122