539 lines · c
1// SPDX-License-Identifier: GPL-2.0+2//3// max77686.c - Regulator driver for the Maxim 776864//5// Copyright (C) 2012 Samsung Electronics6// Chiwoong Byun <woong.byun@samsung.com>7// Jonghwa Lee <jonghwa3.lee@samsung.com>8//9// This driver is based on max8997.c10 11#include <linux/kernel.h>12#include <linux/bug.h>13#include <linux/err.h>14#include <linux/gpio/consumer.h>15#include <linux/slab.h>16#include <linux/platform_device.h>17#include <linux/regulator/driver.h>18#include <linux/regulator/machine.h>19#include <linux/regulator/of_regulator.h>20#include <linux/mfd/max77686.h>21#include <linux/mfd/max77686-private.h>22 23#define MAX77686_LDO_MINUV 80000024#define MAX77686_LDO_UVSTEP 5000025#define MAX77686_LDO_LOW_MINUV 80000026#define MAX77686_LDO_LOW_UVSTEP 2500027#define MAX77686_BUCK_MINUV 75000028#define MAX77686_BUCK_UVSTEP 5000029#define MAX77686_BUCK_ENABLE_TIME 40 /* us */30#define MAX77686_DVS_ENABLE_TIME 22 /* us */31#define MAX77686_RAMP_DELAY 100000 /* uV/us */32#define MAX77686_DVS_RAMP_DELAY 27500 /* uV/us */33#define MAX77686_DVS_MINUV 60000034#define MAX77686_DVS_UVSTEP 1250035 36/*37 * Value for configuring buck[89] and LDO{20,21,22} as GPIO control.38 * It is the same as 'off' for other regulators.39 */40#define MAX77686_GPIO_CONTROL 0x041/*42 * Values used for configuring LDOs and bucks.43 * Forcing low power mode: LDO1, 3-5, 9, 13, 17-2644 */45#define MAX77686_LDO_LOWPOWER 0x146/*47 * On/off controlled by PWRREQ:48 * - LDO2, 6-8, 10-12, 14-1649 * - buck[1234]50 */51#define MAX77686_OFF_PWRREQ 0x152/* Low power mode controlled by PWRREQ: All LDOs */53#define MAX77686_LDO_LOWPOWER_PWRREQ 0x254/* Forcing low power mode: buck[234] */55#define MAX77686_BUCK_LOWPOWER 0x256#define MAX77686_NORMAL 0x357 58#define MAX77686_OPMODE_SHIFT 659#define MAX77686_OPMODE_BUCK234_SHIFT 460#define MAX77686_OPMODE_MASK 0x361 62#define MAX77686_VSEL_MASK 0x3F63#define MAX77686_DVS_VSEL_MASK 0xFF64 65#define MAX77686_RAMP_RATE_MASK 0xC066 67#define MAX77686_REGULATORS MAX77686_REG_MAX68#define MAX77686_LDOS 2669 70struct max77686_data {71 struct device *dev;72 DECLARE_BITMAP(gpio_enabled, MAX77686_REGULATORS);73 74 /* Array indexed by regulator id */75 unsigned int opmode[MAX77686_REGULATORS];76};77 78static unsigned int max77686_get_opmode_shift(int id)79{80 switch (id) {81 case MAX77686_BUCK1:82 case MAX77686_BUCK5 ... MAX77686_BUCK9:83 return 0;84 case MAX77686_BUCK2 ... MAX77686_BUCK4:85 return MAX77686_OPMODE_BUCK234_SHIFT;86 default:87 /* all LDOs */88 return MAX77686_OPMODE_SHIFT;89 }90}91 92/*93 * When regulator is configured for GPIO control then it94 * replaces "normal" mode. Any change from low power mode to normal95 * should actually change to GPIO control.96 * Map normal mode to proper value for such regulators.97 */98static unsigned int max77686_map_normal_mode(struct max77686_data *max77686,99 int id)100{101 switch (id) {102 case MAX77686_BUCK8:103 case MAX77686_BUCK9:104 case MAX77686_LDO20 ... MAX77686_LDO22:105 if (test_bit(id, max77686->gpio_enabled))106 return MAX77686_GPIO_CONTROL;107 }108 109 return MAX77686_NORMAL;110}111 112/* Some BUCKs and LDOs supports Normal[ON/OFF] mode during suspend */113static int max77686_set_suspend_disable(struct regulator_dev *rdev)114{115 unsigned int val, shift;116 struct max77686_data *max77686 = rdev_get_drvdata(rdev);117 int ret, id = rdev_get_id(rdev);118 119 shift = max77686_get_opmode_shift(id);120 val = MAX77686_OFF_PWRREQ;121 122 ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,123 rdev->desc->enable_mask, val << shift);124 if (ret)125 return ret;126 127 max77686->opmode[id] = val;128 return 0;129}130 131/* Some LDOs supports [LPM/Normal]ON mode during suspend state */132static int max77686_set_suspend_mode(struct regulator_dev *rdev,133 unsigned int mode)134{135 struct max77686_data *max77686 = rdev_get_drvdata(rdev);136 unsigned int val;137 int ret, id = rdev_get_id(rdev);138 139 /* BUCK[5-9] doesn't support this feature */140 if (id >= MAX77686_BUCK5)141 return 0;142 143 switch (mode) {144 case REGULATOR_MODE_IDLE: /* ON in LP Mode */145 val = MAX77686_LDO_LOWPOWER_PWRREQ;146 break;147 case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */148 val = max77686_map_normal_mode(max77686, id);149 break;150 default:151 pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n",152 rdev->desc->name, mode);153 return -EINVAL;154 }155 156 ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,157 rdev->desc->enable_mask,158 val << MAX77686_OPMODE_SHIFT);159 if (ret)160 return ret;161 162 max77686->opmode[id] = val;163 return 0;164}165 166/* Some LDOs supports LPM-ON/OFF/Normal-ON mode during suspend state */167static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev,168 unsigned int mode)169{170 unsigned int val;171 struct max77686_data *max77686 = rdev_get_drvdata(rdev);172 int ret, id = rdev_get_id(rdev);173 174 switch (mode) {175 case REGULATOR_MODE_STANDBY: /* switch off */176 val = MAX77686_OFF_PWRREQ;177 break;178 case REGULATOR_MODE_IDLE: /* ON in LP Mode */179 val = MAX77686_LDO_LOWPOWER_PWRREQ;180 break;181 case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */182 val = max77686_map_normal_mode(max77686, id);183 break;184 default:185 pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n",186 rdev->desc->name, mode);187 return -EINVAL;188 }189 190 ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,191 rdev->desc->enable_mask,192 val << MAX77686_OPMODE_SHIFT);193 if (ret)194 return ret;195 196 max77686->opmode[id] = val;197 return 0;198}199 200static int max77686_enable(struct regulator_dev *rdev)201{202 struct max77686_data *max77686 = rdev_get_drvdata(rdev);203 unsigned int shift;204 int id = rdev_get_id(rdev);205 206 shift = max77686_get_opmode_shift(id);207 208 if (max77686->opmode[id] == MAX77686_OFF_PWRREQ)209 max77686->opmode[id] = max77686_map_normal_mode(max77686, id);210 211 return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,212 rdev->desc->enable_mask,213 max77686->opmode[id] << shift);214}215 216static int max77686_of_parse_cb(struct device_node *np,217 const struct regulator_desc *desc,218 struct regulator_config *config)219{220 struct max77686_data *max77686 = config->driver_data;221 int ret;222 223 switch (desc->id) {224 case MAX77686_BUCK8:225 case MAX77686_BUCK9:226 case MAX77686_LDO20 ... MAX77686_LDO22:227 config->ena_gpiod = fwnode_gpiod_get_index(228 of_fwnode_handle(np),229 "maxim,ena",230 0,231 GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE,232 "max77686-regulator");233 if (IS_ERR(config->ena_gpiod))234 config->ena_gpiod = NULL;235 break;236 default:237 return 0;238 }239 240 if (config->ena_gpiod) {241 set_bit(desc->id, max77686->gpio_enabled);242 243 ret = regmap_update_bits(config->regmap, desc->enable_reg,244 desc->enable_mask,245 MAX77686_GPIO_CONTROL);246 if (ret) {247 gpiod_put(config->ena_gpiod);248 config->ena_gpiod = NULL;249 }250 }251 252 return 0;253}254 255static const unsigned int max77686_buck_dvs_ramp_table[] = {256 13750, 27500, 55000, 100000257};258 259static const struct regulator_ops max77686_ops = {260 .list_voltage = regulator_list_voltage_linear,261 .map_voltage = regulator_map_voltage_linear,262 .is_enabled = regulator_is_enabled_regmap,263 .enable = max77686_enable,264 .disable = regulator_disable_regmap,265 .get_voltage_sel = regulator_get_voltage_sel_regmap,266 .set_voltage_sel = regulator_set_voltage_sel_regmap,267 .set_voltage_time_sel = regulator_set_voltage_time_sel,268 .set_suspend_mode = max77686_set_suspend_mode,269};270 271static const struct regulator_ops max77686_ldo_ops = {272 .list_voltage = regulator_list_voltage_linear,273 .map_voltage = regulator_map_voltage_linear,274 .is_enabled = regulator_is_enabled_regmap,275 .enable = max77686_enable,276 .disable = regulator_disable_regmap,277 .get_voltage_sel = regulator_get_voltage_sel_regmap,278 .set_voltage_sel = regulator_set_voltage_sel_regmap,279 .set_voltage_time_sel = regulator_set_voltage_time_sel,280 .set_suspend_mode = max77686_ldo_set_suspend_mode,281 .set_suspend_disable = max77686_set_suspend_disable,282};283 284static const struct regulator_ops max77686_buck1_ops = {285 .list_voltage = regulator_list_voltage_linear,286 .map_voltage = regulator_map_voltage_linear,287 .is_enabled = regulator_is_enabled_regmap,288 .enable = max77686_enable,289 .disable = regulator_disable_regmap,290 .get_voltage_sel = regulator_get_voltage_sel_regmap,291 .set_voltage_sel = regulator_set_voltage_sel_regmap,292 .set_voltage_time_sel = regulator_set_voltage_time_sel,293 .set_suspend_disable = max77686_set_suspend_disable,294};295 296static const struct regulator_ops max77686_buck_dvs_ops = {297 .list_voltage = regulator_list_voltage_linear,298 .map_voltage = regulator_map_voltage_linear,299 .is_enabled = regulator_is_enabled_regmap,300 .enable = max77686_enable,301 .disable = regulator_disable_regmap,302 .get_voltage_sel = regulator_get_voltage_sel_regmap,303 .set_voltage_sel = regulator_set_voltage_sel_regmap,304 .set_voltage_time_sel = regulator_set_voltage_time_sel,305 .set_ramp_delay = regulator_set_ramp_delay_regmap,306 .set_suspend_disable = max77686_set_suspend_disable,307};308 309#define regulator_desc_ldo(num) { \310 .name = "LDO"#num, \311 .of_match = of_match_ptr("LDO"#num), \312 .regulators_node = of_match_ptr("voltage-regulators"), \313 .of_parse_cb = max77686_of_parse_cb, \314 .id = MAX77686_LDO##num, \315 .ops = &max77686_ops, \316 .type = REGULATOR_VOLTAGE, \317 .owner = THIS_MODULE, \318 .min_uV = MAX77686_LDO_MINUV, \319 .uV_step = MAX77686_LDO_UVSTEP, \320 .ramp_delay = MAX77686_RAMP_DELAY, \321 .n_voltages = MAX77686_VSEL_MASK + 1, \322 .vsel_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \323 .vsel_mask = MAX77686_VSEL_MASK, \324 .enable_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \325 .enable_mask = MAX77686_OPMODE_MASK \326 << MAX77686_OPMODE_SHIFT, \327}328#define regulator_desc_lpm_ldo(num) { \329 .name = "LDO"#num, \330 .of_match = of_match_ptr("LDO"#num), \331 .regulators_node = of_match_ptr("voltage-regulators"), \332 .id = MAX77686_LDO##num, \333 .ops = &max77686_ldo_ops, \334 .type = REGULATOR_VOLTAGE, \335 .owner = THIS_MODULE, \336 .min_uV = MAX77686_LDO_MINUV, \337 .uV_step = MAX77686_LDO_UVSTEP, \338 .ramp_delay = MAX77686_RAMP_DELAY, \339 .n_voltages = MAX77686_VSEL_MASK + 1, \340 .vsel_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \341 .vsel_mask = MAX77686_VSEL_MASK, \342 .enable_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \343 .enable_mask = MAX77686_OPMODE_MASK \344 << MAX77686_OPMODE_SHIFT, \345}346#define regulator_desc_ldo_low(num) { \347 .name = "LDO"#num, \348 .of_match = of_match_ptr("LDO"#num), \349 .regulators_node = of_match_ptr("voltage-regulators"), \350 .id = MAX77686_LDO##num, \351 .ops = &max77686_ldo_ops, \352 .type = REGULATOR_VOLTAGE, \353 .owner = THIS_MODULE, \354 .min_uV = MAX77686_LDO_LOW_MINUV, \355 .uV_step = MAX77686_LDO_LOW_UVSTEP, \356 .ramp_delay = MAX77686_RAMP_DELAY, \357 .n_voltages = MAX77686_VSEL_MASK + 1, \358 .vsel_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \359 .vsel_mask = MAX77686_VSEL_MASK, \360 .enable_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \361 .enable_mask = MAX77686_OPMODE_MASK \362 << MAX77686_OPMODE_SHIFT, \363}364#define regulator_desc_ldo1_low(num) { \365 .name = "LDO"#num, \366 .of_match = of_match_ptr("LDO"#num), \367 .regulators_node = of_match_ptr("voltage-regulators"), \368 .id = MAX77686_LDO##num, \369 .ops = &max77686_ops, \370 .type = REGULATOR_VOLTAGE, \371 .owner = THIS_MODULE, \372 .min_uV = MAX77686_LDO_LOW_MINUV, \373 .uV_step = MAX77686_LDO_LOW_UVSTEP, \374 .ramp_delay = MAX77686_RAMP_DELAY, \375 .n_voltages = MAX77686_VSEL_MASK + 1, \376 .vsel_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \377 .vsel_mask = MAX77686_VSEL_MASK, \378 .enable_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \379 .enable_mask = MAX77686_OPMODE_MASK \380 << MAX77686_OPMODE_SHIFT, \381}382#define regulator_desc_buck(num) { \383 .name = "BUCK"#num, \384 .of_match = of_match_ptr("BUCK"#num), \385 .regulators_node = of_match_ptr("voltage-regulators"), \386 .of_parse_cb = max77686_of_parse_cb, \387 .id = MAX77686_BUCK##num, \388 .ops = &max77686_ops, \389 .type = REGULATOR_VOLTAGE, \390 .owner = THIS_MODULE, \391 .min_uV = MAX77686_BUCK_MINUV, \392 .uV_step = MAX77686_BUCK_UVSTEP, \393 .ramp_delay = MAX77686_RAMP_DELAY, \394 .enable_time = MAX77686_BUCK_ENABLE_TIME, \395 .n_voltages = MAX77686_VSEL_MASK + 1, \396 .vsel_reg = MAX77686_REG_BUCK5OUT + (num - 5) * 2, \397 .vsel_mask = MAX77686_VSEL_MASK, \398 .enable_reg = MAX77686_REG_BUCK5CTRL + (num - 5) * 2, \399 .enable_mask = MAX77686_OPMODE_MASK, \400}401#define regulator_desc_buck1(num) { \402 .name = "BUCK"#num, \403 .of_match = of_match_ptr("BUCK"#num), \404 .regulators_node = of_match_ptr("voltage-regulators"), \405 .id = MAX77686_BUCK##num, \406 .ops = &max77686_buck1_ops, \407 .type = REGULATOR_VOLTAGE, \408 .owner = THIS_MODULE, \409 .min_uV = MAX77686_BUCK_MINUV, \410 .uV_step = MAX77686_BUCK_UVSTEP, \411 .ramp_delay = MAX77686_RAMP_DELAY, \412 .enable_time = MAX77686_BUCK_ENABLE_TIME, \413 .n_voltages = MAX77686_VSEL_MASK + 1, \414 .vsel_reg = MAX77686_REG_BUCK1OUT, \415 .vsel_mask = MAX77686_VSEL_MASK, \416 .enable_reg = MAX77686_REG_BUCK1CTRL, \417 .enable_mask = MAX77686_OPMODE_MASK, \418}419#define regulator_desc_buck_dvs(num) { \420 .name = "BUCK"#num, \421 .of_match = of_match_ptr("BUCK"#num), \422 .regulators_node = of_match_ptr("voltage-regulators"), \423 .id = MAX77686_BUCK##num, \424 .ops = &max77686_buck_dvs_ops, \425 .type = REGULATOR_VOLTAGE, \426 .owner = THIS_MODULE, \427 .min_uV = MAX77686_DVS_MINUV, \428 .uV_step = MAX77686_DVS_UVSTEP, \429 .ramp_delay = MAX77686_DVS_RAMP_DELAY, \430 .enable_time = MAX77686_DVS_ENABLE_TIME, \431 .n_voltages = MAX77686_DVS_VSEL_MASK + 1, \432 .vsel_reg = MAX77686_REG_BUCK2DVS1 + (num - 2) * 10, \433 .vsel_mask = MAX77686_DVS_VSEL_MASK, \434 .enable_reg = MAX77686_REG_BUCK2CTRL1 + (num - 2) * 10, \435 .enable_mask = MAX77686_OPMODE_MASK \436 << MAX77686_OPMODE_BUCK234_SHIFT, \437 .ramp_reg = MAX77686_REG_BUCK2CTRL1 + (num - 2) * 10, \438 .ramp_mask = MAX77686_RAMP_RATE_MASK, \439 .ramp_delay_table = max77686_buck_dvs_ramp_table, \440 .n_ramp_values = ARRAY_SIZE(max77686_buck_dvs_ramp_table), \441}442 443static const struct regulator_desc regulators[] = {444 regulator_desc_ldo1_low(1),445 regulator_desc_ldo_low(2),446 regulator_desc_ldo(3),447 regulator_desc_ldo(4),448 regulator_desc_ldo(5),449 regulator_desc_ldo_low(6),450 regulator_desc_ldo_low(7),451 regulator_desc_ldo_low(8),452 regulator_desc_ldo(9),453 regulator_desc_lpm_ldo(10),454 regulator_desc_lpm_ldo(11),455 regulator_desc_lpm_ldo(12),456 regulator_desc_ldo(13),457 regulator_desc_lpm_ldo(14),458 regulator_desc_ldo_low(15),459 regulator_desc_lpm_ldo(16),460 regulator_desc_ldo(17),461 regulator_desc_ldo(18),462 regulator_desc_ldo(19),463 regulator_desc_ldo(20),464 regulator_desc_ldo(21),465 regulator_desc_ldo(22),466 regulator_desc_ldo(23),467 regulator_desc_ldo(24),468 regulator_desc_ldo(25),469 regulator_desc_ldo(26),470 regulator_desc_buck1(1),471 regulator_desc_buck_dvs(2),472 regulator_desc_buck_dvs(3),473 regulator_desc_buck_dvs(4),474 regulator_desc_buck(5),475 regulator_desc_buck(6),476 regulator_desc_buck(7),477 regulator_desc_buck(8),478 regulator_desc_buck(9),479};480 481static int max77686_pmic_probe(struct platform_device *pdev)482{483 struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);484 struct max77686_data *max77686;485 int i;486 struct regulator_config config = { };487 488 dev_dbg(&pdev->dev, "%s\n", __func__);489 490 max77686 = devm_kzalloc(&pdev->dev, sizeof(struct max77686_data),491 GFP_KERNEL);492 if (!max77686)493 return -ENOMEM;494 495 max77686->dev = &pdev->dev;496 config.dev = iodev->dev;497 config.regmap = iodev->regmap;498 config.driver_data = max77686;499 platform_set_drvdata(pdev, max77686);500 501 for (i = 0; i < MAX77686_REGULATORS; i++) {502 struct regulator_dev *rdev;503 int id = regulators[i].id;504 505 max77686->opmode[id] = MAX77686_NORMAL;506 rdev = devm_regulator_register(&pdev->dev,507 ®ulators[i], &config);508 if (IS_ERR(rdev)) {509 int ret = PTR_ERR(rdev);510 dev_err(&pdev->dev,511 "regulator init failed for %d: %d\n", i, ret);512 return ret;513 }514 }515 516 return 0;517}518 519static const struct platform_device_id max77686_pmic_id[] = {520 {"max77686-pmic", 0},521 { },522};523MODULE_DEVICE_TABLE(platform, max77686_pmic_id);524 525static struct platform_driver max77686_pmic_driver = {526 .driver = {527 .name = "max77686-pmic",528 .probe_type = PROBE_PREFER_ASYNCHRONOUS,529 },530 .probe = max77686_pmic_probe,531 .id_table = max77686_pmic_id,532};533 534module_platform_driver(max77686_pmic_driver);535 536MODULE_DESCRIPTION("MAXIM 77686 Regulator Driver");537MODULE_AUTHOR("Chiwoong Byun <woong.byun@samsung.com>");538MODULE_LICENSE("GPL");539