Files
linux/drivers/regulator/sc2730-regulator.c
Otto Pflüger 4c40e28e83 regulator: Add regulator driver for Unisoc SC2730 PMIC
Add a regulator driver for the Spreadtrum/Unisoc SC2730 PMIC, used
e.g. with the UMS512 and UMS9230 SoCs. This version of the driver is
based on a downstream driver provided by Unisoc [1][2] and the existing
SC2731 driver.

[1]: https://github.com/MotorolaMobilityLLC/kernel-sprd/commit/30be0ddfe6b9a877fc9c328fbd2bae84e645eb31
[2]: https://github.com/MotorolaMobilityLLC/kernel-sprd/blob/android-13-release-tla33/drivers/regulator/sc2730-regulator.c

Signed-off-by: Zhongfa Wang <zhongfa.wang@unisoc.com>
[cleanup, adapt to new device tree requirements]
Signed-off-by: Otto Pflüger <otto.pflueger@abscue.de>
Link: https://patch.msgid.link/20260701-sc2730-regulators-v7-2-6e145ce83657@abscue.de
Signed-off-by: Mark Brown <broonie@kernel.org>
2026-07-03 13:27:19 +01:00

376 lines
16 KiB
C

// 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>
/*
* SC2730 regulator base address
*/
#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_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, of_name, en_reg, en_mask, vreg, vmask, \
vstep, vmin, vmax) { \
.name = #_id, \
.of_match = of_name, \
.regulators_node = "regulators", \
.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 = 0, \
}
static const struct regulator_desc regulators[] = {
SC2730_REGU_LINEAR(DCDC_CPU, "dcdc-cpu", SC2730_POWER_PD_SW,
SC2730_DCDC_CPU_PD_MASK, SC2730_DCDC_CPU_VOL,
SC2730_DCDC_CPU_VOL_MASK, 3125, 0, 1596875),
SC2730_REGU_LINEAR(DCDC_GPU, "dcdc-gpu", SC2730_POWER_PD_SW,
SC2730_DCDC_GPU_PD_MASK, SC2730_DCDC_GPU_VOL,
SC2730_DCDC_GPU_VOL_MASK, 3125, 0, 1596875),
SC2730_REGU_LINEAR(DCDC_CORE, "dcdc-core", SC2730_POWER_PD_SW,
SC2730_DCDC_CORE_PD_MASK, SC2730_DCDC_CORE_VOL,
SC2730_DCDC_CORE_VOL_MASK, 3125, 0, 1596875),
SC2730_REGU_LINEAR(DCDC_MODEM, "dcdc-modem", SC2730_POWER_PD_SW,
SC2730_DCDC_MODEM_PD_MASK, SC2730_DCDC_MODEM_VOL,
SC2730_DCDC_MODEM_VOL_MASK, 3125, 0, 1596875),
SC2730_REGU_LINEAR(DCDC_MEM, "dcdc-mem", SC2730_POWER_PD_SW,
SC2730_DCDC_MEM_PD_MASK, SC2730_DCDC_MEM_VOL,
SC2730_DCDC_MEM_VOL_MASK, 6250, 0, 1593750),
SC2730_REGU_LINEAR(DCDC_MEMQ, "dcdc-memq", SC2730_POWER_PD_SW,
SC2730_DCDC_MEMQ_PD_MASK, SC2730_DCDC_MEMQ_VOL,
SC2730_DCDC_MEMQ_VOL_MASK, 3125, 0, 1596875),
SC2730_REGU_LINEAR(DCDC_GEN0, "dcdc-gen0", SC2730_POWER_PD_SW,
SC2730_DCDC_GEN0_PD_MASK, SC2730_DCDC_GEN0_VOL,
SC2730_DCDC_GEN0_VOL_MASK, 9375, 20000, 2410625),
SC2730_REGU_LINEAR(DCDC_GEN1, "dcdc-gen1", SC2730_POWER_PD_SW,
SC2730_DCDC_GEN1_PD_MASK, SC2730_DCDC_GEN1_VOL,
SC2730_DCDC_GEN1_VOL_MASK, 6250, 50000, 1643750),
SC2730_REGU_LINEAR(DCDC_SRAM, "dcdc-sram", SC2730_POWER_PD_SW,
SC2730_DCDC_SRAM_PD_MASK, SC2730_DCDC_SRAM_VOL,
SC2730_DCDC_SRAM_VOL_MASK, 3125, 0, 1596875),
SC2730_REGU_LINEAR(LDO_AVDD18, "ldo-avdd18", SC2730_POWER_PD_SW,
SC2730_LDO_AVDD18_PD_MASK, SC2730_LDO_AVDD18_VOL,
SC2730_LDO_AVDD18_VOL_MASK, 10000, 1175000, 1805000),
SC2730_REGU_LINEAR(LDO_VDDRF18, "ldo-vddrf18", SC2730_LDO_VDDRF18_PD,
SC2730_LDO_VDDRF18_PD_MASK, SC2730_LDO_VDDRF18_VOL,
SC2730_LDO_VDDRF18_VOL_MASK, 10000, 1175000, 1805000),
SC2730_REGU_LINEAR(LDO_VDDCAMIO, "ldo-vddcamio", SC2730_LDO_VDDCAMIO_PD,
SC2730_LDO_VDDCAMIO_PD_MASK, SC2730_LDO_VDDCAMIO_VOL,
SC2730_LDO_VDDCAMIO_VOL_MASK, 10000, 1200000, 1830000),
SC2730_REGU_LINEAR(LDO_VDDWCN, "ldo-vddwcn", SC2730_LDO_VDDWCN_PD,
SC2730_LDO_VDDWCN_PD_MASK, SC2730_LDO_VDDWCN_VOL,
SC2730_LDO_VDDWCN_VOL_MASK, 15000, 900000, 1845000),
SC2730_REGU_LINEAR(LDO_VDDCAMD1, "ldo-vddcamd1", SC2730_LDO_VDDCAMD1_PD,
SC2730_LDO_VDDCAMD1_PD_MASK, SC2730_LDO_VDDCAMD1_VOL,
SC2730_LDO_VDDCAMD1_VOL_MASK, 15000, 900000, 1365000),
SC2730_REGU_LINEAR(LDO_VDDCAMD0, "ldo-vddcamd0", SC2730_LDO_VDDCAMD0_PD,
SC2730_LDO_VDDCAMD0_PD_MASK, SC2730_LDO_VDDCAMD0_VOL,
SC2730_LDO_VDDCAMD0_VOL_MASK, 15000, 900000, 1365000),
SC2730_REGU_LINEAR(LDO_VDDRF1V25, "ldo-vddrf1v25", SC2730_LDO_VDDRF1V25_PD,
SC2730_LDO_VDDRF1V25_PD_MASK, SC2730_LDO_VDDRF1V25_VOL,
SC2730_LDO_VDDRF1V25_VOL_MASK, 15000, 900000, 1365000),
SC2730_REGU_LINEAR(LDO_AVDD12, "ldo-avdd12", SC2730_LDO_AVDD12_PD,
SC2730_LDO_AVDD12_PD_MASK, SC2730_LDO_AVDD12_VOL,
SC2730_LDO_AVDD12_VOL_MASK, 15000, 900000, 1365000),
SC2730_REGU_LINEAR(LDO_VDDCAMA0, "ldo-vddcama0", SC2730_LDO_VDDCAMA0_PD,
SC2730_LDO_VDDCAMA0_PD_MASK, SC2730_LDO_VDDCAMA0_VOL,
SC2730_LDO_VDDCAMA0_VOL_MASK, 10000, 1200000, 3750000),
SC2730_REGU_LINEAR(LDO_VDDCAMA1, "ldo-vddcama1", SC2730_LDO_VDDCAMA1_PD,
SC2730_LDO_VDDCAMA1_PD_MASK, SC2730_LDO_VDDCAMA1_VOL,
SC2730_LDO_VDDCAMA1_VOL_MASK, 10000, 1200000, 3750000),
SC2730_REGU_LINEAR(LDO_VDDCAMMOT, "ldo-vddcammot", SC2730_LDO_VDDCAMMOT_PD,
SC2730_LDO_VDDCAMMOT_PD_MASK, SC2730_LDO_VDDCAMMOT_VOL,
SC2730_LDO_VDDCAMMOT_VOL_MASK, 10000, 1200000, 3750000),
SC2730_REGU_LINEAR(LDO_VDDSIM2, "ldo-vddsim2", SC2730_LDO_VDDSIM2_PD,
SC2730_LDO_VDDSIM2_PD_MASK, SC2730_LDO_VDDSIM2_VOL,
SC2730_LDO_VDDSIM2_VOL_MASK, 10000, 1200000, 3750000),
SC2730_REGU_LINEAR(LDO_VDDEMMCCORE, "ldo-vddemmccore", SC2730_LDO_VDDEMMCCORE_PD,
SC2730_LDO_VDDEMMCCORE_PD_MASK, SC2730_LDO_VDDEMMCCORE_VOL,
SC2730_LDO_VDDEMMCCORE_VOL_MASK, 10000, 1200000, 3750000),
SC2730_REGU_LINEAR(LDO_VDDSDCORE, "ldo-vddsdcore", SC2730_LDO_VDDSDCORE_PD,
SC2730_LDO_VDDSDCORE_PD_MASK, SC2730_LDO_VDDSDCORE_VOL,
SC2730_LDO_VDDSDCORE_VOL_MASK, 10000, 1200000, 3750000),
SC2730_REGU_LINEAR(LDO_VDDSDIO, "ldo-vddsdio", SC2730_LDO_VDDSDIO_PD,
SC2730_LDO_VDDSDIO_PD_MASK, SC2730_LDO_VDDSDIO_VOL,
SC2730_LDO_VDDSDIO_VOL_MASK, 10000, 1200000, 3750000),
SC2730_REGU_LINEAR(LDO_VDD28, "ldo-vdd28", SC2730_POWER_PD_SW,
SC2730_LDO_VDD28_PD_MASK, SC2730_LDO_VDD28_VOL,
SC2730_LDO_VDD28_VOL_MASK, 10000, 1200000, 3750000),
SC2730_REGU_LINEAR(LDO_VDDWIFIPA, "ldo-vddwifipa", SC2730_LDO_VDDWIFIPA_PD,
SC2730_LDO_VDDWIFIPA_PD_MASK, SC2730_LDO_VDDWIFIPA_VOL,
SC2730_LDO_VDDWIFIPA_VOL_MASK, 10000, 1200000, 3750000),
SC2730_REGU_LINEAR(LDO_VDD18_DCXO, "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),
SC2730_REGU_LINEAR(LDO_VDDUSB33, "ldo-vddusb33", SC2730_LDO_VDDUSB33_PD,
SC2730_LDO_VDDUSB33_PD_MASK, SC2730_LDO_VDDUSB33_VOL,
SC2730_LDO_VDDUSB33_VOL_MASK, 10000, 1200000, 3750000),
SC2730_REGU_LINEAR(LDO_VDDLDO0, "ldo-vddldo0", SC2730_LDO_VDDLDO0_PD,
SC2730_LDO_VDDLDO0_PD_MASK, SC2730_LDO_VDDLDO0_VOL,
SC2730_LDO_VDDLDO0_VOL_MASK, 10000, 1200000, 3750000),
SC2730_REGU_LINEAR(LDO_VDDLDO1, "ldo-vddldo1", SC2730_LDO_VDDLDO1_PD,
SC2730_LDO_VDDLDO1_PD_MASK, SC2730_LDO_VDDLDO1_VOL,
SC2730_LDO_VDDLDO1_VOL_MASK, 10000, 1200000, 3750000),
SC2730_REGU_LINEAR(LDO_VDDLDO2, "ldo-vddldo2", SC2730_LDO_VDDLDO2_PD,
SC2730_LDO_VDDLDO2_PD_MASK, SC2730_LDO_VDDLDO2_VOL,
SC2730_LDO_VDDLDO2_VOL_MASK, 10000, 1200000, 3750000),
SC2730_REGU_LINEAR(LDO_VDDKPLED, "ldo-vddkpled", SC2730_LDO_VDDKPLED_PD,
SC2730_LDO_VDDKPLED_PD_MASK, SC2730_LDO_VDDKPLED_VOL,
SC2730_LDO_VDDKPLED_VOL_MASK, 10000, 1200000, 3750000),
};
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)
return dev_err_probe(&pdev->dev, -ENODEV, "failed to get regmap\n");
ret = sc2730_regulator_unlock(regmap);
if (ret)
return dev_err_probe(&pdev->dev, ret, "failed to release regulator lock\n");
config.dev = pdev->dev.parent;
config.regmap = regmap;
for (i = 0; i < ARRAY_SIZE(regulators); i++) {
rdev = devm_regulator_register(&pdev->dev, &regulators[i], &config);
if (IS_ERR(rdev)) {
return dev_err_probe(&pdev->dev, PTR_ERR(rdev),
"failed to register regulator %s\n",
regulators[i].name);
}
}
return 0;
}
static const struct platform_device_id sc2730_regulator_id_table[] = {
{ .name = "sc2730-regulator" },
{ }
};
MODULE_DEVICE_TABLE(platform, sc2730_regulator_id_table);
static struct platform_driver sc2730_regulator_driver = {
.driver = {
.name = "sc2730-regulator",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
.probe = sc2730_regulator_probe,
.id_table = sc2730_regulator_id_table,
};
module_platform_driver(sc2730_regulator_driver);
MODULE_AUTHOR("Zhongfa Wang <zhongfa.wang@unisoc.com>");
MODULE_DESCRIPTION("Spreadtrum SC2730 regulator driver");
MODULE_LICENSE("GPL");