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