1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2013 - Virtual Open Systems
4 * Author: Antonios Motakis <a.motakis@virtualopensystems.com>
7 #include <linux/module.h>
8 #include <linux/slab.h>
9 #include <linux/vfio.h>
10 #include <linux/pm_runtime.h>
11 #include <linux/amba/bus.h>
13 #include "vfio_platform_private.h"
15 #define DRIVER_VERSION "0.10"
16 #define DRIVER_AUTHOR "Antonios Motakis <a.motakis@virtualopensystems.com>"
17 #define DRIVER_DESC "VFIO for AMBA devices - User Level meta-driver"
19 /* probing devices from the AMBA bus */
21 static struct resource
*get_amba_resource(struct vfio_platform_device
*vdev
,
24 struct amba_device
*adev
= (struct amba_device
*) vdev
->opaque
;
32 static int get_amba_irq(struct vfio_platform_device
*vdev
, int i
)
34 struct amba_device
*adev
= (struct amba_device
*) vdev
->opaque
;
40 /* zero is an unset IRQ for AMBA devices */
41 return ret
? ret
: -ENXIO
;
44 static int vfio_amba_init_dev(struct vfio_device
*core_vdev
)
46 struct vfio_platform_device
*vdev
=
47 container_of(core_vdev
, struct vfio_platform_device
, vdev
);
48 struct amba_device
*adev
= to_amba_device(core_vdev
->dev
);
51 vdev
->name
= kasprintf(GFP_KERNEL
, "vfio-amba-%08x", adev
->periphid
);
55 vdev
->opaque
= (void *) adev
;
56 vdev
->flags
= VFIO_DEVICE_FLAGS_AMBA
;
57 vdev
->get_resource
= get_amba_resource
;
58 vdev
->get_irq
= get_amba_irq
;
59 vdev
->reset_required
= false;
61 ret
= vfio_platform_init_common(vdev
);
67 static const struct vfio_device_ops vfio_amba_ops
;
68 static int vfio_amba_probe(struct amba_device
*adev
, const struct amba_id
*id
)
70 struct vfio_platform_device
*vdev
;
73 vdev
= vfio_alloc_device(vfio_platform_device
, vdev
, &adev
->dev
,
78 ret
= vfio_register_group_dev(&vdev
->vdev
);
82 pm_runtime_enable(&adev
->dev
);
83 dev_set_drvdata(&adev
->dev
, vdev
);
87 vfio_put_device(&vdev
->vdev
);
91 static void vfio_amba_release_dev(struct vfio_device
*core_vdev
)
93 struct vfio_platform_device
*vdev
=
94 container_of(core_vdev
, struct vfio_platform_device
, vdev
);
96 vfio_platform_release_common(vdev
);
100 static void vfio_amba_remove(struct amba_device
*adev
)
102 struct vfio_platform_device
*vdev
= dev_get_drvdata(&adev
->dev
);
104 vfio_unregister_group_dev(&vdev
->vdev
);
105 pm_runtime_disable(vdev
->device
);
106 vfio_put_device(&vdev
->vdev
);
109 static const struct vfio_device_ops vfio_amba_ops
= {
111 .init
= vfio_amba_init_dev
,
112 .release
= vfio_amba_release_dev
,
113 .open_device
= vfio_platform_open_device
,
114 .close_device
= vfio_platform_close_device
,
115 .ioctl
= vfio_platform_ioctl
,
116 .read
= vfio_platform_read
,
117 .write
= vfio_platform_write
,
118 .mmap
= vfio_platform_mmap
,
119 .bind_iommufd
= vfio_iommufd_physical_bind
,
120 .unbind_iommufd
= vfio_iommufd_physical_unbind
,
121 .attach_ioas
= vfio_iommufd_physical_attach_ioas
,
122 .detach_ioas
= vfio_iommufd_physical_detach_ioas
,
125 static const struct amba_id vfio_amba_ids
[] = {
129 MODULE_DEVICE_TABLE(amba
, vfio_amba_ids
);
131 static struct amba_driver vfio_amba_driver
= {
132 .probe
= vfio_amba_probe
,
133 .remove
= vfio_amba_remove
,
134 .id_table
= vfio_amba_ids
,
138 .driver_managed_dma
= true,
141 module_amba_driver(vfio_amba_driver
);
143 MODULE_VERSION(DRIVER_VERSION
);
144 MODULE_LICENSE("GPL v2");
145 MODULE_AUTHOR(DRIVER_AUTHOR
);
146 MODULE_DESCRIPTION(DRIVER_DESC
);