USB fixes for 4.5-rc3
Here are some USB fixes for 4.5-rc3. The usual, xhci fixes for reported issues, combined with some small gadget driver fixes, and a MAINTAINERS file update. All have been in linux-next with no reported issues. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iEYEABECAAYFAla205wACgkQMUfUDdst+ymVcACgksg9fcSsphvjo4ruxN79QrjW GaEAn3VmLc2WyLf13on9cXmBi8KrS+WY =sFPR -----END PGP SIGNATURE----- Merge tag 'usb-4.5-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb Pull USB fixes from Greg KH: "Here are some USB fixes for 4.5-rc3. The usual, xhci fixes for reported issues, combined with some small gadget driver fixes, and a MAINTAINERS file update. All have been in linux-next with no reported issues" * tag 'usb-4.5-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: xhci: harden xhci_find_next_ext_cap against device removal xhci: Fix list corruption in urb dequeue at host removal usb: host: xhci-plat: fix NULL pointer in probe for device tree case usb: xhci-mtk: fix AHB bus hang up caused by roothubs polling usb: xhci-mtk: fix bpkts value of LS/HS periodic eps not behind TT usb: xhci: apply XHCI_PME_STUCK_QUIRK to Intel Broxton-M platforms usb: xhci: set SSIC port unused only if xhci_suspend succeeds usb: xhci: add a quirk bit for ssic port unused usb: xhci: handle both SSIC ports in PME stuck quirk usb: dwc3: gadget: set the OTG flag in dwc3 gadget driver. Revert "xhci: don't finish a TD if we get a short-transfer event mid TD" MAINTAINERS: fix my email address usb: dwc2: Fix probe problem on bcm2835 Revert "usb: dwc2: Move reset into dwc2_get_hwparams()" usb: musb: ux500: Fix NULL pointer dereference at system PM usb: phy: mxs: declare variable with initialized value usb: phy: msm: fix error handling in probe.
This commit is contained in:
commit
46df55ceea
10
MAINTAINERS
10
MAINTAINERS
@ -3450,7 +3450,7 @@ S: Maintained
|
|||||||
F: drivers/usb/dwc2/
|
F: drivers/usb/dwc2/
|
||||||
|
|
||||||
DESIGNWARE USB3 DRD IP DRIVER
|
DESIGNWARE USB3 DRD IP DRIVER
|
||||||
M: Felipe Balbi <balbi@ti.com>
|
M: Felipe Balbi <balbi@kernel.org>
|
||||||
L: linux-usb@vger.kernel.org
|
L: linux-usb@vger.kernel.org
|
||||||
L: linux-omap@vger.kernel.org
|
L: linux-omap@vger.kernel.org
|
||||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
|
||||||
@ -7362,7 +7362,7 @@ F: drivers/tty/isicom.c
|
|||||||
F: include/linux/isicom.h
|
F: include/linux/isicom.h
|
||||||
|
|
||||||
MUSB MULTIPOINT HIGH SPEED DUAL-ROLE CONTROLLER
|
MUSB MULTIPOINT HIGH SPEED DUAL-ROLE CONTROLLER
|
||||||
M: Felipe Balbi <balbi@ti.com>
|
M: Felipe Balbi <balbi@kernel.org>
|
||||||
L: linux-usb@vger.kernel.org
|
L: linux-usb@vger.kernel.org
|
||||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
|
||||||
S: Maintained
|
S: Maintained
|
||||||
@ -7931,7 +7931,7 @@ F: drivers/media/platform/omap3isp/
|
|||||||
F: drivers/staging/media/omap4iss/
|
F: drivers/staging/media/omap4iss/
|
||||||
|
|
||||||
OMAP USB SUPPORT
|
OMAP USB SUPPORT
|
||||||
M: Felipe Balbi <balbi@ti.com>
|
M: Felipe Balbi <balbi@kernel.org>
|
||||||
L: linux-usb@vger.kernel.org
|
L: linux-usb@vger.kernel.org
|
||||||
L: linux-omap@vger.kernel.org
|
L: linux-omap@vger.kernel.org
|
||||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
|
||||||
@ -11314,7 +11314,7 @@ F: Documentation/usb/ehci.txt
|
|||||||
F: drivers/usb/host/ehci*
|
F: drivers/usb/host/ehci*
|
||||||
|
|
||||||
USB GADGET/PERIPHERAL SUBSYSTEM
|
USB GADGET/PERIPHERAL SUBSYSTEM
|
||||||
M: Felipe Balbi <balbi@ti.com>
|
M: Felipe Balbi <balbi@kernel.org>
|
||||||
L: linux-usb@vger.kernel.org
|
L: linux-usb@vger.kernel.org
|
||||||
W: http://www.linux-usb.org/gadget
|
W: http://www.linux-usb.org/gadget
|
||||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
|
||||||
@ -11390,7 +11390,7 @@ S: Maintained
|
|||||||
F: drivers/net/usb/pegasus.*
|
F: drivers/net/usb/pegasus.*
|
||||||
|
|
||||||
USB PHY LAYER
|
USB PHY LAYER
|
||||||
M: Felipe Balbi <balbi@ti.com>
|
M: Felipe Balbi <balbi@kernel.org>
|
||||||
L: linux-usb@vger.kernel.org
|
L: linux-usb@vger.kernel.org
|
||||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
@ -572,12 +572,6 @@ static bool dwc2_force_mode(struct dwc2_hsotg *hsotg, bool host)
|
|||||||
set = host ? GUSBCFG_FORCEHOSTMODE : GUSBCFG_FORCEDEVMODE;
|
set = host ? GUSBCFG_FORCEHOSTMODE : GUSBCFG_FORCEDEVMODE;
|
||||||
clear = host ? GUSBCFG_FORCEDEVMODE : GUSBCFG_FORCEHOSTMODE;
|
clear = host ? GUSBCFG_FORCEDEVMODE : GUSBCFG_FORCEHOSTMODE;
|
||||||
|
|
||||||
/*
|
|
||||||
* If the force mode bit is already set, don't set it.
|
|
||||||
*/
|
|
||||||
if ((gusbcfg & set) && !(gusbcfg & clear))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
gusbcfg &= ~clear;
|
gusbcfg &= ~clear;
|
||||||
gusbcfg |= set;
|
gusbcfg |= set;
|
||||||
dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG);
|
dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG);
|
||||||
@ -3278,9 +3272,6 @@ static void dwc2_get_dev_hwparams(struct dwc2_hsotg *hsotg)
|
|||||||
/**
|
/**
|
||||||
* During device initialization, read various hardware configuration
|
* During device initialization, read various hardware configuration
|
||||||
* registers and interpret the contents.
|
* registers and interpret the contents.
|
||||||
*
|
|
||||||
* This should be called during driver probe. It will perform a core
|
|
||||||
* soft reset in order to get the reset values of the parameters.
|
|
||||||
*/
|
*/
|
||||||
int dwc2_get_hwparams(struct dwc2_hsotg *hsotg)
|
int dwc2_get_hwparams(struct dwc2_hsotg *hsotg)
|
||||||
{
|
{
|
||||||
@ -3288,7 +3279,6 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg)
|
|||||||
unsigned width;
|
unsigned width;
|
||||||
u32 hwcfg1, hwcfg2, hwcfg3, hwcfg4;
|
u32 hwcfg1, hwcfg2, hwcfg3, hwcfg4;
|
||||||
u32 grxfsiz;
|
u32 grxfsiz;
|
||||||
int retval;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Attempt to ensure this device is really a DWC_otg Controller.
|
* Attempt to ensure this device is really a DWC_otg Controller.
|
||||||
@ -3308,10 +3298,6 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg)
|
|||||||
hw->snpsid >> 12 & 0xf, hw->snpsid >> 8 & 0xf,
|
hw->snpsid >> 12 & 0xf, hw->snpsid >> 8 & 0xf,
|
||||||
hw->snpsid >> 4 & 0xf, hw->snpsid & 0xf, hw->snpsid);
|
hw->snpsid >> 4 & 0xf, hw->snpsid & 0xf, hw->snpsid);
|
||||||
|
|
||||||
retval = dwc2_core_reset(hsotg);
|
|
||||||
if (retval)
|
|
||||||
return retval;
|
|
||||||
|
|
||||||
hwcfg1 = dwc2_readl(hsotg->regs + GHWCFG1);
|
hwcfg1 = dwc2_readl(hsotg->regs + GHWCFG1);
|
||||||
hwcfg2 = dwc2_readl(hsotg->regs + GHWCFG2);
|
hwcfg2 = dwc2_readl(hsotg->regs + GHWCFG2);
|
||||||
hwcfg3 = dwc2_readl(hsotg->regs + GHWCFG3);
|
hwcfg3 = dwc2_readl(hsotg->regs + GHWCFG3);
|
||||||
|
@ -530,7 +530,13 @@ static int dwc2_driver_probe(struct platform_device *dev)
|
|||||||
if (retval)
|
if (retval)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* Reset the controller and detect hardware config values */
|
/*
|
||||||
|
* Reset before dwc2_get_hwparams() then it could get power-on real
|
||||||
|
* reset value form registers.
|
||||||
|
*/
|
||||||
|
dwc2_core_reset_and_force_dr_mode(hsotg);
|
||||||
|
|
||||||
|
/* Detect config values from hardware */
|
||||||
retval = dwc2_get_hwparams(hsotg);
|
retval = dwc2_get_hwparams(hsotg);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -2789,6 +2789,7 @@ int dwc3_gadget_init(struct dwc3 *dwc)
|
|||||||
dwc->gadget.speed = USB_SPEED_UNKNOWN;
|
dwc->gadget.speed = USB_SPEED_UNKNOWN;
|
||||||
dwc->gadget.sg_supported = true;
|
dwc->gadget.sg_supported = true;
|
||||||
dwc->gadget.name = "dwc3-gadget";
|
dwc->gadget.name = "dwc3-gadget";
|
||||||
|
dwc->gadget.is_otg = dwc->dr_mode == USB_DR_MODE_OTG;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FIXME We might be setting max_speed to <SUPER, however versions
|
* FIXME We might be setting max_speed to <SUPER, however versions
|
||||||
|
@ -112,12 +112,16 @@ static inline int xhci_find_next_ext_cap(void __iomem *base, u32 start, int id)
|
|||||||
offset = start;
|
offset = start;
|
||||||
if (!start || start == XHCI_HCC_PARAMS_OFFSET) {
|
if (!start || start == XHCI_HCC_PARAMS_OFFSET) {
|
||||||
val = readl(base + XHCI_HCC_PARAMS_OFFSET);
|
val = readl(base + XHCI_HCC_PARAMS_OFFSET);
|
||||||
|
if (val == ~0)
|
||||||
|
return 0;
|
||||||
offset = XHCI_HCC_EXT_CAPS(val) << 2;
|
offset = XHCI_HCC_EXT_CAPS(val) << 2;
|
||||||
if (!offset)
|
if (!offset)
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
do {
|
do {
|
||||||
val = readl(base + offset);
|
val = readl(base + offset);
|
||||||
|
if (val == ~0)
|
||||||
|
return 0;
|
||||||
if (XHCI_EXT_CAPS_ID(val) == id && offset != start)
|
if (XHCI_EXT_CAPS_ID(val) == id && offset != start)
|
||||||
return offset;
|
return offset;
|
||||||
|
|
||||||
|
@ -275,8 +275,9 @@ static bool need_bw_sch(struct usb_host_endpoint *ep,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* for LS & FS periodic endpoints which its device don't attach
|
* for LS & FS periodic endpoints which its device is not behind
|
||||||
* to TT are also ignored, root-hub will schedule them directly
|
* a TT are also ignored, root-hub will schedule them directly,
|
||||||
|
* but need set @bpkts field of endpoint context to 1.
|
||||||
*/
|
*/
|
||||||
if (is_fs_or_ls(speed) && !has_tt)
|
if (is_fs_or_ls(speed) && !has_tt)
|
||||||
return false;
|
return false;
|
||||||
@ -339,8 +340,17 @@ int xhci_mtk_add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
|
|||||||
GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)),
|
GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)),
|
||||||
usb_endpoint_dir_in(&ep->desc), ep);
|
usb_endpoint_dir_in(&ep->desc), ep);
|
||||||
|
|
||||||
if (!need_bw_sch(ep, udev->speed, slot_ctx->tt_info & TT_SLOT))
|
if (!need_bw_sch(ep, udev->speed, slot_ctx->tt_info & TT_SLOT)) {
|
||||||
|
/*
|
||||||
|
* set @bpkts to 1 if it is LS or FS periodic endpoint, and its
|
||||||
|
* device does not connected through an external HS hub
|
||||||
|
*/
|
||||||
|
if (usb_endpoint_xfer_int(&ep->desc)
|
||||||
|
|| usb_endpoint_xfer_isoc(&ep->desc))
|
||||||
|
ep_ctx->reserved[0] |= cpu_to_le32(EP_BPKTS(1));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bw_index = get_bw_index(xhci, udev, ep);
|
bw_index = get_bw_index(xhci, udev, ep);
|
||||||
sch_bw = &sch_array[bw_index];
|
sch_bw = &sch_array[bw_index];
|
||||||
|
@ -696,9 +696,24 @@ static int xhci_mtk_remove(struct platform_device *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM_SLEEP
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
/*
|
||||||
|
* if ip sleep fails, and all clocks are disabled, access register will hang
|
||||||
|
* AHB bus, so stop polling roothubs to avoid regs access on bus suspend.
|
||||||
|
* and no need to check whether ip sleep failed or not; this will cause SPM
|
||||||
|
* to wake up system immediately after system suspend complete if ip sleep
|
||||||
|
* fails, it is what we wanted.
|
||||||
|
*/
|
||||||
static int xhci_mtk_suspend(struct device *dev)
|
static int xhci_mtk_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
|
struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
|
||||||
|
struct usb_hcd *hcd = mtk->hcd;
|
||||||
|
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||||
|
|
||||||
|
xhci_dbg(xhci, "%s: stop port polling\n", __func__);
|
||||||
|
clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
|
||||||
|
del_timer_sync(&hcd->rh_timer);
|
||||||
|
clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
|
||||||
|
del_timer_sync(&xhci->shared_hcd->rh_timer);
|
||||||
|
|
||||||
xhci_mtk_host_disable(mtk);
|
xhci_mtk_host_disable(mtk);
|
||||||
xhci_mtk_phy_power_off(mtk);
|
xhci_mtk_phy_power_off(mtk);
|
||||||
@ -710,11 +725,19 @@ static int xhci_mtk_suspend(struct device *dev)
|
|||||||
static int xhci_mtk_resume(struct device *dev)
|
static int xhci_mtk_resume(struct device *dev)
|
||||||
{
|
{
|
||||||
struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
|
struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
|
||||||
|
struct usb_hcd *hcd = mtk->hcd;
|
||||||
|
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||||
|
|
||||||
usb_wakeup_disable(mtk);
|
usb_wakeup_disable(mtk);
|
||||||
xhci_mtk_clks_enable(mtk);
|
xhci_mtk_clks_enable(mtk);
|
||||||
xhci_mtk_phy_power_on(mtk);
|
xhci_mtk_phy_power_on(mtk);
|
||||||
xhci_mtk_host_enable(mtk);
|
xhci_mtk_host_enable(mtk);
|
||||||
|
|
||||||
|
xhci_dbg(xhci, "%s: restart port polling\n", __func__);
|
||||||
|
set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
|
||||||
|
usb_hcd_poll_rh_status(hcd);
|
||||||
|
set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
|
||||||
|
usb_hcd_poll_rh_status(xhci->shared_hcd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,9 @@
|
|||||||
#include "xhci.h"
|
#include "xhci.h"
|
||||||
#include "xhci-trace.h"
|
#include "xhci-trace.h"
|
||||||
|
|
||||||
#define PORT2_SSIC_CONFIG_REG2 0x883c
|
#define SSIC_PORT_NUM 2
|
||||||
|
#define SSIC_PORT_CFG2 0x880c
|
||||||
|
#define SSIC_PORT_CFG2_OFFSET 0x30
|
||||||
#define PROG_DONE (1 << 30)
|
#define PROG_DONE (1 << 30)
|
||||||
#define SSIC_PORT_UNUSED (1 << 31)
|
#define SSIC_PORT_UNUSED (1 << 31)
|
||||||
|
|
||||||
@ -45,6 +47,7 @@
|
|||||||
#define PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI 0x22b5
|
#define PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI 0x22b5
|
||||||
#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI 0xa12f
|
#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI 0xa12f
|
||||||
#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI 0x9d2f
|
#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI 0x9d2f
|
||||||
|
#define PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI 0x0aa8
|
||||||
|
|
||||||
static const char hcd_name[] = "xhci_hcd";
|
static const char hcd_name[] = "xhci_hcd";
|
||||||
|
|
||||||
@ -151,9 +154,14 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
|
|||||||
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
|
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
|
||||||
(pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI ||
|
(pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI ||
|
||||||
pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI ||
|
pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI ||
|
||||||
pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI)) {
|
pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI ||
|
||||||
|
pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI)) {
|
||||||
xhci->quirks |= XHCI_PME_STUCK_QUIRK;
|
xhci->quirks |= XHCI_PME_STUCK_QUIRK;
|
||||||
}
|
}
|
||||||
|
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
|
||||||
|
pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) {
|
||||||
|
xhci->quirks |= XHCI_SSIC_PORT_UNUSED;
|
||||||
|
}
|
||||||
if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
|
if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
|
||||||
pdev->device == PCI_DEVICE_ID_EJ168) {
|
pdev->device == PCI_DEVICE_ID_EJ168) {
|
||||||
xhci->quirks |= XHCI_RESET_ON_RESUME;
|
xhci->quirks |= XHCI_RESET_ON_RESUME;
|
||||||
@ -312,22 +320,20 @@ static void xhci_pci_remove(struct pci_dev *dev)
|
|||||||
* SSIC PORT need to be marked as "unused" before putting xHCI
|
* SSIC PORT need to be marked as "unused" before putting xHCI
|
||||||
* into D3. After D3 exit, the SSIC port need to be marked as "used".
|
* into D3. After D3 exit, the SSIC port need to be marked as "used".
|
||||||
* Without this change, xHCI might not enter D3 state.
|
* Without this change, xHCI might not enter D3 state.
|
||||||
* Make sure PME works on some Intel xHCI controllers by writing 1 to clear
|
|
||||||
* the Internal PME flag bit in vendor specific PMCTRL register at offset 0x80a4
|
|
||||||
*/
|
*/
|
||||||
static void xhci_pme_quirk(struct usb_hcd *hcd, bool suspend)
|
static void xhci_ssic_port_unused_quirk(struct usb_hcd *hcd, bool suspend)
|
||||||
{
|
{
|
||||||
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||||
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
|
|
||||||
u32 val;
|
u32 val;
|
||||||
void __iomem *reg;
|
void __iomem *reg;
|
||||||
|
int i;
|
||||||
|
|
||||||
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
|
for (i = 0; i < SSIC_PORT_NUM; i++) {
|
||||||
pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) {
|
reg = (void __iomem *) xhci->cap_regs +
|
||||||
|
SSIC_PORT_CFG2 +
|
||||||
|
i * SSIC_PORT_CFG2_OFFSET;
|
||||||
|
|
||||||
reg = (void __iomem *) xhci->cap_regs + PORT2_SSIC_CONFIG_REG2;
|
/* Notify SSIC that SSIC profile programming is not done. */
|
||||||
|
|
||||||
/* Notify SSIC that SSIC profile programming is not done */
|
|
||||||
val = readl(reg) & ~PROG_DONE;
|
val = readl(reg) & ~PROG_DONE;
|
||||||
writel(val, reg);
|
writel(val, reg);
|
||||||
|
|
||||||
@ -344,6 +350,17 @@ static void xhci_pme_quirk(struct usb_hcd *hcd, bool suspend)
|
|||||||
writel(val, reg);
|
writel(val, reg);
|
||||||
readl(reg);
|
readl(reg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure PME works on some Intel xHCI controllers by writing 1 to clear
|
||||||
|
* the Internal PME flag bit in vendor specific PMCTRL register at offset 0x80a4
|
||||||
|
*/
|
||||||
|
static void xhci_pme_quirk(struct usb_hcd *hcd)
|
||||||
|
{
|
||||||
|
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||||
|
void __iomem *reg;
|
||||||
|
u32 val;
|
||||||
|
|
||||||
reg = (void __iomem *) xhci->cap_regs + 0x80a4;
|
reg = (void __iomem *) xhci->cap_regs + 0x80a4;
|
||||||
val = readl(reg);
|
val = readl(reg);
|
||||||
@ -355,6 +372,7 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
|
|||||||
{
|
{
|
||||||
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||||
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
|
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
|
||||||
|
int ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Systems with the TI redriver that loses port status change events
|
* Systems with the TI redriver that loses port status change events
|
||||||
@ -364,9 +382,16 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
|
|||||||
pdev->no_d3cold = true;
|
pdev->no_d3cold = true;
|
||||||
|
|
||||||
if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
|
if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
|
||||||
xhci_pme_quirk(hcd, true);
|
xhci_pme_quirk(hcd);
|
||||||
|
|
||||||
return xhci_suspend(xhci, do_wakeup);
|
if (xhci->quirks & XHCI_SSIC_PORT_UNUSED)
|
||||||
|
xhci_ssic_port_unused_quirk(hcd, true);
|
||||||
|
|
||||||
|
ret = xhci_suspend(xhci, do_wakeup);
|
||||||
|
if (ret && (xhci->quirks & XHCI_SSIC_PORT_UNUSED))
|
||||||
|
xhci_ssic_port_unused_quirk(hcd, false);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
|
static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
|
||||||
@ -396,8 +421,11 @@ static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
|
|||||||
if (pdev->vendor == PCI_VENDOR_ID_INTEL)
|
if (pdev->vendor == PCI_VENDOR_ID_INTEL)
|
||||||
usb_enable_intel_xhci_ports(pdev);
|
usb_enable_intel_xhci_ports(pdev);
|
||||||
|
|
||||||
|
if (xhci->quirks & XHCI_SSIC_PORT_UNUSED)
|
||||||
|
xhci_ssic_port_unused_quirk(hcd, false);
|
||||||
|
|
||||||
if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
|
if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
|
||||||
xhci_pme_quirk(hcd, false);
|
xhci_pme_quirk(hcd);
|
||||||
|
|
||||||
retval = xhci_resume(xhci, hibernated);
|
retval = xhci_resume(xhci, hibernated);
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -184,7 +184,8 @@ static int xhci_plat_probe(struct platform_device *pdev)
|
|||||||
struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd);
|
struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd);
|
||||||
|
|
||||||
/* Just copy data for now */
|
/* Just copy data for now */
|
||||||
*priv = *priv_match;
|
if (priv_match)
|
||||||
|
*priv = *priv_match;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xhci_plat_type_is(hcd, XHCI_PLAT_TYPE_MARVELL_ARMADA)) {
|
if (xhci_plat_type_is(hcd, XHCI_PLAT_TYPE_MARVELL_ARMADA)) {
|
||||||
|
@ -2193,10 +2193,6 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
|
|||||||
}
|
}
|
||||||
/* Fast path - was this the last TRB in the TD for this URB? */
|
/* Fast path - was this the last TRB in the TD for this URB? */
|
||||||
} else if (event_trb == td->last_trb) {
|
} else if (event_trb == td->last_trb) {
|
||||||
if (td->urb_length_set && trb_comp_code == COMP_SHORT_TX)
|
|
||||||
return finish_td(xhci, td, event_trb, event, ep,
|
|
||||||
status, false);
|
|
||||||
|
|
||||||
if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
|
if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
|
||||||
td->urb->actual_length =
|
td->urb->actual_length =
|
||||||
td->urb->transfer_buffer_length -
|
td->urb->transfer_buffer_length -
|
||||||
@ -2248,12 +2244,6 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
|
|||||||
td->urb->actual_length +=
|
td->urb->actual_length +=
|
||||||
TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
|
TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
|
||||||
EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
|
EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
|
||||||
|
|
||||||
if (trb_comp_code == COMP_SHORT_TX) {
|
|
||||||
xhci_dbg(xhci, "mid bulk/intr SP, wait for last TRB event\n");
|
|
||||||
td->urb_length_set = true;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return finish_td(xhci, td, event_trb, event, ep, status, false);
|
return finish_td(xhci, td, event_trb, event, ep, status, false);
|
||||||
|
@ -1554,7 +1554,9 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
|
|||||||
xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
|
xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
|
||||||
"HW died, freeing TD.");
|
"HW died, freeing TD.");
|
||||||
urb_priv = urb->hcpriv;
|
urb_priv = urb->hcpriv;
|
||||||
for (i = urb_priv->td_cnt; i < urb_priv->length; i++) {
|
for (i = urb_priv->td_cnt;
|
||||||
|
i < urb_priv->length && xhci->devs[urb->dev->slot_id];
|
||||||
|
i++) {
|
||||||
td = urb_priv->td[i];
|
td = urb_priv->td[i];
|
||||||
if (!list_empty(&td->td_list))
|
if (!list_empty(&td->td_list))
|
||||||
list_del_init(&td->td_list);
|
list_del_init(&td->td_list);
|
||||||
|
@ -1631,6 +1631,7 @@ struct xhci_hcd {
|
|||||||
#define XHCI_BROKEN_STREAMS (1 << 19)
|
#define XHCI_BROKEN_STREAMS (1 << 19)
|
||||||
#define XHCI_PME_STUCK_QUIRK (1 << 20)
|
#define XHCI_PME_STUCK_QUIRK (1 << 20)
|
||||||
#define XHCI_MTK_HOST (1 << 21)
|
#define XHCI_MTK_HOST (1 << 21)
|
||||||
|
#define XHCI_SSIC_PORT_UNUSED (1 << 22)
|
||||||
unsigned int num_active_eps;
|
unsigned int num_active_eps;
|
||||||
unsigned int limit_active_eps;
|
unsigned int limit_active_eps;
|
||||||
/* There are two roothubs to keep track of bus suspend info for */
|
/* There are two roothubs to keep track of bus suspend info for */
|
||||||
|
@ -348,7 +348,9 @@ static int ux500_suspend(struct device *dev)
|
|||||||
struct ux500_glue *glue = dev_get_drvdata(dev);
|
struct ux500_glue *glue = dev_get_drvdata(dev);
|
||||||
struct musb *musb = glue_to_musb(glue);
|
struct musb *musb = glue_to_musb(glue);
|
||||||
|
|
||||||
usb_phy_set_suspend(musb->xceiv, 1);
|
if (musb)
|
||||||
|
usb_phy_set_suspend(musb->xceiv, 1);
|
||||||
|
|
||||||
clk_disable_unprepare(glue->clk);
|
clk_disable_unprepare(glue->clk);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -366,7 +368,8 @@ static int ux500_resume(struct device *dev)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
usb_phy_set_suspend(musb->xceiv, 0);
|
if (musb)
|
||||||
|
usb_phy_set_suspend(musb->xceiv, 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1599,6 +1599,8 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg)
|
|||||||
&motg->id.nb);
|
&motg->id.nb);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(&pdev->dev, "register ID notifier failed\n");
|
dev_err(&pdev->dev, "register ID notifier failed\n");
|
||||||
|
extcon_unregister_notifier(motg->vbus.extcon,
|
||||||
|
EXTCON_USB, &motg->vbus.nb);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1660,15 +1662,6 @@ static int msm_otg_probe(struct platform_device *pdev)
|
|||||||
if (!motg)
|
if (!motg)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
pdata = dev_get_platdata(&pdev->dev);
|
|
||||||
if (!pdata) {
|
|
||||||
if (!np)
|
|
||||||
return -ENXIO;
|
|
||||||
ret = msm_otg_read_dt(pdev, motg);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
motg->phy.otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg),
|
motg->phy.otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!motg->phy.otg)
|
if (!motg->phy.otg)
|
||||||
@ -1710,6 +1703,15 @@ static int msm_otg_probe(struct platform_device *pdev)
|
|||||||
if (!motg->regs)
|
if (!motg->regs)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
pdata = dev_get_platdata(&pdev->dev);
|
||||||
|
if (!pdata) {
|
||||||
|
if (!np)
|
||||||
|
return -ENXIO;
|
||||||
|
ret = msm_otg_read_dt(pdev, motg);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOTE: The PHYs can be multiplexed between the chipidea controller
|
* NOTE: The PHYs can be multiplexed between the chipidea controller
|
||||||
* and the dwc3 controller, using a single bit. It is important that
|
* and the dwc3 controller, using a single bit. It is important that
|
||||||
@ -1717,8 +1719,10 @@ static int msm_otg_probe(struct platform_device *pdev)
|
|||||||
*/
|
*/
|
||||||
if (motg->phy_number) {
|
if (motg->phy_number) {
|
||||||
phy_select = devm_ioremap_nocache(&pdev->dev, USB2_PHY_SEL, 4);
|
phy_select = devm_ioremap_nocache(&pdev->dev, USB2_PHY_SEL, 4);
|
||||||
if (!phy_select)
|
if (!phy_select) {
|
||||||
return -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
goto unregister_extcon;
|
||||||
|
}
|
||||||
/* Enable second PHY with the OTG port */
|
/* Enable second PHY with the OTG port */
|
||||||
writel(0x1, phy_select);
|
writel(0x1, phy_select);
|
||||||
}
|
}
|
||||||
@ -1728,7 +1732,8 @@ static int msm_otg_probe(struct platform_device *pdev)
|
|||||||
motg->irq = platform_get_irq(pdev, 0);
|
motg->irq = platform_get_irq(pdev, 0);
|
||||||
if (motg->irq < 0) {
|
if (motg->irq < 0) {
|
||||||
dev_err(&pdev->dev, "platform_get_irq failed\n");
|
dev_err(&pdev->dev, "platform_get_irq failed\n");
|
||||||
return motg->irq;
|
ret = motg->irq;
|
||||||
|
goto unregister_extcon;
|
||||||
}
|
}
|
||||||
|
|
||||||
regs[0].supply = "vddcx";
|
regs[0].supply = "vddcx";
|
||||||
@ -1737,7 +1742,7 @@ static int msm_otg_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
ret = devm_regulator_bulk_get(motg->phy.dev, ARRAY_SIZE(regs), regs);
|
ret = devm_regulator_bulk_get(motg->phy.dev, ARRAY_SIZE(regs), regs);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto unregister_extcon;
|
||||||
|
|
||||||
motg->vddcx = regs[0].consumer;
|
motg->vddcx = regs[0].consumer;
|
||||||
motg->v3p3 = regs[1].consumer;
|
motg->v3p3 = regs[1].consumer;
|
||||||
@ -1834,6 +1839,12 @@ disable_clks:
|
|||||||
clk_disable_unprepare(motg->clk);
|
clk_disable_unprepare(motg->clk);
|
||||||
if (!IS_ERR(motg->core_clk))
|
if (!IS_ERR(motg->core_clk))
|
||||||
clk_disable_unprepare(motg->core_clk);
|
clk_disable_unprepare(motg->core_clk);
|
||||||
|
unregister_extcon:
|
||||||
|
extcon_unregister_notifier(motg->id.extcon,
|
||||||
|
EXTCON_USB_HOST, &motg->id.nb);
|
||||||
|
extcon_unregister_notifier(motg->vbus.extcon,
|
||||||
|
EXTCON_USB, &motg->vbus.nb);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,7 +220,7 @@ static int mxs_phy_hw_init(struct mxs_phy *mxs_phy)
|
|||||||
/* Return true if the vbus is there */
|
/* Return true if the vbus is there */
|
||||||
static bool mxs_phy_get_vbus_status(struct mxs_phy *mxs_phy)
|
static bool mxs_phy_get_vbus_status(struct mxs_phy *mxs_phy)
|
||||||
{
|
{
|
||||||
unsigned int vbus_value;
|
unsigned int vbus_value = 0;
|
||||||
|
|
||||||
if (!mxs_phy->regmap_anatop)
|
if (!mxs_phy->regmap_anatop)
|
||||||
return false;
|
return false;
|
||||||
|
Loading…
Reference in New Issue
Block a user