xref: /linux/drivers/vfio/platform/vfio_amba.c (revision 70693f470848f05fae04144675e6e41b105d45fe)
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>
1036fe431fSAntonios Motakis #include <linux/amba/bus.h>
1136fe431fSAntonios Motakis 
1236fe431fSAntonios Motakis #include "vfio_platform_private.h"
1336fe431fSAntonios Motakis 
1436fe431fSAntonios Motakis #define DRIVER_VERSION  "0.10"
1536fe431fSAntonios Motakis #define DRIVER_AUTHOR   "Antonios Motakis <a.motakis@virtualopensystems.com>"
1636fe431fSAntonios Motakis #define DRIVER_DESC     "VFIO for AMBA devices - User Level meta-driver"
1736fe431fSAntonios Motakis 
1836fe431fSAntonios Motakis /* probing devices from the AMBA bus */
1936fe431fSAntonios Motakis 
2036fe431fSAntonios Motakis static struct resource *get_amba_resource(struct vfio_platform_device *vdev,
2136fe431fSAntonios Motakis 					  int i)
2236fe431fSAntonios Motakis {
2336fe431fSAntonios Motakis 	struct amba_device *adev = (struct amba_device *) vdev->opaque;
2436fe431fSAntonios Motakis 
2536fe431fSAntonios Motakis 	if (i == 0)
2636fe431fSAntonios Motakis 		return &adev->res;
2736fe431fSAntonios Motakis 
2836fe431fSAntonios Motakis 	return NULL;
2936fe431fSAntonios Motakis }
3036fe431fSAntonios Motakis 
3136fe431fSAntonios Motakis static int get_amba_irq(struct vfio_platform_device *vdev, int i)
3236fe431fSAntonios Motakis {
3336fe431fSAntonios Motakis 	struct amba_device *adev = (struct amba_device *) vdev->opaque;
3436fe431fSAntonios Motakis 	int ret = 0;
3536fe431fSAntonios Motakis 
3636fe431fSAntonios Motakis 	if (i < AMBA_NR_IRQS)
3736fe431fSAntonios Motakis 		ret = adev->irq[i];
3836fe431fSAntonios Motakis 
3936fe431fSAntonios Motakis 	/* zero is an unset IRQ for AMBA devices */
4036fe431fSAntonios Motakis 	return ret ? ret : -ENXIO;
4136fe431fSAntonios Motakis }
4236fe431fSAntonios Motakis 
4336fe431fSAntonios Motakis static int vfio_amba_probe(struct amba_device *adev, const struct amba_id *id)
4436fe431fSAntonios Motakis {
4536fe431fSAntonios Motakis 	struct vfio_platform_device *vdev;
4636fe431fSAntonios Motakis 	int ret;
4736fe431fSAntonios Motakis 
4836fe431fSAntonios Motakis 	vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
4936fe431fSAntonios Motakis 	if (!vdev)
5036fe431fSAntonios Motakis 		return -ENOMEM;
5136fe431fSAntonios Motakis 
5236fe431fSAntonios Motakis 	vdev->name = kasprintf(GFP_KERNEL, "vfio-amba-%08x", adev->periphid);
5336fe431fSAntonios Motakis 	if (!vdev->name) {
5436fe431fSAntonios Motakis 		kfree(vdev);
5536fe431fSAntonios Motakis 		return -ENOMEM;
5636fe431fSAntonios Motakis 	}
5736fe431fSAntonios Motakis 
5836fe431fSAntonios Motakis 	vdev->opaque = (void *) adev;
5936fe431fSAntonios Motakis 	vdev->flags = VFIO_DEVICE_FLAGS_AMBA;
6036fe431fSAntonios Motakis 	vdev->get_resource = get_amba_resource;
6136fe431fSAntonios Motakis 	vdev->get_irq = get_amba_irq;
62b5add544SSinan Kaya 	vdev->reset_required = false;
6336fe431fSAntonios Motakis 
6436fe431fSAntonios Motakis 	ret = vfio_platform_probe_common(vdev, &adev->dev);
6536fe431fSAntonios Motakis 	if (ret) {
6636fe431fSAntonios Motakis 		kfree(vdev->name);
6736fe431fSAntonios Motakis 		kfree(vdev);
68cb616458SJason Gunthorpe 		return ret;
6936fe431fSAntonios Motakis 	}
7036fe431fSAntonios Motakis 
71cb616458SJason Gunthorpe 	dev_set_drvdata(&adev->dev, vdev);
72cb616458SJason Gunthorpe 	return 0;
7336fe431fSAntonios Motakis }
7436fe431fSAntonios Motakis 
753fd269e7SUwe Kleine-König static void vfio_amba_remove(struct amba_device *adev)
7636fe431fSAntonios Motakis {
77cb616458SJason Gunthorpe 	struct vfio_platform_device *vdev = dev_get_drvdata(&adev->dev);
7836fe431fSAntonios Motakis 
79cb616458SJason Gunthorpe 	vfio_platform_remove_common(vdev);
8036fe431fSAntonios Motakis 	kfree(vdev->name);
8136fe431fSAntonios Motakis 	kfree(vdev);
8236fe431fSAntonios Motakis }
8336fe431fSAntonios Motakis 
84417fb50dSArvind Yadav static const struct amba_id pl330_ids[] = {
8536fe431fSAntonios Motakis 	{ 0, 0 },
8636fe431fSAntonios Motakis };
8736fe431fSAntonios Motakis 
8836fe431fSAntonios Motakis MODULE_DEVICE_TABLE(amba, pl330_ids);
8936fe431fSAntonios Motakis 
9036fe431fSAntonios Motakis static struct amba_driver vfio_amba_driver = {
9136fe431fSAntonios Motakis 	.probe = vfio_amba_probe,
9236fe431fSAntonios Motakis 	.remove = vfio_amba_remove,
9336fe431fSAntonios Motakis 	.id_table = pl330_ids,
9436fe431fSAntonios Motakis 	.drv = {
9536fe431fSAntonios Motakis 		.name = "vfio-amba",
9636fe431fSAntonios Motakis 		.owner = THIS_MODULE,
9736fe431fSAntonios Motakis 	},
98*70693f47SLu Baolu 	.driver_managed_dma = true,
9936fe431fSAntonios Motakis };
10036fe431fSAntonios Motakis 
10136fe431fSAntonios Motakis module_amba_driver(vfio_amba_driver);
10236fe431fSAntonios Motakis 
10336fe431fSAntonios Motakis MODULE_VERSION(DRIVER_VERSION);
10436fe431fSAntonios Motakis MODULE_LICENSE("GPL v2");
10536fe431fSAntonios Motakis MODULE_AUTHOR(DRIVER_AUTHOR);
10636fe431fSAntonios Motakis MODULE_DESCRIPTION(DRIVER_DESC);
107