2021-10-08 03:22:20

by Chunyan Zhang

[permalink] [raw]
Subject: [PATCH v2 0/2] Add Unisoc's SC2730 regulator support

From: Chunyan Zhang <[email protected]>

Changes since v1:
* Addressed Mark's comments:
- Removed debugfs things from SC2730 driver and deleted sc2730_regulator_remove() which deal with debugfs only;
- Changed to use C++ style comments on the head of driver.
* Added Rob's Reviewed-by for bindings changes.

Chunyan Zhang (1):
dt-bindings: regulator: Add bindings for Unisoc's SC2730 regulator

Zhongfa Wang (1):
regulator: Add Unisoc's SC2730 regulator driver

.../regulator/sprd,sc2730-regulator.yaml | 61 +++
drivers/regulator/Kconfig | 10 +
drivers/regulator/Makefile | 1 +
drivers/regulator/sc2730-regulator.c | 404 ++++++++++++++++++
4 files changed, 476 insertions(+)
create mode 100644 Documentation/devicetree/bindings/regulator/sprd,sc2730-regulator.yaml
create mode 100644 drivers/regulator/sc2730-regulator.c

--
2.25.1


2021-10-08 03:22:28

by Chunyan Zhang

[permalink] [raw]
Subject: [PATCH v2 1/2] regulator: Add Unisoc's SC2730 regulator driver

From: Zhongfa Wang <[email protected]>

Add SC2730 regulator driver which is used on Unisoc's UMS512 SoC.

Signed-off-by: Zhongfa Wang <[email protected]>
Signed-off-by: Chunyan Zhang <[email protected]>
---
drivers/regulator/Kconfig | 10 +
drivers/regulator/Makefile | 1 +
drivers/regulator/sc2730-regulator.c | 404 +++++++++++++++++++++++++++
3 files changed, 415 insertions(+)
create mode 100644 drivers/regulator/sc2730-regulator.c

diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 4fd13b06231f..e1ecfc703a07 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -1110,6 +1110,16 @@ config REGULATOR_S5M8767
via I2C bus. S5M8767A have 9 Bucks and 28 LDOs output and
supports DVS mode with 8bits of output voltage control.

+config REGULATOR_SC2730
+ tristate "Spreadtrum SC2730 power regulator driver"
+ depends on MFD_SC27XX_PMIC || COMPILE_TEST
+ help
+ This driver provides support for the voltage regulators on the
+ SC2730 PMIC.
+
+ This driver can also be built as a module. If so, the module
+ will be called sc2730-regulator.
+
config REGULATOR_SC2731
tristate "Spreadtrum SC2731 power regulator driver"
depends on MFD_SC27XX_PMIC || COMPILE_TEST
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 9e382b50a5ef..22ffdbde88d7 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -133,6 +133,7 @@ obj-$(CONFIG_REGULATOR_RTQ6752) += rtq6752-regulator.o
obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o
obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
+obj-$(CONFIG_REGULATOR_SC2730) += sc2730-regulator.o
obj-$(CONFIG_REGULATOR_SC2731) += sc2731-regulator.o
obj-$(CONFIG_REGULATOR_SKY81452) += sky81452-regulator.o
obj-$(CONFIG_REGULATOR_SLG51000) += slg51000-regulator.o
diff --git a/drivers/regulator/sc2730-regulator.c b/drivers/regulator/sc2730-regulator.c
new file mode 100644
index 000000000000..8d997fb16dae
--- /dev/null
+++ b/drivers/regulator/sc2730-regulator.c
@@ -0,0 +1,404 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2018-2021 Unisoc Inc.
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+
+#define SC2730_REGULATOR_BASE 0x1800
+
+
+/* SC2730 regulator lock register */
+#define SC2730_WR_UNLOCK_VALUE 0x6e7f
+#define SC2730_PWR_WR_PROT (SC2730_REGULATOR_BASE + 0x3d0)
+
+/* SC2730 enable register */
+#define SC2730_POWER_PD_SW (SC2730_REGULATOR_BASE + 0x01c)
+#define SC2730_LDO_VDDRF18_PD (SC2730_REGULATOR_BASE + 0x10c)
+#define SC2730_LDO_VDDCAMIO_PD (SC2730_REGULATOR_BASE + 0x118)
+#define SC2730_LDO_VDDWCN_PD (SC2730_REGULATOR_BASE + 0x11c)
+#define SC2730_LDO_VDDCAMD1_PD (SC2730_REGULATOR_BASE + 0x128)
+#define SC2730_LDO_VDDCAMD0_PD (SC2730_REGULATOR_BASE + 0x134)
+#define SC2730_LDO_VDDRF1V25_PD (SC2730_REGULATOR_BASE + 0x140)
+#define SC2730_LDO_AVDD12_PD (SC2730_REGULATOR_BASE + 0x14c)
+#define SC2730_LDO_VDDCAMA0_PD (SC2730_REGULATOR_BASE + 0x158)
+#define SC2730_LDO_VDDCAMA1_PD (SC2730_REGULATOR_BASE + 0x164)
+#define SC2730_LDO_VDDCAMMOT_PD (SC2730_REGULATOR_BASE + 0x170)
+#define SC2730_LDO_VDDSIM2_PD (SC2730_REGULATOR_BASE + 0x194)
+#define SC2730_LDO_VDDEMMCCORE_PD (SC2730_REGULATOR_BASE + 0x1a0)
+#define SC2730_LDO_VDDSDCORE_PD (SC2730_REGULATOR_BASE + 0x1ac)
+#define SC2730_LDO_VDDSDIO_PD (SC2730_REGULATOR_BASE + 0x1b8)
+#define SC2730_LDO_VDDWIFIPA_PD (SC2730_REGULATOR_BASE + 0x1d0)
+#define SC2730_LDO_VDDUSB33_PD (SC2730_REGULATOR_BASE + 0x1e8)
+#define SC2730_LDO_VDDLDO0_PD (SC2730_REGULATOR_BASE + 0x1f4)
+#define SC2730_LDO_VDDLDO1_PD (SC2730_REGULATOR_BASE + 0x200)
+#define SC2730_LDO_VDDLDO2_PD (SC2730_REGULATOR_BASE + 0x20c)
+#define SC2730_LDO_VDDKPLED_PD (SC2730_REGULATOR_BASE + 0x38c)
+
+/* SC2730 enable mask */
+#define SC2730_DCDC_CPU_PD_MASK BIT(4)
+#define SC2730_DCDC_GPU_PD_MASK BIT(3)
+#define SC2730_DCDC_CORE_PD_MASK BIT(5)
+#define SC2730_DCDC_MODEM_PD_MASK BIT(11)
+#define SC2730_DCDC_MEM_PD_MASK BIT(6)
+#define SC2730_DCDC_MEMQ_PD_MASK BIT(12)
+#define SC2730_DCDC_GEN0_PD_MASK BIT(8)
+#define SC2730_DCDC_GEN1_PD_MASK BIT(7)
+#define SC2730_DCDC_SRAM_PD_MASK BIT(13)
+#define SC2730_LDO_AVDD18_PD_MASK BIT(2)
+#define SC2730_LDO_VDDRF18_PD_MASK BIT(0)
+#define SC2730_LDO_VDDCAMIO_PD_MASK BIT(0)
+#define SC2730_LDO_VDDWCN_PD_MASK BIT(0)
+#define SC2730_LDO_VDDCAMD1_PD_MASK BIT(0)
+#define SC2730_LDO_VDDCAMD0_PD_MASK BIT(0)
+#define SC2730_LDO_VDDRF1V25_PD_MASK BIT(0)
+#define SC2730_LDO_AVDD12_PD_MASK BIT(0)
+#define SC2730_LDO_VDDCAMA0_PD_MASK BIT(0)
+#define SC2730_LDO_VDDCAMA1_PD_MASK BIT(0)
+#define SC2730_LDO_VDDCAMMOT_PD_MASK BIT(0)
+#define SC2730_LDO_VDDSIM2_PD_MASK BIT(0)
+#define SC2730_LDO_VDDEMMCCORE_PD_MASK BIT(0)
+#define SC2730_LDO_VDDSDCORE_PD_MASK BIT(0)
+#define SC2730_LDO_VDDSDIO_PD_MASK BIT(0)
+#define SC2730_LDO_VDD28_PD_MASK BIT(1)
+#define SC2730_LDO_VDDWIFIPA_PD_MASK BIT(0)
+#define SC2730_LDO_VDD18_DCXO_PD_MASK BIT(10)
+#define SC2730_LDO_VDDUSB33_PD_MASK BIT(0)
+#define SC2730_LDO_VDDLDO0_PD_MASK BIT(0)
+#define SC2730_LDO_VDDLDO1_PD_MASK BIT(0)
+#define SC2730_LDO_VDDLDO2_PD_MASK BIT(0)
+#define SC2730_LDO_VDDKPLED_PD_MASK BIT(15)
+
+/* SC2730 vsel register */
+#define SC2730_DCDC_CPU_VOL (SC2730_REGULATOR_BASE + 0x44)
+#define SC2730_DCDC_GPU_VOL (SC2730_REGULATOR_BASE + 0x54)
+#define SC2730_DCDC_CORE_VOL (SC2730_REGULATOR_BASE + 0x64)
+#define SC2730_DCDC_MODEM_VOL (SC2730_REGULATOR_BASE + 0x74)
+#define SC2730_DCDC_MEM_VOL (SC2730_REGULATOR_BASE + 0x84)
+#define SC2730_DCDC_MEMQ_VOL (SC2730_REGULATOR_BASE + 0x94)
+#define SC2730_DCDC_GEN0_VOL (SC2730_REGULATOR_BASE + 0xa4)
+#define SC2730_DCDC_GEN1_VOL (SC2730_REGULATOR_BASE + 0xb4)
+#define SC2730_DCDC_SRAM_VOL (SC2730_REGULATOR_BASE + 0xdc)
+#define SC2730_LDO_AVDD18_VOL (SC2730_REGULATOR_BASE + 0x104)
+#define SC2730_LDO_VDDRF18_VOL (SC2730_REGULATOR_BASE + 0x110)
+#define SC2730_LDO_VDDCAMIO_VOL (SC2730_REGULATOR_BASE + 0x28)
+#define SC2730_LDO_VDDWCN_VOL (SC2730_REGULATOR_BASE + 0x120)
+#define SC2730_LDO_VDDCAMD1_VOL (SC2730_REGULATOR_BASE + 0x12c)
+#define SC2730_LDO_VDDCAMD0_VOL (SC2730_REGULATOR_BASE + 0x138)
+#define SC2730_LDO_VDDRF1V25_VOL (SC2730_REGULATOR_BASE + 0x144)
+#define SC2730_LDO_AVDD12_VOL (SC2730_REGULATOR_BASE + 0x150)
+#define SC2730_LDO_VDDCAMA0_VOL (SC2730_REGULATOR_BASE + 0x15c)
+#define SC2730_LDO_VDDCAMA1_VOL (SC2730_REGULATOR_BASE + 0x168)
+#define SC2730_LDO_VDDCAMMOT_VOL (SC2730_REGULATOR_BASE + 0x174)
+#define SC2730_LDO_VDDSIM2_VOL (SC2730_REGULATOR_BASE + 0x198)
+#define SC2730_LDO_VDDEMMCCORE_VOL (SC2730_REGULATOR_BASE + 0x1a4)
+#define SC2730_LDO_VDDSDCORE_VOL (SC2730_REGULATOR_BASE + 0x1b0)
+#define SC2730_LDO_VDDSDIO_VOL (SC2730_REGULATOR_BASE + 0x1bc)
+#define SC2730_LDO_VDD28_VOL (SC2730_REGULATOR_BASE + 0x1c8)
+#define SC2730_LDO_VDDWIFIPA_VOL (SC2730_REGULATOR_BASE + 0x1d4)
+#define SC2730_LDO_VDD18_DCXO_VOL (SC2730_REGULATOR_BASE + 0x1e0)
+#define SC2730_LDO_VDDUSB33_VOL (SC2730_REGULATOR_BASE + 0x1ec)
+#define SC2730_LDO_VDDLDO0_VOL (SC2730_REGULATOR_BASE + 0x1f8)
+#define SC2730_LDO_VDDLDO1_VOL (SC2730_REGULATOR_BASE + 0x204)
+#define SC2730_LDO_VDDLDO2_VOL (SC2730_REGULATOR_BASE + 0x210)
+#define SC2730_LDO_VDDKPLED_VOL (SC2730_REGULATOR_BASE + 0x38c)
+
+/* SC2730 vsel register mask */
+#define SC2730_DCDC_CPU_VOL_MASK GENMASK(8, 0)
+#define SC2730_DCDC_GPU_VOL_MASK GENMASK(8, 0)
+#define SC2730_DCDC_CORE_VOL_MASK GENMASK(8, 0)
+#define SC2730_DCDC_MODEM_VOL_MASK GENMASK(8, 0)
+#define SC2730_DCDC_MEM_VOL_MASK GENMASK(7, 0)
+#define SC2730_DCDC_MEMQ_VOL_MASK GENMASK(8, 0)
+#define SC2730_DCDC_GEN0_VOL_MASK GENMASK(7, 0)
+#define SC2730_DCDC_GEN1_VOL_MASK GENMASK(7, 0)
+#define SC2730_DCDC_SRAM_VOL_MASK GENMASK(8, 0)
+#define SC2730_LDO_AVDD18_VOL_MASK GENMASK(5, 0)
+#define SC2730_LDO_VDDRF18_VOL_MASK GENMASK(5, 0)
+#define SC2730_LDO_VDDCAMIO_VOL_MASK GENMASK(5, 0)
+#define SC2730_LDO_VDDWCN_VOL_MASK GENMASK(5, 0)
+#define SC2730_LDO_VDDCAMD1_VOL_MASK GENMASK(4, 0)
+#define SC2730_LDO_VDDCAMD0_VOL_MASK GENMASK(4, 0)
+#define SC2730_LDO_VDDRF1V25_VOL_MASK GENMASK(4, 0)
+#define SC2730_LDO_AVDD12_VOL_MASK GENMASK(4, 0)
+#define SC2730_LDO_VDDCAMA0_VOL_MASK GENMASK(7, 0)
+#define SC2730_LDO_VDDCAMA1_VOL_MASK GENMASK(7, 0)
+#define SC2730_LDO_VDDCAMMOT_VOL_MASK GENMASK(7, 0)
+#define SC2730_LDO_VDDSIM2_VOL_MASK GENMASK(7, 0)
+#define SC2730_LDO_VDDEMMCCORE_VOL_MASK GENMASK(7, 0)
+#define SC2730_LDO_VDDSDCORE_VOL_MASK GENMASK(7, 0)
+#define SC2730_LDO_VDDSDIO_VOL_MASK GENMASK(7, 0)
+#define SC2730_LDO_VDD28_VOL_MASK GENMASK(7, 0)
+#define SC2730_LDO_VDDWIFIPA_VOL_MASK GENMASK(7, 0)
+#define SC2730_LDO_VDD18_DCXO_VOL_MASK GENMASK(7, 0)
+#define SC2730_LDO_VDDUSB33_VOL_MASK GENMASK(7, 0)
+#define SC2730_LDO_VDDLDO0_VOL_MASK GENMASK(7, 0)
+#define SC2730_LDO_VDDLDO1_VOL_MASK GENMASK(7, 0)
+#define SC2730_LDO_VDDLDO2_VOL_MASK GENMASK(7, 0)
+#define SC2730_LDO_VDDKPLED_VOL_MASK GENMASK(14, 7)
+
+enum sc2730_regulator_id {
+ SC2730_DCDC_CPU,
+ SC2730_DCDC_GPU,
+ SC2730_DCDC_CORE,
+ SC2730_DCDC_MODEM,
+ SC2730_DCDC_MEM,
+ SC2730_DCDC_MEMQ,
+ SC2730_DCDC_GEN0,
+ SC2730_DCDC_GEN1,
+ SC2730_DCDC_SRAM,
+ SC2730_LDO_AVDD18,
+ SC2730_LDO_VDDRF18,
+ SC2730_LDO_VDDCAMIO,
+ SC2730_LDO_VDDWCN,
+ SC2730_LDO_VDDCAMD1,
+ SC2730_LDO_VDDCAMD0,
+ SC2730_LDO_VDDRF1V25,
+ SC2730_LDO_AVDD12,
+ SC2730_LDO_VDDCAMA0,
+ SC2730_LDO_VDDCAMA1,
+ SC2730_LDO_VDDCAMMOT,
+ SC2730_LDO_VDDSIM0,
+ SC2730_LDO_VDDSIM1,
+ SC2730_LDO_VDDSIM2,
+ SC2730_LDO_VDDEMMCCORE,
+ SC2730_LDO_VDDSDCORE,
+ SC2730_LDO_VDDSDIO,
+ SC2730_LDO_VDD28,
+ SC2730_LDO_VDDWIFIPA,
+ SC2730_LDO_VDD18_DCXO,
+ SC2730_LDO_VDDUSB33,
+ SC2730_LDO_VDDLDO0,
+ SC2730_LDO_VDDLDO1,
+ SC2730_LDO_VDDLDO2,
+ SC2730_LDO_VDDKPLED,
+};
+
+static const struct regulator_ops sc2730_regu_linear_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .list_voltage = regulator_list_voltage_linear,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+};
+
+#define SC2730_REGU_LINEAR(_id, en_reg, en_mask, vreg, vmask, \
+ vstep, vmin, vmax, min_sel) { \
+ .name = #_id, \
+ .of_match = of_match_ptr(#_id), \
+ .ops = &sc2730_regu_linear_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = SC2730_##_id, \
+ .owner = THIS_MODULE, \
+ .min_uV = vmin, \
+ .n_voltages = ((vmax) - (vmin)) / (vstep) + 1, \
+ .uV_step = vstep, \
+ .enable_is_inverted = true, \
+ .enable_val = 0, \
+ .enable_reg = en_reg, \
+ .enable_mask = en_mask, \
+ .vsel_reg = vreg, \
+ .vsel_mask = vmask, \
+ .linear_min_sel = min_sel, \
+}
+
+static struct regulator_desc regulators[] = {
+ SC2730_REGU_LINEAR(DCDC_CPU, SC2730_POWER_PD_SW,
+ SC2730_DCDC_CPU_PD_MASK, SC2730_DCDC_CPU_VOL,
+ SC2730_DCDC_CPU_VOL_MASK, 3125, 0, 1596875,
+ 0),
+ SC2730_REGU_LINEAR(DCDC_GPU, SC2730_POWER_PD_SW,
+ SC2730_DCDC_GPU_PD_MASK, SC2730_DCDC_GPU_VOL,
+ SC2730_DCDC_GPU_VOL_MASK, 3125, 0, 1596875,
+ 0),
+ SC2730_REGU_LINEAR(DCDC_CORE, SC2730_POWER_PD_SW,
+ SC2730_DCDC_CORE_PD_MASK, SC2730_DCDC_CORE_VOL,
+ SC2730_DCDC_CORE_VOL_MASK, 3125, 0, 1596875,
+ 0),
+ SC2730_REGU_LINEAR(DCDC_MODEM, SC2730_POWER_PD_SW,
+ SC2730_DCDC_MODEM_PD_MASK, SC2730_DCDC_MODEM_VOL,
+ SC2730_DCDC_MODEM_VOL_MASK, 3125, 0, 1596875,
+ 0),
+ SC2730_REGU_LINEAR(DCDC_MEM, SC2730_POWER_PD_SW,
+ SC2730_DCDC_MEM_PD_MASK, SC2730_DCDC_MEM_VOL,
+ SC2730_DCDC_MEM_VOL_MASK, 6250, 0, 1593750,
+ 0),
+ SC2730_REGU_LINEAR(DCDC_MEMQ, SC2730_POWER_PD_SW,
+ SC2730_DCDC_MEMQ_PD_MASK, SC2730_DCDC_MEMQ_VOL,
+ SC2730_DCDC_MEMQ_VOL_MASK, 3125, 0, 1596875,
+ 0),
+ SC2730_REGU_LINEAR(DCDC_GEN0, SC2730_POWER_PD_SW,
+ SC2730_DCDC_GEN0_PD_MASK, SC2730_DCDC_GEN0_VOL,
+ SC2730_DCDC_GEN0_VOL_MASK, 9375, 20000, 2410625,
+ 0),
+ SC2730_REGU_LINEAR(DCDC_GEN1, SC2730_POWER_PD_SW,
+ SC2730_DCDC_GEN1_PD_MASK, SC2730_DCDC_GEN1_VOL,
+ SC2730_DCDC_GEN1_VOL_MASK, 6250, 50000, 1643750,
+ 0),
+ SC2730_REGU_LINEAR(DCDC_SRAM, SC2730_POWER_PD_SW,
+ SC2730_DCDC_SRAM_PD_MASK, SC2730_DCDC_SRAM_VOL,
+ SC2730_DCDC_SRAM_VOL_MASK, 3125, 0, 1596875,
+ 0),
+ SC2730_REGU_LINEAR(LDO_AVDD18, SC2730_POWER_PD_SW,
+ SC2730_LDO_AVDD18_PD_MASK, SC2730_LDO_AVDD18_VOL,
+ SC2730_LDO_AVDD18_VOL_MASK, 10000, 1175000, 1805000,
+ 0),
+ SC2730_REGU_LINEAR(LDO_VDDRF18, SC2730_LDO_VDDRF18_PD,
+ SC2730_LDO_VDDRF18_PD_MASK, SC2730_LDO_VDDRF18_VOL,
+ SC2730_LDO_VDDRF18_VOL_MASK, 10000, 1175000, 1805000,
+ 0),
+ SC2730_REGU_LINEAR(LDO_VDDCAMIO, SC2730_LDO_VDDCAMIO_PD,
+ SC2730_LDO_VDDCAMIO_PD_MASK, SC2730_LDO_VDDCAMIO_VOL,
+ SC2730_LDO_VDDCAMIO_VOL_MASK, 10000, 1200000,
+ 1830000, 0),
+ SC2730_REGU_LINEAR(LDO_VDDWCN, SC2730_LDO_VDDWCN_PD,
+ SC2730_LDO_VDDWCN_PD_MASK, SC2730_LDO_VDDWCN_VOL,
+ SC2730_LDO_VDDWCN_VOL_MASK, 15000, 900000, 1845000,
+ 0),
+ SC2730_REGU_LINEAR(LDO_VDDCAMD1, SC2730_LDO_VDDCAMD1_PD,
+ SC2730_LDO_VDDCAMD1_PD_MASK, SC2730_LDO_VDDCAMD1_VOL,
+ SC2730_LDO_VDDCAMD1_VOL_MASK, 15000, 900000,
+ 1365000, 0),
+ SC2730_REGU_LINEAR(LDO_VDDCAMD0, SC2730_LDO_VDDCAMD0_PD,
+ SC2730_LDO_VDDCAMD0_PD_MASK, SC2730_LDO_VDDCAMD0_VOL,
+ SC2730_LDO_VDDCAMD0_VOL_MASK, 15000, 900000,
+ 1365000, 0),
+ SC2730_REGU_LINEAR(LDO_VDDRF1V25, SC2730_LDO_VDDRF1V25_PD,
+ SC2730_LDO_VDDRF1V25_PD_MASK,
+ SC2730_LDO_VDDRF1V25_VOL,
+ SC2730_LDO_VDDRF1V25_VOL_MASK, 15000, 900000,
+ 1365000, 0),
+ SC2730_REGU_LINEAR(LDO_AVDD12, SC2730_LDO_AVDD12_PD,
+ SC2730_LDO_AVDD12_PD_MASK, SC2730_LDO_AVDD12_VOL,
+ SC2730_LDO_AVDD12_VOL_MASK, 15000, 900000, 1365000,
+ 0),
+ SC2730_REGU_LINEAR(LDO_VDDCAMA0, SC2730_LDO_VDDCAMA0_PD,
+ SC2730_LDO_VDDCAMA0_PD_MASK, SC2730_LDO_VDDCAMA0_VOL,
+ SC2730_LDO_VDDCAMA0_VOL_MASK, 10000, 1200000,
+ 3750000, 0),
+ SC2730_REGU_LINEAR(LDO_VDDCAMA1, SC2730_LDO_VDDCAMA1_PD,
+ SC2730_LDO_VDDCAMA1_PD_MASK, SC2730_LDO_VDDCAMA1_VOL,
+ SC2730_LDO_VDDCAMA1_VOL_MASK, 10000, 1200000,
+ 3750000, 0),
+ SC2730_REGU_LINEAR(LDO_VDDCAMMOT, SC2730_LDO_VDDCAMMOT_PD,
+ SC2730_LDO_VDDCAMMOT_PD_MASK,
+ SC2730_LDO_VDDCAMMOT_VOL,
+ SC2730_LDO_VDDCAMMOT_VOL_MASK, 10000, 1200000,
+ 3750000, 0),
+ SC2730_REGU_LINEAR(LDO_VDDSIM2, SC2730_LDO_VDDSIM2_PD,
+ SC2730_LDO_VDDSIM2_PD_MASK, SC2730_LDO_VDDSIM2_VOL,
+ SC2730_LDO_VDDSIM2_VOL_MASK, 10000, 1200000, 3750000,
+ 0),
+ SC2730_REGU_LINEAR(LDO_VDDEMMCCORE, SC2730_LDO_VDDEMMCCORE_PD,
+ SC2730_LDO_VDDEMMCCORE_PD_MASK,
+ SC2730_LDO_VDDEMMCCORE_VOL,
+ SC2730_LDO_VDDEMMCCORE_VOL_MASK, 10000, 1200000,
+ 3750000, 0),
+ SC2730_REGU_LINEAR(LDO_VDDSDCORE, SC2730_LDO_VDDSDCORE_PD,
+ SC2730_LDO_VDDSDCORE_PD_MASK,
+ SC2730_LDO_VDDSDCORE_VOL,
+ SC2730_LDO_VDDSDCORE_VOL_MASK, 10000, 1200000,
+ 3750000, 0),
+ SC2730_REGU_LINEAR(LDO_VDDSDIO, SC2730_LDO_VDDSDIO_PD,
+ SC2730_LDO_VDDSDIO_PD_MASK, SC2730_LDO_VDDSDIO_VOL,
+ SC2730_LDO_VDDSDIO_VOL_MASK, 10000, 1200000, 3750000,
+ 0),
+ SC2730_REGU_LINEAR(LDO_VDD28, SC2730_POWER_PD_SW,
+ SC2730_LDO_VDD28_PD_MASK, SC2730_LDO_VDD28_VOL,
+ SC2730_LDO_VDD28_VOL_MASK, 10000, 1200000, 3750000,
+ 0),
+ SC2730_REGU_LINEAR(LDO_VDDWIFIPA, SC2730_LDO_VDDWIFIPA_PD,
+ SC2730_LDO_VDDWIFIPA_PD_MASK,
+ SC2730_LDO_VDDWIFIPA_VOL,
+ SC2730_LDO_VDDWIFIPA_VOL_MASK, 10000, 1200000,
+ 3750000, 0),
+ SC2730_REGU_LINEAR(LDO_VDD18_DCXO, SC2730_POWER_PD_SW,
+ SC2730_LDO_VDD18_DCXO_PD_MASK,
+ SC2730_LDO_VDD18_DCXO_VOL,
+ SC2730_LDO_VDD18_DCXO_VOL_MASK, 10000, 1200000,
+ 3750000, 0),
+ SC2730_REGU_LINEAR(LDO_VDDUSB33, SC2730_LDO_VDDUSB33_PD,
+ SC2730_LDO_VDDUSB33_PD_MASK, SC2730_LDO_VDDUSB33_VOL,
+ SC2730_LDO_VDDUSB33_VOL_MASK, 10000, 1200000,
+ 3750000, 0),
+ SC2730_REGU_LINEAR(LDO_VDDLDO0, SC2730_LDO_VDDLDO0_PD,
+ SC2730_LDO_VDDLDO0_PD_MASK, SC2730_LDO_VDDLDO0_VOL,
+ SC2730_LDO_VDDLDO0_VOL_MASK, 10000, 1200000, 3750000,
+ 0),
+ SC2730_REGU_LINEAR(LDO_VDDLDO1, SC2730_LDO_VDDLDO1_PD,
+ SC2730_LDO_VDDLDO1_PD_MASK, SC2730_LDO_VDDLDO1_VOL,
+ SC2730_LDO_VDDLDO1_VOL_MASK, 10000, 1200000, 3750000,
+ 0),
+ SC2730_REGU_LINEAR(LDO_VDDLDO2, SC2730_LDO_VDDLDO2_PD,
+ SC2730_LDO_VDDLDO2_PD_MASK, SC2730_LDO_VDDLDO2_VOL,
+ SC2730_LDO_VDDLDO2_VOL_MASK, 10000, 1200000, 3750000,
+ 0),
+ SC2730_REGU_LINEAR(LDO_VDDKPLED, SC2730_LDO_VDDKPLED_PD,
+ SC2730_LDO_VDDKPLED_PD_MASK, SC2730_LDO_VDDKPLED_VOL,
+ SC2730_LDO_VDDKPLED_VOL_MASK, 10000, 1200000,
+ 3750000, 0),
+};
+
+static int sc2730_regulator_unlock(struct regmap *regmap)
+{
+ return regmap_write(regmap, SC2730_PWR_WR_PROT,
+ SC2730_WR_UNLOCK_VALUE);
+}
+
+static int sc2730_regulator_probe(struct platform_device *pdev)
+{
+ int i, ret;
+ struct regmap *regmap;
+ struct regulator_config config = { };
+ struct regulator_dev *rdev;
+
+ regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!regmap) {
+ dev_err(&pdev->dev, "failed to get regmap.\n");
+ return -ENODEV;
+ }
+
+ ret = sc2730_regulator_unlock(regmap);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to release regulator lock\n");
+ return ret;
+ }
+
+ config.dev = &pdev->dev;
+ config.regmap = regmap;
+
+ for (i = 0; i < ARRAY_SIZE(regulators); i++) {
+ rdev = devm_regulator_register(&pdev->dev, &regulators[i],
+ &config);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "failed to register regulator %s\n",
+ regulators[i].name);
+ return PTR_ERR(rdev);
+ }
+ }
+
+ return 0;
+}
+
+static const struct of_device_id sc2730_regulator_match[] = {
+ { .compatible = "sprd,sc2730-regulator" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, sc2730_regulator_match);
+
+static struct platform_driver sc2730_regulator_driver = {
+ .driver = {
+ .name = "sc2730-regulator",
+ .of_match_table = sc2730_regulator_match,
+ },
+ .probe = sc2730_regulator_probe,
+};
+module_platform_driver(sc2730_regulator_driver);
+
+MODULE_DESCRIPTION("Unisoc SC2730 regulator driver");
+MODULE_LICENSE("GPL");
--
2.25.1

2021-10-08 03:22:39

by Chunyan Zhang

[permalink] [raw]
Subject: [PATCH v2 2/2] dt-bindings: regulator: Add bindings for Unisoc's SC2730 regulator

From: Chunyan Zhang <[email protected]>

SC2730 is used on Unisoc's UMS512 SoC, it integrates low-voltage and low
quiescent current DCDC/LDO.

Signed-off-by: Chunyan Zhang <[email protected]>
Reviewed-by: Rob Herring <[email protected]>
---
.../regulator/sprd,sc2730-regulator.yaml | 61 +++++++++++++++++++
1 file changed, 61 insertions(+)
create mode 100644 Documentation/devicetree/bindings/regulator/sprd,sc2730-regulator.yaml

diff --git a/Documentation/devicetree/bindings/regulator/sprd,sc2730-regulator.yaml b/Documentation/devicetree/bindings/regulator/sprd,sc2730-regulator.yaml
new file mode 100644
index 000000000000..6d1bec03eb52
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/sprd,sc2730-regulator.yaml
@@ -0,0 +1,61 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright 2019-2021 Unisoc Inc.
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/regulator/sprd,sc2730-regulator.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Unisoc SC2730 Voltage Regulators Device Tree Bindings
+
+maintainers:
+ - Orson Zhai <[email protected]>
+ - Baolin Wang <[email protected]>
+ - Chunyan Zhang <[email protected]>
+
+properties:
+ compatible:
+ const: sprd,sc2730-regulator
+
+ reg:
+ maxItems: 1
+
+patternProperties:
+ "^(DCDC|BUCK|LDO)_.+":
+ # Child node
+ type: object
+ description: dcdc/buck/ldo regulator nodes(s).
+ $ref: "regulator.yaml#"
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ pmic {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ regulators@1800 {
+ compatible = "sprd,sc2730-regulator";
+ reg = <0x1800>;
+
+ DCDC_CPU {
+ regulator-name = "vddcpu";
+ regulator-min-microvolt = <200000>;
+ regulator-max-microvolt = <1596875>;
+ regulator-ramp-delay = <25000>;
+ regulator-always-on;
+ };
+
+ LDO_VDDWCN {
+ regulator-name = "vddwcn";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1845000>;
+ regulator-ramp-delay = <25000>;
+ };
+ };
+ };
+...
--
2.25.1

2021-11-12 13:46:47

by Mark Brown

[permalink] [raw]
Subject: Re: [PATCH v2 2/2] dt-bindings: regulator: Add bindings for Unisoc's SC2730 regulator

On Fri, Oct 08, 2021 at 11:19:53AM +0800, Chunyan Zhang wrote:

> +properties:
> + compatible:
> + const: sprd,sc2730-regulator

I still don't understand why this MFD subfunction for a specific device
is a separate binding with a separate compatible string, the issues I
mentioned previously with this just encoding current Linux internals
into the DT rather than describing the device still apply.


Attachments:
(No filename) (403.00 B)
signature.asc (488.00 B)
Download all attachments

2022-09-22 08:44:49

by Chunyan Zhang

[permalink] [raw]
Subject: Re: [PATCH v2 2/2] dt-bindings: regulator: Add bindings for Unisoc's SC2730 regulator

Hi Mark,

Sorry for the late response.
[1] is the v1 on which we had some discussion. I hope that can help
recall the issue below.

On Fri, 12 Nov 2021 at 21:46, Mark Brown <[email protected]> wrote:
>
> On Fri, Oct 08, 2021 at 11:19:53AM +0800, Chunyan Zhang wrote:
>
> > +properties:
> > + compatible:
> > + const: sprd,sc2730-regulator
>
> I still don't understand why this MFD subfunction for a specific device
> is a separate binding with a separate compatible string, the issues I
> mentioned previously with this just encoding current Linux internals
> into the DT rather than describing the device still apply.

I understand your point. But like I described previously [1], if we
still use the current solution (i.e. use devm_of_platform_populate()
to register MFD subdevices), a compatible string is required. I'm open
to switching to other solutions, do you have some suggestions?

Thanks,
Chunyan

[1] https://lkml.org/lkml/2021/9/29/1166

2022-09-22 10:43:55

by Lee Jones

[permalink] [raw]
Subject: Re: [PATCH v2 2/2] dt-bindings: regulator: Add bindings for Unisoc's SC2730 regulator

On Thu, 22 Sep 2022, Chunyan Zhang wrote:

> Hi Mark,
>
> Sorry for the late response.
> [1] is the v1 on which we had some discussion. I hope that can help
> recall the issue below.
>
> On Fri, 12 Nov 2021 at 21:46, Mark Brown <[email protected]> wrote:
> >
> > On Fri, Oct 08, 2021 at 11:19:53AM +0800, Chunyan Zhang wrote:
> >
> > > +properties:
> > > + compatible:
> > > + const: sprd,sc2730-regulator
> >
> > I still don't understand why this MFD subfunction for a specific device
> > is a separate binding with a separate compatible string, the issues I
> > mentioned previously with this just encoding current Linux internals
> > into the DT rather than describing the device still apply.
>
> I understand your point. But like I described previously [1], if we
> still use the current solution (i.e. use devm_of_platform_populate()
> to register MFD subdevices), a compatible string is required. I'm open
> to switching to other solutions, do you have some suggestions?

Many IPs encompassing multiple functions are described that way in
DT. I don't have the details for *this* device to hand, so my
comments here aren't specific to this use-case, but describing each
function individually does describe the H/W accurately, which is all
DT calls for.

Can you imagine describing an SoC, which can be considered as a huge
MFD, with only a single node?

Does the regulator functionality have it's own bank of registers?

--
DEPRECATED: Please use [email protected]

2022-09-22 12:43:12

by Mark Brown

[permalink] [raw]
Subject: Re: [PATCH v2 2/2] dt-bindings: regulator: Add bindings for Unisoc's SC2730 regulator

On Thu, Sep 22, 2022 at 11:19:08AM +0100, Lee Jones wrote:
> On Thu, 22 Sep 2022, Chunyan Zhang wrote:

> > I understand your point. But like I described previously [1], if we
> > still use the current solution (i.e. use devm_of_platform_populate()
> > to register MFD subdevices), a compatible string is required. I'm open
> > to switching to other solutions, do you have some suggestions?
>
> Many IPs encompassing multiple functions are described that way in
> DT. I don't have the details for *this* device to hand, so my
> comments here aren't specific to this use-case, but describing each
> function individually does describe the H/W accurately, which is all
> DT calls for.

If people want to describe the individual regulators that'd be
less of an issue, it's mainly when you're nesting what's
effectively another MFD within a parent MFD that it's just noise
that's being added to the DT.

> Can you imagine describing an SoC, which can be considered as a huge
> MFD, with only a single node?

Honestly we should be arranging things so they're more like that,
at least using overlays for the internals of the SoC so you don't
have to rebuild the whole DT for updates to the SoC internals.


Attachments:
(No filename) (1.20 kB)
signature.asc (499.00 B)
Download all attachments

2022-09-26 08:01:20

by Lee Jones

[permalink] [raw]
Subject: Re: [PATCH v2 2/2] dt-bindings: regulator: Add bindings for Unisoc's SC2730 regulator

On Thu, 22 Sep 2022, Mark Brown wrote:

> On Thu, Sep 22, 2022 at 11:19:08AM +0100, Lee Jones wrote:
> > On Thu, 22 Sep 2022, Chunyan Zhang wrote:
>
> > > I understand your point. But like I described previously [1], if we
> > > still use the current solution (i.e. use devm_of_platform_populate()
> > > to register MFD subdevices), a compatible string is required. I'm open
> > > to switching to other solutions, do you have some suggestions?
> >
> > Many IPs encompassing multiple functions are described that way in
> > DT. I don't have the details for *this* device to hand, so my
> > comments here aren't specific to this use-case, but describing each
> > function individually does describe the H/W accurately, which is all
> > DT calls for.
>
> If people want to describe the individual regulators that'd be
> less of an issue, it's mainly when you're nesting what's
> effectively another MFD within a parent MFD that it's just noise
> that's being added to the DT.

As I say, I haven't studied this use-case.

These comments were designed to be more generic.

What do you mean by nested MFDs?

> > Can you imagine describing an SoC, which can be considered as a huge
> > MFD, with only a single node?
>
> Honestly we should be arranging things so they're more like that,
> at least using overlays for the internals of the SoC so you don't
> have to rebuild the whole DT for updates to the SoC internals.

Right, there would be one device root node. However each function;
clock providers, regulator controllers, PWMs, GPIOs, networking
(various), reset, watchdog, etc would have their own nodes. Rather
than attempting to describe everything in the parent's node.

--
DEPRECATED: Please use [email protected]

2022-09-28 17:41:33

by Mark Brown

[permalink] [raw]
Subject: Re: [PATCH v2 2/2] dt-bindings: regulator: Add bindings for Unisoc's SC2730 regulator

On Mon, Sep 26, 2022 at 07:59:08AM +0100, Lee Jones wrote:
> On Thu, 22 Sep 2022, Mark Brown wrote:

> > If people want to describe the individual regulators that'd be
> > less of an issue, it's mainly when you're nesting what's
> > effectively another MFD within a parent MFD that it's just noise
> > that's being added to the DT.

> As I say, I haven't studied this use-case.

> These comments were designed to be more generic.

> What do you mean by nested MFDs?

Given that individual regulators tend to be separate physical IPs in the
chip if you create a single device tree node that lumps them together
you still need to also represent the individual regulators as well so
that collection is functioning like a MFD does except not on a chip
boundary.

> > > Can you imagine describing an SoC, which can be considered as a huge
> > > MFD, with only a single node?

> > Honestly we should be arranging things so they're more like that,
> > at least using overlays for the internals of the SoC so you don't
> > have to rebuild the whole DT for updates to the SoC internals.

> Right, there would be one device root node. However each function;
> clock providers, regulator controllers, PWMs, GPIOs, networking
> (various), reset, watchdog, etc would have their own nodes. Rather
> than attempting to describe everything in the parent's node.

We don't split things up by function, we split them up by IP - we don't
just allocate a compatible for all the networking related functionality
simply because there's a networking subsystem in Linux for example.


Attachments:
(No filename) (1.56 kB)
signature.asc (499.00 B)
Download all attachments