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 | 502 +++++++++++++++++++++++++++
3 files changed, 513 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..32400ab1f616
--- /dev/null
+++ b/drivers/regulator/sc2730-regulator.c
@@ -0,0 +1,502 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018-2021 Unisoc Inc.
+ */
+
+#include <linux/debugfs.h>
+#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 struct dentry *debugfs_root;
+
+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 debugfs_enable_get(void *data, u64 *val)
+{
+ struct regulator_dev *rdev = data;
+
+ if (rdev && rdev->desc->ops->is_enabled)
+ *val = rdev->desc->ops->is_enabled(rdev);
+ else
+ *val = ~0ULL;
+ return 0;
+}
+
+static int debugfs_enable_set(void *data, u64 val)
+{
+ struct regulator_dev *rdev = data;
+
+ if (rdev && rdev->desc->ops->enable && rdev->desc->ops->disable) {
+ if (val)
+ rdev->desc->ops->enable(rdev);
+ else
+ rdev->desc->ops->disable(rdev);
+ }
+
+ return 0;
+}
+
+static int debugfs_voltage_get(void *data, u64 *val)
+{
+ int sel, ret;
+ struct regulator_dev *rdev = data;
+
+ sel = rdev->desc->ops->get_voltage_sel(rdev);
+ if (sel < 0)
+ return sel;
+
+ ret = rdev->desc->ops->list_voltage(rdev, sel);
+
+ *val = ret / 1000;
+
+ return 0;
+}
+
+static int debugfs_voltage_set(void *data, u64 val)
+{
+ int selector;
+ struct regulator_dev *rdev = data;
+
+ val = val * 1000;
+ selector = regulator_map_voltage_linear(rdev,
+ val - rdev->desc->uV_step / 2,
+ val + rdev->desc->uV_step / 2);
+
+ return rdev->desc->ops->set_voltage_sel(rdev, selector);
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(fops_enable,
+ debugfs_enable_get, debugfs_enable_set, "%llu\n");
+DEFINE_SIMPLE_ATTRIBUTE(fops_ldo,
+ debugfs_voltage_get, debugfs_voltage_set, "%llu\n");
+
+static void sc2730_regulator_debugfs_init(struct regulator_dev *rdev)
+{
+
+ debugfs_root = debugfs_create_dir(rdev->desc->name, NULL);
+
+ if (IS_ERR_OR_NULL(debugfs_root)) {
+ dev_warn(&rdev->dev, "Failed to create debugfs directory\n");
+ rdev->debugfs = NULL;
+ return;
+ }
+
+ debugfs_create_file("enable", 0644,
+ debugfs_root, rdev, &fops_enable);
+ debugfs_create_file("voltage", 0644,
+ debugfs_root, rdev, &fops_ldo);
+}
+
+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, ®ulators[i],
+ &config);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "failed to register regulator %s\n",
+ regulators[i].name);
+ return PTR_ERR(rdev);
+ }
+
+ sc2730_regulator_debugfs_init(rdev);
+ }
+
+ return 0;
+}
+
+static int sc2730_regulator_remove(struct platform_device *pdev)
+{
+ debugfs_remove_recursive(debugfs_root);
+ 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,
+ .remove = sc2730_regulator_remove,
+};
+module_platform_driver(sc2730_regulator_driver);
+
+MODULE_DESCRIPTION("Unisoc SC2730 regulator driver");
+MODULE_LICENSE("GPL");
--
2.25.1
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]>
---
.../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..04e504418e35
--- /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
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]>
---
.../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
On Tue, Sep 28, 2021 at 03:36:08PM +0800, Chunyan Zhang wrote:
> +++ b/drivers/regulator/sc2730-regulator.c
> @@ -0,0 +1,502 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2018-2021 Unisoc Inc.
> + */
Please make the entire comment a C++ one so things look more
intentional.
> +static int debugfs_enable_get(void *data, u64 *val)
> +{
> + struct regulator_dev *rdev = data;
> +
> +static int debugfs_enable_set(void *data, u64 val)
> +{
> + struct regulator_dev *rdev = data;
> +
> +static int debugfs_voltage_get(void *data, u64 *val)
> +{
> +static int debugfs_voltage_set(void *data, u64 val)
> +{
If these were to be implemented they should be in the core as there's
nothing device specific about them (the read side is there), please
remove them from the driver.
> +static const struct of_device_id sc2730_regulator_match[] = {
> + { .compatible = "sprd,sc2730-regulator" },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, sc2730_regulator_match);
Since this is a part of a MFD I'd not expect it to have a compatible
string?
On Tue, 28 Sept 2021 at 19:31, Mark Brown <[email protected]> wrote:
>
> On Tue, Sep 28, 2021 at 03:36:08PM +0800, Chunyan Zhang wrote:
>
> > +++ b/drivers/regulator/sc2730-regulator.c
> > @@ -0,0 +1,502 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (C) 2018-2021 Unisoc Inc.
> > + */
>
> Please make the entire comment a C++ one so things look more
> intentional.
Ok.
>
> > +static int debugfs_enable_get(void *data, u64 *val)
> > +{
> > + struct regulator_dev *rdev = data;
> > +
>
> > +static int debugfs_enable_set(void *data, u64 val)
> > +{
> > + struct regulator_dev *rdev = data;
> > +
>
> > +static int debugfs_voltage_get(void *data, u64 *val)
> > +{
>
> > +static int debugfs_voltage_set(void *data, u64 val)
> > +{
>
> If these were to be implemented they should be in the core as there's
> nothing device specific about them (the read side is there), please
> remove them from the driver.
Ok.
>
> > +static const struct of_device_id sc2730_regulator_match[] = {
> > + { .compatible = "sprd,sc2730-regulator" },
> > + {},
> > +};
> > +MODULE_DEVICE_TABLE(of, sc2730_regulator_match);
>
> Since this is a part of a MFD I'd not expect it to have a compatible
> string?
Since we switched to use devm_of_platform_populate() [1] to register
MFD subdevices, compatible is required, IIUC.
[1] https://elixir.bootlin.com/linux/latest/source/drivers/mfd/sprd-sc27xx-spi.c#L199
Thanks for the review,
Chunyan
On Wed, Sep 29, 2021 at 04:20:37PM +0800, Chunyan Zhang wrote:
> On Tue, 28 Sept 2021 at 19:31, Mark Brown <[email protected]> wrote:
> > Since this is a part of a MFD I'd not expect it to have a compatible
> > string?
> Since we switched to use devm_of_platform_populate() [1] to register
> MFD subdevices, compatible is required, IIUC.
I'm not sure that's a good fit for these regulators, we don't gain any
extra information from the compatible here.
+Lee Jones
On Wed, 29 Sept 2021 at 20:30, Mark Brown <[email protected]> wrote:
>
> On Wed, Sep 29, 2021 at 04:20:37PM +0800, Chunyan Zhang wrote:
> > On Tue, 28 Sept 2021 at 19:31, Mark Brown <[email protected]> wrote:
>
> > > Since this is a part of a MFD I'd not expect it to have a compatible
> > > string?
>
> > Since we switched to use devm_of_platform_populate() [1] to register
> > MFD subdevices, compatible is required, IIUC.
>
> I'm not sure that's a good fit for these regulators, we don't gain any
> extra information from the compatible here.
Humm... regulators cannot be probed without compatible for this case,
except we have a list of mfd_cells which include compatible and driver
name in sc27xx_spi (mfd) driver.
On different platforms, sc27xx_spi consists of different sub-devices
with different compatible string, to avoid adding mfd_cells to
sc27xx_spi driver each time we add a new platform support, we changed
to use devm_of_platform_populate() which can automatically register
sun-devices listed in devicetree.
The above is my understand, please correct me if I'm missing something
@Lee Jones
Thanks,
Chunyan
[1] https://lkml.org/lkml/2020/6/19/207
On Thu, Sep 30, 2021 at 11:12:28AM +0800, Chunyan Zhang wrote:
> On different platforms, sc27xx_spi consists of different sub-devices
> with different compatible string, to avoid adding mfd_cells to
> sc27xx_spi driver each time we add a new platform support, we changed
> to use devm_of_platform_populate() which can automatically register
> sun-devices listed in devicetree.
> The above is my understand, please correct me if I'm missing something
> @Lee Jones
Right, so my pushback here is that it's not clear to me that avoiding
adding compatibles to the MFD is a strong enough goal to justify
creating ABI - it's hard to see the upsides. This is particularly the
case here where the subdevice is really a random collection of devices
that's particularly likely to change between variants and more likely
that other OSs would want something different so it's even harder to
achieve reuse.
On Tue, 28 Sep 2021 16:46:07 +0800, Chunyan Zhang wrote:
> 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]>
> ---
> .../regulator/sprd,sc2730-regulator.yaml | 61 +++++++++++++++++++
> 1 file changed, 61 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/regulator/sprd,sc2730-regulator.yaml
>
Reviewed-by: Rob Herring <[email protected]>