Hi Bin, Marek, Any comment for this serial? Thanks in advance.
Regards, Ran On Wednesday, October 21, 2020 6:02 PM, Ran Wang wrote: > > Register Global frame length adjustment is used to do frame length adjustment > for SOF/ITP counter which is running on the ref_clk. Allow updating it could > help > on avoiding potential USB 2.0 devices time-out over a longer run. > > Refer to Linux commit db2be4e9e30c (“usb: dwc3: Add frame length > adjustment quirk”) > > Signed-off-by: Ran Wang <ran.wan...@nxp.com> > --- > Change in v2: > - None > > drivers/usb/dwc3/core.c | 34 ++++++++++++++++++++++++++++++++++ > drivers/usb/dwc3/core.h | 7 +++++++ > 2 files changed, 41 insertions(+) > > diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index > 2e00353..b3d4751 100644 > --- a/drivers/usb/dwc3/core.c > +++ b/drivers/usb/dwc3/core.c > @@ -310,6 +310,25 @@ static void dwc3_free_scratch_buffers(struct dwc3 > *dwc) > kfree(dwc->scratchbuf); > } > > +/* > + * dwc3_frame_length_adjustment - Adjusts frame length if required > + * @dwc3: Pointer to our controller context structure > + * @val: Value of frame length > + */ > +static void dwc3_frame_length_adjustment(struct dwc3 *dwc, u32 val) { > + u32 reg; > + u32 dft; > + > + reg = dwc3_readl(dwc->regs, DWC3_GFLADJ); > + dft = reg & DWC3_GFLADJ_30MHZ_MASK; > + if (dft != val) { > + reg &= ~DWC3_GFLADJ_30MHZ_MASK; > + reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | val; > + dwc3_writel(dwc->regs, DWC3_GFLADJ, reg); > + } > +} > + > static void dwc3_core_num_eps(struct dwc3 *dwc) { > struct dwc3_hwparams *parms = &dwc->hwparams; > @@ -569,6 +588,9 @@ static int dwc3_core_init(struct dwc3 *dwc) > if (ret) > goto err1; > > + if (dwc->fladj_quirk && dwc->revision >= DWC3_REVISION_250A) > + dwc3_frame_length_adjustment(dwc, dwc->fladj); > + > return 0; > > err1: > @@ -958,6 +980,18 @@ void dwc3_of_parse(struct dwc3 *dwc) > > dwc->hird_threshold = hird_threshold > | (dwc->is_utmi_l1_suspend << 4); > + > + dwc->fladj_quirk = false; > + if (!dev_read_u32(dev, > + "snps,quirk-frame-length-adjustment", > + &dwc->fladj)) { > + if (dwc->fladj <= DWC3_GFLADJ_30MHZ_MASK) > + dwc->fladj_quirk = true; > + else > + dev_err(dev, > + "snps,quirk-frame-length-adjustment invalid: > 0x%x\n", > + dwc->fladj); > + } > } > > int dwc3_init(struct dwc3 *dwc) > diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index > 44533fd..4650216 100644 > --- a/drivers/usb/dwc3/core.h > +++ b/drivers/usb/dwc3/core.h > @@ -115,6 +115,7 @@ > #define DWC3_GEVNTCOUNT(n) (0xc40c + (n * 0x10)) > > #define DWC3_GHWPARAMS8 0xc600 > +#define DWC3_GFLADJ 0xc630 > > /* Device Registers */ > #define DWC3_DCFG 0xc700 > @@ -291,6 +292,10 @@ > #define DWC3_DCTL_ULSTCHNG_COMPLIANCE > (DWC3_DCTL_ULSTCHNGREQ(10)) > #define DWC3_DCTL_ULSTCHNG_LOOPBACK > (DWC3_DCTL_ULSTCHNGREQ(11)) > > +/* Global Frame Length Adjustment Register */ > +#define DWC3_GFLADJ_30MHZ_SDBND_SEL BIT(7) > +#define DWC3_GFLADJ_30MHZ_MASK 0x3f > + > /* Device Event Enable Register */ > #define DWC3_DEVTEN_VNDRDEVTSTRCVEDEN (1 << 12) > #define DWC3_DEVTEN_EVNTOVERFLOWEN (1 << 11) > @@ -764,6 +769,7 @@ struct dwc3 { > u32 num_event_buffers; > u32 u1u2; > u32 maximum_speed; > + u32 fladj; > u32 revision; > > #define DWC3_REVISION_173A 0x5533173a > @@ -845,6 +851,7 @@ struct dwc3 { > > unsigned tx_de_emphasis_quirk:1; > unsigned tx_de_emphasis:2; > + unsigned fladj_quirk:1; > int index; > struct list_head list; > }; > -- > 2.7.4