[PATCH v5 3/9] reset: rzg2l-usbphy-ctrl: Add RZ/G3L support
Biju <[email protected]> Wed, 29 Jul 2026 12:50:11 +0100
| Newsgroups | org.kernel.vger.linux-renesas-soc,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
From: Biju Das <[email protected]> Add the renesas,r9a08g046-usbphy-ctrl compatible string to the OF match table for the RZ/G3L (r9a08g046) SoC, using a dedicated rzg3l_info struct with pwrrdy set, similar to RZ/G3S. The RZ/G3L SoC has 2 OTG controllers compared to one on RZ/G3S, so it uses a separate rzg3l-vbus-regulator driver to handle the additional VBUSEN control for port 2. The regulator_name field is used as the platform device name passed to platform_device_alloc(), and must exactly match the name the corresponding regulator driver registers via its id_table for platform bus matching to succeed. Signed-off-by: Biju Das <[email protected]> --- v4->v5: * Replaced the variable regulator_driver_name->regulator_name in struct rzg2l_usbphy_ctrl_info * Switched to power sequence consumer for controlling pwrrdy signal. * Updated commit description. v3->v4: * Updated the commit description. * Migrated to id_table match using driver_name and reduced the length < 24. v2->v3: * No change. v1->v2: * No change. --- drivers/reset/reset-rzg2l-usbphy-ctrl.c | 79 +++++++++++++++++++++++-- 1 file changed, 73 insertions(+), 6 deletions(-) diff --git a/drivers/reset/reset-rzg2l-usbphy-ctrl.c b/drivers/reset/reset-rzg2l-usbphy-ctrl.c index 40e28d033a93..f332ef9ef3e5 100644 --- a/drivers/reset/reset-rzg2l-usbphy-ctrl.c +++ b/drivers/reset/reset-rzg2l-usbphy-ctrl.c @@ -10,6 +10,7 @@ #include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> +#include <linux/pwrseq/consumer.h> #include <linux/regmap.h> #include <linux/reset.h> #include <linux/reset-controller.h> @@ -37,11 +38,13 @@ struct rzg2l_usbphy_ctrl_priv { void __iomem *base; struct platform_device *vdev; struct regmap_field *pwrrdy; + struct pwrseq_desc *pwrseq; spinlock_t lock; }; struct rzg2l_usbphy_ctrl_info { + const char *regulator_name; bool pwrrdy; }; @@ -110,15 +113,24 @@ static void rzg2l_usbphy_ctrl_init(struct rzg2l_usbphy_ctrl_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); } -static const struct rzg2l_usbphy_ctrl_info rzg2l_info = {}; +static const struct rzg2l_usbphy_ctrl_info rzg2l_info = { + .regulator_name = "rzg2l-vbus-regulator", +}; static const struct rzg2l_usbphy_ctrl_info rzg3s_info = { + .regulator_name = "rzg2l-vbus-regulator", + .pwrrdy = true, +}; + +static const struct rzg2l_usbphy_ctrl_info rzg3l_info = { + .regulator_name = "rzg3l-vbus-regulator", .pwrrdy = true, }; static const struct of_device_id rzg2l_usbphy_ctrl_match_table[] = { { .compatible = "renesas,rzg2l-usbphy-ctrl", .data = &rzg2l_info }, { .compatible = "renesas,r9a08g045-usbphy-ctrl", .data = &rzg3s_info }, + { .compatible = "renesas,r9a08g046-usbphy-ctrl", .data = &rzg3l_info }, { /* Sentinel */ } }; MODULE_DEVICE_TABLE(of, rzg2l_usbphy_ctrl_match_table); @@ -150,11 +162,16 @@ static int rzg2l_usbphy_ctrl_set_pwrrdy(struct regmap_field *pwrrdy, static void rzg2l_usbphy_ctrl_pwrrdy_off(void *data) { - rzg2l_usbphy_ctrl_set_pwrrdy(data, false); + struct rzg2l_usbphy_ctrl_priv *priv = data; + + if (priv->pwrrdy) + rzg2l_usbphy_ctrl_set_pwrrdy(priv->pwrrdy, false); + else + pwrseq_power_off(priv->pwrseq); } -static int rzg2l_usbphy_ctrl_pwrrdy_init(struct device *dev, - struct rzg2l_usbphy_ctrl_priv *priv) +static int rzg2l_usbphy_ctrl_pwrrdy_syscon_init(struct device *dev, + struct rzg2l_usbphy_ctrl_priv *priv) { struct reg_field field; struct regmap *regmap; @@ -183,7 +200,43 @@ static int rzg2l_usbphy_ctrl_pwrrdy_init(struct device *dev, if (ret) return ret; - return devm_add_action_or_reset(dev, rzg2l_usbphy_ctrl_pwrrdy_off, priv->pwrrdy); + return devm_add_action_or_reset(dev, rzg2l_usbphy_ctrl_pwrrdy_off, priv); +} + +static int rzg2l_usbphy_ctrl_pwrrdy_powerseq_init(struct device *dev, + struct rzg2l_usbphy_ctrl_priv *priv) +{ + int ret; + + priv->pwrseq = devm_pwrseq_get(dev, "usb-pwrrdy"); + if (IS_ERR(priv->pwrseq)) { + /* + * This platform requires a sequencer. If we can't get it, we + * must return the error (including -EPROBE_DEFER to wait for + * the provider to appear) + */ + return dev_err_probe(dev, PTR_ERR(priv->pwrseq), + "Failed to get required power sequencer\n"); + } + + ret = pwrseq_power_on(priv->pwrseq); + if (ret) + return ret; + + return devm_add_action_or_reset(dev, rzg2l_usbphy_ctrl_pwrrdy_off, priv); +} + +static int rzg2l_usbphy_ctrl_pwrrdy_init(struct device *dev, + struct rzg2l_usbphy_ctrl_priv *priv) +{ + int ret; + + if (of_property_present(dev->of_node, "renesas,sysc-pwrrdy")) + ret = rzg2l_usbphy_ctrl_pwrrdy_syscon_init(dev, priv); + else + ret = rzg2l_usbphy_ctrl_pwrrdy_powerseq_init(dev, priv); + + return ret; } static int rzg2l_usbphy_ctrl_probe(struct platform_device *pdev) @@ -245,7 +298,7 @@ static int rzg2l_usbphy_ctrl_probe(struct platform_device *pdev) if (error) goto err_pm_runtime_put; - vdev = platform_device_alloc("rzg2l-usb-vbus-regulator", pdev->id); + vdev = platform_device_alloc(info->regulator_name, pdev->id); if (!vdev) { error = -ENOMEM; goto err_pm_runtime_put; @@ -300,6 +353,12 @@ static int rzg2l_usbphy_ctrl_suspend(struct device *dev) if (ret) goto reset_deassert; + if (priv->pwrseq) { + ret = pwrseq_power_off(priv->pwrseq); + if (ret) + goto reset_deassert; + } + return 0; reset_deassert: @@ -314,6 +373,12 @@ static int rzg2l_usbphy_ctrl_resume(struct device *dev) struct rzg2l_usbphy_ctrl_priv *priv = dev_get_drvdata(dev); int ret; + if (priv->pwrseq) { + ret = pwrseq_power_on(priv->pwrseq); + if (ret) + return ret; + } + ret = rzg2l_usbphy_ctrl_set_pwrrdy(priv->pwrrdy, true); if (ret) return ret; @@ -334,6 +399,8 @@ static int rzg2l_usbphy_ctrl_resume(struct device *dev) reset_control_assert(priv->rstc); pwrrdy_off: rzg2l_usbphy_ctrl_set_pwrrdy(priv->pwrrdy, false); + if (priv->pwrseq) + pwrseq_power_off(priv->pwrseq); return ret; } -- 2.43.0