Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 //
0003 // wm831x-dcdc.c  --  DC-DC buck converter driver for the WM831x series
0004 //
0005 // Copyright 2009 Wolfson Microelectronics PLC.
0006 //
0007 // Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
0008 
0009 #include <linux/module.h>
0010 #include <linux/moduleparam.h>
0011 #include <linux/init.h>
0012 #include <linux/bitops.h>
0013 #include <linux/err.h>
0014 #include <linux/i2c.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/regulator/driver.h>
0017 #include <linux/regulator/machine.h>
0018 #include <linux/gpio/consumer.h>
0019 #include <linux/slab.h>
0020 
0021 #include <linux/mfd/wm831x/core.h>
0022 #include <linux/mfd/wm831x/regulator.h>
0023 #include <linux/mfd/wm831x/pdata.h>
0024 
0025 #define WM831X_BUCKV_MAX_SELECTOR 0x68
0026 #define WM831X_BUCKP_MAX_SELECTOR 0x66
0027 
0028 #define WM831X_DCDC_MODE_FAST    0
0029 #define WM831X_DCDC_MODE_NORMAL  1
0030 #define WM831X_DCDC_MODE_IDLE    2
0031 #define WM831X_DCDC_MODE_STANDBY 3
0032 
0033 #define WM831X_DCDC_MAX_NAME 9
0034 
0035 /* Register offsets in control block */
0036 #define WM831X_DCDC_CONTROL_1     0
0037 #define WM831X_DCDC_CONTROL_2     1
0038 #define WM831X_DCDC_ON_CONFIG     2
0039 #define WM831X_DCDC_SLEEP_CONTROL 3
0040 #define WM831X_DCDC_DVS_CONTROL   4
0041 
0042 /*
0043  * Shared
0044  */
0045 
0046 struct wm831x_dcdc {
0047     char name[WM831X_DCDC_MAX_NAME];
0048     char supply_name[WM831X_DCDC_MAX_NAME];
0049     struct regulator_desc desc;
0050     int base;
0051     struct wm831x *wm831x;
0052     struct regulator_dev *regulator;
0053     struct gpio_desc *dvs_gpiod;
0054     int dvs_gpio_state;
0055     int on_vsel;
0056     int dvs_vsel;
0057 };
0058 
0059 static unsigned int wm831x_dcdc_get_mode(struct regulator_dev *rdev)
0060 
0061 {
0062     struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
0063     struct wm831x *wm831x = dcdc->wm831x;
0064     u16 reg = dcdc->base + WM831X_DCDC_ON_CONFIG;
0065     int val;
0066 
0067     val = wm831x_reg_read(wm831x, reg);
0068     if (val < 0)
0069         return val;
0070 
0071     val = (val & WM831X_DC1_ON_MODE_MASK) >> WM831X_DC1_ON_MODE_SHIFT;
0072 
0073     switch (val) {
0074     case WM831X_DCDC_MODE_FAST:
0075         return REGULATOR_MODE_FAST;
0076     case WM831X_DCDC_MODE_NORMAL:
0077         return REGULATOR_MODE_NORMAL;
0078     case WM831X_DCDC_MODE_STANDBY:
0079         return REGULATOR_MODE_STANDBY;
0080     case WM831X_DCDC_MODE_IDLE:
0081         return REGULATOR_MODE_IDLE;
0082     default:
0083         BUG();
0084         return -EINVAL;
0085     }
0086 }
0087 
0088 static int wm831x_dcdc_set_mode_int(struct wm831x *wm831x, int reg,
0089                     unsigned int mode)
0090 {
0091     int val;
0092 
0093     switch (mode) {
0094     case REGULATOR_MODE_FAST:
0095         val = WM831X_DCDC_MODE_FAST;
0096         break;
0097     case REGULATOR_MODE_NORMAL:
0098         val = WM831X_DCDC_MODE_NORMAL;
0099         break;
0100     case REGULATOR_MODE_STANDBY:
0101         val = WM831X_DCDC_MODE_STANDBY;
0102         break;
0103     case REGULATOR_MODE_IDLE:
0104         val = WM831X_DCDC_MODE_IDLE;
0105         break;
0106     default:
0107         return -EINVAL;
0108     }
0109 
0110     return wm831x_set_bits(wm831x, reg, WM831X_DC1_ON_MODE_MASK,
0111                    val << WM831X_DC1_ON_MODE_SHIFT);
0112 }
0113 
0114 static int wm831x_dcdc_set_mode(struct regulator_dev *rdev, unsigned int mode)
0115 {
0116     struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
0117     struct wm831x *wm831x = dcdc->wm831x;
0118     u16 reg = dcdc->base + WM831X_DCDC_ON_CONFIG;
0119 
0120     return wm831x_dcdc_set_mode_int(wm831x, reg, mode);
0121 }
0122 
0123 static int wm831x_dcdc_set_suspend_mode(struct regulator_dev *rdev,
0124                     unsigned int mode)
0125 {
0126     struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
0127     struct wm831x *wm831x = dcdc->wm831x;
0128     u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL;
0129 
0130     return wm831x_dcdc_set_mode_int(wm831x, reg, mode);
0131 }
0132 
0133 static int wm831x_dcdc_get_status(struct regulator_dev *rdev)
0134 {
0135     struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
0136     struct wm831x *wm831x = dcdc->wm831x;
0137     int ret;
0138 
0139     /* First, check for errors */
0140     ret = wm831x_reg_read(wm831x, WM831X_DCDC_UV_STATUS);
0141     if (ret < 0)
0142         return ret;
0143 
0144     if (ret & (1 << rdev_get_id(rdev))) {
0145         dev_dbg(wm831x->dev, "DCDC%d under voltage\n",
0146             rdev_get_id(rdev) + 1);
0147         return REGULATOR_STATUS_ERROR;
0148     }
0149 
0150     /* DCDC1 and DCDC2 can additionally detect high voltage/current */
0151     if (rdev_get_id(rdev) < 2) {
0152         if (ret & (WM831X_DC1_OV_STS << rdev_get_id(rdev))) {
0153             dev_dbg(wm831x->dev, "DCDC%d over voltage\n",
0154                 rdev_get_id(rdev) + 1);
0155             return REGULATOR_STATUS_ERROR;
0156         }
0157 
0158         if (ret & (WM831X_DC1_HC_STS << rdev_get_id(rdev))) {
0159             dev_dbg(wm831x->dev, "DCDC%d over current\n",
0160                 rdev_get_id(rdev) + 1);
0161             return REGULATOR_STATUS_ERROR;
0162         }
0163     }
0164 
0165     /* Is the regulator on? */
0166     ret = wm831x_reg_read(wm831x, WM831X_DCDC_STATUS);
0167     if (ret < 0)
0168         return ret;
0169     if (!(ret & (1 << rdev_get_id(rdev))))
0170         return REGULATOR_STATUS_OFF;
0171 
0172     /* TODO: When we handle hardware control modes so we can report the
0173      * current mode. */
0174     return REGULATOR_STATUS_ON;
0175 }
0176 
0177 static irqreturn_t wm831x_dcdc_uv_irq(int irq, void *data)
0178 {
0179     struct wm831x_dcdc *dcdc = data;
0180 
0181     regulator_notifier_call_chain(dcdc->regulator,
0182                       REGULATOR_EVENT_UNDER_VOLTAGE,
0183                       NULL);
0184 
0185     return IRQ_HANDLED;
0186 }
0187 
0188 static irqreturn_t wm831x_dcdc_oc_irq(int irq, void *data)
0189 {
0190     struct wm831x_dcdc *dcdc = data;
0191 
0192     regulator_notifier_call_chain(dcdc->regulator,
0193                       REGULATOR_EVENT_OVER_CURRENT,
0194                       NULL);
0195 
0196     return IRQ_HANDLED;
0197 }
0198 
0199 /*
0200  * BUCKV specifics
0201  */
0202 
0203 static const struct linear_range wm831x_buckv_ranges[] = {
0204     REGULATOR_LINEAR_RANGE(600000, 0, 0x7, 0),
0205     REGULATOR_LINEAR_RANGE(600000, 0x8, 0x68, 12500),
0206 };
0207 
0208 static int wm831x_buckv_set_dvs(struct regulator_dev *rdev, int state)
0209 {
0210     struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
0211 
0212     if (state == dcdc->dvs_gpio_state)
0213         return 0;
0214 
0215     dcdc->dvs_gpio_state = state;
0216     gpiod_set_value(dcdc->dvs_gpiod, state);
0217 
0218     /* Should wait for DVS state change to be asserted if we have
0219      * a GPIO for it, for now assume the device is configured
0220      * for the fastest possible transition.
0221      */
0222 
0223     return 0;
0224 }
0225 
0226 static int wm831x_buckv_set_voltage_sel(struct regulator_dev *rdev,
0227                     unsigned vsel)
0228 {
0229     struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
0230     struct wm831x *wm831x = dcdc->wm831x;
0231     int on_reg = dcdc->base + WM831X_DCDC_ON_CONFIG;
0232     int dvs_reg = dcdc->base + WM831X_DCDC_DVS_CONTROL;
0233     int ret;
0234 
0235     /* If this value is already set then do a GPIO update if we can */
0236     if (dcdc->dvs_gpiod && dcdc->on_vsel == vsel)
0237         return wm831x_buckv_set_dvs(rdev, 0);
0238 
0239     if (dcdc->dvs_gpiod && dcdc->dvs_vsel == vsel)
0240         return wm831x_buckv_set_dvs(rdev, 1);
0241 
0242     /* Always set the ON status to the minimum voltage */
0243     ret = wm831x_set_bits(wm831x, on_reg, WM831X_DC1_ON_VSEL_MASK, vsel);
0244     if (ret < 0)
0245         return ret;
0246     dcdc->on_vsel = vsel;
0247 
0248     if (!dcdc->dvs_gpiod)
0249         return ret;
0250 
0251     /* Kick the voltage transition now */
0252     ret = wm831x_buckv_set_dvs(rdev, 0);
0253     if (ret < 0)
0254         return ret;
0255 
0256     /*
0257      * If this VSEL is higher than the last one we've seen then
0258      * remember it as the DVS VSEL.  This is optimised for CPUfreq
0259      * usage where we want to get to the highest voltage very
0260      * quickly.
0261      */
0262     if (vsel > dcdc->dvs_vsel) {
0263         ret = wm831x_set_bits(wm831x, dvs_reg,
0264                       WM831X_DC1_DVS_VSEL_MASK,
0265                       vsel);
0266         if (ret == 0)
0267             dcdc->dvs_vsel = vsel;
0268         else
0269             dev_warn(wm831x->dev,
0270                  "Failed to set DCDC DVS VSEL: %d\n", ret);
0271     }
0272 
0273     return 0;
0274 }
0275 
0276 static int wm831x_buckv_set_suspend_voltage(struct regulator_dev *rdev,
0277                         int uV)
0278 {
0279     struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
0280     struct wm831x *wm831x = dcdc->wm831x;
0281     u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL;
0282     int vsel;
0283 
0284     vsel = regulator_map_voltage_linear_range(rdev, uV, uV);
0285     if (vsel < 0)
0286         return vsel;
0287 
0288     return wm831x_set_bits(wm831x, reg, WM831X_DC1_SLP_VSEL_MASK, vsel);
0289 }
0290 
0291 static int wm831x_buckv_get_voltage_sel(struct regulator_dev *rdev)
0292 {
0293     struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
0294 
0295     if (dcdc->dvs_gpiod && dcdc->dvs_gpio_state)
0296         return dcdc->dvs_vsel;
0297     else
0298         return dcdc->on_vsel;
0299 }
0300 
0301 /* Current limit options */
0302 static const unsigned int wm831x_dcdc_ilim[] = {
0303     125000, 250000, 375000, 500000, 625000, 750000, 875000, 1000000
0304 };
0305 
0306 static const struct regulator_ops wm831x_buckv_ops = {
0307     .set_voltage_sel = wm831x_buckv_set_voltage_sel,
0308     .get_voltage_sel = wm831x_buckv_get_voltage_sel,
0309     .list_voltage = regulator_list_voltage_linear_range,
0310     .map_voltage = regulator_map_voltage_linear_range,
0311     .set_suspend_voltage = wm831x_buckv_set_suspend_voltage,
0312     .set_current_limit = regulator_set_current_limit_regmap,
0313     .get_current_limit = regulator_get_current_limit_regmap,
0314 
0315     .is_enabled = regulator_is_enabled_regmap,
0316     .enable = regulator_enable_regmap,
0317     .disable = regulator_disable_regmap,
0318     .get_status = wm831x_dcdc_get_status,
0319     .get_mode = wm831x_dcdc_get_mode,
0320     .set_mode = wm831x_dcdc_set_mode,
0321     .set_suspend_mode = wm831x_dcdc_set_suspend_mode,
0322 };
0323 
0324 /*
0325  * Set up DVS control.  We just log errors since we can still run
0326  * (with reduced performance) if we fail.
0327  */
0328 static void wm831x_buckv_dvs_init(struct platform_device *pdev,
0329                   struct wm831x_dcdc *dcdc,
0330                   struct wm831x_buckv_pdata *pdata)
0331 {
0332     struct wm831x *wm831x = dcdc->wm831x;
0333     int ret;
0334     u16 ctrl;
0335 
0336     if (!pdata)
0337         return;
0338 
0339     /* gpiolib won't let us read the GPIO status so pick the higher
0340      * of the two existing voltages so we take it as platform data.
0341      */
0342     dcdc->dvs_gpio_state = pdata->dvs_init_state;
0343 
0344     dcdc->dvs_gpiod = devm_gpiod_get(&pdev->dev, "dvs",
0345             dcdc->dvs_gpio_state ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW);
0346     if (IS_ERR(dcdc->dvs_gpiod)) {
0347         dev_err(wm831x->dev, "Failed to get %s DVS GPIO: %ld\n",
0348             dcdc->name, PTR_ERR(dcdc->dvs_gpiod));
0349         return;
0350     }
0351 
0352     switch (pdata->dvs_control_src) {
0353     case 1:
0354         ctrl = 2 << WM831X_DC1_DVS_SRC_SHIFT;
0355         break;
0356     case 2:
0357         ctrl = 3 << WM831X_DC1_DVS_SRC_SHIFT;
0358         break;
0359     default:
0360         dev_err(wm831x->dev, "Invalid DVS control source %d for %s\n",
0361             pdata->dvs_control_src, dcdc->name);
0362         return;
0363     }
0364 
0365     /* If DVS_VSEL is set to the minimum value then raise it to ON_VSEL
0366      * to make bootstrapping a bit smoother.
0367      */
0368     if (!dcdc->dvs_vsel) {
0369         ret = wm831x_set_bits(wm831x,
0370                       dcdc->base + WM831X_DCDC_DVS_CONTROL,
0371                       WM831X_DC1_DVS_VSEL_MASK, dcdc->on_vsel);
0372         if (ret == 0)
0373             dcdc->dvs_vsel = dcdc->on_vsel;
0374         else
0375             dev_warn(wm831x->dev, "Failed to set DVS_VSEL: %d\n",
0376                  ret);
0377     }
0378 
0379     ret = wm831x_set_bits(wm831x, dcdc->base + WM831X_DCDC_DVS_CONTROL,
0380                   WM831X_DC1_DVS_SRC_MASK, ctrl);
0381     if (ret < 0) {
0382         dev_err(wm831x->dev, "Failed to set %s DVS source: %d\n",
0383             dcdc->name, ret);
0384     }
0385 }
0386 
0387 static int wm831x_buckv_probe(struct platform_device *pdev)
0388 {
0389     struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
0390     struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);
0391     struct regulator_config config = { };
0392     int id;
0393     struct wm831x_dcdc *dcdc;
0394     struct resource *res;
0395     int ret, irq;
0396 
0397     if (pdata && pdata->wm831x_num)
0398         id = (pdata->wm831x_num * 10) + 1;
0399     else
0400         id = 0;
0401     id = pdev->id - id;
0402 
0403     dev_dbg(&pdev->dev, "Probing DCDC%d\n", id + 1);
0404 
0405     dcdc = devm_kzalloc(&pdev->dev,  sizeof(struct wm831x_dcdc),
0406                 GFP_KERNEL);
0407     if (!dcdc)
0408         return -ENOMEM;
0409 
0410     dcdc->wm831x = wm831x;
0411 
0412     res = platform_get_resource(pdev, IORESOURCE_REG, 0);
0413     if (res == NULL) {
0414         dev_err(&pdev->dev, "No REG resource\n");
0415         ret = -EINVAL;
0416         goto err;
0417     }
0418     dcdc->base = res->start;
0419 
0420     snprintf(dcdc->name, sizeof(dcdc->name), "DCDC%d", id + 1);
0421     dcdc->desc.name = dcdc->name;
0422 
0423     snprintf(dcdc->supply_name, sizeof(dcdc->supply_name),
0424          "DC%dVDD", id + 1);
0425     dcdc->desc.supply_name = dcdc->supply_name;
0426 
0427     dcdc->desc.id = id;
0428     dcdc->desc.type = REGULATOR_VOLTAGE;
0429     dcdc->desc.n_voltages = WM831X_BUCKV_MAX_SELECTOR + 1;
0430     dcdc->desc.linear_ranges = wm831x_buckv_ranges;
0431     dcdc->desc.n_linear_ranges = ARRAY_SIZE(wm831x_buckv_ranges);
0432     dcdc->desc.ops = &wm831x_buckv_ops;
0433     dcdc->desc.owner = THIS_MODULE;
0434     dcdc->desc.enable_reg = WM831X_DCDC_ENABLE;
0435     dcdc->desc.enable_mask = 1 << id;
0436     dcdc->desc.csel_reg = dcdc->base + WM831X_DCDC_CONTROL_2;
0437     dcdc->desc.csel_mask = WM831X_DC1_HC_THR_MASK;
0438     dcdc->desc.n_current_limits = ARRAY_SIZE(wm831x_dcdc_ilim);
0439     dcdc->desc.curr_table = wm831x_dcdc_ilim;
0440 
0441     ret = wm831x_reg_read(wm831x, dcdc->base + WM831X_DCDC_ON_CONFIG);
0442     if (ret < 0) {
0443         dev_err(wm831x->dev, "Failed to read ON VSEL: %d\n", ret);
0444         goto err;
0445     }
0446     dcdc->on_vsel = ret & WM831X_DC1_ON_VSEL_MASK;
0447 
0448     ret = wm831x_reg_read(wm831x, dcdc->base + WM831X_DCDC_DVS_CONTROL);
0449     if (ret < 0) {
0450         dev_err(wm831x->dev, "Failed to read DVS VSEL: %d\n", ret);
0451         goto err;
0452     }
0453     dcdc->dvs_vsel = ret & WM831X_DC1_DVS_VSEL_MASK;
0454 
0455     if (pdata && pdata->dcdc[id])
0456         wm831x_buckv_dvs_init(pdev, dcdc,
0457                       pdata->dcdc[id]->driver_data);
0458 
0459     config.dev = pdev->dev.parent;
0460     if (pdata)
0461         config.init_data = pdata->dcdc[id];
0462     config.driver_data = dcdc;
0463     config.regmap = wm831x->regmap;
0464 
0465     dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc,
0466                           &config);
0467     if (IS_ERR(dcdc->regulator)) {
0468         ret = PTR_ERR(dcdc->regulator);
0469         dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n",
0470             id + 1, ret);
0471         goto err;
0472     }
0473 
0474     irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
0475     ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
0476                     wm831x_dcdc_uv_irq,
0477                     IRQF_TRIGGER_RISING | IRQF_ONESHOT,
0478                     dcdc->name, dcdc);
0479     if (ret != 0) {
0480         dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
0481             irq, ret);
0482         goto err;
0483     }
0484 
0485     irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "HC"));
0486     ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
0487                     wm831x_dcdc_oc_irq,
0488                     IRQF_TRIGGER_RISING | IRQF_ONESHOT,
0489                     dcdc->name, dcdc);
0490     if (ret != 0) {
0491         dev_err(&pdev->dev, "Failed to request HC IRQ %d: %d\n",
0492             irq, ret);
0493         goto err;
0494     }
0495 
0496     platform_set_drvdata(pdev, dcdc);
0497 
0498     return 0;
0499 
0500 err:
0501     return ret;
0502 }
0503 
0504 static struct platform_driver wm831x_buckv_driver = {
0505     .probe = wm831x_buckv_probe,
0506     .driver     = {
0507         .name   = "wm831x-buckv",
0508     },
0509 };
0510 
0511 /*
0512  * BUCKP specifics
0513  */
0514 
0515 static int wm831x_buckp_set_suspend_voltage(struct regulator_dev *rdev, int uV)
0516 {
0517     struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
0518     struct wm831x *wm831x = dcdc->wm831x;
0519     u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL;
0520     int sel;
0521 
0522     sel = regulator_map_voltage_linear(rdev, uV, uV);
0523     if (sel < 0)
0524         return sel;
0525 
0526     return wm831x_set_bits(wm831x, reg, WM831X_DC3_ON_VSEL_MASK, sel);
0527 }
0528 
0529 static const struct regulator_ops wm831x_buckp_ops = {
0530     .set_voltage_sel = regulator_set_voltage_sel_regmap,
0531     .get_voltage_sel = regulator_get_voltage_sel_regmap,
0532     .list_voltage = regulator_list_voltage_linear,
0533     .map_voltage = regulator_map_voltage_linear,
0534     .set_suspend_voltage = wm831x_buckp_set_suspend_voltage,
0535 
0536     .is_enabled = regulator_is_enabled_regmap,
0537     .enable = regulator_enable_regmap,
0538     .disable = regulator_disable_regmap,
0539     .get_status = wm831x_dcdc_get_status,
0540     .get_mode = wm831x_dcdc_get_mode,
0541     .set_mode = wm831x_dcdc_set_mode,
0542     .set_suspend_mode = wm831x_dcdc_set_suspend_mode,
0543 };
0544 
0545 static int wm831x_buckp_probe(struct platform_device *pdev)
0546 {
0547     struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
0548     struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);
0549     struct regulator_config config = { };
0550     int id;
0551     struct wm831x_dcdc *dcdc;
0552     struct resource *res;
0553     int ret, irq;
0554 
0555     if (pdata && pdata->wm831x_num)
0556         id = (pdata->wm831x_num * 10) + 1;
0557     else
0558         id = 0;
0559     id = pdev->id - id;
0560 
0561     dev_dbg(&pdev->dev, "Probing DCDC%d\n", id + 1);
0562 
0563     dcdc = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_dcdc),
0564                 GFP_KERNEL);
0565     if (!dcdc)
0566         return -ENOMEM;
0567 
0568     dcdc->wm831x = wm831x;
0569 
0570     res = platform_get_resource(pdev, IORESOURCE_REG, 0);
0571     if (res == NULL) {
0572         dev_err(&pdev->dev, "No REG resource\n");
0573         ret = -EINVAL;
0574         goto err;
0575     }
0576     dcdc->base = res->start;
0577 
0578     snprintf(dcdc->name, sizeof(dcdc->name), "DCDC%d", id + 1);
0579     dcdc->desc.name = dcdc->name;
0580 
0581     snprintf(dcdc->supply_name, sizeof(dcdc->supply_name),
0582          "DC%dVDD", id + 1);
0583     dcdc->desc.supply_name = dcdc->supply_name;
0584 
0585     dcdc->desc.id = id;
0586     dcdc->desc.type = REGULATOR_VOLTAGE;
0587     dcdc->desc.n_voltages = WM831X_BUCKP_MAX_SELECTOR + 1;
0588     dcdc->desc.ops = &wm831x_buckp_ops;
0589     dcdc->desc.owner = THIS_MODULE;
0590     dcdc->desc.vsel_reg = dcdc->base + WM831X_DCDC_ON_CONFIG;
0591     dcdc->desc.vsel_mask = WM831X_DC3_ON_VSEL_MASK;
0592     dcdc->desc.enable_reg = WM831X_DCDC_ENABLE;
0593     dcdc->desc.enable_mask = 1 << id;
0594     dcdc->desc.min_uV = 850000;
0595     dcdc->desc.uV_step = 25000;
0596 
0597     config.dev = pdev->dev.parent;
0598     if (pdata)
0599         config.init_data = pdata->dcdc[id];
0600     config.driver_data = dcdc;
0601     config.regmap = wm831x->regmap;
0602 
0603     dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc,
0604                           &config);
0605     if (IS_ERR(dcdc->regulator)) {
0606         ret = PTR_ERR(dcdc->regulator);
0607         dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n",
0608             id + 1, ret);
0609         goto err;
0610     }
0611 
0612     irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
0613     ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
0614                     wm831x_dcdc_uv_irq,
0615                     IRQF_TRIGGER_RISING | IRQF_ONESHOT,
0616                     dcdc->name, dcdc);
0617     if (ret != 0) {
0618         dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
0619             irq, ret);
0620         goto err;
0621     }
0622 
0623     platform_set_drvdata(pdev, dcdc);
0624 
0625     return 0;
0626 
0627 err:
0628     return ret;
0629 }
0630 
0631 static struct platform_driver wm831x_buckp_driver = {
0632     .probe = wm831x_buckp_probe,
0633     .driver     = {
0634         .name   = "wm831x-buckp",
0635     },
0636 };
0637 
0638 /*
0639  * DCDC boost convertors
0640  */
0641 
0642 static int wm831x_boostp_get_status(struct regulator_dev *rdev)
0643 {
0644     struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
0645     struct wm831x *wm831x = dcdc->wm831x;
0646     int ret;
0647 
0648     /* First, check for errors */
0649     ret = wm831x_reg_read(wm831x, WM831X_DCDC_UV_STATUS);
0650     if (ret < 0)
0651         return ret;
0652 
0653     if (ret & (1 << rdev_get_id(rdev))) {
0654         dev_dbg(wm831x->dev, "DCDC%d under voltage\n",
0655             rdev_get_id(rdev) + 1);
0656         return REGULATOR_STATUS_ERROR;
0657     }
0658 
0659     /* Is the regulator on? */
0660     ret = wm831x_reg_read(wm831x, WM831X_DCDC_STATUS);
0661     if (ret < 0)
0662         return ret;
0663     if (ret & (1 << rdev_get_id(rdev)))
0664         return REGULATOR_STATUS_ON;
0665     else
0666         return REGULATOR_STATUS_OFF;
0667 }
0668 
0669 static const struct regulator_ops wm831x_boostp_ops = {
0670     .get_status = wm831x_boostp_get_status,
0671 
0672     .is_enabled = regulator_is_enabled_regmap,
0673     .enable = regulator_enable_regmap,
0674     .disable = regulator_disable_regmap,
0675 };
0676 
0677 static int wm831x_boostp_probe(struct platform_device *pdev)
0678 {
0679     struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
0680     struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);
0681     struct regulator_config config = { };
0682     int id = pdev->id % ARRAY_SIZE(pdata->dcdc);
0683     struct wm831x_dcdc *dcdc;
0684     struct resource *res;
0685     int ret, irq;
0686 
0687     dev_dbg(&pdev->dev, "Probing DCDC%d\n", id + 1);
0688 
0689     if (pdata == NULL || pdata->dcdc[id] == NULL)
0690         return -ENODEV;
0691 
0692     dcdc = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_dcdc), GFP_KERNEL);
0693     if (!dcdc)
0694         return -ENOMEM;
0695 
0696     dcdc->wm831x = wm831x;
0697 
0698     res = platform_get_resource(pdev, IORESOURCE_REG, 0);
0699     if (res == NULL) {
0700         dev_err(&pdev->dev, "No REG resource\n");
0701         return -EINVAL;
0702     }
0703     dcdc->base = res->start;
0704 
0705     snprintf(dcdc->name, sizeof(dcdc->name), "DCDC%d", id + 1);
0706     dcdc->desc.name = dcdc->name;
0707     dcdc->desc.id = id;
0708     dcdc->desc.type = REGULATOR_VOLTAGE;
0709     dcdc->desc.ops = &wm831x_boostp_ops;
0710     dcdc->desc.owner = THIS_MODULE;
0711     dcdc->desc.enable_reg = WM831X_DCDC_ENABLE;
0712     dcdc->desc.enable_mask = 1 << id;
0713 
0714     config.dev = pdev->dev.parent;
0715     if (pdata)
0716         config.init_data = pdata->dcdc[id];
0717     config.driver_data = dcdc;
0718     config.regmap = wm831x->regmap;
0719 
0720     dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc,
0721                           &config);
0722     if (IS_ERR(dcdc->regulator)) {
0723         ret = PTR_ERR(dcdc->regulator);
0724         dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n",
0725             id + 1, ret);
0726         return ret;
0727     }
0728 
0729     irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
0730     ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
0731                     wm831x_dcdc_uv_irq,
0732                     IRQF_TRIGGER_RISING | IRQF_ONESHOT,
0733                     dcdc->name,
0734                     dcdc);
0735     if (ret != 0) {
0736         dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
0737             irq, ret);
0738         return ret;
0739     }
0740 
0741     platform_set_drvdata(pdev, dcdc);
0742 
0743     return 0;
0744 }
0745 
0746 static struct platform_driver wm831x_boostp_driver = {
0747     .probe = wm831x_boostp_probe,
0748     .driver     = {
0749         .name   = "wm831x-boostp",
0750     },
0751 };
0752 
0753 /*
0754  * External Power Enable
0755  *
0756  * These aren't actually DCDCs but look like them in hardware so share
0757  * code.
0758  */
0759 
0760 #define WM831X_EPE_BASE 6
0761 
0762 static const struct regulator_ops wm831x_epe_ops = {
0763     .is_enabled = regulator_is_enabled_regmap,
0764     .enable = regulator_enable_regmap,
0765     .disable = regulator_disable_regmap,
0766     .get_status = wm831x_dcdc_get_status,
0767 };
0768 
0769 static int wm831x_epe_probe(struct platform_device *pdev)
0770 {
0771     struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
0772     struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);
0773     struct regulator_config config = { };
0774     int id = pdev->id % ARRAY_SIZE(pdata->epe);
0775     struct wm831x_dcdc *dcdc;
0776     int ret;
0777 
0778     dev_dbg(&pdev->dev, "Probing EPE%d\n", id + 1);
0779 
0780     dcdc = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_dcdc), GFP_KERNEL);
0781     if (!dcdc)
0782         return -ENOMEM;
0783 
0784     dcdc->wm831x = wm831x;
0785 
0786     /* For current parts this is correct; probably need to revisit
0787      * in future.
0788      */
0789     snprintf(dcdc->name, sizeof(dcdc->name), "EPE%d", id + 1);
0790     dcdc->desc.name = dcdc->name;
0791     dcdc->desc.id = id + WM831X_EPE_BASE; /* Offset in DCDC registers */
0792     dcdc->desc.ops = &wm831x_epe_ops;
0793     dcdc->desc.type = REGULATOR_VOLTAGE;
0794     dcdc->desc.owner = THIS_MODULE;
0795     dcdc->desc.enable_reg = WM831X_DCDC_ENABLE;
0796     dcdc->desc.enable_mask = 1 << dcdc->desc.id;
0797 
0798     config.dev = pdev->dev.parent;
0799     if (pdata)
0800         config.init_data = pdata->epe[id];
0801     config.driver_data = dcdc;
0802     config.regmap = wm831x->regmap;
0803 
0804     dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc,
0805                           &config);
0806     if (IS_ERR(dcdc->regulator)) {
0807         ret = PTR_ERR(dcdc->regulator);
0808         dev_err(wm831x->dev, "Failed to register EPE%d: %d\n",
0809             id + 1, ret);
0810         goto err;
0811     }
0812 
0813     platform_set_drvdata(pdev, dcdc);
0814 
0815     return 0;
0816 
0817 err:
0818     return ret;
0819 }
0820 
0821 static struct platform_driver wm831x_epe_driver = {
0822     .probe = wm831x_epe_probe,
0823     .driver     = {
0824         .name   = "wm831x-epe",
0825     },
0826 };
0827 
0828 static struct platform_driver * const drivers[] = {
0829     &wm831x_buckv_driver,
0830     &wm831x_buckp_driver,
0831     &wm831x_boostp_driver,
0832     &wm831x_epe_driver,
0833 };
0834 
0835 static int __init wm831x_dcdc_init(void)
0836 {
0837     return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
0838 }
0839 subsys_initcall(wm831x_dcdc_init);
0840 
0841 static void __exit wm831x_dcdc_exit(void)
0842 {
0843     platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
0844 }
0845 module_exit(wm831x_dcdc_exit);
0846 
0847 /* Module information */
0848 MODULE_AUTHOR("Mark Brown");
0849 MODULE_DESCRIPTION("WM831x DC-DC convertor driver");
0850 MODULE_LICENSE("GPL");
0851 MODULE_ALIAS("platform:wm831x-buckv");
0852 MODULE_ALIAS("platform:wm831x-buckp");
0853 MODULE_ALIAS("platform:wm831x-boostp");
0854 MODULE_ALIAS("platform:wm831x-epe");