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

Commit c77da935 authored by Mayank Rana's avatar Mayank Rana Committed by Jack Pham
Browse files

usb: xhci-plat: Add DT parameter to program xhci imod_interval



XHCI allows interrupt moderation using imod_interval at 250ns
increments. Add DT parameter to specify this imod_value for
targets mainly with single CPU to reduce CPU interrupt loads.
This allows better balance between CPU usage and performance.

CRs-fixed: 1019219
Change-Id: Id479c162da6492caff4dd83de4054fee63b6abc5
Signed-off-by: default avatarManu Gautam <mgautam@codeaurora.org>
Signed-off-by: default avatarMayank Rana <mrana@codeaurora.org>
[jackp@codeaurora.org: squashed with usb: host: Fix passing of
xhci-imod-value property to xhci-plat]
Signed-off-by: default avatarJack Pham <jackp@codeaurora.org>
parent 47741cf2
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -55,6 +55,8 @@ Optional properties:
 - snps,quirk-frame-length-adjustment: Value for GFLADJ_30MHZ field of GFLADJ
	register for post-silicon frame length adjustment when the
	fladj_30mhz_sdbnd signal is invalid or incorrect.
 - snps,xhci-imod-value: Interrupt moderation interval for host mode
	(in increments of 250nsec).

 - <DEPRECATED> tx-fifo-resize: determines if the FIFO *has* to be reallocated.

@@ -69,4 +71,5 @@ dwc3@4a030000 {
	reg = <0x4a030000 0xcfff>;
	interrupts = <0 92 4>
	usb-phy = <&usb2_phy>, <&usb3,phy>;
	snps,xhci-imod-value = <4000>;
};
+4 −0
Original line number Diff line number Diff line
@@ -1032,6 +1032,10 @@ static void dwc3_get_properties(struct dwc3 *dwc)
				"snps,is-utmi-l1-suspend");
	device_property_read_u8(dev, "snps,hird-threshold",
				&hird_threshold);

	device_property_read_u32(dev, "snps,xhci-imod-value",
			&dwc->xhci_imod_value);

	dwc->usb3_lpm_capable = device_property_read_bool(dev,
				"snps,usb3_lpm_capable");

+2 −0
Original line number Diff line number Diff line
@@ -905,6 +905,7 @@ struct dwc3_scratchpad_array {
 *                 increments or 0 to disable.
 * @index: dwc3's instance number
 * @dwc_ipc_log_ctxt: dwc3 ipc log context
 * @xhci_imod_value: imod value to use with xhci
 */
struct dwc3 {
	struct work_struct	drd_work;
@@ -1061,6 +1062,7 @@ struct dwc3 {
	unsigned int		index;
	void			*dwc_ipc_log_ctxt;
	struct dwc3_gadget_events	dbg_gadget_events;
	u32			xhci_imod_value;
};

#define work_to_dwc(w)		(container_of((w), struct dwc3, drd_work))
+12 −1
Original line number Diff line number Diff line
@@ -52,14 +52,16 @@ static int dwc3_host_get_irq(struct dwc3 *dwc)
	return irq;
}

#define NUMBER_OF_PROPS	4
int dwc3_host_init(struct dwc3 *dwc)
{
	struct property_entry	props[3];
	struct property_entry	props[NUMBER_OF_PROPS];
	struct platform_device	*xhci;
	int			ret, irq;
	struct resource		*res;
	struct platform_device	*dwc3_pdev = to_platform_device(dwc->dev);
	int			prop_idx = 0;
	struct property_entry	imod_prop;

	irq = dwc3_host_get_irq(dwc);
	if (irq < 0)
@@ -101,6 +103,15 @@ int dwc3_host_init(struct dwc3 *dwc)
	if (dwc->usb3_lpm_capable)
		props[prop_idx++].name = "usb3-lpm-capable";

	if (dwc->xhci_imod_value) {
		imod_prop.name  = "xhci-imod-value";
		imod_prop.length  = sizeof(u32);
		imod_prop.is_string = false;
		imod_prop.is_array = false;
		imod_prop.value.u32_data = dwc->xhci_imod_value;
		props[prop_idx++] = imod_prop;
	}

	/**
	 * WORKAROUND: dwc3 revisions <=3.00a have a limitation
	 * where Port Disable command doesn't work.
+17 −0
Original line number Diff line number Diff line
@@ -214,6 +214,8 @@ static int xhci_plat_probe(struct platform_device *pdev)
	struct clk              *clk;
	int			ret;
	int			irq;
	u32			temp, imod;
	unsigned long		flags;

	if (usb_disabled())
		return -ENODEV;
@@ -322,6 +324,9 @@ static int xhci_plat_probe(struct platform_device *pdev)
	if (device_property_read_bool(&pdev->dev, "quirk-broken-port-ped"))
		xhci->quirks |= XHCI_BROKEN_PORT_PED;

	if (device_property_read_u32(&pdev->dev, "xhci-imod-value", &imod))
		imod = 0;

	hcd->usb_phy = devm_usb_get_phy_by_phandle(sysdev, "usb-phy", 0);
	if (IS_ERR(hcd->usb_phy)) {
		ret = PTR_ERR(hcd->usb_phy);
@@ -345,6 +350,18 @@ static int xhci_plat_probe(struct platform_device *pdev)
	if (ret)
		goto dealloc_usb2_hcd;

	/* override imod interval if specified */
	if (imod) {
		imod &= ER_IRQ_INTERVAL_MASK;
		spin_lock_irqsave(&xhci->lock, flags);
		temp = readl_relaxed(&xhci->ir_set->irq_control);
		temp &= ~ER_IRQ_INTERVAL_MASK;
		temp |= imod;
		writel_relaxed(temp, &xhci->ir_set->irq_control);
		spin_unlock_irqrestore(&xhci->lock, flags);
		dev_dbg(&pdev->dev, "%s: imod set to %u\n", __func__, imod);
	}

	ret = device_create_file(&pdev->dev, &dev_attr_config_imod);
	if (ret)
		dev_err(&pdev->dev, "%s: unable to create imod sysfs entry\n",