diff options
author | Tom Rini | 2023-06-12 14:55:33 -0400 |
---|---|---|
committer | Tom Rini | 2023-06-12 14:55:33 -0400 |
commit | 260d4962e06c0a7d2713523c131416a3f70d7f2c (patch) | |
tree | 14b9d414810e97f1ffdfdaf099db57a5bbf45a79 /drivers/phy | |
parent | 5b589e139620214f26eb83c9fb7bbd62b5f8fc1d (diff) | |
parent | 19b77d3d23966a0d6dbb3c86187765f11100fb6f (diff) |
Merge tag v2023.07-rc4 into next
Signed-off-by: Tom Rini <trini@konsulko.com>
Diffstat (limited to 'drivers/phy')
-rw-r--r-- | drivers/phy/allwinner/phy-sun50i-usb3.c | 6 | ||||
-rw-r--r-- | drivers/phy/marvell/comphy_core.c | 12 | ||||
-rw-r--r-- | drivers/phy/meson-g12a-usb2.c | 48 | ||||
-rw-r--r-- | drivers/phy/meson-gxbb-usb2.c | 38 | ||||
-rw-r--r-- | drivers/phy/meson-gxl-usb2.c | 30 | ||||
-rw-r--r-- | drivers/phy/phy-stm32-usbphyc.c | 4 | ||||
-rw-r--r-- | drivers/phy/phy-uclass.c | 121 | ||||
-rw-r--r-- | drivers/phy/qcom/phy-qcom-usb-hs-28nm.c | 4 | ||||
-rw-r--r-- | drivers/phy/qcom/phy-qcom-usb-ss.c | 4 | ||||
-rw-r--r-- | drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 169 | ||||
-rw-r--r-- | drivers/phy/rockchip/phy-rockchip-naneng-combphy.c | 103 | ||||
-rw-r--r-- | drivers/phy/rockchip/phy-rockchip-snps-pcie3.c | 4 | ||||
-rw-r--r-- | drivers/phy/rockchip/phy-rockchip-typec.c | 6 |
13 files changed, 357 insertions, 192 deletions
diff --git a/drivers/phy/allwinner/phy-sun50i-usb3.c b/drivers/phy/allwinner/phy-sun50i-usb3.c index e5a3d2d92ea..609d9d4ec93 100644 --- a/drivers/phy/allwinner/phy-sun50i-usb3.c +++ b/drivers/phy/allwinner/phy-sun50i-usb3.c @@ -149,9 +149,9 @@ static int sun50i_usb3_phy_probe(struct udevice *dev) return ret; } - priv->regs = (void __iomem *)dev_read_addr(dev); - if (IS_ERR(priv->regs)) - return PTR_ERR(priv->regs); + priv->regs = dev_read_addr_ptr(dev); + if (!priv->regs) + return -EINVAL; return 0; } diff --git a/drivers/phy/marvell/comphy_core.c b/drivers/phy/marvell/comphy_core.c index df2460dbd7d..7272dfb9fe8 100644 --- a/drivers/phy/marvell/comphy_core.c +++ b/drivers/phy/marvell/comphy_core.c @@ -88,13 +88,13 @@ static int comphy_probe(struct udevice *dev) int res; /* Save base addresses for later use */ - chip_cfg->comphy_base_addr = (void *)devfdt_get_addr_index(dev, 0); - if (IS_ERR(chip_cfg->comphy_base_addr)) - return PTR_ERR(chip_cfg->comphy_base_addr); + chip_cfg->comphy_base_addr = devfdt_get_addr_index_ptr(dev, 0); + if (!chip_cfg->comphy_base_addr) + return -EINVAL; - chip_cfg->hpipe3_base_addr = (void *)devfdt_get_addr_index(dev, 1); - if (IS_ERR(chip_cfg->hpipe3_base_addr)) - return PTR_ERR(chip_cfg->hpipe3_base_addr); + chip_cfg->hpipe3_base_addr = devfdt_get_addr_index_ptr(dev, 1); + if (!chip_cfg->hpipe3_base_addr) + return -EINVAL; if (device_is_compatible(dev, "marvell,comphy-a3700")) { chip_cfg->comphy_init_map = comphy_a3700_init_serdes_map; diff --git a/drivers/phy/meson-g12a-usb2.c b/drivers/phy/meson-g12a-usb2.c index 2fbba7fdae0..650b88bd180 100644 --- a/drivers/phy/meson-g12a-usb2.c +++ b/drivers/phy/meson-g12a-usb2.c @@ -54,50 +54,12 @@ struct phy_meson_g12a_usb2_priv { struct regmap *regmap; -#if CONFIG_IS_ENABLED(DM_REGULATOR) - struct udevice *phy_supply; -#endif #if CONFIG_IS_ENABLED(CLK) struct clk clk; #endif struct reset_ctl reset; }; - -static int phy_meson_g12a_usb2_power_on(struct phy *phy) -{ -#if CONFIG_IS_ENABLED(DM_REGULATOR) - struct udevice *dev = phy->dev; - struct phy_meson_g12a_usb2_priv *priv = dev_get_priv(dev); - - if (priv->phy_supply) { - int ret = regulator_set_enable(priv->phy_supply, true); - if (ret) - return ret; - } -#endif - - return 0; -} - -static int phy_meson_g12a_usb2_power_off(struct phy *phy) -{ -#if CONFIG_IS_ENABLED(DM_REGULATOR) - struct udevice *dev = phy->dev; - struct phy_meson_g12a_usb2_priv *priv = dev_get_priv(dev); - - if (priv->phy_supply) { - int ret = regulator_set_enable(priv->phy_supply, false); - if (ret) { - pr_err("Error disabling PHY supply\n"); - return ret; - } - } -#endif - - return 0; -} - static int phy_meson_g12a_usb2_init(struct phy *phy) { struct udevice *dev = phy->dev; @@ -155,8 +117,6 @@ static int phy_meson_g12a_usb2_exit(struct phy *phy) struct phy_ops meson_g12a_usb2_phy_ops = { .init = phy_meson_g12a_usb2_init, .exit = phy_meson_g12a_usb2_exit, - .power_on = phy_meson_g12a_usb2_power_on, - .power_off = phy_meson_g12a_usb2_power_off, }; int meson_g12a_usb2_phy_probe(struct udevice *dev) @@ -193,14 +153,6 @@ int meson_g12a_usb2_phy_probe(struct udevice *dev) } #endif -#if CONFIG_IS_ENABLED(DM_REGULATOR) - ret = device_get_supply_regulator(dev, "phy-supply", &priv->phy_supply); - if (ret && ret != -ENOENT) { - pr_err("Failed to get PHY regulator\n"); - return ret; - } -#endif - return 0; } diff --git a/drivers/phy/meson-gxbb-usb2.c b/drivers/phy/meson-gxbb-usb2.c index 7a2e3d2739e..70a80b86381 100644 --- a/drivers/phy/meson-gxbb-usb2.c +++ b/drivers/phy/meson-gxbb-usb2.c @@ -12,7 +12,6 @@ #include <clk.h> #include <dm.h> #include <generic-phy.h> -#include <power/regulator.h> #include <regmap.h> #include <reset.h> #include <linux/bitops.h> @@ -81,9 +80,6 @@ struct phy_meson_gxbb_usb2_priv { struct regmap *regmap; struct reset_ctl_bulk resets; -#if CONFIG_IS_ENABLED(DM_REGULATOR) - struct udevice *phy_supply; -#endif }; static int phy_meson_gxbb_usb2_power_on(struct phy *phy) @@ -92,15 +88,6 @@ static int phy_meson_gxbb_usb2_power_on(struct phy *phy) struct phy_meson_gxbb_usb2_priv *priv = dev_get_priv(dev); uint val; -#if CONFIG_IS_ENABLED(DM_REGULATOR) - if (priv->phy_supply) { - int ret = regulator_set_enable(priv->phy_supply, true); - - if (ret) - return ret; - } -#endif - regmap_update_bits(priv->regmap, REG_CONFIG, REG_CONFIG_CLK_32k_ALTSEL, REG_CONFIG_CLK_32k_ALTSEL); @@ -140,26 +127,8 @@ static int phy_meson_gxbb_usb2_power_on(struct phy *phy) return 0; } -static int phy_meson_gxbb_usb2_power_off(struct phy *phy) -{ -#if CONFIG_IS_ENABLED(DM_REGULATOR) - struct udevice *dev = phy->dev; - struct phy_meson_gxbb_usb2_priv *priv = dev_get_priv(dev); - - if (priv->phy_supply) { - int ret = regulator_set_enable(priv->phy_supply, false); - - if (ret) - return ret; - } -#endif - - return 0; -} - static struct phy_ops meson_gxbb_usb2_phy_ops = { .power_on = phy_meson_gxbb_usb2_power_on, - .power_off = phy_meson_gxbb_usb2_power_off, }; static int meson_gxbb_usb2_phy_probe(struct udevice *dev) @@ -192,13 +161,6 @@ static int meson_gxbb_usb2_phy_probe(struct udevice *dev) return ret; } -#if CONFIG_IS_ENABLED(DM_REGULATOR) - ret = device_get_supply_regulator(dev, "phy-supply", &priv->phy_supply); - if (ret && ret != -ENOENT) { - pr_err("Failed to get PHY regulator\n"); - return ret; - } -#endif ret = reset_get_bulk(dev, &priv->resets); if (!ret) { ret = reset_deassert_bulk(&priv->resets); diff --git a/drivers/phy/meson-gxl-usb2.c b/drivers/phy/meson-gxl-usb2.c index 9fb376cec44..4c631310efa 100644 --- a/drivers/phy/meson-gxl-usb2.c +++ b/drivers/phy/meson-gxl-usb2.c @@ -16,7 +16,6 @@ #include <generic-phy.h> #include <regmap.h> #include <linux/delay.h> -#include <power/regulator.h> #include <clk.h> #include <linux/usb/otg.h> @@ -101,9 +100,6 @@ struct phy_meson_gxl_usb2_priv { struct regmap *regmap; -#if CONFIG_IS_ENABLED(DM_REGULATOR) - struct udevice *phy_supply; -#endif #if CONFIG_IS_ENABLED(CLK) struct clk clk; #endif @@ -167,14 +163,6 @@ static int phy_meson_gxl_usb2_power_on(struct phy *phy) phy_meson_gxl_usb2_set_mode(phy, USB_DR_MODE_HOST); -#if CONFIG_IS_ENABLED(DM_REGULATOR) - if (priv->phy_supply) { - int ret = regulator_set_enable(priv->phy_supply, true); - if (ret) - return ret; - } -#endif - return 0; } @@ -189,16 +177,6 @@ static int phy_meson_gxl_usb2_power_off(struct phy *phy) val |= U2P_R0_POWER_ON_RESET; regmap_write(priv->regmap, U2P_R0, val); -#if CONFIG_IS_ENABLED(DM_REGULATOR) - if (priv->phy_supply) { - int ret = regulator_set_enable(priv->phy_supply, false); - if (ret) { - pr_err("Error disabling PHY supply\n"); - return ret; - } - } -#endif - return 0; } @@ -229,14 +207,6 @@ int meson_gxl_usb2_phy_probe(struct udevice *dev) } #endif -#if CONFIG_IS_ENABLED(DM_REGULATOR) - ret = device_get_supply_regulator(dev, "phy-supply", &priv->phy_supply); - if (ret && ret != -ENOENT) { - pr_err("Failed to get PHY regulator\n"); - return ret; - } -#endif - return 0; } diff --git a/drivers/phy/phy-stm32-usbphyc.c b/drivers/phy/phy-stm32-usbphyc.c index dcf2194e9a7..15bd60ca8c5 100644 --- a/drivers/phy/phy-stm32-usbphyc.c +++ b/drivers/phy/phy-stm32-usbphyc.c @@ -583,8 +583,8 @@ static int stm32_usbphyc_probe(struct udevice *dev) phy_id = ofnode_read_u32_default(node, "reg", FDT_ADDR_T_NONE); if (phy_id >= MAX_PHYS) { - dev_err(dev, "invalid reg value %lx for %s\n", - phy_id, ofnode_get_name(node)); + dev_err(dev, "invalid reg value %llx for %s\n", + (fdt64_t)phy_id, ofnode_get_name(node)); return -ENOENT; } diff --git a/drivers/phy/phy-uclass.c b/drivers/phy/phy-uclass.c index 83e4b63079d..629ef3aa3de 100644 --- a/drivers/phy/phy-uclass.c +++ b/drivers/phy/phy-uclass.c @@ -12,6 +12,7 @@ #include <dm/devres.h> #include <generic-phy.h> #include <linux/list.h> +#include <power/regulator.h> /** * struct phy_counts - Init and power-on counts of a single PHY port @@ -29,12 +30,14 @@ * without a matching generic_phy_exit() afterwards * @list: Handle for a linked list of these structures corresponding to * ports of the same PHY provider + * @supply: Handle to a phy-supply device */ struct phy_counts { unsigned long id; int power_on_count; int init_count; struct list_head list; + struct udevice *supply; }; static inline struct phy_ops *phy_dev_ops(struct udevice *dev) @@ -58,7 +61,7 @@ static struct phy_counts *phy_get_counts(struct phy *phy) return NULL; } -static int phy_alloc_counts(struct phy *phy) +static int phy_alloc_counts(struct phy *phy, struct udevice *supply) { struct list_head *uc_priv; struct phy_counts *counts; @@ -76,6 +79,7 @@ static int phy_alloc_counts(struct phy *phy) counts->id = phy->id; counts->power_on_count = 0; counts->init_count = 0; + counts->supply = supply; list_add(&counts->list, uc_priv); return 0; @@ -123,7 +127,7 @@ int generic_phy_get_by_index_nodev(ofnode node, int index, struct phy *phy) { struct ofnode_phandle_args args; struct phy_ops *ops; - struct udevice *phydev; + struct udevice *phydev, *supply = NULL; int i, ret; debug("%s(node=%s, index=%d, phy=%p)\n", @@ -172,7 +176,17 @@ int generic_phy_get_by_index_nodev(ofnode node, int index, struct phy *phy) goto err; } - ret = phy_alloc_counts(phy); + if (CONFIG_IS_ENABLED(DM_REGULATOR)) { + ret = device_get_supply_regulator(phydev, "phy-supply", + &supply); + if (ret && ret != -ENOENT) { + debug("%s: device_get_supply_regulator failed: %d\n", + __func__, ret); + goto err; + } + } + + ret = phy_alloc_counts(phy, supply); if (ret) { debug("phy_alloc_counts() failed: %d\n", ret); goto err; @@ -214,24 +228,24 @@ int generic_phy_init(struct phy *phy) if (!generic_phy_valid(phy)) return 0; - ops = phy_dev_ops(phy->dev); - if (!ops->init) - return 0; - counts = phy_get_counts(phy); if (counts->init_count > 0) { counts->init_count++; return 0; } - ret = ops->init(phy); - if (ret) - dev_err(phy->dev, "PHY: Failed to init %s: %d.\n", - phy->dev->name, ret); - else - counts->init_count = 1; + ops = phy_dev_ops(phy->dev); + if (ops->init) { + ret = ops->init(phy); + if (ret) { + dev_err(phy->dev, "PHY: Failed to init %s: %d.\n", + phy->dev->name, ret); + return ret; + } + } + counts->init_count = 1; - return ret; + return 0; } int generic_phy_reset(struct phy *phy) @@ -260,10 +274,6 @@ int generic_phy_exit(struct phy *phy) if (!generic_phy_valid(phy)) return 0; - ops = phy_dev_ops(phy->dev); - if (!ops->exit) - return 0; - counts = phy_get_counts(phy); if (counts->init_count == 0) return 0; @@ -272,14 +282,18 @@ int generic_phy_exit(struct phy *phy) return 0; } - ret = ops->exit(phy); - if (ret) - dev_err(phy->dev, "PHY: Failed to exit %s: %d.\n", - phy->dev->name, ret); - else - counts->init_count = 0; + ops = phy_dev_ops(phy->dev); + if (ops->exit) { + ret = ops->exit(phy); + if (ret) { + dev_err(phy->dev, "PHY: Failed to exit %s: %d.\n", + phy->dev->name, ret); + return ret; + } + } + counts->init_count = 0; - return ret; + return 0; } int generic_phy_power_on(struct phy *phy) @@ -290,24 +304,32 @@ int generic_phy_power_on(struct phy *phy) if (!generic_phy_valid(phy)) return 0; - ops = phy_dev_ops(phy->dev); - if (!ops->power_on) - return 0; - counts = phy_get_counts(phy); if (counts->power_on_count > 0) { counts->power_on_count++; return 0; } - ret = ops->power_on(phy); - if (ret) - dev_err(phy->dev, "PHY: Failed to power on %s: %d.\n", - phy->dev->name, ret); - else - counts->power_on_count = 1; + ret = regulator_set_enable_if_allowed(counts->supply, true); + if (ret && ret != -ENOSYS) { + dev_err(phy->dev, "PHY: Failed to enable regulator %s: %d.\n", + counts->supply->name, ret); + return ret; + } - return ret; + ops = phy_dev_ops(phy->dev); + if (ops->power_on) { + ret = ops->power_on(phy); + if (ret) { + dev_err(phy->dev, "PHY: Failed to power on %s: %d.\n", + phy->dev->name, ret); + regulator_set_enable_if_allowed(counts->supply, false); + return ret; + } + } + counts->power_on_count = 1; + + return 0; } int generic_phy_power_off(struct phy *phy) @@ -318,10 +340,6 @@ int generic_phy_power_off(struct phy *phy) if (!generic_phy_valid(phy)) return 0; - ops = phy_dev_ops(phy->dev); - if (!ops->power_off) - return 0; - counts = phy_get_counts(phy); if (counts->power_on_count == 0) return 0; @@ -330,14 +348,23 @@ int generic_phy_power_off(struct phy *phy) return 0; } - ret = ops->power_off(phy); - if (ret) - dev_err(phy->dev, "PHY: Failed to power off %s: %d.\n", - phy->dev->name, ret); - else - counts->power_on_count = 0; + ops = phy_dev_ops(phy->dev); + if (ops->power_off) { + ret = ops->power_off(phy); + if (ret) { + dev_err(phy->dev, "PHY: Failed to power off %s: %d.\n", + phy->dev->name, ret); + return ret; + } + } + counts->power_on_count = 0; - return ret; + ret = regulator_set_enable_if_allowed(counts->supply, false); + if (ret && ret != -ENOSYS) + dev_err(phy->dev, "PHY: Failed to disable regulator %s: %d.\n", + counts->supply->name, ret); + + return 0; } int generic_phy_configure(struct phy *phy, void *params) diff --git a/drivers/phy/qcom/phy-qcom-usb-hs-28nm.c b/drivers/phy/qcom/phy-qcom-usb-hs-28nm.c index 14c3d8394df..05a9a2cf1d7 100644 --- a/drivers/phy/qcom/phy-qcom-usb-hs-28nm.c +++ b/drivers/phy/qcom/phy-qcom-usb-hs-28nm.c @@ -184,8 +184,8 @@ static int hsphy_probe(struct udevice *dev) struct hsphy_priv *priv = dev_get_priv(dev); int ret; - priv->base = (void *)dev_read_addr(dev); - if ((ulong)priv->base == FDT_ADDR_T_NONE) + priv->base = dev_read_addr_ptr(dev); + if (!priv->base) return -EINVAL; ret = reset_get_by_name(dev, "phy", &priv->phy_rst); diff --git a/drivers/phy/qcom/phy-qcom-usb-ss.c b/drivers/phy/qcom/phy-qcom-usb-ss.c index 4e816879c6a..1b03a3c43dc 100644 --- a/drivers/phy/qcom/phy-qcom-usb-ss.c +++ b/drivers/phy/qcom/phy-qcom-usb-ss.c @@ -115,8 +115,8 @@ static int ssphy_probe(struct udevice *dev) struct ssphy_priv *priv = dev_get_priv(dev); int ret; - priv->base = (void *)dev_read_addr(dev); - if ((ulong)priv->base == FDT_ADDR_T_NONE) + priv->base = dev_read_addr_ptr(dev); + if (!priv->base) return -EINVAL; ret = ssphy_clk_init(dev, priv); diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c index 55e1dbcfef7..e43a5ba9b5f 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c @@ -7,10 +7,11 @@ */ #include <common.h> -#include <clk.h> +#include <clk-uclass.h> #include <dm.h> #include <asm/global_data.h> #include <dm/device_compat.h> +#include <dm/device-internal.h> #include <dm/lists.h> #include <generic-phy.h> #include <reset.h> @@ -55,6 +56,7 @@ struct rockchip_usb2phy_port_cfg { struct rockchip_usb2phy_cfg { unsigned int reg; + struct usb2phy_reg clkout_ctl; const struct rockchip_usb2phy_port_cfg port_cfgs[USB2PHY_NUM_PORTS]; }; @@ -76,6 +78,18 @@ static inline int property_enable(void *reg_base, return writel(val, reg_base + reg->offset); } +static inline bool property_enabled(void *reg_base, + const struct usb2phy_reg *reg) +{ + unsigned int tmp, orig; + unsigned int mask = GENMASK(reg->bitend, reg->bitstart); + + orig = readl(reg_base + reg->offset); + + tmp = (orig & mask) >> reg->bitstart; + return tmp != reg->disable; +} + static const struct rockchip_usb2phy_port_cfg *us2phy_get_port(struct phy *phy) { @@ -168,6 +182,65 @@ static struct phy_ops rockchip_usb2phy_ops = { .of_xlate = rockchip_usb2phy_of_xlate, }; +/** + * round_rate() - Adjust a rate to the exact rate a clock can provide. + * @clk: The clock to manipulate. + * @rate: Desidered clock rate in Hz. + * + * Return: rounded rate in Hz, or -ve error code. + */ +ulong rockchip_usb2phy_clk_round_rate(struct clk *clk, ulong rate) +{ + return 480000000; +} + +/** + * enable() - Enable a clock. + * @clk: The clock to manipulate. + * + * Return: zero on success, or -ve error code. + */ +int rockchip_usb2phy_clk_enable(struct clk *clk) +{ + struct udevice *parent = dev_get_parent(clk->dev); + struct rockchip_usb2phy *priv = dev_get_priv(parent); + const struct rockchip_usb2phy_cfg *phy_cfg = priv->phy_cfg; + + /* turn on 480m clk output if it is off */ + if (!property_enabled(priv->reg_base, &phy_cfg->clkout_ctl)) { + property_enable(priv->reg_base, &phy_cfg->clkout_ctl, true); + + /* waiting for the clk become stable */ + usleep_range(1200, 1300); + } + + return 0; +} + +/** + * disable() - Disable a clock. + * @clk: The clock to manipulate. + * + * Return: zero on success, or -ve error code. + */ +int rockchip_usb2phy_clk_disable(struct clk *clk) +{ + struct udevice *parent = dev_get_parent(clk->dev); + struct rockchip_usb2phy *priv = dev_get_priv(parent); + const struct rockchip_usb2phy_cfg *phy_cfg = priv->phy_cfg; + + /* turn off 480m clk output */ + property_enable(priv->reg_base, &phy_cfg->clkout_ctl, false); + + return 0; +} + +static struct clk_ops rockchip_usb2phy_clk_ops = { + .enable = rockchip_usb2phy_clk_enable, + .disable = rockchip_usb2phy_clk_disable, + .round_rate = rockchip_usb2phy_clk_round_rate +}; + static int rockchip_usb2phy_probe(struct udevice *dev) { struct rockchip_usb2phy *priv = dev_get_priv(dev); @@ -201,14 +274,14 @@ static int rockchip_usb2phy_probe(struct udevice *dev) /* find out a proper config which can be matched with dt. */ index = 0; - while (phy_cfgs[index].reg) { + do { if (phy_cfgs[index].reg == reg) { priv->phy_cfg = &phy_cfgs[index]; break; } ++index; - } + } while (phy_cfgs[index].reg); if (!priv->phy_cfg) { dev_err(dev, "failed find proper phy-cfg\n"); @@ -234,7 +307,8 @@ static int rockchip_usb2phy_bind(struct udevice *dev) dev_for_each_subnode(node, dev) { if (!ofnode_valid(node)) { dev_info(dev, "subnode %s not found\n", dev->name); - return -ENXIO; + ret = -ENXIO; + goto bind_fail; } name = ofnode_get_name(node); @@ -245,16 +319,36 @@ static int rockchip_usb2phy_bind(struct udevice *dev) if (ret) { dev_err(dev, "'%s' cannot bind 'rockchip_usb2phy_port'\n", name); - return ret; + goto bind_fail; } } + node = dev_ofnode(dev); + name = "clk_usbphy_480m"; + dev_read_string_index(dev, "clock-output-names", 0, &name); + + dev_dbg(dev, "clk %s for node %s\n", name, ofnode_get_name(node)); + + ret = device_bind_driver_to_node(dev, "rockchip_usb2phy_clock", + name, node, &usb2phy_dev); + if (ret) { + dev_err(dev, + "'%s' cannot bind 'rockchip_usb2phy_clock'\n", name); + goto bind_fail; + } + + return 0; + +bind_fail: + device_chld_unbind(dev, NULL); + return ret; } static const struct rockchip_usb2phy_cfg rk3399_usb2phy_cfgs[] = { { .reg = 0xe450, + .clkout_ctl = { 0xe450, 4, 4, 1, 0 }, .port_cfgs = { [USB2PHY_PORT_OTG] = { .phy_sus = { 0xe454, 1, 0, 2, 1 }, @@ -276,6 +370,7 @@ static const struct rockchip_usb2phy_cfg rk3399_usb2phy_cfgs[] = { }, { .reg = 0xe460, + .clkout_ctl = { 0xe460, 4, 4, 1, 0 }, .port_cfgs = { [USB2PHY_PORT_OTG] = { .phy_sus = { 0xe464, 1, 0, 2, 1 }, @@ -301,6 +396,7 @@ static const struct rockchip_usb2phy_cfg rk3399_usb2phy_cfgs[] = { static const struct rockchip_usb2phy_cfg rk3568_phy_cfgs[] = { { .reg = 0xfe8a0000, + .clkout_ctl = { 0x0008, 4, 4, 1, 0 }, .port_cfgs = { [USB2PHY_PORT_OTG] = { .phy_sus = { 0x0000, 8, 0, 0x052, 0x1d1 }, @@ -326,6 +422,7 @@ static const struct rockchip_usb2phy_cfg rk3568_phy_cfgs[] = { }, { .reg = 0xfe8b0000, + .clkout_ctl = { 0x0008, 4, 4, 1, 0 }, .port_cfgs = { [USB2PHY_PORT_OTG] = { .phy_sus = { 0x0000, 8, 0, 0x1d2, 0x1d1 }, @@ -348,6 +445,58 @@ static const struct rockchip_usb2phy_cfg rk3568_phy_cfgs[] = { { /* sentinel */ } }; +static const struct rockchip_usb2phy_cfg rk3588_phy_cfgs[] = { + { + .reg = 0x0000, + .port_cfgs = { + [USB2PHY_PORT_OTG] = { + .phy_sus = { 0x000c, 11, 11, 0, 1 }, + .ls_det_en = { 0x0080, 0, 0, 0, 1 }, + .ls_det_st = { 0x0084, 0, 0, 0, 1 }, + .ls_det_clr = { 0x0088, 0, 0, 0, 1 }, + .utmi_ls = { 0x00c0, 10, 9, 0, 1 }, + } + }, + }, + { + .reg = 0x4000, + .port_cfgs = { + [USB2PHY_PORT_OTG] = { + .phy_sus = { 0x000c, 11, 11, 0, 0 }, + .ls_det_en = { 0x0080, 0, 0, 0, 1 }, + .ls_det_st = { 0x0084, 0, 0, 0, 1 }, + .ls_det_clr = { 0x0088, 0, 0, 0, 1 }, + .utmi_ls = { 0x00c0, 10, 9, 0, 1 }, + } + }, + }, + { + .reg = 0x8000, + .port_cfgs = { + [USB2PHY_PORT_HOST] = { + .phy_sus = { 0x0008, 2, 2, 0, 1 }, + .ls_det_en = { 0x0080, 0, 0, 0, 1 }, + .ls_det_st = { 0x0084, 0, 0, 0, 1 }, + .ls_det_clr = { 0x0088, 0, 0, 0, 1 }, + .utmi_ls = { 0x00c0, 10, 9, 0, 1 }, + } + }, + }, + { + .reg = 0xc000, + .port_cfgs = { + [USB2PHY_PORT_HOST] = { + .phy_sus = { 0x0008, 2, 2, 0, 1 }, + .ls_det_en = { 0x0080, 0, 0, 0, 1 }, + .ls_det_st = { 0x0084, 0, 0, 0, 1 }, + .ls_det_clr = { 0x0088, 0, 0, 0, 1 }, + .utmi_ls = { 0x00c0, 10, 9, 0, 1 }, + } + }, + }, + { /* sentinel */ } +}; + static const struct udevice_id rockchip_usb2phy_ids[] = { { .compatible = "rockchip,rk3399-usb2phy", @@ -357,6 +506,10 @@ static const struct udevice_id rockchip_usb2phy_ids[] = { .compatible = "rockchip,rk3568-usb2phy", .data = (ulong)&rk3568_phy_cfgs, }, + { + .compatible = "rockchip,rk3588-usb2phy", + .data = (ulong)&rk3588_phy_cfgs, + }, { /* sentinel */ } }; @@ -366,6 +519,12 @@ U_BOOT_DRIVER(rockchip_usb2phy_port) = { .ops = &rockchip_usb2phy_ops, }; +U_BOOT_DRIVER(rockchip_usb2phy_clock) = { + .name = "rockchip_usb2phy_clock", + .id = UCLASS_CLK, + .ops = &rockchip_usb2phy_clk_ops, +}; + U_BOOT_DRIVER(rockchip_usb2phy) = { .name = "rockchip_usb2phy", .id = UCLASS_PHY, diff --git a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c index 78da5fe7970..d5408ccac97 100644 --- a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c +++ b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c @@ -58,6 +58,7 @@ struct rockchip_combphy_grfcfg { struct combphy_reg con2_for_sata; struct combphy_reg con3_for_sata; struct combphy_reg pipe_con0_for_sata; + struct combphy_reg pipe_con1_for_sata; struct combphy_reg pipe_sgmii_mac_sel; struct combphy_reg pipe_xpcs_phy_ready; struct combphy_reg u3otg0_port_en; @@ -76,7 +77,7 @@ struct rockchip_combphy_priv { struct regmap *pipe_grf; struct regmap *phy_grf; struct phy *phy; - struct reset_ctl phy_rst; + struct reset_ctl_bulk phy_rsts; struct clk ref_clk; const struct rockchip_combphy_cfg *cfg; }; @@ -189,7 +190,7 @@ static int rockchip_combphy_init(struct phy *phy) if (ret) goto err_clk; - reset_deassert(&priv->phy_rst); + reset_deassert_bulk(&priv->phy_rsts); return 0; @@ -204,7 +205,7 @@ static int rockchip_combphy_exit(struct phy *phy) struct rockchip_combphy_priv *priv = dev_get_priv(phy->dev); clk_disable(&priv->ref_clk); - reset_assert(&priv->phy_rst); + reset_assert_bulk(&priv->phy_rsts); return 0; } @@ -255,7 +256,7 @@ static int rockchip_combphy_parse_dt(struct udevice *dev, return PTR_ERR(&priv->ref_clk); } - ret = reset_get_by_index(dev, 0, &priv->phy_rst); + ret = reset_get_bulk(dev, &priv->phy_rsts); if (ret) { dev_err(dev, "no phy reset control specified\n"); return ret; @@ -423,11 +424,105 @@ static const struct rockchip_combphy_cfg rk3568_combphy_cfgs = { .combphy_cfg = rk3568_combphy_cfg, }; +static int rk3588_combphy_cfg(struct rockchip_combphy_priv *priv) +{ + const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; + u32 val; + + switch (priv->mode) { + case PHY_TYPE_PCIE: + param_write(priv->phy_grf, &cfg->con0_for_pcie, true); + param_write(priv->phy_grf, &cfg->con1_for_pcie, true); + param_write(priv->phy_grf, &cfg->con2_for_pcie, true); + param_write(priv->phy_grf, &cfg->con3_for_pcie, true); + break; + case PHY_TYPE_USB3: + param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false); + param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false); + param_write(priv->phy_grf, &cfg->usb_mode_set, true); + break; + case PHY_TYPE_SATA: + param_write(priv->phy_grf, &cfg->con0_for_sata, true); + param_write(priv->phy_grf, &cfg->con1_for_sata, true); + param_write(priv->phy_grf, &cfg->con2_for_sata, true); + param_write(priv->phy_grf, &cfg->con3_for_sata, true); + param_write(priv->pipe_grf, &cfg->pipe_con0_for_sata, true); + param_write(priv->pipe_grf, &cfg->pipe_con1_for_sata, true); + break; + case PHY_TYPE_SGMII: + case PHY_TYPE_QSGMII: + default: + dev_err(priv->dev, "incompatible PHY type\n"); + return -EINVAL; + } + + /* 100MHz refclock signal is good */ + clk_set_rate(&priv->ref_clk, 100000000); + param_write(priv->phy_grf, &cfg->pipe_clk_100m, true); + if (priv->mode == PHY_TYPE_PCIE) { + /* PLL KVCO tuning fine */ + val = readl(priv->mmio + (0x20 << 2)); + val &= ~GENMASK(4, 2); + val |= 0x4 << 2; + writel(val, priv->mmio + (0x20 << 2)); + + /* Set up rx_trim: PLL LPF C1 85pf R1 1.25kohm */ + val = 0x4c; + writel(val, priv->mmio + (0x1b << 2)); + + /* Set up su_trim: T3 */ + val = 0xb0; + writel(val, priv->mmio + (0xa << 2)); + val = 0x47; + writel(val, priv->mmio + (0xb << 2)); + val = 0x57; + writel(val, priv->mmio + (0xd << 2)); + } + + return 0; +} + +static const struct rockchip_combphy_grfcfg rk3588_combphy_grfcfgs = { + /* pipe-phy-grf */ + .pcie_mode_set = { 0x0000, 5, 0, 0x00, 0x11 }, + .usb_mode_set = { 0x0000, 5, 0, 0x00, 0x04 }, + .pipe_rxterm_set = { 0x0000, 12, 12, 0x00, 0x01 }, + .pipe_txelec_set = { 0x0004, 1, 1, 0x00, 0x01 }, + .pipe_txcomp_set = { 0x0004, 4, 4, 0x00, 0x01 }, + .pipe_clk_25m = { 0x0004, 14, 13, 0x00, 0x01 }, + .pipe_clk_100m = { 0x0004, 14, 13, 0x00, 0x02 }, + .pipe_rxterm_sel = { 0x0008, 8, 8, 0x00, 0x01 }, + .pipe_txelec_sel = { 0x0008, 12, 12, 0x00, 0x01 }, + .pipe_txcomp_sel = { 0x0008, 15, 15, 0x00, 0x01 }, + .pipe_clk_ext = { 0x000c, 9, 8, 0x02, 0x01 }, + .pipe_phy_status = { 0x0034, 6, 6, 0x01, 0x00 }, + .con0_for_pcie = { 0x0000, 15, 0, 0x00, 0x1000 }, + .con1_for_pcie = { 0x0004, 15, 0, 0x00, 0x0000 }, + .con2_for_pcie = { 0x0008, 15, 0, 0x00, 0x0101 }, + .con3_for_pcie = { 0x000c, 15, 0, 0x00, 0x0200 }, + .con0_for_sata = { 0x0000, 15, 0, 0x00, 0x0129 }, + .con1_for_sata = { 0x0004, 15, 0, 0x00, 0x0040 }, + .con2_for_sata = { 0x0008, 15, 0, 0x00, 0x80c1 }, + .con3_for_sata = { 0x000c, 15, 0, 0x00, 0x0407 }, + /* pipe-grf */ + .pipe_con0_for_sata = { 0x0000, 11, 5, 0x00, 0x22 }, + .pipe_con1_for_sata = { 0x0000, 2, 0, 0x00, 0x2 }, +}; + +static const struct rockchip_combphy_cfg rk3588_combphy_cfgs = { + .grfcfg = &rk3588_combphy_grfcfgs, + .combphy_cfg = rk3588_combphy_cfg, +}; + static const struct udevice_id rockchip_combphy_ids[] = { { .compatible = "rockchip,rk3568-naneng-combphy", .data = (ulong)&rk3568_combphy_cfgs }, + { + .compatible = "rockchip,rk3588-naneng-combphy", + .data = (ulong)&rk3588_combphy_cfgs + }, { } }; diff --git a/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c index 5ae41fbeeec..66c75f98e6d 100644 --- a/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c +++ b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c @@ -93,8 +93,8 @@ static int rockchip_p3phy_probe(struct udevice *dev) struct udevice *syscon; int ret; - priv->mmio = (void __iomem *)dev_read_addr(dev); - if ((fdt_addr_t)priv->mmio == FDT_ADDR_T_NONE) + priv->mmio = dev_read_addr_ptr(dev); + if (!priv->mmio) return -EINVAL; ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c b/drivers/phy/rockchip/phy-rockchip-typec.c index ca63b856e13..47c69dd6c45 100644 --- a/drivers/phy/rockchip/phy-rockchip-typec.c +++ b/drivers/phy/rockchip/phy-rockchip-typec.c @@ -674,9 +674,9 @@ static int rockchip_tcphy_probe(struct udevice *dev) unsigned int reg; int index, ret; - priv->reg_base = (void __iomem *)dev_read_addr(dev); - if (IS_ERR(priv->reg_base)) - return PTR_ERR(priv->reg_base); + priv->reg_base = dev_read_addr_ptr(dev); + if (!priv->reg_base) + return -EINVAL; ret = dev_read_u32_index(dev, "reg", 1, ®); if (ret) { |