diff options
Diffstat (limited to 'drivers/phy')
| -rw-r--r-- | drivers/phy/Kconfig | 5 | ||||
| -rw-r--r-- | drivers/phy/Makefile | 1 | ||||
| -rw-r--r-- | drivers/phy/phy-rcar-gen3.c | 79 | ||||
| -rw-r--r-- | drivers/phy/starfive/Kconfig | 21 | ||||
| -rw-r--r-- | drivers/phy/starfive/Makefile | 7 | ||||
| -rw-r--r-- | drivers/phy/starfive/phy-jh7110-pcie.c | 239 | ||||
| -rw-r--r-- | drivers/phy/starfive/phy-jh7110-usb-syscon.h | 9 | ||||
| -rw-r--r-- | drivers/phy/starfive/phy-jh7110-usb2.c | 162 |
8 files changed, 507 insertions, 16 deletions
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index e12347e8a03..d3fe90d939e 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -163,8 +163,8 @@ config PHY_RCAR_GEN2 config PHY_RCAR_GEN3 tristate "Renesas R-Car Gen3 USB PHY" - depends on PHY && RCAR_GEN3 && CLK && DM_REGULATOR - default y if RCAR_GEN3 + depends on PHY && CLK && DM_REGULATOR && (RCAR_GEN3 || RZG2L) + default y if (RCAR_GEN3 || RZG2L) help Support for the Renesas R-Car Gen3 USB PHY. This driver operates the PHY connected to EHCI USB module and controls USB OTG operation. @@ -309,5 +309,6 @@ source "drivers/phy/cadence/Kconfig" source "drivers/phy/ti/Kconfig" source "drivers/phy/qcom/Kconfig" source "drivers/phy/renesas/Kconfig" +source "drivers/phy/starfive/Kconfig" endmenu diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index c35f9294dd9..ce4ea28b299 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -44,3 +44,4 @@ obj-y += cadence/ obj-y += ti/ obj-y += qcom/ obj-y += renesas/ +obj-y += starfive/ diff --git a/drivers/phy/phy-rcar-gen3.c b/drivers/phy/phy-rcar-gen3.c index 8c004eaf4c6..d06861c4f79 100644 --- a/drivers/phy/phy-rcar-gen3.c +++ b/drivers/phy/phy-rcar-gen3.c @@ -55,6 +55,7 @@ /* VBCTRL */ #define USB2_VBCTRL_DRVVBUSSEL BIT(8) +#define USB2_VBCTRL_VBOUT BIT(0) /* LINECTRL1 */ #define USB2_LINECTRL1_DPRPD_EN BIT(19) @@ -68,6 +69,13 @@ #define USB2_ADPCTRL_IDPULLUP BIT(5) /* 1 = ID sampling is enabled */ #define USB2_ADPCTRL_DRVVBUS BIT(4) +/* RZ/G2L specific */ +#define USB2_OBINT_IDCHG_EN BIT(0) +#define USB2_LINECTRL1_USB2_IDMON BIT(0) + +/* Device flags */ +#define RCAR_GEN3_PHY_NO_ADPCTRL BIT(0) + struct rcar_gen3_phy { fdt_addr_t regs; struct clk clk; @@ -122,15 +130,50 @@ static int rcar_gen3_phy_phy_power_off(struct phy *phy) return regulator_set_enable(priv->vbus_supply, false); } +static bool rcar_gen3_phy_check_id(struct phy *phy) +{ + const u32 adpdevmask = USB2_ADPCTRL_IDDIG | USB2_ADPCTRL_OTGSESSVLD; + struct rcar_gen3_phy *priv = dev_get_priv(phy->dev); + ulong flags = dev_get_driver_data(phy->dev); + u32 val; + + if (flags & RCAR_GEN3_PHY_NO_ADPCTRL) { + val = readl(priv->regs + USB2_LINECTRL1); + return !!(val & USB2_LINECTRL1_USB2_IDMON); + } + + val = readl(priv->regs + USB2_ADPCTRL); + return (val & adpdevmask) == adpdevmask; +} + +static void rcar_gen3_phy_set_vbus(struct phy *phy, bool enable) +{ + struct rcar_gen3_phy *priv = dev_get_priv(phy->dev); + ulong flags = dev_get_driver_data(phy->dev); + u32 bits = USB2_ADPCTRL_DRVVBUS; + u64 reg = USB2_ADPCTRL; + + if (flags & RCAR_GEN3_PHY_NO_ADPCTRL) { + bits = USB2_VBCTRL_VBOUT; + reg = USB2_VBCTRL; + } + + if (enable) + setbits_le32(priv->regs + reg, bits); + else + clrbits_le32(priv->regs + reg, bits); +} + static int rcar_gen3_phy_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode) { - const u32 adpdevmask = USB2_ADPCTRL_IDDIG | USB2_ADPCTRL_OTGSESSVLD; struct rcar_gen3_phy *priv = dev_get_priv(phy->dev); - u32 adpctrl; + ulong flags = dev_get_driver_data(phy->dev); if (mode == PHY_MODE_USB_OTG) { if (submode) { + u32 obint_enable_bits; + /* OTG submode is used as initialization indicator */ writel(USB2_INT_ENABLE_UCOM_INTEN | USB2_INT_ENABLE_USBH_INTB_EN | @@ -138,13 +181,16 @@ static int rcar_gen3_phy_phy_set_mode(struct phy *phy, enum phy_mode mode, priv->regs + USB2_INT_ENABLE); setbits_le32(priv->regs + USB2_VBCTRL, USB2_VBCTRL_DRVVBUSSEL); - writel(USB2_OBINT_SESSVLDCHG | USB2_OBINT_IDDIGCHG, - priv->regs + USB2_OBINTSTA); - setbits_le32(priv->regs + USB2_OBINTEN, - USB2_OBINT_SESSVLDCHG | - USB2_OBINT_IDDIGCHG); - setbits_le32(priv->regs + USB2_ADPCTRL, - USB2_ADPCTRL_IDPULLUP); + if (flags & RCAR_GEN3_PHY_NO_ADPCTRL) { + obint_enable_bits = USB2_OBINT_IDCHG_EN; + } else { + obint_enable_bits = USB2_OBINT_SESSVLDCHG | + USB2_OBINT_IDDIGCHG; + setbits_le32(priv->regs + USB2_ADPCTRL, + USB2_ADPCTRL_IDPULLUP); + } + writel(obint_enable_bits, priv->regs + USB2_OBINTSTA); + setbits_le32(priv->regs + USB2_OBINTEN, obint_enable_bits); clrsetbits_le32(priv->regs + USB2_LINECTRL1, USB2_LINECTRL1_DP_RPD | USB2_LINECTRL1_DM_RPD | @@ -154,8 +200,7 @@ static int rcar_gen3_phy_phy_set_mode(struct phy *phy, enum phy_mode mode, USB2_LINECTRL1_DMRPD_EN); } - adpctrl = readl(priv->regs + USB2_ADPCTRL); - if ((adpctrl & adpdevmask) == adpdevmask) + if (rcar_gen3_phy_check_id(phy)) mode = PHY_MODE_USB_DEVICE; else mode = PHY_MODE_USB_HOST; @@ -165,13 +210,13 @@ static int rcar_gen3_phy_phy_set_mode(struct phy *phy, enum phy_mode mode, clrbits_le32(priv->regs + USB2_COMMCTRL, USB2_COMMCTRL_OTG_PERI); setbits_le32(priv->regs + USB2_LINECTRL1, USB2_LINECTRL1_DP_RPD | USB2_LINECTRL1_DM_RPD); - setbits_le32(priv->regs + USB2_ADPCTRL, USB2_ADPCTRL_DRVVBUS); + rcar_gen3_phy_set_vbus(phy, true); } else if (mode == PHY_MODE_USB_DEVICE) { setbits_le32(priv->regs + USB2_COMMCTRL, USB2_COMMCTRL_OTG_PERI); clrsetbits_le32(priv->regs + USB2_LINECTRL1, USB2_LINECTRL1_DP_RPD | USB2_LINECTRL1_DM_RPD, USB2_LINECTRL1_DM_RPD); - clrbits_le32(priv->regs + USB2_ADPCTRL, USB2_ADPCTRL_DRVVBUS); + rcar_gen3_phy_set_vbus(phy, false); } else { dev_err(phy->dev, "Unknown mode %d\n", mode); return -EINVAL; @@ -226,7 +271,13 @@ static int rcar_gen3_phy_remove(struct udevice *dev) } static const struct udevice_id rcar_gen3_phy_of_match[] = { - { .compatible = "renesas,rcar-gen3-usb2-phy", }, + { + .compatible = "renesas,rcar-gen3-usb2-phy", + }, + { + .compatible = "renesas,rzg2l-usb2-phy", + .data = RCAR_GEN3_PHY_NO_ADPCTRL, + }, { }, }; diff --git a/drivers/phy/starfive/Kconfig b/drivers/phy/starfive/Kconfig new file mode 100644 index 00000000000..d11338ed484 --- /dev/null +++ b/drivers/phy/starfive/Kconfig @@ -0,0 +1,21 @@ +# +# PHY drivers for Starfive platforms +# + +menu "Starfive PHY driver" + +config PHY_STARFIVE_JH7110_PCIE + bool "Starfive JH7110 PCIe 2.0 PHY driver" + depends on PHY + help + Enable this to support the Starfive JH7110 PCIE 2.0/USB 3.0 PHY. + Generic PHY driver JH7110 USB 3.0/ PCIe 2.0. + +config PHY_STARFIVE_JH7110_USB2 + bool "Starfive JH7110 USB 2.0 PHY driver" + depends on PHY + help + Enable this to support the Starfive JH7110 USB 2.0 PHY. + Generic PHY driver JH7110 USB 2.0. + +endmenu diff --git a/drivers/phy/starfive/Makefile b/drivers/phy/starfive/Makefile new file mode 100644 index 00000000000..82f25aa21b7 --- /dev/null +++ b/drivers/phy/starfive/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2023 Starfive +# + +obj-$(CONFIG_PHY_STARFIVE_JH7110_PCIE) += phy-jh7110-pcie.o +obj-$(CONFIG_PHY_STARFIVE_JH7110_USB2) += phy-jh7110-usb2.o diff --git a/drivers/phy/starfive/phy-jh7110-pcie.c b/drivers/phy/starfive/phy-jh7110-pcie.c new file mode 100644 index 00000000000..a30582821d9 --- /dev/null +++ b/drivers/phy/starfive/phy-jh7110-pcie.c @@ -0,0 +1,239 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * StarFive JH7110 PCIe 2.0 PHY driver + * + * Copyright (C) 2024 StarFive Technology Co., Ltd. + * Author: Minda Chen <minda.chen@starfivetech.com> + */ +#include <asm/io.h> +#include <dm.h> +#include <dm/device_compat.h> +#include <errno.h> +#include <generic-phy.h> +#include <regmap.h> +#include <soc.h> +#include <syscon.h> +#include <linux/bitops.h> +#include <linux/err.h> + +#include "phy-jh7110-usb-syscon.h" + +#define PCIE_KVCO_LEVEL_OFF 0x28 +#define PCIE_USB3_PHY_PLL_CTL_OFF 0x7c +#define PCIE_USB3_PHY_SS_MODE BIT(4) +#define PCIE_KVCO_TUNE_SIGNAL_OFF 0x80 +#define PHY_KVCO_FINE_TUNE_LEVEL 0x91 +#define PHY_KVCO_FINE_TUNE_SIGNALS 0xc + +#define PCIE_USB3_PHY_MODE 0x1 +#define PCIE_BUS_WIDTH 0x2 +#define PCIE_USB3_PHY_ENABLE 0x1 +#define PCIE_USB3_PHY_SPLIT 0x1 + +struct jh7110_pcie_phy { + struct phy *phy; + struct regmap *stg_syscon; + struct regmap *sys_syscon; + void __iomem *regs; + struct regmap_field *phy_mode; + struct regmap_field *bus_width; + struct regmap_field *usb3_phy_en; + struct regmap_field *usb_split; + enum phy_mode mode; +}; + +static int phy_pcie_mode_set(struct jh7110_pcie_phy *data, bool usb_mode) +{ + unsigned int phy_mode, width, usb3_phy, ss_mode, split; + + /* default is PCIe mode */ + if (!data->stg_syscon || !data->sys_syscon) { + if (usb_mode) { + dev_err(data->phy->dev, "doesn't support USB3 mode\n"); + return -EINVAL; + } + return 0; + } + + if (usb_mode) { + phy_mode = PCIE_USB3_PHY_MODE; + width = 0; + usb3_phy = PCIE_USB3_PHY_ENABLE; + ss_mode = PCIE_USB3_PHY_SS_MODE; + split = 0; + } else { + phy_mode = 0; + width = PCIE_BUS_WIDTH; + usb3_phy = 0; + ss_mode = 0; + split = PCIE_USB3_PHY_SPLIT; + } + + regmap_field_write(data->phy_mode, phy_mode); + regmap_field_write(data->bus_width, width); + regmap_field_write(data->usb3_phy_en, usb3_phy); + clrsetbits_le32(data->regs + PCIE_USB3_PHY_PLL_CTL_OFF, + PCIE_USB3_PHY_SS_MODE, ss_mode); + regmap_field_write(data->usb_split, split); + + return 0; +} + +static void phy_kvco_gain_set(struct jh7110_pcie_phy *phy) +{ + /* PCIe Multi-PHY PLL KVCO Gain fine tune settings: */ + writel(PHY_KVCO_FINE_TUNE_LEVEL, phy->regs + PCIE_KVCO_LEVEL_OFF); + writel(PHY_KVCO_FINE_TUNE_SIGNALS, phy->regs + PCIE_KVCO_TUNE_SIGNAL_OFF); +} + +static int jh7110_pcie_phy_set_mode(struct phy *phy, + enum phy_mode mode, int submode) +{ + struct udevice *dev = phy->dev; + struct jh7110_pcie_phy *pcie_phy = dev_get_priv(dev); + int ret; + + if (mode == pcie_phy->mode) + return 0; + + switch (mode) { + case PHY_MODE_USB_HOST: + case PHY_MODE_USB_DEVICE: + case PHY_MODE_USB_OTG: + ret = phy_pcie_mode_set(pcie_phy, 1); + if (ret) + return ret; + break; + case PHY_MODE_PCIE: + phy_pcie_mode_set(pcie_phy, 0); + break; + default: + return -EINVAL; + } + + dev_dbg(phy->dev, "Changing PHY mode to %d\n", mode); + pcie_phy->mode = mode; + + return 0; +} + +static const struct phy_ops jh7110_pcie_phy_ops = { + .set_mode = jh7110_pcie_phy_set_mode, +}; + +static int phy_stg_regfield_init(struct udevice *dev, int mode, int usb3) +{ + struct jh7110_pcie_phy *phy = dev_get_priv(dev); + struct reg_field phy_mode = REG_FIELD(mode, 20, 21); + struct reg_field bus_width = REG_FIELD(usb3, 2, 3); + struct reg_field usb3_phy_en = REG_FIELD(usb3, 4, 4); + + phy->phy_mode = devm_regmap_field_alloc(dev, phy->stg_syscon, phy_mode); + if (IS_ERR(phy->phy_mode)) { + dev_err(dev, "PHY mode reg field init failed\n"); + return PTR_ERR(phy->phy_mode); + } + + phy->bus_width = devm_regmap_field_alloc(dev, phy->stg_syscon, bus_width); + if (IS_ERR(phy->bus_width)) { + dev_err(dev, "PHY bus width reg field init failed\n"); + return PTR_ERR(phy->bus_width); + } + + phy->usb3_phy_en = devm_regmap_field_alloc(dev, phy->stg_syscon, usb3_phy_en); + if (IS_ERR(phy->usb3_phy_en)) { + dev_err(dev, "USB3 PHY enable field init failed\n"); + return PTR_ERR(phy->bus_width); + } + + return 0; +} + +static int phy_sys_regfield_init(struct udevice *dev, int split) +{ + struct jh7110_pcie_phy *phy = dev_get_priv(dev); + struct reg_field usb_split = REG_FIELD(split, USB_PDRSTN_SPLIT_BIT, USB_PDRSTN_SPLIT_BIT); + + phy->usb_split = devm_regmap_field_alloc(dev, phy->sys_syscon, usb_split); + if (IS_ERR(phy->usb_split)) { + dev_err(dev, "USB split field init failed\n"); + return PTR_ERR(phy->usb_split); + } + + return 0; +} + +static int starfive_pcie_phy_get_syscon(struct udevice *dev) +{ + struct jh7110_pcie_phy *phy = dev_get_priv(dev); + struct ofnode_phandle_args sys_phandle, stg_phandle; + int ret; + + /* get corresponding syscon phandle */ + ret = dev_read_phandle_with_args(dev, "starfive,sys-syscon", NULL, 1, 0, + &sys_phandle); + + if (ret < 0) { + dev_err(dev, "Can't get sys cfg phandle: %d\n", ret); + return ret; + } + + ret = dev_read_phandle_with_args(dev, "starfive,stg-syscon", NULL, 2, 0, + &stg_phandle); + + if (ret < 0) { + dev_err(dev, "Can't get stg cfg phandle: %d\n", ret); + return ret; + } + + phy->sys_syscon = syscon_node_to_regmap(sys_phandle.node); + /* get syscon register offset */ + if (!IS_ERR(phy->sys_syscon)) { + ret = phy_sys_regfield_init(dev, SYSCON_USB_PDRSTN_REG_OFFSET); + if (ret) + return ret; + } else { + phy->sys_syscon = NULL; + } + + phy->stg_syscon = syscon_node_to_regmap(stg_phandle.node); + if (!IS_ERR(phy->stg_syscon)) + return phy_stg_regfield_init(dev, stg_phandle.args[0], + stg_phandle.args[1]); + else + phy->stg_syscon = NULL; + + return 0; +} + +int jh7110_pcie_phy_probe(struct udevice *dev) +{ + struct jh7110_pcie_phy *phy = dev_get_priv(dev); + int rc; + + phy->regs = dev_read_addr_ptr(dev); + if (!phy->regs) + return -EINVAL; + + rc = starfive_pcie_phy_get_syscon(dev); + if (rc) + return rc; + + phy_kvco_gain_set(phy); + + return 0; +} + +static const struct udevice_id jh7110_pcie_phy[] = { + { .compatible = "starfive,jh7110-pcie-phy"}, + {}, +}; + +U_BOOT_DRIVER(jh7110_pcie_phy) = { + .name = "jh7110_pcie_phy", + .id = UCLASS_PHY, + .of_match = jh7110_pcie_phy, + .probe = jh7110_pcie_phy_probe, + .ops = &jh7110_pcie_phy_ops, + .priv_auto = sizeof(struct jh7110_pcie_phy), +}; diff --git a/drivers/phy/starfive/phy-jh7110-usb-syscon.h b/drivers/phy/starfive/phy-jh7110-usb-syscon.h new file mode 100644 index 00000000000..0eb66f0d859 --- /dev/null +++ b/drivers/phy/starfive/phy-jh7110-usb-syscon.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef PHY_JH7110_USB_SYSCON_H_ +#define PHY_JH7110_USB_SYSCON_H_ + +#define SYSCON_USB_PDRSTN_REG_OFFSET 0x18 +#define USB_PDRSTN_SPLIT_BIT 17 + +#endif diff --git a/drivers/phy/starfive/phy-jh7110-usb2.c b/drivers/phy/starfive/phy-jh7110-usb2.c new file mode 100644 index 00000000000..1a28381e0df --- /dev/null +++ b/drivers/phy/starfive/phy-jh7110-usb2.c @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * StarFive JH7110 USB 2.0 PHY driver + * + * Copyright (C) 2024 StarFive Technology Co., Ltd. + * Author: Minda Chen <minda.chen@starfivetech.com> + */ + +#include <asm/io.h> +#include <clk.h> +#include <dm.h> +#include <dm/device_compat.h> +#include <errno.h> +#include <generic-phy.h> +#include <regmap.h> +#include <soc.h> +#include <syscon.h> +#include <linux/bitops.h> +#include <linux/err.h> + +#include "phy-jh7110-usb-syscon.h" + +#define USB_LS_KEEPALIVE_OFF 0x4 +#define USB_LS_KEEPALIVE_ENABLE BIT(4) +#define USB_PHY_CLK_RATE 125000000 + +struct jh7110_usb2_phy { + struct phy *phy; + struct regmap *sys_syscon; + void __iomem *regs; + struct clk *usb_125m_clk; + struct clk *app_125m; + struct regmap_field *usb_split; + enum phy_mode mode; +}; + +static void usb2_set_ls_keepalive(struct jh7110_usb2_phy *phy, bool set) +{ + /* Host mode enable the LS speed keep-alive signal */ + clrsetbits_le32(phy->regs + USB_LS_KEEPALIVE_OFF, + USB_LS_KEEPALIVE_ENABLE, + set ? USB_LS_KEEPALIVE_ENABLE : 0); +} + +static int usb2_phy_set_mode(struct phy *phy, + enum phy_mode mode, int submode) +{ + struct udevice *dev = phy->dev; + struct jh7110_usb2_phy *usb2_phy = dev_get_priv(dev); + + if (mode == usb2_phy->mode) + return 0; + + switch (mode) { + case PHY_MODE_USB_HOST: + case PHY_MODE_USB_DEVICE: + case PHY_MODE_USB_OTG: + dev_dbg(dev, "Changing PHY to %d\n", mode); + usb2_phy->mode = mode; + usb2_set_ls_keepalive(usb2_phy, (mode != PHY_MODE_USB_DEVICE)); + break; + default: + return -EINVAL; + } + + /* set default split usb 2.0 only mode */ + regmap_field_write(usb2_phy->usb_split, true); + + return 0; +} + +static int jh7110_usb2_phy_init(struct phy *phy) +{ + struct udevice *dev = phy->dev; + struct jh7110_usb2_phy *usb2_phy = dev_get_priv(dev); + int ret; + + ret = clk_set_rate(usb2_phy->usb_125m_clk, USB_PHY_CLK_RATE); + if (ret < 0) { + dev_err(dev, "Failed to set 125m clock\n"); + return ret; + } + + return clk_prepare_enable(usb2_phy->app_125m); +} + +static int jh7110_usb2_phy_exit(struct phy *phy) +{ + struct udevice *dev = phy->dev; + struct jh7110_usb2_phy *usb2_phy = dev_get_priv(dev); + + clk_disable_unprepare(usb2_phy->app_125m); + + return 0; +} + +struct phy_ops jh7110_usb2_phy_ops = { + .init = jh7110_usb2_phy_init, + .exit = jh7110_usb2_phy_exit, + .set_mode = usb2_phy_set_mode, +}; + +int jh7110_usb2_phy_probe(struct udevice *dev) +{ + struct jh7110_usb2_phy *phy = dev_get_priv(dev); + ofnode node; + struct reg_field usb_split; + int ret; + + phy->regs = dev_read_addr_ptr(dev); + if (!phy->regs) + return -EINVAL; + + node = ofnode_by_compatible(ofnode_null(), "starfive,jh7110-sys-syscon"); + if (!ofnode_valid(node)) { + dev_err(dev, "Can't get syscon dev node\n"); + return -ENODEV; + } + + phy->sys_syscon = syscon_node_to_regmap(node); + if (IS_ERR(phy->sys_syscon)) { + dev_err(dev, "Can't get syscon regmap: %d\n", ret); + return PTR_ERR(phy->sys_syscon); + } + + usb_split.reg = SYSCON_USB_PDRSTN_REG_OFFSET; + usb_split.lsb = USB_PDRSTN_SPLIT_BIT; + usb_split.msb = USB_PDRSTN_SPLIT_BIT; + phy->usb_split = devm_regmap_field_alloc(dev, phy->sys_syscon, usb_split); + if (IS_ERR(phy->usb_split)) { + dev_err(dev, "USB split field init failed\n"); + return PTR_ERR(phy->usb_split); + } + + phy->usb_125m_clk = devm_clk_get(dev, "125m"); + if (IS_ERR(phy->usb_125m_clk)) { + dev_err(dev, "Failed to get 125m clock\n"); + return PTR_ERR(phy->usb_125m_clk); + } + + phy->app_125m = devm_clk_get(dev, "app_125m"); + if (IS_ERR(phy->app_125m)) { + dev_err(dev, "Failed to get app 125m clock\n"); + return PTR_ERR(phy->app_125m); + } + + return 0; +} + +static const struct udevice_id jh7110_usb2_phy[] = { + { .compatible = "starfive,jh7110-usb-phy"}, + {}, +}; + +U_BOOT_DRIVER(jh7110_usb2_phy) = { + .name = "jh7110_usb2_phy", + .id = UCLASS_PHY, + .of_match = jh7110_usb2_phy, + .probe = jh7110_usb2_phy_probe, + .ops = &jh7110_usb2_phy_ops, + .priv_auto = sizeof(struct jh7110_usb2_phy), +}; |
