]>
Commit | Line | Data |
---|---|---|
1802d0be | 1 | // SPDX-License-Identifier: GPL-2.0-only |
36fe431f AM |
2 | /* |
3 | * Copyright (C) 2013 - Virtual Open Systems | |
4 | * Author: Antonios Motakis <a.motakis@virtualopensystems.com> | |
36fe431f AM |
5 | */ |
6 | ||
7 | #include <linux/module.h> | |
8 | #include <linux/slab.h> | |
9 | #include <linux/vfio.h> | |
10 | #include <linux/amba/bus.h> | |
11 | ||
12 | #include "vfio_platform_private.h" | |
13 | ||
14 | #define DRIVER_VERSION "0.10" | |
15 | #define DRIVER_AUTHOR "Antonios Motakis <a.motakis@virtualopensystems.com>" | |
16 | #define DRIVER_DESC "VFIO for AMBA devices - User Level meta-driver" | |
17 | ||
18 | /* probing devices from the AMBA bus */ | |
19 | ||
20 | static struct resource *get_amba_resource(struct vfio_platform_device *vdev, | |
21 | int i) | |
22 | { | |
23 | struct amba_device *adev = (struct amba_device *) vdev->opaque; | |
24 | ||
25 | if (i == 0) | |
26 | return &adev->res; | |
27 | ||
28 | return NULL; | |
29 | } | |
30 | ||
31 | static int get_amba_irq(struct vfio_platform_device *vdev, int i) | |
32 | { | |
33 | struct amba_device *adev = (struct amba_device *) vdev->opaque; | |
34 | int ret = 0; | |
35 | ||
36 | if (i < AMBA_NR_IRQS) | |
37 | ret = adev->irq[i]; | |
38 | ||
39 | /* zero is an unset IRQ for AMBA devices */ | |
40 | return ret ? ret : -ENXIO; | |
41 | } | |
42 | ||
43 | static int vfio_amba_probe(struct amba_device *adev, const struct amba_id *id) | |
44 | { | |
45 | struct vfio_platform_device *vdev; | |
46 | int ret; | |
47 | ||
48 | vdev = kzalloc(sizeof(*vdev), GFP_KERNEL); | |
49 | if (!vdev) | |
50 | return -ENOMEM; | |
51 | ||
52 | vdev->name = kasprintf(GFP_KERNEL, "vfio-amba-%08x", adev->periphid); | |
53 | if (!vdev->name) { | |
54 | kfree(vdev); | |
55 | return -ENOMEM; | |
56 | } | |
57 | ||
58 | vdev->opaque = (void *) adev; | |
59 | vdev->flags = VFIO_DEVICE_FLAGS_AMBA; | |
60 | vdev->get_resource = get_amba_resource; | |
61 | vdev->get_irq = get_amba_irq; | |
b5add544 | 62 | vdev->reset_required = false; |
36fe431f AM |
63 | |
64 | ret = vfio_platform_probe_common(vdev, &adev->dev); | |
65 | if (ret) { | |
66 | kfree(vdev->name); | |
67 | kfree(vdev); | |
cb616458 | 68 | return ret; |
36fe431f AM |
69 | } |
70 | ||
cb616458 JG |
71 | dev_set_drvdata(&adev->dev, vdev); |
72 | return 0; | |
36fe431f AM |
73 | } |
74 | ||
3fd269e7 | 75 | static void vfio_amba_remove(struct amba_device *adev) |
36fe431f | 76 | { |
cb616458 | 77 | struct vfio_platform_device *vdev = dev_get_drvdata(&adev->dev); |
36fe431f | 78 | |
cb616458 | 79 | vfio_platform_remove_common(vdev); |
5b495ac8 UKK |
80 | kfree(vdev->name); |
81 | kfree(vdev); | |
36fe431f AM |
82 | } |
83 | ||
417fb50d | 84 | static const struct amba_id pl330_ids[] = { |
36fe431f AM |
85 | { 0, 0 }, |
86 | }; | |
87 | ||
88 | MODULE_DEVICE_TABLE(amba, pl330_ids); | |
89 | ||
90 | static struct amba_driver vfio_amba_driver = { | |
91 | .probe = vfio_amba_probe, | |
92 | .remove = vfio_amba_remove, | |
93 | .id_table = pl330_ids, | |
94 | .drv = { | |
95 | .name = "vfio-amba", | |
96 | .owner = THIS_MODULE, | |
97 | }, | |
98 | }; | |
99 | ||
100 | module_amba_driver(vfio_amba_driver); | |
101 | ||
102 | MODULE_VERSION(DRIVER_VERSION); | |
103 | MODULE_LICENSE("GPL v2"); | |
104 | MODULE_AUTHOR(DRIVER_AUTHOR); | |
105 | MODULE_DESCRIPTION(DRIVER_DESC); |