coreboot/util/uio_usbdebug/linux/uio_ehci_pci.c

90 lines
2.0 KiB
C

/* uio_ehci_pci - UIO driver for PCI EHCI devices */
/* This only implements MMIO access (no interrupts). */
/* SPDX-License-Identifier: GPL-2.0-only */
#include <linux/device.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/uio_driver.h>
#define DRIVER_VERSION "0.0.1"
#define DRIVER_AUTHOR "Nico Huber <nico.h@gmx.de>"
#define DRIVER_DESC "UIO driver for PCI EHCI devices"
#define DRIVER_TAG "uio_ehci_pci"
static int probe(struct pci_dev *const pci_dev,
const struct pci_device_id *const did)
{
struct uio_info *info;
int ret;
ret = pci_enable_device(pci_dev);
if (ret)
goto return_;
ret = pci_request_regions(pci_dev, DRIVER_TAG);
if (ret)
goto return_disable;
info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
if (!info) {
ret = -ENOMEM;
goto return_release;
}
info->name = DRIVER_TAG;
info->version = DRIVER_VERSION;
info->mem[0].name = "EHCI MMIO area";
info->mem[0].addr = pci_resource_start(pci_dev, 0);
if (!info->mem[0].addr) {
ret = -ENODEV;
goto return_free;
}
info->mem[0].size = pci_resource_len(pci_dev, 0);
info->mem[0].memtype = UIO_MEM_PHYS;
ret = uio_register_device(&pci_dev->dev, info);
if (ret)
goto return_free;
pci_set_drvdata(pci_dev, info);
return 0;
return_free:
kfree(info);
return_release:
pci_release_regions(pci_dev);
return_disable:
pci_disable_device(pci_dev);
return_:
return ret;
}
static void remove(struct pci_dev *const pci_dev)
{
struct uio_info *const info = pci_get_drvdata(pci_dev);
uio_unregister_device(info);
kfree(info);
pci_release_regions(pci_dev);
pci_disable_device(pci_dev);
}
static DEFINE_PCI_DEVICE_TABLE(ehci_pci_ids) = {
{ PCI_DEVICE(0x8086, 0x27cc) },
{ 0, }
};
static struct pci_driver uio_ehci_pci_driver = {
.name = DRIVER_TAG,
.id_table = ehci_pci_ids,
.probe = probe,
.remove = remove,
};
module_pci_driver(uio_ehci_pci_driver);
MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);