406 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// Copyright (C) 2018 BayLibre SAS4// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>5//6// Regulator driver for MAXIM 77650/77651 charger/power-supply.7 8#include <linux/of.h>9#include <linux/mfd/max77650.h>10#include <linux/module.h>11#include <linux/platform_device.h>12#include <linux/regmap.h>13#include <linux/regulator/driver.h>14 15#define MAX77650_REGULATOR_EN_CTRL_MASK GENMASK(3, 0)16#define MAX77650_REGULATOR_EN_CTRL_BITS(_reg) \17 ((_reg) & MAX77650_REGULATOR_EN_CTRL_MASK)18#define MAX77650_REGULATOR_ENABLED GENMASK(2, 1)19#define MAX77650_REGULATOR_DISABLED BIT(2)20 21#define MAX77650_REGULATOR_V_LDO_MASK GENMASK(6, 0)22#define MAX77650_REGULATOR_V_SBB_MASK GENMASK(5, 0)23#define MAX77651_REGULATOR_V_SBB1_MASK GENMASK(5, 2)24#define MAX77651_REGULATOR_V_SBB1_RANGE_MASK GENMASK(1, 0)25 26#define MAX77650_REGULATOR_AD_MASK BIT(3)27#define MAX77650_REGULATOR_AD_DISABLED 0x0028#define MAX77650_REGULATOR_AD_ENABLED BIT(3)29 30#define MAX77650_REGULATOR_CURR_LIM_MASK GENMASK(7, 6)31 32enum {33 MAX77650_REGULATOR_ID_LDO = 0,34 MAX77650_REGULATOR_ID_SBB0,35 MAX77650_REGULATOR_ID_SBB1,36 MAX77650_REGULATOR_ID_SBB2,37 MAX77650_REGULATOR_NUM_REGULATORS,38};39 40struct max77650_regulator_desc {41 struct regulator_desc desc;42 unsigned int regA;43 unsigned int regB;44};45 46static const unsigned int max77651_sbb1_volt_range_sel[] = {47 0x0, 0x1, 0x2, 0x348};49 50static const struct linear_range max77651_sbb1_volt_ranges[] = {51 /* range index 0 */52 REGULATOR_LINEAR_RANGE(2400000, 0x00, 0x0f, 50000),53 /* range index 1 */54 REGULATOR_LINEAR_RANGE(3200000, 0x00, 0x0f, 50000),55 /* range index 2 */56 REGULATOR_LINEAR_RANGE(4000000, 0x00, 0x0f, 50000),57 /* range index 3 */58 REGULATOR_LINEAR_RANGE(4800000, 0x00, 0x09, 50000),59};60 61static const unsigned int max77650_current_limit_table[] = {62 1000000, 866000, 707000, 500000,63};64 65static int max77650_regulator_is_enabled(struct regulator_dev *rdev)66{67 const struct max77650_regulator_desc *rdesc;68 struct regmap *map;69 int val, rv, en;70 71 rdesc = container_of(rdev->desc, struct max77650_regulator_desc, desc);72 map = rdev_get_regmap(rdev);73 74 rv = regmap_read(map, rdesc->regB, &val);75 if (rv)76 return rv;77 78 en = MAX77650_REGULATOR_EN_CTRL_BITS(val);79 80 return en != MAX77650_REGULATOR_DISABLED;81}82 83static int max77650_regulator_enable(struct regulator_dev *rdev)84{85 const struct max77650_regulator_desc *rdesc;86 struct regmap *map;87 88 rdesc = container_of(rdev->desc, struct max77650_regulator_desc, desc);89 map = rdev_get_regmap(rdev);90 91 return regmap_update_bits(map, rdesc->regB,92 MAX77650_REGULATOR_EN_CTRL_MASK,93 MAX77650_REGULATOR_ENABLED);94}95 96static int max77650_regulator_disable(struct regulator_dev *rdev)97{98 const struct max77650_regulator_desc *rdesc;99 struct regmap *map;100 101 rdesc = container_of(rdev->desc, struct max77650_regulator_desc, desc);102 map = rdev_get_regmap(rdev);103 104 return regmap_update_bits(map, rdesc->regB,105 MAX77650_REGULATOR_EN_CTRL_MASK,106 MAX77650_REGULATOR_DISABLED);107}108 109static const struct regulator_ops max77650_regulator_LDO_ops = {110 .is_enabled = max77650_regulator_is_enabled,111 .enable = max77650_regulator_enable,112 .disable = max77650_regulator_disable,113 .list_voltage = regulator_list_voltage_linear,114 .map_voltage = regulator_map_voltage_linear,115 .get_voltage_sel = regulator_get_voltage_sel_regmap,116 .set_voltage_sel = regulator_set_voltage_sel_regmap,117 .set_active_discharge = regulator_set_active_discharge_regmap,118};119 120static const struct regulator_ops max77650_regulator_SBB_ops = {121 .is_enabled = max77650_regulator_is_enabled,122 .enable = max77650_regulator_enable,123 .disable = max77650_regulator_disable,124 .list_voltage = regulator_list_voltage_linear,125 .map_voltage = regulator_map_voltage_linear,126 .get_voltage_sel = regulator_get_voltage_sel_regmap,127 .set_voltage_sel = regulator_set_voltage_sel_regmap,128 .get_current_limit = regulator_get_current_limit_regmap,129 .set_current_limit = regulator_set_current_limit_regmap,130 .set_active_discharge = regulator_set_active_discharge_regmap,131};132 133/* Special case for max77651 SBB1 - pickable linear-range voltage mapping. */134static const struct regulator_ops max77651_SBB1_regulator_ops = {135 .is_enabled = max77650_regulator_is_enabled,136 .enable = max77650_regulator_enable,137 .disable = max77650_regulator_disable,138 .list_voltage = regulator_list_voltage_pickable_linear_range,139 .get_voltage_sel = regulator_get_voltage_sel_pickable_regmap,140 .set_voltage_sel = regulator_set_voltage_sel_pickable_regmap,141 .get_current_limit = regulator_get_current_limit_regmap,142 .set_current_limit = regulator_set_current_limit_regmap,143 .set_active_discharge = regulator_set_active_discharge_regmap,144};145 146static const struct max77650_regulator_desc max77650_LDO_desc = {147 .desc = {148 .name = "ldo",149 .of_match = of_match_ptr("ldo"),150 .regulators_node = of_match_ptr("regulators"),151 .supply_name = "in-ldo",152 .id = MAX77650_REGULATOR_ID_LDO,153 .ops = &max77650_regulator_LDO_ops,154 .min_uV = 1350000,155 .uV_step = 12500,156 .n_voltages = 128,157 .vsel_step = 1,158 .vsel_mask = MAX77650_REGULATOR_V_LDO_MASK,159 .vsel_reg = MAX77650_REG_CNFG_LDO_A,160 .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,161 .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,162 .active_discharge_mask = MAX77650_REGULATOR_AD_MASK,163 .active_discharge_reg = MAX77650_REG_CNFG_LDO_B,164 .enable_time = 100,165 .type = REGULATOR_VOLTAGE,166 .owner = THIS_MODULE,167 },168 .regA = MAX77650_REG_CNFG_LDO_A,169 .regB = MAX77650_REG_CNFG_LDO_B,170};171 172static const struct max77650_regulator_desc max77650_SBB0_desc = {173 .desc = {174 .name = "sbb0",175 .of_match = of_match_ptr("sbb0"),176 .regulators_node = of_match_ptr("regulators"),177 .supply_name = "in-sbb0",178 .id = MAX77650_REGULATOR_ID_SBB0,179 .ops = &max77650_regulator_SBB_ops,180 .min_uV = 800000,181 .uV_step = 25000,182 .n_voltages = 64,183 .vsel_step = 1,184 .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK,185 .vsel_reg = MAX77650_REG_CNFG_SBB0_A,186 .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,187 .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,188 .active_discharge_mask = MAX77650_REGULATOR_AD_MASK,189 .active_discharge_reg = MAX77650_REG_CNFG_SBB0_B,190 .enable_time = 100,191 .type = REGULATOR_VOLTAGE,192 .owner = THIS_MODULE,193 .csel_reg = MAX77650_REG_CNFG_SBB0_A,194 .csel_mask = MAX77650_REGULATOR_CURR_LIM_MASK,195 .curr_table = max77650_current_limit_table,196 .n_current_limits = ARRAY_SIZE(max77650_current_limit_table),197 },198 .regA = MAX77650_REG_CNFG_SBB0_A,199 .regB = MAX77650_REG_CNFG_SBB0_B,200};201 202static const struct max77650_regulator_desc max77650_SBB1_desc = {203 .desc = {204 .name = "sbb1",205 .of_match = of_match_ptr("sbb1"),206 .regulators_node = of_match_ptr("regulators"),207 .supply_name = "in-sbb1",208 .id = MAX77650_REGULATOR_ID_SBB1,209 .ops = &max77650_regulator_SBB_ops,210 .min_uV = 800000,211 .uV_step = 12500,212 .n_voltages = 64,213 .vsel_step = 1,214 .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK,215 .vsel_reg = MAX77650_REG_CNFG_SBB1_A,216 .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,217 .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,218 .active_discharge_mask = MAX77650_REGULATOR_AD_MASK,219 .active_discharge_reg = MAX77650_REG_CNFG_SBB1_B,220 .enable_time = 100,221 .type = REGULATOR_VOLTAGE,222 .owner = THIS_MODULE,223 .csel_reg = MAX77650_REG_CNFG_SBB1_A,224 .csel_mask = MAX77650_REGULATOR_CURR_LIM_MASK,225 .curr_table = max77650_current_limit_table,226 .n_current_limits = ARRAY_SIZE(max77650_current_limit_table),227 },228 .regA = MAX77650_REG_CNFG_SBB1_A,229 .regB = MAX77650_REG_CNFG_SBB1_B,230};231 232static const struct max77650_regulator_desc max77651_SBB1_desc = {233 .desc = {234 .name = "sbb1",235 .of_match = of_match_ptr("sbb1"),236 .regulators_node = of_match_ptr("regulators"),237 .supply_name = "in-sbb1",238 .id = MAX77650_REGULATOR_ID_SBB1,239 .ops = &max77651_SBB1_regulator_ops,240 .linear_range_selectors_bitfield = max77651_sbb1_volt_range_sel,241 .linear_ranges = max77651_sbb1_volt_ranges,242 .n_linear_ranges = ARRAY_SIZE(max77651_sbb1_volt_ranges),243 .n_voltages = 58,244 .vsel_step = 1,245 .vsel_range_mask = MAX77651_REGULATOR_V_SBB1_RANGE_MASK,246 .vsel_range_reg = MAX77650_REG_CNFG_SBB1_A,247 .vsel_mask = MAX77651_REGULATOR_V_SBB1_MASK,248 .vsel_reg = MAX77650_REG_CNFG_SBB1_A,249 .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,250 .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,251 .active_discharge_mask = MAX77650_REGULATOR_AD_MASK,252 .active_discharge_reg = MAX77650_REG_CNFG_SBB1_B,253 .enable_time = 100,254 .type = REGULATOR_VOLTAGE,255 .owner = THIS_MODULE,256 .csel_reg = MAX77650_REG_CNFG_SBB1_A,257 .csel_mask = MAX77650_REGULATOR_CURR_LIM_MASK,258 .curr_table = max77650_current_limit_table,259 .n_current_limits = ARRAY_SIZE(max77650_current_limit_table),260 },261 .regA = MAX77650_REG_CNFG_SBB1_A,262 .regB = MAX77650_REG_CNFG_SBB1_B,263};264 265static const struct max77650_regulator_desc max77650_SBB2_desc = {266 .desc = {267 .name = "sbb2",268 .of_match = of_match_ptr("sbb2"),269 .regulators_node = of_match_ptr("regulators"),270 .supply_name = "in-sbb0",271 .id = MAX77650_REGULATOR_ID_SBB2,272 .ops = &max77650_regulator_SBB_ops,273 .min_uV = 800000,274 .uV_step = 50000,275 .n_voltages = 64,276 .vsel_step = 1,277 .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK,278 .vsel_reg = MAX77650_REG_CNFG_SBB2_A,279 .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,280 .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,281 .active_discharge_mask = MAX77650_REGULATOR_AD_MASK,282 .active_discharge_reg = MAX77650_REG_CNFG_SBB2_B,283 .enable_time = 100,284 .type = REGULATOR_VOLTAGE,285 .owner = THIS_MODULE,286 .csel_reg = MAX77650_REG_CNFG_SBB2_A,287 .csel_mask = MAX77650_REGULATOR_CURR_LIM_MASK,288 .curr_table = max77650_current_limit_table,289 .n_current_limits = ARRAY_SIZE(max77650_current_limit_table),290 },291 .regA = MAX77650_REG_CNFG_SBB2_A,292 .regB = MAX77650_REG_CNFG_SBB2_B,293};294 295static const struct max77650_regulator_desc max77651_SBB2_desc = {296 .desc = {297 .name = "sbb2",298 .of_match = of_match_ptr("sbb2"),299 .regulators_node = of_match_ptr("regulators"),300 .supply_name = "in-sbb0",301 .id = MAX77650_REGULATOR_ID_SBB2,302 .ops = &max77650_regulator_SBB_ops,303 .min_uV = 2400000,304 .uV_step = 50000,305 .n_voltages = 64,306 .vsel_step = 1,307 .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK,308 .vsel_reg = MAX77650_REG_CNFG_SBB2_A,309 .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,310 .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,311 .active_discharge_mask = MAX77650_REGULATOR_AD_MASK,312 .active_discharge_reg = MAX77650_REG_CNFG_SBB2_B,313 .enable_time = 100,314 .type = REGULATOR_VOLTAGE,315 .owner = THIS_MODULE,316 .csel_reg = MAX77650_REG_CNFG_SBB2_A,317 .csel_mask = MAX77650_REGULATOR_CURR_LIM_MASK,318 .curr_table = max77650_current_limit_table,319 .n_current_limits = ARRAY_SIZE(max77650_current_limit_table),320 },321 .regA = MAX77650_REG_CNFG_SBB2_A,322 .regB = MAX77650_REG_CNFG_SBB2_B,323};324 325static int max77650_regulator_probe(struct platform_device *pdev)326{327 const struct max77650_regulator_desc **rdescs;328 const struct max77650_regulator_desc *rdesc;329 struct regulator_config config = { };330 struct device *dev, *parent;331 struct regulator_dev *rdev;332 struct regmap *map;333 unsigned int val;334 int i, rv;335 336 dev = &pdev->dev;337 parent = dev->parent;338 339 if (!dev->of_node)340 dev->of_node = parent->of_node;341 342 rdescs = devm_kcalloc(dev, MAX77650_REGULATOR_NUM_REGULATORS,343 sizeof(*rdescs), GFP_KERNEL);344 if (!rdescs)345 return -ENOMEM;346 347 map = dev_get_regmap(parent, NULL);348 if (!map)349 return -ENODEV;350 351 rv = regmap_read(map, MAX77650_REG_CID, &val);352 if (rv)353 return rv;354 355 rdescs[MAX77650_REGULATOR_ID_LDO] = &max77650_LDO_desc;356 rdescs[MAX77650_REGULATOR_ID_SBB0] = &max77650_SBB0_desc;357 358 switch (MAX77650_CID_BITS(val)) {359 case MAX77650_CID_77650A:360 case MAX77650_CID_77650C:361 rdescs[MAX77650_REGULATOR_ID_SBB1] = &max77650_SBB1_desc;362 rdescs[MAX77650_REGULATOR_ID_SBB2] = &max77650_SBB2_desc;363 break;364 case MAX77650_CID_77651A:365 case MAX77650_CID_77651B:366 rdescs[MAX77650_REGULATOR_ID_SBB1] = &max77651_SBB1_desc;367 rdescs[MAX77650_REGULATOR_ID_SBB2] = &max77651_SBB2_desc;368 break;369 default:370 return -ENODEV;371 }372 373 config.dev = parent;374 375 for (i = 0; i < MAX77650_REGULATOR_NUM_REGULATORS; i++) {376 rdesc = rdescs[i];377 378 rdev = devm_regulator_register(dev, &rdesc->desc, &config);379 if (IS_ERR(rdev))380 return PTR_ERR(rdev);381 }382 383 return 0;384}385 386static const struct of_device_id max77650_regulator_of_match[] = {387 { .compatible = "maxim,max77650-regulator" },388 { }389};390MODULE_DEVICE_TABLE(of, max77650_regulator_of_match);391 392static struct platform_driver max77650_regulator_driver = {393 .driver = {394 .name = "max77650-regulator",395 .probe_type = PROBE_PREFER_ASYNCHRONOUS,396 .of_match_table = max77650_regulator_of_match,397 },398 .probe = max77650_regulator_probe,399};400module_platform_driver(max77650_regulator_driver);401 402MODULE_DESCRIPTION("MAXIM 77650/77651 regulator driver");403MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");404MODULE_LICENSE("GPL v2");405MODULE_ALIAS("platform:max77650-regulator");406