[PATCH 0/2] drivers: usb: phy: add driver for usb-nop-xceiv

From: "Ying-Chun Liu (PaulLiu)" paul.liu@linaro.org
implement the generic NOP USB transceiver for all USB transceiver which are either built-in into USB IP or which are mostly autonomous.
Ying-Chun Liu (PaulLiu) (2): drivers: usb: phy: add driver for usb-nop-xceiv doc: device-tree-bindings: phy: usb-nop-xceiv
.../phy/usb-nop-xceiv.txt | 43 ++++++ drivers/usb/phy/Kconfig | 8 + drivers/usb/phy/Makefile | 1 + drivers/usb/phy/usb_nop_phy.c | 137 ++++++++++++++++++ 4 files changed, 189 insertions(+) create mode 100644 doc/device-tree-bindings/phy/usb-nop-xceiv.txt create mode 100644 drivers/usb/phy/usb_nop_phy.c

From: "Ying-Chun Liu (PaulLiu)" paul.liu@linaro.org
implement the generic NOP USB transceiver for all USB transceiver which are either built-in into USB IP or which are mostly autonomous.
Signed-off-by: Ying-Chun Liu (PaulLiu) paul.liu@linaro.org --- drivers/usb/phy/Kconfig | 8 ++ drivers/usb/phy/Makefile | 1 + drivers/usb/phy/usb_nop_phy.c | 137 ++++++++++++++++++++++++++++++++++ 3 files changed, 146 insertions(+) create mode 100644 drivers/usb/phy/usb_nop_phy.c
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 8741553d09..663b50a937 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -13,3 +13,11 @@ config OMAP_USB_PHY
config ROCKCHIP_USB2_PHY bool "Rockchip USB2 PHY" + +config NOP_USB_XCEIV + bool "NOP USB Transceiver Driver" + depends on 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 + phy programming such as ISP1x04 etc. diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index 20f7edf48d..079e24770f 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_TWL4030_USB) += twl4030.o obj-$(CONFIG_OMAP_USB_PHY) += omap_usb_phy.o obj-$(CONFIG_ROCKCHIP_USB2_PHY) += rockchip_usb2_phy.o +obj-$(CONFIG_NOP_USB_XCEIV) += usb_nop_phy.o diff --git a/drivers/usb/phy/usb_nop_phy.c b/drivers/usb/phy/usb_nop_phy.c new file mode 100644 index 0000000000..7f4133af39 --- /dev/null +++ b/drivers/usb/phy/usb_nop_phy.c @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * NOP USB transceiver for all USB transceiver which are either built-in + * into USB IP or which are mostly autonomous. + * + * Copyright (C) 2009 Texas Instruments Inc + * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2021 Linaro + * Author: Ajay Kumar Gupta ajay.gupta@ti.com + * Jean-Jacques Hiblot jjhiblot@ti.com + * Ying-Chun Liu (PaulLiu) paul.liu@linaro.org + * Current status: + * This provides a "nop" transceiver for PHYs which are + * autonomous such as isp1504, isp1707, etc. + */ + +#include <clk.h> +#include <common.h> +#include <generic-phy.h> +#include <asm/gpio.h> +#include <dm.h> +#include <dm/device.h> +#include <dm/device_compat.h> +#include <linux/delay.h> +#include <power/regulator.h> + +struct usb_nop_phy_priv { + struct clk_bulk bulk; + struct udevice *vcc; + struct gpio_desc *gpiod_reset; + struct gpio_desc *gpiod_vbus; +}; + +static int usb_nop_phy_reset(struct phy *phy) +{ + int ret = 0; + struct usb_nop_phy_priv *priv = dev_get_priv(phy->dev); + + if (!priv->gpiod_reset) + return ret; + + ret = dm_gpio_set_value(priv->gpiod_reset, 1); + mdelay(20); + ret = dm_gpio_set_value(priv->gpiod_reset, 0); + + return ret; +} + +static int usb_nop_phy_init(struct phy *phy) +{ + struct usb_nop_phy_priv *priv = dev_get_priv(phy->dev); + int ret = 0; + + if (CONFIG_IS_ENABLED(DM_REGULATOR) && priv->vcc) { + ret = regulator_set_enable(priv->vcc, true); + if (ret < 0) { + dev_err(phy->dev, "Failed to enable power: %d\n", ret); + return ret; + } + } + + if (CONFIG_IS_ENABLED(CLK)) { + ret = clk_enable_bulk(&priv->bulk); + if (ret < 0) { + dev_err(phy->dev, "Failed to enable clk: %d\n", ret); + return ret; + } + } + + return ret; +} + +static int usb_nop_phy_probe(struct udevice *dev) +{ + struct usb_nop_phy_priv *priv = dev_get_priv(dev); + u32 clk_rate = 0; + int i, ret = 0; + + /* Get all clocks. Actually only main_clk should be assigned */ + if (CONFIG_IS_ENABLED(CLK)) { + ret = clk_get_bulk(dev, &priv->bulk); + if (ret < 0) + dev_info(dev, "failed to get clock: %d\n", ret); + } + + /* Get vcc-supply */ + if (CONFIG_IS_ENABLED(DM_REGULATOR)) { + ret = device_get_supply_regulator(dev, "vcc-supply", &priv->vcc); + if (ret < 0) { + dev_info(dev, "failed to get vcc-supply: %d\n", ret); + priv->vcc = NULL; + } + } + + ret = ofnode_read_u32(dev_ofnode(dev), "clock-frequency", &clk_rate); + if (ret < 0) + clk_rate = 0; + + priv->gpiod_reset = devm_gpiod_get_optional(dev, "reset", 0); + if (priv->gpiod_reset) + priv->gpiod_vbus = devm_gpiod_get_optional(dev, + "vbus-detect", + 0); + + if (clk_rate) + for (i = 0; i < priv->bulk.count; i++) { + ret = clk_set_rate(&priv->bulk.clks[i], clk_rate); + if (ret < 0) { + dev_err(dev, + "Failed to set clk rate %d: %d\n", + clk_rate, + ret); + return ret; + } + } + + return 0; +} + +static const struct udevice_id usb_nop_phy_ids[] = { + { .compatible = "usb-nop-xceiv" }, + { } +}; + +static struct phy_ops usb_nop_phy_ops = { + .init = usb_nop_phy_init, + .reset = usb_nop_phy_reset, +}; + +U_BOOT_DRIVER(usb_nop_phy) = { + .name = "usb_nop_phy", + .id = UCLASS_PHY, + .of_match = usb_nop_phy_ids, + .ops = &usb_nop_phy_ops, + .probe = usb_nop_phy_probe, + .priv_auto = sizeof(struct usb_nop_phy_priv), +};

From: "Ying-Chun Liu (PaulLiu)" paul.liu@linaro.org
Document the bindings for usb-nop-xceiv
Signed-off-by: Ying-Chun Liu (PaulLiu) paul.liu@linaro.org --- .../phy/usb-nop-xceiv.txt | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 doc/device-tree-bindings/phy/usb-nop-xceiv.txt
diff --git a/doc/device-tree-bindings/phy/usb-nop-xceiv.txt b/doc/device-tree-bindings/phy/usb-nop-xceiv.txt new file mode 100644 index 0000000000..4dc6a8ee30 --- /dev/null +++ b/doc/device-tree-bindings/phy/usb-nop-xceiv.txt @@ -0,0 +1,43 @@ +USB NOP PHY + +Required properties: +- compatible: should be usb-nop-xceiv +- #phy-cells: Must be 0 + +Optional properties: +- clocks: phandle to the PHY clock. Use as per Documentation/devicetree + /bindings/clock/clock-bindings.txt + This property is required if clock-frequency is specified. + +- clock-names: Should be "main_clk" + +- clock-frequency: the clock frequency (in Hz) that the PHY clock must + be configured to. + +- vcc-supply: phandle to the regulator that provides power to the PHY. + +- reset-gpios: Should specify the GPIO for reset. + +- vbus-detect-gpio: should specify the GPIO detecting a VBus insertion + (see Documentation/devicetree/bindings/gpio/gpio.txt) +- vbus-regulator : should specifiy the regulator supplying current drawn from + the VBus line (see Documentation/devicetree/bindings/regulator/regulator.txt). + +Example: + + hsusb1_phy { + compatible = "usb-nop-xceiv"; + clock-frequency = <19200000>; + clocks = <&osc 0>; + clock-names = "main_clk"; + vcc-supply = <&hsusb1_vcc_regulator>; + reset-gpios = <&gpio1 7 GPIO_ACTIVE_LOW>; + vbus-detect-gpio = <&gpio2 13 GPIO_ACTIVE_HIGH>; + vbus-regulator = <&vbus_regulator>; + #phy-cells = <0>; + }; + +hsusb1_phy is a NOP USB PHY device that gets its clock from an oscillator +and expects that clock to be configured to 19.2MHz by the NOP PHY driver. +hsusb1_vcc_regulator provides power to the PHY and GPIO 7 controls RESET. +GPIO 13 detects VBus insertion, and accordingly notifies the vbus-regulator.
participants (1)
-
Ying-Chun Liu