PM / sleep: Asynchronous threads for suspend_noirq
[linux/fpc-iii.git] / drivers / mfd / da9055-core.c
blobcaf8dcffd0ad403d6b239f9f0c3442ac1651aa2c
1 /*
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)
33 switch (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:
101 return true;
102 default:
103 return false;
107 static bool da9055_register_writeable(struct device *dev, unsigned int reg)
109 switch (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:
177 return true;
178 default:
179 return false;
183 static bool da9055_register_volatile(struct device *dev, unsigned int reg)
185 switch (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:
219 return true;
220 default:
221 return false;
225 static struct regmap_irq da9055_irqs[] = {
226 [DA9055_IRQ_NONKEY] = {
227 .reg_offset = 0,
228 .mask = DA9055_IRQ_NONKEY_MASK,
230 [DA9055_IRQ_ALARM] = {
231 .reg_offset = 0,
232 .mask = DA9055_IRQ_ALM_MASK,
234 [DA9055_IRQ_TICK] = {
235 .reg_offset = 0,
236 .mask = DA9055_IRQ_TICK_MASK,
238 [DA9055_IRQ_HWMON] = {
239 .reg_offset = 0,
240 .mask = DA9055_IRQ_ADC_MASK,
242 [DA9055_IRQ_REGULATOR] = {
243 .reg_offset = 1,
244 .mask = DA9055_IRQ_BUCK_ILIM_MASK,
248 struct regmap_config da9055_regmap_config = {
249 .reg_bits = 8,
250 .val_bits = 8,
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 = {
262 .name = "ONKEY",
263 .start = DA9055_IRQ_NONKEY,
264 .end = DA9055_IRQ_NONKEY,
265 .flags = IORESOURCE_IRQ,
268 static struct resource da9055_rtc_resource[] = {
270 .name = "ALM",
271 .start = DA9055_IRQ_ALARM,
272 .end = DA9055_IRQ_ALARM,
273 .flags = IORESOURCE_IRQ,
276 .name = "TICK",
277 .start = DA9055_IRQ_TICK,
278 .end = DA9055_IRQ_TICK,
279 .flags = IORESOURCE_IRQ,
283 static struct resource da9055_hwmon_resource = {
284 .name = "HWMON",
285 .start = DA9055_IRQ_HWMON,
286 .end = DA9055_IRQ_HWMON,
287 .flags = IORESOURCE_IRQ,
290 static struct resource da9055_ld05_6_resource = {
291 .name = "REGULATOR",
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 = "dialog,da9055-gpio",
300 .name = "da9055-gpio",
303 .of_compatible = "dialog,da9055-regulator",
304 .name = "da9055-regulator",
305 .id = 1,
308 .of_compatible = "dialog,da9055-regulator",
309 .name = "da9055-regulator",
310 .id = 2,
313 .of_compatible = "dialog,da9055-regulator",
314 .name = "da9055-regulator",
315 .id = 3,
318 .of_compatible = "dialog,da9055-regulator",
319 .name = "da9055-regulator",
320 .id = 4,
323 .of_compatible = "dialog,da9055-regulator",
324 .name = "da9055-regulator",
325 .id = 5,
328 .of_compatible = "dialog,da9055-regulator",
329 .name = "da9055-regulator",
330 .id = 6,
333 .of_compatible = "dialog,da9055-regulator",
334 .name = "da9055-regulator",
335 .id = 7,
336 .resources = &da9055_ld05_6_resource,
337 .num_resources = 1,
340 .of_compatible = "dialog,da9055-regulator",
341 .name = "da9055-regulator",
342 .resources = &da9055_ld05_6_resource,
343 .num_resources = 1,
344 .id = 8,
347 .of_compatible = "dialog,da9055-onkey",
348 .name = "da9055-onkey",
349 .resources = &da9055_onkey_resource,
350 .num_resources = 1,
353 .of_compatible = "dialog,da9055-rtc",
354 .name = "da9055-rtc",
355 .resources = da9055_rtc_resource,
356 .num_resources = ARRAY_SIZE(da9055_rtc_resource),
359 .of_compatible = "dialog,da9055-hwmon",
360 .name = "da9055-hwmon",
361 .resources = &da9055_hwmon_resource,
362 .num_resources = 1,
365 .of_compatible = "dialog,da9055-watchdog",
366 .name = "da9055-watchdog",
370 static 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,
375 .num_regs = 3,
376 .irqs = da9055_irqs,
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);
383 int ret;
384 uint8_t clear_events[3] = {0xFF, 0xFF, 0xFF};
386 if (pdata && pdata->init != NULL)
387 pdata->init(da9055);
389 if (!pdata || !pdata->irq_base)
390 da9055->irq_base = -1;
391 else
392 da9055->irq_base = pdata->irq_base;
394 ret = da9055_group_write(da9055, DA9055_REG_EVENT_A, 3, clear_events);
395 if (ret < 0)
396 return ret;
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,
401 &da9055->irq_data);
402 if (ret < 0)
403 return ret;
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);
410 if (ret)
411 goto err;
413 return 0;
415 err:
416 mfd_remove_devices(da9055->dev);
417 return ret;
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>");