Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

regulator: add s2dos05 regulator support

S2DOS05 has 1 buck and 4 LDO regulators, used for powering
panel/touchscreen.

Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
Link: https://patch.msgid.link/20250805-starqltechn_integration_upstream-v8-1-09d8a321fafe@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Dzmitry Sankouski and committed by
Mark Brown
bb244140 f6cc4140

+248 -1
+1 -1
MAINTAINERS
··· 22387 22387 F: Documentation/devicetree/bindings/regulator/samsung,s5m*.yaml 22388 22388 F: drivers/clk/clk-s2mps11.c 22389 22389 F: drivers/mfd/sec*.[ch] 22390 - F: drivers/regulator/s2m*.c 22390 + F: drivers/regulator/s2*.c 22391 22391 F: drivers/regulator/s5m*.c 22392 22392 F: drivers/rtc/rtc-s5m.c 22393 22393 F: include/linux/mfd/samsung/
+8
drivers/regulator/Kconfig
··· 1344 1344 and two ldos. It features wide output voltage range from 0.4V to 2.05V 1345 1345 and the capability to configure the corresponding power stages. 1346 1346 1347 + config REGULATOR_S2DOS05 1348 + tristate "Samsung S2DOS05 voltage regulator" 1349 + depends on MFD_SEC_CORE || COMPILE_TEST 1350 + help 1351 + This driver provides support for the voltage regulators of the S2DOS05. 1352 + The S2DOS05 is a companion power management IC for the smart phones. 1353 + The S2DOS05 has 4 LDOs and 1 BUCK outputs. 1354 + 1347 1355 config REGULATOR_S2MPA01 1348 1356 tristate "Samsung S2MPA01 voltage regulator" 1349 1357 depends on MFD_SEC_CORE || COMPILE_TEST
+1
drivers/regulator/Makefile
··· 156 156 obj-$(CONFIG_REGULATOR_RTQ2134) += rtq2134-regulator.o 157 157 obj-$(CONFIG_REGULATOR_RTQ6752) += rtq6752-regulator.o 158 158 obj-$(CONFIG_REGULATOR_RTQ2208) += rtq2208-regulator.o 159 + obj-$(CONFIG_REGULATOR_S2DOS05) += s2dos05-regulator.o 159 160 obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o 160 161 obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o 161 162 obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
+165
drivers/regulator/s2dos05-regulator.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + // 3 + // s2dos05.c - Regulator driver for the Samsung s2dos05 4 + // 5 + // Copyright (C) 2025 Dzmitry Sankouski <dsankouski@gmail.com> 6 + 7 + #include <linux/bug.h> 8 + #include <linux/delay.h> 9 + #include <linux/err.h> 10 + #include <linux/slab.h> 11 + #include <linux/module.h> 12 + #include <linux/regmap.h> 13 + #include <linux/interrupt.h> 14 + #include <linux/platform_device.h> 15 + #include <linux/regulator/driver.h> 16 + #include <linux/regulator/machine.h> 17 + #include <linux/regulator/of_regulator.h> 18 + #include <linux/mfd/samsung/core.h> 19 + #include <linux/regulator/s2dos05.h> 20 + #include <linux/i2c.h> 21 + 22 + struct s2dos05_data { 23 + struct regmap *regmap; 24 + struct device *dev; 25 + }; 26 + 27 + #define _BUCK(macro) S2DOS05_BUCK##macro 28 + #define _buck_ops(num) s2dos05_ops##num 29 + #define _LDO(macro) S2DOS05_LDO##macro 30 + #define _REG(ctrl) S2DOS05_REG##ctrl 31 + #define _ldo_ops(num) s2dos05_ops##num 32 + #define _MASK(macro) S2DOS05_ENABLE_MASK##macro 33 + #define _TIME(macro) S2DOS05_ENABLE_TIME##macro 34 + 35 + #define BUCK_DESC(_name, _id, _ops, m, s, v, e, em, t, a) { \ 36 + .name = _name, \ 37 + .id = _id, \ 38 + .ops = _ops, \ 39 + .of_match = of_match_ptr(_name), \ 40 + .of_match_full_name = true, \ 41 + .regulators_node = of_match_ptr("regulators"), \ 42 + .type = REGULATOR_VOLTAGE, \ 43 + .owner = THIS_MODULE, \ 44 + .min_uV = m, \ 45 + .uV_step = s, \ 46 + .n_voltages = S2DOS05_BUCK_N_VOLTAGES, \ 47 + .vsel_reg = v, \ 48 + .vsel_mask = S2DOS05_BUCK_VSEL_MASK, \ 49 + .enable_reg = e, \ 50 + .enable_mask = em, \ 51 + .enable_time = t, \ 52 + .active_discharge_off = 0, \ 53 + .active_discharge_on = S2DOS05_BUCK_FD_MASK, \ 54 + .active_discharge_reg = a, \ 55 + .active_discharge_mask = S2DOS05_BUCK_FD_MASK \ 56 + } 57 + 58 + #define LDO_DESC(_name, _id, _ops, m, s, v, e, em, t, a) { \ 59 + .name = _name, \ 60 + .id = _id, \ 61 + .ops = _ops, \ 62 + .of_match = of_match_ptr(_name), \ 63 + .of_match_full_name = true, \ 64 + .regulators_node = of_match_ptr("regulators"), \ 65 + .type = REGULATOR_VOLTAGE, \ 66 + .owner = THIS_MODULE, \ 67 + .min_uV = m, \ 68 + .uV_step = s, \ 69 + .n_voltages = S2DOS05_LDO_N_VOLTAGES, \ 70 + .vsel_reg = v, \ 71 + .vsel_mask = S2DOS05_LDO_VSEL_MASK, \ 72 + .enable_reg = e, \ 73 + .enable_mask = em, \ 74 + .enable_time = t, \ 75 + .active_discharge_off = 0, \ 76 + .active_discharge_on = S2DOS05_LDO_FD_MASK, \ 77 + .active_discharge_reg = a, \ 78 + .active_discharge_mask = S2DOS05_LDO_FD_MASK \ 79 + } 80 + 81 + static const struct regulator_ops s2dos05_ops = { 82 + .list_voltage = regulator_list_voltage_linear, 83 + .map_voltage = regulator_map_voltage_linear, 84 + .is_enabled = regulator_is_enabled_regmap, 85 + .enable = regulator_enable_regmap, 86 + .disable = regulator_disable_regmap, 87 + .get_voltage_sel = regulator_get_voltage_sel_regmap, 88 + .set_voltage_sel = regulator_set_voltage_sel_regmap, 89 + .set_voltage_time_sel = regulator_set_voltage_time_sel, 90 + .set_active_discharge = regulator_set_active_discharge_regmap, 91 + }; 92 + 93 + static const struct regulator_desc regulators[S2DOS05_REGULATOR_MAX] = { 94 + // name, id, ops, min_uv, uV_step, vsel_reg, enable_reg 95 + LDO_DESC("ldo1", _LDO(1), &_ldo_ops(), _LDO(_MIN1), 96 + _LDO(_STEP1), _REG(_LDO1_CFG), 97 + _REG(_EN), _MASK(_L1), _TIME(_LDO), _REG(_LDO1_CFG)), 98 + LDO_DESC("ldo2", _LDO(2), &_ldo_ops(), _LDO(_MIN1), 99 + _LDO(_STEP1), _REG(_LDO2_CFG), 100 + _REG(_EN), _MASK(_L2), _TIME(_LDO), _REG(_LDO2_CFG)), 101 + LDO_DESC("ldo3", _LDO(3), &_ldo_ops(), _LDO(_MIN2), 102 + _LDO(_STEP1), _REG(_LDO3_CFG), 103 + _REG(_EN), _MASK(_L3), _TIME(_LDO), _REG(_LDO3_CFG)), 104 + LDO_DESC("ldo4", _LDO(4), &_ldo_ops(), _LDO(_MIN2), 105 + _LDO(_STEP1), _REG(_LDO4_CFG), 106 + _REG(_EN), _MASK(_L4), _TIME(_LDO), _REG(_LDO4_CFG)), 107 + BUCK_DESC("buck", _BUCK(1), &_buck_ops(), _BUCK(_MIN1), 108 + _BUCK(_STEP1), _REG(_BUCK_VOUT), 109 + _REG(_EN), _MASK(_B1), _TIME(_BUCK), _REG(_BUCK_CFG)), 110 + }; 111 + 112 + static int s2dos05_pmic_probe(struct platform_device *pdev) 113 + { 114 + struct device *dev = &pdev->dev; 115 + struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); 116 + struct s2dos05_data *s2dos05; 117 + struct regulator_config config = { }; 118 + unsigned int rdev_num = ARRAY_SIZE(regulators); 119 + 120 + s2dos05 = devm_kzalloc(dev, sizeof(*s2dos05), GFP_KERNEL); 121 + if (!s2dos05) 122 + return -ENOMEM; 123 + 124 + platform_set_drvdata(pdev, s2dos05); 125 + 126 + s2dos05->regmap = iodev->regmap_pmic; 127 + s2dos05->dev = dev; 128 + if (!dev->of_node) 129 + dev->of_node = dev->parent->of_node; 130 + 131 + config.dev = dev; 132 + config.driver_data = s2dos05; 133 + 134 + for (int i = 0; i < rdev_num; i++) { 135 + struct regulator_dev *regulator; 136 + 137 + regulator = devm_regulator_register(&pdev->dev, 138 + &regulators[i], &config); 139 + if (IS_ERR(regulator)) { 140 + return dev_err_probe(&pdev->dev, PTR_ERR(regulator), 141 + "regulator init failed for %d\n", i); 142 + } 143 + } 144 + 145 + return 0; 146 + } 147 + 148 + static const struct platform_device_id s2dos05_pmic_id[] = { 149 + { "s2dos05-regulator" }, 150 + { }, 151 + }; 152 + MODULE_DEVICE_TABLE(platform, s2dos05_pmic_id); 153 + 154 + static struct platform_driver s2dos05_platform_driver = { 155 + .driver = { 156 + .name = "s2dos05", 157 + }, 158 + .probe = s2dos05_pmic_probe, 159 + .id_table = s2dos05_pmic_id, 160 + }; 161 + module_platform_driver(s2dos05_platform_driver); 162 + 163 + MODULE_AUTHOR("Dzmitry Sankouski <dsankouski@gmail.com>"); 164 + MODULE_DESCRIPTION("Samsung S2DOS05 Regulator Driver"); 165 + MODULE_LICENSE("GPL");
+73
include/linux/regulator/s2dos05.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 2 + // s2dos05.h 3 + // 4 + // Copyright (c) 2016 Samsung Electronics Co., Ltd 5 + // http://www.samsung.com 6 + // Copyright (C) 2024 Dzmitry Sankouski <dsankouski@gmail.com> 7 + 8 + #ifndef __LINUX_S2DOS05_H 9 + #define __LINUX_S2DOS05_H 10 + 11 + // S2DOS05 registers 12 + // Slave Addr : 0xC0 13 + enum S2DOS05_reg { 14 + S2DOS05_REG_DEV_ID, 15 + S2DOS05_REG_TOPSYS_STAT, 16 + S2DOS05_REG_STAT, 17 + S2DOS05_REG_EN, 18 + S2DOS05_REG_LDO1_CFG, 19 + S2DOS05_REG_LDO2_CFG, 20 + S2DOS05_REG_LDO3_CFG, 21 + S2DOS05_REG_LDO4_CFG, 22 + S2DOS05_REG_BUCK_CFG, 23 + S2DOS05_REG_BUCK_VOUT, 24 + S2DOS05_REG_IRQ_MASK = 0x0D, 25 + S2DOS05_REG_SSD_TSD = 0x0E, 26 + S2DOS05_REG_OCL = 0x10, 27 + S2DOS05_REG_IRQ = 0x11 28 + }; 29 + 30 + // S2DOS05 regulator ids 31 + enum S2DOS05_regulators { 32 + S2DOS05_LDO1, 33 + S2DOS05_LDO2, 34 + S2DOS05_LDO3, 35 + S2DOS05_LDO4, 36 + S2DOS05_BUCK1, 37 + S2DOS05_REG_MAX, 38 + }; 39 + 40 + #define S2DOS05_IRQ_PWRMT_MASK BIT(5) 41 + #define S2DOS05_IRQ_TSD_MASK BIT(4) 42 + #define S2DOS05_IRQ_SSD_MASK BIT(3) 43 + #define S2DOS05_IRQ_SCP_MASK BIT(2) 44 + #define S2DOS05_IRQ_UVLO_MASK BIT(1) 45 + #define S2DOS05_IRQ_OCD_MASK BIT(0) 46 + 47 + #define S2DOS05_BUCK_MIN1 506250 48 + #define S2DOS05_LDO_MIN1 1500000 49 + #define S2DOS05_LDO_MIN2 2700000 50 + #define S2DOS05_BUCK_STEP1 6250 51 + #define S2DOS05_LDO_STEP1 25000 52 + #define S2DOS05_LDO_VSEL_MASK 0x7F 53 + #define S2DOS05_LDO_FD_MASK 0x80 54 + #define S2DOS05_BUCK_VSEL_MASK 0xFF 55 + #define S2DOS05_BUCK_FD_MASK 0x08 56 + 57 + #define S2DOS05_ENABLE_MASK_L1 BIT(0) 58 + #define S2DOS05_ENABLE_MASK_L2 BIT(1) 59 + #define S2DOS05_ENABLE_MASK_L3 BIT(2) 60 + #define S2DOS05_ENABLE_MASK_L4 BIT(3) 61 + #define S2DOS05_ENABLE_MASK_B1 BIT(4) 62 + 63 + #define S2DOS05_RAMP_DELAY 12000 64 + 65 + #define S2DOS05_ENABLE_TIME_LDO 50 66 + #define S2DOS05_ENABLE_TIME_BUCK 350 67 + 68 + #define S2DOS05_LDO_N_VOLTAGES (S2DOS05_LDO_VSEL_MASK + 1) 69 + #define S2DOS05_BUCK_N_VOLTAGES (S2DOS05_BUCK_VSEL_MASK + 1) 70 + 71 + #define S2DOS05_REGULATOR_MAX (S2DOS05_REG_MAX) 72 + 73 + #endif // __LINUX_S2DOS05_H