From 6747caa76cab1150c60a772cf64f8cd47fa19d39 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Fri, 27 Sep 2013 11:53:27 +0530 Subject: [PATCH] usb: phy: twl4030: use the new generic PHY framework 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 Acked-by: Felipe Balbi Reviewed-by: Sylwester Nawrocki Signed-off-by: Greg Kroah-Hartman --- drivers/phy/Kconfig | 11 +++++ drivers/phy/Makefile | 1 + drivers/{usb => }/phy/phy-twl4030-usb.c | 56 +++++++++++++++++++++++-- drivers/usb/phy/Kconfig | 10 ----- drivers/usb/phy/Makefile | 1 - include/linux/i2c/twl.h | 2 + 6 files changed, 67 insertions(+), 14 deletions(-) rename drivers/{usb => }/phy/phy-twl4030-usb.c (95%) diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 38c3477ead4..ac239aca77e 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -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 diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index ed5b088abae..0dd8a983454 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -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 diff --git a/drivers/usb/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c similarity index 95% rename from drivers/usb/phy/phy-twl4030-usb.c rename to drivers/phy/phy-twl4030-usb.c index 90730c8762b..d02913f9a6b 100644 --- a/drivers/usb/phy/phy-twl4030-usb.c +++ b/drivers/phy/phy-twl4030-usb.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -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); diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 2ce04110999..64b8bef1919 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -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 diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index fa4db0e4bdb..9c3736109c2 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -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 diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h index 81cbbdb96aa..673a3ce67f3 100644 --- a/include/linux/i2c/twl.h +++ b/include/linux/i2c/twl.h @@ -26,6 +26,7 @@ #define __TWL_H_ #include +#include #include /* @@ -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); -- 2.46.0