Skip to content

Commit b6d7dd1

Browse files
Tommaso Merciaivinodkoul
authored andcommitted
phy: renesas: rcar-gen3-usb2: Add regulator for OTG VBUS control
Enable OTG VBUS control on R-Car Gen3 USB2 PHY by registering a regulator driver that manages the VBOUT line. This change allows the controller to handle VBUS output for OTG ports using the regulator framework when the platform requires hardware-based VBUS control. Without this, some platforms cannot properly manage VBUS power on OTG- capable ports, leading to potential USB functionality issues. Signed-off-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com> Link: https://patch.msgid.link/6c1aebf60b4d8ff0c51a8243c68b397c1a384867.1766405010.git.tommaso.merciai.xr@bp.renesas.com Signed-off-by: Vinod Koul <vkoul@kernel.org>
1 parent 230c817 commit b6d7dd1

1 file changed

Lines changed: 137 additions & 5 deletions

File tree

drivers/phy/renesas/phy-rcar-gen3-usb2.c

Lines changed: 137 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <linux/platform_device.h>
2323
#include <linux/pm_runtime.h>
2424
#include <linux/regulator/consumer.h>
25+
#include <linux/regulator/driver.h>
2526
#include <linux/reset.h>
2627
#include <linux/string.h>
2728
#include <linux/usb/of.h>
@@ -141,6 +142,7 @@ struct rcar_gen3_chan {
141142
bool extcon_host;
142143
bool is_otg_channel;
143144
bool uses_otg_pins;
145+
bool otg_internal_reg;
144146
};
145147

146148
struct rcar_gen3_phy_drv_data {
@@ -225,6 +227,11 @@ static void rcar_gen3_phy_usb2_set_vbus(struct rcar_gen3_chan *ch,
225227

226228
static void rcar_gen3_enable_vbus_ctrl(struct rcar_gen3_chan *ch, int vbus)
227229
{
230+
if (ch->otg_internal_reg) {
231+
regulator_hardware_enable(ch->vbus, vbus);
232+
return;
233+
}
234+
228235
if (ch->phy_data->no_adp_ctrl || ch->phy_data->vblvl_ctrl) {
229236
if (ch->vbus)
230237
regulator_hardware_enable(ch->vbus, vbus);
@@ -593,7 +600,7 @@ static int rcar_gen3_phy_usb2_power_on(struct phy *p)
593600
u32 val;
594601
int ret = 0;
595602

596-
if (channel->vbus) {
603+
if (channel->vbus && !channel->otg_internal_reg) {
597604
ret = regulator_enable(channel->vbus);
598605
if (ret)
599606
return ret;
@@ -634,7 +641,7 @@ static int rcar_gen3_phy_usb2_power_off(struct phy *p)
634641
}
635642
}
636643

637-
if (channel->vbus)
644+
if (channel->vbus && !channel->otg_internal_reg)
638645
ret = regulator_disable(channel->vbus);
639646

640647
return ret;
@@ -809,6 +816,128 @@ static int rcar_gen3_phy_usb2_init_bus(struct rcar_gen3_chan *channel)
809816
return 0;
810817
}
811818

819+
static int rcar_gen3_phy_usb2_regulator_endisable(struct regulator_dev *rdev,
820+
bool enable)
821+
{
822+
struct rcar_gen3_chan *channel = rdev_get_drvdata(rdev);
823+
struct device *dev = channel->dev;
824+
int ret;
825+
826+
ret = pm_runtime_resume_and_get(dev);
827+
if (ret < 0) {
828+
dev_warn(dev, "pm_runtime_get failed: %i\n", ret);
829+
return ret;
830+
}
831+
832+
rcar_gen3_phy_usb2_set_vbus(channel, USB2_VBCTRL,
833+
USB2_VBCTRL_VBOUT, enable);
834+
pm_runtime_put_noidle(dev);
835+
836+
return ret;
837+
}
838+
839+
static int rcar_gen3_phy_usb2_regulator_enable(struct regulator_dev *rdev)
840+
{
841+
return rcar_gen3_phy_usb2_regulator_endisable(rdev, true);
842+
}
843+
844+
static int rcar_gen3_phy_usb2_regulator_disable(struct regulator_dev *rdev)
845+
{
846+
return rcar_gen3_phy_usb2_regulator_endisable(rdev, false);
847+
}
848+
849+
static int rcar_gen3_phy_usb2_regulator_is_enabled(struct regulator_dev *rdev)
850+
{
851+
struct rcar_gen3_chan *channel = rdev_get_drvdata(rdev);
852+
void __iomem *usb2_base = channel->base;
853+
struct device *dev = channel->dev;
854+
u32 vbus_ctrl_reg = USB2_VBCTRL;
855+
u32 val;
856+
int ret;
857+
858+
ret = pm_runtime_resume_and_get(dev);
859+
if (ret < 0) {
860+
dev_warn(dev, "pm_runtime_get failed: %i\n", ret);
861+
return ret;
862+
}
863+
864+
val = readl(usb2_base + vbus_ctrl_reg);
865+
866+
pm_runtime_put_noidle(dev);
867+
dev_dbg(channel->dev, "%s: %08x\n", __func__, val);
868+
869+
return (val & USB2_VBCTRL_VBOUT) ? 1 : 0;
870+
}
871+
872+
static const struct regulator_ops rcar_gen3_phy_usb2_regulator_ops = {
873+
.enable = rcar_gen3_phy_usb2_regulator_enable,
874+
.disable = rcar_gen3_phy_usb2_regulator_disable,
875+
.is_enabled = rcar_gen3_phy_usb2_regulator_is_enabled,
876+
};
877+
878+
static const struct regulator_desc rcar_gen3_phy_usb2_regulator = {
879+
.name = "otg-vbus-regulator",
880+
.of_match = of_match_ptr("vbus-regulator"),
881+
.ops = &rcar_gen3_phy_usb2_regulator_ops,
882+
.type = REGULATOR_VOLTAGE,
883+
.owner = THIS_MODULE,
884+
.fixed_uV = 5000000,
885+
.n_voltages = 1,
886+
};
887+
888+
static void rcar_gen3_phy_usb2_vbus_disable_action(void *data)
889+
{
890+
struct regulator *vbus = data;
891+
892+
regulator_disable(vbus);
893+
}
894+
895+
static int rcar_gen3_phy_usb2_vbus_regulator_get_exclusive_enable(struct rcar_gen3_chan *channel,
896+
bool enable)
897+
{
898+
struct device *dev = channel->dev;
899+
int ret;
900+
901+
channel->vbus = devm_regulator_get_exclusive(dev, "vbus");
902+
if (IS_ERR(channel->vbus))
903+
return PTR_ERR(channel->vbus);
904+
905+
if (!enable)
906+
return 0;
907+
908+
ret = regulator_enable(channel->vbus);
909+
if (ret)
910+
return ret;
911+
912+
return devm_add_action_or_reset(dev, rcar_gen3_phy_usb2_vbus_disable_action,
913+
channel->vbus);
914+
}
915+
916+
static int rcar_gen3_phy_usb2_vbus_regulator_register(struct rcar_gen3_chan *channel)
917+
{
918+
struct device *dev = channel->dev;
919+
struct regulator_config rcfg = { .dev = dev, };
920+
struct regulator_dev *rdev;
921+
bool enable = false;
922+
923+
rcfg.of_node = of_get_available_child_by_name(dev->of_node,
924+
"vbus-regulator");
925+
if (rcfg.of_node) {
926+
rcfg.driver_data = channel;
927+
rdev = devm_regulator_register(dev, &rcar_gen3_phy_usb2_regulator,
928+
&rcfg);
929+
of_node_put(rcfg.of_node);
930+
if (IS_ERR(rdev))
931+
return dev_err_probe(dev, PTR_ERR(rdev),
932+
"Failed to create vbus-regulator\n");
933+
934+
channel->otg_internal_reg = true;
935+
enable = true;
936+
}
937+
938+
return rcar_gen3_phy_usb2_vbus_regulator_get_exclusive_enable(channel, enable);
939+
}
940+
812941
static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
813942
{
814943
struct device *dev = &pdev->dev;
@@ -890,10 +1019,13 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
8901019
phy_set_drvdata(channel->rphys[i].phy, &channel->rphys[i]);
8911020
}
8921021

893-
if (channel->phy_data->no_adp_ctrl && channel->is_otg_channel)
894-
channel->vbus = devm_regulator_get_exclusive(dev, "vbus");
895-
else
1022+
if (channel->phy_data->no_adp_ctrl && channel->is_otg_channel) {
1023+
ret = rcar_gen3_phy_usb2_vbus_regulator_register(channel);
1024+
if (ret)
1025+
return ret;
1026+
} else {
8961027
channel->vbus = devm_regulator_get_optional(dev, "vbus");
1028+
}
8971029
if (IS_ERR(channel->vbus)) {
8981030
if (PTR_ERR(channel->vbus) == -EPROBE_DEFER)
8991031
return PTR_ERR(channel->vbus);

0 commit comments

Comments
 (0)