diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2014-03-18 09:43:56 +0100 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2014-03-18 09:43:56 +0100 |
commit | e19b9137142988bec5a76c5f8bdf12a77ea802b0 (patch) | |
tree | b36c83fa93da7f18c1331252fb82a87431697443 /drivers/phy | |
parent | 2fae6a860ca9adb0c881f6dcd633df775c2520e9 (diff) | |
parent | e40d641099213145a034981e646dc2180a488152 (diff) |
Merge remote-tracking branch 'airlied/drm-next' into drm-intel-next
Conflicts:
drivers/gpu/drm/i915/Makefile
Makefile cleanup in drm-intel-next conflicts with a build-fix to move
intel_opregion under CONFIG_ACPI.
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/phy')
-rw-r--r-- | drivers/phy/Kconfig | 16 | ||||
-rw-r--r-- | drivers/phy/Makefile | 2 | ||||
-rw-r--r-- | drivers/phy/phy-bcm-kona-usb2.c | 158 | ||||
-rw-r--r-- | drivers/phy/phy-core.c | 120 | ||||
-rw-r--r-- | drivers/phy/phy-exynos-dp-video.c | 8 | ||||
-rw-r--r-- | drivers/phy/phy-exynos-mipi-video.c | 10 | ||||
-rw-r--r-- | drivers/phy/phy-mvebu-sata.c | 137 | ||||
-rw-r--r-- | drivers/phy/phy-omap-usb2.c | 10 | ||||
-rw-r--r-- | drivers/phy/phy-twl4030-usb.c | 10 |
9 files changed, 429 insertions, 42 deletions
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 330ef2d0656..c7a551c2d5f 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -5,7 +5,7 @@ menu "PHY Subsystem" config GENERIC_PHY - tristate "PHY Core" + bool "PHY Core" help Generic PHY support. @@ -16,11 +16,18 @@ config GENERIC_PHY framework should select this config. config PHY_EXYNOS_MIPI_VIDEO + depends on HAS_IOMEM tristate "S5P/EXYNOS SoC series MIPI CSI-2/DSI PHY driver" help Support for MIPI CSI-2 and MIPI DSI DPHY found on Samsung S5P and EXYNOS SoCs. +config PHY_MVEBU_SATA + def_bool y + depends on ARCH_KIRKWOOD || ARCH_DOVE + depends on OF + select GENERIC_PHY + config OMAP_USB2 tristate "OMAP USB2 PHY Driver" depends on ARCH_OMAP2PLUS @@ -51,4 +58,11 @@ config PHY_EXYNOS_DP_VIDEO help Support for Display Port PHY found on Samsung EXYNOS SoCs. +config BCM_KONA_USB2_PHY + tristate "Broadcom Kona USB2 PHY Driver" + depends on GENERIC_PHY + depends on HAS_IOMEM + help + Enable this to support the Broadcom Kona USB 2.0 PHY. + endmenu diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index d0caae9cfb8..b57c25371cc 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -3,7 +3,9 @@ # obj-$(CONFIG_GENERIC_PHY) += phy-core.o +obj-$(CONFIG_BCM_KONA_USB2_PHY) += phy-bcm-kona-usb2.o obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o +obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o diff --git a/drivers/phy/phy-bcm-kona-usb2.c b/drivers/phy/phy-bcm-kona-usb2.c new file mode 100644 index 00000000000..efc5c1a13a5 --- /dev/null +++ b/drivers/phy/phy-bcm-kona-usb2.c @@ -0,0 +1,158 @@ +/* + * phy-bcm-kona-usb2.c - Broadcom Kona USB2 Phy Driver + * + * Copyright (C) 2013 Linaro Limited + * Matt Porter <mporter@linaro.org> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/phy/phy.h> +#include <linux/platform_device.h> + +#define OTGCTL (0) +#define OTGCTL_OTGSTAT2 BIT(31) +#define OTGCTL_OTGSTAT1 BIT(30) +#define OTGCTL_PRST_N_SW BIT(11) +#define OTGCTL_HRESET_N BIT(10) +#define OTGCTL_UTMI_LINE_STATE1 BIT(9) +#define OTGCTL_UTMI_LINE_STATE0 BIT(8) + +#define P1CTL (8) +#define P1CTL_SOFT_RESET BIT(1) +#define P1CTL_NON_DRIVING BIT(0) + +struct bcm_kona_usb { + void __iomem *regs; +}; + +static void bcm_kona_usb_phy_power(struct bcm_kona_usb *phy, int on) +{ + u32 val; + + val = readl(phy->regs + OTGCTL); + if (on) { + /* Configure and power PHY */ + val &= ~(OTGCTL_OTGSTAT2 | OTGCTL_OTGSTAT1 | + OTGCTL_UTMI_LINE_STATE1 | OTGCTL_UTMI_LINE_STATE0); + val |= OTGCTL_PRST_N_SW | OTGCTL_HRESET_N; + } else { + val &= ~(OTGCTL_PRST_N_SW | OTGCTL_HRESET_N); + } + writel(val, phy->regs + OTGCTL); +} + +static int bcm_kona_usb_phy_init(struct phy *gphy) +{ + struct bcm_kona_usb *phy = phy_get_drvdata(gphy); + u32 val; + + /* Soft reset PHY */ + val = readl(phy->regs + P1CTL); + val &= ~P1CTL_NON_DRIVING; + val |= P1CTL_SOFT_RESET; + writel(val, phy->regs + P1CTL); + writel(val & ~P1CTL_SOFT_RESET, phy->regs + P1CTL); + /* Reset needs to be asserted for 2ms */ + mdelay(2); + writel(val | P1CTL_SOFT_RESET, phy->regs + P1CTL); + + return 0; +} + +static int bcm_kona_usb_phy_power_on(struct phy *gphy) +{ + struct bcm_kona_usb *phy = phy_get_drvdata(gphy); + + bcm_kona_usb_phy_power(phy, 1); + + return 0; +} + +static int bcm_kona_usb_phy_power_off(struct phy *gphy) +{ + struct bcm_kona_usb *phy = phy_get_drvdata(gphy); + + bcm_kona_usb_phy_power(phy, 0); + + return 0; +} + +static struct phy_ops ops = { + .init = bcm_kona_usb_phy_init, + .power_on = bcm_kona_usb_phy_power_on, + .power_off = bcm_kona_usb_phy_power_off, + .owner = THIS_MODULE, +}; + +static int bcm_kona_usb2_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct bcm_kona_usb *phy; + struct resource *res; + struct phy *gphy; + struct phy_provider *phy_provider; + + phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); + if (!phy) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + phy->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(phy->regs)) + return PTR_ERR(phy->regs); + + platform_set_drvdata(pdev, phy); + + gphy = devm_phy_create(dev, &ops, NULL); + if (IS_ERR(gphy)) + return PTR_ERR(gphy); + + /* The Kona PHY supports an 8-bit wide UTMI interface */ + phy_set_bus_width(gphy, 8); + + phy_set_drvdata(gphy, phy); + + phy_provider = devm_of_phy_provider_register(dev, + of_phy_simple_xlate); + if (IS_ERR(phy_provider)) + return PTR_ERR(phy_provider); + + return 0; +} + +static const struct of_device_id bcm_kona_usb2_dt_ids[] = { + { .compatible = "brcm,kona-usb2-phy" }, + { /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, bcm_kona_usb2_dt_ids); + +static struct platform_driver bcm_kona_usb2_driver = { + .probe = bcm_kona_usb2_probe, + .driver = { + .name = "bcm-kona-usb2", + .owner = THIS_MODULE, + .of_match_table = bcm_kona_usb2_dt_ids, + }, +}; + +module_platform_driver(bcm_kona_usb2_driver); + +MODULE_ALIAS("platform:bcm-kona-usb2"); +MODULE_AUTHOR("Matt Porter <mporter@linaro.org>"); +MODULE_DESCRIPTION("BCM Kona USB 2.0 PHY driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index 58e0e973902..6c738376daf 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -94,19 +94,31 @@ static struct phy_provider *of_phy_provider_lookup(struct device_node *node) int phy_pm_runtime_get(struct phy *phy) { + int ret; + if (!pm_runtime_enabled(&phy->dev)) return -ENOTSUPP; - return pm_runtime_get(&phy->dev); + ret = pm_runtime_get(&phy->dev); + if (ret < 0 && ret != -EINPROGRESS) + pm_runtime_put_noidle(&phy->dev); + + return ret; } EXPORT_SYMBOL_GPL(phy_pm_runtime_get); int phy_pm_runtime_get_sync(struct phy *phy) { + int ret; + if (!pm_runtime_enabled(&phy->dev)) return -ENOTSUPP; - return pm_runtime_get_sync(&phy->dev); + ret = pm_runtime_get_sync(&phy->dev); + if (ret < 0) + pm_runtime_put_sync(&phy->dev); + + return ret; } EXPORT_SYMBOL_GPL(phy_pm_runtime_get_sync); @@ -150,18 +162,24 @@ int phy_init(struct phy *phy) { int ret; + if (!phy) + return 0; + ret = phy_pm_runtime_get_sync(phy); if (ret < 0 && ret != -ENOTSUPP) return ret; mutex_lock(&phy->mutex); - if (phy->init_count++ == 0 && phy->ops->init) { + if (phy->init_count == 0 && phy->ops->init) { ret = phy->ops->init(phy); if (ret < 0) { dev_err(&phy->dev, "phy init failed --> %d\n", ret); goto out; } + } else { + ret = 0; /* Override possible ret == -ENOTSUPP */ } + ++phy->init_count; out: mutex_unlock(&phy->mutex); @@ -174,18 +192,22 @@ int phy_exit(struct phy *phy) { int ret; + if (!phy) + return 0; + ret = phy_pm_runtime_get_sync(phy); if (ret < 0 && ret != -ENOTSUPP) return ret; mutex_lock(&phy->mutex); - if (--phy->init_count == 0 && phy->ops->exit) { + if (phy->init_count == 1 && phy->ops->exit) { ret = phy->ops->exit(phy); if (ret < 0) { dev_err(&phy->dev, "phy exit failed --> %d\n", ret); goto out; } } + --phy->init_count; out: mutex_unlock(&phy->mutex); @@ -196,23 +218,32 @@ EXPORT_SYMBOL_GPL(phy_exit); int phy_power_on(struct phy *phy) { - int ret = -ENOTSUPP; + int ret; + + if (!phy) + return 0; ret = phy_pm_runtime_get_sync(phy); if (ret < 0 && ret != -ENOTSUPP) return ret; mutex_lock(&phy->mutex); - if (phy->power_count++ == 0 && phy->ops->power_on) { + if (phy->power_count == 0 && phy->ops->power_on) { ret = phy->ops->power_on(phy); if (ret < 0) { dev_err(&phy->dev, "phy poweron failed --> %d\n", ret); goto out; } + } else { + ret = 0; /* Override possible ret == -ENOTSUPP */ } + ++phy->power_count; + mutex_unlock(&phy->mutex); + return 0; out: mutex_unlock(&phy->mutex); + phy_pm_runtime_put_sync(phy); return ret; } @@ -220,22 +251,25 @@ EXPORT_SYMBOL_GPL(phy_power_on); int phy_power_off(struct phy *phy) { - int ret = -ENOTSUPP; + int ret; + + if (!phy) + return 0; mutex_lock(&phy->mutex); - if (--phy->power_count == 0 && phy->ops->power_off) { + if (phy->power_count == 1 && phy->ops->power_off) { ret = phy->ops->power_off(phy); if (ret < 0) { dev_err(&phy->dev, "phy poweroff failed --> %d\n", ret); - goto out; + mutex_unlock(&phy->mutex); + return ret; } } - -out: + --phy->power_count; mutex_unlock(&phy->mutex); phy_pm_runtime_put(phy); - return ret; + return 0; } EXPORT_SYMBOL_GPL(phy_power_off); @@ -290,7 +324,7 @@ err0: */ void phy_put(struct phy *phy) { - if (IS_ERR(phy)) + if (!phy || IS_ERR(phy)) return; module_put(phy->ops->owner); @@ -310,6 +344,9 @@ void devm_phy_put(struct device *dev, struct phy *phy) { int r; + if (!phy) + return; + r = devres_destroy(dev, devm_phy_release, devm_phy_match, phy); dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n"); } @@ -360,7 +397,7 @@ EXPORT_SYMBOL_GPL(of_phy_simple_xlate); struct phy *phy_get(struct device *dev, const char *string) { int index = 0; - struct phy *phy = NULL; + struct phy *phy; if (string == NULL) { dev_WARN(dev, "missing string\n"); @@ -371,17 +408,11 @@ struct phy *phy_get(struct device *dev, const char *string) index = of_property_match_string(dev->of_node, "phy-names", string); phy = of_phy_get(dev, index); - if (IS_ERR(phy)) { - dev_err(dev, "unable to find phy\n"); - return phy; - } } else { phy = phy_lookup(dev, string); - if (IS_ERR(phy)) { - dev_err(dev, "unable to find phy\n"); - return phy; - } } + if (IS_ERR(phy)) + return phy; if (!try_module_get(phy->ops->owner)) return ERR_PTR(-EPROBE_DEFER); @@ -393,6 +424,27 @@ struct phy *phy_get(struct device *dev, const char *string) EXPORT_SYMBOL_GPL(phy_get); /** + * phy_optional_get() - lookup and obtain a reference to an optional phy. + * @dev: device that requests this phy + * @string: the phy name as given in the dt data or the name of the controller + * port for non-dt case + * + * Returns the phy driver, after getting a refcount to it; or + * NULL if there is no such phy. The caller is responsible for + * calling phy_put() to release that count. + */ +struct phy *phy_optional_get(struct device *dev, const char *string) +{ + struct phy *phy = phy_get(dev, string); + + if (PTR_ERR(phy) == -ENODEV) + phy = NULL; + + return phy; +} +EXPORT_SYMBOL_GPL(phy_optional_get); + +/** * devm_phy_get() - lookup and obtain a reference to a phy. * @dev: device that requests this phy * @string: the phy name as given in the dt data or phy device name @@ -423,6 +475,30 @@ struct phy *devm_phy_get(struct device *dev, const char *string) EXPORT_SYMBOL_GPL(devm_phy_get); /** + * devm_phy_optional_get() - lookup and obtain a reference to an optional phy. + * @dev: device that requests this phy + * @string: the phy name as given in the dt data or phy device name + * for non-dt case + * + * Gets the phy using phy_get(), and associates a device with it using + * devres. On driver detach, release function is invoked on the devres + * data, then, devres data is freed. This differs to devm_phy_get() in + * that if the phy does not exist, it is not considered an error and + * -ENODEV will not be returned. Instead the NULL phy is returned, + * which can be passed to all other phy consumer calls. + */ +struct phy *devm_phy_optional_get(struct device *dev, const char *string) +{ + struct phy *phy = devm_phy_get(dev, string); + + if (PTR_ERR(phy) == -ENODEV) + phy = NULL; + + return phy; +} +EXPORT_SYMBOL_GPL(devm_phy_optional_get); + +/** * phy_create() - create a new phy * @dev: device that is creating the new phy * @ops: function pointers for performing phy operations diff --git a/drivers/phy/phy-exynos-dp-video.c b/drivers/phy/phy-exynos-dp-video.c index 1dbe6ce7b2c..0786fef842e 100644 --- a/drivers/phy/phy-exynos-dp-video.c +++ b/drivers/phy/phy-exynos-dp-video.c @@ -76,10 +76,6 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev) if (IS_ERR(state->regs)) return PTR_ERR(state->regs); - phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); - if (IS_ERR(phy_provider)) - return PTR_ERR(phy_provider); - phy = devm_phy_create(dev, &exynos_dp_video_phy_ops, NULL); if (IS_ERR(phy)) { dev_err(dev, "failed to create Display Port PHY\n"); @@ -87,6 +83,10 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev) } phy_set_drvdata(phy, state); + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + if (IS_ERR(phy_provider)) + return PTR_ERR(phy_provider); + return 0; } diff --git a/drivers/phy/phy-exynos-mipi-video.c b/drivers/phy/phy-exynos-mipi-video.c index 0c5efab11af..7f139326a64 100644 --- a/drivers/phy/phy-exynos-mipi-video.c +++ b/drivers/phy/phy-exynos-mipi-video.c @@ -134,11 +134,6 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev) dev_set_drvdata(dev, state); spin_lock_init(&state->slock); - phy_provider = devm_of_phy_provider_register(dev, - exynos_mipi_video_phy_xlate); - if (IS_ERR(phy_provider)) - return PTR_ERR(phy_provider); - for (i = 0; i < EXYNOS_MIPI_PHYS_NUM; i++) { struct phy *phy = devm_phy_create(dev, &exynos_mipi_video_phy_ops, NULL); @@ -152,6 +147,11 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev) phy_set_drvdata(phy, &state->phys[i]); } + phy_provider = devm_of_phy_provider_register(dev, + exynos_mipi_video_phy_xlate); + if (IS_ERR(phy_provider)) + return PTR_ERR(phy_provider); + return 0; } diff --git a/drivers/phy/phy-mvebu-sata.c b/drivers/phy/phy-mvebu-sata.c new file mode 100644 index 00000000000..d70ecd6a1b3 --- /dev/null +++ b/drivers/phy/phy-mvebu-sata.c @@ -0,0 +1,137 @@ +/* + * phy-mvebu-sata.c: SATA Phy driver for the Marvell mvebu SoCs. + * + * Copyright (C) 2013 Andrew Lunn <andrew@lunn.ch> + * + * 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. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/clk.h> +#include <linux/phy/phy.h> +#include <linux/io.h> +#include <linux/platform_device.h> + +struct priv { + struct clk *clk; + void __iomem *base; +}; + +#define SATA_PHY_MODE_2 0x0330 +#define MODE_2_FORCE_PU_TX BIT(0) +#define MODE_2_FORCE_PU_RX BIT(1) +#define MODE_2_PU_PLL BIT(2) +#define MODE_2_PU_IVREF BIT(3) +#define SATA_IF_CTRL 0x0050 +#define CTRL_PHY_SHUTDOWN BIT(9) + +static int phy_mvebu_sata_power_on(struct phy *phy) +{ + struct priv *priv = phy_get_drvdata(phy); + u32 reg; + + clk_prepare_enable(priv->clk); + + /* Enable PLL and IVREF */ + reg = readl(priv->base + SATA_PHY_MODE_2); + reg |= (MODE_2_FORCE_PU_TX | MODE_2_FORCE_PU_RX | + MODE_2_PU_PLL | MODE_2_PU_IVREF); + writel(reg , priv->base + SATA_PHY_MODE_2); + + /* Enable PHY */ + reg = readl(priv->base + SATA_IF_CTRL); + reg &= ~CTRL_PHY_SHUTDOWN; + writel(reg, priv->base + SATA_IF_CTRL); + + clk_disable_unprepare(priv->clk); + + return 0; +} + +static int phy_mvebu_sata_power_off(struct phy *phy) +{ + struct priv *priv = phy_get_drvdata(phy); + u32 reg; + + clk_prepare_enable(priv->clk); + + /* Disable PLL and IVREF */ + reg = readl(priv->base + SATA_PHY_MODE_2); + reg &= ~(MODE_2_FORCE_PU_TX | MODE_2_FORCE_PU_RX | + MODE_2_PU_PLL | MODE_2_PU_IVREF); + writel(reg, priv->base + SATA_PHY_MODE_2); + + /* Disable PHY */ + reg = readl(priv->base + SATA_IF_CTRL); + reg |= CTRL_PHY_SHUTDOWN; + writel(reg, priv->base + SATA_IF_CTRL); + + clk_disable_unprepare(priv->clk); + + return 0; +} + +static struct phy_ops phy_mvebu_sata_ops = { + .power_on = phy_mvebu_sata_power_on, + .power_off = phy_mvebu_sata_power_off, + .owner = THIS_MODULE, +}; + +static int phy_mvebu_sata_probe(struct platform_device *pdev) +{ + struct phy_provider *phy_provider; + struct resource *res; + struct priv *priv; + struct phy *phy; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + priv->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + + priv->clk = devm_clk_get(&pdev->dev, "sata"); + if (IS_ERR(priv->clk)) + return PTR_ERR(priv->clk); + + phy = devm_phy_create(&pdev->dev, &phy_mvebu_sata_ops, NULL); + if (IS_ERR(phy)) + return PTR_ERR(phy); + + phy_set_drvdata(phy, priv); + + phy_provider = devm_of_phy_provider_register(&pdev->dev, + of_phy_simple_xlate); + if (IS_ERR(phy_provider)) + return PTR_ERR(phy_provider); + + /* The boot loader may of left it on. Turn it off. */ + phy_mvebu_sata_power_off(phy); + + return 0; +} + +static const struct of_device_id phy_mvebu_sata_of_match[] = { + { .compatible = "marvell,mvebu-sata-phy" }, + { }, +}; +MODULE_DEVICE_TABLE(of, phy_mvebu_sata_of_match); + +static struct platform_driver phy_mvebu_sata_driver = { + .probe = phy_mvebu_sata_probe, + .driver = { + .name = "phy-mvebu-sata", + .owner = THIS_MODULE, + .of_match_table = phy_mvebu_sata_of_match, + } +}; +module_platform_driver(phy_mvebu_sata_driver); + +MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch>"); +MODULE_DESCRIPTION("Marvell MVEBU SATA PHY driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/phy/phy-omap-usb2.c b/drivers/phy/phy-omap-usb2.c index bfc5c337f99..7699752fba1 100644 --- a/drivers/phy/phy-omap-usb2.c +++ b/drivers/phy/phy-omap-usb2.c @@ -177,11 +177,6 @@ static int omap_usb2_probe(struct platform_device *pdev) phy->phy.otg = otg; phy->phy.type = USB_PHY_TYPE_USB2; - phy_provider = devm_of_phy_provider_register(phy->dev, - of_phy_simple_xlate); - if (IS_ERR(phy_provider)) - return PTR_ERR(phy_provider); - control_node = of_parse_phandle(node, "ctrl-module", 0); if (!control_node) { dev_err(&pdev->dev, "Failed to get control device phandle\n"); @@ -214,6 +209,11 @@ static int omap_usb2_probe(struct platform_device *pdev) phy_set_drvdata(generic_phy, phy); + phy_provider = devm_of_phy_provider_register(phy->dev, + of_phy_simple_xlate); + if (IS_ERR(phy_provider)) + return PTR_ERR(phy_provider); + phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k"); if (IS_ERR(phy->wkupclk)) { dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n"); diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c index daf65e68aaa..c3ace1db813 100644 --- a/drivers/phy/phy-twl4030-usb.c +++ b/drivers/phy/phy-twl4030-usb.c @@ -695,11 +695,6 @@ 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"); @@ -708,6 +703,11 @@ static int twl4030_usb_probe(struct platform_device *pdev) phy_set_drvdata(phy, twl); + phy_provider = devm_of_phy_provider_register(twl->dev, + of_phy_simple_xlate); + if (IS_ERR(phy_provider)) + return PTR_ERR(phy_provider); + /* init spinlock for workqueue */ spin_lock_init(&twl->lock); |