linux/drivers/regulator/max77650-regulator.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2//
   3// Copyright (C) 2018 BayLibre SAS
   4// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
   5//
   6// Regulator driver for MAXIM 77650/77651 charger/power-supply.
   7
   8#include <linux/of.h>
   9#include <linux/mfd/max77650.h>
  10#include <linux/module.h>
  11#include <linux/platform_device.h>
  12#include <linux/regmap.h>
  13#include <linux/regulator/driver.h>
  14
  15#define MAX77650_REGULATOR_EN_CTRL_MASK         GENMASK(3, 0)
  16#define MAX77650_REGULATOR_EN_CTRL_BITS(_reg) \
  17                ((_reg) & MAX77650_REGULATOR_EN_CTRL_MASK)
  18#define MAX77650_REGULATOR_ENABLED              GENMASK(2, 1)
  19#define MAX77650_REGULATOR_DISABLED             BIT(2)
  20
  21#define MAX77650_REGULATOR_V_LDO_MASK           GENMASK(6, 0)
  22#define MAX77650_REGULATOR_V_SBB_MASK           GENMASK(5, 0)
  23#define MAX77651_REGULATOR_V_SBB1_MASK          GENMASK(5, 2)
  24#define MAX77651_REGULATOR_V_SBB1_RANGE_MASK    GENMASK(1, 0)
  25
  26#define MAX77650_REGULATOR_AD_MASK              BIT(3)
  27#define MAX77650_REGULATOR_AD_DISABLED          0x00
  28#define MAX77650_REGULATOR_AD_ENABLED           BIT(3)
  29
  30#define MAX77650_REGULATOR_CURR_LIM_MASK        GENMASK(7, 6)
  31
  32enum {
  33        MAX77650_REGULATOR_ID_LDO = 0,
  34        MAX77650_REGULATOR_ID_SBB0,
  35        MAX77650_REGULATOR_ID_SBB1,
  36        MAX77650_REGULATOR_ID_SBB2,
  37        MAX77650_REGULATOR_NUM_REGULATORS,
  38};
  39
  40struct max77650_regulator_desc {
  41        struct regulator_desc desc;
  42        unsigned int regA;
  43        unsigned int regB;
  44};
  45
  46static struct max77650_regulator_desc max77651_SBB1_desc;
  47
  48static const unsigned int max77651_sbb1_volt_range_sel[] = {
  49        0x0, 0x1, 0x2, 0x3
  50};
  51
  52static const struct regulator_linear_range max77651_sbb1_volt_ranges[] = {
  53        /* range index 0 */
  54        REGULATOR_LINEAR_RANGE(2400000, 0x00, 0x0f, 50000),
  55        /* range index 1 */
  56        REGULATOR_LINEAR_RANGE(3200000, 0x00, 0x0f, 50000),
  57        /* range index 2 */
  58        REGULATOR_LINEAR_RANGE(4000000, 0x00, 0x0f, 50000),
  59        /* range index 3 */
  60        REGULATOR_LINEAR_RANGE(4800000, 0x00, 0x09, 50000),
  61};
  62
  63static const unsigned int max77650_current_limit_table[] = {
  64        1000000, 866000, 707000, 500000,
  65};
  66
  67static int max77650_regulator_is_enabled(struct regulator_dev *rdev)
  68{
  69        struct max77650_regulator_desc *rdesc;
  70        struct regmap *map;
  71        int val, rv, en;
  72
  73        rdesc = rdev_get_drvdata(rdev);
  74        map = rdev_get_regmap(rdev);
  75
  76        rv = regmap_read(map, rdesc->regB, &val);
  77        if (rv)
  78                return rv;
  79
  80        en = MAX77650_REGULATOR_EN_CTRL_BITS(val);
  81
  82        return en != MAX77650_REGULATOR_DISABLED;
  83}
  84
  85static int max77650_regulator_enable(struct regulator_dev *rdev)
  86{
  87        struct max77650_regulator_desc *rdesc;
  88        struct regmap *map;
  89
  90        rdesc = rdev_get_drvdata(rdev);
  91        map = rdev_get_regmap(rdev);
  92
  93        return regmap_update_bits(map, rdesc->regB,
  94                                  MAX77650_REGULATOR_EN_CTRL_MASK,
  95                                  MAX77650_REGULATOR_ENABLED);
  96}
  97
  98static int max77650_regulator_disable(struct regulator_dev *rdev)
  99{
 100        struct max77650_regulator_desc *rdesc;
 101        struct regmap *map;
 102
 103        rdesc = rdev_get_drvdata(rdev);
 104        map = rdev_get_regmap(rdev);
 105
 106        return regmap_update_bits(map, rdesc->regB,
 107                                  MAX77650_REGULATOR_EN_CTRL_MASK,
 108                                  MAX77650_REGULATOR_DISABLED);
 109}
 110
 111static const struct regulator_ops max77650_regulator_LDO_ops = {
 112        .is_enabled             = max77650_regulator_is_enabled,
 113        .enable                 = max77650_regulator_enable,
 114        .disable                = max77650_regulator_disable,
 115        .list_voltage           = regulator_list_voltage_linear,
 116        .map_voltage            = regulator_map_voltage_linear,
 117        .get_voltage_sel        = regulator_get_voltage_sel_regmap,
 118        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
 119        .set_active_discharge   = regulator_set_active_discharge_regmap,
 120};
 121
 122static const struct regulator_ops max77650_regulator_SBB_ops = {
 123        .is_enabled             = max77650_regulator_is_enabled,
 124        .enable                 = max77650_regulator_enable,
 125        .disable                = max77650_regulator_disable,
 126        .list_voltage           = regulator_list_voltage_linear,
 127        .map_voltage            = regulator_map_voltage_linear,
 128        .get_voltage_sel        = regulator_get_voltage_sel_regmap,
 129        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
 130        .get_current_limit      = regulator_get_current_limit_regmap,
 131        .set_current_limit      = regulator_set_current_limit_regmap,
 132        .set_active_discharge   = regulator_set_active_discharge_regmap,
 133};
 134
 135/* Special case for max77651 SBB1 - pickable linear-range voltage mapping. */
 136static const struct regulator_ops max77651_SBB1_regulator_ops = {
 137        .is_enabled             = max77650_regulator_is_enabled,
 138        .enable                 = max77650_regulator_enable,
 139        .disable                = max77650_regulator_disable,
 140        .list_voltage           = regulator_list_voltage_pickable_linear_range,
 141        .get_voltage_sel        = regulator_get_voltage_sel_pickable_regmap,
 142        .set_voltage_sel        = regulator_set_voltage_sel_pickable_regmap,
 143        .get_current_limit      = regulator_get_current_limit_regmap,
 144        .set_current_limit      = regulator_set_current_limit_regmap,
 145        .set_active_discharge   = regulator_set_active_discharge_regmap,
 146};
 147
 148static struct max77650_regulator_desc max77650_LDO_desc = {
 149        .desc = {
 150                .name                   = "ldo",
 151                .of_match               = of_match_ptr("ldo"),
 152                .regulators_node        = of_match_ptr("regulators"),
 153                .supply_name            = "in-ldo",
 154                .id                     = MAX77650_REGULATOR_ID_LDO,
 155                .ops                    = &max77650_regulator_LDO_ops,
 156                .min_uV                 = 1350000,
 157                .uV_step                = 12500,
 158                .n_voltages             = 128,
 159                .vsel_step              = 1,
 160                .vsel_mask              = MAX77650_REGULATOR_V_LDO_MASK,
 161                .vsel_reg               = MAX77650_REG_CNFG_LDO_A,
 162                .active_discharge_off   = MAX77650_REGULATOR_AD_DISABLED,
 163                .active_discharge_on    = MAX77650_REGULATOR_AD_ENABLED,
 164                .active_discharge_mask  = MAX77650_REGULATOR_AD_MASK,
 165                .active_discharge_reg   = MAX77650_REG_CNFG_LDO_B,
 166                .enable_time            = 100,
 167                .type                   = REGULATOR_VOLTAGE,
 168                .owner                  = THIS_MODULE,
 169        },
 170        .regA           = MAX77650_REG_CNFG_LDO_A,
 171        .regB           = MAX77650_REG_CNFG_LDO_B,
 172};
 173
 174static struct max77650_regulator_desc max77650_SBB0_desc = {
 175        .desc = {
 176                .name                   = "sbb0",
 177                .of_match               = of_match_ptr("sbb0"),
 178                .regulators_node        = of_match_ptr("regulators"),
 179                .supply_name            = "in-sbb0",
 180                .id                     = MAX77650_REGULATOR_ID_SBB0,
 181                .ops                    = &max77650_regulator_SBB_ops,
 182                .min_uV                 = 800000,
 183                .uV_step                = 25000,
 184                .n_voltages             = 64,
 185                .vsel_step              = 1,
 186                .vsel_mask              = MAX77650_REGULATOR_V_SBB_MASK,
 187                .vsel_reg               = MAX77650_REG_CNFG_SBB0_A,
 188                .active_discharge_off   = MAX77650_REGULATOR_AD_DISABLED,
 189                .active_discharge_on    = MAX77650_REGULATOR_AD_ENABLED,
 190                .active_discharge_mask  = MAX77650_REGULATOR_AD_MASK,
 191                .active_discharge_reg   = MAX77650_REG_CNFG_SBB0_B,
 192                .enable_time            = 100,
 193                .type                   = REGULATOR_VOLTAGE,
 194                .owner                  = THIS_MODULE,
 195                .csel_reg               = MAX77650_REG_CNFG_SBB0_A,
 196                .csel_mask              = MAX77650_REGULATOR_CURR_LIM_MASK,
 197                .curr_table             = max77650_current_limit_table,
 198                .n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
 199        },
 200        .regA           = MAX77650_REG_CNFG_SBB0_A,
 201        .regB           = MAX77650_REG_CNFG_SBB0_B,
 202};
 203
 204static struct max77650_regulator_desc max77650_SBB1_desc = {
 205        .desc = {
 206                .name                   = "sbb1",
 207                .of_match               = of_match_ptr("sbb1"),
 208                .regulators_node        = of_match_ptr("regulators"),
 209                .supply_name            = "in-sbb1",
 210                .id                     = MAX77650_REGULATOR_ID_SBB1,
 211                .ops                    = &max77650_regulator_SBB_ops,
 212                .min_uV                 = 800000,
 213                .uV_step                = 12500,
 214                .n_voltages             = 64,
 215                .vsel_step              = 1,
 216                .vsel_mask              = MAX77650_REGULATOR_V_SBB_MASK,
 217                .vsel_reg               = MAX77650_REG_CNFG_SBB1_A,
 218                .active_discharge_off   = MAX77650_REGULATOR_AD_DISABLED,
 219                .active_discharge_on    = MAX77650_REGULATOR_AD_ENABLED,
 220                .active_discharge_mask  = MAX77650_REGULATOR_AD_MASK,
 221                .active_discharge_reg   = MAX77650_REG_CNFG_SBB1_B,
 222                .enable_time            = 100,
 223                .type                   = REGULATOR_VOLTAGE,
 224                .owner                  = THIS_MODULE,
 225                .csel_reg               = MAX77650_REG_CNFG_SBB1_A,
 226                .csel_mask              = MAX77650_REGULATOR_CURR_LIM_MASK,
 227                .curr_table             = max77650_current_limit_table,
 228                .n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
 229        },
 230        .regA           = MAX77650_REG_CNFG_SBB1_A,
 231        .regB           = MAX77650_REG_CNFG_SBB1_B,
 232};
 233
 234static struct max77650_regulator_desc max77651_SBB1_desc = {
 235        .desc = {
 236                .name                   = "sbb1",
 237                .of_match               = of_match_ptr("sbb1"),
 238                .regulators_node        = of_match_ptr("regulators"),
 239                .supply_name            = "in-sbb1",
 240                .id                     = MAX77650_REGULATOR_ID_SBB1,
 241                .ops                    = &max77651_SBB1_regulator_ops,
 242                .linear_range_selectors = max77651_sbb1_volt_range_sel,
 243                .linear_ranges          = max77651_sbb1_volt_ranges,
 244                .n_linear_ranges        = ARRAY_SIZE(max77651_sbb1_volt_ranges),
 245                .n_voltages             = 58,
 246                .vsel_step              = 1,
 247                .vsel_range_mask        = MAX77651_REGULATOR_V_SBB1_RANGE_MASK,
 248                .vsel_range_reg         = MAX77650_REG_CNFG_SBB1_A,
 249                .vsel_mask              = MAX77651_REGULATOR_V_SBB1_MASK,
 250                .vsel_reg               = MAX77650_REG_CNFG_SBB1_A,
 251                .active_discharge_off   = MAX77650_REGULATOR_AD_DISABLED,
 252                .active_discharge_on    = MAX77650_REGULATOR_AD_ENABLED,
 253                .active_discharge_mask  = MAX77650_REGULATOR_AD_MASK,
 254                .active_discharge_reg   = MAX77650_REG_CNFG_SBB1_B,
 255                .enable_time            = 100,
 256                .type                   = REGULATOR_VOLTAGE,
 257                .owner                  = THIS_MODULE,
 258                .csel_reg               = MAX77650_REG_CNFG_SBB1_A,
 259                .csel_mask              = MAX77650_REGULATOR_CURR_LIM_MASK,
 260                .curr_table             = max77650_current_limit_table,
 261                .n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
 262        },
 263        .regA           = MAX77650_REG_CNFG_SBB1_A,
 264        .regB           = MAX77650_REG_CNFG_SBB1_B,
 265};
 266
 267static struct max77650_regulator_desc max77650_SBB2_desc = {
 268        .desc = {
 269                .name                   = "sbb2",
 270                .of_match               = of_match_ptr("sbb2"),
 271                .regulators_node        = of_match_ptr("regulators"),
 272                .supply_name            = "in-sbb0",
 273                .id                     = MAX77650_REGULATOR_ID_SBB2,
 274                .ops                    = &max77650_regulator_SBB_ops,
 275                .min_uV                 = 800000,
 276                .uV_step                = 50000,
 277                .n_voltages             = 64,
 278                .vsel_step              = 1,
 279                .vsel_mask              = MAX77650_REGULATOR_V_SBB_MASK,
 280                .vsel_reg               = MAX77650_REG_CNFG_SBB2_A,
 281                .active_discharge_off   = MAX77650_REGULATOR_AD_DISABLED,
 282                .active_discharge_on    = MAX77650_REGULATOR_AD_ENABLED,
 283                .active_discharge_mask  = MAX77650_REGULATOR_AD_MASK,
 284                .active_discharge_reg   = MAX77650_REG_CNFG_SBB2_B,
 285                .enable_time            = 100,
 286                .type                   = REGULATOR_VOLTAGE,
 287                .owner                  = THIS_MODULE,
 288                .csel_reg               = MAX77650_REG_CNFG_SBB2_A,
 289                .csel_mask              = MAX77650_REGULATOR_CURR_LIM_MASK,
 290                .curr_table             = max77650_current_limit_table,
 291                .n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
 292        },
 293        .regA           = MAX77650_REG_CNFG_SBB2_A,
 294        .regB           = MAX77650_REG_CNFG_SBB2_B,
 295};
 296
 297static struct max77650_regulator_desc max77651_SBB2_desc = {
 298        .desc = {
 299                .name                   = "sbb2",
 300                .of_match               = of_match_ptr("sbb2"),
 301                .regulators_node        = of_match_ptr("regulators"),
 302                .supply_name            = "in-sbb0",
 303                .id                     = MAX77650_REGULATOR_ID_SBB2,
 304                .ops                    = &max77650_regulator_SBB_ops,
 305                .min_uV                 = 2400000,
 306                .uV_step                = 50000,
 307                .n_voltages             = 64,
 308                .vsel_step              = 1,
 309                .vsel_mask              = MAX77650_REGULATOR_V_SBB_MASK,
 310                .vsel_reg               = MAX77650_REG_CNFG_SBB2_A,
 311                .active_discharge_off   = MAX77650_REGULATOR_AD_DISABLED,
 312                .active_discharge_on    = MAX77650_REGULATOR_AD_ENABLED,
 313                .active_discharge_mask  = MAX77650_REGULATOR_AD_MASK,
 314                .active_discharge_reg   = MAX77650_REG_CNFG_SBB2_B,
 315                .enable_time            = 100,
 316                .type                   = REGULATOR_VOLTAGE,
 317                .owner                  = THIS_MODULE,
 318                .csel_reg               = MAX77650_REG_CNFG_SBB2_A,
 319                .csel_mask              = MAX77650_REGULATOR_CURR_LIM_MASK,
 320                .curr_table             = max77650_current_limit_table,
 321                .n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
 322        },
 323        .regA           = MAX77650_REG_CNFG_SBB2_A,
 324        .regB           = MAX77650_REG_CNFG_SBB2_B,
 325};
 326
 327static int max77650_regulator_probe(struct platform_device *pdev)
 328{
 329        struct max77650_regulator_desc **rdescs;
 330        struct max77650_regulator_desc *rdesc;
 331        struct regulator_config config = { };
 332        struct device *dev, *parent;
 333        struct regulator_dev *rdev;
 334        struct regmap *map;
 335        unsigned int val;
 336        int i, rv;
 337
 338        dev = &pdev->dev;
 339        parent = dev->parent;
 340
 341        if (!dev->of_node)
 342                dev->of_node = parent->of_node;
 343
 344        rdescs = devm_kcalloc(dev, MAX77650_REGULATOR_NUM_REGULATORS,
 345                              sizeof(*rdescs), GFP_KERNEL);
 346        if (!rdescs)
 347                return -ENOMEM;
 348
 349        map = dev_get_regmap(parent, NULL);
 350        if (!map)
 351                return -ENODEV;
 352
 353        rv = regmap_read(map, MAX77650_REG_CID, &val);
 354        if (rv)
 355                return rv;
 356
 357        rdescs[MAX77650_REGULATOR_ID_LDO] = &max77650_LDO_desc;
 358        rdescs[MAX77650_REGULATOR_ID_SBB0] = &max77650_SBB0_desc;
 359
 360        switch (MAX77650_CID_BITS(val)) {
 361        case MAX77650_CID_77650A:
 362        case MAX77650_CID_77650C:
 363                rdescs[MAX77650_REGULATOR_ID_SBB1] = &max77650_SBB1_desc;
 364                rdescs[MAX77650_REGULATOR_ID_SBB2] = &max77650_SBB2_desc;
 365                break;
 366        case MAX77650_CID_77651A:
 367        case MAX77650_CID_77651B:
 368                rdescs[MAX77650_REGULATOR_ID_SBB1] = &max77651_SBB1_desc;
 369                rdescs[MAX77650_REGULATOR_ID_SBB2] = &max77651_SBB2_desc;
 370                break;
 371        default:
 372                return -ENODEV;
 373        }
 374
 375        config.dev = parent;
 376
 377        for (i = 0; i < MAX77650_REGULATOR_NUM_REGULATORS; i++) {
 378                rdesc = rdescs[i];
 379                config.driver_data = rdesc;
 380
 381                rdev = devm_regulator_register(dev, &rdesc->desc, &config);
 382                if (IS_ERR(rdev))
 383                        return PTR_ERR(rdev);
 384        }
 385
 386        return 0;
 387}
 388
 389static const struct of_device_id max77650_regulator_of_match[] = {
 390        { .compatible = "maxim,max77650-regulator" },
 391        { }
 392};
 393MODULE_DEVICE_TABLE(of, max77650_regulator_of_match);
 394
 395static struct platform_driver max77650_regulator_driver = {
 396        .driver = {
 397                .name = "max77650-regulator",
 398                .of_match_table = max77650_regulator_of_match,
 399        },
 400        .probe = max77650_regulator_probe,
 401};
 402module_platform_driver(max77650_regulator_driver);
 403
 404MODULE_DESCRIPTION("MAXIM 77650/77651 regulator driver");
 405MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
 406MODULE_LICENSE("GPL v2");
 407MODULE_ALIAS("platform:max77650-regulator");
 408