summaryrefslogtreecommitdiff
path: root/drivers/regulator
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-02-16 22:05:44 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2026-02-16 22:05:44 +0300
commit4668c4831fbcb924ef9ce63b32f8a4daefd3d6fc (patch)
tree36a917815cd17c3dbd3d475266315a71bda07bc2 /drivers/regulator
parent46a1daac56b3bf1bdbd8b37e6db811f015bc1f4b (diff)
parent845776177cf3b75be4e27213425f25dcb630d817 (diff)
downloadlinux-4668c4831fbcb924ef9ce63b32f8a4daefd3d6fc.tar.xz
Merge tag 'mfd-next-6.20' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
Pull MFD updates from Lee Jones: "New Support & Features: - Add comprehensive support for the ROHM BD72720 PMIC, including core MFD, regulator, GPIO, clock gate, RTC, and power-supply drivers - Add support for the Rockchip RK801 PMIC, including core MFD and regulator drivers - Add support for the ROHM BD73900 PMIC by leveraging existing common drivers - Wire up RTC, hwmon, and input sub-devices for the Apple SMC (macsmc) driver - Add support for the Delta Networks TN48M switch CPLD via the simple-mfd-i2c driver - Add support for the TS133 variant to the QNAP MCU driver - Provide support for the sama7d65 XLCD controller in the Atmel HLCDC driver - Add backlight sub-device support to the Congatec Board Controller (cgbc) - Add Intel Nova Lake-S (NVL-S) PCI IDs to the Intel LPSS driver Improvements & Fixes: - Implement a "wrapper regmap" for the ROHM BD72720 to handle dual I2C slave addresses (0x4b and 0x4c) transparently for child devices - Introduce mutex locking around 'mfd_of_node_list' in the MFD core to ensure safe concurrent access - Fix a potential regulator resource leak in the Arizona core driver during boot sequence failures - Resolve child device duplication issues on driver rebind for Qualcomm PM8xxx and OMAP USB host drivers by using of_platform_depopulate() - Fix IRQ domain name duplication for the Samsung S2MPG10 by adding a unique domain suffix - Implement LOCK register handling for the TI TPS65214 variant to unlock registers at probe time - Fully convert the Loongson-2K BMC driver to use managed resources (pcim) and the standard PCI resource API - Ensure the Apple SMC mutex is correctly initialized during probe to prevent NULL pointer dereferences - Expand the ROHM BD71828 power-supply driver to support 9-bit register addresses - Simplify the Samsung S5M RTC driver by querying platform device IRQ resources directly - Revert an incorrect read-to-write mask change in the DA9052 SPI driver to restore default OTP behavior - Fix kernel-doc warnings in the TI TPS6105x driver - Cleanups & Refactoring - Simplify the MFD core by utilizing the scoped for_each_child_of_node_scoped() macro and streamlining device_node storage - Rename ROHM BD71828 IC-specific entities to use consistent prefixes for better extensibility - Refactor ROHM BD71828 regmap definitions using the regmap_reg_range() macro - Update the ROHM BD71828 driver to use standard C-style comment headers - Remove the now unused 'irq_data' field from the Samsung SEC core structure - Drop unnecessary use of irqd_get_trigger_type() in the Maxim MAX77759 driver - Default MFD_SPACEMIT_P1 to 'm' if ARCH_SPACEMIT is selected - Add missing charger-related registers to the ROHM BD71828 core header and Type-C CC registers to the AXP717 Device Tree Binding Updates: - Add new bindings for the ROHM BD72720 PMIC, Rockchip RK801 PMIC, Bitmain BM1880 System Controller, and NXP LPC32xx System Control Block - Clarify trickle-charge terminology and add properties for voltage drop (VDR) correction and upper charge limits to the generic battery binding - Document GPR syscon for NXP S32 SoCs and the smp-memram subnode for Aspeed SCU - Document numerous new Qualcomm SPMI PMIC compatibles (pmcx0102, pmh0101, pmk8850, etc) - Add compatibles for the sama7d65 XLCD (Atmel), LAN9691 Flexcom (Microchip), and various MediaTek SCPSYS and regulator components - Fix a dead link to the audio codec binding in the DA9055 documentation" * tag 'mfd-next-6.20' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (41 commits) dt-bindings: mfd: da9055: Fix dead link to codec binding mfd: cgbc: Add support for backlight dt-bindings: mfd: qcom,spmi-pmic: Document PMICs present on Glymur and Kaanapali dt-bindings: mfd: Document smp-memram subnode for aspeed,ast2x00-scu mfd: intel-lpss: Add Intel Nova Lake-S PCI IDs mfd: ls2kbmc: Use PCI API instead of direct accesses mfd: ls2kbmc: Fully convert to use managed resources dt-bindings: mfd: mediatek: mt6397: Add missing MT6331 regulator compat dt-bindings: mfd: mediatek,mt8195-scpsys: Add mediatek,mt6795-scpsys dt-bindings: mfd: atmel,sama5d2-flexcom: Add microchip,lan9691-flexcom mfd: omap-usb-host: Fix OF populate on driver rebind mfd: qcom-pm8xxx: Fix OF populate on driver rebind dt-bindings: mfd: syscon: Allow syscon compatible for mediatek,mt7981-topmisc mfd: qnap-mcu: Add driver data for TS133 variant dt-bindings: mfd: qnap,ts433-mcu: Add qnap,ts133-mcu compatible mfd: sec: Fix IRQ domain names duplication mfd: simple-mfd-i2c: Add Delta TN48M CPLD support mfd: macsmc: Initialize mutex dt-bindings: mfd: nxp: Add NXP LPC32xx System Control Block mfd: Kconfig: Default MFD_SPACEMIT_P1 to 'm' if ARCH_SPACEMIT ...
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/rk808-regulator.c243
1 files changed, 243 insertions, 0 deletions
diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c
index 1e8142479656..e66408f23bb6 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;