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

regulator: bd70528: Support ROHM BD70528 regulator block

BD70528MWV is an ultra-low Iq general purpose single-chip power
management IC for battery-powered portable devices.

Add support for controlling 3 bucks and 3 LDOs present in
ROHM BD70528.

Signed-off-by: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Matti Vaittinen and committed by
Mark Brown
99ea37bd fd805d99

+302
+11
drivers/regulator/Kconfig
··· 180 180 BCM590xx PMUs. This will enable support for the software 181 181 controllable LDO/Switching regulators. 182 182 183 + config REGULATOR_BD70528 184 + tristate "ROHM BD70528 Power Regulator" 185 + depends on MFD_ROHM_BD70528 186 + help 187 + This driver supports voltage regulators on ROHM BD70528 PMIC. 188 + This will enable support for the software controllable buck 189 + and LDO regulators. 190 + 191 + This driver can also be built as a module. If so, the module 192 + will be called bd70528-regulator. 193 + 183 194 config REGULATOR_BD718XX 184 195 tristate "ROHM BD71837 Power Regulator" 185 196 depends on MFD_ROHM_BD718XX
+1
drivers/regulator/Makefile
··· 27 27 obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o 28 28 obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o 29 29 obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o 30 + obj-$(CONFIG_REGULATOR_BD70528) += bd70528-regulator.o 30 31 obj-$(CONFIG_REGULATOR_BD718XX) += bd718x7-regulator.o 31 32 obj-$(CONFIG_REGULATOR_BD9571MWV) += bd9571mwv-regulator.o 32 33 obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
+290
drivers/regulator/bd70528-regulator.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Copyright (C) 2018 ROHM Semiconductors 3 + // bd70528-regulator.c ROHM BD70528MWV regulator driver 4 + 5 + #include <linux/delay.h> 6 + #include <linux/err.h> 7 + #include <linux/gpio.h> 8 + #include <linux/interrupt.h> 9 + #include <linux/kernel.h> 10 + #include <linux/mfd/rohm-bd70528.h> 11 + #include <linux/module.h> 12 + #include <linux/of.h> 13 + #include <linux/platform_device.h> 14 + #include <linux/regmap.h> 15 + #include <linux/regulator/driver.h> 16 + #include <linux/regulator/machine.h> 17 + #include <linux/regulator/of_regulator.h> 18 + #include <linux/slab.h> 19 + 20 + #define BUCK_RAMPRATE_250MV 0 21 + #define BUCK_RAMPRATE_125MV 1 22 + #define BUCK_RAMP_MAX 250 23 + 24 + static struct regulator_linear_range bd70528_buck1_volts[] = { 25 + REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x1, 600000), 26 + REGULATOR_LINEAR_RANGE(2750000, 0x2, 0xf, 50000), 27 + }; 28 + static struct regulator_linear_range bd70528_buck2_volts[] = { 29 + REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x1, 300000), 30 + REGULATOR_LINEAR_RANGE(1550000, 0x2, 0xd, 50000), 31 + REGULATOR_LINEAR_RANGE(3000000, 0xe, 0xf, 300000), 32 + }; 33 + static struct regulator_linear_range bd70528_buck3_volts[] = { 34 + REGULATOR_LINEAR_RANGE(800000, 0x00, 0xd, 50000), 35 + REGULATOR_LINEAR_RANGE(1800000, 0xe, 0xf, 0), 36 + }; 37 + 38 + /* All LDOs have same voltage ranges */ 39 + static struct regulator_linear_range bd70528_ldo_volts[] = { 40 + REGULATOR_LINEAR_RANGE(1650000, 0x0, 0x07, 50000), 41 + REGULATOR_LINEAR_RANGE(2100000, 0x8, 0x0f, 100000), 42 + REGULATOR_LINEAR_RANGE(2850000, 0x10, 0x19, 50000), 43 + REGULATOR_LINEAR_RANGE(3300000, 0x19, 0x1f, 0), 44 + }; 45 + 46 + /* Also both LEDs support same voltages */ 47 + static const unsigned int led_volts[] = { 48 + 20000, 30000 49 + }; 50 + 51 + static int bd70528_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) 52 + { 53 + if (ramp_delay > 0 && ramp_delay <= BUCK_RAMP_MAX) { 54 + unsigned int ramp_value = BUCK_RAMPRATE_250MV; 55 + 56 + if (ramp_delay <= 125) 57 + ramp_value = BUCK_RAMPRATE_125MV; 58 + 59 + return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg, 60 + BD70528_MASK_BUCK_RAMP, 61 + ramp_value << BD70528_SIFT_BUCK_RAMP); 62 + } 63 + dev_err(&rdev->dev, "%s: ramp_delay: %d not supported\n", 64 + rdev->desc->name, ramp_delay); 65 + return -EINVAL; 66 + } 67 + 68 + static int bd70528_led_set_voltage_sel(struct regulator_dev *rdev, 69 + unsigned int sel) 70 + { 71 + int ret; 72 + 73 + ret = regulator_is_enabled_regmap(rdev); 74 + if (ret < 0) 75 + return ret; 76 + 77 + if (ret == 0) 78 + return regulator_set_voltage_sel_regmap(rdev, sel); 79 + 80 + dev_err(&rdev->dev, 81 + "LED voltage change not allowed when led is enabled\n"); 82 + 83 + return -EBUSY; 84 + } 85 + 86 + static struct regulator_ops bd70528_buck_ops = { 87 + .enable = regulator_enable_regmap, 88 + .disable = regulator_disable_regmap, 89 + .is_enabled = regulator_is_enabled_regmap, 90 + .list_voltage = regulator_list_voltage_linear_range, 91 + .set_voltage_sel = regulator_set_voltage_sel_regmap, 92 + .get_voltage_sel = regulator_get_voltage_sel_regmap, 93 + .set_voltage_time_sel = regulator_set_voltage_time_sel, 94 + .set_ramp_delay = bd70528_set_ramp_delay, 95 + }; 96 + 97 + static struct regulator_ops bd70528_ldo_ops = { 98 + .enable = regulator_enable_regmap, 99 + .disable = regulator_disable_regmap, 100 + .is_enabled = regulator_is_enabled_regmap, 101 + .list_voltage = regulator_list_voltage_linear_range, 102 + .set_voltage_sel = regulator_set_voltage_sel_regmap, 103 + .get_voltage_sel = regulator_get_voltage_sel_regmap, 104 + .set_voltage_time_sel = regulator_set_voltage_time_sel, 105 + .set_ramp_delay = bd70528_set_ramp_delay, 106 + }; 107 + 108 + static struct regulator_ops bd70528_led_ops = { 109 + .enable = regulator_enable_regmap, 110 + .disable = regulator_disable_regmap, 111 + .is_enabled = regulator_is_enabled_regmap, 112 + .list_voltage = regulator_list_voltage_table, 113 + .set_voltage_sel = bd70528_led_set_voltage_sel, 114 + .get_voltage_sel = regulator_get_voltage_sel_regmap, 115 + }; 116 + 117 + 118 + static struct regulator_desc bd70528_desc[] = { 119 + { 120 + .name = "buck1", 121 + .of_match = of_match_ptr("BUCK1"), 122 + .regulators_node = of_match_ptr("regulators"), 123 + .id = BD70528_BUCK1, 124 + .ops = &bd70528_buck_ops, 125 + .type = REGULATOR_VOLTAGE, 126 + .linear_ranges = bd70528_buck1_volts, 127 + .n_linear_ranges = ARRAY_SIZE(bd70528_buck1_volts), 128 + .n_voltages = BD70528_BUCK_VOLTS, 129 + .enable_reg = BD70528_REG_BUCK1_EN, 130 + .enable_mask = BD70528_MASK_RUN_EN, 131 + .vsel_reg = BD70528_REG_BUCK1_VOLT, 132 + .vsel_mask = BD70528_MASK_BUCK_VOLT, 133 + .owner = THIS_MODULE, 134 + }, 135 + { 136 + .name = "buck2", 137 + .of_match = of_match_ptr("BUCK2"), 138 + .regulators_node = of_match_ptr("regulators"), 139 + .id = BD70528_BUCK2, 140 + .ops = &bd70528_buck_ops, 141 + .type = REGULATOR_VOLTAGE, 142 + .linear_ranges = bd70528_buck2_volts, 143 + .n_linear_ranges = ARRAY_SIZE(bd70528_buck2_volts), 144 + .n_voltages = BD70528_BUCK_VOLTS, 145 + .enable_reg = BD70528_REG_BUCK2_EN, 146 + .enable_mask = BD70528_MASK_RUN_EN, 147 + .vsel_reg = BD70528_REG_BUCK2_VOLT, 148 + .vsel_mask = BD70528_MASK_BUCK_VOLT, 149 + .owner = THIS_MODULE, 150 + }, 151 + { 152 + .name = "buck3", 153 + .of_match = of_match_ptr("BUCK3"), 154 + .regulators_node = of_match_ptr("regulators"), 155 + .id = BD70528_BUCK3, 156 + .ops = &bd70528_buck_ops, 157 + .type = REGULATOR_VOLTAGE, 158 + .linear_ranges = bd70528_buck3_volts, 159 + .n_linear_ranges = ARRAY_SIZE(bd70528_buck3_volts), 160 + .n_voltages = BD70528_BUCK_VOLTS, 161 + .enable_reg = BD70528_REG_BUCK3_EN, 162 + .enable_mask = BD70528_MASK_RUN_EN, 163 + .vsel_reg = BD70528_REG_BUCK3_VOLT, 164 + .vsel_mask = BD70528_MASK_BUCK_VOLT, 165 + .owner = THIS_MODULE, 166 + }, 167 + { 168 + .name = "ldo1", 169 + .of_match = of_match_ptr("LDO1"), 170 + .regulators_node = of_match_ptr("regulators"), 171 + .id = BD70528_LDO1, 172 + .ops = &bd70528_ldo_ops, 173 + .type = REGULATOR_VOLTAGE, 174 + .linear_ranges = bd70528_ldo_volts, 175 + .n_linear_ranges = ARRAY_SIZE(bd70528_ldo_volts), 176 + .n_voltages = BD70528_LDO_VOLTS, 177 + .enable_reg = BD70528_REG_LDO1_EN, 178 + .enable_mask = BD70528_MASK_RUN_EN, 179 + .vsel_reg = BD70528_REG_LDO1_VOLT, 180 + .vsel_mask = BD70528_MASK_LDO_VOLT, 181 + .owner = THIS_MODULE, 182 + }, 183 + { 184 + .name = "ldo2", 185 + .of_match = of_match_ptr("LDO2"), 186 + .regulators_node = of_match_ptr("regulators"), 187 + .id = BD70528_LDO2, 188 + .ops = &bd70528_ldo_ops, 189 + .type = REGULATOR_VOLTAGE, 190 + .linear_ranges = bd70528_ldo_volts, 191 + .n_linear_ranges = ARRAY_SIZE(bd70528_ldo_volts), 192 + .n_voltages = BD70528_LDO_VOLTS, 193 + .enable_reg = BD70528_REG_LDO2_EN, 194 + .enable_mask = BD70528_MASK_RUN_EN, 195 + .vsel_reg = BD70528_REG_LDO2_VOLT, 196 + .vsel_mask = BD70528_MASK_LDO_VOLT, 197 + .owner = THIS_MODULE, 198 + }, 199 + { 200 + .name = "ldo3", 201 + .of_match = of_match_ptr("LDO3"), 202 + .regulators_node = of_match_ptr("regulators"), 203 + .id = BD70528_LDO3, 204 + .ops = &bd70528_ldo_ops, 205 + .type = REGULATOR_VOLTAGE, 206 + .linear_ranges = bd70528_ldo_volts, 207 + .n_linear_ranges = ARRAY_SIZE(bd70528_ldo_volts), 208 + .n_voltages = BD70528_LDO_VOLTS, 209 + .enable_reg = BD70528_REG_LDO3_EN, 210 + .enable_mask = BD70528_MASK_RUN_EN, 211 + .vsel_reg = BD70528_REG_LDO3_VOLT, 212 + .vsel_mask = BD70528_MASK_LDO_VOLT, 213 + .owner = THIS_MODULE, 214 + }, 215 + { 216 + .name = "ldo_led1", 217 + .of_match = of_match_ptr("LDO_LED1"), 218 + .regulators_node = of_match_ptr("regulators"), 219 + .id = BD70528_LED1, 220 + .ops = &bd70528_led_ops, 221 + .type = REGULATOR_VOLTAGE, 222 + .volt_table = &led_volts[0], 223 + .n_voltages = ARRAY_SIZE(led_volts), 224 + .enable_reg = BD70528_REG_LED_EN, 225 + .enable_mask = BD70528_MASK_LED1_EN, 226 + .vsel_reg = BD70528_REG_LED_VOLT, 227 + .vsel_mask = BD70528_MASK_LED1_VOLT, 228 + .owner = THIS_MODULE, 229 + }, 230 + { 231 + .name = "ldo_led2", 232 + .of_match = of_match_ptr("LDO_LED2"), 233 + .regulators_node = of_match_ptr("regulators"), 234 + .id = BD70528_LED2, 235 + .ops = &bd70528_led_ops, 236 + .type = REGULATOR_VOLTAGE, 237 + .volt_table = &led_volts[0], 238 + .n_voltages = ARRAY_SIZE(led_volts), 239 + .enable_reg = BD70528_REG_LED_EN, 240 + .enable_mask = BD70528_MASK_LED2_EN, 241 + .vsel_reg = BD70528_REG_LED_VOLT, 242 + .vsel_mask = BD70528_MASK_LED2_VOLT, 243 + .owner = THIS_MODULE, 244 + }, 245 + 246 + }; 247 + 248 + static int bd70528_probe(struct platform_device *pdev) 249 + { 250 + struct bd70528 *bd70528; 251 + int i; 252 + struct regulator_config config = { 253 + .dev = pdev->dev.parent, 254 + }; 255 + 256 + bd70528 = dev_get_drvdata(pdev->dev.parent); 257 + if (!bd70528) { 258 + dev_err(&pdev->dev, "No MFD driver data\n"); 259 + return -EINVAL; 260 + } 261 + 262 + config.regmap = bd70528->chip.regmap; 263 + 264 + for (i = 0; i < ARRAY_SIZE(bd70528_desc); i++) { 265 + struct regulator_dev *rdev; 266 + 267 + rdev = devm_regulator_register(&pdev->dev, &bd70528_desc[i], 268 + &config); 269 + if (IS_ERR(rdev)) { 270 + dev_err(&pdev->dev, 271 + "failed to register %s regulator\n", 272 + bd70528_desc[i].name); 273 + return PTR_ERR(rdev); 274 + } 275 + } 276 + return 0; 277 + } 278 + 279 + static struct platform_driver bd70528_regulator = { 280 + .driver = { 281 + .name = "bd70528-pmic" 282 + }, 283 + .probe = bd70528_probe, 284 + }; 285 + 286 + module_platform_driver(bd70528_regulator); 287 + 288 + MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>"); 289 + MODULE_DESCRIPTION("BD70528 voltage regulator driver"); 290 + MODULE_LICENSE("GPL");