859 lines · c
1// SPDX-License-Identifier: GPL-2.0+2//3// wm831x-dcdc.c -- DC-DC buck converter 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/regulator/machine.h>18#include <linux/gpio/consumer.h>19#include <linux/slab.h>20 21#include <linux/mfd/wm831x/core.h>22#include <linux/mfd/wm831x/regulator.h>23#include <linux/mfd/wm831x/pdata.h>24 25#define WM831X_BUCKV_MAX_SELECTOR 0x6826#define WM831X_BUCKP_MAX_SELECTOR 0x6627 28#define WM831X_DCDC_MODE_FAST 029#define WM831X_DCDC_MODE_NORMAL 130#define WM831X_DCDC_MODE_IDLE 231#define WM831X_DCDC_MODE_STANDBY 332 33#define WM831X_DCDC_MAX_NAME 934 35/* Register offsets in control block */36#define WM831X_DCDC_CONTROL_1 037#define WM831X_DCDC_CONTROL_2 138#define WM831X_DCDC_ON_CONFIG 239#define WM831X_DCDC_SLEEP_CONTROL 340#define WM831X_DCDC_DVS_CONTROL 441 42/*43 * Shared44 */45 46struct wm831x_dcdc {47 char name[WM831X_DCDC_MAX_NAME];48 char supply_name[WM831X_DCDC_MAX_NAME];49 struct regulator_desc desc;50 int base;51 struct wm831x *wm831x;52 struct regulator_dev *regulator;53 struct gpio_desc *dvs_gpiod;54 int dvs_gpio_state;55 int on_vsel;56 int dvs_vsel;57};58 59static unsigned int wm831x_dcdc_get_mode(struct regulator_dev *rdev)60 61{62 struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);63 struct wm831x *wm831x = dcdc->wm831x;64 u16 reg = dcdc->base + WM831X_DCDC_ON_CONFIG;65 int val;66 67 val = wm831x_reg_read(wm831x, reg);68 if (val < 0)69 return val;70 71 val = (val & WM831X_DC1_ON_MODE_MASK) >> WM831X_DC1_ON_MODE_SHIFT;72 73 switch (val) {74 case WM831X_DCDC_MODE_FAST:75 return REGULATOR_MODE_FAST;76 case WM831X_DCDC_MODE_NORMAL:77 return REGULATOR_MODE_NORMAL;78 case WM831X_DCDC_MODE_STANDBY:79 return REGULATOR_MODE_STANDBY;80 case WM831X_DCDC_MODE_IDLE:81 return REGULATOR_MODE_IDLE;82 default:83 BUG();84 return -EINVAL;85 }86}87 88static int wm831x_dcdc_set_mode_int(struct wm831x *wm831x, int reg,89 unsigned int mode)90{91 int val;92 93 switch (mode) {94 case REGULATOR_MODE_FAST:95 val = WM831X_DCDC_MODE_FAST;96 break;97 case REGULATOR_MODE_NORMAL:98 val = WM831X_DCDC_MODE_NORMAL;99 break;100 case REGULATOR_MODE_STANDBY:101 val = WM831X_DCDC_MODE_STANDBY;102 break;103 case REGULATOR_MODE_IDLE:104 val = WM831X_DCDC_MODE_IDLE;105 break;106 default:107 return -EINVAL;108 }109 110 return wm831x_set_bits(wm831x, reg, WM831X_DC1_ON_MODE_MASK,111 val << WM831X_DC1_ON_MODE_SHIFT);112}113 114static int wm831x_dcdc_set_mode(struct regulator_dev *rdev, unsigned int mode)115{116 struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);117 struct wm831x *wm831x = dcdc->wm831x;118 u16 reg = dcdc->base + WM831X_DCDC_ON_CONFIG;119 120 return wm831x_dcdc_set_mode_int(wm831x, reg, mode);121}122 123static int wm831x_dcdc_set_suspend_mode(struct regulator_dev *rdev,124 unsigned int mode)125{126 struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);127 struct wm831x *wm831x = dcdc->wm831x;128 u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL;129 130 return wm831x_dcdc_set_mode_int(wm831x, reg, mode);131}132 133static int wm831x_dcdc_get_status(struct regulator_dev *rdev)134{135 struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);136 struct wm831x *wm831x = dcdc->wm831x;137 int ret;138 139 /* First, check for errors */140 ret = wm831x_reg_read(wm831x, WM831X_DCDC_UV_STATUS);141 if (ret < 0)142 return ret;143 144 if (ret & (1 << rdev_get_id(rdev))) {145 dev_dbg(wm831x->dev, "DCDC%d under voltage\n",146 rdev_get_id(rdev) + 1);147 return REGULATOR_STATUS_ERROR;148 }149 150 /* DCDC1 and DCDC2 can additionally detect high voltage/current */151 if (rdev_get_id(rdev) < 2) {152 if (ret & (WM831X_DC1_OV_STS << rdev_get_id(rdev))) {153 dev_dbg(wm831x->dev, "DCDC%d over voltage\n",154 rdev_get_id(rdev) + 1);155 return REGULATOR_STATUS_ERROR;156 }157 158 if (ret & (WM831X_DC1_HC_STS << rdev_get_id(rdev))) {159 dev_dbg(wm831x->dev, "DCDC%d over current\n",160 rdev_get_id(rdev) + 1);161 return REGULATOR_STATUS_ERROR;162 }163 }164 165 /* Is the regulator on? */166 ret = wm831x_reg_read(wm831x, WM831X_DCDC_STATUS);167 if (ret < 0)168 return ret;169 if (!(ret & (1 << rdev_get_id(rdev))))170 return REGULATOR_STATUS_OFF;171 172 /* TODO: When we handle hardware control modes so we can report the173 * current mode. */174 return REGULATOR_STATUS_ON;175}176 177static irqreturn_t wm831x_dcdc_uv_irq(int irq, void *data)178{179 struct wm831x_dcdc *dcdc = data;180 181 regulator_notifier_call_chain(dcdc->regulator,182 REGULATOR_EVENT_UNDER_VOLTAGE,183 NULL);184 185 return IRQ_HANDLED;186}187 188static irqreturn_t wm831x_dcdc_oc_irq(int irq, void *data)189{190 struct wm831x_dcdc *dcdc = data;191 192 regulator_notifier_call_chain(dcdc->regulator,193 REGULATOR_EVENT_OVER_CURRENT,194 NULL);195 196 return IRQ_HANDLED;197}198 199/*200 * BUCKV specifics201 */202 203static const struct linear_range wm831x_buckv_ranges[] = {204 REGULATOR_LINEAR_RANGE(600000, 0, 0x7, 0),205 REGULATOR_LINEAR_RANGE(600000, 0x8, 0x68, 12500),206};207 208static int wm831x_buckv_set_dvs(struct regulator_dev *rdev, int state)209{210 struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);211 212 if (state == dcdc->dvs_gpio_state)213 return 0;214 215 dcdc->dvs_gpio_state = state;216 gpiod_set_value(dcdc->dvs_gpiod, state);217 218 /* Should wait for DVS state change to be asserted if we have219 * a GPIO for it, for now assume the device is configured220 * for the fastest possible transition.221 */222 223 return 0;224}225 226static int wm831x_buckv_set_voltage_sel(struct regulator_dev *rdev,227 unsigned vsel)228{229 struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);230 struct wm831x *wm831x = dcdc->wm831x;231 int on_reg = dcdc->base + WM831X_DCDC_ON_CONFIG;232 int dvs_reg = dcdc->base + WM831X_DCDC_DVS_CONTROL;233 int ret;234 235 /* If this value is already set then do a GPIO update if we can */236 if (dcdc->dvs_gpiod && dcdc->on_vsel == vsel)237 return wm831x_buckv_set_dvs(rdev, 0);238 239 if (dcdc->dvs_gpiod && dcdc->dvs_vsel == vsel)240 return wm831x_buckv_set_dvs(rdev, 1);241 242 /* Always set the ON status to the minimum voltage */243 ret = wm831x_set_bits(wm831x, on_reg, WM831X_DC1_ON_VSEL_MASK, vsel);244 if (ret < 0)245 return ret;246 dcdc->on_vsel = vsel;247 248 if (!dcdc->dvs_gpiod)249 return ret;250 251 /* Kick the voltage transition now */252 ret = wm831x_buckv_set_dvs(rdev, 0);253 if (ret < 0)254 return ret;255 256 /*257 * If this VSEL is higher than the last one we've seen then258 * remember it as the DVS VSEL. This is optimised for CPUfreq259 * usage where we want to get to the highest voltage very260 * quickly.261 */262 if (vsel > dcdc->dvs_vsel) {263 ret = wm831x_set_bits(wm831x, dvs_reg,264 WM831X_DC1_DVS_VSEL_MASK,265 vsel);266 if (ret == 0)267 dcdc->dvs_vsel = vsel;268 else269 dev_warn(wm831x->dev,270 "Failed to set DCDC DVS VSEL: %d\n", ret);271 }272 273 return 0;274}275 276static int wm831x_buckv_set_suspend_voltage(struct regulator_dev *rdev,277 int uV)278{279 struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);280 struct wm831x *wm831x = dcdc->wm831x;281 u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL;282 int vsel;283 284 vsel = regulator_map_voltage_linear_range(rdev, uV, uV);285 if (vsel < 0)286 return vsel;287 288 return wm831x_set_bits(wm831x, reg, WM831X_DC1_SLP_VSEL_MASK, vsel);289}290 291static int wm831x_buckv_get_voltage_sel(struct regulator_dev *rdev)292{293 struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);294 295 if (dcdc->dvs_gpiod && dcdc->dvs_gpio_state)296 return dcdc->dvs_vsel;297 else298 return dcdc->on_vsel;299}300 301/* Current limit options */302static const unsigned int wm831x_dcdc_ilim[] = {303 125000, 250000, 375000, 500000, 625000, 750000, 875000, 1000000304};305 306static const struct regulator_ops wm831x_buckv_ops = {307 .set_voltage_sel = wm831x_buckv_set_voltage_sel,308 .get_voltage_sel = wm831x_buckv_get_voltage_sel,309 .list_voltage = regulator_list_voltage_linear_range,310 .map_voltage = regulator_map_voltage_linear_range,311 .set_suspend_voltage = wm831x_buckv_set_suspend_voltage,312 .set_current_limit = regulator_set_current_limit_regmap,313 .get_current_limit = regulator_get_current_limit_regmap,314 315 .is_enabled = regulator_is_enabled_regmap,316 .enable = regulator_enable_regmap,317 .disable = regulator_disable_regmap,318 .get_status = wm831x_dcdc_get_status,319 .get_mode = wm831x_dcdc_get_mode,320 .set_mode = wm831x_dcdc_set_mode,321 .set_suspend_mode = wm831x_dcdc_set_suspend_mode,322};323 324/*325 * Set up DVS control. We just log errors since we can still run326 * (with reduced performance) if we fail.327 */328static void wm831x_buckv_dvs_init(struct platform_device *pdev,329 struct wm831x_dcdc *dcdc,330 struct wm831x_buckv_pdata *pdata)331{332 struct wm831x *wm831x = dcdc->wm831x;333 int ret;334 u16 ctrl;335 336 if (!pdata)337 return;338 339 /* gpiolib won't let us read the GPIO status so pick the higher340 * of the two existing voltages so we take it as platform data.341 */342 dcdc->dvs_gpio_state = pdata->dvs_init_state;343 344 dcdc->dvs_gpiod = devm_gpiod_get(&pdev->dev, "dvs",345 dcdc->dvs_gpio_state ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW);346 if (IS_ERR(dcdc->dvs_gpiod)) {347 dev_err(wm831x->dev, "Failed to get %s DVS GPIO: %ld\n",348 dcdc->name, PTR_ERR(dcdc->dvs_gpiod));349 return;350 }351 352 switch (pdata->dvs_control_src) {353 case 1:354 ctrl = 2 << WM831X_DC1_DVS_SRC_SHIFT;355 break;356 case 2:357 ctrl = 3 << WM831X_DC1_DVS_SRC_SHIFT;358 break;359 default:360 dev_err(wm831x->dev, "Invalid DVS control source %d for %s\n",361 pdata->dvs_control_src, dcdc->name);362 return;363 }364 365 /* If DVS_VSEL is set to the minimum value then raise it to ON_VSEL366 * to make bootstrapping a bit smoother.367 */368 if (!dcdc->dvs_vsel) {369 ret = wm831x_set_bits(wm831x,370 dcdc->base + WM831X_DCDC_DVS_CONTROL,371 WM831X_DC1_DVS_VSEL_MASK, dcdc->on_vsel);372 if (ret == 0)373 dcdc->dvs_vsel = dcdc->on_vsel;374 else375 dev_warn(wm831x->dev, "Failed to set DVS_VSEL: %d\n",376 ret);377 }378 379 ret = wm831x_set_bits(wm831x, dcdc->base + WM831X_DCDC_DVS_CONTROL,380 WM831X_DC1_DVS_SRC_MASK, ctrl);381 if (ret < 0) {382 dev_err(wm831x->dev, "Failed to set %s DVS source: %d\n",383 dcdc->name, ret);384 }385}386 387static int wm831x_buckv_probe(struct platform_device *pdev)388{389 struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);390 struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);391 struct regulator_config config = { };392 int id;393 struct wm831x_dcdc *dcdc;394 struct resource *res;395 int ret, irq;396 397 if (pdata && pdata->wm831x_num)398 id = (pdata->wm831x_num * 10) + 1;399 else400 id = 0;401 id = pdev->id - id;402 403 dev_dbg(&pdev->dev, "Probing DCDC%d\n", id + 1);404 405 dcdc = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_dcdc),406 GFP_KERNEL);407 if (!dcdc)408 return -ENOMEM;409 410 dcdc->wm831x = wm831x;411 412 res = platform_get_resource(pdev, IORESOURCE_REG, 0);413 if (res == NULL) {414 dev_err(&pdev->dev, "No REG resource\n");415 ret = -EINVAL;416 goto err;417 }418 dcdc->base = res->start;419 420 snprintf(dcdc->name, sizeof(dcdc->name), "DCDC%d", id + 1);421 dcdc->desc.name = dcdc->name;422 423 snprintf(dcdc->supply_name, sizeof(dcdc->supply_name),424 "DC%dVDD", id + 1);425 dcdc->desc.supply_name = dcdc->supply_name;426 427 dcdc->desc.id = id;428 dcdc->desc.type = REGULATOR_VOLTAGE;429 dcdc->desc.n_voltages = WM831X_BUCKV_MAX_SELECTOR + 1;430 dcdc->desc.linear_ranges = wm831x_buckv_ranges;431 dcdc->desc.n_linear_ranges = ARRAY_SIZE(wm831x_buckv_ranges);432 dcdc->desc.ops = &wm831x_buckv_ops;433 dcdc->desc.owner = THIS_MODULE;434 dcdc->desc.enable_reg = WM831X_DCDC_ENABLE;435 dcdc->desc.enable_mask = 1 << id;436 dcdc->desc.csel_reg = dcdc->base + WM831X_DCDC_CONTROL_2;437 dcdc->desc.csel_mask = WM831X_DC1_HC_THR_MASK;438 dcdc->desc.n_current_limits = ARRAY_SIZE(wm831x_dcdc_ilim);439 dcdc->desc.curr_table = wm831x_dcdc_ilim;440 441 ret = wm831x_reg_read(wm831x, dcdc->base + WM831X_DCDC_ON_CONFIG);442 if (ret < 0) {443 dev_err(wm831x->dev, "Failed to read ON VSEL: %d\n", ret);444 goto err;445 }446 dcdc->on_vsel = ret & WM831X_DC1_ON_VSEL_MASK;447 448 ret = wm831x_reg_read(wm831x, dcdc->base + WM831X_DCDC_DVS_CONTROL);449 if (ret < 0) {450 dev_err(wm831x->dev, "Failed to read DVS VSEL: %d\n", ret);451 goto err;452 }453 dcdc->dvs_vsel = ret & WM831X_DC1_DVS_VSEL_MASK;454 455 if (pdata && pdata->dcdc[id])456 wm831x_buckv_dvs_init(pdev, dcdc,457 pdata->dcdc[id]->driver_data);458 459 config.dev = pdev->dev.parent;460 if (pdata)461 config.init_data = pdata->dcdc[id];462 config.driver_data = dcdc;463 config.regmap = wm831x->regmap;464 465 dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc,466 &config);467 if (IS_ERR(dcdc->regulator)) {468 ret = PTR_ERR(dcdc->regulator);469 dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n",470 id + 1, ret);471 goto err;472 }473 474 irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));475 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,476 wm831x_dcdc_uv_irq,477 IRQF_TRIGGER_RISING | IRQF_ONESHOT,478 dcdc->name, dcdc);479 if (ret != 0) {480 dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",481 irq, ret);482 goto err;483 }484 485 irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "HC"));486 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,487 wm831x_dcdc_oc_irq,488 IRQF_TRIGGER_RISING | IRQF_ONESHOT,489 dcdc->name, dcdc);490 if (ret != 0) {491 dev_err(&pdev->dev, "Failed to request HC IRQ %d: %d\n",492 irq, ret);493 goto err;494 }495 496 platform_set_drvdata(pdev, dcdc);497 498 return 0;499 500err:501 return ret;502}503 504static struct platform_driver wm831x_buckv_driver = {505 .probe = wm831x_buckv_probe,506 .driver = {507 .name = "wm831x-buckv",508 .probe_type = PROBE_PREFER_ASYNCHRONOUS,509 },510};511 512/*513 * BUCKP specifics514 */515 516static int wm831x_buckp_set_suspend_voltage(struct regulator_dev *rdev, int uV)517{518 struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);519 struct wm831x *wm831x = dcdc->wm831x;520 u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL;521 int sel;522 523 sel = regulator_map_voltage_linear(rdev, uV, uV);524 if (sel < 0)525 return sel;526 527 return wm831x_set_bits(wm831x, reg, WM831X_DC3_ON_VSEL_MASK, sel);528}529 530static const struct regulator_ops wm831x_buckp_ops = {531 .set_voltage_sel = regulator_set_voltage_sel_regmap,532 .get_voltage_sel = regulator_get_voltage_sel_regmap,533 .list_voltage = regulator_list_voltage_linear,534 .map_voltage = regulator_map_voltage_linear,535 .set_suspend_voltage = wm831x_buckp_set_suspend_voltage,536 537 .is_enabled = regulator_is_enabled_regmap,538 .enable = regulator_enable_regmap,539 .disable = regulator_disable_regmap,540 .get_status = wm831x_dcdc_get_status,541 .get_mode = wm831x_dcdc_get_mode,542 .set_mode = wm831x_dcdc_set_mode,543 .set_suspend_mode = wm831x_dcdc_set_suspend_mode,544};545 546static int wm831x_buckp_probe(struct platform_device *pdev)547{548 struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);549 struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);550 struct regulator_config config = { };551 int id;552 struct wm831x_dcdc *dcdc;553 struct resource *res;554 int ret, irq;555 556 if (pdata && pdata->wm831x_num)557 id = (pdata->wm831x_num * 10) + 1;558 else559 id = 0;560 id = pdev->id - id;561 562 dev_dbg(&pdev->dev, "Probing DCDC%d\n", id + 1);563 564 dcdc = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_dcdc),565 GFP_KERNEL);566 if (!dcdc)567 return -ENOMEM;568 569 dcdc->wm831x = wm831x;570 571 res = platform_get_resource(pdev, IORESOURCE_REG, 0);572 if (res == NULL) {573 dev_err(&pdev->dev, "No REG resource\n");574 ret = -EINVAL;575 goto err;576 }577 dcdc->base = res->start;578 579 snprintf(dcdc->name, sizeof(dcdc->name), "DCDC%d", id + 1);580 dcdc->desc.name = dcdc->name;581 582 snprintf(dcdc->supply_name, sizeof(dcdc->supply_name),583 "DC%dVDD", id + 1);584 dcdc->desc.supply_name = dcdc->supply_name;585 586 dcdc->desc.id = id;587 dcdc->desc.type = REGULATOR_VOLTAGE;588 dcdc->desc.n_voltages = WM831X_BUCKP_MAX_SELECTOR + 1;589 dcdc->desc.ops = &wm831x_buckp_ops;590 dcdc->desc.owner = THIS_MODULE;591 dcdc->desc.vsel_reg = dcdc->base + WM831X_DCDC_ON_CONFIG;592 dcdc->desc.vsel_mask = WM831X_DC3_ON_VSEL_MASK;593 dcdc->desc.enable_reg = WM831X_DCDC_ENABLE;594 dcdc->desc.enable_mask = 1 << id;595 dcdc->desc.min_uV = 850000;596 dcdc->desc.uV_step = 25000;597 598 config.dev = pdev->dev.parent;599 if (pdata)600 config.init_data = pdata->dcdc[id];601 config.driver_data = dcdc;602 config.regmap = wm831x->regmap;603 604 dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc,605 &config);606 if (IS_ERR(dcdc->regulator)) {607 ret = PTR_ERR(dcdc->regulator);608 dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n",609 id + 1, ret);610 goto err;611 }612 613 irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));614 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,615 wm831x_dcdc_uv_irq,616 IRQF_TRIGGER_RISING | IRQF_ONESHOT,617 dcdc->name, dcdc);618 if (ret != 0) {619 dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",620 irq, ret);621 goto err;622 }623 624 platform_set_drvdata(pdev, dcdc);625 626 return 0;627 628err:629 return ret;630}631 632static struct platform_driver wm831x_buckp_driver = {633 .probe = wm831x_buckp_probe,634 .driver = {635 .name = "wm831x-buckp",636 .probe_type = PROBE_PREFER_ASYNCHRONOUS,637 },638};639 640/*641 * DCDC boost convertors642 */643 644static int wm831x_boostp_get_status(struct regulator_dev *rdev)645{646 struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);647 struct wm831x *wm831x = dcdc->wm831x;648 int ret;649 650 /* First, check for errors */651 ret = wm831x_reg_read(wm831x, WM831X_DCDC_UV_STATUS);652 if (ret < 0)653 return ret;654 655 if (ret & (1 << rdev_get_id(rdev))) {656 dev_dbg(wm831x->dev, "DCDC%d under voltage\n",657 rdev_get_id(rdev) + 1);658 return REGULATOR_STATUS_ERROR;659 }660 661 /* Is the regulator on? */662 ret = wm831x_reg_read(wm831x, WM831X_DCDC_STATUS);663 if (ret < 0)664 return ret;665 if (ret & (1 << rdev_get_id(rdev)))666 return REGULATOR_STATUS_ON;667 else668 return REGULATOR_STATUS_OFF;669}670 671static const struct regulator_ops wm831x_boostp_ops = {672 .get_status = wm831x_boostp_get_status,673 674 .is_enabled = regulator_is_enabled_regmap,675 .enable = regulator_enable_regmap,676 .disable = regulator_disable_regmap,677};678 679static int wm831x_boostp_probe(struct platform_device *pdev)680{681 struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);682 struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);683 struct regulator_config config = { };684 int id = pdev->id % ARRAY_SIZE(pdata->dcdc);685 struct wm831x_dcdc *dcdc;686 struct resource *res;687 int ret, irq;688 689 dev_dbg(&pdev->dev, "Probing DCDC%d\n", id + 1);690 691 if (pdata == NULL || pdata->dcdc[id] == NULL)692 return -ENODEV;693 694 dcdc = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_dcdc), GFP_KERNEL);695 if (!dcdc)696 return -ENOMEM;697 698 dcdc->wm831x = wm831x;699 700 res = platform_get_resource(pdev, IORESOURCE_REG, 0);701 if (res == NULL) {702 dev_err(&pdev->dev, "No REG resource\n");703 return -EINVAL;704 }705 dcdc->base = res->start;706 707 snprintf(dcdc->name, sizeof(dcdc->name), "DCDC%d", id + 1);708 dcdc->desc.name = dcdc->name;709 dcdc->desc.id = id;710 dcdc->desc.type = REGULATOR_VOLTAGE;711 dcdc->desc.ops = &wm831x_boostp_ops;712 dcdc->desc.owner = THIS_MODULE;713 dcdc->desc.enable_reg = WM831X_DCDC_ENABLE;714 dcdc->desc.enable_mask = 1 << id;715 716 config.dev = pdev->dev.parent;717 if (pdata)718 config.init_data = pdata->dcdc[id];719 config.driver_data = dcdc;720 config.regmap = wm831x->regmap;721 722 dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc,723 &config);724 if (IS_ERR(dcdc->regulator)) {725 ret = PTR_ERR(dcdc->regulator);726 dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n",727 id + 1, ret);728 return ret;729 }730 731 irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));732 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,733 wm831x_dcdc_uv_irq,734 IRQF_TRIGGER_RISING | IRQF_ONESHOT,735 dcdc->name,736 dcdc);737 if (ret != 0) {738 dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",739 irq, ret);740 return ret;741 }742 743 platform_set_drvdata(pdev, dcdc);744 745 return 0;746}747 748static struct platform_driver wm831x_boostp_driver = {749 .probe = wm831x_boostp_probe,750 .driver = {751 .name = "wm831x-boostp",752 .probe_type = PROBE_PREFER_ASYNCHRONOUS,753 },754};755 756/*757 * External Power Enable758 *759 * These aren't actually DCDCs but look like them in hardware so share760 * code.761 */762 763#define WM831X_EPE_BASE 6764 765static const struct regulator_ops wm831x_epe_ops = {766 .is_enabled = regulator_is_enabled_regmap,767 .enable = regulator_enable_regmap,768 .disable = regulator_disable_regmap,769 .get_status = wm831x_dcdc_get_status,770};771 772static int wm831x_epe_probe(struct platform_device *pdev)773{774 struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);775 struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);776 struct regulator_config config = { };777 int id = pdev->id % ARRAY_SIZE(pdata->epe);778 struct wm831x_dcdc *dcdc;779 int ret;780 781 dev_dbg(&pdev->dev, "Probing EPE%d\n", id + 1);782 783 dcdc = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_dcdc), GFP_KERNEL);784 if (!dcdc)785 return -ENOMEM;786 787 dcdc->wm831x = wm831x;788 789 /* For current parts this is correct; probably need to revisit790 * in future.791 */792 snprintf(dcdc->name, sizeof(dcdc->name), "EPE%d", id + 1);793 dcdc->desc.name = dcdc->name;794 dcdc->desc.id = id + WM831X_EPE_BASE; /* Offset in DCDC registers */795 dcdc->desc.ops = &wm831x_epe_ops;796 dcdc->desc.type = REGULATOR_VOLTAGE;797 dcdc->desc.owner = THIS_MODULE;798 dcdc->desc.enable_reg = WM831X_DCDC_ENABLE;799 dcdc->desc.enable_mask = 1 << dcdc->desc.id;800 801 config.dev = pdev->dev.parent;802 if (pdata)803 config.init_data = pdata->epe[id];804 config.driver_data = dcdc;805 config.regmap = wm831x->regmap;806 807 dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc,808 &config);809 if (IS_ERR(dcdc->regulator)) {810 ret = PTR_ERR(dcdc->regulator);811 dev_err(wm831x->dev, "Failed to register EPE%d: %d\n",812 id + 1, ret);813 goto err;814 }815 816 platform_set_drvdata(pdev, dcdc);817 818 return 0;819 820err:821 return ret;822}823 824static struct platform_driver wm831x_epe_driver = {825 .probe = wm831x_epe_probe,826 .driver = {827 .name = "wm831x-epe",828 .probe_type = PROBE_PREFER_ASYNCHRONOUS,829 },830};831 832static struct platform_driver * const drivers[] = {833 &wm831x_buckv_driver,834 &wm831x_buckp_driver,835 &wm831x_boostp_driver,836 &wm831x_epe_driver,837};838 839static int __init wm831x_dcdc_init(void)840{841 return platform_register_drivers(drivers, ARRAY_SIZE(drivers));842}843subsys_initcall(wm831x_dcdc_init);844 845static void __exit wm831x_dcdc_exit(void)846{847 platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));848}849module_exit(wm831x_dcdc_exit);850 851/* Module information */852MODULE_AUTHOR("Mark Brown");853MODULE_DESCRIPTION("WM831x DC-DC convertor driver");854MODULE_LICENSE("GPL");855MODULE_ALIAS("platform:wm831x-buckv");856MODULE_ALIAS("platform:wm831x-buckp");857MODULE_ALIAS("platform:wm831x-boostp");858MODULE_ALIAS("platform:wm831x-epe");859