xref: /linux/drivers/vfio/platform/vfio_amba.c (revision ac1237912fbd0f2503344aa268ceb43628cdffa8)
11802d0beSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
236fe431fSAntonios Motakis /*
336fe431fSAntonios Motakis  * Copyright (C) 2013 - Virtual Open Systems
436fe431fSAntonios Motakis  * Author: Antonios Motakis <a.motakis@virtualopensystems.com>
536fe431fSAntonios Motakis  */
636fe431fSAntonios Motakis 
736fe431fSAntonios Motakis #include <linux/module.h>
836fe431fSAntonios Motakis #include <linux/slab.h>
936fe431fSAntonios Motakis #include <linux/vfio.h>
10*ac123791SKevin Tian #include <linux/pm_runtime.h>
1136fe431fSAntonios Motakis #include <linux/amba/bus.h>
1236fe431fSAntonios Motakis 
1336fe431fSAntonios Motakis #include "vfio_platform_private.h"
1436fe431fSAntonios Motakis 
1536fe431fSAntonios Motakis #define DRIVER_VERSION  "0.10"
1636fe431fSAntonios Motakis #define DRIVER_AUTHOR   "Antonios Motakis <a.motakis@virtualopensystems.com>"
1736fe431fSAntonios Motakis #define DRIVER_DESC     "VFIO for AMBA devices - User Level meta-driver"
1836fe431fSAntonios Motakis 
1936fe431fSAntonios Motakis /* probing devices from the AMBA bus */
2036fe431fSAntonios Motakis 
2136fe431fSAntonios Motakis static struct resource *get_amba_resource(struct vfio_platform_device *vdev,
2236fe431fSAntonios Motakis 					  int i)
2336fe431fSAntonios Motakis {
2436fe431fSAntonios Motakis 	struct amba_device *adev = (struct amba_device *) vdev->opaque;
2536fe431fSAntonios Motakis 
2636fe431fSAntonios Motakis 	if (i == 0)
2736fe431fSAntonios Motakis 		return &adev->res;
2836fe431fSAntonios Motakis 
2936fe431fSAntonios Motakis 	return NULL;
3036fe431fSAntonios Motakis }
3136fe431fSAntonios Motakis 
3236fe431fSAntonios Motakis static int get_amba_irq(struct vfio_platform_device *vdev, int i)
3336fe431fSAntonios Motakis {
3436fe431fSAntonios Motakis 	struct amba_device *adev = (struct amba_device *) vdev->opaque;
3536fe431fSAntonios Motakis 	int ret = 0;
3636fe431fSAntonios Motakis 
3736fe431fSAntonios Motakis 	if (i < AMBA_NR_IRQS)
3836fe431fSAntonios Motakis 		ret = adev->irq[i];
3936fe431fSAntonios Motakis 
4036fe431fSAntonios Motakis 	/* zero is an unset IRQ for AMBA devices */
4136fe431fSAntonios Motakis 	return ret ? ret : -ENXIO;
4236fe431fSAntonios Motakis }
4336fe431fSAntonios Motakis 
44*ac123791SKevin Tian static int vfio_amba_init_dev(struct vfio_device *core_vdev)
4536fe431fSAntonios Motakis {
46*ac123791SKevin Tian 	struct vfio_platform_device *vdev =
47*ac123791SKevin Tian 		container_of(core_vdev, struct vfio_platform_device, vdev);
48*ac123791SKevin Tian 	struct amba_device *adev = to_amba_device(core_vdev->dev);
4936fe431fSAntonios Motakis 	int ret;
5036fe431fSAntonios Motakis 
5136fe431fSAntonios Motakis 	vdev->name = kasprintf(GFP_KERNEL, "vfio-amba-%08x", adev->periphid);
52*ac123791SKevin Tian 	if (!vdev->name)
5336fe431fSAntonios Motakis 		return -ENOMEM;
5436fe431fSAntonios Motakis 
5536fe431fSAntonios Motakis 	vdev->opaque = (void *) adev;
5636fe431fSAntonios Motakis 	vdev->flags = VFIO_DEVICE_FLAGS_AMBA;
5736fe431fSAntonios Motakis 	vdev->get_resource = get_amba_resource;
5836fe431fSAntonios Motakis 	vdev->get_irq = get_amba_irq;
59b5add544SSinan Kaya 	vdev->reset_required = false;
6036fe431fSAntonios Motakis 
61*ac123791SKevin Tian 	ret = vfio_platform_init_common(vdev);
62*ac123791SKevin Tian 	if (ret)
6336fe431fSAntonios Motakis 		kfree(vdev->name);
64cb616458SJason Gunthorpe 	return ret;
6536fe431fSAntonios Motakis }
6636fe431fSAntonios Motakis 
67*ac123791SKevin Tian static const struct vfio_device_ops vfio_amba_ops;
68*ac123791SKevin Tian static int vfio_amba_probe(struct amba_device *adev, const struct amba_id *id)
69*ac123791SKevin Tian {
70*ac123791SKevin Tian 	struct vfio_platform_device *vdev;
71*ac123791SKevin Tian 	int ret;
72*ac123791SKevin Tian 
73*ac123791SKevin Tian 	vdev = vfio_alloc_device(vfio_platform_device, vdev, &adev->dev,
74*ac123791SKevin Tian 				 &vfio_amba_ops);
75*ac123791SKevin Tian 	if (IS_ERR(vdev))
76*ac123791SKevin Tian 		return PTR_ERR(vdev);
77*ac123791SKevin Tian 
78*ac123791SKevin Tian 	ret = vfio_register_group_dev(&vdev->vdev);
79*ac123791SKevin Tian 	if (ret)
80*ac123791SKevin Tian 		goto out_put_vdev;
81*ac123791SKevin Tian 
82*ac123791SKevin Tian 	pm_runtime_enable(&adev->dev);
83cb616458SJason Gunthorpe 	dev_set_drvdata(&adev->dev, vdev);
84cb616458SJason Gunthorpe 	return 0;
85*ac123791SKevin Tian 
86*ac123791SKevin Tian out_put_vdev:
87*ac123791SKevin Tian 	vfio_put_device(&vdev->vdev);
88*ac123791SKevin Tian 	return ret;
89*ac123791SKevin Tian }
90*ac123791SKevin Tian 
91*ac123791SKevin Tian static void vfio_amba_release_dev(struct vfio_device *core_vdev)
92*ac123791SKevin Tian {
93*ac123791SKevin Tian 	struct vfio_platform_device *vdev =
94*ac123791SKevin Tian 		container_of(core_vdev, struct vfio_platform_device, vdev);
95*ac123791SKevin Tian 
96*ac123791SKevin Tian 	vfio_platform_release_common(vdev);
97*ac123791SKevin Tian 	kfree(vdev->name);
98*ac123791SKevin Tian 	vfio_free_device(core_vdev);
9936fe431fSAntonios Motakis }
10036fe431fSAntonios Motakis 
1013fd269e7SUwe Kleine-König static void vfio_amba_remove(struct amba_device *adev)
10236fe431fSAntonios Motakis {
103cb616458SJason Gunthorpe 	struct vfio_platform_device *vdev = dev_get_drvdata(&adev->dev);
10436fe431fSAntonios Motakis 
105*ac123791SKevin Tian 	vfio_unregister_group_dev(&vdev->vdev);
106*ac123791SKevin Tian 	pm_runtime_disable(vdev->device);
107*ac123791SKevin Tian 	vfio_put_device(&vdev->vdev);
10836fe431fSAntonios Motakis }
10936fe431fSAntonios Motakis 
110*ac123791SKevin Tian static const struct vfio_device_ops vfio_amba_ops = {
111*ac123791SKevin Tian 	.name		= "vfio-amba",
112*ac123791SKevin Tian 	.init		= vfio_amba_init_dev,
113*ac123791SKevin Tian 	.release	= vfio_amba_release_dev,
114*ac123791SKevin Tian 	.open_device	= vfio_platform_open_device,
115*ac123791SKevin Tian 	.close_device	= vfio_platform_close_device,
116*ac123791SKevin Tian 	.ioctl		= vfio_platform_ioctl,
117*ac123791SKevin Tian 	.read		= vfio_platform_read,
118*ac123791SKevin Tian 	.write		= vfio_platform_write,
119*ac123791SKevin Tian 	.mmap		= vfio_platform_mmap,
120*ac123791SKevin Tian };
121*ac123791SKevin Tian 
122417fb50dSArvind Yadav static const struct amba_id pl330_ids[] = {
12336fe431fSAntonios Motakis 	{ 0, 0 },
12436fe431fSAntonios Motakis };
12536fe431fSAntonios Motakis 
12636fe431fSAntonios Motakis MODULE_DEVICE_TABLE(amba, pl330_ids);
12736fe431fSAntonios Motakis 
12836fe431fSAntonios Motakis static struct amba_driver vfio_amba_driver = {
12936fe431fSAntonios Motakis 	.probe = vfio_amba_probe,
13036fe431fSAntonios Motakis 	.remove = vfio_amba_remove,
13136fe431fSAntonios Motakis 	.id_table = pl330_ids,
13236fe431fSAntonios Motakis 	.drv = {
13336fe431fSAntonios Motakis 		.name = "vfio-amba",
13436fe431fSAntonios Motakis 		.owner = THIS_MODULE,
13536fe431fSAntonios Motakis 	},
13670693f47SLu Baolu 	.driver_managed_dma = true,
13736fe431fSAntonios Motakis };
13836fe431fSAntonios Motakis 
13936fe431fSAntonios Motakis module_amba_driver(vfio_amba_driver);
14036fe431fSAntonios Motakis 
14136fe431fSAntonios Motakis MODULE_VERSION(DRIVER_VERSION);
14236fe431fSAntonios Motakis MODULE_LICENSE("GPL v2");
14336fe431fSAntonios Motakis MODULE_AUTHOR(DRIVER_AUTHOR);
14436fe431fSAntonios Motakis MODULE_DESCRIPTION(DRIVER_DESC);
145