-From 01b1b2989e907305d8b885468c2743f5e35e1b9a Mon Sep 17 00:00:00 2001
+From ca86ebf3fddbdfa8aecc4b887ef059948ee79621 Mon Sep 17 00:00:00 2001
From: Biwen Li <biwen.li@nxp.com>
-Date: Thu, 13 Dec 2018 11:15:15 +0800
+Date: Wed, 17 Apr 2019 18:59:08 +0800
Subject: [PATCH] usb: support layerscape
This is an integrated patch of usb for layerscape
+Signed-off-by: Anurag Kumar Vulisha <anurag.kumar.vulisha@xilinx.com>
+Signed-off-by: Biwen Li <biwen.li@nxp.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Changming Huang <jerry.huang@nxp.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Li Yang <leoli@freescale.com>
+Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Nikhil Badola <nikhil.badola@freescale.com>
Signed-off-by: Rajesh Bhagat <rajesh.bhagat@nxp.com>
Signed-off-by: Ramneek Mehresh <ramneek.mehresh@freescale.com>
Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Shengzhou Liu <Shengzhou.Liu@freescale.com>
Signed-off-by: Suresh Gupta <suresh.gupta@freescale.com>
-Signed-off-by: yinbo.zhu <yinbo.zhu@nxp.com>
-Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
-Signed-off-by: Biwen Li <biwen.li@nxp.com>
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+Signed-off-by: Yinbo Zhu <yinbo.zhu@nxp.com>
+Signed-off-by: Zhao Chenhui <chenhui.zhao@freescale.com>
---
- .../devicetree/bindings/usb/dwc3.txt | 2 +
- arch/arm64/include/asm/io.h | 28 ++
- drivers/usb/common/common.c | 50 ++++
- drivers/usb/core/usb.c | 1 +
- drivers/usb/dwc3/core.c | 104 +++++++
- drivers/usb/dwc3/core.h | 44 +++
- drivers/usb/dwc3/ep0.c | 4 +-
- drivers/usb/dwc3/gadget.c | 7 +
- drivers/usb/dwc3/host.c | 9 +
- 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 | 276 ++++++++++++++++--
- drivers/usb/host/ehci-fsl.h | 3 +
- drivers/usb/host/ehci-hub.c | 2 +
- drivers/usb/host/ehci.h | 3 +
- drivers/usb/host/fsl-mph-dr-of.c | 11 +
- drivers/usb/host/xhci-hub.c | 22 ++
- drivers/usb/host/xhci-plat.c | 16 +-
- drivers/usb/host/xhci-ring.c | 28 +-
- drivers/usb/host/xhci.c | 39 ++-
- drivers/usb/host/xhci.h | 6 +-
- 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 +
- 26 files changed, 704 insertions(+), 85 deletions(-)
+ arch/arm64/include/asm/io.h | 28 +++
+ drivers/usb/common/common.c | 50 +++++
+ drivers/usb/core/usb.c | 1 +
+ drivers/usb/dwc3/core.c | 167 ++++++++++++++++
+ drivers/usb/dwc3/core.h | 58 ++++++
+ drivers/usb/dwc3/ep0.c | 4 +-
+ drivers/usb/dwc3/gadget.c | 7 +
+ drivers/usb/dwc3/host.c | 9 +
+ 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 | 276 +++++++++++++++++++++++---
+ drivers/usb/host/ehci-fsl.h | 3 +
+ drivers/usb/host/ehci-hub.c | 2 +
+ drivers/usb/host/ehci.h | 3 +
+ drivers/usb/host/fsl-mph-dr-of.c | 11 +
+ drivers/usb/host/xhci-hub.c | 22 ++
+ drivers/usb/host/xhci-plat.c | 16 +-
+ drivers/usb/host/xhci-ring.c | 28 ++-
+ drivers/usb/host/xhci.c | 37 +++-
+ drivers/usb/host/xhci.h | 10 +-
+ 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 +
+ 25 files changed, 780 insertions(+), 86 deletions(-)
---- a/Documentation/devicetree/bindings/usb/dwc3.txt
-+++ b/Documentation/devicetree/bindings/usb/dwc3.txt
-@@ -47,6 +47,8 @@ Optional properties:
- from P0 to P1/P2/P3 without delay.
- - snps,dis-tx-ipgap-linecheck-quirk: when set, disable u2mac linestate check
- during HS transmit.
-+ - snps,disable_devinit_u1u2: when set, disable device-initiated U1/U2
-+ LPM request in USB device mode.
- - snps,is-utmi-l1-suspend: true when DWC3 asserts output signal
- utmi_l1_suspend_n, false when asserts utmi_sleep_n
- - snps,hird-threshold: HIRD threshold
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -210,6 +210,34 @@ extern void __iomem *ioremap_cache(phys_
atomic_set(&dev->urbnum, 0);
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
-@@ -766,6 +766,96 @@ static void dwc3_core_setup_global_contr
+@@ -103,6 +103,41 @@ static int dwc3_get_dr_mode(struct dwc3
+ static void dwc3_event_buffers_cleanup(struct dwc3 *dwc);
+ static int dwc3_event_buffers_setup(struct dwc3 *dwc);
+
++/*
++ * dwc3_power_of_all_roothub_ports - Power off all Root hub ports
++ * @dwc3: Pointer to our controller context structure
++ */
++static void dwc3_power_off_all_roothub_ports(struct dwc3 *dwc)
++{
++ int i, port_num;
++ u32 reg, op_regs_base, offset;
++ void __iomem *xhci_regs;
++
++ /* xhci regs is not mapped yet, do it temperary here */
++ if (dwc->xhci_resources[0].start) {
++ xhci_regs = ioremap(dwc->xhci_resources[0].start,
++ DWC3_XHCI_REGS_END);
++ if (IS_ERR(xhci_regs)) {
++ dev_err(dwc->dev, "Failed to ioremap xhci_regs\n");
++ return;
++ }
++
++ op_regs_base = HC_LENGTH(readl(xhci_regs));
++ reg = readl(xhci_regs + XHCI_HCSPARAMS1);
++ port_num = HCS_MAX_PORTS(reg);
++
++ for (i = 1; i <= port_num; i++) {
++ offset = op_regs_base + XHCI_PORTSC_BASE + 0x10*(i-1);
++ reg = readl(xhci_regs + offset);
++ reg &= ~PORT_POWER;
++ writel(reg, xhci_regs + offset);
++ }
++
++ iounmap(xhci_regs);
++ } else
++ dev_err(dwc->dev, "xhci base reg invalid\n");
++}
++
+ static void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode)
+ {
+ u32 reg;
+@@ -111,6 +146,15 @@ static void dwc3_set_prtcap(struct dwc3
+ reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
+ reg |= DWC3_GCTL_PRTCAPDIR(mode);
+ dwc3_writel(dwc->regs, DWC3_GCTL, reg);
++
++ /*
++ * We have to power off all Root hub ports immediately after DWC3 set
++ * to host mode to avoid VBUS glitch happen when xhci get reset later.
++ */
++ if (dwc->host_vbus_glitches) {
++ if (mode == DWC3_GCTL_PRTCAP_HOST)
++ dwc3_power_off_all_roothub_ports(dwc);
++ }
+ }
+
+ static void __dwc3_set_mode(struct work_struct *work)
+@@ -765,6 +809,96 @@ static void dwc3_core_setup_global_contr
static int dwc3_core_get_phy(struct dwc3 *dwc);
static int dwc3_core_ulpi_init(struct dwc3 *dwc);
/**
* dwc3_core_init - Low-level initialization of DWC3 Core
* @dwc: Pointer to our controller context structure
-@@ -828,6 +918,8 @@ static int dwc3_core_init(struct dwc3 *d
+@@ -827,6 +961,8 @@ static int dwc3_core_init(struct dwc3 *d
/* Adjust Frame Length */
dwc3_frame_length_adjustment(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);
-@@ -1074,6 +1166,8 @@ static void dwc3_get_properties(struct d
+@@ -873,6 +1009,22 @@ static int dwc3_core_init(struct dwc3 *d
+ 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);
++ }
++
+ return 0;
+
+ err4:
+@@ -1079,6 +1231,8 @@ static void dwc3_get_properties(struct d
&hird_threshold);
dwc->usb3_lpm_capable = device_property_read_bool(dev,
"snps,usb3_lpm_capable");
dwc->disable_scramble_quirk = device_property_read_bool(dev,
"snps,disable_scramble_quirk");
-@@ -1106,8 +1200,16 @@ static void dwc3_get_properties(struct d
- dwc->dis_tx_ipgap_linecheck_quirk = device_property_read_bool(dev,
- "snps,dis-tx-ipgap-linecheck-quirk");
+@@ -1113,8 +1267,16 @@ static void dwc3_get_properties(struct d
+ dwc->parkmode_disable_ss_quirk = device_property_read_bool(dev,
+ "snps,parkmode-disable-ss-quirk");
+ dwc->quirk_reverse_in_out = device_property_read_bool(dev,
+ "snps,quirk_reverse_in_out");
device_property_read_u8(dev, "snps,tx_de_emphasis",
&tx_de_emphasis);
device_property_read_string(dev, "snps,hsphy_interface",
-@@ -1365,12 +1467,14 @@ static int dwc3_resume_common(struct dwc
+@@ -1125,6 +1287,9 @@ static void dwc3_get_properties(struct d
+ dwc->dis_metastability_quirk = device_property_read_bool(dev,
+ "snps,dis_metastability_quirk");
+
++ dwc->host_vbus_glitches = device_property_read_bool(dev,
++ "snps,host-vbus-glitches");
++
+ dwc->lpm_nyet_threshold = lpm_nyet_threshold;
+ dwc->tx_de_emphasis = tx_de_emphasis;
+
+@@ -1376,12 +1541,14 @@ static int dwc3_resume_common(struct dwc
switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
/* Global Debug Queue/FIFO Space Available Register */
#define DWC3_GDBGFIFOSPACE_NUM(n) ((n) & 0x1f)
#define DWC3_GDBGFIFOSPACE_TYPE(n) (((n) << 5) & 0x1e0)
-@@ -788,6 +814,7 @@ struct dwc3_scratchpad_array {
+@@ -205,6 +231,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_PARKMODE_DISABLE_SS BIT(17)
+ #define DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS BIT(28)
+@@ -478,6 +507,14 @@
+ #define DWC3_DEV_IMOD_INTERVAL_SHIFT 0
+ #define DWC3_DEV_IMOD_INTERVAL_MASK (0xffff << 0)
+
++/* Partial XHCI Register and Bit fields for quirk */
++#define XHCI_HCSPARAMS1 0x4
++#define XHCI_PORTSC_BASE 0x400
++#define PORT_POWER (1 << 9)
++#define HCS_MAX_PORTS(p) (((p) >> 24) & 0x7f)
++#define XHCI_HC_LENGTH(p) (((p)>>00)&0x00ff)
++#define HC_LENGTH(p) XHCI_HC_LENGTH(p)
++
+ /* Structures */
+
+ struct dwc3_trb;
+@@ -789,6 +826,7 @@ struct dwc3_scratchpad_array {
* @regs: base address for our registers
* @regs_size: address space size
* @fladj: frame length adjustment
* @irq_gadget: peripheral controller's IRQ number
* @nr_scratch: number of scratch buffers
* @u1u2: only used on revisions <1.83a for workaround
-@@ -843,6 +870,7 @@ struct dwc3_scratchpad_array {
+@@ -844,6 +882,7 @@ struct dwc3_scratchpad_array {
* @setup_packet_pending: true when there's a Setup Packet in FIFO. Workaround
* @three_stage_setup: set if we perform a three phase setup
* @usb3_lpm_capable: set if hadrware supports Link Power Management
* @disable_scramble_quirk: set if we enable the disable scramble quirk
* @u2exit_lfps_quirk: set if we enable u2exit lfps quirk
* @u2ss_inp3_quirk: set if we enable P3 OK for U2/SS Inactive quirk
-@@ -869,6 +897,11 @@ 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.
-+ * @quirk_reverse_in_out: prevent tx fifo reverse the data direction
-+ * @quirk_stop_transfer_in_block: prevent block transmission from being
-+ * interrupted
-+ * @quirk_stop_ep_in_u1: replace stop commad with disable slot command
- * @imod_interval: set the interrupt moderation interval in 250ns
- * increments or 0 to disable.
- */
-@@ -921,6 +954,12 @@ struct dwc3 {
+@@ -925,6 +964,12 @@ struct dwc3 {
enum usb_phy_interface hsphy_mode;
u32 fladj;
u32 irq_gadget;
u32 nr_scratch;
u32 u1u2;
-@@ -1005,6 +1044,7 @@ struct dwc3 {
+@@ -1009,6 +1054,7 @@ struct dwc3 {
unsigned setup_packet_pending:1;
unsigned three_stage_setup:1;
unsigned usb3_lpm_capable:1;
unsigned disable_scramble_quirk:1;
unsigned u2exit_lfps_quirk:1;
-@@ -1024,6 +1064,10 @@ struct dwc3 {
+@@ -1029,6 +1075,11 @@ struct dwc3 {
unsigned tx_de_emphasis_quirk:1;
unsigned tx_de_emphasis:2;
+ unsigned quirk_reverse_in_out:1;
+ unsigned quirk_stop_transfer_in_block:1;
+ unsigned quirk_stop_ep_in_u1:1;
++ unsigned host_vbus_glitches:1;
+
+ unsigned dis_metastability_quirk:1;
- u16 imod_interval;
- };
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -391,7 +391,7 @@ static int dwc3_ep0_handle_u1(struct dwc
reg &= ~DWC3_DCTL_INITU2ENA;
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
-@@ -3210,6 +3210,7 @@ int dwc3_gadget_init(struct dwc3 *dwc)
+@@ -3216,6 +3216,7 @@ int dwc3_gadget_init(struct dwc3 *dwc)
{
int ret;
int irq;
irq = dwc3_gadget_get_irq(dwc);
if (irq < 0) {
-@@ -3288,6 +3289,12 @@ int dwc3_gadget_init(struct dwc3 *dwc)
+@@ -3294,6 +3295,12 @@ int dwc3_gadget_init(struct dwc3 *dwc)
dwc3_gadget_set_speed(&dwc->gadget, dwc->maximum_speed);
/* DR has been stopped in usb_gadget_unregister_driver() */
remove_proc_file();
-@@ -2569,7 +2579,7 @@ static int fsl_udc_remove(struct platfor
- dma_pool_destroy(udc_controller->td_pool);
- free_irq(udc_controller->irq, udc_controller);
- iounmap(dr_regs);
-- if (pdata->operating_mode == FSL_USB2_DR_DEVICE)
-+ if (res && (pdata->operating_mode == FSL_USB2_DR_DEVICE))
- release_mem_region(res->start, resource_size(res));
-
- /* free udc --wait for the release() finished */
--- a/drivers/usb/gadget/udc/fsl_usb2_udc.h
+++ b/drivers/usb/gadget/udc/fsl_usb2_udc.h
@@ -20,6 +20,10 @@
xhci->quirks |= XHCI_BROKEN_PORT_PED;
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
-@@ -1972,10 +1972,12 @@ static int finish_td(struct xhci_hcd *xh
+@@ -1978,10 +1978,12 @@ static int finish_td(struct xhci_hcd *xh
union xhci_trb *ep_trb, struct xhci_transfer_event *event,
struct xhci_virt_ep *ep, int *status)
{
u32 trb_comp_code;
int ep_index;
-@@ -1998,14 +2000,30 @@ static int finish_td(struct xhci_hcd *xh
+@@ -2004,14 +2006,30 @@ static int finish_td(struct xhci_hcd *xh
if (trb_comp_code == COMP_STALL_ERROR ||
xhci_requires_manual_halt_cleanup(xhci, ep_ctx,
trb_comp_code)) {
while (ep_ring->dequeue != td->last_trb)
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
-@@ -1597,13 +1597,38 @@ static int xhci_urb_dequeue(struct usb_h
+@@ -1604,13 +1604,38 @@ static int xhci_urb_dequeue(struct usb_h
ret = -ENOMEM;
goto done;
}
}
done:
spin_unlock_irqrestore(&xhci->lock, flags);
-@@ -4988,7 +5013,7 @@ int xhci_gen_setup(struct usb_hcd *hcd,
- return retval;
- xhci_dbg(xhci, "Called HCD init\n");
-
-- xhci_info(xhci, "hcc params 0x%08x hci version 0x%x quirks 0x%016llx\n",
-+ xhci_info(xhci, "hcc params 0x%08x hci version 0x%x quirks 0x%llx\n",
- xhci->hcc_params, xhci->hci_version, xhci->quirks);
-
- return 0;
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1794,7 +1794,7 @@ struct xhci_hcd {
#define XHCI_STATE_HALTED (1 << 1)
#define XHCI_STATE_REMOVING (1 << 2)
- unsigned long long quirks;
-+ u64 quirks;
++ unsigned long long quirks;
#define XHCI_LINK_TRB_QUIRK BIT_ULL(0)
#define XHCI_RESET_EP_QUIRK BIT_ULL(1)
#define XHCI_NEC_HOST BIT_ULL(2)
/* For controller with a broken Port Disable implementation */
#define XHCI_BROKEN_PORT_PED BIT_ULL(25)
#define XHCI_LIMIT_ENDPOINT_INTERVAL_7 BIT_ULL(26)
-@@ -1840,6 +1843,7 @@ struct xhci_hcd {
+@@ -1838,8 +1841,9 @@ struct xhci_hcd {
+ #define XHCI_HW_LPM_DISABLE BIT_ULL(29)
+ #define XHCI_SUSPEND_DELAY BIT_ULL(30)
#define XHCI_INTEL_USB_ROLE_SW BIT_ULL(31)
- #define XHCI_RESET_PLL_ON_DISCONNECT BIT_ULL(34)
- #define XHCI_SNPS_BROKEN_SUSPEND BIT_ULL(35)
-+#define XHCI_DIS_U1U2_WHEN_U3 BIT(36)
+-#define XHCI_RESET_PLL_ON_DISCONNECT BIT_ULL(34)
+-#define XHCI_SNPS_BROKEN_SUSPEND BIT_ULL(35)
++#define XHCI_RESET_PLL_ON_DISCONNECT BIT_ULL(35)
++#define XHCI_SNPS_BROKEN_SUSPEND BIT_ULL(36)
++#define XHCI_DIS_U1U2_WHEN_U3 BIT(37)
unsigned int num_active_eps;
unsigned int limit_active_eps;
#define BCSR5_INT_USB (0x02)
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
-@@ -434,6 +434,7 @@ struct usb_bus {
+@@ -432,6 +432,7 @@ struct usb_bus {
* for control transfers?
*/
u8 otg_port; /* 0, or number of OTG/HNP port */