[PATCH 3/5] phy: sun4i-usb: Control supplies via the regulator uclass
Andre Przywara
andre.przywara at arm.com
Tue Jan 30 01:09:40 CET 2024
On Tue, 31 Oct 2023 01:39:53 -0500
Samuel Holland <samuel at sholland.org> wrote:
Hi Samuel,
> The device tree binding for the PHY provides VBUS supplies as regulator
> references. Now that all boards have the appropriate regulator uclass
> drivers enabled, the PHY driver can switch to using them. This replaces
> direct GPIO usage, which in some cases needed a special DM-incompatible
> "virtual" GPIO from the PMIC.
I like that one, avoids one more Kconfig duplicate.
Testing this revealed one problem, though:
> The following boards provided a value for CONFIG_USB0_VBUS_PIN, but are
> missing the "usb0_vbus-supply" property in their device tree. None of
> them have the MUSB controller enabled in host or OTG mode, so they
> should see no impact:
> - Ainol_AW1_defconfig / sun7i-a20-ainol-aw1
> - Ampe_A76_defconfig / sun5i-a13-ampe-a76
> - CHIP_pro_defconfig / sun5i-gr8-chip-pro
> - Cubieboard4_defconfig / sun9i-a80-cubieboard4
> - Merrii_A80_Optimus_defconfig / sun9i-a80-optimus
> - Sunchip_CX-A99_defconfig / sun9i-a80-cx-a99
> - Yones_Toptech_BD1078_defconfig / sun7i-a20-yones-toptech-bd1078
> - Yones_Toptech_BS1078_V2_defconfig /
> sun6i-a31s-yones-toptech-bs1078-v2
> - iNet_3F_defconfig / sun4i-a10-inet-3f
> - iNet_3W_defconfig / sun4i-a10-inet-3w
> - iNet_86VS_defconfig / sun5i-a13-inet-86vs
> - iNet_D978_rev2_defconfig / sun8i-a33-inet-d978-rev2
> - icnova-a20-swac_defconfig / sun7i-a20-icnova-swac
> - sun8i_a23_evb_defconfig / sun8i-a23-evb
>
> Similarly, the following boards set CONFIG_USB1_VBUS_PIN, but do not
> have "usb1_vbus-supply" in their device tree. Neither of them have USB
> enabled at all, so again there should be no impact:
> - Cubieboard4_defconfig / sun9i-a80-cubieboard4 (also for USB3)
> - sun8i_a23_evb_defconfig / sun8i-a23-evb
>
> The following boards use a different pin for USB1 VBUS between their
> defconfig and their device tree. Depending on which is correct, they
> may be broken:
> - Linksprite_pcDuino3_Nano_defconfig (PH11) /
> sun7i-a20-pcduino3-nano (PD2)
> - icnova-a20-swac_defconfig (PG10) / sun7i-a20-icnova-swac (PH6)
>
> Finally, this board has conflicting pins given for its USB2 VBUS:
> - Lamobo_R1_defconfig (PH3) / sun7i-a20-lamobo-r1 (PH12)
>
> Signed-off-by: Samuel Holland <samuel at sholland.org>
> ---
>
> drivers/phy/allwinner/phy-sun4i-usb.c | 41 +++++++++++++--------------
> 1 file changed, 19 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c
> index 6624e9134f4..dc34b828a3a 100644
> --- a/drivers/phy/allwinner/phy-sun4i-usb.c
> +++ b/drivers/phy/allwinner/phy-sun4i-usb.c
> @@ -87,27 +87,22 @@ struct sun4i_usb_phy_cfg {
> };
>
> struct sun4i_usb_phy_info {
> - const char *gpio_vbus;
> const char *gpio_vbus_det;
> const char *gpio_id_det;
> } phy_info[] = {
> {
> - .gpio_vbus = CONFIG_USB0_VBUS_PIN,
> .gpio_vbus_det = CONFIG_USB0_VBUS_DET,
> .gpio_id_det = CONFIG_USB0_ID_DET,
> },
> {
> - .gpio_vbus = CONFIG_USB1_VBUS_PIN,
> .gpio_vbus_det = NULL,
> .gpio_id_det = NULL,
> },
> {
> - .gpio_vbus = CONFIG_USB2_VBUS_PIN,
> .gpio_vbus_det = NULL,
> .gpio_id_det = NULL,
> },
> {
> - .gpio_vbus = CONFIG_USB3_VBUS_PIN,
> .gpio_vbus_det = NULL,
> .gpio_id_det = NULL,
> },
> @@ -115,12 +110,12 @@ struct sun4i_usb_phy_info {
>
> struct sun4i_usb_phy_plat {
> void __iomem *pmu;
> - struct gpio_desc gpio_vbus;
> struct gpio_desc gpio_vbus_det;
> struct gpio_desc gpio_id_det;
> struct clk clocks;
> struct clk clk2;
> struct reset_ctl resets;
> + struct udevice *vbus;
> int id;
> };
>
> @@ -209,6 +204,7 @@ static int sun4i_usb_phy_power_on(struct phy *phy)
> {
> struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev);
> struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id];
> + int ret;
>
> if (initial_usb_scan_delay) {
> mdelay(initial_usb_scan_delay);
> @@ -221,8 +217,11 @@ static int sun4i_usb_phy_power_on(struct phy *phy)
> return 0;
> }
>
> - if (dm_gpio_is_valid(&usb_phy->gpio_vbus))
> - dm_gpio_set_value(&usb_phy->gpio_vbus, 1);
> + if (usb_phy->vbus) {
> + ret = regulator_set_enable(usb_phy->vbus, true);
> + if (ret && ret != -ENOSYS)
> + return ret;
> + }
>
> return 0;
> }
> @@ -231,9 +230,13 @@ static int sun4i_usb_phy_power_off(struct phy *phy)
> {
> struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev);
> struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id];
> + int ret;
>
> - if (dm_gpio_is_valid(&usb_phy->gpio_vbus))
> - dm_gpio_set_value(&usb_phy->gpio_vbus, 0);
> + if (usb_phy->vbus) {
> + ret = regulator_set_enable(usb_phy->vbus, false);
> + if (ret && ret != -ENOSYS)
> + return ret;
> + }
>
> return 0;
> }
> @@ -483,22 +486,16 @@ static int sun4i_usb_phy_probe(struct udevice *dev)
> for (i = 0; i < data->cfg->num_phys; i++) {
> struct sun4i_usb_phy_plat *phy = &plat[i];
> struct sun4i_usb_phy_info *info = &phy_info[i];
> - char name[16];
> + char name[32];
>
> if (data->cfg->missing_phys & BIT(i))
> continue;
>
> - ret = dm_gpio_lookup_name(info->gpio_vbus, &phy->gpio_vbus);
> - if (ret == 0) {
> - ret = dm_gpio_request(&phy->gpio_vbus, "usb_vbus");
> - if (ret)
> - return ret;
> - ret = dm_gpio_set_dir_flags(&phy->gpio_vbus,
> - GPIOD_IS_OUT);
> - if (ret)
> - return ret;
> - ret = dm_gpio_set_value(&phy->gpio_vbus, 0);
> - if (ret)
> + snprintf(name, sizeof(name), "usb%d_vbus-supply", i);
> + ret = device_get_supply_regulator(dev, name, &phy->vbus);
> + if (phy->vbus) {
> + ret = regulator_set_enable(phy->vbus, false);
It's quite likely that this regulator is already disabled, in this case
regulator_set_enable() returns -EALREADY, and probe() exists prematurely.
There is regulator_set_enable_if_allowed() to cover that case, and also
if we want to disable an always-on regulator. When replacing it (and
the call above, in sun4i_usb_phy_power_off()), it works for me, for
instance for the GPIO controlled Orange Pi Zero3, where is was failing
before.
I have fixed that in my tree, if nothing else pops up, there is no need
to re-send.
Cheers,
Andre
> + if (ret && ret != -ENOSYS)
> return ret;
> }
>
More information about the U-Boot
mailing list