1 /* 2 * Core, IRQ and I2C device driver for DA9061 and DA9062 PMICs 3 * Copyright (C) 2015-2017 Dialog Semiconductor 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License 7 * as published by the Free Software Foundation; either version 2 8 * of the License, or (at your option) any later version. 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/kernel.h> 17 #include <linux/module.h> 18 #include <linux/init.h> 19 #include <linux/device.h> 20 #include <linux/interrupt.h> 21 #include <linux/regmap.h> 22 #include <linux/irq.h> 23 #include <linux/mfd/core.h> 24 #include <linux/i2c.h> 25 #include <linux/mfd/da9062/core.h> 26 #include <linux/mfd/da9062/registers.h> 27 #include <linux/regulator/of_regulator.h> 28 29 #define DA9062_REG_EVENT_A_OFFSET 0 30 #define DA9062_REG_EVENT_B_OFFSET 1 31 #define DA9062_REG_EVENT_C_OFFSET 2 32 33 static struct regmap_irq da9061_irqs[] = { 34 /* EVENT A */ 35 [DA9061_IRQ_ONKEY] = { 36 .reg_offset = DA9062_REG_EVENT_A_OFFSET, 37 .mask = DA9062AA_M_NONKEY_MASK, 38 }, 39 [DA9061_IRQ_WDG_WARN] = { 40 .reg_offset = DA9062_REG_EVENT_A_OFFSET, 41 .mask = DA9062AA_M_WDG_WARN_MASK, 42 }, 43 [DA9061_IRQ_SEQ_RDY] = { 44 .reg_offset = DA9062_REG_EVENT_A_OFFSET, 45 .mask = DA9062AA_M_SEQ_RDY_MASK, 46 }, 47 /* EVENT B */ 48 [DA9061_IRQ_TEMP] = { 49 .reg_offset = DA9062_REG_EVENT_B_OFFSET, 50 .mask = DA9062AA_M_TEMP_MASK, 51 }, 52 [DA9061_IRQ_LDO_LIM] = { 53 .reg_offset = DA9062_REG_EVENT_B_OFFSET, 54 .mask = DA9062AA_M_LDO_LIM_MASK, 55 }, 56 [DA9061_IRQ_DVC_RDY] = { 57 .reg_offset = DA9062_REG_EVENT_B_OFFSET, 58 .mask = DA9062AA_M_DVC_RDY_MASK, 59 }, 60 [DA9061_IRQ_VDD_WARN] = { 61 .reg_offset = DA9062_REG_EVENT_B_OFFSET, 62 .mask = DA9062AA_M_VDD_WARN_MASK, 63 }, 64 /* EVENT C */ 65 [DA9061_IRQ_GPI0] = { 66 .reg_offset = DA9062_REG_EVENT_C_OFFSET, 67 .mask = DA9062AA_M_GPI0_MASK, 68 }, 69 [DA9061_IRQ_GPI1] = { 70 .reg_offset = DA9062_REG_EVENT_C_OFFSET, 71 .mask = DA9062AA_M_GPI1_MASK, 72 }, 73 [DA9061_IRQ_GPI2] = { 74 .reg_offset = DA9062_REG_EVENT_C_OFFSET, 75 .mask = DA9062AA_M_GPI2_MASK, 76 }, 77 [DA9061_IRQ_GPI3] = { 78 .reg_offset = DA9062_REG_EVENT_C_OFFSET, 79 .mask = DA9062AA_M_GPI3_MASK, 80 }, 81 [DA9061_IRQ_GPI4] = { 82 .reg_offset = DA9062_REG_EVENT_C_OFFSET, 83 .mask = DA9062AA_M_GPI4_MASK, 84 }, 85 }; 86 87 static struct regmap_irq_chip da9061_irq_chip = { 88 .name = "da9061-irq", 89 .irqs = da9061_irqs, 90 .num_irqs = DA9061_NUM_IRQ, 91 .num_regs = 3, 92 .status_base = DA9062AA_EVENT_A, 93 .mask_base = DA9062AA_IRQ_MASK_A, 94 .ack_base = DA9062AA_EVENT_A, 95 }; 96 97 static struct regmap_irq da9062_irqs[] = { 98 /* EVENT A */ 99 [DA9062_IRQ_ONKEY] = { 100 .reg_offset = DA9062_REG_EVENT_A_OFFSET, 101 .mask = DA9062AA_M_NONKEY_MASK, 102 }, 103 [DA9062_IRQ_ALARM] = { 104 .reg_offset = DA9062_REG_EVENT_A_OFFSET, 105 .mask = DA9062AA_M_ALARM_MASK, 106 }, 107 [DA9062_IRQ_TICK] = { 108 .reg_offset = DA9062_REG_EVENT_A_OFFSET, 109 .mask = DA9062AA_M_TICK_MASK, 110 }, 111 [DA9062_IRQ_WDG_WARN] = { 112 .reg_offset = DA9062_REG_EVENT_A_OFFSET, 113 .mask = DA9062AA_M_WDG_WARN_MASK, 114 }, 115 [DA9062_IRQ_SEQ_RDY] = { 116 .reg_offset = DA9062_REG_EVENT_A_OFFSET, 117 .mask = DA9062AA_M_SEQ_RDY_MASK, 118 }, 119 /* EVENT B */ 120 [DA9062_IRQ_TEMP] = { 121 .reg_offset = DA9062_REG_EVENT_B_OFFSET, 122 .mask = DA9062AA_M_TEMP_MASK, 123 }, 124 [DA9062_IRQ_LDO_LIM] = { 125 .reg_offset = DA9062_REG_EVENT_B_OFFSET, 126 .mask = DA9062AA_M_LDO_LIM_MASK, 127 }, 128 [DA9062_IRQ_DVC_RDY] = { 129 .reg_offset = DA9062_REG_EVENT_B_OFFSET, 130 .mask = DA9062AA_M_DVC_RDY_MASK, 131 }, 132 [DA9062_IRQ_VDD_WARN] = { 133 .reg_offset = DA9062_REG_EVENT_B_OFFSET, 134 .mask = DA9062AA_M_VDD_WARN_MASK, 135 }, 136 /* EVENT C */ 137 [DA9062_IRQ_GPI0] = { 138 .reg_offset = DA9062_REG_EVENT_C_OFFSET, 139 .mask = DA9062AA_M_GPI0_MASK, 140 }, 141 [DA9062_IRQ_GPI1] = { 142 .reg_offset = DA9062_REG_EVENT_C_OFFSET, 143 .mask = DA9062AA_M_GPI1_MASK, 144 }, 145 [DA9062_IRQ_GPI2] = { 146 .reg_offset = DA9062_REG_EVENT_C_OFFSET, 147 .mask = DA9062AA_M_GPI2_MASK, 148 }, 149 [DA9062_IRQ_GPI3] = { 150 .reg_offset = DA9062_REG_EVENT_C_OFFSET, 151 .mask = DA9062AA_M_GPI3_MASK, 152 }, 153 [DA9062_IRQ_GPI4] = { 154 .reg_offset = DA9062_REG_EVENT_C_OFFSET, 155 .mask = DA9062AA_M_GPI4_MASK, 156 }, 157 }; 158 159 static struct regmap_irq_chip da9062_irq_chip = { 160 .name = "da9062-irq", 161 .irqs = da9062_irqs, 162 .num_irqs = DA9062_NUM_IRQ, 163 .num_regs = 3, 164 .status_base = DA9062AA_EVENT_A, 165 .mask_base = DA9062AA_IRQ_MASK_A, 166 .ack_base = DA9062AA_EVENT_A, 167 }; 168 169 static struct resource da9061_core_resources[] = { 170 DEFINE_RES_IRQ_NAMED(DA9061_IRQ_VDD_WARN, "VDD_WARN"), 171 }; 172 173 static struct resource da9061_regulators_resources[] = { 174 DEFINE_RES_IRQ_NAMED(DA9061_IRQ_LDO_LIM, "LDO_LIM"), 175 }; 176 177 static struct resource da9061_thermal_resources[] = { 178 DEFINE_RES_IRQ_NAMED(DA9061_IRQ_TEMP, "THERMAL"), 179 }; 180 181 static struct resource da9061_wdt_resources[] = { 182 DEFINE_RES_IRQ_NAMED(DA9061_IRQ_WDG_WARN, "WD_WARN"), 183 }; 184 185 static struct resource da9061_onkey_resources[] = { 186 DEFINE_RES_IRQ_NAMED(DA9061_IRQ_ONKEY, "ONKEY"), 187 }; 188 189 static const struct mfd_cell da9061_devs[] = { 190 { 191 .name = "da9061-core", 192 .num_resources = ARRAY_SIZE(da9061_core_resources), 193 .resources = da9061_core_resources, 194 }, 195 { 196 .name = "da9062-regulators", 197 .num_resources = ARRAY_SIZE(da9061_regulators_resources), 198 .resources = da9061_regulators_resources, 199 }, 200 { 201 .name = "da9061-watchdog", 202 .num_resources = ARRAY_SIZE(da9061_wdt_resources), 203 .resources = da9061_wdt_resources, 204 .of_compatible = "dlg,da9061-watchdog", 205 }, 206 { 207 .name = "da9061-thermal", 208 .num_resources = ARRAY_SIZE(da9061_thermal_resources), 209 .resources = da9061_thermal_resources, 210 .of_compatible = "dlg,da9061-thermal", 211 }, 212 { 213 .name = "da9061-onkey", 214 .num_resources = ARRAY_SIZE(da9061_onkey_resources), 215 .resources = da9061_onkey_resources, 216 .of_compatible = "dlg,da9061-onkey", 217 }, 218 }; 219 220 static struct resource da9062_core_resources[] = { 221 DEFINE_RES_NAMED(DA9062_IRQ_VDD_WARN, 1, "VDD_WARN", IORESOURCE_IRQ), 222 }; 223 224 static struct resource da9062_regulators_resources[] = { 225 DEFINE_RES_NAMED(DA9062_IRQ_LDO_LIM, 1, "LDO_LIM", IORESOURCE_IRQ), 226 }; 227 228 static struct resource da9062_thermal_resources[] = { 229 DEFINE_RES_NAMED(DA9062_IRQ_TEMP, 1, "THERMAL", IORESOURCE_IRQ), 230 }; 231 232 static struct resource da9062_wdt_resources[] = { 233 DEFINE_RES_NAMED(DA9062_IRQ_WDG_WARN, 1, "WD_WARN", IORESOURCE_IRQ), 234 }; 235 236 static struct resource da9062_rtc_resources[] = { 237 DEFINE_RES_NAMED(DA9062_IRQ_ALARM, 1, "ALARM", IORESOURCE_IRQ), 238 DEFINE_RES_NAMED(DA9062_IRQ_TICK, 1, "TICK", IORESOURCE_IRQ), 239 }; 240 241 static struct resource da9062_onkey_resources[] = { 242 DEFINE_RES_NAMED(DA9062_IRQ_ONKEY, 1, "ONKEY", IORESOURCE_IRQ), 243 }; 244 245 static const struct mfd_cell da9062_devs[] = { 246 { 247 .name = "da9062-core", 248 .num_resources = ARRAY_SIZE(da9062_core_resources), 249 .resources = da9062_core_resources, 250 }, 251 { 252 .name = "da9062-regulators", 253 .num_resources = ARRAY_SIZE(da9062_regulators_resources), 254 .resources = da9062_regulators_resources, 255 }, 256 { 257 .name = "da9062-watchdog", 258 .num_resources = ARRAY_SIZE(da9062_wdt_resources), 259 .resources = da9062_wdt_resources, 260 .of_compatible = "dlg,da9062-wdt", 261 }, 262 { 263 .name = "da9062-thermal", 264 .num_resources = ARRAY_SIZE(da9062_thermal_resources), 265 .resources = da9062_thermal_resources, 266 .of_compatible = "dlg,da9062-thermal", 267 }, 268 { 269 .name = "da9062-rtc", 270 .num_resources = ARRAY_SIZE(da9062_rtc_resources), 271 .resources = da9062_rtc_resources, 272 .of_compatible = "dlg,da9062-rtc", 273 }, 274 { 275 .name = "da9062-onkey", 276 .num_resources = ARRAY_SIZE(da9062_onkey_resources), 277 .resources = da9062_onkey_resources, 278 .of_compatible = "dlg,da9062-onkey", 279 }, 280 }; 281 282 static int da9062_clear_fault_log(struct da9062 *chip) 283 { 284 int ret; 285 int fault_log; 286 287 ret = regmap_read(chip->regmap, DA9062AA_FAULT_LOG, &fault_log); 288 if (ret < 0) 289 return ret; 290 291 if (fault_log) { 292 if (fault_log & DA9062AA_TWD_ERROR_MASK) 293 dev_dbg(chip->dev, "Fault log entry detected: TWD_ERROR\n"); 294 if (fault_log & DA9062AA_POR_MASK) 295 dev_dbg(chip->dev, "Fault log entry detected: POR\n"); 296 if (fault_log & DA9062AA_VDD_FAULT_MASK) 297 dev_dbg(chip->dev, "Fault log entry detected: VDD_FAULT\n"); 298 if (fault_log & DA9062AA_VDD_START_MASK) 299 dev_dbg(chip->dev, "Fault log entry detected: VDD_START\n"); 300 if (fault_log & DA9062AA_TEMP_CRIT_MASK) 301 dev_dbg(chip->dev, "Fault log entry detected: TEMP_CRIT\n"); 302 if (fault_log & DA9062AA_KEY_RESET_MASK) 303 dev_dbg(chip->dev, "Fault log entry detected: KEY_RESET\n"); 304 if (fault_log & DA9062AA_NSHUTDOWN_MASK) 305 dev_dbg(chip->dev, "Fault log entry detected: NSHUTDOWN\n"); 306 if (fault_log & DA9062AA_WAIT_SHUT_MASK) 307 dev_dbg(chip->dev, "Fault log entry detected: WAIT_SHUT\n"); 308 309 ret = regmap_write(chip->regmap, DA9062AA_FAULT_LOG, 310 fault_log); 311 } 312 313 return ret; 314 } 315 316 static int da9062_get_device_type(struct da9062 *chip) 317 { 318 int device_id, variant_id, variant_mrc, variant_vrc; 319 char *type; 320 int ret; 321 322 ret = regmap_read(chip->regmap, DA9062AA_DEVICE_ID, &device_id); 323 if (ret < 0) { 324 dev_err(chip->dev, "Cannot read chip ID.\n"); 325 return -EIO; 326 } 327 if (device_id != DA9062_PMIC_DEVICE_ID) { 328 dev_err(chip->dev, "Invalid device ID: 0x%02x\n", device_id); 329 return -ENODEV; 330 } 331 332 ret = regmap_read(chip->regmap, DA9062AA_VARIANT_ID, &variant_id); 333 if (ret < 0) { 334 dev_err(chip->dev, "Cannot read chip variant id.\n"); 335 return -EIO; 336 } 337 338 variant_vrc = (variant_id & DA9062AA_VRC_MASK) >> DA9062AA_VRC_SHIFT; 339 340 switch (variant_vrc) { 341 case DA9062_PMIC_VARIANT_VRC_DA9061: 342 type = "DA9061"; 343 break; 344 case DA9062_PMIC_VARIANT_VRC_DA9062: 345 type = "DA9062"; 346 break; 347 default: 348 type = "Unknown"; 349 break; 350 } 351 352 dev_info(chip->dev, 353 "Device detected (device-ID: 0x%02X, var-ID: 0x%02X, %s)\n", 354 device_id, variant_id, type); 355 356 variant_mrc = (variant_id & DA9062AA_MRC_MASK) >> DA9062AA_MRC_SHIFT; 357 358 if (variant_mrc < DA9062_PMIC_VARIANT_MRC_AA) { 359 dev_err(chip->dev, 360 "Cannot support variant MRC: 0x%02X\n", variant_mrc); 361 return -ENODEV; 362 } 363 364 return ret; 365 } 366 367 static const struct regmap_range da9061_aa_readable_ranges[] = { 368 { 369 .range_min = DA9062AA_PAGE_CON, 370 .range_max = DA9062AA_STATUS_B, 371 }, { 372 .range_min = DA9062AA_STATUS_D, 373 .range_max = DA9062AA_EVENT_C, 374 }, { 375 .range_min = DA9062AA_IRQ_MASK_A, 376 .range_max = DA9062AA_IRQ_MASK_C, 377 }, { 378 .range_min = DA9062AA_CONTROL_A, 379 .range_max = DA9062AA_GPIO_4, 380 }, { 381 .range_min = DA9062AA_GPIO_WKUP_MODE, 382 .range_max = DA9062AA_GPIO_OUT3_4, 383 }, { 384 .range_min = DA9062AA_BUCK1_CONT, 385 .range_max = DA9062AA_BUCK4_CONT, 386 }, { 387 .range_min = DA9062AA_BUCK3_CONT, 388 .range_max = DA9062AA_BUCK3_CONT, 389 }, { 390 .range_min = DA9062AA_LDO1_CONT, 391 .range_max = DA9062AA_LDO4_CONT, 392 }, { 393 .range_min = DA9062AA_DVC_1, 394 .range_max = DA9062AA_DVC_1, 395 }, { 396 .range_min = DA9062AA_SEQ, 397 .range_max = DA9062AA_ID_4_3, 398 }, { 399 .range_min = DA9062AA_ID_12_11, 400 .range_max = DA9062AA_ID_16_15, 401 }, { 402 .range_min = DA9062AA_ID_22_21, 403 .range_max = DA9062AA_ID_32_31, 404 }, { 405 .range_min = DA9062AA_SEQ_A, 406 .range_max = DA9062AA_WAIT, 407 }, { 408 .range_min = DA9062AA_RESET, 409 .range_max = DA9062AA_BUCK_ILIM_C, 410 }, { 411 .range_min = DA9062AA_BUCK1_CFG, 412 .range_max = DA9062AA_BUCK3_CFG, 413 }, { 414 .range_min = DA9062AA_VBUCK1_A, 415 .range_max = DA9062AA_VBUCK4_A, 416 }, { 417 .range_min = DA9062AA_VBUCK3_A, 418 .range_max = DA9062AA_VBUCK3_A, 419 }, { 420 .range_min = DA9062AA_VLDO1_A, 421 .range_max = DA9062AA_VLDO4_A, 422 }, { 423 .range_min = DA9062AA_VBUCK1_B, 424 .range_max = DA9062AA_VBUCK4_B, 425 }, { 426 .range_min = DA9062AA_VBUCK3_B, 427 .range_max = DA9062AA_VBUCK3_B, 428 }, { 429 .range_min = DA9062AA_VLDO1_B, 430 .range_max = DA9062AA_VLDO4_B, 431 }, { 432 .range_min = DA9062AA_INTERFACE, 433 .range_max = DA9062AA_CONFIG_E, 434 }, { 435 .range_min = DA9062AA_CONFIG_G, 436 .range_max = DA9062AA_CONFIG_K, 437 }, { 438 .range_min = DA9062AA_CONFIG_M, 439 .range_max = DA9062AA_CONFIG_M, 440 }, { 441 .range_min = DA9062AA_GP_ID_0, 442 .range_max = DA9062AA_GP_ID_19, 443 }, { 444 .range_min = DA9062AA_DEVICE_ID, 445 .range_max = DA9062AA_CONFIG_ID, 446 }, 447 }; 448 449 static const struct regmap_range da9061_aa_writeable_ranges[] = { 450 { 451 .range_min = DA9062AA_PAGE_CON, 452 .range_max = DA9062AA_PAGE_CON, 453 }, { 454 .range_min = DA9062AA_FAULT_LOG, 455 .range_max = DA9062AA_EVENT_C, 456 }, { 457 .range_min = DA9062AA_IRQ_MASK_A, 458 .range_max = DA9062AA_IRQ_MASK_C, 459 }, { 460 .range_min = DA9062AA_CONTROL_A, 461 .range_max = DA9062AA_GPIO_4, 462 }, { 463 .range_min = DA9062AA_GPIO_WKUP_MODE, 464 .range_max = DA9062AA_GPIO_OUT3_4, 465 }, { 466 .range_min = DA9062AA_BUCK1_CONT, 467 .range_max = DA9062AA_BUCK4_CONT, 468 }, { 469 .range_min = DA9062AA_BUCK3_CONT, 470 .range_max = DA9062AA_BUCK3_CONT, 471 }, { 472 .range_min = DA9062AA_LDO1_CONT, 473 .range_max = DA9062AA_LDO4_CONT, 474 }, { 475 .range_min = DA9062AA_DVC_1, 476 .range_max = DA9062AA_DVC_1, 477 }, { 478 .range_min = DA9062AA_SEQ, 479 .range_max = DA9062AA_ID_4_3, 480 }, { 481 .range_min = DA9062AA_ID_12_11, 482 .range_max = DA9062AA_ID_16_15, 483 }, { 484 .range_min = DA9062AA_ID_22_21, 485 .range_max = DA9062AA_ID_32_31, 486 }, { 487 .range_min = DA9062AA_SEQ_A, 488 .range_max = DA9062AA_WAIT, 489 }, { 490 .range_min = DA9062AA_RESET, 491 .range_max = DA9062AA_BUCK_ILIM_C, 492 }, { 493 .range_min = DA9062AA_BUCK1_CFG, 494 .range_max = DA9062AA_BUCK3_CFG, 495 }, { 496 .range_min = DA9062AA_VBUCK1_A, 497 .range_max = DA9062AA_VBUCK4_A, 498 }, { 499 .range_min = DA9062AA_VBUCK3_A, 500 .range_max = DA9062AA_VBUCK3_A, 501 }, { 502 .range_min = DA9062AA_VLDO1_A, 503 .range_max = DA9062AA_VLDO4_A, 504 }, { 505 .range_min = DA9062AA_VBUCK1_B, 506 .range_max = DA9062AA_VBUCK4_B, 507 }, { 508 .range_min = DA9062AA_VBUCK3_B, 509 .range_max = DA9062AA_VBUCK3_B, 510 }, { 511 .range_min = DA9062AA_VLDO1_B, 512 .range_max = DA9062AA_VLDO4_B, 513 }, { 514 .range_min = DA9062AA_GP_ID_0, 515 .range_max = DA9062AA_GP_ID_19, 516 }, 517 }; 518 519 static const struct regmap_range da9061_aa_volatile_ranges[] = { 520 { 521 .range_min = DA9062AA_PAGE_CON, 522 .range_max = DA9062AA_STATUS_B, 523 }, { 524 .range_min = DA9062AA_STATUS_D, 525 .range_max = DA9062AA_EVENT_C, 526 }, { 527 .range_min = DA9062AA_CONTROL_A, 528 .range_max = DA9062AA_CONTROL_B, 529 }, { 530 .range_min = DA9062AA_CONTROL_E, 531 .range_max = DA9062AA_CONTROL_F, 532 }, { 533 .range_min = DA9062AA_BUCK1_CONT, 534 .range_max = DA9062AA_BUCK4_CONT, 535 }, { 536 .range_min = DA9062AA_BUCK3_CONT, 537 .range_max = DA9062AA_BUCK3_CONT, 538 }, { 539 .range_min = DA9062AA_LDO1_CONT, 540 .range_max = DA9062AA_LDO4_CONT, 541 }, { 542 .range_min = DA9062AA_DVC_1, 543 .range_max = DA9062AA_DVC_1, 544 }, { 545 .range_min = DA9062AA_SEQ, 546 .range_max = DA9062AA_SEQ, 547 }, 548 }; 549 550 static const struct regmap_access_table da9061_aa_readable_table = { 551 .yes_ranges = da9061_aa_readable_ranges, 552 .n_yes_ranges = ARRAY_SIZE(da9061_aa_readable_ranges), 553 }; 554 555 static const struct regmap_access_table da9061_aa_writeable_table = { 556 .yes_ranges = da9061_aa_writeable_ranges, 557 .n_yes_ranges = ARRAY_SIZE(da9061_aa_writeable_ranges), 558 }; 559 560 static const struct regmap_access_table da9061_aa_volatile_table = { 561 .yes_ranges = da9061_aa_volatile_ranges, 562 .n_yes_ranges = ARRAY_SIZE(da9061_aa_volatile_ranges), 563 }; 564 565 static const struct regmap_range_cfg da9061_range_cfg[] = { 566 { 567 .range_min = DA9062AA_PAGE_CON, 568 .range_max = DA9062AA_CONFIG_ID, 569 .selector_reg = DA9062AA_PAGE_CON, 570 .selector_mask = 1 << DA9062_I2C_PAGE_SEL_SHIFT, 571 .selector_shift = DA9062_I2C_PAGE_SEL_SHIFT, 572 .window_start = 0, 573 .window_len = 256, 574 } 575 }; 576 577 static struct regmap_config da9061_regmap_config = { 578 .reg_bits = 8, 579 .val_bits = 8, 580 .ranges = da9061_range_cfg, 581 .num_ranges = ARRAY_SIZE(da9061_range_cfg), 582 .max_register = DA9062AA_CONFIG_ID, 583 .cache_type = REGCACHE_RBTREE, 584 .rd_table = &da9061_aa_readable_table, 585 .wr_table = &da9061_aa_writeable_table, 586 .volatile_table = &da9061_aa_volatile_table, 587 }; 588 589 static const struct regmap_range da9062_aa_readable_ranges[] = { 590 { 591 .range_min = DA9062AA_PAGE_CON, 592 .range_max = DA9062AA_STATUS_B, 593 }, { 594 .range_min = DA9062AA_STATUS_D, 595 .range_max = DA9062AA_EVENT_C, 596 }, { 597 .range_min = DA9062AA_IRQ_MASK_A, 598 .range_max = DA9062AA_IRQ_MASK_C, 599 }, { 600 .range_min = DA9062AA_CONTROL_A, 601 .range_max = DA9062AA_GPIO_4, 602 }, { 603 .range_min = DA9062AA_GPIO_WKUP_MODE, 604 .range_max = DA9062AA_BUCK4_CONT, 605 }, { 606 .range_min = DA9062AA_BUCK3_CONT, 607 .range_max = DA9062AA_BUCK3_CONT, 608 }, { 609 .range_min = DA9062AA_LDO1_CONT, 610 .range_max = DA9062AA_LDO4_CONT, 611 }, { 612 .range_min = DA9062AA_DVC_1, 613 .range_max = DA9062AA_DVC_1, 614 }, { 615 .range_min = DA9062AA_COUNT_S, 616 .range_max = DA9062AA_SECOND_D, 617 }, { 618 .range_min = DA9062AA_SEQ, 619 .range_max = DA9062AA_ID_4_3, 620 }, { 621 .range_min = DA9062AA_ID_12_11, 622 .range_max = DA9062AA_ID_16_15, 623 }, { 624 .range_min = DA9062AA_ID_22_21, 625 .range_max = DA9062AA_ID_32_31, 626 }, { 627 .range_min = DA9062AA_SEQ_A, 628 .range_max = DA9062AA_BUCK3_CFG, 629 }, { 630 .range_min = DA9062AA_VBUCK2_A, 631 .range_max = DA9062AA_VBUCK4_A, 632 }, { 633 .range_min = DA9062AA_VBUCK3_A, 634 .range_max = DA9062AA_VBUCK3_A, 635 }, { 636 .range_min = DA9062AA_VLDO1_A, 637 .range_max = DA9062AA_VLDO4_A, 638 }, { 639 .range_min = DA9062AA_VBUCK2_B, 640 .range_max = DA9062AA_VBUCK4_B, 641 }, { 642 .range_min = DA9062AA_VBUCK3_B, 643 .range_max = DA9062AA_VBUCK3_B, 644 }, { 645 .range_min = DA9062AA_VLDO1_B, 646 .range_max = DA9062AA_VLDO4_B, 647 }, { 648 .range_min = DA9062AA_BBAT_CONT, 649 .range_max = DA9062AA_BBAT_CONT, 650 }, { 651 .range_min = DA9062AA_INTERFACE, 652 .range_max = DA9062AA_CONFIG_E, 653 }, { 654 .range_min = DA9062AA_CONFIG_G, 655 .range_max = DA9062AA_CONFIG_K, 656 }, { 657 .range_min = DA9062AA_CONFIG_M, 658 .range_max = DA9062AA_CONFIG_M, 659 }, { 660 .range_min = DA9062AA_TRIM_CLDR, 661 .range_max = DA9062AA_GP_ID_19, 662 }, { 663 .range_min = DA9062AA_DEVICE_ID, 664 .range_max = DA9062AA_CONFIG_ID, 665 }, 666 }; 667 668 static const struct regmap_range da9062_aa_writeable_ranges[] = { 669 { 670 .range_min = DA9062AA_PAGE_CON, 671 .range_max = DA9062AA_PAGE_CON, 672 }, { 673 .range_min = DA9062AA_FAULT_LOG, 674 .range_max = DA9062AA_EVENT_C, 675 }, { 676 .range_min = DA9062AA_IRQ_MASK_A, 677 .range_max = DA9062AA_IRQ_MASK_C, 678 }, { 679 .range_min = DA9062AA_CONTROL_A, 680 .range_max = DA9062AA_GPIO_4, 681 }, { 682 .range_min = DA9062AA_GPIO_WKUP_MODE, 683 .range_max = DA9062AA_BUCK4_CONT, 684 }, { 685 .range_min = DA9062AA_BUCK3_CONT, 686 .range_max = DA9062AA_BUCK3_CONT, 687 }, { 688 .range_min = DA9062AA_LDO1_CONT, 689 .range_max = DA9062AA_LDO4_CONT, 690 }, { 691 .range_min = DA9062AA_DVC_1, 692 .range_max = DA9062AA_DVC_1, 693 }, { 694 .range_min = DA9062AA_COUNT_S, 695 .range_max = DA9062AA_ALARM_Y, 696 }, { 697 .range_min = DA9062AA_SEQ, 698 .range_max = DA9062AA_ID_4_3, 699 }, { 700 .range_min = DA9062AA_ID_12_11, 701 .range_max = DA9062AA_ID_16_15, 702 }, { 703 .range_min = DA9062AA_ID_22_21, 704 .range_max = DA9062AA_ID_32_31, 705 }, { 706 .range_min = DA9062AA_SEQ_A, 707 .range_max = DA9062AA_BUCK3_CFG, 708 }, { 709 .range_min = DA9062AA_VBUCK2_A, 710 .range_max = DA9062AA_VBUCK4_A, 711 }, { 712 .range_min = DA9062AA_VBUCK3_A, 713 .range_max = DA9062AA_VBUCK3_A, 714 }, { 715 .range_min = DA9062AA_VLDO1_A, 716 .range_max = DA9062AA_VLDO4_A, 717 }, { 718 .range_min = DA9062AA_VBUCK2_B, 719 .range_max = DA9062AA_VBUCK4_B, 720 }, { 721 .range_min = DA9062AA_VBUCK3_B, 722 .range_max = DA9062AA_VBUCK3_B, 723 }, { 724 .range_min = DA9062AA_VLDO1_B, 725 .range_max = DA9062AA_VLDO4_B, 726 }, { 727 .range_min = DA9062AA_BBAT_CONT, 728 .range_max = DA9062AA_BBAT_CONT, 729 }, { 730 .range_min = DA9062AA_GP_ID_0, 731 .range_max = DA9062AA_GP_ID_19, 732 }, 733 }; 734 735 static const struct regmap_range da9062_aa_volatile_ranges[] = { 736 { 737 .range_min = DA9062AA_PAGE_CON, 738 .range_max = DA9062AA_STATUS_B, 739 }, { 740 .range_min = DA9062AA_STATUS_D, 741 .range_max = DA9062AA_EVENT_C, 742 }, { 743 .range_min = DA9062AA_CONTROL_A, 744 .range_max = DA9062AA_CONTROL_B, 745 }, { 746 .range_min = DA9062AA_CONTROL_E, 747 .range_max = DA9062AA_CONTROL_F, 748 }, { 749 .range_min = DA9062AA_BUCK2_CONT, 750 .range_max = DA9062AA_BUCK4_CONT, 751 }, { 752 .range_min = DA9062AA_BUCK3_CONT, 753 .range_max = DA9062AA_BUCK3_CONT, 754 }, { 755 .range_min = DA9062AA_LDO1_CONT, 756 .range_max = DA9062AA_LDO4_CONT, 757 }, { 758 .range_min = DA9062AA_DVC_1, 759 .range_max = DA9062AA_DVC_1, 760 }, { 761 .range_min = DA9062AA_COUNT_S, 762 .range_max = DA9062AA_SECOND_D, 763 }, { 764 .range_min = DA9062AA_SEQ, 765 .range_max = DA9062AA_SEQ, 766 }, { 767 .range_min = DA9062AA_EN_32K, 768 .range_max = DA9062AA_EN_32K, 769 }, 770 }; 771 772 static const struct regmap_access_table da9062_aa_readable_table = { 773 .yes_ranges = da9062_aa_readable_ranges, 774 .n_yes_ranges = ARRAY_SIZE(da9062_aa_readable_ranges), 775 }; 776 777 static const struct regmap_access_table da9062_aa_writeable_table = { 778 .yes_ranges = da9062_aa_writeable_ranges, 779 .n_yes_ranges = ARRAY_SIZE(da9062_aa_writeable_ranges), 780 }; 781 782 static const struct regmap_access_table da9062_aa_volatile_table = { 783 .yes_ranges = da9062_aa_volatile_ranges, 784 .n_yes_ranges = ARRAY_SIZE(da9062_aa_volatile_ranges), 785 }; 786 787 static const struct regmap_range_cfg da9062_range_cfg[] = { 788 { 789 .range_min = DA9062AA_PAGE_CON, 790 .range_max = DA9062AA_CONFIG_ID, 791 .selector_reg = DA9062AA_PAGE_CON, 792 .selector_mask = 1 << DA9062_I2C_PAGE_SEL_SHIFT, 793 .selector_shift = DA9062_I2C_PAGE_SEL_SHIFT, 794 .window_start = 0, 795 .window_len = 256, 796 } 797 }; 798 799 static struct regmap_config da9062_regmap_config = { 800 .reg_bits = 8, 801 .val_bits = 8, 802 .ranges = da9062_range_cfg, 803 .num_ranges = ARRAY_SIZE(da9062_range_cfg), 804 .max_register = DA9062AA_CONFIG_ID, 805 .cache_type = REGCACHE_RBTREE, 806 .rd_table = &da9062_aa_readable_table, 807 .wr_table = &da9062_aa_writeable_table, 808 .volatile_table = &da9062_aa_volatile_table, 809 }; 810 811 static const struct of_device_id da9062_dt_ids[] = { 812 { .compatible = "dlg,da9061", .data = (void *)COMPAT_TYPE_DA9061, }, 813 { .compatible = "dlg,da9062", .data = (void *)COMPAT_TYPE_DA9062, }, 814 { } 815 }; 816 MODULE_DEVICE_TABLE(of, da9062_dt_ids); 817 818 static int da9062_i2c_probe(struct i2c_client *i2c, 819 const struct i2c_device_id *id) 820 { 821 struct da9062 *chip; 822 const struct of_device_id *match; 823 unsigned int irq_base; 824 const struct mfd_cell *cell; 825 const struct regmap_irq_chip *irq_chip; 826 const struct regmap_config *config; 827 int cell_num; 828 int ret; 829 830 chip = devm_kzalloc(&i2c->dev, sizeof(*chip), GFP_KERNEL); 831 if (!chip) 832 return -ENOMEM; 833 834 if (i2c->dev.of_node) { 835 match = of_match_node(da9062_dt_ids, i2c->dev.of_node); 836 if (!match) 837 return -EINVAL; 838 839 chip->chip_type = (uintptr_t)match->data; 840 } else { 841 chip->chip_type = id->driver_data; 842 } 843 844 i2c_set_clientdata(i2c, chip); 845 chip->dev = &i2c->dev; 846 847 if (!i2c->irq) { 848 dev_err(chip->dev, "No IRQ configured\n"); 849 return -EINVAL; 850 } 851 852 switch (chip->chip_type) { 853 case COMPAT_TYPE_DA9061: 854 cell = da9061_devs; 855 cell_num = ARRAY_SIZE(da9061_devs); 856 irq_chip = &da9061_irq_chip; 857 config = &da9061_regmap_config; 858 break; 859 case COMPAT_TYPE_DA9062: 860 cell = da9062_devs; 861 cell_num = ARRAY_SIZE(da9062_devs); 862 irq_chip = &da9062_irq_chip; 863 config = &da9062_regmap_config; 864 break; 865 default: 866 dev_err(chip->dev, "Unrecognised chip type\n"); 867 return -ENODEV; 868 } 869 870 chip->regmap = devm_regmap_init_i2c(i2c, config); 871 if (IS_ERR(chip->regmap)) { 872 ret = PTR_ERR(chip->regmap); 873 dev_err(chip->dev, "Failed to allocate register map: %d\n", 874 ret); 875 return ret; 876 } 877 878 ret = da9062_clear_fault_log(chip); 879 if (ret < 0) 880 dev_warn(chip->dev, "Cannot clear fault log\n"); 881 882 ret = da9062_get_device_type(chip); 883 if (ret) 884 return ret; 885 886 ret = regmap_add_irq_chip(chip->regmap, i2c->irq, 887 IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED, 888 -1, irq_chip, 889 &chip->regmap_irq); 890 if (ret) { 891 dev_err(chip->dev, "Failed to request IRQ %d: %d\n", 892 i2c->irq, ret); 893 return ret; 894 } 895 896 irq_base = regmap_irq_chip_get_base(chip->regmap_irq); 897 898 ret = mfd_add_devices(chip->dev, PLATFORM_DEVID_NONE, cell, 899 cell_num, NULL, irq_base, 900 NULL); 901 if (ret) { 902 dev_err(chip->dev, "Cannot register child devices\n"); 903 regmap_del_irq_chip(i2c->irq, chip->regmap_irq); 904 return ret; 905 } 906 907 return ret; 908 } 909 910 static int da9062_i2c_remove(struct i2c_client *i2c) 911 { 912 struct da9062 *chip = i2c_get_clientdata(i2c); 913 914 mfd_remove_devices(chip->dev); 915 regmap_del_irq_chip(i2c->irq, chip->regmap_irq); 916 917 return 0; 918 } 919 920 static const struct i2c_device_id da9062_i2c_id[] = { 921 { "da9061", COMPAT_TYPE_DA9061 }, 922 { "da9062", COMPAT_TYPE_DA9062 }, 923 { }, 924 }; 925 MODULE_DEVICE_TABLE(i2c, da9062_i2c_id); 926 927 static struct i2c_driver da9062_i2c_driver = { 928 .driver = { 929 .name = "da9062", 930 .of_match_table = of_match_ptr(da9062_dt_ids), 931 }, 932 .probe = da9062_i2c_probe, 933 .remove = da9062_i2c_remove, 934 .id_table = da9062_i2c_id, 935 }; 936 937 module_i2c_driver(da9062_i2c_driver); 938 939 MODULE_DESCRIPTION("Core device driver for Dialog DA9061 and DA9062"); 940 MODULE_AUTHOR("Steve Twiss <stwiss.opensource@diasemi.com>"); 941 MODULE_LICENSE("GPL"); 942