diff options
author | Thinh Nguyen <Thinh.Nguyen@synopsys.com> | 2020-04-12 05:20:01 +0300 |
---|---|---|
committer | Felipe Balbi <balbi@kernel.org> | 2020-05-25 11:09:40 +0300 |
commit | 9af21dd6faeba593fb47f5cceaf69b1e5a3ff95f (patch) | |
tree | ed12d18ee5161ecea71fc70e9c42ad6295e8158c /drivers/usb/dwc3/core.c | |
parent | 88607a821ffc04034dea91747f79f2d83fe5c232 (diff) | |
download | linux-9af21dd6faeba593fb47f5cceaf69b1e5a3ff95f.tar.xz |
usb: dwc3: Add support for DWC_usb32 IP
Synopsys introduces a new controller DWC_usb32. It supports dual-lane
and speed up to 20 Gbps, and the DWC3 driver will drive this controller.
Currently the driver uses a single field dwc->revision to ID both
DWC_usb3 and DWC_usb31 and their version number. This was sufficient for
two IPs, but this method doesn't work with additional IPs. As a result,
let's separate the dwc->revision field to 2 separate fields: ip and
revision. The ip field now stores the ID of the controller's IP while
the revision field stores the controller's version number.
This new scheme enforces DWC3 to compare the revision within the same IP
only. As a result, we must update all the revision check of the
controller to check its corresponding IP.
To help with this enforcement, we create a few macros to help with
the common version checks:
DWC3_IP_IS(IP)
DWC3_VER_IS(IP, VERSION)
DWC3_VER_IS_PRIOR(IP, VERSION)
DWC3_VER_IS_WITHIN(IP, LOWER_VERSION, UPPER_VERSION)
DWC3_VER_TYPE_IS_WITHIN(IP, VERSION,
LOWER_VERSION_TYPE,
UPPER_VERSION_TYPE)
The DWC_usb32 controller operates using the same programming model and
with very similar configurations as its previous controllers. Please
note that the various IP and revision checks in this patch match the
current checks for DWC_usb31 version 1.90a. Additional configurations
that are unique to DWC_usb32 are applied separately.
Signed-off-by: Thinh Nguyen <thinhn@synopsys.com>
Signed-off-by: Felipe Balbi <balbi@kernel.org>
Diffstat (limited to 'drivers/usb/dwc3/core.c')
-rw-r--r-- | drivers/usb/dwc3/core.c | 49 |
1 files changed, 22 insertions, 27 deletions
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index ab6323b8e323..25c686a752b0 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -87,7 +87,7 @@ static int dwc3_get_dr_mode(struct dwc3 *dwc) if (mode == USB_DR_MODE_OTG && (!IS_ENABLED(CONFIG_USB_ROLE_SWITCH) || !device_property_read_bool(dwc->dev, "usb-role-switch")) && - dwc->revision >= DWC3_REVISION_330A) + !DWC3_VER_IS_PRIOR(DWC3, 330A)) mode = USB_DR_MODE_PERIPHERAL; } @@ -264,7 +264,7 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc) * take a little more than 50ms. Set the polling rate at 20ms * for 10 times instead. */ - if (dwc3_is_usb31(dwc) && dwc->revision >= DWC3_USB31_REVISION_190A) + if (DWC3_VER_IS_WITHIN(DWC31, 190A, ANY) || DWC3_IP_IS(DWC32)) retries = 10; do { @@ -272,8 +272,7 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc) if (!(reg & DWC3_DCTL_CSFTRST)) goto done; - if (dwc3_is_usb31(dwc) && - dwc->revision >= DWC3_USB31_REVISION_190A) + if (DWC3_VER_IS_WITHIN(DWC31, 190A, ANY) || DWC3_IP_IS(DWC32)) msleep(20); else udelay(1); @@ -290,7 +289,7 @@ done: * is cleared, we must wait at least 50ms before accessing the PHY * domain (synchronization delay). */ - if (dwc3_is_usb31(dwc) && dwc->revision <= DWC3_USB31_REVISION_180A) + if (DWC3_VER_IS_WITHIN(DWC31, ANY, 180A)) msleep(50); return 0; @@ -305,7 +304,7 @@ static void dwc3_frame_length_adjustment(struct dwc3 *dwc) u32 reg; u32 dft; - if (dwc->revision < DWC3_REVISION_250A) + if (DWC3_VER_IS_PRIOR(DWC3, 250A)) return; if (dwc->fladj == 0) @@ -586,7 +585,7 @@ static int dwc3_phy_setup(struct dwc3 *dwc) * will be '0' when the core is reset. Application needs to set it * to '1' after the core initialization is completed. */ - if (dwc->revision > DWC3_REVISION_194A) + if (!DWC3_VER_IS_WITHIN(DWC3, ANY, 194A)) reg |= DWC3_GUSB3PIPECTL_SUSPHY; /* @@ -677,7 +676,7 @@ static int dwc3_phy_setup(struct dwc3 *dwc) * be '0' when the core is reset. Application needs to set it to * '1' after the core initialization is completed. */ - if (dwc->revision > DWC3_REVISION_194A) + if (!DWC3_VER_IS_WITHIN(DWC3, ANY, 194A)) reg |= DWC3_GUSB2PHYCFG_SUSPHY; /* @@ -726,15 +725,13 @@ static bool dwc3_core_is_valid(struct dwc3 *dwc) u32 reg; reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); + dwc->ip = DWC3_GSNPS_ID(reg); /* This should read as U3 followed by revision number */ - if ((reg & DWC3_GSNPSID_MASK) == 0x55330000) { - /* Detected DWC_usb3 IP */ + if (DWC3_IP_IS(DWC3)) { dwc->revision = reg; - } else if ((reg & DWC3_GSNPSID_MASK) == 0x33310000) { - /* Detected DWC_usb31 IP */ + } else if (DWC3_IP_IS(DWC31) || DWC3_IP_IS(DWC32)) { dwc->revision = dwc3_readl(dwc->regs, DWC3_VER_NUMBER); - dwc->revision |= DWC3_REVISION_IS_DWC31; dwc->version_type = dwc3_readl(dwc->regs, DWC3_VER_TYPE); } else { return false; @@ -767,8 +764,7 @@ static void dwc3_core_setup_global_control(struct dwc3 *dwc) */ if ((dwc->dr_mode == USB_DR_MODE_HOST || dwc->dr_mode == USB_DR_MODE_OTG) && - (dwc->revision >= DWC3_REVISION_210A && - dwc->revision <= DWC3_REVISION_250A)) + DWC3_VER_IS_WITHIN(DWC3, 210A, 250A)) reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC; else reg &= ~DWC3_GCTL_DSBLCLKGTNG; @@ -811,7 +807,7 @@ static void dwc3_core_setup_global_control(struct dwc3 *dwc) * and falls back to high-speed mode which causes * the device to enter a Connect/Disconnect loop */ - if (dwc->revision < DWC3_REVISION_190A) + if (DWC3_VER_IS_PRIOR(DWC3, 190A)) reg |= DWC3_GCTL_U2RSTECN; dwc3_writel(dwc->regs, DWC3_GCTL, reg); @@ -964,7 +960,7 @@ static int dwc3_core_init(struct dwc3 *dwc) goto err0a; if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD && - dwc->revision > DWC3_REVISION_194A) { + !DWC3_VER_IS_WITHIN(DWC3, ANY, 194A)) { if (!dwc->dis_u3_susphy_quirk) { reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); reg |= DWC3_GUSB3PIPECTL_SUSPHY; @@ -1011,20 +1007,20 @@ static int dwc3_core_init(struct dwc3 *dwc) * the DWC_usb3 controller. It is NOT available in the * DWC_usb31 controller. */ - if (!dwc3_is_usb31(dwc) && dwc->revision >= DWC3_REVISION_310A) { + if (DWC3_VER_IS_WITHIN(DWC3, 310A, ANY)) { reg = dwc3_readl(dwc->regs, DWC3_GUCTL2); reg |= DWC3_GUCTL2_RST_ACTBITLATER; dwc3_writel(dwc->regs, DWC3_GUCTL2, reg); } - if (dwc->revision >= DWC3_REVISION_250A) { + if (!DWC3_VER_IS_PRIOR(DWC3, 250A)) { reg = dwc3_readl(dwc->regs, DWC3_GUCTL1); /* * Enable hardware control of sending remote wakeup * in HS when the device is in the L1 state. */ - if (dwc->revision >= DWC3_REVISION_290A) + if (!DWC3_VER_IS_PRIOR(DWC3, 290A)) reg |= DWC3_GUCTL1_DEV_L1_EXIT_BY_HW; if (dwc->dis_tx_ipgap_linecheck_quirk) @@ -1056,7 +1052,7 @@ static int dwc3_core_init(struct dwc3 *dwc) * Must config both number of packets and max burst settings to enable * RX and/or TX threshold. */ - if (dwc3_is_usb31(dwc) && dwc->dr_mode == USB_DR_MODE_HOST) { + if (!DWC3_IP_IS(DWC3) && dwc->dr_mode == USB_DR_MODE_HOST) { u8 rx_thr_num = dwc->rx_thr_num_pkt_prd; u8 rx_maxburst = dwc->rx_max_burst_prd; u8 tx_thr_num = dwc->tx_thr_num_pkt_prd; @@ -1378,10 +1374,9 @@ static void dwc3_get_properties(struct dwc3 *dwc) /* check whether the core supports IMOD */ bool dwc3_has_imod(struct dwc3 *dwc) { - return ((dwc3_is_usb3(dwc) && - dwc->revision >= DWC3_REVISION_300A) || - (dwc3_is_usb31(dwc) && - dwc->revision >= DWC3_USB31_REVISION_120A)); + return DWC3_VER_IS_WITHIN(DWC3, 300A, ANY) || + DWC3_VER_IS_WITHIN(DWC31, 120A, ANY) || + DWC3_IP_IS(DWC32); } static void dwc3_check_params(struct dwc3 *dwc) @@ -1402,7 +1397,7 @@ static void dwc3_check_params(struct dwc3 *dwc) * affected version. */ if (!dwc->imod_interval && - (dwc->revision == DWC3_REVISION_300A)) + DWC3_VER_IS(DWC3, 300A)) dwc->imod_interval = 1; /* Check the maximum_speed parameter */ @@ -1424,7 +1419,7 @@ static void dwc3_check_params(struct dwc3 *dwc) /* * default to superspeed plus if we are capable. */ - if (dwc3_is_usb31(dwc) && + if ((DWC3_IP_IS(DWC31) || DWC3_IP_IS(DWC32)) && (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == DWC3_GHWPARAMS3_SSPHY_IFC_GEN2)) dwc->maximum_speed = USB_SPEED_SUPER_PLUS; |