Commit 5b738211 authored by Thinh Nguyen's avatar Thinh Nguyen Committed by Greg Kroah-Hartman

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: default avatarThinh Nguyen <thinhn@synopsys.com>
Signed-off-by: default avatarFelipe Balbi <felipe.balbi@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 704a940d
......@@ -57,7 +57,7 @@ int dwc3_gadget_set_test_mode(struct dwc3 *dwc, int mode)
return -EINVAL;
}
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
dwc3_gadget_dctl_write_safe(dwc, reg);
return 0;
}
......@@ -1828,7 +1828,7 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend)
dwc->pullups_connected = false;
}
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
dwc3_gadget_dctl_write_safe(dwc, reg);
do {
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_DCTL_INITU1ENA;
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
reg &= ~DWC3_DCTL_INITU2ENA;
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
dwc3_gadget_dctl_write_safe(dwc, reg);
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_DCTL_TSTCTRL_MASK;
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
dwc3_gadget_dctl_write_safe(dwc, reg);
dwc->test_mode = false;
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)
reg |= DWC3_DCTL_NYET_THRES(dwc->lpm_nyet_threshold);
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
dwc3_gadget_dctl_write_safe(dwc, reg);
} else {
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
reg &= ~DWC3_DCTL_HIRD_THRES_MASK;
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
dwc3_gadget_dctl_write_safe(dwc, reg);
}
dep = dwc->eps[0];
......@@ -3033,7 +3031,7 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,
reg &= ~u1u2;
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
dwc3_gadget_dctl_write_safe(dwc, reg);
break;
default:
/* 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);
}
/**
* 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 */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment