From: Pavel Kubelun Date: Sat, 12 Nov 2016 11:35:56 +0000 (+0300) Subject: ipq806x: switch to upstream usb driver and backport fixes X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=70434c3f948749690de24effbfd98f7a64e0991f;p=openwrt%2Fstaging%2Fneocturne.git ipq806x: switch to upstream usb driver and backport fixes Also removing fifo-resize property drom DT as it has been removed from the driver. Signed-off-by: Pavel Kubelun --- diff --git a/target/linux/ipq806x/Makefile b/target/linux/ipq806x/Makefile index 27ad6a4a06..3a65d334aa 100644 --- a/target/linux/ipq806x/Makefile +++ b/target/linux/ipq806x/Makefile @@ -19,7 +19,7 @@ DEFAULT_PACKAGES += \ kmod-leds-gpio kmod-gpio-button-hotplug swconfig \ kmod-ata-core kmod-ata-ahci kmod-ata-ahci-platform \ kmod-usb-core kmod-usb-ohci kmod-usb2 kmod-usb-ledtrig-usbport \ - kmod-usb3 kmod-usb-dwc3-qcom kmod-usb-phy-qcom-dwc3 \ + kmod-usb3 kmod-usb-dwc3-of-simple kmod-usb-phy-qcom-dwc3 \ kmod-ath10k wpad-mini \ uboot-envtools diff --git a/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8065.dtsi b/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8065.dtsi index 435692b183..e0ba99a41c 100644 --- a/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8065.dtsi +++ b/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8065.dtsi @@ -790,7 +790,6 @@ interrupts = <0 110 0x4>; phys = <&hs_phy_0>, <&ss_phy_0>; phy-names = "usb2-phy", "usb3-phy"; - tx-fifo-resize; dr_mode = "host"; }; }; @@ -812,7 +811,6 @@ interrupts = <0 205 0x4>; phys = <&hs_phy_1>, <&ss_phy_1>; phy-names = "usb2-phy", "usb3-phy"; - tx-fifo-resize; dr_mode = "host"; }; }; diff --git a/target/linux/ipq806x/modules.mk b/target/linux/ipq806x/modules.mk index 38dd195902..6f1ca2d2a4 100644 --- a/target/linux/ipq806x/modules.mk +++ b/target/linux/ipq806x/modules.mk @@ -29,20 +29,3 @@ define KernelPackage/usb-phy-qcom-dwc3/description endef $(eval $(call KernelPackage,usb-phy-qcom-dwc3)) - - -define KernelPackage/usb-dwc3-qcom - TITLE:=DWC3 USB QCOM controller driver - DEPENDS:=@TARGET_ipq806x +kmod-usb-dwc3 +kmod-usb-phy-qcom-dwc3 - KCONFIG:= CONFIG_USB_DWC3_QCOM - FILES:= $(LINUX_DIR)/drivers/usb/dwc3/dwc3-qcom.ko - AUTOLOAD:=$(call AutoLoad,53,dwc3-qcom,1) - $(call AddDepends/usb) -endef - -define KernelPackage/usb-dwc3-qcom/description - This driver provides support for the integrated DesignWare - USB3 IP Core within the QCOM SoCs. -endef - -$(eval $(call KernelPackage,usb-dwc3-qcom)) diff --git a/target/linux/ipq806x/patches-4.4/096-01-usb-dwc3-core-purge-dev_dbg-calls.patch b/target/linux/ipq806x/patches-4.4/096-01-usb-dwc3-core-purge-dev_dbg-calls.patch new file mode 100644 index 0000000000..b940827529 --- /dev/null +++ b/target/linux/ipq806x/patches-4.4/096-01-usb-dwc3-core-purge-dev_dbg-calls.patch @@ -0,0 +1,46 @@ +From 1407bf13e3bf5f1168484c3e68b6ef9d8cf2bc72 Mon Sep 17 00:00:00 2001 +From: Felipe Balbi +Date: Mon, 16 Nov 2015 16:06:37 -0600 +Subject: usb: dwc3: core: purge dev_dbg() calls + +The last few dev_dbg() messages are converted to +tracepoints and we can finally ignore dev_dbg() +messages during debug sessions. + +Signed-off-by: Felipe Balbi +--- + drivers/usb/dwc3/core.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c +index 22b47973..de5e01f 100644 +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -272,7 +272,8 @@ static int dwc3_event_buffers_setup(struct dwc3 *dwc) + + for (n = 0; n < dwc->num_event_buffers; n++) { + evt = dwc->ev_buffs[n]; +- dev_dbg(dwc->dev, "Event buf %p dma %08llx length %d\n", ++ dwc3_trace(trace_dwc3_core, ++ "Event buf %p dma %08llx length %d\n", + evt->buf, (unsigned long long) evt->dma, + evt->length); + +@@ -608,12 +609,13 @@ static int dwc3_core_init(struct dwc3 *dwc) + reg |= DWC3_GCTL_GBLHIBERNATIONEN; + break; + default: +- dev_dbg(dwc->dev, "No power optimization available\n"); ++ dwc3_trace(trace_dwc3_core, "No power optimization available\n"); + } + + /* check if current dwc3 is on simulation board */ + if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) { +- dev_dbg(dwc->dev, "it is on FPGA board\n"); ++ dwc3_trace(trace_dwc3_core, ++ "running on FPGA platform\n"); + dwc->is_fpga = true; + } + +-- +cgit v0.12 diff --git a/target/linux/ipq806x/patches-4.4/096-02-usb-dwc3-Update-maximum_speed-for-SuperSpeedPlus.patch b/target/linux/ipq806x/patches-4.4/096-02-usb-dwc3-Update-maximum_speed-for-SuperSpeedPlus.patch new file mode 100644 index 0000000000..9575166f74 --- /dev/null +++ b/target/linux/ipq806x/patches-4.4/096-02-usb-dwc3-Update-maximum_speed-for-SuperSpeedPlus.patch @@ -0,0 +1,56 @@ +From 2c7f1bd9127a1a49ee25d9c2b2ce17b11c7fb05f Mon Sep 17 00:00:00 2001 +From: John Youn +Date: Fri, 5 Feb 2016 17:08:59 -0800 +Subject: usb: dwc3: Update maximum_speed for SuperSpeedPlus + +If the maximum_speed is not set, set it to a known value, either +SuperSpeed or SuperSpeedPlus based on the type of controller we are +using. If we are on DWC_usb31 controller, check the PHY interface to see +if it is capable of SuperSpeedPlus. + +Also this check is moved after dwc3_core_init() so that we can check +dwc->revision. + +Signed-off-by: John Youn +Signed-off-by: Felipe Balbi +--- + drivers/usb/dwc3/core.c | 17 +++++++++++++---- + 1 file changed, 13 insertions(+), 4 deletions(-) + +diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c +index de5e01f..001c755 100644 +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -962,10 +962,6 @@ static int dwc3_probe(struct platform_device *pdev) + fladj = pdata->fladj_value; + } + +- /* default to superspeed if no maximum_speed passed */ +- if (dwc->maximum_speed == USB_SPEED_UNKNOWN) +- dwc->maximum_speed = USB_SPEED_SUPER; +- + dwc->lpm_nyet_threshold = lpm_nyet_threshold; + dwc->tx_de_emphasis = tx_de_emphasis; + +@@ -1016,6 +1012,19 @@ static int dwc3_probe(struct platform_device *pdev) + goto err1; + } + ++ /* default to superspeed if no maximum_speed passed */ ++ if (dwc->maximum_speed == USB_SPEED_UNKNOWN) { ++ dwc->maximum_speed = USB_SPEED_SUPER; ++ ++ /* ++ * default to superspeed plus if we are capable. ++ */ ++ if (dwc3_is_usb31(dwc) && ++ (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == ++ DWC3_GHWPARAMS3_SSPHY_IFC_GEN2)) ++ dwc->maximum_speed = USB_SPEED_SUPER_PLUS; ++ } ++ + /* Adjust Frame Length */ + dwc3_frame_length_adjustment(dwc, fladj); + +-- +cgit v0.12 diff --git a/target/linux/ipq806x/patches-4.4/096-03-usb-dwc3-Validate-the-maximum_speed-parameter.patch b/target/linux/ipq806x/patches-4.4/096-03-usb-dwc3-Validate-the-maximum_speed-parameter.patch new file mode 100644 index 0000000000..43821266a1 --- /dev/null +++ b/target/linux/ipq806x/patches-4.4/096-03-usb-dwc3-Validate-the-maximum_speed-parameter.patch @@ -0,0 +1,74 @@ +From 77966eb85e6d988a6daaf8ac14ac33026ceb3ab7 Mon Sep 17 00:00:00 2001 +From: John Youn +Date: Fri, 19 Feb 2016 17:31:01 -0800 +Subject: usb: dwc3: Validate the maximum_speed parameter + +Check that dwc->maximum_speed is set to a valid value. Also add an error +when we use it later if we encounter an invalid value. + +Signed-off-by: John Youn +Signed-off-by: Felipe Balbi +--- + drivers/usb/dwc3/core.c | 18 ++++++++++++++++-- + drivers/usb/dwc3/gadget.c | 9 ++++++--- + 2 files changed, 22 insertions(+), 5 deletions(-) + +diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c +index 001c755..17fd814 100644 +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -1012,8 +1012,20 @@ static int dwc3_probe(struct platform_device *pdev) + goto err1; + } + +- /* default to superspeed if no maximum_speed passed */ +- if (dwc->maximum_speed == USB_SPEED_UNKNOWN) { ++ /* Check the maximum_speed parameter */ ++ switch (dwc->maximum_speed) { ++ case USB_SPEED_LOW: ++ case USB_SPEED_FULL: ++ case USB_SPEED_HIGH: ++ case USB_SPEED_SUPER: ++ case USB_SPEED_SUPER_PLUS: ++ break; ++ default: ++ dev_err(dev, "invalid maximum_speed parameter %d\n", ++ dwc->maximum_speed); ++ /* fall through */ ++ case USB_SPEED_UNKNOWN: ++ /* default to superspeed */ + dwc->maximum_speed = USB_SPEED_SUPER; + + /* +@@ -1023,6 +1035,8 @@ static int dwc3_probe(struct platform_device *pdev) + (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == + DWC3_GHWPARAMS3_SSPHY_IFC_GEN2)) + dwc->maximum_speed = USB_SPEED_SUPER_PLUS; ++ ++ break; + } + + /* Adjust Frame Length */ +diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c +index 482e6a1..3ac170f 100644 +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -1670,10 +1670,13 @@ static int dwc3_gadget_start(struct usb_gadget *g, + case USB_SPEED_SUPER_PLUS: + reg |= DWC3_DSTS_SUPERSPEED_PLUS; + break; +- case USB_SPEED_SUPER: /* FALLTHROUGH */ +- case USB_SPEED_UNKNOWN: /* FALTHROUGH */ + default: +- reg |= DWC3_DSTS_SUPERSPEED; ++ dev_err(dwc->dev, "invalid dwc->maximum_speed (%d)\n", ++ dwc->maximum_speed); ++ /* fall through */ ++ case USB_SPEED_SUPER: ++ reg |= DWC3_DCFG_SUPERSPEED; ++ break; + } + } + dwc3_writel(dwc->regs, DWC3_DCFG, reg); +-- +cgit v0.12 diff --git a/target/linux/ipq806x/patches-4.4/096-04-usb-dwc3-DWC_usb31-controller-check.patch b/target/linux/ipq806x/patches-4.4/096-04-usb-dwc3-DWC_usb31-controller-check.patch new file mode 100644 index 0000000000..47278d40c5 --- /dev/null +++ b/target/linux/ipq806x/patches-4.4/096-04-usb-dwc3-DWC_usb31-controller-check.patch @@ -0,0 +1,32 @@ +From c4137a9c841ec7fb300782d211f2d6907f4d6e20 Mon Sep 17 00:00:00 2001 +From: John Youn +Date: Fri, 5 Feb 2016 17:08:18 -0800 +Subject: usb: dwc3: DWC_usb31 controller check + +Add a convenience function to check if the controller is DWC_usb31. + +Signed-off-by: John Youn +Signed-off-by: Felipe Balbi +--- + drivers/usb/dwc3/core.h | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h +index e4f8b90..c0520d67 100644 +--- a/drivers/usb/dwc3/core.h ++++ b/drivers/usb/dwc3/core.h +@@ -1024,6 +1024,12 @@ struct dwc3_gadget_ep_cmd_params { + void dwc3_set_mode(struct dwc3 *dwc, u32 mode); + int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc); + ++/* check whether we are on the DWC_usb31 core */ ++static inline bool dwc3_is_usb31(struct dwc3 *dwc) ++{ ++ return !!(dwc->revision & DWC3_REVISION_IS_DWC31); ++} ++ + #if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE) + int dwc3_host_init(struct dwc3 *dwc); + void dwc3_host_exit(struct dwc3 *dwc); +-- +cgit v0.12 diff --git a/target/linux/ipq806x/patches-4.4/096-05-usb-dwc3-Update-register-fields-for-SuperSpeedPlus.patch b/target/linux/ipq806x/patches-4.4/096-05-usb-dwc3-Update-register-fields-for-SuperSpeedPlus.patch new file mode 100644 index 0000000000..e4805db0b4 --- /dev/null +++ b/target/linux/ipq806x/patches-4.4/096-05-usb-dwc3-Update-register-fields-for-SuperSpeedPlus.patch @@ -0,0 +1,46 @@ +From 1f38f88a24c86d46cf47782ffabd5457f231f8ca Mon Sep 17 00:00:00 2001 +From: John Youn +Date: Fri, 5 Feb 2016 17:08:31 -0800 +Subject: usb: dwc3: Update register fields for SuperSpeedPlus + +Update various registers fields definitions for the DWC_usb31 controller +for SuperSpeedPlus support. + +Signed-off-by: John Youn +Signed-off-by: Felipe Balbi +--- + drivers/usb/dwc3/core.h | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h +index c0520d67..6254b2f 100644 +--- a/drivers/usb/dwc3/core.h ++++ b/drivers/usb/dwc3/core.h +@@ -223,7 +223,8 @@ + /* Global HWPARAMS3 Register */ + #define DWC3_GHWPARAMS3_SSPHY_IFC(n) ((n) & 3) + #define DWC3_GHWPARAMS3_SSPHY_IFC_DIS 0 +-#define DWC3_GHWPARAMS3_SSPHY_IFC_ENA 1 ++#define DWC3_GHWPARAMS3_SSPHY_IFC_GEN1 1 ++#define DWC3_GHWPARAMS3_SSPHY_IFC_GEN2 2 /* DWC_usb31 only */ + #define DWC3_GHWPARAMS3_HSPHY_IFC(n) (((n) & (3 << 2)) >> 2) + #define DWC3_GHWPARAMS3_HSPHY_IFC_DIS 0 + #define DWC3_GHWPARAMS3_HSPHY_IFC_UTMI 1 +@@ -249,6 +250,7 @@ + #define DWC3_DCFG_DEVADDR_MASK DWC3_DCFG_DEVADDR(0x7f) + + #define DWC3_DCFG_SPEED_MASK (7 << 0) ++#define DWC3_DCFG_SUPERSPEED_PLUS (5 << 0) /* DWC_usb31 only */ + #define DWC3_DCFG_SUPERSPEED (4 << 0) + #define DWC3_DCFG_HIGHSPEED (0 << 0) + #define DWC3_DCFG_FULLSPEED2 (1 << 0) +@@ -339,6 +341,7 @@ + + #define DWC3_DSTS_CONNECTSPD (7 << 0) + ++#define DWC3_DSTS_SUPERSPEED_PLUS (5 << 0) /* DWC_usb31 only */ + #define DWC3_DSTS_SUPERSPEED (4 << 0) + #define DWC3_DSTS_HIGHSPEED (0 << 0) + #define DWC3_DSTS_FULLSPEED2 (1 << 0) +-- +cgit v0.12 diff --git a/target/linux/ipq806x/patches-4.4/096-06-usb-dwc3-core-improve-reset-sequence.patch b/target/linux/ipq806x/patches-4.4/096-06-usb-dwc3-core-improve-reset-sequence.patch new file mode 100644 index 0000000000..197dd057d2 --- /dev/null +++ b/target/linux/ipq806x/patches-4.4/096-06-usb-dwc3-core-improve-reset-sequence.patch @@ -0,0 +1,101 @@ +From f59dcab176293b646e1358144c93c58c3cda2813 Mon Sep 17 00:00:00 2001 +From: Felipe Balbi +Date: Fri, 11 Mar 2016 10:51:52 +0200 +Subject: usb: dwc3: core: improve reset sequence + +According to Synopsys Databook, we shouldn't be +relying on GCTL.CORESOFTRESET bit as that's only for +debugging purposes. Instead, let's use DCTL.CSFTRST +if we're OTG or PERIPHERAL mode. + +Host side block will be reset by XHCI driver if +necessary. Note that this reduces amount of time +spent on dwc3_probe() by a long margin. + +We're still gonna wait for reset to finish for a +long time (default to 1ms max), but tests show that +the reset polling loop executed at most 19 times +(modprobe dwc3 && modprobe -r dwc3 executed 1000 +times in a row). + +Suggested-by: Mian Yousaf Kaukab +Signed-off-by: Felipe Balbi +--- + drivers/usb/dwc3/core.c | 48 ++++++++++++++++++------------------------------ + 1 file changed, 18 insertions(+), 30 deletions(-) + +diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c +index 17fd814..fa20f5a9 100644 +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -67,23 +67,9 @@ void dwc3_set_mode(struct dwc3 *dwc, u32 mode) + static int dwc3_core_soft_reset(struct dwc3 *dwc) + { + u32 reg; ++ int retries = 1000; + int ret; + +- /* Before Resetting PHY, put Core in Reset */ +- reg = dwc3_readl(dwc->regs, DWC3_GCTL); +- reg |= DWC3_GCTL_CORESOFTRESET; +- dwc3_writel(dwc->regs, DWC3_GCTL, reg); +- +- /* Assert USB3 PHY reset */ +- reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); +- reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST; +- dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); +- +- /* Assert USB2 PHY reset */ +- reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); +- reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST; +- dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); +- + usb_phy_init(dwc->usb2_phy); + usb_phy_init(dwc->usb3_phy); + ret = phy_init(dwc->usb2_generic_phy); +@@ -95,26 +81,28 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc) + phy_exit(dwc->usb2_generic_phy); + return ret; + } +- mdelay(100); + +- /* Clear USB3 PHY reset */ +- reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); +- reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST; +- dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); ++ /* ++ * We're resetting only the device side because, if we're in host mode, ++ * XHCI driver will reset the host block. If dwc3 was configured for ++ * host-only mode, then we can return early. ++ */ ++ if (dwc->dr_mode == USB_DR_MODE_HOST) ++ return 0; + +- /* Clear USB2 PHY reset */ +- reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); +- reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; +- dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); ++ reg = dwc3_readl(dwc->regs, DWC3_DCTL); ++ reg |= DWC3_DCTL_CSFTRST; ++ dwc3_writel(dwc->regs, DWC3_DCTL, reg); + +- mdelay(100); ++ do { ++ reg = dwc3_readl(dwc->regs, DWC3_DCTL); ++ if (!(reg & DWC3_DCTL_CSFTRST)) ++ return 0; + +- /* After PHYs are stable we can take Core out of reset state */ +- reg = dwc3_readl(dwc->regs, DWC3_GCTL); +- reg &= ~DWC3_GCTL_CORESOFTRESET; +- dwc3_writel(dwc->regs, DWC3_GCTL, reg); ++ udelay(1); ++ } while (--retries); + +- return 0; ++ return -ETIMEDOUT; + } + + /** +-- +cgit v0.12 diff --git a/target/linux/ipq806x/patches-4.4/096-07-usb-dwc3-drop-FIFO-resizing-logic.patch b/target/linux/ipq806x/patches-4.4/096-07-usb-dwc3-drop-FIFO-resizing-logic.patch new file mode 100644 index 0000000000..9b6026d914 --- /dev/null +++ b/target/linux/ipq806x/patches-4.4/096-07-usb-dwc3-drop-FIFO-resizing-logic.patch @@ -0,0 +1,258 @@ +From bc5081617faeb3b2f0c126dc37264b87af7da47f Mon Sep 17 00:00:00 2001 +From: Felipe Balbi +Date: Thu, 4 Feb 2016 14:18:01 +0200 +Subject: usb: dwc3: drop FIFO resizing logic + +That FIFO resizing logic was added to support OMAP5 +ES1.0 which had a bogus default FIFO size. I can't +remember the exact size of default FIFO, but it was +less than one bulk superspeed packet (<1024) which +would prevent USB3 from ever working on OMAP5 ES1.0. + +However, OMAP5 ES1.0 support has been dropped by +commit aa2f4b16f830 ("ARM: OMAP5: id: Remove ES1.0 +support") which renders FIFO resizing unnecessary. + +Tested-by: Kishon Vijay Abraham I +Signed-off-by: Felipe Balbi +--- + Documentation/devicetree/bindings/usb/dwc3.txt | 4 +- + .../devicetree/bindings/usb/qcom,dwc3.txt | 1 - + drivers/usb/dwc3/core.c | 4 - + drivers/usb/dwc3/core.h | 5 -- + drivers/usb/dwc3/ep0.c | 9 --- + drivers/usb/dwc3/gadget.c | 86 ---------------------- + drivers/usb/dwc3/platform_data.h | 1 - + 7 files changed, 2 insertions(+), 108 deletions(-) + +diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt +index fb2ad0a..1569568 100644 +--- a/Documentation/devicetree/bindings/usb/dwc3.txt ++++ b/Documentation/devicetree/bindings/usb/dwc3.txt +@@ -14,7 +14,6 @@ Optional properties: + the second element is expected to be a handle to the USB3/SS PHY + - phys: from the *Generic PHY* bindings + - phy-names: from the *Generic PHY* bindings +- - tx-fifo-resize: determines if the FIFO *has* to be reallocated. + - snps,usb3_lpm_capable: determines if platform is USB3 LPM capable + - snps,disable_scramble_quirk: true when SW should disable data scrambling. + Only really useful for FPGA builds. +@@ -47,6 +46,8 @@ Optional properties: + register for post-silicon frame length adjustment when the + fladj_30mhz_sdbnd signal is invalid or incorrect. + ++ - tx-fifo-resize: determines if the FIFO *has* to be reallocated. ++ + This is usually a subnode to DWC3 glue to which it is connected. + + dwc3@4a030000 { +@@ -54,5 +55,4 @@ dwc3@4a030000 { + reg = <0x4a030000 0xcfff>; + interrupts = <0 92 4> + usb-phy = <&usb2_phy>, <&usb3,phy>; +- tx-fifo-resize; + }; +diff --git a/Documentation/devicetree/bindings/usb/qcom,dwc3.txt b/Documentation/devicetree/bindings/usb/qcom,dwc3.txt +index ca164e7..39acb08 100644 +--- a/Documentation/devicetree/bindings/usb/qcom,dwc3.txt ++++ b/Documentation/devicetree/bindings/usb/qcom,dwc3.txt +@@ -59,7 +59,6 @@ Example device nodes: + interrupts = <0 205 0x4>; + phys = <&hs_phy>, <&ss_phy>; + phy-names = "usb2-phy", "usb3-phy"; +- tx-fifo-resize; + dr_mode = "host"; + }; + }; +diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c +index fa20f5a9..67d183a 100644 +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -882,9 +882,6 @@ static int dwc3_probe(struct platform_device *pdev) + dwc->usb3_lpm_capable = device_property_read_bool(dev, + "snps,usb3_lpm_capable"); + +- dwc->needs_fifo_resize = device_property_read_bool(dev, +- "tx-fifo-resize"); +- + dwc->disable_scramble_quirk = device_property_read_bool(dev, + "snps,disable_scramble_quirk"); + dwc->u2exit_lfps_quirk = device_property_read_bool(dev, +@@ -926,7 +923,6 @@ static int dwc3_probe(struct platform_device *pdev) + if (pdata->hird_threshold) + hird_threshold = pdata->hird_threshold; + +- dwc->needs_fifo_resize = pdata->tx_fifo_resize; + dwc->usb3_lpm_capable = pdata->usb3_lpm_capable; + dwc->dr_mode = pdata->dr_mode; + +diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h +index 6254b2f..7cbe9e9 100644 +--- a/drivers/usb/dwc3/core.h ++++ b/drivers/usb/dwc3/core.h +@@ -709,9 +709,7 @@ struct dwc3_scratchpad_array { + * 0 - utmi_sleep_n + * 1 - utmi_l1_suspend_n + * @is_fpga: true when we are using the FPGA board +- * @needs_fifo_resize: not all users might want fifo resizing, flag it + * @pullups_connected: true when Run/Stop bit is set +- * @resize_fifos: tells us it's ok to reconfigure our TxFIFO sizes. + * @setup_packet_pending: true when there's a Setup Packet in FIFO. Workaround + * @start_config_issued: true when StartConfig command has been issued + * @three_stage_setup: set if we perform a three phase setup +@@ -855,9 +853,7 @@ struct dwc3 { + unsigned has_lpm_erratum:1; + unsigned is_utmi_l1_suspend:1; + unsigned is_fpga:1; +- unsigned needs_fifo_resize:1; + unsigned pullups_connected:1; +- unsigned resize_fifos:1; + unsigned setup_packet_pending:1; + unsigned three_stage_setup:1; + unsigned usb3_lpm_capable:1; +@@ -1025,7 +1021,6 @@ struct dwc3_gadget_ep_cmd_params { + + /* prototypes */ + void dwc3_set_mode(struct dwc3 *dwc, u32 mode); +-int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc); + + /* check whether we are on the DWC_usb31 core */ + static inline bool dwc3_is_usb31(struct dwc3 *dwc) +diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c +index eca2e6d..4454de0 100644 +--- a/drivers/usb/dwc3/ep0.c ++++ b/drivers/usb/dwc3/ep0.c +@@ -586,9 +586,6 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) + reg = dwc3_readl(dwc->regs, DWC3_DCTL); + reg |= (DWC3_DCTL_ACCEPTU1ENA | DWC3_DCTL_ACCEPTU2ENA); + dwc3_writel(dwc->regs, DWC3_DCTL, reg); +- +- dwc->resize_fifos = true; +- dwc3_trace(trace_dwc3_ep0, "resize FIFOs flag SET"); + } + break; + +@@ -1027,12 +1024,6 @@ static int dwc3_ep0_start_control_status(struct dwc3_ep *dep) + + static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep) + { +- if (dwc->resize_fifos) { +- dwc3_trace(trace_dwc3_ep0, "Resizing FIFOs"); +- dwc3_gadget_resize_tx_fifos(dwc); +- dwc->resize_fifos = 0; +- } +- + WARN_ON(dwc3_ep0_start_control_status(dep)); + } + +diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c +index d54a028..3a5c271 100644 +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -145,92 +145,6 @@ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state) + return -ETIMEDOUT; + } + +-/** +- * dwc3_gadget_resize_tx_fifos - reallocate fifo spaces for current use-case +- * @dwc: pointer to our context structure +- * +- * This function will a best effort FIFO allocation in order +- * to improve FIFO usage and throughput, while still allowing +- * us to enable as many endpoints as possible. +- * +- * Keep in mind that this operation will be highly dependent +- * on the configured size for RAM1 - which contains TxFifo -, +- * the amount of endpoints enabled on coreConsultant tool, and +- * the width of the Master Bus. +- * +- * In the ideal world, we would always be able to satisfy the +- * following equation: +- * +- * ((512 + 2 * MDWIDTH-Bytes) + (Number of IN Endpoints - 1) * \ +- * (3 * (1024 + MDWIDTH-Bytes) + MDWIDTH-Bytes)) / MDWIDTH-Bytes +- * +- * Unfortunately, due to many variables that's not always the case. +- */ +-int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc) +-{ +- int last_fifo_depth = 0; +- int ram1_depth; +- int fifo_size; +- int mdwidth; +- int num; +- +- if (!dwc->needs_fifo_resize) +- return 0; +- +- ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7); +- mdwidth = DWC3_MDWIDTH(dwc->hwparams.hwparams0); +- +- /* MDWIDTH is represented in bits, we need it in bytes */ +- mdwidth >>= 3; +- +- /* +- * FIXME For now we will only allocate 1 wMaxPacketSize space +- * for each enabled endpoint, later patches will come to +- * improve this algorithm so that we better use the internal +- * FIFO space +- */ +- for (num = 0; num < dwc->num_in_eps; num++) { +- /* bit0 indicates direction; 1 means IN ep */ +- struct dwc3_ep *dep = dwc->eps[(num << 1) | 1]; +- int mult = 1; +- int tmp; +- +- if (!(dep->flags & DWC3_EP_ENABLED)) +- continue; +- +- if (usb_endpoint_xfer_bulk(dep->endpoint.desc) +- || usb_endpoint_xfer_isoc(dep->endpoint.desc)) +- mult = 3; +- +- /* +- * REVISIT: the following assumes we will always have enough +- * space available on the FIFO RAM for all possible use cases. +- * Make sure that's true somehow and change FIFO allocation +- * accordingly. +- * +- * If we have Bulk or Isochronous endpoints, we want +- * them to be able to be very, very fast. So we're giving +- * those endpoints a fifo_size which is enough for 3 full +- * packets +- */ +- tmp = mult * (dep->endpoint.maxpacket + mdwidth); +- tmp += mdwidth; +- +- fifo_size = DIV_ROUND_UP(tmp, mdwidth); +- +- fifo_size |= (last_fifo_depth << 16); +- +- dwc3_trace(trace_dwc3_gadget, "%s: Fifo Addr %04x Size %d", +- dep->name, last_fifo_depth, fifo_size & 0xffff); +- +- dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(num), fifo_size); +- +- last_fifo_depth += (fifo_size & 0xffff); +- } +- +- return 0; +-} +- + void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, + int status) + { +diff --git a/drivers/usb/dwc3/platform_data.h b/drivers/usb/dwc3/platform_data.h +index 2bb4d3a..aaa6f00 100644 +--- a/drivers/usb/dwc3/platform_data.h ++++ b/drivers/usb/dwc3/platform_data.h +@@ -23,7 +23,6 @@ + struct dwc3_platform_data { + enum usb_device_speed maximum_speed; + enum usb_dr_mode dr_mode; +- bool tx_fifo_resize; + bool usb3_lpm_capable; + + unsigned is_utmi_l1_suspend:1; +-- +cgit v0.12 diff --git a/target/linux/ipq806x/patches-4.4/096-08-usb-dwc3-remove-num_event_buffers.patch b/target/linux/ipq806x/patches-4.4/096-08-usb-dwc3-remove-num_event_buffers.patch new file mode 100644 index 0000000000..8bc0b9817f --- /dev/null +++ b/target/linux/ipq806x/patches-4.4/096-08-usb-dwc3-remove-num_event_buffers.patch @@ -0,0 +1,273 @@ +From 660e9bde74d6915227d7ee3485b11e5f52637b26 Mon Sep 17 00:00:00 2001 +From: Felipe Balbi +Date: Wed, 30 Mar 2016 09:26:24 +0300 +Subject: usb: dwc3: remove num_event_buffers + +We never, ever route any of the other event buffers +so we might as well drop support for them. + +Until someone has a real, proper benefit for +multiple event buffers, we will rely on a single +one. This also helps reduce memory footprint of +dwc3.ko which won't allocate memory for the extra +event buffers. + +Signed-off-by: Felipe Balbi +--- + drivers/usb/dwc3/core.c | 81 +++++++++++++++++++---------------------------- + drivers/usb/dwc3/core.h | 2 -- + drivers/usb/dwc3/gadget.c | 38 +++++++--------------- + 3 files changed, 44 insertions(+), 77 deletions(-) + +diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c +index 67d183a..9e5c57c7 100644 +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -203,13 +203,10 @@ static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, + static void dwc3_free_event_buffers(struct dwc3 *dwc) + { + struct dwc3_event_buffer *evt; +- int i; + +- for (i = 0; i < dwc->num_event_buffers; i++) { +- evt = dwc->ev_buffs[i]; +- if (evt) +- dwc3_free_one_event_buffer(dwc, evt); +- } ++ evt = dwc->ev_buffs[0]; ++ if (evt) ++ dwc3_free_one_event_buffer(dwc, evt); + } + + /** +@@ -222,27 +219,19 @@ static void dwc3_free_event_buffers(struct dwc3 *dwc) + */ + static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) + { +- int num; +- int i; +- +- num = DWC3_NUM_INT(dwc->hwparams.hwparams1); +- dwc->num_event_buffers = num; ++ struct dwc3_event_buffer *evt; + +- dwc->ev_buffs = devm_kzalloc(dwc->dev, sizeof(*dwc->ev_buffs) * num, ++ dwc->ev_buffs = devm_kzalloc(dwc->dev, sizeof(*dwc->ev_buffs), + GFP_KERNEL); + if (!dwc->ev_buffs) + return -ENOMEM; + +- for (i = 0; i < num; i++) { +- struct dwc3_event_buffer *evt; +- +- evt = dwc3_alloc_one_event_buffer(dwc, length); +- if (IS_ERR(evt)) { +- dev_err(dwc->dev, "can't allocate event buffer\n"); +- return PTR_ERR(evt); +- } +- dwc->ev_buffs[i] = evt; ++ evt = dwc3_alloc_one_event_buffer(dwc, length); ++ if (IS_ERR(evt)) { ++ dev_err(dwc->dev, "can't allocate event buffer\n"); ++ return PTR_ERR(evt); + } ++ dwc->ev_buffs[0] = evt; + + return 0; + } +@@ -256,25 +245,22 @@ static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) + static int dwc3_event_buffers_setup(struct dwc3 *dwc) + { + struct dwc3_event_buffer *evt; +- int n; + +- for (n = 0; n < dwc->num_event_buffers; n++) { +- evt = dwc->ev_buffs[n]; +- dwc3_trace(trace_dwc3_core, +- "Event buf %p dma %08llx length %d\n", +- evt->buf, (unsigned long long) evt->dma, +- evt->length); +- +- evt->lpos = 0; +- +- dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), +- lower_32_bits(evt->dma)); +- dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), +- upper_32_bits(evt->dma)); +- dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), +- DWC3_GEVNTSIZ_SIZE(evt->length)); +- dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); +- } ++ evt = dwc->ev_buffs[0]; ++ dwc3_trace(trace_dwc3_core, ++ "Event buf %p dma %08llx length %d\n", ++ evt->buf, (unsigned long long) evt->dma, ++ evt->length); ++ ++ evt->lpos = 0; ++ ++ dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0), ++ lower_32_bits(evt->dma)); ++ dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0), ++ upper_32_bits(evt->dma)); ++ dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), ++ DWC3_GEVNTSIZ_SIZE(evt->length)); ++ dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0); + + return 0; + } +@@ -282,19 +268,16 @@ static int dwc3_event_buffers_setup(struct dwc3 *dwc) + static void dwc3_event_buffers_cleanup(struct dwc3 *dwc) + { + struct dwc3_event_buffer *evt; +- int n; + +- for (n = 0; n < dwc->num_event_buffers; n++) { +- evt = dwc->ev_buffs[n]; ++ evt = dwc->ev_buffs[0]; + +- evt->lpos = 0; ++ evt->lpos = 0; + +- dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0); +- dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0); +- dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), DWC3_GEVNTSIZ_INTMASK +- | DWC3_GEVNTSIZ_SIZE(0)); +- dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); +- } ++ dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0), 0); ++ dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0), 0); ++ dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), DWC3_GEVNTSIZ_INTMASK ++ | DWC3_GEVNTSIZ_SIZE(0)); ++ dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0); + } + + static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc) +diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h +index 4ea4b51..be03999 100644 +--- a/drivers/usb/dwc3/core.h ++++ b/drivers/usb/dwc3/core.h +@@ -667,7 +667,6 @@ struct dwc3_scratchpad_array { + * @regs: base address for our registers + * @regs_size: address space size + * @nr_scratch: number of scratch buffers +- * @num_event_buffers: calculated number of event buffers + * @u1u2: only used on revisions <1.83a for workaround + * @maximum_speed: maximum speed requested (mainly for testing purposes) + * @revision: revision register contents +@@ -778,7 +777,6 @@ struct dwc3 { + u32 gctl; + + u32 nr_scratch; +- u32 num_event_buffers; + u32 u1u2; + u32 maximum_speed; + +diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c +index e6bd3a9..5e6a495 100644 +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -2602,14 +2602,14 @@ static void dwc3_process_event_entry(struct dwc3 *dwc, + } + } + +-static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf) ++static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc) + { + struct dwc3_event_buffer *evt; + irqreturn_t ret = IRQ_NONE; + int left; + u32 reg; + +- evt = dwc->ev_buffs[buf]; ++ evt = dwc->ev_buffs[0]; + left = evt->count; + + if (!(evt->flags & DWC3_EVENT_PENDING)) +@@ -2634,7 +2634,7 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf) + evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE; + left -= 4; + +- dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(buf), 4); ++ dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 4); + } + + evt->count = 0; +@@ -2642,9 +2642,9 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf) + ret = IRQ_HANDLED; + + /* Unmask interrupt */ +- reg = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(buf)); ++ reg = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(0)); + reg &= ~DWC3_GEVNTSIZ_INTMASK; +- dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(buf), reg); ++ dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), reg); + + return ret; + } +@@ -2654,27 +2654,23 @@ static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc) + struct dwc3 *dwc = _dwc; + unsigned long flags; + irqreturn_t ret = IRQ_NONE; +- int i; + + spin_lock_irqsave(&dwc->lock, flags); +- +- for (i = 0; i < dwc->num_event_buffers; i++) +- ret |= dwc3_process_event_buf(dwc, i); +- ++ ret = dwc3_process_event_buf(dwc); + spin_unlock_irqrestore(&dwc->lock, flags); + + return ret; + } + +-static irqreturn_t dwc3_check_event_buf(struct dwc3 *dwc, u32 buf) ++static irqreturn_t dwc3_check_event_buf(struct dwc3 *dwc) + { + struct dwc3_event_buffer *evt; + u32 count; + u32 reg; + +- evt = dwc->ev_buffs[buf]; ++ evt = dwc->ev_buffs[0]; + +- count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(buf)); ++ count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0)); + count &= DWC3_GEVNTCOUNT_MASK; + if (!count) + return IRQ_NONE; +@@ -2683,9 +2679,9 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3 *dwc, u32 buf) + evt->flags |= DWC3_EVENT_PENDING; + + /* Mask interrupt */ +- reg = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(buf)); ++ reg = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(0)); + reg |= DWC3_GEVNTSIZ_INTMASK; +- dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(buf), reg); ++ dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), reg); + + return IRQ_WAKE_THREAD; + } +@@ -2693,18 +2689,8 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3 *dwc, u32 buf) + static irqreturn_t dwc3_interrupt(int irq, void *_dwc) + { + struct dwc3 *dwc = _dwc; +- int i; +- irqreturn_t ret = IRQ_NONE; +- +- for (i = 0; i < dwc->num_event_buffers; i++) { +- irqreturn_t status; + +- status = dwc3_check_event_buf(dwc, i); +- if (status == IRQ_WAKE_THREAD) +- ret = status; +- } +- +- return ret; ++ return dwc3_check_event_buf(dwc); + } + + /** +-- +cgit v0.12 diff --git a/target/linux/ipq806x/patches-4.4/096-09-usb-dwc3-drop-ev_buffs-array.patch b/target/linux/ipq806x/patches-4.4/096-09-usb-dwc3-drop-ev_buffs-array.patch new file mode 100644 index 0000000000..64d796cf38 --- /dev/null +++ b/target/linux/ipq806x/patches-4.4/096-09-usb-dwc3-drop-ev_buffs-array.patch @@ -0,0 +1,104 @@ +From 696c8b1282205caa5206264449f80ef756f14ef7 Mon Sep 17 00:00:00 2001 +From: Felipe Balbi +Date: Wed, 30 Mar 2016 09:37:03 +0300 +Subject: usb: dwc3: drop ev_buffs array + +we will be using a single event buffer and that +renders ev_buffs array unnecessary. Let's remove it +in favor of a single pointer to a single event +buffer. + +Signed-off-by: Felipe Balbi +--- + drivers/usb/dwc3/core.c | 13 ++++--------- + drivers/usb/dwc3/core.h | 2 +- + drivers/usb/dwc3/gadget.c | 4 ++-- + 3 files changed, 7 insertions(+), 12 deletions(-) + +diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c +index 9e5c57c7..05b7ec3 100644 +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -204,7 +204,7 @@ static void dwc3_free_event_buffers(struct dwc3 *dwc) + { + struct dwc3_event_buffer *evt; + +- evt = dwc->ev_buffs[0]; ++ evt = dwc->ev_buf; + if (evt) + dwc3_free_one_event_buffer(dwc, evt); + } +@@ -221,17 +221,12 @@ static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) + { + struct dwc3_event_buffer *evt; + +- dwc->ev_buffs = devm_kzalloc(dwc->dev, sizeof(*dwc->ev_buffs), +- GFP_KERNEL); +- if (!dwc->ev_buffs) +- return -ENOMEM; +- + evt = dwc3_alloc_one_event_buffer(dwc, length); + if (IS_ERR(evt)) { + dev_err(dwc->dev, "can't allocate event buffer\n"); + return PTR_ERR(evt); + } +- dwc->ev_buffs[0] = evt; ++ dwc->ev_buf = evt; + + return 0; + } +@@ -246,7 +241,7 @@ static int dwc3_event_buffers_setup(struct dwc3 *dwc) + { + struct dwc3_event_buffer *evt; + +- evt = dwc->ev_buffs[0]; ++ evt = dwc->ev_buf; + dwc3_trace(trace_dwc3_core, + "Event buf %p dma %08llx length %d\n", + evt->buf, (unsigned long long) evt->dma, +@@ -269,7 +264,7 @@ static void dwc3_event_buffers_cleanup(struct dwc3 *dwc) + { + struct dwc3_event_buffer *evt; + +- evt = dwc->ev_buffs[0]; ++ evt = dwc->ev_buf; + + evt->lpos = 0; + +diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h +index be03999..df72234a 100644 +--- a/drivers/usb/dwc3/core.h ++++ b/drivers/usb/dwc3/core.h +@@ -753,7 +753,7 @@ struct dwc3 { + struct platform_device *xhci; + struct resource xhci_resources[DWC3_XHCI_RESOURCES_NUM]; + +- struct dwc3_event_buffer **ev_buffs; ++ struct dwc3_event_buffer *ev_buf; + struct dwc3_ep *eps[DWC3_ENDPOINTS_NUM]; + + struct usb_gadget gadget; +diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c +index 5e6a495..96dfde0 100644 +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -2609,7 +2609,7 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc) + int left; + u32 reg; + +- evt = dwc->ev_buffs[0]; ++ evt = dwc->ev_buf; + left = evt->count; + + if (!(evt->flags & DWC3_EVENT_PENDING)) +@@ -2668,7 +2668,7 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3 *dwc) + u32 count; + u32 reg; + +- evt = dwc->ev_buffs[0]; ++ evt = dwc->ev_buf; + + count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0)); + count &= DWC3_GEVNTCOUNT_MASK; +-- +cgit v0.12 diff --git a/target/linux/ipq806x/patches-4.4/096-10-usb-dwc3-core-fix-PHY-handling-during-suspend.patch b/target/linux/ipq806x/patches-4.4/096-10-usb-dwc3-core-fix-PHY-handling-during-suspend.patch new file mode 100644 index 0000000000..87f1562cc6 --- /dev/null +++ b/target/linux/ipq806x/patches-4.4/096-10-usb-dwc3-core-fix-PHY-handling-during-suspend.patch @@ -0,0 +1,71 @@ +From 5c4ad318de3b8e8680d654c82a254c4b65243739 Mon Sep 17 00:00:00 2001 +From: Felipe Balbi +Date: Mon, 11 Apr 2016 17:12:34 +0300 +Subject: usb: dwc3: core: fix PHY handling during suspend + +we need to power off the PHY during suspend and +power it back on during resume. + +Signed-off-by: Felipe Balbi +[nsekhar@ti.com: fix call to usb_phy_set_suspend() in dwc3_suspend()] +Signed-off-by: Sekhar Nori +Signed-off-by: Roger Quadros +Signed-off-by: Felipe Balbi +--- + drivers/usb/dwc3/core.c | 23 ++++++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) + +diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c +index fa20f5a9..34277ce 100644 +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -1150,6 +1150,11 @@ static int dwc3_suspend(struct device *dev) + phy_exit(dwc->usb2_generic_phy); + phy_exit(dwc->usb3_generic_phy); + ++ usb_phy_set_suspend(dwc->usb2_phy, 1); ++ usb_phy_set_suspend(dwc->usb3_phy, 1); ++ WARN_ON(phy_power_off(dwc->usb2_generic_phy) < 0); ++ WARN_ON(phy_power_off(dwc->usb3_generic_phy) < 0); ++ + pinctrl_pm_select_sleep_state(dev); + + return 0; +@@ -1163,11 +1168,21 @@ static int dwc3_resume(struct device *dev) + + pinctrl_pm_select_default_state(dev); + ++ usb_phy_set_suspend(dwc->usb2_phy, 0); ++ usb_phy_set_suspend(dwc->usb3_phy, 0); ++ ret = phy_power_on(dwc->usb2_generic_phy); ++ if (ret < 0) ++ return ret; ++ ++ ret = phy_power_on(dwc->usb3_generic_phy); ++ if (ret < 0) ++ goto err_usb2phy_power; ++ + usb_phy_init(dwc->usb3_phy); + usb_phy_init(dwc->usb2_phy); + ret = phy_init(dwc->usb2_generic_phy); + if (ret < 0) +- return ret; ++ goto err_usb3phy_power; + + ret = phy_init(dwc->usb3_generic_phy); + if (ret < 0) +@@ -1200,6 +1215,12 @@ static int dwc3_resume(struct device *dev) + err_usb2phy_init: + phy_exit(dwc->usb2_generic_phy); + ++err_usb3phy_power: ++ phy_power_off(dwc->usb3_generic_phy); ++ ++err_usb2phy_power: ++ phy_power_off(dwc->usb2_generic_phy); ++ + return ret; + } + +-- +cgit v0.12 diff --git a/target/linux/ipq806x/patches-4.4/097-1-usb-dwc3-add-generic-OF-glue-layer.patch b/target/linux/ipq806x/patches-4.4/097-1-usb-dwc3-add-generic-OF-glue-layer.patch new file mode 100644 index 0000000000..214bedc95a --- /dev/null +++ b/target/linux/ipq806x/patches-4.4/097-1-usb-dwc3-add-generic-OF-glue-layer.patch @@ -0,0 +1,234 @@ +From 41c2b5280cd2fa3e198c422cdf223ba6e48f857a Mon Sep 17 00:00:00 2001 +From: Felipe Balbi +Date: Wed, 18 Nov 2015 13:15:20 -0600 +Subject: [PATCH] usb: dwc3: add generic OF glue layer + +For simple platforms which merely enable some clocks +and populate its children, we can use this generic +glue layer to avoid boilerplate code duplication. + +For now this supports Qcom and Xilinx, but if we +find a way to add generic handling of regulators and +optional PHYs, we can absorb exynos as well. + +Tested-by: Subbaraya Sundeep Bhatta +Signed-off-by: Felipe Balbi +(cherry picked from commit 16adc674d0d68a50dfc725574738d7ae11cf5d7e) + +Change-Id: I6fd260442997b198dc12ca726814b7a9518e6353 +Signed-off-by: Nitheesh Sekar +--- + drivers/usb/dwc3/Kconfig | 9 ++ + drivers/usb/dwc3/Makefile | 1 + + drivers/usb/dwc3/dwc3-of-simple.c | 178 ++++++++++++++++++++++++++++++++++++++ + 3 files changed, 188 insertions(+) + create mode 100644 drivers/usb/dwc3/dwc3-of-simple.c + +--- a/drivers/usb/dwc3/Kconfig ++++ b/drivers/usb/dwc3/Kconfig +@@ -87,6 +87,15 @@ config USB_DWC3_KEYSTONE + Support of USB2/3 functionality in TI Keystone2 platforms. + Say 'Y' or 'M' here if you have one such device + ++config USB_DWC3_OF_SIMPLE ++ tristate "Generic OF Simple Glue Layer" ++ depends on OF && COMMON_CLK ++ default USB_DWC3 ++ help ++ Support USB2/3 functionality in simple SoC integrations. ++ Currently supports Xilinx and Qualcomm DWC USB3 IP. ++ Say 'Y' or 'M' if you have one such device. ++ + config USB_DWC3_ST + tristate "STMicroelectronics Platforms" + depends on ARCH_STI && OF +--- a/drivers/usb/dwc3/Makefile ++++ b/drivers/usb/dwc3/Makefile +@@ -37,5 +37,6 @@ obj-$(CONFIG_USB_DWC3_OMAP) += dwc3-oma + obj-$(CONFIG_USB_DWC3_EXYNOS) += dwc3-exynos.o + obj-$(CONFIG_USB_DWC3_PCI) += dwc3-pci.o + obj-$(CONFIG_USB_DWC3_KEYSTONE) += dwc3-keystone.o ++obj-$(CONFIG_USB_DWC3_OF_SIMPLE) += dwc3-of-simple.o + obj-$(CONFIG_USB_DWC3_QCOM) += dwc3-qcom.o + obj-$(CONFIG_USB_DWC3_ST) += dwc3-st.o +--- /dev/null ++++ b/drivers/usb/dwc3/dwc3-of-simple.c +@@ -0,0 +1,178 @@ ++/** ++ * dwc3-of-simple.c - OF glue layer for simple integrations ++ * ++ * Copyright (c) 2015 Texas Instruments Incorporated - http://www.ti.com ++ * ++ * Author: Felipe Balbi ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 of ++ * the License as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * This is a combination of the old dwc3-qcom.c by Ivan T. Ivanov ++ * and the original patch adding support for Xilinx' SoC ++ * by Subbaraya Sundeep Bhatta ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct dwc3_of_simple { ++ struct device *dev; ++ struct clk **clks; ++ int num_clocks; ++}; ++ ++static int dwc3_of_simple_probe(struct platform_device *pdev) ++{ ++ struct dwc3_of_simple *simple; ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ ++ int ret; ++ int i; ++ ++ simple = devm_kzalloc(dev, sizeof(*simple), GFP_KERNEL); ++ if (!simple) ++ return -ENOMEM; ++ ++ ret = of_clk_get_parent_count(np); ++ if (ret < 0) ++ return ret; ++ ++ simple->num_clocks = ret; ++ ++ simple->clks = devm_kcalloc(dev, simple->num_clocks, ++ sizeof(struct clk *), GFP_KERNEL); ++ if (!simple->clks) ++ return -ENOMEM; ++ ++ simple->dev = dev; ++ ++ for (i = 0; i < simple->num_clocks; i++) { ++ struct clk *clk; ++ ++ clk = of_clk_get(np, i); ++ if (IS_ERR(clk)) { ++ while (--i >= 0) ++ clk_put(simple->clks[i]); ++ return PTR_ERR(clk); ++ } ++ ++ ret = clk_prepare_enable(clk); ++ if (ret < 0) { ++ while (--i >= 0) { ++ clk_disable_unprepare(simple->clks[i]); ++ clk_put(simple->clks[i]); ++ } ++ clk_put(clk); ++ ++ return ret; ++ } ++ ++ simple->clks[i] = clk; ++ } ++ ++ ret = of_platform_populate(np, NULL, NULL, dev); ++ if (ret) { ++ for (i = 0; i < simple->num_clocks; i++) { ++ clk_disable_unprepare(simple->clks[i]); ++ clk_put(simple->clks[i]); ++ } ++ ++ return ret; ++ } ++ ++ pm_runtime_set_active(dev); ++ pm_runtime_enable(dev); ++ pm_runtime_get_sync(dev); ++ ++ return 0; ++} ++ ++static int dwc3_of_simple_remove(struct platform_device *pdev) ++{ ++ struct dwc3_of_simple *simple = platform_get_drvdata(pdev); ++ struct device *dev = &pdev->dev; ++ int i; ++ ++ for (i = 0; i < simple->num_clocks; i++) { ++ clk_unprepare(simple->clks[i]); ++ clk_put(simple->clks[i]); ++ } ++ ++ of_platform_depopulate(dev); ++ ++ pm_runtime_put_sync(dev); ++ pm_runtime_disable(dev); ++ ++ return 0; ++} ++ ++static int dwc3_of_simple_runtime_suspend(struct device *dev) ++{ ++ struct dwc3_of_simple *simple = dev_get_drvdata(dev); ++ int i; ++ ++ for (i = 0; i < simple->num_clocks; i++) ++ clk_disable(simple->clks[i]); ++ ++ return 0; ++} ++ ++static int dwc3_of_simple_runtime_resume(struct device *dev) ++{ ++ struct dwc3_of_simple *simple = dev_get_drvdata(dev); ++ int ret; ++ int i; ++ ++ for (i = 0; i < simple->num_clocks; i++) { ++ ret = clk_enable(simple->clks[i]); ++ if (ret < 0) { ++ while (--i >= 0) ++ clk_disable(simple->clks[i]); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops dwc3_of_simple_dev_pm_ops = { ++ SET_RUNTIME_PM_OPS(dwc3_of_simple_runtime_suspend, ++ dwc3_of_simple_runtime_resume, NULL) ++}; ++ ++static const struct of_device_id of_dwc3_simple_match[] = { ++ { .compatible = "qcom,dwc3" }, ++ { .compatible = "xlnx,zynqmp-dwc3" }, ++ { /* Sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, of_dwc3_simple_match); ++ ++static struct platform_driver dwc3_of_simple_driver = { ++ .probe = dwc3_of_simple_probe, ++ .remove = dwc3_of_simple_remove, ++ .driver = { ++ .name = "dwc3-of-simple", ++ .of_match_table = of_dwc3_simple_match, ++ }, ++}; ++ ++module_platform_driver(dwc3_of_simple_driver); ++MODULE_LICENSE("GPL v2"); ++MODULE_DESCRIPTION("DesignWare USB3 OF Simple Glue Layer"); ++MODULE_AUTHOR("Felipe Balbi "); diff --git a/target/linux/ipq806x/patches-4.4/097-2-usb-dwc3-of-simple-fix-build-warning-on-PM.patch b/target/linux/ipq806x/patches-4.4/097-2-usb-dwc3-of-simple-fix-build-warning-on-PM.patch new file mode 100644 index 0000000000..b982c82367 --- /dev/null +++ b/target/linux/ipq806x/patches-4.4/097-2-usb-dwc3-of-simple-fix-build-warning-on-PM.patch @@ -0,0 +1,36 @@ +From 131386d63ca3177d471aa93808c69b85fdac520d Mon Sep 17 00:00:00 2001 +From: Felipe Balbi +Date: Tue, 22 Dec 2015 21:56:10 -0600 +Subject: [PATCH] usb: dwc3: of-simple: fix build warning on !PM + +if we have a !PM kernel build, our runtime +suspend/resume callbacks will be left defined but +unused. Add a ifdef CONFIG_PM guard. + +Signed-off-by: Felipe Balbi +(cherry picked from commit 5072cfc40a80cea3749fd3413b3896630d8c787e) + +Change-Id: I088186c33aa917ec8da2985372ceefc289b24242 +Signed-off-by: Nitheesh Sekar +--- + drivers/usb/dwc3/dwc3-of-simple.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/usb/dwc3/dwc3-of-simple.c ++++ b/drivers/usb/dwc3/dwc3-of-simple.c +@@ -122,6 +122,7 @@ static int dwc3_of_simple_remove(struct + return 0; + } + ++#ifdef CONFIG_PM + static int dwc3_of_simple_runtime_suspend(struct device *dev) + { + struct dwc3_of_simple *simple = dev_get_drvdata(dev); +@@ -150,6 +151,7 @@ static int dwc3_of_simple_runtime_resume + + return 0; + } ++#endif + + static const struct dev_pm_ops dwc3_of_simple_dev_pm_ops = { + SET_RUNTIME_PM_OPS(dwc3_of_simple_runtime_suspend, diff --git a/target/linux/ipq806x/patches-4.4/097-3-usb-dwc3-Remove-impossible-check-for-of_clk_get_pare.patch b/target/linux/ipq806x/patches-4.4/097-3-usb-dwc3-Remove-impossible-check-for-of_clk_get_pare.patch new file mode 100644 index 0000000000..32f9e34177 --- /dev/null +++ b/target/linux/ipq806x/patches-4.4/097-3-usb-dwc3-Remove-impossible-check-for-of_clk_get_pare.patch @@ -0,0 +1,47 @@ +From 07c8b15688055d81ac8e1c8c964b9e4c302287f1 Mon Sep 17 00:00:00 2001 +From: Stephen Boyd +Date: Mon, 22 Feb 2016 11:12:47 -0800 +Subject: [PATCH] usb: dwc3: Remove impossible check for + of_clk_get_parent_count() < 0 + +The check for < 0 is impossible now that +of_clk_get_parent_count() returns an unsigned int. Simplify the +code and update the types. + +Acked-by: Felipe Balbi +Cc: +Signed-off-by: Stephen Boyd +(cherry picked from commit 3d755dcc20dd452b52532eca17da40ebbd12aee9) + +Change-Id: Iaa38e064d801fb36c855fea51c0443840368e0d3 +Signed-off-by: Nitheesh Sekar +--- + drivers/usb/dwc3/dwc3-of-simple.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/drivers/usb/dwc3/dwc3-of-simple.c ++++ b/drivers/usb/dwc3/dwc3-of-simple.c +@@ -42,6 +42,7 @@ static int dwc3_of_simple_probe(struct p + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + ++ unsigned int count; + int ret; + int i; + +@@ -49,11 +50,11 @@ static int dwc3_of_simple_probe(struct p + if (!simple) + return -ENOMEM; + +- ret = of_clk_get_parent_count(np); +- if (ret < 0) +- return ret; ++ count = of_clk_get_parent_count(np); ++ if (!count) ++ return -ENOENT; + +- simple->num_clocks = ret; ++ simple->num_clocks = count; + + simple->clks = devm_kcalloc(dev, simple->num_clocks, + sizeof(struct clk *), GFP_KERNEL); diff --git a/target/linux/ipq806x/patches-4.4/097-4-usb-dwc3-fix-missing-platform_set_drvdata-in-dwc3_of_simple_probe.patch b/target/linux/ipq806x/patches-4.4/097-4-usb-dwc3-fix-missing-platform_set_drvdata-in-dwc3_of_simple_probe.patch new file mode 100644 index 0000000000..2aeadc30ed --- /dev/null +++ b/target/linux/ipq806x/patches-4.4/097-4-usb-dwc3-fix-missing-platform_set_drvdata-in-dwc3_of_simple_probe.patch @@ -0,0 +1,31 @@ +From 4c4f106c032ff32b89c98a4d819e68e6e643c14e Mon Sep 17 00:00:00 2001 +From: Wei Yongjun +Date: Tue, 26 Jul 2016 14:47:00 +0000 +Subject: usb: dwc3: fix missing platform_set_drvdata() in + dwc3_of_simple_probe() + +Add missing platform_set_drvdata() in dwc3_of_simple_probe(), otherwise +calling platform_get_drvdata() in remove returns NULL. + +This is detected by Coccinelle semantic patch. + +Signed-off-by: Wei Yongjun +Signed-off-by: Felipe Balbi +--- + drivers/usb/dwc3/dwc3-of-simple.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/usb/dwc3/dwc3-of-simple.c b/drivers/usb/dwc3/dwc3-of-simple.c +index 9743353..e56d59b 100644 +--- a/drivers/usb/dwc3/dwc3-of-simple.c ++++ b/drivers/usb/dwc3/dwc3-of-simple.c +@@ -61,6 +61,7 @@ static int dwc3_of_simple_probe(struct platform_device *pdev) + if (!simple->clks) + return -ENOMEM; + ++ platform_set_drvdata(pdev, simple); + simple->dev = dev; + + for (i = 0; i < simple->num_clocks; i++) { +-- +cgit v0.12 diff --git a/target/linux/ipq806x/patches-4.4/097-usb-dwc3-add-generic-OF-glue-layer.patch b/target/linux/ipq806x/patches-4.4/097-usb-dwc3-add-generic-OF-glue-layer.patch deleted file mode 100644 index 214bedc95a..0000000000 --- a/target/linux/ipq806x/patches-4.4/097-usb-dwc3-add-generic-OF-glue-layer.patch +++ /dev/null @@ -1,234 +0,0 @@ -From 41c2b5280cd2fa3e198c422cdf223ba6e48f857a Mon Sep 17 00:00:00 2001 -From: Felipe Balbi -Date: Wed, 18 Nov 2015 13:15:20 -0600 -Subject: [PATCH] usb: dwc3: add generic OF glue layer - -For simple platforms which merely enable some clocks -and populate its children, we can use this generic -glue layer to avoid boilerplate code duplication. - -For now this supports Qcom and Xilinx, but if we -find a way to add generic handling of regulators and -optional PHYs, we can absorb exynos as well. - -Tested-by: Subbaraya Sundeep Bhatta -Signed-off-by: Felipe Balbi -(cherry picked from commit 16adc674d0d68a50dfc725574738d7ae11cf5d7e) - -Change-Id: I6fd260442997b198dc12ca726814b7a9518e6353 -Signed-off-by: Nitheesh Sekar ---- - drivers/usb/dwc3/Kconfig | 9 ++ - drivers/usb/dwc3/Makefile | 1 + - drivers/usb/dwc3/dwc3-of-simple.c | 178 ++++++++++++++++++++++++++++++++++++++ - 3 files changed, 188 insertions(+) - create mode 100644 drivers/usb/dwc3/dwc3-of-simple.c - ---- a/drivers/usb/dwc3/Kconfig -+++ b/drivers/usb/dwc3/Kconfig -@@ -87,6 +87,15 @@ config USB_DWC3_KEYSTONE - Support of USB2/3 functionality in TI Keystone2 platforms. - Say 'Y' or 'M' here if you have one such device - -+config USB_DWC3_OF_SIMPLE -+ tristate "Generic OF Simple Glue Layer" -+ depends on OF && COMMON_CLK -+ default USB_DWC3 -+ help -+ Support USB2/3 functionality in simple SoC integrations. -+ Currently supports Xilinx and Qualcomm DWC USB3 IP. -+ Say 'Y' or 'M' if you have one such device. -+ - config USB_DWC3_ST - tristate "STMicroelectronics Platforms" - depends on ARCH_STI && OF ---- a/drivers/usb/dwc3/Makefile -+++ b/drivers/usb/dwc3/Makefile -@@ -37,5 +37,6 @@ obj-$(CONFIG_USB_DWC3_OMAP) += dwc3-oma - obj-$(CONFIG_USB_DWC3_EXYNOS) += dwc3-exynos.o - obj-$(CONFIG_USB_DWC3_PCI) += dwc3-pci.o - obj-$(CONFIG_USB_DWC3_KEYSTONE) += dwc3-keystone.o -+obj-$(CONFIG_USB_DWC3_OF_SIMPLE) += dwc3-of-simple.o - obj-$(CONFIG_USB_DWC3_QCOM) += dwc3-qcom.o - obj-$(CONFIG_USB_DWC3_ST) += dwc3-st.o ---- /dev/null -+++ b/drivers/usb/dwc3/dwc3-of-simple.c -@@ -0,0 +1,178 @@ -+/** -+ * dwc3-of-simple.c - OF glue layer for simple integrations -+ * -+ * Copyright (c) 2015 Texas Instruments Incorporated - http://www.ti.com -+ * -+ * Author: Felipe Balbi -+ * -+ * This program is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 of -+ * the License as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * This is a combination of the old dwc3-qcom.c by Ivan T. Ivanov -+ * and the original patch adding support for Xilinx' SoC -+ * by Subbaraya Sundeep Bhatta -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct dwc3_of_simple { -+ struct device *dev; -+ struct clk **clks; -+ int num_clocks; -+}; -+ -+static int dwc3_of_simple_probe(struct platform_device *pdev) -+{ -+ struct dwc3_of_simple *simple; -+ struct device *dev = &pdev->dev; -+ struct device_node *np = dev->of_node; -+ -+ int ret; -+ int i; -+ -+ simple = devm_kzalloc(dev, sizeof(*simple), GFP_KERNEL); -+ if (!simple) -+ return -ENOMEM; -+ -+ ret = of_clk_get_parent_count(np); -+ if (ret < 0) -+ return ret; -+ -+ simple->num_clocks = ret; -+ -+ simple->clks = devm_kcalloc(dev, simple->num_clocks, -+ sizeof(struct clk *), GFP_KERNEL); -+ if (!simple->clks) -+ return -ENOMEM; -+ -+ simple->dev = dev; -+ -+ for (i = 0; i < simple->num_clocks; i++) { -+ struct clk *clk; -+ -+ clk = of_clk_get(np, i); -+ if (IS_ERR(clk)) { -+ while (--i >= 0) -+ clk_put(simple->clks[i]); -+ return PTR_ERR(clk); -+ } -+ -+ ret = clk_prepare_enable(clk); -+ if (ret < 0) { -+ while (--i >= 0) { -+ clk_disable_unprepare(simple->clks[i]); -+ clk_put(simple->clks[i]); -+ } -+ clk_put(clk); -+ -+ return ret; -+ } -+ -+ simple->clks[i] = clk; -+ } -+ -+ ret = of_platform_populate(np, NULL, NULL, dev); -+ if (ret) { -+ for (i = 0; i < simple->num_clocks; i++) { -+ clk_disable_unprepare(simple->clks[i]); -+ clk_put(simple->clks[i]); -+ } -+ -+ return ret; -+ } -+ -+ pm_runtime_set_active(dev); -+ pm_runtime_enable(dev); -+ pm_runtime_get_sync(dev); -+ -+ return 0; -+} -+ -+static int dwc3_of_simple_remove(struct platform_device *pdev) -+{ -+ struct dwc3_of_simple *simple = platform_get_drvdata(pdev); -+ struct device *dev = &pdev->dev; -+ int i; -+ -+ for (i = 0; i < simple->num_clocks; i++) { -+ clk_unprepare(simple->clks[i]); -+ clk_put(simple->clks[i]); -+ } -+ -+ of_platform_depopulate(dev); -+ -+ pm_runtime_put_sync(dev); -+ pm_runtime_disable(dev); -+ -+ return 0; -+} -+ -+static int dwc3_of_simple_runtime_suspend(struct device *dev) -+{ -+ struct dwc3_of_simple *simple = dev_get_drvdata(dev); -+ int i; -+ -+ for (i = 0; i < simple->num_clocks; i++) -+ clk_disable(simple->clks[i]); -+ -+ return 0; -+} -+ -+static int dwc3_of_simple_runtime_resume(struct device *dev) -+{ -+ struct dwc3_of_simple *simple = dev_get_drvdata(dev); -+ int ret; -+ int i; -+ -+ for (i = 0; i < simple->num_clocks; i++) { -+ ret = clk_enable(simple->clks[i]); -+ if (ret < 0) { -+ while (--i >= 0) -+ clk_disable(simple->clks[i]); -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ -+static const struct dev_pm_ops dwc3_of_simple_dev_pm_ops = { -+ SET_RUNTIME_PM_OPS(dwc3_of_simple_runtime_suspend, -+ dwc3_of_simple_runtime_resume, NULL) -+}; -+ -+static const struct of_device_id of_dwc3_simple_match[] = { -+ { .compatible = "qcom,dwc3" }, -+ { .compatible = "xlnx,zynqmp-dwc3" }, -+ { /* Sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, of_dwc3_simple_match); -+ -+static struct platform_driver dwc3_of_simple_driver = { -+ .probe = dwc3_of_simple_probe, -+ .remove = dwc3_of_simple_remove, -+ .driver = { -+ .name = "dwc3-of-simple", -+ .of_match_table = of_dwc3_simple_match, -+ }, -+}; -+ -+module_platform_driver(dwc3_of_simple_driver); -+MODULE_LICENSE("GPL v2"); -+MODULE_DESCRIPTION("DesignWare USB3 OF Simple Glue Layer"); -+MODULE_AUTHOR("Felipe Balbi "); diff --git a/target/linux/ipq806x/patches-4.4/098-usb-dwc3-of-simple-fix-build-warning-on-PM.patch b/target/linux/ipq806x/patches-4.4/098-usb-dwc3-of-simple-fix-build-warning-on-PM.patch deleted file mode 100644 index b982c82367..0000000000 --- a/target/linux/ipq806x/patches-4.4/098-usb-dwc3-of-simple-fix-build-warning-on-PM.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 131386d63ca3177d471aa93808c69b85fdac520d Mon Sep 17 00:00:00 2001 -From: Felipe Balbi -Date: Tue, 22 Dec 2015 21:56:10 -0600 -Subject: [PATCH] usb: dwc3: of-simple: fix build warning on !PM - -if we have a !PM kernel build, our runtime -suspend/resume callbacks will be left defined but -unused. Add a ifdef CONFIG_PM guard. - -Signed-off-by: Felipe Balbi -(cherry picked from commit 5072cfc40a80cea3749fd3413b3896630d8c787e) - -Change-Id: I088186c33aa917ec8da2985372ceefc289b24242 -Signed-off-by: Nitheesh Sekar ---- - drivers/usb/dwc3/dwc3-of-simple.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/usb/dwc3/dwc3-of-simple.c -+++ b/drivers/usb/dwc3/dwc3-of-simple.c -@@ -122,6 +122,7 @@ static int dwc3_of_simple_remove(struct - return 0; - } - -+#ifdef CONFIG_PM - static int dwc3_of_simple_runtime_suspend(struct device *dev) - { - struct dwc3_of_simple *simple = dev_get_drvdata(dev); -@@ -150,6 +151,7 @@ static int dwc3_of_simple_runtime_resume - - return 0; - } -+#endif - - static const struct dev_pm_ops dwc3_of_simple_dev_pm_ops = { - SET_RUNTIME_PM_OPS(dwc3_of_simple_runtime_suspend, diff --git a/target/linux/ipq806x/patches-4.4/099-usb-dwc3-Remove-impossible-check-for-of_clk_get_pare.patch b/target/linux/ipq806x/patches-4.4/099-usb-dwc3-Remove-impossible-check-for-of_clk_get_pare.patch deleted file mode 100644 index 32f9e34177..0000000000 --- a/target/linux/ipq806x/patches-4.4/099-usb-dwc3-Remove-impossible-check-for-of_clk_get_pare.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 07c8b15688055d81ac8e1c8c964b9e4c302287f1 Mon Sep 17 00:00:00 2001 -From: Stephen Boyd -Date: Mon, 22 Feb 2016 11:12:47 -0800 -Subject: [PATCH] usb: dwc3: Remove impossible check for - of_clk_get_parent_count() < 0 - -The check for < 0 is impossible now that -of_clk_get_parent_count() returns an unsigned int. Simplify the -code and update the types. - -Acked-by: Felipe Balbi -Cc: -Signed-off-by: Stephen Boyd -(cherry picked from commit 3d755dcc20dd452b52532eca17da40ebbd12aee9) - -Change-Id: Iaa38e064d801fb36c855fea51c0443840368e0d3 -Signed-off-by: Nitheesh Sekar ---- - drivers/usb/dwc3/dwc3-of-simple.c | 9 +++++---- - 1 file changed, 5 insertions(+), 4 deletions(-) - ---- a/drivers/usb/dwc3/dwc3-of-simple.c -+++ b/drivers/usb/dwc3/dwc3-of-simple.c -@@ -42,6 +42,7 @@ static int dwc3_of_simple_probe(struct p - struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; - -+ unsigned int count; - int ret; - int i; - -@@ -49,11 +50,11 @@ static int dwc3_of_simple_probe(struct p - if (!simple) - return -ENOMEM; - -- ret = of_clk_get_parent_count(np); -- if (ret < 0) -- return ret; -+ count = of_clk_get_parent_count(np); -+ if (!count) -+ return -ENOENT; - -- simple->num_clocks = ret; -+ simple->num_clocks = count; - - simple->clks = devm_kcalloc(dev, simple->num_clocks, - sizeof(struct clk *), GFP_KERNEL); diff --git a/target/linux/ipq806x/patches-4.4/101-ARM-qcom-add-USB-nodes-to-ipq806x-ap148.patch b/target/linux/ipq806x/patches-4.4/101-ARM-qcom-add-USB-nodes-to-ipq806x-ap148.patch index 6e6f10d549..d1f19c367e 100644 --- a/target/linux/ipq806x/patches-4.4/101-ARM-qcom-add-USB-nodes-to-ipq806x-ap148.patch +++ b/target/linux/ipq806x/patches-4.4/101-ARM-qcom-add-USB-nodes-to-ipq806x-ap148.patch @@ -32,7 +32,7 @@ }; --- a/arch/arm/boot/dts/qcom-ipq8064.dtsi +++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi -@@ -333,6 +333,90 @@ +@@ -333,6 +333,88 @@ compatible = "syscon"; reg = <0x01200600 0x100>; }; @@ -94,7 +94,6 @@ + interrupts = <0 110 0x4>; + phys = <&hs_phy_0>, <&ss_phy_0>; + phy-names = "usb2-phy", "usb3-phy"; -+ tx-fifo-resize; + dr_mode = "host"; + }; + }; @@ -116,7 +115,6 @@ + interrupts = <0 205 0x4>; + phys = <&hs_phy_1>, <&ss_phy_1>; + phy-names = "usb2-phy", "usb3-phy"; -+ tx-fifo-resize; + dr_mode = "host"; + }; + };