1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (C) 2013 - Virtual Open Systems
4 * Author: Antonios Motakis <a.motakis@virtualopensystems.com>
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
20static 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
31static 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
43static 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;
62	vdev->parent_module = THIS_MODULE;
63	vdev->reset_required = false;
64
65	ret = vfio_platform_probe_common(vdev, &adev->dev);
66	if (ret) {
67		kfree(vdev->name);
68		kfree(vdev);
69	}
70
71	return ret;
72}
73
74static void vfio_amba_remove(struct amba_device *adev)
75{
76	struct vfio_platform_device *vdev =
77		vfio_platform_remove_common(&adev->dev);
78
79	kfree(vdev->name);
80	kfree(vdev);
81}
82
83static const struct amba_id pl330_ids[] = {
84	{ 0, 0 },
85};
86
87MODULE_DEVICE_TABLE(amba, pl330_ids);
88
89static struct amba_driver vfio_amba_driver = {
90	.probe = vfio_amba_probe,
91	.remove = vfio_amba_remove,
92	.id_table = pl330_ids,
93	.drv = {
94		.name = "vfio-amba",
95		.owner = THIS_MODULE,
96	},
97};
98
99module_amba_driver(vfio_amba_driver);
100
101MODULE_VERSION(DRIVER_VERSION);
102MODULE_LICENSE("GPL v2");
103MODULE_AUTHOR(DRIVER_AUTHOR);
104MODULE_DESCRIPTION(DRIVER_DESC);
105