linux/drivers/regulator/bd9571mwv-regulator.c
<<
>>
Prefs
   1/*
   2 * ROHM BD9571MWV-M regulator driver
   3 *
   4 * Copyright (C) 2017 Marek Vasut <marek.vasut+renesas@gmail.com>
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 *
  10 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
  11 * kind, whether expressed or implied; without even the implied warranty
  12 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License version 2 for more details.
  14 *
  15 * Based on the TPS65086 driver
  16 *
  17 * NOTE: VD09 is missing
  18 */
  19
  20#include <linux/module.h>
  21#include <linux/of.h>
  22#include <linux/platform_device.h>
  23#include <linux/regulator/driver.h>
  24
  25#include <linux/mfd/bd9571mwv.h>
  26
  27enum bd9571mwv_regulators { VD09, VD18, VD25, VD33, DVFS };
  28
  29#define BD9571MWV_REG(_name, _of, _id, _ops, _vr, _vm, _nv, _min, _step, _lmin)\
  30        {                                                       \
  31                .name                   = _name,                \
  32                .of_match               = of_match_ptr(_of),    \
  33                .regulators_node        = "regulators",         \
  34                .id                     = _id,                  \
  35                .ops                    = &_ops,                \
  36                .n_voltages             = _nv,                  \
  37                .type                   = REGULATOR_VOLTAGE,    \
  38                .owner                  = THIS_MODULE,          \
  39                .vsel_reg               = _vr,                  \
  40                .vsel_mask              = _vm,                  \
  41                .min_uV                 = _min,                 \
  42                .uV_step                = _step,                \
  43                .linear_min_sel         = _lmin,                \
  44        }
  45
  46static int bd9571mwv_avs_get_moni_state(struct regulator_dev *rdev)
  47{
  48        unsigned int val;
  49        int ret;
  50
  51        ret = regmap_read(rdev->regmap, BD9571MWV_AVS_SET_MONI, &val);
  52        if (ret != 0)
  53                return ret;
  54
  55        return val & BD9571MWV_AVS_SET_MONI_MASK;
  56}
  57
  58static int bd9571mwv_avs_set_voltage_sel_regmap(struct regulator_dev *rdev,
  59                                                unsigned int sel)
  60{
  61        int ret;
  62
  63        ret = bd9571mwv_avs_get_moni_state(rdev);
  64        if (ret < 0)
  65                return ret;
  66
  67        return regmap_write_bits(rdev->regmap, BD9571MWV_AVS_VD09_VID(ret),
  68                                 rdev->desc->vsel_mask, sel);
  69}
  70
  71static int bd9571mwv_avs_get_voltage_sel_regmap(struct regulator_dev *rdev)
  72{
  73        unsigned int val;
  74        int ret;
  75
  76        ret = bd9571mwv_avs_get_moni_state(rdev);
  77        if (ret < 0)
  78                return ret;
  79
  80        ret = regmap_read(rdev->regmap, BD9571MWV_AVS_VD09_VID(ret), &val);
  81        if (ret != 0)
  82                return ret;
  83
  84        val &= rdev->desc->vsel_mask;
  85        val >>= ffs(rdev->desc->vsel_mask) - 1;
  86
  87        return val;
  88}
  89
  90static int bd9571mwv_reg_set_voltage_sel_regmap(struct regulator_dev *rdev,
  91                                                unsigned int sel)
  92{
  93        return regmap_write_bits(rdev->regmap, BD9571MWV_DVFS_SETVID,
  94                                 rdev->desc->vsel_mask, sel);
  95}
  96
  97/* Operations permitted on AVS voltage regulator */
  98static struct regulator_ops avs_ops = {
  99        .set_voltage_sel        = bd9571mwv_avs_set_voltage_sel_regmap,
 100        .map_voltage            = regulator_map_voltage_linear,
 101        .get_voltage_sel        = bd9571mwv_avs_get_voltage_sel_regmap,
 102        .list_voltage           = regulator_list_voltage_linear,
 103};
 104
 105/* Operations permitted on voltage regulators */
 106static struct regulator_ops reg_ops = {
 107        .set_voltage_sel        = bd9571mwv_reg_set_voltage_sel_regmap,
 108        .map_voltage            = regulator_map_voltage_linear,
 109        .get_voltage_sel        = regulator_get_voltage_sel_regmap,
 110        .list_voltage           = regulator_list_voltage_linear,
 111};
 112
 113/* Operations permitted on voltage monitors */
 114static struct regulator_ops vid_ops = {
 115        .map_voltage            = regulator_map_voltage_linear,
 116        .get_voltage_sel        = regulator_get_voltage_sel_regmap,
 117        .list_voltage           = regulator_list_voltage_linear,
 118};
 119
 120static struct regulator_desc regulators[] = {
 121        BD9571MWV_REG("VD09", "vd09", VD09, avs_ops, 0, 0x7f,
 122                      0x80, 600000, 10000, 0x3c),
 123        BD9571MWV_REG("VD18", "vd18", VD18, vid_ops, BD9571MWV_VD18_VID, 0xf,
 124                      16, 1625000, 25000, 0),
 125        BD9571MWV_REG("VD25", "vd25", VD25, vid_ops, BD9571MWV_VD25_VID, 0xf,
 126                      16, 2150000, 50000, 0),
 127        BD9571MWV_REG("VD33", "vd33", VD33, vid_ops, BD9571MWV_VD33_VID, 0xf,
 128                      11, 2800000, 100000, 0),
 129        BD9571MWV_REG("DVFS", "dvfs", DVFS, reg_ops,
 130                      BD9571MWV_DVFS_MONIVDAC, 0x7f,
 131                      0x80, 600000, 10000, 0x3c),
 132};
 133
 134static int bd9571mwv_regulator_probe(struct platform_device *pdev)
 135{
 136        struct bd9571mwv *bd = dev_get_drvdata(pdev->dev.parent);
 137        struct regulator_config config = { };
 138        struct regulator_dev *rdev;
 139        int i;
 140
 141        platform_set_drvdata(pdev, bd);
 142
 143        config.dev = &pdev->dev;
 144        config.dev->of_node = bd->dev->of_node;
 145        config.driver_data = bd;
 146        config.regmap = bd->regmap;
 147
 148        for (i = 0; i < ARRAY_SIZE(regulators); i++) {
 149                rdev = devm_regulator_register(&pdev->dev, &regulators[i],
 150                                               &config);
 151                if (IS_ERR(rdev)) {
 152                        dev_err(bd->dev, "failed to register %s regulator\n",
 153                                pdev->name);
 154                        return PTR_ERR(rdev);
 155                }
 156        }
 157
 158        return 0;
 159}
 160
 161static const struct platform_device_id bd9571mwv_regulator_id_table[] = {
 162        { "bd9571mwv-regulator", },
 163        { /* sentinel */ }
 164};
 165MODULE_DEVICE_TABLE(platform, bd9571mwv_regulator_id_table);
 166
 167static struct platform_driver bd9571mwv_regulator_driver = {
 168        .driver = {
 169                .name = "bd9571mwv-regulator",
 170        },
 171        .probe = bd9571mwv_regulator_probe,
 172        .id_table = bd9571mwv_regulator_id_table,
 173};
 174module_platform_driver(bd9571mwv_regulator_driver);
 175
 176MODULE_AUTHOR("Marek Vasut <marek.vasut+renesas@gmail.com>");
 177MODULE_DESCRIPTION("BD9571MWV Regulator driver");
 178MODULE_LICENSE("GPL v2");
 179