393 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2#include <linux/i2c.h>3#include <linux/module.h>4#include <linux/platform_device.h>5#include <linux/regmap.h>6#include <linux/regulator/driver.h>7 8#include <linux/mfd/88pm886.h>9 10static const struct regmap_config pm886_regulator_regmap_config = {11 .reg_bits = 8,12 .val_bits = 8,13 .max_register = PM886_REG_BUCK5_VOUT,14};15 16static const struct regulator_ops pm886_ldo_ops = {17 .list_voltage = regulator_list_voltage_table,18 .map_voltage = regulator_map_voltage_iterate,19 .set_voltage_sel = regulator_set_voltage_sel_regmap,20 .get_voltage_sel = regulator_get_voltage_sel_regmap,21 .enable = regulator_enable_regmap,22 .disable = regulator_disable_regmap,23 .is_enabled = regulator_is_enabled_regmap,24};25 26static const struct regulator_ops pm886_buck_ops = {27 .list_voltage = regulator_list_voltage_linear_range,28 .map_voltage = regulator_map_voltage_linear_range,29 .set_voltage_sel = regulator_set_voltage_sel_regmap,30 .get_voltage_sel = regulator_get_voltage_sel_regmap,31 .enable = regulator_enable_regmap,32 .disable = regulator_disable_regmap,33 .is_enabled = regulator_is_enabled_regmap,34};35 36static const unsigned int pm886_ldo_volt_table1[] = {37 1700000, 1800000, 1900000, 2500000, 2800000, 2900000, 3100000, 3300000,38};39 40static const unsigned int pm886_ldo_volt_table2[] = {41 1200000, 1250000, 1700000, 1800000, 1850000, 1900000, 2500000, 2600000,42 2700000, 2750000, 2800000, 2850000, 2900000, 3000000, 3100000, 3300000,43};44 45static const unsigned int pm886_ldo_volt_table3[] = {46 1700000, 1800000, 1900000, 2000000, 2100000, 2500000, 2700000, 2800000,47};48 49static const struct linear_range pm886_buck_volt_ranges1[] = {50 REGULATOR_LINEAR_RANGE(600000, 0, 79, 12500),51 REGULATOR_LINEAR_RANGE(1600000, 80, 84, 50000),52};53 54static const struct linear_range pm886_buck_volt_ranges2[] = {55 REGULATOR_LINEAR_RANGE(600000, 0, 79, 12500),56 REGULATOR_LINEAR_RANGE(1600000, 80, 114, 50000),57};58 59static struct regulator_desc pm886_regulators[] = {60 {61 .name = "LDO1",62 .regulators_node = "regulators",63 .of_match = "ldo1",64 .ops = &pm886_ldo_ops,65 .type = REGULATOR_VOLTAGE,66 .enable_reg = PM886_REG_LDO_EN1,67 .enable_mask = BIT(0),68 .volt_table = pm886_ldo_volt_table1,69 .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table1),70 .vsel_reg = PM886_REG_LDO1_VOUT,71 .vsel_mask = PM886_LDO_VSEL_MASK,72 },73 {74 .name = "LDO2",75 .regulators_node = "regulators",76 .of_match = "ldo2",77 .ops = &pm886_ldo_ops,78 .type = REGULATOR_VOLTAGE,79 .enable_reg = PM886_REG_LDO_EN1,80 .enable_mask = BIT(1),81 .volt_table = pm886_ldo_volt_table1,82 .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table1),83 .vsel_reg = PM886_REG_LDO2_VOUT,84 .vsel_mask = PM886_LDO_VSEL_MASK,85 },86 {87 .name = "LDO3",88 .regulators_node = "regulators",89 .of_match = "ldo3",90 .ops = &pm886_ldo_ops,91 .type = REGULATOR_VOLTAGE,92 .enable_reg = PM886_REG_LDO_EN1,93 .enable_mask = BIT(2),94 .volt_table = pm886_ldo_volt_table1,95 .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table1),96 .vsel_reg = PM886_REG_LDO3_VOUT,97 .vsel_mask = PM886_LDO_VSEL_MASK,98 },99 {100 .name = "LDO4",101 .regulators_node = "regulators",102 .of_match = "ldo4",103 .ops = &pm886_ldo_ops,104 .type = REGULATOR_VOLTAGE,105 .enable_reg = PM886_REG_LDO_EN1,106 .enable_mask = BIT(3),107 .volt_table = pm886_ldo_volt_table2,108 .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),109 .vsel_reg = PM886_REG_LDO4_VOUT,110 .vsel_mask = PM886_LDO_VSEL_MASK,111 },112 {113 .name = "LDO5",114 .regulators_node = "regulators",115 .of_match = "ldo5",116 .ops = &pm886_ldo_ops,117 .type = REGULATOR_VOLTAGE,118 .enable_reg = PM886_REG_LDO_EN1,119 .enable_mask = BIT(4),120 .volt_table = pm886_ldo_volt_table2,121 .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),122 .vsel_reg = PM886_REG_LDO5_VOUT,123 .vsel_mask = PM886_LDO_VSEL_MASK,124 },125 {126 .name = "LDO6",127 .regulators_node = "regulators",128 .of_match = "ldo6",129 .ops = &pm886_ldo_ops,130 .type = REGULATOR_VOLTAGE,131 .enable_reg = PM886_REG_LDO_EN1,132 .enable_mask = BIT(5),133 .volt_table = pm886_ldo_volt_table2,134 .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),135 .vsel_reg = PM886_REG_LDO6_VOUT,136 .vsel_mask = PM886_LDO_VSEL_MASK,137 },138 {139 .name = "LDO7",140 .regulators_node = "regulators",141 .of_match = "ldo7",142 .ops = &pm886_ldo_ops,143 .type = REGULATOR_VOLTAGE,144 .enable_reg = PM886_REG_LDO_EN1,145 .enable_mask = BIT(6),146 .volt_table = pm886_ldo_volt_table2,147 .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),148 .vsel_reg = PM886_REG_LDO7_VOUT,149 .vsel_mask = PM886_LDO_VSEL_MASK,150 },151 {152 .name = "LDO8",153 .regulators_node = "regulators",154 .of_match = "ldo8",155 .ops = &pm886_ldo_ops,156 .type = REGULATOR_VOLTAGE,157 .enable_reg = PM886_REG_LDO_EN1,158 .enable_mask = BIT(7),159 .volt_table = pm886_ldo_volt_table2,160 .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),161 .vsel_reg = PM886_REG_LDO8_VOUT,162 .vsel_mask = PM886_LDO_VSEL_MASK,163 },164 {165 .name = "LDO9",166 .regulators_node = "regulators",167 .of_match = "ldo9",168 .ops = &pm886_ldo_ops,169 .type = REGULATOR_VOLTAGE,170 .enable_reg = PM886_REG_LDO_EN2,171 .enable_mask = BIT(0),172 .volt_table = pm886_ldo_volt_table2,173 .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),174 .vsel_reg = PM886_REG_LDO9_VOUT,175 .vsel_mask = PM886_LDO_VSEL_MASK,176 },177 {178 .name = "LDO10",179 .regulators_node = "regulators",180 .of_match = "ldo10",181 .ops = &pm886_ldo_ops,182 .type = REGULATOR_VOLTAGE,183 .enable_reg = PM886_REG_LDO_EN2,184 .enable_mask = BIT(1),185 .volt_table = pm886_ldo_volt_table2,186 .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),187 .vsel_reg = PM886_REG_LDO10_VOUT,188 .vsel_mask = PM886_LDO_VSEL_MASK,189 },190 {191 .name = "LDO11",192 .regulators_node = "regulators",193 .of_match = "ldo11",194 .ops = &pm886_ldo_ops,195 .type = REGULATOR_VOLTAGE,196 .enable_reg = PM886_REG_LDO_EN2,197 .enable_mask = BIT(2),198 .volt_table = pm886_ldo_volt_table2,199 .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),200 .vsel_reg = PM886_REG_LDO11_VOUT,201 .vsel_mask = PM886_LDO_VSEL_MASK,202 },203 {204 .name = "LDO12",205 .regulators_node = "regulators",206 .of_match = "ldo12",207 .ops = &pm886_ldo_ops,208 .type = REGULATOR_VOLTAGE,209 .enable_reg = PM886_REG_LDO_EN2,210 .enable_mask = BIT(3),211 .volt_table = pm886_ldo_volt_table2,212 .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),213 .vsel_reg = PM886_REG_LDO12_VOUT,214 .vsel_mask = PM886_LDO_VSEL_MASK,215 },216 {217 .name = "LDO13",218 .regulators_node = "regulators",219 .of_match = "ldo13",220 .ops = &pm886_ldo_ops,221 .type = REGULATOR_VOLTAGE,222 .enable_reg = PM886_REG_LDO_EN2,223 .enable_mask = BIT(4),224 .volt_table = pm886_ldo_volt_table2,225 .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),226 .vsel_reg = PM886_REG_LDO13_VOUT,227 .vsel_mask = PM886_LDO_VSEL_MASK,228 },229 {230 .name = "LDO14",231 .regulators_node = "regulators",232 .of_match = "ldo14",233 .ops = &pm886_ldo_ops,234 .type = REGULATOR_VOLTAGE,235 .enable_reg = PM886_REG_LDO_EN2,236 .enable_mask = BIT(5),237 .volt_table = pm886_ldo_volt_table2,238 .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),239 .vsel_reg = PM886_REG_LDO14_VOUT,240 .vsel_mask = PM886_LDO_VSEL_MASK,241 },242 {243 .name = "LDO15",244 .regulators_node = "regulators",245 .of_match = "ldo15",246 .ops = &pm886_ldo_ops,247 .type = REGULATOR_VOLTAGE,248 .enable_reg = PM886_REG_LDO_EN2,249 .enable_mask = BIT(6),250 .volt_table = pm886_ldo_volt_table2,251 .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2),252 .vsel_reg = PM886_REG_LDO15_VOUT,253 .vsel_mask = PM886_LDO_VSEL_MASK,254 },255 {256 .name = "LDO16",257 .regulators_node = "regulators",258 .of_match = "ldo16",259 .ops = &pm886_ldo_ops,260 .type = REGULATOR_VOLTAGE,261 .enable_reg = PM886_REG_LDO_EN2,262 .enable_mask = BIT(7),263 .volt_table = pm886_ldo_volt_table3,264 .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table3),265 .vsel_reg = PM886_REG_LDO16_VOUT,266 .vsel_mask = PM886_LDO_VSEL_MASK,267 },268 {269 .name = "buck1",270 .regulators_node = "regulators",271 .of_match = "buck1",272 .ops = &pm886_buck_ops,273 .type = REGULATOR_VOLTAGE,274 .n_voltages = 85,275 .linear_ranges = pm886_buck_volt_ranges1,276 .n_linear_ranges = ARRAY_SIZE(pm886_buck_volt_ranges1),277 .vsel_reg = PM886_REG_BUCK1_VOUT,278 .vsel_mask = PM886_BUCK_VSEL_MASK,279 .enable_reg = PM886_REG_BUCK_EN,280 .enable_mask = BIT(0),281 },282 {283 .name = "buck2",284 .regulators_node = "regulators",285 .of_match = "buck2",286 .ops = &pm886_buck_ops,287 .type = REGULATOR_VOLTAGE,288 .n_voltages = 115,289 .linear_ranges = pm886_buck_volt_ranges2,290 .n_linear_ranges = ARRAY_SIZE(pm886_buck_volt_ranges2),291 .vsel_reg = PM886_REG_BUCK2_VOUT,292 .vsel_mask = PM886_BUCK_VSEL_MASK,293 .enable_reg = PM886_REG_BUCK_EN,294 .enable_mask = BIT(1),295 },296 {297 .name = "buck3",298 .regulators_node = "regulators",299 .of_match = "buck3",300 .ops = &pm886_buck_ops,301 .type = REGULATOR_VOLTAGE,302 .n_voltages = 115,303 .linear_ranges = pm886_buck_volt_ranges2,304 .n_linear_ranges = ARRAY_SIZE(pm886_buck_volt_ranges2),305 .vsel_reg = PM886_REG_BUCK3_VOUT,306 .vsel_mask = PM886_BUCK_VSEL_MASK,307 .enable_reg = PM886_REG_BUCK_EN,308 .enable_mask = BIT(2),309 },310 {311 .name = "buck4",312 .regulators_node = "regulators",313 .of_match = "buck4",314 .ops = &pm886_buck_ops,315 .type = REGULATOR_VOLTAGE,316 .n_voltages = 115,317 .linear_ranges = pm886_buck_volt_ranges2,318 .n_linear_ranges = ARRAY_SIZE(pm886_buck_volt_ranges2),319 .vsel_reg = PM886_REG_BUCK4_VOUT,320 .vsel_mask = PM886_BUCK_VSEL_MASK,321 .enable_reg = PM886_REG_BUCK_EN,322 .enable_mask = BIT(3),323 },324 {325 .name = "buck5",326 .regulators_node = "regulators",327 .of_match = "buck5",328 .ops = &pm886_buck_ops,329 .type = REGULATOR_VOLTAGE,330 .n_voltages = 115,331 .linear_ranges = pm886_buck_volt_ranges2,332 .n_linear_ranges = ARRAY_SIZE(pm886_buck_volt_ranges2),333 .vsel_reg = PM886_REG_BUCK5_VOUT,334 .vsel_mask = PM886_BUCK_VSEL_MASK,335 .enable_reg = PM886_REG_BUCK_EN,336 .enable_mask = BIT(4),337 },338};339 340static int pm886_regulator_probe(struct platform_device *pdev)341{342 struct pm886_chip *chip = dev_get_drvdata(pdev->dev.parent);343 struct regulator_config rcfg = { };344 struct device *dev = &pdev->dev;345 struct regulator_desc *rdesc;346 struct regulator_dev *rdev;347 struct i2c_client *page;348 struct regmap *regmap;349 350 page = devm_i2c_new_dummy_device(dev, chip->client->adapter,351 chip->client->addr + PM886_PAGE_OFFSET_REGULATORS);352 if (IS_ERR(page))353 return dev_err_probe(dev, PTR_ERR(page),354 "Failed to initialize regulators client\n");355 356 regmap = devm_regmap_init_i2c(page, &pm886_regulator_regmap_config);357 if (IS_ERR(regmap))358 return dev_err_probe(dev, PTR_ERR(regmap),359 "Failed to initialize regulators regmap\n");360 rcfg.regmap = regmap;361 362 rcfg.dev = dev->parent;363 364 for (int i = 0; i < ARRAY_SIZE(pm886_regulators); i++) {365 rdesc = &pm886_regulators[i];366 rdev = devm_regulator_register(dev, rdesc, &rcfg);367 if (IS_ERR(rdev))368 return dev_err_probe(dev, PTR_ERR(rdev),369 "Failed to register %s\n", rdesc->name);370 }371 372 return 0;373}374 375static const struct platform_device_id pm886_regulator_id_table[] = {376 { "88pm886-regulator", },377 { }378};379MODULE_DEVICE_TABLE(platform, pm886_regulator_id_table);380 381static struct platform_driver pm886_regulator_driver = {382 .driver = {383 .name = "88pm886-regulator",384 },385 .probe = pm886_regulator_probe,386 .id_table = pm886_regulator_id_table,387};388module_platform_driver(pm886_regulator_driver);389 390MODULE_DESCRIPTION("Marvell 88PM886 PMIC regulator driver");391MODULE_AUTHOR("Karel Balej <balejk@matfyz.cz>");392MODULE_LICENSE("GPL");393