root/drivers/regulator/bd9571mwv-regulator.c

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

DEFINITIONS

This source file includes following definitions.
  1. bd9571mwv_avs_get_moni_state
  2. bd9571mwv_avs_set_voltage_sel_regmap
  3. bd9571mwv_avs_get_voltage_sel_regmap
  4. bd9571mwv_reg_set_voltage_sel_regmap
  5. bd9571mwv_bkup_mode_read
  6. bd9571mwv_bkup_mode_write
  7. backup_mode_show
  8. backup_mode_store
  9. bd9571mwv_suspend
  10. bd9571mwv_resume
  11. bd9571mwv_regulator_remove
  12. bd9571mwv_regulator_probe

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * ROHM BD9571MWV-M regulator driver
   4  *
   5  * Copyright (C) 2017 Marek Vasut <marek.vasut+renesas@gmail.com>
   6  *
   7  * Based on the TPS65086 driver
   8  *
   9  * NOTE: VD09 is missing
  10  */
  11 
  12 #include <linux/module.h>
  13 #include <linux/of.h>
  14 #include <linux/platform_device.h>
  15 #include <linux/regulator/driver.h>
  16 
  17 #include <linux/mfd/bd9571mwv.h>
  18 
  19 struct bd9571mwv_reg {
  20         struct bd9571mwv *bd;
  21 
  22         /* DDR Backup Power */
  23         u8 bkup_mode_cnt_keepon;        /* from "rohm,ddr-backup-power" */
  24         u8 bkup_mode_cnt_saved;
  25         bool bkup_mode_enabled;
  26 
  27         /* Power switch type */
  28         bool rstbmode_level;
  29         bool rstbmode_pulse;
  30 };
  31 
  32 enum bd9571mwv_regulators { VD09, VD18, VD25, VD33, DVFS };
  33 
  34 #define BD9571MWV_REG(_name, _of, _id, _ops, _vr, _vm, _nv, _min, _step, _lmin)\
  35         {                                                       \
  36                 .name                   = _name,                \
  37                 .of_match               = of_match_ptr(_of),    \
  38                 .regulators_node        = "regulators",         \
  39                 .id                     = _id,                  \
  40                 .ops                    = &_ops,                \
  41                 .n_voltages             = _nv,                  \
  42                 .type                   = REGULATOR_VOLTAGE,    \
  43                 .owner                  = THIS_MODULE,          \
  44                 .vsel_reg               = _vr,                  \
  45                 .vsel_mask              = _vm,                  \
  46                 .min_uV                 = _min,                 \
  47                 .uV_step                = _step,                \
  48                 .linear_min_sel         = _lmin,                \
  49         }
  50 
  51 static int bd9571mwv_avs_get_moni_state(struct regulator_dev *rdev)
  52 {
  53         unsigned int val;
  54         int ret;
  55 
  56         ret = regmap_read(rdev->regmap, BD9571MWV_AVS_SET_MONI, &val);
  57         if (ret != 0)
  58                 return ret;
  59 
  60         return val & BD9571MWV_AVS_SET_MONI_MASK;
  61 }
  62 
  63 static int bd9571mwv_avs_set_voltage_sel_regmap(struct regulator_dev *rdev,
  64                                                 unsigned int sel)
  65 {
  66         int ret;
  67 
  68         ret = bd9571mwv_avs_get_moni_state(rdev);
  69         if (ret < 0)
  70                 return ret;
  71 
  72         return regmap_write_bits(rdev->regmap, BD9571MWV_AVS_VD09_VID(ret),
  73                                  rdev->desc->vsel_mask, sel);
  74 }
  75 
  76 static int bd9571mwv_avs_get_voltage_sel_regmap(struct regulator_dev *rdev)
  77 {
  78         unsigned int val;
  79         int ret;
  80 
  81         ret = bd9571mwv_avs_get_moni_state(rdev);
  82         if (ret < 0)
  83                 return ret;
  84 
  85         ret = regmap_read(rdev->regmap, BD9571MWV_AVS_VD09_VID(ret), &val);
  86         if (ret != 0)
  87                 return ret;
  88 
  89         val &= rdev->desc->vsel_mask;
  90         val >>= ffs(rdev->desc->vsel_mask) - 1;
  91 
  92         return val;
  93 }
  94 
  95 static int bd9571mwv_reg_set_voltage_sel_regmap(struct regulator_dev *rdev,
  96                                                 unsigned int sel)
  97 {
  98         return regmap_write_bits(rdev->regmap, BD9571MWV_DVFS_SETVID,
  99                                  rdev->desc->vsel_mask, sel);
 100 }
 101 
 102 /* Operations permitted on AVS voltage regulator */
 103 static const struct regulator_ops avs_ops = {
 104         .set_voltage_sel        = bd9571mwv_avs_set_voltage_sel_regmap,
 105         .map_voltage            = regulator_map_voltage_linear,
 106         .get_voltage_sel        = bd9571mwv_avs_get_voltage_sel_regmap,
 107         .list_voltage           = regulator_list_voltage_linear,
 108 };
 109 
 110 /* Operations permitted on voltage regulators */
 111 static const struct regulator_ops reg_ops = {
 112         .set_voltage_sel        = bd9571mwv_reg_set_voltage_sel_regmap,
 113         .map_voltage            = regulator_map_voltage_linear,
 114         .get_voltage_sel        = regulator_get_voltage_sel_regmap,
 115         .list_voltage           = regulator_list_voltage_linear,
 116 };
 117 
 118 /* Operations permitted on voltage monitors */
 119 static const struct regulator_ops vid_ops = {
 120         .map_voltage            = regulator_map_voltage_linear,
 121         .get_voltage_sel        = regulator_get_voltage_sel_regmap,
 122         .list_voltage           = regulator_list_voltage_linear,
 123 };
 124 
 125 static const struct regulator_desc regulators[] = {
 126         BD9571MWV_REG("VD09", "vd09", VD09, avs_ops, 0, 0x7f,
 127                       0x80, 600000, 10000, 0x3c),
 128         BD9571MWV_REG("VD18", "vd18", VD18, vid_ops, BD9571MWV_VD18_VID, 0xf,
 129                       16, 1625000, 25000, 0),
 130         BD9571MWV_REG("VD25", "vd25", VD25, vid_ops, BD9571MWV_VD25_VID, 0xf,
 131                       16, 2150000, 50000, 0),
 132         BD9571MWV_REG("VD33", "vd33", VD33, vid_ops, BD9571MWV_VD33_VID, 0xf,
 133                       11, 2800000, 100000, 0),
 134         BD9571MWV_REG("DVFS", "dvfs", DVFS, reg_ops,
 135                       BD9571MWV_DVFS_MONIVDAC, 0x7f,
 136                       0x80, 600000, 10000, 0x3c),
 137 };
 138 
 139 #ifdef CONFIG_PM_SLEEP
 140 static int bd9571mwv_bkup_mode_read(struct bd9571mwv *bd, unsigned int *mode)
 141 {
 142         int ret;
 143 
 144         ret = regmap_read(bd->regmap, BD9571MWV_BKUP_MODE_CNT, mode);
 145         if (ret) {
 146                 dev_err(bd->dev, "failed to read backup mode (%d)\n", ret);
 147                 return ret;
 148         }
 149 
 150         return 0;
 151 }
 152 
 153 static int bd9571mwv_bkup_mode_write(struct bd9571mwv *bd, unsigned int mode)
 154 {
 155         int ret;
 156 
 157         ret = regmap_write(bd->regmap, BD9571MWV_BKUP_MODE_CNT, mode);
 158         if (ret) {
 159                 dev_err(bd->dev, "failed to configure backup mode 0x%x (%d)\n",
 160                         mode, ret);
 161                 return ret;
 162         }
 163 
 164         return 0;
 165 }
 166 
 167 static ssize_t backup_mode_show(struct device *dev,
 168                                 struct device_attribute *attr, char *buf)
 169 {
 170         struct bd9571mwv_reg *bdreg = dev_get_drvdata(dev);
 171 
 172         return sprintf(buf, "%s\n", bdreg->bkup_mode_enabled ? "on" : "off");
 173 }
 174 
 175 static ssize_t backup_mode_store(struct device *dev,
 176                                  struct device_attribute *attr,
 177                                  const char *buf, size_t count)
 178 {
 179         struct bd9571mwv_reg *bdreg = dev_get_drvdata(dev);
 180         unsigned int mode;
 181         int ret;
 182 
 183         if (!count)
 184                 return 0;
 185 
 186         ret = kstrtobool(buf, &bdreg->bkup_mode_enabled);
 187         if (ret)
 188                 return ret;
 189 
 190         if (!bdreg->rstbmode_level)
 191                 return count;
 192 
 193         /*
 194          * Configure DDR Backup Mode, to change the role of the accessory power
 195          * switch from a power switch to a wake-up switch, or vice versa
 196          */
 197         ret = bd9571mwv_bkup_mode_read(bdreg->bd, &mode);
 198         if (ret)
 199                 return ret;
 200 
 201         mode &= ~BD9571MWV_BKUP_MODE_CNT_KEEPON_MASK;
 202         if (bdreg->bkup_mode_enabled)
 203                 mode |= bdreg->bkup_mode_cnt_keepon;
 204 
 205         ret = bd9571mwv_bkup_mode_write(bdreg->bd, mode);
 206         if (ret)
 207                 return ret;
 208 
 209         return count;
 210 }
 211 
 212 static DEVICE_ATTR_RW(backup_mode);
 213 
 214 static int bd9571mwv_suspend(struct device *dev)
 215 {
 216         struct bd9571mwv_reg *bdreg = dev_get_drvdata(dev);
 217         unsigned int mode;
 218         int ret;
 219 
 220         if (!bdreg->bkup_mode_enabled)
 221                 return 0;
 222 
 223         /* Save DDR Backup Mode */
 224         ret = bd9571mwv_bkup_mode_read(bdreg->bd, &mode);
 225         if (ret)
 226                 return ret;
 227 
 228         bdreg->bkup_mode_cnt_saved = mode;
 229 
 230         if (!bdreg->rstbmode_pulse)
 231                 return 0;
 232 
 233         /* Enable DDR Backup Mode */
 234         mode &= ~BD9571MWV_BKUP_MODE_CNT_KEEPON_MASK;
 235         mode |= bdreg->bkup_mode_cnt_keepon;
 236 
 237         if (mode != bdreg->bkup_mode_cnt_saved)
 238                 return bd9571mwv_bkup_mode_write(bdreg->bd, mode);
 239 
 240         return 0;
 241 }
 242 
 243 static int bd9571mwv_resume(struct device *dev)
 244 {
 245         struct bd9571mwv_reg *bdreg = dev_get_drvdata(dev);
 246 
 247         if (!bdreg->bkup_mode_enabled)
 248                 return 0;
 249 
 250         /* Restore DDR Backup Mode */
 251         return bd9571mwv_bkup_mode_write(bdreg->bd, bdreg->bkup_mode_cnt_saved);
 252 }
 253 
 254 static const struct dev_pm_ops bd9571mwv_pm  = {
 255         SET_SYSTEM_SLEEP_PM_OPS(bd9571mwv_suspend, bd9571mwv_resume)
 256 };
 257 
 258 static int bd9571mwv_regulator_remove(struct platform_device *pdev)
 259 {
 260         device_remove_file(&pdev->dev, &dev_attr_backup_mode);
 261         return 0;
 262 }
 263 #define DEV_PM_OPS      &bd9571mwv_pm
 264 #else
 265 #define DEV_PM_OPS      NULL
 266 #define bd9571mwv_regulator_remove      NULL
 267 #endif /* CONFIG_PM_SLEEP */
 268 
 269 static int bd9571mwv_regulator_probe(struct platform_device *pdev)
 270 {
 271         struct bd9571mwv *bd = dev_get_drvdata(pdev->dev.parent);
 272         struct regulator_config config = { };
 273         struct bd9571mwv_reg *bdreg;
 274         struct regulator_dev *rdev;
 275         unsigned int val;
 276         int i;
 277 
 278         bdreg = devm_kzalloc(&pdev->dev, sizeof(*bdreg), GFP_KERNEL);
 279         if (!bdreg)
 280                 return -ENOMEM;
 281 
 282         bdreg->bd = bd;
 283 
 284         platform_set_drvdata(pdev, bdreg);
 285 
 286         config.dev = &pdev->dev;
 287         config.dev->of_node = bd->dev->of_node;
 288         config.driver_data = bd;
 289         config.regmap = bd->regmap;
 290 
 291         for (i = 0; i < ARRAY_SIZE(regulators); i++) {
 292                 rdev = devm_regulator_register(&pdev->dev, &regulators[i],
 293                                                &config);
 294                 if (IS_ERR(rdev)) {
 295                         dev_err(bd->dev, "failed to register %s regulator\n",
 296                                 pdev->name);
 297                         return PTR_ERR(rdev);
 298                 }
 299         }
 300 
 301         val = 0;
 302         of_property_read_u32(bd->dev->of_node, "rohm,ddr-backup-power", &val);
 303         if (val & ~BD9571MWV_BKUP_MODE_CNT_KEEPON_MASK) {
 304                 dev_err(bd->dev, "invalid %s mode %u\n",
 305                         "rohm,ddr-backup-power", val);
 306                 return -EINVAL;
 307         }
 308         bdreg->bkup_mode_cnt_keepon = val;
 309 
 310         bdreg->rstbmode_level = of_property_read_bool(bd->dev->of_node,
 311                                                       "rohm,rstbmode-level");
 312         bdreg->rstbmode_pulse = of_property_read_bool(bd->dev->of_node,
 313                                                       "rohm,rstbmode-pulse");
 314         if (bdreg->rstbmode_level && bdreg->rstbmode_pulse) {
 315                 dev_err(bd->dev, "only one rohm,rstbmode-* may be specified");
 316                 return -EINVAL;
 317         }
 318 
 319 #ifdef CONFIG_PM_SLEEP
 320         if (bdreg->bkup_mode_cnt_keepon) {
 321                 int ret;
 322 
 323                 /*
 324                  * Backup mode is enabled by default in pulse mode, but needs
 325                  * explicit user setup in level mode.
 326                  */
 327                 bdreg->bkup_mode_enabled = bdreg->rstbmode_pulse;
 328 
 329                 ret = device_create_file(&pdev->dev, &dev_attr_backup_mode);
 330                 if (ret)
 331                         return ret;
 332         }
 333 #endif /* CONFIG_PM_SLEEP */
 334 
 335         return 0;
 336 }
 337 
 338 static const struct platform_device_id bd9571mwv_regulator_id_table[] = {
 339         { "bd9571mwv-regulator", },
 340         { /* sentinel */ }
 341 };
 342 MODULE_DEVICE_TABLE(platform, bd9571mwv_regulator_id_table);
 343 
 344 static struct platform_driver bd9571mwv_regulator_driver = {
 345         .driver = {
 346                 .name = "bd9571mwv-regulator",
 347                 .pm = DEV_PM_OPS,
 348         },
 349         .probe = bd9571mwv_regulator_probe,
 350         .remove = bd9571mwv_regulator_remove,
 351         .id_table = bd9571mwv_regulator_id_table,
 352 };
 353 module_platform_driver(bd9571mwv_regulator_driver);
 354 
 355 MODULE_AUTHOR("Marek Vasut <marek.vasut+renesas@gmail.com>");
 356 MODULE_DESCRIPTION("BD9571MWV Regulator driver");
 357 MODULE_LICENSE("GPL v2");

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