]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
usb: phy: twl4030: use the new generic PHY framework
authorKishon Vijay Abraham I <kishon@ti.com>
Fri, 27 Sep 2013 06:23:27 +0000 (11:53 +0530)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 28 Sep 2013 00:36:58 +0000 (17:36 -0700)
Used the generic PHY framework API to create the PHY. For powering on
and powering off the PHY, power_on and power_off ops are used. Once the
MUSB OMAP glue is adapted to the new framework, the suspend and resume
ops of usb phy library will be removed. Also twl4030-usb driver is moved
to drivers/phy/.

However using the old usb phy library cannot be completely removed
because otg is intertwined with phy and moving to the new
framework completely will break otg. Once we have a separate otg state machine,
we can get rid of the usb phy library.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/phy/Kconfig
drivers/phy/Makefile
drivers/phy/phy-twl4030-usb.c [moved from drivers/usb/phy/phy-twl4030-usb.c with 95% similarity]
drivers/usb/phy/Kconfig
drivers/usb/phy/Makefile
include/linux/i2c/twl.h

index 38c3477ead4c1386a6b97732e14cf15becb481b1..ac239aca77ec6c61edf520e2c26ad3c98313b1fa 100644 (file)
@@ -27,4 +27,15 @@ config OMAP_USB2
          The USB OTG controller communicates with the comparator using this
          driver.
 
+config TWL4030_USB
+       tristate "TWL4030 USB Transceiver Driver"
+       depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
+       select GENERIC_PHY
+       select USB_PHY
+       help
+         Enable this to support the USB OTG transceiver on TWL4030
+         family chips (including the TWL5030 and TPS659x0 devices).
+         This transceiver supports high and full speed devices plus,
+         in host mode, low speed.
+
 endmenu
index ed5b088abaee1b2b7c274a7f96dbd54cd2c5d331..0dd8a98345482867c99d8019bfa068916e3e8429 100644 (file)
@@ -4,3 +4,4 @@
 
 obj-$(CONFIG_GENERIC_PHY)      += phy-core.o
 obj-$(CONFIG_OMAP_USB2)                += phy-omap-usb2.o
+obj-$(CONFIG_TWL4030_USB)      += phy-twl4030-usb.o
similarity index 95%
rename from drivers/usb/phy/phy-twl4030-usb.c
rename to drivers/phy/phy-twl4030-usb.c
index 90730c8762b8f8ee850a8a153ad757a4b5b3337e..d02913f9a6b1aae988e980fb83395611977f9942 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/usb/otg.h>
+#include <linux/phy/phy.h>
 #include <linux/usb/musb-omap.h>
 #include <linux/usb/ulpi.h>
 #include <linux/i2c/twl.h>
@@ -431,6 +432,14 @@ static void twl4030_phy_suspend(struct twl4030_usb *twl, int controller_off)
        dev_dbg(twl->dev, "%s\n", __func__);
 }
 
+static int twl4030_phy_power_off(struct phy *phy)
+{
+       struct twl4030_usb *twl = phy_get_drvdata(phy);
+
+       twl4030_phy_suspend(twl, 0);
+       return 0;
+}
+
 static void __twl4030_phy_resume(struct twl4030_usb *twl)
 {
        twl4030_phy_power(twl, 1);
@@ -459,6 +468,14 @@ static void twl4030_phy_resume(struct twl4030_usb *twl)
        }
 }
 
+static int twl4030_phy_power_on(struct phy *phy)
+{
+       struct twl4030_usb *twl = phy_get_drvdata(phy);
+
+       twl4030_phy_resume(twl);
+       return 0;
+}
+
 static int twl4030_usb_ldo_init(struct twl4030_usb *twl)
 {
        /* Enable writing to power configuration registers */
@@ -602,13 +619,22 @@ static int twl4030_usb_phy_init(struct usb_phy *phy)
        status = twl4030_usb_linkstat(twl);
        twl->linkstat = status;
 
-       if (status == OMAP_MUSB_ID_GROUND || status == OMAP_MUSB_VBUS_VALID)
+       if (status == OMAP_MUSB_ID_GROUND || status == OMAP_MUSB_VBUS_VALID) {
                omap_musb_mailbox(twl->linkstat);
+               twl4030_phy_resume(twl);
+       }
 
        sysfs_notify(&twl->dev->kobj, NULL, "vbus");
        return 0;
 }
 
+static int twl4030_phy_init(struct phy *phy)
+{
+       struct twl4030_usb *twl = phy_get_drvdata(phy);
+
+       return twl4030_usb_phy_init(&twl->phy);
+}
+
 static int twl4030_set_suspend(struct usb_phy *x, int suspend)
 {
        struct twl4030_usb *twl = phy_to_twl(x);
@@ -646,13 +672,23 @@ static int twl4030_set_host(struct usb_otg *otg, struct usb_bus *host)
        return 0;
 }
 
+static const struct phy_ops ops = {
+       .init           = twl4030_phy_init,
+       .power_on       = twl4030_phy_power_on,
+       .power_off      = twl4030_phy_power_off,
+       .owner          = THIS_MODULE,
+};
+
 static int twl4030_usb_probe(struct platform_device *pdev)
 {
        struct twl4030_usb_data *pdata = dev_get_platdata(&pdev->dev);
        struct twl4030_usb      *twl;
+       struct phy              *phy;
        int                     status, err;
        struct usb_otg          *otg;
        struct device_node      *np = pdev->dev.of_node;
+       struct phy_provider     *phy_provider;
+       struct phy_init_data    *init_data = NULL;
 
        twl = devm_kzalloc(&pdev->dev, sizeof *twl, GFP_KERNEL);
        if (!twl)
@@ -661,9 +697,10 @@ static int twl4030_usb_probe(struct platform_device *pdev)
        if (np)
                of_property_read_u32(np, "usb_mode",
                                (enum twl4030_usb_mode *)&twl->usb_mode);
-       else if (pdata)
+       else if (pdata) {
                twl->usb_mode = pdata->usb_mode;
-       else {
+               init_data = pdata->init_data;
+       } else {
                dev_err(&pdev->dev, "twl4030 initialized without pdata\n");
                return -EINVAL;
        }
@@ -689,6 +726,19 @@ static int twl4030_usb_probe(struct platform_device *pdev)
        otg->set_host           = twl4030_set_host;
        otg->set_peripheral     = twl4030_set_peripheral;
 
+       phy_provider = devm_of_phy_provider_register(twl->dev,
+               of_phy_simple_xlate);
+       if (IS_ERR(phy_provider))
+               return PTR_ERR(phy_provider);
+
+       phy = devm_phy_create(twl->dev, &ops, init_data);
+       if (IS_ERR(phy)) {
+               dev_dbg(&pdev->dev, "Failed to create PHY\n");
+               return PTR_ERR(phy);
+       }
+
+       phy_set_drvdata(phy, twl);
+
        /* init spinlock for workqueue */
        spin_lock_init(&twl->lock);
 
index 2ce041109993f5ef8adee212b76ac5173b4b4d6d..64b8bef1919e7e61dfcfc3c7f7bc4caff1486d1e 100644 (file)
@@ -113,16 +113,6 @@ config SAMSUNG_USB3PHY
          Enable this to support Samsung USB 3.0 (Super Speed) phy controller
          for samsung SoCs.
 
-config TWL4030_USB
-       tristate "TWL4030 USB Transceiver Driver"
-       depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
-       select USB_PHY
-       help
-         Enable this to support the USB OTG transceiver on TWL4030
-         family chips (including the TWL5030 and TPS659x0 devices).
-         This transceiver supports high and full speed devices plus,
-         in host mode, low speed.
-
 config TWL6030_USB
        tristate "TWL6030 USB Transceiver Driver"
        depends on TWL4030_CORE && OMAP_USB2 && USB_MUSB_OMAP2PLUS
index fa4db0e4bdb91c03cc6b4449132bfa8cd8439fae..9c3736109c2cb3ee35e0fa866b9b7cd3ee1df97b 100644 (file)
@@ -19,7 +19,6 @@ obj-$(CONFIG_OMAP_USB3)                       += phy-omap-usb3.o
 obj-$(CONFIG_SAMSUNG_USBPHY)           += phy-samsung-usb.o
 obj-$(CONFIG_SAMSUNG_USB2PHY)          += phy-samsung-usb2.o
 obj-$(CONFIG_SAMSUNG_USB3PHY)          += phy-samsung-usb3.o
-obj-$(CONFIG_TWL4030_USB)              += phy-twl4030-usb.o
 obj-$(CONFIG_TWL6030_USB)              += phy-twl6030-usb.o
 obj-$(CONFIG_USB_EHCI_TEGRA)           += phy-tegra-usb.o
 obj-$(CONFIG_USB_GPIO_VBUS)            += phy-gpio-vbus-usb.o
index 81cbbdb96aae2bff8969fd68fefc086231de3c4b..673a3ce67f311df6567aa780dfdbf3d7adbe0cf9 100644 (file)
@@ -26,6 +26,7 @@
 #define __TWL_H_
 
 #include <linux/types.h>
+#include <linux/phy/phy.h>
 #include <linux/input/matrix_keypad.h>
 
 /*
@@ -615,6 +616,7 @@ enum twl4030_usb_mode {
 struct twl4030_usb_data {
        enum twl4030_usb_mode   usb_mode;
        unsigned long           features;
+       struct phy_init_data    *init_data;
 
        int             (*phy_init)(struct device *dev);
        int             (*phy_exit)(struct device *dev);