aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/da903x.c
diff options
context:
space:
mode:
authorEric Miao <eric.miao@marvell.com>2008-10-15 06:20:06 -0400
committerSamuel Ortiz <samuel@sortiz.org>2008-10-19 16:54:11 -0400
commit26b8f5e1e2d1229c186d8e61d26513c43a058c5e (patch)
tree0d1b2b7e92730f82476e1b5811ceda50f0513125 /drivers/mfd/da903x.c
parenta603a7fa8717fb778bba91b5a879babf333dc6a3 (diff)
mfd: add base support for Dialog DA9030/DA9034 PMICs
DA9030 (a.k.a ARAVA) and DA9034 (a.k.a MICCO) are PMICs designed by Dialog Semiconductor, usually found on PXA-based platforms. These PMICs are I2C-based, multi-function devices, usually with LEDs, PWMs for backlight, BUCKs and LDOs, ADCs and touchscreen controller (on DA9034). This is the base support for the I2C operations, event registration and handling, sub-devices management. Signed-off-by: Mike Rapoport <mike@compulab.co.il> Signed-off-by: Eric Miao <eric.miao@marvell.com> Signed-off-by: Liam Girdwood <lrg@kernel.org> Signed-off-by: Samuel Ortiz <sameo@openedhand.com>
Diffstat (limited to 'drivers/mfd/da903x.c')
-rw-r--r--drivers/mfd/da903x.c563
1 files changed, 563 insertions, 0 deletions
diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c
new file mode 100644
index 000000000000..b57326ae464d
--- /dev/null
+++ b/drivers/mfd/da903x.c
@@ -0,0 +1,563 @@
1/*
2 * Base driver for Dialog Semiconductor DA9030/DA9034
3 *
4 * Copyright (C) 2008 Compulab, Ltd.
5 * Mike Rapoport <mike@compulab.co.il>
6 *
7 * Copyright (C) 2006-2008 Marvell International Ltd.
8 * Eric Miao <eric.miao@marvell.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/interrupt.h>
18#include <linux/platform_device.h>
19#include <linux/i2c.h>
20#include <linux/mfd/da903x.h>
21
22#define DA9030_CHIP_ID 0x00
23#define DA9030_EVENT_A 0x01
24#define DA9030_EVENT_B 0x02
25#define DA9030_EVENT_C 0x03
26#define DA9030_STATUS 0x04
27#define DA9030_IRQ_MASK_A 0x05
28#define DA9030_IRQ_MASK_B 0x06
29#define DA9030_IRQ_MASK_C 0x07
30#define DA9030_SYS_CTRL_A 0x08
31#define DA9030_SYS_CTRL_B 0x09
32#define DA9030_FAULT_LOG 0x0a
33
34#define DA9034_CHIP_ID 0x00
35#define DA9034_EVENT_A 0x01
36#define DA9034_EVENT_B 0x02
37#define DA9034_EVENT_C 0x03
38#define DA9034_EVENT_D 0x04
39#define DA9034_STATUS_A 0x05
40#define DA9034_STATUS_B 0x06
41#define DA9034_IRQ_MASK_A 0x07
42#define DA9034_IRQ_MASK_B 0x08
43#define DA9034_IRQ_MASK_C 0x09
44#define DA9034_IRQ_MASK_D 0x0a
45#define DA9034_SYS_CTRL_A 0x0b
46#define DA9034_SYS_CTRL_B 0x0c
47#define DA9034_FAULT_LOG 0x0d
48
49struct da903x_chip;
50
51struct da903x_chip_ops {
52 int (*init_chip)(struct da903x_chip *);
53 int (*unmask_events)(struct da903x_chip *, unsigned int events);
54 int (*mask_events)(struct da903x_chip *, unsigned int events);
55 int (*read_events)(struct da903x_chip *, unsigned int *events);
56 int (*read_status)(struct da903x_chip *, unsigned int *status);
57};
58
59struct da903x_chip {
60 struct i2c_client *client;
61 struct device *dev;
62 struct da903x_chip_ops *ops;
63
64 int type;
65 uint32_t events_mask;
66
67 struct mutex lock;
68 struct work_struct irq_work;
69
70 struct blocking_notifier_head notifier_list;
71};
72
73static inline int __da903x_read(struct i2c_client *client,
74 int reg, uint8_t *val)
75{
76 int ret;
77
78 ret = i2c_smbus_read_byte_data(client, reg);
79 if (ret < 0) {
80 dev_err(&client->dev, "failed reading at 0x%02x\n", reg);
81 return ret;
82 }
83
84 *val = (uint8_t)ret;
85 return 0;
86}
87
88static inline int __da903x_reads(struct i2c_client *client, int reg,
89 int len, uint8_t *val)
90{
91 int ret;
92
93 ret = i2c_smbus_read_i2c_block_data(client, reg, len, val);
94 if (ret < 0) {
95 dev_err(&client->dev, "failed reading from 0x%02x\n", reg);
96 return ret;
97 }
98 return 0;
99}
100
101static inline int __da903x_write(struct i2c_client *client,
102 int reg, uint8_t val)
103{
104 int ret;
105
106 ret = i2c_smbus_write_byte_data(client, reg, val);
107 if (ret < 0) {
108 dev_err(&client->dev, "failed writing 0x%02x to 0x%02x\n",
109 val, reg);
110 return ret;
111 }
112 return 0;
113}
114
115static inline int __da903x_writes(struct i2c_client *client, int reg,
116 int len, uint8_t *val)
117{
118 int ret;
119
120 ret = i2c_smbus_write_i2c_block_data(client, reg, len, val);
121 if (ret < 0) {
122 dev_err(&client->dev, "failed writings to 0x%02x\n", reg);
123 return ret;
124 }
125 return 0;
126}
127
128int da903x_register_notifier(struct device *dev, struct notifier_block *nb,
129 unsigned int events)
130{
131 struct da903x_chip *chip = dev_get_drvdata(dev);
132
133 chip->ops->unmask_events(chip, events);
134 return blocking_notifier_chain_register(&chip->notifier_list, nb);
135}
136EXPORT_SYMBOL_GPL(da903x_register_notifier);
137
138int da903x_unregister_notifier(struct device *dev, struct notifier_block *nb,
139 unsigned int events)
140{
141 struct da903x_chip *chip = dev_get_drvdata(dev);
142
143 chip->ops->mask_events(chip, events);
144 return blocking_notifier_chain_unregister(&chip->notifier_list, nb);
145}
146EXPORT_SYMBOL_GPL(da903x_unregister_notifier);
147
148int da903x_write(struct device *dev, int reg, uint8_t val)
149{
150 return __da903x_write(to_i2c_client(dev), reg, val);
151}
152EXPORT_SYMBOL_GPL(da903x_write);
153
154int da903x_read(struct device *dev, int reg, uint8_t *val)
155{
156 return __da903x_read(to_i2c_client(dev), reg, val);
157}
158EXPORT_SYMBOL_GPL(da903x_read);
159
160int da903x_set_bits(struct device *dev, int reg, uint8_t bit_mask)
161{
162 struct da903x_chip *chip = dev_get_drvdata(dev);
163 uint8_t reg_val;
164 int ret = 0;
165
166 mutex_lock(&chip->lock);
167
168 ret = __da903x_read(chip->client, reg, &reg_val);
169 if (ret)
170 goto out;
171
172 if ((reg_val & bit_mask) == 0) {
173 reg_val |= bit_mask;
174 ret = __da903x_write(chip->client, reg, reg_val);
175 }
176out:
177 mutex_unlock(&chip->lock);
178 return ret;
179}
180EXPORT_SYMBOL_GPL(da903x_set_bits);
181
182int da903x_clr_bits(struct device *dev, int reg, uint8_t bit_mask)
183{
184 struct da903x_chip *chip = dev_get_drvdata(dev);
185 uint8_t reg_val;
186 int ret = 0;
187
188 mutex_lock(&chip->lock);
189
190 ret = __da903x_read(chip->client, reg, &reg_val);
191 if (ret)
192 goto out;
193
194 if (reg_val & bit_mask) {
195 reg_val &= ~bit_mask;
196 ret = __da903x_write(chip->client, reg, reg_val);
197 }
198out:
199 mutex_unlock(&chip->lock);
200 return ret;
201}
202EXPORT_SYMBOL_GPL(da903x_clr_bits);
203
204int da903x_update(struct device *dev, int reg, uint8_t val, uint8_t mask)
205{
206 struct da903x_chip *chip = dev_get_drvdata(dev);
207 uint8_t reg_val;
208 int ret = 0;
209
210 mutex_lock(&chip->lock);
211
212 ret = __da903x_read(chip->client, reg, &reg_val);
213 if (ret)
214 goto out;
215
216 if ((reg_val & mask) != val) {
217 reg_val = (reg_val & ~mask) | val;
218 ret = __da903x_write(chip->client, reg, reg_val);
219 }
220out:
221 mutex_unlock(&chip->lock);
222 return ret;
223}
224EXPORT_SYMBOL_GPL(da903x_update);
225
226int da903x_query_status(struct device *dev, unsigned int sbits)
227{
228 struct da903x_chip *chip = dev_get_drvdata(dev);
229 unsigned int status = 0;
230
231 chip->ops->read_status(chip, &status);
232 return ((status & sbits) == sbits);
233}
234EXPORT_SYMBOL(da903x_query_status);
235
236static int __devinit da9030_init_chip(struct da903x_chip *chip)
237{
238 uint8_t chip_id;
239 int err;
240
241 err = __da903x_read(chip->client, DA9030_CHIP_ID, &chip_id);
242 if (err)
243 return err;
244
245 err = __da903x_write(chip->client, DA9030_SYS_CTRL_A, 0xE8);
246 if (err)
247 return err;
248
249 dev_info(chip->dev, "DA9030 (CHIP ID: 0x%02x) detected\n", chip_id);
250 return 0;
251}
252
253static int da9030_unmask_events(struct da903x_chip *chip, unsigned int events)
254{
255 uint8_t v[3];
256
257 chip->events_mask &= ~events;
258
259 v[0] = (chip->events_mask & 0xff);
260 v[1] = (chip->events_mask >> 8) & 0xff;
261 v[2] = (chip->events_mask >> 16) & 0xff;
262
263 return __da903x_writes(chip->client, DA9030_IRQ_MASK_A, 3, v);
264}
265
266static int da9030_mask_events(struct da903x_chip *chip, unsigned int events)
267{
268 uint8_t v[3];
269
270 chip->events_mask &= ~events;
271
272 v[0] = (chip->events_mask & 0xff);
273 v[1] = (chip->events_mask >> 8) & 0xff;
274 v[2] = (chip->events_mask >> 16) & 0xff;
275
276 return __da903x_writes(chip->client, DA9030_IRQ_MASK_A, 3, v);
277}
278
279static int da9030_read_events(struct da903x_chip *chip, unsigned int *events)
280{
281 uint8_t v[3] = {0, 0, 0};
282 int ret;
283
284 ret = __da903x_reads(chip->client, DA9030_EVENT_A, 3, v);
285 if (ret < 0)
286 return ret;
287
288 *events = (v[2] << 16) | (v[1] << 8) | v[0];
289 return 0;
290}
291
292static int da9030_read_status(struct da903x_chip *chip, unsigned int *status)
293{
294 return __da903x_read(chip->client, DA9030_STATUS, (uint8_t *)status);
295}
296
297static int da9034_init_chip(struct da903x_chip *chip)
298{
299 uint8_t chip_id;
300 int err;
301
302 err = __da903x_read(chip->client, DA9034_CHIP_ID, &chip_id);
303 if (err)
304 return err;
305
306 err = __da903x_write(chip->client, DA9034_SYS_CTRL_A, 0xE8);
307 if (err)
308 return err;
309
310 /* avoid SRAM power off during sleep*/
311 __da903x_write(chip->client, 0x10, 0x07);
312 __da903x_write(chip->client, 0x11, 0xff);
313 __da903x_write(chip->client, 0x12, 0xff);
314
315 /* Enable the ONKEY power down functionality */
316 __da903x_write(chip->client, DA9034_SYS_CTRL_B, 0x20);
317 __da903x_write(chip->client, DA9034_SYS_CTRL_A, 0x60);
318
319 /* workaround to make LEDs work */
320 __da903x_write(chip->client, 0x90, 0x01);
321 __da903x_write(chip->client, 0xB0, 0x08);
322
323 /* make ADTV1 and SDTV1 effective */
324 __da903x_write(chip->client, 0x20, 0x00);
325
326 dev_info(chip->dev, "DA9034 (CHIP ID: 0x%02x) detected\n", chip_id);
327 return 0;
328}
329
330static int da9034_unmask_events(struct da903x_chip *chip, unsigned int events)
331{
332 uint8_t v[4];
333
334 chip->events_mask &= ~events;
335
336 v[0] = (chip->events_mask & 0xff);
337 v[1] = (chip->events_mask >> 8) & 0xff;
338 v[2] = (chip->events_mask >> 16) & 0xff;
339 v[3] = (chip->events_mask >> 24) & 0xff;
340
341 return __da903x_writes(chip->client, DA9034_IRQ_MASK_A, 4, v);
342}
343
344static int da9034_mask_events(struct da903x_chip *chip, unsigned int events)
345{
346 uint8_t v[4];
347
348 chip->events_mask |= events;
349
350 v[0] = (chip->events_mask & 0xff);
351 v[1] = (chip->events_mask >> 8) & 0xff;
352 v[2] = (chip->events_mask >> 16) & 0xff;
353 v[3] = (chip->events_mask >> 24) & 0xff;
354
355 return __da903x_writes(chip->client, DA9034_IRQ_MASK_A, 4, v);
356}
357
358static int da9034_read_events(struct da903x_chip *chip, unsigned int *events)
359{
360 uint8_t v[4] = {0, 0, 0, 0};
361 int ret;
362
363 ret = __da903x_reads(chip->client, DA9034_EVENT_A, 4, v);
364 if (ret < 0)
365 return ret;
366
367 *events = (v[3] << 24) | (v[2] << 16) | (v[1] << 8) | v[0];
368 return 0;
369}
370
371static int da9034_read_status(struct da903x_chip *chip, unsigned int *status)
372{
373 uint8_t v[2] = {0, 0};
374 int ret = 0;
375
376 ret = __da903x_reads(chip->client, DA9034_STATUS_A, 2, v);
377 if (ret)
378 return ret;
379
380 *status = (v[1] << 8) | v[0];
381 return 0;
382}
383
384static void da903x_irq_work(struct work_struct *work)
385{
386 struct da903x_chip *chip =
387 container_of(work, struct da903x_chip, irq_work);
388 unsigned int events = 0;
389
390 while (1) {
391 if (chip->ops->read_events(chip, &events))
392 break;
393
394 events &= ~chip->events_mask;
395 if (events == 0)
396 break;
397
398 blocking_notifier_call_chain(
399 &chip->notifier_list, events, NULL);
400 }
401 enable_irq(chip->client->irq);
402}
403
404static int da903x_irq_handler(int irq, void *data)
405{
406 struct da903x_chip *chip = data;
407
408 disable_irq_nosync(irq);
409 (void)schedule_work(&chip->irq_work);
410
411 return IRQ_HANDLED;
412}
413
414static struct da903x_chip_ops da903x_ops[] = {
415 [0] = {
416 .init_chip = da9030_init_chip,
417 .unmask_events = da9030_unmask_events,
418 .mask_events = da9030_mask_events,
419 .read_events = da9030_read_events,
420 .read_status = da9030_read_status,
421 },
422 [1] = {
423 .init_chip = da9034_init_chip,
424 .unmask_events = da9034_unmask_events,
425 .mask_events = da9034_mask_events,
426 .read_events = da9034_read_events,
427 .read_status = da9034_read_status,
428 }
429};
430
431static const struct i2c_device_id da903x_id_table[] = {
432 { "da9030", 0 },
433 { "da9034", 1 },
434 { },
435};
436MODULE_DEVICE_TABLE(i2c, da903x_id_table);
437
438static int __devexit __remove_subdev(struct device *dev, void *unused)
439{
440 platform_device_unregister(to_platform_device(dev));
441 return 0;
442}
443
444static int __devexit da903x_remove_subdevs(struct da903x_chip *chip)
445{
446 return device_for_each_child(chip->dev, NULL, __remove_subdev);
447}
448
449static int __devinit da903x_add_subdevs(struct da903x_chip *chip,
450 struct da903x_platform_data *pdata)
451{
452 struct da903x_subdev_info *subdev;
453 struct platform_device *pdev;
454 int i, ret = 0;
455
456 for (i = 0; i < pdata->num_subdevs; i++) {
457 subdev = &pdata->subdevs[i];
458
459 pdev = platform_device_alloc(subdev->name, subdev->id);
460
461 pdev->dev.parent = chip->dev;
462 pdev->dev.platform_data = subdev->platform_data;
463
464 ret = platform_device_add(pdev);
465 if (ret)
466 goto failed;
467 }
468 return 0;
469
470failed:
471 da903x_remove_subdevs(chip);
472 return ret;
473}
474
475static int __devinit da903x_probe(struct i2c_client *client,
476 const struct i2c_device_id *id)
477{
478 struct da903x_platform_data *pdata = client->dev.platform_data;
479 struct da903x_chip *chip;
480 unsigned int tmp;
481 int ret;
482
483 chip = kzalloc(sizeof(struct da903x_chip), GFP_KERNEL);
484 if (chip == NULL)
485 return -ENOMEM;
486
487 chip->client = client;
488 chip->dev = &client->dev;
489 chip->ops = &da903x_ops[id->driver_data];
490
491 mutex_init(&chip->lock);
492 INIT_WORK(&chip->irq_work, da903x_irq_work);
493 BLOCKING_INIT_NOTIFIER_HEAD(&chip->notifier_list);
494
495 i2c_set_clientdata(client, chip);
496
497 ret = chip->ops->init_chip(chip);
498 if (ret)
499 goto out_free_chip;
500
501 /* mask and clear all IRQs */
502 chip->events_mask = 0xffffffff;
503 chip->ops->mask_events(chip, chip->events_mask);
504 chip->ops->read_events(chip, &tmp);
505
506 ret = request_irq(client->irq, da903x_irq_handler,
507 IRQF_DISABLED | IRQF_TRIGGER_FALLING,
508 "da903x", chip);
509 if (ret) {
510 dev_err(&client->dev, "failed to request irq %d\n",
511 client->irq);
512 goto out_free_chip;
513 }
514
515 ret = da903x_add_subdevs(chip, pdata);
516 if (ret)
517 goto out_free_irq;
518
519 return 0;
520
521out_free_irq:
522 free_irq(client->irq, chip);
523out_free_chip:
524 i2c_set_clientdata(client, NULL);
525 kfree(chip);
526 return ret;
527}
528
529static int __devexit da903x_remove(struct i2c_client *client)
530{
531 struct da903x_chip *chip = i2c_get_clientdata(client);
532
533 da903x_remove_subdevs(chip);
534 kfree(chip);
535 return 0;
536}
537
538static struct i2c_driver da903x_driver = {
539 .driver = {
540 .name = "da903x",
541 .owner = THIS_MODULE,
542 },
543 .probe = da903x_probe,
544 .remove = __devexit_p(da903x_remove),
545 .id_table = da903x_id_table,
546};
547
548static int __init da903x_init(void)
549{
550 return i2c_add_driver(&da903x_driver);
551}
552module_init(da903x_init);
553
554static void __exit da903x_exit(void)
555{
556 i2c_del_driver(&da903x_driver);
557}
558module_exit(da903x_exit);
559
560MODULE_DESCRIPTION("PMIC Driver for Dialog Semiconductor DA9034");
561MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"
562 "Mike Rapoport <mike@compulab.co.il>");
563MODULE_LICENSE("GPL");