summaryrefslogtreecommitdiff
path: root/drivers/reset
diff options
context:
space:
mode:
authorBiju Das <biju.das.jz@bp.renesas.com>2024-07-02 19:00:16 +0100
committerPhilipp Zabel <p.zabel@pengutronix.de>2024-07-03 10:51:53 +0200
commit4068f22e4b47f7352fc369c22800e04d2860416b (patch)
treee2768a83e9673592ed11fe1dc2e83a3f0294127c /drivers/reset
parentf64f2d6fdda459b10bc8f774ed87e9980a5021e5 (diff)
downloadlwn-4068f22e4b47f7352fc369c22800e04d2860416b.tar.gz
lwn-4068f22e4b47f7352fc369c22800e04d2860416b.zip
reset: renesas: Add USB VBUS regulator device as child
As per RZ/G2L HW manual, VBUS enable can be controlled by the VBOUT bit of the VBUS Control Register(VBENCTL) register in the USBPHY Control. Expose this register as regmap and instantiate the USB VBUS regulator device, so that consumer can control the vbus using regulator API's Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com> Link: https://lore.kernel.org/r/20240702180032.207275-3-biju.das.jz@bp.renesas.com Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Diffstat (limited to 'drivers/reset')
-rw-r--r--drivers/reset/reset-rzg2l-usbphy-ctrl.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/drivers/reset/reset-rzg2l-usbphy-ctrl.c b/drivers/reset/reset-rzg2l-usbphy-ctrl.c
index bea3270fb698..255c894a4782 100644
--- a/drivers/reset/reset-rzg2l-usbphy-ctrl.c
+++ b/drivers/reset/reset-rzg2l-usbphy-ctrl.c
@@ -10,10 +10,12 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
#include <linux/reset.h>
#include <linux/reset-controller.h>
#define RESET 0x000
+#define VBENCTL 0x03c
#define RESET_SEL_PLLRESET BIT(12)
#define RESET_PLLRESET BIT(8)
@@ -32,6 +34,7 @@ struct rzg2l_usbphy_ctrl_priv {
struct reset_controller_dev rcdev;
struct reset_control *rstc;
void __iomem *base;
+ struct platform_device *vdev;
spinlock_t lock;
};
@@ -100,10 +103,19 @@ static const struct reset_control_ops rzg2l_usbphy_ctrl_reset_ops = {
.status = rzg2l_usbphy_ctrl_status,
};
+static const struct regmap_config rzg2l_usb_regconf = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .max_register = 1,
+};
+
static int rzg2l_usbphy_ctrl_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct rzg2l_usbphy_ctrl_priv *priv;
+ struct platform_device *vdev;
+ struct regmap *regmap;
unsigned long flags;
int error;
u32 val;
@@ -116,6 +128,10 @@ static int rzg2l_usbphy_ctrl_probe(struct platform_device *pdev)
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
+ regmap = devm_regmap_init_mmio(dev, priv->base + VBENCTL, &rzg2l_usb_regconf);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
if (IS_ERR(priv->rstc))
return dev_err_probe(dev, PTR_ERR(priv->rstc),
@@ -152,8 +168,22 @@ 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);
+ if (!vdev) {
+ error = -ENOMEM;
+ goto err_pm_runtime_put;
+ }
+ vdev->dev.parent = dev;
+ priv->vdev = vdev;
+
+ error = platform_device_add(vdev);
+ if (error)
+ goto err_device_put;
+
return 0;
+err_device_put:
+ platform_device_put(vdev);
err_pm_runtime_put:
pm_runtime_put(&pdev->dev);
err_pm_disable_reset_deassert:
@@ -166,6 +196,7 @@ static int rzg2l_usbphy_ctrl_remove(struct platform_device *pdev)
{
struct rzg2l_usbphy_ctrl_priv *priv = dev_get_drvdata(&pdev->dev);
+ platform_device_unregister(priv->vdev);
pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev);
reset_control_assert(priv->rstc);