diff options
author | Andre Przywara <andre.przywara@arm.com> | 2018-09-16 11:24:05 +0100 |
---|---|---|
committer | Andre Przywara <andre.przywara@arm.com> | 2018-10-20 16:23:59 +0100 |
commit | ed80c1e2b306d347c25adfe350aa8100a89d88b6 (patch) | |
tree | 0798338d1708c170211dfbb0009355a24cf8a967 /plat/allwinner | |
parent | df301601c872b1c59c55928082a0e1e971b5ba5d (diff) |
allwinner: Scan AXP803 FDT node to setup initial power rails
Now that we have a pointer to the device tree blob, let's use that to
do some initial setup of the PMIC:
- We scan the DT for the compatible string to find the PMIC node.
- We switch the N_VBUSEN pin if the DT property tells us so.
- We scan over all regulator subnodes, and switch DC1SW if there is at
least one other node referencing it (judging by the existence of a
phandle property in that subnode).
This is just the first part of the setup, a follow up patch will setup
voltages.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Diffstat (limited to 'plat/allwinner')
-rw-r--r-- | plat/allwinner/sun50i_a64/sunxi_power.c | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/plat/allwinner/sun50i_a64/sunxi_power.c b/plat/allwinner/sun50i_a64/sunxi_power.c index 48d01d0c..0d73371a 100644 --- a/plat/allwinner/sun50i_a64/sunxi_power.c +++ b/plat/allwinner/sun50i_a64/sunxi_power.c @@ -10,6 +10,7 @@ #include <debug.h> #include <delay_timer.h> #include <errno.h> +#include <libfdt.h> #include <mmio.h> #include <platform_def.h> #include <sunxi_def.h> @@ -126,6 +127,52 @@ static int axp_setbits(uint8_t reg, uint8_t set_mask) return rsb_write(AXP803_RT_ADDR, reg, regval); } +static bool should_enable_regulator(const void *fdt, int node) +{ + if (fdt_getprop(fdt, node, "phandle", NULL) != NULL) + return true; + if (fdt_getprop(fdt, node, "regulator-always-on", NULL) != NULL) + return true; + return false; +} + +static void setup_axp803_rails(const void *fdt) +{ + int node; + + /* locate the PMIC DT node, bail out if not found */ + node = fdt_node_offset_by_compatible(fdt, -1, "x-powers,axp803"); + if (node == -FDT_ERR_NOTFOUND) { + WARN("BL31: PMIC: No AXP803 DT node, skipping initial setup.\n"); + return; + } + + if (fdt_getprop(fdt, node, "x-powers,drive-vbus-en", NULL)) + axp_setbits(0x8f, BIT(4)); + + /* descend into the "regulators" subnode */ + node = fdt_first_subnode(fdt, node); + + /* iterate over all regulators to find used ones */ + for (node = fdt_first_subnode(fdt, node); + node != -FDT_ERR_NOTFOUND; + node = fdt_next_subnode(fdt, node)) { + const char *name; + int length; + + /* We only care if it's always on or referenced. */ + if (!should_enable_regulator(fdt, node)) + continue; + + name = fdt_get_name(fdt, node, &length); + if (!strncmp(name, "dc1sw", length)) { + INFO("PMIC: AXP803: Enabling DC1SW\n"); + axp_setbits(0x12, BIT(7)); + continue; + } + } +} + int sunxi_pmic_setup(uint16_t socid, const void *fdt) { int ret; @@ -148,6 +195,9 @@ int sunxi_pmic_setup(uint16_t socid, const void *fdt) pmic = AXP803_RSB; NOTICE("BL31: PMIC: Detected AXP803 on RSB.\n"); + if (fdt) + setup_axp803_rails(fdt); + break; default: NOTICE("BL31: PMIC: No support for Allwinner %x SoC.\n", socid); |