* [PATCH v9 0/8] Add support for PMICs used on Tegra 3 devices
@ 2023-10-27 8:26 Svyatoslav Ryhel
2023-10-27 8:26 ` [PATCH v9 1/8] power: pmic: palmas: support TI TPS65913 PMIC Svyatoslav Ryhel
` (7 more replies)
0 siblings, 8 replies; 14+ messages in thread
From: Svyatoslav Ryhel @ 2023-10-27 8:26 UTC (permalink / raw)
To: Tom Rini, Jaehoon Chung, Simon Glass, Svyatoslav Ryhel; +Cc: u-boot
Patch set adds basic support for PMICs used in many Tegra 3 devices.
All PMIC drivers are based on datasheets provided by vendors.
Implemented API include regulator set/get voltage enable/disable and
basic PMIC r/w capabilities.
Drivers were tested by me on LG P895 (max77663), HTC One X (TPS80032)
and ASUS TF300T (tps65911). Calculations and behavior were correct,
predictable and reproducible.
Poweroff functional will be added after this basic drivers are merged.
---
Changes from v8:
- dropped common.h
- decreased amount of inclusions
Changes from v7:
- no activity for 3 weeks, no changes, re-sending
Changes from v6:
- no changes, re-sending
Changes from v5:
- pass tps6591x regulator children directly via udevice_id data field
Changes from v4:
- used private structure for TPS80031 SPMS driver so that internal
flags do not interfere with those from dm_regulator_uclass_plat
- fixed detection on ldoln and ldousb for palmas ldo driver
Changes from v3:
- expanded descriptions in Kconfigs for pmics and regulators
- replaced ret with other variable name if it is not used for return
- dropped prefixed with pmic name
- dropped () in ~(var) type expressions
- return dm_i2c_* output in pmic_read/write functions
- switched to log_debug in some places
- added descryptions for some "non obvious" functions
- fixed tps80031 spms voltage calculation in non linear region
- adjsuted tps65911 vio voltage calculation
Changes from v2:
- removed all previously made poweroff API in favour to use sysreset
after this patchset is accepted
Changes from v1:
- created poweroff API for PMIC and integrated it call into do_poweroff
- added poweroff function to submitted max77663, tps80032 and tps65911
drivers
- fixed registers asignments for regulators with non-numeric name
(ldoln, ldousb, vddctrl)
---
Svyatoslav Ryhel (8):
power: pmic: palmas: support TI TPS65913 PMIC
power: regulator: palmas: fix ldoln and ldousb detection
power: pmic: add the base MAX77663 PMIC support
power: regulator: max77663: add regulator support
power: pmic: add the base TPS80031 PMIC support
power: regulator: tps80031: add regulator support
power: pmic: tps65910: add TPS65911 PMIC support
power: regulator: tps65911: add regulator support
doc/device-tree-bindings/pmic/max77663.txt | 84 ++++
doc/device-tree-bindings/pmic/tps65911.txt | 78 ++++
doc/device-tree-bindings/pmic/tps80031.txt | 76 ++++
drivers/power/pmic/Kconfig | 20 +
drivers/power/pmic/Makefile | 2 +
drivers/power/pmic/max77663.c | 81 ++++
drivers/power/pmic/palmas.c | 1 +
drivers/power/pmic/pmic_tps65910_dm.c | 15 +-
drivers/power/pmic/tps80031.c | 82 ++++
drivers/power/regulator/Kconfig | 28 ++
drivers/power/regulator/Makefile | 3 +
drivers/power/regulator/max77663_regulator.c | 375 ++++++++++++++++++
drivers/power/regulator/palmas_regulator.c | 24 +-
drivers/power/regulator/tps65911_regulator.c | 395 +++++++++++++++++++
drivers/power/regulator/tps80031_regulator.c | 347 ++++++++++++++++
include/power/max77663.h | 42 ++
include/power/tps65910_pmic.h | 44 +++
include/power/tps80031.h | 45 +++
18 files changed, 1729 insertions(+), 13 deletions(-)
create mode 100644 doc/device-tree-bindings/pmic/max77663.txt
create mode 100644 doc/device-tree-bindings/pmic/tps65911.txt
create mode 100644 doc/device-tree-bindings/pmic/tps80031.txt
create mode 100644 drivers/power/pmic/max77663.c
create mode 100644 drivers/power/pmic/tps80031.c
create mode 100644 drivers/power/regulator/max77663_regulator.c
create mode 100644 drivers/power/regulator/tps65911_regulator.c
create mode 100644 drivers/power/regulator/tps80031_regulator.c
create mode 100644 include/power/max77663.h
create mode 100644 include/power/tps80031.h
--
2.39.2
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v9 1/8] power: pmic: palmas: support TI TPS65913 PMIC
2023-10-27 8:26 [PATCH v9 0/8] Add support for PMICs used on Tegra 3 devices Svyatoslav Ryhel
@ 2023-10-27 8:26 ` Svyatoslav Ryhel
2023-10-31 6:44 ` Jaehoon Chung
2023-11-04 13:57 ` Tom Rini
2023-10-27 8:26 ` [PATCH v9 2/8] power: regulator: palmas: fix ldoln and ldousb detection Svyatoslav Ryhel
` (6 subsequent siblings)
7 siblings, 2 replies; 14+ messages in thread
From: Svyatoslav Ryhel @ 2023-10-27 8:26 UTC (permalink / raw)
To: Tom Rini, Jaehoon Chung, Simon Glass, Svyatoslav Ryhel; +Cc: u-boot
Existing PALMAS PMIC driver is fully compatible with TI TPS65913
PMIC found in many Tegra 4 devices, like Tegra Note 7 and ASUS
TF701T. TPS65913 shares same structure of regulators like TPS659038
so data can be reused.
Tested-by: Svyatoslav Ryhel <clamor95@gmail.com> # NVIDIA Tegratab
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
drivers/power/pmic/palmas.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/power/pmic/palmas.c b/drivers/power/pmic/palmas.c
index eb83c88d56..b2e8a2930c 100644
--- a/drivers/power/pmic/palmas.c
+++ b/drivers/power/pmic/palmas.c
@@ -88,6 +88,7 @@ static struct dm_pmic_ops palmas_ops = {
static const struct udevice_id palmas_ids[] = {
{ .compatible = "ti,tps659038", .data = TPS659038 },
+ { .compatible = "ti,tps65913" , .data = TPS659038 },
{ .compatible = "ti,tps65917" , .data = TPS65917 },
{ }
};
--
2.39.2
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v9 2/8] power: regulator: palmas: fix ldoln and ldousb detection
2023-10-27 8:26 [PATCH v9 0/8] Add support for PMICs used on Tegra 3 devices Svyatoslav Ryhel
2023-10-27 8:26 ` [PATCH v9 1/8] power: pmic: palmas: support TI TPS65913 PMIC Svyatoslav Ryhel
@ 2023-10-27 8:26 ` Svyatoslav Ryhel
2023-10-27 8:26 ` [PATCH v9 3/8] power: pmic: add the base MAX77663 PMIC support Svyatoslav Ryhel
` (5 subsequent siblings)
7 siblings, 0 replies; 14+ messages in thread
From: Svyatoslav Ryhel @ 2023-10-27 8:26 UTC (permalink / raw)
To: Tom Rini, Jaehoon Chung, Simon Glass, Svyatoslav Ryhel; +Cc: u-boot
dev->driver_data will carry the tail of ldo if there is a number and
if there is no number it will be an error code, anyway it will not be
zero. This results in a wrong ldo regulator detection.
To avoid this check for non-numerical ldo first and then manipulate
dev->driver_data.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
drivers/power/regulator/palmas_regulator.c | 24 +++++++++++++---------
1 file changed, 14 insertions(+), 10 deletions(-)
diff --git a/drivers/power/regulator/palmas_regulator.c b/drivers/power/regulator/palmas_regulator.c
index 3c4eb83be7..d615e94734 100644
--- a/drivers/power/regulator/palmas_regulator.c
+++ b/drivers/power/regulator/palmas_regulator.c
@@ -301,19 +301,23 @@ static int palmas_ldo_probe(struct udevice *dev)
uc_pdata->type = REGULATOR_TYPE_LDO;
- if (dev->driver_data) {
+ /* check for ldoln and ldousb cases */
+ if (!strcmp("ldoln", dev->name)) {
+ uc_pdata->ctrl_reg = palmas_ldo_ctrl[type][9];
+ uc_pdata->volt_reg = palmas_ldo_volt[type][9];
+ return 0;
+ }
+
+ if (!strcmp("ldousb", dev->name)) {
+ uc_pdata->ctrl_reg = palmas_ldo_ctrl[type][10];
+ uc_pdata->volt_reg = palmas_ldo_volt[type][10];
+ return 0;
+ }
+
+ if (dev->driver_data > 0) {
u8 idx = dev->driver_data - 1;
uc_pdata->ctrl_reg = palmas_ldo_ctrl[type][idx];
uc_pdata->volt_reg = palmas_ldo_volt[type][idx];
- } else {
- /* check for ldoln and ldousb cases */
- if (!strcmp("ldoln", dev->name)) {
- uc_pdata->ctrl_reg = palmas_ldo_ctrl[type][9];
- uc_pdata->volt_reg = palmas_ldo_volt[type][9];
- } else if (!strcmp("ldousb", dev->name)) {
- uc_pdata->ctrl_reg = palmas_ldo_ctrl[type][10];
- uc_pdata->volt_reg = palmas_ldo_volt[type][10];
- }
}
return 0;
--
2.39.2
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v9 3/8] power: pmic: add the base MAX77663 PMIC support
2023-10-27 8:26 [PATCH v9 0/8] Add support for PMICs used on Tegra 3 devices Svyatoslav Ryhel
2023-10-27 8:26 ` [PATCH v9 1/8] power: pmic: palmas: support TI TPS65913 PMIC Svyatoslav Ryhel
2023-10-27 8:26 ` [PATCH v9 2/8] power: regulator: palmas: fix ldoln and ldousb detection Svyatoslav Ryhel
@ 2023-10-27 8:26 ` Svyatoslav Ryhel
2023-10-31 8:57 ` Jaehoon Chung
2023-10-27 8:26 ` [PATCH v9 4/8] power: regulator: max77663: add regulator support Svyatoslav Ryhel
` (4 subsequent siblings)
7 siblings, 1 reply; 14+ messages in thread
From: Svyatoslav Ryhel @ 2023-10-27 8:26 UTC (permalink / raw)
To: Tom Rini, Jaehoon Chung, Simon Glass, Svyatoslav Ryhel; +Cc: u-boot
Add support to bind the regulators/child nodes with the pmic.
Also adds the pmic i2c based read/write functions to access pmic
registers.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
doc/device-tree-bindings/pmic/max77663.txt | 84 ++++++++++++++++++++++
drivers/power/pmic/Kconfig | 9 +++
drivers/power/pmic/Makefile | 1 +
drivers/power/pmic/max77663.c | 81 +++++++++++++++++++++
include/power/max77663.h | 42 +++++++++++
5 files changed, 217 insertions(+)
create mode 100644 doc/device-tree-bindings/pmic/max77663.txt
create mode 100644 drivers/power/pmic/max77663.c
create mode 100644 include/power/max77663.h
diff --git a/doc/device-tree-bindings/pmic/max77663.txt b/doc/device-tree-bindings/pmic/max77663.txt
new file mode 100644
index 0000000000..ddb7d3eb14
--- /dev/null
+++ b/doc/device-tree-bindings/pmic/max77663.txt
@@ -0,0 +1,84 @@
+MAXIM, MAX77663 PMIC
+
+This device uses two drivers:
+- drivers/power/pmic/max77663.c (for parent device)
+- drivers/power/regulator/max77663_regulator.c (for child regulators)
+
+This chapter describes the binding info for the PMIC driver and regulators.
+
+Required properties for PMIC:
+- compatible: "maxim,max77663"
+- reg: usually 0x1c or 0x3c
+
+With those two properties, the pmic device can be used for read/write only.
+To bind each regulator, the optional regulators subnode should exists.
+
+Optional subnode:
+- name: regulators (subnode list of each device's regulator)
+
+Regulators subnode contains set on supported regulators.
+
+Required properties:
+- regulator-name: used for regulator uclass platform data '.name',
+
+List of supported regulator nodes names for max77663:
+- sd0, sd1, sd2, sd3, ldo0, ldo1, ldo2, ldo3, ldo4, ldo5, ldo6, ldo7, ldo8
+
+Optional:
+- regulator-min-microvolt: minimum allowed Voltage to set
+- regulator-max-microvolt: minimum allowed Voltage to set
+- regulator-always-on: regulator should be never disabled
+- regulator-boot-on: regulator should be enabled by the bootloader
+
+Linux driver binding for this driver is compatible.
+
+Example:
+
+max77663@1c {
+ compatible = "maxim,max77663";
+ reg = <0x1c>;
+
+ regulators {
+ sd0 {
+ regulator-name = "vdd_cpu";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1250000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ ...
+
+ ldo0 {
+ regulator-name = "avdd_pll";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ ...
+
+ ldo2 {
+ regulator-name = "avdd_usb";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ ldo3 {
+ regulator-name = "vdd_sdmmc3";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ ...
+
+ ldo8 {
+ regulator-name = "avdd_dsi_csi";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+ };
+};
diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig
index 4a6f0ce093..54665d7e2b 100644
--- a/drivers/power/pmic/Kconfig
+++ b/drivers/power/pmic/Kconfig
@@ -184,6 +184,15 @@ config SPL_DM_PMIC_PFUZE100
This config enables implementation of driver-model pmic uclass features
for PMIC PFUZE100 in SPL. The driver implements read/write operations.
+config DM_PMIC_MAX77663
+ bool "Enable Driver Model for PMIC MAX77663"
+ ---help---
+ This config enables implementation of driver-model pmic uclass features
+ for PMIC MAX77663. The driver implements read/write operations.
+ This is a Power Management IC with a decent set of peripherals from which
+ 4 DC-to-DC Step-Down (SD) Regulators, 9 Low-Dropout Linear (LDO) Regulators,
+ 8 GPIOs, Real-Time Clock (RTC) and more with I2C Compatible Interface.
+
config DM_PMIC_MAX77686
bool "Enable Driver Model for PMIC MAX77686"
---help---
diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile
index 0b3b3d62d0..414a9d8225 100644
--- a/drivers/power/pmic/Makefile
+++ b/drivers/power/pmic/Makefile
@@ -6,6 +6,7 @@
obj-$(CONFIG_$(SPL_TPL_)DM_PMIC) += pmic-uclass.o
obj-$(CONFIG_$(SPL_)DM_PMIC_FAN53555) += fan53555.o
obj-$(CONFIG_$(SPL_)DM_PMIC_DA9063) += da9063.o
+obj-$(CONFIG_$(SPL_)DM_PMIC_MAX77663) += max77663.o
obj-$(CONFIG_DM_PMIC_MAX77686) += max77686.o
obj-$(CONFIG_DM_PMIC_MAX8998) += max8998.o
obj-$(CONFIG_DM_PMIC_MC34708) += mc34708.o
diff --git a/drivers/power/pmic/max77663.c b/drivers/power/pmic/max77663.c
new file mode 100644
index 0000000000..fac97ed221
--- /dev/null
+++ b/drivers/power/pmic/max77663.c
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright(C) 2023 Svyatoslav Ryhel <clamor95@gmail.com>
+ */
+
+#include <dm.h>
+#include <dm/lists.h>
+#include <power/pmic.h>
+#include <power/max77663.h>
+
+static const struct pmic_child_info pmic_children_info[] = {
+ { .prefix = "ldo", .driver = MAX77663_LDO_DRIVER },
+ { .prefix = "sd", .driver = MAX77663_SD_DRIVER },
+ { },
+};
+
+static int max77663_write(struct udevice *dev, uint reg, const uint8_t *buff,
+ int len)
+{
+ int ret;
+
+ ret = dm_i2c_write(dev, reg, buff, len);
+ if (ret) {
+ log_debug("write error to device: %p register: %#x!\n", dev, reg);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int max77663_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+ int ret;
+
+ ret = dm_i2c_read(dev, reg, buff, len);
+ if (ret) {
+ log_debug("read error from device: %p register: %#x!\n", dev, reg);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int max77663_bind(struct udevice *dev)
+{
+ ofnode regulators_node;
+ int children;
+
+ regulators_node = dev_read_subnode(dev, "regulators");
+ if (!ofnode_valid(regulators_node)) {
+ log_err("%s regulators subnode not found!\n", 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)
+ log_err("%s - no child found\n", dev->name);
+
+ /* Always return success for this device */
+ return 0;
+}
+
+static struct dm_pmic_ops max77663_ops = {
+ .read = max77663_read,
+ .write = max77663_write,
+};
+
+static const struct udevice_id max77663_ids[] = {
+ { .compatible = "maxim,max77663" },
+ { }
+};
+
+U_BOOT_DRIVER(pmic_max77663) = {
+ .name = "max77663_pmic",
+ .id = UCLASS_PMIC,
+ .of_match = max77663_ids,
+ .bind = max77663_bind,
+ .ops = &max77663_ops,
+};
diff --git a/include/power/max77663.h b/include/power/max77663.h
new file mode 100644
index 0000000000..0f764bcbcc
--- /dev/null
+++ b/include/power/max77663.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright(C) 2023 Svyatoslav Ryhel <clamor95@gmail.com>
+ */
+
+#ifndef _MAX77663_H_
+#define _MAX77663_H_
+
+#define MAX77663_LDO_NUM 9
+#define MAX77663_SD_NUM 5
+
+/* Drivers name */
+#define MAX77663_LDO_DRIVER "max77663_ldo"
+#define MAX77663_SD_DRIVER "max77663_sd"
+
+/* Step-Down (SD) Regulator calculations */
+#define SD_STATUS_MASK 0x30
+
+#define SD0_VOLT_MAX_HEX 0x40
+#define SD1_VOLT_MAX_HEX 0x4c
+#define SD_VOLT_MAX_HEX 0xff
+#define SD_VOLT_MIN_HEX 0x02
+
+#define SD0_VOLT_MAX 1400000
+#define SD1_VOLT_MAX 1550000
+#define SD_VOLT_MAX 3787500
+#define SD_VOLT_MIN 625000
+
+#define SD_VOLT_BASE 600000
+
+/* Low-Dropout Linear (LDO) Regulator calculations */
+#define LDO_STATUS_MASK 0xc0
+#define LDO_VOLT_MASK 0x3f
+#define LDO_VOLT_MAX_HEX 0x3f
+
+#define LDO01_VOLT_MAX 2375000
+#define LDO4_VOLT_MAX 1587500
+#define LDO_VOLT_MAX 3950000
+
+#define LDO_VOLT_BASE 800000
+
+#endif /* _MAX77663_H_ */
--
2.39.2
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v9 4/8] power: regulator: max77663: add regulator support
2023-10-27 8:26 [PATCH v9 0/8] Add support for PMICs used on Tegra 3 devices Svyatoslav Ryhel
` (2 preceding siblings ...)
2023-10-27 8:26 ` [PATCH v9 3/8] power: pmic: add the base MAX77663 PMIC support Svyatoslav Ryhel
@ 2023-10-27 8:26 ` Svyatoslav Ryhel
2023-10-31 8:58 ` Jaehoon Chung
2023-10-27 8:26 ` [PATCH v9 5/8] power: pmic: add the base TPS80031 PMIC support Svyatoslav Ryhel
` (3 subsequent siblings)
7 siblings, 1 reply; 14+ messages in thread
From: Svyatoslav Ryhel @ 2023-10-27 8:26 UTC (permalink / raw)
To: Tom Rini, Jaehoon Chung, Simon Glass, Svyatoslav Ryhel; +Cc: u-boot
The driver provides regulator set/get voltage
enable/disable functions for MAXIM MAX77663 PMICs.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
drivers/power/regulator/Kconfig | 9 +
drivers/power/regulator/Makefile | 1 +
drivers/power/regulator/max77663_regulator.c | 375 +++++++++++++++++++
3 files changed, 385 insertions(+)
create mode 100644 drivers/power/regulator/max77663_regulator.c
diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig
index eb5aa38c1c..581816294c 100644
--- a/drivers/power/regulator/Kconfig
+++ b/drivers/power/regulator/Kconfig
@@ -141,6 +141,15 @@ config SPL_REGULATOR_PWM
This config enables implementation of driver-model regulator uclass
features for PWM regulators in SPL.
+config DM_REGULATOR_MAX77663
+ bool "Enable Driver Model for REGULATOR MAX77663"
+ depends on DM_REGULATOR && DM_PMIC_MAX77663
+ ---help---
+ This config enables implementation of driver-model regulator uclass
+ features for REGULATOR MAX77663. The driver supports both DC-to-DC
+ Step-Down (SD) Regulators and Low-Dropout Linear (LDO) Regulators
+ found in MAX77663 PMIC and implements get/set api for value and enable.
+
config DM_REGULATOR_MAX77686
bool "Enable Driver Model for REGULATOR MAX77686"
depends on DM_REGULATOR && DM_PMIC_MAX77686
diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile
index d9e0cd5949..8d73169b50 100644
--- a/drivers/power/regulator/Makefile
+++ b/drivers/power/regulator/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_REGULATOR_AS3722) += as3722_regulator.o
obj-$(CONFIG_$(SPL_)REGULATOR_AXP) += axp_regulator.o
obj-$(CONFIG_$(SPL_)REGULATOR_AXP_USB_POWER) += axp_usb_power.o
obj-$(CONFIG_$(SPL_)DM_REGULATOR_DA9063) += da9063.o
+obj-$(CONFIG_$(SPL_)DM_REGULATOR_MAX77663) += max77663_regulator.o
obj-$(CONFIG_DM_REGULATOR_MAX77686) += max77686.o
obj-$(CONFIG_DM_REGULATOR_NPCM8XX) += npcm8xx_regulator.o
obj-$(CONFIG_$(SPL_)DM_PMIC_PFUZE100) += pfuze100.o
diff --git a/drivers/power/regulator/max77663_regulator.c b/drivers/power/regulator/max77663_regulator.c
new file mode 100644
index 0000000000..ea4b7c63e5
--- /dev/null
+++ b/drivers/power/regulator/max77663_regulator.c
@@ -0,0 +1,375 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright(C) 2023 Svyatoslav Ryhel <clamor95@gmail.com>
+ */
+
+#include <dm.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/max77663.h>
+
+/* fist row is control registers, second is voltage registers */
+static const char max77663_sd_reg[][MAX77663_SD_NUM] = {
+ { 0x1d, 0x1e, 0x1f, 0x20, 0x21 },
+ { 0x16, 0x17, 0x18, 0x19, 0x2a },
+};
+
+static const char max77663_ldo_reg[MAX77663_LDO_NUM] = {
+ 0x23, 0x25, 0x27, 0x29, 0x2b, 0x2d, 0x2f, 0x31, 0x33
+};
+
+static int max77663_sd_enable(struct udevice *dev, int op, bool *enable)
+{
+ struct dm_regulator_uclass_plat *uc_pdata =
+ dev_get_uclass_plat(dev);
+ u32 adr = uc_pdata->ctrl_reg;
+ int val, ret;
+
+ val = pmic_reg_read(dev->parent, adr);
+ if (val < 0)
+ return val;
+
+ if (op == PMIC_OP_GET) {
+ if (val & SD_STATUS_MASK)
+ *enable = true;
+ else
+ *enable = false;
+
+ return 0;
+ } else if (op == PMIC_OP_SET) {
+ val &= ~SD_STATUS_MASK;
+
+ if (*enable)
+ val |= SD_STATUS_MASK;
+
+ ret = pmic_reg_write(dev->parent, adr, val);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * max77663_*_volt2hex() - convert voltage in uV into
+ * applicable to register hex value
+ *
+ * @idx: regulator index
+ * @uV: voltage in uV
+ *
+ * Return: voltage in hex on success, -ve on failure
+ */
+static int max77663_sd_volt2hex(int idx, int uV)
+{
+ switch (idx) {
+ case 0:
+ /* SD0 has max voltage 1.4V */
+ if (uV > SD0_VOLT_MAX)
+ return -EINVAL;
+ break;
+ case 1:
+ /* SD1 has max voltage 1.55V */
+ if (uV > SD1_VOLT_MAX)
+ return -EINVAL;
+ break;
+ default:
+ /* SD2 and SD3 have max voltage 3.79V */
+ if (uV > SD_VOLT_MAX)
+ return -EINVAL;
+ break;
+ };
+
+ if (uV < SD_VOLT_MIN)
+ uV = SD_VOLT_MIN;
+
+ return (uV - SD_VOLT_BASE) / 12500;
+}
+
+/**
+ * max77663_*_hex2volt() - convert register hex value into
+ * actual voltage in uV
+ *
+ * @idx: regulator index
+ * @hex: hex value of register
+ *
+ * Return: voltage in uV on success, -ve on failure
+ */
+static int max77663_sd_hex2volt(int idx, int hex)
+{
+ switch (idx) {
+ case 0:
+ /* SD0 has max voltage 1.4V */
+ if (hex > SD0_VOLT_MAX_HEX)
+ return -EINVAL;
+ break;
+ case 1:
+ /* SD1 has max voltage 1.55V */
+ if (hex > SD1_VOLT_MAX_HEX)
+ return -EINVAL;
+ break;
+ default:
+ /* SD2 and SD3 have max voltage 3.79V */
+ if (hex > SD_VOLT_MAX_HEX)
+ return -EINVAL;
+ break;
+ };
+
+ if (hex < SD_VOLT_MIN_HEX)
+ hex = SD_VOLT_MIN_HEX;
+
+ return SD_VOLT_BASE + hex * 12500;
+}
+
+static int max77663_sd_val(struct udevice *dev, int op, int *uV)
+{
+ struct dm_regulator_uclass_plat *uc_pdata =
+ dev_get_uclass_plat(dev);
+ u32 adr = uc_pdata->volt_reg;
+ int idx = dev->driver_data;
+ int hex, ret;
+
+ if (op == PMIC_OP_GET) {
+ hex = pmic_reg_read(dev->parent, adr);
+ if (hex < 0)
+ return hex;
+
+ *uV = 0;
+
+ ret = max77663_sd_hex2volt(idx, hex);
+ if (ret < 0)
+ return ret;
+ *uV = ret;
+
+ return 0;
+ }
+
+ /* SD regulators use entire register for voltage */
+ hex = max77663_sd_volt2hex(idx, *uV);
+ if (hex < 0)
+ return hex;
+
+ return pmic_reg_write(dev->parent, adr, hex);
+}
+
+static int max77663_sd_probe(struct udevice *dev)
+{
+ struct dm_regulator_uclass_plat *uc_pdata =
+ dev_get_uclass_plat(dev);
+ int idx = dev->driver_data;
+
+ uc_pdata->type = REGULATOR_TYPE_BUCK;
+ uc_pdata->ctrl_reg = max77663_sd_reg[0][idx];
+ uc_pdata->volt_reg = max77663_sd_reg[1][idx];
+
+ return 0;
+}
+
+static int sd_get_value(struct udevice *dev)
+{
+ int uV;
+ int ret;
+
+ ret = max77663_sd_val(dev, PMIC_OP_GET, &uV);
+ if (ret)
+ return ret;
+
+ return uV;
+}
+
+static int sd_set_value(struct udevice *dev, int uV)
+{
+ return max77663_sd_val(dev, PMIC_OP_SET, &uV);
+}
+
+static int sd_get_enable(struct udevice *dev)
+{
+ bool enable = false;
+ int ret;
+
+ ret = max77663_sd_enable(dev, PMIC_OP_GET, &enable);
+ if (ret)
+ return ret;
+
+ return enable;
+}
+
+static int sd_set_enable(struct udevice *dev, bool enable)
+{
+ return max77663_sd_enable(dev, PMIC_OP_SET, &enable);
+}
+
+static const struct dm_regulator_ops max77663_sd_ops = {
+ .get_value = sd_get_value,
+ .set_value = sd_set_value,
+ .get_enable = sd_get_enable,
+ .set_enable = sd_set_enable,
+};
+
+U_BOOT_DRIVER(max77663_sd) = {
+ .name = MAX77663_SD_DRIVER,
+ .id = UCLASS_REGULATOR,
+ .ops = &max77663_sd_ops,
+ .probe = max77663_sd_probe,
+};
+
+static int max77663_ldo_enable(struct udevice *dev, int op, bool *enable)
+{
+ struct dm_regulator_uclass_plat *uc_pdata =
+ dev_get_uclass_plat(dev);
+ u32 adr = uc_pdata->ctrl_reg;
+ int val, ret;
+
+ val = pmic_reg_read(dev->parent, adr);
+ if (val < 0)
+ return val;
+
+ if (op == PMIC_OP_GET) {
+ if (val & LDO_STATUS_MASK)
+ *enable = true;
+ else
+ *enable = false;
+
+ return 0;
+ } else if (op == PMIC_OP_SET) {
+ val &= ~LDO_STATUS_MASK;
+
+ if (*enable)
+ val |= LDO_STATUS_MASK;
+
+ ret = pmic_reg_write(dev->parent, adr, val);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int max77663_ldo_volt2hex(int idx, int uV)
+{
+ switch (idx) {
+ case 0:
+ case 1:
+ if (uV > LDO01_VOLT_MAX)
+ return -EINVAL;
+
+ return (uV - LDO_VOLT_BASE) / 25000;
+ case 4:
+ if (uV > LDO4_VOLT_MAX)
+ return -EINVAL;
+
+ return (uV - LDO_VOLT_BASE) / 12500;
+ default:
+ if (uV > LDO_VOLT_MAX)
+ return -EINVAL;
+
+ return (uV - LDO_VOLT_BASE) / 50000;
+ };
+}
+
+static int max77663_ldo_hex2volt(int idx, int hex)
+{
+ if (hex > LDO_VOLT_MAX_HEX)
+ return -EINVAL;
+
+ switch (idx) {
+ case 0:
+ case 1:
+ return (hex * 25000) + LDO_VOLT_BASE;
+ case 4:
+ return (hex * 12500) + LDO_VOLT_BASE;
+ default:
+ return (hex * 50000) + LDO_VOLT_BASE;
+ };
+}
+
+static int max77663_ldo_val(struct udevice *dev, int op, int *uV)
+{
+ struct dm_regulator_uclass_plat *uc_pdata =
+ dev_get_uclass_plat(dev);
+ u32 adr = uc_pdata->ctrl_reg;
+ int idx = dev->driver_data;
+ int hex, val, ret;
+
+ val = pmic_reg_read(dev->parent, adr);
+ if (val < 0)
+ return val;
+
+ if (op == PMIC_OP_GET) {
+ *uV = 0;
+
+ ret = max77663_ldo_hex2volt(idx, val & LDO_VOLT_MASK);
+ if (ret < 0)
+ return ret;
+
+ *uV = ret;
+ return 0;
+ }
+
+ hex = max77663_ldo_volt2hex(idx, *uV);
+ if (hex < 0)
+ return hex;
+
+ val &= ~LDO_VOLT_MASK;
+
+ return pmic_reg_write(dev->parent, adr, val | hex);
+}
+
+static int max77663_ldo_probe(struct udevice *dev)
+{
+ struct dm_regulator_uclass_plat *uc_pdata =
+ dev_get_uclass_plat(dev);
+ int idx = dev->driver_data;
+
+ uc_pdata->type = REGULATOR_TYPE_LDO;
+ uc_pdata->ctrl_reg = max77663_ldo_reg[idx];
+
+ return 0;
+}
+
+static int ldo_get_value(struct udevice *dev)
+{
+ int uV;
+ int ret;
+
+ ret = max77663_ldo_val(dev, PMIC_OP_GET, &uV);
+ if (ret)
+ return ret;
+
+ return uV;
+}
+
+static int ldo_set_value(struct udevice *dev, int uV)
+{
+ return max77663_ldo_val(dev, PMIC_OP_SET, &uV);
+}
+
+static int ldo_get_enable(struct udevice *dev)
+{
+ bool enable = false;
+ int ret;
+
+ ret = max77663_ldo_enable(dev, PMIC_OP_GET, &enable);
+ if (ret)
+ return ret;
+
+ return enable;
+}
+
+static int ldo_set_enable(struct udevice *dev, bool enable)
+{
+ return max77663_ldo_enable(dev, PMIC_OP_SET, &enable);
+}
+
+static const struct dm_regulator_ops max77663_ldo_ops = {
+ .get_value = ldo_get_value,
+ .set_value = ldo_set_value,
+ .get_enable = ldo_get_enable,
+ .set_enable = ldo_set_enable,
+};
+
+U_BOOT_DRIVER(max77663_ldo) = {
+ .name = MAX77663_LDO_DRIVER,
+ .id = UCLASS_REGULATOR,
+ .ops = &max77663_ldo_ops,
+ .probe = max77663_ldo_probe,
+};
--
2.39.2
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v9 5/8] power: pmic: add the base TPS80031 PMIC support
2023-10-27 8:26 [PATCH v9 0/8] Add support for PMICs used on Tegra 3 devices Svyatoslav Ryhel
` (3 preceding siblings ...)
2023-10-27 8:26 ` [PATCH v9 4/8] power: regulator: max77663: add regulator support Svyatoslav Ryhel
@ 2023-10-27 8:26 ` Svyatoslav Ryhel
2023-10-27 8:26 ` [PATCH v9 6/8] power: regulator: tps80031: add regulator support Svyatoslav Ryhel
` (2 subsequent siblings)
7 siblings, 0 replies; 14+ messages in thread
From: Svyatoslav Ryhel @ 2023-10-27 8:26 UTC (permalink / raw)
To: Tom Rini, Jaehoon Chung, Simon Glass, Svyatoslav Ryhel; +Cc: u-boot
Add support to bind the regulators/child nodes with the pmic.
Also adds the pmic i2c based read/write functions to access pmic
registers.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
doc/device-tree-bindings/pmic/tps80031.txt | 76 ++++++++++++++++++++
drivers/power/pmic/Kconfig | 11 +++
drivers/power/pmic/Makefile | 1 +
drivers/power/pmic/tps80031.c | 82 ++++++++++++++++++++++
include/power/tps80031.h | 45 ++++++++++++
5 files changed, 215 insertions(+)
create mode 100644 doc/device-tree-bindings/pmic/tps80031.txt
create mode 100644 drivers/power/pmic/tps80031.c
create mode 100644 include/power/tps80031.h
diff --git a/doc/device-tree-bindings/pmic/tps80031.txt b/doc/device-tree-bindings/pmic/tps80031.txt
new file mode 100644
index 0000000000..577e6de1c1
--- /dev/null
+++ b/doc/device-tree-bindings/pmic/tps80031.txt
@@ -0,0 +1,76 @@
+Texas Instruments, TPS80031/TPS80032 PMIC
+
+This device uses two drivers:
+- drivers/power/pmic/tps80031.c (for parent device)
+- drivers/power/regulator/tps80031_regulator.c (for child regulators)
+
+This chapter describes the binding info for the PMIC driver and regulators.
+
+Required properties for PMIC:
+- compatible: "ti,tps80031" or "ti,tps80032"
+- reg: 0x48
+
+With those two properties, the pmic device can be used for read/write only.
+To bind each regulator, the optional regulators subnode should exists.
+
+Optional subnode:
+- name: regulators (subnode list of each device's regulator)
+
+Regulators subnode contains set on supported regulators.
+
+Required properties:
+- regulator-name: used for regulator uclass platform data '.name',
+
+List of supported regulator nodes names for tps80031/tps80032:
+- smps1, smps2, smps3, smps4, smps5
+- ldo1, ldo2, ldo3, ldo4, ldo5, ldo6, ldo7, ldoln, ldousb
+
+SMPS5 in Linux 3.1.10 is referred as vio, but datasheet clearly names it SMPS5.
+
+Optional:
+- regulator-min-microvolt: minimum allowed Voltage to set
+- regulator-max-microvolt: minimum allowed Voltage to set
+- regulator-always-on: regulator should be never disabled
+- regulator-boot-on: regulator should be enabled by the bootloader
+
+Example:
+
+tps80032@48 {
+ compatible = "ti,tps80032";
+ reg = <0x48>;
+
+ regulators {
+ smps1 {
+ regulator-name = "vdd_cpu";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1250000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ ...
+
+ smps5 {
+ regulator-name = "vdd_1v8_gen";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ ldo1 {
+ regulator-name = "avdd_dsi_csi";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-boot-on;
+ };
+
+ ...
+
+ ldousb {
+ regulator-name = "avdd_usb";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+ };
+};
diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig
index 54665d7e2b..454a6e0cf8 100644
--- a/drivers/power/pmic/Kconfig
+++ b/drivers/power/pmic/Kconfig
@@ -351,6 +351,17 @@ config DM_PMIC_TPS65910
DC-DC converter, 8 LDOs and a RTC. This driver binds the SMPS and LDO
pmic children.
+config DM_PMIC_TPS80031
+ bool "Enable driver for Texas Instruments TPS80031/TPS80032 PMIC"
+ ---help---
+ This config enables implementation of driver-model pmic uclass features
+ for TPS80031/TPS80032 PMICs. The driver implements read/write operations.
+ This is a Power Management IC with a decent set of peripherals from which
+ 5 Buck Converters refered as Switched-mode power supply (SMPS), 11 General-
+ Purpose Low-Dropout Voltage Regulators (LDO), USB OTG Module, Real-Time
+ Clock (RTC) with Timer and Alarm Wake-Up, Two Digital PWM Outputs and more
+ with I2C Compatible Interface. PMIC occupies 4 I2C addresses.
+
config PMIC_STPMIC1
bool "Enable support for STMicroelectronics STPMIC1 PMIC"
depends on DM_I2C
diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile
index 414a9d8225..55ee614364 100644
--- a/drivers/power/pmic/Makefile
+++ b/drivers/power/pmic/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_$(SPL_)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_)DM_PMIC_TPS80031) += tps80031.o
obj-$(CONFIG_$(SPL_)PMIC_PALMAS) += palmas.o
obj-$(CONFIG_$(SPL_)PMIC_LP873X) += lp873x.o
obj-$(CONFIG_$(SPL_)PMIC_LP87565) += lp87565.o
diff --git a/drivers/power/pmic/tps80031.c b/drivers/power/pmic/tps80031.c
new file mode 100644
index 0000000000..6b36ebbf7d
--- /dev/null
+++ b/drivers/power/pmic/tps80031.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright(C) 2023 Svyatoslav Ryhel <clamor95@gmail.com>
+ */
+
+#include <dm.h>
+#include <dm/lists.h>
+#include <power/pmic.h>
+#include <power/tps80031.h>
+
+static const struct pmic_child_info pmic_children_info[] = {
+ { .prefix = "ldo", .driver = TPS80031_LDO_DRIVER },
+ { .prefix = "smps", .driver = TPS80031_SMPS_DRIVER },
+ { },
+};
+
+static int tps80031_write(struct udevice *dev, uint reg, const uint8_t *buff,
+ int len)
+{
+ int ret;
+
+ ret = dm_i2c_write(dev, reg, buff, len);
+ if (ret) {
+ log_debug("write error to device: %p register: %#x!\n", dev, reg);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int tps80031_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+ int ret;
+
+ ret = dm_i2c_read(dev, reg, buff, len);
+ if (ret) {
+ log_debug("read error from device: %p register: %#x!\n", dev, reg);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int tps80031_bind(struct udevice *dev)
+{
+ ofnode regulators_node;
+ int children;
+
+ regulators_node = dev_read_subnode(dev, "regulators");
+ if (!ofnode_valid(regulators_node)) {
+ log_err("%s regulators subnode not found!\n", 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)
+ log_err("%s - no child found\n", dev->name);
+
+ /* Always return success for this device */
+ return 0;
+}
+
+static struct dm_pmic_ops tps80031_ops = {
+ .read = tps80031_read,
+ .write = tps80031_write,
+};
+
+static const struct udevice_id tps80031_ids[] = {
+ { .compatible = "ti,tps80031" },
+ { .compatible = "ti,tps80032" },
+ { }
+};
+
+U_BOOT_DRIVER(pmic_tps80031) = {
+ .name = "tps80031_pmic",
+ .id = UCLASS_PMIC,
+ .of_match = tps80031_ids,
+ .bind = tps80031_bind,
+ .ops = &tps80031_ops,
+};
diff --git a/include/power/tps80031.h b/include/power/tps80031.h
new file mode 100644
index 0000000000..c80692a8af
--- /dev/null
+++ b/include/power/tps80031.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright(C) 2023 Svyatoslav Ryhel <clamor95@gmail.com>
+ */
+
+#ifndef _TPS80031_H_
+#define _TPS80031_H_
+
+#define TPS80031_LDO_NUM 9
+#define TPS80031_SMPS_NUM 5
+
+/* Drivers name */
+#define TPS80031_LDO_DRIVER "tps80031_ldo"
+#define TPS80031_SMPS_DRIVER "tps80031_smps"
+
+#define TPS80031_SMPS_OFFSET 0xe0
+#define TPS80031_OFFSET_FLAG BIT(0)
+
+#define REGULATOR_STATUS_MASK 0x3
+#define REGULATOR_MODE_ON 0x1
+
+/* Switched-Mode Power Supply Regulator calculations */
+#define SMPS_VOLT_MASK 0x3f
+#define SMPS_VOLT_LINEAR_HEX 0x39
+#define SMPS_VOLT_NLINEAR_HEX 0x3a
+#define SMPS_VOLT_LINEAR 1300000
+#define SMPS_VOLT_BASE 600000
+#define SMPS_VOLT_BASE_OFFSET 700000
+
+/* Low-Dropout Linear (LDO) Regulator calculations */
+#define LDO_VOLT_MASK 0x3f
+#define LDO_VOLT_MAX_HEX 0x18
+#define LDO_VOLT_MIN_HEX 0x01
+#define LDO_VOLT_MAX 3360000
+#define LDO_VOLT_MIN 1018000
+#define LDO_VOLT_BASE 916000
+
+/* register groups */
+enum {
+ CTRL,
+ VOLT,
+ OFFSET,
+};
+
+#endif /* _TPS80031_H_ */
--
2.39.2
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v9 6/8] power: regulator: tps80031: add regulator support
2023-10-27 8:26 [PATCH v9 0/8] Add support for PMICs used on Tegra 3 devices Svyatoslav Ryhel
` (4 preceding siblings ...)
2023-10-27 8:26 ` [PATCH v9 5/8] power: pmic: add the base TPS80031 PMIC support Svyatoslav Ryhel
@ 2023-10-27 8:26 ` Svyatoslav Ryhel
2023-10-27 8:26 ` [PATCH v9 7/8] power: pmic: tps65910: add TPS65911 PMIC support Svyatoslav Ryhel
2023-10-27 8:26 ` [PATCH v9 8/8] power: regulator: tps65911: add regulator support Svyatoslav Ryhel
7 siblings, 0 replies; 14+ messages in thread
From: Svyatoslav Ryhel @ 2023-10-27 8:26 UTC (permalink / raw)
To: Tom Rini, Jaehoon Chung, Simon Glass, Svyatoslav Ryhel; +Cc: u-boot
The driver provides regulator set/get voltage enable/disable
functions for TI TPS80031/TPS80032 PMICs.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
drivers/power/regulator/Kconfig | 8 +
drivers/power/regulator/Makefile | 1 +
drivers/power/regulator/tps80031_regulator.c | 347 +++++++++++++++++++
3 files changed, 356 insertions(+)
create mode 100644 drivers/power/regulator/tps80031_regulator.c
diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig
index 581816294c..6454c54855 100644
--- a/drivers/power/regulator/Kconfig
+++ b/drivers/power/regulator/Kconfig
@@ -356,6 +356,14 @@ config DM_REGULATOR_TPS62360
implements the get/set api for value only, as the power line is
always on.
+config DM_REGULATOR_TPS80031
+ bool "Enable driver for TPS80031/TPS80032 PMIC regulators"
+ depends on DM_PMIC_TPS80031
+ ---help---
+ This enables implementation of driver-model regulator uclass
+ features for TPS80031/TPS80032 PMICs. The driver implements
+ get/set api for: value and enable.
+
config DM_REGULATOR_STPMIC1
bool "Enable driver for STPMIC1 regulators"
depends on DM_REGULATOR && PMIC_STPMIC1
diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile
index 8d73169b50..3ef55dc534 100644
--- a/drivers/power/regulator/Makefile
+++ b/drivers/power/regulator/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_$(SPL_)DM_REGULATOR_LP87565) += lp87565_regulator.o
obj-$(CONFIG_$(SPL_)DM_REGULATOR_STM32_VREFBUF) += stm32-vrefbuf.o
obj-$(CONFIG_DM_REGULATOR_TPS65910) += tps65910_regulator.o
obj-$(CONFIG_DM_REGULATOR_TPS62360) += tps62360_regulator.o
+obj-$(CONFIG_$(SPL_)DM_REGULATOR_TPS80031) += tps80031_regulator.o
obj-$(CONFIG_$(SPL_)DM_REGULATOR_STPMIC1) += stpmic1.o
obj-$(CONFIG_DM_REGULATOR_TPS65941) += tps65941_regulator.o
obj-$(CONFIG_DM_REGULATOR_SCMI) += scmi_regulator.o
diff --git a/drivers/power/regulator/tps80031_regulator.c b/drivers/power/regulator/tps80031_regulator.c
new file mode 100644
index 0000000000..87696662e1
--- /dev/null
+++ b/drivers/power/regulator/tps80031_regulator.c
@@ -0,0 +1,347 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright(C) 2023 Svyatoslav Ryhel <clamor95@gmail.com>
+ */
+
+#include <dm.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/tps80031.h>
+
+static const char tps80031_smps_reg[][TPS80031_SMPS_NUM] = {
+ { 0x54, 0x5a, 0x66, 0x42, 0x48 },
+ { 0x56, 0x5c, 0x68, 0x44, 0x4a },
+ { BIT(3), BIT(4), BIT(6), BIT(0), BIT(1) },
+};
+
+static const char tps80031_ldo_reg[][TPS80031_LDO_NUM] = {
+ { 0x9e, 0x86, 0x8e, 0x8a, 0x9a, 0x92, 0xa6, 0x96, 0xa2 },
+ { 0x9f, 0x87, 0x8f, 0x8b, 0x9b, 0x93, 0xa7, 0x97, 0xa3 },
+};
+
+static int tps80031_regulator_enable(struct udevice *dev, int op, bool *enable)
+{
+ struct dm_regulator_uclass_plat *uc_pdata =
+ dev_get_uclass_plat(dev);
+ u32 adr = uc_pdata->ctrl_reg;
+ int val, ret;
+
+ val = pmic_reg_read(dev->parent, adr);
+ if (val < 0)
+ return val;
+
+ if (op == PMIC_OP_GET) {
+ if (val & REGULATOR_MODE_ON)
+ *enable = true;
+ else
+ *enable = false;
+
+ return 0;
+ } else if (op == PMIC_OP_SET) {
+ val &= ~REGULATOR_STATUS_MASK;
+
+ if (*enable)
+ val |= REGULATOR_MODE_ON;
+
+ ret = pmic_reg_write(dev->parent, adr, val);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int tps80031_get_enable(struct udevice *dev)
+{
+ bool enable = false;
+ int ret;
+
+ ret = tps80031_regulator_enable(dev, PMIC_OP_GET, &enable);
+ if (ret)
+ return ret;
+
+ return enable;
+}
+
+static int tps80031_set_enable(struct udevice *dev, bool enable)
+{
+ return tps80031_regulator_enable(dev, PMIC_OP_SET, &enable);
+}
+
+/**
+ * tps80031_ldo_volt2hex() - convert voltage in uV into
+ * applicable to register hex value
+ *
+ * @uV: voltage in uV
+ *
+ * Return: voltage in hex on success, -ve on failure
+ */
+static int tps80031_ldo_volt2hex(int uV)
+{
+ if (uV > LDO_VOLT_MAX)
+ return -EINVAL;
+
+ if (uV < LDO_VOLT_MIN)
+ uV = LDO_VOLT_MIN;
+
+ return DIV_ROUND_UP(uV - LDO_VOLT_BASE, 102000);
+}
+
+/**
+ * tps80031_ldo_hex2volt() - convert register hex value into
+ * actual voltage in uV
+ *
+ * @hex: hex value of register
+ *
+ * Return: voltage in uV on success, -ve on failure
+ */
+static int tps80031_ldo_hex2volt(int hex)
+{
+ if (hex > LDO_VOLT_MAX_HEX)
+ return -EINVAL;
+
+ if (hex < LDO_VOLT_MIN_HEX)
+ hex = LDO_VOLT_MIN_HEX;
+
+ return LDO_VOLT_BASE + hex * 102000;
+}
+
+static int tps80031_ldo_val(struct udevice *dev, int op, int *uV)
+{
+ struct dm_regulator_uclass_plat *uc_pdata =
+ dev_get_uclass_plat(dev);
+ u32 adr = uc_pdata->volt_reg;
+ int val, hex, ret;
+
+ val = pmic_reg_read(dev->parent, adr);
+ if (val < 0)
+ return val;
+
+ if (op == PMIC_OP_GET) {
+ *uV = 0;
+
+ ret = tps80031_ldo_hex2volt(val & LDO_VOLT_MASK);
+ if (ret < 0)
+ return ret;
+
+ *uV = ret;
+ return 0;
+ }
+
+ hex = tps80031_ldo_volt2hex(*uV);
+ if (hex < 0)
+ return hex;
+
+ val &= ~LDO_VOLT_MASK;
+
+ return pmic_reg_write(dev->parent, adr, val | hex);
+}
+
+static int tps80031_ldo_probe(struct udevice *dev)
+{
+ struct dm_regulator_uclass_plat *uc_pdata =
+ dev_get_uclass_plat(dev);
+
+ uc_pdata->type = REGULATOR_TYPE_LDO;
+
+ /* check for ldoln and ldousb cases */
+ if (!strcmp("ldoln", dev->name)) {
+ uc_pdata->ctrl_reg = tps80031_ldo_reg[CTRL][7];
+ uc_pdata->volt_reg = tps80031_ldo_reg[VOLT][7];
+ return 0;
+ }
+
+ if (!strcmp("ldousb", dev->name)) {
+ uc_pdata->ctrl_reg = tps80031_ldo_reg[CTRL][8];
+ uc_pdata->volt_reg = tps80031_ldo_reg[VOLT][8];
+ return 0;
+ }
+
+ if (dev->driver_data > 0) {
+ u8 idx = dev->driver_data - 1;
+
+ uc_pdata->ctrl_reg = tps80031_ldo_reg[CTRL][idx];
+ uc_pdata->volt_reg = tps80031_ldo_reg[VOLT][idx];
+ }
+
+ return 0;
+}
+
+static int ldo_get_value(struct udevice *dev)
+{
+ int uV;
+ int ret;
+
+ ret = tps80031_ldo_val(dev, PMIC_OP_GET, &uV);
+ if (ret)
+ return ret;
+
+ return uV;
+}
+
+static int ldo_set_value(struct udevice *dev, int uV)
+{
+ return tps80031_ldo_val(dev, PMIC_OP_SET, &uV);
+}
+
+static const struct dm_regulator_ops tps80031_ldo_ops = {
+ .get_value = ldo_get_value,
+ .set_value = ldo_set_value,
+ .get_enable = tps80031_get_enable,
+ .set_enable = tps80031_set_enable,
+};
+
+U_BOOT_DRIVER(tps80031_ldo) = {
+ .name = TPS80031_LDO_DRIVER,
+ .id = UCLASS_REGULATOR,
+ .ops = &tps80031_ldo_ops,
+ .probe = tps80031_ldo_probe,
+};
+
+struct tps80031_smps_priv {
+ int flags;
+};
+
+/* DCDC voltages for the selector of 0x39 to 0x3F */
+static int tps80031_dcdc_voltages[5] = {
+ 1350000, 1500000, 1800000, 1900000, 2100000
+};
+
+/**
+ * tps80031_smps_volt2hex() - convert voltage in uV into
+ * applicable to register hex value
+ *
+ * @base: base voltage in uV
+ * @uV: voltage in uV
+ *
+ * Return: voltage in hex on success, -ve on failure
+ */
+static int tps80031_smps_volt2hex(u32 base, int uV)
+{
+ int i;
+
+ if (uV < base)
+ return 1;
+
+ if (uV > SMPS_VOLT_LINEAR) {
+ for (i = 0; i < ARRAY_SIZE(tps80031_dcdc_voltages); i++)
+ if (uV <= tps80031_dcdc_voltages[i])
+ break;
+
+ return SMPS_VOLT_NLINEAR_HEX + i;
+ }
+
+ return DIV_ROUND_UP(uV - base, 12500);
+}
+
+/**
+ * tps80031_smps_hex2volt() - convert register hex value into
+ * actual voltage in uV
+ *
+ * @base: base voltage in uV
+ * @hex: hex value of register
+ *
+ * Return: voltage in uV on success, -ve on failure
+ */
+static int tps80031_smps_hex2volt(u32 base, int hex)
+{
+ if (!hex)
+ return 0;
+
+ /* if reg value exceeds linear scale use table */
+ if (hex > SMPS_VOLT_LINEAR_HEX)
+ return tps80031_dcdc_voltages[hex - SMPS_VOLT_LINEAR_HEX];
+ else
+ return base + hex * 12500;
+}
+
+static int tps80031_smps_val(struct udevice *dev, int op, int *uV)
+{
+ struct dm_regulator_uclass_plat *uc_pdata =
+ dev_get_uclass_plat(dev);
+ struct tps80031_smps_priv *priv = dev_get_priv(dev);
+ u32 adr = uc_pdata->volt_reg;
+ int base, val, hex, ret;
+
+ /* If offset flag was set then base voltage is higher */
+ if (priv->flags & TPS80031_OFFSET_FLAG)
+ base = SMPS_VOLT_BASE_OFFSET;
+ else
+ base = SMPS_VOLT_BASE;
+
+ val = pmic_reg_read(dev->parent, adr);
+ if (val < 0)
+ return val;
+
+ if (op == PMIC_OP_GET) {
+ *uV = 0;
+
+ ret = tps80031_smps_hex2volt(base, val & SMPS_VOLT_MASK);
+ if (ret < 0)
+ return ret;
+
+ *uV = ret;
+ return 0;
+ }
+
+ hex = tps80031_smps_volt2hex(base, *uV);
+ if (hex < 0)
+ return hex;
+
+ val &= ~SMPS_VOLT_MASK;
+
+ return pmic_reg_write(dev->parent, adr, val | hex);
+}
+
+static int tps80031_smps_probe(struct udevice *dev)
+{
+ struct dm_regulator_uclass_plat *uc_pdata =
+ dev_get_uclass_plat(dev);
+ struct tps80031_smps_priv *priv = dev_get_priv(dev);
+ int idx = dev->driver_data - 1;
+ int val;
+
+ uc_pdata->type = REGULATOR_TYPE_BUCK;
+
+ uc_pdata->ctrl_reg = tps80031_smps_reg[CTRL][idx];
+ uc_pdata->volt_reg = tps80031_smps_reg[VOLT][idx];
+
+ /* Determine if smps regulator uses higher voltage */
+ val = pmic_reg_read(dev->parent, TPS80031_SMPS_OFFSET);
+ if (val & tps80031_smps_reg[OFFSET][idx])
+ priv->flags |= TPS80031_OFFSET_FLAG;
+
+ return 0;
+}
+
+static int smps_get_value(struct udevice *dev)
+{
+ int uV;
+ int ret;
+
+ ret = tps80031_smps_val(dev, PMIC_OP_GET, &uV);
+ if (ret)
+ return ret;
+
+ return uV;
+}
+
+static int smps_set_value(struct udevice *dev, int uV)
+{
+ return tps80031_smps_val(dev, PMIC_OP_SET, &uV);
+}
+
+static const struct dm_regulator_ops tps80031_smps_ops = {
+ .get_value = smps_get_value,
+ .set_value = smps_set_value,
+ .get_enable = tps80031_get_enable,
+ .set_enable = tps80031_set_enable,
+};
+
+U_BOOT_DRIVER(tps80031_smps) = {
+ .name = TPS80031_SMPS_DRIVER,
+ .id = UCLASS_REGULATOR,
+ .ops = &tps80031_smps_ops,
+ .probe = tps80031_smps_probe,
+ .priv_auto = sizeof(struct tps80031_smps_priv),
+};
--
2.39.2
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v9 7/8] power: pmic: tps65910: add TPS65911 PMIC support
2023-10-27 8:26 [PATCH v9 0/8] Add support for PMICs used on Tegra 3 devices Svyatoslav Ryhel
` (5 preceding siblings ...)
2023-10-27 8:26 ` [PATCH v9 6/8] power: regulator: tps80031: add regulator support Svyatoslav Ryhel
@ 2023-10-27 8:26 ` Svyatoslav Ryhel
2023-10-27 8:26 ` [PATCH v9 8/8] power: regulator: tps65911: add regulator support Svyatoslav Ryhel
7 siblings, 0 replies; 14+ messages in thread
From: Svyatoslav Ryhel @ 2023-10-27 8:26 UTC (permalink / raw)
To: Tom Rini, Jaehoon Chung, Simon Glass, Svyatoslav Ryhel; +Cc: u-boot
Add support to bind the regulators/child nodes with the pmic.
Also adds the pmic i2c based read/write functions to access pmic
registers.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
doc/device-tree-bindings/pmic/tps65911.txt | 78 ++++++++++++++++++++++
drivers/power/pmic/pmic_tps65910_dm.c | 15 ++++-
include/power/tps65910_pmic.h | 44 ++++++++++++
3 files changed, 134 insertions(+), 3 deletions(-)
create mode 100644 doc/device-tree-bindings/pmic/tps65911.txt
diff --git a/doc/device-tree-bindings/pmic/tps65911.txt b/doc/device-tree-bindings/pmic/tps65911.txt
new file mode 100644
index 0000000000..29270efbfe
--- /dev/null
+++ b/doc/device-tree-bindings/pmic/tps65911.txt
@@ -0,0 +1,78 @@
+Texas Instruments, TPS65911 PMIC
+
+This device uses two drivers:
+- drivers/power/pmic/tps65910.c (for parent device)
+- drivers/power/regulator/tps65911_regulator.c (for child regulators)
+
+This chapter describes the binding info for the PMIC driver and regulators.
+
+Required properties for PMIC:
+- compatible: "ti,tps65911"
+- reg: 0x2d
+
+With those two properties, the pmic device can be used for read/write only.
+To bind each regulator, the optional regulators subnode should exists.
+
+Optional subnode:
+- name: regulators (subnode list of each device's regulator)
+
+Regulators subnode contains set on supported regulators.
+
+Required properties:
+- regulator-name: used for regulator uclass platform data '.name',
+
+List of supported regulator nodes names for tps65911:
+- vdd1, vdd2, vddctrl, vddio
+- ldo1, ldo2, ldo3, ldo4, ldo5, ldo6, ldo7, ldo8
+
+vddio in datasheet is referred as vio, but for reduction of code and
+unification of smps regulators it is named vddio.
+
+Optional:
+- regulator-min-microvolt: minimum allowed Voltage to set
+- regulator-max-microvolt: minimum allowed Voltage to set
+- regulator-always-on: regulator should be never disabled
+- regulator-boot-on: regulator should be enabled by the bootloader
+
+Example:
+
+tps65911@2d {
+ compatible = "ti,tps65911";
+ reg = <0x2d>;
+
+ regulators {
+ vdd1 {
+ regulator-name = "vdd_1v2_backlight";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ ...
+
+ vddio {
+ regulator-name = "vdd_1v8_gen";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ ldo1 {
+ regulator-name = "vdd_emmc_core";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ ...
+
+ ldo8 {
+ regulator-name = "vdd_ddr_hs";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ };
+ };
+};
diff --git a/drivers/power/pmic/pmic_tps65910_dm.c b/drivers/power/pmic/pmic_tps65910_dm.c
index 8ead1db802..0a4911cef6 100644
--- a/drivers/power/pmic/pmic_tps65910_dm.c
+++ b/drivers/power/pmic/pmic_tps65910_dm.c
@@ -12,13 +12,19 @@
#include <power/regulator.h>
#include <power/tps65910_pmic.h>
-static const struct pmic_child_info pmic_children_info[] = {
+static const struct pmic_child_info tps65910_children_info[] = {
{ .prefix = "ldo_", .driver = TPS65910_LDO_DRIVER },
{ .prefix = "buck_", .driver = TPS65910_BUCK_DRIVER },
{ .prefix = "boost_", .driver = TPS65910_BOOST_DRIVER },
{ },
};
+static const struct pmic_child_info tps65911_children_info[] = {
+ { .prefix = "ldo", .driver = TPS65911_LDO_DRIVER },
+ { .prefix = "vdd", .driver = TPS65911_VDD_DRIVER },
+ { },
+};
+
static int pmic_tps65910_reg_count(struct udevice *dev)
{
return TPS65910_NUM_REGS;
@@ -50,6 +56,8 @@ static int pmic_tps65910_read(struct udevice *dev, uint reg, u8 *buffer,
static int pmic_tps65910_bind(struct udevice *dev)
{
+ const struct pmic_child_info *tps6591x_children_info =
+ (struct pmic_child_info *)dev_get_driver_data(dev);
ofnode regulators_node;
int children;
@@ -59,7 +67,7 @@ static int pmic_tps65910_bind(struct udevice *dev)
return -EINVAL;
}
- children = pmic_bind_children(dev, regulators_node, pmic_children_info);
+ children = pmic_bind_children(dev, regulators_node, tps6591x_children_info);
if (!children)
debug("%s has no children (regulators)\n", dev->name);
@@ -83,7 +91,8 @@ static struct dm_pmic_ops pmic_tps65910_ops = {
};
static const struct udevice_id pmic_tps65910_match[] = {
- { .compatible = "ti,tps65910" },
+ { .compatible = "ti,tps65910", .data = (ulong)&tps65910_children_info },
+ { .compatible = "ti,tps65911", .data = (ulong)&tps65911_children_info },
{ /* sentinel */ }
};
diff --git a/include/power/tps65910_pmic.h b/include/power/tps65910_pmic.h
index 66214786d3..7d6545abdf 100644
--- a/include/power/tps65910_pmic.h
+++ b/include/power/tps65910_pmic.h
@@ -126,4 +126,48 @@ struct tps65910_regulator_pdata {
#define TPS65910_BOOST_DRIVER "tps65910_boost"
#define TPS65910_LDO_DRIVER "tps65910_ldo"
+/* tps65911 i2c registers */
+enum {
+ TPS65911_REG_VIO = 0x20,
+ TPS65911_REG_VDD1,
+ TPS65911_REG_VDD1_OP,
+ TPS65911_REG_VDD1_SR,
+ TPS65911_REG_VDD2,
+ TPS65911_REG_VDD2_OP,
+ TPS65911_REG_VDD2_SR,
+ TPS65911_REG_VDDCTRL,
+ TPS65911_REG_VDDCTRL_OP,
+ TPS65911_REG_VDDCTRL_SR,
+ TPS65911_REG_LDO1 = 0x30,
+ TPS65911_REG_LDO2,
+ TPS65911_REG_LDO5,
+ TPS65911_REG_LDO8,
+ TPS65911_REG_LDO7,
+ TPS65911_REG_LDO6,
+ TPS65911_REG_LDO4,
+ TPS65911_REG_LDO3,
+};
+
+#define TPS65911_VDD_NUM 4
+#define TPS65911_LDO_NUM 8
+
+#define TPS65911_VDD_VOLT_MAX 1500000
+#define TPS65911_VDD_VOLT_MIN 600000
+#define TPS65911_VDD_VOLT_BASE 562500
+
+#define TPS65911_LDO_VOLT_MAX 3300000
+#define TPS65911_LDO_VOLT_BASE 800000
+
+#define TPS65911_LDO_SEL_MASK (0x3f << 2)
+
+#define TPS65911_LDO124_VOLT_MAX_HEX 0x32
+#define TPS65911_LDO358_VOLT_MAX_HEX 0x19
+#define TPS65911_LDO358_VOLT_MIN_HEX 0x02
+
+#define TPS65911_LDO124_VOLT_STEP 50000
+#define TPS65911_LDO358_VOLT_STEP 100000
+
+#define TPS65911_VDD_DRIVER "tps65911_vdd"
+#define TPS65911_LDO_DRIVER "tps65911_ldo"
+
#endif /* __TPS65910_PMIC_H_ */
--
2.39.2
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v9 8/8] power: regulator: tps65911: add regulator support
2023-10-27 8:26 [PATCH v9 0/8] Add support for PMICs used on Tegra 3 devices Svyatoslav Ryhel
` (6 preceding siblings ...)
2023-10-27 8:26 ` [PATCH v9 7/8] power: pmic: tps65910: add TPS65911 PMIC support Svyatoslav Ryhel
@ 2023-10-27 8:26 ` Svyatoslav Ryhel
7 siblings, 0 replies; 14+ messages in thread
From: Svyatoslav Ryhel @ 2023-10-27 8:26 UTC (permalink / raw)
To: Tom Rini, Jaehoon Chung, Simon Glass, Svyatoslav Ryhel; +Cc: u-boot
The driver provides regulator set/get voltage enable/disable
functions for TI TPS5911 PMIC.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
drivers/power/regulator/Kconfig | 11 +
drivers/power/regulator/Makefile | 1 +
drivers/power/regulator/tps65911_regulator.c | 395 +++++++++++++++++++
3 files changed, 407 insertions(+)
create mode 100644 drivers/power/regulator/tps65911_regulator.c
diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig
index 6454c54855..102ec7bc5f 100644
--- a/drivers/power/regulator/Kconfig
+++ b/drivers/power/regulator/Kconfig
@@ -346,6 +346,17 @@ config DM_REGULATOR_TPS65910
regulator types of the TPS65910 (BUCK, BOOST and LDO). It implements
the get/set api for value and enable.
+config DM_REGULATOR_TPS65911
+ bool "Enable driver for TPS65911 PMIC regulators"
+ depends on DM_PMIC_TPS65910
+ ---help---
+ This config enables implementation of driver-model regulator
+ uclass features for the TPS65911 PMIC. The driver supports Step-Down
+ DC-DC Converters for Processor Cores (VDD1 and VDD2), Step-Down DC-DC
+ Converter for I/O Power (VIO), Controller for External FETs (VDDCtrl)
+ and LDO Voltage Regulators found in TPS65911 PMIC and implements
+ get/set api for value and enable.
+
config DM_REGULATOR_TPS62360
bool "Enable driver for TPS6236x Power Regulator"
depends on DM_REGULATOR
diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile
index 3ef55dc534..f79932d833 100644
--- a/drivers/power/regulator/Makefile
+++ b/drivers/power/regulator/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_$(SPL_)DM_REGULATOR_LP873X) += lp873x_regulator.o
obj-$(CONFIG_$(SPL_)DM_REGULATOR_LP87565) += lp87565_regulator.o
obj-$(CONFIG_$(SPL_)DM_REGULATOR_STM32_VREFBUF) += stm32-vrefbuf.o
obj-$(CONFIG_DM_REGULATOR_TPS65910) += tps65910_regulator.o
+obj-$(CONFIG_$(SPL_)DM_REGULATOR_TPS65911) += tps65911_regulator.o
obj-$(CONFIG_DM_REGULATOR_TPS62360) += tps62360_regulator.o
obj-$(CONFIG_$(SPL_)DM_REGULATOR_TPS80031) += tps80031_regulator.o
obj-$(CONFIG_$(SPL_)DM_REGULATOR_STPMIC1) += stpmic1.o
diff --git a/drivers/power/regulator/tps65911_regulator.c b/drivers/power/regulator/tps65911_regulator.c
new file mode 100644
index 0000000000..2b5acdfcbb
--- /dev/null
+++ b/drivers/power/regulator/tps65911_regulator.c
@@ -0,0 +1,395 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright(C) 2023 Svyatoslav Ryhel <clamor95@gmail.com>
+ */
+
+#include <dm.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/tps65910_pmic.h>
+
+/* fist row is control registers, second is voltage registers */
+static const char tps65911_vdd_reg[][TPS65911_VDD_NUM] = {
+ { TPS65911_REG_VDD1, TPS65911_REG_VDD2,
+ TPS65911_REG_VDDCTRL, TPS65911_REG_VIO },
+ { TPS65911_REG_VDD1_OP, TPS65911_REG_VDD2_OP,
+ TPS65911_REG_VDDCTRL_OP, 0x00 },
+};
+
+static const char tps65911_ldo_reg[TPS65911_LDO_NUM] = {
+ TPS65911_REG_LDO1, TPS65911_REG_LDO2, TPS65911_REG_LDO3,
+ TPS65911_REG_LDO4, TPS65911_REG_LDO5, TPS65911_REG_LDO6,
+ TPS65911_REG_LDO7, TPS65911_REG_LDO8
+};
+
+static int tps65911_regulator_enable(struct udevice *dev, int op, bool *enable)
+{
+ struct dm_regulator_uclass_plat *uc_pdata =
+ dev_get_uclass_plat(dev);
+ u32 adr = uc_pdata->ctrl_reg;
+ int val, ret;
+
+ val = pmic_reg_read(dev->parent, adr);
+ if (val < 0)
+ return val;
+
+ if (op == PMIC_OP_GET) {
+ if (val & TPS65910_SUPPLY_STATE_ON)
+ *enable = true;
+ else
+ *enable = false;
+
+ return 0;
+ } else if (op == PMIC_OP_SET) {
+ val &= ~TPS65910_SUPPLY_STATE_MASK;
+
+ if (*enable)
+ val |= TPS65910_SUPPLY_STATE_ON;
+
+ ret = pmic_reg_write(dev->parent, adr, val);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int tps65911_get_enable(struct udevice *dev)
+{
+ bool enable = false;
+ int ret;
+
+ ret = tps65911_regulator_enable(dev, PMIC_OP_GET, &enable);
+ if (ret)
+ return ret;
+
+ return enable;
+}
+
+static int tps65911_set_enable(struct udevice *dev, bool enable)
+{
+ return tps65911_regulator_enable(dev, PMIC_OP_SET, &enable);
+}
+
+/**
+ * tps65911_vdd_volt2hex() - convert voltage in uV into
+ * applicable to register hex value
+ *
+ * @uV: voltage in uV
+ *
+ * Return: voltage in hex on success, -ve on failure
+ */
+static int tps65911_vdd_volt2hex(int uV)
+{
+ if (uV > TPS65911_VDD_VOLT_MAX)
+ return -EINVAL;
+
+ if (uV < TPS65911_VDD_VOLT_MIN)
+ uV = TPS65911_VDD_VOLT_MIN;
+
+ return (uV - TPS65911_VDD_VOLT_BASE) / 12500;
+}
+
+/**
+ * tps65911_vdd_hex2volt() - convert register hex value into
+ * actual voltage in uV
+ *
+ * @hex: hex value of register
+ *
+ * Return: voltage in uV on success, -ve on failure
+ */
+static int tps65911_vdd_hex2volt(int hex)
+{
+ if (hex > TPS65910_VDD_SEL_MAX)
+ return -EINVAL;
+
+ if (hex < TPS65910_VDD_SEL_MIN)
+ hex = TPS65910_VDD_SEL_MIN;
+
+ return TPS65911_VDD_VOLT_BASE + hex * 12500;
+}
+
+static int tps65911_vio_range[4] = {
+ 1500000, 1800000, 2500000, 3300000
+};
+
+static int tps65911_vio_val(struct udevice *dev, int op, int *uV)
+{
+ struct dm_regulator_uclass_plat *uc_pdata =
+ dev_get_uclass_plat(dev);
+ u32 adr = uc_pdata->volt_reg;
+ int i, val;
+
+ val = pmic_reg_read(dev->parent, adr);
+ if (val < 0)
+ return val;
+
+ if (op == PMIC_OP_GET) {
+ *uV = 0;
+
+ val &= TPS65910_SEL_MASK;
+
+ *uV = tps65911_vio_range[val >> 2];
+
+ return 0;
+ }
+
+ val &= ~TPS65910_SEL_MASK;
+
+ for (i = 0; i < ARRAY_SIZE(tps65911_vio_range); i++)
+ if (*uV <= tps65911_vio_range[i])
+ break;
+
+ return pmic_reg_write(dev->parent, adr, val | i << 2);
+}
+
+static int tps65911_vdd_val(struct udevice *dev, int op, int *uV)
+{
+ struct dm_regulator_uclass_plat *uc_pdata =
+ dev_get_uclass_plat(dev);
+ u32 adr = uc_pdata->volt_reg;
+ int val, ret;
+
+ /* in case vdd is vio */
+ if (!adr)
+ return tps65911_vio_val(dev, op, uV);
+
+ val = pmic_reg_read(dev->parent, adr);
+ if (val < 0)
+ return val;
+
+ if (op == PMIC_OP_GET) {
+ *uV = 0;
+
+ ret = tps65911_vdd_hex2volt(val);
+ if (ret < 0)
+ return ret;
+
+ *uV = ret;
+ return 0;
+ }
+
+ val = tps65911_vdd_volt2hex(*uV);
+ if (val < 0)
+ return val;
+
+ return pmic_reg_write(dev->parent, adr, val);
+}
+
+static int tps65911_vdd_probe(struct udevice *dev)
+{
+ struct dm_regulator_uclass_plat *uc_pdata =
+ dev_get_uclass_plat(dev);
+
+ uc_pdata->type = REGULATOR_TYPE_BUCK;
+
+ /* check for vddctrl and vddio cases */
+ if (!strcmp("vddctrl", dev->name)) {
+ uc_pdata->ctrl_reg = tps65911_vdd_reg[0][2];
+ uc_pdata->volt_reg = tps65911_vdd_reg[1][2];
+ return 0;
+ }
+
+ if (!strcmp("vddio", dev->name)) {
+ uc_pdata->ctrl_reg = tps65911_vdd_reg[0][3];
+ uc_pdata->volt_reg = tps65911_vdd_reg[1][3];
+ return 0;
+ }
+
+ if (dev->driver_data > 0) {
+ u8 idx = dev->driver_data - 1;
+
+ uc_pdata->ctrl_reg = tps65911_vdd_reg[0][idx];
+ uc_pdata->volt_reg = tps65911_vdd_reg[1][idx];
+ }
+
+ return 0;
+}
+
+static int vdd_get_value(struct udevice *dev)
+{
+ int uV;
+ int ret;
+
+ ret = tps65911_vdd_val(dev, PMIC_OP_GET, &uV);
+ if (ret)
+ return ret;
+
+ return uV;
+}
+
+static int vdd_set_value(struct udevice *dev, int uV)
+{
+ return tps65911_vdd_val(dev, PMIC_OP_SET, &uV);
+}
+
+static const struct dm_regulator_ops tps65911_vdd_ops = {
+ .get_value = vdd_get_value,
+ .set_value = vdd_set_value,
+ .get_enable = tps65911_get_enable,
+ .set_enable = tps65911_set_enable,
+};
+
+U_BOOT_DRIVER(tps65911_vdd) = {
+ .name = TPS65911_VDD_DRIVER,
+ .id = UCLASS_REGULATOR,
+ .ops = &tps65911_vdd_ops,
+ .probe = tps65911_vdd_probe,
+};
+
+/**
+ * tps65911_ldo_volt2hex() - convert voltage in uV into
+ * applicable to register hex value
+ *
+ * @idx: regulator index
+ * @uV: voltage in uV
+ *
+ * Return: voltage in hex on success, -ve on failure
+ */
+static int tps65911_ldo_volt2hex(int idx, int uV)
+{
+ int step;
+
+ if (uV > TPS65911_LDO_VOLT_MAX)
+ return -EINVAL;
+
+ if (uV < TPS65911_LDO_VOLT_BASE)
+ uV = TPS65911_LDO_VOLT_BASE;
+
+ switch (idx) {
+ case 1:
+ case 2:
+ case 4:
+ step = TPS65911_LDO124_VOLT_STEP;
+ break;
+ case 3:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ step = TPS65911_LDO358_VOLT_STEP;
+ break;
+ default:
+ return -EINVAL;
+ };
+
+ return ((uV - TPS65911_LDO_VOLT_BASE) / step) << 2;
+}
+
+/**
+ * tps65911_ldo_hex2volt() - convert register hex value into
+ * actual voltage in uV
+ *
+ * @idx: regulator index
+ * @hex: hex value of register
+ *
+ * Return: voltage in uV on success, -ve on failure
+ */
+static int tps65911_ldo_hex2volt(int idx, int hex)
+{
+ int step;
+
+ switch (idx) {
+ case 1:
+ case 2:
+ case 4:
+ if (hex > TPS65911_LDO124_VOLT_MAX_HEX)
+ return -EINVAL;
+
+ step = TPS65911_LDO124_VOLT_STEP;
+ break;
+ case 3:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ if (hex > TPS65911_LDO358_VOLT_MAX_HEX)
+ return -EINVAL;
+
+ if (hex < TPS65911_LDO358_VOLT_MIN_HEX)
+ hex = TPS65911_LDO358_VOLT_MIN_HEX;
+
+ step = TPS65911_LDO358_VOLT_STEP;
+ break;
+ default:
+ return -EINVAL;
+ };
+
+ return TPS65911_LDO_VOLT_BASE + hex * step;
+}
+
+static int tps65911_ldo_val(struct udevice *dev, int op, int *uV)
+{
+ struct dm_regulator_uclass_plat *uc_pdata =
+ dev_get_uclass_plat(dev);
+ u32 adr = uc_pdata->ctrl_reg;
+ int idx = dev->driver_data;
+ int val, hex, ret;
+
+ val = pmic_reg_read(dev->parent, adr);
+ if (val < 0)
+ return val;
+
+ if (op == PMIC_OP_GET) {
+ *uV = 0;
+ val &= TPS65911_LDO_SEL_MASK;
+
+ ret = tps65911_ldo_hex2volt(idx, val >> 2);
+ if (ret < 0)
+ return ret;
+
+ *uV = ret;
+ return 0;
+ }
+
+ hex = tps65911_ldo_volt2hex(idx, *uV);
+ if (hex < 0)
+ return hex;
+
+ val &= ~TPS65911_LDO_SEL_MASK;
+
+ return pmic_reg_write(dev->parent, adr, val | hex);
+}
+
+static int tps65911_ldo_probe(struct udevice *dev)
+{
+ struct dm_regulator_uclass_plat *uc_pdata =
+ dev_get_uclass_plat(dev);
+ u8 idx = dev->driver_data - 1;
+
+ uc_pdata->type = REGULATOR_TYPE_LDO;
+ uc_pdata->ctrl_reg = tps65911_ldo_reg[idx];
+
+ return 0;
+}
+
+static int ldo_get_value(struct udevice *dev)
+{
+ int uV;
+ int ret;
+
+ ret = tps65911_ldo_val(dev, PMIC_OP_GET, &uV);
+ if (ret)
+ return ret;
+
+ return uV;
+}
+
+static int ldo_set_value(struct udevice *dev, int uV)
+{
+ return tps65911_ldo_val(dev, PMIC_OP_SET, &uV);
+}
+
+static const struct dm_regulator_ops tps65911_ldo_ops = {
+ .get_value = ldo_get_value,
+ .set_value = ldo_set_value,
+ .get_enable = tps65911_get_enable,
+ .set_enable = tps65911_set_enable,
+};
+
+U_BOOT_DRIVER(tps65911_ldo) = {
+ .name = TPS65911_LDO_DRIVER,
+ .id = UCLASS_REGULATOR,
+ .ops = &tps65911_ldo_ops,
+ .probe = tps65911_ldo_probe,
+};
--
2.39.2
^ permalink raw reply related [flat|nested] 14+ messages in thread
* RE: [PATCH v9 1/8] power: pmic: palmas: support TI TPS65913 PMIC
2023-10-27 8:26 ` [PATCH v9 1/8] power: pmic: palmas: support TI TPS65913 PMIC Svyatoslav Ryhel
@ 2023-10-31 6:44 ` Jaehoon Chung
2023-11-04 13:57 ` Tom Rini
1 sibling, 0 replies; 14+ messages in thread
From: Jaehoon Chung @ 2023-10-31 6:44 UTC (permalink / raw)
To: 'Svyatoslav Ryhel', 'Tom Rini',
'Simon Glass'
Cc: u-boot
> -----Original Message-----
> From: Svyatoslav Ryhel <clamor95@gmail.com>
> Sent: Friday, October 27, 2023 5:26 PM
> To: Tom Rini <trini@konsulko.com>; Jaehoon Chung <jh80.chung@samsung.com>; Simon Glass
> <sjg@chromium.org>; Svyatoslav Ryhel <clamor95@gmail.com>
> Cc: u-boot@lists.denx.de
> Subject: [PATCH v9 1/8] power: pmic: palmas: support TI TPS65913 PMIC
>
> Existing PALMAS PMIC driver is fully compatible with TI TPS65913
> PMIC found in many Tegra 4 devices, like Tegra Note 7 and ASUS
> TF701T. TPS65913 shares same structure of regulators like TPS659038
> so data can be reused.
>
> Tested-by: Svyatoslav Ryhel <clamor95@gmail.com> # NVIDIA Tegratab
> Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>
Best Regards,
Jaehoon Chung
> ---
> drivers/power/pmic/palmas.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/power/pmic/palmas.c b/drivers/power/pmic/palmas.c
> index eb83c88d56..b2e8a2930c 100644
> --- a/drivers/power/pmic/palmas.c
> +++ b/drivers/power/pmic/palmas.c
> @@ -88,6 +88,7 @@ static struct dm_pmic_ops palmas_ops = {
>
> static const struct udevice_id palmas_ids[] = {
> { .compatible = "ti,tps659038", .data = TPS659038 },
> + { .compatible = "ti,tps65913" , .data = TPS659038 },
> { .compatible = "ti,tps65917" , .data = TPS65917 },
> { }
> };
> --
> 2.39.2
^ permalink raw reply [flat|nested] 14+ messages in thread
* RE: [PATCH v9 3/8] power: pmic: add the base MAX77663 PMIC support
2023-10-27 8:26 ` [PATCH v9 3/8] power: pmic: add the base MAX77663 PMIC support Svyatoslav Ryhel
@ 2023-10-31 8:57 ` Jaehoon Chung
2023-10-31 9:08 ` Svyatoslav Ryhel
0 siblings, 1 reply; 14+ messages in thread
From: Jaehoon Chung @ 2023-10-31 8:57 UTC (permalink / raw)
To: 'Svyatoslav Ryhel', 'Tom Rini',
'Simon Glass'
Cc: u-boot
> -----Original Message-----
> From: Svyatoslav Ryhel <clamor95@gmail.com>
> Sent: Friday, October 27, 2023 5:26 PM
> To: Tom Rini <trini@konsulko.com>; Jaehoon Chung <jh80.chung@samsung.com>; Simon Glass
> <sjg@chromium.org>; Svyatoslav Ryhel <clamor95@gmail.com>
> Cc: u-boot@lists.denx.de
> Subject: [PATCH v9 3/8] power: pmic: add the base MAX77663 PMIC support
>
> Add support to bind the regulators/child nodes with the pmic.
> Also adds the pmic i2c based read/write functions to access pmic
> registers.
>
> Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>
Just add a minor comment at below.
> ---
> doc/device-tree-bindings/pmic/max77663.txt | 84 ++++++++++++++++++++++
> drivers/power/pmic/Kconfig | 9 +++
> drivers/power/pmic/Makefile | 1 +
> drivers/power/pmic/max77663.c | 81 +++++++++++++++++++++
> include/power/max77663.h | 42 +++++++++++
> 5 files changed, 217 insertions(+)
> create mode 100644 doc/device-tree-bindings/pmic/max77663.txt
> create mode 100644 drivers/power/pmic/max77663.c
> create mode 100644 include/power/max77663.h
>
> diff --git a/doc/device-tree-bindings/pmic/max77663.txt b/doc/device-tree-bindings/pmic/max77663.txt
> new file mode 100644
> index 0000000000..ddb7d3eb14
> --- /dev/null
> +++ b/doc/device-tree-bindings/pmic/max77663.txt
> @@ -0,0 +1,84 @@
> +MAXIM, MAX77663 PMIC
> +
> +This device uses two drivers:
> +- drivers/power/pmic/max77663.c (for parent device)
> +- drivers/power/regulator/max77663_regulator.c (for child regulators)
> +
> +This chapter describes the binding info for the PMIC driver and regulators.
> +
> +Required properties for PMIC:
> +- compatible: "maxim,max77663"
> +- reg: usually 0x1c or 0x3c
> +
> +With those two properties, the pmic device can be used for read/write only.
> +To bind each regulator, the optional regulators subnode should exists.
> +
> +Optional subnode:
> +- name: regulators (subnode list of each device's regulator)
> +
> +Regulators subnode contains set on supported regulators.
> +
> +Required properties:
> +- regulator-name: used for regulator uclass platform data '.name',
> +
> +List of supported regulator nodes names for max77663:
> +- sd0, sd1, sd2, sd3, ldo0, ldo1, ldo2, ldo3, ldo4, ldo5, ldo6, ldo7, ldo8
> +
> +Optional:
> +- regulator-min-microvolt: minimum allowed Voltage to set
> +- regulator-max-microvolt: minimum allowed Voltage to set
> +- regulator-always-on: regulator should be never disabled
> +- regulator-boot-on: regulator should be enabled by the bootloader
> +
> +Linux driver binding for this driver is compatible.
> +
> +Example:
> +
> +max77663@1c {
> + compatible = "maxim,max77663";
> + reg = <0x1c>;
> +
> + regulators {
> + sd0 {
> + regulator-name = "vdd_cpu";
> + regulator-min-microvolt = <800000>;
> + regulator-max-microvolt = <1250000>;
> + regulator-always-on;
> + regulator-boot-on;
> + };
> +
> + ...
> +
> + ldo0 {
> + regulator-name = "avdd_pll";
> + regulator-min-microvolt = <1200000>;
> + regulator-max-microvolt = <1200000>;
> + };
> +
> + ...
> +
> + ldo2 {
> + regulator-name = "avdd_usb";
> + regulator-min-microvolt = <3300000>;
> + regulator-max-microvolt = <3300000>;
> + regulator-always-on;
> + regulator-boot-on;
> + };
> +
> + ldo3 {
> + regulator-name = "vdd_sdmmc3";
> + regulator-min-microvolt = <3000000>;
> + regulator-max-microvolt = <3000000>;
> + regulator-always-on;
> + regulator-boot-on;
> + };
> +
> + ...
> +
> + ldo8 {
> + regulator-name = "avdd_dsi_csi";
> + regulator-min-microvolt = <1200000>;
> + regulator-max-microvolt = <1200000>;
> + };
> + };
> +};
> diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig
> index 4a6f0ce093..54665d7e2b 100644
> --- a/drivers/power/pmic/Kconfig
> +++ b/drivers/power/pmic/Kconfig
> @@ -184,6 +184,15 @@ config SPL_DM_PMIC_PFUZE100
> This config enables implementation of driver-model pmic uclass features
> for PMIC PFUZE100 in SPL. The driver implements read/write operations.
>
> +config DM_PMIC_MAX77663
> + bool "Enable Driver Model for PMIC MAX77663"
> + ---help---
> + This config enables implementation of driver-model pmic uclass features
> + for PMIC MAX77663. The driver implements read/write operations.
> + This is a Power Management IC with a decent set of peripherals from which
> + 4 DC-to-DC Step-Down (SD) Regulators, 9 Low-Dropout Linear (LDO) Regulators,
> + 8 GPIOs, Real-Time Clock (RTC) and more with I2C Compatible Interface.
> +
> config DM_PMIC_MAX77686
> bool "Enable Driver Model for PMIC MAX77686"
> ---help---
> diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile
> index 0b3b3d62d0..414a9d8225 100644
> --- a/drivers/power/pmic/Makefile
> +++ b/drivers/power/pmic/Makefile
> @@ -6,6 +6,7 @@
> obj-$(CONFIG_$(SPL_TPL_)DM_PMIC) += pmic-uclass.o
> obj-$(CONFIG_$(SPL_)DM_PMIC_FAN53555) += fan53555.o
> obj-$(CONFIG_$(SPL_)DM_PMIC_DA9063) += da9063.o
> +obj-$(CONFIG_$(SPL_)DM_PMIC_MAX77663) += max77663.o
> obj-$(CONFIG_DM_PMIC_MAX77686) += max77686.o
> obj-$(CONFIG_DM_PMIC_MAX8998) += max8998.o
> obj-$(CONFIG_DM_PMIC_MC34708) += mc34708.o
> diff --git a/drivers/power/pmic/max77663.c b/drivers/power/pmic/max77663.c
> new file mode 100644
> index 0000000000..fac97ed221
> --- /dev/null
> +++ b/drivers/power/pmic/max77663.c
> @@ -0,0 +1,81 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright(C) 2023 Svyatoslav Ryhel <clamor95@gmail.com>
> + */
> +
> +#include <dm.h>
> +#include <dm/lists.h>
> +#include <power/pmic.h>
> +#include <power/max77663.h>
> +
> +static const struct pmic_child_info pmic_children_info[] = {
> + { .prefix = "ldo", .driver = MAX77663_LDO_DRIVER },
> + { .prefix = "sd", .driver = MAX77663_SD_DRIVER },
> + { },
> +};
> +
> +static int max77663_write(struct udevice *dev, uint reg, const uint8_t *buff,
> + int len)
> +{
> + int ret;
> +
> + ret = dm_i2c_write(dev, reg, buff, len);
> + if (ret) {
> + log_debug("write error to device: %p register: %#x!\n", dev, reg);
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static int max77663_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
> +{
> + int ret;
> +
> + ret = dm_i2c_read(dev, reg, buff, len);
> + if (ret) {
> + log_debug("read error from device: %p register: %#x!\n", dev, reg);
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static int max77663_bind(struct udevice *dev)
> +{
> + ofnode regulators_node;
> + int children;
> +
> + regulators_node = dev_read_subnode(dev, "regulators");
> + if (!ofnode_valid(regulators_node)) {
> + log_err("%s regulators subnode not found!\n", 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)
> + log_err("%s - no child found\n", dev->name);
> +
> + /* Always return success for this device */
> + return 0;
> +}
> +
> +static struct dm_pmic_ops max77663_ops = {
> + .read = max77663_read,
> + .write = max77663_write,
> +};
> +
> +static const struct udevice_id max77663_ids[] = {
> + { .compatible = "maxim,max77663" },
> + { }
> +};
> +
> +U_BOOT_DRIVER(pmic_max77663) = {
> + .name = "max77663_pmic",
> + .id = UCLASS_PMIC,
> + .of_match = max77663_ids,
> + .bind = max77663_bind,
> + .ops = &max77663_ops,
> +};
> diff --git a/include/power/max77663.h b/include/power/max77663.h
> new file mode 100644
> index 0000000000..0f764bcbcc
> --- /dev/null
> +++ b/include/power/max77663.h
> @@ -0,0 +1,42 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright(C) 2023 Svyatoslav Ryhel <clamor95@gmail.com>
> + */
> +
> +#ifndef _MAX77663_H_
> +#define _MAX77663_H_
> +
> +#define MAX77663_LDO_NUM 9
> +#define MAX77663_SD_NUM 5
> +
> +/* Drivers name */
> +#define MAX77663_LDO_DRIVER "max77663_ldo"
> +#define MAX77663_SD_DRIVER "max77663_sd"
> +
> +/* Step-Down (SD) Regulator calculations */
> +#define SD_STATUS_MASK 0x30
> +
> +#define SD0_VOLT_MAX_HEX 0x40
> +#define SD1_VOLT_MAX_HEX 0x4c
> +#define SD_VOLT_MAX_HEX 0xff
> +#define SD_VOLT_MIN_HEX 0x02
> +
> +#define SD0_VOLT_MAX 1400000
> +#define SD1_VOLT_MAX 1550000
> +#define SD_VOLT_MAX 3787500
> +#define SD_VOLT_MIN 625000
> +
> +#define SD_VOLT_BASE 600000
> +
> +/* Low-Dropout Linear (LDO) Regulator calculations */
> +#define LDO_STATUS_MASK 0xc0
> +#define LDO_VOLT_MASK 0x3f
> +#define LDO_VOLT_MAX_HEX 0x3f
> +
> +#define LDO01_VOLT_MAX 2375000
Does it mean ldo0~1 or only ldo1?
> +#define LDO4_VOLT_MAX 1587500
> +#define LDO_VOLT_MAX 3950000
> +
> +#define LDO_VOLT_BASE 800000
> +
> +#endif /* _MAX77663_H_ */
> --
> 2.39.2
^ permalink raw reply [flat|nested] 14+ messages in thread
* RE: [PATCH v9 4/8] power: regulator: max77663: add regulator support
2023-10-27 8:26 ` [PATCH v9 4/8] power: regulator: max77663: add regulator support Svyatoslav Ryhel
@ 2023-10-31 8:58 ` Jaehoon Chung
0 siblings, 0 replies; 14+ messages in thread
From: Jaehoon Chung @ 2023-10-31 8:58 UTC (permalink / raw)
To: 'Svyatoslav Ryhel', 'Tom Rini',
'Simon Glass'
Cc: u-boot
> -----Original Message-----
> From: Svyatoslav Ryhel <clamor95@gmail.com>
> Sent: Friday, October 27, 2023 5:26 PM
> To: Tom Rini <trini@konsulko.com>; Jaehoon Chung <jh80.chung@samsung.com>; Simon Glass
> <sjg@chromium.org>; Svyatoslav Ryhel <clamor95@gmail.com>
> Cc: u-boot@lists.denx.de
> Subject: [PATCH v9 4/8] power: regulator: max77663: add regulator support
>
> The driver provides regulator set/get voltage
> enable/disable functions for MAXIM MAX77663 PMICs.
>
> Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>
Best Regards,
Jaehoon Chung
> ---
> drivers/power/regulator/Kconfig | 9 +
> drivers/power/regulator/Makefile | 1 +
> drivers/power/regulator/max77663_regulator.c | 375 +++++++++++++++++++
> 3 files changed, 385 insertions(+)
> create mode 100644 drivers/power/regulator/max77663_regulator.c
>
> diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig
> index eb5aa38c1c..581816294c 100644
> --- a/drivers/power/regulator/Kconfig
> +++ b/drivers/power/regulator/Kconfig
> @@ -141,6 +141,15 @@ config SPL_REGULATOR_PWM
> This config enables implementation of driver-model regulator uclass
> features for PWM regulators in SPL.
>
> +config DM_REGULATOR_MAX77663
> + bool "Enable Driver Model for REGULATOR MAX77663"
> + depends on DM_REGULATOR && DM_PMIC_MAX77663
> + ---help---
> + This config enables implementation of driver-model regulator uclass
> + features for REGULATOR MAX77663. The driver supports both DC-to-DC
> + Step-Down (SD) Regulators and Low-Dropout Linear (LDO) Regulators
> + found in MAX77663 PMIC and implements get/set api for value and enable.
> +
> config DM_REGULATOR_MAX77686
> bool "Enable Driver Model for REGULATOR MAX77686"
> depends on DM_REGULATOR && DM_PMIC_MAX77686
> diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile
> index d9e0cd5949..8d73169b50 100644
> --- a/drivers/power/regulator/Makefile
> +++ b/drivers/power/regulator/Makefile
> @@ -10,6 +10,7 @@ obj-$(CONFIG_REGULATOR_AS3722) += as3722_regulator.o
> obj-$(CONFIG_$(SPL_)REGULATOR_AXP) += axp_regulator.o
> obj-$(CONFIG_$(SPL_)REGULATOR_AXP_USB_POWER) += axp_usb_power.o
> obj-$(CONFIG_$(SPL_)DM_REGULATOR_DA9063) += da9063.o
> +obj-$(CONFIG_$(SPL_)DM_REGULATOR_MAX77663) += max77663_regulator.o
> obj-$(CONFIG_DM_REGULATOR_MAX77686) += max77686.o
> obj-$(CONFIG_DM_REGULATOR_NPCM8XX) += npcm8xx_regulator.o
> obj-$(CONFIG_$(SPL_)DM_PMIC_PFUZE100) += pfuze100.o
> diff --git a/drivers/power/regulator/max77663_regulator.c
> b/drivers/power/regulator/max77663_regulator.c
> new file mode 100644
> index 0000000000..ea4b7c63e5
> --- /dev/null
> +++ b/drivers/power/regulator/max77663_regulator.c
> @@ -0,0 +1,375 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright(C) 2023 Svyatoslav Ryhel <clamor95@gmail.com>
> + */
> +
> +#include <dm.h>
> +#include <power/pmic.h>
> +#include <power/regulator.h>
> +#include <power/max77663.h>
> +
> +/* fist row is control registers, second is voltage registers */
> +static const char max77663_sd_reg[][MAX77663_SD_NUM] = {
> + { 0x1d, 0x1e, 0x1f, 0x20, 0x21 },
> + { 0x16, 0x17, 0x18, 0x19, 0x2a },
> +};
> +
> +static const char max77663_ldo_reg[MAX77663_LDO_NUM] = {
> + 0x23, 0x25, 0x27, 0x29, 0x2b, 0x2d, 0x2f, 0x31, 0x33
> +};
> +
> +static int max77663_sd_enable(struct udevice *dev, int op, bool *enable)
> +{
> + struct dm_regulator_uclass_plat *uc_pdata =
> + dev_get_uclass_plat(dev);
> + u32 adr = uc_pdata->ctrl_reg;
> + int val, ret;
> +
> + val = pmic_reg_read(dev->parent, adr);
> + if (val < 0)
> + return val;
> +
> + if (op == PMIC_OP_GET) {
> + if (val & SD_STATUS_MASK)
> + *enable = true;
> + else
> + *enable = false;
> +
> + return 0;
> + } else if (op == PMIC_OP_SET) {
> + val &= ~SD_STATUS_MASK;
> +
> + if (*enable)
> + val |= SD_STATUS_MASK;
> +
> + ret = pmic_reg_write(dev->parent, adr, val);
> + if (ret)
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +/**
> + * max77663_*_volt2hex() - convert voltage in uV into
> + * applicable to register hex value
> + *
> + * @idx: regulator index
> + * @uV: voltage in uV
> + *
> + * Return: voltage in hex on success, -ve on failure
> + */
> +static int max77663_sd_volt2hex(int idx, int uV)
> +{
> + switch (idx) {
> + case 0:
> + /* SD0 has max voltage 1.4V */
> + if (uV > SD0_VOLT_MAX)
> + return -EINVAL;
> + break;
> + case 1:
> + /* SD1 has max voltage 1.55V */
> + if (uV > SD1_VOLT_MAX)
> + return -EINVAL;
> + break;
> + default:
> + /* SD2 and SD3 have max voltage 3.79V */
> + if (uV > SD_VOLT_MAX)
> + return -EINVAL;
> + break;
> + };
> +
> + if (uV < SD_VOLT_MIN)
> + uV = SD_VOLT_MIN;
> +
> + return (uV - SD_VOLT_BASE) / 12500;
> +}
> +
> +/**
> + * max77663_*_hex2volt() - convert register hex value into
> + * actual voltage in uV
> + *
> + * @idx: regulator index
> + * @hex: hex value of register
> + *
> + * Return: voltage in uV on success, -ve on failure
> + */
> +static int max77663_sd_hex2volt(int idx, int hex)
> +{
> + switch (idx) {
> + case 0:
> + /* SD0 has max voltage 1.4V */
> + if (hex > SD0_VOLT_MAX_HEX)
> + return -EINVAL;
> + break;
> + case 1:
> + /* SD1 has max voltage 1.55V */
> + if (hex > SD1_VOLT_MAX_HEX)
> + return -EINVAL;
> + break;
> + default:
> + /* SD2 and SD3 have max voltage 3.79V */
> + if (hex > SD_VOLT_MAX_HEX)
> + return -EINVAL;
> + break;
> + };
> +
> + if (hex < SD_VOLT_MIN_HEX)
> + hex = SD_VOLT_MIN_HEX;
> +
> + return SD_VOLT_BASE + hex * 12500;
> +}
> +
> +static int max77663_sd_val(struct udevice *dev, int op, int *uV)
> +{
> + struct dm_regulator_uclass_plat *uc_pdata =
> + dev_get_uclass_plat(dev);
> + u32 adr = uc_pdata->volt_reg;
> + int idx = dev->driver_data;
> + int hex, ret;
> +
> + if (op == PMIC_OP_GET) {
> + hex = pmic_reg_read(dev->parent, adr);
> + if (hex < 0)
> + return hex;
> +
> + *uV = 0;
> +
> + ret = max77663_sd_hex2volt(idx, hex);
> + if (ret < 0)
> + return ret;
> + *uV = ret;
> +
> + return 0;
> + }
> +
> + /* SD regulators use entire register for voltage */
> + hex = max77663_sd_volt2hex(idx, *uV);
> + if (hex < 0)
> + return hex;
> +
> + return pmic_reg_write(dev->parent, adr, hex);
> +}
> +
> +static int max77663_sd_probe(struct udevice *dev)
> +{
> + struct dm_regulator_uclass_plat *uc_pdata =
> + dev_get_uclass_plat(dev);
> + int idx = dev->driver_data;
> +
> + uc_pdata->type = REGULATOR_TYPE_BUCK;
> + uc_pdata->ctrl_reg = max77663_sd_reg[0][idx];
> + uc_pdata->volt_reg = max77663_sd_reg[1][idx];
> +
> + return 0;
> +}
> +
> +static int sd_get_value(struct udevice *dev)
> +{
> + int uV;
> + int ret;
> +
> + ret = max77663_sd_val(dev, PMIC_OP_GET, &uV);
> + if (ret)
> + return ret;
> +
> + return uV;
> +}
> +
> +static int sd_set_value(struct udevice *dev, int uV)
> +{
> + return max77663_sd_val(dev, PMIC_OP_SET, &uV);
> +}
> +
> +static int sd_get_enable(struct udevice *dev)
> +{
> + bool enable = false;
> + int ret;
> +
> + ret = max77663_sd_enable(dev, PMIC_OP_GET, &enable);
> + if (ret)
> + return ret;
> +
> + return enable;
> +}
> +
> +static int sd_set_enable(struct udevice *dev, bool enable)
> +{
> + return max77663_sd_enable(dev, PMIC_OP_SET, &enable);
> +}
> +
> +static const struct dm_regulator_ops max77663_sd_ops = {
> + .get_value = sd_get_value,
> + .set_value = sd_set_value,
> + .get_enable = sd_get_enable,
> + .set_enable = sd_set_enable,
> +};
> +
> +U_BOOT_DRIVER(max77663_sd) = {
> + .name = MAX77663_SD_DRIVER,
> + .id = UCLASS_REGULATOR,
> + .ops = &max77663_sd_ops,
> + .probe = max77663_sd_probe,
> +};
> +
> +static int max77663_ldo_enable(struct udevice *dev, int op, bool *enable)
> +{
> + struct dm_regulator_uclass_plat *uc_pdata =
> + dev_get_uclass_plat(dev);
> + u32 adr = uc_pdata->ctrl_reg;
> + int val, ret;
> +
> + val = pmic_reg_read(dev->parent, adr);
> + if (val < 0)
> + return val;
> +
> + if (op == PMIC_OP_GET) {
> + if (val & LDO_STATUS_MASK)
> + *enable = true;
> + else
> + *enable = false;
> +
> + return 0;
> + } else if (op == PMIC_OP_SET) {
> + val &= ~LDO_STATUS_MASK;
> +
> + if (*enable)
> + val |= LDO_STATUS_MASK;
> +
> + ret = pmic_reg_write(dev->parent, adr, val);
> + if (ret)
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static int max77663_ldo_volt2hex(int idx, int uV)
> +{
> + switch (idx) {
> + case 0:
> + case 1:
> + if (uV > LDO01_VOLT_MAX)
> + return -EINVAL;
> +
> + return (uV - LDO_VOLT_BASE) / 25000;
> + case 4:
> + if (uV > LDO4_VOLT_MAX)
> + return -EINVAL;
> +
> + return (uV - LDO_VOLT_BASE) / 12500;
> + default:
> + if (uV > LDO_VOLT_MAX)
> + return -EINVAL;
> +
> + return (uV - LDO_VOLT_BASE) / 50000;
> + };
> +}
> +
> +static int max77663_ldo_hex2volt(int idx, int hex)
> +{
> + if (hex > LDO_VOLT_MAX_HEX)
> + return -EINVAL;
> +
> + switch (idx) {
> + case 0:
> + case 1:
> + return (hex * 25000) + LDO_VOLT_BASE;
> + case 4:
> + return (hex * 12500) + LDO_VOLT_BASE;
> + default:
> + return (hex * 50000) + LDO_VOLT_BASE;
> + };
> +}
> +
> +static int max77663_ldo_val(struct udevice *dev, int op, int *uV)
> +{
> + struct dm_regulator_uclass_plat *uc_pdata =
> + dev_get_uclass_plat(dev);
> + u32 adr = uc_pdata->ctrl_reg;
> + int idx = dev->driver_data;
> + int hex, val, ret;
> +
> + val = pmic_reg_read(dev->parent, adr);
> + if (val < 0)
> + return val;
> +
> + if (op == PMIC_OP_GET) {
> + *uV = 0;
> +
> + ret = max77663_ldo_hex2volt(idx, val & LDO_VOLT_MASK);
> + if (ret < 0)
> + return ret;
> +
> + *uV = ret;
> + return 0;
> + }
> +
> + hex = max77663_ldo_volt2hex(idx, *uV);
> + if (hex < 0)
> + return hex;
> +
> + val &= ~LDO_VOLT_MASK;
> +
> + return pmic_reg_write(dev->parent, adr, val | hex);
> +}
> +
> +static int max77663_ldo_probe(struct udevice *dev)
> +{
> + struct dm_regulator_uclass_plat *uc_pdata =
> + dev_get_uclass_plat(dev);
> + int idx = dev->driver_data;
> +
> + uc_pdata->type = REGULATOR_TYPE_LDO;
> + uc_pdata->ctrl_reg = max77663_ldo_reg[idx];
> +
> + return 0;
> +}
> +
> +static int ldo_get_value(struct udevice *dev)
> +{
> + int uV;
> + int ret;
> +
> + ret = max77663_ldo_val(dev, PMIC_OP_GET, &uV);
> + if (ret)
> + return ret;
> +
> + return uV;
> +}
> +
> +static int ldo_set_value(struct udevice *dev, int uV)
> +{
> + return max77663_ldo_val(dev, PMIC_OP_SET, &uV);
> +}
> +
> +static int ldo_get_enable(struct udevice *dev)
> +{
> + bool enable = false;
> + int ret;
> +
> + ret = max77663_ldo_enable(dev, PMIC_OP_GET, &enable);
> + if (ret)
> + return ret;
> +
> + return enable;
> +}
> +
> +static int ldo_set_enable(struct udevice *dev, bool enable)
> +{
> + return max77663_ldo_enable(dev, PMIC_OP_SET, &enable);
> +}
> +
> +static const struct dm_regulator_ops max77663_ldo_ops = {
> + .get_value = ldo_get_value,
> + .set_value = ldo_set_value,
> + .get_enable = ldo_get_enable,
> + .set_enable = ldo_set_enable,
> +};
> +
> +U_BOOT_DRIVER(max77663_ldo) = {
> + .name = MAX77663_LDO_DRIVER,
> + .id = UCLASS_REGULATOR,
> + .ops = &max77663_ldo_ops,
> + .probe = max77663_ldo_probe,
> +};
> --
> 2.39.2
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v9 3/8] power: pmic: add the base MAX77663 PMIC support
2023-10-31 8:57 ` Jaehoon Chung
@ 2023-10-31 9:08 ` Svyatoslav Ryhel
0 siblings, 0 replies; 14+ messages in thread
From: Svyatoslav Ryhel @ 2023-10-31 9:08 UTC (permalink / raw)
To: Jaehoon Chung; +Cc: Tom Rini, Simon Glass, u-boot
вт, 31 жовт. 2023 р. о 10:57 Jaehoon Chung <jh80.chung@samsung.com> пише:
>
>
>
> > -----Original Message-----
> > From: Svyatoslav Ryhel <clamor95@gmail.com>
> > Sent: Friday, October 27, 2023 5:26 PM
> > To: Tom Rini <trini@konsulko.com>; Jaehoon Chung <jh80.chung@samsung.com>; Simon Glass
> > <sjg@chromium.org>; Svyatoslav Ryhel <clamor95@gmail.com>
> > Cc: u-boot@lists.denx.de
> > Subject: [PATCH v9 3/8] power: pmic: add the base MAX77663 PMIC support
> >
> > Add support to bind the regulators/child nodes with the pmic.
> > Also adds the pmic i2c based read/write functions to access pmic
> > registers.
> >
> > Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> > Reviewed-by: Simon Glass <sjg@chromium.org>
>
> Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>
>
> Just add a minor comment at below.
>
> > ---
> > doc/device-tree-bindings/pmic/max77663.txt | 84 ++++++++++++++++++++++
> > drivers/power/pmic/Kconfig | 9 +++
> > drivers/power/pmic/Makefile | 1 +
> > drivers/power/pmic/max77663.c | 81 +++++++++++++++++++++
> > include/power/max77663.h | 42 +++++++++++
> > 5 files changed, 217 insertions(+)
> > create mode 100644 doc/device-tree-bindings/pmic/max77663.txt
> > create mode 100644 drivers/power/pmic/max77663.c
> > create mode 100644 include/power/max77663.h
> >
> > diff --git a/doc/device-tree-bindings/pmic/max77663.txt b/doc/device-tree-bindings/pmic/max77663.txt
> > new file mode 100644
> > index 0000000000..ddb7d3eb14
> > --- /dev/null
> > +++ b/doc/device-tree-bindings/pmic/max77663.txt
> > @@ -0,0 +1,84 @@
> > +MAXIM, MAX77663 PMIC
> > +
> > +This device uses two drivers:
> > +- drivers/power/pmic/max77663.c (for parent device)
> > +- drivers/power/regulator/max77663_regulator.c (for child regulators)
> > +
> > +This chapter describes the binding info for the PMIC driver and regulators.
> > +
> > +Required properties for PMIC:
> > +- compatible: "maxim,max77663"
> > +- reg: usually 0x1c or 0x3c
> > +
> > +With those two properties, the pmic device can be used for read/write only.
> > +To bind each regulator, the optional regulators subnode should exists.
> > +
> > +Optional subnode:
> > +- name: regulators (subnode list of each device's regulator)
> > +
> > +Regulators subnode contains set on supported regulators.
> > +
> > +Required properties:
> > +- regulator-name: used for regulator uclass platform data '.name',
> > +
> > +List of supported regulator nodes names for max77663:
> > +- sd0, sd1, sd2, sd3, ldo0, ldo1, ldo2, ldo3, ldo4, ldo5, ldo6, ldo7, ldo8
> > +
> > +Optional:
> > +- regulator-min-microvolt: minimum allowed Voltage to set
> > +- regulator-max-microvolt: minimum allowed Voltage to set
> > +- regulator-always-on: regulator should be never disabled
> > +- regulator-boot-on: regulator should be enabled by the bootloader
> > +
> > +Linux driver binding for this driver is compatible.
> > +
> > +Example:
> > +
> > +max77663@1c {
> > + compatible = "maxim,max77663";
> > + reg = <0x1c>;
> > +
> > + regulators {
> > + sd0 {
> > + regulator-name = "vdd_cpu";
> > + regulator-min-microvolt = <800000>;
> > + regulator-max-microvolt = <1250000>;
> > + regulator-always-on;
> > + regulator-boot-on;
> > + };
> > +
> > + ...
> > +
> > + ldo0 {
> > + regulator-name = "avdd_pll";
> > + regulator-min-microvolt = <1200000>;
> > + regulator-max-microvolt = <1200000>;
> > + };
> > +
> > + ...
> > +
> > + ldo2 {
> > + regulator-name = "avdd_usb";
> > + regulator-min-microvolt = <3300000>;
> > + regulator-max-microvolt = <3300000>;
> > + regulator-always-on;
> > + regulator-boot-on;
> > + };
> > +
> > + ldo3 {
> > + regulator-name = "vdd_sdmmc3";
> > + regulator-min-microvolt = <3000000>;
> > + regulator-max-microvolt = <3000000>;
> > + regulator-always-on;
> > + regulator-boot-on;
> > + };
> > +
> > + ...
> > +
> > + ldo8 {
> > + regulator-name = "avdd_dsi_csi";
> > + regulator-min-microvolt = <1200000>;
> > + regulator-max-microvolt = <1200000>;
> > + };
> > + };
> > +};
> > diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig
> > index 4a6f0ce093..54665d7e2b 100644
> > --- a/drivers/power/pmic/Kconfig
> > +++ b/drivers/power/pmic/Kconfig
> > @@ -184,6 +184,15 @@ config SPL_DM_PMIC_PFUZE100
> > This config enables implementation of driver-model pmic uclass features
> > for PMIC PFUZE100 in SPL. The driver implements read/write operations.
> >
> > +config DM_PMIC_MAX77663
> > + bool "Enable Driver Model for PMIC MAX77663"
> > + ---help---
> > + This config enables implementation of driver-model pmic uclass features
> > + for PMIC MAX77663. The driver implements read/write operations.
> > + This is a Power Management IC with a decent set of peripherals from which
> > + 4 DC-to-DC Step-Down (SD) Regulators, 9 Low-Dropout Linear (LDO) Regulators,
> > + 8 GPIOs, Real-Time Clock (RTC) and more with I2C Compatible Interface.
> > +
> > config DM_PMIC_MAX77686
> > bool "Enable Driver Model for PMIC MAX77686"
> > ---help---
> > diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile
> > index 0b3b3d62d0..414a9d8225 100644
> > --- a/drivers/power/pmic/Makefile
> > +++ b/drivers/power/pmic/Makefile
> > @@ -6,6 +6,7 @@
> > obj-$(CONFIG_$(SPL_TPL_)DM_PMIC) += pmic-uclass.o
> > obj-$(CONFIG_$(SPL_)DM_PMIC_FAN53555) += fan53555.o
> > obj-$(CONFIG_$(SPL_)DM_PMIC_DA9063) += da9063.o
> > +obj-$(CONFIG_$(SPL_)DM_PMIC_MAX77663) += max77663.o
> > obj-$(CONFIG_DM_PMIC_MAX77686) += max77686.o
> > obj-$(CONFIG_DM_PMIC_MAX8998) += max8998.o
> > obj-$(CONFIG_DM_PMIC_MC34708) += mc34708.o
> > diff --git a/drivers/power/pmic/max77663.c b/drivers/power/pmic/max77663.c
> > new file mode 100644
> > index 0000000000..fac97ed221
> > --- /dev/null
> > +++ b/drivers/power/pmic/max77663.c
> > @@ -0,0 +1,81 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Copyright(C) 2023 Svyatoslav Ryhel <clamor95@gmail.com>
> > + */
> > +
> > +#include <dm.h>
> > +#include <dm/lists.h>
> > +#include <power/pmic.h>
> > +#include <power/max77663.h>
> > +
> > +static const struct pmic_child_info pmic_children_info[] = {
> > + { .prefix = "ldo", .driver = MAX77663_LDO_DRIVER },
> > + { .prefix = "sd", .driver = MAX77663_SD_DRIVER },
> > + { },
> > +};
> > +
> > +static int max77663_write(struct udevice *dev, uint reg, const uint8_t *buff,
> > + int len)
> > +{
> > + int ret;
> > +
> > + ret = dm_i2c_write(dev, reg, buff, len);
> > + if (ret) {
> > + log_debug("write error to device: %p register: %#x!\n", dev, reg);
> > + return ret;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static int max77663_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
> > +{
> > + int ret;
> > +
> > + ret = dm_i2c_read(dev, reg, buff, len);
> > + if (ret) {
> > + log_debug("read error from device: %p register: %#x!\n", dev, reg);
> > + return ret;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static int max77663_bind(struct udevice *dev)
> > +{
> > + ofnode regulators_node;
> > + int children;
> > +
> > + regulators_node = dev_read_subnode(dev, "regulators");
> > + if (!ofnode_valid(regulators_node)) {
> > + log_err("%s regulators subnode not found!\n", 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)
> > + log_err("%s - no child found\n", dev->name);
> > +
> > + /* Always return success for this device */
> > + return 0;
> > +}
> > +
> > +static struct dm_pmic_ops max77663_ops = {
> > + .read = max77663_read,
> > + .write = max77663_write,
> > +};
> > +
> > +static const struct udevice_id max77663_ids[] = {
> > + { .compatible = "maxim,max77663" },
> > + { }
> > +};
> > +
> > +U_BOOT_DRIVER(pmic_max77663) = {
> > + .name = "max77663_pmic",
> > + .id = UCLASS_PMIC,
> > + .of_match = max77663_ids,
> > + .bind = max77663_bind,
> > + .ops = &max77663_ops,
> > +};
> > diff --git a/include/power/max77663.h b/include/power/max77663.h
> > new file mode 100644
> > index 0000000000..0f764bcbcc
> > --- /dev/null
> > +++ b/include/power/max77663.h
> > @@ -0,0 +1,42 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * Copyright(C) 2023 Svyatoslav Ryhel <clamor95@gmail.com>
> > + */
> > +
> > +#ifndef _MAX77663_H_
> > +#define _MAX77663_H_
> > +
> > +#define MAX77663_LDO_NUM 9
> > +#define MAX77663_SD_NUM 5
> > +
> > +/* Drivers name */
> > +#define MAX77663_LDO_DRIVER "max77663_ldo"
> > +#define MAX77663_SD_DRIVER "max77663_sd"
> > +
> > +/* Step-Down (SD) Regulator calculations */
> > +#define SD_STATUS_MASK 0x30
> > +
> > +#define SD0_VOLT_MAX_HEX 0x40
> > +#define SD1_VOLT_MAX_HEX 0x4c
> > +#define SD_VOLT_MAX_HEX 0xff
> > +#define SD_VOLT_MIN_HEX 0x02
> > +
> > +#define SD0_VOLT_MAX 1400000
> > +#define SD1_VOLT_MAX 1550000
> > +#define SD_VOLT_MAX 3787500
> > +#define SD_VOLT_MIN 625000
> > +
> > +#define SD_VOLT_BASE 600000
> > +
> > +/* Low-Dropout Linear (LDO) Regulator calculations */
> > +#define LDO_STATUS_MASK 0xc0
> > +#define LDO_VOLT_MASK 0x3f
> > +#define LDO_VOLT_MAX_HEX 0x3f
> > +
> > +#define LDO01_VOLT_MAX 2375000
>
> Does it mean ldo0~1 or only ldo1?
>
0 and 1, then 4 and then the rest. They are grouped by common the
properties (max voltage and step)
Best regards,
Svyatoslav R.
> > +#define LDO4_VOLT_MAX 1587500
> > +#define LDO_VOLT_MAX 3950000
> > +
> > +#define LDO_VOLT_BASE 800000
> > +
> > +#endif /* _MAX77663_H_ */
> > --
> > 2.39.2
>
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v9 1/8] power: pmic: palmas: support TI TPS65913 PMIC
2023-10-27 8:26 ` [PATCH v9 1/8] power: pmic: palmas: support TI TPS65913 PMIC Svyatoslav Ryhel
2023-10-31 6:44 ` Jaehoon Chung
@ 2023-11-04 13:57 ` Tom Rini
1 sibling, 0 replies; 14+ messages in thread
From: Tom Rini @ 2023-11-04 13:57 UTC (permalink / raw)
To: Svyatoslav Ryhel; +Cc: Jaehoon Chung, Simon Glass, u-boot
[-- Attachment #1: Type: text/plain, Size: 597 bytes --]
On Fri, Oct 27, 2023 at 11:26:08AM +0300, Svyatoslav Ryhel wrote:
> Existing PALMAS PMIC driver is fully compatible with TI TPS65913
> PMIC found in many Tegra 4 devices, like Tegra Note 7 and ASUS
> TF701T. TPS65913 shares same structure of regulators like TPS659038
> so data can be reused.
>
> Tested-by: Svyatoslav Ryhel <clamor95@gmail.com> # NVIDIA Tegratab
> Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>
For the series, applied to u-boot/master, thanks!
--
Tom
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2023-11-04 13:59 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-10-27 8:26 [PATCH v9 0/8] Add support for PMICs used on Tegra 3 devices Svyatoslav Ryhel
2023-10-27 8:26 ` [PATCH v9 1/8] power: pmic: palmas: support TI TPS65913 PMIC Svyatoslav Ryhel
2023-10-31 6:44 ` Jaehoon Chung
2023-11-04 13:57 ` Tom Rini
2023-10-27 8:26 ` [PATCH v9 2/8] power: regulator: palmas: fix ldoln and ldousb detection Svyatoslav Ryhel
2023-10-27 8:26 ` [PATCH v9 3/8] power: pmic: add the base MAX77663 PMIC support Svyatoslav Ryhel
2023-10-31 8:57 ` Jaehoon Chung
2023-10-31 9:08 ` Svyatoslav Ryhel
2023-10-27 8:26 ` [PATCH v9 4/8] power: regulator: max77663: add regulator support Svyatoslav Ryhel
2023-10-31 8:58 ` Jaehoon Chung
2023-10-27 8:26 ` [PATCH v9 5/8] power: pmic: add the base TPS80031 PMIC support Svyatoslav Ryhel
2023-10-27 8:26 ` [PATCH v9 6/8] power: regulator: tps80031: add regulator support Svyatoslav Ryhel
2023-10-27 8:26 ` [PATCH v9 7/8] power: pmic: tps65910: add TPS65911 PMIC support Svyatoslav Ryhel
2023-10-27 8:26 ` [PATCH v9 8/8] power: regulator: tps65911: add regulator support Svyatoslav Ryhel
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.