aboutsummaryrefslogtreecommitdiffstats
path: root/roms/u-boot/drivers/power/pmic
diff options
context:
space:
mode:
authorAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
committerAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
commitaf1a266670d040d2f4083ff309d732d648afba2a (patch)
tree2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/u-boot/drivers/power/pmic
parente02cda008591317b1625707ff8e115a4841aa889 (diff)
Add submodule dependency filesHEADmaster
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/u-boot/drivers/power/pmic')
-rw-r--r--roms/u-boot/drivers/power/pmic/Kconfig334
-rw-r--r--roms/u-boot/drivers/power/pmic/Makefile43
-rw-r--r--roms/u-boot/drivers/power/pmic/act8846.c86
-rw-r--r--roms/u-boot/drivers/power/pmic/as3722.c178
-rw-r--r--roms/u-boot/drivers/power/pmic/as3722_gpio.c120
-rw-r--r--roms/u-boot/drivers/power/pmic/bd71837.c111
-rw-r--r--roms/u-boot/drivers/power/pmic/da9063.c131
-rw-r--r--roms/u-boot/drivers/power/pmic/fan53555.c87
-rw-r--r--roms/u-boot/drivers/power/pmic/i2c_pmic_emul.c166
-rw-r--r--roms/u-boot/drivers/power/pmic/lp873x.c82
-rw-r--r--roms/u-boot/drivers/power/pmic/lp87565.c85
-rw-r--r--roms/u-boot/drivers/power/pmic/max77686.c88
-rw-r--r--roms/u-boot/drivers/power/pmic/max8997.c58
-rw-r--r--roms/u-boot/drivers/power/pmic/max8998.c58
-rw-r--r--roms/u-boot/drivers/power/pmic/mc34708.c106
-rw-r--r--roms/u-boot/drivers/power/pmic/mp5416.c99
-rw-r--r--roms/u-boot/drivers/power/pmic/muic_max8997.c74
-rw-r--r--roms/u-boot/drivers/power/pmic/palmas.c100
-rw-r--r--roms/u-boot/drivers/power/pmic/pca9450.c95
-rw-r--r--roms/u-boot/drivers/power/pmic/pfuze100.c93
-rw-r--r--roms/u-boot/drivers/power/pmic/pm8916.c86
-rw-r--r--roms/u-boot/drivers/power/pmic/pmic-uclass.c200
-rw-r--r--roms/u-boot/drivers/power/pmic/pmic_hi6553.c133
-rw-r--r--roms/u-boot/drivers/power/pmic/pmic_ltc3676.c31
-rw-r--r--roms/u-boot/drivers/power/pmic/pmic_mc34vr500.c31
-rw-r--r--roms/u-boot/drivers/power/pmic/pmic_pca9450.c31
-rw-r--r--roms/u-boot/drivers/power/pmic/pmic_pfuze100.c31
-rw-r--r--roms/u-boot/drivers/power/pmic/pmic_pfuze3000.c31
-rw-r--r--roms/u-boot/drivers/power/pmic/pmic_tps62362.c70
-rw-r--r--roms/u-boot/drivers/power/pmic/pmic_tps65217.c150
-rw-r--r--roms/u-boot/drivers/power/pmic/pmic_tps65218.c260
-rw-r--r--roms/u-boot/drivers/power/pmic/pmic_tps65910.c121
-rw-r--r--roms/u-boot/drivers/power/pmic/pmic_tps65910_dm.c96
-rw-r--r--roms/u-boot/drivers/power/pmic/rk8xx.c198
-rw-r--r--roms/u-boot/drivers/power/pmic/rn5t567.c64
-rw-r--r--roms/u-boot/drivers/power/pmic/s2mps11.c88
-rw-r--r--roms/u-boot/drivers/power/pmic/s5m8767.c92
-rw-r--r--roms/u-boot/drivers/power/pmic/sandbox.c76
-rw-r--r--roms/u-boot/drivers/power/pmic/stpmic1.c269
-rw-r--r--roms/u-boot/drivers/power/pmic/tps65090.c90
-rw-r--r--roms/u-boot/drivers/power/pmic/tps65941.c84
41 files changed, 4426 insertions, 0 deletions
diff --git a/roms/u-boot/drivers/power/pmic/Kconfig b/roms/u-boot/drivers/power/pmic/Kconfig
new file mode 100644
index 000000000..583fd3ddc
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/Kconfig
@@ -0,0 +1,334 @@
+config DM_PMIC
+ bool "Enable Driver Model for PMIC drivers (UCLASS_PMIC)"
+ depends on DM
+ ---help---
+ This config enables the driver-model PMIC support.
+ UCLASS_PMIC - designed to provide an I/O interface for PMIC devices.
+ For the multi-function PMIC devices, this can be used as parent I/O
+ device for each IC's interface. Then, each children uses its parent
+ for read/write. For detailed description, please refer to the files:
+ - 'drivers/power/pmic/pmic-uclass.c'
+ - 'include/power/pmic.h'
+
+config PMIC_CHILDREN
+ bool "Allow child devices for PMICs"
+ depends on DM_PMIC
+ default y
+ ---help---
+ This allows PMICs to support child devices (such as regulators) in
+ SPL. This adds quite a bit of code so if you are not using this
+ feature you can turn it off. Most likely you should turn it on for
+ U-Boot proper.
+
+config SPL_PMIC_CHILDREN
+ bool "Allow child devices for PMICs in SPL"
+ depends on DM_PMIC
+ default y
+ ---help---
+ This allows PMICs to support child devices (such as regulators) in
+ SPL. This adds quite a bit of code so if you are not using this
+ feature you can turn it off. In this case you may need a 'back door'
+ to call your regulator code (e.g. see rk8xx.c for direct functions
+ for use in SPL).
+
+config PMIC_ACT8846
+ bool "Enable support for the active-semi 8846 PMIC"
+ depends on DM_PMIC && DM_I2C
+ ---help---
+ This PMIC includes 4 DC/DC step-down buck regulators and 8 low-dropout
+ regulators (LDOs). It also provides some GPIO, reset and battery
+ functions. It uses an I2C interface and is designed for use with
+ tablets and smartphones.
+
+config DM_PMIC_DA9063
+ bool "Enable Driver Model for the Dialog DA9063 PMIC"
+ depends on DM_PMIC
+ help
+ This config enables implementation of driver-model pmic uclass features
+ for PMIC DA9063. The driver implements read/write operations.
+
+config SPL_DM_PMIC_DA9063
+ bool "Enable Driver Model for the Dialog DA9063 PMIC in SPL"
+ depends on DM_PMIC && SPL
+ help
+ This config enables implementation of driver-model pmic uclass features
+ for PMIC DA9063. The driver implements read/write operations.
+
+config PMIC_AS3722
+ bool "Enable support for the Austria Micro Systems (AMS) AS7322 PMIC"
+ help
+ The AS3722 includes 7 DC/DC buck convertors, 11 low-noise LDOs, a
+ real-time clock, GPIOs, ADC and a few other features. It uses an I2C
+ interface and is designs to cover most of the power managementment
+ required for a tablets or laptop.
+
+config DM_PMIC_BD71837
+ bool "Enable Driver Model for PMIC BD71837"
+ depends on DM_PMIC
+ help
+ This config enables implementation of driver-model pmic uclass features
+ for PMIC BD71837. The driver implements read/write operations.
+
+config SPL_DM_PMIC_BD71837
+ bool "Enable Driver Model for PMIC BD71837 in SPL stage"
+ depends on DM_PMIC
+ help
+ This config enables implementation of driver-model pmic uclass
+ features for PMIC BD71837. The driver implements read/write
+ operations.
+
+config DM_PMIC_FAN53555
+ bool "Enable support for OnSemi FAN53555"
+ depends on DM_PMIC && DM_REGULATOR && DM_I2C
+ select DM_REGULATOR_FAN53555
+ help
+ This config enables implementation of driver-model PMIC
+ uclass features for the FAN53555 regulator. The FAN53555 is
+ a (family of) single-output regulators that supports
+ transitioning between two different output voltages based on
+ an voltage selection pin.
+
+ The driver implements read/write operations for use with the FAN53555
+ regulator driver and binds the regulator driver to its node.
+
+config DM_PMIC_MP5416
+ bool "Enable Driver Model for PMIC MP5416"
+ depends on DM_PMIC
+ help
+ This config enables implementation of driver-model pmic uclass features
+ for PMIC MP5416. The driver implements read/write operations.
+
+config SPL_DM_PMIC_MP5416
+ bool "Enable Driver Model for PMIC MP5416 in SPL stage"
+ depends on DM_PMIC
+ help
+ This config enables implementation of driver-model pmic uclass
+ features for PMIC MP5416. The driver implements read/write
+ operations.
+
+config DM_PMIC_PCA9450
+ bool "Enable Driver Model for PMIC PCA9450"
+ depends on DM_PMIC
+ help
+ This config enables implementation of driver-model pmic uclass features
+ for PMIC PCA9450. The driver implements read/write operations.
+
+config SPL_DM_PMIC_PCA9450
+ bool "Enable Driver Model for PMIC PCA9450"
+ depends on DM_PMIC
+ help
+ This config enables implementation of driver-model pmic uclass features
+ for PMIC PCA9450 in SPL. The driver implements read/write operations.
+
+config DM_PMIC_PFUZE100
+ bool "Enable Driver Model for PMIC PFUZE100"
+ depends on DM_PMIC
+ ---help---
+ This config enables implementation of driver-model pmic uclass features
+ for PMIC PFUZE100. The driver implements read/write operations.
+
+config SPL_DM_PMIC_PFUZE100
+ bool "Enable Driver Model for PMIC PFUZE100 in SPL"
+ depends on DM_PMIC
+ ---help---
+ This config enables implementation of driver-model pmic uclass features
+ for PMIC PFUZE100 in SPL. The driver implements read/write operations.
+
+config DM_PMIC_MAX77686
+ bool "Enable Driver Model for PMIC MAX77686"
+ depends on DM_PMIC
+ ---help---
+ This config enables implementation of driver-model pmic uclass features
+ for PMIC MAX77686. The driver implements read/write operations.
+
+config DM_PMIC_MAX8998
+ bool "Enable Driver Model for PMIC MAX8998"
+ depends on DM_PMIC
+ ---help---
+ This config enables implementation of driver-model pmic uclass features
+ for PMIC MAX8998. The driver implements read/write operations.
+
+config DM_PMIC_MC34708
+ bool "Enable Driver Model for PMIC MC34708"
+ depends on DM_PMIC
+ help
+ This config enables implementation of driver-model pmic uclass features
+ for PMIC MC34708. The driver implements read/write operations.
+
+config PMIC_MAX8997
+ bool "Enable Driver Model for PMIC MAX8997"
+ depends on DM_PMIC
+ ---help---
+ This config enables implementation of driver-model pmic uclass features
+ for PMIC MAX8997. The driver implements read/write operations.
+ This is a Power Management IC with RTC, Fuel Gauge, MUIC control on Chip.
+ - 21x LDOs
+ - 12x GPIOs
+ - Haptic Motor driver
+ - RTC with two alarms
+ - Fueal Gauge and One backup battery charger
+ - MUIC
+ - Others
+
+config PMIC_PM8916
+ bool "Enable Driver Model for Qualcomm PM8916 PMIC"
+ depends on DM_PMIC
+ ---help---
+ The PM8916 is a PMIC connected to one (or several) processors
+ with SPMI bus. It has 2 slaves with several peripherals:
+ - 18x LDO
+ - 4x GPIO
+ - Power and Reset buttons
+ - Watchdog
+ - RTC
+ - Vibrator drivers
+ - Others
+
+ Driver binding info: doc/device-tree-bindings/pmic/pm8916.txt
+
+config PMIC_RK8XX
+ bool "Enable support for Rockchip PMIC RK8XX"
+ depends on DM_PMIC
+ ---help---
+ The Rockchip RK808 PMIC provides four buck DC-DC convertors, 8 LDOs,
+ an RTC and two low Rds (resistance (drain to source)) switches. It is
+ accessed via an I2C interface. The device is used with Rockchip SoCs.
+ This driver implements register read/write operations.
+
+config PMIC_S2MPS11
+ bool "Enable Driver Model for PMIC Samsung S2MPS11"
+ depends on DM_PMIC
+ ---help---
+ The Samsung S2MPS11 PMIC provides:
+ - 38 adjustable LDO regulators
+ - 9 High-Efficiency Buck Converters
+ - 1 BuckBoost Converter
+ - RTC with two alarms
+ - Backup battery charger
+ - I2C Configuration Interface
+ This driver provides access to I/O interface only.
+ Binding info: doc/device-tree-bindings/pmic/s2mps11.txt
+
+config DM_PMIC_SANDBOX
+ bool "Enable Driver Model for emulated Sandbox PMIC"
+ depends on DM_PMIC
+ ---help---
+ Enable the driver for Sandbox PMIC emulation. The emulated PMIC device
+ depends on two drivers:
+ - sandbox PMIC I/O driver - implements dm pmic operations
+ - sandbox PMIC i2c emul driver - emulates the PMIC's I2C transmission
+
+ A detailed information can be found in header: '<power/sandbox_pmic.h>'
+
+ The Sandbox PMIC info:
+ * I/O interface:
+ - I2C chip address: 0x40
+ - first register address: 0x0
+ - register count: 0x10
+ * Adjustable outputs:
+ - 2x LDO
+ - 2x BUCK
+ - Each, with a different operating conditions (header).
+ * Reset values:
+ - set by i2c emul driver's probe() (defaults in header)
+
+ Driver binding info: doc/device-tree-bindings/pmic/sandbox.txt
+
+config PMIC_S5M8767
+ bool "Enable Driver Model for the Samsung S5M8767 PMIC"
+ depends on DM_PMIC
+ ---help---
+ The S5M8767 PMIC provides a large array of LDOs and BUCKs for use
+ as a SoC power controller. It also provides 32KHz clock outputs. This
+ driver provides basic register access and sets up the attached
+ regulators if regulator support is enabled.
+
+config PMIC_RN5T567
+ bool "Enable driver for Ricoh RN5T567 PMIC"
+ depends on DM_PMIC
+ ---help---
+ The RN5T567 is a PMIC with 4 step-down DC/DC converters, 5 LDO
+ regulators Real-Time Clock and 4 GPIOs. This driver provides
+ register access only.
+
+config PMIC_TPS65090
+ bool "Enable driver for Texas Instruments TPS65090 PMIC"
+ depends on DM_PMIC
+ ---help---
+ The TPS65090 is a PMIC containing several LDOs, DC to DC convertors,
+ FETs and a battery charger. This driver provides register access
+ only, and you can enable the regulator/charger drivers separately if
+ required.
+
+config PMIC_PALMAS
+ bool "Enable driver for Texas Instruments PALMAS PMIC"
+ depends on DM_PMIC
+ ---help---
+ The PALMAS is a PMIC containing several LDOs, SMPS.
+ This driver binds the pmic children.
+
+config PMIC_LP873X
+ bool "Enable driver for Texas Instruments LP873X PMIC"
+ depends on DM_PMIC
+ ---help---
+ The LP873X is a PMIC containing couple of LDOs and couple of SMPS.
+ This driver binds the pmic children.
+
+config PMIC_LP87565
+ bool "Enable driver for Texas Instruments LP87565 PMIC"
+ depends on DM_PMIC
+ ---help---
+ The LP87565 is a PMIC containing a bunch of SMPS.
+ This driver binds the pmic children.
+
+config POWER_MC34VR500
+ bool "Enable driver for Freescale MC34VR500 PMIC"
+ ---help---
+ The MC34VR500 is used in conjunction with the FSL T1 and LS1 series
+ SoC. It provides 4 buck DC-DC convertors and 5 LDOs, and it is accessed
+ via an I2C interface.
+
+config DM_PMIC_TPS65910
+ bool "Enable driver for Texas Instruments TPS65910 PMIC"
+ depends on DM_PMIC
+ ---help---
+ The TPS65910 is a PMIC containing 3 buck DC-DC converters, one boost
+ DC-DC converter, 8 LDOs and a RTC. This driver binds the SMPS and LDO
+ pmic children.
+
+config PMIC_STPMIC1
+ bool "Enable support for STMicroelectronics STPMIC1 PMIC"
+ depends on DM_PMIC && DM_I2C
+ select SYSRESET_CMD_POWEROFF if CMD_POWEROFF && !ARM_PSCI_FW
+ ---help---
+ The STPMIC1 PMIC provides 4 BUCKs, 6 LDOs, 1 VREF and 2 power switches.
+ It is accessed via an I2C interface. The device is used with STM32MP1
+ SoCs. This driver implements register read/write operations.
+
+config SPL_PMIC_PALMAS
+ bool "Enable driver for Texas Instruments PALMAS PMIC"
+ depends on DM_PMIC
+ help
+ The PALMAS is a PMIC containing several LDOs, SMPS.
+ This driver binds the pmic children in SPL.
+
+config SPL_PMIC_LP873X
+ bool "Enable driver for Texas Instruments LP873X PMIC"
+ depends on DM_PMIC
+ help
+ The LP873X is a PMIC containing couple of LDOs and couple of SMPS.
+ This driver binds the pmic children in SPL.
+
+config SPL_PMIC_LP87565
+ bool "Enable driver for Texas Instruments LP87565 PMIC"
+ depends on DM_PMIC
+ help
+ The LP87565 is a PMIC containing a bunch of SMPS.
+ This driver binds the pmic children in SPL.
+
+config PMIC_TPS65941
+ bool "Enable driver for Texas Instruments TPS65941 PMIC"
+ depends on DM_PMIC
+ help
+ The TPS65941 is a PMIC containing a bunch of SMPS & LDOs.
+ This driver binds the pmic children.
diff --git a/roms/u-boot/drivers/power/pmic/Makefile b/roms/u-boot/drivers/power/pmic/Makefile
new file mode 100644
index 000000000..89099fde5
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/Makefile
@@ -0,0 +1,43 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2012 Samsung Electronics
+# Lukasz Majewski <l.majewski@samsung.com>
+
+obj-$(CONFIG_DM_PMIC) += pmic-uclass.o
+obj-$(CONFIG_DM_PMIC_FAN53555) += fan53555.o
+obj-$(CONFIG_$(SPL_)DM_PMIC_DA9063) += da9063.o
+obj-$(CONFIG_DM_PMIC_MAX77686) += max77686.o
+obj-$(CONFIG_DM_PMIC_MAX8998) += max8998.o
+obj-$(CONFIG_DM_PMIC_MC34708) += mc34708.o
+obj-$(CONFIG_$(SPL_)DM_PMIC_BD71837) += bd71837.o
+obj-$(CONFIG_$(SPL_)DM_PMIC_MP5416) += mp5416.o
+obj-$(CONFIG_$(SPL_)DM_PMIC_PFUZE100) += pfuze100.o
+obj-$(CONFIG_$(SPL_)DM_PMIC_PCA9450) += pca9450.o
+obj-$(CONFIG_PMIC_S2MPS11) += s2mps11.o
+obj-$(CONFIG_DM_PMIC_SANDBOX) += sandbox.o i2c_pmic_emul.o
+obj-$(CONFIG_PMIC_ACT8846) += act8846.o
+obj-$(CONFIG_PMIC_AS3722) += as3722.o as3722_gpio.o
+obj-$(CONFIG_PMIC_MAX8997) += max8997.o
+obj-$(CONFIG_PMIC_PM8916) += pm8916.o
+obj-$(CONFIG_PMIC_RK8XX) += rk8xx.o
+obj-$(CONFIG_PMIC_RN5T567) += rn5t567.o
+obj-$(CONFIG_PMIC_TPS65090) += tps65090.o
+obj-$(CONFIG_PMIC_S5M8767) += s5m8767.o
+obj-$(CONFIG_DM_PMIC_TPS65910) += pmic_tps65910_dm.o
+obj-$(CONFIG_$(SPL_)PMIC_PALMAS) += palmas.o
+obj-$(CONFIG_$(SPL_)PMIC_LP873X) += lp873x.o
+obj-$(CONFIG_$(SPL_)PMIC_LP87565) += lp87565.o
+obj-$(CONFIG_PMIC_STPMIC1) += stpmic1.o
+
+obj-$(CONFIG_POWER_LTC3676) += pmic_ltc3676.o
+obj-$(CONFIG_POWER_MUIC_MAX8997) += muic_max8997.o
+obj-$(CONFIG_POWER_PCA9450) += pmic_pca9450.o
+obj-$(CONFIG_POWER_PFUZE100) += pmic_pfuze100.o
+obj-$(CONFIG_POWER_PFUZE3000) += pmic_pfuze3000.o
+obj-$(CONFIG_POWER_TPS65217) += pmic_tps65217.o
+obj-$(CONFIG_POWER_TPS65218) += pmic_tps62362.o
+obj-$(CONFIG_POWER_TPS65218) += pmic_tps65218.o
+obj-$(CONFIG_POWER_TPS65910) += pmic_tps65910.o
+obj-$(CONFIG_POWER_HI6553) += pmic_hi6553.o
+obj-$(CONFIG_POWER_MC34VR500) += pmic_mc34vr500.o
+obj-$(CONFIG_PMIC_TPS65941) += tps65941.o
diff --git a/roms/u-boot/drivers/power/pmic/act8846.c b/roms/u-boot/drivers/power/pmic/act8846.c
new file mode 100644
index 000000000..8f0f5a6d9
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/act8846.c
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <log.h>
+#include <linux/libfdt.h>
+#include <power/act8846_pmic.h>
+#include <power/pmic.h>
+
+static const struct pmic_child_info pmic_children_info[] = {
+ { .prefix = "REG", .driver = "act8846_reg"},
+ { },
+};
+
+static int act8846_reg_count(struct udevice *dev)
+{
+ return ACT8846_NUM_OF_REGS;
+}
+
+static int act8846_write(struct udevice *dev, uint reg, const uint8_t *buff,
+ int len)
+{
+ if (dm_i2c_write(dev, reg, buff, len)) {
+ debug("write error to device: %p register: %#x!\n", dev, reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int act8846_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+ if (dm_i2c_read(dev, reg, buff, len)) {
+ debug("read error from device: %p register: %#x!\n", dev, reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int act8846_bind(struct udevice *dev)
+{
+ ofnode regulators_node;
+ int children;
+
+ regulators_node = dev_read_subnode(dev, "regulators");
+ if (!ofnode_valid(regulators_node)) {
+ debug("%s: %s regulators subnode not found!\n", __func__,
+ dev->name);
+ return -ENXIO;
+ }
+
+ debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
+
+ children = pmic_bind_children(dev, regulators_node, pmic_children_info);
+ if (!children)
+ debug("%s: %s - no child found\n", __func__, dev->name);
+
+ /* Always return success for this device */
+ return 0;
+}
+
+static struct dm_pmic_ops act8846_ops = {
+ .reg_count = act8846_reg_count,
+ .read = act8846_read,
+ .write = act8846_write,
+};
+
+static const struct udevice_id act8846_ids[] = {
+ { .compatible = "active-semi,act8846" },
+ { }
+};
+
+U_BOOT_DRIVER(pmic_act8846) = {
+ .name = "act8846 pmic",
+ .id = UCLASS_PMIC,
+ .of_match = act8846_ids,
+ .bind = act8846_bind,
+ .ops = &act8846_ops,
+};
diff --git a/roms/u-boot/drivers/power/pmic/as3722.c b/roms/u-boot/drivers/power/pmic/as3722.c
new file mode 100644
index 000000000..3aa3cce94
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/as3722.c
@@ -0,0 +1,178 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2014 NVIDIA Corporation
+ */
+
+#define pr_fmt(fmt) "as3722: " fmt
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <i2c.h>
+#include <log.h>
+#include <dm/lists.h>
+#include <power/as3722.h>
+#include <power/pmic.h>
+
+#define AS3722_NUM_OF_REGS 0x92
+
+static int as3722_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+ int ret;
+
+ ret = dm_i2c_read(dev, reg, buff, len);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int as3722_write(struct udevice *dev, uint reg, const uint8_t *buff,
+ int len)
+{
+ int ret;
+
+ ret = dm_i2c_write(dev, reg, buff, len);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int as3722_read_id(struct udevice *dev, uint *idp, uint *revisionp)
+{
+ int ret;
+
+ ret = pmic_reg_read(dev, AS3722_ASIC_ID1);
+ if (ret < 0) {
+ pr_err("failed to read ID1 register: %d\n", ret);
+ return ret;
+ }
+ *idp = ret;
+
+ ret = pmic_reg_read(dev, AS3722_ASIC_ID2);
+ if (ret < 0) {
+ pr_err("failed to read ID2 register: %d\n", ret);
+ return ret;
+ }
+ *revisionp = ret;
+
+ return 0;
+}
+
+/* TODO(treding@nvidia.com): Add proper regulator support to avoid this */
+int as3722_sd_set_voltage(struct udevice *dev, unsigned int sd, u8 value)
+{
+ int ret;
+
+ if (sd > 6)
+ return -EINVAL;
+
+ ret = pmic_reg_write(dev, AS3722_SD_VOLTAGE(sd), value);
+ if (ret < 0) {
+ pr_err("failed to write SD%u voltage register: %d\n", sd, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+int as3722_ldo_set_voltage(struct udevice *dev, unsigned int ldo, u8 value)
+{
+ int ret;
+
+ if (ldo > 11)
+ return -EINVAL;
+
+ ret = pmic_reg_write(dev, AS3722_LDO_VOLTAGE(ldo), value);
+ if (ret < 0) {
+ pr_err("failed to write LDO%u voltage register: %d\n", ldo,
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int as3722_probe(struct udevice *dev)
+{
+ uint id, revision;
+ int ret;
+
+ ret = as3722_read_id(dev, &id, &revision);
+ if (ret < 0) {
+ pr_err("failed to read ID: %d\n", ret);
+ return ret;
+ }
+
+ if (id != AS3722_DEVICE_ID) {
+ pr_err("unknown device\n");
+ return -ENOENT;
+ }
+
+ debug("AS3722 revision %#x found on I2C bus %s\n", revision, dev->name);
+
+ return 0;
+}
+
+#if CONFIG_IS_ENABLED(PMIC_CHILDREN)
+static const struct pmic_child_info pmic_children_info[] = {
+ { .prefix = "sd", .driver = "as3722_stepdown"},
+ { .prefix = "ldo", .driver = "as3722_ldo"},
+ { },
+};
+
+static int as3722_bind(struct udevice *dev)
+{
+ struct udevice *gpio_dev;
+ ofnode regulators_node;
+ int children;
+ int ret;
+
+ regulators_node = dev_read_subnode(dev, "regulators");
+ if (!ofnode_valid(regulators_node)) {
+ debug("%s: %s regulators subnode not found\n", __func__,
+ dev->name);
+ return -ENXIO;
+ }
+
+ children = pmic_bind_children(dev, regulators_node, pmic_children_info);
+ if (!children)
+ debug("%s: %s - no child found\n", __func__, dev->name);
+ ret = device_bind_driver(dev, "gpio_as3722", "gpio_as3722", &gpio_dev);
+ if (ret) {
+ debug("%s: Cannot bind GPIOs (ret=%d)\n", __func__, ret);
+ return ret;
+ }
+
+ return 0;
+}
+#endif
+
+static int as3722_reg_count(struct udevice *dev)
+{
+ return AS3722_NUM_OF_REGS;
+}
+
+static struct dm_pmic_ops as3722_ops = {
+ .reg_count = as3722_reg_count,
+ .read = as3722_read,
+ .write = as3722_write,
+};
+
+static const struct udevice_id as3722_ids[] = {
+ { .compatible = "ams,as3722" },
+ { }
+};
+
+U_BOOT_DRIVER(pmic_as3722) = {
+ .name = "as3722_pmic",
+ .id = UCLASS_PMIC,
+ .of_match = as3722_ids,
+#if CONFIG_IS_ENABLED(PMIC_CHILDREN)
+ .bind = as3722_bind,
+#endif
+ .probe = as3722_probe,
+ .ops = &as3722_ops,
+};
diff --git a/roms/u-boot/drivers/power/pmic/as3722_gpio.c b/roms/u-boot/drivers/power/pmic/as3722_gpio.c
new file mode 100644
index 000000000..96943bc1a
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/as3722_gpio.c
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2014 NVIDIA Corporation
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/gpio.h>
+#include <power/as3722.h>
+#include <power/pmic.h>
+
+#define NUM_GPIOS 8
+
+int as3722_gpio_configure(struct udevice *pmic, unsigned int gpio,
+ unsigned long flags)
+{
+ u8 value = 0;
+ int err;
+
+ if (flags & AS3722_GPIO_OUTPUT_VDDH)
+ value |= AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH;
+
+ if (flags & AS3722_GPIO_INVERT)
+ value |= AS3722_GPIO_CONTROL_INVERT;
+
+ err = pmic_reg_write(pmic, AS3722_GPIO_CONTROL(gpio), value);
+ if (err) {
+ pr_err("failed to configure GPIO#%u: %d\n", gpio, err);
+ return err;
+ }
+
+ return 0;
+}
+
+static int as3722_gpio_set_value(struct udevice *dev, unsigned int gpio,
+ int level)
+{
+ struct udevice *pmic = dev_get_parent(dev);
+ const char *l;
+ u8 value;
+ int err;
+
+ if (gpio >= NUM_GPIOS)
+ return -EINVAL;
+
+ err = pmic_reg_read(pmic, AS3722_GPIO_SIGNAL_OUT);
+ if (err < 0) {
+ pr_err("failed to read GPIO signal out register: %d\n", err);
+ return err;
+ }
+ value = err;
+
+ if (level == 0) {
+ value &= ~(1 << gpio);
+ l = "low";
+ } else {
+ value |= 1 << gpio;
+ l = "high";
+ }
+
+ err = pmic_reg_write(pmic, AS3722_GPIO_SIGNAL_OUT, value);
+ if (err) {
+ pr_err("failed to set GPIO#%u %s: %d\n", gpio, l, err);
+ return err;
+ }
+
+ return 0;
+}
+
+int as3722_gpio_direction_output(struct udevice *dev, unsigned int gpio,
+ int value)
+{
+ struct udevice *pmic = dev_get_parent(dev);
+ int err;
+
+ if (gpio > 7)
+ return -EINVAL;
+
+ if (value == 0)
+ value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL;
+ else
+ value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH;
+
+ err = pmic_reg_write(pmic, AS3722_GPIO_CONTROL(gpio), value);
+ if (err) {
+ pr_err("failed to configure GPIO#%u as output: %d\n", gpio,
+ err);
+ return err;
+ }
+
+ err = as3722_gpio_set_value(pmic, gpio, value);
+ if (err < 0) {
+ pr_err("failed to set GPIO#%u high: %d\n", gpio, err);
+ return err;
+ }
+
+ return 0;
+}
+
+static int as3722_gpio_probe(struct udevice *dev)
+{
+ struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+
+ uc_priv->gpio_count = NUM_GPIOS;
+ uc_priv->bank_name = "as3722_";
+
+ return 0;
+}
+
+static const struct dm_gpio_ops gpio_as3722_ops = {
+ .direction_output = as3722_gpio_direction_output,
+ .set_value = as3722_gpio_set_value,
+};
+
+U_BOOT_DRIVER(gpio_as3722) = {
+ .name = "gpio_as3722",
+ .id = UCLASS_GPIO,
+ .ops = &gpio_as3722_ops,
+ .probe = as3722_gpio_probe,
+};
diff --git a/roms/u-boot/drivers/power/pmic/bd71837.c b/roms/u-boot/drivers/power/pmic/bd71837.c
new file mode 100644
index 000000000..cb9238972
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/bd71837.c
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 NXP
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <dm.h>
+#include <i2c.h>
+#include <log.h>
+#include <asm/global_data.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/bd71837.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const struct pmic_child_info pmic_children_info[] = {
+ /* buck */
+ { .prefix = "b", .driver = BD718XX_REGULATOR_DRIVER},
+ /* ldo */
+ { .prefix = "l", .driver = BD718XX_REGULATOR_DRIVER},
+ { },
+};
+
+static int bd71837_reg_count(struct udevice *dev)
+{
+ return BD718XX_MAX_REGISTER - 1;
+}
+
+static int bd71837_write(struct udevice *dev, uint reg, const uint8_t *buff,
+ int len)
+{
+ if (dm_i2c_write(dev, reg, buff, len)) {
+ pr_err("write error to device: %p register: %#x!", dev, reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int bd71837_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+ if (dm_i2c_read(dev, reg, buff, len)) {
+ pr_err("read error from device: %p register: %#x!", dev, reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int bd71837_bind(struct udevice *dev)
+{
+ int children;
+ ofnode regulators_node;
+
+ regulators_node = dev_read_subnode(dev, "regulators");
+ if (!ofnode_valid(regulators_node)) {
+ debug("%s: %s regulators subnode not found!\n", __func__,
+ dev->name);
+ return -ENXIO;
+ }
+
+ debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
+
+ children = pmic_bind_children(dev, regulators_node, pmic_children_info);
+ if (!children)
+ debug("%s: %s - no child found\n", __func__, dev->name);
+
+ /* Always return success for this device */
+ return 0;
+}
+
+static int bd718x7_probe(struct udevice *dev)
+{
+ int ret;
+ uint8_t mask = BD718XX_REGLOCK_PWRSEQ | BD718XX_REGLOCK_VREG;
+
+ /* Unlock the PMIC regulator control before probing the children */
+ ret = pmic_clrsetbits(dev, BD718XX_REGLOCK, mask, 0);
+ if (ret) {
+ debug("%s: %s Failed to unlock regulator control\n", __func__,
+ dev->name);
+ return ret;
+ }
+ debug("%s: '%s' - BD718x7 PMIC registers unlocked\n", __func__,
+ dev->name);
+
+ return 0;
+}
+
+static struct dm_pmic_ops bd71837_ops = {
+ .reg_count = bd71837_reg_count,
+ .read = bd71837_read,
+ .write = bd71837_write,
+};
+
+static const struct udevice_id bd71837_ids[] = {
+ { .compatible = "rohm,bd71837", .data = ROHM_CHIP_TYPE_BD71837, },
+ { .compatible = "rohm,bd71847", .data = ROHM_CHIP_TYPE_BD71847, },
+ { }
+};
+
+U_BOOT_DRIVER(pmic_bd71837) = {
+ .name = "bd71837 pmic",
+ .id = UCLASS_PMIC,
+ .of_match = bd71837_ids,
+ .bind = bd71837_bind,
+ .probe = bd718x7_probe,
+ .ops = &bd71837_ops,
+};
diff --git a/roms/u-boot/drivers/power/pmic/da9063.c b/roms/u-boot/drivers/power/pmic/da9063.c
new file mode 100644
index 000000000..25101d18f
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/da9063.c
@@ -0,0 +1,131 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Flowbird
+ * Martin Fuzzey <martin.fuzzey@flowbird.group>
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <errno.h>
+#include <dm.h>
+#include <i2c.h>
+#include <log.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/da9063_pmic.h>
+
+static const struct pmic_child_info pmic_children_info[] = {
+ { .prefix = "ldo", .driver = DA9063_LDO_DRIVER },
+ { .prefix = "b", .driver = DA9063_BUCK_DRIVER },
+ { },
+};
+
+/*
+ * The register map is non contiguous and attempts to read in the holes fail.
+ * But "pmic dump" tries to dump the full register map.
+ * So define the holes here so we can fix that.
+ */
+struct da9063_reg_hole {
+ u16 first;
+ u16 last;
+};
+
+static const struct da9063_reg_hole da9063_reg_holes[] = {
+ DA9063_REG_HOLE_1,
+ DA9063_REG_HOLE_2,
+ DA9063_REG_HOLE_3,
+ /* These aren't readable. I can't see why from the datasheet but
+ * attempts to read fail and the kernel marks them unreadable too,
+ */
+ {DA9063_REG_OTP_COUNT, DA9063_REG_OTP_DATA},
+};
+
+static int da9063_reg_count(struct udevice *dev)
+{
+ return DA9063_NUM_OF_REGS;
+}
+
+static bool da9063_reg_valid(uint reg)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(da9063_reg_holes); i++) {
+ const struct da9063_reg_hole *hole = &da9063_reg_holes[i];
+
+ if (reg >= hole->first && reg <= hole->last)
+ return false;
+ }
+
+ return true;
+}
+
+static int da9063_write(struct udevice *dev, uint reg, const uint8_t *buff,
+ int len)
+{
+ if (dm_i2c_write(dev, reg, buff, len)) {
+ pr_err("write error to device: %p register: %#x!", dev, reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int da9063_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+ if (!da9063_reg_valid(reg))
+ return -ENODATA;
+
+ if (dm_i2c_read(dev, reg, buff, len)) {
+ pr_err("read error from device: %p register: %#x!", dev, reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int da9063_bind(struct udevice *dev)
+{
+ ofnode regulators_node;
+ int children;
+
+ regulators_node = dev_read_subnode(dev, "regulators");
+ if (!ofnode_valid(regulators_node)) {
+ debug("%s: %s regulators subnode not found!", __func__,
+ dev->name);
+ return -ENXIO;
+ }
+
+ debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
+
+ children = pmic_bind_children(dev, regulators_node, pmic_children_info);
+ if (!children)
+ debug("%s: %s - no child found\n", __func__, dev->name);
+
+ /* Always return success for this device */
+ return 0;
+}
+
+static int da9063_probe(struct udevice *dev)
+{
+ return i2c_set_chip_addr_offset_mask(dev, 0x1);
+}
+
+static struct dm_pmic_ops da9063_ops = {
+ .reg_count = da9063_reg_count,
+ .read = da9063_read,
+ .write = da9063_write,
+};
+
+static const struct udevice_id da9063_ids[] = {
+ { .compatible = "dlg,da9063" },
+ { }
+};
+
+U_BOOT_DRIVER(pmic_da9063) = {
+ .name = "da9063_pmic",
+ .id = UCLASS_PMIC,
+ .of_match = da9063_ids,
+ .bind = da9063_bind,
+ .probe = da9063_probe,
+ .ops = &da9063_ops,
+};
diff --git a/roms/u-boot/drivers/power/pmic/fan53555.c b/roms/u-boot/drivers/power/pmic/fan53555.c
new file mode 100644
index 000000000..4d1e686d2
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/fan53555.c
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) 2018 Theobroma Systems Design und Consulting GmbH
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <dm/device-internal.h>
+#include <dm/device_compat.h>
+#include <dm/lists.h>
+#include <i2c.h>
+#include <power/fan53555.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+
+static int pmic_fan53555_reg_count(struct udevice *dev)
+{
+ return 1;
+};
+
+static int pmic_fan53555_read(struct udevice *dev, uint reg,
+ u8 *buff, int len)
+{
+ if (dm_i2c_read(dev, reg, buff, len)) {
+ pr_err("%s: read error for register: %#x!", dev->name, reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int pmic_fan53555_write(struct udevice *dev, uint reg,
+ const u8 *buff, int len)
+{
+ if (dm_i2c_write(dev, reg, buff, len)) {
+ pr_err("%s: write error for register: %#x!", dev->name, reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int pmic_fan53555_bind(struct udevice *dev)
+{
+ /*
+ * The FAN53555 has only a single regulator and therefore doesn't
+ * have a subnode. So we have to rebind a child device (the one
+ * regulator) here.
+ */
+
+ const char *regulator_driver_name = "fan53555_regulator";
+ struct udevice *child;
+ struct driver *drv;
+
+ debug("%s\n", __func__);
+
+ drv = lists_driver_lookup_name(regulator_driver_name);
+ if (!drv) {
+ dev_err(dev, "no driver '%s'\n", regulator_driver_name);
+ return -ENOENT;
+ }
+
+ return device_bind_with_driver_data(dev, drv, "SW", dev->driver_data,
+ dev_ofnode(dev), &child);
+};
+
+static struct dm_pmic_ops pmic_fan53555_ops = {
+ .reg_count = pmic_fan53555_reg_count,
+ .read = pmic_fan53555_read,
+ .write = pmic_fan53555_write,
+};
+
+static const struct udevice_id pmic_fan53555_match[] = {
+ { .compatible = "fcs,fan53555", .data = FAN53555_VENDOR_FAIRCHILD, },
+ { .compatible = "silergy,syr827", .data = FAN53555_VENDOR_SILERGY, },
+ { .compatible = "silergy,syr828", .data = FAN53555_VENDOR_SILERGY, },
+ { },
+};
+
+U_BOOT_DRIVER(pmic_fan53555) = {
+ .name = "pmic_fan53555",
+ .id = UCLASS_PMIC,
+ .of_match = pmic_fan53555_match,
+ .bind = pmic_fan53555_bind,
+ .ops = &pmic_fan53555_ops,
+};
diff --git a/roms/u-boot/drivers/power/pmic/i2c_pmic_emul.c b/roms/u-boot/drivers/power/pmic/i2c_pmic_emul.c
new file mode 100644
index 000000000..abe3a1051
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/i2c_pmic_emul.c
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015 Samsung Electronics
+ * Przemyslaw Marczak <p.marczak@samsung.com>
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <dm.h>
+#include <i2c.h>
+#include <log.h>
+#include <malloc.h>
+#include <power/pmic.h>
+#include <power/sandbox_pmic.h>
+
+/**
+ * struct sandbox_i2c_pmic_plat_data - platform data for the PMIC
+ *
+ * @rw_reg: PMICs register of the chip I/O transaction
+ * @reg: PMICs registers array
+ */
+struct sandbox_i2c_pmic_plat_data {
+ u8 rw_reg, rw_idx;
+ u8 reg_count;
+ u8 trans_len;
+ u8 buf_size;
+ u8 *reg;
+};
+
+static int sandbox_i2c_pmic_read_data(struct udevice *emul, uchar chip,
+ uchar *buffer, int len)
+{
+ struct sandbox_i2c_pmic_plat_data *plat = dev_get_plat(emul);
+
+ if (plat->rw_idx + len > plat->buf_size) {
+ pr_err("Request exceeds PMIC register range! Max register: %#x",
+ plat->reg_count);
+ return -EFAULT;
+ }
+
+ debug("Read PMIC: %#x at register: %#x idx: %#x count: %d\n",
+ (unsigned int)chip & 0xff, plat->rw_reg, plat->rw_idx, len);
+
+ memcpy(buffer, plat->reg + plat->rw_idx, len);
+
+ return 0;
+}
+
+static int sandbox_i2c_pmic_write_data(struct udevice *emul, uchar chip,
+ uchar *buffer, int len,
+ bool next_is_read)
+{
+ struct sandbox_i2c_pmic_plat_data *plat = dev_get_plat(emul);
+
+ /* Probe only */
+ if (!len)
+ return 0;
+
+ /* Set PMIC register for I/O */
+ plat->rw_reg = *buffer;
+ plat->rw_idx = plat->rw_reg * plat->trans_len;
+
+ debug("Write PMIC: %#x at register: %#x idx: %#x count: %d\n",
+ (unsigned int)chip & 0xff, plat->rw_reg, plat->rw_idx, len);
+
+ /* For read operation, set (write) only chip reg */
+ if (next_is_read)
+ return 0;
+
+ buffer++;
+ len--;
+
+ if (plat->rw_idx + len > plat->buf_size) {
+ pr_err("Request exceeds PMIC register range! Max register: %#x",
+ plat->reg_count);
+ }
+
+ memcpy(plat->reg + plat->rw_idx, buffer, len);
+
+ return 0;
+}
+
+static int sandbox_i2c_pmic_xfer(struct udevice *emul, struct i2c_msg *msg,
+ int nmsgs)
+{
+ int ret = 0;
+
+ for (; nmsgs > 0; nmsgs--, msg++) {
+ bool next_is_read = nmsgs > 1 && (msg[1].flags & I2C_M_RD);
+ if (msg->flags & I2C_M_RD) {
+ ret = sandbox_i2c_pmic_read_data(emul, msg->addr,
+ msg->buf, msg->len);
+ } else {
+ ret = sandbox_i2c_pmic_write_data(emul, msg->addr,
+ msg->buf, msg->len,
+ next_is_read);
+ }
+
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
+static int sandbox_i2c_pmic_of_to_plat(struct udevice *emul)
+{
+ struct sandbox_i2c_pmic_plat_data *plat = dev_get_plat(emul);
+ struct udevice *pmic_dev = i2c_emul_get_device(emul);
+
+ debug("%s:%d Setting PMIC default registers\n", __func__, __LINE__);
+ plat->reg_count = pmic_reg_count(pmic_dev);
+
+ return 0;
+}
+
+static int sandbox_i2c_pmic_probe(struct udevice *emul)
+{
+ struct sandbox_i2c_pmic_plat_data *plat = dev_get_plat(emul);
+ struct udevice *pmic_dev = i2c_emul_get_device(emul);
+ struct uc_pmic_priv *upriv = dev_get_uclass_priv(pmic_dev);
+ const u8 *reg_defaults;
+
+ plat->trans_len = upriv->trans_len;
+ plat->buf_size = plat->reg_count * plat->trans_len;
+
+ plat->reg = calloc(1, plat->buf_size);
+ if (!plat->reg) {
+ debug("Canot allocate memory (%d B) for PMIC I2C emulation!\n",
+ plat->buf_size);
+ return -ENOMEM;
+ }
+
+ reg_defaults = dev_read_u8_array_ptr(emul, "reg-defaults",
+ plat->buf_size);
+
+ if (!reg_defaults) {
+ pr_err("Property \"reg-defaults\" not found for device: %s!",
+ emul->name);
+ free(plat->reg);
+ return -EINVAL;
+ }
+
+ memcpy(plat->reg, reg_defaults, plat->buf_size);
+
+ return 0;
+}
+
+struct dm_i2c_ops sandbox_i2c_pmic_emul_ops = {
+ .xfer = sandbox_i2c_pmic_xfer,
+};
+
+static const struct udevice_id sandbox_i2c_pmic_ids[] = {
+ { .compatible = "sandbox,i2c-pmic" },
+ { }
+};
+
+U_BOOT_DRIVER(sandbox_i2c_pmic_emul) = {
+ .name = "sandbox_i2c_pmic_emul",
+ .id = UCLASS_I2C_EMUL,
+ .of_match = sandbox_i2c_pmic_ids,
+ .of_to_plat = sandbox_i2c_pmic_of_to_plat,
+ .probe = sandbox_i2c_pmic_probe,
+ .plat_auto = sizeof(struct sandbox_i2c_pmic_plat_data),
+ .ops = &sandbox_i2c_pmic_emul_ops,
+};
diff --git a/roms/u-boot/drivers/power/pmic/lp873x.c b/roms/u-boot/drivers/power/pmic/lp873x.c
new file mode 100644
index 000000000..2b1260ec6
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/lp873x.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2016 Texas Instruments Incorporated, <www.ti.com>
+ * Keerthy <j-keerthy@ti.com>
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <errno.h>
+#include <dm.h>
+#include <i2c.h>
+#include <log.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/lp873x.h>
+#include <dm/device.h>
+
+static const struct pmic_child_info pmic_children_info[] = {
+ { .prefix = "ldo", .driver = LP873X_LDO_DRIVER },
+ { .prefix = "buck", .driver = LP873X_BUCK_DRIVER },
+ { },
+};
+
+static int lp873x_write(struct udevice *dev, uint reg, const uint8_t *buff,
+ int len)
+{
+ if (dm_i2c_write(dev, reg, buff, len)) {
+ pr_err("write error to device: %p register: %#x!\n", dev, reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int lp873x_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+ if (dm_i2c_read(dev, reg, buff, len)) {
+ pr_err("read error from device: %p register: %#x!\n", dev, reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int lp873x_bind(struct udevice *dev)
+{
+ ofnode regulators_node;
+ int children;
+
+ regulators_node = dev_read_subnode(dev, "regulators");
+ if (!ofnode_valid(regulators_node)) {
+ debug("%s: %s regulators subnode not found!\n", __func__,
+ dev->name);
+ return -ENXIO;
+ }
+
+ children = pmic_bind_children(dev, regulators_node, pmic_children_info);
+ if (!children)
+ printf("%s: %s - no child found\n", __func__, dev->name);
+
+ /* Always return success for this device */
+ return 0;
+}
+
+static struct dm_pmic_ops lp873x_ops = {
+ .read = lp873x_read,
+ .write = lp873x_write,
+};
+
+static const struct udevice_id lp873x_ids[] = {
+ { .compatible = "ti,lp8732", .data = LP8732 },
+ { .compatible = "ti,lp8733" , .data = LP8733 },
+ { }
+};
+
+U_BOOT_DRIVER(pmic_lp873x) = {
+ .name = "lp873x_pmic",
+ .id = UCLASS_PMIC,
+ .of_match = lp873x_ids,
+ .bind = lp873x_bind,
+ .ops = &lp873x_ops,
+};
diff --git a/roms/u-boot/drivers/power/pmic/lp87565.c b/roms/u-boot/drivers/power/pmic/lp87565.c
new file mode 100644
index 000000000..f4a4bd03d
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/lp87565.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2017 Texas Instruments Incorporated, <www.ti.com>
+ * Keerthy <j-keerthy@ti.com>
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <errno.h>
+#include <dm.h>
+#include <i2c.h>
+#include <log.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/lp87565.h>
+#include <dm/device.h>
+
+static const struct pmic_child_info pmic_children_info[] = {
+ { .prefix = "buck", .driver = LP87565_BUCK_DRIVER },
+ { },
+};
+
+static int lp87565_write(struct udevice *dev, uint reg, const uint8_t *buff,
+ int len)
+{
+ int ret;
+
+ ret = dm_i2c_write(dev, reg, buff, len);
+ if (ret)
+ pr_err("write error to device: %p register: %#x!\n", dev, reg);
+
+ return ret;
+}
+
+static int lp87565_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+ int ret;
+
+ ret = dm_i2c_read(dev, reg, buff, len);
+ if (ret)
+ pr_err("read error from device: %p register: %#x!\n", dev, reg);
+
+ return ret;
+}
+
+static int lp87565_bind(struct udevice *dev)
+{
+ ofnode regulators_node;
+ int children;
+
+ regulators_node = dev_read_subnode(dev, "regulators");
+ if (!ofnode_valid(regulators_node)) {
+ debug("%s: %s regulators subnode not found!\n", __func__,
+ dev->name);
+ return -ENXIO;
+ }
+
+ debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
+
+ children = pmic_bind_children(dev, regulators_node, pmic_children_info);
+ if (!children)
+ printf("%s: %s - no child found\n", __func__, dev->name);
+
+ /* Always return success for this device */
+ return 0;
+}
+
+static struct dm_pmic_ops lp87565_ops = {
+ .read = lp87565_read,
+ .write = lp87565_write,
+};
+
+static const struct udevice_id lp87565_ids[] = {
+ { .compatible = "ti,lp87565", .data = LP87565 },
+ { .compatible = "ti,lp87565-q1", .data = LP87565_Q1 },
+ { }
+};
+
+U_BOOT_DRIVER(pmic_lp87565) = {
+ .name = "lp87565_pmic",
+ .id = UCLASS_PMIC,
+ .of_match = lp87565_ids,
+ .bind = lp87565_bind,
+ .ops = &lp87565_ops,
+};
diff --git a/roms/u-boot/drivers/power/pmic/max77686.c b/roms/u-boot/drivers/power/pmic/max77686.c
new file mode 100644
index 000000000..9f02c0b6f
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/max77686.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2014-2015 Samsung Electronics
+ * Przemyslaw Marczak <p.marczak@samsung.com>
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <errno.h>
+#include <dm.h>
+#include <i2c.h>
+#include <log.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/max77686_pmic.h>
+
+static const struct pmic_child_info pmic_children_info[] = {
+ { .prefix = "LDO", .driver = MAX77686_LDO_DRIVER },
+ { .prefix = "BUCK", .driver = MAX77686_BUCK_DRIVER },
+ { },
+};
+
+static int max77686_reg_count(struct udevice *dev)
+{
+ return MAX77686_NUM_OF_REGS;
+}
+
+static int max77686_write(struct udevice *dev, uint reg, const uint8_t *buff,
+ int len)
+{
+ if (dm_i2c_write(dev, reg, buff, len)) {
+ pr_err("write error to device: %p register: %#x!\n", dev, reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int max77686_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+ if (dm_i2c_read(dev, reg, buff, len)) {
+ pr_err("read error from device: %p register: %#x!\n", dev, reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int max77686_bind(struct udevice *dev)
+{
+ ofnode regulators_node;
+ int children;
+
+ regulators_node = dev_read_subnode(dev, "voltage-regulators");
+ if (!ofnode_valid(regulators_node)) {
+ debug("%s: %s regulators subnode not found!\n", __func__,
+ dev->name);
+ return -ENXIO;
+ }
+
+ debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
+
+ children = pmic_bind_children(dev, regulators_node, pmic_children_info);
+ if (!children)
+ debug("%s: %s - no child found\n", __func__, dev->name);
+
+ /* Always return success for this device */
+ return 0;
+}
+
+static struct dm_pmic_ops max77686_ops = {
+ .reg_count = max77686_reg_count,
+ .read = max77686_read,
+ .write = max77686_write,
+};
+
+static const struct udevice_id max77686_ids[] = {
+ { .compatible = "maxim,max77686" },
+ { }
+};
+
+U_BOOT_DRIVER(pmic_max77686) = {
+ .name = "max77686_pmic",
+ .id = UCLASS_PMIC,
+ .of_match = max77686_ids,
+ .bind = max77686_bind,
+ .ops = &max77686_ops,
+};
diff --git a/roms/u-boot/drivers/power/pmic/max8997.c b/roms/u-boot/drivers/power/pmic/max8997.c
new file mode 100644
index 000000000..dbae155fb
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/max8997.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016 Samsung Electronics
+ * Jaehoon Chung <jh80.chung@samsung.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <i2c.h>
+#include <power/pmic.h>
+#include <power/max8997_pmic.h>
+#include <errno.h>
+
+static int max8997_reg_count(struct udevice *dev)
+{
+ return PMIC_NUM_OF_REGS;
+}
+
+static int max8997_write(struct udevice *dev, uint reg, const uint8_t *buff,
+ int len)
+{
+ int ret;
+
+ ret = dm_i2c_write(dev, reg, buff, len);
+ if (ret)
+ pr_err("write error to device: %p register: %#x!\n", dev, reg);
+
+ return ret;
+}
+
+static int max8997_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+ int ret;
+
+ ret = dm_i2c_read(dev, reg, buff, len);
+ if (ret)
+ pr_err("read error from device: %p register: %#x!\n", dev, reg);
+
+ return ret;
+}
+
+static struct dm_pmic_ops max8997_ops = {
+ .reg_count = max8997_reg_count,
+ .read = max8997_read,
+ .write = max8997_write,
+};
+
+static const struct udevice_id max8997_ids[] = {
+ { .compatible = "maxim,max8997" },
+ { },
+};
+
+U_BOOT_DRIVER(pmic_max8997) = {
+ .name = "max8997_pmic",
+ .id = UCLASS_PMIC,
+ .of_match = max8997_ids,
+ .ops = &max8997_ops,
+};
diff --git a/roms/u-boot/drivers/power/pmic/max8998.c b/roms/u-boot/drivers/power/pmic/max8998.c
new file mode 100644
index 000000000..f58d9f2d7
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/max8998.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016 Samsung Electronics
+ * Jaehoon Chung <jh80.chung@samsung.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <i2c.h>
+#include <power/pmic.h>
+#include <power/max8998_pmic.h>
+
+static int max8998_reg_count(struct udevice *dev)
+{
+ return PMIC_NUM_OF_REGS;
+}
+
+static int max8998_write(struct udevice *dev, uint reg, const uint8_t *buff,
+ int len)
+{
+ int ret;
+
+ ret = dm_i2c_write(dev, reg, buff, len);
+ if (ret)
+ pr_err("write error to device: %p register: %#x!\n", dev, reg);
+
+ return ret;
+}
+
+static int max8998_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+ int ret;
+
+ ret = dm_i2c_read(dev, reg, buff, len);
+ if (ret)
+ pr_err("read error from device: %p register: %#x!\n", dev, reg);
+
+ return ret;
+}
+
+static struct dm_pmic_ops max8998_ops = {
+ .reg_count = max8998_reg_count,
+ .read = max8998_read,
+ .write = max8998_write,
+};
+
+static const struct udevice_id max8998_ids[] = {
+ { .compatible = "maxim,max8998" },
+ { }
+};
+
+U_BOOT_DRIVER(pmic_max8998) = {
+ .name = "max8998_pmic",
+ .id = UCLASS_PMIC,
+ .of_match = max8998_ids,
+ .ops = &max8998_ops,
+};
diff --git a/roms/u-boot/drivers/power/pmic/mc34708.c b/roms/u-boot/drivers/power/pmic/mc34708.c
new file mode 100644
index 000000000..40d732224
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/mc34708.c
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018
+ * Lukasz Majewski, DENX Software Engineering, lukma@denx.de
+ *
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fsl_pmic.h>
+#include <i2c.h>
+#include <asm/global_data.h>
+#include <power/pmic.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int mc34708_reg_count(struct udevice *dev)
+{
+ return PMIC_NUM_OF_REGS;
+}
+
+static int mc34708_write(struct udevice *dev, uint reg, const u8 *buff,
+ int len)
+{
+ u8 buf[3] = { 0 };
+ int ret;
+
+ if (len != MC34708_TRANSFER_SIZE)
+ return -EINVAL;
+
+ /*
+ * The MC34708 sends data with big endian format, hence we need to
+ * perform manual byte swap.
+ */
+ buf[0] = buff[2];
+ buf[1] = buff[1];
+ buf[2] = buff[0];
+
+ ret = dm_i2c_write(dev, reg, buf, len);
+ if (ret)
+ printf("write error to device: %p register: %#x!\n", dev, reg);
+
+ return ret;
+}
+
+static int mc34708_read(struct udevice *dev, uint reg, u8 *buff, int len)
+{
+ u8 buf[3] = { 0 };
+ int ret;
+
+ if (len != MC34708_TRANSFER_SIZE)
+ return -EINVAL;
+
+ ret = dm_i2c_read(dev, reg, buf, len);
+ if (ret)
+ printf("read error from device: %p register: %#x!\n", dev, reg);
+
+ buff[0] = buf[2];
+ buff[1] = buf[1];
+ buff[2] = buf[0];
+
+ return ret;
+}
+
+static int mc34708_probe(struct udevice *dev)
+{
+ struct uc_pmic_priv *priv = dev_get_uclass_priv(dev);
+
+ priv->trans_len = MC34708_TRANSFER_SIZE;
+
+ /*
+ * Handle PMIC Errata 37: APS mode not fully functional,
+ * use explicit PWM or PFM instead
+ */
+ pmic_clrsetbits(dev, MC34708_REG_SW12_OPMODE,
+ MC34708_SW1AMODE_MASK | MC34708_SW2MODE_MASK,
+ SW_MODE_PWMPWM | (SW_MODE_PWMPWM << 14u));
+
+ pmic_clrsetbits(dev, MC34708_REG_SW345_OPMODE,
+ MC34708_SW3MODE_MASK | MC34708_SW4AMODE_MASK |
+ MC34708_SW4BMODE_MASK | MC34708_SW5MODE_MASK,
+ SW_MODE_PWMPWM | (SW_MODE_PWMPWM << 6u) |
+ (SW_MODE_PWMPWM << 12u) | (SW_MODE_PWMPWM << 18u));
+
+ return 0;
+}
+
+static struct dm_pmic_ops mc34708_ops = {
+ .reg_count = mc34708_reg_count,
+ .read = mc34708_read,
+ .write = mc34708_write,
+};
+
+static const struct udevice_id mc34708_ids[] = {
+ { .compatible = "fsl,mc34708" },
+ { }
+};
+
+U_BOOT_DRIVER(pmic_mc34708) = {
+ .name = "mc34708_pmic",
+ .id = UCLASS_PMIC,
+ .of_match = mc34708_ids,
+ .probe = mc34708_probe,
+ .ops = &mc34708_ops,
+};
diff --git a/roms/u-boot/drivers/power/pmic/mp5416.c b/roms/u-boot/drivers/power/pmic/mp5416.c
new file mode 100644
index 000000000..6180adf77
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/mp5416.c
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2020 Gateworks Corporation
+ */
+#include <common.h>
+#include <errno.h>
+#include <dm.h>
+#include <i2c.h>
+#include <log.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/mp5416.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const struct pmic_child_info pmic_children_info[] = {
+ /* buck */
+ { .prefix = "b", .driver = MP6416_REGULATOR_DRIVER },
+ /* ldo */
+ { .prefix = "l", .driver = MP6416_REGULATOR_DRIVER },
+ { },
+};
+
+static int mp5416_reg_count(struct udevice *dev)
+{
+ return MP5416_NUM_OF_REGS - 1;
+}
+
+static int mp5416_write(struct udevice *dev, uint reg, const uint8_t *buff,
+ int len)
+{
+ if (dm_i2c_write(dev, reg, buff, len)) {
+ pr_err("write error to device: %p register: %#x!", dev, reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int mp5416_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+ if (dm_i2c_read(dev, reg, buff, len)) {
+ pr_err("read error from device: %p register: %#x!", dev, reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int mp5416_bind(struct udevice *dev)
+{
+ int children;
+ ofnode regulators_node;
+
+ debug("%s %s\n", __func__, dev->name);
+ regulators_node = dev_read_subnode(dev, "regulators");
+ if (!ofnode_valid(regulators_node)) {
+ debug("%s: %s regulators subnode not found!\n", __func__,
+ dev->name);
+ return -ENXIO;
+ }
+
+ debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
+
+ children = pmic_bind_children(dev, regulators_node, pmic_children_info);
+ if (!children)
+ debug("%s: %s - no child found\n", __func__, dev->name);
+
+ /* Always return success for this device */
+ return 0;
+}
+
+static int mp5416_probe(struct udevice *dev)
+{
+ debug("%s %s\n", __func__, dev->name);
+
+ return 0;
+}
+
+static struct dm_pmic_ops mp5416_ops = {
+ .reg_count = mp5416_reg_count,
+ .read = mp5416_read,
+ .write = mp5416_write,
+};
+
+static const struct udevice_id mp5416_ids[] = {
+ { .compatible = "mps,mp5416", },
+ { }
+};
+
+U_BOOT_DRIVER(pmic_mp5416) = {
+ .name = "mp5416 pmic",
+ .id = UCLASS_PMIC,
+ .of_match = mp5416_ids,
+ .bind = mp5416_bind,
+ .probe = mp5416_probe,
+ .ops = &mp5416_ops,
+};
diff --git a/roms/u-boot/drivers/power/pmic/muic_max8997.c b/roms/u-boot/drivers/power/pmic/muic_max8997.c
new file mode 100644
index 000000000..969ce9023
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/muic_max8997.c
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2012 Samsung Electronics
+ * Lukasz Majewski <l.majewski@samsung.com>
+ */
+
+#include <common.h>
+#include <log.h>
+#include <power/pmic.h>
+#include <power/power_chrg.h>
+#include <power/max8997_muic.h>
+#include <i2c.h>
+#include <errno.h>
+
+static int power_chrg_get_type(struct pmic *p)
+{
+ unsigned int val;
+ unsigned char charge_type, charger;
+
+ if (pmic_probe(p))
+ return CHARGER_NO;
+
+ pmic_reg_read(p, MAX8997_MUIC_STATUS2, &val);
+ charge_type = val & MAX8997_MUIC_CHG_MASK;
+
+ switch (charge_type) {
+ case MAX8997_MUIC_CHG_NO:
+ charger = CHARGER_NO;
+ break;
+ case MAX8997_MUIC_CHG_USB:
+ case MAX8997_MUIC_CHG_USB_D:
+ charger = CHARGER_USB;
+ break;
+ case MAX8997_MUIC_CHG_TA:
+ case MAX8997_MUIC_CHG_TA_1A:
+ charger = CHARGER_TA;
+ break;
+ case MAX8997_MUIC_CHG_TA_500:
+ charger = CHARGER_TA_500;
+ break;
+ default:
+ charger = CHARGER_UNKNOWN;
+ break;
+ }
+
+ return charger;
+}
+
+static struct power_chrg power_chrg_muic_ops = {
+ .chrg_type = power_chrg_get_type,
+};
+
+int power_muic_init(unsigned int bus)
+{
+ static const char name[] = "MAX8997_MUIC";
+ struct pmic *p = pmic_alloc();
+
+ if (!p) {
+ printf("%s: POWER allocation error!\n", __func__);
+ return -ENOMEM;
+ }
+
+ debug("Board Micro USB Interface Controller init\n");
+
+ p->name = name;
+ p->interface = PMIC_I2C;
+ p->number_of_regs = MUIC_NUM_OF_REGS;
+ p->hw.i2c.addr = MAX8997_MUIC_I2C_ADDR;
+ p->hw.i2c.tx_num = 1;
+ p->bus = bus;
+
+ p->chrg = &power_chrg_muic_ops;
+ return 0;
+}
diff --git a/roms/u-boot/drivers/power/pmic/palmas.c b/roms/u-boot/drivers/power/pmic/palmas.c
new file mode 100644
index 000000000..6080cbff0
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/palmas.c
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2016 Texas Instruments Incorporated, <www.ti.com>
+ * Keerthy <j-keerthy@ti.com>
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <errno.h>
+#include <dm.h>
+#include <i2c.h>
+#include <log.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/palmas.h>
+#include <dm/device.h>
+
+static const struct pmic_child_info pmic_children_info[] = {
+ { .prefix = "ldo", .driver = PALMAS_LDO_DRIVER },
+ { .prefix = "smps", .driver = PALMAS_SMPS_DRIVER },
+ { },
+};
+
+static int palmas_write(struct udevice *dev, uint reg, const uint8_t *buff,
+ int len)
+{
+ if (dm_i2c_write(dev, reg, buff, len)) {
+ pr_err("write error to device: %p register: %#x!\n", dev, reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int palmas_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+ if (dm_i2c_read(dev, reg, buff, len)) {
+ pr_err("read error from device: %p register: %#x!\n", dev, reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int palmas_bind(struct udevice *dev)
+{
+ ofnode pmic_node = ofnode_null(), regulators_node;
+ ofnode subnode;
+ int children;
+
+ dev_for_each_subnode(subnode, dev) {
+ const char *name;
+ char *temp;
+
+ name = ofnode_get_name(subnode);
+ temp = strstr(name, "pmic");
+ if (temp) {
+ pmic_node = subnode;
+ break;
+ }
+ }
+
+ if (!ofnode_valid(pmic_node)) {
+ debug("%s: %s pmic subnode not found!\n", __func__, dev->name);
+ return -ENXIO;
+ }
+
+ regulators_node = ofnode_find_subnode(pmic_node, "regulators");
+
+ if (!ofnode_valid(regulators_node)) {
+ debug("%s: %s reg subnode not found!\n", __func__, dev->name);
+ return -ENXIO;
+ }
+
+ children = pmic_bind_children(dev, regulators_node, pmic_children_info);
+ if (!children)
+ debug("%s: %s - no child found\n", __func__, dev->name);
+
+ /* Always return success for this device */
+ return 0;
+}
+
+static struct dm_pmic_ops palmas_ops = {
+ .read = palmas_read,
+ .write = palmas_write,
+};
+
+static const struct udevice_id palmas_ids[] = {
+ { .compatible = "ti,tps659038", .data = TPS659038 },
+ { .compatible = "ti,tps65917" , .data = TPS65917 },
+ { }
+};
+
+U_BOOT_DRIVER(pmic_palmas) = {
+ .name = "palmas_pmic",
+ .id = UCLASS_PMIC,
+ .of_match = palmas_ids,
+ .bind = palmas_bind,
+ .ops = &palmas_ops,
+};
diff --git a/roms/u-boot/drivers/power/pmic/pca9450.c b/roms/u-boot/drivers/power/pmic/pca9450.c
new file mode 100644
index 000000000..a886647f1
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/pca9450.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 NXP
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <errno.h>
+#include <dm.h>
+#include <i2c.h>
+#include <log.h>
+#include <asm/global_data.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/pca9450.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const struct pmic_child_info pmic_children_info[] = {
+ /* buck */
+ { .prefix = "b", .driver = PCA9450_REGULATOR_DRIVER},
+ /* ldo */
+ { .prefix = "l", .driver = PCA9450_REGULATOR_DRIVER},
+ { },
+};
+
+static int pca9450_reg_count(struct udevice *dev)
+{
+ return PCA9450_REG_NUM;
+}
+
+static int pca9450_write(struct udevice *dev, uint reg, const uint8_t *buff,
+ int len)
+{
+ if (dm_i2c_write(dev, reg, buff, len)) {
+ pr_err("write error to device: %p register: %#x!", dev, reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int pca9450_read(struct udevice *dev, uint reg, uint8_t *buff,
+ int len)
+{
+ if (dm_i2c_read(dev, reg, buff, len)) {
+ pr_err("read error from device: %p register: %#x!", dev, reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int pca9450_bind(struct udevice *dev)
+{
+ int children;
+ ofnode regulators_node;
+
+ regulators_node = dev_read_subnode(dev, "regulators");
+ if (!ofnode_valid(regulators_node)) {
+ debug("%s: %s regulators subnode not found!", __func__,
+ dev->name);
+ return -ENXIO;
+ }
+
+ debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
+
+ children = pmic_bind_children(dev, regulators_node,
+ pmic_children_info);
+ if (!children)
+ debug("%s: %s - no child found\n", __func__, dev->name);
+
+ /* Always return success for this device */
+ return 0;
+}
+
+static struct dm_pmic_ops pca9450_ops = {
+ .reg_count = pca9450_reg_count,
+ .read = pca9450_read,
+ .write = pca9450_write,
+};
+
+static const struct udevice_id pca9450_ids[] = {
+ { .compatible = "nxp,pca9450a", .data = 0x25, },
+ { .compatible = "nxp,pca9450b", .data = 0x25, },
+ { }
+};
+
+U_BOOT_DRIVER(pmic_pca9450) = {
+ .name = "pca9450 pmic",
+ .id = UCLASS_PMIC,
+ .of_match = pca9450_ids,
+ .bind = pca9450_bind,
+ .ops = &pca9450_ops,
+};
diff --git a/roms/u-boot/drivers/power/pmic/pfuze100.c b/roms/u-boot/drivers/power/pmic/pfuze100.c
new file mode 100644
index 000000000..65c445697
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/pfuze100.c
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc
+ * Peng Fan <Peng.Fan@freescale.com>
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <errno.h>
+#include <dm.h>
+#include <i2c.h>
+#include <log.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/pfuze100_pmic.h>
+#include <power/pfuze3000_pmic.h>
+
+static const struct pmic_child_info pmic_children_info[] = {
+ /* sw[x], swbst */
+ { .prefix = "s", .driver = PFUZE100_REGULATOR_DRIVER },
+ /* vgen[x], vsnvs, vcc, v33, vcc_sd */
+ { .prefix = "v", .driver = PFUZE100_REGULATOR_DRIVER },
+ { },
+};
+
+static int pfuze100_reg_count(struct udevice *dev)
+{
+ return dev->driver_data == PFUZE3000 ? PFUZE3000_NUM_OF_REGS : PFUZE100_NUM_OF_REGS;
+}
+
+static int pfuze100_write(struct udevice *dev, uint reg, const uint8_t *buff,
+ int len)
+{
+ if (dm_i2c_write(dev, reg, buff, len)) {
+ pr_err("write error to device: %p register: %#x!\n", dev, reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int pfuze100_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+ if (dm_i2c_read(dev, reg, buff, len)) {
+ debug("read error from device: %p register: %#x!\n", dev, reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int pfuze100_bind(struct udevice *dev)
+{
+ ofnode regulators_node;
+ int children;
+
+ regulators_node = dev_read_subnode(dev, "regulators");
+ if (!ofnode_valid(regulators_node)) {
+ debug("%s: %s regulators subnode not found!\n", __func__,
+ dev->name);
+ return -ENXIO;
+ }
+
+ debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
+
+ children = pmic_bind_children(dev, regulators_node, pmic_children_info);
+ if (!children)
+ debug("%s: %s - no child found\n", __func__, dev->name);
+
+ /* Always return success for this device */
+ return 0;
+}
+
+static struct dm_pmic_ops pfuze100_ops = {
+ .reg_count = pfuze100_reg_count,
+ .read = pfuze100_read,
+ .write = pfuze100_write,
+};
+
+static const struct udevice_id pfuze100_ids[] = {
+ { .compatible = "fsl,pfuze100", .data = PFUZE100, },
+ { .compatible = "fsl,pfuze200", .data = PFUZE200, },
+ { .compatible = "fsl,pfuze3000", .data = PFUZE3000, },
+ { }
+};
+
+U_BOOT_DRIVER(pmic_pfuze100) = {
+ .name = "pfuze100 pmic",
+ .id = UCLASS_PMIC,
+ .of_match = pfuze100_ids,
+ .bind = pfuze100_bind,
+ .ops = &pfuze100_ops,
+};
diff --git a/roms/u-boot/drivers/power/pmic/pm8916.c b/roms/u-boot/drivers/power/pmic/pm8916.c
new file mode 100644
index 000000000..5f4386d4a
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/pm8916.c
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Qualcomm pm8916 pmic driver
+ *
+ * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
+ */
+#include <common.h>
+#include <dm.h>
+#include <power/pmic.h>
+#include <spmi/spmi.h>
+
+#define PID_SHIFT 8
+#define PID_MASK (0xFF << PID_SHIFT)
+#define REG_MASK 0xFF
+
+struct pm8916_priv {
+ uint32_t usid; /* Slave ID on SPMI bus */
+};
+
+static int pm8916_reg_count(struct udevice *dev)
+{
+ return 0xFFFF;
+}
+
+static int pm8916_write(struct udevice *dev, uint reg, const uint8_t *buff,
+ int len)
+{
+ struct pm8916_priv *priv = dev_get_priv(dev);
+
+ if (len != 1)
+ return -EINVAL;
+
+ return spmi_reg_write(dev->parent, priv->usid,
+ (reg & PID_MASK) >> PID_SHIFT, reg & REG_MASK,
+ *buff);
+}
+
+static int pm8916_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+ struct pm8916_priv *priv = dev_get_priv(dev);
+ int val;
+
+ if (len != 1)
+ return -EINVAL;
+
+ val = spmi_reg_read(dev->parent, priv->usid,
+ (reg & PID_MASK) >> PID_SHIFT, reg & REG_MASK);
+
+ if (val < 0)
+ return val;
+ *buff = val;
+ return 0;
+}
+
+static struct dm_pmic_ops pm8916_ops = {
+ .reg_count = pm8916_reg_count,
+ .read = pm8916_read,
+ .write = pm8916_write,
+};
+
+static const struct udevice_id pm8916_ids[] = {
+ { .compatible = "qcom,spmi-pmic" },
+ { }
+};
+
+static int pm8916_probe(struct udevice *dev)
+{
+ struct pm8916_priv *priv = dev_get_priv(dev);
+
+ priv->usid = dev_read_addr(dev);
+
+ if (priv->usid == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ return 0;
+}
+
+U_BOOT_DRIVER(pmic_pm8916) = {
+ .name = "pmic_pm8916",
+ .id = UCLASS_PMIC,
+ .of_match = pm8916_ids,
+ .bind = dm_scan_fdt_dev,
+ .probe = pm8916_probe,
+ .ops = &pm8916_ops,
+ .priv_auto = sizeof(struct pm8916_priv),
+};
diff --git a/roms/u-boot/drivers/power/pmic/pmic-uclass.c b/roms/u-boot/drivers/power/pmic/pmic-uclass.c
new file mode 100644
index 000000000..79166b8bb
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/pmic-uclass.c
@@ -0,0 +1,200 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2014-2015 Samsung Electronics
+ * Przemyslaw Marczak <p.marczak@samsung.com>
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <errno.h>
+#include <dm.h>
+#include <log.h>
+#include <vsprintf.h>
+#include <dm/lists.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
+#include <power/pmic.h>
+#include <linux/ctype.h>
+
+#if CONFIG_IS_ENABLED(PMIC_CHILDREN)
+int pmic_bind_children(struct udevice *pmic, ofnode parent,
+ const struct pmic_child_info *child_info)
+{
+ const struct pmic_child_info *info;
+ struct driver *drv;
+ struct udevice *child;
+ const char *node_name;
+ const char *reg_name;
+ int bind_count = 0;
+ ofnode node;
+ int prefix_len;
+ int ret;
+
+ debug("%s for '%s' at node offset: %d\n", __func__, pmic->name,
+ dev_of_offset(pmic));
+
+ ofnode_for_each_subnode(node, parent) {
+ node_name = ofnode_get_name(node);
+
+ debug("* Found child node: '%s'\n", node_name);
+
+ child = NULL;
+ for (info = child_info; info->prefix && info->driver; info++) {
+ debug(" - compatible prefix: '%s'\n", info->prefix);
+
+ prefix_len = strlen(info->prefix);
+ if (strncmp(info->prefix, node_name, prefix_len)) {
+ reg_name = ofnode_read_string(node,
+ "regulator-name");
+ if (!reg_name)
+ continue;
+ if (strncmp(info->prefix, reg_name, prefix_len))
+ continue;
+ }
+
+ drv = lists_driver_lookup_name(info->driver);
+ if (!drv) {
+ debug(" - driver: '%s' not found!\n",
+ info->driver);
+ continue;
+ }
+
+ debug(" - found child driver: '%s'\n", drv->name);
+
+ ret = device_bind_with_driver_data(pmic, drv, node_name,
+ 0, node, &child);
+ if (ret) {
+ debug(" - child binding error: %d\n", ret);
+ continue;
+ }
+
+ debug(" - bound child device: '%s'\n", child->name);
+
+ child->driver_data = trailing_strtol(node_name);
+
+ debug(" - set 'child->driver_data': %lu\n",
+ child->driver_data);
+ break;
+ }
+
+ if (child)
+ bind_count++;
+ else
+ debug(" - compatible prefix not found\n");
+ }
+
+ debug("Bound: %d children for PMIC: '%s'\n", bind_count, pmic->name);
+ return bind_count;
+}
+#endif
+
+int pmic_get(const char *name, struct udevice **devp)
+{
+ return uclass_get_device_by_name(UCLASS_PMIC, name, devp);
+}
+
+int pmic_reg_count(struct udevice *dev)
+{
+ const struct dm_pmic_ops *ops = dev_get_driver_ops(dev);
+
+ if (!ops || !ops->reg_count)
+ return -ENOSYS;
+
+ return ops->reg_count(dev);
+}
+
+int pmic_read(struct udevice *dev, uint reg, uint8_t *buffer, int len)
+{
+ const struct dm_pmic_ops *ops = dev_get_driver_ops(dev);
+
+ if (!buffer)
+ return -EFAULT;
+
+ if (!ops || !ops->read)
+ return -ENOSYS;
+
+ return ops->read(dev, reg, buffer, len);
+}
+
+int pmic_write(struct udevice *dev, uint reg, const uint8_t *buffer, int len)
+{
+ const struct dm_pmic_ops *ops = dev_get_driver_ops(dev);
+
+ if (!buffer)
+ return -EFAULT;
+
+ if (!ops || !ops->write)
+ return -ENOSYS;
+
+ return ops->write(dev, reg, buffer, len);
+}
+
+int pmic_reg_read(struct udevice *dev, uint reg)
+{
+ struct uc_pmic_priv *priv = dev_get_uclass_priv(dev);
+ u32 val = 0;
+ int ret;
+
+ if (priv->trans_len < 1 || priv->trans_len > sizeof(val)) {
+ debug("Wrong transmission size [%d]\n", priv->trans_len);
+ return -EINVAL;
+ }
+
+ debug("%s: reg=%x priv->trans_len:%d", __func__, reg, priv->trans_len);
+ ret = pmic_read(dev, reg, (uint8_t *)&val, priv->trans_len);
+ debug(", value=%x, ret=%d\n", val, ret);
+
+ return ret ? ret : val;
+}
+
+int pmic_reg_write(struct udevice *dev, uint reg, uint value)
+{
+ struct uc_pmic_priv *priv = dev_get_uclass_priv(dev);
+ int ret;
+
+ if (priv->trans_len < 1 || priv->trans_len > sizeof(value)) {
+ debug("Wrong transmission size [%d]\n", priv->trans_len);
+ return -EINVAL;
+ }
+
+ debug("%s: reg=%x, value=%x priv->trans_len:%d", __func__, reg, value,
+ priv->trans_len);
+ ret = pmic_write(dev, reg, (uint8_t *)&value, priv->trans_len);
+ debug(", ret=%d\n", ret);
+
+ return ret;
+}
+
+int pmic_clrsetbits(struct udevice *dev, uint reg, uint clr, uint set)
+{
+ struct uc_pmic_priv *priv = dev_get_uclass_priv(dev);
+ u32 val = 0;
+ int ret;
+
+ if (priv->trans_len < 1 || priv->trans_len > sizeof(val)) {
+ debug("Wrong transmission size [%d]\n", priv->trans_len);
+ return -EINVAL;
+ }
+
+ ret = pmic_read(dev, reg, (uint8_t *)&val, priv->trans_len);
+ if (ret < 0)
+ return ret;
+
+ val = (val & ~clr) | set;
+ return pmic_write(dev, reg, (uint8_t *)&val, priv->trans_len);
+}
+
+static int pmic_pre_probe(struct udevice *dev)
+{
+ struct uc_pmic_priv *pmic_priv = dev_get_uclass_priv(dev);
+
+ pmic_priv->trans_len = 1;
+ return 0;
+}
+
+UCLASS_DRIVER(pmic) = {
+ .id = UCLASS_PMIC,
+ .name = "pmic",
+ .pre_probe = pmic_pre_probe,
+ .per_device_auto = sizeof(struct uc_pmic_priv),
+};
diff --git a/roms/u-boot/drivers/power/pmic/pmic_hi6553.c b/roms/u-boot/drivers/power/pmic/pmic_hi6553.c
new file mode 100644
index 000000000..80b9078cf
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/pmic_hi6553.c
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015 Linaro
+ * Peter Griffin <peter.griffin@linaro.org>
+ */
+#include <asm/io.h>
+#include <common.h>
+#include <linux/delay.h>
+#include <power/pmic.h>
+#include <power/max8997_muic.h>
+#include <power/hi6553_pmic.h>
+#include <errno.h>
+
+u8 *pmussi_base;
+
+uint8_t hi6553_readb(u32 offset)
+{
+ return readb(pmussi_base + (offset << 2));
+}
+
+void hi6553_writeb(u32 offset, uint8_t value)
+{
+ writeb(value, pmussi_base + (offset << 2));
+}
+
+int pmic_reg_write(struct pmic *p, u32 reg, u32 val)
+{
+ if (check_reg(p, reg))
+ return -EINVAL;
+
+ hi6553_writeb(reg, (uint8_t)val);
+
+ return 0;
+}
+
+int pmic_reg_read(struct pmic *p, u32 reg, u32 *val)
+{
+ if (check_reg(p, reg))
+ return -EINVAL;
+
+ *val = (u32)hi6553_readb(reg);
+
+ return 0;
+}
+
+static void hi6553_init(void)
+{
+ int data;
+
+ hi6553_writeb(HI6553_PERI_EN_MARK, 0x1e);
+ hi6553_writeb(HI6553_NP_REG_ADJ1, 0);
+ data = HI6553_DISABLE6_XO_CLK_CONN | HI6553_DISABLE6_XO_CLK_NFC |
+ HI6553_DISABLE6_XO_CLK_RF1 | HI6553_DISABLE6_XO_CLK_RF2;
+ hi6553_writeb(HI6553_DISABLE6_XO_CLK, data);
+
+ /* configure BUCK0 & BUCK1 */
+ hi6553_writeb(HI6553_BUCK01_CTRL2, 0x5e);
+ hi6553_writeb(HI6553_BUCK0_CTRL7, 0x10);
+ hi6553_writeb(HI6553_BUCK1_CTRL7, 0x10);
+ hi6553_writeb(HI6553_BUCK0_CTRL5, 0x1e);
+ hi6553_writeb(HI6553_BUCK1_CTRL5, 0x1e);
+ hi6553_writeb(HI6553_BUCK0_CTRL1, 0xfc);
+ hi6553_writeb(HI6553_BUCK1_CTRL1, 0xfc);
+
+ /* configure BUCK2 */
+ hi6553_writeb(HI6553_BUCK2_REG1, 0x4f);
+ hi6553_writeb(HI6553_BUCK2_REG5, 0x99);
+ hi6553_writeb(HI6553_BUCK2_REG6, 0x45);
+ mdelay(1);
+ hi6553_writeb(HI6553_VSET_BUCK2_ADJ, 0x22);
+ mdelay(1);
+
+ /* configure BUCK3 */
+ hi6553_writeb(HI6553_BUCK3_REG3, 0x02);
+ hi6553_writeb(HI6553_BUCK3_REG5, 0x99);
+ hi6553_writeb(HI6553_BUCK3_REG6, 0x41);
+ hi6553_writeb(HI6553_VSET_BUCK3_ADJ, 0x02);
+ mdelay(1);
+
+ /* configure BUCK4 */
+ hi6553_writeb(HI6553_BUCK4_REG2, 0x9a);
+ hi6553_writeb(HI6553_BUCK4_REG5, 0x99);
+ hi6553_writeb(HI6553_BUCK4_REG6, 0x45);
+
+ /* configure LDO20 */
+ hi6553_writeb(HI6553_LDO20_REG_ADJ, 0x50);
+
+ hi6553_writeb(HI6553_NP_REG_CHG, 0x0f);
+ hi6553_writeb(HI6553_CLK_TOP0, 0x06);
+ hi6553_writeb(HI6553_CLK_TOP3, 0xc0);
+ hi6553_writeb(HI6553_CLK_TOP4, 0x00);
+
+ /* configure LDO7 & LDO10 for SD slot */
+ data = hi6553_readb(HI6553_LDO7_REG_ADJ);
+ data = (data & 0xf8) | 0x2;
+ hi6553_writeb(HI6553_LDO7_REG_ADJ, data);
+ mdelay(5);
+ /* enable LDO7 */
+ hi6553_writeb(HI6553_ENABLE2_LDO1_8, 1 << 6);
+ mdelay(5);
+ data = hi6553_readb(HI6553_LDO10_REG_ADJ);
+ data = (data & 0xf8) | 0x5;
+ hi6553_writeb(HI6553_LDO10_REG_ADJ, data);
+ mdelay(5);
+ /* enable LDO10 */
+ hi6553_writeb(HI6553_ENABLE3_LDO9_16, 1 << 1);
+ mdelay(5);
+
+ /* select 32.764KHz */
+ hi6553_writeb(HI6553_CLK19M2_600_586_EN, 0x01);
+}
+
+int power_hi6553_init(u8 *base)
+{
+ static const char name[] = "HI6553 PMIC";
+ struct pmic *p = pmic_alloc();
+
+ if (!p) {
+ printf("%s: POWER allocation error!\n", __func__);
+ return -ENOMEM;
+ }
+
+ p->name = name;
+ p->interface = PMIC_NONE;
+ p->number_of_regs = 44;
+ pmussi_base = base;
+
+ hi6553_init();
+
+ puts("HI6553 PMIC init\n");
+
+ return 0;
+}
diff --git a/roms/u-boot/drivers/power/pmic/pmic_ltc3676.c b/roms/u-boot/drivers/power/pmic/pmic_ltc3676.c
new file mode 100644
index 000000000..00c3e201c
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/pmic_ltc3676.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2014 Gateworks Corporation
+ * Tim Harvey <tharvey@gateworks.com>
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <i2c.h>
+#include <power/pmic.h>
+#include <power/ltc3676_pmic.h>
+
+int power_ltc3676_init(unsigned char bus)
+{
+ static const char name[] = "LTC3676_PMIC";
+ struct pmic *p = pmic_alloc();
+
+ if (!p) {
+ printf("%s: POWER allocation error!\n", __func__);
+ return -ENOMEM;
+ }
+
+ p->name = name;
+ p->interface = PMIC_I2C;
+ p->number_of_regs = LTC3676_NUM_OF_REGS;
+ p->hw.i2c.addr = CONFIG_POWER_LTC3676_I2C_ADDR;
+ p->hw.i2c.tx_num = 1;
+ p->bus = bus;
+
+ return 0;
+}
diff --git a/roms/u-boot/drivers/power/pmic/pmic_mc34vr500.c b/roms/u-boot/drivers/power/pmic/pmic_mc34vr500.c
new file mode 100644
index 000000000..9dd1c46ea
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/pmic_mc34vr500.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ * Hou Zhiqiang <Zhiqiang.Hou@freescale.com>
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <i2c.h>
+#include <power/pmic.h>
+#include <power/mc34vr500_pmic.h>
+
+int power_mc34vr500_init(unsigned char bus)
+{
+ static const char name[] = "MC34VR500";
+ struct pmic *p = pmic_alloc();
+
+ if (!p) {
+ printf("%s: POWER allocation error!\n", __func__);
+ return -ENOMEM;
+ }
+
+ p->name = name;
+ p->interface = PMIC_I2C;
+ p->number_of_regs = MC34VR500_NUM_OF_REGS;
+ p->hw.i2c.addr = MC34VR500_I2C_ADDR;
+ p->hw.i2c.tx_num = 1;
+ p->bus = bus;
+
+ return 0;
+}
diff --git a/roms/u-boot/drivers/power/pmic/pmic_pca9450.c b/roms/u-boot/drivers/power/pmic/pmic_pca9450.c
new file mode 100644
index 000000000..8c4d0a923
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/pmic_pca9450.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 NXP
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <i2c.h>
+#include <power/pmic.h>
+#include <power/pca9450.h>
+
+static const char pca9450_name[] = "PCA9450";
+
+int power_pca9450_init(unsigned char bus, unsigned char addr)
+{
+ struct pmic *p = pmic_alloc();
+
+ if (!p) {
+ printf("%s: POWER allocation error!\n", __func__);
+ return -ENOMEM;
+ }
+
+ p->name = pca9450_name;
+ p->interface = PMIC_I2C;
+ p->number_of_regs = PCA9450_REG_NUM;
+ p->hw.i2c.addr = addr;
+ p->hw.i2c.tx_num = 1;
+ p->bus = bus;
+
+ return 0;
+}
diff --git a/roms/u-boot/drivers/power/pmic/pmic_pfuze100.c b/roms/u-boot/drivers/power/pmic/pmic_pfuze100.c
new file mode 100644
index 000000000..c646a0c31
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/pmic_pfuze100.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2014 Gateworks Corporation
+ * Tim Harvey <tharvey@gateworks.com>
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <i2c.h>
+#include <power/pmic.h>
+#include <power/pfuze100_pmic.h>
+
+int power_pfuze100_init(unsigned char bus)
+{
+ static const char name[] = "PFUZE100";
+ struct pmic *p = pmic_alloc();
+
+ if (!p) {
+ printf("%s: POWER allocation error!\n", __func__);
+ return -ENOMEM;
+ }
+
+ p->name = name;
+ p->interface = PMIC_I2C;
+ p->number_of_regs = PFUZE100_NUM_OF_REGS;
+ p->hw.i2c.addr = CONFIG_POWER_PFUZE100_I2C_ADDR;
+ p->hw.i2c.tx_num = 1;
+ p->bus = bus;
+
+ return 0;
+}
diff --git a/roms/u-boot/drivers/power/pmic/pmic_pfuze3000.c b/roms/u-boot/drivers/power/pmic/pmic_pfuze3000.c
new file mode 100644
index 000000000..1077fa5e9
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/pmic_pfuze3000.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ * Peng Fan <Peng.Fan@freescale.com>
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <i2c.h>
+#include <power/pmic.h>
+#include <power/pfuze3000_pmic.h>
+
+int power_pfuze3000_init(unsigned char bus)
+{
+ static const char name[] = "PFUZE3000";
+ struct pmic *p = pmic_alloc();
+
+ if (!p) {
+ printf("%s: POWER allocation error!\n", __func__);
+ return -ENOMEM;
+ }
+
+ p->name = name;
+ p->interface = PMIC_I2C;
+ p->number_of_regs = PFUZE3000_NUM_OF_REGS;
+ p->hw.i2c.addr = CONFIG_POWER_PFUZE3000_I2C_ADDR;
+ p->hw.i2c.tx_num = 1;
+ p->bus = bus;
+
+ return 0;
+}
diff --git a/roms/u-boot/drivers/power/pmic/pmic_tps62362.c b/roms/u-boot/drivers/power/pmic/pmic_tps62362.c
new file mode 100644
index 000000000..59190d6f6
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/pmic_tps62362.c
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2014 Texas Instruments Incorporated - http://www.ti.com
+ * Author: Felipe Balbi <balbi@ti.com>
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <linux/errno.h>
+#include <power/pmic.h>
+#include <power/tps62362.h>
+
+#if CONFIG_IS_ENABLED(DM_I2C)
+struct udevice *tps62362_dev __section(".data") = NULL;
+#endif
+
+/**
+ * tps62362_voltage_update() - Function to change a voltage level, as this
+ * is a multi-step process.
+ * @reg: Register address to write to
+ * @volt_sel: Voltage register value to write
+ * @return: 0 on success, 1 on failure
+ */
+int tps62362_voltage_update(unsigned char reg, unsigned char volt_sel)
+{
+ if (reg > TPS62362_NUM_REGS)
+ return 1;
+
+#if !CONFIG_IS_ENABLED(DM_I2C)
+ return i2c_write(TPS62362_I2C_ADDR, reg, 1, &volt_sel, 1);
+#else
+ if (!tps62362_dev)
+ return -ENODEV;
+ return dm_i2c_reg_write(tps62362_dev, reg, volt_sel);
+#endif
+}
+
+#if !CONFIG_IS_ENABLED(DM_I2C)
+int power_tps62362_init(unsigned char bus)
+{
+ static const char name[] = "TPS62362";
+ struct pmic *p = pmic_alloc();
+
+ if (!p) {
+ printf("%s: POWER allocation error!\n", __func__);
+ return -ENOMEM;
+ }
+
+ p->name = name;
+ p->interface = PMIC_I2C;
+ p->number_of_regs = TPS62362_NUM_REGS;
+ p->hw.i2c.addr = TPS62362_I2C_ADDR;
+ p->hw.i2c.tx_num = 1;
+ p->bus = bus;
+
+ return 0;
+}
+#else
+int power_tps62362_init(unsigned char bus)
+{
+ struct udevice *dev = NULL;
+ int rc;
+
+ rc = i2c_get_chip_for_busnum(bus, TPS62362_I2C_ADDR, 1, &dev);
+ if (rc)
+ return rc;
+ tps62362_dev = dev;
+ return 0;
+}
+#endif
diff --git a/roms/u-boot/drivers/power/pmic/pmic_tps65217.c b/roms/u-boot/drivers/power/pmic/pmic_tps65217.c
new file mode 100644
index 000000000..c7f532df4
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/pmic_tps65217.c
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2011-2013
+ * Texas Instruments, <www.ti.com>
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <power/tps65217.h>
+
+struct udevice *tps65217_dev __section(".data") = NULL;
+
+/**
+ * tps65217_reg_read() - Generic function that can read a TPS65217 register
+ * @src_reg: Source register address
+ * @src_val: Address of destination variable
+ * @return: 0 for success, not 0 on failure.
+ */
+int tps65217_reg_read(uchar src_reg, uchar *src_val)
+{
+#if !CONFIG_IS_ENABLED(DM_I2C)
+ return i2c_read(TPS65217_CHIP_PM, src_reg, 1, src_val, 1);
+#else
+ return dm_i2c_read(tps65217_dev, src_reg, src_val, 1);
+#endif
+}
+
+/**
+ * tps65217_reg_write() - Generic function that can write a TPS65217 PMIC
+ * register or bit field regardless of protection
+ * level.
+ *
+ * @prot_level: Register password protection. Use
+ * TPS65217_PROT_LEVEL_NONE,
+ * TPS65217_PROT_LEVEL_1 or TPS65217_PROT_LEVEL_2
+ * @dest_reg: Register address to write.
+ * @dest_val: Value to write.
+ * @mask: Bit mask (8 bits) to be applied. Function will only
+ * change bits that are set in the bit mask.
+ *
+ * @return: 0 for success, not 0 on failure, as per the i2c API
+ */
+int tps65217_reg_write(uchar prot_level, uchar dest_reg, uchar dest_val,
+ uchar mask)
+{
+ uchar read_val;
+ uchar xor_reg;
+ int ret;
+
+ /*
+ * If we are affecting only a bit field, read dest_reg and apply the
+ * mask
+ */
+ if (mask != TPS65217_MASK_ALL_BITS) {
+#if !CONFIG_IS_ENABLED(DM_I2C)
+ ret = i2c_read(TPS65217_CHIP_PM, dest_reg, 1, &read_val, 1);
+#else
+ ret = dm_i2c_read(tps65217_dev, dest_reg, &read_val, 1);
+#endif
+ if (ret)
+ return ret;
+
+ read_val &= (~mask);
+ read_val |= (dest_val & mask);
+ dest_val = read_val;
+ }
+
+ if (prot_level > 0) {
+ xor_reg = dest_reg ^ TPS65217_PASSWORD_UNLOCK;
+#if !CONFIG_IS_ENABLED(DM_I2C)
+ ret = i2c_write(TPS65217_CHIP_PM, TPS65217_PASSWORD, 1,
+ &xor_reg, 1);
+#else
+ ret = dm_i2c_write(tps65217_dev, TPS65217_PASSWORD,
+ &xor_reg, 1);
+#endif
+ if (ret)
+ return ret;
+ }
+#if !CONFIG_IS_ENABLED(DM_I2C)
+ ret = i2c_write(TPS65217_CHIP_PM, dest_reg, 1, &dest_val, 1);
+#else
+ ret = dm_i2c_write(tps65217_dev, dest_reg, &dest_val, 1);
+#endif
+ if (ret)
+ return ret;
+
+ if (prot_level == TPS65217_PROT_LEVEL_2) {
+#if !CONFIG_IS_ENABLED(DM_I2C)
+ ret = i2c_write(TPS65217_CHIP_PM, TPS65217_PASSWORD, 1,
+ &xor_reg, 1);
+#else
+ ret = dm_i2c_write(tps65217_dev, TPS65217_PASSWORD,
+ &xor_reg, 1);
+#endif
+ if (ret)
+ return ret;
+
+#if !CONFIG_IS_ENABLED(DM_I2C)
+ ret = i2c_write(TPS65217_CHIP_PM, dest_reg, 1, &dest_val, 1);
+#else
+ ret = dm_i2c_write(tps65217_dev, dest_reg, &dest_val, 1);
+#endif
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * tps65217_voltage_update() - Function to change a voltage level, as this
+ * is a multi-step process.
+ * @dc_cntrl_reg: DC voltage control register to change.
+ * @volt_sel: New value for the voltage register
+ * @return: 0 for success, not 0 on failure.
+ */
+int tps65217_voltage_update(uchar dc_cntrl_reg, uchar volt_sel)
+{
+ if ((dc_cntrl_reg != TPS65217_DEFDCDC1) &&
+ (dc_cntrl_reg != TPS65217_DEFDCDC2) &&
+ (dc_cntrl_reg != TPS65217_DEFDCDC3))
+ return 1;
+
+ /* set voltage level */
+ if (tps65217_reg_write(TPS65217_PROT_LEVEL_2, dc_cntrl_reg, volt_sel,
+ TPS65217_MASK_ALL_BITS))
+ return 1;
+
+ /* set GO bit to initiate voltage transition */
+ if (tps65217_reg_write(TPS65217_PROT_LEVEL_2, TPS65217_DEFSLEW,
+ TPS65217_DCDC_GO, TPS65217_DCDC_GO))
+ return 1;
+
+ return 0;
+}
+
+int power_tps65217_init(unsigned char bus)
+{
+#if CONFIG_IS_ENABLED(DM_I2C)
+ struct udevice *dev = NULL;
+ int rc;
+
+ rc = i2c_get_chip_for_busnum(bus, TPS65217_CHIP_PM, 1, &dev);
+ if (rc)
+ return rc;
+ tps65217_dev = dev;
+#endif
+ return 0;
+}
diff --git a/roms/u-boot/drivers/power/pmic/pmic_tps65218.c b/roms/u-boot/drivers/power/pmic/pmic_tps65218.c
new file mode 100644
index 000000000..671749018
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/pmic_tps65218.c
@@ -0,0 +1,260 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2011-2013
+ * Texas Instruments, <www.ti.com>
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <linux/errno.h>
+#include <power/pmic.h>
+#include <power/tps65218.h>
+
+#if !CONFIG_IS_ENABLED(DM_I2C)
+int tps65218_reg_read(uchar dest_reg, uchar *dest_val)
+{
+ uchar read_val;
+ int ret;
+
+ ret = i2c_read(TPS65218_CHIP_PM, dest_reg, 1, &read_val, 1);
+ if (ret)
+ return ret;
+
+ *dest_val = read_val;
+
+ return 0;
+}
+
+/**
+ * tps65218_reg_write() - Generic function that can write a TPS65218 PMIC
+ * register or bit field regardless of protection
+ * level.
+ *
+ * @prot_level: Register password protection. Use
+ * TPS65218_PROT_LEVEL_NONE,
+ * TPS65218_PROT_LEVEL_1 or TPS65218_PROT_LEVEL_2
+ * @dest_reg: Register address to write.
+ * @dest_val: Value to write.
+ * @mask: Bit mask (8 bits) to be applied. Function will only
+ * change bits that are set in the bit mask.
+ *
+ * @return: 0 for success, not 0 on failure, as per the i2c API
+ */
+int tps65218_reg_write(uchar prot_level, uchar dest_reg, uchar dest_val,
+ uchar mask)
+{
+ uchar read_val;
+ uchar xor_reg;
+ int ret;
+
+ /*
+ * If we are affecting only a bit field, read dest_reg and apply the
+ * mask
+ */
+ if (mask != TPS65218_MASK_ALL_BITS) {
+ ret = i2c_read(TPS65218_CHIP_PM, dest_reg, 1, &read_val, 1);
+ if (ret)
+ return ret;
+ read_val &= (~mask);
+ read_val |= (dest_val & mask);
+ dest_val = read_val;
+ }
+
+ if (prot_level > 0) {
+ xor_reg = dest_reg ^ TPS65218_PASSWORD_UNLOCK;
+ ret = i2c_write(TPS65218_CHIP_PM, TPS65218_PASSWORD, 1,
+ &xor_reg, 1);
+ if (ret)
+ return ret;
+ }
+
+ ret = i2c_write(TPS65218_CHIP_PM, dest_reg, 1, &dest_val, 1);
+ if (ret)
+ return ret;
+
+ if (prot_level == TPS65218_PROT_LEVEL_2) {
+ ret = i2c_write(TPS65218_CHIP_PM, TPS65218_PASSWORD, 1,
+ &xor_reg, 1);
+ if (ret)
+ return ret;
+
+ ret = i2c_write(TPS65218_CHIP_PM, dest_reg, 1, &dest_val, 1);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+#else
+struct udevice *tps65218_dev __section(".data") = NULL;
+
+int tps65218_reg_read(uchar dest_reg, uchar *dest_val)
+{
+ uchar read_val;
+ int ret;
+
+ if (!tps65218_dev)
+ return -ENODEV;
+
+ ret = dm_i2c_read(tps65218_dev, dest_reg, &read_val, 1);
+ if (ret)
+ return ret;
+
+ *dest_val = read_val;
+
+ return 0;
+}
+
+int tps65218_reg_write(uchar prot_level, uchar dest_reg, uchar dest_val,
+ uchar mask)
+{
+ uchar read_val;
+ uchar xor_reg;
+ int ret;
+
+ if (!tps65218_dev)
+ return -ENODEV;
+
+ /*
+ * If we are affecting only a bit field, read dest_reg and apply the
+ * mask
+ */
+ if (mask != TPS65218_MASK_ALL_BITS) {
+ ret = dm_i2c_read(tps65218_dev, dest_reg, &read_val, 1);
+ if (ret)
+ return ret;
+
+ read_val &= (~mask);
+ read_val |= (dest_val & mask);
+ dest_val = read_val;
+ }
+
+ if (prot_level > 0) {
+ xor_reg = dest_reg ^ TPS65218_PASSWORD_UNLOCK;
+ ret = dm_i2c_write(tps65218_dev, TPS65218_PASSWORD, &xor_reg,
+ 1);
+ if (ret)
+ return ret;
+ }
+
+ ret = dm_i2c_write(tps65218_dev, dest_reg, &dest_val, 1);
+ if (ret)
+ return ret;
+
+ if (prot_level == TPS65218_PROT_LEVEL_2) {
+ ret = dm_i2c_write(tps65218_dev, TPS65218_PASSWORD, &xor_reg,
+ 1);
+ if (ret)
+ return ret;
+
+ ret = dm_i2c_write(tps65218_dev, dest_reg, &dest_val, 1);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+#endif
+
+/**
+ * tps65218_voltage_update() - Function to change a voltage level, as this
+ * is a multi-step process.
+ * @dc_cntrl_reg: DC voltage control register to change.
+ * @volt_sel: New value for the voltage register
+ * @return: 0 for success, not 0 on failure.
+ */
+int tps65218_voltage_update(uchar dc_cntrl_reg, uchar volt_sel)
+{
+ if ((dc_cntrl_reg != TPS65218_DCDC1) &&
+ (dc_cntrl_reg != TPS65218_DCDC2) &&
+ (dc_cntrl_reg != TPS65218_DCDC3))
+ return 1;
+
+ /* set voltage level */
+ if (tps65218_reg_write(TPS65218_PROT_LEVEL_2, dc_cntrl_reg, volt_sel,
+ TPS65218_DCDC_VSEL_MASK))
+ return 1;
+
+ /* set GO bit to initiate voltage transition */
+ if (tps65218_reg_write(TPS65218_PROT_LEVEL_2, TPS65218_SLEW,
+ TPS65218_DCDC_GO, TPS65218_DCDC_GO))
+ return 1;
+
+ return 0;
+}
+
+/**
+ * tps65218_toggle_fseal() - Perform the sequence that toggles the FSEAL bit.
+ *
+ * @return: 0 on success, -EBADE if the sequence was broken
+ */
+int tps65218_toggle_fseal(void)
+{
+ if (tps65218_reg_write(TPS65218_PROT_LEVEL_NONE, TPS65218_PASSWORD,
+ 0xb1, TPS65218_MASK_ALL_BITS))
+ return -EBADE;
+
+ if (tps65218_reg_write(TPS65218_PROT_LEVEL_NONE, TPS65218_PASSWORD,
+ 0xfe, TPS65218_MASK_ALL_BITS))
+ return -EBADE;
+
+ if (tps65218_reg_write(TPS65218_PROT_LEVEL_NONE, TPS65218_PASSWORD,
+ 0xa3, TPS65218_MASK_ALL_BITS))
+ return -EBADE;
+
+ return 0;
+}
+
+/**
+ * tps65218_lock_fseal() - Perform the sequence that locks the FSEAL bit to 1.
+ *
+ * The FSEAL bit prevents the PMIC from turning off DCDC5 and DCDC6. It can be
+ * toggled at most 3 times: 0->1, 1->0, and finally 0->1. After the third switch
+ * its value is locked and can only be reset by powering off the PMIC entirely.
+ *
+ * @return: 0 on success, -EBADE if the sequence was broken
+ */
+int tps65218_lock_fseal(void)
+{
+ int i;
+
+ for (i = 0; i < 3; i++)
+ if (tps65218_toggle_fseal())
+ return -EBADE;
+
+ return 0;
+}
+
+#if !CONFIG_IS_ENABLED(DM_I2C)
+int power_tps65218_init(unsigned char bus)
+{
+ static const char name[] = "TPS65218_PMIC";
+ struct pmic *p = pmic_alloc();
+
+ if (!p) {
+ printf("%s: POWER allocation error!\n", __func__);
+ return -ENOMEM;
+ }
+
+ p->name = name;
+ p->interface = PMIC_I2C;
+ p->number_of_regs = TPS65218_PMIC_NUM_OF_REGS;
+ p->hw.i2c.addr = TPS65218_CHIP_PM;
+ p->hw.i2c.tx_num = 1;
+ p->bus = bus;
+
+ return 0;
+}
+#else
+int power_tps65218_init(unsigned char bus)
+{
+ struct udevice *dev = NULL;
+ int rc;
+
+ rc = i2c_get_chip_for_busnum(bus, TPS65218_CHIP_PM, 1, &dev);
+ if (rc)
+ return rc;
+ tps65218_dev = dev;
+ return 0;
+}
+#endif
diff --git a/roms/u-boot/drivers/power/pmic/pmic_tps65910.c b/roms/u-boot/drivers/power/pmic/pmic_tps65910.c
new file mode 100644
index 000000000..fcd0a654a
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/pmic_tps65910.c
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2011-2013
+ * Texas Instruments, <www.ti.com>
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <power/tps65910.h>
+
+struct udevice *tps65910_dev __section(".data") = NULL;
+
+static inline int tps65910_read_reg(int addr, uchar *buf)
+{
+#if !CONFIG_IS_ENABLED(DM_I2C)
+ return i2c_read(TPS65910_CTRL_I2C_ADDR, addr, 1, buf, 1);
+#else
+ int rc;
+
+ rc = dm_i2c_reg_read(tps65910_dev, addr);
+ if (rc < 0)
+ return rc;
+ *buf = (uchar)rc;
+ return 0;
+#endif
+}
+
+static inline int tps65910_write_reg(int addr, uchar *buf)
+{
+#if !CONFIG_IS_ENABLED(DM_I2C)
+ return i2c_write(TPS65910_CTRL_I2C_ADDR, addr, 1, buf, 1);
+#else
+ return dm_i2c_reg_write(tps65910_dev, addr, *buf);
+#endif
+}
+
+int power_tps65910_init(unsigned char bus)
+{
+#if CONFIG_IS_ENABLED(DM_I2C)
+ struct udevice *dev = NULL;
+ int rc;
+
+ rc = i2c_get_chip_for_busnum(bus, TPS65910_CTRL_I2C_ADDR, 1, &dev);
+
+ if (rc)
+ return rc;
+ tps65910_dev = dev;
+#endif
+ return 0;
+}
+
+/*
+ * tps65910_set_i2c_control() - Set the TPS65910 to be controlled via the I2C
+ * interface.
+ * @return: 0 on success, not 0 on failure
+ */
+int tps65910_set_i2c_control(void)
+{
+ int ret;
+ uchar buf;
+
+ /* VDD1/2 voltage selection register access by control i/f */
+ ret = tps65910_read_reg(TPS65910_DEVCTRL_REG, &buf);
+
+ if (ret)
+ return ret;
+
+ buf |= TPS65910_DEVCTRL_REG_SR_CTL_I2C_SEL_CTL_I2C;
+
+ return tps65910_write_reg(TPS65910_DEVCTRL_REG, &buf);
+}
+
+/*
+ * tps65910_voltage_update() - Voltage switching for MPU frequency switching.
+ * @module: mpu - 0, core - 1
+ * @vddx_op_vol_sel: vdd voltage to set
+ * @return: 0 on success, not 0 on failure
+ */
+int tps65910_voltage_update(unsigned int module, unsigned char vddx_op_vol_sel)
+{
+ uchar buf;
+ unsigned int reg_offset;
+ int ret;
+
+ if (module == MPU)
+ reg_offset = TPS65910_VDD1_OP_REG;
+ else
+ reg_offset = TPS65910_VDD2_OP_REG;
+
+ /* Select VDDx OP */
+ ret = tps65910_read_reg(reg_offset, &buf);
+ if (ret)
+ return ret;
+
+ buf &= ~TPS65910_OP_REG_CMD_MASK;
+
+ ret = tps65910_write_reg(reg_offset, &buf);
+ if (ret)
+ return ret;
+
+ /* Configure VDDx OP Voltage */
+ ret = tps65910_read_reg(reg_offset, &buf);
+ if (ret)
+ return ret;
+
+ buf &= ~TPS65910_OP_REG_SEL_MASK;
+ buf |= vddx_op_vol_sel;
+
+ ret = tps65910_write_reg(reg_offset, &buf);
+ if (ret)
+ return ret;
+
+ ret = tps65910_read_reg(reg_offset, &buf);
+ if (ret)
+ return ret;
+
+ if ((buf & TPS65910_OP_REG_SEL_MASK) != vddx_op_vol_sel)
+ return 1;
+
+ return 0;
+}
diff --git a/roms/u-boot/drivers/power/pmic/pmic_tps65910_dm.c b/roms/u-boot/drivers/power/pmic/pmic_tps65910_dm.c
new file mode 100644
index 000000000..e03ddc98d
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/pmic_tps65910_dm.c
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) EETS GmbH, 2017, Felix Brack <f.brack@eets.ch>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <i2c.h>
+#include <log.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/tps65910_pmic.h>
+
+static const struct pmic_child_info pmic_children_info[] = {
+ { .prefix = "ldo_", .driver = TPS65910_LDO_DRIVER },
+ { .prefix = "buck_", .driver = TPS65910_BUCK_DRIVER },
+ { .prefix = "boost_", .driver = TPS65910_BOOST_DRIVER },
+ { },
+};
+
+static int pmic_tps65910_reg_count(struct udevice *dev)
+{
+ return TPS65910_NUM_REGS;
+}
+
+static int pmic_tps65910_write(struct udevice *dev, uint reg, const u8 *buffer,
+ int len)
+{
+ int ret;
+
+ ret = dm_i2c_write(dev, reg, buffer, len);
+ if (ret)
+ pr_err("%s write error on register %02x\n", dev->name, reg);
+
+ return ret;
+}
+
+static int pmic_tps65910_read(struct udevice *dev, uint reg, u8 *buffer,
+ int len)
+{
+ int ret;
+
+ ret = dm_i2c_read(dev, reg, buffer, len);
+ if (ret)
+ pr_err("%s read error on register %02x\n", dev->name, reg);
+
+ return ret;
+}
+
+static int pmic_tps65910_bind(struct udevice *dev)
+{
+ ofnode regulators_node;
+ int children;
+
+ regulators_node = dev_read_subnode(dev, "regulators");
+ if (!ofnode_valid(regulators_node)) {
+ debug("%s regulators subnode not found\n", dev->name);
+ return -EINVAL;
+ }
+
+ children = pmic_bind_children(dev, regulators_node, pmic_children_info);
+ if (!children)
+ debug("%s has no children (regulators)\n", dev->name);
+
+ return 0;
+}
+
+static int pmic_tps65910_probe(struct udevice *dev)
+{
+ /* use I2C control interface instead of I2C smartreflex interface to
+ * access smartrefelex registers VDD1_OP_REG, VDD1_SR_REG, VDD2_OP_REG
+ * and VDD2_SR_REG
+ */
+ return pmic_clrsetbits(dev, TPS65910_REG_DEVICE_CTRL, 0,
+ TPS65910_I2C_SEL_MASK);
+}
+
+static struct dm_pmic_ops pmic_tps65910_ops = {
+ .reg_count = pmic_tps65910_reg_count,
+ .read = pmic_tps65910_read,
+ .write = pmic_tps65910_write,
+};
+
+static const struct udevice_id pmic_tps65910_match[] = {
+ { .compatible = "ti,tps65910" },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(pmic_tps65910) = {
+ .name = "pmic_tps65910",
+ .id = UCLASS_PMIC,
+ .of_match = pmic_tps65910_match,
+ .bind = pmic_tps65910_bind,
+ .probe = pmic_tps65910_probe,
+ .ops = &pmic_tps65910_ops,
+};
diff --git a/roms/u-boot/drivers/power/pmic/rk8xx.c b/roms/u-boot/drivers/power/pmic/rk8xx.c
new file mode 100644
index 000000000..5f442fea6
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/rk8xx.c
@@ -0,0 +1,198 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <log.h>
+#include <power/rk8xx_pmic.h>
+#include <power/pmic.h>
+
+static struct reg_data rk817_init_reg[] = {
+/* enable the under-voltage protection,
+ * the under-voltage protection will shutdown the LDO3 and reset the PMIC
+ */
+ { RK817_BUCK4_CMIN, 0x60, 0x60},
+};
+
+static const struct pmic_child_info pmic_children_info[] = {
+ { .prefix = "DCDC_REG", .driver = "rk8xx_buck"},
+ { .prefix = "LDO_REG", .driver = "rk8xx_ldo"},
+ { .prefix = "SWITCH_REG", .driver = "rk8xx_switch"},
+ { },
+};
+
+static int rk8xx_reg_count(struct udevice *dev)
+{
+ return RK808_NUM_OF_REGS;
+}
+
+static int rk8xx_write(struct udevice *dev, uint reg, const uint8_t *buff,
+ int len)
+{
+ int ret;
+
+ ret = dm_i2c_write(dev, reg, buff, len);
+ if (ret) {
+ debug("write error to device: %p register: %#x!\n", dev, reg);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int rk8xx_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+ int ret;
+
+ ret = dm_i2c_read(dev, reg, buff, len);
+ if (ret) {
+ debug("read error from device: %p register: %#x!\n", dev, reg);
+ return ret;
+ }
+
+ return 0;
+}
+
+#if CONFIG_IS_ENABLED(PMIC_CHILDREN)
+static int rk8xx_bind(struct udevice *dev)
+{
+ ofnode regulators_node;
+ int children;
+
+ regulators_node = dev_read_subnode(dev, "regulators");
+ if (!ofnode_valid(regulators_node)) {
+ debug("%s: %s regulators subnode not found!\n", __func__,
+ dev->name);
+ return -ENXIO;
+ }
+
+ debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
+
+ children = pmic_bind_children(dev, regulators_node, pmic_children_info);
+ if (!children)
+ debug("%s: %s - no child found\n", __func__, dev->name);
+
+ /* Always return success for this device */
+ return 0;
+}
+#endif
+
+static int rk8xx_probe(struct udevice *dev)
+{
+ struct rk8xx_priv *priv = dev_get_priv(dev);
+ struct reg_data *init_data = NULL;
+ int init_data_num = 0;
+ int ret = 0, i, show_variant;
+ u8 msb, lsb, id_msb, id_lsb;
+ u8 on_source = 0, off_source = 0;
+ u8 power_en0, power_en1, power_en2, power_en3;
+ u8 value;
+
+ /* read Chip variant */
+ if (device_is_compatible(dev, "rockchip,rk817") ||
+ device_is_compatible(dev, "rockchip,rk809")) {
+ id_msb = RK817_ID_MSB;
+ id_lsb = RK817_ID_LSB;
+ } else {
+ id_msb = ID_MSB;
+ id_lsb = ID_LSB;
+ }
+
+ ret = rk8xx_read(dev, id_msb, &msb, 1);
+ if (ret)
+ return ret;
+ ret = rk8xx_read(dev, id_lsb, &lsb, 1);
+ if (ret)
+ return ret;
+
+ priv->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK;
+ show_variant = priv->variant;
+ switch (priv->variant) {
+ case RK808_ID:
+ show_variant = 0x808; /* RK808 hardware ID is 0 */
+ break;
+ case RK805_ID:
+ case RK816_ID:
+ case RK818_ID:
+ on_source = RK8XX_ON_SOURCE;
+ off_source = RK8XX_OFF_SOURCE;
+ break;
+ case RK809_ID:
+ case RK817_ID:
+ on_source = RK817_ON_SOURCE;
+ off_source = RK817_OFF_SOURCE;
+ init_data = rk817_init_reg;
+ init_data_num = ARRAY_SIZE(rk817_init_reg);
+ power_en0 = pmic_reg_read(dev, RK817_POWER_EN0);
+ power_en1 = pmic_reg_read(dev, RK817_POWER_EN1);
+ power_en2 = pmic_reg_read(dev, RK817_POWER_EN2);
+ power_en3 = pmic_reg_read(dev, RK817_POWER_EN3);
+
+ value = (power_en0 & 0x0f) | ((power_en1 & 0x0f) << 4);
+ pmic_reg_write(dev, RK817_POWER_EN_SAVE0, value);
+ value = (power_en2 & 0x0f) | ((power_en3 & 0x0f) << 4);
+ pmic_reg_write(dev, RK817_POWER_EN_SAVE1, value);
+ break;
+ default:
+ printf("Unknown PMIC: RK%x!!\n", priv->variant);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < init_data_num; i++) {
+ ret = pmic_clrsetbits(dev,
+ init_data[i].reg,
+ init_data[i].mask,
+ init_data[i].val);
+ if (ret < 0) {
+ printf("%s: i2c set reg 0x%x failed, ret=%d\n",
+ __func__, init_data[i].reg, ret);
+ }
+
+ debug("%s: reg[0x%x] = 0x%x\n", __func__, init_data[i].reg,
+ pmic_reg_read(dev, init_data[i].reg));
+ }
+
+ printf("PMIC: RK%x ", show_variant);
+
+ if (on_source && off_source)
+ printf("(on=0x%02x, off=0x%02x)",
+ pmic_reg_read(dev, on_source),
+ pmic_reg_read(dev, off_source));
+ printf("\n");
+
+ return 0;
+}
+
+static struct dm_pmic_ops rk8xx_ops = {
+ .reg_count = rk8xx_reg_count,
+ .read = rk8xx_read,
+ .write = rk8xx_write,
+};
+
+static const struct udevice_id rk8xx_ids[] = {
+ { .compatible = "rockchip,rk805" },
+ { .compatible = "rockchip,rk808" },
+ { .compatible = "rockchip,rk809" },
+ { .compatible = "rockchip,rk816" },
+ { .compatible = "rockchip,rk817" },
+ { .compatible = "rockchip,rk818" },
+ { }
+};
+
+U_BOOT_DRIVER(rockchip_rk805) = {
+ .name = "rockchip_rk805",
+ .id = UCLASS_PMIC,
+ .of_match = rk8xx_ids,
+#if CONFIG_IS_ENABLED(PMIC_CHILDREN)
+ .bind = rk8xx_bind,
+#endif
+ .priv_auto = sizeof(struct rk8xx_priv),
+ .probe = rk8xx_probe,
+ .ops = &rk8xx_ops,
+};
+
+DM_DRIVER_ALIAS(rockchip_rk805, rockchip_rk808)
diff --git a/roms/u-boot/drivers/power/pmic/rn5t567.c b/roms/u-boot/drivers/power/pmic/rn5t567.c
new file mode 100644
index 000000000..d9a8298eb
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/rn5t567.c
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016 Toradex AG
+ * Stefan Agner <stefan.agner@toradex.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <log.h>
+#include <linux/libfdt.h>
+#include <power/rn5t567_pmic.h>
+#include <power/pmic.h>
+
+static int rn5t567_reg_count(struct udevice *dev)
+{
+ return RN5T567_NUM_OF_REGS;
+}
+
+static int rn5t567_write(struct udevice *dev, uint reg, const uint8_t *buff,
+ int len)
+{
+ int ret;
+
+ ret = dm_i2c_write(dev, reg, buff, len);
+ if (ret) {
+ debug("write error to device: %p register: %#x!\n", dev, reg);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int rn5t567_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+ int ret;
+
+ ret = dm_i2c_read(dev, reg, buff, len);
+ if (ret) {
+ debug("read error from device: %p register: %#x!\n", dev, reg);
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct dm_pmic_ops rn5t567_ops = {
+ .reg_count = rn5t567_reg_count,
+ .read = rn5t567_read,
+ .write = rn5t567_write,
+};
+
+static const struct udevice_id rn5t567_ids[] = {
+ { .compatible = "ricoh,rn5t567" },
+ { }
+};
+
+U_BOOT_DRIVER(pmic_rn5t567) = {
+ .name = "rn5t567 pmic",
+ .id = UCLASS_PMIC,
+ .of_match = rn5t567_ids,
+ .ops = &rn5t567_ops,
+};
diff --git a/roms/u-boot/drivers/power/pmic/s2mps11.c b/roms/u-boot/drivers/power/pmic/s2mps11.c
new file mode 100644
index 000000000..1ba1640a8
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/s2mps11.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015 Samsung Electronics
+ * Przemyslaw Marczak <p.marczak@samsung.com>
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <errno.h>
+#include <dm.h>
+#include <i2c.h>
+#include <log.h>
+#include <power/pmic.h>
+#include <power/s2mps11.h>
+
+static const struct pmic_child_info pmic_children_info[] = {
+ { .prefix = S2MPS11_OF_LDO_PREFIX, .driver = S2MPS11_LDO_DRIVER },
+ { .prefix = S2MPS11_OF_BUCK_PREFIX, .driver = S2MPS11_BUCK_DRIVER },
+ { },
+};
+
+static int s2mps11_reg_count(struct udevice *dev)
+{
+ return S2MPS11_REG_COUNT;
+}
+
+static int s2mps11_write(struct udevice *dev, uint reg, const uint8_t *buff,
+ int len)
+{
+ int ret;
+
+ ret = dm_i2c_write(dev, reg, buff, len);
+ if (ret)
+ pr_err("write error to device: %p register: %#x!\n", dev, reg);
+
+ return ret;
+}
+
+static int s2mps11_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+ int ret;
+
+ ret = dm_i2c_read(dev, reg, buff, len);
+ if (ret)
+ pr_err("read error from device: %p register: %#x!\n", dev, reg);
+
+ return ret;
+}
+
+static int s2mps11_probe(struct udevice *dev)
+{
+ ofnode regulators_node;
+ int children;
+
+ regulators_node = dev_read_subnode(dev, "voltage-regulators");
+ if (!ofnode_valid(regulators_node)) {
+ debug("%s: %s regulators subnode not found!\n", __func__,
+ dev->name);
+ return -ENXIO;
+ }
+
+ debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
+
+ children = pmic_bind_children(dev, regulators_node, pmic_children_info);
+ if (!children)
+ debug("%s: %s - no child found\n", __func__, dev->name);
+
+ return 0;
+}
+
+static struct dm_pmic_ops s2mps11_ops = {
+ .reg_count = s2mps11_reg_count,
+ .read = s2mps11_read,
+ .write = s2mps11_write,
+};
+
+static const struct udevice_id s2mps11_ids[] = {
+ { .compatible = "samsung,s2mps11-pmic" },
+ { }
+};
+
+U_BOOT_DRIVER(pmic_s2mps11) = {
+ .name = "s2mps11_pmic",
+ .id = UCLASS_PMIC,
+ .of_match = s2mps11_ids,
+ .ops = &s2mps11_ops,
+ .probe = s2mps11_probe,
+};
diff --git a/roms/u-boot/drivers/power/pmic/s5m8767.c b/roms/u-boot/drivers/power/pmic/s5m8767.c
new file mode 100644
index 000000000..db6d0357e
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/s5m8767.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015 Google, Inc
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <errno.h>
+#include <dm.h>
+#include <i2c.h>
+#include <log.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/s5m8767.h>
+
+static const struct pmic_child_info pmic_children_info[] = {
+ { .prefix = "LDO", .driver = S5M8767_LDO_DRIVER },
+ { .prefix = "BUCK", .driver = S5M8767_BUCK_DRIVER },
+ { },
+};
+
+static int s5m8767_reg_count(struct udevice *dev)
+{
+ return S5M8767_NUM_OF_REGS;
+}
+
+static int s5m8767_write(struct udevice *dev, uint reg, const uint8_t *buff,
+ int len)
+{
+ if (dm_i2c_write(dev, reg, buff, len)) {
+ pr_err("write error to device: %p register: %#x!\n", dev, reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int s5m8767_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+ if (dm_i2c_read(dev, reg, buff, len)) {
+ pr_err("read error from device: %p register: %#x!\n", dev, reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+int s5m8767_enable_32khz_cp(struct udevice *dev)
+{
+ return pmic_clrsetbits(dev, S5M8767_EN32KHZ_CP, 0, 1 << 1);
+}
+
+static int s5m8767_bind(struct udevice *dev)
+{
+ int children;
+ ofnode node;
+
+ node = dev_read_subnode(dev, "regulators");
+ if (!ofnode_valid(node)) {
+ debug("%s: %s regulators subnode not found!\n", __func__,
+ dev->name);
+ return -ENXIO;
+ }
+
+ debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
+
+ children = pmic_bind_children(dev, node, pmic_children_info);
+ if (!children)
+ debug("%s: %s - no child found\n", __func__, dev->name);
+
+ /* Always return success for this device */
+ return 0;
+}
+
+static struct dm_pmic_ops s5m8767_ops = {
+ .reg_count = s5m8767_reg_count,
+ .read = s5m8767_read,
+ .write = s5m8767_write,
+};
+
+static const struct udevice_id s5m8767_ids[] = {
+ { .compatible = "samsung,s5m8767-pmic" },
+ { }
+};
+
+U_BOOT_DRIVER(pmic_s5m8767) = {
+ .name = "s5m8767_pmic",
+ .id = UCLASS_PMIC,
+ .of_match = s5m8767_ids,
+ .bind = s5m8767_bind,
+ .ops = &s5m8767_ops,
+};
diff --git a/roms/u-boot/drivers/power/pmic/sandbox.c b/roms/u-boot/drivers/power/pmic/sandbox.c
new file mode 100644
index 000000000..d7870915d
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/sandbox.c
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015 Samsung Electronics
+ * Przemyslaw Marczak <p.marczak@samsung.com>
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <errno.h>
+#include <dm.h>
+#include <i2c.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/sandbox_pmic.h>
+
+static const struct pmic_child_info pmic_children_info[] = {
+ { .prefix = SANDBOX_OF_LDO_PREFIX, .driver = SANDBOX_LDO_DRIVER },
+ { .prefix = SANDBOX_OF_BUCK_PREFIX, .driver = SANDBOX_BUCK_DRIVER },
+ { },
+};
+
+static int sandbox_pmic_reg_count(struct udevice *dev)
+{
+ return SANDBOX_PMIC_REG_COUNT;
+}
+
+static int sandbox_pmic_write(struct udevice *dev, uint reg,
+ const uint8_t *buff, int len)
+{
+ if (dm_i2c_write(dev, reg, buff, len)) {
+ pr_err("write error to device: %p register: %#x!\n", dev, reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int sandbox_pmic_read(struct udevice *dev, uint reg,
+ uint8_t *buff, int len)
+{
+ if (dm_i2c_read(dev, reg, buff, len)) {
+ pr_err("read error from device: %p register: %#x!\n", dev, reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int sandbox_pmic_bind(struct udevice *dev)
+{
+ if (!pmic_bind_children(dev, dev_ofnode(dev), pmic_children_info))
+ pr_err("%s:%d PMIC: %s - no child found!", __func__, __LINE__,
+ dev->name);
+
+ /* Always return success for this device - allows for PMIC I/O */
+ return 0;
+}
+
+static struct dm_pmic_ops sandbox_pmic_ops = {
+ .reg_count = sandbox_pmic_reg_count,
+ .read = sandbox_pmic_read,
+ .write = sandbox_pmic_write,
+};
+
+static const struct udevice_id sandbox_pmic_ids[] = {
+ { .compatible = "sandbox,pmic" },
+ { }
+};
+
+U_BOOT_DRIVER(sandbox_pmic) = {
+ .name = "sandbox_pmic",
+ .id = UCLASS_PMIC,
+ .of_match = sandbox_pmic_ids,
+ .bind = sandbox_pmic_bind,
+ .ops = &sandbox_pmic_ops,
+};
diff --git a/roms/u-boot/drivers/power/pmic/stpmic1.c b/roms/u-boot/drivers/power/pmic/stpmic1.c
new file mode 100644
index 000000000..2c85410b1
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/stpmic1.c
@@ -0,0 +1,269 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <i2c.h>
+#include <misc.h>
+#include <sysreset.h>
+#include <time.h>
+#include <dm/device.h>
+#include <dm/device_compat.h>
+#include <dm/lists.h>
+#include <power/pmic.h>
+#include <power/stpmic1.h>
+
+#define STPMIC1_NUM_OF_REGS 0x100
+
+#define STPMIC1_NVM_SIZE 8
+#define STPMIC1_NVM_POLL_TIMEOUT 100000
+#define STPMIC1_NVM_START_ADDRESS 0xf8
+
+enum pmic_nvm_op {
+ SHADOW_READ,
+ SHADOW_WRITE,
+ NVM_READ,
+ NVM_WRITE,
+};
+
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
+static const struct pmic_child_info stpmic1_children_info[] = {
+ { .prefix = "ldo", .driver = "stpmic1_ldo" },
+ { .prefix = "buck", .driver = "stpmic1_buck" },
+ { .prefix = "vref_ddr", .driver = "stpmic1_vref_ddr" },
+ { .prefix = "pwr_sw", .driver = "stpmic1_pwr_sw" },
+ { .prefix = "boost", .driver = "stpmic1_boost" },
+ { },
+};
+#endif /* DM_REGULATOR */
+
+static int stpmic1_reg_count(struct udevice *dev)
+{
+ return STPMIC1_NUM_OF_REGS;
+}
+
+static int stpmic1_write(struct udevice *dev, uint reg, const uint8_t *buff,
+ int len)
+{
+ int ret;
+
+ ret = dm_i2c_write(dev, reg, buff, len);
+ if (ret)
+ dev_err(dev, "%s: failed to write register %#x :%d",
+ __func__, reg, ret);
+
+ return ret;
+}
+
+static int stpmic1_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+ int ret;
+
+ ret = dm_i2c_read(dev, reg, buff, len);
+ if (ret)
+ dev_err(dev, "%s: failed to read register %#x : %d",
+ __func__, reg, ret);
+
+ return ret;
+}
+
+static int stpmic1_bind(struct udevice *dev)
+{
+ int ret;
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
+ ofnode regulators_node;
+ int children;
+
+ regulators_node = dev_read_subnode(dev, "regulators");
+ if (!ofnode_valid(regulators_node)) {
+ dev_dbg(dev, "regulators subnode not found!");
+ return -ENXIO;
+ }
+ dev_dbg(dev, "found regulators subnode\n");
+
+ children = pmic_bind_children(dev, regulators_node,
+ stpmic1_children_info);
+ if (!children)
+ dev_dbg(dev, "no child found\n");
+#endif /* DM_REGULATOR */
+
+ if (!IS_ENABLED(CONFIG_SPL_BUILD)) {
+ ret = device_bind_driver(dev, "stpmic1-nvm",
+ "stpmic1-nvm", NULL);
+ if (ret)
+ return ret;
+ }
+
+ if (CONFIG_IS_ENABLED(SYSRESET))
+ return device_bind_driver(dev, "stpmic1-sysreset",
+ "stpmic1-sysreset", NULL);
+
+ return 0;
+}
+
+static struct dm_pmic_ops stpmic1_ops = {
+ .reg_count = stpmic1_reg_count,
+ .read = stpmic1_read,
+ .write = stpmic1_write,
+};
+
+static const struct udevice_id stpmic1_ids[] = {
+ { .compatible = "st,stpmic1" },
+ { }
+};
+
+U_BOOT_DRIVER(pmic_stpmic1) = {
+ .name = "stpmic1_pmic",
+ .id = UCLASS_PMIC,
+ .of_match = stpmic1_ids,
+ .bind = stpmic1_bind,
+ .ops = &stpmic1_ops,
+};
+
+#ifndef CONFIG_SPL_BUILD
+static int stpmic1_nvm_rw(struct udevice *dev, u8 addr, u8 *buf, int buf_len,
+ enum pmic_nvm_op op)
+{
+ unsigned long timeout;
+ u8 cmd = STPMIC1_NVM_CMD_READ;
+ int ret, len = buf_len;
+
+ if (addr < STPMIC1_NVM_START_ADDRESS)
+ return -EACCES;
+ if (addr + buf_len > STPMIC1_NVM_START_ADDRESS + STPMIC1_NVM_SIZE)
+ len = STPMIC1_NVM_START_ADDRESS + STPMIC1_NVM_SIZE - addr;
+
+ if (op == SHADOW_READ) {
+ ret = pmic_read(dev, addr, buf, len);
+ if (ret < 0)
+ return ret;
+ else
+ return len;
+ }
+
+ if (op == SHADOW_WRITE) {
+ ret = pmic_write(dev, addr, buf, len);
+ if (ret < 0)
+ return ret;
+ else
+ return len;
+ }
+
+ if (op == NVM_WRITE) {
+ cmd = STPMIC1_NVM_CMD_PROGRAM;
+
+ ret = pmic_write(dev, addr, buf, len);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = pmic_reg_read(dev, STPMIC1_NVM_CR);
+ if (ret < 0)
+ return ret;
+
+ ret = pmic_reg_write(dev, STPMIC1_NVM_CR, ret | cmd);
+ if (ret < 0)
+ return ret;
+
+ timeout = timer_get_us() + STPMIC1_NVM_POLL_TIMEOUT;
+ for (;;) {
+ ret = pmic_reg_read(dev, STPMIC1_NVM_SR);
+ if (ret < 0)
+ return ret;
+
+ if (!(ret & STPMIC1_NVM_BUSY))
+ break;
+
+ if (time_after(timer_get_us(), timeout))
+ break;
+ }
+
+ if (ret & STPMIC1_NVM_BUSY)
+ return -ETIMEDOUT;
+
+ if (op == NVM_READ) {
+ ret = pmic_read(dev, addr, buf, len);
+ if (ret < 0)
+ return ret;
+ }
+
+ return len;
+}
+
+static int stpmic1_nvm_read(struct udevice *dev, int offset,
+ void *buf, int size)
+{
+ enum pmic_nvm_op op = NVM_READ;
+
+ if (offset < 0) {
+ op = SHADOW_READ;
+ offset = -offset;
+ }
+
+ return stpmic1_nvm_rw(dev->parent, offset, buf, size, op);
+}
+
+static int stpmic1_nvm_write(struct udevice *dev, int offset,
+ const void *buf, int size)
+{
+ enum pmic_nvm_op op = NVM_WRITE;
+
+ if (offset < 0) {
+ op = SHADOW_WRITE;
+ offset = -offset;
+ }
+
+ return stpmic1_nvm_rw(dev->parent, offset, (void *)buf, size, op);
+}
+
+static const struct misc_ops stpmic1_nvm_ops = {
+ .read = stpmic1_nvm_read,
+ .write = stpmic1_nvm_write,
+};
+
+U_BOOT_DRIVER(stpmic1_nvm) = {
+ .name = "stpmic1-nvm",
+ .id = UCLASS_MISC,
+ .ops = &stpmic1_nvm_ops,
+};
+#endif /* CONFIG_SPL_BUILD */
+
+#ifdef CONFIG_SYSRESET
+static int stpmic1_sysreset_request(struct udevice *dev, enum sysreset_t type)
+{
+ struct udevice *pmic_dev = dev->parent;
+ int ret;
+
+ if (type != SYSRESET_POWER && type != SYSRESET_POWER_OFF)
+ return -EPROTONOSUPPORT;
+
+ ret = pmic_reg_read(pmic_dev, STPMIC1_MAIN_CR);
+ if (ret < 0)
+ return ret;
+
+ ret |= STPMIC1_SWOFF;
+ ret &= ~STPMIC1_RREQ_EN;
+ /* request Power Cycle */
+ if (type == SYSRESET_POWER)
+ ret |= STPMIC1_RREQ_EN;
+
+ ret = pmic_reg_write(pmic_dev, STPMIC1_MAIN_CR, ret);
+ if (ret < 0)
+ return ret;
+
+ return -EINPROGRESS;
+}
+
+static struct sysreset_ops stpmic1_sysreset_ops = {
+ .request = stpmic1_sysreset_request,
+};
+
+U_BOOT_DRIVER(stpmic1_sysreset) = {
+ .name = "stpmic1-sysreset",
+ .id = UCLASS_SYSRESET,
+ .ops = &stpmic1_sysreset_ops,
+};
+#endif
diff --git a/roms/u-boot/drivers/power/pmic/tps65090.c b/roms/u-boot/drivers/power/pmic/tps65090.c
new file mode 100644
index 000000000..b81df0dff
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/tps65090.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <i2c.h>
+#include <log.h>
+#include <power/pmic.h>
+#include <power/tps65090.h>
+
+static const struct pmic_child_info pmic_children_info[] = {
+ { .prefix = "fet", .driver = TPS65090_FET_DRIVER },
+ { },
+};
+
+static int tps65090_reg_count(struct udevice *dev)
+{
+ return TPS65090_NUM_REGS;
+}
+
+static int tps65090_write(struct udevice *dev, uint reg, const uint8_t *buff,
+ int len)
+{
+ if (dm_i2c_write(dev, reg, buff, len)) {
+ pr_err("write error to device: %p register: %#x!\n", dev, reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int tps65090_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+ int ret;
+
+ ret = dm_i2c_read(dev, reg, buff, len);
+ if (ret) {
+ pr_err("read error %d from device: %p register: %#x!\n", ret,
+ dev, reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int tps65090_bind(struct udevice *dev)
+{
+ ofnode regulators_node;
+ int children;
+
+ regulators_node = dev_read_subnode(dev, "regulators");
+ if (!ofnode_valid(regulators_node)) {
+ debug("%s: %s regulators subnode not found!\n", __func__,
+ dev->name);
+ return -ENXIO;
+ }
+
+ debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
+
+ children = pmic_bind_children(dev, regulators_node, pmic_children_info);
+ if (!children)
+ debug("%s: %s - no child found\n", __func__, dev->name);
+
+ /* Always return success for this device */
+ return 0;
+}
+
+static struct dm_pmic_ops tps65090_ops = {
+ .reg_count = tps65090_reg_count,
+ .read = tps65090_read,
+ .write = tps65090_write,
+};
+
+static const struct udevice_id tps65090_ids[] = {
+ { .compatible = "ti,tps65090" },
+ { }
+};
+
+U_BOOT_DRIVER(pmic_tps65090) = {
+ .name = "tps65090 pmic",
+ .id = UCLASS_PMIC,
+ .of_match = tps65090_ids,
+ .bind = tps65090_bind,
+ .ops = &tps65090_ops,
+};
diff --git a/roms/u-boot/drivers/power/pmic/tps65941.c b/roms/u-boot/drivers/power/pmic/tps65941.c
new file mode 100644
index 000000000..3dfc1918d
--- /dev/null
+++ b/roms/u-boot/drivers/power/pmic/tps65941.c
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2019 Texas Instruments Incorporated, <www.ti.com>
+ * Keerthy <j-keerthy@ti.com>
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <errno.h>
+#include <dm.h>
+#include <i2c.h>
+#include <log.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/tps65941.h>
+#include <dm/device.h>
+
+static const struct pmic_child_info pmic_children_info[] = {
+ { .prefix = "ldo", .driver = TPS65941_LDO_DRIVER },
+ { .prefix = "buck", .driver = TPS65941_BUCK_DRIVER },
+ { },
+};
+
+static int tps65941_write(struct udevice *dev, uint reg, const uint8_t *buff,
+ int len)
+{
+ if (dm_i2c_write(dev, reg, buff, len)) {
+ pr_err("write error to device: %p register: %#x!\n", dev, reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int tps65941_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+ if (dm_i2c_read(dev, reg, buff, len)) {
+ pr_err("read error from device: %p register: %#x!\n", dev, reg);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int tps65941_bind(struct udevice *dev)
+{
+ ofnode regulators_node;
+ int children;
+
+ regulators_node = dev_read_subnode(dev, "regulators");
+ if (!ofnode_valid(regulators_node)) {
+ debug("%s: %s regulators subnode not found!\n", __func__,
+ dev->name);
+ return -ENXIO;
+ }
+
+ debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
+
+ children = pmic_bind_children(dev, regulators_node, pmic_children_info);
+ if (!children)
+ printf("%s: %s - no child found\n", __func__, dev->name);
+
+ /* Probe all the child devices */
+ return dm_scan_fdt_dev(dev);
+}
+
+static struct dm_pmic_ops tps65941_ops = {
+ .read = tps65941_read,
+ .write = tps65941_write,
+};
+
+static const struct udevice_id tps65941_ids[] = {
+ { .compatible = "ti,tps659411", .data = TPS659411 },
+ { .compatible = "ti,tps659413", .data = TPS659413 },
+ { }
+};
+
+U_BOOT_DRIVER(pmic_tps65941) = {
+ .name = "tps65941_pmic",
+ .id = UCLASS_PMIC,
+ .of_match = tps65941_ids,
+ .bind = tps65941_bind,
+ .ops = &tps65941_ops,
+};