735 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Core, IRQ and I2C device driver for DA9061 and DA9062 PMICs4 * Copyright (C) 2015-2017 Dialog Semiconductor5 */6 7#include <linux/kernel.h>8#include <linux/module.h>9#include <linux/init.h>10#include <linux/device.h>11#include <linux/interrupt.h>12#include <linux/of.h>13#include <linux/regmap.h>14#include <linux/irq.h>15#include <linux/mfd/core.h>16#include <linux/i2c.h>17#include <linux/mfd/da9062/core.h>18#include <linux/mfd/da9062/registers.h>19#include <linux/regulator/of_regulator.h>20 21#define DA9062_REG_EVENT_A_OFFSET 022#define DA9062_REG_EVENT_B_OFFSET 123#define DA9062_REG_EVENT_C_OFFSET 224 25#define DA9062_IRQ_LOW 026#define DA9062_IRQ_HIGH 127 28static const struct regmap_irq da9061_irqs[] = {29 /* EVENT A */30 [DA9061_IRQ_ONKEY] = {31 .reg_offset = DA9062_REG_EVENT_A_OFFSET,32 .mask = DA9062AA_M_NONKEY_MASK,33 },34 [DA9061_IRQ_WDG_WARN] = {35 .reg_offset = DA9062_REG_EVENT_A_OFFSET,36 .mask = DA9062AA_M_WDG_WARN_MASK,37 },38 [DA9061_IRQ_SEQ_RDY] = {39 .reg_offset = DA9062_REG_EVENT_A_OFFSET,40 .mask = DA9062AA_M_SEQ_RDY_MASK,41 },42 /* EVENT B */43 [DA9061_IRQ_TEMP] = {44 .reg_offset = DA9062_REG_EVENT_B_OFFSET,45 .mask = DA9062AA_M_TEMP_MASK,46 },47 [DA9061_IRQ_LDO_LIM] = {48 .reg_offset = DA9062_REG_EVENT_B_OFFSET,49 .mask = DA9062AA_M_LDO_LIM_MASK,50 },51 [DA9061_IRQ_DVC_RDY] = {52 .reg_offset = DA9062_REG_EVENT_B_OFFSET,53 .mask = DA9062AA_M_DVC_RDY_MASK,54 },55 [DA9061_IRQ_VDD_WARN] = {56 .reg_offset = DA9062_REG_EVENT_B_OFFSET,57 .mask = DA9062AA_M_VDD_WARN_MASK,58 },59 /* EVENT C */60 [DA9061_IRQ_GPI0] = {61 .reg_offset = DA9062_REG_EVENT_C_OFFSET,62 .mask = DA9062AA_M_GPI0_MASK,63 },64 [DA9061_IRQ_GPI1] = {65 .reg_offset = DA9062_REG_EVENT_C_OFFSET,66 .mask = DA9062AA_M_GPI1_MASK,67 },68 [DA9061_IRQ_GPI2] = {69 .reg_offset = DA9062_REG_EVENT_C_OFFSET,70 .mask = DA9062AA_M_GPI2_MASK,71 },72 [DA9061_IRQ_GPI3] = {73 .reg_offset = DA9062_REG_EVENT_C_OFFSET,74 .mask = DA9062AA_M_GPI3_MASK,75 },76 [DA9061_IRQ_GPI4] = {77 .reg_offset = DA9062_REG_EVENT_C_OFFSET,78 .mask = DA9062AA_M_GPI4_MASK,79 },80};81 82static const struct regmap_irq_chip da9061_irq_chip = {83 .name = "da9061-irq",84 .irqs = da9061_irqs,85 .num_irqs = DA9061_NUM_IRQ,86 .num_regs = 3,87 .status_base = DA9062AA_EVENT_A,88 .mask_base = DA9062AA_IRQ_MASK_A,89 .ack_base = DA9062AA_EVENT_A,90};91 92static const struct regmap_irq da9062_irqs[] = {93 /* EVENT A */94 [DA9062_IRQ_ONKEY] = {95 .reg_offset = DA9062_REG_EVENT_A_OFFSET,96 .mask = DA9062AA_M_NONKEY_MASK,97 },98 [DA9062_IRQ_ALARM] = {99 .reg_offset = DA9062_REG_EVENT_A_OFFSET,100 .mask = DA9062AA_M_ALARM_MASK,101 },102 [DA9062_IRQ_TICK] = {103 .reg_offset = DA9062_REG_EVENT_A_OFFSET,104 .mask = DA9062AA_M_TICK_MASK,105 },106 [DA9062_IRQ_WDG_WARN] = {107 .reg_offset = DA9062_REG_EVENT_A_OFFSET,108 .mask = DA9062AA_M_WDG_WARN_MASK,109 },110 [DA9062_IRQ_SEQ_RDY] = {111 .reg_offset = DA9062_REG_EVENT_A_OFFSET,112 .mask = DA9062AA_M_SEQ_RDY_MASK,113 },114 /* EVENT B */115 [DA9062_IRQ_TEMP] = {116 .reg_offset = DA9062_REG_EVENT_B_OFFSET,117 .mask = DA9062AA_M_TEMP_MASK,118 },119 [DA9062_IRQ_LDO_LIM] = {120 .reg_offset = DA9062_REG_EVENT_B_OFFSET,121 .mask = DA9062AA_M_LDO_LIM_MASK,122 },123 [DA9062_IRQ_DVC_RDY] = {124 .reg_offset = DA9062_REG_EVENT_B_OFFSET,125 .mask = DA9062AA_M_DVC_RDY_MASK,126 },127 [DA9062_IRQ_VDD_WARN] = {128 .reg_offset = DA9062_REG_EVENT_B_OFFSET,129 .mask = DA9062AA_M_VDD_WARN_MASK,130 },131 /* EVENT C */132 [DA9062_IRQ_GPI0] = {133 .reg_offset = DA9062_REG_EVENT_C_OFFSET,134 .mask = DA9062AA_M_GPI0_MASK,135 },136 [DA9062_IRQ_GPI1] = {137 .reg_offset = DA9062_REG_EVENT_C_OFFSET,138 .mask = DA9062AA_M_GPI1_MASK,139 },140 [DA9062_IRQ_GPI2] = {141 .reg_offset = DA9062_REG_EVENT_C_OFFSET,142 .mask = DA9062AA_M_GPI2_MASK,143 },144 [DA9062_IRQ_GPI3] = {145 .reg_offset = DA9062_REG_EVENT_C_OFFSET,146 .mask = DA9062AA_M_GPI3_MASK,147 },148 [DA9062_IRQ_GPI4] = {149 .reg_offset = DA9062_REG_EVENT_C_OFFSET,150 .mask = DA9062AA_M_GPI4_MASK,151 },152};153 154static const struct regmap_irq_chip da9062_irq_chip = {155 .name = "da9062-irq",156 .irqs = da9062_irqs,157 .num_irqs = DA9062_NUM_IRQ,158 .num_regs = 3,159 .status_base = DA9062AA_EVENT_A,160 .mask_base = DA9062AA_IRQ_MASK_A,161 .ack_base = DA9062AA_EVENT_A,162};163 164static const struct resource da9061_core_resources[] = {165 DEFINE_RES_IRQ_NAMED(DA9061_IRQ_VDD_WARN, "VDD_WARN"),166};167 168static const struct resource da9061_regulators_resources[] = {169 DEFINE_RES_IRQ_NAMED(DA9061_IRQ_LDO_LIM, "LDO_LIM"),170};171 172static const struct resource da9061_thermal_resources[] = {173 DEFINE_RES_IRQ_NAMED(DA9061_IRQ_TEMP, "THERMAL"),174};175 176static const struct resource da9061_wdt_resources[] = {177 DEFINE_RES_IRQ_NAMED(DA9061_IRQ_WDG_WARN, "WD_WARN"),178};179 180static const struct resource da9061_onkey_resources[] = {181 DEFINE_RES_IRQ_NAMED(DA9061_IRQ_ONKEY, "ONKEY"),182};183 184static const struct mfd_cell da9061_devs_irq[] = {185 MFD_CELL_OF("da9061-core", da9061_core_resources, NULL, 0, 0,186 NULL),187 MFD_CELL_OF("da9062-regulators", da9061_regulators_resources, NULL, 0, 0,188 NULL),189 MFD_CELL_OF("da9061-watchdog", da9061_wdt_resources, NULL, 0, 0,190 "dlg,da9061-watchdog"),191 MFD_CELL_OF("da9061-thermal", da9061_thermal_resources, NULL, 0, 0,192 "dlg,da9061-thermal"),193 MFD_CELL_OF("da9061-onkey", da9061_onkey_resources, NULL, 0, 0,194 "dlg,da9061-onkey"),195};196 197static const struct mfd_cell da9061_devs_noirq[] = {198 MFD_CELL_OF("da9061-core", NULL, NULL, 0, 0, NULL),199 MFD_CELL_OF("da9062-regulators", NULL, NULL, 0, 0, NULL),200 MFD_CELL_OF("da9061-watchdog", NULL, NULL, 0, 0, "dlg,da9061-watchdog"),201 MFD_CELL_OF("da9061-thermal", NULL, NULL, 0, 0, "dlg,da9061-thermal"),202 MFD_CELL_OF("da9061-onkey", NULL, NULL, 0, 0, "dlg,da9061-onkey"),203};204 205static const struct resource da9062_core_resources[] = {206 DEFINE_RES_NAMED(DA9062_IRQ_VDD_WARN, 1, "VDD_WARN", IORESOURCE_IRQ),207};208 209static const struct resource da9062_regulators_resources[] = {210 DEFINE_RES_NAMED(DA9062_IRQ_LDO_LIM, 1, "LDO_LIM", IORESOURCE_IRQ),211};212 213static const struct resource da9062_thermal_resources[] = {214 DEFINE_RES_NAMED(DA9062_IRQ_TEMP, 1, "THERMAL", IORESOURCE_IRQ),215};216 217static const struct resource da9062_wdt_resources[] = {218 DEFINE_RES_NAMED(DA9062_IRQ_WDG_WARN, 1, "WD_WARN", IORESOURCE_IRQ),219};220 221static const struct resource da9062_rtc_resources[] = {222 DEFINE_RES_NAMED(DA9062_IRQ_ALARM, 1, "ALARM", IORESOURCE_IRQ),223 DEFINE_RES_NAMED(DA9062_IRQ_TICK, 1, "TICK", IORESOURCE_IRQ),224};225 226static const struct resource da9062_onkey_resources[] = {227 DEFINE_RES_NAMED(DA9062_IRQ_ONKEY, 1, "ONKEY", IORESOURCE_IRQ),228};229 230static const struct resource da9062_gpio_resources[] = {231 DEFINE_RES_NAMED(DA9062_IRQ_GPI0, 1, "GPI0", IORESOURCE_IRQ),232 DEFINE_RES_NAMED(DA9062_IRQ_GPI1, 1, "GPI1", IORESOURCE_IRQ),233 DEFINE_RES_NAMED(DA9062_IRQ_GPI2, 1, "GPI2", IORESOURCE_IRQ),234 DEFINE_RES_NAMED(DA9062_IRQ_GPI3, 1, "GPI3", IORESOURCE_IRQ),235 DEFINE_RES_NAMED(DA9062_IRQ_GPI4, 1, "GPI4", IORESOURCE_IRQ),236};237 238static const struct mfd_cell da9062_devs_irq[] = {239 MFD_CELL_OF("da9062-core", da9062_core_resources, NULL, 0, 0,240 NULL),241 MFD_CELL_OF("da9062-regulators", da9062_regulators_resources, NULL, 0, 0,242 NULL),243 MFD_CELL_OF("da9062-watchdog", da9062_wdt_resources, NULL, 0, 0,244 "dlg,da9062-watchdog"),245 MFD_CELL_OF("da9062-thermal", da9062_thermal_resources, NULL, 0, 0,246 "dlg,da9062-thermal"),247 MFD_CELL_OF("da9062-rtc", da9062_rtc_resources, NULL, 0, 0,248 "dlg,da9062-rtc"),249 MFD_CELL_OF("da9062-onkey", da9062_onkey_resources, NULL, 0, 0,250 "dlg,da9062-onkey"),251 MFD_CELL_OF("da9062-gpio", da9062_gpio_resources, NULL, 0, 0,252 "dlg,da9062-gpio"),253};254 255static const struct mfd_cell da9062_devs_noirq[] = {256 MFD_CELL_OF("da9062-core", NULL, NULL, 0, 0, NULL),257 MFD_CELL_OF("da9062-regulators", NULL, NULL, 0, 0, NULL),258 MFD_CELL_OF("da9062-watchdog", NULL, NULL, 0, 0, "dlg,da9062-watchdog"),259 MFD_CELL_OF("da9062-thermal", NULL, NULL, 0, 0, "dlg,da9062-thermal"),260 MFD_CELL_OF("da9062-rtc", NULL, NULL, 0, 0, "dlg,da9062-rtc"),261 MFD_CELL_OF("da9062-onkey", NULL, NULL, 0, 0, "dlg,da9062-onkey"),262 MFD_CELL_OF("da9062-gpio", NULL, NULL, 0, 0, "dlg,da9062-gpio"),263};264 265static int da9062_clear_fault_log(struct da9062 *chip)266{267 int ret;268 int fault_log;269 270 ret = regmap_read(chip->regmap, DA9062AA_FAULT_LOG, &fault_log);271 if (ret < 0)272 return ret;273 274 if (fault_log) {275 if (fault_log & DA9062AA_TWD_ERROR_MASK)276 dev_dbg(chip->dev, "Fault log entry detected: TWD_ERROR\n");277 if (fault_log & DA9062AA_POR_MASK)278 dev_dbg(chip->dev, "Fault log entry detected: POR\n");279 if (fault_log & DA9062AA_VDD_FAULT_MASK)280 dev_dbg(chip->dev, "Fault log entry detected: VDD_FAULT\n");281 if (fault_log & DA9062AA_VDD_START_MASK)282 dev_dbg(chip->dev, "Fault log entry detected: VDD_START\n");283 if (fault_log & DA9062AA_TEMP_CRIT_MASK)284 dev_dbg(chip->dev, "Fault log entry detected: TEMP_CRIT\n");285 if (fault_log & DA9062AA_KEY_RESET_MASK)286 dev_dbg(chip->dev, "Fault log entry detected: KEY_RESET\n");287 if (fault_log & DA9062AA_NSHUTDOWN_MASK)288 dev_dbg(chip->dev, "Fault log entry detected: NSHUTDOWN\n");289 if (fault_log & DA9062AA_WAIT_SHUT_MASK)290 dev_dbg(chip->dev, "Fault log entry detected: WAIT_SHUT\n");291 292 ret = regmap_write(chip->regmap, DA9062AA_FAULT_LOG,293 fault_log);294 }295 296 return ret;297}298 299static int da9062_get_device_type(struct da9062 *chip)300{301 int device_id, variant_id, variant_mrc, variant_vrc;302 char *type;303 int ret;304 305 ret = regmap_read(chip->regmap, DA9062AA_DEVICE_ID, &device_id);306 if (ret < 0) {307 dev_err(chip->dev, "Cannot read chip ID.\n");308 return -EIO;309 }310 if (device_id != DA9062_PMIC_DEVICE_ID) {311 dev_err(chip->dev, "Invalid device ID: 0x%02x\n", device_id);312 return -ENODEV;313 }314 315 ret = regmap_read(chip->regmap, DA9062AA_VARIANT_ID, &variant_id);316 if (ret < 0) {317 dev_err(chip->dev, "Cannot read chip variant id.\n");318 return -EIO;319 }320 321 variant_vrc = (variant_id & DA9062AA_VRC_MASK) >> DA9062AA_VRC_SHIFT;322 323 switch (variant_vrc) {324 case DA9062_PMIC_VARIANT_VRC_DA9061:325 type = "DA9061";326 break;327 case DA9062_PMIC_VARIANT_VRC_DA9062:328 type = "DA9062";329 break;330 default:331 type = "Unknown";332 break;333 }334 335 dev_info(chip->dev,336 "Device detected (device-ID: 0x%02X, var-ID: 0x%02X, %s)\n",337 device_id, variant_id, type);338 339 variant_mrc = (variant_id & DA9062AA_MRC_MASK) >> DA9062AA_MRC_SHIFT;340 341 if (variant_mrc < DA9062_PMIC_VARIANT_MRC_AA) {342 dev_err(chip->dev,343 "Cannot support variant MRC: 0x%02X\n", variant_mrc);344 return -ENODEV;345 }346 347 return ret;348}349 350static u32 da9062_configure_irq_type(struct da9062 *chip, int irq, u32 *trigger)351{352 u32 irq_type = 0;353 struct irq_data *irq_data = irq_get_irq_data(irq);354 355 if (!irq_data) {356 dev_err(chip->dev, "Invalid IRQ: %d\n", irq);357 return -EINVAL;358 }359 *trigger = irqd_get_trigger_type(irq_data);360 361 switch (*trigger) {362 case IRQ_TYPE_LEVEL_HIGH:363 irq_type = DA9062_IRQ_HIGH;364 break;365 case IRQ_TYPE_LEVEL_LOW:366 irq_type = DA9062_IRQ_LOW;367 break;368 default:369 dev_warn(chip->dev, "Unsupported IRQ type: %d\n", *trigger);370 return -EINVAL;371 }372 return regmap_update_bits(chip->regmap, DA9062AA_CONFIG_A,373 DA9062AA_IRQ_TYPE_MASK,374 irq_type << DA9062AA_IRQ_TYPE_SHIFT);375}376 377static const struct regmap_range da9061_aa_readable_ranges[] = {378 regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B),379 regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C),380 regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C),381 regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4),382 regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_GPIO_OUT3_4),383 regmap_reg_range(DA9062AA_BUCK1_CONT, DA9062AA_BUCK4_CONT),384 regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),385 regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),386 regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),387 regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3),388 regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15),389 regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31),390 regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_WAIT),391 regmap_reg_range(DA9062AA_RESET, DA9062AA_BUCK_ILIM_C),392 regmap_reg_range(DA9062AA_BUCK1_CFG, DA9062AA_BUCK3_CFG),393 regmap_reg_range(DA9062AA_VBUCK1_A, DA9062AA_VBUCK4_A),394 regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A),395 regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A),396 regmap_reg_range(DA9062AA_CONFIG_A, DA9062AA_CONFIG_A),397 regmap_reg_range(DA9062AA_VBUCK1_B, DA9062AA_VBUCK4_B),398 regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B),399 regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B),400 regmap_reg_range(DA9062AA_INTERFACE, DA9062AA_CONFIG_E),401 regmap_reg_range(DA9062AA_CONFIG_G, DA9062AA_CONFIG_K),402 regmap_reg_range(DA9062AA_CONFIG_M, DA9062AA_CONFIG_M),403 regmap_reg_range(DA9062AA_GP_ID_0, DA9062AA_GP_ID_19),404 regmap_reg_range(DA9062AA_DEVICE_ID, DA9062AA_CONFIG_ID),405};406 407static const struct regmap_range da9061_aa_writeable_ranges[] = {408 regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_PAGE_CON),409 regmap_reg_range(DA9062AA_FAULT_LOG, DA9062AA_EVENT_C),410 regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C),411 regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4),412 regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_GPIO_OUT3_4),413 regmap_reg_range(DA9062AA_BUCK1_CONT, DA9062AA_BUCK4_CONT),414 regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),415 regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),416 regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),417 regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3),418 regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15),419 regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31),420 regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_WAIT),421 regmap_reg_range(DA9062AA_RESET, DA9062AA_BUCK_ILIM_C),422 regmap_reg_range(DA9062AA_BUCK1_CFG, DA9062AA_BUCK3_CFG),423 regmap_reg_range(DA9062AA_VBUCK1_A, DA9062AA_VBUCK4_A),424 regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A),425 regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A),426 regmap_reg_range(DA9062AA_CONFIG_A, DA9062AA_CONFIG_A),427 regmap_reg_range(DA9062AA_VBUCK1_B, DA9062AA_VBUCK4_B),428 regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B),429 regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B),430 regmap_reg_range(DA9062AA_CONFIG_J, DA9062AA_CONFIG_J),431 regmap_reg_range(DA9062AA_GP_ID_0, DA9062AA_GP_ID_19),432};433 434static const struct regmap_range da9061_aa_volatile_ranges[] = {435 regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B),436 regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C),437 regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_CONTROL_B),438 regmap_reg_range(DA9062AA_CONTROL_E, DA9062AA_CONTROL_F),439 regmap_reg_range(DA9062AA_BUCK1_CONT, DA9062AA_BUCK4_CONT),440 regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),441 regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),442 regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),443 regmap_reg_range(DA9062AA_SEQ, DA9062AA_SEQ),444};445 446static const struct regmap_access_table da9061_aa_readable_table = {447 .yes_ranges = da9061_aa_readable_ranges,448 .n_yes_ranges = ARRAY_SIZE(da9061_aa_readable_ranges),449};450 451static const struct regmap_access_table da9061_aa_writeable_table = {452 .yes_ranges = da9061_aa_writeable_ranges,453 .n_yes_ranges = ARRAY_SIZE(da9061_aa_writeable_ranges),454};455 456static const struct regmap_access_table da9061_aa_volatile_table = {457 .yes_ranges = da9061_aa_volatile_ranges,458 .n_yes_ranges = ARRAY_SIZE(da9061_aa_volatile_ranges),459};460 461static const struct regmap_range_cfg da9061_range_cfg[] = {462 {463 .range_min = DA9062AA_PAGE_CON,464 .range_max = DA9062AA_CONFIG_ID,465 .selector_reg = DA9062AA_PAGE_CON,466 .selector_mask = 1 << DA9062_I2C_PAGE_SEL_SHIFT,467 .selector_shift = DA9062_I2C_PAGE_SEL_SHIFT,468 .window_start = 0,469 .window_len = 256,470 }471};472 473static const struct regmap_config da9061_regmap_config = {474 .reg_bits = 8,475 .val_bits = 8,476 .ranges = da9061_range_cfg,477 .num_ranges = ARRAY_SIZE(da9061_range_cfg),478 .max_register = DA9062AA_CONFIG_ID,479 .cache_type = REGCACHE_MAPLE,480 .rd_table = &da9061_aa_readable_table,481 .wr_table = &da9061_aa_writeable_table,482 .volatile_table = &da9061_aa_volatile_table,483};484 485static const struct regmap_range da9062_aa_readable_ranges[] = {486 regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B),487 regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C),488 regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C),489 regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4),490 regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_BUCK4_CONT),491 regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),492 regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),493 regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),494 regmap_reg_range(DA9062AA_COUNT_S, DA9062AA_SECOND_D),495 regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3),496 regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15),497 regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31),498 regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_BUCK3_CFG),499 regmap_reg_range(DA9062AA_VBUCK2_A, DA9062AA_VBUCK4_A),500 regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A),501 regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A),502 regmap_reg_range(DA9062AA_VBUCK2_B, DA9062AA_VBUCK4_B),503 regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B),504 regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B),505 regmap_reg_range(DA9062AA_BBAT_CONT, DA9062AA_BBAT_CONT),506 regmap_reg_range(DA9062AA_INTERFACE, DA9062AA_CONFIG_E),507 regmap_reg_range(DA9062AA_CONFIG_G, DA9062AA_CONFIG_K),508 regmap_reg_range(DA9062AA_CONFIG_M, DA9062AA_CONFIG_M),509 regmap_reg_range(DA9062AA_TRIM_CLDR, DA9062AA_GP_ID_19),510 regmap_reg_range(DA9062AA_DEVICE_ID, DA9062AA_CONFIG_ID),511};512 513static const struct regmap_range da9062_aa_writeable_ranges[] = {514 regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_PAGE_CON),515 regmap_reg_range(DA9062AA_FAULT_LOG, DA9062AA_EVENT_C),516 regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C),517 regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4),518 regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_BUCK4_CONT),519 regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),520 regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),521 regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),522 regmap_reg_range(DA9062AA_COUNT_S, DA9062AA_ALARM_Y),523 regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3),524 regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15),525 regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31),526 regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_BUCK3_CFG),527 regmap_reg_range(DA9062AA_VBUCK2_A, DA9062AA_VBUCK4_A),528 regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A),529 regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A),530 regmap_reg_range(DA9062AA_VBUCK2_B, DA9062AA_VBUCK4_B),531 regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B),532 regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B),533 regmap_reg_range(DA9062AA_BBAT_CONT, DA9062AA_BBAT_CONT),534 regmap_reg_range(DA9062AA_CONFIG_J, DA9062AA_CONFIG_J),535 regmap_reg_range(DA9062AA_GP_ID_0, DA9062AA_GP_ID_19),536};537 538static const struct regmap_range da9062_aa_volatile_ranges[] = {539 regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B),540 regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C),541 regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_CONTROL_B),542 regmap_reg_range(DA9062AA_CONTROL_E, DA9062AA_CONTROL_F),543 regmap_reg_range(DA9062AA_BUCK2_CONT, DA9062AA_BUCK4_CONT),544 regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),545 regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),546 regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),547 regmap_reg_range(DA9062AA_COUNT_S, DA9062AA_SECOND_D),548 regmap_reg_range(DA9062AA_SEQ, DA9062AA_SEQ),549 regmap_reg_range(DA9062AA_EN_32K, DA9062AA_EN_32K),550};551 552static const struct regmap_access_table da9062_aa_readable_table = {553 .yes_ranges = da9062_aa_readable_ranges,554 .n_yes_ranges = ARRAY_SIZE(da9062_aa_readable_ranges),555};556 557static const struct regmap_access_table da9062_aa_writeable_table = {558 .yes_ranges = da9062_aa_writeable_ranges,559 .n_yes_ranges = ARRAY_SIZE(da9062_aa_writeable_ranges),560};561 562static const struct regmap_access_table da9062_aa_volatile_table = {563 .yes_ranges = da9062_aa_volatile_ranges,564 .n_yes_ranges = ARRAY_SIZE(da9062_aa_volatile_ranges),565};566 567static const struct regmap_range_cfg da9062_range_cfg[] = {568 {569 .range_min = DA9062AA_PAGE_CON,570 .range_max = DA9062AA_CONFIG_ID,571 .selector_reg = DA9062AA_PAGE_CON,572 .selector_mask = 1 << DA9062_I2C_PAGE_SEL_SHIFT,573 .selector_shift = DA9062_I2C_PAGE_SEL_SHIFT,574 .window_start = 0,575 .window_len = 256,576 }577};578 579static const struct regmap_config da9062_regmap_config = {580 .reg_bits = 8,581 .val_bits = 8,582 .ranges = da9062_range_cfg,583 .num_ranges = ARRAY_SIZE(da9062_range_cfg),584 .max_register = DA9062AA_CONFIG_ID,585 .cache_type = REGCACHE_MAPLE,586 .rd_table = &da9062_aa_readable_table,587 .wr_table = &da9062_aa_writeable_table,588 .volatile_table = &da9062_aa_volatile_table,589};590 591static int da9062_i2c_probe(struct i2c_client *i2c)592{593 struct da9062 *chip;594 unsigned int irq_base = 0;595 const struct mfd_cell *cell;596 const struct regmap_irq_chip *irq_chip;597 const struct regmap_config *config;598 int cell_num;599 u32 trigger_type = 0;600 int ret;601 602 chip = devm_kzalloc(&i2c->dev, sizeof(*chip), GFP_KERNEL);603 if (!chip)604 return -ENOMEM;605 606 chip->chip_type = (uintptr_t)i2c_get_match_data(i2c);607 608 i2c_set_clientdata(i2c, chip);609 chip->dev = &i2c->dev;610 611 /* Start with a base configuration without IRQ */612 switch (chip->chip_type) {613 case COMPAT_TYPE_DA9061:614 cell = da9061_devs_noirq;615 cell_num = ARRAY_SIZE(da9061_devs_noirq);616 config = &da9061_regmap_config;617 break;618 case COMPAT_TYPE_DA9062:619 cell = da9062_devs_noirq;620 cell_num = ARRAY_SIZE(da9062_devs_noirq);621 config = &da9062_regmap_config;622 break;623 default:624 dev_err(chip->dev, "Unrecognised chip type\n");625 return -ENODEV;626 }627 628 chip->regmap = devm_regmap_init_i2c(i2c, config);629 if (IS_ERR(chip->regmap)) {630 ret = PTR_ERR(chip->regmap);631 dev_err(chip->dev, "Failed to allocate register map: %d\n",632 ret);633 return ret;634 }635 636 /* If SMBus is not available and only I2C is possible, enter I2C mode */637 if (i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) {638 dev_info(chip->dev, "Entering I2C mode!\n");639 ret = regmap_clear_bits(chip->regmap, DA9062AA_CONFIG_J,640 DA9062AA_TWOWIRE_TO_MASK);641 if (ret < 0) {642 dev_err(chip->dev, "Failed to set Two-Wire Bus Mode.\n");643 return ret;644 }645 }646 647 ret = da9062_clear_fault_log(chip);648 if (ret < 0)649 dev_warn(chip->dev, "Cannot clear fault log\n");650 651 ret = da9062_get_device_type(chip);652 if (ret)653 return ret;654 655 /* If IRQ is available, reconfigure it accordingly */656 if (i2c->irq) {657 if (chip->chip_type == COMPAT_TYPE_DA9061) {658 cell = da9061_devs_irq;659 cell_num = ARRAY_SIZE(da9061_devs_irq);660 irq_chip = &da9061_irq_chip;661 } else {662 cell = da9062_devs_irq;663 cell_num = ARRAY_SIZE(da9062_devs_irq);664 irq_chip = &da9062_irq_chip;665 }666 667 ret = da9062_configure_irq_type(chip, i2c->irq, &trigger_type);668 if (ret < 0) {669 dev_err(chip->dev, "Failed to configure IRQ type\n");670 return ret;671 }672 673 ret = regmap_add_irq_chip(chip->regmap, i2c->irq,674 trigger_type | IRQF_SHARED | IRQF_ONESHOT,675 -1, irq_chip, &chip->regmap_irq);676 if (ret) {677 dev_err(chip->dev, "Failed to request IRQ %d: %d\n",678 i2c->irq, ret);679 return ret;680 }681 682 irq_base = regmap_irq_chip_get_base(chip->regmap_irq);683 }684 685 ret = mfd_add_devices(chip->dev, PLATFORM_DEVID_NONE, cell,686 cell_num, NULL, irq_base,687 NULL);688 if (ret) {689 dev_err(chip->dev, "Cannot register child devices\n");690 if (i2c->irq)691 regmap_del_irq_chip(i2c->irq, chip->regmap_irq);692 return ret;693 }694 695 return ret;696}697 698static void da9062_i2c_remove(struct i2c_client *i2c)699{700 struct da9062 *chip = i2c_get_clientdata(i2c);701 702 mfd_remove_devices(chip->dev);703 regmap_del_irq_chip(i2c->irq, chip->regmap_irq);704}705 706static const struct of_device_id da9062_dt_ids[] = {707 { .compatible = "dlg,da9061", .data = (void *)COMPAT_TYPE_DA9061 },708 { .compatible = "dlg,da9062", .data = (void *)COMPAT_TYPE_DA9062 },709 { }710};711MODULE_DEVICE_TABLE(of, da9062_dt_ids);712 713static const struct i2c_device_id da9062_i2c_id[] = {714 { "da9061", COMPAT_TYPE_DA9061 },715 { "da9062", COMPAT_TYPE_DA9062 },716 { }717};718MODULE_DEVICE_TABLE(i2c, da9062_i2c_id);719 720static struct i2c_driver da9062_i2c_driver = {721 .driver = {722 .name = "da9062",723 .of_match_table = da9062_dt_ids,724 },725 .probe = da9062_i2c_probe,726 .remove = da9062_i2c_remove,727 .id_table = da9062_i2c_id,728};729 730module_i2c_driver(da9062_i2c_driver);731 732MODULE_DESCRIPTION("Core device driver for Dialog DA9061 and DA9062");733MODULE_AUTHOR("Steve Twiss <stwiss.opensource@diasemi.com>");734MODULE_LICENSE("GPL");735