This patch add a quirk to be compatible for AMD NL SoC Some specific behaviors on NL: - configure USB3 PIPE registers - enable GCTL disscramble - enable U2EXIT_LFPS - enable hibernation at the global level - set LPM errata dissabled Signed-off-by: Huang Rui <ray.huang@xxxxxxx> --- drivers/usb/dwc3/core.c | 33 ++++++++++++++++++++++++++++++++- drivers/usb/dwc3/core.h | 5 +++++ drivers/usb/dwc3/dwc3-pci.c | 14 ++++++++++++++ drivers/usb/dwc3/gadget.c | 8 ++++++++ drivers/usb/dwc3/platform_data.h | 1 + 5 files changed, 60 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index b0f4d52..6138c5d 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -115,6 +115,25 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc) } /** + * dwc3_core_nl_set_pipe3 - Configure USB3 PHY Interface for NL + * @dwc: Pointer to our controller context structure + */ +static void dwc3_core_nl_set_pipe3(struct dwc3 *dwc) +{ + u32 reg = 0; + + reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK | DWC3_GUSB3PIPECTL_UX_EXITINPX + | DWC3_GUSB3PIPECTL_UX_EXITINPX | DWC3_GUSB3PIPECTL_U1U2EXITFAIL + | DWC3_GUSB3PIPECTL_DEPOCHANGE | DWC3_GUSB3PIPECTL_RX_DETOPOLL; + + reg |= DWC3_GUSB3PIPECTL_DEP1P2P3(1) | DWC3_GUSB3PIPECTL_TX_DEEPH(1); + + dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); + + mdelay(100); +} + +/** * dwc3_free_one_event_buffer - Frees one event buffer * @dwc: Pointer to our controller context structure * @evt: Pointer to event buffer to be freed @@ -412,9 +431,19 @@ static int dwc3_core_init(struct dwc3 *dwc) if (ret) goto err0; + if (dwc->quirks & DWC3_AMD_NL_PLAT) + dwc3_core_nl_set_pipe3(dwc); + reg = dwc3_readl(dwc->regs, DWC3_GCTL); + reg &= ~DWC3_GCTL_SCALEDOWN_MASK; - reg &= ~DWC3_GCTL_DISSCRAMBLE; + + if (dwc->quirks & DWC3_AMD_NL_PLAT) { + reg |= DWC3_GCTL_DISSCRAMBLE; + reg |= DWC3_GCTL_U2EXIT_LFPS; + reg |= DWC3_GCTL_GBLHIBERNATIONEN; + } else + reg &= ~DWC3_GCTL_DISSCRAMBLE; switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) { case DWC3_GHWPARAMS1_EN_PWROPT_CLK: @@ -695,6 +724,8 @@ static int dwc3_probe(struct platform_device *pdev) dwc->needs_fifo_resize = pdata->tx_fifo_resize; dwc->dr_mode = pdata->dr_mode; + + dwc->quirks = pdata->quirks; } /* default to superspeed if no maximum_speed passed */ diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index ccde369..a1c7dc5 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -642,6 +642,7 @@ struct dwc3_scratchpad_array { * @u1u2: only used on revisions <1.83a for workaround * @maximum_speed: maximum speed requested (mainly for testing purposes) * @revision: revision register contents + * @quirks: represents different SOCs hardware work-arounds and quirks * @dr_mode: requested mode of operation * @usb2_phy: pointer to USB2 PHY * @usb3_phy: pointer to USB3 PHY @@ -745,6 +746,10 @@ struct dwc3 { #define DWC3_REVISION_270A 0x5533270a #define DWC3_REVISION_280A 0x5533280a + u32 quirks; + +#define DWC3_AMD_NL_PLAT (1 << 0) + enum dwc3_ep0_next ep0_next_event; enum dwc3_ep0_state ep0state; enum dwc3_link_state link_state; diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index cebbd01..7f471ff 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -25,6 +25,9 @@ #include <linux/usb/otg.h> #include <linux/usb/usb_phy_generic.h> +#include "platform_data.h" +#include "core.h" + /* FIXME define these in <linux/pci_ids.h> */ #define PCI_VENDOR_ID_SYNOPSYS 0x16c3 #define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3 0xabcd @@ -102,6 +105,9 @@ static int dwc3_pci_probe(struct pci_dev *pci, struct dwc3_pci *glue; int ret; struct device *dev = &pci->dev; + struct dwc3_platform_data dwc3_pdata; + + memset(&dwc3_pdata, 0x00, sizeof(dwc3_pdata)); glue = devm_kzalloc(dev, sizeof(*glue), GFP_KERNEL); if (!glue) @@ -148,6 +154,14 @@ static int dwc3_pci_probe(struct pci_dev *pci, pci_set_drvdata(pci, glue); + if (pci->vendor == PCI_VENDOR_ID_AMD && + pci->device == PCI_DEVICE_ID_AMD_NL) + dwc3_pdata.quirks |= DWC3_AMD_NL_PLAT; + + ret = platform_device_add_data(dwc3, &dwc3_pdata, sizeof(dwc3_pdata)); + if (ret) + goto err3; + dma_set_coherent_mask(&dwc3->dev, dev->coherent_dma_mask); dwc3->dev.dma_mask = dev->dma_mask; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 0fcc0a3..8277065 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2635,6 +2635,7 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc) */ int dwc3_gadget_init(struct dwc3 *dwc) { + u32 reg; int ret; dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req), @@ -2689,6 +2690,13 @@ int dwc3_gadget_init(struct dwc3 *dwc) if (ret) goto err4; + if (dwc->quirks & DWC3_AMD_NL_PLAT) { + reg = dwc3_readl(dwc->regs, DWC3_DCTL); + reg |= DWC3_DCTL_LPM_ERRATA(0xf); + dwc3_writel(dwc->regs, DWC3_DCTL, reg); + } else + reg = 0; + ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget); if (ret) { dev_err(dwc->dev, "failed to register udc\n"); diff --git a/drivers/usb/dwc3/platform_data.h b/drivers/usb/dwc3/platform_data.h index 7db34f0..b0ef7fa 100644 --- a/drivers/usb/dwc3/platform_data.h +++ b/drivers/usb/dwc3/platform_data.h @@ -24,4 +24,5 @@ struct dwc3_platform_data { enum usb_device_speed maximum_speed; enum usb_dr_mode dr_mode; bool tx_fifo_resize; + u32 quirks; }; -- 1.8.1.2 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html