1 /* 2 * Core, IRQ and I2C device driver for DA9062 PMIC 3 * Copyright (C) 2015 Dialog Semiconductor Ltd. 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 da9062_irqs[] = { 34 /* EVENT A */ 35 [DA9062_IRQ_ONKEY] = { 36 .reg_offset = DA9062_REG_EVENT_A_OFFSET, 37 .mask = DA9062AA_M_NONKEY_MASK, 38 }, 39 [DA9062_IRQ_ALARM] = { 40 .reg_offset = DA9062_REG_EVENT_A_OFFSET, 41 .mask = DA9062AA_M_ALARM_MASK, 42 }, 43 [DA9062_IRQ_TICK] = { 44 .reg_offset = DA9062_REG_EVENT_A_OFFSET, 45 .mask = DA9062AA_M_TICK_MASK, 46 }, 47 [DA9062_IRQ_WDG_WARN] = { 48 .reg_offset = DA9062_REG_EVENT_A_OFFSET, 49 .mask = DA9062AA_M_WDG_WARN_MASK, 50 }, 51 [DA9062_IRQ_SEQ_RDY] = { 52 .reg_offset = DA9062_REG_EVENT_A_OFFSET, 53 .mask = DA9062AA_M_SEQ_RDY_MASK, 54 }, 55 /* EVENT B */ 56 [DA9062_IRQ_TEMP] = { 57 .reg_offset = DA9062_REG_EVENT_B_OFFSET, 58 .mask = DA9062AA_M_TEMP_MASK, 59 }, 60 [DA9062_IRQ_LDO_LIM] = { 61 .reg_offset = DA9062_REG_EVENT_B_OFFSET, 62 .mask = DA9062AA_M_LDO_LIM_MASK, 63 }, 64 [DA9062_IRQ_DVC_RDY] = { 65 .reg_offset = DA9062_REG_EVENT_B_OFFSET, 66 .mask = DA9062AA_M_DVC_RDY_MASK, 67 }, 68 [DA9062_IRQ_VDD_WARN] = { 69 .reg_offset = DA9062_REG_EVENT_B_OFFSET, 70 .mask = DA9062AA_M_VDD_WARN_MASK, 71 }, 72 /* EVENT C */ 73 [DA9062_IRQ_GPI0] = { 74 .reg_offset = DA9062_REG_EVENT_C_OFFSET, 75 .mask = DA9062AA_M_GPI0_MASK, 76 }, 77 [DA9062_IRQ_GPI1] = { 78 .reg_offset = DA9062_REG_EVENT_C_OFFSET, 79 .mask = DA9062AA_M_GPI1_MASK, 80 }, 81 [DA9062_IRQ_GPI2] = { 82 .reg_offset = DA9062_REG_EVENT_C_OFFSET, 83 .mask = DA9062AA_M_GPI2_MASK, 84 }, 85 [DA9062_IRQ_GPI3] = { 86 .reg_offset = DA9062_REG_EVENT_C_OFFSET, 87 .mask = DA9062AA_M_GPI3_MASK, 88 }, 89 [DA9062_IRQ_GPI4] = { 90 .reg_offset = DA9062_REG_EVENT_C_OFFSET, 91 .mask = DA9062AA_M_GPI4_MASK, 92 }, 93 }; 94 95 static struct regmap_irq_chip da9062_irq_chip = { 96 .name = "da9062-irq", 97 .irqs = da9062_irqs, 98 .num_irqs = DA9062_NUM_IRQ, 99 .num_regs = 3, 100 .status_base = DA9062AA_EVENT_A, 101 .mask_base = DA9062AA_IRQ_MASK_A, 102 .ack_base = DA9062AA_EVENT_A, 103 }; 104 105 static struct resource da9062_core_resources[] = { 106 DEFINE_RES_NAMED(DA9062_IRQ_VDD_WARN, 1, "VDD_WARN", IORESOURCE_IRQ), 107 }; 108 109 static struct resource da9062_regulators_resources[] = { 110 DEFINE_RES_NAMED(DA9062_IRQ_LDO_LIM, 1, "LDO_LIM", IORESOURCE_IRQ), 111 }; 112 113 static struct resource da9062_thermal_resources[] = { 114 DEFINE_RES_NAMED(DA9062_IRQ_TEMP, 1, "THERMAL", IORESOURCE_IRQ), 115 }; 116 117 static struct resource da9062_wdt_resources[] = { 118 DEFINE_RES_NAMED(DA9062_IRQ_WDG_WARN, 1, "WD_WARN", IORESOURCE_IRQ), 119 }; 120 121 static struct resource da9062_rtc_resources[] = { 122 DEFINE_RES_NAMED(DA9062_IRQ_ALARM, 1, "ALARM", IORESOURCE_IRQ), 123 DEFINE_RES_NAMED(DA9062_IRQ_TICK, 1, "TICK", IORESOURCE_IRQ), 124 }; 125 126 static struct resource da9062_onkey_resources[] = { 127 DEFINE_RES_NAMED(DA9062_IRQ_ONKEY, 1, "ONKEY", IORESOURCE_IRQ), 128 }; 129 130 static const struct mfd_cell da9062_devs[] = { 131 { 132 .name = "da9062-core", 133 .num_resources = ARRAY_SIZE(da9062_core_resources), 134 .resources = da9062_core_resources, 135 }, 136 { 137 .name = "da9062-regulators", 138 .num_resources = ARRAY_SIZE(da9062_regulators_resources), 139 .resources = da9062_regulators_resources, 140 }, 141 { 142 .name = "da9062-watchdog", 143 .num_resources = ARRAY_SIZE(da9062_wdt_resources), 144 .resources = da9062_wdt_resources, 145 .of_compatible = "dlg,da9062-wdt", 146 }, 147 { 148 .name = "da9062-thermal", 149 .num_resources = ARRAY_SIZE(da9062_thermal_resources), 150 .resources = da9062_thermal_resources, 151 .of_compatible = "dlg,da9062-thermal", 152 }, 153 { 154 .name = "da9062-rtc", 155 .num_resources = ARRAY_SIZE(da9062_rtc_resources), 156 .resources = da9062_rtc_resources, 157 .of_compatible = "dlg,da9062-rtc", 158 }, 159 { 160 .name = "da9062-onkey", 161 .num_resources = ARRAY_SIZE(da9062_onkey_resources), 162 .resources = da9062_onkey_resources, 163 .of_compatible = "dlg,da9062-onkey", 164 }, 165 }; 166 167 static int da9062_clear_fault_log(struct da9062 *chip) 168 { 169 int ret; 170 int fault_log; 171 172 ret = regmap_read(chip->regmap, DA9062AA_FAULT_LOG, &fault_log); 173 if (ret < 0) 174 return ret; 175 176 if (fault_log) { 177 if (fault_log & DA9062AA_TWD_ERROR_MASK) 178 dev_dbg(chip->dev, "Fault log entry detected: TWD_ERROR\n"); 179 if (fault_log & DA9062AA_POR_MASK) 180 dev_dbg(chip->dev, "Fault log entry detected: POR\n"); 181 if (fault_log & DA9062AA_VDD_FAULT_MASK) 182 dev_dbg(chip->dev, "Fault log entry detected: VDD_FAULT\n"); 183 if (fault_log & DA9062AA_VDD_START_MASK) 184 dev_dbg(chip->dev, "Fault log entry detected: VDD_START\n"); 185 if (fault_log & DA9062AA_TEMP_CRIT_MASK) 186 dev_dbg(chip->dev, "Fault log entry detected: TEMP_CRIT\n"); 187 if (fault_log & DA9062AA_KEY_RESET_MASK) 188 dev_dbg(chip->dev, "Fault log entry detected: KEY_RESET\n"); 189 if (fault_log & DA9062AA_NSHUTDOWN_MASK) 190 dev_dbg(chip->dev, "Fault log entry detected: NSHUTDOWN\n"); 191 if (fault_log & DA9062AA_WAIT_SHUT_MASK) 192 dev_dbg(chip->dev, "Fault log entry detected: WAIT_SHUT\n"); 193 194 ret = regmap_write(chip->regmap, DA9062AA_FAULT_LOG, 195 fault_log); 196 } 197 198 return ret; 199 } 200 201 int get_device_type(struct da9062 *chip) 202 { 203 int device_id, variant_id, variant_mrc; 204 int ret; 205 206 ret = regmap_read(chip->regmap, DA9062AA_DEVICE_ID, &device_id); 207 if (ret < 0) { 208 dev_err(chip->dev, "Cannot read chip ID.\n"); 209 return -EIO; 210 } 211 if (device_id != DA9062_PMIC_DEVICE_ID) { 212 dev_err(chip->dev, "Invalid device ID: 0x%02x\n", device_id); 213 return -ENODEV; 214 } 215 216 ret = regmap_read(chip->regmap, DA9062AA_VARIANT_ID, &variant_id); 217 if (ret < 0) { 218 dev_err(chip->dev, "Cannot read chip variant id.\n"); 219 return -EIO; 220 } 221 222 dev_info(chip->dev, 223 "Device detected (device-ID: 0x%02X, var-ID: 0x%02X)\n", 224 device_id, variant_id); 225 226 variant_mrc = (variant_id & DA9062AA_MRC_MASK) >> DA9062AA_MRC_SHIFT; 227 228 if (variant_mrc < DA9062_PMIC_VARIANT_MRC_AA) { 229 dev_err(chip->dev, 230 "Cannot support variant MRC: 0x%02X\n", variant_mrc); 231 return -ENODEV; 232 } 233 234 return ret; 235 } 236 237 static const struct regmap_range da9062_aa_readable_ranges[] = { 238 { 239 .range_min = DA9062AA_PAGE_CON, 240 .range_max = DA9062AA_STATUS_B, 241 }, { 242 .range_min = DA9062AA_STATUS_D, 243 .range_max = DA9062AA_EVENT_C, 244 }, { 245 .range_min = DA9062AA_IRQ_MASK_A, 246 .range_max = DA9062AA_IRQ_MASK_C, 247 }, { 248 .range_min = DA9062AA_CONTROL_A, 249 .range_max = DA9062AA_GPIO_4, 250 }, { 251 .range_min = DA9062AA_GPIO_WKUP_MODE, 252 .range_max = DA9062AA_BUCK4_CONT, 253 }, { 254 .range_min = DA9062AA_BUCK3_CONT, 255 .range_max = DA9062AA_BUCK3_CONT, 256 }, { 257 .range_min = DA9062AA_LDO1_CONT, 258 .range_max = DA9062AA_LDO4_CONT, 259 }, { 260 .range_min = DA9062AA_DVC_1, 261 .range_max = DA9062AA_DVC_1, 262 }, { 263 .range_min = DA9062AA_COUNT_S, 264 .range_max = DA9062AA_SECOND_D, 265 }, { 266 .range_min = DA9062AA_SEQ, 267 .range_max = DA9062AA_ID_4_3, 268 }, { 269 .range_min = DA9062AA_ID_12_11, 270 .range_max = DA9062AA_ID_16_15, 271 }, { 272 .range_min = DA9062AA_ID_22_21, 273 .range_max = DA9062AA_ID_32_31, 274 }, { 275 .range_min = DA9062AA_SEQ_A, 276 .range_max = DA9062AA_BUCK3_CFG, 277 }, { 278 .range_min = DA9062AA_VBUCK2_A, 279 .range_max = DA9062AA_VBUCK4_A, 280 }, { 281 .range_min = DA9062AA_VBUCK3_A, 282 .range_max = DA9062AA_VBUCK3_A, 283 }, { 284 .range_min = DA9062AA_VLDO1_A, 285 .range_max = DA9062AA_VLDO4_A, 286 }, { 287 .range_min = DA9062AA_VBUCK2_B, 288 .range_max = DA9062AA_VBUCK4_B, 289 }, { 290 .range_min = DA9062AA_VBUCK3_B, 291 .range_max = DA9062AA_VBUCK3_B, 292 }, { 293 .range_min = DA9062AA_VLDO1_B, 294 .range_max = DA9062AA_VLDO4_B, 295 }, { 296 .range_min = DA9062AA_BBAT_CONT, 297 .range_max = DA9062AA_BBAT_CONT, 298 }, { 299 .range_min = DA9062AA_INTERFACE, 300 .range_max = DA9062AA_CONFIG_E, 301 }, { 302 .range_min = DA9062AA_CONFIG_G, 303 .range_max = DA9062AA_CONFIG_K, 304 }, { 305 .range_min = DA9062AA_CONFIG_M, 306 .range_max = DA9062AA_CONFIG_M, 307 }, { 308 .range_min = DA9062AA_TRIM_CLDR, 309 .range_max = DA9062AA_GP_ID_19, 310 }, { 311 .range_min = DA9062AA_DEVICE_ID, 312 .range_max = DA9062AA_CONFIG_ID, 313 }, 314 }; 315 316 static const struct regmap_range da9062_aa_writeable_ranges[] = { 317 { 318 .range_min = DA9062AA_PAGE_CON, 319 .range_max = DA9062AA_PAGE_CON, 320 }, { 321 .range_min = DA9062AA_FAULT_LOG, 322 .range_max = DA9062AA_EVENT_C, 323 }, { 324 .range_min = DA9062AA_IRQ_MASK_A, 325 .range_max = DA9062AA_IRQ_MASK_C, 326 }, { 327 .range_min = DA9062AA_CONTROL_A, 328 .range_max = DA9062AA_GPIO_4, 329 }, { 330 .range_min = DA9062AA_GPIO_WKUP_MODE, 331 .range_max = DA9062AA_BUCK4_CONT, 332 }, { 333 .range_min = DA9062AA_BUCK3_CONT, 334 .range_max = DA9062AA_BUCK3_CONT, 335 }, { 336 .range_min = DA9062AA_LDO1_CONT, 337 .range_max = DA9062AA_LDO4_CONT, 338 }, { 339 .range_min = DA9062AA_DVC_1, 340 .range_max = DA9062AA_DVC_1, 341 }, { 342 .range_min = DA9062AA_COUNT_S, 343 .range_max = DA9062AA_ALARM_Y, 344 }, { 345 .range_min = DA9062AA_SEQ, 346 .range_max = DA9062AA_ID_4_3, 347 }, { 348 .range_min = DA9062AA_ID_12_11, 349 .range_max = DA9062AA_ID_16_15, 350 }, { 351 .range_min = DA9062AA_ID_22_21, 352 .range_max = DA9062AA_ID_32_31, 353 }, { 354 .range_min = DA9062AA_SEQ_A, 355 .range_max = DA9062AA_BUCK3_CFG, 356 }, { 357 .range_min = DA9062AA_VBUCK2_A, 358 .range_max = DA9062AA_VBUCK4_A, 359 }, { 360 .range_min = DA9062AA_VBUCK3_A, 361 .range_max = DA9062AA_VBUCK3_A, 362 }, { 363 .range_min = DA9062AA_VLDO1_A, 364 .range_max = DA9062AA_VLDO4_A, 365 }, { 366 .range_min = DA9062AA_VBUCK2_B, 367 .range_max = DA9062AA_VBUCK4_B, 368 }, { 369 .range_min = DA9062AA_VBUCK3_B, 370 .range_max = DA9062AA_VBUCK3_B, 371 }, { 372 .range_min = DA9062AA_VLDO1_B, 373 .range_max = DA9062AA_VLDO4_B, 374 }, { 375 .range_min = DA9062AA_BBAT_CONT, 376 .range_max = DA9062AA_BBAT_CONT, 377 }, { 378 .range_min = DA9062AA_GP_ID_0, 379 .range_max = DA9062AA_GP_ID_19, 380 }, 381 }; 382 383 static const struct regmap_range da9062_aa_volatile_ranges[] = { 384 { 385 .range_min = DA9062AA_PAGE_CON, 386 .range_max = DA9062AA_STATUS_B, 387 }, { 388 .range_min = DA9062AA_STATUS_D, 389 .range_max = DA9062AA_EVENT_C, 390 }, { 391 .range_min = DA9062AA_CONTROL_F, 392 .range_max = DA9062AA_CONTROL_F, 393 }, { 394 .range_min = DA9062AA_COUNT_S, 395 .range_max = DA9062AA_SECOND_D, 396 }, 397 }; 398 399 static const struct regmap_access_table da9062_aa_readable_table = { 400 .yes_ranges = da9062_aa_readable_ranges, 401 .n_yes_ranges = ARRAY_SIZE(da9062_aa_readable_ranges), 402 }; 403 404 static const struct regmap_access_table da9062_aa_writeable_table = { 405 .yes_ranges = da9062_aa_writeable_ranges, 406 .n_yes_ranges = ARRAY_SIZE(da9062_aa_writeable_ranges), 407 }; 408 409 static const struct regmap_access_table da9062_aa_volatile_table = { 410 .yes_ranges = da9062_aa_volatile_ranges, 411 .n_yes_ranges = ARRAY_SIZE(da9062_aa_volatile_ranges), 412 }; 413 414 static const struct regmap_range_cfg da9062_range_cfg[] = { 415 { 416 .range_min = DA9062AA_PAGE_CON, 417 .range_max = DA9062AA_CONFIG_ID, 418 .selector_reg = DA9062AA_PAGE_CON, 419 .selector_mask = 1 << DA9062_I2C_PAGE_SEL_SHIFT, 420 .selector_shift = DA9062_I2C_PAGE_SEL_SHIFT, 421 .window_start = 0, 422 .window_len = 256, 423 } 424 }; 425 426 static struct regmap_config da9062_regmap_config = { 427 .reg_bits = 8, 428 .val_bits = 8, 429 .ranges = da9062_range_cfg, 430 .num_ranges = ARRAY_SIZE(da9062_range_cfg), 431 .max_register = DA9062AA_CONFIG_ID, 432 .cache_type = REGCACHE_RBTREE, 433 .rd_table = &da9062_aa_readable_table, 434 .wr_table = &da9062_aa_writeable_table, 435 .volatile_table = &da9062_aa_volatile_table, 436 }; 437 438 static int da9062_i2c_probe(struct i2c_client *i2c, 439 const struct i2c_device_id *id) 440 { 441 struct da9062 *chip; 442 unsigned int irq_base; 443 int ret; 444 445 chip = devm_kzalloc(&i2c->dev, sizeof(*chip), GFP_KERNEL); 446 if (!chip) 447 return -ENOMEM; 448 449 i2c_set_clientdata(i2c, chip); 450 chip->dev = &i2c->dev; 451 452 if (!i2c->irq) { 453 dev_err(chip->dev, "No IRQ configured\n"); 454 return -EINVAL; 455 } 456 457 chip->regmap = devm_regmap_init_i2c(i2c, &da9062_regmap_config); 458 if (IS_ERR(chip->regmap)) { 459 ret = PTR_ERR(chip->regmap); 460 dev_err(chip->dev, "Failed to allocate register map: %d\n", 461 ret); 462 return ret; 463 } 464 465 ret = da9062_clear_fault_log(chip); 466 if (ret < 0) 467 dev_warn(chip->dev, "Cannot clear fault log\n"); 468 469 ret = get_device_type(chip); 470 if (ret) 471 return ret; 472 473 ret = regmap_add_irq_chip(chip->regmap, i2c->irq, 474 IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED, 475 -1, &da9062_irq_chip, 476 &chip->regmap_irq); 477 if (ret) { 478 dev_err(chip->dev, "Failed to request IRQ %d: %d\n", 479 i2c->irq, ret); 480 return ret; 481 } 482 483 irq_base = regmap_irq_chip_get_base(chip->regmap_irq); 484 485 ret = mfd_add_devices(chip->dev, PLATFORM_DEVID_NONE, da9062_devs, 486 ARRAY_SIZE(da9062_devs), NULL, irq_base, 487 NULL); 488 if (ret) { 489 dev_err(chip->dev, "Cannot register child devices\n"); 490 regmap_del_irq_chip(i2c->irq, chip->regmap_irq); 491 return ret; 492 } 493 494 return ret; 495 } 496 497 static int da9062_i2c_remove(struct i2c_client *i2c) 498 { 499 struct da9062 *chip = i2c_get_clientdata(i2c); 500 501 mfd_remove_devices(chip->dev); 502 regmap_del_irq_chip(i2c->irq, chip->regmap_irq); 503 504 return 0; 505 } 506 507 static const struct i2c_device_id da9062_i2c_id[] = { 508 { "da9062", 0 }, 509 { }, 510 }; 511 MODULE_DEVICE_TABLE(i2c, da9062_i2c_id); 512 513 static const struct of_device_id da9062_dt_ids[] = { 514 { .compatible = "dlg,da9062", }, 515 { } 516 }; 517 MODULE_DEVICE_TABLE(of, da9062_dt_ids); 518 519 static struct i2c_driver da9062_i2c_driver = { 520 .driver = { 521 .name = "da9062", 522 .of_match_table = of_match_ptr(da9062_dt_ids), 523 }, 524 .probe = da9062_i2c_probe, 525 .remove = da9062_i2c_remove, 526 .id_table = da9062_i2c_id, 527 }; 528 529 module_i2c_driver(da9062_i2c_driver); 530 531 MODULE_DESCRIPTION("Core device driver for Dialog DA9062"); 532 MODULE_AUTHOR("Steve Twiss <stwiss.opensource@diasemi.com>"); 533 MODULE_LICENSE("GPL"); 534