Skip to content

Commit

Permalink
usb: dwc3: gadget: Add support for disabling U1 and U2 entries
Browse files Browse the repository at this point in the history
Gadget applications may have a requirement to disable the U1 and U2
entry based on the usecase. Below are few usecases where the disabling
U1/U2 entries may be possible.

Usecase 1:
When combining dwc3 with an redriver for a USB Type-C device solution, it
sometimes have problems with leaving U1/U2 for certain hosts, resulting in
link training errors and reconnects. For this U1/U2 state entries may be
avoided.

Usecase 2:
When performing performance benchmarking on mass storage gadget the
U1 and U2 entries can be disabled.

Usecase 3:
When periodic transfers like ISOC transfers are used with bInterval
of 1 which doesn't require the link to enter into U1 or U2 state entry
(since ping is issued from host for every uframe interval). In this
case the U1 and U2 entry can be disabled.

Disablement of U1/U2 can be done by setting U1DevExitLat and U2DevExitLat
values to 0 in the BOS descriptor. Host on seeing 0 value for U1DevExitLat
and U2DevExitLat, it doesn't send SET_SEL requests to the gadget. There
may be some hosts which may send SET_SEL requests even after seeing 0 in
the UxDevExitLat of BOS descriptor. To aviod U1/U2 entries for these type
of hosts, dwc3 controller can be programmed to reject those U1/U2 requests
by not enabling ACCEPTUxENA bits in DCTL register.

This patch updates the same.

Signed-off-by: Anurag Kumar Vulisha <anurag.kumar.vulisha@xilinx.com>
Signed-off-by: Claus H. Stovgaard <cst@phaseone.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
  • Loading branch information
Anurag Kumar Vulisha authored and radheyxilinx committed Jul 8, 2019
1 parent 801ea4b commit 65313f1
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 1 deletion.
4 changes: 4 additions & 0 deletions drivers/usb/dwc3/core.c
Expand Up @@ -1410,6 +1410,10 @@ static void dwc3_get_properties(struct dwc3 *dwc)
"snps,dis_u2_susphy_quirk");
dwc->dis_enblslpm_quirk = device_property_read_bool(dev,
"snps,dis_enblslpm_quirk");
dwc->dis_u1_entry_quirk = device_property_read_bool(dev,
"snps,dis-u1-entry-quirk");
dwc->dis_u2_entry_quirk = device_property_read_bool(dev,
"snps,dis-u2-entry-quirk");
dwc->dis_rxdet_inp3_quirk = device_property_read_bool(dev,
"snps,dis_rxdet_inp3_quirk");
dwc->dis_u2_freeclk_exists_quirk = device_property_read_bool(dev,
Expand Down
4 changes: 4 additions & 0 deletions drivers/usb/dwc3/core.h
Expand Up @@ -1011,6 +1011,8 @@ struct dwc3_scratchpad_array {
* @dis_u2_susphy_quirk: set if we disable usb2 suspend phy
* @dis_enblslpm_quirk: set if we clear enblslpm in GUSB2PHYCFG,
* disabling the suspend signal to the PHY.
* @dis_u1_entry_quirk: set if link entering into U1 state needs to be disabled.
* @dis_u2_entry_quirk: set if link entering into U2 state needs to be disabled.
* @dis_rxdet_inp3_quirk: set if we disable Rx.Detect in P3
* @dis_u2_freeclk_exists_quirk : set if we clear u2_freeclk_exists
* in GUSB2PHYCFG, specify that USB2 PHY doesn't
Expand Down Expand Up @@ -1201,6 +1203,8 @@ struct dwc3 {
unsigned dis_u3_susphy_quirk:1;
unsigned dis_u2_susphy_quirk:1;
unsigned dis_enblslpm_quirk:1;
unsigned dis_u1_entry_quirk:1;
unsigned dis_u2_entry_quirk:1;
unsigned dis_rxdet_inp3_quirk:1;
unsigned dis_u2_freeclk_exists_quirk:1;
unsigned dis_del_phy_power_chg_quirk:1;
Expand Down
9 changes: 8 additions & 1 deletion drivers/usb/dwc3/ep0.c
Expand Up @@ -384,6 +384,8 @@ static int dwc3_ep0_handle_u1(struct dwc3 *dwc, enum usb_device_state state,
if ((dwc->speed != DWC3_DSTS_SUPERSPEED) &&
(dwc->speed != DWC3_DSTS_SUPERSPEED_PLUS))
return -EINVAL;
if (set && dwc->dis_u1_entry_quirk)
return -EINVAL;

reg = dwc3_readl(dwc->regs, DWC3_DCTL);
if (set)
Expand All @@ -406,6 +408,8 @@ static int dwc3_ep0_handle_u2(struct dwc3 *dwc, enum usb_device_state state,
if ((dwc->speed != DWC3_DSTS_SUPERSPEED) &&
(dwc->speed != DWC3_DSTS_SUPERSPEED_PLUS))
return -EINVAL;
if (set && dwc->dis_u2_entry_quirk)
return -EINVAL;

reg = dwc3_readl(dwc->regs, DWC3_DCTL);
if (set)
Expand Down Expand Up @@ -664,7 +668,10 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
* nothing is pending from application.
*/
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
reg |= (DWC3_DCTL_ACCEPTU1ENA | DWC3_DCTL_ACCEPTU2ENA);
if (!dwc->dis_u1_entry_quirk)
reg |= DWC3_DCTL_ACCEPTU1ENA;
if (!dwc->dis_u2_entry_quirk)
reg |= DWC3_DCTL_ACCEPTU2ENA;
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
}
break;
Expand Down
20 changes: 20 additions & 0 deletions drivers/usb/dwc3/gadget.c
Expand Up @@ -2073,6 +2073,25 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
return 0;
}

static void dwc3_gadget_config_params(struct usb_gadget *g,
struct usb_dcd_config_params *params)
{
struct dwc3 *dwc = gadget_to_dwc(g);

/* U1 Device exit Latency */
if (dwc->dis_u1_entry_quirk)
params->bU1devExitLat = 0;
else
params->bU1devExitLat = DWC3_DEFAULT_U1_DEV_EXIT_LAT;

/* U2 Device exit Latency */
if (dwc->dis_u2_entry_quirk)
params->bU2DevExitLat = 0;
else
params->bU2DevExitLat =
cpu_to_le16(DWC3_DEFAULT_U2_DEV_EXIT_LAT);
}

static void dwc3_gadget_set_speed(struct usb_gadget *g,
enum usb_device_speed speed)
{
Expand Down Expand Up @@ -2142,6 +2161,7 @@ static const struct usb_gadget_ops dwc3_gadget_ops = {
.udc_start = dwc3_gadget_start,
.udc_stop = dwc3_gadget_stop,
.udc_set_speed = dwc3_gadget_set_speed,
.get_config_params = dwc3_gadget_config_params,
};

/* -------------------------------------------------------------------------- */
Expand Down
6 changes: 6 additions & 0 deletions drivers/usb/dwc3/gadget.h
Expand Up @@ -56,6 +56,12 @@ struct dwc3;
#define DWC3_NON_STICKY_SAVE_DELAY 100
#define DWC3_DEVICE_CTRL_READY_DELAY 5

/* U1 Device exit Latency */
#define DWC3_DEFAULT_U1_DEV_EXIT_LAT 0x0A /* Less then 10 microsec */

/* U2 Device exit Latency */
#define DWC3_DEFAULT_U2_DEV_EXIT_LAT 0x1FF /* Less then 511 microsec */

/* -------------------------------------------------------------------------- */

#define to_dwc3_request(r) (container_of(r, struct dwc3_request, request))
Expand Down

0 comments on commit 65313f1

Please sign in to comment.