xref: /linux/drivers/vfio/platform/vfio_amba.c (revision 32a2d71c4e808b5aa6c414d4422b5e6c594c8805)
136fe431fSAntonios Motakis /*
236fe431fSAntonios Motakis  * Copyright (C) 2013 - Virtual Open Systems
336fe431fSAntonios Motakis  * Author: Antonios Motakis <a.motakis@virtualopensystems.com>
436fe431fSAntonios Motakis  *
536fe431fSAntonios Motakis  * This program is free software; you can redistribute it and/or modify
636fe431fSAntonios Motakis  * it under the terms of the GNU General Public License, version 2, as
736fe431fSAntonios Motakis  * published by the Free Software Foundation.
836fe431fSAntonios Motakis  *
936fe431fSAntonios Motakis  * This program is distributed in the hope that it will be useful,
1036fe431fSAntonios Motakis  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1136fe431fSAntonios Motakis  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1236fe431fSAntonios Motakis  * GNU General Public License for more details.
1336fe431fSAntonios Motakis  */
1436fe431fSAntonios Motakis 
1536fe431fSAntonios Motakis #include <linux/module.h>
1636fe431fSAntonios Motakis #include <linux/slab.h>
1736fe431fSAntonios Motakis #include <linux/vfio.h>
1836fe431fSAntonios Motakis #include <linux/amba/bus.h>
1936fe431fSAntonios Motakis 
2036fe431fSAntonios Motakis #include "vfio_platform_private.h"
2136fe431fSAntonios Motakis 
2236fe431fSAntonios Motakis #define DRIVER_VERSION  "0.10"
2336fe431fSAntonios Motakis #define DRIVER_AUTHOR   "Antonios Motakis <a.motakis@virtualopensystems.com>"
2436fe431fSAntonios Motakis #define DRIVER_DESC     "VFIO for AMBA devices - User Level meta-driver"
2536fe431fSAntonios Motakis 
2636fe431fSAntonios Motakis /* probing devices from the AMBA bus */
2736fe431fSAntonios Motakis 
2836fe431fSAntonios Motakis static struct resource *get_amba_resource(struct vfio_platform_device *vdev,
2936fe431fSAntonios Motakis 					  int i)
3036fe431fSAntonios Motakis {
3136fe431fSAntonios Motakis 	struct amba_device *adev = (struct amba_device *) vdev->opaque;
3236fe431fSAntonios Motakis 
3336fe431fSAntonios Motakis 	if (i == 0)
3436fe431fSAntonios Motakis 		return &adev->res;
3536fe431fSAntonios Motakis 
3636fe431fSAntonios Motakis 	return NULL;
3736fe431fSAntonios Motakis }
3836fe431fSAntonios Motakis 
3936fe431fSAntonios Motakis static int get_amba_irq(struct vfio_platform_device *vdev, int i)
4036fe431fSAntonios Motakis {
4136fe431fSAntonios Motakis 	struct amba_device *adev = (struct amba_device *) vdev->opaque;
4236fe431fSAntonios Motakis 	int ret = 0;
4336fe431fSAntonios Motakis 
4436fe431fSAntonios Motakis 	if (i < AMBA_NR_IRQS)
4536fe431fSAntonios Motakis 		ret = adev->irq[i];
4636fe431fSAntonios Motakis 
4736fe431fSAntonios Motakis 	/* zero is an unset IRQ for AMBA devices */
4836fe431fSAntonios Motakis 	return ret ? ret : -ENXIO;
4936fe431fSAntonios Motakis }
5036fe431fSAntonios Motakis 
5136fe431fSAntonios Motakis static int vfio_amba_probe(struct amba_device *adev, const struct amba_id *id)
5236fe431fSAntonios Motakis {
5336fe431fSAntonios Motakis 	struct vfio_platform_device *vdev;
5436fe431fSAntonios Motakis 	int ret;
5536fe431fSAntonios Motakis 
5636fe431fSAntonios Motakis 	vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
5736fe431fSAntonios Motakis 	if (!vdev)
5836fe431fSAntonios Motakis 		return -ENOMEM;
5936fe431fSAntonios Motakis 
6036fe431fSAntonios Motakis 	vdev->name = kasprintf(GFP_KERNEL, "vfio-amba-%08x", adev->periphid);
6136fe431fSAntonios Motakis 	if (!vdev->name) {
6236fe431fSAntonios Motakis 		kfree(vdev);
6336fe431fSAntonios Motakis 		return -ENOMEM;
6436fe431fSAntonios Motakis 	}
6536fe431fSAntonios Motakis 
6636fe431fSAntonios Motakis 	vdev->opaque = (void *) adev;
6736fe431fSAntonios Motakis 	vdev->flags = VFIO_DEVICE_FLAGS_AMBA;
6836fe431fSAntonios Motakis 	vdev->get_resource = get_amba_resource;
6936fe431fSAntonios Motakis 	vdev->get_irq = get_amba_irq;
70*32a2d71cSEric Auger 	vdev->parent_module = THIS_MODULE;
7136fe431fSAntonios Motakis 
7236fe431fSAntonios Motakis 	ret = vfio_platform_probe_common(vdev, &adev->dev);
7336fe431fSAntonios Motakis 	if (ret) {
7436fe431fSAntonios Motakis 		kfree(vdev->name);
7536fe431fSAntonios Motakis 		kfree(vdev);
7636fe431fSAntonios Motakis 	}
7736fe431fSAntonios Motakis 
7836fe431fSAntonios Motakis 	return ret;
7936fe431fSAntonios Motakis }
8036fe431fSAntonios Motakis 
8136fe431fSAntonios Motakis static int vfio_amba_remove(struct amba_device *adev)
8236fe431fSAntonios Motakis {
8336fe431fSAntonios Motakis 	struct vfio_platform_device *vdev;
8436fe431fSAntonios Motakis 
8536fe431fSAntonios Motakis 	vdev = vfio_platform_remove_common(&adev->dev);
8636fe431fSAntonios Motakis 	if (vdev) {
8736fe431fSAntonios Motakis 		kfree(vdev->name);
8836fe431fSAntonios Motakis 		kfree(vdev);
8936fe431fSAntonios Motakis 		return 0;
9036fe431fSAntonios Motakis 	}
9136fe431fSAntonios Motakis 
9236fe431fSAntonios Motakis 	return -EINVAL;
9336fe431fSAntonios Motakis }
9436fe431fSAntonios Motakis 
9536fe431fSAntonios Motakis static struct amba_id pl330_ids[] = {
9636fe431fSAntonios Motakis 	{ 0, 0 },
9736fe431fSAntonios Motakis };
9836fe431fSAntonios Motakis 
9936fe431fSAntonios Motakis MODULE_DEVICE_TABLE(amba, pl330_ids);
10036fe431fSAntonios Motakis 
10136fe431fSAntonios Motakis static struct amba_driver vfio_amba_driver = {
10236fe431fSAntonios Motakis 	.probe = vfio_amba_probe,
10336fe431fSAntonios Motakis 	.remove = vfio_amba_remove,
10436fe431fSAntonios Motakis 	.id_table = pl330_ids,
10536fe431fSAntonios Motakis 	.drv = {
10636fe431fSAntonios Motakis 		.name = "vfio-amba",
10736fe431fSAntonios Motakis 		.owner = THIS_MODULE,
10836fe431fSAntonios Motakis 	},
10936fe431fSAntonios Motakis };
11036fe431fSAntonios Motakis 
11136fe431fSAntonios Motakis module_amba_driver(vfio_amba_driver);
11236fe431fSAntonios Motakis 
11336fe431fSAntonios Motakis MODULE_VERSION(DRIVER_VERSION);
11436fe431fSAntonios Motakis MODULE_LICENSE("GPL v2");
11536fe431fSAntonios Motakis MODULE_AUTHOR(DRIVER_AUTHOR);
11636fe431fSAntonios Motakis MODULE_DESCRIPTION(DRIVER_DESC);
117