2 * Core, IRQ and I2C device driver for DA9061 and DA9062 PMICs
3 * Copyright (C) 2015-2017 Dialog Semiconductor
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.
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.
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>
29 #define DA9062_REG_EVENT_A_OFFSET 0
30 #define DA9062_REG_EVENT_B_OFFSET 1
31 #define DA9062_REG_EVENT_C_OFFSET 2
33 static struct regmap_irq da9061_irqs
[] = {
35 [DA9061_IRQ_ONKEY
] = {
36 .reg_offset
= DA9062_REG_EVENT_A_OFFSET
,
37 .mask
= DA9062AA_M_NONKEY_MASK
,
39 [DA9061_IRQ_WDG_WARN
] = {
40 .reg_offset
= DA9062_REG_EVENT_A_OFFSET
,
41 .mask
= DA9062AA_M_WDG_WARN_MASK
,
43 [DA9061_IRQ_SEQ_RDY
] = {
44 .reg_offset
= DA9062_REG_EVENT_A_OFFSET
,
45 .mask
= DA9062AA_M_SEQ_RDY_MASK
,
49 .reg_offset
= DA9062_REG_EVENT_B_OFFSET
,
50 .mask
= DA9062AA_M_TEMP_MASK
,
52 [DA9061_IRQ_LDO_LIM
] = {
53 .reg_offset
= DA9062_REG_EVENT_B_OFFSET
,
54 .mask
= DA9062AA_M_LDO_LIM_MASK
,
56 [DA9061_IRQ_DVC_RDY
] = {
57 .reg_offset
= DA9062_REG_EVENT_B_OFFSET
,
58 .mask
= DA9062AA_M_DVC_RDY_MASK
,
60 [DA9061_IRQ_VDD_WARN
] = {
61 .reg_offset
= DA9062_REG_EVENT_B_OFFSET
,
62 .mask
= DA9062AA_M_VDD_WARN_MASK
,
66 .reg_offset
= DA9062_REG_EVENT_C_OFFSET
,
67 .mask
= DA9062AA_M_GPI0_MASK
,
70 .reg_offset
= DA9062_REG_EVENT_C_OFFSET
,
71 .mask
= DA9062AA_M_GPI1_MASK
,
74 .reg_offset
= DA9062_REG_EVENT_C_OFFSET
,
75 .mask
= DA9062AA_M_GPI2_MASK
,
78 .reg_offset
= DA9062_REG_EVENT_C_OFFSET
,
79 .mask
= DA9062AA_M_GPI3_MASK
,
82 .reg_offset
= DA9062_REG_EVENT_C_OFFSET
,
83 .mask
= DA9062AA_M_GPI4_MASK
,
87 static struct regmap_irq_chip da9061_irq_chip
= {
90 .num_irqs
= DA9061_NUM_IRQ
,
92 .status_base
= DA9062AA_EVENT_A
,
93 .mask_base
= DA9062AA_IRQ_MASK_A
,
94 .ack_base
= DA9062AA_EVENT_A
,
97 static struct regmap_irq da9062_irqs
[] = {
99 [DA9062_IRQ_ONKEY
] = {
100 .reg_offset
= DA9062_REG_EVENT_A_OFFSET
,
101 .mask
= DA9062AA_M_NONKEY_MASK
,
103 [DA9062_IRQ_ALARM
] = {
104 .reg_offset
= DA9062_REG_EVENT_A_OFFSET
,
105 .mask
= DA9062AA_M_ALARM_MASK
,
107 [DA9062_IRQ_TICK
] = {
108 .reg_offset
= DA9062_REG_EVENT_A_OFFSET
,
109 .mask
= DA9062AA_M_TICK_MASK
,
111 [DA9062_IRQ_WDG_WARN
] = {
112 .reg_offset
= DA9062_REG_EVENT_A_OFFSET
,
113 .mask
= DA9062AA_M_WDG_WARN_MASK
,
115 [DA9062_IRQ_SEQ_RDY
] = {
116 .reg_offset
= DA9062_REG_EVENT_A_OFFSET
,
117 .mask
= DA9062AA_M_SEQ_RDY_MASK
,
120 [DA9062_IRQ_TEMP
] = {
121 .reg_offset
= DA9062_REG_EVENT_B_OFFSET
,
122 .mask
= DA9062AA_M_TEMP_MASK
,
124 [DA9062_IRQ_LDO_LIM
] = {
125 .reg_offset
= DA9062_REG_EVENT_B_OFFSET
,
126 .mask
= DA9062AA_M_LDO_LIM_MASK
,
128 [DA9062_IRQ_DVC_RDY
] = {
129 .reg_offset
= DA9062_REG_EVENT_B_OFFSET
,
130 .mask
= DA9062AA_M_DVC_RDY_MASK
,
132 [DA9062_IRQ_VDD_WARN
] = {
133 .reg_offset
= DA9062_REG_EVENT_B_OFFSET
,
134 .mask
= DA9062AA_M_VDD_WARN_MASK
,
137 [DA9062_IRQ_GPI0
] = {
138 .reg_offset
= DA9062_REG_EVENT_C_OFFSET
,
139 .mask
= DA9062AA_M_GPI0_MASK
,
141 [DA9062_IRQ_GPI1
] = {
142 .reg_offset
= DA9062_REG_EVENT_C_OFFSET
,
143 .mask
= DA9062AA_M_GPI1_MASK
,
145 [DA9062_IRQ_GPI2
] = {
146 .reg_offset
= DA9062_REG_EVENT_C_OFFSET
,
147 .mask
= DA9062AA_M_GPI2_MASK
,
149 [DA9062_IRQ_GPI3
] = {
150 .reg_offset
= DA9062_REG_EVENT_C_OFFSET
,
151 .mask
= DA9062AA_M_GPI3_MASK
,
153 [DA9062_IRQ_GPI4
] = {
154 .reg_offset
= DA9062_REG_EVENT_C_OFFSET
,
155 .mask
= DA9062AA_M_GPI4_MASK
,
159 static struct regmap_irq_chip da9062_irq_chip
= {
160 .name
= "da9062-irq",
162 .num_irqs
= DA9062_NUM_IRQ
,
164 .status_base
= DA9062AA_EVENT_A
,
165 .mask_base
= DA9062AA_IRQ_MASK_A
,
166 .ack_base
= DA9062AA_EVENT_A
,
169 static struct resource da9061_core_resources
[] = {
170 DEFINE_RES_IRQ_NAMED(DA9061_IRQ_VDD_WARN
, "VDD_WARN"),
173 static struct resource da9061_regulators_resources
[] = {
174 DEFINE_RES_IRQ_NAMED(DA9061_IRQ_LDO_LIM
, "LDO_LIM"),
177 static struct resource da9061_thermal_resources
[] = {
178 DEFINE_RES_IRQ_NAMED(DA9061_IRQ_TEMP
, "THERMAL"),
181 static struct resource da9061_wdt_resources
[] = {
182 DEFINE_RES_IRQ_NAMED(DA9061_IRQ_WDG_WARN
, "WD_WARN"),
185 static struct resource da9061_onkey_resources
[] = {
186 DEFINE_RES_IRQ_NAMED(DA9061_IRQ_ONKEY
, "ONKEY"),
189 static const struct mfd_cell da9061_devs
[] = {
191 .name
= "da9061-core",
192 .num_resources
= ARRAY_SIZE(da9061_core_resources
),
193 .resources
= da9061_core_resources
,
196 .name
= "da9062-regulators",
197 .num_resources
= ARRAY_SIZE(da9061_regulators_resources
),
198 .resources
= da9061_regulators_resources
,
201 .name
= "da9061-watchdog",
202 .num_resources
= ARRAY_SIZE(da9061_wdt_resources
),
203 .resources
= da9061_wdt_resources
,
204 .of_compatible
= "dlg,da9061-watchdog",
207 .name
= "da9061-thermal",
208 .num_resources
= ARRAY_SIZE(da9061_thermal_resources
),
209 .resources
= da9061_thermal_resources
,
210 .of_compatible
= "dlg,da9061-thermal",
213 .name
= "da9061-onkey",
214 .num_resources
= ARRAY_SIZE(da9061_onkey_resources
),
215 .resources
= da9061_onkey_resources
,
216 .of_compatible
= "dlg,da9061-onkey",
220 static struct resource da9062_core_resources
[] = {
221 DEFINE_RES_NAMED(DA9062_IRQ_VDD_WARN
, 1, "VDD_WARN", IORESOURCE_IRQ
),
224 static struct resource da9062_regulators_resources
[] = {
225 DEFINE_RES_NAMED(DA9062_IRQ_LDO_LIM
, 1, "LDO_LIM", IORESOURCE_IRQ
),
228 static struct resource da9062_thermal_resources
[] = {
229 DEFINE_RES_NAMED(DA9062_IRQ_TEMP
, 1, "THERMAL", IORESOURCE_IRQ
),
232 static struct resource da9062_wdt_resources
[] = {
233 DEFINE_RES_NAMED(DA9062_IRQ_WDG_WARN
, 1, "WD_WARN", IORESOURCE_IRQ
),
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
),
241 static struct resource da9062_onkey_resources
[] = {
242 DEFINE_RES_NAMED(DA9062_IRQ_ONKEY
, 1, "ONKEY", IORESOURCE_IRQ
),
245 static const struct mfd_cell da9062_devs
[] = {
247 .name
= "da9062-core",
248 .num_resources
= ARRAY_SIZE(da9062_core_resources
),
249 .resources
= da9062_core_resources
,
252 .name
= "da9062-regulators",
253 .num_resources
= ARRAY_SIZE(da9062_regulators_resources
),
254 .resources
= da9062_regulators_resources
,
257 .name
= "da9062-watchdog",
258 .num_resources
= ARRAY_SIZE(da9062_wdt_resources
),
259 .resources
= da9062_wdt_resources
,
260 .of_compatible
= "dlg,da9062-wdt",
263 .name
= "da9062-thermal",
264 .num_resources
= ARRAY_SIZE(da9062_thermal_resources
),
265 .resources
= da9062_thermal_resources
,
266 .of_compatible
= "dlg,da9062-thermal",
269 .name
= "da9062-rtc",
270 .num_resources
= ARRAY_SIZE(da9062_rtc_resources
),
271 .resources
= da9062_rtc_resources
,
272 .of_compatible
= "dlg,da9062-rtc",
275 .name
= "da9062-onkey",
276 .num_resources
= ARRAY_SIZE(da9062_onkey_resources
),
277 .resources
= da9062_onkey_resources
,
278 .of_compatible
= "dlg,da9062-onkey",
282 static int da9062_clear_fault_log(struct da9062
*chip
)
287 ret
= regmap_read(chip
->regmap
, DA9062AA_FAULT_LOG
, &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");
309 ret
= regmap_write(chip
->regmap
, DA9062AA_FAULT_LOG
,
316 static int da9062_get_device_type(struct da9062
*chip
)
318 int device_id
, variant_id
, variant_mrc
, variant_vrc
;
322 ret
= regmap_read(chip
->regmap
, DA9062AA_DEVICE_ID
, &device_id
);
324 dev_err(chip
->dev
, "Cannot read chip ID.\n");
327 if (device_id
!= DA9062_PMIC_DEVICE_ID
) {
328 dev_err(chip
->dev
, "Invalid device ID: 0x%02x\n", device_id
);
332 ret
= regmap_read(chip
->regmap
, DA9062AA_VARIANT_ID
, &variant_id
);
334 dev_err(chip
->dev
, "Cannot read chip variant id.\n");
338 variant_vrc
= (variant_id
& DA9062AA_VRC_MASK
) >> DA9062AA_VRC_SHIFT
;
340 switch (variant_vrc
) {
341 case DA9062_PMIC_VARIANT_VRC_DA9061
:
344 case DA9062_PMIC_VARIANT_VRC_DA9062
:
353 "Device detected (device-ID: 0x%02X, var-ID: 0x%02X, %s)\n",
354 device_id
, variant_id
, type
);
356 variant_mrc
= (variant_id
& DA9062AA_MRC_MASK
) >> DA9062AA_MRC_SHIFT
;
358 if (variant_mrc
< DA9062_PMIC_VARIANT_MRC_AA
) {
360 "Cannot support variant MRC: 0x%02X\n", variant_mrc
);
367 static const struct regmap_range da9061_aa_readable_ranges
[] = {
368 regmap_reg_range(DA9062AA_PAGE_CON
, DA9062AA_STATUS_B
),
369 regmap_reg_range(DA9062AA_STATUS_D
, DA9062AA_EVENT_C
),
370 regmap_reg_range(DA9062AA_IRQ_MASK_A
, DA9062AA_IRQ_MASK_C
),
371 regmap_reg_range(DA9062AA_CONTROL_A
, DA9062AA_GPIO_4
),
372 regmap_reg_range(DA9062AA_GPIO_WKUP_MODE
, DA9062AA_GPIO_OUT3_4
),
373 regmap_reg_range(DA9062AA_BUCK1_CONT
, DA9062AA_BUCK4_CONT
),
374 regmap_reg_range(DA9062AA_BUCK3_CONT
, DA9062AA_BUCK3_CONT
),
375 regmap_reg_range(DA9062AA_LDO1_CONT
, DA9062AA_LDO4_CONT
),
376 regmap_reg_range(DA9062AA_DVC_1
, DA9062AA_DVC_1
),
377 regmap_reg_range(DA9062AA_SEQ
, DA9062AA_ID_4_3
),
378 regmap_reg_range(DA9062AA_ID_12_11
, DA9062AA_ID_16_15
),
379 regmap_reg_range(DA9062AA_ID_22_21
, DA9062AA_ID_32_31
),
380 regmap_reg_range(DA9062AA_SEQ_A
, DA9062AA_WAIT
),
381 regmap_reg_range(DA9062AA_RESET
, DA9062AA_BUCK_ILIM_C
),
382 regmap_reg_range(DA9062AA_BUCK1_CFG
, DA9062AA_BUCK3_CFG
),
383 regmap_reg_range(DA9062AA_VBUCK1_A
, DA9062AA_VBUCK4_A
),
384 regmap_reg_range(DA9062AA_VBUCK3_A
, DA9062AA_VBUCK3_A
),
385 regmap_reg_range(DA9062AA_VLDO1_A
, DA9062AA_VLDO4_A
),
386 regmap_reg_range(DA9062AA_VBUCK1_B
, DA9062AA_VBUCK4_B
),
387 regmap_reg_range(DA9062AA_VBUCK3_B
, DA9062AA_VBUCK3_B
),
388 regmap_reg_range(DA9062AA_VLDO1_B
, DA9062AA_VLDO4_B
),
389 regmap_reg_range(DA9062AA_INTERFACE
, DA9062AA_CONFIG_E
),
390 regmap_reg_range(DA9062AA_CONFIG_G
, DA9062AA_CONFIG_K
),
391 regmap_reg_range(DA9062AA_CONFIG_M
, DA9062AA_CONFIG_M
),
392 regmap_reg_range(DA9062AA_GP_ID_0
, DA9062AA_GP_ID_19
),
393 regmap_reg_range(DA9062AA_DEVICE_ID
, DA9062AA_CONFIG_ID
),
396 static const struct regmap_range da9061_aa_writeable_ranges
[] = {
397 regmap_reg_range(DA9062AA_PAGE_CON
, DA9062AA_PAGE_CON
),
398 regmap_reg_range(DA9062AA_FAULT_LOG
, DA9062AA_EVENT_C
),
399 regmap_reg_range(DA9062AA_IRQ_MASK_A
, DA9062AA_IRQ_MASK_C
),
400 regmap_reg_range(DA9062AA_CONTROL_A
, DA9062AA_GPIO_4
),
401 regmap_reg_range(DA9062AA_GPIO_WKUP_MODE
, DA9062AA_GPIO_OUT3_4
),
402 regmap_reg_range(DA9062AA_BUCK1_CONT
, DA9062AA_BUCK4_CONT
),
403 regmap_reg_range(DA9062AA_BUCK3_CONT
, DA9062AA_BUCK3_CONT
),
404 regmap_reg_range(DA9062AA_LDO1_CONT
, DA9062AA_LDO4_CONT
),
405 regmap_reg_range(DA9062AA_DVC_1
, DA9062AA_DVC_1
),
406 regmap_reg_range(DA9062AA_SEQ
, DA9062AA_ID_4_3
),
407 regmap_reg_range(DA9062AA_ID_12_11
, DA9062AA_ID_16_15
),
408 regmap_reg_range(DA9062AA_ID_22_21
, DA9062AA_ID_32_31
),
409 regmap_reg_range(DA9062AA_SEQ_A
, DA9062AA_WAIT
),
410 regmap_reg_range(DA9062AA_RESET
, DA9062AA_BUCK_ILIM_C
),
411 regmap_reg_range(DA9062AA_BUCK1_CFG
, DA9062AA_BUCK3_CFG
),
412 regmap_reg_range(DA9062AA_VBUCK1_A
, DA9062AA_VBUCK4_A
),
413 regmap_reg_range(DA9062AA_VBUCK3_A
, DA9062AA_VBUCK3_A
),
414 regmap_reg_range(DA9062AA_VLDO1_A
, DA9062AA_VLDO4_A
),
415 regmap_reg_range(DA9062AA_VBUCK1_B
, DA9062AA_VBUCK4_B
),
416 regmap_reg_range(DA9062AA_VBUCK3_B
, DA9062AA_VBUCK3_B
),
417 regmap_reg_range(DA9062AA_VLDO1_B
, DA9062AA_VLDO4_B
),
418 regmap_reg_range(DA9062AA_GP_ID_0
, DA9062AA_GP_ID_19
),
421 static const struct regmap_range da9061_aa_volatile_ranges
[] = {
422 regmap_reg_range(DA9062AA_PAGE_CON
, DA9062AA_STATUS_B
),
423 regmap_reg_range(DA9062AA_STATUS_D
, DA9062AA_EVENT_C
),
424 regmap_reg_range(DA9062AA_CONTROL_A
, DA9062AA_CONTROL_B
),
425 regmap_reg_range(DA9062AA_CONTROL_E
, DA9062AA_CONTROL_F
),
426 regmap_reg_range(DA9062AA_BUCK1_CONT
, DA9062AA_BUCK4_CONT
),
427 regmap_reg_range(DA9062AA_BUCK3_CONT
, DA9062AA_BUCK3_CONT
),
428 regmap_reg_range(DA9062AA_LDO1_CONT
, DA9062AA_LDO4_CONT
),
429 regmap_reg_range(DA9062AA_DVC_1
, DA9062AA_DVC_1
),
430 regmap_reg_range(DA9062AA_SEQ
, DA9062AA_SEQ
),
433 static const struct regmap_access_table da9061_aa_readable_table
= {
434 .yes_ranges
= da9061_aa_readable_ranges
,
435 .n_yes_ranges
= ARRAY_SIZE(da9061_aa_readable_ranges
),
438 static const struct regmap_access_table da9061_aa_writeable_table
= {
439 .yes_ranges
= da9061_aa_writeable_ranges
,
440 .n_yes_ranges
= ARRAY_SIZE(da9061_aa_writeable_ranges
),
443 static const struct regmap_access_table da9061_aa_volatile_table
= {
444 .yes_ranges
= da9061_aa_volatile_ranges
,
445 .n_yes_ranges
= ARRAY_SIZE(da9061_aa_volatile_ranges
),
448 static const struct regmap_range_cfg da9061_range_cfg
[] = {
450 .range_min
= DA9062AA_PAGE_CON
,
451 .range_max
= DA9062AA_CONFIG_ID
,
452 .selector_reg
= DA9062AA_PAGE_CON
,
453 .selector_mask
= 1 << DA9062_I2C_PAGE_SEL_SHIFT
,
454 .selector_shift
= DA9062_I2C_PAGE_SEL_SHIFT
,
460 static struct regmap_config da9061_regmap_config
= {
463 .ranges
= da9061_range_cfg
,
464 .num_ranges
= ARRAY_SIZE(da9061_range_cfg
),
465 .max_register
= DA9062AA_CONFIG_ID
,
466 .cache_type
= REGCACHE_RBTREE
,
467 .rd_table
= &da9061_aa_readable_table
,
468 .wr_table
= &da9061_aa_writeable_table
,
469 .volatile_table
= &da9061_aa_volatile_table
,
472 static const struct regmap_range da9062_aa_readable_ranges
[] = {
473 regmap_reg_range(DA9062AA_PAGE_CON
, DA9062AA_STATUS_B
),
474 regmap_reg_range(DA9062AA_STATUS_D
, DA9062AA_EVENT_C
),
475 regmap_reg_range(DA9062AA_IRQ_MASK_A
, DA9062AA_IRQ_MASK_C
),
476 regmap_reg_range(DA9062AA_CONTROL_A
, DA9062AA_GPIO_4
),
477 regmap_reg_range(DA9062AA_GPIO_WKUP_MODE
, DA9062AA_BUCK4_CONT
),
478 regmap_reg_range(DA9062AA_BUCK3_CONT
, DA9062AA_BUCK3_CONT
),
479 regmap_reg_range(DA9062AA_LDO1_CONT
, DA9062AA_LDO4_CONT
),
480 regmap_reg_range(DA9062AA_DVC_1
, DA9062AA_DVC_1
),
481 regmap_reg_range(DA9062AA_COUNT_S
, DA9062AA_SECOND_D
),
482 regmap_reg_range(DA9062AA_SEQ
, DA9062AA_ID_4_3
),
483 regmap_reg_range(DA9062AA_ID_12_11
, DA9062AA_ID_16_15
),
484 regmap_reg_range(DA9062AA_ID_22_21
, DA9062AA_ID_32_31
),
485 regmap_reg_range(DA9062AA_SEQ_A
, DA9062AA_BUCK3_CFG
),
486 regmap_reg_range(DA9062AA_VBUCK2_A
, DA9062AA_VBUCK4_A
),
487 regmap_reg_range(DA9062AA_VBUCK3_A
, DA9062AA_VBUCK3_A
),
488 regmap_reg_range(DA9062AA_VLDO1_A
, DA9062AA_VLDO4_A
),
489 regmap_reg_range(DA9062AA_VBUCK2_B
, DA9062AA_VBUCK4_B
),
490 regmap_reg_range(DA9062AA_VBUCK3_B
, DA9062AA_VBUCK3_B
),
491 regmap_reg_range(DA9062AA_VLDO1_B
, DA9062AA_VLDO4_B
),
492 regmap_reg_range(DA9062AA_BBAT_CONT
, DA9062AA_BBAT_CONT
),
493 regmap_reg_range(DA9062AA_INTERFACE
, DA9062AA_CONFIG_E
),
494 regmap_reg_range(DA9062AA_CONFIG_G
, DA9062AA_CONFIG_K
),
495 regmap_reg_range(DA9062AA_CONFIG_M
, DA9062AA_CONFIG_M
),
496 regmap_reg_range(DA9062AA_TRIM_CLDR
, DA9062AA_GP_ID_19
),
497 regmap_reg_range(DA9062AA_DEVICE_ID
, DA9062AA_CONFIG_ID
),
500 static const struct regmap_range da9062_aa_writeable_ranges
[] = {
501 regmap_reg_range(DA9062AA_PAGE_CON
, DA9062AA_PAGE_CON
),
502 regmap_reg_range(DA9062AA_FAULT_LOG
, DA9062AA_EVENT_C
),
503 regmap_reg_range(DA9062AA_IRQ_MASK_A
, DA9062AA_IRQ_MASK_C
),
504 regmap_reg_range(DA9062AA_CONTROL_A
, DA9062AA_GPIO_4
),
505 regmap_reg_range(DA9062AA_GPIO_WKUP_MODE
, DA9062AA_BUCK4_CONT
),
506 regmap_reg_range(DA9062AA_BUCK3_CONT
, DA9062AA_BUCK3_CONT
),
507 regmap_reg_range(DA9062AA_LDO1_CONT
, DA9062AA_LDO4_CONT
),
508 regmap_reg_range(DA9062AA_DVC_1
, DA9062AA_DVC_1
),
509 regmap_reg_range(DA9062AA_COUNT_S
, DA9062AA_ALARM_Y
),
510 regmap_reg_range(DA9062AA_SEQ
, DA9062AA_ID_4_3
),
511 regmap_reg_range(DA9062AA_ID_12_11
, DA9062AA_ID_16_15
),
512 regmap_reg_range(DA9062AA_ID_22_21
, DA9062AA_ID_32_31
),
513 regmap_reg_range(DA9062AA_SEQ_A
, DA9062AA_BUCK3_CFG
),
514 regmap_reg_range(DA9062AA_VBUCK2_A
, DA9062AA_VBUCK4_A
),
515 regmap_reg_range(DA9062AA_VBUCK3_A
, DA9062AA_VBUCK3_A
),
516 regmap_reg_range(DA9062AA_VLDO1_A
, DA9062AA_VLDO4_A
),
517 regmap_reg_range(DA9062AA_VBUCK2_B
, DA9062AA_VBUCK4_B
),
518 regmap_reg_range(DA9062AA_VBUCK3_B
, DA9062AA_VBUCK3_B
),
519 regmap_reg_range(DA9062AA_VLDO1_B
, DA9062AA_VLDO4_B
),
520 regmap_reg_range(DA9062AA_BBAT_CONT
, DA9062AA_BBAT_CONT
),
521 regmap_reg_range(DA9062AA_GP_ID_0
, DA9062AA_GP_ID_19
),
524 static const struct regmap_range da9062_aa_volatile_ranges
[] = {
525 regmap_reg_range(DA9062AA_PAGE_CON
, DA9062AA_STATUS_B
),
526 regmap_reg_range(DA9062AA_STATUS_D
, DA9062AA_EVENT_C
),
527 regmap_reg_range(DA9062AA_CONTROL_A
, DA9062AA_CONTROL_B
),
528 regmap_reg_range(DA9062AA_CONTROL_E
, DA9062AA_CONTROL_F
),
529 regmap_reg_range(DA9062AA_BUCK2_CONT
, DA9062AA_BUCK4_CONT
),
530 regmap_reg_range(DA9062AA_BUCK3_CONT
, DA9062AA_BUCK3_CONT
),
531 regmap_reg_range(DA9062AA_LDO1_CONT
, DA9062AA_LDO4_CONT
),
532 regmap_reg_range(DA9062AA_DVC_1
, DA9062AA_DVC_1
),
533 regmap_reg_range(DA9062AA_COUNT_S
, DA9062AA_SECOND_D
),
534 regmap_reg_range(DA9062AA_SEQ
, DA9062AA_SEQ
),
535 regmap_reg_range(DA9062AA_EN_32K
, DA9062AA_EN_32K
),
538 static const struct regmap_access_table da9062_aa_readable_table
= {
539 .yes_ranges
= da9062_aa_readable_ranges
,
540 .n_yes_ranges
= ARRAY_SIZE(da9062_aa_readable_ranges
),
543 static const struct regmap_access_table da9062_aa_writeable_table
= {
544 .yes_ranges
= da9062_aa_writeable_ranges
,
545 .n_yes_ranges
= ARRAY_SIZE(da9062_aa_writeable_ranges
),
548 static const struct regmap_access_table da9062_aa_volatile_table
= {
549 .yes_ranges
= da9062_aa_volatile_ranges
,
550 .n_yes_ranges
= ARRAY_SIZE(da9062_aa_volatile_ranges
),
553 static const struct regmap_range_cfg da9062_range_cfg
[] = {
555 .range_min
= DA9062AA_PAGE_CON
,
556 .range_max
= DA9062AA_CONFIG_ID
,
557 .selector_reg
= DA9062AA_PAGE_CON
,
558 .selector_mask
= 1 << DA9062_I2C_PAGE_SEL_SHIFT
,
559 .selector_shift
= DA9062_I2C_PAGE_SEL_SHIFT
,
565 static struct regmap_config da9062_regmap_config
= {
568 .ranges
= da9062_range_cfg
,
569 .num_ranges
= ARRAY_SIZE(da9062_range_cfg
),
570 .max_register
= DA9062AA_CONFIG_ID
,
571 .cache_type
= REGCACHE_RBTREE
,
572 .rd_table
= &da9062_aa_readable_table
,
573 .wr_table
= &da9062_aa_writeable_table
,
574 .volatile_table
= &da9062_aa_volatile_table
,
577 static const struct of_device_id da9062_dt_ids
[] = {
578 { .compatible
= "dlg,da9061", .data
= (void *)COMPAT_TYPE_DA9061
, },
579 { .compatible
= "dlg,da9062", .data
= (void *)COMPAT_TYPE_DA9062
, },
582 MODULE_DEVICE_TABLE(of
, da9062_dt_ids
);
584 static int da9062_i2c_probe(struct i2c_client
*i2c
,
585 const struct i2c_device_id
*id
)
588 const struct of_device_id
*match
;
589 unsigned int irq_base
;
590 const struct mfd_cell
*cell
;
591 const struct regmap_irq_chip
*irq_chip
;
592 const struct regmap_config
*config
;
596 chip
= devm_kzalloc(&i2c
->dev
, sizeof(*chip
), GFP_KERNEL
);
600 if (i2c
->dev
.of_node
) {
601 match
= of_match_node(da9062_dt_ids
, i2c
->dev
.of_node
);
605 chip
->chip_type
= (uintptr_t)match
->data
;
607 chip
->chip_type
= id
->driver_data
;
610 i2c_set_clientdata(i2c
, chip
);
611 chip
->dev
= &i2c
->dev
;
614 dev_err(chip
->dev
, "No IRQ configured\n");
618 switch (chip
->chip_type
) {
619 case COMPAT_TYPE_DA9061
:
621 cell_num
= ARRAY_SIZE(da9061_devs
);
622 irq_chip
= &da9061_irq_chip
;
623 config
= &da9061_regmap_config
;
625 case COMPAT_TYPE_DA9062
:
627 cell_num
= ARRAY_SIZE(da9062_devs
);
628 irq_chip
= &da9062_irq_chip
;
629 config
= &da9062_regmap_config
;
632 dev_err(chip
->dev
, "Unrecognised chip type\n");
636 chip
->regmap
= devm_regmap_init_i2c(i2c
, config
);
637 if (IS_ERR(chip
->regmap
)) {
638 ret
= PTR_ERR(chip
->regmap
);
639 dev_err(chip
->dev
, "Failed to allocate register map: %d\n",
644 ret
= da9062_clear_fault_log(chip
);
646 dev_warn(chip
->dev
, "Cannot clear fault log\n");
648 ret
= da9062_get_device_type(chip
);
652 ret
= regmap_add_irq_chip(chip
->regmap
, i2c
->irq
,
653 IRQF_TRIGGER_LOW
| IRQF_ONESHOT
| IRQF_SHARED
,
657 dev_err(chip
->dev
, "Failed to request IRQ %d: %d\n",
662 irq_base
= regmap_irq_chip_get_base(chip
->regmap_irq
);
664 ret
= mfd_add_devices(chip
->dev
, PLATFORM_DEVID_NONE
, cell
,
665 cell_num
, NULL
, irq_base
,
668 dev_err(chip
->dev
, "Cannot register child devices\n");
669 regmap_del_irq_chip(i2c
->irq
, chip
->regmap_irq
);
676 static int da9062_i2c_remove(struct i2c_client
*i2c
)
678 struct da9062
*chip
= i2c_get_clientdata(i2c
);
680 mfd_remove_devices(chip
->dev
);
681 regmap_del_irq_chip(i2c
->irq
, chip
->regmap_irq
);
686 static const struct i2c_device_id da9062_i2c_id
[] = {
687 { "da9061", COMPAT_TYPE_DA9061
},
688 { "da9062", COMPAT_TYPE_DA9062
},
691 MODULE_DEVICE_TABLE(i2c
, da9062_i2c_id
);
693 static struct i2c_driver da9062_i2c_driver
= {
696 .of_match_table
= of_match_ptr(da9062_dt_ids
),
698 .probe
= da9062_i2c_probe
,
699 .remove
= da9062_i2c_remove
,
700 .id_table
= da9062_i2c_id
,
703 module_i2c_driver(da9062_i2c_driver
);
705 MODULE_DESCRIPTION("Core device driver for Dialog DA9061 and DA9062");
706 MODULE_AUTHOR("Steve Twiss <stwiss.opensource@diasemi.com>");
707 MODULE_LICENSE("GPL");