• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/drivers/uio/
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