usb: gadget: Link state changes
Subsystems (2)
Thinh Nguyen
maintainerv2 cover usb: gadget: Link state changes
This patch series adds some fixes to how dwc3 handles cases related to link state changes.
Changes in v2:
- Create inline function to do safe write to DCTL
Thinh Nguyen (4):
usb: dwc3: gadget: Don't send unintended link state change
usb: dwc3: gadget: Set link state to RX_Detect on disconnect
usb: dwc3: gadget: Clear DCTL.ULSTCHNGREQ before set
usb: dwc3: debug: Remove newline printout
drivers/usb/dwc3/debug.h | 4 ++-- drivers/usb/dwc3/gadget.c | 21 ++++++++++++--------- drivers/usb/dwc3/gadget.h | 14 ++++++++++++++ 3 files changed, 28 insertions(+), 11 deletions(-)
Signature · 1 line
2.11.0
Thinh Nguyen
maintainerPATCH v2 1/4 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.
---
Changes in v2:
- Create inline function to do safe write to DCTL
drivers/usb/dwc3/gadget.c | 16 +++++++--------- drivers/usb/dwc3/gadget.h | 14 ++++++++++++++ 2 files changed, 21 insertions(+), 9 deletions(-)
drivers/usb/dwc3/gadget.c +7 -9
@@ -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 ; }
@@ -1822,7 +1822,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);
@@ -2745,10 +2745,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);
@@ -2800,7 +2798,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);
@@ -2904,11 +2902,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 ];
@@ -3017,7 +3015,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 */
drivers/usb/dwc3/gadget.h +14 -0
@@ -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 */
Signature · 1 line
2.11.0
Thinh Nguyen
maintainerPATCH v2 2/4 usb: dwc3: gadget: Set link state to RX_Detect on disconnect
In reply to Thinh NguyenWhen DWC3 receives disconnect event, it needs to set the link state to RX_Detect.
DWC_usb3 3.30a programming guide 4.1.7
--- drivers/usb/dwc3/gadget.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/usb/dwc3/gadget.c +2 -0
@@ -2743,6 +2743,8 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc) {int reg; +dwc3_gadget_set_link_state (dwc,DWC3_LINK_STATE_RX_DET ); + reg =dwc3_readl (dwc->regs,DWC3_DCTL ); reg &= ~DWC3_DCTL_INITU1ENA ; reg &= ~DWC3_DCTL_INITU2ENA ;
Signature · 1 line
2.11.0
Thinh Nguyen
maintainerPATCH v2 3/4 usb: dwc3: gadget: Clear DCTL.ULSTCHNGREQ before set
In reply to Thinh NguyenSend a no-action link state change request before the actual request so DWC3 can send the same request whenever we call dwc3_gadget_set_link_state().
--- drivers/usb/dwc3/gadget.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/usb/dwc3/gadget.c +3 -0
@@ -111,6 +111,9 @@ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state) reg =dwc3_readl (dwc->regs,DWC3_DCTL ); reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK ; +/* set no action before sending new link state change */ +dwc3_writel (dwc->regs,DWC3_DCTL , reg); +/* set requested state */ reg |=DWC3_DCTL_ULSTCHNGREQ (state);dwc3_writel (dwc->regs,DWC3_DCTL , reg);
Signature · 1 line
2.11.0
Thinh Nguyen
maintainerPATCH v2 4/4 usb: dwc3: debug: Remove newline printout
In reply to Thinh NguyenThe newline from the unknown link state tracepoint doesn't follow the other tracepoints, and it looks unsightly. Let's remove it.
--- drivers/usb/dwc3/debug.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/usb/dwc3/debug.h +2 -2
@@ -112,7 +112,7 @@ dwc3_gadget_link_string(enum dwc3_link_state link_state)case DWC3_LINK_STATE_RESUME :return "Resume" ;default : -return "UNKNOWN link state\n" ; +return "UNKNOWN link state" ; } }
@@ -141,7 +141,7 @@ dwc3_gadget_hs_link_string(enum dwc3_link_state link_state)case DWC3_LINK_STATE_RESUME :return "Resume" ;default : -return "UNKNOWN link state\n" ; +return "UNKNOWN link state" ; } }
Signature · 1 line
2.11.0