lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20260112124351.17707-4-chenjh@rock-chips.com>
Date: Mon, 12 Jan 2026 20:43:51 +0800
From: Joseph Chen <chenjh@...k-chips.com>
To: Conor Dooley <conor+dt@...nel.org>,
	Krzysztof Kozlowski <krzk+dt@...nel.org>,
	Lee Jones <lee@...nel.org>,
	Liam Girdwood <lgirdwood@...il.com>,
	Mark Brown <broonie@...nel.org>,
	Rob Herring <robh@...nel.org>
Cc: Heiko Stuebner <heiko@...ech.de>,
	devicetree@...r.kernel.org,
	linux-arm-kernel@...ts.infradead.org,
	linux-kernel@...r.kernel.org,
	linux-rockchip@...ts.infradead.org,
	Joseph Chen <chenjh@...k-chips.com>
Subject: [PATCH v3 3/3] regulator: rk808: Add RK801 support

Add support for rk801 to the existing rk808 regulator driver.
It provides 4 BUCK, 2 LDO and 1 SWITCH.

Signed-off-by: Joseph Chen <chenjh@...k-chips.com>
---
 drivers/regulator/rk808-regulator.c | 243 ++++++++++++++++++++++++++++
 1 file changed, 243 insertions(+)

diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c
index 1e814247965..e66408f23bb 100644
--- a/drivers/regulator/rk808-regulator.c
+++ b/drivers/regulator/rk808-regulator.c
@@ -24,6 +24,9 @@
 #include <linux/gpio/consumer.h>
 
 /* Field definitions */
+#define RK801_BUCK_VSEL_MASK		0x7f
+#define RK801_LDO_VSEL_MASK		0x3f
+
 #define RK808_BUCK_VSEL_MASK	0x3f
 #define RK808_BUCK4_VSEL_MASK	0xf
 #define RK808_LDO_VSEL_MASK	0x1f
@@ -158,6 +161,11 @@
 	RK8XX_DESC_COM(_id, _match, _supply, _min, _max, _step, _vreg,	\
 	_vmask, _ereg, _emask, 0, 0, _etime, &rk808_reg_ops)
 
+#define RK801_DESC(_id, _match, _supply, _min, _max, _step, _vreg,	\
+	_vmask, _ereg, _emask, _disval, _etime)				\
+	RK8XX_DESC_COM(_id, _match, _supply, _min, _max, _step, _vreg,	\
+	_vmask, _ereg, _emask, _emask, _disval, _etime, &rk801_reg_ops)
+
 #define RK816_DESC(_id, _match, _supply, _min, _max, _step, _vreg,	\
 	_vmask, _ereg, _emask, _disval, _etime)				\
 	RK8XX_DESC_COM(_id, _match, _supply, _min, _max, _step, _vreg,	\
@@ -185,6 +193,11 @@
 		.ops		= _ops					\
 	}
 
+#define RK801_DESC_SWITCH(_id, _match, _supply, _ereg, _emask,		\
+	_disval)							\
+	RKXX_DESC_SWITCH_COM(_id, _match, _supply, _ereg, _emask,	\
+	_emask, _disval, &rk801_switch_ops)
+
 #define RK817_DESC_SWITCH(_id, _match, _supply, _ereg, _emask,		\
 	_disval)							\
 	RKXX_DESC_SWITCH_COM(_id, _match, _supply, _ereg, _emask,	\
@@ -802,6 +815,115 @@ static unsigned int rk8xx_regulator_of_map_mode(unsigned int mode)
 	}
 }
 
+static unsigned int rk801_get_mode(struct regulator_dev *rdev)
+{
+	unsigned int val;
+	int err;
+
+	err = regmap_read(rdev->regmap, RK801_POWER_FPWM_EN_REG, &val);
+	if (err)
+		return err;
+
+	if (val & BIT(rdev->desc->id))
+		return REGULATOR_MODE_FAST;
+	else
+		return REGULATOR_MODE_NORMAL;
+}
+
+static int rk801_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+	unsigned int offset = rdev->desc->id;
+
+	switch (mode) {
+	case REGULATOR_MODE_FAST:
+		return regmap_update_bits(rdev->regmap, RK801_POWER_FPWM_EN_REG,
+					  BIT(offset), RK801_FPWM_MODE << offset);
+	case REGULATOR_MODE_NORMAL:
+		return regmap_update_bits(rdev->regmap, RK801_POWER_FPWM_EN_REG,
+					  BIT(offset), RK801_AUTO_PWM_MODE << offset);
+	default:
+		dev_err(&rdev->dev, "do not support this mode\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int rk801_set_suspend_voltage(struct regulator_dev *rdev, int uv)
+{
+	unsigned int reg;
+	int sel;
+
+	if (rdev->desc->id < RK801_ID_LDO1)
+		sel = regulator_map_voltage_linear_range(rdev, uv, uv);
+	else
+		sel = regulator_map_voltage_linear(rdev, uv, uv);
+	if (sel < 0)
+		return -EINVAL;
+
+	reg = rdev->desc->vsel_reg + RK801_SLP_REG_OFFSET;
+
+	return regmap_update_bits(rdev->regmap, reg,
+				  rdev->desc->vsel_mask, sel);
+}
+
+static int rk801_set_suspend_enable(struct regulator_dev *rdev)
+{
+	return regmap_update_bits(rdev->regmap, RK801_POWER_SLP_EN_REG,
+				  BIT(rdev->desc->id), BIT(rdev->desc->id));
+}
+
+static int rk801_set_suspend_disable(struct regulator_dev *rdev)
+{
+	return regmap_update_bits(rdev->regmap, RK801_POWER_SLP_EN_REG,
+				  BIT(rdev->desc->id), 0);
+}
+
+static int rk801_set_voltage_time_sel(struct regulator_dev *rdev,
+				      unsigned int old_selector,
+				      unsigned int new_selector)
+{
+	return regulator_set_voltage_time_sel(rdev, old_selector,
+					      new_selector) + RK801_HW_SYNC_US;
+}
+
+static const struct regulator_ops rk801_buck_ops = {
+	.list_voltage		= regulator_list_voltage_linear_range,
+	.map_voltage		= regulator_map_voltage_linear_range,
+	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+	.set_voltage_time_sel	= rk801_set_voltage_time_sel,
+	.enable			= regulator_enable_regmap,
+	.disable		= regulator_disable_regmap,
+	.is_enabled		= regulator_is_enabled_regmap,
+	.set_mode		= rk801_set_mode,
+	.get_mode		= rk801_get_mode,
+	.set_suspend_voltage	= rk801_set_suspend_voltage,
+	.set_suspend_enable	= rk801_set_suspend_enable,
+	.set_suspend_disable	= rk801_set_suspend_disable,
+};
+
+static const struct regulator_ops rk801_reg_ops = {
+	.list_voltage		= regulator_list_voltage_linear,
+	.map_voltage		= regulator_map_voltage_linear,
+	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+	.enable			= regulator_enable_regmap,
+	.disable		= regulator_disable_regmap,
+	.is_enabled		= regulator_is_enabled_regmap,
+	.set_suspend_voltage	= rk801_set_suspend_voltage,
+	.set_suspend_enable	= rk801_set_suspend_enable,
+	.set_suspend_disable	= rk801_set_suspend_disable,
+};
+
+static const struct regulator_ops rk801_switch_ops = {
+	.enable			= regulator_enable_regmap,
+	.disable		= regulator_disable_regmap,
+	.is_enabled		= regulator_is_enabled_regmap,
+	.set_suspend_enable	= rk801_set_suspend_enable,
+	.set_suspend_disable	= rk801_set_suspend_disable,
+};
+
 static const struct regulator_ops rk805_reg_ops = {
 	.list_voltage           = regulator_list_voltage_linear,
 	.map_voltage            = regulator_map_voltage_linear,
@@ -1049,6 +1171,123 @@ static const struct regulator_ops rk817_switch_ops = {
 	.set_suspend_disable	= rk817_set_suspend_disable,
 };
 
+static const struct linear_range rk801_buck1_voltage_ranges[] = {
+	REGULATOR_LINEAR_RANGE(500000,   0, 80, 12500),	/* 0.5v - 1.5v */
+	REGULATOR_LINEAR_RANGE(1800000, 81, 82, 400000),/* 1.8v - 2.2v */
+	REGULATOR_LINEAR_RANGE(3300000, 83, 83, 0),	/* 3.3v */
+	REGULATOR_LINEAR_RANGE(5000000, 84, 84, 0),	/* 5.0v */
+	REGULATOR_LINEAR_RANGE(5250000, 85, 85, 0),	/* 5.25v */
+};
+
+static const struct linear_range rk801_buck2_voltage_ranges[] = {
+	REGULATOR_LINEAR_RANGE(800000,  0, 2, 50000),	/* 0.8v - 0.9v */
+	REGULATOR_LINEAR_RANGE(1800000, 3, 4, 400000),	/* 1.8v - 2.2v */
+	REGULATOR_LINEAR_RANGE(3300000, 5, 5, 0),	/* 3.3v */
+	REGULATOR_LINEAR_RANGE(5000000, 6, 6, 0),	/* 5.0v */
+	REGULATOR_LINEAR_RANGE(5250000, 7, 7, 0),	/* 5.25v */
+};
+
+static const struct linear_range rk801_buck4_voltage_ranges[] = {
+	REGULATOR_LINEAR_RANGE(500000,   0, 80, 12500),	/* 0.5v - 1.5v */
+	REGULATOR_LINEAR_RANGE(1800000, 81, 82, 400000),/* 1.8v - 2.2v */
+	REGULATOR_LINEAR_RANGE(2500000, 83, 83, 0),	/* 2.5v */
+	REGULATOR_LINEAR_RANGE(2800000, 84, 84, 0),	/* 2.8v */
+	REGULATOR_LINEAR_RANGE(3000000, 85, 85, 0),	/* 3.0v */
+	REGULATOR_LINEAR_RANGE(3300000, 86, 86, 0),	/* 3.3v */
+};
+
+static const struct regulator_desc rk801_reg[] = {
+	{
+		.name = "dcdc1",
+		.supply_name = "vcc1",
+		.of_match = of_match_ptr("dcdc1"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = RK801_ID_DCDC1,
+		.ops = &rk801_buck_ops,
+		.type = REGULATOR_VOLTAGE,
+		.n_voltages = 86,
+		.linear_ranges = rk801_buck1_voltage_ranges,
+		.n_linear_ranges = ARRAY_SIZE(rk801_buck1_voltage_ranges),
+		.vsel_reg = RK801_BUCK1_ON_VSEL_REG,
+		.vsel_mask = RK801_BUCK_VSEL_MASK,
+		.enable_reg = RK801_POWER_EN0_REG,
+		.enable_mask = ENABLE_MASK(RK801_ID_DCDC1),
+		.enable_val = ENABLE_MASK(RK801_ID_DCDC1),
+		.disable_val = DISABLE_VAL(RK801_ID_DCDC1),
+		.ramp_delay = 1000,
+		.of_map_mode = rk8xx_regulator_of_map_mode,
+		.enable_time = 400,
+		.owner = THIS_MODULE,
+	}, {
+		.name = "dcdc2",
+		.supply_name = "vcc2",
+		.of_match = of_match_ptr("dcdc2"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = RK801_ID_DCDC2,
+		.ops = &rk801_buck_ops,
+		.type = REGULATOR_VOLTAGE,
+		.n_voltages = 8,
+		.linear_ranges = rk801_buck2_voltage_ranges,
+		.n_linear_ranges = ARRAY_SIZE(rk801_buck2_voltage_ranges),
+		.vsel_reg = RK801_BUCK2_ON_VSEL_REG,
+		.vsel_mask = RK801_BUCK_VSEL_MASK,
+		.enable_reg = RK801_POWER_EN0_REG,
+		.enable_mask = ENABLE_MASK(RK801_ID_DCDC2),
+		.enable_val = ENABLE_MASK(RK801_ID_DCDC2),
+		.disable_val = DISABLE_VAL(RK801_ID_DCDC2),
+		.ramp_delay = 1000,
+		.of_map_mode = rk8xx_regulator_of_map_mode,
+		.enable_time = 400,
+		.owner = THIS_MODULE,
+	}, {
+		.name = "dcdc3",
+		.supply_name = "vcc3",
+		.of_match = of_match_ptr("dcdc3"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = RK801_ID_DCDC3,
+		.ops = &rk801_switch_ops,
+		.type = REGULATOR_VOLTAGE,
+		.n_voltages = 1,
+		.enable_reg = RK801_POWER_EN0_REG,
+		.enable_mask = ENABLE_MASK(RK801_ID_DCDC3),
+		.enable_val = ENABLE_MASK(RK801_ID_DCDC3),
+		.disable_val = DISABLE_VAL(RK801_ID_DCDC3),
+		.of_map_mode = rk8xx_regulator_of_map_mode,
+		.enable_time = 400,
+		.owner = THIS_MODULE,
+	}, {
+		.name = "dcdc4",
+		.supply_name = "vcc4",
+		.of_match = of_match_ptr("dcdc4"),
+		.regulators_node = of_match_ptr("regulators"),
+		.id = RK801_ID_DCDC4,
+		.ops = &rk801_buck_ops,
+		.type = REGULATOR_VOLTAGE,
+		.n_voltages = 87,
+		.linear_ranges = rk801_buck4_voltage_ranges,
+		.n_linear_ranges = ARRAY_SIZE(rk801_buck4_voltage_ranges),
+		.vsel_reg = RK801_BUCK4_ON_VSEL_REG,
+		.vsel_mask = RK801_BUCK_VSEL_MASK,
+		.enable_reg = RK801_POWER_EN0_REG,
+		.enable_mask = ENABLE_MASK(RK801_ID_DCDC4),
+		.enable_val = ENABLE_MASK(RK801_ID_DCDC4),
+		.disable_val = DISABLE_VAL(RK801_ID_DCDC4),
+		.ramp_delay = 1000,
+		.of_map_mode = rk8xx_regulator_of_map_mode,
+		.enable_time = 400,
+		.owner = THIS_MODULE,
+	},
+
+	RK801_DESC(RK801_ID_LDO1, "ldo1", "vcc5", 500, 3400, 50,
+		RK801_LDO1_ON_VSEL_REG, RK801_LDO_VSEL_MASK, RK801_POWER_EN1_REG,
+		ENABLE_MASK(0), DISABLE_VAL(0), 400),
+	RK801_DESC(RK801_ID_LDO2, "ldo2", "vcc6", 500, 3400, 50,
+		RK801_LDO2_ON_VSEL_REG, RK801_LDO_VSEL_MASK, RK801_POWER_EN1_REG,
+		ENABLE_MASK(1), DISABLE_VAL(1), 400),
+	RK801_DESC_SWITCH(RK801_ID_SWITCH, "switch", "vcc7", RK801_POWER_EN1_REG,
+		ENABLE_MASK(2), DISABLE_VAL(2)),
+};
+
 static const struct regulator_desc rk805_reg[] = {
 	{
 		.name = "DCDC_REG1",
@@ -1887,6 +2126,10 @@ static int rk808_regulator_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	switch (rk808->variant) {
+	case RK801_ID:
+		regulators = rk801_reg;
+		nregulators = RK801_NUM_REGULATORS;
+		break;
 	case RK805_ID:
 		regulators = rk805_reg;
 		nregulators = RK805_NUM_REGULATORS;
-- 
2.25.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ