All of lore.kernel.org
 help / color / mirror / Atom feed
* [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.