2 * Device access for Dialog DA9055 PMICs.
4 * Copyright(c) 2012 Dialog Semiconductor Ltd.
6 * Author: David Dajun Chen <dchen@diasemi.com>
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.
14 #include <linux/module.h>
15 #include <linux/device.h>
16 #include <linux/input.h>
17 #include <linux/irq.h>
18 #include <linux/mutex.h>
20 #include <linux/mfd/core.h>
21 #include <linux/mfd/da9055/core.h>
22 #include <linux/mfd/da9055/pdata.h>
23 #include <linux/mfd/da9055/reg.h>
25 #define DA9055_IRQ_NONKEY_MASK 0x01
26 #define DA9055_IRQ_ALM_MASK 0x02
27 #define DA9055_IRQ_TICK_MASK 0x04
28 #define DA9055_IRQ_ADC_MASK 0x08
29 #define DA9055_IRQ_BUCK_ILIM_MASK 0x08
31 static bool da9055_register_readable(struct device
*dev
, unsigned int reg
)
34 case DA9055_REG_STATUS_A
:
35 case DA9055_REG_STATUS_B
:
36 case DA9055_REG_EVENT_A
:
37 case DA9055_REG_EVENT_B
:
38 case DA9055_REG_EVENT_C
:
39 case DA9055_REG_IRQ_MASK_A
:
40 case DA9055_REG_IRQ_MASK_B
:
41 case DA9055_REG_IRQ_MASK_C
:
43 case DA9055_REG_CONTROL_A
:
44 case DA9055_REG_CONTROL_B
:
45 case DA9055_REG_CONTROL_C
:
46 case DA9055_REG_CONTROL_D
:
47 case DA9055_REG_CONTROL_E
:
49 case DA9055_REG_ADC_MAN
:
50 case DA9055_REG_ADC_CONT
:
51 case DA9055_REG_VSYS_MON
:
52 case DA9055_REG_ADC_RES_L
:
53 case DA9055_REG_ADC_RES_H
:
54 case DA9055_REG_VSYS_RES
:
55 case DA9055_REG_ADCIN1_RES
:
56 case DA9055_REG_ADCIN2_RES
:
57 case DA9055_REG_ADCIN3_RES
:
59 case DA9055_REG_COUNT_S
:
60 case DA9055_REG_COUNT_MI
:
61 case DA9055_REG_COUNT_H
:
62 case DA9055_REG_COUNT_D
:
63 case DA9055_REG_COUNT_MO
:
64 case DA9055_REG_COUNT_Y
:
65 case DA9055_REG_ALARM_H
:
66 case DA9055_REG_ALARM_D
:
67 case DA9055_REG_ALARM_MI
:
68 case DA9055_REG_ALARM_MO
:
69 case DA9055_REG_ALARM_Y
:
71 case DA9055_REG_GPIO0_1
:
72 case DA9055_REG_GPIO2
:
73 case DA9055_REG_GPIO_MODE0_2
:
75 case DA9055_REG_BCORE_CONT
:
76 case DA9055_REG_BMEM_CONT
:
77 case DA9055_REG_LDO1_CONT
:
78 case DA9055_REG_LDO2_CONT
:
79 case DA9055_REG_LDO3_CONT
:
80 case DA9055_REG_LDO4_CONT
:
81 case DA9055_REG_LDO5_CONT
:
82 case DA9055_REG_LDO6_CONT
:
83 case DA9055_REG_BUCK_LIM
:
84 case DA9055_REG_BCORE_MODE
:
85 case DA9055_REG_VBCORE_A
:
86 case DA9055_REG_VBMEM_A
:
87 case DA9055_REG_VLDO1_A
:
88 case DA9055_REG_VLDO2_A
:
89 case DA9055_REG_VLDO3_A
:
90 case DA9055_REG_VLDO4_A
:
91 case DA9055_REG_VLDO5_A
:
92 case DA9055_REG_VLDO6_A
:
93 case DA9055_REG_VBCORE_B
:
94 case DA9055_REG_VBMEM_B
:
95 case DA9055_REG_VLDO1_B
:
96 case DA9055_REG_VLDO2_B
:
97 case DA9055_REG_VLDO3_B
:
98 case DA9055_REG_VLDO4_B
:
99 case DA9055_REG_VLDO5_B
:
100 case DA9055_REG_VLDO6_B
:
107 static bool da9055_register_writeable(struct device
*dev
, unsigned int reg
)
110 case DA9055_REG_STATUS_A
:
111 case DA9055_REG_STATUS_B
:
112 case DA9055_REG_EVENT_A
:
113 case DA9055_REG_EVENT_B
:
114 case DA9055_REG_EVENT_C
:
115 case DA9055_REG_IRQ_MASK_A
:
116 case DA9055_REG_IRQ_MASK_B
:
117 case DA9055_REG_IRQ_MASK_C
:
119 case DA9055_REG_CONTROL_A
:
120 case DA9055_REG_CONTROL_B
:
121 case DA9055_REG_CONTROL_C
:
122 case DA9055_REG_CONTROL_D
:
123 case DA9055_REG_CONTROL_E
:
125 case DA9055_REG_ADC_MAN
:
126 case DA9055_REG_ADC_CONT
:
127 case DA9055_REG_VSYS_MON
:
128 case DA9055_REG_ADC_RES_L
:
129 case DA9055_REG_ADC_RES_H
:
130 case DA9055_REG_VSYS_RES
:
131 case DA9055_REG_ADCIN1_RES
:
132 case DA9055_REG_ADCIN2_RES
:
133 case DA9055_REG_ADCIN3_RES
:
135 case DA9055_REG_COUNT_S
:
136 case DA9055_REG_COUNT_MI
:
137 case DA9055_REG_COUNT_H
:
138 case DA9055_REG_COUNT_D
:
139 case DA9055_REG_COUNT_MO
:
140 case DA9055_REG_COUNT_Y
:
141 case DA9055_REG_ALARM_H
:
142 case DA9055_REG_ALARM_D
:
143 case DA9055_REG_ALARM_MI
:
144 case DA9055_REG_ALARM_MO
:
145 case DA9055_REG_ALARM_Y
:
147 case DA9055_REG_GPIO0_1
:
148 case DA9055_REG_GPIO2
:
149 case DA9055_REG_GPIO_MODE0_2
:
151 case DA9055_REG_BCORE_CONT
:
152 case DA9055_REG_BMEM_CONT
:
153 case DA9055_REG_LDO1_CONT
:
154 case DA9055_REG_LDO2_CONT
:
155 case DA9055_REG_LDO3_CONT
:
156 case DA9055_REG_LDO4_CONT
:
157 case DA9055_REG_LDO5_CONT
:
158 case DA9055_REG_LDO6_CONT
:
159 case DA9055_REG_BUCK_LIM
:
160 case DA9055_REG_BCORE_MODE
:
161 case DA9055_REG_VBCORE_A
:
162 case DA9055_REG_VBMEM_A
:
163 case DA9055_REG_VLDO1_A
:
164 case DA9055_REG_VLDO2_A
:
165 case DA9055_REG_VLDO3_A
:
166 case DA9055_REG_VLDO4_A
:
167 case DA9055_REG_VLDO5_A
:
168 case DA9055_REG_VLDO6_A
:
169 case DA9055_REG_VBCORE_B
:
170 case DA9055_REG_VBMEM_B
:
171 case DA9055_REG_VLDO1_B
:
172 case DA9055_REG_VLDO2_B
:
173 case DA9055_REG_VLDO3_B
:
174 case DA9055_REG_VLDO4_B
:
175 case DA9055_REG_VLDO5_B
:
176 case DA9055_REG_VLDO6_B
:
183 static bool da9055_register_volatile(struct device
*dev
, unsigned int reg
)
186 case DA9055_REG_STATUS_A
:
187 case DA9055_REG_STATUS_B
:
188 case DA9055_REG_EVENT_A
:
189 case DA9055_REG_EVENT_B
:
190 case DA9055_REG_EVENT_C
:
192 case DA9055_REG_CONTROL_A
:
193 case DA9055_REG_CONTROL_E
:
195 case DA9055_REG_ADC_MAN
:
196 case DA9055_REG_ADC_RES_L
:
197 case DA9055_REG_ADC_RES_H
:
198 case DA9055_REG_VSYS_RES
:
199 case DA9055_REG_ADCIN1_RES
:
200 case DA9055_REG_ADCIN2_RES
:
201 case DA9055_REG_ADCIN3_RES
:
203 case DA9055_REG_COUNT_S
:
204 case DA9055_REG_COUNT_MI
:
205 case DA9055_REG_COUNT_H
:
206 case DA9055_REG_COUNT_D
:
207 case DA9055_REG_COUNT_MO
:
208 case DA9055_REG_COUNT_Y
:
209 case DA9055_REG_ALARM_MI
:
211 case DA9055_REG_BCORE_CONT
:
212 case DA9055_REG_BMEM_CONT
:
213 case DA9055_REG_LDO1_CONT
:
214 case DA9055_REG_LDO2_CONT
:
215 case DA9055_REG_LDO3_CONT
:
216 case DA9055_REG_LDO4_CONT
:
217 case DA9055_REG_LDO5_CONT
:
218 case DA9055_REG_LDO6_CONT
:
225 static const struct regmap_irq da9055_irqs
[] = {
226 [DA9055_IRQ_NONKEY
] = {
228 .mask
= DA9055_IRQ_NONKEY_MASK
,
230 [DA9055_IRQ_ALARM
] = {
232 .mask
= DA9055_IRQ_ALM_MASK
,
234 [DA9055_IRQ_TICK
] = {
236 .mask
= DA9055_IRQ_TICK_MASK
,
238 [DA9055_IRQ_HWMON
] = {
240 .mask
= DA9055_IRQ_ADC_MASK
,
242 [DA9055_IRQ_REGULATOR
] = {
244 .mask
= DA9055_IRQ_BUCK_ILIM_MASK
,
248 const struct regmap_config da9055_regmap_config
= {
252 .cache_type
= REGCACHE_RBTREE
,
254 .max_register
= DA9055_MAX_REGISTER_CNT
,
255 .readable_reg
= da9055_register_readable
,
256 .writeable_reg
= da9055_register_writeable
,
257 .volatile_reg
= da9055_register_volatile
,
259 EXPORT_SYMBOL_GPL(da9055_regmap_config
);
261 static struct resource da9055_onkey_resource
= {
263 .start
= DA9055_IRQ_NONKEY
,
264 .end
= DA9055_IRQ_NONKEY
,
265 .flags
= IORESOURCE_IRQ
,
268 static struct resource da9055_rtc_resource
[] = {
271 .start
= DA9055_IRQ_ALARM
,
272 .end
= DA9055_IRQ_ALARM
,
273 .flags
= IORESOURCE_IRQ
,
277 .start
= DA9055_IRQ_TICK
,
278 .end
= DA9055_IRQ_TICK
,
279 .flags
= IORESOURCE_IRQ
,
283 static struct resource da9055_hwmon_resource
= {
285 .start
= DA9055_IRQ_HWMON
,
286 .end
= DA9055_IRQ_HWMON
,
287 .flags
= IORESOURCE_IRQ
,
290 static struct resource da9055_ld05_6_resource
= {
292 .start
= DA9055_IRQ_REGULATOR
,
293 .end
= DA9055_IRQ_REGULATOR
,
294 .flags
= IORESOURCE_IRQ
,
297 static const struct mfd_cell da9055_devs
[] = {
299 .of_compatible
= "dlg,da9055-gpio",
300 .name
= "da9055-gpio",
303 .of_compatible
= "dlg,da9055-regulator",
304 .name
= "da9055-regulator",
308 .of_compatible
= "dlg,da9055-regulator",
309 .name
= "da9055-regulator",
313 .of_compatible
= "dlg,da9055-regulator",
314 .name
= "da9055-regulator",
318 .of_compatible
= "dlg,da9055-regulator",
319 .name
= "da9055-regulator",
323 .of_compatible
= "dlg,da9055-regulator",
324 .name
= "da9055-regulator",
328 .of_compatible
= "dlg,da9055-regulator",
329 .name
= "da9055-regulator",
333 .of_compatible
= "dlg,da9055-regulator",
334 .name
= "da9055-regulator",
336 .resources
= &da9055_ld05_6_resource
,
340 .of_compatible
= "dlg,da9055-regulator",
341 .name
= "da9055-regulator",
342 .resources
= &da9055_ld05_6_resource
,
347 .of_compatible
= "dlg,da9055-onkey",
348 .name
= "da9055-onkey",
349 .resources
= &da9055_onkey_resource
,
353 .of_compatible
= "dlg,da9055-rtc",
354 .name
= "da9055-rtc",
355 .resources
= da9055_rtc_resource
,
356 .num_resources
= ARRAY_SIZE(da9055_rtc_resource
),
359 .of_compatible
= "dlg,da9055-hwmon",
360 .name
= "da9055-hwmon",
361 .resources
= &da9055_hwmon_resource
,
365 .of_compatible
= "dlg,da9055-watchdog",
366 .name
= "da9055-watchdog",
370 static const struct regmap_irq_chip da9055_regmap_irq_chip
= {
371 .name
= "da9055_irq",
372 .status_base
= DA9055_REG_EVENT_A
,
373 .mask_base
= DA9055_REG_IRQ_MASK_A
,
374 .ack_base
= DA9055_REG_EVENT_A
,
377 .num_irqs
= ARRAY_SIZE(da9055_irqs
),
380 int da9055_device_init(struct da9055
*da9055
)
382 struct da9055_pdata
*pdata
= dev_get_platdata(da9055
->dev
);
384 uint8_t clear_events
[3] = {0xFF, 0xFF, 0xFF};
386 if (pdata
&& pdata
->init
!= NULL
)
389 if (!pdata
|| !pdata
->irq_base
)
390 da9055
->irq_base
= -1;
392 da9055
->irq_base
= pdata
->irq_base
;
394 ret
= da9055_group_write(da9055
, DA9055_REG_EVENT_A
, 3, clear_events
);
398 ret
= regmap_add_irq_chip(da9055
->regmap
, da9055
->chip_irq
,
399 IRQF_TRIGGER_LOW
| IRQF_ONESHOT
,
400 da9055
->irq_base
, &da9055_regmap_irq_chip
,
405 da9055
->irq_base
= regmap_irq_chip_get_base(da9055
->irq_data
);
407 ret
= mfd_add_devices(da9055
->dev
, -1,
408 da9055_devs
, ARRAY_SIZE(da9055_devs
),
409 NULL
, da9055
->irq_base
, NULL
);
416 mfd_remove_devices(da9055
->dev
);
420 void da9055_device_exit(struct da9055
*da9055
)
422 regmap_del_irq_chip(da9055
->chip_irq
, da9055
->irq_data
);
423 mfd_remove_devices(da9055
->dev
);
426 MODULE_DESCRIPTION("Core support for the DA9055 PMIC");
427 MODULE_LICENSE("GPL");
428 MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");