linux/drivers/regulator/bd70528-regulator.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2// Copyright (C) 2018 ROHM Semiconductors
   3// bd70528-regulator.c ROHM BD70528MWV regulator driver
   4
   5#include <linux/delay.h>
   6#include <linux/err.h>
   7#include <linux/interrupt.h>
   8#include <linux/kernel.h>
   9#include <linux/mfd/rohm-bd70528.h>
  10#include <linux/module.h>
  11#include <linux/of.h>
  12#include <linux/platform_device.h>
  13#include <linux/regmap.h>
  14#include <linux/regulator/driver.h>
  15#include <linux/regulator/machine.h>
  16#include <linux/regulator/of_regulator.h>
  17#include <linux/slab.h>
  18
  19#define BUCK_RAMPRATE_250MV 0
  20#define BUCK_RAMPRATE_125MV 1
  21#define BUCK_RAMP_MAX 250
  22
  23static const struct regulator_linear_range bd70528_buck1_volts[] = {
  24        REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x1, 600000),
  25        REGULATOR_LINEAR_RANGE(2750000, 0x2, 0xf, 50000),
  26};
  27static const struct regulator_linear_range bd70528_buck2_volts[] = {
  28        REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x1, 300000),
  29        REGULATOR_LINEAR_RANGE(1550000, 0x2, 0xd, 50000),
  30        REGULATOR_LINEAR_RANGE(3000000, 0xe, 0xf, 300000),
  31};
  32static const struct regulator_linear_range bd70528_buck3_volts[] = {
  33        REGULATOR_LINEAR_RANGE(800000, 0x00, 0xd, 50000),
  34        REGULATOR_LINEAR_RANGE(1800000, 0xe, 0xf, 0),
  35};
  36
  37/* All LDOs have same voltage ranges */
  38static const struct regulator_linear_range bd70528_ldo_volts[] = {
  39        REGULATOR_LINEAR_RANGE(1650000, 0x0, 0x07, 50000),
  40        REGULATOR_LINEAR_RANGE(2100000, 0x8, 0x0f, 100000),
  41        REGULATOR_LINEAR_RANGE(2850000, 0x10, 0x19, 50000),
  42        REGULATOR_LINEAR_RANGE(3300000, 0x19, 0x1f, 0),
  43};
  44
  45/* Also both LEDs support same voltages */
  46static const unsigned int led_volts[] = {
  47        20000, 30000
  48};
  49
  50static int bd70528_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
  51{
  52        if (ramp_delay > 0 && ramp_delay <= BUCK_RAMP_MAX) {
  53                unsigned int ramp_value = BUCK_RAMPRATE_250MV;
  54
  55                if (ramp_delay <= 125)
  56                        ramp_value = BUCK_RAMPRATE_125MV;
  57
  58                return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg,
  59                                  BD70528_MASK_BUCK_RAMP,
  60                                  ramp_value << BD70528_SIFT_BUCK_RAMP);
  61        }
  62        dev_err(&rdev->dev, "%s: ramp_delay: %d not supported\n",
  63                rdev->desc->name, ramp_delay);
  64        return -EINVAL;
  65}
  66
  67static int bd70528_led_set_voltage_sel(struct regulator_dev *rdev,
  68                                       unsigned int sel)
  69{
  70        int ret;
  71
  72        ret = regulator_is_enabled_regmap(rdev);
  73        if (ret < 0)
  74                return ret;
  75
  76        if (ret == 0)
  77                return regulator_set_voltage_sel_regmap(rdev, sel);
  78
  79        dev_err(&rdev->dev,
  80                "LED voltage change not allowed when led is enabled\n");
  81
  82        return -EBUSY;
  83}
  84
  85static const struct regulator_ops bd70528_buck_ops = {
  86        .enable = regulator_enable_regmap,
  87        .disable = regulator_disable_regmap,
  88        .is_enabled = regulator_is_enabled_regmap,
  89        .list_voltage = regulator_list_voltage_linear_range,
  90        .set_voltage_sel = regulator_set_voltage_sel_regmap,
  91        .get_voltage_sel = regulator_get_voltage_sel_regmap,
  92        .set_voltage_time_sel = regulator_set_voltage_time_sel,
  93        .set_ramp_delay = bd70528_set_ramp_delay,
  94};
  95
  96static const struct regulator_ops bd70528_ldo_ops = {
  97        .enable = regulator_enable_regmap,
  98        .disable = regulator_disable_regmap,
  99        .is_enabled = regulator_is_enabled_regmap,
 100        .list_voltage = regulator_list_voltage_linear_range,
 101        .set_voltage_sel = regulator_set_voltage_sel_regmap,
 102        .get_voltage_sel = regulator_get_voltage_sel_regmap,
 103        .set_voltage_time_sel = regulator_set_voltage_time_sel,
 104};
 105
 106static const struct regulator_ops bd70528_led_ops = {
 107        .enable = regulator_enable_regmap,
 108        .disable = regulator_disable_regmap,
 109        .is_enabled = regulator_is_enabled_regmap,
 110        .list_voltage = regulator_list_voltage_table,
 111        .set_voltage_sel = bd70528_led_set_voltage_sel,
 112        .get_voltage_sel = regulator_get_voltage_sel_regmap,
 113};
 114
 115static const struct regulator_desc bd70528_desc[] = {
 116        {
 117                .name = "buck1",
 118                .of_match = of_match_ptr("BUCK1"),
 119                .regulators_node = of_match_ptr("regulators"),
 120                .id = BD70528_BUCK1,
 121                .ops = &bd70528_buck_ops,
 122                .type = REGULATOR_VOLTAGE,
 123                .linear_ranges = bd70528_buck1_volts,
 124                .n_linear_ranges = ARRAY_SIZE(bd70528_buck1_volts),
 125                .n_voltages = BD70528_BUCK_VOLTS,
 126                .enable_reg = BD70528_REG_BUCK1_EN,
 127                .enable_mask = BD70528_MASK_RUN_EN,
 128                .vsel_reg = BD70528_REG_BUCK1_VOLT,
 129                .vsel_mask = BD70528_MASK_BUCK_VOLT,
 130                .owner = THIS_MODULE,
 131        },
 132        {
 133                .name = "buck2",
 134                .of_match = of_match_ptr("BUCK2"),
 135                .regulators_node = of_match_ptr("regulators"),
 136                .id = BD70528_BUCK2,
 137                .ops = &bd70528_buck_ops,
 138                .type = REGULATOR_VOLTAGE,
 139                .linear_ranges = bd70528_buck2_volts,
 140                .n_linear_ranges = ARRAY_SIZE(bd70528_buck2_volts),
 141                .n_voltages = BD70528_BUCK_VOLTS,
 142                .enable_reg = BD70528_REG_BUCK2_EN,
 143                .enable_mask = BD70528_MASK_RUN_EN,
 144                .vsel_reg = BD70528_REG_BUCK2_VOLT,
 145                .vsel_mask = BD70528_MASK_BUCK_VOLT,
 146                .owner = THIS_MODULE,
 147        },
 148        {
 149                .name = "buck3",
 150                .of_match = of_match_ptr("BUCK3"),
 151                .regulators_node = of_match_ptr("regulators"),
 152                .id = BD70528_BUCK3,
 153                .ops = &bd70528_buck_ops,
 154                .type = REGULATOR_VOLTAGE,
 155                .linear_ranges = bd70528_buck3_volts,
 156                .n_linear_ranges = ARRAY_SIZE(bd70528_buck3_volts),
 157                .n_voltages = BD70528_BUCK_VOLTS,
 158                .enable_reg = BD70528_REG_BUCK3_EN,
 159                .enable_mask = BD70528_MASK_RUN_EN,
 160                .vsel_reg = BD70528_REG_BUCK3_VOLT,
 161                .vsel_mask = BD70528_MASK_BUCK_VOLT,
 162                .owner = THIS_MODULE,
 163        },
 164        {
 165                .name = "ldo1",
 166                .of_match = of_match_ptr("LDO1"),
 167                .regulators_node = of_match_ptr("regulators"),
 168                .id = BD70528_LDO1,
 169                .ops = &bd70528_ldo_ops,
 170                .type = REGULATOR_VOLTAGE,
 171                .linear_ranges = bd70528_ldo_volts,
 172                .n_linear_ranges = ARRAY_SIZE(bd70528_ldo_volts),
 173                .n_voltages = BD70528_LDO_VOLTS,
 174                .enable_reg = BD70528_REG_LDO1_EN,
 175                .enable_mask = BD70528_MASK_RUN_EN,
 176                .vsel_reg = BD70528_REG_LDO1_VOLT,
 177                .vsel_mask = BD70528_MASK_LDO_VOLT,
 178                .owner = THIS_MODULE,
 179        },
 180        {
 181                .name = "ldo2",
 182                .of_match = of_match_ptr("LDO2"),
 183                .regulators_node = of_match_ptr("regulators"),
 184                .id = BD70528_LDO2,
 185                .ops = &bd70528_ldo_ops,
 186                .type = REGULATOR_VOLTAGE,
 187                .linear_ranges = bd70528_ldo_volts,
 188                .n_linear_ranges = ARRAY_SIZE(bd70528_ldo_volts),
 189                .n_voltages = BD70528_LDO_VOLTS,
 190                .enable_reg = BD70528_REG_LDO2_EN,
 191                .enable_mask = BD70528_MASK_RUN_EN,
 192                .vsel_reg = BD70528_REG_LDO2_VOLT,
 193                .vsel_mask = BD70528_MASK_LDO_VOLT,
 194                .owner = THIS_MODULE,
 195        },
 196        {
 197                .name = "ldo3",
 198                .of_match = of_match_ptr("LDO3"),
 199                .regulators_node = of_match_ptr("regulators"),
 200                .id = BD70528_LDO3,
 201                .ops = &bd70528_ldo_ops,
 202                .type = REGULATOR_VOLTAGE,
 203                .linear_ranges = bd70528_ldo_volts,
 204                .n_linear_ranges = ARRAY_SIZE(bd70528_ldo_volts),
 205                .n_voltages = BD70528_LDO_VOLTS,
 206                .enable_reg = BD70528_REG_LDO3_EN,
 207                .enable_mask = BD70528_MASK_RUN_EN,
 208                .vsel_reg = BD70528_REG_LDO3_VOLT,
 209                .vsel_mask = BD70528_MASK_LDO_VOLT,
 210                .owner = THIS_MODULE,
 211        },
 212        {
 213                .name = "ldo_led1",
 214                .of_match = of_match_ptr("LDO_LED1"),
 215                .regulators_node = of_match_ptr("regulators"),
 216                .id = BD70528_LED1,
 217                .ops = &bd70528_led_ops,
 218                .type = REGULATOR_VOLTAGE,
 219                .volt_table = &led_volts[0],
 220                .n_voltages = ARRAY_SIZE(led_volts),
 221                .enable_reg = BD70528_REG_LED_EN,
 222                .enable_mask = BD70528_MASK_LED1_EN,
 223                .vsel_reg = BD70528_REG_LED_VOLT,
 224                .vsel_mask = BD70528_MASK_LED1_VOLT,
 225                .owner = THIS_MODULE,
 226        },
 227        {
 228                .name = "ldo_led2",
 229                .of_match = of_match_ptr("LDO_LED2"),
 230                .regulators_node = of_match_ptr("regulators"),
 231                .id = BD70528_LED2,
 232                .ops = &bd70528_led_ops,
 233                .type = REGULATOR_VOLTAGE,
 234                .volt_table = &led_volts[0],
 235                .n_voltages = ARRAY_SIZE(led_volts),
 236                .enable_reg = BD70528_REG_LED_EN,
 237                .enable_mask = BD70528_MASK_LED2_EN,
 238                .vsel_reg = BD70528_REG_LED_VOLT,
 239                .vsel_mask = BD70528_MASK_LED2_VOLT,
 240                .owner = THIS_MODULE,
 241        },
 242
 243};
 244
 245static int bd70528_probe(struct platform_device *pdev)
 246{
 247        struct rohm_regmap_dev *bd70528;
 248        int i;
 249        struct regulator_config config = {
 250                .dev = pdev->dev.parent,
 251        };
 252
 253        bd70528 = dev_get_drvdata(pdev->dev.parent);
 254        if (!bd70528) {
 255                dev_err(&pdev->dev, "No MFD driver data\n");
 256                return -EINVAL;
 257        }
 258
 259        config.regmap = bd70528->regmap;
 260
 261        for (i = 0; i < ARRAY_SIZE(bd70528_desc); i++) {
 262                struct regulator_dev *rdev;
 263
 264                rdev = devm_regulator_register(&pdev->dev, &bd70528_desc[i],
 265                                               &config);
 266                if (IS_ERR(rdev)) {
 267                        dev_err(&pdev->dev,
 268                                "failed to register %s regulator\n",
 269                                bd70528_desc[i].name);
 270                        return PTR_ERR(rdev);
 271                }
 272        }
 273        return 0;
 274}
 275
 276static struct platform_driver bd70528_regulator = {
 277        .driver = {
 278                .name = "bd70528-pmic"
 279        },
 280        .probe = bd70528_probe,
 281};
 282
 283module_platform_driver(bd70528_regulator);
 284
 285MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
 286MODULE_DESCRIPTION("BD70528 voltage regulator driver");
 287MODULE_LICENSE("GPL");
 288MODULE_ALIAS("platform:bd70528-pmic");
 289