plat/allwinner: Only enable DRIVEVBUS if really needed

The DRIVEVBUS power rail of the AXP803 PMIC is mostly used to supply
the USB bus power on micro USB sockets, when used in host mode. As this
is a dynamic operation, and mostly we want micro USB sockets to act in
client mode initially, BL31 should not actually enable this power line.
However, on some boards DRIVEVBUS is used to supply power to normal
USB-A sockets. Failing to activate this line there results in
non-functional USB in U-Boot on those boards.

For that reason we were enabling DRIVEVBUS so far, as it did not seem to
cause any harm to the other boards. However it turns out that on the
Pinephone (and other systems with a battery), actually enabling DRIVEVBUS
unconditionally causes serious problems (reboot loop).

To accommodate both use cases, without reverting to a build time option,
check the default OTG configuration in the devicetree. For boards with
USB-A sockets this is set to "host", on boards with micro-B sockets to
"otg". Depending on this setting, we either enable DRIVEVBUS or leave it
alone.

This fixes TF-A on the Pinephone and potentially other battery powered
devices.

Change-Id: Iec0e07f218b2b4393bf4e05c3386261f8ed19e9f
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
This commit is contained in:
Andre Przywara 2020-08-03 00:25:21 +01:00
parent 9bc28a5eb2
commit 93fa305c0a
1 changed files with 21 additions and 1 deletions

View File

@ -105,6 +105,25 @@ static bool should_enable_regulator(const void *fdt, int node)
return false;
}
static bool board_uses_usb0_host_mode(const void *fdt)
{
int node, length;
const char *prop;
node = fdt_node_offset_by_compatible(fdt, -1,
"allwinner,sun8i-a33-musb");
if (node < 0) {
return false;
}
prop = fdt_getprop(fdt, node, "dr_mode", &length);
if (!prop) {
return false;
}
return !strncmp(prop, "host", length);
}
void axp_setup_regulators(const void *fdt)
{
int node;
@ -121,7 +140,8 @@ void axp_setup_regulators(const void *fdt)
}
/* This applies to AXP803 only. */
if (fdt_getprop(fdt, node, "x-powers,drive-vbus-en", NULL)) {
if (fdt_getprop(fdt, node, "x-powers,drive-vbus-en", NULL) &&
board_uses_usb0_host_mode(fdt)) {
axp_clrbits(0x8f, BIT(4));
axp_setbits(0x30, BIT(2));
INFO("PMIC: Enabling DRIVEVBUS\n");