xref: /linux/drivers/mfd/da9055-core.c (revision bd628c1bed7902ec1f24ba0fe70758949146abbe)
1 /*
2  * Device access for Dialog DA9055 PMICs.
3  *
4  * Copyright(c) 2012 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/module.h>
15 #include <linux/device.h>
16 #include <linux/input.h>
17 #include <linux/irq.h>
18 #include <linux/mutex.h>
19 
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>
24 
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
30 
31 static bool da9055_register_readable(struct device *dev, unsigned int reg)
32 {
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:
42 
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:
48 
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:
58 
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:
70 
71 	case DA9055_REG_GPIO0_1:
72 	case DA9055_REG_GPIO2:
73 	case DA9055_REG_GPIO_MODE0_2:
74 
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;
104 	}
105 }
106 
107 static bool da9055_register_writeable(struct device *dev, unsigned int reg)
108 {
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:
118 
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:
124 
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:
134 
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:
146 
147 	case DA9055_REG_GPIO0_1:
148 	case DA9055_REG_GPIO2:
149 	case DA9055_REG_GPIO_MODE0_2:
150 
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;
180 	}
181 }
182 
183 static bool da9055_register_volatile(struct device *dev, unsigned int reg)
184 {
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:
191 
192 	case DA9055_REG_CONTROL_A:
193 	case DA9055_REG_CONTROL_E:
194 
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:
202 
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:
210 
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;
222 	}
223 }
224 
225 static const struct regmap_irq da9055_irqs[] = {
226 	[DA9055_IRQ_NONKEY] = {
227 		.reg_offset = 0,
228 		.mask = DA9055_IRQ_NONKEY_MASK,
229 	},
230 	[DA9055_IRQ_ALARM] = {
231 		.reg_offset = 0,
232 		.mask = DA9055_IRQ_ALM_MASK,
233 	},
234 	[DA9055_IRQ_TICK] = {
235 		.reg_offset = 0,
236 		.mask = DA9055_IRQ_TICK_MASK,
237 	},
238 	[DA9055_IRQ_HWMON] = {
239 		.reg_offset = 0,
240 		.mask = DA9055_IRQ_ADC_MASK,
241 	},
242 	[DA9055_IRQ_REGULATOR] = {
243 		.reg_offset = 1,
244 		.mask = DA9055_IRQ_BUCK_ILIM_MASK,
245 	},
246 };
247 
248 const struct regmap_config da9055_regmap_config = {
249 	.reg_bits = 8,
250 	.val_bits = 8,
251 
252 	.cache_type = REGCACHE_RBTREE,
253 
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,
258 };
259 EXPORT_SYMBOL_GPL(da9055_regmap_config);
260 
261 static struct resource da9055_onkey_resource = {
262 	.name = "ONKEY",
263 	.start = DA9055_IRQ_NONKEY,
264 	.end   = DA9055_IRQ_NONKEY,
265 	.flags = IORESOURCE_IRQ,
266 };
267 
268 static struct resource da9055_rtc_resource[] = {
269 	{
270 		.name = "ALM",
271 		.start = DA9055_IRQ_ALARM,
272 		.end   = DA9055_IRQ_ALARM,
273 		.flags = IORESOURCE_IRQ,
274 	},
275 	{
276 		.name = "TICK",
277 		.start = DA9055_IRQ_TICK,
278 		.end   = DA9055_IRQ_TICK,
279 		.flags = IORESOURCE_IRQ,
280 	},
281 };
282 
283 static struct resource da9055_hwmon_resource = {
284 	.name = "HWMON",
285 	.start = DA9055_IRQ_HWMON,
286 	.end   = DA9055_IRQ_HWMON,
287 	.flags = IORESOURCE_IRQ,
288 };
289 
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,
295 };
296 
297 static const struct mfd_cell da9055_devs[] = {
298 	{
299 		.of_compatible = "dlg,da9055-gpio",
300 		.name = "da9055-gpio",
301 	},
302 	{
303 		.of_compatible = "dlg,da9055-regulator",
304 		.name = "da9055-regulator",
305 		.id = 1,
306 	},
307 	{
308 		.of_compatible = "dlg,da9055-regulator",
309 		.name = "da9055-regulator",
310 		.id = 2,
311 	},
312 	{
313 		.of_compatible = "dlg,da9055-regulator",
314 		.name = "da9055-regulator",
315 		.id = 3,
316 	},
317 	{
318 		.of_compatible = "dlg,da9055-regulator",
319 		.name = "da9055-regulator",
320 		.id = 4,
321 	},
322 	{
323 		.of_compatible = "dlg,da9055-regulator",
324 		.name = "da9055-regulator",
325 		.id = 5,
326 	},
327 	{
328 		.of_compatible = "dlg,da9055-regulator",
329 		.name = "da9055-regulator",
330 		.id = 6,
331 	},
332 	{
333 		.of_compatible = "dlg,da9055-regulator",
334 		.name = "da9055-regulator",
335 		.id = 7,
336 		.resources = &da9055_ld05_6_resource,
337 		.num_resources = 1,
338 	},
339 	{
340 		.of_compatible = "dlg,da9055-regulator",
341 		.name = "da9055-regulator",
342 		.resources = &da9055_ld05_6_resource,
343 		.num_resources = 1,
344 		.id = 8,
345 	},
346 	{
347 		.of_compatible = "dlg,da9055-onkey",
348 		.name = "da9055-onkey",
349 		.resources = &da9055_onkey_resource,
350 		.num_resources = 1,
351 	},
352 	{
353 		.of_compatible = "dlg,da9055-rtc",
354 		.name = "da9055-rtc",
355 		.resources = da9055_rtc_resource,
356 		.num_resources = ARRAY_SIZE(da9055_rtc_resource),
357 	},
358 	{
359 		.of_compatible = "dlg,da9055-hwmon",
360 		.name = "da9055-hwmon",
361 		.resources = &da9055_hwmon_resource,
362 		.num_resources = 1,
363 	},
364 	{
365 		.of_compatible = "dlg,da9055-watchdog",
366 		.name = "da9055-watchdog",
367 	},
368 };
369 
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,
375 	.num_regs = 3,
376 	.irqs = da9055_irqs,
377 	.num_irqs = ARRAY_SIZE(da9055_irqs),
378 };
379 
380 int da9055_device_init(struct da9055 *da9055)
381 {
382 	struct da9055_pdata *pdata = dev_get_platdata(da9055->dev);
383 	int ret;
384 	uint8_t clear_events[3] = {0xFF, 0xFF, 0xFF};
385 
386 	if (pdata && pdata->init != NULL)
387 		pdata->init(da9055);
388 
389 	if (!pdata || !pdata->irq_base)
390 		da9055->irq_base = -1;
391 	else
392 		da9055->irq_base = pdata->irq_base;
393 
394 	ret = da9055_group_write(da9055, DA9055_REG_EVENT_A, 3, clear_events);
395 	if (ret < 0)
396 		return ret;
397 
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;
404 
405 	da9055->irq_base = regmap_irq_chip_get_base(da9055->irq_data);
406 
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;
412 
413 	return 0;
414 
415 err:
416 	mfd_remove_devices(da9055->dev);
417 	return ret;
418 }
419 
420 void da9055_device_exit(struct da9055 *da9055)
421 {
422 	regmap_del_irq_chip(da9055->chip_irq, da9055->irq_data);
423 	mfd_remove_devices(da9055->dev);
424 }
425 
426 MODULE_DESCRIPTION("Core support for the DA9055 PMIC");
427 MODULE_LICENSE("GPL");
428 MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
429