diff options
-rw-r--r-- | drivers/usb/dwc3/Kconfig | 13 | ||||
-rw-r--r-- | drivers/usb/dwc3/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/dwc3/dwc3-haps.c | 137 | ||||
-rw-r--r-- | drivers/usb/dwc3/dwc3-pci.c | 30 |
4 files changed, 147 insertions, 34 deletions
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index 451012ea1294..518ead12458d 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -74,11 +74,16 @@ config USB_DWC3_PCI depends on USB_PCI && ACPI default USB_DWC3 help - If you're using the DesignWare Core IP with a PCIe, please say - 'Y' or 'M' here. + If you're using the DesignWare Core IP with a PCIe (but not HAPS + platform), please say 'Y' or 'M' here. - One such PCIe-based platform is Synopsys' PCIe HAPS model of - this IP. +config USB_DWC3_HAPS + tristate "Synopsys PCIe-based HAPS Platforms" + depends on USB_PCI + default USB_DWC3 + help + If you're using the DesignWare Core IP with a Synopsys PCIe HAPS + platform, please say 'Y' or 'M' here. config USB_DWC3_KEYSTONE tristate "Texas Instruments Keystone2 Platforms" diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index 5c07d8f925e0..6e3ef6144e5d 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile @@ -45,6 +45,7 @@ endif obj-$(CONFIG_USB_DWC3_OMAP) += dwc3-omap.o obj-$(CONFIG_USB_DWC3_EXYNOS) += dwc3-exynos.o obj-$(CONFIG_USB_DWC3_PCI) += dwc3-pci.o +obj-$(CONFIG_USB_DWC3_HAPS) += dwc3-haps.o obj-$(CONFIG_USB_DWC3_KEYSTONE) += dwc3-keystone.o obj-$(CONFIG_USB_DWC3_OF_SIMPLE) += dwc3-of-simple.o obj-$(CONFIG_USB_DWC3_ST) += dwc3-st.o diff --git a/drivers/usb/dwc3/dwc3-haps.c b/drivers/usb/dwc3/dwc3-haps.c new file mode 100644 index 000000000000..c9cc33881bef --- /dev/null +++ b/drivers/usb/dwc3/dwc3-haps.c @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: GPL-2.0 +/** + * dwc3-haps.c - Synopsys HAPS PCI Specific glue layer + * + * Copyright (C) 2018 Synopsys, Inc. + * + * Authors: Thinh Nguyen <thinhn@synopsys.com>, + * John Youn <johnyoun@synopsys.com> + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/pci.h> +#include <linux/platform_device.h> +#include <linux/property.h> + +#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3 0xabcd +#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3_AXI 0xabce +#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB31 0xabcf + +/** + * struct dwc3_haps - Driver private structure + * @dwc3: child dwc3 platform_device + * @pci: our link to PCI bus + */ +struct dwc3_haps { + struct platform_device *dwc3; + struct pci_dev *pci; +}; + +static const struct property_entry initial_properties[] = { + PROPERTY_ENTRY_BOOL("snps,usb3_lpm_capable"), + PROPERTY_ENTRY_BOOL("snps,has-lpm-erratum"), + PROPERTY_ENTRY_BOOL("snps,dis_enblslpm_quirk"), + PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"), + { }, +}; + +static int dwc3_haps_probe(struct pci_dev *pci, + const struct pci_device_id *id) +{ + struct dwc3_haps *dwc; + struct device *dev = &pci->dev; + struct resource res[2]; + int ret; + + ret = pcim_enable_device(pci); + if (ret) { + dev_err(dev, "failed to enable pci device\n"); + return -ENODEV; + } + + pci_set_master(pci); + + dwc = devm_kzalloc(dev, sizeof(*dwc), GFP_KERNEL); + if (!dwc) + return -ENOMEM; + + dwc->dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO); + if (!dwc->dwc3) + return -ENOMEM; + + memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res)); + + res[0].start = pci_resource_start(pci, 0); + res[0].end = pci_resource_end(pci, 0); + res[0].name = "dwc_usb3"; + res[0].flags = IORESOURCE_MEM; + + res[1].start = pci->irq; + res[1].name = "dwc_usb3"; + res[1].flags = IORESOURCE_IRQ; + + ret = platform_device_add_resources(dwc->dwc3, res, ARRAY_SIZE(res)); + if (ret) { + dev_err(dev, "couldn't add resources to dwc3 device\n"); + goto err; + } + + dwc->pci = pci; + dwc->dwc3->dev.parent = dev; + + ret = platform_device_add_properties(dwc->dwc3, initial_properties); + if (ret) + goto err; + + ret = platform_device_add(dwc->dwc3); + if (ret) { + dev_err(dev, "failed to register dwc3 device\n"); + goto err; + } + + pci_set_drvdata(pci, dwc); + + return 0; +err: + platform_device_put(dwc->dwc3); + return ret; +} + +static void dwc3_haps_remove(struct pci_dev *pci) +{ + struct dwc3_haps *dwc = pci_get_drvdata(pci); + + platform_device_unregister(dwc->dwc3); +} + +static const struct pci_device_id dwc3_haps_id_table[] = { + { + PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS, + PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3), + }, + { + PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS, + PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3_AXI), + }, + { + PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS, + PCI_DEVICE_ID_SYNOPSYS_HAPSUSB31), + }, + { } /* Terminating Entry */ +}; +MODULE_DEVICE_TABLE(pci, dwc3_haps_id_table); + +static struct pci_driver dwc3_haps_driver = { + .name = "dwc3-haps", + .id_table = dwc3_haps_id_table, + .probe = dwc3_haps_probe, + .remove = dwc3_haps_remove, +}; + +MODULE_AUTHOR("Thinh Nguyen <thinhn@synopsys.com>"); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Synopsys HAPS PCI Glue Layer"); + +module_pci_driver(dwc3_haps_driver); diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index f57e7c94b8e5..80f5dc691038 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -19,9 +19,6 @@ #include <linux/acpi.h> #include <linux/delay.h> -#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3 0xabcd -#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3_AXI 0xabce -#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB31 0xabcf #define PCI_DEVICE_ID_INTEL_BYT 0x0f37 #define PCI_DEVICE_ID_INTEL_MRFLD 0x119e #define PCI_DEVICE_ID_INTEL_BSW 0x22b7 @@ -151,21 +148,6 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc) } } - if (pdev->vendor == PCI_VENDOR_ID_SYNOPSYS && - (pdev->device == PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3 || - pdev->device == PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3_AXI || - pdev->device == PCI_DEVICE_ID_SYNOPSYS_HAPSUSB31)) { - struct property_entry properties[] = { - PROPERTY_ENTRY_BOOL("snps,usb3_lpm_capable"), - PROPERTY_ENTRY_BOOL("snps,has-lpm-erratum"), - PROPERTY_ENTRY_BOOL("snps,dis_enblslpm_quirk"), - PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"), - { }, - }; - - return platform_device_add_properties(dwc3, properties); - } - return 0; } @@ -266,18 +248,6 @@ static void dwc3_pci_remove(struct pci_dev *pci) } static const struct pci_device_id dwc3_pci_id_table[] = { - { - PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS, - PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3), - }, - { - PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS, - PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3_AXI), - }, - { - PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS, - PCI_DEVICE_ID_SYNOPSYS_HAPSUSB31), - }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BSW), }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT), }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MRFLD), }, |