root/drivers/regulator/wm8400-regulator.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wm8400_dcdc_get_mode
  2. wm8400_dcdc_set_mode
  3. wm8400_dcdc_get_optimum_mode
  4. wm8400_regulator_probe
  5. wm8400_register_regulator
  6. wm8400_regulator_init
  7. wm8400_regulator_exit

   1 // SPDX-License-Identifier: GPL-2.0+
   2 //
   3 // Regulator support for WM8400
   4 //
   5 // Copyright 2008 Wolfson Microelectronics PLC.
   6 //
   7 // Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
   8 
   9 #include <linux/bug.h>
  10 #include <linux/err.h>
  11 #include <linux/kernel.h>
  12 #include <linux/module.h>
  13 #include <linux/regulator/driver.h>
  14 #include <linux/mfd/wm8400-private.h>
  15 
  16 static const struct regulator_linear_range wm8400_ldo_ranges[] = {
  17         REGULATOR_LINEAR_RANGE(900000, 0, 14, 50000),
  18         REGULATOR_LINEAR_RANGE(1700000, 15, 31, 100000),
  19 };
  20 
  21 static const struct regulator_ops wm8400_ldo_ops = {
  22         .is_enabled = regulator_is_enabled_regmap,
  23         .enable = regulator_enable_regmap,
  24         .disable = regulator_disable_regmap,
  25         .list_voltage = regulator_list_voltage_linear_range,
  26         .get_voltage_sel = regulator_get_voltage_sel_regmap,
  27         .set_voltage_sel = regulator_set_voltage_sel_regmap,
  28         .map_voltage = regulator_map_voltage_linear_range,
  29 };
  30 
  31 static unsigned int wm8400_dcdc_get_mode(struct regulator_dev *dev)
  32 {
  33         struct regmap *rmap = rdev_get_regmap(dev);
  34         int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
  35         u16 data[2];
  36         int ret;
  37 
  38         ret = regmap_bulk_read(rmap, WM8400_DCDC1_CONTROL_1 + offset, data, 2);
  39         if (ret != 0)
  40                 return 0;
  41 
  42         /* Datasheet: hibernate */
  43         if (data[0] & WM8400_DC1_SLEEP)
  44                 return REGULATOR_MODE_STANDBY;
  45 
  46         /* Datasheet: standby */
  47         if (!(data[0] & WM8400_DC1_ACTIVE))
  48                 return REGULATOR_MODE_IDLE;
  49 
  50         /* Datasheet: active with or without force PWM */
  51         if (data[1] & WM8400_DC1_FRC_PWM)
  52                 return REGULATOR_MODE_FAST;
  53         else
  54                 return REGULATOR_MODE_NORMAL;
  55 }
  56 
  57 static int wm8400_dcdc_set_mode(struct regulator_dev *dev, unsigned int mode)
  58 {
  59         struct regmap *rmap = rdev_get_regmap(dev);
  60         int offset = (rdev_get_id(dev) - WM8400_DCDC1) * 2;
  61         int ret;
  62 
  63         switch (mode) {
  64         case REGULATOR_MODE_FAST:
  65                 /* Datasheet: active with force PWM */
  66                 ret = regmap_update_bits(rmap, WM8400_DCDC1_CONTROL_2 + offset,
  67                                       WM8400_DC1_FRC_PWM, WM8400_DC1_FRC_PWM);
  68                 if (ret != 0)
  69                         return ret;
  70 
  71                 return regmap_update_bits(rmap, WM8400_DCDC1_CONTROL_1 + offset,
  72                                        WM8400_DC1_ACTIVE | WM8400_DC1_SLEEP,
  73                                        WM8400_DC1_ACTIVE);
  74 
  75         case REGULATOR_MODE_NORMAL:
  76                 /* Datasheet: active */
  77                 ret = regmap_update_bits(rmap, WM8400_DCDC1_CONTROL_2 + offset,
  78                                       WM8400_DC1_FRC_PWM, 0);
  79                 if (ret != 0)
  80                         return ret;
  81 
  82                 return regmap_update_bits(rmap, WM8400_DCDC1_CONTROL_1 + offset,
  83                                        WM8400_DC1_ACTIVE | WM8400_DC1_SLEEP,
  84                                        WM8400_DC1_ACTIVE);
  85 
  86         case REGULATOR_MODE_IDLE:
  87                 /* Datasheet: standby */
  88                 return regmap_update_bits(rmap, WM8400_DCDC1_CONTROL_1 + offset,
  89                                        WM8400_DC1_ACTIVE | WM8400_DC1_SLEEP, 0);
  90         default:
  91                 return -EINVAL;
  92         }
  93 }
  94 
  95 static unsigned int wm8400_dcdc_get_optimum_mode(struct regulator_dev *dev,
  96                                                  int input_uV, int output_uV,
  97                                                  int load_uA)
  98 {
  99         return REGULATOR_MODE_NORMAL;
 100 }
 101 
 102 static const struct regulator_ops wm8400_dcdc_ops = {
 103         .is_enabled = regulator_is_enabled_regmap,
 104         .enable = regulator_enable_regmap,
 105         .disable = regulator_disable_regmap,
 106         .list_voltage = regulator_list_voltage_linear,
 107         .map_voltage = regulator_map_voltage_linear,
 108         .get_voltage_sel = regulator_get_voltage_sel_regmap,
 109         .set_voltage_sel = regulator_set_voltage_sel_regmap,
 110         .get_mode = wm8400_dcdc_get_mode,
 111         .set_mode = wm8400_dcdc_set_mode,
 112         .get_optimum_mode = wm8400_dcdc_get_optimum_mode,
 113 };
 114 
 115 static struct regulator_desc regulators[] = {
 116         {
 117                 .name = "LDO1",
 118                 .id = WM8400_LDO1,
 119                 .ops = &wm8400_ldo_ops,
 120                 .enable_reg = WM8400_LDO1_CONTROL,
 121                 .enable_mask = WM8400_LDO1_ENA,
 122                 .n_voltages = WM8400_LDO1_VSEL_MASK + 1,
 123                 .linear_ranges = wm8400_ldo_ranges,
 124                 .n_linear_ranges = ARRAY_SIZE(wm8400_ldo_ranges),
 125                 .vsel_reg = WM8400_LDO1_CONTROL,
 126                 .vsel_mask = WM8400_LDO1_VSEL_MASK,
 127                 .type = REGULATOR_VOLTAGE,
 128                 .owner = THIS_MODULE,
 129         },
 130         {
 131                 .name = "LDO2",
 132                 .id = WM8400_LDO2,
 133                 .ops = &wm8400_ldo_ops,
 134                 .enable_reg = WM8400_LDO2_CONTROL,
 135                 .enable_mask = WM8400_LDO2_ENA,
 136                 .n_voltages = WM8400_LDO2_VSEL_MASK + 1,
 137                 .linear_ranges = wm8400_ldo_ranges,
 138                 .n_linear_ranges = ARRAY_SIZE(wm8400_ldo_ranges),
 139                 .type = REGULATOR_VOLTAGE,
 140                 .vsel_reg = WM8400_LDO2_CONTROL,
 141                 .vsel_mask = WM8400_LDO2_VSEL_MASK,
 142                 .owner = THIS_MODULE,
 143         },
 144         {
 145                 .name = "LDO3",
 146                 .id = WM8400_LDO3,
 147                 .ops = &wm8400_ldo_ops,
 148                 .enable_reg = WM8400_LDO3_CONTROL,
 149                 .enable_mask = WM8400_LDO3_ENA,
 150                 .n_voltages = WM8400_LDO3_VSEL_MASK + 1,
 151                 .linear_ranges = wm8400_ldo_ranges,
 152                 .n_linear_ranges = ARRAY_SIZE(wm8400_ldo_ranges),
 153                 .vsel_reg = WM8400_LDO3_CONTROL,
 154                 .vsel_mask = WM8400_LDO3_VSEL_MASK,
 155                 .type = REGULATOR_VOLTAGE,
 156                 .owner = THIS_MODULE,
 157         },
 158         {
 159                 .name = "LDO4",
 160                 .id = WM8400_LDO4,
 161                 .ops = &wm8400_ldo_ops,
 162                 .enable_reg = WM8400_LDO4_CONTROL,
 163                 .enable_mask = WM8400_LDO4_ENA,
 164                 .n_voltages = WM8400_LDO4_VSEL_MASK + 1,
 165                 .linear_ranges = wm8400_ldo_ranges,
 166                 .n_linear_ranges = ARRAY_SIZE(wm8400_ldo_ranges),
 167                 .vsel_reg = WM8400_LDO4_CONTROL,
 168                 .vsel_mask = WM8400_LDO4_VSEL_MASK,
 169                 .type = REGULATOR_VOLTAGE,
 170                 .owner = THIS_MODULE,
 171         },
 172         {
 173                 .name = "DCDC1",
 174                 .id = WM8400_DCDC1,
 175                 .ops = &wm8400_dcdc_ops,
 176                 .enable_reg = WM8400_DCDC1_CONTROL_1,
 177                 .enable_mask = WM8400_DC1_ENA_MASK,
 178                 .n_voltages = WM8400_DC1_VSEL_MASK + 1,
 179                 .vsel_reg = WM8400_DCDC1_CONTROL_1,
 180                 .vsel_mask = WM8400_DC1_VSEL_MASK,
 181                 .min_uV = 850000,
 182                 .uV_step = 25000,
 183                 .type = REGULATOR_VOLTAGE,
 184                 .owner = THIS_MODULE,
 185         },
 186         {
 187                 .name = "DCDC2",
 188                 .id = WM8400_DCDC2,
 189                 .ops = &wm8400_dcdc_ops,
 190                 .enable_reg = WM8400_DCDC2_CONTROL_1,
 191                 .enable_mask = WM8400_DC2_ENA_MASK,
 192                 .n_voltages = WM8400_DC2_VSEL_MASK + 1,
 193                 .vsel_reg = WM8400_DCDC2_CONTROL_1,
 194                 .vsel_mask = WM8400_DC2_VSEL_MASK,
 195                 .min_uV = 850000,
 196                 .uV_step = 25000,
 197                 .type = REGULATOR_VOLTAGE,
 198                 .owner = THIS_MODULE,
 199         },
 200 };
 201 
 202 static int wm8400_regulator_probe(struct platform_device *pdev)
 203 {
 204         struct wm8400 *wm8400 = container_of(pdev, struct wm8400, regulators[pdev->id]);
 205         struct regulator_config config = { };
 206         struct regulator_dev *rdev;
 207 
 208         config.dev = &pdev->dev;
 209         config.init_data = dev_get_platdata(&pdev->dev);
 210         config.driver_data = wm8400;
 211         config.regmap = wm8400->regmap;
 212 
 213         rdev = devm_regulator_register(&pdev->dev, &regulators[pdev->id],
 214                                        &config);
 215         if (IS_ERR(rdev))
 216                 return PTR_ERR(rdev);
 217 
 218         platform_set_drvdata(pdev, rdev);
 219 
 220         return 0;
 221 }
 222 
 223 static struct platform_driver wm8400_regulator_driver = {
 224         .driver = {
 225                 .name = "wm8400-regulator",
 226         },
 227         .probe = wm8400_regulator_probe,
 228 };
 229 
 230 /**
 231  * wm8400_register_regulator - enable software control of a WM8400 regulator
 232  *
 233  * This function enables software control of a WM8400 regulator via
 234  * the regulator API.  It is intended to be called from the
 235  * platform_init() callback of the WM8400 MFD driver.
 236  *
 237  * @param dev      The WM8400 device to operate on.
 238  * @param reg      The regulator to control.
 239  * @param initdata Regulator initdata for the regulator.
 240  */
 241 int wm8400_register_regulator(struct device *dev, int reg,
 242                               struct regulator_init_data *initdata)
 243 {
 244         struct wm8400 *wm8400 = dev_get_drvdata(dev);
 245 
 246         if (wm8400->regulators[reg].name)
 247                 return -EBUSY;
 248 
 249         initdata->driver_data = wm8400;
 250 
 251         wm8400->regulators[reg].name = "wm8400-regulator";
 252         wm8400->regulators[reg].id = reg;
 253         wm8400->regulators[reg].dev.parent = dev;
 254         wm8400->regulators[reg].dev.platform_data = initdata;
 255 
 256         return platform_device_register(&wm8400->regulators[reg]);
 257 }
 258 EXPORT_SYMBOL_GPL(wm8400_register_regulator);
 259 
 260 static int __init wm8400_regulator_init(void)
 261 {
 262         return platform_driver_register(&wm8400_regulator_driver);
 263 }
 264 subsys_initcall(wm8400_regulator_init);
 265 
 266 static void __exit wm8400_regulator_exit(void)
 267 {
 268         platform_driver_unregister(&wm8400_regulator_driver);
 269 }
 270 module_exit(wm8400_regulator_exit);
 271 
 272 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
 273 MODULE_DESCRIPTION("WM8400 regulator driver");
 274 MODULE_LICENSE("GPL");
 275 MODULE_ALIAS("platform:wm8400-regulator");

/* [<][>][^][v][top][bottom][index][help] */