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: Manu Gautam <mgautam@codeaurora.org>
Signed-off-by: Mayank Rana <mrana@codeaurora.org>
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 6ee10df..37c6d3d 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -200,6 +200,8 @@
 	struct clk              *clk;
 	int			ret;
 	int			irq;
+	u32			temp, imod;
+	unsigned long		flags;
 
 	if (usb_disabled())
 		return -ENODEV;
@@ -308,6 +310,9 @@
 	if (device_property_read_bool(sysdev, "usb3-lpm-capable"))
 		xhci->quirks |= XHCI_LPM_SUPPORT;
 
+	if (device_property_read_u32(sysdev, "snps,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);
@@ -331,6 +336,18 @@
 	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",