diff options
Diffstat (limited to 'drivers/usb/phy')
-rw-r--r-- | drivers/usb/phy/Kconfig | 10 | ||||
-rw-r--r-- | drivers/usb/phy/Makefile | 2 | ||||
-rw-r--r-- | drivers/usb/phy/phy-am335x.c | 6 | ||||
-rw-r--r-- | drivers/usb/phy/phy-tegra-usb.c | 140 | ||||
-rw-r--r-- | drivers/usb/phy/phy.c | 133 |
5 files changed, 126 insertions, 165 deletions
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 0f8ab981d572..d7312eed6088 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -159,6 +159,16 @@ config USB_MXS_PHY MXS Phy is used by some of the i.MX SoCs, for example imx23/28/6x. +config USB_TEGRA_PHY + tristate "NVIDIA Tegra USB PHY Driver" + depends on ARCH_TEGRA + select USB_COMMON + select USB_PHY + select USB_ULPI + help + This driver provides PHY support for the USB controllers found + on NVIDIA Tegra SoC's. + config USB_ULPI bool "Generic ULPI Transceiver Driver" depends on ARM || ARM64 diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index 25e579fb92b8..df1d99010079 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -16,7 +16,7 @@ obj-$(CONFIG_AM335X_CONTROL_USB) += phy-am335x-control.o obj-$(CONFIG_AM335X_PHY_USB) += phy-am335x.o obj-$(CONFIG_OMAP_OTG) += phy-omap-otg.o obj-$(CONFIG_TWL6030_USB) += phy-twl6030-usb.o -obj-$(CONFIG_USB_EHCI_TEGRA) += phy-tegra-usb.o +obj-$(CONFIG_USB_TEGRA_PHY) += phy-tegra-usb.o obj-$(CONFIG_USB_GPIO_VBUS) += phy-gpio-vbus-usb.o obj-$(CONFIG_USB_ISP1301) += phy-isp1301.o obj-$(CONFIG_USB_MV_OTG) += phy-mv-usb.o diff --git a/drivers/usb/phy/phy-am335x.c b/drivers/usb/phy/phy-am335x.c index b36fa8b953d0..27bdb7222527 100644 --- a/drivers/usb/phy/phy-am335x.c +++ b/drivers/usb/phy/phy-am335x.c @@ -96,8 +96,7 @@ static int am335x_phy_remove(struct platform_device *pdev) #ifdef CONFIG_PM_SLEEP static int am335x_phy_suspend(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct am335x_phy *am_phy = platform_get_drvdata(pdev); + struct am335x_phy *am_phy = dev_get_drvdata(dev); /* * Enable phy wakeup only if dev->power.can_wakeup is true. @@ -117,8 +116,7 @@ static int am335x_phy_suspend(struct device *dev) static int am335x_phy_resume(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct am335x_phy *am_phy = platform_get_drvdata(pdev); + struct am335x_phy *am_phy = dev_get_drvdata(dev); phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, am_phy->dr_mode, true); diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c index 0e8d23e51732..ea7ef1dc0b42 100644 --- a/drivers/usb/phy/phy-tegra-usb.c +++ b/drivers/usb/phy/phy-tegra-usb.c @@ -236,13 +236,83 @@ static void set_phcd(struct tegra_usb_phy *phy, bool enable) static int utmip_pad_open(struct tegra_usb_phy *phy) { + int ret; + phy->pad_clk = devm_clk_get(phy->u_phy.dev, "utmi-pads"); if (IS_ERR(phy->pad_clk)) { - pr_err("%s: can't get utmip pad clock\n", __func__); - return PTR_ERR(phy->pad_clk); + ret = PTR_ERR(phy->pad_clk); + dev_err(phy->u_phy.dev, + "Failed to get UTMIP pad clock: %d\n", ret); + return ret; } - return 0; + phy->pad_rst = devm_reset_control_get_optional_shared( + phy->u_phy.dev, "utmi-pads"); + if (IS_ERR(phy->pad_rst)) { + ret = PTR_ERR(phy->pad_rst); + dev_err(phy->u_phy.dev, + "Failed to get UTMI-pads reset: %d\n", ret); + return ret; + } + + ret = clk_prepare_enable(phy->pad_clk); + if (ret) { + dev_err(phy->u_phy.dev, + "Failed to enable UTMI-pads clock: %d\n", ret); + return ret; + } + + spin_lock(&utmip_pad_lock); + + ret = reset_control_deassert(phy->pad_rst); + if (ret) { + dev_err(phy->u_phy.dev, + "Failed to initialize UTMI-pads reset: %d\n", ret); + goto unlock; + } + + ret = reset_control_assert(phy->pad_rst); + if (ret) { + dev_err(phy->u_phy.dev, + "Failed to assert UTMI-pads reset: %d\n", ret); + goto unlock; + } + + udelay(1); + + ret = reset_control_deassert(phy->pad_rst); + if (ret) + dev_err(phy->u_phy.dev, + "Failed to deassert UTMI-pads reset: %d\n", ret); +unlock: + spin_unlock(&utmip_pad_lock); + + clk_disable_unprepare(phy->pad_clk); + + return ret; +} + +static int utmip_pad_close(struct tegra_usb_phy *phy) +{ + int ret; + + ret = clk_prepare_enable(phy->pad_clk); + if (ret) { + dev_err(phy->u_phy.dev, + "Failed to enable UTMI-pads clock: %d\n", ret); + return ret; + } + + ret = reset_control_assert(phy->pad_rst); + if (ret) + dev_err(phy->u_phy.dev, + "Failed to assert UTMI-pads reset: %d\n", ret); + + udelay(1); + + clk_disable_unprepare(phy->pad_clk); + + return ret; } static void utmip_pad_power_on(struct tegra_usb_phy *phy) @@ -282,7 +352,7 @@ static int utmip_pad_power_off(struct tegra_usb_phy *phy) void __iomem *base = phy->pad_regs; if (!utmip_pad_count) { - pr_err("%s: utmip pad already powered off\n", __func__); + dev_err(phy->u_phy.dev, "UTMIP pad already powered off\n"); return -EINVAL; } @@ -338,7 +408,8 @@ static void utmi_phy_clk_disable(struct tegra_usb_phy *phy) set_phcd(phy, true); if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0) - pr_err("%s: timeout waiting for phy to stabilize\n", __func__); + dev_err(phy->u_phy.dev, + "Timeout waiting for PHY to stabilize on disable\n"); } static void utmi_phy_clk_enable(struct tegra_usb_phy *phy) @@ -370,7 +441,8 @@ static void utmi_phy_clk_enable(struct tegra_usb_phy *phy) if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, USB_PHY_CLK_VALID)) - pr_err("%s: timeout waiting for phy to stabilize\n", __func__); + dev_err(phy->u_phy.dev, + "Timeout waiting for PHY to stabilize on enable\n"); } static int utmi_phy_power_on(struct tegra_usb_phy *phy) @@ -617,15 +689,15 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy) ret = gpio_direction_output(phy->reset_gpio, 0); if (ret < 0) { - dev_err(phy->u_phy.dev, "gpio %d not set to 0\n", - phy->reset_gpio); + dev_err(phy->u_phy.dev, "GPIO %d not set to 0: %d\n", + phy->reset_gpio, ret); return ret; } msleep(5); ret = gpio_direction_output(phy->reset_gpio, 1); if (ret < 0) { - dev_err(phy->u_phy.dev, "gpio %d not set to 1\n", - phy->reset_gpio); + dev_err(phy->u_phy.dev, "GPIO %d not set to 1: %d\n", + phy->reset_gpio, ret); return ret; } @@ -661,13 +733,13 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy) /* Fix VbusInvalid due to floating VBUS */ ret = usb_phy_io_write(phy->ulpi, 0x40, 0x08); if (ret) { - pr_err("%s: ulpi write failed\n", __func__); + dev_err(phy->u_phy.dev, "ULPI write failed: %d\n", ret); return ret; } ret = usb_phy_io_write(phy->ulpi, 0x80, 0x0B); if (ret) { - pr_err("%s: ulpi write failed\n", __func__); + dev_err(phy->u_phy.dev, "ULPI write failed: %d\n", ret); return ret; } @@ -694,6 +766,9 @@ static void tegra_usb_phy_close(struct tegra_usb_phy *phy) if (!IS_ERR(phy->vbus)) regulator_disable(phy->vbus); + if (!phy->is_ulpi_phy) + utmip_pad_close(phy); + clk_disable_unprepare(phy->pll_u); } @@ -728,28 +803,30 @@ static int ulpi_open(struct tegra_usb_phy *phy) phy->clk = devm_clk_get(phy->u_phy.dev, "ulpi-link"); if (IS_ERR(phy->clk)) { - pr_err("%s: can't get ulpi clock\n", __func__); - return PTR_ERR(phy->clk); + err = PTR_ERR(phy->clk); + dev_err(phy->u_phy.dev, "Failed to get ULPI clock: %d\n", err); + return err; } err = devm_gpio_request(phy->u_phy.dev, phy->reset_gpio, "ulpi_phy_reset_b"); if (err < 0) { - dev_err(phy->u_phy.dev, "request failed for gpio: %d\n", - phy->reset_gpio); + dev_err(phy->u_phy.dev, "Request failed for GPIO %d: %d\n", + phy->reset_gpio, err); return err; } err = gpio_direction_output(phy->reset_gpio, 0); if (err < 0) { - dev_err(phy->u_phy.dev, "gpio %d direction not set to output\n", - phy->reset_gpio); + dev_err(phy->u_phy.dev, + "GPIO %d direction not set to output: %d\n", + phy->reset_gpio, err); return err; } phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0); if (!phy->ulpi) { - dev_err(phy->u_phy.dev, "otg_ulpi_create returned NULL\n"); + dev_err(phy->u_phy.dev, "Failed to create ULPI OTG\n"); err = -ENOMEM; return err; } @@ -766,8 +843,10 @@ static int tegra_usb_phy_init(struct tegra_usb_phy *phy) phy->pll_u = devm_clk_get(phy->u_phy.dev, "pll_u"); if (IS_ERR(phy->pll_u)) { - pr_err("Can't get pll_u clock\n"); - return PTR_ERR(phy->pll_u); + err = PTR_ERR(phy->pll_u); + dev_err(phy->u_phy.dev, + "Failed to get pll_u clock: %d\n", err); + return err; } err = clk_prepare_enable(phy->pll_u); @@ -782,7 +861,8 @@ static int tegra_usb_phy_init(struct tegra_usb_phy *phy) } } if (!phy->freq) { - pr_err("invalid pll_u parent rate %ld\n", parent_rate); + dev_err(phy->u_phy.dev, "Invalid pll_u parent rate %ld\n", + parent_rate); err = -EINVAL; goto fail; } @@ -791,7 +871,7 @@ static int tegra_usb_phy_init(struct tegra_usb_phy *phy) err = regulator_enable(phy->vbus); if (err) { dev_err(phy->u_phy.dev, - "failed to enable usb vbus regulator: %d\n", + "Failed to enable USB VBUS regulator: %d\n", err); goto fail; } @@ -855,7 +935,8 @@ static int read_utmi_param(struct platform_device *pdev, const char *param, int err = of_property_read_u32(pdev->dev.of_node, param, &value); *dest = (u8)value; if (err < 0) - dev_err(&pdev->dev, "Failed to read USB UTMI parameter %s: %d\n", + dev_err(&pdev->dev, + "Failed to read USB UTMI parameter %s: %d\n", param, err); return err; } @@ -871,14 +952,14 @@ static int utmi_phy_probe(struct tegra_usb_phy *tegra_phy, res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (!res) { - dev_err(&pdev->dev, "Failed to get UTMI Pad regs\n"); + dev_err(&pdev->dev, "Failed to get UTMI pad regs\n"); return -ENXIO; } tegra_phy->pad_regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (!tegra_phy->pad_regs) { - dev_err(&pdev->dev, "Failed to remap UTMI Pad regs\n"); + dev_err(&pdev->dev, "Failed to remap UTMI pad regs\n"); return -ENOMEM; } @@ -1020,15 +1101,16 @@ static int tegra_usb_phy_probe(struct platform_device *pdev) tegra_phy->reset_gpio = of_get_named_gpio(np, "nvidia,phy-reset-gpio", 0); if (!gpio_is_valid(tegra_phy->reset_gpio)) { - dev_err(&pdev->dev, "invalid gpio: %d\n", - tegra_phy->reset_gpio); + dev_err(&pdev->dev, + "Invalid GPIO: %d\n", tegra_phy->reset_gpio); return tegra_phy->reset_gpio; } tegra_phy->config = NULL; break; default: - dev_err(&pdev->dev, "phy_type is invalid or unsupported\n"); + dev_err(&pdev->dev, "phy_type %u is invalid or unsupported\n", + phy_type); return -EINVAL; } diff --git a/drivers/usb/phy/phy.c b/drivers/usb/phy/phy.c index bceb2c9988dd..0277f62739a2 100644 --- a/drivers/usb/phy/phy.c +++ b/drivers/usb/phy/phy.c @@ -27,7 +27,6 @@ #define DEFAULT_ACA_CUR_MAX 5000 static LIST_HEAD(phy_list); -static LIST_HEAD(phy_bind_list); static DEFINE_SPINLOCK(phy_lock); struct phy_devm { @@ -50,24 +49,6 @@ static struct usb_phy *__usb_find_phy(struct list_head *list, return ERR_PTR(-ENODEV); } -static struct usb_phy *__usb_find_phy_dev(struct device *dev, - struct list_head *list, u8 index) -{ - struct usb_phy_bind *phy_bind = NULL; - - list_for_each_entry(phy_bind, list, list) { - if (!(strcmp(phy_bind->dev_name, dev_name(dev))) && - phy_bind->index == index) { - if (phy_bind->phy) - return phy_bind->phy; - else - return ERR_PTR(-EPROBE_DEFER); - } - } - - return ERR_PTR(-ENODEV); -} - static struct usb_phy *__of_usb_find_phy(struct device_node *node) { struct usb_phy *phy; @@ -585,72 +566,6 @@ struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev, EXPORT_SYMBOL_GPL(devm_usb_get_phy_by_phandle); /** - * usb_get_phy_dev - find the USB PHY - * @dev - device that requests this phy - * @index - the index of the phy - * - * Returns the phy driver, after getting a refcount to it; or - * -ENODEV if there is no such phy. The caller is responsible for - * calling usb_put_phy() to release that count. - * - * For use by USB host and peripheral drivers. - */ -struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index) -{ - struct usb_phy *phy = NULL; - unsigned long flags; - - spin_lock_irqsave(&phy_lock, flags); - - phy = __usb_find_phy_dev(dev, &phy_bind_list, index); - if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) { - dev_dbg(dev, "unable to find transceiver\n"); - if (!IS_ERR(phy)) - phy = ERR_PTR(-ENODEV); - - goto err0; - } - - get_device(phy->dev); - -err0: - spin_unlock_irqrestore(&phy_lock, flags); - - return phy; -} -EXPORT_SYMBOL_GPL(usb_get_phy_dev); - -/** - * devm_usb_get_phy_dev - find the USB PHY using device ptr and index - * @dev - device that requests this phy - * @index - the index of the phy - * - * Gets the phy using usb_get_phy_dev(), and associates a device with it using - * devres. On driver detach, release function is invoked on the devres data, - * then, devres data is freed. - * - * For use by USB host and peripheral drivers. - */ -struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index) -{ - struct usb_phy **ptr, *phy; - - ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return NULL; - - phy = usb_get_phy_dev(dev, index); - if (!IS_ERR(phy)) { - *ptr = phy; - devres_add(dev, ptr); - } else - devres_free(ptr); - - return phy; -} -EXPORT_SYMBOL_GPL(devm_usb_get_phy_dev); - -/** * devm_usb_put_phy - release the USB PHY * @dev - device that wants to release this phy * @phy - the phy returned by devm_usb_get_phy() @@ -745,7 +660,6 @@ EXPORT_SYMBOL_GPL(usb_add_phy); */ int usb_add_phy_dev(struct usb_phy *x) { - struct usb_phy_bind *phy_bind; unsigned long flags; int ret; @@ -762,13 +676,9 @@ int usb_add_phy_dev(struct usb_phy *x) ATOMIC_INIT_NOTIFIER_HEAD(&x->notifier); spin_lock_irqsave(&phy_lock, flags); - list_for_each_entry(phy_bind, &phy_bind_list, list) - if (!(strcmp(phy_bind->phy_dev_name, dev_name(x->dev)))) - phy_bind->phy = x; - list_add_tail(&x->head, &phy_list); - spin_unlock_irqrestore(&phy_lock, flags); + return 0; } EXPORT_SYMBOL_GPL(usb_add_phy_dev); @@ -782,54 +692,15 @@ EXPORT_SYMBOL_GPL(usb_add_phy_dev); void usb_remove_phy(struct usb_phy *x) { unsigned long flags; - struct usb_phy_bind *phy_bind; spin_lock_irqsave(&phy_lock, flags); - if (x) { - list_for_each_entry(phy_bind, &phy_bind_list, list) - if (phy_bind->phy == x) - phy_bind->phy = NULL; + if (x) list_del(&x->head); - } spin_unlock_irqrestore(&phy_lock, flags); } EXPORT_SYMBOL_GPL(usb_remove_phy); /** - * usb_bind_phy - bind the phy and the controller that uses the phy - * @dev_name: the device name of the device that will bind to the phy - * @index: index to specify the port number - * @phy_dev_name: the device name of the phy - * - * Fills the phy_bind structure with the dev_name and phy_dev_name. This will - * be used when the phy driver registers the phy and when the controller - * requests this phy. - * - * To be used by platform specific initialization code. - */ -int usb_bind_phy(const char *dev_name, u8 index, - const char *phy_dev_name) -{ - struct usb_phy_bind *phy_bind; - unsigned long flags; - - phy_bind = kzalloc(sizeof(*phy_bind), GFP_KERNEL); - if (!phy_bind) - return -ENOMEM; - - phy_bind->dev_name = dev_name; - phy_bind->phy_dev_name = phy_dev_name; - phy_bind->index = index; - - spin_lock_irqsave(&phy_lock, flags); - list_add_tail(&phy_bind->list, &phy_bind_list); - spin_unlock_irqrestore(&phy_lock, flags); - - return 0; -} -EXPORT_SYMBOL_GPL(usb_bind_phy); - -/** * usb_phy_set_event - set event to phy event * @x: the phy returned by usb_get_phy(); * |