public inbox for u-boot@lists.denx.de
 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox