Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9bb95a8d authored by Huang Rui's avatar Huang Rui Committed by Jack Pham
Browse files

usb: dwc3: add lpm erratum support



When parameter DWC_USB3_LPM_ERRATA_ENABLE is enabled in Andvanced
Configuration of coreConsultant, it supports of xHCI BESL Errata Dated
10/19/2011 is enabled in host mode. In device mode it adds the capability
to send NYET response threshold based on the BESL value received in the LPM
token, and the threhold is configurable for each soc platform.

This patch adds an entry that soc platform is able to define the lpm
capacity with their own device tree or bus glue layer.

[ balbi@ti.com : added devicetree documentation, spelled threshold
		completely, made sure threshold is only applied to
		proper core revisions. ]

Signed-off-by: default avatarHuang Rui <ray.huang@amd.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
Change-Id: Ifb8a1f0dfd4c6bf24776867eea52166a00245a59
Git-commit: 80caf7d21adca10c4621d511f6eb01f7ed2b342c
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git


[jackp@codeaurora.org: fixed up trivial merge conflicts]
Signed-off-by: default avatarJack Pham <jackp@codeaurora.org>
parent 37bc52a5
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@ Optional properties:
	If BESL value received from the host in the LPM token is less than this value we send LPM ACK to
	the host. Otherwise the device returns LPM NYET.
 - snps,disable-clk-gating: If present, disable controller's internal clock gating. Default it is enabled.
 - snps,has-lpm-erratum: true when DWC3 was configured with LPM Erratum enabled
 - snps,lpm-nyet-threshold: LPM NYET threshold

This is usually a subnode to DWC3 glue to which it is connected.

+15 −1
Original line number Diff line number Diff line
@@ -785,6 +785,7 @@ static int dwc3_probe(struct platform_device *pdev)
	struct device_node	*node = dev->of_node;
	struct resource		*res;
	struct dwc3		*dwc;
	u8			lpm_nyet_threshold;

	int			ret;

@@ -844,10 +845,18 @@ static int dwc3_probe(struct platform_device *pdev)
	 */
	res->start -= DWC3_GLOBALS_REGS_START;

	/* default to highest possible threshold */
	lpm_nyet_threshold = 0xff;

	if (node) {
		dwc->maximum_speed = of_usb_get_maximum_speed(node);
		dwc->has_lpm_erratum = of_property_read_bool(node,
				"snps,has-lpm-erratum");
		of_property_read_u8(node, "snps,lpm-nyet-threshold",
				&lpm_nyet_threshold);

		dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
		dwc->needs_fifo_resize = of_property_read_bool(node,
				"tx-fifo-resize");
		dwc->dr_mode = of_usb_get_dr_mode(node);
		dwc->nominal_elastic_buffer = of_property_read_bool(node,
				"snps,nominal-elastic-buffer");
@@ -874,6 +883,9 @@ static int dwc3_probe(struct platform_device *pdev)
		}
	} else if (pdata) {
		dwc->maximum_speed = pdata->maximum_speed;
		dwc->has_lpm_erratum = pdata->has_lpm_erratum;
		if (pdata->lpm_nyet_threshold)
			lpm_nyet_threshold = pdata->lpm_nyet_threshold;

		dwc->needs_fifo_resize = pdata->tx_fifo_resize;
		dwc->dr_mode = pdata->dr_mode;
@@ -883,6 +895,8 @@ static int dwc3_probe(struct platform_device *pdev)
	if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
		dwc->maximum_speed = USB_SPEED_SUPER;

	dwc->lpm_nyet_threshold = lpm_nyet_threshold;

	ret = dwc3_core_get_phy(dwc);
	if (ret)
		return ret;
+17 −9
Original line number Diff line number Diff line
@@ -280,6 +280,9 @@
#define DWC3_DCTL_TRGTULST_SS_INACT	(DWC3_DCTL_TRGTULST(6))

/* These apply for core versions 1.94a and later */
#define DWC3_DCTL_LPM_ERRATA_MASK	DWC3_DCTL_LPM_ERRATA(0xf)
#define DWC3_DCTL_LPM_ERRATA(n)		((n) << 20)

#define DWC3_DCTL_KEEP_CONNECT		(1 << 19)
#define DWC3_DCTL_L1_HIBER_EN		(1 << 18)
#define DWC3_DCTL_CRS			(1 << 17)
@@ -781,10 +784,13 @@ struct dwc3_scratchpad_array {
 * @regset: debugfs pointer to regdump file
 * @test_mode: true when we're entering a USB test mode
 * @test_mode_nr: test feature selector
 * @lpm_nyet_threshold: LPM NYET response threshold
 * @delayed_status: true when gadget driver asks for delayed status
 * @ep0_bounced: true when we used bounce buffer
 * @ep0_expect_in: true when we expect a DATA IN transfer
 * @has_hibernation: true when dwc3 was configured with Hibernation
 * @has_lpm_erratum: true when core was configured with LPM Erratum. Note that
 *			there's now way for software to detect this in runtime.
 * @is_selfpowered: true when we are selfpowered
 * @needs_fifo_resize: not all users might want fifo resizing, flag it
 * @pullups_connected: true when Run/Stop bit is set
@@ -899,6 +905,7 @@ struct dwc3 {

	u8			test_mode;
	u8			test_mode_nr;
	u8			lpm_nyet_threshold;

	void (*notify_event)	(struct dwc3 *, unsigned);
	struct work_struct	wakeup_work;
@@ -907,6 +914,7 @@ struct dwc3 {
	unsigned		ep0_bounced:1;
	unsigned		ep0_expect_in:1;
	unsigned		has_hibernation:1;
	unsigned		has_lpm_erratum:1;
	unsigned		is_selfpowered:1;
	unsigned		needs_fifo_resize:1;
	unsigned		pullups_connected:1;
+14 −0
Original line number Diff line number Diff line
@@ -2979,6 +2979,20 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
			reg &= ~DWC3_DCTL_LPM_NYET_THRES_MASK;
			reg |= DWC3_DCTL_LPM_NYET_THRES(dwc->lpm_nyet_thresh);
		}

		/*
		 * When dwc3 revisions >= 2.40a, LPM Erratum is enabled and
		 * DCFG.LPMCap is set, core responses with an ACK and the
		 * BESL value in the LPM token is less than or equal to LPM
		 * NYET threshold.
		 */
		WARN_ONCE(dwc->revision < DWC3_REVISION_240A
				&& dwc->has_lpm_erratum,
				"LPM Erratum not available on dwc3 revisisions < 2.40a\n");

		if (dwc->has_lpm_erratum && dwc->revision >= DWC3_REVISION_240A)
			reg |= DWC3_DCTL_LPM_ERRATA(dwc->lpm_nyet_threshold);

		dwc3_writel(dwc->regs, DWC3_DCTL, reg);
	} else {
		reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+4 −0
Original line number Diff line number Diff line
@@ -24,4 +24,8 @@ struct dwc3_platform_data {
	enum usb_device_speed maximum_speed;
	enum usb_dr_mode dr_mode;
	bool tx_fifo_resize;

	u8 lpm_nyet_threshold;

	unsigned has_lpm_erratum:1;
};