usb: gadget: Add HSIC peripheral support.
Add support in HSIC peripheral(device).
Only one USB core can be use - currently
HSUSB is enabled by default.
To enable HSIC core defconfig file should be changed.
Change-Id: I02413658e28f799de2a083db7847fb8b01d04eac
Signed-off-by: Ofir Cohen <ofirc@codeaurora.org>
diff --git a/arch/arm/mach-msm/board-9615-regulator.c b/arch/arm/mach-msm/board-9615-regulator.c
index 4859f18..95a1347 100644
--- a/arch/arm/mach-msm/board-9615-regulator.c
+++ b/arch/arm/mach-msm/board-9615-regulator.c
@@ -69,6 +69,7 @@
VREG_CONSUMERS(S1) = {
REGULATOR_SUPPLY("8018_s1", NULL),
REGULATOR_SUPPLY("HSUSB_VDDCX", "msm_otg"),
+ REGULATOR_SUPPLY("HSIC_VDDCX", "msm_hsic_peripheral"),
};
VREG_CONSUMERS(S2) = {
REGULATOR_SUPPLY("8018_s2", NULL),
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 0c46c9d..314d064 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -170,6 +170,29 @@
},
};
+static struct resource resources_hsic_peripheral[] = {
+ {
+ .start = MSM9615_HSIC_PHYS,
+ .end = MSM9615_HSIC_PHYS + MSM9615_HSIC_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = USB_HSIC_IRQ,
+ .end = USB_HSIC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device msm_device_hsic_peripheral = {
+ .name = "msm_hsic_peripheral",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(resources_hsic_peripheral),
+ .resource = resources_hsic_peripheral,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
static struct resource resources_hsusb_host[] = {
{
.start = MSM9615_HSUSB_PHYS,
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 6d8d393..33a543d 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -94,7 +94,7 @@
extern struct platform_device msm_device_hsic_host;
extern struct platform_device msm_device_otg;
-
+extern struct platform_device msm_device_hsic_peripheral;
extern struct platform_device msm8960_device_otg;
extern struct platform_device msm8960_device_gadget_peripheral;
diff --git a/arch/arm/mach-msm/include/mach/irqs-9615.h b/arch/arm/mach-msm/include/mach/irqs-9615.h
index 74e5847..5fba24e 100644
--- a/arch/arm/mach-msm/include/mach/irqs-9615.h
+++ b/arch/arm/mach-msm/include/mach/irqs-9615.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -179,8 +179,9 @@
#define TLMM_MSM_DIR_CONN_IRQ_21 (GIC_SPI_START + 224)
#define MSM_SPARE0_IRQ (GIC_SPI_START + 225)
#define PMIC_SEC_IRQ_N (GIC_SPI_START + 226)
+#define USB_HSIC_IRQ (GIC_SPI_START + 232)
-#define NR_MSM_IRQS 256
+#define NR_MSM_IRQS 288
#define NR_GPIO_IRQS 88
#define NR_PM8018_IRQS 256
#define NR_BOARD_IRQS NR_PM8018_IRQS
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-9615.h b/arch/arm/mach-msm/include/mach/msm_iomap-9615.h
index dda5f50..fc9b198 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-9615.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-9615.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
* Author: Brian Swetland <swetland@google.com>
*
* This software is licensed under the terms of the GNU General Public
@@ -77,6 +77,9 @@
#define MSM9615_HSUSB_PHYS 0x12500000
#define MSM9615_HSUSB_SIZE SZ_4K
+#define MSM9615_HSIC_PHYS 0x12540000
+#define MSM9615_HSIC_SIZE SZ_4K
+
#define MSM9615_QFPROM_PHYS 0x00700000
#define MSM9615_QFPROM_SIZE SZ_4K
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 94ed950..97e7aa4 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -594,6 +594,24 @@
default USB_GADGET
select USB_GADGET_SELECTED
+config USB_GADGET_CI13XXX_MSM_HSIC
+ boolean "MIPS HSIC CI13xxx for MSM"
+ depends on ARCH_MSM
+ select USB_GADGET_DUALSPEED
+ help
+ MSM SoC has chipidea USB controller. This driver uses
+ ci13xxx_udc core. Support USB-HSIC core.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "ci13xxx_msm_hsic" and force all
+ gadget drivers to also be dynamically linked.
+
+config USB_CI13XXX_MSM_HSIC
+ tristate
+ depends on USB_GADGET_CI13XXX_MSM_HSIC
+ default USB_GADGET
+ select USB_GADGET_SELECTED
+
#
# LAST -- dummy/emulated controller
#
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 064960c..141f649 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -27,6 +27,7 @@
obj-$(CONFIG_USB_EG20T) += pch_udc.o
obj-$(CONFIG_USB_PXA_U2O) += mv_udc.o
mv_udc-y := mv_udc_core.o mv_udc_phy.o
+obj-$(CONFIG_USB_CI13XXX_MSM_HSIC) += ci13xxx_msm_hsic.o
obj-$(CONFIG_USB_CI13XXX_MSM) += ci13xxx_msm.o
obj-$(CONFIG_USB_FUSB300) += fusb300_udc.o
obj-$(CONFIG_USB_MSM_72K) += msm72k_udc.o
diff --git a/drivers/usb/gadget/ci13xxx_msm_hsic.c b/drivers/usb/gadget/ci13xxx_msm_hsic.c
new file mode 100644
index 0000000..135c84d
--- /dev/null
+++ b/drivers/usb/gadget/ci13xxx_msm_hsic.c
@@ -0,0 +1,484 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/wakelock.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/usb.h>
+
+#include <linux/usb/gadget.h>
+#include <linux/usb/msm_hsusb_hw.h>
+#include <linux/usb/msm_hsusb.h>
+
+#include <mach/clk.h>
+#include <mach/msm_iomap.h>
+#include <mach/msm_xo.h>
+
+#include "ci13xxx_udc.c"
+
+#define MSM_USB_BASE (mhsic->regs)
+
+#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
+#define USB_PHY_VDD_DIG_VOL_MIN 1045000 /* uV */
+#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
+#define USB_PHY_VDD_DIG_LOAD 49360 /* uA */
+#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
+#define HSIC_CFG_REG 0x30
+#define HSIC_IO_CAL_PER_REG 0x33
+#define HSIC_DBG1_REG 0x38
+
+struct msm_hsic_per *the_mhsic;
+
+struct msm_hsic_per {
+ struct device *dev;
+ struct clk *iface_clk;
+ struct clk *core_clk;
+ struct clk *alt_core_clk;
+ struct clk *phy_clk;
+ struct clk *cal_clk;
+ struct regulator *hsic_vddcx;
+ bool async_int;
+ void __iomem *regs;
+ int irq;
+};
+
+static int msm_hsic_init_vddcx(struct msm_hsic_per *mhsic, int init)
+{
+ int ret = 0;
+
+ if (!init)
+ goto disable_reg;
+
+ mhsic->hsic_vddcx = regulator_get(mhsic->dev, "HSIC_VDDCX");
+ if (IS_ERR(mhsic->hsic_vddcx)) {
+ dev_err(mhsic->dev, "unable to get hsic vddcx\n");
+ return PTR_ERR(mhsic->hsic_vddcx);
+ }
+
+ ret = regulator_set_voltage(mhsic->hsic_vddcx,
+ USB_PHY_VDD_DIG_VOL_MIN,
+ USB_PHY_VDD_DIG_VOL_MAX);
+ if (ret) {
+ dev_err(mhsic->dev, "unable to set the voltage"
+ "for hsic vddcx\n");
+ goto reg_set_voltage_err;
+ }
+
+ ret = regulator_set_optimum_mode(mhsic->hsic_vddcx,
+ USB_PHY_VDD_DIG_LOAD);
+ if (ret < 0) {
+ pr_err("%s: Unable to set optimum mode of the regulator:"
+ "VDDCX\n", __func__);
+ goto reg_optimum_mode_err;
+ }
+
+ ret = regulator_enable(mhsic->hsic_vddcx);
+ if (ret) {
+ dev_err(mhsic->dev, "unable to enable hsic vddcx\n");
+ goto reg_enable_err;
+ }
+
+ return 0;
+
+disable_reg:
+ regulator_disable(mhsic->hsic_vddcx);
+reg_enable_err:
+ regulator_set_optimum_mode(mhsic->hsic_vddcx, 0);
+reg_optimum_mode_err:
+ regulator_set_voltage(mhsic->hsic_vddcx, 0,
+ USB_PHY_VDD_DIG_VOL_MIN);
+reg_set_voltage_err:
+ regulator_put(mhsic->hsic_vddcx);
+
+ return ret;
+
+}
+
+static int ulpi_write(struct msm_hsic_per *mhsic, u32 val, u32 reg)
+{
+ int cnt = 0;
+
+ /* initiate write operation */
+ writel_relaxed(ULPI_RUN | ULPI_WRITE |
+ ULPI_ADDR(reg) | ULPI_DATA(val),
+ USB_ULPI_VIEWPORT);
+
+ /* wait for completion */
+ while (cnt < ULPI_IO_TIMEOUT_USEC) {
+ if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
+ break;
+ udelay(1);
+ cnt++;
+ }
+
+ if (cnt >= ULPI_IO_TIMEOUT_USEC) {
+ dev_err(mhsic->dev, "ulpi_write: timeout\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int msm_hsic_phy_clk_reset(struct msm_hsic_per *mhsic)
+{
+ int ret;
+
+ ret = clk_reset(mhsic->core_clk, CLK_RESET_ASSERT);
+ if (ret) {
+ clk_disable(mhsic->alt_core_clk);
+ dev_err(mhsic->dev, "usb phy clk assert failed\n");
+ return ret;
+ }
+ usleep_range(10000, 12000);
+ clk_disable(mhsic->alt_core_clk);
+
+ ret = clk_reset(mhsic->core_clk, CLK_RESET_DEASSERT);
+ if (ret)
+ dev_err(mhsic->dev, "usb phy clk deassert failed\n");
+
+ return ret;
+}
+
+static int msm_hsic_phy_reset(struct msm_hsic_per *mhsic)
+{
+ u32 val;
+ int ret;
+
+ ret = msm_hsic_phy_clk_reset(mhsic);
+ if (ret)
+ return ret;
+
+ val = readl_relaxed(USB_PORTSC) & ~PORTSC_PTS_MASK;
+ writel_relaxed(val | PORTSC_PTS_ULPI, USB_PORTSC);
+
+ /*
+ * Ensure that RESET operation is completed before
+ * turning off clock.
+ */
+ mb();
+ dev_dbg(mhsic->dev, "phy_reset: success\n");
+
+ return 0;
+}
+
+static int msm_hsic_enable_clocks(struct platform_device *pdev,
+ struct msm_hsic_per *mhsic, bool enable)
+{
+ int ret = 0;
+
+ if (!enable)
+ goto put_clocks;
+
+ mhsic->iface_clk = clk_get(&pdev->dev, "iface_clk");
+ if (IS_ERR(mhsic->iface_clk)) {
+ dev_err(mhsic->dev, "failed to get iface_clk\n");
+ ret = PTR_ERR(mhsic->iface_clk);
+ goto put_iface_clk;
+ }
+
+ mhsic->core_clk = clk_get(&pdev->dev, "core_clk");
+ if (IS_ERR(mhsic->core_clk)) {
+ dev_err(mhsic->dev, "failed to get core_clk\n");
+ ret = PTR_ERR(mhsic->core_clk);
+ goto put_core_clk;
+ }
+
+ mhsic->phy_clk = clk_get(&pdev->dev, "phy_clk");
+ if (IS_ERR(mhsic->phy_clk)) {
+ dev_err(mhsic->dev, "failed to get phy_clk\n");
+ ret = PTR_ERR(mhsic->phy_clk);
+ goto put_phy_clk;
+ }
+
+ mhsic->alt_core_clk = clk_get(&pdev->dev, "alt_core_clk");
+ if (IS_ERR(mhsic->alt_core_clk)) {
+ dev_err(mhsic->dev, "failed to get alt_core_clk\n");
+ ret = PTR_ERR(mhsic->alt_core_clk);
+ goto put_alt_core_clk;
+ }
+
+ mhsic->cal_clk = clk_get(&pdev->dev, "cal_clk");
+ if (IS_ERR(mhsic->cal_clk)) {
+ dev_err(mhsic->dev, "failed to get cal_clk\n");
+ ret = PTR_ERR(mhsic->cal_clk);
+ goto put_cal_clk;
+ }
+
+ clk_enable(mhsic->iface_clk);
+ clk_enable(mhsic->core_clk);
+ clk_enable(mhsic->phy_clk);
+ clk_enable(mhsic->alt_core_clk);
+ clk_enable(mhsic->cal_clk);
+
+ return 0;
+
+put_clocks:
+ clk_disable(mhsic->iface_clk);
+ clk_disable(mhsic->core_clk);
+ clk_disable(mhsic->phy_clk);
+ clk_disable(mhsic->alt_core_clk);
+ clk_disable(mhsic->cal_clk);
+put_cal_clk:
+ clk_put(mhsic->cal_clk);
+put_alt_core_clk:
+ clk_put(mhsic->alt_core_clk);
+put_phy_clk:
+ clk_put(mhsic->phy_clk);
+put_core_clk:
+ clk_put(mhsic->core_clk);
+put_iface_clk:
+ clk_put(mhsic->iface_clk);
+
+ return ret;
+}
+
+static int msm_hsic_reset(struct msm_hsic_per *mhsic)
+{
+ int cnt = 0;
+ int ret;
+
+ ret = msm_hsic_phy_reset(mhsic);
+ if (ret) {
+ dev_err(mhsic->dev, "phy_reset failed\n");
+ return ret;
+ }
+
+ writel_relaxed(USBCMD_RESET, USB_USBCMD);
+ while (cnt < LINK_RESET_TIMEOUT_USEC) {
+ if (!(readl_relaxed(USB_USBCMD) & USBCMD_RESET))
+ break;
+ udelay(1);
+ cnt++;
+ }
+ if (cnt >= LINK_RESET_TIMEOUT_USEC)
+ return -ETIMEDOUT;
+
+ /* Reset PORTSC and select ULPI phy */
+ writel_relaxed(0x80000000, USB_PORTSC);
+ return 0;
+}
+
+static void msm_hsic_start(void)
+{
+ int ret;
+
+ /* programmable length of connect signaling (33.2ns) */
+ ret = ulpi_write(the_mhsic, 3, HSIC_DBG1_REG);
+ if (ret) {
+ pr_err("%s: Unable to program length of connect signaling\n",
+ __func__);
+ }
+
+ /*set periodic calibration interval to ~2.048sec in HSIC_IO_CAL_REG */
+ ret = ulpi_write(the_mhsic, 0xFF, HSIC_IO_CAL_PER_REG);
+
+ if (ret) {
+ pr_err("%s: Unable to set periodic calibration interval\n",
+ __func__);
+ }
+
+ /* Enable periodic IO calibration in HSIC_CFG register */
+ ret = ulpi_write(the_mhsic, 0xE9, HSIC_CFG_REG);
+ if (ret) {
+ pr_err("%s: Unable to enable periodic IO calibration\n",
+ __func__);
+ }
+}
+
+/**
+ * Dummy match function - will be called only for HSIC msm
+ * device (msm_device_gadget_hsic_peripheral).
+ */
+static inline int __match(struct device *dev, void *data) { return 1; }
+
+static void msm_hsic_connect_peripheral(struct device *msm_udc_dev)
+{
+ struct device *dev;
+ struct usb_gadget *gadget;
+
+ dev = device_find_child(msm_udc_dev, NULL, __match);
+ gadget = dev_to_usb_gadget(dev);
+ usb_gadget_vbus_connect(gadget);
+}
+
+static irqreturn_t msm_udc_hsic_irq(int irq, void *data)
+{
+ return udc_irq();
+}
+
+static void ci13xxx_msm_hsic_notify_event(struct ci13xxx *udc, unsigned event)
+{
+ struct device *dev = udc->gadget.dev.parent;
+ struct msm_hsic_per *mhsic = the_mhsic;
+
+ switch (event) {
+ case CI13XXX_CONTROLLER_RESET_EVENT:
+ dev_dbg(dev, "CI13XXX_CONTROLLER_RESET_EVENT received\n");
+ writel_relaxed(0, USB_AHBBURST);
+ writel_relaxed(0, USB_AHBMODE);
+ break;
+ case CI13XXX_CONTROLLER_CONNECT_EVENT:
+ dev_dbg(dev, "CI13XXX_CONTROLLER_CONNECT_EVENT received\n");
+ msm_hsic_start();
+ break;
+ default:
+ dev_dbg(dev, "unknown ci13xxx_udc event\n");
+ break;
+ }
+}
+
+static struct ci13xxx_udc_driver ci13xxx_msm_udc_hsic_driver = {
+ .name = "ci13xxx_msm_hsic",
+ .flags = CI13XXX_REGS_SHARED |
+ CI13XXX_PULLUP_ON_VBUS |
+ CI13XXX_DISABLE_STREAMING |
+ CI13XXX_ZERO_ITC,
+
+ .notify_event = ci13xxx_msm_hsic_notify_event,
+};
+
+static int __devinit msm_hsic_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct msm_hsic_per *mhsic;
+ int ret = 0;
+
+ dev_dbg(&pdev->dev, "msm-hsic probe\n");
+
+ mhsic = kzalloc(sizeof(struct msm_hsic_per), GFP_KERNEL);
+ if (!mhsic) {
+ dev_err(&pdev->dev, "unable to allocate msm_hsic\n");
+ return -ENOMEM;
+ }
+ the_mhsic = mhsic;
+ platform_set_drvdata(pdev, mhsic);
+ mhsic->dev = &pdev->dev;
+
+ mhsic->irq = platform_get_irq(pdev, 0);
+ if (mhsic->irq < 0) {
+ dev_err(&pdev->dev, "Unable to get IRQ resource\n");
+ ret = mhsic->irq;
+ goto error;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "Unable to get memory resource\n");
+ ret = -ENODEV;
+ goto error;
+ }
+ mhsic->regs = ioremap(res->start, resource_size(res));
+ if (!mhsic->regs) {
+ dev_err(&pdev->dev, "ioremap failed\n");
+ ret = -ENOMEM;
+ goto unmap;
+ }
+ dev_info(&pdev->dev, "HSIC Peripheral regs = %p\n", mhsic->regs);
+
+ ret = msm_hsic_enable_clocks(pdev, mhsic, true);
+
+ if (ret) {
+ dev_err(&pdev->dev, "msm_hsic_enable_clocks failed\n");
+ ret = -ENODEV;
+ goto deinit_clocks;
+ }
+ ret = msm_hsic_init_vddcx(mhsic, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to initialize VDDCX\n");
+ ret = -ENODEV;
+ goto deinit_vddcx;
+ }
+
+ ret = msm_hsic_reset(mhsic);
+ if (ret) {
+ dev_err(&pdev->dev, "msm_hsic_reset failed\n");
+ ret = -ENODEV;
+ goto deinit_vddcx;
+ }
+
+ ret = udc_probe(&ci13xxx_msm_udc_hsic_driver, &pdev->dev, mhsic->regs);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "udc_probe failed\n");
+ ret = -ENODEV;
+ goto deinit_vddcx;
+ }
+
+ msm_hsic_connect_peripheral(&pdev->dev);
+
+ ret = request_irq(mhsic->irq, msm_udc_hsic_irq,
+ IRQF_SHARED, pdev->name, pdev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "request_irq failed\n");
+ ret = -ENODEV;
+ goto udc_remove;
+ }
+
+ pm_runtime_no_callbacks(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
+ return 0;
+udc_remove:
+ udc_remove();
+deinit_vddcx:
+ msm_hsic_init_vddcx(mhsic, 0);
+deinit_clocks:
+ msm_hsic_enable_clocks(pdev, mhsic, 0);
+unmap:
+ iounmap(mhsic->regs);
+error:
+ kfree(mhsic);
+ return ret;
+}
+
+static int __devexit hsic_msm_remove(struct platform_device *pdev)
+{
+ struct msm_hsic_per *mhsic = platform_get_drvdata(pdev);
+
+ device_init_wakeup(&pdev->dev, 0);
+ msm_hsic_init_vddcx(mhsic, 0);
+ msm_hsic_enable_clocks(pdev, mhsic, 0);
+ udc_remove();
+ iounmap(mhsic->regs);
+ kfree(mhsic);
+
+ return 0;
+}
+static struct platform_driver msm_hsic_peripheral_driver = {
+ .probe = msm_hsic_probe,
+ .remove = __devexit_p(hsic_msm_remove),
+ .driver = {
+ .name = "msm_hsic_peripheral",
+ },
+};
+
+static int __init msm_hsic_peripheral_init(void)
+{
+ return platform_driver_probe(&msm_hsic_peripheral_driver,
+ msm_hsic_probe);
+}
+
+static void __exit msm_hsic_peripheral_exit(void)
+{
+ platform_driver_unregister(&msm_hsic_peripheral_driver);
+}
+
+module_init(msm_hsic_peripheral_init);
+module_exit(msm_hsic_peripheral_exit);
+
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 703494a..35327cc 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -2816,8 +2816,12 @@
}
spin_unlock_irqrestore(udc->lock, flags);
- if (is_active)
+ if (is_active) {
hw_device_state(udc->ep0out.qh.dma);
+ if (udc->udc_driver->notify_event)
+ udc->udc_driver->notify_event(udc,
+ CI13XXX_CONTROLLER_CONNECT_EVENT);
+ }
else
hw_device_state(0);
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h
index 35b0712..fce611a 100644
--- a/drivers/usb/gadget/ci13xxx_udc.h
+++ b/drivers/usb/gadget/ci13xxx_udc.h
@@ -127,6 +127,7 @@
#define CI13XXX_ZERO_ITC BIT(4)
#define CI13XXX_CONTROLLER_RESET_EVENT 0
+#define CI13XXX_CONTROLLER_CONNECT_EVENT 1
void (*notify_event) (struct ci13xxx *udc, unsigned event);
};
@@ -233,7 +234,10 @@
"[%s] " format "\n", __func__, ## args); \
} while (0)
+#ifndef err
#define err(format, args...) ci13xxx_printk(KERN_ERR, format, ## args)
+#endif
+
#define warn(format, args...) ci13xxx_printk(KERN_WARNING, format, ## args)
#define info(format, args...) ci13xxx_printk(KERN_INFO, format, ## args)
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
index 05692bb..da312d4 100644
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -160,6 +160,13 @@
#define gadget_is_ci13xxx_msm(g) 0
#endif
+#ifdef CONFIG_USB_GADGET_CI13XXX_MSM_HSIC
+#define gadget_is_ci13xxx_msm_hsic(g) \
+ (!strncmp("ci13xxx_msm_hsic", (g)->name, 16))
+#else
+#define gadget_is_ci13xxx_msm_hsic(g) 0
+#endif
+
#ifdef CONFIG_USB_GADGET_RENESAS_USBHS
#define gadget_is_renesas_usbhs(g) (!strcmp("renesas_usbhs_udc", (g)->name))
#else
@@ -231,6 +238,8 @@
return 0x30;
else if (gadget_is_msm72k(gadget))
return 0x31;
+ else if (gadget_is_ci13xxx_msm_hsic(gadget))
+ return 0x32;
return -ENOENT;
}