diff options
Diffstat (limited to 'drivers/usb/dwc3')
-rw-r--r-- | drivers/usb/dwc3/Kconfig | 13 | ||||
-rw-r--r-- | drivers/usb/dwc3/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/dwc3/core.c | 118 | ||||
-rw-r--r-- | drivers/usb/dwc3/core.h | 17 | ||||
-rw-r--r-- | drivers/usb/dwc3/dwc3-haps.c | 137 | ||||
-rw-r--r-- | drivers/usb/dwc3/dwc3-of-simple.c | 29 | ||||
-rw-r--r-- | drivers/usb/dwc3/dwc3-pci.c | 223 | ||||
-rw-r--r-- | drivers/usb/dwc3/gadget.c | 2 | ||||
-rw-r--r-- | drivers/usb/dwc3/gadget.h | 2 |
9 files changed, 446 insertions, 96 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/core.c b/drivers/usb/dwc3/core.c index 103807587dc6..88c80fcc39f5 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -78,6 +78,14 @@ static int dwc3_get_dr_mode(struct dwc3 *dwc) mode = USB_DR_MODE_HOST; else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) mode = USB_DR_MODE_PERIPHERAL; + + /* + * dwc_usb31 does not support OTG mode. If the controller + * supports DRD but the dr_mode is not specified or set to OTG, + * then set the mode to peripheral. + */ + if (mode == USB_DR_MODE_OTG && dwc3_is_usb31(dwc)) + mode = USB_DR_MODE_PERIPHERAL; } if (mode != dwc->dr_mode) { @@ -778,6 +786,98 @@ static void dwc3_core_setup_global_control(struct dwc3 *dwc) static int dwc3_core_get_phy(struct dwc3 *dwc); static int dwc3_core_ulpi_init(struct dwc3 *dwc); +/* set global incr burst type configuration registers */ +static void dwc3_set_incr_burst_type(struct dwc3 *dwc) +{ + struct device *dev = dwc->dev; + /* incrx_mode : for INCR burst type. */ + bool incrx_mode; + /* incrx_size : for size of INCRX burst. */ + u32 incrx_size; + u32 *vals; + u32 cfg; + int ntype; + int ret; + int i; + + cfg = dwc3_readl(dwc->regs, DWC3_GSBUSCFG0); + + /* + * Handle property "snps,incr-burst-type-adjustment". + * Get the number of value from this property: + * result <= 0, means this property is not supported. + * result = 1, means INCRx burst mode supported. + * result > 1, means undefined length burst mode supported. + */ + ntype = device_property_read_u32_array(dev, + "snps,incr-burst-type-adjustment", NULL, 0); + if (ntype <= 0) + return; + + vals = kcalloc(ntype, sizeof(u32), GFP_KERNEL); + if (!vals) { + dev_err(dev, "Error to get memory\n"); + return; + } + + /* Get INCR burst type, and parse it */ + ret = device_property_read_u32_array(dev, + "snps,incr-burst-type-adjustment", vals, ntype); + if (ret) { + dev_err(dev, "Error to get property\n"); + return; + } + + incrx_size = *vals; + + if (ntype > 1) { + /* INCRX (undefined length) burst mode */ + incrx_mode = INCRX_UNDEF_LENGTH_BURST_MODE; + for (i = 1; i < ntype; i++) { + if (vals[i] > incrx_size) + incrx_size = vals[i]; + } + } else { + /* INCRX burst mode */ + incrx_mode = INCRX_BURST_MODE; + } + + /* Enable Undefined Length INCR Burst and Enable INCRx Burst */ + cfg &= ~DWC3_GSBUSCFG0_INCRBRST_MASK; + if (incrx_mode) + cfg |= DWC3_GSBUSCFG0_INCRBRSTENA; + switch (incrx_size) { + case 256: + cfg |= DWC3_GSBUSCFG0_INCR256BRSTENA; + break; + case 128: + cfg |= DWC3_GSBUSCFG0_INCR128BRSTENA; + break; + case 64: + cfg |= DWC3_GSBUSCFG0_INCR64BRSTENA; + break; + case 32: + cfg |= DWC3_GSBUSCFG0_INCR32BRSTENA; + break; + case 16: + cfg |= DWC3_GSBUSCFG0_INCR16BRSTENA; + break; + case 8: + cfg |= DWC3_GSBUSCFG0_INCR8BRSTENA; + break; + case 4: + cfg |= DWC3_GSBUSCFG0_INCR4BRSTENA; + break; + case 1: + break; + default: + dev_err(dev, "Invalid property\n"); + break; + } + + dwc3_writel(dwc->regs, DWC3_GSBUSCFG0, cfg); +} + /** * dwc3_core_init - Low-level initialization of DWC3 Core * @dwc: Pointer to our controller context structure @@ -840,6 +940,8 @@ static int dwc3_core_init(struct dwc3 *dwc) /* Adjust Frame Length */ dwc3_frame_length_adjustment(dwc); + dwc3_set_incr_burst_type(dwc); + usb_phy_set_suspend(dwc->usb2_phy, 0); usb_phy_set_suspend(dwc->usb3_phy, 0); ret = phy_power_on(dwc->usb2_generic_phy); @@ -883,6 +985,22 @@ static int dwc3_core_init(struct dwc3 *dwc) dwc3_writel(dwc->regs, DWC3_GUCTL1, reg); } + if (dwc->dr_mode == USB_DR_MODE_HOST || + dwc->dr_mode == USB_DR_MODE_OTG) { + reg = dwc3_readl(dwc->regs, DWC3_GUCTL); + + /* + * Enable Auto retry Feature to make the controller operating in + * Host mode on seeing transaction errors(CRC errors or internal + * overrun scenerios) on IN transfers to reply to the device + * with a non-terminating retry ACK (i.e, an ACK transcation + * packet with Retry=1 & Nump != 0) + */ + reg |= DWC3_GUCTL_HSTINAUTORETRY; + + dwc3_writel(dwc->regs, DWC3_GUCTL, reg); + } + /* * Must config both number of packets and max burst settings to enable * RX and/or TX threshold. diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 285ce0ef3b91..5bfb62533e0f 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -163,6 +163,17 @@ /* Bit fields */ +/* Global SoC Bus Configuration INCRx Register 0 */ +#define DWC3_GSBUSCFG0_INCR256BRSTENA (1 << 7) /* INCR256 burst */ +#define DWC3_GSBUSCFG0_INCR128BRSTENA (1 << 6) /* INCR128 burst */ +#define DWC3_GSBUSCFG0_INCR64BRSTENA (1 << 5) /* INCR64 burst */ +#define DWC3_GSBUSCFG0_INCR32BRSTENA (1 << 4) /* INCR32 burst */ +#define DWC3_GSBUSCFG0_INCR16BRSTENA (1 << 3) /* INCR16 burst */ +#define DWC3_GSBUSCFG0_INCR8BRSTENA (1 << 2) /* INCR8 burst */ +#define DWC3_GSBUSCFG0_INCR4BRSTENA (1 << 1) /* INCR4 burst */ +#define DWC3_GSBUSCFG0_INCRBRSTENA (1 << 0) /* undefined length enable */ +#define DWC3_GSBUSCFG0_INCRBRST_MASK 0xff + /* Global Debug Queue/FIFO Space Available Register */ #define DWC3_GDBGFIFOSPACE_NUM(n) ((n) & 0x1f) #define DWC3_GDBGFIFOSPACE_TYPE(n) (((n) << 5) & 0x1e0) @@ -227,6 +238,9 @@ #define DWC3_GCTL_GBLHIBERNATIONEN BIT(1) #define DWC3_GCTL_DSBLCLKGTNG BIT(0) +/* Global User Control Register */ +#define DWC3_GUCTL_HSTINAUTORETRY BIT(14) + /* Global User Control 1 Register */ #define DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS BIT(28) #define DWC3_GUCTL1_DEV_L1_EXIT_BY_HW BIT(24) @@ -1157,6 +1171,9 @@ struct dwc3 { u16 imod_interval; }; +#define INCRX_BURST_MODE 0 +#define INCRX_UNDEF_LENGTH_BURST_MODE 1 + #define work_to_dwc(w) (container_of((w), struct dwc3, drd_work)) /* -------------------------------------------------------------------------- */ 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-of-simple.c b/drivers/usb/dwc3/dwc3-of-simple.c index dbeff5e6ad14..40bf9e0bbc59 100644 --- a/drivers/usb/dwc3/dwc3-of-simple.c +++ b/drivers/usb/dwc3/dwc3-of-simple.c @@ -28,6 +28,7 @@ struct dwc3_of_simple { int num_clocks; struct reset_control *resets; bool pulse_resets; + bool need_reset; }; static int dwc3_of_simple_clk_init(struct dwc3_of_simple *simple, int count) @@ -93,6 +94,13 @@ static int dwc3_of_simple_probe(struct platform_device *pdev) platform_set_drvdata(pdev, simple); simple->dev = dev; + /* + * Some controllers need to toggle the usb3-otg reset before trying to + * initialize the PHY, otherwise the PHY times out. + */ + if (of_device_is_compatible(np, "rockchip,rk3399-dwc3")) + simple->need_reset = true; + if (of_device_is_compatible(np, "amlogic,meson-axg-dwc3") || of_device_is_compatible(np, "amlogic,meson-gxl-dwc3")) { shared_resets = true; @@ -201,9 +209,30 @@ static int dwc3_of_simple_runtime_resume(struct device *dev) return 0; } + +static int dwc3_of_simple_suspend(struct device *dev) +{ + struct dwc3_of_simple *simple = dev_get_drvdata(dev); + + if (simple->need_reset) + reset_control_assert(simple->resets); + + return 0; +} + +static int dwc3_of_simple_resume(struct device *dev) +{ + struct dwc3_of_simple *simple = dev_get_drvdata(dev); + + if (simple->need_reset) + reset_control_deassert(simple->resets); + + return 0; +} #endif static const struct dev_pm_ops dwc3_of_simple_dev_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(dwc3_of_simple_suspend, dwc3_of_simple_resume) SET_RUNTIME_PM_OPS(dwc3_of_simple_runtime_suspend, dwc3_of_simple_runtime_resume, NULL) }; diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index f57e7c94b8e5..5edd79470368 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -16,12 +16,10 @@ #include <linux/pm_runtime.h> #include <linux/platform_device.h> #include <linux/gpio/consumer.h> +#include <linux/gpio/machine.h> #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 @@ -41,12 +39,17 @@ #define PCI_INTEL_BXT_STATE_D0 0 #define PCI_INTEL_BXT_STATE_D3 3 +#define GP_RWBAR 1 +#define GP_RWREG1 0xa0 +#define GP_RWREG1_ULPI_REFCLK_DISABLE (1 << 17) + /** * struct dwc3_pci - Driver private structure * @dwc3: child dwc3 platform_device * @pci: our link to PCI bus * @guid: _DSM GUID * @has_dsm_for_pm: true for devices which need to run _DSM on runtime PM + * @wakeup_work: work for asynchronous resume */ struct dwc3_pci { struct platform_device *dwc3; @@ -67,52 +70,74 @@ static const struct acpi_gpio_mapping acpi_dwc3_byt_gpios[] = { { }, }; -static int dwc3_pci_quirks(struct dwc3_pci *dwc) +static struct gpiod_lookup_table platform_bytcr_gpios = { + .dev_id = "0000:00:16.0", + .table = { + GPIO_LOOKUP("INT33FC:00", 54, "reset", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("INT33FC:02", 14, "cs", GPIO_ACTIVE_HIGH), + {} + }, +}; + +static int dwc3_byt_enable_ulpi_refclock(struct pci_dev *pci) { - struct platform_device *dwc3 = dwc->dwc3; - struct pci_dev *pdev = dwc->pci; + void __iomem *reg; + u32 value; + + reg = pcim_iomap(pci, GP_RWBAR, 0); + if (IS_ERR(reg)) + return PTR_ERR(reg); + + value = readl(reg + GP_RWREG1); + if (!(value & GP_RWREG1_ULPI_REFCLK_DISABLE)) + goto unmap; /* ULPI refclk already enabled */ + + value &= ~GP_RWREG1_ULPI_REFCLK_DISABLE; + writel(value, reg + GP_RWREG1); + /* This comes from the Intel Android x86 tree w/o any explanation */ + msleep(100); +unmap: + pcim_iounmap(pci, reg); + return 0; +} - if (pdev->vendor == PCI_VENDOR_ID_AMD && - pdev->device == PCI_DEVICE_ID_AMD_NL_USB) { - struct property_entry properties[] = { - PROPERTY_ENTRY_BOOL("snps,has-lpm-erratum"), - PROPERTY_ENTRY_U8("snps,lpm-nyet-threshold", 0xf), - PROPERTY_ENTRY_BOOL("snps,u2exit_lfps_quirk"), - PROPERTY_ENTRY_BOOL("snps,u2ss_inp3_quirk"), - PROPERTY_ENTRY_BOOL("snps,req_p1p2p3_quirk"), - PROPERTY_ENTRY_BOOL("snps,del_p1p2p3_quirk"), - PROPERTY_ENTRY_BOOL("snps,del_phy_power_chg_quirk"), - PROPERTY_ENTRY_BOOL("snps,lfps_filter_quirk"), - PROPERTY_ENTRY_BOOL("snps,rx_detect_poll_quirk"), - PROPERTY_ENTRY_BOOL("snps,tx_de_emphasis_quirk"), - PROPERTY_ENTRY_U8("snps,tx_de_emphasis", 1), - /* - * FIXME these quirks should be removed when AMD NL - * tapes out - */ - PROPERTY_ENTRY_BOOL("snps,disable_scramble_quirk"), - PROPERTY_ENTRY_BOOL("snps,dis_u3_susphy_quirk"), - PROPERTY_ENTRY_BOOL("snps,dis_u2_susphy_quirk"), - PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"), - { }, - }; - - return platform_device_add_properties(dwc3, properties); - } +static const struct property_entry dwc3_pci_intel_properties[] = { + PROPERTY_ENTRY_STRING("dr_mode", "peripheral"), + PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"), + {} +}; - if (pdev->vendor == PCI_VENDOR_ID_INTEL) { - int ret; +static const struct property_entry dwc3_pci_mrfld_properties[] = { + PROPERTY_ENTRY_STRING("dr_mode", "otg"), + PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"), + {} +}; - struct property_entry properties[] = { - PROPERTY_ENTRY_STRING("dr_mode", "peripheral"), - PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"), - { } - }; +static const struct property_entry dwc3_pci_amd_properties[] = { + PROPERTY_ENTRY_BOOL("snps,has-lpm-erratum"), + PROPERTY_ENTRY_U8("snps,lpm-nyet-threshold", 0xf), + PROPERTY_ENTRY_BOOL("snps,u2exit_lfps_quirk"), + PROPERTY_ENTRY_BOOL("snps,u2ss_inp3_quirk"), + PROPERTY_ENTRY_BOOL("snps,req_p1p2p3_quirk"), + PROPERTY_ENTRY_BOOL("snps,del_p1p2p3_quirk"), + PROPERTY_ENTRY_BOOL("snps,del_phy_power_chg_quirk"), + PROPERTY_ENTRY_BOOL("snps,lfps_filter_quirk"), + PROPERTY_ENTRY_BOOL("snps,rx_detect_poll_quirk"), + PROPERTY_ENTRY_BOOL("snps,tx_de_emphasis_quirk"), + PROPERTY_ENTRY_U8("snps,tx_de_emphasis", 1), + /* FIXME these quirks should be removed when AMD NL tapes out */ + PROPERTY_ENTRY_BOOL("snps,disable_scramble_quirk"), + PROPERTY_ENTRY_BOOL("snps,dis_u3_susphy_quirk"), + PROPERTY_ENTRY_BOOL("snps,dis_u2_susphy_quirk"), + PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"), + {} +}; - ret = platform_device_add_properties(dwc3, properties); - if (ret < 0) - return ret; +static int dwc3_pci_quirks(struct dwc3_pci *dwc) +{ + struct pci_dev *pdev = dwc->pci; + if (pdev->vendor == PCI_VENDOR_ID_INTEL) { if (pdev->device == PCI_DEVICE_ID_INTEL_BXT || pdev->device == PCI_DEVICE_ID_INTEL_BXT_M) { guid_parse(PCI_INTEL_BXT_DSM_GUID, &dwc->guid); @@ -121,6 +146,12 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc) if (pdev->device == PCI_DEVICE_ID_INTEL_BYT) { struct gpio_desc *gpio; + int ret; + + /* On BYT the FW does not always enable the refclock */ + ret = dwc3_byt_enable_ulpi_refclock(pdev); + if (ret) + return ret; ret = devm_acpi_dev_add_driver_gpios(&pdev->dev, acpi_dwc3_byt_gpios); @@ -128,44 +159,36 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc) dev_dbg(&pdev->dev, "failed to add mapping table\n"); /* + * A lot of BYT devices lack ACPI resource entries for + * the GPIOs, add a fallback mapping to the reference + * design GPIOs which all boards seem to use. + */ + gpiod_add_lookup_table(&platform_bytcr_gpios); + + /* * These GPIOs will turn on the USB2 PHY. Note that we have to * put the gpio descriptors again here because the phy driver * might want to grab them, too. */ - gpio = gpiod_get_optional(&pdev->dev, "cs", GPIOD_OUT_LOW); + gpio = devm_gpiod_get_optional(&pdev->dev, "cs", + GPIOD_OUT_LOW); if (IS_ERR(gpio)) return PTR_ERR(gpio); gpiod_set_value_cansleep(gpio, 1); - gpiod_put(gpio); - gpio = gpiod_get_optional(&pdev->dev, "reset", GPIOD_OUT_LOW); + gpio = devm_gpiod_get_optional(&pdev->dev, "reset", + GPIOD_OUT_LOW); if (IS_ERR(gpio)) return PTR_ERR(gpio); if (gpio) { gpiod_set_value_cansleep(gpio, 1); - gpiod_put(gpio); usleep_range(10000, 11000); } } } - 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; } @@ -185,9 +208,9 @@ static void dwc3_pci_resume_work(struct work_struct *work) } #endif -static int dwc3_pci_probe(struct pci_dev *pci, - const struct pci_device_id *id) +static int dwc3_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) { + struct property_entry *p = (struct property_entry *)id->driver_data; struct dwc3_pci *dwc; struct resource res[2]; int ret; @@ -230,6 +253,10 @@ static int dwc3_pci_probe(struct pci_dev *pci, dwc->dwc3->dev.parent = dev; ACPI_COMPANION_SET(&dwc->dwc3->dev, ACPI_COMPANION(dev)); + ret = platform_device_add_properties(dwc->dwc3, p); + if (ret < 0) + return ret; + ret = dwc3_pci_quirks(dwc); if (ret) goto err; @@ -257,6 +284,7 @@ static void dwc3_pci_remove(struct pci_dev *pci) { struct dwc3_pci *dwc = pci_get_drvdata(pci); + gpiod_remove_lookup_table(&platform_bytcr_gpios); #ifdef CONFIG_PM cancel_work_sync(&dwc->wakeup_work); #endif @@ -266,32 +294,47 @@ 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), }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTLP), }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTH), }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BXT), }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BXT_M), }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_APL), }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KBP), }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_GLK), }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CNPLP), }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CNPH), }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICLLP), }, - { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_NL_USB), }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BSW), + (kernel_ulong_t) &dwc3_pci_intel_properties }, + + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BYT), + (kernel_ulong_t) &dwc3_pci_intel_properties, }, + + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MRFLD), + (kernel_ulong_t) &dwc3_pci_mrfld_properties, }, + + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SPTLP), + (kernel_ulong_t) &dwc3_pci_intel_properties, }, + + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SPTH), + (kernel_ulong_t) &dwc3_pci_intel_properties, }, + + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BXT), + (kernel_ulong_t) &dwc3_pci_intel_properties, }, + + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BXT_M), + (kernel_ulong_t) &dwc3_pci_intel_properties, }, + + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_APL), + (kernel_ulong_t) &dwc3_pci_intel_properties, }, + + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_KBP), + (kernel_ulong_t) &dwc3_pci_intel_properties, }, + + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_GLK), + (kernel_ulong_t) &dwc3_pci_intel_properties, }, + + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_CNPLP), + (kernel_ulong_t) &dwc3_pci_intel_properties, }, + + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_CNPH), + (kernel_ulong_t) &dwc3_pci_intel_properties, }, + + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICLLP), + (kernel_ulong_t) &dwc3_pci_intel_properties, }, + + { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_NL_USB), + (kernel_ulong_t) &dwc3_pci_amd_properties, }, { } /* Terminating Entry */ }; MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table); diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 69bf137aab37..032ea7d709ba 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1121,7 +1121,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, req->request.short_not_ok, req->request.no_interrupt); } else if (req->request.zero && req->request.length && - (IS_ALIGNED(req->request.length,dep->endpoint.maxpacket))) { + (IS_ALIGNED(req->request.length, maxp))) { struct dwc3 *dwc = dep->dwc; struct dwc3_trb *trb; diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h index db610c56f1d6..2aacd1afd9ff 100644 --- a/drivers/usb/dwc3/gadget.h +++ b/drivers/usb/dwc3/gadget.h @@ -25,7 +25,7 @@ struct dwc3; #define DWC3_DEPCFG_XFER_IN_PROGRESS_EN BIT(9) #define DWC3_DEPCFG_XFER_NOT_READY_EN BIT(10) #define DWC3_DEPCFG_FIFO_ERROR_EN BIT(11) -#define DWC3_DEPCFG_STREAM_EVENT_EN BIT(12) +#define DWC3_DEPCFG_STREAM_EVENT_EN BIT(13) #define DWC3_DEPCFG_BINTERVAL_M1(n) (((n) & 0xff) << 16) #define DWC3_DEPCFG_STREAM_CAPABLE BIT(24) #define DWC3_DEPCFG_EP_NUMBER(n) (((n) & 0x1f) << 25) |