usb: dwc3: gadget: Don't send unintended link state change
DCTL.ULSTCHNGREQ is a write-only field. When doing a read-modify-write to DCTL, the driver must make sure that there's no unintended link state change request from whatever is read from DCTL.ULSTCHNGREQ. Set link state change to no-action when the driver writes to DCTL. Signed-off-by: Thinh Nguyen <thinhn@synopsys.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
704a940d55
commit
5b738211fb
|
@ -57,7 +57,7 @@ int dwc3_gadget_set_test_mode(struct dwc3 *dwc, int mode)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
|
dwc3_gadget_dctl_write_safe(dwc, reg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1828,7 +1828,7 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend)
|
||||||
dwc->pullups_connected = false;
|
dwc->pullups_connected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
|
dwc3_gadget_dctl_write_safe(dwc, reg);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
reg = dwc3_readl(dwc->regs, DWC3_DSTS);
|
reg = dwc3_readl(dwc->regs, DWC3_DSTS);
|
||||||
|
@ -2761,10 +2761,8 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc)
|
||||||
|
|
||||||
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
|
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
|
||||||
reg &= ~DWC3_DCTL_INITU1ENA;
|
reg &= ~DWC3_DCTL_INITU1ENA;
|
||||||
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
|
|
||||||
|
|
||||||
reg &= ~DWC3_DCTL_INITU2ENA;
|
reg &= ~DWC3_DCTL_INITU2ENA;
|
||||||
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
|
dwc3_gadget_dctl_write_safe(dwc, reg);
|
||||||
|
|
||||||
dwc3_disconnect_gadget(dwc);
|
dwc3_disconnect_gadget(dwc);
|
||||||
|
|
||||||
|
@ -2816,7 +2814,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
|
||||||
|
|
||||||
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
|
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
|
||||||
reg &= ~DWC3_DCTL_TSTCTRL_MASK;
|
reg &= ~DWC3_DCTL_TSTCTRL_MASK;
|
||||||
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
|
dwc3_gadget_dctl_write_safe(dwc, reg);
|
||||||
dwc->test_mode = false;
|
dwc->test_mode = false;
|
||||||
dwc3_clear_stall_all_ep(dwc);
|
dwc3_clear_stall_all_ep(dwc);
|
||||||
|
|
||||||
|
@ -2920,11 +2918,11 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
|
||||||
if (dwc->has_lpm_erratum && dwc->revision >= DWC3_REVISION_240A)
|
if (dwc->has_lpm_erratum && dwc->revision >= DWC3_REVISION_240A)
|
||||||
reg |= DWC3_DCTL_NYET_THRES(dwc->lpm_nyet_threshold);
|
reg |= DWC3_DCTL_NYET_THRES(dwc->lpm_nyet_threshold);
|
||||||
|
|
||||||
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
|
dwc3_gadget_dctl_write_safe(dwc, reg);
|
||||||
} else {
|
} else {
|
||||||
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
|
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
|
||||||
reg &= ~DWC3_DCTL_HIRD_THRES_MASK;
|
reg &= ~DWC3_DCTL_HIRD_THRES_MASK;
|
||||||
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
|
dwc3_gadget_dctl_write_safe(dwc, reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
dep = dwc->eps[0];
|
dep = dwc->eps[0];
|
||||||
|
@ -3033,7 +3031,7 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,
|
||||||
|
|
||||||
reg &= ~u1u2;
|
reg &= ~u1u2;
|
||||||
|
|
||||||
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
|
dwc3_gadget_dctl_write_safe(dwc, reg);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
|
|
|
@ -127,4 +127,18 @@ static inline void dwc3_gadget_ep_get_transfer_index(struct dwc3_ep *dep)
|
||||||
dep->resource_index = DWC3_DEPCMD_GET_RSC_IDX(res_id);
|
dep->resource_index = DWC3_DEPCMD_GET_RSC_IDX(res_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dwc3_gadget_dctl_write_safe - write to DCTL safe from link state change
|
||||||
|
* @dwc: pointer to our context structure
|
||||||
|
* @value: value to write to DCTL
|
||||||
|
*
|
||||||
|
* Use this function when doing read-modify-write to DCTL. It will not
|
||||||
|
* send link state change request.
|
||||||
|
*/
|
||||||
|
static inline void dwc3_gadget_dctl_write_safe(struct dwc3 *dwc, u32 value)
|
||||||
|
{
|
||||||
|
value &= ~DWC3_DCTL_ULSTCHNGREQ_MASK;
|
||||||
|
dwc3_writel(dwc->regs, DWC3_DCTL, value);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* __DRIVERS_USB_DWC3_GADGET_H */
|
#endif /* __DRIVERS_USB_DWC3_GADGET_H */
|
||||||
|
|
Loading…
Reference in New Issue