From: Sandeep Singh <sandeep.si...@amd.com>

commit 2a632815683d2d34df52b701a36fe5ac6654e719 upstream.

On some platform of AMD, S3 fails with HCE and SRE errors. To fix this,
need to disable a bit which is enable in sparse controller.

Cc: sta...@vger.kernel.org #v4.19+
Signed-off-by: Sanket Goswami <sanket.gosw...@amd.com>
Signed-off-by: Sandeep Singh <sandeep.si...@amd.com>
Signed-off-by: Mathias Nyman <mathias.ny...@linux.intel.com>
Link: 
https://lore.kernel.org/r/20201028203124.375344-3-mathias.ny...@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>

---
 drivers/usb/host/xhci-pci.c |   17 +++++++++++++++++
 drivers/usb/host/xhci.h     |    1 +
 2 files changed, 18 insertions(+)

--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -21,6 +21,8 @@
 #define SSIC_PORT_CFG2_OFFSET  0x30
 #define PROG_DONE              (1 << 30)
 #define SSIC_PORT_UNUSED       (1 << 31)
+#define SPARSE_DISABLE_BIT     17
+#define SPARSE_CNTL_ENABLE     0xC12C
 
 /* Device for a quirk */
 #define PCI_VENDOR_ID_FRESCO_LOGIC     0x1b73
@@ -149,6 +151,9 @@ static void xhci_pci_quirks(struct devic
            (pdev->device == 0x15e0 || pdev->device == 0x15e1))
                xhci->quirks |= XHCI_SNPS_BROKEN_SUSPEND;
 
+       if (pdev->vendor == PCI_VENDOR_ID_AMD && pdev->device == 0x15e5)
+               xhci->quirks |= XHCI_DISABLE_SPARSE;
+
        if (pdev->vendor == PCI_VENDOR_ID_AMD)
                xhci->quirks |= XHCI_TRUST_TX_LENGTH;
 
@@ -467,6 +472,15 @@ static void xhci_pme_quirk(struct usb_hc
        readl(reg);
 }
 
+static void xhci_sparse_control_quirk(struct usb_hcd *hcd)
+{
+       u32 reg;
+
+       reg = readl(hcd->regs + SPARSE_CNTL_ENABLE);
+       reg &= ~BIT(SPARSE_DISABLE_BIT);
+       writel(reg, hcd->regs + SPARSE_CNTL_ENABLE);
+}
+
 static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
 {
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
@@ -486,6 +500,9 @@ static int xhci_pci_suspend(struct usb_h
        if (xhci->quirks & XHCI_SSIC_PORT_UNUSED)
                xhci_ssic_port_unused_quirk(hcd, true);
 
+       if (xhci->quirks & XHCI_DISABLE_SPARSE)
+               xhci_sparse_control_quirk(hcd);
+
        ret = xhci_suspend(xhci, do_wakeup);
        if (ret && (xhci->quirks & XHCI_SSIC_PORT_UNUSED))
                xhci_ssic_port_unused_quirk(hcd, false);
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1873,6 +1873,7 @@ struct xhci_hcd {
 #define XHCI_DEFAULT_PM_RUNTIME_ALLOW  BIT_ULL(33)
 #define XHCI_RESET_PLL_ON_DISCONNECT   BIT_ULL(34)
 #define XHCI_SNPS_BROKEN_SUSPEND    BIT_ULL(35)
+#define XHCI_DISABLE_SPARSE    BIT_ULL(38)
 
        unsigned int            num_active_eps;
        unsigned int            limit_active_eps;


Reply via email to