679 lines · c
1// SPDX-License-Identifier: GPL-2.0+2//3// wm831x-ldo.c -- LDO driver for the WM831x series4//5// Copyright 2009 Wolfson Microelectronics PLC.6//7// Author: Mark Brown <broonie@opensource.wolfsonmicro.com>8 9#include <linux/module.h>10#include <linux/moduleparam.h>11#include <linux/init.h>12#include <linux/bitops.h>13#include <linux/err.h>14#include <linux/i2c.h>15#include <linux/platform_device.h>16#include <linux/regulator/driver.h>17#include <linux/slab.h>18 19#include <linux/mfd/wm831x/core.h>20#include <linux/mfd/wm831x/regulator.h>21#include <linux/mfd/wm831x/pdata.h>22 23#define WM831X_LDO_MAX_NAME 924 25#define WM831X_LDO_CONTROL 026#define WM831X_LDO_ON_CONTROL 127#define WM831X_LDO_SLEEP_CONTROL 228 29#define WM831X_ALIVE_LDO_ON_CONTROL 030#define WM831X_ALIVE_LDO_SLEEP_CONTROL 131 32struct wm831x_ldo {33 char name[WM831X_LDO_MAX_NAME];34 char supply_name[WM831X_LDO_MAX_NAME];35 struct regulator_desc desc;36 int base;37 struct wm831x *wm831x;38 struct regulator_dev *regulator;39};40 41/*42 * Shared43 */44 45static irqreturn_t wm831x_ldo_uv_irq(int irq, void *data)46{47 struct wm831x_ldo *ldo = data;48 49 regulator_notifier_call_chain(ldo->regulator,50 REGULATOR_EVENT_UNDER_VOLTAGE,51 NULL);52 53 return IRQ_HANDLED;54}55 56/*57 * General purpose LDOs58 */59 60static const struct linear_range wm831x_gp_ldo_ranges[] = {61 REGULATOR_LINEAR_RANGE(900000, 0, 14, 50000),62 REGULATOR_LINEAR_RANGE(1700000, 15, 31, 100000),63};64 65static int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev,66 int uV)67{68 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);69 struct wm831x *wm831x = ldo->wm831x;70 int sel, reg = ldo->base + WM831X_LDO_SLEEP_CONTROL;71 72 sel = regulator_map_voltage_linear_range(rdev, uV, uV);73 if (sel < 0)74 return sel;75 76 return wm831x_set_bits(wm831x, reg, WM831X_LDO1_ON_VSEL_MASK, sel);77}78 79static unsigned int wm831x_gp_ldo_get_mode(struct regulator_dev *rdev)80{81 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);82 struct wm831x *wm831x = ldo->wm831x;83 int ctrl_reg = ldo->base + WM831X_LDO_CONTROL;84 int on_reg = ldo->base + WM831X_LDO_ON_CONTROL;85 int ret;86 87 ret = wm831x_reg_read(wm831x, on_reg);88 if (ret < 0)89 return ret;90 91 if (!(ret & WM831X_LDO1_ON_MODE))92 return REGULATOR_MODE_NORMAL;93 94 ret = wm831x_reg_read(wm831x, ctrl_reg);95 if (ret < 0)96 return ret;97 98 if (ret & WM831X_LDO1_LP_MODE)99 return REGULATOR_MODE_STANDBY;100 else101 return REGULATOR_MODE_IDLE;102}103 104static int wm831x_gp_ldo_set_mode(struct regulator_dev *rdev,105 unsigned int mode)106{107 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);108 struct wm831x *wm831x = ldo->wm831x;109 int ctrl_reg = ldo->base + WM831X_LDO_CONTROL;110 int on_reg = ldo->base + WM831X_LDO_ON_CONTROL;111 int ret;112 113 114 switch (mode) {115 case REGULATOR_MODE_NORMAL:116 ret = wm831x_set_bits(wm831x, on_reg,117 WM831X_LDO1_ON_MODE, 0);118 if (ret < 0)119 return ret;120 break;121 122 case REGULATOR_MODE_IDLE:123 ret = wm831x_set_bits(wm831x, ctrl_reg,124 WM831X_LDO1_LP_MODE, 0);125 if (ret < 0)126 return ret;127 128 ret = wm831x_set_bits(wm831x, on_reg,129 WM831X_LDO1_ON_MODE,130 WM831X_LDO1_ON_MODE);131 if (ret < 0)132 return ret;133 break;134 135 case REGULATOR_MODE_STANDBY:136 ret = wm831x_set_bits(wm831x, ctrl_reg,137 WM831X_LDO1_LP_MODE,138 WM831X_LDO1_LP_MODE);139 if (ret < 0)140 return ret;141 142 ret = wm831x_set_bits(wm831x, on_reg,143 WM831X_LDO1_ON_MODE,144 WM831X_LDO1_ON_MODE);145 if (ret < 0)146 return ret;147 break;148 149 default:150 return -EINVAL;151 }152 153 return 0;154}155 156static int wm831x_gp_ldo_get_status(struct regulator_dev *rdev)157{158 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);159 struct wm831x *wm831x = ldo->wm831x;160 int mask = 1 << rdev_get_id(rdev);161 int ret;162 163 /* Is the regulator on? */164 ret = wm831x_reg_read(wm831x, WM831X_LDO_STATUS);165 if (ret < 0)166 return ret;167 if (!(ret & mask))168 return REGULATOR_STATUS_OFF;169 170 /* Is it reporting under voltage? */171 ret = wm831x_reg_read(wm831x, WM831X_LDO_UV_STATUS);172 if (ret < 0)173 return ret;174 if (ret & mask)175 return REGULATOR_STATUS_ERROR;176 177 ret = wm831x_gp_ldo_get_mode(rdev);178 if (ret < 0)179 return ret;180 else181 return regulator_mode_to_status(ret);182}183 184static unsigned int wm831x_gp_ldo_get_optimum_mode(struct regulator_dev *rdev,185 int input_uV,186 int output_uV, int load_uA)187{188 if (load_uA < 20000)189 return REGULATOR_MODE_STANDBY;190 if (load_uA < 50000)191 return REGULATOR_MODE_IDLE;192 return REGULATOR_MODE_NORMAL;193}194 195 196static const struct regulator_ops wm831x_gp_ldo_ops = {197 .list_voltage = regulator_list_voltage_linear_range,198 .map_voltage = regulator_map_voltage_linear_range,199 .get_voltage_sel = regulator_get_voltage_sel_regmap,200 .set_voltage_sel = regulator_set_voltage_sel_regmap,201 .set_suspend_voltage = wm831x_gp_ldo_set_suspend_voltage,202 .get_mode = wm831x_gp_ldo_get_mode,203 .set_mode = wm831x_gp_ldo_set_mode,204 .get_status = wm831x_gp_ldo_get_status,205 .get_optimum_mode = wm831x_gp_ldo_get_optimum_mode,206 .get_bypass = regulator_get_bypass_regmap,207 .set_bypass = regulator_set_bypass_regmap,208 209 .is_enabled = regulator_is_enabled_regmap,210 .enable = regulator_enable_regmap,211 .disable = regulator_disable_regmap,212};213 214static int wm831x_gp_ldo_probe(struct platform_device *pdev)215{216 struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);217 struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);218 struct regulator_config config = { };219 int id;220 struct wm831x_ldo *ldo;221 struct resource *res;222 int ret, irq;223 224 if (pdata && pdata->wm831x_num)225 id = (pdata->wm831x_num * 10) + 1;226 else227 id = 0;228 id = pdev->id - id;229 230 dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);231 232 ldo = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_ldo), GFP_KERNEL);233 if (!ldo)234 return -ENOMEM;235 236 ldo->wm831x = wm831x;237 238 res = platform_get_resource(pdev, IORESOURCE_REG, 0);239 if (res == NULL) {240 dev_err(&pdev->dev, "No REG resource\n");241 ret = -EINVAL;242 goto err;243 }244 ldo->base = res->start;245 246 snprintf(ldo->name, sizeof(ldo->name), "LDO%d", id + 1);247 ldo->desc.name = ldo->name;248 249 snprintf(ldo->supply_name, sizeof(ldo->supply_name),250 "LDO%dVDD", id + 1);251 ldo->desc.supply_name = ldo->supply_name;252 253 ldo->desc.id = id;254 ldo->desc.type = REGULATOR_VOLTAGE;255 ldo->desc.n_voltages = 32;256 ldo->desc.ops = &wm831x_gp_ldo_ops;257 ldo->desc.owner = THIS_MODULE;258 ldo->desc.vsel_reg = ldo->base + WM831X_LDO_ON_CONTROL;259 ldo->desc.vsel_mask = WM831X_LDO1_ON_VSEL_MASK;260 ldo->desc.enable_reg = WM831X_LDO_ENABLE;261 ldo->desc.enable_mask = 1 << id;262 ldo->desc.bypass_reg = ldo->base;263 ldo->desc.bypass_mask = WM831X_LDO1_SWI;264 ldo->desc.linear_ranges = wm831x_gp_ldo_ranges;265 ldo->desc.n_linear_ranges = ARRAY_SIZE(wm831x_gp_ldo_ranges);266 267 config.dev = pdev->dev.parent;268 if (pdata)269 config.init_data = pdata->ldo[id];270 config.driver_data = ldo;271 config.regmap = wm831x->regmap;272 273 ldo->regulator = devm_regulator_register(&pdev->dev, &ldo->desc,274 &config);275 if (IS_ERR(ldo->regulator)) {276 ret = PTR_ERR(ldo->regulator);277 dev_err(wm831x->dev, "Failed to register LDO%d: %d\n",278 id + 1, ret);279 goto err;280 }281 282 irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));283 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,284 wm831x_ldo_uv_irq,285 IRQF_TRIGGER_RISING | IRQF_ONESHOT,286 ldo->name,287 ldo);288 if (ret != 0) {289 dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",290 irq, ret);291 goto err;292 }293 294 platform_set_drvdata(pdev, ldo);295 296 return 0;297 298err:299 return ret;300}301 302static struct platform_driver wm831x_gp_ldo_driver = {303 .probe = wm831x_gp_ldo_probe,304 .driver = {305 .name = "wm831x-ldo",306 .probe_type = PROBE_PREFER_ASYNCHRONOUS,307 },308};309 310/*311 * Analogue LDOs312 */313 314static const struct linear_range wm831x_aldo_ranges[] = {315 REGULATOR_LINEAR_RANGE(1000000, 0, 12, 50000),316 REGULATOR_LINEAR_RANGE(1700000, 13, 31, 100000),317};318 319static int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev,320 int uV)321{322 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);323 struct wm831x *wm831x = ldo->wm831x;324 int sel, reg = ldo->base + WM831X_LDO_SLEEP_CONTROL;325 326 sel = regulator_map_voltage_linear_range(rdev, uV, uV);327 if (sel < 0)328 return sel;329 330 return wm831x_set_bits(wm831x, reg, WM831X_LDO7_ON_VSEL_MASK, sel);331}332 333static unsigned int wm831x_aldo_get_mode(struct regulator_dev *rdev)334{335 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);336 struct wm831x *wm831x = ldo->wm831x;337 int on_reg = ldo->base + WM831X_LDO_ON_CONTROL;338 int ret;339 340 ret = wm831x_reg_read(wm831x, on_reg);341 if (ret < 0)342 return 0;343 344 if (ret & WM831X_LDO7_ON_MODE)345 return REGULATOR_MODE_IDLE;346 else347 return REGULATOR_MODE_NORMAL;348}349 350static int wm831x_aldo_set_mode(struct regulator_dev *rdev,351 unsigned int mode)352{353 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);354 struct wm831x *wm831x = ldo->wm831x;355 int on_reg = ldo->base + WM831X_LDO_ON_CONTROL;356 int ret;357 358 359 switch (mode) {360 case REGULATOR_MODE_NORMAL:361 ret = wm831x_set_bits(wm831x, on_reg, WM831X_LDO7_ON_MODE, 0);362 if (ret < 0)363 return ret;364 break;365 366 case REGULATOR_MODE_IDLE:367 ret = wm831x_set_bits(wm831x, on_reg, WM831X_LDO7_ON_MODE,368 WM831X_LDO7_ON_MODE);369 if (ret < 0)370 return ret;371 break;372 373 default:374 return -EINVAL;375 }376 377 return 0;378}379 380static int wm831x_aldo_get_status(struct regulator_dev *rdev)381{382 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);383 struct wm831x *wm831x = ldo->wm831x;384 int mask = 1 << rdev_get_id(rdev);385 int ret;386 387 /* Is the regulator on? */388 ret = wm831x_reg_read(wm831x, WM831X_LDO_STATUS);389 if (ret < 0)390 return ret;391 if (!(ret & mask))392 return REGULATOR_STATUS_OFF;393 394 /* Is it reporting under voltage? */395 ret = wm831x_reg_read(wm831x, WM831X_LDO_UV_STATUS);396 if (ret < 0)397 return ret;398 if (ret & mask)399 return REGULATOR_STATUS_ERROR;400 401 ret = wm831x_aldo_get_mode(rdev);402 if (ret < 0)403 return ret;404 else405 return regulator_mode_to_status(ret);406}407 408static const struct regulator_ops wm831x_aldo_ops = {409 .list_voltage = regulator_list_voltage_linear_range,410 .map_voltage = regulator_map_voltage_linear_range,411 .get_voltage_sel = regulator_get_voltage_sel_regmap,412 .set_voltage_sel = regulator_set_voltage_sel_regmap,413 .set_suspend_voltage = wm831x_aldo_set_suspend_voltage,414 .get_mode = wm831x_aldo_get_mode,415 .set_mode = wm831x_aldo_set_mode,416 .get_status = wm831x_aldo_get_status,417 .set_bypass = regulator_set_bypass_regmap,418 .get_bypass = regulator_get_bypass_regmap,419 420 .is_enabled = regulator_is_enabled_regmap,421 .enable = regulator_enable_regmap,422 .disable = regulator_disable_regmap,423};424 425static int wm831x_aldo_probe(struct platform_device *pdev)426{427 struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);428 struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);429 struct regulator_config config = { };430 int id;431 struct wm831x_ldo *ldo;432 struct resource *res;433 int ret, irq;434 435 if (pdata && pdata->wm831x_num)436 id = (pdata->wm831x_num * 10) + 1;437 else438 id = 0;439 id = pdev->id - id;440 441 dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);442 443 ldo = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_ldo), GFP_KERNEL);444 if (!ldo)445 return -ENOMEM;446 447 ldo->wm831x = wm831x;448 449 res = platform_get_resource(pdev, IORESOURCE_REG, 0);450 if (res == NULL) {451 dev_err(&pdev->dev, "No REG resource\n");452 ret = -EINVAL;453 goto err;454 }455 ldo->base = res->start;456 457 snprintf(ldo->name, sizeof(ldo->name), "LDO%d", id + 1);458 ldo->desc.name = ldo->name;459 460 snprintf(ldo->supply_name, sizeof(ldo->supply_name),461 "LDO%dVDD", id + 1);462 ldo->desc.supply_name = ldo->supply_name;463 464 ldo->desc.id = id;465 ldo->desc.type = REGULATOR_VOLTAGE;466 ldo->desc.n_voltages = 32;467 ldo->desc.linear_ranges = wm831x_aldo_ranges;468 ldo->desc.n_linear_ranges = ARRAY_SIZE(wm831x_aldo_ranges);469 ldo->desc.ops = &wm831x_aldo_ops;470 ldo->desc.owner = THIS_MODULE;471 ldo->desc.vsel_reg = ldo->base + WM831X_LDO_ON_CONTROL;472 ldo->desc.vsel_mask = WM831X_LDO7_ON_VSEL_MASK;473 ldo->desc.enable_reg = WM831X_LDO_ENABLE;474 ldo->desc.enable_mask = 1 << id;475 ldo->desc.bypass_reg = ldo->base;476 ldo->desc.bypass_mask = WM831X_LDO7_SWI;477 478 config.dev = pdev->dev.parent;479 if (pdata)480 config.init_data = pdata->ldo[id];481 config.driver_data = ldo;482 config.regmap = wm831x->regmap;483 484 ldo->regulator = devm_regulator_register(&pdev->dev, &ldo->desc,485 &config);486 if (IS_ERR(ldo->regulator)) {487 ret = PTR_ERR(ldo->regulator);488 dev_err(wm831x->dev, "Failed to register LDO%d: %d\n",489 id + 1, ret);490 goto err;491 }492 493 irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));494 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,495 wm831x_ldo_uv_irq,496 IRQF_TRIGGER_RISING | IRQF_ONESHOT,497 ldo->name, ldo);498 if (ret != 0) {499 dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",500 irq, ret);501 goto err;502 }503 504 platform_set_drvdata(pdev, ldo);505 506 return 0;507 508err:509 return ret;510}511 512static struct platform_driver wm831x_aldo_driver = {513 .probe = wm831x_aldo_probe,514 .driver = {515 .name = "wm831x-aldo",516 .probe_type = PROBE_PREFER_ASYNCHRONOUS,517 },518};519 520/*521 * Alive LDO522 */523 524#define WM831X_ALIVE_LDO_MAX_SELECTOR 0xf525 526static int wm831x_alive_ldo_set_suspend_voltage(struct regulator_dev *rdev,527 int uV)528{529 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);530 struct wm831x *wm831x = ldo->wm831x;531 int sel, reg = ldo->base + WM831X_ALIVE_LDO_SLEEP_CONTROL;532 533 sel = regulator_map_voltage_linear(rdev, uV, uV);534 if (sel < 0)535 return sel;536 537 return wm831x_set_bits(wm831x, reg, WM831X_LDO11_ON_VSEL_MASK, sel);538}539 540static int wm831x_alive_ldo_get_status(struct regulator_dev *rdev)541{542 struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);543 struct wm831x *wm831x = ldo->wm831x;544 int mask = 1 << rdev_get_id(rdev);545 int ret;546 547 /* Is the regulator on? */548 ret = wm831x_reg_read(wm831x, WM831X_LDO_STATUS);549 if (ret < 0)550 return ret;551 if (ret & mask)552 return REGULATOR_STATUS_ON;553 else554 return REGULATOR_STATUS_OFF;555}556 557static const struct regulator_ops wm831x_alive_ldo_ops = {558 .list_voltage = regulator_list_voltage_linear,559 .map_voltage = regulator_map_voltage_linear,560 .get_voltage_sel = regulator_get_voltage_sel_regmap,561 .set_voltage_sel = regulator_set_voltage_sel_regmap,562 .set_suspend_voltage = wm831x_alive_ldo_set_suspend_voltage,563 .get_status = wm831x_alive_ldo_get_status,564 565 .is_enabled = regulator_is_enabled_regmap,566 .enable = regulator_enable_regmap,567 .disable = regulator_disable_regmap,568};569 570static int wm831x_alive_ldo_probe(struct platform_device *pdev)571{572 struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);573 struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);574 struct regulator_config config = { };575 int id;576 struct wm831x_ldo *ldo;577 struct resource *res;578 int ret;579 580 if (pdata && pdata->wm831x_num)581 id = (pdata->wm831x_num * 10) + 1;582 else583 id = 0;584 id = pdev->id - id;585 586 587 dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);588 589 ldo = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_ldo), GFP_KERNEL);590 if (!ldo)591 return -ENOMEM;592 593 ldo->wm831x = wm831x;594 595 res = platform_get_resource(pdev, IORESOURCE_REG, 0);596 if (res == NULL) {597 dev_err(&pdev->dev, "No REG resource\n");598 ret = -EINVAL;599 goto err;600 }601 ldo->base = res->start;602 603 snprintf(ldo->name, sizeof(ldo->name), "LDO%d", id + 1);604 ldo->desc.name = ldo->name;605 606 snprintf(ldo->supply_name, sizeof(ldo->supply_name),607 "LDO%dVDD", id + 1);608 ldo->desc.supply_name = ldo->supply_name;609 610 ldo->desc.id = id;611 ldo->desc.type = REGULATOR_VOLTAGE;612 ldo->desc.n_voltages = WM831X_ALIVE_LDO_MAX_SELECTOR + 1;613 ldo->desc.ops = &wm831x_alive_ldo_ops;614 ldo->desc.owner = THIS_MODULE;615 ldo->desc.vsel_reg = ldo->base + WM831X_ALIVE_LDO_ON_CONTROL;616 ldo->desc.vsel_mask = WM831X_LDO11_ON_VSEL_MASK;617 ldo->desc.enable_reg = WM831X_LDO_ENABLE;618 ldo->desc.enable_mask = 1 << id;619 ldo->desc.min_uV = 800000;620 ldo->desc.uV_step = 50000;621 ldo->desc.enable_time = 1000;622 623 config.dev = pdev->dev.parent;624 if (pdata)625 config.init_data = pdata->ldo[id];626 config.driver_data = ldo;627 config.regmap = wm831x->regmap;628 629 ldo->regulator = devm_regulator_register(&pdev->dev, &ldo->desc,630 &config);631 if (IS_ERR(ldo->regulator)) {632 ret = PTR_ERR(ldo->regulator);633 dev_err(wm831x->dev, "Failed to register LDO%d: %d\n",634 id + 1, ret);635 goto err;636 }637 638 platform_set_drvdata(pdev, ldo);639 640 return 0;641 642err:643 return ret;644}645 646static struct platform_driver wm831x_alive_ldo_driver = {647 .probe = wm831x_alive_ldo_probe,648 .driver = {649 .name = "wm831x-alive-ldo",650 .probe_type = PROBE_PREFER_ASYNCHRONOUS,651 },652};653 654static struct platform_driver * const drivers[] = {655 &wm831x_gp_ldo_driver,656 &wm831x_aldo_driver,657 &wm831x_alive_ldo_driver,658};659 660static int __init wm831x_ldo_init(void)661{662 return platform_register_drivers(drivers, ARRAY_SIZE(drivers));663}664subsys_initcall(wm831x_ldo_init);665 666static void __exit wm831x_ldo_exit(void)667{668 platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));669}670module_exit(wm831x_ldo_exit);671 672/* Module information */673MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");674MODULE_DESCRIPTION("WM831x LDO driver");675MODULE_LICENSE("GPL");676MODULE_ALIAS("platform:wm831x-ldo");677MODULE_ALIAS("platform:wm831x-aldo");678MODULE_ALIAS("platform:wm831x-aliveldo");679