usb: gadget: Allow non-default and non-zero ITC value
Allow setting ITC value provided from device tree. In case no value
provided from device tree, check the CI13XXX_ZERO_ITC flag, and
if set use the value of 0 as the ITC.
Change-Id: I9333124913b7ae737eabc8eb5d154d99ac184ee8
Signed-off-by: Amit Blay <ablay@codeaurora.org>
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index fbe2d25..e3a6721 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -135,6 +135,21 @@
qcom,usb2-power-budget = <500>;
};
+MSM HSUSB controller
+
+Required properties :
+- compatible : should be "qcom,ci13xxx_msm"
+
+Optional properties :
+- qcom,itc-level: value of 2^itc-level will be used for as the interrupt threshold
+ (ITC), when itc-level is between 0 to 6.
+
+Example MSM HSUSB controller device node :
+ msm_hsusb: qcom,ci13xxx_msm {
+ compatible = "qcom,ci13xxx_msm";
+ qcom,itc-level = <4>;
+};
+
ANDROID USB:
Required properties:
diff --git a/drivers/usb/gadget/ci13xxx_msm.c b/drivers/usb/gadget/ci13xxx_msm.c
index 3cad3ce..8d8c30e 100644
--- a/drivers/usb/gadget/ci13xxx_msm.c
+++ b/drivers/usb/gadget/ci13xxx_msm.c
@@ -16,6 +16,8 @@
#define MSM_USB_BASE (udc->regs)
+#define CI13XXX_MSM_MAX_ITC_LEVEL 6
+
struct ci13xxx_udc_context {
int irq;
void __iomem *regs;
@@ -177,7 +179,7 @@
CI13XXX_ZERO_ITC |
CI13XXX_DISABLE_STREAMING |
CI13XXX_IS_OTG,
-
+ .nz_itc = 0,
.notify_event = ci13xxx_msm_notify_event,
};
@@ -230,10 +232,21 @@
static int ci13xxx_msm_probe(struct platform_device *pdev)
{
struct resource *res;
- int ret;
+ int ret, rc;
+ int itc_level = 0;
dev_dbg(&pdev->dev, "ci13xxx_msm_probe\n");
+ if (pdev->dev.of_node) {
+ rc = of_property_read_u32(pdev->dev.of_node, "qcom,itc-level",
+ &itc_level);
+ /* Acceptable values for nz_itc are: 0,1,2,4,8,16,32,64 */
+ if (itc_level > CI13XXX_MSM_MAX_ITC_LEVEL || rc)
+ ci13xxx_msm_udc_driver.nz_itc = 0;
+ else
+ ci13xxx_msm_udc_driver.nz_itc = 1 << itc_level;
+ }
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "failed to get platform resource mem\n");
@@ -313,9 +326,18 @@
writel_relaxed(val, USB_GENCONFIG);
}
+static const struct of_device_id ci13xx_msm_dt_match[] = {
+ { .compatible = "qcom,ci13xxx_msm",
+ },
+ {}
+};
+
static struct platform_driver ci13xxx_msm_driver = {
.probe = ci13xxx_msm_probe,
- .driver = { .name = "msm_hsusb", },
+ .driver = {
+ .name = "msm_hsusb",
+ .of_match_table = ci13xx_msm_dt_match,
+ },
.remove = ci13xxx_msm_remove,
};
MODULE_ALIAS("platform:msm_hsusb");
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index a258c30..952fb6d 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -367,7 +367,10 @@
* 8 micro frames. If CPU can handle interrupts at faster rate, ITC
* can be set to lesser value to gain performance.
*/
- if (udc->udc_driver->flags & CI13XXX_ZERO_ITC)
+ if (udc->udc_driver->nz_itc)
+ hw_cwrite(CAP_USBCMD, USBCMD_ITC_MASK,
+ USBCMD_ITC(udc->udc_driver->nz_itc));
+ else if (udc->udc_driver->flags & CI13XXX_ZERO_ITC)
hw_cwrite(CAP_USBCMD, USBCMD_ITC_MASK, USBCMD_ITC(0));
if (hw_cread(CAP_USBMODE, USBMODE_CM) != USBMODE_CM_DEVICE) {
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h
index 1530474..53ff6f0 100644
--- a/drivers/usb/gadget/ci13xxx_udc.h
+++ b/drivers/usb/gadget/ci13xxx_udc.h
@@ -129,6 +129,7 @@
struct ci13xxx_udc_driver {
const char *name;
unsigned long flags;
+ unsigned int nz_itc;
#define CI13XXX_REGS_SHARED BIT(0)
#define CI13XXX_REQUIRE_TRANSCEIVER BIT(1)
#define CI13XXX_PULLUP_ON_VBUS BIT(2)