| From 48c4d3e94ccc93e9f060794186a0fba0f540113e Mon Sep 17 00:00:00 2001 |
| From: Adam Wallis <awallis@codeaurora.org> |
| Date: Fri, 8 Dec 2017 17:59:13 +0200 |
| Subject: [PATCH 0530/1795] usb: xhci: allow imod-interval to be configurable |
| |
| The xHCI driver currently has the IMOD set to 160, which |
| translates to an IMOD interval of 40,000ns (160 * 250)ns |
| |
| Commit 0cbd4b34cda9 ("xhci: mediatek: support MTK xHCI host controller") |
| introduced a QUIRK for the MTK platform to adjust this interval to 20, |
| which translates to an IMOD interval of 5,000ns (20 * 250)ns. This is |
| due to the fact that the MTK controller IMOD interval is 8 times |
| as much as defined in xHCI spec. |
| |
| Instead of adding more quirk bits for additional platforms, this patch |
| introduces the ability for vendors to set the IMOD_INTERVAL as is |
| optimal for their platform. By using device_property_read_u32() on |
| "imod-interval-ns", the IMOD INTERVAL can be specified in nano seconds. |
| If no interval is specified, the default of 40,000ns (IMOD=160) will be |
| used. |
| |
| No bounds checking has been implemented due to the fact that a vendor |
| may have violated the spec and would need to specify a value outside of |
| the max 8,000 IRQs/second limit specified in the xHCI spec. |
| |
| Tested-by: Chunfeng Yun <chunfeng.yun@mediatek.com> |
| Reviewed-by: Rob Herring <robh@kernel.org> |
| Signed-off-by: Adam Wallis <awallis@codeaurora.org> |
| Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| (cherry picked from commit ab725cbec3e83dc29cc00b733bd26063b588fa98) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> |
| --- |
| .../devicetree/bindings/usb/mediatek,mtk-xhci.txt | 2 ++ |
| Documentation/devicetree/bindings/usb/usb-xhci.txt | 1 + |
| drivers/usb/host/xhci-mtk.c | 9 +++++++++ |
| drivers/usb/host/xhci-pci.c | 3 +++ |
| drivers/usb/host/xhci-plat.c | 5 +++++ |
| drivers/usb/host/xhci.c | 6 +----- |
| drivers/usb/host/xhci.h | 2 ++ |
| 7 files changed, 23 insertions(+), 5 deletions(-) |
| |
| diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt |
| index 5611a2e4ddf0..c008e8d9aa99 100644 |
| --- a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt |
| +++ b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt |
| @@ -43,6 +43,7 @@ Optional properties: |
| - pinctrl-names : a pinctrl state named "default" must be defined |
| - pinctrl-0 : pin control group |
| See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt |
| + - imod-interval-ns: default interrupt moderation interval is 5000ns |
| |
| Example: |
| usb30: usb@11270000 { |
| @@ -65,6 +66,7 @@ usb30: usb@11270000 { |
| usb3-lpm-capable; |
| mediatek,syscon-wakeup = <&pericfg>; |
| mediatek,wakeup-src = <1>; |
| + imod-interval-ns = <10000>; |
| }; |
| |
| 2nd: dual-role mode with xHCI driver |
| diff --git a/Documentation/devicetree/bindings/usb/usb-xhci.txt b/Documentation/devicetree/bindings/usb/usb-xhci.txt |
| index ff4747219638..1651483a7048 100644 |
| --- a/Documentation/devicetree/bindings/usb/usb-xhci.txt |
| +++ b/Documentation/devicetree/bindings/usb/usb-xhci.txt |
| @@ -32,6 +32,7 @@ Optional properties: |
| - usb2-lpm-disable: indicate if we don't want to enable USB2 HW LPM |
| - usb3-lpm-capable: determines if platform is USB3 LPM capable |
| - quirk-broken-port-ped: set if the controller has broken port disable mechanism |
| + - imod-interval-ns: default interrupt moderation interval is 5000ns |
| |
| Example: |
| usb@f0931000 { |
| diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c |
| index 95f583f41bfd..c9eb0fc18f4d 100644 |
| --- a/drivers/usb/host/xhci-mtk.c |
| +++ b/drivers/usb/host/xhci-mtk.c |
| @@ -661,6 +661,15 @@ static int xhci_mtk_probe(struct platform_device *pdev) |
| |
| xhci = hcd_to_xhci(hcd); |
| xhci->main_hcd = hcd; |
| + |
| + /* |
| + * imod_interval is the interrupt moderation value in nanoseconds. |
| + * The increment interval is 8 times as much as that defined in |
| + * the xHCI spec on MTK's controller. |
| + */ |
| + xhci->imod_interval = 5000; |
| + device_property_read_u32(dev, "imod-interval-ns", &xhci->imod_interval); |
| + |
| xhci->shared_hcd = usb_create_shared_hcd(driver, dev, |
| dev_name(dev), hcd); |
| if (!xhci->shared_hcd) { |
| diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c |
| index c3ae5784649a..93ce34bce7b5 100644 |
| --- a/drivers/usb/host/xhci-pci.c |
| +++ b/drivers/usb/host/xhci-pci.c |
| @@ -254,6 +254,9 @@ static int xhci_pci_setup(struct usb_hcd *hcd) |
| if (!xhci->sbrn) |
| pci_read_config_byte(pdev, XHCI_SBRN_OFFSET, &xhci->sbrn); |
| |
| + /* imod_interval is the interrupt moderation value in nanoseconds. */ |
| + xhci->imod_interval = 40000; |
| + |
| retval = xhci_gen_setup(hcd, xhci_pci_quirks); |
| if (retval) |
| return retval; |
| diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c |
| index 833ca511fd35..c435df29cdb8 100644 |
| --- a/drivers/usb/host/xhci-plat.c |
| +++ b/drivers/usb/host/xhci-plat.c |
| @@ -269,6 +269,11 @@ 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; |
| |
| + /* imod_interval is the interrupt moderation value in nanoseconds. */ |
| + xhci->imod_interval = 40000; |
| + device_property_read_u32(sysdev, "imod-interval-ns", |
| + &xhci->imod_interval); |
| + |
| 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); |
| diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c |
| index 786cca0eb73c..34bc8a678bd5 100644 |
| --- a/drivers/usb/host/xhci.c |
| +++ b/drivers/usb/host/xhci.c |
| @@ -583,11 +583,7 @@ int xhci_run(struct usb_hcd *hcd) |
| "// Set the interrupt modulation register"); |
| temp = readl(&xhci->ir_set->irq_control); |
| temp &= ~ER_IRQ_INTERVAL_MASK; |
| - /* |
| - * the increment interval is 8 times as much as that defined |
| - * in xHCI spec on MTK's controller |
| - */ |
| - temp |= (u32) ((xhci->quirks & XHCI_MTK_HOST) ? 20 : 160); |
| + temp |= (xhci->imod_interval / 250) & ER_IRQ_INTERVAL_MASK; |
| writel(temp, &xhci->ir_set->irq_control); |
| |
| /* Set the HCD state before we enable the irqs */ |
| diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h |
| index 68f314e49d07..2961d1020981 100644 |
| --- a/drivers/usb/host/xhci.h |
| +++ b/drivers/usb/host/xhci.h |
| @@ -1722,6 +1722,8 @@ struct xhci_hcd { |
| u8 max_interrupters; |
| u8 max_ports; |
| u8 isoc_threshold; |
| + /* imod_interval in ns (I * 250ns) */ |
| + u32 imod_interval; |
| int event_ring_max; |
| /* 4KB min, 128MB max */ |
| int page_size; |
| -- |
| 2.19.0 |
| |