linux/drivers/regulator/atc260x-regulator.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2//
   3// Regulator driver for ATC260x PMICs
   4//
   5// Copyright (C) 2019 Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
   6// Copyright (C) 2020 Cristian Ciocaltea <cristian.ciocaltea@gmail.com>
   7
   8#include <linux/mfd/atc260x/core.h>
   9#include <linux/module.h>
  10#include <linux/of_device.h>
  11#include <linux/regmap.h>
  12#include <linux/regulator/driver.h>
  13
  14struct atc260x_regulator_data {
  15        int voltage_time_dcdc;
  16        int voltage_time_ldo;
  17};
  18
  19static const struct linear_range atc2603c_dcdc_voltage_ranges[] = {
  20        REGULATOR_LINEAR_RANGE(1300000, 0, 13, 50000),
  21        REGULATOR_LINEAR_RANGE(1950000, 14, 15, 100000),
  22};
  23
  24static const struct linear_range atc2609a_dcdc_voltage_ranges[] = {
  25        REGULATOR_LINEAR_RANGE(600000, 0, 127, 6250),
  26        REGULATOR_LINEAR_RANGE(1400000, 128, 232, 25000),
  27};
  28
  29static const struct linear_range atc2609a_ldo_voltage_ranges0[] = {
  30        REGULATOR_LINEAR_RANGE(700000, 0, 15, 100000),
  31        REGULATOR_LINEAR_RANGE(2100000, 0, 12, 100000),
  32};
  33
  34static const struct linear_range atc2609a_ldo_voltage_ranges1[] = {
  35        REGULATOR_LINEAR_RANGE(850000, 0, 15, 100000),
  36        REGULATOR_LINEAR_RANGE(2100000, 0, 11, 100000),
  37};
  38
  39static const unsigned int atc260x_ldo_voltage_range_sel[] = {
  40        0x0, 0x20,
  41};
  42
  43static int atc260x_dcdc_set_voltage_time_sel(struct regulator_dev *rdev,
  44                                             unsigned int old_selector,
  45                                             unsigned int new_selector)
  46{
  47        struct atc260x_regulator_data *data = rdev_get_drvdata(rdev);
  48
  49        if (new_selector > old_selector)
  50                return data->voltage_time_dcdc;
  51
  52        return 0;
  53}
  54
  55static int atc260x_ldo_set_voltage_time_sel(struct regulator_dev *rdev,
  56                                            unsigned int old_selector,
  57                                            unsigned int new_selector)
  58{
  59        struct atc260x_regulator_data *data = rdev_get_drvdata(rdev);
  60
  61        if (new_selector > old_selector)
  62                return data->voltage_time_ldo;
  63
  64        return 0;
  65}
  66
  67static const struct regulator_ops atc260x_dcdc_ops = {
  68        .enable = regulator_enable_regmap,
  69        .disable = regulator_disable_regmap,
  70        .is_enabled = regulator_is_enabled_regmap,
  71        .list_voltage = regulator_list_voltage_linear,
  72        .set_voltage_sel = regulator_set_voltage_sel_regmap,
  73        .get_voltage_sel = regulator_get_voltage_sel_regmap,
  74        .set_voltage_time_sel = atc260x_dcdc_set_voltage_time_sel,
  75};
  76
  77static const struct regulator_ops atc260x_ldo_ops = {
  78        .enable = regulator_enable_regmap,
  79        .disable = regulator_disable_regmap,
  80        .is_enabled = regulator_is_enabled_regmap,
  81        .list_voltage = regulator_list_voltage_linear,
  82        .set_voltage_sel = regulator_set_voltage_sel_regmap,
  83        .get_voltage_sel = regulator_get_voltage_sel_regmap,
  84        .set_voltage_time_sel = atc260x_ldo_set_voltage_time_sel,
  85};
  86
  87static const struct regulator_ops atc260x_ldo_bypass_ops = {
  88        .enable = regulator_enable_regmap,
  89        .disable = regulator_disable_regmap,
  90        .is_enabled = regulator_is_enabled_regmap,
  91        .list_voltage = regulator_list_voltage_linear,
  92        .set_voltage_sel = regulator_set_voltage_sel_regmap,
  93        .get_voltage_sel = regulator_get_voltage_sel_regmap,
  94        .set_voltage_time_sel = atc260x_ldo_set_voltage_time_sel,
  95        .set_bypass = regulator_set_bypass_regmap,
  96        .get_bypass = regulator_get_bypass_regmap,
  97};
  98
  99static const struct regulator_ops atc260x_ldo_bypass_discharge_ops = {
 100        .enable = regulator_enable_regmap,
 101        .disable = regulator_disable_regmap,
 102        .is_enabled = regulator_is_enabled_regmap,
 103        .list_voltage = regulator_list_voltage_linear,
 104        .set_voltage_sel = regulator_set_voltage_sel_regmap,
 105        .get_voltage_sel = regulator_get_voltage_sel_regmap,
 106        .set_voltage_time_sel = atc260x_ldo_set_voltage_time_sel,
 107        .set_bypass = regulator_set_bypass_regmap,
 108        .get_bypass = regulator_get_bypass_regmap,
 109        .set_active_discharge = regulator_set_active_discharge_regmap,
 110};
 111
 112static const struct regulator_ops atc260x_dcdc_range_ops = {
 113        .enable = regulator_enable_regmap,
 114        .disable = regulator_disable_regmap,
 115        .is_enabled = regulator_is_enabled_regmap,
 116        .list_voltage = regulator_list_voltage_linear_range,
 117        .set_voltage_sel = regulator_set_voltage_sel_regmap,
 118        .get_voltage_sel = regulator_get_voltage_sel_regmap,
 119        .set_voltage_time_sel = atc260x_dcdc_set_voltage_time_sel,
 120};
 121
 122static const struct regulator_ops atc260x_ldo_range_pick_ops = {
 123        .enable = regulator_enable_regmap,
 124        .disable = regulator_disable_regmap,
 125        .is_enabled = regulator_is_enabled_regmap,
 126        .list_voltage = regulator_list_voltage_pickable_linear_range,
 127        .set_voltage_sel = regulator_set_voltage_sel_pickable_regmap,
 128        .get_voltage_sel = regulator_get_voltage_sel_pickable_regmap,
 129        .set_voltage_time_sel = atc260x_ldo_set_voltage_time_sel,
 130};
 131
 132static const struct regulator_ops atc260x_dcdc_fixed_ops = {
 133        .list_voltage = regulator_list_voltage_linear,
 134        .set_voltage_sel = regulator_set_voltage_sel_regmap,
 135        .get_voltage_sel = regulator_get_voltage_sel_regmap,
 136        .set_voltage_time_sel = atc260x_dcdc_set_voltage_time_sel,
 137};
 138
 139static const struct regulator_ops atc260x_ldo_fixed_ops = {
 140        .list_voltage = regulator_list_voltage_linear,
 141        .set_voltage_sel = regulator_set_voltage_sel_regmap,
 142        .get_voltage_sel = regulator_get_voltage_sel_regmap,
 143        .set_voltage_time_sel = atc260x_ldo_set_voltage_time_sel,
 144};
 145
 146static const struct regulator_ops atc260x_no_ops = {
 147};
 148
 149/*
 150 * Note LDO8 is not documented in datasheet (v2.4), but supported
 151 * in the vendor's driver implementation (xapp-le-kernel).
 152 */
 153enum atc2603c_reg_ids {
 154        ATC2603C_ID_DCDC1,
 155        ATC2603C_ID_DCDC2,
 156        ATC2603C_ID_DCDC3,
 157        ATC2603C_ID_LDO1,
 158        ATC2603C_ID_LDO2,
 159        ATC2603C_ID_LDO3,
 160        ATC2603C_ID_LDO5,
 161        ATC2603C_ID_LDO6,
 162        ATC2603C_ID_LDO7,
 163        ATC2603C_ID_LDO8,
 164        ATC2603C_ID_LDO11,
 165        ATC2603C_ID_LDO12,
 166        ATC2603C_ID_SWITCHLDO1,
 167        ATC2603C_ID_MAX,
 168};
 169
 170#define atc2603c_reg_desc_dcdc(num, min, step, n_volt, vsel_h, vsel_l) { \
 171        .name = "DCDC"#num, \
 172        .supply_name = "dcdc"#num, \
 173        .of_match = of_match_ptr("dcdc"#num), \
 174        .regulators_node = of_match_ptr("regulators"), \
 175        .id = ATC2603C_ID_DCDC##num, \
 176        .ops = &atc260x_dcdc_ops, \
 177        .type = REGULATOR_VOLTAGE, \
 178        .min_uV = min, \
 179        .uV_step = step, \
 180        .n_voltages = n_volt, \
 181        .vsel_reg = ATC2603C_PMU_DC##num##_CTL0, \
 182        .vsel_mask = GENMASK(vsel_h, vsel_l), \
 183        .enable_reg = ATC2603C_PMU_DC##num##_CTL0, \
 184        .enable_mask = BIT(15), \
 185        .enable_time = 800, \
 186        .owner = THIS_MODULE, \
 187}
 188
 189#define atc2603c_reg_desc_dcdc_range(num, vsel_h, vsel_l) { \
 190        .name = "DCDC"#num, \
 191        .supply_name = "dcdc"#num, \
 192        .of_match = of_match_ptr("dcdc"#num), \
 193        .regulators_node = of_match_ptr("regulators"), \
 194        .id = ATC2603C_ID_DCDC##num, \
 195        .ops = &atc260x_dcdc_range_ops, \
 196        .type = REGULATOR_VOLTAGE, \
 197        .n_voltages = 16, \
 198        .linear_ranges = atc2603c_dcdc_voltage_ranges, \
 199        .n_linear_ranges = ARRAY_SIZE(atc2603c_dcdc_voltage_ranges), \
 200        .vsel_reg = ATC2603C_PMU_DC##num##_CTL0, \
 201        .vsel_mask = GENMASK(vsel_h, vsel_l), \
 202        .enable_reg = ATC2603C_PMU_DC##num##_CTL0, \
 203        .enable_mask = BIT(15), \
 204        .enable_time = 800, \
 205        .owner = THIS_MODULE, \
 206}
 207
 208#define atc2603c_reg_desc_dcdc_fixed(num, min, step, n_volt, vsel_h, vsel_l) { \
 209        .name = "DCDC"#num, \
 210        .supply_name = "dcdc"#num, \
 211        .of_match = of_match_ptr("dcdc"#num), \
 212        .regulators_node = of_match_ptr("regulators"), \
 213        .id = ATC2603C_ID_DCDC##num, \
 214        .ops = &atc260x_dcdc_fixed_ops, \
 215        .type = REGULATOR_VOLTAGE, \
 216        .min_uV = min, \
 217        .uV_step = step, \
 218        .n_voltages = n_volt, \
 219        .vsel_reg = ATC2603C_PMU_DC##num##_CTL0, \
 220        .vsel_mask = GENMASK(vsel_h, vsel_l), \
 221        .enable_time = 800, \
 222        .owner = THIS_MODULE, \
 223}
 224
 225#define atc2603c_reg_desc_ldo(num, min, step, n_volt, vsel_h, vsel_l) { \
 226        .name = "LDO"#num, \
 227        .supply_name = "ldo"#num, \
 228        .of_match = of_match_ptr("ldo"#num), \
 229        .regulators_node = of_match_ptr("regulators"), \
 230        .id = ATC2603C_ID_LDO##num, \
 231        .ops = &atc260x_ldo_ops, \
 232        .type = REGULATOR_VOLTAGE, \
 233        .min_uV = min, \
 234        .uV_step = step, \
 235        .n_voltages = n_volt, \
 236        .vsel_reg = ATC2603C_PMU_LDO##num##_CTL, \
 237        .vsel_mask = GENMASK(vsel_h, vsel_l), \
 238        .enable_reg = ATC2603C_PMU_LDO##num##_CTL, \
 239        .enable_mask = BIT(0), \
 240        .enable_time = 2000, \
 241        .owner = THIS_MODULE, \
 242}
 243
 244#define atc2603c_reg_desc_ldo_fixed(num, min, step, n_volt, vsel_h, vsel_l) { \
 245        .name = "LDO"#num, \
 246        .supply_name = "ldo"#num, \
 247        .of_match = of_match_ptr("ldo"#num), \
 248        .regulators_node = of_match_ptr("regulators"), \
 249        .id = ATC2603C_ID_LDO##num, \
 250        .ops = &atc260x_ldo_fixed_ops, \
 251        .type = REGULATOR_VOLTAGE, \
 252        .min_uV = min, \
 253        .uV_step = step, \
 254        .n_voltages = n_volt, \
 255        .vsel_reg = ATC2603C_PMU_LDO##num##_CTL, \
 256        .vsel_mask = GENMASK(vsel_h, vsel_l), \
 257        .enable_time = 2000, \
 258        .owner = THIS_MODULE, \
 259}
 260
 261#define atc2603c_reg_desc_ldo_noops(num, vfixed) { \
 262        .name = "LDO"#num, \
 263        .supply_name = "ldo"#num, \
 264        .of_match = of_match_ptr("ldo"#num), \
 265        .regulators_node = of_match_ptr("regulators"), \
 266        .id = ATC2603C_ID_LDO##num, \
 267        .ops = &atc260x_no_ops, \
 268        .type = REGULATOR_VOLTAGE, \
 269        .fixed_uV = vfixed, \
 270        .n_voltages = 1, \
 271        .owner = THIS_MODULE, \
 272}
 273
 274#define atc2603c_reg_desc_ldo_switch(num, min, step, n_volt, vsel_h, vsel_l) { \
 275        .name = "SWITCHLDO"#num, \
 276        .supply_name = "switchldo"#num, \
 277        .of_match = of_match_ptr("switchldo"#num), \
 278        .regulators_node = of_match_ptr("regulators"), \
 279        .id = ATC2603C_ID_SWITCHLDO##num, \
 280        .ops = &atc260x_ldo_bypass_discharge_ops, \
 281        .type = REGULATOR_VOLTAGE, \
 282        .min_uV = min, \
 283        .uV_step = step, \
 284        .n_voltages = n_volt, \
 285        .vsel_reg = ATC2603C_PMU_SWITCH_CTL, \
 286        .vsel_mask = GENMASK(vsel_h, vsel_l), \
 287        .enable_reg = ATC2603C_PMU_SWITCH_CTL, \
 288        .enable_mask = BIT(15), \
 289        .enable_is_inverted = true, \
 290        .enable_time = 2000, \
 291        .bypass_reg = ATC2603C_PMU_SWITCH_CTL, \
 292        .bypass_mask = BIT(5), \
 293        .active_discharge_reg = ATC2603C_PMU_SWITCH_CTL, \
 294        .active_discharge_mask = BIT(1), \
 295        .owner = THIS_MODULE, \
 296}
 297
 298static const struct regulator_desc atc2603c_reg[] = {
 299        atc2603c_reg_desc_dcdc_fixed(1, 700000, 25000, 29, 11, 7),
 300        atc2603c_reg_desc_dcdc_range(2, 12, 8),
 301        atc2603c_reg_desc_dcdc_fixed(3, 2600000, 100000, 8, 11, 9),
 302        atc2603c_reg_desc_ldo_fixed(1, 2600000, 100000, 8, 15, 13),
 303        atc2603c_reg_desc_ldo_fixed(2, 2600000, 100000, 8, 15, 13),
 304        atc2603c_reg_desc_ldo_fixed(3, 1500000, 100000, 6, 15, 13),
 305        atc2603c_reg_desc_ldo(5, 2600000, 100000, 8, 15, 13),
 306        atc2603c_reg_desc_ldo_fixed(6, 700000, 25000, 29, 15, 11),
 307        atc2603c_reg_desc_ldo(7, 1500000, 100000, 6, 15, 13),
 308        atc2603c_reg_desc_ldo(8, 2300000, 100000, 11, 15, 12),
 309        atc2603c_reg_desc_ldo_fixed(11, 2600000, 100000, 8, 15, 13),
 310        atc2603c_reg_desc_ldo_noops(12, 1800000),
 311        atc2603c_reg_desc_ldo_switch(1, 3000000, 100000, 4, 4, 3),
 312};
 313
 314static const struct regulator_desc atc2603c_reg_dcdc2_ver_b =
 315        atc2603c_reg_desc_dcdc(2, 1000000, 50000, 18, 12, 8);
 316
 317enum atc2609a_reg_ids {
 318        ATC2609A_ID_DCDC0,
 319        ATC2609A_ID_DCDC1,
 320        ATC2609A_ID_DCDC2,
 321        ATC2609A_ID_DCDC3,
 322        ATC2609A_ID_DCDC4,
 323        ATC2609A_ID_LDO0,
 324        ATC2609A_ID_LDO1,
 325        ATC2609A_ID_LDO2,
 326        ATC2609A_ID_LDO3,
 327        ATC2609A_ID_LDO4,
 328        ATC2609A_ID_LDO5,
 329        ATC2609A_ID_LDO6,
 330        ATC2609A_ID_LDO7,
 331        ATC2609A_ID_LDO8,
 332        ATC2609A_ID_LDO9,
 333        ATC2609A_ID_MAX,
 334};
 335
 336#define atc2609a_reg_desc_dcdc(num, en_bit) { \
 337        .name = "DCDC"#num, \
 338        .supply_name = "dcdc"#num, \
 339        .of_match = of_match_ptr("dcdc"#num), \
 340        .regulators_node = of_match_ptr("regulators"), \
 341        .id = ATC2609A_ID_DCDC##num, \
 342        .ops = &atc260x_dcdc_ops, \
 343        .type = REGULATOR_VOLTAGE, \
 344        .min_uV = 600000, \
 345        .uV_step = 6250, \
 346        .n_voltages = 256, \
 347        .vsel_reg = ATC2609A_PMU_DC##num##_CTL0, \
 348        .vsel_mask = GENMASK(15, 8), \
 349        .enable_reg = ATC2609A_PMU_DC_OSC, \
 350        .enable_mask = BIT(en_bit), \
 351        .enable_time = 800, \
 352        .owner = THIS_MODULE, \
 353}
 354
 355#define atc2609a_reg_desc_dcdc_range(num, en_bit) { \
 356        .name = "DCDC"#num, \
 357        .supply_name = "dcdc"#num, \
 358        .of_match = of_match_ptr("dcdc"#num), \
 359        .regulators_node = of_match_ptr("regulators"), \
 360        .id = ATC2609A_ID_DCDC##num, \
 361        .ops = &atc260x_dcdc_range_ops, \
 362        .type = REGULATOR_VOLTAGE, \
 363        .n_voltages = 233, \
 364        .linear_ranges = atc2609a_dcdc_voltage_ranges, \
 365        .n_linear_ranges = ARRAY_SIZE(atc2609a_dcdc_voltage_ranges), \
 366        .vsel_reg = ATC2609A_PMU_DC##num##_CTL0, \
 367        .vsel_mask = GENMASK(15, 8), \
 368        .enable_reg = ATC2609A_PMU_DC_OSC, \
 369        .enable_mask = BIT(en_bit), \
 370        .enable_time = 800, \
 371        .owner = THIS_MODULE, \
 372}
 373
 374#define atc2609a_reg_desc_ldo(num) { \
 375        .name = "LDO"#num, \
 376        .supply_name = "ldo"#num, \
 377        .of_match = of_match_ptr("ldo"#num), \
 378        .regulators_node = of_match_ptr("regulators"), \
 379        .id = ATC2609A_ID_LDO##num, \
 380        .ops = &atc260x_ldo_ops, \
 381        .type = REGULATOR_VOLTAGE, \
 382        .min_uV = 700000, \
 383        .uV_step = 100000, \
 384        .n_voltages = 16, \
 385        .vsel_reg = ATC2609A_PMU_LDO##num##_CTL0, \
 386        .vsel_mask = GENMASK(4, 1), \
 387        .enable_reg = ATC2609A_PMU_LDO##num##_CTL0, \
 388        .enable_mask = BIT(0), \
 389        .enable_time = 2000, \
 390        .owner = THIS_MODULE, \
 391}
 392
 393#define atc2609a_reg_desc_ldo_bypass(num) { \
 394        .name = "LDO"#num, \
 395        .supply_name = "ldo"#num, \
 396        .of_match = of_match_ptr("ldo"#num), \
 397        .regulators_node = of_match_ptr("regulators"), \
 398        .id = ATC2609A_ID_LDO##num, \
 399        .ops = &atc260x_ldo_bypass_ops, \
 400        .type = REGULATOR_VOLTAGE, \
 401        .min_uV = 2300000, \
 402        .uV_step = 100000, \
 403        .n_voltages = 12, \
 404        .vsel_reg = ATC2609A_PMU_LDO##num##_CTL0, \
 405        .vsel_mask = GENMASK(5, 2), \
 406        .enable_reg = ATC2609A_PMU_LDO##num##_CTL0, \
 407        .enable_mask = BIT(0), \
 408        .enable_time = 2000, \
 409        .bypass_reg = ATC2609A_PMU_LDO##num##_CTL0, \
 410        .bypass_mask = BIT(1), \
 411        .owner = THIS_MODULE, \
 412}
 413
 414#define atc2609a_reg_desc_ldo_range_pick(num, n_range, n_volt) { \
 415        .name = "LDO"#num, \
 416        .supply_name = "ldo"#num, \
 417        .of_match = of_match_ptr("ldo"#num), \
 418        .regulators_node = of_match_ptr("regulators"), \
 419        .id = ATC2609A_ID_LDO##num, \
 420        .ops = &atc260x_ldo_range_pick_ops, \
 421        .type = REGULATOR_VOLTAGE, \
 422        .linear_ranges = atc2609a_ldo_voltage_ranges##n_range, \
 423        .n_linear_ranges = ARRAY_SIZE(atc2609a_ldo_voltage_ranges##n_range), \
 424        .n_voltages = n_volt, \
 425        .vsel_reg = ATC2609A_PMU_LDO##num##_CTL0, \
 426        .vsel_mask = GENMASK(4, 1), \
 427        .vsel_range_reg = ATC2609A_PMU_LDO##num##_CTL0, \
 428        .vsel_range_mask = BIT(5), \
 429        .linear_range_selectors = atc260x_ldo_voltage_range_sel, \
 430        .enable_reg = ATC2609A_PMU_LDO##num##_CTL0, \
 431        .enable_mask = BIT(0), \
 432        .enable_time = 2000, \
 433        .owner = THIS_MODULE, \
 434}
 435
 436#define atc2609a_reg_desc_ldo_fixed(num) { \
 437        .name = "LDO"#num, \
 438        .supply_name = "ldo"#num, \
 439        .of_match = of_match_ptr("ldo"#num), \
 440        .regulators_node = of_match_ptr("regulators"), \
 441        .id = ATC2609A_ID_LDO##num, \
 442        .ops = &atc260x_ldo_fixed_ops, \
 443        .type = REGULATOR_VOLTAGE, \
 444        .min_uV = 2600000, \
 445        .uV_step = 100000, \
 446        .n_voltages = 8, \
 447        .vsel_reg = ATC2609A_PMU_LDO##num##_CTL, \
 448        .vsel_mask = GENMASK(15, 13), \
 449        .enable_time = 2000, \
 450        .owner = THIS_MODULE, \
 451}
 452
 453static const struct regulator_desc atc2609a_reg[] = {
 454        atc2609a_reg_desc_dcdc(0, 4),
 455        atc2609a_reg_desc_dcdc(1, 5),
 456        atc2609a_reg_desc_dcdc(2, 6),
 457        atc2609a_reg_desc_dcdc_range(3, 7),
 458        atc2609a_reg_desc_dcdc(4, 8),
 459        atc2609a_reg_desc_ldo_bypass(0),
 460        atc2609a_reg_desc_ldo_bypass(1),
 461        atc2609a_reg_desc_ldo_bypass(2),
 462        atc2609a_reg_desc_ldo_range_pick(3, 0, 29),
 463        atc2609a_reg_desc_ldo_range_pick(4, 0, 29),
 464        atc2609a_reg_desc_ldo(5),
 465        atc2609a_reg_desc_ldo_range_pick(6, 1, 28),
 466        atc2609a_reg_desc_ldo_range_pick(7, 0, 29),
 467        atc2609a_reg_desc_ldo_range_pick(8, 0, 29),
 468        atc2609a_reg_desc_ldo_fixed(9),
 469};
 470
 471static int atc260x_regulator_probe(struct platform_device *pdev)
 472{
 473        struct atc260x *atc260x = dev_get_drvdata(pdev->dev.parent);
 474        struct device *dev = atc260x->dev;
 475        struct atc260x_regulator_data *atc260x_data;
 476        struct regulator_config config = {};
 477        struct regulator_dev *atc260x_rdev;
 478        const struct regulator_desc *regulators;
 479        bool atc2603c_ver_b = false;
 480        int i, nregulators;
 481
 482        atc260x_data = devm_kzalloc(&pdev->dev, sizeof(*atc260x_data), GFP_KERNEL);
 483        if (!atc260x_data)
 484                return -ENOMEM;
 485
 486        atc260x_data->voltage_time_dcdc = 350;
 487        atc260x_data->voltage_time_ldo = 800;
 488
 489        switch (atc260x->ic_type) {
 490        case ATC2603C:
 491                regulators = atc2603c_reg;
 492                nregulators = ATC2603C_ID_MAX;
 493                atc2603c_ver_b = atc260x->ic_ver == ATC260X_B;
 494                break;
 495        case ATC2609A:
 496                atc260x_data->voltage_time_dcdc = 250;
 497                regulators = atc2609a_reg;
 498                nregulators = ATC2609A_ID_MAX;
 499                break;
 500        default:
 501                dev_err(dev, "unsupported ATC260X ID %d\n", atc260x->ic_type);
 502                return -EINVAL;
 503        }
 504
 505        config.dev = dev;
 506        config.regmap = atc260x->regmap;
 507        config.driver_data = atc260x_data;
 508
 509        /* Instantiate the regulators */
 510        for (i = 0; i < nregulators; i++) {
 511                if (atc2603c_ver_b && regulators[i].id == ATC2603C_ID_DCDC2)
 512                        atc260x_rdev = devm_regulator_register(&pdev->dev,
 513                                                               &atc2603c_reg_dcdc2_ver_b,
 514                                                               &config);
 515                else
 516                        atc260x_rdev = devm_regulator_register(&pdev->dev,
 517                                                               &regulators[i],
 518                                                               &config);
 519                if (IS_ERR(atc260x_rdev)) {
 520                        dev_err(dev, "failed to register regulator: %d\n", i);
 521                        return PTR_ERR(atc260x_rdev);
 522                }
 523        }
 524
 525        return 0;
 526}
 527
 528static struct platform_driver atc260x_regulator_driver = {
 529        .probe = atc260x_regulator_probe,
 530        .driver = {
 531                .name = "atc260x-regulator",
 532        },
 533};
 534
 535module_platform_driver(atc260x_regulator_driver);
 536
 537MODULE_DESCRIPTION("Regulator driver for ATC260x PMICs");
 538MODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>");
 539MODULE_AUTHOR("Cristian Ciocaltea <cristian.ciocaltea@gmail.com>");
 540MODULE_LICENSE("GPL");
 541