Merge remote-tracking branch 'upstream' into next
[cascardo/linux.git] / drivers / mfd / 88pm860x-core.c
1 /*
2  * Base driver for Marvell 88PM8607
3  *
4  * Copyright (C) 2009 Marvell International Ltd.
5  *      Haojian Zhuang <haojian.zhuang@marvell.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  */
11
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/i2c.h>
15 #include <linux/irq.h>
16 #include <linux/interrupt.h>
17 #include <linux/platform_device.h>
18 #include <linux/mfd/core.h>
19 #include <linux/mfd/88pm860x.h>
20 #include <linux/regulator/machine.h>
21
22 #define INT_STATUS_NUM                  3
23
24 static struct resource bk_resources[] __devinitdata = {
25         {PM8606_BACKLIGHT1, PM8606_BACKLIGHT1, "backlight-0", IORESOURCE_IO,},
26         {PM8606_BACKLIGHT2, PM8606_BACKLIGHT2, "backlight-1", IORESOURCE_IO,},
27         {PM8606_BACKLIGHT3, PM8606_BACKLIGHT3, "backlight-2", IORESOURCE_IO,},
28 };
29
30 static struct resource led_resources[] __devinitdata = {
31         {PM8606_LED1_RED,   PM8606_LED1_RED,   "led0-red",   IORESOURCE_IO,},
32         {PM8606_LED1_GREEN, PM8606_LED1_GREEN, "led0-green", IORESOURCE_IO,},
33         {PM8606_LED1_BLUE,  PM8606_LED1_BLUE,  "led0-blue",  IORESOURCE_IO,},
34         {PM8606_LED2_RED,   PM8606_LED2_RED,   "led1-red",   IORESOURCE_IO,},
35         {PM8606_LED2_GREEN, PM8606_LED2_GREEN, "led1-green", IORESOURCE_IO,},
36         {PM8606_LED2_BLUE,  PM8606_LED2_BLUE,  "led1-blue",  IORESOURCE_IO,},
37 };
38
39 static struct resource regulator_resources[] __devinitdata = {
40         {PM8607_ID_BUCK1, PM8607_ID_BUCK1, "buck-1", IORESOURCE_IO,},
41         {PM8607_ID_BUCK2, PM8607_ID_BUCK2, "buck-2", IORESOURCE_IO,},
42         {PM8607_ID_BUCK3, PM8607_ID_BUCK3, "buck-3", IORESOURCE_IO,},
43         {PM8607_ID_LDO1,  PM8607_ID_LDO1,  "ldo-01", IORESOURCE_IO,},
44         {PM8607_ID_LDO2,  PM8607_ID_LDO2,  "ldo-02", IORESOURCE_IO,},
45         {PM8607_ID_LDO3,  PM8607_ID_LDO3,  "ldo-03", IORESOURCE_IO,},
46         {PM8607_ID_LDO4,  PM8607_ID_LDO4,  "ldo-04", IORESOURCE_IO,},
47         {PM8607_ID_LDO5,  PM8607_ID_LDO5,  "ldo-05", IORESOURCE_IO,},
48         {PM8607_ID_LDO6,  PM8607_ID_LDO6,  "ldo-06", IORESOURCE_IO,},
49         {PM8607_ID_LDO7,  PM8607_ID_LDO7,  "ldo-07", IORESOURCE_IO,},
50         {PM8607_ID_LDO8,  PM8607_ID_LDO8,  "ldo-08", IORESOURCE_IO,},
51         {PM8607_ID_LDO9,  PM8607_ID_LDO9,  "ldo-09", IORESOURCE_IO,},
52         {PM8607_ID_LDO10, PM8607_ID_LDO10, "ldo-10", IORESOURCE_IO,},
53         {PM8607_ID_LDO11, PM8607_ID_LDO11, "ldo-11", IORESOURCE_IO,},
54         {PM8607_ID_LDO12, PM8607_ID_LDO12, "ldo-12", IORESOURCE_IO,},
55         {PM8607_ID_LDO13, PM8607_ID_LDO13, "ldo-13", IORESOURCE_IO,},
56         {PM8607_ID_LDO14, PM8607_ID_LDO14, "ldo-14", IORESOURCE_IO,},
57         {PM8607_ID_LDO15, PM8607_ID_LDO15, "ldo-15", IORESOURCE_IO,},
58 };
59
60 static struct resource touch_resources[] __devinitdata = {
61         {PM8607_IRQ_PEN, PM8607_IRQ_PEN, "touch", IORESOURCE_IRQ,},
62 };
63
64 static struct resource onkey_resources[] __devinitdata = {
65         {PM8607_IRQ_ONKEY, PM8607_IRQ_ONKEY, "onkey", IORESOURCE_IRQ,},
66 };
67
68 static struct resource codec_resources[] __devinitdata = {
69         /* Headset microphone insertion or removal */
70         {PM8607_IRQ_MICIN,   PM8607_IRQ_MICIN,   "micin",   IORESOURCE_IRQ,},
71         /* Hook-switch press or release */
72         {PM8607_IRQ_HOOK,    PM8607_IRQ_HOOK,    "hook",    IORESOURCE_IRQ,},
73         /* Headset insertion or removal */
74         {PM8607_IRQ_HEADSET, PM8607_IRQ_HEADSET, "headset", IORESOURCE_IRQ,},
75         /* Audio short */
76         {PM8607_IRQ_AUDIO_SHORT, PM8607_IRQ_AUDIO_SHORT, "audio-short", IORESOURCE_IRQ,},
77 };
78
79 static struct resource battery_resources[] __devinitdata = {
80         {PM8607_IRQ_CC,  PM8607_IRQ_CC,  "columb counter", IORESOURCE_IRQ,},
81         {PM8607_IRQ_BAT, PM8607_IRQ_BAT, "battery",        IORESOURCE_IRQ,},
82 };
83
84 static struct resource charger_resources[] __devinitdata = {
85         {PM8607_IRQ_CHG,  PM8607_IRQ_CHG,  "charger detect",  IORESOURCE_IRQ,},
86         {PM8607_IRQ_CHG_DONE,  PM8607_IRQ_CHG_DONE,  "charging done",       IORESOURCE_IRQ,},
87         {PM8607_IRQ_CHG_FAULT, PM8607_IRQ_CHG_FAULT, "charging timeout",    IORESOURCE_IRQ,},
88         {PM8607_IRQ_GPADC1,    PM8607_IRQ_GPADC1,    "battery temperature", IORESOURCE_IRQ,},
89         {PM8607_IRQ_VBAT, PM8607_IRQ_VBAT, "battery voltage", IORESOURCE_IRQ,},
90         {PM8607_IRQ_VCHG, PM8607_IRQ_VCHG, "vchg voltage",    IORESOURCE_IRQ,},
91 };
92
93 static struct resource preg_resources[] __devinitdata = {
94         {PM8606_ID_PREG,  PM8606_ID_PREG,  "preg",   IORESOURCE_IO,},
95 };
96
97 static struct resource rtc_resources[] __devinitdata = {
98         {PM8607_IRQ_RTC, PM8607_IRQ_RTC, "rtc", IORESOURCE_IRQ,},
99 };
100
101 static struct mfd_cell bk_devs[] = {
102         {"88pm860x-backlight", 0,},
103         {"88pm860x-backlight", 1,},
104         {"88pm860x-backlight", 2,},
105 };
106
107 static struct mfd_cell led_devs[] = {
108         {"88pm860x-led", 0,},
109         {"88pm860x-led", 1,},
110         {"88pm860x-led", 2,},
111         {"88pm860x-led", 3,},
112         {"88pm860x-led", 4,},
113         {"88pm860x-led", 5,},
114 };
115
116 static struct mfd_cell regulator_devs[] = {
117         {"88pm860x-regulator", 0,},
118         {"88pm860x-regulator", 1,},
119         {"88pm860x-regulator", 2,},
120         {"88pm860x-regulator", 3,},
121         {"88pm860x-regulator", 4,},
122         {"88pm860x-regulator", 5,},
123         {"88pm860x-regulator", 6,},
124         {"88pm860x-regulator", 7,},
125         {"88pm860x-regulator", 8,},
126         {"88pm860x-regulator", 9,},
127         {"88pm860x-regulator", 10,},
128         {"88pm860x-regulator", 11,},
129         {"88pm860x-regulator", 12,},
130         {"88pm860x-regulator", 13,},
131         {"88pm860x-regulator", 14,},
132         {"88pm860x-regulator", 15,},
133         {"88pm860x-regulator", 16,},
134         {"88pm860x-regulator", 17,},
135 };
136
137 static struct mfd_cell touch_devs[] = {
138         {"88pm860x-touch", -1,},
139 };
140
141 static struct mfd_cell onkey_devs[] = {
142         {"88pm860x-onkey", -1,},
143 };
144
145 static struct mfd_cell codec_devs[] = {
146         {"88pm860x-codec", -1,},
147 };
148
149 static struct regulator_consumer_supply preg_supply[] = {
150         REGULATOR_SUPPLY("preg", "charger-manager"),
151 };
152
153 static struct regulator_init_data preg_init_data = {
154         .num_consumer_supplies  = ARRAY_SIZE(preg_supply),
155         .consumer_supplies      = &preg_supply[0],
156 };
157
158 static struct mfd_cell power_devs[] = {
159         {"88pm860x-battery", -1,},
160         {"88pm860x-charger", -1,},
161         {"88pm860x-preg",    -1,},
162 };
163
164 static struct mfd_cell rtc_devs[] = {
165         {"88pm860x-rtc", -1,},
166 };
167
168
169 struct pm860x_irq_data {
170         int     reg;
171         int     mask_reg;
172         int     enable;         /* enable or not */
173         int     offs;           /* bit offset in mask register */
174 };
175
176 static struct pm860x_irq_data pm860x_irqs[] = {
177         [PM8607_IRQ_ONKEY] = {
178                 .reg            = PM8607_INT_STATUS1,
179                 .mask_reg       = PM8607_INT_MASK_1,
180                 .offs           = 1 << 0,
181         },
182         [PM8607_IRQ_EXTON] = {
183                 .reg            = PM8607_INT_STATUS1,
184                 .mask_reg       = PM8607_INT_MASK_1,
185                 .offs           = 1 << 1,
186         },
187         [PM8607_IRQ_CHG] = {
188                 .reg            = PM8607_INT_STATUS1,
189                 .mask_reg       = PM8607_INT_MASK_1,
190                 .offs           = 1 << 2,
191         },
192         [PM8607_IRQ_BAT] = {
193                 .reg            = PM8607_INT_STATUS1,
194                 .mask_reg       = PM8607_INT_MASK_1,
195                 .offs           = 1 << 3,
196         },
197         [PM8607_IRQ_RTC] = {
198                 .reg            = PM8607_INT_STATUS1,
199                 .mask_reg       = PM8607_INT_MASK_1,
200                 .offs           = 1 << 4,
201         },
202         [PM8607_IRQ_CC] = {
203                 .reg            = PM8607_INT_STATUS1,
204                 .mask_reg       = PM8607_INT_MASK_1,
205                 .offs           = 1 << 5,
206         },
207         [PM8607_IRQ_VBAT] = {
208                 .reg            = PM8607_INT_STATUS2,
209                 .mask_reg       = PM8607_INT_MASK_2,
210                 .offs           = 1 << 0,
211         },
212         [PM8607_IRQ_VCHG] = {
213                 .reg            = PM8607_INT_STATUS2,
214                 .mask_reg       = PM8607_INT_MASK_2,
215                 .offs           = 1 << 1,
216         },
217         [PM8607_IRQ_VSYS] = {
218                 .reg            = PM8607_INT_STATUS2,
219                 .mask_reg       = PM8607_INT_MASK_2,
220                 .offs           = 1 << 2,
221         },
222         [PM8607_IRQ_TINT] = {
223                 .reg            = PM8607_INT_STATUS2,
224                 .mask_reg       = PM8607_INT_MASK_2,
225                 .offs           = 1 << 3,
226         },
227         [PM8607_IRQ_GPADC0] = {
228                 .reg            = PM8607_INT_STATUS2,
229                 .mask_reg       = PM8607_INT_MASK_2,
230                 .offs           = 1 << 4,
231         },
232         [PM8607_IRQ_GPADC1] = {
233                 .reg            = PM8607_INT_STATUS2,
234                 .mask_reg       = PM8607_INT_MASK_2,
235                 .offs           = 1 << 5,
236         },
237         [PM8607_IRQ_GPADC2] = {
238                 .reg            = PM8607_INT_STATUS2,
239                 .mask_reg       = PM8607_INT_MASK_2,
240                 .offs           = 1 << 6,
241         },
242         [PM8607_IRQ_GPADC3] = {
243                 .reg            = PM8607_INT_STATUS2,
244                 .mask_reg       = PM8607_INT_MASK_2,
245                 .offs           = 1 << 7,
246         },
247         [PM8607_IRQ_AUDIO_SHORT] = {
248                 .reg            = PM8607_INT_STATUS3,
249                 .mask_reg       = PM8607_INT_MASK_3,
250                 .offs           = 1 << 0,
251         },
252         [PM8607_IRQ_PEN] = {
253                 .reg            = PM8607_INT_STATUS3,
254                 .mask_reg       = PM8607_INT_MASK_3,
255                 .offs           = 1 << 1,
256         },
257         [PM8607_IRQ_HEADSET] = {
258                 .reg            = PM8607_INT_STATUS3,
259                 .mask_reg       = PM8607_INT_MASK_3,
260                 .offs           = 1 << 2,
261         },
262         [PM8607_IRQ_HOOK] = {
263                 .reg            = PM8607_INT_STATUS3,
264                 .mask_reg       = PM8607_INT_MASK_3,
265                 .offs           = 1 << 3,
266         },
267         [PM8607_IRQ_MICIN] = {
268                 .reg            = PM8607_INT_STATUS3,
269                 .mask_reg       = PM8607_INT_MASK_3,
270                 .offs           = 1 << 4,
271         },
272         [PM8607_IRQ_CHG_FAIL] = {
273                 .reg            = PM8607_INT_STATUS3,
274                 .mask_reg       = PM8607_INT_MASK_3,
275                 .offs           = 1 << 5,
276         },
277         [PM8607_IRQ_CHG_DONE] = {
278                 .reg            = PM8607_INT_STATUS3,
279                 .mask_reg       = PM8607_INT_MASK_3,
280                 .offs           = 1 << 6,
281         },
282         [PM8607_IRQ_CHG_FAULT] = {
283                 .reg            = PM8607_INT_STATUS3,
284                 .mask_reg       = PM8607_INT_MASK_3,
285                 .offs           = 1 << 7,
286         },
287 };
288
289 static irqreturn_t pm860x_irq(int irq, void *data)
290 {
291         struct pm860x_chip *chip = data;
292         struct pm860x_irq_data *irq_data;
293         struct i2c_client *i2c;
294         int read_reg = -1, value = 0;
295         int i;
296
297         i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
298         for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) {
299                 irq_data = &pm860x_irqs[i];
300                 if (read_reg != irq_data->reg) {
301                         read_reg = irq_data->reg;
302                         value = pm860x_reg_read(i2c, irq_data->reg);
303                 }
304                 if (value & irq_data->enable)
305                         handle_nested_irq(chip->irq_base + i);
306         }
307         return IRQ_HANDLED;
308 }
309
310 static void pm860x_irq_lock(struct irq_data *data)
311 {
312         struct pm860x_chip *chip = irq_data_get_irq_chip_data(data);
313
314         mutex_lock(&chip->irq_lock);
315 }
316
317 static void pm860x_irq_sync_unlock(struct irq_data *data)
318 {
319         struct pm860x_chip *chip = irq_data_get_irq_chip_data(data);
320         struct pm860x_irq_data *irq_data;
321         struct i2c_client *i2c;
322         static unsigned char cached[3] = {0x0, 0x0, 0x0};
323         unsigned char mask[3];
324         int i;
325
326         i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
327         /* Load cached value. In initial, all IRQs are masked */
328         for (i = 0; i < 3; i++)
329                 mask[i] = cached[i];
330         for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) {
331                 irq_data = &pm860x_irqs[i];
332                 switch (irq_data->mask_reg) {
333                 case PM8607_INT_MASK_1:
334                         mask[0] &= ~irq_data->offs;
335                         mask[0] |= irq_data->enable;
336                         break;
337                 case PM8607_INT_MASK_2:
338                         mask[1] &= ~irq_data->offs;
339                         mask[1] |= irq_data->enable;
340                         break;
341                 case PM8607_INT_MASK_3:
342                         mask[2] &= ~irq_data->offs;
343                         mask[2] |= irq_data->enable;
344                         break;
345                 default:
346                         dev_err(chip->dev, "wrong IRQ\n");
347                         break;
348                 }
349         }
350         /* update mask into registers */
351         for (i = 0; i < 3; i++) {
352                 if (mask[i] != cached[i]) {
353                         cached[i] = mask[i];
354                         pm860x_reg_write(i2c, PM8607_INT_MASK_1 + i, mask[i]);
355                 }
356         }
357
358         mutex_unlock(&chip->irq_lock);
359 }
360
361 static void pm860x_irq_enable(struct irq_data *data)
362 {
363         struct pm860x_chip *chip = irq_data_get_irq_chip_data(data);
364         pm860x_irqs[data->irq - chip->irq_base].enable
365                 = pm860x_irqs[data->irq - chip->irq_base].offs;
366 }
367
368 static void pm860x_irq_disable(struct irq_data *data)
369 {
370         struct pm860x_chip *chip = irq_data_get_irq_chip_data(data);
371         pm860x_irqs[data->irq - chip->irq_base].enable = 0;
372 }
373
374 static struct irq_chip pm860x_irq_chip = {
375         .name           = "88pm860x",
376         .irq_bus_lock   = pm860x_irq_lock,
377         .irq_bus_sync_unlock = pm860x_irq_sync_unlock,
378         .irq_enable     = pm860x_irq_enable,
379         .irq_disable    = pm860x_irq_disable,
380 };
381
382 static int __devinit device_gpadc_init(struct pm860x_chip *chip,
383                                        struct pm860x_platform_data *pdata)
384 {
385         struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
386                                 : chip->companion;
387         int data;
388         int ret;
389
390         /* initialize GPADC without activating it */
391
392         if (!pdata || !pdata->touch)
393                 return -EINVAL;
394
395         /* set GPADC MISC1 register */
396         data = 0;
397         data |= (pdata->touch->gpadc_prebias << 1) & PM8607_GPADC_PREBIAS_MASK;
398         data |= (pdata->touch->slot_cycle << 3) & PM8607_GPADC_SLOT_CYCLE_MASK;
399         data |= (pdata->touch->off_scale << 5) & PM8607_GPADC_OFF_SCALE_MASK;
400         data |= (pdata->touch->sw_cal << 7) & PM8607_GPADC_SW_CAL_MASK;
401         if (data) {
402                 ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data);
403                 if (ret < 0)
404                         goto out;
405         }
406         /* set tsi prebias time */
407         if (pdata->touch->tsi_prebias) {
408                 data = pdata->touch->tsi_prebias;
409                 ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data);
410                 if (ret < 0)
411                         goto out;
412         }
413         /* set prebias & prechg time of pen detect */
414         data = 0;
415         data |= pdata->touch->pen_prebias & PM8607_PD_PREBIAS_MASK;
416         data |= (pdata->touch->pen_prechg << 5) & PM8607_PD_PRECHG_MASK;
417         if (data) {
418                 ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data);
419                 if (ret < 0)
420                         goto out;
421         }
422
423         ret = pm860x_set_bits(i2c, PM8607_GPADC_MISC1,
424                               PM8607_GPADC_EN, PM8607_GPADC_EN);
425 out:
426         return ret;
427 }
428
429 static int __devinit device_irq_init(struct pm860x_chip *chip,
430                                      struct pm860x_platform_data *pdata)
431 {
432         struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
433                                 : chip->companion;
434         unsigned char status_buf[INT_STATUS_NUM];
435         unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
436         int i, data, mask, ret = -EINVAL;
437         int __irq;
438
439         if (!pdata || !pdata->irq_base) {
440                 dev_warn(chip->dev, "No interrupt support on IRQ base\n");
441                 return -EINVAL;
442         }
443
444         mask = PM8607_B0_MISC1_INV_INT | PM8607_B0_MISC1_INT_CLEAR
445                 | PM8607_B0_MISC1_INT_MASK;
446         data = 0;
447         chip->irq_mode = 0;
448         if (pdata && pdata->irq_mode) {
449                 /*
450                  * irq_mode defines the way of clearing interrupt. If it's 1,
451                  * clear IRQ by write. Otherwise, clear it by read.
452                  * This control bit is valid from 88PM8607 B0 steping.
453                  */
454                 data |= PM8607_B0_MISC1_INT_CLEAR;
455                 chip->irq_mode = 1;
456         }
457         ret = pm860x_set_bits(i2c, PM8607_B0_MISC1, mask, data);
458         if (ret < 0)
459                 goto out;
460
461         /* mask all IRQs */
462         memset(status_buf, 0, INT_STATUS_NUM);
463         ret = pm860x_bulk_write(i2c, PM8607_INT_MASK_1,
464                                 INT_STATUS_NUM, status_buf);
465         if (ret < 0)
466                 goto out;
467
468         if (chip->irq_mode) {
469                 /* clear interrupt status by write */
470                 memset(status_buf, 0xFF, INT_STATUS_NUM);
471                 ret = pm860x_bulk_write(i2c, PM8607_INT_STATUS1,
472                                         INT_STATUS_NUM, status_buf);
473         } else {
474                 /* clear interrupt status by read */
475                 ret = pm860x_bulk_read(i2c, PM8607_INT_STATUS1,
476                                         INT_STATUS_NUM, status_buf);
477         }
478         if (ret < 0)
479                 goto out;
480
481         mutex_init(&chip->irq_lock);
482         chip->irq_base = pdata->irq_base;
483         chip->core_irq = i2c->irq;
484         if (!chip->core_irq)
485                 goto out;
486
487         /* register IRQ by genirq */
488         for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) {
489                 __irq = i + chip->irq_base;
490                 irq_set_chip_data(__irq, chip);
491                 irq_set_chip_and_handler(__irq, &pm860x_irq_chip,
492                                          handle_edge_irq);
493                 irq_set_nested_thread(__irq, 1);
494 #ifdef CONFIG_ARM
495                 set_irq_flags(__irq, IRQF_VALID);
496 #else
497                 irq_set_noprobe(__irq);
498 #endif
499         }
500
501         ret = request_threaded_irq(chip->core_irq, NULL, pm860x_irq, flags,
502                                    "88pm860x", chip);
503         if (ret) {
504                 dev_err(chip->dev, "Failed to request IRQ: %d\n", ret);
505                 chip->core_irq = 0;
506         }
507
508         return 0;
509 out:
510         chip->core_irq = 0;
511         return ret;
512 }
513
514 static void device_irq_exit(struct pm860x_chip *chip)
515 {
516         if (chip->core_irq)
517                 free_irq(chip->core_irq, chip);
518 }
519
520 int pm8606_osc_enable(struct pm860x_chip *chip, unsigned short client)
521 {
522         int ret = -EIO;
523         struct i2c_client *i2c = (chip->id == CHIP_PM8606) ?
524                 chip->client : chip->companion;
525
526         dev_dbg(chip->dev, "%s(B): client=0x%x\n", __func__, client);
527         dev_dbg(chip->dev, "%s(B): vote=0x%x status=%d\n",
528                         __func__, chip->osc_vote,
529                         chip->osc_status);
530
531         mutex_lock(&chip->osc_lock);
532         /* Update voting status */
533         chip->osc_vote |= client;
534         /* If reference group is off - turn on*/
535         if (chip->osc_status != PM8606_REF_GP_OSC_ON) {
536                 chip->osc_status = PM8606_REF_GP_OSC_UNKNOWN;
537                 /* Enable Reference group Vsys */
538                 if (pm860x_set_bits(i2c, PM8606_VSYS,
539                                 PM8606_VSYS_EN, PM8606_VSYS_EN))
540                         goto out;
541
542                 /*Enable Internal Oscillator */
543                 if (pm860x_set_bits(i2c, PM8606_MISC,
544                                 PM8606_MISC_OSC_EN, PM8606_MISC_OSC_EN))
545                         goto out;
546                 /* Update status (only if writes succeed) */
547                 chip->osc_status = PM8606_REF_GP_OSC_ON;
548         }
549         mutex_unlock(&chip->osc_lock);
550
551         dev_dbg(chip->dev, "%s(A): vote=0x%x status=%d ret=%d\n",
552                         __func__, chip->osc_vote,
553                         chip->osc_status, ret);
554         return 0;
555 out:
556         mutex_unlock(&chip->osc_lock);
557         return ret;
558 }
559 EXPORT_SYMBOL(pm8606_osc_enable);
560
561 int pm8606_osc_disable(struct pm860x_chip *chip, unsigned short client)
562 {
563         int ret = -EIO;
564         struct i2c_client *i2c = (chip->id == CHIP_PM8606) ?
565                 chip->client : chip->companion;
566
567         dev_dbg(chip->dev, "%s(B): client=0x%x\n", __func__, client);
568         dev_dbg(chip->dev, "%s(B): vote=0x%x status=%d\n",
569                         __func__, chip->osc_vote,
570                         chip->osc_status);
571
572         mutex_lock(&chip->osc_lock);
573         /*Update voting status */
574         chip->osc_vote &= ~(client);
575         /* If reference group is off and this is the last client to release
576          * - turn off */
577         if ((chip->osc_status != PM8606_REF_GP_OSC_OFF) &&
578                         (chip->osc_vote == REF_GP_NO_CLIENTS)) {
579                 chip->osc_status = PM8606_REF_GP_OSC_UNKNOWN;
580                 /* Disable Reference group Vsys */
581                 if (pm860x_set_bits(i2c, PM8606_VSYS, PM8606_VSYS_EN, 0))
582                         goto out;
583                 /* Disable Internal Oscillator */
584                 if (pm860x_set_bits(i2c, PM8606_MISC, PM8606_MISC_OSC_EN, 0))
585                         goto out;
586                 chip->osc_status = PM8606_REF_GP_OSC_OFF;
587         }
588         mutex_unlock(&chip->osc_lock);
589
590         dev_dbg(chip->dev, "%s(A): vote=0x%x status=%d ret=%d\n",
591                         __func__, chip->osc_vote,
592                         chip->osc_status, ret);
593         return 0;
594 out:
595         mutex_unlock(&chip->osc_lock);
596         return ret;
597 }
598 EXPORT_SYMBOL(pm8606_osc_disable);
599
600 static void __devinit device_osc_init(struct i2c_client *i2c)
601 {
602         struct pm860x_chip *chip = i2c_get_clientdata(i2c);
603
604         mutex_init(&chip->osc_lock);
605         /* init portofino reference group voting and status */
606         /* Disable Reference group Vsys */
607         pm860x_set_bits(i2c, PM8606_VSYS, PM8606_VSYS_EN, 0);
608         /* Disable Internal Oscillator */
609         pm860x_set_bits(i2c, PM8606_MISC, PM8606_MISC_OSC_EN, 0);
610
611         chip->osc_vote = REF_GP_NO_CLIENTS;
612         chip->osc_status = PM8606_REF_GP_OSC_OFF;
613 }
614
615 static void __devinit device_bk_init(struct pm860x_chip *chip,
616                                      struct pm860x_platform_data *pdata)
617 {
618         int ret;
619         int i, j, id;
620
621         if ((pdata == NULL) || (pdata->backlight == NULL))
622                 return;
623
624         if (pdata->num_backlights > ARRAY_SIZE(bk_devs))
625                 pdata->num_backlights = ARRAY_SIZE(bk_devs);
626
627         for (i = 0; i < pdata->num_backlights; i++) {
628                 bk_devs[i].platform_data = &pdata->backlight[i];
629                 bk_devs[i].pdata_size = sizeof(struct pm860x_backlight_pdata);
630
631                 for (j = 0; j < ARRAY_SIZE(bk_devs); j++) {
632                         id = bk_resources[j].start;
633                         if (pdata->backlight[i].flags != id)
634                                 continue;
635
636                         bk_devs[i].num_resources = 1;
637                         bk_devs[i].resources = &bk_resources[j];
638                         ret = mfd_add_devices(chip->dev, 0,
639                                               &bk_devs[i], 1,
640                                               &bk_resources[j], 0);
641                         if (ret < 0) {
642                                 dev_err(chip->dev, "Failed to add "
643                                         "backlight subdev\n");
644                                 return;
645                         }
646                 }
647         }
648 }
649
650 static void __devinit device_led_init(struct pm860x_chip *chip,
651                                       struct pm860x_platform_data *pdata)
652 {
653         int ret;
654         int i, j, id;
655
656         if ((pdata == NULL) || (pdata->led == NULL))
657                 return;
658
659         if (pdata->num_leds > ARRAY_SIZE(led_devs))
660                 pdata->num_leds = ARRAY_SIZE(led_devs);
661
662         for (i = 0; i < pdata->num_leds; i++) {
663                 led_devs[i].platform_data = &pdata->led[i];
664                 led_devs[i].pdata_size = sizeof(struct pm860x_led_pdata);
665
666                 for (j = 0; j < ARRAY_SIZE(led_devs); j++) {
667                         id = led_resources[j].start;
668                         if (pdata->led[i].flags != id)
669                                 continue;
670
671                         led_devs[i].num_resources = 1;
672                         led_devs[i].resources = &led_resources[j],
673                         ret = mfd_add_devices(chip->dev, 0,
674                                               &led_devs[i], 1,
675                                               &led_resources[j], 0);
676                         if (ret < 0) {
677                                 dev_err(chip->dev, "Failed to add "
678                                         "led subdev\n");
679                                 return;
680                         }
681                 }
682         }
683 }
684
685 static void __devinit device_regulator_init(struct pm860x_chip *chip,
686                                             struct pm860x_platform_data *pdata)
687 {
688         struct regulator_init_data *initdata;
689         int ret;
690         int i, seq;
691
692         if ((pdata == NULL) || (pdata->regulator == NULL))
693                 return;
694
695         if (pdata->num_regulators > ARRAY_SIZE(regulator_devs))
696                 pdata->num_regulators = ARRAY_SIZE(regulator_devs);
697
698         for (i = 0, seq = -1; i < pdata->num_regulators; i++) {
699                 initdata = &pdata->regulator[i];
700                 seq = *(unsigned int *)initdata->driver_data;
701                 if ((seq < 0) || (seq > PM8607_ID_RG_MAX)) {
702                         dev_err(chip->dev, "Wrong ID(%d) on regulator(%s)\n",
703                                 seq, initdata->constraints.name);
704                         goto out;
705                 }
706                 regulator_devs[i].platform_data = &pdata->regulator[i];
707                 regulator_devs[i].pdata_size = sizeof(struct regulator_init_data);
708                 regulator_devs[i].num_resources = 1;
709                 regulator_devs[i].resources = &regulator_resources[seq];
710
711                 ret = mfd_add_devices(chip->dev, 0, &regulator_devs[i], 1,
712                                       &regulator_resources[seq], 0);
713                 if (ret < 0) {
714                         dev_err(chip->dev, "Failed to add regulator subdev\n");
715                         goto out;
716                 }
717         }
718 out:
719         return;
720 }
721
722 static void __devinit device_rtc_init(struct pm860x_chip *chip,
723                                       struct pm860x_platform_data *pdata)
724 {
725         int ret;
726
727         if ((pdata == NULL))
728                 return;
729
730         rtc_devs[0].platform_data = pdata->rtc;
731         rtc_devs[0].pdata_size = sizeof(struct pm860x_rtc_pdata);
732         rtc_devs[0].num_resources = ARRAY_SIZE(rtc_resources);
733         rtc_devs[0].resources = &rtc_resources[0];
734         ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],
735                               ARRAY_SIZE(rtc_devs), &rtc_resources[0],
736                               chip->irq_base);
737         if (ret < 0)
738                 dev_err(chip->dev, "Failed to add rtc subdev\n");
739 }
740
741 static void __devinit device_touch_init(struct pm860x_chip *chip,
742                                         struct pm860x_platform_data *pdata)
743 {
744         int ret;
745
746         if (pdata == NULL)
747                 return;
748
749         touch_devs[0].platform_data = pdata->touch;
750         touch_devs[0].pdata_size = sizeof(struct pm860x_touch_pdata);
751         touch_devs[0].num_resources = ARRAY_SIZE(touch_resources);
752         touch_devs[0].resources = &touch_resources[0];
753         ret = mfd_add_devices(chip->dev, 0, &touch_devs[0],
754                               ARRAY_SIZE(touch_devs), &touch_resources[0],
755                               chip->irq_base);
756         if (ret < 0)
757                 dev_err(chip->dev, "Failed to add touch subdev\n");
758 }
759
760 static void __devinit device_power_init(struct pm860x_chip *chip,
761                                         struct pm860x_platform_data *pdata)
762 {
763         int ret;
764
765         if (pdata == NULL)
766                 return;
767
768         power_devs[0].platform_data = pdata->power;
769         power_devs[0].pdata_size = sizeof(struct pm860x_power_pdata);
770         power_devs[0].num_resources = ARRAY_SIZE(battery_resources);
771         power_devs[0].resources = &battery_resources[0],
772         ret = mfd_add_devices(chip->dev, 0, &power_devs[0], 1,
773                               &battery_resources[0], chip->irq_base);
774         if (ret < 0)
775                 dev_err(chip->dev, "Failed to add battery subdev\n");
776
777         power_devs[1].platform_data = pdata->power;
778         power_devs[1].pdata_size = sizeof(struct pm860x_power_pdata);
779         power_devs[1].num_resources = ARRAY_SIZE(charger_resources);
780         power_devs[1].resources = &charger_resources[0],
781         ret = mfd_add_devices(chip->dev, 0, &power_devs[1], 1,
782                               &charger_resources[0], chip->irq_base);
783         if (ret < 0)
784                 dev_err(chip->dev, "Failed to add charger subdev\n");
785
786         power_devs[2].platform_data = &preg_init_data;
787         power_devs[2].pdata_size = sizeof(struct regulator_init_data);
788         power_devs[2].num_resources = ARRAY_SIZE(preg_resources);
789         power_devs[2].resources = &preg_resources[0],
790         ret = mfd_add_devices(chip->dev, 0, &power_devs[2], 1,
791                               &preg_resources[0], chip->irq_base);
792         if (ret < 0)
793                 dev_err(chip->dev, "Failed to add preg subdev\n");
794 }
795
796 static void __devinit device_onkey_init(struct pm860x_chip *chip,
797                                         struct pm860x_platform_data *pdata)
798 {
799         int ret;
800
801         onkey_devs[0].num_resources = ARRAY_SIZE(onkey_resources);
802         onkey_devs[0].resources = &onkey_resources[0],
803         ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0],
804                               ARRAY_SIZE(onkey_devs), &onkey_resources[0],
805                               chip->irq_base);
806         if (ret < 0)
807                 dev_err(chip->dev, "Failed to add onkey subdev\n");
808 }
809
810 static void __devinit device_codec_init(struct pm860x_chip *chip,
811                                         struct pm860x_platform_data *pdata)
812 {
813         int ret;
814
815         codec_devs[0].num_resources = ARRAY_SIZE(codec_resources);
816         codec_devs[0].resources = &codec_resources[0],
817         ret = mfd_add_devices(chip->dev, 0, &codec_devs[0],
818                               ARRAY_SIZE(codec_devs), &codec_resources[0], 0);
819         if (ret < 0)
820                 dev_err(chip->dev, "Failed to add codec subdev\n");
821 }
822
823 static void __devinit device_8607_init(struct pm860x_chip *chip,
824                                        struct i2c_client *i2c,
825                                        struct pm860x_platform_data *pdata)
826 {
827         int data, ret;
828
829         ret = pm860x_reg_read(i2c, PM8607_CHIP_ID);
830         if (ret < 0) {
831                 dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret);
832                 goto out;
833         }
834         switch (ret & PM8607_VERSION_MASK) {
835         case 0x40:
836         case 0x50:
837                 dev_info(chip->dev, "Marvell 88PM8607 (ID: %02x) detected\n",
838                          ret);
839                 break;
840         default:
841                 dev_err(chip->dev, "Failed to detect Marvell 88PM8607. "
842                         "Chip ID: %02x\n", ret);
843                 goto out;
844         }
845
846         ret = pm860x_reg_read(i2c, PM8607_BUCK3);
847         if (ret < 0) {
848                 dev_err(chip->dev, "Failed to read BUCK3 register: %d\n", ret);
849                 goto out;
850         }
851         if (ret & PM8607_BUCK3_DOUBLE)
852                 chip->buck3_double = 1;
853
854         ret = pm860x_reg_read(i2c, PM8607_B0_MISC1);
855         if (ret < 0) {
856                 dev_err(chip->dev, "Failed to read MISC1 register: %d\n", ret);
857                 goto out;
858         }
859
860         if (pdata && (pdata->i2c_port == PI2C_PORT))
861                 data = PM8607_B0_MISC1_PI2C;
862         else
863                 data = 0;
864         ret = pm860x_set_bits(i2c, PM8607_B0_MISC1, PM8607_B0_MISC1_PI2C, data);
865         if (ret < 0) {
866                 dev_err(chip->dev, "Failed to access MISC1:%d\n", ret);
867                 goto out;
868         }
869
870         ret = device_gpadc_init(chip, pdata);
871         if (ret < 0)
872                 goto out;
873
874         ret = device_irq_init(chip, pdata);
875         if (ret < 0)
876                 goto out;
877
878         device_regulator_init(chip, pdata);
879         device_rtc_init(chip, pdata);
880         device_onkey_init(chip, pdata);
881         device_touch_init(chip, pdata);
882         device_power_init(chip, pdata);
883         device_codec_init(chip, pdata);
884 out:
885         return;
886 }
887
888 static void __devinit device_8606_init(struct pm860x_chip *chip,
889                                        struct i2c_client *i2c,
890                                        struct pm860x_platform_data *pdata)
891 {
892         device_osc_init(i2c);
893         device_bk_init(chip, pdata);
894         device_led_init(chip, pdata);
895 }
896
897 int __devinit pm860x_device_init(struct pm860x_chip *chip,
898                        struct pm860x_platform_data *pdata)
899 {
900         chip->core_irq = 0;
901
902         switch (chip->id) {
903         case CHIP_PM8606:
904                 device_8606_init(chip, chip->client, pdata);
905                 break;
906         case CHIP_PM8607:
907                 device_8607_init(chip, chip->client, pdata);
908                 break;
909         }
910
911         if (chip->companion) {
912                 switch (chip->id) {
913                 case CHIP_PM8607:
914                         device_8606_init(chip, chip->companion, pdata);
915                         break;
916                 case CHIP_PM8606:
917                         device_8607_init(chip, chip->companion, pdata);
918                         break;
919                 }
920         }
921
922         return 0;
923 }
924
925 void __devexit pm860x_device_exit(struct pm860x_chip *chip)
926 {
927         device_irq_exit(chip);
928         mfd_remove_devices(chip->dev);
929 }
930
931 MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM860x");
932 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
933 MODULE_LICENSE("GPL");