On Wed, Oct 21, 2020 at 6:17 PM Thinh Nguyen <Thinh.Nguyen@xxxxxxxxxxxx> wrote: > > John Stultz wrote: > > From: Yu Chen <chenyu56@xxxxxxxxxx> > > > > With the current dwc3 code on the HiKey960 we often see the > > COREIDLE flag get stuck off in __dwc3_gadget_start(), which > > seems to prevent the reset irq and causes the USB gadget to > > fail to initialize. > > > > We had seen occasional initialization failures with older > > kernels but with recent 5.x era kernels it seemed to be becoming > > much more common, so I dug back through some older trees and > > realized I dropped this quirk from Yu Chen during upstreaming > > as I couldn't provide a proper rational for it and it didn't > > seem to be necessary. I now realize I was wrong. > > > > After resubmitting the quirk Thinh Nguyen pointed out that it > > shouldn't be a quirk and it is actually mentioned in the > > programming guide that it should be done when switching modes > > in DRD. > > > > So, to avoid these !COREIDLE lockups seen on HiKey960, this > > patch issues GCTL soft reset when switching modes if the > > controller is in DRD mode. > > > > Cc: Felipe Balbi <balbi@xxxxxxxxxx> > > Cc: Tejas Joglekar <tejas.joglekar@xxxxxxxxxxxx> > > Cc: Yang Fei <fei.yang@xxxxxxxxx> > > Cc: YongQin Liu <yongqin.liu@xxxxxxxxxx> > > Cc: Andrzej Pietrasiewicz <andrzej.p@xxxxxxxxxxxxx> > > Cc: Thinh Nguyen <thinhn@xxxxxxxxxxxx> > > Cc: Jun Li <lijun.kernel@xxxxxxxxx> > > Cc: Mauro Carvalho Chehab <mchehab+huawei@xxxxxxxxxx> > > Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> > > Cc: linux-usb@xxxxxxxxxxxxxxx > > Signed-off-by: Yu Chen <chenyu56@xxxxxxxxxx> > > Signed-off-by: John Stultz <john.stultz@xxxxxxxxxx> > > --- > > v2: > > * Rework to always call the GCTL soft reset in DRD mode, > > rather then using a quirk as suggested by Thinh Nguyen > > > > --- > > drivers/usb/dwc3/core.c | 19 +++++++++++++++++++ > > 1 file changed, 19 insertions(+) > > > > diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c > > index bdf0925da6b6..ca94f3a2a83c 100644 > > --- a/drivers/usb/dwc3/core.c > > +++ b/drivers/usb/dwc3/core.c > > @@ -114,10 +114,24 @@ void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode) > > dwc->current_dr_role = mode; > > } > > > > +static void dwc3_gctl_core_soft_reset(struct dwc3 *dwc) > > +{ > > + int reg; > > + > > + reg = dwc3_readl(dwc->regs, DWC3_GCTL); > > + reg |= (DWC3_GCTL_CORESOFTRESET); > > + dwc3_writel(dwc->regs, DWC3_GCTL, reg); > > + > > + reg = dwc3_readl(dwc->regs, DWC3_GCTL); > > + reg &= ~(DWC3_GCTL_CORESOFTRESET); > > + dwc3_writel(dwc->regs, DWC3_GCTL, reg); > > +} > > + > > static void __dwc3_set_mode(struct work_struct *work) > > { > > struct dwc3 *dwc = work_to_dwc(work); > > unsigned long flags; > > + int hw_mode; > > int ret; > > u32 reg; > > > > @@ -154,6 +168,11 @@ static void __dwc3_set_mode(struct work_struct *work) > > break; > > } > > > > + /* Execute a GCTL Core Soft Reset when switch mode in DRD*/ > > + hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0); > > + if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD) > > + dwc3_gctl_core_soft_reset(dwc); > > + > > I think this should be done inside the spin_lock. > > > spin_lock_irqsave(&dwc->lock, flags); > > > > dwc3_set_prtcap(dwc, dwc->desired_dr_role); > > The DRD mode change sequence should be like this if we want to switch > from host -> device according to the programming guide (for all DRD IPs): > 1. Reset controller with GCTL.CoreSoftReset > 2. Set GCTL.PrtCapDir(device) > 3. Soft reset with DCTL.CSftRst > 4. Then follow up with the initializing registers sequence > > However, from code review, with this patch, it follows this sequence: > a. Soft reset with DCTL.CSftRst on driver probe > b. Reset controller with GCTL.CoreSoftReset > c. Set GCTL.PrtCapDir(device) > d. < missing DCTL.CSftRst > > e. Then follow up with initializing registers sequence > > It may work, but it doesn't follow the programming guide. Much appreciated for the guidance here. I don't believe I have access to the programming guide (unless its publicly available somewhere?), so I'm just working with what I can experimentally figure out and vendor patch history. So I'll try to translate the above into the driver as best I can, but again, I really appreciate your review and corrections here! thanks -john