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