diff mbox series

[v6,04/13] usb: dwc3: Add splitdisable quirk for Hisilicon Kirin Soc

Message ID 20190420064019.57522-5-chenyu56@huawei.com (mailing list archive)
State New, archived
Headers show
Series Add support for usb on Hikey960 | expand

Commit Message

Chen Yu April 20, 2019, 6:40 a.m. UTC
SPLIT_BOUNDARY_DISABLE should be set for DesignWare USB3 DRD Core
of Hisilicon Kirin Soc when dwc3 core act as host.

Cc: Andy Shevchenko <andy.shevchenko@gmail.com>
Cc: Felipe Balbi <balbi@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Binghui Wang <wangbinghui@hisilicon.com>
Signed-off-by: Yu Chen <chenyu56@huawei.com>
---
v4:
* Add dwc3_complete definition while CONFIG_PM_SLEEP does not defined.
* Add description for 'dis_split_quirk'.
---
---
 drivers/usb/dwc3/core.c | 26 ++++++++++++++++++++++++++
 drivers/usb/dwc3/core.h |  7 +++++++
 2 files changed, 33 insertions(+)

Comments

Mauro Carvalho Chehab Sept. 7, 2020, 1:06 p.m. UTC | #1
Hi Felipe/Greg,

What's the status of this patch? 

I tested here, together with the Hikey 970 phy RFC patches I sent
last week.

Without this patch, the USB HID driver receives -EPROTO from
submitted URBs, causing it to enter into an endless reset cycle
on every 500 ms, at the hid_io_error() logic.

Tested-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>

If you prefer, I can re-submit this one with my SOB.

Thanks,
Mauro

Em Sat, 20 Apr 2019 14:40:10 +0800
Yu Chen <chenyu56@huawei.com> escreveu:

> SPLIT_BOUNDARY_DISABLE should be set for DesignWare USB3 DRD Core
> of Hisilicon Kirin Soc when dwc3 core act as host.
> 
> Cc: Andy Shevchenko <andy.shevchenko@gmail.com>
> Cc: Felipe Balbi <balbi@kernel.org>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: John Stultz <john.stultz@linaro.org>
> Cc: Binghui Wang <wangbinghui@hisilicon.com>
> Signed-off-by: Yu Chen <chenyu56@huawei.com>
> ---
> v4:
> * Add dwc3_complete definition while CONFIG_PM_SLEEP does not defined.
> * Add description for 'dis_split_quirk'.
> ---
> ---
>  drivers/usb/dwc3/core.c | 26 ++++++++++++++++++++++++++
>  drivers/usb/dwc3/core.h |  7 +++++++
>  2 files changed, 33 insertions(+)
> 
> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> index a1b126f90261..c3ef6bd2b0d4 100644
> --- a/drivers/usb/dwc3/core.c
> +++ b/drivers/usb/dwc3/core.c
> @@ -117,6 +117,7 @@ static void __dwc3_set_mode(struct work_struct *work)
>  	struct dwc3 *dwc = work_to_dwc(work);
>  	unsigned long flags;
>  	int ret;
> +	u32 reg;
>  
>  	if (dwc->dr_mode != USB_DR_MODE_OTG)
>  		return;
> @@ -169,6 +170,11 @@ static void __dwc3_set_mode(struct work_struct *work)
>  			phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST);
>  			phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST);
>  			phy_calibrate(dwc->usb2_generic_phy);
> +			if (dwc->dis_split_quirk) {
> +				reg = dwc3_readl(dwc->regs, DWC3_GUCTL3);
> +				reg |= DWC3_GUCTL3_SPLITDISABLE;
> +				dwc3_writel(dwc->regs, DWC3_GUCTL3, reg);
> +			}
>  		}
>  		break;
>  	case DWC3_GCTL_PRTCAP_DEVICE:
> @@ -1306,6 +1312,9 @@ static void dwc3_get_properties(struct dwc3 *dwc)
>  	dwc->dis_metastability_quirk = device_property_read_bool(dev,
>  				"snps,dis_metastability_quirk");
>  
> +	dwc->dis_split_quirk = device_property_read_bool(dev,
> +				"snps,dis-split-quirk");
> +
>  	dwc->lpm_nyet_threshold = lpm_nyet_threshold;
>  	dwc->tx_de_emphasis = tx_de_emphasis;
>  
> @@ -1825,10 +1834,27 @@ static int dwc3_resume(struct device *dev)
>  
>  	return 0;
>  }
> +
> +static void dwc3_complete(struct device *dev)
> +{
> +	struct dwc3	*dwc = dev_get_drvdata(dev);
> +	u32		reg;
> +
> +	if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST &&
> +			dwc->dis_split_quirk) {
> +		dev_dbg(dwc->dev, "set DWC3_GUCTL3_SPLITDISABLE\n");
> +		reg = dwc3_readl(dwc->regs, DWC3_GUCTL3);
> +		reg |= DWC3_GUCTL3_SPLITDISABLE;
> +		dwc3_writel(dwc->regs, DWC3_GUCTL3, reg);
> +	}
> +}
> +#else
> +#define dwc3_complete NULL
>  #endif /* CONFIG_PM_SLEEP */
>  
>  static const struct dev_pm_ops dwc3_dev_pm_ops = {
>  	SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume)
> +	.complete = dwc3_complete,
>  	SET_RUNTIME_PM_OPS(dwc3_runtime_suspend, dwc3_runtime_resume,
>  			dwc3_runtime_idle)
>  };
> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> index 1528d395b156..28475e301ad9 100644
> --- a/drivers/usb/dwc3/core.h
> +++ b/drivers/usb/dwc3/core.h
> @@ -136,6 +136,7 @@
>  #define DWC3_GEVNTCOUNT(n)	(0xc40c + ((n) * 0x10))
>  
>  #define DWC3_GHWPARAMS8		0xc600
> +#define DWC3_GUCTL3		0xc60c
>  #define DWC3_GFLADJ		0xc630
>  
>  /* Device Registers */
> @@ -370,6 +371,9 @@
>  /* Global User Control Register 2 */
>  #define DWC3_GUCTL2_RST_ACTBITLATER		BIT(14)
>  
> +/* Global User Control Register 3 */
> +#define DWC3_GUCTL3_SPLITDISABLE		BIT(14)
> +
>  /* Device Configuration Register */
>  #define DWC3_DCFG_DEVADDR(addr)	((addr) << 3)
>  #define DWC3_DCFG_DEVADDR_MASK	DWC3_DCFG_DEVADDR(0x7f)
> @@ -1030,6 +1034,7 @@ struct dwc3_scratchpad_array {
>   * 	2	- No de-emphasis
>   * 	3	- Reserved
>   * @dis_metastability_quirk: set to disable metastability quirk.
> + * @dis_split_quirk: set to disable split boundary.
>   * @imod_interval: set the interrupt moderation interval in 250ns
>   *                 increments or 0 to disable.
>   */
> @@ -1216,6 +1221,8 @@ struct dwc3 {
>  
>  	unsigned		dis_metastability_quirk:1;
>  
> +	unsigned		dis_split_quirk:1;
> +
>  	u16			imod_interval;
>  };
>  



Thanks,
Mauro
Felipe Balbi Sept. 7, 2020, 2:04 p.m. UTC | #2
Hi Mauro,

Mauro Carvalho Chehab <mchehab+huawei@kernel.org> writes:

> Hi Felipe/Greg,
>
> What's the status of this patch? 

to be frank, I don't think I have this in my inbox anymore.

> I tested here, together with the Hikey 970 phy RFC patches I sent
> last week.
>
> Without this patch, the USB HID driver receives -EPROTO from
> submitted URBs, causing it to enter into an endless reset cycle
> on every 500 ms, at the hid_io_error() logic.

> Tested-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
>
> If you prefer, I can re-submit this one with my SOB.

Please do, but since you're changing device tree, I need Rob's acked-by.

> Thanks,
> Mauro
>
> Em Sat, 20 Apr 2019 14:40:10 +0800
> Yu Chen <chenyu56@huawei.com> escreveu:
>
>> SPLIT_BOUNDARY_DISABLE should be set for DesignWare USB3 DRD Core
>> of Hisilicon Kirin Soc when dwc3 core act as host.

is this Kirin-specific or is this something that we should do a revision
check? Why does it affect only Hikey kirin? What's the dwc3 revision on
that SoC (grep SNPSID /sys/kernel/debugfs/*dwc3/regdump)?

>> @@ -1825,10 +1834,27 @@ static int dwc3_resume(struct device *dev)
>>  
>>  	return 0;
>>  }
>> +
>> +static void dwc3_complete(struct device *dev)
>> +{
>> +	struct dwc3	*dwc = dev_get_drvdata(dev);
>> +	u32		reg;
>> +
>> +	if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST &&
>> +			dwc->dis_split_quirk) {
>> +		dev_dbg(dwc->dev, "set DWC3_GUCTL3_SPLITDISABLE\n");

no more dev_dbg() should be added. This driver relies exclusively on
tracepoints for debugging.

>> +		reg = dwc3_readl(dwc->regs, DWC3_GUCTL3);
>> +		reg |= DWC3_GUCTL3_SPLITDISABLE;
>> +		dwc3_writel(dwc->regs, DWC3_GUCTL3, reg);
>> +	}
>> +}
>> +#else
>> +#define dwc3_complete NULL
>>  #endif /* CONFIG_PM_SLEEP */
>>  
>>  static const struct dev_pm_ops dwc3_dev_pm_ops = {
>>  	SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume)
>> +	.complete = dwc3_complete,

why is this done on complete? Why can't it be done at the end of
dwc3_resume()?
Mauro Carvalho Chehab Sept. 7, 2020, 2:50 p.m. UTC | #3
Em Mon, 07 Sep 2020 17:04:31 +0300
Felipe Balbi <balbi@kernel.org> escreveu:

> Hi Mauro,
> 
> Mauro Carvalho Chehab <mchehab+huawei@kernel.org> writes:
> 
> > Hi Felipe/Greg,
> >
> > What's the status of this patch?   
> 
> to be frank, I don't think I have this in my inbox anymore.
> 
> > I tested here, together with the Hikey 970 phy RFC patches I sent
> > last week.
> >
> > Without this patch, the USB HID driver receives -EPROTO from
> > submitted URBs, causing it to enter into an endless reset cycle
> > on every 500 ms, at the hid_io_error() logic.  
> 
> > Tested-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
> >
> > If you prefer, I can re-submit this one with my SOB.  
> 
> Please do, but since you're changing device tree, I need Rob's acked-by.

Ok, I'll do that.

> > Thanks,
> > Mauro
> >
> > Em Sat, 20 Apr 2019 14:40:10 +0800
> > Yu Chen <chenyu56@huawei.com> escreveu:
> >  
> >> SPLIT_BOUNDARY_DISABLE should be set for DesignWare USB3 DRD Core
> >> of Hisilicon Kirin Soc when dwc3 core act as host.  
> 
> is this Kirin-specific or is this something that we should do a revision
> check? 

I've no idea. I don't have any datasheets from this device.

> Why does it affect only Hikey kirin? 

As John Stultz didn't re-submit this one (and looking at the DT
between Kirin 960 and 970 from the original Kernel 4.9 official
drivers), I suspect that only Kirin 970 requires this quirk.

It could well be due to some Dwc3 revision, but it could also be due
to some differences at the USB part of the SoC, as there are a
few other things different between hikey 960 and 970: it has a
different PHY driver, and there are also some differences at the
USB HUB which is connected into it.

On both devices, the USB physical ports are actually connected
into a HUB. In the case of Hikey 970, the hub seems to be a
TI TUSB8041 4-Port Hub:
	
	$ lsusb
	Bus 002 Device 002: ID 0451:8140 Texas Instruments, Inc. TUSB8041 4-Port Hub
	Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
	Bus 001 Device 004: ID 090c:1000 Silicon Motion, Inc. - Taiwan (formerly Feiya Technology Corp.) Flash Drive
	Bus 001 Device 003: ID 413c:301a Dell Computer Corp. Dell MS116 Optical Mouse
	Bus 001 Device 002: ID 0451:8142 Texas Instruments, Inc. TUSB8041 4-Port Hub
	Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

> What's the dwc3 revision on
> that SoC (grep SNPSID /sys/kernel/debugfs/*dwc3/regdump)?

	GSNPSID = 0x33313130

> 
> >> @@ -1825,10 +1834,27 @@ static int dwc3_resume(struct device *dev)
> >>  
> >>  	return 0;
> >>  }
> >> +
> >> +static void dwc3_complete(struct device *dev)
> >> +{
> >> +	struct dwc3	*dwc = dev_get_drvdata(dev);
> >> +	u32		reg;
> >> +
> >> +	if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST &&
> >> +			dwc->dis_split_quirk) {
> >> +		dev_dbg(dwc->dev, "set DWC3_GUCTL3_SPLITDISABLE\n");  
> 
> no more dev_dbg() should be added. This driver relies exclusively on
> tracepoints for debugging.

Ok. 

> 
> >> +		reg = dwc3_readl(dwc->regs, DWC3_GUCTL3);
> >> +		reg |= DWC3_GUCTL3_SPLITDISABLE;
> >> +		dwc3_writel(dwc->regs, DWC3_GUCTL3, reg);
> >> +	}
> >> +}
> >> +#else
> >> +#define dwc3_complete NULL
> >>  #endif /* CONFIG_PM_SLEEP */
> >>  
> >>  static const struct dev_pm_ops dwc3_dev_pm_ops = {
> >>  	SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume)
> >> +	.complete = dwc3_complete,  
> 
> why is this done on complete? Why can't it be done at the end of
> dwc3_resume()?

Again, no idea. I didn't actually tried to suspend/resume.

Maybe the original author can shed a light on it.

Thanks,
Mauro
Felipe Balbi Sept. 8, 2020, 6:09 a.m. UTC | #4
Hi,

Mauro Carvalho Chehab <mchehab+huawei@kernel.org> writes:
>> > I tested here, together with the Hikey 970 phy RFC patches I sent
>> > last week.
>> >
>> > Without this patch, the USB HID driver receives -EPROTO from
>> > submitted URBs, causing it to enter into an endless reset cycle
>> > on every 500 ms, at the hid_io_error() logic.  
>> 
>> > Tested-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
>> >
>> > If you prefer, I can re-submit this one with my SOB.  
>> 
>> Please do, but since you're changing device tree, I need Rob's acked-by.
>
> Ok, I'll do that.

thanks

>> > Em Sat, 20 Apr 2019 14:40:10 +0800
>> > Yu Chen <chenyu56@huawei.com> escreveu:
>> >  
>> >> SPLIT_BOUNDARY_DISABLE should be set for DesignWare USB3 DRD Core
>> >> of Hisilicon Kirin Soc when dwc3 core act as host.  
>> 
>> is this Kirin-specific or is this something that we should do a revision
>> check? 
>
> I've no idea. I don't have any datasheets from this device.

I see

>> Why does it affect only Hikey kirin? 
>
> As John Stultz didn't re-submit this one (and looking at the DT
> between Kirin 960 and 970 from the original Kernel 4.9 official
> drivers), I suspect that only Kirin 970 requires this quirk.
>
> It could well be due to some Dwc3 revision, but it could also be due
> to some differences at the USB part of the SoC, as there are a

the reason I ask is that if it's caused by dwc3 revision, then we don't
need the extra dt property, we can rely on a revision check. If it's
something that can't be detected in runtime, then we need a property.

> few other things different between hikey 960 and 970: it has a
> different PHY driver, and there are also some differences at the
> USB HUB which is connected into it.
>
> On both devices, the USB physical ports are actually connected
> into a HUB. In the case of Hikey 970, the hub seems to be a
> TI TUSB8041 4-Port Hub:
> 	
> 	$ lsusb
> 	Bus 002 Device 002: ID 0451:8140 Texas Instruments, Inc. TUSB8041 4-Port Hub
> 	Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
> 	Bus 001 Device 004: ID 090c:1000 Silicon Motion, Inc. - Taiwan (formerly Feiya Technology Corp.) Flash Drive
> 	Bus 001 Device 003: ID 413c:301a Dell Computer Corp. Dell MS116 Optical Mouse
> 	Bus 001 Device 002: ID 0451:8142 Texas Instruments, Inc. TUSB8041 4-Port Hub
> 	Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
>
>> What's the dwc3 revision on
>> that SoC (grep SNPSID /sys/kernel/debugfs/*dwc3/regdump)?
>
> 	GSNPSID = 0x33313130

This isn't even listed as a known revision in dwc3/core.h. Thinh, could
the issue being described here caused by a known Erratum with this
particular revision?

>> >> +		reg = dwc3_readl(dwc->regs, DWC3_GUCTL3);
>> >> +		reg |= DWC3_GUCTL3_SPLITDISABLE;
>> >> +		dwc3_writel(dwc->regs, DWC3_GUCTL3, reg);
>> >> +	}
>> >> +}
>> >> +#else
>> >> +#define dwc3_complete NULL
>> >>  #endif /* CONFIG_PM_SLEEP */
>> >>  
>> >>  static const struct dev_pm_ops dwc3_dev_pm_ops = {
>> >>  	SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume)
>> >> +	.complete = dwc3_complete,  
>> 
>> why is this done on complete? Why can't it be done at the end of
>> dwc3_resume()?
>
> Again, no idea. I didn't actually tried to suspend/resume.
>
> Maybe the original author can shed a light on it.

yeah, would be nice :-)
Mauro Carvalho Chehab Sept. 8, 2020, 6:42 a.m. UTC | #5
Em Mon, 07 Sep 2020 17:04:31 +0300
Felipe Balbi <balbi@kernel.org> escreveu:

> >>  static const struct dev_pm_ops dwc3_dev_pm_ops = {
> >>  	SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume)
> >> +	.complete = dwc3_complete,  
> 
> why is this done on complete? Why can't it be done at the end of
> dwc3_resume()?

Updating my answer:

No. I just tested moving the code from .complete to the end of
.resume. After moving it, the HID won't be able to properly enable
the device at resume time (logs filtered to show only relevant msgs):

	# echo reboot > /sys/power/disk; echo disk > /sys/power/state

	...
	[   29.051314] Freezing user space processes ... (elapsed 0.001 seconds) done.
	[   29.059811] OOM killer disabled.
	[   30.171526] PM: hibernation: Creating image:
	[   30.171526] PM: hibernation: Need to copy 164192 pages
	[   30.171526] PM: hibernation: Image created (164192 pages copied)
	[   30.171644] Enabling non-boot CPUs ...
	[   30.293953] dwc3 ff100000.dwc3: dwc3_resume
	[   30.424549] usb usb1-port1: status 0101 change 0001
	[   30.428538] usb usb2-port1: status 0203 change 0001
	[   30.536609] usb 1-1: Waited 0ms for CONNECT
	[   30.543822] usb 1-1: finish reset-resume
	[   30.544619] usb 2-1: Waited 0ms for CONNECT
	[   30.558869] usb 2-1: finish reset-resume
	[   30.676706] usb 1-1: reset high-speed USB device number 2 using xhci-hcd
	[   30.882194] hub 1-1:1.0: hub_reset_resume
	[   30.888479] hub 1-1:1.0: enabling power on all ports
	[   30.960767] usb 2-1: reset SuperSpeed Gen 1 USB device number 2 using xhci-hcd
	[   30.994229] hub 2-1:1.0: hub_reset_resume
	[   31.000574] usb 1-1-port1: status 0301 change 0001
	[   31.002088] hub 2-1:1.0: enabling power on all ports
	[   31.009079] usb 1-1-port2: status 0101 change 0001
	[   31.132633] usb 1-1.2: Waited 0ms for CONNECT
	[   31.132665] usb 1-1.1: Waited 0ms for CONNECT
	[   31.140560] usb 1-1.2: finish reset-resume
	[   31.148509] usb 1-1.1: finish reset-resume
	[   31.240760] usb 1-1.2: reset high-speed USB device number 4 using xhci-hcd
	[   32.471492] dwc3 ff100000.dwc3: dwc3_complete
	[   32.480512] PM: Cannot find swap device, try swapon -a
	[   32.489532] PM: Cannot get swap writer
	[   32.575790] Restarting tasks ... 
	[   32.575891] hub 1-0:1.0: state 7 ports 1 chg 0000 evt 0000
	[   32.575894] hub 2-0:1.0: state 7 ports 1 chg 0000 evt 0000
	[   32.575896] hub 1-1:1.0: state 7 ports 4 chg 0000 evt 0002
	[   32.576570] hub 2-1:1.0: state 7 ports 4 chg 0000 evt 0000
	[   32.576876] done.
	[   32.600094] hub 2-1:1.0: hub_suspend
	[   32.642090] PM: hibernation: hibernation exit
	[   32.650255] usb 2-1: usb auto-suspend, wakeup 1
	[   32.668581] hub 2-0:1.0: hub_suspend
	[   33.122384] hub 1-1:1.0: state 7 ports 4 chg 0000 evt 0002
	[   33.378220] usb 1-1.1: reset low-speed USB device number 3 using xhci-hcd
	[   33.698394] hub 1-1:1.0: state 7 ports 4 chg 0000 evt 0000
	[   34.882365] hub 1-1:1.0: state 7 ports 4 chg 0000 evt 0002
	[   35.138217] usb 1-1.1: reset low-speed USB device number 3 using xhci-hcd
	[   35.458617] hub 1-1:1.0: state 7 ports 4 chg 0000 evt 0000
	[   36.642392] hub 1-1:1.0: state 7 ports 4 chg 0000 evt 0002
	[   36.898207] usb 1-1.1: reset low-speed USB device number 3 using xhci-hcd
	[   37.218598] hub 1-1:1.0: state 7 ports 4 chg 0000 evt 0000
	[   37.672658] kirin9xx-drm e8600000.dpe: [drm:dss_disable_vblank [kirin9xx_drm]] dss_disable_vblank
	[   38.402368] hub 1-1:1.0: state 7 ports 4 chg 0000 evt 0002
	[   38.658174] usb 1-1.1: reset low-speed USB device number 3 using xhci-hcd
	[   38.978594] hub 1-1:1.0: state 7 ports 4 chg 0000 evt 0000
	[   40.162361] hub 1-1:1.0: state 7 ports 4 chg 0000 evt 0002
	[   40.418148] usb 1-1.1: reset low-speed USB device number 3 using xhci-hcd
	...
	[  397.698132] usb 1-1.1: reset low-speed USB device number 3 using xhci-hcd
	[  398.018565] hub 1-1:1.0: state 7 ports 4 chg 0000 evt 0000

Basically, after resume, the code behaves just like the quirk were
not applied.

Explaining with more details, without the splitdisable quirk, what
happens is that the USB URBs return -EPROTO errors, causing
hid-core.c to call hid_io_error(). This function starts a reset
work (usbhid->reset_work), which ends calling (at hid_reset()):

	usb_queue_reset_device(usbhid->intf);

This happens on every HZ/2 intervals, causing an endless reset
loop.

Thanks,
Mauro
Mauro Carvalho Chehab Sept. 8, 2020, 6:49 a.m. UTC | #6
Em Tue, 08 Sep 2020 09:09:46 +0300
Felipe Balbi <balbi@kernel.org> escreveu:

> >> Why does it affect only Hikey kirin?   
> >
> > As John Stultz didn't re-submit this one (and looking at the DT
> > between Kirin 960 and 970 from the original Kernel 4.9 official
> > drivers), I suspect that only Kirin 970 requires this quirk.
> >
> > It could well be due to some Dwc3 revision, but it could also be due
> > to some differences at the USB part of the SoC, as there are a  
> 
> the reason I ask is that if it's caused by dwc3 revision, then we don't
> need the extra dt property, we can rely on a revision check. If it's
> something that can't be detected in runtime, then we need a property.

Yeah, if it would be possible to auto-detect, that would be
better. Yet, hard to say if it would be possible to do that, 
without access to the Dwc3 docs, and without different hardware 
for testing it.

> > few other things different between hikey 960 and 970: it has a
> > different PHY driver, and there are also some differences at the
> > USB HUB which is connected into it.
> >
> > On both devices, the USB physical ports are actually connected
> > into a HUB. In the case of Hikey 970, the hub seems to be a
> > TI TUSB8041 4-Port Hub:
> > 	
> > 	$ lsusb
> > 	Bus 002 Device 002: ID 0451:8140 Texas Instruments, Inc. TUSB8041 4-Port Hub
> > 	Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
> > 	Bus 001 Device 004: ID 090c:1000 Silicon Motion, Inc. - Taiwan (formerly Feiya Technology Corp.) Flash Drive
> > 	Bus 001 Device 003: ID 413c:301a Dell Computer Corp. Dell MS116 Optical Mouse
> > 	Bus 001 Device 002: ID 0451:8142 Texas Instruments, Inc. TUSB8041 4-Port Hub
> > 	Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
> >  
> >> What's the dwc3 revision on
> >> that SoC (grep SNPSID /sys/kernel/debugfs/*dwc3/regdump)?  
> >
> > 	GSNPSID = 0x33313130  
> 
> This isn't even listed as a known revision in dwc3/core.h. Thinh, could
> the issue being described here caused by a known Erratum with this
> particular revision?

Maybe. Again, hard to tell without any documentation from Synopsys.

Maybe some of the Synopsys folks at USB MK can shed a light.

Thanks,
Mauro
Thinh Nguyen Sept. 8, 2020, 5:40 p.m. UTC | #7
Felipe Balbi wrote:
> Hi,
>
> Mauro Carvalho Chehab <mchehab+huawei@kernel.org> writes:
>>>> I tested here, together with the Hikey 970 phy RFC patches I sent
>>>> last week.
>>>>
>>>> Without this patch, the USB HID driver receives -EPROTO from
>>>> submitted URBs, causing it to enter into an endless reset cycle
>>>> on every 500 ms, at the hid_io_error() logic.  
>>>> Tested-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
>>>>
>>>> If you prefer, I can re-submit this one with my SOB.  
>>> Please do, but since you're changing device tree, I need Rob's acked-by.
>> Ok, I'll do that.
> thanks
>
>>>> Em Sat, 20 Apr 2019 14:40:10 +0800
>>>> Yu Chen <chenyu56@huawei.com> escreveu:
>>>>  
>>>>> SPLIT_BOUNDARY_DISABLE should be set for DesignWare USB3 DRD Core
>>>>> of Hisilicon Kirin Soc when dwc3 core act as host.  
>>> is this Kirin-specific or is this something that we should do a revision
>>> check? 
>> I've no idea. I don't have any datasheets from this device.
> I see
>
>>> Why does it affect only Hikey kirin? 
>> As John Stultz didn't re-submit this one (and looking at the DT
>> between Kirin 960 and 970 from the original Kernel 4.9 official
>> drivers), I suspect that only Kirin 970 requires this quirk.
>>
>> It could well be due to some Dwc3 revision, but it could also be due
>> to some differences at the USB part of the SoC, as there are a
> the reason I ask is that if it's caused by dwc3 revision, then we don't
> need the extra dt property, we can rely on a revision check. If it's
> something that can't be detected in runtime, then we need a property.
>
>> few other things different between hikey 960 and 970: it has a
>> different PHY driver, and there are also some differences at the
>> USB HUB which is connected into it.
>>
>> On both devices, the USB physical ports are actually connected
>> into a HUB. In the case of Hikey 970, the hub seems to be a
>> TI TUSB8041 4-Port Hub:
>> 	
>> 	$ lsusb
>> 	Bus 002 Device 002: ID 0451:8140 Texas Instruments, Inc. TUSB8041 4-Port Hub
>> 	Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
>> 	Bus 001 Device 004: ID 090c:1000 Silicon Motion, Inc. - Taiwan (formerly Feiya Technology Corp.) Flash Drive
>> 	Bus 001 Device 003: ID 413c:301a Dell Computer Corp. Dell MS116 Optical Mouse
>> 	Bus 001 Device 002: ID 0451:8142 Texas Instruments, Inc. TUSB8041 4-Port Hub
>> 	Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
>>
>>> What's the dwc3 revision on
>>> that SoC (grep SNPSID /sys/kernel/debugfs/*dwc3/regdump)?
>> 	GSNPSID = 0x33313130
> This isn't even listed as a known revision in dwc3/core.h. Thinh, could
> the issue being described here caused by a known Erratum with this
> particular revision?

If you have a STAR issue number, then I may be able to look it up.

Btw, GNSPSID register is the ID for DWC_usb31 IP. For DWC_usb31 and
DWC_usb32, we need to read the version number and version type registers
(offset 0xc1a0 and 0xc1a4 respectively).

We need to add these registers to the register dump.

BR,
Thinh

>
>>>>> +		reg = dwc3_readl(dwc->regs, DWC3_GUCTL3);
>>>>> +		reg |= DWC3_GUCTL3_SPLITDISABLE;
>>>>> +		dwc3_writel(dwc->regs, DWC3_GUCTL3, reg);
>>>>> +	}
>>>>> +}
>>>>> +#else
>>>>> +#define dwc3_complete NULL
>>>>>  #endif /* CONFIG_PM_SLEEP */
>>>>>  
>>>>>  static const struct dev_pm_ops dwc3_dev_pm_ops = {
>>>>>  	SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume)
>>>>> +	.complete = dwc3_complete,  
>>> why is this done on complete? Why can't it be done at the end of
>>> dwc3_resume()?
>> Again, no idea. I didn't actually tried to suspend/resume.
>>
>> Maybe the original author can shed a light on it.
> yeah, would be nice :-)
>
diff mbox series

Patch

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index a1b126f90261..c3ef6bd2b0d4 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -117,6 +117,7 @@  static void __dwc3_set_mode(struct work_struct *work)
 	struct dwc3 *dwc = work_to_dwc(work);
 	unsigned long flags;
 	int ret;
+	u32 reg;
 
 	if (dwc->dr_mode != USB_DR_MODE_OTG)
 		return;
@@ -169,6 +170,11 @@  static void __dwc3_set_mode(struct work_struct *work)
 			phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST);
 			phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST);
 			phy_calibrate(dwc->usb2_generic_phy);
+			if (dwc->dis_split_quirk) {
+				reg = dwc3_readl(dwc->regs, DWC3_GUCTL3);
+				reg |= DWC3_GUCTL3_SPLITDISABLE;
+				dwc3_writel(dwc->regs, DWC3_GUCTL3, reg);
+			}
 		}
 		break;
 	case DWC3_GCTL_PRTCAP_DEVICE:
@@ -1306,6 +1312,9 @@  static void dwc3_get_properties(struct dwc3 *dwc)
 	dwc->dis_metastability_quirk = device_property_read_bool(dev,
 				"snps,dis_metastability_quirk");
 
+	dwc->dis_split_quirk = device_property_read_bool(dev,
+				"snps,dis-split-quirk");
+
 	dwc->lpm_nyet_threshold = lpm_nyet_threshold;
 	dwc->tx_de_emphasis = tx_de_emphasis;
 
@@ -1825,10 +1834,27 @@  static int dwc3_resume(struct device *dev)
 
 	return 0;
 }
+
+static void dwc3_complete(struct device *dev)
+{
+	struct dwc3	*dwc = dev_get_drvdata(dev);
+	u32		reg;
+
+	if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST &&
+			dwc->dis_split_quirk) {
+		dev_dbg(dwc->dev, "set DWC3_GUCTL3_SPLITDISABLE\n");
+		reg = dwc3_readl(dwc->regs, DWC3_GUCTL3);
+		reg |= DWC3_GUCTL3_SPLITDISABLE;
+		dwc3_writel(dwc->regs, DWC3_GUCTL3, reg);
+	}
+}
+#else
+#define dwc3_complete NULL
 #endif /* CONFIG_PM_SLEEP */
 
 static const struct dev_pm_ops dwc3_dev_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume)
+	.complete = dwc3_complete,
 	SET_RUNTIME_PM_OPS(dwc3_runtime_suspend, dwc3_runtime_resume,
 			dwc3_runtime_idle)
 };
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 1528d395b156..28475e301ad9 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -136,6 +136,7 @@ 
 #define DWC3_GEVNTCOUNT(n)	(0xc40c + ((n) * 0x10))
 
 #define DWC3_GHWPARAMS8		0xc600
+#define DWC3_GUCTL3		0xc60c
 #define DWC3_GFLADJ		0xc630
 
 /* Device Registers */
@@ -370,6 +371,9 @@ 
 /* Global User Control Register 2 */
 #define DWC3_GUCTL2_RST_ACTBITLATER		BIT(14)
 
+/* Global User Control Register 3 */
+#define DWC3_GUCTL3_SPLITDISABLE		BIT(14)
+
 /* Device Configuration Register */
 #define DWC3_DCFG_DEVADDR(addr)	((addr) << 3)
 #define DWC3_DCFG_DEVADDR_MASK	DWC3_DCFG_DEVADDR(0x7f)
@@ -1030,6 +1034,7 @@  struct dwc3_scratchpad_array {
  * 	2	- No de-emphasis
  * 	3	- Reserved
  * @dis_metastability_quirk: set to disable metastability quirk.
+ * @dis_split_quirk: set to disable split boundary.
  * @imod_interval: set the interrupt moderation interval in 250ns
  *                 increments or 0 to disable.
  */
@@ -1216,6 +1221,8 @@  struct dwc3 {
 
 	unsigned		dis_metastability_quirk:1;
 
+	unsigned		dis_split_quirk:1;
+
 	u16			imod_interval;
 };