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