Merge tag 'usb-serial-4.4-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/johan...
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 19 Nov 2015 22:08:37 +0000 (14:08 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 19 Nov 2015 22:08:37 +0000 (14:08 -0800)
Johan writes:

USB-serial fixes for v4.4-rc2

Here are some new device ids, support for an odd qcserial Gobi interface
layout and a fix for the qcserial Huawei interface layout.

Signed-off-by: Johan Hovold <johan@kernel.org>
18 files changed:
arch/arm/boot/dts/imx27.dtsi
drivers/usb/chipidea/ci_hdrc_imx.c
drivers/usb/chipidea/debug.c
drivers/usb/chipidea/udc.c
drivers/usb/chipidea/usbmisc_imx.c
drivers/usb/dwc2/hcd.c
drivers/usb/dwc2/platform.c
drivers/usb/dwc3/dwc3-pci.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/function/f_loopback.c
drivers/usb/gadget/udc/atmel_usba_udc.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_host.c
drivers/usb/phy/phy-mxs-usb.c
drivers/usb/phy/phy-omap-otg.c

index feb9d34b239c8069450c1d4c1479ebaf207ef3ec..f818ea483aeb57ee804e34d07e4b8383fae2eb63 100644 (file)
                                compatible = "fsl,imx27-usb";
                                reg = <0x10024000 0x200>;
                                interrupts = <56>;
-                               clocks = <&clks IMX27_CLK_USB_IPG_GATE>;
+                               clocks = <&clks IMX27_CLK_USB_IPG_GATE>,
+                                       <&clks IMX27_CLK_USB_AHB_GATE>,
+                                       <&clks IMX27_CLK_USB_DIV>;
+                               clock-names = "ipg", "ahb", "per";
                                fsl,usbmisc = <&usbmisc 0>;
                                status = "disabled";
                        };
                                compatible = "fsl,imx27-usb";
                                reg = <0x10024200 0x200>;
                                interrupts = <54>;
-                               clocks = <&clks IMX27_CLK_USB_IPG_GATE>;
+                               clocks = <&clks IMX27_CLK_USB_IPG_GATE>,
+                                       <&clks IMX27_CLK_USB_AHB_GATE>,
+                                       <&clks IMX27_CLK_USB_DIV>;
+                               clock-names = "ipg", "ahb", "per";
                                fsl,usbmisc = <&usbmisc 1>;
                                dr_mode = "host";
                                status = "disabled";
                                compatible = "fsl,imx27-usb";
                                reg = <0x10024400 0x200>;
                                interrupts = <55>;
-                               clocks = <&clks IMX27_CLK_USB_IPG_GATE>;
+                               clocks = <&clks IMX27_CLK_USB_IPG_GATE>,
+                                       <&clks IMX27_CLK_USB_AHB_GATE>,
+                                       <&clks IMX27_CLK_USB_DIV>;
+                               clock-names = "ipg", "ahb", "per";
                                fsl,usbmisc = <&usbmisc 2>;
                                dr_mode = "host";
                                status = "disabled";
                                #index-cells = <1>;
                                compatible = "fsl,imx27-usbmisc";
                                reg = <0x10024600 0x200>;
-                               clocks = <&clks IMX27_CLK_USB_AHB_GATE>;
                        };
 
                        sahara2: sahara@10025000 {
index 6ccbf60cdd5c1204f77072a396d9791c6bfdcc2a..5a048b7b92e8f8c7821f3e0a6880f38ab3259733 100644 (file)
@@ -84,6 +84,12 @@ struct ci_hdrc_imx_data {
        struct imx_usbmisc_data *usbmisc_data;
        bool supports_runtime_pm;
        bool in_lpm;
+       /* SoC before i.mx6 (except imx23/imx28) needs three clks */
+       bool need_three_clks;
+       struct clk *clk_ipg;
+       struct clk *clk_ahb;
+       struct clk *clk_per;
+       /* --------------------------------- */
 };
 
 /* Common functions shared by usbmisc drivers */
@@ -135,6 +141,102 @@ static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev)
 }
 
 /* End of common functions shared by usbmisc drivers*/
+static int imx_get_clks(struct device *dev)
+{
+       struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
+       int ret = 0;
+
+       data->clk_ipg = devm_clk_get(dev, "ipg");
+       if (IS_ERR(data->clk_ipg)) {
+               /* If the platform only needs one clocks */
+               data->clk = devm_clk_get(dev, NULL);
+               if (IS_ERR(data->clk)) {
+                       ret = PTR_ERR(data->clk);
+                       dev_err(dev,
+                               "Failed to get clks, err=%ld,%ld\n",
+                               PTR_ERR(data->clk), PTR_ERR(data->clk_ipg));
+                       return ret;
+               }
+               return ret;
+       }
+
+       data->clk_ahb = devm_clk_get(dev, "ahb");
+       if (IS_ERR(data->clk_ahb)) {
+               ret = PTR_ERR(data->clk_ahb);
+               dev_err(dev,
+                       "Failed to get ahb clock, err=%d\n", ret);
+               return ret;
+       }
+
+       data->clk_per = devm_clk_get(dev, "per");
+       if (IS_ERR(data->clk_per)) {
+               ret = PTR_ERR(data->clk_per);
+               dev_err(dev,
+                       "Failed to get per clock, err=%d\n", ret);
+               return ret;
+       }
+
+       data->need_three_clks = true;
+       return ret;
+}
+
+static int imx_prepare_enable_clks(struct device *dev)
+{
+       struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
+       int ret = 0;
+
+       if (data->need_three_clks) {
+               ret = clk_prepare_enable(data->clk_ipg);
+               if (ret) {
+                       dev_err(dev,
+                               "Failed to prepare/enable ipg clk, err=%d\n",
+                               ret);
+                       return ret;
+               }
+
+               ret = clk_prepare_enable(data->clk_ahb);
+               if (ret) {
+                       dev_err(dev,
+                               "Failed to prepare/enable ahb clk, err=%d\n",
+                               ret);
+                       clk_disable_unprepare(data->clk_ipg);
+                       return ret;
+               }
+
+               ret = clk_prepare_enable(data->clk_per);
+               if (ret) {
+                       dev_err(dev,
+                               "Failed to prepare/enable per clk, err=%d\n",
+                               ret);
+                       clk_disable_unprepare(data->clk_ahb);
+                       clk_disable_unprepare(data->clk_ipg);
+                       return ret;
+               }
+       } else {
+               ret = clk_prepare_enable(data->clk);
+               if (ret) {
+                       dev_err(dev,
+                               "Failed to prepare/enable clk, err=%d\n",
+                               ret);
+                       return ret;
+               }
+       }
+
+       return ret;
+}
+
+static void imx_disable_unprepare_clks(struct device *dev)
+{
+       struct ci_hdrc_imx_data *data = dev_get_drvdata(dev);
+
+       if (data->need_three_clks) {
+               clk_disable_unprepare(data->clk_per);
+               clk_disable_unprepare(data->clk_ahb);
+               clk_disable_unprepare(data->clk_ipg);
+       } else {
+               clk_disable_unprepare(data->clk);
+       }
+}
 
 static int ci_hdrc_imx_probe(struct platform_device *pdev)
 {
@@ -145,31 +247,31 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
                .flags          = CI_HDRC_SET_NON_ZERO_TTHA,
        };
        int ret;
-       const struct of_device_id *of_id =
-                       of_match_device(ci_hdrc_imx_dt_ids, &pdev->dev);
-       const struct ci_hdrc_imx_platform_flag *imx_platform_flag = of_id->data;
+       const struct of_device_id *of_id;
+       const struct ci_hdrc_imx_platform_flag *imx_platform_flag;
+
+       of_id = of_match_device(ci_hdrc_imx_dt_ids, &pdev->dev);
+       if (!of_id)
+               return -ENODEV;
+
+       imx_platform_flag = of_id->data;
 
        data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
        if (!data)
                return -ENOMEM;
 
+       platform_set_drvdata(pdev, data);
        data->usbmisc_data = usbmisc_get_init_data(&pdev->dev);
        if (IS_ERR(data->usbmisc_data))
                return PTR_ERR(data->usbmisc_data);
 
-       data->clk = devm_clk_get(&pdev->dev, NULL);
-       if (IS_ERR(data->clk)) {
-               dev_err(&pdev->dev,
-                       "Failed to get clock, err=%ld\n", PTR_ERR(data->clk));
-               return PTR_ERR(data->clk);
-       }
+       ret = imx_get_clks(&pdev->dev);
+       if (ret)
+               return ret;
 
-       ret = clk_prepare_enable(data->clk);
-       if (ret) {
-               dev_err(&pdev->dev,
-                       "Failed to prepare or enable clock, err=%d\n", ret);
+       ret = imx_prepare_enable_clks(&pdev->dev);
+       if (ret)
                return ret;
-       }
 
        data->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "fsl,usbphy", 0);
        if (IS_ERR(data->phy)) {
@@ -212,8 +314,6 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
                goto disable_device;
        }
 
-       platform_set_drvdata(pdev, data);
-
        if (data->supports_runtime_pm) {
                pm_runtime_set_active(&pdev->dev);
                pm_runtime_enable(&pdev->dev);
@@ -226,7 +326,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
 disable_device:
        ci_hdrc_remove_device(data->ci_pdev);
 err_clk:
-       clk_disable_unprepare(data->clk);
+       imx_disable_unprepare_clks(&pdev->dev);
        return ret;
 }
 
@@ -240,7 +340,7 @@ static int ci_hdrc_imx_remove(struct platform_device *pdev)
                pm_runtime_put_noidle(&pdev->dev);
        }
        ci_hdrc_remove_device(data->ci_pdev);
-       clk_disable_unprepare(data->clk);
+       imx_disable_unprepare_clks(&pdev->dev);
 
        return 0;
 }
@@ -252,7 +352,7 @@ static int imx_controller_suspend(struct device *dev)
 
        dev_dbg(dev, "at %s\n", __func__);
 
-       clk_disable_unprepare(data->clk);
+       imx_disable_unprepare_clks(dev);
        data->in_lpm = true;
 
        return 0;
@@ -270,7 +370,7 @@ static int imx_controller_resume(struct device *dev)
                return 0;
        }
 
-       ret = clk_prepare_enable(data->clk);
+       ret = imx_prepare_enable_clks(dev);
        if (ret)
                return ret;
 
@@ -285,7 +385,7 @@ static int imx_controller_resume(struct device *dev)
        return 0;
 
 clk_disable:
-       clk_disable_unprepare(data->clk);
+       imx_disable_unprepare_clks(dev);
        return ret;
 }
 
index 080b7be3daf034939bd12c509353c041b6027f49..58c8485a0715ada6c585a29e23883f25091fa127 100644 (file)
@@ -322,8 +322,10 @@ static ssize_t ci_role_write(struct file *file, const char __user *ubuf,
                return -EINVAL;
 
        pm_runtime_get_sync(ci->dev);
+       disable_irq(ci->irq);
        ci_role_stop(ci);
        ret = ci_role_start(ci, role);
+       enable_irq(ci->irq);
        pm_runtime_put_sync(ci->dev);
 
        return ret ? ret : count;
index 8223fe73ea85926477cf710227fc3907b5ad9ff1..391a1225b0ba330cd818028f240cb151e8ade65c 100644 (file)
@@ -1751,6 +1751,22 @@ static int ci_udc_start(struct usb_gadget *gadget,
        return retval;
 }
 
+static void ci_udc_stop_for_otg_fsm(struct ci_hdrc *ci)
+{
+       if (!ci_otg_is_fsm_mode(ci))
+               return;
+
+       mutex_lock(&ci->fsm.lock);
+       if (ci->fsm.otg->state == OTG_STATE_A_PERIPHERAL) {
+               ci->fsm.a_bidl_adis_tmout = 1;
+               ci_hdrc_otg_fsm_start(ci);
+       } else if (ci->fsm.otg->state == OTG_STATE_B_PERIPHERAL) {
+               ci->fsm.protocol = PROTO_UNDEF;
+               ci->fsm.otg->state = OTG_STATE_UNDEFINED;
+       }
+       mutex_unlock(&ci->fsm.lock);
+}
+
 /**
  * ci_udc_stop: unregister a gadget driver
  */
@@ -1775,6 +1791,7 @@ static int ci_udc_stop(struct usb_gadget *gadget)
        ci->driver = NULL;
        spin_unlock_irqrestore(&ci->lock, flags);
 
+       ci_udc_stop_for_otg_fsm(ci);
        return 0;
 }
 
index fcea4eb36eeedbceac777ecd8d676e5ede74cba6..ab8b027e8cc870615d399abb631849875db72427 100644 (file)
@@ -500,7 +500,11 @@ static int usbmisc_imx_probe(struct platform_device *pdev)
 {
        struct resource *res;
        struct imx_usbmisc *data;
-       struct of_device_id *tmp_dev;
+       const struct of_device_id *of_id;
+
+       of_id = of_match_device(usbmisc_imx_dt_ids, &pdev->dev);
+       if (!of_id)
+               return -ENODEV;
 
        data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
        if (!data)
@@ -513,9 +517,7 @@ static int usbmisc_imx_probe(struct platform_device *pdev)
        if (IS_ERR(data->base))
                return PTR_ERR(data->base);
 
-       tmp_dev = (struct of_device_id *)
-               of_match_device(usbmisc_imx_dt_ids, &pdev->dev);
-       data->ops = (const struct usbmisc_ops *)tmp_dev->data;
+       data->ops = (const struct usbmisc_ops *)of_id->data;
        platform_set_drvdata(pdev, data);
 
        return 0;
index e79baf73c234f58bf3162bb9d52d5efce9bca1ca..571c21727ff9f5cb8c774eeb1178cfc55e8e88b4 100644 (file)
@@ -324,12 +324,13 @@ void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg)
  */
 static void dwc2_hcd_rem_wakeup(struct dwc2_hsotg *hsotg)
 {
-       if (hsotg->lx_state == DWC2_L2) {
+       if (hsotg->bus_suspended) {
                hsotg->flags.b.port_suspend_change = 1;
                usb_hcd_resume_root_hub(hsotg->priv);
-       } else {
-               hsotg->flags.b.port_l1_change = 1;
        }
+
+       if (hsotg->lx_state == DWC2_L1)
+               hsotg->flags.b.port_l1_change = 1;
 }
 
 /**
@@ -1428,8 +1429,8 @@ static void dwc2_wakeup_detected(unsigned long data)
        dev_dbg(hsotg->dev, "Clear Resume: HPRT0=%0x\n",
                dwc2_readl(hsotg->regs + HPRT0));
 
-       hsotg->bus_suspended = 0;
        dwc2_hcd_rem_wakeup(hsotg);
+       hsotg->bus_suspended = 0;
 
        /* Change to L0 state */
        hsotg->lx_state = DWC2_L0;
index 5859b0fa19ee3f907b2bfa93945a6378ae10911a..e61d773cf65e71e27a41f3c7d8e5306939d08908 100644 (file)
@@ -108,7 +108,8 @@ static const struct dwc2_core_params params_rk3066 = {
        .host_ls_low_power_phy_clk      = -1,
        .ts_dline                       = -1,
        .reload_ctl                     = -1,
-       .ahbcfg                         = 0x7, /* INCR16 */
+       .ahbcfg                         = GAHBCFG_HBSTLEN_INCR16 <<
+                                         GAHBCFG_HBSTLEN_SHIFT,
        .uframe_sched                   = -1,
        .external_id_pin_ctl            = -1,
        .hibernation                    = -1,
index 77a622cb48ab1555a87dfaf279f5d25368672e99..009d83048c8c9ab51ae01191e3cb2aa30207d928 100644 (file)
@@ -34,6 +34,8 @@
 #define PCI_DEVICE_ID_INTEL_BSW                        0x22b7
 #define PCI_DEVICE_ID_INTEL_SPTLP              0x9d30
 #define PCI_DEVICE_ID_INTEL_SPTH               0xa130
+#define PCI_DEVICE_ID_INTEL_BXT                        0x0aaa
+#define PCI_DEVICE_ID_INTEL_APL                        0x5aaa
 
 static const struct acpi_gpio_params reset_gpios = { 0, 0, false };
 static const struct acpi_gpio_params cs_gpios = { 1, 0, false };
@@ -210,6 +212,8 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MRFLD), },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTLP), },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SPTH), },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BXT), },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_APL), },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_NL_USB), },
        {  }    /* Terminating Entry */
 };
index 55ba447fdf8bf56720eeac029ed4f96d932ee0ea..e24a01cc98df4a43f2fd556e44b1557dce778d33 100644 (file)
@@ -2744,11 +2744,33 @@ int dwc3_gadget_init(struct dwc3 *dwc)
        }
 
        dwc->gadget.ops                 = &dwc3_gadget_ops;
-       dwc->gadget.max_speed           = USB_SPEED_SUPER;
        dwc->gadget.speed               = USB_SPEED_UNKNOWN;
        dwc->gadget.sg_supported        = true;
        dwc->gadget.name                = "dwc3-gadget";
 
+       /*
+        * FIXME We might be setting max_speed to <SUPER, however versions
+        * <2.20a of dwc3 have an issue with metastability (documented
+        * elsewhere in this driver) which tells us we can't set max speed to
+        * anything lower than SUPER.
+        *
+        * Because gadget.max_speed is only used by composite.c and function
+        * drivers (i.e. it won't go into dwc3's registers) we are allowing this
+        * to happen so we avoid sending SuperSpeed Capability descriptor
+        * together with our BOS descriptor as that could confuse host into
+        * thinking we can handle super speed.
+        *
+        * Note that, in fact, we won't even support GetBOS requests when speed
+        * is less than super speed because we don't have means, yet, to tell
+        * composite.c that we are USB 2.0 + LPM ECN.
+        */
+       if (dwc->revision < DWC3_REVISION_220A)
+               dwc3_trace(trace_dwc3_gadget,
+                               "Changing max_speed on rev %08x\n",
+                               dwc->revision);
+
+       dwc->gadget.max_speed           = dwc->maximum_speed;
+
        /*
         * Per databook, DWC3 needs buffer size to be aligned to MaxPacketSize
         * on ep out.
index 23933bdf2d9d6cebc66750050ba704c9a20d109c..ddc3aad886b7457dd0ab4c79587104b474889ca0 100644 (file)
@@ -329,7 +329,7 @@ static int alloc_requests(struct usb_composite_dev *cdev,
        for (i = 0; i < loop->qlen && result == 0; i++) {
                result = -ENOMEM;
 
-               in_req = usb_ep_alloc_request(loop->in_ep, GFP_KERNEL);
+               in_req = usb_ep_alloc_request(loop->in_ep, GFP_ATOMIC);
                if (!in_req)
                        goto fail;
 
index f0f2b066ac08366d353b046d3a3a193600977d1d..f92f5aff0dd5e8ece600cc44b5ba6168e3f1bb81 100644 (file)
@@ -1633,7 +1633,7 @@ static irqreturn_t usba_udc_irq(int irq, void *devid)
        spin_lock(&udc->lock);
 
        int_enb = usba_int_enb_get(udc);
-       status = usba_readl(udc, INT_STA) & int_enb;
+       status = usba_readl(udc, INT_STA) & (int_enb | USBA_HIGH_SPEED);
        DBG(DBG_INT, "irq, status=%#08x\n", status);
 
        if (status & USBA_DET_SUSPEND) {
index 5d2d7e954bd4cb8dbaa51ec1121e236e8f472dce..0230965fb78cf3433702932625aee270dbf90535 100644 (file)
@@ -782,12 +782,15 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
                        status |= USB_PORT_STAT_SUSPEND;
                }
        }
-       if ((raw_port_status & PORT_PLS_MASK) == XDEV_U0
-                       && (raw_port_status & PORT_POWER)
-                       && (bus_state->suspended_ports & (1 << wIndex))) {
-               bus_state->suspended_ports &= ~(1 << wIndex);
-               if (hcd->speed < HCD_USB3)
-                       bus_state->port_c_suspend |= 1 << wIndex;
+       if ((raw_port_status & PORT_PLS_MASK) == XDEV_U0 &&
+           (raw_port_status & PORT_POWER)) {
+               if (bus_state->suspended_ports & (1 << wIndex)) {
+                       bus_state->suspended_ports &= ~(1 << wIndex);
+                       if (hcd->speed < HCD_USB3)
+                               bus_state->port_c_suspend |= 1 << wIndex;
+               }
+               bus_state->resume_done[wIndex] = 0;
+               clear_bit(wIndex, &bus_state->resuming_ports);
        }
        if (raw_port_status & PORT_CONNECT) {
                status |= USB_PORT_STAT_CONNECTION;
index fa836251ca21e4f19c59b3fd37b3b788b7b81008..6c5e8133cf87c4b203e2072de5b7275c4d944365 100644 (file)
@@ -3896,28 +3896,6 @@ cleanup:
        return ret;
 }
 
-static int ep_ring_is_processing(struct xhci_hcd *xhci,
-               int slot_id, unsigned int ep_index)
-{
-       struct xhci_virt_device *xdev;
-       struct xhci_ring *ep_ring;
-       struct xhci_ep_ctx *ep_ctx;
-       struct xhci_virt_ep *xep;
-       dma_addr_t hw_deq;
-
-       xdev = xhci->devs[slot_id];
-       xep = &xhci->devs[slot_id]->eps[ep_index];
-       ep_ring = xep->ring;
-       ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
-
-       if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) != EP_STATE_RUNNING)
-               return 0;
-
-       hw_deq = le64_to_cpu(ep_ctx->deq) & ~EP_CTX_CYCLE_MASK;
-       return (hw_deq !=
-               xhci_trb_virt_to_dma(ep_ring->enq_seg, ep_ring->enqueue));
-}
-
 /*
  * Check transfer ring to guarantee there is enough room for the urb.
  * Update ISO URB start_frame and interval.
@@ -3983,10 +3961,12 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags,
        }
 
        /* Calculate the start frame and put it in urb->start_frame. */
-       if (HCC_CFC(xhci->hcc_params) &&
-                       ep_ring_is_processing(xhci, slot_id, ep_index)) {
-               urb->start_frame = xep->next_frame_id;
-               goto skip_start_over;
+       if (HCC_CFC(xhci->hcc_params) && !list_empty(&ep_ring->td_list)) {
+               if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) ==
+                               EP_STATE_RUNNING) {
+                       urb->start_frame = xep->next_frame_id;
+                       goto skip_start_over;
+               }
        }
 
        start_frame = readl(&xhci->run_regs->microframe_index);
index 6e7dc6f93978c54e300caaa1b53155a672c91019..dfa44d3e8eee469c9b8321fed57056ebe5813a2a 100644 (file)
@@ -175,6 +175,16 @@ int xhci_reset(struct xhci_hcd *xhci)
        command |= CMD_RESET;
        writel(command, &xhci->op_regs->command);
 
+       /* Existing Intel xHCI controllers require a delay of 1 mS,
+        * after setting the CMD_RESET bit, and before accessing any
+        * HC registers. This allows the HC to complete the
+        * reset operation and be ready for HC register access.
+        * Without this delay, the subsequent HC register access,
+        * may result in a system hang very rarely.
+        */
+       if (xhci->quirks & XHCI_INTEL_HOST)
+               udelay(1000);
+
        ret = xhci_handshake(&xhci->op_regs->command,
                        CMD_RESET, 0, 10 * 1000 * 1000);
        if (ret)
index ba13529cbd52ff82658e88bdba30db82a8e99790..18cfc0a361cb340612bdf943d79a6302694afc43 100644 (file)
@@ -132,7 +132,7 @@ static inline struct musb *dev_to_musb(struct device *dev)
 /*-------------------------------------------------------------------------*/
 
 #ifndef CONFIG_BLACKFIN
-static int musb_ulpi_read(struct usb_phy *phy, u32 offset)
+static int musb_ulpi_read(struct usb_phy *phy, u32 reg)
 {
        void __iomem *addr = phy->io_priv;
        int     i = 0;
@@ -151,7 +151,7 @@ static int musb_ulpi_read(struct usb_phy *phy, u32 offset)
         * ULPICarKitControlDisableUTMI after clearing POWER_SUSPENDM.
         */
 
-       musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)offset);
+       musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)reg);
        musb_writeb(addr, MUSB_ULPI_REG_CONTROL,
                        MUSB_ULPI_REG_REQ | MUSB_ULPI_RDN_WR);
 
@@ -176,7 +176,7 @@ out:
        return ret;
 }
 
-static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data)
+static int musb_ulpi_write(struct usb_phy *phy, u32 val, u32 reg)
 {
        void __iomem *addr = phy->io_priv;
        int     i = 0;
@@ -191,8 +191,8 @@ static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data)
        power &= ~MUSB_POWER_SUSPENDM;
        musb_writeb(addr, MUSB_POWER, power);
 
-       musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)offset);
-       musb_writeb(addr, MUSB_ULPI_REG_DATA, (u8)data);
+       musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)reg);
+       musb_writeb(addr, MUSB_ULPI_REG_DATA, (u8)val);
        musb_writeb(addr, MUSB_ULPI_REG_CONTROL, MUSB_ULPI_REG_REQ);
 
        while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL)
@@ -1668,7 +1668,7 @@ EXPORT_SYMBOL_GPL(musb_interrupt);
 static bool use_dma = 1;
 
 /* "modprobe ... use_dma=0" etc */
-module_param(use_dma, bool, 0);
+module_param(use_dma, bool, 0644);
 MODULE_PARM_DESC(use_dma, "enable/disable use of DMA");
 
 void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit)
index 26c65e66cc0f1db8680933d13ed2d2b960603906..795a45b1b25bacb016552b4d0635166965ebfce6 100644 (file)
@@ -112,22 +112,32 @@ static void musb_h_tx_flush_fifo(struct musb_hw_ep *ep)
        struct musb     *musb = ep->musb;
        void __iomem    *epio = ep->regs;
        u16             csr;
-       u16             lastcsr = 0;
        int             retries = 1000;
 
        csr = musb_readw(epio, MUSB_TXCSR);
        while (csr & MUSB_TXCSR_FIFONOTEMPTY) {
-               if (csr != lastcsr)
-                       dev_dbg(musb->controller, "Host TX FIFONOTEMPTY csr: %02x\n", csr);
-               lastcsr = csr;
                csr |= MUSB_TXCSR_FLUSHFIFO | MUSB_TXCSR_TXPKTRDY;
                musb_writew(epio, MUSB_TXCSR, csr);
                csr = musb_readw(epio, MUSB_TXCSR);
-               if (WARN(retries-- < 1,
+
+               /*
+                * FIXME: sometimes the tx fifo flush failed, it has been
+                * observed during device disconnect on AM335x.
+                *
+                * To reproduce the issue, ensure tx urb(s) are queued when
+                * unplug the usb device which is connected to AM335x usb
+                * host port.
+                *
+                * I found using a usb-ethernet device and running iperf
+                * (client on AM335x) has very high chance to trigger it.
+                *
+                * Better to turn on dev_dbg() in musb_cleanup_urb() with
+                * CPPI enabled to see the issue when aborting the tx channel.
+                */
+               if (dev_WARN_ONCE(musb->controller, retries-- < 1,
                                "Could not flush host TX%d fifo: csr: %04x\n",
                                ep->epnum, csr))
                        return;
-               mdelay(1);
        }
 }
 
index 4d863ebc117c0f59cce46f39fda4d191e93b9843..b7536af777ab9c4f083d7b88ff2bfe093fca9e21 100644 (file)
@@ -452,10 +452,13 @@ static int mxs_phy_probe(struct platform_device *pdev)
        struct clk *clk;
        struct mxs_phy *mxs_phy;
        int ret;
-       const struct of_device_id *of_id =
-                       of_match_device(mxs_phy_dt_ids, &pdev->dev);
+       const struct of_device_id *of_id;
        struct device_node *np = pdev->dev.of_node;
 
+       of_id = of_match_device(mxs_phy_dt_ids, &pdev->dev);
+       if (!of_id)
+               return -ENODEV;
+
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(base))
index 1270906ccb95808714d174f0461a081c8d1d1cc6..c4bf2de6d14ec3a47259f06977e27ea1f3329ed1 100644 (file)
@@ -105,7 +105,6 @@ static int omap_otg_probe(struct platform_device *pdev)
        extcon = extcon_get_extcon_dev(config->extcon);
        if (!extcon)
                return -EPROBE_DEFER;
-       otg_dev->extcon = extcon;
 
        otg_dev = devm_kzalloc(&pdev->dev, sizeof(*otg_dev), GFP_KERNEL);
        if (!otg_dev)
@@ -115,6 +114,7 @@ static int omap_otg_probe(struct platform_device *pdev)
        if (IS_ERR(otg_dev->base))
                return PTR_ERR(otg_dev->base);
 
+       otg_dev->extcon = extcon;
        otg_dev->id_nb.notifier_call = omap_otg_id_notifier;
        otg_dev->vbus_nb.notifier_call = omap_otg_vbus_notifier;