summaryrefslogtreecommitdiffstats
path: root/drivers/usb/phy
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-08-13 15:28:01 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-08-13 15:28:01 -0700
commit165f60642ae988f0b9dcfd4988806e7a938b26c7 (patch)
tree29293f73a4b022620f68dbf48d7450e501be5855 /drivers/usb/phy
parentc23bda365dfbf56aa4d6d4a97f83136c36050e01 (diff)
parent8b841cb217fac676498de3dfe8fabe38b39cba4e (diff)
Merge tag 'usb-for-v3.12' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next
Felipe writes: usb: patches for v3.12 merge window All patches here have been pending on linux-usb and sitting in linux-next for a while now. The biggest things in this tag are: DWC3 learned proper usage of threaded IRQ handlers and now we spend very little time in hardirq context. MUSB now has proper support for BeagleBone and Beaglebone Black. Tegra's USB support also got quite a bit of love and is learning to use PHY layer and generic DT attributes. Other than that, the usual pack of cleanups and non-critical fixes follow. Signed-of-by: Felipe Balbi <balbi@ti.com> Conflicts: drivers/usb/gadget/udc-core.c drivers/usb/host/ehci-tegra.c drivers/usb/musb/omap2430.c drivers/usb/musb/tusb6010.c
Diffstat (limited to 'drivers/usb/phy')
-rw-r--r--drivers/usb/phy/Kconfig48
-rw-r--r--drivers/usb/phy/Makefile4
-rw-r--r--drivers/usb/phy/am35x-phy-control.h21
-rw-r--r--drivers/usb/phy/phy-am335x-control.c137
-rw-r--r--drivers/usb/phy/phy-am335x.c99
-rw-r--r--drivers/usb/phy/phy-fsl-usb.c6
-rw-r--r--drivers/usb/phy/phy-generic.c (renamed from drivers/usb/phy/phy-nop.c)167
-rw-r--r--drivers/usb/phy/phy-generic.h20
-rw-r--r--drivers/usb/phy/phy-gpio-vbus-usb.c10
-rw-r--r--drivers/usb/phy/phy-msm-usb.c4
-rw-r--r--drivers/usb/phy/phy-mv-u3d-usb.c4
-rw-r--r--drivers/usb/phy/phy-mv-usb.c6
-rw-r--r--drivers/usb/phy/phy-mxs-usb.c13
-rw-r--r--drivers/usb/phy/phy-omap-control.c3
-rw-r--r--drivers/usb/phy/phy-omap-usb3.c87
-rw-r--r--drivers/usb/phy/phy-rcar-usb.c9
-rw-r--r--drivers/usb/phy/phy-samsung-usb2.c2
-rw-r--r--drivers/usb/phy/phy-samsung-usb3.c2
-rw-r--r--drivers/usb/phy/phy-tegra-usb.c460
-rw-r--r--drivers/usb/phy/phy-twl4030-usb.c2
-rw-r--r--drivers/usb/phy/phy-twl6030-usb.c2
21 files changed, 799 insertions, 307 deletions
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
index b57514ba486a..d5589f9c60a9 100644
--- a/drivers/usb/phy/Kconfig
+++ b/drivers/usb/phy/Kconfig
@@ -1,22 +1,10 @@
#
# Physical Layer USB driver configuration
#
-menuconfig USB_PHY
- bool "USB Physical Layer drivers"
- help
- Most USB controllers have the physical layer signalling part
- (commonly called a PHY) built in. However, dual-role devices
- (a.k.a. USB on-the-go) which support being USB master or slave
- with the same connector often use an external PHY.
-
- The drivers in this submenu add support for such PHY devices.
- They are not needed for standard master-only (or the vast
- majority of slave-only) USB interfaces.
+menu "USB Physical Layer drivers"
- If you're not sure if this applies to you, it probably doesn't;
- say N here.
-
-if USB_PHY
+config USB_PHY
+ def_bool n
#
# USB Transceiver Drivers
@@ -24,6 +12,7 @@ if USB_PHY
config AB8500_USB
tristate "AB8500 USB Transceiver Driver"
depends on AB8500_CORE
+ select USB_PHY
help
Enable this to support the USB OTG transceiver in AB8500 chip.
This transceiver supports high and full speed devices plus,
@@ -33,12 +22,14 @@ config FSL_USB2_OTG
bool "Freescale USB OTG Transceiver Driver"
depends on USB_EHCI_FSL && USB_FSL_USB2 && PM_RUNTIME
select USB_OTG
+ select USB_PHY
help
Enable this to support Freescale USB OTG transceiver.
config ISP1301_OMAP
tristate "Philips ISP1301 with OMAP OTG"
depends on I2C && ARCH_OMAP_OTG
+ select USB_PHY
help
If you say yes here you get support for the Philips ISP1301
USB-On-The-Go transceiver working with the OMAP OTG controller.
@@ -52,12 +43,14 @@ config ISP1301_OMAP
config MV_U3D_PHY
bool "Marvell USB 3.0 PHY controller Driver"
depends on CPU_MMP3
+ select USB_PHY
help
Enable this to support Marvell USB 3.0 phy controller for Marvell
SoC.
config NOP_USB_XCEIV
tristate "NOP USB Transceiver Driver"
+ select USB_PHY
help
This driver is to be used by all the usb transceiver which are either
built-in with usb ip or which are autonomous and doesn't require any
@@ -77,6 +70,7 @@ config OMAP_USB2
tristate "OMAP USB2 PHY Driver"
depends on ARCH_OMAP2PLUS
select OMAP_CONTROL_USB
+ select USB_PHY
help
Enable this to support the transceiver that is part of SOC. This
driver takes care of all the PHY functionality apart from comparator.
@@ -87,12 +81,25 @@ config OMAP_USB3
tristate "OMAP USB3 PHY Driver"
depends on ARCH_OMAP2PLUS || COMPILE_TEST
select OMAP_CONTROL_USB
+ select USB_PHY
help
Enable this to support the USB3 PHY that is part of SOC. This
driver takes care of all the PHY functionality apart from comparator.
This driver interacts with the "OMAP Control USB Driver" to power
on/off the PHY.
+config AM335X_CONTROL_USB
+ tristate
+
+config AM335X_PHY_USB
+ tristate "AM335x USB PHY Driver"
+ select USB_PHY
+ select AM335X_CONTROL_USB
+ select NOP_USB_XCEIV
+ help
+ This driver provides PHY support for that phy which part for the
+ AM335x SoC.
+
config SAMSUNG_USBPHY
tristate
help
@@ -103,6 +110,7 @@ config SAMSUNG_USBPHY
config SAMSUNG_USB2PHY
tristate "Samsung USB 2.0 PHY controller Driver"
select SAMSUNG_USBPHY
+ select USB_PHY
help
Enable this to support Samsung USB 2.0 (High Speed) PHY controller
driver for Samsung SoCs.
@@ -110,6 +118,7 @@ config SAMSUNG_USB2PHY
config SAMSUNG_USB3PHY
tristate "Samsung USB 3.0 PHY controller Driver"
select SAMSUNG_USBPHY
+ select USB_PHY
help
Enable this to support Samsung USB 3.0 (Super Speed) phy controller
for samsung SoCs.
@@ -117,6 +126,7 @@ config SAMSUNG_USB3PHY
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).
@@ -137,6 +147,7 @@ config TWL6030_USB
config USB_GPIO_VBUS
tristate "GPIO based peripheral-only VBUS sensing 'transceiver'"
depends on GPIOLIB
+ select USB_PHY
help
Provides simple GPIO VBUS sensing for controllers with an
internal transceiver via the usb_phy interface, and
@@ -147,6 +158,7 @@ config USB_ISP1301
tristate "NXP ISP1301 USB transceiver support"
depends on USB || USB_GADGET
depends on I2C
+ select USB_PHY
help
Say Y here to add support for the NXP ISP1301 USB transceiver driver.
This chip is typically used as USB transceiver for USB host, gadget
@@ -158,6 +170,7 @@ config USB_ISP1301
config USB_MSM_OTG
tristate "OTG support for Qualcomm on-chip USB controller"
depends on (USB || USB_GADGET) && ARCH_MSM
+ select USB_PHY
help
Enable this to support the USB OTG transceiver on MSM chips. It
handles PHY initialization, clock management, and workarounds
@@ -171,6 +184,7 @@ config USB_MV_OTG
tristate "Marvell USB OTG support"
depends on USB_EHCI_MV && USB_MV_UDC && PM_RUNTIME
select USB_OTG
+ select USB_PHY
help
Say Y here if you want to build Marvell USB OTG transciever
driver in kernel (including PXA and MMP series). This driver
@@ -182,6 +196,7 @@ config USB_MXS_PHY
tristate "Freescale MXS USB PHY support"
depends on ARCH_MXC || ARCH_MXS
select STMP_DEVICE
+ select USB_PHY
help
Enable this to support the Freescale MXS USB PHY.
@@ -190,6 +205,7 @@ config USB_MXS_PHY
config USB_RCAR_PHY
tristate "Renesas R-Car USB PHY support"
depends on USB || USB_GADGET
+ select USB_PHY
help
Say Y here to add support for the Renesas R-Car USB common PHY driver.
This chip is typically used as USB PHY for USB host, gadget.
@@ -212,4 +228,4 @@ config USB_ULPI_VIEWPORT
Provides read/write operations to the ULPI phy register set for
controllers with a viewport register (e.g. Chipidea/ARC controllers).
-endif # USB_PHY
+endmenu
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
index 98730ca1d5d3..2135e85f46ed 100644
--- a/drivers/usb/phy/Makefile
+++ b/drivers/usb/phy/Makefile
@@ -11,8 +11,10 @@ phy-fsl-usb2-objs := phy-fsl-usb.o phy-fsm-usb.o
obj-$(CONFIG_FSL_USB2_OTG) += phy-fsl-usb2.o
obj-$(CONFIG_ISP1301_OMAP) += phy-isp1301-omap.o
obj-$(CONFIG_MV_U3D_PHY) += phy-mv-u3d-usb.o
-obj-$(CONFIG_NOP_USB_XCEIV) += phy-nop.o
+obj-$(CONFIG_NOP_USB_XCEIV) += phy-generic.o
obj-$(CONFIG_OMAP_CONTROL_USB) += phy-omap-control.o
+obj-$(CONFIG_AM335X_CONTROL_USB) += phy-am335x-control.o
+obj-$(CONFIG_AM335X_PHY_USB) += phy-am335x.o
obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o
obj-$(CONFIG_OMAP_USB3) += phy-omap-usb3.o
obj-$(CONFIG_SAMSUNG_USBPHY) += phy-samsung-usb.o
diff --git a/drivers/usb/phy/am35x-phy-control.h b/drivers/usb/phy/am35x-phy-control.h
new file mode 100644
index 000000000000..b96594d1962c
--- /dev/null
+++ b/drivers/usb/phy/am35x-phy-control.h
@@ -0,0 +1,21 @@
+#ifndef _AM335x_PHY_CONTROL_H_
+#define _AM335x_PHY_CONTROL_H_
+
+struct phy_control {
+ void (*phy_power)(struct phy_control *phy_ctrl, u32 id, bool on);
+ void (*phy_wkup)(struct phy_control *phy_ctrl, u32 id, bool on);
+};
+
+static inline void phy_ctrl_power(struct phy_control *phy_ctrl, u32 id, bool on)
+{
+ phy_ctrl->phy_power(phy_ctrl, id, on);
+}
+
+static inline void phy_ctrl_wkup(struct phy_control *phy_ctrl, u32 id, bool on)
+{
+ phy_ctrl->phy_wkup(phy_ctrl, id, on);
+}
+
+struct phy_control *am335x_get_phy_control(struct device *dev);
+
+#endif
diff --git a/drivers/usb/phy/phy-am335x-control.c b/drivers/usb/phy/phy-am335x-control.c
new file mode 100644
index 000000000000..759754521426
--- /dev/null
+++ b/drivers/usb/phy/phy-am335x-control.c
@@ -0,0 +1,137 @@
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/io.h>
+
+struct phy_control {
+ void (*phy_power)(struct phy_control *phy_ctrl, u32 id, bool on);
+ void (*phy_wkup)(struct phy_control *phy_ctrl, u32 id, bool on);
+};
+
+struct am335x_control_usb {
+ struct device *dev;
+ void __iomem *phy_reg;
+ void __iomem *wkup;
+ spinlock_t lock;
+ struct phy_control phy_ctrl;
+};
+
+#define AM335X_USB0_CTRL 0x0
+#define AM335X_USB1_CTRL 0x8
+#define AM335x_USB_WKUP 0x0
+
+#define USBPHY_CM_PWRDN (1 << 0)
+#define USBPHY_OTG_PWRDN (1 << 1)
+#define USBPHY_OTGVDET_EN (1 << 19)
+#define USBPHY_OTGSESSEND_EN (1 << 20)
+
+static void am335x_phy_power(struct phy_control *phy_ctrl, u32 id, bool on)
+{
+ struct am335x_control_usb *usb_ctrl;
+ u32 val;
+ u32 reg;
+
+ usb_ctrl = container_of(phy_ctrl, struct am335x_control_usb, phy_ctrl);
+
+ switch (id) {
+ case 0:
+ reg = AM335X_USB0_CTRL;
+ break;
+ case 1:
+ reg = AM335X_USB1_CTRL;
+ break;
+ default:
+ __WARN();
+ return;
+ }
+
+ val = readl(usb_ctrl->phy_reg + reg);
+ if (on) {
+ val &= ~(USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN);
+ val |= USBPHY_OTGVDET_EN | USBPHY_OTGSESSEND_EN;
+ } else {
+ val |= USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN;
+ }
+
+ writel(val, usb_ctrl->phy_reg + reg);
+}
+
+static const struct phy_control ctrl_am335x = {
+ .phy_power = am335x_phy_power,
+};
+
+static const struct of_device_id omap_control_usb_id_table[] = {
+ { .compatible = "ti,am335x-usb-ctrl-module", .data = &ctrl_am335x },
+ {}
+};
+MODULE_DEVICE_TABLE(of, omap_control_usb_id_table);
+
+static struct platform_driver am335x_control_driver;
+static int match(struct device *dev, void *data)
+{
+ struct device_node *node = (struct device_node *)data;
+ return dev->of_node == node &&
+ dev->driver == &am335x_control_driver.driver;
+}
+
+struct phy_control *am335x_get_phy_control(struct device *dev)
+{
+ struct device_node *node;
+ struct am335x_control_usb *ctrl_usb;
+
+ node = of_parse_phandle(dev->of_node, "ti,ctrl_mod", 0);
+ if (!node)
+ return NULL;
+
+ dev = bus_find_device(&platform_bus_type, NULL, node, match);
+ ctrl_usb = dev_get_drvdata(dev);
+ if (!ctrl_usb)
+ return NULL;
+ return &ctrl_usb->phy_ctrl;
+}
+EXPORT_SYMBOL_GPL(am335x_get_phy_control);
+
+static int am335x_control_usb_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct am335x_control_usb *ctrl_usb;
+ const struct of_device_id *of_id;
+ const struct phy_control *phy_ctrl;
+
+ of_id = of_match_node(omap_control_usb_id_table, pdev->dev.of_node);
+ if (!of_id)
+ return -EINVAL;
+
+ phy_ctrl = of_id->data;
+
+ ctrl_usb = devm_kzalloc(&pdev->dev, sizeof(*ctrl_usb), GFP_KERNEL);
+ if (!ctrl_usb) {
+ dev_err(&pdev->dev, "unable to alloc memory for control usb\n");
+ return -ENOMEM;
+ }
+
+ ctrl_usb->dev = &pdev->dev;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_ctrl");
+ ctrl_usb->phy_reg = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(ctrl_usb->phy_reg))
+ return PTR_ERR(ctrl_usb->phy_reg);
+ spin_lock_init(&ctrl_usb->lock);
+ ctrl_usb->phy_ctrl = *phy_ctrl;
+
+ dev_set_drvdata(ctrl_usb->dev, ctrl_usb);
+ return 0;
+}
+
+static struct platform_driver am335x_control_driver = {
+ .probe = am335x_control_usb_probe,
+ .driver = {
+ .name = "am335x-control-usb",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(omap_control_usb_id_table),
+ },
+};
+
+module_platform_driver(am335x_control_driver);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/phy/phy-am335x.c b/drivers/usb/phy/phy-am335x.c
new file mode 100644
index 000000000000..c4d614d1f173
--- /dev/null
+++ b/drivers/usb/phy/phy-am335x.c
@@ -0,0 +1,99 @@
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/usb_phy_gen_xceiv.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include "am35x-phy-control.h"
+#include "phy-generic.h"
+
+struct am335x_phy {
+ struct usb_phy_gen_xceiv usb_phy_gen;
+ struct phy_control *phy_ctrl;
+ int id;
+};
+
+static int am335x_init(struct usb_phy *phy)
+{
+ struct am335x_phy *am_phy = dev_get_drvdata(phy->dev);
+
+ phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, true);
+ return 0;
+}
+
+static void am335x_shutdown(struct usb_phy *phy)
+{
+ struct am335x_phy *am_phy = dev_get_drvdata(phy->dev);
+
+ phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, false);
+}
+
+static int am335x_phy_probe(struct platform_device *pdev)
+{
+ struct am335x_phy *am_phy;
+ struct device *dev = &pdev->dev;
+ int ret;
+
+ am_phy = devm_kzalloc(dev, sizeof(*am_phy), GFP_KERNEL);
+ if (!am_phy)
+ return -ENOMEM;
+
+ am_phy->phy_ctrl = am335x_get_phy_control(dev);
+ if (!am_phy->phy_ctrl)
+ return -EPROBE_DEFER;
+ am_phy->id = of_alias_get_id(pdev->dev.of_node, "phy");
+ if (am_phy->id < 0) {
+ dev_err(&pdev->dev, "Missing PHY id: %d\n", am_phy->id);
+ return am_phy->id;
+ }
+
+ ret = usb_phy_gen_create_phy(dev, &am_phy->usb_phy_gen,
+ USB_PHY_TYPE_USB2, 0, false, false);
+ if (ret)
+ return ret;
+
+ ret = usb_add_phy_dev(&am_phy->usb_phy_gen.phy);
+ if (ret)
+ goto err_add;
+ am_phy->usb_phy_gen.phy.init = am335x_init;
+ am_phy->usb_phy_gen.phy.shutdown = am335x_shutdown;
+
+ platform_set_drvdata(pdev, am_phy);
+ return 0;
+
+err_add:
+ usb_phy_gen_cleanup_phy(&am_phy->usb_phy_gen);
+ return ret;
+}
+
+static int am335x_phy_remove(struct platform_device *pdev)
+{
+ struct am335x_phy *am_phy = platform_get_drvdata(pdev);
+
+ usb_remove_phy(&am_phy->usb_phy_gen.phy);
+ return 0;
+}
+
+static const struct of_device_id am335x_phy_ids[] = {
+ { .compatible = "ti,am335x-usb-phy" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, am335x_phy_ids);
+
+static struct platform_driver am335x_phy_driver = {
+ .probe = am335x_phy_probe,
+ .remove = am335x_phy_remove,
+ .driver = {
+ .name = "am335x-phy-driver",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(am335x_phy_ids),
+ },
+};
+
+module_platform_driver(am335x_phy_driver);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/phy/phy-fsl-usb.c b/drivers/usb/phy/phy-fsl-usb.c
index 181bfb10a57a..fa7c9f9628b5 100644
--- a/drivers/usb/phy/phy-fsl-usb.c
+++ b/drivers/usb/phy/phy-fsl-usb.c
@@ -834,7 +834,7 @@ int usb_otg_start(struct platform_device *pdev)
int status;
struct resource *res;
u32 temp;
- struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+ struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
p_otg = container_of(otg_trans, struct fsl_otg, phy);
fsm = &p_otg->fsm;
@@ -1105,7 +1105,7 @@ static int fsl_otg_probe(struct platform_device *pdev)
{
int ret;
- if (!pdev->dev.platform_data)
+ if (!dev_get_platdata(&pdev->dev))
return -ENODEV;
/* configure the OTG */
@@ -1137,7 +1137,7 @@ static int fsl_otg_probe(struct platform_device *pdev)
static int fsl_otg_remove(struct platform_device *pdev)
{
- struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+ struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
usb_remove_phy(&fsl_otg_dev->phy);
free_irq(fsl_otg_dev->irq, fsl_otg_dev);
diff --git a/drivers/usb/phy/phy-nop.c b/drivers/usb/phy/phy-generic.c
index 55445e5d72e5..efe59f3f7fda 100644
--- a/drivers/usb/phy/phy-nop.c
+++ b/drivers/usb/phy/phy-generic.c
@@ -30,19 +30,13 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/usb/otg.h>
-#include <linux/usb/nop-usb-xceiv.h>
+#include <linux/usb/usb_phy_gen_xceiv.h>
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/regulator/consumer.h>
#include <linux/of.h>
-struct nop_usb_xceiv {
- struct usb_phy phy;
- struct device *dev;
- struct clk *clk;
- struct regulator *vcc;
- struct regulator *reset;
-};
+#include "phy-generic.h"
static struct platform_device *pd;
@@ -50,9 +44,9 @@ void usb_nop_xceiv_register(void)
{
if (pd)
return;
- pd = platform_device_register_simple("nop_usb_xceiv", -1, NULL, 0);
+ pd = platform_device_register_simple("usb_phy_gen_xceiv", -1, NULL, 0);
if (!pd) {
- printk(KERN_ERR "Unable to register usb nop transceiver\n");
+ pr_err("Unable to register generic usb transceiver\n");
return;
}
}
@@ -70,9 +64,9 @@ static int nop_set_suspend(struct usb_phy *x, int suspend)
return 0;
}
-static int nop_init(struct usb_phy *phy)
+int usb_gen_phy_init(struct usb_phy *phy)
{
- struct nop_usb_xceiv *nop = dev_get_drvdata(phy->dev);
+ struct usb_phy_gen_xceiv *nop = dev_get_drvdata(phy->dev);
if (!IS_ERR(nop->vcc)) {
if (regulator_enable(nop->vcc))
@@ -90,10 +84,11 @@ static int nop_init(struct usb_phy *phy)
return 0;
}
+EXPORT_SYMBOL_GPL(usb_gen_phy_init);
-static void nop_shutdown(struct usb_phy *phy)
+void usb_gen_phy_shutdown(struct usb_phy *phy)
{
- struct nop_usb_xceiv *nop = dev_get_drvdata(phy->dev);
+ struct usb_phy_gen_xceiv *nop = dev_get_drvdata(phy->dev);
if (!IS_ERR(nop->reset)) {
/* Assert RESET */
@@ -109,6 +104,7 @@ static void nop_shutdown(struct usb_phy *phy)
dev_err(phy->dev, "Failed to disable power\n");
}
}
+EXPORT_SYMBOL_GPL(usb_gen_phy_shutdown);
static int nop_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget)
{
@@ -139,52 +135,27 @@ static int nop_set_host(struct usb_otg *otg, struct usb_bus *host)
return 0;
}
-static int nop_usb_xceiv_probe(struct platform_device *pdev)
+int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop,
+ enum usb_phy_type type, u32 clk_rate, bool needs_vcc,
+ bool needs_reset)
{
- struct device *dev = &pdev->dev;
- struct nop_usb_xceiv_platform_data *pdata = pdev->dev.platform_data;
- struct nop_usb_xceiv *nop;
- enum usb_phy_type type = USB_PHY_TYPE_USB2;
int err;
- u32 clk_rate = 0;
- bool needs_vcc = false;
- bool needs_reset = false;
-
- nop = devm_kzalloc(&pdev->dev, sizeof(*nop), GFP_KERNEL);
- if (!nop)
- return -ENOMEM;
- nop->phy.otg = devm_kzalloc(&pdev->dev, sizeof(*nop->phy.otg),
- GFP_KERNEL);
+ nop->phy.otg = devm_kzalloc(dev, sizeof(*nop->phy.otg),
+ GFP_KERNEL);
if (!nop->phy.otg)
return -ENOMEM;
- if (dev->of_node) {
- struct device_node *node = dev->of_node;
-
- if (of_property_read_u32(node, "clock-frequency", &clk_rate))
- clk_rate = 0;
-
- needs_vcc = of_property_read_bool(node, "vcc-supply");
- needs_reset = of_property_read_bool(node, "reset-supply");
-
- } else if (pdata) {
- type = pdata->type;
- clk_rate = pdata->clk_rate;
- needs_vcc = pdata->needs_vcc;
- needs_reset = pdata->needs_reset;
- }
-
- nop->clk = devm_clk_get(&pdev->dev, "main_clk");
+ nop->clk = devm_clk_get(dev, "main_clk");
if (IS_ERR(nop->clk)) {
- dev_dbg(&pdev->dev, "Can't get phy clock: %ld\n",
+ dev_dbg(dev, "Can't get phy clock: %ld\n",
PTR_ERR(nop->clk));
}
if (!IS_ERR(nop->clk) && clk_rate) {
err = clk_set_rate(nop->clk, clk_rate);
if (err) {
- dev_err(&pdev->dev, "Error setting clock rate\n");
+ dev_err(dev, "Error setting clock rate\n");
return err;
}
}
@@ -192,33 +163,31 @@ static int nop_usb_xceiv_probe(struct platform_device *pdev)
if (!IS_ERR(nop->clk)) {
err = clk_prepare(nop->clk);
if (err) {
- dev_err(&pdev->dev, "Error preparing clock\n");
+ dev_err(dev, "Error preparing clock\n");
return err;
}
}
- nop->vcc = devm_regulator_get(&pdev->dev, "vcc");
+ nop->vcc = devm_regulator_get(dev, "vcc");
if (IS_ERR(nop->vcc)) {
- dev_dbg(&pdev->dev, "Error getting vcc regulator: %ld\n",
+ dev_dbg(dev, "Error getting vcc regulator: %ld\n",
PTR_ERR(nop->vcc));
if (needs_vcc)
return -EPROBE_DEFER;
}
- nop->reset = devm_regulator_get(&pdev->dev, "reset");
+ nop->reset = devm_regulator_get(dev, "reset");
if (IS_ERR(nop->reset)) {
- dev_dbg(&pdev->dev, "Error getting reset regulator: %ld\n",
+ dev_dbg(dev, "Error getting reset regulator: %ld\n",
PTR_ERR(nop->reset));
if (needs_reset)
return -EPROBE_DEFER;
}
- nop->dev = &pdev->dev;
+ nop->dev = dev;
nop->phy.dev = nop->dev;
nop->phy.label = "nop-xceiv";
nop->phy.set_suspend = nop_set_suspend;
- nop->phy.init = nop_init;
- nop->phy.shutdown = nop_shutdown;
nop->phy.state = OTG_STATE_UNDEFINED;
nop->phy.type = type;
@@ -226,6 +195,59 @@ static int nop_usb_xceiv_probe(struct platform_device *pdev)
nop->phy.otg->set_host = nop_set_host;
nop->phy.otg->set_peripheral = nop_set_peripheral;
+ ATOMIC_INIT_NOTIFIER_HEAD(&nop->phy.notifier);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(usb_phy_gen_create_phy);
+
+void usb_phy_gen_cleanup_phy(struct usb_phy_gen_xceiv *nop)
+{
+ if (!IS_ERR(nop->clk))
+ clk_unprepare(nop->clk);
+}
+EXPORT_SYMBOL_GPL(usb_phy_gen_cleanup_phy);
+
+static int usb_phy_gen_xceiv_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct usb_phy_gen_xceiv_platform_data *pdata =
+ dev_get_platdata(&pdev->dev);
+ struct usb_phy_gen_xceiv *nop;
+ enum usb_phy_type type = USB_PHY_TYPE_USB2;
+ int err;
+ u32 clk_rate = 0;
+ bool needs_vcc = false;
+ bool needs_reset = false;
+
+ if (dev->of_node) {
+ struct device_node *node = dev->of_node;
+
+ if (of_property_read_u32(node, "clock-frequency", &clk_rate))
+ clk_rate = 0;
+
+ needs_vcc = of_property_read_bool(node, "vcc-supply");
+ needs_reset = of_property_read_bool(node, "reset-supply");
+
+ } else if (pdata) {
+ type = pdata->type;
+ clk_rate = pdata->clk_rate;
+ needs_vcc = pdata->needs_vcc;
+ needs_reset = pdata->needs_reset;
+ }
+
+ nop = devm_kzalloc(dev, sizeof(*nop), GFP_KERNEL);
+ if (!nop)
+ return -ENOMEM;
+
+
+ err = usb_phy_gen_create_phy(dev, nop, type, clk_rate, needs_vcc,
+ needs_reset);
+ if (err)
+ return err;
+
+ nop->phy.init = usb_gen_phy_init;
+ nop->phy.shutdown = usb_gen_phy_shutdown;
+
err = usb_add_phy_dev(&nop->phy);
if (err) {
dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
@@ -235,23 +257,18 @@ static int nop_usb_xceiv_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, nop);
- ATOMIC_INIT_NOTIFIER_HEAD(&nop->phy.notifier);
-
return 0;
err_add:
- if (!IS_ERR(nop->clk))
- clk_unprepare(nop->clk);
+ usb_phy_gen_cleanup_phy(nop);
return err;
}
-static int nop_usb_xceiv_remove(struct platform_device *pdev)
+static int usb_phy_gen_xceiv_remove(struct platform_device *pdev)
{
- struct nop_usb_xceiv *nop = platform_get_drvdata(pdev);
-
- if (!IS_ERR(nop->clk))
- clk_unprepare(nop->clk);
+ struct usb_phy_gen_xceiv *nop = platform_get_drvdata(pdev);
+ usb_phy_gen_cleanup_phy(nop);
usb_remove_phy(&nop->phy);
return 0;
@@ -264,29 +281,29 @@ static const struct of_device_id nop_xceiv_dt_ids[] = {
MODULE_DEVICE_TABLE(of, nop_xceiv_dt_ids);
-static struct platform_driver nop_usb_xceiv_driver = {
- .probe = nop_usb_xceiv_probe,
- .remove = nop_usb_xceiv_remove,
+static struct platform_driver usb_phy_gen_xceiv_driver = {
+ .probe = usb_phy_gen_xceiv_probe,
+ .remove = usb_phy_gen_xceiv_remove,
.driver = {
- .name = "nop_usb_xceiv",
+ .name = "usb_phy_gen_xceiv",
.owner = THIS_MODULE,
.of_match_table = nop_xceiv_dt_ids,
},
};
-static int __init nop_usb_xceiv_init(void)
+static int __init usb_phy_gen_xceiv_init(void)
{
- return platform_driver_register(&nop_usb_xceiv_driver);
+ return platform_driver_register(&usb_phy_gen_xceiv_driver);
}
-subsys_initcall(nop_usb_xceiv_init);
+subsys_initcall(usb_phy_gen_xceiv_init);
-static void __exit nop_usb_xceiv_exit(void)
+static void __exit usb_phy_gen_xceiv_exit(void)
{
- platform_driver_unregister(&nop_usb_xceiv_driver);
+ platform_driver_unregister(&usb_phy_gen_xceiv_driver);
}
-module_exit(nop_usb_xceiv_exit);
+module_exit(usb_phy_gen_xceiv_exit);
-MODULE_ALIAS("platform:nop_usb_xceiv");
+MODULE_ALIAS("platform:usb_phy_gen_xceiv");
MODULE_AUTHOR("Texas Instruments Inc");
MODULE_DESCRIPTION("NOP USB Transceiver driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/phy/phy-generic.h b/drivers/usb/phy/phy-generic.h
new file mode 100644
index 000000000000..61687d5a965b
--- /dev/null
+++ b/drivers/usb/phy/phy-generic.h
@@ -0,0 +1,20 @@
+#ifndef _PHY_GENERIC_H_
+#define _PHY_GENERIC_H_
+
+struct usb_phy_gen_xceiv {
+ struct usb_phy phy;
+ struct device *dev;
+ struct clk *clk;
+ struct regulator *vcc;
+ struct regulator *reset;
+};
+
+int usb_gen_phy_init(struct usb_phy *phy);
+void usb_gen_phy_shutdown(struct usb_phy *phy);
+
+int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop,
+ enum usb_phy_type type, u32 clk_rate, bool needs_vcc,
+ bool needs_reset);
+void usb_phy_gen_cleanup_phy(struct usb_phy_gen_xceiv *nop);
+
+#endif
diff --git a/drivers/usb/phy/phy-gpio-vbus-usb.c b/drivers/usb/phy/phy-gpio-vbus-usb.c
index 8443335c2ea0..b2f29c9aebbf 100644
--- a/drivers/usb/phy/phy-gpio-vbus-usb.c
+++ b/drivers/usb/phy/phy-gpio-vbus-usb.c
@@ -101,7 +101,7 @@ static void gpio_vbus_work(struct work_struct *work)
{
struct gpio_vbus_data *gpio_vbus =
container_of(work, struct gpio_vbus_data, work.work);
- struct gpio_vbus_mach_info *pdata = gpio_vbus->dev->platform_data;
+ struct gpio_vbus_mach_info *pdata = dev_get_platdata(gpio_vbus->dev);
int gpio, status, vbus;
if (!gpio_vbus->phy.otg->gadget)
@@ -155,7 +155,7 @@ static void gpio_vbus_work(struct work_struct *work)
static irqreturn_t gpio_vbus_irq(int irq, void *data)
{
struct platform_device *pdev = data;
- struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data;
+ struct gpio_vbus_mach_info *pdata = dev_get_platdata(&pdev->dev);
struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev);
struct usb_otg *otg = gpio_vbus->phy.otg;
@@ -182,7 +182,7 @@ static int gpio_vbus_set_peripheral(struct usb_otg *otg,
gpio_vbus = container_of(otg->phy, struct gpio_vbus_data, phy);
pdev = to_platform_device(gpio_vbus->dev);
- pdata = gpio_vbus->dev->platform_data;
+ pdata = dev_get_platdata(gpio_vbus->dev);
gpio = pdata->gpio_pullup;
if (!gadget) {
@@ -243,7 +243,7 @@ static int gpio_vbus_set_suspend(struct usb_phy *phy, int suspend)
static int __init gpio_vbus_probe(struct platform_device *pdev)
{
- struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data;
+ struct gpio_vbus_mach_info *pdata = dev_get_platdata(&pdev->dev);
struct gpio_vbus_data *gpio_vbus;
struct resource *res;
int err, gpio, irq;
@@ -352,7 +352,7 @@ err_gpio:
static int __exit gpio_vbus_remove(struct platform_device *pdev)
{
struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev);
- struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data;
+ struct gpio_vbus_mach_info *pdata = dev_get_platdata(&pdev->dev);
int gpio = pdata->gpio_vbus;
device_init_wakeup(&pdev->dev, 0);
diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c
index d08f33435e96..e9d4cd960ecd 100644
--- a/drivers/usb/phy/phy-msm-usb.c
+++ b/drivers/usb/phy/phy-msm-usb.c
@@ -1419,7 +1419,7 @@ static int __init msm_otg_probe(struct platform_device *pdev)
struct usb_phy *phy;
dev_info(&pdev->dev, "msm_otg probe\n");
- if (!pdev->dev.platform_data) {
+ if (!dev_get_platdata(&pdev->dev)) {
dev_err(&pdev->dev, "No platform data given. Bailing out\n");
return -ENODEV;
}
@@ -1436,7 +1436,7 @@ static int __init msm_otg_probe(struct platform_device *pdev)
return -ENOMEM;
}
- motg->pdata = pdev->dev.platform_data;
+ motg->pdata = dev_get_platdata(&pdev->dev);
phy = &motg->phy;
phy->dev = &pdev->dev;
diff --git a/drivers/usb/phy/phy-mv-u3d-usb.c b/drivers/usb/phy/phy-mv-u3d-usb.c
index 1568ea63e338..d317903022bf 100644
--- a/drivers/usb/phy/phy-mv-u3d-usb.c
+++ b/drivers/usb/phy/phy-mv-u3d-usb.c
@@ -82,7 +82,7 @@ static void mv_u3d_phy_w