All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/3] usb: musb: add new phy driver
@ 2012-05-30 14:34 ` Kishon Vijay Abraham I
  0 siblings, 0 replies; 23+ messages in thread
From: Kishon Vijay Abraham I @ 2012-05-30 14:34 UTC (permalink / raw)
  To: tony, linux, gregkh, kishon, linux-omap, linux-arm-kernel,
	linux-kernel, linux-usb, balbi

This series adds a new usb2 phy driver. The device for which is created
by the ocp2scp driver. This also uses control module driver.

This series converts twl6030 as a comparator driver (previously it was
also the phy driver) and makes use of omap-usb2 as the phy driver.

Instead of notification mechanism by power chip to omap glue to pass detection
of any events, an export API has been added in omap glue. Both twl4030 and
twl6030 will call to this API to pass any event. (twl6030 is used in omap4 and
twl4030 is used in omap3).

This series depends on:
*[RFC PATCH 00/11] OMAP System Control Module* patch series
However System Control Module driver has only dt support, so wouldn't
be able to test this patch series. However I'll adapt omap usb2 phy
driver and musb driver for dt and send it asap to the list.

This series also depends on:
*[PATCH v3 0/3] usb: multi-phy support* patch series
*[RFC PATCH 0/5] omap: add ocp2scp as a misc driver* patch series

Compile tested only.

Kishon Vijay Abraham I (3):
  drivers: usb: otg: add a new driver for omap usb2 phy
  usb: musb: omap glue: use omap-usb2 as the phy driver
  arm: omap: phy: remove unused functions from omap-phy-internal.c

 arch/arm/mach-omap2/omap_phy_internal.c |  138 ------------------
 arch/arm/mach-omap2/twl-common.c        |    5 -
 arch/arm/mach-omap2/usb-musb.c          |    3 -
 drivers/usb/musb/musb_core.h            |    1 -
 drivers/usb/musb/omap2430.c             |  150 ++++++++++++++------
 drivers/usb/otg/Kconfig                 |   17 ++-
 drivers/usb/otg/Makefile                |    1 +
 drivers/usb/otg/omap-usb2.c             |  232 +++++++++++++++++++++++++++++++
 drivers/usb/otg/twl4030-usb.c           |   40 ++----
 drivers/usb/otg/twl6030-usb.c           |  172 +++++------------------
 include/linux/usb/musb-omap.h           |   31 ++++
 include/linux/usb/omap_usb.h            |   47 ++++++
 include/linux/usb/phy_companion.h       |   34 +++++
 13 files changed, 514 insertions(+), 357 deletions(-)
 create mode 100644 drivers/usb/otg/omap-usb2.c
 create mode 100644 include/linux/usb/musb-omap.h
 create mode 100644 include/linux/usb/omap_usb.h
 create mode 100644 include/linux/usb/phy_companion.h

-- 
1.7.5.4


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [RFC PATCH 0/3] usb: musb: add new phy driver
@ 2012-05-30 14:34 ` Kishon Vijay Abraham I
  0 siblings, 0 replies; 23+ messages in thread
From: Kishon Vijay Abraham I @ 2012-05-30 14:34 UTC (permalink / raw)
  To: tony, linux, gregkh, kishon, linux-omap, linux-arm-kernel,
	linux-kernel, linux-usb, balbi

This series adds a new usb2 phy driver. The device for which is created
by the ocp2scp driver. This also uses control module driver.

This series converts twl6030 as a comparator driver (previously it was
also the phy driver) and makes use of omap-usb2 as the phy driver.

Instead of notification mechanism by power chip to omap glue to pass detection
of any events, an export API has been added in omap glue. Both twl4030 and
twl6030 will call to this API to pass any event. (twl6030 is used in omap4 and
twl4030 is used in omap3).

This series depends on:
*[RFC PATCH 00/11] OMAP System Control Module* patch series
However System Control Module driver has only dt support, so wouldn't
be able to test this patch series. However I'll adapt omap usb2 phy
driver and musb driver for dt and send it asap to the list.

This series also depends on:
*[PATCH v3 0/3] usb: multi-phy support* patch series
*[RFC PATCH 0/5] omap: add ocp2scp as a misc driver* patch series

Compile tested only.

Kishon Vijay Abraham I (3):
  drivers: usb: otg: add a new driver for omap usb2 phy
  usb: musb: omap glue: use omap-usb2 as the phy driver
  arm: omap: phy: remove unused functions from omap-phy-internal.c

 arch/arm/mach-omap2/omap_phy_internal.c |  138 ------------------
 arch/arm/mach-omap2/twl-common.c        |    5 -
 arch/arm/mach-omap2/usb-musb.c          |    3 -
 drivers/usb/musb/musb_core.h            |    1 -
 drivers/usb/musb/omap2430.c             |  150 ++++++++++++++------
 drivers/usb/otg/Kconfig                 |   17 ++-
 drivers/usb/otg/Makefile                |    1 +
 drivers/usb/otg/omap-usb2.c             |  232 +++++++++++++++++++++++++++++++
 drivers/usb/otg/twl4030-usb.c           |   40 ++----
 drivers/usb/otg/twl6030-usb.c           |  172 +++++------------------
 include/linux/usb/musb-omap.h           |   31 ++++
 include/linux/usb/omap_usb.h            |   47 ++++++
 include/linux/usb/phy_companion.h       |   34 +++++
 13 files changed, 514 insertions(+), 357 deletions(-)
 create mode 100644 drivers/usb/otg/omap-usb2.c
 create mode 100644 include/linux/usb/musb-omap.h
 create mode 100644 include/linux/usb/omap_usb.h
 create mode 100644 include/linux/usb/phy_companion.h

-- 
1.7.5.4

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [RFC PATCH 0/3] usb: musb: add new phy driver
@ 2012-05-30 14:34 ` Kishon Vijay Abraham I
  0 siblings, 0 replies; 23+ messages in thread
From: Kishon Vijay Abraham I @ 2012-05-30 14:34 UTC (permalink / raw)
  To: linux-arm-kernel

This series adds a new usb2 phy driver. The device for which is created
by the ocp2scp driver. This also uses control module driver.

This series converts twl6030 as a comparator driver (previously it was
also the phy driver) and makes use of omap-usb2 as the phy driver.

Instead of notification mechanism by power chip to omap glue to pass detection
of any events, an export API has been added in omap glue. Both twl4030 and
twl6030 will call to this API to pass any event. (twl6030 is used in omap4 and
twl4030 is used in omap3).

This series depends on:
*[RFC PATCH 00/11] OMAP System Control Module* patch series
However System Control Module driver has only dt support, so wouldn't
be able to test this patch series. However I'll adapt omap usb2 phy
driver and musb driver for dt and send it asap to the list.

This series also depends on:
*[PATCH v3 0/3] usb: multi-phy support* patch series
*[RFC PATCH 0/5] omap: add ocp2scp as a misc driver* patch series

Compile tested only.

Kishon Vijay Abraham I (3):
  drivers: usb: otg: add a new driver for omap usb2 phy
  usb: musb: omap glue: use omap-usb2 as the phy driver
  arm: omap: phy: remove unused functions from omap-phy-internal.c

 arch/arm/mach-omap2/omap_phy_internal.c |  138 ------------------
 arch/arm/mach-omap2/twl-common.c        |    5 -
 arch/arm/mach-omap2/usb-musb.c          |    3 -
 drivers/usb/musb/musb_core.h            |    1 -
 drivers/usb/musb/omap2430.c             |  150 ++++++++++++++------
 drivers/usb/otg/Kconfig                 |   17 ++-
 drivers/usb/otg/Makefile                |    1 +
 drivers/usb/otg/omap-usb2.c             |  232 +++++++++++++++++++++++++++++++
 drivers/usb/otg/twl4030-usb.c           |   40 ++----
 drivers/usb/otg/twl6030-usb.c           |  172 +++++------------------
 include/linux/usb/musb-omap.h           |   31 ++++
 include/linux/usb/omap_usb.h            |   47 ++++++
 include/linux/usb/phy_companion.h       |   34 +++++
 13 files changed, 514 insertions(+), 357 deletions(-)
 create mode 100644 drivers/usb/otg/omap-usb2.c
 create mode 100644 include/linux/usb/musb-omap.h
 create mode 100644 include/linux/usb/omap_usb.h
 create mode 100644 include/linux/usb/phy_companion.h

-- 
1.7.5.4

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [RFC PATCH 1/3] drivers: usb: otg: add a new driver for omap usb2 phy
  2012-05-30 14:34 ` Kishon Vijay Abraham I
  (?)
@ 2012-05-30 14:34   ` Kishon Vijay Abraham I
  -1 siblings, 0 replies; 23+ messages in thread
From: Kishon Vijay Abraham I @ 2012-05-30 14:34 UTC (permalink / raw)
  To: tony, linux, gregkh, kishon, linux-omap, linux-arm-kernel,
	linux-kernel, linux-usb, balbi

All phy related programming like enabling/disabling the clocks, powering
on/off the phy is taken care of by this driver. It is also used for OTG
related functionality like srp.

Cc: Felipe Balbi <balbi@ti.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/usb/otg/Kconfig           |   17 ++-
 drivers/usb/otg/Makefile          |    1 +
 drivers/usb/otg/omap-usb2.c       |  232 +++++++++++++++++++++++++++++++++++++
 include/linux/usb/omap_usb.h      |   47 ++++++++
 include/linux/usb/phy_companion.h |   34 ++++++
 5 files changed, 327 insertions(+), 4 deletions(-)
 create mode 100644 drivers/usb/otg/omap-usb2.c
 create mode 100644 include/linux/usb/omap_usb.h
 create mode 100644 include/linux/usb/phy_companion.h

diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
index e2840f1..3264c0d 100644
--- a/drivers/usb/otg/Kconfig
+++ b/drivers/usb/otg/Kconfig
@@ -73,10 +73,8 @@ config TWL6030_USB
 	help
 	  Enable this to support the USB OTG transceiver on TWL6030
 	  family chips. This TWL6030 transceiver has the VBUS and ID GND
-	  and OTG SRP events capabilities. For all other transceiver functionality
-	  UTMI PHY is embedded in OMAP4430. The internal PHY configurations APIs
-	  are hooked to this driver through platform_data structure.
-	  The definition of internal PHY APIs are in the mach-omap2 layer.
+          and OTG SRP events capabilities. For all other transceiver
+	  functionality UTMI PHY is embedded in OMAP4430.
 
 config OMAP4_USB_PHY
 	tristate "Texas Instruments OMAP4+ USB pin control driver"
@@ -91,6 +89,17 @@ config OMAP4_USB_PHY
 	  performing the above mentioned configuration, API's are added in
 	  by this children of the control module driver.
 
+config OMAP_USB2
+	tristate "OMAP USB2 PHY Driver"
+	depends on OMAP_OCP2SCP
+	depends on OMAP4_USB_PHY
+	select USB_OTG_UTILS
+	help
+	  Enable this to support the transceiver that is part of SOC. This
+	  driver takes care of all the PHY functionality apart from comparator.
+	  The USB OTG controller communicates with the comparator using this
+	  driver.
+
 config NOP_USB_XCEIV
 	tristate "NOP USB Transceiver Driver"
 	select USB_OTG_UTILS
diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile
index 60c8c83..2f02912 100644
--- a/drivers/usb/otg/Makefile
+++ b/drivers/usb/otg/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_ISP1301_OMAP)	+= isp1301_omap.o
 obj-$(CONFIG_TWL4030_USB)	+= twl4030-usb.o
 obj-$(CONFIG_TWL6030_USB)	+= twl6030-usb.o
 obj-$(CONFIG_OMAP4_USB_PHY)	+= omap4-usb-phy.o
+obj-$(CONFIG_OMAP_USB2)		+= omap-usb2.o
 obj-$(CONFIG_NOP_USB_XCEIV)	+= nop-usb-xceiv.o
 obj-$(CONFIG_USB_ULPI)		+= ulpi.o
 obj-$(CONFIG_USB_ULPI_VIEWPORT)	+= ulpi_viewport.o
diff --git a/drivers/usb/otg/omap-usb2.c b/drivers/usb/otg/omap-usb2.c
new file mode 100644
index 0000000..ccd74b6
--- /dev/null
+++ b/drivers/usb/otg/omap-usb2.c
@@ -0,0 +1,232 @@
+/*
+ * omap-usb2.c - USB PHY, talking to musb controller in OMAP.
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/usb/omap_usb.h>
+#include <linux/usb/phy_companion.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
+#include <linux/mfd/omap_control.h>
+#include <linux/usb/omap4_usb_phy.h>
+
+/**
+ * omap_usb2_set_comparator - links the comparator present in the sytem with
+ *	this phy
+ * @comparator - the companion phy(comparator) for this phy
+ *
+ * The phy companion driver should call this API passing the phy_companion
+ * filled with set_vbus and start_srp to be used by usb phy.
+ *
+ * For use by phy companion driver
+ */
+void omap_usb2_set_comparator(struct phy_companion *comparator)
+{
+	struct usb_phy	*x = usb_get_phy(USB_PHY_TYPE_USB2);
+	struct omap_usb	*phy = phy_to_omapusb(x);
+
+	phy->comparator = comparator;
+}
+EXPORT_SYMBOL_GPL(omap_usb2_set_comparator);
+
+static int omap_usb_set_vbus(struct usb_otg *otg, bool enabled)
+{
+	struct omap_usb *phy = phy_to_omapusb(otg->phy);
+
+	if (!phy->comparator)
+		return -ENODEV;
+
+	return phy->comparator->set_vbus(phy->comparator, enabled);
+}
+
+static int omap_usb_start_srp(struct usb_otg *otg)
+{
+	struct omap_usb *phy = phy_to_omapusb(otg->phy);
+
+	if (!phy->comparator)
+		return -ENODEV;
+
+	return phy->comparator->start_srp(phy->comparator);
+}
+
+static int omap_usb_set_host(struct usb_otg *otg, struct usb_bus *host)
+{
+	struct usb_phy	*phy = otg->phy;
+
+	otg->host = host;
+	if (!host)
+		phy->state = OTG_STATE_UNDEFINED;
+
+	return 0;
+}
+
+static int omap_usb_set_peripheral(struct usb_otg *otg,
+		struct usb_gadget *gadget)
+{
+	struct usb_phy	*phy = otg->phy;
+
+	otg->gadget = gadget;
+	if (!gadget)
+		phy->state = OTG_STATE_UNDEFINED;
+
+	return 0;
+}
+
+static int omap_usb2_suspend(struct usb_phy *x, int suspend)
+{
+	struct omap_usb *phy = phy_to_omapusb(x);
+
+	if (suspend && !phy->is_suspended) {
+		pm_runtime_put_sync(phy->dev);
+		phy->is_suspended = 1;
+	} else if (!suspend && phy->is_suspended) {
+		pm_runtime_get_sync(phy->dev);
+		phy->is_suspended = 0;
+	}
+
+	return 0;
+}
+
+static int __devinit omap_usb2_probe(struct platform_device *pdev)
+{
+	struct omap_usb			*phy;
+	struct usb_otg			*otg;
+
+	phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
+	if (!phy) {
+		dev_err(&pdev->dev, "unable to allocate memory for USB2 PHY\n");
+		return -ENOMEM;
+	}
+
+	otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
+	if (!otg) {
+		dev_err(&pdev->dev, "unable to allocate memory for USB OTG\n");
+		return -ENOMEM;
+	}
+
+	phy->dev		= &pdev->dev;
+
+	phy->phy.dev		= phy->dev;
+	phy->phy.label		= "omap-usb2";
+	phy->phy.set_suspend	= omap_usb2_suspend;
+	phy->phy.otg		= otg;
+
+	phy->control_dev	= omap_control_get();
+	if (IS_ERR(phy->control_dev)) {
+		dev_err(&pdev->dev, "no control device present in system\n");
+		return PTR_ERR(phy->control_dev);
+	}
+
+	phy->is_suspended	= 1;
+	omap4_usb_phy_power(phy->control_dev, 0);
+
+	otg->set_host		= omap_usb_set_host;
+	otg->set_peripheral	= omap_usb_set_peripheral;
+	otg->set_vbus		= omap_usb_set_vbus;
+	otg->start_srp		= omap_usb_start_srp;
+	otg->phy		= &phy->phy;
+
+	phy->wkupclk = clk_get(phy->dev, "usb_phy_cm_clk32k");
+
+	usb_add_phy(&phy->phy, USB_PHY_TYPE_USB2);
+
+	platform_set_drvdata(pdev, phy);
+
+	pm_runtime_enable(phy->dev);
+
+	return 0;
+}
+
+static int __devexit omap_usb2_remove(struct platform_device *pdev)
+{
+	struct omap_usb	*phy = platform_get_drvdata(pdev);
+
+	usb_remove_phy(&phy->phy);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int omap_usb2_runtime_suspend(struct device *dev)
+{
+	struct platform_device	*pdev = to_platform_device(dev);
+	struct omap_usb	*phy = platform_get_drvdata(pdev);
+
+	clk_disable(phy->wkupclk);
+	omap4_usb_phy_power(phy->control_dev, 0);
+
+	return 0;
+}
+
+static int omap_usb2_runtime_resume(struct device *dev)
+{
+	struct platform_device	*pdev = to_platform_device(dev);
+	struct omap_usb	*phy = platform_get_drvdata(pdev);
+
+	omap4_usb_phy_power(phy->control_dev, 1);
+	clk_enable(phy->wkupclk);
+
+	return 0;
+}
+
+static const struct dev_pm_ops omap_usb2_pm_ops = {
+	SET_RUNTIME_PM_OPS(omap_usb2_runtime_suspend, omap_usb2_runtime_resume,
+		NULL)
+};
+
+#define DEV_PM_OPS     (&omap_usb2_pm_ops)
+#else
+#define DEV_PM_OPS     NULL
+#endif
+
+static struct platform_driver omap_usb2_driver = {
+	.probe		= omap_usb2_probe,
+	.remove		= __devexit_p(omap_usb2_remove),
+	.driver		= {
+		.name	= "omap-usb2",
+		.owner	= THIS_MODULE,
+		.pm	= DEV_PM_OPS,
+	},
+};
+
+static int __init usb2_omap_init(void)
+{
+	return platform_driver_register(&omap_usb2_driver);
+}
+arch_initcall(usb2_omap_init);
+
+static void __exit usb2_omap_exit(void)
+{
+	platform_driver_unregister(&omap_usb2_driver);
+}
+module_exit(usb2_omap_exit);
+
+MODULE_ALIAS("platform: omap_usb2");
+MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
+MODULE_DESCRIPTION("OMAP USB2 PHY DRIVER");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/usb/omap_usb.h b/include/linux/usb/omap_usb.h
new file mode 100644
index 0000000..8d781df
--- /dev/null
+++ b/include/linux/usb/omap_usb.h
@@ -0,0 +1,47 @@
+/*
+ * omap_usb.h -- omap usb2 phy header file
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef __DRIVERS_OMAP_USB2_H
+#define __DRIVERS_OMAP_USB2_H
+
+#include <linux/usb/otg.h>
+
+struct omap_usb {
+	struct usb_phy		phy;
+	struct phy_companion	*comparator;
+	struct device		*dev;
+	struct device		*control_dev;
+	struct clk		*wkupclk;
+	u8			is_suspended:1;
+};
+
+#define	phy_to_omapusb(x)	container_of((x), struct omap_usb, phy)
+
+#if defined(CONFIG_OMAP_USB2) || defined(CONFIG_OMAP_USB2_MODULE)
+void omap_usb2_set_comparator(struct phy_companion *comparator);
+#else
+static inline void omap_usb2_set_comparator(struct phy_companion *comparator)
+{
+}
+#endif
+
+#endif /* __DRIVERS_OMAP_USB_H */
diff --git a/include/linux/usb/phy_companion.h b/include/linux/usb/phy_companion.h
new file mode 100644
index 0000000..321290f
--- /dev/null
+++ b/include/linux/usb/phy_companion.h
@@ -0,0 +1,34 @@
+/*
+ * phy-companion.h -- phy companion to indicate the comparator part of PHY
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef __DRIVERS_PHY_COMPANION_H
+#define __DRIVERS_PHY_COMPANION_H
+
+#include <linux/usb/otg.h>
+
+/* phy_companion to take care of VBUS, ID and srp capabilities */
+struct phy_companion {
+
+	/* effective for A-peripheral, ignored for B devices */
+	int	(*set_vbus)(struct phy_companion *x, bool enabled);
+
+	/* for B devices only:  start session with A-Host */
+	int	(*start_srp)(struct phy_companion *x);
+};
+
+#endif /* __DRIVERS_PHY_COMPANION_H */
-- 
1.7.5.4


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH 1/3] drivers: usb: otg: add a new driver for omap usb2 phy
@ 2012-05-30 14:34   ` Kishon Vijay Abraham I
  0 siblings, 0 replies; 23+ messages in thread
From: Kishon Vijay Abraham I @ 2012-05-30 14:34 UTC (permalink / raw)
  To: tony, linux, gregkh, kishon, linux-omap, linux-arm-kernel,
	linux-kernel, linux-usb, balbi

All phy related programming like enabling/disabling the clocks, powering
on/off the phy is taken care of by this driver. It is also used for OTG
related functionality like srp.

Cc: Felipe Balbi <balbi@ti.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/usb/otg/Kconfig           |   17 ++-
 drivers/usb/otg/Makefile          |    1 +
 drivers/usb/otg/omap-usb2.c       |  232 +++++++++++++++++++++++++++++++++++++
 include/linux/usb/omap_usb.h      |   47 ++++++++
 include/linux/usb/phy_companion.h |   34 ++++++
 5 files changed, 327 insertions(+), 4 deletions(-)
 create mode 100644 drivers/usb/otg/omap-usb2.c
 create mode 100644 include/linux/usb/omap_usb.h
 create mode 100644 include/linux/usb/phy_companion.h

diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
index e2840f1..3264c0d 100644
--- a/drivers/usb/otg/Kconfig
+++ b/drivers/usb/otg/Kconfig
@@ -73,10 +73,8 @@ config TWL6030_USB
 	help
 	  Enable this to support the USB OTG transceiver on TWL6030
 	  family chips. This TWL6030 transceiver has the VBUS and ID GND
-	  and OTG SRP events capabilities. For all other transceiver functionality
-	  UTMI PHY is embedded in OMAP4430. The internal PHY configurations APIs
-	  are hooked to this driver through platform_data structure.
-	  The definition of internal PHY APIs are in the mach-omap2 layer.
+          and OTG SRP events capabilities. For all other transceiver
+	  functionality UTMI PHY is embedded in OMAP4430.
 
 config OMAP4_USB_PHY
 	tristate "Texas Instruments OMAP4+ USB pin control driver"
@@ -91,6 +89,17 @@ config OMAP4_USB_PHY
 	  performing the above mentioned configuration, API's are added in
 	  by this children of the control module driver.
 
+config OMAP_USB2
+	tristate "OMAP USB2 PHY Driver"
+	depends on OMAP_OCP2SCP
+	depends on OMAP4_USB_PHY
+	select USB_OTG_UTILS
+	help
+	  Enable this to support the transceiver that is part of SOC. This
+	  driver takes care of all the PHY functionality apart from comparator.
+	  The USB OTG controller communicates with the comparator using this
+	  driver.
+
 config NOP_USB_XCEIV
 	tristate "NOP USB Transceiver Driver"
 	select USB_OTG_UTILS
diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile
index 60c8c83..2f02912 100644
--- a/drivers/usb/otg/Makefile
+++ b/drivers/usb/otg/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_ISP1301_OMAP)	+= isp1301_omap.o
 obj-$(CONFIG_TWL4030_USB)	+= twl4030-usb.o
 obj-$(CONFIG_TWL6030_USB)	+= twl6030-usb.o
 obj-$(CONFIG_OMAP4_USB_PHY)	+= omap4-usb-phy.o
+obj-$(CONFIG_OMAP_USB2)		+= omap-usb2.o
 obj-$(CONFIG_NOP_USB_XCEIV)	+= nop-usb-xceiv.o
 obj-$(CONFIG_USB_ULPI)		+= ulpi.o
 obj-$(CONFIG_USB_ULPI_VIEWPORT)	+= ulpi_viewport.o
diff --git a/drivers/usb/otg/omap-usb2.c b/drivers/usb/otg/omap-usb2.c
new file mode 100644
index 0000000..ccd74b6
--- /dev/null
+++ b/drivers/usb/otg/omap-usb2.c
@@ -0,0 +1,232 @@
+/*
+ * omap-usb2.c - USB PHY, talking to musb controller in OMAP.
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/usb/omap_usb.h>
+#include <linux/usb/phy_companion.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
+#include <linux/mfd/omap_control.h>
+#include <linux/usb/omap4_usb_phy.h>
+
+/**
+ * omap_usb2_set_comparator - links the comparator present in the sytem with
+ *	this phy
+ * @comparator - the companion phy(comparator) for this phy
+ *
+ * The phy companion driver should call this API passing the phy_companion
+ * filled with set_vbus and start_srp to be used by usb phy.
+ *
+ * For use by phy companion driver
+ */
+void omap_usb2_set_comparator(struct phy_companion *comparator)
+{
+	struct usb_phy	*x = usb_get_phy(USB_PHY_TYPE_USB2);
+	struct omap_usb	*phy = phy_to_omapusb(x);
+
+	phy->comparator = comparator;
+}
+EXPORT_SYMBOL_GPL(omap_usb2_set_comparator);
+
+static int omap_usb_set_vbus(struct usb_otg *otg, bool enabled)
+{
+	struct omap_usb *phy = phy_to_omapusb(otg->phy);
+
+	if (!phy->comparator)
+		return -ENODEV;
+
+	return phy->comparator->set_vbus(phy->comparator, enabled);
+}
+
+static int omap_usb_start_srp(struct usb_otg *otg)
+{
+	struct omap_usb *phy = phy_to_omapusb(otg->phy);
+
+	if (!phy->comparator)
+		return -ENODEV;
+
+	return phy->comparator->start_srp(phy->comparator);
+}
+
+static int omap_usb_set_host(struct usb_otg *otg, struct usb_bus *host)
+{
+	struct usb_phy	*phy = otg->phy;
+
+	otg->host = host;
+	if (!host)
+		phy->state = OTG_STATE_UNDEFINED;
+
+	return 0;
+}
+
+static int omap_usb_set_peripheral(struct usb_otg *otg,
+		struct usb_gadget *gadget)
+{
+	struct usb_phy	*phy = otg->phy;
+
+	otg->gadget = gadget;
+	if (!gadget)
+		phy->state = OTG_STATE_UNDEFINED;
+
+	return 0;
+}
+
+static int omap_usb2_suspend(struct usb_phy *x, int suspend)
+{
+	struct omap_usb *phy = phy_to_omapusb(x);
+
+	if (suspend && !phy->is_suspended) {
+		pm_runtime_put_sync(phy->dev);
+		phy->is_suspended = 1;
+	} else if (!suspend && phy->is_suspended) {
+		pm_runtime_get_sync(phy->dev);
+		phy->is_suspended = 0;
+	}
+
+	return 0;
+}
+
+static int __devinit omap_usb2_probe(struct platform_device *pdev)
+{
+	struct omap_usb			*phy;
+	struct usb_otg			*otg;
+
+	phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
+	if (!phy) {
+		dev_err(&pdev->dev, "unable to allocate memory for USB2 PHY\n");
+		return -ENOMEM;
+	}
+
+	otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
+	if (!otg) {
+		dev_err(&pdev->dev, "unable to allocate memory for USB OTG\n");
+		return -ENOMEM;
+	}
+
+	phy->dev		= &pdev->dev;
+
+	phy->phy.dev		= phy->dev;
+	phy->phy.label		= "omap-usb2";
+	phy->phy.set_suspend	= omap_usb2_suspend;
+	phy->phy.otg		= otg;
+
+	phy->control_dev	= omap_control_get();
+	if (IS_ERR(phy->control_dev)) {
+		dev_err(&pdev->dev, "no control device present in system\n");
+		return PTR_ERR(phy->control_dev);
+	}
+
+	phy->is_suspended	= 1;
+	omap4_usb_phy_power(phy->control_dev, 0);
+
+	otg->set_host		= omap_usb_set_host;
+	otg->set_peripheral	= omap_usb_set_peripheral;
+	otg->set_vbus		= omap_usb_set_vbus;
+	otg->start_srp		= omap_usb_start_srp;
+	otg->phy		= &phy->phy;
+
+	phy->wkupclk = clk_get(phy->dev, "usb_phy_cm_clk32k");
+
+	usb_add_phy(&phy->phy, USB_PHY_TYPE_USB2);
+
+	platform_set_drvdata(pdev, phy);
+
+	pm_runtime_enable(phy->dev);
+
+	return 0;
+}
+
+static int __devexit omap_usb2_remove(struct platform_device *pdev)
+{
+	struct omap_usb	*phy = platform_get_drvdata(pdev);
+
+	usb_remove_phy(&phy->phy);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int omap_usb2_runtime_suspend(struct device *dev)
+{
+	struct platform_device	*pdev = to_platform_device(dev);
+	struct omap_usb	*phy = platform_get_drvdata(pdev);
+
+	clk_disable(phy->wkupclk);
+	omap4_usb_phy_power(phy->control_dev, 0);
+
+	return 0;
+}
+
+static int omap_usb2_runtime_resume(struct device *dev)
+{
+	struct platform_device	*pdev = to_platform_device(dev);
+	struct omap_usb	*phy = platform_get_drvdata(pdev);
+
+	omap4_usb_phy_power(phy->control_dev, 1);
+	clk_enable(phy->wkupclk);
+
+	return 0;
+}
+
+static const struct dev_pm_ops omap_usb2_pm_ops = {
+	SET_RUNTIME_PM_OPS(omap_usb2_runtime_suspend, omap_usb2_runtime_resume,
+		NULL)
+};
+
+#define DEV_PM_OPS     (&omap_usb2_pm_ops)
+#else
+#define DEV_PM_OPS     NULL
+#endif
+
+static struct platform_driver omap_usb2_driver = {
+	.probe		= omap_usb2_probe,
+	.remove		= __devexit_p(omap_usb2_remove),
+	.driver		= {
+		.name	= "omap-usb2",
+		.owner	= THIS_MODULE,
+		.pm	= DEV_PM_OPS,
+	},
+};
+
+static int __init usb2_omap_init(void)
+{
+	return platform_driver_register(&omap_usb2_driver);
+}
+arch_initcall(usb2_omap_init);
+
+static void __exit usb2_omap_exit(void)
+{
+	platform_driver_unregister(&omap_usb2_driver);
+}
+module_exit(usb2_omap_exit);
+
+MODULE_ALIAS("platform: omap_usb2");
+MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
+MODULE_DESCRIPTION("OMAP USB2 PHY DRIVER");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/usb/omap_usb.h b/include/linux/usb/omap_usb.h
new file mode 100644
index 0000000..8d781df
--- /dev/null
+++ b/include/linux/usb/omap_usb.h
@@ -0,0 +1,47 @@
+/*
+ * omap_usb.h -- omap usb2 phy header file
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef __DRIVERS_OMAP_USB2_H
+#define __DRIVERS_OMAP_USB2_H
+
+#include <linux/usb/otg.h>
+
+struct omap_usb {
+	struct usb_phy		phy;
+	struct phy_companion	*comparator;
+	struct device		*dev;
+	struct device		*control_dev;
+	struct clk		*wkupclk;
+	u8			is_suspended:1;
+};
+
+#define	phy_to_omapusb(x)	container_of((x), struct omap_usb, phy)
+
+#if defined(CONFIG_OMAP_USB2) || defined(CONFIG_OMAP_USB2_MODULE)
+void omap_usb2_set_comparator(struct phy_companion *comparator);
+#else
+static inline void omap_usb2_set_comparator(struct phy_companion *comparator)
+{
+}
+#endif
+
+#endif /* __DRIVERS_OMAP_USB_H */
diff --git a/include/linux/usb/phy_companion.h b/include/linux/usb/phy_companion.h
new file mode 100644
index 0000000..321290f
--- /dev/null
+++ b/include/linux/usb/phy_companion.h
@@ -0,0 +1,34 @@
+/*
+ * phy-companion.h -- phy companion to indicate the comparator part of PHY
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef __DRIVERS_PHY_COMPANION_H
+#define __DRIVERS_PHY_COMPANION_H
+
+#include <linux/usb/otg.h>
+
+/* phy_companion to take care of VBUS, ID and srp capabilities */
+struct phy_companion {
+
+	/* effective for A-peripheral, ignored for B devices */
+	int	(*set_vbus)(struct phy_companion *x, bool enabled);
+
+	/* for B devices only:  start session with A-Host */
+	int	(*start_srp)(struct phy_companion *x);
+};
+
+#endif /* __DRIVERS_PHY_COMPANION_H */
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH 1/3] drivers: usb: otg: add a new driver for omap usb2 phy
@ 2012-05-30 14:34   ` Kishon Vijay Abraham I
  0 siblings, 0 replies; 23+ messages in thread
From: Kishon Vijay Abraham I @ 2012-05-30 14:34 UTC (permalink / raw)
  To: linux-arm-kernel

All phy related programming like enabling/disabling the clocks, powering
on/off the phy is taken care of by this driver. It is also used for OTG
related functionality like srp.

Cc: Felipe Balbi <balbi@ti.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/usb/otg/Kconfig           |   17 ++-
 drivers/usb/otg/Makefile          |    1 +
 drivers/usb/otg/omap-usb2.c       |  232 +++++++++++++++++++++++++++++++++++++
 include/linux/usb/omap_usb.h      |   47 ++++++++
 include/linux/usb/phy_companion.h |   34 ++++++
 5 files changed, 327 insertions(+), 4 deletions(-)
 create mode 100644 drivers/usb/otg/omap-usb2.c
 create mode 100644 include/linux/usb/omap_usb.h
 create mode 100644 include/linux/usb/phy_companion.h

diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
index e2840f1..3264c0d 100644
--- a/drivers/usb/otg/Kconfig
+++ b/drivers/usb/otg/Kconfig
@@ -73,10 +73,8 @@ config TWL6030_USB
 	help
 	  Enable this to support the USB OTG transceiver on TWL6030
 	  family chips. This TWL6030 transceiver has the VBUS and ID GND
-	  and OTG SRP events capabilities. For all other transceiver functionality
-	  UTMI PHY is embedded in OMAP4430. The internal PHY configurations APIs
-	  are hooked to this driver through platform_data structure.
-	  The definition of internal PHY APIs are in the mach-omap2 layer.
+          and OTG SRP events capabilities. For all other transceiver
+	  functionality UTMI PHY is embedded in OMAP4430.
 
 config OMAP4_USB_PHY
 	tristate "Texas Instruments OMAP4+ USB pin control driver"
@@ -91,6 +89,17 @@ config OMAP4_USB_PHY
 	  performing the above mentioned configuration, API's are added in
 	  by this children of the control module driver.
 
+config OMAP_USB2
+	tristate "OMAP USB2 PHY Driver"
+	depends on OMAP_OCP2SCP
+	depends on OMAP4_USB_PHY
+	select USB_OTG_UTILS
+	help
+	  Enable this to support the transceiver that is part of SOC. This
+	  driver takes care of all the PHY functionality apart from comparator.
+	  The USB OTG controller communicates with the comparator using this
+	  driver.
+
 config NOP_USB_XCEIV
 	tristate "NOP USB Transceiver Driver"
 	select USB_OTG_UTILS
diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile
index 60c8c83..2f02912 100644
--- a/drivers/usb/otg/Makefile
+++ b/drivers/usb/otg/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_ISP1301_OMAP)	+= isp1301_omap.o
 obj-$(CONFIG_TWL4030_USB)	+= twl4030-usb.o
 obj-$(CONFIG_TWL6030_USB)	+= twl6030-usb.o
 obj-$(CONFIG_OMAP4_USB_PHY)	+= omap4-usb-phy.o
+obj-$(CONFIG_OMAP_USB2)		+= omap-usb2.o
 obj-$(CONFIG_NOP_USB_XCEIV)	+= nop-usb-xceiv.o
 obj-$(CONFIG_USB_ULPI)		+= ulpi.o
 obj-$(CONFIG_USB_ULPI_VIEWPORT)	+= ulpi_viewport.o
diff --git a/drivers/usb/otg/omap-usb2.c b/drivers/usb/otg/omap-usb2.c
new file mode 100644
index 0000000..ccd74b6
--- /dev/null
+++ b/drivers/usb/otg/omap-usb2.c
@@ -0,0 +1,232 @@
+/*
+ * omap-usb2.c - USB PHY, talking to musb controller in OMAP.
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/usb/omap_usb.h>
+#include <linux/usb/phy_companion.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
+#include <linux/mfd/omap_control.h>
+#include <linux/usb/omap4_usb_phy.h>
+
+/**
+ * omap_usb2_set_comparator - links the comparator present in the sytem with
+ *	this phy
+ * @comparator - the companion phy(comparator) for this phy
+ *
+ * The phy companion driver should call this API passing the phy_companion
+ * filled with set_vbus and start_srp to be used by usb phy.
+ *
+ * For use by phy companion driver
+ */
+void omap_usb2_set_comparator(struct phy_companion *comparator)
+{
+	struct usb_phy	*x = usb_get_phy(USB_PHY_TYPE_USB2);
+	struct omap_usb	*phy = phy_to_omapusb(x);
+
+	phy->comparator = comparator;
+}
+EXPORT_SYMBOL_GPL(omap_usb2_set_comparator);
+
+static int omap_usb_set_vbus(struct usb_otg *otg, bool enabled)
+{
+	struct omap_usb *phy = phy_to_omapusb(otg->phy);
+
+	if (!phy->comparator)
+		return -ENODEV;
+
+	return phy->comparator->set_vbus(phy->comparator, enabled);
+}
+
+static int omap_usb_start_srp(struct usb_otg *otg)
+{
+	struct omap_usb *phy = phy_to_omapusb(otg->phy);
+
+	if (!phy->comparator)
+		return -ENODEV;
+
+	return phy->comparator->start_srp(phy->comparator);
+}
+
+static int omap_usb_set_host(struct usb_otg *otg, struct usb_bus *host)
+{
+	struct usb_phy	*phy = otg->phy;
+
+	otg->host = host;
+	if (!host)
+		phy->state = OTG_STATE_UNDEFINED;
+
+	return 0;
+}
+
+static int omap_usb_set_peripheral(struct usb_otg *otg,
+		struct usb_gadget *gadget)
+{
+	struct usb_phy	*phy = otg->phy;
+
+	otg->gadget = gadget;
+	if (!gadget)
+		phy->state = OTG_STATE_UNDEFINED;
+
+	return 0;
+}
+
+static int omap_usb2_suspend(struct usb_phy *x, int suspend)
+{
+	struct omap_usb *phy = phy_to_omapusb(x);
+
+	if (suspend && !phy->is_suspended) {
+		pm_runtime_put_sync(phy->dev);
+		phy->is_suspended = 1;
+	} else if (!suspend && phy->is_suspended) {
+		pm_runtime_get_sync(phy->dev);
+		phy->is_suspended = 0;
+	}
+
+	return 0;
+}
+
+static int __devinit omap_usb2_probe(struct platform_device *pdev)
+{
+	struct omap_usb			*phy;
+	struct usb_otg			*otg;
+
+	phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
+	if (!phy) {
+		dev_err(&pdev->dev, "unable to allocate memory for USB2 PHY\n");
+		return -ENOMEM;
+	}
+
+	otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
+	if (!otg) {
+		dev_err(&pdev->dev, "unable to allocate memory for USB OTG\n");
+		return -ENOMEM;
+	}
+
+	phy->dev		= &pdev->dev;
+
+	phy->phy.dev		= phy->dev;
+	phy->phy.label		= "omap-usb2";
+	phy->phy.set_suspend	= omap_usb2_suspend;
+	phy->phy.otg		= otg;
+
+	phy->control_dev	= omap_control_get();
+	if (IS_ERR(phy->control_dev)) {
+		dev_err(&pdev->dev, "no control device present in system\n");
+		return PTR_ERR(phy->control_dev);
+	}
+
+	phy->is_suspended	= 1;
+	omap4_usb_phy_power(phy->control_dev, 0);
+
+	otg->set_host		= omap_usb_set_host;
+	otg->set_peripheral	= omap_usb_set_peripheral;
+	otg->set_vbus		= omap_usb_set_vbus;
+	otg->start_srp		= omap_usb_start_srp;
+	otg->phy		= &phy->phy;
+
+	phy->wkupclk = clk_get(phy->dev, "usb_phy_cm_clk32k");
+
+	usb_add_phy(&phy->phy, USB_PHY_TYPE_USB2);
+
+	platform_set_drvdata(pdev, phy);
+
+	pm_runtime_enable(phy->dev);
+
+	return 0;
+}
+
+static int __devexit omap_usb2_remove(struct platform_device *pdev)
+{
+	struct omap_usb	*phy = platform_get_drvdata(pdev);
+
+	usb_remove_phy(&phy->phy);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int omap_usb2_runtime_suspend(struct device *dev)
+{
+	struct platform_device	*pdev = to_platform_device(dev);
+	struct omap_usb	*phy = platform_get_drvdata(pdev);
+
+	clk_disable(phy->wkupclk);
+	omap4_usb_phy_power(phy->control_dev, 0);
+
+	return 0;
+}
+
+static int omap_usb2_runtime_resume(struct device *dev)
+{
+	struct platform_device	*pdev = to_platform_device(dev);
+	struct omap_usb	*phy = platform_get_drvdata(pdev);
+
+	omap4_usb_phy_power(phy->control_dev, 1);
+	clk_enable(phy->wkupclk);
+
+	return 0;
+}
+
+static const struct dev_pm_ops omap_usb2_pm_ops = {
+	SET_RUNTIME_PM_OPS(omap_usb2_runtime_suspend, omap_usb2_runtime_resume,
+		NULL)
+};
+
+#define DEV_PM_OPS     (&omap_usb2_pm_ops)
+#else
+#define DEV_PM_OPS     NULL
+#endif
+
+static struct platform_driver omap_usb2_driver = {
+	.probe		= omap_usb2_probe,
+	.remove		= __devexit_p(omap_usb2_remove),
+	.driver		= {
+		.name	= "omap-usb2",
+		.owner	= THIS_MODULE,
+		.pm	= DEV_PM_OPS,
+	},
+};
+
+static int __init usb2_omap_init(void)
+{
+	return platform_driver_register(&omap_usb2_driver);
+}
+arch_initcall(usb2_omap_init);
+
+static void __exit usb2_omap_exit(void)
+{
+	platform_driver_unregister(&omap_usb2_driver);
+}
+module_exit(usb2_omap_exit);
+
+MODULE_ALIAS("platform: omap_usb2");
+MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
+MODULE_DESCRIPTION("OMAP USB2 PHY DRIVER");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/usb/omap_usb.h b/include/linux/usb/omap_usb.h
new file mode 100644
index 0000000..8d781df
--- /dev/null
+++ b/include/linux/usb/omap_usb.h
@@ -0,0 +1,47 @@
+/*
+ * omap_usb.h -- omap usb2 phy header file
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef __DRIVERS_OMAP_USB2_H
+#define __DRIVERS_OMAP_USB2_H
+
+#include <linux/usb/otg.h>
+
+struct omap_usb {
+	struct usb_phy		phy;
+	struct phy_companion	*comparator;
+	struct device		*dev;
+	struct device		*control_dev;
+	struct clk		*wkupclk;
+	u8			is_suspended:1;
+};
+
+#define	phy_to_omapusb(x)	container_of((x), struct omap_usb, phy)
+
+#if defined(CONFIG_OMAP_USB2) || defined(CONFIG_OMAP_USB2_MODULE)
+void omap_usb2_set_comparator(struct phy_companion *comparator);
+#else
+static inline void omap_usb2_set_comparator(struct phy_companion *comparator)
+{
+}
+#endif
+
+#endif /* __DRIVERS_OMAP_USB_H */
diff --git a/include/linux/usb/phy_companion.h b/include/linux/usb/phy_companion.h
new file mode 100644
index 0000000..321290f
--- /dev/null
+++ b/include/linux/usb/phy_companion.h
@@ -0,0 +1,34 @@
+/*
+ * phy-companion.h -- phy companion to indicate the comparator part of PHY
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef __DRIVERS_PHY_COMPANION_H
+#define __DRIVERS_PHY_COMPANION_H
+
+#include <linux/usb/otg.h>
+
+/* phy_companion to take care of VBUS, ID and srp capabilities */
+struct phy_companion {
+
+	/* effective for A-peripheral, ignored for B devices */
+	int	(*set_vbus)(struct phy_companion *x, bool enabled);
+
+	/* for B devices only:  start session with A-Host */
+	int	(*start_srp)(struct phy_companion *x);
+};
+
+#endif /* __DRIVERS_PHY_COMPANION_H */
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH 2/3] usb: musb: omap glue: use omap-usb2 as the phy driver
  2012-05-30 14:34 ` Kishon Vijay Abraham I
  (?)
@ 2012-05-30 14:34   ` Kishon Vijay Abraham I
  -1 siblings, 0 replies; 23+ messages in thread
From: Kishon Vijay Abraham I @ 2012-05-30 14:34 UTC (permalink / raw)
  To: tony, linux, gregkh, kishon, linux-omap, linux-arm-kernel,
	linux-kernel, linux-usb, balbi

The twl6030 which was the phy driver (phy + comparator) is now
made only as comparator driver used for detecting VBUS and ID events
and reporting it to the glue using an export API created in omap musb
glue.

The MUSB should now use omap-usb2 as the phy driver.

Both twl6030 and twl4030 are made to use the export API from omap musb glue.

Cc: Felipe Balbi <balbi@ti.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 arch/arm/mach-omap2/usb-musb.c |    3 -
 drivers/usb/musb/musb_core.h   |    1 -
 drivers/usb/musb/omap2430.c    |  150 +++++++++++++++++++++++++----------
 drivers/usb/otg/twl4030-usb.c  |   40 +++------
 drivers/usb/otg/twl6030-usb.c  |  172 ++++++++--------------------------------
 include/linux/usb/musb-omap.h  |   31 +++++++
 6 files changed, 187 insertions(+), 210 deletions(-)
 create mode 100644 include/linux/usb/musb-omap.h

diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c
index 8d5ed77..8ada8cc 100644
--- a/arch/arm/mach-omap2/usb-musb.c
+++ b/arch/arm/mach-omap2/usb-musb.c
@@ -119,7 +119,4 @@ void __init usb_musb_init(struct omap_musb_board_data *musb_board_data)
 	dev->dma_mask = &musb_dmamask;
 	dev->coherent_dma_mask = musb_dmamask;
 	put_device(dev);
-
-	if (cpu_is_omap44xx())
-		omap4430_phy_init(dev);
 }
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index f4a40f0..0b0174b 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -327,7 +327,6 @@ struct musb {
 
 	irqreturn_t		(*isr)(int, void *);
 	struct work_struct	irq_work;
-	struct work_struct	otg_notifier_work;
 	u16			hwvers;
 
 /* this hub status bit is reserved by USB 2.0 and not seen by usbcore */
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index e279cf3..a94e13e 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -34,6 +34,9 @@
 #include <linux/dma-mapping.h>
 #include <linux/pm_runtime.h>
 #include <linux/err.h>
+#include <linux/usb/musb-omap.h>
+#include <linux/usb/omap4_usb_phy.h>
+#include <linux/mfd/omap_control.h>
 
 #include "musb_core.h"
 #include "omap2430.h"
@@ -41,9 +44,14 @@
 struct omap2430_glue {
 	struct device		*dev;
 	struct platform_device	*musb;
+	struct work_struct	omap_musb_mailbox_work;
+	struct device		*control_dev;
+	enum omap_musb_vbus_id_status status;
 };
 #define glue_to_musb(g)		platform_get_drvdata(g->musb)
 
+struct omap2430_glue		*_glue;
+
 static struct timer_list musb_idle_timer;
 
 static void musb_do_idle(unsigned long _musb)
@@ -223,68 +231,104 @@ static inline void omap2430_low_level_init(struct musb *musb)
 	musb_writel(musb->mregs, OTG_FORCESTDBY, l);
 }
 
-static int musb_otg_notifications(struct notifier_block *nb,
-		unsigned long event, void *unused)
+int omap_musb_mailbox(enum omap_musb_vbus_id_status status)
 {
-	struct musb	*musb = container_of(nb, struct musb, nb);
+	struct omap2430_glue	*glue = _glue;
+	struct musb		*musb = glue_to_musb(glue);
+
+	glue->status = status;
+	if (!musb) {
+		dev_err(glue->dev, "musb core is not yet ready\n");
+		return -ENODEV;
+	}
 
-	musb->xceiv_event = event;
-	schedule_work(&musb->otg_notifier_work);
+	schedule_work(&glue->omap_musb_mailbox_work);
 
-	return NOTIFY_OK;
+	return 0;
 }
 
-static void musb_otg_notifier_work(struct work_struct *data_notifier_work)
+static void omap_musb_set_mailbox(struct omap2430_glue *glue)
 {
-	struct musb *musb = container_of(data_notifier_work, struct musb, otg_notifier_work);
+	struct musb *musb = glue_to_musb(glue);
 	struct device *dev = musb->controller;
 	struct musb_hdrc_platform_data *pdata = dev->platform_data;
 	struct omap_musb_board_data *data = pdata->board_data;
+	struct usb_otg *otg = musb->xceiv->otg;
+	u32 val;
 
-	switch (musb->xceiv_event) {
-	case USB_EVENT_ID:
-		dev_dbg(musb->controller, "ID GND\n");
+	switch (glue->status) {
+	case OMAP_MUSB_ID_GROUND:
+		dev_dbg(dev, "ID GND\n");
 
+		otg->default_a = true;
+		musb->xceiv->state = OTG_STATE_A_IDLE;
+		musb->xceiv->last_event = USB_EVENT_ID;
 		if (!is_otg_enabled(musb) || musb->gadget_driver) {
-			pm_runtime_get_sync(musb->controller);
-			usb_phy_init(musb->xceiv);
+			pm_runtime_get_sync(dev);
+			if (glue->control_dev) {
+				val = AVALID | VBUSVALID;
+				omap4_usb_phy_mailbox(glue->control_dev, val);
+			}
 			omap2430_musb_set_vbus(musb, 1);
 		}
 		break;
 
-	case USB_EVENT_VBUS:
-		dev_dbg(musb->controller, "VBUS Connect\n");
+	case OMAP_MUSB_VBUS_VALID:
+		dev_dbg(dev, "VBUS Connect\n");
 
+		otg->default_a = false;
+		musb->xceiv->state = OTG_STATE_B_IDLE;
+		musb->xceiv->last_event = USB_EVENT_VBUS;
 		if (musb->gadget_driver)
-			pm_runtime_get_sync(musb->controller);
-		usb_phy_init(musb->xceiv);
+			pm_runtime_get_sync(dev);
+
+		if (glue->control_dev) {
+			val = IDDIG | AVALID | VBUSVALID;
+			omap4_usb_phy_mailbox(glue->control_dev, val);
+		}
 		break;
 
-	case USB_EVENT_NONE:
-		dev_dbg(musb->controller, "VBUS Disconnect\n");
+	case OMAP_MUSB_ID_FLOAT:
+	case OMAP_MUSB_VBUS_OFF:
+		dev_dbg(dev, "VBUS Disconnect\n");
+
+		musb->xceiv->last_event = USB_EVENT_NONE;
 
 		if (is_otg_enabled(musb) || is_peripheral_enabled(musb))
 			if (musb->gadget_driver) {
-				pm_runtime_mark_last_busy(musb->controller);
-				pm_runtime_put_autosuspend(musb->controller);
+				pm_runtime_mark_last_busy(dev);
+				pm_runtime_put_autosuspend(dev);
 			}
 
 		if (data->interface_type == MUSB_INTERFACE_UTMI) {
 			if (musb->xceiv->otg->set_vbus)
 				otg_set_vbus(musb->xceiv->otg, 0);
 		}
-		usb_phy_shutdown(musb->xceiv);
+
+		if (glue->control_dev) {
+			val = SESSEND | IDDIG;
+			omap4_usb_phy_mailbox(glue->control_dev, val);
+		}
 		break;
 	default:
-		dev_dbg(musb->controller, "ID float\n");
+		dev_dbg(dev, "ID float\n");
 	}
 }
 
+
+static void omap_musb_mailbox_work(struct work_struct *mailbox_work)
+{
+	struct omap2430_glue *glue = container_of(mailbox_work,
+				struct omap2430_glue, omap_musb_mailbox_work);
+	omap_musb_set_mailbox(glue);
+}
+
 static int omap2430_musb_init(struct musb *musb)
 {
 	u32 l;
 	int status = 0;
 	struct device *dev = musb->controller;
+	struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
 	struct musb_hdrc_platform_data *plat = dev->platform_data;
 	struct omap_musb_board_data *data = plat->board_data;
 
@@ -292,14 +336,12 @@ static int omap2430_musb_init(struct musb *musb)
 	 * up through ULPI.  TWL4030-family PMICs include one,
 	 * which needs a driver, drivers aren't always needed.
 	 */
-	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
+	musb->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
 	if (!musb->xceiv) {
 		pr_err("HS USB OTG: no transceiver configured\n");
 		return -ENODEV;
 	}
 
-	INIT_WORK(&musb->otg_notifier_work, musb_otg_notifier_work);
-
 	status = pm_runtime_get_sync(dev);
 	if (status < 0) {
 		dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status);
@@ -326,15 +368,14 @@ static int omap2430_musb_init(struct musb *musb)
 			musb_readl(musb->mregs, OTG_INTERFSEL),
 			musb_readl(musb->mregs, OTG_SIMENABLE));
 
-	musb->nb.notifier_call = musb_otg_notifications;
-	status = usb_register_notifier(musb->xceiv, &musb->nb);
-
-	if (status)
-		dev_dbg(musb->controller, "notification register failed\n");
+	usb_phy_init(musb->xceiv);
 
 	setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
 
-	pm_runtime_put_noidle(musb->controller);
+	if (glue->status != OMAP_MUSB_UNKNOWN)
+		omap_musb_set_mailbox(glue);
+
+	pm_runtime_put_sync(musb->controller);
 	return 0;
 
 err1:
@@ -343,16 +384,22 @@ err1:
 
 static void omap2430_musb_enable(struct musb *musb)
 {
+	u32		val;
 	u8		devctl;
 	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
 	struct device *dev = musb->controller;
+	struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
 	struct musb_hdrc_platform_data *pdata = dev->platform_data;
 	struct omap_musb_board_data *data = pdata->board_data;
 
-	switch (musb->xceiv->last_event) {
+	switch (glue->status) {
+
+	case OMAP_MUSB_ID_GROUND:
+		if (glue->control_dev) {
+			val = AVALID | VBUSVALID;
+			omap4_usb_phy_mailbox(glue->control_dev, val);
+		}
 
-	case USB_EVENT_ID:
-		usb_phy_init(musb->xceiv);
 		if (data->interface_type != MUSB_INTERFACE_UTMI)
 			break;
 		devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
@@ -370,8 +417,11 @@ static void omap2430_musb_enable(struct musb *musb)
 		}
 		break;
 
-	case USB_EVENT_VBUS:
-		usb_phy_init(musb->xceiv);
+	case OMAP_MUSB_VBUS_VALID:
+		if (glue->control_dev) {
+			val = IDDIG | AVALID | VBUSVALID;
+			omap4_usb_phy_mailbox(glue->control_dev, val);
+		}
 		break;
 
 	default:
@@ -381,17 +431,21 @@ static void omap2430_musb_enable(struct musb *musb)
 
 static void omap2430_musb_disable(struct musb *musb)
 {
-	if (musb->xceiv->last_event)
-		usb_phy_shutdown(musb->xceiv);
+	u32 val;
+	struct device *dev = musb->controller;
+	struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
+
+	if (musb->xceiv->last_event && glue->control_dev) {
+		val = SESSEND | IDDIG;
+		omap4_usb_phy_mailbox(glue->control_dev, val);
+	}
 }
 
 static int omap2430_musb_exit(struct musb *musb)
 {
 	del_timer_sync(&musb_idle_timer);
-	cancel_work_sync(&musb->otg_notifier_work);
 
 	omap2430_low_level_exit(musb);
-	usb_put_phy(musb->xceiv);
 
 	return 0;
 }
@@ -436,11 +490,21 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
 
 	glue->dev			= &pdev->dev;
 	glue->musb			= musb;
+	glue->status			= OMAP_MUSB_UNKNOWN;
+	glue->control_dev		= omap_control_get();
 
 	pdata->platform_ops		= &omap2430_ops;
 
 	platform_set_drvdata(pdev, glue);
 
+	/*
+	 * REVISIT if we ever have two instances of the wrapper, we will be
+	 * in big trouble
+	 */
+	_glue	= glue;
+
+	INIT_WORK(&glue->omap_musb_mailbox_work, omap_musb_mailbox_work);
+
 	ret = platform_device_add_resources(musb, pdev->resource,
 			pdev->num_resources);
 	if (ret) {
@@ -478,6 +542,8 @@ static int __devexit omap2430_remove(struct platform_device *pdev)
 {
 	struct omap2430_glue		*glue = platform_get_drvdata(pdev);
 
+	cancel_work_sync(&glue->omap_musb_mailbox_work);
+
 	platform_device_del(glue->musb);
 	platform_device_put(glue->musb);
 	kfree(glue);
@@ -546,7 +612,7 @@ static int __init omap2430_init(void)
 {
 	return platform_driver_register(&omap2430_driver);
 }
-module_init(omap2430_init);
+subsys_initcall(omap2430_init);
 
 static void __exit omap2430_exit(void)
 {
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c
index f8139b3..d9357d4 100644
--- a/drivers/usb/otg/twl4030-usb.c
+++ b/drivers/usb/otg/twl4030-usb.c
@@ -32,6 +32,7 @@
 #include <linux/workqueue.h>
 #include <linux/io.h>
 #include <linux/delay.h>
+#include <linux/usb/musb-omap.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
 #include <linux/i2c/twl.h>
@@ -159,10 +160,11 @@ struct twl4030_usb {
 	enum twl4030_usb_mode	usb_mode;
 
 	int			irq;
-	u8			linkstat;
 	bool			vbus_supplied;
 	u8			asleep;
 	bool			irq_enabled;
+
+	enum omap_musb_vbus_id_status prev_status;
 };
 
 /* internal define on top of container_of */
@@ -250,7 +252,6 @@ static enum usb_phy_events twl4030_usb_linkstat(struct twl4030_usb *twl)
 {
 	int	status;
 	int	linkstat = USB_EVENT_NONE;
-	struct usb_otg *otg = twl->phy.otg;
 
 	twl->vbus_supplied = false;
 
@@ -272,33 +273,21 @@ static enum usb_phy_events twl4030_usb_linkstat(struct twl4030_usb *twl)
 		if (status & (BIT(7)))
                         twl->vbus_supplied = true;
 
-		if (status & BIT(2))
+		if (status & BIT(2)) {
+			twl->prev_status = OMAP_MUSB_ID_GROUND;
 			linkstat = USB_EVENT_ID;
-		else
+		} else {
+			twl->prev_status = OMAP_MUSB_VBUS_VALID;
 			linkstat = USB_EVENT_VBUS;
-	} else
+		}
+	} else {
+		twl->prev_status = OMAP_MUSB_VBUS_OFF;
 		linkstat = USB_EVENT_NONE;
+	}
 
 	dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n",
 			status, status, linkstat);
 
-	twl->phy.last_event = linkstat;
-
-	/* REVISIT this assumes host and peripheral controllers
-	 * are registered, and that both are active...
-	 */
-
-	spin_lock_irq(&twl->lock);
-	twl->linkstat = linkstat;
-	if (linkstat == USB_EVENT_ID) {
-		otg->default_a = true;
-		twl->phy.state = OTG_STATE_A_IDLE;
-	} else {
-		otg->default_a = false;
-		twl->phy.state = OTG_STATE_B_IDLE;
-	}
-	spin_unlock_irq(&twl->lock);
-
 	return linkstat;
 }
 
@@ -521,8 +510,7 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
 		else
 			twl4030_phy_resume(twl);
 
-		atomic_notifier_call_chain(&twl->phy.notifier, status,
-				twl->phy.otg->gadget);
+		omap_musb_mailbox(twl->prev_status);
 	}
 	sysfs_notify(&twl->dev->kobj, NULL, "vbus");
 
@@ -543,8 +531,7 @@ static void twl4030_usb_phy_init(struct twl4030_usb *twl)
 			twl->asleep = 0;
 		}
 
-		atomic_notifier_call_chain(&twl->phy.notifier, status,
-				twl->phy.otg->gadget);
+		omap_musb_mailbox(twl->prev_status);
 	}
 	sysfs_notify(&twl->dev->kobj, NULL, "vbus");
 }
@@ -613,6 +600,7 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev)
 	twl->usb_mode		= pdata->usb_mode;
 	twl->vbus_supplied	= false;
 	twl->asleep		= 1;
+	twl->prev_status	= OMAP_MUSB_UNKNOWN;
 
 	twl->phy.dev		= twl->dev;
 	twl->phy.label		= "twl4030";
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c
index dbee00a..e3ac51f 100644
--- a/drivers/usb/otg/twl6030-usb.c
+++ b/drivers/usb/otg/twl6030-usb.c
@@ -26,10 +26,12 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/usb/otg.h>
+#include <linux/usb/phy_companion.h>
+#include <linux/usb/omap_usb.h>
+#include <linux/usb/musb-omap.h>
 #include <linux/i2c/twl.h>
 #include <linux/regulator/consumer.h>
 #include <linux/err.h>
-#include <linux/notifier.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 
@@ -87,7 +89,7 @@
 #define	VBUS_DET			BIT(2)
 
 struct twl6030_usb {
-	struct usb_phy		phy;
+	struct phy_companion	comparator;
 	struct device		*dev;
 
 	/* for vbus reporting with irqs disabled */
@@ -100,15 +102,16 @@ struct twl6030_usb {
 
 	int			irq1;
 	int			irq2;
-	u8			linkstat;
 	u8			asleep;
 	bool			irq_enabled;
 	bool			vbus_enable;
 	unsigned long		features;
-};
 
-#define phy_to_twl(x)		container_of((x), struct twl6030_usb, phy)
+	enum omap_musb_vbus_id_status prev_status;
+
+};
 
+#define	comparator_to_twl(x) container_of((x), struct twl6030_usb, comparator)
 /*-------------------------------------------------------------------------*/
 
 static inline int twl6030_writeb(struct twl6030_usb *twl, u8 module,
@@ -137,50 +140,9 @@ static inline u8 twl6030_readb(struct twl6030_usb *twl, u8 module, u8 address)
 	return ret;
 }
 
-static int twl6030_phy_init(struct usb_phy *x)
-{
-	struct twl6030_usb *twl;
-	struct device *dev;
-	struct twl4030_usb_data *pdata;
-
-	twl = phy_to_twl(x);
-	dev  = twl->dev;
-	pdata = dev->platform_data;
-
-	if (twl->linkstat == USB_EVENT_ID)
-		pdata->phy_power(twl->dev, 1, 1);
-	else
-		pdata->phy_power(twl->dev, 0, 1);
-
-	return 0;
-}
-
-static void twl6030_phy_shutdown(struct usb_phy *x)
-{
-	struct twl6030_usb *twl;
-	struct device *dev;
-	struct twl4030_usb_data *pdata;
-
-	twl = phy_to_twl(x);
-	dev  = twl->dev;
-	pdata = dev->platform_data;
-	pdata->phy_power(twl->dev, 0, 0);
-}
-
-static int twl6030_phy_suspend(struct usb_phy *x, int suspend)
-{
-	struct twl6030_usb *twl = phy_to_twl(x);
-	struct device *dev = twl->dev;
-	struct twl4030_usb_data *pdata = dev->platform_data;
-
-	pdata->phy_suspend(dev, suspend);
-
-	return 0;
-}
-
-static int twl6030_start_srp(struct usb_otg *otg)
+static int twl6030_start_srp(struct phy_companion *comparator)
 {
-	struct twl6030_usb *twl = phy_to_twl(otg->phy);
+	struct twl6030_usb *twl = comparator_to_twl(comparator);
 
 	twl6030_writeb(twl, TWL_MODULE_USB, 0x24, USB_VBUS_CTRL_SET);
 	twl6030_writeb(twl, TWL_MODULE_USB, 0x84, USB_VBUS_CTRL_SET);
@@ -234,14 +196,14 @@ static ssize_t twl6030_usb_vbus_show(struct device *dev,
 
 	spin_lock_irqsave(&twl->lock, flags);
 
-	switch (twl->linkstat) {
-	case USB_EVENT_VBUS:
+	switch (twl->prev_status) {
+	case OMAP_MUSB_VBUS_VALID:
 	       ret = snprintf(buf, PAGE_SIZE, "vbus\n");
 	       break;
-	case USB_EVENT_ID:
+	case OMAP_MUSB_ID_GROUND:
 	       ret = snprintf(buf, PAGE_SIZE, "id\n");
 	       break;
-	case USB_EVENT_NONE:
+	case OMAP_MUSB_VBUS_OFF:
 	       ret = snprintf(buf, PAGE_SIZE, "none\n");
 	       break;
 	default:
@@ -256,8 +218,7 @@ static DEVICE_ATTR(vbus, 0444, twl6030_usb_vbus_show, NULL);
 static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
 {
 	struct twl6030_usb *twl = _twl;
-	struct usb_otg *otg = twl->phy.otg;
-	int status;
+	int status = OMAP_MUSB_UNKNOWN;
 	u8 vbus_state, hw_state;
 
 	hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
@@ -268,25 +229,20 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
 		if (vbus_state & VBUS_DET) {
 			regulator_enable(twl->usb3v3);
 			twl->asleep = 1;
-			status = USB_EVENT_VBUS;
-			otg->default_a = false;
-			twl->phy.state = OTG_STATE_B_IDLE;
-			twl->linkstat = status;
-			twl->phy.last_event = status;
-			atomic_notifier_call_chain(&twl->phy.notifier,
-						status, otg->gadget);
+			status = OMAP_MUSB_VBUS_VALID;
+			omap_musb_mailbox(status);
 		} else {
-			status = USB_EVENT_NONE;
-			twl->linkstat = status;
-			twl->phy.last_event = status;
-			atomic_notifier_call_chain(&twl->phy.notifier,
-						status, otg->gadget);
-			if (twl->asleep) {
-				regulator_disable(twl->usb3v3);
-				twl->asleep = 0;
+			if (twl->prev_status != OMAP_MUSB_UNKNOWN) {
+				status = OMAP_MUSB_VBUS_OFF;
+				omap_musb_mailbox(status);
+				if (twl->asleep) {
+					regulator_disable(twl->usb3v3);
+					twl->asleep = 0;
+				}
 			}
 		}
 	}
+	twl->prev_status = status;
 	sysfs_notify(&twl->dev->kobj, NULL, "vbus");
 
 	return IRQ_HANDLED;
@@ -295,7 +251,6 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
 static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
 {
 	struct twl6030_usb *twl = _twl;
-	struct usb_otg *otg = twl->phy.otg;
 	int status = USB_EVENT_NONE;
 	u8 hw_state;
 
@@ -309,12 +264,7 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
 		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET,
 								0x10);
 		status = USB_EVENT_ID;
-		otg->default_a = true;
-		twl->phy.state = OTG_STATE_A_IDLE;
-		twl->linkstat = status;
-		twl->phy.last_event = status;
-		atomic_notifier_call_chain(&twl->phy.notifier, status,
-							otg->gadget);
+		omap_musb_mailbox(OMAP_MUSB_ID_GROUND);
 	} else  {
 		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR,
 								0x10);
@@ -326,23 +276,8 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
 	return IRQ_HANDLED;
 }
 
-static int twl6030_set_peripheral(struct usb_otg *otg,
-		struct usb_gadget *gadget)
-{
-	if (!otg)
-		return -ENODEV;
-
-	otg->gadget = gadget;
-	if (!gadget)
-		otg->phy->state = OTG_STATE_UNDEFINED;
-
-	return 0;
-}
-
-static int twl6030_enable_irq(struct usb_phy *x)
+static int twl6030_enable_irq(struct twl6030_usb *twl)
 {
-	struct twl6030_usb *twl = phy_to_twl(x);
-
 	twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET, 0x1);
 	twl6030_interrupt_unmask(0x05, REG_INT_MSK_LINE_C);
 	twl6030_interrupt_unmask(0x05, REG_INT_MSK_STS_C);
@@ -375,9 +310,9 @@ static void otg_set_vbus_work(struct work_struct *data)
 							CHARGERUSB_CTRL1);
 }
 
-static int twl6030_set_vbus(struct usb_otg *otg, bool enabled)
+static int twl6030_set_vbus(struct phy_companion *comparator, bool enabled)
 {
-	struct twl6030_usb *twl = phy_to_twl(otg->phy);
+	struct twl6030_usb *twl = comparator_to_twl(comparator);
 
 	twl->vbus_enable = enabled;
 	schedule_work(&twl->set_vbus_work);
@@ -385,23 +320,11 @@ static int twl6030_set_vbus(struct usb_otg *otg, bool enabled)
 	return 0;
 }
 
-static int twl6030_set_host(struct usb_otg *otg, struct usb_bus *host)
-{
-	if (!otg)
-		return -ENODEV;
-
-	otg->host = host;
-	if (!host)
-		otg->phy->state = OTG_STATE_UNDEFINED;
-	return 0;
-}
-
 static int __devinit twl6030_usb_probe(struct platform_device *pdev)
 {
 	struct twl6030_usb	*twl;
 	int			status, err;
 	struct twl4030_usb_data *pdata;
-	struct usb_otg		*otg;
 	struct device *dev = &pdev->dev;
 	pdata = dev->platform_data;
 
@@ -409,29 +332,16 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
 	if (!twl)
 		return -ENOMEM;
 
-	otg = kzalloc(sizeof *otg, GFP_KERNEL);
-	if (!otg) {
-		kfree(twl);
-		return -ENOMEM;
-	}
-
 	twl->dev		= &pdev->dev;
 	twl->irq1		= platform_get_irq(pdev, 0);
 	twl->irq2		= platform_get_irq(pdev, 1);
 	twl->features		= pdata->features;
+	twl->prev_status	= OMAP_MUSB_UNKNOWN;
 
-	twl->phy.dev		= twl->dev;
-	twl->phy.label		= "twl6030";
-	twl->phy.otg		= otg;
-	twl->phy.init		= twl6030_phy_init;
-	twl->phy.shutdown	= twl6030_phy_shutdown;
-	twl->phy.set_suspend	= twl6030_phy_suspend;
+	twl->comparator.set_vbus	= twl6030_set_vbus;
+	twl->comparator.start_srp	= twl6030_start_srp;
 
-	otg->phy		= &twl->phy;
-	otg->set_host		= twl6030_set_host;
-	otg->set_peripheral	= twl6030_set_peripheral;
-	otg->set_vbus		= twl6030_set_vbus;
-	otg->start_srp		= twl6030_start_srp;
+	omap_usb2_set_comparator(&twl->comparator);
 
 	/* init spinlock for workqueue */
 	spin_lock_init(&twl->lock);
@@ -439,18 +349,14 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
 	err = twl6030_usb_ldo_init(twl);
 	if (err) {
 		dev_err(&pdev->dev, "ldo init failed\n");
-		kfree(otg);
 		kfree(twl);
 		return err;
 	}
-	usb_add_phy(&twl->phy, USB_PHY_TYPE_USB2);
 
 	platform_set_drvdata(pdev, twl);
 	if (device_create_file(&pdev->dev, &dev_attr_vbus))
 		dev_warn(&pdev->dev, "could not create sysfs file\n");
 
-	ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier);
-
 	INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work);
 
 	twl->irq_enabled = true;
@@ -461,7 +367,6 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
 			twl->irq1, status);
 		device_remove_file(twl->dev, &dev_attr_vbus);
-		kfree(otg);
 		kfree(twl);
 		return status;
 	}
@@ -474,15 +379,12 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
 			twl->irq2, status);
 		free_irq(twl->irq1, twl);
 		device_remove_file(twl->dev, &dev_attr_vbus);
-		kfree(otg);
 		kfree(twl);
 		return status;
 	}
 
 	twl->asleep = 0;
-	pdata->phy_init(dev);
-	twl6030_phy_suspend(&twl->phy, 0);
-	twl6030_enable_irq(&twl->phy);
+	twl6030_enable_irq(twl);
 	dev_info(&pdev->dev, "Initialized TWL6030 USB module\n");
 
 	return 0;
@@ -492,10 +394,6 @@ static int __exit twl6030_usb_remove(struct platform_device *pdev)
 {
 	struct twl6030_usb *twl = platform_get_drvdata(pdev);
 
-	struct twl4030_usb_data *pdata;
-	struct device *dev = &pdev->dev;
-	pdata = dev->platform_data;
-
 	twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
 		REG_INT_MSK_LINE_C);
 	twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
@@ -503,10 +401,8 @@ static int __exit twl6030_usb_remove(struct platform_device *pdev)
 	free_irq(twl->irq1, twl);
 	free_irq(twl->irq2, twl);
 	regulator_put(twl->usb3v3);
-	pdata->phy_exit(twl->dev);
 	device_remove_file(twl->dev, &dev_attr_vbus);
 	cancel_work_sync(&twl->set_vbus_work);
-	kfree(twl->phy.otg);
 	kfree(twl);
 
 	return 0;
diff --git a/include/linux/usb/musb-omap.h b/include/linux/usb/musb-omap.h
new file mode 100644
index 0000000..c84224c
--- /dev/null
+++ b/include/linux/usb/musb-omap.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011-2012 by Texas Instruments
+ *
+ * The Inventra Controller Driver for Linux is free software; you
+ * can redistribute it and/or modify it under the terms of the GNU
+ * General Public License version 2 as published by the Free Software
+ * Foundation.
+ */
+
+#ifndef __MUSB_OMAP_H__
+#define __MUSB_OMAP_H__
+
+enum omap_musb_vbus_id_status {
+	OMAP_MUSB_UNKNOWN = 0,
+	OMAP_MUSB_ID_GROUND,
+	OMAP_MUSB_ID_FLOAT,
+	OMAP_MUSB_VBUS_VALID,
+	OMAP_MUSB_VBUS_OFF,
+};
+
+#if (defined(CONFIG_USB_MUSB_OMAP2PLUS) || \
+				defined(CONFIG_USB_MUSB_OMAP2PLUS_MODULE))
+int omap_musb_mailbox(enum omap_musb_vbus_id_status status);
+#else
+static inline int omap_musb_mailbox(enum omap_musb_vbus_id_status status)
+{
+	return -EINVAL;
+}
+#endif
+
+#endif	/* __MUSB_OMAP_H__ */
-- 
1.7.5.4


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH 2/3] usb: musb: omap glue: use omap-usb2 as the phy driver
@ 2012-05-30 14:34   ` Kishon Vijay Abraham I
  0 siblings, 0 replies; 23+ messages in thread
From: Kishon Vijay Abraham I @ 2012-05-30 14:34 UTC (permalink / raw)
  To: tony, linux, gregkh, kishon, linux-omap, linux-arm-kernel,
	linux-kernel, linux-usb, balbi

The twl6030 which was the phy driver (phy + comparator) is now
made only as comparator driver used for detecting VBUS and ID events
and reporting it to the glue using an export API created in omap musb
glue.

The MUSB should now use omap-usb2 as the phy driver.

Both twl6030 and twl4030 are made to use the export API from omap musb glue.

Cc: Felipe Balbi <balbi@ti.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 arch/arm/mach-omap2/usb-musb.c |    3 -
 drivers/usb/musb/musb_core.h   |    1 -
 drivers/usb/musb/omap2430.c    |  150 +++++++++++++++++++++++++----------
 drivers/usb/otg/twl4030-usb.c  |   40 +++------
 drivers/usb/otg/twl6030-usb.c  |  172 ++++++++--------------------------------
 include/linux/usb/musb-omap.h  |   31 +++++++
 6 files changed, 187 insertions(+), 210 deletions(-)
 create mode 100644 include/linux/usb/musb-omap.h

diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c
index 8d5ed77..8ada8cc 100644
--- a/arch/arm/mach-omap2/usb-musb.c
+++ b/arch/arm/mach-omap2/usb-musb.c
@@ -119,7 +119,4 @@ void __init usb_musb_init(struct omap_musb_board_data *musb_board_data)
 	dev->dma_mask = &musb_dmamask;
 	dev->coherent_dma_mask = musb_dmamask;
 	put_device(dev);
-
-	if (cpu_is_omap44xx())
-		omap4430_phy_init(dev);
 }
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index f4a40f0..0b0174b 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -327,7 +327,6 @@ struct musb {
 
 	irqreturn_t		(*isr)(int, void *);
 	struct work_struct	irq_work;
-	struct work_struct	otg_notifier_work;
 	u16			hwvers;
 
 /* this hub status bit is reserved by USB 2.0 and not seen by usbcore */
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index e279cf3..a94e13e 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -34,6 +34,9 @@
 #include <linux/dma-mapping.h>
 #include <linux/pm_runtime.h>
 #include <linux/err.h>
+#include <linux/usb/musb-omap.h>
+#include <linux/usb/omap4_usb_phy.h>
+#include <linux/mfd/omap_control.h>
 
 #include "musb_core.h"
 #include "omap2430.h"
@@ -41,9 +44,14 @@
 struct omap2430_glue {
 	struct device		*dev;
 	struct platform_device	*musb;
+	struct work_struct	omap_musb_mailbox_work;
+	struct device		*control_dev;
+	enum omap_musb_vbus_id_status status;
 };
 #define glue_to_musb(g)		platform_get_drvdata(g->musb)
 
+struct omap2430_glue		*_glue;
+
 static struct timer_list musb_idle_timer;
 
 static void musb_do_idle(unsigned long _musb)
@@ -223,68 +231,104 @@ static inline void omap2430_low_level_init(struct musb *musb)
 	musb_writel(musb->mregs, OTG_FORCESTDBY, l);
 }
 
-static int musb_otg_notifications(struct notifier_block *nb,
-		unsigned long event, void *unused)
+int omap_musb_mailbox(enum omap_musb_vbus_id_status status)
 {
-	struct musb	*musb = container_of(nb, struct musb, nb);
+	struct omap2430_glue	*glue = _glue;
+	struct musb		*musb = glue_to_musb(glue);
+
+	glue->status = status;
+	if (!musb) {
+		dev_err(glue->dev, "musb core is not yet ready\n");
+		return -ENODEV;
+	}
 
-	musb->xceiv_event = event;
-	schedule_work(&musb->otg_notifier_work);
+	schedule_work(&glue->omap_musb_mailbox_work);
 
-	return NOTIFY_OK;
+	return 0;
 }
 
-static void musb_otg_notifier_work(struct work_struct *data_notifier_work)
+static void omap_musb_set_mailbox(struct omap2430_glue *glue)
 {
-	struct musb *musb = container_of(data_notifier_work, struct musb, otg_notifier_work);
+	struct musb *musb = glue_to_musb(glue);
 	struct device *dev = musb->controller;
 	struct musb_hdrc_platform_data *pdata = dev->platform_data;
 	struct omap_musb_board_data *data = pdata->board_data;
+	struct usb_otg *otg = musb->xceiv->otg;
+	u32 val;
 
-	switch (musb->xceiv_event) {
-	case USB_EVENT_ID:
-		dev_dbg(musb->controller, "ID GND\n");
+	switch (glue->status) {
+	case OMAP_MUSB_ID_GROUND:
+		dev_dbg(dev, "ID GND\n");
 
+		otg->default_a = true;
+		musb->xceiv->state = OTG_STATE_A_IDLE;
+		musb->xceiv->last_event = USB_EVENT_ID;
 		if (!is_otg_enabled(musb) || musb->gadget_driver) {
-			pm_runtime_get_sync(musb->controller);
-			usb_phy_init(musb->xceiv);
+			pm_runtime_get_sync(dev);
+			if (glue->control_dev) {
+				val = AVALID | VBUSVALID;
+				omap4_usb_phy_mailbox(glue->control_dev, val);
+			}
 			omap2430_musb_set_vbus(musb, 1);
 		}
 		break;
 
-	case USB_EVENT_VBUS:
-		dev_dbg(musb->controller, "VBUS Connect\n");
+	case OMAP_MUSB_VBUS_VALID:
+		dev_dbg(dev, "VBUS Connect\n");
 
+		otg->default_a = false;
+		musb->xceiv->state = OTG_STATE_B_IDLE;
+		musb->xceiv->last_event = USB_EVENT_VBUS;
 		if (musb->gadget_driver)
-			pm_runtime_get_sync(musb->controller);
-		usb_phy_init(musb->xceiv);
+			pm_runtime_get_sync(dev);
+
+		if (glue->control_dev) {
+			val = IDDIG | AVALID | VBUSVALID;
+			omap4_usb_phy_mailbox(glue->control_dev, val);
+		}
 		break;
 
-	case USB_EVENT_NONE:
-		dev_dbg(musb->controller, "VBUS Disconnect\n");
+	case OMAP_MUSB_ID_FLOAT:
+	case OMAP_MUSB_VBUS_OFF:
+		dev_dbg(dev, "VBUS Disconnect\n");
+
+		musb->xceiv->last_event = USB_EVENT_NONE;
 
 		if (is_otg_enabled(musb) || is_peripheral_enabled(musb))
 			if (musb->gadget_driver) {
-				pm_runtime_mark_last_busy(musb->controller);
-				pm_runtime_put_autosuspend(musb->controller);
+				pm_runtime_mark_last_busy(dev);
+				pm_runtime_put_autosuspend(dev);
 			}
 
 		if (data->interface_type == MUSB_INTERFACE_UTMI) {
 			if (musb->xceiv->otg->set_vbus)
 				otg_set_vbus(musb->xceiv->otg, 0);
 		}
-		usb_phy_shutdown(musb->xceiv);
+
+		if (glue->control_dev) {
+			val = SESSEND | IDDIG;
+			omap4_usb_phy_mailbox(glue->control_dev, val);
+		}
 		break;
 	default:
-		dev_dbg(musb->controller, "ID float\n");
+		dev_dbg(dev, "ID float\n");
 	}
 }
 
+
+static void omap_musb_mailbox_work(struct work_struct *mailbox_work)
+{
+	struct omap2430_glue *glue = container_of(mailbox_work,
+				struct omap2430_glue, omap_musb_mailbox_work);
+	omap_musb_set_mailbox(glue);
+}
+
 static int omap2430_musb_init(struct musb *musb)
 {
 	u32 l;
 	int status = 0;
 	struct device *dev = musb->controller;
+	struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
 	struct musb_hdrc_platform_data *plat = dev->platform_data;
 	struct omap_musb_board_data *data = plat->board_data;
 
@@ -292,14 +336,12 @@ static int omap2430_musb_init(struct musb *musb)
 	 * up through ULPI.  TWL4030-family PMICs include one,
 	 * which needs a driver, drivers aren't always needed.
 	 */
-	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
+	musb->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
 	if (!musb->xceiv) {
 		pr_err("HS USB OTG: no transceiver configured\n");
 		return -ENODEV;
 	}
 
-	INIT_WORK(&musb->otg_notifier_work, musb_otg_notifier_work);
-
 	status = pm_runtime_get_sync(dev);
 	if (status < 0) {
 		dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status);
@@ -326,15 +368,14 @@ static int omap2430_musb_init(struct musb *musb)
 			musb_readl(musb->mregs, OTG_INTERFSEL),
 			musb_readl(musb->mregs, OTG_SIMENABLE));
 
-	musb->nb.notifier_call = musb_otg_notifications;
-	status = usb_register_notifier(musb->xceiv, &musb->nb);
-
-	if (status)
-		dev_dbg(musb->controller, "notification register failed\n");
+	usb_phy_init(musb->xceiv);
 
 	setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
 
-	pm_runtime_put_noidle(musb->controller);
+	if (glue->status != OMAP_MUSB_UNKNOWN)
+		omap_musb_set_mailbox(glue);
+
+	pm_runtime_put_sync(musb->controller);
 	return 0;
 
 err1:
@@ -343,16 +384,22 @@ err1:
 
 static void omap2430_musb_enable(struct musb *musb)
 {
+	u32		val;
 	u8		devctl;
 	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
 	struct device *dev = musb->controller;
+	struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
 	struct musb_hdrc_platform_data *pdata = dev->platform_data;
 	struct omap_musb_board_data *data = pdata->board_data;
 
-	switch (musb->xceiv->last_event) {
+	switch (glue->status) {
+
+	case OMAP_MUSB_ID_GROUND:
+		if (glue->control_dev) {
+			val = AVALID | VBUSVALID;
+			omap4_usb_phy_mailbox(glue->control_dev, val);
+		}
 
-	case USB_EVENT_ID:
-		usb_phy_init(musb->xceiv);
 		if (data->interface_type != MUSB_INTERFACE_UTMI)
 			break;
 		devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
@@ -370,8 +417,11 @@ static void omap2430_musb_enable(struct musb *musb)
 		}
 		break;
 
-	case USB_EVENT_VBUS:
-		usb_phy_init(musb->xceiv);
+	case OMAP_MUSB_VBUS_VALID:
+		if (glue->control_dev) {
+			val = IDDIG | AVALID | VBUSVALID;
+			omap4_usb_phy_mailbox(glue->control_dev, val);
+		}
 		break;
 
 	default:
@@ -381,17 +431,21 @@ static void omap2430_musb_enable(struct musb *musb)
 
 static void omap2430_musb_disable(struct musb *musb)
 {
-	if (musb->xceiv->last_event)
-		usb_phy_shutdown(musb->xceiv);
+	u32 val;
+	struct device *dev = musb->controller;
+	struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
+
+	if (musb->xceiv->last_event && glue->control_dev) {
+		val = SESSEND | IDDIG;
+		omap4_usb_phy_mailbox(glue->control_dev, val);
+	}
 }
 
 static int omap2430_musb_exit(struct musb *musb)
 {
 	del_timer_sync(&musb_idle_timer);
-	cancel_work_sync(&musb->otg_notifier_work);
 
 	omap2430_low_level_exit(musb);
-	usb_put_phy(musb->xceiv);
 
 	return 0;
 }
@@ -436,11 +490,21 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
 
 	glue->dev			= &pdev->dev;
 	glue->musb			= musb;
+	glue->status			= OMAP_MUSB_UNKNOWN;
+	glue->control_dev		= omap_control_get();
 
 	pdata->platform_ops		= &omap2430_ops;
 
 	platform_set_drvdata(pdev, glue);
 
+	/*
+	 * REVISIT if we ever have two instances of the wrapper, we will be
+	 * in big trouble
+	 */
+	_glue	= glue;
+
+	INIT_WORK(&glue->omap_musb_mailbox_work, omap_musb_mailbox_work);
+
 	ret = platform_device_add_resources(musb, pdev->resource,
 			pdev->num_resources);
 	if (ret) {
@@ -478,6 +542,8 @@ static int __devexit omap2430_remove(struct platform_device *pdev)
 {
 	struct omap2430_glue		*glue = platform_get_drvdata(pdev);
 
+	cancel_work_sync(&glue->omap_musb_mailbox_work);
+
 	platform_device_del(glue->musb);
 	platform_device_put(glue->musb);
 	kfree(glue);
@@ -546,7 +612,7 @@ static int __init omap2430_init(void)
 {
 	return platform_driver_register(&omap2430_driver);
 }
-module_init(omap2430_init);
+subsys_initcall(omap2430_init);
 
 static void __exit omap2430_exit(void)
 {
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c
index f8139b3..d9357d4 100644
--- a/drivers/usb/otg/twl4030-usb.c
+++ b/drivers/usb/otg/twl4030-usb.c
@@ -32,6 +32,7 @@
 #include <linux/workqueue.h>
 #include <linux/io.h>
 #include <linux/delay.h>
+#include <linux/usb/musb-omap.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
 #include <linux/i2c/twl.h>
@@ -159,10 +160,11 @@ struct twl4030_usb {
 	enum twl4030_usb_mode	usb_mode;
 
 	int			irq;
-	u8			linkstat;
 	bool			vbus_supplied;
 	u8			asleep;
 	bool			irq_enabled;
+
+	enum omap_musb_vbus_id_status prev_status;
 };
 
 /* internal define on top of container_of */
@@ -250,7 +252,6 @@ static enum usb_phy_events twl4030_usb_linkstat(struct twl4030_usb *twl)
 {
 	int	status;
 	int	linkstat = USB_EVENT_NONE;
-	struct usb_otg *otg = twl->phy.otg;
 
 	twl->vbus_supplied = false;
 
@@ -272,33 +273,21 @@ static enum usb_phy_events twl4030_usb_linkstat(struct twl4030_usb *twl)
 		if (status & (BIT(7)))
                         twl->vbus_supplied = true;
 
-		if (status & BIT(2))
+		if (status & BIT(2)) {
+			twl->prev_status = OMAP_MUSB_ID_GROUND;
 			linkstat = USB_EVENT_ID;
-		else
+		} else {
+			twl->prev_status = OMAP_MUSB_VBUS_VALID;
 			linkstat = USB_EVENT_VBUS;
-	} else
+		}
+	} else {
+		twl->prev_status = OMAP_MUSB_VBUS_OFF;
 		linkstat = USB_EVENT_NONE;
+	}
 
 	dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n",
 			status, status, linkstat);
 
-	twl->phy.last_event = linkstat;
-
-	/* REVISIT this assumes host and peripheral controllers
-	 * are registered, and that both are active...
-	 */
-
-	spin_lock_irq(&twl->lock);
-	twl->linkstat = linkstat;
-	if (linkstat == USB_EVENT_ID) {
-		otg->default_a = true;
-		twl->phy.state = OTG_STATE_A_IDLE;
-	} else {
-		otg->default_a = false;
-		twl->phy.state = OTG_STATE_B_IDLE;
-	}
-	spin_unlock_irq(&twl->lock);
-
 	return linkstat;
 }
 
@@ -521,8 +510,7 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
 		else
 			twl4030_phy_resume(twl);
 
-		atomic_notifier_call_chain(&twl->phy.notifier, status,
-				twl->phy.otg->gadget);
+		omap_musb_mailbox(twl->prev_status);
 	}
 	sysfs_notify(&twl->dev->kobj, NULL, "vbus");
 
@@ -543,8 +531,7 @@ static void twl4030_usb_phy_init(struct twl4030_usb *twl)
 			twl->asleep = 0;
 		}
 
-		atomic_notifier_call_chain(&twl->phy.notifier, status,
-				twl->phy.otg->gadget);
+		omap_musb_mailbox(twl->prev_status);
 	}
 	sysfs_notify(&twl->dev->kobj, NULL, "vbus");
 }
@@ -613,6 +600,7 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev)
 	twl->usb_mode		= pdata->usb_mode;
 	twl->vbus_supplied	= false;
 	twl->asleep		= 1;
+	twl->prev_status	= OMAP_MUSB_UNKNOWN;
 
 	twl->phy.dev		= twl->dev;
 	twl->phy.label		= "twl4030";
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c
index dbee00a..e3ac51f 100644
--- a/drivers/usb/otg/twl6030-usb.c
+++ b/drivers/usb/otg/twl6030-usb.c
@@ -26,10 +26,12 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/usb/otg.h>
+#include <linux/usb/phy_companion.h>
+#include <linux/usb/omap_usb.h>
+#include <linux/usb/musb-omap.h>
 #include <linux/i2c/twl.h>
 #include <linux/regulator/consumer.h>
 #include <linux/err.h>
-#include <linux/notifier.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 
@@ -87,7 +89,7 @@
 #define	VBUS_DET			BIT(2)
 
 struct twl6030_usb {
-	struct usb_phy		phy;
+	struct phy_companion	comparator;
 	struct device		*dev;
 
 	/* for vbus reporting with irqs disabled */
@@ -100,15 +102,16 @@ struct twl6030_usb {
 
 	int			irq1;
 	int			irq2;
-	u8			linkstat;
 	u8			asleep;
 	bool			irq_enabled;
 	bool			vbus_enable;
 	unsigned long		features;
-};
 
-#define phy_to_twl(x)		container_of((x), struct twl6030_usb, phy)
+	enum omap_musb_vbus_id_status prev_status;
+
+};
 
+#define	comparator_to_twl(x) container_of((x), struct twl6030_usb, comparator)
 /*-------------------------------------------------------------------------*/
 
 static inline int twl6030_writeb(struct twl6030_usb *twl, u8 module,
@@ -137,50 +140,9 @@ static inline u8 twl6030_readb(struct twl6030_usb *twl, u8 module, u8 address)
 	return ret;
 }
 
-static int twl6030_phy_init(struct usb_phy *x)
-{
-	struct twl6030_usb *twl;
-	struct device *dev;
-	struct twl4030_usb_data *pdata;
-
-	twl = phy_to_twl(x);
-	dev  = twl->dev;
-	pdata = dev->platform_data;
-
-	if (twl->linkstat == USB_EVENT_ID)
-		pdata->phy_power(twl->dev, 1, 1);
-	else
-		pdata->phy_power(twl->dev, 0, 1);
-
-	return 0;
-}
-
-static void twl6030_phy_shutdown(struct usb_phy *x)
-{
-	struct twl6030_usb *twl;
-	struct device *dev;
-	struct twl4030_usb_data *pdata;
-
-	twl = phy_to_twl(x);
-	dev  = twl->dev;
-	pdata = dev->platform_data;
-	pdata->phy_power(twl->dev, 0, 0);
-}
-
-static int twl6030_phy_suspend(struct usb_phy *x, int suspend)
-{
-	struct twl6030_usb *twl = phy_to_twl(x);
-	struct device *dev = twl->dev;
-	struct twl4030_usb_data *pdata = dev->platform_data;
-
-	pdata->phy_suspend(dev, suspend);
-
-	return 0;
-}
-
-static int twl6030_start_srp(struct usb_otg *otg)
+static int twl6030_start_srp(struct phy_companion *comparator)
 {
-	struct twl6030_usb *twl = phy_to_twl(otg->phy);
+	struct twl6030_usb *twl = comparator_to_twl(comparator);
 
 	twl6030_writeb(twl, TWL_MODULE_USB, 0x24, USB_VBUS_CTRL_SET);
 	twl6030_writeb(twl, TWL_MODULE_USB, 0x84, USB_VBUS_CTRL_SET);
@@ -234,14 +196,14 @@ static ssize_t twl6030_usb_vbus_show(struct device *dev,
 
 	spin_lock_irqsave(&twl->lock, flags);
 
-	switch (twl->linkstat) {
-	case USB_EVENT_VBUS:
+	switch (twl->prev_status) {
+	case OMAP_MUSB_VBUS_VALID:
 	       ret = snprintf(buf, PAGE_SIZE, "vbus\n");
 	       break;
-	case USB_EVENT_ID:
+	case OMAP_MUSB_ID_GROUND:
 	       ret = snprintf(buf, PAGE_SIZE, "id\n");
 	       break;
-	case USB_EVENT_NONE:
+	case OMAP_MUSB_VBUS_OFF:
 	       ret = snprintf(buf, PAGE_SIZE, "none\n");
 	       break;
 	default:
@@ -256,8 +218,7 @@ static DEVICE_ATTR(vbus, 0444, twl6030_usb_vbus_show, NULL);
 static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
 {
 	struct twl6030_usb *twl = _twl;
-	struct usb_otg *otg = twl->phy.otg;
-	int status;
+	int status = OMAP_MUSB_UNKNOWN;
 	u8 vbus_state, hw_state;
 
 	hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
@@ -268,25 +229,20 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
 		if (vbus_state & VBUS_DET) {
 			regulator_enable(twl->usb3v3);
 			twl->asleep = 1;
-			status = USB_EVENT_VBUS;
-			otg->default_a = false;
-			twl->phy.state = OTG_STATE_B_IDLE;
-			twl->linkstat = status;
-			twl->phy.last_event = status;
-			atomic_notifier_call_chain(&twl->phy.notifier,
-						status, otg->gadget);
+			status = OMAP_MUSB_VBUS_VALID;
+			omap_musb_mailbox(status);
 		} else {
-			status = USB_EVENT_NONE;
-			twl->linkstat = status;
-			twl->phy.last_event = status;
-			atomic_notifier_call_chain(&twl->phy.notifier,
-						status, otg->gadget);
-			if (twl->asleep) {
-				regulator_disable(twl->usb3v3);
-				twl->asleep = 0;
+			if (twl->prev_status != OMAP_MUSB_UNKNOWN) {
+				status = OMAP_MUSB_VBUS_OFF;
+				omap_musb_mailbox(status);
+				if (twl->asleep) {
+					regulator_disable(twl->usb3v3);
+					twl->asleep = 0;
+				}
 			}
 		}
 	}
+	twl->prev_status = status;
 	sysfs_notify(&twl->dev->kobj, NULL, "vbus");
 
 	return IRQ_HANDLED;
@@ -295,7 +251,6 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
 static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
 {
 	struct twl6030_usb *twl = _twl;
-	struct usb_otg *otg = twl->phy.otg;
 	int status = USB_EVENT_NONE;
 	u8 hw_state;
 
@@ -309,12 +264,7 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
 		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET,
 								0x10);
 		status = USB_EVENT_ID;
-		otg->default_a = true;
-		twl->phy.state = OTG_STATE_A_IDLE;
-		twl->linkstat = status;
-		twl->phy.last_event = status;
-		atomic_notifier_call_chain(&twl->phy.notifier, status,
-							otg->gadget);
+		omap_musb_mailbox(OMAP_MUSB_ID_GROUND);
 	} else  {
 		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR,
 								0x10);
@@ -326,23 +276,8 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
 	return IRQ_HANDLED;
 }
 
-static int twl6030_set_peripheral(struct usb_otg *otg,
-		struct usb_gadget *gadget)
-{
-	if (!otg)
-		return -ENODEV;
-
-	otg->gadget = gadget;
-	if (!gadget)
-		otg->phy->state = OTG_STATE_UNDEFINED;
-
-	return 0;
-}
-
-static int twl6030_enable_irq(struct usb_phy *x)
+static int twl6030_enable_irq(struct twl6030_usb *twl)
 {
-	struct twl6030_usb *twl = phy_to_twl(x);
-
 	twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET, 0x1);
 	twl6030_interrupt_unmask(0x05, REG_INT_MSK_LINE_C);
 	twl6030_interrupt_unmask(0x05, REG_INT_MSK_STS_C);
@@ -375,9 +310,9 @@ static void otg_set_vbus_work(struct work_struct *data)
 							CHARGERUSB_CTRL1);
 }
 
-static int twl6030_set_vbus(struct usb_otg *otg, bool enabled)
+static int twl6030_set_vbus(struct phy_companion *comparator, bool enabled)
 {
-	struct twl6030_usb *twl = phy_to_twl(otg->phy);
+	struct twl6030_usb *twl = comparator_to_twl(comparator);
 
 	twl->vbus_enable = enabled;
 	schedule_work(&twl->set_vbus_work);
@@ -385,23 +320,11 @@ static int twl6030_set_vbus(struct usb_otg *otg, bool enabled)
 	return 0;
 }
 
-static int twl6030_set_host(struct usb_otg *otg, struct usb_bus *host)
-{
-	if (!otg)
-		return -ENODEV;
-
-	otg->host = host;
-	if (!host)
-		otg->phy->state = OTG_STATE_UNDEFINED;
-	return 0;
-}
-
 static int __devinit twl6030_usb_probe(struct platform_device *pdev)
 {
 	struct twl6030_usb	*twl;
 	int			status, err;
 	struct twl4030_usb_data *pdata;
-	struct usb_otg		*otg;
 	struct device *dev = &pdev->dev;
 	pdata = dev->platform_data;
 
@@ -409,29 +332,16 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
 	if (!twl)
 		return -ENOMEM;
 
-	otg = kzalloc(sizeof *otg, GFP_KERNEL);
-	if (!otg) {
-		kfree(twl);
-		return -ENOMEM;
-	}
-
 	twl->dev		= &pdev->dev;
 	twl->irq1		= platform_get_irq(pdev, 0);
 	twl->irq2		= platform_get_irq(pdev, 1);
 	twl->features		= pdata->features;
+	twl->prev_status	= OMAP_MUSB_UNKNOWN;
 
-	twl->phy.dev		= twl->dev;
-	twl->phy.label		= "twl6030";
-	twl->phy.otg		= otg;
-	twl->phy.init		= twl6030_phy_init;
-	twl->phy.shutdown	= twl6030_phy_shutdown;
-	twl->phy.set_suspend	= twl6030_phy_suspend;
+	twl->comparator.set_vbus	= twl6030_set_vbus;
+	twl->comparator.start_srp	= twl6030_start_srp;
 
-	otg->phy		= &twl->phy;
-	otg->set_host		= twl6030_set_host;
-	otg->set_peripheral	= twl6030_set_peripheral;
-	otg->set_vbus		= twl6030_set_vbus;
-	otg->start_srp		= twl6030_start_srp;
+	omap_usb2_set_comparator(&twl->comparator);
 
 	/* init spinlock for workqueue */
 	spin_lock_init(&twl->lock);
@@ -439,18 +349,14 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
 	err = twl6030_usb_ldo_init(twl);
 	if (err) {
 		dev_err(&pdev->dev, "ldo init failed\n");
-		kfree(otg);
 		kfree(twl);
 		return err;
 	}
-	usb_add_phy(&twl->phy, USB_PHY_TYPE_USB2);
 
 	platform_set_drvdata(pdev, twl);
 	if (device_create_file(&pdev->dev, &dev_attr_vbus))
 		dev_warn(&pdev->dev, "could not create sysfs file\n");
 
-	ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier);
-
 	INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work);
 
 	twl->irq_enabled = true;
@@ -461,7 +367,6 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
 			twl->irq1, status);
 		device_remove_file(twl->dev, &dev_attr_vbus);
-		kfree(otg);
 		kfree(twl);
 		return status;
 	}
@@ -474,15 +379,12 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
 			twl->irq2, status);
 		free_irq(twl->irq1, twl);
 		device_remove_file(twl->dev, &dev_attr_vbus);
-		kfree(otg);
 		kfree(twl);
 		return status;
 	}
 
 	twl->asleep = 0;
-	pdata->phy_init(dev);
-	twl6030_phy_suspend(&twl->phy, 0);
-	twl6030_enable_irq(&twl->phy);
+	twl6030_enable_irq(twl);
 	dev_info(&pdev->dev, "Initialized TWL6030 USB module\n");
 
 	return 0;
@@ -492,10 +394,6 @@ static int __exit twl6030_usb_remove(struct platform_device *pdev)
 {
 	struct twl6030_usb *twl = platform_get_drvdata(pdev);
 
-	struct twl4030_usb_data *pdata;
-	struct device *dev = &pdev->dev;
-	pdata = dev->platform_data;
-
 	twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
 		REG_INT_MSK_LINE_C);
 	twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
@@ -503,10 +401,8 @@ static int __exit twl6030_usb_remove(struct platform_device *pdev)
 	free_irq(twl->irq1, twl);
 	free_irq(twl->irq2, twl);
 	regulator_put(twl->usb3v3);
-	pdata->phy_exit(twl->dev);
 	device_remove_file(twl->dev, &dev_attr_vbus);
 	cancel_work_sync(&twl->set_vbus_work);
-	kfree(twl->phy.otg);
 	kfree(twl);
 
 	return 0;
diff --git a/include/linux/usb/musb-omap.h b/include/linux/usb/musb-omap.h
new file mode 100644
index 0000000..c84224c
--- /dev/null
+++ b/include/linux/usb/musb-omap.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011-2012 by Texas Instruments
+ *
+ * The Inventra Controller Driver for Linux is free software; you
+ * can redistribute it and/or modify it under the terms of the GNU
+ * General Public License version 2 as published by the Free Software
+ * Foundation.
+ */
+
+#ifndef __MUSB_OMAP_H__
+#define __MUSB_OMAP_H__
+
+enum omap_musb_vbus_id_status {
+	OMAP_MUSB_UNKNOWN = 0,
+	OMAP_MUSB_ID_GROUND,
+	OMAP_MUSB_ID_FLOAT,
+	OMAP_MUSB_VBUS_VALID,
+	OMAP_MUSB_VBUS_OFF,
+};
+
+#if (defined(CONFIG_USB_MUSB_OMAP2PLUS) || \
+				defined(CONFIG_USB_MUSB_OMAP2PLUS_MODULE))
+int omap_musb_mailbox(enum omap_musb_vbus_id_status status);
+#else
+static inline int omap_musb_mailbox(enum omap_musb_vbus_id_status status)
+{
+	return -EINVAL;
+}
+#endif
+
+#endif	/* __MUSB_OMAP_H__ */
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH 2/3] usb: musb: omap glue: use omap-usb2 as the phy driver
@ 2012-05-30 14:34   ` Kishon Vijay Abraham I
  0 siblings, 0 replies; 23+ messages in thread
From: Kishon Vijay Abraham I @ 2012-05-30 14:34 UTC (permalink / raw)
  To: linux-arm-kernel

The twl6030 which was the phy driver (phy + comparator) is now
made only as comparator driver used for detecting VBUS and ID events
and reporting it to the glue using an export API created in omap musb
glue.

The MUSB should now use omap-usb2 as the phy driver.

Both twl6030 and twl4030 are made to use the export API from omap musb glue.

Cc: Felipe Balbi <balbi@ti.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 arch/arm/mach-omap2/usb-musb.c |    3 -
 drivers/usb/musb/musb_core.h   |    1 -
 drivers/usb/musb/omap2430.c    |  150 +++++++++++++++++++++++++----------
 drivers/usb/otg/twl4030-usb.c  |   40 +++------
 drivers/usb/otg/twl6030-usb.c  |  172 ++++++++--------------------------------
 include/linux/usb/musb-omap.h  |   31 +++++++
 6 files changed, 187 insertions(+), 210 deletions(-)
 create mode 100644 include/linux/usb/musb-omap.h

diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c
index 8d5ed77..8ada8cc 100644
--- a/arch/arm/mach-omap2/usb-musb.c
+++ b/arch/arm/mach-omap2/usb-musb.c
@@ -119,7 +119,4 @@ void __init usb_musb_init(struct omap_musb_board_data *musb_board_data)
 	dev->dma_mask = &musb_dmamask;
 	dev->coherent_dma_mask = musb_dmamask;
 	put_device(dev);
-
-	if (cpu_is_omap44xx())
-		omap4430_phy_init(dev);
 }
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index f4a40f0..0b0174b 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -327,7 +327,6 @@ struct musb {
 
 	irqreturn_t		(*isr)(int, void *);
 	struct work_struct	irq_work;
-	struct work_struct	otg_notifier_work;
 	u16			hwvers;
 
 /* this hub status bit is reserved by USB 2.0 and not seen by usbcore */
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index e279cf3..a94e13e 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -34,6 +34,9 @@
 #include <linux/dma-mapping.h>
 #include <linux/pm_runtime.h>
 #include <linux/err.h>
+#include <linux/usb/musb-omap.h>
+#include <linux/usb/omap4_usb_phy.h>
+#include <linux/mfd/omap_control.h>
 
 #include "musb_core.h"
 #include "omap2430.h"
@@ -41,9 +44,14 @@
 struct omap2430_glue {
 	struct device		*dev;
 	struct platform_device	*musb;
+	struct work_struct	omap_musb_mailbox_work;
+	struct device		*control_dev;
+	enum omap_musb_vbus_id_status status;
 };
 #define glue_to_musb(g)		platform_get_drvdata(g->musb)
 
+struct omap2430_glue		*_glue;
+
 static struct timer_list musb_idle_timer;
 
 static void musb_do_idle(unsigned long _musb)
@@ -223,68 +231,104 @@ static inline void omap2430_low_level_init(struct musb *musb)
 	musb_writel(musb->mregs, OTG_FORCESTDBY, l);
 }
 
-static int musb_otg_notifications(struct notifier_block *nb,
-		unsigned long event, void *unused)
+int omap_musb_mailbox(enum omap_musb_vbus_id_status status)
 {
-	struct musb	*musb = container_of(nb, struct musb, nb);
+	struct omap2430_glue	*glue = _glue;
+	struct musb		*musb = glue_to_musb(glue);
+
+	glue->status = status;
+	if (!musb) {
+		dev_err(glue->dev, "musb core is not yet ready\n");
+		return -ENODEV;
+	}
 
-	musb->xceiv_event = event;
-	schedule_work(&musb->otg_notifier_work);
+	schedule_work(&glue->omap_musb_mailbox_work);
 
-	return NOTIFY_OK;
+	return 0;
 }
 
-static void musb_otg_notifier_work(struct work_struct *data_notifier_work)
+static void omap_musb_set_mailbox(struct omap2430_glue *glue)
 {
-	struct musb *musb = container_of(data_notifier_work, struct musb, otg_notifier_work);
+	struct musb *musb = glue_to_musb(glue);
 	struct device *dev = musb->controller;
 	struct musb_hdrc_platform_data *pdata = dev->platform_data;
 	struct omap_musb_board_data *data = pdata->board_data;
+	struct usb_otg *otg = musb->xceiv->otg;
+	u32 val;
 
-	switch (musb->xceiv_event) {
-	case USB_EVENT_ID:
-		dev_dbg(musb->controller, "ID GND\n");
+	switch (glue->status) {
+	case OMAP_MUSB_ID_GROUND:
+		dev_dbg(dev, "ID GND\n");
 
+		otg->default_a = true;
+		musb->xceiv->state = OTG_STATE_A_IDLE;
+		musb->xceiv->last_event = USB_EVENT_ID;
 		if (!is_otg_enabled(musb) || musb->gadget_driver) {
-			pm_runtime_get_sync(musb->controller);
-			usb_phy_init(musb->xceiv);
+			pm_runtime_get_sync(dev);
+			if (glue->control_dev) {
+				val = AVALID | VBUSVALID;
+				omap4_usb_phy_mailbox(glue->control_dev, val);
+			}
 			omap2430_musb_set_vbus(musb, 1);
 		}
 		break;
 
-	case USB_EVENT_VBUS:
-		dev_dbg(musb->controller, "VBUS Connect\n");
+	case OMAP_MUSB_VBUS_VALID:
+		dev_dbg(dev, "VBUS Connect\n");
 
+		otg->default_a = false;
+		musb->xceiv->state = OTG_STATE_B_IDLE;
+		musb->xceiv->last_event = USB_EVENT_VBUS;
 		if (musb->gadget_driver)
-			pm_runtime_get_sync(musb->controller);
-		usb_phy_init(musb->xceiv);
+			pm_runtime_get_sync(dev);
+
+		if (glue->control_dev) {
+			val = IDDIG | AVALID | VBUSVALID;
+			omap4_usb_phy_mailbox(glue->control_dev, val);
+		}
 		break;
 
-	case USB_EVENT_NONE:
-		dev_dbg(musb->controller, "VBUS Disconnect\n");
+	case OMAP_MUSB_ID_FLOAT:
+	case OMAP_MUSB_VBUS_OFF:
+		dev_dbg(dev, "VBUS Disconnect\n");
+
+		musb->xceiv->last_event = USB_EVENT_NONE;
 
 		if (is_otg_enabled(musb) || is_peripheral_enabled(musb))
 			if (musb->gadget_driver) {
-				pm_runtime_mark_last_busy(musb->controller);
-				pm_runtime_put_autosuspend(musb->controller);
+				pm_runtime_mark_last_busy(dev);
+				pm_runtime_put_autosuspend(dev);
 			}
 
 		if (data->interface_type == MUSB_INTERFACE_UTMI) {
 			if (musb->xceiv->otg->set_vbus)
 				otg_set_vbus(musb->xceiv->otg, 0);
 		}
-		usb_phy_shutdown(musb->xceiv);
+
+		if (glue->control_dev) {
+			val = SESSEND | IDDIG;
+			omap4_usb_phy_mailbox(glue->control_dev, val);
+		}
 		break;
 	default:
-		dev_dbg(musb->controller, "ID float\n");
+		dev_dbg(dev, "ID float\n");
 	}
 }
 
+
+static void omap_musb_mailbox_work(struct work_struct *mailbox_work)
+{
+	struct omap2430_glue *glue = container_of(mailbox_work,
+				struct omap2430_glue, omap_musb_mailbox_work);
+	omap_musb_set_mailbox(glue);
+}
+
 static int omap2430_musb_init(struct musb *musb)
 {
 	u32 l;
 	int status = 0;
 	struct device *dev = musb->controller;
+	struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
 	struct musb_hdrc_platform_data *plat = dev->platform_data;
 	struct omap_musb_board_data *data = plat->board_data;
 
@@ -292,14 +336,12 @@ static int omap2430_musb_init(struct musb *musb)
 	 * up through ULPI.  TWL4030-family PMICs include one,
 	 * which needs a driver, drivers aren't always needed.
 	 */
-	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
+	musb->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
 	if (!musb->xceiv) {
 		pr_err("HS USB OTG: no transceiver configured\n");
 		return -ENODEV;
 	}
 
-	INIT_WORK(&musb->otg_notifier_work, musb_otg_notifier_work);
-
 	status = pm_runtime_get_sync(dev);
 	if (status < 0) {
 		dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status);
@@ -326,15 +368,14 @@ static int omap2430_musb_init(struct musb *musb)
 			musb_readl(musb->mregs, OTG_INTERFSEL),
 			musb_readl(musb->mregs, OTG_SIMENABLE));
 
-	musb->nb.notifier_call = musb_otg_notifications;
-	status = usb_register_notifier(musb->xceiv, &musb->nb);
-
-	if (status)
-		dev_dbg(musb->controller, "notification register failed\n");
+	usb_phy_init(musb->xceiv);
 
 	setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
 
-	pm_runtime_put_noidle(musb->controller);
+	if (glue->status != OMAP_MUSB_UNKNOWN)
+		omap_musb_set_mailbox(glue);
+
+	pm_runtime_put_sync(musb->controller);
 	return 0;
 
 err1:
@@ -343,16 +384,22 @@ err1:
 
 static void omap2430_musb_enable(struct musb *musb)
 {
+	u32		val;
 	u8		devctl;
 	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
 	struct device *dev = musb->controller;
+	struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
 	struct musb_hdrc_platform_data *pdata = dev->platform_data;
 	struct omap_musb_board_data *data = pdata->board_data;
 
-	switch (musb->xceiv->last_event) {
+	switch (glue->status) {
+
+	case OMAP_MUSB_ID_GROUND:
+		if (glue->control_dev) {
+			val = AVALID | VBUSVALID;
+			omap4_usb_phy_mailbox(glue->control_dev, val);
+		}
 
-	case USB_EVENT_ID:
-		usb_phy_init(musb->xceiv);
 		if (data->interface_type != MUSB_INTERFACE_UTMI)
 			break;
 		devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
@@ -370,8 +417,11 @@ static void omap2430_musb_enable(struct musb *musb)
 		}
 		break;
 
-	case USB_EVENT_VBUS:
-		usb_phy_init(musb->xceiv);
+	case OMAP_MUSB_VBUS_VALID:
+		if (glue->control_dev) {
+			val = IDDIG | AVALID | VBUSVALID;
+			omap4_usb_phy_mailbox(glue->control_dev, val);
+		}
 		break;
 
 	default:
@@ -381,17 +431,21 @@ static void omap2430_musb_enable(struct musb *musb)
 
 static void omap2430_musb_disable(struct musb *musb)
 {
-	if (musb->xceiv->last_event)
-		usb_phy_shutdown(musb->xceiv);
+	u32 val;
+	struct device *dev = musb->controller;
+	struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
+
+	if (musb->xceiv->last_event && glue->control_dev) {
+		val = SESSEND | IDDIG;
+		omap4_usb_phy_mailbox(glue->control_dev, val);
+	}
 }
 
 static int omap2430_musb_exit(struct musb *musb)
 {
 	del_timer_sync(&musb_idle_timer);
-	cancel_work_sync(&musb->otg_notifier_work);
 
 	omap2430_low_level_exit(musb);
-	usb_put_phy(musb->xceiv);
 
 	return 0;
 }
@@ -436,11 +490,21 @@ static int __devinit omap2430_probe(struct platform_device *pdev)
 
 	glue->dev			= &pdev->dev;
 	glue->musb			= musb;
+	glue->status			= OMAP_MUSB_UNKNOWN;
+	glue->control_dev		= omap_control_get();
 
 	pdata->platform_ops		= &omap2430_ops;
 
 	platform_set_drvdata(pdev, glue);
 
+	/*
+	 * REVISIT if we ever have two instances of the wrapper, we will be
+	 * in big trouble
+	 */
+	_glue	= glue;
+
+	INIT_WORK(&glue->omap_musb_mailbox_work, omap_musb_mailbox_work);
+
 	ret = platform_device_add_resources(musb, pdev->resource,
 			pdev->num_resources);
 	if (ret) {
@@ -478,6 +542,8 @@ static int __devexit omap2430_remove(struct platform_device *pdev)
 {
 	struct omap2430_glue		*glue = platform_get_drvdata(pdev);
 
+	cancel_work_sync(&glue->omap_musb_mailbox_work);
+
 	platform_device_del(glue->musb);
 	platform_device_put(glue->musb);
 	kfree(glue);
@@ -546,7 +612,7 @@ static int __init omap2430_init(void)
 {
 	return platform_driver_register(&omap2430_driver);
 }
-module_init(omap2430_init);
+subsys_initcall(omap2430_init);
 
 static void __exit omap2430_exit(void)
 {
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c
index f8139b3..d9357d4 100644
--- a/drivers/usb/otg/twl4030-usb.c
+++ b/drivers/usb/otg/twl4030-usb.c
@@ -32,6 +32,7 @@
 #include <linux/workqueue.h>
 #include <linux/io.h>
 #include <linux/delay.h>
+#include <linux/usb/musb-omap.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
 #include <linux/i2c/twl.h>
@@ -159,10 +160,11 @@ struct twl4030_usb {
 	enum twl4030_usb_mode	usb_mode;
 
 	int			irq;
-	u8			linkstat;
 	bool			vbus_supplied;
 	u8			asleep;
 	bool			irq_enabled;
+
+	enum omap_musb_vbus_id_status prev_status;
 };
 
 /* internal define on top of container_of */
@@ -250,7 +252,6 @@ static enum usb_phy_events twl4030_usb_linkstat(struct twl4030_usb *twl)
 {
 	int	status;
 	int	linkstat = USB_EVENT_NONE;
-	struct usb_otg *otg = twl->phy.otg;
 
 	twl->vbus_supplied = false;
 
@@ -272,33 +273,21 @@ static enum usb_phy_events twl4030_usb_linkstat(struct twl4030_usb *twl)
 		if (status & (BIT(7)))
                         twl->vbus_supplied = true;
 
-		if (status & BIT(2))
+		if (status & BIT(2)) {
+			twl->prev_status = OMAP_MUSB_ID_GROUND;
 			linkstat = USB_EVENT_ID;
-		else
+		} else {
+			twl->prev_status = OMAP_MUSB_VBUS_VALID;
 			linkstat = USB_EVENT_VBUS;
-	} else
+		}
+	} else {
+		twl->prev_status = OMAP_MUSB_VBUS_OFF;
 		linkstat = USB_EVENT_NONE;
+	}
 
 	dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n",
 			status, status, linkstat);
 
-	twl->phy.last_event = linkstat;
-
-	/* REVISIT this assumes host and peripheral controllers
-	 * are registered, and that both are active...
-	 */
-
-	spin_lock_irq(&twl->lock);
-	twl->linkstat = linkstat;
-	if (linkstat == USB_EVENT_ID) {
-		otg->default_a = true;
-		twl->phy.state = OTG_STATE_A_IDLE;
-	} else {
-		otg->default_a = false;
-		twl->phy.state = OTG_STATE_B_IDLE;
-	}
-	spin_unlock_irq(&twl->lock);
-
 	return linkstat;
 }
 
@@ -521,8 +510,7 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
 		else
 			twl4030_phy_resume(twl);
 
-		atomic_notifier_call_chain(&twl->phy.notifier, status,
-				twl->phy.otg->gadget);
+		omap_musb_mailbox(twl->prev_status);
 	}
 	sysfs_notify(&twl->dev->kobj, NULL, "vbus");
 
@@ -543,8 +531,7 @@ static void twl4030_usb_phy_init(struct twl4030_usb *twl)
 			twl->asleep = 0;
 		}
 
-		atomic_notifier_call_chain(&twl->phy.notifier, status,
-				twl->phy.otg->gadget);
+		omap_musb_mailbox(twl->prev_status);
 	}
 	sysfs_notify(&twl->dev->kobj, NULL, "vbus");
 }
@@ -613,6 +600,7 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev)
 	twl->usb_mode		= pdata->usb_mode;
 	twl->vbus_supplied	= false;
 	twl->asleep		= 1;
+	twl->prev_status	= OMAP_MUSB_UNKNOWN;
 
 	twl->phy.dev		= twl->dev;
 	twl->phy.label		= "twl4030";
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c
index dbee00a..e3ac51f 100644
--- a/drivers/usb/otg/twl6030-usb.c
+++ b/drivers/usb/otg/twl6030-usb.c
@@ -26,10 +26,12 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/usb/otg.h>
+#include <linux/usb/phy_companion.h>
+#include <linux/usb/omap_usb.h>
+#include <linux/usb/musb-omap.h>
 #include <linux/i2c/twl.h>
 #include <linux/regulator/consumer.h>
 #include <linux/err.h>
-#include <linux/notifier.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 
@@ -87,7 +89,7 @@
 #define	VBUS_DET			BIT(2)
 
 struct twl6030_usb {
-	struct usb_phy		phy;
+	struct phy_companion	comparator;
 	struct device		*dev;
 
 	/* for vbus reporting with irqs disabled */
@@ -100,15 +102,16 @@ struct twl6030_usb {
 
 	int			irq1;
 	int			irq2;
-	u8			linkstat;
 	u8			asleep;
 	bool			irq_enabled;
 	bool			vbus_enable;
 	unsigned long		features;
-};
 
-#define phy_to_twl(x)		container_of((x), struct twl6030_usb, phy)
+	enum omap_musb_vbus_id_status prev_status;
+
+};
 
+#define	comparator_to_twl(x) container_of((x), struct twl6030_usb, comparator)
 /*-------------------------------------------------------------------------*/
 
 static inline int twl6030_writeb(struct twl6030_usb *twl, u8 module,
@@ -137,50 +140,9 @@ static inline u8 twl6030_readb(struct twl6030_usb *twl, u8 module, u8 address)
 	return ret;
 }
 
-static int twl6030_phy_init(struct usb_phy *x)
-{
-	struct twl6030_usb *twl;
-	struct device *dev;
-	struct twl4030_usb_data *pdata;
-
-	twl = phy_to_twl(x);
-	dev  = twl->dev;
-	pdata = dev->platform_data;
-
-	if (twl->linkstat == USB_EVENT_ID)
-		pdata->phy_power(twl->dev, 1, 1);
-	else
-		pdata->phy_power(twl->dev, 0, 1);
-
-	return 0;
-}
-
-static void twl6030_phy_shutdown(struct usb_phy *x)
-{
-	struct twl6030_usb *twl;
-	struct device *dev;
-	struct twl4030_usb_data *pdata;
-
-	twl = phy_to_twl(x);
-	dev  = twl->dev;
-	pdata = dev->platform_data;
-	pdata->phy_power(twl->dev, 0, 0);
-}
-
-static int twl6030_phy_suspend(struct usb_phy *x, int suspend)
-{
-	struct twl6030_usb *twl = phy_to_twl(x);
-	struct device *dev = twl->dev;
-	struct twl4030_usb_data *pdata = dev->platform_data;
-
-	pdata->phy_suspend(dev, suspend);
-
-	return 0;
-}
-
-static int twl6030_start_srp(struct usb_otg *otg)
+static int twl6030_start_srp(struct phy_companion *comparator)
 {
-	struct twl6030_usb *twl = phy_to_twl(otg->phy);
+	struct twl6030_usb *twl = comparator_to_twl(comparator);
 
 	twl6030_writeb(twl, TWL_MODULE_USB, 0x24, USB_VBUS_CTRL_SET);
 	twl6030_writeb(twl, TWL_MODULE_USB, 0x84, USB_VBUS_CTRL_SET);
@@ -234,14 +196,14 @@ static ssize_t twl6030_usb_vbus_show(struct device *dev,
 
 	spin_lock_irqsave(&twl->lock, flags);
 
-	switch (twl->linkstat) {
-	case USB_EVENT_VBUS:
+	switch (twl->prev_status) {
+	case OMAP_MUSB_VBUS_VALID:
 	       ret = snprintf(buf, PAGE_SIZE, "vbus\n");
 	       break;
-	case USB_EVENT_ID:
+	case OMAP_MUSB_ID_GROUND:
 	       ret = snprintf(buf, PAGE_SIZE, "id\n");
 	       break;
-	case USB_EVENT_NONE:
+	case OMAP_MUSB_VBUS_OFF:
 	       ret = snprintf(buf, PAGE_SIZE, "none\n");
 	       break;
 	default:
@@ -256,8 +218,7 @@ static DEVICE_ATTR(vbus, 0444, twl6030_usb_vbus_show, NULL);
 static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
 {
 	struct twl6030_usb *twl = _twl;
-	struct usb_otg *otg = twl->phy.otg;
-	int status;
+	int status = OMAP_MUSB_UNKNOWN;
 	u8 vbus_state, hw_state;
 
 	hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
@@ -268,25 +229,20 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
 		if (vbus_state & VBUS_DET) {
 			regulator_enable(twl->usb3v3);
 			twl->asleep = 1;
-			status = USB_EVENT_VBUS;
-			otg->default_a = false;
-			twl->phy.state = OTG_STATE_B_IDLE;
-			twl->linkstat = status;
-			twl->phy.last_event = status;
-			atomic_notifier_call_chain(&twl->phy.notifier,
-						status, otg->gadget);
+			status = OMAP_MUSB_VBUS_VALID;
+			omap_musb_mailbox(status);
 		} else {
-			status = USB_EVENT_NONE;
-			twl->linkstat = status;
-			twl->phy.last_event = status;
-			atomic_notifier_call_chain(&twl->phy.notifier,
-						status, otg->gadget);
-			if (twl->asleep) {
-				regulator_disable(twl->usb3v3);
-				twl->asleep = 0;
+			if (twl->prev_status != OMAP_MUSB_UNKNOWN) {
+				status = OMAP_MUSB_VBUS_OFF;
+				omap_musb_mailbox(status);
+				if (twl->asleep) {
+					regulator_disable(twl->usb3v3);
+					twl->asleep = 0;
+				}
 			}
 		}
 	}
+	twl->prev_status = status;
 	sysfs_notify(&twl->dev->kobj, NULL, "vbus");
 
 	return IRQ_HANDLED;
@@ -295,7 +251,6 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
 static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
 {
 	struct twl6030_usb *twl = _twl;
-	struct usb_otg *otg = twl->phy.otg;
 	int status = USB_EVENT_NONE;
 	u8 hw_state;
 
@@ -309,12 +264,7 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
 		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET,
 								0x10);
 		status = USB_EVENT_ID;
-		otg->default_a = true;
-		twl->phy.state = OTG_STATE_A_IDLE;
-		twl->linkstat = status;
-		twl->phy.last_event = status;
-		atomic_notifier_call_chain(&twl->phy.notifier, status,
-							otg->gadget);
+		omap_musb_mailbox(OMAP_MUSB_ID_GROUND);
 	} else  {
 		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR,
 								0x10);
@@ -326,23 +276,8 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
 	return IRQ_HANDLED;
 }
 
-static int twl6030_set_peripheral(struct usb_otg *otg,
-		struct usb_gadget *gadget)
-{
-	if (!otg)
-		return -ENODEV;
-
-	otg->gadget = gadget;
-	if (!gadget)
-		otg->phy->state = OTG_STATE_UNDEFINED;
-
-	return 0;
-}
-
-static int twl6030_enable_irq(struct usb_phy *x)
+static int twl6030_enable_irq(struct twl6030_usb *twl)
 {
-	struct twl6030_usb *twl = phy_to_twl(x);
-
 	twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET, 0x1);
 	twl6030_interrupt_unmask(0x05, REG_INT_MSK_LINE_C);
 	twl6030_interrupt_unmask(0x05, REG_INT_MSK_STS_C);
@@ -375,9 +310,9 @@ static void otg_set_vbus_work(struct work_struct *data)
 							CHARGERUSB_CTRL1);
 }
 
-static int twl6030_set_vbus(struct usb_otg *otg, bool enabled)
+static int twl6030_set_vbus(struct phy_companion *comparator, bool enabled)
 {
-	struct twl6030_usb *twl = phy_to_twl(otg->phy);
+	struct twl6030_usb *twl = comparator_to_twl(comparator);
 
 	twl->vbus_enable = enabled;
 	schedule_work(&twl->set_vbus_work);
@@ -385,23 +320,11 @@ static int twl6030_set_vbus(struct usb_otg *otg, bool enabled)
 	return 0;
 }
 
-static int twl6030_set_host(struct usb_otg *otg, struct usb_bus *host)
-{
-	if (!otg)
-		return -ENODEV;
-
-	otg->host = host;
-	if (!host)
-		otg->phy->state = OTG_STATE_UNDEFINED;
-	return 0;
-}
-
 static int __devinit twl6030_usb_probe(struct platform_device *pdev)
 {
 	struct twl6030_usb	*twl;
 	int			status, err;
 	struct twl4030_usb_data *pdata;
-	struct usb_otg		*otg;
 	struct device *dev = &pdev->dev;
 	pdata = dev->platform_data;
 
@@ -409,29 +332,16 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
 	if (!twl)
 		return -ENOMEM;
 
-	otg = kzalloc(sizeof *otg, GFP_KERNEL);
-	if (!otg) {
-		kfree(twl);
-		return -ENOMEM;
-	}
-
 	twl->dev		= &pdev->dev;
 	twl->irq1		= platform_get_irq(pdev, 0);
 	twl->irq2		= platform_get_irq(pdev, 1);
 	twl->features		= pdata->features;
+	twl->prev_status	= OMAP_MUSB_UNKNOWN;
 
-	twl->phy.dev		= twl->dev;
-	twl->phy.label		= "twl6030";
-	twl->phy.otg		= otg;
-	twl->phy.init		= twl6030_phy_init;
-	twl->phy.shutdown	= twl6030_phy_shutdown;
-	twl->phy.set_suspend	= twl6030_phy_suspend;
+	twl->comparator.set_vbus	= twl6030_set_vbus;
+	twl->comparator.start_srp	= twl6030_start_srp;
 
-	otg->phy		= &twl->phy;
-	otg->set_host		= twl6030_set_host;
-	otg->set_peripheral	= twl6030_set_peripheral;
-	otg->set_vbus		= twl6030_set_vbus;
-	otg->start_srp		= twl6030_start_srp;
+	omap_usb2_set_comparator(&twl->comparator);
 
 	/* init spinlock for workqueue */
 	spin_lock_init(&twl->lock);
@@ -439,18 +349,14 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
 	err = twl6030_usb_ldo_init(twl);
 	if (err) {
 		dev_err(&pdev->dev, "ldo init failed\n");
-		kfree(otg);
 		kfree(twl);
 		return err;
 	}
-	usb_add_phy(&twl->phy, USB_PHY_TYPE_USB2);
 
 	platform_set_drvdata(pdev, twl);
 	if (device_create_file(&pdev->dev, &dev_attr_vbus))
 		dev_warn(&pdev->dev, "could not create sysfs file\n");
 
-	ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier);
-
 	INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work);
 
 	twl->irq_enabled = true;
@@ -461,7 +367,6 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
 			twl->irq1, status);
 		device_remove_file(twl->dev, &dev_attr_vbus);
-		kfree(otg);
 		kfree(twl);
 		return status;
 	}
@@ -474,15 +379,12 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
 			twl->irq2, status);
 		free_irq(twl->irq1, twl);
 		device_remove_file(twl->dev, &dev_attr_vbus);
-		kfree(otg);
 		kfree(twl);
 		return status;
 	}
 
 	twl->asleep = 0;
-	pdata->phy_init(dev);
-	twl6030_phy_suspend(&twl->phy, 0);
-	twl6030_enable_irq(&twl->phy);
+	twl6030_enable_irq(twl);
 	dev_info(&pdev->dev, "Initialized TWL6030 USB module\n");
 
 	return 0;
@@ -492,10 +394,6 @@ static int __exit twl6030_usb_remove(struct platform_device *pdev)
 {
 	struct twl6030_usb *twl = platform_get_drvdata(pdev);
 
-	struct twl4030_usb_data *pdata;
-	struct device *dev = &pdev->dev;
-	pdata = dev->platform_data;
-
 	twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
 		REG_INT_MSK_LINE_C);
 	twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
@@ -503,10 +401,8 @@ static int __exit twl6030_usb_remove(struct platform_device *pdev)
 	free_irq(twl->irq1, twl);
 	free_irq(twl->irq2, twl);
 	regulator_put(twl->usb3v3);
-	pdata->phy_exit(twl->dev);
 	device_remove_file(twl->dev, &dev_attr_vbus);
 	cancel_work_sync(&twl->set_vbus_work);
-	kfree(twl->phy.otg);
 	kfree(twl);
 
 	return 0;
diff --git a/include/linux/usb/musb-omap.h b/include/linux/usb/musb-omap.h
new file mode 100644
index 0000000..c84224c
--- /dev/null
+++ b/include/linux/usb/musb-omap.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011-2012 by Texas Instruments
+ *
+ * The Inventra Controller Driver for Linux is free software; you
+ * can redistribute it and/or modify it under the terms of the GNU
+ * General Public License version 2 as published by the Free Software
+ * Foundation.
+ */
+
+#ifndef __MUSB_OMAP_H__
+#define __MUSB_OMAP_H__
+
+enum omap_musb_vbus_id_status {
+	OMAP_MUSB_UNKNOWN = 0,
+	OMAP_MUSB_ID_GROUND,
+	OMAP_MUSB_ID_FLOAT,
+	OMAP_MUSB_VBUS_VALID,
+	OMAP_MUSB_VBUS_OFF,
+};
+
+#if (defined(CONFIG_USB_MUSB_OMAP2PLUS) || \
+				defined(CONFIG_USB_MUSB_OMAP2PLUS_MODULE))
+int omap_musb_mailbox(enum omap_musb_vbus_id_status status);
+#else
+static inline int omap_musb_mailbox(enum omap_musb_vbus_id_status status)
+{
+	return -EINVAL;
+}
+#endif
+
+#endif	/* __MUSB_OMAP_H__ */
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH 3/3] arm: omap: phy: remove unused functions from omap-phy-internal.c
  2012-05-30 14:34 ` Kishon Vijay Abraham I
  (?)
@ 2012-05-30 14:34   ` Kishon Vijay Abraham I
  -1 siblings, 0 replies; 23+ messages in thread
From: Kishon Vijay Abraham I @ 2012-05-30 14:34 UTC (permalink / raw)
  To: tony, linux, gregkh, kishon, linux-omap, linux-arm-kernel,
	linux-kernel, linux-usb, balbi

All the unnessary functions in omap-phy-internal is removed.
These functionality are now handled by omap-usb2 phy driver.

Cc: Felipe Balbi <balbi@ti.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 arch/arm/mach-omap2/omap_phy_internal.c |  138 -------------------------------
 arch/arm/mach-omap2/twl-common.c        |    5 -
 2 files changed, 0 insertions(+), 143 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_phy_internal.c b/arch/arm/mach-omap2/omap_phy_internal.c
index b2c9253..9a9e960 100644
--- a/arch/arm/mach-omap2/omap_phy_internal.c
+++ b/arch/arm/mach-omap2/omap_phy_internal.c
@@ -31,144 +31,6 @@
 #include <plat/usb.h>
 #include <mach/control.h>
 
-/* OMAP control module register for UTMI PHY */
-#define CONTROL_DEV_CONF		0x300
-#define PHY_PD				0x1
-
-#define USBOTGHS_CONTROL		0x33c
-#define	AVALID				BIT(0)
-#define	BVALID				BIT(1)
-#define	VBUSVALID			BIT(2)
-#define	SESSEND				BIT(3)
-#define	IDDIG				BIT(4)
-
-static struct clk *phyclk, *clk48m, *clk32k;
-static void __iomem *ctrl_base;
-static int usbotghs_control;
-
-int omap4430_phy_init(struct device *dev)
-{
-	ctrl_base = ioremap(OMAP443X_SCM_BASE, SZ_1K);
-	if (!ctrl_base) {
-		pr_err("control module ioremap failed\n");
-		return -ENOMEM;
-	}
-	/* Power down the phy */
-	__raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF);
-
-	if (!dev) {
-		iounmap(ctrl_base);
-		return 0;
-	}
-
-	phyclk = clk_get(dev, "ocp2scp_usb_phy_ick");
-	if (IS_ERR(phyclk)) {
-		dev_err(dev, "cannot clk_get ocp2scp_usb_phy_ick\n");
-		iounmap(ctrl_base);
-		return PTR_ERR(phyclk);
-	}
-
-	clk48m = clk_get(dev, "ocp2scp_usb_phy_phy_48m");
-	if (IS_ERR(clk48m)) {
-		dev_err(dev, "cannot clk_get ocp2scp_usb_phy_phy_48m\n");
-		clk_put(phyclk);
-		iounmap(ctrl_base);
-		return PTR_ERR(clk48m);
-	}
-
-	clk32k = clk_get(dev, "usb_phy_cm_clk32k");
-	if (IS_ERR(clk32k)) {
-		dev_err(dev, "cannot clk_get usb_phy_cm_clk32k\n");
-		clk_put(phyclk);
-		clk_put(clk48m);
-		iounmap(ctrl_base);
-		return PTR_ERR(clk32k);
-	}
-	return 0;
-}
-
-int omap4430_phy_set_clk(struct device *dev, int on)
-{
-	static int state;
-
-	if (on && !state) {
-		/* Enable the phy clocks */
-		clk_enable(phyclk);
-		clk_enable(clk48m);
-		clk_enable(clk32k);
-		state = 1;
-	} else if (state) {
-		/* Disable the phy clocks */
-		clk_disable(phyclk);
-		clk_disable(clk48m);
-		clk_disable(clk32k);
-		state = 0;
-	}
-	return 0;
-}
-
-int omap4430_phy_power(struct device *dev, int ID, int on)
-{
-	if (on) {
-		if (ID)
-			/* enable VBUS valid, IDDIG groung */
-			__raw_writel(AVALID | VBUSVALID, ctrl_base +
-							USBOTGHS_CONTROL);
-		else
-			/*
-			 * Enable VBUS Valid, AValid and IDDIG
-			 * high impedance
-			 */
-			__raw_writel(IDDIG | AVALID | VBUSVALID,
-						ctrl_base + USBOTGHS_CONTROL);
-	} else {
-		/* Enable session END and IDIG to high impedance. */
-		__raw_writel(SESSEND | IDDIG, ctrl_base +
-					USBOTGHS_CONTROL);
-	}
-	return 0;
-}
-
-int omap4430_phy_suspend(struct device *dev, int suspend)
-{
-	if (suspend) {
-		/* Disable the clocks */
-		omap4430_phy_set_clk(dev, 0);
-		/* Power down the phy */
-		__raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF);
-
-		/* save the context */
-		usbotghs_control = __raw_readl(ctrl_base + USBOTGHS_CONTROL);
-	} else {
-		/* Enable the internel phy clcoks */
-		omap4430_phy_set_clk(dev, 1);
-		/* power on the phy */
-		if (__raw_readl(ctrl_base + CONTROL_DEV_CONF) & PHY_PD) {
-			__raw_writel(~PHY_PD, ctrl_base + CONTROL_DEV_CONF);
-			mdelay(200);
-		}
-
-		/* restore the context */
-		__raw_writel(usbotghs_control, ctrl_base + USBOTGHS_CONTROL);
-	}
-
-	return 0;
-}
-
-int omap4430_phy_exit(struct device *dev)
-{
-	if (ctrl_base)
-		iounmap(ctrl_base);
-	if (phyclk)
-		clk_put(phyclk);
-	if (clk48m)
-		clk_put(clk48m);
-	if (clk32k)
-		clk_put(clk32k);
-
-	return 0;
-}
-
 void am35x_musb_reset(void)
 {
 	u32	regval;
diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c
index 119d5a9..396d189 100644
--- a/arch/arm/mach-omap2/twl-common.c
+++ b/arch/arm/mach-omap2/twl-common.c
@@ -250,11 +250,6 @@ void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
 
 #if defined(CONFIG_ARCH_OMAP4)
 static struct twl4030_usb_data omap4_usb_pdata = {
-	.phy_init	= omap4430_phy_init,
-	.phy_exit	= omap4430_phy_exit,
-	.phy_power	= omap4430_phy_power,
-	.phy_set_clock	= omap4430_phy_set_clk,
-	.phy_suspend	= omap4430_phy_suspend,
 };
 
 static struct regulator_init_data omap4_vdac_idata = {
-- 
1.7.5.4


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH 3/3] arm: omap: phy: remove unused functions from omap-phy-internal.c
@ 2012-05-30 14:34   ` Kishon Vijay Abraham I
  0 siblings, 0 replies; 23+ messages in thread
From: Kishon Vijay Abraham I @ 2012-05-30 14:34 UTC (permalink / raw)
  To: tony, linux, gregkh, kishon, linux-omap, linux-arm-kernel,
	linux-kernel, linux-usb, balbi

All the unnessary functions in omap-phy-internal is removed.
These functionality are now handled by omap-usb2 phy driver.

Cc: Felipe Balbi <balbi@ti.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 arch/arm/mach-omap2/omap_phy_internal.c |  138 -------------------------------
 arch/arm/mach-omap2/twl-common.c        |    5 -
 2 files changed, 0 insertions(+), 143 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_phy_internal.c b/arch/arm/mach-omap2/omap_phy_internal.c
index b2c9253..9a9e960 100644
--- a/arch/arm/mach-omap2/omap_phy_internal.c
+++ b/arch/arm/mach-omap2/omap_phy_internal.c
@@ -31,144 +31,6 @@
 #include <plat/usb.h>
 #include <mach/control.h>
 
-/* OMAP control module register for UTMI PHY */
-#define CONTROL_DEV_CONF		0x300
-#define PHY_PD				0x1
-
-#define USBOTGHS_CONTROL		0x33c
-#define	AVALID				BIT(0)
-#define	BVALID				BIT(1)
-#define	VBUSVALID			BIT(2)
-#define	SESSEND				BIT(3)
-#define	IDDIG				BIT(4)
-
-static struct clk *phyclk, *clk48m, *clk32k;
-static void __iomem *ctrl_base;
-static int usbotghs_control;
-
-int omap4430_phy_init(struct device *dev)
-{
-	ctrl_base = ioremap(OMAP443X_SCM_BASE, SZ_1K);
-	if (!ctrl_base) {
-		pr_err("control module ioremap failed\n");
-		return -ENOMEM;
-	}
-	/* Power down the phy */
-	__raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF);
-
-	if (!dev) {
-		iounmap(ctrl_base);
-		return 0;
-	}
-
-	phyclk = clk_get(dev, "ocp2scp_usb_phy_ick");
-	if (IS_ERR(phyclk)) {
-		dev_err(dev, "cannot clk_get ocp2scp_usb_phy_ick\n");
-		iounmap(ctrl_base);
-		return PTR_ERR(phyclk);
-	}
-
-	clk48m = clk_get(dev, "ocp2scp_usb_phy_phy_48m");
-	if (IS_ERR(clk48m)) {
-		dev_err(dev, "cannot clk_get ocp2scp_usb_phy_phy_48m\n");
-		clk_put(phyclk);
-		iounmap(ctrl_base);
-		return PTR_ERR(clk48m);
-	}
-
-	clk32k = clk_get(dev, "usb_phy_cm_clk32k");
-	if (IS_ERR(clk32k)) {
-		dev_err(dev, "cannot clk_get usb_phy_cm_clk32k\n");
-		clk_put(phyclk);
-		clk_put(clk48m);
-		iounmap(ctrl_base);
-		return PTR_ERR(clk32k);
-	}
-	return 0;
-}
-
-int omap4430_phy_set_clk(struct device *dev, int on)
-{
-	static int state;
-
-	if (on && !state) {
-		/* Enable the phy clocks */
-		clk_enable(phyclk);
-		clk_enable(clk48m);
-		clk_enable(clk32k);
-		state = 1;
-	} else if (state) {
-		/* Disable the phy clocks */
-		clk_disable(phyclk);
-		clk_disable(clk48m);
-		clk_disable(clk32k);
-		state = 0;
-	}
-	return 0;
-}
-
-int omap4430_phy_power(struct device *dev, int ID, int on)
-{
-	if (on) {
-		if (ID)
-			/* enable VBUS valid, IDDIG groung */
-			__raw_writel(AVALID | VBUSVALID, ctrl_base +
-							USBOTGHS_CONTROL);
-		else
-			/*
-			 * Enable VBUS Valid, AValid and IDDIG
-			 * high impedance
-			 */
-			__raw_writel(IDDIG | AVALID | VBUSVALID,
-						ctrl_base + USBOTGHS_CONTROL);
-	} else {
-		/* Enable session END and IDIG to high impedance. */
-		__raw_writel(SESSEND | IDDIG, ctrl_base +
-					USBOTGHS_CONTROL);
-	}
-	return 0;
-}
-
-int omap4430_phy_suspend(struct device *dev, int suspend)
-{
-	if (suspend) {
-		/* Disable the clocks */
-		omap4430_phy_set_clk(dev, 0);
-		/* Power down the phy */
-		__raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF);
-
-		/* save the context */
-		usbotghs_control = __raw_readl(ctrl_base + USBOTGHS_CONTROL);
-	} else {
-		/* Enable the internel phy clcoks */
-		omap4430_phy_set_clk(dev, 1);
-		/* power on the phy */
-		if (__raw_readl(ctrl_base + CONTROL_DEV_CONF) & PHY_PD) {
-			__raw_writel(~PHY_PD, ctrl_base + CONTROL_DEV_CONF);
-			mdelay(200);
-		}
-
-		/* restore the context */
-		__raw_writel(usbotghs_control, ctrl_base + USBOTGHS_CONTROL);
-	}
-
-	return 0;
-}
-
-int omap4430_phy_exit(struct device *dev)
-{
-	if (ctrl_base)
-		iounmap(ctrl_base);
-	if (phyclk)
-		clk_put(phyclk);
-	if (clk48m)
-		clk_put(clk48m);
-	if (clk32k)
-		clk_put(clk32k);
-
-	return 0;
-}
-
 void am35x_musb_reset(void)
 {
 	u32	regval;
diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c
index 119d5a9..396d189 100644
--- a/arch/arm/mach-omap2/twl-common.c
+++ b/arch/arm/mach-omap2/twl-common.c
@@ -250,11 +250,6 @@ void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
 
 #if defined(CONFIG_ARCH_OMAP4)
 static struct twl4030_usb_data omap4_usb_pdata = {
-	.phy_init	= omap4430_phy_init,
-	.phy_exit	= omap4430_phy_exit,
-	.phy_power	= omap4430_phy_power,
-	.phy_set_clock	= omap4430_phy_set_clk,
-	.phy_suspend	= omap4430_phy_suspend,
 };
 
 static struct regulator_init_data omap4_vdac_idata = {
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH 3/3] arm: omap: phy: remove unused functions from omap-phy-internal.c
@ 2012-05-30 14:34   ` Kishon Vijay Abraham I
  0 siblings, 0 replies; 23+ messages in thread
From: Kishon Vijay Abraham I @ 2012-05-30 14:34 UTC (permalink / raw)
  To: linux-arm-kernel

All the unnessary functions in omap-phy-internal is removed.
These functionality are now handled by omap-usb2 phy driver.

Cc: Felipe Balbi <balbi@ti.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 arch/arm/mach-omap2/omap_phy_internal.c |  138 -------------------------------
 arch/arm/mach-omap2/twl-common.c        |    5 -
 2 files changed, 0 insertions(+), 143 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_phy_internal.c b/arch/arm/mach-omap2/omap_phy_internal.c
index b2c9253..9a9e960 100644
--- a/arch/arm/mach-omap2/omap_phy_internal.c
+++ b/arch/arm/mach-omap2/omap_phy_internal.c
@@ -31,144 +31,6 @@
 #include <plat/usb.h>
 #include <mach/control.h>
 
-/* OMAP control module register for UTMI PHY */
-#define CONTROL_DEV_CONF		0x300
-#define PHY_PD				0x1
-
-#define USBOTGHS_CONTROL		0x33c
-#define	AVALID				BIT(0)
-#define	BVALID				BIT(1)
-#define	VBUSVALID			BIT(2)
-#define	SESSEND				BIT(3)
-#define	IDDIG				BIT(4)
-
-static struct clk *phyclk, *clk48m, *clk32k;
-static void __iomem *ctrl_base;
-static int usbotghs_control;
-
-int omap4430_phy_init(struct device *dev)
-{
-	ctrl_base = ioremap(OMAP443X_SCM_BASE, SZ_1K);
-	if (!ctrl_base) {
-		pr_err("control module ioremap failed\n");
-		return -ENOMEM;
-	}
-	/* Power down the phy */
-	__raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF);
-
-	if (!dev) {
-		iounmap(ctrl_base);
-		return 0;
-	}
-
-	phyclk = clk_get(dev, "ocp2scp_usb_phy_ick");
-	if (IS_ERR(phyclk)) {
-		dev_err(dev, "cannot clk_get ocp2scp_usb_phy_ick\n");
-		iounmap(ctrl_base);
-		return PTR_ERR(phyclk);
-	}
-
-	clk48m = clk_get(dev, "ocp2scp_usb_phy_phy_48m");
-	if (IS_ERR(clk48m)) {
-		dev_err(dev, "cannot clk_get ocp2scp_usb_phy_phy_48m\n");
-		clk_put(phyclk);
-		iounmap(ctrl_base);
-		return PTR_ERR(clk48m);
-	}
-
-	clk32k = clk_get(dev, "usb_phy_cm_clk32k");
-	if (IS_ERR(clk32k)) {
-		dev_err(dev, "cannot clk_get usb_phy_cm_clk32k\n");
-		clk_put(phyclk);
-		clk_put(clk48m);
-		iounmap(ctrl_base);
-		return PTR_ERR(clk32k);
-	}
-	return 0;
-}
-
-int omap4430_phy_set_clk(struct device *dev, int on)
-{
-	static int state;
-
-	if (on && !state) {
-		/* Enable the phy clocks */
-		clk_enable(phyclk);
-		clk_enable(clk48m);
-		clk_enable(clk32k);
-		state = 1;
-	} else if (state) {
-		/* Disable the phy clocks */
-		clk_disable(phyclk);
-		clk_disable(clk48m);
-		clk_disable(clk32k);
-		state = 0;
-	}
-	return 0;
-}
-
-int omap4430_phy_power(struct device *dev, int ID, int on)
-{
-	if (on) {
-		if (ID)
-			/* enable VBUS valid, IDDIG groung */
-			__raw_writel(AVALID | VBUSVALID, ctrl_base +
-							USBOTGHS_CONTROL);
-		else
-			/*
-			 * Enable VBUS Valid, AValid and IDDIG
-			 * high impedance
-			 */
-			__raw_writel(IDDIG | AVALID | VBUSVALID,
-						ctrl_base + USBOTGHS_CONTROL);
-	} else {
-		/* Enable session END and IDIG to high impedance. */
-		__raw_writel(SESSEND | IDDIG, ctrl_base +
-					USBOTGHS_CONTROL);
-	}
-	return 0;
-}
-
-int omap4430_phy_suspend(struct device *dev, int suspend)
-{
-	if (suspend) {
-		/* Disable the clocks */
-		omap4430_phy_set_clk(dev, 0);
-		/* Power down the phy */
-		__raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF);
-
-		/* save the context */
-		usbotghs_control = __raw_readl(ctrl_base + USBOTGHS_CONTROL);
-	} else {
-		/* Enable the internel phy clcoks */
-		omap4430_phy_set_clk(dev, 1);
-		/* power on the phy */
-		if (__raw_readl(ctrl_base + CONTROL_DEV_CONF) & PHY_PD) {
-			__raw_writel(~PHY_PD, ctrl_base + CONTROL_DEV_CONF);
-			mdelay(200);
-		}
-
-		/* restore the context */
-		__raw_writel(usbotghs_control, ctrl_base + USBOTGHS_CONTROL);
-	}
-
-	return 0;
-}
-
-int omap4430_phy_exit(struct device *dev)
-{
-	if (ctrl_base)
-		iounmap(ctrl_base);
-	if (phyclk)
-		clk_put(phyclk);
-	if (clk48m)
-		clk_put(clk48m);
-	if (clk32k)
-		clk_put(clk32k);
-
-	return 0;
-}
-
 void am35x_musb_reset(void)
 {
 	u32	regval;
diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c
index 119d5a9..396d189 100644
--- a/arch/arm/mach-omap2/twl-common.c
+++ b/arch/arm/mach-omap2/twl-common.c
@@ -250,11 +250,6 @@ void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
 
 #if defined(CONFIG_ARCH_OMAP4)
 static struct twl4030_usb_data omap4_usb_pdata = {
-	.phy_init	= omap4430_phy_init,
-	.phy_exit	= omap4430_phy_exit,
-	.phy_power	= omap4430_phy_power,
-	.phy_set_clock	= omap4430_phy_set_clk,
-	.phy_suspend	= omap4430_phy_suspend,
 };
 
 static struct regulator_init_data omap4_vdac_idata = {
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH 1/3] drivers: usb: otg: add a new driver for omap usb2 phy
  2012-05-30 14:34   ` Kishon Vijay Abraham I
@ 2012-05-30 15:05     ` Shilimkar, Santosh
  -1 siblings, 0 replies; 23+ messages in thread
From: Shilimkar, Santosh @ 2012-05-30 15:05 UTC (permalink / raw)
  To: Kishon Vijay Abraham I
  Cc: tony, linux, gregkh, linux-omap, linux-arm-kernel, linux-kernel,
	linux-usb, balbi

On Wed, May 30, 2012 at 8:04 PM, Kishon Vijay Abraham I <kishon@ti.com> wrote:
> All phy related programming like enabling/disabling the clocks, powering
> on/off the phy is taken care of by this driver. It is also used for OTG
> related functionality like srp.
>
> Cc: Felipe Balbi <balbi@ti.com>
> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
> ---
>  drivers/usb/otg/Kconfig           |   17 ++-
>  drivers/usb/otg/Makefile          |    1 +
>  drivers/usb/otg/omap-usb2.c       |  232 +++++++++++++++++++++++++++++++++++++
>  include/linux/usb/omap_usb.h      |   47 ++++++++
>  include/linux/usb/phy_companion.h |   34 ++++++
>  5 files changed, 327 insertions(+), 4 deletions(-)
>  create mode 100644 drivers/usb/otg/omap-usb2.c
>  create mode 100644 include/linux/usb/omap_usb.h
>  create mode 100644 include/linux/usb/phy_companion.h
>

[...]

> diff --git a/drivers/usb/otg/omap-usb2.c b/drivers/usb/otg/omap-usb2.c
> new file mode 100644
> index 0000000..ccd74b6
> --- /dev/null
> +++ b/drivers/usb/otg/omap-usb2.c
> @@ -0,0 +1,232 @@
> +/*
> + * omap-usb2.c - USB PHY, talking to musb controller in OMAP.
> + *
> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com
s/2011/2012
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * Author: Kishon Vijay Abraham I <kishon@ti.com>
> + *
> + * 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.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + */
> +
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +#include <linux/of.h>
> +#include <linux/usb/omap_usb.h>
> +#include <linux/usb/phy_companion.h>
> +#include <linux/clk.h>
> +#include <linux/err.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/delay.h>
Do you need it ?

> +#include <linux/mfd/omap_control.h>
> +#include <linux/usb/omap4_usb_phy.h>
> +
> +/**
> + * omap_usb2_set_comparator - links the comparator present in the sytem with
> + *     this phy
> + * @comparator - the companion phy(comparator) for this phy
> + *
> + * The phy companion driver should call this API passing the phy_companion
> + * filled with set_vbus and start_srp to be used by usb phy.
> + *
> + * For use by phy companion driver
> + */
> +void omap_usb2_set_comparator(struct phy_companion *comparator)
> +{
> +       struct usb_phy  *x = usb_get_phy(USB_PHY_TYPE_USB2);
> +       struct omap_usb *phy = phy_to_omapusb(x);
> +
> +       phy->comparator = comparator;
> +}
> +EXPORT_SYMBOL_GPL(omap_usb2_set_comparator);
> +
> +static int omap_usb_set_vbus(struct usb_otg *otg, bool enabled)
> +{
> +       struct omap_usb *phy = phy_to_omapusb(otg->phy);
> +
> +       if (!phy->comparator)
> +               return -ENODEV;
> +
> +       return phy->comparator->set_vbus(phy->comparator, enabled);
> +}
> +
> +static int omap_usb_start_srp(struct usb_otg *otg)
> +{
> +       struct omap_usb *phy = phy_to_omapusb(otg->phy);
> +
> +       if (!phy->comparator)
> +               return -ENODEV;
> +
> +       return phy->comparator->start_srp(phy->comparator);
> +}
> +
> +static int omap_usb_set_host(struct usb_otg *otg, struct usb_bus *host)
> +{
> +       struct usb_phy  *phy = otg->phy;
> +
> +       otg->host = host;
> +       if (!host)
> +               phy->state = OTG_STATE_UNDEFINED;
> +
> +       return 0;
> +}
> +
> +static int omap_usb_set_peripheral(struct usb_otg *otg,
> +               struct usb_gadget *gadget)
> +{
> +       struct usb_phy  *phy = otg->phy;
> +
> +       otg->gadget = gadget;
> +       if (!gadget)
> +               phy->state = OTG_STATE_UNDEFINED;
> +
> +       return 0;
> +}
> +
> +static int omap_usb2_suspend(struct usb_phy *x, int suspend)
> +{
> +       struct omap_usb *phy = phy_to_omapusb(x);
> +
> +       if (suspend && !phy->is_suspended) {
> +               pm_runtime_put_sync(phy->dev);
> +               phy->is_suspended = 1;
> +       } else if (!suspend && phy->is_suspended) {
> +               pm_runtime_get_sync(phy->dev);
> +               phy->is_suspended = 0;
> +       }
> +
> +       return 0;
> +}
> +
> +static int __devinit omap_usb2_probe(struct platform_device *pdev)
> +{
> +       struct omap_usb                 *phy;
> +       struct usb_otg                  *otg;
> +
> +       phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
> +       if (!phy) {
> +               dev_err(&pdev->dev, "unable to allocate memory for USB2 PHY\n");
> +               return -ENOMEM;
> +       }
> +
> +       otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
> +       if (!otg) {
> +               dev_err(&pdev->dev, "unable to allocate memory for USB OTG\n");
> +               return -ENOMEM;
> +       }
> +
> +       phy->dev                = &pdev->dev;
> +
> +       phy->phy.dev            = phy->dev;
> +       phy->phy.label          = "omap-usb2";
> +       phy->phy.set_suspend    = omap_usb2_suspend;
> +       phy->phy.otg            = otg;
> +
> +       phy->control_dev        = omap_control_get();
> +       if (IS_ERR(phy->control_dev)) {
> +               dev_err(&pdev->dev, "no control device present in system\n");
> +               return PTR_ERR(phy->control_dev);
> +       }
> +
> +       phy->is_suspended       = 1;
> +       omap4_usb_phy_power(phy->control_dev, 0);
> +
> +       otg->set_host           = omap_usb_set_host;
> +       otg->set_peripheral     = omap_usb_set_peripheral;
> +       otg->set_vbus           = omap_usb_set_vbus;
> +       otg->start_srp          = omap_usb_start_srp;
> +       otg->phy                = &phy->phy;
> +
> +       phy->wkupclk = clk_get(phy->dev, "usb_phy_cm_clk32k");
Error check missing here.

> +
> +       usb_add_phy(&phy->phy, USB_PHY_TYPE_USB2);
> +
unnecessary extra line
> +       platform_set_drvdata(pdev, phy);
> +
this one too
> +       pm_runtime_enable(phy->dev);
> +
> +       return 0;
> +}
> +
> +static int __devexit omap_usb2_remove(struct platform_device *pdev)
> +{
> +       struct omap_usb *phy = platform_get_drvdata(pdev);
> +
> +       usb_remove_phy(&phy->phy);
> +       platform_set_drvdata(pdev, NULL);
> +
> +       return 0;
> +}
> +
> +#ifdef CONFIG_PM
s/ CONFIG_PM/CONFIG_SUSPEND
otherwise you will get build warning with !CONFIG_SUSPEND

> +
> +static int omap_usb2_runtime_suspend(struct device *dev)
> +{
> +       struct platform_device  *pdev = to_platform_device(dev);
> +       struct omap_usb *phy = platform_get_drvdata(pdev);
> +
> +       clk_disable(phy->wkupclk);
> +       omap4_usb_phy_power(phy->control_dev, 0);
> +
> +       return 0;
> +}
> +
> +static int omap_usb2_runtime_resume(struct device *dev)
> +{
> +       struct platform_device  *pdev = to_platform_device(dev);
> +       struct omap_usb *phy = platform_get_drvdata(pdev);
> +
> +       omap4_usb_phy_power(phy->control_dev, 1);
> +       clk_enable(phy->wkupclk);
> +
> +       return 0;
> +}
> +
> +static const struct dev_pm_ops omap_usb2_pm_ops = {
> +       SET_RUNTIME_PM_OPS(omap_usb2_runtime_suspend, omap_usb2_runtime_resume,
> +               NULL)
> +};
> +
> +#define DEV_PM_OPS     (&omap_usb2_pm_ops)
> +#else
> +#define DEV_PM_OPS     NULL
> +#endif
> +
> +static struct platform_driver omap_usb2_driver = {
> +       .probe          = omap_usb2_probe,
> +       .remove         = __devexit_p(omap_usb2_remove),
> +       .driver         = {
> +               .name   = "omap-usb2",
> +               .owner  = THIS_MODULE,
> +               .pm     = DEV_PM_OPS,
> +       },
> +};
> +
> +static int __init usb2_omap_init(void)
> +{
> +       return platform_driver_register(&omap_usb2_driver);
> +}
> +arch_initcall(usb2_omap_init);
> +
> +static void __exit usb2_omap_exit(void)
> +{
> +       platform_driver_unregister(&omap_usb2_driver);
> +}
> +module_exit(usb2_omap_exit);
> +
> +MODULE_ALIAS("platform: omap_usb2");
> +MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
> +MODULE_DESCRIPTION("OMAP USB2 PHY DRIVER");
> +MODULE_LICENSE("GPL");
> diff --git a/include/linux/usb/omap_usb.h b/include/linux/usb/omap_usb.h
> new file mode 100644
> index 0000000..8d781df
> --- /dev/null
> +++ b/include/linux/usb/omap_usb.h
> @@ -0,0 +1,47 @@
> +/*
> + * omap_usb.h -- omap usb2 phy header file
> + *
> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com
s/2011/2012

> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * Author: Kishon Vijay Abraham I <kishon@ti.com>
> + *
> + * 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.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + */
> +
> +#ifndef __DRIVERS_OMAP_USB2_H
> +#define __DRIVERS_OMAP_USB2_H
> +
> +#include <linux/usb/otg.h>
> +
> +struct omap_usb {
> +       struct usb_phy          phy;
> +       struct phy_companion    *comparator;
> +       struct device           *dev;
> +       struct device           *control_dev;
> +       struct clk              *wkupclk;
> +       u8                      is_suspended:1;
> +};
> +
> +#define        phy_to_omapusb(x)       container_of((x), struct omap_usb, phy)
> +
> +#if defined(CONFIG_OMAP_USB2) || defined(CONFIG_OMAP_USB2_MODULE)
> +void omap_usb2_set_comparator(struct phy_companion *comparator);
> +#else
> +static inline void omap_usb2_set_comparator(struct phy_companion *comparator)
> +{
> +}
> +#endif
> +
> +#endif /* __DRIVERS_OMAP_USB_H */
> diff --git a/include/linux/usb/phy_companion.h b/include/linux/usb/phy_companion.h
> new file mode 100644
> index 0000000..321290f
> --- /dev/null
> +++ b/include/linux/usb/phy_companion.h
> @@ -0,0 +1,34 @@
> +/*
> + * phy-companion.h -- phy companion to indicate the comparator part of PHY
> + *
> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com
Here too..

Regards
Santosh

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [RFC PATCH 1/3] drivers: usb: otg: add a new driver for omap usb2 phy
@ 2012-05-30 15:05     ` Shilimkar, Santosh
  0 siblings, 0 replies; 23+ messages in thread
From: Shilimkar, Santosh @ 2012-05-30 15:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, May 30, 2012 at 8:04 PM, Kishon Vijay Abraham I <kishon@ti.com> wrote:
> All phy related programming like enabling/disabling the clocks, powering
> on/off the phy is taken care of by this driver. It is also used for OTG
> related functionality like srp.
>
> Cc: Felipe Balbi <balbi@ti.com>
> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
> ---
> ?drivers/usb/otg/Kconfig ? ? ? ? ? | ? 17 ++-
> ?drivers/usb/otg/Makefile ? ? ? ? ?| ? ?1 +
> ?drivers/usb/otg/omap-usb2.c ? ? ? | ?232 +++++++++++++++++++++++++++++++++++++
> ?include/linux/usb/omap_usb.h ? ? ?| ? 47 ++++++++
> ?include/linux/usb/phy_companion.h | ? 34 ++++++
> ?5 files changed, 327 insertions(+), 4 deletions(-)
> ?create mode 100644 drivers/usb/otg/omap-usb2.c
> ?create mode 100644 include/linux/usb/omap_usb.h
> ?create mode 100644 include/linux/usb/phy_companion.h
>

[...]

> diff --git a/drivers/usb/otg/omap-usb2.c b/drivers/usb/otg/omap-usb2.c
> new file mode 100644
> index 0000000..ccd74b6
> --- /dev/null
> +++ b/drivers/usb/otg/omap-usb2.c
> @@ -0,0 +1,232 @@
> +/*
> + * omap-usb2.c - USB PHY, talking to musb controller in OMAP.
> + *
> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com
s/2011/2012
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * Author: Kishon Vijay Abraham I <kishon@ti.com>
> + *
> + * 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.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + */
> +
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +#include <linux/of.h>
> +#include <linux/usb/omap_usb.h>
> +#include <linux/usb/phy_companion.h>
> +#include <linux/clk.h>
> +#include <linux/err.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/delay.h>
Do you need it ?

> +#include <linux/mfd/omap_control.h>
> +#include <linux/usb/omap4_usb_phy.h>
> +
> +/**
> + * omap_usb2_set_comparator - links the comparator present in the sytem with
> + * ? ? this phy
> + * @comparator - the companion phy(comparator) for this phy
> + *
> + * The phy companion driver should call this API passing the phy_companion
> + * filled with set_vbus and start_srp to be used by usb phy.
> + *
> + * For use by phy companion driver
> + */
> +void omap_usb2_set_comparator(struct phy_companion *comparator)
> +{
> + ? ? ? struct usb_phy ?*x = usb_get_phy(USB_PHY_TYPE_USB2);
> + ? ? ? struct omap_usb *phy = phy_to_omapusb(x);
> +
> + ? ? ? phy->comparator = comparator;
> +}
> +EXPORT_SYMBOL_GPL(omap_usb2_set_comparator);
> +
> +static int omap_usb_set_vbus(struct usb_otg *otg, bool enabled)
> +{
> + ? ? ? struct omap_usb *phy = phy_to_omapusb(otg->phy);
> +
> + ? ? ? if (!phy->comparator)
> + ? ? ? ? ? ? ? return -ENODEV;
> +
> + ? ? ? return phy->comparator->set_vbus(phy->comparator, enabled);
> +}
> +
> +static int omap_usb_start_srp(struct usb_otg *otg)
> +{
> + ? ? ? struct omap_usb *phy = phy_to_omapusb(otg->phy);
> +
> + ? ? ? if (!phy->comparator)
> + ? ? ? ? ? ? ? return -ENODEV;
> +
> + ? ? ? return phy->comparator->start_srp(phy->comparator);
> +}
> +
> +static int omap_usb_set_host(struct usb_otg *otg, struct usb_bus *host)
> +{
> + ? ? ? struct usb_phy ?*phy = otg->phy;
> +
> + ? ? ? otg->host = host;
> + ? ? ? if (!host)
> + ? ? ? ? ? ? ? phy->state = OTG_STATE_UNDEFINED;
> +
> + ? ? ? return 0;
> +}
> +
> +static int omap_usb_set_peripheral(struct usb_otg *otg,
> + ? ? ? ? ? ? ? struct usb_gadget *gadget)
> +{
> + ? ? ? struct usb_phy ?*phy = otg->phy;
> +
> + ? ? ? otg->gadget = gadget;
> + ? ? ? if (!gadget)
> + ? ? ? ? ? ? ? phy->state = OTG_STATE_UNDEFINED;
> +
> + ? ? ? return 0;
> +}
> +
> +static int omap_usb2_suspend(struct usb_phy *x, int suspend)
> +{
> + ? ? ? struct omap_usb *phy = phy_to_omapusb(x);
> +
> + ? ? ? if (suspend && !phy->is_suspended) {
> + ? ? ? ? ? ? ? pm_runtime_put_sync(phy->dev);
> + ? ? ? ? ? ? ? phy->is_suspended = 1;
> + ? ? ? } else if (!suspend && phy->is_suspended) {
> + ? ? ? ? ? ? ? pm_runtime_get_sync(phy->dev);
> + ? ? ? ? ? ? ? phy->is_suspended = 0;
> + ? ? ? }
> +
> + ? ? ? return 0;
> +}
> +
> +static int __devinit omap_usb2_probe(struct platform_device *pdev)
> +{
> + ? ? ? struct omap_usb ? ? ? ? ? ? ? ? *phy;
> + ? ? ? struct usb_otg ? ? ? ? ? ? ? ? ?*otg;
> +
> + ? ? ? phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
> + ? ? ? if (!phy) {
> + ? ? ? ? ? ? ? dev_err(&pdev->dev, "unable to allocate memory for USB2 PHY\n");
> + ? ? ? ? ? ? ? return -ENOMEM;
> + ? ? ? }
> +
> + ? ? ? otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
> + ? ? ? if (!otg) {
> + ? ? ? ? ? ? ? dev_err(&pdev->dev, "unable to allocate memory for USB OTG\n");
> + ? ? ? ? ? ? ? return -ENOMEM;
> + ? ? ? }
> +
> + ? ? ? phy->dev ? ? ? ? ? ? ? ?= &pdev->dev;
> +
> + ? ? ? phy->phy.dev ? ? ? ? ? ?= phy->dev;
> + ? ? ? phy->phy.label ? ? ? ? ?= "omap-usb2";
> + ? ? ? phy->phy.set_suspend ? ?= omap_usb2_suspend;
> + ? ? ? phy->phy.otg ? ? ? ? ? ?= otg;
> +
> + ? ? ? phy->control_dev ? ? ? ?= omap_control_get();
> + ? ? ? if (IS_ERR(phy->control_dev)) {
> + ? ? ? ? ? ? ? dev_err(&pdev->dev, "no control device present in system\n");
> + ? ? ? ? ? ? ? return PTR_ERR(phy->control_dev);
> + ? ? ? }
> +
> + ? ? ? phy->is_suspended ? ? ? = 1;
> + ? ? ? omap4_usb_phy_power(phy->control_dev, 0);
> +
> + ? ? ? otg->set_host ? ? ? ? ? = omap_usb_set_host;
> + ? ? ? otg->set_peripheral ? ? = omap_usb_set_peripheral;
> + ? ? ? otg->set_vbus ? ? ? ? ? = omap_usb_set_vbus;
> + ? ? ? otg->start_srp ? ? ? ? ?= omap_usb_start_srp;
> + ? ? ? otg->phy ? ? ? ? ? ? ? ?= &phy->phy;
> +
> + ? ? ? phy->wkupclk = clk_get(phy->dev, "usb_phy_cm_clk32k");
Error check missing here.

> +
> + ? ? ? usb_add_phy(&phy->phy, USB_PHY_TYPE_USB2);
> +
unnecessary extra line
> + ? ? ? platform_set_drvdata(pdev, phy);
> +
this one too
> + ? ? ? pm_runtime_enable(phy->dev);
> +
> + ? ? ? return 0;
> +}
> +
> +static int __devexit omap_usb2_remove(struct platform_device *pdev)
> +{
> + ? ? ? struct omap_usb *phy = platform_get_drvdata(pdev);
> +
> + ? ? ? usb_remove_phy(&phy->phy);
> + ? ? ? platform_set_drvdata(pdev, NULL);
> +
> + ? ? ? return 0;
> +}
> +
> +#ifdef CONFIG_PM
s/ CONFIG_PM/CONFIG_SUSPEND
otherwise you will get build warning with !CONFIG_SUSPEND

> +
> +static int omap_usb2_runtime_suspend(struct device *dev)
> +{
> + ? ? ? struct platform_device ?*pdev = to_platform_device(dev);
> + ? ? ? struct omap_usb *phy = platform_get_drvdata(pdev);
> +
> + ? ? ? clk_disable(phy->wkupclk);
> + ? ? ? omap4_usb_phy_power(phy->control_dev, 0);
> +
> + ? ? ? return 0;
> +}
> +
> +static int omap_usb2_runtime_resume(struct device *dev)
> +{
> + ? ? ? struct platform_device ?*pdev = to_platform_device(dev);
> + ? ? ? struct omap_usb *phy = platform_get_drvdata(pdev);
> +
> + ? ? ? omap4_usb_phy_power(phy->control_dev, 1);
> + ? ? ? clk_enable(phy->wkupclk);
> +
> + ? ? ? return 0;
> +}
> +
> +static const struct dev_pm_ops omap_usb2_pm_ops = {
> + ? ? ? SET_RUNTIME_PM_OPS(omap_usb2_runtime_suspend, omap_usb2_runtime_resume,
> + ? ? ? ? ? ? ? NULL)
> +};
> +
> +#define DEV_PM_OPS ? ? (&omap_usb2_pm_ops)
> +#else
> +#define DEV_PM_OPS ? ? NULL
> +#endif
> +
> +static struct platform_driver omap_usb2_driver = {
> + ? ? ? .probe ? ? ? ? ?= omap_usb2_probe,
> + ? ? ? .remove ? ? ? ? = __devexit_p(omap_usb2_remove),
> + ? ? ? .driver ? ? ? ? = {
> + ? ? ? ? ? ? ? .name ? = "omap-usb2",
> + ? ? ? ? ? ? ? .owner ?= THIS_MODULE,
> + ? ? ? ? ? ? ? .pm ? ? = DEV_PM_OPS,
> + ? ? ? },
> +};
> +
> +static int __init usb2_omap_init(void)
> +{
> + ? ? ? return platform_driver_register(&omap_usb2_driver);
> +}
> +arch_initcall(usb2_omap_init);
> +
> +static void __exit usb2_omap_exit(void)
> +{
> + ? ? ? platform_driver_unregister(&omap_usb2_driver);
> +}
> +module_exit(usb2_omap_exit);
> +
> +MODULE_ALIAS("platform: omap_usb2");
> +MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
> +MODULE_DESCRIPTION("OMAP USB2 PHY DRIVER");
> +MODULE_LICENSE("GPL");
> diff --git a/include/linux/usb/omap_usb.h b/include/linux/usb/omap_usb.h
> new file mode 100644
> index 0000000..8d781df
> --- /dev/null
> +++ b/include/linux/usb/omap_usb.h
> @@ -0,0 +1,47 @@
> +/*
> + * omap_usb.h -- omap usb2 phy header file
> + *
> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com
s/2011/2012

> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * Author: Kishon Vijay Abraham I <kishon@ti.com>
> + *
> + * 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.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + */
> +
> +#ifndef __DRIVERS_OMAP_USB2_H
> +#define __DRIVERS_OMAP_USB2_H
> +
> +#include <linux/usb/otg.h>
> +
> +struct omap_usb {
> + ? ? ? struct usb_phy ? ? ? ? ?phy;
> + ? ? ? struct phy_companion ? ?*comparator;
> + ? ? ? struct device ? ? ? ? ? *dev;
> + ? ? ? struct device ? ? ? ? ? *control_dev;
> + ? ? ? struct clk ? ? ? ? ? ? ?*wkupclk;
> + ? ? ? u8 ? ? ? ? ? ? ? ? ? ? ?is_suspended:1;
> +};
> +
> +#define ? ? ? ?phy_to_omapusb(x) ? ? ? container_of((x), struct omap_usb, phy)
> +
> +#if defined(CONFIG_OMAP_USB2) || defined(CONFIG_OMAP_USB2_MODULE)
> +void omap_usb2_set_comparator(struct phy_companion *comparator);
> +#else
> +static inline void omap_usb2_set_comparator(struct phy_companion *comparator)
> +{
> +}
> +#endif
> +
> +#endif /* __DRIVERS_OMAP_USB_H */
> diff --git a/include/linux/usb/phy_companion.h b/include/linux/usb/phy_companion.h
> new file mode 100644
> index 0000000..321290f
> --- /dev/null
> +++ b/include/linux/usb/phy_companion.h
> @@ -0,0 +1,34 @@
> +/*
> + * phy-companion.h -- phy companion to indicate the comparator part of PHY
> + *
> + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com
Here too..

Regards
Santosh

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH 3/3] arm: omap: phy: remove unused functions from omap-phy-internal.c
@ 2012-05-30 15:09     ` Shilimkar, Santosh
  0 siblings, 0 replies; 23+ messages in thread
From: Shilimkar, Santosh @ 2012-05-30 15:09 UTC (permalink / raw)
  To: Kishon Vijay Abraham I
  Cc: tony, linux, gregkh, linux-omap, linux-arm-kernel, linux-kernel,
	linux-usb, balbi

On Wed, May 30, 2012 at 8:04 PM, Kishon Vijay Abraham I <kishon@ti.com> wrote:
> All the unnessary functions in omap-phy-internal is removed.
> These functionality are now handled by omap-usb2 phy driver.
>
Cool. One less item in platform code.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH 3/3] arm: omap: phy: remove unused functions from omap-phy-internal.c
@ 2012-05-30 15:09     ` Shilimkar, Santosh
  0 siblings, 0 replies; 23+ messages in thread
From: Shilimkar, Santosh @ 2012-05-30 15:09 UTC (permalink / raw)
  To: Kishon Vijay Abraham I
  Cc: tony-4v6yS6AI5VpBDgjK7y7TUQ, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-usb-u79uwXL29TY76Z2rM5mHXA, balbi-l0cyMroinI0

On Wed, May 30, 2012 at 8:04 PM, Kishon Vijay Abraham I <kishon-l0cyMroinI0@public.gmane.org> wrote:
> All the unnessary functions in omap-phy-internal is removed.
> These functionality are now handled by omap-usb2 phy driver.
>
Cool. One less item in platform code.
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [RFC PATCH 3/3] arm: omap: phy: remove unused functions from omap-phy-internal.c
@ 2012-05-30 15:09     ` Shilimkar, Santosh
  0 siblings, 0 replies; 23+ messages in thread
From: Shilimkar, Santosh @ 2012-05-30 15:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, May 30, 2012 at 8:04 PM, Kishon Vijay Abraham I <kishon@ti.com> wrote:
> All the unnessary functions in omap-phy-internal is removed.
> These functionality are now handled by omap-usb2 phy driver.
>
Cool. One less item in platform code.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH 0/3] usb: musb: add new phy driver
  2012-05-30 14:34 ` Kishon Vijay Abraham I
@ 2012-06-12 10:48   ` Felipe Balbi
  -1 siblings, 0 replies; 23+ messages in thread
From: Felipe Balbi @ 2012-06-12 10:48 UTC (permalink / raw)
  To: Kishon Vijay Abraham I
  Cc: tony, linux, gregkh, linux-omap, linux-arm-kernel, linux-kernel,
	linux-usb, balbi

[-- Attachment #1: Type: text/plain, Size: 1187 bytes --]

On Wed, May 30, 2012 at 08:04:23PM +0530, Kishon Vijay Abraham I wrote:
> This series adds a new usb2 phy driver. The device for which is created
> by the ocp2scp driver. This also uses control module driver.
> 
> This series converts twl6030 as a comparator driver (previously it was
> also the phy driver) and makes use of omap-usb2 as the phy driver.
> 
> Instead of notification mechanism by power chip to omap glue to pass detection
> of any events, an export API has been added in omap glue. Both twl4030 and
> twl6030 will call to this API to pass any event. (twl6030 is used in omap4 and
> twl4030 is used in omap3).
> 
> This series depends on:
> *[RFC PATCH 00/11] OMAP System Control Module* patch series
> However System Control Module driver has only dt support, so wouldn't
> be able to test this patch series. However I'll adapt omap usb2 phy
> driver and musb driver for dt and send it asap to the list.
> 
> This series also depends on:
> *[PATCH v3 0/3] usb: multi-phy support* patch series
> *[RFC PATCH 0/5] omap: add ocp2scp as a misc driver* patch series
> 
> Compile tested only.

are we getting new version of this series ?

-- 
balbi

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [RFC PATCH 0/3] usb: musb: add new phy driver
@ 2012-06-12 10:48   ` Felipe Balbi
  0 siblings, 0 replies; 23+ messages in thread
From: Felipe Balbi @ 2012-06-12 10:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, May 30, 2012 at 08:04:23PM +0530, Kishon Vijay Abraham I wrote:
> This series adds a new usb2 phy driver. The device for which is created
> by the ocp2scp driver. This also uses control module driver.
> 
> This series converts twl6030 as a comparator driver (previously it was
> also the phy driver) and makes use of omap-usb2 as the phy driver.
> 
> Instead of notification mechanism by power chip to omap glue to pass detection
> of any events, an export API has been added in omap glue. Both twl4030 and
> twl6030 will call to this API to pass any event. (twl6030 is used in omap4 and
> twl4030 is used in omap3).
> 
> This series depends on:
> *[RFC PATCH 00/11] OMAP System Control Module* patch series
> However System Control Module driver has only dt support, so wouldn't
> be able to test this patch series. However I'll adapt omap usb2 phy
> driver and musb driver for dt and send it asap to the list.
> 
> This series also depends on:
> *[PATCH v3 0/3] usb: multi-phy support* patch series
> *[RFC PATCH 0/5] omap: add ocp2scp as a misc driver* patch series
> 
> Compile tested only.

are we getting new version of this series ?

-- 
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120612/702f7f0b/attachment.sig>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH 0/3] usb: musb: add new phy driver
  2012-06-12 10:48   ` Felipe Balbi
@ 2012-06-13 14:28     ` ABRAHAM, KISHON VIJAY
  -1 siblings, 0 replies; 23+ messages in thread
From: ABRAHAM, KISHON VIJAY @ 2012-06-13 14:28 UTC (permalink / raw)
  To: balbi
  Cc: tony, linux, gregkh, linux-omap, linux-arm-kernel, linux-kernel,
	linux-usb

Hi,

On Tue, Jun 12, 2012 at 4:18 PM, Felipe Balbi <balbi@ti.com> wrote:
> On Wed, May 30, 2012 at 08:04:23PM +0530, Kishon Vijay Abraham I wrote:
>> This series adds a new usb2 phy driver. The device for which is created
>> by the ocp2scp driver. This also uses control module driver.
>>
>> This series converts twl6030 as a comparator driver (previously it was
>> also the phy driver) and makes use of omap-usb2 as the phy driver.
>>
>> Instead of notification mechanism by power chip to omap glue to pass detection
>> of any events, an export API has been added in omap glue. Both twl4030 and
>> twl6030 will call to this API to pass any event. (twl6030 is used in omap4 and
>> twl4030 is used in omap3).
>>
>> This series depends on:
>> *[RFC PATCH 00/11] OMAP System Control Module* patch series
>> However System Control Module driver has only dt support, so wouldn't
>> be able to test this patch series. However I'll adapt omap usb2 phy
>> driver and musb driver for dt and send it asap to the list.
>>
>> This series also depends on:
>> *[PATCH v3 0/3] usb: multi-phy support* patch series
>> *[RFC PATCH 0/5] omap: add ocp2scp as a misc driver* patch series
>>
>> Compile tested only.
>
> are we getting new version of this series ?

Yes. I'm planning to send a new version with only dt support by next week.

Thanks
Kishon

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [RFC PATCH 0/3] usb: musb: add new phy driver
@ 2012-06-13 14:28     ` ABRAHAM, KISHON VIJAY
  0 siblings, 0 replies; 23+ messages in thread
From: ABRAHAM, KISHON VIJAY @ 2012-06-13 14:28 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Tue, Jun 12, 2012 at 4:18 PM, Felipe Balbi <balbi@ti.com> wrote:
> On Wed, May 30, 2012 at 08:04:23PM +0530, Kishon Vijay Abraham I wrote:
>> This series adds a new usb2 phy driver. The device for which is created
>> by the ocp2scp driver. This also uses control module driver.
>>
>> This series converts twl6030 as a comparator driver (previously it was
>> also the phy driver) and makes use of omap-usb2 as the phy driver.
>>
>> Instead of notification mechanism by power chip to omap glue to pass detection
>> of any events, an export API has been added in omap glue. Both twl4030 and
>> twl6030 will call to this API to pass any event. (twl6030 is used in omap4 and
>> twl4030 is used in omap3).
>>
>> This series depends on:
>> *[RFC PATCH 00/11] OMAP System Control Module* patch series
>> However System Control Module driver has only dt support, so wouldn't
>> be able to test this patch series. However I'll adapt omap usb2 phy
>> driver and musb driver for dt and send it asap to the list.
>>
>> This series also depends on:
>> *[PATCH v3 0/3] usb: multi-phy support* patch series
>> *[RFC PATCH 0/5] omap: add ocp2scp as a misc driver* patch series
>>
>> Compile tested only.
>
> are we getting new version of this series ?

Yes. I'm planning to send a new version with only dt support by next week.

Thanks
Kishon

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH 3/3] arm: omap: phy: remove unused functions from omap-phy-internal.c
  2012-05-30 14:34   ` Kishon Vijay Abraham I
@ 2012-06-20 10:44     ` Tony Lindgren
  -1 siblings, 0 replies; 23+ messages in thread
From: Tony Lindgren @ 2012-06-20 10:44 UTC (permalink / raw)
  To: Kishon Vijay Abraham I
  Cc: linux, gregkh, linux-omap, linux-arm-kernel, linux-kernel,
	linux-usb, balbi

* Kishon Vijay Abraham I <kishon@ti.com> [120530 07:38]:
> All the unnessary functions in omap-phy-internal is removed.
> These functionality are now handled by omap-usb2 phy driver.

Glad to see these move to live under drivers. Up to Felipe
to merge via linux-usb once the driver parts are finished:

Acked-by: Tony Lindgren <tony@atomide.com>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [RFC PATCH 3/3] arm: omap: phy: remove unused functions from omap-phy-internal.c
@ 2012-06-20 10:44     ` Tony Lindgren
  0 siblings, 0 replies; 23+ messages in thread
From: Tony Lindgren @ 2012-06-20 10:44 UTC (permalink / raw)
  To: linux-arm-kernel

* Kishon Vijay Abraham I <kishon@ti.com> [120530 07:38]:
> All the unnessary functions in omap-phy-internal is removed.
> These functionality are now handled by omap-usb2 phy driver.

Glad to see these move to live under drivers. Up to Felipe
to merge via linux-usb once the driver parts are finished:

Acked-by: Tony Lindgren <tony@atomide.com>

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2012-06-20 10:44 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-05-30 14:34 [RFC PATCH 0/3] usb: musb: add new phy driver Kishon Vijay Abraham I
2012-05-30 14:34 ` Kishon Vijay Abraham I
2012-05-30 14:34 ` Kishon Vijay Abraham I
2012-05-30 14:34 ` [RFC PATCH 1/3] drivers: usb: otg: add a new driver for omap usb2 phy Kishon Vijay Abraham I
2012-05-30 14:34   ` Kishon Vijay Abraham I
2012-05-30 14:34   ` Kishon Vijay Abraham I
2012-05-30 15:05   ` Shilimkar, Santosh
2012-05-30 15:05     ` Shilimkar, Santosh
2012-05-30 14:34 ` [RFC PATCH 2/3] usb: musb: omap glue: use omap-usb2 as the phy driver Kishon Vijay Abraham I
2012-05-30 14:34   ` Kishon Vijay Abraham I
2012-05-30 14:34   ` Kishon Vijay Abraham I
2012-05-30 14:34 ` [RFC PATCH 3/3] arm: omap: phy: remove unused functions from omap-phy-internal.c Kishon Vijay Abraham I
2012-05-30 14:34   ` Kishon Vijay Abraham I
2012-05-30 14:34   ` Kishon Vijay Abraham I
2012-05-30 15:09   ` Shilimkar, Santosh
2012-05-30 15:09     ` Shilimkar, Santosh
2012-05-30 15:09     ` Shilimkar, Santosh
2012-06-20 10:44   ` Tony Lindgren
2012-06-20 10:44     ` Tony Lindgren
2012-06-12 10:48 ` [RFC PATCH 0/3] usb: musb: add new phy driver Felipe Balbi
2012-06-12 10:48   ` Felipe Balbi
2012-06-13 14:28   ` ABRAHAM, KISHON VIJAY
2012-06-13 14:28     ` ABRAHAM, KISHON VIJAY

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.