|
|
@@ -1,9 +1,9 @@
|
|
|
-From b14460ee524a34d3b94b44032b52155c4cd708e5 Mon Sep 17 00:00:00 2001
|
|
|
+From a2a97f0d2c07a772899ca09967547bea6c9124c5 Mon Sep 17 00:00:00 2001
|
|
|
From: Yangbo Lu <[email protected]>
|
|
|
-Date: Wed, 27 Sep 2017 10:34:07 +0800
|
|
|
-Subject: [PATCH] usb: support layerscape
|
|
|
+Date: Wed, 17 Jan 2018 15:46:03 +0800
|
|
|
+Subject: [PATCH 29/30] usb: support layerscape
|
|
|
|
|
|
-This is a integrated patch for layerscape usb support.
|
|
|
+This is an integrated patch for layerscape usb support.
|
|
|
|
|
|
Signed-off-by: yinbo.zhu <[email protected]>
|
|
|
Signed-off-by: Ramneek Mehresh <[email protected]>
|
|
|
@@ -15,29 +15,68 @@ Signed-off-by: Suresh Gupta <[email protected]>
|
|
|
Signed-off-by: Zhao Chenhui <[email protected]>
|
|
|
Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
---
|
|
|
- drivers/net/usb/r8152.c | 4 +
|
|
|
+ drivers/net/usb/cdc_ether.c | 8 +
|
|
|
+ drivers/net/usb/r8152.c | 6 +
|
|
|
drivers/usb/common/common.c | 50 ++++++
|
|
|
drivers/usb/core/hub.c | 8 +
|
|
|
- drivers/usb/dwc3/core.c | 235 ++++++++++++++++++++++++++-
|
|
|
- drivers/usb/dwc3/core.h | 46 +++++-
|
|
|
- drivers/usb/dwc3/host.c | 15 +-
|
|
|
+ drivers/usb/dwc3/core.c | 243 ++++++++++++++++++++++++++++-
|
|
|
+ drivers/usb/dwc3/core.h | 51 ++++++-
|
|
|
+ drivers/usb/dwc3/ep0.c | 4 +-
|
|
|
+ drivers/usb/dwc3/gadget.c | 7 +
|
|
|
+ drivers/usb/dwc3/host.c | 24 ++-
|
|
|
drivers/usb/gadget/udc/fsl_udc_core.c | 46 +++---
|
|
|
drivers/usb/gadget/udc/fsl_usb2_udc.h | 16 +-
|
|
|
drivers/usb/host/Kconfig | 2 +-
|
|
|
- drivers/usb/host/ehci-fsl.c | 289 +++++++++++++++++++++++++++++++---
|
|
|
+ drivers/usb/host/ehci-fsl.c | 279 +++++++++++++++++++++++++++++++---
|
|
|
drivers/usb/host/ehci-fsl.h | 3 +
|
|
|
- drivers/usb/host/ehci-hub.c | 2 +
|
|
|
- drivers/usb/host/ehci.h | 5 +
|
|
|
+ drivers/usb/host/ehci-hub.c | 4 +
|
|
|
+ drivers/usb/host/ehci.h | 9 ++
|
|
|
drivers/usb/host/fsl-mph-dr-of.c | 12 ++
|
|
|
+ drivers/usb/host/xhci-plat.c | 10 ++
|
|
|
+ drivers/usb/host/xhci-ring.c | 29 +++-
|
|
|
+ drivers/usb/host/xhci.c | 38 ++++-
|
|
|
+ drivers/usb/host/xhci.h | 5 +-
|
|
|
drivers/usb/phy/phy-fsl-usb.c | 59 +++++--
|
|
|
drivers/usb/phy/phy-fsl-usb.h | 8 +
|
|
|
include/linux/usb.h | 1 +
|
|
|
include/linux/usb/of.h | 2 +
|
|
|
- 18 files changed, 730 insertions(+), 73 deletions(-)
|
|
|
+ 25 files changed, 836 insertions(+), 88 deletions(-)
|
|
|
|
|
|
+--- a/drivers/net/usb/cdc_ether.c
|
|
|
++++ b/drivers/net/usb/cdc_ether.c
|
|
|
+@@ -532,6 +532,7 @@ static const struct driver_info wwan_inf
|
|
|
+ #define LENOVO_VENDOR_ID 0x17ef
|
|
|
+ #define NVIDIA_VENDOR_ID 0x0955
|
|
|
+ #define HP_VENDOR_ID 0x03f0
|
|
|
++#define TPLINK_VENDOR_ID 0x2357
|
|
|
+
|
|
|
+ static const struct usb_device_id products[] = {
|
|
|
+ /* BLACKLIST !!
|
|
|
+@@ -732,6 +733,13 @@ static const struct usb_device_id produc
|
|
|
+ USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
|
|
+ .driver_info = 0,
|
|
|
+ },
|
|
|
++
|
|
|
++ /* TP-LINK UE300 USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */
|
|
|
++{
|
|
|
++ USB_DEVICE_AND_INTERFACE_INFO(TPLINK_VENDOR_ID, 0x0601, USB_CLASS_COMM,
|
|
|
++ USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
|
|
++ .driver_info = 0,
|
|
|
++},
|
|
|
+
|
|
|
+ /* WHITELIST!!!
|
|
|
+ *
|
|
|
--- a/drivers/net/usb/r8152.c
|
|
|
+++ b/drivers/net/usb/r8152.c
|
|
|
-@@ -1816,6 +1816,10 @@ static int rx_bottom(struct r8152 *tp, i
|
|
|
+@@ -520,6 +520,7 @@ enum rtl8152_flags {
|
|
|
+ #define VENDOR_ID_SAMSUNG 0x04e8
|
|
|
+ #define VENDOR_ID_LENOVO 0x17ef
|
|
|
+ #define VENDOR_ID_NVIDIA 0x0955
|
|
|
++#define VENDOR_ID_TPLINK 0x2357
|
|
|
+
|
|
|
+ #define MCU_TYPE_PLA 0x0100
|
|
|
+ #define MCU_TYPE_USB 0x0000
|
|
|
+@@ -1816,6 +1817,10 @@ static int rx_bottom(struct r8152 *tp, i
|
|
|
unsigned int pkt_len;
|
|
|
struct sk_buff *skb;
|
|
|
|
|
|
@@ -48,6 +87,14 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
pkt_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK;
|
|
|
if (pkt_len < ETH_ZLEN)
|
|
|
break;
|
|
|
+@@ -4507,6 +4512,7 @@ static struct usb_device_id rtl8152_tabl
|
|
|
+ {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7205)},
|
|
|
+ {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x304f)},
|
|
|
+ {REALTEK_USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff)},
|
|
|
++ {REALTEK_USB_DEVICE(VENDOR_ID_TPLINK, 0x0601)},
|
|
|
+ {}
|
|
|
+ };
|
|
|
+
|
|
|
--- a/drivers/usb/common/common.c
|
|
|
+++ b/drivers/usb/common/common.c
|
|
|
@@ -105,6 +105,56 @@ static const char *const usb_dr_modes[]
|
|
|
@@ -280,7 +327,7 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
/* Adjust Frame Length */
|
|
|
dwc3_frame_length_adjustment(dwc);
|
|
|
|
|
|
-@@ -919,11 +1034,109 @@ static void dwc3_core_exit_mode(struct d
|
|
|
+@@ -919,11 +1034,117 @@ static void dwc3_core_exit_mode(struct d
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -325,6 +372,12 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
+ &hird_threshold);
|
|
|
+ dwc->usb3_lpm_capable = device_property_read_bool(dev,
|
|
|
+ "snps,usb3_lpm_capable");
|
|
|
++ dwc->quirk_reverse_in_out = device_property_read_bool(dev,
|
|
|
++ "snps,quirk_reverse_in_out");
|
|
|
++ dwc->quirk_stop_transfer_in_block = device_property_read_bool(dev,
|
|
|
++ "snps,quirk_stop_transfer_in_block");
|
|
|
++ dwc->quirk_stop_ep_in_u1 = device_property_read_bool(dev,
|
|
|
++ "snps,quirk_stop_ep_in_u1");
|
|
|
+
|
|
|
+ dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
|
|
|
+
|
|
|
@@ -365,6 +418,8 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
+
|
|
|
+ dwc->tx_de_emphasis_quirk = device_property_read_bool(dev,
|
|
|
+ "snps,tx_de_emphasis_quirk");
|
|
|
++ dwc->disable_devinit_u1u2_quirk = device_property_read_bool(dev,
|
|
|
++ "snps,disable_devinit_u1u2");
|
|
|
+ device_property_read_u8(dev, "snps,tx_de_emphasis",
|
|
|
+ &tx_de_emphasis);
|
|
|
+ device_property_read_string(dev, "snps,hsphy_interface",
|
|
|
@@ -390,7 +445,7 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
struct resource *res;
|
|
|
struct dwc3 *dwc;
|
|
|
u8 lpm_nyet_threshold;
|
|
|
-@@ -955,6 +1168,11 @@ static int dwc3_probe(struct platform_de
|
|
|
+@@ -955,6 +1176,11 @@ static int dwc3_probe(struct platform_de
|
|
|
dwc->xhci_resources[0].flags = res->flags;
|
|
|
dwc->xhci_resources[0].name = res->name;
|
|
|
|
|
|
@@ -402,7 +457,7 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
res->start += DWC3_GLOBALS_REGS_START;
|
|
|
|
|
|
/*
|
|
|
-@@ -997,6 +1215,12 @@ static int dwc3_probe(struct platform_de
|
|
|
+@@ -997,6 +1223,12 @@ static int dwc3_probe(struct platform_de
|
|
|
dwc->usb3_lpm_capable = device_property_read_bool(dev,
|
|
|
"snps,usb3_lpm_capable");
|
|
|
|
|
|
@@ -415,7 +470,7 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
dwc->disable_scramble_quirk = device_property_read_bool(dev,
|
|
|
"snps,disable_scramble_quirk");
|
|
|
dwc->u2exit_lfps_quirk = device_property_read_bool(dev,
|
|
|
-@@ -1041,6 +1265,8 @@ static int dwc3_probe(struct platform_de
|
|
|
+@@ -1041,6 +1273,8 @@ static int dwc3_probe(struct platform_de
|
|
|
dwc->hird_threshold = hird_threshold
|
|
|
| (dwc->is_utmi_l1_suspend << 4);
|
|
|
|
|
|
@@ -424,7 +479,7 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
platform_set_drvdata(pdev, dwc);
|
|
|
dwc3_cache_hwparams(dwc);
|
|
|
|
|
|
-@@ -1064,6 +1290,11 @@ static int dwc3_probe(struct platform_de
|
|
|
+@@ -1064,6 +1298,11 @@ static int dwc3_probe(struct platform_de
|
|
|
if (ret < 0)
|
|
|
goto err1;
|
|
|
|
|
|
@@ -506,7 +561,15 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
* @irq_gadget: peripheral controller's IRQ number
|
|
|
* @nr_scratch: number of scratch buffers
|
|
|
* @u1u2: only used on revisions <1.83a for workaround
|
|
|
-@@ -847,6 +878,7 @@ struct dwc3 {
|
|
|
+@@ -829,6 +860,7 @@ struct dwc3_scratchpad_array {
|
|
|
+ * 1 - -3.5dB de-emphasis
|
|
|
+ * 2 - No de-emphasis
|
|
|
+ * 3 - Reserved
|
|
|
++ * @disable_devinit_u1u2_quirk: disable device-initiated U1/U2 request.
|
|
|
+ */
|
|
|
+ struct dwc3 {
|
|
|
+ struct usb_ctrlrequest *ctrl_req;
|
|
|
+@@ -847,6 +879,7 @@ struct dwc3 {
|
|
|
spinlock_t lock;
|
|
|
|
|
|
struct device *dev;
|
|
|
@@ -514,7 +577,7 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
|
|
|
struct platform_device *xhci;
|
|
|
struct resource xhci_resources[DWC3_XHCI_RESOURCES_NUM];
|
|
|
-@@ -872,6 +904,12 @@ struct dwc3 {
|
|
|
+@@ -872,6 +905,12 @@ struct dwc3 {
|
|
|
enum usb_phy_interface hsphy_mode;
|
|
|
|
|
|
u32 fladj;
|
|
|
@@ -527,7 +590,7 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
u32 irq_gadget;
|
|
|
u32 nr_scratch;
|
|
|
u32 u1u2;
|
|
|
-@@ -948,9 +986,12 @@ struct dwc3 {
|
|
|
+@@ -948,9 +987,12 @@ struct dwc3 {
|
|
|
unsigned ep0_bounced:1;
|
|
|
unsigned ep0_expect_in:1;
|
|
|
unsigned has_hibernation:1;
|
|
|
@@ -540,7 +603,7 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
unsigned pending_events:1;
|
|
|
unsigned pullups_connected:1;
|
|
|
unsigned setup_packet_pending:1;
|
|
|
-@@ -971,9 +1012,12 @@ struct dwc3 {
|
|
|
+@@ -971,9 +1013,16 @@ struct dwc3 {
|
|
|
unsigned dis_rxdet_inp3_quirk:1;
|
|
|
unsigned dis_u2_freeclk_exists_quirk:1;
|
|
|
unsigned dis_del_phy_power_chg_quirk:1;
|
|
|
@@ -548,11 +611,52 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
|
|
|
unsigned tx_de_emphasis_quirk:1;
|
|
|
unsigned tx_de_emphasis:2;
|
|
|
++ unsigned disable_devinit_u1u2_quirk:1;
|
|
|
++ unsigned quirk_reverse_in_out:1;
|
|
|
++ unsigned quirk_stop_transfer_in_block:1;
|
|
|
++ unsigned quirk_stop_ep_in_u1:1;
|
|
|
+
|
|
|
+ u16 imod_interval;
|
|
|
};
|
|
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
|
+--- a/drivers/usb/dwc3/ep0.c
|
|
|
++++ b/drivers/usb/dwc3/ep0.c
|
|
|
+@@ -360,9 +360,9 @@ static int dwc3_ep0_handle_status(struct
|
|
|
+ if ((dwc->speed == DWC3_DSTS_SUPERSPEED) ||
|
|
|
+ (dwc->speed == DWC3_DSTS_SUPERSPEED_PLUS)) {
|
|
|
+ reg = dwc3_readl(dwc->regs, DWC3_DCTL);
|
|
|
+- if (reg & DWC3_DCTL_INITU1ENA)
|
|
|
++ if ((reg & DWC3_DCTL_INITU1ENA) && !dwc->disable_devinit_u1u2_quirk)
|
|
|
+ usb_status |= 1 << USB_DEV_STAT_U1_ENABLED;
|
|
|
+- if (reg & DWC3_DCTL_INITU2ENA)
|
|
|
++ if ((reg & DWC3_DCTL_INITU2ENA) && !dwc->disable_devinit_u1u2_quirk)
|
|
|
+ usb_status |= 1 << USB_DEV_STAT_U2_ENABLED;
|
|
|
+ }
|
|
|
+
|
|
|
+--- a/drivers/usb/dwc3/gadget.c
|
|
|
++++ b/drivers/usb/dwc3/gadget.c
|
|
|
+@@ -2930,6 +2930,7 @@ static irqreturn_t dwc3_interrupt(int ir
|
|
|
+ int dwc3_gadget_init(struct dwc3 *dwc)
|
|
|
+ {
|
|
|
+ int ret, irq;
|
|
|
++ u32 reg;
|
|
|
+ struct platform_device *dwc3_pdev = to_platform_device(dwc->dev);
|
|
|
+
|
|
|
+ irq = platform_get_irq_byname(dwc3_pdev, "peripheral");
|
|
|
+@@ -3044,6 +3045,12 @@ int dwc3_gadget_init(struct dwc3 *dwc)
|
|
|
+ goto err5;
|
|
|
+ }
|
|
|
+
|
|
|
++ if (dwc->disable_devinit_u1u2_quirk) {
|
|
|
++ reg = dwc3_readl(dwc->regs, DWC3_DCTL);
|
|
|
++ reg &= ~(DWC3_DCTL_INITU1ENA | DWC3_DCTL_INITU2ENA);
|
|
|
++ dwc3_writel(dwc->regs, DWC3_DCTL, reg);
|
|
|
++ }
|
|
|
++
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ err5:
|
|
|
--- a/drivers/usb/dwc3/host.c
|
|
|
+++ b/drivers/usb/dwc3/host.c
|
|
|
@@ -17,6 +17,8 @@
|
|
|
@@ -588,6 +692,22 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
dwc->xhci = xhci;
|
|
|
|
|
|
ret = platform_device_add_resources(xhci, dwc->xhci_resources,
|
|
|
+@@ -90,6 +101,15 @@ int dwc3_host_init(struct dwc3 *dwc)
|
|
|
+
|
|
|
+ memset(props, 0, sizeof(struct property_entry) * ARRAY_SIZE(props));
|
|
|
+
|
|
|
++ if (dwc->quirk_reverse_in_out)
|
|
|
++ props[prop_idx++].name = "quirk-reverse-in-out";
|
|
|
++
|
|
|
++ if (dwc->quirk_stop_transfer_in_block)
|
|
|
++ props[prop_idx++].name = "quirk-stop-transfer-in-block";
|
|
|
++
|
|
|
++ if (dwc->quirk_stop_ep_in_u1)
|
|
|
++ props[prop_idx++].name = "quirk-stop-ep-in-u1";
|
|
|
++
|
|
|
+ if (dwc->usb3_lpm_capable)
|
|
|
+ props[prop_idx++].name = "usb3-lpm-capable";
|
|
|
+
|
|
|
--- a/drivers/usb/gadget/udc/fsl_udc_core.c
|
|
|
+++ b/drivers/usb/gadget/udc/fsl_udc_core.c
|
|
|
@@ -198,7 +198,11 @@ __acquires(ep->udc->lock)
|
|
|
@@ -815,15 +935,17 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
Variation of ARC USB block used in some Freescale chips.
|
|
|
--- a/drivers/usb/host/ehci-fsl.c
|
|
|
+++ b/drivers/usb/host/ehci-fsl.c
|
|
|
-@@ -37,13 +37,141 @@
|
|
|
+@@ -36,15 +36,127 @@
|
|
|
+ #include <linux/platform_device.h>
|
|
|
#include <linux/fsl_devices.h>
|
|
|
#include <linux/of_platform.h>
|
|
|
-
|
|
|
++#include <linux/io.h>
|
|
|
++
|
|
|
+#ifdef CONFIG_PPC
|
|
|
+#include <asm/fsl_pm.h>
|
|
|
+#include <linux/suspend.h>
|
|
|
+#endif
|
|
|
-+
|
|
|
+
|
|
|
#include "ehci.h"
|
|
|
#include "ehci-fsl.h"
|
|
|
|
|
|
@@ -864,13 +986,23 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
#define DRV_NAME "ehci-fsl"
|
|
|
|
|
|
static struct hc_driver __read_mostly fsl_ehci_hc_driver;
|
|
|
+
|
|
|
+struct ehci_fsl {
|
|
|
-+ /* store current hcd state for otg;
|
|
|
-+ * have_hcd is true when host drv al already part of otg framework,
|
|
|
-+ * otherwise false;
|
|
|
-+ * hcd_add is true when otg framework wants to add host
|
|
|
-+ * drv as part of otg;flase when it wants to remove it
|
|
|
-+ */
|
|
|
++ struct ehci_hcd ehci;
|
|
|
++
|
|
|
++#ifdef CONFIG_PM
|
|
|
++struct ehci_regs saved_regs;
|
|
|
++struct ccsr_usb_phy saved_phy_regs;
|
|
|
++/* Saved USB PHY settings, need to restore after deep sleep. */
|
|
|
++u32 usb_ctrl;
|
|
|
++#endif
|
|
|
++ /*
|
|
|
++ * store current hcd state for otg;
|
|
|
++ * have_hcd is true when host drv al already part of otg framework,
|
|
|
++ * otherwise false;
|
|
|
++ * hcd_add is true when otg framework wants to add host
|
|
|
++ * drv as part of otg;flase when it wants to remove it
|
|
|
++ */
|
|
|
+unsigned have_hcd:1;
|
|
|
+unsigned hcd_add:1;
|
|
|
+};
|
|
|
@@ -897,7 +1029,7 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
+ /* host, gadget and otg share same int line */
|
|
|
+ retval = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
|
|
|
+ if (retval == 0)
|
|
|
-+ ehci_fsl->have_hcd = 1;
|
|
|
++ ehci_fsl->have_hcd = 1;
|
|
|
+ } else if (!ehci_fsl->hcd_add && ehci_fsl->have_hcd) {
|
|
|
+ usb_remove_hcd(hcd);
|
|
|
+ ehci_fsl->have_hcd = 0;
|
|
|
@@ -905,59 +1037,33 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
-+struct ehci_fsl {
|
|
|
-+ struct ehci_hcd ehci;
|
|
|
-+
|
|
|
-+#ifdef CONFIG_PM
|
|
|
-+struct ehci_regs saved_regs;
|
|
|
-+struct ccsr_usb_phy saved_phy_regs;
|
|
|
-+/* Saved USB PHY settings, need to restore after deep sleep. */
|
|
|
-+u32 usb_ctrl;
|
|
|
-+#endif
|
|
|
-+ /*
|
|
|
-+ * store current hcd state for otg;
|
|
|
-+ * have_hcd is true when host drv al already part of otg framework,
|
|
|
-+ * otherwise false;
|
|
|
-+ * hcd_add is true when otg framework wants to add host
|
|
|
-+ * drv as part of otg;flase when it wants to remove it
|
|
|
-+ */
|
|
|
-+unsigned have_hcd:1;
|
|
|
-+unsigned hcd_add:1;
|
|
|
-+};
|
|
|
-+
|
|
|
-+static strut ehci_fsl *hcd_to_ehci_fsl(struct usb_hcd *hcd)
|
|
|
-+{
|
|
|
-+struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
|
|
-+
|
|
|
-+return container_of(ehci, struct ehci_fsl, ehci);
|
|
|
-+}
|
|
|
-+
|
|
|
+#if defined(CONFIG_FSL_USB2_OTG) || defined(CONFIG_FSL_USB2_OTG_MODULE)
|
|
|
+static void do_change_hcd(struct work_struct *work)
|
|
|
+{
|
|
|
-+struct ehci_hcd *ehci = container_of(work, struct ehci_hcd,
|
|
|
-+change_hcd_work);
|
|
|
-+struct usb_hcd *hcd = ehci_to_hcd(ehci);
|
|
|
-+struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd);
|
|
|
-+void __iomem *non_ehci = hcd->regs;
|
|
|
-+int retval;
|
|
|
++ struct ehci_hcd *ehci = container_of(work, struct ehci_hcd,
|
|
|
++ change_hcd_work);
|
|
|
++ struct usb_hcd *hcd = ehci_to_hcd(ehci);
|
|
|
++ struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd);
|
|
|
++ void __iomem *non_ehci = hcd->regs;
|
|
|
++ int retval;
|
|
|
+
|
|
|
-+if (ehci_fsl->hcd_add && !ehci_fsl->have_hcd) {
|
|
|
-+writel(USBMODE_CM_HOST, non_ehci + FSL_SOC_USB_USBMODE);
|
|
|
-+/* host, gadget and otg share same int line */
|
|
|
-+retval = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
|
|
|
-+if (retval == 0)
|
|
|
-+ehci_fsl->have_hcd = 1;
|
|
|
-+} else if (!ehci_fsl->hcd_add && ehci_fsl->have_hcd) {
|
|
|
-+ usb_remove_hcd(hcd);
|
|
|
-+ehci_fsl->have_hcd = 0;
|
|
|
-+}
|
|
|
++ if (ehci_fsl->hcd_add && !ehci_fsl->have_hcd) {
|
|
|
++ writel(USBMODE_CM_HOST, non_ehci + FSL_SOC_USB_USBMODE);
|
|
|
++ /* host, gadget and otg share same int line */
|
|
|
++ retval = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
|
|
|
++ if (retval == 0)
|
|
|
++ ehci_fsl->have_hcd = 1;
|
|
|
++ } else if (!ehci_fsl->hcd_add && ehci_fsl->have_hcd) {
|
|
|
++ usb_remove_hcd(hcd);
|
|
|
++ ehci_fsl->have_hcd = 0;
|
|
|
++ }
|
|
|
+}
|
|
|
+#endif
|
|
|
-
|
|
|
++
|
|
|
/* configure so an HC device and id are always provided */
|
|
|
/* always called with process context; sleeping is OK */
|
|
|
-@@ -131,6 +259,12 @@ static int fsl_ehci_drv_probe(struct pla
|
|
|
+
|
|
|
+@@ -131,6 +243,12 @@ static int fsl_ehci_drv_probe(struct pla
|
|
|
clrsetbits_be32(hcd->regs + FSL_SOC_USB_CTRL,
|
|
|
CONTROL_REGISTER_W1C_MASK, 0x4);
|
|
|
|
|
|
@@ -970,7 +1076,7 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
/*
|
|
|
* Enable UTMI phy and program PTS field in UTMI mode before asserting
|
|
|
* controller reset for USB Controller version 2.5
|
|
|
-@@ -143,16 +277,20 @@ static int fsl_ehci_drv_probe(struct pla
|
|
|
+@@ -143,16 +261,20 @@ static int fsl_ehci_drv_probe(struct pla
|
|
|
|
|
|
/* Don't need to set host mode here. It will be done by tdi_reset() */
|
|
|
|
|
|
@@ -993,7 +1099,7 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
dev_dbg(&pdev->dev, "hcd=0x%p ehci=0x%p, phy=0x%p\n",
|
|
|
hcd, ehci, hcd->usb_phy);
|
|
|
|
|
|
-@@ -168,6 +306,11 @@ static int fsl_ehci_drv_probe(struct pla
|
|
|
+@@ -168,6 +290,11 @@ static int fsl_ehci_drv_probe(struct pla
|
|
|
retval = -ENODEV;
|
|
|
goto err2;
|
|
|
}
|
|
|
@@ -1005,17 +1111,16 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
}
|
|
|
#endif
|
|
|
return retval;
|
|
|
-@@ -181,6 +324,18 @@ static int fsl_ehci_drv_probe(struct pla
|
|
|
+@@ -181,6 +308,17 @@ static int fsl_ehci_drv_probe(struct pla
|
|
|
return retval;
|
|
|
}
|
|
|
|
|
|
-+static bool usb_phy_clk_valid(struct usb_hcd *hcd,
|
|
|
-+ enum fsl_usb2_phy_modes phy_mode)
|
|
|
++static bool usb_phy_clk_valid(struct usb_hcd *hcd)
|
|
|
+{
|
|
|
+ void __iomem *non_ehci = hcd->regs;
|
|
|
+ bool ret = true;
|
|
|
+
|
|
|
-+ if (!(in_be32(non_ehci + FSL_SOC_USB_CTRL) & PHY_CLK_VALID))
|
|
|
++ if (!(ioread32be(non_ehci + FSL_SOC_USB_CTRL) & PHY_CLK_VALID))
|
|
|
+ ret = false;
|
|
|
+
|
|
|
+ return ret;
|
|
|
@@ -1024,7 +1129,7 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
|
|
|
enum fsl_usb2_phy_modes phy_mode,
|
|
|
unsigned int port_offset)
|
|
|
-@@ -219,6 +374,21 @@ static int ehci_fsl_setup_phy(struct usb
|
|
|
+@@ -219,6 +357,21 @@ static int ehci_fsl_setup_phy(struct usb
|
|
|
/* fall through */
|
|
|
case FSL_USB2_PHY_UTMI:
|
|
|
case FSL_USB2_PHY_UTMI_DUAL:
|
|
|
@@ -1046,7 +1151,16 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
if (pdata->have_sysif_regs && pdata->controller_ver) {
|
|
|
/* controller version 1.6 or above */
|
|
|
clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL,
|
|
|
-@@ -292,14 +462,9 @@ static int ehci_fsl_usb_setup(struct ehc
|
|
|
+@@ -286,20 +439,18 @@ static int ehci_fsl_usb_setup(struct ehc
|
|
|
+ if (pdata->has_fsl_erratum_a005275 == 1)
|
|
|
+ ehci->has_fsl_hs_errata = 1;
|
|
|
+
|
|
|
++ if (pdata->has_fsl_erratum_a005697 == 1)
|
|
|
++ ehci->has_fsl_susp_errata = 1;
|
|
|
++
|
|
|
+ if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
|
|
|
+ (pdata->operating_mode == FSL_USB2_DR_OTG))
|
|
|
+ if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0))
|
|
|
return -EINVAL;
|
|
|
|
|
|
if (pdata->operating_mode == FSL_USB2_MPH_HOST) {
|
|
|
@@ -1062,7 +1176,7 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
ehci->has_fsl_port_bug = 1;
|
|
|
|
|
|
if (pdata->port_enables & FSL_USB2_PORT0_ENABLED)
|
|
|
-@@ -379,16 +544,57 @@ static int ehci_fsl_setup(struct usb_hcd
|
|
|
+@@ -379,16 +530,57 @@ static int ehci_fsl_setup(struct usb_hcd
|
|
|
return retval;
|
|
|
}
|
|
|
|
|
|
@@ -1127,7 +1241,7 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
|
|
|
#ifdef CONFIG_PPC_MPC512x
|
|
|
static int ehci_fsl_mpc512x_drv_suspend(struct device *dev)
|
|
|
-@@ -535,26 +741,43 @@ static inline int ehci_fsl_mpc512x_drv_r
|
|
|
+@@ -535,26 +727,45 @@ static inline int ehci_fsl_mpc512x_drv_r
|
|
|
}
|
|
|
#endif /* CONFIG_PPC_MPC512x */
|
|
|
|
|
|
@@ -1149,7 +1263,9 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
+
|
|
|
+#ifdef CONFIG_PPC
|
|
|
+suspend_state_t pm_state;
|
|
|
-+pm_state = pm_suspend_state();
|
|
|
++/* FIXME:Need to port fsl_pm.h before enable below code. */
|
|
|
++/*pm_state = pm_suspend_state();*/
|
|
|
++pm_state = PM_SUSPEND_MEM;
|
|
|
+
|
|
|
+if (pm_state == PM_SUSPEND_MEM)
|
|
|
+ ehci_fsl_save_context(hcd);
|
|
|
@@ -1178,7 +1294,7 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
if (!fsl_deep_sleep())
|
|
|
return 0;
|
|
|
|
|
|
-@@ -568,12 +791,34 @@ static int ehci_fsl_drv_resume(struct de
|
|
|
+@@ -568,12 +779,36 @@ static int ehci_fsl_drv_resume(struct de
|
|
|
struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd);
|
|
|
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
|
|
void __iomem *non_ehci = hcd->regs;
|
|
|
@@ -1188,7 +1304,9 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
+
|
|
|
+#ifdef CONFIG_PPC
|
|
|
+suspend_state_t pm_state;
|
|
|
-+pm_state = pm_suspend_state();
|
|
|
++/* FIXME:Need to port fsl_pm.h before enable below code.*/
|
|
|
++/* pm_state = pm_suspend_state(); */
|
|
|
++pm_state = PM_SUSPEND_MEM;
|
|
|
+
|
|
|
+if (pm_state == PM_SUSPEND_MEM)
|
|
|
+ ehci_fsl_restore_context(hcd);
|
|
|
@@ -1225,7 +1343,16 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
#endif /* _EHCI_FSL_H */
|
|
|
--- a/drivers/usb/host/ehci-hub.c
|
|
|
+++ b/drivers/usb/host/ehci-hub.c
|
|
|
-@@ -305,6 +305,8 @@ static int ehci_bus_suspend (struct usb_
|
|
|
+@@ -278,6 +278,8 @@ static int ehci_bus_suspend (struct usb_
|
|
|
+ else if ((t1 & PORT_PE) && !(t1 & PORT_SUSPEND)) {
|
|
|
+ t2 |= PORT_SUSPEND;
|
|
|
+ set_bit(port, &ehci->bus_suspended);
|
|
|
++ if (ehci_has_fsl_susp_errata(ehci))
|
|
|
++ usleep_range(10000, 20000);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* enable remote wakeup on all ports, if told to do so */
|
|
|
+@@ -305,6 +307,8 @@ static int ehci_bus_suspend (struct usb_
|
|
|
USB_PORT_STAT_HIGH_SPEED)
|
|
|
fs_idle_delay = true;
|
|
|
ehci_writel(ehci, t2, reg);
|
|
|
@@ -1246,8 +1373,21 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
|
|
|
/* list of itds & sitds completed while now_frame was still active */
|
|
|
struct list_head cached_itd_list;
|
|
|
-@@ -706,8 +709,10 @@ ehci_port_speed(struct ehci_hcd *ehci, u
|
|
|
+@@ -219,6 +222,7 @@ struct ehci_hcd { /* one per controlle
|
|
|
+ unsigned no_selective_suspend:1;
|
|
|
+ unsigned has_fsl_port_bug:1; /* FreeScale */
|
|
|
+ unsigned has_fsl_hs_errata:1; /* Freescale HS quirk */
|
|
|
++ unsigned has_fsl_susp_errata:1; /*Freescale SUSP quirk*/
|
|
|
+ unsigned big_endian_mmio:1;
|
|
|
+ unsigned big_endian_desc:1;
|
|
|
+ unsigned big_endian_capbase:1;
|
|
|
+@@ -704,10 +708,15 @@ ehci_port_speed(struct ehci_hcd *ehci, u
|
|
|
+ #if defined(CONFIG_PPC_85xx)
|
|
|
+ /* Some Freescale processors have an erratum (USB A-005275) in which
|
|
|
* incoming packets get corrupted in HS mode
|
|
|
++ * Some Freescale processors have an erratum (USB A-005697) in which
|
|
|
++ * we need to wait for 10ms for bus to fo into suspend mode after
|
|
|
++ * setting SUSP bit
|
|
|
*/
|
|
|
#define ehci_has_fsl_hs_errata(e) ((e)->has_fsl_hs_errata)
|
|
|
+#define ehci_has_fsl_susp_errata(e) ((e)->has_fsl_susp_errata)
|
|
|
@@ -1278,6 +1418,149 @@ Signed-off-by: Yangbo Lu <[email protected]>
|
|
|
|
|
|
/*
|
|
|
* Determine whether phy_clk_valid needs to be checked
|
|
|
+--- a/drivers/usb/host/xhci-plat.c
|
|
|
++++ b/drivers/usb/host/xhci-plat.c
|
|
|
+@@ -223,6 +223,16 @@ static int xhci_plat_probe(struct platfo
|
|
|
+ if (device_property_read_bool(&pdev->dev, "usb3-lpm-capable"))
|
|
|
+ xhci->quirks |= XHCI_LPM_SUPPORT;
|
|
|
+
|
|
|
++ if (device_property_read_bool(&pdev->dev, "quirk-reverse-in-out"))
|
|
|
++ xhci->quirks |= XHCI_REVERSE_IN_OUT;
|
|
|
++
|
|
|
++ if (device_property_read_bool(&pdev->dev,
|
|
|
++ "quirk-stop-transfer-in-block"))
|
|
|
++ xhci->quirks |= XHCI_STOP_TRANSFER_IN_BLOCK;
|
|
|
++
|
|
|
++ if (device_property_read_bool(&pdev->dev, "quirk-stop-ep-in-u1"))
|
|
|
++ xhci->quirks |= XHCI_STOP_EP_IN_U1;
|
|
|
++
|
|
|
+ if (device_property_read_bool(&pdev->dev, "quirk-broken-port-ped"))
|
|
|
+ xhci->quirks |= XHCI_BROKEN_PORT_PED;
|
|
|
+
|
|
|
+--- a/drivers/usb/host/xhci-ring.c
|
|
|
++++ b/drivers/usb/host/xhci-ring.c
|
|
|
+@@ -1852,14 +1852,17 @@ static int finish_td(struct xhci_hcd *xh
|
|
|
+ union xhci_trb *event_trb, struct xhci_transfer_event *event,
|
|
|
+ struct xhci_virt_ep *ep, int *status, bool skip)
|
|
|
+ {
|
|
|
++ struct xhci_dequeue_state deq_state;
|
|
|
+ struct xhci_virt_device *xdev;
|
|
|
+ struct xhci_ring *ep_ring;
|
|
|
++ unsigned int stream_id;
|
|
|
+ unsigned int slot_id;
|
|
|
+ int ep_index;
|
|
|
+ struct urb *urb = NULL;
|
|
|
+ struct xhci_ep_ctx *ep_ctx;
|
|
|
+ int ret = 0;
|
|
|
+ struct urb_priv *urb_priv;
|
|
|
++ u32 remaining;
|
|
|
+ u32 trb_comp_code;
|
|
|
+
|
|
|
+ slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
|
|
|
+@@ -1885,13 +1888,29 @@ static int finish_td(struct xhci_hcd *xh
|
|
|
+ if (trb_comp_code == COMP_STALL ||
|
|
|
+ xhci_requires_manual_halt_cleanup(xhci, ep_ctx,
|
|
|
+ trb_comp_code)) {
|
|
|
+- /* Issue a reset endpoint command to clear the host side
|
|
|
+- * halt, followed by a set dequeue command to move the
|
|
|
+- * dequeue pointer past the TD.
|
|
|
+- * The class driver clears the device side halt later.
|
|
|
++ /*
|
|
|
++ * A-007463: After transaction error, controller switches
|
|
|
++ * control transfer data stage from IN to OUT direction.
|
|
|
+ */
|
|
|
+- xhci_cleanup_halted_endpoint(xhci, slot_id, ep_index,
|
|
|
++ remaining = EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
|
|
|
++ if (remaining && xhci_requires_manual_halt_cleanup(xhci, ep_ctx,
|
|
|
++ trb_comp_code) &&
|
|
|
++ (xhci->quirks & XHCI_REVERSE_IN_OUT)) {
|
|
|
++ memset(&deq_state, 0, sizeof(deq_state));
|
|
|
++ xhci_find_new_dequeue_state(xhci, slot_id,
|
|
|
++ ep_index, td->urb->stream_id, td, &deq_state);
|
|
|
++ xhci_queue_new_dequeue_state(xhci, slot_id, ep_index,
|
|
|
++ stream_id, &deq_state);
|
|
|
++ xhci_ring_cmd_db(xhci);
|
|
|
++ } else {
|
|
|
++ /* Issue a reset endpoint command to clear the host side
|
|
|
++ * halt, followed by a set dequeue command to move the
|
|
|
++ * dequeue pointer past the TD.
|
|
|
++ * The class driver clears the device side halt later.
|
|
|
++ */
|
|
|
++ xhci_cleanup_halted_endpoint(xhci, slot_id, ep_index,
|
|
|
+ ep_ring->stream_id, td, event_trb);
|
|
|
++ }
|
|
|
+ } else {
|
|
|
+ /* Update ring dequeue pointer */
|
|
|
+ while (ep_ring->dequeue != td->last_trb)
|
|
|
+--- a/drivers/usb/host/xhci.c
|
|
|
++++ b/drivers/usb/host/xhci.c
|
|
|
+@@ -1570,14 +1570,38 @@ int xhci_urb_dequeue(struct usb_hcd *hcd
|
|
|
+ ret = -ENOMEM;
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+- ep->ep_state |= EP_HALT_PENDING;
|
|
|
+- ep->stop_cmds_pending++;
|
|
|
+- ep->stop_cmd_timer.expires = jiffies +
|
|
|
++ /*
|
|
|
++ *A-009611: Issuing an End Transfer command on an IN endpoint.
|
|
|
++ *when a transfer is in progress on USB blocks the transmission
|
|
|
++ *Workaround: Software must wait for all existing TRBs to
|
|
|
++ *complete before issuing End transfer command.
|
|
|
++ */
|
|
|
++ if ((ep_ring->enqueue == ep_ring->dequeue &&
|
|
|
++ (xhci->quirks & XHCI_STOP_TRANSFER_IN_BLOCK)) ||
|
|
|
++ !(xhci->quirks & XHCI_STOP_TRANSFER_IN_BLOCK)) {
|
|
|
++ ep->ep_state |= EP_HALT_PENDING;
|
|
|
++ ep->stop_cmds_pending++;
|
|
|
++ ep->stop_cmd_timer.expires = jiffies +
|
|
|
+ XHCI_STOP_EP_CMD_TIMEOUT * HZ;
|
|
|
+- add_timer(&ep->stop_cmd_timer);
|
|
|
+- xhci_queue_stop_endpoint(xhci, command, urb->dev->slot_id,
|
|
|
+- ep_index, 0);
|
|
|
+- xhci_ring_cmd_db(xhci);
|
|
|
++ add_timer(&ep->stop_cmd_timer);
|
|
|
++ xhci_queue_stop_endpoint(xhci, command,
|
|
|
++ urb->dev->slot_id,
|
|
|
++ ep_index, 0);
|
|
|
++ xhci_ring_cmd_db(xhci);
|
|
|
++ }
|
|
|
++
|
|
|
++ /*
|
|
|
++ *A-009668: Stop Endpoint Command does not complete.
|
|
|
++ *Workaround: Instead of issuing a Stop Endpoint Command,
|
|
|
++ *issue a Disable Slot Command with the corresponding slot ID.
|
|
|
++ *Alternately, you can issue an Address Device Command with
|
|
|
++ *BSR=1
|
|
|
++ */
|
|
|
++ if ((urb->dev->speed <= USB_SPEED_HIGH) &&
|
|
|
++ (xhci->quirks & XHCI_STOP_EP_IN_U1)) {
|
|
|
++ xhci_queue_slot_control(xhci, command, TRB_DISABLE_SLOT,
|
|
|
++ urb->dev->slot_id);
|
|
|
++ }
|
|
|
+ }
|
|
|
+ done:
|
|
|
+ spin_unlock_irqrestore(&xhci->lock, flags);
|
|
|
+--- a/drivers/usb/host/xhci.h
|
|
|
++++ b/drivers/usb/host/xhci.h
|
|
|
+@@ -1621,7 +1621,7 @@ struct xhci_hcd {
|
|
|
+ #define XHCI_STATE_REMOVING (1 << 2)
|
|
|
+ /* Statistics */
|
|
|
+ int error_bitmask;
|
|
|
+- unsigned int quirks;
|
|
|
++ u64 quirks;
|
|
|
+ #define XHCI_LINK_TRB_QUIRK (1 << 0)
|
|
|
+ #define XHCI_RESET_EP_QUIRK (1 << 1)
|
|
|
+ #define XHCI_NEC_HOST (1 << 2)
|
|
|
+@@ -1657,6 +1657,9 @@ struct xhci_hcd {
|
|
|
+ #define XHCI_SSIC_PORT_UNUSED (1 << 22)
|
|
|
+ #define XHCI_NO_64BIT_SUPPORT (1 << 23)
|
|
|
+ #define XHCI_MISSING_CAS (1 << 24)
|
|
|
++#define XHCI_REVERSE_IN_OUT (1 << 29)
|
|
|
++#define XHCI_STOP_TRANSFER_IN_BLOCK (1 << 30)
|
|
|
++#define XHCI_STOP_EP_IN_U1 (1 << 31)
|
|
|
+ /* For controller with a broken Port Disable implementation */
|
|
|
+ #define XHCI_BROKEN_PORT_PED (1 << 25)
|
|
|
+ #define XHCI_LIMIT_ENDPOINT_INTERVAL_7 (1 << 26)
|
|
|
--- a/drivers/usb/phy/phy-fsl-usb.c
|
|
|
+++ b/drivers/usb/phy/phy-fsl-usb.c
|
|
|
@@ -1,5 +1,5 @@
|