linux/drivers/regulator/as3722-regulator.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Voltage regulator support for AMS AS3722 PMIC
   4 *
   5 * Copyright (C) 2013 ams
   6 *
   7 * Author: Florian Lobmaier <florian.lobmaier@ams.com>
   8 * Author: Laxman Dewangan <ldewangan@nvidia.com>
   9 */
  10
  11#include <linux/err.h>
  12#include <linux/kernel.h>
  13#include <linux/module.h>
  14#include <linux/mfd/as3722.h>
  15#include <linux/of.h>
  16#include <linux/of_platform.h>
  17#include <linux/platform_device.h>
  18#include <linux/regulator/driver.h>
  19#include <linux/regulator/machine.h>
  20#include <linux/regulator/of_regulator.h>
  21#include <linux/slab.h>
  22
  23/* Regulator IDs */
  24enum as3722_regulators_id {
  25        AS3722_REGULATOR_ID_SD0,
  26        AS3722_REGULATOR_ID_SD1,
  27        AS3722_REGULATOR_ID_SD2,
  28        AS3722_REGULATOR_ID_SD3,
  29        AS3722_REGULATOR_ID_SD4,
  30        AS3722_REGULATOR_ID_SD5,
  31        AS3722_REGULATOR_ID_SD6,
  32        AS3722_REGULATOR_ID_LDO0,
  33        AS3722_REGULATOR_ID_LDO1,
  34        AS3722_REGULATOR_ID_LDO2,
  35        AS3722_REGULATOR_ID_LDO3,
  36        AS3722_REGULATOR_ID_LDO4,
  37        AS3722_REGULATOR_ID_LDO5,
  38        AS3722_REGULATOR_ID_LDO6,
  39        AS3722_REGULATOR_ID_LDO7,
  40        AS3722_REGULATOR_ID_LDO9,
  41        AS3722_REGULATOR_ID_LDO10,
  42        AS3722_REGULATOR_ID_LDO11,
  43        AS3722_REGULATOR_ID_MAX,
  44};
  45
  46struct as3722_register_mapping {
  47        u8 regulator_id;
  48        const char *name;
  49        const char *sname;
  50        u8 vsel_reg;
  51        u8 vsel_mask;
  52        int n_voltages;
  53        u32 enable_reg;
  54        u8 enable_mask;
  55        u32 control_reg;
  56        u8 mode_mask;
  57        u32 sleep_ctrl_reg;
  58        u8 sleep_ctrl_mask;
  59};
  60
  61struct as3722_regulator_config_data {
  62        struct regulator_init_data *reg_init;
  63        bool enable_tracking;
  64        int ext_control;
  65};
  66
  67struct as3722_regulators {
  68        struct device *dev;
  69        struct as3722 *as3722;
  70        struct regulator_desc desc[AS3722_REGULATOR_ID_MAX];
  71        struct as3722_regulator_config_data
  72                        reg_config_data[AS3722_REGULATOR_ID_MAX];
  73};
  74
  75static const struct as3722_register_mapping as3722_reg_lookup[] = {
  76        {
  77                .regulator_id = AS3722_REGULATOR_ID_SD0,
  78                .name = "as3722-sd0",
  79                .vsel_reg = AS3722_SD0_VOLTAGE_REG,
  80                .vsel_mask = AS3722_SD_VSEL_MASK,
  81                .enable_reg = AS3722_SD_CONTROL_REG,
  82                .enable_mask = AS3722_SDn_CTRL(0),
  83                .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG,
  84                .sleep_ctrl_mask = AS3722_SD0_EXT_ENABLE_MASK,
  85                .control_reg = AS3722_SD0_CONTROL_REG,
  86                .mode_mask = AS3722_SD0_MODE_FAST,
  87        },
  88        {
  89                .regulator_id = AS3722_REGULATOR_ID_SD1,
  90                .name = "as3722-sd1",
  91                .vsel_reg = AS3722_SD1_VOLTAGE_REG,
  92                .vsel_mask = AS3722_SD_VSEL_MASK,
  93                .enable_reg = AS3722_SD_CONTROL_REG,
  94                .enable_mask = AS3722_SDn_CTRL(1),
  95                .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG,
  96                .sleep_ctrl_mask = AS3722_SD1_EXT_ENABLE_MASK,
  97                .control_reg = AS3722_SD1_CONTROL_REG,
  98                .mode_mask = AS3722_SD1_MODE_FAST,
  99        },
 100        {
 101                .regulator_id = AS3722_REGULATOR_ID_SD2,
 102                .name = "as3722-sd2",
 103                .sname = "vsup-sd2",
 104                .vsel_reg = AS3722_SD2_VOLTAGE_REG,
 105                .vsel_mask = AS3722_SD_VSEL_MASK,
 106                .enable_reg = AS3722_SD_CONTROL_REG,
 107                .enable_mask = AS3722_SDn_CTRL(2),
 108                .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG,
 109                .sleep_ctrl_mask = AS3722_SD2_EXT_ENABLE_MASK,
 110                .control_reg = AS3722_SD23_CONTROL_REG,
 111                .mode_mask = AS3722_SD2_MODE_FAST,
 112                .n_voltages = AS3722_SD2_VSEL_MAX + 1,
 113        },
 114        {
 115                .regulator_id = AS3722_REGULATOR_ID_SD3,
 116                .name = "as3722-sd3",
 117                .sname = "vsup-sd3",
 118                .vsel_reg = AS3722_SD3_VOLTAGE_REG,
 119                .vsel_mask = AS3722_SD_VSEL_MASK,
 120                .enable_reg = AS3722_SD_CONTROL_REG,
 121                .enable_mask = AS3722_SDn_CTRL(3),
 122                .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG,
 123                .sleep_ctrl_mask = AS3722_SD3_EXT_ENABLE_MASK,
 124                .control_reg = AS3722_SD23_CONTROL_REG,
 125                .mode_mask = AS3722_SD3_MODE_FAST,
 126                .n_voltages = AS3722_SD2_VSEL_MAX + 1,
 127        },
 128        {
 129                .regulator_id = AS3722_REGULATOR_ID_SD4,
 130                .name = "as3722-sd4",
 131                .sname = "vsup-sd4",
 132                .vsel_reg = AS3722_SD4_VOLTAGE_REG,
 133                .vsel_mask = AS3722_SD_VSEL_MASK,
 134                .enable_reg = AS3722_SD_CONTROL_REG,
 135                .enable_mask = AS3722_SDn_CTRL(4),
 136                .sleep_ctrl_reg = AS3722_ENABLE_CTRL2_REG,
 137                .sleep_ctrl_mask = AS3722_SD4_EXT_ENABLE_MASK,
 138                .control_reg = AS3722_SD4_CONTROL_REG,
 139                .mode_mask = AS3722_SD4_MODE_FAST,
 140                .n_voltages = AS3722_SD2_VSEL_MAX + 1,
 141        },
 142        {
 143                .regulator_id = AS3722_REGULATOR_ID_SD5,
 144                .name = "as3722-sd5",
 145                .sname = "vsup-sd5",
 146                .vsel_reg = AS3722_SD5_VOLTAGE_REG,
 147                .vsel_mask = AS3722_SD_VSEL_MASK,
 148                .enable_reg = AS3722_SD_CONTROL_REG,
 149                .enable_mask = AS3722_SDn_CTRL(5),
 150                .sleep_ctrl_reg = AS3722_ENABLE_CTRL2_REG,
 151                .sleep_ctrl_mask = AS3722_SD5_EXT_ENABLE_MASK,
 152                .control_reg = AS3722_SD5_CONTROL_REG,
 153                .mode_mask = AS3722_SD5_MODE_FAST,
 154                .n_voltages = AS3722_SD2_VSEL_MAX + 1,
 155        },
 156        {
 157                .regulator_id = AS3722_REGULATOR_ID_SD6,
 158                .name = "as3722-sd6",
 159                .vsel_reg = AS3722_SD6_VOLTAGE_REG,
 160                .vsel_mask = AS3722_SD_VSEL_MASK,
 161                .enable_reg = AS3722_SD_CONTROL_REG,
 162                .enable_mask = AS3722_SDn_CTRL(6),
 163                .sleep_ctrl_reg = AS3722_ENABLE_CTRL2_REG,
 164                .sleep_ctrl_mask = AS3722_SD6_EXT_ENABLE_MASK,
 165                .control_reg = AS3722_SD6_CONTROL_REG,
 166                .mode_mask = AS3722_SD6_MODE_FAST,
 167        },
 168        {
 169                .regulator_id = AS3722_REGULATOR_ID_LDO0,
 170                .name = "as3722-ldo0",
 171                .sname = "vin-ldo0",
 172                .vsel_reg = AS3722_LDO0_VOLTAGE_REG,
 173                .vsel_mask = AS3722_LDO0_VSEL_MASK,
 174                .enable_reg = AS3722_LDOCONTROL0_REG,
 175                .enable_mask = AS3722_LDO0_CTRL,
 176                .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG,
 177                .sleep_ctrl_mask = AS3722_LDO0_EXT_ENABLE_MASK,
 178                .n_voltages = AS3722_LDO0_NUM_VOLT,
 179        },
 180        {
 181                .regulator_id = AS3722_REGULATOR_ID_LDO1,
 182                .name = "as3722-ldo1",
 183                .sname = "vin-ldo1-6",
 184                .vsel_reg = AS3722_LDO1_VOLTAGE_REG,
 185                .vsel_mask = AS3722_LDO_VSEL_MASK,
 186                .enable_reg = AS3722_LDOCONTROL0_REG,
 187                .enable_mask = AS3722_LDO1_CTRL,
 188                .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG,
 189                .sleep_ctrl_mask = AS3722_LDO1_EXT_ENABLE_MASK,
 190                .n_voltages = AS3722_LDO_NUM_VOLT,
 191        },
 192        {
 193                .regulator_id = AS3722_REGULATOR_ID_LDO2,
 194                .name = "as3722-ldo2",
 195                .sname = "vin-ldo2-5-7",
 196                .vsel_reg = AS3722_LDO2_VOLTAGE_REG,
 197                .vsel_mask = AS3722_LDO_VSEL_MASK,
 198                .enable_reg = AS3722_LDOCONTROL0_REG,
 199                .enable_mask = AS3722_LDO2_CTRL,
 200                .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG,
 201                .sleep_ctrl_mask = AS3722_LDO2_EXT_ENABLE_MASK,
 202                .n_voltages = AS3722_LDO_NUM_VOLT,
 203        },
 204        {
 205                .regulator_id = AS3722_REGULATOR_ID_LDO3,
 206                .name = "as3722-ldo3",
 207                .sname = "vin-ldo3-4",
 208                .vsel_reg = AS3722_LDO3_VOLTAGE_REG,
 209                .vsel_mask = AS3722_LDO3_VSEL_MASK,
 210                .enable_reg = AS3722_LDOCONTROL0_REG,
 211                .enable_mask = AS3722_LDO3_CTRL,
 212                .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG,
 213                .sleep_ctrl_mask = AS3722_LDO3_EXT_ENABLE_MASK,
 214                .n_voltages = AS3722_LDO3_NUM_VOLT,
 215        },
 216        {
 217                .regulator_id = AS3722_REGULATOR_ID_LDO4,
 218                .name = "as3722-ldo4",
 219                .sname = "vin-ldo3-4",
 220                .vsel_reg = AS3722_LDO4_VOLTAGE_REG,
 221                .vsel_mask = AS3722_LDO_VSEL_MASK,
 222                .enable_reg = AS3722_LDOCONTROL0_REG,
 223                .enable_mask = AS3722_LDO4_CTRL,
 224                .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG,
 225                .sleep_ctrl_mask = AS3722_LDO4_EXT_ENABLE_MASK,
 226                .n_voltages = AS3722_LDO_NUM_VOLT,
 227        },
 228        {
 229                .regulator_id = AS3722_REGULATOR_ID_LDO5,
 230                .name = "as3722-ldo5",
 231                .sname = "vin-ldo2-5-7",
 232                .vsel_reg = AS3722_LDO5_VOLTAGE_REG,
 233                .vsel_mask = AS3722_LDO_VSEL_MASK,
 234                .enable_reg = AS3722_LDOCONTROL0_REG,
 235                .enable_mask = AS3722_LDO5_CTRL,
 236                .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG,
 237                .sleep_ctrl_mask = AS3722_LDO5_EXT_ENABLE_MASK,
 238                .n_voltages = AS3722_LDO_NUM_VOLT,
 239        },
 240        {
 241                .regulator_id = AS3722_REGULATOR_ID_LDO6,
 242                .name = "as3722-ldo6",
 243                .sname = "vin-ldo1-6",
 244                .vsel_reg = AS3722_LDO6_VOLTAGE_REG,
 245                .vsel_mask = AS3722_LDO_VSEL_MASK,
 246                .enable_reg = AS3722_LDOCONTROL0_REG,
 247                .enable_mask = AS3722_LDO6_CTRL,
 248                .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG,
 249                .sleep_ctrl_mask = AS3722_LDO6_EXT_ENABLE_MASK,
 250                .n_voltages = AS3722_LDO_NUM_VOLT,
 251        },
 252        {
 253                .regulator_id = AS3722_REGULATOR_ID_LDO7,
 254                .name = "as3722-ldo7",
 255                .sname = "vin-ldo2-5-7",
 256                .vsel_reg = AS3722_LDO7_VOLTAGE_REG,
 257                .vsel_mask = AS3722_LDO_VSEL_MASK,
 258                .enable_reg = AS3722_LDOCONTROL0_REG,
 259                .enable_mask = AS3722_LDO7_CTRL,
 260                .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG,
 261                .sleep_ctrl_mask = AS3722_LDO7_EXT_ENABLE_MASK,
 262                .n_voltages = AS3722_LDO_NUM_VOLT,
 263        },
 264        {
 265                .regulator_id = AS3722_REGULATOR_ID_LDO9,
 266                .name = "as3722-ldo9",
 267                .sname = "vin-ldo9-10",
 268                .vsel_reg = AS3722_LDO9_VOLTAGE_REG,
 269                .vsel_mask = AS3722_LDO_VSEL_MASK,
 270                .enable_reg = AS3722_LDOCONTROL1_REG,
 271                .enable_mask = AS3722_LDO9_CTRL,
 272                .sleep_ctrl_reg = AS3722_ENABLE_CTRL5_REG,
 273                .sleep_ctrl_mask = AS3722_LDO9_EXT_ENABLE_MASK,
 274                .n_voltages = AS3722_LDO_NUM_VOLT,
 275        },
 276        {
 277                .regulator_id = AS3722_REGULATOR_ID_LDO10,
 278                .name = "as3722-ldo10",
 279                .sname = "vin-ldo9-10",
 280                .vsel_reg = AS3722_LDO10_VOLTAGE_REG,
 281                .vsel_mask = AS3722_LDO_VSEL_MASK,
 282                .enable_reg = AS3722_LDOCONTROL1_REG,
 283                .enable_mask = AS3722_LDO10_CTRL,
 284                .sleep_ctrl_reg = AS3722_ENABLE_CTRL5_REG,
 285                .sleep_ctrl_mask = AS3722_LDO10_EXT_ENABLE_MASK,
 286                .n_voltages = AS3722_LDO_NUM_VOLT,
 287        },
 288        {
 289                .regulator_id = AS3722_REGULATOR_ID_LDO11,
 290                .name = "as3722-ldo11",
 291                .sname = "vin-ldo11",
 292                .vsel_reg = AS3722_LDO11_VOLTAGE_REG,
 293                .vsel_mask = AS3722_LDO_VSEL_MASK,
 294                .enable_reg = AS3722_LDOCONTROL1_REG,
 295                .enable_mask = AS3722_LDO11_CTRL,
 296                .sleep_ctrl_reg = AS3722_ENABLE_CTRL5_REG,
 297                .sleep_ctrl_mask = AS3722_LDO11_EXT_ENABLE_MASK,
 298                .n_voltages = AS3722_LDO_NUM_VOLT,
 299        },
 300};
 301
 302static const unsigned int as3722_ldo_current[] = { 150000, 300000 };
 303static const unsigned int as3722_sd016_current[] = {
 304        2500000, 3000000, 3500000
 305};
 306
 307static const struct regulator_ops as3722_ldo0_ops = {
 308        .is_enabled = regulator_is_enabled_regmap,
 309        .enable = regulator_enable_regmap,
 310        .disable = regulator_disable_regmap,
 311        .list_voltage = regulator_list_voltage_linear,
 312        .get_voltage_sel = regulator_get_voltage_sel_regmap,
 313        .set_voltage_sel = regulator_set_voltage_sel_regmap,
 314        .get_current_limit = regulator_get_current_limit_regmap,
 315        .set_current_limit = regulator_set_current_limit_regmap,
 316};
 317
 318static const struct regulator_ops as3722_ldo0_extcntrl_ops = {
 319        .list_voltage = regulator_list_voltage_linear,
 320        .get_voltage_sel = regulator_get_voltage_sel_regmap,
 321        .set_voltage_sel = regulator_set_voltage_sel_regmap,
 322        .get_current_limit = regulator_get_current_limit_regmap,
 323        .set_current_limit = regulator_set_current_limit_regmap,
 324};
 325
 326static int as3722_ldo3_set_tracking_mode(struct as3722_regulators *as3722_reg,
 327                int id, u8 mode)
 328{
 329        struct as3722 *as3722 = as3722_reg->as3722;
 330
 331        switch (mode) {
 332        case AS3722_LDO3_MODE_PMOS:
 333        case AS3722_LDO3_MODE_PMOS_TRACKING:
 334        case AS3722_LDO3_MODE_NMOS:
 335        case AS3722_LDO3_MODE_SWITCH:
 336                return as3722_update_bits(as3722,
 337                        as3722_reg_lookup[id].vsel_reg,
 338                        AS3722_LDO3_MODE_MASK, mode);
 339
 340        default:
 341                return -EINVAL;
 342        }
 343}
 344
 345static int as3722_ldo3_get_current_limit(struct regulator_dev *rdev)
 346{
 347        return 150000;
 348}
 349
 350static const struct regulator_ops as3722_ldo3_ops = {
 351        .is_enabled = regulator_is_enabled_regmap,
 352        .enable = regulator_enable_regmap,
 353        .disable = regulator_disable_regmap,
 354        .list_voltage = regulator_list_voltage_linear,
 355        .get_voltage_sel = regulator_get_voltage_sel_regmap,
 356        .set_voltage_sel = regulator_set_voltage_sel_regmap,
 357        .get_current_limit = as3722_ldo3_get_current_limit,
 358};
 359
 360static const struct regulator_ops as3722_ldo3_extcntrl_ops = {
 361        .list_voltage = regulator_list_voltage_linear,
 362        .get_voltage_sel = regulator_get_voltage_sel_regmap,
 363        .set_voltage_sel = regulator_set_voltage_sel_regmap,
 364        .get_current_limit = as3722_ldo3_get_current_limit,
 365};
 366
 367static const struct regulator_ops as3722_ldo6_ops = {
 368        .is_enabled = regulator_is_enabled_regmap,
 369        .enable = regulator_enable_regmap,
 370        .disable = regulator_disable_regmap,
 371        .map_voltage = regulator_map_voltage_linear_range,
 372        .set_voltage_sel = regulator_set_voltage_sel_regmap,
 373        .get_voltage_sel = regulator_get_voltage_sel_regmap,
 374        .list_voltage = regulator_list_voltage_linear_range,
 375        .get_current_limit = regulator_get_current_limit_regmap,
 376        .set_current_limit = regulator_set_current_limit_regmap,
 377        .get_bypass = regulator_get_bypass_regmap,
 378        .set_bypass = regulator_set_bypass_regmap,
 379};
 380
 381static const struct regulator_ops as3722_ldo6_extcntrl_ops = {
 382        .map_voltage = regulator_map_voltage_linear_range,
 383        .set_voltage_sel = regulator_set_voltage_sel_regmap,
 384        .get_voltage_sel = regulator_get_voltage_sel_regmap,
 385        .list_voltage = regulator_list_voltage_linear_range,
 386        .get_current_limit = regulator_get_current_limit_regmap,
 387        .set_current_limit = regulator_set_current_limit_regmap,
 388        .get_bypass = regulator_get_bypass_regmap,
 389        .set_bypass = regulator_set_bypass_regmap,
 390};
 391
 392static const struct linear_range as3722_ldo_ranges[] = {
 393        REGULATOR_LINEAR_RANGE(0, 0x00, 0x00, 0),
 394        REGULATOR_LINEAR_RANGE(825000, 0x01, 0x24, 25000),
 395        REGULATOR_LINEAR_RANGE(1725000, 0x40, 0x7F, 25000),
 396};
 397
 398static const struct regulator_ops as3722_ldo_ops = {
 399        .is_enabled = regulator_is_enabled_regmap,
 400        .enable = regulator_enable_regmap,
 401        .disable = regulator_disable_regmap,
 402        .map_voltage = regulator_map_voltage_linear_range,
 403        .set_voltage_sel = regulator_set_voltage_sel_regmap,
 404        .get_voltage_sel = regulator_get_voltage_sel_regmap,
 405        .list_voltage = regulator_list_voltage_linear_range,
 406        .get_current_limit = regulator_get_current_limit_regmap,
 407        .set_current_limit = regulator_set_current_limit_regmap,
 408};
 409
 410static const struct regulator_ops as3722_ldo_extcntrl_ops = {
 411        .map_voltage = regulator_map_voltage_linear_range,
 412        .set_voltage_sel = regulator_set_voltage_sel_regmap,
 413        .get_voltage_sel = regulator_get_voltage_sel_regmap,
 414        .list_voltage = regulator_list_voltage_linear_range,
 415        .get_current_limit = regulator_get_current_limit_regmap,
 416        .set_current_limit = regulator_set_current_limit_regmap,
 417};
 418
 419static unsigned int as3722_sd_get_mode(struct regulator_dev *rdev)
 420{
 421        struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
 422        struct as3722 *as3722 = as3722_regs->as3722;
 423        int id = rdev_get_id(rdev);
 424        u32 val;
 425        int ret;
 426
 427        if (!as3722_reg_lookup[id].control_reg)
 428                return -ENOTSUPP;
 429
 430        ret = as3722_read(as3722, as3722_reg_lookup[id].control_reg, &val);
 431        if (ret < 0) {
 432                dev_err(as3722_regs->dev, "Reg 0x%02x read failed: %d\n",
 433                        as3722_reg_lookup[id].control_reg, ret);
 434                return ret;
 435        }
 436
 437        if (val & as3722_reg_lookup[id].mode_mask)
 438                return REGULATOR_MODE_FAST;
 439        else
 440                return REGULATOR_MODE_NORMAL;
 441}
 442
 443static int as3722_sd_set_mode(struct regulator_dev *rdev,
 444                unsigned int mode)
 445{
 446        struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
 447        struct as3722 *as3722 = as3722_regs->as3722;
 448        u8 id = rdev_get_id(rdev);
 449        u8 val = 0;
 450        int ret;
 451
 452        if (!as3722_reg_lookup[id].control_reg)
 453                return -ERANGE;
 454
 455        switch (mode) {
 456        case REGULATOR_MODE_FAST:
 457                val = as3722_reg_lookup[id].mode_mask;
 458                fallthrough;
 459        case REGULATOR_MODE_NORMAL:
 460                break;
 461        default:
 462                return -EINVAL;
 463        }
 464
 465        ret = as3722_update_bits(as3722, as3722_reg_lookup[id].control_reg,
 466                        as3722_reg_lookup[id].mode_mask, val);
 467        if (ret < 0) {
 468                dev_err(as3722_regs->dev, "Reg 0x%02x update failed: %d\n",
 469                        as3722_reg_lookup[id].control_reg, ret);
 470                return ret;
 471        }
 472        return ret;
 473}
 474
 475static bool as3722_sd0_is_low_voltage(struct as3722_regulators *as3722_regs)
 476{
 477        int err;
 478        unsigned val;
 479
 480        err = as3722_read(as3722_regs->as3722, AS3722_FUSE7_REG, &val);
 481        if (err < 0) {
 482                dev_err(as3722_regs->dev, "Reg 0x%02x read failed: %d\n",
 483                        AS3722_FUSE7_REG, err);
 484                return false;
 485        }
 486        if (val & AS3722_FUSE7_SD0_LOW_VOLTAGE)
 487                return true;
 488        return false;
 489}
 490
 491static const struct linear_range as3722_sd2345_ranges[] = {
 492        REGULATOR_LINEAR_RANGE(0, 0x00, 0x00, 0),
 493        REGULATOR_LINEAR_RANGE(612500, 0x01, 0x40, 12500),
 494        REGULATOR_LINEAR_RANGE(1425000, 0x41, 0x70, 25000),
 495        REGULATOR_LINEAR_RANGE(2650000, 0x71, 0x7F, 50000),
 496};
 497
 498static const struct regulator_ops as3722_sd016_ops = {
 499        .is_enabled = regulator_is_enabled_regmap,
 500        .enable = regulator_enable_regmap,
 501        .disable = regulator_disable_regmap,
 502        .list_voltage = regulator_list_voltage_linear,
 503        .map_voltage = regulator_map_voltage_linear,
 504        .get_voltage_sel = regulator_get_voltage_sel_regmap,
 505        .set_voltage_sel = regulator_set_voltage_sel_regmap,
 506        .get_current_limit = regulator_get_current_limit_regmap,
 507        .set_current_limit = regulator_set_current_limit_regmap,
 508        .get_mode = as3722_sd_get_mode,
 509        .set_mode = as3722_sd_set_mode,
 510};
 511
 512static const struct regulator_ops as3722_sd016_extcntrl_ops = {
 513        .list_voltage = regulator_list_voltage_linear,
 514        .map_voltage = regulator_map_voltage_linear,
 515        .get_voltage_sel = regulator_get_voltage_sel_regmap,
 516        .set_voltage_sel = regulator_set_voltage_sel_regmap,
 517        .get_current_limit = regulator_get_current_limit_regmap,
 518        .set_current_limit = regulator_set_current_limit_regmap,
 519        .get_mode = as3722_sd_get_mode,
 520        .set_mode = as3722_sd_set_mode,
 521};
 522
 523static const struct regulator_ops as3722_sd2345_ops = {
 524        .is_enabled = regulator_is_enabled_regmap,
 525        .enable = regulator_enable_regmap,
 526        .disable = regulator_disable_regmap,
 527        .list_voltage = regulator_list_voltage_linear_range,
 528        .map_voltage = regulator_map_voltage_linear_range,
 529        .set_voltage_sel = regulator_set_voltage_sel_regmap,
 530        .get_voltage_sel = regulator_get_voltage_sel_regmap,
 531        .get_mode = as3722_sd_get_mode,
 532        .set_mode = as3722_sd_set_mode,
 533};
 534
 535static const struct regulator_ops as3722_sd2345_extcntrl_ops = {
 536        .list_voltage = regulator_list_voltage_linear_range,
 537        .map_voltage = regulator_map_voltage_linear_range,
 538        .set_voltage_sel = regulator_set_voltage_sel_regmap,
 539        .get_voltage_sel = regulator_get_voltage_sel_regmap,
 540        .get_mode = as3722_sd_get_mode,
 541        .set_mode = as3722_sd_set_mode,
 542};
 543
 544static int as3722_extreg_init(struct as3722_regulators *as3722_regs, int id,
 545                int ext_pwr_ctrl)
 546{
 547        int ret;
 548        unsigned int val;
 549
 550        if ((ext_pwr_ctrl < AS3722_EXT_CONTROL_ENABLE1) ||
 551                (ext_pwr_ctrl > AS3722_EXT_CONTROL_ENABLE3))
 552                return -EINVAL;
 553
 554        val =  ext_pwr_ctrl << (ffs(as3722_reg_lookup[id].sleep_ctrl_mask) - 1);
 555        ret = as3722_update_bits(as3722_regs->as3722,
 556                        as3722_reg_lookup[id].sleep_ctrl_reg,
 557                        as3722_reg_lookup[id].sleep_ctrl_mask, val);
 558        if (ret < 0)
 559                dev_err(as3722_regs->dev, "Reg 0x%02x update failed: %d\n",
 560                        as3722_reg_lookup[id].sleep_ctrl_reg, ret);
 561        return ret;
 562}
 563
 564static struct of_regulator_match as3722_regulator_matches[] = {
 565        { .name = "sd0", },
 566        { .name = "sd1", },
 567        { .name = "sd2", },
 568        { .name = "sd3", },
 569        { .name = "sd4", },
 570        { .name = "sd5", },
 571        { .name = "sd6", },
 572        { .name = "ldo0", },
 573        { .name = "ldo1", },
 574        { .name = "ldo2", },
 575        { .name = "ldo3", },
 576        { .name = "ldo4", },
 577        { .name = "ldo5", },
 578        { .name = "ldo6", },
 579        { .name = "ldo7", },
 580        { .name = "ldo9", },
 581        { .name = "ldo10", },
 582        { .name = "ldo11", },
 583};
 584
 585static int as3722_get_regulator_dt_data(struct platform_device *pdev,
 586                struct as3722_regulators *as3722_regs)
 587{
 588        struct device_node *np;
 589        struct as3722_regulator_config_data *reg_config;
 590        u32 prop;
 591        int id;
 592        int ret;
 593
 594        np = of_get_child_by_name(pdev->dev.parent->of_node, "regulators");
 595        if (!np) {
 596                dev_err(&pdev->dev, "Device is not having regulators node\n");
 597                return -ENODEV;
 598        }
 599        pdev->dev.of_node = np;
 600
 601        ret = of_regulator_match(&pdev->dev, np, as3722_regulator_matches,
 602                        ARRAY_SIZE(as3722_regulator_matches));
 603        of_node_put(np);
 604        if (ret < 0) {
 605                dev_err(&pdev->dev, "Parsing of regulator node failed: %d\n",
 606                        ret);
 607                return ret;
 608        }
 609
 610        for (id = 0; id < ARRAY_SIZE(as3722_regulator_matches); ++id) {
 611                struct device_node *reg_node;
 612
 613                reg_config = &as3722_regs->reg_config_data[id];
 614                reg_config->reg_init = as3722_regulator_matches[id].init_data;
 615                reg_node = as3722_regulator_matches[id].of_node;
 616
 617                if (!reg_config->reg_init || !reg_node)
 618                        continue;
 619
 620                ret = of_property_read_u32(reg_node, "ams,ext-control", &prop);
 621                if (!ret) {
 622                        if (prop < 3)
 623                                reg_config->ext_control = prop;
 624                        else
 625                                dev_warn(&pdev->dev,
 626                                        "ext-control have invalid option: %u\n",
 627                                        prop);
 628                }
 629                reg_config->enable_tracking =
 630                        of_property_read_bool(reg_node, "ams,enable-tracking");
 631        }
 632        return 0;
 633}
 634
 635static int as3722_regulator_probe(struct platform_device *pdev)
 636{
 637        struct as3722 *as3722 = dev_get_drvdata(pdev->dev.parent);
 638        struct as3722_regulators *as3722_regs;
 639        struct as3722_regulator_config_data *reg_config;
 640        struct regulator_dev *rdev;
 641        struct regulator_config config = { };
 642        const struct regulator_ops *ops;
 643        int id;
 644        int ret;
 645
 646        as3722_regs = devm_kzalloc(&pdev->dev, sizeof(*as3722_regs),
 647                                GFP_KERNEL);
 648        if (!as3722_regs)
 649                return -ENOMEM;
 650
 651        as3722_regs->dev = &pdev->dev;
 652        as3722_regs->as3722 = as3722;
 653        platform_set_drvdata(pdev, as3722_regs);
 654
 655        ret = as3722_get_regulator_dt_data(pdev, as3722_regs);
 656        if (ret < 0)
 657                return ret;
 658
 659        config.dev = &pdev->dev;
 660        config.driver_data = as3722_regs;
 661        config.regmap = as3722->regmap;
 662
 663        for (id = 0; id < AS3722_REGULATOR_ID_MAX; id++) {
 664                struct regulator_desc *desc;
 665
 666                desc = &as3722_regs->desc[id];
 667                reg_config = &as3722_regs->reg_config_data[id];
 668
 669                desc->name = as3722_reg_lookup[id].name;
 670                desc->supply_name = as3722_reg_lookup[id].sname;
 671                desc->id = as3722_reg_lookup[id].regulator_id;
 672                desc->n_voltages = as3722_reg_lookup[id].n_voltages;
 673                desc->type = REGULATOR_VOLTAGE;
 674                desc->owner = THIS_MODULE;
 675                desc->enable_reg = as3722_reg_lookup[id].enable_reg;
 676                desc->enable_mask = as3722_reg_lookup[id].enable_mask;
 677                desc->vsel_reg = as3722_reg_lookup[id].vsel_reg;
 678                desc->vsel_mask = as3722_reg_lookup[id].vsel_mask;
 679                switch (id) {
 680                case AS3722_REGULATOR_ID_LDO0:
 681                        if (reg_config->ext_control)
 682                                ops = &as3722_ldo0_extcntrl_ops;
 683                        else
 684                                ops = &as3722_ldo0_ops;
 685                        desc->min_uV = 825000;
 686                        desc->uV_step = 25000;
 687                        desc->linear_min_sel = 1;
 688                        desc->enable_time = 500;
 689                        desc->curr_table = as3722_ldo_current;
 690                        desc->n_current_limits = ARRAY_SIZE(as3722_ldo_current);
 691                        desc->csel_reg = as3722_reg_lookup[id].vsel_reg;
 692                        desc->csel_mask = AS3722_LDO_ILIMIT_MASK;
 693                        break;
 694                case AS3722_REGULATOR_ID_LDO3:
 695                        if (reg_config->ext_control)
 696                                ops = &as3722_ldo3_extcntrl_ops;
 697                        else
 698                                ops = &as3722_ldo3_ops;
 699                        desc->min_uV = 620000;
 700                        desc->uV_step = 20000;
 701                        desc->linear_min_sel = 1;
 702                        desc->enable_time = 500;
 703                        if (reg_config->enable_tracking) {
 704                                ret = as3722_ldo3_set_tracking_mode(as3722_regs,
 705                                        id, AS3722_LDO3_MODE_PMOS_TRACKING);
 706                                if (ret < 0) {
 707                                        dev_err(&pdev->dev,
 708                                                "LDO3 tracking failed: %d\n",
 709                                                ret);
 710                                        return ret;
 711                                }
 712                        }
 713                        break;
 714                case AS3722_REGULATOR_ID_LDO6:
 715                        if (reg_config->ext_control)
 716                                ops = &as3722_ldo6_extcntrl_ops;
 717                        else
 718                                ops = &as3722_ldo6_ops;
 719                        desc->enable_time = 500;
 720                        desc->bypass_reg = AS3722_LDO6_VOLTAGE_REG;
 721                        desc->bypass_mask = AS3722_LDO_VSEL_MASK;
 722                        desc->bypass_val_on = AS3722_LDO6_VSEL_BYPASS;
 723                        desc->bypass_val_off = AS3722_LDO6_VSEL_BYPASS;
 724                        desc->linear_ranges = as3722_ldo_ranges;
 725                        desc->n_linear_ranges = ARRAY_SIZE(as3722_ldo_ranges);
 726                        desc->curr_table = as3722_ldo_current;
 727                        desc->n_current_limits = ARRAY_SIZE(as3722_ldo_current);
 728                        desc->csel_reg = as3722_reg_lookup[id].vsel_reg;
 729                        desc->csel_mask = AS3722_LDO_ILIMIT_MASK;
 730                        break;
 731                case AS3722_REGULATOR_ID_SD0:
 732                case AS3722_REGULATOR_ID_SD1:
 733                case AS3722_REGULATOR_ID_SD6:
 734                        if (reg_config->ext_control)
 735                                ops = &as3722_sd016_extcntrl_ops;
 736                        else
 737                                ops = &as3722_sd016_ops;
 738                        if (id == AS3722_REGULATOR_ID_SD0 &&
 739                            as3722_sd0_is_low_voltage(as3722_regs)) {
 740                                as3722_regs->desc[id].n_voltages =
 741                                        AS3722_SD0_VSEL_LOW_VOL_MAX + 1;
 742                                as3722_regs->desc[id].min_uV = 410000;
 743                        } else {
 744                                as3722_regs->desc[id].n_voltages =
 745                                        AS3722_SD0_VSEL_MAX + 1;
 746                                as3722_regs->desc[id].min_uV = 610000;
 747                        }
 748                        desc->uV_step = 10000;
 749                        desc->linear_min_sel = 1;
 750                        desc->enable_time = 600;
 751                        desc->curr_table = as3722_sd016_current;
 752                        desc->n_current_limits =
 753                                ARRAY_SIZE(as3722_sd016_current);
 754                        if (id == AS3722_REGULATOR_ID_SD0) {
 755                                desc->csel_reg = AS3722_OVCURRENT_REG;
 756                                desc->csel_mask =
 757                                        AS3722_OVCURRENT_SD0_TRIP_MASK;
 758                        } else if (id == AS3722_REGULATOR_ID_SD1) {
 759                                desc->csel_reg = AS3722_OVCURRENT_REG;
 760                                desc->csel_mask =
 761                                        AS3722_OVCURRENT_SD1_TRIP_MASK;
 762                        } else if (id == AS3722_REGULATOR_ID_SD6) {
 763                                desc->csel_reg = AS3722_OVCURRENT_DEB_REG;
 764                                desc->csel_mask =
 765                                        AS3722_OVCURRENT_SD6_TRIP_MASK;
 766                        }
 767                        break;
 768                case AS3722_REGULATOR_ID_SD2:
 769                case AS3722_REGULATOR_ID_SD3:
 770                case AS3722_REGULATOR_ID_SD4:
 771                case AS3722_REGULATOR_ID_SD5:
 772                        if (reg_config->ext_control)
 773                                ops = &as3722_sd2345_extcntrl_ops;
 774                        else
 775                                ops = &as3722_sd2345_ops;
 776                        desc->linear_ranges = as3722_sd2345_ranges;
 777                        desc->n_linear_ranges =
 778                                        ARRAY_SIZE(as3722_sd2345_ranges);
 779                        break;
 780                default:
 781                        if (reg_config->ext_control)
 782                                ops = &as3722_ldo_extcntrl_ops;
 783                        else
 784                                ops = &as3722_ldo_ops;
 785                        desc->enable_time = 500;
 786                        desc->linear_ranges = as3722_ldo_ranges;
 787                        desc->n_linear_ranges = ARRAY_SIZE(as3722_ldo_ranges);
 788                        desc->curr_table = as3722_ldo_current;
 789                        desc->n_current_limits = ARRAY_SIZE(as3722_ldo_current);
 790                        desc->csel_reg = as3722_reg_lookup[id].vsel_reg;
 791                        desc->csel_mask = AS3722_LDO_ILIMIT_MASK;
 792                        break;
 793                }
 794                desc->ops = ops;
 795                config.init_data = reg_config->reg_init;
 796                config.of_node = as3722_regulator_matches[id].of_node;
 797                rdev = devm_regulator_register(&pdev->dev, desc, &config);
 798                if (IS_ERR(rdev)) {
 799                        ret = PTR_ERR(rdev);
 800                        dev_err(&pdev->dev, "regulator %d register failed %d\n",
 801                                id, ret);
 802                        return ret;
 803                }
 804
 805                if (reg_config->ext_control) {
 806                        ret = regulator_enable_regmap(rdev);
 807                        if (ret < 0) {
 808                                dev_err(&pdev->dev,
 809                                        "Regulator %d enable failed: %d\n",
 810                                        id, ret);
 811                                return ret;
 812                        }
 813                        ret = as3722_extreg_init(as3722_regs, id,
 814                                        reg_config->ext_control);
 815                        if (ret < 0) {
 816                                dev_err(&pdev->dev,
 817                                        "AS3722 ext control failed: %d", ret);
 818                                return ret;
 819                        }
 820                }
 821        }
 822        return 0;
 823}
 824
 825static const struct of_device_id of_as3722_regulator_match[] = {
 826        { .compatible = "ams,as3722-regulator", },
 827        {},
 828};
 829MODULE_DEVICE_TABLE(of, of_as3722_regulator_match);
 830
 831static struct platform_driver as3722_regulator_driver = {
 832        .driver = {
 833                .name = "as3722-regulator",
 834                .of_match_table = of_as3722_regulator_match,
 835        },
 836        .probe = as3722_regulator_probe,
 837};
 838
 839module_platform_driver(as3722_regulator_driver);
 840
 841MODULE_ALIAS("platform:as3722-regulator");
 842MODULE_DESCRIPTION("AS3722 regulator driver");
 843MODULE_AUTHOR("Florian Lobmaier <florian.lobmaier@ams.com>");
 844MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
 845MODULE_LICENSE("GPL");
 846