linux/drivers/regulator/axp20x-regulator.c
<<
>>
Prefs
   1/*
   2 * AXP20x regulators driver.
   3 *
   4 * Copyright (C) 2013 Carlo Caione <carlo@caione.org>
   5 *
   6 * This file is subject to the terms and conditions of the GNU General
   7 * Public License. See the file "COPYING" in the main directory of this
   8 * archive for more details.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13 * GNU General Public License for more details.
  14 */
  15
  16#include <linux/err.h>
  17#include <linux/init.h>
  18#include <linux/module.h>
  19#include <linux/of.h>
  20#include <linux/of_device.h>
  21#include <linux/platform_device.h>
  22#include <linux/regmap.h>
  23#include <linux/mfd/axp20x.h>
  24#include <linux/regulator/driver.h>
  25#include <linux/regulator/of_regulator.h>
  26
  27#define AXP20X_IO_ENABLED               0x03
  28#define AXP20X_IO_DISABLED              0x07
  29
  30#define AXP22X_IO_ENABLED               0x03
  31#define AXP22X_IO_DISABLED              0x04
  32
  33#define AXP20X_WORKMODE_DCDC2_MASK      BIT(2)
  34#define AXP20X_WORKMODE_DCDC3_MASK      BIT(1)
  35#define AXP22X_WORKMODE_DCDCX_MASK(x)   BIT(x)
  36
  37#define AXP20X_FREQ_DCDC_MASK           0x0f
  38
  39#define AXP22X_MISC_N_VBUSEN_FUNC       BIT(4)
  40
  41#define AXP_DESC_IO(_family, _id, _match, _supply, _min, _max, _step, _vreg,    \
  42                    _vmask, _ereg, _emask, _enable_val, _disable_val)           \
  43        [_family##_##_id] = {                                                   \
  44                .name           = (_match),                                     \
  45                .supply_name    = (_supply),                                    \
  46                .of_match       = of_match_ptr(_match),                         \
  47                .regulators_node = of_match_ptr("regulators"),                  \
  48                .type           = REGULATOR_VOLTAGE,                            \
  49                .id             = _family##_##_id,                              \
  50                .n_voltages     = (((_max) - (_min)) / (_step) + 1),            \
  51                .owner          = THIS_MODULE,                                  \
  52                .min_uV         = (_min) * 1000,                                \
  53                .uV_step        = (_step) * 1000,                               \
  54                .vsel_reg       = (_vreg),                                      \
  55                .vsel_mask      = (_vmask),                                     \
  56                .enable_reg     = (_ereg),                                      \
  57                .enable_mask    = (_emask),                                     \
  58                .enable_val     = (_enable_val),                                \
  59                .disable_val    = (_disable_val),                               \
  60                .ops            = &axp20x_ops,                                  \
  61        }
  62
  63#define AXP_DESC(_family, _id, _match, _supply, _min, _max, _step, _vreg,       \
  64                 _vmask, _ereg, _emask)                                         \
  65        [_family##_##_id] = {                                                   \
  66                .name           = (_match),                                     \
  67                .supply_name    = (_supply),                                    \
  68                .of_match       = of_match_ptr(_match),                         \
  69                .regulators_node = of_match_ptr("regulators"),                  \
  70                .type           = REGULATOR_VOLTAGE,                            \
  71                .id             = _family##_##_id,                              \
  72                .n_voltages     = (((_max) - (_min)) / (_step) + 1),            \
  73                .owner          = THIS_MODULE,                                  \
  74                .min_uV         = (_min) * 1000,                                \
  75                .uV_step        = (_step) * 1000,                               \
  76                .vsel_reg       = (_vreg),                                      \
  77                .vsel_mask      = (_vmask),                                     \
  78                .enable_reg     = (_ereg),                                      \
  79                .enable_mask    = (_emask),                                     \
  80                .ops            = &axp20x_ops,                                  \
  81        }
  82
  83#define AXP_DESC_SW(_family, _id, _match, _supply, _ereg, _emask)               \
  84        [_family##_##_id] = {                                                   \
  85                .name           = (_match),                                     \
  86                .supply_name    = (_supply),                                    \
  87                .of_match       = of_match_ptr(_match),                         \
  88                .regulators_node = of_match_ptr("regulators"),                  \
  89                .type           = REGULATOR_VOLTAGE,                            \
  90                .id             = _family##_##_id,                              \
  91                .owner          = THIS_MODULE,                                  \
  92                .enable_reg     = (_ereg),                                      \
  93                .enable_mask    = (_emask),                                     \
  94                .ops            = &axp20x_ops_sw,                               \
  95        }
  96
  97#define AXP_DESC_FIXED(_family, _id, _match, _supply, _volt)                    \
  98        [_family##_##_id] = {                                                   \
  99                .name           = (_match),                                     \
 100                .supply_name    = (_supply),                                    \
 101                .of_match       = of_match_ptr(_match),                         \
 102                .regulators_node = of_match_ptr("regulators"),                  \
 103                .type           = REGULATOR_VOLTAGE,                            \
 104                .id             = _family##_##_id,                              \
 105                .n_voltages     = 1,                                            \
 106                .owner          = THIS_MODULE,                                  \
 107                .min_uV         = (_volt) * 1000,                               \
 108                .ops            = &axp20x_ops_fixed                             \
 109        }
 110
 111#define AXP_DESC_RANGES(_family, _id, _match, _supply, _ranges, _n_voltages,    \
 112                        _vreg, _vmask, _ereg, _emask)                           \
 113        [_family##_##_id] = {                                                   \
 114                .name           = (_match),                                     \
 115                .supply_name    = (_supply),                                    \
 116                .of_match       = of_match_ptr(_match),                         \
 117                .regulators_node = of_match_ptr("regulators"),                  \
 118                .type           = REGULATOR_VOLTAGE,                            \
 119                .id             = _family##_##_id,                              \
 120                .n_voltages     = (_n_voltages),                                \
 121                .owner          = THIS_MODULE,                                  \
 122                .vsel_reg       = (_vreg),                                      \
 123                .vsel_mask      = (_vmask),                                     \
 124                .enable_reg     = (_ereg),                                      \
 125                .enable_mask    = (_emask),                                     \
 126                .linear_ranges  = (_ranges),                                    \
 127                .n_linear_ranges = ARRAY_SIZE(_ranges),                         \
 128                .ops            = &axp20x_ops_range,                            \
 129        }
 130
 131static struct regulator_ops axp20x_ops_fixed = {
 132        .list_voltage           = regulator_list_voltage_linear,
 133};
 134
 135static struct regulator_ops axp20x_ops_range = {
 136        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
 137        .get_voltage_sel        = regulator_get_voltage_sel_regmap,
 138        .list_voltage           = regulator_list_voltage_linear_range,
 139        .enable                 = regulator_enable_regmap,
 140        .disable                = regulator_disable_regmap,
 141        .is_enabled             = regulator_is_enabled_regmap,
 142};
 143
 144static struct regulator_ops axp20x_ops = {
 145        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
 146        .get_voltage_sel        = regulator_get_voltage_sel_regmap,
 147        .list_voltage           = regulator_list_voltage_linear,
 148        .enable                 = regulator_enable_regmap,
 149        .disable                = regulator_disable_regmap,
 150        .is_enabled             = regulator_is_enabled_regmap,
 151};
 152
 153static struct regulator_ops axp20x_ops_sw = {
 154        .enable                 = regulator_enable_regmap,
 155        .disable                = regulator_disable_regmap,
 156        .is_enabled             = regulator_is_enabled_regmap,
 157};
 158
 159static const struct regulator_linear_range axp20x_ldo4_ranges[] = {
 160        REGULATOR_LINEAR_RANGE(1250000, 0x0, 0x0, 0),
 161        REGULATOR_LINEAR_RANGE(1300000, 0x1, 0x8, 100000),
 162        REGULATOR_LINEAR_RANGE(2500000, 0x9, 0x9, 0),
 163        REGULATOR_LINEAR_RANGE(2700000, 0xa, 0xb, 100000),
 164        REGULATOR_LINEAR_RANGE(3000000, 0xc, 0xf, 100000),
 165};
 166
 167static const struct regulator_desc axp20x_regulators[] = {
 168        AXP_DESC(AXP20X, DCDC2, "dcdc2", "vin2", 700, 2275, 25,
 169                 AXP20X_DCDC2_V_OUT, 0x3f, AXP20X_PWR_OUT_CTRL, 0x10),
 170        AXP_DESC(AXP20X, DCDC3, "dcdc3", "vin3", 700, 3500, 25,
 171                 AXP20X_DCDC3_V_OUT, 0x7f, AXP20X_PWR_OUT_CTRL, 0x02),
 172        AXP_DESC_FIXED(AXP20X, LDO1, "ldo1", "acin", 1300),
 173        AXP_DESC(AXP20X, LDO2, "ldo2", "ldo24in", 1800, 3300, 100,
 174                 AXP20X_LDO24_V_OUT, 0xf0, AXP20X_PWR_OUT_CTRL, 0x04),
 175        AXP_DESC(AXP20X, LDO3, "ldo3", "ldo3in", 700, 3500, 25,
 176                 AXP20X_LDO3_V_OUT, 0x7f, AXP20X_PWR_OUT_CTRL, 0x40),
 177        AXP_DESC_RANGES(AXP20X, LDO4, "ldo4", "ldo24in", axp20x_ldo4_ranges,
 178                        16, AXP20X_LDO24_V_OUT, 0x0f, AXP20X_PWR_OUT_CTRL,
 179                        0x08),
 180        AXP_DESC_IO(AXP20X, LDO5, "ldo5", "ldo5in", 1800, 3300, 100,
 181                    AXP20X_LDO5_V_OUT, 0xf0, AXP20X_GPIO0_CTRL, 0x07,
 182                    AXP20X_IO_ENABLED, AXP20X_IO_DISABLED),
 183};
 184
 185static const struct regulator_desc axp22x_regulators[] = {
 186        AXP_DESC(AXP22X, DCDC1, "dcdc1", "vin1", 1600, 3400, 100,
 187                 AXP22X_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(1)),
 188        AXP_DESC(AXP22X, DCDC2, "dcdc2", "vin2", 600, 1540, 20,
 189                 AXP22X_DCDC2_V_OUT, 0x3f, AXP22X_PWR_OUT_CTRL1, BIT(2)),
 190        AXP_DESC(AXP22X, DCDC3, "dcdc3", "vin3", 600, 1860, 20,
 191                 AXP22X_DCDC3_V_OUT, 0x3f, AXP22X_PWR_OUT_CTRL1, BIT(3)),
 192        AXP_DESC(AXP22X, DCDC4, "dcdc4", "vin4", 600, 1540, 20,
 193                 AXP22X_DCDC4_V_OUT, 0x3f, AXP22X_PWR_OUT_CTRL1, BIT(4)),
 194        AXP_DESC(AXP22X, DCDC5, "dcdc5", "vin5", 1000, 2550, 50,
 195                 AXP22X_DCDC5_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(5)),
 196        /* secondary switchable output of DCDC1 */
 197        AXP_DESC_SW(AXP22X, DC1SW, "dc1sw", NULL, AXP22X_PWR_OUT_CTRL2,
 198                    BIT(7)),
 199        /* LDO regulator internally chained to DCDC5 */
 200        AXP_DESC(AXP22X, DC5LDO, "dc5ldo", NULL, 700, 1400, 100,
 201                 AXP22X_DC5LDO_V_OUT, 0x7, AXP22X_PWR_OUT_CTRL1, BIT(0)),
 202        AXP_DESC(AXP22X, ALDO1, "aldo1", "aldoin", 700, 3300, 100,
 203                 AXP22X_ALDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(6)),
 204        AXP_DESC(AXP22X, ALDO2, "aldo2", "aldoin", 700, 3300, 100,
 205                 AXP22X_ALDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(7)),
 206        AXP_DESC(AXP22X, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
 207                 AXP22X_ALDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(7)),
 208        AXP_DESC(AXP22X, DLDO1, "dldo1", "dldoin", 700, 3300, 100,
 209                 AXP22X_DLDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(3)),
 210        AXP_DESC(AXP22X, DLDO2, "dldo2", "dldoin", 700, 3300, 100,
 211                 AXP22X_DLDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(4)),
 212        AXP_DESC(AXP22X, DLDO3, "dldo3", "dldoin", 700, 3300, 100,
 213                 AXP22X_DLDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(5)),
 214        AXP_DESC(AXP22X, DLDO4, "dldo4", "dldoin", 700, 3300, 100,
 215                 AXP22X_DLDO4_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(6)),
 216        AXP_DESC(AXP22X, ELDO1, "eldo1", "eldoin", 700, 3300, 100,
 217                 AXP22X_ELDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(0)),
 218        AXP_DESC(AXP22X, ELDO2, "eldo2", "eldoin", 700, 3300, 100,
 219                 AXP22X_ELDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(1)),
 220        AXP_DESC(AXP22X, ELDO3, "eldo3", "eldoin", 700, 3300, 100,
 221                 AXP22X_ELDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(2)),
 222        /* Note the datasheet only guarantees reliable operation up to
 223         * 3.3V, this needs to be enforced via dts provided constraints */
 224        AXP_DESC_IO(AXP22X, LDO_IO0, "ldo_io0", "ips", 700, 3800, 100,
 225                    AXP22X_LDO_IO0_V_OUT, 0x1f, AXP20X_GPIO0_CTRL, 0x07,
 226                    AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
 227        /* Note the datasheet only guarantees reliable operation up to
 228         * 3.3V, this needs to be enforced via dts provided constraints */
 229        AXP_DESC_IO(AXP22X, LDO_IO1, "ldo_io1", "ips", 700, 3800, 100,
 230                    AXP22X_LDO_IO1_V_OUT, 0x1f, AXP20X_GPIO1_CTRL, 0x07,
 231                    AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
 232        AXP_DESC_FIXED(AXP22X, RTC_LDO, "rtc_ldo", "ips", 3000),
 233};
 234
 235static const struct regulator_desc axp22x_drivevbus_regulator = {
 236        .name           = "drivevbus",
 237        .supply_name    = "drivevbus",
 238        .of_match       = of_match_ptr("drivevbus"),
 239        .regulators_node = of_match_ptr("regulators"),
 240        .type           = REGULATOR_VOLTAGE,
 241        .owner          = THIS_MODULE,
 242        .enable_reg     = AXP20X_VBUS_IPSOUT_MGMT,
 243        .enable_mask    = BIT(2),
 244        .ops            = &axp20x_ops_sw,
 245};
 246
 247static const struct regulator_linear_range axp806_dcdca_ranges[] = {
 248        REGULATOR_LINEAR_RANGE(600000, 0x0, 0x32, 10000),
 249        REGULATOR_LINEAR_RANGE(1120000, 0x33, 0x47, 20000),
 250};
 251
 252static const struct regulator_linear_range axp806_dcdcd_ranges[] = {
 253        REGULATOR_LINEAR_RANGE(600000, 0x0, 0x2d, 20000),
 254        REGULATOR_LINEAR_RANGE(1600000, 0x2e, 0x3f, 100000),
 255};
 256
 257static const struct regulator_linear_range axp806_cldo2_ranges[] = {
 258        REGULATOR_LINEAR_RANGE(700000, 0x0, 0x1a, 100000),
 259        REGULATOR_LINEAR_RANGE(3400000, 0x1b, 0x1f, 200000),
 260};
 261
 262static const struct regulator_desc axp806_regulators[] = {
 263        AXP_DESC_RANGES(AXP806, DCDCA, "dcdca", "vina", axp806_dcdca_ranges,
 264                        72, AXP806_DCDCA_V_CTRL, 0x7f, AXP806_PWR_OUT_CTRL1,
 265                        BIT(0)),
 266        AXP_DESC(AXP806, DCDCB, "dcdcb", "vinb", 1000, 2550, 50,
 267                 AXP806_DCDCB_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(1)),
 268        AXP_DESC_RANGES(AXP806, DCDCC, "dcdcc", "vinc", axp806_dcdca_ranges,
 269                        72, AXP806_DCDCC_V_CTRL, 0x7f, AXP806_PWR_OUT_CTRL1,
 270                        BIT(2)),
 271        AXP_DESC_RANGES(AXP806, DCDCD, "dcdcd", "vind", axp806_dcdcd_ranges,
 272                        64, AXP806_DCDCD_V_CTRL, 0x3f, AXP806_PWR_OUT_CTRL1,
 273                        BIT(3)),
 274        AXP_DESC(AXP806, DCDCE, "dcdce", "vine", 1100, 3400, 100,
 275                 AXP806_DCDCB_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(4)),
 276        AXP_DESC(AXP806, ALDO1, "aldo1", "aldoin", 700, 3300, 100,
 277                 AXP806_ALDO1_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(5)),
 278        AXP_DESC(AXP806, ALDO2, "aldo2", "aldoin", 700, 3400, 100,
 279                 AXP806_ALDO2_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(6)),
 280        AXP_DESC(AXP806, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
 281                 AXP806_ALDO3_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(7)),
 282        AXP_DESC(AXP806, BLDO1, "bldo1", "bldoin", 700, 1900, 100,
 283                 AXP806_BLDO1_V_CTRL, 0x0f, AXP806_PWR_OUT_CTRL2, BIT(0)),
 284        AXP_DESC(AXP806, BLDO2, "bldo2", "bldoin", 700, 1900, 100,
 285                 AXP806_BLDO2_V_CTRL, 0x0f, AXP806_PWR_OUT_CTRL2, BIT(1)),
 286        AXP_DESC(AXP806, BLDO3, "bldo3", "bldoin", 700, 1900, 100,
 287                 AXP806_BLDO3_V_CTRL, 0x0f, AXP806_PWR_OUT_CTRL2, BIT(2)),
 288        AXP_DESC(AXP806, BLDO4, "bldo4", "bldoin", 700, 1900, 100,
 289                 AXP806_BLDO4_V_CTRL, 0x0f, AXP806_PWR_OUT_CTRL2, BIT(3)),
 290        AXP_DESC(AXP806, CLDO1, "cldo1", "cldoin", 700, 3300, 100,
 291                 AXP806_CLDO1_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL2, BIT(4)),
 292        AXP_DESC_RANGES(AXP806, CLDO2, "cldo2", "cldoin", axp806_cldo2_ranges,
 293                        32, AXP806_CLDO2_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL2,
 294                        BIT(5)),
 295        AXP_DESC(AXP806, CLDO3, "cldo3", "cldoin", 700, 3300, 100,
 296                 AXP806_CLDO3_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL2, BIT(6)),
 297        AXP_DESC_SW(AXP806, SW, "sw", "swin", AXP806_PWR_OUT_CTRL2, BIT(7)),
 298};
 299
 300static const struct regulator_linear_range axp809_dcdc4_ranges[] = {
 301        REGULATOR_LINEAR_RANGE(600000, 0x0, 0x2f, 20000),
 302        REGULATOR_LINEAR_RANGE(1800000, 0x30, 0x38, 100000),
 303};
 304
 305static const struct regulator_desc axp809_regulators[] = {
 306        AXP_DESC(AXP809, DCDC1, "dcdc1", "vin1", 1600, 3400, 100,
 307                 AXP22X_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(1)),
 308        AXP_DESC(AXP809, DCDC2, "dcdc2", "vin2", 600, 1540, 20,
 309                 AXP22X_DCDC2_V_OUT, 0x3f, AXP22X_PWR_OUT_CTRL1, BIT(2)),
 310        AXP_DESC(AXP809, DCDC3, "dcdc3", "vin3", 600, 1860, 20,
 311                 AXP22X_DCDC3_V_OUT, 0x3f, AXP22X_PWR_OUT_CTRL1, BIT(3)),
 312        AXP_DESC_RANGES(AXP809, DCDC4, "dcdc4", "vin4", axp809_dcdc4_ranges,
 313                        57, AXP22X_DCDC4_V_OUT, 0x3f, AXP22X_PWR_OUT_CTRL1,
 314                        BIT(4)),
 315        AXP_DESC(AXP809, DCDC5, "dcdc5", "vin5", 1000, 2550, 50,
 316                 AXP22X_DCDC5_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(5)),
 317        /* secondary switchable output of DCDC1 */
 318        AXP_DESC_SW(AXP809, DC1SW, "dc1sw", NULL, AXP22X_PWR_OUT_CTRL2,
 319                    BIT(7)),
 320        /* LDO regulator internally chained to DCDC5 */
 321        AXP_DESC(AXP809, DC5LDO, "dc5ldo", NULL, 700, 1400, 100,
 322                 AXP22X_DC5LDO_V_OUT, 0x7, AXP22X_PWR_OUT_CTRL1, BIT(0)),
 323        AXP_DESC(AXP809, ALDO1, "aldo1", "aldoin", 700, 3300, 100,
 324                 AXP22X_ALDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(6)),
 325        AXP_DESC(AXP809, ALDO2, "aldo2", "aldoin", 700, 3300, 100,
 326                 AXP22X_ALDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(7)),
 327        AXP_DESC(AXP809, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
 328                 AXP22X_ALDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(5)),
 329        AXP_DESC_RANGES(AXP809, DLDO1, "dldo1", "dldoin", axp806_cldo2_ranges,
 330                        32, AXP22X_DLDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2,
 331                        BIT(3)),
 332        AXP_DESC(AXP809, DLDO2, "dldo2", "dldoin", 700, 3300, 100,
 333                 AXP22X_DLDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(4)),
 334        AXP_DESC(AXP809, ELDO1, "eldo1", "eldoin", 700, 3300, 100,
 335                 AXP22X_ELDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(0)),
 336        AXP_DESC(AXP809, ELDO2, "eldo2", "eldoin", 700, 3300, 100,
 337                 AXP22X_ELDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(1)),
 338        AXP_DESC(AXP809, ELDO3, "eldo3", "eldoin", 700, 3300, 100,
 339                 AXP22X_ELDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(2)),
 340        AXP_DESC_IO(AXP809, LDO_IO0, "ldo_io0", "ips", 700, 3300, 100,
 341                    AXP22X_LDO_IO0_V_OUT, 0x1f, AXP20X_GPIO0_CTRL, 0x07,
 342                    AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
 343        AXP_DESC_IO(AXP809, LDO_IO1, "ldo_io1", "ips", 700, 3300, 100,
 344                    AXP22X_LDO_IO1_V_OUT, 0x1f, AXP20X_GPIO1_CTRL, 0x07,
 345                    AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
 346        AXP_DESC_FIXED(AXP809, RTC_LDO, "rtc_ldo", "ips", 1800),
 347        AXP_DESC_SW(AXP809, SW, "sw", "swin", AXP22X_PWR_OUT_CTRL2, BIT(6)),
 348};
 349
 350static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
 351{
 352        struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
 353        unsigned int reg = AXP20X_DCDC_FREQ;
 354        u32 min, max, def, step;
 355
 356        switch (axp20x->variant) {
 357        case AXP202_ID:
 358        case AXP209_ID:
 359                min = 750;
 360                max = 1875;
 361                def = 1500;
 362                step = 75;
 363                break;
 364        case AXP806_ID:
 365                /*
 366                 * AXP806 DCDC work frequency setting has the same range and
 367                 * step as AXP22X, but at a different register.
 368                 * Fall through to the check below.
 369                 * (See include/linux/mfd/axp20x.h)
 370                 */
 371                reg = AXP806_DCDC_FREQ_CTRL;
 372        case AXP221_ID:
 373        case AXP223_ID:
 374        case AXP809_ID:
 375                min = 1800;
 376                max = 4050;
 377                def = 3000;
 378                step = 150;
 379                break;
 380        default:
 381                dev_err(&pdev->dev,
 382                        "Setting DCDC frequency for unsupported AXP variant\n");
 383                return -EINVAL;
 384        }
 385
 386        if (dcdcfreq == 0)
 387                dcdcfreq = def;
 388
 389        if (dcdcfreq < min) {
 390                dcdcfreq = min;
 391                dev_warn(&pdev->dev, "DCDC frequency too low. Set to %ukHz\n",
 392                         min);
 393        }
 394
 395        if (dcdcfreq > max) {
 396                dcdcfreq = max;
 397                dev_warn(&pdev->dev, "DCDC frequency too high. Set to %ukHz\n",
 398                         max);
 399        }
 400
 401        dcdcfreq = (dcdcfreq - min) / step;
 402
 403        return regmap_update_bits(axp20x->regmap, reg,
 404                                  AXP20X_FREQ_DCDC_MASK, dcdcfreq);
 405}
 406
 407static int axp20x_regulator_parse_dt(struct platform_device *pdev)
 408{
 409        struct device_node *np, *regulators;
 410        int ret;
 411        u32 dcdcfreq = 0;
 412
 413        np = of_node_get(pdev->dev.parent->of_node);
 414        if (!np)
 415                return 0;
 416
 417        regulators = of_get_child_by_name(np, "regulators");
 418        if (!regulators) {
 419                dev_warn(&pdev->dev, "regulators node not found\n");
 420        } else {
 421                of_property_read_u32(regulators, "x-powers,dcdc-freq", &dcdcfreq);
 422                ret = axp20x_set_dcdc_freq(pdev, dcdcfreq);
 423                if (ret < 0) {
 424                        dev_err(&pdev->dev, "Error setting dcdc frequency: %d\n", ret);
 425                        return ret;
 426                }
 427
 428                of_node_put(regulators);
 429        }
 430
 431        return 0;
 432}
 433
 434static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 workmode)
 435{
 436        struct axp20x_dev *axp20x = rdev_get_drvdata(rdev);
 437        unsigned int reg = AXP20X_DCDC_MODE;
 438        unsigned int mask;
 439
 440        switch (axp20x->variant) {
 441        case AXP202_ID:
 442        case AXP209_ID:
 443                if ((id != AXP20X_DCDC2) && (id != AXP20X_DCDC3))
 444                        return -EINVAL;
 445
 446                mask = AXP20X_WORKMODE_DCDC2_MASK;
 447                if (id == AXP20X_DCDC3)
 448                        mask = AXP20X_WORKMODE_DCDC3_MASK;
 449
 450                workmode <<= ffs(mask) - 1;
 451                break;
 452
 453        case AXP806_ID:
 454                reg = AXP806_DCDC_MODE_CTRL2;
 455                /*
 456                 * AXP806 DCDC regulator IDs have the same range as AXP22X.
 457                 * Fall through to the check below.
 458                 * (See include/linux/mfd/axp20x.h)
 459                 */
 460        case AXP221_ID:
 461        case AXP223_ID:
 462        case AXP809_ID:
 463                if (id < AXP22X_DCDC1 || id > AXP22X_DCDC5)
 464                        return -EINVAL;
 465
 466                mask = AXP22X_WORKMODE_DCDCX_MASK(id - AXP22X_DCDC1);
 467                workmode <<= id - AXP22X_DCDC1;
 468                break;
 469
 470        default:
 471                /* should not happen */
 472                WARN_ON(1);
 473                return -EINVAL;
 474        }
 475
 476        return regmap_update_bits(rdev->regmap, reg, mask, workmode);
 477}
 478
 479/*
 480 * This function checks whether a regulator is part of a poly-phase
 481 * output setup based on the registers settings. Returns true if it is.
 482 */
 483static bool axp20x_is_polyphase_slave(struct axp20x_dev *axp20x, int id)
 484{
 485        u32 reg = 0;
 486
 487        /* Only AXP806 has poly-phase outputs */
 488        if (axp20x->variant != AXP806_ID)
 489                return false;
 490
 491        regmap_read(axp20x->regmap, AXP806_DCDC_MODE_CTRL2, &reg);
 492
 493        switch (id) {
 494        case AXP806_DCDCB:
 495                return (((reg & GENMASK(7, 6)) == BIT(6)) ||
 496                        ((reg & GENMASK(7, 6)) == BIT(7)));
 497        case AXP806_DCDCC:
 498                return ((reg & GENMASK(7, 6)) == BIT(7));
 499        case AXP806_DCDCE:
 500                return !!(reg & BIT(5));
 501        }
 502
 503        return false;
 504}
 505
 506static int axp20x_regulator_probe(struct platform_device *pdev)
 507{
 508        struct regulator_dev *rdev;
 509        struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
 510        const struct regulator_desc *regulators;
 511        struct regulator_config config = {
 512                .dev = pdev->dev.parent,
 513                .regmap = axp20x->regmap,
 514                .driver_data = axp20x,
 515        };
 516        int ret, i, nregulators;
 517        u32 workmode;
 518        const char *dcdc1_name = axp22x_regulators[AXP22X_DCDC1].name;
 519        const char *dcdc5_name = axp22x_regulators[AXP22X_DCDC5].name;
 520        bool drivevbus = false;
 521
 522        switch (axp20x->variant) {
 523        case AXP202_ID:
 524        case AXP209_ID:
 525                regulators = axp20x_regulators;
 526                nregulators = AXP20X_REG_ID_MAX;
 527                break;
 528        case AXP221_ID:
 529        case AXP223_ID:
 530                regulators = axp22x_regulators;
 531                nregulators = AXP22X_REG_ID_MAX;
 532                drivevbus = of_property_read_bool(pdev->dev.parent->of_node,
 533                                                  "x-powers,drive-vbus-en");
 534                break;
 535        case AXP806_ID:
 536                regulators = axp806_regulators;
 537                nregulators = AXP806_REG_ID_MAX;
 538                break;
 539        case AXP809_ID:
 540                regulators = axp809_regulators;
 541                nregulators = AXP809_REG_ID_MAX;
 542                break;
 543        default:
 544                dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n",
 545                        axp20x->variant);
 546                return -EINVAL;
 547        }
 548
 549        /* This only sets the dcdc freq. Ignore any errors */
 550        axp20x_regulator_parse_dt(pdev);
 551
 552        for (i = 0; i < nregulators; i++) {
 553                const struct regulator_desc *desc = &regulators[i];
 554                struct regulator_desc *new_desc;
 555
 556                /*
 557                 * If this regulator is a slave in a poly-phase setup,
 558                 * skip it, as its controls are bound to the master
 559                 * regulator and won't work.
 560                 */
 561                if (axp20x_is_polyphase_slave(axp20x, i))
 562                        continue;
 563
 564                /*
 565                 * Regulators DC1SW and DC5LDO are connected internally,
 566                 * so we have to handle their supply names separately.
 567                 *
 568                 * We always register the regulators in proper sequence,
 569                 * so the supply names are correctly read. See the last
 570                 * part of this loop to see where we save the DT defined
 571                 * name.
 572                 */
 573                if ((regulators == axp22x_regulators && i == AXP22X_DC1SW) ||
 574                    (regulators == axp809_regulators && i == AXP809_DC1SW)) {
 575                        new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc),
 576                                                GFP_KERNEL);
 577                        *new_desc = regulators[i];
 578                        new_desc->supply_name = dcdc1_name;
 579                        desc = new_desc;
 580                }
 581
 582                if ((regulators == axp22x_regulators && i == AXP22X_DC5LDO) ||
 583                    (regulators == axp809_regulators && i == AXP809_DC5LDO)) {
 584                        new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc),
 585                                                GFP_KERNEL);
 586                        *new_desc = regulators[i];
 587                        new_desc->supply_name = dcdc5_name;
 588                        desc = new_desc;
 589                }
 590
 591                rdev = devm_regulator_register(&pdev->dev, desc, &config);
 592                if (IS_ERR(rdev)) {
 593                        dev_err(&pdev->dev, "Failed to register %s\n",
 594                                regulators[i].name);
 595
 596                        return PTR_ERR(rdev);
 597                }
 598
 599                ret = of_property_read_u32(rdev->dev.of_node,
 600                                           "x-powers,dcdc-workmode",
 601                                           &workmode);
 602                if (!ret) {
 603                        if (axp20x_set_dcdc_workmode(rdev, i, workmode))
 604                                dev_err(&pdev->dev, "Failed to set workmode on %s\n",
 605                                        rdev->desc->name);
 606                }
 607
 608                /*
 609                 * Save AXP22X DCDC1 / DCDC5 regulator names for later.
 610                 */
 611                if ((regulators == axp22x_regulators && i == AXP22X_DCDC1) ||
 612                    (regulators == axp809_regulators && i == AXP809_DCDC1))
 613                        of_property_read_string(rdev->dev.of_node,
 614                                                "regulator-name",
 615                                                &dcdc1_name);
 616
 617                if ((regulators == axp22x_regulators && i == AXP22X_DCDC5) ||
 618                    (regulators == axp809_regulators && i == AXP809_DCDC5))
 619                        of_property_read_string(rdev->dev.of_node,
 620                                                "regulator-name",
 621                                                &dcdc5_name);
 622        }
 623
 624        if (drivevbus) {
 625                /* Change N_VBUSEN sense pin to DRIVEVBUS output pin */
 626                regmap_update_bits(axp20x->regmap, AXP20X_OVER_TMP,
 627                                   AXP22X_MISC_N_VBUSEN_FUNC, 0);
 628                rdev = devm_regulator_register(&pdev->dev,
 629                                               &axp22x_drivevbus_regulator,
 630                                               &config);
 631                if (IS_ERR(rdev)) {
 632                        dev_err(&pdev->dev, "Failed to register drivevbus\n");
 633                        return PTR_ERR(rdev);
 634                }
 635        }
 636
 637        return 0;
 638}
 639
 640static struct platform_driver axp20x_regulator_driver = {
 641        .probe  = axp20x_regulator_probe,
 642        .driver = {
 643                .name           = "axp20x-regulator",
 644        },
 645};
 646
 647module_platform_driver(axp20x_regulator_driver);
 648
 649MODULE_LICENSE("GPL v2");
 650MODULE_AUTHOR("Carlo Caione <carlo@caione.org>");
 651MODULE_DESCRIPTION("Regulator Driver for AXP20X PMIC");
 652MODULE_ALIAS("platform:axp20x-regulator");
 653