599 lines · c
1// SPDX-License-Identifier: GPL-2.0+2//3// Regulator driver for DA9055 PMIC4//5// Copyright(c) 2012 Dialog Semiconductor Ltd.6//7// Author: David Dajun Chen <dchen@diasemi.com>8 9#include <linux/module.h>10#include <linux/init.h>11#include <linux/err.h>12#include <linux/gpio/consumer.h>13#include <linux/platform_device.h>14#include <linux/regulator/driver.h>15#include <linux/regulator/machine.h>16#include <linux/of.h>17#include <linux/regulator/of_regulator.h>18 19#include <linux/mfd/da9055/core.h>20#include <linux/mfd/da9055/reg.h>21#include <linux/mfd/da9055/pdata.h>22 23#define DA9055_MIN_UA 024#define DA9055_MAX_UA 325 26#define DA9055_LDO_MODE_SYNC 027#define DA9055_LDO_MODE_SLEEP 128 29#define DA9055_BUCK_MODE_SLEEP 130#define DA9055_BUCK_MODE_SYNC 231#define DA9055_BUCK_MODE_AUTO 332 33/* DA9055 REGULATOR IDs */34#define DA9055_ID_BUCK1 035#define DA9055_ID_BUCK2 136#define DA9055_ID_LDO1 237#define DA9055_ID_LDO2 338#define DA9055_ID_LDO3 439#define DA9055_ID_LDO4 540#define DA9055_ID_LDO5 641#define DA9055_ID_LDO6 742 43/* DA9055 BUCK current limit */44static const unsigned int da9055_current_limits[] = {45 500000, 600000, 700000, 80000046};47 48struct da9055_conf_reg {49 int reg;50 int sel_mask;51 int en_mask;52};53 54struct da9055_volt_reg {55 int reg_a;56 int reg_b;57 int sl_shift;58 int v_mask;59};60 61struct da9055_mode_reg {62 int reg;63 int mask;64 int shift;65};66 67struct da9055_regulator_info {68 struct regulator_desc reg_desc;69 struct da9055_conf_reg conf;70 struct da9055_volt_reg volt;71 struct da9055_mode_reg mode;72};73 74struct da9055_regulator {75 struct da9055 *da9055;76 const struct da9055_regulator_info *info;77 struct regulator_dev *rdev;78 enum gpio_select reg_rselect;79};80 81static unsigned int da9055_buck_get_mode(struct regulator_dev *rdev)82{83 struct da9055_regulator *regulator = rdev_get_drvdata(rdev);84 const struct da9055_regulator_info *info = regulator->info;85 int ret, mode = 0;86 87 ret = da9055_reg_read(regulator->da9055, info->mode.reg);88 if (ret < 0)89 return ret;90 91 switch ((ret & info->mode.mask) >> info->mode.shift) {92 case DA9055_BUCK_MODE_SYNC:93 mode = REGULATOR_MODE_FAST;94 break;95 case DA9055_BUCK_MODE_AUTO:96 mode = REGULATOR_MODE_NORMAL;97 break;98 case DA9055_BUCK_MODE_SLEEP:99 mode = REGULATOR_MODE_STANDBY;100 break;101 }102 103 return mode;104}105 106static int da9055_buck_set_mode(struct regulator_dev *rdev,107 unsigned int mode)108{109 struct da9055_regulator *regulator = rdev_get_drvdata(rdev);110 const struct da9055_regulator_info *info = regulator->info;111 int val = 0;112 113 switch (mode) {114 case REGULATOR_MODE_FAST:115 val = DA9055_BUCK_MODE_SYNC << info->mode.shift;116 break;117 case REGULATOR_MODE_NORMAL:118 val = DA9055_BUCK_MODE_AUTO << info->mode.shift;119 break;120 case REGULATOR_MODE_STANDBY:121 val = DA9055_BUCK_MODE_SLEEP << info->mode.shift;122 break;123 }124 125 return da9055_reg_update(regulator->da9055, info->mode.reg,126 info->mode.mask, val);127}128 129static unsigned int da9055_ldo_get_mode(struct regulator_dev *rdev)130{131 struct da9055_regulator *regulator = rdev_get_drvdata(rdev);132 const struct da9055_regulator_info *info = regulator->info;133 int ret;134 135 ret = da9055_reg_read(regulator->da9055, info->volt.reg_b);136 if (ret < 0)137 return ret;138 139 if (ret >> info->volt.sl_shift)140 return REGULATOR_MODE_STANDBY;141 else142 return REGULATOR_MODE_NORMAL;143}144 145static int da9055_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode)146{147 struct da9055_regulator *regulator = rdev_get_drvdata(rdev);148 const struct da9055_regulator_info *info = regulator->info;149 struct da9055_volt_reg volt = info->volt;150 int val = 0;151 152 switch (mode) {153 case REGULATOR_MODE_NORMAL:154 case REGULATOR_MODE_FAST:155 val = DA9055_LDO_MODE_SYNC;156 break;157 case REGULATOR_MODE_STANDBY:158 val = DA9055_LDO_MODE_SLEEP;159 break;160 }161 162 return da9055_reg_update(regulator->da9055, volt.reg_b,163 1 << volt.sl_shift,164 val << volt.sl_shift);165}166 167static int da9055_regulator_get_voltage_sel(struct regulator_dev *rdev)168{169 struct da9055_regulator *regulator = rdev_get_drvdata(rdev);170 const struct da9055_regulator_info *info = regulator->info;171 struct da9055_volt_reg volt = info->volt;172 int ret, sel;173 174 /*175 * There are two voltage register set A & B for voltage ramping but176 * either one of then can be active therefore we first determine177 * the active register set.178 */179 ret = da9055_reg_read(regulator->da9055, info->conf.reg);180 if (ret < 0)181 return ret;182 183 ret &= info->conf.sel_mask;184 185 /* Get the voltage for the active register set A/B */186 if (ret == DA9055_REGUALTOR_SET_A)187 ret = da9055_reg_read(regulator->da9055, volt.reg_a);188 else189 ret = da9055_reg_read(regulator->da9055, volt.reg_b);190 191 if (ret < 0)192 return ret;193 194 sel = (ret & volt.v_mask);195 return sel;196}197 198static int da9055_regulator_set_voltage_sel(struct regulator_dev *rdev,199 unsigned int selector)200{201 struct da9055_regulator *regulator = rdev_get_drvdata(rdev);202 const struct da9055_regulator_info *info = regulator->info;203 int ret;204 205 /*206 * Regulator register set A/B is not selected through GPIO therefore207 * we use default register set A for voltage ramping.208 */209 if (regulator->reg_rselect == NO_GPIO) {210 /* Select register set A */211 ret = da9055_reg_update(regulator->da9055, info->conf.reg,212 info->conf.sel_mask, DA9055_SEL_REG_A);213 if (ret < 0)214 return ret;215 216 /* Set the voltage */217 return da9055_reg_update(regulator->da9055, info->volt.reg_a,218 info->volt.v_mask, selector);219 }220 221 /*222 * Here regulator register set A/B is selected through GPIO.223 * Therefore we first determine the selected register set A/B and224 * then set the desired voltage for that register set A/B.225 */226 ret = da9055_reg_read(regulator->da9055, info->conf.reg);227 if (ret < 0)228 return ret;229 230 ret &= info->conf.sel_mask;231 232 /* Set the voltage */233 if (ret == DA9055_REGUALTOR_SET_A)234 return da9055_reg_update(regulator->da9055, info->volt.reg_a,235 info->volt.v_mask, selector);236 else237 return da9055_reg_update(regulator->da9055, info->volt.reg_b,238 info->volt.v_mask, selector);239}240 241static int da9055_regulator_set_suspend_voltage(struct regulator_dev *rdev,242 int uV)243{244 struct da9055_regulator *regulator = rdev_get_drvdata(rdev);245 const struct da9055_regulator_info *info = regulator->info;246 int ret;247 248 /* Select register set B for suspend voltage ramping. */249 if (regulator->reg_rselect == NO_GPIO) {250 ret = da9055_reg_update(regulator->da9055, info->conf.reg,251 info->conf.sel_mask, DA9055_SEL_REG_B);252 if (ret < 0)253 return ret;254 }255 256 ret = regulator_map_voltage_linear(rdev, uV, uV);257 if (ret < 0)258 return ret;259 260 return da9055_reg_update(regulator->da9055, info->volt.reg_b,261 info->volt.v_mask, ret);262}263 264static int da9055_suspend_enable(struct regulator_dev *rdev)265{266 struct da9055_regulator *regulator = rdev_get_drvdata(rdev);267 const struct da9055_regulator_info *info = regulator->info;268 269 /* Select register set B for voltage ramping. */270 if (regulator->reg_rselect == NO_GPIO)271 return da9055_reg_update(regulator->da9055, info->conf.reg,272 info->conf.sel_mask, DA9055_SEL_REG_B);273 else274 return 0;275}276 277static int da9055_suspend_disable(struct regulator_dev *rdev)278{279 struct da9055_regulator *regulator = rdev_get_drvdata(rdev);280 const struct da9055_regulator_info *info = regulator->info;281 282 /* Diselect register set B. */283 if (regulator->reg_rselect == NO_GPIO)284 return da9055_reg_update(regulator->da9055, info->conf.reg,285 info->conf.sel_mask, DA9055_SEL_REG_A);286 else287 return 0;288}289 290static const struct regulator_ops da9055_buck_ops = {291 .get_mode = da9055_buck_get_mode,292 .set_mode = da9055_buck_set_mode,293 294 .get_current_limit = regulator_get_current_limit_regmap,295 .set_current_limit = regulator_set_current_limit_regmap,296 297 .get_voltage_sel = da9055_regulator_get_voltage_sel,298 .set_voltage_sel = da9055_regulator_set_voltage_sel,299 .list_voltage = regulator_list_voltage_linear,300 .map_voltage = regulator_map_voltage_linear,301 .is_enabled = regulator_is_enabled_regmap,302 .enable = regulator_enable_regmap,303 .disable = regulator_disable_regmap,304 305 .set_suspend_voltage = da9055_regulator_set_suspend_voltage,306 .set_suspend_enable = da9055_suspend_enable,307 .set_suspend_disable = da9055_suspend_disable,308 .set_suspend_mode = da9055_buck_set_mode,309};310 311static const struct regulator_ops da9055_ldo_ops = {312 .get_mode = da9055_ldo_get_mode,313 .set_mode = da9055_ldo_set_mode,314 315 .get_voltage_sel = da9055_regulator_get_voltage_sel,316 .set_voltage_sel = da9055_regulator_set_voltage_sel,317 .list_voltage = regulator_list_voltage_linear,318 .map_voltage = regulator_map_voltage_linear,319 .is_enabled = regulator_is_enabled_regmap,320 .enable = regulator_enable_regmap,321 .disable = regulator_disable_regmap,322 323 .set_suspend_voltage = da9055_regulator_set_suspend_voltage,324 .set_suspend_enable = da9055_suspend_enable,325 .set_suspend_disable = da9055_suspend_disable,326 .set_suspend_mode = da9055_ldo_set_mode,327 328};329 330#define DA9055_LDO(_id, step, min, max, vbits, voffset) \331{\332 .reg_desc = {\333 .name = #_id,\334 .of_match = of_match_ptr(#_id),\335 .regulators_node = of_match_ptr("regulators"),\336 .ops = &da9055_ldo_ops,\337 .type = REGULATOR_VOLTAGE,\338 .id = DA9055_ID_##_id,\339 .n_voltages = (max - min) / step + 1 + (voffset), \340 .enable_reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \341 .enable_mask = 1, \342 .min_uV = (min) * 1000,\343 .uV_step = (step) * 1000,\344 .linear_min_sel = (voffset),\345 .owner = THIS_MODULE,\346 },\347 .conf = {\348 .reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \349 .sel_mask = (1 << 4),\350 .en_mask = 1,\351 },\352 .volt = {\353 .reg_a = DA9055_REG_VBCORE_A + DA9055_ID_##_id, \354 .reg_b = DA9055_REG_VBCORE_B + DA9055_ID_##_id, \355 .sl_shift = 7,\356 .v_mask = (1 << (vbits)) - 1,\357 },\358}359 360#define DA9055_BUCK(_id, step, min, max, vbits, voffset, mbits, sbits) \361{\362 .reg_desc = {\363 .name = #_id,\364 .of_match = of_match_ptr(#_id),\365 .regulators_node = of_match_ptr("regulators"),\366 .ops = &da9055_buck_ops,\367 .type = REGULATOR_VOLTAGE,\368 .id = DA9055_ID_##_id,\369 .n_voltages = (max - min) / step + 1 + (voffset), \370 .enable_reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \371 .enable_mask = 1,\372 .min_uV = (min) * 1000,\373 .uV_step = (step) * 1000,\374 .linear_min_sel = (voffset),\375 .owner = THIS_MODULE,\376 .curr_table = da9055_current_limits,\377 .n_current_limits = ARRAY_SIZE(da9055_current_limits),\378 .csel_reg = DA9055_REG_BUCK_LIM,\379 .csel_mask = (mbits),\380 },\381 .conf = {\382 .reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \383 .sel_mask = (1 << 4),\384 .en_mask = 1,\385 },\386 .volt = {\387 .reg_a = DA9055_REG_VBCORE_A + DA9055_ID_##_id, \388 .reg_b = DA9055_REG_VBCORE_B + DA9055_ID_##_id, \389 .sl_shift = 7,\390 .v_mask = (1 << (vbits)) - 1,\391 },\392 .mode = {\393 .reg = DA9055_REG_BCORE_MODE,\394 .mask = (mbits),\395 .shift = (sbits),\396 },\397}398 399static const struct da9055_regulator_info da9055_regulator_info[] = {400 DA9055_BUCK(BUCK1, 25, 725, 2075, 6, 9, 0xc, 2),401 DA9055_BUCK(BUCK2, 25, 925, 2500, 6, 0, 3, 0),402 DA9055_LDO(LDO1, 50, 900, 3300, 6, 2),403 DA9055_LDO(LDO2, 50, 900, 3300, 6, 3),404 DA9055_LDO(LDO3, 50, 900, 3300, 6, 2),405 DA9055_LDO(LDO4, 50, 900, 3300, 6, 2),406 DA9055_LDO(LDO5, 50, 900, 2750, 6, 2),407 DA9055_LDO(LDO6, 20, 900, 3300, 7, 0),408};409 410/*411 * Configures regulator to be controlled either through GPIO 1 or 2.412 * GPIO can control regulator state and/or select the regulator register413 * set A/B for voltage ramping.414 */415static int da9055_gpio_init(struct device *dev,416 struct da9055_regulator *regulator,417 struct regulator_config *config,418 struct da9055_pdata *pdata, int id)419{420 const struct da9055_regulator_info *info = regulator->info;421 struct gpio_desc *ren;422 struct gpio_desc *ena;423 struct gpio_desc *rsel;424 int ret = 0;425 426 /* Look for "regulator-enable-gpios" GPIOs in the regulator node */427 ren = devm_gpiod_get_optional(dev, "regulator-enable", GPIOD_IN);428 if (IS_ERR(ren))429 return PTR_ERR(ren);430 431 if (ren) {432 /* This GPIO is not optional at this point */433 ena = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH);434 if (IS_ERR(ena))435 return PTR_ERR(ena);436 437 config->ena_gpiod = ena;438 439 /*440 * GPI pin is muxed with regulator to control the441 * regulator state.442 */443 gpiod_set_consumer_name(ren, "DA9055 ren GPI");444 445 /*446 * Let the regulator know that its state is controlled447 * through GPI.448 */449 ret = da9055_reg_update(regulator->da9055, info->conf.reg,450 DA9055_E_GPI_MASK,451 pdata->reg_ren[id]452 << DA9055_E_GPI_SHIFT);453 if (ret < 0)454 return ret;455 }456 457 /* Look for "regulator-select-gpios" GPIOs in the regulator node */458 rsel = devm_gpiod_get_optional(dev, "regulator-select", GPIOD_IN);459 if (IS_ERR(rsel))460 return PTR_ERR(rsel);461 462 if (rsel) {463 regulator->reg_rselect = pdata->reg_rsel[id];464 465 /*466 * GPI pin is muxed with regulator to select the467 * regulator register set A/B for voltage ramping.468 */469 gpiod_set_consumer_name(rsel, "DA9055 rsel GPI");470 471 /*472 * Let the regulator know that its register set A/B473 * will be selected through GPI for voltage ramping.474 */475 ret = da9055_reg_update(regulator->da9055, info->conf.reg,476 DA9055_V_GPI_MASK,477 pdata->reg_rsel[id]478 << DA9055_V_GPI_SHIFT);479 }480 481 return ret;482}483 484static irqreturn_t da9055_ldo5_6_oc_irq(int irq, void *data)485{486 struct da9055_regulator *regulator = data;487 488 regulator_notifier_call_chain(regulator->rdev,489 REGULATOR_EVENT_OVER_CURRENT, NULL);490 491 return IRQ_HANDLED;492}493 494static inline const struct da9055_regulator_info *find_regulator_info(int id)495{496 const struct da9055_regulator_info *info;497 int i;498 499 for (i = 0; i < ARRAY_SIZE(da9055_regulator_info); i++) {500 info = &da9055_regulator_info[i];501 if (info->reg_desc.id == id)502 return info;503 }504 505 return NULL;506}507 508static int da9055_regulator_probe(struct platform_device *pdev)509{510 struct regulator_config config = { };511 struct da9055_regulator *regulator;512 struct da9055 *da9055 = dev_get_drvdata(pdev->dev.parent);513 struct da9055_pdata *pdata = dev_get_platdata(da9055->dev);514 int ret, irq;515 516 regulator = devm_kzalloc(&pdev->dev, sizeof(struct da9055_regulator),517 GFP_KERNEL);518 if (!regulator)519 return -ENOMEM;520 521 regulator->info = find_regulator_info(pdev->id);522 if (regulator->info == NULL) {523 dev_err(&pdev->dev, "invalid regulator ID specified\n");524 return -EINVAL;525 }526 527 regulator->da9055 = da9055;528 config.dev = da9055->dev;529 config.driver_data = regulator;530 config.regmap = da9055->regmap;531 532 if (pdata)533 config.init_data = pdata->regulators[pdev->id];534 535 ret = da9055_gpio_init(&pdev->dev, regulator, &config, pdata, pdev->id);536 if (ret < 0)537 return ret;538 539 regulator->rdev = devm_regulator_register(&pdev->dev,540 ®ulator->info->reg_desc,541 &config);542 if (IS_ERR(regulator->rdev)) {543 dev_err(&pdev->dev, "Failed to register regulator %s\n",544 regulator->info->reg_desc.name);545 return PTR_ERR(regulator->rdev);546 }547 548 /* Only LDO 5 and 6 has got the over current interrupt */549 if (pdev->id == DA9055_ID_LDO5 || pdev->id == DA9055_ID_LDO6) {550 irq = platform_get_irq_byname(pdev, "REGULATOR");551 if (irq < 0)552 return irq;553 554 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,555 da9055_ldo5_6_oc_irq,556 IRQF_TRIGGER_HIGH |557 IRQF_ONESHOT |558 IRQF_PROBE_SHARED,559 pdev->name, regulator);560 if (ret != 0) {561 if (ret != -EBUSY) {562 dev_err(&pdev->dev,563 "Failed to request Regulator IRQ %d: %d\n",564 irq, ret);565 return ret;566 }567 }568 }569 570 platform_set_drvdata(pdev, regulator);571 572 return 0;573}574 575static struct platform_driver da9055_regulator_driver = {576 .probe = da9055_regulator_probe,577 .driver = {578 .name = "da9055-regulator",579 .probe_type = PROBE_PREFER_ASYNCHRONOUS,580 },581};582 583static int __init da9055_regulator_init(void)584{585 return platform_driver_register(&da9055_regulator_driver);586}587subsys_initcall(da9055_regulator_init);588 589static void __exit da9055_regulator_exit(void)590{591 platform_driver_unregister(&da9055_regulator_driver);592}593module_exit(da9055_regulator_exit);594 595MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");596MODULE_DESCRIPTION("Power Regulator driver for Dialog DA9055 PMIC");597MODULE_LICENSE("GPL");598MODULE_ALIAS("platform:da9055-regulator");599