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 14 struct atc260x_regulator_data { 15 int voltage_time_dcdc; 16 int voltage_time_ldo; 17 }; 18 19 static 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 24 static 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 29 static 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 34 static 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 39 static const unsigned int atc260x_ldo_voltage_range_sel[] = { 40 0x0, 0x20, 41 }; 42 43 static 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 55 static 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 67 static 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 77 static 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 87 static 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 99 static 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 112 static 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 122 static 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 132 static 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 139 static 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 146 static 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 */ 153 enum 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 .active_discharge_on = BIT(1), \ 296 .owner = THIS_MODULE, \ 297 } 298 299 static const struct regulator_desc atc2603c_reg[] = { 300 atc2603c_reg_desc_dcdc_fixed(1, 700000, 25000, 29, 11, 7), 301 atc2603c_reg_desc_dcdc_range(2, 12, 8), 302 atc2603c_reg_desc_dcdc_fixed(3, 2600000, 100000, 8, 11, 9), 303 atc2603c_reg_desc_ldo_fixed(1, 2600000, 100000, 8, 15, 13), 304 atc2603c_reg_desc_ldo_fixed(2, 2600000, 100000, 8, 15, 13), 305 atc2603c_reg_desc_ldo_fixed(3, 1500000, 100000, 6, 15, 13), 306 atc2603c_reg_desc_ldo(5, 2600000, 100000, 8, 15, 13), 307 atc2603c_reg_desc_ldo_fixed(6, 700000, 25000, 29, 15, 11), 308 atc2603c_reg_desc_ldo(7, 1500000, 100000, 6, 15, 13), 309 atc2603c_reg_desc_ldo(8, 2300000, 100000, 11, 15, 12), 310 atc2603c_reg_desc_ldo_fixed(11, 2600000, 100000, 8, 15, 13), 311 atc2603c_reg_desc_ldo_noops(12, 1800000), 312 atc2603c_reg_desc_ldo_switch(1, 3000000, 100000, 4, 4, 3), 313 }; 314 315 static const struct regulator_desc atc2603c_reg_dcdc2_ver_b = 316 atc2603c_reg_desc_dcdc(2, 1000000, 50000, 18, 12, 8); 317 318 enum atc2609a_reg_ids { 319 ATC2609A_ID_DCDC0, 320 ATC2609A_ID_DCDC1, 321 ATC2609A_ID_DCDC2, 322 ATC2609A_ID_DCDC3, 323 ATC2609A_ID_DCDC4, 324 ATC2609A_ID_LDO0, 325 ATC2609A_ID_LDO1, 326 ATC2609A_ID_LDO2, 327 ATC2609A_ID_LDO3, 328 ATC2609A_ID_LDO4, 329 ATC2609A_ID_LDO5, 330 ATC2609A_ID_LDO6, 331 ATC2609A_ID_LDO7, 332 ATC2609A_ID_LDO8, 333 ATC2609A_ID_LDO9, 334 ATC2609A_ID_MAX, 335 }; 336 337 #define atc2609a_reg_desc_dcdc(num, en_bit) { \ 338 .name = "DCDC"#num, \ 339 .supply_name = "dcdc"#num, \ 340 .of_match = of_match_ptr("dcdc"#num), \ 341 .regulators_node = of_match_ptr("regulators"), \ 342 .id = ATC2609A_ID_DCDC##num, \ 343 .ops = &atc260x_dcdc_ops, \ 344 .type = REGULATOR_VOLTAGE, \ 345 .min_uV = 600000, \ 346 .uV_step = 6250, \ 347 .n_voltages = 256, \ 348 .vsel_reg = ATC2609A_PMU_DC##num##_CTL0, \ 349 .vsel_mask = GENMASK(15, 8), \ 350 .enable_reg = ATC2609A_PMU_DC_OSC, \ 351 .enable_mask = BIT(en_bit), \ 352 .enable_time = 800, \ 353 .owner = THIS_MODULE, \ 354 } 355 356 #define atc2609a_reg_desc_dcdc_range(num, en_bit) { \ 357 .name = "DCDC"#num, \ 358 .supply_name = "dcdc"#num, \ 359 .of_match = of_match_ptr("dcdc"#num), \ 360 .regulators_node = of_match_ptr("regulators"), \ 361 .id = ATC2609A_ID_DCDC##num, \ 362 .ops = &atc260x_dcdc_range_ops, \ 363 .type = REGULATOR_VOLTAGE, \ 364 .n_voltages = 233, \ 365 .linear_ranges = atc2609a_dcdc_voltage_ranges, \ 366 .n_linear_ranges = ARRAY_SIZE(atc2609a_dcdc_voltage_ranges), \ 367 .vsel_reg = ATC2609A_PMU_DC##num##_CTL0, \ 368 .vsel_mask = GENMASK(15, 8), \ 369 .enable_reg = ATC2609A_PMU_DC_OSC, \ 370 .enable_mask = BIT(en_bit), \ 371 .enable_time = 800, \ 372 .owner = THIS_MODULE, \ 373 } 374 375 #define atc2609a_reg_desc_ldo(num) { \ 376 .name = "LDO"#num, \ 377 .supply_name = "ldo"#num, \ 378 .of_match = of_match_ptr("ldo"#num), \ 379 .regulators_node = of_match_ptr("regulators"), \ 380 .id = ATC2609A_ID_LDO##num, \ 381 .ops = &atc260x_ldo_ops, \ 382 .type = REGULATOR_VOLTAGE, \ 383 .min_uV = 700000, \ 384 .uV_step = 100000, \ 385 .n_voltages = 16, \ 386 .vsel_reg = ATC2609A_PMU_LDO##num##_CTL0, \ 387 .vsel_mask = GENMASK(4, 1), \ 388 .enable_reg = ATC2609A_PMU_LDO##num##_CTL0, \ 389 .enable_mask = BIT(0), \ 390 .enable_time = 2000, \ 391 .owner = THIS_MODULE, \ 392 } 393 394 #define atc2609a_reg_desc_ldo_bypass(num) { \ 395 .name = "LDO"#num, \ 396 .supply_name = "ldo"#num, \ 397 .of_match = of_match_ptr("ldo"#num), \ 398 .regulators_node = of_match_ptr("regulators"), \ 399 .id = ATC2609A_ID_LDO##num, \ 400 .ops = &atc260x_ldo_bypass_ops, \ 401 .type = REGULATOR_VOLTAGE, \ 402 .min_uV = 2300000, \ 403 .uV_step = 100000, \ 404 .n_voltages = 12, \ 405 .vsel_reg = ATC2609A_PMU_LDO##num##_CTL0, \ 406 .vsel_mask = GENMASK(5, 2), \ 407 .enable_reg = ATC2609A_PMU_LDO##num##_CTL0, \ 408 .enable_mask = BIT(0), \ 409 .enable_time = 2000, \ 410 .bypass_reg = ATC2609A_PMU_LDO##num##_CTL0, \ 411 .bypass_mask = BIT(1), \ 412 .owner = THIS_MODULE, \ 413 } 414 415 #define atc2609a_reg_desc_ldo_range_pick(num, n_range, n_volt) { \ 416 .name = "LDO"#num, \ 417 .supply_name = "ldo"#num, \ 418 .of_match = of_match_ptr("ldo"#num), \ 419 .regulators_node = of_match_ptr("regulators"), \ 420 .id = ATC2609A_ID_LDO##num, \ 421 .ops = &atc260x_ldo_range_pick_ops, \ 422 .type = REGULATOR_VOLTAGE, \ 423 .linear_ranges = atc2609a_ldo_voltage_ranges##n_range, \ 424 .n_linear_ranges = ARRAY_SIZE(atc2609a_ldo_voltage_ranges##n_range), \ 425 .n_voltages = n_volt, \ 426 .vsel_reg = ATC2609A_PMU_LDO##num##_CTL0, \ 427 .vsel_mask = GENMASK(4, 1), \ 428 .vsel_range_reg = ATC2609A_PMU_LDO##num##_CTL0, \ 429 .vsel_range_mask = BIT(5), \ 430 .linear_range_selectors = atc260x_ldo_voltage_range_sel, \ 431 .enable_reg = ATC2609A_PMU_LDO##num##_CTL0, \ 432 .enable_mask = BIT(0), \ 433 .enable_time = 2000, \ 434 .owner = THIS_MODULE, \ 435 } 436 437 #define atc2609a_reg_desc_ldo_fixed(num) { \ 438 .name = "LDO"#num, \ 439 .supply_name = "ldo"#num, \ 440 .of_match = of_match_ptr("ldo"#num), \ 441 .regulators_node = of_match_ptr("regulators"), \ 442 .id = ATC2609A_ID_LDO##num, \ 443 .ops = &atc260x_ldo_fixed_ops, \ 444 .type = REGULATOR_VOLTAGE, \ 445 .min_uV = 2600000, \ 446 .uV_step = 100000, \ 447 .n_voltages = 8, \ 448 .vsel_reg = ATC2609A_PMU_LDO##num##_CTL, \ 449 .vsel_mask = GENMASK(15, 13), \ 450 .enable_time = 2000, \ 451 .owner = THIS_MODULE, \ 452 } 453 454 static const struct regulator_desc atc2609a_reg[] = { 455 atc2609a_reg_desc_dcdc(0, 4), 456 atc2609a_reg_desc_dcdc(1, 5), 457 atc2609a_reg_desc_dcdc(2, 6), 458 atc2609a_reg_desc_dcdc_range(3, 7), 459 atc2609a_reg_desc_dcdc(4, 8), 460 atc2609a_reg_desc_ldo_bypass(0), 461 atc2609a_reg_desc_ldo_bypass(1), 462 atc2609a_reg_desc_ldo_bypass(2), 463 atc2609a_reg_desc_ldo_range_pick(3, 0, 29), 464 atc2609a_reg_desc_ldo_range_pick(4, 0, 29), 465 atc2609a_reg_desc_ldo(5), 466 atc2609a_reg_desc_ldo_range_pick(6, 1, 28), 467 atc2609a_reg_desc_ldo_range_pick(7, 0, 29), 468 atc2609a_reg_desc_ldo_range_pick(8, 0, 29), 469 atc2609a_reg_desc_ldo_fixed(9), 470 }; 471 472 static int atc260x_regulator_probe(struct platform_device *pdev) 473 { 474 struct atc260x *atc260x = dev_get_drvdata(pdev->dev.parent); 475 struct device *dev = atc260x->dev; 476 struct atc260x_regulator_data *atc260x_data; 477 struct regulator_config config = {}; 478 struct regulator_dev *atc260x_rdev; 479 const struct regulator_desc *regulators; 480 bool atc2603c_ver_b = false; 481 int i, nregulators; 482 483 atc260x_data = devm_kzalloc(&pdev->dev, sizeof(*atc260x_data), GFP_KERNEL); 484 if (!atc260x_data) 485 return -ENOMEM; 486 487 atc260x_data->voltage_time_dcdc = 350; 488 atc260x_data->voltage_time_ldo = 800; 489 490 switch (atc260x->ic_type) { 491 case ATC2603C: 492 regulators = atc2603c_reg; 493 nregulators = ATC2603C_ID_MAX; 494 atc2603c_ver_b = atc260x->ic_ver == ATC260X_B; 495 break; 496 case ATC2609A: 497 atc260x_data->voltage_time_dcdc = 250; 498 regulators = atc2609a_reg; 499 nregulators = ATC2609A_ID_MAX; 500 break; 501 default: 502 dev_err(dev, "unsupported ATC260X ID %d\n", atc260x->ic_type); 503 return -EINVAL; 504 } 505 506 config.dev = dev; 507 config.regmap = atc260x->regmap; 508 config.driver_data = atc260x_data; 509 510 /* Instantiate the regulators */ 511 for (i = 0; i < nregulators; i++) { 512 if (atc2603c_ver_b && regulators[i].id == ATC2603C_ID_DCDC2) 513 atc260x_rdev = devm_regulator_register(&pdev->dev, 514 &atc2603c_reg_dcdc2_ver_b, 515 &config); 516 else 517 atc260x_rdev = devm_regulator_register(&pdev->dev, 518 ®ulators[i], 519 &config); 520 if (IS_ERR(atc260x_rdev)) { 521 dev_err(dev, "failed to register regulator: %d\n", i); 522 return PTR_ERR(atc260x_rdev); 523 } 524 } 525 526 return 0; 527 } 528 529 static struct platform_driver atc260x_regulator_driver = { 530 .probe = atc260x_regulator_probe, 531 .driver = { 532 .name = "atc260x-regulator", 533 }, 534 }; 535 536 module_platform_driver(atc260x_regulator_driver); 537 538 MODULE_DESCRIPTION("Regulator driver for ATC260x PMICs"); 539 MODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>"); 540 MODULE_AUTHOR("Cristian Ciocaltea <cristian.ciocaltea@gmail.com>"); 541 MODULE_LICENSE("GPL"); 542