Merge branch 'samsung-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene...
[cascardo/linux.git] / drivers / mfd / da9052-core.c
1 /*
2  * Device access for Dialog DA9052 PMICs.
3  *
4  * Copyright(c) 2011 Dialog Semiconductor Ltd.
5  *
6  * Author: David Dajun Chen <dchen@diasemi.com>
7  *
8  *  This program is free software; you can redistribute  it and/or modify it
9  *  under  the terms of  the GNU General  Public License as published by the
10  *  Free Software Foundation;  either version 2 of the  License, or (at your
11  *  option) any later version.
12  */
13
14 #include <linux/device.h>
15 #include <linux/delay.h>
16 #include <linux/input.h>
17 #include <linux/interrupt.h>
18 #include <linux/irq.h>
19 #include <linux/mutex.h>
20 #include <linux/mfd/core.h>
21 #include <linux/slab.h>
22 #include <linux/module.h>
23
24 #include <linux/mfd/da9052/da9052.h>
25 #include <linux/mfd/da9052/pdata.h>
26 #include <linux/mfd/da9052/reg.h>
27
28 #define DA9052_NUM_IRQ_REGS             4
29 #define DA9052_IRQ_MASK_POS_1           0x01
30 #define DA9052_IRQ_MASK_POS_2           0x02
31 #define DA9052_IRQ_MASK_POS_3           0x04
32 #define DA9052_IRQ_MASK_POS_4           0x08
33 #define DA9052_IRQ_MASK_POS_5           0x10
34 #define DA9052_IRQ_MASK_POS_6           0x20
35 #define DA9052_IRQ_MASK_POS_7           0x40
36 #define DA9052_IRQ_MASK_POS_8           0x80
37
38 static bool da9052_reg_readable(struct device *dev, unsigned int reg)
39 {
40         switch (reg) {
41         case DA9052_PAGE0_CON_REG:
42         case DA9052_STATUS_A_REG:
43         case DA9052_STATUS_B_REG:
44         case DA9052_STATUS_C_REG:
45         case DA9052_STATUS_D_REG:
46         case DA9052_EVENT_A_REG:
47         case DA9052_EVENT_B_REG:
48         case DA9052_EVENT_C_REG:
49         case DA9052_EVENT_D_REG:
50         case DA9052_FAULTLOG_REG:
51         case DA9052_IRQ_MASK_A_REG:
52         case DA9052_IRQ_MASK_B_REG:
53         case DA9052_IRQ_MASK_C_REG:
54         case DA9052_IRQ_MASK_D_REG:
55         case DA9052_CONTROL_A_REG:
56         case DA9052_CONTROL_B_REG:
57         case DA9052_CONTROL_C_REG:
58         case DA9052_CONTROL_D_REG:
59         case DA9052_PDDIS_REG:
60         case DA9052_INTERFACE_REG:
61         case DA9052_RESET_REG:
62         case DA9052_GPIO_0_1_REG:
63         case DA9052_GPIO_2_3_REG:
64         case DA9052_GPIO_4_5_REG:
65         case DA9052_GPIO_6_7_REG:
66         case DA9052_GPIO_14_15_REG:
67         case DA9052_ID_0_1_REG:
68         case DA9052_ID_2_3_REG:
69         case DA9052_ID_4_5_REG:
70         case DA9052_ID_6_7_REG:
71         case DA9052_ID_8_9_REG:
72         case DA9052_ID_10_11_REG:
73         case DA9052_ID_12_13_REG:
74         case DA9052_ID_14_15_REG:
75         case DA9052_ID_16_17_REG:
76         case DA9052_ID_18_19_REG:
77         case DA9052_ID_20_21_REG:
78         case DA9052_SEQ_STATUS_REG:
79         case DA9052_SEQ_A_REG:
80         case DA9052_SEQ_B_REG:
81         case DA9052_SEQ_TIMER_REG:
82         case DA9052_BUCKA_REG:
83         case DA9052_BUCKB_REG:
84         case DA9052_BUCKCORE_REG:
85         case DA9052_BUCKPRO_REG:
86         case DA9052_BUCKMEM_REG:
87         case DA9052_BUCKPERI_REG:
88         case DA9052_LDO1_REG:
89         case DA9052_LDO2_REG:
90         case DA9052_LDO3_REG:
91         case DA9052_LDO4_REG:
92         case DA9052_LDO5_REG:
93         case DA9052_LDO6_REG:
94         case DA9052_LDO7_REG:
95         case DA9052_LDO8_REG:
96         case DA9052_LDO9_REG:
97         case DA9052_LDO10_REG:
98         case DA9052_SUPPLY_REG:
99         case DA9052_PULLDOWN_REG:
100         case DA9052_CHGBUCK_REG:
101         case DA9052_WAITCONT_REG:
102         case DA9052_ISET_REG:
103         case DA9052_BATCHG_REG:
104         case DA9052_CHG_CONT_REG:
105         case DA9052_INPUT_CONT_REG:
106         case DA9052_CHG_TIME_REG:
107         case DA9052_BBAT_CONT_REG:
108         case DA9052_BOOST_REG:
109         case DA9052_LED_CONT_REG:
110         case DA9052_LEDMIN123_REG:
111         case DA9052_LED1_CONF_REG:
112         case DA9052_LED2_CONF_REG:
113         case DA9052_LED3_CONF_REG:
114         case DA9052_LED1CONT_REG:
115         case DA9052_LED2CONT_REG:
116         case DA9052_LED3CONT_REG:
117         case DA9052_LED_CONT_4_REG:
118         case DA9052_LED_CONT_5_REG:
119         case DA9052_ADC_MAN_REG:
120         case DA9052_ADC_CONT_REG:
121         case DA9052_ADC_RES_L_REG:
122         case DA9052_ADC_RES_H_REG:
123         case DA9052_VDD_RES_REG:
124         case DA9052_VDD_MON_REG:
125         case DA9052_ICHG_AV_REG:
126         case DA9052_ICHG_THD_REG:
127         case DA9052_ICHG_END_REG:
128         case DA9052_TBAT_RES_REG:
129         case DA9052_TBAT_HIGHP_REG:
130         case DA9052_TBAT_HIGHN_REG:
131         case DA9052_TBAT_LOW_REG:
132         case DA9052_T_OFFSET_REG:
133         case DA9052_ADCIN4_RES_REG:
134         case DA9052_AUTO4_HIGH_REG:
135         case DA9052_AUTO4_LOW_REG:
136         case DA9052_ADCIN5_RES_REG:
137         case DA9052_AUTO5_HIGH_REG:
138         case DA9052_AUTO5_LOW_REG:
139         case DA9052_ADCIN6_RES_REG:
140         case DA9052_AUTO6_HIGH_REG:
141         case DA9052_AUTO6_LOW_REG:
142         case DA9052_TJUNC_RES_REG:
143         case DA9052_TSI_CONT_A_REG:
144         case DA9052_TSI_CONT_B_REG:
145         case DA9052_TSI_X_MSB_REG:
146         case DA9052_TSI_Y_MSB_REG:
147         case DA9052_TSI_LSB_REG:
148         case DA9052_TSI_Z_MSB_REG:
149         case DA9052_COUNT_S_REG:
150         case DA9052_COUNT_MI_REG:
151         case DA9052_COUNT_H_REG:
152         case DA9052_COUNT_D_REG:
153         case DA9052_COUNT_MO_REG:
154         case DA9052_COUNT_Y_REG:
155         case DA9052_ALARM_MI_REG:
156         case DA9052_ALARM_H_REG:
157         case DA9052_ALARM_D_REG:
158         case DA9052_ALARM_MO_REG:
159         case DA9052_ALARM_Y_REG:
160         case DA9052_SECOND_A_REG:
161         case DA9052_SECOND_B_REG:
162         case DA9052_SECOND_C_REG:
163         case DA9052_SECOND_D_REG:
164         case DA9052_PAGE1_CON_REG:
165                 return true;
166         default:
167                 return false;
168         }
169 }
170
171 static bool da9052_reg_writeable(struct device *dev, unsigned int reg)
172 {
173         switch (reg) {
174         case DA9052_PAGE0_CON_REG:
175         case DA9052_EVENT_A_REG:
176         case DA9052_EVENT_B_REG:
177         case DA9052_EVENT_C_REG:
178         case DA9052_EVENT_D_REG:
179         case DA9052_IRQ_MASK_A_REG:
180         case DA9052_IRQ_MASK_B_REG:
181         case DA9052_IRQ_MASK_C_REG:
182         case DA9052_IRQ_MASK_D_REG:
183         case DA9052_CONTROL_A_REG:
184         case DA9052_CONTROL_B_REG:
185         case DA9052_CONTROL_C_REG:
186         case DA9052_CONTROL_D_REG:
187         case DA9052_PDDIS_REG:
188         case DA9052_RESET_REG:
189         case DA9052_GPIO_0_1_REG:
190         case DA9052_GPIO_2_3_REG:
191         case DA9052_GPIO_4_5_REG:
192         case DA9052_GPIO_6_7_REG:
193         case DA9052_GPIO_14_15_REG:
194         case DA9052_ID_0_1_REG:
195         case DA9052_ID_2_3_REG:
196         case DA9052_ID_4_5_REG:
197         case DA9052_ID_6_7_REG:
198         case DA9052_ID_8_9_REG:
199         case DA9052_ID_10_11_REG:
200         case DA9052_ID_12_13_REG:
201         case DA9052_ID_14_15_REG:
202         case DA9052_ID_16_17_REG:
203         case DA9052_ID_18_19_REG:
204         case DA9052_ID_20_21_REG:
205         case DA9052_SEQ_STATUS_REG:
206         case DA9052_SEQ_A_REG:
207         case DA9052_SEQ_B_REG:
208         case DA9052_SEQ_TIMER_REG:
209         case DA9052_BUCKA_REG:
210         case DA9052_BUCKB_REG:
211         case DA9052_BUCKCORE_REG:
212         case DA9052_BUCKPRO_REG:
213         case DA9052_BUCKMEM_REG:
214         case DA9052_BUCKPERI_REG:
215         case DA9052_LDO1_REG:
216         case DA9052_LDO2_REG:
217         case DA9052_LDO3_REG:
218         case DA9052_LDO4_REG:
219         case DA9052_LDO5_REG:
220         case DA9052_LDO6_REG:
221         case DA9052_LDO7_REG:
222         case DA9052_LDO8_REG:
223         case DA9052_LDO9_REG:
224         case DA9052_LDO10_REG:
225         case DA9052_SUPPLY_REG:
226         case DA9052_PULLDOWN_REG:
227         case DA9052_CHGBUCK_REG:
228         case DA9052_WAITCONT_REG:
229         case DA9052_ISET_REG:
230         case DA9052_BATCHG_REG:
231         case DA9052_CHG_CONT_REG:
232         case DA9052_INPUT_CONT_REG:
233         case DA9052_BBAT_CONT_REG:
234         case DA9052_BOOST_REG:
235         case DA9052_LED_CONT_REG:
236         case DA9052_LEDMIN123_REG:
237         case DA9052_LED1_CONF_REG:
238         case DA9052_LED2_CONF_REG:
239         case DA9052_LED3_CONF_REG:
240         case DA9052_LED1CONT_REG:
241         case DA9052_LED2CONT_REG:
242         case DA9052_LED3CONT_REG:
243         case DA9052_LED_CONT_4_REG:
244         case DA9052_LED_CONT_5_REG:
245         case DA9052_ADC_MAN_REG:
246         case DA9052_ADC_CONT_REG:
247         case DA9052_ADC_RES_L_REG:
248         case DA9052_ADC_RES_H_REG:
249         case DA9052_VDD_RES_REG:
250         case DA9052_VDD_MON_REG:
251         case DA9052_ICHG_THD_REG:
252         case DA9052_ICHG_END_REG:
253         case DA9052_TBAT_HIGHP_REG:
254         case DA9052_TBAT_HIGHN_REG:
255         case DA9052_TBAT_LOW_REG:
256         case DA9052_T_OFFSET_REG:
257         case DA9052_AUTO4_HIGH_REG:
258         case DA9052_AUTO4_LOW_REG:
259         case DA9052_AUTO5_HIGH_REG:
260         case DA9052_AUTO5_LOW_REG:
261         case DA9052_AUTO6_HIGH_REG:
262         case DA9052_AUTO6_LOW_REG:
263         case DA9052_TSI_CONT_A_REG:
264         case DA9052_TSI_CONT_B_REG:
265         case DA9052_COUNT_S_REG:
266         case DA9052_COUNT_MI_REG:
267         case DA9052_COUNT_H_REG:
268         case DA9052_COUNT_D_REG:
269         case DA9052_COUNT_MO_REG:
270         case DA9052_COUNT_Y_REG:
271         case DA9052_ALARM_MI_REG:
272         case DA9052_ALARM_H_REG:
273         case DA9052_ALARM_D_REG:
274         case DA9052_ALARM_MO_REG:
275         case DA9052_ALARM_Y_REG:
276         case DA9052_PAGE1_CON_REG:
277                 return true;
278         default:
279                 return false;
280         }
281 }
282
283 static bool da9052_reg_volatile(struct device *dev, unsigned int reg)
284 {
285         switch (reg) {
286         case DA9052_STATUS_A_REG:
287         case DA9052_STATUS_B_REG:
288         case DA9052_STATUS_C_REG:
289         case DA9052_STATUS_D_REG:
290         case DA9052_EVENT_A_REG:
291         case DA9052_EVENT_B_REG:
292         case DA9052_EVENT_C_REG:
293         case DA9052_EVENT_D_REG:
294         case DA9052_FAULTLOG_REG:
295         case DA9052_CHG_TIME_REG:
296         case DA9052_ADC_RES_L_REG:
297         case DA9052_ADC_RES_H_REG:
298         case DA9052_VDD_RES_REG:
299         case DA9052_ICHG_AV_REG:
300         case DA9052_TBAT_RES_REG:
301         case DA9052_ADCIN4_RES_REG:
302         case DA9052_ADCIN5_RES_REG:
303         case DA9052_ADCIN6_RES_REG:
304         case DA9052_TJUNC_RES_REG:
305         case DA9052_TSI_X_MSB_REG:
306         case DA9052_TSI_Y_MSB_REG:
307         case DA9052_TSI_LSB_REG:
308         case DA9052_TSI_Z_MSB_REG:
309         case DA9052_COUNT_S_REG:
310         case DA9052_COUNT_MI_REG:
311         case DA9052_COUNT_H_REG:
312         case DA9052_COUNT_D_REG:
313         case DA9052_COUNT_MO_REG:
314         case DA9052_COUNT_Y_REG:
315         case DA9052_ALARM_MI_REG:
316                 return true;
317         default:
318                 return false;
319         }
320 }
321
322 static struct resource da9052_rtc_resource = {
323         .name = "ALM",
324         .start = DA9052_IRQ_ALARM,
325         .end   = DA9052_IRQ_ALARM,
326         .flags = IORESOURCE_IRQ,
327 };
328
329 static struct resource da9052_onkey_resource = {
330         .name = "ONKEY",
331         .start = DA9052_IRQ_NONKEY,
332         .end   = DA9052_IRQ_NONKEY,
333         .flags = IORESOURCE_IRQ,
334 };
335
336 static struct resource da9052_bat_resources[] = {
337         {
338                 .name = "BATT TEMP",
339                 .start = DA9052_IRQ_TBAT,
340                 .end   = DA9052_IRQ_TBAT,
341                 .flags = IORESOURCE_IRQ,
342         },
343         {
344                 .name = "DCIN DET",
345                 .start = DA9052_IRQ_DCIN,
346                 .end   = DA9052_IRQ_DCIN,
347                 .flags = IORESOURCE_IRQ,
348         },
349         {
350                 .name = "DCIN REM",
351                 .start = DA9052_IRQ_DCINREM,
352                 .end   = DA9052_IRQ_DCINREM,
353                 .flags = IORESOURCE_IRQ,
354         },
355         {
356                 .name = "VBUS DET",
357                 .start = DA9052_IRQ_VBUS,
358                 .end   = DA9052_IRQ_VBUS,
359                 .flags = IORESOURCE_IRQ,
360         },
361         {
362                 .name = "VBUS REM",
363                 .start = DA9052_IRQ_VBUSREM,
364                 .end   = DA9052_IRQ_VBUSREM,
365                 .flags = IORESOURCE_IRQ,
366         },
367         {
368                 .name = "CHG END",
369                 .start = DA9052_IRQ_CHGEND,
370                 .end   = DA9052_IRQ_CHGEND,
371                 .flags = IORESOURCE_IRQ,
372         },
373 };
374
375 static struct resource da9052_tsi_resources[] = {
376         {
377                 .name = "PENDWN",
378                 .start = DA9052_IRQ_PENDOWN,
379                 .end   = DA9052_IRQ_PENDOWN,
380                 .flags = IORESOURCE_IRQ,
381         },
382         {
383                 .name = "TSIRDY",
384                 .start = DA9052_IRQ_TSIREADY,
385                 .end   = DA9052_IRQ_TSIREADY,
386                 .flags = IORESOURCE_IRQ,
387         },
388 };
389
390 static struct mfd_cell __devinitdata da9052_subdev_info[] = {
391         {
392                 .name = "da9052-regulator",
393                 .id = 1,
394         },
395         {
396                 .name = "da9052-regulator",
397                 .id = 2,
398         },
399         {
400                 .name = "da9052-regulator",
401                 .id = 3,
402         },
403         {
404                 .name = "da9052-regulator",
405                 .id = 4,
406         },
407         {
408                 .name = "da9052-regulator",
409                 .id = 5,
410         },
411         {
412                 .name = "da9052-regulator",
413                 .id = 6,
414         },
415         {
416                 .name = "da9052-regulator",
417                 .id = 7,
418         },
419         {
420                 .name = "da9052-regulator",
421                 .id = 8,
422         },
423         {
424                 .name = "da9052-regulator",
425                 .id = 9,
426         },
427         {
428                 .name = "da9052-regulator",
429                 .id = 10,
430         },
431         {
432                 .name = "da9052-regulator",
433                 .id = 11,
434         },
435         {
436                 .name = "da9052-regulator",
437                 .id = 12,
438         },
439         {
440                 .name = "da9052-regulator",
441                 .id = 13,
442         },
443         {
444                 .name = "da9052-regulator",
445                 .id = 14,
446         },
447         {
448                 .name = "da9052-onkey",
449                 .resources = &da9052_onkey_resource,
450                 .num_resources = 1,
451         },
452         {
453                 .name = "da9052-rtc",
454                 .resources = &da9052_rtc_resource,
455                 .num_resources = 1,
456         },
457         {
458                 .name = "da9052-gpio",
459         },
460         {
461                 .name = "da9052-hwmon",
462         },
463         {
464                 .name = "da9052-leds",
465         },
466         {
467                 .name = "da9052-wled1",
468         },
469         {
470                 .name = "da9052-wled2",
471         },
472         {
473                 .name = "da9052-wled3",
474         },
475         {
476                 .name = "da9052-tsi",
477                 .resources = da9052_tsi_resources,
478                 .num_resources = ARRAY_SIZE(da9052_tsi_resources),
479         },
480         {
481                 .name = "da9052-bat",
482                 .resources = da9052_bat_resources,
483                 .num_resources = ARRAY_SIZE(da9052_bat_resources),
484         },
485         {
486                 .name = "da9052-watchdog",
487         },
488 };
489
490 static struct regmap_irq da9052_irqs[] = {
491         [DA9052_IRQ_DCIN] = {
492                 .reg_offset = 0,
493                 .mask = DA9052_IRQ_MASK_POS_1,
494         },
495         [DA9052_IRQ_VBUS] = {
496                 .reg_offset = 0,
497                 .mask = DA9052_IRQ_MASK_POS_2,
498         },
499         [DA9052_IRQ_DCINREM] = {
500                 .reg_offset = 0,
501                 .mask = DA9052_IRQ_MASK_POS_3,
502         },
503         [DA9052_IRQ_VBUSREM] = {
504                 .reg_offset = 0,
505                 .mask = DA9052_IRQ_MASK_POS_4,
506         },
507         [DA9052_IRQ_VDDLOW] = {
508                 .reg_offset = 0,
509                 .mask = DA9052_IRQ_MASK_POS_5,
510         },
511         [DA9052_IRQ_ALARM] = {
512                 .reg_offset = 0,
513                 .mask = DA9052_IRQ_MASK_POS_6,
514         },
515         [DA9052_IRQ_SEQRDY] = {
516                 .reg_offset = 0,
517                 .mask = DA9052_IRQ_MASK_POS_7,
518         },
519         [DA9052_IRQ_COMP1V2] = {
520                 .reg_offset = 0,
521                 .mask = DA9052_IRQ_MASK_POS_8,
522         },
523         [DA9052_IRQ_NONKEY] = {
524                 .reg_offset = 1,
525                 .mask = DA9052_IRQ_MASK_POS_1,
526         },
527         [DA9052_IRQ_IDFLOAT] = {
528                 .reg_offset = 1,
529                 .mask = DA9052_IRQ_MASK_POS_2,
530         },
531         [DA9052_IRQ_IDGND] = {
532                 .reg_offset = 1,
533                 .mask = DA9052_IRQ_MASK_POS_3,
534         },
535         [DA9052_IRQ_CHGEND] = {
536                 .reg_offset = 1,
537                 .mask = DA9052_IRQ_MASK_POS_4,
538         },
539         [DA9052_IRQ_TBAT] = {
540                 .reg_offset = 1,
541                 .mask = DA9052_IRQ_MASK_POS_5,
542         },
543         [DA9052_IRQ_ADC_EOM] = {
544                 .reg_offset = 1,
545                 .mask = DA9052_IRQ_MASK_POS_6,
546         },
547         [DA9052_IRQ_PENDOWN] = {
548                 .reg_offset = 1,
549                 .mask = DA9052_IRQ_MASK_POS_7,
550         },
551         [DA9052_IRQ_TSIREADY] = {
552                 .reg_offset = 1,
553                 .mask = DA9052_IRQ_MASK_POS_8,
554         },
555         [DA9052_IRQ_GPI0] = {
556                 .reg_offset = 2,
557                 .mask = DA9052_IRQ_MASK_POS_1,
558         },
559         [DA9052_IRQ_GPI1] = {
560                 .reg_offset = 2,
561                 .mask = DA9052_IRQ_MASK_POS_2,
562         },
563         [DA9052_IRQ_GPI2] = {
564                 .reg_offset = 2,
565                 .mask = DA9052_IRQ_MASK_POS_3,
566         },
567         [DA9052_IRQ_GPI3] = {
568                 .reg_offset = 2,
569                 .mask = DA9052_IRQ_MASK_POS_4,
570         },
571         [DA9052_IRQ_GPI4] = {
572                 .reg_offset = 2,
573                 .mask = DA9052_IRQ_MASK_POS_5,
574         },
575         [DA9052_IRQ_GPI5] = {
576                 .reg_offset = 2,
577                 .mask = DA9052_IRQ_MASK_POS_6,
578         },
579         [DA9052_IRQ_GPI6] = {
580                 .reg_offset = 2,
581                 .mask = DA9052_IRQ_MASK_POS_7,
582         },
583         [DA9052_IRQ_GPI7] = {
584                 .reg_offset = 2,
585                 .mask = DA9052_IRQ_MASK_POS_8,
586         },
587         [DA9052_IRQ_GPI8] = {
588                 .reg_offset = 3,
589                 .mask = DA9052_IRQ_MASK_POS_1,
590         },
591         [DA9052_IRQ_GPI9] = {
592                 .reg_offset = 3,
593                 .mask = DA9052_IRQ_MASK_POS_2,
594         },
595         [DA9052_IRQ_GPI10] = {
596                 .reg_offset = 3,
597                 .mask = DA9052_IRQ_MASK_POS_3,
598         },
599         [DA9052_IRQ_GPI11] = {
600                 .reg_offset = 3,
601                 .mask = DA9052_IRQ_MASK_POS_4,
602         },
603         [DA9052_IRQ_GPI12] = {
604                 .reg_offset = 3,
605                 .mask = DA9052_IRQ_MASK_POS_5,
606         },
607         [DA9052_IRQ_GPI13] = {
608                 .reg_offset = 3,
609                 .mask = DA9052_IRQ_MASK_POS_6,
610         },
611         [DA9052_IRQ_GPI14] = {
612                 .reg_offset = 3,
613                 .mask = DA9052_IRQ_MASK_POS_7,
614         },
615         [DA9052_IRQ_GPI15] = {
616                 .reg_offset = 3,
617                 .mask = DA9052_IRQ_MASK_POS_8,
618         },
619 };
620
621 static struct regmap_irq_chip da9052_regmap_irq_chip = {
622         .name = "da9052_irq",
623         .status_base = DA9052_EVENT_A_REG,
624         .mask_base = DA9052_IRQ_MASK_A_REG,
625         .ack_base = DA9052_EVENT_A_REG,
626         .num_regs = DA9052_NUM_IRQ_REGS,
627         .irqs = da9052_irqs,
628         .num_irqs = ARRAY_SIZE(da9052_irqs),
629 };
630
631 struct regmap_config da9052_regmap_config = {
632         .reg_bits = 8,
633         .val_bits = 8,
634
635         .cache_type = REGCACHE_RBTREE,
636
637         .max_register = DA9052_PAGE1_CON_REG,
638         .readable_reg = da9052_reg_readable,
639         .writeable_reg = da9052_reg_writeable,
640         .volatile_reg = da9052_reg_volatile,
641 };
642 EXPORT_SYMBOL_GPL(da9052_regmap_config);
643
644 int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id)
645 {
646         struct da9052_pdata *pdata = da9052->dev->platform_data;
647         struct irq_desc *desc;
648         int ret;
649
650         mutex_init(&da9052->io_lock);
651
652         if (pdata && pdata->init != NULL)
653                 pdata->init(da9052);
654
655         da9052->chip_id = chip_id;
656
657         if (!pdata || !pdata->irq_base)
658                 da9052->irq_base = -1;
659         else
660                 da9052->irq_base = pdata->irq_base;
661
662         ret = regmap_add_irq_chip(da9052->regmap, da9052->chip_irq,
663                                   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
664                                   da9052->irq_base, &da9052_regmap_irq_chip,
665                                   NULL);
666         if (ret < 0)
667                 goto regmap_err;
668
669         desc = irq_to_desc(da9052->chip_irq);
670         da9052->irq_base = regmap_irq_chip_get_base(desc->action->dev_id);
671
672         ret = mfd_add_devices(da9052->dev, -1, da9052_subdev_info,
673                               ARRAY_SIZE(da9052_subdev_info), NULL, 0);
674         if (ret)
675                 goto err;
676
677         return 0;
678
679 err:
680         mfd_remove_devices(da9052->dev);
681 regmap_err:
682         return ret;
683 }
684
685 void da9052_device_exit(struct da9052 *da9052)
686 {
687         regmap_del_irq_chip(da9052->chip_irq,
688                             irq_get_irq_data(da9052->irq_base)->chip_data);
689         mfd_remove_devices(da9052->dev);
690 }
691
692 MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
693 MODULE_DESCRIPTION("DA9052 MFD Core");
694 MODULE_LICENSE("GPL");