aboutsummaryrefslogtreecommitdiff
path: root/drivers/phy
diff options
context:
space:
mode:
authorTom Rini2023-06-12 14:55:33 -0400
committerTom Rini2023-06-12 14:55:33 -0400
commit260d4962e06c0a7d2713523c131416a3f70d7f2c (patch)
tree14b9d414810e97f1ffdfdaf099db57a5bbf45a79 /drivers/phy
parent5b589e139620214f26eb83c9fb7bbd62b5f8fc1d (diff)
parent19b77d3d23966a0d6dbb3c86187765f11100fb6f (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.c6
-rw-r--r--drivers/phy/marvell/comphy_core.c12
-rw-r--r--drivers/phy/meson-g12a-usb2.c48
-rw-r--r--drivers/phy/meson-gxbb-usb2.c38
-rw-r--r--drivers/phy/meson-gxl-usb2.c30
-rw-r--r--drivers/phy/phy-stm32-usbphyc.c4
-rw-r--r--drivers/phy/phy-uclass.c121
-rw-r--r--drivers/phy/qcom/phy-qcom-usb-hs-28nm.c4
-rw-r--r--drivers/phy/qcom/phy-qcom-usb-ss.c4
-rw-r--r--drivers/phy/rockchip/phy-rockchip-inno-usb2.c169
-rw-r--r--drivers/phy/rockchip/phy-rockchip-naneng-combphy.c103
-rw-r--r--drivers/phy/rockchip/phy-rockchip-snps-pcie3.c4
-rw-r--r--drivers/phy/rockchip/phy-rockchip-typec.c6
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, &reg);
if (ret) {