Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | /*
* bdc_pci.c - BRCM BDC USB3.0 device controller PCI interface file.
*
* Copyright (C) 2014 Broadcom Corporation
*
* Author: Ashwini Pahuja
*
* Based on drivers under drivers/usb/
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/pci_ids.h>
#include <linux/platform_device.h>
#include "bdc.h"
#define BDC_PCI_PID 0x1570
struct bdc_pci {
struct device *dev;
struct platform_device *bdc;
};
static int bdc_setup_msi(struct pci_dev *pci)
{
int ret;
ret = pci_enable_msi(pci);
if (ret) {
pr_err("failed to allocate MSI entry\n");
return ret;
}
return ret;
}
static int bdc_pci_probe(struct pci_dev *pci, const struct pci_device_id *id)
{
struct resource res[2];
struct platform_device *bdc;
struct bdc_pci *glue;
int ret = -ENOMEM;
glue = devm_kzalloc(&pci->dev, sizeof(*glue), GFP_KERNEL);
if (!glue)
return -ENOMEM;
glue->dev = &pci->dev;
ret = pci_enable_device(pci);
if (ret) {
dev_err(&pci->dev, "failed to enable pci device\n");
return -ENODEV;
}
pci_set_master(pci);
bdc = platform_device_alloc(BRCM_BDC_NAME, PLATFORM_DEVID_AUTO);
if (!bdc)
return -ENOMEM;
memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res));
bdc_setup_msi(pci);
res[0].start = pci_resource_start(pci, 0);
res[0].end = pci_resource_end(pci, 0);
res[0].name = BRCM_BDC_NAME;
res[0].flags = IORESOURCE_MEM;
res[1].start = pci->irq;
res[1].name = BRCM_BDC_NAME;
res[1].flags = IORESOURCE_IRQ;
ret = platform_device_add_resources(bdc, res, ARRAY_SIZE(res));
if (ret) {
dev_err(&pci->dev,
"couldn't add resources to bdc device\n");
return ret;
}
pci_set_drvdata(pci, glue);
dma_set_coherent_mask(&bdc->dev, pci->dev.coherent_dma_mask);
bdc->dev.dma_mask = pci->dev.dma_mask;
bdc->dev.dma_parms = pci->dev.dma_parms;
bdc->dev.parent = &pci->dev;
glue->bdc = bdc;
ret = platform_device_add(bdc);
if (ret) {
dev_err(&pci->dev, "failed to register bdc device\n");
platform_device_put(bdc);
return ret;
}
return 0;
}
static void bdc_pci_remove(struct pci_dev *pci)
{
struct bdc_pci *glue = pci_get_drvdata(pci);
platform_device_unregister(glue->bdc);
pci_disable_msi(pci);
}
static struct pci_device_id bdc_pci_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, BDC_PCI_PID), },
{} /* Terminating Entry */
};
MODULE_DEVICE_TABLE(pci, bdc_pci_id_table);
static struct pci_driver bdc_pci_driver = {
.name = "bdc-pci",
.id_table = bdc_pci_id_table,
.probe = bdc_pci_probe,
.remove = bdc_pci_remove,
};
MODULE_AUTHOR("Ashwini Pahuja <ashwini.linux@gmail.com>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("BRCM BDC USB3 PCI Glue layer");
module_pci_driver(bdc_pci_driver);
|